@@ -178,6 +178,52 @@ def is_allocated(scode1: str, scode2: str) -> bool:
178
178
return allocations .get (scode1 , {}).get (scode2 ) is not None
179
179
180
180
181
+ def allocate_to_centers (centers : List [Dict [str , str ]], school : Dict [str , str ], to_allot : int , remaining_cap : Dict [str , int ], stretch : bool = False ):
182
+ allocated_centers = {}
183
+ per_center = calc_per_center (to_allot )
184
+
185
+ for center in centers :
186
+ school_code = school ['scode' ]
187
+ center_code = center ['cscode' ]
188
+ writer .writerow ([
189
+ school_code ,
190
+ school ['count' ],
191
+ school ['name-address' ],
192
+ school ['lat' ],
193
+ school ['long' ],
194
+ center_code ,
195
+ center ['name' ],
196
+ center ['address' ],
197
+ center ['capacity' ],
198
+ center ['distance_km' ]
199
+ ])
200
+
201
+ if is_allocated (center_code , school_code ):
202
+ continue
203
+
204
+ centers_cap_left = remaining_cap [center_code ]
205
+
206
+ if stretch :
207
+ stretched_capacity = math .floor (int (center ['capacity' ]) * STRETCH_CAPACITY_FACTOR + centers_cap_left )
208
+ next_allot = min (to_allot , max (stretched_capacity , MIN_STUDENT_IN_CENTER ))
209
+ centers_cap_left = stretched_capacity
210
+ else :
211
+ next_allot = min (to_allot , per_center , max (centers_cap_left , MIN_STUDENT_IN_CENTER ))
212
+
213
+ if to_allot > 0 and next_allot > 0 and centers_cap_left >= next_allot :
214
+ if next_allot < MIN_STUDENT_IN_CENTER and len (allocated_centers ) > 0 :
215
+ # get the first center code
216
+ allocate_center_code = centers [0 ]['cscode' ]
217
+ else :
218
+ allocate_center_code = center_code
219
+ allocated_centers [allocate_center_code ] = center
220
+
221
+ allocate (school_code , allocate_center_code , next_allot )
222
+ to_allot -= next_allot
223
+ remaining_cap [center_code ] -= next_allot
224
+
225
+ return to_allot , allocated_centers
226
+
181
227
parser = argparse .ArgumentParser (
182
228
prog = 'center randomizer' ,
183
229
description = 'Assigns centers to exam centers to students' )
@@ -234,49 +280,13 @@ def is_allocated(scode1: str, scode2: str) -> bool:
234
280
centers_for_school = centers_within_distance (
235
281
s , centers , PREF_DISTANCE_THRESHOLD )
236
282
to_allot = int (s ['count' ])
237
- per_center = calc_per_center (to_allot )
238
-
239
- allocated_centers = {}
240
-
241
- # per_center = math.ceil(to_allot / min(calc_num_centers(to_allot), len(centers_for_school)))
242
- for c in centers_for_school :
243
- writer .writerow ([s ['scode' ],
244
- s ['count' ],
245
- s ['name-address' ],
246
- s ['lat' ],
247
- s ['long' ],
248
- c ['cscode' ],
249
- c ['name' ],
250
- c ['address' ],
251
- c ['capacity' ],
252
- c ['distance_km' ]])
253
- if is_allocated (c ['cscode' ], s ['scode' ]):
254
- continue
255
- next_allot = min (to_allot , per_center , max (
256
- centers_remaining_cap [c ['cscode' ]], MIN_STUDENT_IN_CENTER ))
257
- if to_allot > 0 and next_allot > 0 and centers_remaining_cap [c ['cscode' ]] >= next_allot :
258
- allocated_centers [c ['cscode' ]] = c
259
- allocate (s ['scode' ], c ['cscode' ], next_allot )
260
- # allocation.writerow([s['scode'], s['name-address'], c['cscode'], c['name'], c['address'], next_allot, c['distance_km']])
261
- to_allot -= next_allot
262
- centers_remaining_cap [c ['cscode' ]] -= next_allot
263
-
264
- if to_allot > 0 : # try again with relaxed constraints and more capacity at centers
265
- expanded_centers = centers_within_distance (
266
- s , centers , ABS_DISTANCE_THRESHOLD )
267
- for c in expanded_centers :
268
- if is_allocated (c ['cscode' ], s ['scode' ]):
269
- continue
270
- stretched_capacity = math .floor (
271
- int (c ['capacity' ]) * STRETCH_CAPACITY_FACTOR + centers_remaining_cap [c ['cscode' ]])
272
- next_allot = min (to_allot , max (
273
- stretched_capacity , MIN_STUDENT_IN_CENTER ))
274
- if to_allot > 0 and next_allot > 0 and stretched_capacity >= next_allot :
275
- allocated_centers [c ['cscode' ]] = c
276
- allocate (s ['scode' ], c ['cscode' ], next_allot )
277
- # allocation.writerow([s['scode'], s['name-address'], c['cscode'], c['name'], c['address'], next_allot, c['distance_km']])
278
- to_allot -= next_allot
279
- centers_remaining_cap [c ['cscode' ]] -= next_allot
283
+
284
+ # per_center = math.ceil(to_allot / min(calc_num_centers(to_allot), len(centers_for_school)))
285
+ to_allot , allocated_centers = allocate_to_centers (centers_for_school , s , to_allot , centers_remaining_cap )
286
+
287
+ if to_allot > 0 : # try again with relaxed constraints and more capacity at centers
288
+ expanded_centers = centers_within_distance (s , centers , ABS_DISTANCE_THRESHOLD )
289
+ to_allot , allocated_centers = allocate_to_centers (expanded_centers , s , to_allot , centers_remaining_cap , stretch_capacity = True )
280
290
281
291
for c in allocated_centers .values ():
282
292
allocation_file .writerow ([s ['scode' ],
0 commit comments