Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyKilominx.java @ 5d09301e

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.objects;
11

    
12
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.COS54;
13
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.SIN54;
14

    
15
import java.io.InputStream;
16

    
17
import org.distorted.library.type.Static3D;
18
import org.distorted.library.type.Static4D;
19
import org.distorted.library.main.QuatHelper;
20

    
21
import org.distorted.objectlib.helpers.ObjectFaceShape;
22
import org.distorted.objectlib.helpers.ObjectSignature;
23
import org.distorted.objectlib.main.InitData;
24
import org.distorted.objectlib.main.ObjectType;
25
import org.distorted.objectlib.helpers.ObjectShape;
26

    
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28

    
29
public class TwistyKilominx extends TwistyMinx
30
{
31
  public TwistyKilominx(InitData data, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
32
    {
33
    super(data, meshState, iconMode, quat, move, scale, stream);
34
    }
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37
// make the 'center' sticker artificially smaller, so that we paint over the area in the center of the face.
38

    
39
  @Override
40
  public void adjustStickerCoords()
41
    {
42
    int[] numLayers = getNumLayers();
43
    int index = numLayers[0]==3 ? 0:3;
44
    float CENTER_CORR = 0.87f;
45

    
46
    mStickerCoords[index][2] *= CENTER_CORR;
47
    mStickerCoords[index][3] *= CENTER_CORR;
48
    }
49

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

    
52
  private int numCubitsPerCorner(int numLayers)
53
    {
54
    return 3*((numLayers-3)/2)*((numLayers-5)/2) + (numLayers<5 ? 0:1);
55
    }
56

    
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58

    
59
  private int numCubitsPerEdge(int numLayers)
60
    {
61
    return numLayers<5 ? 0 : 2*(numLayers-4);
62
    }
63

    
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65

    
66
  public float[][] getCuts(int[] numLayers)
67
    {
68
    return genericGetCuts(numLayers[0],0.5f);
69
    }
70

    
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72
// Fill out mCurrCorner{X,Y,Z} by applying appropriate Quat to mBasicCorner{X,Y,Z}
73
// Appropriate one: QUATS[QUAT_INDICES[corner]].
74

    
75
  private void computeBasicCornerVectors(int corner)
76
    {
77
    if( mQuatCornerIndices==null ) initializeQuatIndices();
78
    if( mCurrCornerV==null || mBasicCornerV==null ) initializeCornerV();
79

    
80
    Static4D quat = mObjectQuats[mQuatCornerIndices[corner]];
81

    
82
    mCurrCornerV[0] = QuatHelper.rotateVectorByQuat(mBasicCornerV[0],quat);
83
    mCurrCornerV[1] = QuatHelper.rotateVectorByQuat(mBasicCornerV[1],quat);
84
    mCurrCornerV[2] = QuatHelper.rotateVectorByQuat(mBasicCornerV[2],quat);
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  private float[] computeCorner(int numCubitsPerCorner, int numLayers, int corner, int part)
90
    {
91
    if( mCorners==null ) initializeCorners();
92
    if( mCurrCornerV==null || mBasicCornerV==null ) initializeCornerV();
93

    
94
    float D = numLayers/3.0f;
95
    float[] corn = mCorners[corner];
96

    
97
    if( part==0 )
98
      {
99
      return new float[] { corn[0]*D, corn[1]*D, corn[2]*D };
100
      }
101
    else
102
      {
103
      float E = D/(0.5f*(numLayers-1));   // ?? maybe 0.5*
104
      int N = (numCubitsPerCorner-1)/3;
105
      int block = (part-1) % N;
106
      int index = (part-1) / N;
107
      Static4D pri = mCurrCornerV[index];
108
      Static4D sec = mCurrCornerV[(index+2)%3];
109

    
110
      int layers= (numLayers-5)/2;
111
      int multP = (block % layers) + 1;
112
      int multS = (block / layers);
113

    
114
      return new float[] {
115
                          corn[0]*D + (pri.get0()*multP + sec.get0()*multS)*E,
116
                          corn[1]*D + (pri.get1()*multP + sec.get1()*multS)*E,
117
                          corn[2]*D + (pri.get2()*multP + sec.get2()*multS)*E
118
                         };
119
      }
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  private float[] computeCenter(int numLayers, int center, int part)
125
    {
126
    if( mCenterCoords==null ) initializeCenterCoords();
127
    if( mCorners     ==null ) initializeCorners();
128
    if( mCenterMap   ==null ) initializeCenterMap();
129

    
130
    int corner = mCenterMap[center][part];
131
    float[] cent = mCenterCoords[center];
132
    float[] corn = mCorners[corner];
133
    float D = numLayers/3.0f;
134
    float F = 1.0f - (2.0f*numLayers-6.0f)/(numLayers-1)*COS54*COS54;
135

    
136
    return new float[]
137
      {
138
        D * ( cent[0] + (corn[0]-cent[0])*F),
139
        D * ( cent[1] + (corn[1]-cent[1])*F),
140
        D * ( cent[2] + (corn[2]-cent[2])*F)
141
      };
142
    }
143

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

    
146
  private int computeEdgeType(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
147
    {
148
    int part = (cubit - NUM_CORNERS*numCubitsPerCorner) % numCubitsPerEdge;
149
    return part - 2*(part/4);
150
    }
151

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

    
154
  private float[] computeEdge(int numLayers, int edge, int part)
155
    {
156
    if( mCenterCoords==null ) initializeCenterCoords();
157
    if( mCorners==null ) initializeCorners();
158
    if( mEdgeMap==null ) initializeEdgeMap();
159

    
160
    float D = numLayers/3.0f;
161
    float[] c1 = mCorners[ mEdgeMap[edge][0] ];
162
    float[] c2 = mCorners[ mEdgeMap[edge][1] ];
163

    
164
    int leftRight = 2*(part%2) -1;
165
    part /= 2;
166

    
167
    if( part==0 )
168
      {
169
      float T = 0.5f + leftRight/(numLayers-1.0f);
170
      float x = D * (T*c1[0]+(1.0f-T)*c2[0]);
171
      float y = D * (T*c1[1]+(1.0f-T)*c2[1]);
172
      float z = D * (T*c1[2]+(1.0f-T)*c2[2]);
173

    
174
      return new float[] { x, y, z };
175
      }
176
    else
177
      {
178
      int mult = (part+1)/2;
179
      int dir  = (part+1)%2;
180
      float[] center = mCenterCoords[ mEdgeMap[edge][dir+2] ];
181
      float x = 0.5f * D * (c1[0]+c2[0]);
182
      float y = 0.5f * D * (c1[1]+c2[1]);
183
      float z = 0.5f * D * (c1[2]+c2[2]);
184

    
185
      float vX = D*center[0] - x;
186
      float vY = D*center[1] - y;
187
      float vZ = D*center[2] - z;
188

    
189
      float T = 0.5f + leftRight*(mult*SIN18 + 1.0f)/(numLayers-1);
190

    
191
      x = D * (T*c1[0]+(1.0f-T)*c2[0]);
192
      y = D * (T*c1[1]+(1.0f-T)*c2[1]);
193
      z = D * (T*c1[2]+(1.0f-T)*c2[2]);
194

    
195
      float H = mult*D*COS18/(numLayers-1);
196
      H /= (float)Math.sqrt(vX*vX+vY*vY+vZ*vZ);
197

    
198
      return new float[] { x + H*vX, y + H*vY, z + H*vZ };
199
      }
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  public float[][] getCubitPositions(int[] numLayers)
205
    {
206
    if( mCorners==null ) initializeCorners();
207

    
208
    int numL = numLayers[0];
209
    if( numL<5 ) return mCorners;
210

    
211
    int numCubitsPerCorner = numCubitsPerCorner(numL);
212
    int numCubitsPerEdge   = numCubitsPerEdge(numL);
213
    int numCubitsPerCenter = 5;
214
    int numCubits = NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge + NUM_CENTERS*numCubitsPerCenter;
215
    int index=0;
216

    
217
    final float[][] CENTERS = new float[numCubits][];
218

    
219
    for(int corner=0; corner<NUM_CORNERS; corner++)
220
      {
221
      computeBasicCornerVectors(corner);
222

    
223
      for(int part=0; part<numCubitsPerCorner; part++, index++)
224
        {
225
        CENTERS[index] = computeCorner(numCubitsPerCorner,numL,corner,part);
226
        }
227
      }
228

    
229
    for(int edge=0; edge<NUM_EDGES; edge++)
230
      {
231
      for(int part=0; part<numCubitsPerEdge; part++, index++)
232
        {
233
        CENTERS[index] = computeEdge(numL, edge, part );
234
        }
235
      }
236

    
237
    for(int center=0; center<NUM_CENTERS; center++)
238
      {
239
      for(int part=0; part<numCubitsPerCenter; part++, index++)
240
        {
241
        CENTERS[index] = computeCenter(numL,center, part);
242
        }
243
      }
244

    
245
    return CENTERS;
246
    }
247

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

    
250
  public Static4D getCubitQuats(int cubit, int[] numLayers)
251
    {
252
    int numL = numLayers[0];
253
    int numCubitsPerCorner = numCubitsPerCorner(numL);
254
    int numCubitsPerEdge   = numCubitsPerEdge(numL);
255
    int q = getQuat(cubit,numCubitsPerCorner,numCubitsPerEdge);
256
    return mObjectQuats[q];
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260

    
261
  private int getQuat(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
262
    {
263
    if( mQuatCornerIndices==null || mQuatEdgeIndices==null ) initializeQuatIndices();
264
    if( mCenterMap==null ) initializeCenterMap();
265

    
266
    if( cubit < NUM_CORNERS*numCubitsPerCorner )
267
      {
268
      int corner = cubit/numCubitsPerCorner;
269
      return mQuatCornerIndices[corner];
270
      }
271

    
272
    if( cubit < NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
273
      {
274
      int edge = (cubit-NUM_CORNERS*numCubitsPerCorner)/numCubitsPerEdge;
275
      return mQuatEdgeIndices[edge];
276
      }
277

    
278
    if( numCubitsPerCorner==0 )
279
      {
280
      return mQuatCornerIndices[cubit];
281
      }
282
    else
283
      {
284
      cubit -= (NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge);
285
      int numCubitsPerCenter = 5;
286
      int face = cubit/numCubitsPerCenter;
287
      int index= cubit%numCubitsPerCenter;
288
      int center=mCenterMap[face][index];
289
      return mQuatCornerIndices[center];
290
      }
291
    }
292

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
295
  public ObjectShape getObjectShape(int variant)
296
    {
297
    int[] numLayers = getNumLayers();
298
    int numVariants = getNumCubitVariants(numLayers);
299
    int numL        = numLayers[0];
300
    boolean small   = numL<=3;
301

    
302
    if( variant==0 && !small )
303
      {
304
      float width = numL/(numL-1.0f);
305
      float X = width*COS18*SIN_HALFD;
306
      float Y = width*SIN18;
307
      float Z = width*COS18*COS_HALFD;
308

    
309
      float[][] vertices =
310
        {
311
            {   0,   0      ,   0 },
312
            {   X,   Y      ,  -Z },
313
            {   0, 2*Y      ,-2*Z },
314
            {  -X,   Y      ,  -Z },
315
            {   0,   0-width,   0 },
316
            {   X,   Y-width,  -Z },
317
            {   0, 2*Y-width,-2*Z },
318
            {  -X,   Y-width,  -Z },
319
        };
320

    
321
      int[][] indices =
322
        {
323
            {4,5,1,0},
324
            {7,4,0,3},
325
            {0,1,2,3},
326
            {7,6,5,4},
327
            {2,1,5,6},
328
            {3,2,6,7}
329
        };
330

    
331
      return new ObjectShape(vertices, indices);
332
      }
333
    if( variant<numVariants-1 )
334
      {
335
      int type = variant-1;
336
      float tmpVal= numL/(numL-1.0f);
337
      float height= tmpVal*COS18;
338
      float width = tmpVal + (type/2)*tmpVal*SIN18;
339
      boolean left = (type%2)==0;
340

    
341
      float X = height*SIN_HALFD;
342
      float Y = height*SIN18/COS18;
343
      float Z = height*COS_HALFD;
344

    
345
      float[][] vertices =
346
        {
347
            {   0,   0   ,   0 },
348
            {   X,   Y   ,  -Z },
349
            {   0, 2*Y   ,-2*Z },
350
            {  -X,   Y   ,  -Z },
351
            {   0, -width,   0 },
352
            {   X, -width,  -Z },
353
            {   0, -width,-2*Z },
354
            {  -X, -width,  -Z },
355
        };
356

    
357
      int[][] indices =
358
        {
359
            {4,5,1,0},
360
            {7,4,0,3},
361
            {3,2,6,7},
362
            {2,1,5,6},
363
            {0,1,2,3},
364
            {7,6,5,4}
365
        };
366

    
367
      if( !left )
368
        {
369
        int tmp, len = vertices.length;
370
        for(int i=0; i<len; i++) vertices[i][1] = -vertices[i][1];
371

    
372
        len = indices.length;
373
        for(int i=0; i<len; i++)
374
          {
375
          tmp = indices[i][0];
376
          indices[i][0] = indices[i][3];
377
          indices[i][3] = tmp;
378
          tmp = indices[i][1];
379
          indices[i][1] = indices[i][2];
380
          indices[i][2] = tmp;
381
          }
382
        }
383

    
384
      return new ObjectShape(vertices, indices);
385
      }
386
    else
387
      {
388
      float width = (1+0.5f*(numL-3)*SIN18)*numL/(numL-1);
389
      float X = width*COS18*SIN_HALFD;
390
      float Y = width*SIN18;
391
      float Z = width*COS18*COS_HALFD;
392
      float H = width*(SIN54/COS54);
393
      float H3= H/COS_HALFD;
394
      float X3= H*SIN_HALFD;
395
      float Z3= H*COS_HALFD;
396
      float C = 1/(COS54*(float)Math.sqrt(2-2*SIN18));
397

    
398
      float[][] vertices =
399
        {
400
            {   0,   0  ,     0 },
401
            {   X,   Y  ,    -Z },
402
            {   0,C*2*Y ,-2*C*Z },
403
            {  -X,   Y  ,    -Z },
404
            {   0,-width,     0 },
405
            {  X3,-width,   -Z3 },
406
            {   0,-width,   -H3 },
407
            { -X3,-width,   -Z3 }
408
        };
409

    
410
      int[][] indices =
411
        {
412
            {4,5,1,0},
413
            {7,4,0,3},
414
            {0,1,2,3},
415
            {3,2,6,7},
416
            {2,1,5,6},
417
            {7,6,5,4}
418
        };
419

    
420
      return new ObjectShape(vertices, indices);
421
      }
422
    }
423

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

    
426
  public ObjectFaceShape getObjectFaceShape(int variant)
427
    {
428
    int[] numLayers = getNumLayers();
429
    int numVariants = getNumCubitVariants(numLayers);
430
    int numL        = numLayers[0];
431
    boolean small   = numL<=3;
432

    
433
    if( variant==0 && !small )
434
      {
435
      float A = (2*SQ3/3)*SIN54;
436
      float B = 0.4f;
437
      float h1 = isInIconMode() ? 0.001f : 0.04f;
438

    
439
      float[][] bands     = { {h1,34,0.3f,0.2f, 3, 0, 0}, {0.001f,34,0.0f,0.0f, 2, 0, 0} };
440
      int[] bandIndices   = { 0,0,0,1,1,1};
441
      float[][] corners   = { {0.04f,0.10f} };
442
      int[] cornerIndices = { 0,-1,-1,-1,-1,-1,-1,-1 };
443
      float[][] centers   = { {0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B} };
444
      int[] centerIndices = { 0,-1,-1,-1,-1,-1,-1,-1 };
445

    
446
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
447
      }
448
    if( variant<numVariants-1 )
449
      {
450
      int type = variant-1;
451
      float tmpVal= numL/(numL-1.0f);
452
      float height= tmpVal*COS18;
453
      float width = tmpVal + (type/2)*tmpVal*SIN18;
454
      float Z = height*COS_HALFD;
455
      int E  = small ? 1 : 0;
456
      int N0 = small ? 4 : 3;
457
      int N1 = small ? 3 : 2;
458
      float h1 = isInIconMode() ? 0.001f : 0.04f;
459

    
460
      float[][] bands     = { {h1,34,0.2f,0.2f,N0,E,E}, {0.001f,34,0.0f,0.0f,N1,0,0} };
461
      int[] bandIndices   = { 0,0,1,1,1,1};
462
      float[][] corners   = { {0.04f,0.10f} };
463
      int[] cornerIndices = { 0,-1,-1,-1, 0,-1,-1,-1 };
464
      float[][] centers   = { {0.0f, -width/2, -2*Z} };
465
      int[] centerIndices = { 0,-1,-1,-1, 0,-1,-1,-1 };
466

    
467
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
468
      }
469
    else
470
      {
471
      float A = (2*SQ3/3)*SIN54;
472
      float B = 0.4f;
473
      int N = small ? 4 : 3;
474
      int E = small ? 1 : 0;
475
      float h1 = isInIconMode() ? 0.001f : 0.04f;
476
      float h2 = isInIconMode() ? 0.001f : 0.01f;
477

    
478
      float[][] bands     = { {h1,17,0.3f,0.2f,N,E,E},{h2,17,0.3f,0.2f,N,E,E} };
479
      int[] bandIndices   = { 0,0,0,1,1,1};
480
      float[][] corners   = { {0.03f,0.10f} };
481
      int[] cornerIndices = { 0, 0,-1, 0, 0,-1,-1,-1 };
482
      float[][] centers   = { {0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B} };
483
      int[] centerIndices = { 0, 0,-1, 0, 0,-1,-1,-1 };
484

    
485
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
486
      }
487
    }
488

    
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490

    
491
  public int getNumCubitVariants(int[] numLayers)
492
    {
493
    switch(numLayers[0])
494
      {
495
      case 3: return 1;
496
      case 5: return 4;
497
      }
498

    
499
    return 1;
500
    }
501

    
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503

    
504
  public int getCubitVariant(int cubit, int[] numLayers)
505
    {
506
    int numL = numLayers[0];
507
    int numCubitsPerCorner = numCubitsPerCorner(numL);
508

    
509
    if( cubit<NUM_CORNERS*numCubitsPerCorner ) return 0;
510

    
511
    int numCubitsPerEdge = numCubitsPerEdge(numL);
512

    
513
    if( cubit<NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
514
      {
515
      int type = computeEdgeType(cubit,numCubitsPerCorner,numCubitsPerEdge);
516
      return type+1;
517
      }
518

    
519
    return getNumCubitVariants(numLayers)-1;
520
    }
521

    
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523

    
524
  public float getStickerRadius()
525
    {
526
    return 0.18f;
527
    }
528

    
529
///////////////////////////////////////////////////////////////////////////////////////////////////
530

    
531
  public float getStickerStroke()
532
    {
533
    float stroke = 0.25f;
534

    
535
    if( isInIconMode() )
536
      {
537
      int[] numLayers = getNumLayers();
538
      if( numLayers[0]>3 ) stroke*=1.5f;
539
      }
540

    
541
    return stroke;
542
    }
543

    
544
///////////////////////////////////////////////////////////////////////////////////////////////////
545

    
546
  public float[][] getStickerAngles()
547
    {
548
    return null;
549
    }
550

    
551
///////////////////////////////////////////////////////////////////////////////////////////////////
552

    
553
  public String getShortName()
554
    {
555
    switch(getNumLayers()[0])
556
      {
557
      case 3: return ObjectType.KILO_3.name();
558
      case 5: return ObjectType.KILO_5.name();
559
      }
560

    
561
    return ObjectType.KILO_3.name();
562
    }
563

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

    
566
  public ObjectSignature getSignature()
567
    {
568
    switch(getNumLayers()[0])
569
      {
570
      case 3: return new ObjectSignature(ObjectType.KILO_3);
571
      case 5: return new ObjectSignature(ObjectType.KILO_5);
572
      }
573

    
574
    return null;
575
    }
576

    
577
///////////////////////////////////////////////////////////////////////////////////////////////////
578

    
579
  public String getObjectName()
580
    {
581
    switch(getNumLayers()[0])
582
      {
583
      case 3: return "Kilominx";
584
      case 5: return "Master Kilominx";
585
      }
586
    return null;
587
    }
588

    
589
///////////////////////////////////////////////////////////////////////////////////////////////////
590

    
591
  public String getInventor()
592
    {
593
    switch(getNumLayers()[0])
594
      {
595
      case 3: return "Thomas de Bruin";
596
      case 5: return "David Gugl";
597
      }
598
    return "Thomas de Bruin";
599
    }
600

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

    
603
  public int getYearOfInvention()
604
    {
605
    switch(getNumLayers()[0])
606
      {
607
      case 3: return 2008;
608
      case 5: return 2010;
609
      }
610
    return 2008;
611
    }
612

    
613
///////////////////////////////////////////////////////////////////////////////////////////////////
614

    
615
  public int getComplexity()
616
    {
617
    switch(getNumLayers()[0])
618
      {
619
      case 3: return 2;
620
      case 5: return 3;
621
      }
622
    return 8;
623
    }
624

    
625
///////////////////////////////////////////////////////////////////////////////////////////////////
626

    
627
  public String[][] getTutorials()
628
    {
629
    int[] numLayers = getNumLayers();
630

    
631
    switch(numLayers[0])
632
      {
633
      case 3: return new String[][] {
634
                          {"gb","grgGgUSxiQg","How to Solve the Kilominx","Z3"},
635
                          {"es","g6WMYjkCLok","Resolver Kilominx","Cuby"},
636
                          {"ru","gjaknjuZXPs","Киломинкс как собрать","CUBES WORLD"},
637
                          {"fr","F7z6LztN-7A","Résoudre le Kilominx","Twins Cuber"},
638
                          {"de","fcmJdpLfZwk","Megaminx 2x2 lösen","JamesKnopf"},
639
                          {"pl","tdWh8f8qpq4","Kilominx TUTORIAL PL","MrUK"},
640
                          {"kr","8-X4GhQnE5I","2X2 킬로밍크스 TUTORIAL","큐브놀이터"},
641
                          {"vn","eW7RLayPPmA","Tutorial N.11 - Kilominx","Duy Thích Rubik"},
642
                         };
643
      case 5: return new String[][] {
644
                          {"gb","VAnzC2SYVc4","How To Solve A Master Kilominx","Grizz Media"},
645
                          {"es","ozINTg-61Fs","Tutorial Master Kilominx","RubikArt"},
646
                          {"ru","0aemQayCZRc","Как собрать Мастер Киломинкс ч.1","Артем Мартиросов"},
647
                          {"ru","ohOUFTx-oQI","Как собрать Мастер Киломинкс ч.2","Артем Мартиросов"},
648
                          {"ru","YRXRdT2jCn8","Как собрать Мастер Киломинкс ч.3","Артем Мартиросов"},
649
                          {"fr","usMiWt44aqo","Résolution du Master Kilominx","Asthalis"},
650
                          {"pl","rdln0IG86_s","Master Kilominx TUTORIAL PL","MrUK"},
651
                          {"br","0nmaZf2-44M","Como resolver o Master Kilominx 1/3","Rafael Cinoto"},
652
                          {"br","SkR6RybAKHc","Como resolver o Master Kilominx 2/3","Rafael Cinoto"},
653
                          {"br","5C7J7Cb4a7Q","Como resolver o Master Kilominx 3/3","Rafael Cinoto"},
654
                          {"kr","dvy-GxCjm5c","마스터 킬로밍크스 배우기 1","vincentcube"},
655
                          {"kr","Jm0B12vNxsE","마스터 킬로밍크스 배우기 2","vincentcube"},
656
                          {"kr","H1I18FVpr6g","마스터 킬로밍크스 배우기 3","vincentcube"},
657
                         };
658
      }
659
    return null;
660
    }
661
}
(16-16/36)