albhu commited on
Commit
d1ea62c
·
verified ·
1 Parent(s): 1288fb0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -24
app.py CHANGED
@@ -1,38 +1,89 @@
1
  import streamlit as st
2
  import pandas as pd
3
- from datetime import datetime
4
- import random
5
 
6
- # Upload spreadsheet
7
- st.title("Duty Roster Generator")
8
- uploaded_file = st.file_uploader("Upload your spreadsheet", type=["csv", "xlsx"])
 
 
 
 
9
 
10
  if uploaded_file:
11
- # Load the data
12
  if uploaded_file.name.endswith('.csv'):
13
  df = pd.read_csv(uploaded_file)
14
  else:
15
  df = pd.read_excel(uploaded_file)
16
 
17
- # Display uploaded data
18
- st.write("Personnel Availability Data:")
19
  st.dataframe(df)
20
 
21
- # Input for user-specific conditions or preferences
22
- user_prompt = st.text_input("Enter specific roster requirements (e.g., preferred shifts, coverage needs)")
23
-
24
- # Generate duty roster (basic example)
25
- def generate_roster(data, prompt):
26
- # Dummy logic to assign random available days based on constraints
27
- roster = {}
28
- for _, row in data.iterrows():
29
- name = row['Name']
30
- unavailable_days = row['Unavailable Days'].split(',')
31
- available_days = [day for day in range(1, 31) if str(day) not in unavailable_days]
32
- roster[name] = random.choice(available_days) if available_days else "No Available Days"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  return roster
34
 
35
- # Display roster
36
- roster = generate_roster(df, user_prompt)
37
- st.write("Generated Duty Roster:")
38
- st.write(roster)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import pandas as pd
3
+ from collections import defaultdict
4
+ import plotly.express as px
5
 
6
+ # Title and file upload
7
+ st.title("Enhanced Duty Roster Generator with Role-Specific Assignments")
8
+ uploaded_file = st.file_uploader("Upload your availability spreadsheet with roles", type=["csv", "xlsx"])
9
+
10
+ # Multi-shift configuration
11
+ shifts = st.multiselect("Select shifts for each day", ["Morning", "Afternoon", "Night"], ["Morning", "Afternoon"])
12
+ shift_requirements = {shift: st.number_input(f"Personnel required for {shift} shift", min_value=1, value=1) for shift in shifts}
13
 
14
  if uploaded_file:
15
+ # Load the file
16
  if uploaded_file.name.endswith('.csv'):
17
  df = pd.read_csv(uploaded_file)
18
  else:
19
  df = pd.read_excel(uploaded_file)
20
 
21
+ # Display data and allow user to confirm roles
22
+ st.write("Personnel Availability and Roles Data:")
23
  st.dataframe(df)
24
 
25
+ # Generate duty roster with roles
26
+ def generate_duty_roster_with_roles(data, shifts, shift_reqs):
27
+ roster = defaultdict(lambda: defaultdict(list))
28
+
29
+ for day in range(1, 31): # Example with 30 days
30
+ for shift in shifts:
31
+ role_counts = defaultdict(int)
32
+ assigned_today = 0
33
+
34
+ for _, row in data.iterrows():
35
+ name = row['Name']
36
+ role = row['Role']
37
+ unavailable_days = set(map(int, row['Unavailable Days'].split(',')))
38
+
39
+ if day not in unavailable_days and role_counts[role] < shift_reqs[shift]:
40
+ roster[day][shift].append((name, role))
41
+ role_counts[role] += 1
42
+ assigned_today += 1
43
+
44
+ if assigned_today == shift_reqs[shift]:
45
+ break
46
+
47
+ # If unable to meet required personnel, mark as unassigned
48
+ if assigned_today < shift_reqs[shift]:
49
+ roster[day][shift].append(("Unassigned", "N/A"))
50
+
51
  return roster
52
 
53
+ # Generate and display the duty roster
54
+ duty_roster = generate_duty_roster_with_roles(df, shifts, shift_requirements)
55
+
56
+ # Display the roster with roles and shifts
57
+ st.write("Generated Duty Roster with Roles:")
58
+ for day, shifts in duty_roster.items():
59
+ st.write(f"Day {day}:")
60
+ for shift, personnel in shifts.items():
61
+ st.write(f"{shift} Shift: {', '.join([f'{p[0]} ({p[1]})' for p in personnel])}")
62
+
63
+ # Interactive Calendar Visualization
64
+ flattened_data = []
65
+ for day, shifts in duty_roster.items():
66
+ for shift, personnel in shifts.items():
67
+ for name, role in personnel:
68
+ flattened_data.append({"Day": day, "Shift": shift, "Personnel": name, "Role": role})
69
+
70
+ df_roster = pd.DataFrame(flattened_data)
71
+ fig = px.timeline(df_roster, x_start="Day", x_end="Day", y="Personnel", color="Shift", title="Duty Roster Calendar View")
72
+ st.plotly_chart(fig)
73
+
74
+ # Downloadable individual schedules
75
+ st.write("Download Individual Schedules:")
76
+ for person in df['Name'].unique():
77
+ person_schedule = df_roster[df_roster['Personnel'] == person]
78
+ person_csv = person_schedule.to_csv(index=False).encode('utf-8')
79
+ st.download_button(f"Download Schedule for {person}", data=person_csv, file_name=f"{person}_schedule.csv", mime="text/csv")
80
+
81
+ # Scheduling Insights and Analytics
82
+ st.write("Scheduling Insights:")
83
+ personnel_counts = df_roster.groupby("Personnel").size()
84
+ st.bar_chart(personnel_counts)
85
+ st.write(f"Total shifts assigned per person: {personnel_counts.to_dict()}")
86
+
87
+ st.write("Days with unassigned shifts:")
88
+ unassigned_days = df_roster[df_roster['Personnel'] == "Unassigned"]
89
+ st.write(unassigned_days[['Day', 'Shift']].drop_duplicates())