Can't remember what changed tbh

master
noah metz 2024-01-21 15:33:00 -07:00
parent 0642a9980a
commit 38cfa8e932
1 changed files with 145 additions and 111 deletions

@ -2,7 +2,6 @@ use rumqttc::{MqttOptions, Client, QoS, LastWill};
use bytes::Bytes; use bytes::Bytes;
use std::time::Duration; use std::time::Duration;
use std::thread; use std::thread;
use std::iter::Enumerate;
use std::collections::hash_map::HashMap; use std::collections::hash_map::HashMap;
use prost::Message; use prost::Message;
use std::io::Cursor; use std::io::Cursor;
@ -143,17 +142,49 @@ struct MQTTMessage {
payload: String, payload: String,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
struct Event { struct Event {
divisions: HashMap<i32, Division>, divisions: HashMap<i32, Division>,
field_sets: HashMap<i32, FieldSet>,
} }
impl Event { impl Event {
fn from_match_list(msg: BackendMessage) -> Event { fn new() -> Event {
let mut divisions: HashMap<i32, Division> = HashMap::new(); Event{
match msg.data.match_list { divisions: HashMap::new(),
Some(matches) => { field_sets: HashMap::new(),
for m in matches.matches.iter() { }
}
// TODO: remove extra entries instead of just adding new ones
fn parse_field_sets(self: &mut Event, sets: tm::FieldSetList) {
for set in sets.field_sets {
let mut fields = Vec::new();
for field in &set.fields {
fields.push(Field{
name: String::from(field.name()),
id: field.id(),
last_known_match: None,
});
}
self.field_sets.insert(set.id(), FieldSet{
fields,
});
}
}
fn parse_division_list(self: &mut Event, division_list: tm::DivisionList) {
for division in division_list.divisions {
self.divisions.insert(division.id() as i32, Division{
name: String::from(division.name()),
matches: Vec::new(),
});
}
}
fn parse_match_list(self: &mut Event, match_list: tm::MatchList) {
let mut matches: HashMap<i32, Vec<Match>> = HashMap::new();
for m in match_list.matches.iter() {
let match_tuple = MatchTuple{ let match_tuple = MatchTuple{
division: m.division.unwrap(), division: m.division.unwrap(),
round: int_to_round(m.round.unwrap()), round: int_to_round(m.round.unwrap()),
@ -161,53 +192,49 @@ impl Event {
match_num: m.r#match.unwrap(), match_num: m.r#match.unwrap(),
session: m.session.unwrap(), session: m.session.unwrap(),
}; };
match divisions.get_mut(&match_tuple.division) { match matches.get_mut(&match_tuple.division) {
Some(division) => { Some(match_list) => {
division.matches.push(Match{ match_list.push(Match{
match_tuple: match_tuple.clone(), match_tuple: match_tuple.clone(),
}) })
}, },
None => { None => {
let mut new_division = Division{ let mut new_match_list = Vec::new();
name: String::from(""), new_match_list.push(Match{
matches: Vec::new(),
field_set: None,
};
new_division.matches.push(Match{
match_tuple: match_tuple.clone(), match_tuple: match_tuple.clone(),
}); });
divisions.insert(match_tuple.division, new_division); matches.insert(match_tuple.division, new_match_list);
}, },
} }
} }
}, for (id, match_list) in matches {
None => log::warn!("Parsed match list without match_list"), match self.divisions.get_mut(&id) {
}; None => log::warn!("parsed match list with nonexistant division {}", id),
return Event{ Some(division) => division.matches = match_list,
divisions, }
}; }
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
struct Division { struct Division {
name: String, name: String,
matches: Vec<Match>, matches: Vec<Match>,
field_set: Option<FieldSet>,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
struct FieldSet { struct FieldSet {
fields: Vec<Field>, fields: Vec<Field>,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
struct Field { struct Field {
name: String, name: String,
current_match: u32, id: i32,
last_known_match: Option<MatchTuple>,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug, Clone)]
struct Match { struct Match {
match_tuple: MatchTuple, match_tuple: MatchTuple,
} }
@ -420,13 +447,6 @@ struct TMClient {
connected: bool, connected: bool,
} }
struct TMConnection {
notices: mpsc::Receiver<Box<tm::Notice>>,
responses: mpsc::Receiver<Box<BackendMessage>>,
requests: mpsc::Sender<Box<BackendMessage>>,
}
const TCP_BUFFER_SIZE: usize = 10000; const TCP_BUFFER_SIZE: usize = 10000;
impl TMClient { impl TMClient {
fn new(uuid: [u8; 16], client_name: [u8; 32], password: String, username: [u8; 16]) -> (TMClient, TMConnection) { fn new(uuid: [u8; 16], client_name: [u8; 32], password: String, username: [u8; 16]) -> (TMClient, TMConnection) {
@ -566,7 +586,20 @@ impl TMClient {
} }
} }
type NoticeCallback = fn(tm::Notice, Event, &TMConnection) -> (Vec<MQTTMessage>, Event); struct TMConnection {
notices: mpsc::Receiver<Box<tm::Notice>>,
responses: mpsc::Receiver<Box<BackendMessage>>,
requests: mpsc::Sender<Box<BackendMessage>>,
}
impl TMConnection {
fn request(self: &TMConnection, request_id: u32, data: tm::BackendMessageData) -> BackendMessage {
self.requests.send(Box::new(BackendMessage::new(request_id, data))).unwrap();
return *self.responses.recv().unwrap();
}
}
type NoticeCallback = fn(tm::Notice, &mut Event, &TMConnection) -> Vec<MQTTMessage>;
fn get_affected_match(notice: &tm::Notice) -> Option<MatchTuple> { fn get_affected_match(notice: &tm::Notice) -> Option<MatchTuple> {
match &notice.affected_match { match &notice.affected_match {
@ -707,14 +740,14 @@ fn get_game_score(notice: &tm::Notice) -> Option<GameScore> {
} }
} }
fn on_score_change(notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_score_change(notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
match get_affected_match(&notice) { match get_affected_match(&notice) {
None => (Vec::new(), event), None => Vec::new(),
Some(tuple) => { Some(tuple) => {
// Use `event` to figure out which arena topic to publish to // Use `event` to figure out which arena topic to publish to
// Also add the match score topic based on the tuple // Also add the match score topic based on the tuple
match get_game_score(&notice) { match get_game_score(&notice) {
None => (Vec::new(), event), None => Vec::new(),
Some(score) => { Some(score) => {
let serialized = serde_json::to_string(&score).unwrap(); let serialized = serde_json::to_string(&score).unwrap();
let game_topic = format!("division/{}/{:?}/{}/score", tuple.division, tuple.round, tuple.match_num); let game_topic = format!("division/{}/{:?}/{}/score", tuple.division, tuple.round, tuple.match_num);
@ -723,78 +756,65 @@ fn on_score_change(notice: tm::Notice, event: Event, _connection: &TMConnection)
topic: game_topic, topic: game_topic,
payload: serialized, payload: serialized,
}); });
return (out, event); return out;
}, },
} }
}, },
} }
} }
fn on_match_start(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_match_start(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn on_match_cancel(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_match_cancel(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn on_match_reset(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_match_reset(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn on_match_assigned(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_match_assigned(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn on_active_field_changed(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_active_field_changed(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn on_rankings_updated(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_rankings_updated(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn on_event_status_updated(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_event_status_updated(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn on_elim_alliance_update(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_elim_alliance_update(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn on_elim_unavail_teams_update(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_elim_unavail_teams_update(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return (Vec::new(), event); return Vec::new();
} }
fn _on_match_list_update(connection: &TMConnection) -> (Vec<MQTTMessage>, Event) { fn on_match_list_update(_notice: tm::Notice, event: &mut Event, connection: &TMConnection) -> Vec<MQTTMessage> {
let mut get_match_list_tuple = tm::MatchTuple::default();
get_match_list_tuple.division = Some(0);
get_match_list_tuple.round = None;
get_match_list_tuple.instance = Some(0);
get_match_list_tuple.r#match = Some(0);
get_match_list_tuple.session = Some(0);
let mut get_match_list_data = tm::BackendMessageData::default();
get_match_list_data.match_tuple = Some(get_match_list_tuple);
let get_match_list_req = BackendMessage::new(1002, get_match_list_data.clone());
connection.requests.send(Box::new(get_match_list_req)).unwrap();
let get_match_list_resp = connection.responses.recv().unwrap();
let new_event = Event::from_match_list(*get_match_list_resp);
let mut messages = Vec::new(); let mut messages = Vec::new();
for (division_id, division) in new_event.divisions.iter() { let match_list_resp = connection.request(1002, tm::BackendMessageData::default());
match match_list_resp.data.match_list {
None => {},
Some(match_list) => {
event.parse_match_list(match_list);
for (division_id, division) in &event.divisions {
messages.push(MQTTMessage{ messages.push(MQTTMessage{
topic: format!("division/{}/schedule", division_id), topic: format!("division/{}/schedule", division_id),
payload: serde_json::to_string(&division.matches).unwrap(), payload: serde_json::to_string(&division.matches).unwrap(),
}); });
} }
return (messages, new_event); },
} }
return messages;
fn on_match_list_update(_notice: tm::Notice, _event: Event, connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return _on_match_list_update(connection);
} }
fn main() { fn main() {
@ -845,15 +865,30 @@ fn main() {
} }
); );
let (messages, mut event) = _on_match_list_update(&tm_connection); let mut event = Event::new();
for message in messages { let division_list_resp = tm_connection.request(200, tm::BackendMessageData::default());
let result = client.publish(message.topic, QoS::AtMostOnce, true, message.payload); event.parse_division_list(division_list_resp.data.division_list.unwrap());
match result {
Ok(_) => {}, let field_set_resp = tm_connection.request(300, tm::BackendMessageData::default());
Err(error) => log::error!("Publish error: {}", error), event.parse_field_sets(field_set_resp.data.field_set_list.unwrap());
let match_list_resp = tm_connection.request(1002, tm::BackendMessageData::default());
event.parse_match_list(match_list_resp.data.match_list.unwrap());
for (field_set_id, field_set) in &event.field_sets {
for field in &field_set.fields {
let mut field_req = tm::BackendMessageData::default();
let mut field_data = tm::OnFieldMatch::default();
let mut f = tm::Field::default();
f.id = Some(field.id);
f.field_set_id = Some(*field_set_id);
field_data.field = Some(f);
field_req.on_field_match = Some(field_data);
let field_resp = tm_connection.request(309, field_req);
println!("Field {}/{}: {:#?}", field_set_id, field.id, field_resp);
} }
} }
log::debug!("Initial event: {:?}", event);
while running { while running {
thread::sleep(Duration::from_millis(1000)); thread::sleep(Duration::from_millis(1000));
@ -868,8 +903,7 @@ fn main() {
} }
}, },
Some(callback) => { Some(callback) => {
let (messages, next_event) = callback(*notice, event, &tm_connection); let messages = callback(*notice, &mut event, &tm_connection);
event = next_event;
for message in messages { for message in messages {
let result = client.publish(message.topic, QoS::AtMostOnce, true, message.payload); let result = client.publish(message.topic, QoS::AtMostOnce, true, message.payload);
match result { match result {