commit 1fa125c22100b42f56c4e0542ec9d7cd6876c44b
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Jan 10 15:32:32 2022 +0100

    Add debugging for the case when people submit suspicious records.

diff --git a/src/main/java/org/distorted/config/ConfigObjectLibInterface.java b/src/main/java/org/distorted/config/ConfigObjectLibInterface.java
index dff776cd..adf8f2ad 100644
--- a/src/main/java/org/distorted/config/ConfigObjectLibInterface.java
+++ b/src/main/java/org/distorted/config/ConfigObjectLibInterface.java
@@ -30,7 +30,7 @@ import org.distorted.objectlib.helpers.ObjectLibInterface;
 
 public class ConfigObjectLibInterface implements ObjectLibInterface
 {
-  public void onWinEffectFinished(String debug, int scrambleNum) { }
+  public void onWinEffectFinished(long startTime, long endTime, String debug, int scrambleNum) { }
   public void onScrambleEffectFinished() { }
   public void onBeginRotation() { }
   public void onSolved() { }
diff --git a/src/main/java/org/distorted/main/RubikObjectLibInterface.java b/src/main/java/org/distorted/main/RubikObjectLibInterface.java
index 8bdd8854..35dc186f 100644
--- a/src/main/java/org/distorted/main/RubikObjectLibInterface.java
+++ b/src/main/java/org/distorted/main/RubikObjectLibInterface.java
@@ -34,6 +34,7 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics;
 
 import org.distorted.library.message.EffectMessageSender;
 
+import org.distorted.network.RubikNetwork;
 import org.distorted.objectlib.BuildConfig;
 import org.distorted.objectlib.helpers.BlockController;
 import org.distorted.objectlib.helpers.ObjectLibInterface;
@@ -96,7 +97,7 @@ public class RubikObjectLibInterface implements ObjectLibInterface
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void reportRecord(RubikActivity act, String debug, int scrambleNum)
+  private void reportRecord(RubikActivity act, long startTime, long endTime, String debug, int scrambleNum)
     {
     RubikScreenPlay play= (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
     RubikScores scores  = RubikScores.getInstance();
@@ -116,6 +117,16 @@ public class RubikObjectLibInterface implements ObjectLibInterface
        }
     else
       {
+      long timeNow = System.currentTimeMillis();
+      long elapsed = timeNow - startTime;
+
+      if( level>=9 && mNewRecord<300*level )
+        {
+        String suspicious ="start"+startTime+"end"+endTime+"elapsed"+elapsed+"obj"+objName+"level"+level+"record"+mNewRecord+"scrambles"+scrambleNum+debug;
+        RubikNetwork network = RubikNetwork.getInstance();
+        network.suspicious(act,suspicious);
+        }
+
       FirebaseAnalytics analytics = act.getAnalytics();
 
       if( analytics!=null )
@@ -183,7 +194,7 @@ public class RubikObjectLibInterface implements ObjectLibInterface
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void onWinEffectFinished(String debug, int scrambleNum)
+  public void onWinEffectFinished(long startTime, long endTime, String debug, int scrambleNum)
     {
     if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
       {
@@ -191,7 +202,7 @@ public class RubikObjectLibInterface implements ObjectLibInterface
       Bundle bundle = new Bundle();
       bundle.putLong("time", mNewRecord );
 
-      reportRecord(act,debug,scrambleNum);
+      reportRecord(act,startTime,endTime,debug,scrambleNum);
       requestReview(act);
 
       if( mIsNewRecord )
diff --git a/src/main/java/org/distorted/network/RubikNetwork.java b/src/main/java/org/distorted/network/RubikNetwork.java
index 4e3403d8..a5e67a4e 100644
--- a/src/main/java/org/distorted/network/RubikNetwork.java
+++ b/src/main/java/org/distorted/network/RubikNetwork.java
@@ -36,7 +36,6 @@ import androidx.appcompat.app.AppCompatActivity;
 import androidx.fragment.app.FragmentActivity;
 
 import org.distorted.library.main.DistortedLibrary;
-import org.distorted.objects.RubikObject;
 import org.distorted.objects.RubikObjectList;
 
 import static org.distorted.objects.RubikObjectList.MAX_LEVEL;
@@ -57,7 +56,8 @@ public class RubikNetwork implements Runnable
   private static final int DOWNLOAD   = 0;
   private static final int SUBMIT     = 1;
   private static final int DEBUG      = 2;
-  private static final int IDLE       = 3;
+  private static final int SUSPICIOUS = 3;
+  private static final int IDLE       = 4;
 
   private static final int REND_ADRENO= 0;
   private static final int REND_MALI  = 1;
@@ -110,6 +110,7 @@ public class RubikNetwork implements Runnable
   private static int mMode = IDLE;
   private static Receiver mReceiver;
   private static String mVersion;
+  private static String mDebug;
   private static int mNumObjects;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -387,6 +388,31 @@ public class RubikNetwork implements Runnable
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void sendSuspicious()
+    {
+    String url = constructSuspiciousURL();
+
+    try
+      {
+      java.net.URL connectURL = new URL(url);
+      HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
+
+      conn.setDoInput(true);
+      conn.setDoOutput(true);
+      conn.setUseCaches(false);
+      conn.setRequestMethod("GET");
+      conn.connect();
+      conn.getOutputStream().flush();
+      conn.getInputStream();
+      }
+    catch( final Exception e )
+      {
+      // ignore
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private boolean network(String url)
@@ -439,6 +465,20 @@ public class RubikNetwork implements Runnable
     return true;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private String constructSuspiciousURL()
+    {
+    RubikScores scores = RubikScores.getInstance();
+    int deviceID= scores.getDeviceID();
+    String debug = URLencode(mDebug);
+
+    String url="https://distorted.org/magic/cgi-bin/suspicious.cgi";
+    url += "?i="+deviceID+"&d="+debug;
+
+    return url;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private String constructDebugURL()
@@ -460,26 +500,6 @@ public class RubikNetwork implements Runnable
     return url;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private static String getObjectList()
-    {
-    StringBuilder list = new StringBuilder();
-
-    for(int i=0; i<mNumObjects; i++)
-      {
-      RubikObject object = RubikObjectList.getObject(i);
-
-      if( object!=null )
-        {
-        if( i>0 ) list.append(',');
-        list.append(object.getName());
-        }
-      }
-
-    return list.toString();
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private String constructDownloadURL()
@@ -552,8 +572,9 @@ public class RubikNetwork implements Runnable
       if( mMode==SUBMIT )
         {
         mRunning = true;
+        RubikScores scores = RubikScores.getInstance();
 
-        if( RubikScores.getInstance().thereAreUnsubmittedRecords() )
+        if( scores.thereAreUnsubmittedRecords() )
           {
           receiveValues = network(constructSubmitURL());
           }
@@ -564,6 +585,12 @@ public class RubikNetwork implements Runnable
         receiveValues = false;
         mRunning = false;
         }
+      if( mMode==SUSPICIOUS )
+        {
+        sendSuspicious();
+        receiveValues = false;
+        mRunning = false;
+        }
       }
     catch( Exception e )
       {
@@ -656,4 +683,12 @@ public class RubikNetwork implements Runnable
     {
     start(null, act, DEBUG);
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void suspicious(AppCompatActivity act, String debug)
+    {
+    mDebug = debug;
+    start(null, act, SUSPICIOUS);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/org/distorted/tutorials/TutorialObjectLibInterface.java b/src/main/java/org/distorted/tutorials/TutorialObjectLibInterface.java
index 746c30da..52f6bf2e 100644
--- a/src/main/java/org/distorted/tutorials/TutorialObjectLibInterface.java
+++ b/src/main/java/org/distorted/tutorials/TutorialObjectLibInterface.java
@@ -41,7 +41,7 @@ public class TutorialObjectLibInterface implements ObjectLibInterface
     mAct = new WeakReference<>(act);
     }
 
-  public void onWinEffectFinished(String debug, int scrambleNum) { }
+  public void onWinEffectFinished(long startTime, long endTime, String debug, int scrambleNum) { }
   public void onScrambleEffectFinished() { }
   public void onBeginRotation() { }
   public void onSolved() { }
