private double calculateMinionScore(Minion minion, ThreatLevel threatLevel) {
    if (minion.hasAttribute(Attribute.MARKED_FOR_DEATH)) {
      return 0;
    }
    double minionScore = weights.get(WeightedFeature.MINION_INTRINSIC_VALUE);
    minionScore +=
        weights.get(WeightedFeature.MINION_ATTACK_FACTOR)
            * (minion.getAttack() - minion.getAttributeValue(Attribute.TEMPORARY_ATTACK_BONUS));
    minionScore += weights.get(WeightedFeature.MINION_HP_FACTOR) * minion.getHp();

    if (minion.hasAttribute(Attribute.TAUNT)) {
      switch (threatLevel) {
        case RED:
          minionScore += weights.get(WeightedFeature.MINION_RED_TAUNT_MODIFIER);
          break;
        case YELLOW:
          minionScore += weights.get(WeightedFeature.MINION_YELLOW_TAUNT_MODIFIER);
          break;
        default:
          minionScore += weights.get(WeightedFeature.MINION_DEFAULT_TAUNT_MODIFIER);
          break;
      }
    }

    if (minion.hasAttribute(Attribute.WINDFURY)) {
      minionScore += weights.get(WeightedFeature.MINION_WINDFURY_MODIFIER);
    } else if (minion.hasAttribute(Attribute.MEGA_WINDFURY)) {
      minionScore += 2 * weights.get(WeightedFeature.MINION_WINDFURY_MODIFIER);
    }

    if (minion.hasAttribute(Attribute.DIVINE_SHIELD)) {
      minionScore += weights.get(WeightedFeature.MINION_DIVINE_SHIELD_MODIFIER);
    }
    if (minion.hasAttribute(Attribute.SPELL_DAMAGE)) {
      minionScore +=
          minion.getAttributeValue(Attribute.SPELL_DAMAGE)
              * weights.get(WeightedFeature.MINION_SPELL_POWER_MODIFIER);
    }

    if (minion.hasAttribute(Attribute.STEALTH)) {
      minionScore += weights.get(WeightedFeature.MINION_STEALTHED_MODIFIER);
    }
    if (minion.hasAttribute(Attribute.UNTARGETABLE_BY_SPELLS)) {
      minionScore += weights.get(WeightedFeature.MINION_UNTARGETABLE_BY_SPELLS_MODIFIER);
    }

    return minionScore;
  }
  private static ThreatLevel calcuateThreatLevel(GameContext context, int playerId) {
    int damageOnBoard = 0;
    Player player = context.getPlayer(playerId);
    Player opponent = context.getOpponent(player);
    for (Minion minion : opponent.getMinions()) {
      damageOnBoard += minion.getAttack() * minion.getAttributeValue(Attribute.NUMBER_OF_ATTACKS);
    }
    damageOnBoard += getHeroDamage(opponent.getHero());

    int remainingHp = player.getHero().getEffectiveHp() - damageOnBoard;
    if (remainingHp < 1) {
      return ThreatLevel.RED;
    } else if (remainingHp < 15) {
      return ThreatLevel.YELLOW;
    }

    return ThreatLevel.GREEN;
  }