-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKalanit_shifts.py
302 lines (276 loc) · 12.2 KB
/
Kalanit_shifts.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
import pickle
import os
import datetime
from pick import pick
import csv
# Define shifts
shifts = [
{"name": "14-18", "start": 14, "end": 18},
{"name": "18-22", "start": 18, "end": 22},
{"name": "22-02", "start": 22, "end": 2},
{"name": "02-06", "start": 2, "end": 6},
{"name": "06-10", "start": 6, "end": 10},
{"name": "10-14", "start": 10, "end": 14},
]
all_guards=[]
# Read guards from csv file
try:
with open('guards.csv', 'r', encoding='utf-8-sig') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
all_guards.append(row[0]) # assuming guard name is in the first column
except FileNotFoundError:
with open(input('העתק-הדבק את הנתיב לקובץ רשימת שומרים כולל סיומת (.csv)'), 'r', encoding='utf-8-sig') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
all_guards.append(row[0]) # assuming guard name is in the first column
# Sort guards alphabetically
all_guards.sort()
#TODO update all selectors to run from function
# Define single selector function
def single_selector(title, options):
title=title
options=options
selected=pick(options, title)
chosen=selected[0]
return(chosen)
# Define multi selector function
def multi_selector(title, options, min_selection_count):
title=title
options=options
selected=pick(options, title, multiselect=True, min_selection_count=min_selection_count)
chosen=[x[0] for x in selected]
return(chosen)
# Selector for unavailable guards
title=("(מי בחוץ? (לבחור באמצעות רווח, להתקדם עם אנטר")
options=all_guards
selected= pick(options,title,multiselect=True, min_selection_count=0)
out_guards=[x[0] for x in selected]
print(out_guards, ":מחוץ לסבב ")
# Remove unavailable guards from available list
available_guards = [guard for guard in all_guards if not any(guard in tup for tup in selected)]
# Initialize day and night shifts
day_shifts = []
night_shifts = []
# Selector for number of guards during the day
title=("כמה שומרים ביום?")
options=["1","2","3","4"]
selected= pick(options,title)
print(selected[0]," :שומרים ביום")
day_count=int(selected[0])
# Selector for number of guards during the night
title=("כמה שומרים בלילה?")
options=["1","2","3","4"]
selected= pick(options,title)
print(selected[0]," :שומרים בלילה")
night_count=int(selected[0])
# Last shift file path
last_shift_file = 'last_shift.pkl'
# Check if the file exists
load_file=False
if os.path.exists(last_shift_file):
# Selector for loading shift history or starting from scratch
title=("?לטעון היסטוריית שמירות או להתחיל מהתחלה")
options=["לטעון היסטוריה","להתחיל מהתחלה"]
selected= pick(options,title)
print(selected[0])
if selected[0]=="לטעון היסטוריה": load_file=True
if os.path.exists(last_shift_file) and load_file:
# Load last_shift from the file
with open(last_shift_file, 'rb') as f:
last_shift = pickle.load(f)
else:
# Initialize last shift for each guard
last_shift = {guard: 6 for guard in all_guards}
# Ask the user for input about the guards from the previous day's 18-22 shift
previous_18_22_guards = []
title=("?מי שמר 18-22")
options=all_guards # Update last_shift for these guards
selected=pick(options,title,multiselect=True, min_selection_count=0)
for guard in selected: previous_18_22_guards.append(guard[0])
for guard in previous_18_22_guards:
last_shift[guard] = 5
# Ask the user for input about the guards from the previous day's 22-2 shift
previous_22_2_guards = []
title=("?מי שמר 22-02")
options=all_guards # Update last_shift for these guards
selected=pick(options,title,multiselect=True, min_selection_count=0)
for guard in selected: previous_22_2_guards.append(guard[0])
for guard in previous_22_2_guards:
last_shift[guard] = 4
# Ask the user for input about the guards from the previous day's 2-6 shift
previous_2_6_guards = []
title=("?מי שמר 02-06")
options=all_guards # Update last_shift for these guards
selected=pick(options,title,multiselect=True, min_selection_count=0)
for guard in selected: previous_2_6_guards.append(guard[0])
for guard in previous_2_6_guards:
last_shift[guard] = 3
# Ask the user for input about the guards from the previous day's 6-10 shift
previous_6_10_guards = []
title=("?מי שמר 06-10")
options=all_guards # Update last_shift for these guards
selected=pick(options,title,multiselect=True, min_selection_count=0)
for guard in selected: previous_6_10_guards.append(guard[0])
for guard in previous_6_10_guards:
last_shift[guard] = 2
# Ask the user for input about the guards from the previous day's 10-14 shift
previous_10_14_guards = []
title=("?מי שמר 10_14")
options=all_guards # Update last_shift for these guards
selected=pick(options,title,multiselect=True, min_selection_count=0)
for guard in selected: previous_10_14_guards.append(guard[0])
for guard in previous_10_14_guards:
last_shift[guard] = 1
# Check if each guard in the CSV file exists in the last_shift dictionary
for guard in all_guards:
if guard not in last_shift:
# If a guard doesn't exist, add them with a default last_shift value
last_shift[guard] = 6
# Ask the user for input about the returning guards
returning_guards = []
# Selector for returning guards
title=("?מי חוזר")
options=available_guards
selected=pick(options,title,multiselect=True, min_selection_count=0)
return_guards=[x[0] for x in selected]
print(return_guards, ":חוזרים ")
for guard in selected: returning_guards.append(guard[0])
# Selector for returning guards shift time
title=("?14-18 מי שחוזר שומר")
options=["כן","לא"]
selected=pick(options,title)
print("14-18 ","חוזרים ",selected[0], " שומרים")
if selected[0]=="כן":
return_break=False
elif selected[0]=="לא":
return_break=True
# Assign guards to shifts
for i, shift in enumerate(shifts):
# Sort available guards by the number of shifts since their last shift
available_guards.sort(key=lambda guard: (i - last_shift[guard] if last_shift[guard] is not None else float('inf')))
assigned_guards = 0
# Initialize not_assigned_guards with all available guards
not_assigned_guards = all_guards.copy()
if shift["start"] != 22 and shift["start"] != 2:
# Day shift
for _ in range(day_count):
if available_guards:
for guard in available_guards:
# Check if guard has had at least 2 shifts of rest
if last_shift[guard] >= 2:
# Make sure returning guards are not assigned to the 14-18 shift
if shift["start"] == 14 and guard in returning_guards and return_break==True:
continue
# Assign guard to shift and update last shift
last_shift[guard] = 0
day_shifts.append((shift["name"], guard))
assigned_guards += 1
# Remove guard from not_assigned_guards
not_assigned_guards.remove(guard)
break
# Increment last shift for guards not assigned to the current shift
for guard in not_assigned_guards:
last_shift[guard] += 1
# If not enough guards are assigned, assign returning guards
if assigned_guards < day_count:
for guard in returning_guards:
if last_shift[guard] >= 2:
last_shift[guard] = 0
day_shifts.append((shift["name"], guard))
assigned_guards += 1
if assigned_guards == day_count:
break
# If still not enough guards, print error and add placeholder
while assigned_guards < day_count:
# print(f"שגיאה: אין מספיק שומרים עבור משמרת {shift['name']}")
day_shifts.append((shift["name"], "חסר שומר"))
assigned_guards += 1
else:
# Night shift
for _ in range(night_count):
if available_guards:
for guard in available_guards:
# Check if guard has had at least 2 shifts of rest
if last_shift[guard] >= 2:
# Assign guard to shift and update last shift
last_shift[guard] = 0
night_shifts.append((shift["name"], guard))
assigned_guards += 1
# Remove guard from not_assigned_guards
not_assigned_guards.remove(guard)
break
# Increment last shift for guards not assigned to the current shift
for guard in not_assigned_guards:
last_shift[guard] += 1
# If not enough guards are assigned, print error and add placeholder
while assigned_guards < night_count:
# print(f"שגיאה: אין מספיק שומרים עבור משמרת {shift['name']}")
night_shifts.append((shift["name"], "חסר שומר"))
assigned_guards += 1
# Combine day_shifts and night_shifts into one list of tuples
shifts = day_shifts + night_shifts
# Define sorting key function
def sorting_key(shift):
start_time = int(shift[0].split('-')[0])
return start_time + 24 if start_time < 14 else start_time
# Sort shifts by start time in a circular manner
shifts.sort(key=sorting_key)
# Define group shifts by time function
def by_time():
shifts_dict = {}
for shift in shifts:
if shift[0] not in shifts_dict:
shifts_dict[shift[0]] = list(shift[1:])
else:
shifts_dict[shift[0]].extend(shift[1:])
return(shifts_dict)
shifts_dict=by_time()
# Define shift roster print function
def roster_print():
days_of_the_week = {"Sunday":"ראשון", "Monday":"שני", "Tuesday":"שלישי", "Wednesday":"רביעי", "Thursday":"חמישי", "Friday":"שישי", "Saturday":"שבת"}
print("\n")
print(days_of_the_week[datetime.date.today().strftime("%A")],"-",days_of_the_week[(datetime.date.today() + datetime.timedelta(days=1)).strftime("%A")])
print(datetime.date.today().strftime("%d/%m"),"-",(datetime.date.today() + datetime.timedelta(days=1)).strftime("%d/%m"))
for time, guards in shifts_dict.items():
print(f"{time}: {', '.join(guards)}")
print("\n")
# First roster print
roster_print()
# Ask user to swap, currently swaps ALL shifts. TODO: update to swap individual shifts
swapping=True
while swapping:
swap=input("לבצע חילוף ראש בראש? כן\לא \n")
if swap=="כן":
# Selector for swapping shifts
title=("בחר שני שומרים להחליף ראש בראש")
swap_list=available_guards.copy()
swap_list.sort()
options=swap_list
selected=pick(options,title,multiselect=True, min_selection_count=2)
swap_guards=[x[0] for x in selected]
if len(swap_guards) != 2:
print("שגיאה: יש לבחור שני שומרים להחליף ראש בראש.")
else:
# Swap shifts between swap_guards
a = swap_guards[0]
b= swap_guards[1]
last_shift[a], last_shift[b] = last_shift[b], last_shift[a]
for i,shift in enumerate(shifts_dict):
for h,guard in enumerate(shifts_dict[shift]):
if guard==a:
shifts_dict[shift][h]=b
continue
elif guard==b:
shifts_dict[shift][h]=a
roster_print()
else:
swapping=False
# Wait for user input to exit
input("...לחץ על אנטר כדי לצאת מהתוכנה")
# Pop last element for last_shift if empty
if list(last_shift.keys())[-1]=='':
last_shift.popitem()
# At the end of the program, write last_shift to the file
with open(last_shift_file, 'wb') as f:
pickle.dump(last_shift, f)