feat: complete academic symbol lexicon heal, 2-column Cooper extraction, and updated assets
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Ogham lexicon intersections + stamp [Огам: …] on the 1000-word catalog."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
CANON = ROOT / "oracle_enricher" / "data" / "traditions_canon.json"
|
||||
ASSET = ROOT / "assets" / "data" / "traditions_canon.json"
|
||||
LEX = ROOT / "oracle_enricher" / "data" / "lexicon.json"
|
||||
DART = ROOT / "lib" / "data" / "words_data.dart"
|
||||
HTML = ROOT / "lexicon_viewer.html"
|
||||
|
||||
OGHAM_TAG_RE = re.compile(r"\[Огам:[^\]]*\]\s*")
|
||||
|
||||
CLUSTERS = {
|
||||
"beith": ["начало", "рост", "лес"],
|
||||
"luis": ["защита", "взгляд", "огонь"],
|
||||
"fern": ["щит", "воин", "вода"],
|
||||
"sail": ["луна", "вода", "сон"],
|
||||
"nion": ["древо", "ось", "небо", "земля"],
|
||||
"uath": ["порог", "тайна", "защита"],
|
||||
"duir": ["сила", "дверь", "корона"],
|
||||
"tinne": ["огонь", "воин", "щит"],
|
||||
"coll": ["мудрость", "книга", "плод"],
|
||||
"ceirt": ["плод", "сад", "выбор"] if False else ["плод", "сад"],
|
||||
"muin": ["путь", "связь", "тайна"],
|
||||
"gort": ["связь", "путь", "рост"],
|
||||
"ngetal": ["удар", "путь"],
|
||||
"straif": ["тьма", "судьба", "тёрн"],
|
||||
"ruis": ["смерть", "цикл"],
|
||||
"ailm": ["свет", "взгляд", "небо"],
|
||||
"onn": ["огонь", "рост"],
|
||||
"ur": ["земля", "судьба"],
|
||||
"eadha": ["страх", "воздух"],
|
||||
"idho": ["смерть", "вечность", "цикл", "корень"],
|
||||
}
|
||||
|
||||
|
||||
def payload(e: dict) -> dict:
|
||||
return {
|
||||
"id": e["id"],
|
||||
"word": e["word"],
|
||||
"emoji": e.get("emoji", ""),
|
||||
"pos": e.get("pos", ""),
|
||||
"category": e.get("category", ""),
|
||||
"desc": "",
|
||||
}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
canon = json.loads(CANON.read_text(encoding="utf-8"))
|
||||
lex = {e["word"]: e for e in json.loads(LEX.read_text(encoding="utf-8"))}
|
||||
og = canon["ogham"]
|
||||
word_to_tags: dict[str, list[str]] = defaultdict(list)
|
||||
|
||||
for st in og["stations"]:
|
||||
sid = st["id"]
|
||||
prim = (st.get("primary") or {}).get("word")
|
||||
extra = []
|
||||
for w in CLUSTERS.get(sid, []):
|
||||
if w == prim or w not in lex or w in extra:
|
||||
continue
|
||||
extra.append(w)
|
||||
st["cluster"] = [payload(lex[w]) for w in extra[:6]]
|
||||
tag = f"[Огам: {st['name']}]"
|
||||
if prim:
|
||||
word_to_tags[prim].append(tag)
|
||||
for w in extra:
|
||||
word_to_tags[w].append(tag)
|
||||
|
||||
og["description"] = (
|
||||
"20 священных fews (деревьев) в 4 аикмах. Значения с oghamlore, Druid Ogham "
|
||||
"и пересечения со словарём 999. Сочетания в раскладе — соседство fews."
|
||||
)
|
||||
|
||||
text = json.dumps(canon, ensure_ascii=False, indent=2) + "\n"
|
||||
CANON.write_text(text, encoding="utf-8")
|
||||
ASSET.write_text(text, encoding="utf-8")
|
||||
|
||||
dart_lines = DART.read_text(encoding="utf-8").splitlines(keepends=True)
|
||||
i = 0
|
||||
while i < len(dart_lines):
|
||||
wm = re.match(r'(\s*word: ")([^"]+)(",\s*)$', dart_lines[i])
|
||||
if wm:
|
||||
word = wm.group(2)
|
||||
for j in range(i + 1, min(i + 12, len(dart_lines))):
|
||||
raw = dart_lines[j].rstrip("\n")
|
||||
dm = re.match(r'^(\s*description: ")(.*)(",)\s*$', raw)
|
||||
if dm:
|
||||
body = OGHAM_TAG_RE.sub("", dm.group(2)).strip()
|
||||
tags = word_to_tags.get(word)
|
||||
if tags:
|
||||
dart_lines[j] = f"{dm.group(1)}{' '.join(tags)} {body}{dm.group(3)}\n"
|
||||
else:
|
||||
dart_lines[j] = f"{dm.group(1)}{body}{dm.group(3)}\n"
|
||||
break
|
||||
if dart_lines[j].strip().startswith("WordItem("):
|
||||
break
|
||||
i += 1
|
||||
dart2 = "".join(dart_lines)
|
||||
DART.write_text(dart2, encoding="utf-8")
|
||||
|
||||
html = HTML.read_text(encoding="utf-8")
|
||||
start = html.find(" const TRADITIONS_CANON = ")
|
||||
end = html.find(" const WORDS_DATA = ")
|
||||
if start > 0 and end > start:
|
||||
html = (
|
||||
html[:start]
|
||||
+ " const TRADITIONS_CANON = "
|
||||
+ json.dumps(canon, ensure_ascii=False, indent=2)
|
||||
+ ";\n\n"
|
||||
+ html[end:]
|
||||
)
|
||||
m = re.search(r"const WORDS_DATA = (\[.*?\]);", html, flags=re.DOTALL)
|
||||
if m:
|
||||
words = json.loads(m.group(1))
|
||||
dart_descs = dict(re.findall(r'word: "([^"]+)"[\s\S]*?description: "([^"]*)"', dart2))
|
||||
for w in words:
|
||||
if w.get("word") in dart_descs:
|
||||
w["description"] = dart_descs[w["word"]]
|
||||
html = html[: m.start(1)] + json.dumps(words, ensure_ascii=False) + html[m.end(1) :]
|
||||
HTML.write_text(html, encoding="utf-8")
|
||||
|
||||
print("ogham stations", len(og["stations"]), "words tagged", len(word_to_tags))
|
||||
for st in og["stations"]:
|
||||
print(f" {st['id']:10} prim={(st.get('primary') or {}).get('word')} cl={[x['word'] for x in st['cluster']]}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user