Skip to content

Commit

Permalink
#106 few fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
bomzheg committed Nov 15, 2024
1 parent 584705b commit e7c2497
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 19 deletions.
1 change: 1 addition & 0 deletions shvatka/core/models/dto/scn/action/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
TypedKeysState,
BonusKeyDecision,
KeyBonusCondition,
WrongKeyDecision,
)
from .state_holder import InMemoryStateHolder
11 changes: 4 additions & 7 deletions shvatka/core/models/dto/scn/action/decisions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from abc import abstractmethod
from dataclasses import dataclass
from typing import Literal, Sequence, overload

Expand All @@ -7,20 +6,18 @@

@dataclass
class NotImplementedActionDecision(Decision):
type: Literal[DecisionType.NO_ACTION] = DecisionType.NOT_IMPLEMENTED
type: Literal[DecisionType.NOT_IMPLEMENTED] = DecisionType.NOT_IMPLEMENTED


class Decisions(Sequence[Decision]):
def __init__(self, decisions: list[Decision]):
self.decisions = decisions

@overload
@abstractmethod
def __getitem__(self, index: int) -> Decision:
return self.decisions[index]

@overload
@abstractmethod
def __getitem__(self, index: slice) -> Sequence[Decision]:
return self.decisions[index]

Expand All @@ -40,10 +37,10 @@ def get_implemented(self) -> "Decisions":
return self.get_all_except(DecisionType.NOT_IMPLEMENTED)

def get_all(self, *type_: type) -> "Decisions":
return Decisions([d for d in self if isinstance(d, type_)])
return Decisions([d for d in self.decisions if isinstance(d, type_)])

def get_all_except(self, *type_: DecisionType) -> "Decisions":
return Decisions([d for d in self if d.type not in type_])
return Decisions([d for d in self.decisions if d.type not in type_])

def get_all_only(self, *type_: DecisionType) -> "Decisions":
return Decisions([d for d in self if d.type in type_])
return Decisions([d for d in self.decisions if d.type in type_])
14 changes: 12 additions & 2 deletions shvatka/core/models/dto/scn/action/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ class WrongKeyDecision(Decision):
type: Literal[DecisionType.NO_ACTION] = DecisionType.NO_ACTION
key_type: typing.Literal[enums.KeyType.wrong] = enums.KeyType.wrong

def to_parsed_key(self) -> dto.ParsedKey:
return dto.ParsedKey(
type_=self.key_type,
text=self.key,
)

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


@dataclass
class KeyDecision(Decision):
Expand Down Expand Up @@ -91,13 +101,13 @@ class BonusKeyDecision(Decision):
type: DecisionType
key_type: enums.KeyType
duplicate: bool
key: BonusKey | None
key: BonusKey

def to_parsed_key(self) -> dto.ParsedKey:
if self.type == DecisionType.BONUS_TIME:
return dto.ParsedBonusKey(
type_=enums.KeyType.bonus,
text=self.key.text,
text=self.key_text,
bonus_minutes=self.key.bonus_minutes,
)
else:
Expand Down
7 changes: 3 additions & 4 deletions shvatka/core/models/dto/scn/level.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def __init__(self, conditions: Sequence[WinCondition]):

@staticmethod
def validate(conditions: Sequence[WinCondition]) -> None:
keys = set()
keys: set[str] = set()
win_conditions = []
for c in conditions:
if isinstance(c, KeyWinCondition):
Expand All @@ -159,7 +159,7 @@ def validate(conditions: Sequence[WinCondition]) -> None:
text=f"keys already exists {keys.intersection(c.keys)}"
)
keys.union(c.keys)
if isinstance(c, KeyBonusCondition):
elif isinstance(c, KeyBonusCondition):
if keys.intersection({k.text for k in c.keys}):
raise exceptions.LevelError(
text=f"keys already exists {keys.intersection(c.keys)}"
Expand Down Expand Up @@ -247,8 +247,7 @@ def check(self, action: Action, state: StateHolder) -> Decision:
"Will used first but it's not clear %s",
obfuscate_sensitive(significant_key_decisions),
)
else:
return significant_key_decisions[0]
return significant_key_decisions[0]
else:
return NotImplementedActionDecision()

Expand Down
2 changes: 2 additions & 0 deletions shvatka/core/services/game_play.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ async def check_key(
)

new_key = await key_processor.check_key(key=key, player=player, team=team)
if new_key is None:
return
if new_key.is_duplicate:
await view.duplicate_key(key=new_key)
return
Expand Down
17 changes: 14 additions & 3 deletions shvatka/core/services/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ class KeyProcessor:
game: dto.FullGame
locker: KeyCheckerFactory

async def check_key(self, key: str, team: dto.Team, player: dto.Player) -> dto.InsertedKey:
async def check_key(
self, key: str, team: dto.Team, player: dto.Player
) -> dto.InsertedKey | None:
if not is_key_valid(key):
raise exceptions.InvalidKey(key=key, team=team, player=player, game=self.game)
return await self.submit_key(key=key, player=player, team=team)
Expand All @@ -29,9 +31,10 @@ async def submit_key(
key: str,
player: dto.Player,
team: dto.Team,
) -> dto.InsertedKey:
) -> dto.InsertedKey | None:
async with self.locker(team):
level = await self.dao.get_current_level(team, self.game)
assert level.number_in_game is not None
correct_keys = await self.dao.get_correct_typed_keys(
level=level, game=self.game, team=team
)
Expand All @@ -46,7 +49,9 @@ async def submit_key(
action=action.TypedKeyAction(key=key),
state=state,
)
if isinstance(decision, action.KeyDecision | action.BonusKeyDecision):
if isinstance(
decision, action.KeyDecision | action.BonusKeyDecision | action.WrongKeyDecision
):
saved_key = await self.dao.save_key(
key=decision.key_text,
team=team,
Expand All @@ -62,3 +67,9 @@ async def submit_key(
return dto.InsertedKey.from_key_time(
saved_key, is_level_up, parsed_key=decision.to_parsed_key()
)
elif isinstance(decision, action.NotImplementedActionDecision):
logger.warning("impossible decision here cant be not implemented")
return None
else:
logger.warning("impossible decision here is %s", type(decision))
return None
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def map_level_for_upload(level: dto.Level) -> data.LevelForUpload:
hint_number=0,
next_hint_time=scn.time_hints[1].time,
text=hint_parts_to_text(first_hint.hint),
key="".join(scn.keys),
key="".join(scn.get_keys()),
brain_key="",
)
hints = []
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/bot_full/test_level_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,6 @@ async def test_write_level(
assert 1 == await dao.level.count()
level, *_ = await dao.level.get_all_my(author)
assert author.id == level.author.id
assert {"SHTESTKEY"} == level.scenario.keys
assert {"SHTESTKEY"} == level.scenario.get_keys()
assert 2 == level.hints_count
bot.auto_mock_success = False
2 changes: 1 addition & 1 deletion tests/integration/test_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ async def test_simple_level(simple_scn: RawGameScenario, dao: HolderDao, retort:
assert lvl.game_id is None
assert lvl.number_in_game is None

assert lvl.scenario.keys == {"SH123", "SH321"}
assert lvl.scenario.get_keys() == {"SH123", "SH321"}

0 comments on commit e7c2497

Please sign in to comment.