• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

A Nix-friendly SQLite-enhanced fork of Flitter, a speedrunning split timer for Unix-style terminals


Commit MetaInfo

Revision3247aeb375ae5c49ecaf6ff00059a8b5a96412ce (tree)
Time2022-12-19 09:45:40
AuthorCorbin <cds@corb...>
CommiterCorbin

Log Message

Set up and invoke ocamlformat.

This was less than I expected! ocamlformat has improved greatly.

Change Summary

Incremental Difference

--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,12 @@
1+{ nixpkgs ? import <nixpkgs> {} }:
2+let
3+ inherit (nixpkgs) pkgs;
4+in pkgs.stdenv.mkDerivation {
5+ name = "flitter-dev-env";
6+ buildInputs = with pkgs; [
7+ # working with S-expressions
8+ ocamlPackages.sexp
9+ # maintaining OCaml code
10+ ocamlformat
11+ ];
12+}
--- a/src/big.ml
+++ b/src/big.ml
@@ -2,15 +2,17 @@ open Core
22 open Notty
33
44 let big_font_map =
5- let font = [
6- "00000111112222233333444445555566666777778888899999 !!::..";
7- ".^^. .| .^^. .^^. . | |^^^ .^^ ^^^| .^^. .^^. | ";
8- "| | | .^ .^ |..| |.. |.. ][ ^..^ ^..| | ^ ";
9- "| | | .^ . | | | | | | | | | ^ ^ ";
10- " ^^ ^^^ ^^^^ ^^ ^ ^^^ ^^ ^ ^^ ^^ ^ ^ ";
11- ] in
12-
13- let uchar_of_char =
5+ let font =
6+ [
7+ "00000111112222233333444445555566666777778888899999 !!::..";
8+ ".^^. .| .^^. .^^. . | |^^^ .^^ ^^^| .^^. .^^. | ";
9+ "| | | .^ .^ |..| |.. |.. ][ ^..^ ^..| | ^ ";
10+ "| | | .^ . | | | | | | | | | ^ ^ ";
11+ " ^^ ^^^ ^^^^ ^^ ^ ^^^ ^^ ^ ^^ ^^ ^ ^ ";
12+ ]
13+ in
14+
15+ let uchar_of_char =
1416 let open Caml.Uchar in
1517 function
1618 | '[' -> of_int 0x258C
@@ -25,18 +27,20 @@ let big_font_map =
2527
2628 let extract_char_at start_idx =
2729 let ch = String.get fst_line start_idx in
28- let end_idx = (String.rindex_exn fst_line ch) + 1 in
29- let char_rows = List.map (List.tl_exn font) ~f:(fun line ->
30- let row_str = String.(drop_prefix (prefix line end_idx) start_idx) in
31- let row_list = String.to_list row_str in
32- Array.of_list_map row_list ~f:uchar_of_char
33- ) in
30+ let end_idx = String.rindex_exn fst_line ch + 1 in
31+ let char_rows =
32+ List.map (List.tl_exn font) ~f:(fun line ->
33+ let row_str = String.(drop_prefix (prefix line end_idx) start_idx) in
34+ let row_list = String.to_list row_str in
35+ Array.of_list_map row_list ~f:uchar_of_char)
36+ in
3437
3538 (char_rows, end_idx)
3639 in
3740
3841 let rec map_chars_at map idx =
39- if idx >= String.length fst_line then map else
42+ if idx >= String.length fst_line then map
43+ else
4044 let img, next_idx = extract_char_at idx in
4145 let ch = String.get fst_line idx in
4246 map_chars_at (Map.add_exn map ~key:ch ~data:img) next_idx
@@ -46,6 +50,5 @@ let big_font_map =
4650
4751 let image_of_string attr str =
4852 List.map (String.to_list str) ~f:(fun ch ->
49- List.map (Map.find_exn big_font_map ch) ~f:(I.uchars attr)
50- |> I.vcat
51- ) |> I.hcat
\ No newline at end of file
53+ List.map (Map.find_exn big_font_map ch) ~f:(I.uchars attr) |> I.vcat)
54+ |> I.hcat
--- a/src/colors.ml
+++ b/src/colors.ml
@@ -5,19 +5,17 @@ let color_of_hexstring str =
55 match Color.of_hexstring str with
66 | None -> failwith "Failed to derive color from hexstring"
77 | Some color ->
8- let rgba = Color.to_rgba color in
9- A.rgb_888 ~r:rgba.r ~g:rgba.g ~b:rgba.b
8+ let rgba = Color.to_rgba color in
9+ A.rgb_888 ~r:rgba.r ~g:rgba.g ~b:rgba.b
1010
1111 let color_of_hsl h s l =
1212 let hsl = Color.of_hsl h s l in
1313 let rgba = Color.to_rgba hsl in
1414 A.rgb_888 ~r:rgba.r ~g:rgba.g ~b:rgba.b
1515
16-let default_bg = A.(bg (color_of_hexstring "#2f3542"))
17-let selection_bg = A.(bg (color_of_hexstring "#485460"))
18-
19-let attr_of_hexstring str =
20- A.(fg (color_of_hexstring str) ++ default_bg)
16+let default_bg = A.(bg (color_of_hexstring "#2f3542"))
17+let selection_bg = A.(bg (color_of_hexstring "#485460"))
18+let attr_of_hexstring str = A.(fg (color_of_hexstring str) ++ default_bg)
2119
2220 (* https://flatuicolors.com/palette/cn *)
2321 (* TODO Find better color palette *)
@@ -31,6 +29,8 @@ let label = attr_of_hexstring "#a4b0be"
3129
3230 let rainbow () =
3331 let period = 3. in
34- let h = Float.mod_float (Core_unix.gettimeofday ()) period /. period *. 360. in
32+ let h =
33+ Float.mod_float (Core_unix.gettimeofday ()) period /. period *. 360.
34+ in
3535 let rb = color_of_hsl h 1. 0.7 in
36- A.(fg rb ++ default_bg ++ st bold)
\ No newline at end of file
36+ A.(fg rb ++ default_bg ++ st bold)
--- a/src/display.ml
+++ b/src/display.ml
@@ -9,10 +9,9 @@ let left_pad width i =
99 I.hpad (width - I.width i) 0 i
1010
1111 let center_pad width i =
12- if I.width i > width
13- then I.hcrop 0 (I.width i - width) i
12+ if I.width i > width then I.hcrop 0 (I.width i - width) i
1413 else
15- let pad = (width - I.width i) in
14+ let pad = width - I.width i in
1615 let lpad = pad / 2 in
1716 let rpad = pad - lpad in
1817 I.hpad lpad rpad i
@@ -31,9 +30,10 @@ let preamble timer width =
3130 I.(title <-> category)
3231
3332 let splits_header timer width =
34- let labels = match timer.wr with
35- | Some _ -> ["Delta"; "Sgmt"; "Time"; "WR"]
36- | None -> ["Delta"; "Sgmt"; "Time"]
33+ let labels =
34+ match timer.wr with
35+ | Some _ -> [ "Delta"; "Sgmt"; "Time"; "WR" ]
36+ | None -> [ "Delta"; "Sgmt"; "Time" ]
3737 in
3838
3939 let colored = List.map ~f:(I.string Colors.label) labels in
@@ -58,18 +58,18 @@ let time_status timer split_num =
5858 else
5959 color depends on whether currently ahead and how lead/loss compares to last available lead/loss
6060 *)
61-
62- if Splits.is_gold timer split_num then Gold else
61+ if Splits.is_gold timer split_num then Gold
62+ else
6363 match Splits.ahead_by timer split_num with
6464 | None -> Ahead_gain
65- | Some delta ->
66- match Splits.ahead_by timer (split_num - 1) with
67- | None -> (if delta < 0 then Ahead_gain else Behind_loss)
68- | Some prev_delta -> (
69- if delta < 0
70- then if delta < prev_delta then Ahead_gain else Ahead_loss
71- else if delta > prev_delta then Behind_loss else Behind_gain
72- )
65+ | Some delta -> (
66+ match Splits.ahead_by timer (split_num - 1) with
67+ | None -> if delta < 0 then Ahead_gain else Behind_loss
68+ | Some prev_delta ->
69+ if delta < 0 then
70+ if delta < prev_delta then Ahead_gain else Ahead_loss
71+ else if delta > prev_delta then Behind_loss
72+ else Behind_gain)
7373
7474 let time_color timer split_num =
7575 match time_status timer split_num with
@@ -80,39 +80,39 @@ let time_color timer split_num =
8080 | Gold -> Colors.rainbow ()
8181
8282 let show_delta timer split_num =
83- (* if previous split or behind or
84- (if gold available and segment time avail and seg slower than gold):
83+ (* if previous split or behind or
84+ (if gold available and segment time avail and seg slower than gold):
8585 show
86- else
87- hide
86+ else
87+ hide
8888 *)
8989 match timer.state with
9090 | Idle -> false
91- | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) ->
92- if split_num < Array.length splits then true else
93- (match time_status timer split_num with
94- | Behind_gain | Behind_loss -> true
95- | Ahead_gain | Ahead_loss | Gold ->
96- let sgmt = Splits.segment_time timer split_num in
97- let gold = timer.golds.(split_num).duration in
98- (match sgmt, gold with
99- | Some s, Some g -> s > g
100- | _ -> false
101- )
102- )
91+ | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) -> (
92+ if split_num < Array.length splits then true
93+ else
94+ match time_status timer split_num with
95+ | Behind_gain | Behind_loss -> true
96+ | Ahead_gain | Ahead_loss | Gold -> (
97+ let sgmt = Splits.segment_time timer split_num in
98+ let gold = timer.golds.(split_num).duration in
99+ match (sgmt, gold) with Some s, Some g -> s > g | _ -> false))
103100
104101 let split_row timer width i =
105- let bg_attr = match timer.state with
102+ let bg_attr =
103+ match timer.state with
106104 | Idle | Done _ -> Colors.default_bg
107105 | Timing (splits, _) | Paused (splits, _, _) ->
108- if i = Array.length splits then Colors.selection_bg else Colors.default_bg
106+ if i = Array.length splits then Colors.selection_bg
107+ else Colors.default_bg
109108 in
110109 let uncolored_attr = A.(Colors.text ++ bg_attr) in
111110
112- let curr_split = match timer.state with
111+ let curr_split =
112+ match timer.state with
113113 | Idle -> -1
114114 | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) ->
115- Array.length splits
115+ Array.length splits
116116 in
117117 let show_comparison = i > curr_split in
118118
@@ -120,24 +120,22 @@ let split_row timer width i =
120120
121121 (* Compute the split's ahead/behind time image *)
122122 let delta_image =
123- if show_comparison then
124- I.string uncolored_attr "-"
123+ if show_comparison then I.string uncolored_attr "-"
125124 else
126125 match Splits.ahead_by timer i with
127126 | None -> I.string uncolored_attr "-"
128- | Some delta -> (
129- if not (show_delta timer i) then I.string uncolored_attr "" else
127+ | Some delta ->
128+ if not (show_delta timer i) then I.string uncolored_attr ""
129+ else
130130 let time_str = Duration.to_string_plus delta 1 in
131131 let color = A.(time_color timer i ++ bg_attr) in
132132 I.string color time_str
133- )
134133 in
135134
136135 (* Compute the image of the split's segment time *)
137136 let sgmt_image =
138137 let seg_time =
139- if show_comparison
140- then Splits.archived_segment_time timer i
138+ if show_comparison then Splits.archived_segment_time timer i
141139 else Splits.segment_time timer i
142140 in
143141
@@ -148,50 +146,50 @@ let split_row timer width i =
148146
149147 (* Compute the image of the split's absolute time *)
150148 let time =
151- if show_comparison
152- then Splits.archived_split_time timer i
149+ if show_comparison then Splits.archived_split_time timer i
153150 else Splits.split_time timer i
154151 in
155- let time_str = match time with
156- | Some t -> Duration.to_string t 1
157- | None -> "-"
152+ let time_str =
153+ match time with Some t -> Duration.to_string t 1 | None -> "-"
158154 in
159155 let time_image = I.string uncolored_attr time_str in
160156
161157 (* Compute the image of the WR comparison cell *)
162- let wr_image = match timer.wr with
158+ let wr_image =
159+ match timer.wr with
163160 | None -> None
164- | Some wr_run ->
165- let default_img =
166- match wr_run.splits.(i).time with
167- | Some t -> Some (I.string uncolored_attr (Duration.to_string t 2))
168- | None -> Some (I.string uncolored_attr "-")
169- in
170-
171- if i >= curr_split then default_img else
172-
173- (* Determine how much we're ahead or behind WR *)
174- match timer.state with
175- | Idle -> default_img
176- | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) -> (
177- match splits.(i), wr_run.splits.(i).time with
178- | Some curr_t, Some wr_t ->
179- let delta = curr_t - wr_t in
180- let delta_str = Duration.to_string_plus delta 2 in
181- let delta_color = if delta < 0 then Colors.ahead_gain else Colors.behind_gain in
182- Some (I.string delta_color delta_str)
183- | _ -> Some (I.string uncolored_attr "-")
184- )
161+ | Some wr_run -> (
162+ let default_img =
163+ match wr_run.splits.(i).time with
164+ | Some t -> Some (I.string uncolored_attr (Duration.to_string t 2))
165+ | None -> Some (I.string uncolored_attr "-")
166+ in
167+
168+ if i >= curr_split then default_img
169+ else
170+ (* Determine how much we're ahead or behind WR *)
171+ match timer.state with
172+ | Idle -> default_img
173+ | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) -> (
174+ match (splits.(i), wr_run.splits.(i).time) with
175+ | Some curr_t, Some wr_t ->
176+ let delta = curr_t - wr_t in
177+ let delta_str = Duration.to_string_plus delta 2 in
178+ let delta_color =
179+ if delta < 0 then Colors.ahead_gain else Colors.behind_gain
180+ in
181+ Some (I.string delta_color delta_str)
182+ | _ -> Some (I.string uncolored_attr "-")))
185183 in
186184
187185 (* Combine the three time columns together with proper padding *)
188- let time_cells = match wr_image with
189- | Some wr -> [delta_image; sgmt_image; time_image; wr]
190- | None -> [delta_image; sgmt_image; time_image]
186+ let time_cells =
187+ match wr_image with
188+ | Some wr -> [ delta_image; sgmt_image; time_image; wr ]
189+ | None -> [ delta_image; sgmt_image; time_image ]
191190 in
192191 let time_cols_combined =
193- List.map time_cells ~f:(left_pad time_col_width)
194- |> I.hcat
192+ List.map time_cells ~f:(left_pad time_col_width) |> I.hcat
195193 in
196194
197195 (* Add the split title and background color to fill in the padding *)
@@ -204,87 +202,91 @@ let splits timer width =
204202 |> Array.to_list |> I.vcat
205203
206204 let big_timer timer width =
207- let time, color = match timer.state with
208- | Idle -> 0, Colors.idle
209-
205+ let time, color =
206+ match timer.state with
207+ | Idle -> (0, Colors.idle)
210208 | Timing (splits, start_time) ->
211- let time = Duration.since start_time in
212- let color = time_color timer (Array.length splits) in
213- time, color
214-
209+ let time = Duration.since start_time in
210+ let color = time_color timer (Array.length splits) in
211+ (time, color)
215212 | Paused (splits, start_time, pause_time) ->
216- let time = Duration.between start_time pause_time in
217- let color = time_color timer (Array.length splits) in
218- time, color
219-
213+ let time = Duration.between start_time pause_time in
214+ let color = time_color timer (Array.length splits) in
215+ (time, color)
220216 | Done (splits, _) -> (
221217 let last_split_num = Array.length splits - 1 in
222218 match splits.(last_split_num) with
223219 | None -> failwith "Last split found empty on done"
224220 | Some time -> (
225221 match timer.comparison with
226- | None -> time, Colors.ahead_gain
222+ | None -> (time, Colors.ahead_gain)
227223 | Some comp -> (
228224 match comp.splits.(last_split_num).time with
229225 | None -> failwith "Last split of comparison found empty"
230226 | Some comp_time ->
231- let color = if time < comp_time then Colors.rainbow () else Colors.behind_loss in
232- time, color
233- )
234- )
235- )
227+ let color =
228+ if time < comp_time then Colors.rainbow ()
229+ else Colors.behind_loss
230+ in
231+ (time, color))))
236232 in
237233
238- Duration.to_string time 2
239- |> Big.image_of_string color
240- |> left_pad width
234+ Duration.to_string time 2 |> Big.image_of_string color |> left_pad width
241235
242236 let previous_segment timer width =
243237 let desc_img = I.string Colors.default_bg "Previous Segment" in
244238 let empty_time_img = I.string Colors.default_bg "-" in
245239
246- let time_img = match timer.state with
240+ let time_img =
241+ match timer.state with
247242 | Idle -> empty_time_img
248- | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) ->
249- let curr_split = Array.length splits in
250- let prev_delta = Splits.ahead_by timer (curr_split - 1) in
251- let prev_prev_delta = Splits.ahead_by timer (curr_split - 2) in
252- (match prev_delta, prev_prev_delta with
253- | Some pd, Some ppd ->
254- let diff = pd - ppd in
255- let diff_str = Duration.to_string_plus diff 2 in
256- let color = if diff < 0 then Colors.ahead_gain else Colors.behind_loss in
257- I.string color diff_str
258- | _ -> empty_time_img
259- )
243+ | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) -> (
244+ let curr_split = Array.length splits in
245+ let prev_delta = Splits.ahead_by timer (curr_split - 1) in
246+ let prev_prev_delta = Splits.ahead_by timer (curr_split - 2) in
247+ match (prev_delta, prev_prev_delta) with
248+ | Some pd, Some ppd ->
249+ let diff = pd - ppd in
250+ let diff_str = Duration.to_string_plus diff 2 in
251+ let color =
252+ if diff < 0 then Colors.ahead_gain else Colors.behind_loss
253+ in
254+ I.string color diff_str
255+ | _ -> empty_time_img)
260256 in
261257
262258 join_pad width desc_img time_img
263259
264260 let best_possible_time timer width =
265- let t = match timer.state with
261+ let t =
262+ match timer.state with
266263 | Idle -> Splits.gold_sum timer 0 (Array.length timer.split_names)
267- | Timing (splits, _) | Paused (splits, _, _) ->
268- let curr_split = Array.length splits in
269- let total_splits = Array.length timer.split_names in
270-
271- let future_sob = Splits.gold_sum timer (curr_split + 1) (total_splits) in
272- let curr_gold = (Splits.updated_golds timer).(curr_split).duration in
273- let last_split_time = if curr_split = 0 then Some 0 else splits.(curr_split - 1) in
274- let curr_seg = Splits.segment_time timer curr_split in
275-
276- (match future_sob, curr_gold, last_split_time, curr_seg with
277- | Some future_sob', Some curr_gold', Some last_split_time', Some curr_seg' ->
278- Some (last_split_time' + max curr_seg' curr_gold' + future_sob')
279- | _ -> None
280- )
264+ | Timing (splits, _) | Paused (splits, _, _) -> (
265+ let curr_split = Array.length splits in
266+ let total_splits = Array.length timer.split_names in
267+
268+ let future_sob = Splits.gold_sum timer (curr_split + 1) total_splits in
269+ let curr_gold = (Splits.updated_golds timer).(curr_split).duration in
270+ let last_split_time =
271+ if curr_split = 0 then Some 0 else splits.(curr_split - 1)
272+ in
273+ let curr_seg = Splits.segment_time timer curr_split in
274+
275+ match (future_sob, curr_gold, last_split_time, curr_seg) with
276+ | ( Some future_sob',
277+ Some curr_gold',
278+ Some last_split_time',
279+ Some curr_seg' ) ->
280+ Some (last_split_time' + max curr_seg' curr_gold' + future_sob')
281+ | _ -> None)
281282 | Done (splits, _) -> splits.(Array.length splits - 1)
282283 in
283284
284- let time_img = match t with
285+ let time_img =
286+ match t with
285287 | Some t' ->
286- let time_str = Duration.to_string t' 2 in
287- I.string Colors.text time_str
288+ let time_str = Duration.to_string t' 2 in
289+ I.string Colors.text time_str
288290 | None -> I.string Colors.text "-"
289291 in
290292
@@ -293,7 +295,8 @@ let best_possible_time timer width =
293295
294296 let sob timer width =
295297 let sob_time = Splits.gold_sum timer 0 (Array.length timer.split_names) in
296- let sob_img = match sob_time with
298+ let sob_img =
299+ match sob_time with
297300 | Some sob -> I.string Colors.text (Duration.to_string sob 2)
298301 | None -> I.empty
299302 in
@@ -304,10 +307,9 @@ let sob timer width =
304307 (* Result might be slightly bigger than given size *)
305308 let rec subdivide_space color w h max_size =
306309 if w > max_size || h > max_size then
307- let subspace = subdivide_space color (w / 2 + 1) (h / 2 + 1) max_size in
308- I.((subspace <|> subspace) <-> (subspace <|> subspace))
309- else
310- I.char color ' ' w h
310+ let subspace = subdivide_space color ((w / 2) + 1) ((h / 2) + 1) max_size in
311+ I.(subspace <|> subspace <-> (subspace <|> subspace))
312+ else I.char color ' ' w h
311313
312314 let display timer (w, h) =
313315 (* TODO remedy this Notty bug workaround
@@ -319,28 +321,18 @@ let display timer (w, h) =
319321 a few different terminals (Gnome-terminal, Termite, urxvt, not xterm though)
320322 *)
321323 I.(
322- (
323- preamble timer w <->
324- void w 1 <->
325- splits_header timer w <->
326- splits timer w <->
327- void w 1 <->
328- big_timer timer w <->
329- previous_segment timer w <->
330- sob timer w <->
331- best_possible_time timer w
332- ) </> subdivide_space Colors.default_bg w h 10
333- )
324+ preamble timer w <-> void w 1 <-> splits_header timer w <-> splits timer w
325+ <-> void w 1 <-> big_timer timer w <-> previous_segment timer w
326+ <-> sob timer w <-> best_possible_time timer w
327+ </> subdivide_space Colors.default_bg w h 10)
334328
335329 type t = Notty_unix.Term.t
336330
337-let make () =
338- Notty_unix.Term.create ()
331+let make () = Notty_unix.Term.create ()
339332
340333 let draw term timer =
341334 let open Notty_unix in
342335 let image = display timer (Term.size term) in
343336 Term.image term image
344337
345-let close term =
346- Notty_unix.Term.release term
338+let close term = Notty_unix.Term.release term
--- a/src/duration.ml
+++ b/src/duration.ml
@@ -10,8 +10,8 @@ let hour : t = minute * 60
1010 let day : t = hour * 60
1111
1212 let compiled_re =
13- {|^(?:(?:(?:(\d+):)?(\d+):)?(\d+):)?(\d+)(?:\.(\d{1,3}))?$|}
14- |> Re.Perl.re |> Re.compile
13+ {|^(?:(?:(?:(\d+):)?(\d+):)?(\d+):)?(\d+)(?:\.(\d{1,3}))?$|} |> Re.Perl.re
14+ |> Re.compile
1515
1616 let string_valid = Re.execp compiled_re
1717
@@ -22,36 +22,35 @@ let left_pad_zeros_char_list str size =
2222 prepend (String.to_list str) (size - String.length str)
2323
2424 let left_pad_zeros size str =
25- left_pad_zeros_char_list str size
26- |> String.of_char_list
25+ left_pad_zeros_char_list str size |> String.of_char_list
2726
2827 let of_string str =
2928 match Re.exec_opt compiled_re str with
3029 | None -> None
3130 | Some groups ->
32- let group_strs = Re.Group.all groups in
31+ let group_strs = Re.Group.all groups in
3332
34- let to_int_default x = if String.length x = 0 then 0 else Int.of_string x in
33+ let to_int_default x =
34+ if String.length x = 0 then 0 else Int.of_string x
35+ in
3536
36- let days = group_strs.(1) |> to_int_default in
37- let hours = group_strs.(2) |> to_int_default in
38- let minutes = group_strs.(3) |> to_int_default in
39- let seconds = group_strs.(4) |> to_int_default in
40- let millis = group_strs.(5) |> left_pad_zeros 3 |> to_int_default in
37+ let days = group_strs.(1) |> to_int_default in
38+ let hours = group_strs.(2) |> to_int_default in
39+ let minutes = group_strs.(3) |> to_int_default in
40+ let seconds = group_strs.(4) |> to_int_default in
41+ let millis = group_strs.(5) |> left_pad_zeros 3 |> to_int_default in
4142
42- Some (
43- day * days +
44- hour * hours +
45- minute * minutes +
46- second * seconds +
47- milli * millis
48- )
43+ Some
44+ ((day * days) + (hour * hours) + (minute * minutes) + (second * seconds)
45+ + (milli * millis))
4946
50-let t_of_sexp sexp = match sexp with
47+let t_of_sexp sexp =
48+ match sexp with
5149 | Sexp.List _ -> of_sexp_error "Durations should be strings, not lists" sexp
52- | Sexp.Atom s -> match of_string s with
53- | None -> of_sexp_error "Invalid duration string" sexp
54- | Some d -> d
50+ | Sexp.Atom s -> (
51+ match of_string s with
52+ | None -> of_sexp_error "Invalid duration string" sexp
53+ | Some d -> d)
5554
5655 let to_string_pos duration decimals =
5756 let days = duration / day in
@@ -66,37 +65,31 @@ let to_string_pos duration decimals =
6665 let seconds = duration_minute / second in
6766 let millis = duration_minute % second in
6867
69- let millis_str =
68+ let millis_str =
7069 let zero_padded = left_pad_zeros 3 (Int.to_string millis) in
7170 String.prefix zero_padded decimals
7271 in
73- let seconds_str =
72+ let seconds_str =
7473 let str = Int.to_string seconds in
7574 if duration >= minute then left_pad_zeros 2 str else str
7675 in
7776
7877 let minutes_str =
79- if duration >= hour
80- then (Int.to_string minutes |> left_pad_zeros 2) ^ ":"
81- else if duration >= minute then Int.to_string minutes ^ ":" else ""
78+ if duration >= hour then (Int.to_string minutes |> left_pad_zeros 2) ^ ":"
79+ else if duration >= minute then Int.to_string minutes ^ ":"
80+ else ""
8281 in
8382
8483 let hours_str =
85- if duration >= day
86- then (Int.to_string hours |> left_pad_zeros 2) ^ ":"
87- else if duration >= hour then Int.to_string hours ^ ":" else ""
84+ if duration >= day then (Int.to_string hours |> left_pad_zeros 2) ^ ":"
85+ else if duration >= hour then Int.to_string hours ^ ":"
86+ else ""
8887 in
8988
9089 let days_str = if duration >= day then Int.to_string days ^ ":" else "" in
9190
92- String.concat [
93- days_str;
94- hours_str;
95- minutes_str;
96- seconds_str;
97- ".";
98- millis_str;
99- ]
91+ String.concat
92+ [ days_str; hours_str; minutes_str; seconds_str; "."; millis_str ]
10093
10194 let to_string duration decimals =
10295 if duration < 0 then "-" ^ to_string_pos (-duration) decimals
@@ -108,8 +101,5 @@ let to_string_plus duration decimals =
108101 let str = to_string duration decimals in
109102 if duration >= 0 then "+" ^ str else str
110103
111-let between start finish =
112- (finish -. start) *. 1000. |> Int.of_float
113-
114-let since time_float =
115- between time_float (Core_unix.gettimeofday ())
104+let between start finish = (finish -. start) *. 1000. |> Int.of_float
105+let since time_float = between time_float (Core_unix.gettimeofday ())
--- a/src/event_loop.ml
+++ b/src/event_loop.ml
@@ -17,7 +17,9 @@ let draw_event flitter =
1717
1818 let deadline = flitter.last_draw +. period in
1919 let delay = deadline -. Core_unix.gettimeofday () in
20- let%lwt () = if Float.(delay > 0.) then Lwt_unix.sleep delay else Lwt.return_unit in
20+ let%lwt () =
21+ if Float.(delay > 0.) then Lwt_unix.sleep delay else Lwt.return_unit
22+ in
2123 Lwt.return Draw_tick
2224
2325 let keyboard_event flitter =
@@ -32,143 +34,131 @@ let array_replace arr i value =
3234
3335 let handle_key flitter (t, key_str) =
3436 let timer = flitter.timer in
35- let new_timer = match flitter.timer.state with
37+ let new_timer =
38+ match flitter.timer.state with
3639 | Idle -> (
3740 match key_str with
38- | "space" | "j" -> {
39- timer with
40- state = Timing ([||], t)
41- }
41+ | "space" | "j" -> { timer with state = Timing ([||], t) }
4242 | "q" -> raise Stdlib.Exit
43- | _ -> timer
44- )
45-
43+ | _ -> timer)
4644 | Timing (splits, start_time) -> (
4745 let curr_split = Array.length splits in
4846 match key_str with
49- | "space" | "j" ->
50- let curr_split_time = Some (Duration.between start_time t) in
51- let new_splits = Array.append splits [|curr_split_time|] in
52-
53- let new_state =
54- if Array.length new_splits = Array.length timer.split_names
55- then Done (new_splits, start_time)
56- else Timing (new_splits, start_time)
57- in
58- {timer with state = new_state}
59-
60- | "k" ->
61- let new_state =
62- match curr_split with
63- | 0 -> Idle
64- | 1 -> Timing ([||], start_time)
65- | _ -> Timing ((Array.slice splits 0 (curr_split - 1)), start_time)
66- in
67- {timer with state = new_state}
68-
69- | "backspace" | "delete" -> {timer with state = Paused (splits, start_time, t)}
70-
71- | "d" ->
72- let new_state =
73- if curr_split > 0 then
74- let new_splits = array_replace splits (curr_split - 1) None in
75- Timing (new_splits, start_time)
76- else
77- Idle
78- in
79- {timer with state = new_state}
80-
81- | _ -> timer
82- )
83-
47+ | "space" | "j" ->
48+ let curr_split_time = Some (Duration.between start_time t) in
49+ let new_splits = Array.append splits [| curr_split_time |] in
50+
51+ let new_state =
52+ if Array.length new_splits = Array.length timer.split_names then
53+ Done (new_splits, start_time)
54+ else Timing (new_splits, start_time)
55+ in
56+ { timer with state = new_state }
57+ | "k" ->
58+ let new_state =
59+ match curr_split with
60+ | 0 -> Idle
61+ | 1 -> Timing ([||], start_time)
62+ | _ -> Timing (Array.slice splits 0 (curr_split - 1), start_time)
63+ in
64+ { timer with state = new_state }
65+ | "backspace" | "delete" ->
66+ { timer with state = Paused (splits, start_time, t) }
67+ | "d" ->
68+ let new_state =
69+ if curr_split > 0 then
70+ let new_splits = array_replace splits (curr_split - 1) None in
71+ Timing (new_splits, start_time)
72+ else Idle
73+ in
74+ { timer with state = new_state }
75+ | _ -> timer)
8476 | Paused (splits, start_time, pause_time) -> (
8577 match key_str with
86- | "space" | "j" ->
87- let new_state = Timing (splits, start_time +. t -. pause_time) in
88- {timer with state = new_state}
89-
90- | "backspace" ->
91- let new_timer = {
92- timer with
93- state = Idle;
94- golds = Splits.updated_golds timer;
95- attempts = timer.attempts + 1;
96- } in
97- Loadsave.save new_timer;
98- new_timer
99-
100- | "delete" -> {timer with state = Idle}
101- | _ -> timer
102- )
103-
78+ | "space" | "j" ->
79+ let new_state = Timing (splits, start_time +. t -. pause_time) in
80+ { timer with state = new_state }
81+ | "backspace" ->
82+ let new_timer =
83+ {
84+ timer with
85+ state = Idle;
86+ golds = Splits.updated_golds timer;
87+ attempts = timer.attempts + 1;
88+ }
89+ in
90+ Loadsave.save new_timer;
91+ new_timer
92+ | "delete" -> { timer with state = Idle }
93+ | _ -> timer)
10494 | Done (splits, start_time) -> (
10595 match key_str with
10696 | "space" | "backspace" ->
107- let archived_run = Splits.archive_done_run timer splits in
108- let pb = Splits.updated_pb timer in
109-
110- let new_timer = {
111- timer with
112- state = Idle;
113- golds = Splits.updated_golds timer;
114- attempts = timer.attempts + 1;
115- completed = timer.completed + 1;
116- history = archived_run :: timer.history;
117- pb = pb;
118- comparison = pb;
119- } in
120-
121- Loadsave.save new_timer;
122- new_timer
123-
124- | "delete" -> {timer with state = Idle}
125-
126- | "k" ->
127- let new_splits = if Array.length splits = 1
128- then [||]
129- else Array.(slice splits 0 (length splits - 1))
130- in
131- {timer with state = Timing (new_splits, start_time)}
132-
97+ let archived_run = Splits.archive_done_run timer splits in
98+ let pb = Splits.updated_pb timer in
99+
100+ let new_timer =
101+ {
102+ timer with
103+ state = Idle;
104+ golds = Splits.updated_golds timer;
105+ attempts = timer.attempts + 1;
106+ completed = timer.completed + 1;
107+ history = archived_run :: timer.history;
108+ pb;
109+ comparison = pb;
110+ }
111+ in
112+
113+ Loadsave.save new_timer;
114+ new_timer
115+ | "delete" -> { timer with state = Idle }
116+ | "k" ->
117+ let new_splits =
118+ if Array.length splits = 1 then [||]
119+ else Array.(slice splits 0 (length splits - 1))
120+ in
121+ { timer with state = Timing (new_splits, start_time) }
133122 | "q" -> raise Stdlib.Exit
134- | _ -> timer
135- )
123+ | _ -> timer)
136124 in
137- {flitter with timer = new_timer}
125+ { flitter with timer = new_timer }
138126
139127 let handle_draw flitter =
140128 let draw_time = Core_unix.gettimeofday () in
141129 Display.draw flitter.display flitter.timer;
142- {flitter with last_draw = draw_time}
130+ { flitter with last_draw = draw_time }
143131
144132 let rec handle_events flitter events =
145133 match events with
146- | evt :: remaining_evts -> (
147- let new_flitter = match evt with
134+ | evt :: remaining_evts ->
135+ let new_flitter =
136+ match evt with
148137 | Draw_tick -> handle_draw flitter
149138 | Key keypress -> handle_key flitter keypress
150139 in
151140
152141 handle_events new_flitter remaining_evts
153- )
154-
155142 | [] -> flitter
156143
157144 let make timer =
158145 let%lwt hotkeys_stream = Hotkeys.make_stream () in
159- Lwt.return {
160- timer = timer;
161- display = Display.make ();
162- (* Make sure we're due for a draw *)
163- last_draw = Core_unix.gettimeofday () -. (1. /. draw_rate);
164- hotkeys_stream = hotkeys_stream;
165- }
146+ Lwt.return
147+ {
148+ timer;
149+ display = Display.make ();
150+ (* Make sure we're due for a draw *)
151+ last_draw = Core_unix.gettimeofday () -. (1. /. draw_rate);
152+ hotkeys_stream;
153+ }
166154
167155 let loop flitter =
168156 let rec loop' flitter =
169- let%lwt events = Lwt.npick [(draw_event flitter); (keyboard_event flitter)] in
157+ let%lwt events = Lwt.npick [ draw_event flitter; keyboard_event flitter ] in
170158 match handle_events flitter events with
171159 | new_flitter -> loop' new_flitter
172- | exception Stdlib.Exit -> Display.close flitter.display; Lwt.return ()
160+ | exception Stdlib.Exit ->
161+ Display.close flitter.display;
162+ Lwt.return ()
173163 in
174- loop' flitter
\ No newline at end of file
164+ loop' flitter
--- a/src/flitter.ml
+++ b/src/flitter.ml
@@ -1,8 +1,6 @@
1-let usage =
2- "Usage:\n" ^
3-
4- "flitter <splits_path>\n" ^
5- "Open the splits file pointed to by `splits_path`.\n"
1+let usage =
2+ "Usage:\n" ^ "flitter <splits_path>\n"
3+ ^ "Open the splits file pointed to by `splits_path`.\n"
64
75 let run_event_loop timer =
86 let%lwt event_loop = Event_loop.make timer in
@@ -10,8 +8,7 @@ let run_event_loop timer =
108
119 let run () =
1210 match Sys.argv with
13- | [|_; path|] ->
14- let timer = Loadsave.load path in
15- Lwt_main.run (run_event_loop timer)
16-
17- | _ -> print_string usage
\ No newline at end of file
11+ | [| _; path |] ->
12+ let timer = Loadsave.load path in
13+ Lwt_main.run (run_event_loop timer)
14+ | _ -> print_string usage
--- a/src/hotkeys.ml
+++ b/src/hotkeys.ml
@@ -3,7 +3,8 @@ open Core
33 type keypress = float * string
44 type t = keypress Lwt_stream.t
55
6-let python_detect_keys = {|
6+let python_detect_keys =
7+ {|
78 import time
89 import sys
910 from pynput import keyboard
@@ -35,33 +36,33 @@ with keyboard.Listener(on_press=on_press) as listener:
3536 |}
3637
3738 let stream_of_python python_src =
38- let cmd = "", [|"python3"; "-"|] in
39+ let cmd = ("", [| "python3"; "-" |]) in
3940 let pipe_out_fd, pipe_out_fd_unix = Lwt_unix.pipe_out () in
4041 let () = Lwt_unix.set_close_on_exec pipe_out_fd_unix in
4142 let redir = `FD_move pipe_out_fd in
4243
4344 let py_stream = Lwt_process.pread_lines ~stdin:redir cmd in
4445
45- let%lwt n = Lwt_unix.write_string pipe_out_fd_unix python_src 0 (String.length python_src) in
46- if n < String.length python_src then failwith "Failed to write python to pipe"
47- else
46+ let%lwt n =
47+ Lwt_unix.write_string pipe_out_fd_unix python_src 0
48+ (String.length python_src)
49+ in
50+ if n < String.length python_src then failwith "Failed to write python to pipe"
51+ else
4852 let%lwt () = Lwt_unix.close pipe_out_fd_unix in
4953 Lwt.return py_stream
5054
5155 let make_stream () =
5256 let%lwt str_stream = stream_of_python python_detect_keys in
53- let stream = Lwt_stream.from (fun () ->
54- match%lwt Lwt_stream.get str_stream with
55- | Some str -> (
56- match String.split str ~on:' ' with
57- | time_str :: key_str :: [] ->
58- Lwt.return (Some ((Float.of_string time_str), key_str))
59-
60- | _ -> failwith "Invalid output from Python keypress server"
61-
62- )
63- | None -> Lwt.return None
64- )
57+ let stream =
58+ Lwt_stream.from (fun () ->
59+ match%lwt Lwt_stream.get str_stream with
60+ | Some str -> (
61+ match String.split str ~on:' ' with
62+ | [ time_str; key_str ] ->
63+ Lwt.return (Some (Float.of_string time_str, key_str))
64+ | _ -> failwith "Invalid output from Python keypress server")
65+ | None -> Lwt.return None)
6566 in
6667
67- Lwt.return stream
\ No newline at end of file
68+ Lwt.return stream
--- a/src/loadsave.ml
+++ b/src/loadsave.ml
@@ -4,34 +4,24 @@ open Core
44 type split = {
55 title : string;
66 time : Duration.t;
7- is_gold : bool [@default false];
7+ is_gold : bool; [@default false]
88 }
99 [@@deriving sexp]
1010
1111 (* A gold split. *)
12-type gold = {
13- title : string;
14- duration : Duration.t;
15-}
16-[@@deriving sexp]
17-
18-type archived_run = {
19- attempt : int;
20- splits : split array;
21-}
22-[@@deriving sexp]
12+type gold = { title : string; duration : Duration.t } [@@deriving sexp]
13+type archived_run = { attempt : int; splits : split array } [@@deriving sexp]
2314
2415 type game = {
2516 title : string;
2617 category : string;
2718 attempts : int;
2819 completed : int;
29-
3020 split_names : string array;
31- golds : gold array [@sexp.omit_nil];
32- personal_best : archived_run option [@sexp.option];
33- world_record : archived_run option [@sexp.option];
34- history : archived_run list [@sexp.omit_nil];
21+ golds : gold array; [@sexp.omit_nil]
22+ personal_best : archived_run option; [@sexp.option]
23+ world_record : archived_run option; [@sexp.option]
24+ history : archived_run list; [@sexp.omit_nil]
3525 }
3626 [@@deriving sexp]
3727
@@ -40,56 +30,52 @@ let game_of_sexp sexp =
4030 let num_splits = Array.length game.split_names in
4131 if num_splits = 0 then of_sexp_error "No split names defined" sexp
4232 else
43-
4433 let check_run run name =
45- let pb_ok = match run with
34+ let pb_ok =
35+ match run with
4636 | Some r -> Array.length r.splits = num_splits
4737 | None -> true
4838 in
49- if not pb_ok
50- then of_sexp_error (name ^ " has different number of splits than split_names") sexp
39+ if not pb_ok then
40+ of_sexp_error
41+ (name ^ " has different number of splits than split_names")
42+ sexp
5143 else ()
5244 in
5345
5446 check_run game.personal_best "Personal best";
5547 check_run game.world_record "World record";
5648
57- let history_runs_ok = List.fold game.history ~init:true ~f:(
58- fun all_ok run -> all_ok && Array.length run.splits = num_splits
59- )
49+ let history_runs_ok =
50+ List.fold game.history ~init:true ~f:(fun all_ok run ->
51+ all_ok && Array.length run.splits = num_splits)
6052 in
61- if not history_runs_ok
62- then of_sexp_error "Not all history runs have same number of splits as split_names" sexp
53+ if not history_runs_ok then
54+ of_sexp_error
55+ "Not all history runs have same number of splits as split_names" sexp
6356 else game
6457
6558 let load_golds parsed_game =
66- if Int.equal (Array.length parsed_game.golds) 0 then
59+ if Int.equal (Array.length parsed_game.golds) 0 then
6760 Array.map parsed_game.split_names ~f:(fun name ->
68- {Timer_types.title = name; duration = None}
69- )
70- else
61+ { Timer_types.title = name; duration = None })
62+ else
7163 Array.map parsed_game.golds ~f:(fun seg ->
72- {
73- Timer_types.title = seg.title;
74- duration = Some seg.duration;
75- }
76- )
64+ { Timer_types.title = seg.title; duration = Some seg.duration })
7765
7866 let load_run parsed_run =
79- let splits = Array.map parsed_run.splits ~f:(fun split ->
80- {
81- Timer_types.title = split.title;
82- time = Some split.time;
83- is_gold = split.is_gold;
84- }
85- )
67+ let splits =
68+ Array.map parsed_run.splits ~f:(fun split ->
69+ {
70+ Timer_types.title = split.title;
71+ time = Some split.time;
72+ is_gold = split.is_gold;
73+ })
8674 in
8775
88- {Timer_types.attempt = parsed_run.attempt; splits = splits}
76+ { Timer_types.attempt = parsed_run.attempt; splits }
8977
90-let load_run_opt = function
91- | Some run -> Some (load_run run)
92- | None -> None
78+let load_run_opt = function Some run -> Some (load_run run) | None -> None
9379
9480 let load filepath =
9581 let game = Sexp.load_sexp_conv_exn filepath game_of_sexp in
@@ -103,46 +89,38 @@ let load filepath =
10389 category = game.category;
10490 attempts = game.attempts;
10591 completed = game.completed;
106-
10792 split_names = game.split_names;
108- golds = golds;
109- history = history;
110-
93+ golds;
94+ history;
11195 comparison = pb;
112- pb = pb;
113- wr = wr;
96+ pb;
97+ wr;
11498 state = Idle;
115-
11699 splits_file = filepath;
117100 }
118101
119-let export_run (run : Timer_types.archived_run) =
102+let export_run (run : Timer_types.archived_run) =
120103 {
121104 attempt = run.attempt;
122- splits = Array.map run.splits ~f:(fun split ->
123- {
124- title = split.title;
125- time = (
126- match split.time with
127- | Some t -> t
128- | None -> assert false
129- );
130- is_gold = split.is_gold;
131- }
132- );
133- }
105+ splits =
106+ Array.map run.splits ~f:(fun split ->
107+ {
108+ title = split.title;
109+ time = (match split.time with Some t -> t | None -> assert false);
110+ is_gold = split.is_gold;
111+ });
112+ }
134113
135-let map_run_opt = function
136- | Some run -> Some (export_run run)
137- | None -> None
114+let map_run_opt = function Some run -> Some (export_run run) | None -> None
138115
139116 let save (timer : Timer_types.timer) =
140117 let map_gold (gold : Timer_types.gold) =
141118 {
142119 title = gold.title;
143- duration = match gold.duration with
120+ duration =
121+ (match gold.duration with
144122 | Some duration -> duration
145- | None -> assert false;
123+ | None -> assert false);
146124 }
147125 in
148126
@@ -151,18 +129,19 @@ let save (timer : Timer_types.timer) =
151129
152130 let history = List.map timer.history ~f:export_run in
153131
154- let game = {
155- title = timer.title;
156- category = timer.category;
157- attempts = timer.attempts;
158- completed = timer.completed;
159-
160- split_names = timer.split_names;
161- golds = Array.map timer.golds ~f:map_gold;
162- history = history;
163- personal_best = pb;
164- world_record = wr;
165- } in
132+ let game =
133+ {
134+ title = timer.title;
135+ category = timer.category;
136+ attempts = timer.attempts;
137+ completed = timer.completed;
138+ split_names = timer.split_names;
139+ golds = Array.map timer.golds ~f:map_gold;
140+ history;
141+ personal_best = pb;
142+ world_record = wr;
143+ }
144+ in
166145
167146 let sexp = sexp_of_game game in
168147 let sexp_string = Sexp_pretty.sexp_to_string sexp in
--- a/src/splits.ml
+++ b/src/splits.ml
@@ -2,23 +2,24 @@ open Core
22 open Timer_types
33
44 let split_time timer ?now split_num =
5- if split_num < 0 then Some 0 else
6- let curr_time = match now with Some t -> t | None -> Core_unix.gettimeofday () in
5+ if split_num < 0 then Some 0
6+ else
7+ let curr_time =
8+ match now with Some t -> t | None -> Core_unix.gettimeofday ()
9+ in
710
811 match timer.state with
912 | Idle -> None
10-
1113 | Paused (splits, start_time, pause_time) ->
12- if split_num > Array.length splits then None
13- else if split_num = Array.length splits
14- then Some (Duration.between start_time pause_time)
15- else splits.(split_num)
16-
14+ if split_num > Array.length splits then None
15+ else if split_num = Array.length splits then
16+ Some (Duration.between start_time pause_time)
17+ else splits.(split_num)
1718 | Timing (splits, start_time) | Done (splits, start_time) ->
18- if split_num > Array.length splits then None
19- else if split_num = Array.length splits
20- then Some (Duration.between start_time curr_time)
21- else splits.(split_num)
19+ if split_num > Array.length splits then None
20+ else if split_num = Array.length splits then
21+ Some (Duration.between start_time curr_time)
22+ else splits.(split_num)
2223
2324 let duration timer =
2425 match timer.state with
@@ -26,18 +27,19 @@ let duration timer =
2627 | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) -> (
2728 match split_time timer (Array.length splits) with
2829 | Some t -> t
29- | None -> assert false
30- )
30+ | None -> assert false)
3131
3232 let ahead_by timer ?now split_num =
33- if split_num < 0 then None else
33+ if split_num < 0 then None
34+ else
3435 let split_time = split_time timer ?now split_num in
35- let comp_time = match timer.comparison with
36+ let comp_time =
37+ match timer.comparison with
3638 | None -> None
3739 | Some comp -> comp.splits.(split_num).time
3840 in
3941
40- match split_time, comp_time with
42+ match (split_time, comp_time) with
4143 | Some st, Some ct -> Some (st - ct)
4244 | _ -> None
4345
@@ -45,60 +47,57 @@ let segment_time timer ?now split_num =
4547 let t0 = split_time timer ?now (split_num - 1) in
4648 let t1 = split_time timer ?now split_num in
4749
48- match t0, t1 with
49- | Some t0', Some t1' -> Some (t1' - t0')
50- | _ -> None
50+ match (t0, t1) with Some t0', Some t1' -> Some (t1' - t0') | _ -> None
5151
5252 let current_split timer =
5353 match timer.state with
5454 | Idle -> None
5555 | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) ->
56- Some (Array.length splits)
56+ Some (Array.length splits)
5757
5858 let is_gold timer split_num =
59- match current_split timer, segment_time timer split_num with
59+ match (current_split timer, segment_time timer split_num) with
6060 | Some n, Some seg_time -> (
61- if split_num >= n then false else
61+ if split_num >= n then false
62+ else
6263 match timer.golds.(split_num).duration with
6364 | Some duration -> seg_time < duration
64- | None -> true
65- )
65+ | None -> true)
6666 | _ -> false
6767
6868 let updated_golds timer =
6969 match timer.state with
7070 | Idle -> timer.golds
7171 | Timing (splits, _) | Paused (splits, _, _) | Done (splits, _) ->
72- let seg_durations = Array.mapi splits ~f:(fun i _ ->
73- segment_time timer i
74- ) in
75- let old_durations = Array.map timer.golds ~f:(fun g -> g.duration) in
76-
77- let new_durations = Array.mapi timer.split_names ~f:(fun i _ ->
78- if i >= Array.length splits
79- then old_durations.(i)
80- else
81- match seg_durations.(i), old_durations.(i) with
82- | Some n, Some o -> if n < o then Some n else Some o
83- | Some n, None -> Some n
84- | None, Some o -> Some o
85- | None, None -> None
86- ) in
87-
88- Array.map2_exn timer.split_names new_durations ~f:(fun name dur ->
89- {title = name; duration = dur}
90- )
72+ let seg_durations =
73+ Array.mapi splits ~f:(fun i _ -> segment_time timer i)
74+ in
75+ let old_durations = Array.map timer.golds ~f:(fun g -> g.duration) in
76+
77+ let new_durations =
78+ Array.mapi timer.split_names ~f:(fun i _ ->
79+ if i >= Array.length splits then old_durations.(i)
80+ else
81+ match (seg_durations.(i), old_durations.(i)) with
82+ | Some n, Some o -> if n < o then Some n else Some o
83+ | Some n, None -> Some n
84+ | None, Some o -> Some o
85+ | None, None -> None)
86+ in
87+
88+ Array.map2_exn timer.split_names new_durations ~f:(fun name dur ->
89+ { title = name; duration = dur })
9190
9291 let gold_sum timer start bound =
9392 let gold_array = Array.slice (updated_golds timer) start bound in
9493 Array.fold gold_array ~init:(Some 0) ~f:(fun sum gold ->
95- match sum, gold.duration with
94+ match (sum, gold.duration) with
9695 | Some x, Some y -> Some (x + y)
97- | _ -> None
98- )
96+ | _ -> None)
9997
10098 let archived_split_time run split_num =
101- if split_num < 0 then Some 0 else
99+ if split_num < 0 then Some 0
100+ else
102101 match run.comparison with
103102 | Some comp -> comp.splits.(split_num).time
104103 | None -> None
@@ -106,23 +105,15 @@ let archived_split_time run split_num =
106105 let archived_segment_time run split_num =
107106 let t0 = archived_split_time run (split_num - 1) in
108107 let t1 = archived_split_time run split_num in
109- match t0, t1 with
110- | Some t0', Some t1' -> Some (t1' - t0')
111- | _ -> None
108+ match (t0, t1) with Some t0', Some t1' -> Some (t1' - t0') | _ -> None
112109
113110 let archive_done_run timer splits =
114- let run_splits = Array.mapi timer.split_names ~f:(fun i name ->
115- {
116- title = name;
117- time = splits.(i);
118- is_gold = is_gold timer i;
119- }
120- ) in
121-
122- {
123- attempt = timer.attempts;
124- splits = run_splits;
125- }
111+ let run_splits =
112+ Array.mapi timer.split_names ~f:(fun i name ->
113+ { title = name; time = splits.(i); is_gold = is_gold timer i })
114+ in
115+
116+ { attempt = timer.attempts; splits = run_splits }
126117
127118 let updated_pb timer =
128119 match timer.state with
@@ -132,9 +123,8 @@ let updated_pb timer =
132123 | None -> None
133124 | Some pb_run -> (
134125 let last_idx = Array.length splits - 1 in
135- match splits.(last_idx), pb_run.splits.(last_idx).time with
136- | Some new_t, Some old_t ->
137- if new_t < old_t then Some (archive_done_run timer splits) else timer.pb
138- | _ -> None
139- )
140- )
\ No newline at end of file
126+ match (splits.(last_idx), pb_run.splits.(last_idx).time) with
127+ | Some new_t, Some old_t ->
128+ if new_t < old_t then Some (archive_done_run timer splits)
129+ else timer.pb
130+ | _ -> None))
--- a/src/timer_types.ml
+++ b/src/timer_types.ml
@@ -1,25 +1,13 @@
1-type split = {
2- title : string;
3- time : Duration.t option;
4- is_gold: bool;
5-}
6-
7-type gold = {
8- title : string;
9- duration : Duration.t option;
10-}
11-
12-type archived_run = {
13- attempt : int;
14- splits : split array;
15-}
16-
1+type split = { title : string; time : Duration.t option; is_gold : bool }
2+type gold = { title : string; duration : Duration.t option }
3+type archived_run = { attempt : int; splits : split array }
174 type live_splits = Duration.t option array
185
19-type timer_state =
6+type timer_state =
207 | Idle
218 | Timing of live_splits * float (* splits * start time *)
22- | Paused of live_splits * float * float (* splits * start time * paused time *)
9+ | Paused of
10+ live_splits * float * float (* splits * start time * paused time *)
2311 | Done of live_splits * float (* completed splits * start time *)
2412
2513 (* Most of timer state is bundled together in this single package.
@@ -30,15 +18,12 @@ type timer = {
3018 category : string;
3119 attempts : int;
3220 completed : int;
33-
3421 split_names : string array;
3522 golds : gold array;
3623 history : archived_run list;
3724 comparison : archived_run option;
3825 pb : archived_run option;
3926 wr : archived_run option;
40-
4127 state : timer_state;
42-
4328 splits_file : string;
44-}
\ No newline at end of file
29+}