aboutsummaryrefslogtreecommitdiff
path: root/nim/logger.nim
diff options
context:
space:
mode:
authoreuxane2025-02-08 22:41:27 +0100
committereuxane2025-02-08 23:34:38 +0100
commitbda07906d1851f95bfc25f0bfc43a42ced8d48b2 (patch)
treea97f4a5ff7570a1f6d5da3fa8cbd0a215d3b9064 /nim/logger.nim
parent93d00382d3a8f4a89674c60207d6b797bf0d0b99 (diff)
downloadtickwatch-bda07906d1851f95bfc25f0bfc43a42ced8d48b2.tar.gz
repo: move nim sources into subdir
Diffstat (limited to 'nim/logger.nim')
-rw-r--r--nim/logger.nim92
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
5import std/sugar
6import std/math
7import std/unicode
8import std/times
9import std/os
10
11
12const
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
20type Scale* = proc(val: float): float {.noSideEffect.}
21
22proc 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
27proc indicator*(symbols: seq[Rune], min, max, val: int, scale: Scale): Rune =
28 symbols.indicator(min.float, max.float, val.float, scale)
29
30func millisecond(t: DateTime): int =
31 t.nanosecond div (1_000_000)
32
33func msUntilNextSec(t: DateTime): int =
34 1000 - t.millisecond + 1
35
36proc puts(f: File, s: string) =
37 f.write s
38 f.flushFile
39
40proc puts(f: File, r: Rune) =
41 f.puts r.toUTF8
42
43func formatTimestampDateTime*(dt: DateTime): string =
44 dt.format(TIMESTAMP_FORMAT)
45
46func formatTimestampUnix*(dt: DateTime): string =
47 ($dt.toTime.toUnix) & " "
48
49func formatTimestampNone*(dt: DateTime): string =
50 ""
51
52proc 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
79proc flushAndQuit*() {.noconv.} =
80 stdout.puts "\n"
81 quit(0)
82
83
84when 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