event_trigger_action_system/
triggers.rs1use 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#[derive(Debug, Clone)]
15pub struct Triggers<Event, Action> {
16 triggers: Vec<Trigger<Event, Action>>,
17}
18
19#[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#[derive(Debug, Clone)]
39pub struct Trigger<Event, Action> {
40 pub id_str: String,
42 pub condition: TriggerCondition<Event>,
44 pub actions: Vec<Action>,
46}
47
48#[derive(Debug, Clone)]
50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
51pub struct CompiledTrigger<Event: TriggerEvent> {
52 pub id_str: String,
54 condition: CompiledTriggerCondition<Event>,
55 actions: Option<Vec<Event::Action>>,
56}
57
58#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63pub struct TriggerHandle(usize);
64
65pub trait TriggerAction: Debug + Clone {}
67
68pub trait TriggerEventIdentifier: Debug + Ord + Clone {}
79
80pub trait TriggerEvent: From<Self::Action> + PartialOrd {
82 type Action: TriggerAction + ConditionalSerde;
84
85 type Identifier: TriggerEventIdentifier + ConditionalSerde;
89
90 fn identifier(&self) -> Self::Identifier;
92
93 fn partial_cmp_progress(&self, other: &Self, target_ordering: Ordering) -> Option<f64> {
98 self.partial_cmp(other).map(|ordering| {
99 if ordering == target_ordering {
100 1.0
101 } else {
102 0.0
103 }
104 })
105 }
106}
107
108impl<Event, Action> Triggers<Event, Action> {
109 pub fn new(triggers: Vec<Trigger<Event, Action>>) -> Self {
111 Self { triggers }
112 }
113
114 pub fn compile<
118 EventCompiler: Fn(Event) -> CompiledEvent,
119 CompiledEvent: TriggerEvent,
120 ActionCompiler: Fn(Action) -> CompiledEvent::Action,
121 >(
122 self,
123 event_compiler: &EventCompiler,
124 action_compiler: &ActionCompiler,
125 ) -> CompiledTriggers<CompiledEvent> {
126 CompiledTriggers::new(
127 self.triggers
128 .into_iter()
129 .map(|trigger| trigger.compile(event_compiler, action_compiler))
130 .collect(),
131 )
132 }
133}
134
135impl<Event: TriggerEvent> CompiledTriggers<Event> {
136 pub(crate) fn new(mut triggers: Vec<CompiledTrigger<Event>>) -> Self {
137 let mut initial_actions = Vec::new();
138 let subscriptions = triggers
139 .iter_mut()
140 .enumerate()
141 .flat_map(|(id, trigger)| {
142 let subscriptions = trigger.subscriptions();
143 if trigger.completed() {
144 initial_actions.append(&mut trigger.consume_actions());
145 }
146 subscriptions
147 .into_iter()
148 .map(move |identifier| (identifier, id))
149 })
150 .collect();
151 let mut trigger_system = TriggerSystem {
152 triggers,
153 subscriptions,
154 };
155
156 let mut i = 0;
157 while i < initial_actions.len() {
158 initial_actions.append(
159 &mut trigger_system.execute_event(&Event::from(initial_actions[i].clone())),
160 );
161 i += 1;
162 }
163
164 Self {
165 trigger_system,
166 action_queue: initial_actions.into_iter().collect(),
167 }
168 }
169
170 pub fn execute_event(&mut self, event: &Event) {
175 self.action_queue
176 .extend(self.trigger_system.execute_event(event));
177 }
178
179 pub fn execute_events<'events>(&mut self, events: impl IntoIterator<Item = &'events Event>)
184 where
185 Event: 'events,
186 {
187 events
188 .into_iter()
189 .for_each(|event| self.execute_event(event));
190 }
191
192 pub fn execute_owned_events(&mut self, events: impl IntoIterator<Item = Event>) {
199 events
200 .into_iter()
201 .for_each(|event| self.execute_event(&event));
202 }
203
204 pub fn consume_action(&mut self) -> Option<Event::Action> {
206 self.action_queue.pop_front()
207 }
208
209 pub fn consume_all_actions(&mut self) -> impl '_ + Iterator<Item = Event::Action> {
213 self.action_queue.drain(0..self.action_queue.len())
214 }
215
216 pub fn progress(&self, handle: TriggerHandle) -> Option<(f64, f64)> {
220 self.trigger_system
221 .triggers
222 .get(handle.0)
223 .map(|trigger| trigger.progress())
224 }
225}
226
227impl<Event: TriggerEvent> TriggerSystem<Event> {
228 fn execute_event(&mut self, event: &Event) -> Vec<Event::Action> {
229 let mut all_actions = Vec::new();
230 let identifier = event.identifier();
231 let trigger_indices: Vec<_> = self
232 .subscriptions
233 .get(&identifier)
234 .unwrap_or(&BTreeMap::new())
235 .keys()
236 .copied()
237 .collect();
238 for trigger_index in trigger_indices {
239 let trigger = &mut self.triggers[trigger_index];
240 let (mut actions, trigger_condition_updates) = trigger.execute_event(event);
241 all_actions.append(&mut actions);
242
243 for trigger_condition_update in trigger_condition_updates {
244 match trigger_condition_update {
245 TriggerConditionUpdate::Subscribe(identifier) => {
246 self.subscriptions.insert(identifier.clone(), trigger_index);
247 }
248 TriggerConditionUpdate::Unsubscribe(identifier) => {
249 self.subscriptions
250 .remove_key_value(&identifier, &trigger_index);
251 }
252 }
253 }
254 }
255
256 let mut i = 0;
257 while i < all_actions.len() {
258 all_actions.append(&mut self.execute_event(&Event::from(all_actions[i].clone())));
259 i += 1;
260 }
261
262 all_actions
263 }
264}
265
266impl<Event, Action> Trigger<Event, Action> {
267 pub fn new(id_str: String, condition: TriggerCondition<Event>, actions: Vec<Action>) -> Self {
269 Self {
270 id_str,
271 condition,
272 actions,
273 }
274 }
275
276 pub fn compile<
280 EventCompiler: Fn(Event) -> CompiledEvent,
281 CompiledEvent: TriggerEvent,
282 ActionCompiler: Fn(Action) -> CompiledEvent::Action,
283 >(
284 self,
285 event_compiler: &EventCompiler,
286 action_compiler: &ActionCompiler,
287 ) -> CompiledTrigger<CompiledEvent> {
288 CompiledTrigger::new(
289 self.id_str,
290 self.condition.compile(event_compiler),
291 self.actions.into_iter().map(action_compiler).collect(),
292 )
293 }
294}
295
296impl<Event: TriggerEvent> CompiledTrigger<Event> {
297 pub(crate) fn new(
298 id_str: String,
299 condition: CompiledTriggerCondition<Event>,
300 actions: Vec<Event::Action>,
301 ) -> Self {
302 Self {
303 id_str,
304 condition,
305 actions: Some(actions),
306 }
307 }
308
309 pub(crate) fn subscriptions(&self) -> Vec<Event::Identifier> {
310 self.condition.subscriptions()
311 }
312
313 pub(crate) fn execute_event(
314 &mut self,
315 event: &Event,
316 ) -> (
317 Vec<Event::Action>,
318 Vec<TriggerConditionUpdate<Event::Identifier>>,
319 ) {
320 let (trigger_condition_updates, result, _) = self.condition.execute_event(event);
321 if result {
322 (self.actions.take().unwrap(), trigger_condition_updates)
323 } else {
324 (Default::default(), trigger_condition_updates)
325 }
326 }
327
328 pub(crate) fn progress(&self) -> (f64, f64) {
329 (
330 self.condition.current_progress(),
331 self.condition.required_progress(),
332 )
333 }
334
335 #[allow(dead_code)]
337 pub(crate) fn condition(&self) -> &CompiledTriggerCondition<Event> {
338 &self.condition
339 }
340
341 #[allow(dead_code)]
343 pub(crate) fn actions(&self) -> &[Event::Action] {
344 self.actions.as_deref().unwrap_or(&[])
345 }
346
347 pub(crate) fn completed(&self) -> bool {
348 self.condition.completed()
349 }
350
351 fn consume_actions(&mut self) -> Vec<Event::Action> {
352 self.actions.take().unwrap()
353 }
354}
355
356impl From<usize> for TriggerHandle {
357 fn from(value: usize) -> Self {
358 Self(value)
359 }
360}