<gh_stars>0
# library imports

# project imports
from consumer_brain import ConsumerBrain


class Consumer:
    """
    A consumer agent with agenda to optimize
    """

    def __init__(self,
                 index: int,
                 current_money: float,
                 salary: float,
                 preferences: list):
        self._index = index
        self._current_money = current_money
        self._salary = salary
        self._preferences = preferences
        self._brain = ConsumerBrain()

        # changing members
        self._policy_index = 0
        self._policy = []
        self._purchases_scores = []

    # save\load functions #

    def to_json(self):
        return {"_index": self._index,
                "_current_money": self._current_money,
                "_salary": self._salary,
                "_preferences": self._preferences,
                "_brain": self._brain.to_json(),
                "_policy_index": self._policy_index,
                "_policy": self._policy,
                "_purchases_scores": self._purchases_scores}

    @staticmethod
    def from_json(data):
        answer = Consumer(index=data["_index"],
                          current_money=data["_current_money"],
                          salary=data["_salary"],
                          preferences=data["_preferences"])
        answer._policy_index = data["_policy_index"]
        answer._policy = data["_policy"]
        answer._purchases_scores = data["_purchases_scores"]
        return answer

    # end - save\load functions #

    # getters #

    def get_index(self):
        return self._index

    def get_current_money(self):
        return self._current_money

    def get_salary(self):
        return self._salary

    def get_preferences(self):
        return self._preferences

    # end - getters #

    # logic #

    def evaluate_utility(self):
        answer = 0
        for score in self._purchases_scores:
            answer += score
        return answer

    def buy(self,
            products: dict):
        # if _policy ended, find the product that optimize happiness in a greedy way
        if self._policy_index > len(self._policy):
            best_preference = 0
            product_price = 0
            best_product = None
            for key, price in products.items():
                if price < self._current_money and self._preferences[key] > best_preference:
                    best_preference = self._preferences[key]
                    best_product = key
                    product_price = price
            if best_product is not None:
                self._current_money -= product_price
                self._purchases_scores.append(best_preference)
                # tell to the simulator what has been bought
                return best_product
            else:
                # tell to the simulator no buy has happen
                raise Exception("Error at Consumer.buy saying no possible product to buy")
        # if we have _policy, do it
        try:
            pick_product_key = self._policy[self._policy_index]
            pick_product_price = products[pick_product_key]
            # try to buy it
            if pick_product_price < self._current_money:
                self._current_money -= pick_product_price
                self._purchases_scores.append(self._preferences[self._policy[self._policy_index]])
            self._policy_index += 1
            # tell to the simulator what has been bought
            return pick_product_key
        except Exception as error:
            # tell to the simulator no buy has happen
            raise Exception("Error at Consumer.buy saying: {}".format(error))

    def been_marketed(self,
                      products_preferences: dict):
        for key, preferences_add in products_preferences.items():
            self._preferences[key] += preferences_add

    def update_policy(self,
                      products: list):
        # clear last cycle
        self._purchases_scores = []
        self._current_money += self._salary
        # update the _policy
        self._policy_index = 0
        self._policy = self._brain.run(self._current_money,
                                       self._preferences,
                                       products)

    # end - logic #

    def __repr__(self):
        return "<Consumer | id: {}>".format(self._index)

    def __str__(self):
        return "<Consumer | id: {}, current_money: {}, salary: {}>".format(self._index,
                                                                           self._current_money,
                                                                           self._salary)

# library imports

# project imports
from consumer_brain import ConsumerBrain


class Consumer:
    """
    A consumer agent with agenda to optimize
    """

    def __init__(self,
                 index: int,
                 current_money: float,
                 salary: float,
                 preferences: list):
        self._index = index
        self._current_money = current_money
        self._salary = salary
        self._preferences = preferences
        self._brain = ConsumerBrain()

        # changing members
        self._policy_index = 0
        self._policy = []
        self._purchases_scores = []

    # save\load functions #

    def to_json(self):
        return {"_index": self._index,
                "_current_money": self._current_money,
                "_salary": self._salary,
                "_preferences": self._preferences,
                "_brain": self._brain.to_json(),
                "_policy_index": self._policy_index,
                "_policy": self._policy,
                "_purchases_scores": self._purchases_scores}

    @staticmethod
    def from_json(data):
        answer = Consumer(index=data["_index"],
                          current_money=data["_current_money"],
                          salary=data["_salary"],
                          preferences=data["_preferences"])
        answer._policy_index = data["_policy_index"]
        answer._policy = data["_policy"]
        answer._purchases_scores = data["_purchases_scores"]
        return answer

    # end - save\load functions #

    # getters #

    def get_index(self):
        return self._index

    def get_current_money(self):
        return self._current_money

    def get_salary(self):
        return self._salary

    def get_preferences(self):
        return self._preferences

    # end - getters #

    # logic #

    def evaluate_utility(self):
        answer = 0
        for score in self._purchases_scores:
            answer += score
        return answer

    def buy(self,
            products: dict):
        # if _policy ended, find the product that optimize happiness in a greedy way
        if self._policy_index > len(self._policy):
            best_preference = 0
            product_price = 0
            best_product = None
            for key, price in products.items():
                if price < self._current_money and self._preferences[key] > best_preference:
                    best_preference = self._preferences[key]
                    best_product = key
                    product_price = price
            if best_product is not None:
                self._current_money -= product_price
                self._purchases_scores.append(best_preference)
                # tell to the simulator what has been bought
                return best_product
            else:
                # tell to the simulator no buy has happen
                raise Exception("Error at Consumer.buy saying no possible product to buy")
        # if we have _policy, do it
        try:
            pick_product_key = self._policy[self._policy_index]
            pick_product_price = products[pick_product_key]
            # try to buy it
            if pick_product_price < self._current_money:
                self._current_money -= pick_product_price
                self._purchases_scores.append(self._preferences[self._policy[self._policy_index]])
            self._policy_index += 1
            # tell to the simulator what has been bought
            return pick_product_key
        except Exception as error:
            # tell to the simulator no buy has happen
            raise Exception("Error at Consumer.buy saying: {}".format(error))

    def been_marketed(self,
                      products_preferences: dict):
        for key, preferences_add in products_preferences.items():
            self._preferences[key] += preferences_add

    def update_policy(self,
                      products: list):
        # clear last cycle
        self._purchases_scores = []
        self._current_money += self._salary
        # update the _policy
        self._policy_index = 0
        self._policy = self._brain.run(self._current_money,
                                       self._preferences,
                                       products)

    # end - logic #

    def __repr__(self):
        return "<Consumer | id: {}>".format(self._index)

    def __str__(self):
        return "<Consumer | id: {}, current_money: {}, salary: {}>".format(self._index,
                                                                           self._current_money,
                                                                           self._salary)
# library imports # project imports A consumer agent with agenda to optimize # changing members # save\load functions # # end - save\load functions # # getters # # end - getters # # logic # # if _policy ended, find the product that optimize happiness in a greedy way # tell to the simulator what has been bought # tell to the simulator no buy has happen # if we have _policy, do it # try to buy it # tell to the simulator what has been bought # tell to the simulator no buy has happen # clear last cycle # update the _policy # end - logic #