commit 6142069a820edb9cbbe9a63ade539cb99b9bd00b
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Sep 19 12:37:49 2022 +0200

    Progress with marking objects as free.

diff --git a/src/main/java/org/distorted/external/RubikScores.java b/src/main/java/org/distorted/external/RubikScores.java
index d27b6d61..cd4637d0 100644
--- a/src/main/java/org/distorted/external/RubikScores.java
+++ b/src/main/java/org/distorted/external/RubikScores.java
@@ -21,6 +21,7 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics;
 import org.distorted.main.BuildConfig;
 import org.distorted.objects.RubikObject;
 import org.distorted.objects.RubikObjectList;
+import org.distorted.screens.RubikScreenPlay;
 
 import static org.distorted.objectlib.main.ObjectType.MAX_SCRAMBLES;
 
@@ -431,6 +432,21 @@ public class RubikScores
     if( thereWasError ) recordDBError(errorStr);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int numberOfSolvedMAXes()
+    {
+    int numObjects = RubikObjectList.getNumObjects();
+    int ret=0, level = RubikScreenPlay.LEVELS_SHOWN;
+
+    for(int obj=0; obj<numObjects; obj++)
+      {
+      if( isSolved(obj,level) ) ret++;
+      }
+
+    return ret;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void recordDBError(String message)
diff --git a/src/main/java/org/distorted/main/RubikActivity.java b/src/main/java/org/distorted/main/RubikActivity.java
index 51563927..43518290 100644
--- a/src/main/java/org/distorted/main/RubikActivity.java
+++ b/src/main/java/org/distorted/main/RubikActivity.java
@@ -61,6 +61,7 @@ import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
 public class RubikActivity extends AppCompatActivity
 {
     public static final boolean SHOW_DOWNLOADED_DEBUG = false;
+    public static final boolean SHOW_SOLVED_DEBUG     = true;
 
     public static final float PADDING             = 0.01f;
     public static final float SMALL_MARGIN        = 0.004f;
@@ -253,12 +254,12 @@ public class RubikActivity extends AppCompatActivity
       DistortedLibrary.onResume(ACTIVITY_NUMBER);
       RubikSurfaceView view = findViewById(R.id.rubikSurfaceView);
       view.onResume();
-      restorePreferences(mJustStarted);
 
+      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+      restorePreferences(preferences,mJustStarted);
       ScreenList.setScreen(this);
       unblockEverything();
-
-      restoreMoves();
+      restoreMoves(preferences);
 
       if( mJustStarted )
         {
@@ -266,7 +267,6 @@ public class RubikActivity extends AppCompatActivity
         RubikScores scores = RubikScores.getInstance();
         scores.incrementNumRuns();
         scores.setCountry(this);
-        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
         RubikObjectList.restoreMeshState(preferences);
         }
 
@@ -345,10 +345,8 @@ public class RubikActivity extends AppCompatActivity
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private void restorePreferences(boolean justStarted)
+    private void restorePreferences(SharedPreferences preferences, boolean justStarted)
       {
-      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
-
       mPolicyAccepted = preferences.getBoolean("policyAccepted", false);
       String oldVersion = preferences.getString("appVersion","");
 
@@ -364,6 +362,9 @@ public class RubikActivity extends AppCompatActivity
         ScreenList.getScreen(i).getScreenClass().restorePreferences(preferences);
         }
 
+      // this needs to be after the above ScreenList.restore as that restores the Records which we need here
+      if( justStarted ) RubikObjectList.setObjectFreeState();
+
       ScreenList.restorePreferences(preferences);
       RubikSurfaceView view = findViewById(R.id.rubikSurfaceView);
 
@@ -392,9 +393,8 @@ public class RubikActivity extends AppCompatActivity
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private void restoreMoves()
+    private void restoreMoves(SharedPreferences preferences)
       {
-      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
       ScreenList curr = ScreenList.getCurrentScreen();
 
       if( curr==ScreenList.PLAY )
diff --git a/src/main/java/org/distorted/objects/RubikObjectList.java b/src/main/java/org/distorted/objects/RubikObjectList.java
index 49deaa93..24541168 100644
--- a/src/main/java/org/distorted/objects/RubikObjectList.java
+++ b/src/main/java/org/distorted/objects/RubikObjectList.java
@@ -16,13 +16,16 @@ import android.content.Context;
 import android.content.SharedPreferences;
 
 import org.distorted.external.RubikFiles;
+import org.distorted.external.RubikScores;
 import org.distorted.main.RubikActivity;
 import org.distorted.objectlib.main.ObjectSignatures;
 import org.distorted.objectlib.main.ObjectType;
+import org.distorted.screens.RubikScreenPlay;
 
 import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
 import static org.distorted.objectlib.main.ObjectType.NUM_OBJECTS;
 import static org.distorted.main.RubikActivity.SHOW_DOWNLOADED_DEBUG;
+import static org.distorted.main.RubikActivity.SHOW_SOLVED_DEBUG;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -59,13 +62,15 @@ public class RubikObjectList
   private static ArrayList<DownloadedObject> mDownloadedObjects;
   private static String mFreeSolvedObjects;
   private static String mFreeBoughtObjects;
+  private static int mNumFreeSolved;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private RubikObjectList()
     {
-    mNumObjects= 0;
-    mNumExtras = 0;
+    mNumObjects    = 0;
+    mNumExtras     = 0;
+    mNumFreeSolved = 0;
 
     mObjects           = new ArrayList<>();
     mDownloadedObjects = new ArrayList<>();
@@ -116,6 +121,15 @@ public class RubikObjectList
     mObjects.add(obj);
     mNumObjects++;
 
+    int numUnclaimed = getNumUnclaimedSolves();
+
+    if( numUnclaimed>0 && !obj.isFree() )
+      {
+      String objname = obj.getUpperName();
+      if( SHOW_SOLVED_DEBUG ) android.util.Log.e("D", "downloadedObject: "+objname+" making it solved. Unclaimed: "+numUnclaimed);
+      solveObject(obj,objname);
+      }
+
     if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "creating downloaded object "+obj.getUpperName() );
 
     if( obj.hasExtras() )
@@ -133,6 +147,121 @@ public class RubikObjectList
     return true;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private static void restoreFreedObjects(SharedPreferences preferences)
+    {
+    mFreeSolvedObjects = preferences.getString("rol_freeSolved", "");
+    mFreeBoughtObjects = preferences.getString("rol_freeBought", "");
+
+    if( SHOW_SOLVED_DEBUG )
+      {
+      android.util.Log.e("D", "freeSolved: "+mFreeSolvedObjects);
+      android.util.Log.e("D", "freeBought: "+mFreeBoughtObjects);
+      }
+
+    if( mFreeBoughtObjects.length()>0 )
+      {
+      if( mFreeBoughtObjects.charAt(0)=='*' )
+        {
+        for(int i=0; i<mNumObjects; i++)
+          {
+          RubikObject o = mObjects.get(i);
+          o.markFree();
+          }
+        }
+      else
+        {
+        String[] objs = mFreeBoughtObjects.split(",");
+
+        for( String obj : objs )
+          {
+          RubikObject o = getObject(obj);
+          if( o!=null ) o.markFree();
+          }
+        }
+      }
+
+    if( mFreeSolvedObjects.length()>0 )
+      {
+      String[] objs = mFreeSolvedObjects.split(",");
+      mNumFreeSolved = objs.length;
+
+      for( String obj : objs )
+        {
+        RubikObject o = getObject(obj);
+        if( o!=null ) o.markFree();
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private static int getNumUnclaimedSolves()
+    {
+    RubikScores scores = RubikScores.getInstance();
+    int numMAXes = scores.numberOfSolvedMAXes();
+    return numMAXes-mNumFreeSolved;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private static int markAllSolvedAsFree()
+    {
+    RubikScores scores = RubikScores.getInstance();
+    int numObjects = RubikObjectList.getNumObjects();
+    int level = RubikScreenPlay.LEVELS_SHOWN;
+    int ret = 0;
+
+    for(int obj=0; obj<numObjects; obj++)
+      {
+      RubikObject object = getObject(obj);
+
+      if( object!=null && !object.isFree() && scores.isSolved(obj,level) )
+        {
+        solveObject(object.getUpperName());
+        ret++;
+        }
+      }
+
+    return ret;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private static void markAsFree(int numToBeMarked)
+    {
+    int numObjects = RubikObjectList.getNumObjects();
+
+    for(int obj=0; obj<numObjects && numToBeMarked>0; obj++)
+      {
+      RubikObject object = getObject(obj);
+
+      if( object!=null && !object.isFree() )
+        {
+        solveObject(object.getUpperName());
+        numToBeMarked--;
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static boolean solveObject(RubikObject object, String shortName)
+    {
+    if( object!=null && !object.isFree() )
+      {
+      if( SHOW_SOLVED_DEBUG ) android.util.Log.e("D", "object "+shortName+" marked as solved");
+      object.markFree();
+      String add = mFreeSolvedObjects.length()==0 ? shortName : (","+shortName);
+      mFreeSolvedObjects += add;
+      mNumFreeSolved++;
+      return true;
+      }
+
+    return false;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 
@@ -242,6 +371,7 @@ public class RubikObjectList
   public static void buyAll()
     {
     mFreeBoughtObjects = "*";
+    if( SHOW_SOLVED_DEBUG ) android.util.Log.e("D", "all objects marked as bought");
 
     for(int i=0; i<mNumObjects; i++)
       {
@@ -258,6 +388,7 @@ public class RubikObjectList
 
     if( o!=null && !o.isFree() )
       {
+      if( SHOW_SOLVED_DEBUG ) android.util.Log.e("D", "object "+shortName+" marked as bought");
       o.markFree();
       String add = mFreeBoughtObjects.length()==0 ? shortName : (","+shortName);
       mFreeBoughtObjects += add;
@@ -271,17 +402,8 @@ public class RubikObjectList
 
   public static boolean solveObject(String shortName)
     {
-    RubikObject o = getObject(shortName);
-
-    if( o!=null && !o.isFree() )
-      {
-      o.markFree();
-      String add = mFreeSolvedObjects.length()==0 ? shortName : (","+shortName);
-      mFreeSolvedObjects += add;
-      return true;
-      }
-
-    return false;
+    RubikObject object = getObject(shortName);
+    return solveObject(object,shortName);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -330,6 +452,12 @@ public class RubikObjectList
 
     editor.putString("rol_freeSolved", mFreeSolvedObjects);
     editor.putString("rol_freeBought", mFreeBoughtObjects);
+
+    if( SHOW_SOLVED_DEBUG )
+      {
+      android.util.Log.e("D", "saving solved objects: "+mFreeSolvedObjects);
+      android.util.Log.e("D", "saving bought objects: "+mFreeBoughtObjects);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -381,44 +509,7 @@ public class RubikObjectList
     mObject = getOrdinal(objName);
     if( mObject<0 || mObject>=mNumObjects ) mObject = DEF_OBJECT;
 
-    if( justStarted )
-      {
-      mFreeSolvedObjects = preferences.getString("rol_freeSolved", "");
-      mFreeBoughtObjects = preferences.getString("rol_freeBought", "");
-
-      if( mFreeBoughtObjects.length()>0 )
-        {
-        if( mFreeBoughtObjects.charAt(0)=='*' )
-          {
-          for(int i=0; i<mNumObjects; i++)
-            {
-            RubikObject o = mObjects.get(i);
-            o.markFree();
-            }
-          }
-        else
-          {
-          String[] objs = mFreeBoughtObjects.split(",");
-
-          for( String obj : objs )
-            {
-            RubikObject o = getObject(obj);
-            if( o!=null ) o.markFree();
-            }
-          }
-        }
-
-      if( mFreeSolvedObjects.length()>0 )
-        {
-        String[] objs = mFreeSolvedObjects.split(",");
-
-        for( String obj : objs )
-          {
-          RubikObject o = getObject(obj);
-          if( o!=null ) o.markFree();
-          }
-        }
-      }
+    if( justStarted) restoreFreedObjects(preferences);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -438,6 +529,20 @@ public class RubikObjectList
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void setObjectFreeState()
+    {
+    int numUnclaimed = getNumUnclaimedSolves();
+
+    if( numUnclaimed>0 )
+      {
+      int marked = markAllSolvedAsFree();
+      int stillUnclaimed = numUnclaimed-marked;
+      if( stillUnclaimed>0) markAsFree(stillUnclaimed);
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public static boolean setCurrObject(int ordinal)
