commit 00fcfefac3a4f44fafcb9badc32bf71674944853
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Nov 23 16:03:34 2022 +0100

    All users who are upgrading from a version <1.11.4, where there was no concept of 'stars', get all their stars.

diff --git a/src/main/java/org/distorted/external/RubikScores.java b/src/main/java/org/distorted/external/RubikScores.java
index 06f10736..7d8320e6 100644
--- a/src/main/java/org/distorted/external/RubikScores.java
+++ b/src/main/java/org/distorted/external/RubikScores.java
@@ -24,6 +24,7 @@ import org.distorted.objects.RubikObjectList;
 import org.distorted.screens.RubikScreenPlay;
 
 import static org.distorted.objectlib.main.ObjectType.MAX_SCRAMBLES;
+import static org.distorted.screens.RubikScreenPlay.LEVELS_SHOWN;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // hold my own scores, and some other statistics.
@@ -249,6 +250,32 @@ public class RubikScores
     return mNumStars;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void correctNumStars()
+    {
+    int numObjects = RubikObjectList.getNumObjects();
+
+    for(int obj=0; obj<numObjects; obj++)
+      {
+      for(int level=0; level<=RubikScreenPlay.LEVELS_SHOWN; level++)
+        {
+        if( isSolved(obj,level) )
+          {
+          int numStars = computeNumStars(level+1);
+          mNumStars += numStars;
+          }
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int computeNumStars(int level)
+    {
+    return level>=LEVELS_SHOWN ? 50 : level;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void setName(String newName)
diff --git a/src/main/java/org/distorted/main/RubikActivity.java b/src/main/java/org/distorted/main/RubikActivity.java
index 9915c2af..71971cdc 100644
--- a/src/main/java/org/distorted/main/RubikActivity.java
+++ b/src/main/java/org/distorted/main/RubikActivity.java
@@ -390,6 +390,45 @@ public class RubikActivity extends AppCompatActivity
         FirebaseAnalytics analytics = getAnalytics();
         analytics.setUserId(scores.getName());
         }
+
+      // all old users upgrading from version <1.11.4, where there was no concept of 'stars',
+      // get all the stars they have earned
+      int numStars = scores.getNumStars();
+
+      if( numStars==0 && upgradingFromVersionWithNoStars(oldVersion) )
+        {
+        scores.correctNumStars();
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private boolean upgradingFromVersionWithNoStars(String version)
+      {
+      if( version!=null )
+        {
+        try
+          {
+          int dot = version.indexOf('.',2);
+
+          if( dot>2 )
+            {
+            String middle = version.substring(2,dot);
+            int middleInt = Integer.parseInt(middle);
+
+            if( middleInt<11 ) return true;
+            if( middleInt==11 )
+              {
+              String end = version.substring(dot+1);
+              int endInt = Integer.parseInt(end);
+              return endInt<4;
+              }
+            }
+          }
+        catch(Exception ignored) {}
+        }
+
+      return false;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/main/RubikObjectLibInterface.java b/src/main/java/org/distorted/main/RubikObjectLibInterface.java
index b739b6c2..d3d87e3b 100644
--- a/src/main/java/org/distorted/main/RubikObjectLibInterface.java
+++ b/src/main/java/org/distorted/main/RubikObjectLibInterface.java
@@ -450,7 +450,7 @@ public class RubikObjectLibInterface implements ObjectLibInterface, ListenerOver
         case RECORD_FIRST  : RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
                              int level = play.getLevel();
                              RubikScores scores = RubikScores.getInstance();
-                             int newStars = RubikObjectList.computeNumStars(level);
+                             int newStars = scores.computeNumStars(level);
                              scores.changeNumStars(newStars);
                              RubikDialogNewRecord d1 = new RubikDialogNewRecord();
                              d1.setArguments(bundle);
diff --git a/src/main/java/org/distorted/objects/RubikObjectList.java b/src/main/java/org/distorted/objects/RubikObjectList.java
index e0200cd1..c909bb8d 100644
--- a/src/main/java/org/distorted/objects/RubikObjectList.java
+++ b/src/main/java/org/distorted/objects/RubikObjectList.java
@@ -147,13 +147,6 @@ public class RubikObjectList
     return true;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public static int computeNumStars(int level)
-    {
-    return level>=LEVELS_SHOWN ? 50 : level;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private static void restoreFreedObjects(SharedPreferences preferences)
