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:] }