package net.demilich.metastone.game.statistics; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; import net.demilich.metastone.game.cards.Card; import net.demilich.metastone.game.cards.CardType; import net.demilich.metastone.game.entities.minions.Minion; import net.demilich.metastone.game.entities.minions.Permanent; import net.demilich.metastone.game.entities.weapons.Weapon; public class GameStatistics implements Cloneable { private final Map<Statistic, Object> stats = new EnumMap<Statistic, Object>(Statistic.class); private final Map<String, Map<Integer, Integer>> cardsPlayed = new HashMap<String, Map<Integer, Integer>>(); private final Map<String, Map<Integer, Integer>> minionsSummoned = new HashMap<String, Map<Integer, Integer>>(); private final Map<String, Map<Integer, Integer>> permanentsSummoned = new HashMap<String, Map<Integer, Integer>>(); private void add(Statistic key, long value) { if (!stats.containsKey(key)) { stats.put(key, 0L); } long newValue = getLong(key) + value; stats.put(key, newValue); } public void armorGained(int armor) { add(Statistic.ARMOR_GAINED, armor); } public void cardDrawn() { add(Statistic.CARDS_DRAWN, 1); } public void cardPlayed(Card card, int turn) { add(Statistic.CARDS_PLAYED, 1); switch (card.getCardType()) { case HERO_POWER: add(Statistic.HERO_POWER_USED, 1); break; case MINION: add(Statistic.MINIONS_PLAYED, 1); break; case PERMANENT: add(Statistic.PERMANENTS_PLAYED, 1); break; case SPELL: case CHOOSE_ONE: add(Statistic.SPELLS_CAST, 1); break; case WEAPON: add(Statistic.WEAPONS_PLAYED, 1); case HERO: break; } increaseCardCount(card, turn); } public GameStatistics clone() { GameStatistics clone = new GameStatistics(); clone.stats.putAll(stats); clone.getCardsPlayed().putAll(getCardsPlayed()); clone.getMinionsSummoned().putAll(getMinionsSummoned()); clone.getPermanentsSummoned().putAll(getPermanentsSummoned()); return clone; } public boolean contains(Statistic key) { return stats.containsKey(key); } public void damageDealt(int damage) { add(Statistic.DAMAGE_DEALT, damage); } public void equipWeapon(Weapon weapon) { add(Statistic.WEAPONS_EQUIPPED, 1); } public void fatigueDamage(int fatigueDamage) { add(Statistic.FATIGUE_DAMAGE, fatigueDamage); } public void gameLost() { add(Statistic.GAMES_LOST, 1); updateWinRate(); } public void gameWon() { add(Statistic.GAMES_WON, 1); updateWinRate(); } public Object get(Statistic key) { return stats.get(key); } public Map<String, Map<Integer, Integer>> getCardsPlayed() { return cardsPlayed; } public int getCardsPlayedCount(String cardId) { int count = 0; for (String card : cardsPlayed.keySet()) { for (int turn : cardsPlayed.get(card).keySet()) { count += cardsPlayed.get(card).get(turn); } } return count; } public Map<String, Map<Integer, Integer>> getMinionsSummoned() { return minionsSummoned; } public Map<String, Map<Integer, Integer>> getPermanentsSummoned() { return permanentsSummoned; } public double getDouble(Statistic key) { return stats.containsKey(key) ? (double) stats.get(key) : 0.0; } public long getLong(Statistic key) { return stats.containsKey(key) ? (long) stats.get(key) : 0L; } public void heal(int healing) { add(Statistic.HEALING_DONE, healing); } private void increaseCardCount(Card card, int turn) { if (card.getCardType().isCardType(CardType.HERO_POWER)) { return; } String cardId = card.getCardId(); if (!getCardsPlayed().containsKey(cardId)) { getCardsPlayed().put(cardId, new HashMap<Integer, Integer>()); } if (!getCardsPlayed().get(cardId).containsKey(turn)) { getCardsPlayed().get(cardId).put(turn, 0); } getCardsPlayed().get(cardId).put(turn, getCardsPlayed().get(cardId).get(turn) + 1); } private void increaseMinionCount(Minion minion, int turn) { String cardId = minion.getSourceCard().getCardId(); if (!getMinionsSummoned().containsKey(cardId)) { getMinionsSummoned().put(cardId, new HashMap<Integer, Integer>()); } if (!getMinionsSummoned().get(cardId).containsKey(turn)) { getMinionsSummoned().get(cardId).put(turn, 0); } getMinionsSummoned().get(cardId).put(turn, getMinionsSummoned().get(cardId).get(turn) + 1); } private void increasePermanentCount(Permanent permanent, int turn) { String cardId = permanent.getSourceCard().getCardId(); if (!getPermanentsSummoned().containsKey(cardId)) { getPermanentsSummoned().put(cardId, new HashMap<Integer, Integer>()); } if (!getPermanentsSummoned().get(cardId).containsKey(turn)) { getPermanentsSummoned().get(cardId).put(turn, 0); } getPermanentsSummoned().get(cardId).put(turn, getPermanentsSummoned().get(cardId).get(turn) + 1); } public void manaSpent(int mana) { add(Statistic.MANA_SPENT, mana); } public void merge(GameStatistics otherStatistics) { for (Statistic stat : otherStatistics.stats.keySet()) { Object value = get(stat); if (value != null) { if (value instanceof Long) { add(stat, otherStatistics.getLong(stat)); } } else { stats.put(stat, otherStatistics.get(stat)); } } for (String cardId : otherStatistics.getCardsPlayed().keySet()) { if (!getCardsPlayed().containsKey(cardId)) { getCardsPlayed().put(cardId, new HashMap<Integer, Integer>()); } for (int turn : otherStatistics.getCardsPlayed().get(cardId).keySet()) { if (!getCardsPlayed().get(cardId).containsKey(turn)) { getCardsPlayed().get(cardId).put(turn, 0); } getCardsPlayed().get(cardId).put(turn, getCardsPlayed().get(cardId).get(turn) + otherStatistics.getCardsPlayed().get(cardId).get(turn)); } } updateWinRate(); } public void minionSummoned(Minion minion, int turn) { add(Statistic.MINIONS_PLAYED, 1); increaseMinionCount(minion, turn); } public void permanentSummoned(Permanent permanent, int turn) { add(Statistic.PERMANENTS_PLAYED, 1); increasePermanentCount(permanent, turn); } public void set(Statistic key, Object value) { stats.put(key, value); } public void startTurn() { add(Statistic.TURNS_TAKEN, 1); } @Override public String toString() { StringBuilder builder = new StringBuilder("[GameStatistics]\n"); for (Statistic stat : stats.keySet()) { builder.append(stat); builder.append(": "); builder.append(stats.get(stat)); builder.append("\n"); } return builder.toString(); } private void updateWinRate() { double winRate = getLong(Statistic.GAMES_WON) / (double) (getLong(Statistic.GAMES_WON) + getLong(Statistic.GAMES_LOST)); set(Statistic.WIN_RATE, winRate); } }