Last active
December 23, 2016 07:19
-
-
Save Lvl4Sword/3acf5742e3a91c710f38639e2d7b2a2b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import csv | |
import Tkinter | |
import tkFileDialog | |
import sys | |
def calc_hours_shift(a_shift): | |
hours_shift = 0 | |
str_from = a_shift[a_shift.find("[")+1:a_shift.find(" - ")] | |
int_from = int(str_from[:str_from.find("M")-1]) | |
str_to = a_shift[a_shift.find(" - ")+3:a_shift.find("]")] | |
int_to = int(str_to[:str_to.rfind("M")-1]) | |
if str_from.find("12AM") >= 0: | |
int_from = 0 | |
if str_from.find("PM") >= 0 and str_from.find("12PM") < 0: | |
int_from += 12 | |
if str_to.find("12AM") >= 0: | |
int_to = 24 | |
if str_to.find("PM") >= 0 and str_to.find("12PM") < 0: | |
int_to += 12 | |
if str_from.find("PM") >= 0 and str_to.find("AM") >= 0 and int_to < 24: | |
int_to += 24 | |
hours_shift = (int_to-int_from) | |
return hours_shift | |
def calc_hours(shifts): | |
hours_shifts = 0 | |
for a_shift in shifts: | |
hours_shifts += calc_hours_shift(a_shift) | |
return hours_shifts | |
class Shift_Person(object): | |
def __init__(self, shift, hours_shift, staff_person): | |
self.shift = shift | |
self.hours_shift = hours_shift | |
self.staff_person = staff_person | |
def get_shift(self): | |
return self.shift | |
def get_hours_shift(self): | |
return self.hours_shift | |
def get_staff(self): | |
return self.staff_person | |
def available_employ(self): | |
available = -1 | |
for i in xrange(len(staff_person)-1, -1, -1): | |
if staff_person[i] == None: | |
available = i | |
return available | |
def add_person(self, new_person): | |
if self.available_employ() >= 0: | |
staff_person[self.available_employ()] = new_person | |
class Person(object): | |
def __init__ (self, full_name, hours_available, rank, num_shifts_available): | |
self.full_name = full_name | |
self.hours_available = hours_available | |
self.rank = rank | |
self.hours_worked = 0 | |
self.shift_work = list() | |
self.cal_hours_work = [0] * num_shifts_available | |
def get_full_name(self): | |
return self.full_name | |
def get_max_hours_available(self): | |
return self.hours_available | |
def get_rank(self): | |
return self.rank | |
def get_hours_worked(self): | |
return self.hours_worked | |
def get_shifts_worked(self): | |
return self.shift_work | |
def get_cal_hours_work(self): | |
return self.cal_hours_work | |
def set_cal_hours_work(self, ind_hours, num_hours): | |
self.cal_hours_work[ind_hours] = num_hours | |
self.hours_worked = self.hours_worked + num_hours | |
def add_shift(self, a_shift): | |
self.shift_work.append(a_shift) | |
def __cmp__(self, Person1): | |
if self.rank is not Person1.get_rank(): | |
return cmp(self.rank, Person1.get_rank()) | |
else: | |
ratio1 = float(self.hours_worked)/float(self.hours_available) | |
ratio2 = float(Person1.get_hours_worked())/float(Person1.get_max_hours_available()) | |
if ratio1 > ratio2: | |
return 1 | |
if ratio1 < ratio2: | |
return -1 | |
return 0 | |
Tkinter.Tk().withdraw() | |
in_path_file = tkFileDialog.askopenfilename(filetypes=[("CSV", ".csv")]) | |
out_path_file = in_path_file.replace(".csv", "_NEW.csv") | |
try: | |
csvfile = open(in_path_file) | |
except IOError: | |
sys.exit("CSV was not selected and we cannot proceed!") | |
min_for_swift = int(raw_input("How many people minimum for a shift? ")) | |
max_for_swift = int(raw_input("How many people maximum for a shift? ")) | |
or_min_for_swift = min_for_swift | |
reader = list(csv.reader(csvfile)) | |
old_headers = reader[0] | |
new_headers = ["Full name", "Rank", "Actual allotted hours", "Preferred number of hours"] | |
for a_header in old_headers[7:]: | |
new_headers.append(a_header[a_header.find(",")+2:]) | |
tot_hours = calc_hours(old_headers[7:]) | |
max_hours_available = 0 | |
staff = [] | |
for a_line in reader[1:]: | |
a_person = Person(a_line[1] + " " + a_line[2], int(a_line[5]), a_line[3], len(old_headers)-7) | |
staff.append(a_person) | |
max_hours_available += int(a_line[5]) | |
min_for_swift = max_hours_available/tot_hours | |
change_criteria = False | |
if min_for_swift<or_min_for_swift: | |
change_criteria = True | |
if min_for_swift > max_for_swift: | |
min_for_swift = max_for_swift | |
shift_staff = {} | |
for a_index in xrange(4, len(new_headers)): | |
a_shift = new_headers[a_index] | |
day_hour_shift = a_shift | |
hours_of_work = calc_hours_shift(a_shift) | |
a_staff_person = [] | |
staff.sort(key=lambda x: x.hours_worked, reverse=False) | |
for i in xrange(min_for_swift): | |
for j in xrange(len(staff)): | |
if len(a_staff_person) <= 0 and ((staff[j].hours_worked+hours_of_work) <= staff[j].hours_available) and (sum(staff[j].cal_hours_work[a_index-9:a_index-4])+hours_of_work) < 10: | |
staff[j].add_shift(a_shift) | |
staff[j].set_cal_hours_work(a_index-4, hours_of_work) | |
a_staff_person.append(staff[j]) | |
else: | |
level_occ = [] | |
for tmp in a_staff_person: | |
level_occ.append(tmp.rank) | |
if staff[j].cal_hours_work[a_index-4] == 0 and staff[j].rank not in level_occ and ((staff[j].hours_worked+hours_of_work) <= staff[j].hours_available) and len(a_staff_person) < min_for_swift and (sum(staff[j].cal_hours_work[a_index-9:a_index-4])+hours_of_work) < 10: | |
staff[j].add_shift(a_shift) | |
staff[j].set_cal_hours_work(a_index-4, hours_of_work) | |
a_staff_person.append(staff[j]) | |
if len(a_staff_person) < min_for_swift: | |
for j in xrange(len(staff)): | |
if staff[j].cal_hours_work[a_index-4] == 0 and ((staff[j].hours_worked+hours_of_work) <= staff[j].hours_available) and len(a_staff_person) < min_for_swift and (sum(staff[j].cal_hours_work[a_index-9:a_index-4])+hours_of_work) < 10: | |
staff[j].add_shift(a_shift) | |
staff[j].set_cal_hours_work(a_index-4, hours_of_work) | |
a_staff_person.append(staff[j]) | |
a_shift_person = Shift_Person(a_shift, hours_of_work, a_staff_person) | |
shift_staff[a_shift] = a_shift_person | |
staff.sort(key=lambda x: x.rank, reverse=True) | |
new_shifts = [] | |
new_shifts.append(new_headers) | |
for ap in staff: | |
a_line = [] | |
a_line.append(ap.get_full_name()) | |
a_line.append(ap.get_rank()) | |
a_line.append(str(ap.get_hours_worked())) | |
a_line.append(str(ap.get_max_hours_available())) | |
for i in xrange(4, len(old_headers)-3): | |
a_line.append("") | |
if new_headers[i] in ap.get_shifts_worked(): | |
a_line[i] = "Scheduled" | |
new_shifts.append(a_line) | |
writer = csv.writer(open(out_path_file, "wb")) | |
for row in new_shifts: | |
writer.writerow(row) | |
if change_criteria: | |
sys.exit("The available hours are insufficient to proceed according to these criteria!") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment