Project

General

Profile

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

magiccube / src / main / java / org / distorted / scores / RubikScores.java @ a4259b7f

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.scores;
21

    
22
import android.content.Context;
23
import android.content.SharedPreferences;
24
import android.telephony.TelephonyManager;
25

    
26
import org.distorted.objects.ObjectList;
27

    
28
import java.util.UUID;
29

    
30
import static org.distorted.objects.ObjectList.MAX_NUM_OBJECTS;
31
import static org.distorted.objects.ObjectList.NUM_OBJECTS;
32
import static org.distorted.objects.ObjectList.MAX_LEVEL;
33

    
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35
// hold my own scores, and some other statistics.
36

    
37
public class RubikScores
38
  {
39
  public static final long NO_RECORD = Long.MAX_VALUE;
40
  private static RubikScores mThis;
41

    
42
  private long[][][] mRecords;
43
  private int [][][] mSubmitted;
44

    
45
  private String mName, mCountry;
46
  private boolean mNameIsVerified;
47
  private int mNumRuns;
48
  private int mNumPlays;
49
  private int mNumReviews;
50
  private int mDeviceID;
51

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

    
54
  private RubikScores()
55
    {
56
    mRecords   = new long[NUM_OBJECTS][MAX_NUM_OBJECTS][MAX_LEVEL];
57
    mSubmitted = new int [NUM_OBJECTS][MAX_NUM_OBJECTS][MAX_LEVEL];
58

    
59
    for(int i=0; i<NUM_OBJECTS; i++)
60
      for(int j=0; j<MAX_NUM_OBJECTS; j++)
61
        for(int k=0; k<MAX_LEVEL; k++)
62
          {
63
          mRecords[i][j][k]   = NO_RECORD;
64
          mSubmitted[i][j][k] = 0;
65
          }
66

    
67
    mName = "";
68
    mCountry = "un";
69

    
70
    mNameIsVerified = false;
71

    
72
    mNumPlays   = -1;
73
    mNumRuns    = -1;
74
    mDeviceID   = -1;
75
    mNumReviews =  0;
76
    }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

    
80
  private int privateGetDeviceID()
81
    {
82
    int id;
83

    
84
    try
85
      {
86
      String s = UUID.randomUUID().toString();
87
      id = s.hashCode();
88
      }
89
    catch(Exception ex)
90
      {
91
      id = 0;
92
      android.util.Log.e("scores", "Exception in getDeviceID()");
93
      }
94

    
95
    return id<0 ? -id : id;
96
    }
97

    
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99

    
100
  synchronized void successfulSubmit()
101
    {
102
    mNameIsVerified = true;
103

    
104
    for(int i=0; i<NUM_OBJECTS; i++)
105
      for(int j=0; j<MAX_NUM_OBJECTS; j++)
106
        for(int k=0; k<MAX_LEVEL; k++)
107
          {
108
          mSubmitted[i][j][k]=1;
109
          }
110
    }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113

    
114
  int getDeviceID()
115
    {
116
    return mDeviceID;
117
    }
118

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120

    
121
  boolean isVerified()
122
    {
123
    return mNameIsVerified;
124
    }
125

    
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127

    
128
  synchronized boolean thereAreUnsubmittedRecords()
129
    {
130
    ObjectList list;
131
    int length;
132

    
133
    for(int object=0; object<NUM_OBJECTS; object++)
134
      {
135
      list = ObjectList.getObject(object);
136
      length = list.getSizes().length;
137

    
138
      for(int size=0; size<length; size++)
139
        for(int level=0; level<MAX_LEVEL; level++)
140
          {
141
          if( mSubmitted[object][size][level]==0 && mRecords[object][size][level]<NO_RECORD )
142
            {
143
            return true;
144
            }
145
          }
146
      }
147

    
148
    return false;
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152

    
153
  synchronized String getRecordList(String strObj, String strLvl, String strTim)
154
    {
155
    ObjectList list;
156
    StringBuilder builderObj = new StringBuilder();
157
    StringBuilder builderLvl = new StringBuilder();
158
    StringBuilder builderTim = new StringBuilder();
159
    boolean first = true;
160
    int[] sizes;
161
    int length;
162

    
163
    for(int object=0; object<NUM_OBJECTS; object++)
164
      {
165
      list = ObjectList.getObject(object);
166
      sizes = list.getSizes();
167
      length = sizes.length;
168

    
169
      for(int size=0; size<length; size++)
170
        {
171
        for(int level=0; level<MAX_LEVEL; level++)
172
          {
173
          if( mSubmitted[object][size][level]==0 && mRecords[object][size][level]<NO_RECORD )
174
            {
175
            if( !first )
176
              {
177
              builderObj.append(',');
178
              builderLvl.append(',');
179
              builderTim.append(',');
180
              }
181
            else
182
              {
183
              first=false;
184
              }
185

    
186
            builderObj.append(list.name());
187
            builderObj.append("_");
188
            builderObj.append(sizes[size]);
189
            builderLvl.append(level);
190
            builderTim.append(mRecords[object][size][level]);
191
            }
192
          }
193
        }
194
      }
195

    
196
    return strObj+builderObj.toString()+strLvl+builderLvl.toString()+strTim+builderTim.toString();
197
    }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200
// Public API
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

    
203
  public synchronized long getRecord(int object, int size, int level)
204
    {
205
    int maxsize = ObjectList.getObject(object).getSizes().length;
206

    
207
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && level>=0 && level<MAX_LEVEL )
208
      {
209
      return mRecords[object][size][level];
210
      }
211

    
212
    return -1;
213
    }
214

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

    
217
  public synchronized boolean isSubmitted(int object, int size, int level)
218
    {
219
    int maxsize = ObjectList.getObject(object).getSizes().length;
220

    
221
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && level>=0 && level<MAX_LEVEL )
222
      {
223
      return mSubmitted[object][size][level]==1;
224
      }
225

    
226
    return false;
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
  public int getNumPlays()
232
    {
233
    return mNumPlays;
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
  public int getNumRuns()
239
    {
240
    return mNumRuns;
241
    }
242

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

    
245
  public int getNumReviews()
246
    {
247
    return mNumReviews;
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  public String getName()
253
    {
254
    return mName;
255
    }
256

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

    
259
  public String getCountry()
260
    {
261
    return mCountry;
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  public void incrementNumPlays()
267
    {
268
    mNumPlays++;
269
    }
270

    
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272

    
273
  public void incrementNumRuns()
274
    {
275
    mNumRuns++;
276
    }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279

    
280
  public void incrementNumReviews()
281
    {
282
    mNumReviews++;
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  public void setName(String newName)
288
    {
289
    mName = newName;
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  public void setCountry(String country)
295
    {
296
    mCountry = country;
297

    
298
    if( mCountry.equals("do") ) mCountry = "dm";  // see above
299
    }
300

    
301
///////////////////////////////////////////////////////////////////////////////////////////////////
302

    
303
  public synchronized boolean isSolved(int object, int size, int level)
304
    {
305
    int maxsize = ObjectList.getObject(object).getSizes().length;
306

    
307
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && level>=0 && level<MAX_LEVEL )
308
      {
309
      return mRecords[object][size][level]<NO_RECORD;
310
      }
311

    
312
    return false;
313
    }
314

    
315
///////////////////////////////////////////////////////////////////////////////////////////////////
316

    
317
  public void setCountry(Context context)
318
    {
319
    TelephonyManager tM =((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
320

    
321
    if( tM!=null )
322
      {
323
      mCountry = tM.getSimCountryIso();
324

    
325
      if( mCountry==null || mCountry.length()<=1 )
326
        {
327
        mCountry = tM.getNetworkCountryIso();
328
        }
329
      }
330

    
331
    // Special case: Dominicana. Its ISO-3166-alpha-2 country code is 'do' which we can't have here
332
    // because we later on map this to a resource name (the flag) and 'do' is a reserved Java keyword
333
    // and can't be a resource name.
334

    
335
    if( mCountry.equals("do") ) mCountry = "dm";
336
    }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339

    
340
  public static RubikScores getInstance()
341
    {
342
    if( mThis==null )
343
      {
344
      mThis = new RubikScores();
345
      }
346

    
347
    return mThis;
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  public synchronized void savePreferences(SharedPreferences.Editor editor)
353
    {
354
    StringBuilder builder = new StringBuilder();
355
    ObjectList list;
356
    int[] sizes;
357
    int length;
358

    
359
    for(int level=0; level<MAX_LEVEL; level++)
360
      {
361
      builder.setLength(0);
362

    
363
      for(int object=0; object<NUM_OBJECTS; object++)
364
        {
365
        list = ObjectList.getObject(object);
366
        sizes = list.getSizes();
367
        length = sizes.length;
368

    
369
        for(int size=0; size<length; size++)
370
          {
371
          builder.append(list.name());
372
          builder.append("_");
373
          builder.append(sizes[size]);
374
          builder.append("=");
375
          builder.append(mRecords[object][size][level]);
376
          builder.append(",");
377
          builder.append(mSubmitted[object][size][level]);
378
          builder.append(" ");
379
          }
380
        }
381

    
382
      editor.putString("scores_record"+level, builder.toString());
383
      }
384

    
385
    editor.putString("scores_name"  , mName  );
386
    editor.putBoolean("scores_isVerified", mNameIsVerified);
387
    editor.putInt("scores_numPlays", mNumPlays);
388
    editor.putInt("scores_numRuns" , mNumRuns);
389
    editor.putInt("scores_deviceid", mDeviceID);
390
    editor.putInt("scores_review"  , mNumReviews);
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
  public synchronized void restorePreferences(SharedPreferences preferences)
396
    {
397
    String recordStr, subStr, nameStr, sizeStr, timeStr, submStr;
398
    int start, end, equals, underscore, comma;
399
    int object, sizeIndex, subm;
400
    long time;
401

    
402
    for(int level=0; level<MAX_LEVEL; level++)
403
      {
404
      start = end = 0;
405
      recordStr = preferences.getString("scores_record"+level, "");
406

    
407
      while( end!=-1 )
408
        {
409
        end = recordStr.indexOf(" ", start);
410

    
411
        if( end==-1 ) subStr = recordStr.substring(start);
412
        else          subStr = recordStr.substring(start,end);
413

    
414
        start = end+1;
415

    
416
        underscore = subStr.indexOf("_");
417
        equals = subStr.indexOf("=");
418
        comma = subStr.indexOf(",");
419

    
420
        if( underscore>=0 && equals>=0 && comma>=0 )
421
          {
422
          nameStr = subStr.substring(0,underscore);
423
          sizeStr = subStr.substring(underscore+1, equals);
424
          timeStr = subStr.substring(equals+1,comma);
425
          submStr = subStr.substring(comma+1);
426

    
427
          object = ObjectList.getOrdinal(nameStr);
428

    
429
          if( object>=0 && object< NUM_OBJECTS )
430
            {
431
            sizeIndex = ObjectList.getSizeIndex(object,Integer.parseInt(sizeStr));
432
            time = Long.parseLong(timeStr);
433
            subm = Integer.parseInt(submStr);
434

    
435
            if( sizeIndex>=0 && sizeIndex<MAX_NUM_OBJECTS && subm>=0 && subm<=1 )
436
              {
437
              mRecords  [object][sizeIndex][level] = time;
438
              mSubmitted[object][sizeIndex][level] = subm;
439
              }
440
            else
441
              {
442
              android.util.Log.e("scores", "error: size="+sizeIndex+" subm="+subm);
443
              }
444
            }
445
          else
446
            {
447
            android.util.Log.e("scores", "error: object="+object);
448
            }
449
          }
450
        }
451
      }
452

    
453
    mName           = preferences.getString("scores_name"  , "" );
454
    mNameIsVerified = preferences.getBoolean("scores_isVerified", false);
455
    mNumPlays       = preferences.getInt("scores_numPlays", 0);
456
    mNumRuns        = preferences.getInt("scores_numRuns" , 0);
457
    mDeviceID       = preferences.getInt("scores_deviceid",-1);
458
    mNumReviews     = preferences.getInt("scores_review"  ,-3);
459

    
460
    if( mDeviceID==-1 ) mDeviceID = privateGetDeviceID();
461
    }
462

    
463
///////////////////////////////////////////////////////////////////////////////////////////////////
464

    
465
  public synchronized boolean setRecord(int object, int size, int level, long timeTaken)
466
    {
467
    int maxsize = ObjectList.getObject(object).getSizes().length;
468

    
469
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && level>=1 && level<=MAX_LEVEL )
470
      {
471
      if( mRecords[object][size][level-1]> timeTaken )
472
        {
473
        mRecords  [object][size][level-1] = timeTaken;
474
        mSubmitted[object][size][level-1] = 0;
475
        return true;
476
        }
477
      }
478

    
479
    return false;
480
    }
481
  }
(1-1/2)