Project

General

Profile

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

magiccube / src / main / java / org / distorted / playui / PlayLibInterface.java @ 97201782

1 9530f6b0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2 7ee8337b leszek
// Copyright 2023 Leszek Koltunski                                                               //
3 9530f6b0 Leszek Koltunski
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 44fec653 Leszek Koltunski
// 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 9530f6b0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10 7ee8337b leszek
package org.distorted.playui;
11 ce31f774 Leszek Koltunski
12 18b0ae9c leszek
import static org.distorted.external.RubikScores.RECORD_FIRST;
13
import static org.distorted.external.RubikScores.RECORD_NEW;
14
import static org.distorted.external.RubikScores.RECORD_NOT_NEW;
15
16
import android.os.Bundle;
17
18
import androidx.annotation.NonNull;
19
20 88b94310 Leszek Koltunski
import java.lang.ref.WeakReference;
21
22 18b0ae9c leszek
import com.google.android.play.core.review.ReviewInfo;
23
import com.google.android.play.core.review.ReviewManager;
24
import com.google.android.play.core.review.ReviewManagerFactory;
25
import com.google.android.play.core.tasks.OnCompleteListener;
26
import com.google.android.play.core.tasks.OnFailureListener;
27
import com.google.android.play.core.tasks.Task;
28
import com.google.firebase.analytics.FirebaseAnalytics;
29 9530f6b0 Leszek Koltunski
import com.google.firebase.crashlytics.FirebaseCrashlytics;
30
31 18b0ae9c leszek
import org.distorted.dialogs.RubikDialogNewRecord;
32
import org.distorted.dialogs.RubikDialogScoresView;
33
import org.distorted.dialogs.RubikDialogSolved;
34
import org.distorted.external.RubikNetwork;
35
import org.distorted.external.RubikScores;
36 9530f6b0 Leszek Koltunski
import org.distorted.library.message.EffectMessageSender;
37
import org.distorted.objectlib.helpers.BlockController;
38
import org.distorted.objectlib.helpers.ObjectLibInterface;
39 18b0ae9c leszek
import org.distorted.objectlib.main.ObjectControl;
40 e09119d8 Leszek Koltunski
import org.distorted.objects.RubikObject;
41
import org.distorted.objects.RubikObjectList;
42 7ee8337b leszek
import org.distorted.main.BuildConfig;
43 9530f6b0 Leszek Koltunski
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45
46 7ee8337b leszek
public class PlayLibInterface implements ObjectLibInterface
47 9530f6b0 Leszek Koltunski
{
48 7ee8337b leszek
  private final WeakReference<PlayActivity> mAct;
49 18b0ae9c leszek
  private int mIsNewRecord;
50
  private int mNewRecord;
51
  private boolean mReviewAsked;
52
  private int mNumRotations, mNumScrambles;
53 88b94310 Leszek Koltunski
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55
56 7ee8337b leszek
  PlayLibInterface(PlayActivity act)
57 88b94310 Leszek Koltunski
    {
58
    mAct = new WeakReference<>(act);
59 18b0ae9c leszek
    mReviewAsked = false;
60
    mNumRotations = 0;
61
    mNumScrambles = 0;
62 88b94310 Leszek Koltunski
    }
63
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65
66 9530f6b0 Leszek Koltunski
  public void onObjectCreated(long time) { }
67
  public void onReplaceModeDown(int cubit, int face) { }
68
  public void onReplaceModeUp() { }
69 88b94310 Leszek Koltunski
70 18b0ae9c leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
71
72
  private void analyticsReport(PlayActivity act, String message, String name, long timeBegin)
73
    {
74
    long elapsed = System.currentTimeMillis() - timeBegin;
75
    String msg = message+" startTime: "+timeBegin+" elapsed: "+elapsed+" name: "+name;
76
77
    if( BuildConfig.DEBUG )
78
      {
79
      android.util.Log.d("libInterface", msg);
80
      }
81
    else
82
      {
83
      FirebaseAnalytics analytics = act.getAnalytics();
84
85
      if( analytics!=null )
86
        {
87
        Bundle bundle = new Bundle();
88
        bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, msg);
89
        analytics.logEvent(FirebaseAnalytics.Event.SHARE, bundle);
90
        }
91
      }
92
    }
93
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95
96
  private void reportRecord(PlayActivity act, long startTime, long endTime, String debug, int scrambleNum)
97
    {
98
    RubikScores scores  = RubikScores.getInstance();
99
    int object  = RubikObjectList.getCurrObject();
100
    String name = scores.getName();
101
    RubikObject obj = RubikObjectList.getObject(object);
102
    String objName = obj==null ? "NULL" : obj.getUpperName();
103
104
    String record = objName+" time "+mNewRecord+" isNew: "+mIsNewRecord+" scrambleNum: "+scrambleNum;
105
106
    if( BuildConfig.DEBUG )
107
      {
108
      android.util.Log.e("libInterface", debug);
109
      android.util.Log.e("libInterface", name);
110
      android.util.Log.e("libInterface", record);
111
      }
112
    else
113
      {
114
      if( scrambleNum>=9 && mNewRecord<300*scrambleNum )
115
        {
116
        long timeNow = System.currentTimeMillis();
117
        long elapsed = timeNow - startTime;
118
        String suspicious ="start"+startTime+"end"+endTime+"elapsed"+elapsed+"obj"+objName+"record"+mNewRecord+"scrambles"+scrambleNum+debug;
119
        RubikNetwork network = RubikNetwork.getInstance();
120
        network.suspicious(suspicious,act);
121
        }
122
123
      FirebaseAnalytics analytics = act.getAnalytics();
124
125
      if( analytics!=null )
126
        {
127
        Bundle bundle = new Bundle();
128
        bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, debug);
129
        bundle.putString(FirebaseAnalytics.Param.CHARACTER, name);
130
        bundle.putString(FirebaseAnalytics.Param.LEVEL, record);
131
        analytics.logEvent(FirebaseAnalytics.Event.LEVEL_UP, bundle);
132
        }
133
      }
134
    }
135
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137
138
  private Bundle createDialogBundle()
139
    {
140
    Bundle bundle = new Bundle();
141
    String arg = RubikDialogScoresView.formatRecord(mNewRecord);
142
    bundle.putString("argument", arg );
143
    return bundle;
144
    }
145
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147
148
  private void requestReview(PlayActivity act)
149
    {
150
    android.util.Log.e("D", "ASKING FOR REVIEW");
151
152
    mReviewAsked = true;
153
    final String name = RubikScores.getInstance().getName();
154
    final long timeBegin = System.currentTimeMillis();
155
    final ReviewManager manager = ReviewManagerFactory.create(act);
156
    Task<ReviewInfo> request = manager.requestReviewFlow();
157
158
    request.addOnCompleteListener(new OnCompleteListener<ReviewInfo>()
159
      {
160
      @Override
161
      public void onComplete (@NonNull Task<ReviewInfo> task)
162
        {
163
        if (task.isSuccessful())
164
          {
165
          ReviewInfo reviewInfo = task.getResult();
166
          Task<Void> flow = manager.launchReviewFlow(act, reviewInfo);
167
168
          flow.addOnFailureListener(new OnFailureListener()
169
            {
170
            @Override
171
            public void onFailure(Exception e)
172
            {
173
            analyticsReport(act,"Failed", name, timeBegin);
174
            }
175
            });
176
177
          flow.addOnCompleteListener(new OnCompleteListener<Void>()
178
            {
179
            @Override
180
            public void onComplete(@NonNull Task<Void> task)
181
              {
182
              analyticsReport(act,"Complete", name, timeBegin);
183
              }
184
            });
185
          }
186
        else analyticsReport(act,"Not Successful", name, timeBegin);
187
        }
188
      });
189
    }
190
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192
193
  public void onScrambleEffectFinished()
194
    {
195
    if( ScreenList.getCurrentScreen()==ScreenList.SCRA )
196
      {
197
      PlayActivity act = mAct.get();
198
      RubikScores.getInstance().incrementNumPlays();
199
200
      act.runOnUiThread(new Runnable()
201
        {
202
        @Override
203
        public void run()
204
          {
205 e9397ae9 leszek
          ScreenList.switchScreen(act,ScreenList.READ);
206 18b0ae9c leszek
          ObjectControl control = act.getControl();
207
          control.unblockEverything();
208
          }
209
        });
210
      }
211
212
    mNumScrambles++;
213
214
    if( mNumScrambles==10 && !mReviewAsked )
215
      {
216
      PlayActivity act = mAct.get();
217
      requestReview(act);
218
      }
219
    }
220
221 88b94310 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
222
223
  public void onFinishRotation(int axis, int row, int angle)
224
    {
225 18b0ae9c leszek
    mNumRotations++;
226 7ee8337b leszek
    PlayActivity act = mAct.get();
227 88b94310 Leszek Koltunski
228
    if( act!=null )
229
      {
230 15ed3429 leszek
      ScreenList screen = ScreenList.getCurrentScreen();
231
232 18b0ae9c leszek
      if( screen==ScreenList.FREE ||
233
          screen==ScreenList.SOLV  ) ((ScreenBase)screen.getScreenClass()).addMove(act,axis,row,angle);
234
      }
235
236
    if( mNumRotations==40 && !mReviewAsked )
237
      {
238
      requestReview(act);
239
      }
240
    }
241
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243
244
  public void onBeginRotation()
245
    {
246 e9397ae9 leszek
    if( ScreenList.getCurrentScreen()==ScreenList.READ )
247 18b0ae9c leszek
      {
248
      ScreenSolving solving = (ScreenSolving) ScreenList.SOLV.getScreenClass();
249
      solving.resetElapsed();
250
      PlayActivity act = mAct.get();
251 e9397ae9 leszek
      ScreenList.switchScreen( act,ScreenList.SOLV );
252 18b0ae9c leszek
253 e9397ae9 leszek
      /*
254 18b0ae9c leszek
      act.runOnUiThread(new Runnable()
255
        {
256
        @Override
257
        public void run()
258
          {
259 e9397ae9 leszek
260 18b0ae9c leszek
          }
261
        });
262 e9397ae9 leszek
263
       */
264 88b94310 Leszek Koltunski
      }
265
    }
266
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268
269
  public void failedToDrag()
270
    {
271 7ee8337b leszek
    PlayActivity act = mAct.get();
272 88b94310 Leszek Koltunski
273
    if( act!=null )
274
      {
275 15ed3429 leszek
      ScreenList screen = ScreenList.getCurrentScreen();
276
277 18b0ae9c leszek
      if( screen==ScreenList.FREE ||
278
          screen==ScreenList.SOLV ||
279
          screen==ScreenList.SCRA  ) ((ScreenBase)screen.getScreenClass()).reddenLock(act);
280
      }
281
    }
282
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284
285
  public void onSolved()
286
    {
287
    if( ScreenList.getCurrentScreen()==ScreenList.SOLV )
288
      {
289
      ScreenSolving solving = (ScreenSolving)ScreenList.SOLV.getScreenClass();
290
      mNewRecord = solving.stopTimerAndGetRecord();
291
      mIsNewRecord = solving.setRecord();
292
      }
293
    }
294
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296
297
  public void onWinEffectFinished(long startTime, long endTime, String debug, int scrambleNum)
298
    {
299
    if( ScreenList.getCurrentScreen()==ScreenList.SOLV )
300
      {
301
      PlayActivity act = mAct.get();
302
      reportRecord(act,startTime,endTime,debug,scrambleNum);
303
304
      RubikScores scores = RubikScores.getInstance();
305
      int numWins = scores.incrementNumWins();
306
      int numRuns = scores.getNumRuns();
307
308
      if( numRuns==3 || numRuns==6 || numWins==4 || numWins==20 || numWins==50 || numWins==80 || numWins==100)
309
        {
310
        requestReview(act);
311
        }
312
313
      switch(mIsNewRecord)
314
        {
315
        case RECORD_FIRST  :
316
        case RECORD_NEW    : Bundle byes = createDialogBundle();
317
                             RubikDialogNewRecord dyes = new RubikDialogNewRecord();
318
                             dyes.setArguments(byes);
319
                             dyes.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
320
                             break;
321
        case RECORD_NOT_NEW: Bundle bno = createDialogBundle();
322
                             RubikDialogSolved dno = new RubikDialogSolved();
323
                             dno.setArguments(bno);
324
                             dno.show( act.getSupportFragmentManager(), RubikDialogSolved.getDialogTag() );
325
        break;
326
        }
327
328
      act.runOnUiThread(new Runnable()
329
        {
330
        @Override
331
        public void run()
332
          {
333
          ScreenList.switchScreen( act,ScreenList.DONE );
334
          }
335
        });
336 88b94310 Leszek Koltunski
      }
337
    }
338 9530f6b0 Leszek Koltunski
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340
341
  public void reportProblem(String problem, boolean reportException)
342
    {
343
    if( BuildConfig.DEBUG )
344
      {
345
      android.util.Log.e("interface", problem);
346
      }
347
    else
348
      {
349
      if( reportException )
350
        {
351
        Exception ex = new Exception(problem);
352
        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
353
        crashlytics.setCustomKey("problem" , problem);
354
        crashlytics.recordException(ex);
355
        }
356
      else
357
        {
358
        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
359
        crashlytics.log(problem);
360
        }
361
      }
362
    }
363
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365
366 919b830e Leszek Koltunski
  private void reportScramblingProblem(int place, long pause, long resume, long time)
367 9530f6b0 Leszek Koltunski
    {
368 919b830e Leszek Koltunski
    String error = "SCRAMBLING BLOCK "+place+" blocked for "+time;
369 9530f6b0 Leszek Koltunski
370
    if( BuildConfig.DEBUG )
371
       {
372
       android.util.Log.e("D", error);
373
       }
374
    else
375
      {
376
      Exception ex = new Exception(error);
377
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
378
      crashlytics.setCustomKey("pause" , pause );
379
      crashlytics.setCustomKey("resume", resume );
380
      crashlytics.recordException(ex);
381
      }
382
    }
383
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385
386 919b830e Leszek Koltunski
  private void reportRotationProblem(int place, long pause, long resume, long time)
387 9530f6b0 Leszek Koltunski
    {
388 919b830e Leszek Koltunski
    String error = "ROTATION BLOCK "+place+" blocked for "+time;
389 9530f6b0 Leszek Koltunski
390
    if( BuildConfig.DEBUG )
391
       {
392
       android.util.Log.e("D", error);
393
       }
394
    else
395
      {
396
      Exception ex = new Exception(error);
397
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
398
      crashlytics.setCustomKey("pause" , pause );
399
      crashlytics.setCustomKey("resume", resume);
400
      crashlytics.recordException(ex);
401
      }
402
    }
403
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405
406
  private void reportThreadProblem(int place, long pause, long resume, long time)
407
    {
408
    String error = EffectMessageSender.reportState();
409
410
    if( BuildConfig.DEBUG )
411
       {
412
       android.util.Log.e("D", error);
413
       }
414
    else
415
      {
416
      Exception ex = new Exception(error);
417
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
418
      crashlytics.setCustomKey("pause" , pause  );
419
      crashlytics.setCustomKey("resume", resume );
420
      crashlytics.recordException(ex);
421
      }
422
    }
423
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425
426
  public void reportBlockProblem(int type, int place, long pause, long resume, long time)
427
    {
428
    switch(type)
429
      {
430 919b830e Leszek Koltunski
      case BlockController.TYPE_SCRAMBLING: reportScramblingProblem(place,pause,resume,time); break;
431
      case BlockController.TYPE_ROTATION  : reportRotationProblem(place,pause,resume,time); break;
432
      case BlockController.TYPE_THREAD    : reportThreadProblem(place,pause,resume,time); break;
433 9530f6b0 Leszek Koltunski
      }
434
    }
435 e09119d8 Leszek Koltunski
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437
438
  public void reportJSONError(String error, int ordinal)
439
    {
440
    RubikObject object = RubikObjectList.getObject(ordinal);
441
    String name = object==null ? "NULL" : object.getUpperName();
442
443
    if( BuildConfig.DEBUG )
444
       {
445
       android.util.Log.e("libInterface", "name="+name+" JSON error: "+error);
446
       }
447
    else
448
      {
449
      Exception ex = new Exception(error);
450
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
451
      crashlytics.setCustomKey("name" , name );
452
      crashlytics.setCustomKey("JSONerror", error );
453
      crashlytics.recordException(ex);
454
      }
455
    }
456 9530f6b0 Leszek Koltunski
}