Coverage for events/views.py: 32%
135 statements
« prev ^ index » next coverage.py v6.4.4, created at 2022-10-12 12:25 -0500
« prev ^ index » next coverage.py v6.4.4, created at 2022-10-12 12:25 -0500
1from random import shuffle, choice
2from django.db import transaction
3from rest_framework.decorators import action
4from rest_framework.exceptions import ValidationError
5from rest_framework.mixins import (CreateModelMixin as Create, ListModelMixin as List, RetrieveModelMixin as Detail,
6 UpdateModelMixin as Update)
7from rest_framework.permissions import AllowAny
8from rest_framework.response import Response
9from rest_framework.viewsets import GenericViewSet
10from app.mixins import ActionSerializerMixin
11from .models import Event, Challenge, Participant, StationCheckIn, Station
12from .serializers import (EventDisplaySerializer, EventDetailSerializer, ChallengeDetailSerializer,
13 SaveScoresSerializer, ChallengeSerializer, ParticipantSerializer, TeamSerializer,
14 EventSerializer, ParticipantDetailSerializer, StationCheckInSerializer)
17class EventViewSet(ActionSerializerMixin, GenericViewSet, List, Detail):
18 serializer_class = EventSerializer
19 action_serializers = {'display': EventDisplaySerializer, 'retrieve': EventDetailSerializer}
21 def get_queryset(self):
22 return Event.objects.filter(participants__user=self.request.user)
24 def get_serializer_context(self):
25 context = super(EventViewSet, self).get_serializer_context()
26 context['user'] = self.request.user
27 return context
29 @action(detail=True, methods=['GET'])
30 def display(self, request, *args, **kwargs):
31 return super(EventViewSet, self).retrieve(request, *args, **kwargs)
33 @action(detail=True, methods=['POST'])
34 def challenges_order(self, request, *args, **kwargs):
35 challenge_list = request.data.get('challenges')
36 order = 1
37 for item in challenge_list:
38 challenge = Challenge.objects.get(random_slug=item.get('random_slug'))
39 challenge.order = order
40 challenge.save()
41 order += 1
42 return Response()
44 @action(detail=True, methods=['POST'])
45 def randomize_participants(self, request, pk):
46 event = Event.objects.get(random_slug=pk)
47 teams_count = event.teams.count()
48 teams = list(event.teams.all())
49 participants = list(event.participants.all())
51 shuffle(participants)
53 team_number = 0
54 while len(participants) > 0:
55 participant = participants.pop()
56 participant.team = teams[team_number % teams_count]
57 participant.save()
58 team_number += 1
60 serializer = TeamSerializer(event.teams.all(), many=True)
62 return Response(serializer.data)
65class ChallengeViewSet(ActionSerializerMixin, GenericViewSet, Detail, Create, Update):
66 action_serializers = {'retrieve': ChallengeDetailSerializer, 'create': ChallengeSerializer}
68 def get_serializer_context(self):
69 context = super(ChallengeViewSet, self).get_serializer_context()
70 context['user'] = self.request.user
71 return context
73 def get_queryset(self):
74 qs = Challenge.objects.filter(event__participants__user=self.request.user)
75 return qs
77 @action(detail=True, methods=['PATCH'])
78 def activate(self, request, *args, **kwargs):
79 challenge = self.get_object()
80 challenge.status = challenge.Status.CURRENT
81 challenge.save()
83 # create stations for teams
84 if challenge.type_of == challenge.Type.SCAVENGER_HUNT:
85 stations_list = list(challenge.stations.all())
86 with transaction.atomic():
87 for team in challenge.event.teams.all():
88 if challenge.scavenger_order == challenge.StationsOrder.UNORDERED:
89 for station in stations_list:
90 StationCheckIn.objects.create(
91 team=team,
92 station=station,
93 )
94 else:
95 if challenge.scavenger_order == challenge.StationsOrder.DEFAULT:
96 first_station = challenge.stations.get(order=1)
97 else:
98 first_station = choice(stations_list)
99 StationCheckIn.objects.create(
100 team=team,
101 station=first_station,
102 )
103 return Response()
105 @action(detail=True, methods=['PATCH'])
106 def deactivate(self, request, *args, **kwargs):
107 challenge = self.get_object()
108 challenge.status = challenge.Status.PAST
109 challenge.save()
110 return Response()
113class ScoresViewSet(GenericViewSet):
114 def create(self, request):
115 serializer = SaveScoresSerializer(data=request.data)
116 serializer.is_valid(True)
117 serializer.save()
118 challenge = Challenge.objects.get(random_slug=request.data.get('challenge'))
119 scores = challenge.scores.order_by('position')
120 max_position = max([s.position for s in scores] + [0])
121 positions = []
122 for i in range(max_position):
123 positions.append(None)
124 for s in scores:
125 positions[s.position - 1] = s.score
126 return Response(positions)
129class ParticipantViewSet(ActionSerializerMixin, GenericViewSet, Create, Detail, Update):
130 serializer_class = ParticipantDetailSerializer
131 queryset = Participant.objects.all()
132 action_serializers = {'create': ParticipantSerializer}
134 def get_permissions(self):
135 if self.action == 'partial_update':
136 return [AllowAny()]
137 return super(ParticipantViewSet, self).get_permissions()
139 def perform_create(self, serializer):
140 serializer.save(invited_by=self.request.user)
143class TeamViewSet(GenericViewSet, Create):
144 serializer_class = TeamSerializer
147class StationViewSet(GenericViewSet, Create):
149 def get_queryset(self):
150 return Station.objects.filter(
151 check_ins__team__members=self.request.user
152 )
154 @action(methods=['PATCH'], detail=True)
155 def check_in(self, request, pk, *args, **kwargs):
156 station = Station.objects.get(uuid=pk)
157 participant = Participant.objects.get(
158 user=request.user, event=station.challenge.event)
159 try:
160 checkin_instance = StationCheckIn.objects.get(team=participant.team, station=station)
161 except StationCheckIn.DoesNotExist:
162 raise ValidationError("You're not allowed to scan this qr")
163 if checkin_instance.has_checkin:
164 raise ValidationError('Already Scanned QR')
165 checkin_instance.participant = participant
166 checkin_instance.save()
168 next_checkin = None
169 current_station = checkin_instance.station
170 challenge = current_station.challenge
171 if challenge.scavenger_order in [challenge.StationsOrder.STAGGERED, challenge.StationsOrder.DEFAULT]:
172 next_station_order = (current_station.order % challenge.stations.count()) + 1
173 next_station = challenge.stations.get(order=next_station_order)
174 next_checkin, _ = StationCheckIn.objects.get_or_create(station=next_station, team=participant.team)
175 elif challenge.scavenger_order == challenge.StationsOrder.RANDOM:
176 choices = challenge.stations.exclude(checkins__team=participant.team)
177 if choices:
178 next_station = choice(choices)
179 next_checkin = StationCheckIn.objects.create(station=next_station, team=participant.team)
181 data = {
182 'success': True,
183 'station': checkin_instance.station.name,
184 'random_slug': checkin_instance.random_slug,
185 'datetime': checkin_instance.updated_at.strftime('%b %d, %Y at %H:%M'),
186 }
188 return Response(data)