def valid_candidate_no_overtime(sln, sid, dow, wid, worker_min, wk): if valid_candidate(sln, sid, dow, wid, wk): s = station.find_station_by_id(sid) m = worker_min + s.get_station_duration() return m <= 0 else: return False
def print_solution_by_tuple(sln): for x in sln: sid = x[0] dow = x[1] wid = x[2] s = station.find_station_by_id(sid) d = time.days_of_week[dow] w = worker.get_assignment_display_text(wid) print "%-10s %-2s %-10s" % (s.name, d, w)
def print_solution_by_tuple(sln, wk): sln2 = [slot for slot in sln if slot[3] == wk] for x in sln2: sid = x[0] dow = x[1] wid = x[2] s = station.find_station_by_id(sid) d = time.days_of_week[dow] w = worker.get_assignment_display_text(wid) print "%-10s %-2s %-10s" % (s.name, d, w)
def format_worker_comment_for_file(wid, worker_assignments): # Prepare station data for comment sids = rmdups([int(slot[0]) for slot in worker_assignments]) sids.sort() ss = [] for sid in sids: s = station.find_station_by_id(sid) station_name = s.name ss.append("%1d=%s" % (sid, s.name)) stations_comment = ", ".join(ss) w = worker.find_worker_by_id(wid) worker_name = "%s %s" % (w.first_name, w.last_name) return "# %s\n# %s\n" % (worker_name, stations_comment)
def format_slot_comment_for_file(slot): s = station.find_station_by_id(int(slot[0])) station_name = s.name day_name = time.days_of_week[int(slot[1])] wid = int(slot[2]) worker_name = "OPEN" if wid > 0: w = worker.find_worker_by_id(int(slot[2])) worker_name = "%s %s" % (w.first_name, w.last_name) return "#%s,%s,%s\n" % (station_name, day_name, worker_name)
def get_worker_minutes_in_schedule(sln): worker_minutes = {} for w in worker.workers: worker_minutes[ w.id] = (-1) * w.hours_per_week * 60 + len(w.benefit_days) * 8 * 60 for slot in sln: sid = slot[0] wid = slot[2] if wid > 0: s = station.find_station_by_id(sid) worker_minutes[wid] += s.get_station_duration() return worker_minutes
def assign_workers_to_only_capability(candidates_by_station, sln, choose_candidate, wk): new_sln = [t for t in sln if t[3] == wk] for w in worker.workers: slots = [slot for slot in sln if slot[2] == w.id if slot[3] == wk] ss = worker_capability.worker_stations_map[w.id] if len(ss) == 1: s = station.find_station_by_id(ss[0]) only_candidate = {} only_candidate[s.id] = [w.id] for dow in range(len(time.days_of_week)): slot = find_slot_by_station_id_and_dow(new_sln, s.id, dow, wk) if slot[2] == 0: new_slot = slot wid = choose_candidate(new_sln, slot, s.id, dow, only_candidate, wk) if wid > 0: new_slot = (slot[0], slot[1], wid, slot[3]) ii = new_sln.index(slot) new_sln[ii] = new_slot return new_sln
def calculate_gaps(sln, wid): # Get the worker's assignments. dow_stations = [(slot[1], slot[0]) for slot in sln if slot[2] == wid] # Sort by day of week then start_time. dow_stations.sort(key=lambda tup: tup[0] * 10000 + time.time_to_min( station.find_station_by_id(tup[1]).start_time)) # Pair up successive assignments. pairs = zip(dow_stations, tail(dow_stations)) # Discard pairs within same day. pairs2 = [p for p in pairs if p[0][0] != p[1][0]] # Extract stations from pairs. pairs3 = [(p[0][1], p[1][1]) for p in pairs2] # Compute the gaps between station pairs. gaps = map(station.get_station_gap_minutes, pairs3) return gaps
def choose_candidate_ranked(sln, slot, sid, dow, candidates_by_station, wk): s = station.find_station_by_id(sid) print print "station", sid, s.name print "day of week", dow, time.days_of_week[dow] print "candidates_by_station[sid]", candidates_by_station[sid] candidates = [] for wid in candidates_by_station[sid]: print "considering worker", wid if valid_candidate(sln, sid, dow, wid, wk): print "worker is valid candidate" stats = get_worker_assignment_stats(sln, dow, wid, wk) print "worker stats" print " wid", stats[0] print " slots", stats[1] print " full_time", stats[2] print " minutes_week", stats[3] print " minutes_today", stats[4] print " fav_station", stats[5] # stats[0] = wid # [1] = slots for wid in sln # [2] = True if w is full time # [3] = assigned minutes for w in sln # [4] = assigned minutes for w in sln for dow # [5] = worker's favorite station same_assignment = len( [slot for slot in stats[1] if slot[0] == sid]) > 0 full_time = stats[2] minutes_week = stats[3] + s.get_station_duration() minutes_today = stats[4] + s.get_station_duration() # gaps = calculate_gaps(sln + [(sid, dow, wid)], wid, wk) # small_gaps = [g for g in gaps if g < 8] is_first_choice = stats[5] == sid is_only_choice = len(candidates_by_station[sid]) == 1 # If overtime and worker is not willing to do it, not a candidate. valid = True if minutes_week > 0: w = worker.find_worker_by_id(wid) valid = w.overtime_ok if valid: print "worker willing to work overtime" else: print "worker not willing to work overtime" # if valid: # if small_gaps: # print "successive assignments too close together" # valid = False # else: # print "successive assignments OK" if valid: r = calculate_rank(full_time, minutes_week, minutes_today, same_assignment, is_first_choice, is_only_choice) print "full_time", full_time print "minutes_week", minutes_week print "minutes_today", minutes_today print "same_assignment", same_assignment print "is_first_choice", is_first_choice print "is_only_choice", is_only_choice print "rank", r candidates.append((r, wid)) if len(candidates) == 0: print "no valid candidates" return 0 else: print "candidates", candidates candidates.sort candidates.sort(key=lambda tup: tup[0]) print "candidates, sorted", candidates return candidates[0][1]