/* * * Copyright (c) Microsoft. All rights reserved. * Licensed under the MIT license. * * Project Oxford: http://ProjectOxford.ai * * Project Oxford Mimicker Alarm Github: * https://github.com/Microsoft/ProjectOxford-Apps-MimickerAlarm * * Copyright (c) Microsoft Corporation * All rights reserved. * * MIT License: * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ package com.microsoft.mimickeralarm.mimics; import android.util.Log; import android.view.View; import java.lang.ref.WeakReference; /** * This class coordinates Mimic game state between the common UI controls: * The countdown timer across the top of the screen * The progress button which is used to capture images or audio * The banner which animates across the screen giving user feedback * * This class should be instantiated in a Mimic game fragment. The fragment should * implement IMimicImplementation and register itself and its controls with the class. This * class implements the IMimicMediator interface * * The fragment should call into this class in the following cases: * It should register the appropriate controls and itself * The fragment onStart and onStop implementations should call start and stop * All game failure/success cases must call into this class * * The fragment can optionally call the isMimicRunning method to determine whether to do any * further processing. */ public class MimicStateManager implements IMimicMediator { private static String TAG = "MimicStateManager"; MimicStateBanner mMimicStateBanner; CountDownTimerView mCountDownTimer; ProgressButton mProgressButton; MimicButtonBehavior mButtonBehavior; WeakReference<IMimicImplementation> mMimicRef; boolean mMimicRunning; // Should be called from Fragment::onStart, which is when it becomes visible to the user public void start(){ Log.d(TAG, "Entered start!"); mMimicRunning = true; mCountDownTimer.start(); IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.initializeCapture(); } } // Should be called from Fragment::onStop, when the fragment is invisible public void stop() { Log.d(TAG, "Entered stop!"); mMimicRunning = false; IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.stopCapture(); } mProgressButton.setReady(); } public boolean isMimicRunning() { return mMimicRunning; } public void onMimicSuccess(String successMessage) { Log.d(TAG, "Entered onMimicSuccess!"); if (isMimicRunning()) { handleButtonState(); mCountDownTimer.stop(); mMimicStateBanner.success(successMessage, new MimicStateBanner.Command() { @Override public void execute() { Log.d(TAG, "Entered onMimicSuccess callback!"); if (isMimicRunning()) { IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.onSucceeded(); } } } }); } } public void onMimicFailureWithRetry(String failureMessage) { Log.d(TAG, "Entered onMimicFailureWithRetry!"); // If the countdown timer has just expired and has already registered a failure command, // then we should avoid changing state if (isMimicRunning() && !mCountDownTimer.hasExpired()) { mCountDownTimer.pause(); mMimicStateBanner.failure(failureMessage, new MimicStateBanner.Command() { @Override public void execute() { Log.d(TAG, "Entered onMimicFailureWithRetry callback!"); if (isMimicRunning()) { mCountDownTimer.resume(); mProgressButton.setReady(); } } }); } } public void onMimicFailure(String failureMessage) { Log.d(TAG, "Entered onMimicFailure!"); handleButtonState(); mCountDownTimer.stop(); mProgressButton.setClickable(false); mMimicStateBanner.failure(failureMessage, new MimicStateBanner.Command() { @Override public void execute() { Log.d(TAG, "Entered onMimicFailure callback!"); IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.onFailed(); } } }); } public void onMimicInternalError() { Log.d(TAG, "Entered onMimicInternalError!"); handleButtonState(); mCountDownTimer.stop(); mProgressButton.setClickable(false); IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.onInternalError(); } } public void registerStateBanner(MimicStateBanner mimicStateBanner) { mMimicStateBanner = mimicStateBanner; } public void registerCountDownTimer(CountDownTimerView countDownTimer, int timeout) { mCountDownTimer = countDownTimer; mCountDownTimer.init(timeout, new CountDownTimerView.Command() { @Override public void execute() { Log.d(TAG, "Countdown timer expired!"); if (isMimicRunning()) { IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.stopCapture(); mimic.onCountDownTimerExpired(); } } } }); } public void registerProgressButton(ProgressButton progressButton, MimicButtonBehavior buttonBehavior) { mProgressButton = progressButton; mButtonBehavior = buttonBehavior; if (mButtonBehavior == MimicButtonBehavior.AUDIO) { mProgressButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mProgressButton.isReady()) { IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.startCapture(); } mProgressButton.waiting(); } else { IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.stopCapture(); } } } }); } else if (mButtonBehavior == MimicButtonBehavior.CAMERA) { mProgressButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCountDownTimer.pause(); mProgressButton.loading(); IMimicImplementation mimic = mMimicRef.get(); if (mimic != null) { mimic.startCapture(); } } }); } mProgressButton.setReady(); } public void registerMimic(IMimicImplementation mimic) { mMimicRef = new WeakReference<>(mimic); } private void handleButtonState() { if (mButtonBehavior == MimicButtonBehavior.CAMERA) { mProgressButton.stop(); } } }