tui/num.bend

cswap-bend-cli@0.1.0.0 · 156 lines · 27 definitions

1import Base
2import cswap-bend-cli@0.1.0.0/json.bend as Json
3import cswap-bend-cli@0.1.0.0/clock.bend as Clock
4
5# Reading numbers and stamps out of the JSON files the dashboard follows.
6
7def sel(+c: Bool, +x: U32, +y: U32) -> U32:
8  match c:
9    case True{}:
10      x
11    case False{}:
12      y
13
14def read_or(+m: Maybe<&2, U32>, +d: U32) -> U32:
15  match m:
16    case None{}:
17      d
18    case Some{x}:
19      x
20
21# Two fraction digits, padded: "5" -> 50, "07" -> 7, "555" -> 55.
22def frac_centi(+f: String) -> Maybe<&2, U32>:
23  U32.read(String.take(f ++ "00", 2n))
24
25def centi_join(+i: Maybe<&2, U32>, +f: Maybe<&2, U32>) -> Maybe<&2, U32>:
26  match i f:
27    case Some{a} Some{b}:
28      Some{(a * 100 + b : U32)}
29    case _ _:
30      None{}
31
32def centi_parts(+ps: List<&2, String>) -> Maybe<&2, U32>:
33  match ps:
34    case Con{i, Nil{}}:
35      centi_join(U32.read(i), Some{0})
36    case Con{i, Con{f, Nil{}}}:
37      centi_join(U32.read(i), frac_centi(f))
38    case _:
39      None{}
40
41# "47" -> 4700, "47.5" -> 4750, "47.555" -> 4755; anything else is None.
42def centi_text(+t: String) -> Maybe<&2, U32>:
43  centi_parts(String.split(t, '.'))
44
45def centi_of(+j: Json.Json) -> Maybe<&2, U32>:
46  match j:
47    case Json.JNum{t}:
48      centi_text(t)
49    case _:
50      None{}
51
52def centi_at2(+m: Maybe<&2, Json.Json>) -> Maybe<&2, U32>:
53  match m:
54    case None{}:
55      None{}
56    case Some{x}:
57      centi_of(x)
58
59def centi_at(+key: String, +j: Json.Json) -> Maybe<&2, U32>:
60  centi_at2(Json.get(key, j))
61
62def secs_parts(+ps: List<&2, String>) -> Maybe<&2, U32>:
63  match ps:
64    case Con{i, t}:
65      U32.read(i)
66    case Nil{}:
67      None{}
68
69# Whole seconds of a JSON number: "1792740000.1" -> 1792740000.
70def secs_of(+j: Json.Json) -> Maybe<&2, U32>:
71  match j:
72    case Json.JNum{t}:
73      secs_parts(String.split(t, '.'))
74    case _:
75      None{}
76
77def secs_at2(+m: Maybe<&2, Json.Json>) -> Maybe<&2, U32>:
78  match m:
79    case None{}:
80      None{}
81    case Some{x}:
82      secs_of(x)
83
84def secs_at(+key: String, +j: Json.Json) -> Maybe<&2, U32>:
85  secs_at2(Json.get(key, j))
86
87def iso_of(+j: Json.Json) -> Maybe<&2, U32>:
88  match j:
89    case Json.JStr{s}:
90      Clock.parse_iso8601(s)
91    case _:
92      None{}
93
94def iso_at2(+m: Maybe<&2, Json.Json>) -> Maybe<&2, U32>:
95  match m:
96    case None{}:
97      None{}
98    case Some{x}:
99      iso_of(x)
100
101def iso_at(+key: String, +j: Json.Json) -> Maybe<&2, U32>:
102  iso_at2(Json.get(key, j))
103
104def uint_of(+j: Json.Json) -> Maybe<&2, U32>:
105  Json.as_u32(j)
106
107def uint_at2(+m: Maybe<&2, Json.Json>) -> Maybe<&2, U32>:
108  match m:
109    case None{}:
110      None{}
111    case Some{x}:
112      uint_of(x)
113
114def uint_at(+key: String, +j: Json.Json) -> Maybe<&2, U32>:
115  uint_at2(Json.get(key, j))
116
117def str_or(+m: Maybe<&2, String>, +d: String) -> String:
118  match m:
119    case None{}:
120      d
121    case Some{s}:
122      s
123
124def opt_json_s(+m: Maybe<&2, Json.Json>) -> Maybe<&2, String>:
125  match m:
126    case None{}:
127      None{}
128    case Some{j}:
129      Json.as_string(j)
130
131def str_at(+key: String, +j: Json.Json) -> String:
132  str_or(opt_json_s(Json.get(key, j)), "")
133
134def null_json() -> Json.Json:
135  Json.JNull{}
136
137# A parsed value, JSON null when the text does not parse.
138def parsed(+r: Result<&2, &2, String, Json.Json>) -> Json.Json:
139  match r:
140    case Done{j}:
141      j
142    case Fail{e}:
143      Json.JNull{}
144
145def parse_text(+t: String) -> Json.Json:
146  parsed(Json.parse(t))
147
148def from_opt(+m: Maybe<&2, Json.Json>) -> Json.Json:
149  match m:
150    case None{}:
151      Json.JNull{}
152    case Some{j}:
153      j
154
155def get_or_null(+key: String, +j: Json.Json) -> Json.Json:
156  from_opt(Json.get(key, j))