event_trigger_action_system/
triggers.rs

1use crate::TriggerCondition;
2use crate::conditions::{CompiledTriggerCondition, TriggerConditionUpdate};
3use btreemultimap_value_ord::BTreeMultiMap;
4use conditional_serde::ConditionalSerde;
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7use std::cmp::Ordering;
8use std::collections::{BTreeMap, VecDeque};
9use std::fmt::Debug;
10
11mod std_lib_implementations;
12
13/// A raw collection of triggers.
14#[derive(Debug, Clone)]
15pub struct Triggers<Event, Action> {
16    triggers: Vec<Trigger<Event, Action>>,
17}
18
19/// A compiled collection of triggers.
20///
21/// This is the central type for using the event trigger action system.
22/// Execute events via [`Self::execute_event`], [`Self::execute_events`] and [`Self::execute_owned_events`], and collect actions via [`Self::consume_action`] and [`Self::consume_all_actions`].
23#[derive(Debug, Clone)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub struct CompiledTriggers<Event: TriggerEvent> {
26    trigger_system: TriggerSystem<Event>,
27    action_queue: VecDeque<Event::Action>,
28}
29
30#[derive(Debug, Clone)]
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32struct TriggerSystem<Event: TriggerEvent> {
33    triggers: Vec<CompiledTrigger<Event>>,
34    subscriptions: BTreeMultiMap<Event::Identifier, usize>,
35}
36
37/// A raw trigger.
38#[derive(Debug, Clone)]
39pub struct Trigger<Event, Action> {
40    /// A unique identifier of the trigger.
41    pub id_str: String,
42    /// The condition for the trigger to trigger.
43    pub condition: TriggerCondition<Event>,
44    /// The actions the trigger executes when triggered.
45    pub actions: Vec<Action>,
46}
47
48/// A compiled trigger.
49#[derive(Debug, Clone)]
50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
51pub struct CompiledTrigger<Event: TriggerEvent> {
52    /// A unique identifier of the trigger.
53    pub id_str: String,
54    condition: CompiledTriggerCondition<Event>,
55    actions: Option<Vec<Event::Action>>,
56}
57
58/// A handle of a trigger.
59///
60/// This allows to identify a trigger without worrying about lifetimes.
61#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63pub struct TriggerHandle(usize);
64
65/// A trigger action.
66pub trait TriggerAction: Debug + Clone {}
67
68/// An identifier of a trigger.
69///
70/// This type should be cheap to clone.
71pub trait TriggerIdentifier: Debug + Ord + Clone {}
72
73/// A trigger event.
74pub trait TriggerEvent: From<Self::Action> + PartialOrd {
75    /// The action type used by the trigger event.
76    type Action: TriggerAction + ConditionalSerde;
77
78    /// The identifier of a trigger event.
79    ///
80    /// This type should be cheap to clone.
81    type Identifier: TriggerIdentifier + ConditionalSerde;
82
83    /// Returns the identifier of this trigger event.
84    fn identifier(&self) -> Self::Identifier;
85
86    /// Returns a number between 0.0 and 1.0 indicating how close the ordering of this and other is to the target ordering.
87    /// If the events are not ordered, then `None` is returned.
88    fn partial_cmp_progress(&self, other: &Self, target_ordering: Ordering) -> Option<f64>;
89}
90
91impl<Event, Action> Triggers<Event, Action> {
92    /// Create a new raw triggers instance.
93    pub fn new(triggers: Vec<Trigger<Event, Action>>) -> Self {
94        Self { triggers }
95    }
96
97    /// Compile the raw triggers.
98    ///
99    /// Events are compiled by the event compiler, and actions are compiled by the action compiler.
100    pub fn compile<
101        EventCompiler: Fn(Event) -> CompiledEvent,
102        CompiledEvent: TriggerEvent,
103        ActionCompiler: Fn(Action) -> CompiledEvent::Action,
104    >(
105        self,
106        event_compiler: &EventCompiler,
107        action_compiler: &ActionCompiler,
108    ) -> CompiledTriggers<CompiledEvent> {
109        CompiledTriggers::new(
110            self.triggers
111                .into_iter()
112                .map(|trigger| trigger.compile(event_compiler, action_compiler))
113                .collect(),
114        )
115    }
116}
117
118impl<Event: TriggerEvent> CompiledTriggers<Event> {
119    pub(crate) fn new(mut triggers: Vec<CompiledTrigger<Event>>) -> Self {
120        let mut initial_actions = Vec::new();
121        let subscriptions = triggers
122            .iter_mut()
123            .enumerate()
124            .flat_map(|(id, trigger)| {
125                let subscriptions = trigger.subscriptions();
126                if trigger.completed() {
127                    initial_actions.append(&mut trigger.consume_actions());
128                }
129                subscriptions
130                    .into_iter()
131                    .map(move |identifier| (identifier, id))
132            })
133            .collect();
134        let mut trigger_system = TriggerSystem {
135            triggers,
136            subscriptions,
137        };
138
139        let mut i = 0;
140        while i < initial_actions.len() {
141            initial_actions.append(
142                &mut trigger_system.execute_event(&Event::from(initial_actions[i].clone())),
143            );
144            i += 1;
145        }
146
147        Self {
148            trigger_system,
149            action_queue: initial_actions.into_iter().collect(),
150        }
151    }
152
153    /// Execute the given event.
154    ///
155    /// The event is executed right away, and all resulting actions are stored in an internal action queue,
156    /// waiting to be retrieved via [`Self::consume_action`] or [`Self::consume_all_actions`].
157    pub fn execute_event(&mut self, event: &Event) {
158        self.action_queue
159            .extend(self.trigger_system.execute_event(event));
160    }
161
162    /// Execute the given events.
163    ///
164    /// The event is executed right away, and all resulting actions are stored in an internal action queue,
165    /// waiting to be retrieved via [`Self::consume_action`] or [`Self::consume_all_actions`].
166    pub fn execute_events<'events>(&mut self, events: impl IntoIterator<Item = &'events Event>)
167    where
168        Event: 'events,
169    {
170        events
171            .into_iter()
172            .for_each(|event| self.execute_event(event));
173    }
174
175    /// Execute the given owned events.
176    ///
177    /// The event is executed right away, and all resulting actions are stored in an internal action queue,
178    /// waiting to be retrieved via [`Self::consume_action`] or [`Self::consume_all_actions`].
179    ///
180    /// This method is no different from [`Self::execute_events`], except that it drops the given events after execution.
181    pub fn execute_owned_events(&mut self, events: impl IntoIterator<Item = Event>) {
182        events
183            .into_iter()
184            .for_each(|event| self.execute_event(&event));
185    }
186
187    /// Consume an action from the action queue, if there is one.
188    pub fn consume_action(&mut self) -> Option<Event::Action> {
189        self.action_queue.pop_front()
190    }
191
192    /// Consume all action from the action queue.
193    ///
194    /// If the returned iterator is dropped before all actions are consumed, the remaining actions are dropped quietly.
195    pub fn consume_all_actions(&mut self) -> impl '_ + Iterator<Item = Event::Action> {
196        self.action_queue.drain(0..self.action_queue.len())
197    }
198
199    /// Returns the progress of the given trigger as `(current_progress, required_progress)`.
200    ///
201    /// When `current_progress` reaches `required_progress`, then the trigger triggers.
202    pub fn progress(&self, handle: TriggerHandle) -> Option<(f64, f64)> {
203        self.trigger_system
204            .triggers
205            .get(handle.0)
206            .map(|trigger| trigger.progress())
207    }
208}
209
210impl<Event: TriggerEvent> TriggerSystem<Event> {
211    fn execute_event(&mut self, event: &Event) -> Vec<Event::Action> {
212        let mut all_actions = Vec::new();
213        let identifier = event.identifier();
214        let trigger_indices: Vec<_> = self
215            .subscriptions
216            .get(&identifier)
217            .unwrap_or(&BTreeMap::new())
218            .keys()
219            .copied()
220            .collect();
221        for trigger_index in trigger_indices {
222            let trigger = &mut self.triggers[trigger_index];
223            let (mut actions, trigger_condition_updates) = trigger.execute_event(event);
224            all_actions.append(&mut actions);
225
226            for trigger_condition_update in trigger_condition_updates {
227                match trigger_condition_update {
228                    TriggerConditionUpdate::Subscribe(identifier) => {
229                        self.subscriptions.insert(identifier.clone(), trigger_index);
230                    }
231                    TriggerConditionUpdate::Unsubscribe(identifier) => {
232                        self.subscriptions
233                            .remove_key_value(&identifier, &trigger_index);
234                    }
235                }
236            }
237        }
238
239        let mut i = 0;
240        while i < all_actions.len() {
241            all_actions.append(&mut self.execute_event(&Event::from(all_actions[i].clone())));
242            i += 1;
243        }
244
245        all_actions
246    }
247}
248
249impl<Event, Action> Trigger<Event, Action> {
250    /// Creates a new raw trigger.
251    pub fn new(id_str: String, condition: TriggerCondition<Event>, actions: Vec<Action>) -> Self {
252        Self {
253            id_str,
254            condition,
255            actions,
256        }
257    }
258
259    /// Compiles this trigger.
260    ///
261    /// Events are compiled by the event compiler, and actions are compiled by the action compiler.
262    pub fn compile<
263        EventCompiler: Fn(Event) -> CompiledEvent,
264        CompiledEvent: TriggerEvent,
265        ActionCompiler: Fn(Action) -> CompiledEvent::Action,
266    >(
267        self,
268        event_compiler: &EventCompiler,
269        action_compiler: &ActionCompiler,
270    ) -> CompiledTrigger<CompiledEvent> {
271        CompiledTrigger::new(
272            self.id_str,
273            self.condition.compile(event_compiler),
274            self.actions.into_iter().map(action_compiler).collect(),
275        )
276    }
277}
278
279impl<Event: TriggerEvent> CompiledTrigger<Event> {
280    pub(crate) fn new(
281        id_str: String,
282        condition: CompiledTriggerCondition<Event>,
283        actions: Vec<Event::Action>,
284    ) -> Self {
285        Self {
286            id_str,
287            condition,
288            actions: Some(actions),
289        }
290    }
291
292    pub(crate) fn subscriptions(&self) -> Vec<Event::Identifier> {
293        self.condition.subscriptions()
294    }
295
296    pub(crate) fn execute_event(
297        &mut self,
298        event: &Event,
299    ) -> (
300        Vec<Event::Action>,
301        Vec<TriggerConditionUpdate<Event::Identifier>>,
302    ) {
303        let (trigger_condition_updates, result, _) = self.condition.execute_event(event);
304        if result {
305            (self.actions.take().unwrap(), trigger_condition_updates)
306        } else {
307            (Default::default(), trigger_condition_updates)
308        }
309    }
310
311    pub(crate) fn progress(&self) -> (f64, f64) {
312        (
313            self.condition.current_progress(),
314            self.condition.required_progress(),
315        )
316    }
317
318    /// Returns the trigger condition of this trigger.
319    #[allow(dead_code)]
320    pub(crate) fn condition(&self) -> &CompiledTriggerCondition<Event> {
321        &self.condition
322    }
323
324    /// Returns the actions of this trigger.
325    #[allow(dead_code)]
326    pub(crate) fn actions(&self) -> &[Event::Action] {
327        self.actions.as_deref().unwrap_or(&[])
328    }
329
330    pub(crate) fn completed(&self) -> bool {
331        self.condition.completed()
332    }
333
334    fn consume_actions(&mut self) -> Vec<Event::Action> {
335        self.actions.take().unwrap()
336    }
337}
338
339impl From<usize> for TriggerHandle {
340    fn from(value: usize) -> Self {
341        Self(value)
342    }
343}