Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyPyraminx.java @ 074a0284

1 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 6133be67 Leszek Koltunski
// 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 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.objects;
11
12 c9c71c3f Leszek Koltunski
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_TETRAHEDRON;
13
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
14 29b82486 Leszek Koltunski
15
import org.distorted.library.type.Static3D;
16
import org.distorted.library.type.Static4D;
17
18 84a17011 Leszek Koltunski
import org.distorted.objectlib.helpers.FactoryCubit;
19 3ee1d662 Leszek Koltunski
import org.distorted.objectlib.helpers.ObjectFaceShape;
20 ae9d9227 leszek
import org.distorted.objectlib.metadata.Metadata;
21 84a17011 Leszek Koltunski
import org.distorted.objectlib.helpers.ObjectVertexEffects;
22 cf93ea4e Leszek Koltunski
import org.distorted.objectlib.main.InitAssets;
23 c9c71c3f Leszek Koltunski
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
24 361fd0de leszek
import org.distorted.objectlib.metadata.ListObjects;
25 198c5bf0 Leszek Koltunski
import org.distorted.objectlib.helpers.ObjectShape;
26 b31249d6 Leszek Koltunski
import org.distorted.objectlib.shape.ShapeTetrahedron;
27 29b82486 Leszek Koltunski
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29
30 386af988 Leszek Koltunski
public class TwistyPyraminx extends ShapeTetrahedron
31 29b82486 Leszek Koltunski
{
32 ccd8a6f2 Leszek Koltunski
  static final Static3D[] ROT_AXIS = new Static3D[]
33 29b82486 Leszek Koltunski
         {
34
           new Static3D(     0,-SQ3/3,-SQ6/3),
35 84a17011 Leszek Koltunski
           new Static3D(     0,-SQ3/3, SQ6/3),
36
           new Static3D( SQ6/3, SQ3/3,     0),
37
           new Static3D(-SQ6/3, SQ3/3,     0),
38 29b82486 Leszek Koltunski
         };
39
40 9ba7f3f6 Leszek Koltunski
  private int[][] mEdges;
41 beee90ab Leszek Koltunski
  private int[][] mBasicAngle;
42 29b82486 Leszek Koltunski
  private float[][] mCuts;
43
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45
46 ae9d9227 leszek
  public TwistyPyraminx(int iconMode, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
47 29b82486 Leszek Koltunski
    {
48 ae9d9227 leszek
    super(iconMode, meta.getNumLayers()[0], quat, move, scale, meta, asset);
49 29b82486 Leszek Koltunski
    }
50
51 fb1e9a31 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
52
53
  @Override
54
  public float[][] returnRotationFactor()
55
    {
56
    int numL= getNumLayers()[0];
57
    float[][] factor = new float[4][numL];
58
59
    for(int ax=0; ax<4; ax++)
60
      for(int la=0; la<numL; la++) factor[ax][la] = ((float)numL)/(numL-la);
61
62
    return factor;
63
    }
64
65 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
66 e649d99a Leszek Koltunski
// edge[i] is the state after moving layer i (0 is the largest)
67 29b82486 Leszek Koltunski
68 9ba7f3f6 Leszek Koltunski
  public int[][] getScrambleEdges()
69 29b82486 Leszek Koltunski
    {
70 9ba7f3f6 Leszek Koltunski
    if( mEdges==null )
71 29b82486 Leszek Koltunski
      {
72 e649d99a Leszek Koltunski
      int nL = getNumLayers()[0];
73
      mEdges = new int[nL][];
74
75
      for(int i=0; i<nL; i++)
76
        {
77
        int numEnabledMoves = 2*(nL-i);
78
        mEdges[i] = new int[4*2*numEnabledMoves];
79
80
        int index = 0;
81
        int startMove= 0;
82
        int offset = (i==nL-1 ? 2:0);  // if the last move was a tip, the only possible
83
                                       // next move is the second-to-largest layer.
84
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
85
        index += (2*numEnabledMoves);
86
        startMove += (2*nL);
87
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
88
        index += (2*numEnabledMoves);
89
        startMove += (2*nL);
90
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
91
        index += (2*numEnabledMoves);
92
        startMove += (2*nL);
93
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
94
        }
95 29b82486 Leszek Koltunski
      }
96
97 9ba7f3f6 Leszek Koltunski
    return mEdges;
98 29b82486 Leszek Koltunski
    }
99
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101
102 e649d99a Leszek Koltunski
  private void fillEdge(int[] edge, int index, int move, int offset, int num)
103 29b82486 Leszek Koltunski
    {
104 e649d99a Leszek Koltunski
    for(int i=0; i<num; i++)
105 29b82486 Leszek Koltunski
      {
106 e649d99a Leszek Koltunski
      edge[index+2*i  ] = (move+offset);
107
      edge[index+2*i+1] = (i+offset)/2;
108
      move++;
109 29b82486 Leszek Koltunski
      }
110
    }
111
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
114
  private void addTetrahedralLattice(int size, int index, float[][] pos)
115
    {
116
    final float DX = 1.0f;
117
    final float DY = SQ2/2;
118
    final float DZ = 1.0f;
119
120
    float startX = 0.0f;
121
    float startY =-DY*(size-1)/2;
122
    float startZ = DZ*(size-1)/2;
123
124
    for(int layer=0; layer<size; layer++)
125
      {
126
      float currX = startX;
127
      float currY = startY;
128
129
      for(int x=0; x<layer+1; x++)
130
        {
131
        float currZ = startZ;
132
133
        for(int z=0; z<size-layer; z++)
134
          {
135
          pos[index] = new float[] {currX,currY,currZ};
136
          index++;
137
          currZ -= DZ;
138
          }
139
140
        currX += DX;
141
        }
142
143
      startX-=DX/2;
144
      startY+=DY;
145
      startZ-=DZ/2;
146
      }
147
    }
148
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150
151 d0e6cf7f Leszek Koltunski
  private int getNumOctahedrons(int numLayers)
152 29b82486 Leszek Koltunski
    {
153 d0e6cf7f Leszek Koltunski
    return (numLayers-1)*numLayers*(numLayers+1)/6;
154
    }
155 29b82486 Leszek Koltunski
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157
158 7bbfc84f Leszek Koltunski
  public float[][] getCuts(int[] numLayers)
159 29b82486 Leszek Koltunski
    {
160
    if( mCuts==null )
161
      {
162 a57e6870 Leszek Koltunski
      int numL = numLayers[0];
163
      mCuts = new float[4][numL-1];
164 acf9ed9b leszek
      float cut = (SQ6/6)*(2-numL*0.5f);
165 29b82486 Leszek Koltunski
166 a57e6870 Leszek Koltunski
      for(int i=0; i<numL-1; i++)
167 29b82486 Leszek Koltunski
        {
168
        mCuts[0][i] = cut;
169
        mCuts[1][i] = cut;
170
        mCuts[2][i] = cut;
171
        mCuts[3][i] = cut;
172 acf9ed9b leszek
        cut += SQ6/3;
173 29b82486 Leszek Koltunski
        }
174
      }
175
176
    return mCuts;
177
    }
178
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180
181 59c20632 Leszek Koltunski
  public boolean[][] getLayerRotatable(int[] numLayers)
182 29b82486 Leszek Koltunski
    {
183 59c20632 Leszek Koltunski
    int numAxis = ROT_AXIS.length;
184
    boolean[][] layerRotatable = new boolean[numAxis][];
185 a57e6870 Leszek Koltunski
186 59c20632 Leszek Koltunski
    for(int i=0; i<numAxis; i++)
187
      {
188
      layerRotatable[i] = new boolean[numLayers[i]];
189
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
190 29b82486 Leszek Koltunski
      }
191 59c20632 Leszek Koltunski
192
    return layerRotatable;
193
    }
194
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196
197 11fa413d Leszek Koltunski
  public int getTouchControlType()
198 59c20632 Leszek Koltunski
    {
199 c9c71c3f Leszek Koltunski
    return TC_TETRAHEDRON;
200 59c20632 Leszek Koltunski
    }
201
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203
204 11fa413d Leszek Koltunski
  public int getTouchControlSplit()
205 59c20632 Leszek Koltunski
    {
206
    return TYPE_NOT_SPLIT;
207
    }
208
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210
211
  public int[][][] getEnabled()
212
    {
213
    return new int[][][] { {{1,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,2}} };
214
    }
215
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217
218
  public float[] getDist3D(int[] numLayers)
219
    {
220 4c9ca251 Leszek Koltunski
    return TouchControlTetrahedron.D3D;
221
    }
222
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224
225
  public Static3D[] getFaceAxis()
226
    {
227
    return TouchControlTetrahedron.FACE_AXIS;
228 29b82486 Leszek Koltunski
    }
229
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231 d0e6cf7f Leszek Koltunski
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
232 29b82486 Leszek Koltunski
233 d0e6cf7f Leszek Koltunski
  public float[][] getCubitPositions(int[] numLayers)
234 29b82486 Leszek Koltunski
    {
235 d0e6cf7f Leszek Koltunski
    int numL = numLayers[0];
236
    int numOcta = (numL-1)*numL*(numL+1)/6;
237
    int numTetra= numL*(numL+1)*(numL+2)/6;
238
    float[][] ret = new float[numOcta+numTetra][];
239
240
    addTetrahedralLattice(numL-1,      0,ret);
241
    addTetrahedralLattice(numL  ,numOcta,ret);
242
243
    return ret;
244
    }
245
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247
248
  public Static4D getCubitQuats(int cubit, int[] numLayers)
249
    {
250 802fe251 Leszek Koltunski
    return mObjectQuats[0];
251 29b82486 Leszek Koltunski
    }
252
253 84a17011 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
254
255
  private float[][] getVertices(int variant)
256
    {
257
    if( variant==0 )
258
      {
259
      return new float[][] { { 0.5f,0.0f,0.5f},{ 0.5f,0.0f,-0.5f},{-0.5f,0.0f,-0.5f},{-0.5f,0.0f,0.5f},{ 0.0f,SQ2/2,0.0f},{ 0.0f,-SQ2/2,0.0f} };
260
      }
261
    else
262
      {
263
      return new float[][] { {-0.5f, SQ2/4, 0.0f},{ 0.5f, SQ2/4, 0.0f},{ 0.0f,-SQ2/4, 0.5f},{ 0.0f,-SQ2/4,-0.5f} };
264
      }
265
    }
266
267 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
268
269 e30c522a Leszek Koltunski
  public ObjectShape getObjectShape(int variant)
270 29b82486 Leszek Koltunski
    {
271
    if( variant==0 )
272
      {
273 4e9f2df5 Leszek Koltunski
      int[][] indices   = { {3,0,4},{0,1,4},{1,2,4},{2,3,4},{5,0,3},{5,1,0},{5,2,1},{5,3,2} };
274 84a17011 Leszek Koltunski
      return new ObjectShape(getVertices(variant), indices);
275 29b82486 Leszek Koltunski
      }
276
    else
277
      {
278 4e9f2df5 Leszek Koltunski
      int[][] indices   = { {2,1,0},{3,0,1},{3,2,0},{2,3,1} };
279 84a17011 Leszek Koltunski
      return new ObjectShape(getVertices(variant), indices);
280 3ee1d662 Leszek Koltunski
      }
281
    }
282
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284
285
  public ObjectFaceShape getObjectFaceShape(int variant)
286
    {
287
    int numL = getNumLayers()[0];
288 3bf19410 Leszek Koltunski
    float height = isInIconMode() ? 0.001f : 0.05f;
289 347f6cc1 Leszek Koltunski
    int angle = 25;
290
    float R = 0.7f;
291
    float S = 0.5f;
292 3ee1d662 Leszek Koltunski
293
    if( variant==0 )
294
      {
295
      int N = numL==3? 6 : 5;
296
      int E = numL==3? 2 : 1;
297 347f6cc1 Leszek Koltunski
      float[][] bands = { {height,angle,R,S,N,E,E} };
298 84a17011 Leszek Koltunski
      int[] indices   = { 0,0,0,0,0,0,0,0 };
299
      return new ObjectFaceShape(bands,indices,null);
300 3ee1d662 Leszek Koltunski
      }
301
    else
302
      {
303 a57e6870 Leszek Koltunski
      int N = numL==3? 6 : 5;
304
      int E = numL==3? 2 : 1;
305 347f6cc1 Leszek Koltunski
      float[][] bands = { {height,angle,R,S,N,E,E} };
306 84a17011 Leszek Koltunski
      int[] indices   = { 0,0,0,0 };
307
      return new ObjectFaceShape(bands,indices,null);
308
      }
309
    }
310
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312
313
  public ObjectVertexEffects getVertexEffects(int variant)
314
    {
315
    if( variant==0 )
316
      {
317
      float[][] corners = { {0.04f,0.20f} };
318
      int[] indices     = { 0,0,0,0,0,0 };
319
      float[][] centers = { {0.0f, 0.0f, 0.0f} };
320
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
321
      }
322
    else
323
      {
324
      float[][] corners = { {0.06f,0.15f} };
325
      int[] indices     = { 0,0,0,0 };
326
      float[][] centers = { {0.0f, 0.0f, 0.0f} };
327
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
328 29b82486 Leszek Koltunski
      }
329
    }
330
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332
333 e30c522a Leszek Koltunski
  public int getNumCubitVariants(int[] numLayers)
334 29b82486 Leszek Koltunski
    {
335
    return 2;
336
    }
337
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
340 e30c522a Leszek Koltunski
  public int getCubitVariant(int cubit, int[] numLayers)
341 29b82486 Leszek Koltunski
    {
342 a57e6870 Leszek Koltunski
    return cubit<getNumOctahedrons(numLayers[0]) ? 0:1;
343 29b82486 Leszek Koltunski
    }
344
345 053ffa02 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
346
347 d53fb890 Leszek Koltunski
  public float getStickerRadius()
348 053ffa02 Leszek Koltunski
    {
349 00f4980d Leszek Koltunski
    return 0.08f;
350 053ffa02 Leszek Koltunski
    }
351
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353
354 d53fb890 Leszek Koltunski
  public float getStickerStroke()
355 053ffa02 Leszek Koltunski
    {
356
    float stroke = 0.08f;
357
358 3bf19410 Leszek Koltunski
    if( isInIconMode() )
359 053ffa02 Leszek Koltunski
      {
360
      int[] numLayers = getNumLayers();
361
362
      switch(numLayers[0])
363
        {
364
        case 2: stroke*=1.0f; break;
365
        case 3: stroke*=1.4f; break;
366
        case 4: stroke*=1.7f; break;
367
        default:stroke*=1.9f; break;
368 8592461c Leszek Koltunski
        }
369 053ffa02 Leszek Koltunski
      }
370 8592461c Leszek Koltunski
371 053ffa02 Leszek Koltunski
    return stroke;
372
    }
373
374 00f4980d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
375
376 ebe8c08e leszek
  public float[][][] getStickerAngles()
377 00f4980d Leszek Koltunski
    {
378
    return null;
379
    }
380
381 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
382
// public API
383
384
  public Static3D[] getRotationAxis()
385
    {
386
    return ROT_AXIS;
387
    }
388
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390
391 beee90ab Leszek Koltunski
  public int[][] getBasicAngles()
392 29b82486 Leszek Koltunski
    {
393 beee90ab Leszek Koltunski
    if( mBasicAngle ==null )
394
      {
395
      int num = getNumLayers()[0];
396
      int[] tmp = new int[num];
397
      for(int i=0; i<num; i++) tmp[i] = 3;
398
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
399
      }
400
401 29b82486 Leszek Koltunski
    return mBasicAngle;
402
    }
403
404 61aa85e4 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
405
406 5f54927b Leszek Koltunski
  public String getShortName()
407 61aa85e4 Leszek Koltunski
    {
408 5f54927b Leszek Koltunski
    switch(getNumLayers()[0])
409
      {
410 361fd0de leszek
      case 3: return ListObjects.PYRA_3.name();
411
      case 4: return ListObjects.PYRA_4.name();
412
      case 5: return ListObjects.PYRA_5.name();
413
      case 6: return ListObjects.PYRA_6.name();
414 5f54927b Leszek Koltunski
      }
415
416 361fd0de leszek
    return ListObjects.PYRA_3.name();
417 5f54927b Leszek Koltunski
    }
418
419 052e0362 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
420
421
  public String[][] getTutorials()
422
    {
423
    int[] numLayers = getNumLayers();
424
425
    switch(numLayers[0])
426
      {
427
      case 3: return new String[][] {
428
                          {"gb","xIQtn2qazvg","Pyraminx Layer By Layer","Z3"},
429
                          {"es","4cJJe9RAzAU","Resolver Pyraminx","Cuby"},
430
                          {"ru","F4_bhfWyVRQ","Как собрать ПИРАМИДКУ","Е Бондаренко"},
431
                          {"fr","Z2h1YI6jPes","Comment résoudre le Pyraminx","ValentinoCube"},
432
                          {"de","x_DMA8htJpY","Pyraminx lösen","Pezcraft"},
433
                          {"pl","uNpKpJfAa5I","Jak ułożyć: Pyraminx","DżoDżo"},
434
                          {"br","dtC0GNGyXqw","Como resolver o Pyraminx","Pedro Filho"},
435
                          {"kr","mO3excjvvoA","피라밍크스 맞추는 방법","iamzoone"},
436 a399e91b Leszek Koltunski
                          {"vn","p9LUWUW5iYg","Tutorial N.4 - Pyraminx","Duy Thích Rubik"},
437 2318a72a leszek
                          {"tw","wZu3OAuNY5Q","金字塔方塊 教學","不正常魔術方塊研究中心"},
438 052e0362 Leszek Koltunski
                         };
439
      case 4: return new String[][] {
440
                          {"gb","tGQDqDcSa6U","How to Solve the Master Pyraminx","Z3"},
441
                          {"es","74PIPm9-uPg","Resolver Master Pyraminx 4x4","Cuby"},
442
                          {"ru","-F_xJAwkobU","Как собрать Мастер Пираминкс"," Алексей Ярыгин"},
443
                          {"fr","F3gzBs7uvmw","Tuto: résoudre le Master Pyraminx","Spaghetti Cubing"},
444
                          {"de","3Q_bO7_FfAI","Master Pyraminx lösen","CubaroCubing"},
445
                          {"pl","EamwvhmHC7Q","4x4 (Master) Pyraminx PL","MrUk"},
446
                          {"br","cKql6YZ7yAg","Como resolver o Pyraminx 4x4 1/3","Rafael Cinoto"},
447
                          {"br","gtNQDPsN2Dg","Como resolver o Pyraminx 4x4 2/3","Rafael Cinoto"},
448
                          {"br","j8_-s4rd8mw","Como resolver o Pyraminx 4x4 3/3","Rafael Cinoto"},
449
                          {"kr","JlmBKaHESyY","마스터 피라밍크스 해법","주누후누"},
450 a399e91b Leszek Koltunski
                          {"vn","AMCll82WcJY","Tutorial N.13 - Master Pyraminx","Duy Thích Rubik"},
451 2318a72a leszek
                          {"tw","Tghr4ow9Ckk","四階金字塔 教學","不正常魔術方塊研究中心"},
452 052e0362 Leszek Koltunski
                         };
453
      case 5: return new String[][] {
454
                          {"gb","2nsPEECDdN0","Professor Pyraminx Solve","RedKB"},
455
                          {"es","cSDj8OQK3TU","Tutorial del Professor Pyraminx","QBAndo"},
456
                          {"ru","gMp1tbDyDWg","Как собрать Professor Pyraminx","RBcuber"},
457
                          {"de","pCHx9bVMSgI","Professor Pyraminx Teil 1","Arvid Bollmann"},
458
                          {"de","iiNXJMVNmCM","Professor Pyraminx Teil 2","Arvid Bollmann"},
459
                          {"br","t2QJSSjNxPw","Resolver o Professor Pyraminx 1/4","Rafael Cinoto"},
460
                          {"br","mI6W6IFyVv0","Resolver o Professor Pyraminx 2/4","Rafael Cinoto"},
461
                          {"br","0HoOp6JlLSs","Resolver o Professor Pyraminx 3/4","Rafael Cinoto"},
462
                          {"br","Xg1jnCRsw_I","Resolver o Professor Pyraminx 4/4","Rafael Cinoto"},
463 a399e91b Leszek Koltunski
                          {"vn","OHwPqp3kQdE","Professor Pyraminx làm chậm","TRẦN QUANG HÙNG"},
464 2318a72a leszek
                          {"tw","X3NxqT8bt8s","五階金字塔 教學","不正常魔術方塊研究中心"},
465
                         };
466
      case 6: return new String[][] {
467
                          {"gb","1u6FPbkp0-c","Royal Pyraminx: a Tutorial","Superantoniovivaldi"},
468
                          {"es","7px2uG7zhVk","Royal Pyraminx Tutorial","Gadi Rubik"},
469
                          {"tw","hbK2L28hEvM","六階金字塔 教學","不正常魔術方塊研究中心"},
470 052e0362 Leszek Koltunski
                         };
471
      }
472
    return null;
473
    }
474 29b82486 Leszek Koltunski
}