from typing import List, Optional, Tuple

from axelrod._strategy_utils import detect_cycle

from axelrod.action import Action

from axelrod.player import Player

C, D = Action.C, Action.D

def is_alternator(history: List[Action]) -> bool:
    for i in range(len(history) - 1):
        if history[i] == history[i + 1]:
            return False
    return True

class MathConstantHunter(Player):
    """A player who hunts for mathematical constant players.

    Names:

    Math Constant Hunter: Original name by Karol Langner
    """

    name = "Math Constant Hunter"
    classifier = {
        "memory_depth": float("inf"),  # Long memory
        "stochastic": False,
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }

    def strategy(self, opponent: Player) -> Action:
        """
        Check whether the number of cooperations in the first and second halves
        of the history are close. The variance of the uniform distribution (1/4)
        is a reasonable delta but use something lower for certainty and avoiding
        false positives. This approach will also detect a lot of random players.
        """

        n = len(self.history)
        if n >= 8 and opponent.cooperations and opponent.defections:
            start1, end1 = 0, n // 2
            start2, end2 = n // 4, 3 * n // 4
            start3, end3 = n // 2, n
            count1 = opponent.history[start1:end1].count(C) + self.history[
                start1:end1
            ].count(C)
            count2 = opponent.history[start2:end2].count(C) + self.history[
                start2:end2
            ].count(C)
            count3 = opponent.history[start3:end3].count(C) + self.history[
                start3:end3
            ].count(C)
            ratio1 = 0.5 * count1 / (end1 - start1)
            ratio2 = 0.5 * count2 / (end2 - start2)
            ratio3 = 0.5 * count3 / (end3 - start3)
            if abs(ratio1 - ratio2) < 0.2 and abs(ratio1 - ratio3) < 0.2:
                return D
        return C