Spaces:
Sleeping
Sleeping
from collections import defaultdict | |
from datetime import datetime | |
from statistics import median | |
import pandas as pd | |
def calculate_probability(numerator, denominator): | |
"""Calculate percentage probability.""" | |
return (numerator / denominator * 100) if denominator else 0 | |
def analyze_streaks(games_sorted, username): | |
"""Analyze win/loss streaks within the same hour.""" | |
win_after_win_same_hour = 0 | |
loss_after_loss_same_hour = 0 | |
total_win_streaks_same_hour = 0 | |
total_loss_streaks_same_hour = 0 | |
previous_result = None | |
previous_hour = None | |
for game in games_sorted: | |
end_time = game.get('end_time') | |
if not end_time: | |
continue | |
hour_of_day = datetime.fromtimestamp(end_time).hour | |
current_result = get_game_result(game, username) | |
if not current_result: | |
continue | |
if previous_result and previous_hour == hour_of_day: | |
if previous_result == 'win': | |
total_win_streaks_same_hour += 1 | |
if current_result == 'win': | |
win_after_win_same_hour += 1 | |
elif previous_result == 'loss': | |
total_loss_streaks_same_hour += 1 | |
if current_result == 'loss': | |
loss_after_loss_same_hour += 1 | |
previous_result = current_result | |
previous_hour = hour_of_day | |
print(f"Total win streaks: {total_win_streaks_same_hour}, Wins after win: {win_after_win_same_hour}") | |
print(f"Total loss streaks: {total_loss_streaks_same_hour}, Losses after loss: {loss_after_loss_same_hour}") | |
win_probability = calculate_probability(win_after_win_same_hour, total_win_streaks_same_hour) | |
loss_probability = calculate_probability(loss_after_loss_same_hour, total_loss_streaks_same_hour) | |
return win_probability, loss_probability | |
def analyze_sequences(games_sorted, username): | |
"""Analyze 'win-loss' and 'loss-win' sequences within the same hour.""" | |
win_after_win_loss_same_hour = 0 | |
win_after_loss_win_same_hour = 0 | |
total_win_loss_sequences_same_hour = 0 | |
total_loss_win_sequences_same_hour = 0 | |
previous_result = None | |
previous_hour = None | |
for i, game in enumerate(games_sorted): | |
end_time = game.get('end_time') | |
if not end_time: | |
continue | |
hour_of_day = datetime.fromtimestamp(end_time).hour | |
current_result = get_game_result(game, username) | |
if not current_result: | |
continue | |
if previous_result and previous_hour == hour_of_day: | |
if previous_result == 'win' and current_result == 'loss': | |
total_win_loss_sequences_same_hour += 1 | |
next_game_result = get_game_result(games_sorted[i + 1], username) if i + 1 < len(games_sorted) else None | |
if next_game_result == 'win': | |
win_after_win_loss_same_hour += 1 | |
elif previous_result == 'loss' and current_result == 'win': | |
total_loss_win_sequences_same_hour += 1 | |
next_game_result = get_game_result(games_sorted[i + 1], username) if i + 1 < len(games_sorted) else None | |
if next_game_result == 'win': | |
win_after_loss_win_same_hour += 1 | |
previous_result = current_result | |
previous_hour = hour_of_day | |
print(f"Total 'win-loss' sequences: {total_win_loss_sequences_same_hour}, Wins after 'win-loss': {win_after_win_loss_same_hour}") | |
print(f"Total 'loss-win' sequences: {total_loss_win_sequences_same_hour}, Wins after 'loss-win': {win_after_loss_win_same_hour}") | |
win_after_win_loss_probability = calculate_probability(win_after_win_loss_same_hour, total_win_loss_sequences_same_hour) | |
win_after_loss_win_probability = calculate_probability(win_after_loss_win_same_hour, total_loss_win_sequences_same_hour) | |
return win_after_win_loss_probability, win_after_loss_win_probability | |
def analyze_games(games, username): | |
"""Analyze games by month and return statistics.""" | |
games_per_month = defaultdict(int) | |
stats_per_month = defaultdict(lambda: defaultdict(int)) | |
total_games = 0 | |
total_wins = 0 | |
total_losses = 0 | |
total_timeouts = 0 | |
for game in games: | |
end_time = game.get('end_time') | |
if not end_time: | |
continue | |
end_datetime = datetime.fromtimestamp(end_time) | |
month = end_datetime.strftime('%Y-%m') | |
result = get_game_result(game, username) | |
if result == 'win': | |
stats_per_month[month]['wins'] += 1 | |
total_wins += 1 | |
elif result == 'timeout': | |
stats_per_month[month]['timeouts'] += 1 | |
total_timeouts += 1 | |
stats_per_month[month]['losses'] += 1 # Count timeout as a loss | |
total_losses += 1 | |
elif result == 'loss': | |
stats_per_month[month]['losses'] += 1 | |
total_losses += 1 | |
games_per_month[month] += 1 | |
total_games += 1 | |
total_months_played = len(games_per_month) | |
return games_per_month, stats_per_month, total_games, total_wins, total_losses, total_timeouts, total_months_played | |
def generate_monthly_report(games_per_month, stats_per_month): | |
"""Generate a Pandas DataFrame report for monthly analysis including Timeout Rate.""" | |
data = [] | |
for month, total_games in games_per_month.items(): | |
wins = stats_per_month[month]['wins'] | |
losses = stats_per_month[month]['losses'] | |
timeouts = stats_per_month[month]['timeouts'] | |
win_rate = (wins / total_games * 100) if total_games else 0 | |
loss_rate = (losses / total_games * 100) if total_games else 0 | |
timeout_rate = (timeouts / total_games * 100) if total_games else 0 | |
data.append({ | |
'Month': month, | |
'Games Played': total_games, | |
'Wins': wins, | |
'Losses': losses, | |
'Win Rate (%)': round(win_rate, 1), | |
'Loss Rate (%)': round(loss_rate, 1), | |
'Timeout Rate (%)': round(timeout_rate, 1) | |
}) | |
return pd.DataFrame(data) | |
def get_game_result(game, username): | |
"""Determine if the user won or lost the game.""" | |
result = None | |
if game.get('white', {}).get('username') == username: | |
result = game.get('white', {}).get('result') | |
elif game.get('black', {}).get('username') == username: | |
result = game.get('black', {}).get('result') | |
if result == 'win': | |
return 'win' | |
elif result == 'timeout': | |
return 'timeout' # Explicitly return "timeout" | |
elif result in ['checkmated', 'resigned', 'lose', 'abandoned']: | |
return 'loss' | |
return None | |
def calculate_average_and_median_games(games): | |
"""Calculate the average and median number of games played per day.""" | |
games_per_day = defaultdict(int) | |
for game in games: | |
end_time = game.get('end_time') | |
if not end_time: | |
continue | |
end_date = datetime.fromtimestamp(end_time).date() | |
games_per_day[end_date] += 1 | |
total_days = len(games_per_day) | |
total_games = sum(games_per_day.values()) | |
average_games = total_games / total_days if total_days else 0 | |
median_games = median(games_per_day.values()) if total_days else 0 | |
return average_games, median_games | |
def format_duration(total_months): | |
"""Format the duration as 'X years, Y months'.""" | |
years = total_months // 12 | |
months = total_months % 12 | |
if years > 0 and months > 0: | |
return f"{years} year(s), {months} month(s)" | |
elif years > 0: | |
return f"{years} year(s)" | |
else: | |
return f"{months} month(s)" |