forked from KajetanMieloch/Shift-composer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
generator.py
120 lines (92 loc) · 5.88 KB
/
generator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from generatorResources import *
# Generate the schedule
def generate_schedule(employees: list[Employee], modifierShiftsInRow: int) -> list[list[tuple[str, int, int]]]:
try:
schedule = [[] for _ in range(days)]
# Generate the of days (range)
for day in range(days):
nonDescontPriority = False
descontAllreadyAssigned = False
#Set hadShift to False for all employees
allEmployees = [employee for employee in employees]
for employee in allEmployees:
employee.hadShift = False
employee.doNotAssign = False
#define max shifts
maxShifts = 3
# Generate the shifts (range)
for shift in range(1, maxShifts+1):
available_employees = availableEmployees(employees, day, shift)
# Get the coordinator
coordinator = next((employee for employee in available_employees if employee.coordinator), None)
#Get all descont employees
descont_employee = [employee for employee in available_employees if employee.descont if employee.contract == False]
# Assign the coordinator (no more than one per shift)
if coordinator:
schedule[day].append((coordinator.name, shift, coordinator.id))
coordinator.hoursInTotal += 8
if len(descont_employee) < 4 and shift == 1:
nonDescontPriority = True
continue
else:
if len(descont_employee) < 7 and shift == 1:
nonDescontPriority = True
# Generate the contract employees (list comprehension)
contract_employees = [employee for employee in available_employees if employee.contract]
# Assign the contract employees
for employee in contract_employees:
employee.hoursInTotal += 8
schedule[day].append((employee.name, shift, employee.id))
available_employees.remove(employee)
descontAllreadyAssigned = True
#Assign the descont employee (at least one per shift)
if descont_employee:
assignDescontEmployee(schedule, day, shift, available_employees, descont_employee, modifierShiftsInRow)
#If there is no descont employee, then try delete previous shift descont employee
elif not descont_employee:
reasignEmployee(schedule, day, shift, available_employees, maxShifts, "descont",modifierShiftsInRow, employees, descont_employee, descontAllreadyAssigned)
# Assign the rest of the employees
available_employees.sort(key=lambda employee: employee.shiftsInRow, reverse=True)
iterationOfNonDescontEmployee = 0
iterationOfDescontEmployee = 0
while len([x for x in schedule[day] if x[1] == shift]) < 3:
iterationOfNonDescontEmployee += 1
iterationOfDescontEmployee += 1
#Check if there is descont employee on next shift
if shift != 3:
if isNextShiftDescont(employees, day, shift):
nonDescontPriority = False
#If there is nonDescontPriority, then non descont employee is assigned first
if nonDescontPriority and iterationOfNonDescontEmployee <=3 and shift <=3:
for employee in available_employees:
if employee.descont == False and employee.doNotAssign == False:
schedule[day].append((employee.name, shift, employee.id))
available_employees.remove(employee)
shiftsInRow(employee, day, modifierShiftsInRow)
break
#If there is no nonDescontPriority, then descont employee is assigned first
#but if employee has doNotAssign set to True, then he is not assigned
elif iterationOfDescontEmployee <=3 and shift <=3:
for employee in available_employees:
if employee.doNotAssign == False:
schedule[day].append((employee.name, shift, employee.id))
available_employees.remove(employee)
shiftsInRow(employee, day, modifierShiftsInRow)
break
#Else, employee is assigned by order
else:
if employee.doNotAssign == False:
if assignEmployeesByOrder(available_employees, schedule, day, shift ,0, maxShifts, modifierShiftsInRow, employees):
break
else:
if assignEmployeesByOrder(available_employees, schedule, day, shift ,1, maxShifts, modifierShiftsInRow, employees):
break
#TODO Program a recurency, that will figure out what to do if there is no more employees to assign
#If there is less than 2 employees on shift, then recurency is called
if len([x for x in schedule[day] if x[1] == shift]) < 2:
raise NotEnoughEmploeesException("Not enough employees on shift" + str(shift) + " on day " + str(day+1))
assignEmployeeOffShifts(schedule, day, employees)
#If there is exeption, then return False
except NotEnoughEmploeesException as e:
return False
return schedule