Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikObjectList.java @ 8feb68c2

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 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.objects;
11

    
12
import java.util.ArrayList;
13
import java.util.Locale;
14

    
15
import android.content.Context;
16
import android.content.SharedPreferences;
17

    
18
import org.distorted.external.RubikFiles;
19
import org.distorted.external.RubikScores;
20
import org.distorted.main.RubikActivity;
21
import org.distorted.objectlib.main.ObjectSignatures;
22
import org.distorted.objectlib.main.ObjectType;
23

    
24
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
25
import static org.distorted.objectlib.main.ObjectType.NUM_OBJECTS;
26
import static org.distorted.main.RubikActivity.SHOW_DOWNLOADED_DEBUG;
27
import static org.distorted.main.RubikActivity.SHOW_SOLVED_DEBUG;
28
import static org.distorted.screens.RubikScreenPlay.LEVELS_SHOWN;
29

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

    
32
public class RubikObjectList
33
{
34
  public static final int DEF_OBJECT= ObjectSignatures.CUBE_3;
35
  private static RubikObjectList mThis;
36
  private static int mNumObjects;
37
  private static int mNumExtras;
38
  private static ArrayList<RubikObject> mObjects;
39
  private static int mObject = DEF_OBJECT;
40

    
41
  public static class DownloadedObject
42
    {
43
    String shortName;
44
    boolean icon,object,extras,free;
45
    int numScrambles, objectMinor, extrasMinor;
46

    
47
    DownloadedObject(String sName, int scrambles, boolean isFree, int oMinor, int eMinor, boolean i, boolean o, boolean e)
48
      {
49
      shortName = sName;
50

    
51
      numScrambles= scrambles;
52
      free        = isFree;
53
      objectMinor = oMinor;
54
      extrasMinor = eMinor;
55

    
56
      icon   = i;
57
      object = o;
58
      extras = e;
59
      }
60
    }
61

    
62
  private static ArrayList<DownloadedObject> mDownloadedObjects;
63
  private static String mFreeSolvedObjects;
64
  private static String mFreeBoughtObjects;
65
  private static int mNumFreeSolved;
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
  private RubikObjectList()
70
    {
71
    mNumObjects    = 0;
72
    mNumExtras     = 0;
73
    mNumFreeSolved = 0;
74

    
75
    mObjects           = new ArrayList<>();
76
    mDownloadedObjects = new ArrayList<>();
77

    
78
    createBuiltinObjects();
79
    }
80

    
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

    
83
  private void createBuiltinObjects()
84
    {
85
    for(int i=0; i<NUM_OBJECTS; i++)
86
      {
87
      ObjectType type = ObjectType.getObject(i);
88
      RubikObject obj = new RubikObject(type);
89
      mObjects.add(obj);
90
      mNumObjects++;
91

    
92
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "creating local object "+type.name() );
93

    
94
      if( obj.hasExtras() )
95
        {
96
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "has extras "+mNumExtras );
97

    
98
        obj.setExtrasOrdinal(mNumExtras);
99
        mNumExtras++;
100
        }
101
      else
102
        {
103
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "no extras");
104
        }
105
      }
106
    }
107

    
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

    
110
  private static boolean internalAddDownloadedObject(DownloadedObject object)
111
    {
112
    String name = object.shortName;
113

    
114
    for(RubikObject ro : mObjects )
115
      if( ro.getLowerName().equals(name) )
116
        {
117
        return ro.updateObject(object);
118
        }
119

    
120
    RubikObject obj = new RubikObject(object);
121
    mObjects.add(obj);
122
    mNumObjects++;
123

    
124
    int numUnclaimed = getNumUnclaimedSolves();
125

    
126
    if( numUnclaimed>0 && !obj.isFree() )
127
      {
128
      String objname = obj.getUpperName();
129
      if( SHOW_SOLVED_DEBUG ) android.util.Log.e("D", "downloadedObject: "+objname+" making it solved. Unclaimed: "+numUnclaimed);
130
      solveObject(obj,objname);
131
      }
132

    
133
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "creating downloaded object "+obj.getUpperName() );
134

    
135
    if( obj.hasExtras() )
136
      {
137
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "has extras "+mNumExtras );
138

    
139
      obj.setExtrasOrdinal(mNumExtras);
140
      mNumExtras++;
141
      }
142
    else
143
      {
144
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "no extras");
145
      }
146

    
147
    return true;
148
    }
149

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

    
152
  public static int computeNumStars(int level)
153
    {
154
    return level>=LEVELS_SHOWN ? 50 : level;
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  private static void restoreFreedObjects(SharedPreferences preferences)
160
    {
161
    mFreeSolvedObjects = preferences.getString("rol_freeSolved", "");
162
    mFreeBoughtObjects = preferences.getString("rol_freeBought", "");
163

    
164
    if( SHOW_SOLVED_DEBUG )
165
      {
166
      android.util.Log.e("D", "freeSolved: "+mFreeSolvedObjects);
167
      android.util.Log.e("D", "freeBought: "+mFreeBoughtObjects);
168
      }
169

    
170
    if( mFreeBoughtObjects.length()>0 )
171
      {
172
      if( mFreeBoughtObjects.charAt(0)=='*' )
173
        {
174
        for(int i=0; i<mNumObjects; i++)
175
          {
176
          RubikObject o = mObjects.get(i);
177
          o.markFree();
178
          }
179
        }
180
      else
181
        {
182
        String[] objs = mFreeBoughtObjects.split(",");
183

    
184
        for( String obj : objs )
185
          {
186
          RubikObject o = getObject(obj);
187
          if( o!=null ) o.markFree();
188
          }
189
        }
190
      }
191

    
192
    if( mFreeSolvedObjects.length()>0 )
193
      {
194
      String[] objs = mFreeSolvedObjects.split(",");
195
      mNumFreeSolved = objs.length;
196

    
197
      for( String obj : objs )
198
        {
199
        RubikObject o = getObject(obj);
200
        if( o!=null ) o.markFree();
201
        }
202
      }
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  private static int getNumUnclaimedSolves()
208
    {
209
    RubikScores scores = RubikScores.getInstance();
210
    int numMAXes = scores.numberOfSolvedMAXes();
211
    return numMAXes-mNumFreeSolved;
212
    }
213

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

    
216
  private static int markAllSolvedAsFree()
217
    {
218
    RubikScores scores = RubikScores.getInstance();
219
    int numObjects = RubikObjectList.getNumObjects();
220
    int level = LEVELS_SHOWN;
221
    int ret = 0;
222

    
223
    for(int obj=0; obj<numObjects; obj++)
224
      {
225
      RubikObject object = getObject(obj);
226

    
227
      if( object!=null && !object.isFree() && scores.isSolved(obj,level) )
228
        {
229
        solveObject(object.getUpperName());
230
        ret++;
231
        }
232
      }
233

    
234
    return ret;
235
    }
236

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

    
239
  private static void markAsFree(int numToBeMarked)
240
    {
241
    int numObjects = RubikObjectList.getNumObjects();
242

    
243
    for(int obj=0; obj<numObjects && numToBeMarked>0; obj++)
244
      {
245
      RubikObject object = getObject(obj);
246

    
247
      if( object!=null && !object.isFree() )
248
        {
249
        solveObject(object.getUpperName());
250
        numToBeMarked--;
251
        }
252
      }
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

    
257
  public static boolean solveObject(RubikObject object, String shortName)
258
    {
259
    if( object!=null && !object.isFree() )
260
      {
261
      if( SHOW_SOLVED_DEBUG ) android.util.Log.e("D", "object "+shortName+" marked as solved");
262
      object.markFree();
263
      String add = mFreeSolvedObjects.length()==0 ? shortName : (","+shortName);
264
      mFreeSolvedObjects += add;
265
      mNumFreeSolved++;
266
      return true;
267
      }
268

    
269
    return false;
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273
// PUBLIC API
274

    
275
  public static boolean addDownloadedObject(Context context, String shortName, int numScrambles, boolean isFree, int objectMinor,
276
                                         int extrasMinor, boolean icon, boolean object, boolean extras)
277
    {
278
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "New downloaded object "+shortName+" icon="+icon+" object="+object+" extras="+extras);
279

    
280
    for( DownloadedObject obj : mDownloadedObjects )
281
      {
282
      if( obj.shortName.equals(shortName) )
283
        {
284
        obj.icon  |= icon;
285
        obj.object|= object;
286
        obj.extras|= extras;
287

    
288
        if( !obj.object ) objectMinor=-1;
289
        if( !obj.extras ) extrasMinor=-1;
290

    
291
        obj.objectMinor = objectMinor;
292
        obj.extrasMinor = extrasMinor;
293

    
294
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Updating downloaded object "+shortName+" icon="+obj.icon+" object="+obj.object+" extras="+obj.extras);
295

    
296
        try
297
          {
298
          RubikActivity ract = (RubikActivity)context;
299
          ract.reloadObject(shortName);
300
          }
301
        catch(Exception ex)
302
          {
303
          android.util.Log.e("D", "exception trying to reload object: "+ex.getMessage() );
304
          }
305

    
306
        return false;
307
        }
308
      }
309

    
310
    if( !object ) objectMinor=-1;
311
    if( !extras ) extrasMinor=-1;
312

    
313
    DownloadedObject obj = new DownloadedObject(shortName,numScrambles,isFree,objectMinor,extrasMinor,icon,object,extras);
314
    if ( internalAddDownloadedObject(obj) )
315
      {
316
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Adding new downloaded object "+shortName+" icon="+obj.icon+" object="+obj.object+" extras="+obj.extras);
317
      mDownloadedObjects.add(obj);
318
      return true;
319
      }
320
    else
321
      {
322
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "New downloaded object "+shortName+" is already built-in, deleting");
323
      RubikFiles files = RubikFiles.getInstance();
324
      files.deleteIcon(context,shortName);
325
      files.deleteJsonObject(context,shortName);
326
      files.deleteJsonExtras(context,shortName);
327
      return false;
328
      }
329
    }
330

    
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

    
333
  public static void setMeshState(int ordinal, int state)
334
    {
335
    if( ordinal>=0 && ordinal<mNumObjects ) mObjects.get(ordinal).setMeshState(state);
336
    }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339

    
340
  public static int getMeshState(int ordinal)
341
    {
342
    return (ordinal>=0 && ordinal<mNumObjects) ? mObjects.get(ordinal).getMeshState() : MESH_NICE;
343
    }
344

    
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
  public static void saveMeshState(SharedPreferences.Editor editor)
348
    {
349
    for(int i=0; i<mNumObjects; i++)
350
      {
351
      RubikObject obj = getObject(i);
352

    
353
      if( obj!=null )
354
        {
355
        String name = obj.getUpperName();
356
        editor.putInt("rol_"+name, obj.getMeshState() );
357
        }
358
      }
359
    }
360

    
361
///////////////////////////////////////////////////////////////////////////////////////////////////
362

    
363
  public static boolean allAlreadyBought()
364
    {
365
    return mFreeBoughtObjects.equals("*");
366
    }
367

    
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369

    
370
  public static boolean thereAreLockedObjects()
371
    {
372
    for(int i=0; i<mNumObjects; i++)
373
      {
374
      RubikObject o = mObjects.get(i);
375
      if( !o.isFree() ) return true;
376
      }
377

    
378
    return false;
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  public static boolean objectAlreadyBought(String shortName)
384
    {
385
    RubikObject o = getObject(shortName);
386
    return ( o!=null && o.isFree() );
387
    }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  public static void buyAll()
392
    {
393
    mFreeBoughtObjects = "*";
394
    if( SHOW_SOLVED_DEBUG ) android.util.Log.e("D", "all objects marked as bought");
395

    
396
    for(int i=0; i<mNumObjects; i++)
397
      {
398
      RubikObject o = mObjects.get(i);
399
      o.markFree();
400
      }
401
    }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
  public static boolean buyObject(String shortName)
406
    {
407
    RubikObject o = getObject(shortName);
408

    
409
    if( o!=null && !o.isFree() )
410
      {
411
      if( SHOW_SOLVED_DEBUG ) android.util.Log.e("D", "object "+shortName+" marked as bought");
412
      o.markFree();
413
      String add = mFreeBoughtObjects.length()==0 ? shortName : (","+shortName);
414
      mFreeBoughtObjects += add;
415
      return true;
416
      }
417

    
418
    return false;
419
    }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422

    
423
  public static boolean solveObject(String shortName)
424
    {
425
    RubikObject object = getObject(shortName);
426
    return solveObject(object,shortName);
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
  public static void savePreferences(SharedPreferences.Editor editor)
432
    {
433
    RubikObject obj = getObject(mObject);
434
    if( obj!=null ) editor.putString("rol_objName", obj.getUpperName() );
435

    
436
    int numDownloaded = mDownloadedObjects.size();
437

    
438
    if( numDownloaded>0 )
439
      {
440
      StringBuilder downloadedObjects = new StringBuilder();
441

    
442
      for(int i=0; i<numDownloaded; i++)
443
        {
444
        if( i>0 ) downloadedObjects.append(',');
445

    
446
        DownloadedObject object = mDownloadedObjects.get(i);
447
        downloadedObjects.append(object.shortName);
448
        downloadedObjects.append(' ');
449
        downloadedObjects.append(object.numScrambles);
450
        downloadedObjects.append(' ');
451
        downloadedObjects.append(object.objectMinor);
452
        downloadedObjects.append(' ');
453
        downloadedObjects.append(object.extrasMinor);
454
        downloadedObjects.append(' ');
455
        downloadedObjects.append(object.icon   ? "1":"0");
456
        downloadedObjects.append(' ');
457
        downloadedObjects.append(object.object ? "1":"0");
458
        downloadedObjects.append(' ');
459
        downloadedObjects.append(object.extras ? "1":"0");
460
        downloadedObjects.append(' ');
461
        downloadedObjects.append(object.free ? "true":"false");
462
        }
463

    
464
      String objects = downloadedObjects.toString();
465
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "saving: "+objects);
466
      editor.putString("rol_downloaded", objects );
467
      }
468
    else
469
      {
470
      editor.putString("rol_downloaded", "" );
471
      }
472

    
473
    editor.putString("rol_freeSolved", mFreeSolvedObjects);
474
    editor.putString("rol_freeBought", mFreeBoughtObjects);
475

    
476
    if( SHOW_SOLVED_DEBUG )
477
      {
478
      android.util.Log.e("D", "saving solved objects: "+mFreeSolvedObjects);
479
      android.util.Log.e("D", "saving bought objects: "+mFreeBoughtObjects);
480
      }
481
    }
482

    
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484

    
485
  public static void restorePreferences(Context context, SharedPreferences preferences, boolean justStarted)
486
    {
487
    if( mThis==null ) mThis = new RubikObjectList();
488

    
489
    String downloaded = preferences.getString("rol_downloaded","");
490

    
491
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", downloaded);
492

    
493
    if( !downloaded.equals(""))
494
      {
495
      String[] dObjects = downloaded.split(",");
496

    
497
      for(String dObj : dObjects)
498
        {
499
        String[] parts = dObj.split(" ");
500
        int length = parts.length;
501

    
502
        if( length==7 || length==8 )
503
          {
504
          String name = parts[0];
505
          String scra = parts[1];
506
          String objM = parts[2];
507
          String extM = parts[3];
508
          String icon = parts[4];
509
          String obje = parts[5];
510
          String extr = parts[6];
511
          boolean isFree = (length==7 || Boolean.parseBoolean(parts[7]));
512

    
513
          int scrambles = Integer.parseInt(scra);
514
          int oMinor    = Integer.parseInt(objM);
515
          int eMinor    = Integer.parseInt(extM);
516

    
517
          boolean bIcon = icon.equals("1");
518
          boolean bObje = obje.equals("1");
519
          boolean bExtr = extr.equals("1");
520

    
521
          addDownloadedObject(context,name,scrambles,isFree,oMinor,eMinor,bIcon,bObje,bExtr);
522
          }
523
        }
524
      }
525

    
526
    RubikObject object = getObject(DEF_OBJECT);
527
    String defName = object==null ? "CUBE_3" : object.getUpperName();
528
    String objName= preferences.getString("rol_objName",defName);
529
    mObject = getOrdinal(objName);
530
    if( mObject<0 || mObject>=mNumObjects ) mObject = DEF_OBJECT;
531

    
532
    if( justStarted) restoreFreedObjects(preferences);
533
    }
534

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

    
537
  public static void restoreMeshState(SharedPreferences preferences)
538
    {
539
    for(int i=0; i<mNumObjects; i++)
540
      {
541
      RubikObject obj = getObject(i);
542

    
543
      if( obj!=null )
544
        {
545
        String name  = obj.getUpperName();
546
        int meshState= preferences.getInt("rol_"+name,MESH_NICE);
547
        obj.setMeshState(meshState);
548
        }
549
      }
550
    }
551

    
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

    
554
  public static void setObjectFreeState()
555
    {
556
    int numUnclaimed = getNumUnclaimedSolves();
557

    
558
    if( numUnclaimed>0 )
559
      {
560
      int marked = markAllSolvedAsFree();
561
      int stillUnclaimed = numUnclaimed-marked;
562
      if( stillUnclaimed>0) markAsFree(stillUnclaimed);
563
      }
564
    }
565

    
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567

    
568
  public static boolean setCurrObject(int ordinal)
569
    {
570
    if( mObject!=ordinal )
571
      {
572
      mObject = ordinal;
573
      return true;
574
      }
575

    
576
    return false;
577
    }
578

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

    
581
  public static int getCurrObject()
582
    {
583
    return mObject;
584
    }
585

    
586
///////////////////////////////////////////////////////////////////////////////////////////////////
587

    
588
  public static String getCurrentName()
589
    {
590
    RubikObject object = mObjects.get(mObject);
591
    return object==null ? "" : object.getUpperName();
592
    }
593

    
594
///////////////////////////////////////////////////////////////////////////////////////////////////
595

    
596
  public static RubikObject getObject(int ordinal)
597
    {
598
    if( mThis==null ) mThis = new RubikObjectList();
599
    return ordinal>=0 && ordinal<mNumObjects ? mObjects.get(ordinal) : null;
600
    }
601

    
602
///////////////////////////////////////////////////////////////////////////////////////////////////
603

    
604
  public static RubikObject getObject(String shortUpperName)
605
    {
606
    if( mThis==null ) mThis = new RubikObjectList();
607

    
608
    for(int i=0; i<mNumObjects; i++)
609
      {
610
      RubikObject object = mObjects.get(i);
611
      if( object.getUpperName().equals(shortUpperName) )
612
        {
613
        return object;
614
        }
615
      }
616

    
617
    return null;
618
    }
619

    
620
///////////////////////////////////////////////////////////////////////////////////////////////////
621

    
622
  public static int getNumObjects()
623
    {
624
    if( mThis==null ) mThis = new RubikObjectList();
625
    return mNumObjects;
626
    }
627

    
628
///////////////////////////////////////////////////////////////////////////////////////////////////
629

    
630
  public static int getOrdinal(String name)
631
    {
632
    if( mThis==null ) mThis = new RubikObjectList();
633

    
634
    String lowerName = name.toLowerCase(Locale.ENGLISH);
635

    
636
    for(int i=0; i<mNumObjects; i++)
637
      {
638
      RubikObject obj = mObjects.get(i);
639
      if( obj.getLowerName().equals(lowerName) ) return i;
640
      }
641

    
642
    return -1;
643
    }
644

    
645
///////////////////////////////////////////////////////////////////////////////////////////////////
646

    
647
  public static int getNumExtrasObjects()
648
    {
649
    return mNumExtras;
650
    }
651

    
652
///////////////////////////////////////////////////////////////////////////////////////////////////
653

    
654
  public static int getNumTutorialObjects()
655
    {
656
    return mNumExtras;
657
    }
658

    
659
///////////////////////////////////////////////////////////////////////////////////////////////////
660

    
661
  public static int getObjectOrdinal(int extrasOrdinal)
662
    {
663
    for(int i=extrasOrdinal; i<mNumObjects; i++)
664
      {
665
      RubikObject object = getObject(i);
666
      int extOrd = object!=null ? object.getExtrasOrdinal() : -1;
667
      if( extOrd==extrasOrdinal ) return i;
668
      }
669

    
670
    return -1;
671
    }
672

    
673
///////////////////////////////////////////////////////////////////////////////////////////////////
674

    
675
  public static int getExtrasOrdinal(int objectOrdinal)
676
    {
677
    RubikObject object = getObject(objectOrdinal);
678
    return object!=null ? object.getExtrasOrdinal() : -1;
679
    }
680

    
681
///////////////////////////////////////////////////////////////////////////////////////////////////
682

    
683
  public static int getTutorialOrdinal(int objectOrdinal)
684
    {
685
    RubikObject object = getObject(objectOrdinal);
686
    return object!=null ? object.getExtrasOrdinal() : -1;
687
    }
688

    
689
///////////////////////////////////////////////////////////////////////////////////////////////////
690

    
691
  public static int getLocalObjectMinor(int objectOrdinal)
692
    {
693
    RubikObject object = getObject(objectOrdinal);
694
    return object!=null ? object.getObjectMinor() : -1;
695
    }
696

    
697
///////////////////////////////////////////////////////////////////////////////////////////////////
698

    
699
  public static int getLocalExtrasMinor(int objectOrdinal)
700
    {
701
    RubikObject object = getObject(objectOrdinal);
702
    return object!=null ? object.getExtrasMinor() : -1;
703
    }
704
}
(2-2/2)