diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-25 19:24:29 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-25 19:24:29 +0200 |
| commit | 4f3af5d6fdc3f5aafe955f88ee9a7788e420b62e (patch) | |
| tree | a8f7b4266a5f5b831141f003540451fce693a518 | |
| parent | 8885c9af2f69b81b9aefcf3ab6c4da641338b71d (diff) | |
| download | colitur-4f3af5d6fdc3f5aafe955f88ee9a7788e420b62e.tar.gz colitur-4f3af5d6fdc3f5aafe955f88ee9a7788e420b62e.zip | |
feat(of): transcribe Tabula part III, completing the table
Entries 10-13. Entry 12 is one undivided row -- the Tabula draws no
universal/proper split for optional memorials, unlike entries 3/4, 7/8 and
10/11 -- so it deliberately does not read the layer.
Entry 13's four clauses need no date arithmetic of their own: every
privileged feria is entries 2 and 9, tested earlier in the chain, so what
reaches the final branch is exactly the residue those clauses name.
Entry 10 uses [not (is_proper layer)], not the brief's original
[is_universal layer]: is_universal was deleted as dead code in Task 2,
because every temporal-origin candidate carries layer = "temporal", never
universal_layer, so a positive is_universal test can never match one --
the same correction entries 3, 5 and 7 already apply.
| -rw-r--r-- | lib/rites/rite_of/precedence_of.ml | 18 | ||||
| -rw-r--r-- | test/test_precedence_of.ml | 51 |
2 files changed, 68 insertions, 1 deletions
diff --git a/lib/rites/rite_of/precedence_of.ml b/lib/rites/rite_of/precedence_of.ml index d777f68..cb15d68 100644 --- a/lib/rites/rite_of/precedence_of.ml +++ b/lib/rites/rite_of/precedence_of.ml @@ -149,4 +149,22 @@ let band (ctx : Vocab_of.season Precedence.context) temporal && (is_late_advent_feria ctx || is_nativity_octave_day ctx || is_lenten_feria ctx) then 90 (* Tabula II.9 *) + else if c.cel.rank = Vocab_of.Memoria_obligatoria && not (is_proper layer) then + 100 (* Tabula III.10 -- universal or temporal-origin, never proper; see the + [is_proper] comment above for why this is not [is_universal] *) + else if c.cel.rank = Vocab_of.Memoria_obligatoria && is_proper layer then + 110 (* Tabula III.11 *) + else if c.cel.rank = Vocab_of.Memoria_ad_libitum then + (* Tabula III.12. ONE undivided row: unlike entries 10/11 (and 3/4, 7/8), + the Tabula draws no universal/proper split for optional memorials, so + [layer] is deliberately not read here. The asymmetry is the source's. *) + 120 + else if temporal && c.cel.rank = Vocab_of.Feria then + (* Tabula III.13, four clauses -- ordinary Advent ferias to 16 December, + Christmas-time ferias from 2 January, paschal ferias after the Octave, + and ferias "per annum". Every privileged feria (entries 2 and 9) is + tested earlier in this chain, so what reaches here is exactly the + residue those four clauses name, and no clause needs its own date + arithmetic. *) + 130 else unclassified diff --git a/test/test_precedence_of.ml b/test/test_precedence_of.ml index 0d2db63..8817fa8 100644 --- a/test/test_precedence_of.ml +++ b/test/test_precedence_of.ml @@ -177,7 +177,56 @@ let test_part2 () = Alcotest.(check int) label expected (Rite_of.Precedence_of.band c cand)) part2_cases +let part3_cases = + [ ( "entry 10: a universal obligatory memorial", + ctx ~iso:"2026-01-21" ~season:Vocab_of.Ordinary_time, + mk ~slug:"of-agnes" ~rank:Vocab_of.Memoria_obligatoria + ~origin:Precedence.Sanctoral (), + 100 ); + ( "entry 11: a proper obligatory memorial", + ctx ~iso:"2026-01-21" ~season:Vocab_of.Ordinary_time, + mk ~layer:"proper:diocese-of-poznan" ~slug:"of-secondary-patron" + ~rank:Vocab_of.Memoria_obligatoria ~origin:Precedence.Sanctoral (), + 110 ); + ( "entry 12: an optional memorial", + ctx ~iso:"2026-01-13" ~season:Vocab_of.Ordinary_time, + mk ~slug:"of-hilary" ~rank:Vocab_of.Memoria_ad_libitum + ~origin:Precedence.Sanctoral (), + 120 ); + ( "entry 12: an optional memorial is entry 12 on a proper layer too", + ctx ~iso:"2026-01-13" ~season:Vocab_of.Ordinary_time, + mk ~layer:"proper:diocese-of-poznan" ~slug:"of-local-optional" + ~rank:Vocab_of.Memoria_ad_libitum ~origin:Precedence.Sanctoral (), + 120 ); + ( "entry 13: an ordinary feria per annum", + ctx ~iso:"2026-07-14" ~season:Vocab_of.Ordinary_time, + mk ~slug:"of-ordinary-time-15-tuesday" ~rank:Vocab_of.Feria + ~origin:Precedence.Temporal (), + 130 ); + ( "entry 13: a Christmas-time feria after 1 January", + ctx ~iso:"2027-01-05" ~season:Vocab_of.Christmas, + mk ~slug:"of-christmas-1-tuesday" ~rank:Vocab_of.Feria + ~origin:Precedence.Temporal (), + 130 ); + ( "entry 13, not 9: an Advent feria on 16 December", + ctx ~iso:"2026-12-16" ~season:Vocab_of.Advent, + mk ~slug:"of-advent-3-wednesday" ~rank:Vocab_of.Feria + ~origin:Precedence.Temporal (), + 130 ); + ( "entry 13: a paschal feria after the Octave", + ctx ~iso:"2026-04-14" ~season:Vocab_of.Easter, + mk ~slug:"of-easter-2-tuesday" ~rank:Vocab_of.Feria + ~origin:Precedence.Temporal (), + 130 ) ] + +let test_part3 () = + List.iter + (fun (label, c, cand, expected) -> + Alcotest.(check int) label expected (Rite_of.Precedence_of.band c cand)) + part3_cases + let suite = ( "precedence-of", [ Alcotest.test_case "Tabula part I (entries 1-4)" `Quick test_part1; - Alcotest.test_case "Tabula part II (entries 5-9)" `Quick test_part2 ] ) + Alcotest.test_case "Tabula part II (entries 5-9)" `Quick test_part2; + Alcotest.test_case "Tabula part III (entries 10-13)" `Quick test_part3 ] ) |
