Project

General

Profile

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

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

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.main.Cubit;
36
import org.distorted.objectlib.objects.TwistyBandagedCuboid;
37
import org.json.JSONArray;
38
import org.json.JSONException;
39
import org.json.JSONObject;
40

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

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

    
49
///////////////////////////////////////////////////////////////////////////////////////////////////
50

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

    
88
  private static JsonReader mThis;
89

    
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91

    
92
  private JsonReader()
93
    {
94
    }
95

    
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97

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

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105

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

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

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

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

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

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

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

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

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

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

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

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

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

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

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

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

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

    
227
    mNumCubitFaces = -1;
228

    
229
    for(int i=0; i<mNumCubitVariants; i++)
230
      {
231
      JSONObject jsonShape = object.getJSONObject(i);
232

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

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

    
250
      ////// faces ////////////////////////////////////////////////////
251
      JSONArray jsonFaces= jsonShape.getJSONArray("faces");
252
      int numFaces = jsonFaces.length();
253
      mVariantFaceColor[i] = new int[numFaces];
254
      bandIndices[i] = new int[numFaces];
255
      vertIndices[i] = new int[numFaces][];
256

    
257
      if( mNumCubitFaces<numFaces ) mNumCubitFaces=numFaces;
258

    
259
      for(int j=0; j<numFaces; j++)
260
        {
261
        JSONObject jsonFace = jsonFaces.getJSONObject(j);
262
        mVariantFaceColor[i][j] = jsonFace.getInt("sticker");
263
        bandIndices[i][j] = jsonFace.getInt("bandIndex");
264
        JSONArray vertices = jsonFace.getJSONArray("vertexIndices");
265
        int numV = vertices.length();
266
        vertIndices[i][j] = new int[numV];
267
        for(int k=0; k<numV; k++) vertIndices[i][j][k] = vertices.getInt(k);
268
        }
269

    
270
      ////// bands ////////////////////////////////////////////////////
271
      JSONArray jsonBands= jsonShape.getJSONArray("bands");
272
      int numBands = jsonBands.length();
273
      bands[i] = new float[numBands][7];
274

    
275
      for(int j=0; j<numBands; j++)
276
        {
277
        JSONObject jsonBand = jsonBands.getJSONObject(j);
278

    
279
        bands[i][j][0] = (float)jsonBand.getDouble("height");
280
        bands[i][j][1] = (float)jsonBand.getDouble("angle");
281
        bands[i][j][2] = (float)jsonBand.getDouble("distanceToCenter");
282
        bands[i][j][3] = (float)jsonBand.getDouble("distanceToFlat");
283
        bands[i][j][4] = (float)jsonBand.getDouble("numOfBands");
284
        bands[i][j][5] = (float)jsonBand.getDouble("extraI");
285
        bands[i][j][6] = (float)jsonBand.getDouble("extraJ");
286
        }
287

    
288
      ////// cornerPush ///////////////////////////////////////////////
289
      JSONArray jsonCornerPush= jsonShape.optJSONArray("cornerPush");
290

    
291
      if( jsonCornerPush!=null )
292
        {
293
        int numCornerP = jsonCornerPush.length();
294
        corners[i] = new float[numCornerP][2];
295

    
296
        for(int j=0; j<numCornerP; j++)
297
          {
298
          JSONObject jsonC = jsonCornerPush.getJSONObject(j);
299
          corners[i][j][0] = (float)jsonC.getDouble("strength");
300
          corners[i][j][1] = (float)jsonC.getDouble("radius");
301
          }
302
        }
303

    
304
      ////// centerPush ///////////////////////////////////////////////
305
      JSONArray jsonCenterPush= jsonShape.optJSONArray("centerPush");
306

    
307
      if( jsonCenterPush!=null )
308
        {
309
        int numCenterP = jsonCenterPush.length();
310
        centers[i] = new float[numCenterP][3];
311

    
312
        for(int j=0; j<numCenterP; j++)
313
          {
314
          JSONObject jsonC = jsonCenterPush.getJSONObject(j);
315
          centers[i][j][0] = (float)jsonC.getDouble("x");
316
          centers[i][j][1] = (float)jsonC.getDouble("y");
317
          centers[i][j][2] = (float)jsonC.getDouble("z");
318
          }
319
        }
320

    
321
      ////// convexity ///////////////////////////////////////////////
322
      JSONObject jsonConvexity = jsonShape.optJSONObject("convexity");
323

    
324
      if( jsonConvexity!=null )
325
        {
326
        convexity[i] = new float[3];
327
        convexity[i][0] = (float)jsonConvexity.getDouble("x");
328
        convexity[i][1] = (float)jsonConvexity.getDouble("y");
329
        convexity[i][2] = (float)jsonConvexity.getDouble("z");
330
        }
331
      }
332

    
333
    for(int i=0; i<mNumCubitVariants; i++)
334
      {
335
      mShapes[i] = new ObjectShape(verts[i],vertIndices[i]);
336
      mFaceShapes[i] = new ObjectFaceShape(bands[i],bandIndices[i],corners[i],cornerIndices[i],centers[i],centerIndices[i],convexity[i] );
337
      }
338
    }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
  private void parseStickers(JSONArray object) throws JSONException
343
    {
344
    mNumStickerTypes = object.length();
345
    mObjectSticker = new ObjectSticker[mNumStickerTypes];
346

    
347
    for(int i=0; i<mNumStickerTypes; i++)
348
      {
349
      JSONObject sticker = object.getJSONObject(i);
350
      float stroke = (float)sticker.getDouble("stroke");
351
      JSONArray vertices = sticker.getJSONArray("vertices");
352
      int numVertices = vertices.length();
353

    
354
      float[] coords     = new float[2*numVertices];
355
      float[] curvatures = new float[numVertices];
356
      float[] radii      = new float[numVertices];
357

    
358
      for(int j=0; j<numVertices; j++)
359
        {
360
        JSONObject vertex = vertices.getJSONObject(j);
361

    
362
        coords[2*j  ] = (float)vertex.getDouble("x");
363
        coords[2*j+1] = (float)vertex.getDouble("y");
364
        curvatures[j] = (float)vertex.getDouble("angle");
365
        radii[j]      = (float)vertex.getDouble("radius");
366
        }
367

    
368
      mObjectSticker[i] = new ObjectSticker(coords,curvatures,radii,stroke);
369
      }
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  private void parseMesh(JSONObject object) throws JSONException
375
    {
376
    JSONArray cubits   = object.getJSONArray("cubits");
377
    parseCubits(cubits);
378
    JSONArray shapes   = object.getJSONArray("shapes");
379
    parseShapes(shapes);
380
    JSONArray stickers = object.getJSONArray("stickers");
381
    parseStickers(stickers);
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
  private void parseAxis1(JSONArray object) throws JSONException
387
    {
388
    int numAxis = object.length();
389

    
390
    mBasicAngle     = new int[numAxis][];
391
    mAxis           = new Static3D[numAxis];
392
    mCuts           = new float[numAxis][];
393
    mLayerRotatable = new boolean[numAxis][];
394
    mNumLayers      = new int[numAxis];
395

    
396
    for(int i=0; i<numAxis; i++)
397
      {
398
      JSONObject jsonAx = object.getJSONObject(i);
399

    
400
      float x = (float)jsonAx.getDouble("x");
401
      float y = (float)jsonAx.getDouble("y");
402
      float z = (float)jsonAx.getDouble("z");
403

    
404
      mAxis[i] = new Static3D(x,y,z);
405

    
406
      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
407
      int numCuts = jsonCuts.length();
408
      mCuts[i] = new float[numCuts];
409
      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
410

    
411
      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
412
      int numRota = jsonRota.length();
413
      mLayerRotatable[i] = new boolean[numRota];
414
      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
415

    
416
      mBasicAngle[i] = new int[numRota];
417
      int basicAngle = jsonAx.getInt("basicAngle");
418
      for(int j=0; j<numRota; j++) mBasicAngle[i][j] = basicAngle;
419

    
420
      mNumLayers[i] = numRota;
421
      }
422
    }
423

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

    
426
  private void parseAxis2or3or4(JSONArray object) throws JSONException
427
    {
428
    int numAxis = object.length();
429

    
430
    mBasicAngle     = new int[numAxis][];
431
    mAxis           = new Static3D[numAxis];
432
    mCuts           = new float[numAxis][];
433
    mLayerRotatable = new boolean[numAxis][];
434
    mNumLayers      = new int[numAxis];
435

    
436
    for(int i=0; i<numAxis; i++)
437
      {
438
      JSONObject jsonAx = object.getJSONObject(i);
439

    
440
      float x = (float)jsonAx.getDouble("x");
441
      float y = (float)jsonAx.getDouble("y");
442
      float z = (float)jsonAx.getDouble("z");
443

    
444
      mAxis[i] = new Static3D(x,y,z);
445

    
446
      JSONArray jsonAngles = jsonAx.getJSONArray("basicAngles");
447
      int numAngles = jsonAngles.length();
448
      mBasicAngle[i] = new int[numAngles];
449
      for(int j=0; j<numAngles; j++) mBasicAngle[i][j] = jsonAngles.getInt(j);
450

    
451
      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
452
      int numCuts = jsonCuts.length();
453
      mCuts[i] = new float[numCuts];
454
      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
455

    
456
      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
457
      int numRota = jsonRota.length();
458
      mLayerRotatable[i] = new boolean[numRota];
459
      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
460

    
461
      mNumLayers[i] = numRota;
462
      }
463
    }
464

    
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466

    
467
  private void parseQuats(JSONArray object) throws JSONException
468
    {
469
    int numQuats = object.length();
470
    mQuats = new Static4D[numQuats];
471

    
472
    for(int i=0; i<numQuats; i++)
473
      {
474
      JSONObject jsonQuat = object.getJSONObject(i);
475

    
476
      float x = (float)jsonQuat.getDouble("x");
477
      float y = (float)jsonQuat.getDouble("y");
478
      float z = (float)jsonQuat.getDouble("z");
479
      float w = (float)jsonQuat.getDouble("w");
480

    
481
      mQuats[i] = new Static4D(x,y,z,w);
482
      }
483
    }
484

    
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486

    
487
  private void parseScrambling(JSONObject object) throws JSONException
488
    {
489
    mScrambleType = object.getInt("scrambleType");
490

    
491
    if( mScrambleType==0 )
492
      {
493
      JSONArray jsonStates = object.getJSONArray("scrambleStates");
494
      int numStates = jsonStates.length();
495
      mStates = new ScrambleState[numStates];
496

    
497
      for(int i=0; i<numStates; i++)
498
        {
499
        JSONArray jsonState = jsonStates.getJSONArray(i);
500
        int numAxis = jsonState.length();
501
        int[][] scramblingData = new int[numAxis][];
502

    
503
        for(int j=0; j<numAxis; j++)
504
          {
505
          JSONArray jsonData = jsonState.getJSONArray(j);
506
          int numData = jsonData.length();
507
          scramblingData[j] = new int[numData];
508
          for(int k=0; k<numData; k++) scramblingData[j][k] = jsonData.getInt(k);
509
          }
510

    
511
        mStates[i] = new ScrambleState(scramblingData);
512
        }
513
      }
514
    }
515

    
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

    
518
  private void parseTouchcontrol(JSONObject object) throws JSONException
519
    {
520
    mMovementType = object.getInt("movementType");
521
    mMovementSplit= object.getInt("movementSplit");
522

    
523
    try
524
      {
525
      JSONArray jsonEnabled = object.getJSONArray("enabledAxis");
526
      int numFace = jsonEnabled.length();
527

    
528
      mEnabled = new int[numFace][][];
529

    
530
      for(int i=0; i<numFace; i++)
531
        {
532
        JSONArray jsonSection = jsonEnabled.getJSONArray(i);
533
        int numSection = jsonSection.length();
534
        mEnabled[i] = new int[numSection][];
535

    
536
        for(int j=0; j<numSection; j++)
537
          {
538
          JSONArray jsonAx = jsonSection.getJSONArray(j);
539
          int numAxis = jsonAx.length();
540
          mEnabled[i][j] = new int[numAxis];
541
          for(int k=0; k<numAxis; k++) mEnabled[i][j][k] = jsonAx.getInt(k);
542
          }
543
        }
544
      }
545
    catch( JSONException ex )
546
      {
547
      // ignore, the object does not have to have 'enabledAxis' defined at all.
548
      }
549

    
550
    try
551
      {
552
      JSONArray jsonDist = object.getJSONArray("dist3D");
553
      int num = jsonDist.length();
554
      mDist3D = new float[num];
555
      for(int j=0; j<num; j++) mDist3D[j] = (float)jsonDist.getDouble(j);
556
      }
557
    catch( JSONException ex )
558
      {
559
      // ignore, the object does not have a 'dist3D' which is possible.
560
      }
561
    }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564

    
565
  private void parseColors(JSONArray object) throws JSONException
566
    {
567
    mNumFaceColors = object.length()-1;
568

    
569
    mColor = new int[mNumFaceColors];
570
    for(int i=0; i<mNumFaceColors; i++) mColor[i] = object.getInt(i);
571

    
572
    mInternalColor = object.getInt(mNumFaceColors);
573
    }
574

    
575
///////////////////////////////////////////////////////////////////////////////////////////////////
576

    
577
  private void parseSolved(JSONObject solved) throws JSONException
578
    {
579
    mSolvedFuncIndex = solved.getInt("functionIndex");
580

    
581
    try
582
      {
583
      JSONArray groupArray= solved.getJSONArray("groups");
584
      int numGroups = groupArray.length();
585
      mSolvedQuats  = new int[numGroups][];
586

    
587
      for(int i=0; i<numGroups; i++)
588
        {
589
        JSONArray groupElements = groupArray.getJSONArray(i);
590
        int groupSize = groupElements.length();
591
        mSolvedQuats[i] = new int[groupSize];
592
        for(int j=0; j<groupSize; j++) mSolvedQuats[i][j] = groupElements.getInt(j);
593
        }
594
      }
595
    catch( JSONException ex )
596
      {
597
      // ignore, the object does not have to have an array of solved groups.
598
      }
599
    }
600

    
601
///////////////////////////////////////////////////////////////////////////////////////////////////
602

    
603
  private void parseVersion1(JSONObject object) throws JSONException
604
    {
605
    JSONObject metadata    = object.getJSONObject("metadata");
606
    parseMetadata1(metadata);
607
    JSONObject mesh        = object.getJSONObject("mesh");
608
    parseMesh(mesh);
609
    JSONArray axis         = object.getJSONArray("axis");
610
    parseAxis1(axis);
611
    JSONArray quats        = object.getJSONArray("quats");
612
    parseQuats(quats);
613
    JSONObject scrambling  = object.getJSONObject("scrambling");
614
    parseScrambling(scrambling);
615
    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
616
    parseTouchcontrol(touchcontrol);
617
    JSONArray colors       = object.getJSONArray("colors");
618
    parseColors(colors);
619
    JSONObject solved      = object.getJSONObject("solved");
620
    parseSolved(solved);
621
    }
622

    
623
///////////////////////////////////////////////////////////////////////////////////////////////////
624

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

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

    
647
  private void parseVersion1Tutorial(JSONObject object) throws JSONException
648
    {
649
    mTutorialObject = object.getString("object");
650
    JSONArray tuts= object.getJSONArray("tutorials");
651

    
652
    int len = tuts.length();
653
    mTutorials = new String[len][4];
654

    
655
    for(int i=0; i<len; i++)
656
      {
657
      JSONObject tut = tuts.getJSONObject(i);
658
      mTutorials[i][0] = tut.getString("language");
659
      mTutorials[i][1] = tut.getString("link");
660
      mTutorials[i][2] = tut.getString("title");
661
      mTutorials[i][3] = tut.getString("author");
662
      }
663
    }
664

    
665
///////////////////////////////////////////////////////////////////////////////////////////////////
666

    
667
  private void parseVersion1Metadata(JSONObject object) throws JSONException
668
    {
669
    JSONObject metadata = object.getJSONObject("metadata");
670
    parseMetadata1(metadata);
671
    }
672

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

    
675
  private void parseVersion2or3or4Metadata(JSONObject object) throws JSONException
676
    {
677
    JSONObject metadata = object.getJSONObject("metadata");
678
    parseMetadata2or3or4(metadata);
679
    }
680

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

    
683
  public void parseJsonFile(InputStream jsonStream)
684
    {
685
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
686

    
687
    try
688
      {
689
      StringBuilder contents = new StringBuilder();
690
      String tmp;
691
      while( (tmp = br.readLine()) != null) contents.append(tmp);
692
      br.close();
693
      jsonStream.close();
694

    
695
      JSONObject object = new JSONObject(contents.toString());
696
      int major = object.getInt("major");
697

    
698
      if( major==1 )
699
        {
700
        parseVersion1(object);
701
        }
702
      else if( major==2 || major==3 || major==4 )
703
        {
704
        parseVersion2or3or4(object);
705
        }
706
      else
707
        {
708
        android.util.Log.e("readJsonFile", "Unknown version "+major);
709
        }
710
      }
711
    catch(IOException e)
712
      {
713
      android.util.Log.e("readJsonFile", "Error reading JSON file: "+e.toString());
714
      }
715
    catch( JSONException e )
716
      {
717
      android.util.Log.e("parseJsonFile", "Error parsing JSON file: "+e.toString());
718
      }
719
    }
720

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

    
723
  public void parseJsonFileMetadata(InputStream jsonStream)
724
    {
725
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
726

    
727
    try
728
      {
729
      StringBuilder contents = new StringBuilder();
730
      String tmp;
731
      while( (tmp = br.readLine()) != null) contents.append(tmp);
732
      br.close();
733
      jsonStream.close();
734

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

    
738
      if( major==1 )
739
        {
740
        parseVersion1Metadata(object);
741
        }
742
      else if( major==2 || major==3 || major==4 )
743
        {
744
        parseVersion2or3or4Metadata(object);
745
        }
746
      else
747
        {
748
        android.util.Log.e("readJsonFileQuick", "Unknown version "+major);
749
        }
750
      }
751
    catch(IOException e)
752
      {
753
      android.util.Log.e("readJsonFileQuick", "Error reading JSON file: "+e.toString());
754
      }
755
    catch( JSONException e )
756
      {
757
      android.util.Log.e("parseJsonFileQuick", "Error parsing JSON file: "+e.toString());
758
      }
759
    }
760

    
761
///////////////////////////////////////////////////////////////////////////////////////////////////
762

    
763
  public int readNumScrambles(Context context, String fileName)
764
    {
765
    File file = new File(context.getFilesDir(), fileName);
766
    InputStream stream;
767

    
768
    try
769
      {
770
      stream = new FileInputStream(file);
771
      BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
772

    
773
      StringBuilder contents = new StringBuilder();
774
      String tmp;
775
      while( (tmp = br.readLine()) != null) contents.append(tmp);
776
      br.close();
777
      stream.close();
778

    
779
      JSONObject object = new JSONObject(contents.toString());
780
      JSONObject metadata = object.getJSONObject("metadata");
781
      return metadata.getInt("scrambles");
782
      }
783
    catch(FileNotFoundException ex)
784
      {
785
      android.util.Log.e("readNumScrambles", "file "+fileName+" not found: "+ex.getMessage());
786
      }
787
    catch(IOException e)
788
      {
789
      android.util.Log.e("readNumScrambles", "Error reading JSON file: "+e.toString());
790
      }
791
    catch( JSONException e )
792
      {
793
      android.util.Log.e("readNumScrambles", "Error parsing JSON file: "+e.toString());
794
      }
795

    
796
    return 0;
797
    }
798

    
799
///////////////////////////////////////////////////////////////////////////////////////////////////
800

    
801
  public void parseJsonTutorial(InputStream jsonStream)
802
    {
803
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
804

    
805
    try
806
      {
807
      StringBuilder contents = new StringBuilder();
808
      String tmp;
809
      while( (tmp = br.readLine()) != null) contents.append(tmp);
810
      br.close();
811
      jsonStream.close();
812

    
813
      JSONObject object = new JSONObject(contents.toString());
814
      int major = object.getInt("major");
815

    
816
      if( major==1 )
817
        {
818
        parseVersion1Tutorial(object);
819
        }
820
      else
821
        {
822
        android.util.Log.e("readJsonFile", "Unknown tutorial version "+major);
823
        }
824
      }
825
    catch(IOException e)
826
      {
827
      android.util.Log.e("readJsonFile", "Error reading JSON file: "+e.toString());
828
      }
829
    catch( JSONException e )
830
      {
831
      android.util.Log.e("parseJsonFile", "Error parsing JSON file: "+e.toString());
832
      }
833
    }
834

    
835
///////////////////////////////////////////////////////////////////////////////////////////////////
836

    
837
  public ScrambleState[] getScrambleStates()
838
    {
839
    return mStates;
840
    }
841

    
842
///////////////////////////////////////////////////////////////////////////////////////////////////
843

    
844
  public int[][] getSolvedQuats()
845
    {
846
    return mSolvedQuats;
847
    }
848

    
849
///////////////////////////////////////////////////////////////////////////////////////////////////
850

    
851
  public Static4D[] getQuats()
852
    {
853
    return mQuats;
854
    }
855

    
856
///////////////////////////////////////////////////////////////////////////////////////////////////
857

    
858
  public int getSolvedFunctionIndex()
859
    {
860
    return mSolvedFuncIndex;
861
    }
862

    
863
///////////////////////////////////////////////////////////////////////////////////////////////////
864

    
865
  public int getNumStickerTypes()
866
    {
867
    return mNumStickerTypes;
868
    }
869

    
870
///////////////////////////////////////////////////////////////////////////////////////////////////
871

    
872
  public float[][] getCuts()
873
    {
874
    return mCuts;
875
    }
876

    
877
///////////////////////////////////////////////////////////////////////////////////////////////////
878

    
879
  public boolean[][] getLayerRotatable()
880
    {
881
    return mLayerRotatable;
882
    }
883

    
884
///////////////////////////////////////////////////////////////////////////////////////////////////
885

    
886
  public int getMovementType()
887
    {
888
    return mMovementType;
889
    }
890

    
891
///////////////////////////////////////////////////////////////////////////////////////////////////
892

    
893
  public int getMovementSplit()
894
    {
895
    return mMovementSplit;
896
    }
897

    
898
///////////////////////////////////////////////////////////////////////////////////////////////////
899

    
900
  public int[][][] getEnabled()
901
    {
902
    return mEnabled;
903
    }
904

    
905
///////////////////////////////////////////////////////////////////////////////////////////////////
906

    
907
  public float[] getDist3D()
908
    {
909
    return mDist3D;
910
    }
911

    
912
///////////////////////////////////////////////////////////////////////////////////////////////////
913

    
914
  public int getNumCubitFaces()
915
    {
916
    return mNumCubitFaces;
917
    }
918

    
919
///////////////////////////////////////////////////////////////////////////////////////////////////
920

    
921
  public float[][] getCubitPositions()
922
    {
923
    return mPositions;
924
    }
925

    
926
///////////////////////////////////////////////////////////////////////////////////////////////////
927

    
928
  public ObjectShape getObjectShape(int variant)
929
    {
930
    return mShapes[variant];
931
    }
932

    
933
///////////////////////////////////////////////////////////////////////////////////////////////////
934

    
935
  public ObjectFaceShape getObjectFaceShape(int variant)
936
    {
937
    return mFaceShapes[variant];
938
    }
939

    
940
///////////////////////////////////////////////////////////////////////////////////////////////////
941

    
942
  public Static4D getCubitQuats(int cubit)
943
    {
944
    return mCubitQuats[cubit];
945
    }
946

    
947
///////////////////////////////////////////////////////////////////////////////////////////////////
948

    
949
  public int getNumCubitVariants()
950
    {
951
    return mNumCubitVariants;
952
    }
953

    
954
///////////////////////////////////////////////////////////////////////////////////////////////////
955

    
956
  public int getCubitVariant(int cubit)
957
    {
958
    return mCubitVariant[cubit];
959
    }
960

    
961
///////////////////////////////////////////////////////////////////////////////////////////////////
962

    
963
  public int getVariantFaceColor(int variant, int face)
964
    {
965
    int[] colors = mVariantFaceColor[variant];
966
    return colors.length>face ? colors[face] : -1;
967
    }
968

    
969
///////////////////////////////////////////////////////////////////////////////////////////////////
970

    
971
  public int[] getCubitTypes()
972
    {
973
    return mCubitType;
974
    }
975

    
976
///////////////////////////////////////////////////////////////////////////////////////////////////
977

    
978
  public float[][] getCubitOffsets()
979
    {
980
    return mCubitRowOffset;
981
    }
982

    
983
///////////////////////////////////////////////////////////////////////////////////////////////////
984

    
985
  public int getCubitFaceFace(int cubit, int face)
986
    {
987
    return mCubitFaceColor[cubit][face];
988
    }
989

    
990
///////////////////////////////////////////////////////////////////////////////////////////////////
991

    
992
  public int getNumScrambles()
993
    {
994
    return mNumScrambles;
995
    }
996

    
997
///////////////////////////////////////////////////////////////////////////////////////////////////
998

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

    
1004
///////////////////////////////////////////////////////////////////////////////////////////////////
1005

    
1006
  public Static3D[] getRotationAxis()
1007
    {
1008
    return mAxis;
1009
    }
1010

    
1011
///////////////////////////////////////////////////////////////////////////////////////////////////
1012

    
1013
  public int[][] getBasicAngle()
1014
    {
1015
    return mBasicAngle;
1016
    }
1017

    
1018
///////////////////////////////////////////////////////////////////////////////////////////////////
1019

    
1020
  public ObjectSignature getSignature()
1021
    {
1022
    return mSignature;
1023
    }
1024

    
1025
///////////////////////////////////////////////////////////////////////////////////////////////////
1026

    
1027
  public String getObjectName()
1028
    {
1029
    return mLongName;
1030
    }
1031

    
1032
///////////////////////////////////////////////////////////////////////////////////////////////////
1033

    
1034
  public String getShortName()
1035
    {
1036
    return mShortName;
1037
    }
1038

    
1039
///////////////////////////////////////////////////////////////////////////////////////////////////
1040

    
1041
  public String getInventor()
1042
    {
1043
    return mInventor;
1044
    }
1045

    
1046
///////////////////////////////////////////////////////////////////////////////////////////////////
1047

    
1048
  public int getYearOfInvention()
1049
    {
1050
    return mYearOfInvention;
1051
    }
1052

    
1053
///////////////////////////////////////////////////////////////////////////////////////////////////
1054

    
1055
  public int getComplexity()
1056
    {
1057
    return mComplexity;
1058
    }
1059

    
1060
///////////////////////////////////////////////////////////////////////////////////////////////////
1061

    
1062
  public int getNumFaces()
1063
    {
1064
    return mNumFaces;
1065
    }
1066

    
1067
///////////////////////////////////////////////////////////////////////////////////////////////////
1068

    
1069
  public int getNumFaceColors()
1070
    {
1071
    return mNumFaceColors;
1072
    }
1073

    
1074
///////////////////////////////////////////////////////////////////////////////////////////////////
1075

    
1076
  public int[] getNumLayers()
1077
    {
1078
    return mNumLayers;
1079
    }
1080

    
1081
///////////////////////////////////////////////////////////////////////////////////////////////////
1082

    
1083
  public float getSize()
1084
    {
1085
    return mSize;
1086
    }
1087

    
1088
///////////////////////////////////////////////////////////////////////////////////////////////////
1089

    
1090
  public int getScrambleType()
1091
    {
1092
    return mScrambleType;
1093
    }
1094

    
1095
///////////////////////////////////////////////////////////////////////////////////////////////////
1096

    
1097
  public int getColor(int face)
1098
    {
1099
    return mColor[face];
1100
    }
1101

    
1102
///////////////////////////////////////////////////////////////////////////////////////////////////
1103

    
1104
  public int getInternalColor()
1105
    {
1106
    return mInternalColor;
1107
    }
1108

    
1109
///////////////////////////////////////////////////////////////////////////////////////////////////
1110

    
1111
  public boolean shouldResetTextureMaps()
1112
    {
1113
    return mResetMaps;
1114
    }
1115

    
1116
///////////////////////////////////////////////////////////////////////////////////////////////////
1117

    
1118
  public String getTutorialObject()
1119
    {
1120
    return mTutorialObject;
1121
    }
1122

    
1123
///////////////////////////////////////////////////////////////////////////////////////////////////
1124

    
1125
  public String[][] getTutorials()
1126
    {
1127
    return mTutorials;
1128
    }
1129

    
1130
}
(1-1/2)