1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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:]
}
|