Project

General

Profile

Download (14 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / patterns / RubikPattern.java @ 5a4d4fba

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.patterns;
21

    
22
import org.distorted.main.RubikPreRender;
23

    
24
import java.util.ArrayList;
25
import java.util.List;
26

    
27
import static org.distorted.patterns.RubikPatternList.NUM_OBJECTS;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

    
31
public class RubikPattern
32
{
33
  private static final int DURATION_MILLIS = 750;
34

    
35
  private int[] numCategories   = new int[NUM_OBJECTS];
36
  private int[] currentCategory = new int[NUM_OBJECTS];
37
  private int[] currentScrollPos= new int[NUM_OBJECTS];
38

    
39
  private List<List<Category>> mCategories;
40
  private static RubikPattern mThis;
41

    
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43

    
44
  private static class Category
45
    {
46
    private String[] mLines;
47
    private int numPatterns;
48
    private ArrayList<Pattern> mPatterns;
49
    private boolean mInitialized;
50

    
51
  /////////////////////////////////////////////////////////////
52

    
53
    Category(String[] lines)
54
      {
55
      mLines       = lines;
56
      numPatterns  = lines.length-1;
57
      mInitialized = false;
58
      }
59

    
60
  /////////////////////////////////////////////////////////////
61

    
62
    void initialize()
63
      {
64
      int colon;
65
      String moves, name;
66
      Pattern pattern;
67

    
68
      mPatterns = new ArrayList<>();
69

    
70
      for(int i=0; i<numPatterns; i++)
71
        {
72
        colon = mLines[i+1].indexOf(":");
73

    
74
        if( colon!=-1 )
75
          {
76
          moves   = mLines[i+1].substring(colon+1);
77
          name    = mLines[i+1].substring(0,colon);
78
          pattern = new Pattern(name,moves);
79

    
80
          mPatterns.add(pattern);
81
          }
82
        else
83
          {
84
          numPatterns--;
85
          }
86
        }
87

    
88
      mInitialized = true;
89
      }
90

    
91
  /////////////////////////////////////////////////////////////
92

    
93
    int getNumPatterns()
94
      {
95
      return numPatterns;
96
      }
97

    
98
  /////////////////////////////////////////////////////////////
99

    
100
    String getName()
101
      {
102
      return mLines[0];
103
      }
104

    
105
  /////////////////////////////////////////////////////////////
106

    
107
    String getPatternName(int pattern)
108
      {
109
      if( !mInitialized ) initialize();
110

    
111
      if( pattern>=0 && pattern<numPatterns )
112
        {
113
        Pattern p = mPatterns.get(pattern);
114
        return  p!=null ? p.getName():"";
115
        }
116

    
117
      return "";
118
      }
119

    
120
  /////////////////////////////////////////////////////////////
121

    
122
    int getPatternCurMove(int pattern)
123
      {
124
      if( !mInitialized ) initialize();
125

    
126
      if( pattern>=0 && pattern<numPatterns )
127
        {
128
        Pattern p = mPatterns.get(pattern);
129
        return  p!=null ? p.getCurMove():-1;
130
        }
131

    
132
      return -1;
133
      }
134

    
135
  /////////////////////////////////////////////////////////////
136

    
137
    int getPatternNumMove(int pattern)
138
      {
139
      if( !mInitialized ) initialize();
140

    
141
      if( pattern>=0 && pattern<numPatterns )
142
        {
143
        Pattern p = mPatterns.get(pattern);
144
        return  p!=null ? p.getNumMove():-1;
145
        }
146

    
147
      return -1;
148
      }
149

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

    
152
    void makeMove(RubikPreRender pre, int pattern)
153
      {
154
      if( !mInitialized ) initialize();
155

    
156
      if( pattern>=0 && pattern<numPatterns )
157
        {
158
        Pattern p = mPatterns.get(pattern);
159
        if( p!=null ) p.makeMove(pre);
160
        }
161
      }
162

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

    
165
    void backMove(RubikPreRender pre, int pattern)
166
      {
167
      if( !mInitialized ) initialize();
168

    
169
      if( pattern>=0 && pattern<numPatterns )
170
        {
171
        Pattern p = mPatterns.get(pattern);
172
        if( p!=null ) p.backMove(pre);
173
        }
174
      }
175

    
176
  /////////////////////////////////////////////////////////////
177

    
178
    int[][] reInitialize(int pattern)
179
      {
180
      if( !mInitialized ) initialize();
181

    
182
      if( pattern>=0 && pattern<numPatterns )
183
        {
184
        Pattern p = mPatterns.get(pattern);
185
        if( p!=null ) return p.reInitialize();
186
        }
187

    
188
      return null;
189
      }
190
    }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
  private static class Pattern implements RubikPreRender.ActionFinishedListener
195
    {
196
    private String nameStr, moveStr;
197
    private int[][] moves;
198
    private int curMove;
199
    private int numMove;
200
    private boolean mCanRotate;
201
    private boolean mInitialized;
202

    
203
  /////////////////////////////////////////////////////////////
204

    
205
    Pattern(String name, String moves)
206
      {
207
      nameStr      = name;
208
      moveStr      = moves;
209
      mCanRotate   = true;
210
      mInitialized = false;
211
      }
212

    
213
  /////////////////////////////////////////////////////////////
214

    
215
    private void initialize()
216
      {
217
      numMove = moveStr.length()/4;
218
      moves   = new int[numMove][3];
219
      curMove = numMove;
220
      parseMoves(moves,numMove,moveStr);
221
      moveStr = null;
222
      mInitialized = true;
223
      }
224

    
225
  /////////////////////////////////////////////////////////////
226

    
227
    String getName()
228
      {
229
      return nameStr;
230
      }
231

    
232
  /////////////////////////////////////////////////////////////
233

    
234
    int getNumMove()
235
      {
236
      if( !mInitialized ) initialize();
237

    
238
      return numMove;
239
      }
240

    
241
  /////////////////////////////////////////////////////////////
242

    
243
    int getCurMove()
244
      {
245
      if( !mInitialized ) initialize();
246

    
247
      return curMove;
248
      }
249

    
250
  /////////////////////////////////////////////////////////////
251

    
252
    void makeMove(RubikPreRender pre)
253
      {
254
      if( !mInitialized ) initialize();
255

    
256
      if( mCanRotate )
257
        {
258
        curMove++;
259

    
260
        if( curMove>numMove )
261
          {
262
          curMove= 0;
263
          pre.initializeObject(null);
264
          }
265
        else
266
          {
267
          int axis     = moves[curMove-1][0];
268
		      int rowBitmap= moves[curMove-1][1];
269
		      int bareAngle= moves[curMove-1][2];
270
          int angle    = bareAngle*(360/pre.getObject().getBasicAngle());
271
          int numRot   = Math.abs(bareAngle);
272

    
273
          if( angle!=0 )
274
            {
275
            mCanRotate = false;
276
            pre.addRotation(this, axis, rowBitmap, angle, numRot*DURATION_MILLIS);
277
            }
278
          else
279
            {
280
            android.util.Log.e("pattern", "error: pattern "+nameStr+" move "+(curMove-1)+" angle 0");
281
            }
282
          }
283
        }
284
      else
285
        {
286
        android.util.Log.e("pattern", "failed to make Move!");
287
        }
288
      }
289

    
290
  /////////////////////////////////////////////////////////////
291

    
292
    void backMove(RubikPreRender pre)
293
      {
294
      if( !mInitialized ) initialize();
295

    
296
      if( mCanRotate )
297
        {
298
        curMove--;
299

    
300
        if( curMove<0 )
301
          {
302
          curMove=numMove;
303
          pre.initializeObject(moves);
304
          }
305
        else
306
          {
307
          int axis     = moves[curMove][0];
308
		      int rowBitmap= moves[curMove][1];
309
		      int bareAngle= moves[curMove][2];
310
          int angle    = bareAngle*(360/pre.getObject().getBasicAngle());
311
          int numRot   = Math.abs(bareAngle);
312

    
313
          if( angle!=0 )
314
            {
315
            mCanRotate = false;
316
            pre.addRotation(this, axis, rowBitmap, -angle, numRot*DURATION_MILLIS);
317
            }
318
          else
319
            {
320
            android.util.Log.e("pattern", "error: pattern "+nameStr+" move "+curMove+" angle 0");
321
            }
322
          }
323
        }
324
      else
325
        {
326
        android.util.Log.e("pattern", "failed to back Move!");
327
        }
328
      }
329

    
330
  /////////////////////////////////////////////////////////////
331

    
332
    int[][] reInitialize()
333
      {
334
      if( !mInitialized ) initialize();
335

    
336
      mCanRotate = true;
337
      curMove = numMove;
338
      return moves;
339
      }
340

    
341
  /////////////////////////////////////////////////////////////
342

    
343
    public void onActionFinished(final long effectID)
344
      {
345
      mCanRotate = true;
346
      }
347
    }
348

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

    
351
  private RubikPattern()
352
    {
353
    mCategories = new ArrayList<>();
354

    
355
    for(int i=0; i<NUM_OBJECTS; i++)
356
      {
357
      List<Category> list = new ArrayList<>();
358
      String[][] patStrings = RubikPatternList.getPatterns(i);
359

    
360
      for(String[] lines: patStrings) list.add(new Category(lines));
361

    
362
      mCategories.add(list);
363
      numCategories[i]=patStrings.length;
364
      }
365
    }
366

    
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368

    
369
  private Category getCategory(int tab, int cat)
370
    {
371
    if( tab>=0 && tab<NUM_OBJECTS && cat>=0 && cat<numCategories[tab] )
372
      {
373
      return mCategories.get(tab).get(cat);
374
      }
375

    
376
    return null;
377
    }
378

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380
// PUBLIC API
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  public static RubikPattern getInstance()
384
    {
385
    if( mThis==null )
386
      {
387
      mThis = new RubikPattern();
388
      }
389

    
390
    return mThis;
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
  public static void parseMoves(int[][] result, int numMoves, String moves)
396
    {
397
    int digit0, digit1, digit2, number;
398

    
399
    for(int i=0; i<numMoves; i++)
400
      {
401
      digit0 = moves.charAt(4*i+1)-'0';
402
      digit1 = moves.charAt(4*i+2)-'0';
403
      digit2 = moves.charAt(4*i+3)-'0';
404
      number = 100*digit0+10*digit1+digit2;
405

    
406
      result[i][0] =  (number/32)%4;   // axis
407
      result[i][1] =  (number%32)  ;   // bitmap
408
      result[i][2] =2-(number/32)/4;   // angle
409
      }
410
    }
411

    
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413

    
414
  public int getNumCategories(int tab)
415
    {
416
    return tab>=0 && tab<NUM_OBJECTS ? numCategories[tab] : 0;
417
    }
418

    
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420

    
421
  public void rememberState(int tab, int cat, int scrollPos)
422
    {
423
    if( tab>=0 && tab<NUM_OBJECTS )
424
      {
425
      currentCategory[tab] = cat;
426
      currentScrollPos[tab]= scrollPos;
427
      }
428
    }
429

    
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431

    
432
  public int recallCategory(int tab)
433
    {
434
    return tab>=0 && tab<NUM_OBJECTS ? currentCategory[tab] : 0;
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  public int recallScrollPos(int tab)
440
    {
441
    return tab>=0 && tab<NUM_OBJECTS ? currentScrollPos[tab] : 0;
442
    }
443

    
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

    
446
  public String getCategoryName(int tab, int cat)
447
    {
448
    Category c = getCategory(tab,cat);
449
    return c!=null ? c.getName() : null;
450
    }
451

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453

    
454
  public String getPatternName(int tab, int cat, int pat)
455
    {
456
    Category c = getCategory(tab,cat);
457
    return c!=null ? c.getPatternName(pat) : null;
458
    }
459

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461

    
462
  public int getNumPatterns(int tab, int cat)
463
    {
464
    Category c = getCategory(tab,cat);
465
    return c!=null ? c.getNumPatterns() : 0;
466
    }
467

    
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469

    
470
  public int getCurMove(int tab, int cat, int pat)
471
    {
472
    Category c = getCategory(tab,cat);
473
    return c!=null ? c.getPatternCurMove(pat) : 0;
474
    }
475

    
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477

    
478
  public int getNumMoves(int tab, int cat, int pat)
479
    {
480
    Category c = getCategory(tab,cat);
481
    return c!=null ? c.getPatternNumMove(pat) : 0;
482
    }
483

    
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485

    
486
  public void makeMove(RubikPreRender pre, int tab, int cat, int pat)
487
    {
488
    Category c = getCategory(tab,cat);
489
    if( c!=null ) c.makeMove(pre,pat);
490
    }
491

    
492
///////////////////////////////////////////////////////////////////////////////////////////////////
493

    
494
  public void backMove(RubikPreRender pre, int tab, int cat, int pat)
495
    {
496
    Category c = getCategory(tab,cat);
497
    if( c!=null ) c.backMove(pre,pat);
498
    }
499

    
500
///////////////////////////////////////////////////////////////////////////////////////////////////
501

    
502
  public int[][] reInitialize(int tab, int cat, int pat)
503
    {
504
    Category c = getCategory(tab,cat);
505
    return c!=null ? c.reInitialize(pat) : null;
506
    }
507
}
(1-1/9)