use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;
use anyhow::Result;
use super::batch::{BatchValidationStats, SplitWriteStats};
use super::record::OracleTraceRecord;
impl BatchValidationStats {
pub fn write_jsonl_split(&self, out_dir: &str, prefix: &str) -> Result<SplitWriteStats> {
let dir = Path::new(out_dir);
std::fs::create_dir_all(dir)?;
let paths = BucketPaths::new(dir, prefix);
write_bucket(&paths.golden, &self.golden, "golden")?;
write_bucket(&paths.consensus, &self.consensus, "consensus")?;
write_reason_bucket(&paths.failed, &self.failed, "failed")?;
write_reason_bucket(&paths.unverified, &self.unverified, "unverified")?;
Ok(paths.into_stats(self))
}
}
struct BucketPaths {
golden: std::path::PathBuf,
consensus: std::path::PathBuf,
failed: std::path::PathBuf,
unverified: std::path::PathBuf,
}
impl BucketPaths {
fn new(dir: &Path, prefix: &str) -> Self {
Self {
golden: dir.join(format!("{prefix}.golden.jsonl")),
consensus: dir.join(format!("{prefix}.consensus.jsonl")),
failed: dir.join(format!("{prefix}.failed.jsonl")),
unverified: dir.join(format!("{prefix}.unverified.jsonl")),
}
}
fn into_stats(self, b: &BatchValidationStats) -> SplitWriteStats {
SplitWriteStats {
golden_path: self.golden.to_string_lossy().into(),
consensus_path: self.consensus.to_string_lossy().into(),
failed_path: self.failed.to_string_lossy().into(),
unverified_path: self.unverified.to_string_lossy().into(),
golden_count: b.golden.len(),
consensus_count: b.consensus.len(),
failed_count: b.failed.len(),
unverified_count: b.unverified.len(),
}
}
}
fn write_bucket(
path: &Path,
traces: &[super::trace_types::ValidatedTrace],
verdict: &str,
) -> Result<()> {
let mut w = BufWriter::new(File::create(path)?);
for trace in traces {
let rec = OracleTraceRecord {
verdict: verdict.to_string(),
reason: None,
agreement_ratio: None,
trace: trace.clone(),
};
writeln!(w, "{}", serde_json::to_string(&rec)?)?;
}
w.flush()?;
Ok(())
}
fn write_reason_bucket(
path: &Path,
items: &[(super::trace_types::ValidatedTrace, String)],
verdict: &str,
) -> Result<()> {
let mut w = BufWriter::new(File::create(path)?);
for (trace, reason) in items {
let rec = OracleTraceRecord {
verdict: verdict.to_string(),
reason: Some(reason.clone()),
agreement_ratio: None,
trace: trace.clone(),
};
writeln!(w, "{}", serde_json::to_string(&rec)?)?;
}
w.flush()?;
Ok(())
}