@@ -80,23 +80,30 @@ def add_judges():
8080 Round .judges .through .objects .filter (
8181 round__round_number = round_number
8282 ).delete ()
83- judges = list (
83+ # Get all checked-in judges
84+ all_judges = list (
8485 Judge .objects .filter (
85- checkin__round_number = round_number ,
86- wing_only = False
86+ checkin__round_number = round_number
8787 ).prefetch_related (
8888 "judges" , # poorly named relation for the round
8989 "scratches" ,
9090 )
9191 )
92+
93+ # Sort all_judges once before creating filtered subsets
94+ random .seed (1337 )
95+ random .shuffle (all_judges )
96+ all_judges = sorted (all_judges , key = lambda j : j .rank , reverse = True )
97+
98+ chairs = [j for j in all_judges if not j .wing_only ]
99+
92100 pairings = tab_logic .sorted_pairings (round_number )
93101
94102 random .seed (1337 )
95103 random .shuffle (pairings )
96- random .seed (1337 )
97- random .shuffle (judges )
98- judges = sorted (judges , key = lambda j : j .rank , reverse = True )
99- judge_scores = construct_judge_scores (judges , settings .mode )
104+
105+ chair_scores = construct_judge_scores (chairs , settings .mode )
106+
100107 bubble_priority = settings .round_priority == InroundRoundPriority .BUBBLE_ROUNDS
101108 if bubble_priority and round_number > 1 :
102109 bubble_rounds = [p for p in pairings if is_bubble_round (p , round_number )]
@@ -116,90 +123,104 @@ def add_judges():
116123 all_teams .extend ((pairing .gov_team , pairing .opp_team ))
117124 rejudge_counts = {}
118125 if settings .allow_rejudges :
119- rejudge_counts = judge_team_rejudge_counts (judges , all_teams )
126+ rejudge_counts = judge_team_rejudge_counts (chairs , all_teams )
120127
121128 graph_edges = []
122- for judge_i , judge in enumerate (judges ):
123- judge_score = judge_scores [ judge_i ]
129+ for chair_i , chair in enumerate (chairs ):
130+ chair_score = chair_scores [ chair_i ]
124131
125132 for pairing_i , pairing in enumerate (pairings ):
126133 has_conflict = judge_conflict (
127- judge ,
134+ chair ,
128135 pairing .gov_team ,
129136 pairing .opp_team ,
130137 settings .allow_rejudges ,
131138 )
132139 if has_conflict :
133140 continue
134- weight = calc_weight (judge_score , pairing_i , settings .mode )
135- judge_counts = rejudge_counts .get (judge .id )
141+ weight = calc_weight (chair_score , pairing_i , settings .mode )
142+ judge_counts = rejudge_counts .get (chair .id )
136143 rejudge_sum = 0
137144 if judge_counts :
138145 rejudge_sum = (
139146 judge_counts .get (pairing .gov_team .id , 0 )
140147 + judge_counts .get (pairing .opp_team .id , 0 )
141148 )
142149 if rejudge_sum > 0 and settings .rejudge_penalty > 0 :
143- penalty = settings .rejudge_penalty * (1 + 0.1 * judge_score )
150+ penalty = settings .rejudge_penalty * (1 + 0.1 * chair_score )
144151 weight -= penalty * rejudge_sum
145152
146- graph_edges .append ((pairing_i , num_rounds + judge_i , weight ))
153+ graph_edges .append ((pairing_i , num_rounds + chair_i , weight ))
147154 judge_assignments = mwmatching .maxWeightMatching (graph_edges , maxcardinality = True )
148155
149156 if - 1 in judge_assignments [:num_rounds ] or (num_rounds > 0 and not graph_edges ):
150157 if not graph_edges :
151- raise errors .JudgeAssignmentError (
152- "Impossible to assign judges, consider reducing your gaps if you"
153- " are making panels, otherwise find some more judges."
154- )
158+ # Check if we have enough judges including wing_only judges
159+ if len (all_judges ) >= num_rounds :
160+ raise errors .JudgeAssignmentError (
161+ "Impossible to assign chairs to all rounds. You have enough "
162+ "checked-in judges, but some are marked as wing-only and cannot "
163+ "chair. Either check in more non-wing judges or unmark some "
164+ "wing-only judges to allow them to chair."
165+ )
166+ else :
167+ raise errors .JudgeAssignmentError (
168+ "Impossible to assign judges, consider reducing your gaps if you"
169+ " are making panels, otherwise find some more judges."
170+ )
155171 elif - 1 in judge_assignments [:num_rounds ]:
156172 pairing_list = judge_assignments [: len (pairings )]
157173 bad_pairing = pairings [pairing_list .index (- 1 )]
158- raise errors .JudgeAssignmentError (
159- "Could not find a judge for: %s" % str (bad_pairing )
160- )
174+ # Check if we have enough judges including wing_only judges
175+ if len (all_judges ) >= num_rounds and len (chairs ) < num_rounds :
176+ raise errors .JudgeAssignmentError (
177+ "Impossible to assign chairs to all rounds. You have enough "
178+ "checked-in judges, but some are marked as wing-only and cannot "
179+ "chair. Either check in more non-wing judges or unmark some "
180+ "wing-only judges to allow them to chair."
181+ )
182+ else :
183+ raise errors .JudgeAssignmentError (
184+ "Could not find a judge for: %s" % str (bad_pairing )
185+ )
161186 else :
162187 raise errors .JudgeAssignmentError ()
163188
164189 judge_round_joins , chair_by_pairing = [], [None ] * num_rounds
165- assigned_judges = set ()
166- assigned_pairs = set ()
167- for pairing_i , padded_judge_i in enumerate (judge_assignments [:num_rounds ]):
168- judge_i = padded_judge_i - num_rounds
190+ assigned_judge_objects = set () # Track actual Judge objects by ID
191+ for pairing_i , padded_chair_i in enumerate (judge_assignments [:num_rounds ]):
192+ chair_i = padded_chair_i - num_rounds
169193
170194 round_obj = pairings [pairing_i ]
171- judge = judges [ judge_i ]
195+ chair = chairs [ chair_i ]
172196
173- round_obj .chair = judge
174- chair_by_pairing [pairing_i ] = judge_i
175- assigned_judges .add (judge_i )
176- assigned_pairs .add ((pairing_i , judge_i ))
197+ round_obj .chair = chair
198+ chair_by_pairing [pairing_i ] = chair_i
199+ assigned_judge_objects .add (chair .id ) # Track by judge ID
177200 judge_round_joins .append (
178- Round .judges .through (judge = judge , round = round_obj )
201+ Round .judges .through (judge = chair , round = round_obj )
179202 )
180203
181204 Round .objects .bulk_update (pairings , ["chair" ])
182- if settings .pair_wings and num_rounds and len (judges ) > num_rounds :
183- max_per_round = min (3 , len (judges ) // num_rounds + 1 )
205+ if settings .pair_wings and num_rounds and len (all_judges ) > num_rounds :
206+ max_per_round = min (3 , len (all_judges ) // num_rounds + 1 )
184207 for _ in range (1 , max_per_round ):
185- available_indices = [
186- judge_i
187- for judge_i in range (len (judges ))
188- if judge_i not in assigned_judges
189- ]
190- if not available_indices :
208+ # Build wing pool from all_judges excluding already assigned
209+ wing_judges = [j for j in all_judges if j .id not in assigned_judge_objects ]
210+ if not wing_judges :
191211 break
192212
193- wing_pool = list (available_indices )
213+ wing_pool = list (range ( len ( wing_judges )) )
194214 pairing_indices = list (range (num_rounds ))
195215 if settings .wing_mode == WingPairingMode .RANDOM :
196216 random .shuffle (wing_pool )
197217 random .shuffle (pairing_indices )
198218
199219 wing_edges = []
200- for relative_rank , judge_i in enumerate (wing_pool ):
201- judge = judges [judge_i ]
202- judge_score = judge_scores [judge_i ]
220+ wing_judge_scores = construct_judge_scores (wing_judges , settings .mode )
221+ for relative_rank , wing_judge_i in enumerate (wing_pool ):
222+ judge = wing_judges [wing_judge_i ]
223+ judge_score = wing_judge_scores [wing_judge_i ]
203224 for pairing_i in pairing_indices :
204225 pairing = pairings [pairing_i ]
205226 has_conflict = judge_conflict (
@@ -226,34 +247,32 @@ def add_judges():
226247 wing_mode = settings .wing_mode ,
227248 chair_judge_i = chair_by_pairing [pairing_i ],
228249 relative_judge_rank = relative_rank ,
229- judge_index = judge_i ,
250+ judge_index = wing_judge_i ,
230251 )
231252 if rejudge_sum > 0 and settings .rejudge_penalty > 0 :
232253 penalty = settings .rejudge_penalty * (1 + 0.1 * judge_score )
233254 weight -= penalty * rejudge_sum
234255
235- wing_edges .append ((pairing_i , num_rounds + judge_i , weight ))
256+ wing_edges .append ((pairing_i , num_rounds + wing_judge_i , weight ))
236257
237258 if not wing_edges :
238259 break
239260
240261 wing_matches = mwmatching .maxWeightMatching (wing_edges , maxcardinality = True )
241- for pairing_i , padded_judge_i in enumerate (wing_matches [:num_rounds ]):
242- if padded_judge_i == - 1 :
243- continue
244- judge_i = padded_judge_i - num_rounds
245- if judge_i in assigned_judges :
262+ for pairing_i , padded_wing_judge_i in enumerate (wing_matches [:num_rounds ]):
263+ if padded_wing_judge_i == - 1 :
246264 continue
247- if (pairing_i , judge_i ) in assigned_pairs :
265+ wing_judge_i = padded_wing_judge_i - num_rounds
266+ judge = wing_judges [wing_judge_i ]
267+ if judge .id in assigned_judge_objects :
248268 continue
249269 judge_round_joins .append (
250270 Round .judges .through (
251- judge = judges [ judge_i ] ,
271+ judge = judge ,
252272 round = pairings [pairing_i ],
253273 )
254274 )
255- assigned_judges .add (judge_i )
256- assigned_pairs .add ((pairing_i , judge_i ))
275+ assigned_judge_objects .add (judge .id )
257276
258277 Round .judges .through .objects .bulk_create (judge_round_joins )
259278
0 commit comments