use std::{fs::{self, File}, marker::PhantomData, path::Path};
use crate::{Metadata, RunResult};
pub struct OutputFiles<MD, const COLS: usize>
where
MD: Metadata<COLS>,
{
filename: String,
wtr: Option<csv::Writer<File>>,
_phantom: PhantomData<MD>,
}
impl<MD, const COLS: usize> OutputFiles<MD, COLS>
where
MD: Metadata<COLS>,
{
pub fn new(name: &str) -> Self {
let name = sanitize_filename::sanitize(name);
let date = chrono::offset::Local::now().format("%Y-%m-%d-%H-%M-%S").to_string();
let filename = format!("{}-{}.csv", name, date);
Self { filename, wtr: None, _phantom: PhantomData }
}
pub fn write_results(&mut self, metadata: &MD, run_results: &Vec<RunResult>) -> csv::Result<()> {
let wtr = self.wtr.get_or_insert_with(|| {
let mut wtr = create_file(&self.filename).unwrap();
let keys = run_results[0].energy.keys().collect();
Self::init_columns(&mut wtr, keys).unwrap();
wtr
});
for run in run_results {
for val in metadata.get_values() {
wtr.write_field(val)?;
}
wtr.write_field(run.runtime.as_secs_f32().to_string())?;
for val in run.energy.values() {
wtr.write_field(val.to_string())?;
}
wtr.write_record(None::<&[u8]>)?;
}
Ok(())
}
fn init_columns(wtr: &mut csv::Writer<File>, keys: Vec<&String>) -> csv::Result<()> {
for key in MD::get_header() {
wtr.write_field(key)?;
}
wtr.write_field("Runtime (s)")?;
for key in keys {
wtr.write_field(key)?;
}
wtr.write_record(None::<&[u8]>)
}
}
fn create_file(filename: &str) -> csv::Result<csv::Writer<File>> {
const ROOT_DIR: &str = "energy-bench";
let path = Path::new(ROOT_DIR).join(filename);
fs::create_dir_all(ROOT_DIR)?;
csv::Writer::from_path(path)
}