aboutsummaryrefslogtreecommitdiff
path: root/scripts/gen-sanctoral.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-28 08:32:35 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-28 08:32:35 +0200
commitd3b7f41c7a823bda6b7bafae3a156348c4ce687f (patch)
treee08f0d74b0c42bcae65247f7d0868d9d5105e7b0 /scripts/gen-sanctoral.go
parent1f694889f767dedd84f60d8e0cbccf201c2d123f (diff)
downloadlectio-d3b7f41c7a823bda6b7bafae3a156348c4ce687f.tar.gz
lectio-d3b7f41c7a823bda6b7bafae3a156348c4ce687f.zip
fix(of): recover season-commemorated saints + correct Irenaeus rank
Audit of the OF sanctoral vs calapi's full celebration list (2026-2028) found saints that calapi only ever shows as 'commemoration' in a privileged season (Lent, late Advent, the Christmas octave) were dropped by the generator, and 'first-year-wins' froze a stale rank. - gen-sanctoral.go: map calapi 'commemoration' -> optional memorial; keep the HIGHEST rank per saint across an expanded 2025-2029 reference span (so a saint is seen at its true rank on an ordinary weekday, e.g. Polycarp as a memorial when Feb 23 falls in Ordinary Time). - Recovers 15 saints: Polycarp, Perpetua & Felicity, John of God, Frances of Rome, Patrick, Cyril of Jerusalem, Turibius, Isidore, Vincent Ferrer, Peter Canisius, John of Kanty, Thomas Becket, Sylvester I, and others (197->212). - Corrects St Irenaeus (June 28) optional -> obligatory memorial (2022 change). Verified vs calapi per-day 2026-2028: remaining diffs are only the 3 skipped movable memorials and name-phrasing of temporal days.
Diffstat (limited to 'scripts/gen-sanctoral.go')
-rw-r--r--scripts/gen-sanctoral.go47
1 files changed, 42 insertions, 5 deletions
diff --git a/scripts/gen-sanctoral.go b/scripts/gen-sanctoral.go
index 6d81d66..db2e490 100644
--- a/scripts/gen-sanctoral.go
+++ b/scripts/gen-sanctoral.go
@@ -61,11 +61,32 @@ func fetchMonth(cal string, y, m int) ([]calDay, error) {
}
var (
- rankMap = map[string]calendar.Rank{"solemnity": calendar.RankSolemnity, "feast": calendar.RankFeast, "memorial": calendar.RankMemorial, "optional memorial": calendar.RankOptional}
+ // "commemoration" is calapi's rank for a saint reduced to a commemoration by a
+ // privileged season (Lent, late Advent, the Christmas octave). Such a saint is
+ // never the observed day, so it maps to an optional memorial for lectio; its
+ // true (higher) rank is recovered from a year where its date is an ordinary
+ // weekday (see rankBand + the highest-rank-wins merge below).
+ rankMap = map[string]calendar.Rank{"solemnity": calendar.RankSolemnity, "feast": calendar.RankFeast, "memorial": calendar.RankMemorial, "optional memorial": calendar.RankOptional, "commemoration": calendar.RankOptional}
slugStripRe = regexp.MustCompile(`[^a-z0-9]+`)
plPrefixRe = regexp.MustCompile(`^(?:Uroczystość|Święto|Wspomnienie(?: obowiązkowe)?)\s+`)
)
+// rankBand orders OF ranks for the highest-rank-wins merge (higher = higher rank).
+func rankBand(r calendar.Rank) int {
+ switch r {
+ case calendar.RankSolemnity:
+ return 5
+ case calendar.RankFeast:
+ return 4
+ case calendar.RankMemorial:
+ return 3
+ case calendar.RankOptional:
+ return 2
+ default:
+ return 0
+ }
+}
+
func slugify(title string) string {
s := strings.ToLower(title)
s = strings.NewReplacer("ł", "l", "æ", "ae", "é", "e", "è", "e", "ô", "o", "ç", "c").Replace(s)
@@ -121,9 +142,13 @@ func main() {
"the-memorial-of-the-blessed-virgin-mary-on-saturday": true, // any free Saturday
}
- // Reference years: cover every weekday so a saint whose date is a Sunday in
- // one year is captured in another. 2025 is past -> niedziela gives pl names.
- for _, y := range []int{2025, 2026, 2027} {
+ // Reference years: enough spread that every fixed date falls on an ordinary
+ // weekday (not a Sunday, not inside a privileged season) in at least one year,
+ // so each saint is seen with its true rank. Start at 2025 (past -> niedziela
+ // gives pl names; also the date of a transferred feast is taken from the first
+ // year it is observed, and 2025 observes Joseph/Annunciation on their proper
+ // fixed dates).
+ for _, y := range []int{2025, 2026, 2027, 2028, 2029} {
for m := 1; m <= 12; m++ {
en, err := fetchMonth("general-en", y, m)
if err != nil {
@@ -167,7 +192,19 @@ func main() {
if slug == "" || movableSkip[slug] {
continue
}
- if _, seen := entries[slug]; seen {
+ // Highest-rank-wins: a saint seen as a commemoration in a
+ // privileged season one year and as its full rank on an ordinary
+ // weekday another year keeps the higher rank. Date/name/pl are
+ // kept from the first (proper-date) occurrence; rank/colour/class
+ // are upgraded.
+ if cur, seen := entries[slug]; seen {
+ if rankBand(rk) > rankBand(calendar.Rank(cur.rank)) {
+ cur.rank = string(rk)
+ cur.colour = c.Colour
+ cur.class = classOf(c.Title)
+ cur.rankNum = c.RankNum
+ entries[slug] = cur
+ }
continue
}
laTitle := ""