aboutsummaryrefslogtreecommitdiff
path: root/internal/calendar/precedence_ef.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-27 13:59:02 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-27 13:59:02 +0200
commitba5b6b54819b5dbea10213138d9f210373b2c629 (patch)
treef5965c73eaf1bea444f6ddc8a16173c914f7b1d1 /internal/calendar/precedence_ef.go
parent3bda15bfe7786ae97fac1cbf779b713cf4238846 (diff)
downloadlectio-ba5b6b54819b5dbea10213138d9f210373b2c629.tar.gz
lectio-ba5b6b54819b5dbea10213138d9f210373b2c629.zip
feat(calendar): precedenceEF (1960 occurrence by class + temporal-before-sanctoral)
Diffstat (limited to 'internal/calendar/precedence_ef.go')
-rw-r--r--internal/calendar/precedence_ef.go49
1 files changed, 49 insertions, 0 deletions
diff --git a/internal/calendar/precedence_ef.go b/internal/calendar/precedence_ef.go
new file mode 100644
index 0000000..81862b7
--- /dev/null
+++ b/internal/calendar/precedence_ef.go
@@ -0,0 +1,49 @@
+package calendar
+
+import "sort"
+
+// efRankOrder orders EF (1960) ranks: class-1 highest, then class-2..4,
+// commemoration, ferial lowest.
+func efRankOrder(r Rank) int {
+ switch r {
+ case RankClass1:
+ return 5
+ case RankClass2:
+ return 4
+ case RankClass3:
+ return 3
+ case RankClass4:
+ return 2
+ case RankCommemoration:
+ return 1
+ default: // ferial / unset
+ return 0
+ }
+}
+
+// precedenceEF ranks an EF candidate for occurrence (lower = higher precedence):
+// by class first, then — at equal class — the temporal office before the
+// sanctoral (a first-cut of the 1960 occurrence table; the missalemeum oracle
+// drives refinement).
+func precedenceEF(c candidate) int {
+ p := (6 - efRankOrder(c.Cel.Rank)) * 2 // class-1 -> 2, ferial -> 12
+ if !c.Temporal {
+ p++ // sanctoral yields to a temporal office of equal class
+ }
+ return p
+}
+
+// pickEF returns the observed EF celebration and the commemorations, ordered
+// deterministically by precedence then slug.
+func pickEF(cands []candidate) (candidate, []candidate) {
+ sorted := make([]candidate, len(cands))
+ copy(sorted, cands)
+ sort.SliceStable(sorted, func(i, j int) bool {
+ pi, pj := precedenceEF(sorted[i]), precedenceEF(sorted[j])
+ if pi != pj {
+ return pi < pj
+ }
+ return sorted[i].Cel.Slug < sorted[j].Cel.Slug
+ })
+ return sorted[0], sorted[1:]
+}