aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/rites/rite_of/precedence_of.ml40
-rw-r--r--lib/rites/rite_of/precedence_of.mli20
-rw-r--r--test/test_precedence_of.ml25
3 files changed, 84 insertions, 1 deletions
diff --git a/lib/rites/rite_of/precedence_of.ml b/lib/rites/rite_of/precedence_of.ml
index 5ceaa11..fb26d64 100644
--- a/lib/rites/rite_of/precedence_of.ml
+++ b/lib/rites/rite_of/precedence_of.ml
@@ -200,3 +200,43 @@ let disposition ~(winner : Vocab_of.rank Precedence.candidate)
| Vocab_of.Festum | Vocab_of.Memoria_obligatoria | Vocab_of.Memoria_ad_libitum
| Vocab_of.Feria ->
Precedence.Omit
+
+(* Normae n. 60's "Reliquae celebrationes eo anno omittuntur", read together
+ with the whole Tabula: nothing in the OF is admitted as a commemoration of
+ another day's office, so this returns the empty list unconditionally.
+
+ NOT A STUB. This is [disposition]'s own rule expressed at the second of the
+ two places the kernel asks about it: [disposition] never returns
+ [Commemorate], so Precedence.resolve never offers this function a candidate
+ it could admit even if it wanted to. Returning [] is therefore the only
+ answer consistent with the rubric, and every losing candidate is reported in
+ [resolution.omitted] with its reason -- nothing is dropped silently.
+
+ All three parameters are unread, for that reason. The EF's own admit reads
+ all of them (RG 108-113); the OF's has nothing to decide. *)
+let admit ~(observed : Vocab_of.rank Precedence.candidate)
+ ~(temporal : Vocab_of.rank Precedence.candidate)
+ (_ : (Vocab_of.rank Precedence.candidate * Precedence.privilege * int) list) :
+ (Vocab_of.rank Precedence.candidate * Precedence.privilege) list =
+ ignore observed;
+ ignore temporal;
+ []
+
+(* RG 33's third omission trigger is EF-only. The OF has no vigil OFFICE that
+ can be orphaned by its feast moving: Normae n. 11 gives solemnities First
+ Vespers and n. 13 denies them to feasts, but neither creates a separate
+ celebration that could survive or fail independently of the day it precedes.
+ The one OF celebration whose slug says "vigil" -- the Nativity's, which
+ Temporal_of emits as "of-nativity-vigil" -- is a MASS FORMULARY of the
+ solemnity itself (IGMR n. 346's own Christmas-Mass series: ad vigiliam, in
+ nocte, in aurora, in die), not a distinct celebration.
+
+ So [None] unconditionally, and Calendar's RG 33 suppression pass never
+ fires for this rite. *)
+let vigil_feast (_ : Vocab_of.rank Precedence.candidate) : Slug.t option = None
+
+(* The assembled record Precedence.resolve consumes. Kept here rather than in
+ rite_of.ml so a reader sees the four functions and their citations
+ together. *)
+let rules : (Vocab_of.season, Vocab_of.rank) Precedence.rules =
+ { band; disposition; admit; vigil_feast }
diff --git a/lib/rites/rite_of/precedence_of.mli b/lib/rites/rite_of/precedence_of.mli
index be4713d..6b30dad 100644
--- a/lib/rites/rite_of/precedence_of.mli
+++ b/lib/rites/rite_of/precedence_of.mli
@@ -56,3 +56,23 @@ val disposition :
winner:Vocab_of.rank Precedence.candidate ->
loser:Vocab_of.rank Precedence.candidate ->
Precedence.disposition
+
+(** [admit]: always the empty list. The OF admits no commemorations at all --
+ the direct consequence of {!disposition} never returning [Commemorate], and
+ argued from the same Normae n. 60. Not a stub: every losing candidate is
+ still reported in {!Colitur_kernel.Precedence.resolution.omitted} with its
+ reason, so nothing is dropped silently. All three parameters are unread. *)
+val admit :
+ observed:Vocab_of.rank Precedence.candidate ->
+ temporal:Vocab_of.rank Precedence.candidate ->
+ (Vocab_of.rank Precedence.candidate * Precedence.privilege * int) list ->
+ (Vocab_of.rank Precedence.candidate * Precedence.privilege) list
+
+(** [vigil_feast]: always [None]. RG 33's third omission trigger is EF-only;
+ the OF has no vigil OFFICE that its feast's movement could orphan. The
+ Nativity's "of-nativity-vigil" is a Mass formulary of the solemnity, not a
+ separate celebration. *)
+val vigil_feast : Vocab_of.rank Precedence.candidate -> Slug.t option
+
+(** The four functions assembled for {!Colitur_kernel.Precedence.resolve}. *)
+val rules : (Vocab_of.season, Vocab_of.rank) Precedence.rules
diff --git a/test/test_precedence_of.ml b/test/test_precedence_of.ml
index b947d11..6c50fa9 100644
--- a/test/test_precedence_of.ml
+++ b/test/test_precedence_of.ml
@@ -316,6 +316,27 @@ let test_disposition_never_commemorates () =
Vocab_of.ranks)
Vocab_of.ranks
+let test_admit_is_always_empty () =
+ let cand slug rank =
+ mk ~slug ~rank ~origin:Precedence.Sanctoral () in
+ let observed = cand "of-winner" Vocab_of.Sollemnitas in
+ let temporal = cand "of-feria" Vocab_of.Feria in
+ let losers =
+ [ (cand "of-a" Vocab_of.Festum, Precedence.Ordinary, 70);
+ (cand "of-b" Vocab_of.Memoria_obligatoria, Precedence.Privileged, 100) ] in
+ Alcotest.(check int) "nothing is ever admitted" 0
+ (List.length (Rite_of.Precedence_of.admit ~observed ~temporal losers))
+
+let test_vigil_feast_is_always_none () =
+ List.iter
+ (fun slug ->
+ let c = mk ~slug ~rank:Vocab_of.Sollemnitas ~origin:Precedence.Sanctoral () in
+ Alcotest.(check bool)
+ (Printf.sprintf "%s has no vigil-feast link" slug)
+ true
+ (Rite_of.Precedence_of.vigil_feast c = None))
+ [ "of-nativity-vigil"; "of-nativity"; "of-pentecost"; "of-peter-and-paul" ]
+
let suite =
( "precedence-of",
[ Alcotest.test_case "Tabula part I (entries 1-4)" `Quick test_part1;
@@ -323,5 +344,7 @@ let suite =
Alcotest.test_case "Tabula part III (entries 10-13)" `Quick test_part3;
Alcotest.test_case "band is total over the domain" `Slow test_exhaustive_band_total;
Alcotest.test_case "disposition (Normae n. 60)" `Quick test_disposition;
- Alcotest.test_case "disposition never commemorates" `Quick test_disposition_never_commemorates ]
+ Alcotest.test_case "disposition never commemorates" `Quick test_disposition_never_commemorates;
+ Alcotest.test_case "admit is always empty" `Quick test_admit_is_always_empty;
+ Alcotest.test_case "vigil_feast is always none" `Quick test_vigil_feast_is_always_none ]
@ List.map QCheck_alcotest.to_alcotest [ prop_band_total ] )