diff --git a/apps/roadmap/models.py b/apps/roadmap/models.py index acc2e849..8c5f97af 100644 --- a/apps/roadmap/models.py +++ b/apps/roadmap/models.py @@ -1,16 +1,19 @@ -from django.db import models - -from apps.fsm.models import State +from apps.fsm.models import PlayerTransition, State +# todo: refactor: Link model should be replaced with PlayerTransiton model class Link: source: str target: str - def __init__(self, source, target): + def __init__(self, source: State, target: State): self.source = source self.target = target @staticmethod - def get_link_from_states(source: State, target: State): - return Link(source.name, target.name) + def get_link_from_states(source_state: State, taret_state: State): + return Link(source_state.name, taret_state.name) + + @staticmethod + def get_link_from_transition(player_transition: PlayerTransition): + return Link.get_link_from_states(player_transition.source_state, player_transition.target_state) diff --git a/apps/roadmap/utils.py b/apps/roadmap/utils.py index 9db2a825..3de9c62c 100644 --- a/apps/roadmap/utils.py +++ b/apps/roadmap/utils.py @@ -1,6 +1,7 @@ +from django.utils import timezone from apps.fsm.utils import _get_fsm_edges from apps.roadmap.models import Link -from apps.fsm.models import FSM, Player, PlayerStateHistory, State +from apps.fsm.models import FSM, Player, State, PlayerTransition def _get_fsm_links(fsm_id: int): @@ -11,35 +12,42 @@ def _get_fsm_links(fsm_id: int): return links -def _get_player_taken_path(player_id: int): - player = Player.get_player(player_id) +def _get_player_transited_path(player_id: int): + player: Player = Player.get_player(player_id) + transitions: list[PlayerTransition] = player.player_transitions.all() player_current_state: State = player.current_state - fsm = player_current_state.fsm - histories: list[PlayerStateHistory] = player.player_state_histories.all() + current_time = timezone.now() taken_path: list[Link] = [] # 100 is consumed as maximum length in a fsm graph for i in range(100): - previous_state = _get_previous_taken_state( - player_current_state, histories) + previous_transition = _get_player_previous_transition( + player_current_state, current_time, transitions) # if the transited_edge is deleted, it isn't possible to reach to previous state - if not previous_state: + if not previous_transition: break - taken_path.append(Link.get_link_from_states( - previous_state, player_current_state)) - player_current_state = previous_state + taken_path.append(Link.get_link_from_transition(previous_transition)) + player_current_state = previous_transition.source_state + current_time = previous_transition.time + + print("FFFFFFFFf", taken_path) taken_path.reverse() return taken_path -def _get_previous_taken_state(player_current_state: State, histories: list[PlayerStateHistory]): - for history in histories: - if history.is_edge_transited_in_reverse: - continue - # if the transited_edge is deleted: - if not history.transited_edge: - continue - if history.transited_edge.head == player_current_state: - return history.transited_edge.tail - return None +def _get_player_previous_transition(player_state: State, time, transitions: list[PlayerTransition]) -> PlayerTransition: + try: + last_transition = transitions.filter( + target_state=player_state, time__lte=time).last() + return last_transition + except: + return None + + +def _get_player_previous_state(player_current_state: State, time, transitions: list[PlayerTransition]) -> State: + try: + _get_player_previous_transition( + player_current_state, time, transitions).source_state + except: + return None diff --git a/apps/roadmap/views.py b/apps/roadmap/views.py index cc0227fa..697eaf1c 100644 --- a/apps/roadmap/views.py +++ b/apps/roadmap/views.py @@ -7,13 +7,13 @@ from apps.roadmap.models import Link from apps.fsm.models import FSM from apps.roadmap.serializers import LinkSerializer -from apps.roadmap.utils import _get_fsm_links, _get_player_taken_path +from apps.roadmap.utils import _get_fsm_links, _get_player_transited_path @api_view(["POST"]) def get_player_taken_path(request): player_id = request.data.get('player_id', None) - taken_path: list[Link] = _get_player_taken_path(player_id) + taken_path: list[Link] = _get_player_transited_path(player_id) return Response(data=LinkSerializer(taken_path, many=True).data, status=status.HTTP_200_OK)