a93e5d4cdc
Plain-C, dependency-free engine that produces a personalized daily Celtic Cross tarot spread and natal-chart/transit astrology reading, plus a standalone CLI (dist/deck-engine) and run.sh wrapper. Includes English/German output via a simple key=value translation format, and docs/diagrams describing the architecture and I/O.
156 lines
6.6 KiB
Markdown
156 lines
6.6 KiB
Markdown
# Input & output formats
|
|
|
|
See [`architecture.md`](architecture.md) for how these fit together.
|
|
There are two ways to provide input (direct CLI flags, or `run.sh` +
|
|
`user.properties`) and two output formats (`text`, `html`); the
|
|
`DailyReading` struct is the programmatic form both outputs are rendered
|
|
from, and the one the future watchapp will consume directly.
|
|
|
|
## Input
|
|
|
|
### Direct CLI flags (`dist/deck-engine`)
|
|
|
|
```
|
|
deck-engine --seed <string> --birth-date YYYY-MM-DD --birth-time HH:MM
|
|
--birth-utc-offset <hours> --birth-lat <deg> --birth-lon <deg>
|
|
[--date YYYY-MM-DDTHH:MM] [--format text|html]
|
|
```
|
|
|
|
| Flag | Required | Format | Meaning |
|
|
|---|---|---|---|
|
|
| `--seed` | yes | any string | Tarot seed. The same seed always produces the same 10-card spread, positions, and orientations (see `rng.c`/`tarot.c`). |
|
|
| `--birth-date` | yes | `YYYY-MM-DD` | Birth date, local calendar. |
|
|
| `--birth-time` | yes | `HH:MM` (24h) | Birth time, local clock. |
|
|
| `--birth-utc-offset` | yes | decimal hours, e.g. `2` or `-5.5` | Hours to **subtract** from local birth time to get UTC (e.g. `2` for CEST). |
|
|
| `--birth-lat` | yes | decimal degrees | Birth latitude, north positive. |
|
|
| `--birth-lon` | yes | decimal degrees | Birth longitude, east positive. |
|
|
| `--date` | no | `YYYY-MM-DDTHH:MM[:SS]` | UTC moment used for today's transits and as the moment the tarot seed is drawn against. Defaults to the current system time. |
|
|
| `--format` | no | `text` \| `html` | Output format, defaults to `text`. |
|
|
| `--lang` | no | language code, e.g. `en`, `de` | Reading language, defaults to `en`. Matches a file named `<code>.lang` in `--i18n-dir` (see "Translations" below). Unknown codes or missing files fall back to English with a warning on stderr. |
|
|
| `--i18n-dir` | no | path | Directory to look for `<lang>.lang` in. Defaults to an `i18n/` directory next to the binary itself (resolved from `argv[0]`, so `dist/deck-engine` finds `dist/i18n/` regardless of the caller's working directory). |
|
|
|
|
Birth latitude/longitude only affect the Ascendant/houses — planet signs
|
|
are geocentric and location-independent.
|
|
|
|
### `run.sh` + `user.properties`
|
|
|
|
`dist/run.sh [text|html] [lang]` wraps the binary for daily use:
|
|
|
|
- **Seed and `--date`** come from the OS clock: `date +%Y-%m-%d` (stable
|
|
all day) and `date -u +%Y-%m-%dT%H:%M`.
|
|
- **Birth data and language** are read from `dist/user.properties`, a
|
|
`key=value` properties file next to the script (`#`-prefixed lines and
|
|
blank lines are comments; whitespace around `=` is trimmed):
|
|
|
|
```properties
|
|
birth_date=1990-05-14
|
|
birth_time=14:32
|
|
birth_utc_offset=2
|
|
birth_lat=52.5200
|
|
birth_lon=13.4050
|
|
lang=en
|
|
```
|
|
|
|
The file is seeded once from `engine/scripts/user.properties.template`
|
|
with placeholder values (`YOUR_BIRTH_DATE_HERE`, etc.) and is **never
|
|
overwritten by later builds**. `run.sh` checks every birth field for an
|
|
empty value or a leftover `YOUR_` placeholder and refuses to run with a
|
|
clear error until the file is filled in; `lang` has no such check since
|
|
it always has a usable default (`en`).
|
|
- The optional second argument overrides `lang=` for a single run without
|
|
editing the file, e.g. `dist/run.sh html de`.
|
|
|
|
### Translations (`--lang`, `dist/i18n/`)
|
|
|
|
Every piece of display text — planet/sign/moon-phase/aspect names, tarot
|
|
card names and meanings, Celtic Cross position names, and the section
|
|
headers in the `text`/`html` output — is looked up in a translation
|
|
catalog with the built-in English text as the fallback for any key the
|
|
catalog doesn't have. See `CLAUDE.md`'s "Translations" section for the
|
|
key-naming convention and how to add a new language.
|
|
|
|
`engine/i18n/en.lang` and `de.lang` are the shipped translation files;
|
|
`make` copies `engine/i18n/*.lang` to `dist/i18n/` (refreshed on every
|
|
build, like `dist/img/`). Adding a language is just dropping another
|
|
`<code>.lang` file into `engine/i18n/` — no code changes needed.
|
|
|
|
## Output
|
|
|
|
### `DailyReading` (the real output — `reading.h`)
|
|
|
|
`reading_generate()` is the actual API; `text`/`html` below are just two
|
|
ways of rendering the struct it fills in. This is what the watchapp will
|
|
read directly once it exists.
|
|
|
|
```c
|
|
typedef struct {
|
|
NatalChart natal;
|
|
DailyTransits transits;
|
|
CelticCrossSpread spread;
|
|
} DailyReading;
|
|
```
|
|
|
|
- **`NatalChart`** (`astro.h`): `bodies[10]` (Sun..Pluto, each a sign +
|
|
degree-in-sign + raw ecliptic longitude), `ascendant_longitude`,
|
|
`houses[12]` (whole-sign: `houses[0]` is the Ascendant's sign).
|
|
- **`DailyTransits`** (`astro.h`): `bodies[10]` (today's positions, same
|
|
shape as above), `moon_phase` (one of 8 named phases), `aspects[]` +
|
|
`aspect_count` (each aspect names a transiting planet, a natal planet,
|
|
an `AspectType` — conjunction/sextile/square/trine/opposition — and
|
|
the orb in degrees).
|
|
- **`CelticCrossSpread`** (`tarot.h`): `positions[10]`, indexed by
|
|
`CelticCrossPosition` (Present, Challenge, Crown, Foundation, Recent
|
|
Past, Near Future, Attitude, Environment, Hopes and Fears, Outcome —
|
|
Waite's own drawing order), each holding a `TarotCard` and a `reversed`
|
|
bool.
|
|
|
|
### `--format text`
|
|
|
|
Four `=====`-delimited sections, in order: natal chart (each body's sign
|
|
+ degree, then the Ascendant), today's sky (Moon phase, then each body's
|
|
transiting position), today's aspects to the natal chart (one line per
|
|
aspect, with orb), and the Celtic Cross (one block per position: name,
|
|
card, `(Reversed)` if applicable, the position's meaning, then the
|
|
card's meaning).
|
|
|
|
```
|
|
===== Natal Chart =====
|
|
Sun 23.5° Taurus
|
|
Moon 15.2° Capricorn
|
|
...
|
|
Ascendant 18.4° Pisces
|
|
|
|
===== Today's Sky =====
|
|
Moon phase: Waning Gibbous
|
|
Sun 11.5° Cancer
|
|
...
|
|
|
|
===== Today's Aspects to Natal Chart =====
|
|
Transiting Sun Opposition natal Moon (orb 3.7°)
|
|
...
|
|
|
|
===== Celtic Cross =====
|
|
The Present The High Priestess (Reversed)
|
|
This covers him: the general influence affecting the matter.
|
|
Passion, moral or physical ardour, conceit, surface knowledge.
|
|
...
|
|
```
|
|
|
|
### `--format html`
|
|
|
|
A single self-contained HTML page (inline `<style>`, no JS, no external
|
|
requests) with the same four sections, plus each of the 10 Celtic Cross
|
|
cards rendered as an image:
|
|
|
|
```html
|
|
<img class="reversed" src="img/RWS_Tarot_02_High_Priestess.jpeg" alt="The High Priestess">
|
|
```
|
|
|
|
- `src="img/<file>"` is relative to the **HTML file's own location** —
|
|
it expects to sit next to an `img/` directory, exactly like
|
|
`dist/reading.html` next to `dist/img/` (which `make images` populates
|
|
from `res/img/`). Saving the HTML output anywhere else breaks the
|
|
image links.
|
|
- Reversed cards get `class="reversed"`, styled with `transform:
|
|
rotate(180deg)` in the page's inline CSS.
|