# Path: lcs/strategies/action_selection/BestAction.py
# class BestAction:
# 
#     def __init__(self, all_actions: int):
#         self.all_actions = all_actions
# 
#     def __call__(self, population):
#         cl = population.get_best_classifier()
# 
#         if cl is not None:
#             return cl.action
#         else:
#             return np.random.randint(self.all_actions)
# 
# Path: lcs/strategies/action_selection/RandomAction.py
# class RandomAction:
# 
#     def __init__(self, all_actions: int):
#         self.all_actions = all_actions
# 
#     def __call__(self, population):
#         return np.random.randint(self.all_actions)


from itertools import groupby
from . import RandomAction, BestAction
import numpy as np
import lcs.agents.acs as acs
import lcs.agents.acs2 as acs2
class KnowledgeArray:
    """
    Knowledge-array bias.

    Creates 'knowledge array' that represents the average quality of the
    anticipation for each action in the current list. Chosen is
    the action, ACS2 knows least about the consequences.
    """

    def __init__(self, all_actions: int, **kwargs):
        self.all_actions = all_actions
        self.epsilon = kwargs['epsilon']
        self.biased_exploration_prob = kwargs['biased_exploration_prob']
        assert 0 <= self.epsilon <= 1
        assert 0 <= self.biased_exploration_prob <= 1

    def __call__(self, population) -> int:
        if np.random.uniform() < self.epsilon:
            if np.random.uniform() < self.biased_exploration_prob:
                # We are in biased exploration
                if type(population) is acs.ClassifiersList:
                    raise NotImplementedError()
                elif type(population) is acs2.ClassifiersList:
                    return self._handle_knowledge_array_for_acs2(population)
                else:
                    raise TypeError()
            else:
                # Normal exploration
                return RandomAction(all_actions=self.all_actions)(population)
        else:

# Path: lcs/strategies/action_selection/BestAction.py
# class BestAction:
# 
#     def __init__(self, all_actions: int):
#         self.all_actions = all_actions
# 
#     def __call__(self, population):
#         cl = population.get_best_classifier()
# 
#         if cl is not None:
#             return cl.action
#         else:
#             return np.random.randint(self.all_actions)
# 
# Path: lcs/strategies/action_selection/RandomAction.py
# class RandomAction:
# 
#     def __init__(self, all_actions: int):
#         self.all_actions = all_actions
# 
#     def __call__(self, population):
#         return np.random.randint(self.all_actions)


# Path: lcs/strategies/action_selection/KnowledgeArray.py
from itertools import groupby
from . import RandomAction, BestAction
import numpy as np
import lcs.agents.acs as acs
import lcs.agents.acs2 as acs2

class KnowledgeArray:
    """
    Knowledge-array bias.

    Creates 'knowledge array' that represents the average quality of the
    anticipation for each action in the current list. Chosen is
    the action, ACS2 knows least about the consequences.
    """

    def __init__(self, all_actions: int, **kwargs):
        self.all_actions = all_actions
        self.epsilon = kwargs['epsilon']
        self.biased_exploration_prob = kwargs['biased_exploration_prob']
        assert 0 <= self.epsilon <= 1
        assert 0 <= self.biased_exploration_prob <= 1

    def __call__(self, population) -> int:
        if np.random.uniform() < self.epsilon:
            if np.random.uniform() < self.biased_exploration_prob:
                # We are in biased exploration
                if type(population) is acs.ClassifiersList:
                    raise NotImplementedError()
                elif type(population) is acs2.ClassifiersList:
                    return self._handle_knowledge_array_for_acs2(population)
                else:
                    raise TypeError()
            else:
                # Normal exploration
                return RandomAction(all_actions=self.all_actions)(population)
        else:

            return BestAction(all_actions=self.all_actions)(population)