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 std::time::Duration;
use std::thread;
use std::iter::Enumerate;
use std::collections::hash_map::HashMap;
use prost::Message;
use std::io::Cursor;
@ -143,71 +142,99 @@ struct MQTTMessage {
payload: String,
}
#[derive(Debug)]
#[derive(Debug, Clone)]
struct Event {
divisions: HashMap<i32, Division>,
field_sets: HashMap<i32, FieldSet>,
}
impl Event {
fn from_match_list(msg: BackendMessage) -> Event {
let mut divisions: HashMap<i32, Division> = HashMap::new();
match msg.data.match_list {
Some(matches) => {
for m in matches.matches.iter() {
let match_tuple = MatchTuple{
division: m.division.unwrap(),
round: int_to_round(m.round.unwrap()),
instance: m.instance.unwrap(),
match_num: m.r#match.unwrap(),
session: m.session.unwrap(),
};
match divisions.get_mut(&match_tuple.division) {
Some(division) => {
division.matches.push(Match{
match_tuple: match_tuple.clone(),
})
},
None => {
let mut new_division = Division{
name: String::from(""),
matches: Vec::new(),
field_set: None,
};
new_division.matches.push(Match{
match_tuple: match_tuple.clone(),
});
divisions.insert(match_tuple.division, new_division);
},
}
}
},
None => log::warn!("Parsed match list without match_list"),
};
return Event{
divisions,
};
fn new() -> Event {
Event{
divisions: HashMap::new(),
field_sets: HashMap::new(),
}
}
// 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{
division: m.division.unwrap(),
round: int_to_round(m.round.unwrap()),
instance: m.instance.unwrap(),
match_num: m.r#match.unwrap(),
session: m.session.unwrap(),
};
match matches.get_mut(&match_tuple.division) {
Some(match_list) => {
match_list.push(Match{
match_tuple: match_tuple.clone(),
})
},
None => {
let mut new_match_list = Vec::new();
new_match_list.push(Match{
match_tuple: match_tuple.clone(),
});
matches.insert(match_tuple.division, new_match_list);
},
}
}
for (id, match_list) in matches {
match self.divisions.get_mut(&id) {
None => log::warn!("parsed match list with nonexistant division {}", id),
Some(division) => division.matches = match_list,
}
}
}
}
#[derive(Debug)]
#[derive(Debug, Clone)]
struct Division {
name: String,
matches: Vec<Match>,
field_set: Option<FieldSet>,
}
#[derive(Debug)]
#[derive(Debug, Clone)]
struct FieldSet {
fields: Vec<Field>,
}
#[derive(Debug)]
#[derive(Debug, Clone)]
struct Field {
name: String,
current_match: u32,
id: i32,
last_known_match: Option<MatchTuple>,
}
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, Clone)]
struct Match {
match_tuple: MatchTuple,
}
@ -420,13 +447,6 @@ struct TMClient {
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;
impl TMClient {
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> {
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) {
None => (Vec::new(), event),
None => Vec::new(),
Some(tuple) => {
// Use `event` to figure out which arena topic to publish to
// Also add the match score topic based on the tuple
match get_game_score(&notice) {
None => (Vec::new(), event),
None => Vec::new(),
Some(score) => {
let serialized = serde_json::to_string(&score).unwrap();
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,
payload: serialized,
});
return (out, event);
return out;
},
}
},
}
}
fn on_match_start(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_match_start(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn on_match_cancel(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_match_cancel(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn on_match_reset(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_match_reset(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn on_match_assigned(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_match_assigned(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn on_active_field_changed(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_active_field_changed(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn on_rankings_updated(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_rankings_updated(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn on_event_status_updated(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_event_status_updated(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn on_elim_alliance_update(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_elim_alliance_update(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn on_elim_unavail_teams_update(_notice: tm::Notice, event: Event, _connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
fn on_elim_unavail_teams_update(_notice: tm::Notice, event: &mut Event, _connection: &TMConnection) -> Vec<MQTTMessage> {
return Vec::new();
}
fn _on_match_list_update(connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
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);
fn on_match_list_update(_notice: tm::Notice, event: &mut Event, connection: &TMConnection) -> Vec<MQTTMessage> {
let mut messages = Vec::new();
for (division_id, division) in new_event.divisions.iter() {
messages.push(MQTTMessage{
topic: format!("division/{}/schedule", division_id),
payload: serde_json::to_string(&division.matches).unwrap(),
});
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{
topic: format!("division/{}/schedule", division_id),
payload: serde_json::to_string(&division.matches).unwrap(),
});
}
},
}
return (messages, new_event);
}
fn on_match_list_update(_notice: tm::Notice, _event: Event, connection: &TMConnection) -> (Vec<MQTTMessage>, Event) {
return _on_match_list_update(connection);
return messages;
}
fn main() {
@ -845,15 +865,30 @@ fn main() {
}
);
let (messages, mut event) = _on_match_list_update(&tm_connection);
for message in messages {
let result = client.publish(message.topic, QoS::AtMostOnce, true, message.payload);
match result {
Ok(_) => {},
Err(error) => log::error!("Publish error: {}", error),
let mut event = Event::new();
let division_list_resp = tm_connection.request(200, tm::BackendMessageData::default());
event.parse_division_list(division_list_resp.data.division_list.unwrap());
let field_set_resp = tm_connection.request(300, tm::BackendMessageData::default());
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 {
thread::sleep(Duration::from_millis(1000));
@ -868,8 +903,7 @@ fn main() {
}
},
Some(callback) => {
let (messages, next_event) = callback(*notice, event, &tm_connection);
event = next_event;
let messages = callback(*notice, &mut event, &tm_connection);
for message in messages {
let result = client.publish(message.topic, QoS::AtMostOnce, true, message.payload);
match result {