commit daedd473dc9b5509242958e548d5844e96b047bb
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Nov 16 17:38:03 2025 +0100

    progress with remembering solves: properly abstract out saving/restoring the Object State to/from JSON to the objlib.

diff --git a/src/main/java/org/distorted/helpers/RubikRememberedSolves.java b/src/main/java/org/distorted/helpers/RubikRememberedSolves.java
index f9111714..1bbecafd 100644
--- a/src/main/java/org/distorted/helpers/RubikRememberedSolves.java
+++ b/src/main/java/org/distorted/helpers/RubikRememberedSolves.java
@@ -13,6 +13,7 @@ import android.app.Activity;
 
 import org.distorted.library.type.Static4D;
 import org.distorted.main.MainObjectPopup;
+import org.distorted.objectlib.main.TwistyObject;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -56,7 +57,7 @@ public class RubikRememberedSolves
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private JSONObject createData(int elapsed, Static4D rot, int[] quats) throws JSONException
+  private JSONObject createData(int elapsed, Static4D rot, TwistyObject object) throws JSONException
     {
     JSONObject data = new JSONObject();
     data.put("time",System.currentTimeMillis());
@@ -65,9 +66,8 @@ public class RubikRememberedSolves
     data.put("rot1", rot.get1() );
     data.put("rot2", rot.get2() );
     data.put("rot3", rot.get3() );
-    JSONArray qs = new JSONArray();
-    for(int q:quats) qs.put(q);
-    data.put("quats", qs);
+    JSONObject state = object.generateObjectState();
+    data.put("objState", state);
 
     return data;
     }
@@ -100,7 +100,7 @@ public class RubikRememberedSolves
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private String addInfo(InputStream stream, int level, int elapsed, Static4D rot, int[] quats)
+  private String addInfo(InputStream stream, int level, int elapsed, Static4D rot, TwistyObject object)
     {
     if( stream!=null )
       {
@@ -109,7 +109,7 @@ public class RubikRememberedSolves
         String contents = readContents(stream);
         JSONArray levels = new JSONArray(contents);
         JSONArray lvl = levels.getJSONArray(level);
-        JSONObject data = createData(elapsed,rot,quats);
+        JSONObject data = createData(elapsed,rot,object);
         if( lvl.length()>=MAXSOLVES || level==0) lvl.remove(0);
         lvl.put(data);
         return levels.toString();
@@ -129,7 +129,7 @@ public class RubikRememberedSolves
 
           if( l==level )
             {
-            JSONObject data = createData(elapsed,rot,quats);
+            JSONObject data = createData(elapsed,rot,object);
             save.put(data);
             }
           levels.put(save);
@@ -181,13 +181,9 @@ public class RubikRememberedSolves
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getQuats(JSONObject object) throws JSONException
+  public JSONObject getObjectState(JSONObject object) throws JSONException
     {
-    JSONArray quats = object.getJSONArray("quats");
-    int len = quats.length();
-    int[] ret = new int[len];
-    for(int i=0; i<len; i++)  ret[i] = quats.getInt(i);
-    return ret;
+    return object.getJSONObject("objState");
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -240,12 +236,12 @@ public class RubikRememberedSolves
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void rememberSolve(Activity act, String objname, int level, int elapsed, Static4D rot, int[] quats)
+  public void rememberSolve(Activity act, String objname, int level, int elapsed, Static4D rot, TwistyObject object)
     {
     String filename  = objname.toLowerCase()+"_solves.json";
     RubikFiles files = RubikFiles.getInstance();
     InputStream input= files.openFile(act,filename);
-    String contents  = addInfo(input,level,elapsed,rot,quats);
+    String contents  = addInfo(input,level,elapsed,rot,object);
     File file        = new File(act.getFilesDir(), filename);
 
     try( FileOutputStream fos = new FileOutputStream(file) )
diff --git a/src/main/java/org/distorted/main/MainActivity.java b/src/main/java/org/distorted/main/MainActivity.java
index bbbbc3b1..9da09658 100644
--- a/src/main/java/org/distorted/main/MainActivity.java
+++ b/src/main/java/org/distorted/main/MainActivity.java
@@ -48,7 +48,8 @@ import org.distorted.patterns.PatternActivity;
 import org.distorted.play.PlayActivity;
 import org.distorted.solvers.SolverActivity;
 import org.distorted.tutorials.TutorialActivity;
-import org.json.JSONArray;
+
+import org.json.JSONObject;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -338,7 +339,7 @@ public class MainActivity extends BaseActivity implements RubikNetwork.Updatee,
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void switchToPlay(RubikObject object, int ordinal, int scrambles, int level, int elapsed, Static4D rot, int[] quats)
+    public void switchToPlay(RubikObject object, int ordinal, int scrambles, int level, int elapsed, Static4D rot, JSONObject objState)
       {
       boolean local = object.isLocal();
       String name = local ? object.getLowerName() : object.getUpperName();
@@ -353,14 +354,14 @@ public class MainActivity extends BaseActivity implements RubikNetwork.Updatee,
 
       if( rot!=null )
         {
-        intent.putExtra("rot0", rot.get0() );
-        intent.putExtra("rot1", rot.get1() );
-        intent.putExtra("rot2", rot.get2() );
-        intent.putExtra("rot3", rot.get3() );
+        intent.putExtra("r0", rot.get0() );
+        intent.putExtra("r1", rot.get1() );
+        intent.putExtra("r2", rot.get2() );
+        intent.putExtra("r3", rot.get3() );
         }
-      if( quats!=null )
+      if( objState!=null )
         {
-        intent.putExtra("quats", quats);
+        intent.putExtra("objstate", objState.toString() );
         }
 
       startActivity(intent);
diff --git a/src/main/java/org/distorted/main/MainObjectPopup.java b/src/main/java/org/distorted/main/MainObjectPopup.java
index 6e9a98ec..5b1b10a7 100644
--- a/src/main/java/org/distorted/main/MainObjectPopup.java
+++ b/src/main/java/org/distorted/main/MainObjectPopup.java
@@ -298,8 +298,8 @@ public class MainObjectPopup
                 {
                 JSONObject obj = json.getJSONObject(0);
                 Static4D rotQuat = solves.getRotQuat(obj);
-                int[] quats = solves.getQuats(obj);
-                act.switchToPlay(object,mObjectOrdinal,scrambles,ll,1,rotQuat,quats);
+                JSONObject objState = solves.getObjectState(obj);
+                act.switchToPlay(object,mObjectOrdinal,scrambles,ll,1,rotQuat,objState);
                 }
               catch(JSONException jex)
                 {
diff --git a/src/main/java/org/distorted/main/MainSolvesPopup.java b/src/main/java/org/distorted/main/MainSolvesPopup.java
index fa504678..f279ba42 100644
--- a/src/main/java/org/distorted/main/MainSolvesPopup.java
+++ b/src/main/java/org/distorted/main/MainSolvesPopup.java
@@ -90,8 +90,8 @@ public class MainSolvesPopup
         long time = solves.getTime(object);
         int elapsed = solves.getElapsed(object);
         Static4D rotQuat = solves.getRotQuat(object);
-        int[] quats = solves.getQuats(object);
-        View pane = createOldPane(act, time, elapsed, rotQuat, quats, pL, pT);
+        JSONObject objState = solves.getObjectState(object);
+        View pane = createOldPane(act, time, elapsed, rotQuat, objState, pL, pT);
         mLayout.addView(pane);
         }
       }
@@ -122,7 +122,7 @@ public class MainSolvesPopup
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private View createOldPane(MainActivity act, long time, int elapsed, Static4D rot, int[] quats,
+  private View createOldPane(MainActivity act, long time, int elapsed, Static4D rot, JSONObject objState,
                              LinearLayout.LayoutParams pView, LinearLayout.LayoutParams pText)
     {
     View view = act.getLayoutInflater().inflate(R.layout.dialog_solve_old_pane, null);
@@ -168,7 +168,7 @@ public class MainSolvesPopup
         public void onClick(View v)
           {
           mPopup.dismiss();
-          act.switchToPlay(mObject,mObjectOrdinal,mNumScrambles,mLevel, elapsed, rot, quats);
+          act.switchToPlay(mObject,mObjectOrdinal,mNumScrambles,mLevel, elapsed, rot, objState);
           }
         });
 
diff --git a/src/main/java/org/distorted/play/PlayActivity.java b/src/main/java/org/distorted/play/PlayActivity.java
index 18d49ab0..24c88e69 100644
--- a/src/main/java/org/distorted/play/PlayActivity.java
+++ b/src/main/java/org/distorted/play/PlayActivity.java
@@ -39,6 +39,8 @@ import org.distorted.main.R;
 import org.distorted.objects.RubikObject;
 import org.distorted.objects.RubikObjectList;
 import org.distorted.os.OSInterface;
+import org.json.JSONException;
+import org.json.JSONObject;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -55,7 +57,7 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
     private int mNumScrambles;
     private int mElapsed;
     private Static4D mRotQuat;
-    private int[] mQuats;
+    private JSONObject mObjectState;
     private boolean mObjectLocal, mModeResume;
     private int mObjectOrdinal;
     private int mLevel;
@@ -88,12 +90,21 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
 
         if( mElapsed>0 )
           {
-          float r0 = b.getFloat("rot0");
-          float r1 = b.getFloat("rot1");
-          float r2 = b.getFloat("rot2");
-          float r3 = b.getFloat("rot3");
+          float r0 = b.getFloat("r0");
+          float r1 = b.getFloat("r1");
+          float r2 = b.getFloat("r2");
+          float r3 = b.getFloat("r3");
           mRotQuat = new Static4D(r0,r1,r2,r3);
-          mQuats = b.getIntArray("quats");
+          String state = b.getString("objstate");
+
+          try
+            {
+            mObjectState = new JSONObject(state);
+            }
+          catch(JSONException jex)
+            {
+            android.util.Log.e("D", "PlayActivity: exception unpacking object state: "+jex.getMessage() );
+            }
           }
         }
       else
@@ -105,7 +116,7 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
         mObjectOrdinal = 0;
         mElapsed = 0;
         mRotQuat = null;
-        mQuats = null;
+        mObjectState = null;
         }
 
       mModeFree = (mLevel<0);
@@ -190,7 +201,7 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
 
         if( !mObjectName.isEmpty() )
           {
-          changeIfDifferent(mObjectName, mObjectLocal, mObjectOrdinal, control, mQuats);
+          changeIfDifferent(mObjectName, mObjectLocal, mObjectOrdinal, control, mObjectState);
           }
 
         control.setRotateOnCreation(false);
@@ -289,7 +300,7 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private void changeIfDifferent(String name, boolean local, int ordinal, ObjectControl control, int[] initQuats)
+    private void changeIfDifferent(String name, boolean local, int ordinal, ObjectControl control, JSONObject state)
       {
       if( local )
         {
@@ -297,7 +308,7 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
         int iconMode = TwistyObject.MODE_NORM;
         InputStream jsonStream = files.openFile(this, name+"_object.json");
         InitAssets asset = new InitAssets(jsonStream, null, null);
-        control.changeIfDifferent(ordinal, name, iconMode, asset, initQuats);
+        control.changeIfDifferent(ordinal, name, iconMode, asset, state);
         }
       else
         {
@@ -308,7 +319,7 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
         PlayView view = findViewById(R.id.playView);
         OSInterface os = view.getInterface();
         InitAssets asset = new InitAssets(jsonStream, meshStream, os);
-        control.changeIfDifferent(ordinal, name, iconMode, asset, initQuats);
+        control.changeIfDifferent(ordinal, name, iconMode, asset, state);
         }
       }
 
@@ -351,9 +362,6 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
 
       int level = mLevel==LEVELS_SHOWN ? mLevel : mLevel+1;
       String name = object.getShortName();
-      int numCubits = object.getNumCubits();
-      int[] quats = new int[numCubits];
-      for(int c=0; c<numCubits; c++) quats[c] = object.getCubitQuatIndex(c);
       Static4D rotQuat = control.getQuat();
       Activity act = this;
 
@@ -362,7 +370,7 @@ public class PlayActivity extends BaseActivity implements DialogScores.ScoresInv
         public void run()
           {
           RubikRememberedSolves solves = RubikRememberedSolves.getInstance();
-          solves.rememberSolve(act,name,level,time,rotQuat,quats);
+          solves.rememberSolve(act,name,level,time,rotQuat,object);
           }
         };
 
