diff options
author | euxane | 2024-11-24 17:17:02 +0100 |
---|---|---|
committer | euxane | 2024-11-24 17:17:02 +0100 |
commit | a41641398d09f8457a33445b73a1a402c08c87cd (patch) | |
tree | f6527d03ef2e8ceb23527074c21541ae230af557 | |
parent | 5c49ffa36145b63bd6415af27ac6fee6b8dd5fe3 (diff) | |
download | tickwatch-a41641398d09f8457a33445b73a1a402c08c87cd.tar.gz |
logger: add module
-rw-r--r-- | logger.nim | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/logger.nim b/logger.nim new file mode 100644 index 0000000..a4d90a0 --- /dev/null +++ b/logger.nim | |||
@@ -0,0 +1,79 @@ | |||
1 | # tickwatch | ||
2 | # Author: Euxane TRAN-GIRARD | ||
3 | # Licence: EUPL-1.2 | ||
4 | |||
5 | import std/sugar | ||
6 | import std/math | ||
7 | import std/unicode | ||
8 | import std/times | ||
9 | import std/os | ||
10 | |||
11 | |||
12 | const | ||
13 | TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mmZZZ " | ||
14 | SKIPPED_SYMBOL = "." | ||
15 | UNKNOWN_SYMBOL = "!" | ||
16 | NUMERIC_SYMBOLS* = "123456789".toRunes | ||
17 | UNICODE_SYMBOLS* = "_▁▂▃▄▅▆▇█".toRunes | ||
18 | |||
19 | |||
20 | type Scale* = proc(val: float): float {.noSideEffect.} | ||
21 | |||
22 | proc indicator(symbols: seq[Rune], min, max, val: float, scale: Scale): Rune = | ||
23 | let division = scale(max - min) / float(symbols.len) | ||
24 | let bucket = int(scale(val - min) / division) | ||
25 | symbols[bucket.clamp(0, symbols.len - 1)] | ||
26 | |||
27 | proc indicator*(symbols: seq[Rune], min, max, val: int, scale: Scale): Rune = | ||
28 | symbols.indicator(min.float, max.float, val.float, scale) | ||
29 | |||
30 | func millisecond(t: DateTime): int = | ||
31 | t.nanosecond div (1_000_000) | ||
32 | |||
33 | func msUntilNextSec(t: DateTime): int = | ||
34 | 1000 - t.millisecond + 1 | ||
35 | |||
36 | proc puts(f: File, s: string) = | ||
37 | f.write s | ||
38 | f.flushFile | ||
39 | |||
40 | proc puts(f: File, r: Rune) = | ||
41 | f.puts r.toUTF8 | ||
42 | |||
43 | proc loop*(probe: (timeout: Duration) -> int, getSymbol: (int) -> Rune) = | ||
44 | while true: | ||
45 | stdout.puts now().format(TIMESTAMP_FORMAT) | ||
46 | |||
47 | for tick in 0..<60: | ||
48 | let t = now() | ||
49 | if tick < t.second: | ||
50 | stdout.puts SKIPPED_SYMBOL | ||
51 | continue | ||
52 | |||
53 | let timeout = initDuration(milliseconds = t.msUntilNextSec) | ||
54 | try: | ||
55 | let val = probe(timeout) | ||
56 | stdout.puts getSymbol(val) | ||
57 | except CatchableError: | ||
58 | stdout.puts UNKNOWN_SYMBOL | ||
59 | |||
60 | let tAfter = now() | ||
61 | if tAfter < t + timeout: | ||
62 | sleep(tAfter.msUntilNextSec) | ||
63 | |||
64 | stdout.puts "\n" | ||
65 | |||
66 | proc flushAndQuit*() {.noconv.} = | ||
67 | stdout.puts "\n" | ||
68 | quit(0) | ||
69 | |||
70 | |||
71 | when defined(test): | ||
72 | import std/unittest | ||
73 | import std/sequtils | ||
74 | |||
75 | suite "logger": | ||
76 | test "indicator value": | ||
77 | proc id(val: float): float = val | ||
78 | let indics = (0..30).mapIt(NUMERIC_SYMBOLS.indicator(5, 20, it, id)) | ||
79 | check indics.deduplicate(isSorted = true) == NUMERIC_SYMBOLS | ||