Skip to content

Commit

Permalink
Implement Mr. X position messages
Browse files Browse the repository at this point in the history
  • Loading branch information
konsumlamm committed May 23, 2024
1 parent dc7cf3b commit dfb24c9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 17 deletions.
17 changes: 15 additions & 2 deletions robusta/src/kvv.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use chrono::{DateTime, Utc};
use futures_util::future::join_all;
use lazy_static::lazy_static;
use serde::Serialize;
use serde::{Deserialize, Serialize};

use std::collections::HashMap;
use std::sync::OnceLock;
Expand All @@ -16,7 +16,7 @@ use crate::ws_message::Train;
const DEFAULT_WAIT_TIME: Duration = Duration::from_secs(30);

/// Information about a tram station.
#[derive(Debug, Serialize, specta::Type, PartialEq)]
#[derive(Debug, Serialize, Deserialize, specta::Type, Clone, PartialEq)]
pub struct Stop {
/// human readable stop name
pub name: String,
Expand Down Expand Up @@ -342,3 +342,16 @@ pub fn train_positions(departures_per_line: &LineDepartures, render_time: DateTi
.flat_map(|(journey_ref, departures)| train_position_per_route(render_time, journey_ref, departures, stops))
.collect()
}

pub fn nearest_stop(pos: Point) -> &'static Stop {
let stops = KVV_STOPS.get().expect("KVV_STOPS not initialized");
stops
.iter()
.min_by_key(|stop| {
pos.distance(Point {
latitude: stop.lat as f32,
longitude: stop.lon as f32,
}) as u64
})
.expect("no stops")
}
44 changes: 29 additions & 15 deletions robusta/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use axum::{
Json, Router,
};
use futures_util::SinkExt;
use point::Point;
use reqwest::StatusCode;
use tokio::sync::mpsc::{Receiver, Sender};
use tokio::time::Instant;
Expand All @@ -26,6 +27,7 @@ use tower_http::{
};
use tracing::{error, info, warn, Level};
use tracing_appender::rolling::{self, Rotation};
use ws_message::MrXPosition;

use crate::gadgets::{DetectiveGadget, GadgetState, MrXGadget};
use crate::kvv::LineDepartures;
Expand Down Expand Up @@ -388,7 +390,7 @@ async fn run_game_loop(mut recv: Receiver<InputMessage>, state: SharedState) {
let mut interval = tokio::time::interval(Duration::from_millis(500));

let running_state = Arc::new(tokio::sync::Mutex::new(RunningState::new()));
start_game(Arc::clone(&running_state)).await;
start_game(Arc::clone(&state), Arc::clone(&running_state)).await;

loop {
interval.tick().await;
Expand Down Expand Up @@ -603,50 +605,62 @@ impl RunningState {
}
}

async fn start_game(state: Arc<tokio::sync::Mutex<RunningState>>) {
async fn start_game(state: SharedState, running_state: Arc<tokio::sync::Mutex<RunningState>>) {
tokio::spawn(async move {
let mut warmup = true;

let mut time = Instant::now();
let mut interval = tokio::time::interval(Duration::from_millis(100));
loop {
interval.tick().await;
let mut state = state.lock().await;
let mut running_state = running_state.lock().await;

let old_time = time;
time = Instant::now();
let delta = (time - old_time).as_secs_f32();
if let Some(cooldown) = state.position_cooldown.as_mut() {
if let Some(cooldown) = running_state.position_cooldown.as_mut() {
*cooldown -= delta;
if *cooldown < 0.0 {
state.position_cooldown = Some(COOLDOWN);
running_state.position_cooldown = Some(COOLDOWN);
if warmup {
// TODO: broadcast Detective start
warmup = false;
state.mr_x_gadgets.allow_use();
state.detective_gadgets.allow_use();
running_state.mr_x_gadgets.allow_use();
running_state.detective_gadgets.allow_use();
} else {
// broadcast Mr. X position
match &state.special_pos {
let mut state = state.lock().await;
let position = match running_state.special_pos.take() {
Some(SpecialPos::Stop(stop_id)) => {
// TODO: broadcast stop id
MrXPosition::Stop(stop_id)
}
Some(SpecialPos::Image(image)) => {
// TODO: broadcast image
MrXPosition::Image(image)
}
Some(SpecialPos::NotFound) => {
// TODO: broadcast 404
MrXPosition::NotFound
}
None => {
// TODO: broadcast Mr. X position
let mr_x = state.teams.iter().find(|ts| ts.team.kind == TeamKind::MrX).expect("no Mr. X");
let stop = kvv::nearest_stop(Point { latitude: mr_x.lat, longitude: mr_x.long });
MrXPosition::Stop(stop.id.clone())
}
};
for connection in state.connections.iter_mut() {
if let Err(err) = connection
.send
.send(ClientResponse::MrXPosition(position.clone()))
.await
{
error!("failed to send Mr. X position to client {}: {}", connection.id, err);
continue;
}
}
state.special_pos = None;
}
}
}
state.mr_x_gadgets.update_time(delta);
state.detective_gadgets.update_time(delta);
running_state.mr_x_gadgets.update_time(delta);
running_state.detective_gadgets.update_time(delta);
}
});
}
9 changes: 9 additions & 0 deletions robusta/src/ws_message.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use serde::{Deserialize, Serialize};

use crate::gadgets::{DetectiveGadget, MrXGadget};
use crate::kvv::Stop;

#[derive(specta::Type, Clone, Deserialize, Debug)]
pub enum ClientMessage {
Expand All @@ -19,6 +20,14 @@ pub enum ClientResponse {
GameState(GameState),
MrXGadget(MrXGadget),
DetectiveGadget(DetectiveGadget),
MrXPosition(MrXPosition),
}

#[derive(specta::Type, Clone, Serialize, Deserialize, Debug)]
pub enum MrXPosition {
Stop(String),
Image(Vec<u8>),
NotFound,
}

#[derive(specta::Type, Default, Clone, Serialize, Deserialize, Debug)]
Expand Down

0 comments on commit dfb24c9

Please sign in to comment.