Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikObjectLibInterface.java @ 240bf467

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 void requestReview(RubikActivity act)
143
    {
144
    final RubikScores scores = RubikScores.getInstance();
145
    int numWins = scores.incrementNumWins();
146
    int numRuns = scores.getNumRuns();
147

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

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

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

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

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  public void onScrambleEffectFinished()
196
    {
197
    RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
198

    
199
    if( play.shouldReactToEndOfScrambling() )
200
      {
201
      RubikActivity act = mAct.get();
202
      RubikScores.getInstance().incrementNumPlays();
203

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

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

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

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

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

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

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253

    
254
  public void failedToDrag()
255
    {
256
    ScreenList curr = ScreenList.getCurrentScreen();
257

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

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276

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

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

    
289
  public void onObjectCreated(long time)
290
    {
291

    
292
    }
293

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

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

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

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

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

    
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340

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

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

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  private void reportThreadProblem(int place, long pause, long resume, long time)
362
    {
363
    String error = EffectMessageSender.reportState();
364

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

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380

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

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

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

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

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

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

    
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427

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

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

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

    
448
      reportRecord(act,startTime,endTime,debug,scrambleNum);
449
      requestReview(act);
450

    
451
      switch(mIsNewRecord)
452
        {
453
        case RECORD_FIRST  : /*
454
                             // temporarily switch off the 'stars' animation
455
                             RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
456
                             int level = play.getLevel();
457
                             RubikScores scores = RubikScores.getInstance();
458
                             int totStars = scores.getNumStars();
459
                             int newStars = RubikObjectList.computeNumStars(level);
460
                             DistortedScreen screen = act.getScreen();
461

    
462
                             OverlayStars stars = new OverlayStars();
463
                             DataStars data  = new DataStars(totStars,newStars,act.getResources());
464
                             stars.startOverlay(screen,this,data);
465
                             break;
466
                             */
467
        case RECORD_NEW    : RubikDialogNewRecord d2 = new RubikDialogNewRecord();
468
                             d2.setArguments(bundle);
469
                             d2.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
470
                             break;
471
        case RECORD_NOT_NEW: RubikDialogSolved d3 = new RubikDialogSolved();
472
                             d3.setArguments(bundle);
473
                             d3.show( act.getSupportFragmentManager(), RubikDialogSolved.getDialogTag() );
474
                             break;
475
        }
476

    
477
      act.runOnUiThread(new Runnable()
478
        {
479
        @Override
480
        public void run()
481
          {
482
          ScreenList.switchScreen( act, ScreenList.DONE);
483
          }
484
        });
485
      }
486
    }
487

    
488
///////////////////////////////////////////////////////////////////////////////////////////////////
489

    
490
  public void overlayFinished(long id)
491
    {
492
    RubikActivity act = mAct.get();
493
    Bundle bundle = new Bundle();
494
    bundle.putLong("time", mNewRecord );
495

    
496
    RubikDialogNewRecord d2 = new RubikDialogNewRecord();
497
    d2.setArguments(bundle);
498
    d2.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
499
    }
500
}
(2-2/4)