commit 373fa45f4fda3af46335192c996f889b93f04eb2
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Apr 6 21:10:37 2020 +0100

    Progress making the Solver state more abstract.

diff --git a/src/main/java/org/distorted/solvers/ImplementedSolversList.java b/src/main/java/org/distorted/solvers/ImplementedSolversList.java
new file mode 100644
index 00000000..c631bd53
--- /dev/null
+++ b/src/main/java/org/distorted/solvers/ImplementedSolversList.java
@@ -0,0 +1,70 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2020 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Magic Cube.                                                              //
+//                                                                                               //
+// Magic Cube is free software: you can redistribute it and/or modify                            //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Magic Cube is distributed in the hope that it will be useful,                                 //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.solvers;
+
+import org.distorted.objects.RubikObjectList;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public enum ImplementedSolversList
+{
+  CUBE3 ( RubikObjectList.CUBE, 3),
+  ;
+
+  public static final int NUM_OBJECTS = values().length;
+
+  private final RubikObjectList mObject;
+  private final int mObjectSize;
+
+  private static final ImplementedSolversList[] objects;
+
+  static
+    {
+    objects = new ImplementedSolversList[NUM_OBJECTS];
+    int i=0;
+
+    for(ImplementedSolversList object: ImplementedSolversList.values())
+      {
+      objects[i++] = object;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static RubikObjectList getObject(int ordinal)
+    {
+    return objects[ordinal].mObject;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int getObjectSize(int ordinal)
+    {
+    return objects[ordinal].mObjectSize;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  ImplementedSolversList( RubikObjectList object, int size)
+    {
+    mObject     = object;
+    mObjectSize =  size;
+    }
+}
diff --git a/src/main/java/org/distorted/solvers/Solver.java b/src/main/java/org/distorted/solvers/Solver.java
index f85dbd62..2bc9ea52 100644
--- a/src/main/java/org/distorted/solvers/Solver.java
+++ b/src/main/java/org/distorted/solvers/Solver.java
@@ -22,7 +22,7 @@ package org.distorted.solvers;
 import android.content.res.Resources;
 
 import org.distorted.main.R;
-import org.distorted.main.RubikActivity;
+import org.distorted.objects.RubikObjectList;
 import org.distorted.states.RubikState;
 import org.distorted.states.RubikStateSolver;
 
@@ -31,64 +31,82 @@ import org.distorted.states.RubikStateSolver;
 public class Solver implements Runnable
 {
   private String mObjectPosition;
-  private RubikActivity mAct;
+  private Resources mRes;
+  private RubikObjectList mObject;
+  private int mSize;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public Solver(RubikActivity act, String position )
+  public Solver(Resources res, RubikObjectList object, int size, String position )
     {
+    mRes            = res;
+    mObject         = object;
+    mSize           = size;
     mObjectPosition = position;
-    mAct            = act;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void start()
+  private void solveCube3(RubikStateSolver solver)
     {
-    Thread thr = new Thread(this);
-    thr.start();
+    String result;
+
+    if( !org.distorted.solvers.cube3.Search.prepare(mRes) )
+      result= "Error 9";
+    else
+      result = org.distorted.solvers.cube3.Search.solution(mObjectPosition, 24, 20);
+
+    if (result.contains("Error"))
+      {
+      switch (result.charAt(result.length() - 1))
+        {
+        case '1': result = mRes.getString(R.string.solver_cube3_error1); break;
+        case '2': result = mRes.getString(R.string.solver_cube3_error2); break;
+        case '3': result = mRes.getString(R.string.solver_cube3_error3); break;
+        case '4': result = mRes.getString(R.string.solver_cube3_error4); break;
+        case '5': result = mRes.getString(R.string.solver_cube3_error5); break;
+        case '6': result = mRes.getString(R.string.solver_cube3_error6); break;
+        case '7': result = mRes.getString(R.string.solver_cube3_error7); break;
+        case '8': result = mRes.getString(R.string.solver_cube3_error8); break;
+        case '9': result = mRes.getString(R.string.solver_cube3_error9); break;
+        }
+
+      solver.displayErrorDialog(result);
+      }
+    else
+      {
+      solver.setSolved(result);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void interrupt()
+  private void interruptCube3()
     {
     org.distorted.solvers.cube3.Search.interrupt();
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void start()
+    {
+    Thread thr = new Thread(this);
+    thr.start();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void run()
     {
-    Resources res = mAct.getResources();
     RubikStateSolver solver = (RubikStateSolver) RubikState.SVER.getStateClass();
-    String result;
 
-    if( !org.distorted.solvers.cube3.Search.prepare(res) )
-      result= "Error 9";
-    else
-      result = org.distorted.solvers.cube3.Search.solution(mObjectPosition, 24, 20);
-
-    if (result.contains("Error"))
+    if( mObject == RubikObjectList.CUBE && mSize == 3)
       {
-      switch (result.charAt(result.length() - 1))
-        {
-        case '1': result = res.getString(R.string.error1); break;
-        case '2': result = res.getString(R.string.error2); break;
-        case '3': result = res.getString(R.string.error3); break;
-        case '4': result = res.getString(R.string.error4); break;
-        case '5': result = res.getString(R.string.error5); break;
-        case '6': result = res.getString(R.string.error6); break;
-        case '7': result = res.getString(R.string.error7); break;
-        case '8': result = res.getString(R.string.error8); break;
-        case '9': result = res.getString(R.string.error9); break;
-        }
-
-      solver.displayErrorDialog(mAct,result);
+      solveCube3(solver);
       }
     else
       {
-      solver.setSolved( mAct, org.distorted.solvers.cube3.Search.numMoves(), result);
+      solver.displayErrorDialog(mRes.getString(R.string.solver_generic_error1));
       }
     }
 }  
diff --git a/src/main/java/org/distorted/states/RubikStateSolution.java b/src/main/java/org/distorted/states/RubikStateSolution.java
index 98b3398c..3ef67ff0 100644
--- a/src/main/java/org/distorted/states/RubikStateSolution.java
+++ b/src/main/java/org/distorted/states/RubikStateSolution.java
@@ -250,16 +250,14 @@ public class RubikStateSolution extends RubikStateAbstract implements RubikPostR
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  void setupMoves(final RubikActivity act, int numMoves, String moves)
+  void setupMoves(final RubikActivity act, String moves)
     {
-    android.util.Log.e("solution", "got "+numMoves+" moves: "+moves);
-
     mCanRotate= true;
     mCurrMove = 0;
-    mNumMoves = numMoves;
+    mNumMoves = moves.length()/4;
     mMoves    = new int[mNumMoves][3];
 
-    RubikPattern.parseMoves(mMoves,numMoves,moves);
+    RubikPattern.parseMoves(mMoves,mNumMoves,moves);
 
     mMovesText.setText(act.getString(R.string.mo_placeholder,mCurrMove,mNumMoves));
     }
diff --git a/src/main/java/org/distorted/states/RubikStateSolver.java b/src/main/java/org/distorted/states/RubikStateSolver.java
index 6bce5147..fc892021 100644
--- a/src/main/java/org/distorted/states/RubikStateSolver.java
+++ b/src/main/java/org/distorted/states/RubikStateSolver.java
@@ -39,17 +39,17 @@ import org.distorted.main.RubikActivity;
 import org.distorted.main.RubikPostRender;
 import org.distorted.objects.RubikObject;
 import org.distorted.objects.RubikObjectList;
+import org.distorted.solvers.ImplementedSolversList;
 import org.distorted.solvers.Solver;
 
+import java.lang.ref.WeakReference;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class RubikStateSolver extends RubikStateAbstract
   {
   private static final int BITMAP_SIZE = 35;
 
-  private static final RubikObjectList OBJECT = RubikObjectList.CUBE;
-  private static final int             SIZE   = 3;
-
   private static Bitmap[] mBitmap;
   private ImageButton[] mColorButton;
   private Button mBackButton, mSolveButton;
@@ -58,6 +58,11 @@ public class RubikStateSolver extends RubikStateAbstract
   private int[] mFaceColors;
   private int mNumFaces;
 
+  private RubikObjectList mCurrentObject;
+  private int mCurrentObjectSize;
+
+  private WeakReference<RubikActivity> mWeakAct;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   void leaveState(RubikActivity act)
@@ -69,13 +74,18 @@ public class RubikStateSolver extends RubikStateAbstract
 
   void enterState(final RubikActivity act)
     {
+    mWeakAct = new WeakReference<>(act);
+
     mSolving = false;
 
-    act.changeObject(OBJECT,SIZE,null);
+    mCurrentObject     = ImplementedSolversList.getObject(0);
+    mCurrentObjectSize = ImplementedSolversList.getObjectSize(0);
+
+    act.changeObject(mCurrentObject, mCurrentObjectSize, null);
     RubikStatePlay play = (RubikStatePlay)RubikState.PLAY.getStateClass();
-    play.setObjectAndSize(OBJECT,SIZE);
+    play.setObjectAndSize(mCurrentObject, mCurrentObjectSize);
 
-    mFaceColors = RubikObjectList.retFaceColors(OBJECT);
+    mFaceColors = RubikObjectList.retFaceColors(mCurrentObject);
     mNumFaces   = mFaceColors!=null ? mFaceColors.length : 0;
 
     DisplayMetrics metrics = act.getResources().getDisplayMetrics();
@@ -189,7 +199,7 @@ public class RubikStateSolver extends RubikStateAbstract
           mSolving = true;
           RubikObject object = act.getObject();
           String objectString = object.retObjectString();
-          Solver solver = new Solver( act, objectString );
+          Solver solver = new Solver( act.getResources(), mCurrentObject, mCurrentObjectSize, objectString );
           solver.start();
           }
         }
@@ -265,32 +275,40 @@ public class RubikStateSolver extends RubikStateAbstract
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void setSolved( final RubikActivity act, final int numMoves, final String moves)
+  public void setSolved(final String moves)
     {
     mSolving = false;
+    final RubikActivity act = mWeakAct.get();
 
-    act.runOnUiThread(new Runnable()
+    if( act!=null )
       {
-      @Override
-      public void run()
+      act.runOnUiThread(new Runnable()
         {
-        RubikState.switchState(act,RubikState.SOLU);
-        RubikStateSolution solution = (RubikStateSolution) RubikState.SOLU.getStateClass();
-        solution.setupMoves(act, numMoves, moves);
-        }
-      });
+        @Override
+        public void run()
+          {
+          RubikState.switchState(act,RubikState.SOLU);
+          RubikStateSolution solution = (RubikStateSolution) RubikState.SOLU.getStateClass();
+          solution.setupMoves(act, moves);
+          }
+        });
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void displayErrorDialog( final RubikActivity act, String message)
+  public void displayErrorDialog( String message)
     {
     mSolving = false;
+    RubikActivity act = mWeakAct.get();
 
-    RubikDialogSolverError dialog = new RubikDialogSolverError();
-    Bundle bundle = new Bundle();
-    bundle.putString("error", message );
-    dialog.setArguments(bundle);
-    dialog.show( act.getSupportFragmentManager(), null);
+    if( act!=null )
+      {
+      RubikDialogSolverError dialog = new RubikDialogSolverError();
+      Bundle bundle = new Bundle();
+      bundle.putString("error", message );
+      dialog.setArguments(bundle);
+      dialog.show( act.getSupportFragmentManager(), null);
+      }
     }
   }
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 6e279fa8..203bfb7c 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -39,15 +39,17 @@
     <string name="credits1">Open Source app developed using the Distorted graphics library. Licensed under GPL version 2 or - at your option - any later version.</string>
     <string name="credits2">Download code, take a look at tutorials, learn how to add your own graphics effect, learn how to code your own object, contribute a Pretty Pattern, implement your own solver, or report a bug: \n\n<a href="https://distorted.org/redmine/projects/magic-cube/wiki">Distorted.org</a></string>
 
-    <string name="error1">There are not exactly 9 facelets of each color!</string>
-    <string name="error2">Not all 12 edges exist exactly once!</string>
-    <string name="error3">One edge has to be flipped!</string>
-    <string name="error4">Not all 8 corners exist exactly once!</string>
-    <string name="error5">One corner has to be twisted!</string>
-    <string name="error6">Two corners or two edges have to be exchanged!</string>
-    <string name="error7">No solution exists for the given maximum move number!</string>
-    <string name="error8">Timeout, no solution found in 20 seconds!</string>
-    <string name="error9">Solver interrupted!</string>
+    <string name="solver_generic_error1">Solver for this object and size not implemented yet!</string>
+
+    <string name="solver_cube3_error1">There are not exactly 9 facelets of each color!</string>
+    <string name="solver_cube3_error2">Not all 12 edges exist exactly once!</string>
+    <string name="solver_cube3_error3">One edge has to be flipped!</string>
+    <string name="solver_cube3_error4">Not all 8 corners exist exactly once!</string>
+    <string name="solver_cube3_error5">One corner has to be twisted!</string>
+    <string name="solver_cube3_error6">Two corners or two edges have to be exchanged!</string>
+    <string name="solver_cube3_error7">No solution exists for the given maximum move number!</string>
+    <string name="solver_cube3_error8">Timeout, no solution found in 20 seconds!</string>
+    <string name="solver_cube3_error9">Solver interrupted!</string>
 
     <string name="ms_placeholder">%1$d ms</string>
     <string name="sc_placeholder">Scramble %1$d</string>
