From 48588cf9293fe311f37e02954887ba170af6c759 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sat, 27 Oct 2018 04:48:12 +0100 Subject: [PATCH] Robustify message display Adjust the behavior of the GameStateManager; it's not quite what it should be, but it's less bad than what was there before. Notably, Msg objects now have the right .equals() behavior, not just .compareTo() Improve CtFwSDisplayLocal and stay subscribed to game state changes while not visible so we stay informed of messages. Do not, however, stay subscribed to service state messages, as there is no point. We might lose messages all the same, but hopefully fewer and hopefully without duplicates spamming everyone all the time. While here, more correctly (I think?) use the Android lifecycle events. --- .../ctfwstimer/lib/CtFwSGameStateManager.java | 25 ++++++++---- .../ctfwstimer/CtFwSDisplayLocal.java | 38 +++++++++++++++---- .../ctfwstimer/MainActivity.java | 20 ++++++++-- 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameStateManager.java b/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameStateManager.java index 389afd9..de2730a 100644 --- a/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameStateManager.java +++ b/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameStateManager.java @@ -221,6 +221,14 @@ public class CtFwSGameStateManager { } return (Long.valueOf(when).compareTo(Long.valueOf(m.when))); } + + @Override + public boolean equals(Object o) { + if (! (o instanceof Msg)) { + return false; + } + return 0 == this.compareTo((Msg)o); + } } private final List msgs = new ArrayList<>(); private long lastMsgTimestamp; @@ -233,23 +241,24 @@ public class CtFwSGameStateManager { try { t = s.nextLong(); } catch (NoSuchElementException nse) { - // Maybe they forgot a time stamp; use round start. - // That's not ideal, but... fake it? - // XXX Back off a bit, for time sync reasons + // Maybe they forgot a time stamp? Fake one up, a second ago or so, + // to allow for some clock drift and another message with a timestamp. synchronized (this) { - lastMsgTimestamp = 0; - m = new Msg(lastMsgTimestamp, str); + m = new Msg(mT.wallMS() - 1000, str); } } if (m == null) { s.useDelimiter("\\z"); - new Msg(t, s.next().trim()); + m = new Msg(t, s.next().trim()); } synchronized (this) { - // If there is no configuration, assume the message is new enough - // If there *is* a configuration, check the time. + // Advance message clock monotonically; accept any message if there + // is no configuration, or check the start time to suppress old + // messages if we're just now coming online. + // + // XXX this is bogus if (isMessageTimeWithin(t) && (lastMsgTimestamp <= t)) { lastMsgTimestamp = t; if (!msgs.contains(m)) { diff --git a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplayLocal.java b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplayLocal.java index 7a73859..1e9a837 100644 --- a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplayLocal.java +++ b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplayLocal.java @@ -15,6 +15,7 @@ import android.widget.TextView; import com.acmetensortoys.ctfwstimer.lib.CtFwSGameStateManager; import java.util.List; +import java.util.ListIterator; import static android.view.View.INVISIBLE; @@ -297,6 +298,7 @@ class CtFwSDisplayLocal implements CtFwSGameStateManager.Observer { }); } + private CtFwSGameStateManager.Msg lastMsg; @Override public void onCtFwSMessage(CtFwSGameStateManager gs, List msgs) { final TextView msgstv = (TextView) (mAct.findViewById(R.id.msgs)); @@ -309,24 +311,44 @@ class CtFwSDisplayLocal implements CtFwSGameStateManager.Observer { msgstv.setText(""); } }); + return; + } + + int ix; + if (lastMsg == null) { + ix = 0; } else { - CtFwSGameStateManager.Msg m = msgs.get(s - 1); + ix = msgs.indexOf(lastMsg); + if (ix == -1) { + ix = 0; + } else if (ix == s) { + return; + } else { + ix = ix + 1; + } + } + final StringBuffer sb = new StringBuffer(); + for (ListIterator news = msgs.listIterator(ix); + news.hasNext(); ) { + + CtFwSGameStateManager.Msg m = news.next(); long td = (m.when == 0) ? 0 : (gs.isConfigured()) ? m.when - gs.getStartT() : 0; - final StringBuffer sb = new StringBuffer(); sb.append(DateUtils.formatElapsedTime(td)); sb.append(": "); sb.append(m.msg); sb.append("\n"); - msgstv.post(new Runnable() { - @Override - public void run() { - msgstv.append(sb); - } - }); + lastMsg = m; } + + msgstv.post(new Runnable() { + @Override + public void run() { + msgstv.append(sb); + } + }); } // Stun timers diff --git a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java index 6bfe738..f03c707 100644 --- a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java +++ b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java @@ -103,7 +103,15 @@ public class MainActivity extends AppCompatActivity { if (mSrvBinder == null) { Intent si = new Intent(this, MainService.class); bindService(si, ctfwssc, Context.BIND_AUTO_CREATE | Context.BIND_ABOVE_CLIENT); - } else { + } + } + + @Override + public void onResume() { + Log.d("CtFwS", "onResume"); + super.onResume(); + + if (mSrvBinder != null) { mSrvBinder.getGameState().registerObserver(mCdl); mSrvBinder.registerObserver(mSrvObs); } @@ -124,13 +132,19 @@ public class MainActivity extends AppCompatActivity { } @Override - protected void onStop() { - Log.d("CtFwS", "onStop"); + protected void onPause() { + Log.d("CtFwS", "onPause"); if (mSrvBinder != null) { mSrvBinder.getGameState().unregisterObserver(mCdl); mSrvBinder.unregisterObserver(mSrvObs); } + super.onPause(); + } + + @Override + protected void onStop() { + Log.d("CtFwS", "onStop"); super.onStop(); } -- 2.50.1