1 import Base 2 import ../json.bend as Json 3 import ../clock.bend as Clock 4 5 # Reading numbers and stamps out of the JSON files the dashboard follows. 6 7 def sel(+c: Bool, +x: U32, +y: U32) -> U32: 8 match c: 9 case True{}: 10 x 11 case False{}: 12 y 13 14 def 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. 22 def frac_centi(+f: String) -> Maybe<&2, U32>: 23 U32.read(String.take(f ++ "00", 2n)) 24 25 def 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 32 def 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. 42 def centi_text(+t: String) -> Maybe<&2, U32>: 43 centi_parts(String.split(t, '.')) 44 45 def 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 52 def 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 59 def centi_at(+key: String, +j: Json.Json) -> Maybe<&2, U32>: 60 centi_at2(Json.get(key, j)) 61 62 def 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. 70 def 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 77 def 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 84 def secs_at(+key: String, +j: Json.Json) -> Maybe<&2, U32>: 85 secs_at2(Json.get(key, j)) 86 87 def 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 94 def 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 101 def iso_at(+key: String, +j: Json.Json) -> Maybe<&2, U32>: 102 iso_at2(Json.get(key, j)) 103 104 def uint_of(+j: Json.Json) -> Maybe<&2, U32>: 105 Json.as_u32(j) 106 107 def 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 114 def uint_at(+key: String, +j: Json.Json) -> Maybe<&2, U32>: 115 uint_at2(Json.get(key, j)) 116 117 def str_or(+m: Maybe<&2, String>, +d: String) -> String: 118 match m: 119 case None{}: 120 d 121 case Some{s}: 122 s 123 124 def 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 131 def str_at(+key: String, +j: Json.Json) -> String: 132 str_or(opt_json_s(Json.get(key, j)), "") 133 134 def null_json() -> Json.Json: 135 Json.JNull{} 136 137 # A parsed value, JSON null when the text does not parse. 138 def 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 145 def parse_text(+t: String) -> Json.Json: 146 parsed(Json.parse(t)) 147 148 def 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 155 def get_or_null(+key: String, +j: Json.Json) -> Json.Json: 156 from_opt(Json.get(key, j))