gael1130 commited on
Commit
6d3434f
·
verified ·
1 Parent(s): b56863a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +222 -0
app.py ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from utils.data_loader import fetch_and_save_chess_data
3
+ from utils.game_analysis import (
4
+ analyze_games,
5
+ generate_monthly_report,
6
+ calculate_average_and_median_games,
7
+ analyze_streaks,
8
+ analyze_sequences,
9
+ format_duration
10
+ )
11
+ from datetime import datetime
12
+ import os
13
+ import json
14
+
15
+ import matplotlib.pyplot as plt
16
+ import io
17
+ from PIL import Image
18
+ import plotly.graph_objects as go
19
+ import pandas as pd
20
+ import csv
21
+
22
+ logged_in_user = None # Global state to store the logged-in user
23
+
24
+
25
+ # Define your user credentials
26
+ auth_users = [
27
+ ("Sacha", "SachaIsTheBest"),
28
+ ("Florian", "FlorianIsTheBest"),
29
+ ("Lucas", "Slevin"),
30
+ ("Gael", "Kalel"),
31
+ ("BlueNote", "MamaLinda")
32
+ ]
33
+
34
+
35
+
36
+ DATA_FOLDER = 'data/'
37
+ LOG_FILE = 'user_logs.csv'
38
+
39
+ # Initialize log file if it doesn't exist
40
+ if not os.path.exists(LOG_FILE):
41
+ with open(LOG_FILE, 'w', newline='') as log_file:
42
+ writer = csv.writer(log_file)
43
+ writer.writerow(["Username", "Timestamp", "Action", "Query"])
44
+
45
+ def log_user_action(username, action, query=""):
46
+ """Log user actions to a CSV file."""
47
+ timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
48
+ with open(LOG_FILE, 'a', newline='') as log_file:
49
+ writer = csv.writer(log_file)
50
+ writer.writerow([username, timestamp, action, query])
51
+
52
+ def get_monthly_report(username, logged_in_user):
53
+ """Fetch data for a given username, reuse existing data if available, and generate a monthly report."""
54
+ current_date = datetime.now().strftime('%Y-%m-%d')
55
+ filename = os.path.join(DATA_FOLDER, f"{username}_{current_date}.json")
56
+
57
+ log_user_action(logged_in_user, "Search", username)
58
+
59
+ if os.path.exists(filename):
60
+ print(f"Using existing data file: {filename}")
61
+ with open(filename, 'r') as file:
62
+ games = json.load(file)
63
+ else:
64
+ games = fetch_and_save_chess_data(username, filename)
65
+ if not games:
66
+ return "No data found for the specified username."
67
+
68
+ games_sorted = sorted(games, key=lambda x: x.get('end_time'))
69
+
70
+ # Perform monthly analysis
71
+ games_per_month, stats_per_month, total_games, total_wins, total_losses, total_timeouts, total_months_played = analyze_games(games, username)
72
+ report_df = generate_monthly_report(games_per_month, stats_per_month)
73
+
74
+ # Calculate average and median games per day
75
+ average_games, median_games = calculate_average_and_median_games(games)
76
+
77
+ # Calculate streak probabilities
78
+ win_prob, loss_prob = analyze_streaks(games_sorted, username)
79
+
80
+ # Calculate sequence probabilities
81
+ win_after_wl_prob, win_after_lw_prob = analyze_sequences(games_sorted, username)
82
+
83
+ # Format the duration of months played
84
+ formatted_duration = format_duration(total_months_played)
85
+
86
+
87
+ # Prepare the text summary
88
+ summary_text = (
89
+ f"Total duration played: {formatted_duration}\n"
90
+ f"Total games played: {total_games}\n"
91
+ f"Total wins: {total_wins}\n"
92
+ f"Total losses: {total_losses}\n"
93
+ f"Total timeouts: {total_timeouts}\n"
94
+ f"Average games played per day: {average_games:.2f}\n"
95
+ f"Median games played per day: {median_games}\n"
96
+ f"Probability of winning the next game after a win in the same hour: {win_prob:.2f}%\n"
97
+ f"Probability of losing the next game after a loss in the same hour: {loss_prob:.2f}%\n"
98
+ f"Probability of winning the next game after a 'win-loss' sequence in the same hour: {win_after_wl_prob:.2f}%\n"
99
+ f"Probability of winning the next game after a 'loss-win' sequence in the same hour: {win_after_lw_prob:.2f}%"
100
+ )
101
+
102
+ stacked_bar_img = generate_stacked_bar_chart(report_df)
103
+
104
+ return report_df, summary_text, stacked_bar_img
105
+
106
+
107
+
108
+
109
+ def generate_stacked_bar_chart(report_df):
110
+ """Generate an interactive stacked bar chart with wins, losses, and a line plot for timeouts using Plotly."""
111
+ # Extract data
112
+ months = pd.to_datetime(report_df['Month']).dt.strftime('%b, %Y')
113
+ wins = report_df['Wins']
114
+ losses = report_df['Losses']
115
+ timeouts = report_df['Timeout Rate (%)']
116
+ total_games = report_df['Games Played']
117
+
118
+ # Create the figure
119
+ fig = go.Figure()
120
+
121
+ # Add wins bars
122
+ fig.add_trace(go.Bar(
123
+ x=months,
124
+ y=wins,
125
+ name='Wins',
126
+ marker=dict(color='#1f77b4'),
127
+ hovertemplate='<b>Wins</b>: %{y}<extra></extra>'
128
+ ))
129
+
130
+ # Add losses bars stacked on top of wins
131
+ fig.add_trace(go.Bar(
132
+ x=months,
133
+ y=losses,
134
+ name='Losses',
135
+ marker=dict(color='#ff7f0e'),
136
+ hovertemplate='<b>Losses</b>: %{y}<extra></extra>'
137
+ ))
138
+
139
+ # Add timeouts as a line plot
140
+ fig.add_trace(go.Scatter(
141
+ x=months,
142
+ y=timeouts,
143
+ mode='lines+markers',
144
+ name='Timeouts',
145
+ line=dict(color='#da5bac', width=2),
146
+ hovertemplate='<b>Timeouts</b>: %{y:.1f}%<extra></extra>'
147
+ ))
148
+
149
+ # Add rotated annotations for total games on top of each bar
150
+ for i, total in enumerate(total_games):
151
+ fig.add_annotation(
152
+ x=months[i],
153
+ y=total + 5,
154
+ text=str(int(total)),
155
+ showarrow=False,
156
+ font=dict(size=12, color='white'),
157
+ align='center',
158
+ textangle=-45 # Rotate the text label by -45 degrees
159
+ )
160
+
161
+ # Update layout for stacked bars and hover information
162
+ fig.update_layout(
163
+ barmode='stack',
164
+ title='Monthly Win/Loss Stacked Bar Chart with Total Games and Timeouts',
165
+ xaxis_title='Month',
166
+ yaxis_title='Count',
167
+ legend_title='Legend',
168
+ hovermode='x unified',
169
+ template='plotly_dark'
170
+ )
171
+
172
+ # Return the Plotly figure
173
+ return fig
174
+
175
+ logged_in_user_state = gr.State()
176
+
177
+ # Authentication callback function
178
+ def auth_callback(username, password):
179
+ global logged_in_user
180
+ valid_users = dict(auth_users)
181
+ if username in valid_users and valid_users[username] == password:
182
+ log_user_action(username, "Login")
183
+ logged_in_user = username # Store the logged-in user globally
184
+ return True
185
+ return False
186
+
187
+
188
+
189
+
190
+ def get_report_with_user(username):
191
+ global logged_in_user
192
+ return get_monthly_report(username, logged_in_user or "Unknown")
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+ # Custom layout using gr.Blocks with CSS
201
+ with gr.Blocks(css="style.css", theme=gr.themes.Soft()) as app:
202
+ gr.Markdown("# Chess Analysis App")
203
+ username_input = gr.Textbox(label="Chess.com Username", placeholder="Enter Chess.com username")
204
+ submit_button = gr.Button("Submit")
205
+
206
+ # Define outputs
207
+ output_data = gr.Dataframe(headers=["Month", "Games Played", "Wins", "Losses", "Win Rate (%)", "Loss Rate (%)", "Timeout Rate (%)"])
208
+ summary_text = gr.Textbox(label="Summary", interactive=False)
209
+ # stacked_bar_img = gr.Image(label="Monthly Stacked Bar Chart with Timeouts")
210
+ stacked_bar_img = gr.Plot(label="Monthly Stacked Bar Chart with Timeouts")
211
+
212
+
213
+ # Link the click event
214
+ submit_button.click(
215
+ fn=get_report_with_user,
216
+ inputs=[username_input],
217
+ outputs=[output_data, summary_text, stacked_bar_img]
218
+ )
219
+
220
+
221
+
222
+ app.launch(auth=auth_users, share=True)