1. Yaron Minsky
  2. screentime-monitor

Source

screentime-monitor / rule.ml

open Core.Std

module Name : Identifiable = String

module T = struct
  type t =
    { name       : Name.t
    ; days       : Day_of_week.t list
    ; categories : Category.t Blang.t
    ; limit      : Time.Span.t
    }
  with sexp, bin_io, compare, fields
end
include Sexpable.To_stringable(T)
include T

let check (t:t) daylogs =
  let relevant_span =
    let days = Day_of_week.Set.of_list t.days in
    List.fold daylogs ~init:Time.Span.zero ~f:(fun acc (date,daylog) ->
      if not (Set.mem days (Date.day_of_week date)) then acc
      else
        Map.fold (Daylog.Closed.span_map daylog) ~init:acc
          ~f:(fun ~key:cat ~data:span acc ->
            let matches =
              Blang.eval t.categories (fun cat' -> Category.(=) cat' cat)
            in
            if not matches then acc
            else Time.Span.(+) acc span))
  in
  let excess = Time.Span.(relevant_span - t.limit) in
  if Time.Span.(excess > Time.Span.zero) then `Exceeded excess else `Ok

include Comparable.Make_binable(T)

module List = struct
  type nonrec t = t list with sexp, bin_io

  let t_of_sexp sexp =
    let rules = t_of_sexp sexp in
    let names = List.map rules ~f:(fun r -> r.name) in
    match List.find_a_dup names with
    | Some dup -> of_sexp_error ("Duplicate name found :" ^ Name.to_string dup) sexp
    | None -> rules
end