package dan.dit.whatsthat.riddle.achievement; import android.content.SharedPreferences; import android.content.res.Resources; import android.support.annotation.NonNull; import android.util.Log; import java.util.Calendar; import java.util.Date; import dan.dit.whatsthat.R; import dan.dit.whatsthat.achievement.Achievement; import dan.dit.whatsthat.achievement.AchievementDataEvent; import dan.dit.whatsthat.achievement.AchievementManager; import dan.dit.whatsthat.riddle.achievement.holders.AchievementCircle; import dan.dit.whatsthat.riddle.types.PracticalRiddleType; import dan.dit.whatsthat.testsubject.LevelDependency; import dan.dit.whatsthat.testsubject.TestSubject; import dan.dit.whatsthat.util.dependencies.Dependency; /** * Created by daniel on 12.01.16. */ public abstract class DailyAchievement extends Achievement { private static final String KEY_LAST_RESET_TIMESTAMP = "daily_lastreset"; private static final String KEY_AVAILABLE_TODAY = "daily_available"; private static final boolean DEFAULT_IS_AVAILABLE = false; private static final int REQUIRED_DIFFERENT_RIDDLE_TYPES_FOR_DAILY_ACHIEVEMENTS = 2; private boolean mInitialized; private static final Calendar CHECKER = Calendar.getInstance(); private static final Date CHECKER_DATE = new Date(); private long mLastResetTimestamp; private boolean mAvailableToday; protected DailyAchievement(int nameResId, int descrResId, int rewardResId, AchievementManager manager, int level, int number, int scoreReward, int maxValue, boolean discovered) { super(makeId(number), nameResId, descrResId, rewardResId, manager, level, scoreReward, maxValue, discovered); } private static final Dependency MIN_DIFFERENT_RIDDLE_TYPES_DEPENDENCY = new Dependency() { @Override public boolean isFulfilled() { return TestSubject.getInstance().getTestSubjectRiddleTypeCountDependency().getValue() >= REQUIRED_DIFFERENT_RIDDLE_TYPES_FOR_DAILY_ACHIEVEMENTS; } @Override public CharSequence getName(Resources res) { return res.getString(R.string.dependency_testsubject_riddle_type_min_count, REQUIRED_DIFFERENT_RIDDLE_TYPES_FOR_DAILY_ACHIEVEMENTS); } }; public void setDependencies() { addLevelDependency(); // get achievement "the beginning" mDependencies.add(TestSubject.getInstance().makeClaimedAchievementDependency (PracticalRiddleType.CIRCLE_INSTANCE, AchievementCircle.Achievement1.NUMBER)); // get another riddle type mDependencies.add(MIN_DIFFERENT_RIDDLE_TYPES_DEPENDENCY); } @Override public final void onDataEvent(AchievementDataEvent event) { if (isAvailable()) { onIsAvailableDataEvent(event); } } protected abstract void onIsAvailableDataEvent(AchievementDataEvent event); @Override public int getIconResId() { return R.drawable.eye_refresh; } public int getIconResIdByState() { if (!areDependenciesFulfilled()) { if (isDiscovered()) { return R.drawable.eye_locked; } else { return R.drawable.eye_blind_locked; } } if (mDiscovered) { if (isAchieved()) { if (isRewardClaimable()) { return R.drawable.alien_achieved; } else { return R.drawable.alien_achieved_claimed; } } else { return getIconResId(); } } else { return R.drawable.eye_blind; } } public final void init(@NonNull Calendar initTime) { if (!mInitialized && isNotAchievedToday(initTime)) { Log.d("Achievement", "Initializing " + mId); mInitialized = true; onInit(); checkedReset(initTime); } } public boolean checkedReset(@NonNull Calendar initTime) { if (isNotAchievedToday(initTime) && !gotResetToday(initTime) && areDependenciesFulfilled()) { // ensure initialized if (!mInitialized) { init(initTime); // will also invoke reset by invoking checkedReset again } else { reset(initTime); } return true; } return false; } private void reset(Calendar initTime) { Log.d("Achievement", "Resetting " + mId + " on " + initTime); mLastResetTimestamp = initTime.getTimeInMillis(); mAvailableToday = DEFAULT_IS_AVAILABLE; resetAnyProgress(); onReset(); } protected abstract void onReset(); private boolean isNotAchievedToday(@NonNull Calendar today) { CHECKER_DATE.setTime(mAchievedTimestamp); CHECKER.setTime(CHECKER_DATE); return !isToday(today, CHECKER); } public boolean gotResetToday(@NonNull Calendar today) { CHECKER_DATE.setTime(mLastResetTimestamp); CHECKER.setTime(CHECKER_DATE); return isToday(today, CHECKER); } private static boolean isToday(Calendar today, Calendar check) { return today.get(Calendar.DAY_OF_YEAR) == check.get(Calendar.DAY_OF_YEAR) && today.get(Calendar.YEAR) == check.get(Calendar.YEAR); } @Override protected void addData(SharedPreferences.Editor editor) { super.addData(editor); editor .putLong(mId + Achievement.SEPARATOR + KEY_LAST_RESET_TIMESTAMP, mLastResetTimestamp) .putBoolean(mId + Achievement.SEPARATOR + KEY_AVAILABLE_TODAY, mAvailableToday); } protected void loadData(SharedPreferences prefs) { super.loadData(prefs); mLastResetTimestamp = prefs.getLong(mId + Achievement.SEPARATOR + KEY_LAST_RESET_TIMESTAMP, 0L); mAvailableToday = prefs.getBoolean(mId + Achievement.SEPARATOR + KEY_AVAILABLE_TODAY, DEFAULT_IS_AVAILABLE); } public void setAvailable() { Log.d("Achievement", "Made available: " + mId); mAvailableToday = true; mManager.onChanged(this, AchievementManager.CHANGED_OTHER); } public boolean isAvailable() { return mAvailableToday; } public void onInit() { } @Override protected void onDiscovered() { } private void addLevelDependency() { mDependencies.add(LevelDependency.getInstance(mLevel)); } @Override protected void onAchieved() { Log.d("Achievement", "Achieved: " + mId); } public int getExpectedScore(int forLevel) { return 0; // do not expect daily achievements to produce any score } protected static String makeId(int number) { return "daily_achievement" + number; } }