1pub mod client;
2pub mod coordinator;
3pub mod net;
4pub mod ship;
5
6use mt_net::{ActionPlan, BagMsg, Rules, VariableHuman};
7use rkyv::{
8 Archive, Deserialize, Serialize,
9 api::high::{HighSerializer, HighValidator},
10 bytecheck::CheckBytes,
11 de::Pool,
12 rancor::Strategy,
13 ser::allocator::ArenaHandle,
14 util::AlignedVec,
15};
16
17#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize, Hash, Eq, PartialOrd, Ord)]
18pub enum ShipKind {
19 Rat(String),
20 Wind(String),
21}
22
23pub type ShipName = i128;
24
25#[derive(Debug, Clone, Serialize, Deserialize, Archive, PartialEq, Eq)]
26pub struct NetworkShipAddress {
27 ip: [u8; 4],
28 port: u16,
29 ship: ShipName,
30 pub kind: ShipKind,
31}
32
33#[derive(Debug, Archive, Clone, Default, Serialize, Deserialize)]
34pub enum Action {
35 #[default]
36 Sail,
37 Shoot {
38 target: Vec<NetworkShipAddress>,
39 id: u32,
40 },
41 Catch {
42 source: NetworkShipAddress,
43 id: u32,
44 },
45}
46
47#[derive(Clone, Debug)]
48pub struct Variable {
49 pub ship: ShipName,
50 pub strategy: Option<Action>,
51}
52
53pub fn get_strategies(
54 haystack: &Rules,
55 rat_ship: &str,
56 variable: String,
57 indirect_parent_rat: Option<&str>,
58) -> Vec<ActionPlan> {
59 match haystack.raw().get(&variable) {
60 None => vec![ActionPlan::default()],
61 Some(plans) => {
62 let directly = plans
64 .iter()
65 .filter(|plan| plan.ship == rat_ship)
66 .filter_map(|el| el.strategy.clone())
67 .collect::<Vec<_>>();
68
69 let mut indirect = plans
71 .iter()
72 .filter_map(|plan| {
73 if let Some(partner) = indirect_parent_rat {
74 if plan.ship == partner {
75 Some(plan)
76 } else {
77 None
78 }
79 } else {
80 Some(plan)
81 }
82 })
83 .filter_map(|plan| match plan.strategy.as_ref()? {
84 ActionPlan::Sail => None,
85 ActionPlan::Shoot { target, id } => target
86 .iter()
87 .find(|shoot_target| *shoot_target == rat_ship)
88 .map(|_| ActionPlan::Catch {
89 source: plan.ship.clone(),
90 id: *id,
91 }),
92 ActionPlan::Catch { source, id } => {
93 if source == rat_ship {
94 Some(ActionPlan::Shoot {
95 target: vec![source.clone()],
96 id: *id,
97 })
98 } else {
99 None
100 }
101 }
102 })
103 .collect::<Vec<_>>();
104
105 indirect.extend(directly);
106 indirect
107 }
108 }
109}
110
111#[async_trait::async_trait]
112pub trait Ship: Send + Sync + 'static {
113 async fn ask_for_action(&self, variable_name: &str) -> anyhow::Result<(Action, bool)>;
115
116 async fn wait_for_wind(&self) -> anyhow::Result<Vec<WindData>>;
119
120 fn get_cannon(&self) -> &impl Cannon;
121}
122
123#[derive(Archive, Serialize, Deserialize, Debug, Clone, Copy, Default)]
124pub enum VariableType {
125 #[default]
126 StaticOnly, U8,
128 I32,
129 F32,
130 F64,
131}
132
133impl From<u8> for VariableType {
134 fn from(value: u8) -> Self {
135 match value {
136 1 => Self::U8,
137 2 => Self::I32,
138 3 => Self::F32,
139 4 => Self::F64,
140 _ => Self::default(),
141 }
142 }
143}
144
145impl From<VariableType> for u8 {
146 fn from(value: VariableType) -> Self {
147 match value {
148 VariableType::StaticOnly => 0,
149 VariableType::U8 => 1,
150 VariableType::I32 => 2,
151 VariableType::F32 => 3,
152 VariableType::F64 => 4,
153 }
154 }
155}
156
157use rkyv::rancor::Error as RkyvError;
158
159pub trait Sendable: Sized + Send + Sync + 'static
162where
163 Self: for<'b> Serialize<HighSerializer<AlignedVec, ArenaHandle<'b>, RkyvError>>,
164{
165}
166impl<T> Sendable for T
168where
169 T: Sized + Send + Sync + 'static,
170 T: for<'b> Serialize<HighSerializer<AlignedVec, ArenaHandle<'b>, RkyvError>>,
171{
172}
173
174#[async_trait::async_trait]
175pub trait Cannon: Send + Sync + 'static {
176 async fn shoot<'b, T: Sendable>(
180 &self,
181 targets: &'b [crate::NetworkShipAddress],
182 id: u32,
183 data: &T,
184 variable_type: VariableType,
185 variable_name: &str,
186 ) -> anyhow::Result<()>;
187
188 async fn catch<T>(&self, id: u32) -> anyhow::Result<Vec<T>>
192 where
193 T: Send,
194 T: Archive,
195 T::Archived: for<'a> CheckBytes<HighValidator<'a, rkyv::rancor::Error>>
196 + Deserialize<T, Strategy<Pool, rkyv::rancor::Error>>;
197
198 async fn catch_dyn(&self, id: u32) -> anyhow::Result<Vec<(String, VariableType, String)>>;
199}
200
201#[derive(Clone, Debug, Default, Copy, Archive, Serialize, Deserialize, PartialEq)]
202pub struct TimeMsg {
203 pub sec: i32,
204 pub nanosec: u32,
205}
206
207#[derive(Clone, Debug, Default, PartialEq, Archive, Serialize, Deserialize)]
208pub struct Header {
209 pub seq: u32,
210 pub stamp: TimeMsg,
211 pub frame_id: String,
212}
213
214pub type WindData = BagMsg;
215
216#[async_trait::async_trait]
217pub trait Coordinator: Send + Sync + 'static {
218 async fn rat_action_request_queue(
219 &self,
220 ship: String,
221 ) -> anyhow::Result<tokio::sync::broadcast::Receiver<String>>;
222
223 async fn blow_wind(&self, ship: String, data: Vec<WindData>) -> anyhow::Result<()>;
224
225 async fn rat_action_send(
226 &self,
227 ship: String,
228 action: ActionPlan,
229 lock_until_ack: bool,
230 ) -> anyhow::Result<()>;
231}