commit ffe7e55d51ebe175a8aa253af511da5802e80ec8
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Jan 27 00:21:36 2022 +0100

    Reorganize the Network so that concurrent network operattions are possible.
    Finally figure out and fix the bug which was causing users to multi-submit the same records over and over.

diff --git a/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java b/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
index 2b56b4e1..a067f07c 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
@@ -177,6 +177,9 @@ public class RubikDialogUpdates extends AppCompatDialogFragment implements Rubik
           View pane = rubikView.createView(act,info,mFontSize,mPadding,pI,pV,pT,pB);
           mLayout.addView(pane);
           }
+
+        RubikNetwork network = RubikNetwork.getInstance();
+        network.downloadIcons(this);
         }
       else
         {
@@ -211,6 +214,13 @@ public class RubikDialogUpdates extends AppCompatDialogFragment implements Rubik
     mText.setText("Network error");
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void iconDownloaded()
+    {
+
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public static String getDialogTag()
diff --git a/src/main/java/org/distorted/main/RubikObjectLibInterface.java b/src/main/java/org/distorted/main/RubikObjectLibInterface.java
index 06100a8f..05e05dda 100644
--- a/src/main/java/org/distorted/main/RubikObjectLibInterface.java
+++ b/src/main/java/org/distorted/main/RubikObjectLibInterface.java
@@ -123,7 +123,7 @@ public class RubikObjectLibInterface implements ObjectLibInterface
         long elapsed = timeNow - startTime;
         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);
+        network.suspicious(suspicious);
         }
 
       FirebaseAnalytics analytics = act.getAnalytics();
diff --git a/src/main/java/org/distorted/main/RubikRenderer.java b/src/main/java/org/distorted/main/RubikRenderer.java
index efd8dd0c..74eea6fb 100644
--- a/src/main/java/org/distorted/main/RubikRenderer.java
+++ b/src/main/java/org/distorted/main/RubikRenderer.java
@@ -140,7 +140,7 @@ public class RubikRenderer implements GLSurfaceView.Renderer, DistortedLibrary.E
         {
         mDebugSent= true;
         RubikNetwork network = RubikNetwork.getInstance();
-        network.debug( (RubikActivity)mView.getContext());
+        network.debug();
         }
       }
 
diff --git a/src/main/java/org/distorted/network/RubikNetwork.java b/src/main/java/org/distorted/network/RubikNetwork.java
index f1e9de49..e41a2f91 100644
--- a/src/main/java/org/distorted/network/RubikNetwork.java
+++ b/src/main/java/org/distorted/network/RubikNetwork.java
@@ -28,11 +28,9 @@ import java.net.UnknownHostException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 
-import android.app.Activity;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 
-import androidx.appcompat.app.AppCompatActivity;
 import androidx.fragment.app.FragmentActivity;
 
 import org.distorted.library.main.DistortedLibrary;
@@ -43,7 +41,7 @@ import static org.distorted.objects.RubikObjectList.MAX_LEVEL;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-public class RubikNetwork implements Runnable
+public class RubikNetwork
   {
   public interface Receiver
     {
@@ -54,24 +52,18 @@ public class RubikNetwork implements Runnable
 
   public interface Updatee
     {
+    void iconDownloaded();
     void receiveUpdate(RubikUpdates update);
     void errorUpdate();
     }
 
   public static final int MAX_PLACES = 10;
 
-  private static final int DOWNLOAD   = 0;
-  private static final int SUBMIT     = 1;
-  private static final int DEBUG      = 2;
-  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;
   private static final int REND_POWER = 2;
   private static final int REND_OTHER = 3;
 
-  private static final int DEBUG_NOT_YET = 0;
   private static final int DEBUG_RUNNING = 1;
   private static final int DEBUG_SUCCESS = 2;
   private static final int DEBUG_FAILURE = 3;
@@ -119,7 +111,6 @@ public class RubikNetwork implements Runnable
   private static RubikNetwork mThis;
   private static String mScores = "";
   private static boolean mRunning = false;
-  private static int mMode = IDLE;
   private static Receiver mReceiver;
   private static Updatee mUpdatee;
   private static String mVersion;
@@ -380,73 +371,6 @@ public class RubikNetwork implements Runnable
     return sbuf.toString();
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void sendDebug()
-    {
-    String url = constructDebugURL();
-/*
-    try { Thread.sleep(5000); }
-    catch( InterruptedException ignored) {}
-*/
-    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();
-
-      InputStream is = conn.getInputStream();
-      BufferedReader r = new BufferedReader(new InputStreamReader(is));
-      StringBuilder answer = new StringBuilder();
-
-      for (String line; (line = r.readLine()) != null; )
-        {
-        answer.append(line).append('\n');
-        }
-
-      String updates = answer.toString();
-      mUpdates.parse(updates);
-      if( mUpdatee!=null ) mUpdatee.receiveUpdate(mUpdates);
-      mDebugState = DEBUG_SUCCESS;
-      }
-    catch( final Exception e )
-      {
-      if( mUpdatee!=null ) mUpdatee.errorUpdate();
-      mDebugState = DEBUG_FAILURE;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  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)
@@ -592,64 +516,142 @@ public class RubikNetwork implements Runnable
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  @Override
-  public void run()
+  private void figureOutVersion(FragmentActivity act)
     {
-    boolean receiveValues=true;
+    try
+      {
+      PackageInfo pInfo = act.getPackageManager().getPackageInfo( act.getPackageName(), 0);
+      mVersion = pInfo.versionName;
+      }
+    catch (PackageManager.NameNotFoundException e)
+      {
+      mVersion = "0.9.2";
+      }
+    }
 
-    initializeStatics();
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
+  private void downloadThread()
+    {
     try
       {
-      if( mMode==DOWNLOAD && gottaDownload() )
-        {
-        mRunning = true;
-        receiveValues = network(constructDownloadURL());
-        }
-      if( mMode==SUBMIT )
+      if( gottaDownload() )
         {
         mRunning = true;
-        RubikScores scores = RubikScores.getInstance();
+        boolean receiveValues = network(constructDownloadURL());
 
-        if( scores.thereAreUnsubmittedRecords() )
+        if( mRunning )
           {
-          receiveValues = network(constructSubmitURL());
+          receiveValues = fillValuesNormal();
+          mRunning = false;
           }
-        }
-      if( mMode==DEBUG )
-        {
-        sendDebug();
-        receiveValues = false;
-        mRunning = false;
-        }
-      if( mMode==SUSPICIOUS )
-        {
-        sendSuspicious();
-        receiveValues = false;
-        mRunning = false;
+
+        if( receiveValues && mReceiver!=null ) mReceiver.receive(mCountry, mName, mTime);
         }
       }
     catch( Exception e )
       {
-      android.util.Log.e("D", "Exception in RUN");
-
       if( mReceiver!=null ) mReceiver.message("Exception downloading records: "+e.getMessage() );
       }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    if( mRunning )
+  private void submitThread()
+    {
+    try
+      {
+      mRunning = true;
+      RubikScores scores = RubikScores.getInstance();
+
+      if( scores.thereAreUnsubmittedRecords() )
+        {
+        boolean receiveValues = network(constructSubmitURL());
+
+        if( mRunning )
+          {
+          receiveValues = fillValuesNormal();
+          mRunning = false;
+          }
+
+        if( receiveValues )
+          {
+          RubikScores.getInstance().successfulSubmit();
+          if( mReceiver!=null ) mReceiver.receive(mCountry, mName, mTime);
+          }
+        }
+      }
+    catch( Exception e )
       {
-      receiveValues = fillValuesNormal();
-      mRunning = false;
+      if( mReceiver!=null ) mReceiver.message("Exception submitting records: "+e.getMessage() );
       }
+    }
 
-    if( receiveValues )
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void debugThread()
+    {
+    String url = constructDebugURL();
+/*
+    try { Thread.sleep(5000); }
+    catch( InterruptedException ignored) {}
+*/
+    try
       {
-      if( mReceiver!=null ) mReceiver.receive(mCountry, mName, mTime);
+      java.net.URL connectURL = new URL(url);
+      HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
 
-      if( mMode==SUBMIT )
+      conn.setDoInput(true);
+      conn.setDoOutput(true);
+      conn.setUseCaches(false);
+      conn.setRequestMethod("GET");
+      conn.connect();
+      conn.getOutputStream().flush();
+
+      InputStream is = conn.getInputStream();
+      BufferedReader r = new BufferedReader(new InputStreamReader(is));
+      StringBuilder answer = new StringBuilder();
+
+      for (String line; (line = r.readLine()) != null; )
         {
-        RubikScores.getInstance().successfulSubmit();
+        answer.append(line).append('\n');
         }
+
+      String updates = answer.toString();
+      mUpdates.parse(updates);
+
+      if( mUpdatee!=null ) mUpdatee.receiveUpdate(mUpdates);
+      mDebugState = DEBUG_SUCCESS;
+      }
+    catch( final Exception e )
+      {
+      if( mUpdatee!=null ) mUpdatee.errorUpdate();
+      mDebugState = DEBUG_FAILURE;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void suspiciousThread()
+    {
+    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
       }
     }
 
@@ -683,53 +685,76 @@ public class RubikNetwork implements Runnable
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void start(Receiver receiver, Activity act, int mode)
+  public void download(Receiver receiver, FragmentActivity act)
     {
+    initializeStatics();
     mReceiver = receiver;
-    mMode     = mode;
+    figureOutVersion(act);
 
-    try
+    Thread thread = new Thread()
       {
-      PackageInfo pInfo = act.getPackageManager().getPackageInfo( act.getPackageName(), 0);
-      mVersion = pInfo.versionName;
-      }
-    catch (PackageManager.NameNotFoundException e)
-      {
-      mVersion = "0.9.2";
-      }
+      public void run()
+        {
+        downloadThread();
+        }
+      };
 
-    Thread networkThrd = new Thread(this);
-    networkThrd.start();
+    thread.start();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void download(Receiver receiver, FragmentActivity act)
+  public void submit(Receiver receiver, FragmentActivity act)
     {
-    start(receiver, act, DOWNLOAD);
-    }
+    initializeStatics();
+    mReceiver = receiver;
+    figureOutVersion(act);
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    Thread thread = new Thread()
+      {
+      public void run()
+        {
+        submitThread();
+        }
+      };
 
-  public void submit(Receiver receiver, FragmentActivity act)
-    {
-    start(receiver, act, SUBMIT);
+    thread.start();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void debug(AppCompatActivity act)
+  public void debug()
     {
+    initializeStatics();
     mDebugState = DEBUG_RUNNING;
-    start(null, act, DEBUG);
+
+    Thread thread = new Thread()
+      {
+      public void run()
+        {
+        debugThread();
+        }
+      };
+
+    thread.start();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void suspicious(AppCompatActivity act, String suspicious)
+  public void suspicious(String suspicious)
     {
+    initializeStatics();
     mSuspicious = suspicious;
-    start(null, act, SUSPICIOUS);
+
+    Thread thread = new Thread()
+      {
+      public void run()
+        {
+        suspiciousThread();
+        }
+      };
+
+    thread.start();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -749,6 +774,13 @@ public class RubikNetwork implements Runnable
     else mUpdatee = updatee;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void downloadIcons(Updatee updatee)
+    {
+
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void updateDone(String shortName)
diff --git a/src/main/java/org/distorted/screens/RubikScreenPlay.java b/src/main/java/org/distorted/screens/RubikScreenPlay.java
index 5c8bdb7f..97ec7150 100644
--- a/src/main/java/org/distorted/screens/RubikScreenPlay.java
+++ b/src/main/java/org/distorted/screens/RubikScreenPlay.java
@@ -710,8 +710,6 @@ public class RubikScreenPlay extends RubikScreenBase implements RubikNetwork.Upd
 
   public void receiveUpdate(RubikUpdates updates)
     {
-    updates.showDebug();
-
     Activity act = mWeakAct.get();
 
     if( act!=null )
@@ -746,4 +744,11 @@ public class RubikScreenPlay extends RubikScreenBase implements RubikNetwork.Upd
     {
     android.util.Log.e("D", "Screen: Error receiving update");
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void iconDownloaded()
+    {
+    // empty
+    }
   }
