pub mod draw;
pub mod records;
pub mod repredict;
pub mod sample;
pub mod score;
pub mod stats;
pub mod subsample;
mod merges;
mod population;
mod redact;
mod report_md;
mod verdict;
use std::path::{Path, PathBuf};
use rusqlite::Connection;
use thiserror::Error;
pub use records::{SampleRecord, StrataSummary, Stratum};
pub use repredict::{run_repredict, RepredictParams, RepredictSummary};
pub use sample::{run_sample, SampleParams, SampleSummary};
pub use score::{run_score, ScoreParams, ScoreReport};
pub use subsample::{run_subsample, SubsampleParams, SubsampleSummary};
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum EvalError {
#[error("database error: {0}")]
Db(#[from] rusqlite::Error),
#[error(transparent)]
Core(#[from] crate::core::errors::TgaError),
#[error("rule engine: {0}")]
Classify(#[from] crate::classify::ClassifyError),
#[error("refusing to run: {0} is not opened read-only")]
NotReadOnly(PathBuf),
#[error("{path}: {source}")]
Io {
path: PathBuf,
source: std::io::Error,
},
#[error("{path}: {source}")]
Json {
path: PathBuf,
source: serde_json::Error,
},
#[error("{path}: {source}")]
Csv {
path: PathBuf,
source: csv::Error,
},
#[error("{0}")]
Invalid(String),
}
pub type Result<T> = std::result::Result<T, EvalError>;
pub(crate) fn io_err(path: &Path) -> impl FnOnce(std::io::Error) -> EvalError + '_ {
move |source| EvalError::Io {
path: path.to_path_buf(),
source,
}
}
pub fn config_categories(config: &crate::core::config::Config) -> Result<Vec<String>> {
let pipeline = crate::classify::ClassificationPipeline::new(config.clone());
let engine = pipeline.build_rule_engine()?;
let taxonomy = engine.taxonomy().all().iter().map(|d| d.name.clone());
Ok(taxonomy.chain(pipeline.rule_categories()?).collect())
}
pub fn open_eval_db(path: &Path) -> Result<Connection> {
let conn = crate::core::inspect::open_read_only(path)?;
if !conn.is_readonly(rusqlite::MAIN_DB)? {
return Err(EvalError::NotReadOnly(path.to_path_buf()));
}
conn.pragma_update(None, "query_only", true)?;
Ok(conn)
}