Skip to content

Commit

Permalink
added routing for key condition
Browse files Browse the repository at this point in the history
  • Loading branch information
bomzheg committed Jan 2, 2025
1 parent ee6a3d2 commit 5b16f88
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 27 deletions.
10 changes: 9 additions & 1 deletion shvatka/core/interfaces/dal/game_play.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,16 @@ async def get_team_typed_keys(
) -> list[dto.KeyTime]:
raise NotImplementedError

async def level_up(self, team: dto.Team, level: dto.Level, game: dto.Game) -> None:
async def level_up(
self, team: dto.Team, level: dto.Level, game: dto.Game, next_level: dto.Level
) -> None:
raise NotImplementedError

async def finish(self, game: dto.Game) -> None:
raise NotImplementedError

async def get_next_level(self, level: dto.Level, game: dto.Game) -> dto.Level:
raise NotImplementedError

async def get_level_by_name(self, level_name: str, game: dto.Game) -> dto.Level | None:
raise NotImplementedError
1 change: 1 addition & 0 deletions shvatka/core/models/dto/action/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
BonusKeyDecision,
KeyBonusCondition,
WrongKeyDecision,
LevelUpDecision,
)
from .state_holder import InMemoryStateHolder

Expand Down
16 changes: 12 additions & 4 deletions shvatka/core/models/dto/action/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,21 @@ def get(self, state_class: type[T]) -> T:
raise NotImplementedError


class Decision(Protocol):
type: DecisionType


class DecisionType(enum.StrEnum):
NOT_IMPLEMENTED = enum.auto()
LEVEL_UP = enum.auto()
SIGNIFICANT_ACTION = enum.auto()
NO_ACTION = enum.auto()
BONUS_TIME = enum.auto()


class Decision(Protocol):
type: DecisionType

def is_level_up(self) -> bool:
return self.type == DecisionType.LEVEL_UP


class LevelUpDecision(Decision):
type: typing.Literal[DecisionType.LEVEL_UP] = DecisionType.LEVEL_UP
next_level: str | None = None
32 changes: 26 additions & 6 deletions shvatka/core/models/dto/action/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@
from shvatka.core.models import enums
from . import StateHolder
from .decisions import NotImplementedActionDecision
from .interface import Action, State, Decision, Condition, DecisionType, ConditionType
from .interface import (
Action,
State,
Decision,
Condition,
DecisionType,
ConditionType,
LevelUpDecision,
)

SHKey: typing.TypeAlias = str

Expand Down Expand Up @@ -50,25 +58,29 @@ def key_text(self) -> str:
return self.key


@dataclass
@dataclass(kw_only=True)
class KeyDecision(Decision):
type: DecisionType
key_type: enums.KeyType
duplicate: bool
key: SHKey

def is_level_up(self) -> bool:
return self.type == DecisionType.LEVEL_UP

@property
def key_text(self) -> str:
return self.key


@dataclass(kw_only=True)
class LevelUpKeyDecision(KeyDecision, LevelUpDecision):
type: typing.Literal[DecisionType.LEVEL_UP] = DecisionType.LEVEL_UP
next_level: str | None = None


@dataclass
class KeyWinCondition(Condition):
keys: set[SHKey]
type: Literal["WIN_KEY"] = ConditionType.WIN_KEY.name
next_level: str | None = None

def check(self, action: Action, state_holder: StateHolder) -> Decision:
if not isinstance(action, TypedKeyAction):
Expand All @@ -79,7 +91,15 @@ def check(self, action: Action, state_holder: StateHolder) -> Decision:
return WrongKeyDecision(duplicate=state.is_duplicate(action), key=action.key)
if not state.is_duplicate(action):
if self._is_all_typed(action, state):
type_ = DecisionType.LEVEL_UP
return LevelUpKeyDecision(
type=DecisionType.LEVEL_UP,
key_type=enums.KeyType.simple
if self._is_correct(action)
else enums.KeyType.wrong,
duplicate=state.is_duplicate(action),
key=action.key,
next_level=self.next_level,
)
else:
type_ = DecisionType.SIGNIFICANT_ACTION
else:
Expand Down
24 changes: 22 additions & 2 deletions shvatka/core/services/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,15 @@ async def submit_key(
type_=decision.key_type,
is_duplicate=decision.duplicate,
)
if is_level_up := decision.type == action.DecisionType.LEVEL_UP:
await self.dao.level_up(team=team, level=level, game=self.game)
if is_level_up := isinstance(decision, action.LevelUpDecision):
await self.dao.level_up(
team=team,
level=level,
game=self.game,
next_level=await self.define_next_level(
level, self.game, decision.next_level
),
)
await self.dao.commit()
return dto.InsertedKey.from_key_time(
saved_key, is_level_up, parsed_key=decision_to_parsed_key(decision)
Expand All @@ -74,6 +81,19 @@ async def submit_key(
logger.warning("impossible decision here is %s", type(decision))
return None

async def define_next_level(
self, level: dto.Level, game: dto.Game, level_name: str | None = None
) -> dto.Level:
if level_name is None:
return await self.dao.get_next_level(level, game)
else:
next_level = await self.dao.get_level_by_name(level_name, game)
if next_level is None:
raise exceptions.ScenarioNotCorrect(
text="Level name not found", name_id=level_name
)
return next_level


def decision_to_parsed_key(
decision: action.KeyDecision | action.BonusKeyDecision | action.WrongKeyDecision,
Expand Down
15 changes: 12 additions & 3 deletions shvatka/infrastructure/db/dao/complex/game_play.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,14 @@ async def get_team_typed_keys(
) -> list[dto.KeyTime]:
return await self.key_time.get_team_typed_keys(game, team, level_number)

async def level_up(self, team: dto.Team, level: dto.Level, game: dto.Game) -> None:
assert level.number_in_game is not None
async def level_up(
self, team: dto.Team, level: dto.Level, game: dto.Game, next_level: dto.Level
) -> None:
assert next_level.number_in_game is not None
await self.level_time.set_to_level(
team=team,
game=game,
level_number=level.number_in_game + 1,
level_number=next_level.number_in_game,
)

async def finish(self, game: dto.Game) -> None:
Expand All @@ -144,5 +146,12 @@ async def get_orgs(
) -> list[dto.SecondaryOrganizer]:
return await self.organizer.get_orgs(game)

async def get_next_level(self, level: dto.Level, game: dto.Game) -> dto.Level:
assert level.number_in_game is not None
return await self.level.get_by_number(game=game, level_number=level.number_in_game + 1)

async def get_level_by_name(self, level_name: str, game: dto.Game) -> dto.Level | None:
return await self.level.get_by_author_and_name_id(game.author, level_name)

async def commit(self) -> None:
await self.key_time.commit()
27 changes: 20 additions & 7 deletions shvatka/infrastructure/db/dao/rdb/level_times.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,29 @@ def __init__(
super().__init__(models.LevelTime, session, clock=clock)

async def set_to_level(
self, team: dto.Team, game: dto.Game, level_number: int, at: datetime | None = None
self,
team: dto.Team,
game: dto.Game,
level_number: int,
level_name: str | None = None,
at: datetime | None = None,
):
if at is None:
at = datetime.now(tz=tz_utc)
level_time = models.LevelTime(
game_id=game.id,
team_id=team.id,
level_number=level_number,
start_at=at,
)
if level_name is None:
level_time = models.LevelTime(
game_id=game.id,
team_id=team.id,
level_number=level_number,
start_at=at,
)
else:
level_time = models.LevelTime(
game_id=game.id,
team_id=team.id,
level_name=level_name,
start_at=at,
)
self._save(level_time)

async def is_team_on_level(self, team: dto.Team, level: dto.Level) -> bool:
Expand Down
8 changes: 4 additions & 4 deletions tests/fixtures/game_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ async def finished_game(
type_=enums.KeyType.simple,
is_duplicate=False,
)
await dao.game_player.level_up(slytherin, game.levels[0], game)
await dao.game_player.level_up(slytherin, game.levels[0], game, game.levels[1])
await asyncio.sleep(0.1)
await dao.key_time.save_key(
key="SH123",
Expand All @@ -128,7 +128,7 @@ async def finished_game(
type_=enums.KeyType.simple,
is_duplicate=False,
)
await dao.game_player.level_up(gryffindor, game.levels[0], game)
await dao.game_player.level_up(gryffindor, game.levels[0], game, game.levels[1])
await asyncio.sleep(0.2)
await dao.key_time.save_key(
key="SHOOT",
Expand All @@ -139,7 +139,7 @@ async def finished_game(
type_=enums.KeyType.simple,
is_duplicate=False,
)
await dao.game_player.level_up(gryffindor, game.levels[1], game)
await dao.game_player.level_up(gryffindor, game.levels[1], game, game.levels[2])
await asyncio.sleep(0.1)
await dao.key_time.save_key(
key="SHOOT",
Expand All @@ -150,7 +150,7 @@ async def finished_game(
type_=enums.KeyType.simple,
is_duplicate=False,
)
await dao.game_player.level_up(slytherin, game.levels[1], game)
await dao.game_player.level_up(slytherin, game.levels[1], game, game.levels[2])
await dao.game.set_finished(game)
await dao.commit()

Expand Down

0 comments on commit 5b16f88

Please sign in to comment.