aboutsummaryrefslogtreecommitdiff
path: root/lib/kernel/record.ml
blob: 425aad5df332dc154f0ee71cbd3efdfe95a73e2d (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
(* The canonical flat output view (spec §2.4). Rite-parametric types stop here:
   every field is a string, so CSV, JSON and the template engine never see a
   type variable. *)
type t = {
  date : string;
  rite : string;
  season : string;
  week : string;  (** "" when the day is outside a numbered week *)
  weekday : string;
  slug : string;
  rank : string;
  colour : string;
  subject : string;
  names : (string * string) list;
  citations : (string * string) list;
}

let of_temporal ~rite vocab date (t : ('s, 'r) Temporal.t) =
  let cel = t.Temporal.office in
  {
    date = Date.to_iso8601 date;
    rite;
    season = vocab.Vocab.season_to_string t.Temporal.season;
    week = (match t.Temporal.week with Some n -> string_of_int n | None -> "");
    weekday = Date.weekday_to_string t.Temporal.weekday;
    slug = Slug.to_string cel.Celebration.slug;
    rank = vocab.Vocab.rank_to_string cel.Celebration.rank;
    colour = Colour.to_string cel.Celebration.colour;
    subject = Subject.to_string cel.Celebration.subject;
    names = List.map (fun (l, n) -> (Lang.to_string l, n)) (Names.to_list cel.Celebration.names);
    citations =
      List.map (fun c -> (Citation.part_to_string c.Citation.part, c.Citation.reference))
        cel.Celebration.citations;
  }

(* Scalar columns, each with a (name, extractor) pair. Derived from this single
   source ensures headers and to_row cannot drift apart. Names and citations are
   excluded: they are variable-arity and belong to richer encoders in Plan 5. *)
let columns =
  [ ("date",    fun r -> r.date);
    ("rite",    fun r -> r.rite);
    ("season",  fun r -> r.season);
    ("week",    fun r -> r.week);
    ("weekday", fun r -> r.weekday);
    ("slug",    fun r -> r.slug);
    ("rank",    fun r -> r.rank);
    ("colour",  fun r -> r.colour);
    ("subject", fun r -> r.subject);
  ]

let headers = List.map fst columns

let to_row r = List.map (fun (_, get) -> get r) columns