Verified Commit 0da5df82 authored by Jakob Moser's avatar Jakob Moser
Browse files

Add director

parent 933bce6c
Loading
Loading
Loading
Loading
+92 −0
Original line number Diff line number Diff line
from dataclasses import dataclass, field

from poolpay.model.Card import Card
from poolpay.price.constants import DRINK
from poolpay.ui.Play import Play
from poolpay.ui.scenes.Scene import Scene


@dataclass
class Director:
    """
    Connects the scenes of a play with the underlying model.

    The director knows when which scene needs to be presented and what changes need to
    be done to the model at what time.

    This class is usually called a Controller in most design patterns, but I found
    the name director funnier in this context.
    """

    play: Play
    _next_scene_on_card_presented: type[Scene] = field(init=False)

    def start(self) -> None:
        self.nothing_requested()

    def card_presented(self, card_id: int) -> None:
        card = Card.get_only(card_id)

        if not card:
            # TODO Show error that this card is not enrolled
            return

        match self._next_scene_on_card_presented:
            case self.play.Reversal:
                self._do_reversal(card)
            case self.play.Balance:
                self._do_balance(card)
            case self.play.PaymentSuccess:
                self._do_payment(card)

    def card_removed(self) -> None:
        self.nothing_requested()

    def nothing_requested(self) -> None:
        self._next_scene_on_card_presented = self.play.PaymentSuccess
        self.play.Idle(self, price=DRINK).present()

    def reversal_requested(self) -> None:
        self._next_scene_on_card_presented = self.play.Reversal
        self.play.WaitForCard(self).present()

    def balance_requested(self) -> None:
        self._next_scene_on_card_presented = self.play.Balance
        self.play.WaitForCard(self).present()

    def _do_payment(self, card: Card) -> None:
        # We just pretend that this is certainly atomic and there is no way that we will ever have a race condition here
        old_balance = card.owner.balance_str
        card.owner.pay(DRINK)
        new_balance = card.owner.balance_str

        # TODO Commit to the database

        self.play.PaymentSuccess(
            self,
            old_balance=old_balance,
            new_balance=new_balance,
            person_name=card.owner.name,
        ).present()

    def _do_reversal(self, card: Card) -> None:
        # We just pretend that this is certainly atomic and there is no way that we will ever have a race condition here
        old_balance = card.owner.balance_str
        card.owner.pay(-DRINK)
        new_balance = card.owner.balance_str

        # TODO Commit to the database

        self.play.Reversal(
            self,
            old_balance=old_balance,
            new_balance=new_balance,
            person_name=card.owner.name,
        ).present()

    def _do_balance(self, card: Card) -> None:
        self.play.Balance(
            self,
            balance=card.owner.balance_str,
            person_name=card.owner.name,
        ).present()