josie / alder-tools

Plot: correct nvtop step-glyph pairing (fall ╮╰, rise ╭╯ via step_glyphs); ring glyph tests

d9c227b271c941d0a244f033bfbc0d5b5c7c5212
josie <administrator@josie-c.com> · 2026-08-30T13:31 · browse files at this commit

parents: 3cbad50

diff --git a/src/plot.rs b/src/plot.rs
index 2ef0aa8..225482a 100644
--- a/src/plot.rs
+++ b/src/plot.rs
@@ -58,6 +58,19 @@ fn levels(samples: &[f64], max: f64, rows: usize) -> Vec<usize> {
         .collect()
 }
 
+/// nvtop corner convention for one column where the level steps from
+/// `prev` to `now` (row numbers; smaller = higher on screen):
+/// falling value (line steps down screen): `╮` at prev (open left,
+/// toward the incoming line) + `╰` at now (open right, toward the
+/// outgoing line); rising value: `╭` at now + `╯` at prev.
+fn step_glyphs(prev: usize, now: usize) -> (usize, usize, char, char) {
+    if prev < now {
+        (prev, now, '╮', '╰') // falling on screen
+    } else {
+        (now, prev, '╭', '╯') // rising on screen
+    }
+}
+
 pub fn render(f: &mut Frame, area: Rect, ring: &Ring, window_ticks: usize, max: f64, color: Color, marker_row: Option<u16>) {
     if area.width == 0 || area.height == 0 || max <= 0.0 {
         return;
@@ -96,12 +109,17 @@ pub fn render(f: &mut Frame, area: Rect, ring: &Ring, window_ticks: usize, max:
         if prev_l == l {
             set(l, c, '─', st);
         } else {
-            // Value rise = row number falls (top row is max), so
-            // prev_l > l means the line steps up on screen.
-            let (upper, lower) = if prev_l < l { (l, prev_l) } else { (prev_l, l) };
-            set(upper, c, '╮', st);
-            set(lower, c, '╰', st);
-            for r in upper + 1..lower {
+            // nvtop corner convention: a step connects the previous row
+            // (open side toward the incoming line) to the new row (open
+            // side toward the outgoing line).
+            //   falling value = line steps DOWN screen (prev above, new
+            //   below): top cell '╮' opens left, bottom cell '╭' opens
+            //   right. Rising value (line steps UP screen): top '╭',
+            //   bottom '╯'.
+            let (top, bot, top_ch, bot_ch) = step_glyphs(prev_l, l);
+            set(top, c, top_ch, st);
+            set(bot, c, bot_ch, st);
+            for r in top + 1..bot {
                 set(r, c, '│', st);
             }
         }
@@ -127,4 +145,36 @@ pub fn render(f: &mut Frame, area: Rect, ring: &Ring, window_ticks: usize, max:
         })
         .collect();
     f.render_widget(ratatui::text::Text::from(lines), area);
-}
\ No newline at end of file
+}
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn levels_map_value_to_rows() {
+        assert_eq!(levels(&[10.0, 0.0], 10.0, 5), [0, 4]);
+        assert_eq!(levels(&[5.0], 10.0, 5), [2]);
+    }
+
+    #[test]
+    fn falling_step_uses_drop_glyphs() {
+        // prev row 1, now row 3 = value fell -> '╮' top, '╰' bottom
+        assert_eq!(step_glyphs(1, 3), (1, 3, '╮', '╰'));
+        // prev row 3, now row 1 = value rose -> '╭' top, '╯' bottom
+        assert_eq!(step_glyphs(3, 1), (1, 3, '╭', '╯'));
+    }
+
+    #[test]
+    fn ring_window_and_wrap() {
+        let mut r = Ring::new(4);
+        for v in 1..=6 {
+            r.push(v as f64);
+        }
+        // wrapped: holds 3..6 (capacity 4)
+        let got: Vec<f64> = r.samples_window(4).collect();
+        assert_eq!(got, vec![3.0, 4.0, 5.0, 6.0]);
+        let got2: Vec<f64> = r.samples_window(2).collect();
+        assert_eq!(got2, vec![5.0, 6.0]);
+        assert_eq!(r.max_window(2), 6.0);
+    }
+}