File size: 7,802 Bytes
641009d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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)"