Project

General

Profile

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

magiccube / src / main / java / org / distorted / patterns / RubikPattern.java @ e4f656d1

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 java.util.ArrayList;
23
import java.util.List;
24

    
25
import org.distorted.objectlib.helpers.MovesFinished;
26
import org.distorted.objectlib.main.ObjectControl;
27

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

    
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31

    
32
public class RubikPattern
33
{
34
  private static final int MILLIS_PER_DEGREE = 6;
35

    
36
  private final int[] numCategories    = new int[NUM_OBJECTS];
37
  private final int[] currentCategory  = new int[NUM_OBJECTS];
38
  private final int[] currentVisiblePos= new int[NUM_OBJECTS];
39
  private final int[] currentExpanded  = new int[NUM_OBJECTS];
40

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

    
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

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

    
53
  /////////////////////////////////////////////////////////////
54

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

    
62
  /////////////////////////////////////////////////////////////
63

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

    
70
      mPatterns = new ArrayList<>();
71

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

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

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

    
90
      mInitialized = true;
91
      }
92

    
93
  /////////////////////////////////////////////////////////////
94

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

    
100
  /////////////////////////////////////////////////////////////
101

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

    
107
  /////////////////////////////////////////////////////////////
108

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

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

    
119
      return "";
120
      }
121

    
122
  /////////////////////////////////////////////////////////////
123

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

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

    
134
      return -1;
135
      }
136

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

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

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

    
149
      return -1;
150
      }
151

    
152
  /////////////////////////////////////////////////////////////
153

    
154
    void makeMove(ObjectControl control, int pattern)
155
      {
156
      if( !mInitialized ) initialize();
157

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

    
165
  /////////////////////////////////////////////////////////////
166

    
167
    void backMove(ObjectControl control, int pattern)
168
      {
169
      if( !mInitialized ) initialize();
170

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

    
178
  /////////////////////////////////////////////////////////////
179

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

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

    
190
      return null;
191
      }
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

    
196
  private static class Pattern implements MovesFinished
197
    {
198
    private final String nameStr;
199
    private String moveStr;
200
    private int[][] moves;
201
    private int curMove;
202
    private int numMove;
203
    private boolean mCanRotate;
204
    private boolean mInitialized;
205

    
206
  /////////////////////////////////////////////////////////////
207

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

    
216
  /////////////////////////////////////////////////////////////
217

    
218
    private String expandOne(String moves)
219
      {
220
      int right, left=-1;
221
      int len=moves.length();
222

    
223
      for(int ch=0; ch<len; ch++)
224
        {
225
        char c = moves.charAt(ch);
226

    
227
        if( c == '(' ) left=ch;
228
        if( c == ')' && left>=0 )
229
          {
230
          right = ch;
231
          String lStr = moves.substring(0, moves.charAt(left-1)==' ' ? left-1 : left);
232
          String mStr = moves.substring(left+1,right);
233
          String rStr = moves.substring(right+1);
234
          int number, space = rStr.indexOf(' ');
235
          if( mStr.charAt(0) != ' ') mStr = ' '+mStr;
236

    
237
          if( space>0 )
238
            {
239
            number = Integer.parseInt(rStr.substring(0,space));
240
            rStr = rStr.substring(space);
241
            }
242
          else if( space==0 )
243
            {
244
            number = 1;
245
            }
246
          else
247
            {
248
            number = Integer.parseInt(rStr);
249
            rStr = "";
250
            }
251

    
252
          StringBuilder builder = new StringBuilder();
253
          builder.append(lStr);
254
          for(int i=0; i<number; i++) builder.append(mStr);
255
          builder.append(rStr);
256
          return builder.toString();
257
          }
258
        }
259

    
260
      return moves;
261
      }
262

    
263
  /////////////////////////////////////////////////////////////
264

    
265
    private String expand(String moves)
266
      {
267
      String next,curr = moves;
268
      boolean expanded;
269

    
270
      do
271
        {
272
        next = expandOne(curr);
273
        expanded = (next.length() > curr.length());
274
        curr = next;
275
        }
276
      while(expanded);
277

    
278
      return curr;
279
      }
280

    
281
  /////////////////////////////////////////////////////////////
282

    
283
    private void initialize()
284
      {
285
      numMove = moveStr.length()/4;
286
      moves   = new int[numMove][3];
287
      curMove = numMove;
288
      parseMoves(moves,numMove,moveStr);
289
      moveStr = null;
290
      mInitialized = true;
291
      }
292

    
293
  /////////////////////////////////////////////////////////////
294

    
295
    String getName()
296
      {
297
      return nameStr;
298
      }
299

    
300
  /////////////////////////////////////////////////////////////
301

    
302
    int getNumMove()
303
      {
304
      if( !mInitialized ) initialize();
305

    
306
      return numMove;
307
      }
308

    
309
  /////////////////////////////////////////////////////////////
310

    
311
    int getCurMove()
312
      {
313
      if( !mInitialized ) initialize();
314

    
315
      return curMove;
316
      }
317

    
318
  /////////////////////////////////////////////////////////////
319

    
320
    void makeMove(ObjectControl control)
321
      {
322
      if( !mInitialized ) initialize();
323

    
324
      if( mCanRotate )
325
        {
326
        curMove++;
327

    
328
        if( curMove>numMove )
329
          {
330
          curMove= 0;
331
          control.initializeObject(null);
332
          }
333
        else
334
          {
335
          int axis      = moves[curMove-1][0];
336
		      int rowBitmap = moves[curMove-1][1];
337
		      int bareAngle = moves[curMove-1][2];
338

    
339
          if( bareAngle!=0 )
340
            {
341
            mCanRotate = false;
342
            control.addRotation(this, axis, rowBitmap, bareAngle, MILLIS_PER_DEGREE);
343
            }
344
          else
345
            {
346
            android.util.Log.e("pattern", "error: pattern "+nameStr+" move "+(curMove-1)+" angle 0");
347
            }
348
          }
349
        }
350
      else
351
        {
352
        android.util.Log.e("pattern", "failed to make Move!");
353
        }
354
      }
355

    
356
  /////////////////////////////////////////////////////////////
357

    
358
    void backMove(ObjectControl control)
359
      {
360
      if( !mInitialized ) initialize();
361

    
362
      if( mCanRotate )
363
        {
364
        curMove--;
365

    
366
        if( curMove<0 )
367
          {
368
          curMove=numMove;
369
          control.initializeObject(moves);
370
          }
371
        else
372
          {
373
          int axis      = moves[curMove][0];
374
		      int rowBitmap = moves[curMove][1];
375
		      int bareAngle = moves[curMove][2];
376

    
377
          if( bareAngle!=0 )
378
            {
379
            mCanRotate = false;
380
            control.addRotation(this, axis, rowBitmap, -bareAngle, MILLIS_PER_DEGREE);
381
            }
382
          else
383
            {
384
            android.util.Log.e("pattern", "error: pattern "+nameStr+" move "+curMove+" angle 0");
385
            }
386
          }
387
        }
388
      else
389
        {
390
        android.util.Log.e("pattern", "failed to back Move!");
391
        }
392
      }
393

    
394
  /////////////////////////////////////////////////////////////
395

    
396
    int[][] reInitialize()
397
      {
398
      if( !mInitialized ) initialize();
399

    
400
      mCanRotate = true;
401
      curMove = numMove;
402
      return moves;
403
      }
404

    
405
  /////////////////////////////////////////////////////////////
406

    
407
    public void onActionFinished(final long effectID)
408
      {
409
      mCanRotate = true;
410
      }
411
    }
412

    
413
///////////////////////////////////////////////////////////////////////////////////////////////////
414

    
415
  private RubikPattern()
416
    {
417
    mCategories = new ArrayList<>();
418

    
419
    for(int i=0; i<NUM_OBJECTS; i++)
420
      {
421
      List<Category> list = new ArrayList<>();
422
      String[][] patStrings = RubikPatternList.getPatterns(i);
423

    
424
      for(String[] lines: patStrings) list.add(new Category(lines));
425

    
426
      mCategories.add(list);
427
      numCategories[i]=patStrings.length;
428

    
429
      currentExpanded[i] = -1;
430
      }
431
    }
432

    
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434

    
435
  private Category getCategory(int tab, int cat)
436
    {
437
    if( tab>=0 && tab<NUM_OBJECTS && cat>=0 && cat<numCategories[tab] )
438
      {
439
      return mCategories.get(tab).get(cat);
440
      }
441

    
442
    return null;
443
    }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446
// PUBLIC API
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

    
449
  public static RubikPattern getInstance()
450
    {
451
    if( mThis==null )
452
      {
453
      mThis = new RubikPattern();
454
      }
455

    
456
    return mThis;
457
    }
458

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

    
461
  public static void parseMoves(int[][] result, int numMoves, String moves)
462
    {
463
    int digit0, digit1, digit2, number;
464

    
465
    for(int i=0; i<numMoves; i++)
466
      {
467
      digit0 = moves.charAt(4*i+1)-'0';
468
      digit1 = moves.charAt(4*i+2)-'0';
469
      digit2 = moves.charAt(4*i+3)-'0';
470
      number = 100*digit0+10*digit1+digit2;
471

    
472
      int axis   = (number/32)%8;
473
      int bitmap = (number%32)  ;
474
      int angle  = (number/32)/8;
475

    
476
      switch(angle)
477
        {
478
        case 0: angle = 2; break;
479
        case 1: angle = 1; break;
480
        case 2: angle =-1; break;
481
        case 3: angle =-2; break;
482
        default: android.util.Log.e("D", "ERROR!! parsing move "+moves+" number="+number);
483
        }
484

    
485
      result[i][0] = axis;
486
      result[i][1] = bitmap;
487
      result[i][2] = angle;
488
      }
489
    }
490

    
491
///////////////////////////////////////////////////////////////////////////////////////////////////
492

    
493
  public int getNumCategories(int tab)
494
    {
495
    return tab>=0 && tab<NUM_OBJECTS ? numCategories[tab] : 0;
496
    }
497

    
498
///////////////////////////////////////////////////////////////////////////////////////////////////
499

    
500
  public void rememberState(int tab, int cat, int scrollPos, int expanded)
501
    {
502
    if( tab>=0 && tab<NUM_OBJECTS )
503
      {
504
      currentCategory[tab]  = cat;
505
      currentVisiblePos[tab]= scrollPos;
506
      currentExpanded[tab]  = expanded;
507
      }
508
    }
509

    
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511

    
512
  public int recallCategory(int tab)
513
    {
514
    return tab>=0 && tab<NUM_OBJECTS ? currentCategory[tab] : 0;
515
    }
516

    
517
///////////////////////////////////////////////////////////////////////////////////////////////////
518

    
519
  public int recallVisiblePos(int tab)
520
    {
521
    return tab>=0 && tab<NUM_OBJECTS ? currentVisiblePos[tab] : 0;
522
    }
523

    
524
///////////////////////////////////////////////////////////////////////////////////////////////////
525

    
526
  public int recallExpanded(int tab)
527
    {
528
    return tab>=0 && tab<NUM_OBJECTS ? currentExpanded[tab] : -1;
529
    }
530

    
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532

    
533
  public String getCategoryName(int tab, int cat)
534
    {
535
    Category c = getCategory(tab,cat);
536
    return c!=null ? c.getName() : null;
537
    }
538

    
539
///////////////////////////////////////////////////////////////////////////////////////////////////
540

    
541
  public String getPatternName(int tab, int cat, int pat)
542
    {
543
    Category c = getCategory(tab,cat);
544
    return c!=null ? c.getPatternName(pat) : null;
545
    }
546

    
547
///////////////////////////////////////////////////////////////////////////////////////////////////
548

    
549
  public int getNumPatterns(int tab, int cat)
550
    {
551
    Category c = getCategory(tab,cat);
552
    return c!=null ? c.getNumPatterns() : 0;
553
    }
554

    
555
///////////////////////////////////////////////////////////////////////////////////////////////////
556

    
557
  public int getCurMove(int tab, int cat, int pat)
558
    {
559
    Category c = getCategory(tab,cat);
560
    return c!=null ? c.getPatternCurMove(pat) : 0;
561
    }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564

    
565
  public int getNumMoves(int tab, int cat, int pat)
566
    {
567
    Category c = getCategory(tab,cat);
568
    return c!=null ? c.getPatternNumMove(pat) : 0;
569
    }
570

    
571
///////////////////////////////////////////////////////////////////////////////////////////////////
572

    
573
  public void makeMove(ObjectControl control, int tab, int cat, int pat)
574
    {
575
    Category c = getCategory(tab,cat);
576
    if( c!=null ) c.makeMove(control,pat);
577
    }
578

    
579
///////////////////////////////////////////////////////////////////////////////////////////////////
580

    
581
  public void backMove(ObjectControl control, int tab, int cat, int pat)
582
    {
583
    Category c = getCategory(tab,cat);
584
    if( c!=null ) c.backMove(control,pat);
585
    }
586

    
587
///////////////////////////////////////////////////////////////////////////////////////////////////
588

    
589
  public int[][] reInitialize(int tab, int cat, int pat)
590
    {
591
    Category c = getCategory(tab,cat);
592
    return c!=null ? c.reInitialize(pat) : null;
593
    }
594
}
(10-10/11)