@@ -40,10 +40,10 @@ def haversine_distance(lat1, lon1, lat2, lon2):
40
40
return distance
41
41
42
42
43
- def centers_within_distance (school : Dict [str , str ], centers : Dict [str , str ], distance_threshold : float ) -> List [Dict [str , any ]]:
43
+ def centers_within_distance (school : Dict [str , str ], centers : Dict [str , str ], distance_threshold : float , relax_threshold : bool ) -> List [Dict [str , any ]]:
44
44
"""
45
45
Return List of centers that are within given distance from school.
46
- If there are no centers within given distance return one that is closest
46
+ relax_threshold: If there are no centers within given distance return one that is closest
47
47
Returned params :
48
48
{'cscode', 'name', 'address', 'capacity', 'lat', 'long', 'distance_km'}
49
49
@@ -60,33 +60,35 @@ def center_to_dict(c, distance):
60
60
def sort_key (c ):
61
61
# intent: sort by preference score DESC then by distance_km ASC
62
62
# leaky abstraction - sorted requires a single numeric value for each element
63
- return c ['distance_km' ] * random .uniform (1 , 5 ) - get_pref (school ['scode' ], c ['cscode' ])* 100
64
-
63
+ return c ['distance_km' ] * random .uniform (1 , 5 ) - get_pref (school ['scode' ], c ['cscode' ]) * 100
64
+
65
65
school_lat = school .get ('lat' )
66
66
school_long = school .get ('long' )
67
67
if len (school_lat ) == 0 or len (school_long ) == 0 :
68
68
return []
69
69
70
- within_distance = []
71
- nearest_distance = None
72
- nearest_center = None
70
+ qualifying_centers = []
71
+ # nearest_distance = None
72
+ # nearest_center = None
73
73
for c in centers :
74
+ if school ['scode' ] == c ['cscode' ] \
75
+ or is_allocated (c ['cscode' ], s ['scode' ]) \
76
+ or get_pref (school ['scode' ], c ['cscode' ]) <= PREF_CUTOFF :
77
+ continue
74
78
distance = haversine_distance (float (school_lat ), float (
75
79
school_long ), float (c .get ('lat' )), float (c .get ('long' )))
76
- if school ['scode' ] == c ['cscode' ]:
77
- continue
78
- if nearest_center is None or distance < nearest_distance :
79
- nearest_center = c
80
- nearest_distance = distance
81
-
82
- if distance <= distance_threshold and get_pref (school ['scode' ], c ['cscode' ]) > PREF_CUTOFF :
83
- within_distance .append (center_to_dict (c , distance ))
80
+ # if nearest_center is None or distance < nearest_distance:
81
+ # nearest_center = c
82
+ # nearest_distance = distance
83
+ qualifying_centers .append (center_to_dict (c , distance ))
84
84
85
+ within_distance = [ c for c in qualifying_centers if c ['distance_km' ] <= distance_threshold ]
85
86
if len (within_distance ) > 0 :
86
- return sorted (within_distance , key = sort_key )
87
- else : # if there are no centers within given threshold, return one that is closest
88
- return [center_to_dict (nearest_center , nearest_distance )]
89
-
87
+ return sorted (within_distance , key = sort_key )
88
+ elif relax_threshold : # if there are no centers within given threshold, return one that is closest
89
+ return sorted (qualifying_centers , key = sort_key )
90
+ else :
91
+ return []
90
92
91
93
def read_tsv (file_path : str ) -> List [Dict [str , str ]]:
92
94
"""
@@ -271,7 +273,7 @@ def get_output_filename():
271
273
272
274
for s in schools :
273
275
centers_for_school = centers_within_distance (
274
- s , centers , PREF_DISTANCE_THRESHOLD )
276
+ s , centers , PREF_DISTANCE_THRESHOLD , False )
275
277
to_allot = int (s ['count' ])
276
278
per_center = calc_per_center (to_allot )
277
279
@@ -289,8 +291,6 @@ def get_output_filename():
289
291
c ['address' ],
290
292
c ['capacity' ],
291
293
c ['distance_km' ]])
292
- if is_allocated (c ['cscode' ], s ['scode' ]):
293
- continue
294
294
next_allot = min (to_allot , per_center , max (
295
295
centers_remaining_cap [c ['cscode' ]], MIN_STUDENT_IN_CENTER ))
296
296
if to_allot > 0 and next_allot > 0 and centers_remaining_cap [c ['cscode' ]] >= next_allot :
@@ -302,10 +302,8 @@ def get_output_filename():
302
302
303
303
if to_allot > 0 : # try again with relaxed constraints and more capacity at centers
304
304
expanded_centers = centers_within_distance (
305
- s , centers , ABS_DISTANCE_THRESHOLD )
305
+ s , centers , ABS_DISTANCE_THRESHOLD , True )
306
306
for c in expanded_centers :
307
- if is_allocated (c ['cscode' ], s ['scode' ]):
308
- continue
309
307
stretched_capacity = math .floor (
310
308
int (c ['capacity' ]) * STRETCH_CAPACITY_FACTOR + centers_remaining_cap [c ['cscode' ]])
311
309
next_allot = min (to_allot , max (
@@ -330,7 +328,7 @@ def get_output_filename():
330
328
331
329
if to_allot > 0 :
332
330
remaining += to_allot
333
- logger .warn (
331
+ logger .warning (
334
332
f"{ to_allot } /{ s ['count' ]} left for { s ['scode' ]} { s ['name-address' ]} centers: { len (centers_for_school )} " )
335
333
336
334
logger .info ("Remaining capacity at each center (remaining_capacity cscode):" )
0 commit comments