add fancy progress bar :D
This commit is contained in:
parent
04197d4256
commit
517a64156a
|
@ -3,7 +3,7 @@ use rand::RngCore as _;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{atomic, mpsc, Arc};
|
use std::sync::{atomic, mpsc, Arc};
|
||||||
use std::time::Duration;
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use fish::bot;
|
use fish::bot;
|
||||||
use tidepool::{cli, config, output, sim};
|
use tidepool::{cli, config, output, sim};
|
||||||
|
@ -75,14 +75,21 @@ fn single(args: cli::SingleRun) -> Result<()> {
|
||||||
tracing::debug!("heartbeat");
|
tracing::debug!("heartbeat");
|
||||||
}
|
}
|
||||||
Msg::Status(_id, status) => {
|
Msg::Status(_id, status) => {
|
||||||
if !args.io.quiet {
|
if exit_early.load(atomic::Ordering::Relaxed) {
|
||||||
let ps = status.pieces;
|
continue;
|
||||||
let ll = status.lines_left;
|
|
||||||
let pps = ps as f64 / status.time.as_secs_f64();
|
|
||||||
eprintln!("#{ps}, {ll} lines left, {pps:.2} pps");
|
|
||||||
}
|
}
|
||||||
|
write_progress_bar(
|
||||||
|
&args.io,
|
||||||
|
status.pieces,
|
||||||
|
status.lines_left,
|
||||||
|
config.game.goal,
|
||||||
|
status.time,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Msg::Done(_id, output) => {
|
Msg::Done(_id, output) => {
|
||||||
|
// dropping rx early does two things here: 1) removing any of the 'break's
|
||||||
|
// in this block become a compile error, 2) interrupts will not be able to
|
||||||
|
// be sent so the ctrl-c handler will abort the program
|
||||||
std::mem::drop(rx);
|
std::mem::drop(rx);
|
||||||
|
|
||||||
if output.cleared < config.game.goal {
|
if output.cleared < config.game.goal {
|
||||||
|
@ -144,6 +151,44 @@ fn write_output(io_args: &cli::IoArgs, path: Option<&Path>, output: &output::Out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_progress_bar(
|
||||||
|
io_args: &cli::IoArgs,
|
||||||
|
pieces: usize,
|
||||||
|
lines_left: usize,
|
||||||
|
goal: usize,
|
||||||
|
time: Duration,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
if io_args.quiet {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let width = 40; // TODO: get terminal size?
|
||||||
|
let cleared = goal - lines_left;
|
||||||
|
let pps = pieces as f64 / time.as_secs_f64().max(0.001);
|
||||||
|
let pace = pieces * 100 / cleared.max(1);
|
||||||
|
|
||||||
|
let writer = std::io::stderr().lock();
|
||||||
|
let mut writer = std::io::BufWriter::new(writer);
|
||||||
|
write!(writer, "\r[")?;
|
||||||
|
for i in 0..width {
|
||||||
|
if goal * i <= cleared * (width - 1) {
|
||||||
|
write!(writer, "#")
|
||||||
|
} else {
|
||||||
|
write!(writer, " ")
|
||||||
|
}?;
|
||||||
|
}
|
||||||
|
write!(
|
||||||
|
writer,
|
||||||
|
"] {cleared}/{goal} #{pieces}, {pps:.2} pps, {pace} pace"
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if cleared == goal {
|
||||||
|
writeln!(writer)
|
||||||
|
} else {
|
||||||
|
writer.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn prompt_yn(io_args: &cli::IoArgs, msg: &str) -> bool {
|
fn prompt_yn(io_args: &cli::IoArgs, msg: &str) -> bool {
|
||||||
if io_args.noninteractive {
|
if io_args.noninteractive {
|
||||||
return true;
|
return true;
|
||||||
|
@ -174,7 +219,7 @@ fn run_simulation(
|
||||||
};
|
};
|
||||||
let mut sim = sim::Simul::new(seed, sim_opts);
|
let mut sim = sim::Simul::new(seed, sim_opts);
|
||||||
|
|
||||||
let time_start = std::time::Instant::now();
|
let time_start = Instant::now();
|
||||||
|
|
||||||
while sim.lines_left() > 0 {
|
while sim.lines_left() > 0 {
|
||||||
if exit_early.load(atomic::Ordering::Relaxed) {
|
if exit_early.load(atomic::Ordering::Relaxed) {
|
||||||
|
@ -213,14 +258,14 @@ fn run_simulation(
|
||||||
let status = Status {
|
let status = Status {
|
||||||
lines_left: sim.lines_left(),
|
lines_left: sim.lines_left(),
|
||||||
pieces: sim.pieces(),
|
pieces: sim.pieces(),
|
||||||
time: std::time::Instant::now() - time_start,
|
time: Instant::now() - time_start,
|
||||||
};
|
};
|
||||||
if tx.send(Msg::Status(id, status.into())).is_err() {
|
if tx.send(Msg::Status(id, status.into())).is_err() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let time_end = std::time::Instant::now();
|
let time_end = Instant::now();
|
||||||
|
|
||||||
let profile = data_args.profile.then(|| output::Profile {
|
let profile = data_args.profile.then(|| output::Profile {
|
||||||
time: time_end - time_start,
|
time: time_end - time_start,
|
||||||
|
|
Loading…
Reference in New Issue