diff --git a/add-readings.py b/add-readings.py
index 0cf77ad..5f987fa 100644
--- a/add-readings.py
+++ b/add-readings.py
@@ -1,138 +1,17 @@
-import json
-import MeCab
-import re
-
-import requests
-
-request_url = "http://127.0.0.1:19633"
-request_timeout = 10
-
-# Generate Hiragana and Katakana characters
-hiragana = tuple(chr(i) for i in range(12353, 12436)) # \u3041 - \u3094
-katakana = tuple(chr(i) for i in range(12450, 12532)) # \u30A2 - \u30F4
-punctuation = tuple(chr(i) for i in range(65281, 65382))
-
-# Combine both into one tuple
-all_kana = hiragana + katakana + punctuation + (' ', 'ー', '・')
-
-KANJI_RE = re.compile(r"[\u4E00-\u9FFF]")
-
-def katakana_to_hiragana(text: str) -> str:
- return "".join(
- chr(ord(ch) - 0x60) if 0x30A1 <= ord(ch) <= 0x30F6 else ch
- for ch in text
- )
-
-# def get_node_reading(node) -> str:
-# features = node.feature.split(",")
-# print()
-# if len(features) >= 8 and features[7] != "*":
-# return katakana_to_hiragana(features[7])
-# return node.surface
-
-def has_kanji(text: str) -> bool:
- return bool(KANJI_RE.search(text))
-
-def get_node_reading(node) -> str:
- features = node.feature.split(",")
- ## These depend on what dictionary is being used.
- if len(features) > 6 and features[6] != "*":
- return katakana_to_hiragana(features[6])
- return node.surface
-
-def annotate_phrase(text: str) -> str:
- tagger = MeCab.Tagger()
- node = tagger.parseToNode(text)
- vocab = ()
- parts = []
- # 漢字
- furi = []
- while node:
- surface = node.surface
- if surface:
- vocab += (surface,)
- if has_kanji(surface):
- reading = get_node_reading(node)
- parts.append(f"{surface}({reading})")
- furi.append(f"{surface}")
- else:
- parts.append(surface)
- furi.append(surface)
- node = node.next
-
- return {'reading':("".join(parts)),'vocab':vocab,"furigana":("".join(furi))}
-
-def elide(text: str) -> str:
- elide_max_length = 100
- if len(text) > elide_max_length:
- return text[:100] + "..."
- return text
-
-def anki_fields_term(term : str) -> dict:
- params = {
- "text": term,
- "type": "term",
- "markers": ["audio", "cloze-body-kana", "conjugation", "expression", "furigana", "furigana-plain", "glossary", "glossary-brief", "glossary-no-dictionary", "glossary-first", "glossary-first-brief", "glossary-first-no-dictionary", "part-of-speech", "phonetic-transcriptions", "pitch-accents", "pitch-accent-graphs", "pitch-accent-graphs-jj", "pitch-accent-positions", "pitch-accent-categories", "reading", "tags", "clipboard-image", "clipboard-text", "cloze-body", "cloze-prefix", "cloze-suffix", "dictionary", "dictionary-alias", "document-title", "frequencies", "frequency-harmonic-rank", "frequency-harmonic-occurrence", "frequency-average-rank", "frequency-average-occurrence", "screenshot", "search-query", "popup-selection-text", "sentence", "sentence-furigana", "sentence-furigana-plain", "url"],
- "maxEntries": 1,
- "includeMedia": False,
- }
- response = requests.post(request_url + "/ankiFields", json = params, timeout = request_timeout)
- return json.loads(response.text)
-
-def term_entries(term :str) -> dict:
- #print("Requesting termEntries:")
- params = {
- "term": term,
- "maxEntries": 1,
- "includeMedia": False,
- }
- response = requests.post(request_url + "/termEntries", json = params, timeout = request_timeout)
- return json.loads(response.text)
-
-# perhaps set up a filter parameter.
-def flatten_string(node):
- if isinstance(node,str):
- yield node
- elif isinstance(node, list):
- for item in node:
- yield from flatten_string(item)
- elif isinstance(node,dict):
- if isinstance(node.get("content"), str):
- yield node["content"]
- else:
- for v in node.values():
- yield from flatten_string(v)
-
-def extract_text_by_type(node, target_type):
- if isinstance(node,dict):
- data = node.get("data")
- if isinstance(data,dict) and data.get("content") == target_type:
- yield from flatten_string(node.get("content"))
- #yield from ",".join(node.get("content"))
- for value in node.values():
- yield from extract_text_by_type(value, target_type)
- elif isinstance(node,list):
- for item in node:
- yield from extract_text_by_type(item,target_type)
-
-def get_glossary(word :str) -> list:
- glossary = list()
- dict_items = term_entries(word)
-
- entry = next(iter(dict_items.get("dictionaryEntries",[])),None)
- if entry:
- definition = next(iter(entry.get("definitions",[])),None)
- if definition:
- def_entry = next(iter(definition.get("entries", [])),None)
- if def_entry:
- glossary.extend( list(extract_text_by_type(def_entry, "glossary")) )
- return glossary[:2]
+from parser import *
#print(annotate_phrase("私は学校へ行きます"))
with open("dump2.json", "r", encoding="utf-16") as f:
dump = json.load(f)
+# foo = anki_fields_term(surface)
+# for entry in foo.get("fields"):
+# entry['expression']
+# entry['glossary-first-brief']
+ # entry['glossary-plain-no-dictionary']
+ # entry['frequency-average-rank']
+
vocab_dict = {}
## A micab phrase based word parser
for cd in dump:
@@ -196,8 +75,8 @@ for cd in dump:
vocab_dict = sorted(vocab_dict.items(), key= lambda x: x[1]['count'], reverse=True)
-with open("dump-withFuri.json", "w", encoding="utf-16") as outfile:
- json.dump(dump, outfile, ensure_ascii=False, indent=2)
+#with open("dump-withFuri.json", "w", encoding="utf-16") as outfile:
+# json.dump(dump, outfile, ensure_ascii=False, indent=2)
#with open("dump-vocab.json", "w", encoding="utf-16") as outfile:
# json.dump(vocab_dict, outfile, ensure_ascii=False, indent=2)
diff --git a/create-notes.py b/create-notes.py
index 255647f..377b446 100644
--- a/create-notes.py
+++ b/create-notes.py
@@ -1,79 +1,13 @@
-import json
-import MeCab
-import re
-
-import requests
+from parser import *
import os
from pathlib import Path
import shutil
-
-request_url = "http://127.0.0.1:19633"
-request_timeout = 10
+import hashlib
destination_directory_name = '/run/media/deck/YF8SD/Sync/Notebooks/Obsidian/Japanese/Yu-Gi-Oh/Cards/'
destination_path = Path(destination_directory_name)
-# Generate Hiragana and Katakana characters
-hiragana = tuple(chr(i) for i in range(12353, 12436)) # \u3041 - \u3094
-katakana = tuple(chr(i) for i in range(12450, 12532)) # \u30A2 - \u30F4
-punctuation = tuple(chr(i) for i in range(65281, 65382))
-
-# Combine both into one tuple
-all_kana = hiragana + katakana + punctuation + (' ', 'ー', '・')
-
-KANJI_RE = re.compile(r"[\u4E00-\u9FFF]")
-
-def katakana_to_hiragana(text: str) -> str:
- return "".join(
- chr(ord(ch) - 0x60) if 0x30A1 <= ord(ch) <= 0x30F6 else ch
- for ch in text
- )
-
-# def get_node_reading(node) -> str:
-# features = node.feature.split(",")
-# print()
-# if len(features) >= 8 and features[7] != "*":
-# return katakana_to_hiragana(features[7])
-# return node.surface
-
-def has_kanji(text: str) -> bool:
- return bool(KANJI_RE.search(text))
-
-def anki_fields_term(term : str) -> dict:
- params = {
- "text": term,
- "type": "term",
- "markers": ["audio", "cloze-body-kana", "conjugation", "expression", "furigana", "furigana-plain", "glossary", "glossary-brief", "glossary-no-dictionary", "glossary-first", "glossary-first-brief", "glossary-first-no-dictionary", "part-of-speech", "phonetic-transcriptions", "pitch-accents", "pitch-accent-graphs", "pitch-accent-graphs-jj", "pitch-accent-positions", "pitch-accent-categories", "reading", "tags", "clipboard-image", "clipboard-text", "cloze-body", "cloze-prefix", "cloze-suffix", "dictionary", "dictionary-alias", "document-title", "frequencies", "frequency-harmonic-rank", "frequency-harmonic-occurrence", "frequency-average-rank", "frequency-average-occurrence", "screenshot", "search-query", "popup-selection-text", "sentence", "sentence-furigana", "sentence-furigana-plain", "url"],
- "maxEntries": 1,
- "includeMedia": False,
- }
- response = requests.post(request_url + "/ankiFields", json = params, timeout = request_timeout)
- return json.loads(response.text)
-
-def term_entries(term :str) -> dict:
- #print("Requesting termEntries:")
- params = {
- "term": term,
- "maxEntries": 1,
- "includeMedia": False,
- }
- response = requests.post(request_url + "/termEntries", json = params, timeout = request_timeout)
- return json.loads(response.text)
-
-def get_glossary(word :str) -> list:
- glossary = list()
- dict_items = term_entries(word)
-
- entry = next(iter(dict_items.get("dictionaryEntries",[])),None)
- if entry:
- definition = next(iter(entry.get("definitions",[])),None)
- if definition:
- def_entry = next(iter(definition.get("entries", [])),None)
- if def_entry:
- glossary.extend( list(extract_text_by_type(def_entry, "glossary")) )
- return glossary[:2]
-
#print(annotate_phrase("私は学校へ行きます"))
## Make sure directories exist
@@ -81,6 +15,8 @@ if not destination_path.exists():
destination_path.mkdir(parents=True, exist_ok=True)
if not destination_path.joinpath('_attachments').exists():
destination_path.joinpath('_attachments').mkdir(parents=True, exist_ok=True)
+if not destination_path.joinpath('vocab').exists():
+ destination_path.joinpath('vocab').mkdir(parents=True, exist_ok=True)
with open("dump-withFuri.json", "r", encoding="utf-16") as f:
dump = json.load(f)
@@ -97,33 +33,64 @@ for cd in dump:
card_note.write("---\n")
## Name at the top
card_note.write(f"![[{cd}.jpg]]")
- card_note.write("\n##### Name\n")
+ card_note.write("\n#### Name\n")
card_note.write("")
card_note.write(dump[cd]['name_J'])
card_note.write("
")
card_note.write(dump[cd]['name_E'])
card_note.write(" ")
## the description
- card_note.write("\n##### Details\n")
+ card_note.write("\n#### Details\n")
card_note.write("")
card_note.write(dump[cd]['desc_J'])
card_note.write("
")
card_note.write(dump[cd]['desc_E'])
card_note.write(" ")
# desc_Furi
- card_note.write("\n##### Reading\n")
+ card_note.write("\n#### Reading\n")
if(dump[cd].get("furi")):
card_note.write(f"{dump[cd]['furi']}\n")
else:
card_note.write(dump[cd]['name_J'])
card_note.write("\n")
+ card_note.write("##### Glossary\n")
+ for vocab in dump[cd]["glossary_Name_J"]:
+ print(f"{vocab} : {dump[cd]["glossary_Name_J"][vocab]}", file=card_note)
+ card_note.write("\n")
if(dump[cd].get("desc_Furi")):
card_note.write(f"{dump[cd]['desc_Furi']}\n")
else:
card_note.write(dump[cd]['desc_J'])
card_note.write("\n")
- card_note.write("\n##### Glossary\n")
+ card_note.write("##### Glossary\n")
for vocab in dump[cd]["glossary_Desc_J"]:
- print(f"{vocab} : {dump[cd]["glossary_Desc_J"][vocab]}", file=card_note)
+ vocab_hash = hashlib.shake_256((vocab + 'Jitendex.org [2026-04-04]').encode()).hexdigest(4)
+ ## Only search and create a vocab file if it doesn't exist
+ if Path(destination_path.joinpath('vocab/' + vocab_hash + '.md')).exists() == False:
+ definitions = anki_fields_term(vocab)
+ if definitions.get("fields"):
+ with open(destination_path.as_posix() + '/vocab/' + vocab_hash + '.md', 'w') as vocab_note:
+ for entry in definitions.get("fields"):
+ vocab_note.write("\n")
+ print(entry['expression'], file=vocab_note)
+ #print(entry['furigana-plain'], file=vocab_note)
+ if entry['expression'] != entry['reading']:
+ print(entry['reading'], file=vocab_note)
+ print(entry['furigana'], file=vocab_note)
+ #print(f"Part of Speech: {entry['part-of-speech']}", file=vocab_note)
+ print(f"Frequency: {entry['frequency-average-rank']}", file=vocab_note)
+ #print(entry['glossary-plain-no-dictionary'], file=vocab_note)
+ vocab_note.write(entry['glossary-first'])
+ print("##### Other Definitions", file=vocab_note)
+ print(entry['glossary-plain-no-dictionary'], file=vocab_note)
+ print(f"[[{vocab_hash}|{vocab}]] : {dump[cd]["glossary_Desc_J"][vocab]}", file=card_note)
#print('>' + dump[cd]["glossary_Desc_J"][vocab], file=card_note)
-
+ card_note.write("\n")
+
+# foo = anki_fields_term(surface)
+# for entry in foo.get("fields"):
+# entry['expression']
+# entry['glossary-first-brief']
+ # entry['glossary-plain-no-dictionary']
+ # entry['frequency-average-rank']
+
diff --git a/parser.py b/parser.py
new file mode 100644
index 0000000..faf5e8d
--- /dev/null
+++ b/parser.py
@@ -0,0 +1,130 @@
+import json
+import MeCab
+import re
+
+import requests
+
+request_url = "http://127.0.0.1:19633"
+request_timeout = 10
+
+# Generate Hiragana and Katakana characters
+hiragana = tuple(chr(i) for i in range(12353, 12436)) # \u3041 - \u3094
+katakana = tuple(chr(i) for i in range(12450, 12532)) # \u30A2 - \u30F4
+punctuation = tuple(chr(i) for i in range(65281, 65382))
+
+# Combine both into one tuple
+all_kana = hiragana + katakana + punctuation + (' ', 'ー', '・')
+
+KANJI_RE = re.compile(r"[\u4E00-\u9FFF]")
+
+def katakana_to_hiragana(text: str) -> str:
+ return "".join(
+ chr(ord(ch) - 0x60) if 0x30A1 <= ord(ch) <= 0x30F6 else ch
+ for ch in text
+ )
+
+# def get_node_reading(node) -> str:
+# features = node.feature.split(",")
+# print()
+# if len(features) >= 8 and features[7] != "*":
+# return katakana_to_hiragana(features[7])
+# return node.surface
+
+def has_kanji(text: str) -> bool:
+ return bool(KANJI_RE.search(text))
+
+def get_node_reading(node) -> str:
+ features = node.feature.split(",")
+ ## These depend on what dictionary is being used.
+ if len(features) > 6 and features[6] != "*":
+ return katakana_to_hiragana(features[6])
+ return node.surface
+
+def annotate_phrase(text: str) -> str:
+ tagger = MeCab.Tagger()
+ node = tagger.parseToNode(text)
+ vocab = ()
+ parts = []
+ # 漢字
+ furi = []
+ while node:
+ surface = node.surface
+ if surface:
+ vocab += (surface,)
+ if has_kanji(surface):
+ reading = get_node_reading(node)
+ parts.append(f"{surface}({reading})")
+ furi.append(f"{surface}")
+ else:
+ parts.append(surface)
+ furi.append(surface)
+ node = node.next
+
+ return {'reading':("".join(parts)),'vocab':vocab,"furigana":("".join(furi))}
+
+def elide(text: str) -> str:
+ elide_max_length = 100
+ if len(text) > elide_max_length:
+ return text[:100] + "..."
+ return text
+
+def anki_fields_term(term : str) -> dict:
+ params = {
+ "text": term,
+ "type": "term",
+ #"markers": ["audio", "cloze-body-kana", "conjugation", "expression", "furigana", "furigana-plain", "glossary", "glossary-brief", "glossary-no-dictionary", "glossary-first", "glossary-first-brief", "glossary-first-no-dictionary", "part-of-speech", "phonetic-transcriptions", "pitch-accents", "pitch-accent-graphs", "pitch-accent-graphs-jj", "pitch-accent-positions", "pitch-accent-categories", "reading", "tags", "clipboard-image", "clipboard-text", "cloze-body", "cloze-prefix", "cloze-suffix", "dictionary", "dictionary-alias", "document-title", "frequencies", "frequency-harmonic-rank", "frequency-harmonic-occurrence", "frequency-average-rank", "frequency-average-occurrence", "screenshot", "search-query", "popup-selection-text", "sentence", "sentence-furigana", "sentence-furigana-plain", "url"],
+ "markers": ["audio", "expression", "cloze-body" , "furigana","furigana-plain", "part-of-speech", "reading", "glossary-first", "glossary-plain-no-dictionary" , "glossary-first-no-dictionary" , "dictionary", "frequencies", "frequency-average-rank", "frequency-average-occurrence", "screenshot", "sentence", "sentence-furigana", "sentence-furigana-plain" ],
+ "maxEntries": 2,
+ "includeMedia": False,
+ }
+ response = requests.post(request_url + "/ankiFields", json = params, timeout = request_timeout)
+ return json.loads(response.text)
+
+def term_entries(term :str) -> dict:
+ #print("Requesting termEntries:")
+ params = {
+ "term": term,
+ "maxEntries": 1,
+ "includeMedia": False,
+ }
+ response = requests.post(request_url + "/termEntries", json = params, timeout = request_timeout)
+ return json.loads(response.text)
+
+# perhaps set up a filter parameter.
+def flatten_string(node):
+ if isinstance(node,str):
+ yield node
+ elif isinstance(node, list):
+ for item in node:
+ yield from flatten_string(item)
+ elif isinstance(node,dict):
+ if isinstance(node.get("content"), str):
+ yield node["content"]
+ else:
+ for v in node.values():
+ yield from flatten_string(v)
+
+def extract_text_by_type(node, target_type):
+ if isinstance(node,dict):
+ data = node.get("data")
+ if isinstance(data,dict) and data.get("content") == target_type:
+ yield from flatten_string(node.get("content"))
+ #yield from ",".join(node.get("content"))
+ for value in node.values():
+ yield from extract_text_by_type(value, target_type)
+ elif isinstance(node,list):
+ for item in node:
+ yield from extract_text_by_type(item,target_type)
+
+def get_glossary(word :str) -> list:
+ glossary = list()
+ dict_items = term_entries(word)
+
+ entry = next(iter(dict_items.get("dictionaryEntries",[])),None)
+ if entry:
+ definition = next(iter(entry.get("definitions",[])),None)
+ if definition:
+ def_entry = next(iter(definition.get("entries", [])),None)
+ if def_entry:
+ glossary.extend( list(extract_text_by_type(def_entry, "glossary")) )
+ return glossary[:2]