package calendar import "sort" // candidate is one celebration competing for a given day: the temporal day, or // a sanctoral celebration landing on it. The flags come from the temporal // builder (Task 4) or are empty for sanctoral entries. type candidate struct { Cel Celebration Temporal bool Privileged bool // band 1-2 temporal day PrivFeria bool // band 9 privileged feria Sunday bool // Ordinary/Christmas Sunday (band 6) Season Season } // precedence maps a candidate to its band in the Table of Liturgical Days // (Universal Norms, 1969) — lower = higher precedence. "Proper" celebrations // (a non-universal, non-temporal layer) sit one band below their General // Calendar counterpart. func precedence(c candidate) int { proper := c.Cel.Layer != "" && c.Cel.Layer != "universal" && c.Cel.Layer != "temporal" if c.Temporal { switch { case c.Season == Triduum: return 1 case c.Privileged: return 2 case c.Sunday: // Ordinary/Christmas Sunday (checked before the solemnity-rank fallback) return 6 case c.Cel.Rank == RankSolemnity: // Trinity, Corpus Christi, Sacred Heart, Christ the King return 3 case c.Cel.Rank == RankFeast: // feasts of the Lord (Baptism, Holy Family) return 5 case c.PrivFeria: return 9 default: return 13 } } switch c.Cel.Rank { case RankSolemnity: if proper { return 4 } return 3 case RankFeast: switch { case proper: return 8 case c.Cel.Class == ClassLord: // feasts of the Lord in the General Calendar return 5 default: return 7 } case RankMemorial: if proper { return 11 } return 10 case RankOptional: return 12 default: return 13 } } // pick returns the highest-precedence candidate as observed and the rest as // others (commemorations / optional memorials). Ordering is deterministic: // by precedence band, then by slug, so equal-band collisions resolve the same // way on every run. func pick(cands []candidate) (candidate, []candidate) { sorted := make([]candidate, len(cands)) copy(sorted, cands) sort.SliceStable(sorted, func(i, j int) bool { pi, pj := precedence(sorted[i]), precedence(sorted[j]) if pi != pj { return pi < pj } return sorted[i].Cel.Slug < sorted[j].Cel.Slug }) return sorted[0], sorted[1:] }