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)" |