aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-14 13:22:16 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-14 13:22:16 +0200
commit913974b10a993af251b25125d1a417c452ad785c (patch)
tree5dd82811c100de6daa995bebd115a12434296508 /cmd
parentd7da4b09f7775276231d0241cfe2700d247728ee (diff)
parent3b32c002d3eddda5ece9422442717657b9fee63b (diff)
downloadlectio-913974b10a993af251b25125d1a417c452ad785c.tar.gz
lectio-913974b10a993af251b25125d1a417c452ad785c.zip
Merge branch 'polish-ui-and-calendar': the gomobile facade and the EF calendar fixes
Two bodies of work that shared a branch. The gomobile facade (2026-08-03..05): mobile.PartLabels, Days, and the observed rank on DayInfo, so dlectio stops hardcoding part IDs and rank strings; the 1962 part labels become i18n data; the documented gomobile bind command is corrected so it reproduces the shipped .aar. The EF calendar fixes (2026-08-12): seven defects found by differencing this engine against colitur, a second 1962 implementation built from the Missal's General Rubrics rather than from this codebase. RG 96 transfers were not skipping II-class days; a II-class privileged feria was not yielding to a feast; Sunday ranks, the two Rose Sundays and Holy Thursday's colour were wrong; and scripts/gen-sanctoral-ef inferred ranks, deduped and tagged classes wrongly, which put 15 III-class feasts into the shipped tridentine-calendar.ini as bare commemorations and dropped four entries outright. Holy Thursday was violet in both engines, which is how a shared lineage hides a defect: this project's ini is generated from missalemeum and colitur's data was bootstrapped from here, so an error inherited by both is invisible to a differential. It took the Missal itself to see it. The EF oracle test now asserts rank and colour, not season alone. One known gap is recorded in the source rather than fixed, as out of scope: RG 95 chained transfers (calendar.go).
Diffstat (limited to 'cmd')
-rw-r--r--cmd/lectio-ef-dump/main.go136
1 files changed, 136 insertions, 0 deletions
diff --git a/cmd/lectio-ef-dump/main.go b/cmd/lectio-ef-dump/main.go
new file mode 100644
index 0000000..e7d014a
--- /dev/null
+++ b/cmd/lectio-ef-dump/main.go
@@ -0,0 +1,136 @@
+// Command lectio-ef-dump prints lectio's Extraordinary Form (1962) calendar,
+// one line per day, for use as colitur's differential oracle.
+//
+// Output format is colitur's `colitur day <year>` line, PLUS two display-name
+// columns colitur's own line does not carry (so a straight `diff` against
+// colitur's output must ignore trailing fields, not compare them line for
+// line):
+//
+// YYYY-MM-DD weekday season week slug rank colour name_en name_pl [+other-slug]...
+//
+// name_en and name_pl are the observed celebration's own display name in
+// English and Polish (Celebration.Name["en"]/["pl"]), spaces replaced with
+// "_" so the line stays whitespace-delimited; "-" where the name is empty
+// (a bare feria with no proper name). Added after a regeneration of
+// internal/caldata/tridentine-calendar.ini once deleted all 322 Polish
+// names (name.pl 322 -> 0) with nothing in this repository's test suite OR
+// this dumper noticing: the season/rank/colour columns this tool already
+// printed were all still correct, since name is a wholly separate field
+// naming.CelebrationName reads independently. This dumper is what the
+// task's own before/after diff verification is run against, so it needed
+// to be structurally capable of seeing a name regression, not just told to
+// look harder next time.
+//
+// Every column carries lectio's OWN vocabulary (season names, slugs, rank and
+// colour spellings) -- this dumper does not translate lectio's values into
+// colitur's. The mapping between the two vocabularies is the differential
+// comparator's job, not this dumper's; translating here would hide real
+// divergences behind an already-reconciled view.
+//
+// The trailing "+other-slug" tokens are lectio's Others: the sanctoral
+// candidates that lost the day's precedence contest. lectio has no RG 111
+// commemoration-admission logic, so this is the set of losing candidates, not
+// the set of admitted commemorations -- the two are different things. See the
+// task report for detail; the comparator does not diff this column.
+//
+// Usage: lectio-ef-dump <from-year> <to-year>
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/lukaszkasprzak/lectio/internal/caldata"
+ "github.com/lukaszkasprzak/lectio/internal/calendar"
+)
+
+func main() {
+ os.Exit(run(os.Args[1:], os.Stdout, os.Stderr))
+}
+
+// run is lectio-ef-dump's testable entry point: parse args, compute, and
+// write. Returns a process exit code (0 ok, 1 runtime error, 2 usage error).
+func run(args []string, stdout, stderr io.Writer) int {
+ if len(args) != 2 {
+ fmt.Fprintln(stderr, "usage: lectio-ef-dump <from-year> <to-year>")
+ return 2
+ }
+ from, errFrom := strconv.Atoi(args[0])
+ to, errTo := strconv.Atoi(args[1])
+ if errFrom != nil || errTo != nil {
+ fmt.Fprintln(stderr, "lectio-ef-dump: from-year and to-year must be integers")
+ return 2
+ }
+ if from > to {
+ fmt.Fprintf(stderr, "lectio-ef-dump: from-year %d is after to-year %d\n", from, to)
+ return 2
+ }
+
+ sel := calendar.DefaultSelection()
+ sel.Form = "old"
+ layers := []calendar.Layer{caldata.Tridentine()}
+
+ w := bufio.NewWriter(stdout)
+ for y := from; y <= to; y++ {
+ start := time.Date(y, time.January, 1, 0, 0, 0, 0, time.UTC)
+ end := time.Date(y, time.December, 31, 0, 0, 0, 0, time.UTC)
+ for d := start; !d.After(end); d = d.AddDate(0, 0, 1) {
+ day := calendar.Compute(d, sel, layers)
+ if _, err := w.WriteString(dumpLine(day)); err != nil {
+ fmt.Fprintf(stderr, "lectio-ef-dump: %v\n", err)
+ return 1
+ }
+ }
+ }
+ if err := w.Flush(); err != nil {
+ fmt.Fprintf(stderr, "lectio-ef-dump: %v\n", err)
+ return 1
+ }
+ return 0
+}
+
+// dumpName renders a display-name field: spaces become "_" so the line stays
+// whitespace-delimited (names routinely contain spaces, e.g. "St. Thomas
+// Becket", "Wniebowzięcie N. M. P."); "-" for an empty name, matching the
+// week column's own convention for "absent".
+func dumpName(s string) string {
+ if s == "" {
+ return "-"
+ }
+ return strings.ReplaceAll(s, " ", "_")
+}
+
+// dumpLine renders one LiturgicalDay as a colitur-format line, plus the
+// name_en/name_pl columns colitur's own line does not carry (see this
+// package's doc comment). Week is lectio's own int (0 where no season week
+// applies, e.g. named I class feasts and per annum green-season ferias);
+// printed as "-" there so the field count stays fixed, matching colitur's
+// own convention for an absent week.
+func dumpLine(day calendar.LiturgicalDay) string {
+ week := "-"
+ if day.Week != 0 {
+ week = strconv.Itoa(day.Week)
+ }
+ var b strings.Builder
+ fmt.Fprintf(&b, "%s %s %s %s %s %s %s %s %s",
+ day.Date.Format("2006-01-02"),
+ strings.ToLower(day.Weekday.String()),
+ string(day.Season),
+ week,
+ day.Observed.Slug,
+ string(day.Observed.Rank),
+ string(day.Colour),
+ dumpName(day.Observed.Name["en"]),
+ dumpName(day.Observed.Name["pl"]),
+ )
+ for _, o := range day.Others {
+ fmt.Fprintf(&b, " +%s", o.Slug)
+ }
+ b.WriteByte('\n')
+ return b.String()
+}