Project

General

Profile

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

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

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 static org.distorted.objectlib.objects.TwistyBandagedCuboid.OBJECT_NAME;
13
import static org.distorted.objectlib.scrambling.ScrambleStateBandagedCuboid.MAX_SUPPORTED_SIZE;
14

    
15
import java.io.BufferedReader;
16
import java.io.File;
17
import java.io.FileInputStream;
18
import java.io.IOException;
19
import java.io.InputStream;
20
import java.io.InputStreamReader;
21
import java.nio.charset.StandardCharsets;
22

    
23
import android.content.Context;
24

    
25
import org.distorted.objectlib.helpers.ObjectFaceShape;
26
import org.distorted.objectlib.helpers.ObjectSignature;
27
import org.distorted.objectlib.helpers.ObjectStickerOverride;
28
import org.distorted.objectlib.helpers.ObjectVertexEffects;
29
import org.distorted.objectlib.main.TwistyObjectCubit;
30
import org.distorted.objectlib.scrambling.ScrambleEdgeGenerator;
31
import org.json.JSONArray;
32
import org.json.JSONException;
33
import org.json.JSONObject;
34

    
35
import org.distorted.library.type.Static3D;
36
import org.distorted.library.type.Static4D;
37

    
38
import org.distorted.objectlib.helpers.ObjectShape;
39
import org.distorted.objectlib.helpers.ObjectSticker;
40
import org.distorted.objectlib.main.ObjectType;
41

    
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43

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

    
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

    
88
  public static ObjectSignature produceSignature(String shortName, String longName, long[] signature)
89
    {
90
    // 'BAN*_*' ( or future possible 'BA**_*' ) objects
91
    if( shortName.charAt(0)=='B' && shortName.charAt(1)=='A' && shortName.charAt(4)=='_' )
92
      {
93
      char second = shortName.charAt(2);
94
      char third  = shortName.charAt(3);
95

    
96
      if( (second=='N' || (second>='0' && second<='9')) && (third>='0' && third<='9') )
97
        {
98
        int size = shortName.charAt(5) - '0';
99
        if( size>=2 && size<=MAX_SUPPORTED_SIZE ) return new ObjectSignature(size,signature);
100
        }
101
      }
102

    
103
    if( longName.equals(OBJECT_NAME) ) new ObjectSignature(shortName,signature);
104

    
105
    return new ObjectSignature(signature);
106
    }
107

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

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

    
122
    try
123
      {
124
      JSONArray sigArray = metadata.getJSONArray("signature");
125
      int size = sigArray.length();
126
      long[] signature = new long[size];
127
      for(int i=0; i<size; i++) signature[i] = sigArray.getLong(i);
128
      mSignature = produceSignature(mShortName,mLongName,signature);
129
      }
130
    catch(JSONException ex)
131
      {
132
      long signature = metadata.getLong("signature");
133
      mSignature = new ObjectSignature(signature);
134
      }
135

    
136
    boolean free = metadata.optBoolean("free", true);
137

    
138
    if( free ) mPrice = 0;
139
    else mPrice = metadata.optInt("price", ObjectType.DEFAULT_PRICE_OF_OLD_OBJECTS );
140
    }
141

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

    
144
  private void parseCubits(JSONArray object) throws JSONException
145
    {
146
    int numCubits = object.length();
147

    
148
    mCubitQuats     = new Static4D[numCubits];
149
    mCubitVariant   = new int[numCubits];
150
    mPositions      = new float[numCubits][];
151
    mCubitFaceColor = new int[numCubits][];
152
    mCubitType      = new int[numCubits];
153
    mCubitRowOffset = new float[numCubits][];
154

    
155
    for(int i=0; i<numCubits; i++)
156
      {
157
      JSONObject jsonCubit = object.getJSONObject(i);
158

    
159
      float qx = (float)jsonCubit.getDouble("qx");
160
      float qy = (float)jsonCubit.getDouble("qy");
161
      float qz = (float)jsonCubit.getDouble("qz");
162
      float qw = (float)jsonCubit.getDouble("qw");
163

    
164
      mCubitQuats[i] = new Static4D(qx,qy,qz,qw);
165
      mCubitVariant[i] = jsonCubit.getInt("variant");
166

    
167
      JSONArray jsonCenter = jsonCubit.getJSONArray("centers");
168
      int numCenter = jsonCenter.length();
169
      mPositions[i] = new float[numCenter];
170
      for(int j=0; j<numCenter; j++) mPositions[i][j] = (float)jsonCenter.getDouble(j);
171

    
172
      JSONArray jsonColor  = jsonCubit.getJSONArray("colors");
173
      int numColor = jsonColor.length();
174
      mCubitFaceColor[i] = new int[numColor];
175
      for(int j=0; j<numColor; j++) mCubitFaceColor[i][j] = jsonColor.getInt(j);
176

    
177
      mCubitType[i] = jsonCubit.optInt("type", TwistyObjectCubit.TYPE_NORMAL);
178
      float xoff = (float)jsonCubit.optDouble("offsetX", 0 );
179
      float yoff = (float)jsonCubit.optDouble("offsetY", 0 );
180
      float zoff = (float)jsonCubit.optDouble("offsetZ", 0 );
181
      mCubitRowOffset[i] = new float[] {xoff,yoff,zoff};
182
      }
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
  private void parseShapes(JSONArray object) throws JSONException
188
    {
189
    mNumCubitVariants     = object.length();
190
    mVariantStickerShape  = new int[mNumCubitVariants][];
191
    mVariantFaceIsOuter   = new int[mNumCubitVariants][];
192
    mShapes               = new ObjectShape[mNumCubitVariants];
193
    mFaceShapes           = new ObjectFaceShape[mNumCubitVariants];
194
    mVertexEffects        = new ObjectVertexEffects[mNumCubitVariants];
195
    float[][][] verts     = new float[mNumCubitVariants][][];
196
    float[][][] bands     = new float[mNumCubitVariants][][];
197
    float[][] convexity   = new float[mNumCubitVariants][];
198
    int[][] bandIndices   = new int[mNumCubitVariants][];
199
    int[][][] vertIndices = new int[mNumCubitVariants][][];
200

    
201
    mNumCubitFaces = -1;
202

    
203
    for(int i=0; i<mNumCubitVariants; i++)
204
      {
205
      JSONObject jsonShape = object.getJSONObject(i);
206

    
207
      ////// vertices /////////////////////////////////////////////////
208
      JSONArray jsonVertices= jsonShape.getJSONArray("vertices");
209
      int numVertices = jsonVertices.length();
210
      verts[i] = new float[numVertices][3];
211

    
212
      for(int j=0; j<numVertices; j++)
213
        {
214
        JSONObject vert = jsonVertices.getJSONObject(j);
215
        verts[i][j][0] = (float)vert.getDouble("x");
216
        verts[i][j][1] = (float)vert.getDouble("y");
217
        verts[i][j][2] = (float)vert.getDouble("z");
218
        }
219

    
220
      ////// faces ////////////////////////////////////////////////////
221
      JSONArray jsonFaces= jsonShape.getJSONArray("faces");
222
      int numFaces = jsonFaces.length();
223
      mVariantStickerShape[i]= new int[numFaces];
224
      mVariantFaceIsOuter[i] = new int[numFaces];
225
      bandIndices[i] = new int[numFaces];
226
      vertIndices[i] = new int[numFaces][];
227

    
228
      if( mNumCubitFaces<numFaces ) mNumCubitFaces=numFaces;
229

    
230
      for(int j=0; j<numFaces; j++)
231
        {
232
        JSONObject jsonFace = jsonFaces.getJSONObject(j);
233
        mVariantStickerShape[i][j]= jsonFace.getInt("sticker");
234
        mVariantFaceIsOuter[i][j] = jsonFace.optInt("isOuter",0);
235
        bandIndices[i][j] = jsonFace.getInt("bandIndex");
236
        JSONArray vertices = jsonFace.getJSONArray("vertexIndices");
237
        int numV = vertices.length();
238
        vertIndices[i][j] = new int[numV];
239
        for(int k=0; k<numV; k++) vertIndices[i][j][k] = vertices.getInt(k);
240
        }
241

    
242
      ////// bands ////////////////////////////////////////////////////
243
      JSONArray jsonBands= jsonShape.getJSONArray("bands");
244
      int numBands = jsonBands.length();
245
      bands[i] = new float[numBands][7];
246

    
247
      for(int j=0; j<numBands; j++)
248
        {
249
        JSONObject jsonBand = jsonBands.getJSONObject(j);
250

    
251
        bands[i][j][0] = (float)jsonBand.getDouble("height");
252
        bands[i][j][1] = (float)jsonBand.getDouble("angle");
253
        bands[i][j][2] = (float)jsonBand.getDouble("distanceToCenter");
254
        bands[i][j][3] = (float)jsonBand.getDouble("distanceToFlat");
255
        bands[i][j][4] = (float)jsonBand.getDouble("numOfBands");
256
        bands[i][j][5] = (float)jsonBand.getDouble("extraI");
257
        bands[i][j][6] = (float)jsonBand.getDouble("extraJ");
258
        }
259

    
260
      ////// convexity ///////////////////////////////////////////////
261
      JSONObject jsonConvexity = jsonShape.optJSONObject("convexity");
262

    
263
      if( jsonConvexity!=null )
264
        {
265
        convexity[i] = new float[3];
266
        convexity[i][0] = (float)jsonConvexity.getDouble("x");
267
        convexity[i][1] = (float)jsonConvexity.getDouble("y");
268
        convexity[i][2] = (float)jsonConvexity.getDouble("z");
269
        }
270

    
271
      ////// effects /////////////////////////////////////////////////
272
      JSONArray jsonEffects = jsonShape.optJSONArray("effects");
273

    
274
      if( jsonEffects!=null )
275
        {
276
        int numEffects = jsonEffects.length();
277

    
278
        String[] name    = new String[numEffects];
279
        float[][] vars   = new float[numEffects][5];
280
        float[][] center = new float[numEffects][3];
281
        float[][] region = new float[numEffects][4];
282
        boolean[] use    = new boolean[numEffects];
283

    
284
        for(int j=0; j<numEffects; j++)
285
          {
286
          JSONObject jsonEffect = jsonEffects.getJSONObject(j);
287

    
288
          name[j] = jsonEffect.getString("name");
289

    
290
          vars[j][0] = (float)jsonEffect.getDouble("var0");
291
          vars[j][1] = (float)jsonEffect.getDouble("var1");
292
          vars[j][2] = (float)jsonEffect.getDouble("var2");
293
          vars[j][3] = (float)jsonEffect.getDouble("var3");
294
          vars[j][4] = (float)jsonEffect.getDouble("var4");
295

    
296
          center[j][0] = (float)jsonEffect.getDouble("center0");
297
          center[j][1] = (float)jsonEffect.getDouble("center1");
298
          center[j][2] = (float)jsonEffect.getDouble("center2");
299

    
300
          region[j][0] = (float)jsonEffect.getDouble("region0");
301
          region[j][1] = (float)jsonEffect.getDouble("region1");
302
          region[j][2] = (float)jsonEffect.getDouble("region2");
303
          region[j][3] = (float)jsonEffect.getDouble("region3");
304

    
305
          use[j] = jsonEffect.getBoolean("use");
306
          }
307

    
308
        mVertexEffects[i] = new ObjectVertexEffects(name,vars,center,region,use);
309
        }
310
      }
311

    
312
    for(int i=0; i<mNumCubitVariants; i++)
313
      {
314
      mShapes[i] = new ObjectShape(verts[i],vertIndices[i]);
315
      mFaceShapes[i] = new ObjectFaceShape(bands[i],bandIndices[i],convexity[i]);
316
      }
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
  private void parseStickers(JSONArray object) throws JSONException
322
    {
323
    mNumStickerTypes = object.length();
324
    mObjectSticker = new ObjectSticker[mNumStickerTypes];
325

    
326
    for(int i=0; i<mNumStickerTypes; i++)
327
      {
328
      JSONObject sticker = object.getJSONObject(i);
329
      float stroke = (float)sticker.getDouble("stroke");
330
      JSONArray vertices = sticker.getJSONArray("vertices");
331
      int numVertices = vertices.length();
332

    
333
      float[] coords     = new float[2*numVertices];
334
      float[] curvatures = new float[numVertices];
335
      float[] radii      = new float[numVertices];
336

    
337
      for(int j=0; j<numVertices; j++)
338
        {
339
        JSONObject vertex = vertices.getJSONObject(j);
340

    
341
        coords[2*j  ] = (float)vertex.getDouble("x");
342
        coords[2*j+1] = (float)vertex.getDouble("y");
343
        curvatures[j] = (float)vertex.getDouble("angle");
344
        radii[j]      = (float)vertex.getDouble("radius");
345
        }
346

    
347
      mObjectSticker[i] = new ObjectSticker(coords,curvatures,radii,stroke);
348
      }
349
    }
350

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

    
353
  private void parseOverrides(JSONArray object) throws JSONException
354
    {
355
    if( object!=null )
356
      {
357
      int numOverrides = object.length();
358
      mStickerOverrides= new ObjectStickerOverride[numOverrides];
359

    
360
      for(int i=0; i<numOverrides; i++)
361
        {
362
        JSONObject override  = object.getJSONObject(i);
363
        JSONArray cubitArray = override.getJSONArray("cubitfaces");
364
        int color = override.getInt("color");
365
        int numCubits = cubitArray.length();
366
        int[] cubitface = new int[numCubits];
367
        for(int j=0; j<numCubits; j++) cubitface[j] = cubitArray.getInt(j);
368
        mStickerOverrides[i] = new ObjectStickerOverride(cubitface,color);
369
        }
370
      }
371
    else
372
      {
373
      mStickerOverrides = null;
374
      }
375
    }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

    
379
  private void parseMesh(JSONObject object) throws JSONException
380
    {
381
    JSONArray cubits   = object.getJSONArray("cubits");
382
    parseCubits(cubits);
383
    JSONArray shapes   = object.getJSONArray("shapes");
384
    parseShapes(shapes);
385
    JSONArray stickers = object.getJSONArray("stickers");
386
    parseStickers(stickers);
387

    
388
    JSONArray overrides= object.optJSONArray("overrides");
389
    parseOverrides(overrides);
390

    
391
    mPillowCoeff = (float)object.optDouble("pillow",1.0);
392
    }
393

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

    
396
  private void parseAxis(JSONArray object) throws JSONException
397
    {
398
    int numAxis = object.length();
399

    
400
    mBasicAngle     = new int[numAxis][];
401
    mAxis           = new Static3D[numAxis];
402
    mCuts           = new float[numAxis][];
403
    mLayerRotatable = new boolean[numAxis][];
404
    mNumLayers      = new int[numAxis];
405

    
406
    for(int i=0; i<numAxis; i++)
407
      {
408
      JSONObject jsonAx = object.getJSONObject(i);
409

    
410
      float x = (float)jsonAx.getDouble("x");
411
      float y = (float)jsonAx.getDouble("y");
412
      float z = (float)jsonAx.getDouble("z");
413

    
414
      mAxis[i] = new Static3D(x,y,z);
415

    
416
      JSONArray jsonAngles = jsonAx.getJSONArray("basicAngles");
417
      int numAngles = jsonAngles.length();
418
      mBasicAngle[i] = new int[numAngles];
419
      for(int j=0; j<numAngles; j++) mBasicAngle[i][j] = jsonAngles.getInt(j);
420

    
421
      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
422
      int numCuts = jsonCuts.length();
423
      mCuts[i] = new float[numCuts];
424
      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
425

    
426
      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
427
      int numRota = jsonRota.length();
428
      mLayerRotatable[i] = new boolean[numRota];
429
      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
430

    
431
      mNumLayers[i] = numRota;
432
      }
433
    }
434

    
435
///////////////////////////////////////////////////////////////////////////////////////////////////
436

    
437
  private void parseQuats(JSONArray object) throws JSONException
438
    {
439
    int numQuats = object.length();
440
    mQuats = new Static4D[numQuats];
441

    
442
    for(int i=0; i<numQuats; i++)
443
      {
444
      JSONObject jsonQuat = object.getJSONObject(i);
445

    
446
      float x = (float)jsonQuat.getDouble("x");
447
      float y = (float)jsonQuat.getDouble("y");
448
      float z = (float)jsonQuat.getDouble("z");
449
      float w = (float)jsonQuat.getDouble("w");
450

    
451
      mQuats[i] = new Static4D(x,y,z,w);
452
      }
453
    }
454

    
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

    
457
  private int getAlgorithmIndex(int ax, int layer, int angle)
458
    {
459
    int numAlgs = mAlgorithms.length;
460

    
461
    for(int alg=0; alg<numAlgs; alg++)
462
      {
463
      int[] a = mAlgorithms[alg];
464
      if( a.length>=3 && a[0]==ax && a[1]==layer && a[2]==angle ) return alg;
465
      }
466

    
467
    return -1;
468
    }
469

    
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471

    
472
  private int[] produceEdge(int[][] scramblingData)
473
    {
474
    int index=0, length=0;
475
    int numAxis = scramblingData.length;
476
    for (int[] scramblingDatum : scramblingData) length += scramblingDatum.length;
477

    
478
    int[] ret = new int[2*length/3];
479

    
480
    for(int ax=0; ax<numAxis; ax++)
481
      {
482
      int[] data = scramblingData[ax];
483
      int num = data.length/3;
484

    
485
      for(int j=0; j<num; j++)
486
        {
487
        int layer = data[3*j];
488
        int angle = data[3*j+1];
489
        int state = data[3*j+2];
490

    
491
        ret[2*index  ] = getAlgorithmIndex(ax,layer,angle);
492
        ret[2*index+1] = state;
493
        index++;
494
        }
495
      }
496

    
497
    return ret;
498
    }
499

    
500
///////////////////////////////////////////////////////////////////////////////////////////////////
501

    
502
  private void parseScrambling6(JSONObject object) throws JSONException
503
    {
504
    JSONArray jsonStates = object.getJSONArray("scrambleStates");
505
    int numStates = jsonStates.length();
506
    int[][][] scramblingData = new int[numStates][][];
507

    
508
    for(int i=0; i<numStates; i++)
509
      {
510
      JSONArray jsonState = jsonStates.getJSONArray(i);
511
      int numAxis = jsonState.length();
512
      scramblingData[i] = new int[numAxis][];
513

    
514
      for(int j=0; j<numAxis; j++)
515
        {
516
        JSONArray jsonData = jsonState.getJSONArray(j);
517
        int numData = jsonData.length();
518
        scramblingData[i][j] = new int[numData];
519
        for(int k=0; k<numData; k++) scramblingData[i][j][k] = jsonData.getInt(k);
520
        }
521
      }
522

    
523
    mAlgorithms = ScrambleEdgeGenerator.getScramblingAlgorithms(mBasicAngle);
524
    mEdges = new int[numStates][];
525
    for(int i=0; i<numStates; i++) mEdges[i] = produceEdge(scramblingData[i]);
526
    }
527

    
528
///////////////////////////////////////////////////////////////////////////////////////////////////
529

    
530
  private void parseScrambling7orMore(JSONObject object) throws JSONException
531
    {
532
    JSONArray jsonAlgorithms = object.getJSONArray("algorithms");
533
    int numAlgs = jsonAlgorithms.length();
534
    mAlgorithms = new int[numAlgs][];
535

    
536
    for(int i=0; i<numAlgs; i++)
537
      {
538
      JSONArray jsonAlg = jsonAlgorithms.getJSONArray(i);
539
      int numEntries = jsonAlg.length();
540
      mAlgorithms[i] = new int[numEntries];
541
      for(int j=0; j<numEntries; j++) mAlgorithms[i][j] = jsonAlg.getInt(j);
542
      }
543

    
544
    JSONArray jsonEdges = object.getJSONArray("edges");
545
    int numEdges = jsonEdges.length();
546
    mEdges = new int[numEdges][];
547

    
548
    for(int i=0; i<numEdges; i++)
549
      {
550
      JSONArray jsonEdge = jsonEdges.getJSONArray(i);
551
      int numEntries = jsonEdge.length();
552
      mEdges[i] = new int[numEntries];
553
      for(int j=0; j<numEntries; j++) mEdges[i][j] = jsonEdge.getInt(j);
554
      }
555
    }
556

    
557
///////////////////////////////////////////////////////////////////////////////////////////////////
558

    
559
  private void parseScrambling(JSONObject object, int major) throws JSONException
560
    {
561
    mScrambleType = object.getInt("scrambleType");
562

    
563
    if( mScrambleType==0 )
564
      {
565
      if( major==6 ) parseScrambling6(object);
566
      else           parseScrambling7orMore(object);
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 parseFile(JSONObject object, int major) throws JSONException
658
    {
659
    JSONObject metadata    = object.getJSONObject("metadata");
660
    parseMetadata(metadata);
661
    JSONObject mesh        = object.getJSONObject("mesh");
662
    parseMesh(mesh);
663
    JSONArray axis         = object.getJSONArray("axis");
664
    parseAxis(axis);
665
    JSONArray quats        = object.getJSONArray("quats");
666
    parseQuats(quats);
667
    JSONObject scrambling  = object.getJSONObject("scrambling");
668
    parseScrambling(scrambling,major);
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 parseTutorial(JSONObject object) throws JSONException
680
    {
681
    mTutorialObject = object.getString("object");
682
    JSONArray tuts= object.getJSONArray("tutorials");
683

    
684
    int len = tuts.length();
685
    mTutorials = new String[len][4];
686

    
687
    for(int i=0; i<len; i++)
688
      {
689
      JSONObject tut = tuts.getJSONObject(i);
690
      mTutorials[i][0] = tut.getString("language");
691
      mTutorials[i][1] = tut.getString("link");
692
      mTutorials[i][2] = tut.getString("title");
693
      mTutorials[i][3] = tut.getString("author");
694
      }
695
    }
696

    
697
///////////////////////////////////////////////////////////////////////////////////////////////////
698
// PUBLIC
699
///////////////////////////////////////////////////////////////////////////////////////////////////
700

    
701
  public void parseJsonFile(InputStream jsonStream) throws JSONException, IOException
702
    {
703
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
704
    StringBuilder contents = new StringBuilder();
705
    String line;
706

    
707
    while( (line = br.readLine()) != null) contents.append(line);
708
    br.close();
709
    jsonStream.close();
710
    String contentsString = contents.toString();
711
    JSONObject object = new JSONObject(contentsString);
712
    int major = object.getInt("major");
713

    
714
    if( major>=6 )
715
      {
716
      parseFile(object,major);
717
      }
718
    else
719
      {
720
      android.util.Log.e("readJsonFile", "Unknown version "+major);
721
      }
722
    }
723

    
724
///////////////////////////////////////////////////////////////////////////////////////////////////
725

    
726
  public void parseJsonFileMetadata(InputStream jsonStream) throws JSONException, IOException
727
    {
728
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
729
    StringBuilder contents = new StringBuilder();
730
    String tmp;
731

    
732
    while( (tmp = br.readLine()) != null) contents.append(tmp);
733
    br.close();
734
    jsonStream.close();
735

    
736
    JSONObject object = new JSONObject(contents.toString());
737
    int major = object.getInt("major");
738

    
739
    if( major>=6 )
740
      {
741
      JSONObject metadata = object.getJSONObject("metadata");
742
      parseMetadata(metadata);
743
      }
744
    else
745
      {
746
      android.util.Log.e("readJsonFileQuick", "Unknown version "+major);
747
      }
748
    }
749

    
750
///////////////////////////////////////////////////////////////////////////////////////////////////
751

    
752
  public void readNumScramblesAndPrice(Context context, String fileName) throws IOException, JSONException
753
    {
754
    File file = new File(context.getFilesDir(), fileName);
755
    InputStream stream = new FileInputStream(file);
756
    BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
757

    
758
    StringBuilder contents = new StringBuilder();
759
    String tmp;
760
    while( (tmp = br.readLine()) != null) contents.append(tmp);
761
    br.close();
762
    stream.close();
763

    
764
    JSONObject object = new JSONObject(contents.toString());
765
    JSONObject metadata = object.getJSONObject("metadata");
766
    mNumScrambles = metadata.getInt("scrambles");
767

    
768
    boolean free = metadata.optBoolean("free",true);
769
    if( free ) mPrice = 0;
770
    else mPrice = metadata.optInt("price", ObjectType.DEFAULT_PRICE_OF_OLD_OBJECTS );
771
    }
772

    
773
///////////////////////////////////////////////////////////////////////////////////////////////////
774

    
775
  public void parseJsonTutorial(InputStream jsonStream) throws IOException, JSONException
776
    {
777
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
778
    StringBuilder contents = new StringBuilder();
779
    String tmp;
780

    
781
    while( (tmp = br.readLine()) != null) contents.append(tmp);
782
    br.close();
783
    jsonStream.close();
784

    
785
    JSONObject object = new JSONObject(contents.toString());
786
    int major = object.getInt("major");
787

    
788
    if( major==1 )
789
      {
790
      parseTutorial(object);
791
      }
792
    else
793
      {
794
      android.util.Log.e("readJsonFile", "Unknown tutorial version "+major);
795
      }
796
    }
797

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

    
800
  public int getScrambleType()
801
    {
802
    return mScrambleType;
803
    }
804

    
805
///////////////////////////////////////////////////////////////////////////////////////////////////
806

    
807
  public int[][] getScrambleEdges()
808
    {
809
    return mEdges;
810
    }
811

    
812
///////////////////////////////////////////////////////////////////////////////////////////////////
813

    
814
  public int[][] getScrambleAlgorithms()
815
    {
816
    return mAlgorithms;
817
    }
818

    
819
///////////////////////////////////////////////////////////////////////////////////////////////////
820

    
821
  public int[][] getSolvedQuats()
822
    {
823
    return mSolvedQuats;
824
    }
825

    
826
///////////////////////////////////////////////////////////////////////////////////////////////////
827

    
828
  public Static4D[] getQuats()
829
    {
830
    return mQuats;
831
    }
832

    
833
///////////////////////////////////////////////////////////////////////////////////////////////////
834

    
835
  public int getSolvedFunctionIndex()
836
    {
837
    return mSolvedFuncIndex;
838
    }
839

    
840
///////////////////////////////////////////////////////////////////////////////////////////////////
841

    
842
  public int getNumStickerTypes()
843
    {
844
    return mNumStickerTypes;
845
    }
846

    
847
///////////////////////////////////////////////////////////////////////////////////////////////////
848

    
849
  public float[][] getCuts()
850
    {
851
    return mCuts;
852
    }
853

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

    
856
  public boolean[][] getLayerRotatable()
857
    {
858
    return mLayerRotatable;
859
    }
860

    
861
///////////////////////////////////////////////////////////////////////////////////////////////////
862

    
863
  public int getMovementType()
864
    {
865
    return mMovementType;
866
    }
867

    
868
///////////////////////////////////////////////////////////////////////////////////////////////////
869

    
870
  public int getMovementSplit()
871
    {
872
    return mMovementSplit;
873
    }
874

    
875
///////////////////////////////////////////////////////////////////////////////////////////////////
876

    
877
  public int[][][] getEnabled()
878
    {
879
    return mEnabled;
880
    }
881

    
882
///////////////////////////////////////////////////////////////////////////////////////////////////
883

    
884
  public float[] getDist3D()
885
    {
886
    return mDist3D;
887
    }
888

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

    
891
  public int getNumCubitFaces()
892
    {
893
    return mNumCubitFaces;
894
    }
895

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

    
898
  public float[][] getCubitPositions()
899
    {
900
    return mPositions;
901
    }
902

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

    
905
  public ObjectShape getObjectShape(int variant)
906
    {
907
    return mShapes[variant];
908
    }
909

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

    
912
  public ObjectFaceShape getObjectFaceShape(int variant)
913
    {
914
    return mFaceShapes[variant];
915
    }
916

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

    
919
  public ObjectVertexEffects getVertexEffects(int variant)
920
    {
921
    return mVertexEffects[variant];
922
    }
923

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

    
926
  public Static4D getCubitQuats(int cubit)
927
    {
928
    return mCubitQuats[cubit];
929
    }
930

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

    
933
  public int getNumCubitVariants()
934
    {
935
    return mNumCubitVariants;
936
    }
937

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

    
940
  public int getCubitVariant(int cubit)
941
    {
942
    return mCubitVariant[cubit];
943
    }
944

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

    
947
  public int getVariantStickerShape(int variant, int face)
948
    {
949
    int[] shapes = mVariantStickerShape[variant];
950
    return shapes.length>face ? shapes[face] : -1;
951
    }
952

    
953
///////////////////////////////////////////////////////////////////////////////////////////////////
954

    
955
  public int[] getCubitTypes()
956
    {
957
    return mCubitType;
958
    }
959

    
960
///////////////////////////////////////////////////////////////////////////////////////////////////
961

    
962
  public float[][] getCubitOffsets()
963
    {
964
    return mCubitRowOffset;
965
    }
966

    
967
///////////////////////////////////////////////////////////////////////////////////////////////////
968

    
969
  public int[][] getVariantFaceIsOuter()
970
    {
971
    return mVariantFaceIsOuter;
972
    }
973

    
974
///////////////////////////////////////////////////////////////////////////////////////////////////
975

    
976
  public int getCubitFaceFace(int cubit, int face)
977
    {
978
    return mCubitFaceColor[cubit][face];
979
    }
980

    
981
///////////////////////////////////////////////////////////////////////////////////////////////////
982

    
983
  public int getNumScrambles()
984
    {
985
    return mNumScrambles;
986
    }
987

    
988
///////////////////////////////////////////////////////////////////////////////////////////////////
989

    
990
  public int getPrice()
991
    {
992
    return mPrice;
993
    }
994

    
995
///////////////////////////////////////////////////////////////////////////////////////////////////
996

    
997
  public ObjectSticker retSticker(int sticker)
998
    {
999
    return mObjectSticker[sticker];
1000
    }
1001

    
1002
///////////////////////////////////////////////////////////////////////////////////////////////////
1003

    
1004
  public ObjectStickerOverride[] getStickerOverrides()
1005
    {
1006
    return mStickerOverrides;
1007
    }
1008

    
1009
///////////////////////////////////////////////////////////////////////////////////////////////////
1010

    
1011
  public float getPillowCoeff()
1012
    {
1013
    return mPillowCoeff;
1014
    }
1015

    
1016
///////////////////////////////////////////////////////////////////////////////////////////////////
1017

    
1018
  public Static3D[] getRotationAxis()
1019
    {
1020
    return mAxis;
1021
    }
1022

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

    
1025
  public int[][] getBasicAngle()
1026
    {
1027
    return mBasicAngle;
1028
    }
1029

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

    
1032
  public ObjectSignature getSignature()
1033
    {
1034
    return mSignature;
1035
    }
1036

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

    
1039
  public String getObjectName()
1040
    {
1041
    return mLongName;
1042
    }
1043

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

    
1046
  public String getShortName()
1047
    {
1048
    return mShortName;
1049
    }
1050

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

    
1053
  public String getInventor()
1054
    {
1055
    return mInventor;
1056
    }
1057

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

    
1060
  public int getYearOfInvention()
1061
    {
1062
    return mYearOfInvention;
1063
    }
1064

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

    
1067
  public int getComplexity()
1068
    {
1069
    return mComplexity;
1070
    }
1071

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

    
1074
  public int getNumFaces()
1075
    {
1076
    return mNumFaces;
1077
    }
1078

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

    
1081
  public int getNumFaceColors()
1082
    {
1083
    return mNumFaceColors;
1084
    }
1085

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

    
1088
  public int[] getNumLayers()
1089
    {
1090
    return mNumLayers;
1091
    }
1092

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

    
1095
  public float getSize()
1096
    {
1097
    return mSize;
1098
    }
1099

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

    
1102
  public int getColor(int face)
1103
    {
1104
    return mColor[face];
1105
    }
1106

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

    
1109
  public int getInternalColor()
1110
    {
1111
    return mInternalColor;
1112
    }
1113

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

    
1116
  public boolean shouldResetTextureMaps()
1117
    {
1118
    return mResetMaps;
1119
    }
1120

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

    
1123
  public String getTutorialObject()
1124
    {
1125
    return mTutorialObject;
1126
    }
1127

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

    
1130
  public String[][] getTutorials()
1131
    {
1132
    return mTutorials;
1133
    }
1134
}
(1-1/2)