Project

General

Profile

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

magiccube / src / main / java / org / distorted / scores / RubikScores.java @ 53f23b64

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.object.RubikObjectList;
27

    
28
import java.util.UUID;
29

    
30
import static org.distorted.object.RubikObjectList.MAX_SIZE;
31
import static org.distorted.object.RubikObjectList.NUM_OBJECTS;
32
import static org.distorted.uistate.RubikStatePlay.MAX_SCRAMBLE;
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 mDeviceID;
50

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

    
53
  private RubikScores()
54
    {
55
    mRecords   = new long[NUM_OBJECTS][MAX_SIZE][MAX_SCRAMBLE];
56
    mSubmitted = new int [NUM_OBJECTS][MAX_SIZE][MAX_SCRAMBLE];
57

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

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

    
69
    mNameIsVerified = false;
70

    
71
    mNumPlays= -1;
72
    mNumRuns = -1;
73
    mDeviceID= -1;
74
    }
75

    
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

    
78
  private int privateGetDeviceID()
79
    {
80
    int id;
81

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

    
93
    return id<0 ? -id : id;
94
    }
95

    
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97

    
98
  private String getUnsubmittedList(int mode)
99
    {
100
    RubikObjectList list;
101
    StringBuilder builder = new StringBuilder();
102
    boolean first = true;
103
    int[] sizes;
104
    int length;
105

    
106
    for(int object=0; object<NUM_OBJECTS; object++)
107
      {
108
      list = RubikObjectList.getObject(object);
109
      sizes = list.getSizes();
110
      length = sizes.length;
111

    
112
      for(int size=0; size<length; size++)
113
        {
114
        for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
115
          {
116
          if( mSubmitted[object][size][scramble]==0 && mRecords[object][size][scramble]<NO_RECORD )
117
            {
118
            if( !first ) builder.append(',');
119
            else         first=false;
120

    
121
            switch(mode)
122
              {
123
              case 0: builder.append(list.name());
124
                      builder.append("_");
125
                      builder.append(sizes[size]);
126
                      break;
127
              case 1: builder.append(scramble);
128
                      break;
129
              case 2: builder.append(mRecords[object][size][scramble]);
130
                      break;
131
              }
132
            }
133
          }
134
        }
135
      }
136

    
137
    return builder.toString();
138
    }
139

    
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141
// PUBLIC API
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

    
144
  public static RubikScores getInstance()
145
    {
146
    if( mThis==null )
147
      {
148
      mThis = new RubikScores();
149
      }
150

    
151
    return mThis;
152
    }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

    
156
  public void savePreferences(SharedPreferences.Editor editor)
157
    {
158
    StringBuilder builder = new StringBuilder();
159
    RubikObjectList list;
160
    int[] sizes;
161
    int length;
162

    
163
    for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
164
      {
165
      builder.setLength(0);
166

    
167
      for(int object=0; object<NUM_OBJECTS; object++)
168
        {
169
        list = RubikObjectList.getObject(object);
170
        sizes = list.getSizes();
171
        length = sizes.length;
172

    
173
        for(int size=0; size<length; size++)
174
          {
175
          builder.append(list.name());
176
          builder.append("_");
177
          builder.append(sizes[size]);
178
          builder.append("=");
179
          builder.append(mRecords[object][size][scramble]);
180
          builder.append(",");
181
          builder.append(mSubmitted[object][size][scramble]);
182
          builder.append(" ");
183
          }
184
        }
185

    
186
      editor.putString("scores_record"+scramble, builder.toString());
187
      }
188

    
189
    editor.putString("scores_name"  , mName  );
190
    editor.putBoolean("scores_isVerified", mNameIsVerified);
191
    editor.putInt("scores_numPlays", mNumPlays);
192
    editor.putInt("scores_numRuns" , mNumRuns);
193
    editor.putInt("scores_deviceid", mDeviceID);
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  public void restorePreferences(SharedPreferences preferences)
199
    {
200
    String recordStr, subStr, nameStr, sizeStr, timeStr, submStr;
201
    int start, end, equals, underscore, comma;
202
    int object, sizeIndex, subm;
203
    long time;
204

    
205
    for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
206
      {
207
      start = end = 0;
208
      recordStr = preferences.getString("scores_record"+scramble, "");
209

    
210
      while( end!=-1 )
211
        {
212
        end = recordStr.indexOf(" ", start);
213

    
214
        if( end==-1 ) subStr = recordStr.substring(start);
215
        else          subStr = recordStr.substring(start,end);
216

    
217
        start = end+1;
218

    
219
        underscore = subStr.indexOf("_");
220
        equals = subStr.indexOf("=");
221
        comma = subStr.indexOf(",");
222

    
223
        if( underscore>=0 && equals>=0 && comma>=0 )
224
          {
225
          nameStr = subStr.substring(0,underscore);
226
          sizeStr = subStr.substring(underscore+1, equals);
227
          timeStr = subStr.substring(equals+1,comma);
228
          submStr = subStr.substring(comma+1);
229

    
230
          object = RubikObjectList.getOrdinal(nameStr);
231

    
232
          if( object>=0 && object< NUM_OBJECTS )
233
            {
234
            sizeIndex = RubikObjectList.getSizeIndex(object,Integer.parseInt(sizeStr));
235
            time = Long.parseLong(timeStr);
236
            subm = Integer.parseInt(submStr);
237

    
238
            if( sizeIndex>=0 && sizeIndex<MAX_SIZE && subm>=0 && subm<=1 )
239
              {
240
              mRecords  [object][sizeIndex][scramble] = time;
241
              mSubmitted[object][sizeIndex][scramble] = subm;
242
              }
243
            else
244
              {
245
              android.util.Log.e("solv", "error: size="+sizeIndex+" subm="+subm);
246
              }
247
            }
248
          else
249
            {
250
            android.util.Log.e("solv", "error: object="+object);
251
            }
252
          }
253
        }
254
      }
255

    
256
    mName           = preferences.getString("scores_name"  , "" );
257
    mNameIsVerified = preferences.getBoolean("scores_isVerified", false);
258
    mNumPlays       = preferences.getInt("scores_numPlays", 0);
259
    mNumRuns        = preferences.getInt("scores_numRuns" , 0);
260
    mDeviceID       = preferences.getInt("scores_deviceid",-1);
261

    
262
    if( mDeviceID==-1 ) mDeviceID = privateGetDeviceID();
263
    }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
  public boolean setRecord(int object, int size, int scramble, long timeTaken)
268
    {
269
    int maxsize = RubikObjectList.getObject(object).getSizes().length;
270

    
271
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && scramble>=1 && scramble<=MAX_SCRAMBLE )
272
      {
273
      if( mRecords[object][size][scramble-1]> timeTaken )
274
        {
275
        mRecords  [object][size][scramble-1] = timeTaken;
276
        mSubmitted[object][size][scramble-1] = 0;
277
        return true;
278
        }
279
      }
280

    
281
    return false;
282
    }
283

    
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285

    
286
  public void incrementNumPlays()
287
    {
288
    mNumPlays++;
289
    }
290

    
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292

    
293
  public void incrementNumRuns()
294
    {
295
    mNumRuns++;
296
    }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  public void setName(String newName)
301
    {
302
    mName = newName;
303
    }
304

    
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

    
307
  void successfulSubmit()
308
    {
309
    mNameIsVerified = true;
310

    
311
    for(int i=0; i<NUM_OBJECTS; i++)
312
      for(int j=0; j<MAX_SIZE   ; j++)
313
        for(int k=0; k<MAX_SCRAMBLE; k++)
314
          {
315
          mSubmitted[i][j][k]=1;
316
          }
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
  public void setCountry(Context context)
322
    {
323
    TelephonyManager tM =((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
324

    
325
    if( tM!=null )
326
      {
327
      mCountry = tM.getSimCountryIso();
328

    
329
      if( mCountry==null || mCountry.length()<=1 )
330
        {
331
        mCountry = tM.getNetworkCountryIso();
332
        }
333
      }
334

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

    
339
    if( mCountry.equals("do") ) mCountry = "dm";
340
    }
341

    
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

    
344
  public long getRecord(int object, int size, int scramble)
345
    {
346
    int maxsize = RubikObjectList.getObject(object).getSizes().length;
347

    
348
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && scramble>=0 && scramble<MAX_SCRAMBLE )
349
      {
350
      return mRecords[object][size][scramble];
351
      }
352

    
353
    return -1;
354
    }
355

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

    
358
  public boolean isSubmitted(int object, int size, int scramble)
359
    {
360
    int maxsize = RubikObjectList.getObject(object).getSizes().length;
361

    
362
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && scramble>=0 && scramble<MAX_SCRAMBLE )
363
      {
364
      return mSubmitted[object][size][scramble]==1;
365
      }
366

    
367
    return false;
368
    }
369

    
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

    
372
  int getDeviceID()
373
    {
374
    return mDeviceID;
375
    }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

    
379
  boolean isVerified()
380
    {
381
    return mNameIsVerified;
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
  int getNumPlays()
387
    {
388
    return mNumPlays;
389
    }
390

    
391
///////////////////////////////////////////////////////////////////////////////////////////////////
392

    
393
  int getNumRuns()
394
    {
395
    return mNumRuns;
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  public String getName()
401
    {
402
    return mName;
403
    }
404

    
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406

    
407
  public String getCountry()
408
    {
409
    return mCountry;
410
    }
411

    
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413

    
414
  boolean thereAreUnsubmittedRecords()
415
    {
416
    RubikObjectList list;
417
    int length;
418

    
419
    for(int object=0; object<NUM_OBJECTS; object++)
420
      {
421
      list = RubikObjectList.getObject(object);
422
      length = list.getSizes().length;
423

    
424
      for(int size=0; size<length; size++)
425
        for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
426
          {
427
          if( mSubmitted[object][size][scramble]==0 && mRecords[object][size][scramble]<NO_RECORD )
428
            {
429
            return true;
430
            }
431
          }
432
      }
433

    
434
    return false;
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  String getUnsubmittedObjlist()
440
    {
441
    return getUnsubmittedList(0);
442
    }
443

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

    
446
  String getUnsubmittedLevellist()
447
    {
448
    return getUnsubmittedList(1);
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  String getUnsubmittedTimelist()
454
    {
455
    return getUnsubmittedList(2);
456
    }
457
  }
(1-1/2)