gkdivya commited on
Commit
d5bea00
·
1 Parent(s): b23fa5e

Update match_organizer.py

Browse files
Files changed (1) hide show
  1. match_organizer.py +105 -171
match_organizer.py CHANGED
@@ -1,178 +1,112 @@
1
  import streamlit as st
2
- from ortools.linear_solver import pywraplp
3
- from utils import read_teams_players
4
  import pandas as pd
5
-
6
- def schedule_incomplete_matches(num_slots, num_courts, slot_duration, availability):
7
- # Load sample matches data
8
- sample_matches_df = pd.read_csv("files/updated_sample_matches_data.csv")
 
 
 
 
 
 
 
 
 
 
 
9
 
10
- # Define time slots and courts
11
- time_slots = [f"Slot_{i}" for i in range(num_slots)]
12
- courts = [f"Court_{i}" for i in range(num_courts)]
 
 
 
13
 
14
- # Extract all players from the matches data
15
- all_players = set()
16
- for _, row in sample_matches_df.iterrows():
17
- players = row['player1'].split(' & ') + row['player2'].split(' & ')
18
- all_players.update(players)
19
- all_players = list(all_players)
20
 
21
- # Initialize the Linear Programming Solver
22
- solver = pywraplp.Solver.CreateSolver('GLOP')
23
-
24
- # Decision Variables
25
- x = {}
26
- waiting_time = {}
27
- for match_index in range(len(sample_matches_df)):
28
- for slot in time_slots:
29
- for court in courts:
30
- x[(match_index, slot, court)] = solver.BoolVar(f'Match_{match_index}_{slot}_{court}')
31
-
32
- for player in all_players:
33
- for slot in time_slots:
34
- waiting_time[(player, slot)] = solver.NumVar(0, solver.infinity(), f'Waiting_Time_{player}_{slot}')
35
-
36
- # Objective Function
37
- objective = solver.Objective()
38
- for player in all_players:
39
- for slot in time_slots:
40
- objective.SetCoefficient(waiting_time[(player, slot)], 1)
41
- objective.SetMinimization()
42
-
43
- # Constraints
44
- for match_index, match in sample_matches_df.iterrows():
45
- # Each match must be scheduled exactly once
46
- solver.Add(sum(x[(match_index, slot, court)] for slot in time_slots for court in courts) == 1)
47
-
48
- # Matches can only be scheduled when all the players of the match are available
49
- for slot in time_slots:
50
- for court in courts:
51
- if match['match_type'] == 'Singles':
52
- if availability[(match['player1'], slot)] == 0 or availability[(match['player2'], slot)] == 0:
53
- solver.Add(x[(match_index, slot, court)] == 0)
54
- else:
55
- player1_team1, player2_team1 = match['player1'].split(' & ')
56
- player1_team2, player2_team2 = match['player2'].split(' & ')
57
- if (availability[(player1_team1, slot)] == 0 or
58
- availability[(player2_team1, slot)] == 0 or
59
- availability[(player1_team2, slot)] == 0 or
60
- availability[(player2_team2, slot)] == 0):
61
- solver.Add(x[(match_index, slot, court)] == 0)
62
-
63
- # No player can be scheduled for two matches at the same time
64
- for slot in time_slots:
65
- for player in all_players:
66
- solver.Add(sum(x[(match_index, slot, court)] for match_index, match in sample_matches_df.iterrows() for court in courts if player in match['player1'].split(' & ') or player in match['player2'].split(' & ')) <= 1)
67
-
68
- # One game per court per slot
69
- for slot in time_slots:
70
- for court in courts:
71
- solver.Add(sum(x[(match_index, slot, court)] for match_index in range(len(sample_matches_df))) <= 1)
72
-
73
- # No player can have consecutive games
74
- for slot_index in range(num_slots - 1):
75
- for player in all_players:
76
- for court in courts:
77
- for match1_index, match1 in sample_matches_df.iterrows():
78
- for match2_index, match2 in sample_matches_df.iterrows():
79
- if player in match1['player1'].split(' & ') or player in match1['player2'].split(' & '):
80
- if player in match2['player1'].split(' & ') or player in match2['player2'].split(' & '):
81
- solver.Add(x[(match1_index, time_slots[slot_index], court)] + x[(match2_index, time_slots[slot_index + 1], court)] <= 1)
82
-
83
- # Update players' waiting time
84
- for player in all_players:
85
- for slot_index, slot in enumerate(time_slots):
86
- if slot_index > 0:
87
- solver.Add(waiting_time[(player, slot)] >= waiting_time[(player, time_slots[slot_index - 1])] + slot_duration * (1 - sum(x[(match_index, slot, court)] for match_index, match in sample_matches_df.iterrows() for court in courts if player in match['player1'].split(' & ') or player in match['player2'].split(' & '))))
88
- solver.Add(waiting_time[(player, slot)] >= 0 - slot_duration * sum(x[(match_index, slot, court)] for match_index, match in sample_matches_df.iterrows() for court in courts if player in match['player1'].split(' & ') or player in match['player2'].split(' & ')))
89
-
90
- # Solve the optimization problem
91
- status = solver.Solve()
92
-
93
- if status == pywraplp.Solver.OPTIMAL:
94
- # Process results
95
- scheduled_matches = []
96
- for match_index, match in sample_matches_df.iterrows():
97
- if match['Incomplete'] == 1: # Check if the match is marked as incomplete
98
- for slot in time_slots:
99
- for court in courts:
100
- if x[(match_index, slot, court)].solution_value() > 0.5:
101
- scheduled_matches.append({
102
- "Match": match_index,
103
- "Team Match": match["team_match"],
104
- "Match Type": match["match_type"],
105
- "Players": f"{match['player1']} vs {match['player2']}",
106
- "Time Slot": slot,
107
- "Court": court
108
- })
109
-
110
- # Convert results to DataFrame for easy display in Streamlit
111
- scheduled_matches_df = pd.DataFrame(scheduled_matches)
112
-
113
- # Output waiting times
114
- waiting_times = pd.DataFrame(index=time_slots, columns=list(all_players))
115
- for player in all_players:
116
- for slot in time_slots:
117
- waiting_times.at[slot, player] = waiting_time[(player, slot)].solution_value()
118
-
119
- return scheduled_matches_df, waiting_times
120
-
121
- else:
122
- st.error('The problem does not have an optimal solution.')
123
- return pd.DataFrame(), pd.DataFrame()
124
-
125
- def process_availability_data(players_availability_df, num_slots):
126
- availability = {}
127
- time_slots = [f"Slot_{i}" for i in range(num_slots)]
128
-
129
- for _, row in players_availability_df.iterrows():
130
- player = row['Player']
131
- for slot in time_slots:
132
- # Assuming the availability data has columns for each time slot
133
- if slot in row:
134
- availability[(player, slot)] = row[slot]
135
  else:
136
- availability[(player, slot)] = 0 # Default to not available if slot is not in the data
137
-
138
- return availability
139
-
140
-
141
- def schedule_matches_screen():
142
- st.header("Dynamic Match Scheduling")
143
-
144
- # Read players' availability
145
- players_availability_df = read_teams_players()
146
- print(players_availability_df.head()) # Show a preview of the availability data
147
-
148
- # User Inputs for scheduling parameters
149
- total_time = st.number_input("Enter the total available time (in minutes):", min_value=0, value=180)
150
- num_slots = st.number_input("Enter the number of time slots:", min_value=1, value=6)
151
- num_courts = st.number_input("Enter the number of courts:", min_value=1, value=3)
152
- slot_duration = total_time / num_slots # Calculate slot duration based on total time and number of slots
153
-
154
- # Process availability data
155
- availability = process_availability_data(players_availability_df, num_slots)
156
- print("Availability Data:")
157
- print(availability) # Show the availability data
158
-
159
- # Confirm scheduling
160
- if st.button("Schedule Matches"):
161
- st.write("Scheduling Matches...") # Debugging print
162
- # Run the optimization model
163
- results, waiting_times = schedule_incomplete_matches(num_slots, num_courts, slot_duration, availability)
164
-
165
- # Display results
166
- if not results.empty:
167
- st.subheader("Scheduled Matches:")
168
- st.write(results)
169
- else:
170
- st.write("No matches scheduled. Please check the optimization model and data.")
171
-
172
- if not waiting_times.empty:
173
- st.subheader("Players' Waiting Times:")
174
- st.write(waiting_times)
175
  else:
176
- st.write("No waiting times data available.")
177
-
178
-
 
1
  import streamlit as st
2
+ from ortools.sat.python import cp_model
 
3
  import pandas as pd
4
+ import gspread
5
+ from oauth2client.service_account import ServiceAccountCredentials
6
+
7
+ # Function to read data from Google Sheets
8
+
9
+ def auth_gspread():
10
+ scope = [
11
+ 'https://spreadsheets.google.com/feeds',
12
+ 'https://www.googleapis.com/auth/spreadsheets',
13
+ 'https://www.googleapis.com/auth/drive.file',
14
+ 'https://www.googleapis.com/auth/drive'
15
+ ]
16
+ creds = Credentials.from_service_account_file('/content/apartmentgames-97503f144bf1.json', scopes=scopes)
17
+ client = gspread.authorize(creds)
18
+ return client
19
 
20
+ def read_google_sheet(sheet_number):
21
+ client = auth_gspread()
22
+ spreadsheet = client.open('sample_data') # Use your actual spreadsheet name
23
+ worksheet = spreadsheet.get_worksheet(sheet_number) # Assuming you are using the first worksheet
24
+ data = worksheet.get_all_records()
25
+ return pd.DataFrame(data)
26
 
27
+ def schedule_matches_screen():
28
+ df_players = read_google_sheet(1) # Replace with your actual sheet name
29
+ df_matches = read_google_sheet(0)
 
 
 
30
 
31
+ st.title('Tennis Match Scheduler')
32
+
33
+ # UI components for input
34
+ num_courts = st.number_input('Number of Courts', min_value=1, value=3)
35
+ num_time_slots = st.number_input('Number of Time Slots', min_value=1, value=20)
36
+
37
+ if st.button('Schedule Matches'):
38
+
39
+ # Sample data
40
+ players_availability = {row['Player']: row['AvailabilityStatus'] for _, row in df_players.iterrows()}
41
+
42
+ matches = []
43
+ for _, row in df_matches.iterrows():
44
+ # Process match data
45
+ match_players = row['player1'].split(' & ') + row['player2'].split(' & ')
46
+ is_completed = row['completed'] in ['TRUE', 'True', True] # Adjust based on your data format
47
+ matches.append((match_players, row['match_type'] == 'Doubles', is_completed))
48
+
49
+ num_courts = 3
50
+ num_time_slots = 20 # Example: 15-minute slots from 12:00 PM to 10:00 PM
51
+
52
+ # Create the model
53
+ model = cp_model.CpModel()
54
+
55
+ # Create variables
56
+ # Define the break period (number of time slots)
57
+ break_period = 2
58
+
59
+ match_vars = {}
60
+ for match_id, match_info in enumerate(matches):
61
+ for time_slot in range(num_time_slots):
62
+ match_vars[(match_id, time_slot)] = model.NewBoolVar(f'match_{match_id}_time_{time_slot}')
63
+
64
+ # Constraints
65
+
66
+ # Player availability constraints
67
+ for time_slot in range(num_time_slots):
68
+ for player in set(player for match in matches for player in match[0]):
69
+ # Sum of all matches that include 'player' in 'time_slot' should be <= 1
70
+ model.Add(sum(match_vars[(match_id, time_slot)] for match_id, match in enumerate(matches) if player in match[0]) <= 1)
71
+
72
+ # Update the model with break period constraints
73
+ for player in set(player for match in matches for player in match[0]):
74
+ for time_slot in range(num_time_slots - break_period):
75
+ # Sum of matches for 'player' in 'time_slot' and the next 'break_period' slots should be <= 1
76
+ model.Add(sum(match_vars[(match_id, t)]
77
+ for t in range(time_slot, time_slot + break_period + 1)
78
+ for match_id, match in enumerate(matches)
79
+ if player in match[0]) <= 1)
80
+
81
+ for match_id, (players_in_match, is_double, completed) in enumerate(matches):
82
+ if not completed and all(players_availability[player] == 'Available' for player in players_in_match):
83
+ model.Add(sum(match_vars[(match_id, time_slot)] for time_slot in range(num_time_slots)) == 1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  else:
85
+ for time_slot in range(num_time_slots):
86
+ model.Add(match_vars[(match_id, time_slot)] == 0)
87
+
88
+ for time_slot in range(num_time_slots):
89
+ model.Add(sum(match_vars[(match_id, time_slot)] for match_id in range(len(matches))) <= num_courts)
90
+
91
+ # Data structure to hold scheduled matches
92
+ scheduled_matches = []
93
+
94
+ solver = cp_model.CpSolver()
95
+ status = solver.Solve(model)
96
+
97
+ if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
98
+ for match_id, (players_in_match, _, _) in enumerate(matches):
99
+ for time_slot in range(num_time_slots):
100
+ if solver.BooleanValue(match_vars[(match_id, time_slot)]):
101
+ scheduled_matches.append((time_slot, match_id, ' & '.join(players_in_match)))
102
+
103
+ if status in [cp_model.OPTIMAL, cp_model.FEASIBLE]:
104
+ # Display the scheduled matches
105
+ for time_slot, match_id, players in scheduled_matches:
106
+ for court in range(1, num_courts + 1):
107
+ if court not in court_assignment[time_slot]:
108
+ court_assignment[time_slot].append(court)
109
+ st.write(f'Time Slot: {time_slot}, Match: {match_id}, Players: {players}, Court: {court}')
110
+ break
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  else:
112
+ st.write('No solution found.')