diff --git a/src/main.rs b/src/main.rs index 2c5640d..158d18f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -158,7 +158,7 @@ fn get_match(divisions: &mut HashMap, tuple: MatchTuple) -> Optio None => {}, Some(division) => { for m in &mut division.matches { - if m.tuple == tuple { + if m.info.tuple == tuple { return Some(m); } } @@ -233,7 +233,7 @@ impl Event { start: started as f64 / 1000.0, }, Some(division) => { - match division.matches.iter().find(|a| a.tuple == tuple) { + match division.matches.iter().find(|a| a.info.tuple == tuple) { None => match_state = MatchState{ state: GameState::Scheduled, start: started as f64 / 1000.0, @@ -261,12 +261,12 @@ impl Event { match_list.push(Match{ state: match_state, info: MatchInfo{ + tuple: tuple.clone(), red_teams: [String::from(red_1), String::from(red_2)], blue_teams: [String::from(blue_1), String::from(blue_2)], field, }, score: None, - tuple: tuple.clone(), }) }, None => { @@ -274,12 +274,12 @@ impl Event { new_match_list.push(Match{ state: match_state, info: MatchInfo{ + tuple: tuple.clone(), red_teams: [String::from(red_1), String::from(red_2)], blue_teams: [String::from(blue_1), String::from(blue_2)], field, }, score: None, - tuple: tuple.clone(), }); matches.insert(tuple.division, new_match_list); }, @@ -327,6 +327,7 @@ struct MatchState { #[derive(Serialize, Deserialize, Debug, Clone)] struct MatchInfo { + tuple: MatchTuple, red_teams: [String; 2], blue_teams: [String; 2], field: FieldTuple, @@ -337,7 +338,6 @@ struct Match { state: MatchState, info: MatchInfo, score: Option, - tuple: MatchTuple, } #[derive(Debug)] @@ -920,7 +920,7 @@ fn on_score_set(notice: tm::Notice, event: &mut Event, _connection: &mut TMConne let Some(scores) = notice.match_score else { return Vec::new() }; let Some(score) = get_game_score(&scores) else { return Vec::new() }; let Some(division) = &mut event.divisions.get_mut(&tuple.division) else { return Vec::new() }; - let Some(m) = &mut division.matches.iter_mut().find(|a| a.tuple == tuple) else { return Vec::new() }; + let Some(m) = &mut division.matches.iter_mut().find(|a| a.info.tuple == tuple) else { return Vec::new() }; m.score = Some(score.clone()); m.state = MatchState{ @@ -930,33 +930,29 @@ fn on_score_set(notice: tm::Notice, event: &mut Event, _connection: &mut TMConne let score_serialized = serde_json::to_string_pretty(&m.score).unwrap(); let state_serialized = serde_json::to_string_pretty(&m.state).unwrap(); - let game_score_topic = format!("division/{}/{:?}/{}/score", tuple.division, tuple.round, tuple.match_num); - let game_state_topic = format!("division/{}/{:?}/{}/state", tuple.division, tuple.round, tuple.match_num); let mut out = Vec::new(); out.push(MQTTMessage{ - topic: game_score_topic, + topic: tuple.topic("/score"), payload: score_serialized.clone(), }); out.push(MQTTMessage{ - topic: game_state_topic, + topic: tuple.topic("/state"), payload: state_serialized.clone(), }); - for (field_set_id, field_set) in &event.field_sets { - for (field_id, field) in &field_set.fields { + for (_, field_set) in &event.field_sets { + for (_, field) in &field_set.fields { match field.last_known_match { None => {}, Some(last_known_match) => { if last_known_match == tuple { - let field_score_topic = format!("field/{}/{}/score", field_set_id, field_id); - let field_state_topic = format!("field/{}/{}/state", field_set_id, field_id); out.push(MQTTMessage{ - topic: field_score_topic, + topic: field.tuple.topic("/score"), payload: score_serialized.clone(), }); out.push(MQTTMessage{ - topic: field_state_topic, + topic: field.tuple.topic("/state"), payload: state_serialized.clone(), }); } @@ -972,26 +968,24 @@ fn on_score_change(notice: tm::Notice, event: &mut Event, _connection: &mut TMCo let Some(scores) = notice.match_score else { return Vec::new() }; let Some(score) = get_game_score(&scores) else { return Vec::new() }; let Some(division) = &mut event.divisions.get_mut(&tuple.division) else { return Vec::new() }; - let Some(m) = &mut division.matches.iter_mut().find(|a| a.tuple == tuple) else { return Vec::new() }; + let Some(m) = &mut division.matches.iter_mut().find(|a| a.info.tuple == tuple) else { return Vec::new() }; m.score = Some(score.clone()); let serialized = serde_json::to_string_pretty(&score).unwrap(); - let game_topic = format!("division/{}/{:?}/{}/score", tuple.division, tuple.round, tuple.match_num); let mut out = Vec::new(); out.push(MQTTMessage{ - topic: game_topic, + topic: tuple.topic("/score"), payload: serialized.clone(), }); - for (field_set_id, field_set) in &event.field_sets { - for (field_id, field) in &field_set.fields { + for (_, field_set) in &event.field_sets { + for (_, field) in &field_set.fields { match field.last_known_match { None => {}, Some(last_known_match) => { if last_known_match == tuple { - let field_topic = format!("field/{}/{}/score", field_set_id, field_id); out.push(MQTTMessage{ - topic: field_topic, + topic: field.tuple.topic("/score"), payload: serialized.clone(), }); } @@ -1017,13 +1011,41 @@ fn on_match_list_update(_notice: tm::Notice, event: &mut Event, connection: &mut for m in &division.matches { let serialized = serde_json::to_string_pretty(&m.info).unwrap(); messages.push(MQTTMessage{ - topic: m.tuple.topic(""), + topic: m.info.tuple.topic(""), payload: serialized }); + + let serialized_state = serde_json::to_string_pretty(&m.state).unwrap(); + messages.push(MQTTMessage{ + topic: m.info.tuple.topic("/state"), + payload: serialized_state, + }); } } }, } + + for (_, field_set) in &event.field_sets { + for (_, field) in &field_set.fields { + match field.last_known_match { + None => {}, + Some(tuple) => { + let Some(m) = get_match(&mut event.divisions, tuple) else {continue;}; + let serialized_state = serde_json::to_string_pretty(&m.state).unwrap(); + let serialized = serde_json::to_string_pretty(&m.info).unwrap(); + messages.push(MQTTMessage{ + topic: field.tuple.topic(""), + payload: serialized, + }); + messages.push(MQTTMessage{ + topic: field.tuple.topic("/state"), + payload: serialized_state, + }); + }, + } + } + } + return messages; } @@ -1048,23 +1070,26 @@ fn on_field_assigned(notice: tm::Notice, event: &mut Event, _connection: &mut TM let mut messages = Vec::new(); let serialized = serde_json::to_string_pretty(&m.state).unwrap(); - let field_topic = field_info.topic("/state"); - let match_topic = tuple.topic("/state"); + let serialized_info = serde_json::to_string_pretty(&m.info).unwrap(); messages.push(MQTTMessage{ - topic: field_topic, + topic: field_info.topic("/state"), payload: serialized.clone(), }); messages.push(MQTTMessage{ - topic: match_topic, + topic: field_info.topic(""), + payload: serialized_info, + }); + + messages.push(MQTTMessage{ + topic: tuple.topic("/state"), payload: serialized, }); if let Some(score) = &m.score { let serialized = serde_json::to_string_pretty(&score).unwrap(); - let topic = tuple.topic("/score"); messages.push(MQTTMessage{ - topic, + topic: tuple.topic("/score"), payload: serialized, }); } @@ -1245,14 +1270,14 @@ fn main() { for (_, division) in &mut event.divisions { for m in &mut division.matches { let serialized = serde_json::to_string_pretty(&m.info).unwrap(); - client.publish(m.tuple.topic(""), QoS::AtLeastOnce, true, serialized).unwrap(); - m.score = get_match_score(&tm_connection, struct_tuple_to_tm(m.tuple)); + client.publish(m.info.tuple.topic(""), QoS::AtLeastOnce, true, serialized).unwrap(); + m.score = get_match_score(&tm_connection, struct_tuple_to_tm(m.info.tuple)); let state_serialized = serde_json::to_string_pretty(&m.state).unwrap(); - client.publish(m.tuple.topic("/state"), QoS::AtLeastOnce, true, state_serialized).unwrap(); + client.publish(m.info.tuple.topic("/state"), QoS::AtLeastOnce, true, state_serialized).unwrap(); if let Some(score) = &m.score { let serialized_score = serde_json::to_string_pretty(score).unwrap(); - client.publish(m.tuple.topic("/score"), QoS::AtLeastOnce, true, serialized_score).unwrap(); + client.publish(m.info.tuple.topic("/score"), QoS::AtLeastOnce, true, serialized_score).unwrap(); } } } @@ -1280,6 +1305,8 @@ fn main() { None => {}, Some(field) => { field.last_known_match = Some(tuple); + let serialized = serde_json::to_string_pretty(&m.info).unwrap(); + client.publish(field.tuple.topic(""), QoS::AtLeastOnce, true, serialized).unwrap(); let serialized_score = serde_json::to_string_pretty(&m.score).unwrap(); client.publish(field.tuple.topic("/score"), QoS::AtLeastOnce, true, serialized_score).unwrap(); let serialized_state = serde_json::to_string_pretty(&m.state).unwrap(); @@ -1324,11 +1351,9 @@ fn main() { None => log::warn!("Received state change for unknown match {:#?}", state_change.tuple), Some(m) => { m.state = state_change.next_state.clone(); - let field_state_topic = format!("field/{}/{}/state", state_change.field.set, state_change.field.id); - let match_state_topic = format!("division/{}/{:?}/{}/score", state_change.tuple.division, state_change.tuple.round, state_change.tuple.match_num); - let payload = serde_json::to_vec_pretty(&state_change.next_state).unwrap(); - client.publish(field_state_topic, QoS::AtLeastOnce, true, payload.clone()).expect("Failed MQTT publish"); - client.publish(match_state_topic, QoS::AtLeastOnce, true, payload).expect("Failed MQTT publish"); + let state_serialized = serde_json::to_vec_pretty(&state_change.next_state).unwrap(); + client.publish(state_change.field.topic("/state"), QoS::AtLeastOnce, true, state_serialized.clone()).expect("Failed MQTT publish"); + client.publish(m.info.tuple.topic("/state"), QoS::AtLeastOnce, true, state_serialized).expect("Failed MQTT publish"); }, } },