Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikObjectLibInterface.java @ 24679c47

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.screens.RubikScreenPlay;
39
import org.distorted.screens.RubikScreenReady;
40
import org.distorted.screens.RubikScreenSolver;
41
import org.distorted.screens.RubikScreenSolving;
42
import org.distorted.screens.ScreenList;
43
import org.distorted.solvers.SolverMain;
44

    
45
import java.lang.ref.WeakReference;
46

    
47
import static org.distorted.external.RubikScores.RECORD_FIRST;
48
import static org.distorted.external.RubikScores.RECORD_NOT_NEW;
49

    
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51

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

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

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

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

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

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

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

    
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

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

    
103
    String record = objName+" level "+level+" time "+mNewRecord+" isNew: "+mIsNewRecord+" scrambleNum: "+scrambleNum;
104

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

    
122
      FirebaseAnalytics analytics = act.getAnalytics();
123

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

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

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

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

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

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

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

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  public void onWinEffectFinished(long startTime, long endTime, String debug, int scrambleNum)
191
    {
192
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
193
      {
194
      RubikActivity act = mAct.get();
195
      Bundle bundle = new Bundle();
196
      bundle.putLong("time", mNewRecord );
197

    
198
      reportRecord(act,startTime,endTime,debug,scrambleNum);
199
      requestReview(act);
200

    
201
      if( mIsNewRecord!=RECORD_NOT_NEW )
202
        {
203
        if( mIsNewRecord==RECORD_FIRST && RubikObjectList.thereAreLockedObjects() )
204
          {
205

    
206
          }
207
        else
208
          {
209
          RubikDialogNewRecord dialog = new RubikDialogNewRecord();
210
          dialog.setArguments(bundle);
211
          dialog.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
212
          }
213
        }
214
      else
215
        {
216
        RubikDialogSolved dialog = new RubikDialogSolved();
217
        dialog.setArguments(bundle);
218
        dialog.show( act.getSupportFragmentManager(), RubikDialogSolved.getDialogTag() );
219
        }
220

    
221
      act.runOnUiThread(new Runnable()
222
        {
223
        @Override
224
        public void run()
225
          {
226
          ScreenList.switchScreen( act, ScreenList.DONE);
227
          }
228
        });
229
      }
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233

    
234
  public void onScrambleEffectFinished()
235
    {
236
    RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
237

    
238
    if( play.shouldReactToEndOfScrambling() )
239
      {
240
      RubikActivity act = mAct.get();
241
      RubikScores.getInstance().incrementNumPlays();
242

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

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
  public void onFinishRotation(int axis, int row, int angle)
257
    {
258
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
259
      {
260
      RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
261
      solv.addMove(mAct.get(), axis, row, angle);
262
      }
263
    if( ScreenList.getCurrentScreen()== ScreenList.PLAY )
264
      {
265
      RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
266
      play.addMove(mAct.get(), axis, row, angle);
267
      }
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
  public void onBeginRotation()
273
    {
274
    if( ScreenList.getCurrentScreen()== ScreenList.READ )
275
      {
276
      RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
277
      solving.resetElapsed();
278
      RubikActivity act = mAct.get();
279

    
280
      act.runOnUiThread(new Runnable()
281
        {
282
        @Override
283
        public void run()
284
          {
285
          ScreenList.switchScreen( act, ScreenList.SOLV);
286
          }
287
        });
288
      }
289
    }
290

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

    
293
  public void failedToDrag()
294
    {
295
    ScreenList curr = ScreenList.getCurrentScreen();
296

    
297
    if( curr==ScreenList.PLAY )
298
      {
299
      RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
300
      play.reddenLock(mAct.get());
301
      }
302
    else if( curr==ScreenList.READ )
303
      {
304
      RubikScreenReady read = (RubikScreenReady) ScreenList.READ.getScreenClass();
305
      read.reddenLock(mAct.get());
306
      }
307
    else if( curr==ScreenList.SOLV )
308
      {
309
      RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
310
      solv.reddenLock(mAct.get());
311
      }
312
    }
313

    
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315

    
316
  public void onSolved()
317
    {
318
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
319
      {
320
      RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
321
      mNewRecord = solving.stopTimerAndGetRecord();
322
      mIsNewRecord = solving.setRecord();
323
      }
324
    }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  public void onObjectCreated(long time)
329
    {
330

    
331
    }
332

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

    
335
  public void reportProblem(String problem, boolean recordException)
336
    {
337
    if( BuildConfig.DEBUG )
338
      {
339
      android.util.Log.e("libInterface", problem);
340
      }
341
    else
342
      {
343
      if( recordException )
344
        {
345
        Exception ex = new Exception(problem);
346
        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
347
        crashlytics.setCustomKey("problem" , problem);
348
        crashlytics.recordException(ex);
349
        }
350
      else
351
        {
352
        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
353
        crashlytics.log(problem);
354
        }
355
      }
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

    
360
  private void reportUIProblem(int place, long pause, long resume, long time)
361
    {
362
    String error = "UI BLOCK "+place+" blocked for "+time;
363

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

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  private void reportTouchProblem(int place, long pause, long resume, long time)
381
    {
382
    String error = "TOUCH BLOCK "+place+" blocked for "+time;
383

    
384
    if( BuildConfig.DEBUG )
385
       {
386
       android.util.Log.e("libInterface", error);
387
       }
388
    else
389
      {
390
      Exception ex = new Exception(error);
391
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
392
      crashlytics.setCustomKey("pause" , pause );
393
      crashlytics.setCustomKey("resume", resume);
394
      crashlytics.recordException(ex);
395
      }
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  private void reportThreadProblem(int place, long pause, long resume, long time)
401
    {
402
    String error = EffectMessageSender.reportState();
403

    
404
    if( BuildConfig.DEBUG )
405
       {
406
       android.util.Log.e("libInterface", error);
407
       }
408
    else
409
      {
410
      Exception ex = new Exception(error);
411
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
412
      crashlytics.setCustomKey("pause" , pause  );
413
      crashlytics.setCustomKey("resume", resume );
414
      crashlytics.recordException(ex);
415
      }
416
    }
417

    
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419

    
420
  public void reportBlockProblem(int type, int place, long pause, long resume, long time)
421
    {
422
    switch(type)
423
      {
424
      case BlockController.TYPE_UI    : reportUIProblem(place,pause,resume,time); break;
425
      case BlockController.TYPE_TOUCH : reportTouchProblem(place,pause,resume,time); break;
426
      case BlockController.TYPE_THREAD: reportThreadProblem(place,pause,resume,time); break;
427
      }
428
    }
429

    
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431

    
432
  public void reportJSONError(String error, int ordinal)
433
    {
434
    RubikObject object = RubikObjectList.getObject(ordinal);
435
    String name = object==null ? "NULL" : object.getUpperName();
436

    
437
    if( BuildConfig.DEBUG )
438
       {
439
       android.util.Log.e("libInterface", "name="+name+" JSON error: "+error);
440
       }
441
    else
442
      {
443
      Exception ex = new Exception(error);
444
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
445
      crashlytics.setCustomKey("name" , name );
446
      crashlytics.setCustomKey("JSONerror", error );
447
      crashlytics.recordException(ex);
448
      }
449
    }
450

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

    
453
  public void onReplaceModeDown(int cubit, int face)
454
    {
455
    RubikScreenSolver solver = (RubikScreenSolver) ScreenList.SVER.getScreenClass();
456
    int color = solver.getCurrentColor();
457
    int currObject = RubikObjectList.getCurrObject();
458
    mLastCubitColor = SolverMain.cubitIsLocked(currObject,cubit);
459
    mLastCubit = cubit;
460
    mLastCubitFace = face;
461
    ObjectControl control = mAct.get().getControl();
462
    control.setTextureMap( cubit, face, color );
463
    }
464

    
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466

    
467
  public void onReplaceModeUp()
468
    {
469
    if( mLastCubitColor>=0 )
470
      {
471
      ObjectControl control = mAct.get().getControl();
472
      control.setTextureMap( mLastCubit, mLastCubitFace, mLastCubitColor );
473
      mLastCubitColor = -1;
474
      }
475
    }
476
}
(2-2/4)