commit 17f9a69551f0023598294031cb8eda54b59a10e4
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Mar 22 01:17:14 2020 +0000

    progress with submitting one's high scores.

diff --git a/src/main/java/org/distorted/dialog/RubikDialogScoresPagerAdapter.java b/src/main/java/org/distorted/dialog/RubikDialogScoresPagerAdapter.java
index 84bc1697..426bf8b6 100644
--- a/src/main/java/org/distorted/dialog/RubikDialogScoresPagerAdapter.java
+++ b/src/main/java/org/distorted/dialog/RubikDialogScoresPagerAdapter.java
@@ -60,6 +60,38 @@ class RubikDialogScoresPagerAdapter extends PagerAdapter implements RubikScoresD
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void message(final String mess)
+    {
+    mAct.runOnUiThread(new Runnable()
+      {
+      @Override
+      public void run()
+        {
+        for(int i=0; i<mNumTabs; i++)
+          {
+          mViews[i].message(mess);
+          }
+        }
+      });
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void serverError(final String error)
+    {
+    char errorNumber = error.charAt(0);
+
+    switch(errorNumber)
+      {
+      case '2': message("Name Taken");   // TODO
+                break;
+      case '3': message("Server error");
+                break;
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void prepareView()
@@ -113,23 +145,6 @@ class RubikDialogScoresPagerAdapter extends PagerAdapter implements RubikScoresD
       }
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void message(final String mess)
-    {
-    mAct.runOnUiThread(new Runnable()
-      {
-      @Override
-      public void run()
-        {
-        for(int i=0; i<mNumTabs; i++)
-          {
-          mViews[i].message(mess);
-          }
-        }
-      });
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   RubikDialogScoresPagerAdapter(FragmentActivity act, ViewPager viewPager, boolean isSubmitting)
diff --git a/src/main/java/org/distorted/scores/RubikScores.java b/src/main/java/org/distorted/scores/RubikScores.java
index e39c1808..74623a8e 100644
--- a/src/main/java/org/distorted/scores/RubikScores.java
+++ b/src/main/java/org/distorted/scores/RubikScores.java
@@ -73,6 +73,72 @@ public class RubikScores
     mDeviceID= -1;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int privateGetDeviceID()
+    {
+    int id;
+
+    try
+      {
+      String s = UUID.randomUUID().toString();
+      id = (s!=null ? s.hashCode():0);
+      }
+    catch(Exception ex)
+      {
+      id = 0;
+      android.util.Log.e("scores", "Exception in getDeviceID()");
+      }
+
+    return id<0 ? -id : id;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private String getUnsubmittedList(int mode)
+    {
+    RubikObjectList list;
+    StringBuilder builder = new StringBuilder();
+    boolean first = true;
+    int[] sizes;
+    int length;
+
+    for(int object=0; object<NUM_OBJECTS; object++)
+      {
+      list = RubikObjectList.getObject(object);
+      sizes = list.getSizes();
+      length = sizes.length;
+
+      for(int size=0; size<length; size++)
+        {
+        for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
+          {
+          if( mSubmitted[object][size][scramble]==0 && mRecords[object][size][scramble]<NO_RECORD )
+            {
+            if( !first ) builder.append(',');
+            else         first=false;
+
+            switch(mode)
+              {
+              case 0: builder.append(list.name());
+                      builder.append("_");
+                      builder.append(sizes[size]);
+                      break;
+              case 1: builder.append(scramble);
+                      break;
+              case 2: builder.append(mRecords[object][size][scramble]);
+                      break;
+              }
+            }
+          }
+        }
+      }
+
+    return builder.toString();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public static RubikScores getInstance()
@@ -170,11 +236,12 @@ public class RubikScores
             {
             mRecords  [object][size][scramble] = time;
             mSubmitted[object][size][scramble] = subm;
-
+/*
             if( time<NO_RECORD )
               {
               android.util.Log.e("solv", "Set record for: object="+object+" size="+size+" scramble="+scramble+" time: "+time+" submitted: "+subm);
               }
+*/
             }
           else
             {
@@ -190,7 +257,7 @@ public class RubikScores
     mNumRuns        = preferences.getInt("scores_numRuns" , 0);
     mDeviceID       = preferences.getInt("scores_deviceid",-1);
 
-    if( mDeviceID==-1 ) mDeviceID = getDeviceID();
+    if( mDeviceID==-1 ) mDeviceID = privateGetDeviceID();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -234,9 +301,8 @@ public class RubikScores
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO
 
-  public void successfulSubmit()
+  void successfulSubmit()
     {
     mNameIsVerified = true;
 
@@ -271,26 +337,6 @@ public class RubikScores
     if( mCountry.equals("do") ) mCountry = "dm";
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  int getDeviceID()
-    {
-    int id;
-
-    try
-      {
-      String s = UUID.randomUUID().toString();
-      id = (s!=null ? s.hashCode():0);
-      }
-    catch(Exception ex)
-      {
-      id = 0;
-      android.util.Log.e("scores", "Exception in getDeviceID()");
-      }
-
-    return id<0 ? -id : id;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public long getRecord(int object, int size, int scramble)
@@ -319,6 +365,13 @@ public class RubikScores
     return false;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int getDeviceID()
+    {
+    return mDeviceID;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   boolean isVerified()
@@ -356,46 +409,25 @@ public class RubikScores
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private String getUnsubmittedList(int mode)
+  boolean thereAreUnsubmittedRecords()
     {
     RubikObjectList list;
-    StringBuilder builder = new StringBuilder();
-    boolean first = true;
-    int[] sizes;
     int length;
 
     for(int object=0; object<NUM_OBJECTS; object++)
       {
       list = RubikObjectList.getObject(object);
-      sizes = list.getSizes();
-      length = sizes.length;
+      length = list.getSizes().length;
 
       for(int size=0; size<length; size++)
-        {
         for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
-          {
           if( mSubmitted[object][size][scramble]==0 && mRecords[object][size][scramble]<NO_RECORD )
             {
-            if( !first ) builder.append(',');
-            else         first=false;
-
-            switch(mode)
-              {
-              case 0: builder.append(list.name());
-                      builder.append("_");
-                      builder.append(sizes[size]);
-                      break;
-              case 1: builder.append(scramble);
-                      break;
-              case 2: builder.append(mRecords[object][size][scramble]);
-                      break;
-              }
+            return true;
             }
-          }
-        }
       }
 
-    return builder.toString();
+    return false;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/scores/RubikScoresDownloader.java b/src/main/java/org/distorted/scores/RubikScoresDownloader.java
index b4dacbb1..c3fce4c4 100644
--- a/src/main/java/org/distorted/scores/RubikScoresDownloader.java
+++ b/src/main/java/org/distorted/scores/RubikScoresDownloader.java
@@ -39,6 +39,7 @@ public class RubikScoresDownloader implements Runnable
     {
     void receive(String[][][] country, String[][][] name, float[][][] time);
     void message(String mess);
+    void serverError(String error);
     }
 
   public static final int MAX_PLACES = 10;
@@ -106,18 +107,11 @@ public class RubikScoresDownloader implements Runnable
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// TODO: handle the fact that the server might return 'error' (3) or 'name taken' (2)
 
-  private void fillSubmittedValues()
-    {
-    fillDownloadedValues();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void fillDownloadedValues()
+  private boolean fillValues()
     {
     int begin=-1 ,end, len = mScores.length();
+    String row;
 
     for(int i=0; i<mTotal; i++)
       for(int j=0; j<MAX_SCRAMBLE; j++)
@@ -132,7 +126,17 @@ public class RubikScoresDownloader implements Runnable
 
       try
         {
-        fillRow(mScores.substring(begin+1,end));
+        row = mScores.substring(begin+1,end);
+
+        if( row.length()==1 )
+          {
+          mReceiver.serverError(row);
+          return false;
+          }
+        else
+          {
+          fillRow(row);
+          }
         }
       catch(Exception ex)
         {
@@ -141,6 +145,8 @@ public class RubikScoresDownloader implements Runnable
 
       begin = end;
       }
+
+    return true;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -273,6 +279,47 @@ public class RubikScoresDownloader implements Runnable
     return true;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private String constructDownloadURL()
+    {
+    RubikScores scores = RubikScores.getInstance();
+    String name = URLencode(scores.getName());
+    String veri = scores.isVerified() ? name : "";
+    int numRuns = scores.getNumRuns();
+    int numPlay = scores.getNumPlays();
+
+    String url="https://distorted.org/magic/cgi-bin/download.cgi";
+    url += "?n="+name+"&v="+veri+"&r="+numRuns+"&p="+numPlay+"&e="+mVersion+"d";
+    url += "&o="+RubikObjectList.getObjectList()+"&min=0&max="+MAX_SCRAMBLE+"&l="+MAX_PLACES;
+
+    return url;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private String constructSubmitURL()
+    {
+    RubikScores scores = RubikScores.getInstance();
+    String name = URLencode(scores.getName());
+    String veri = scores.isVerified() ? name : "";
+    int numRuns = scores.getNumRuns();
+    int numPlay = scores.getNumPlays();
+    int deviceID= scores.getDeviceID();
+    String objlist = scores.getUnsubmittedObjlist();
+    String lvllist = scores.getUnsubmittedLevellist();
+    String timlist = scores.getUnsubmittedTimelist();
+    String country = scores.getCountry();
+    int hash = computeHash(name,veri,country,lvllist,objlist,timlist,numRuns);
+
+    String url="https://distorted.org/magic/cgi-bin/submit.cgi";
+    url += "?n="+name+"&v="+veri+"&r="+numRuns+"&p="+numPlay+"&i="+deviceID+"&e="+mVersion+"d";
+    url += "&o="+objlist+"&l="+lvllist+"&t="+timlist+"&c="+country+"&h="+hash;
+    url += "&oo="+RubikObjectList.getObjectList()+"&min=0&max="+MAX_SCRAMBLE+"&lo="+MAX_PLACES;
+
+    return url;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private boolean gottaDownload()
@@ -287,70 +334,42 @@ public class RubikScoresDownloader implements Runnable
     {
     boolean success=true;
 
-    if( mMode==DOWNLOAD && gottaDownload() )
+    try
       {
-      mRunning = true;
-
-      try
+      if( mMode==DOWNLOAD && gottaDownload() )
         {
-        RubikScores scores = RubikScores.getInstance();
-        String name = URLencode(scores.getName());
-        String veri = scores.isVerified() ? name : "";
-        int numRuns = scores.getNumRuns();
-        int numPlay = scores.getNumPlays();
-
-        String url="https://distorted.org/magic/cgi-bin/download.cgi";
-        url += "?n="+name+"&v="+veri+"&r="+numRuns+"&p="+numPlay+"&e="+mVersion+"d";
-        url += "&o="+RubikObjectList.getObjectList()+"&min=0&max="+MAX_SCRAMBLE+"&l="+MAX_PLACES;
-
-        success = network(url);
+        mRunning = true;
+        success = network(constructDownloadURL());
         }
-      catch( Exception e )
+      if( mMode==SUBMIT )
         {
-        mReceiver.message("Exception downloading records: "+e.getMessage() );
-        }
+        mRunning = true;
 
-      fillDownloadedValues();
+        if( RubikScores.getInstance().thereAreUnsubmittedRecords() )
+          {
+          success = network(constructSubmitURL());
+          }
+        }
       }
-
-    if( mMode==SUBMIT )
+    catch( Exception e )
       {
-      mRunning = true;
-
-      try
-        {
-        RubikScores scores = RubikScores.getInstance();
-        String name = URLencode(scores.getName());
-        String veri = scores.isVerified() ? name : "";
-        int numRuns = scores.getNumRuns();
-        int numPlay = scores.getNumPlays();
-        int deviceID= scores.getDeviceID();
-        String objlist = scores.getUnsubmittedObjlist();
-        String lvllist = scores.getUnsubmittedLevellist();
-        String timlist = scores.getUnsubmittedTimelist();
-        String country = scores.getCountry();
-        int hash = computeHash(name,veri,country,lvllist,objlist,timlist,numRuns);
-
-        String url="https://distorted.org/magic/cgi-bin/submit.cgi";
-        url += "?n="+name+"&v="+veri+"&r="+numRuns+"&p="+numPlay+"&i="+deviceID+"&e="+mVersion+"d";
-        url += "&o="+objlist+"&l="+lvllist+"&t="+timlist+"&c="+country+"&h="+hash;
-        url += "&oo="+RubikObjectList.getObjectList()+"&min=0&max="+MAX_SCRAMBLE+"&lo="+MAX_PLACES;
-
-        success = network(url);
-        }
-      catch( Exception e )
-        {
-        mReceiver.message("Exception submitting records: "+e.getMessage() );
-        }
-
-      fillSubmittedValues();
+      mReceiver.message("Exception downloading records: "+e.getMessage() );
       }
 
-    mRunning = false;
+    if( mRunning )
+      {
+      success = fillValues();
+      mRunning = false;
+      }
 
     if( success )
       {
       mReceiver.receive(mCountry, mName, mTime);
+
+      if( mMode==SUBMIT )
+        {
+        RubikScores.getInstance().successfulSubmit();
+        }
       }
     }
 
