Project

General

Profile

« Previous | Next » 

Revision 2f53a016

Added by Leszek Koltunski 1 day ago

Integration of the Algorithmic solvers into the App.

View differences:

src/main/java/org/distorted/dialogs/RubikDialogSolverView.java
9 9

  
10 10
package org.distorted.dialogs;
11 11

  
12
import android.content.res.Resources;
12 13
import android.util.TypedValue;
13 14
import android.view.View;
14 15
import android.widget.Button;
......
16 17
import android.widget.TextView;
17 18

  
18 19
import org.distorted.main.R;
20
import org.distorted.objectlib.helpers.OperatingSystemInterface;
19 21
import org.distorted.objectlib.main.TwistyObject;
20 22
import org.distorted.solvers.SolvingList;
21 23
import org.distorted.solvers.SolvingThread;
......
53 55
        {
54 56
        dialog.dismiss();
55 57
        SolvingList list = SolvingList.getSolver(solverOrdinal);
58
        OperatingSystemInterface os = act.getInterface();
59
        Resources res = act.getResources();
56 60
        TwistyObject object = act.getObject();
57
        SolvingThread solver = new SolvingThread( act.getInterface(), act.getResources(), object, list );
61
        SolvingThread solver = new SolvingThread( os,res,object,list );
58 62
        solver.start();
59 63
        }
60 64
      });
src/main/java/org/distorted/solvers/SolverAlgorithmic.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2024 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

  
10
package org.distorted.solvers;
11

  
12
import android.content.res.Resources;
13

  
14
import org.distorted.objectlib.algsolvers.SolutionListener;
15
import org.distorted.objectlib.algsolvers.SolvedObject;
16
import org.distorted.objectlib.algsolvers.implemented.PhasedSolver3x3Beginner;
17
import org.distorted.objectlib.algsolvers.implemented.PhasedSolverAbstract;
18
import org.distorted.objectlib.helpers.OperatingSystemInterface;
19
import org.distorted.objectlib.main.TwistyObject;
20
import org.distorted.solverui.ScreenList;
21
import org.distorted.solverui.ScreenPhasedSolution;
22
import org.distorted.solverui.ScreenSolver;
23

  
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25

  
26
public abstract class SolverAlgorithmic implements SolvingInterface, SolutionListener
27
{
28
  private final SolvedObject mSolvedObject;
29
  private final PhasedSolverAbstract mSolver;
30
  private final OperatingSystemInterface mOS;
31
  private final Resources mRes;
32
  private final TwistyObject mObject;
33
  private long mTime;
34
  private ScreenSolver mScreen;
35

  
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37
// PUBLIC API
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

  
40
  public SolverAlgorithmic(OperatingSystemInterface os, Resources res, TwistyObject object)
41
    {
42
    mOS     = os;
43
    mRes    = res;
44
    mObject = object;
45
    mSolver = new PhasedSolver3x3Beginner();
46
    mSolvedObject = mSolver.getObject();
47
    }
48

  
49
///////////////////////////////////////////////////////////////////////////////////////////////////
50

  
51
  abstract int[] validatePosition(TwistyObject object);
52
  abstract String getError(Resources res);
53

  
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

  
56
  public void solve(ScreenSolver screen)
57
    {
58
    mScreen = screen;
59
    int[] quats = validatePosition(mObject);
60

  
61
    if( quats!=null )
62
      {
63
      int numPhases = mSolver.getNumPhases();
64
      String[] names = new String[numPhases];
65
      for(int p=0; p<numPhases; p++) names[p] = mSolver.getPhaseName(p);
66
      ScreenPhasedSolution solScreen = (ScreenPhasedSolution) ScreenList.PHAS.getScreenClass();
67
      solScreen.updateNames(names);
68
      mTime = System.currentTimeMillis();
69
      mSolver.solution(this,quats);
70
      }
71
    else
72
      {
73
      String error = getError(mRes);
74
      screen.displayImpossibleDialog(error);
75
      }
76
    }
77

  
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

  
80
  public void receiveSolution(int[] solution, int phaseNumber)
81
    {
82
    if( solution==null )
83
      {
84
      String message = "Phase "+phaseNumber+": FAIL";
85
      System.out.println(message);
86
      }
87
    else
88
      {
89
      int numMoves = solution[0];
90
      int[][] moves = new int[numMoves][];
91
      int index = 0;
92

  
93
      for(int m=1; m<=numMoves; m++)
94
        moves[index++] = mSolvedObject.findMove(solution[m]);
95

  
96
      int[][] subphases = mSolver.getSubPhases(phaseNumber);
97
      mScreen.setSolved(moves,phaseNumber,subphases);
98
      }
99

  
100
    long time = System.currentTimeMillis();
101
    long diff = time - mTime;
102
    mTime = time;
103

  
104
    System.out.println("Phase "+phaseNumber+" solved in "+diff+"ms. Moves: "+(solution==null ? 0:solution[0]));
105
    }
106
}  
107

  
src/main/java/org/distorted/solvers/SolverAlgorithmicCUBE3.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2024 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

  
10
package org.distorted.solvers;
11

  
12
import android.content.res.Resources;
13

  
14
import org.distorted.objectlib.helpers.OperatingSystemInterface;
15
import org.distorted.objectlib.main.TwistyObject;
16
import org.distorted.solverui.SolverActivity;
17

  
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
public class SolverAlgorithmicCUBE3 extends SolverAlgorithmic
21
{
22
  public SolverAlgorithmicCUBE3(OperatingSystemInterface os, Resources res, TwistyObject object)
23
    {
24
    super(os,res,object);
25
    }
26

  
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28

  
29
  int[] validatePosition(TwistyObject object)
30
    {
31
    int numCubits = object.getNumCubits();
32
    int[] ret = new int[numCubits];   // mockup
33
    return ret;
34
    }
35

  
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

  
38
  String getError(Resources res)
39
    {
40
    return null;
41
    }
42
}  
43

  
src/main/java/org/distorted/solvers/SolvingList.java
25 25

  
26 26
public enum SolvingList
27 27
{
28
  CUBE2          (CUBE_2.ordinal(), SolverTablebaseCUBE2.class, R.string.solver_cube2_title, R.string.solver_cube2_description, true),
29
  CUBE3_KOCIEMBA (CUBE_3.ordinal(), SolverKociembaCUBE3.class , R.string.solver_cube3_title, R.string.solver_cube3_description, true),
30
  CUBE3_FAKE     (CUBE_3.ordinal(), SolverKociembaCUBE3.class , R.string.solver_cube3_title, R.string.solver_cube3_description, true),
31

  
32
  CU232          (CU_232.ordinal(), SolverTablebaseCU232.class, R.string.solver_cu232_title, R.string.solver_cu232_description, true),
33
  CU323          (CU_323.ordinal(), SolverTablebaseCU323.class, R.string.solver_cu323_title, R.string.solver_cu323_description, true),
34
  PYRAMINX       (PYRA_3.ordinal(), SolverTablebasePYRA3.class, R.string.solver_pyra3_title, R.string.solver_pyra3_description, true),
35
  SKEWB          (SKEW_2.ordinal(), SolverTablebaseSKEW2.class, R.string.solver_skew2_title, R.string.solver_skew2_description, true),
36
  PYRAMINX_DUO   (PDUO_2.ordinal(), SolverTablebasePDUO2.class, R.string.solver_pduo2_title, R.string.solver_pduo2_description, true),
37
  IVY            (IVY_2.ordinal() , SolverTablebaseIVY2.class , R.string.solver_ivy_title, R.string.solver_ivy_description, true),
38
  DIAMOND        (DIAM_2.ordinal(), SolverTablebaseDIAM2.class, R.string.solver_diam2_title, R.string.solver_diam2_description, true),
39
  JING2          (JING_2.ordinal(), SolverTablebaseJING2.class, R.string.solver_jing2_title, R.string.solver_jing2_description, true),
40
  DINO6          (DINO_3.ordinal(), SolverTablebaseDINO6.class, R.string.solver_dino6_title, R.string.solver_dino6_description, true),
41
  DINO4          (DIN4_3.ordinal(), SolverTablebaseDINO4.class, R.string.solver_dino4_title, R.string.solver_dino4_description, true),
42
  PDIA           (PDIA_3.ordinal(), SolverTablebasePDIA3.class, R.string.solver_pdia_title, R.string.solver_pdia_description, true),
28
  CUBE2          (CUBE_2.ordinal(), SolverTablebaseCUBE2.class  , R.string.solver_cube2_title, R.string.solver_cube2_description, true),
29
  CUBE3_KOCIEMBA (CUBE_3.ordinal(), SolverKociembaCUBE3.class   , R.string.solver_cube3_title, R.string.solver_cube3_description, true),
30
  CUBE3_ALGO     (CUBE_3.ordinal(), SolverAlgorithmicCUBE3.class, R.string.solver_3algo_title, R.string.solver_3algo_description, true),
31
  CU232          (CU_232.ordinal(), SolverTablebaseCU232.class  , R.string.solver_cu232_title, R.string.solver_cu232_description, true),
32
  CU323          (CU_323.ordinal(), SolverTablebaseCU323.class  , R.string.solver_cu323_title, R.string.solver_cu323_description, true),
33
  PYRAMINX       (PYRA_3.ordinal(), SolverTablebasePYRA3.class  , R.string.solver_pyra3_title, R.string.solver_pyra3_description, true),
34
  SKEWB          (SKEW_2.ordinal(), SolverTablebaseSKEW2.class  , R.string.solver_skew2_title, R.string.solver_skew2_description, true),
35
  PYRAMINX_DUO   (PDUO_2.ordinal(), SolverTablebasePDUO2.class  , R.string.solver_pduo2_title, R.string.solver_pduo2_description, true),
36
  IVY            (IVY_2.ordinal() , SolverTablebaseIVY2.class   , R.string.solver_ivy_title, R.string.solver_ivy_description, true),
37
  DIAMOND        (DIAM_2.ordinal(), SolverTablebaseDIAM2.class  , R.string.solver_diam2_title, R.string.solver_diam2_description, true),
38
  JING2          (JING_2.ordinal(), SolverTablebaseJING2.class  , R.string.solver_jing2_title, R.string.solver_jing2_description, true),
39
  DINO6          (DINO_3.ordinal(), SolverTablebaseDINO6.class  , R.string.solver_dino6_title, R.string.solver_dino6_description, true),
40
  DINO4          (DIN4_3.ordinal(), SolverTablebaseDINO4.class  , R.string.solver_dino4_title, R.string.solver_dino4_description, true),
41
  PDIA           (PDIA_3.ordinal(), SolverTablebasePDIA3.class  , R.string.solver_pdia_title, R.string.solver_pdia_description, true),
43 42
  ;
44 43

  
45 44
  public static final int NUM_OBJECTS = values().length;
src/main/java/org/distorted/solverui/ScreenList.java
18 18

  
19 19
public enum ScreenList
20 20
  {
21
  SVER ( null , MODE_REPLACE, new ScreenSolver()   ),
22
  SOLU ( SVER , MODE_DRAG   , new ScreenSolution() ),
21
  SVER ( null , MODE_REPLACE, new ScreenSolver()         ),
22
  SOLU ( SVER , MODE_DRAG   , new ScreenSolution()       ),
23
  PHAS ( SVER , MODE_DRAG   , new ScreenPhasedSolution() ),
23 24
  ;
24 25

  
25 26
  public static final int LENGTH = values().length;
src/main/java/org/distorted/solverui/ScreenPhasedSolution.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2024 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

  
10
package org.distorted.solverui;
11

  
12
import android.content.SharedPreferences;
13
import android.util.TypedValue;
14
import android.view.Gravity;
15
import android.view.View;
16
import android.widget.LinearLayout;
17
import android.widget.TextView;
18

  
19
import org.distorted.helpers.TransparentImageButton;
20
import org.distorted.library.effect.PostprocessEffectGlow;
21
import org.distorted.library.main.DistortedEffects;
22
import org.distorted.library.mesh.MeshBase;
23
import org.distorted.library.message.EffectListener;
24
import org.distorted.library.type.Dynamic2D;
25
import org.distorted.library.type.Dynamic4D;
26
import org.distorted.library.type.Static2D;
27
import org.distorted.library.type.Static4D;
28
import org.distorted.main.R;
29
import org.distorted.objectlib.helpers.MovesFinished;
30
import org.distorted.objectlib.main.ObjectControl;
31
import org.distorted.objectlib.main.TwistyObject;
32

  
33
import java.lang.ref.WeakReference;
34

  
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

  
37
public class ScreenPhasedSolution extends ScreenAbstract implements MovesFinished, EffectListener
38
  {
39
  private static final int MOVES_PLACE_0 = 100;
40
  private static final int MOVES_PLACE_1 = 101;
41
  private static final int FLASH_TIME = 1200;
42
  private static final int MILLIS_PER_DEGREE = 6;
43

  
44
  private WeakReference<SolverActivity> mAct;
45
  private TransparentImageButton mPrevButton, mNextButton, mBackButton, mPrevPhase, mNextPhase;
46
  private float mButtonSize;
47

  
48
  private TextView mMovesText, mMovesPhase;
49
  private String[] mPhaseNames;
50
  private int mNumPhases;
51
  private int[][][] mMoves;
52
  private int[][] mCubitsNotInvolved;
53
  private int mNumMoves,mCurrMove,mCurrPhase;
54
  private boolean mCanMove;
55

  
56
  private Dynamic2D mHaloAndRadiusDyn;
57
  private Dynamic4D mColorDyn;
58
  private PostprocessEffectGlow mGlow;
59
  private boolean mEffectWorking;
60

  
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

  
63
  void leaveScreen(SolverActivity act)
64
    {
65
    ObjectControl control = act.getControl();
66
    control.solveOnly();
67
    }
68

  
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

  
71
  void enterScreen(final SolverActivity act)
72
    {
73
    mAct = new WeakReference<>(act);
74

  
75
    mHaloAndRadiusDyn = new Dynamic2D(FLASH_TIME,1.0f);
76
    mHaloAndRadiusDyn.add(new Static2D( 0,0));
77
    mHaloAndRadiusDyn.add(new Static2D(10,5));
78

  
79
    mColorDyn = new Dynamic4D(FLASH_TIME,1.0f);
80

  
81
    final int[] colors  = new int[] {1,1,1}; // white
82

  
83
    Static4D P1 = new Static4D(colors[0],colors[1],colors[2], 0.0f);
84
    Static4D P2 = new Static4D(colors[0],colors[1],colors[2], 1.0f);
85
    mColorDyn.add(P1);
86
    mColorDyn.add(P2);
87

  
88
    mGlow = new PostprocessEffectGlow(mHaloAndRadiusDyn,mColorDyn);
89

  
90
    float width = act.getScreenWidthInPixels();
91
    mButtonSize = width*SolverActivity.BUTTON_TEXT_SIZE;
92

  
93
    // TOP ////////////////////////////
94
    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
95
    layoutTop.removeAllViews();
96

  
97
    setupPrevPhase(act);
98
    setupNextPhase(act);
99
    setupTextPhase(act,width);
100

  
101
    layoutTop.addView(mPrevPhase);
102
    layoutTop.addView(mMovesPhase);
103
    layoutTop.addView(mNextPhase);
104

  
105
    // BOT ////////////////////////////
106
    LinearLayout layoutBot = act.findViewById(R.id.lowerBar);
107
    layoutBot.removeAllViews();
108

  
109
    LinearLayout.LayoutParams paramsL = new LinearLayout.LayoutParams((int)(width/2),LinearLayout.LayoutParams.MATCH_PARENT);
110
    LinearLayout.LayoutParams paramsM = new LinearLayout.LayoutParams((int)(width/6),LinearLayout.LayoutParams.MATCH_PARENT);
111
    LinearLayout.LayoutParams paramsR = new LinearLayout.LayoutParams((int)(width/3),LinearLayout.LayoutParams.MATCH_PARENT);
112

  
113
    LinearLayout layoutLeft = new LinearLayout(act);
114
    layoutLeft.setLayoutParams(paramsL);
115
    LinearLayout layoutMid = new LinearLayout(act);
116
    layoutMid.setLayoutParams(paramsM);
117
    LinearLayout layoutRight = new LinearLayout(act);
118
    layoutRight.setLayoutParams(paramsR);
119

  
120
    setupPrevButton(act);
121
    setupNextButton(act);
122
    setupTextView(act,width);
123

  
124
    layoutLeft.addView(mPrevButton);
125
    layoutLeft.addView(mMovesText);
126
    layoutLeft.addView(mNextButton);
127

  
128
    setupBackButton(act);
129

  
130
    layoutRight.addView(mBackButton);
131

  
132
    layoutBot.addView(layoutLeft);
133
    layoutBot.addView(layoutMid);
134
    layoutBot.addView(layoutRight);
135
    }
136

  
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

  
139
  private void setupPrevButton(final SolverActivity act)
140
    {
141
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
142
    mPrevButton = new TransparentImageButton(act,R.drawable.ui_left,params);
143

  
144
    mPrevButton.setOnClickListener( new View.OnClickListener()
145
      {
146
      @Override public void onClick(View v) { backMove(); }
147
      });
148
    }
149

  
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

  
152
  private void setupNextButton(final SolverActivity act)
153
    {
154
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
155
    mNextButton = new TransparentImageButton(act,R.drawable.ui_right,params);
156

  
157
    mNextButton.setOnClickListener( new View.OnClickListener()
158
      {
159
      @Override public void onClick(View v) { nextMove(); }
160
      });
161
    }
162

  
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

  
165
  private void setupTextView(final SolverActivity act, final float width)
166
    {
167
    int padding = (int)(width*SolverActivity.PADDING);
168
    int margin  = (int)(width*SolverActivity.SMALL_MARGIN);
169
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,2.0f);
170
    params.topMargin    = margin;
171
    params.bottomMargin = margin;
172
    params.leftMargin   = margin;
173
    params.rightMargin  = margin;
174

  
175
    mMovesText = new TextView(act);
176
    mMovesText.setTextSize(20);
177
    mMovesText.setLayoutParams(params);
178
    mMovesText.setPadding(padding,0,padding,0);
179
    mMovesText.setGravity(Gravity.CENTER);
180
    mMovesText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mButtonSize);
181
    mMovesText.setText(act.getString(R.string.mo_placeholder,mCurrMove,mNumMoves));
182
    }
183

  
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

  
186
  private void setupPrevPhase(final SolverActivity act)
187
    {
188
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
189
    mPrevPhase = new TransparentImageButton(act,R.drawable.ui_left,params);
190

  
191
    mPrevPhase.setOnClickListener( new View.OnClickListener()
192
      {
193
      @Override public void onClick(View v) { backPhase(); }
194
      });
195
    }
196

  
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

  
199
  private void setupNextPhase(final SolverActivity act)
200
    {
201
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
202
    mNextPhase = new TransparentImageButton(act,R.drawable.ui_right,params);
203

  
204
    mNextPhase.setOnClickListener( new View.OnClickListener()
205
      {
206
      @Override public void onClick(View v) { nextPhase(); }
207
      });
208
    }
209

  
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

  
212
  private void setupTextPhase(final SolverActivity act, final float width)
213
    {
214
    int padding = (int)(width*SolverActivity.PADDING);
215
    int margin  = (int)(width*SolverActivity.SMALL_MARGIN);
216
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,2.0f);
217
    params.topMargin    = margin;
218
    params.bottomMargin = margin;
219
    params.leftMargin   = margin;
220
    params.rightMargin  = margin;
221

  
222
    mMovesPhase = new TextView(act);
223
    mMovesPhase.setTextSize(20);
224
    mMovesPhase.setLayoutParams(params);
225
    mMovesPhase.setPadding(padding,0,padding,0);
226
    mMovesPhase.setGravity(Gravity.CENTER);
227
    mMovesPhase.setTextSize(TypedValue.COMPLEX_UNIT_PX, mButtonSize);
228
    mMovesPhase.setText(act.getString(R.string.mo_placeholder,mCurrMove,mNumMoves));
229
    }
230

  
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

  
233
  private void setupBackButton(final SolverActivity act)
234
    {
235
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
236
    mBackButton = new TransparentImageButton(act,R.drawable.ui_back,params);
237

  
238
    mBackButton.setOnClickListener( new View.OnClickListener()
239
      {
240
      @Override
241
      public void onClick(View v)
242
        {
243
        ScreenList.goBack(act);
244
        }
245
      });
246
    }
247

  
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

  
250
  public void savePreferences(SharedPreferences.Editor editor) { }
251
  public void restorePreferences(SharedPreferences preferences) { }
252

  
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

  
255
  void backPhase()
256
    {
257
    SolverActivity act = mAct.get();
258
    ObjectControl control = act.getControl();
259

  
260
    if( mCurrMove>0 )
261
      {
262
      int[][] moves = transformMoves(mMoves[mCurrPhase],0,mCurrMove, false);
263
      control.applyScrambles(moves);
264
      mCurrMove = 0;
265
      }
266
    else if( mCurrPhase>0 )
267
      {
268
      mCurrPhase--;
269
      mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
270
      mCurrMove = 0;
271
      int[][] moves = transformMoves(mMoves[mCurrPhase],0,mNumMoves, false);
272
      control.applyScrambles(moves);
273
      }
274
    else
275
      {
276
      mCurrPhase = mNumPhases-1;
277
      mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
278
      mCurrMove = mNumMoves;
279
      int[][] moves = transformMoves(mMoves, true);
280
      control.applyScrambles(moves);
281
      }
282

  
283
    setText(act);
284
    }
285

  
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287

  
288
  void nextPhase()
289
    {
290
    SolverActivity act = mAct.get();
291
    ObjectControl control = act.getControl();
292

  
293
    if( mCurrPhase<mNumPhases-1 )
294
      {
295
      glowCubits(mCubitsNotInvolved[mCurrPhase]);
296
      int[][] moves = transformMoves(mMoves[mCurrPhase],mCurrMove,mNumMoves, true);
297
      control.applyScrambles(moves);
298
      mCurrPhase++;
299
      mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
300
      mCurrMove = 0;
301
      }
302
    else if( mCurrMove<mNumMoves )
303
      {
304
      glowCubits(mCubitsNotInvolved[mCurrPhase]);
305
      int[][] moves = transformMoves(mMoves[mCurrPhase],mCurrMove,mNumMoves, true);
306
      control.applyScrambles(moves);
307
      mCurrMove = mNumMoves;
308
      }
309
    else
310
      {
311
      mCurrPhase = 0;
312
      mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
313
      mCurrMove = 0;
314
      int[][] moves = transformMoves(mMoves, false);
315
      control.applyScrambles(moves);
316
      }
317

  
318
    setText(act);
319
    }
320

  
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

  
323
  private void setText(SolverActivity act)
324
    {
325
    int currMove = 0;
326
    int totalMove = 0;
327

  
328
    if( mMoves!=null )
329
      {
330
      currMove = mCurrMove;
331
      for(int p=0; p<mCurrPhase; p++) currMove  += (mMoves[p]==null ? 0: mMoves[p].length);
332
      for(int p=0; p<mNumPhases; p++) totalMove += (mMoves[p]==null ? 0: mMoves[p].length);
333
      }
334

  
335
    final int cMove = currMove;
336
    final int tMove = totalMove;
337

  
338
    act.runOnUiThread(new Runnable()
339
      {
340
      @Override
341
      public void run()
342
        {
343
        mMovesPhase.setText(mPhaseNames[mCurrPhase]+" "+mCurrMove+"/"+mNumMoves);
344
        mMovesText.setText(cMove+"/"+tMove);
345
        }
346
      });
347
    }
348

  
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350

  
351
  private int[][] transformMoves(int[][] moves, int start, int end, boolean front)
352
    {
353
    int mult = front ? 1:-1;
354
    int len = end-start;
355
    int[][] ret = new int[len][];
356

  
357
    for(int m=0; m<len; m++)
358
      {
359
      int[] mv = moves[front ? start+m : end-1-m];
360
      int[] rt = new int[3];
361
      rt[0] = mv[0];
362
      rt[1] = (1<<mv[1]);
363
      rt[2] = mult*mv[2];
364
      ret[m] = rt;
365
      }
366

  
367
    return ret;
368
    }
369

  
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

  
372
  private int[][] transformMoves(int[][][] moves, boolean front)
373
    {
374
    int len = moves.length;
375
    int totalLen = 0;
376
    for (int[][] move : moves) totalLen += (move==null ? 0 : move.length);
377

  
378
    int[][] ret = new int[totalLen][];
379
    int mult = front ? 1:-1;
380
    int index = 0;
381

  
382
    for(int m=0; m<len; m++)
383
      {
384
      int[][] mv = moves[front ? m : len-1-m];
385
      int l = (mv==null ? 0 : mv.length);
386

  
387
      for(int p=0; p<l; p++)
388
        {
389
        int[] mve = mv[front ? p : l-1-p];
390
        int[] rt = new int[3];
391
        rt[0] = mve[0];
392
        rt[1] = (1<<mve[1]);
393
        rt[2] = mult*mve[2];
394
        ret[index++] = rt;
395
        }
396
      }
397

  
398
    return ret;
399
    }
400

  
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

  
403
  private void glowCubits(int[] cubits)
404
    {
405
    if( !mEffectWorking )
406
      {
407
      mEffectWorking = true;
408
      SolverActivity act=mAct.get();
409
      ObjectControl control = act.getControl();
410
      TwistyObject object=control.getObject();
411
      DistortedEffects effects=object.getObjectEffects();
412
      effects.apply(mGlow);
413

  
414
      MeshBase mesh=object.getObjectMesh();
415
      mesh.setComponentsNotAffectedByPostprocessing(cubits);
416

  
417
      mHaloAndRadiusDyn.resetToBeginning();
418
      mColorDyn.resetToBeginning();
419
      mGlow.notifyWhenFinished(this);
420
      }
421
    }
422

  
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

  
425
  private int[] computeCubitsNotInvolved(int[][] subphases, int numCubits)
426
    {
427
    int numCubitsInvolved = 0;
428
    boolean[] involved = new boolean[numCubits];
429

  
430
    for(int[] sub : subphases)
431
      if( sub!=null )
432
        for(int s : sub)
433
          {
434
          numCubitsInvolved++;
435
          involved[s] = true;
436
          }
437

  
438
    int[] ret = new int[numCubits-numCubitsInvolved];
439
    int index = 0;
440

  
441
    for(int c=0; c<numCubits; c++)
442
      if( !involved[c] ) ret[index++] = c;
443

  
444
    return ret;
445
    }
446

  
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

  
449
  void backMove()
450
    {
451
    if( mMoves!=null && mCanMove )
452
      {
453
      SolverActivity act=mAct.get();
454

  
455
      if( mCurrMove>0 )
456
        {
457
        mCanMove = false;
458
        int[] move = mMoves[mCurrPhase][--mCurrMove];
459
        ObjectControl control = act.getControl();
460
        control.blockTouch(MOVES_PLACE_0);
461
        control.addRotation(this, move[0], (1<<move[1]), -move[2], MILLIS_PER_DEGREE);
462
        }
463
      else if( mCurrPhase>0 )
464
        {
465
        mCurrPhase--;
466
        mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
467
        mCurrMove = mNumMoves;
468
        glowCubits(mCubitsNotInvolved[mCurrPhase]);
469
        }
470
      else
471
        {
472
        mCurrPhase = mNumPhases-1;
473
        mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
474
        mCurrMove = mNumMoves;
475
        int[][] moves = transformMoves(mMoves, true);
476
        ObjectControl control = act.getControl();
477
        control.applyScrambles(moves);
478
        glowCubits(mCubitsNotInvolved[mCurrPhase]);
479
        }
480

  
481
      setText(act);
482
      }
483
    }
484

  
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486

  
487
  void nextMove()
488
    {
489
    if( mMoves!=null && mCanMove )
490
      {
491
      SolverActivity act=mAct.get();
492

  
493
      if( mCurrMove<mNumMoves )
494
        {
495
        mCanMove = false;
496
        int[] move = mMoves[mCurrPhase][mCurrMove++];
497
        ObjectControl control = act.getControl();
498
        control.blockTouch(MOVES_PLACE_1);
499
        control.addRotation(this, move[0], (1<<move[1]), move[2], MILLIS_PER_DEGREE);
500
        if( mCurrMove==mNumMoves && mCurrPhase==mNumPhases-1 ) glowCubits(mCubitsNotInvolved[mCurrPhase]);
501
        }
502
      else if( mCurrPhase<mNumPhases-1 )
503
        {
504
        mCurrPhase++;
505
        mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
506
        mCurrMove = 0;
507
        glowCubits(mCubitsNotInvolved[mCurrPhase-1]);
508
        }
509
      else
510
        {
511
        mCurrPhase = 0;
512
        mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
513
        mCurrMove = 0;
514
        int[][] moves = transformMoves(mMoves, false);
515
        ObjectControl control = act.getControl();
516
        control.applyScrambles(moves);
517
        }
518

  
519
      setText(act);
520
      }
521
    }
522

  
523
///////////////////////////////////////////////////////////////////////////////////////////////////
524

  
525
  public void updateNames(String[] names)
526
    {
527
    mPhaseNames = names;
528
    mNumPhases = names.length;
529
    mMoves = new int[mNumPhases][][];
530
    mCubitsNotInvolved = new int[mNumPhases][];
531
    mCanMove = true;
532
    if( mAct!=null ) setSolution(null,0,null);
533
    }
534

  
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536

  
537
  public void setSolution(int[][] moves, int phase, int[][] subphases)
538
    {
539
    SolverActivity act=mAct.get();
540

  
541
    if( subphases!=null )
542
      {
543
      ObjectControl control=act.getControl();
544
      TwistyObject object=control.getObject();
545
      int numCubits=object.getNumCubits();
546
      mCubitsNotInvolved[phase]= computeCubitsNotInvolved(subphases, numCubits);
547
      }
548

  
549
    mMoves[phase] = moves;
550
    if( phase==0 ) mNumMoves = (moves==null ? 0 : moves.length);
551
    mCurrPhase = 0;
552
    mCurrMove = 0;
553

  
554
    setText(act);
555
    }
556

  
557
///////////////////////////////////////////////////////////////////////////////////////////////////
558

  
559
  public void onActionFinished(final long effectID)
560
    {
561
    mCanMove = true;
562
    SolverActivity act=mAct.get();
563
    ObjectControl control = act.getControl();
564
    control.unblockRotation();
565
    }
566

  
567
///////////////////////////////////////////////////////////////////////////////////////////////////
568

  
569
  public void effectFinished(long id)
570
    {
571
    SolverActivity act=mAct.get();
572
    ObjectControl control = act.getControl();
573
    TwistyObject object=control.getObject();
574
    DistortedEffects effects=object.getObjectEffects();
575
    effects.abortById(id);
576
    mEffectWorking = false;
577
    }
578
  }
src/main/java/org/distorted/solverui/ScreenSolver.java
12 12
import static org.distorted.objectlib.metadata.ListObjects.*;
13 13

  
14 14
import android.content.SharedPreferences;
15
import android.content.res.Resources;
15 16
import android.graphics.Bitmap;
16 17
import android.graphics.Canvas;
17 18
import android.graphics.Paint;
......
30 31
import org.distorted.helpers.TransparentImageButton;
31 32
import org.distorted.main.MainActivity;
32 33
import org.distorted.main.R;
34
import org.distorted.objectlib.helpers.OperatingSystemInterface;
33 35
import org.distorted.objectlib.main.ObjectControl;
34 36
import org.distorted.objectlib.main.TwistyObject;
35 37
import org.distorted.objectlib.metadata.ListObjects;
......
252 254
      if( len==1 ) // just one solver - simply launch it and start finding the solution
253 255
        {
254 256
        SolvingList list = SolvingList.getSolver(solverOrdinals[0]);
257
        OperatingSystemInterface os = act.getInterface();
258
        Resources res = act.getResources();
255 259
        TwistyObject object = act.getObject();
256
        SolvingThread solver = new SolvingThread( act.getInterface(), act.getResources(), object, list );
260
        SolvingThread solver = new SolvingThread( os,res,object,list );
257 261
        solver.start();
258 262
        return true;
259 263
        }
......
452 456
      }
453 457
    }
454 458

  
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460

  
461
  public void setSolved(final int[][] moves, final int phaseNumber, final int[][] subphases)
462
    {
463
    mSolving = false;
464
    final SolverActivity act = mWeakAct.get();
465

  
466
    if( act!=null )
467
      {
468
      act.runOnUiThread(new Runnable()
469
        {
470
        @Override
471
        public void run()
472
          {
473
          if( phaseNumber==0 ) ScreenList.switchScreen(act, ScreenList.PHAS);
474
          ScreenPhasedSolution screen = (ScreenPhasedSolution) ScreenList.PHAS.getScreenClass();
475
          screen.setSolution(moves, phaseNumber,subphases);
476
          if( moves!=null && moves.length>0 ) act.doNotShowDialogAnymore();
477
          }
478
        });
479
      }
480
    }
481

  
455 482
///////////////////////////////////////////////////////////////////////////////////////////////////
456 483

  
457 484
  public void displayErrorDialog(String message)
src/main/res/values-de/strings.xml
208 208
    <string name="color_violet7">violette</string>
209 209
    <string name="color_grey7">graue</string>
210 210

  
211
    <string name="solver_cube3_description">Ein nahezu perfekter, sofortiger, zweiphasiger 3x3x3-Löser.\nAutor: Herbert Kociemba.</string>
211
    <string name="solver_cube3_description">Ein nahezu perfekter, sofortiger, zweiphasiger 3x3-Löser.\nAutor: Herbert Kociemba.</string>
212
    <string name="solver_3algo_description">Implementierung des Anfängeralgorithmus. 7 Phasen. Erzeugt Lösungen mit etwa 100 Zügen.\nAutor: Leszek Koltunski.</string>
212 213
    <string name="solver_pduo2_description">Ein perfekter, sofortiger Löser.\nAutor: Leszek Koltunski.</string>
213 214
    <string name="solver_ivy_description">Ein perfekter, sofortiger Löser.\nAutor: Leszek Koltunski.</string>
214 215
    <string name="solver_cu232_description">Ein perfekter, sofortiger Löser.\nAutor: Leszek Koltunski.</string>
src/main/res/values-es/strings.xml
209 209
    <string name="color_grey7">grises</string>
210 210

  
211 211
    <string name="solver_cube3_description">Un 3x3x3 solucionador casi perfecto, instantáneo, de dos fases.\nAutor: Herbert Kociemba.</string>
212
    <string name="solver_3algo_description">Implementación del algoritmo para principiantes. 7 fases. Produce soluciones de aproximadamente 100 movimientos.\nAutor: Leszek Koltunski.</string>
212 213
    <string name="solver_pduo2_description">Un solucionador perfecto e instantáneo.\nAutor: Leszek Koltunski.</string>
213 214
    <string name="solver_ivy_description">Un solucionador perfecto e instantáneo.\nAutor: Leszek Koltunski.</string>
214 215
    <string name="solver_cu232_description">Un solucionador perfecto e instantáneo.\nAutor: Leszek Koltunski.</string>
src/main/res/values-fr/strings.xml
208 208
    <string name="color_violet7">violets</string>
209 209
    <string name="color_grey7">gris</string>
210 210

  
211
    <string name="solver_cube3_description">Un solveur 3x3x3 biphasé presque parfait, instantané.\nAuteur: Herbert Kociemba.</string>
211
    <string name="solver_cube3_description">Un solveur 3x3 biphasé presque parfait, instantané.\nAuteur: Herbert Kociemba.</string>
212
    <string name="solver_3algo_description">Mise en œuvre de l\'algorithme pour débutants. 7 phases. Produit des solutions longues d\'environ 100 coups.\nAuteur: Leszek Koltunski.</string>
212 213
    <string name="solver_pduo2_description">Un solveur parfait et instantané.\nAuteur: Leszek Koltunski.</string>
213 214
    <string name="solver_ivy_description">Un solveur parfait et instantané.\nAuteur: Leszek Koltunski.</string>
214 215
    <string name="solver_cu232_description">Un solveur parfait et instantané.\nAuteur: Leszek Koltunski.</string>
src/main/res/values-ja/strings.xml
209 209
    <string name="color_grey7">グレー</string>
210 210

  
211 211
    <string name="solver_cube3_description">ほぼ完璧で瞬間的な 2 フェーズ 3x3x3 ソルバー。\n著者: Herbert Kociemba.</string>
212
    <string name="solver_3algo_description">初心者向けアルゴリズムの実装。7 フェーズ。約 100 手の長さのソリューションを生成します。\n著者: Leszek Koltunski.</string>
212 213
    <string name="solver_pduo2_description">完璧で瞬時のソルバー。\n著者: Leszek Koltunski.</string>
213 214
    <string name="solver_ivy_description">完璧で瞬時のソルバー。\n著者: Leszek Koltunski.</string>
214 215
    <string name="solver_cu232_description">完璧で瞬時のソルバー。\n著者: Leszek Koltunski.</string>
src/main/res/values-ko/strings.xml
209 209
    <string name="color_grey7">회색</string>
210 210

  
211 211
    <string name="solver_cube3_description">거의 완벽하고 즉각적인 2상 3x3x3 솔버입니다.\n작가: Herbert Kociemba.</string>
212
    <string name="solver_3algo_description">초보자 알고리즘 구현. 7단계. 약 100-이동 길이의 솔루션을 생성합니다.\n작가: Leszek Koltunski.</string>
212 213
    <string name="solver_pduo2_description">완벽하고 즉각적인 솔버.\n작가: Leszek Koltunski.</string>
213 214
    <string name="solver_ivy_description">완벽하고 즉각적인 솔버.\n작가: Leszek Koltunski.</string>
214 215
    <string name="solver_cu232_description">완벽하고 즉각적인 솔버.\n작가: Leszek Koltunski.</string>
src/main/res/values-pl/strings.xml
209 209
    <string name="color_grey7">szare</string>
210 210

  
211 211
    <string name="solver_cube3_description">Natychmiastowy, prawie optymalny rozwiązywacz kostki 3x3x3.\nAutor: Herbert Kociemba.</string>
212
    <string name="solver_3algo_description">Implementacja algorytmu dla początkujących. 7 faz. Tworzy rozwiązania o długości około 100 ruchów.\nAutor: Leszek Koltunski.</string>
212 213
    <string name="solver_pduo2_description">Optymalny, natychmiastowy rozwiązywacz.\nAutor: Leszek Koltunski.</string>
213 214
    <string name="solver_ivy_description">Optymalny, natychmiastowy rozwiązywacz.\nAutor: Leszek Koltunski.</string>
214 215
    <string name="solver_cu232_description">Optymalny, natychmiastowy rozwiązywacz.\nAutor: Leszek Koltunski.</string>
src/main/res/values-ru/strings.xml
209 209
    <string name="color_grey7">серых</string>
210 210

  
211 211
    <string name="solver_cube3_description">Практически идеальный, мгновенный, двухфазный решатель 3x3x3.\nАвтор: Herbert Kociemba.</string>
212
    <string name="solver_3algo_description">Реализация алгоритма для начинающих. 7 фаз. Выдает решения длиной около 100 ходов.\nАвтор: Leszek Koltunski.</string>
212 213
    <string name="solver_pduo2_description">Идеальный, мгновенный решатель.\nАвтор: Leszek Koltunski.</string>
213 214
    <string name="solver_ivy_description">Идеальный, мгновенный решатель.\nАвтор: Leszek Koltunski.</string>
214 215
    <string name="solver_cu232_description">Идеальный, мгновенный решатель.\nАвтор: Leszek Koltunski.</string>
src/main/res/values-zh-rCN/strings.xml
215 215
    <string name="color_grey7">灰色的</string>
216 216

  
217 217
    <string name="solver_cube3_description">一个几乎完美的、瞬时的、两相的3x3x3解算器。\n作者: Herbert Kociemba.</string>
218
    <string name="solver_3algo_description">初学者算法的实现。7 个阶段。产生大约 100 步长的解决方案。\n作者: Leszek Koltunski.</string>
218 219
    <string name="solver_pduo2_description">完美的即时求解器。\n作者: Leszek Koltunski.</string>
219 220
    <string name="solver_ivy_description">完美的即时求解器。\n作者: Leszek Koltunski.</string>
220 221
    <string name="solver_cu232_description">完美的即时求解器。\n作者: Leszek Koltunski.</string>
src/main/res/values-zh-rTW/strings.xml
209 209
    <string name="color_grey7">灰色的</string>
210 210

  
211 211
    <string name="solver_cube3_description">一個近乎完美的瞬時兩相 3x3x3 求解器。\n作者: Herbert Kociemba.</string>
212
    <string name="solver_3algo_description">初學者演算法的實作。 7 個階段。產生大約 100 個動作的長解。\n作者: Leszek Koltunski.</string>
212 213
    <string name="solver_pduo2_description">完美的即時求解器。\n作者: Leszek Koltunski.</string>
213 214
    <string name="solver_ivy_description">完美的即時求解器。\n作者: Leszek Koltunski.</string>
214 215
    <string name="solver_cu232_description">完美的即時求解器。\n作者: Leszek Koltunski.</string>
src/main/res/values/strings.xml
232 232
    <string name="color_grey7">grey</string>
233 233

  
234 234
    <string name="solver_cube3_title" translatable="false">Kociemba Solver</string>
235
    <string name="solver_3algo_title" translatable="false">3x3 Beginner</string>
235 236
    <string name="solver_pduo2_title" translatable="false">Pyraminx Duo Solver</string>
236 237
    <string name="solver_pyra3_title" translatable="false">Pyraminx Solver</string>
237 238
    <string name="solver_ivy_title" translatable="false">Ivy Solver</string>
......
246 247
    <string name="solver_pdia_title" translatable="false">Pyraminx Diamond Solver</string>
247 248

  
248 249
    <string name="solver_cube3_description">A near-perfect, instantaneous, two-phase 3x3x3 solver.\nAuthor: Herbert Kociemba.</string>
250
    <string name="solver_3algo_description">Implementation of the beginner algorithm. 7 phases. Produces about 100 move long solutions.\nAuthor: Leszek Koltunski.</string>
249 251
    <string name="solver_pduo2_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
250 252
    <string name="solver_ivy_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>
251 253
    <string name="solver_cu232_description">A perfect, instantaneous solver.\nAuthor: Leszek Koltunski.</string>

Also available in: Unified diff