Project

General

Profile

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

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

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, mVariantFaceIsOuter, 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
    mVariantFaceIsOuter   = new int[mNumCubitVariants][];
216
    mShapes               = new ObjectShape[mNumCubitVariants];
217
    mFaceShapes           = new ObjectFaceShape[mNumCubitVariants];
218
    float[][][] verts     = new float[mNumCubitVariants][][];
219
    float[][][] bands     = new float[mNumCubitVariants][][];
220
    float[][][] corners   = new float[mNumCubitVariants][][];
221
    float[][][] centers   = new float[mNumCubitVariants][][];
222
    float[][] convexity   = new float[mNumCubitVariants][];
223
    int[][] cornerIndices = new int[mNumCubitVariants][];
224
    int[][] centerIndices = new int[mNumCubitVariants][];
225
    int[][] bandIndices   = new int[mNumCubitVariants][];
226
    int[][][] vertIndices = new int[mNumCubitVariants][][];
227

    
228
    mNumCubitFaces = -1;
229

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

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

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

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

    
259
      if( mNumCubitFaces<numFaces ) mNumCubitFaces=numFaces;
260

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

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

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

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

    
291
      ////// cornerPush ///////////////////////////////////////////////
292
      JSONArray jsonCornerPush= jsonShape.optJSONArray("cornerPush");
293

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

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

    
307
      ////// centerPush ///////////////////////////////////////////////
308
      JSONArray jsonCenterPush= jsonShape.optJSONArray("centerPush");
309

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

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

    
324
      ////// convexity ///////////////////////////////////////////////
325
      JSONObject jsonConvexity = jsonShape.optJSONObject("convexity");
326

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

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

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

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

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

    
357
      float[] coords     = new float[2*numVertices];
358
      float[] curvatures = new float[numVertices];
359
      float[] radii      = new float[numVertices];
360

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

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

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

    
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376

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

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
  private void parseAxis1(JSONArray object) throws JSONException
390
    {
391
    int numAxis = object.length();
392

    
393
    mBasicAngle     = new int[numAxis][];
394
    mAxis           = new Static3D[numAxis];
395
    mCuts           = new float[numAxis][];
396
    mLayerRotatable = new boolean[numAxis][];
397
    mNumLayers      = new int[numAxis];
398

    
399
    for(int i=0; i<numAxis; i++)
400
      {
401
      JSONObject jsonAx = object.getJSONObject(i);
402

    
403
      float x = (float)jsonAx.getDouble("x");
404
      float y = (float)jsonAx.getDouble("y");
405
      float z = (float)jsonAx.getDouble("z");
406

    
407
      mAxis[i] = new Static3D(x,y,z);
408

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

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

    
419
      mBasicAngle[i] = new int[numRota];
420
      int basicAngle = jsonAx.getInt("basicAngle");
421
      for(int j=0; j<numRota; j++) mBasicAngle[i][j] = basicAngle;
422

    
423
      mNumLayers[i] = numRota;
424
      }
425
    }
426

    
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428

    
429
  private void parseAxis2or3or4(JSONArray object) throws JSONException
430
    {
431
    int numAxis = object.length();
432

    
433
    mBasicAngle     = new int[numAxis][];
434
    mAxis           = new Static3D[numAxis];
435
    mCuts           = new float[numAxis][];
436
    mLayerRotatable = new boolean[numAxis][];
437
    mNumLayers      = new int[numAxis];
438

    
439
    for(int i=0; i<numAxis; i++)
440
      {
441
      JSONObject jsonAx = object.getJSONObject(i);
442

    
443
      float x = (float)jsonAx.getDouble("x");
444
      float y = (float)jsonAx.getDouble("y");
445
      float z = (float)jsonAx.getDouble("z");
446

    
447
      mAxis[i] = new Static3D(x,y,z);
448

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

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

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

    
464
      mNumLayers[i] = numRota;
465
      }
466
    }
467

    
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469

    
470
  private void parseQuats(JSONArray object) throws JSONException
471
    {
472
    int numQuats = object.length();
473
    mQuats = new Static4D[numQuats];
474

    
475
    for(int i=0; i<numQuats; i++)
476
      {
477
      JSONObject jsonQuat = object.getJSONObject(i);
478

    
479
      float x = (float)jsonQuat.getDouble("x");
480
      float y = (float)jsonQuat.getDouble("y");
481
      float z = (float)jsonQuat.getDouble("z");
482
      float w = (float)jsonQuat.getDouble("w");
483

    
484
      mQuats[i] = new Static4D(x,y,z,w);
485
      }
486
    }
487

    
488
///////////////////////////////////////////////////////////////////////////////////////////////////
489

    
490
  private void parseScrambling(JSONObject object) throws JSONException
491
    {
492
    mScrambleType = object.getInt("scrambleType");
493

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

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

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

    
514
        mStates[i] = new ScrambleState(scramblingData);
515
        }
516
      }
517
    }
518

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

    
521
  private void parseTouchcontrol(JSONObject object) throws JSONException
522
    {
523
    mMovementType = object.getInt("movementType");
524
    mMovementSplit= object.getInt("movementSplit");
525

    
526
    try
527
      {
528
      JSONArray jsonEnabled = object.getJSONArray("enabledAxis");
529
      int numFace = jsonEnabled.length();
530

    
531
      mEnabled = new int[numFace][][];
532

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

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

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

    
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567

    
568
  private void parseColors(JSONArray object) throws JSONException
569
    {
570
    mNumFaceColors = object.length()-1;
571

    
572
    mColor = new int[mNumFaceColors];
573
    for(int i=0; i<mNumFaceColors; i++) mColor[i] = object.getInt(i);
574

    
575
    mInternalColor = object.getInt(mNumFaceColors);
576
    }
577

    
578
///////////////////////////////////////////////////////////////////////////////////////////////////
579

    
580
  private void parseSolved(JSONObject solved) throws JSONException
581
    {
582
    mSolvedFuncIndex = solved.getInt("functionIndex");
583

    
584
    try
585
      {
586
      JSONArray groupArray= solved.getJSONArray("groups");
587
      int numGroups = groupArray.length();
588
      mSolvedQuats  = new int[numGroups][];
589

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

    
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605

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

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

    
628
  private void parseVersion2or3or4(JSONObject object) throws JSONException
629
    {
630
    JSONObject metadata    = object.getJSONObject("metadata");
631
    parseMetadata2or3or4(metadata);
632
    JSONObject mesh        = object.getJSONObject("mesh");
633
    parseMesh(mesh);
634
    JSONArray axis         = object.getJSONArray("axis");
635
    parseAxis2or3or4(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 parseVersion1Tutorial(JSONObject object) throws JSONException
651
    {
652
    mTutorialObject = object.getString("object");
653
    JSONArray tuts= object.getJSONArray("tutorials");
654

    
655
    int len = tuts.length();
656
    mTutorials = new String[len][4];
657

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

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

    
670
  private void parseVersion1Metadata(JSONObject object) throws JSONException
671
    {
672
    JSONObject metadata = object.getJSONObject("metadata");
673
    parseMetadata1(metadata);
674
    }
675

    
676
///////////////////////////////////////////////////////////////////////////////////////////////////
677

    
678
  private void parseVersion2or3or4Metadata(JSONObject object) throws JSONException
679
    {
680
    JSONObject metadata = object.getJSONObject("metadata");
681
    parseMetadata2or3or4(metadata);
682
    }
683

    
684
///////////////////////////////////////////////////////////////////////////////////////////////////
685

    
686
  public void parseJsonFile(InputStream jsonStream)
687
    {
688
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
689

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

    
698
      JSONObject object = new JSONObject(contents.toString());
699
      int major = object.getInt("major");
700

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

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

    
726
  public void parseJsonFileMetadata(InputStream jsonStream)
727
    {
728
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
729

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

    
738
      JSONObject object = new JSONObject(contents.toString());
739
      int major = object.getInt("major");
740

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

    
764
///////////////////////////////////////////////////////////////////////////////////////////////////
765

    
766
  public int readNumScrambles(Context context, String fileName)
767
    {
768
    File file = new File(context.getFilesDir(), fileName);
769
    InputStream stream;
770

    
771
    try
772
      {
773
      stream = new FileInputStream(file);
774
      BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
775

    
776
      StringBuilder contents = new StringBuilder();
777
      String tmp;
778
      while( (tmp = br.readLine()) != null) contents.append(tmp);
779
      br.close();
780
      stream.close();
781

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

    
799
    return 0;
800
    }
801

    
802
///////////////////////////////////////////////////////////////////////////////////////////////////
803

    
804
  public void parseJsonTutorial(InputStream jsonStream)
805
    {
806
    BufferedReader br = new BufferedReader(new InputStreamReader(jsonStream, StandardCharsets.UTF_8));
807

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

    
816
      JSONObject object = new JSONObject(contents.toString());
817
      int major = object.getInt("major");
818

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

    
838
///////////////////////////////////////////////////////////////////////////////////////////////////
839

    
840
  public ScrambleState[] getScrambleStates()
841
    {
842
    return mStates;
843
    }
844

    
845
///////////////////////////////////////////////////////////////////////////////////////////////////
846

    
847
  public int[][] getSolvedQuats()
848
    {
849
    return mSolvedQuats;
850
    }
851

    
852
///////////////////////////////////////////////////////////////////////////////////////////////////
853

    
854
  public Static4D[] getQuats()
855
    {
856
    return mQuats;
857
    }
858

    
859
///////////////////////////////////////////////////////////////////////////////////////////////////
860

    
861
  public int getSolvedFunctionIndex()
862
    {
863
    return mSolvedFuncIndex;
864
    }
865

    
866
///////////////////////////////////////////////////////////////////////////////////////////////////
867

    
868
  public int getNumStickerTypes()
869
    {
870
    return mNumStickerTypes;
871
    }
872

    
873
///////////////////////////////////////////////////////////////////////////////////////////////////
874

    
875
  public float[][] getCuts()
876
    {
877
    return mCuts;
878
    }
879

    
880
///////////////////////////////////////////////////////////////////////////////////////////////////
881

    
882
  public boolean[][] getLayerRotatable()
883
    {
884
    return mLayerRotatable;
885
    }
886

    
887
///////////////////////////////////////////////////////////////////////////////////////////////////
888

    
889
  public int getMovementType()
890
    {
891
    return mMovementType;
892
    }
893

    
894
///////////////////////////////////////////////////////////////////////////////////////////////////
895

    
896
  public int getMovementSplit()
897
    {
898
    return mMovementSplit;
899
    }
900

    
901
///////////////////////////////////////////////////////////////////////////////////////////////////
902

    
903
  public int[][][] getEnabled()
904
    {
905
    return mEnabled;
906
    }
907

    
908
///////////////////////////////////////////////////////////////////////////////////////////////////
909

    
910
  public float[] getDist3D()
911
    {
912
    return mDist3D;
913
    }
914

    
915
///////////////////////////////////////////////////////////////////////////////////////////////////
916

    
917
  public int getNumCubitFaces()
918
    {
919
    return mNumCubitFaces;
920
    }
921

    
922
///////////////////////////////////////////////////////////////////////////////////////////////////
923

    
924
  public float[][] getCubitPositions()
925
    {
926
    return mPositions;
927
    }
928

    
929
///////////////////////////////////////////////////////////////////////////////////////////////////
930

    
931
  public ObjectShape getObjectShape(int variant)
932
    {
933
    return mShapes[variant];
934
    }
935

    
936
///////////////////////////////////////////////////////////////////////////////////////////////////
937

    
938
  public ObjectFaceShape getObjectFaceShape(int variant)
939
    {
940
    return mFaceShapes[variant];
941
    }
942

    
943
///////////////////////////////////////////////////////////////////////////////////////////////////
944

    
945
  public Static4D getCubitQuats(int cubit)
946
    {
947
    return mCubitQuats[cubit];
948
    }
949

    
950
///////////////////////////////////////////////////////////////////////////////////////////////////
951

    
952
  public int getNumCubitVariants()
953
    {
954
    return mNumCubitVariants;
955
    }
956

    
957
///////////////////////////////////////////////////////////////////////////////////////////////////
958

    
959
  public int getCubitVariant(int cubit)
960
    {
961
    return mCubitVariant[cubit];
962
    }
963

    
964
///////////////////////////////////////////////////////////////////////////////////////////////////
965

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

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

    
974
  public int[] getCubitTypes()
975
    {
976
    return mCubitType;
977
    }
978

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

    
981
  public float[][] getCubitOffsets()
982
    {
983
    return mCubitRowOffset;
984
    }
985

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

    
988
  public int[][] getVariantFaceIsOuter()
989
    {
990
    return mVariantFaceIsOuter;
991
    }
992

    
993
///////////////////////////////////////////////////////////////////////////////////////////////////
994

    
995
  public int getCubitFaceFace(int cubit, int face)
996
    {
997
    return mCubitFaceColor[cubit][face];
998
    }
999

    
1000
///////////////////////////////////////////////////////////////////////////////////////////////////
1001

    
1002
  public int getNumScrambles()
1003
    {
1004
    return mNumScrambles;
1005
    }
1006

    
1007
///////////////////////////////////////////////////////////////////////////////////////////////////
1008

    
1009
  public ObjectSticker retSticker(int sticker)
1010
    {
1011
    return mObjectSticker[sticker];
1012
    }
1013

    
1014
///////////////////////////////////////////////////////////////////////////////////////////////////
1015

    
1016
  public Static3D[] getRotationAxis()
1017
    {
1018
    return mAxis;
1019
    }
1020

    
1021
///////////////////////////////////////////////////////////////////////////////////////////////////
1022

    
1023
  public int[][] getBasicAngle()
1024
    {
1025
    return mBasicAngle;
1026
    }
1027

    
1028
///////////////////////////////////////////////////////////////////////////////////////////////////
1029

    
1030
  public ObjectSignature getSignature()
1031
    {
1032
    return mSignature;
1033
    }
1034

    
1035
///////////////////////////////////////////////////////////////////////////////////////////////////
1036

    
1037
  public String getObjectName()
1038
    {
1039
    return mLongName;
1040
    }
1041

    
1042
///////////////////////////////////////////////////////////////////////////////////////////////////
1043

    
1044
  public String getShortName()
1045
    {
1046
    return mShortName;
1047
    }
1048

    
1049
///////////////////////////////////////////////////////////////////////////////////////////////////
1050

    
1051
  public String getInventor()
1052
    {
1053
    return mInventor;
1054
    }
1055

    
1056
///////////////////////////////////////////////////////////////////////////////////////////////////
1057

    
1058
  public int getYearOfInvention()
1059
    {
1060
    return mYearOfInvention;
1061
    }
1062

    
1063
///////////////////////////////////////////////////////////////////////////////////////////////////
1064

    
1065
  public int getComplexity()
1066
    {
1067
    return mComplexity;
1068
    }
1069

    
1070
///////////////////////////////////////////////////////////////////////////////////////////////////
1071

    
1072
  public int getNumFaces()
1073
    {
1074
    return mNumFaces;
1075
    }
1076

    
1077
///////////////////////////////////////////////////////////////////////////////////////////////////
1078

    
1079
  public int getNumFaceColors()
1080
    {
1081
    return mNumFaceColors;
1082
    }
1083

    
1084
///////////////////////////////////////////////////////////////////////////////////////////////////
1085

    
1086
  public int[] getNumLayers()
1087
    {
1088
    return mNumLayers;
1089
    }
1090

    
1091
///////////////////////////////////////////////////////////////////////////////////////////////////
1092

    
1093
  public float getSize()
1094
    {
1095
    return mSize;
1096
    }
1097

    
1098
///////////////////////////////////////////////////////////////////////////////////////////////////
1099

    
1100
  public int getScrambleType()
1101
    {
1102
    return mScrambleType;
1103
    }
1104

    
1105
///////////////////////////////////////////////////////////////////////////////////////////////////
1106

    
1107
  public int getColor(int face)
1108
    {
1109
    return mColor[face];
1110
    }
1111

    
1112
///////////////////////////////////////////////////////////////////////////////////////////////////
1113

    
1114
  public int getInternalColor()
1115
    {
1116
    return mInternalColor;
1117
    }
1118

    
1119
///////////////////////////////////////////////////////////////////////////////////////////////////
1120

    
1121
  public boolean shouldResetTextureMaps()
1122
    {
1123
    return mResetMaps;
1124
    }
1125

    
1126
///////////////////////////////////////////////////////////////////////////////////////////////////
1127

    
1128
  public String getTutorialObject()
1129
    {
1130
    return mTutorialObject;
1131
    }
1132

    
1133
///////////////////////////////////////////////////////////////////////////////////////////////////
1134

    
1135
  public String[][] getTutorials()
1136
    {
1137
    return mTutorials;
1138
    }
1139

    
1140
}
(1-1/2)