monitoring kit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#![feature(iter_array_chunks, portable_simd)]
use anyhow::{ensure, Result};
use comat::cwrite;
use cpu::*;
use grapher::{truncwrite, Grapher};
use std::array;
use std::convert::identity;
use std::io::Write;
use std::io::{stdout, Read};
use std::thread::sleep;
use std::time::Duration;
use termion::color::*;
use termion::cursor::Hide;
use termion::raw::IntoRawMode;
use termion::screen::IntoAlternateScreen;
use termion::{async_stdin, clear, cursor, style};

fn main() -> Result<()> {
    fn inter([a, b, c]: [f32; 3], [d, e, f]: [f32; 3], fc: f32) -> [f32; 3] {
        [a + (d - a) * fc, b + (e - b) * fc, c + (f - c) * fc]
    }

    let info = CpuInfo::read()?;
    let core = std::env::args()
        .nth(1)
        .and_then(|x| x.parse::<u64>().ok())
        .map_or(ViewCore::All(info.count), ViewCore::One);
    CORE.set(core).unwrap();
    match core {
        ViewCore::One(x) => ensure!(x < info.count, "not enough cores"),
        _ => (),
    }
    let mut t = temps()?;

    let mut g = Grapher::new()?;
    g.push_point(t.read()? / 105.0);

    let mut d = 0.1;

    let mut stdout = stdout().into_raw_mode()?.into_alternate_screen()?;
    let mut stdin = async_stdin();
    write!(stdout, "{}{}{}", Hide, clear::All, style::Reset).unwrap();

    'out: loop {
        let (_, h) = termion::terminal_size()?;

        let mut key = 0;
        while stdin.read(array::from_mut(&mut key)).unwrap() != 0 {
            match key {
                b'q' => break 'out,
                b'+' => d = (d + 0.1f32).min(1.0),
                b'-' if d >= 0.2 => d -= 0.1,
                b'-' if d >= 0.02 => d -= 0.01,
                b'-' => d = 0.00833,
                _ => (),
            }
        }

        g.draw(
            |y| {
                Some(
                    inter(
                        [228, 197, 63].map(|x| x as f32 / 255.0),     // yellow
                        [0x5c, 0xc7, 0xdd].map(|x| x as f32 / 255.0), // blue
                        y as f32 / (h - 1) as f32,
                    )
                    .map(|x| (x * 255.0) as u8),
                )
            },
            identity,
        )?;

        write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
        let name = &*info.name;
        let speed = speed()?;
        let temp = t.read()?;
        let fps = (1f32 / d).round();
        let core = if !name.contains("Ryzen") {
            core.to_string() + " "
        } else {
            "".to_string()
        };
        truncwrite!(g.buffer," {fps}fps ──── {name} {core}@ {speed:.2} GHz ──── \u{1b}[0;34;31m{temp:.0}\u{1b}[0m °C",)?;
        stdout.write_all(&g.buffer)?;
        stdout.flush()?;

        g.push_point(temp / 105.);

        sleep(Duration::from_secs_f32(d));
    }
    println!("\x1B[?7l");
    Ok(())
}