mod cost;
mod learner;
mod time;
mod value;
pub use cost::CostEstimator;
pub use learner::{EstimationLearner, LearningModel};
pub use time::TimeEstimator;
pub use value::ValueEstimator;
use rust_decimal::Decimal;
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct JobEstimate {
pub cost: Decimal,
pub duration: Duration,
pub value: Decimal,
pub confidence: f64,
pub tool_breakdown: Vec<ToolEstimate>,
}
#[derive(Debug, Clone)]
pub struct ToolEstimate {
pub tool_name: String,
pub cost: Decimal,
pub duration: Duration,
pub confidence: f64,
}
pub struct Estimator {
cost: CostEstimator,
time: TimeEstimator,
value: ValueEstimator,
learner: EstimationLearner,
}
impl Estimator {
pub fn new() -> Self {
Self {
cost: CostEstimator::new(),
time: TimeEstimator::new(),
value: ValueEstimator::new(),
learner: EstimationLearner::new(),
}
}
pub fn estimate_job(
&self,
description: &str,
category: Option<&str>,
tools: &[String],
) -> JobEstimate {
let tool_estimates: Vec<ToolEstimate> = tools
.iter()
.map(|t| ToolEstimate {
tool_name: t.clone(),
cost: self.cost.estimate_tool(t),
duration: self.time.estimate_tool(t),
confidence: 0.7, })
.collect();
let total_cost: Decimal = tool_estimates.iter().map(|e| e.cost).sum();
let total_duration: Duration = tool_estimates.iter().map(|e| e.duration).sum();
let (adjusted_cost, adjusted_time) =
self.learner
.adjust(category.unwrap_or("general"), total_cost, total_duration);
let value = self.value.estimate(description, adjusted_cost);
let confidence = self.learner.confidence(category.unwrap_or("general"));
JobEstimate {
cost: adjusted_cost,
duration: adjusted_time,
value,
confidence,
tool_breakdown: tool_estimates,
}
}
pub fn record_actuals(
&mut self,
category: &str,
estimated_cost: Decimal,
actual_cost: Decimal,
estimated_time: Duration,
actual_time: Duration,
) {
self.learner.record(
category,
estimated_cost,
actual_cost,
estimated_time,
actual_time,
);
}
pub fn cost(&self) -> &CostEstimator {
&self.cost
}
pub fn time(&self) -> &TimeEstimator {
&self.time
}
pub fn value(&self) -> &ValueEstimator {
&self.value
}
}
impl Default for Estimator {
fn default() -> Self {
Self::new()
}
}