use super::*;
use brep_kernel::RouteStatus;
#[derive(Debug, Clone, PartialEq)]
pub enum WireLengthState {
Current,
RunPending,
Cancelled,
NoRun,
RolledBack,
Unrouted { status: RouteStatus, message: String },
}
impl WireLengthState {
pub fn as_str(&self) -> &'static str {
match self {
WireLengthState::Current => "current",
WireLengthState::RunPending => "routing",
WireLengthState::Cancelled => "cancelled",
WireLengthState::NoRun => "no-run",
WireLengthState::RolledBack => "rolled-back",
WireLengthState::Unrouted { status, .. } => status.as_str(),
}
}
pub fn describe(&self) -> String {
match self {
WireLengthState::Current => String::new(),
WireLengthState::RunPending => "routing…".into(),
WireLengthState::Cancelled => "rebuild cancelled".into(),
WireLengthState::NoRun => "needs a rebuild".into(),
WireLengthState::RolledBack => "rolled back".into(),
WireLengthState::Unrouted { status, .. } => format!("not routed ({})", status.as_str()),
}
}
pub fn explain(&self) -> String {
match self {
WireLengthState::Current => "routed by the current run".into(),
WireLengthState::RunPending => {
"a rebuild is running; the cut length appears when it lands".into()
}
WireLengthState::Cancelled => {
"the last rebuild was cancelled, so the route on hand is from before your last edit; rebuild for cut lengths"
.into()
}
WireLengthState::NoRun => "no routing run has been applied; rebuild the model".into(),
WireLengthState::RolledBack => {
"the history is rolled back, so the route may miss later splines; roll to the end for cut lengths"
.into()
}
WireLengthState::Unrouted { message, .. } => message.clone(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct WireBomLine {
pub id: String,
pub connection_id: String,
pub stock_part_number: String,
pub length: Option<f64>,
pub margin: f64,
pub mf_qty: Option<f64>,
pub state: WireLengthState,
}
impl EngineState {
pub fn wire_bom_lines(&self) -> Vec<WireBomLine> {
let state = self.wire_harness_state();
let margin = state.cut_margin;
let rolled_back = !self.history.is_empty() && self.history.rollback() + 1 < self.history.len();
state
.connections
.iter()
.map(|connection| {
let route = self
.wire_harness_report
.as_ref()
.and_then(|report| report.routes.iter().find(|route| route.connection_id == connection.id));
let (state, length) = if self.run_pending() {
(WireLengthState::RunPending, None)
} else if self.cancelled_run.is_some() {
(WireLengthState::Cancelled, None)
} else if self.wire_harness_report.is_none() {
(WireLengthState::NoRun, None)
} else if rolled_back {
(WireLengthState::RolledBack, None)
} else {
match route {
None => (WireLengthState::NoRun, None),
Some(route) if !route.feasible => (
WireLengthState::Unrouted {
status: route.status,
message: route.message.clone(),
},
None,
),
Some(route) => match route.length {
Some(length) => (WireLengthState::Current, Some(length)),
None => (WireLengthState::NoRun, None),
},
}
};
let connection_id = if connection.name.trim().is_empty() {
connection.id.clone()
} else {
connection.name.clone()
};
WireBomLine {
id: connection.id.clone(),
connection_id,
stock_part_number: connection.id.strip_prefix("diagram:")
.and_then(|id| self.history.diagram_block()?.get("wires")?.as_array()?.iter()
.find(|wire| wire["id"].as_str() == Some(id))?
.get("stock_part_number")?.as_str()).unwrap_or("").to_owned(),
length,
margin,
mf_qty: length.map(|length| length + margin),
state,
}
})
.collect()
}
}