1662d550c7
- guidance.c now prints last, after the full spread; both it and main.c's new Celtic Cross readout pull real Waite card meanings via tarot_data.c instead of just naming cards. - interpreter-cli gains --format text|html|json and --lang en|de, matching deck-engine - required linking engine/src/tarot_data.c and i18n.c into the interpreter binary (a narrow, documented exception to its earlier "no engine .c files" policy) and writing German translations for narrative.c's/guidance.c's own text.
97 lines
4.7 KiB
Markdown
97 lines
4.7 KiB
Markdown
# Architecture
|
|
|
|
See [`CLAUDE.md`](../CLAUDE.md) for build commands and the sharp edges to
|
|
know before changing the engine. This document is the visual overview.
|
|
|
|
## Components
|
|
|
|

|
|
|
|
- **`res/`** holds the source assets: the 22 Rider-Waite-Smith Major
|
|
Arcana card images and A. E. Waite's *Pictorial Key to the Tarot* PDF
|
|
(public domain), which `tarot_data.c`'s card and position text is
|
|
condensed from.
|
|
- **`engine/third_party/astronomy/`** is a vendored, unmodified copy of
|
|
[cosinekitty/astronomy](https://github.com/cosinekitty/astronomy)
|
|
(MIT), pinned to a specific commit — see its `VENDORED.md`.
|
|
- **`engine/src/`** is the core engine. Everything except `main.c`,
|
|
`reading.c`'s `reading_print_text`/`reading_print_html` functions, and
|
|
`i18n.c`'s file-loading half is free of `stdio`/CLI assumptions, so it
|
|
links straight into a Pebble watchapp without rework.
|
|
- `rng.c` — deterministic string-seeded PRNG (FNV-1a + splitmix64).
|
|
- `tarot.c` / `tarot_data.c` — the Celtic Cross draw and its content.
|
|
- `astro.c` — natal chart + daily transits, built on the vendored
|
|
Astronomy Engine.
|
|
- `i18n.c` — loads a `key=value` translation file into a small
|
|
fixed-size catalog; every display-text lookup elsewhere falls back to
|
|
the built-in English string if no catalog is loaded or a key is
|
|
missing from it.
|
|
- `reading.c` — orchestrates the above into one `DailyReading` and
|
|
(desktop-only) renders it as text or HTML.
|
|
- `main.c` — CLI argument parsing, the only consumer of `reading_print_*`.
|
|
- **`engine/i18n/`** holds the translation source files (`en.lang`,
|
|
`de.lang`, ...), one `key=value` file per language — see
|
|
[`CLAUDE.md`](../CLAUDE.md) for the key-naming convention.
|
|
- **`dist/`** is generated by the single root `Makefile`: the
|
|
`deck-engine` and `interpreter-cli` binaries, a copy of the card art
|
|
under `img/`, a copy of the translation files under `i18n/`,
|
|
`run-engine.sh`/`run-interpreter.sh`, and `user.properties`. Since
|
|
`dist/` itself is disposable, `user.properties` also gets backed up to
|
|
`engine/scripts/user.properties.local` (gitignored) once it's filled
|
|
in, and restored from there if `dist/` is ever wiped — see
|
|
`CLAUDE.md`'s "Build & run".
|
|
|
|
## Dataflow
|
|
|
|

|
|
|
|
A single reading is produced by one call: `reading_generate(seed, birth,
|
|
utc_moment, &out)` in `reading.c`. It fans out to three independent
|
|
computations and combines their results:
|
|
|
|
1. **`astro_compute_natal_chart(birth)`** → `NatalChart` — geocentric
|
|
ecliptic sign/degree for the Sun through Pluto, the Ascendant, and
|
|
whole-sign houses, all from the birth date/time/location.
|
|
2. **`astro_compute_daily_transits(utc_moment, natal_chart)`** →
|
|
`DailyTransits` — today's planetary positions, the Moon phase, and
|
|
every transiting-to-natal aspect within orb. Depends on the natal
|
|
chart (read-only) to compute aspects against it.
|
|
3. **`tarot_draw_celtic_cross(seed)`** → `CelticCrossSpread` — ten cards
|
|
with position and upright/reversed orientation, fully determined by
|
|
the seed string alone.
|
|
|
|
These three results are combined into one `DailyReading` struct — the
|
|
real API surface. `reading_print_text`/`reading_print_html` (used by the
|
|
CLI) are just one way of consuming it; any caller, including watch UI
|
|
code, can walk the struct's fields directly. See
|
|
[`input-output-format.md`](input-output-format.md) for the exact fields
|
|
and output formats.
|
|
|
|
Every display string produced along the way (`tarot_data.c`'s card and
|
|
position text, `astro.c`'s body/sign/moon-phase/aspect names, and
|
|
`reading.c`'s section headers) is looked up in `i18n.c`'s translation
|
|
catalog, with the built-in English text as the fallback. `main.c` loads
|
|
the catalog from `--lang`/`--i18n-dir` (or `run-engine.sh`'s `lang=`
|
|
property) before calling `reading_generate`, so this is orthogonal to
|
|
the three computations above — it only affects how their results are
|
|
rendered as text, not the underlying `TarotCard`/`ZodiacSign`/etc. enum
|
|
values.
|
|
|
|
Both entry points (direct CLI flags, or `run-engine.sh` pulling the
|
|
seed/date from the OS clock and birth data from `user.properties`)
|
|
converge on the same `main.c` argument parsing before calling
|
|
`reading_generate` — there is exactly one code path from parsed input to
|
|
a reading. `run-interpreter.sh` reuses those same OS-clock/`user.properties`
|
|
inputs, but calls `deck-engine --format json` and pipes the result into
|
|
`interpreter-cli` instead of printing a reading directly.
|
|
|
|
## Regenerating the diagrams
|
|
|
|
The diagrams are Graphviz sources in `docs/diagrams/`, rendered to PNG:
|
|
|
|
```bash
|
|
cd docs
|
|
dot -Tpng -Gdpi=150 diagrams/architecture.dot -o images/architecture.png
|
|
dot -Tpng -Gdpi=150 diagrams/dataflow.dot -o images/dataflow.png
|
|
```
|