GameSentenceMiner 2.18.6__py3-none-any.whl → 2.18.7__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.
@@ -773,6 +773,49 @@ document.addEventListener('DOMContentLoaded', function () {
773
773
  fromDateInput.addEventListener("change", handleDateChange);
774
774
  toDateInput.addEventListener("change", handleDateChange);
775
775
 
776
+ // Session navigation button handlers
777
+ const prevSessionBtn = document.querySelector('.prev-session-btn');
778
+ const nextSessionBtn = document.querySelector('.next-session-btn');
779
+
780
+ function updateSessionNavigationButtons() {
781
+ if (!window.todaySessionDetails || window.todaySessionDetails.length === 0) {
782
+ prevSessionBtn.disabled = true;
783
+ nextSessionBtn.disabled = true;
784
+ return;
785
+ }
786
+ prevSessionBtn.disabled = window.currentSessionIndex <= 0;
787
+ nextSessionBtn.disabled = window.currentSessionIndex >= window.todaySessionDetails.length - 1;
788
+ }
789
+
790
+ function showSessionAtIndex(index) {
791
+ if (!window.todaySessionDetails || window.todaySessionDetails.length === 0) return;
792
+ if (index < 0 || index >= window.todaySessionDetails.length) return;
793
+ window.currentSessionIndex = index;
794
+ updateCurrentSessionOverview(window.todaySessionDetails, index);
795
+ updateSessionNavigationButtons();
796
+ }
797
+
798
+ prevSessionBtn.addEventListener('click', () => {
799
+ if (!window.todaySessionDetails) return;
800
+ let idx = window.currentSessionIndex || 0;
801
+ if (idx > 0) {
802
+ showSessionAtIndex(idx - 1);
803
+ }
804
+ });
805
+
806
+ nextSessionBtn.addEventListener('click', () => {
807
+ if (!window.todaySessionDetails) return;
808
+ let idx = window.currentSessionIndex || 0;
809
+ if (idx < window.todaySessionDetails.length - 1) {
810
+ showSessionAtIndex(idx + 1);
811
+ }
812
+ });
813
+
814
+ // Update navigation buttons whenever sessions are loaded
815
+ document.addEventListener('datesSet', () => {
816
+ setTimeout(updateSessionNavigationButtons, 1200);
817
+ });
818
+
776
819
  initializeDates();
777
820
 
778
821
  // Popup close button
@@ -821,6 +864,61 @@ document.addEventListener('DOMContentLoaded', function () {
821
864
  window.loadStatsData = loadStatsData;
822
865
  window.loadGoalProgress = loadGoalProgress;
823
866
 
867
+ function updateCurrentSessionOverview(sessionDetails, index = sessionDetails.length - 1) {
868
+ window.currentSessionIndex = index; // Store globally for potential future use
869
+ console.log('Updating current session overview:', sessionDetails);
870
+ // Get the session at index
871
+ const lastSession = sessionDetails && sessionDetails.length > 0 ? sessionDetails[index] : null;
872
+
873
+ if (!lastSession) {
874
+ // No current session
875
+ document.getElementById('currentSessionStatus').textContent = 'No active session';
876
+ document.getElementById('currentSessionTotalHours').textContent = '-';
877
+ document.getElementById('currentSessionTotalChars').textContent = '-';
878
+ document.getElementById('currentSessionStartTime').textContent = '-';
879
+ document.getElementById('currentSessionEndTime').textContent = '-';
880
+ document.getElementById('currentSessionCharsPerHour').textContent = '-';
881
+ return;
882
+ }
883
+
884
+ // Update session status (show game name if available)
885
+ const statusText = lastSession.gameName ? `Playing: ${lastSession.gameName}` : 'Active session';
886
+ document.getElementById('currentSessionStatus').textContent = statusText;
887
+
888
+ // Format session duration
889
+ let hoursDisplay = '-';
890
+ const sessionHours = lastSession.totalSeconds / 3600;
891
+ if (sessionHours > 0) {
892
+ const h = Math.floor(sessionHours);
893
+ const m = Math.round((sessionHours - h) * 60);
894
+ hoursDisplay = h > 0 ? `${h}h${m > 0 ? ' ' + m + 'm' : ''}` : `${m}m`;
895
+ }
896
+
897
+ // Format start time
898
+ const startTimeDisplay = new Date(lastSession.startTime * 1000).toLocaleTimeString('en-US', {
899
+ hour: '2-digit',
900
+ minute: '2-digit',
901
+ hour12: false
902
+ });
903
+
904
+ const endTimeDisplay = new Date(lastSession.endTime * 1000).toLocaleTimeString('en-US', {
905
+ hour: '2-digit',
906
+ minute: '2-digit',
907
+ hour12: false
908
+ });
909
+
910
+ // Update the DOM elements
911
+ document.getElementById('currentSessionTotalHours').textContent = hoursDisplay;
912
+ document.getElementById('currentSessionTotalChars').textContent = lastSession.totalChars.toLocaleString();
913
+ document.getElementById('currentSessionStartTime').textContent = startTimeDisplay;
914
+ if (index === sessionDetails.length - 1) {
915
+ document.getElementById('currentSessionEndTime').textContent = 'Now';
916
+ } else {
917
+ document.getElementById('currentSessionEndTime').textContent = endTimeDisplay;
918
+ }
919
+ document.getElementById('currentSessionCharsPerHour').textContent = lastSession.readSpeed !== '-' ? lastSession.readSpeed.toLocaleString() : '-';
920
+ }
921
+
824
922
  // Dashboard functionality
825
923
  function loadDashboardData(data = null, end_timestamp = null) {
826
924
  function updateTodayOverview(allLinesData) {
@@ -849,27 +947,84 @@ document.addEventListener('DOMContentLoaded', function () {
849
947
  // Calculate sessions (count gaps > session threshold as new sessions)
850
948
  let sessions = 0;
851
949
  let sessionGap = window.statsConfig ? window.statsConfig.sessionGapSeconds : 3600;
852
- if (todayLines.length > 0 && todayLines[0].session_id !== undefined) {
853
- const sessionSet = new Set(todayLines.map(l => l.session_id));
854
- sessions = sessionSet.size;
855
- } else {
856
- // Use timestamp gap logic
857
- const timestamps = todayLines
858
- .map(l => parseFloat(l.timestamp))
859
- .filter(ts => !isNaN(ts))
860
- .sort((a, b) => a - b);
861
- if (timestamps.length > 0) {
862
- sessions = 1;
863
- for (let i = 1; i < timestamps.length; i++) {
864
- if (timestamps[i] - timestamps[i - 1] > sessionGap) {
865
- sessions += 1;
950
+ let minimumSessionLength = 300; // 5 minutes minimum session length
951
+ let sessionDetails = [];
952
+ if (todayLines.length > 0) {
953
+ // Sort lines by timestamp
954
+ const sortedLines = todayLines.slice().sort((a, b) => parseFloat(a.timestamp) - parseFloat(b.timestamp));
955
+ let currentSession = null;
956
+ let lastTimestamp = null;
957
+ let lastGameName = null;
958
+
959
+ for (let i = 0; i < sortedLines.length; i++) {
960
+ const line = sortedLines[i];
961
+ const ts = parseFloat(line.timestamp);
962
+ const gameName = line.game_name || '';
963
+ const chars = Number(line.characters) || 0;
964
+
965
+ // Determine if new session: gap or new game
966
+ const isNewSession =
967
+ (lastTimestamp !== null && ts - lastTimestamp > sessionGap) ||
968
+ (lastGameName !== null && gameName !== lastGameName);
969
+
970
+ if (!currentSession || isNewSession) {
971
+ // Finish previous session
972
+ if (currentSession) {
973
+ // Calculate read speed for session
974
+ if (currentSession.totalSeconds > 0) {
975
+ currentSession.readSpeed = Math.round(currentSession.totalChars / (currentSession.totalSeconds / 3600));
976
+ } else {
977
+ currentSession.readSpeed = '-';
978
+ }
979
+ // Only add session if it meets minimum length requirement
980
+ if (currentSession.totalSeconds >= minimumSessionLength) {
981
+ sessionDetails.push(currentSession);
982
+ }
983
+ }
984
+ // Start new session
985
+ currentSession = {
986
+ startTime: ts,
987
+ endTime: ts,
988
+ gameName: gameName,
989
+ totalChars: chars,
990
+ totalSeconds: 0,
991
+ lines: [line]
992
+ };
993
+ } else {
994
+ // Continue current session
995
+ currentSession.endTime = ts;
996
+ currentSession.totalChars += chars;
997
+ currentSession.lines.push(line);
998
+ if (lastTimestamp !== null) {
999
+ let afkTimerSeconds = window.statsConfig ? window.statsConfig.afkTimerSeconds : 120;
1000
+ currentSession.totalSeconds += Math.min(ts - lastTimestamp, afkTimerSeconds);
866
1001
  }
867
1002
  }
868
- } else {
869
- sessions = 0;
1003
+
1004
+ lastTimestamp = ts;
1005
+ lastGameName = gameName;
1006
+ }
1007
+
1008
+ // Push last session
1009
+ if (currentSession) {
1010
+ if (currentSession.totalSeconds > 0) {
1011
+ currentSession.readSpeed = Math.round(currentSession.totalChars / (currentSession.totalSeconds / 3600));
1012
+ } else {
1013
+ currentSession.readSpeed = '-';
1014
+ }
1015
+ sessionDetails.push(currentSession);
870
1016
  }
1017
+
1018
+ sessions = sessionDetails.length;
1019
+ } else {
1020
+ sessions = 0;
1021
+ sessionDetails = [];
871
1022
  }
872
1023
 
1024
+ // Optionally, you can expose sessionDetails for debugging or further UI use:
1025
+ console.log(sessionDetails);
1026
+ window.todaySessionDetails = sessionDetails;
1027
+
873
1028
  // Calculate total reading time (reuse AFK logic from calculateHeatmapStreaks)
874
1029
  let totalSeconds = 0;
875
1030
  const timestamps = todayLines
@@ -908,6 +1063,9 @@ document.addEventListener('DOMContentLoaded', function () {
908
1063
  document.getElementById('todayTotalChars').textContent = totalChars.toLocaleString();
909
1064
  document.getElementById('todaySessions').textContent = sessions;
910
1065
  document.getElementById('todayCharsPerHour').textContent = charsPerHour;
1066
+
1067
+ // Update current session overview with the last session
1068
+ showSessionAtIndex(sessionDetails.length - 1);
911
1069
  }
912
1070
 
913
1071
  function updateOverviewForEndDay(allLinesData, endTimestamp) {
@@ -936,29 +1094,89 @@ document.addEventListener('DOMContentLoaded', function () {
936
1094
  return sum + (isNaN(chars) ? 0 : chars);
937
1095
  }, 0);
938
1096
 
939
- // Determine session gap (from settings or default)
940
- let sessionGap = window.statsConfig?.sessionGapSeconds || 3600;
941
-
942
- // Calculate sessions
943
1097
  let sessions = 0;
944
- if (targetLines.length > 0 && targetLines[0].session_id !== undefined) {
945
- const sessionSet = new Set(targetLines.map(l => l.session_id));
946
- sessions = sessionSet.size;
947
- } else {
948
- const timestamps = targetLines
949
- .map(l => parseFloat(l.timestamp))
950
- .filter(ts => !isNaN(ts))
951
- .sort((a, b) => a - b);
952
- if (timestamps.length > 0) {
953
- sessions = 1;
954
- for (let i = 1; i < timestamps.length; i++) {
955
- if (timestamps[i] - timestamps[i - 1] > sessionGap) {
956
- sessions += 1;
1098
+ let sessionGap = window.statsConfig ? window.statsConfig.sessionGapSeconds : 3600;
1099
+ let minimumSessionLength = 300; // 5 minutes minimum session length
1100
+ let sessionDetails = [];
1101
+ if (targetLines.length > 0) {
1102
+ // Sort lines by timestamp
1103
+ const sortedLines = targetLines.slice().sort((a, b) => parseFloat(a.timestamp) - parseFloat(b.timestamp));
1104
+ let currentSession = null;
1105
+ let lastTimestamp = null;
1106
+ let lastGameName = null;
1107
+
1108
+ for (let i = 0; i < sortedLines.length; i++) {
1109
+ const line = sortedLines[i];
1110
+ const ts = parseFloat(line.timestamp);
1111
+ const gameName = line.game_name || '';
1112
+ const chars = Number(line.characters) || 0;
1113
+
1114
+ // Determine if new session: gap or new game
1115
+ const isNewSession =
1116
+ (lastTimestamp !== null && ts - lastTimestamp > sessionGap) ||
1117
+ (lastGameName !== null && gameName !== lastGameName);
1118
+
1119
+ if (!currentSession || isNewSession) {
1120
+ // Finish previous session
1121
+ if (currentSession) {
1122
+ // Calculate read speed for session
1123
+ if (currentSession.totalSeconds > 0) {
1124
+ currentSession.readSpeed = Math.round(currentSession.totalChars / (currentSession.totalSeconds / 3600));
1125
+ } else {
1126
+ currentSession.readSpeed = '-';
1127
+ }
1128
+ // Only add session if it meets minimum length requirement
1129
+ if (currentSession.totalSeconds >= minimumSessionLength) {
1130
+ sessionDetails.push(currentSession);
1131
+ }
1132
+ }
1133
+ // Start new session
1134
+ currentSession = {
1135
+ startTime: ts,
1136
+ endTime: ts,
1137
+ gameName: gameName,
1138
+ totalChars: chars,
1139
+ totalSeconds: 0,
1140
+ lines: [line]
1141
+ };
1142
+ } else {
1143
+ // Continue current session
1144
+ currentSession.endTime = ts;
1145
+ currentSession.totalChars += chars;
1146
+ currentSession.lines.push(line);
1147
+ if (lastTimestamp !== null) {
1148
+ let afkTimerSeconds = window.statsConfig ? window.statsConfig.afkTimerSeconds : 120;
1149
+ currentSession.totalSeconds += Math.min(ts - lastTimestamp, afkTimerSeconds);
957
1150
  }
958
1151
  }
1152
+
1153
+ lastTimestamp = ts;
1154
+ lastGameName = gameName;
959
1155
  }
1156
+
1157
+ // Push last session
1158
+ if (currentSession) {
1159
+ if (currentSession.totalSeconds > 0) {
1160
+ currentSession.readSpeed = Math.round(currentSession.totalChars / (currentSession.totalSeconds / 3600));
1161
+ } else {
1162
+ currentSession.readSpeed = '-';
1163
+ }
1164
+ // Only add session if it meets minimum length requirement
1165
+ if (currentSession.totalSeconds >= minimumSessionLength) {
1166
+ sessionDetails.push(currentSession);
1167
+ }
1168
+ }
1169
+
1170
+ sessions = sessionDetails.length;
1171
+ } else {
1172
+ sessions = 0;
1173
+ sessionDetails = [];
960
1174
  }
961
1175
 
1176
+ // Optionally, you can expose sessionDetails for debugging or further UI use:
1177
+ console.log(sessionDetails);
1178
+ window.todaySessionDetails = sessionDetails;
1179
+
962
1180
  // Calculate total reading time
963
1181
  let totalSeconds = 0;
964
1182
  const timestamps = targetLines
@@ -999,6 +1217,8 @@ document.addEventListener('DOMContentLoaded', function () {
999
1217
  document.getElementById('todayTotalChars').textContent = totalChars.toLocaleString();
1000
1218
  document.getElementById('todaySessions').textContent = sessions;
1001
1219
  document.getElementById('todayCharsPerHour').textContent = charsPerHour;
1220
+
1221
+ showSessionAtIndex(sessionDetails.length - 1);
1002
1222
  }
1003
1223
 
1004
1224
  if (data && data.currentGameStats && data.allGamesStats) {
@@ -219,6 +219,44 @@
219
219
  </div>
220
220
  </div>
221
221
 
222
+ <!-- Today's Sessions Overview Card -->
223
+ <div class="dashboard-card current-session-overview" id="currentSessionOverviewCard" style="margin-bottom: 24px;">
224
+ <div class="dashboard-card-header">
225
+ <h3 class="dashboard-card-title">
226
+ <span class="dashboard-card-icon">🔄</span>
227
+ Today's Sessions
228
+ </h3>
229
+ <p class="dashboard-card-subtitle" id="currentSessionStatus">Loading...</p>
230
+ <!-- Two Arrow Keys To Navigate Between Sessions -->
231
+ <div class="session-navigation">
232
+ <button class="prev-session-btn" data-action="prevSession">←</button>
233
+ <button class="next-session-btn" data-action="nextSession">→</button>
234
+ </div>
235
+ </div>
236
+ <div class="dashboard-stats-grid" id="currentSessionStats">
237
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total hours spent reading in latest session">
238
+ <span class="dashboard-stat-value" id="currentSessionTotalHours">-</span>
239
+ <span class="dashboard-stat-label">Hours Spent</span>
240
+ </div>
241
+ <div class="dashboard-stat-item tooltip" data-tooltip="Total characters read in latest session">
242
+ <span class="dashboard-stat-value" id="currentSessionTotalChars">-</span>
243
+ <span class="dashboard-stat-label">Characters</span>
244
+ </div>
245
+ <div class="dashboard-stat-item tooltip" data-tooltip="Session start time">
246
+ <span class="dashboard-stat-value" id="currentSessionStartTime">-</span>
247
+ <span class="dashboard-stat-label">Started</span>
248
+ </div>
249
+ <div class="dashboard-stat-item tooltip" data-tooltip="Session end time">
250
+ <span class="dashboard-stat-value" id="currentSessionEndTime">-</span>
251
+ <span class="dashboard-stat-label">Ended</span>
252
+ </div>
253
+ <div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed in latest session">
254
+ <span class="dashboard-stat-value" id="currentSessionCharsPerHour">-</span>
255
+ <span class="dashboard-stat-label">Chars/Hour</span>
256
+ </div>
257
+ </div>
258
+ </div>
259
+
222
260
  <div class="chart-container">
223
261
  <h2>Activity Heatmap</h2>
224
262
  <div id="heatmapContainer"></div>
@@ -179,7 +179,10 @@ def get_screenshot():
179
179
  event_id = data.get('id')
180
180
  if event_id is None:
181
181
  return jsonify({'error': 'Missing id'}), 400
182
- gsm_state.line_for_screenshot = get_line_by_id(event_id)
182
+ line = get_line_by_id(event_id)
183
+ if not line:
184
+ return jsonify({'error': 'Invalid id'}), 400
185
+ gsm_state.line_for_screenshot = line
183
186
  if gsm_state.previous_line_for_screenshot and gsm_state.line_for_screenshot == gsm_state.previous_line_for_screenshot or gsm_state.previous_line_for_audio and gsm_state.line_for_screenshot == gsm_state.previous_line_for_audio:
184
187
  handle_texthooker_button(gsm_state.previous_replay)
185
188
  else:
@@ -195,7 +198,10 @@ def play_audio():
195
198
  if event_id is None:
196
199
  return jsonify({'error': 'Missing id'}), 400
197
200
  print(f"Playing audio for event ID: {event_id}")
198
- gsm_state.line_for_audio = get_line_by_id(event_id)
201
+ line = get_line_by_id(event_id)
202
+ if not line:
203
+ return jsonify({'error': 'Invalid id'}), 400
204
+ gsm_state.line_for_audio = line
199
205
  print(f"gsm_state.line_for_audio: {gsm_state.line_for_audio}")
200
206
  if gsm_state.previous_line_for_audio and gsm_state.line_for_audio == gsm_state.previous_line_for_audio or gsm_state.previous_line_for_screenshot and gsm_state.line_for_audio == gsm_state.previous_line_for_screenshot:
201
207
  handle_texthooker_button(gsm_state.previous_replay)
@@ -212,6 +218,8 @@ def translate_line():
212
218
  if event_id is None:
213
219
  return jsonify({'error': 'Missing id'}), 400
214
220
  line = get_line_by_id(event_id)
221
+ if line is None:
222
+ return jsonify({'error': 'Invalid id'}), 400
215
223
  line_to_translate = text if text else line.text
216
224
  translation = get_ai_prompt_result(get_all_lines(), line_to_translate,
217
225
  line, get_current_game())
@@ -384,6 +392,13 @@ def reset_checked_lines():
384
392
  })
385
393
  event_manager.reset_checked_lines()
386
394
  asyncio.run(send_reset_message())
395
+
396
+ def reset_buttons():
397
+ async def send_reset_message():
398
+ await websocket_server_thread.send_text({
399
+ 'event': 'reset_buttons',
400
+ })
401
+ asyncio.run(send_reset_message())
387
402
 
388
403
 
389
404
  def open_texthooker():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GameSentenceMiner
3
- Version: 2.18.6
3
+ Version: 2.18.7
4
4
  Summary: A tool for mining sentences from games. Update: Overlay?
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -1,9 +1,9 @@
1
1
  GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- GameSentenceMiner/anki.py,sha256=TgLJIGZq6qPfmXV378BzG_SEnL6KvHK74u4ztTggzbM,31139
2
+ GameSentenceMiner/anki.py,sha256=XHsLU_uhTA9qO6TfX8NwkHEy7dyfD6rHlvG37u2-x1E,31251
3
3
  GameSentenceMiner/gametext.py,sha256=FBL3kgJ71hCg5Nczuo9dAEi_sLGdVIGgvc62bT5KhCc,10691
4
4
  GameSentenceMiner/gsm.py,sha256=0hEpEBDbI9FtiKtHeyrSLKV1nys-mKTKfxLY0Dk7mOQ,36387
5
5
  GameSentenceMiner/obs.py,sha256=tyiZhVTGxWUsc_L1A5PmmSxHuWILx-B_QnW5TKbcf4A,36873
6
- GameSentenceMiner/vad.py,sha256=dhZpbTsVI4scqXZ0M701BenUur0EzYM96tnyGXo8iI0,21021
6
+ GameSentenceMiner/vad.py,sha256=I9ySJkblBmLaNumK77yZcQ7xM7DjLhGP2hNosBtNfjQ,21289
7
7
  GameSentenceMiner/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  GameSentenceMiner/ai/ai_prompting.py,sha256=mq9Odv_FpohXagU-OoSZbLWttdrEl1M1NiqnodeUpD8,29126
9
9
  GameSentenceMiner/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -14,9 +14,9 @@ GameSentenceMiner/assets/icon32.png,sha256=Kww0hU_qke9_22wBuO_Nq0Dv2SfnOLwMhCyGg
14
14
  GameSentenceMiner/assets/icon512.png,sha256=HxUj2GHjyQsk8NV433256UxU9phPhtjCY-YB_7W4sqs,192487
15
15
  GameSentenceMiner/assets/icon64.png,sha256=N8xgdZXvhqVQP9QUK3wX5iqxX9LxHljD7c-Bmgim6tM,9301
16
16
  GameSentenceMiner/assets/pickaxe.png,sha256=VfIGyXyIZdzEnVcc4PmG3wszPMO1W4KCT7Q_nFK6eSE,1403829
17
- GameSentenceMiner/locales/en_us.json,sha256=FMoG9Nggx3G48ydy9bXgEBwQv9lxb4UZI7WzXatdBtY,28202
18
- GameSentenceMiner/locales/ja_jp.json,sha256=ilCa04D4MbtCc2dlnij_a5qpZ_ity4CLtmSrRJ2h_7M,30172
19
- GameSentenceMiner/locales/zh_cn.json,sha256=tFhxETRemkhFOcNIF_1R4TiFDdKHrSqq8BoIbZ5KoHc,26190
17
+ GameSentenceMiner/locales/en_us.json,sha256=SzkTPoCTXqX0utPiSVUE8Unv_27ehuMHOBQzT9t8pMo,28152
18
+ GameSentenceMiner/locales/ja_jp.json,sha256=ekgfTyPPVn1rFZlgE70Gc07SDicIBsJ3A8qHUw9yCZg,30194
19
+ GameSentenceMiner/locales/zh_cn.json,sha256=aa7IdLCYEXB05TpXdIGXJFyfVaJOABIdXwYKwpYyB1Y,26144
20
20
  GameSentenceMiner/ocr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  GameSentenceMiner/ocr/gsm_ocr_config.py,sha256=Ov04c-nKzh3sADxO-5JyZWVe4DlrHM9edM9tc7-97Jo,5970
22
22
  GameSentenceMiner/ocr/ocrconfig.py,sha256=_tY8mjnzHMJrLS8E5pHqYXZjMuLoGKYgJwdhYgN-ny4,6466
@@ -36,15 +36,16 @@ GameSentenceMiner/tools/furigana_filter_preview.py,sha256=BXv7FChPEJW_VeG5XYt6su
36
36
  GameSentenceMiner/tools/ss_selector.py,sha256=ob2oJdiYreDMMau7CvsglpnhZ1CDnJqop3lV54-PjRo,4782
37
37
  GameSentenceMiner/tools/window_transparency.py,sha256=GtbxbmZg0-UYPXhfHff-7IKZyY2DKe4B9GdyovfmpeM,8166
38
38
  GameSentenceMiner/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- GameSentenceMiner/ui/anki_confirmation.py,sha256=m27IcWbUwb6o6Klh3NwXBc2FtMX9Da3vbLc2Bdht1G8,8593
40
- GameSentenceMiner/ui/config_gui.py,sha256=Nt6uuJrinOrSpDdrw92zdd1GvyQNjOoGvkZQdGWA9ds,151913
39
+ GameSentenceMiner/ui/anki_confirmation.py,sha256=fAPdZ_nfpSCuhLBim7jpHNXCnlODWwQs-c8qAS-brwU,10699
40
+ GameSentenceMiner/ui/config_gui.py,sha256=4baqfL33oMshmqm903GZok32Y4JIEV-3K9gf5gxAJDU,152131
41
41
  GameSentenceMiner/ui/screenshot_selector.py,sha256=AKML87MpgYQeSuj1F10GngpNrn9qp06zLLzNRwrQWM8,8900
42
42
  GameSentenceMiner/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- GameSentenceMiner/util/configuration.py,sha256=fYlU4Qrr6T-k_G2MY2rgoQ9EV_k7XBfbtsO8q7PKTsU,46653
43
+ GameSentenceMiner/util/audio_player.py,sha256=-yFsf0qoTSS1ga5rCmEJZJGUSJzXCvfZHY3t0NxycDk,7896
44
+ GameSentenceMiner/util/configuration.py,sha256=lwo73S3xnIMPq8lWSWM6N0pd08A4-JvrejypT3ZvTr8,47483
44
45
  GameSentenceMiner/util/db.py,sha256=1DjGjlwWnPefmQfzvMqqFPW0a0qeO-fIXE1YqKiok18,32000
45
46
  GameSentenceMiner/util/electron_config.py,sha256=KfeJToeFFVw0IR5MKa-gBzpzaGrU-lyJbR9z-sDEHYU,8767
46
47
  GameSentenceMiner/util/ffmpeg.py,sha256=cAzztfY36Xf2WvsJDjavoiMOvA9ac2GVdCrSB4LzHk4,29007
47
- GameSentenceMiner/util/get_overlay_coords.py,sha256=c37zVKPxFqwIi5XjZKjxRCW_Y8W4e1MX7vSLLwcOhs4,22116
48
+ GameSentenceMiner/util/get_overlay_coords.py,sha256=4V04RNVSIoiGrxRbYgzec2r29L8s7kmOjI_tuwfjLhI,24592
48
49
  GameSentenceMiner/util/gsm_utils.py,sha256=mASECTmN10c2yPL4NEfLg0Y0YWwFso1i6r_hhJPR3MY,10974
49
50
  GameSentenceMiner/util/model.py,sha256=R-_RYTYLSDNgBoVTPuPBcIHeOznIqi_vBzQ7VQ20WYk,6727
50
51
  GameSentenceMiner/util/notification.py,sha256=YBhf_mSo_i3cjBz-pmeTPx3wchKiG9BK2VBdZSa2prQ,4597
@@ -62,9 +63,9 @@ GameSentenceMiner/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
62
63
  GameSentenceMiner/web/database_api.py,sha256=Ph30uGAJFSxRkBdrZglXKsuwuKP46RxjzGODMO5aaLc,84827
63
64
  GameSentenceMiner/web/events.py,sha256=6Vyz5c9MdpMIa7Zqljqhap2XFQnAVYJ0CdQV64TSZsA,5119
64
65
  GameSentenceMiner/web/gsm_websocket.py,sha256=B0VKpxmsRu0WRh5nFWlpDPBQ6-K2ed7TEIa0O6YWeoo,4166
65
- GameSentenceMiner/web/service.py,sha256=YZchmScTn7AX_GkwV1ULEK6qjdOnJcpc3qfMwDf7cUE,5363
66
+ GameSentenceMiner/web/service.py,sha256=6cgUmDgtp3ZKzuPFszowjPoq-BDtC1bS3ux6sykeaqo,6662
66
67
  GameSentenceMiner/web/stats.py,sha256=zIK0ZzyInvvlJh87KhAKYl2CCuMJWW6Wyv7UssURFbE,22366
67
- GameSentenceMiner/web/texthooking_page.py,sha256=f_-oqyb4NoU4ZrveDkPhGbHR4REdYiceceohKDq2e_I,15253
68
+ GameSentenceMiner/web/texthooking_page.py,sha256=IHRy3VTMAwJeGjTNr3TgjHgxe--g5jZcnHmNzxILXQE,15698
68
69
  GameSentenceMiner/web/static/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
70
  GameSentenceMiner/web/static/apple-touch-icon.png,sha256=OcMI8af_68DA_tweOsQ5LytTyMwm7-hPW07IfrOVgEs,46132
70
71
  GameSentenceMiner/web/static/favicon-96x96.png,sha256=lOePzjiKl1JY2J1kT_PMdyEnrlJmi5GWbmXJunM12B4,16502
@@ -85,7 +86,7 @@ GameSentenceMiner/web/static/js/anki_stats.js,sha256=ZZqvqvePan9w17Nry7ui1ozR0SM
85
86
  GameSentenceMiner/web/static/js/database.js,sha256=Yz72C0u2KbL8w9mkenNzeBi_v8mZrMyM3dEsxps7r5E,31133
86
87
  GameSentenceMiner/web/static/js/goals.js,sha256=PaJNS1jR1pIpBxYrI8Gog6XFQNPrnbaNWZ1QX7JVlAo,30938
87
88
  GameSentenceMiner/web/static/js/kanji-grid.js,sha256=k9y25X4TvFYi2CEO7cusrcFVSQRBFWAT1LQ3zJhewYc,16365
88
- GameSentenceMiner/web/static/js/overview.js,sha256=V9doaiu8axN5xl6cA0d7lAjc4R56W66XP7pnIFI0gr0,51858
89
+ GameSentenceMiner/web/static/js/overview.js,sha256=X2zYM0FOxZ3rO9MIor1KBp7Wbffq7yFypHzoBXv6sG8,62410
89
90
  GameSentenceMiner/web/static/js/search.js,sha256=QrjsVXf90c1LzD09TPaK93RbIN9yEiXF8IKAKrDY4hw,10482
90
91
  GameSentenceMiner/web/static/js/shared.js,sha256=ZNibQkJxdypg93uMhmr_NEgoT5hJfxikzF6RKGz5Wy0,20416
91
92
  GameSentenceMiner/web/static/js/stats.js,sha256=kfJ756a9JPK8l9S8YUldxXuICAGMIHMGaDoJCKpjfEs,35604
@@ -93,7 +94,7 @@ GameSentenceMiner/web/templates/anki_stats.html,sha256=0Y5lT-wGlliqgWHx9bgRZyiT_
93
94
  GameSentenceMiner/web/templates/database.html,sha256=fwqNfS4yX_LOXAMCSL3ieuuvzWz8KuwXizFplPFyzSs,17972
94
95
  GameSentenceMiner/web/templates/goals.html,sha256=kYUIteYzIArDWyZguuNzJScwMrrezWjFXxreU-LzzRk,21755
95
96
  GameSentenceMiner/web/templates/index.html,sha256=y1mrlcKWRdwmfBP8B06p1CBk1avAJOr32388nX8YX4A,229074
96
- GameSentenceMiner/web/templates/overview.html,sha256=mSlASGqiRO4oUsUDIhZhaPhFF396_xjE5sMJKtLmhqQ,23924
97
+ GameSentenceMiner/web/templates/overview.html,sha256=bzV28od9JyrQYD2M2O4rnRSrw0H7Atr7XoeQ8XSSpCQ,26327
97
98
  GameSentenceMiner/web/templates/search.html,sha256=nao3M_hAbm5ftzThi91NtQ3ZiINMPUNx4ngFmqLnLQ4,4060
98
99
  GameSentenceMiner/web/templates/stats.html,sha256=IOOFK3DXa3UVSrTLR_kLLNl6iy3ei-_C4EGqdbvZCos,22811
99
100
  GameSentenceMiner/web/templates/utility.html,sha256=KtqnZUMAYs5XsEdC9Tlsd40NKAVic0mu6sh-ReMDJpU,16940
@@ -124,9 +125,9 @@ GameSentenceMiner/web/templates/components/kanji_grid/thousand_character_classic
124
125
  GameSentenceMiner/web/templates/components/kanji_grid/wanikani_levels.json,sha256=8wjnnaYQqmho6t5tMxrIAc03512A2tYhQh5dfsQnfAM,11372
125
126
  GameSentenceMiner/web/templates/components/kanji_grid/words_hk_frequency_list.json,sha256=wRkqZNPzz6DT9OTPHpXwfqW96Qb96stCQNNgOL-ZdKk,17535
126
127
  GameSentenceMiner/wip/__init___.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
127
- gamesentenceminer-2.18.6.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
128
- gamesentenceminer-2.18.6.dist-info/METADATA,sha256=_wS71dKRpI114wDcNIOsAnBW7oHVbj6XrcYyeshaXxA,7487
129
- gamesentenceminer-2.18.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
130
- gamesentenceminer-2.18.6.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
131
- gamesentenceminer-2.18.6.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
132
- gamesentenceminer-2.18.6.dist-info/RECORD,,
128
+ gamesentenceminer-2.18.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
129
+ gamesentenceminer-2.18.7.dist-info/METADATA,sha256=tSdKTLxo7GQEm-9Zea4mSZs_2Z1unk-1jPRF3BXEM_Q,7487
130
+ gamesentenceminer-2.18.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
131
+ gamesentenceminer-2.18.7.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
132
+ gamesentenceminer-2.18.7.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
133
+ gamesentenceminer-2.18.7.dist-info/RECORD,,