diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-28 10:54:28 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-28 10:54:28 +0200 |
| commit | f0bfe1efb93e04e0e3b9a33b8b085fc09e86af36 (patch) | |
| tree | 4cffcb7c8b712730a34a8a5f52c4ae7ad0c5484f /internal/caldata/readings.go | |
| parent | 98fe454868ffff3f52396e095b5cd5f1251f1fd2 (diff) | |
| download | lectio-f0bfe1efb93e04e0e3b9a33b8b085fc09e86af36.tar.gz lectio-f0bfe1efb93e04e0e3b9a33b8b085fc09e86af36.zip | |
fix(of): partial-proper memorials compose proper part + ferial (match USCCB)
A memorial marked 'PROPER Gospel' (Guardian Angels, Mary Magdalene, Our Lady of
Sorrows, Joseph the Worker, the Passion of John the Baptist, Sts Martha/Mary/
Lazarus) uses the FERIAL first reading + its proper gospel; one marked 'PROPER
First Reading' (Barnabas) uses its proper first + the ferial gospel. Previously we
imported catholic-resources' *suggested* first for the gospel-proper ones, which
differs from what USCCB publishes.
- readings.go: when the observed's inline Mass has only a proper gospel (or only a
proper first), fill the missing reading/psalm from the day's ferial and sort into
canonical order. A fully-proper feast is untouched. Factored out ofFerial().
- gen-of-sanctoral-readings.py: keep only the strictly-proper part per the CR
source-note.
Verified vs USCCB: Guardian Angels (2025-10-02) now = Nehemiah 8 / Ps 19 /
Matt 18:1-5,10 exactly. Updates TestUniversalSanctoralReadings.
Diffstat (limited to 'internal/caldata/readings.go')
| -rw-r--r-- | internal/caldata/readings.go | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/internal/caldata/readings.go b/internal/caldata/readings.go index 49109f5..1b87b7a 100644 --- a/internal/caldata/readings.go +++ b/internal/caldata/readings.go @@ -1,11 +1,25 @@ package caldata import ( + "sort" "time" "github.com/lukaszkasprzak/lectio/internal/calendar" ) +var partOrder = map[string]int{"first": 0, "psalm": 1, "second": 2, "acclamation": 3, "gospel": 4} + +// ofFerial returns the day's Ordinary-Form ferial (weekday) readings, or nil. +func ofFerial(sel calendar.Selection, date time.Time, day calendar.LiturgicalDay) []calendar.Reading { + if day.WeekdayCycle == "" || date.Weekday() == time.Sunday { + return nil + } + if temp := calendar.Compute(date, sel, nil); temp.Observed.Layer == "temporal" { + return TemporalReadings("new", temp.Observed.Slug+"-"+day.WeekdayCycle) + } + return nil +} + // Readings resolves a day's Mass readings: the observed celebration's inline // propers, else the temporal lectionary for its slug, else -- for an EF // weekday with no proper Mass -- the preceding Sunday's Mass (the 1962 rule @@ -17,6 +31,24 @@ func Readings(sel calendar.Selection, layers []calendar.Layer, date time.Time, d rs = append(rs, m.Readings...) } if len(rs) > 0 { + // OF: a memorial with only a PROPER gospel (or only a proper first) takes + // the missing reading from the day's ferial -- e.g. the Guardian Angels are + // the ferial first reading + their proper gospel (Matt 18), and St Barnabas + // is his proper first (Acts 11) + the ferial gospel. A fully-proper feast + // (first AND gospel present) is left untouched. + have := map[string]bool{} + for _, r := range rs { + have[r.Part] = true + } + if sel.Form != "old" && !(have["first"] && have["gospel"]) { + for _, fr := range ofFerial(sel, date, day) { + if p := fr.Part; !have[p] && (p == "first" || p == "psalm" || p == "gospel") { + rs = append(rs, fr) + have[p] = true + } + } + sort.SliceStable(rs, func(i, j int) bool { return partOrder[rs[i].Part] < partOrder[rs[j].Part] }) + } return rs } // temporal table: EF by bare slug; OF by slug+cycle. Sundays & solemnities @@ -39,14 +71,9 @@ func Readings(sel calendar.Selection, layers []calendar.Layer, date time.Time, d } // OF: a sanctoral memorial / optional memorial with no proper readings of its // own reads the FERIAL (weekday) readings of the day -- the ordinary OF rule. - // Compute the pure temporal (no sanctoral) to get the day's ferial slug. - if sel.Form != "old" && day.Observed.Layer != "temporal" && - day.WeekdayCycle != "" && date.Weekday() != time.Sunday { - temp := calendar.Compute(date, sel, nil) - if temp.Observed.Layer == "temporal" { - if r := TemporalReadings("new", temp.Observed.Slug+"-"+day.WeekdayCycle); len(r) > 0 { - return r - } + if sel.Form != "old" && day.Observed.Layer != "temporal" { + if r := ofFerial(sel, date, day); len(r) > 0 { + return r } } // EF: a green-season weekday with no proper Mass repeats the preceding Sunday. |
