Files
Code/python/persian-tutor/anki_export.py
dl92 3a8705ece8 Fix bugs, N+1 queries, and wire settings in persian-tutor
- Replace inline __import__("datetime").timedelta hack with proper import
- Remove unused import random in anki_export.py
- Add error handling for Claude CLI subprocess failures in ai.py
- Fix hardcoded absolute path in stt.py with relative Path resolution
- Fix N+1 DB queries in vocab.get_flashcard_batch and dashboard.get_category_breakdown
  by adding db.get_all_word_progress() batch query
- Wire Ollama model and Whisper size settings to actually update config
  via ai.set_ollama_model() and stt.set_whisper_size()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 15:40:24 +00:00

76 lines
2.4 KiB
Python

"""Generate Anki .apkg decks from vocabulary data."""
import genanki
# Stable model/deck IDs (generated once, kept constant)
_MODEL_ID = 1607392319
_DECK_ID = 2059400110
def _make_model():
"""Create an Anki note model with two card templates."""
return genanki.Model(
_MODEL_ID,
"GCSE Persian",
fields=[
{"name": "English"},
{"name": "Persian"},
{"name": "Finglish"},
{"name": "Category"},
],
templates=[
{
"name": "English → Persian",
"qfmt": '<div style="font-size:1.5em">{{English}}</div>'
'<br><small>{{Category}}</small>',
"afmt": '{{FrontSide}}<hr id="answer">'
'<div dir="rtl" style="font-size:2em">{{Persian}}</div>'
"<br><div>{{Finglish}}</div>",
},
{
"name": "Persian → English",
"qfmt": '<div dir="rtl" style="font-size:2em">{{Persian}}</div>'
'<br><small>{{Category}}</small>',
"afmt": '{{FrontSide}}<hr id="answer">'
'<div style="font-size:1.5em">{{English}}</div>'
"<br><div>{{Finglish}}</div>",
},
],
css=".card { font-family: arial; text-align: center; }",
)
def export_deck(vocab, categories=None, output_path="gcse-persian.apkg"):
"""Generate an Anki .apkg deck from vocabulary entries.
Args:
vocab: List of vocabulary entries (dicts with english, persian, finglish, category).
categories: Optional list of categories to include. None = all.
output_path: Where to save the .apkg file.
Returns:
Path to the generated .apkg file.
"""
model = _make_model()
deck = genanki.Deck(_DECK_ID, "GCSE Persian")
for entry in vocab:
if categories and entry.get("category") not in categories:
continue
note = genanki.Note(
model=model,
fields=[
entry.get("english", ""),
entry.get("persian", ""),
entry.get("finglish", ""),
entry.get("category", ""),
],
guid=genanki.guid_for(entry.get("id", entry["english"])),
)
deck.add_note(note)
package = genanki.Package(deck)
package.write_to_file(output_path)
return output_path