Project

General

Profile

Download (18.7 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.app.Activity;
16
import android.content.Context;
17
import android.content.SharedPreferences;
18

    
19
import org.distorted.helpers.RubikFiles;
20
import org.distorted.helpers.RubikScores;
21
import org.distorted.objectlib.metadata.ListObjects;
22

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

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

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

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

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

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

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

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

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

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

    
79
    createBuiltinObjects();
80
    }
81

    
82
///////////////////////////////////////////////////////////////////////////////////////////////////
83

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

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90

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

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

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

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

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

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121

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

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

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

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

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

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

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

    
156
    return true;
157
    }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

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

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

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

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

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
// PUBLIC API
195

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

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

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

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

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

    
218
        return false;
219
        }
220
      }
221

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

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

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

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

    
253
    return false;
254
    }
255

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257

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

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

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

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

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

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

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

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

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

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

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

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

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

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

    
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

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

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

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

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

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

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

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

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

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

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

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

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

    
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

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

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

    
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441

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

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

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

    
458
    return ret;
459
    }
460

    
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462

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

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

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

    
479
///////////////////////////////////////////////////////////////////////////////////////////////////
480

    
481
  private static void markAsFree(RubikObject object, RubikScores scores)
482
    {
483
    String shortName = object.getUpperName();
484
    if( SHOW_IAP_DEBUG ) android.util.Log.e("D", "object "+object.getUpperName()+" marked as free");
485
    object.markFree();
486
    String add = mBoughtObjects.isEmpty() ? shortName : (","+shortName);
487
    mBoughtObjects += add;
488
    }
489

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491

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

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

    
500
  public static RubikObject getObject(String shortUpperName)
501
    {
502
    if( mThis==null ) mThis = new RubikObjectList();
503

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

    
513
    return null;
514
    }
515

    
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

    
518
  public static int getNumObjects()
519
    {
520
    if( mThis==null ) mThis = new RubikObjectList();
521
    return mNumObjects;
522
    }
523

    
524
///////////////////////////////////////////////////////////////////////////////////////////////////
525

    
526
  public static int getOrdinal(String name)
527
    {
528
    if( mThis==null ) mThis = new RubikObjectList();
529

    
530
    String lowerName = name.toLowerCase(Locale.ENGLISH);
531

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

    
538
    return -1;
539
    }
540

    
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542

    
543
  public static int getNumExtrasObjects()
544
    {
545
    return mNumExtras;
546
    }
547

    
548
///////////////////////////////////////////////////////////////////////////////////////////////////
549

    
550
  public static int getNumTutorialObjects()
551
    {
552
    return mNumExtras;
553
    }
554

    
555
///////////////////////////////////////////////////////////////////////////////////////////////////
556

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

    
566
    return -1;
567
    }
568

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

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

    
577
///////////////////////////////////////////////////////////////////////////////////////////////////
578

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

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586

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

    
593
///////////////////////////////////////////////////////////////////////////////////////////////////
594

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