Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikObjectLibInterface.java @ 6142069a

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
///////////////////////////////////////////////////////////////////////////////////////////////////
48

    
49
public class RubikObjectLibInterface implements ObjectLibInterface
50
{
51
  private final WeakReference<RubikActivity> mAct;
52
  private boolean mIsNewRecord;
53
  private long mNewRecord;
54
  private int mLastCubitColor, mLastCubit, mLastCubitFace;
55

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

    
58
  RubikObjectLibInterface(RubikActivity act)
59
    {
60
    mAct = new WeakReference<>(act);
61
    mLastCubitColor = -1;
62
    }
63

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

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

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

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

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

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

    
100
    String record = objName+" level "+level+" time "+mNewRecord+" isNew: "+mIsNewRecord+" scrambleNum: "+scrambleNum;
101

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

    
119
      FirebaseAnalytics analytics = act.getAnalytics();
120

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

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

    
134
  private void requestReview(RubikActivity act)
135
    {
136
    final RubikScores scores = RubikScores.getInstance();
137
    int numWins = scores.incrementNumWins();
138
    int numRuns = scores.getNumRuns();
139

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

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

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

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

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

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

    
195
      reportRecord(act,startTime,endTime,debug,scrambleNum);
196
      requestReview(act);
197

    
198
      if( mIsNewRecord )
199
        {
200
        RubikDialogNewRecord dialog = new RubikDialogNewRecord();
201
        dialog.setArguments(bundle);
202
        dialog.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
203
        }
204
      else
205
        {
206
        RubikDialogSolved dialog = new RubikDialogSolved();
207
        dialog.setArguments(bundle);
208
        dialog.show( act.getSupportFragmentManager(), RubikDialogSolved.getDialogTag() );
209
        }
210

    
211
      act.runOnUiThread(new Runnable()
212
        {
213
        @Override
214
        public void run()
215
          {
216
          ScreenList.switchScreen( act, ScreenList.DONE);
217
          }
218
        });
219
      }
220
    }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

    
224
  public void onScrambleEffectFinished()
225
    {
226
    RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
227

    
228
    if( play.shouldReactToEndOfScrambling() )
229
      {
230
      RubikActivity act = mAct.get();
231
      RubikScores.getInstance().incrementNumPlays();
232

    
233
      act.runOnUiThread(new Runnable()
234
        {
235
        @Override
236
        public void run()
237
        {
238
        ScreenList.switchScreen( act, ScreenList.READ);
239
        }
240
        });
241
      }
242
    }
243

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

    
246
  public void onFinishRotation(int axis, int row, int angle)
247
    {
248
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
249
      {
250
      RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
251
      solv.addMove(mAct.get(), axis, row, angle);
252
      }
253
    if( ScreenList.getCurrentScreen()== ScreenList.PLAY )
254
      {
255
      RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
256
      play.addMove(mAct.get(), axis, row, angle);
257
      }
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

    
262
  public void onBeginRotation()
263
    {
264
    if( ScreenList.getCurrentScreen()== ScreenList.READ )
265
      {
266
      RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
267
      solving.resetElapsed();
268
      RubikActivity act = mAct.get();
269

    
270
      act.runOnUiThread(new Runnable()
271
        {
272
        @Override
273
        public void run()
274
          {
275
          ScreenList.switchScreen( act, ScreenList.SOLV);
276
          }
277
        });
278
      }
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
  public void failedToDrag()
284
    {
285
    ScreenList curr = ScreenList.getCurrentScreen();
286

    
287
    if( curr==ScreenList.PLAY )
288
      {
289
      RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
290
      play.reddenLock(mAct.get());
291
      }
292
    else if( curr==ScreenList.READ )
293
      {
294
      RubikScreenReady read = (RubikScreenReady) ScreenList.READ.getScreenClass();
295
      read.reddenLock(mAct.get());
296
      }
297
    else if( curr==ScreenList.SOLV )
298
      {
299
      RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
300
      solv.reddenLock(mAct.get());
301
      }
302
    }
303

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

    
306
  public void onSolved()
307
    {
308
    if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
309
      {
310
      RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
311
      mNewRecord = solving.getRecord();
312

    
313
      if( mNewRecord< 0 )
314
        {
315
        mNewRecord = -mNewRecord;
316
        mIsNewRecord = false;
317
        }
318
      else
319
        {
320
        mIsNewRecord = true;
321
        }
322
      }
323
    }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
  public void onObjectCreated(long time)
328
    {
329

    
330
    }
331

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

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

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

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

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

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

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

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

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398

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

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

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418

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

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

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

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

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

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

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465

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