Skip to content

Commit 719f01c

Browse files
committed
refactor: assign less than min threshold students to previous center
Abstracts the center allocation to a separate function Assigns the remaining students to previous center if the remainder is less than minimum threshold
1 parent 2836273 commit 719f01c

File tree

1 file changed

+53
-43
lines changed

1 file changed

+53
-43
lines changed

school_center.py

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,52 @@ def is_allocated(scode1: str, scode2: str) -> bool:
178178
return allocations.get(scode1, {}).get(scode2) is not None
179179

180180

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+
181227
parser = argparse.ArgumentParser(
182228
prog='center randomizer',
183229
description='Assigns centers to exam centers to students')
@@ -234,49 +280,13 @@ def is_allocated(scode1: str, scode2: str) -> bool:
234280
centers_for_school = centers_within_distance(
235281
s, centers, PREF_DISTANCE_THRESHOLD)
236282
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)
280290

281291
for c in allocated_centers.values():
282292
allocation_file.writerow([s['scode'],

0 commit comments

Comments
 (0)