Project

General

Profile

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

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

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.touchcontrol.TouchControlHexahedron;
32
import org.distorted.objectlib.main.ObjectType;
33
import org.distorted.objectlib.helpers.ObjectShape;
34
import org.distorted.objectlib.scrambling.ScrambleState;
35
import org.distorted.objectlib.main.ShapeHexahedron;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

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

    
49
  private ScrambleState[] mStates;
50
  private int[] mBasicAngle;
51
  private float[][] mCuts;
52
  private float[][] mPositions;
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

    
56
  public TwistySkewb(int[] numL, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
57
    {
58
    super(numL, meshState, iconMode, 2*numL[0]-2, quat, move, scale, stream);
59
    }
60

    
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

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

    
70
      int[] tmp = {0,-1,0, 0,1,0, numL-1,-1,0, numL-1,1,0 };
71

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

    
78
    return mStates;
79
    }
80

    
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

    
83
  private int getNumCorners()
84
    {
85
    return 8;
86
    }
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

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

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96

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

    
102
///////////////////////////////////////////////////////////////////////////////////////////////////
103

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

    
112
    return mCuts;
113
    }
114

    
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116

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

    
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

    
125
  public int getTouchControlType()
126
    {
127
    return TC_HEXAHEDRON;
128
    }
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

    
132
  public int getTouchControlSplit()
133
    {
134
    return TYPE_SPLIT_CORNER;
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

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

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

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

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

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

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

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

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

    
181
      mPositions = new float[numCorners+numEdges+numCenters][];
182

    
183
      /// CORNERS //////////////////////////////////////////////
184

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

    
194
      /// CENTERS //////////////////////////////////////////////
195

    
196
      int index=8;
197
      final float X= -1000.0f;
198
      final float Y= -1001.0f;
199

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

    
210
      float x,y, cen0, cen1, cen2;
211

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

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

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

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

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

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

    
238
        x = 3-numL;
239

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

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

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

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

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

    
263
      /// EDGES ///////////////////////////////////////////////
264

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

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

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

    
294
    return mPositions;
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

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

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

    
324
      switch(center)
325
        {
326
        case 0: return new Static4D(0,-SQ2/2,0,SQ2/2);    // -90 along Y
327
        case 1: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
328
        case 2: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
329
        case 3: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
330
        case 4: return mObjectQuats[0];                   //  unit quaternion
331
        case 5: return mObjectQuats[9];                   // 180 along X
332
        }
333
      }
334
    else
335
      {
336
      int edge = (cubit-numCorners-numCenters)/(numL-2);
337

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

    
355
    return null;
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

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

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

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

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

    
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432

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

    
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

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

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446

    
447
  public float getStickerRadius()
448
    {
449
    return 0.08f;
450
    }
451

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453

    
454
  public float getStickerStroke()
455
    {
456
    float stroke = 0.08f;
457

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

    
464
    return stroke;
465
    }
466

    
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468

    
469
  public float[][] getStickerAngles()
470
    {
471
    return null;
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475
// PUBLIC API
476

    
477
  public Static3D[] getRotationAxis()
478
    {
479
    return ROT_AXIS;
480
    }
481

    
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483

    
484
  public int[] getBasicAngles()
485
    {
486
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
487
    return mBasicAngle;
488
    }
489

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

    
492
  public String getShortName()
493
    {
494
    switch(getNumLayers()[0])
495
      {
496
      case 2: return ObjectType.SKEW_2.name();
497
      case 3: return ObjectType.SKEW_3.name();
498
      }
499

    
500
    return ObjectType.SKEW_2.name();
501
    }
502

    
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504

    
505
  public long getSignature()
506
    {
507
    switch(getNumLayers()[0])
508
      {
509
      case 2: return ObjectType.SKEW_2.ordinal();
510
      case 3: return ObjectType.SKEW_3.ordinal();
511
      }
512

    
513
    return ObjectType.SKEW_2.ordinal();
514
    }
515

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

    
518
  public String getObjectName()
519
    {
520
    switch(getNumLayers()[0])
521
      {
522
      case 2: return "Skewb";
523
      case 3: return "Master Skewb";
524
      }
525
    return "Skewb";
526
    }
527

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

    
530
  public String getInventor()
531
    {
532
    switch(getNumLayers()[0])
533
      {
534
      case 2: return "Tony Durham";
535
      case 3: return "Katsuhiko Okamoto";
536
      }
537
    return "Tony Durham";
538
    }
539

    
540
///////////////////////////////////////////////////////////////////////////////////////////////////
541

    
542
  public int getYearOfInvention()
543
    {
544
    switch(getNumLayers()[0])
545
      {
546
      case 2: return 1982;
547
      case 3: return 2003;
548
      }
549
    return 1982;
550
    }
551

    
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

    
554
  public int getComplexity()
555
    {
556
    switch(getNumLayers()[0])
557
      {
558
      case 2: return 1;
559
      case 3: return 3;
560
      }
561
    return 5;
562
    }
563

    
564
///////////////////////////////////////////////////////////////////////////////////////////////////
565

    
566
  public String[][] getTutorials()
567
    {
568
    int[] numLayers = getNumLayers();
569

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