subtr_actor/
actor_state.rs

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