Project

General

Profile

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

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

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 int mPrice;
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
///////////////////////////////////////////////////////////////////////////////////////////////////
82

    
83
  private void parseMetadata1(JSONObject object) throws JSONException
84
    {
85
    mLongName        = object.getString("longname");
86
    mShortName       = object.getString("shortname");
87
    mInventor        = object.getString("inventor");
88
    mYearOfInvention = object.getInt("year");
89
    mComplexity      = object.getInt("complexity");
90
    mSize            = (float)object.getDouble("size");
91
    mNumScrambles    = object.getInt("scrambles");
92
    mResetMaps       = object.getBoolean("resetmaps");
93
    mNumFaces        = object.getInt("num_faces");
94
    mPrice           = 0;
95

    
96
    try
97
      {
98
      long signature = object.getLong("signature");
99
      mSignature = new ObjectSignature(signature);
100
      }
101
    catch(JSONException ex)
102
      {
103
      // objects older than Feb 2022 do not have the 'signature' field. They all use the ObjectType.ordinal
104
      // as their signature.
105
      long signature = ObjectType.getOrdinal(mShortName);
106
      mSignature = new ObjectSignature(signature);
107
      }
108
    }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

    
112
  private void parseMetadata2or3or4(JSONObject object) throws JSONException
113
    {
114
    mLongName        = object.getString("longname");
115
    mShortName       = object.getString("shortname");
116
    mInventor        = object.getString("inventor");
117
    mYearOfInvention = object.getInt("year");
118
    mComplexity      = object.getInt("complexity");
119
    mSize            = (float)object.getDouble("size");
120
    mNumScrambles    = object.getInt("scrambles");
121
    mResetMaps       = object.getBoolean("resetmaps");
122
    mNumFaces        = object.getInt("num_faces");
123
    mPrice           = 0;
124

    
125
    try
126
      {
127
      long signature1 = object.getLong("signature1");
128
      long signature2 = object.getLong("signature2");
129
      long signature3 = object.getLong("signature3");
130
      long[] signature= new long[] {signature1,signature2,signature3};
131

    
132
      switch( TwistyBandagedCuboid.getType(mShortName,mLongName) )
133
        {
134
        case 0: mSignature = new ObjectSignature(signature); break;
135
        case 1: mSignature = new ObjectSignature(mShortName,signature); break;
136
        case 2: mSignature = new ObjectSignature("333",signature); break;
137
        }
138
      }
139
    catch(JSONException ex)
140
      {
141
      long signature = object.getLong("signature");
142
      mSignature = new ObjectSignature(signature);
143
      }
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

    
148
  private void parseMetadata5or6(JSONObject object) throws JSONException
149
    {
150
    mLongName        = object.getString("longname");
151
    mShortName       = object.getString("shortname");
152
    mInventor        = object.getString("inventor");
153
    mYearOfInvention = object.getInt("year");
154
    mComplexity      = object.getInt("complexity");
155
    mSize            = (float)object.getDouble("size");
156
    mNumScrambles    = object.getInt("scrambles");
157
    mResetMaps       = object.getBoolean("resetmaps");
158
    mNumFaces        = object.getInt("num_faces");
159

    
160
    try
161
      {
162
      JSONArray sigArray = object.getJSONArray("signature");
163
      int size = sigArray.length();
164
      long[] signature = new long[size];
165
      for(int i=0; i<size; i++) signature[i] = sigArray.getLong(i);
166

    
167
      switch( TwistyBandagedCuboid.getType(mShortName,mLongName) )
168
        {
169
        case 0: mSignature = new ObjectSignature(signature); break;
170
        case 1: mSignature = new ObjectSignature(mShortName,signature); break;
171
        case 2: mSignature = new ObjectSignature("333",signature); break;
172
        }
173
      }
174
    catch(JSONException ex)
175
      {
176
      long signature = object.getLong("signature");
177
      mSignature = new ObjectSignature(signature);
178
      }
179

    
180
    boolean free = object.optBoolean("free", true);
181

    
182
    if( free ) mPrice = 0;
183
    else mPrice = object.optInt("price", ObjectType.DEFAULT_PRICE_OF_OLD_OBJECTS );
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
  private void parseCubits(JSONArray object) throws JSONException
189
    {
190
    int numCubits = object.length();
191

    
192
    mCubitQuats     = new Static4D[numCubits];
193
    mCubitVariant   = new int[numCubits];
194
    mPositions      = new float[numCubits][];
195
    mCubitFaceColor = new int[numCubits][];
196
    mCubitType      = new int[numCubits];
197
    mCubitRowOffset = new float[numCubits][];
198

    
199
    for(int i=0; i<numCubits; i++)
200
      {
201
      JSONObject jsonCubit = object.getJSONObject(i);
202

    
203
      float qx = (float)jsonCubit.getDouble("qx");
204
      float qy = (float)jsonCubit.getDouble("qy");
205
      float qz = (float)jsonCubit.getDouble("qz");
206
      float qw = (float)jsonCubit.getDouble("qw");
207

    
208
      mCubitQuats[i] = new Static4D(qx,qy,qz,qw);
209
      mCubitVariant[i] = jsonCubit.getInt("variant");
210

    
211
      JSONArray jsonCenter = jsonCubit.getJSONArray("centers");
212
      int numCenter = jsonCenter.length();
213
      mPositions[i] = new float[numCenter];
214
      for(int j=0; j<numCenter; j++) mPositions[i][j] = (float)jsonCenter.getDouble(j);
215

    
216
      JSONArray jsonColor  = jsonCubit.getJSONArray("colors");
217
      int numColor = jsonColor.length();
218
      mCubitFaceColor[i] = new int[numColor];
219
      for(int j=0; j<numColor; j++) mCubitFaceColor[i][j] = jsonColor.getInt(j);
220

    
221
      mCubitType[i] = jsonCubit.optInt("type", Cubit.TYPE_NORMAL);
222
      float xoff = (float)jsonCubit.optDouble("offsetX", 0 );
223
      float yoff = (float)jsonCubit.optDouble("offsetY", 0 );
224
      float zoff = (float)jsonCubit.optDouble("offsetZ", 0 );
225
      mCubitRowOffset[i] = new float[] {xoff,yoff,zoff};
226
      }
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
  private void parseShapes(JSONArray object) throws JSONException
232
    {
233
    mNumCubitVariants     = object.length();
234
    mVariantFaceColor     = new int[mNumCubitVariants][];
235
    mVariantFaceIsOuter   = new int[mNumCubitVariants][];
236
    mShapes               = new ObjectShape[mNumCubitVariants];
237
    mFaceShapes           = new ObjectFaceShape[mNumCubitVariants];
238
    float[][][] verts     = new float[mNumCubitVariants][][];
239
    float[][][] bands     = new float[mNumCubitVariants][][];
240
    float[][][] corners   = new float[mNumCubitVariants][][];
241
    float[][][] centers   = new float[mNumCubitVariants][][];
242
    float[][] convexity   = new float[mNumCubitVariants][];
243
    int[][] cornerIndices = new int[mNumCubitVariants][];
244
    int[][] centerIndices = new int[mNumCubitVariants][];
245
    int[][] bandIndices   = new int[mNumCubitVariants][];
246
    int[][][] vertIndices = new int[mNumCubitVariants][][];
247

    
248
    mNumCubitFaces = -1;
249

    
250
    for(int i=0; i<mNumCubitVariants; i++)
251
      {
252
      JSONObject jsonShape = object.getJSONObject(i);
253

    
254
      ////// vertices /////////////////////////////////////////////////
255
      JSONArray jsonVertices= jsonShape.getJSONArray("vertices");
256
      int numVertices = jsonVertices.length();
257
      verts[i] = new float[numVertices][3];
258
      cornerIndices[i] = new int[numVertices];
259
      centerIndices[i] = new int[numVertices];
260

    
261
      for(int j=0; j<numVertices; j++)
262
        {
263
        JSONObject vert = jsonVertices.getJSONObject(j);
264
        verts[i][j][0] = (float)vert.getDouble("x");
265
        verts[i][j][1] = (float)vert.getDouble("y");
266
        verts[i][j][2] = (float)vert.getDouble("z");
267
        cornerIndices[i][j] = vert.getInt("cornerIndex");
268
        centerIndices[i][j] = vert.getInt("centerIndex");
269
        }
270

    
271
      ////// faces ////////////////////////////////////////////////////
272
      JSONArray jsonFaces= jsonShape.getJSONArray("faces");
273
      int numFaces = jsonFaces.length();
274
      mVariantFaceColor[i]   = new int[numFaces];
275
      mVariantFaceIsOuter[i] = new int[numFaces];
276
      bandIndices[i] = new int[numFaces];
277
      vertIndices[i] = new int[numFaces][];
278

    
279
      if( mNumCubitFaces<numFaces ) mNumCubitFaces=numFaces;
280

    
281
      for(int j=0; j<numFaces; j++)
282
        {
283
        JSONObject jsonFace = jsonFaces.getJSONObject(j);
284
        mVariantFaceColor[i][j]   = jsonFace.getInt("sticker");
285
        mVariantFaceIsOuter[i][j] = jsonFace.optInt("isOuter",0);
286
        bandIndices[i][j] = jsonFace.getInt("bandIndex");
287
        JSONArray vertices = jsonFace.getJSONArray("vertexIndices");
288
        int numV = vertices.length();
289
        vertIndices[i][j] = new int[numV];
290
        for(int k=0; k<numV; k++) vertIndices[i][j][k] = vertices.getInt(k);
291
        }
292

    
293
      ////// bands ////////////////////////////////////////////////////
294
      JSONArray jsonBands= jsonShape.getJSONArray("bands");
295
      int numBands = jsonBands.length();
296
      bands[i] = new float[numBands][7];
297

    
298
      for(int j=0; j<numBands; j++)
299
        {
300
        JSONObject jsonBand = jsonBands.getJSONObject(j);
301

    
302
        bands[i][j][0] = (float)jsonBand.getDouble("height");
303
        bands[i][j][1] = (float)jsonBand.getDouble("angle");
304
        bands[i][j][2] = (float)jsonBand.getDouble("distanceToCenter");
305
        bands[i][j][3] = (float)jsonBand.getDouble("distanceToFlat");
306
        bands[i][j][4] = (float)jsonBand.getDouble("numOfBands");
307
        bands[i][j][5] = (float)jsonBand.getDouble("extraI");
308
        bands[i][j][6] = (float)jsonBand.getDouble("extraJ");
309
        }
310

    
311
      ////// cornerPush ///////////////////////////////////////////////
312
      JSONArray jsonCornerPush= jsonShape.optJSONArray("cornerPush");
313

    
314
      if( jsonCornerPush!=null )
315
        {
316
        int numCornerP = jsonCornerPush.length();
317
        corners[i] = new float[numCornerP][2];
318

    
319
        for(int j=0; j<numCornerP; j++)
320
          {
321
          JSONObject jsonC = jsonCornerPush.getJSONObject(j);
322
          corners[i][j][0] = (float)jsonC.getDouble("strength");
323
          corners[i][j][1] = (float)jsonC.getDouble("radius");
324
          }
325
        }
326

    
327
      ////// centerPush ///////////////////////////////////////////////
328
      JSONArray jsonCenterPush= jsonShape.optJSONArray("centerPush");
329

    
330
      if( jsonCenterPush!=null )
331
        {
332
        int numCenterP = jsonCenterPush.length();
333
        centers[i] = new float[numCenterP][3];
334

    
335
        for(int j=0; j<numCenterP; j++)
336
          {
337
          JSONObject jsonC = jsonCenterPush.getJSONObject(j);
338
          centers[i][j][0] = (float)jsonC.getDouble("x");
339
          centers[i][j][1] = (float)jsonC.getDouble("y");
340
          centers[i][j][2] = (float)jsonC.getDouble("z");
341
          }
342
        }
343

    
344
      ////// convexity ///////////////////////////////////////////////
345
      JSONObject jsonConvexity = jsonShape.optJSONObject("convexity");
346

    
347
      if( jsonConvexity!=null )
348
        {
349
        convexity[i] = new float[3];
350
        convexity[i][0] = (float)jsonConvexity.getDouble("x");
351
        convexity[i][1] = (float)jsonConvexity.getDouble("y");
352
        convexity[i][2] = (float)jsonConvexity.getDouble("z");
353
        }
354
      }
355

    
356
    for(int i=0; i<mNumCubitVariants; i++)
357
      {
358
      mShapes[i] = new ObjectShape(verts[i],vertIndices[i]);
359
      mFaceShapes[i] = new ObjectFaceShape(bands[i],bandIndices[i],corners[i],cornerIndices[i],centers[i],centerIndices[i],convexity[i] );
360
      }
361
    }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
  private void parseStickers(JSONArray object) throws JSONException
366
    {
367
    mNumStickerTypes = object.length();
368
    mObjectSticker = new ObjectSticker[mNumStickerTypes];
369

    
370
    for(int i=0; i<mNumStickerTypes; i++)
371
      {
372
      JSONObject sticker = object.getJSONObject(i);
373
      float stroke = (float)sticker.getDouble("stroke");
374
      JSONArray vertices = sticker.getJSONArray("vertices");
375
      int numVertices = vertices.length();
376

    
377
      float[] coords     = new float[2*numVertices];
378
      float[] curvatures = new float[numVertices];
379
      float[] radii      = new float[numVertices];
380

    
381
      for(int j=0; j<numVertices; j++)
382
        {
383
        JSONObject vertex = vertices.getJSONObject(j);
384

    
385
        coords[2*j  ] = (float)vertex.getDouble("x");
386
        coords[2*j+1] = (float)vertex.getDouble("y");
387
        curvatures[j] = (float)vertex.getDouble("angle");
388
        radii[j]      = (float)vertex.getDouble("radius");
389
        }
390

    
391
      mObjectSticker[i] = new ObjectSticker(coords,curvatures,radii,stroke);
392
      }
393
    }
394

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

    
397
  private void parseOverrides(JSONArray object) throws JSONException
398
    {
399
    if( object!=null )
400
      {
401
      int numOverrides = object.length();
402
      mStickerOverrides= new ObjectStickerOverride[numOverrides];
403

    
404
      for(int i=0; i<numOverrides; i++)
405
        {
406
        JSONObject override  = object.getJSONObject(i);
407
        JSONArray cubitArray = override.getJSONArray("cubitfaces");
408
        int color = override.getInt("color");
409
        int numCubits = cubitArray.length();
410
        int[] cubitface = new int[numCubits];
411
        for(int j=0; j<numCubits; j++) cubitface[j] = cubitArray.getInt(j);
412
        mStickerOverrides[i] = new ObjectStickerOverride(cubitface,color);
413
        }
414
      }
415
    else
416
      {
417
      mStickerOverrides = null;
418
      }
419
    }
420

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

    
423
  private void parseMesh(JSONObject object) throws JSONException
424
    {
425
    JSONArray cubits   = object.getJSONArray("cubits");
426
    parseCubits(cubits);
427
    JSONArray shapes   = object.getJSONArray("shapes");
428
    parseShapes(shapes);
429
    JSONArray stickers = object.getJSONArray("stickers");
430
    parseStickers(stickers);
431

    
432
    JSONArray overrides= object.optJSONArray("overrides");
433
    parseOverrides(overrides);
434

    
435
    mPillowCoeff = (float)object.optDouble("pillow",1.0);
436
    }
437

    
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

    
440
  private void parseAxis1(JSONArray object) throws JSONException
441
    {
442
    int numAxis = object.length();
443

    
444
    mBasicAngle     = new int[numAxis][];
445
    mAxis           = new Static3D[numAxis];
446
    mCuts           = new float[numAxis][];
447
    mLayerRotatable = new boolean[numAxis][];
448
    mNumLayers      = new int[numAxis];
449

    
450
    for(int i=0; i<numAxis; i++)
451
      {
452
      JSONObject jsonAx = object.getJSONObject(i);
453

    
454
      float x = (float)jsonAx.getDouble("x");
455
      float y = (float)jsonAx.getDouble("y");
456
      float z = (float)jsonAx.getDouble("z");
457

    
458
      mAxis[i] = new Static3D(x,y,z);
459

    
460
      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
461
      int numCuts = jsonCuts.length();
462
      mCuts[i] = new float[numCuts];
463
      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
464

    
465
      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
466
      int numRota = jsonRota.length();
467
      mLayerRotatable[i] = new boolean[numRota];
468
      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
469

    
470
      mBasicAngle[i] = new int[numRota];
471
      int basicAngle = jsonAx.getInt("basicAngle");
472
      for(int j=0; j<numRota; j++) mBasicAngle[i][j] = basicAngle;
473

    
474
      mNumLayers[i] = numRota;
475
      }
476
    }
477

    
478
///////////////////////////////////////////////////////////////////////////////////////////////////
479

    
480
  private void parseAxis2or3or4or5or6(JSONArray object) throws JSONException
481
    {
482
    int numAxis = object.length();
483

    
484
    mBasicAngle     = new int[numAxis][];
485
    mAxis           = new Static3D[numAxis];
486
    mCuts           = new float[numAxis][];
487
    mLayerRotatable = new boolean[numAxis][];
488
    mNumLayers      = new int[numAxis];
489

    
490
    for(int i=0; i<numAxis; i++)
491
      {
492
      JSONObject jsonAx = object.getJSONObject(i);
493

    
494
      float x = (float)jsonAx.getDouble("x");
495
      float y = (float)jsonAx.getDouble("y");
496
      float z = (float)jsonAx.getDouble("z");
497

    
498
      mAxis[i] = new Static3D(x,y,z);
499

    
500
      JSONArray jsonAngles = jsonAx.getJSONArray("basicAngles");
501
      int numAngles = jsonAngles.length();
502
      mBasicAngle[i] = new int[numAngles];
503
      for(int j=0; j<numAngles; j++) mBasicAngle[i][j] = jsonAngles.getInt(j);
504

    
505
      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
506
      int numCuts = jsonCuts.length();
507
      mCuts[i] = new float[numCuts];
508
      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
509

    
510
      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
511
      int numRota = jsonRota.length();
512
      mLayerRotatable[i] = new boolean[numRota];
513
      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
514

    
515
      mNumLayers[i] = numRota;
516
      }
517
    }
518

    
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520

    
521
  private void parseQuats(JSONArray object) throws JSONException
522
    {
523
    int numQuats = object.length();
524
    mQuats = new Static4D[numQuats];
525

    
526
    for(int i=0; i<numQuats; i++)
527
      {
528
      JSONObject jsonQuat = object.getJSONObject(i);
529

    
530
      float x = (float)jsonQuat.getDouble("x");
531
      float y = (float)jsonQuat.getDouble("y");
532
      float z = (float)jsonQuat.getDouble("z");
533
      float w = (float)jsonQuat.getDouble("w");
534

    
535
      mQuats[i] = new Static4D(x,y,z,w);
536
      }
537
    }
538

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

    
541
  private void parseScrambling(JSONObject object) throws JSONException
542
    {
543
    mScrambleType = object.getInt("scrambleType");
544

    
545
    if( mScrambleType==0 )
546
      {
547
      JSONArray jsonStates = object.getJSONArray("scrambleStates");
548
      int numStates = jsonStates.length();
549
      mStates = new ScrambleState[numStates];
550

    
551
      for(int i=0; i<numStates; i++)
552
        {
553
        JSONArray jsonState = jsonStates.getJSONArray(i);
554
        int numAxis = jsonState.length();
555
        int[][] scramblingData = new int[numAxis][];
556

    
557
        for(int j=0; j<numAxis; j++)
558
          {
559
          JSONArray jsonData = jsonState.getJSONArray(j);
560
          int numData = jsonData.length();
561
          scramblingData[j] = new int[numData];
562
          for(int k=0; k<numData; k++) scramblingData[j][k] = jsonData.getInt(k);
563
          }
564

    
565
        mStates[i] = new ScrambleState(scramblingData);
566
        }
567
      }
568
    }
569

    
570
///////////////////////////////////////////////////////////////////////////////////////////////////
571

    
572
  private void parseTouchcontrol(JSONObject object) throws JSONException
573
    {
574
    mMovementType = object.getInt("movementType");
575
    mMovementSplit= object.getInt("movementSplit");
576

    
577
    try
578
      {
579
      JSONArray jsonEnabled = object.getJSONArray("enabledAxis");
580
      int numFace = jsonEnabled.length();
581

    
582
      mEnabled = new int[numFace][][];
583

    
584
      for(int i=0; i<numFace; i++)
585
        {
586
        JSONArray jsonSection = jsonEnabled.getJSONArray(i);
587
        int numSection = jsonSection.length();
588
        mEnabled[i] = new int[numSection][];
589

    
590
        for(int j=0; j<numSection; j++)
591
          {
592
          JSONArray jsonAx = jsonSection.getJSONArray(j);
593
          int numAxis = jsonAx.length();
594
          mEnabled[i][j] = new int[numAxis];
595
          for(int k=0; k<numAxis; k++) mEnabled[i][j][k] = jsonAx.getInt(k);
596
          }
597
        }
598
      }
599
    catch( JSONException ex )
600
      {
601
      // ignore, the object does not have to have 'enabledAxis' defined at all.
602
      }
603

    
604
    try
605
      {
606
      JSONArray jsonDist = object.getJSONArray("dist3D");
607
      int num = jsonDist.length();
608
      mDist3D = new float[num];
609
      for(int j=0; j<num; j++) mDist3D[j] = (float)jsonDist.getDouble(j);
610
      }
611
    catch( JSONException ex )
612
      {
613
      // ignore, the object does not have a 'dist3D' which is possible.
614
      }
615
    }
616

    
617
///////////////////////////////////////////////////////////////////////////////////////////////////
618

    
619
  private void parseColors(JSONArray object) throws JSONException
620
    {
621
    mNumFaceColors = object.length()-1;
622

    
623
    mColor = new int[mNumFaceColors];
624
    for(int i=0; i<mNumFaceColors; i++) mColor[i] = object.getInt(i);
625

    
626
    mInternalColor = object.getInt(mNumFaceColors);
627
    }
628

    
629
///////////////////////////////////////////////////////////////////////////////////////////////////
630

    
631
  private void parseSolved(JSONObject solved) throws JSONException
632
    {
633
    mSolvedFuncIndex = solved.getInt("functionIndex");
634

    
635
    try
636
      {
637
      JSONArray groupArray= solved.getJSONArray("groups");
638
      int numGroups = groupArray.length();
639
      mSolvedQuats  = new int[numGroups][];
640

    
641
      for(int i=0; i<numGroups; i++)
642
        {
643
        JSONArray groupElements = groupArray.getJSONArray(i);
644
        int groupSize = groupElements.length();
645
        mSolvedQuats[i] = new int[groupSize];
646
        for(int j=0; j<groupSize; j++) mSolvedQuats[i][j] = groupElements.getInt(j);
647
        }
648
      }
649
    catch( JSONException ex )
650
      {
651
      // ignore, the object does not have to have an array of solved groups.
652
      }
653
    }
654

    
655
///////////////////////////////////////////////////////////////////////////////////////////////////
656

    
657
  private void parseVersion1(JSONObject object) throws JSONException
658
    {
659
    JSONObject metadata    = object.getJSONObject("metadata");
660
    parseMetadata1(metadata);
661
    JSONObject mesh        = object.getJSONObject("mesh");
662
    parseMesh(mesh);
663
    JSONArray axis         = object.getJSONArray("axis");
664
    parseAxis1(axis);
665
    JSONArray quats        = object.getJSONArray("quats");
666
    parseQuats(quats);
667
    JSONObject scrambling  = object.getJSONObject("scrambling");
668
    parseScrambling(scrambling);
669
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
670
    parseTouchcontrol(touchcontrol);
671
    JSONArray colors       = object.getJSONArray("colors");
672
    parseColors(colors);
673
    JSONObject solved      = object.getJSONObject("solved");
674
    parseSolved(solved);
675
    }
676

    
677
///////////////////////////////////////////////////////////////////////////////////////////////////
678

    
679
  private void parseVersion2or3or4(JSONObject object) throws JSONException
680
    {
681
    JSONObject metadata    = object.getJSONObject("metadata");
682
    parseMetadata2or3or4(metadata);
683
    JSONObject mesh        = object.getJSONObject("mesh");
684
    parseMesh(mesh);
685
    JSONArray axis         = object.getJSONArray("axis");
686
    parseAxis2or3or4or5or6(axis);
687
    JSONArray quats        = object.getJSONArray("quats");
688
    parseQuats(quats);
689
    JSONObject scrambling  = object.getJSONObject("scrambling");
690
    parseScrambling(scrambling);
691
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
692
    parseTouchcontrol(touchcontrol);
693
    JSONArray colors       = object.getJSONArray("colors");
694
    parseColors(colors);
695
    JSONObject solved      = object.getJSONObject("solved");
696
    parseSolved(solved);
697
    }
698

    
699
///////////////////////////////////////////////////////////////////////////////////////////////////
700

    
701
  private void parseVersion5or6(JSONObject object) throws JSONException
702
    {
703
    JSONObject metadata    = object.getJSONObject("metadata");
704
    parseMetadata5or6(metadata);
705
    JSONObject mesh        = object.getJSONObject("mesh");
706
    parseMesh(mesh);
707
    JSONArray axis         = object.getJSONArray("axis");
708
    parseAxis2or3or4or5or6(axis);
709
    JSONArray quats        = object.getJSONArray("quats");
710
    parseQuats(quats);
711
    JSONObject scrambling  = object.getJSONObject("scrambling");
712
    parseScrambling(scrambling);
713
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
714
    parseTouchcontrol(touchcontrol);
715
    JSONArray colors       = object.getJSONArray("colors");
716
    parseColors(colors);
717
    JSONObject solved      = object.getJSONObject("solved");
718
    parseSolved(solved);
719
    }
720

    
721
///////////////////////////////////////////////////////////////////////////////////////////////////
722

    
723
  private void parseVersion1Tutorial(JSONObject object) throws JSONException
724
    {
725
    mTutorialObject = object.getString("object");
726
    JSONArray tuts= object.getJSONArray("tutorials");
727

    
728
    int len = tuts.length();
729
    mTutorials = new String[len][4];
730

    
731
    for(int i=0; i<len; i++)
732
      {
733
      JSONObject tut = tuts.getJSONObject(i);
734
      mTutorials[i][0] = tut.getString("language");
735
      mTutorials[i][1] = tut.getString("link");
736
      mTutorials[i][2] = tut.getString("title");
737
      mTutorials[i][3] = tut.getString("author");
738
      }
739
    }
740

    
741
///////////////////////////////////////////////////////////////////////////////////////////////////
742

    
743
  private void parseVersion1Metadata(JSONObject object) throws JSONException
744
    {
745
    JSONObject metadata = object.getJSONObject("metadata");
746
    parseMetadata1(metadata);
747
    }
748

    
749
///////////////////////////////////////////////////////////////////////////////////////////////////
750

    
751
  private void parseVersion2or3or4Metadata(JSONObject object) throws JSONException
752
    {
753
    JSONObject metadata = object.getJSONObject("metadata");
754
    parseMetadata2or3or4(metadata);
755
    }
756

    
757
///////////////////////////////////////////////////////////////////////////////////////////////////
758

    
759
  private void parseVersion5or6Metadata(JSONObject object) throws JSONException
760
    {
761
    JSONObject metadata = object.getJSONObject("metadata");
762
    parseMetadata5or6(metadata);
763
    }
764

    
765
///////////////////////////////////////////////////////////////////////////////////////////////////
766

    
767
  public void parseJsonFile(InputStream jsonStream) throws JSONException, IOException
768
    {
769
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
770
    StringBuilder contents = new StringBuilder();
771
    String tmp;
772

    
773
    while( (tmp = br.readLine()) != null) contents.append(tmp);
774
    br.close();
775
    jsonStream.close();
776

    
777
    JSONObject object = new JSONObject(contents.toString());
778
    int major = object.getInt("major");
779

    
780
    if( major==1 )
781
      {
782
      parseVersion1(object);
783
      }
784
    else if( major==2 || major==3 || major==4 )
785
      {
786
      parseVersion2or3or4(object);
787
      }
788
    else if( major==5 || major==6 )
789
      {
790
      parseVersion5or6(object);
791
      }
792
    else
793
      {
794
      android.util.Log.e("readJsonFile", "Unknown version "+major);
795
      }
796
    }
797

    
798
///////////////////////////////////////////////////////////////////////////////////////////////////
799

    
800
  public void parseJsonFileMetadata(InputStream jsonStream) throws JSONException, IOException
801
    {
802
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
803
    StringBuilder contents = new StringBuilder();
804
    String tmp;
805

    
806
    while( (tmp = br.readLine()) != null) contents.append(tmp);
807
    br.close();
808
    jsonStream.close();
809

    
810
    JSONObject object = new JSONObject(contents.toString());
811
    int major = object.getInt("major");
812

    
813
    if( major==1 )
814
      {
815
      parseVersion1Metadata(object);
816
      }
817
    else if( major==2 || major==3 || major==4 )
818
      {
819
      parseVersion2or3or4Metadata(object);
820
      }
821
    else if( major==5 || major==6 )
822
      {
823
      parseVersion5or6Metadata(object);
824
      }
825
    else
826
      {
827
      android.util.Log.e("readJsonFileQuick", "Unknown version "+major);
828
      }
829
    }
830

    
831
///////////////////////////////////////////////////////////////////////////////////////////////////
832

    
833
  public void readNumScramblesAndPrice(Context context, String fileName) throws IOException, JSONException
834
    {
835
    File file = new File(context.getFilesDir(), fileName);
836
    InputStream stream = new FileInputStream(file);
837
    BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
838

    
839
    StringBuilder contents = new StringBuilder();
840
    String tmp;
841
    while( (tmp = br.readLine()) != null) contents.append(tmp);
842
    br.close();
843
    stream.close();
844

    
845
    JSONObject object = new JSONObject(contents.toString());
846
    JSONObject metadata = object.getJSONObject("metadata");
847
    mNumScrambles = metadata.getInt("scrambles");
848

    
849
    boolean free = metadata.optBoolean("free",true);
850
    if( free ) mPrice = 0;
851
    else mPrice = metadata.optInt("price", ObjectType.DEFAULT_PRICE_OF_OLD_OBJECTS );
852
    }
853

    
854
///////////////////////////////////////////////////////////////////////////////////////////////////
855

    
856
  public void parseJsonTutorial(InputStream jsonStream) throws IOException, JSONException
857
    {
858
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
859
    StringBuilder contents = new StringBuilder();
860
    String tmp;
861

    
862
    while( (tmp = br.readLine()) != null) contents.append(tmp);
863
    br.close();
864
    jsonStream.close();
865

    
866
    JSONObject object = new JSONObject(contents.toString());
867
    int major = object.getInt("major");
868

    
869
    if( major==1 )
870
      {
871
      parseVersion1Tutorial(object);
872
      }
873
    else
874
      {
875
      android.util.Log.e("readJsonFile", "Unknown tutorial version "+major);
876
      }
877
    }
878

    
879
///////////////////////////////////////////////////////////////////////////////////////////////////
880

    
881
  public ScrambleState[] getScrambleStates()
882
    {
883
    return mStates;
884
    }
885

    
886
///////////////////////////////////////////////////////////////////////////////////////////////////
887

    
888
  public int[][] getSolvedQuats()
889
    {
890
    return mSolvedQuats;
891
    }
892

    
893
///////////////////////////////////////////////////////////////////////////////////////////////////
894

    
895
  public Static4D[] getQuats()
896
    {
897
    return mQuats;
898
    }
899

    
900
///////////////////////////////////////////////////////////////////////////////////////////////////
901

    
902
  public int getSolvedFunctionIndex()
903
    {
904
    return mSolvedFuncIndex;
905
    }
906

    
907
///////////////////////////////////////////////////////////////////////////////////////////////////
908

    
909
  public int getNumStickerTypes()
910
    {
911
    return mNumStickerTypes;
912
    }
913

    
914
///////////////////////////////////////////////////////////////////////////////////////////////////
915

    
916
  public float[][] getCuts()
917
    {
918
    return mCuts;
919
    }
920

    
921
///////////////////////////////////////////////////////////////////////////////////////////////////
922

    
923
  public boolean[][] getLayerRotatable()
924
    {
925
    return mLayerRotatable;
926
    }
927

    
928
///////////////////////////////////////////////////////////////////////////////////////////////////
929

    
930
  public int getMovementType()
931
    {
932
    return mMovementType;
933
    }
934

    
935
///////////////////////////////////////////////////////////////////////////////////////////////////
936

    
937
  public int getMovementSplit()
938
    {
939
    return mMovementSplit;
940
    }
941

    
942
///////////////////////////////////////////////////////////////////////////////////////////////////
943

    
944
  public int[][][] getEnabled()
945
    {
946
    return mEnabled;
947
    }
948

    
949
///////////////////////////////////////////////////////////////////////////////////////////////////
950

    
951
  public float[] getDist3D()
952
    {
953
    return mDist3D;
954
    }
955

    
956
///////////////////////////////////////////////////////////////////////////////////////////////////
957

    
958
  public int getNumCubitFaces()
959
    {
960
    return mNumCubitFaces;
961
    }
962

    
963
///////////////////////////////////////////////////////////////////////////////////////////////////
964

    
965
  public float[][] getCubitPositions()
966
    {
967
    return mPositions;
968
    }
969

    
970
///////////////////////////////////////////////////////////////////////////////////////////////////
971

    
972
  public ObjectShape getObjectShape(int variant)
973
    {
974
    return mShapes[variant];
975
    }
976

    
977
///////////////////////////////////////////////////////////////////////////////////////////////////
978

    
979
  public ObjectFaceShape getObjectFaceShape(int variant)
980
    {
981
    return mFaceShapes[variant];
982
    }
983

    
984
///////////////////////////////////////////////////////////////////////////////////////////////////
985

    
986
  public Static4D getCubitQuats(int cubit)
987
    {
988
    return mCubitQuats[cubit];
989
    }
990

    
991
///////////////////////////////////////////////////////////////////////////////////////////////////
992

    
993
  public int getNumCubitVariants()
994
    {
995
    return mNumCubitVariants;
996
    }
997

    
998
///////////////////////////////////////////////////////////////////////////////////////////////////
999

    
1000
  public int getCubitVariant(int cubit)
1001
    {
1002
    return mCubitVariant[cubit];
1003
    }
1004

    
1005
///////////////////////////////////////////////////////////////////////////////////////////////////
1006

    
1007
  public int getVariantFaceColor(int variant, int face)
1008
    {
1009
    int[] colors = mVariantFaceColor[variant];
1010
    return colors.length>face ? colors[face] : -1;
1011
    }
1012

    
1013
///////////////////////////////////////////////////////////////////////////////////////////////////
1014

    
1015
  public int[] getCubitTypes()
1016
    {
1017
    return mCubitType;
1018
    }
1019

    
1020
///////////////////////////////////////////////////////////////////////////////////////////////////
1021

    
1022
  public float[][] getCubitOffsets()
1023
    {
1024
    return mCubitRowOffset;
1025
    }
1026

    
1027
///////////////////////////////////////////////////////////////////////////////////////////////////
1028

    
1029
  public int[][] getVariantFaceIsOuter()
1030
    {
1031
    return mVariantFaceIsOuter;
1032
    }
1033

    
1034
///////////////////////////////////////////////////////////////////////////////////////////////////
1035

    
1036
  public int getCubitFaceFace(int cubit, int face)
1037
    {
1038
    return mCubitFaceColor[cubit][face];
1039
    }
1040

    
1041
///////////////////////////////////////////////////////////////////////////////////////////////////
1042

    
1043
  public int getNumScrambles()
1044
    {
1045
    return mNumScrambles;
1046
    }
1047

    
1048
///////////////////////////////////////////////////////////////////////////////////////////////////
1049

    
1050
  public int getPrice()
1051
    {
1052
    return mPrice;
1053
    }
1054

    
1055
///////////////////////////////////////////////////////////////////////////////////////////////////
1056

    
1057
  public ObjectSticker retSticker(int sticker)
1058
    {
1059
    return mObjectSticker[sticker];
1060
    }
1061

    
1062
///////////////////////////////////////////////////////////////////////////////////////////////////
1063

    
1064
  public ObjectStickerOverride[] getStickerOverrides()
1065
    {
1066
    return mStickerOverrides;
1067
    }
1068

    
1069
///////////////////////////////////////////////////////////////////////////////////////////////////
1070

    
1071
  public float getPillowCoeff()
1072
    {
1073
    return mPillowCoeff;
1074
    }
1075

    
1076
///////////////////////////////////////////////////////////////////////////////////////////////////
1077

    
1078
  public Static3D[] getRotationAxis()
1079
    {
1080
    return mAxis;
1081
    }
1082

    
1083
///////////////////////////////////////////////////////////////////////////////////////////////////
1084

    
1085
  public int[][] getBasicAngle()
1086
    {
1087
    return mBasicAngle;
1088
    }
1089

    
1090
///////////////////////////////////////////////////////////////////////////////////////////////////
1091

    
1092
  public ObjectSignature getSignature()
1093
    {
1094
    return mSignature;
1095
    }
1096

    
1097
///////////////////////////////////////////////////////////////////////////////////////////////////
1098

    
1099
  public String getObjectName()
1100
    {
1101
    return mLongName;
1102
    }
1103

    
1104
///////////////////////////////////////////////////////////////////////////////////////////////////
1105

    
1106
  public String getShortName()
1107
    {
1108
    return mShortName;
1109
    }
1110

    
1111
///////////////////////////////////////////////////////////////////////////////////////////////////
1112

    
1113
  public String getInventor()
1114
    {
1115
    return mInventor;
1116
    }
1117

    
1118
///////////////////////////////////////////////////////////////////////////////////////////////////
1119

    
1120
  public int getYearOfInvention()
1121
    {
1122
    return mYearOfInvention;
1123
    }
1124

    
1125
///////////////////////////////////////////////////////////////////////////////////////////////////
1126

    
1127
  public int getComplexity()
1128
    {
1129
    return mComplexity;
1130
    }
1131

    
1132
///////////////////////////////////////////////////////////////////////////////////////////////////
1133

    
1134
  public int getNumFaces()
1135
    {
1136
    return mNumFaces;
1137
    }
1138

    
1139
///////////////////////////////////////////////////////////////////////////////////////////////////
1140

    
1141
  public int getNumFaceColors()
1142
    {
1143
    return mNumFaceColors;
1144
    }
1145

    
1146
///////////////////////////////////////////////////////////////////////////////////////////////////
1147

    
1148
  public int[] getNumLayers()
1149
    {
1150
    return mNumLayers;
1151
    }
1152

    
1153
///////////////////////////////////////////////////////////////////////////////////////////////////
1154

    
1155
  public float getSize()
1156
    {
1157
    return mSize;
1158
    }
1159

    
1160
///////////////////////////////////////////////////////////////////////////////////////////////////
1161

    
1162
  public int getScrambleType()
1163
    {
1164
    return mScrambleType;
1165
    }
1166

    
1167
///////////////////////////////////////////////////////////////////////////////////////////////////
1168

    
1169
  public int getColor(int face)
1170
    {
1171
    return mColor[face];
1172
    }
1173

    
1174
///////////////////////////////////////////////////////////////////////////////////////////////////
1175

    
1176
  public int getInternalColor()
1177
    {
1178
    return mInternalColor;
1179
    }
1180

    
1181
///////////////////////////////////////////////////////////////////////////////////////////////////
1182

    
1183
  public boolean shouldResetTextureMaps()
1184
    {
1185
    return mResetMaps;
1186
    }
1187

    
1188
///////////////////////////////////////////////////////////////////////////////////////////////////
1189

    
1190
  public String getTutorialObject()
1191
    {
1192
    return mTutorialObject;
1193
    }
1194

    
1195
///////////////////////////////////////////////////////////////////////////////////////////////////
1196

    
1197
  public String[][] getTutorials()
1198
    {
1199
    return mTutorials;
1200
    }
1201
}
(1-1/2)