Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.json;
21

    
22
import java.io.BufferedReader;
23
import java.io.File;
24
import java.io.FileInputStream;
25
import java.io.FileNotFoundException;
26
import java.io.IOException;
27
import java.io.InputStream;
28
import java.io.InputStreamReader;
29
import java.nio.charset.StandardCharsets;
30

    
31
import android.content.Context;
32

    
33
import org.distorted.objectlib.helpers.ObjectFaceShape;
34
import org.distorted.objectlib.helpers.ObjectSignature;
35
import org.distorted.objectlib.helpers.ObjectStickerOverride;
36
import org.distorted.objectlib.main.Cubit;
37
import org.distorted.objectlib.objects.TwistyBandagedCuboid;
38
import org.json.JSONArray;
39
import org.json.JSONException;
40
import org.json.JSONObject;
41

    
42
import org.distorted.library.type.Static3D;
43
import org.distorted.library.type.Static4D;
44

    
45
import org.distorted.objectlib.helpers.ObjectShape;
46
import org.distorted.objectlib.helpers.ObjectSticker;
47
import org.distorted.objectlib.scrambling.ScrambleState;
48
import org.distorted.objectlib.main.ObjectType;
49

    
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51

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

    
90
  private static JsonReader mThis;
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  private JsonReader()
95
    {
96
    }
97

    
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99

    
100
  public static JsonReader getInstance()
101
    {
102
    if( mThis==null ) mThis = new JsonReader();
103
    return mThis;
104
    }
105

    
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107

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

    
120
    try
121
      {
122
      long signature = object.getLong("signature");
123
      mSignature = new ObjectSignature(signature);
124
      }
125
    catch(JSONException ex)
126
      {
127
      // objects older than Feb 2022 do not have the 'signature' field. They all use the ObjectType.ordinal
128
      // as their signature.
129
      long signature = ObjectType.getOrdinal(mShortName);
130
      mSignature = new ObjectSignature(signature);
131
      }
132
    }
133

    
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135

    
136
  private void parseMetadata2or3or4(JSONObject object) throws JSONException
137
    {
138
    mLongName        = object.getString("longname");
139
    mShortName       = object.getString("shortname");
140
    mInventor        = object.getString("inventor");
141
    mYearOfInvention = object.getInt("year");
142
    mComplexity      = object.getInt("complexity");
143
    mSize            = (float)object.getDouble("size");
144
    mNumScrambles    = object.getInt("scrambles");
145
    mResetMaps       = object.getBoolean("resetmaps");
146
    mNumFaces        = object.getInt("num_faces");
147

    
148
    try
149
      {
150
      long signature1 = object.getLong("signature1");
151
      long signature2 = object.getLong("signature2");
152
      long signature3 = object.getLong("signature3");
153

    
154
      switch( TwistyBandagedCuboid.getType(mShortName,mLongName) )
155
        {
156
        case 0: mSignature = new ObjectSignature(signature1,signature2,signature3); break;
157
        case 1: mSignature = new ObjectSignature(mShortName,signature1,signature2,signature3); break;
158
        case 2: mSignature = new ObjectSignature("333",signature1,signature2,signature3); break;
159
        }
160
      }
161
    catch(JSONException ex)
162
      {
163
      long signature = object.getLong("signature");
164
      mSignature = new ObjectSignature(signature);
165
      }
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

    
170
  private void parseCubits(JSONArray object) throws JSONException
171
    {
172
    int numCubits = object.length();
173

    
174
    mCubitQuats     = new Static4D[numCubits];
175
    mCubitVariant   = new int[numCubits];
176
    mPositions      = new float[numCubits][];
177
    mCubitFaceColor = new int[numCubits][];
178
    mCubitType      = new int[numCubits];
179
    mCubitRowOffset = new float[numCubits][];
180

    
181
    for(int i=0; i<numCubits; i++)
182
      {
183
      JSONObject jsonCubit = object.getJSONObject(i);
184

    
185
      float qx = (float)jsonCubit.getDouble("qx");
186
      float qy = (float)jsonCubit.getDouble("qy");
187
      float qz = (float)jsonCubit.getDouble("qz");
188
      float qw = (float)jsonCubit.getDouble("qw");
189

    
190
      mCubitQuats[i] = new Static4D(qx,qy,qz,qw);
191
      mCubitVariant[i] = jsonCubit.getInt("variant");
192

    
193
      JSONArray jsonCenter = jsonCubit.getJSONArray("centers");
194
      int numCenter = jsonCenter.length();
195
      mPositions[i] = new float[numCenter];
196
      for(int j=0; j<numCenter; j++) mPositions[i][j] = (float)jsonCenter.getDouble(j);
197

    
198
      JSONArray jsonColor  = jsonCubit.getJSONArray("colors");
199
      int numColor = jsonColor.length();
200
      mCubitFaceColor[i] = new int[numColor];
201
      for(int j=0; j<numColor; j++) mCubitFaceColor[i][j] = jsonColor.getInt(j);
202

    
203
      mCubitType[i] = (int)jsonCubit.optInt("type", Cubit.TYPE_NORMAL);
204
      float xoff = (float)jsonCubit.optDouble("offsetX", 0 );
205
      float yoff = (float)jsonCubit.optDouble("offsetY", 0 );
206
      float zoff = (float)jsonCubit.optDouble("offsetZ", 0 );
207
      mCubitRowOffset[i] = new float[] {xoff,yoff,zoff};
208
      }
209
    }
210

    
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

    
213
  private void parseShapes(JSONArray object) throws JSONException
214
    {
215
    mNumCubitVariants     = object.length();
216
    mVariantFaceColor     = new int[mNumCubitVariants][];
217
    mVariantFaceIsOuter   = new int[mNumCubitVariants][];
218
    mShapes               = new ObjectShape[mNumCubitVariants];
219
    mFaceShapes           = new ObjectFaceShape[mNumCubitVariants];
220
    float[][][] verts     = new float[mNumCubitVariants][][];
221
    float[][][] bands     = new float[mNumCubitVariants][][];
222
    float[][][] corners   = new float[mNumCubitVariants][][];
223
    float[][][] centers   = new float[mNumCubitVariants][][];
224
    float[][] convexity   = new float[mNumCubitVariants][];
225
    int[][] cornerIndices = new int[mNumCubitVariants][];
226
    int[][] centerIndices = new int[mNumCubitVariants][];
227
    int[][] bandIndices   = new int[mNumCubitVariants][];
228
    int[][][] vertIndices = new int[mNumCubitVariants][][];
229

    
230
    mNumCubitFaces = -1;
231

    
232
    for(int i=0; i<mNumCubitVariants; i++)
233
      {
234
      JSONObject jsonShape = object.getJSONObject(i);
235

    
236
      ////// vertices /////////////////////////////////////////////////
237
      JSONArray jsonVertices= jsonShape.getJSONArray("vertices");
238
      int numVertices = jsonVertices.length();
239
      verts[i] = new float[numVertices][3];
240
      cornerIndices[i] = new int[numVertices];
241
      centerIndices[i] = new int[numVertices];
242

    
243
      for(int j=0; j<numVertices; j++)
244
        {
245
        JSONObject vert = jsonVertices.getJSONObject(j);
246
        verts[i][j][0] = (float)vert.getDouble("x");
247
        verts[i][j][1] = (float)vert.getDouble("y");
248
        verts[i][j][2] = (float)vert.getDouble("z");
249
        cornerIndices[i][j] = vert.getInt("cornerIndex");
250
        centerIndices[i][j] = vert.getInt("centerIndex");
251
        }
252

    
253
      ////// faces ////////////////////////////////////////////////////
254
      JSONArray jsonFaces= jsonShape.getJSONArray("faces");
255
      int numFaces = jsonFaces.length();
256
      mVariantFaceColor[i]   = new int[numFaces];
257
      mVariantFaceIsOuter[i] = new int[numFaces];
258
      bandIndices[i] = new int[numFaces];
259
      vertIndices[i] = new int[numFaces][];
260

    
261
      if( mNumCubitFaces<numFaces ) mNumCubitFaces=numFaces;
262

    
263
      for(int j=0; j<numFaces; j++)
264
        {
265
        JSONObject jsonFace = jsonFaces.getJSONObject(j);
266
        mVariantFaceColor[i][j]   = jsonFace.getInt("sticker");
267
        mVariantFaceIsOuter[i][j] = jsonFace.optInt("isOuter",0);
268
        bandIndices[i][j] = jsonFace.getInt("bandIndex");
269
        JSONArray vertices = jsonFace.getJSONArray("vertexIndices");
270
        int numV = vertices.length();
271
        vertIndices[i][j] = new int[numV];
272
        for(int k=0; k<numV; k++) vertIndices[i][j][k] = vertices.getInt(k);
273
        }
274

    
275
      ////// bands ////////////////////////////////////////////////////
276
      JSONArray jsonBands= jsonShape.getJSONArray("bands");
277
      int numBands = jsonBands.length();
278
      bands[i] = new float[numBands][7];
279

    
280
      for(int j=0; j<numBands; j++)
281
        {
282
        JSONObject jsonBand = jsonBands.getJSONObject(j);
283

    
284
        bands[i][j][0] = (float)jsonBand.getDouble("height");
285
        bands[i][j][1] = (float)jsonBand.getDouble("angle");
286
        bands[i][j][2] = (float)jsonBand.getDouble("distanceToCenter");
287
        bands[i][j][3] = (float)jsonBand.getDouble("distanceToFlat");
288
        bands[i][j][4] = (float)jsonBand.getDouble("numOfBands");
289
        bands[i][j][5] = (float)jsonBand.getDouble("extraI");
290
        bands[i][j][6] = (float)jsonBand.getDouble("extraJ");
291
        }
292

    
293
      ////// cornerPush ///////////////////////////////////////////////
294
      JSONArray jsonCornerPush= jsonShape.optJSONArray("cornerPush");
295

    
296
      if( jsonCornerPush!=null )
297
        {
298
        int numCornerP = jsonCornerPush.length();
299
        corners[i] = new float[numCornerP][2];
300

    
301
        for(int j=0; j<numCornerP; j++)
302
          {
303
          JSONObject jsonC = jsonCornerPush.getJSONObject(j);
304
          corners[i][j][0] = (float)jsonC.getDouble("strength");
305
          corners[i][j][1] = (float)jsonC.getDouble("radius");
306
          }
307
        }
308

    
309
      ////// centerPush ///////////////////////////////////////////////
310
      JSONArray jsonCenterPush= jsonShape.optJSONArray("centerPush");
311

    
312
      if( jsonCenterPush!=null )
313
        {
314
        int numCenterP = jsonCenterPush.length();
315
        centers[i] = new float[numCenterP][3];
316

    
317
        for(int j=0; j<numCenterP; j++)
318
          {
319
          JSONObject jsonC = jsonCenterPush.getJSONObject(j);
320
          centers[i][j][0] = (float)jsonC.getDouble("x");
321
          centers[i][j][1] = (float)jsonC.getDouble("y");
322
          centers[i][j][2] = (float)jsonC.getDouble("z");
323
          }
324
        }
325

    
326
      ////// convexity ///////////////////////////////////////////////
327
      JSONObject jsonConvexity = jsonShape.optJSONObject("convexity");
328

    
329
      if( jsonConvexity!=null )
330
        {
331
        convexity[i] = new float[3];
332
        convexity[i][0] = (float)jsonConvexity.getDouble("x");
333
        convexity[i][1] = (float)jsonConvexity.getDouble("y");
334
        convexity[i][2] = (float)jsonConvexity.getDouble("z");
335
        }
336
      }
337

    
338
    for(int i=0; i<mNumCubitVariants; i++)
339
      {
340
      mShapes[i] = new ObjectShape(verts[i],vertIndices[i]);
341
      mFaceShapes[i] = new ObjectFaceShape(bands[i],bandIndices[i],corners[i],cornerIndices[i],centers[i],centerIndices[i],convexity[i] );
342
      }
343
    }
344

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

    
347
  private void parseStickers(JSONArray object) throws JSONException
348
    {
349
    mNumStickerTypes = object.length();
350
    mObjectSticker = new ObjectSticker[mNumStickerTypes];
351

    
352
    for(int i=0; i<mNumStickerTypes; i++)
353
      {
354
      JSONObject sticker = object.getJSONObject(i);
355
      float stroke = (float)sticker.getDouble("stroke");
356
      JSONArray vertices = sticker.getJSONArray("vertices");
357
      int numVertices = vertices.length();
358

    
359
      float[] coords     = new float[2*numVertices];
360
      float[] curvatures = new float[numVertices];
361
      float[] radii      = new float[numVertices];
362

    
363
      for(int j=0; j<numVertices; j++)
364
        {
365
        JSONObject vertex = vertices.getJSONObject(j);
366

    
367
        coords[2*j  ] = (float)vertex.getDouble("x");
368
        coords[2*j+1] = (float)vertex.getDouble("y");
369
        curvatures[j] = (float)vertex.getDouble("angle");
370
        radii[j]      = (float)vertex.getDouble("radius");
371
        }
372

    
373
      mObjectSticker[i] = new ObjectSticker(coords,curvatures,radii,stroke);
374
      }
375
    }
376

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

    
379
  private void parseOverrides(JSONArray object) throws JSONException
380
    {
381
    int numOverrides = object.length();
382
    mStickerOverrides= new ObjectStickerOverride[numOverrides];
383

    
384
    for(int i=0; i<numOverrides; i++)
385
      {
386
      JSONObject override = object.getJSONObject(i);
387
      int cubit = override.getInt("cubit");
388
      int face  = override.getInt("face");
389
      int color = override.getInt("color");
390
      mStickerOverrides[i] = new ObjectStickerOverride(cubit,face,color);
391
      }
392
    }
393

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

    
396
  private void parseMesh(JSONObject object) throws JSONException
397
    {
398
    JSONArray cubits   = object.getJSONArray("cubits");
399
    parseCubits(cubits);
400
    JSONArray shapes   = object.getJSONArray("shapes");
401
    parseShapes(shapes);
402
    JSONArray stickers = object.getJSONArray("stickers");
403
    parseStickers(stickers);
404

    
405
    JSONArray overrides= object.optJSONArray("overrides");
406
    if( overrides!=null ) parseOverrides(overrides);
407
    }
408

    
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

    
411
  private void parseAxis1(JSONArray object) throws JSONException
412
    {
413
    int numAxis = object.length();
414

    
415
    mBasicAngle     = new int[numAxis][];
416
    mAxis           = new Static3D[numAxis];
417
    mCuts           = new float[numAxis][];
418
    mLayerRotatable = new boolean[numAxis][];
419
    mNumLayers      = new int[numAxis];
420

    
421
    for(int i=0; i<numAxis; i++)
422
      {
423
      JSONObject jsonAx = object.getJSONObject(i);
424

    
425
      float x = (float)jsonAx.getDouble("x");
426
      float y = (float)jsonAx.getDouble("y");
427
      float z = (float)jsonAx.getDouble("z");
428

    
429
      mAxis[i] = new Static3D(x,y,z);
430

    
431
      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
432
      int numCuts = jsonCuts.length();
433
      mCuts[i] = new float[numCuts];
434
      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
435

    
436
      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
437
      int numRota = jsonRota.length();
438
      mLayerRotatable[i] = new boolean[numRota];
439
      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
440

    
441
      mBasicAngle[i] = new int[numRota];
442
      int basicAngle = jsonAx.getInt("basicAngle");
443
      for(int j=0; j<numRota; j++) mBasicAngle[i][j] = basicAngle;
444

    
445
      mNumLayers[i] = numRota;
446
      }
447
    }
448

    
449
///////////////////////////////////////////////////////////////////////////////////////////////////
450

    
451
  private void parseAxis2or3or4(JSONArray object) throws JSONException
452
    {
453
    int numAxis = object.length();
454

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

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

    
465
      float x = (float)jsonAx.getDouble("x");
466
      float y = (float)jsonAx.getDouble("y");
467
      float z = (float)jsonAx.getDouble("z");
468

    
469
      mAxis[i] = new Static3D(x,y,z);
470

    
471
      JSONArray jsonAngles = jsonAx.getJSONArray("basicAngles");
472
      int numAngles = jsonAngles.length();
473
      mBasicAngle[i] = new int[numAngles];
474
      for(int j=0; j<numAngles; j++) mBasicAngle[i][j] = jsonAngles.getInt(j);
475

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

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

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

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491

    
492
  private void parseQuats(JSONArray object) throws JSONException
493
    {
494
    int numQuats = object.length();
495
    mQuats = new Static4D[numQuats];
496

    
497
    for(int i=0; i<numQuats; i++)
498
      {
499
      JSONObject jsonQuat = object.getJSONObject(i);
500

    
501
      float x = (float)jsonQuat.getDouble("x");
502
      float y = (float)jsonQuat.getDouble("y");
503
      float z = (float)jsonQuat.getDouble("z");
504
      float w = (float)jsonQuat.getDouble("w");
505

    
506
      mQuats[i] = new Static4D(x,y,z,w);
507
      }
508
    }
509

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

    
512
  private void parseScrambling(JSONObject object) throws JSONException
513
    {
514
    mScrambleType = object.getInt("scrambleType");
515

    
516
    if( mScrambleType==0 )
517
      {
518
      JSONArray jsonStates = object.getJSONArray("scrambleStates");
519
      int numStates = jsonStates.length();
520
      mStates = new ScrambleState[numStates];
521

    
522
      for(int i=0; i<numStates; i++)
523
        {
524
        JSONArray jsonState = jsonStates.getJSONArray(i);
525
        int numAxis = jsonState.length();
526
        int[][] scramblingData = new int[numAxis][];
527

    
528
        for(int j=0; j<numAxis; j++)
529
          {
530
          JSONArray jsonData = jsonState.getJSONArray(j);
531
          int numData = jsonData.length();
532
          scramblingData[j] = new int[numData];
533
          for(int k=0; k<numData; k++) scramblingData[j][k] = jsonData.getInt(k);
534
          }
535

    
536
        mStates[i] = new ScrambleState(scramblingData);
537
        }
538
      }
539
    }
540

    
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542

    
543
  private void parseTouchcontrol(JSONObject object) throws JSONException
544
    {
545
    mMovementType = object.getInt("movementType");
546
    mMovementSplit= object.getInt("movementSplit");
547

    
548
    try
549
      {
550
      JSONArray jsonEnabled = object.getJSONArray("enabledAxis");
551
      int numFace = jsonEnabled.length();
552

    
553
      mEnabled = new int[numFace][][];
554

    
555
      for(int i=0; i<numFace; i++)
556
        {
557
        JSONArray jsonSection = jsonEnabled.getJSONArray(i);
558
        int numSection = jsonSection.length();
559
        mEnabled[i] = new int[numSection][];
560

    
561
        for(int j=0; j<numSection; j++)
562
          {
563
          JSONArray jsonAx = jsonSection.getJSONArray(j);
564
          int numAxis = jsonAx.length();
565
          mEnabled[i][j] = new int[numAxis];
566
          for(int k=0; k<numAxis; k++) mEnabled[i][j][k] = jsonAx.getInt(k);
567
          }
568
        }
569
      }
570
    catch( JSONException ex )
571
      {
572
      // ignore, the object does not have to have 'enabledAxis' defined at all.
573
      }
574

    
575
    try
576
      {
577
      JSONArray jsonDist = object.getJSONArray("dist3D");
578
      int num = jsonDist.length();
579
      mDist3D = new float[num];
580
      for(int j=0; j<num; j++) mDist3D[j] = (float)jsonDist.getDouble(j);
581
      }
582
    catch( JSONException ex )
583
      {
584
      // ignore, the object does not have a 'dist3D' which is possible.
585
      }
586
    }
587

    
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589

    
590
  private void parseColors(JSONArray object) throws JSONException
591
    {
592
    mNumFaceColors = object.length()-1;
593

    
594
    mColor = new int[mNumFaceColors];
595
    for(int i=0; i<mNumFaceColors; i++) mColor[i] = object.getInt(i);
596

    
597
    mInternalColor = object.getInt(mNumFaceColors);
598
    }
599

    
600
///////////////////////////////////////////////////////////////////////////////////////////////////
601

    
602
  private void parseSolved(JSONObject solved) throws JSONException
603
    {
604
    mSolvedFuncIndex = solved.getInt("functionIndex");
605

    
606
    try
607
      {
608
      JSONArray groupArray= solved.getJSONArray("groups");
609
      int numGroups = groupArray.length();
610
      mSolvedQuats  = new int[numGroups][];
611

    
612
      for(int i=0; i<numGroups; i++)
613
        {
614
        JSONArray groupElements = groupArray.getJSONArray(i);
615
        int groupSize = groupElements.length();
616
        mSolvedQuats[i] = new int[groupSize];
617
        for(int j=0; j<groupSize; j++) mSolvedQuats[i][j] = groupElements.getInt(j);
618
        }
619
      }
620
    catch( JSONException ex )
621
      {
622
      // ignore, the object does not have to have an array of solved groups.
623
      }
624
    }
625

    
626
///////////////////////////////////////////////////////////////////////////////////////////////////
627

    
628
  private void parseVersion1(JSONObject object) throws JSONException
629
    {
630
    JSONObject metadata    = object.getJSONObject("metadata");
631
    parseMetadata1(metadata);
632
    JSONObject mesh        = object.getJSONObject("mesh");
633
    parseMesh(mesh);
634
    JSONArray axis         = object.getJSONArray("axis");
635
    parseAxis1(axis);
636
    JSONArray quats        = object.getJSONArray("quats");
637
    parseQuats(quats);
638
    JSONObject scrambling  = object.getJSONObject("scrambling");
639
    parseScrambling(scrambling);
640
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
641
    parseTouchcontrol(touchcontrol);
642
    JSONArray colors       = object.getJSONArray("colors");
643
    parseColors(colors);
644
    JSONObject solved      = object.getJSONObject("solved");
645
    parseSolved(solved);
646
    }
647

    
648
///////////////////////////////////////////////////////////////////////////////////////////////////
649

    
650
  private void parseVersion2or3or4(JSONObject object) throws JSONException
651
    {
652
    JSONObject metadata    = object.getJSONObject("metadata");
653
    parseMetadata2or3or4(metadata);
654
    JSONObject mesh        = object.getJSONObject("mesh");
655
    parseMesh(mesh);
656
    JSONArray axis         = object.getJSONArray("axis");
657
    parseAxis2or3or4(axis);
658
    JSONArray quats        = object.getJSONArray("quats");
659
    parseQuats(quats);
660
    JSONObject scrambling  = object.getJSONObject("scrambling");
661
    parseScrambling(scrambling);
662
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
663
    parseTouchcontrol(touchcontrol);
664
    JSONArray colors       = object.getJSONArray("colors");
665
    parseColors(colors);
666
    JSONObject solved      = object.getJSONObject("solved");
667
    parseSolved(solved);
668
    }
669

    
670
///////////////////////////////////////////////////////////////////////////////////////////////////
671

    
672
  private void parseVersion1Tutorial(JSONObject object) throws JSONException
673
    {
674
    mTutorialObject = object.getString("object");
675
    JSONArray tuts= object.getJSONArray("tutorials");
676

    
677
    int len = tuts.length();
678
    mTutorials = new String[len][4];
679

    
680
    for(int i=0; i<len; i++)
681
      {
682
      JSONObject tut = tuts.getJSONObject(i);
683
      mTutorials[i][0] = tut.getString("language");
684
      mTutorials[i][1] = tut.getString("link");
685
      mTutorials[i][2] = tut.getString("title");
686
      mTutorials[i][3] = tut.getString("author");
687
      }
688
    }
689

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

    
692
  private void parseVersion1Metadata(JSONObject object) throws JSONException
693
    {
694
    JSONObject metadata = object.getJSONObject("metadata");
695
    parseMetadata1(metadata);
696
    }
697

    
698
///////////////////////////////////////////////////////////////////////////////////////////////////
699

    
700
  private void parseVersion2or3or4Metadata(JSONObject object) throws JSONException
701
    {
702
    JSONObject metadata = object.getJSONObject("metadata");
703
    parseMetadata2or3or4(metadata);
704
    }
705

    
706
///////////////////////////////////////////////////////////////////////////////////////////////////
707

    
708
  public void parseJsonFile(InputStream jsonStream)
709
    {
710
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
711

    
712
    try
713
      {
714
      StringBuilder contents = new StringBuilder();
715
      String tmp;
716
      while( (tmp = br.readLine()) != null) contents.append(tmp);
717
      br.close();
718
      jsonStream.close();
719

    
720
      JSONObject object = new JSONObject(contents.toString());
721
      int major = object.getInt("major");
722

    
723
      if( major==1 )
724
        {
725
        parseVersion1(object);
726
        }
727
      else if( major==2 || major==3 || major==4 )
728
        {
729
        parseVersion2or3or4(object);
730
        }
731
      else
732
        {
733
        android.util.Log.e("readJsonFile", "Unknown version "+major);
734
        }
735
      }
736
    catch(IOException e)
737
      {
738
      android.util.Log.e("readJsonFile", "Error reading JSON file: "+e.toString());
739
      }
740
    catch( JSONException e )
741
      {
742
      android.util.Log.e("parseJsonFile", "Error parsing JSON file: "+e.toString());
743
      }
744
    }
745

    
746
///////////////////////////////////////////////////////////////////////////////////////////////////
747

    
748
  public void parseJsonFileMetadata(InputStream jsonStream)
749
    {
750
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
751

    
752
    try
753
      {
754
      StringBuilder contents = new StringBuilder();
755
      String tmp;
756
      while( (tmp = br.readLine()) != null) contents.append(tmp);
757
      br.close();
758
      jsonStream.close();
759

    
760
      JSONObject object = new JSONObject(contents.toString());
761
      int major = object.getInt("major");
762

    
763
      if( major==1 )
764
        {
765
        parseVersion1Metadata(object);
766
        }
767
      else if( major==2 || major==3 || major==4 )
768
        {
769
        parseVersion2or3or4Metadata(object);
770
        }
771
      else
772
        {
773
        android.util.Log.e("readJsonFileQuick", "Unknown version "+major);
774
        }
775
      }
776
    catch(IOException e)
777
      {
778
      android.util.Log.e("readJsonFileQuick", "Error reading JSON file: "+e.toString());
779
      }
780
    catch( JSONException e )
781
      {
782
      android.util.Log.e("parseJsonFileQuick", "Error parsing JSON file: "+e.toString());
783
      }
784
    }
785

    
786
///////////////////////////////////////////////////////////////////////////////////////////////////
787

    
788
  public int readNumScrambles(Context context, String fileName)
789
    {
790
    File file = new File(context.getFilesDir(), fileName);
791
    InputStream stream;
792

    
793
    try
794
      {
795
      stream = new FileInputStream(file);
796
      BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
797

    
798
      StringBuilder contents = new StringBuilder();
799
      String tmp;
800
      while( (tmp = br.readLine()) != null) contents.append(tmp);
801
      br.close();
802
      stream.close();
803

    
804
      JSONObject object = new JSONObject(contents.toString());
805
      JSONObject metadata = object.getJSONObject("metadata");
806
      return metadata.getInt("scrambles");
807
      }
808
    catch(FileNotFoundException ex)
809
      {
810
      android.util.Log.e("readNumScrambles", "file "+fileName+" not found: "+ex.getMessage());
811
      }
812
    catch(IOException e)
813
      {
814
      android.util.Log.e("readNumScrambles", "Error reading JSON file: "+e.toString());
815
      }
816
    catch( JSONException e )
817
      {
818
      android.util.Log.e("readNumScrambles", "Error parsing JSON file: "+e.toString());
819
      }
820

    
821
    return 0;
822
    }
823

    
824
///////////////////////////////////////////////////////////////////////////////////////////////////
825

    
826
  public void parseJsonTutorial(InputStream jsonStream)
827
    {
828
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
829

    
830
    try
831
      {
832
      StringBuilder contents = new StringBuilder();
833
      String tmp;
834
      while( (tmp = br.readLine()) != null) contents.append(tmp);
835
      br.close();
836
      jsonStream.close();
837

    
838
      JSONObject object = new JSONObject(contents.toString());
839
      int major = object.getInt("major");
840

    
841
      if( major==1 )
842
        {
843
        parseVersion1Tutorial(object);
844
        }
845
      else
846
        {
847
        android.util.Log.e("readJsonFile", "Unknown tutorial version "+major);
848
        }
849
      }
850
    catch(IOException e)
851
      {
852
      android.util.Log.e("readJsonFile", "Error reading JSON file: "+e.toString());
853
      }
854
    catch( JSONException e )
855
      {
856
      android.util.Log.e("parseJsonFile", "Error parsing JSON file: "+e.toString());
857
      }
858
    }
859

    
860
///////////////////////////////////////////////////////////////////////////////////////////////////
861

    
862
  public ScrambleState[] getScrambleStates()
863
    {
864
    return mStates;
865
    }
866

    
867
///////////////////////////////////////////////////////////////////////////////////////////////////
868

    
869
  public int[][] getSolvedQuats()
870
    {
871
    return mSolvedQuats;
872
    }
873

    
874
///////////////////////////////////////////////////////////////////////////////////////////////////
875

    
876
  public Static4D[] getQuats()
877
    {
878
    return mQuats;
879
    }
880

    
881
///////////////////////////////////////////////////////////////////////////////////////////////////
882

    
883
  public int getSolvedFunctionIndex()
884
    {
885
    return mSolvedFuncIndex;
886
    }
887

    
888
///////////////////////////////////////////////////////////////////////////////////////////////////
889

    
890
  public int getNumStickerTypes()
891
    {
892
    return mNumStickerTypes;
893
    }
894

    
895
///////////////////////////////////////////////////////////////////////////////////////////////////
896

    
897
  public float[][] getCuts()
898
    {
899
    return mCuts;
900
    }
901

    
902
///////////////////////////////////////////////////////////////////////////////////////////////////
903

    
904
  public boolean[][] getLayerRotatable()
905
    {
906
    return mLayerRotatable;
907
    }
908

    
909
///////////////////////////////////////////////////////////////////////////////////////////////////
910

    
911
  public int getMovementType()
912
    {
913
    return mMovementType;
914
    }
915

    
916
///////////////////////////////////////////////////////////////////////////////////////////////////
917

    
918
  public int getMovementSplit()
919
    {
920
    return mMovementSplit;
921
    }
922

    
923
///////////////////////////////////////////////////////////////////////////////////////////////////
924

    
925
  public int[][][] getEnabled()
926
    {
927
    return mEnabled;
928
    }
929

    
930
///////////////////////////////////////////////////////////////////////////////////////////////////
931

    
932
  public float[] getDist3D()
933
    {
934
    return mDist3D;
935
    }
936

    
937
///////////////////////////////////////////////////////////////////////////////////////////////////
938

    
939
  public int getNumCubitFaces()
940
    {
941
    return mNumCubitFaces;
942
    }
943

    
944
///////////////////////////////////////////////////////////////////////////////////////////////////
945

    
946
  public float[][] getCubitPositions()
947
    {
948
    return mPositions;
949
    }
950

    
951
///////////////////////////////////////////////////////////////////////////////////////////////////
952

    
953
  public ObjectShape getObjectShape(int variant)
954
    {
955
    return mShapes[variant];
956
    }
957

    
958
///////////////////////////////////////////////////////////////////////////////////////////////////
959

    
960
  public ObjectFaceShape getObjectFaceShape(int variant)
961
    {
962
    return mFaceShapes[variant];
963
    }
964

    
965
///////////////////////////////////////////////////////////////////////////////////////////////////
966

    
967
  public Static4D getCubitQuats(int cubit)
968
    {
969
    return mCubitQuats[cubit];
970
    }
971

    
972
///////////////////////////////////////////////////////////////////////////////////////////////////
973

    
974
  public int getNumCubitVariants()
975
    {
976
    return mNumCubitVariants;
977
    }
978

    
979
///////////////////////////////////////////////////////////////////////////////////////////////////
980

    
981
  public int getCubitVariant(int cubit)
982
    {
983
    return mCubitVariant[cubit];
984
    }
985

    
986
///////////////////////////////////////////////////////////////////////////////////////////////////
987

    
988
  public int getVariantFaceColor(int variant, int face)
989
    {
990
    int[] colors = mVariantFaceColor[variant];
991
    return colors.length>face ? colors[face] : -1;
992
    }
993

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

    
996
  public int[] getCubitTypes()
997
    {
998
    return mCubitType;
999
    }
1000

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

    
1003
  public float[][] getCubitOffsets()
1004
    {
1005
    return mCubitRowOffset;
1006
    }
1007

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

    
1010
  public int[][] getVariantFaceIsOuter()
1011
    {
1012
    return mVariantFaceIsOuter;
1013
    }
1014

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

    
1017
  public int getCubitFaceFace(int cubit, int face)
1018
    {
1019
    return mCubitFaceColor[cubit][face];
1020
    }
1021

    
1022
///////////////////////////////////////////////////////////////////////////////////////////////////
1023

    
1024
  public int getNumScrambles()
1025
    {
1026
    return mNumScrambles;
1027
    }
1028

    
1029
///////////////////////////////////////////////////////////////////////////////////////////////////
1030

    
1031
  public ObjectSticker retSticker(int sticker)
1032
    {
1033
    return mObjectSticker[sticker];
1034
    }
1035

    
1036
///////////////////////////////////////////////////////////////////////////////////////////////////
1037

    
1038
  public ObjectStickerOverride[] getStickerOverrides()
1039
    {
1040
    return mStickerOverrides;
1041
    }
1042

    
1043
///////////////////////////////////////////////////////////////////////////////////////////////////
1044

    
1045
  public Static3D[] getRotationAxis()
1046
    {
1047
    return mAxis;
1048
    }
1049

    
1050
///////////////////////////////////////////////////////////////////////////////////////////////////
1051

    
1052
  public int[][] getBasicAngle()
1053
    {
1054
    return mBasicAngle;
1055
    }
1056

    
1057
///////////////////////////////////////////////////////////////////////////////////////////////////
1058

    
1059
  public ObjectSignature getSignature()
1060
    {
1061
    return mSignature;
1062
    }
1063

    
1064
///////////////////////////////////////////////////////////////////////////////////////////////////
1065

    
1066
  public String getObjectName()
1067
    {
1068
    return mLongName;
1069
    }
1070

    
1071
///////////////////////////////////////////////////////////////////////////////////////////////////
1072

    
1073
  public String getShortName()
1074
    {
1075
    return mShortName;
1076
    }
1077

    
1078
///////////////////////////////////////////////////////////////////////////////////////////////////
1079

    
1080
  public String getInventor()
1081
    {
1082
    return mInventor;
1083
    }
1084

    
1085
///////////////////////////////////////////////////////////////////////////////////////////////////
1086

    
1087
  public int getYearOfInvention()
1088
    {
1089
    return mYearOfInvention;
1090
    }
1091

    
1092
///////////////////////////////////////////////////////////////////////////////////////////////////
1093

    
1094
  public int getComplexity()
1095
    {
1096
    return mComplexity;
1097
    }
1098

    
1099
///////////////////////////////////////////////////////////////////////////////////////////////////
1100

    
1101
  public int getNumFaces()
1102
    {
1103
    return mNumFaces;
1104
    }
1105

    
1106
///////////////////////////////////////////////////////////////////////////////////////////////////
1107

    
1108
  public int getNumFaceColors()
1109
    {
1110
    return mNumFaceColors;
1111
    }
1112

    
1113
///////////////////////////////////////////////////////////////////////////////////////////////////
1114

    
1115
  public int[] getNumLayers()
1116
    {
1117
    return mNumLayers;
1118
    }
1119

    
1120
///////////////////////////////////////////////////////////////////////////////////////////////////
1121

    
1122
  public float getSize()
1123
    {
1124
    return mSize;
1125
    }
1126

    
1127
///////////////////////////////////////////////////////////////////////////////////////////////////
1128

    
1129
  public int getScrambleType()
1130
    {
1131
    return mScrambleType;
1132
    }
1133

    
1134
///////////////////////////////////////////////////////////////////////////////////////////////////
1135

    
1136
  public int getColor(int face)
1137
    {
1138
    return mColor[face];
1139
    }
1140

    
1141
///////////////////////////////////////////////////////////////////////////////////////////////////
1142

    
1143
  public int getInternalColor()
1144
    {
1145
    return mInternalColor;
1146
    }
1147

    
1148
///////////////////////////////////////////////////////////////////////////////////////////////////
1149

    
1150
  public boolean shouldResetTextureMaps()
1151
    {
1152
    return mResetMaps;
1153
    }
1154

    
1155
///////////////////////////////////////////////////////////////////////////////////////////////////
1156

    
1157
  public String getTutorialObject()
1158
    {
1159
    return mTutorialObject;
1160
    }
1161

    
1162
///////////////////////////////////////////////////////////////////////////////////////////////////
1163

    
1164
  public String[][] getTutorials()
1165
    {
1166
    return mTutorials;
1167
    }
1168

    
1169
}
(1-1/2)