Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikObjectLibInterface.java @ 4483b119

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.dialogs.RubikDialogScoresView;
26
import org.distorted.library.main.DistortedScreen;
27
import org.distorted.library.message.EffectMessageSender;
28

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

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

    
50
import java.lang.ref.WeakReference;
51

    
52
import static org.distorted.external.RubikScores.RECORD_FIRST;
53
import static org.distorted.external.RubikScores.RECORD_NEW;
54
import static org.distorted.external.RubikScores.RECORD_NOT_NEW;
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

    
58
public class RubikObjectLibInterface implements ObjectLibInterface, ListenerOverlay
59
{
60
  private final WeakReference<RubikActivity> mAct;
61
  private int mIsNewRecord;
62
  private int mNewRecord;
63
  private int mLastCubitColor, mLastCubit, mLastCubitFace;
64

    
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

    
67
  RubikObjectLibInterface(RubikActivity act)
68
    {
69
    mAct = new WeakReference<>(act);
70
    mLastCubitColor = -1;
71
    }
72

    
73
///////////////////////////////////////////////////////////////////////////////////////////////////
74

    
75
  private void analyticsReport(RubikActivity act, String message, String name, long timeBegin)
76
    {
77
    long elapsed = System.currentTimeMillis() - timeBegin;
78
    String msg = message+" startTime: "+timeBegin+" elapsed: "+elapsed+" name: "+name;
79

    
80
    if( BuildConfig.DEBUG )
81
       {
82
       android.util.Log.d("libInterface", msg);
83
       }
84
    else
85
      {
86
      FirebaseAnalytics analytics = act.getAnalytics();
87

    
88
      if( analytics!=null )
89
        {
90
        Bundle bundle = new Bundle();
91
        bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, msg);
92
        analytics.logEvent(FirebaseAnalytics.Event.SHARE, bundle);
93
        }
94
      }
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98

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

    
109
    String record = objName+" level "+level+" time "+mNewRecord+" isNew: "+mIsNewRecord+" scrambleNum: "+scrambleNum;
110

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

    
128
      FirebaseAnalytics analytics = act.getAnalytics();
129

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

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142

    
143
  private Bundle createDialogBundle()
144
    {
145
    Bundle bundle = new Bundle();
146
    String arg = RubikDialogScoresView.formatRecord(mNewRecord);
147
    bundle.putString("argument", arg );
148
    return bundle;
149
    }
150

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

    
153
  private void requestReview(RubikActivity act)
154
    {
155
    final RubikScores scores = RubikScores.getInstance();
156
    int numWins = scores.incrementNumWins();
157
    int numRuns = scores.getNumRuns();
158

    
159
    if( numRuns==3 || numRuns==6 || numWins==7 || numWins==30 || numWins==50 || numWins==80 || numWins==100)
160
      {
161
      final long timeBegin = System.currentTimeMillis();
162
      final ReviewManager manager = ReviewManagerFactory.create(act);
163
      Task<ReviewInfo> request = manager.requestReviewFlow();
164

    
165
      request.addOnCompleteListener(new OnCompleteListener<ReviewInfo>()
166
        {
167
        @Override
168
        public void onComplete (@NonNull Task<ReviewInfo> task)
169
          {
170
          if (task.isSuccessful())
171
            {
172
            final String name = scores.getName();
173
            ReviewInfo reviewInfo = task.getResult();
174
            Task<Void> flow = manager.launchReviewFlow(act, reviewInfo);
175

    
176
            flow.addOnFailureListener(new OnFailureListener()
177
              {
178
              @Override
179
              public void onFailure(Exception e)
180
                {
181
                analyticsReport(act,"Failed", name, timeBegin);
182
                }
183
              });
184

    
185
            flow.addOnCompleteListener(new OnCompleteListener<Void>()
186
              {
187
              @Override
188
              public void onComplete(@NonNull Task<Void> task)
189
                {
190
                analyticsReport(act,"Complete", name, timeBegin);
191
                }
192
              });
193
            }
194
          else
195
            {
196
            String name = scores.getName();
197
            analyticsReport(act,"Not Successful", name, timeBegin);
198
            }
199
          }
200
        });
201
      }
202
    }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
  public void onScrambleEffectFinished()
207
    {
208
    RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
209

    
210
    if( play.shouldReactToEndOfScrambling() )
211
      {
212
      RubikActivity act = mAct.get();
213
      RubikScores.getInstance().incrementNumPlays();
214

    
215
      act.runOnUiThread(new Runnable()
216
        {
217
        @Override
218
        public void run()
219
          {
220
          ScreenList.switchScreen( act, ScreenList.READ);
221
          ObjectControl control = act.getControl();
222
          control.unblockEverything();
223
          }
224
        });
225
      }
226
    }
227

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

    
230
  public void onFinishRotation(int axis, int row, int angle)
231
    {
232
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
233
      {
234
      RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
235
      solv.addMove(mAct.get(), axis, row, angle);
236
      }
237
    if( ScreenList.getCurrentScreen()== ScreenList.PLAY )
238
      {
239
      RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
240
      play.addMove(mAct.get(), axis, row, angle);
241
      }
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

    
246
  public void onBeginRotation()
247
    {
248
    if( ScreenList.getCurrentScreen()== ScreenList.READ )
249
      {
250
      RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
251
      solving.resetElapsed();
252
      RubikActivity act = mAct.get();
253

    
254
      act.runOnUiThread(new Runnable()
255
        {
256
        @Override
257
        public void run()
258
          {
259
          ScreenList.switchScreen( act, ScreenList.SOLV);
260
          }
261
        });
262
      }
263
    }
264

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

    
267
  public void failedToDrag()
268
    {
269
    ScreenList curr = ScreenList.getCurrentScreen();
270

    
271
    if( curr==ScreenList.PLAY )
272
      {
273
      RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
274
      play.reddenLock(mAct.get());
275
      }
276
    else if( curr==ScreenList.READ )
277
      {
278
      RubikScreenReady read = (RubikScreenReady) ScreenList.READ.getScreenClass();
279
      read.reddenLock(mAct.get());
280
      }
281
    else if( curr==ScreenList.SOLV )
282
      {
283
      RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
284
      solv.reddenLock(mAct.get());
285
      }
286
    }
287

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

    
290
  public void onSolved()
291
    {
292
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
293
      {
294
      RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
295
      mNewRecord = solving.stopTimerAndGetRecord();
296
      mIsNewRecord = solving.setRecord();
297
      }
298
    }
299

    
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301

    
302
  public void onObjectCreated(long time)
303
    {
304

    
305
    }
306

    
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

    
309
  public void reportProblem(String problem, boolean recordException)
310
    {
311
    if( BuildConfig.DEBUG )
312
      {
313
      android.util.Log.e("libInterface", problem);
314
      }
315
    else
316
      {
317
      if( recordException )
318
        {
319
        Exception ex = new Exception(problem);
320
        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
321
        crashlytics.setCustomKey("problem" , problem);
322
        crashlytics.recordException(ex);
323
        }
324
      else
325
        {
326
        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
327
        crashlytics.log(problem);
328
        }
329
      }
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

    
334
  private void reportScramblingProblem(int place, long pause, long resume, long time)
335
    {
336
    String error = "SCRAMBLING BLOCK "+place+" blocked for "+time;
337

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

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  private void reportRotationProblem(int place, long pause, long resume, long time)
355
    {
356
    String error = "ROTATION BLOCK "+place+" blocked for "+time;
357

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

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  private void reportThreadProblem(int place, long pause, long resume, long time)
375
    {
376
    String error = EffectMessageSender.reportState();
377

    
378
    if( BuildConfig.DEBUG )
379
       {
380
       android.util.Log.e("libInterface", error);
381
       }
382
    else
383
      {
384
      Exception ex = new Exception(error);
385
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
386
      crashlytics.setCustomKey("pause" , pause  );
387
      crashlytics.setCustomKey("resume", resume );
388
      crashlytics.recordException(ex);
389
      }
390
    }
391

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393

    
394
  public void reportBlockProblem(int type, int place, long pause, long resume, long time)
395
    {
396
    switch(type)
397
      {
398
      case BlockController.TYPE_SCRAMBLING: reportScramblingProblem(place,pause,resume,time); break;
399
      case BlockController.TYPE_ROTATION  : reportRotationProblem(place,pause,resume,time); break;
400
      case BlockController.TYPE_THREAD    : reportThreadProblem(place,pause,resume,time); break;
401
      }
402
    }
403

    
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405

    
406
  public void reportJSONError(String error, int ordinal)
407
    {
408
    RubikObject object = RubikObjectList.getObject(ordinal);
409
    String name = object==null ? "NULL" : object.getUpperName();
410

    
411
    if( BuildConfig.DEBUG )
412
       {
413
       android.util.Log.e("libInterface", "name="+name+" JSON error: "+error);
414
       }
415
    else
416
      {
417
      Exception ex = new Exception(error);
418
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
419
      crashlytics.setCustomKey("name" , name );
420
      crashlytics.setCustomKey("JSONerror", error );
421
      crashlytics.recordException(ex);
422
      }
423
    }
424

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

    
427
  public void onReplaceModeDown(int cubit, int face)
428
    {
429
    RubikScreenSolver solver = (RubikScreenSolver) ScreenList.SVER.getScreenClass();
430
    int color = solver.getCurrentColor();
431
    int currObject = RubikObjectList.getCurrObject();
432
    mLastCubitColor = SolverMain.cubitIsLocked(currObject,cubit);
433
    mLastCubit = cubit;
434
    mLastCubitFace = face;
435
    ObjectControl control = mAct.get().getControl();
436
    control.setTextureMap( cubit, face, color );
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441
  public void onReplaceModeUp()
442
    {
443
    if( mLastCubitColor>=0 )
444
      {
445
      ObjectControl control = mAct.get().getControl();
446
      control.setTextureMap( mLastCubit, mLastCubitFace, mLastCubitColor );
447
      mLastCubitColor = -1;
448
      }
449
    }
450

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

    
453
  public void onWinEffectFinished(long startTime, long endTime, String debug, int scrambleNum)
454
    {
455
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
456
      {
457
      RubikActivity act = mAct.get();
458
      reportRecord(act,startTime,endTime,debug,scrambleNum);
459
      requestReview(act);
460

    
461
      switch(mIsNewRecord)
462
        {
463
        case RECORD_FIRST  : if( RubikActivity.USE_IAP )
464
                                {
465
                                RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
466
                                int level = play.getLevel();
467
                                RubikScores scores = RubikScores.getInstance();
468
                                int newStars = scores.computeNumStars(level);
469
                                int totStars = scores.getNumStars();
470
                                scores.changeNumStars(newStars);
471
                                DistortedScreen screen = act.getScreen();
472
                                OverlayStars stars = new OverlayStars();
473
                                DataStars data  = new DataStars(totStars,newStars,act.getResources());
474
                                stars.startOverlay(screen,this,data);
475
                                }
476
                             else
477
                                {
478
                                Bundle bundle = createDialogBundle();
479
                                RubikDialogNewRecord d2 = new RubikDialogNewRecord();
480
                                d2.setArguments(bundle);
481
                                d2.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
482
                                }
483
                             break;
484
        case RECORD_NEW    : Bundle byes = createDialogBundle();
485
                             RubikDialogNewRecord dyes = new RubikDialogNewRecord();
486
                             dyes.setArguments(byes);
487
                             dyes.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
488
                             break;
489
        case RECORD_NOT_NEW: Bundle bno = createDialogBundle();
490
                             RubikDialogSolved dno = new RubikDialogSolved();
491
                             dno.setArguments(bno);
492
                             dno.show( act.getSupportFragmentManager(), RubikDialogSolved.getDialogTag() );
493
                             break;
494
        }
495

    
496
      act.runOnUiThread(new Runnable()
497
        {
498
        @Override
499
        public void run()
500
          {
501
          ScreenList.switchScreen( act, ScreenList.DONE);
502
          }
503
        });
504
      }
505
    }
506

    
507
///////////////////////////////////////////////////////////////////////////////////////////////////
508

    
509
  public void overlayFinished(long id)
510
    {
511
    RubikActivity act = mAct.get();
512
    Bundle bundle = createDialogBundle();
513
    RubikDialogNewRecord d = new RubikDialogNewRecord();
514
    d.setArguments(bundle);
515
    d.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
516
    }
517
}
(2-2/4)