Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / json / JsonWriter.java @ b2e19fa7

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
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.json;
11

    
12
import java.io.BufferedWriter;
13
import java.io.FileOutputStream;
14
import java.io.IOException;
15
import java.io.OutputStreamWriter;
16
import java.nio.charset.StandardCharsets;
17

    
18
import org.distorted.objectlib.helpers.ObjectFaceShape;
19
import org.distorted.objectlib.helpers.ObjectStickerOverride;
20
import org.distorted.objectlib.helpers.ObjectVertexEffects;
21
import org.json.JSONArray;
22
import org.json.JSONException;
23
import org.json.JSONObject;
24

    
25
import org.distorted.library.type.Static3D;
26
import org.distorted.library.type.Static4D;
27

    
28
import org.distorted.objectlib.helpers.ObjectShape;
29
import org.distorted.objectlib.helpers.ObjectSticker;
30
import org.distorted.objectlib.main.TwistyObject;
31

    
32
///////////////////////////////////////////////////////////////////////////////////////////////////
33

    
34
public class JsonWriter
35
{
36
  public static final int VERSION_OBJECT_MAJOR = 10;
37
  public static final int VERSION_OBJECT_MINOR = 0;
38
  public static final int VERSION_EXTRAS_MAJOR = 1;
39
  public static final int VERSION_EXTRAS_MINOR = 0;
40

    
41
  private static JsonWriter mThis;
42
  private static int mNumCubitFaces;
43

    
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

    
46
  private JsonWriter()
47
    {
48

    
49
    }
50

    
51
///////////////////////////////////////////////////////////////////////////////////////////////////
52

    
53
  private JSONArray generateCubits(TwistyObject object) throws JSONException
54
    {
55
    JSONArray array = new JSONArray();
56

    
57
    int[] numLayers     = object.getNumLayers();
58
    float[][] positions = object.getCubitPositions(numLayers);
59
    int numCubits       = positions.length;
60

    
61
    for(int c=0; c<numCubits; c++)
62
      {
63
      JSONObject cubit = new JSONObject();
64
      Static4D rotQuat = object.getCubitQuats(c,numLayers);
65
      int variant      = object.getCubitVariant(c,numLayers);
66
      int type         = object.getCubitType(c);
67
      float[] offset   = object.getCubitOffset(c);
68

    
69
      JSONArray pos = new JSONArray();
70
      int numPos = positions[c].length;
71
      for(int j=0; j<numPos; j++) pos.put(positions[c][j]);
72
      cubit.put("centers", pos);
73
      cubit.put("qx", rotQuat.get0() );
74
      cubit.put("qy", rotQuat.get1() );
75
      cubit.put("qz", rotQuat.get2() );
76
      cubit.put("qw", rotQuat.get3() );
77
      cubit.put("variant", variant );
78
      cubit.put("type", type);
79

    
80
      if( offset!=null )
81
        {
82
        cubit.put("offsetX", offset[0]);
83
        cubit.put("offsetY", offset[1]);
84
        cubit.put("offsetZ", offset[2]);
85
        }
86

    
87
      JSONArray colors = new JSONArray();
88

    
89
      for(int f=0; f<mNumCubitFaces; f++)
90
        {
91
        int cubColor = object.getCubitFaceMap(c,f);
92
        colors.put(cubColor);
93
        }
94
      cubit.put("colors",colors);
95

    
96
      array.put(cubit);
97
      }
98

    
99
    return array;
100
    }
101

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

    
104
  private JSONArray generateBands(float[][] bands) throws JSONException
105
    {
106
    JSONArray array = new JSONArray();
107

    
108
    for (float[] b : bands)
109
      {
110
      JSONObject band = new JSONObject();
111
      band.put("height"          , b[0]);
112
      band.put("angle"           , b[1]);
113
      band.put("distanceToCenter", b[2]);
114
      band.put("distanceToFlat"  , b[3]);
115
      band.put("numOfBands"      , b[4]);
116
      band.put("extraI"          , b[5]);
117
      band.put("extraJ"          , b[6]);
118
      array.put(band);
119
      }
120

    
121
    return array;
122
    }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

    
126
  private JSONArray generateFaces(TwistyObject object, int[][] vertIndices, int[] bandIndices, int[] faceOuter, int cubit, int[] numLayers) throws JSONException
127
    {
128
    JSONArray array = new JSONArray();
129
    int numFaces = vertIndices.length;
130
    int variant = object.getCubitVariant(cubit,numLayers);
131

    
132
    for(int i=0; i<numFaces; i++)
133
      {
134
      JSONObject face = new JSONObject();
135
      face.put("bandIndex", bandIndices[i]);
136

    
137
      int stiShape = object.getVariantStickerShape(variant,i);
138
      face.put("sticker", stiShape);
139
      face.put("isOuter", faceOuter[i]);
140

    
141
      JSONArray vertArr = new JSONArray();
142
      int numV = vertIndices[i].length;
143
      for(int j=0; j<numV; j++) vertArr.put(vertIndices[i][j]);
144
      face.put("vertexIndices",vertArr);
145

    
146
      array.put(face);
147
      }
148

    
149
    return array;
150
    }
151

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

    
154
  private JSONArray generateVertices(float[][] vertices) throws JSONException
155
    {
156
    JSONArray array = new JSONArray();
157

    
158
    for (float[] vertex : vertices)
159
      {
160
      JSONObject vert = new JSONObject();
161
      vert.put("x", vertex[0]);
162
      vert.put("y", vertex[1]);
163
      vert.put("z", vertex[2]);
164
      array.put(vert);
165
      }
166

    
167
    return array;
168
    }
169

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

    
172
  private JSONObject generateConvexity(float[] convexity) throws JSONException
173
    {
174
    JSONObject object = new JSONObject();
175
    object.put("x", convexity[0]);
176
    object.put("y", convexity[1]);
177
    object.put("z", convexity[2]);
178
    return object;
179
    }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
  private JSONObject generateEffect(String name, float[] var, float[] center, float[] region, boolean use) throws JSONException
184
    {
185
    JSONObject object = new JSONObject();
186

    
187
    object.put("name",name);
188

    
189
    object.put("var0", var[0]);
190
    object.put("var1", var[1]);
191
    object.put("var2", var[2]);
192
    object.put("var3", var[3]);
193
    object.put("var4", var[4]);
194

    
195
    object.put("center0", center[0]);
196
    object.put("center1", center[1]);
197
    object.put("center2", center[2]);
198

    
199
    object.put("region0", region[0]);
200
    object.put("region1", region[1]);
201
    object.put("region2", region[2]);
202
    object.put("region3", region[3]);
203

    
204
    object.put("use", use);
205

    
206
    return object;
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
  private JSONArray generateEffects(String[] names, float[][] vars, float[][] centers, float[][] regions, boolean[] uses) throws JSONException
212
    {
213
    int numEffects = names==null ? 0 : names.length;
214

    
215
    if( numEffects>0 )
216
      {
217
      JSONArray array = new JSONArray();
218

    
219
      for(int i=0; i<numEffects; i++)
220
        {
221
        if( names[i]!=null )
222
          {
223
          JSONObject object = generateEffect(names[i],vars[i],centers[i],regions[i],uses[i]);
224
          array.put(object);
225
          }
226
        }
227

    
228
      return array;
229
      }
230

    
231
    return null;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  private int findCubitWithVariant(TwistyObject object, int variant, int numCubits, int[] numLayers)
237
    {
238
    for(int i=0; i<numCubits; i++)
239
      {
240
      if( object.getCubitVariant(i,numLayers)==variant ) return i;
241
      }
242

    
243
    return -1;
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  private JSONArray generateShapes(TwistyObject object) throws JSONException
249
    {
250
    JSONArray shapes = new JSONArray();
251

    
252
    int[] numLayers = object.getNumLayers();
253
    int numVariants = object.getNumCubitVariants(numLayers);
254
    float[][] positions = object.getCubitPositions(numLayers);
255
    int[][] faceOuter   = object.getVariantFaceIsOuter();
256
    int numCubits = positions.length;
257
    mNumCubitFaces = 0;
258

    
259
    for(int i=0; i<numVariants; i++)
260
      {
261
      JSONObject shapeObj = new JSONObject();
262

    
263
      ObjectShape shape = object.getObjectShape(i);
264
      ObjectFaceShape face = object.getObjectFaceShape(i);
265
      ObjectVertexEffects effects = object.getVertexEffects(i);
266

    
267
      float[] convexity  = face.getConvexityCenter();
268
      float[][] vertices = shape.getVertices();
269
      int[][] vertIndices= shape.getVertIndices();
270
      float[][] bands    = face.getBands();
271
      int[] bandIndices  = face.getBandIndices();
272

    
273
      int num = vertIndices.length;
274
      if( num>mNumCubitFaces ) mNumCubitFaces=num;
275

    
276
      int cubit = findCubitWithVariant(object,i,numCubits,numLayers);
277

    
278
      if( convexity!=null )
279
        {
280
        JSONObject convObj = generateConvexity(convexity);
281
        shapeObj.put("convexity", convObj);
282
        }
283

    
284
      JSONArray verticesArr = generateVertices(vertices);
285
      shapeObj.put("vertices", verticesArr);
286
      JSONArray facesArr = generateFaces(object,vertIndices,bandIndices,faceOuter[i],cubit,numLayers);
287
      shapeObj.put("faces", facesArr);
288
      JSONArray bandsArr = generateBands(bands);
289
      shapeObj.put("bands", bandsArr);
290

    
291
      if( effects!=null )
292
        {
293
        String[] effNames = effects.getNames();
294
        float[][] effVars = effects.getVariables();
295
        float[][] effCent = effects.getCenters();
296
        float[][] effRegi = effects.getRegions();
297
        boolean[] effUses = effects.getUses();
298

    
299
        JSONArray effectsArr = generateEffects(effNames,effVars,effCent,effRegi,effUses);
300
        if( effectsArr!=null ) shapeObj.put("effects", effectsArr);
301
        }
302

    
303
      shapes.put(shapeObj);
304
      }
305

    
306
    return shapes;
307
    }
308

    
309
///////////////////////////////////////////////////////////////////////////////////////////////////
310

    
311
  private JSONArray generateStickers(TwistyObject object) throws JSONException
312
    {
313
    JSONArray stickers = new JSONArray();
314

    
315
    int numStickers = object.getNumStickerTypes();
316

    
317
    for(int i=0; i<numStickers; i++)
318
      {
319
      JSONObject stickerObj = new JSONObject();
320
      JSONArray  vertexArray= new JSONArray();
321

    
322
      ObjectSticker sticker = object.retSticker(i);
323

    
324
      float[] coords     = sticker.getCoords();
325
      float[] curvatures = sticker.getCurvature();
326
      float[] radii      = sticker.getRadii();
327
      float   stroke     = sticker.getStroke();
328

    
329
      stickerObj.put("stroke", stroke);
330
      int numVertices = radii.length;
331

    
332
      for(int j=0; j<numVertices; j++)
333
        {
334
        JSONObject vertex = new JSONObject();
335
        vertex.put("x", coords[2*j  ]);
336
        vertex.put("y", coords[2*j+1]);
337
        vertex.put("angle", curvatures==null ? 0 : curvatures[j]);
338
        vertex.put("radius",radii[j]);
339
        vertexArray.put(vertex);
340
        }
341
      stickerObj.put("vertices", vertexArray);
342
      stickers.put(stickerObj);
343
      }
344

    
345
    return stickers;
346
    }
347

    
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

    
350
  private JSONArray generateOverrides(TwistyObject object) throws JSONException
351
    {
352
    ObjectStickerOverride[] overrides = object.getStickerOverrides();
353

    
354
    if( overrides!=null )
355
      {
356
      JSONArray overrideArray = new JSONArray();
357

    
358
      for (ObjectStickerOverride objectStickerOverride : overrides)
359
        {
360
        JSONObject override = new JSONObject();
361
        int[] cubfac = objectStickerOverride.getCubitFaces();
362
        int color    = objectStickerOverride.getColor();
363
        JSONArray cubfacArray = new JSONArray();
364
        for (int cf : cubfac) cubfacArray.put(cf);
365

    
366
        override.put("cubitfaces", cubfacArray);
367
        override.put("color", color);
368

    
369
        overrideArray.put(override);
370
        }
371

    
372
      return overrideArray;
373
      }
374

    
375
    return null;
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  private JSONObject generateMesh(TwistyObject object) throws JSONException
381
    {
382
    JSONObject mesh = new JSONObject();
383

    
384
    JSONArray shapes   = generateShapes(object);  // do this before cubits so we calculate numCubitFaces
385
    JSONArray cubits   = generateCubits(object);
386
    JSONArray stickers = generateStickers(object);
387

    
388
    mesh.put("shapes"  , shapes);
389
    mesh.put("cubits"  , cubits);
390
    mesh.put("stickers", stickers);
391
    mesh.put("pillow"  , object.getPillowCoeff() );
392

    
393
    JSONArray overrides = generateOverrides(object);
394
    if( overrides!=null ) mesh.put("overrides", overrides);
395

    
396
    return mesh;
397
    }
398

    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400

    
401
  private JSONObject generateMetadata(TwistyObject object, int numScramble, int price) throws JSONException
402
    {
403
    JSONObject metadata = new JSONObject();
404

    
405
    metadata.put("longname"   , object.getObjectName() );
406
    metadata.put("inventor"   , object.getInventor());
407
    metadata.put("year"       , object.getYearOfInvention());
408
    metadata.put("complexity" , object.getComplexity());
409
    metadata.put("size"       , object.getSize() );
410
    metadata.put("scrambles"  , numScramble );
411
    metadata.put("shortname"  , object.getShortName() );
412
    metadata.put("resetmaps"  , object.shouldResetTextureMaps() );
413
    metadata.put("num_faces"  , object.getNumFaces() );
414
    metadata.put("price"      , price );
415

    
416
    JSONArray sigArray = new JSONArray();
417
    long[] sig = object.getSignature().getArray();
418
    for (long l : sig) sigArray.put(l);
419
    metadata.put("signature" , sigArray );
420

    
421
    return metadata;
422
    }
423

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

    
426
  private JSONArray generateQuats(TwistyObject object) throws JSONException
427
    {
428
    JSONArray quatsArray = new JSONArray();
429
    Static4D[] quats = object.getQuats();
430

    
431
    for(Static4D quat : quats)
432
      {
433
      JSONObject q = new JSONObject();
434
      q.put("x",quat.get0());
435
      q.put("y",quat.get1());
436
      q.put("z",quat.get2());
437
      q.put("w",quat.get3());
438
      quatsArray.put(q);
439
      }
440

    
441
    return quatsArray;
442
    }
443

    
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

    
446
  private JSONArray generateAxis(TwistyObject object) throws JSONException
447
    {
448
    JSONArray axis = new JSONArray();
449

    
450
    Static3D[] rotAxis = object.getRotationAxis();
451
    int numAxis = rotAxis.length;
452
    int[][] basicAngle = object.getBasicAngles();
453
    int[] numLayers = object.getNumLayers();
454
    float[][] cuts = object.getCuts(numLayers);
455
    boolean[][] rotatable = object.getLayerRotatable(numLayers);
456

    
457
    for( int i=0; i<numAxis; i++ )
458
      {
459
      JSONObject axObject = new JSONObject();
460
      Static3D ax = rotAxis[i];
461

    
462
      axObject.put("x", ax.get0() );
463
      axObject.put("y", ax.get1() );
464
      axObject.put("z", ax.get2() );
465

    
466
      JSONArray angleArray = new JSONArray();
467
      for(float angle : basicAngle[i]) angleArray.put(angle);
468
      axObject.put("basicAngles", angleArray);
469
      JSONArray cutsArray = new JSONArray();
470
      if( cuts[i]!=null ) for(float cut : cuts[i]) cutsArray.put(cut);
471
      axObject.put("cuts", cutsArray);
472
      JSONArray rotaArray = new JSONArray();
473
      for(boolean rot : rotatable[i]) rotaArray.put(rot);
474
      axObject.put("rotatable", rotaArray );
475

    
476
      axis.put(axObject);
477
      }
478

    
479
    return axis;
480
    }
481

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

    
484
  private JSONObject generateScrambling(TwistyObject object) throws JSONException
485
    {
486
    JSONObject scrambling = new JSONObject();
487

    
488
    int scrambleType = object.getScrambleType();
489
    scrambling.put("scrambleType",scrambleType );
490
    int[][] algorithms = object.getScrambleAlgorithms();
491

    
492
    if( algorithms!=null )
493
      {
494
      JSONArray scrambleAlgorithms = new JSONArray();
495

    
496
      for(int[] algorithm : algorithms)
497
        {
498
        JSONArray algArray = new JSONArray();
499
        for (int entry : algorithm) algArray.put(entry);
500
        scrambleAlgorithms.put(algArray);
501
        }
502

    
503
      scrambling.put("algorithms", scrambleAlgorithms);
504
      }
505

    
506
    int[][] edges = object.getScrambleEdges();
507

    
508
    if( edges!=null )
509
      {
510
      JSONArray scrambleEdges = new JSONArray();
511

    
512
      for(int[] edge : edges)
513
        {
514
        JSONArray edgeArray = new JSONArray();
515
        for (int entry : edge) edgeArray.put(entry);
516
        scrambleEdges.put(edgeArray);
517
        }
518

    
519
      scrambling.put("edges", scrambleEdges);
520
      }
521

    
522
    return scrambling;
523
    }
524

    
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526

    
527
  private JSONObject generateTouchControl(TwistyObject object) throws JSONException
528
    {
529
    JSONObject touchControl = new JSONObject();
530

    
531
    touchControl.put("movementType" , object.getTouchControlType() );
532
    touchControl.put("movementSplit", object.getTouchControlSplit() );
533

    
534
    int[][][] enabled = object.getEnabled();
535

    
536
    if( enabled!=null )
537
      {
538
      JSONArray enabledArray = new JSONArray();
539

    
540
      for(int[][] faceEnabled : enabled)
541
        {
542
        JSONArray faceArray = new JSONArray();
543

    
544
        for(int[] sectionEnabled : faceEnabled)
545
          {
546
          JSONArray sectionArray = new JSONArray();
547
          for(int ax : sectionEnabled) sectionArray.put(ax);
548
          faceArray.put(sectionArray);
549
          }
550
        enabledArray.put(faceArray);
551
        }
552

    
553
      touchControl.put("enabledAxis", enabledArray);
554
      }
555

    
556
    int[] numLayers = object.getNumLayers();
557
    float[] dist3D = object.getDist3D(numLayers);
558

    
559
    if( dist3D!=null )
560
      {
561
      JSONArray distArray = new JSONArray();
562
      for( float dist: dist3D ) distArray.put(dist);
563
      touchControl.put("dist3D", distArray);
564
      }
565

    
566
    return touchControl;
567
    }
568

    
569
///////////////////////////////////////////////////////////////////////////////////////////////////
570

    
571
  private JSONArray generateColors(TwistyObject object)
572
    {
573
    JSONArray jsonColors = new JSONArray();
574
    int numFaceColors = object.getNumFaceColors();
575
    for(int i=0; i<numFaceColors; i++) jsonColors.put(object.getColor(i));
576

    
577
    jsonColors.put(object.getInternalColor());
578

    
579
    return jsonColors;
580
    }
581

    
582
///////////////////////////////////////////////////////////////////////////////////////////////////
583

    
584
  private JSONObject generateSolved(TwistyObject object) throws JSONException
585
    {
586
    JSONObject solved = new JSONObject();
587
    int[][] solvedGroups = object.getSolvedQuats();
588

    
589
    solved.put("functionIndex", object.getSolvedFunctionIndex() );
590

    
591
    if( solvedGroups!=null )
592
      {
593
      JSONArray groupArray = new JSONArray();
594

    
595
      for( int[] group : solvedGroups )
596
        {
597
        JSONArray groupElements = new JSONArray();
598
        for( int element : group ) groupElements.put(element);
599
        groupArray.put(groupElements);
600
        }
601

    
602
      solved.put("groups", groupArray );
603
      }
604

    
605
    return solved;
606
    }
607

    
608
///////////////////////////////////////////////////////////////////////////////////////////////////
609

    
610
  public String createObjectString(TwistyObject object,int numScramble, int price) throws JSONException
611
    {
612
    JSONObject json = new JSONObject();
613

    
614
    JSONObject metadata    = generateMetadata(object,numScramble,price);
615
    JSONObject mesh        = generateMesh(object);
616
    JSONArray  axis        = generateAxis(object);
617
    JSONArray  quats       = generateQuats(object);
618
    JSONObject scrambling  = generateScrambling(object);
619
    JSONObject touchControl= generateTouchControl(object);
620
    JSONArray  colors      = generateColors(object);
621
    JSONObject solved      = generateSolved(object);
622

    
623
    json.put("major"       , VERSION_OBJECT_MAJOR);
624
    json.put("minor"       , VERSION_OBJECT_MINOR);
625
    json.put("metadata"    , metadata);
626
    json.put("mesh"        , mesh);
627
    json.put("axis"        , axis);
628
    json.put("quats"       , quats);
629
    json.put("scrambling"  , scrambling);
630
    json.put("touchcontrol", touchControl);
631
    json.put("colors"      , colors);
632
    json.put("solved"      , solved);
633

    
634
    return json.toString();
635
    }
636

    
637
///////////////////////////////////////////////////////////////////////////////////////////////////
638

    
639
  public String createExtrasString(TwistyObject object) throws JSONException
640
    {
641
    String[][] tuts = object.getTutorials();
642

    
643
    if( tuts!=null )
644
      {
645
      JSONObject json = new JSONObject();
646
      JSONArray  tutorials = new JSONArray();
647

    
648
      for(String[] tut : tuts)
649
        {
650
        String language = tut[0];
651
        String link     = tut[1];
652
        String title    = tut[2];
653
        String author   = tut[3];
654

    
655
        JSONObject oneTut = new JSONObject();
656

    
657
        oneTut.put("language", language);
658
        oneTut.put("link"    , link    );
659
        oneTut.put("title"   , title   );
660
        oneTut.put("author"  , author  );
661

    
662
        tutorials.put(oneTut);
663
        }
664

    
665
      json.put("major"     , VERSION_EXTRAS_MAJOR);
666
      json.put("minor"     , VERSION_EXTRAS_MINOR);
667
      json.put("object"    , object.getShortName() );
668
      json.put("tutorials" , tutorials);
669

    
670
      return json.toString();
671
      }
672

    
673
    return null;
674
    }
675

    
676
///////////////////////////////////////////////////////////////////////////////////////////////////
677

    
678
  public void write(String filename, String contents) throws IOException
679
    {
680
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filename), StandardCharsets.UTF_8);
681
    BufferedWriter bw = new BufferedWriter(osw);
682
    bw.write(contents);
683
    bw.flush();
684
    }
685

    
686
///////////////////////////////////////////////////////////////////////////////////////////////////
687

    
688
  public static JsonWriter getInstance()
689
    {
690
    if( mThis==null ) mThis = new JsonWriter();
691
    return mThis;
692
    }
693
}
(2-2/2)