1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
use crate::*;
use boxcars;
use std::collections::HashMap;
/// A struct representing the state of an actor.
///
/// This includes both attributes and derived attributes, along with the
/// associated object id and name id.
#[derive(PartialEq, Debug, Clone)]
pub struct ActorState {
/// A map of the actor's attributes with their corresponding object ids and
/// frame indices.
pub attributes: HashMap<boxcars::ObjectId, (boxcars::Attribute, usize)>,
/// A map of the actor's derived attributes with their corresponding object
/// ids and frame indices.
pub derived_attributes: HashMap<String, (boxcars::Attribute, usize)>,
/// The object id associated with the actor.
pub object_id: boxcars::ObjectId,
/// Optional name id associated with the actor.
pub name_id: Option<i32>,
}
impl ActorState {
/// Creates a new `ActorState` from a given `NewActor`.
///
/// # Arguments
///
/// * `new_actor` - The new actor to initialize the state from.
///
/// # Returns
///
/// A new `ActorState` object.
fn new(new_actor: &boxcars::NewActor) -> Self {
Self {
attributes: HashMap::new(),
derived_attributes: HashMap::new(),
object_id: new_actor.object_id,
name_id: new_actor.name_id,
}
}
/// Updates an attribute in the `ActorState`.
///
/// # Arguments
///
/// * `update` - The updated attribute.
/// * `frame_index` - The index of the frame at which the update occurs.
///
/// # Returns
///
/// An optional tuple of the updated attribute and its frame index.
fn update_attribute(
&mut self,
update: &boxcars::UpdatedAttribute,
frame_index: usize,
) -> Option<(boxcars::Attribute, usize)> {
self.attributes
.insert(update.object_id, (update.attribute.clone(), frame_index))
}
}
/// A struct modeling the states of multiple actors at a given point in time.
/// Provides methods to update that state with successive frames from a
/// boxcars::Replay.
pub struct ActorStateModeler {
/// A map of actor states with their corresponding actor ids.
pub actor_states: HashMap<boxcars::ActorId, ActorState>,
/// A map of actor ids with their corresponding object ids.
pub actor_ids_by_type: HashMap<boxcars::ObjectId, Vec<boxcars::ActorId>>,
}
impl ActorStateModeler {
/// Creates a new [`ActorStateModeler`].
///
/// # Returns
///
/// A new [`ActorStateModeler`]. object.
pub fn new() -> Self {
Self {
actor_states: HashMap::new(),
actor_ids_by_type: HashMap::new(),
}
}
/// Processes a frame, including handling of new, updated, and deleted actors.
///
/// # Arguments
///
/// * `frame` - The frame to be processed.
/// * `frame_index` - The index of the frame to be processed.
///
/// # Returns
///
/// An empty result (`Ok(())`) on success, [`SubtrActorError`] on failure.
pub fn process_frame(
&mut self,
frame: &boxcars::Frame,
frame_index: usize,
) -> SubtrActorResult<()> {
if let Some(err) = frame
.deleted_actors
.iter()
.map(|n| self.delete_actor(n))
.find(|r| r.is_err())
{
return err.map(|_| ());
}
if let Some(err) = frame
.new_actors
.iter()
.map(|n| self.new_actor(n))
.find(|r| r.is_err())
{
return err;
}
if let Some(err) = frame
.updated_actors
.iter()
.map(|u| self.update_attribute(u, frame_index))
.find(|r| r.is_err())
{
return err.map(|_| ());
}
Ok(())
}
pub fn new_actor(&mut self, new_actor: &boxcars::NewActor) -> SubtrActorResult<()> {
if let Some(state) = self.actor_states.get(&new_actor.actor_id) {
if state.object_id != new_actor.object_id {
return SubtrActorError::new_result(SubtrActorErrorVariant::ActorIdAlreadyExists {
actor_id: new_actor.actor_id.clone(),
object_id: new_actor.object_id.clone(),
});
}
} else {
self.actor_states
.insert(new_actor.actor_id, ActorState::new(new_actor));
self.actor_ids_by_type
.entry(new_actor.object_id)
.or_insert_with(|| Vec::new())
.push(new_actor.actor_id)
}
Ok(())
}
pub fn update_attribute(
&mut self,
update: &boxcars::UpdatedAttribute,
frame_index: usize,
) -> SubtrActorResult<Option<(boxcars::Attribute, usize)>> {
self.actor_states
.get_mut(&update.actor_id)
.map(|state| state.update_attribute(update, frame_index))
.ok_or_else(|| {
SubtrActorError::new(SubtrActorErrorVariant::UpdatedActorIdDoesNotExist {
update: update.clone(),
})
})
}
pub fn delete_actor(&mut self, actor_id: &boxcars::ActorId) -> SubtrActorResult<ActorState> {
let state = self.actor_states.remove(actor_id).ok_or_else(|| {
SubtrActorError::new(SubtrActorErrorVariant::NoStateForActorId {
actor_id: actor_id.clone(),
})
})?;
self.actor_ids_by_type
.entry(state.object_id)
.or_insert_with(|| Vec::new())
.retain(|x| x != actor_id);
Ok(state)
}
}