GameSentenceMiner 2.16.7__py3-none-any.whl → 2.16.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of GameSentenceMiner might be problematic. Click here for more details.

@@ -1,520 +1,562 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
+
3
4
  <head>
4
5
  <meta charset="UTF-8">
5
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
7
  <title>GSM Dashboard</title>
7
8
  <!-- Include Chart.js from a CDN -->
8
9
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
9
-
10
+
10
11
  <!-- Include html2canvas for screenshot functionality -->
11
12
  <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
12
-
13
+
13
14
  <!-- Include shared theme styles -->
14
15
  {% include 'components/theme-styles.html' %}
15
-
16
+
16
17
  <!-- Include shared CSS -->
17
18
  <link rel="stylesheet" href="/static/css/shared.css">
18
-
19
+
19
20
  <!-- Include stats-specific CSS -->
20
21
  <link rel="stylesheet" href="/static/css/stats.css">
21
-
22
+
22
23
  <!-- Include shared kanji grid CSS -->
23
24
  <link rel="stylesheet" href="/static/css/kanji-grid.css">
24
25
  </head>
26
+
25
27
  <body>
26
28
 
27
- <div class="container">
28
- <h1>GSM - Statistics</h1>
29
-
30
- <!-- Include shared navigation -->
31
- {% include 'components/navigation.html' %}
29
+ <div class="container">
30
+ <h1>GSM - Statistics</h1>
32
31
 
33
- <!-- Dashboard Statistics Sections -->
34
- <div class="dashboard-container">
35
- <!-- Current Game Statistics Panel -->
36
- <div class="dashboard-card current-game" id="currentGameCard">
37
- <div class="dashboard-card-header">
38
- <div>
39
- <h3 class="dashboard-card-title">
40
- <span class="dashboard-card-icon">🎮</span>
41
- Current Game Statistics
42
- </h3>
43
- <p class="dashboard-card-subtitle" id="currentGameName">Loading...</p>
44
- </div>
45
- <div class="dashboard-streak-indicator" id="currentGameStreak" style="display: none;">
46
- <span id="currentStreakValue">0</span> day streak
47
- </div>
48
- </div>
49
-
50
- <div class="dashboard-stats-grid" id="currentGameStats">
51
- <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read in this game">
52
- <span class="dashboard-stat-value" id="currentTotalChars">-</span>
53
- <span class="dashboard-stat-label">Characters</span>
54
- </div>
55
- <div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading this game">
56
- <span class="dashboard-stat-value" id="currentTotalTime">-</span>
57
- <span class="dashboard-stat-label">Time Spent</span>
58
- </div>
59
- <div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed for this game">
60
- <span class="dashboard-stat-value" id="currentReadingSpeed">-</span>
61
- <span class="dashboard-stat-label">Chars/Hour</span>
62
- </div>
63
- <div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions for this game">
64
- <span class="dashboard-stat-value" id="currentSessions">-</span>
65
- <span class="dashboard-stat-label">Sessions</span>
32
+ <!-- Include shared navigation -->
33
+ {% include 'components/navigation.html' %}
34
+
35
+ <!-- Dashboard Statistics Sections -->
36
+ <div class="dashboard-container">
37
+ <!-- Current Game Statistics Panel -->
38
+ <div class="dashboard-card current-game" id="currentGameCard">
39
+ <div class="dashboard-card-header">
40
+ <div>
41
+ <h3 class="dashboard-card-title">
42
+ <span class="dashboard-card-icon">🎮</span>
43
+ Current Game Statistics
44
+ </h3>
45
+ <p class="dashboard-card-subtitle" id="currentGameName">Loading...</p>
46
+ </div>
47
+ <div class="dashboard-streak-indicator" id="currentGameStreak" style="display: none;">
48
+ <span id="currentStreakValue">0</span> day streak
49
+ </div>
66
50
  </div>
67
- </div>
68
-
69
- <div class="dashboard-progress-section">
70
- <div class="dashboard-progress-title">Recent Progress</div>
71
- <div class="dashboard-progress-items">
72
- <div class="dashboard-progress-item">
73
- <div class="dashboard-progress-value positive" id="currentMonthlyChars">-</div>
74
- <div class="dashboard-progress-label">Monthly Characters</div>
51
+
52
+ <div class="dashboard-stats-grid" id="currentGameStats">
53
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read in this game">
54
+ <span class="dashboard-stat-value" id="currentTotalChars">-</span>
55
+ <span class="dashboard-stat-label">Characters</span>
56
+ </div>
57
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading this game">
58
+ <span class="dashboard-stat-value" id="currentTotalTime">-</span>
59
+ <span class="dashboard-stat-label">Time Spent</span>
75
60
  </div>
76
- <div class="dashboard-progress-item">
77
- <div class="dashboard-progress-value neutral" id="currentFirstDate">-</div>
78
- <div class="dashboard-progress-label">Started</div>
61
+ <div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed for this game">
62
+ <span class="dashboard-stat-value" id="currentReadingSpeed">-</span>
63
+ <span class="dashboard-stat-label">Chars/Hour</span>
79
64
  </div>
80
- <div class="dashboard-progress-item">
81
- <div class="dashboard-progress-value neutral" id="currentLastDate">-</div>
82
- <div class="dashboard-progress-label">Last Activity</div>
65
+ <div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions for this game">
66
+ <span class="dashboard-stat-value" id="currentSessions">-</span>
67
+ <span class="dashboard-stat-label">Sessions</span>
83
68
  </div>
84
69
  </div>
85
- </div>
86
- </div>
87
70
 
88
- <!-- All Games Historical Overview -->
89
- <div class="dashboard-card all-games" id="allGamesCard">
90
- <div class="dashboard-card-header">
91
- <div>
92
- <h3 class="dashboard-card-title">
93
- <span class="dashboard-card-icon">📚</span>
94
- All Games Overview
95
- </h3>
96
- <p class="dashboard-card-subtitle" id="totalGamesCount">Loading...</p>
97
- </div>
98
- <div class="dashboard-streak-indicator" id="allGamesStreak" style="display: none;">
99
- <span id="allStreakValue">0</span> day streak
71
+ <div class="dashboard-progress-section">
72
+ <div class="dashboard-progress-title">Recent Progress</div>
73
+ <div class="dashboard-progress-items">
74
+ <div class="dashboard-progress-item">
75
+ <div class="dashboard-progress-value positive" id="currentMonthlyChars">-</div>
76
+ <div class="dashboard-progress-label">Monthly Characters</div>
77
+ </div>
78
+ <div class="dashboard-progress-item">
79
+ <div class="dashboard-progress-value neutral" id="currentFirstDate">-</div>
80
+ <div class="dashboard-progress-label">Started</div>
81
+ </div>
82
+ <div class="dashboard-progress-item">
83
+ <div class="dashboard-progress-value neutral" id="currentLastDate">-</div>
84
+ <div class="dashboard-progress-label">Last Activity</div>
85
+ </div>
86
+ </div>
100
87
  </div>
101
88
  </div>
102
-
103
- <div class="dashboard-stats-grid" id="allGamesStats">
104
- <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read across all games">
105
- <span class="dashboard-stat-value" id="allTotalChars">-</span>
106
- <span class="dashboard-stat-label">Characters</span>
107
- </div>
108
- <div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading across all games">
109
- <span class="dashboard-stat-value" id="allTotalTime">-</span>
110
- <span class="dashboard-stat-label">Time Spent</span>
111
- </div>
112
- <div class="dashboard-stat-item tooltip" data-tooltip="Overall average reading speed">
113
- <span class="dashboard-stat-value" id="allReadingSpeed">-</span>
114
- <span class="dashboard-stat-label">Chars/Hour</span>
115
- </div>
116
- <div class="dashboard-stat-item tooltip" data-tooltip="Total number of reading sessions">
117
- <span class="dashboard-stat-value" id="allSessions">-</span>
118
- <span class="dashboard-stat-label">Sessions</span>
89
+
90
+ <!-- All Games Historical Overview -->
91
+ <div class="dashboard-card all-games" id="allGamesCard">
92
+ <div class="dashboard-card-header">
93
+ <div>
94
+ <h3 class="dashboard-card-title">
95
+ <span class="dashboard-card-icon">📚</span>
96
+ All Games Overview
97
+ </h3>
98
+ <p class="dashboard-card-subtitle" id="totalGamesCount">Loading...</p>
99
+ </div>
100
+ <div class="dashboard-streak-indicator" id="allGamesStreak" style="display: none;">
101
+ <span id="allStreakValue">0</span> day streak
102
+ </div>
119
103
  </div>
120
- </div>
121
-
122
- <div class="dashboard-progress-section">
123
- <div class="dashboard-progress-title">Overall Progress</div>
124
- <div class="dashboard-progress-items">
125
- <div class="dashboard-progress-item">
126
- <div class="dashboard-progress-value positive" id="allMonthlyChars">-</div>
127
- <div class="dashboard-progress-label">Monthly Characters</div>
104
+
105
+ <div class="dashboard-stats-grid" id="allGamesStats">
106
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read across all games">
107
+ <span class="dashboard-stat-value" id="allTotalChars">-</span>
108
+ <span class="dashboard-stat-label">Characters</span>
109
+ </div>
110
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading across all games">
111
+ <span class="dashboard-stat-value" id="allTotalTime">-</span>
112
+ <span class="dashboard-stat-label">Time Spent</span>
113
+ </div>
114
+ <div class="dashboard-stat-item tooltip" data-tooltip="Overall average reading speed">
115
+ <span class="dashboard-stat-value" id="allReadingSpeed">-</span>
116
+ <span class="dashboard-stat-label">Chars/Hour</span>
128
117
  </div>
129
- <div class="dashboard-progress-item">
130
- <div class="dashboard-progress-value neutral" id="allUniqueGames">-</div>
131
- <div class="dashboard-progress-label">Games Played</div>
118
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total number of reading sessions">
119
+ <span class="dashboard-stat-value" id="allSessions">-</span>
120
+ <span class="dashboard-stat-label">Sessions</span>
132
121
  </div>
133
- <div class="dashboard-progress-item">
134
- <div class="dashboard-progress-value neutral" id="allTotalSentences">-</div>
135
- <div class="dashboard-progress-label">Total Sentences</div>
122
+ </div>
123
+
124
+ <div class="dashboard-progress-section">
125
+ <div class="dashboard-progress-title">Overall Progress</div>
126
+ <div class="dashboard-progress-items">
127
+ <div class="dashboard-progress-item">
128
+ <div class="dashboard-progress-value positive" id="allMonthlyChars">-</div>
129
+ <div class="dashboard-progress-label">Monthly Characters</div>
130
+ </div>
131
+ <div class="dashboard-progress-item">
132
+ <div class="dashboard-progress-value neutral" id="allUniqueGames">-</div>
133
+ <div class="dashboard-progress-label">Games Played</div>
134
+ </div>
135
+ <div class="dashboard-progress-item">
136
+ <div class="dashboard-progress-value neutral" id="allTotalSentences">-</div>
137
+ <div class="dashboard-progress-label">Total Sentences</div>
138
+ </div>
136
139
  </div>
137
140
  </div>
138
141
  </div>
139
142
  </div>
140
- </div>
141
143
 
142
- <!-- Loading/Error states for dashboard -->
143
- <div class="dashboard-loading" id="dashboardLoading" style="display: none;">
144
- <div class="spinner"></div>
145
- <span>Loading dashboard statistics...</span>
146
- </div>
144
+ <!-- Loading/Error states for dashboard -->
145
+ <div class="dashboard-loading" id="dashboardLoading" style="display: none;">
146
+ <div class="spinner"></div>
147
+ <span>Loading dashboard statistics...</span>
148
+ </div>
147
149
 
148
- <div class="dashboard-error" id="dashboardError" style="display: none;">
149
- <div class="dashboard-error-icon">⚠️</div>
150
- <div class="dashboard-error-message">Failed to load dashboard statistics</div>
151
- <button class="dashboard-retry-btn" data-action="loadDashboardData">Retry</button>
152
- </div>
150
+ <div class="dashboard-error" id="dashboardError" style="display: none;">
151
+ <div class="dashboard-error-icon">⚠️</div>
152
+ <div class="dashboard-error-message">Failed to load dashboard statistics</div>
153
+ <button class="dashboard-retry-btn" data-action="loadDashboardData">Retry</button>
154
+ </div>
153
155
 
154
156
 
155
- <!-- Today's Overview Card -->
156
- <div class="dashboard-card today-overview" id="todayOverviewCard" style="margin-bottom: 24px;">
157
- <div class="dashboard-card-header">
158
- <h3 class="dashboard-card-title">
159
- <span class="dashboard-card-icon">📅</span>
160
- Today's Overview
161
- </h3>
162
- <p class="dashboard-card-subtitle" id="todayDate">Loading...</p>
163
- </div>
164
- <div class="dashboard-stats-grid" id="todayStats">
165
- <div class="dashboard-stat-item tooltip" data-tooltip="Total hours spent reading today">
166
- <span class="dashboard-stat-value" id="todayTotalHours">-</span>
167
- <span class="dashboard-stat-label">Hours Spent</span>
168
- </div>
169
- <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read today">
170
- <span class="dashboard-stat-value" id="todayTotalChars">-</span>
171
- <span class="dashboard-stat-label">Characters</span>
172
- </div>
173
- <div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions today">
174
- <span class="dashboard-stat-value" id="todaySessions">-</span>
175
- <span class="dashboard-stat-label">Sessions</span>
157
+ <!-- Today's Overview Card -->
158
+ <div class="dashboard-card today-overview" id="todayOverviewCard" style="margin-bottom: 24px;">
159
+ <div class="dashboard-card-header">
160
+ <h3 class="dashboard-card-title">
161
+ <span class="dashboard-card-icon">📅</span>
162
+ Today's Overview
163
+ </h3>
164
+ <p class="dashboard-card-subtitle" id="todayDate">Loading...</p>
176
165
  </div>
177
- <div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed today">
178
- <span class="dashboard-stat-value" id="todayCharsPerHour">-</span>
179
- <span class="dashboard-stat-label">Chars/Hour</span>
166
+ <div class="dashboard-stats-grid" id="todayStats">
167
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total hours spent reading today">
168
+ <span class="dashboard-stat-value" id="todayTotalHours">-</span>
169
+ <span class="dashboard-stat-label">Hours Spent</span>
170
+ </div>
171
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read today">
172
+ <span class="dashboard-stat-value" id="todayTotalChars">-</span>
173
+ <span class="dashboard-stat-label">Characters</span>
174
+ </div>
175
+ <div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions today">
176
+ <span class="dashboard-stat-value" id="todaySessions">-</span>
177
+ <span class="dashboard-stat-label">Sessions</span>
178
+ </div>
179
+ <div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed today">
180
+ <span class="dashboard-stat-value" id="todayCharsPerHour">-</span>
181
+ <span class="dashboard-stat-label">Chars/Hour</span>
182
+ </div>
180
183
  </div>
181
184
  </div>
182
- </div>
183
185
 
184
186
  <!-- Goal Progress Chart -->
185
- <div class="dashboard-card goal-progress-chart" id="goalProgressChart" style="margin-bottom: 30px;">
186
- <div class="dashboard-card-header">
187
- <h3 class="dashboard-card-title">
188
- <span class="dashboard-card-icon">🎯</span>
189
- Goal Progress Chart
190
- </h3>
191
- <p class="dashboard-card-subtitle">Track your reading goals and projected completion dates</p>
192
- </div>
193
-
194
- <div class="goal-progress-grid">
195
- <!-- Reading Hours Goal -->
196
- <div class="goal-progress-item">
197
- <div class="goal-progress-header">
198
- <div class="goal-progress-label">
199
- <span class="goal-icon">⏱️</span>
200
- Reading Hours
187
+ <div class="dashboard-card goal-progress-chart" id="goalProgressChart" style="margin-bottom: 30px;">
188
+ <div class="dashboard-card-header">
189
+ <h3 class="dashboard-card-title">
190
+ <span class="dashboard-card-icon">🎯</span>
191
+ Goal Progress Chart
192
+ </h3>
193
+ <p class="dashboard-card-subtitle">Track your reading goals and projected completion dates</p>
194
+ </div>
195
+
196
+ <div class="goal-progress-grid">
197
+ <!-- Reading Hours Goal -->
198
+ <div class="goal-progress-item">
199
+ <div class="goal-progress-header">
200
+ <div class="goal-progress-label">
201
+ <span class="goal-icon">⏱️</span>
202
+ Reading Hours
203
+ </div>
204
+ <div class="goal-progress-values">
205
+ <span class="goal-current" id="goalHoursCurrent">-</span>
206
+ <span class="goal-separator">/</span>
207
+ <span class="goal-target" id="goalHoursTarget">-</span>
208
+ </div>
201
209
  </div>
202
- <div class="goal-progress-values">
203
- <span class="goal-current" id="goalHoursCurrent">-</span>
204
- <span class="goal-separator">/</span>
205
- <span class="goal-target" id="goalHoursTarget">-</span>
210
+ <div class="goal-progress-bar">
211
+ <div class="goal-progress-fill" id="goalHoursProgress" data-percentage="0"></div>
212
+ </div>
213
+ <div class="goal-progress-info">
214
+ <span class="goal-percentage" id="goalHoursPercentage">0%</span>
215
+ <span class="goal-projection" id="goalHoursProjection">-</span>
206
216
  </div>
207
217
  </div>
208
- <div class="goal-progress-bar">
209
- <div class="goal-progress-fill" id="goalHoursProgress" data-percentage="0"></div>
210
- </div>
211
- <div class="goal-progress-info">
212
- <span class="goal-percentage" id="goalHoursPercentage">0%</span>
213
- <span class="goal-projection" id="goalHoursProjection">-</span>
214
- </div>
215
- </div>
216
218
 
217
- <!-- Character Count Goal -->
218
- <div class="goal-progress-item">
219
- <div class="goal-progress-header">
220
- <div class="goal-progress-label">
221
- <span class="goal-icon">📖</span>
222
- Characters Read
219
+ <!-- Character Count Goal -->
220
+ <div class="goal-progress-item">
221
+ <div class="goal-progress-header">
222
+ <div class="goal-progress-label">
223
+ <span class="goal-icon">📖</span>
224
+ Characters Read
225
+ </div>
226
+ <div class="goal-progress-values">
227
+ <span class="goal-current" id="goalCharsCurrent">-</span>
228
+ <span class="goal-separator">/</span>
229
+ <span class="goal-target" id="goalCharsTarget">-</span>
230
+ </div>
223
231
  </div>
224
- <div class="goal-progress-values">
225
- <span class="goal-current" id="goalCharsCurrent">-</span>
226
- <span class="goal-separator">/</span>
227
- <span class="goal-target" id="goalCharsTarget">-</span>
232
+ <div class="goal-progress-bar">
233
+ <div class="goal-progress-fill" id="goalCharsProgress" data-percentage="0"></div>
234
+ </div>
235
+ <div class="goal-progress-info">
236
+ <span class="goal-percentage" id="goalCharsPercentage">0%</span>
237
+ <span class="goal-projection" id="goalCharsProjection">-</span>
228
238
  </div>
229
239
  </div>
230
- <div class="goal-progress-bar">
231
- <div class="goal-progress-fill" id="goalCharsProgress" data-percentage="0"></div>
232
- </div>
233
- <div class="goal-progress-info">
234
- <span class="goal-percentage" id="goalCharsPercentage">0%</span>
235
- <span class="goal-projection" id="goalCharsProjection">-</span>
236
- </div>
237
- </div>
238
240
 
239
- <!-- Games Goal -->
240
- <div class="goal-progress-item">
241
- <div class="goal-progress-header">
242
- <div class="goal-progress-label">
243
- <span class="goal-icon">🎮</span>
244
- Games
241
+ <!-- Games Goal -->
242
+ <div class="goal-progress-item">
243
+ <div class="goal-progress-header">
244
+ <div class="goal-progress-label">
245
+ <span class="goal-icon">🎮</span>
246
+ Games
247
+ </div>
248
+ <div class="goal-progress-values">
249
+ <span class="goal-current" id="goalGamesCurrent">-</span>
250
+ <span class="goal-separator">/</span>
251
+ <span class="goal-target" id="goalGamesTarget">-</span>
252
+ </div>
245
253
  </div>
246
- <div class="goal-progress-values">
247
- <span class="goal-current" id="goalGamesCurrent">-</span>
248
- <span class="goal-separator">/</span>
249
- <span class="goal-target" id="goalGamesTarget">-</span>
254
+ <div class="goal-progress-bar">
255
+ <div class="goal-progress-fill" id="goalGamesProgress" data-percentage="0"></div>
256
+ </div>
257
+ <div class="goal-progress-info">
258
+ <span class="goal-percentage" id="goalGamesPercentage">0%</span>
259
+ <span class="goal-projection" id="goalGamesProjection">-</span>
250
260
  </div>
251
- </div>
252
- <div class="goal-progress-bar">
253
- <div class="goal-progress-fill" id="goalGamesProgress" data-percentage="0"></div>
254
- </div>
255
- <div class="goal-progress-info">
256
- <span class="goal-percentage" id="goalGamesPercentage">0%</span>
257
- <span class="goal-projection" id="goalGamesProjection">-</span>
258
261
  </div>
259
262
  </div>
260
- </div>
261
263
 
262
- <!-- Loading/Error states -->
263
- <div class="goal-progress-loading" id="goalProgressLoading" style="display: none;">
264
- <div class="spinner"></div>
265
- <span>Loading goal progress...</span>
266
- </div>
264
+ <!-- Loading/Error states -->
265
+ <div class="goal-progress-loading" id="goalProgressLoading" style="display: none;">
266
+ <div class="spinner"></div>
267
+ <span>Loading goal progress...</span>
268
+ </div>
267
269
 
268
- <div class="goal-progress-error" id="goalProgressError" style="display: none;">
269
- <div class="goal-progress-error-icon">⚠️</div>
270
- <div class="goal-progress-error-message">Failed to load goal progress</div>
271
- <button class="retry-btn" onclick="loadGoalProgress()">Retry</button>
270
+ <div class="goal-progress-error" id="goalProgressError" style="display: none;">
271
+ <div class="goal-progress-error-icon">⚠️</div>
272
+ <div class="goal-progress-error-message">Failed to load goal progress</div>
273
+ <button class="retry-btn" onclick="loadGoalProgress()">Retry</button>
274
+ </div>
272
275
  </div>
273
- </div>
274
-
275
- <div class="chart-container">
276
- <h2>Activity Heatmap</h2>
277
- <div id="heatmapContainer"></div>
278
- </div>
279
-
280
- <div class="chart-container">
281
- <h2>Lines Received Over Time</h2>
282
- <canvas id="linesChart"></canvas>
283
- </div>
284
276
 
285
- <div class="chart-container">
286
- <h2>Characters Read Over Time</h2>
287
- <canvas id="charsChart"></canvas>
288
- </div>
277
+ <div class="chart-container">
278
+ <h2>Activity Heatmap</h2>
279
+ <div id="heatmapContainer"></div>
280
+ </div>
289
281
 
290
- <div class="chart-container">
291
- <h2>Reading Chars Quantity</h2>
292
- <canvas id="readingCharsChart"></canvas>
293
- </div>
282
+ <div class="chart-container">
283
+ <h2>Lines Received Over Time</h2>
284
+ <canvas id="linesChart"></canvas>
285
+ </div>
294
286
 
295
- <div class="chart-container">
296
- <h2>Reading Time Quantity</h2>
297
- <canvas id="readingTimeChart"></canvas>
298
- </div>
287
+ <div class="chart-container">
288
+ <h2>Characters Read Over Time</h2>
289
+ <canvas id="charsChart"></canvas>
290
+ </div>
299
291
 
300
- <div class="chart-container">
301
- <h2>Reading Speed Improvement</h2>
302
- <canvas id="readingSpeedPerGameChart"></canvas>
303
- </div>
292
+ <div class="chart-container">
293
+ <h2>Reading Chars Quantity</h2>
294
+ <canvas id="readingCharsChart"></canvas>
295
+ </div>
304
296
 
305
- <div class="chart-container">
306
- <h2>Kanji Grid</h2>
307
- <div id="kanjiGridContainer">
308
- <div id="kanjiCounter" class="kanji-counter">
309
- Unique Kanji Seen: <span id="kanjiCount">0</span>
310
- </div>
311
- <div id="kanjiGrid" class="kanji-grid"></div>
312
- <div class="kanji-legend">
313
- <span>Rarely Seen</span>
314
- <div class="kanji-legend-item" style="background-color: #ebedf0;" title="No encounters"></div>
315
- <div class="kanji-legend-item" style="background-color: #e6342e;" title="Seen once"></div>
316
- <div class="kanji-legend-item" style="background-color: #e6dc2e;" title="Occasionally seen"></div>
317
- <div class="kanji-legend-item" style="background-color: #3be62f;" title="Frequently seen"></div>
318
- <div class="kanji-legend-item" style="background-color: #2ee6e0;" title="Most frequently seen"></div>
319
- <span>Frequently Seen</span>
320
- </div>
297
+ <div class="chart-container">
298
+ <h2>Reading Time Quantity</h2>
299
+ <canvas id="readingTimeChart"></canvas>
321
300
  </div>
322
- </div>
323
301
 
324
- <!-- Settings Modal -->
325
- <div id="settingsModal" class="modal">
326
- <div class="modal-content">
327
- <div class="modal-header">
328
- <h3>Statistics Settings</h3>
329
- <span class="close-btn" id="closeSettingsModal">&times;</span>
330
- </div>
331
- <div class="modal-body">
332
- <p style="color: var(--text-secondary); margin-bottom: 20px;">
333
- Configure how reading time and sessions are calculated for your statistics.
334
- </p>
335
-
336
- <form id="settingsForm">
337
- <div style="margin-bottom: 20px;">
338
- <label for="afkTimer" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
339
- AFK Timer (seconds)
340
- </label>
341
- <input
342
- type="number"
343
- id="afkTimer"
344
- name="afk_timer_seconds"
345
- style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
346
- placeholder="120"
347
- >
348
- <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
349
- Maximum time between activities that still counts as active reading
350
- </small>
351
- </div>
352
-
353
- <div style="margin-bottom: 20px;">
354
- <label for="sessionGap" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
355
- Session Gap (seconds)
356
- </label>
357
- <input
358
- type="number"
359
- id="sessionGap"
360
- name="session_gap_seconds"
361
- style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
362
- placeholder="3600"
363
- >
364
- <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
365
- Time gap that triggers a new reading session
366
- </small>
367
- </div>
302
+ <div class="chart-container">
303
+ <h2>Reading Speed Improvement</h2>
304
+ <canvas id="readingSpeedPerGameChart"></canvas>
305
+ </div>
368
306
 
369
- <div style="margin-bottom: 20px;">
370
- <label for="heatmapYear" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
371
- Heatmap Display Year
372
- </label>
373
- <select
374
- id="heatmapYear"
375
- name="heatmap_year"
376
- style="width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
377
- >
378
- <option value="all">All Years</option>
379
- </select>
380
- <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
381
- Select which year to display in the reading activity heatmap
382
- </small>
307
+ <div class="chart-container">
308
+ <h2>Kanji Grid</h2>
309
+ <div id="kanjiGridContainer">
310
+ <div id="kanjiCounter" class="kanji-counter">
311
+ Unique Kanji Seen: <span id="kanjiCount">0</span>
312
+ </div>
313
+ <div id="kanjiGrid" class="kanji-grid"></div>
314
+ <div class="kanji-legend">
315
+ <span>Rarely Seen</span>
316
+ <div class="kanji-legend-item" style="background-color: #ebedf0;" title="No encounters"></div>
317
+ <div class="kanji-legend-item" style="background-color: #e6342e;" title="Seen once"></div>
318
+ <div class="kanji-legend-item" style="background-color: #e6dc2e;" title="Occasionally seen"></div>
319
+ <div class="kanji-legend-item" style="background-color: #3be62f;" title="Frequently seen"></div>
320
+ <div class="kanji-legend-item" style="background-color: #2ee6e0;" title="Most frequently seen">
383
321
  </div>
322
+ <span>Frequently Seen</span>
323
+ </div>
324
+ </div>
325
+ </div>
384
326
 
385
- <div style="margin-bottom: 20px;">
386
- <label for="streakRequirement" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
387
- Streak Requirement (hours)
388
- </label>
389
- <input
390
- type="number"
391
- id="streakRequirement"
392
- name="streak_requirement_hours"
393
- min="0.01"
394
- max="24"
395
- step="0.01"
396
- style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
397
- placeholder="1.0"
398
- >
399
- <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
400
- Minimum hours of reading activity required to maintain streak (0.01-24 hours)
401
- </small>
402
- </div>
327
+ <!-- Settings Modal -->
328
+ <div id="settingsModal" class="modal">
329
+ <div class="modal-content">
330
+ <div class="modal-header">
331
+ <h3>Statistics Settings</h3>
332
+ <span class="close-btn" id="closeSettingsModal">&times;</span>
333
+ </div>
334
+ <div class="modal-body">
335
+ <p style="color: var(--text-secondary); margin-bottom: 20px;">
336
+ Configure how reading time and sessions are calculated for your statistics.
337
+ </p>
338
+ <form id="settingsForm">
339
+ <!-- <div style="margin-bottom: 20px;">
340
+ <label for="timezone-select"
341
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
342
+ Timezone
343
+ </label>
344
+ <div style="display: flex; gap: 8px;">
345
+ <select id="timezone-select" name="timezone"
346
+ style="flex-grow: 1; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;">
347
+ </select>
348
+ <button id="set-local-timezone-btn"
349
+ style="padding: 10px; border: none; border-radius: 5px; background: var(--primary-color); color: white; font-size: 14px; cursor: pointer;">
350
+ Set to Local
351
+ </button>
352
+ </div>
353
+ <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
354
+ Select the timezone to base your statistics on
355
+ </small>
356
+ </div> -->
403
357
 
404
- <!-- Reading Goals Section -->
405
- <div style="margin-bottom: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
406
- <label style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
407
- Reading Goals Configuration
408
- </label>
409
- <p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 14px;">
410
- Set your long-term reading targets for tracking progress and projections.
411
- </p>
412
-
413
- <div style="margin-bottom: 15px;">
414
- <label for="readingHoursTarget" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
415
- Reading Hours Target
358
+ <div style="margin-bottom: 20px;">
359
+ <label for="afkTimer"
360
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
361
+ AFK Timer (seconds)
416
362
  </label>
417
- <input
418
- type="number"
419
- id="readingHoursTarget"
420
- name="reading_hours_target"
421
- min="1"
422
- max="10000"
363
+ <input type="number" id="afkTimer" name="afk_timer_seconds"
423
364
  style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
424
- placeholder="1500"
425
- >
426
- <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
427
- Total reading hours goal (1-10,000 hours) - Default: 1500 hours based on TMW N1 achievement
365
+ placeholder="120">
366
+ <small
367
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
368
+ Maximum time between activities that still counts as active reading
428
369
  </small>
429
370
  </div>
430
-
431
- <div style="margin-bottom: 15px;">
432
- <label for="characterCountTarget" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
433
- Character Count Target
371
+
372
+ <div style="margin-bottom: 20px;">
373
+ <label for="sessionGap"
374
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
375
+ Session Gap (seconds)
434
376
  </label>
435
- <input
436
- type="number"
437
- id="characterCountTarget"
438
- name="character_count_target"
439
- min="1000"
440
- max="1000000000"
377
+ <input type="number" id="sessionGap" name="session_gap_seconds"
441
378
  style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
442
- placeholder="25000000"
443
- >
444
- <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
445
- Total characters read goal (1,000-1,000,000,000) - Default: 25 million characters
379
+ placeholder="3600">
380
+ <small
381
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
382
+ Time gap that triggers a new reading session
446
383
  </small>
447
384
  </div>
448
-
449
- <div style="margin-bottom: 15px;">
450
- <label for="gamesTarget" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
451
- Games/Visual Novels Target
385
+
386
+ <div style="margin-bottom: 20px;">
387
+ <label for="heatmapYear"
388
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
389
+ Heatmap Display Year
452
390
  </label>
453
- <input
454
- type="number"
455
- id="gamesTarget"
456
- name="games_target"
457
- min="1"
458
- max="1000"
459
- style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
460
- placeholder="100"
461
- >
462
- <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
463
- Number of games/visual novels to complete (1-1,000) - Default: 100 based on Refold standards
391
+ <select id="heatmapYear" name="heatmap_year"
392
+ style="width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;">
393
+ <option value="all">All Years</option>
394
+ </select>
395
+ <small
396
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
397
+ Select which year to display in the reading activity heatmap
464
398
  </small>
465
399
  </div>
466
- </div>
467
400
 
468
- <!-- Import ExStatic Lines Section -->
469
- <div style="margin-bottom: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
470
- <label style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
471
- Import ExStatic Lines
472
- </label>
473
- <div style="margin-bottom: 10px;">
474
- <input
475
- type="file"
476
- id="exstaticFile"
477
- accept=".csv"
401
+ <div style="margin-bottom: 20px;">
402
+ <label for="streakRequirement"
403
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
404
+ Streak Requirement (hours)
405
+ </label>
406
+ <input type="number" id="streakRequirement" name="streak_requirement_hours" min="0.01"
407
+ max="24" step="0.01"
478
408
  style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
479
- >
480
- <small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
481
- Select an ExStatic CSV file to import reading data into GSM
409
+ placeholder="1.0">
410
+ <small
411
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
412
+ Minimum hours of reading activity required to maintain streak (0.01-24 hours)
482
413
  </small>
483
414
  </div>
484
- <button
485
- type="button"
486
- id="importExstaticBtn"
487
- style="width: 90%; padding: 10px; background: #666; color: white; border: none; border-radius: 5px; font-size: 14px; cursor: not-allowed; margin-bottom: 10px;"
488
- disabled
489
- >
490
- Import ExStatic Lines
491
- </button>
492
- <div id="importProgress" style="display: none; margin-bottom: 10px;">
493
- <div style="background: var(--bg-tertiary); border-radius: 5px; overflow: hidden; height: 20px; position: relative;">
494
- <div id="importProgressBar" style="background: var(--primary-color); height: 100%; width: 0%; transition: width 0.3s ease;"></div>
495
- <span id="importProgressText" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 12px; color: var(--text-primary);">0%</span>
415
+
416
+ <!-- Reading Goals Section -->
417
+ <div style="margin-bottom: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
418
+ <label
419
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
420
+ Reading Goals Configuration
421
+ </label>
422
+ <p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 14px;">
423
+ Set your long-term reading targets for tracking progress and projections.
424
+ </p>
425
+
426
+ <div style="margin-bottom: 15px;">
427
+ <label for="readingHoursTarget"
428
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
429
+ Reading Hours Target
430
+ </label>
431
+ <input type="number" id="readingHoursTarget" name="reading_hours_target" min="1"
432
+ max="10000"
433
+ style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
434
+ placeholder="1500">
435
+ <small
436
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
437
+ Total reading hours goal (1-10,000 hours) - Default: 1500 hours based on TMW N1
438
+ achievement
439
+ </small>
440
+ </div>
441
+
442
+ <div style="margin-bottom: 15px;">
443
+ <label for="characterCountTarget"
444
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
445
+ Character Count Target
446
+ </label>
447
+ <input type="number" id="characterCountTarget" name="character_count_target" min="1000"
448
+ max="1000000000"
449
+ style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
450
+ placeholder="25000000">
451
+ <small
452
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
453
+ Total characters read goal (1,000-1,000,000,000) - Default: 25 million characters
454
+ </small>
496
455
  </div>
456
+
457
+ <div style="margin-bottom: 15px;">
458
+ <label for="gamesTarget"
459
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
460
+ Games/Visual Novels Target
461
+ </label>
462
+ <input type="number" id="gamesTarget" name="games_target" min="1" max="1000"
463
+ style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
464
+ placeholder="100">
465
+ <small
466
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
467
+ Number of games/visual novels to complete (1-1,000) - Default: 100 based on Refold
468
+ standards
469
+ </small>
470
+ </div>
471
+ </div>
472
+
473
+ <!-- Import ExStatic Lines Section -->
474
+ <div style="margin-bottom: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
475
+ <label
476
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
477
+ Import ExStatic Lines
478
+ </label>
479
+ <div style="margin-bottom: 10px;">
480
+ <input type="file" id="exstaticFile" accept=".csv"
481
+ style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;">
482
+ <small
483
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
484
+ Select an ExStatic CSV file to import reading data into GSM
485
+ </small>
486
+ </div>
487
+ <button type="button" id="importExstaticBtn"
488
+ style="width: 90%; padding: 10px; background: #666; color: white; border: none; border-radius: 5px; font-size: 14px; cursor: not-allowed; margin-bottom: 10px;"
489
+ disabled>
490
+ Import ExStatic Lines
491
+ </button>
492
+ <div id="importProgress" style="display: none; margin-bottom: 10px;">
493
+ <div
494
+ style="background: var(--bg-tertiary); border-radius: 5px; overflow: hidden; height: 20px; position: relative;">
495
+ <div id="importProgressBar"
496
+ style="background: var(--primary-color); height: 100%; width: 0%; transition: width 0.3s ease;">
497
+ </div>
498
+ <span id="importProgressText"
499
+ style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 12px; color: var(--text-primary);">0%</span>
500
+ </div>
501
+ </div>
502
+ <div id="importStatus"
503
+ style="display: none; padding: 10px; border-radius: 5px; font-size: 14px;"></div>
497
504
  </div>
498
- <div id="importStatus" style="display: none; padding: 10px; border-radius: 5px; font-size: 14px;"></div>
505
+ </form>
506
+
507
+ <div id="settingsError"
508
+ style="display: none; background: var(--danger-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;">
499
509
  </div>
500
- </form>
501
-
502
- <div id="settingsError" style="display: none; background: var(--danger-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;"></div>
503
- <div id="settingsSuccess" style="display: none; background: var(--success-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;"></div>
504
- </div>
505
- <div class="modal-footer">
506
- <button id="cancelSettingsBtn" class="cancel-btn">Cancel</button>
507
- <button id="saveSettingsBtn" class="confirm-delete-btn">Save Settings</button>
510
+ <div id="settingsSuccess"
511
+ style="display: none; background: var(--success-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;">
512
+ </div>
513
+ </div>
514
+ <div class="modal-footer">
515
+ <button id="cancelSettingsBtn" class="cancel-btn">Cancel</button>
516
+ <button id="saveSettingsBtn" class="confirm-delete-btn">Save Settings</button>
517
+ </div>
508
518
  </div>
509
519
  </div>
510
520
  </div>
511
- </div>
512
521
 
513
522
 
514
- <!-- Include shared JavaScript first (required dependency for stats.js) -->
515
- <script src="/static/js/shared.js"></script>
516
- <script src="/static/js/kanji-grid.js"></script>
517
- <script src="/static/js/stats.js"></script>
523
+ <!-- Include shared JavaScript first (required dependency for stats.js) -->
524
+ <script src="/static/js/shared.js"></script>
525
+ <script src="/static/js/kanji-grid.js"></script>
526
+ <script src="/static/js/stats.js"></script>
527
+ <!-- <script>
528
+ document.addEventListener('DOMContentLoaded', () => {
529
+ const timezoneSelect = document.getElementById('timezone-select');
530
+ const setLocalTimezoneBtn = document.getElementById('set-local-timezone-btn');
531
+
532
+ function populateTimezoneSelect() {
533
+ const timezones = Intl.supportedValuesOf('timeZone');
534
+ const fragment = document.createDocumentFragment();
535
+
536
+ timezones.forEach(tz => {
537
+ const option = document.createElement('option');
538
+ option.value = tz;
539
+ option.textContent = tz.replace(/_/g, ' '); // Improve readability
540
+ fragment.appendChild(option);
541
+ });
542
+
543
+ timezoneSelect.appendChild(fragment);
544
+ }
545
+
546
+ function setLocalTimezone() {
547
+ const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
548
+ timezoneSelect.value = localTimezone;
549
+ }
550
+
551
+ populateTimezoneSelect();
552
+ setLocalTimezone();
553
+
554
+ setLocalTimezoneBtn.addEventListener('click', () => {
555
+ setLocalTimezone();
556
+ });
557
+ });
558
+ </script> -->
518
559
 
519
560
  </body>
561
+
520
562
  </html>