summaryrefslogtreecommitdiff
path: root/internal/calendar/types.go
blob: 298e49daee3bc3368c3ff29c5a96338851fd19fa (plain) (blame)
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// Package calendar computes the Ordinary Form liturgical day for any Gregorian
// date, offline and from first principles. It imports only the standard library.
package calendar

import "time"

// Rank is a form-specific rank token. Ordinary Form uses the values below;
// the Extraordinary Form uses its own (class-1..class-4, commemoration, ferial).
// Each form's precedence interprets its own vocabulary.
type Rank string

const (
	// Ordinary Form ranks.
	RankFerial    Rank = "ferial"    // ordinary weekday
	RankOptional  Rank = "optional"  // optional memorial
	RankMemorial  Rank = "memorial"  // obligatory memorial
	RankFeast     Rank = "feast"     //
	RankSolemnity Rank = "solemnity" //

	// Extraordinary Form ranks (1960 Code of Rubrics): I-IV class + commemoration.
	RankClass1        Rank = "class-1"
	RankClass2        Rank = "class-2"
	RankClass3        Rank = "class-3"
	RankClass4        Rank = "class-4"
	RankCommemoration Rank = "commemoration"
)

// ofRankOrder orders the Ordinary Form ranks for the few `<` comparisons in the
// OF path (ferial lowest, solemnity highest). Unknown/empty → 0 (ferial-level).
func ofRankOrder(r Rank) int {
	switch r {
	case RankSolemnity:
		return 4
	case RankFeast:
		return 3
	case RankMemorial:
		return 2
	case RankOptional:
		return 1
	default:
		return 0
	}
}

type Class int

const (
	ClassNone  Class = iota // temporal / ferial
	ClassSaint              // a saint
	ClassBVM                // the Blessed Virgin Mary
	ClassLord               // the Lord
)

type Colour string

const (
	White  Colour = "white"
	Red    Colour = "red"
	Green  Colour = "green"
	Violet Colour = "violet"
	Rose   Colour = "rose"
	Black  Colour = "black"
)

type Season string

const (
	Advent    Season = "advent"
	Christmas Season = "christmas"
	Lent      Season = "lent"
	Triduum   Season = "triduum"
	Easter_   Season = "easter" // trailing underscore: Easter is the func name
	Ordinary  Season = "ordinary"
)

type Reading struct{ Part, Citation string }

type Mass struct {
	Variant  string // "" = the day Mass; e.g. "vigil"
	Readings []Reading
}

// DateSpec is a celebration's raw date expression, resolved by resolveDate:
// "MM-DD" (fixed) | "easter±N" | "christmas±N" | "sunday-after MM-DD".
type DateSpec string

// RawCelebration is a celebration's fields exactly as parsed from a layer,
// before typing/merging. Fields are raw INI values keyed by INI key
// (e.g. "rank", "name.pl"); Variants holds "[slug/variant]" sub-sections.
type RawCelebration struct {
	Fields   map[string]string
	Variants map[string]map[string]string
}

// Celebration is the typed, built form used in results.
type Celebration struct {
	Slug   string
	Name   map[string]string // lang -> name
	Rank   Rank
	Class  Class
	Colour Colour
	Date   DateSpec
	Masses []Mass
	Layer  string // provenance
}

// Layer is one calendar layer (the embedded universal base, or later an
// override file). Cels is keyed by slug; insertion order is not significant.
type Layer struct {
	ID, Name, Type string
	Cels           map[string]RawCelebration
}

// Selection carries the config choices that steer computation.
type Selection struct {
	Form          string // "new" (OF). "old" reserved.
	Epiphany      string // "fixed" | "sunday"
	Ascension     string // "thursday" | "sunday"
	CorpusChristi string // "thursday" | "sunday"
}

// DefaultSelection is the Universal Roman Calendar default.
func DefaultSelection() Selection {
	return Selection{Form: "new", Epiphany: "fixed", Ascension: "thursday", CorpusChristi: "thursday"}
}

type LiturgicalDay struct {
	Date         time.Time
	Season       Season
	Week         int
	Weekday      time.Weekday
	Observed     Celebration
	Others       []Celebration
	Colour       Colour
	ObservedBand int    // Table-of-Liturgical-Days band of the observed celebration (1=highest)
	SundayCycle  string // "A" | "B" | "C"
	WeekdayCycle string // "I" | "II"
}

// ParseRank validates a rank token (OF or EF vocabulary), falling back to
// RankFerial for anything unknown.
func ParseRank(s string) Rank {
	switch Rank(s) {
	case RankSolemnity, RankFeast, RankMemorial, RankOptional, RankFerial,
		RankClass1, RankClass2, RankClass3, RankClass4, RankCommemoration:
		return Rank(s)
	default:
		return RankFerial
	}
}

func ParseClass(s string) Class {
	switch s {
	case "lord":
		return ClassLord
	case "bvm":
		return ClassBVM
	case "saint":
		return ClassSaint
	default:
		return ClassNone
	}
}

func ParseColour(s string) Colour {
	switch Colour(s) {
	case White, Red, Green, Violet, Rose, Black:
		return Colour(s)
	default:
		return ""
	}
}