Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistySkewb.java @ a8295031

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube 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
// Magic Cube 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 Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.objects;
21

    
22
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_HEXAHEDRON;
23
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_SPLIT_CORNER;
24

    
25
import java.io.InputStream;
26

    
27
import org.distorted.library.type.Static3D;
28
import org.distorted.library.type.Static4D;
29

    
30
import org.distorted.objectlib.helpers.ObjectFaceShape;
31
import org.distorted.objectlib.helpers.ObjectSignature;
32
import org.distorted.objectlib.main.InitData;
33
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
34
import org.distorted.objectlib.main.ObjectType;
35
import org.distorted.objectlib.helpers.ObjectShape;
36
import org.distorted.objectlib.scrambling.ScrambleState;
37
import org.distorted.objectlib.main.ShapeHexahedron;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
public class TwistySkewb extends ShapeHexahedron
42
{
43
  static final Static3D[] ROT_AXIS = new Static3D[]
44
         {
45
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
46
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
47
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
48
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
49
         };
50

    
51
  private ScrambleState[] mStates;
52
  private int[][] mBasicAngle;
53
  private float[][] mCuts;
54
  private float[][] mPositions;
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

    
58
  public TwistySkewb(InitData data, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
59
    {
60
    super(data, meshState, iconMode, 2*data.getNumLayers()[0]-2, quat, move, scale, stream);
61
    }
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

    
65
  public ScrambleState[] getScrambleStates()
66
    {
67
    if( mStates==null )
68
      {
69
      int[] numLayers = getNumLayers();
70
      int numL = numLayers[0];
71

    
72
      int[] tmp = {0,-1,0, 0,1,0, numL-1,-1,0, numL-1,1,0 };
73

    
74
      mStates = new ScrambleState[]
75
        {
76
        new ScrambleState( new int[][] {tmp,tmp,tmp,tmp} )
77
        };
78
      }
79

    
80
    return mStates;
81
    }
82

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

    
85
  private int getNumCorners()
86
    {
87
    return 8;
88
    }
89

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

    
92
  private int getNumEdges(int numLayers)
93
    {
94
    return (numLayers-2)*12;
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98

    
99
  private int getNumCentersPerFace(int numLayers)
100
    {
101
    return ((numLayers-2)*(numLayers-2) + (numLayers-1)*(numLayers-1));
102
    }
103

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

    
106
  public float[][] getCuts(int[] numLayers)
107
    {
108
    if( mCuts==null )
109
      {
110
      float[] c = numLayers[0]==2 ? (new float[] {0.0f}) : (new float[] {-SQ3/6,+SQ3/6});
111
      mCuts = new float[][] {c,c,c,c};
112
      }
113

    
114
    return mCuts;
115
    }
116

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118

    
119
  public boolean[][] getLayerRotatable(int[] numLayers)
120
    {
121
    boolean[] tmp = numLayers[0]==2 ? (new boolean[] {true,true}) : (new boolean[] {true,false,true});
122
    return new boolean[][] { tmp,tmp,tmp,tmp };
123
    }
124

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

    
127
  public int getTouchControlType()
128
    {
129
    return TC_HEXAHEDRON;
130
    }
131

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

    
134
  public int getTouchControlSplit()
135
    {
136
    return TYPE_SPLIT_CORNER;
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

    
141
  public int[][][] getEnabled()
142
    {
143
    return new int[][][]
144
      {
145
          {{0,1},{3,1},{2,3},{0,2}},
146
          {{2,3},{3,1},{0,1},{0,2}},
147
          {{1,2},{0,1},{0,3},{2,3}},
148
          {{1,2},{2,3},{0,3},{0,1}},
149
          {{0,3},{0,2},{1,2},{1,3}},
150
          {{1,2},{0,2},{0,3},{1,3}},
151
      };
152
    }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

    
156
  public float[] getDist3D(int[] numLayers)
157
    {
158
    return TouchControlHexahedron.D3D;
159
    }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
  public Static3D[] getFaceAxis()
164
    {
165
    return TouchControlHexahedron.FACE_AXIS;
166
    }
167

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

    
170
  public float[][] getCubitPositions(int[] numLayers)
171
    {
172
    if( mPositions==null )
173
      {
174
      int numL = numLayers[0];
175
      final float DIST_CORNER = numL-1;
176
      final float DIST_EDGE   = numL-1;
177
      final float DIST_CENTER = numL-1;
178

    
179
      final int numCorners = getNumCorners();
180
      final int numEdges   = getNumEdges(numL);
181
      final int numCenters = 6*getNumCentersPerFace(numL);
182

    
183
      mPositions = new float[numCorners+numEdges+numCenters][];
184

    
185
      /// CORNERS //////////////////////////////////////////////
186

    
187
      mPositions[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
188
      mPositions[1] = new float[] { DIST_CORNER, DIST_CORNER,-DIST_CORNER };
189
      mPositions[2] = new float[] { DIST_CORNER,-DIST_CORNER, DIST_CORNER };
190
      mPositions[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
191
      mPositions[4] = new float[] {-DIST_CORNER, DIST_CORNER, DIST_CORNER };
192
      mPositions[5] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
193
      mPositions[6] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
194
      mPositions[7] = new float[] {-DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
195

    
196
      /// CENTERS //////////////////////////////////////////////
197

    
198
      int index=8;
199
      final float X= -1000.0f;
200
      final float Y= -1001.0f;
201

    
202
      final float[][]  centerTable =
203
        {
204
            {X,Y,+DIST_CENTER},
205
            {X,Y,-DIST_CENTER},
206
            {X,+DIST_CENTER,Y},
207
            {X,-DIST_CENTER,Y},
208
            {+DIST_CENTER,X,Y},
209
            {-DIST_CENTER,X,Y},
210
        };
211

    
212
      float x,y, cen0, cen1, cen2;
213

    
214
      for( float[] centers : centerTable )
215
        {
216
        x = 2-numL;
217

    
218
        for(int i=0; i<numL-1; i++, x+=2)
219
          {
220
          y = 2-numL;
221

    
222
          for(int j=0; j<numL-1; j++, y+=2, index++)
223
            {
224
                 if( centers[0]==Y ) cen0 = y;
225
            else if( centers[0]==X ) cen0 = x;
226
            else                     cen0 = centers[0];
227

    
228
                 if( centers[1]==Y ) cen1 = y;
229
            else if( centers[1]==X ) cen1 = x;
230
            else                     cen1 = centers[1];
231

    
232
                 if( centers[2]==Y ) cen2 = y;
233
            else if( centers[2]==X ) cen2 = x;
234
            else                     cen2 = centers[2];
235

    
236
            mPositions[index] = new float[] {cen0,cen1,cen2};
237
            }
238
          }
239

    
240
        x = 3-numL;
241

    
242
        for(int i=0; i<numL-2; i++, x+=2)
243
          {
244
          y = 3-numL;
245

    
246
          for(int j=0; j<numL-2; j++, y+=2, index++)
247
            {
248
                 if( centers[0]==Y ) cen0 = y;
249
            else if( centers[0]==X ) cen0 = x;
250
            else                     cen0 = centers[0];
251

    
252
                 if( centers[1]==Y ) cen1 = y;
253
            else if( centers[1]==X ) cen1 = x;
254
            else                     cen1 = centers[1];
255

    
256
                 if( centers[2]==Y ) cen2 = y;
257
            else if( centers[2]==X ) cen2 = x;
258
            else                     cen2 = centers[2];
259

    
260
            mPositions[index] = new float[] {cen0,cen1,cen2};
261
            }
262
          }
263
        }
264

    
265
      /// EDGES ///////////////////////////////////////////////
266

    
267
      final float[][]  edgeTable =
268
        {
269
            {0,+DIST_EDGE,+DIST_EDGE},
270
            {+DIST_EDGE,0,+DIST_EDGE},
271
            {0,-DIST_EDGE,+DIST_EDGE},
272
            {-DIST_EDGE,0,+DIST_EDGE},
273
            {+DIST_EDGE,+DIST_EDGE,0},
274
            {+DIST_EDGE,-DIST_EDGE,0},
275
            {-DIST_EDGE,-DIST_EDGE,0},
276
            {-DIST_EDGE,+DIST_EDGE,0},
277
            {0,+DIST_EDGE,-DIST_EDGE},
278
            {+DIST_EDGE,0,-DIST_EDGE},
279
            {0,-DIST_EDGE,-DIST_EDGE},
280
            {-DIST_EDGE,0,-DIST_EDGE}
281
        };
282

    
283
      for (float[] edges : edgeTable)
284
        {
285
        float c = 3-numL;
286

    
287
        for (int j=0; j<numL-2; j++, c+=2, index++)
288
          {
289
          mPositions[index] = new float[] { edges[0]==0 ? c : edges[0] ,
290
                                            edges[1]==0 ? c : edges[1] ,
291
                                            edges[2]==0 ? c : edges[2] };
292
          }
293
        }
294
      }
295

    
296
    return mPositions;
297
    }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  public Static4D getCubitQuats(int cubit, int[] numLayers)
302
    {
303
    int numL = numLayers[0];
304
    int numCorners = getNumCorners();
305
    int numCentersPerFace = getNumCentersPerFace(numL);
306
    int numCenters = 6*numCentersPerFace;
307

    
308
    if( cubit<numCorners )
309
      {
310
      switch(cubit)
311
        {
312
        case  0: return mObjectQuats[0];                   //  unit quat
313
        case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
314
        case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
315
        case  3: return mObjectQuats[9];                   // 180 along X
316
        case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
317
        case  5: return mObjectQuats[11];                  // 180 along Y
318
        case  6: return mObjectQuats[10];                  // 180 along Z
319
        case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
320
        }
321
      }
322
    else if( cubit<numCorners+numCenters )
323
      {
324
      int center = (cubit-numCorners)/numCentersPerFace;
325

    
326
      switch(center)
327
        {
328
        case 0: return mObjectQuats[0];
329
        case 1: return mObjectQuats[9];
330
        case 2: return mObjectQuats[1];
331
        case 3: return mObjectQuats[4];
332
        case 4: return mObjectQuats[2];
333
        case 5: return mObjectQuats[3];
334
        }
335
      }
336
    else
337
      {
338
      int edge = (cubit-numCorners-numCenters)/(numL-2);
339

    
340
      switch(edge)
341
        {
342
        case  0: return mObjectQuats[ 0];
343
        case  1: return mObjectQuats[ 2];
344
        case  2: return mObjectQuats[10];
345
        case  3: return mObjectQuats[ 8];
346
        case  4: return mObjectQuats[ 1];
347
        case  5: return mObjectQuats[ 4];
348
        case  6: return mObjectQuats[ 6];
349
        case  7: return mObjectQuats[ 7];
350
        case  8: return mObjectQuats[11];
351
        case  9: return mObjectQuats[ 5];
352
        case 10: return mObjectQuats[ 9];
353
        case 11: return mObjectQuats[ 3];
354
        }
355
      }
356

    
357
    return null;
358
    }
359

    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

    
362
  public ObjectShape getObjectShape(int variant)
363
    {
364
    if( variant==0 )
365
      {
366
      float[][] vertices= { {-1,0,0},{0,-1,0},{0,0,-1},{-1,-1,-1},{0,0,0} };
367
      int[][] indices   = { {0,1,4},{2,0,4},{1,2,4},{3,1,0},{3,2,1},{3,0,2} };
368
      return new ObjectShape(vertices, indices);
369
      }
370
    else if( variant==1 )
371
      {
372
      float[][] vertices= { {-1,0,0},{0,-1,0},{1,0,0},{0,1,0},{0,0,-1} };
373
      int[][] indices   = { {0,1,2,3},{4,1,0},{4,2,1},{4,3,2},{4,0,3} };
374
      return new ObjectShape(vertices, indices);
375
      }
376
    else
377
      {
378
      float[][] vertices= { {-1,0,0},{1,0,0},{0,-1,0},{0,0,-1} };
379
      int[][] indices   = { {2,1,0},{3,0,1},{2,3,1},{3,2,0} };
380
      return new ObjectShape(vertices, indices);
381
      }
382
    }
383

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

    
386
  public ObjectFaceShape getObjectFaceShape(int variant)
387
    {
388
    int numL = getNumLayers()[0];
389

    
390
    if( variant==0 )
391
      {
392
      int N = numL==2 ? 7:5;
393
      int E1= numL==2 ? 3:2;
394
      int E2= numL==2 ? 5:3;
395
      float height = isInIconMode() ? 0.001f : 0.02f;
396
      float[][] bands     = { {height,35,0.16f,0.7f,N,E1,E1}, {0.001f, 35,1.00f,0.0f,3,1,E2} };
397
      int[] bandIndices   = { 0,0,0,1,1,1 };
398
      float[][] corners   = { {0.05f,0.25f}, {0.05f,0.20f} };
399
      int[] cornerIndices = { 1,1,1,0,0 };
400
      float[][] centers   = { {-0.5f, -0.5f, -0.5f} };
401
      int[] centerIndices = { 0,0,0,-1,0 };
402
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
403
      }
404
    else if( variant==1 )
405
      {
406
      int N = numL==2 ? 7:6;
407
      int E = numL==2 ? 3:1;
408
      float height = isInIconMode() ? 0.001f : 0.04f;
409
      float[][] bands     = { {height,35,SQ2/8,0.9f,N,E,E}, {0.001f,35,1,0.0f,3,0,0} };
410
      int[] bandIndices   = { 0,1,1,1,1 };
411
      float[][] corners   = { {0.06f,0.15f} };
412
      int[] cornerIndices = { 0,0,0,0,0 };
413
      float[][] centers   = { {0,0,-0.4f} };
414
      int[] centerIndices = { 0,0,0,0,-1 };
415
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
416
      }
417
    else
418
      {
419
      int N = numL==2 ? 7:5;
420
      int E = numL==2 ? 5:2;
421
      float h1 = isInIconMode() ? 0.001f : 0.035f;
422
      float h2 = isInIconMode() ? 0.001f : 0.020f;
423
      float[][] bands     = { {h1,30,0.16f,0.8f,N,2,E}, {h2,45,0.16f,0.2f,3,1,2} };
424
      int[] bandIndices   = { 0,0,1,1 };
425
      float[][] corners   = { {0.07f,0.20f}, {0.02f,0.30f} };
426
      int[] cornerIndices = { 0,0,1,1 };
427
      float[][] centers   = { {0.0f, -0.5f, -0.5f} };
428
      int[] centerIndices = { 0,0,0,0 };
429
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
430
      }
431
    }
432

    
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434

    
435
  public int getNumCubitVariants(int[] numLayers)
436
    {
437
    return numLayers[0]==2 ? 2:3;
438
    }
439

    
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441

    
442
  public int getCubitVariant(int cubit, int[] numLayers)
443
    {
444
    return cubit<8 ? 0 : (cubit<8+6*getNumCentersPerFace(numLayers[0]) ? 1:2);
445
    }
446

    
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

    
449
  public float getStickerRadius()
450
    {
451
    return 0.08f;
452
    }
453

    
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

    
456
  public float getStickerStroke()
457
    {
458
    float stroke = 0.08f;
459

    
460
    if( isInIconMode() )
461
      {
462
      int[] numLayers = getNumLayers();
463
      stroke *= (numLayers[0]==2 ? 2.0f : 2.7f);
464
      }
465

    
466
    return stroke;
467
    }
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

    
471
  public float[][] getStickerAngles()
472
    {
473
    return null;
474
    }
475

    
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477
// PUBLIC API
478

    
479
  public Static3D[] getRotationAxis()
480
    {
481
    return ROT_AXIS;
482
    }
483

    
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485

    
486
  public int[][] getBasicAngles()
487
    {
488
    if( mBasicAngle ==null )
489
      {
490
      int num = getNumLayers()[0];
491
      int[] tmp = new int[num];
492
      for(int i=0; i<num; i++) tmp[i] = 3;
493
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
494
      }
495

    
496
    return mBasicAngle;
497
    }
498

    
499
///////////////////////////////////////////////////////////////////////////////////////////////////
500

    
501
  public String getShortName()
502
    {
503
    switch(getNumLayers()[0])
504
      {
505
      case 2: return ObjectType.SKEW_2.name();
506
      case 3: return ObjectType.SKEW_3.name();
507
      }
508

    
509
    return ObjectType.SKEW_2.name();
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513

    
514
  public ObjectSignature getSignature()
515
    {
516
    switch(getNumLayers()[0])
517
      {
518
      case 2: return new ObjectSignature(ObjectType.SKEW_2);
519
      case 3: return new ObjectSignature(ObjectType.SKEW_3);
520
      }
521

    
522
    return null;
523
    }
524

    
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526

    
527
  public String getObjectName()
528
    {
529
    switch(getNumLayers()[0])
530
      {
531
      case 2: return "Skewb";
532
      case 3: return "Master Skewb";
533
      }
534
    return null;
535
    }
536

    
537
///////////////////////////////////////////////////////////////////////////////////////////////////
538

    
539
  public String getInventor()
540
    {
541
    switch(getNumLayers()[0])
542
      {
543
      case 2: return "Tony Durham";
544
      case 3: return "Katsuhiko Okamoto";
545
      }
546
    return null;
547
    }
548

    
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550

    
551
  public int getYearOfInvention()
552
    {
553
    switch(getNumLayers()[0])
554
      {
555
      case 2: return 1982;
556
      case 3: return 2003;
557
      }
558
    return 1982;
559
    }
560

    
561
///////////////////////////////////////////////////////////////////////////////////////////////////
562

    
563
  public int getComplexity()
564
    {
565
    switch(getNumLayers()[0])
566
      {
567
      case 2: return 1;
568
      case 3: return 3;
569
      }
570
    return 5;
571
    }
572

    
573
///////////////////////////////////////////////////////////////////////////////////////////////////
574

    
575
  public String[][] getTutorials()
576
    {
577
    int[] numLayers = getNumLayers();
578

    
579
    switch(numLayers[0])
580
      {
581
      case 2: return new String[][] {
582
                          {"gb","I6132yshkeU","How to Solve the Skewb","Z3"},
583
                          {"es","wxQX3HhPgds","Resolver Skewb (Principiantes)","Cuby"},
584
                          {"ru","EICw3aqn6Bc","Как собрать Скьюб?","Алексей Ярыгин"},
585
                          {"fr","lR-GuIroh4k","Comment réussir le skewb","Rachma Nikov"},
586
                          {"de","7RX6D5pznOk","Skewb lösen","Pezcraft"},
587
                          {"pl","ofRu1fByNpk","Jak ułożyć: Skewb","DżoDżo"},
588
                          {"br","mNycauwshWs","Como resolver o Skewb","Pedro Filho"},
589
                          {"kr","5R3sU-_bMAI","SKEWB 초보 공식","iamzoone"},
590
                          {"vn","Db5mXuqgQP8","Tutorial N.5 - Skewb","Duy Thích Rubik"},
591
                     //   {"tw","8srf9xhsS9k","Skewb斜轉方塊解法","1hrBLD"},
592
                         };
593
      case 3: return new String[][] {
594
                          {"gb","Jiuf7zQyPYI","Master Skewb Cube Tutorial","Bearded Cubing"},
595
                          {"es","8TP6p63KQCA","Master Skewb en Español","jorlozCubes"},
596
                          {"ru","7155QSp3T74","часть 1: Как собрать мастер Скьюб","Иван Циков"},
597
                          {"ru","14ey-RihjgY","часть 2: Как собрать мастер Скьюб","Иван Циков"},
598
                          {"ru","watq6TLa5_E","часть 2.5: Как собрать мастер Скьюб","Иван Циков"},
599
                          {"ru","UnsvseFBXmo","часть 3: Как собрать мастер Скьюб","Иван Циков"},
600
                          {"fr","tYMoY4EOHVA","Résolution du Master Skewb","Asthalis"},
601
                          {"de","LSErzqGNElI","Master Skewb lösen","JamesKnopf"},
602
                          {"pl","Y7l3AYFvDJI","Master Skewb TUTORIAL PL","MrUk"},
603
                          {"kr","ycR-WmXJCG0","마스터 스큐브 3번째 해법","듀나메스 큐브 해법연구소"},
604
                          {"vn","uG8H0ZQTZgw","Tutorial N.35 - Master Skewb","Duy Thích Rubik"},
605
                         };
606
      }
607
    return null;
608
    }
609
}
(32-32/40)