use std::path::{Path, PathBuf};
use serde_json::Value;
#[allow(dead_code)]
pub fn json_approx_eq(a: &Value, b: &Value) -> bool {
match (a, b) {
(Value::Number(x), Value::Number(y)) => match (x.as_f64(), y.as_f64()) {
(Some(xf), Some(yf)) => (xf - yf).abs() <= 1e-9 * xf.abs().max(yf.abs()).max(1.0),
_ => x == y,
},
(Value::Array(xs), Value::Array(ys)) => {
xs.len() == ys.len() && xs.iter().zip(ys).all(|(p, q)| json_approx_eq(p, q))
}
(Value::Object(xs), Value::Object(ys)) => {
xs.len() == ys.len()
&& xs
.iter()
.all(|(k, p)| ys.get(k).is_some_and(|q| json_approx_eq(p, q)))
}
_ => a == b,
}
}
#[allow(dead_code)]
pub fn powerworld_vendored(name: &str) -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../tests/data/powerworld")
.join(name)
}
#[allow(dead_code)]
pub fn activsg2000_fetched(name: &str) -> Option<PathBuf> {
let p = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../tests/data/large/ACTIVSg2000")
.join(name);
p.exists().then_some(p)
}
#[allow(dead_code)]
pub fn rts_gmlc_fetched(name: &str) -> Option<PathBuf> {
let p = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../tests/data/large/RTS-GMLC")
.join(name);
p.exists().then_some(p)
}
#[allow(dead_code)]
pub fn ckt(b: &powerio::Branch) -> String {
b.extras
.get("LineCircuit")
.and_then(|v| v.as_str())
.unwrap_or("1")
.trim()
.to_string()
}
#[allow(dead_code)]
pub fn local_corpus_path(label: &str) -> Option<PathBuf> {
let manifest = Path::new(env!("CARGO_MANIFEST_DIR")).join("../tests/data/local_pwb_corpus.tsv");
let text = std::fs::read_to_string(manifest).ok()?;
let path = text.lines().find_map(|line| {
let mut f = line.split('\t');
(f.next() == Some(label)).then(|| f.next()).flatten()
})?;
let p = PathBuf::from(path);
p.exists().then_some(p)
}