subtr_actor/stats/analysis_graph/
mod.rs1#![allow(dead_code)]
2
3use std::collections::HashSet;
4
5use crate::Collector;
6use crate::{SubtrActorError, SubtrActorErrorVariant, SubtrActorResult};
7
8pub mod graph;
9pub use graph::{
10 AnalysisDependency, AnalysisGraph, AnalysisNode, AnalysisNodeDyn, AnalysisStateContext,
11 AnalysisStateRef,
12};
13
14#[macro_use]
15mod node_macros;
16
17mod collector;
18mod nodes;
19
20use crate::stats::calculators::FrameInput;
21
22#[allow(unused_imports)]
23pub use collector::AnalysisNodeCollector;
24#[allow(unused_imports)]
25pub use nodes::*;
26
27pub(crate) fn boxed_analysis_node_by_name(name: &str) -> Option<Box<dyn AnalysisNodeDyn>> {
28 match name {
29 "core" => Some(nodes::match_stats::boxed_default()),
30 "backboard" => Some(nodes::backboard::boxed_default()),
31 "ceiling_shot" => Some(nodes::ceiling_shot::boxed_default()),
32 "double_tap" => Some(nodes::double_tap::boxed_default()),
33 "fifty_fifty" => Some(nodes::fifty_fifty::boxed_default()),
34 "possession" => Some(nodes::possession::boxed_default()),
35 "pressure" => Some(nodes::pressure::boxed_default()),
36 "rush" => Some(nodes::rush::boxed_default()),
37 "touch" => Some(nodes::touch::boxed_default()),
38 "whiff" => Some(nodes::whiff::boxed_default()),
39 "speed_flip" => Some(nodes::speed_flip::boxed_default()),
40 "musty_flick" => Some(nodes::musty_flick::boxed_default()),
41 "dodge_reset" => Some(nodes::dodge_reset::boxed_default()),
42 "ball_carry" => Some(nodes::ball_carry::boxed_default()),
43 "boost" => Some(nodes::boost::boxed_default()),
44 "movement" => Some(nodes::movement::boxed_default()),
45 "positioning" => Some(nodes::positioning::boxed_default()),
46 "powerslide" => Some(nodes::powerslide::boxed_default()),
47 "demo" => Some(nodes::demo::boxed_default()),
48 _ => None,
49 }
50}
51
52pub fn graph_with_builtin_analysis_nodes<I, S>(names: I) -> SubtrActorResult<AnalysisGraph>
53where
54 I: IntoIterator<Item = S>,
55 S: AsRef<str>,
56{
57 let mut graph = AnalysisGraph::new().with_input_state_type::<FrameInput>();
58 graph.push_boxed_node(nodes::live_play::boxed_default());
59 let mut seen = HashSet::new();
60 for name in names {
61 let name = name.as_ref();
62 if !seen.insert(name.to_owned()) {
63 continue;
64 }
65 graph.push_boxed_node(boxed_analysis_node_by_name(name).ok_or_else(|| {
66 SubtrActorError::new(SubtrActorErrorVariant::UnknownStatsModuleName(
67 name.to_owned(),
68 ))
69 })?);
70 }
71 Ok(graph)
72}
73
74pub fn collect_analysis_graph_for_replay(
75 replay: &boxcars::Replay,
76 graph: AnalysisGraph,
77) -> SubtrActorResult<AnalysisGraph> {
78 let collector = collector::AnalysisNodeCollector::new(graph).process_replay(replay)?;
79 Ok(collector.into_graph())
80}
81
82pub fn collect_builtin_analysis_graph_for_replay<I, S>(
83 replay: &boxcars::Replay,
84 names: I,
85) -> SubtrActorResult<AnalysisGraph>
86where
87 I: IntoIterator<Item = S>,
88 S: AsRef<str>,
89{
90 collect_analysis_graph_for_replay(replay, graph_with_builtin_analysis_nodes(names)?)
91}
92
93pub fn all_analysis_nodes() -> Vec<Box<dyn AnalysisNodeDyn>> {
94 vec![
95 nodes::backboard::boxed_default(),
96 nodes::ball_carry::boxed_default(),
97 nodes::boost::boxed_default(),
98 nodes::ceiling_shot::boxed_default(),
99 nodes::demo::boxed_default(),
100 nodes::dodge_reset::boxed_default(),
101 nodes::double_tap::boxed_default(),
102 nodes::fifty_fifty::boxed_default(),
103 nodes::match_stats::boxed_default(),
104 nodes::movement::boxed_default(),
105 nodes::musty_flick::boxed_default(),
106 nodes::positioning::boxed_default(),
107 nodes::possession::boxed_default(),
108 nodes::powerslide::boxed_default(),
109 nodes::pressure::boxed_default(),
110 nodes::rush::boxed_default(),
111 nodes::settings::boxed_default(),
112 nodes::speed_flip::boxed_default(),
113 nodes::touch::boxed_default(),
114 nodes::whiff::boxed_default(),
115 ]
116}
117
118pub fn graph_with_all_analysis_nodes() -> AnalysisGraph {
119 let mut graph = AnalysisGraph::new().with_input_state_type::<FrameInput>();
120 graph.push_boxed_node(nodes::live_play::boxed_default());
121 for node in all_analysis_nodes() {
122 graph.push_boxed_node(node);
123 }
124 graph
125}
126
127#[cfg(test)]
128#[path = "module_tests.rs"]
129mod tests;