Project

General

Profile

« Previous | Next » 

Revision ed6b7481

Added by Leszek Koltunski 7 months ago

First tries at Bump Jing and Bump Pyraminx ( both crash on startup now)

View differences:

src/main/java/org/distorted/objectlib/objects/TwistyMirrorPyraminx.java
15 15
import org.distorted.library.type.Static3D;
16 16
import org.distorted.library.type.Static4D;
17 17
import org.distorted.objectlib.helpers.FactoryCubit;
18
import org.distorted.objectlib.helpers.FactoryShape;
18 19
import org.distorted.objectlib.helpers.ObjectFaceShape;
19 20
import org.distorted.objectlib.helpers.ObjectShape;
20 21
import org.distorted.objectlib.helpers.ObjectVertexEffects;
21 22
import org.distorted.objectlib.main.InitAssets;
22 23
import org.distorted.objectlib.main.InitData;
23 24
import org.distorted.objectlib.main.ObjectType;
24
import org.distorted.objectlib.scrambling.ScrambleEdgeGenerator;
25
import org.distorted.objectlib.shape.ShapeHexahedron;
25
import org.distorted.objectlib.shape.ShapeTetrahedron;
26 26
import org.distorted.objectlib.signature.ObjectConstants;
27 27
import org.distorted.objectlib.signature.ObjectSignature;
28
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
28
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
29 29

  
30 30
///////////////////////////////////////////////////////////////////////////////////////////////////
31 31

  
32
public class TwistyMirrorPyraminx extends ShapeHexahedron
32
public class TwistyMirrorPyraminx extends ShapeTetrahedron
33 33
{
34
  public static final Static3D[] ROT_AXIS =
35
         {
36
           new Static3D( SQ3/3, SQ3/3, SQ3/3),
37
           new Static3D( SQ3/3, SQ3/3,-SQ3/3),
38
           new Static3D( SQ3/3,-SQ3/3, SQ3/3),
39
           new Static3D( SQ3/3,-SQ3/3,-SQ3/3)
40
         };
34
  static final Static3D[] ROT_AXIS = new Static3D[]
35
    {
36
      new Static3D(     0,-SQ3/3,-SQ6/3),
37
      new Static3D(     0,-SQ3/3, SQ6/3),
38
      new Static3D( SQ6/3, SQ3/3,     0),
39
      new Static3D(-SQ6/3, SQ3/3,     0),
40
    };
41 41

  
42 42
  private static final int[] FACE_COLORS = new int[] { COLOR_WHITE };
43
  private static final float[] MIRROR_VEC = { 0.10f, 0.25f, 0.40f };
43
  private static final float[] MIRROR_VEC = { 0.0f, 0.0f, 0.0f };
44 44

  
45 45
  private int[][] mEdges;
46 46
  private int[][] mBasicAngle;
47 47
  private float[][] mCuts;
48 48
  private float[][] mPositions;
49
  private ObjectShape[] mShapes;
50
  private float[][] mCutPlanes;
51
  private float[] mDist3D, mDist;
52
  private float[][] mPotentialVertices;
49 53

  
50 54
///////////////////////////////////////////////////////////////////////////////////////////////////
51 55

  
52 56
  public TwistyMirrorPyraminx(int iconMode, Static4D quat, Static3D move, float scale, InitData data, InitAssets asset)
53 57
    {
54
    super(iconMode, 2*data.getNumLayers()[0]-2, quat, move, scale, data, asset);
58
    super(iconMode, data.getNumLayers()[0], quat, move, scale, data, asset);
55 59
    }
56 60

  
57 61
///////////////////////////////////////////////////////////////////////////////////////////////////
......
59 63
  @Override
60 64
  public int getInternalColor()
61 65
    {
62
    return 0xff222222;
66
    return 0xff333333;
63 67
    }
64 68

  
65 69
///////////////////////////////////////////////////////////////////////////////////////////////////
......
83 87
  @Override
84 88
  public float[][] returnRotationFactor()
85 89
    {
86
    int numL = getNumLayers()[0];
87
    float[] f = new float[numL];
88
    for(int i=0; i<numL; i++) f[i] = 1.7f;
89
    return new float[][] { f,f,f,f };
90
    int numL= getNumLayers()[0];
91
    float[][] factor = new float[4][numL];
92

  
93
    for(int ax=0; ax<4; ax++)
94
      for(int la=0; la<numL; la++) factor[ax][la] = ((float)numL)/(numL-la);
95

  
96
    return factor;
90 97
    }
91 98

  
92 99
///////////////////////////////////////////////////////////////////////////////////////////////////
93 100

  
94 101
  public int[][] getScrambleEdges()
95 102
    {
96
    if( mEdges==null ) mEdges = ScrambleEdgeGenerator.getScrambleEdgesSingle(mBasicAngle);
103
    if( mEdges==null )
104
      {
105
      int nL = getNumLayers()[0];
106
      mEdges = new int[nL][];
107

  
108
      for(int i=0; i<nL; i++)
109
        {
110
        int numEnabledMoves = 2*(nL-i);
111
        mEdges[i] = new int[4*2*numEnabledMoves];
112

  
113
        int index = 0;
114
        int startMove= 0;
115
        int offset = (i==nL-1 ? 2:0);  // if the last move was a tip, the only possible
116
                                       // next move is the second-to-largest layer.
117
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
118
        index += (2*numEnabledMoves);
119
        startMove += (2*nL);
120
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
121
        index += (2*numEnabledMoves);
122
        startMove += (2*nL);
123
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
124
        index += (2*numEnabledMoves);
125
        startMove += (2*nL);
126
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
127
        }
128
      }
129

  
97 130
    return mEdges;
98 131
    }
99 132

  
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134

  
135
  private void fillEdge(int[] edge, int index, int move, int offset, int num)
136
    {
137
    for(int i=0; i<num; i++)
138
      {
139
      edge[index+2*i  ] = (move+offset);
140
      edge[index+2*i+1] = (i+offset)/2;
141
      move++;
142
      }
143
    }
144

  
100 145
///////////////////////////////////////////////////////////////////////////////////////////////////
101 146

  
102 147
  public float[][] getCuts(int[] numLayers)
103 148
    {
104 149
    if( mCuts==null )
105 150
      {
106
      int numAxis = ROT_AXIS.length;
107
      final float CUT = SQ3/6;
108
      mCuts = new float[numAxis][];
109

  
110
      for(int a=0; a<numAxis; a++)
111
        {
112
        Static3D ax = ROT_AXIS[a];
113
        float move = MIRROR_VEC[0]*ax.get0() + MIRROR_VEC[1]*ax.get1() + MIRROR_VEC[2]*ax.get2();
114
        mCuts[a] = new float[] {-CUT+move,CUT+move};
115
        }
151
      float[] c = { SQ6/12, 5*SQ6/12 };  // ??
152
      mCuts = new float[][] {c,c,c,c};
116 153
      }
117 154

  
118 155
    return mCuts;
......
122 159

  
123 160
  public boolean[][] getLayerRotatable(int[] numLayers)
124 161
    {
125
    boolean[] tmp = new boolean[] {true,true};
162
    boolean[] tmp = {true,true,true};
126 163
    return new boolean[][] { tmp,tmp,tmp,tmp };
127 164
    }
128 165

  
......
148 185
    }
149 186

  
150 187
///////////////////////////////////////////////////////////////////////////////////////////////////
188
// 'full' dists (not divided by numLayers)
189

  
190
  private float[] getDist()
191
    {
192
    if( mDist==null )
193
      {
194
      float DX = MIRROR_VEC[0];
195
      float DY = MIRROR_VEC[1];
196
      float DZ = MIRROR_VEC[2];
197
      Static3D[] axis = getFaceAxis();
198
      mDist = new float[4];
199

  
200
      for( int a=0; a<4; a++ )
201
        {
202
        Static3D ax = axis[a];
203
        float d = ax.get0()*DX + ax.get1()*DY + ax.get2()*DZ;
204
        mDist[a] = SQ6/6 + d;
205
        }
206
      }
207

  
208
    return mDist;
209
    }
210

  
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212
// 'regular' dists for the touchControl (have to be divided by numLayers)
151 213

  
152 214
  public float[] getDist3D(int[] numLayers)
153 215
    {
154
    int N = numLayers[0];
155
    float DX = MIRROR_VEC[0]/N;
156
    float DY = MIRROR_VEC[1]/N;
157
    float DZ = MIRROR_VEC[2]/N;
158
    return new float[] { 0.5f+DX, 0.5f-DX, 0.5f-DY, 0.5f+DY, 0.5f-DZ, 0.5f+DZ };
216
    if( mDist3D==null )
217
      {
218
      float[] d = getDist();
219
      mDist3D = new float[] { d[0]/3, d[1]/3, d[2]/3, d[3]/3 };
220
      }
221

  
222
    return mDist3D;
159 223
    }
160 224

  
161 225
///////////////////////////////////////////////////////////////////////////////////////////////////
162 226

  
163 227
  public Static3D[] getFaceAxis()
164 228
    {
165
    return TouchControlHexahedron.FACE_AXIS;
229
    return TouchControlTetrahedron.FACE_AXIS;
166 230
    }
167 231

  
168 232
///////////////////////////////////////////////////////////////////////////////////////////////////
169 233

  
170
  public float[][] getCubitPositions(int[] numLayers)
234
  private void addTetrahedralLattice(int size, int index, float[][] pos)
235
    {
236
    final float DX = 1.0f;
237
    final float DY = SQ2/2;
238
    final float DZ = 1.0f;
239

  
240
    float startX = 0.0f;
241
    float startY =-DY*(size-1)/2;
242
    float startZ = DZ*(size-1)/2;
243

  
244
    for(int layer=0; layer<size; layer++)
245
      {
246
      float currX = startX;
247
      float currY = startY;
248

  
249
      for(int x=0; x<layer+1; x++)
250
        {
251
        float currZ = startZ;
252

  
253
        for(int z=0; z<size-layer; z++)
254
          {
255
          pos[index] = new float[] {currX,currY,currZ};
256
          index++;
257
          currZ -= DZ;
258
          }
259

  
260
        currX += DX;
261
        }
262

  
263
      startX-=DX/2;
264
      startY+=DY;
265
      startZ-=DZ/2;
266
      }
267
    }
268

  
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270

  
271
  private float[][] getPositions()
171 272
    {
172 273
    if( mPositions==null )
173 274
      {
174
      final float DIST_CORNER = 1;
175
      final float DIST_CENTER = 1;
176

  
177
      mPositions = new float[8+6][];
178

  
179
      /// CORNERS //////////////////////////////////////////////
180

  
181
      mPositions[0] = new float[]{ DIST_CORNER,  DIST_CORNER,  DIST_CORNER};
182
      mPositions[1] = new float[]{ DIST_CORNER,  DIST_CORNER, -DIST_CORNER};
183
      mPositions[2] = new float[]{ DIST_CORNER, -DIST_CORNER,  DIST_CORNER};
184
      mPositions[3] = new float[]{ DIST_CORNER, -DIST_CORNER, -DIST_CORNER};
185
      mPositions[4] = new float[]{-DIST_CORNER,  DIST_CORNER,  DIST_CORNER};
186
      mPositions[5] = new float[]{-DIST_CORNER,  DIST_CORNER, -DIST_CORNER};
187
      mPositions[6] = new float[]{-DIST_CORNER, -DIST_CORNER,  DIST_CORNER};
188
      mPositions[7] = new float[]{-DIST_CORNER, -DIST_CORNER, -DIST_CORNER};
189

  
190
      /// CENTERS //////////////////////////////////////////////
191

  
192
      final float X = 0.0f;
193
      final float Y = 0.0f;
194
      final float Z = 0.0f;
195

  
196
      mPositions[ 8] = new float[]{ X, Y, DIST_CENTER };
197
      mPositions[ 9] = new float[]{ X, Y,-DIST_CENTER };
198
      mPositions[10] = new float[]{ X, DIST_CENTER, Z };
199
      mPositions[11] = new float[]{ X,-DIST_CENTER, Z };
200
      mPositions[12] = new float[]{ DIST_CENTER, Y, Z };
201
      mPositions[13] = new float[]{-DIST_CENTER, Y, Z };
275
      final float X = MIRROR_VEC[0];
276
      final float Y = MIRROR_VEC[1];
277
      final float Z = MIRROR_VEC[2];
278

  
279
      mPositions = new float[14][];
280

  
281
      addTetrahedralLattice(3, 0,mPositions);
282
      addTetrahedralLattice(2,10,mPositions);
283

  
284
      for( float[] pos : mPositions )
285
        {
286
        pos[0] += X;
287
        pos[1] += Y;
288
        pos[2] += Z;
289
        }
202 290
      }
203 291

  
204 292
    return mPositions;
205 293
    }
206 294

  
295

  
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

  
298
  public float[][] getCubitPositions(int[] numLayers)
299
    {
300
    return getPositions();
301
    }
302

  
207 303
///////////////////////////////////////////////////////////////////////////////////////////////////
208 304

  
209 305
  public Static4D getCubitQuats(int cubit, int[] numLayers)
......
212 308
    }
213 309

  
214 310
///////////////////////////////////////////////////////////////////////////////////////////////////
215
// TODO
216 311

  
217
  private float[][] getVertices(int variant)
312
  private void createCutPlanes()
218 313
    {
219
    return null;
314
    int numPlanes = 3*4;
315
    mCutPlanes = new float[numPlanes][];
316
    Static3D[] faceAxis = getFaceAxis();
317
    float[] dist = getDist();
318
    int[] numLayers = getNumLayers();
319
    float[][] cuts = getCuts(numLayers);
320
    float cut0 = cuts[0][0];
321
    float cut1 = cuts[0][1];
322

  
323
    for(int p=0; p<4; p++)
324
      {
325
      Static3D ax = faceAxis[p];
326
      mCutPlanes[p] = new float[] { ax.get0(), ax.get1(), ax.get2(), dist[p] };
327
      }
328

  
329
    for(int p=4; p<8; p++)
330
      {
331
      Static3D ax = ROT_AXIS[p-4];
332
      mCutPlanes[p] = new float[] { ax.get0(), ax.get1(), ax.get2(), cut0 };
333
      }
334
    for(int p=8; p<12; p++)
335
      {
336
      Static3D ax = ROT_AXIS[p-8];
337
      mCutPlanes[p] = new float[] { ax.get0(), ax.get1(), ax.get2(), cut1 };
338
      }
339
    }
340

  
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

  
343
  private float[] internalPoint(int variant)
344
    {
345
    float[][] pos = getPositions();
346
    float[] position = pos[variant];
347
    float[][] center = computeVertexEffectCenter(variant);
348
    float[] cent = center[0];
349

  
350
    float[] ret = new float[3];
351

  
352
    float A = 0.05f;
353

  
354
    ret[0] = position[0] + A*cent[0];
355
    ret[1] = position[1] + A*cent[1];
356
    ret[2] = position[2] + A*cent[2];
357

  
358
    return ret;
220 359
    }
221 360

  
222 361
///////////////////////////////////////////////////////////////////////////////////////////////////
223
// TODO
224 362

  
225 363
  public ObjectShape getObjectShape(int variant)
226 364
    {
227
    return null;
365
    if( mShapes==null )
366
      {
367
      int[] numLayers = getNumLayers();
368
      int numV = getNumCubitVariants(numLayers);
369
      mShapes = new ObjectShape[numV];
370
      createCutPlanes();
371
      mPotentialVertices = FactoryShape.computePotentialVertices(mCutPlanes);
372
      }
373

  
374
    if( mShapes[variant]==null )
375
      {
376
      float[][] pos = getPositions();
377
      float[] point = internalPoint(variant);
378
      mShapes[variant] = FactoryShape.createShape(mCutPlanes,mPotentialVertices,pos[variant],point);
379
      }
380

  
381
    return mShapes[variant];
228 382
    }
229 383

  
230 384
///////////////////////////////////////////////////////////////////////////////////////////////////
231 385

  
232 386
  public ObjectFaceShape getObjectFaceShape(int variant)
233 387
    {
234
    if( variant<8 )
388
    ObjectShape shape = getObjectShape(variant);
389
    int[][] ind    = shape.getVertIndices();
390
    float[][] vert = shape.getVertices();
391
    float[][] pos  = getPositions();
392
    int[] indices  = FactoryShape.produceBandIndices(vert, pos[variant], ind, getFaceAxis(), getDist() );
393

  
394
    if( variant<10 )
235 395
      {
236
      int N = 6;
237
      int E1= 3;
238
      int E2= 1;
239
      float height = isInIconMode() ? 0.001f : 0.02f;
240
      float[][] bands = { {height,35,0.16f,0.7f,N,E1,E1}, {0.001f, 35,1.00f,0.0f,3,1,E2} };
241
      int[] indices   = { 0,0,0,1,1,1 };
396
      int N = 5;
397
      int E = 1;
398
      float height = isInIconMode() ? 0.001f : 0.04f;
399
      float[][] bands = { {height,35,0.3f,0.5f,N,E,E}, {0.001f,35,0.3f,0.5f,N,E,E} };
242 400
      return new ObjectFaceShape(bands,indices,null);
243 401
      }
244 402
    else
245 403
      {
246
      int N = 6;
247
      int E = 2;
248
      float height = isInIconMode() ? 0.001f : 0.04f;
249
      float[][] bands = { {height,35,SQ2/8,0.9f,N,E,E}, {0.001f,35,1,0.0f,3,0,0} };
250
      int[] indices   = { 0,1,1,1,1 };
404
      int N = 5;
405
      int E = 1;
406
      float height = isInIconMode() ? 0.001f : 0.05f;
407
      float[][] bands = { {height,35,0.3f,0.5f,N,E,E}, {0.001f,35,0.3f,0.5f,3,0,0} };
251 408
      return new ObjectFaceShape(bands,indices,null);
252 409
      }
253 410
    }
254 411

  
255 412
///////////////////////////////////////////////////////////////////////////////////////////////////
256
// TODO: centers, number of vertices
413

  
414
  private float[][] computeVertexEffectCenter(int variant)
415
    {
416
    float A = variant<4 ? 0.5f : 1.0f;
417

  
418
    float[][] positions = getPositions();
419
    float[] p = positions[variant];
420

  
421
    return new float[][] {{ A*p[0], A*p[1], A*p[2] }};
422
    }
423

  
424
///////////////////////////////////////////////////////////////////////////////////////////////////
257 425

  
258 426
  public ObjectVertexEffects getVertexEffects(int variant)
259 427
    {
260
    if( variant<8 )
261
      {
262
      float[][] corners   = { {0.05f,0.25f}, {0.05f,0.20f} };
263
      int[] cornerIndices = { 1,1,1,0,0 };
264
      float[][] centers   = { {-0.5f, -0.5f, -0.5f} };
265
      int[] centerIndices = { 0,0,0,-1,0 };
266
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,cornerIndices,centers,centerIndices);
267
      }
268
    else
269
      {
270
      float[][] corners   = { {0.06f,0.15f} };
271
      int[] cornerIndices = { 0,0,0,0,0 };
272
      float[][] centers   = { {0,0,-0.4f} };
273
      int[] centerIndices = { 0,0,0,0,-1 };
274
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,cornerIndices,centers,centerIndices);
275
      }
428
    ObjectShape shape  = getObjectShape(variant);
429
    float[][] vertices = shape.getVertices();
430
    float[][] centers  = computeVertexEffectCenter(variant);
431
    float[][] pos      = getPositions();
432
    int[] indices      = FactoryShape.computeVertexEffectsIndices(vertices, pos[variant], getFaceAxis(), getDist() );
433
    float[][] corners  = variant<10 ? new float[][]{{0.03f, 0.20f}} : new float[][]{{0.03f, 0.15f}};
434

  
435
    return FactoryCubit.generateVertexEffect(vertices,corners,indices,centers,indices);
276 436
    }
277 437

  
278 438
///////////////////////////////////////////////////////////////////////////////////////////////////
......
300 460

  
301 461
  public float getStickerStroke()
302 462
    {
303
    return isInIconMode() ? 0.16f : 0.08f;
463
    return isInIconMode() ? 0.12f : 0.08f;
304 464
    }
305 465

  
306 466
///////////////////////////////////////////////////////////////////////////////////////////////////
......
337 497

  
338 498
  public String getShortName()
339 499
    {
340
    switch(getNumLayers()[0])
341
      {
342
      case 2: return ObjectType.SKEW_2.name();
343
      case 3: return ObjectType.SKEW_3.name();
344
      }
345

  
346
    return ObjectType.SKEW_2.name();
500
    return ObjectType.MPYR_3.name();
347 501
    }
348 502

  
349 503
///////////////////////////////////////////////////////////////////////////////////////////////////
350 504

  
351 505
  public ObjectSignature getSignature()
352 506
    {
353
    switch(getNumLayers()[0])
354
      {
355
      case 2: return new ObjectSignature(ObjectConstants.SKEW_2);
356
      case 3: return new ObjectSignature(ObjectConstants.SKEW_3);
357
      }
358

  
359
    return null;
507
    return new ObjectSignature(ObjectConstants.MPYR_3);
360 508
    }
361 509

  
362 510
///////////////////////////////////////////////////////////////////////////////////////////////////
363 511

  
364 512
  public String getObjectName()
365 513
    {
366
    switch(getNumLayers()[0])
367
      {
368
      case 2: return "Skewb";
369
      case 3: return "Master Skewb";
370
      }
371
    return null;
514
    return "Bump Pyraminx";
372 515
    }
373 516

  
374 517
///////////////////////////////////////////////////////////////////////////////////////////////////
375 518

  
376 519
  public String getInventor()
377 520
    {
378
    switch(getNumLayers()[0])
379
      {
380
      case 2: return "Tony Durham";
381
      case 3: return "Katsuhiko Okamoto";
382
      }
383
    return null;
521
    return "Ryan Allsop";
384 522
    }
385 523

  
386 524
///////////////////////////////////////////////////////////////////////////////////////////////////
387 525

  
388 526
  public int getYearOfInvention()
389 527
    {
390
    switch(getNumLayers()[0])
391
      {
392
      case 2: return 1982;
393
      case 3: return 2003;
394
      }
395
    return 1982;
528
    return 2012;
396 529
    }
397 530

  
398 531
///////////////////////////////////////////////////////////////////////////////////////////////////
399 532

  
400 533
  public int getComplexity()
401 534
    {
402
    switch(getNumLayers()[0])
403
      {
404
      case 2: return 1;
405
      case 3: return 3;
406
      }
407
    return 5;
535
    return 1;
408 536
    }
409 537

  
410 538
///////////////////////////////////////////////////////////////////////////////////////////////////
411 539

  
412 540
  public String[][] getTutorials()
413 541
    {
414
    int[] numLayers = getNumLayers();
415

  
416
    switch(numLayers[0])
417
      {
418
      case 2: return new String[][] {
419
                          {"gb","I6132yshkeU","How to Solve the Skewb","Z3"},
420
                          {"es","wxQX3HhPgds","Resolver Skewb (Principiantes)","Cuby"},
421
                          {"ru","EICw3aqn6Bc","Как собрать Скьюб?","Алексей Ярыгин"},
422
                          {"fr","lR-GuIroh4k","Comment réussir le skewb","Rachma Nikov"},
423
                          {"de","7RX6D5pznOk","Skewb lösen","Pezcraft"},
424
                          {"pl","ofRu1fByNpk","Jak ułożyć: Skewb","DżoDżo"},
425
                          {"br","mNycauwshWs","Como resolver o Skewb","Pedro Filho"},
426
                          {"kr","5R3sU-_bMAI","SKEWB 초보 공식","iamzoone"},
427
                          {"vn","Db5mXuqgQP8","Tutorial N.5 - Skewb","Duy Thích Rubik"},
428
                          {"tw","XtZL9WFMkA8","斜轉魔方教學","不正常魔術方塊研究中心"},
429
                         };
430
      case 3: return new String[][] {
431
                          {"gb","Jiuf7zQyPYI","Master Skewb Cube Tutorial","Bearded Cubing"},
432
                          {"es","8TP6p63KQCA","Master Skewb en Español","jorlozCubes"},
433
                          {"ru","7155QSp3T74","часть 1: Как собрать мастер Скьюб","Иван Циков"},
434
                          {"ru","14ey-RihjgY","часть 2: Как собрать мастер Скьюб","Иван Циков"},
435
                          {"ru","watq6TLa5_E","часть 2.5: Как собрать мастер Скьюб","Иван Циков"},
436
                          {"ru","UnsvseFBXmo","часть 3: Как собрать мастер Скьюб","Иван Циков"},
437
                          {"fr","tYMoY4EOHVA","Résolution du Master Skewb","Asthalis"},
438
                          {"de","LSErzqGNElI","Master Skewb lösen","JamesKnopf"},
439
                          {"pl","Y7l3AYFvDJI","Master Skewb TUTORIAL PL","MrUk"},
440
                          {"kr","ycR-WmXJCG0","마스터 스큐브 3번째 해법","듀나메스 큐브 해법연구소"},
441
                          {"vn","uG8H0ZQTZgw","Tutorial N.35 - Master Skewb","Duy Thích Rubik"},
442
                          {"tw","PAPa069Y92M","大師斜轉方塊 教學","不正常魔術方塊研究中心"},
443
                         };
444
      }
445 542
    return null;
446 543
    }
447 544
}

Also available in: Unified diff