Project

General

Profile

Download (39.1 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / json / JsonReader.java @ b63235a0

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
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.objectlib.json;
11

    
12
import java.io.BufferedReader;
13
import java.io.File;
14
import java.io.FileInputStream;
15
import java.io.IOException;
16
import java.io.InputStream;
17
import java.io.InputStreamReader;
18
import java.nio.charset.StandardCharsets;
19

    
20
import android.content.Context;
21

    
22
import org.distorted.objectlib.helpers.ObjectFaceShape;
23
import org.distorted.objectlib.helpers.ObjectSignature;
24
import org.distorted.objectlib.helpers.ObjectStickerOverride;
25
import org.distorted.objectlib.main.Cubit;
26
import org.distorted.objectlib.objects.TwistyBandagedCuboid;
27
import org.json.JSONArray;
28
import org.json.JSONException;
29
import org.json.JSONObject;
30

    
31
import org.distorted.library.type.Static3D;
32
import org.distorted.library.type.Static4D;
33

    
34
import org.distorted.objectlib.helpers.ObjectShape;
35
import org.distorted.objectlib.helpers.ObjectSticker;
36
import org.distorted.objectlib.scrambling.ScrambleState;
37
import org.distorted.objectlib.main.ObjectType;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
public class JsonReader
42
{
43
  private ScrambleState[] mStates;
44
  private int[][] mSolvedQuats;
45
  private Static4D[] mQuats;
46
  private int mSolvedFuncIndex;
47
  private int mNumStickerTypes;
48
  private float[][] mCuts;
49
  private boolean[][] mLayerRotatable;
50
  private int mMovementType, mMovementSplit;
51
  private int[][][] mEnabled;
52
  private float[] mDist3D;
53
  private int mNumCubitFaces, mNumFaces, mNumFaceColors;
54
  private float[][] mPositions;
55
  private ObjectShape[] mShapes;
56
  private ObjectFaceShape[] mFaceShapes;
57
  private Static4D[] mCubitQuats;
58
  private int mNumCubitVariants;
59
  private int[] mCubitVariant;
60
  private int[][] mVariantFaceColor, mVariantFaceIsOuter, mCubitFaceColor;
61
  private ObjectSticker[] mObjectSticker;
62
  private Static3D[] mAxis;
63
  private int[][] mBasicAngle;
64
  private String mLongName, mShortName, mInventor;
65
  private int mYearOfInvention, mComplexity;
66
  private int[] mNumLayers;
67
  private float mSize;
68
  private int mScrambleType, mNumScrambles;
69
  private boolean mIsFree;
70
  private int[] mColor;
71
  private int mInternalColor;
72
  private boolean mResetMaps;
73
  private String mTutorialObject;
74
  private String[][] mTutorials;
75
  private ObjectSignature mSignature;
76
  private int[] mCubitType;
77
  private float[][] mCubitRowOffset;
78
  private ObjectStickerOverride[] mStickerOverrides;
79
  private float mPillowCoeff;
80

    
81
  private static JsonReader mThis;
82

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

    
85
  private JsonReader()
86
    {
87
    }
88

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90

    
91
  public static JsonReader getInstance()
92
    {
93
    if( mThis==null ) mThis = new JsonReader();
94
    return mThis;
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98

    
99
  private void parseMetadata1(JSONObject object) throws JSONException
100
    {
101
    mLongName        = object.getString("longname");
102
    mShortName       = object.getString("shortname");
103
    mInventor        = object.getString("inventor");
104
    mYearOfInvention = object.getInt("year");
105
    mComplexity      = object.getInt("complexity");
106
    mSize            = (float)object.getDouble("size");
107
    mNumScrambles    = object.getInt("scrambles");
108
    mResetMaps       = object.getBoolean("resetmaps");
109
    mNumFaces        = object.getInt("num_faces");
110
    mIsFree          = true;
111

    
112
    try
113
      {
114
      long signature = object.getLong("signature");
115
      mSignature = new ObjectSignature(signature);
116
      }
117
    catch(JSONException ex)
118
      {
119
      // objects older than Feb 2022 do not have the 'signature' field. They all use the ObjectType.ordinal
120
      // as their signature.
121
      long signature = ObjectType.getOrdinal(mShortName);
122
      mSignature = new ObjectSignature(signature);
123
      }
124
    }
125

    
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127

    
128
  private void parseMetadata2or3or4(JSONObject object) throws JSONException
129
    {
130
    mLongName        = object.getString("longname");
131
    mShortName       = object.getString("shortname");
132
    mInventor        = object.getString("inventor");
133
    mYearOfInvention = object.getInt("year");
134
    mComplexity      = object.getInt("complexity");
135
    mSize            = (float)object.getDouble("size");
136
    mNumScrambles    = object.getInt("scrambles");
137
    mResetMaps       = object.getBoolean("resetmaps");
138
    mNumFaces        = object.getInt("num_faces");
139
    mIsFree          = true;
140

    
141
    try
142
      {
143
      long signature1 = object.getLong("signature1");
144
      long signature2 = object.getLong("signature2");
145
      long signature3 = object.getLong("signature3");
146
      long[] signature= new long[] {signature1,signature2,signature3};
147

    
148
      switch( TwistyBandagedCuboid.getType(mShortName,mLongName) )
149
        {
150
        case 0: mSignature = new ObjectSignature(signature); break;
151
        case 1: mSignature = new ObjectSignature(mShortName,signature); break;
152
        case 2: mSignature = new ObjectSignature("333",signature); break;
153
        }
154
      }
155
    catch(JSONException ex)
156
      {
157
      long signature = object.getLong("signature");
158
      mSignature = new ObjectSignature(signature);
159
      }
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

    
164
  private void parseMetadata5or6(JSONObject object) throws JSONException
165
    {
166
    mLongName        = object.getString("longname");
167
    mShortName       = object.getString("shortname");
168
    mInventor        = object.getString("inventor");
169
    mYearOfInvention = object.getInt("year");
170
    mComplexity      = object.getInt("complexity");
171
    mSize            = (float)object.getDouble("size");
172
    mNumScrambles    = object.getInt("scrambles");
173
    mResetMaps       = object.getBoolean("resetmaps");
174
    mNumFaces        = object.getInt("num_faces");
175

    
176
    try
177
      {
178
      JSONArray sigArray = object.getJSONArray("signature");
179
      int size = sigArray.length();
180
      long[] signature = new long[size];
181
      for(int i=0; i<size; i++) signature[i] = sigArray.getLong(i);
182

    
183
      switch( TwistyBandagedCuboid.getType(mShortName,mLongName) )
184
        {
185
        case 0: mSignature = new ObjectSignature(signature); break;
186
        case 1: mSignature = new ObjectSignature(mShortName,signature); break;
187
        case 2: mSignature = new ObjectSignature("333",signature); break;
188
        }
189
      }
190
    catch(JSONException ex)
191
      {
192
      long signature = object.getLong("signature");
193
      mSignature = new ObjectSignature(signature);
194
      }
195

    
196
    mIsFree = object.optBoolean("free", true);
197
    }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
  private void parseCubits(JSONArray object) throws JSONException
202
    {
203
    int numCubits = object.length();
204

    
205
    mCubitQuats     = new Static4D[numCubits];
206
    mCubitVariant   = new int[numCubits];
207
    mPositions      = new float[numCubits][];
208
    mCubitFaceColor = new int[numCubits][];
209
    mCubitType      = new int[numCubits];
210
    mCubitRowOffset = new float[numCubits][];
211

    
212
    for(int i=0; i<numCubits; i++)
213
      {
214
      JSONObject jsonCubit = object.getJSONObject(i);
215

    
216
      float qx = (float)jsonCubit.getDouble("qx");
217
      float qy = (float)jsonCubit.getDouble("qy");
218
      float qz = (float)jsonCubit.getDouble("qz");
219
      float qw = (float)jsonCubit.getDouble("qw");
220

    
221
      mCubitQuats[i] = new Static4D(qx,qy,qz,qw);
222
      mCubitVariant[i] = jsonCubit.getInt("variant");
223

    
224
      JSONArray jsonCenter = jsonCubit.getJSONArray("centers");
225
      int numCenter = jsonCenter.length();
226
      mPositions[i] = new float[numCenter];
227
      for(int j=0; j<numCenter; j++) mPositions[i][j] = (float)jsonCenter.getDouble(j);
228

    
229
      JSONArray jsonColor  = jsonCubit.getJSONArray("colors");
230
      int numColor = jsonColor.length();
231
      mCubitFaceColor[i] = new int[numColor];
232
      for(int j=0; j<numColor; j++) mCubitFaceColor[i][j] = jsonColor.getInt(j);
233

    
234
      mCubitType[i] = jsonCubit.optInt("type", Cubit.TYPE_NORMAL);
235
      float xoff = (float)jsonCubit.optDouble("offsetX", 0 );
236
      float yoff = (float)jsonCubit.optDouble("offsetY", 0 );
237
      float zoff = (float)jsonCubit.optDouble("offsetZ", 0 );
238
      mCubitRowOffset[i] = new float[] {xoff,yoff,zoff};
239
      }
240
    }
241

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

    
244
  private void parseShapes(JSONArray object) throws JSONException
245
    {
246
    mNumCubitVariants     = object.length();
247
    mVariantFaceColor     = new int[mNumCubitVariants][];
248
    mVariantFaceIsOuter   = new int[mNumCubitVariants][];
249
    mShapes               = new ObjectShape[mNumCubitVariants];
250
    mFaceShapes           = new ObjectFaceShape[mNumCubitVariants];
251
    float[][][] verts     = new float[mNumCubitVariants][][];
252
    float[][][] bands     = new float[mNumCubitVariants][][];
253
    float[][][] corners   = new float[mNumCubitVariants][][];
254
    float[][][] centers   = new float[mNumCubitVariants][][];
255
    float[][] convexity   = new float[mNumCubitVariants][];
256
    int[][] cornerIndices = new int[mNumCubitVariants][];
257
    int[][] centerIndices = new int[mNumCubitVariants][];
258
    int[][] bandIndices   = new int[mNumCubitVariants][];
259
    int[][][] vertIndices = new int[mNumCubitVariants][][];
260

    
261
    mNumCubitFaces = -1;
262

    
263
    for(int i=0; i<mNumCubitVariants; i++)
264
      {
265
      JSONObject jsonShape = object.getJSONObject(i);
266

    
267
      ////// vertices /////////////////////////////////////////////////
268
      JSONArray jsonVertices= jsonShape.getJSONArray("vertices");
269
      int numVertices = jsonVertices.length();
270
      verts[i] = new float[numVertices][3];
271
      cornerIndices[i] = new int[numVertices];
272
      centerIndices[i] = new int[numVertices];
273

    
274
      for(int j=0; j<numVertices; j++)
275
        {
276
        JSONObject vert = jsonVertices.getJSONObject(j);
277
        verts[i][j][0] = (float)vert.getDouble("x");
278
        verts[i][j][1] = (float)vert.getDouble("y");
279
        verts[i][j][2] = (float)vert.getDouble("z");
280
        cornerIndices[i][j] = vert.getInt("cornerIndex");
281
        centerIndices[i][j] = vert.getInt("centerIndex");
282
        }
283

    
284
      ////// faces ////////////////////////////////////////////////////
285
      JSONArray jsonFaces= jsonShape.getJSONArray("faces");
286
      int numFaces = jsonFaces.length();
287
      mVariantFaceColor[i]   = new int[numFaces];
288
      mVariantFaceIsOuter[i] = new int[numFaces];
289
      bandIndices[i] = new int[numFaces];
290
      vertIndices[i] = new int[numFaces][];
291

    
292
      if( mNumCubitFaces<numFaces ) mNumCubitFaces=numFaces;
293

    
294
      for(int j=0; j<numFaces; j++)
295
        {
296
        JSONObject jsonFace = jsonFaces.getJSONObject(j);
297
        mVariantFaceColor[i][j]   = jsonFace.getInt("sticker");
298
        mVariantFaceIsOuter[i][j] = jsonFace.optInt("isOuter",0);
299
        bandIndices[i][j] = jsonFace.getInt("bandIndex");
300
        JSONArray vertices = jsonFace.getJSONArray("vertexIndices");
301
        int numV = vertices.length();
302
        vertIndices[i][j] = new int[numV];
303
        for(int k=0; k<numV; k++) vertIndices[i][j][k] = vertices.getInt(k);
304
        }
305

    
306
      ////// bands ////////////////////////////////////////////////////
307
      JSONArray jsonBands= jsonShape.getJSONArray("bands");
308
      int numBands = jsonBands.length();
309
      bands[i] = new float[numBands][7];
310

    
311
      for(int j=0; j<numBands; j++)
312
        {
313
        JSONObject jsonBand = jsonBands.getJSONObject(j);
314

    
315
        bands[i][j][0] = (float)jsonBand.getDouble("height");
316
        bands[i][j][1] = (float)jsonBand.getDouble("angle");
317
        bands[i][j][2] = (float)jsonBand.getDouble("distanceToCenter");
318
        bands[i][j][3] = (float)jsonBand.getDouble("distanceToFlat");
319
        bands[i][j][4] = (float)jsonBand.getDouble("numOfBands");
320
        bands[i][j][5] = (float)jsonBand.getDouble("extraI");
321
        bands[i][j][6] = (float)jsonBand.getDouble("extraJ");
322
        }
323

    
324
      ////// cornerPush ///////////////////////////////////////////////
325
      JSONArray jsonCornerPush= jsonShape.optJSONArray("cornerPush");
326

    
327
      if( jsonCornerPush!=null )
328
        {
329
        int numCornerP = jsonCornerPush.length();
330
        corners[i] = new float[numCornerP][2];
331

    
332
        for(int j=0; j<numCornerP; j++)
333
          {
334
          JSONObject jsonC = jsonCornerPush.getJSONObject(j);
335
          corners[i][j][0] = (float)jsonC.getDouble("strength");
336
          corners[i][j][1] = (float)jsonC.getDouble("radius");
337
          }
338
        }
339

    
340
      ////// centerPush ///////////////////////////////////////////////
341
      JSONArray jsonCenterPush= jsonShape.optJSONArray("centerPush");
342

    
343
      if( jsonCenterPush!=null )
344
        {
345
        int numCenterP = jsonCenterPush.length();
346
        centers[i] = new float[numCenterP][3];
347

    
348
        for(int j=0; j<numCenterP; j++)
349
          {
350
          JSONObject jsonC = jsonCenterPush.getJSONObject(j);
351
          centers[i][j][0] = (float)jsonC.getDouble("x");
352
          centers[i][j][1] = (float)jsonC.getDouble("y");
353
          centers[i][j][2] = (float)jsonC.getDouble("z");
354
          }
355
        }
356

    
357
      ////// convexity ///////////////////////////////////////////////
358
      JSONObject jsonConvexity = jsonShape.optJSONObject("convexity");
359

    
360
      if( jsonConvexity!=null )
361
        {
362
        convexity[i] = new float[3];
363
        convexity[i][0] = (float)jsonConvexity.getDouble("x");
364
        convexity[i][1] = (float)jsonConvexity.getDouble("y");
365
        convexity[i][2] = (float)jsonConvexity.getDouble("z");
366
        }
367
      }
368

    
369
    for(int i=0; i<mNumCubitVariants; i++)
370
      {
371
      mShapes[i] = new ObjectShape(verts[i],vertIndices[i]);
372
      mFaceShapes[i] = new ObjectFaceShape(bands[i],bandIndices[i],corners[i],cornerIndices[i],centers[i],centerIndices[i],convexity[i] );
373
      }
374
    }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

    
378
  private void parseStickers(JSONArray object) throws JSONException
379
    {
380
    mNumStickerTypes = object.length();
381
    mObjectSticker = new ObjectSticker[mNumStickerTypes];
382

    
383
    for(int i=0; i<mNumStickerTypes; i++)
384
      {
385
      JSONObject sticker = object.getJSONObject(i);
386
      float stroke = (float)sticker.getDouble("stroke");
387
      JSONArray vertices = sticker.getJSONArray("vertices");
388
      int numVertices = vertices.length();
389

    
390
      float[] coords     = new float[2*numVertices];
391
      float[] curvatures = new float[numVertices];
392
      float[] radii      = new float[numVertices];
393

    
394
      for(int j=0; j<numVertices; j++)
395
        {
396
        JSONObject vertex = vertices.getJSONObject(j);
397

    
398
        coords[2*j  ] = (float)vertex.getDouble("x");
399
        coords[2*j+1] = (float)vertex.getDouble("y");
400
        curvatures[j] = (float)vertex.getDouble("angle");
401
        radii[j]      = (float)vertex.getDouble("radius");
402
        }
403

    
404
      mObjectSticker[i] = new ObjectSticker(coords,curvatures,radii,stroke);
405
      }
406
    }
407

    
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409

    
410
  private void parseOverrides(JSONArray object) throws JSONException
411
    {
412
    if( object!=null )
413
      {
414
      int numOverrides = object.length();
415
      mStickerOverrides= new ObjectStickerOverride[numOverrides];
416

    
417
      for(int i=0; i<numOverrides; i++)
418
        {
419
        JSONObject override  = object.getJSONObject(i);
420
        JSONArray cubitArray = override.getJSONArray("cubitfaces");
421
        int color = override.getInt("color");
422
        int numCubits = cubitArray.length();
423
        int[] cubitface = new int[numCubits];
424
        for(int j=0; j<numCubits; j++) cubitface[j] = cubitArray.getInt(j);
425
        mStickerOverrides[i] = new ObjectStickerOverride(cubitface,color);
426
        }
427
      }
428
    else
429
      {
430
      mStickerOverrides = null;
431
      }
432
    }
433

    
434
///////////////////////////////////////////////////////////////////////////////////////////////////
435

    
436
  private void parseMesh(JSONObject object) throws JSONException
437
    {
438
    JSONArray cubits   = object.getJSONArray("cubits");
439
    parseCubits(cubits);
440
    JSONArray shapes   = object.getJSONArray("shapes");
441
    parseShapes(shapes);
442
    JSONArray stickers = object.getJSONArray("stickers");
443
    parseStickers(stickers);
444

    
445
    JSONArray overrides= object.optJSONArray("overrides");
446
    parseOverrides(overrides);
447

    
448
    mPillowCoeff = (float)object.optDouble("pillow",1.0);
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  private void parseAxis1(JSONArray object) throws JSONException
454
    {
455
    int numAxis = object.length();
456

    
457
    mBasicAngle     = new int[numAxis][];
458
    mAxis           = new Static3D[numAxis];
459
    mCuts           = new float[numAxis][];
460
    mLayerRotatable = new boolean[numAxis][];
461
    mNumLayers      = new int[numAxis];
462

    
463
    for(int i=0; i<numAxis; i++)
464
      {
465
      JSONObject jsonAx = object.getJSONObject(i);
466

    
467
      float x = (float)jsonAx.getDouble("x");
468
      float y = (float)jsonAx.getDouble("y");
469
      float z = (float)jsonAx.getDouble("z");
470

    
471
      mAxis[i] = new Static3D(x,y,z);
472

    
473
      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
474
      int numCuts = jsonCuts.length();
475
      mCuts[i] = new float[numCuts];
476
      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
477

    
478
      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
479
      int numRota = jsonRota.length();
480
      mLayerRotatable[i] = new boolean[numRota];
481
      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
482

    
483
      mBasicAngle[i] = new int[numRota];
484
      int basicAngle = jsonAx.getInt("basicAngle");
485
      for(int j=0; j<numRota; j++) mBasicAngle[i][j] = basicAngle;
486

    
487
      mNumLayers[i] = numRota;
488
      }
489
    }
490

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

    
493
  private void parseAxis2or3or4or5or6(JSONArray object) throws JSONException
494
    {
495
    int numAxis = object.length();
496

    
497
    mBasicAngle     = new int[numAxis][];
498
    mAxis           = new Static3D[numAxis];
499
    mCuts           = new float[numAxis][];
500
    mLayerRotatable = new boolean[numAxis][];
501
    mNumLayers      = new int[numAxis];
502

    
503
    for(int i=0; i<numAxis; i++)
504
      {
505
      JSONObject jsonAx = object.getJSONObject(i);
506

    
507
      float x = (float)jsonAx.getDouble("x");
508
      float y = (float)jsonAx.getDouble("y");
509
      float z = (float)jsonAx.getDouble("z");
510

    
511
      mAxis[i] = new Static3D(x,y,z);
512

    
513
      JSONArray jsonAngles = jsonAx.getJSONArray("basicAngles");
514
      int numAngles = jsonAngles.length();
515
      mBasicAngle[i] = new int[numAngles];
516
      for(int j=0; j<numAngles; j++) mBasicAngle[i][j] = jsonAngles.getInt(j);
517

    
518
      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
519
      int numCuts = jsonCuts.length();
520
      mCuts[i] = new float[numCuts];
521
      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
522

    
523
      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
524
      int numRota = jsonRota.length();
525
      mLayerRotatable[i] = new boolean[numRota];
526
      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
527

    
528
      mNumLayers[i] = numRota;
529
      }
530
    }
531

    
532
///////////////////////////////////////////////////////////////////////////////////////////////////
533

    
534
  private void parseQuats(JSONArray object) throws JSONException
535
    {
536
    int numQuats = object.length();
537
    mQuats = new Static4D[numQuats];
538

    
539
    for(int i=0; i<numQuats; i++)
540
      {
541
      JSONObject jsonQuat = object.getJSONObject(i);
542

    
543
      float x = (float)jsonQuat.getDouble("x");
544
      float y = (float)jsonQuat.getDouble("y");
545
      float z = (float)jsonQuat.getDouble("z");
546
      float w = (float)jsonQuat.getDouble("w");
547

    
548
      mQuats[i] = new Static4D(x,y,z,w);
549
      }
550
    }
551

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

    
554
  private void parseScrambling(JSONObject object) throws JSONException
555
    {
556
    mScrambleType = object.getInt("scrambleType");
557

    
558
    if( mScrambleType==0 )
559
      {
560
      JSONArray jsonStates = object.getJSONArray("scrambleStates");
561
      int numStates = jsonStates.length();
562
      mStates = new ScrambleState[numStates];
563

    
564
      for(int i=0; i<numStates; i++)
565
        {
566
        JSONArray jsonState = jsonStates.getJSONArray(i);
567
        int numAxis = jsonState.length();
568
        int[][] scramblingData = new int[numAxis][];
569

    
570
        for(int j=0; j<numAxis; j++)
571
          {
572
          JSONArray jsonData = jsonState.getJSONArray(j);
573
          int numData = jsonData.length();
574
          scramblingData[j] = new int[numData];
575
          for(int k=0; k<numData; k++) scramblingData[j][k] = jsonData.getInt(k);
576
          }
577

    
578
        mStates[i] = new ScrambleState(scramblingData);
579
        }
580
      }
581
    }
582

    
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584

    
585
  private void parseTouchcontrol(JSONObject object) throws JSONException
586
    {
587
    mMovementType = object.getInt("movementType");
588
    mMovementSplit= object.getInt("movementSplit");
589

    
590
    try
591
      {
592
      JSONArray jsonEnabled = object.getJSONArray("enabledAxis");
593
      int numFace = jsonEnabled.length();
594

    
595
      mEnabled = new int[numFace][][];
596

    
597
      for(int i=0; i<numFace; i++)
598
        {
599
        JSONArray jsonSection = jsonEnabled.getJSONArray(i);
600
        int numSection = jsonSection.length();
601
        mEnabled[i] = new int[numSection][];
602

    
603
        for(int j=0; j<numSection; j++)
604
          {
605
          JSONArray jsonAx = jsonSection.getJSONArray(j);
606
          int numAxis = jsonAx.length();
607
          mEnabled[i][j] = new int[numAxis];
608
          for(int k=0; k<numAxis; k++) mEnabled[i][j][k] = jsonAx.getInt(k);
609
          }
610
        }
611
      }
612
    catch( JSONException ex )
613
      {
614
      // ignore, the object does not have to have 'enabledAxis' defined at all.
615
      }
616

    
617
    try
618
      {
619
      JSONArray jsonDist = object.getJSONArray("dist3D");
620
      int num = jsonDist.length();
621
      mDist3D = new float[num];
622
      for(int j=0; j<num; j++) mDist3D[j] = (float)jsonDist.getDouble(j);
623
      }
624
    catch( JSONException ex )
625
      {
626
      // ignore, the object does not have a 'dist3D' which is possible.
627
      }
628
    }
629

    
630
///////////////////////////////////////////////////////////////////////////////////////////////////
631

    
632
  private void parseColors(JSONArray object) throws JSONException
633
    {
634
    mNumFaceColors = object.length()-1;
635

    
636
    mColor = new int[mNumFaceColors];
637
    for(int i=0; i<mNumFaceColors; i++) mColor[i] = object.getInt(i);
638

    
639
    mInternalColor = object.getInt(mNumFaceColors);
640
    }
641

    
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643

    
644
  private void parseSolved(JSONObject solved) throws JSONException
645
    {
646
    mSolvedFuncIndex = solved.getInt("functionIndex");
647

    
648
    try
649
      {
650
      JSONArray groupArray= solved.getJSONArray("groups");
651
      int numGroups = groupArray.length();
652
      mSolvedQuats  = new int[numGroups][];
653

    
654
      for(int i=0; i<numGroups; i++)
655
        {
656
        JSONArray groupElements = groupArray.getJSONArray(i);
657
        int groupSize = groupElements.length();
658
        mSolvedQuats[i] = new int[groupSize];
659
        for(int j=0; j<groupSize; j++) mSolvedQuats[i][j] = groupElements.getInt(j);
660
        }
661
      }
662
    catch( JSONException ex )
663
      {
664
      // ignore, the object does not have to have an array of solved groups.
665
      }
666
    }
667

    
668
///////////////////////////////////////////////////////////////////////////////////////////////////
669

    
670
  private void parseVersion1(JSONObject object) throws JSONException
671
    {
672
    JSONObject metadata    = object.getJSONObject("metadata");
673
    parseMetadata1(metadata);
674
    JSONObject mesh        = object.getJSONObject("mesh");
675
    parseMesh(mesh);
676
    JSONArray axis         = object.getJSONArray("axis");
677
    parseAxis1(axis);
678
    JSONArray quats        = object.getJSONArray("quats");
679
    parseQuats(quats);
680
    JSONObject scrambling  = object.getJSONObject("scrambling");
681
    parseScrambling(scrambling);
682
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
683
    parseTouchcontrol(touchcontrol);
684
    JSONArray colors       = object.getJSONArray("colors");
685
    parseColors(colors);
686
    JSONObject solved      = object.getJSONObject("solved");
687
    parseSolved(solved);
688
    }
689

    
690
///////////////////////////////////////////////////////////////////////////////////////////////////
691

    
692
  private void parseVersion2or3or4(JSONObject object) throws JSONException
693
    {
694
    JSONObject metadata    = object.getJSONObject("metadata");
695
    parseMetadata2or3or4(metadata);
696
    JSONObject mesh        = object.getJSONObject("mesh");
697
    parseMesh(mesh);
698
    JSONArray axis         = object.getJSONArray("axis");
699
    parseAxis2or3or4or5or6(axis);
700
    JSONArray quats        = object.getJSONArray("quats");
701
    parseQuats(quats);
702
    JSONObject scrambling  = object.getJSONObject("scrambling");
703
    parseScrambling(scrambling);
704
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
705
    parseTouchcontrol(touchcontrol);
706
    JSONArray colors       = object.getJSONArray("colors");
707
    parseColors(colors);
708
    JSONObject solved      = object.getJSONObject("solved");
709
    parseSolved(solved);
710
    }
711

    
712
///////////////////////////////////////////////////////////////////////////////////////////////////
713

    
714
  private void parseVersion5or6(JSONObject object) throws JSONException
715
    {
716
    JSONObject metadata    = object.getJSONObject("metadata");
717
    parseMetadata5or6(metadata);
718
    JSONObject mesh        = object.getJSONObject("mesh");
719
    parseMesh(mesh);
720
    JSONArray axis         = object.getJSONArray("axis");
721
    parseAxis2or3or4or5or6(axis);
722
    JSONArray quats        = object.getJSONArray("quats");
723
    parseQuats(quats);
724
    JSONObject scrambling  = object.getJSONObject("scrambling");
725
    parseScrambling(scrambling);
726
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
727
    parseTouchcontrol(touchcontrol);
728
    JSONArray colors       = object.getJSONArray("colors");
729
    parseColors(colors);
730
    JSONObject solved      = object.getJSONObject("solved");
731
    parseSolved(solved);
732
    }
733

    
734
///////////////////////////////////////////////////////////////////////////////////////////////////
735

    
736
  private void parseVersion1Tutorial(JSONObject object) throws JSONException
737
    {
738
    mTutorialObject = object.getString("object");
739
    JSONArray tuts= object.getJSONArray("tutorials");
740

    
741
    int len = tuts.length();
742
    mTutorials = new String[len][4];
743

    
744
    for(int i=0; i<len; i++)
745
      {
746
      JSONObject tut = tuts.getJSONObject(i);
747
      mTutorials[i][0] = tut.getString("language");
748
      mTutorials[i][1] = tut.getString("link");
749
      mTutorials[i][2] = tut.getString("title");
750
      mTutorials[i][3] = tut.getString("author");
751
      }
752
    }
753

    
754
///////////////////////////////////////////////////////////////////////////////////////////////////
755

    
756
  private void parseVersion1Metadata(JSONObject object) throws JSONException
757
    {
758
    JSONObject metadata = object.getJSONObject("metadata");
759
    parseMetadata1(metadata);
760
    }
761

    
762
///////////////////////////////////////////////////////////////////////////////////////////////////
763

    
764
  private void parseVersion2or3or4Metadata(JSONObject object) throws JSONException
765
    {
766
    JSONObject metadata = object.getJSONObject("metadata");
767
    parseMetadata2or3or4(metadata);
768
    }
769

    
770
///////////////////////////////////////////////////////////////////////////////////////////////////
771

    
772
  private void parseVersion5or6Metadata(JSONObject object) throws JSONException
773
    {
774
    JSONObject metadata = object.getJSONObject("metadata");
775
    parseMetadata5or6(metadata);
776
    }
777

    
778
///////////////////////////////////////////////////////////////////////////////////////////////////
779

    
780
  public void parseJsonFile(InputStream jsonStream) throws JSONException, IOException
781
    {
782
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
783
    StringBuilder contents = new StringBuilder();
784
    String tmp;
785

    
786
    while( (tmp = br.readLine()) != null) contents.append(tmp);
787
    br.close();
788
    jsonStream.close();
789

    
790
    JSONObject object = new JSONObject(contents.toString());
791
    int major = object.getInt("major");
792

    
793
    if( major==1 )
794
      {
795
      parseVersion1(object);
796
      }
797
    else if( major==2 || major==3 || major==4 )
798
      {
799
      parseVersion2or3or4(object);
800
      }
801
    else if( major==5 || major==6 )
802
      {
803
      parseVersion5or6(object);
804
      }
805
    else
806
      {
807
      android.util.Log.e("readJsonFile", "Unknown version "+major);
808
      }
809
    }
810

    
811
///////////////////////////////////////////////////////////////////////////////////////////////////
812

    
813
  public void parseJsonFileMetadata(InputStream jsonStream) throws JSONException, IOException
814
    {
815
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
816
    StringBuilder contents = new StringBuilder();
817
    String tmp;
818

    
819
    while( (tmp = br.readLine()) != null) contents.append(tmp);
820
    br.close();
821
    jsonStream.close();
822

    
823
    JSONObject object = new JSONObject(contents.toString());
824
    int major = object.getInt("major");
825

    
826
    if( major==1 )
827
      {
828
      parseVersion1Metadata(object);
829
      }
830
    else if( major==2 || major==3 || major==4 )
831
      {
832
      parseVersion2or3or4Metadata(object);
833
      }
834
    else if( major==5 || major==6 )
835
      {
836
      parseVersion5or6Metadata(object);
837
      }
838
    else
839
      {
840
      android.util.Log.e("readJsonFileQuick", "Unknown version "+major);
841
      }
842
    }
843

    
844
///////////////////////////////////////////////////////////////////////////////////////////////////
845

    
846
  public void readNumScramblesAndIsFree(Context context, String fileName) throws IOException, JSONException
847
    {
848
    File file = new File(context.getFilesDir(), fileName);
849
    InputStream stream = new FileInputStream(file);
850
    BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
851

    
852
    StringBuilder contents = new StringBuilder();
853
    String tmp;
854
    while( (tmp = br.readLine()) != null) contents.append(tmp);
855
    br.close();
856
    stream.close();
857

    
858
    JSONObject object = new JSONObject(contents.toString());
859
    JSONObject metadata = object.getJSONObject("metadata");
860
    mNumScrambles = metadata.getInt("scrambles");
861
    mIsFree       = metadata.optBoolean("free",true);
862
    }
863

    
864
///////////////////////////////////////////////////////////////////////////////////////////////////
865

    
866
  public void parseJsonTutorial(InputStream jsonStream) throws IOException, JSONException
867
    {
868
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
869
    StringBuilder contents = new StringBuilder();
870
    String tmp;
871

    
872
    while( (tmp = br.readLine()) != null) contents.append(tmp);
873
    br.close();
874
    jsonStream.close();
875

    
876
    JSONObject object = new JSONObject(contents.toString());
877
    int major = object.getInt("major");
878

    
879
    if( major==1 )
880
      {
881
      parseVersion1Tutorial(object);
882
      }
883
    else
884
      {
885
      android.util.Log.e("readJsonFile", "Unknown tutorial version "+major);
886
      }
887
    }
888

    
889
///////////////////////////////////////////////////////////////////////////////////////////////////
890

    
891
  public ScrambleState[] getScrambleStates()
892
    {
893
    return mStates;
894
    }
895

    
896
///////////////////////////////////////////////////////////////////////////////////////////////////
897

    
898
  public int[][] getSolvedQuats()
899
    {
900
    return mSolvedQuats;
901
    }
902

    
903
///////////////////////////////////////////////////////////////////////////////////////////////////
904

    
905
  public Static4D[] getQuats()
906
    {
907
    return mQuats;
908
    }
909

    
910
///////////////////////////////////////////////////////////////////////////////////////////////////
911

    
912
  public int getSolvedFunctionIndex()
913
    {
914
    return mSolvedFuncIndex;
915
    }
916

    
917
///////////////////////////////////////////////////////////////////////////////////////////////////
918

    
919
  public int getNumStickerTypes()
920
    {
921
    return mNumStickerTypes;
922
    }
923

    
924
///////////////////////////////////////////////////////////////////////////////////////////////////
925

    
926
  public float[][] getCuts()
927
    {
928
    return mCuts;
929
    }
930

    
931
///////////////////////////////////////////////////////////////////////////////////////////////////
932

    
933
  public boolean[][] getLayerRotatable()
934
    {
935
    return mLayerRotatable;
936
    }
937

    
938
///////////////////////////////////////////////////////////////////////////////////////////////////
939

    
940
  public int getMovementType()
941
    {
942
    return mMovementType;
943
    }
944

    
945
///////////////////////////////////////////////////////////////////////////////////////////////////
946

    
947
  public int getMovementSplit()
948
    {
949
    return mMovementSplit;
950
    }
951

    
952
///////////////////////////////////////////////////////////////////////////////////////////////////
953

    
954
  public int[][][] getEnabled()
955
    {
956
    return mEnabled;
957
    }
958

    
959
///////////////////////////////////////////////////////////////////////////////////////////////////
960

    
961
  public float[] getDist3D()
962
    {
963
    return mDist3D;
964
    }
965

    
966
///////////////////////////////////////////////////////////////////////////////////////////////////
967

    
968
  public int getNumCubitFaces()
969
    {
970
    return mNumCubitFaces;
971
    }
972

    
973
///////////////////////////////////////////////////////////////////////////////////////////////////
974

    
975
  public float[][] getCubitPositions()
976
    {
977
    return mPositions;
978
    }
979

    
980
///////////////////////////////////////////////////////////////////////////////////////////////////
981

    
982
  public ObjectShape getObjectShape(int variant)
983
    {
984
    return mShapes[variant];
985
    }
986

    
987
///////////////////////////////////////////////////////////////////////////////////////////////////
988

    
989
  public ObjectFaceShape getObjectFaceShape(int variant)
990
    {
991
    return mFaceShapes[variant];
992
    }
993

    
994
///////////////////////////////////////////////////////////////////////////////////////////////////
995

    
996
  public Static4D getCubitQuats(int cubit)
997
    {
998
    return mCubitQuats[cubit];
999
    }
1000

    
1001
///////////////////////////////////////////////////////////////////////////////////////////////////
1002

    
1003
  public int getNumCubitVariants()
1004
    {
1005
    return mNumCubitVariants;
1006
    }
1007

    
1008
///////////////////////////////////////////////////////////////////////////////////////////////////
1009

    
1010
  public int getCubitVariant(int cubit)
1011
    {
1012
    return mCubitVariant[cubit];
1013
    }
1014

    
1015
///////////////////////////////////////////////////////////////////////////////////////////////////
1016

    
1017
  public int getVariantFaceColor(int variant, int face)
1018
    {
1019
    int[] colors = mVariantFaceColor[variant];
1020
    return colors.length>face ? colors[face] : -1;
1021
    }
1022

    
1023
///////////////////////////////////////////////////////////////////////////////////////////////////
1024

    
1025
  public int[] getCubitTypes()
1026
    {
1027
    return mCubitType;
1028
    }
1029

    
1030
///////////////////////////////////////////////////////////////////////////////////////////////////
1031

    
1032
  public float[][] getCubitOffsets()
1033
    {
1034
    return mCubitRowOffset;
1035
    }
1036

    
1037
///////////////////////////////////////////////////////////////////////////////////////////////////
1038

    
1039
  public int[][] getVariantFaceIsOuter()
1040
    {
1041
    return mVariantFaceIsOuter;
1042
    }
1043

    
1044
///////////////////////////////////////////////////////////////////////////////////////////////////
1045

    
1046
  public int getCubitFaceFace(int cubit, int face)
1047
    {
1048
    return mCubitFaceColor[cubit][face];
1049
    }
1050

    
1051
///////////////////////////////////////////////////////////////////////////////////////////////////
1052

    
1053
  public int getNumScrambles()
1054
    {
1055
    return mNumScrambles;
1056
    }
1057

    
1058
///////////////////////////////////////////////////////////////////////////////////////////////////
1059

    
1060
  public boolean isFree()
1061
    {
1062
    return mIsFree;
1063
    }
1064

    
1065
///////////////////////////////////////////////////////////////////////////////////////////////////
1066

    
1067
  public ObjectSticker retSticker(int sticker)
1068
    {
1069
    return mObjectSticker[sticker];
1070
    }
1071

    
1072
///////////////////////////////////////////////////////////////////////////////////////////////////
1073

    
1074
  public ObjectStickerOverride[] getStickerOverrides()
1075
    {
1076
    return mStickerOverrides;
1077
    }
1078

    
1079
///////////////////////////////////////////////////////////////////////////////////////////////////
1080

    
1081
  public float getPillowCoeff()
1082
    {
1083
    return mPillowCoeff;
1084
    }
1085

    
1086
///////////////////////////////////////////////////////////////////////////////////////////////////
1087

    
1088
  public Static3D[] getRotationAxis()
1089
    {
1090
    return mAxis;
1091
    }
1092

    
1093
///////////////////////////////////////////////////////////////////////////////////////////////////
1094

    
1095
  public int[][] getBasicAngle()
1096
    {
1097
    return mBasicAngle;
1098
    }
1099

    
1100
///////////////////////////////////////////////////////////////////////////////////////////////////
1101

    
1102
  public ObjectSignature getSignature()
1103
    {
1104
    return mSignature;
1105
    }
1106

    
1107
///////////////////////////////////////////////////////////////////////////////////////////////////
1108

    
1109
  public String getObjectName()
1110
    {
1111
    return mLongName;
1112
    }
1113

    
1114
///////////////////////////////////////////////////////////////////////////////////////////////////
1115

    
1116
  public String getShortName()
1117
    {
1118
    return mShortName;
1119
    }
1120

    
1121
///////////////////////////////////////////////////////////////////////////////////////////////////
1122

    
1123
  public String getInventor()
1124
    {
1125
    return mInventor;
1126
    }
1127

    
1128
///////////////////////////////////////////////////////////////////////////////////////////////////
1129

    
1130
  public int getYearOfInvention()
1131
    {
1132
    return mYearOfInvention;
1133
    }
1134

    
1135
///////////////////////////////////////////////////////////////////////////////////////////////////
1136

    
1137
  public int getComplexity()
1138
    {
1139
    return mComplexity;
1140
    }
1141

    
1142
///////////////////////////////////////////////////////////////////////////////////////////////////
1143

    
1144
  public int getNumFaces()
1145
    {
1146
    return mNumFaces;
1147
    }
1148

    
1149
///////////////////////////////////////////////////////////////////////////////////////////////////
1150

    
1151
  public int getNumFaceColors()
1152
    {
1153
    return mNumFaceColors;
1154
    }
1155

    
1156
///////////////////////////////////////////////////////////////////////////////////////////////////
1157

    
1158
  public int[] getNumLayers()
1159
    {
1160
    return mNumLayers;
1161
    }
1162

    
1163
///////////////////////////////////////////////////////////////////////////////////////////////////
1164

    
1165
  public float getSize()
1166
    {
1167
    return mSize;
1168
    }
1169

    
1170
///////////////////////////////////////////////////////////////////////////////////////////////////
1171

    
1172
  public int getScrambleType()
1173
    {
1174
    return mScrambleType;
1175
    }
1176

    
1177
///////////////////////////////////////////////////////////////////////////////////////////////////
1178

    
1179
  public int getColor(int face)
1180
    {
1181
    return mColor[face];
1182
    }
1183

    
1184
///////////////////////////////////////////////////////////////////////////////////////////////////
1185

    
1186
  public int getInternalColor()
1187
    {
1188
    return mInternalColor;
1189
    }
1190

    
1191
///////////////////////////////////////////////////////////////////////////////////////////////////
1192

    
1193
  public boolean shouldResetTextureMaps()
1194
    {
1195
    return mResetMaps;
1196
    }
1197

    
1198
///////////////////////////////////////////////////////////////////////////////////////////////////
1199

    
1200
  public String getTutorialObject()
1201
    {
1202
    return mTutorialObject;
1203
    }
1204

    
1205
///////////////////////////////////////////////////////////////////////////////////////////////////
1206

    
1207
  public String[][] getTutorials()
1208
    {
1209
    return mTutorials;
1210
    }
1211
}
(1-1/2)