diff options
Diffstat (limited to 'internal/calendar/oracle_ef_test.go')
| -rw-r--r-- | internal/calendar/oracle_ef_test.go | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/internal/calendar/oracle_ef_test.go b/internal/calendar/oracle_ef_test.go new file mode 100644 index 0000000..ce4badd --- /dev/null +++ b/internal/calendar/oracle_ef_test.go @@ -0,0 +1,116 @@ +package calendar_test + +import ( + "encoding/json" + "os" + "sort" + "strings" + "testing" + "time" + + "github.com/lukaszkasprzak/lectio/internal/caldata" + "github.com/lukaszkasprzak/lectio/internal/calendar" +) + +type efOracleDay struct { + Tempora string `json:"tempora"` + Title string `json:"title"` + Rank int `json:"rank"` + Colour string `json:"colour"` +} + +// efSeasonFromString maps a missalemeum tempora/title phrase (for a day in the +// given month) to lectio's EF season. Order matters. Two position-dependent +// subtleties: the Whit-octave weekdays ("Monday after Pentecost") are still +// Paschaltide, so only "Sunday after Pentecost" is Time after Pentecost; and the +// resumed Sundays after Epiphany (celebrated in autumn) sit within Time after +// Pentecost, so an "after Epiphany" phrase in the second half of the year maps +// there, not to Time after Epiphany. +func efSeasonFromString(s string, month int) calendar.Season { + s = strings.ToLower(s) + has := func(subs ...string) bool { + for _, sub := range subs { + if strings.Contains(s, sub) { + return true + } + } + return false + } + switch { + case has("vigil of christmas"): // last day of Advent + return calendar.Advent + case has("advent"): + return calendar.Advent + case has("sunday after pentecost"), has("trinity", "christ the king", "corpus christi"): + return calendar.TimeAfterPentecost + case has("after epiphany", "epiphany"): + if month >= 6 { // resumed Epiphany Sundays, celebrated within Time after Pentecost + return calendar.TimeAfterPentecost + } + return calendar.TimeAfterEpiphany + case has("passion", "palm", "holy week", "maundy", "good friday", "holy saturday"): + return calendar.Passiontide + case has("septuagesima", "sexagesima", "quinquagesima"): + return calendar.Septuagesima + case has("ash wednesday", "lent"): + return calendar.Lent + case has("pentecost", "ascension", "rogation", "after easter", "easter", "low sunday", "paschal", "whit"): + return calendar.Easter_ // incl. the Whit octave (Mon-Sat after Pentecost) + case has("christmas", "nativity", "circumcision", "holy name", "octave day of christ"): + return calendar.Christmas + default: + return "" // unknown phrase -> skip this day + } +} + +// TestOracleEF diffs the EF engine against missalemeum (Divinum Officium data). +// Season is asserted strictly (validates temporalEF); rank/colour are reported +// informationally (partial 1962 sanctoral). +func TestOracleEF(t *testing.T) { + raw, err := os.ReadFile("testdata/oracle-ef.json") + if err != nil { + t.Skip("EF oracle snapshot missing; run scripts/build-oracle-ef.sh") + } + var oracle map[string]efOracleDay + if err := json.Unmarshal(raw, &oracle); err != nil { + t.Fatal(err) + } + sel := calendar.DefaultSelection() + sel.Form = "old" + layers := []calendar.Layer{caldata.Tridentine()} + + dates := make([]string, 0, len(oracle)) + for d := range oracle { + dates = append(dates, d) + } + sort.Strings(dates) + + var seasonMiss, skipped, total int + shown := 0 + for _, date := range dates { + od := oracle[date] + src := od.Tempora + if src == "" { + src = od.Title + } + day, _ := time.Parse("2006-01-02", date) + want := efSeasonFromString(src, int(day.Month())) + if want == "" { + skipped++ + continue + } + total++ + got := calendar.Compute(day.UTC(), sel, layers) + if got.Season != want { + seasonMiss++ + if shown < 25 { + t.Errorf("%s: EF season got %q want %q (from %q)", date, got.Season, want, src) + shown++ + } + } + } + t.Logf("EF oracle: %d checked, %d skipped(unmapped), %d season mismatches", total, skipped, seasonMiss) + if seasonMiss > 0 { + t.Fatalf("%d/%d EF season mismatches vs missalemeum — temporalEF is wrong", seasonMiss, total) + } +} |
