Coverage for events/views.py: 32%

135 statements  

« 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) 

15 

16 

17class EventViewSet(ActionSerializerMixin, GenericViewSet, List, Detail): 

18 serializer_class = EventSerializer 

19 action_serializers = {'display': EventDisplaySerializer, 'retrieve': EventDetailSerializer} 

20 

21 def get_queryset(self): 

22 return Event.objects.filter(participants__user=self.request.user) 

23 

24 def get_serializer_context(self): 

25 context = super(EventViewSet, self).get_serializer_context() 

26 context['user'] = self.request.user 

27 return context 

28 

29 @action(detail=True, methods=['GET']) 

30 def display(self, request, *args, **kwargs): 

31 return super(EventViewSet, self).retrieve(request, *args, **kwargs) 

32 

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() 

43 

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()) 

50 

51 shuffle(participants) 

52 

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 

59 

60 serializer = TeamSerializer(event.teams.all(), many=True) 

61 

62 return Response(serializer.data) 

63 

64 

65class ChallengeViewSet(ActionSerializerMixin, GenericViewSet, Detail, Create, Update): 

66 action_serializers = {'retrieve': ChallengeDetailSerializer, 'create': ChallengeSerializer} 

67 

68 def get_serializer_context(self): 

69 context = super(ChallengeViewSet, self).get_serializer_context() 

70 context['user'] = self.request.user 

71 return context 

72 

73 def get_queryset(self): 

74 qs = Challenge.objects.filter(event__participants__user=self.request.user) 

75 return qs 

76 

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() 

82 

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() 

104 

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() 

111 

112 

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) 

127 

128 

129class ParticipantViewSet(ActionSerializerMixin, GenericViewSet, Create, Detail, Update): 

130 serializer_class = ParticipantDetailSerializer 

131 queryset = Participant.objects.all() 

132 action_serializers = {'create': ParticipantSerializer} 

133 

134 def get_permissions(self): 

135 if self.action == 'partial_update': 

136 return [AllowAny()] 

137 return super(ParticipantViewSet, self).get_permissions() 

138 

139 def perform_create(self, serializer): 

140 serializer.save(invited_by=self.request.user) 

141 

142 

143class TeamViewSet(GenericViewSet, Create): 

144 serializer_class = TeamSerializer 

145 

146 

147class StationViewSet(GenericViewSet, Create): 

148 

149 def get_queryset(self): 

150 return Station.objects.filter( 

151 check_ins__team__members=self.request.user 

152 ) 

153 

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() 

167 

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) 

180 

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 } 

187 

188 return Response(data)