diff options
author | euxane | 2025-02-08 22:41:27 +0100 |
---|---|---|
committer | euxane | 2025-02-08 23:34:38 +0100 |
commit | bda07906d1851f95bfc25f0bfc43a42ced8d48b2 (patch) | |
tree | a97f4a5ff7570a1f6d5da3fa8cbd0a215d3b9064 /nim/logger.nim | |
parent | 93d00382d3a8f4a89674c60207d6b797bf0d0b99 (diff) | |
download | tickwatch-bda07906d1851f95bfc25f0bfc43a42ced8d48b2.tar.gz |
repo: move nim sources into subdir
Diffstat (limited to 'nim/logger.nim')
-rw-r--r-- | nim/logger.nim | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/nim/logger.nim b/nim/logger.nim new file mode 100644 index 0000000..48aedf2 --- /dev/null +++ b/nim/logger.nim | |||
@@ -0,0 +1,92 @@ | |||
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 | func formatTimestampDateTime*(dt: DateTime): string = | ||
44 | dt.format(TIMESTAMP_FORMAT) | ||
45 | |||
46 | func formatTimestampUnix*(dt: DateTime): string = | ||
47 | ($dt.toTime.toUnix) & " " | ||
48 | |||
49 | func formatTimestampNone*(dt: DateTime): string = | ||
50 | "" | ||
51 | |||
52 | proc loop*( | ||
53 | probe: (timeout: Duration) -> int, | ||
54 | getSymbol: (int) -> Rune, | ||
55 | timestampHeader: (DateTime) -> string, | ||
56 | ) = | ||
57 | while true: | ||
58 | stdout.puts timestampHeader(now()) | ||
59 | |||
60 | for tick in 0..<60: | ||
61 | let t = now() | ||
62 | if tick < t.second: | ||
63 | stdout.puts SKIPPED_SYMBOL | ||
64 | continue | ||
65 | |||
66 | let timeout = initDuration(milliseconds = t.msUntilNextSec) | ||
67 | try: | ||
68 | let val = probe(timeout) | ||
69 | stdout.puts getSymbol(val) | ||
70 | except CatchableError: | ||
71 | stdout.puts UNKNOWN_SYMBOL | ||
72 | |||
73 | let tAfter = now() | ||
74 | if tAfter < t + timeout: | ||
75 | sleep(tAfter.msUntilNextSec) | ||
76 | |||
77 | stdout.puts "\n" | ||
78 | |||
79 | proc flushAndQuit*() {.noconv.} = | ||
80 | stdout.puts "\n" | ||
81 | quit(0) | ||
82 | |||
83 | |||
84 | when defined(test): | ||
85 | import std/unittest | ||
86 | import std/sequtils | ||
87 | |||
88 | suite "logger": | ||
89 | test "indicator value": | ||
90 | proc id(val: float): float = val | ||
91 | let indics = (0..30).mapIt(NUMERIC_SYMBOLS.indicator(5, 20, it, id)) | ||
92 | check indics.deduplicate(isSorted = true) == NUMERIC_SYMBOLS | ||