use anyhow::Result;
use dsfb_database::adapters::postgres::load_pg_stat_statements;
use dsfb_database::grammar::{replay, MotifClass, MotifEngine, MotifGrammar};
use std::path::Path;
fn main() -> Result<()> {
let csv_path =
Path::new(env!("CARGO_MANIFEST_DIR")).join("examples/data/pg_stat_statements_sample.csv");
let stream = load_pg_stat_statements(&csv_path)?;
println!("loaded residual stream: {}", stream.source);
println!("samples: {}", stream.samples.len());
const SHA256_HEX_BYTES: usize = 32;
let stream_fp = stream
.fingerprint()
.iter()
.take(SHA256_HEX_BYTES)
.map(|b| format!("{:02x}", b))
.collect::<String>();
println!("stream fingerprint = {}", stream_fp);
let grammar = MotifGrammar::default();
let episodes = MotifEngine::new(grammar).run(&stream);
println!("episodes: {}", episodes.len());
let eps_fp = replay::fingerprint_hex(&episodes);
println!("episode fingerprint = {}", eps_fp);
for ep in &episodes {
println!(
" motif={:?} channel={:?} t=[{:.1}, {:.1}] peak={:.3}",
ep.motif, ep.channel, ep.t_start, ep.t_end, ep.peak
);
}
let regressions = episodes
.iter()
.filter(|e| e.motif == MotifClass::PlanRegressionOnset)
.count();
assert!(
regressions >= 1,
"expected at least one plan_regression_onset episode from the q3 regression in the bundled sample CSV; got {regressions}"
);
const EXPECTED_STREAM_FP: &str =
"ca3630150f102c2d7f9cfcc7db58e9ed23d81dbc501c8bf5896336728e6853a2";
const EXPECTED_EPISODE_FP: &str =
"36f75f6e495dff8ef551164e605deb24df365f03f1f6f5f8cb7ea8b6102637ce";
assert_eq!(
stream_fp, EXPECTED_STREAM_FP,
"stream fingerprint drift: adapter or sample CSV changed"
);
assert_eq!(
eps_fp, EXPECTED_EPISODE_FP,
"episode fingerprint drift: motif state machine or adapter changed"
);
println!(
"OK: {} plan_regression_onset episode(s) detected.",
regressions
);
println!("OK: stream + episode fingerprints match pinned values.");
Ok(())
}