Files
deck_in_a_dash/docs/input-output-format.md
T
ml 57deb62b51 Add astrological houses to natal chart and daily transits
Every planet position now carries its whole-sign house (1-12); transits
report the natal house each transiting planet currently occupies rather
than a fresh "houses for right now" chart, matching how transits are
normally read. Surfaced in both text and HTML output, fully translated.
2026-07-04 12:41:03 +02:00

6.8 KiB

Input & output formats

See 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):

    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.

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 + whole-sign house 1-12), 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 — house here is the natal chart's house the transiting planet currently occupies, not a fresh "houses for right now" chart), 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 + house, then the Ascendant), today's sky (Moon phase, then each body's transiting position + the natal house it currently occupies), 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      (House 3)
Moon      15.2° Capricorn   (House 11)
...
Ascendant  18.4° Pisces

===== Today's Sky =====
Moon phase: Waning Gibbous
Sun       11.5° Cancer      (House 5)
...

===== 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:

<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.