Project

General

Profile

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

magiccube / src / main / java / org / distorted / scores / RubikScores.java @ 4895fff6

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 = "YOU";
67
    mCountry = "un";
68

    
69
    mNameIsVerified = false;
70

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

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

    
78
  public static RubikScores getInstance()
79
    {
80
    if( mThis==null )
81
      {
82
      mThis = new RubikScores();
83
      }
84

    
85
    return mThis;
86
    }
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

    
90
  public void savePreferences(SharedPreferences.Editor editor)
91
    {
92
    StringBuilder builder = new StringBuilder();
93
    RubikObjectList list;
94
    int[] sizes;
95
    int length;
96

    
97
    for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
98
      {
99
      builder.setLength(0);
100

    
101
      for(int object=0; object<NUM_OBJECTS; object++)
102
        {
103
        list = RubikObjectList.getObject(object);
104
        sizes = list.getSizes();
105
        length = sizes.length;
106

    
107
        for(int size=0; size<length; size++)
108
          {
109
          builder.append(list.name());
110
          builder.append("_");
111
          builder.append(sizes[size]);
112
          builder.append("=");
113
          builder.append(mRecords[object][size][scramble]);
114
          builder.append(",");
115
          builder.append(mSubmitted[object][size][scramble]);
116
          builder.append(" ");
117
          }
118
        }
119

    
120
      editor.putString("scores_record"+scramble, builder.toString());
121
      }
122

    
123
    editor.putString("scores_name"  , mName  );
124
    editor.putBoolean("scores_isVerified", mNameIsVerified);
125
    editor.putInt("scores_numPlays", mNumPlays);
126
    editor.putInt("scores_numRuns" , mNumRuns);
127
    editor.putInt("scores_deviceid", mDeviceID);
128
    }
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

    
132
  public void restorePreferences(SharedPreferences preferences)
133
    {
134
    String recordStr, subStr, nameStr, sizeStr, timeStr, submStr;
135
    int start, end, equals, underscore, comma;
136
    int object, size, subm;
137
    long time;
138

    
139
    for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
140
      {
141
      start = end = 0;
142
      recordStr = preferences.getString("scores_record"+scramble, "");
143

    
144
      while( end!=-1 )
145
        {
146
        end = recordStr.indexOf(" ", start);
147

    
148
        if( end==-1 ) subStr = recordStr.substring(start);
149
        else          subStr = recordStr.substring(start,end);
150

    
151
        start = end+1;
152

    
153
        underscore = subStr.indexOf("_");
154
        equals = subStr.indexOf("=");
155
        comma = subStr.indexOf(",");
156

    
157
        if( underscore>=0 && equals>=0 && comma>=0 )
158
          {
159
          nameStr = subStr.substring(0,underscore);
160
          sizeStr = subStr.substring(underscore+1, equals);
161
          timeStr = subStr.substring(equals+1,comma);
162
          submStr = subStr.substring(comma+1);
163

    
164
          object = RubikObjectList.getOrdinal(nameStr);
165
          size   = RubikObjectList.getSize(object,Integer.parseInt(sizeStr));
166
          time   = Long.parseLong(timeStr);
167
          subm   = Integer.parseInt(submStr);
168

    
169
          if( object>=0 && object< NUM_OBJECTS && size>=0 && size<MAX_SIZE && subm>=0 && subm<=1 )
170
            {
171
            mRecords  [object][size][scramble] = time;
172
            mSubmitted[object][size][scramble] = subm;
173

    
174
            if( time<NO_RECORD )
175
              {
176
              android.util.Log.e("solv", "Set record for: object="+object+" size="+size+" scramble="+scramble+" time: "+time+" submitted: "+subm);
177
              }
178
            }
179
          else
180
            {
181
            android.util.Log.e("solv", "error: object="+object+" size="+size);
182
            }
183
          }
184
        }
185
      }
186

    
187
    mName           = preferences.getString("scores_name"  , "YOU" );
188
    mNameIsVerified = preferences.getBoolean("scores_isVerified", false);
189
    mNumPlays       = preferences.getInt("scores_numPlays", 0);
190
    mNumRuns        = preferences.getInt("scores_numRuns" , 0);
191
    mDeviceID       = preferences.getInt("scores_deviceid",-1);
192

    
193
    if( mDeviceID==-1 ) mDeviceID = getDeviceID();
194
    }
195

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

    
198
  public boolean setRecord(int object, int size, int scramble, long timeTaken)
199
    {
200
    int maxsize = RubikObjectList.getObject(object).getSizes().length;
201

    
202
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && scramble>=1 && scramble<=MAX_SCRAMBLE )
203
      {
204
      if( mRecords[object][size][scramble-1]> timeTaken )
205
        {
206
        mRecords[object][size][scramble-1] = timeTaken;
207
        return true;
208
        }
209
      }
210

    
211
    return false;
212
    }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

    
216
  public void incrementNumPlays()
217
    {
218
    mNumPlays++;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  public void incrementNumRuns()
224
    {
225
    mNumRuns++;
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229
// TODO
230

    
231
  public void setName(String newName)
232
    {
233
    mName = newName;
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
// TODO
238

    
239
  public void successfulSubmit()
240
    {
241
    mNameIsVerified = true;
242

    
243
    for(int i=0; i<NUM_OBJECTS; i++)
244
      for(int j=0; j<MAX_SIZE   ; j++)
245
        for(int k=0; k<MAX_SCRAMBLE; k++)
246
          {
247
          mSubmitted[i][j][k]=1;
248
          }
249
    }
250

    
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

    
253
  public void setCountry(Context context)
254
    {
255
    TelephonyManager tM =((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
256

    
257
    if( tM!=null )
258
      {
259
      mCountry = tM.getSimCountryIso();
260

    
261
      if( mCountry==null || mCountry.length()<=1 )
262
        {
263
        mCountry = tM.getNetworkCountryIso();
264
        }
265
      }
266

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

    
271
    if( mCountry.equals("do") ) mCountry = "dm";
272
    }
273

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

    
276
  int getDeviceID()
277
    {
278
    int id;
279

    
280
    try
281
      {
282
      String s = UUID.randomUUID().toString();
283
      id = (s!=null ? s.hashCode():0);
284
      }
285
    catch(Exception ex)
286
      {
287
      id = 0;
288
      android.util.Log.e("scores", "Exception in getDeviceID()");
289
      }
290

    
291
    return id<0 ? -id : id;
292
    }
293

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

    
296
  public long getRecord(int object, int size, int scramble)
297
    {
298
    int maxsize = RubikObjectList.getObject(object).getSizes().length;
299

    
300
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && scramble>=0 && scramble<MAX_SCRAMBLE )
301
      {
302
      return mRecords[object][size][scramble];
303
      }
304

    
305
    return -1;
306
    }
307

    
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309

    
310
  public boolean isSubmitted(int object, int size, int scramble)
311
    {
312
    int maxsize = RubikObjectList.getObject(object).getSizes().length;
313

    
314
    if( object>=0 && object<NUM_OBJECTS && size>=0 && size<maxsize && scramble>=0 && scramble<MAX_SCRAMBLE )
315
      {
316
      return mSubmitted[object][size][scramble]==1;
317
      }
318

    
319
    return false;
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

    
324
  boolean isVerified()
325
    {
326
    return mNameIsVerified;
327
    }
328

    
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330

    
331
  int getNumPlays()
332
    {
333
    return mNumPlays;
334
    }
335

    
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337

    
338
  int getNumRuns()
339
    {
340
    return mNumRuns;
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  public String getName()
346
    {
347
    return mName;
348
    }
349

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

    
352
  public String getCountry()
353
    {
354
    return mCountry;
355
    }
356

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

    
359
  private String getUnsubmittedList(int mode)
360
    {
361
    RubikObjectList list;
362
    StringBuilder builder = new StringBuilder();
363
    boolean first = true;
364
    int[] sizes;
365
    int length;
366

    
367
    for(int object=0; object<NUM_OBJECTS; object++)
368
      {
369
      list = RubikObjectList.getObject(object);
370
      sizes = list.getSizes();
371
      length = sizes.length;
372

    
373
      for(int size=0; size<length; size++)
374
        {
375
        for(int scramble=0; scramble<MAX_SCRAMBLE; scramble++)
376
          {
377
          if( mSubmitted[object][size][scramble]==0 && mRecords[object][size][scramble]<NO_RECORD )
378
            {
379
            if( !first ) builder.append(',');
380
            else         first=false;
381

    
382
            switch(mode)
383
              {
384
              case 0: builder.append(list.name());
385
                      builder.append("_");
386
                      builder.append(sizes[size]);
387
                      break;
388
              case 1: builder.append(scramble);
389
                      break;
390
              case 2: builder.append(mRecords[object][size][scramble]);
391
                      break;
392
              }
393
            }
394
          }
395
        }
396
      }
397

    
398
    return builder.toString();
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  String getUnsubmittedObjlist()
404
    {
405
    return getUnsubmittedList(0);
406
    }
407

    
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409

    
410
  String getUnsubmittedLevellist()
411
    {
412
    return getUnsubmittedList(1);
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  String getUnsubmittedTimelist()
418
    {
419
    return getUnsubmittedList(2);
420
    }
421
  }
(1-1/2)