pub mod entity;
pub mod spatial;
pub mod value;
pub use entity::{
AccelerationConditionBuilder, EndOfRoadConditionBuilder, EnhancedSpeedConditionBuilder,
ReachPositionConditionBuilder, TraveledDistanceConditionBuilder,
};
pub use spatial::{
CollisionConditionBuilder, DistanceConditionBuilder, RelativeDistanceConditionBuilder,
};
pub use value::{
ParameterConditionBuilder, SpeedConditionBuilder,
SpeedConditionBuilder as ValueSpeedConditionBuilder, StoryboardElementStateConditionBuilder,
TimeConditionBuilder, VariableConditionBuilder,
};
use crate::builder::{BuilderError, BuilderResult};
use crate::types::{
scenario::triggers::Condition,
scenario::triggers::{ConditionGroup, Trigger},
};
#[derive(Debug, Default)]
pub struct TriggerBuilder {
condition_groups: Vec<ConditionGroup>,
}
impl TriggerBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn add_condition_group(self) -> ConditionGroupBuilder {
ConditionGroupBuilder::new(self)
}
pub fn add_condition(mut self, condition: Condition) -> Self {
let group = ConditionGroup {
conditions: vec![condition],
};
self.condition_groups.push(group);
self
}
pub fn build(self) -> BuilderResult<Trigger> {
if self.condition_groups.is_empty() {
return Err(BuilderError::validation_error(
"At least one condition is required",
));
}
Ok(Trigger {
condition_groups: self.condition_groups,
})
}
pub(crate) fn add_group(mut self, group: ConditionGroup) -> Self {
self.condition_groups.push(group);
self
}
}
pub struct ConditionGroupBuilder {
parent: TriggerBuilder,
conditions: Vec<Condition>,
}
impl ConditionGroupBuilder {
pub fn new(parent: TriggerBuilder) -> Self {
Self {
parent,
conditions: Vec::new(),
}
}
pub fn add_condition(mut self, condition: Condition) -> Self {
self.conditions.push(condition);
self
}
pub fn time_condition(self) -> TimeConditionGroupBuilder {
TimeConditionGroupBuilder::new(self)
}
pub fn speed_condition(self) -> SpeedConditionGroupBuilder {
SpeedConditionGroupBuilder::new(self)
}
pub fn finish_group(self) -> TriggerBuilder {
if !self.conditions.is_empty() {
let group = ConditionGroup {
conditions: self.conditions,
};
self.parent.add_group(group)
} else {
self.parent
}
}
pub fn build(self) -> TriggerBuilder {
self.finish_group()
}
}
pub struct TimeConditionGroupBuilder {
parent: ConditionGroupBuilder,
builder: TimeConditionBuilder,
}
impl TimeConditionGroupBuilder {
pub fn new(parent: ConditionGroupBuilder) -> Self {
Self {
parent,
builder: TimeConditionBuilder::new(),
}
}
pub fn at_time(mut self, time: f64) -> Self {
self.builder = self.builder.at_time(time);
self
}
pub fn finish(self) -> BuilderResult<ConditionGroupBuilder> {
let condition = self.builder.build()?;
Ok(self.parent.add_condition(condition))
}
}
pub struct SpeedConditionGroupBuilder {
parent: ConditionGroupBuilder,
builder: ValueSpeedConditionBuilder,
}
impl SpeedConditionGroupBuilder {
pub fn new(parent: ConditionGroupBuilder) -> Self {
Self {
parent,
builder: ValueSpeedConditionBuilder::new(),
}
}
pub fn for_entity(mut self, entity_ref: &str) -> Self {
self.builder = self.builder.for_entity(entity_ref);
self
}
pub fn speed_above(mut self, speed: f64) -> Self {
self.builder = self.builder.speed_above(speed);
self
}
pub fn finish(self) -> BuilderResult<ConditionGroupBuilder> {
let condition = self.builder.build()?;
Ok(self.parent.add_condition(condition))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::basic::Value;
#[test]
fn test_trigger_builder_basic() {
let time_condition = TimeConditionBuilder::new().at_time(3.0).build().unwrap();
let trigger = TriggerBuilder::new()
.add_condition(time_condition)
.build()
.unwrap();
assert_eq!(trigger.condition_groups.len(), 1);
assert_eq!(trigger.condition_groups[0].conditions.len(), 1);
}
#[test]
fn test_condition_group_builder() {
let time_condition = TimeConditionBuilder::new().at_time(5.0).build().unwrap();
let speed_condition = ValueSpeedConditionBuilder::new()
.for_entity("ego")
.speed_above(30.0)
.build()
.unwrap();
let trigger = TriggerBuilder::new()
.add_condition_group()
.add_condition(time_condition)
.add_condition(speed_condition)
.finish_group()
.build()
.unwrap();
assert_eq!(trigger.condition_groups.len(), 1);
assert_eq!(trigger.condition_groups[0].conditions.len(), 2);
}
}