Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikObjectLibInterface.java @ 00fcfefa

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 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.main;
11

    
12
import android.os.Bundle;
13

    
14
import androidx.annotation.NonNull;
15

    
16
import com.google.android.play.core.review.ReviewInfo;
17
import com.google.android.play.core.review.ReviewManager;
18
import com.google.android.play.core.review.ReviewManagerFactory;
19
import com.google.android.play.core.tasks.OnCompleteListener;
20
import com.google.android.play.core.tasks.OnFailureListener;
21
import com.google.android.play.core.tasks.Task;
22
import com.google.firebase.analytics.FirebaseAnalytics;
23
import com.google.firebase.crashlytics.FirebaseCrashlytics;
24

    
25
import org.distorted.library.message.EffectMessageSender;
26

    
27
import org.distorted.external.RubikNetwork;
28
import org.distorted.objectlib.BuildConfig;
29
import org.distorted.objectlib.helpers.BlockController;
30
import org.distorted.objectlib.helpers.ObjectLibInterface;
31
import org.distorted.objectlib.main.ObjectControl;
32

    
33
import org.distorted.dialogs.RubikDialogNewRecord;
34
import org.distorted.dialogs.RubikDialogSolved;
35
import org.distorted.external.RubikScores;
36
import org.distorted.objects.RubikObject;
37
import org.distorted.objects.RubikObjectList;
38
import org.distorted.overlays.ListenerOverlay;
39
import org.distorted.screens.RubikScreenPlay;
40
import org.distorted.screens.RubikScreenReady;
41
import org.distorted.screens.RubikScreenSolver;
42
import org.distorted.screens.RubikScreenSolving;
43
import org.distorted.screens.ScreenList;
44
import org.distorted.solvers.SolverMain;
45

    
46
import java.lang.ref.WeakReference;
47

    
48
import static org.distorted.external.RubikScores.RECORD_FIRST;
49
import static org.distorted.external.RubikScores.RECORD_NEW;
50
import static org.distorted.external.RubikScores.RECORD_NOT_NEW;
51

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

    
54
public class RubikObjectLibInterface implements ObjectLibInterface, ListenerOverlay
55
{
56
  private final WeakReference<RubikActivity> mAct;
57
  private int mIsNewRecord;
58
  private long mNewRecord;
59
  private int mLastCubitColor, mLastCubit, mLastCubitFace;
60

    
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

    
63
  RubikObjectLibInterface(RubikActivity act)
64
    {
65
    mAct = new WeakReference<>(act);
66
    mLastCubitColor = -1;
67
    }
68

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

    
71
  private void analyticsReport(RubikActivity act, String message, String name, long timeBegin)
72
    {
73
    long elapsed = System.currentTimeMillis() - timeBegin;
74
    String msg = message+" startTime: "+timeBegin+" elapsed: "+elapsed+" name: "+name;
75

    
76
    if( BuildConfig.DEBUG )
77
       {
78
       android.util.Log.d("libInterface", msg);
79
       }
80
    else
81
      {
82
      FirebaseAnalytics analytics = act.getAnalytics();
83

    
84
      if( analytics!=null )
85
        {
86
        Bundle bundle = new Bundle();
87
        bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, msg);
88
        analytics.logEvent(FirebaseAnalytics.Event.SHARE, bundle);
89
        }
90
      }
91
    }
92

    
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94

    
95
  private void reportRecord(RubikActivity act, long startTime, long endTime, String debug, int scrambleNum)
96
    {
97
    RubikScreenPlay play= (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
98
    RubikScores scores  = RubikScores.getInstance();
99
    int object  = RubikObjectList.getCurrObject();
100
    int level   = play.getLevel();
101
    String name = scores.getName();
102
    RubikObject obj = RubikObjectList.getObject(object);
103
    String objName = obj==null ? "NULL" : obj.getUpperName();
104

    
105
    String record = objName+" level "+level+" time "+mNewRecord+" isNew: "+mIsNewRecord+" scrambleNum: "+scrambleNum;
106

    
107
    if( BuildConfig.DEBUG )
108
       {
109
       android.util.Log.e("libInterface", debug);
110
       android.util.Log.e("libInterface", name);
111
       android.util.Log.e("libInterface", record);
112
       }
113
    else
114
      {
115
      if( level>=9 && mNewRecord<300*level )
116
        {
117
        long timeNow = System.currentTimeMillis();
118
        long elapsed = timeNow - startTime;
119
        String suspicious ="start"+startTime+"end"+endTime+"elapsed"+elapsed+"obj"+objName+"level"+level+"record"+mNewRecord+"scrambles"+scrambleNum+debug;
120
        RubikNetwork network = RubikNetwork.getInstance();
121
        network.suspicious(suspicious,act);
122
        }
123

    
124
      FirebaseAnalytics analytics = act.getAnalytics();
125

    
126
      if( analytics!=null )
127
        {
128
        Bundle bundle = new Bundle();
129
        bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, debug);
130
        bundle.putString(FirebaseAnalytics.Param.CHARACTER, name);
131
        bundle.putString(FirebaseAnalytics.Param.LEVEL, record);
132
        analytics.logEvent(FirebaseAnalytics.Event.LEVEL_UP, bundle);
133
        }
134
      }
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

    
139
  private void requestReview(RubikActivity act)
140
    {
141
    final RubikScores scores = RubikScores.getInstance();
142
    int numWins = scores.incrementNumWins();
143
    int numRuns = scores.getNumRuns();
144

    
145
    if( numRuns==3 || numRuns==6 || numWins==7 || numWins==30 || numWins==50 || numWins==80 || numWins==100)
146
      {
147
      final long timeBegin = System.currentTimeMillis();
148
      final ReviewManager manager = ReviewManagerFactory.create(act);
149
      Task<ReviewInfo> request = manager.requestReviewFlow();
150

    
151
      request.addOnCompleteListener(new OnCompleteListener<ReviewInfo>()
152
        {
153
        @Override
154
        public void onComplete (@NonNull Task<ReviewInfo> task)
155
          {
156
          if (task.isSuccessful())
157
            {
158
            final String name = scores.getName();
159
            ReviewInfo reviewInfo = task.getResult();
160
            Task<Void> flow = manager.launchReviewFlow(act, reviewInfo);
161

    
162
            flow.addOnFailureListener(new OnFailureListener()
163
              {
164
              @Override
165
              public void onFailure(Exception e)
166
                {
167
                analyticsReport(act,"Failed", name, timeBegin);
168
                }
169
              });
170

    
171
            flow.addOnCompleteListener(new OnCompleteListener<Void>()
172
              {
173
              @Override
174
              public void onComplete(@NonNull Task<Void> task)
175
                {
176
                analyticsReport(act,"Complete", name, timeBegin);
177
                }
178
              });
179
            }
180
          else
181
            {
182
            String name = scores.getName();
183
            analyticsReport(act,"Not Successful", name, timeBegin);
184
            }
185
          }
186
        });
187
      }
188
    }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
  public void onScrambleEffectFinished()
193
    {
194
    RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
195

    
196
    if( play.shouldReactToEndOfScrambling() )
197
      {
198
      RubikActivity act = mAct.get();
199
      RubikScores.getInstance().incrementNumPlays();
200

    
201
      act.runOnUiThread(new Runnable()
202
        {
203
        @Override
204
        public void run()
205
        {
206
        ScreenList.switchScreen( act, ScreenList.READ);
207
        }
208
        });
209
      }
210
    }
211

    
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

    
214
  public void onFinishRotation(int axis, int row, int angle)
215
    {
216
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
217
      {
218
      RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
219
      solv.addMove(mAct.get(), axis, row, angle);
220
      }
221
    if( ScreenList.getCurrentScreen()== ScreenList.PLAY )
222
      {
223
      RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
224
      play.addMove(mAct.get(), axis, row, angle);
225
      }
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  public void onBeginRotation()
231
    {
232
    if( ScreenList.getCurrentScreen()== ScreenList.READ )
233
      {
234
      RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
235
      solving.resetElapsed();
236
      RubikActivity act = mAct.get();
237

    
238
      act.runOnUiThread(new Runnable()
239
        {
240
        @Override
241
        public void run()
242
          {
243
          ScreenList.switchScreen( act, ScreenList.SOLV);
244
          }
245
        });
246
      }
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  public void failedToDrag()
252
    {
253
    ScreenList curr = ScreenList.getCurrentScreen();
254

    
255
    if( curr==ScreenList.PLAY )
256
      {
257
      RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
258
      play.reddenLock(mAct.get());
259
      }
260
    else if( curr==ScreenList.READ )
261
      {
262
      RubikScreenReady read = (RubikScreenReady) ScreenList.READ.getScreenClass();
263
      read.reddenLock(mAct.get());
264
      }
265
    else if( curr==ScreenList.SOLV )
266
      {
267
      RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
268
      solv.reddenLock(mAct.get());
269
      }
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
  public void onSolved()
275
    {
276
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
277
      {
278
      RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
279
      mNewRecord = solving.stopTimerAndGetRecord();
280
      mIsNewRecord = solving.setRecord();
281
      }
282
    }
283

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

    
286
  public void onObjectCreated(long time)
287
    {
288

    
289
    }
290

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

    
293
  public void reportProblem(String problem, boolean recordException)
294
    {
295
    if( BuildConfig.DEBUG )
296
      {
297
      android.util.Log.e("libInterface", problem);
298
      }
299
    else
300
      {
301
      if( recordException )
302
        {
303
        Exception ex = new Exception(problem);
304
        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
305
        crashlytics.setCustomKey("problem" , problem);
306
        crashlytics.recordException(ex);
307
        }
308
      else
309
        {
310
        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
311
        crashlytics.log(problem);
312
        }
313
      }
314
    }
315

    
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317

    
318
  private void reportUIProblem(int place, long pause, long resume, long time)
319
    {
320
    String error = "UI BLOCK "+place+" blocked for "+time;
321

    
322
    if( BuildConfig.DEBUG )
323
       {
324
       android.util.Log.e("libInterface", error);
325
       }
326
    else
327
      {
328
      Exception ex = new Exception(error);
329
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
330
      crashlytics.setCustomKey("pause" , pause );
331
      crashlytics.setCustomKey("resume", resume );
332
      crashlytics.recordException(ex);
333
      }
334
    }
335

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

    
338
  private void reportTouchProblem(int place, long pause, long resume, long time)
339
    {
340
    String error = "TOUCH BLOCK "+place+" blocked for "+time;
341

    
342
    if( BuildConfig.DEBUG )
343
       {
344
       android.util.Log.e("libInterface", error);
345
       }
346
    else
347
      {
348
      Exception ex = new Exception(error);
349
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
350
      crashlytics.setCustomKey("pause" , pause );
351
      crashlytics.setCustomKey("resume", resume);
352
      crashlytics.recordException(ex);
353
      }
354
    }
355

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

    
358
  private void reportThreadProblem(int place, long pause, long resume, long time)
359
    {
360
    String error = EffectMessageSender.reportState();
361

    
362
    if( BuildConfig.DEBUG )
363
       {
364
       android.util.Log.e("libInterface", error);
365
       }
366
    else
367
      {
368
      Exception ex = new Exception(error);
369
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
370
      crashlytics.setCustomKey("pause" , pause  );
371
      crashlytics.setCustomKey("resume", resume );
372
      crashlytics.recordException(ex);
373
      }
374
    }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

    
378
  public void reportBlockProblem(int type, int place, long pause, long resume, long time)
379
    {
380
    switch(type)
381
      {
382
      case BlockController.TYPE_UI    : reportUIProblem(place,pause,resume,time); break;
383
      case BlockController.TYPE_TOUCH : reportTouchProblem(place,pause,resume,time); break;
384
      case BlockController.TYPE_THREAD: reportThreadProblem(place,pause,resume,time); break;
385
      }
386
    }
387

    
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389

    
390
  public void reportJSONError(String error, int ordinal)
391
    {
392
    RubikObject object = RubikObjectList.getObject(ordinal);
393
    String name = object==null ? "NULL" : object.getUpperName();
394

    
395
    if( BuildConfig.DEBUG )
396
       {
397
       android.util.Log.e("libInterface", "name="+name+" JSON error: "+error);
398
       }
399
    else
400
      {
401
      Exception ex = new Exception(error);
402
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
403
      crashlytics.setCustomKey("name" , name );
404
      crashlytics.setCustomKey("JSONerror", error );
405
      crashlytics.recordException(ex);
406
      }
407
    }
408

    
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

    
411
  public void onReplaceModeDown(int cubit, int face)
412
    {
413
    RubikScreenSolver solver = (RubikScreenSolver) ScreenList.SVER.getScreenClass();
414
    int color = solver.getCurrentColor();
415
    int currObject = RubikObjectList.getCurrObject();
416
    mLastCubitColor = SolverMain.cubitIsLocked(currObject,cubit);
417
    mLastCubit = cubit;
418
    mLastCubitFace = face;
419
    ObjectControl control = mAct.get().getControl();
420
    control.setTextureMap( cubit, face, color );
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

    
425
  public void onReplaceModeUp()
426
    {
427
    if( mLastCubitColor>=0 )
428
      {
429
      ObjectControl control = mAct.get().getControl();
430
      control.setTextureMap( mLastCubit, mLastCubitFace, mLastCubitColor );
431
      mLastCubitColor = -1;
432
      }
433
    }
434

    
435
///////////////////////////////////////////////////////////////////////////////////////////////////
436

    
437
  public void onWinEffectFinished(long startTime, long endTime, String debug, int scrambleNum)
438
    {
439
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
440
      {
441
      RubikActivity act = mAct.get();
442
      Bundle bundle = new Bundle();
443
      bundle.putLong("time", mNewRecord );
444

    
445
      reportRecord(act,startTime,endTime,debug,scrambleNum);
446
      requestReview(act);
447

    
448
      switch(mIsNewRecord)
449
        {
450
        case RECORD_FIRST  : RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
451
                             int level = play.getLevel();
452
                             RubikScores scores = RubikScores.getInstance();
453
                             int newStars = scores.computeNumStars(level);
454
                             scores.changeNumStars(newStars);
455
                             RubikDialogNewRecord d1 = new RubikDialogNewRecord();
456
                             d1.setArguments(bundle);
457
                             d1.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
458
                             break;
459
        case RECORD_NEW    : RubikDialogNewRecord d2 = new RubikDialogNewRecord();
460
                             d2.setArguments(bundle);
461
                             d2.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
462
                             break;
463
        case RECORD_NOT_NEW: RubikDialogSolved d3 = new RubikDialogSolved();
464
                             d3.setArguments(bundle);
465
                             d3.show( act.getSupportFragmentManager(), RubikDialogSolved.getDialogTag() );
466
                             break;
467
        }
468

    
469
      act.runOnUiThread(new Runnable()
470
        {
471
        @Override
472
        public void run()
473
          {
474
          ScreenList.switchScreen( act, ScreenList.DONE);
475
          }
476
        });
477
      }
478
    }
479

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

    
482
  public void overlayFinished(long id)
483
    {
484
    RubikActivity act = mAct.get();
485
    Bundle bundle = new Bundle();
486
    bundle.putLong("time", mNewRecord );
487

    
488
    RubikDialogNewRecord d2 = new RubikDialogNewRecord();
489
    d2.setArguments(bundle);
490
    d2.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
491
    }
492
}
(2-2/4)