From a45a6da1940995ecde1a082db410cec53595df7f Mon Sep 17 00:00:00 2001 From: Seyed Alireza Hashemi Date: Mon, 13 May 2024 20:07:01 +0330 Subject: [PATCH] refactor move_on_edge function --- apps/fsm/admin.py | 9 ++++- ...n_is_edge_transited_in_reverse_and_more.py | 32 ++++++++++++++++ apps/fsm/models.py | 4 +- apps/fsm/utils.py | 37 +++++++++++++------ apps/fsm/views/edge_view.py | 13 ++----- apps/fsm/views/player_view.py | 14 +++---- 6 files changed, 78 insertions(+), 31 deletions(-) create mode 100644 apps/fsm/migrations/0123_remove_playertransition_is_edge_transited_in_reverse_and_more.py diff --git a/apps/fsm/admin.py b/apps/fsm/admin.py index 0a87dc48..e3f2cf3a 100644 --- a/apps/fsm/admin.py +++ b/apps/fsm/admin.py @@ -6,7 +6,7 @@ from django.http import HttpResponseRedirect, HttpResponse from import_export.admin import ExportActionMixin -from apps.fsm.models import Choice, DetailBoxWidget, Edge, Paper, ProgramContactInfo, RegistrationForm, Problem, AnswerSheet, RegistrationReceipt, Team, \ +from apps.fsm.models import Choice, DetailBoxWidget, Edge, Paper, PlayerTransition, ProgramContactInfo, RegistrationForm, Problem, AnswerSheet, RegistrationReceipt, Team, \ Invitation, CertificateTemplate, Font, FSM, State, WidgetHint, Hint, Widget, Video, Audio, Image, Player, Iframe, SmallAnswerProblem, \ SmallAnswer, BigAnswerProblem, BigAnswer, MultiChoiceProblem, MultiChoiceAnswer, Answer, TextWidget, Event, \ UploadFileAnswer, UploadFileProblem, PlayerStateHistory, Article, Tag, Aparat @@ -56,6 +56,13 @@ def delta_time(self, obj): return "-" +@admin.register(PlayerTransition) +class PlayerTransitionAdmin(admin.ModelAdmin): + model = PlayerTransition + list_display = ['source_state', 'target_state', 'time', 'transited_edge'] + list_filter = [] + + class TextWidgetAdmin(admin.ModelAdmin): model = TextWidget list_display = ['paper', 'text'] diff --git a/apps/fsm/migrations/0123_remove_playertransition_is_edge_transited_in_reverse_and_more.py b/apps/fsm/migrations/0123_remove_playertransition_is_edge_transited_in_reverse_and_more.py new file mode 100644 index 00000000..cd2d8a11 --- /dev/null +++ b/apps/fsm/migrations/0123_remove_playertransition_is_edge_transited_in_reverse_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.1.3 on 2024-05-13 16:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fsm', '0122_rename_playertransitionhistory_playertransition_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='playertransition', + name='is_edge_transited_in_reverse', + ), + migrations.AlterField( + model_name='playerstatehistory', + name='arrival_time', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='playertransition', + name='time', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='tag', + name='created_at', + field=models.DateTimeField(auto_now_add=True), + ), + ] diff --git a/apps/fsm/models.py b/apps/fsm/models.py index 2a6f0835..d63cf3fe 100644 --- a/apps/fsm/models.py +++ b/apps/fsm/models.py @@ -410,7 +410,9 @@ class PlayerTransition(models.Model): time = models.DateTimeField(auto_now_add=True) transited_edge = models.ForeignKey(Edge, related_name='player_transition_histories', null=True, blank=True, on_delete=models.SET_NULL) - is_edge_transited_in_reverse = models.BooleanField(null=True, blank=True) + + def is_edge_transited_in_reverse(self): + return True # todo: fix class PlayerStateHistory(models.Model): diff --git a/apps/fsm/utils.py b/apps/fsm/utils.py index 847173cc..360ae932 100644 --- a/apps/fsm/utils.py +++ b/apps/fsm/utils.py @@ -1,3 +1,4 @@ +from django.utils import timezone from errors.error_codes import serialize_error from rest_framework.exceptions import ParseError import logging @@ -7,7 +8,7 @@ from django.core.files.uploadedfile import InMemoryUploadedFile from django.db.models import Q -from apps.fsm.models import FSM, Edge, Player, PlayerStateHistory, RegistrationReceipt +from apps.fsm.models import FSM, Edge, Player, PlayerStateHistory, PlayerTransition, RegistrationReceipt, State def go_next_step(player): @@ -63,21 +64,35 @@ def get_player(user, fsm, receipt) -> Player: return user.players.filter(fsm=fsm, receipt=receipt, is_active=True).first() -def move_on_edge(player: Player, edge: Edge, departure_time, is_forward) -> Player: - player.current_state = edge.head if is_forward else edge.tail - player.last_visit = departure_time +def transit_player_in_fsm(player: Player, source_state: State, target_state: State, edge: Edge) -> Player: + player.current_state = target_state + transition_time = timezone.now() + + player.last_visit = transition_time player.save() + + player_transition = PlayerTransition.objects.create( + source_state=source_state, + target_state=target_state, + time=transition_time, + transited_edge=edge + ) + try: last_state_history = PlayerStateHistory.objects.filter( - player=player, state=edge.tail if is_forward else edge.head, departure_time=None).last() - last_state_history.departure_time = departure_time + player=player, state=source_state, departure_time=None).last() + last_state_history.departure_time = transition_time + last_state_history.departure = player_transition last_state_history.save() except: - last_state_history = None - PlayerStateHistory.objects.create(player=player, - state=edge.head if is_forward else edge.tail, - transited_edge=edge, arrival_time=departure_time, - is_edge_transited_in_reverse=not is_forward) + pass + + PlayerStateHistory.objects.create( + player=player, + state=target_state, + arrival=player_transition, + ) + return player diff --git a/apps/fsm/views/edge_view.py b/apps/fsm/views/edge_view.py index 48dfcc1d..225c6896 100644 --- a/apps/fsm/views/edge_view.py +++ b/apps/fsm/views/edge_view.py @@ -15,7 +15,7 @@ from apps.fsm.permissions import IsEdgeModifier from apps.fsm.serializers.fsm_serializers import EdgeSerializer, KeySerializer, TeamGetSerializer from apps.fsm.serializers.player_serializer import PlayerSerializer -from apps.fsm.utils import get_receipt, get_player, move_on_edge, get_a_player_from_team +from apps.fsm.utils import get_receipt, get_player, transit_player_in_fsm, get_a_player_from_team logger = logging.getLogger(__name__) @@ -72,12 +72,10 @@ def go_forward(self, request, pk): # todo - handle scoring things - departure_time = timezone.now() for member in team.members.all(): player = member.get_player_of(fsm=fsm) if player: - player = move_on_edge( - player, edge, departure_time, is_forward=True) + player = transit_player_in_fsm(player, edge.tail, edge.head, edge) if player.id == player.id: player = player @@ -92,9 +90,7 @@ def go_forward(self, request, pk): raise ParseError(serialize_error('4083')) elif fsm.fsm_p_type in [FSM.FSMPType.Individual, FSM.FSMPType.Hybrid]: if player.current_state == edge.tail: - departure_time = timezone.now() - player = move_on_edge( - player, edge, departure_time, is_forward=True) + player = transit_player_in_fsm(player, edge.tail, edge.head, edge) return Response(PlayerSerializer(context=self.get_serializer_context()).to_representation(player), status=status.HTTP_200_OK) elif player.current_state == edge.head: @@ -120,7 +116,6 @@ def mentor_move_forward(self, request, pk): for member in team.members.all(): player = member.get_player_of(fsm=fsm) if player: - player = move_on_edge( - player, edge, departure_time=timezone.now(), is_forward=True) + player = transit_player_in_fsm(player, edge.tail, edge.head, edge) return Response({'message': 'ok'}, status=status.HTTP_200_OK) diff --git a/apps/fsm/views/player_view.py b/apps/fsm/views/player_view.py index d475ae3f..f8101f8c 100644 --- a/apps/fsm/views/player_view.py +++ b/apps/fsm/views/player_view.py @@ -16,7 +16,7 @@ from apps.fsm.models import FSM from apps.fsm.serializers.fsm_serializers import KeySerializer, TeamGetSerializer from apps.fsm.serializers.player_serializer import PlayerSerializer -from apps.fsm.utils import move_on_edge, get_player_latest_taken_edge +from apps.fsm.utils import transit_player_in_fsm, get_player_latest_taken_edge class PlayerViewSet(viewsets.GenericViewSet, RetrieveModelMixin): @@ -58,12 +58,10 @@ def go_backward(self, request, pk): raise ParseError(serialize_error('4089')) if player.current_state == edge.head: - departure_time = timezone.now() for member in team.members.all(): player = member.get_player_of(fsm=fsm) if player: - player = move_on_edge( - player, edge, departure_time, is_forward=False) + player = transit_player_in_fsm(player, edge.head, edge.tail, edge) if player.id == player.id: player = player return Response(PlayerSerializer(context=self.get_serializer_context()).to_representation(player), @@ -76,9 +74,7 @@ def go_backward(self, request, pk): elif fsm.fsm_p_type in [FSM.FSMPType.Individual, FSM.FSMPType.Hybrid]: if player.current_state == edge.head: - departure_time = timezone.now() - player = move_on_edge( - player, edge, departure_time, is_forward=False) + player = transit_player_in_fsm(player, edge.head, edge.tail, edge) return Response(PlayerSerializer(context=self.get_serializer_context()).to_representation(player), status=status.HTTP_200_OK) elif player.current_state == edge.tail: @@ -108,8 +104,8 @@ def mentor_move_backward(self, request, pk): for member in team.members.all(): player = member.get_player_of(fsm=fsm) if player: - player = move_on_edge( - player, edge, departure_time, is_forward=False) + player = transit_player_in_fsm( + player, edge.head, edge.tail, edge, departure_time) if player.id == player.id: player = player return Response(PlayerSerializer(context=self.get_serializer_context()).to_representation(player),