Project

General

Profile

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

magiccube / src / main / java / org / distorted / patterns / RubikPattern.java @ 925ed78f

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[] currentVisiblePos= new int[NUM_OBJECTS];
38
  private int[] currentExpanded  = new int[NUM_OBJECTS];
39

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

    
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44

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

    
52
  /////////////////////////////////////////////////////////////
53

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

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

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

    
69
      mPatterns = new ArrayList<>();
70

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

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

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

    
89
      mInitialized = true;
90
      }
91

    
92
  /////////////////////////////////////////////////////////////
93

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

    
99
  /////////////////////////////////////////////////////////////
100

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

    
106
  /////////////////////////////////////////////////////////////
107

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

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

    
118
      return "";
119
      }
120

    
121
  /////////////////////////////////////////////////////////////
122

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

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

    
133
      return -1;
134
      }
135

    
136
  /////////////////////////////////////////////////////////////
137

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

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

    
148
      return -1;
149
      }
150

    
151
  /////////////////////////////////////////////////////////////
152

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

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

    
164
  /////////////////////////////////////////////////////////////
165

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

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

    
177
  /////////////////////////////////////////////////////////////
178

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

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

    
189
      return null;
190
      }
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

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

    
204
  /////////////////////////////////////////////////////////////
205

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

    
214
  /////////////////////////////////////////////////////////////
215

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

    
226
  /////////////////////////////////////////////////////////////
227

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

    
233
  /////////////////////////////////////////////////////////////
234

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

    
239
      return numMove;
240
      }
241

    
242
  /////////////////////////////////////////////////////////////
243

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

    
248
      return curMove;
249
      }
250

    
251
  /////////////////////////////////////////////////////////////
252

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

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

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

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

    
292
  /////////////////////////////////////////////////////////////
293

    
294
    void backMove(RubikPreRender pre)
295
      {
296
      if( !mInitialized ) initialize();
297

    
298
      if( mCanRotate )
299
        {
300
        curMove--;
301

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

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

    
333
  /////////////////////////////////////////////////////////////
334

    
335
    int[][] reInitialize()
336
      {
337
      if( !mInitialized ) initialize();
338

    
339
      mCanRotate = true;
340
      curMove = numMove;
341
      return moves;
342
      }
343

    
344
  /////////////////////////////////////////////////////////////
345

    
346
    public void onActionFinished(final long effectID)
347
      {
348
      mCanRotate = true;
349
      }
350
    }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  private RubikPattern()
355
    {
356
    mCategories = new ArrayList<>();
357

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

    
363
      for(String[] lines: patStrings) list.add(new Category(lines));
364

    
365
      mCategories.add(list);
366
      numCategories[i]=patStrings.length;
367

    
368
      currentExpanded[i] = -1;
369
      }
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  private Category getCategory(int tab, int cat)
375
    {
376
    if( tab>=0 && tab<NUM_OBJECTS && cat>=0 && cat<numCategories[tab] )
377
      {
378
      return mCategories.get(tab).get(cat);
379
      }
380

    
381
    return null;
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385
// PUBLIC API
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  public static RubikPattern getInstance()
389
    {
390
    if( mThis==null )
391
      {
392
      mThis = new RubikPattern();
393
      }
394

    
395
    return mThis;
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  public static void parseMoves(int[][] result, int numMoves, String moves)
401
    {
402
    int digit0, digit1, digit2, number;
403

    
404
    for(int i=0; i<numMoves; i++)
405
      {
406
      digit0 = moves.charAt(4*i+1)-'0';
407
      digit1 = moves.charAt(4*i+2)-'0';
408
      digit2 = moves.charAt(4*i+3)-'0';
409
      number = 100*digit0+10*digit1+digit2;
410

    
411
      result[i][0] =  (number/32)%4;   // axis
412
      result[i][1] =  (number%32)  ;   // bitmap
413
      result[i][2] =2-(number/32)/4;   // angle
414
      }
415
    }
416

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418

    
419
  public int getNumCategories(int tab)
420
    {
421
    return tab>=0 && tab<NUM_OBJECTS ? numCategories[tab] : 0;
422
    }
423

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

    
426
  public void rememberState(int tab, int cat, int scrollPos, int expanded)
427
    {
428
    if( tab>=0 && tab<NUM_OBJECTS )
429
      {
430
      currentCategory[tab]  = cat;
431
      currentVisiblePos[tab]= scrollPos;
432
      currentExpanded[tab]  = expanded;
433
      }
434
    }
435

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437

    
438
  public int recallCategory(int tab)
439
    {
440
    return tab>=0 && tab<NUM_OBJECTS ? currentCategory[tab] : 0;
441
    }
442

    
443
///////////////////////////////////////////////////////////////////////////////////////////////////
444

    
445
  public int recallVisiblePos(int tab)
446
    {
447
    return tab>=0 && tab<NUM_OBJECTS ? currentVisiblePos[tab] : 0;
448
    }
449

    
450
///////////////////////////////////////////////////////////////////////////////////////////////////
451

    
452
  public int recallExpanded(int tab)
453
    {
454
    return tab>=0 && tab<NUM_OBJECTS ? currentExpanded[tab] : -1;
455
    }
456

    
457
///////////////////////////////////////////////////////////////////////////////////////////////////
458

    
459
  public String getCategoryName(int tab, int cat)
460
    {
461
    Category c = getCategory(tab,cat);
462
    return c!=null ? c.getName() : null;
463
    }
464

    
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466

    
467
  public String getPatternName(int tab, int cat, int pat)
468
    {
469
    Category c = getCategory(tab,cat);
470
    return c!=null ? c.getPatternName(pat) : null;
471
    }
472

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

    
475
  public int getNumPatterns(int tab, int cat)
476
    {
477
    Category c = getCategory(tab,cat);
478
    return c!=null ? c.getNumPatterns() : 0;
479
    }
480

    
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482

    
483
  public int getCurMove(int tab, int cat, int pat)
484
    {
485
    Category c = getCategory(tab,cat);
486
    return c!=null ? c.getPatternCurMove(pat) : 0;
487
    }
488

    
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490

    
491
  public int getNumMoves(int tab, int cat, int pat)
492
    {
493
    Category c = getCategory(tab,cat);
494
    return c!=null ? c.getPatternNumMove(pat) : 0;
495
    }
496

    
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498

    
499
  public void makeMove(RubikPreRender pre, int tab, int cat, int pat)
500
    {
501
    Category c = getCategory(tab,cat);
502
    if( c!=null ) c.makeMove(pre,pat);
503
    }
504

    
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506

    
507
  public void backMove(RubikPreRender pre, int tab, int cat, int pat)
508
    {
509
    Category c = getCategory(tab,cat);
510
    if( c!=null ) c.backMove(pre,pat);
511
    }
512

    
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514

    
515
  public int[][] reInitialize(int tab, int cat, int pat)
516
    {
517
    Category c = getCategory(tab,cat);
518
    return c!=null ? c.reInitialize(pat) : null;
519
    }
520
}
(8-8/9)