/* * 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.types; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import dan.dit.whatsthat.achievement.AchievementManager; import dan.dit.whatsthat.image.Image; import dan.dit.whatsthat.riddle.Riddle; import dan.dit.whatsthat.riddle.RiddleConfig; import dan.dit.whatsthat.riddle.achievement.AchievementDataRiddleGame; import dan.dit.whatsthat.riddle.achievement.AchievementDataRiddleType; import dan.dit.whatsthat.riddle.achievement.holders.TypeAchievementHolder; import dan.dit.whatsthat.riddle.control.RiddleGame; import dan.dit.whatsthat.riddle.control.RiddleScoreConfig; import dan.dit.whatsthat.testsubject.TestSubject; import dan.dit.whatsthat.util.compaction.CompactedDataCorruptException; import dan.dit.whatsthat.util.general.PercentProgressListener; /** * Created by daniel on 01.04.15. */ public abstract class PracticalRiddleType extends RiddleType { private static final Map<String, PracticalRiddleType> ALL_TYPES = new HashMap<>(); private static final int INTEREST_VALUE = 10; public static final TypesHolder.Circle CIRCLE_INSTANCE = new TypesHolder.Circle(); public static final TypesHolder.Snow SNOW_INSTANCE = new TypesHolder.Snow(); public static final TypesHolder.Dice DICE_INSTANCE = new TypesHolder.Dice(); private static final TypesHolder.Developer DEVELOPER_INSTANCE = new TypesHolder.Developer(); public static final TypesHolder.Triangle TRIANGLE_INSTANCE = new TypesHolder.Triangle(); public static final TypesHolder.Jumper JUMPER_INSTANCE = new TypesHolder.Jumper(); public static final TypesHolder.Memory MEMORY_INSTANCE = new TypesHolder.Memory(); public static final TypesHolder.Lazor LAZOR_INSTANCE = new TypesHolder.Lazor(); public static final TypesHolder.Torchlight TORCHLIGHT_INSTANCE = new TypesHolder.Torchlight(); public static final TypesHolder.Flow FLOW_INSTANCE = new TypesHolder.Flow(); public static final List<PracticalRiddleType> ALL_PLAYABLE_TYPES = new ArrayList<>(); public static final int NO_ID = 0; static { ALL_PLAYABLE_TYPES.add(CIRCLE_INSTANCE); ALL_PLAYABLE_TYPES.add(LAZOR_INSTANCE); ALL_PLAYABLE_TYPES.add(FLOW_INSTANCE); ALL_PLAYABLE_TYPES.add(JUMPER_INSTANCE); ALL_PLAYABLE_TYPES.add(DICE_INSTANCE); ALL_PLAYABLE_TYPES.add(TRIANGLE_INSTANCE); ALL_PLAYABLE_TYPES.add(SNOW_INSTANCE); ALL_PLAYABLE_TYPES.add(MEMORY_INSTANCE); } private final RiddleScoreConfig mScoreConfig; private SoftReference<Drawable> mIcon; private volatile AchievementDataRiddleType mAchievementData; private final AchievementDataRiddleGame mAchievementDataGame = new AchievementDataRiddleGame(this); protected TypeAchievementHolder mHolder; protected PracticalRiddleType(@NonNull RiddleScoreConfig scoreConfig) { mScoreConfig = scoreConfig; } public Drawable getIcon(Resources res) { if (mIcon != null) { Drawable icon = mIcon.get(); if (icon != null) { return icon; } } if (res != null) { Drawable icon = res.getDrawable(getIconResId()); mIcon = new SoftReference<>(icon); return icon; } return null; } public abstract int getIconResId(); public AchievementDataRiddleType getAchievementData(AchievementManager manager) { if (mAchievementData != null || manager == null) { return mAchievementData; } synchronized (this) { if (mAchievementData == null) { try { mAchievementData = new AchievementDataRiddleType(this, manager); } catch (CompactedDataCorruptException e) { Log.e("Achievement", "Failed creating data for riddle type " + this + ": " + e); mAchievementData = new AchievementDataRiddleType(this, manager, true); } } } return mAchievementData; } public double getSuggestedBitmapAspectRatio() { return getSuggestedCanvasAspectRatio(); // by default fit the bitmap into the canvas } public double getSuggestedCanvasAspectRatio() { return 1.; // square by default } /** * If the type enforces the ratio given by getSuggestedBitmapAspectRatio. * It has no real power on the aspect ratio of the given bitmap but the system * will take try its best to fit the biggest bitmap with this ratio inside the available canvas. * @return If the aspect ratio is not only meant as a suggestion. */ public boolean enforcesBitmapAspectRatio() { return false; } public abstract int getNameResId(); public abstract int getExplanationResId(); public int calculateRefusal(Image image) { List<RiddleType> refused = image.getRefusedRiddleTypes(); int refusal = 0; if (refused != null) { for (RiddleType r : refused) { refusal += getInterestValue(r); // the image hates something which the riddle likes } } List<RiddleType> preferred= image.getPreferredRiddleTypes(); if (preferred != null) { for (RiddleType p : preferred) { refusal += getRefusalValue(p); // the image is something the riddle doesn't like } } return refusal; } public int calculateInterest(Image image) { List<RiddleType> preferred= image.getPreferredRiddleTypes(); int interest = 0; if (preferred != null) { for (RiddleType p : preferred) { interest += getInterestValue(p); // they like the same things } } List<RiddleType> refused = image.getRefusedRiddleTypes(); if (refused != null) { for (RiddleType r : refused) { interest += getRefusalValue(r); // they hate the same things } } return interest; } public abstract RiddleGame makeRiddle(Riddle riddle, Image image, Bitmap bitmap, Resources res, RiddleConfig config, PercentProgressListener listener); @Override protected char getTypePrefix() { return RiddleType.RIDDLE_TYPE_PREFIX_PRACTICAL; } @Override protected void registerType() { ALL_TYPES.put(getFullName(), this); } public static List<PracticalRiddleType> getAll() { List<PracticalRiddleType> types = new ArrayList<>(ALL_TYPES.values()); TestSubject.sortTypes(types); return types; } public static PracticalRiddleType getInstance(String fullName) { if (TextUtils.isEmpty(fullName) || fullName.length() < FULL_NAME_MIN_LENGTH) { return null; } return ALL_TYPES.get(fullName); } public int getInterestValue(RiddleType inType) { return getInterestValueIfEqual(inType); // always interested in itself } public int getRefusalValue(RiddleType refusedTypeOfImage) {return getInterestValueIfEqual(DEVELOPER_INSTANCE);} // we don't want images marked for developers @Override public final int getInterestValue() { return INTEREST_VALUE; } public @NonNull AchievementDataRiddleGame getAchievementDataGame() { return mAchievementDataGame; } public TypeAchievementHolder getAchievementHolder() { return mHolder; } public CharSequence getRiddleHint(Resources res, int hintNumber) { return null; } public int getAvailableHintsAtStartCount() { return 0; } public int getTotalAvailableHintsCount() { return 0; } public List<Integer> getHintCosts() { return null; } public abstract int getAdvertisingResId(); /** * Returns the id of this riddle type. This is some positive integer. * @return A positive integer identifying the PractialRiddleType among all others. */ public abstract int getId(); public int getBaseScore(long timeTaken) { return mScoreConfig.getBaseScore(timeTaken); } }