def templates(): if request.method == "GET": org_id = 1 templates = Shift.create_templates(1) json_templates = json.dumps(templates) return render_template("templates.html",params={}) if request.method == "POST": org_id = 1 # get from user chosen_template = 1 # get from user Shift.create_from_template(org_id, chosen_template) # create shifts in DB
def send_hours_info(): try: if request.method == "GET": org_id = 1 # get user's org_id start_date = datetimeHelp.next_weekday(dt.today(), 6) # next week's Sunday end_date = datetimeHelp.next_weekday(dt.today(), 12) # next week's Saturday raw_shifts = db.get_shifts_by_date_range(org_id, start_date, end_date) shifts = [ Shift(shift[0], shift[1], shift[2]) for shift in raw_shifts ] return str([json.dumps(s.__dict__) for s in shifts]) if request.method == "POST": # match the user's days request user_id = request.form["user_id"] dates = request.form[ "dates"] # convert days to date - accepted format YYYY-MM-DD HH:MM start_time = request.form["hours"] end_time = "NULL" # change arrangement and employee logic to handle multiple hour choice, for date in dates: db.insert_employee_times(user_id, date, start_time, end_time) flash("Shift options recorded successfully") return redirect("/send_hours") # session.pop('_flashes', None) # flash("Attendance failed to register") except IOError: print("Error fetching information")
def arrangement_info(): if request.method == "GET": # make sure start_date is before end_date user_id = 1 # get logged in user's ID same_day_scheduling = False # get this from user start_date = "1-1-2020" # get this from user # start_date = str(datetimeHelp.next_weekday(dt.today(), 6)) - date of next Sunday end_date = "7-1-2020" # get this from user # end_time = str(datetimeHelp.next_weekday(dt.today(), 12)) - date of next Saturday org_id = db.get_org_by_usr(user_id)[0][0] # get user org_id sol_num = db.sol_exists(org_id) # gets the max sol number from DB if sol_num[0]: # if solution exists in DB session["sol"] = sol_num[0] + 1 else: session["sol"] += 1 raw_employees = db.get_employees_by_date_range(org_id, start_date, end_date) employees = Employee.create_from_DB(raw_employees) raw_shifts = db.get_shifts_by_date_range(org_id, start_date, end_date) shifts = Shift.create_from_DB(raw_shifts) raw_workdays = db.get_wdays_by_date_range(org_id, start_date, end_date) workdays = WorkDay.create_from_DB(org_id, raw_workdays) # add shifts to corresponding days for shift in shifts: for i in range(len(workdays)): if shift.get_date() == workdays[i].get_date(): workdays[i].add_shift(shift) ww = WorkWeek(workdays) dic, sol = ww.create_arrangement(employees, same_day_scheduling) employees, shifts = ww.extract_solution(sol) mat = Matrix(employees, shifts) # dic is a dictionary that maps number of shifts assigned to a employee # sol is the actual solved arrangement # for example {1:[E1,E2], 2:[E3,E4]..} # add arrangement to DB # db.register_arrangement(sol, session["sol"]) #print(WorkWeek.min_shifts_swap(dic,sol)) # 2: [Employee 5, tom col, dict_keys(['waitress', 'bartender']), Employee 7, itzik shawarma, dict_keys(['waitress']), Employee 8, roni kofif, dict_keys(['waitress', 'bartender'])], # 3: [Employee 6, pagi pagi, dict_keys(['waitress', 'bartender']), Employee 4, niv mali, dict_keys(['bartender']), Employee 9, some guy, dict_keys(['waitress']), Employee 1, ben mali, dict_keys(['bartender']), Employee 2, paz mali, dict_keys(['waitress']), Employee 3, rom mali, dict_keys(['bartender'])], # 4: [Employee 10, another guy, dict_keys(['bartender', 'waitress'])], 5: [], 6: [], 7: [], 8: [], 9: [], 10: []}] #2: [Employee 5, tom col, dict_keys(['waitress', 'bartender']), Employee 7, itzik shawarma, dict_keys(['waitress']), Employee 8, roni kofif, dict_keys(['waitress', 'bartender'])], # 3: [Employee 6, pagi pagi, dict_keys(['waitress', 'bartender']), Employee 4, niv mali, dict_keys(['bartender']), Employee 9, some guy, dict_keys(['waitress']), Employee 1, ben mali, dict_keys(['bartender']), Employee 10, another guy, dict_keys(['bartender', 'waitress']), Employee 3, rom mali, dict_keys(['bartender'])], # 4: [Employee 2, paz mali, dict_keys(['waitress'])] #swap 2 and 10 set 10 to 4 min dic, solution = ww.min_shifts_swap(dic, sol) js_dict = {} for i in range(len(solution)): js_dict["shift {}".format(i+1)] = solution[i].get_json() return js_dict else: return render_template("error_page.html")
def from_template(cls, org_id, template_no): # for future use """ initialize WorkWeek from template :param org_id: Org id :param template_no: number of template in DB user chose :return: WorkWeek object """ try: db = DB("Resty.db") templates = db.get_ww_templates(org_id) # get all the templates templates_dic = {} for shift in templates: template = shift[-1] if template in templates_dic: templates_dic[template] += [shift] else: templates_dic[template] = [shift] if template_no in templates_dic: # user requested an existing template chosen_template = templates_dic[template_no] dates = datetimeHelp.this_week_dates() # next week dates workdays = {} workdays_lst = [] for shift in chosen_template: if shift[0] in workdays: workdays[shift[0]] += [shift] # create workday else: workdays[shift[0]] = [shift] print(workdays) shift_id = db.get_max_shift_id(org_id)[0] + 1 for day, shifts in workdays.items(): date = datetimeHelp.day_to_date(day, dates) shift_lst = [ Shift(shift_id + i, date, shifts[i][1], shifts[i][2], shifts[i][3]) for i in range(len(shifts)) ] shift_id += len(shifts) wd = WorkDay(org_id, date) wd.set_shifts(shift_lst) workdays_lst.append(wd) return cls(workdays_lst) else: print("template doesn't exist") # create Workdays from data, add them together to create WW except IOError: print("Failed to create template from restore")
def create_arrangement(self, employees, same_day_scheduling=False): """ get needed shifts for each day for each shift find number of needed staff get random employee and fit him to shift add shift to employees """ """""" def schedule(position): """ try schedule a chosen employee to shift :return: True if successfully scheduled Employee to Shift, False else """ if shift.get_date() in chosen_employee.get_dates().keys(): if shift.get_start_hour() in chosen_employee.get_dates()[ shift.get_date()]: # makes sure employee isn't already scheduled to work # same_day_scheduling is set to false by default if chosen_employee not in day.get_employees( ) or same_day_scheduling: if chosen_employee not in shift.get_employees(): mat.set_tensor(chosen_employee, shift.get_full_time(), position) chosen_employee.add_shift(shift) shift_dic[i + 1] += [chosen_employee] decrement_list = shift_dic[i] decrement_list.remove(chosen_employee) shift_dic[i] = decrement_list day.add_employee(chosen_employee) return True return False try: # same_day_scheduling is a variable that can be changed to enable same day scheduling # get number of employees in eligible date range # employees should be a dictionary, mapping between dates and available employees # create employee objects # limit the number of shifts an employee can have per week to 10 # initialize dictionary where its' keys are number of shifts and values are list of employee ids which have # this number of shifts assigned # this method is good when you need even distribution between employees # create dictionary to map num of shifts per employee max_shifts = 10 max_num_employees = 0 # the maximum number of scheduled employees so far required_employees = 0 # the number of scheduled employees needed for a full solution days = [day for day in self.work_days[:]] shifts = [] best = [] for day in days: for shift in day.get_shifts(): shifts.append(shift) # sums up the needed number of employees to create full arrangement required_employees += shift.get_num_barts( ) + shift.get_num_waits() mat = Matrix(employees, shifts) for j in range(50): # try to find solution 50 times num_employees = 0 shift_dic = { 0: employees[:] } # reset dictionary if no solution was found [employee.reset_shifts() for employee in employees[:]] # reset shifts for employees solution = [] [day.reset_shifts() for day in self.work_days[:]] for i in range(1, max_shifts + 1): shift_dic[i] = [] for day in self.work_days: # iterate over every day of the WordDay element for shift in day.get_shifts( ): # iterate over every shift in the WorkDay num_bartenders = shift.get_num_barts() num_waitresses = shift.get_num_waits() num_scheduled_bartenders, num_scheduled_waitresses = 0, 0 for i in range(7): if num_bartenders == num_scheduled_bartenders and num_waitresses == num_scheduled_waitresses: break # scheduling shift is over, break loop if shift_dic[i]: possible_employees = [ bartender for bartender in shift_dic[i] if "bartender" in bartender.get_positions() ] else: continue while num_bartenders > num_scheduled_bartenders: if len(possible_employees) == 0: break # try schedule the first strong employee found if day.is_first_shift( shift) and not shift.get_bartenders(): chosen_employee = Shift.get_senior_employee( shift.get_date(), "bartender", 2, possible_employees) # find a senior employee that can work at this shift else: # not the first shift of the day, fill randomly chosen_employee = random.choice( possible_employees) if not chosen_employee: # no match found for a senior employee # try schedule another employee instead, manager decision chosen_employee = random.choice( possible_employees) if schedule("bartender"): shift.add_bartender(chosen_employee) num_scheduled_bartenders += 1 # remove chosen employee anyway, not viable for scheduling in this shift anymore possible_employees.remove(chosen_employee) possible_employees = [ waitress for waitress in shift_dic[i] if "waitress" in waitress.get_positions() ] # filter out waitresses from while num_waitresses > num_scheduled_waitresses: if len(possible_employees ) == 0: # if no possible match found break if day.is_first_shift( shift ) and not shift.get_waitresses( ): # try schedule the first strong employee found chosen_employee = Shift.get_senior_employee( shift.get_date(), "waitress", 2, possible_employees) else: # not the first shift of the day, fill randomly chosen_employee = random.choice( possible_employees) # makes sure employee is able to work at this shift if not chosen_employee: # no match found for the employee chosen_employee = random.choice( possible_employees) if schedule("waitress"): shift.add_waitress(chosen_employee) num_scheduled_waitresses += 1 # remove chosen employee anyway, not viable for scheduling in this shift anymore possible_employees.remove(chosen_employee) # end of while loops solution.append(copy.deepcopy(shift)) num_employees += len(day.get_employees()) if max_num_employees < num_employees: # current solution is better than previous best max_num_employees = num_employees best = solution[:] best_dictionary = copy.deepcopy(shift_dic) print("\"\"\"\"\"") print(best) print("\"\"\"\"\"") print("iteration: {}".format(j)) if required_employees == num_employees: # full solution found print(mat.tensor) return shift_dic, best print("No viable solution found - getting our best solution!") return best_dictionary, best except OverflowError: print("Too many loops - program shutdown") except IndexError: print("Cant create scheduling, no valid options")
employees.append(employee) shifts.append(shift) return employees, shifts def create_combinations(self, employees): for employee in employees: for date in employee.get_dates(): pass # lst = list(itertools.combinations(iterable, r)) if __name__ == "__main__": db = DB("Resty.db") # --- test 2 ----# s1 = Shift(1, "1-1-2020", "16:00") s2 = Shift(2, "1-1-2020", "19:00") s3 = Shift(3, "2-1-2020", "16:00") s4 = Shift(4, "2-1-2020", "19:00") s5 = Shift(5, "3-1-2020", "16:00") s6 = Shift(6, "3-1-2020", "19:00") s7 = Shift(7, "4-1-2020", "16:00") s8 = Shift(8, "4-1-2020", "19:00") s9 = Shift(9, "5-1-2020", "16:00") s10 = Shift(10, "5-1-2020", "19:00") s11 = Shift(11, "6-1-2020", "16:00") s12 = Shift(12, "6-1-2020", "19:00") s13 = Shift(13, "7-1-2020", "16:00") s14 = Shift(14, "7-1-2020", "19:00") wd = WorkDay("1-1-2020", "16:00", "Tom") wd2 = WorkDay("2-1-2020", "16:00", "Tom")
def templates_info(): if request.method == "GET": org_id = 1 # get from user return json.dumps(Shift.create_templates(org_id))
dic, solution = ww.min_shifts_swap(dic, sol) js_dict = {} for i in range(len(solution)): js_dict["shift {}".format(i+1)] = solution[i].get_json() return js_dict else: return render_template("error_page.html") if __name__ == "__main__": user_id = 1 # get logged in user's ID org_id = db.get_org_by_usr(user_id)[0][0] # get user org_id #raw_employees = db.get_employees_by_date_range(org_id, "1-1-2020", "7-1-2020") employees = Employee.create_from_DB(db.get_employees_by_date_range(org_id, "2020-01-01", "2020-01-07")) raw_shifts = db.get_shifts_by_date_range(org_id, "1-1-2020", "7-1-2020") shifts = [Shift(shift[0], shift[1], shift[2]) for shift in raw_shifts] raw_workdays = db.get_wdays_by_date_range(org_id, "1-1-2020", "7-1-2020") workdays = [WorkDay(org_id, wd[0], wd[1]) for wd in raw_workdays] i = 0 # add shifts to corresponding days for shift in shifts: while i < len(workdays): if shift.get_date() == workdays[i].get_date(): workdays[i].add_shift(shift) break else: i += 1 ww = WorkWeek(workdays) dic, sol = ww.create_arrangement(employees) for shift in sol: print(shift)