Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyKilominx.java @ 1d581993

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.TouchControlDodecahedron.COS54;
23
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.SIN54;
24

    
25
import java.io.InputStream;
26

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

    
31
import org.distorted.objectlib.helpers.ObjectFaceShape;
32
import org.distorted.objectlib.helpers.ObjectSignature;
33
import org.distorted.objectlib.main.ObjectType;
34
import org.distorted.objectlib.helpers.ObjectShape;
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

    
38
public class TwistyKilominx extends TwistyMinx
39
{
40
  public TwistyKilominx(int[] numL, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
41
    {
42
    super(numL, meshState, iconMode, quat, move, scale, stream);
43
    }
44

    
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46
// make the 'center' sticker artificially smaller, so that we paint over the area in the center of the face.
47

    
48
  @Override
49
  public void adjustStickerCoords()
50
    {
51
    int[] numLayers = getNumLayers();
52
    int index = numLayers[0]==3 ? 0:3;
53
    float CENTER_CORR = 0.87f;
54

    
55
    mStickerCoords[index][2] *= CENTER_CORR;
56
    mStickerCoords[index][3] *= CENTER_CORR;
57
    }
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
  private int numCubitsPerCorner(int numLayers)
62
    {
63
    return 3*((numLayers-3)/2)*((numLayers-5)/2) + (numLayers<5 ? 0:1);
64
    }
65

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

    
68
  private int numCubitsPerEdge(int numLayers)
69
    {
70
    return numLayers<5 ? 0 : 2*(numLayers-4);
71
    }
72

    
73
///////////////////////////////////////////////////////////////////////////////////////////////////
74

    
75
  public float[][] getCuts(int[] numLayers)
76
    {
77
    return genericGetCuts(numLayers[0],0.5f);
78
    }
79

    
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81
// Fill out mCurrCorner{X,Y,Z} by applying appropriate Quat to mBasicCorner{X,Y,Z}
82
// Appropriate one: QUATS[QUAT_INDICES[corner]].
83

    
84
  private void computeBasicCornerVectors(int corner)
85
    {
86
    if( mQuatCornerIndices==null ) initializeQuatIndices();
87
    if( mCurrCornerV==null || mBasicCornerV==null ) initializeCornerV();
88

    
89
    Static4D quat = mObjectQuats[mQuatCornerIndices[corner]];
90

    
91
    mCurrCornerV[0] = QuatHelper.rotateVectorByQuat(mBasicCornerV[0],quat);
92
    mCurrCornerV[1] = QuatHelper.rotateVectorByQuat(mBasicCornerV[1],quat);
93
    mCurrCornerV[2] = QuatHelper.rotateVectorByQuat(mBasicCornerV[2],quat);
94
    }
95

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

    
98
  private float[] computeCorner(int numCubitsPerCorner, int numLayers, int corner, int part)
99
    {
100
    if( mCorners==null ) initializeCorners();
101
    if( mCurrCornerV==null || mBasicCornerV==null ) initializeCornerV();
102

    
103
    float D = numLayers/3.0f;
104
    float[] corn = mCorners[corner];
105

    
106
    if( part==0 )
107
      {
108
      return new float[] { corn[0]*D, corn[1]*D, corn[2]*D };
109
      }
110
    else
111
      {
112
      float E = D/(0.5f*(numLayers-1));   // ?? maybe 0.5*
113
      int N = (numCubitsPerCorner-1)/3;
114
      int block = (part-1) % N;
115
      int index = (part-1) / N;
116
      Static4D pri = mCurrCornerV[index];
117
      Static4D sec = mCurrCornerV[(index+2)%3];
118

    
119
      int layers= (numLayers-5)/2;
120
      int multP = (block % layers) + 1;
121
      int multS = (block / layers);
122

    
123
      return new float[] {
124
                          corn[0]*D + (pri.get0()*multP + sec.get0()*multS)*E,
125
                          corn[1]*D + (pri.get1()*multP + sec.get1()*multS)*E,
126
                          corn[2]*D + (pri.get2()*multP + sec.get2()*multS)*E
127
                         };
128
      }
129
    }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  private float[] computeCenter(int numLayers, int center, int part)
134
    {
135
    if( mCenterCoords==null ) initializeCenterCoords();
136
    if( mCorners     ==null ) initializeCorners();
137
    if( mCenterMap   ==null ) initializeCenterMap();
138

    
139
    int corner = mCenterMap[center][part];
140
    float[] cent = mCenterCoords[center];
141
    float[] corn = mCorners[corner];
142
    float D = numLayers/3.0f;
143
    float F = 1.0f - (2.0f*numLayers-6.0f)/(numLayers-1)*COS54*COS54;
144

    
145
    return new float[]
146
      {
147
        D * ( cent[0] + (corn[0]-cent[0])*F),
148
        D * ( cent[1] + (corn[1]-cent[1])*F),
149
        D * ( cent[2] + (corn[2]-cent[2])*F)
150
      };
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  private int computeEdgeType(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
156
    {
157
    int part = (cubit - NUM_CORNERS*numCubitsPerCorner) % numCubitsPerEdge;
158
    return part - 2*(part/4);
159
    }
160

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

    
163
  private float[] computeEdge(int numLayers, int edge, int part)
164
    {
165
    if( mCenterCoords==null ) initializeCenterCoords();
166
    if( mCorners==null ) initializeCorners();
167
    if( mEdgeMap==null ) initializeEdgeMap();
168

    
169
    float D = numLayers/3.0f;
170
    float[] c1 = mCorners[ mEdgeMap[edge][0] ];
171
    float[] c2 = mCorners[ mEdgeMap[edge][1] ];
172

    
173
    int leftRight = 2*(part%2) -1;
174
    part /= 2;
175

    
176
    if( part==0 )
177
      {
178
      float T = 0.5f + leftRight/(numLayers-1.0f);
179
      float x = D * (T*c1[0]+(1.0f-T)*c2[0]);
180
      float y = D * (T*c1[1]+(1.0f-T)*c2[1]);
181
      float z = D * (T*c1[2]+(1.0f-T)*c2[2]);
182

    
183
      return new float[] { x, y, z };
184
      }
185
    else
186
      {
187
      int mult = (part+1)/2;
188
      int dir  = (part+1)%2;
189
      float[] center = mCenterCoords[ mEdgeMap[edge][dir+2] ];
190
      float x = 0.5f * D * (c1[0]+c2[0]);
191
      float y = 0.5f * D * (c1[1]+c2[1]);
192
      float z = 0.5f * D * (c1[2]+c2[2]);
193

    
194
      float vX = D*center[0] - x;
195
      float vY = D*center[1] - y;
196
      float vZ = D*center[2] - z;
197

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

    
200
      x = D * (T*c1[0]+(1.0f-T)*c2[0]);
201
      y = D * (T*c1[1]+(1.0f-T)*c2[1]);
202
      z = D * (T*c1[2]+(1.0f-T)*c2[2]);
203

    
204
      float H = mult*D*COS18/(numLayers-1);
205
      H /= (float)Math.sqrt(vX*vX+vY*vY+vZ*vZ);
206

    
207
      return new float[] { x + H*vX, y + H*vY, z + H*vZ };
208
      }
209
    }
210

    
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

    
213
  public float[][] getCubitPositions(int[] numLayers)
214
    {
215
    if( mCorners==null ) initializeCorners();
216

    
217
    int numL = numLayers[0];
218
    if( numL<5 ) return mCorners;
219

    
220
    int numCubitsPerCorner = numCubitsPerCorner(numL);
221
    int numCubitsPerEdge   = numCubitsPerEdge(numL);
222
    int numCubitsPerCenter = 5;
223
    int numCubits = NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge + NUM_CENTERS*numCubitsPerCenter;
224
    int index=0;
225

    
226
    final float[][] CENTERS = new float[numCubits][];
227

    
228
    for(int corner=0; corner<NUM_CORNERS; corner++)
229
      {
230
      computeBasicCornerVectors(corner);
231

    
232
      for(int part=0; part<numCubitsPerCorner; part++, index++)
233
        {
234
        CENTERS[index] = computeCorner(numCubitsPerCorner,numL,corner,part);
235
        }
236
      }
237

    
238
    for(int edge=0; edge<NUM_EDGES; edge++)
239
      {
240
      for(int part=0; part<numCubitsPerEdge; part++, index++)
241
        {
242
        CENTERS[index] = computeEdge(numL, edge, part );
243
        }
244
      }
245

    
246
    for(int center=0; center<NUM_CENTERS; center++)
247
      {
248
      for(int part=0; part<numCubitsPerCenter; part++, index++)
249
        {
250
        CENTERS[index] = computeCenter(numL,center, part);
251
        }
252
      }
253

    
254
    return CENTERS;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  public Static4D getCubitQuats(int cubit, int[] numLayers)
260
    {
261
    int numL = numLayers[0];
262
    int numCubitsPerCorner = numCubitsPerCorner(numL);
263
    int numCubitsPerEdge   = numCubitsPerEdge(numL);
264
    int q = getQuat(cubit,numCubitsPerCorner,numCubitsPerEdge);
265
    return mObjectQuats[q];
266
    }
267

    
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

    
270
  private int getQuat(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
271
    {
272
    if( mQuatCornerIndices==null || mQuatEdgeIndices==null ) initializeQuatIndices();
273
    if( mCenterMap==null ) initializeCenterMap();
274

    
275
    if( cubit < NUM_CORNERS*numCubitsPerCorner )
276
      {
277
      int corner = cubit/numCubitsPerCorner;
278
      return mQuatCornerIndices[corner];
279
      }
280

    
281
    if( cubit < NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
282
      {
283
      int edge = (cubit-NUM_CORNERS*numCubitsPerCorner)/numCubitsPerEdge;
284
      return mQuatEdgeIndices[edge];
285
      }
286

    
287
    if( numCubitsPerCorner==0 )
288
      {
289
      return mQuatCornerIndices[cubit];
290
      }
291
    else
292
      {
293
      cubit -= (NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge);
294
      int numCubitsPerCenter = 5;
295
      int face = cubit/numCubitsPerCenter;
296
      int index= cubit%numCubitsPerCenter;
297
      int center=mCenterMap[face][index];
298
      return mQuatCornerIndices[center];
299
      }
300
    }
301

    
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303

    
304
  public ObjectShape getObjectShape(int variant)
305
    {
306
    int[] numLayers = getNumLayers();
307
    int numVariants = getNumCubitVariants(numLayers);
308
    int numL        = numLayers[0];
309
    boolean small   = numL<=3;
310

    
311
    if( variant==0 && !small )
312
      {
313
      float width = numL/(numL-1.0f);
314
      float X = width*COS18*SIN_HALFD;
315
      float Y = width*SIN18;
316
      float Z = width*COS18*COS_HALFD;
317

    
318
      float[][] vertices =
319
        {
320
            {   0,   0      ,   0 },
321
            {   X,   Y      ,  -Z },
322
            {   0, 2*Y      ,-2*Z },
323
            {  -X,   Y      ,  -Z },
324
            {   0,   0-width,   0 },
325
            {   X,   Y-width,  -Z },
326
            {   0, 2*Y-width,-2*Z },
327
            {  -X,   Y-width,  -Z },
328
        };
329

    
330
      int[][] indices =
331
        {
332
            {4,5,1,0},
333
            {7,4,0,3},
334
            {0,1,2,3},
335
            {7,6,5,4},
336
            {2,1,5,6},
337
            {3,2,6,7}
338
        };
339

    
340
      return new ObjectShape(vertices, indices);
341
      }
342
    if( variant<numVariants-1 )
343
      {
344
      int type = variant-1;
345
      float tmpVal= numL/(numL-1.0f);
346
      float height= tmpVal*COS18;
347
      float width = tmpVal + (type/2)*tmpVal*SIN18;
348
      boolean left = (type%2)==0;
349

    
350
      float X = height*SIN_HALFD;
351
      float Y = height*SIN18/COS18;
352
      float Z = height*COS_HALFD;
353

    
354
      float[][] vertices =
355
        {
356
            {   0,   0   ,   0 },
357
            {   X,   Y   ,  -Z },
358
            {   0, 2*Y   ,-2*Z },
359
            {  -X,   Y   ,  -Z },
360
            {   0, -width,   0 },
361
            {   X, -width,  -Z },
362
            {   0, -width,-2*Z },
363
            {  -X, -width,  -Z },
364
        };
365

    
366
      int[][] indices =
367
        {
368
            {4,5,1,0},
369
            {7,4,0,3},
370
            {3,2,6,7},
371
            {2,1,5,6},
372
            {0,1,2,3},
373
            {7,6,5,4}
374
        };
375

    
376
      if( !left )
377
        {
378
        int tmp, len = vertices.length;
379
        for(int i=0; i<len; i++) vertices[i][1] = -vertices[i][1];
380

    
381
        len = indices.length;
382
        for(int i=0; i<len; i++)
383
          {
384
          tmp = indices[i][0];
385
          indices[i][0] = indices[i][3];
386
          indices[i][3] = tmp;
387
          tmp = indices[i][1];
388
          indices[i][1] = indices[i][2];
389
          indices[i][2] = tmp;
390
          }
391
        }
392

    
393
      return new ObjectShape(vertices, indices);
394
      }
395
    else
396
      {
397
      float width = (1+0.5f*(numL-3)*SIN18)*numL/(numL-1);
398
      float X = width*COS18*SIN_HALFD;
399
      float Y = width*SIN18;
400
      float Z = width*COS18*COS_HALFD;
401
      float H = width*(SIN54/COS54);
402
      float H3= H/COS_HALFD;
403
      float X3= H*SIN_HALFD;
404
      float Z3= H*COS_HALFD;
405
      float C = 1/(COS54*(float)Math.sqrt(2-2*SIN18));
406

    
407
      float[][] vertices =
408
        {
409
            {   0,   0  ,     0 },
410
            {   X,   Y  ,    -Z },
411
            {   0,C*2*Y ,-2*C*Z },
412
            {  -X,   Y  ,    -Z },
413
            {   0,-width,     0 },
414
            {  X3,-width,   -Z3 },
415
            {   0,-width,   -H3 },
416
            { -X3,-width,   -Z3 }
417
        };
418

    
419
      int[][] indices =
420
        {
421
            {4,5,1,0},
422
            {7,4,0,3},
423
            {0,1,2,3},
424
            {3,2,6,7},
425
            {2,1,5,6},
426
            {7,6,5,4}
427
        };
428

    
429
      return new ObjectShape(vertices, indices);
430
      }
431
    }
432

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

    
435
  public ObjectFaceShape getObjectFaceShape(int variant)
436
    {
437
    int[] numLayers = getNumLayers();
438
    int numVariants = getNumCubitVariants(numLayers);
439
    int numL        = numLayers[0];
440
    boolean small   = numL<=3;
441

    
442
    if( variant==0 && !small )
443
      {
444
      float A = (2*SQ3/3)*SIN54;
445
      float B = 0.4f;
446
      float h1 = isInIconMode() ? 0.001f : 0.04f;
447

    
448
      float[][] bands     = { {h1,34,0.3f,0.2f, 3, 0, 0}, {0.001f,34,0.0f,0.0f, 2, 0, 0} };
449
      int[] bandIndices   = { 0,0,0,1,1,1};
450
      float[][] corners   = { {0.04f,0.10f} };
451
      int[] cornerIndices = { 0,-1,-1,-1,-1,-1,-1,-1 };
452
      float[][] centers   = { {0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B} };
453
      int[] centerIndices = { 0,-1,-1,-1,-1,-1,-1,-1 };
454

    
455
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
456
      }
457
    if( variant<numVariants-1 )
458
      {
459
      int type = variant-1;
460
      float tmpVal= numL/(numL-1.0f);
461
      float height= tmpVal*COS18;
462
      float width = tmpVal + (type/2)*tmpVal*SIN18;
463
      float Z = height*COS_HALFD;
464
      int E  = small ? 1 : 0;
465
      int N0 = small ? 4 : 3;
466
      int N1 = small ? 3 : 2;
467
      float h1 = isInIconMode() ? 0.001f : 0.04f;
468

    
469
      float[][] bands     = { {h1,34,0.2f,0.2f,N0,E,E}, {0.001f,34,0.0f,0.0f,N1,0,0} };
470
      int[] bandIndices   = { 0,0,1,1,1,1};
471
      float[][] corners   = { {0.04f,0.10f} };
472
      int[] cornerIndices = { 0,-1,-1,-1, 0,-1,-1,-1 };
473
      float[][] centers   = { {0.0f, -width/2, -2*Z} };
474
      int[] centerIndices = { 0,-1,-1,-1, 0,-1,-1,-1 };
475

    
476
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
477
      }
478
    else
479
      {
480
      float A = (2*SQ3/3)*SIN54;
481
      float B = 0.4f;
482
      int N = small ? 4 : 3;
483
      int E = small ? 1 : 0;
484
      float h1 = isInIconMode() ? 0.001f : 0.04f;
485
      float h2 = isInIconMode() ? 0.001f : 0.01f;
486

    
487
      float[][] bands     = { {h1,17,0.3f,0.2f,N,E,E},{h2,17,0.3f,0.2f,N,E,E} };
488
      int[] bandIndices   = { 0,0,0,1,1,1};
489
      float[][] corners   = { {0.03f,0.10f} };
490
      int[] cornerIndices = { 0, 0,-1, 0, 0,-1,-1,-1 };
491
      float[][] centers   = { {0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B} };
492
      int[] centerIndices = { 0, 0,-1, 0, 0,-1,-1,-1 };
493

    
494
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
495
      }
496
    }
497

    
498
///////////////////////////////////////////////////////////////////////////////////////////////////
499

    
500
  public int getNumCubitVariants(int[] numLayers)
501
    {
502
    switch(numLayers[0])
503
      {
504
      case 3: return 1;
505
      case 5: return 4;
506
      }
507

    
508
    return 1;
509
    }
510

    
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512

    
513
  public int getCubitVariant(int cubit, int[] numLayers)
514
    {
515
    int numL = numLayers[0];
516
    int numCubitsPerCorner = numCubitsPerCorner(numL);
517

    
518
    if( cubit<NUM_CORNERS*numCubitsPerCorner ) return 0;
519

    
520
    int numCubitsPerEdge = numCubitsPerEdge(numL);
521

    
522
    if( cubit<NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
523
      {
524
      int type = computeEdgeType(cubit,numCubitsPerCorner,numCubitsPerEdge);
525
      return type+1;
526
      }
527

    
528
    return getNumCubitVariants(numLayers)-1;
529
    }
530

    
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532

    
533
  public float getStickerRadius()
534
    {
535
    return 0.18f;
536
    }
537

    
538
///////////////////////////////////////////////////////////////////////////////////////////////////
539

    
540
  public float getStickerStroke()
541
    {
542
    float stroke = 0.25f;
543

    
544
    if( isInIconMode() )
545
      {
546
      int[] numLayers = getNumLayers();
547
      if( numLayers[0]>3 ) stroke*=1.5f;
548
      }
549

    
550
    return stroke;
551
    }
552

    
553
///////////////////////////////////////////////////////////////////////////////////////////////////
554

    
555
  public float[][] getStickerAngles()
556
    {
557
    return null;
558
    }
559

    
560
///////////////////////////////////////////////////////////////////////////////////////////////////
561

    
562
  public String getShortName()
563
    {
564
    switch(getNumLayers()[0])
565
      {
566
      case 3: return ObjectType.KILO_3.name();
567
      case 5: return ObjectType.KILO_5.name();
568
      }
569

    
570
    return ObjectType.KILO_3.name();
571
    }
572

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

    
575
  public ObjectSignature getSignature()
576
    {
577
    switch(getNumLayers()[0])
578
      {
579
      case 3: return new ObjectSignature(ObjectType.KILO_3);
580
      case 5: return new ObjectSignature(ObjectType.KILO_5);
581
      }
582

    
583
    return null;
584
    }
585

    
586
///////////////////////////////////////////////////////////////////////////////////////////////////
587

    
588
  public String getObjectName()
589
    {
590
    switch(getNumLayers()[0])
591
      {
592
      case 3: return "Kilominx";
593
      case 5: return "Master Kilominx";
594
      }
595
    return null;
596
    }
597

    
598
///////////////////////////////////////////////////////////////////////////////////////////////////
599

    
600
  public String getInventor()
601
    {
602
    switch(getNumLayers()[0])
603
      {
604
      case 3: return "Thomas de Bruin";
605
      case 5: return "David Gugl";
606
      }
607
    return "Thomas de Bruin";
608
    }
609

    
610
///////////////////////////////////////////////////////////////////////////////////////////////////
611

    
612
  public int getYearOfInvention()
613
    {
614
    switch(getNumLayers()[0])
615
      {
616
      case 3: return 2008;
617
      case 5: return 2010;
618
      }
619
    return 2008;
620
    }
621

    
622
///////////////////////////////////////////////////////////////////////////////////////////////////
623

    
624
  public int getComplexity()
625
    {
626
    switch(getNumLayers()[0])
627
      {
628
      case 3: return 2;
629
      case 5: return 3;
630
      }
631
    return 8;
632
    }
633

    
634
///////////////////////////////////////////////////////////////////////////////////////////////////
635

    
636
  public String[][] getTutorials()
637
    {
638
    int[] numLayers = getNumLayers();
639

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