Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikObjectLibInterface.java @ 79357e2b

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

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

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

    
49
import java.lang.ref.WeakReference;
50

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

    
55
///////////////////////////////////////////////////////////////////////////////////////////////////
56

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

    
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65

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

    
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

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

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

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

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

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

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

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

    
127
      FirebaseAnalytics analytics = act.getAnalytics();
128

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

    
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141

    
142
  private Bundle createDialogBundle()
143
    {
144
    Bundle bundle = new Bundle();
145
    String arg = String.valueOf((mNewRecord/10)/100.0f);
146
    bundle.putString("argument", arg );
147
    return bundle;
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

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

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

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

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

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

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

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

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

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

    
227
///////////////////////////////////////////////////////////////////////////////////////////////////
228

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

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

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

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

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

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

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

    
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288

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

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  public void onObjectCreated(long time)
302
    {
303

    
304
    }
305

    
306
///////////////////////////////////////////////////////////////////////////////////////////////////
307

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

    
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

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

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

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

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

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

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

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

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

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

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

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

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

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

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

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

    
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

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

    
450
///////////////////////////////////////////////////////////////////////////////////////////////////
451

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

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

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

    
506
///////////////////////////////////////////////////////////////////////////////////////////////////
507

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