]> hydra-www.ietfng.org Git - acmetensortoys-ctfws-android/commitdiff
Robustify message display
authorNathaniel Wesley Filardo <nwfilardo@gmail.com>
Sat, 27 Oct 2018 03:48:12 +0000 (04:48 +0100)
committerNathaniel Wesley Filardo <nwfilardo@gmail.com>
Sat, 27 Oct 2018 14:11:49 +0000 (15:11 +0100)
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.

lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameStateManager.java
mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplayLocal.java
mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java

index 389afd9fc46c641ffc0be460a271a2ad20b767b0..de2730a8ed7e71a4c6266e452228585ccab14e9c 100644 (file)
@@ -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<Msg> 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)) {
index 7a7385997e5b3840e9a4c06929600eabfb73fe62..1e9a8376656a7deb72f8bcd71fbb53bc498b543a 100644 (file)
@@ -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<CtFwSGameStateManager.Msg> 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<CtFwSGameStateManager.Msg> 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
index 6bfe73848d43ee477d0ff866ae08f6217f18ce26..f03c70755a10568caef68365ebdd5d8d5a32e209 100644 (file)
@@ -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();
     }