Project

General

Profile

Download (18.8 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objects / RubikObjectList.java @ master

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

    
10
package org.distorted.objects;
11

    
12
import java.util.ArrayList;
13
import java.util.Locale;
14

    
15
import android.content.Context;
16
import android.content.SharedPreferences;
17

    
18
import org.distorted.external.RubikFiles;
19
import org.distorted.external.RubikScores;
20
import org.distorted.objectlib.metadata.ListObjects;
21

    
22
import static org.distorted.objectlib.metadata.ListObjects.NUM_OBJECTS;
23

    
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25

    
26
public class RubikObjectList
27
{
28
  public static final boolean SHOW_DOWNLOADED_DEBUG = false;
29
  public static final boolean SHOW_IAP_DEBUG        = false;
30
  public static final boolean USE_IAP               = false;
31

    
32
  private static RubikObjectList mThis;
33
  private static int mNumObjects;
34
  private static int mNumExtras;
35
  private static ArrayList<RubikObject> mObjects;
36

    
37
  public static class DownloadedObject
38
    {
39
    String shortName;
40
    boolean icon,object,extras,adjColors;
41
    int numScrambles, objectVersion, extrasVersion, price;
42
    int category, year;
43
    float difficulty;
44
    String author;
45

    
46
    DownloadedObject(String sName, int scrambles, int pr, int oVersion, int eVersion, boolean i,
47
                     boolean o, boolean e, float diff, int cat, int y, String a, boolean c)
48
      {
49
      shortName     = sName;
50
      numScrambles  = scrambles;
51
      price         = pr;
52
      objectVersion = oVersion;
53
      extrasVersion = eVersion;
54
      difficulty    = diff;
55
      category      = cat;
56
      year          = y;
57
      author        = a;
58
      adjColors     = c;
59

    
60
      icon   = i;
61
      object = o;
62
      extras = e;
63
      }
64
    }
65

    
66
  private static ArrayList<DownloadedObject> mDownloadedObjects;
67
  private static String mBoughtObjects;
68

    
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

    
71
  private RubikObjectList()
72
    {
73
    mNumObjects        = 0;
74
    mNumExtras         = 0;
75
    mObjects           = new ArrayList<>();
76
    mDownloadedObjects = new ArrayList<>();
77

    
78
    createBuiltinObjects();
79
    }
80

    
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

    
83
  private static boolean allObjectsUnlocked()
84
    {
85
    return mBoughtObjects!=null       &&
86
           mBoughtObjects.length()>0  &&
87
           mBoughtObjects.charAt(0)=='*';
88
    }
89

    
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91

    
92
  private void createBuiltinObjects()
93
    {
94
    for(int i=0; i<NUM_OBJECTS; i++)
95
      {
96
      ListObjects lo = ListObjects.getObject(i);
97

    
98
      if( lo.isEnabled() )
99
        {
100
        RubikObject obj = new RubikObject(lo);
101
        mObjects.add(obj);
102
        mNumObjects++;
103

    
104
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "creating local object "+lo.name() );
105

    
106
        if( obj.hasExtras() )
107
          {
108
          if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "has extras "+mNumExtras );
109

    
110
          obj.setExtrasOrdinal(mNumExtras);
111
          mNumExtras++;
112
          }
113
        else
114
          {
115
          if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "no extras");
116
          }
117
        }
118
      }
119
    }
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
  private static boolean internalAddDownloadedObject(DownloadedObject object)
124
    {
125
    String name = object.shortName;
126

    
127
    for(RubikObject ro : mObjects )
128
      if( ro.getLowerName().equals(name) )
129
        {
130
        return ro.updateObject(object);
131
        }
132

    
133
    RubikObject obj = new RubikObject(object);
134
    mObjects.add(obj);
135
    mNumObjects++;
136

    
137
    if( USE_IAP && !obj.isFree() && allObjectsUnlocked() )
138
      {
139
      if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "everything unlocked, so setting downloaded object free: "+obj.getUpperName() );
140
      obj.markFree();
141
      }
142

    
143
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "creating downloaded object "+obj.getUpperName() );
144

    
145
    if( obj.hasExtras() )
146
      {
147
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "has extras "+mNumExtras );
148

    
149
      obj.setExtrasOrdinal(mNumExtras);
150
      mNumExtras++;
151
      }
152
    else
153
      {
154
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "no extras");
155
      }
156

    
157
    return true;
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161

    
162
  private static void restoreFreedObjects(SharedPreferences preferences)
163
    {
164
    mBoughtObjects = preferences.getString("rol_bought", "");
165

    
166
    if( SHOW_IAP_DEBUG )
167
      {
168
      android.util.Log.e("D", "bought objects: "+mBoughtObjects);
169
      }
170

    
171
    if( mBoughtObjects.length()>0 )
172
      {
173
      if( mBoughtObjects.charAt(0)=='*' )
174
        {
175
        for(int i=0; i<mNumObjects; i++)
176
          {
177
          RubikObject o = mObjects.get(i);
178
          if( o!=null ) o.markFree();
179
          }
180
        }
181
      else
182
        {
183
        String[] objs = mBoughtObjects.split(",");
184

    
185
        for( String obj : objs )
186
          {
187
          RubikObject o = getObject(obj);
188
          if( o!=null ) o.markFree();
189
          }
190
        }
191
      }
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195
// PUBLIC API
196

    
197
  public static boolean addDownloadedObject(Context context, String shortName, int numScrambles, int price, int objectVersion,
198
                                         int extrasVersion, boolean icon, boolean object, boolean extras, float diff,
199
                                         int category, int year, String author, boolean adjColors)
200
    {
201
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "New downloaded object "+shortName+" icon="+icon+" object="+object+" extras="+extras);
202

    
203
    for( DownloadedObject obj : mDownloadedObjects )
204
      {
205
      if( obj.shortName.equals(shortName) )
206
        {
207
        obj.icon  |= icon;
208
        obj.object|= object;
209
        obj.extras|= extras;
210

    
211
        if( !obj.object ) objectVersion=-1;
212
        if( !obj.extras ) extrasVersion=-1;
213

    
214
        obj.objectVersion = objectVersion;
215
        obj.extrasVersion = extrasVersion;
216

    
217
        if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Updating downloaded object "+shortName+" icon="+obj.icon+" object="+obj.object+" extras="+obj.extras);
218

    
219
        return false;
220
        }
221
      }
222

    
223
    if( !object ) objectVersion=-1;
224
    if( !extras ) extrasVersion=-1;
225

    
226
    DownloadedObject obj = new DownloadedObject(shortName,numScrambles,price,objectVersion,extrasVersion,icon,object,extras,diff,category,year,author,adjColors);
227
    if ( internalAddDownloadedObject(obj) )
228
      {
229
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "Adding new downloaded object "+shortName+" icon="+obj.icon+" object="+obj.object+" extras="+obj.extras);
230
      mDownloadedObjects.add(obj);
231
      return true;
232
      }
233
    else
234
      {
235
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "New downloaded object "+shortName+" is already built-in, deleting");
236
      RubikFiles files = RubikFiles.getInstance();
237
      files.deleteIcon(context,shortName);
238
      files.deleteJsonObject(context,shortName);
239
      files.deleteJsonExtras(context,shortName);
240
      return false;
241
      }
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

    
246
  public static boolean thereAreLockedObjects()
247
    {
248
    for(int i=0; i<mNumObjects; i++)
249
      {
250
      RubikObject o = mObjects.get(i);
251
      if( !o.isFree() ) return true;
252
      }
253

    
254
    return false;
255
    }
256

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

    
259
  public static boolean objectAlreadyBought(RubikObject object)
260
    {
261
    return ( object!=null && object.isFree() );
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265
// calling PurchaseScreenPane charges the user.
266

    
267
  public static void buyAll()
268
    {
269
    mBoughtObjects = "*";
270
    if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "all objects marked as bought");
271

    
272
    for(int i=0; i<mNumObjects; i++)
273
      {
274
      RubikObject o = mObjects.get(i);
275
      o.markFree();
276
      }
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280
// calling PurchaseScreenPane charges the user.
281

    
282
  public static void buyObject(RubikObject object)
283
    {
284
    if( object!=null && !object.isFree() )
285
      {
286
      String shortName = object.getUpperName();
287
      if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "object "+shortName+" marked as bought");
288
      object.markFree();
289
      String add = mBoughtObjects.length()==0 ? shortName : (","+shortName);
290
      mBoughtObjects += add;
291
      }
292
    }
293

    
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295

    
296
  public static void savePreferences(SharedPreferences.Editor editor)
297
    {
298
    int numDownloaded = mDownloadedObjects.size();
299

    
300
    if( numDownloaded>0 )
301
      {
302
      StringBuilder downloadedObjects = new StringBuilder();
303

    
304
      for(int i=0; i<numDownloaded; i++)
305
        {
306
        if( i>0 ) downloadedObjects.append(',');
307

    
308
        DownloadedObject object = mDownloadedObjects.get(i);
309
        downloadedObjects.append(object.shortName);
310
        downloadedObjects.append(' ');
311
        downloadedObjects.append(object.numScrambles);
312
        downloadedObjects.append(' ');
313
        downloadedObjects.append(object.objectVersion);
314
        downloadedObjects.append(' ');
315
        downloadedObjects.append(object.extrasVersion);
316
        downloadedObjects.append(' ');
317
        downloadedObjects.append(object.icon   ? "1":"0");
318
        downloadedObjects.append(' ');
319
        downloadedObjects.append(object.object ? "1":"0");
320
        downloadedObjects.append(' ');
321
        downloadedObjects.append(object.extras ? "1":"0");
322
        downloadedObjects.append(' ');
323
        downloadedObjects.append(object.difficulty);
324
        downloadedObjects.append(' ');
325
        downloadedObjects.append(object.category);
326
        downloadedObjects.append(' ');
327
        downloadedObjects.append(object.year);
328
        downloadedObjects.append(' ');
329
        downloadedObjects.append(object.author.replace(' ','_'));
330
        downloadedObjects.append(' ');
331
        downloadedObjects.append(object.price);
332
        downloadedObjects.append(' ');
333
        downloadedObjects.append(object.adjColors ? "1":"0");
334
        }
335

    
336
      String objects = downloadedObjects.toString();
337
      if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", "saving: "+objects);
338
      editor.putString("rol_downloaded", objects );
339
      }
340
    else
341
      {
342
      editor.putString("rol_downloaded", "" );
343
      }
344

    
345
    if( USE_IAP )
346
      {
347
      editor.putString("rol_bought", mBoughtObjects);
348

    
349
      if( SHOW_IAP_DEBUG )
350
        {
351
        android.util.Log.e("D", "saving bought objects: "+mBoughtObjects);
352
        }
353
      }
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357

    
358
  public static void restorePreferences(Context context, SharedPreferences preferences, boolean justStarted)
359
    {
360
    if( mThis==null ) mThis = new RubikObjectList();
361

    
362
    String downloaded = preferences.getString("rol_downloaded","");
363

    
364
    if( SHOW_DOWNLOADED_DEBUG ) android.util.Log.e("D", downloaded);
365

    
366
    if( !downloaded.equals(""))
367
      {
368
      String[] dObjects = downloaded.split(",");
369

    
370
      for(String dObj : dObjects)
371
        {
372
        String[] parts = dObj.split(" ");
373
        int length = parts.length;
374

    
375
        if( length>=7 )
376
          {
377
          String name = parts[0];
378
          String scra = parts[1];
379
          String objV = parts[2];
380
          String extV = parts[3];
381
          String icon = parts[4];
382
          String obje = parts[5];
383
          String extr = parts[6];
384

    
385
          int price=0,category=0,year=0;
386
          boolean supportsAdjColors=true;
387
          float diff=0.0f;
388
          String author="";
389

    
390
          if( length>=11 )
391
            {
392
            diff     = Float.parseFloat(parts[7]);
393
            category = Integer.parseInt(parts[8]);
394
            year     = Integer.parseInt(parts[9]);
395
            author   = parts[10].replace('_',' ');
396
            }
397
          if( length>=12 )
398
            {
399
            char c = parts[11].charAt(0);
400
            if( c=='t' )      price = 0;
401
            else if( c=='f' ) price = ListObjects.DEFAULT_PRICE_OF_OLD_OBJECTS;
402
            else              price = Integer.parseInt(parts[11]);
403
            }
404
          if( length>=13 )
405
            {
406
            char s = parts[12].charAt(0);
407
            supportsAdjColors = (s=='1');
408
            }
409

    
410
          int scrambles = Integer.parseInt(scra);
411
          int oVersion  = Integer.parseInt(objV);
412
          int eVersion  = Integer.parseInt(extV);
413

    
414
          boolean bIcon = icon.equals("1");
415
          boolean bObje = obje.equals("1");
416
          boolean bExtr = extr.equals("1");
417

    
418
          addDownloadedObject(context,name,scrambles,price,oVersion,eVersion,bIcon,bObje,bExtr,diff,category,year,author,supportsAdjColors);
419
          }
420
        }
421
      }
422

    
423
    if( USE_IAP && justStarted ) restoreFreedObjects(preferences);
424
    }
425

    
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427

    
428
  public static void firstUpgradeMarkAllSolvedAsFree()
429
    {
430
    RubikScores scores = RubikScores.getInstance();
431
    int numUnclaimed = scores.numberOfSolvedMAXes();
432

    
433
    if( numUnclaimed>0 )
434
      {
435
      int marked = markAllSolvedAsFree(scores);
436
      int stillUnclaimed = numUnclaimed-marked;
437
      if( stillUnclaimed>0) markObjectsAsFree(scores,stillUnclaimed);
438
      }
439
    }
440

    
441
///////////////////////////////////////////////////////////////////////////////////////////////////
442

    
443
  private static int markAllSolvedAsFree(RubikScores scores)
444
    {
445
    int numObjects = RubikObjectList.getNumObjects();
446
    int ret = 0;
447

    
448
    for(int obj=0; obj<numObjects; obj++)
449
      {
450
      RubikObject object = getObject(obj);
451

    
452
      if( object!=null && !object.isFree() && scores.isSolved(obj,RubikScores.LEVELS_SHOWN) )
453
        {
454
        markAsFree(object,scores);
455
        ret++;
456
        }
457
      }
458

    
459
    return ret;
460
    }
461

    
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

    
464
  private static void markObjectsAsFree(RubikScores scores, int numToBeMarked)
465
    {
466
    int numObjects = RubikObjectList.getNumObjects();
467

    
468
    for(int obj=0; obj<numObjects && numToBeMarked>0; obj++)
469
      {
470
      RubikObject object = getObject(obj);
471

    
472
      if( object!=null && !object.isFree() )
473
        {
474
        markAsFree(object,scores);
475
        numToBeMarked--;
476
        }
477
      }
478
    }
479

    
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481

    
482
  private static void markAsFree(RubikObject object, RubikScores scores)
483
    {
484
    String shortName = object.getUpperName();
485
    if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "object "+object.getUpperName()+" marked as free");
486
    object.markFree();
487
    int price = object.getPrice();
488
    scores.changeNumStars(-price);
489
    String add = mBoughtObjects.length()==0 ? shortName : (","+shortName);
490
    mBoughtObjects += add;
491
    }
492

    
493
///////////////////////////////////////////////////////////////////////////////////////////////////
494

    
495
  public static RubikObject getObject(int ordinal)
496
    {
497
    if( mThis==null ) mThis = new RubikObjectList();
498
    return ordinal>=0 && ordinal<mNumObjects ? mObjects.get(ordinal) : null;
499
    }
500

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502

    
503
  public static RubikObject getObject(String shortUpperName)
504
    {
505
    if( mThis==null ) mThis = new RubikObjectList();
506

    
507
    for(int i=0; i<mNumObjects; i++)
508
      {
509
      RubikObject object = mObjects.get(i);
510
      if( object.getUpperName().equals(shortUpperName) )
511
        {
512
        return object;
513
        }
514
      }
515

    
516
    return null;
517
    }
518

    
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520

    
521
  public static int getNumObjects()
522
    {
523
    if( mThis==null ) mThis = new RubikObjectList();
524
    return mNumObjects;
525
    }
526

    
527
///////////////////////////////////////////////////////////////////////////////////////////////////
528

    
529
  public static int getOrdinal(String name)
530
    {
531
    if( mThis==null ) mThis = new RubikObjectList();
532

    
533
    String lowerName = name.toLowerCase(Locale.ENGLISH);
534

    
535
    for(int i=0; i<mNumObjects; i++)
536
      {
537
      RubikObject obj = mObjects.get(i);
538
      if( obj.getLowerName().equals(lowerName) ) return i;
539
      }
540

    
541
    return -1;
542
    }
543

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

    
546
  public static int getNumExtrasObjects()
547
    {
548
    return mNumExtras;
549
    }
550

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

    
553
  public static int getNumTutorialObjects()
554
    {
555
    return mNumExtras;
556
    }
557

    
558
///////////////////////////////////////////////////////////////////////////////////////////////////
559

    
560
  public static int getObjectOrdinal(int extrasOrdinal)
561
    {
562
    for(int i=extrasOrdinal; i<mNumObjects; i++)
563
      {
564
      RubikObject object = getObject(i);
565
      int extOrd = object!=null ? object.getExtrasOrdinal() : -1;
566
      if( extOrd==extrasOrdinal ) return i;
567
      }
568

    
569
    return -1;
570
    }
571

    
572
///////////////////////////////////////////////////////////////////////////////////////////////////
573

    
574
  public static int getExtrasOrdinal(int objectOrdinal)
575
    {
576
    RubikObject object = getObject(objectOrdinal);
577
    return object!=null ? object.getExtrasOrdinal() : -1;
578
    }
579

    
580
///////////////////////////////////////////////////////////////////////////////////////////////////
581

    
582
  public static int getTutorialOrdinal(int objectOrdinal)
583
    {
584
    RubikObject object = getObject(objectOrdinal);
585
    return object!=null ? object.getExtrasOrdinal() : -1;
586
    }
587

    
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589

    
590
  public static int getLocalObjectVersion(int objectOrdinal)
591
    {
592
    RubikObject object = getObject(objectOrdinal);
593
    return object!=null ? object.getObjectVersion() : -1;
594
    }
595

    
596
///////////////////////////////////////////////////////////////////////////////////////////////////
597

    
598
  public static int getLocalExtrasVersion(int objectOrdinal)
599
    {
600
    RubikObject object = getObject(objectOrdinal);
601
    return object!=null ? object.getExtrasVersion() : -1;
602
    }
603
}
(7-7/7)