GameSentenceMiner 2.15.10__tar.gz → 2.15.12__tar.gz

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.
Files changed (104) hide show
  1. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/anki.py +31 -0
  2. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/ocr/owocr_helper.py +5 -5
  3. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/css/kanji-grid.css +107 -0
  4. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/css/search.css +14 -0
  5. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/css/shared.css +932 -0
  6. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/css/stats.css +499 -0
  7. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/js/anki_stats.js +84 -0
  8. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/js/database.js +541 -0
  9. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/js/kanji-grid.js +203 -0
  10. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/js/search.js +273 -0
  11. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/js/shared.js +506 -0
  12. gamesentenceminer-2.15.12/GameSentenceMiner/web/static/js/stats.js +1427 -0
  13. gamesentenceminer-2.15.12/GameSentenceMiner/web/templates/anki_stats.html +205 -0
  14. gamesentenceminer-2.15.12/GameSentenceMiner/web/templates/components/navigation.html +16 -0
  15. gamesentenceminer-2.15.12/GameSentenceMiner/web/templates/components/theme-styles.html +128 -0
  16. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/templates/stats.html +4 -0
  17. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/texthooking_page.py +50 -0
  18. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner.egg-info/PKG-INFO +1 -1
  19. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner.egg-info/SOURCES.txt +13 -1
  20. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/PKG-INFO +1 -1
  21. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/pyproject.toml +2 -2
  22. gamesentenceminer-2.15.10/GameSentenceMiner/web/templates/text_replacements.html +0 -449
  23. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/__init__.py +0 -0
  24. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/ai/__init__.py +0 -0
  25. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/ai/ai_prompting.py +0 -0
  26. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/assets/__init__.py +0 -0
  27. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/assets/icon.png +0 -0
  28. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/assets/icon128.png +0 -0
  29. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/assets/icon256.png +0 -0
  30. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/assets/icon32.png +0 -0
  31. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/assets/icon512.png +0 -0
  32. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/assets/icon64.png +0 -0
  33. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/assets/pickaxe.png +0 -0
  34. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/config_gui.py +0 -0
  35. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/gametext.py +0 -0
  36. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/gsm.py +0 -0
  37. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/locales/en_us.json +0 -0
  38. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/locales/ja_jp.json +0 -0
  39. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/locales/zh_cn.json +0 -0
  40. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/obs.py +0 -0
  41. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/ocr/__init__.py +0 -0
  42. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/ocr/gsm_ocr_config.py +0 -0
  43. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/ocr/ocrconfig.py +0 -0
  44. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/ocr/owocr_area_selector.py +0 -0
  45. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/ocr/ss_picker.py +0 -0
  46. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/owocr/owocr/__init__.py +0 -0
  47. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/owocr/owocr/__main__.py +0 -0
  48. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/owocr/owocr/config.py +0 -0
  49. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/owocr/owocr/lens_betterproto.py +0 -0
  50. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/owocr/owocr/ocr.py +0 -0
  51. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/owocr/owocr/run.py +0 -0
  52. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py +0 -0
  53. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/tools/__init__.py +0 -0
  54. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/tools/audio_offset_selector.py +0 -0
  55. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/tools/furigana_filter_preview.py +0 -0
  56. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/tools/ss_selector.py +0 -0
  57. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/tools/window_transparency.py +0 -0
  58. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/__init__.py +0 -0
  59. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/communication/__init__.py +0 -0
  60. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/communication/send.py +0 -0
  61. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/communication/websocket.py +0 -0
  62. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/configuration.py +0 -0
  63. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/db.py +0 -0
  64. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/downloader/Untitled_json.py +0 -0
  65. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/downloader/__init__.py +0 -0
  66. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/downloader/download_tools.py +0 -0
  67. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/downloader/oneocr_dl.py +0 -0
  68. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/electron_config.py +0 -0
  69. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/ffmpeg.py +0 -0
  70. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/get_overlay_coords.py +0 -0
  71. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/gsm_utils.py +0 -0
  72. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/model.py +0 -0
  73. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/notification.py +0 -0
  74. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/text_log.py +0 -0
  75. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/win10toast/__init__.py +0 -0
  76. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/util/win10toast/__main__.py +0 -0
  77. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/vad.py +0 -0
  78. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/__init__.py +0 -0
  79. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/database_api.py +0 -0
  80. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/events.py +0 -0
  81. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/service.py +0 -0
  82. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/__init__.py +0 -0
  83. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/apple-touch-icon.png +0 -0
  84. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/favicon-96x96.png +0 -0
  85. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/favicon.ico +0 -0
  86. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/favicon.svg +0 -0
  87. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/site.webmanifest +0 -0
  88. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/style.css +0 -0
  89. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/web-app-manifest-192x192.png +0 -0
  90. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/static/web-app-manifest-512x512.png +0 -0
  91. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/stats.py +0 -0
  92. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/templates/database.html +0 -0
  93. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/templates/index.html +0 -0
  94. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/templates/search.html +0 -0
  95. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/templates/utility.html +0 -0
  96. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/web/websockets.py +0 -0
  97. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner/wip/__init___.py +0 -0
  98. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner.egg-info/dependency_links.txt +0 -0
  99. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner.egg-info/entry_points.txt +0 -0
  100. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner.egg-info/requires.txt +0 -0
  101. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/GameSentenceMiner.egg-info/top_level.txt +0 -0
  102. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/LICENSE +0 -0
  103. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/README.md +0 -0
  104. {gamesentenceminer-2.15.10 → gamesentenceminer-2.15.12}/setup.cfg +0 -0
@@ -546,5 +546,36 @@ def start_monitoring_anki():
546
546
  obs_thread.start()
547
547
 
548
548
 
549
+ # --- Anki Stats Kanji Extraction Utilities ---
550
+
551
+ def get_all_anki_first_field_kanji():
552
+ """
553
+ Fetch all notes from Anki and extract unique kanji from the first field of each note.
554
+ Returns a set of kanji characters.
555
+ """
556
+ from GameSentenceMiner.web.stats import is_kanji
557
+ try:
558
+ note_ids = invoke("findNotes", query="")
559
+ if not note_ids:
560
+ return set()
561
+ kanji_set = set()
562
+ batch_size = 1000
563
+ for i in range(0, len(note_ids), batch_size):
564
+ batch_ids = note_ids[i:i+batch_size]
565
+ notes_info = invoke("notesInfo", notes=batch_ids)
566
+ for note in notes_info:
567
+ fields = note.get("fields", {})
568
+ first_field = next(iter(fields.values()), None)
569
+ if first_field and "value" in first_field:
570
+ first_field_value = first_field["value"]
571
+ for char in first_field_value:
572
+ if is_kanji(char):
573
+ kanji_set.add(char)
574
+ return kanji_set
575
+ except Exception as e:
576
+ logger.error(f"Failed to fetch kanji from Anki: {e}")
577
+ return set()
578
+
579
+
549
580
  if __name__ == "__main__":
550
581
  print(invoke("getIntervals", cards=["1754694986036"]))
@@ -414,7 +414,7 @@ done = False
414
414
  # Create a queue for tasks
415
415
  second_ocr_queue = queue.Queue()
416
416
 
417
- def get_ocr2_image(crop_coords, og_image, ocr2_engine=None):
417
+ def get_ocr2_image(crop_coords, og_image: Image.Image, ocr2_engine=None):
418
418
  """
419
419
  Returns the image to use for the second OCR pass, cropping and scaling as needed.
420
420
  Logic is unchanged, but code is refactored for clarity and maintainability.
@@ -424,10 +424,10 @@ def get_ocr2_image(crop_coords, og_image, ocr2_engine=None):
424
424
  if not crop_coords or not get_ocr_optimize_second_scan():
425
425
  return og_image
426
426
  x1, y1, x2, y2 = crop_coords
427
- x1 = min(max(0, x1), img.width)
428
- y1 = min(max(0, y1), img.height)
429
- x2 = min(max(0, x2), img.width)
430
- y2 = min(max(0, y2), img.height)
427
+ x1 = min(max(0, x1), og_image.width)
428
+ y1 = min(max(0, y1), og_image.height)
429
+ x2 = min(max(0, x2), og_image.width)
430
+ y2 = min(max(0, y2), og_image.height)
431
431
  og_image.save(os.path.join(get_temporary_directory(), "pre_oneocrcrop.png"))
432
432
  return og_image.crop((x1, y1, x2, y2))
433
433
 
@@ -0,0 +1,107 @@
1
+ /* Shared Kanji Grid Component Styles */
2
+
3
+ /* Kanji Grid Container */
4
+ .kanji-counter {
5
+ text-align: center;
6
+ font-size: 18px;
7
+ font-weight: bold;
8
+ color: #495057;
9
+ margin-bottom: 20px;
10
+ }
11
+
12
+ .kanji-grid {
13
+ display: grid;
14
+ grid-template-columns: repeat(auto-fill, minmax(30px, 1fr));
15
+ gap: 3px;
16
+ margin-bottom: 20px;
17
+ max-width: 100%;
18
+ }
19
+
20
+ /* Individual Kanji Cell */
21
+ .kanji-cell {
22
+ width: 30px;
23
+ height: 30px;
24
+ background-color: #ebedf0;
25
+ border-radius: 3px;
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ font-size: 16px;
30
+ font-weight: bold;
31
+ color: #333;
32
+ cursor: pointer;
33
+ position: relative;
34
+ transition: all 0.2s ease;
35
+ font-family: "Noto Sans CJK JP", "Hiragino Sans", "Yu Gothic", "Meiryo", "Takao", "IPAexGothic", "IPAPGothic", "VL PGothic", "Koruri", sans-serif;
36
+ line-height: 1;
37
+ text-align: center;
38
+ }
39
+
40
+ .kanji-cell:hover {
41
+ transform: scale(1.1);
42
+ z-index: 10;
43
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
44
+ }
45
+
46
+ /* Frequency-based color levels (for backward compatibility) */
47
+ .kanji-cell.level-1 { background-color: #c6e48b; }
48
+ .kanji-cell.level-2 { background-color: #7bc96f; }
49
+ .kanji-cell.level-3 { background-color: #239a3b; color: white; }
50
+ .kanji-cell.level-4 { background-color: #196127; color: white; }
51
+
52
+ /* Legend */
53
+ .kanji-legend {
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: center;
57
+ margin-top: 10px;
58
+ font-size: 12px;
59
+ color: #586069;
60
+ }
61
+
62
+ .kanji-legend-item {
63
+ width: 12px;
64
+ height: 12px;
65
+ margin: 0 2px;
66
+ border-radius: 2px;
67
+ }
68
+
69
+ /* Grid Container Wrapper */
70
+ .kanji-grid-container {
71
+ background: var(--bg-secondary);
72
+ padding: 20px;
73
+ border-radius: 8px;
74
+ box-shadow: 0 4px 12px var(--shadow-color);
75
+ border: 1px solid var(--border-color);
76
+ }
77
+
78
+ /* Responsive Design */
79
+ @media (max-width: 768px) {
80
+ .kanji-grid {
81
+ grid-template-columns: repeat(auto-fill, minmax(25px, 1fr));
82
+ gap: 2px;
83
+ }
84
+
85
+ .kanji-cell {
86
+ width: 25px;
87
+ height: 25px;
88
+ font-size: 14px;
89
+ }
90
+
91
+ .kanji-counter {
92
+ font-size: 16px;
93
+ }
94
+ }
95
+
96
+ @media (max-width: 480px) {
97
+ .kanji-grid {
98
+ grid-template-columns: repeat(auto-fill, minmax(22px, 1fr));
99
+ gap: 1px;
100
+ }
101
+
102
+ .kanji-cell {
103
+ width: 22px;
104
+ height: 22px;
105
+ font-size: 12px;
106
+ }
107
+ }
@@ -0,0 +1,14 @@
1
+ /* Search Page Specific Styles */
2
+
3
+ /* Search-specific responsive styles */
4
+ @media (max-width: 768px) {
5
+ .navigation {
6
+ padding: 10px;
7
+ }
8
+
9
+ .nav-link {
10
+ display: block;
11
+ margin: 5px 0;
12
+ text-align: center;
13
+ }
14
+ }