feat: complete academic symbol lexicon heal, 2-column Cooper extraction, and updated assets

This commit is contained in:
2026-10-09 15:26:58 +05:00
parent 7f91366201
commit 0b12e4583b
244 changed files with 611461 additions and 1617 deletions
+134
View File
@@ -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()