use crate::builder::actions::base::{ActionBuilder, ManeuverAction};
use crate::builder::positions::PositionBuilder;
use crate::builder::{BuilderError, BuilderResult};
use crate::types::{
actions::movement::{
AbsoluteTargetSpeed, LongitudinalAction, LongitudinalActionChoice, SpeedAction,
SpeedActionTarget, TeleportAction, TransitionDynamics,
},
actions::wrappers::PrivateAction,
basic::Double,
enums::{DynamicsDimension, DynamicsShape},
positions::Position,
};
#[derive(Debug, Default)]
pub struct SpeedActionBuilder {
entity_ref: Option<String>,
target_speed: Option<f64>,
}
impl SpeedActionBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn for_entity(mut self, entity_ref: &str) -> Self {
self.entity_ref = Some(entity_ref.to_string());
self
}
pub fn to_speed(mut self, speed: f64) -> Self {
self.target_speed = Some(speed);
self
}
pub fn change_by(mut self, delta: f64) -> Self {
self.target_speed = Some(delta);
self
}
}
impl ActionBuilder for SpeedActionBuilder {
fn build_action(self) -> BuilderResult<PrivateAction> {
self.validate()?;
let speed_action = SpeedAction {
speed_action_dynamics: TransitionDynamics {
dynamics_dimension: DynamicsDimension::Time,
dynamics_shape: DynamicsShape::Linear,
value: Double::literal(1.0),
},
speed_action_target: SpeedActionTarget {
absolute: Some(AbsoluteTargetSpeed {
value: Double::literal(self.target_speed.unwrap()),
}),
relative: None,
},
};
Ok(PrivateAction::LongitudinalAction(LongitudinalAction {
longitudinal_action_choice: LongitudinalActionChoice::SpeedAction(speed_action),
}))
}
fn validate(&self) -> BuilderResult<()> {
if self.target_speed.is_none() {
return Err(BuilderError::validation_error("Target speed is required"));
}
Ok(())
}
}
impl ManeuverAction for SpeedActionBuilder {
fn entity_ref(&self) -> Option<&str> {
self.entity_ref.as_deref()
}
}
#[derive(Debug, Default)]
pub struct TeleportActionBuilder {
entity_ref: Option<String>,
position: Option<Position>,
}
impl TeleportActionBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn for_entity(mut self, entity_ref: &str) -> Self {
self.entity_ref = Some(entity_ref.to_string());
self
}
pub fn to_position(mut self, position: Position) -> Self {
self.position = Some(position);
self
}
pub fn to(self) -> TeleportPositionBuilder {
TeleportPositionBuilder::new(self)
}
}
impl ActionBuilder for TeleportActionBuilder {
fn build_action(self) -> BuilderResult<PrivateAction> {
self.validate()?;
let teleport_action = TeleportAction {
position: self.position.unwrap(),
};
Ok(PrivateAction::TeleportAction(teleport_action))
}
fn validate(&self) -> BuilderResult<()> {
if self.position.is_none() {
return Err(BuilderError::validation_error(
"Position is required for teleport action",
));
}
Ok(())
}
}
impl ManeuverAction for TeleportActionBuilder {
fn entity_ref(&self) -> Option<&str> {
self.entity_ref.as_deref()
}
}
pub struct TeleportPositionBuilder {
parent: TeleportActionBuilder,
}
impl TeleportPositionBuilder {
fn new(parent: TeleportActionBuilder) -> Self {
Self { parent }
}
pub fn world_position(mut self, x: f64, y: f64, z: f64) -> TeleportActionBuilder {
let position = crate::builder::positions::WorldPositionBuilder::new()
.x(x)
.y(y)
.z(z)
.finish()
.unwrap();
self.parent.position = Some(position);
self.parent
}
pub fn lane_position(mut self, road_id: &str, lane_id: &str, s: f64) -> TeleportActionBuilder {
let position = crate::builder::positions::LanePositionBuilder::new()
.road(road_id)
.lane(lane_id)
.s(s)
.offset(0.0)
.finish()
.unwrap();
self.parent.position = Some(position);
self.parent
}
}