Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikObjectLibInterface.java @ c02fa107

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
        }
221
        });
222
      }
223
    }
224

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

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

    
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242

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

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

    
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

    
264
  public void failedToDrag()
265
    {
266
    ScreenList curr = ScreenList.getCurrentScreen();
267

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

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

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

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
299
  public void onObjectCreated(long time)
300
    {
301

    
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

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

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

    
331
  private void reportUIProblem(int place, long pause, long resume, long time)
332
    {
333
    String error = "UI BLOCK "+place+" blocked for "+time;
334

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

    
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350

    
351
  private void reportTouchProblem(int place, long pause, long resume, long time)
352
    {
353
    String error = "TOUCH BLOCK "+place+" blocked for "+time;
354

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

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370

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

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

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  public void reportBlockProblem(int type, int place, long pause, long resume, long time)
392
    {
393
    switch(type)
394
      {
395
      case BlockController.TYPE_UI    : reportUIProblem(place,pause,resume,time); break;
396
      case BlockController.TYPE_TOUCH : reportTouchProblem(place,pause,resume,time); break;
397
      case BlockController.TYPE_THREAD: reportThreadProblem(place,pause,resume,time); break;
398
      }
399
    }
400

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

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

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

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

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

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437

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

    
448
///////////////////////////////////////////////////////////////////////////////////////////////////
449

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

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

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

    
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

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