Coverage for events/serializers/__init__.py: 58%
182 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-03-30 17:01 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-03-30 17:01 -0600
1from .checkin import MakeCheckInSerializer, StationCheckInSerializer, StationCheckInDetailSerializer
3import datetime
4from rest_framework import serializers
5from users.models import User
6from ..models import Event, Challenge, Team, Score, Participant, StationCheckIn, Station
9class ChallengeSerializer(serializers.ModelSerializer):
10 score = serializers.SerializerMethodField(read_only=True)
12 class Meta:
13 model = Challenge
14 fields = ["random_slug", "event", "name", "status", "score", "type_of", "start_date", "end_date"]
15 extra_kwargs = {"status": {"read_only": True}}
17 def get_score(self, challenge):
18 try:
19 participant = Participant.objects.get(event=challenge.event, user=self.context.get("user"))
20 score = challenge.scores.get(team=participant.team)
21 return score.score
22 except (Participant.DoesNotExist, Score.DoesNotExist):
23 return None
26class EventSerializer(serializers.ModelSerializer):
27 owner = serializers.CharField(source="owner.name", read_only=True)
28 is_master_of_ceremony = serializers.SerializerMethodField(read_only=True)
30 class Meta:
31 model = Event
32 fields = [
33 "random_slug",
34 "name",
35 "date",
36 "image",
37 "owner",
38 "is_master_of_ceremony",
39 "image",
40 ]
42 def get_is_master_of_ceremony(self, event):
43 try:
44 participant = Participant.objects.get(event=event, user=self.context.get("user"))
45 return participant.is_master_of_ceremony
46 except Participant.DoesNotExist:
47 return None
50class ParticipantDetailSerializer(serializers.ModelSerializer):
51 event = EventSerializer(read_only=True)
52 invited_by = serializers.CharField(source="invited_by.email", read_only=True)
54 class Meta:
55 model = Participant
56 fields = ["random_slug", "event", "is_master_of_ceremony", "rsvp", "invited_by"]
59class ParticipantSerializer(serializers.ModelSerializer):
60 email = serializers.EmailField(source="user.email")
61 full_name = serializers.SerializerMethodField()
63 class Meta:
64 model = Participant
65 fields = ["random_slug", "email", "event", "is_master_of_ceremony", "full_name"]
67 def create(self, validated_data):
68 email = validated_data.get("user").get("email")
69 user, _ = User.objects.get_or_create(email=email)
70 validated_data["user"] = user
71 participant, _ = Participant.objects.get_or_create(**validated_data)
72 return participant
74 def get_full_name(self, instance):
75 return f"{instance.user.first_name} {instance.user.last_name}"
78class TeamScoreSerializer(serializers.ModelSerializer):
79 members = ParticipantSerializer(many=True, read_only=True)
81 class Meta:
82 model = Team
83 fields = ["random_slug", "name", "total_score", "members"]
84 extra_kwargs = {
85 "total_score": {"read_only": True},
86 }
89class TeamSerializer(serializers.ModelSerializer):
90 members = ParticipantSerializer(many=True, read_only=True)
92 class Meta:
93 model = Team
94 fields = ["random_slug", "name", "members", "event"]
95 extra_kwargs = {"event": {"write_only": True}}
98class EventDisplaySerializer(EventSerializer):
99 challenges = ChallengeSerializer(many=True, read_only=True)
100 teams = serializers.SerializerMethodField(read_only=True)
101 my_team = serializers.SerializerMethodField(read_only=True)
103 class Meta:
104 model = Event
105 fields = [
106 "random_slug",
107 "name",
108 "challenges",
109 "teams",
110 "date",
111 "my_team",
112 "is_master_of_ceremony",
113 "image",
114 ]
116 def get_teams(self, instance):
117 teams = instance.teams.all()
118 serializer = TeamScoreSerializer(teams, many=True)
119 data = serializer.data
120 return sorted(data, key=lambda item: item["total_score"], reverse=True)
122 def get_my_team(self, instance):
123 try:
124 participant = instance.participants.get(user=self.context.get("user"))
125 return participant.team.random_slug if participant.team else None
126 except Participant.DoesNotExist:
127 return None
130class EventDetailSerializer(EventDisplaySerializer):
131 participants = serializers.SerializerMethodField(read_only=True)
132 teams = TeamSerializer(many=True, read_only=True)
134 class Meta(EventDisplaySerializer.Meta):
135 fields = ["random_slug", "name", "challenges", "participants", "teams", "date"]
137 def get_participants(self, instance):
138 participants = instance.participants.filter(team__isnull=True)
139 serializer = ParticipantSerializer(participants, many=True)
140 return serializer.data
143class SimpleTeamSerializer(serializers.ModelSerializer):
144 class Meta:
145 model = Team
146 fields = ["random_slug", "name"]
147 read_only_fields = fields
150# class StationCheckInDetailSerializer(serializers.ModelSerializer):
151# class Meta:
152# model = StationCheckIn
153# fields = ["team", "participant", "has_checkin", "updated_at"]
156class StationSerializer(serializers.ModelSerializer):
157 check_in = serializers.SerializerMethodField(read_only=True)
159 class Meta:
160 model = Station
161 fields = ["name", "hint", "type_of", "check_in"]
163 def get_check_in(self, station):
164 user = self.context.get("user")
165 event = station.challenge.event
167 participant = user.participants.get(event=event)
168 team = participant.team
169 if team:
170 try:
171 check_in = team.check_ins.get(station=station)
172 return StationCheckInSerializer(check_in).data
173 except StationCheckIn.DoesNotExist:
174 return None
175 return None
178class ChallengeDetailSerializer(serializers.ModelSerializer):
179 event = EventSerializer(read_only=True)
180 finished = serializers.SerializerMethodField(read_only=True)
181 unfinished = serializers.SerializerMethodField(read_only=True)
182 teams_count = serializers.SerializerMethodField(read_only=True)
183 is_master_of_ceremony = serializers.SerializerMethodField(read_only=True)
184 stations = StationSerializer(many=True, read_only=True)
185 my_team = serializers.SerializerMethodField(read_only=True)
187 class Meta:
188 model = Challenge
189 fields = [
190 "random_slug",
191 "name",
192 "objective",
193 "event",
194 "is_master_of_ceremony",
195 "teams_count",
196 "finished",
197 "unfinished",
198 "type_of",
199 "status",
200 "stations",
201 "my_team",
202 "start_date",
203 "end_date",
204 ]
205 extra_kwargs = {"status": {"read_only": True}}
207 def get_finished(self, challenge):
208 scores = challenge.scores.order_by("position")
209 max_position = max([s.position for s in scores] + [0])
210 positions = []
211 for i in range(max_position):
212 positions.append({"teams": [], "points": None})
213 for s in scores:
214 team = SimpleTeamSerializer(s.team)
215 positions[s.position - 1]["teams"].append(team.data)
216 positions[s.position - 1]["points"] = s.score
217 return positions
219 def get_unfinished(self, challenge):
220 qs = challenge.event.teams.exclude(scores__challenge=challenge)
221 return SimpleTeamSerializer(qs, many=True).data
223 def get_teams_count(self, challenge):
224 return challenge.event.teams.count()
226 def get_is_master_of_ceremony(self, challenge):
227 participant = Participant.objects.get(event=challenge.event, user=self.context.get("user"))
228 return participant.is_master_of_ceremony
230 def get_my_team(self, instance):
231 try:
232 participant = instance.event.participants.get(user=self.context.get("user"))
233 return participant.team.random_slug if participant.team else None
234 except Participant.DoesNotExist:
235 return None
237 def to_representation(self, instance):
238 representation = super(ChallengeDetailSerializer, self).to_representation(instance)
239 stations = representation.pop("stations")
240 stations = sorted(stations, key=self._get_station_key)
241 representation["stations"] = stations
242 return representation
244 def _get_station_key(self, item):
245 from django.utils import timezone
247 check_in = item.get("check_in")
248 if check_in:
249 slug = check_in.get("random_slug")
250 instance = StationCheckIn.objects.get(pk=slug)
251 return instance.checkin_timestamp if instance.checkin_timestamp else timezone.now()
253 return timezone.now() + timezone.timedelta(minutes=1)
256class SaveScoresSerializer(serializers.Serializer):
257 challenge = serializers.CharField(write_only=True)
258 positions = serializers.ListField(write_only=True)
260 class Meta:
261 fields = ["challenge", "positions"]
263 def save(self, **kwargs):
264 challenge = Challenge.objects.get(random_slug=self.validated_data.get("challenge"))
266 slugs = []
267 position = 1
268 total_teams = challenge.event.teams.count()
269 scores = [i + 1 for i in range(total_teams)]
271 for item in self.validated_data.get("positions"):
272 score = [scores.pop() for i in range(len(item))]
273 for team in item:
274 random_slug = team.get("random_slug")
275 team = Team.objects.get(random_slug=random_slug)
276 Score.objects.update_or_create(
277 challenge=challenge,
278 team=team,
279 defaults={"position": position, "score": sum(score) / len(score)},
280 )
281 slugs.append(random_slug)
282 position += 1
284 challenge.scores.exclude(team__random_slug__in=slugs).delete()