GameSentenceMiner 2.17.7__py3-none-any.whl → 2.18.1__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.

Files changed (76) hide show
  1. GameSentenceMiner/ai/ai_prompting.py +6 -6
  2. GameSentenceMiner/anki.py +236 -152
  3. GameSentenceMiner/gametext.py +7 -4
  4. GameSentenceMiner/gsm.py +49 -10
  5. GameSentenceMiner/locales/en_us.json +7 -3
  6. GameSentenceMiner/locales/ja_jp.json +8 -4
  7. GameSentenceMiner/locales/zh_cn.json +8 -4
  8. GameSentenceMiner/obs.py +238 -59
  9. GameSentenceMiner/ocr/owocr_helper.py +1 -1
  10. GameSentenceMiner/tools/ss_selector.py +7 -8
  11. GameSentenceMiner/ui/__init__.py +0 -0
  12. GameSentenceMiner/ui/anki_confirmation.py +187 -0
  13. GameSentenceMiner/{config_gui.py → ui/config_gui.py} +100 -35
  14. GameSentenceMiner/ui/screenshot_selector.py +215 -0
  15. GameSentenceMiner/util/configuration.py +124 -22
  16. GameSentenceMiner/util/db.py +22 -13
  17. GameSentenceMiner/util/downloader/download_tools.py +2 -2
  18. GameSentenceMiner/util/ffmpeg.py +24 -30
  19. GameSentenceMiner/util/get_overlay_coords.py +34 -34
  20. GameSentenceMiner/util/gsm_utils.py +31 -1
  21. GameSentenceMiner/util/text_log.py +11 -9
  22. GameSentenceMiner/vad.py +31 -12
  23. GameSentenceMiner/web/database_api.py +742 -123
  24. GameSentenceMiner/web/static/css/dashboard-shared.css +241 -0
  25. GameSentenceMiner/web/static/css/kanji-grid.css +94 -2
  26. GameSentenceMiner/web/static/css/overview.css +850 -0
  27. GameSentenceMiner/web/static/css/popups-shared.css +126 -0
  28. GameSentenceMiner/web/static/css/shared.css +97 -0
  29. GameSentenceMiner/web/static/css/stats.css +192 -597
  30. GameSentenceMiner/web/static/js/anki_stats.js +6 -4
  31. GameSentenceMiner/web/static/js/database.js +209 -5
  32. GameSentenceMiner/web/static/js/goals.js +610 -0
  33. GameSentenceMiner/web/static/js/kanji-grid.js +267 -4
  34. GameSentenceMiner/web/static/js/overview.js +1176 -0
  35. GameSentenceMiner/web/static/js/shared.js +25 -0
  36. GameSentenceMiner/web/static/js/stats.js +154 -1459
  37. GameSentenceMiner/web/stats.py +2 -2
  38. GameSentenceMiner/web/templates/anki_stats.html +5 -0
  39. GameSentenceMiner/web/templates/components/kanji_grid/basic_kanji_book_bkb_v1_v2.json +17 -0
  40. GameSentenceMiner/web/templates/components/kanji_grid/duolingo_kanji.json +29 -0
  41. GameSentenceMiner/web/templates/components/kanji_grid/grade.json +17 -0
  42. GameSentenceMiner/web/templates/components/kanji_grid/hk_primary_learning.json +17 -0
  43. GameSentenceMiner/web/templates/components/kanji_grid/hkscs2016.json +13 -0
  44. GameSentenceMiner/web/templates/components/kanji_grid/hsk_levels.json +33 -0
  45. GameSentenceMiner/web/templates/components/kanji_grid/humanum_frequency_list.json +41 -0
  46. GameSentenceMiner/web/templates/components/kanji_grid/jis_levels.json +25 -0
  47. GameSentenceMiner/web/templates/components/kanji_grid/jlpt_level.json +29 -0
  48. GameSentenceMiner/web/templates/components/kanji_grid/jpdb_kanji_frequency_list.json +37 -0
  49. GameSentenceMiner/web/templates/components/kanji_grid/jpdbv2_kanji_frequency_list.json +161 -0
  50. GameSentenceMiner/web/templates/components/kanji_grid/jun_das_modern_chinese_character_frequency_list.json +13 -0
  51. GameSentenceMiner/web/templates/components/kanji_grid/kanji_in_context_revised_edition.json +37 -0
  52. GameSentenceMiner/web/templates/components/kanji_grid/kanji_kentei_level.json +61 -0
  53. GameSentenceMiner/web/templates/components/kanji_grid/mainland_china_elementary_textbook_characters.json +33 -0
  54. GameSentenceMiner/web/templates/components/kanji_grid/moe_way_quiz.json +47 -0
  55. GameSentenceMiner/web/templates/components/kanji_grid/official_kanji.json +25 -0
  56. GameSentenceMiner/web/templates/components/kanji_grid/remembering_the_kanji.json +25 -0
  57. GameSentenceMiner/web/templates/components/kanji_grid/standard_form_of_national_characters.json +25 -0
  58. GameSentenceMiner/web/templates/components/kanji_grid/table_of_general_standard_chinese_characters.json +21 -0
  59. GameSentenceMiner/web/templates/components/kanji_grid/the_kodansha_kanji_learners_course_klc.json +45 -0
  60. GameSentenceMiner/web/templates/components/kanji_grid/thousand_character_classic.json +13 -0
  61. GameSentenceMiner/web/templates/components/kanji_grid/wanikani_levels.json +249 -0
  62. GameSentenceMiner/web/templates/components/kanji_grid/words_hk_frequency_list.json +33 -0
  63. GameSentenceMiner/web/templates/components/navigation.html +3 -1
  64. GameSentenceMiner/web/templates/database.html +73 -1
  65. GameSentenceMiner/web/templates/goals.html +376 -0
  66. GameSentenceMiner/web/templates/index.html +13 -11
  67. GameSentenceMiner/web/templates/overview.html +416 -0
  68. GameSentenceMiner/web/templates/stats.html +46 -251
  69. GameSentenceMiner/web/texthooking_page.py +18 -0
  70. {gamesentenceminer-2.17.7.dist-info → gamesentenceminer-2.18.1.dist-info}/METADATA +5 -1
  71. gamesentenceminer-2.18.1.dist-info/RECORD +132 -0
  72. gamesentenceminer-2.17.7.dist-info/RECORD +0 -98
  73. {gamesentenceminer-2.17.7.dist-info → gamesentenceminer-2.18.1.dist-info}/WHEEL +0 -0
  74. {gamesentenceminer-2.17.7.dist-info → gamesentenceminer-2.18.1.dist-info}/entry_points.txt +0 -0
  75. {gamesentenceminer-2.17.7.dist-info → gamesentenceminer-2.18.1.dist-info}/licenses/LICENSE +0 -0
  76. {gamesentenceminer-2.17.7.dist-info → gamesentenceminer-2.18.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,416 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>GSM Overview</title>
8
+ <!-- Include Chart.js from a CDN -->
9
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
10
+
11
+ <!-- Include html2canvas for screenshot functionality -->
12
+ <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
13
+
14
+ <!-- Include shared theme styles -->
15
+ {% include 'components/theme-styles.html' %}
16
+
17
+ <!-- Include shared CSS -->
18
+ <link rel="stylesheet" href="/static/css/shared.css">
19
+
20
+ <!-- Include shared dashboard and popup CSS -->
21
+ <link rel="stylesheet" href="/static/css/dashboard-shared.css">
22
+ <link rel="stylesheet" href="/static/css/popups-shared.css">
23
+
24
+ <!-- Include overview-specific CSS -->
25
+ <link rel="stylesheet" href="/static/css/overview.css">
26
+ </head>
27
+
28
+ <body>
29
+
30
+ <div class="container">
31
+ <h1>GSM - Overview</h1>
32
+
33
+ <!-- Include shared navigation -->
34
+ {% include 'components/navigation.html' %}
35
+
36
+ <div class="dashboard-card date-range">
37
+ <div class="dashboard-card-header">
38
+ <h3 class="dashboard-card-title">
39
+ <span class="dashboard-card-icon">📅</span>
40
+ Date Range
41
+ </h3>
42
+ </div>
43
+
44
+ <div class="dashboard-date-range">
45
+ <div class="dashboard-date-item tooltip" data-tooltip="Select the start date for your stats">
46
+ <label for="fromDate">From</label>
47
+ <input type="date" id="fromDate" class="dashboard-date-input">
48
+ </div>
49
+ <div class="dashboard-date-item tooltip" data-tooltip="Select the end date for your stats">
50
+ <label for="toDate">To</label>
51
+ <input type="date" id="toDate" class="dashboard-date-input">
52
+ </div>
53
+ </div>
54
+ </div>
55
+
56
+ <div id="dateErrorPopup" class="dashboard-popup hidden">
57
+ <div class="dashboard-popup-content">
58
+ <div class="dashboard-popup-icon">⚠️</div>
59
+ <div class="dashboard-popup-message">"From" date cannot be later than "To" date.</div>
60
+ <button id="closePopupBtn" class="dashboard-popup-btn">OK</button>
61
+ </div>
62
+ </div>
63
+
64
+ <div id="noDataPopup" class="no-data-popup hidden">
65
+ <div class="no-data-content">
66
+ <p>No data found for the selected range.</p>
67
+ <button id="closeNoDataPopup">OK</button>
68
+ </div>
69
+ </div>
70
+
71
+ <!-- Dashboard Statistics Sections -->
72
+ <div class="dashboard-container">
73
+ <!-- Current Game Statistics Panel -->
74
+ <div class="dashboard-card current-game" id="currentGameCard">
75
+ <div class="dashboard-card-header">
76
+ <div>
77
+ <h3 class="dashboard-card-title">
78
+ <span class="dashboard-card-icon">🎮</span>
79
+ Current Game Statistics
80
+ </h3>
81
+ <p class="dashboard-card-subtitle" id="currentGameName">Loading...</p>
82
+ </div>
83
+ <div class="dashboard-streak-indicator" id="currentGameStreak" style="display: none;">
84
+ <span id="currentStreakValue">0</span> day streak
85
+ </div>
86
+ </div>
87
+
88
+ <div class="dashboard-stats-grid" id="currentGameStats">
89
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read in this game">
90
+ <span class="dashboard-stat-value" id="currentTotalChars">-</span>
91
+ <span class="dashboard-stat-label">Characters</span>
92
+ </div>
93
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading this game">
94
+ <span class="dashboard-stat-value" id="currentTotalTime">-</span>
95
+ <span class="dashboard-stat-label">Time Spent</span>
96
+ </div>
97
+ <div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed for this game">
98
+ <span class="dashboard-stat-value" id="currentReadingSpeed">-</span>
99
+ <span class="dashboard-stat-label">Chars/Hour</span>
100
+ </div>
101
+ <div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions for this game">
102
+ <span class="dashboard-stat-value" id="currentSessions">-</span>
103
+ <span class="dashboard-stat-label">Sessions</span>
104
+ </div>
105
+ </div>
106
+
107
+ <div class="dashboard-progress-section">
108
+ <div class="dashboard-progress-title">Recent Progress</div>
109
+ <div class="dashboard-progress-items">
110
+ <div class="dashboard-progress-item">
111
+ <div class="dashboard-progress-value positive" id="currentMonthlyChars">-</div>
112
+ <div class="dashboard-progress-label">Monthly Characters</div>
113
+ </div>
114
+ <div class="dashboard-progress-item">
115
+ <div class="dashboard-progress-value neutral" id="currentFirstDate">-</div>
116
+ <div class="dashboard-progress-label">Started</div>
117
+ </div>
118
+ <div class="dashboard-progress-item">
119
+ <div class="dashboard-progress-value neutral" id="currentLastDate">-</div>
120
+ <div class="dashboard-progress-label">Last Activity</div>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </div>
125
+
126
+ <!-- All Games Historical Overview -->
127
+ <div class="dashboard-card all-games" id="allGamesCard">
128
+ <div class="dashboard-card-header">
129
+ <div>
130
+ <h3 class="dashboard-card-title">
131
+ <span class="dashboard-card-icon">📚</span>
132
+ All Games Overview
133
+ </h3>
134
+ <p class="dashboard-card-subtitle" id="totalGamesCount">Loading...</p>
135
+ </div>
136
+ <div class="dashboard-streak-indicator" id="allGamesStreak" style="display: none;">
137
+ <span id="allStreakValue">0</span> day streak
138
+ </div>
139
+ </div>
140
+
141
+ <div class="dashboard-stats-grid" id="allGamesStats">
142
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read across all games">
143
+ <span class="dashboard-stat-value" id="allTotalChars">-</span>
144
+ <span class="dashboard-stat-label">Characters</span>
145
+ </div>
146
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading across all games">
147
+ <span class="dashboard-stat-value" id="allTotalTime">-</span>
148
+ <span class="dashboard-stat-label">Time Spent</span>
149
+ </div>
150
+ <div class="dashboard-stat-item tooltip" data-tooltip="Overall average reading speed">
151
+ <span class="dashboard-stat-value" id="allReadingSpeed">-</span>
152
+ <span class="dashboard-stat-label">Chars/Hour</span>
153
+ </div>
154
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total number of reading sessions">
155
+ <span class="dashboard-stat-value" id="allSessions">-</span>
156
+ <span class="dashboard-stat-label">Sessions</span>
157
+ </div>
158
+ </div>
159
+
160
+ <div class="dashboard-progress-section">
161
+ <div class="dashboard-progress-title">Overall Progress</div>
162
+ <div class="dashboard-progress-items">
163
+ <div class="dashboard-progress-item">
164
+ <div class="dashboard-progress-value positive" id="allMonthlyChars">-</div>
165
+ <div class="dashboard-progress-label">Monthly Characters</div>
166
+ </div>
167
+ <div class="dashboard-progress-item">
168
+ <div class="dashboard-progress-value neutral" id="allUniqueGames">-</div>
169
+ <div class="dashboard-progress-label">Games Played</div>
170
+ </div>
171
+ <div class="dashboard-progress-item">
172
+ <div class="dashboard-progress-value neutral" id="allTotalSentences">-</div>
173
+ <div class="dashboard-progress-label">Total Sentences</div>
174
+ </div>
175
+ </div>
176
+ </div>
177
+ </div>
178
+ </div>
179
+
180
+ <!-- Loading/Error states for dashboard -->
181
+ <div class="dashboard-loading" id="dashboardLoading" style="display: none;">
182
+ <div class="spinner"></div>
183
+ <span>Loading dashboard statistics...</span>
184
+ </div>
185
+
186
+ <div class="dashboard-error" id="dashboardError" style="display: none;">
187
+ <div class="dashboard-error-icon">⚠️</div>
188
+ <div class="dashboard-error-message">Failed to load dashboard statistics</div>
189
+ <button class="dashboard-retry-btn" data-action="loadDashboardData">Retry</button>
190
+ </div>
191
+
192
+
193
+ <!-- Today's Overview Card -->
194
+ <div class="dashboard-card today-overview" id="todayOverviewCard" style="margin-bottom: 24px;">
195
+ <div class="dashboard-card-header">
196
+ <h3 class="dashboard-card-title">
197
+ <span class="dashboard-card-icon">📅</span>
198
+ Today's Overview
199
+ </h3>
200
+ <p class="dashboard-card-subtitle" id="todayDate">Loading...</p>
201
+ </div>
202
+ <div class="dashboard-stats-grid" id="todayStats">
203
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total hours spent reading today">
204
+ <span class="dashboard-stat-value" id="todayTotalHours">-</span>
205
+ <span class="dashboard-stat-label">Hours Spent</span>
206
+ </div>
207
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read today">
208
+ <span class="dashboard-stat-value" id="todayTotalChars">-</span>
209
+ <span class="dashboard-stat-label">Characters</span>
210
+ </div>
211
+ <div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions today">
212
+ <span class="dashboard-stat-value" id="todaySessions">-</span>
213
+ <span class="dashboard-stat-label">Sessions</span>
214
+ </div>
215
+ <div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed today">
216
+ <span class="dashboard-stat-value" id="todayCharsPerHour">-</span>
217
+ <span class="dashboard-stat-label">Chars/Hour</span>
218
+ </div>
219
+ </div>
220
+ </div>
221
+
222
+ <div class="chart-container">
223
+ <h2>Activity Heatmap</h2>
224
+ <div id="heatmapContainer"></div>
225
+ </div>
226
+ <!-- Settings Modal -->
227
+ <div id="settingsModal" class="modal">
228
+ <div class="modal-content">
229
+ <div class="modal-header">
230
+ <h3>Statistics Settings</h3>
231
+ <span class="close-btn" id="closeSettingsModal">&times;</span>
232
+ </div>
233
+ <div class="modal-body">
234
+ <p style="color: var(--text-secondary); margin-bottom: 20px;">
235
+ Configure how reading time and sessions are calculated for your statistics.
236
+ </p>
237
+ <form id="settingsForm">
238
+ <div style="margin-bottom: 20px;">
239
+ <label for="afkTimer"
240
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
241
+ AFK Timer (seconds)
242
+ </label>
243
+ <input type="number" id="afkTimer" name="afk_timer_seconds"
244
+ style="padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
245
+ placeholder="120">
246
+ <small
247
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
248
+ Maximum time between activities that still counts as active reading
249
+ </small>
250
+ </div>
251
+
252
+ <div style="margin-bottom: 20px;">
253
+ <label for="sessionGap"
254
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
255
+ Session Gap (seconds)
256
+ </label>
257
+ <input type="number" id="sessionGap" name="session_gap_seconds"
258
+ style="padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
259
+ placeholder="3600">
260
+ <small
261
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
262
+ Time gap that triggers a new reading session
263
+ </small>
264
+ </div>
265
+
266
+ <div style="margin-bottom: 20px;">
267
+ <label for="streakRequirement"
268
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
269
+ Streak Requirement (hours)
270
+ </label>
271
+ <input type="number" id="streakRequirement" name="streak_requirement_hours" min="0.01"
272
+ max="24" step="0.01"
273
+ style="padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
274
+ placeholder="1.0">
275
+ <small
276
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
277
+ Minimum hours of reading activity required to maintain streak (0.01-24 hours)
278
+ </small>
279
+ </div>
280
+
281
+ <!-- Reading Goals Section -->
282
+ <div style="margin-bottom: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
283
+ <label
284
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
285
+ Reading Goals Configuration
286
+ </label>
287
+ <p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 14px;">
288
+ Set your long-term reading targets for tracking progress and projections.
289
+ </p>
290
+
291
+ <div style="margin-bottom: 15px;">
292
+ <label for="readingHoursTarget"
293
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
294
+ Reading Hours Target
295
+ </label>
296
+ <input type="number" id="readingHoursTarget" name="reading_hours_target" min="1"
297
+ max="10000"
298
+ style="padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
299
+ placeholder="1500">
300
+ <small
301
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
302
+ Total reading hours goal (1-10,000 hours) - Default: 1500 hours based on TMW N1
303
+ achievement
304
+ </small>
305
+ </div>
306
+
307
+ <div style="margin-bottom: 15px;">
308
+ <label for="characterCountTarget"
309
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
310
+ Character Count Target
311
+ </label>
312
+ <input type="number" id="characterCountTarget" name="character_count_target" min="1000"
313
+ max="1000000000"
314
+ style="padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
315
+ placeholder="25000000">
316
+ <small
317
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
318
+ Total characters read goal (1,000-1,000,000,000) - Default: 25 million characters
319
+ </small>
320
+ </div>
321
+
322
+ <div style="margin-bottom: 15px;">
323
+ <label for="gamesTarget"
324
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
325
+ Games/Visual Novels Target
326
+ </label>
327
+ <input type="number" id="gamesTarget" name="games_target" min="1" max="1000"
328
+ 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;"
329
+ placeholder="100">
330
+ <small
331
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
332
+ Number of games/visual novels to complete (1-1,000) - Default: 100 based on Refold
333
+ standards
334
+ </small>
335
+ </div>
336
+ </div>
337
+
338
+ <!-- Import ExStatic Lines Section -->
339
+ <div style="margin-bottom: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
340
+ <label
341
+ style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
342
+ Import ExStatic Lines
343
+ </label>
344
+ <div style="margin-bottom: 10px;">
345
+ <input type="file" id="exstaticFile" accept=".csv"
346
+ 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;">
347
+ <small
348
+ style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
349
+ Select an ExStatic CSV file to import reading data into GSM
350
+ </small>
351
+ </div>
352
+ <button type="button" id="importExstaticBtn"
353
+ style="width: 90%; padding: 10px; background: #666; color: white; border: none; border-radius: 5px; font-size: 14px; cursor: not-allowed; margin-bottom: 10px;"
354
+ disabled>
355
+ Import ExStatic Lines
356
+ </button>
357
+ <div id="importProgress" style="display: none; margin-bottom: 10px;">
358
+ <div
359
+ style="background: var(--bg-tertiary); border-radius: 5px; overflow: hidden; height: 20px; position: relative;">
360
+ <div id="importProgressBar"
361
+ style="background: var(--primary-color); height: 100%; width: 0%; transition: width 0.3s ease;">
362
+ </div>
363
+ <span id="importProgressText"
364
+ style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 12px; color: var(--text-primary);">0%</span>
365
+ </div>
366
+ </div>
367
+ <div id="importStatus"
368
+ style="display: none; padding: 10px; border-radius: 5px; font-size: 14px;"></div>
369
+ </div>
370
+ </form>
371
+
372
+ <div id="settingsError"
373
+ style="display: none; background: var(--danger-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;">
374
+ </div>
375
+ <div id="settingsSuccess"
376
+ style="display: none; background: var(--success-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;">
377
+ </div>
378
+ </div>
379
+ <div class="modal-footer">
380
+ <button id="cancelSettingsBtn" class="cancel-btn">Cancel</button>
381
+ <button id="saveSettingsBtn" class="confirm-delete-btn">Save Settings</button>
382
+ </div>
383
+ </div>
384
+ </div>
385
+ </div>
386
+
387
+
388
+ {% set afk_timer = stats_config.afk_timer_seconds | default(120) %}
389
+ {% set session_gap = stats_config.session_gap_seconds | default(3600) %}
390
+ {% set streak_req = config.advanced.streak_requirement_hours | default(1.0) %}
391
+ {% set hours_target = stats_config.reading_hours_target | default(1500) %}
392
+ {% set chars_target = stats_config.character_count_target | default(25000000) %}
393
+ {% set games_target = stats_config.games_target | default(100) %}
394
+ {% set heatmap_year = 'all' %}
395
+
396
+ {% set stats_config = {
397
+ 'afkTimerSeconds': afk_timer,
398
+ 'sessionGapSeconds': session_gap,
399
+ 'streakRequirementHours': streak_req,
400
+ 'readingHoursTarget': hours_target,
401
+ 'characterCountTarget': chars_target,
402
+ 'gamesTarget': games_target,
403
+ 'heatmapDisplayYear': heatmap_year
404
+ } %}
405
+
406
+ <!-- Inject stats config values for frontend -->
407
+ <script>
408
+ window.statsConfig = {{ stats_config | tojson }};
409
+ </script>
410
+ <!-- Include shared JavaScript first (required dependency for overview.js) -->
411
+ <script src="/static/js/shared.js"></script>
412
+ <script src="/static/js/overview.js"></script>
413
+
414
+ </body>
415
+
416
+ </html>