@@ -143,6 +143,52 @@ def is_allocated(scode1: str, scode2:str) -> bool:
143
143
else :
144
144
return False
145
145
146
+ def allocate_to_centers (centers : List [Dict [str , str ]], school : Dict [str , str ], to_allot : int , remaining_cap : Dict [str , int ], stretch : bool = False ):
147
+ allocated_centers = {}
148
+ per_center = calc_per_center (to_allot )
149
+
150
+ for center in centers :
151
+ school_code = school ['scode' ]
152
+ center_code = center ['cscode' ]
153
+ writer .writerow ([
154
+ school_code ,
155
+ school ['count' ],
156
+ school ['name-address' ],
157
+ school ['lat' ],
158
+ school ['long' ],
159
+ center_code ,
160
+ center ['name' ],
161
+ center ['address' ],
162
+ center ['capacity' ],
163
+ center ['distance_km' ]
164
+ ])
165
+
166
+ if is_allocated (center_code , school_code ):
167
+ continue
168
+
169
+ centers_cap_left = remaining_cap [center_code ]
170
+
171
+ if stretch :
172
+ stretched_capacity = math .floor (int (center ['capacity' ]) * STRETCH_CAPACITY_FACTOR + centers_cap_left )
173
+ next_allot = min (to_allot , max (stretched_capacity , MIN_STUDENT_IN_CENTER ))
174
+ centers_cap_left = stretched_capacity
175
+ else :
176
+ next_allot = min (to_allot , per_center , max (centers_cap_left , MIN_STUDENT_IN_CENTER ))
177
+
178
+ if to_allot > 0 and next_allot > 0 and centers_cap_left >= next_allot :
179
+ if next_allot < MIN_STUDENT_IN_CENTER and len (allocated_centers ) > 0 :
180
+ # get the first center code
181
+ allocate_center_code = centers [0 ]['cscode' ]
182
+ else :
183
+ allocate_center_code = center_code
184
+ allocated_centers [allocate_center_code ] = center
185
+
186
+ allocate (school_code , allocate_center_code , next_allot )
187
+ to_allot -= next_allot
188
+ remaining_cap [center_code ] -= next_allot
189
+
190
+ return to_allot , allocated_centers
191
+
146
192
parser = argparse .ArgumentParser (
147
193
prog = 'center randomizer' ,
148
194
description = 'Assigns centers to exam centers to students' )
@@ -172,36 +218,13 @@ def is_allocated(scode1: str, scode2:str) -> bool:
172
218
for s in schools :
173
219
centers_for_school = centers_within_distance (s , centers , PREF_DISTANCE_THRESHOLD )
174
220
to_allot = int (s ['count' ])
175
- per_center = calc_per_center (to_allot )
176
-
177
- allocated_centers = {}
178
221
179
222
# per_center = math.ceil(to_allot / min(calc_num_centers(to_allot), len(centers_for_school)))
180
- for c in centers_for_school :
181
- writer .writerow ([s ['scode' ], s ['count' ], s ['name-address' ], s ['lat' ], s ['long' ], c ['cscode' ], c ['name' ], c ['address' ], c ['capacity' ], c ['distance_km' ] ])
182
- if is_allocated (c ['cscode' ], s ['scode' ]):
183
- continue
184
- next_allot = min (to_allot , per_center , max (centers_remaining_cap [c ['cscode' ]], MIN_STUDENT_IN_CENTER ))
185
- if to_allot > 0 and next_allot > 0 and centers_remaining_cap [c ['cscode' ]] >= next_allot :
186
- allocated_centers [c ['cscode' ]] = c
187
- allocate (s ['scode' ], c ['cscode' ], next_allot )
188
- # allocation.writerow([s['scode'], s['name-address'], c['cscode'], c['name'], c['address'], next_allot, c['distance_km']])
189
- to_allot -= next_allot
190
- centers_remaining_cap [c ['cscode' ]] -= next_allot
223
+ to_allot , allocated_centers = allocate_to_centers (centers_for_school , s , to_allot , centers_remaining_cap )
191
224
192
225
if to_allot > 0 : # try again with relaxed constraints and more capacity at centers
193
226
expanded_centers = centers_within_distance (s , centers , ABS_DISTANCE_THRESHOLD )
194
- for c in expanded_centers :
195
- if is_allocated (c ['cscode' ], s ['scode' ]):
196
- continue
197
- stretched_capacity = math .floor (int (c ['capacity' ]) * STRETCH_CAPACITY_FACTOR + centers_remaining_cap [c ['cscode' ]])
198
- next_allot = min (to_allot , max (stretched_capacity , MIN_STUDENT_IN_CENTER ))
199
- if to_allot > 0 and next_allot > 0 and stretched_capacity >= next_allot :
200
- allocated_centers [c ['cscode' ]] = c
201
- allocate (s ['scode' ], c ['cscode' ], next_allot )
202
- # allocation.writerow([s['scode'], s['name-address'], c['cscode'], c['name'], c['address'], next_allot, c['distance_km']])
203
- to_allot -= next_allot
204
- centers_remaining_cap [c ['cscode' ]] -= next_allot
227
+ to_allot , allocated_centers = allocate_to_centers (expanded_centers , s , to_allot , centers_remaining_cap , stretch_capacity = True )
205
228
206
229
for c in allocated_centers .values ():
207
230
allocation_file .writerow ([s ['scode' ], s ['name-address' ], c ['cscode' ], c ['name' ], c ['address' ], allocations [s ['scode' ]][c ['cscode' ]], c ['distance_km' ]])
0 commit comments