/*
* Copyright 2015 Daniel Dittmar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dan.dit.whatsthat.riddle.achievement.holders;
import android.content.res.Resources;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
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.achievement.AchievementProperties;
import dan.dit.whatsthat.riddle.achievement.AchievementDataRiddleType;
import dan.dit.whatsthat.riddle.achievement.AchievementPropertiesMapped;
import dan.dit.whatsthat.riddle.achievement.MiscAchievement;
import dan.dit.whatsthat.riddle.types.PracticalRiddleType;
import dan.dit.whatsthat.util.compaction.CompactedDataCorruptException;
/**
* Created by daniel on 21.06.15.
*/
public class MiscAchievementHolder implements AchievementHolder {
public static final String KEY_ADMIRED_IMAGE_AUTHOR ="admired_image_author";
private static final String DATA_NAME = "misc_achievement_data";
public static final String KEY_SOLUTION_INPUT_CURRENT_TEXT = "misc_solution_input_current_text";
public static final String KEY_LAST_SOLVED_GAME_PLAYED_TIME = "misc_last_solved_game_played_time";
public static final String KEY_LAST_SOLVED_GAME_TOTAL_TIME = "misc_last_solved_game_total_time";
public static final String KEY_ACHIEVEMENTS_EARNED_COUNT = "misc_total_achievements_earned";
public static final String KEY_FEATURES_PURCHASED = "misc_features_purchased";
public static final String KEY_SPIN_WHEEL_START_ANGLE_SPEED =
"misc_spin_wheel_start_angle_speed";
public static final String KEY_RETRYING_RIDDLE_COUNT = "misc_retrying_riddle_count";
public static final String KEY_REMADE_RIDDLE_CURRENT_REMADE_COUNT = "misc_remade_riddle_current_remade_count";
public static final String KEY_REMADE_RIDDLE_CURRENT_COUNT =
"misc_remade_riddle_current_count";
public static final String KEY_LEFT_DONATION_SITE_STAY_TIME =
"misc_left_donation_site_stay_time";
private AchievementPropertiesMapped<String> mData;
private SortedMap<Integer, MiscAchievement> mAchievements;
public AchievementPropertiesMapped<String> getData() {
return mData;
}
private void makeData(AchievementManager manager) {
try {
mData = new AchievementPropertiesMapped<>(DATA_NAME, manager.loadDataEvent(DATA_NAME));
} catch (CompactedDataCorruptException e) {
mData = new AchievementPropertiesMapped<>(DATA_NAME);
Log.e("Achievement","Failed creating misc properties from data: " + e);
}
manager.manageAchievementData(mData);
}
@Override
public void makeAchievements(AchievementManager manager) {
makeData(manager);
mAchievements = new TreeMap<>();
mAchievements.put(Achievement1.NUMBER, new Achievement1(manager, mData));
mAchievements.put(Achievement2.NUMBER, new Achievement2(manager, mData));
mAchievements.put(Achievement3.NUMBER, new Achievement3(manager, mData));
mAchievements.put(Achievement4.NUMBER, new Achievement4(manager, mData));
mAchievements.put(Achievement5.NUMBER, new Achievement5(manager, mData));
mAchievements.put(Achievement6.NUMBER, new Achievement6(manager, mData));
mAchievements.put(Achievement7.NUMBER, new Achievement7(manager, mData));
mAchievements.put(Achievement8.NUMBER, new Achievement8(manager, mData));
mAchievements.put(Achievement9.NUMBER, new Achievement9(manager, mData));
mAchievements.put(Achievement10.NUMBER, new Achievement10(manager, mData));
}
private static class Achievement1 extends MiscAchievement {
public static final int NUMBER = 1;
public static final int LEVEL = 0;
public static final int REWARD = 50;
public static final boolean DISCOVERED = true;
public static final String CREATOR_NAME_1_1 = "Daniel";
public static final String CREATOR_NAME_1_2 = "Dani";
public static final String CREATOR_NAME_2_1 = "Fabian";
public static final String CREATOR_NAME_2_2 = "Fabi";
public static final String KEY_FIRST_CREATOR_NAME_ALREADY_ENTERED = MiscAchievement.makeId(NUMBER) + "first_name_entered";
public Achievement1(AchievementManager manager, AchievementPropertiesMapped<String> miscData) {
super(miscData, R.string.achievement_misc_1_name, R.string.achievement_misc_1_descr, 0, NUMBER, manager, LEVEL, REWARD, 2, DISCOVERED);
}
@Override
public void onAchieved() {
super.onAchieved();
mMiscData.removeKey(KEY_FIRST_CREATOR_NAME_ALREADY_ENTERED);
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() == mMiscData && event.hasChangedKey(MiscAchievementHolder.KEY_SOLUTION_INPUT_CURRENT_TEXT)) {
String currentText = mMiscData.getMappedValue(MiscAchievementHolder.KEY_SOLUTION_INPUT_CURRENT_TEXT);
if (!TextUtils.isEmpty(currentText) && areDependenciesFulfilled()) {
if ((currentText.equalsIgnoreCase(CREATOR_NAME_1_1) || currentText.equalsIgnoreCase(CREATOR_NAME_1_2))
&& mMiscData.getValue(KEY_FIRST_CREATOR_NAME_ALREADY_ENTERED, 0L) == 0L) {
mMiscData.putValue(KEY_FIRST_CREATOR_NAME_ALREADY_ENTERED, 1L, AchievementProperties.UPDATE_POLICY_ALWAYS);
achieveDelta(1);
} else if ((currentText.equalsIgnoreCase(CREATOR_NAME_2_1) || currentText.equalsIgnoreCase(CREATOR_NAME_2_2))
&& (getValue() == 0 || mMiscData.getValue(KEY_FIRST_CREATOR_NAME_ALREADY_ENTERED, 0L) == 1L)) {
achieveDelta(1);
}
}
}
}
}
private static class Achievement2 extends MiscAchievement {
public static final int NUMBER = 2;
public static final int LEVEL = 0;
public static final int REWARD = 75;
public static final boolean DISCOVERED = false;
private static final long MS_TO_DAYS = 1000 * 60 * 60 * 24;
private static final long MIN_TOTAL_TIME = MS_TO_DAYS * 3; // ms
public Achievement2(AchievementManager manager, AchievementPropertiesMapped<String> miscData) {
super(miscData, R.string.achievement_misc_2_name, R.string.achievement_misc_2_descr, 0, NUMBER, manager, LEVEL, REWARD, 1, DISCOVERED);
}
@Override
public CharSequence getDescription(Resources res) {
return res.getString(mDescrResId, MIN_TOTAL_TIME / MS_TO_DAYS);
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() == mMiscData && event.hasChangedKey(KEY_LAST_SOLVED_GAME_TOTAL_TIME)) {
if (mMiscData.getValue(KEY_LAST_SOLVED_GAME_TOTAL_TIME, 0L) >= MIN_TOTAL_TIME) {
achieveAfterDependencyCheck();
}
}
}
}
private static class Achievement3 extends MiscAchievement {
public static final int NUMBER = 3;
public static final int LEVEL = 0;
public static final int REWARD = 100;
public static final boolean DISCOVERED = false;
private static final long MS_TO_HOURS = 1000 * 60 * 60;
private static final long MIN_PLAYED_TIME = MS_TO_HOURS * 2; // ms
public Achievement3(AchievementManager manager, AchievementPropertiesMapped<String> miscData) {
super(miscData, R.string.achievement_misc_3_name, R.string.achievement_misc_3_descr, 0, NUMBER, manager, LEVEL, REWARD, 1, DISCOVERED);
}
@Override
public CharSequence getDescription(Resources res) {
return res.getString(mDescrResId, MIN_PLAYED_TIME / MS_TO_HOURS);
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() == mMiscData && event.hasChangedKey(KEY_LAST_SOLVED_GAME_PLAYED_TIME)) {
if (mMiscData.getValue(KEY_LAST_SOLVED_GAME_PLAYED_TIME, 0L) >= MIN_PLAYED_TIME) {
achieveAfterDependencyCheck();
}
}
}
}
private static class Achievement4 extends MiscAchievement {
public static final int NUMBER = 4;
public static final int LEVEL = 2;
public static final int REWARD = 300;
public static final boolean DISCOVERED = true;
public static final int ACHIEVEMENTS_REQUIRED = 60; //Daily achievements count in, too
public Achievement4(AchievementManager manager, AchievementPropertiesMapped<String> miscData) {
super(miscData, R.string.achievement_misc_4_name, R.string.achievement_misc_4_descr, 0, NUMBER, manager, LEVEL, REWARD, ACHIEVEMENTS_REQUIRED, DISCOVERED);
}
@Override
public CharSequence getDescription(Resources res) {
return res.getString(mDescrResId, getValue(), ACHIEVEMENTS_REQUIRED);
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() == mMiscData && event.hasChangedKey(KEY_ACHIEVEMENTS_EARNED_COUNT)) {
achieveDelta(1); // do not check for conditions for this achievement!
}
}
}
private static class Achievement5 extends MiscAchievement {
public static final int NUMBER = 5;
public static final int LEVEL = 0;
public static final int REWARD = 60;
public static final boolean DISCOVERED = true;
public static final int REQUIRED_TIME_ON_DONATION_SITE = 60000;//ms
public Achievement5(AchievementManager manager, AchievementPropertiesMapped<String>
miscData) {
super(miscData, R.string.achievement_misc_5_name, R.string.achievement_misc_5_descr,
0, NUMBER, manager, LEVEL, REWARD, 1, DISCOVERED);
}
@Override
public CharSequence getDescription(Resources res) {
if (isAchieved()) {
return res.getString(R.string.achievement_misc_5_achieved_descr);
}
return super.getDescription(res);
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() == mMiscData && event.hasChangedKey
(KEY_LEFT_DONATION_SITE_STAY_TIME)) {
if (mMiscData.getValue(KEY_LEFT_DONATION_SITE_STAY_TIME, 0L) >=
REQUIRED_TIME_ON_DONATION_SITE) {
achieveAfterDependencyCheck();
}
}
}
}
private static class Achievement6 extends MiscAchievement {
public static final int NUMBER = 6;
public static final int LEVEL = 0;
public static final int REWARD = 100;
public static final boolean DISCOVERED = true;
public static final int ONE_TYPE_PLAYED_COUNT = 100;
public Achievement6(AchievementManager manager, AchievementPropertiesMapped<String>
miscData) {
super(miscData, R.string.achievement_misc_6_name, R.string.achievement_misc_6_descr,
0, NUMBER, manager, LEVEL, REWARD, ONE_TYPE_PLAYED_COUNT, DISCOVERED);
}
@Override
public CharSequence getDescription(Resources res) {
return res.getString(mDescrResId, ONE_TYPE_PLAYED_COUNT);
}
@Override
protected void onInit() {
super.onInit();
for (PracticalRiddleType type : PracticalRiddleType.ALL_PLAYABLE_TYPES) {
type.getAchievementData(mManager).addListener(this);
}
}
protected void onAchieved() {
super.onAchieved();
for (PracticalRiddleType type : PracticalRiddleType.ALL_PLAYABLE_TYPES) {
type.getAchievementData(mManager).removeListener(this);
}
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.hasChangedKey(AchievementDataRiddleType.KEY_GAMES_SOLVED)) {
int max = 0;
for (PracticalRiddleType type : PracticalRiddleType.ALL_PLAYABLE_TYPES) {
AchievementDataRiddleType typeData = type.getAchievementData(mManager);
if (typeData != null) {
max = (int) Math.max(max, typeData.getValue(AchievementDataRiddleType
.KEY_GAMES_SOLVED, 0L));
}
if (typeData != null && typeData == event.getChangedData()
&& max >= ONE_TYPE_PLAYED_COUNT) {
achieveAfterDependencyCheck();
break;
} else if (max < ONE_TYPE_PLAYED_COUNT) {
achieveProgressPercent((int) ((max / (double) ONE_TYPE_PLAYED_COUNT) *
100));
}
}
}
}
}
private static class Achievement7 extends MiscAchievement {
public static final int NUMBER = 7;
public static final int LEVEL = 0;
public static final int REWARD = 50;
public static final boolean DISCOVERED = true;
public static final float SPIN_ANGLE_SPEED_THRESHOLD = 6000f;
public Achievement7(AchievementManager manager, AchievementPropertiesMapped<String>
miscData) {
super(miscData, R.string.achievement_misc_7_name, R.string.achievement_misc_7_descr,
0, NUMBER, manager, LEVEL, REWARD, 1, DISCOVERED);
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() == mMiscData && event.hasChangedKey
(KEY_SPIN_WHEEL_START_ANGLE_SPEED)) {
if (mMiscData.getValue(KEY_SPIN_WHEEL_START_ANGLE_SPEED, 0L) >=
SPIN_ANGLE_SPEED_THRESHOLD) {
achieveAfterDependencyCheck();
}
}
}
}
private static class Achievement8 extends MiscAchievement {
public static final int NUMBER = 8;
public static final int LEVEL = 0;
public static final int REWARD = 30;
public static final boolean DISCOVERED = true;
public static final int REQUIRED_REMADE_COUNT = 3;
public Achievement8(AchievementManager manager, AchievementPropertiesMapped<String>
miscData) {
super(miscData, R.string.achievement_misc_8_name, R.string.achievement_misc_8_descr,
0, NUMBER, manager, LEVEL, REWARD, 1, DISCOVERED);
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() == mMiscData && event.hasChangedKey
(KEY_REMADE_RIDDLE_CURRENT_COUNT)) {
if (mMiscData.getValue(KEY_REMADE_RIDDLE_CURRENT_REMADE_COUNT, 0L) >=
REQUIRED_REMADE_COUNT) {
achieveAfterDependencyCheck();
}
}
}
}
private static class Achievement9 extends MiscAchievement {
public static final int NUMBER = 9;
public static final int LEVEL = 1;
public static final int REWARD = 100;
public static final boolean DISCOVERED = true;
public static final int REQUIRED_TYPES_WITH_BONUS = 3;
public Achievement9(AchievementManager manager, AchievementPropertiesMapped<String>
miscData) {
super(miscData, R.string.achievement_misc_9_name, R.string.achievement_misc_9_descr,
0, NUMBER, manager, LEVEL, REWARD, 1, DISCOVERED);
}
@Override
public CharSequence getDescription(Resources res) {
return res.getString(mDescrResId, REQUIRED_TYPES_WITH_BONUS);
}
@Override
protected void onInit() {
super.onInit();
for (PracticalRiddleType type : PracticalRiddleType.ALL_PLAYABLE_TYPES) {
type.getAchievementData(mManager).addListener(this);
}
}
protected void onAchieved() {
super.onAchieved();
for (PracticalRiddleType type : PracticalRiddleType.ALL_PLAYABLE_TYPES) {
type.getAchievementData(mManager).removeListener(this);
}
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() != mMiscData) {
int hasBonusCount = 0;
for (PracticalRiddleType type : PracticalRiddleType.ALL_PLAYABLE_TYPES) {
hasBonusCount += type.getAchievementData(mManager).getValue
(AchievementDataRiddleType.KEY_BONUS_GAINED_COUNT, 0L) > 0L ? 1 : 0;
}
if (hasBonusCount >= REQUIRED_TYPES_WITH_BONUS) {
achieveAfterDependencyCheck();
}
}
}
}
private static class Achievement10 extends MiscAchievement {
public static final int NUMBER = 10;
public static final int LEVEL = 0;
public static final int REWARD = 42;
public static final boolean DISCOVERED = false;
public Achievement10(AchievementManager manager, AchievementPropertiesMapped<String>
miscData) {
super(miscData, R.string.achievement_misc_10_name, R.string.achievement_misc_10_descr,
0, NUMBER, manager, LEVEL, REWARD, 1, DISCOVERED);
}
@Override
public void onDataEvent(AchievementDataEvent event) {
if (event.getChangedData() == mMiscData && event.hasChangedKey(MiscAchievementHolder.KEY_SOLUTION_INPUT_CURRENT_TEXT)) {
String currentText = mMiscData.getMappedValue(MiscAchievementHolder.KEY_SOLUTION_INPUT_CURRENT_TEXT);
if (!TextUtils.isEmpty(currentText) && areDependenciesFulfilled()) {
if (currentText.equalsIgnoreCase("keks") || currentText.equalsIgnoreCase
("cookie")) {
achieve();
}
}
}
}
}
@Override
public void addDependencies() {
for (MiscAchievement achievement : mAchievements.values()) {
achievement.setDependencies();
}
}
@Override
public void initAchievements() {
for (MiscAchievement achievement : mAchievements.values()) {
achievement.init();
}
}
@Override
public List<? extends Achievement> getAchievements() {
return new ArrayList<>(mAchievements.values());
}
@Override
public int getExpectableTestSubjectScore(int testSubjectLevel) {
int expected = 0;
for (Achievement achievement : mAchievements.values()) {
expected += achievement.getExpectedScore(testSubjectLevel);
}
return expected;
}
}