send info when connecting

This commit is contained in:
catvayor 2024-09-10 15:39:59 +02:00
parent ebc217ce2a
commit 799724b122
Signed by: lbailly
GPG key ID: CE3E645251AC63F3
5 changed files with 109 additions and 76 deletions

View file

@ -11,7 +11,7 @@ use rocket::{
}; };
use rocket_dyn_templates::{context, Template}; use rocket_dyn_templates::{context, Template};
use crate::global::*; use crate::{coords::admin_view, global::*};
struct AdminAuth(String); struct AdminAuth(String);

85
src/coords.rs Normal file
View file

@ -0,0 +1,85 @@
use crate::global::{TrackedState::*, *};
use rand::Rng;
use rocket::{response::stream::Event, tokio::time::Duration};
pub fn base_view(team: &Tracked) -> TrackedInfo {
TrackedInfo {
name: team.name.clone(),
pos: team.pos,
color: team.state.color(),
}
}
pub fn admin_view(team: &Tracked) -> AdminTrackedInfo {
AdminTrackedInfo {
name: team.name.clone(),
id: team.id.clone(),
pos: team.pos,
color: team.state.admin_color(),
state: team.state.clone(),
}
}
pub fn apparent_info(
watcher: &Tracked,
team: &Tracked,
blurred_move: (f32, f32),
) -> Option<TrackedInfo> {
if watcher.id == team.id {
None
} else if let Conscrit { captured, .. } = watcher.state {
if captured {
if team.state.invisible() || team.state.npc() {
None
} else if team.state.blurred() {
let mut rng = rand::thread_rng();
let (lat, lon) = team.pos;
Some(TrackedInfo {
pos: (
lat + blurred_move.0 * (rng.gen::<f32>() * 2.0 - 1.0),
lon + blurred_move.1 * (rng.gen::<f32>() * 2.0 - 1.0),
),
..base_view(team)
})
} else {
Some(base_view(team))
}
} else {
Some(base_view(team))
}
} else {
Some(admin_view(team).into())
}
}
pub fn send_coords_to(
watcher: &Tracked,
evt_queue: &TrackedEventQueue,
tracking: &Tracking,
config: &Config,
) {
if watcher.last_coord.elapsed() > Duration::from_millis(config.fairness_timeout) {
return;
}
let mut infos: Vec<TrackedInfo> = Vec::new();
for (_, tracked) in tracking.iter() {
if let Some(info) = apparent_info(&watcher, &tracked.read().unwrap(), config.blurred_move) {
infos.push(info);
}
}
evt_queue
.write()
.unwrap()
.push_back(Event::json(&infos).event("coords").into());
}
pub fn send_coords(tracking: &Tracking, evt_queue: &TrackingEventQueue, config: &Config) {
for (id, queue) in evt_queue.iter() {
send_coords_to(
&tracking.get(id).unwrap().read().unwrap(),
&queue,
tracking,
config,
);
}
}

View file

@ -1,4 +1,3 @@
use rand::Rng;
use rocket::{ use rocket::{
response::stream::Event, response::stream::Event,
serde::{Deserialize, Serialize}, serde::{Deserialize, Serialize},
@ -9,6 +8,8 @@ use std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
use crate::coords::*;
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
pub struct TeamConfig { pub struct TeamConfig {
@ -168,7 +169,8 @@ impl From<QueuedEvent> for Event {
} }
pub type Tracking = Arc<HashMap<String, RwLock<Tracked>>>; pub type Tracking = Arc<HashMap<String, RwLock<Tracked>>>;
pub type TrackingEventQueue = Arc<HashMap<String, RwLock<VecDeque<QueuedEvent>>>>; pub type TrackedEventQueue = RwLock<VecDeque<QueuedEvent>>;
pub type TrackingEventQueue = Arc<HashMap<String, TrackedEventQueue>>;
pub type AdminEventQueue = Arc<RwLock<VecDeque<QueuedEvent>>>; pub type AdminEventQueue = Arc<RwLock<VecDeque<QueuedEvent>>>;
#[derive(Serialize)] #[derive(Serialize)]
@ -199,56 +201,6 @@ impl From<AdminTrackedInfo> for TrackedInfo {
} }
} }
pub fn base_view(team: &Tracked) -> TrackedInfo {
TrackedInfo {
name: team.name.clone(),
pos: team.pos,
color: team.state.color(),
}
}
pub fn admin_view(team: &Tracked) -> AdminTrackedInfo {
AdminTrackedInfo {
name: team.name.clone(),
id: team.id.clone(),
pos: team.pos,
color: team.state.admin_color(),
state: team.state.clone(),
}
}
pub fn apparent_info(
watcher: &Tracked,
team: &Tracked,
blurred_move: (f32, f32),
) -> Option<TrackedInfo> {
if watcher.id == team.id {
None
} else if let Conscrit { captured, .. } = watcher.state {
if captured {
if team.state.invisible() || team.state.npc() {
None
} else if team.state.blurred() {
let mut rng = rand::thread_rng();
let (lat, lon) = team.pos;
Some(TrackedInfo {
pos: (
lat + blurred_move.0 * (rng.gen::<f32>() * 2.0 - 1.0),
lon + blurred_move.1 * (rng.gen::<f32>() * 2.0 - 1.0),
),
..base_view(team)
})
} else {
Some(base_view(team))
}
} else {
Some(base_view(team))
}
} else {
Some(admin_view(team).into())
}
}
pub fn evts_to_send(evt_queue: &RwLock<VecDeque<QueuedEvent>>, timeout: Duration) -> Vec<Event> { pub fn evts_to_send(evt_queue: &RwLock<VecDeque<QueuedEvent>>, timeout: Duration) -> Vec<Event> {
evt_queue evt_queue
.read() .read()

View file

@ -4,7 +4,7 @@ use rocket::{
fairing::AdHoc, fairing::AdHoc,
fs::{relative, FileServer}, fs::{relative, FileServer},
http::Status, http::Status,
response::{content, stream::Event}, response::content,
tokio::{ tokio::{
self, select, self, select,
time::{self, Duration}, time::{self, Duration},
@ -19,8 +19,10 @@ use std::{
}; };
mod admin; mod admin;
mod coords;
mod global; mod global;
mod track; mod track;
use coords::*;
use global::*; use global::*;
#[get("/")] #[get("/")]
@ -28,27 +30,6 @@ fn index() -> &'static str {
"Hello, world!" "Hello, world!"
} }
fn send_coords(tracking: &Tracking, evt_queue: &TrackingEventQueue, config: &Config) {
for (id, queue) in evt_queue.iter() {
let watcher = tracking.get(id).unwrap().read().unwrap();
if watcher.last_coord.elapsed() > Duration::from_millis(config.fairness_timeout) {
continue
}
let mut infos: Vec<TrackedInfo> = Vec::new();
for (_, tracked) in tracking.iter() {
if let Some(info) =
apparent_info(&watcher, &tracked.read().unwrap(), config.blurred_move)
{
infos.push(info);
}
}
queue
.write()
.unwrap()
.push_back(Event::json(&infos).event("coords").into());
}
}
fn clean_expired_evt( fn clean_expired_evt(
evt_queues: &TrackingEventQueue, evt_queues: &TrackingEventQueue,
admin_queue: &AdminEventQueue, admin_queue: &AdminEventQueue,

View file

@ -9,7 +9,10 @@ use rocket::{
}; };
use rocket_dyn_templates::{context, Template}; use rocket_dyn_templates::{context, Template};
use crate::global::{TrackedState::*, *}; use crate::{
coords::*,
global::{TrackedState::*, *},
};
#[get("/")] #[get("/")]
fn no_id() -> Status { fn no_id() -> Status {
@ -44,12 +47,24 @@ fn tracked_view(
#[get("/<id>/events")] #[get("/<id>/events")]
fn tracked_events<'a>( fn tracked_events<'a>(
id: &'a str, id: &'a str,
tracking: &'a State<Tracking>,
evt_queue: &'a State<TrackingEventQueue>, evt_queue: &'a State<TrackingEventQueue>,
config: &State<Config>, config: &State<Config>,
mut shutdown: Shutdown, mut shutdown: Shutdown,
) -> Result<EventStream![Event + 'a], Status> { ) -> Result<EventStream![Event + 'a], Status> {
if evt_queue.contains_key(&id.to_string()) { if evt_queue.contains_key(&id.to_string()) {
let timeout = Duration::from_millis(config.event_timeout); let timeout = Duration::from_millis(config.event_timeout);
send_coords_to(
&tracking.get(id).unwrap().read().unwrap(),
&evt_queue.get(id).unwrap(),
tracking,
config,
);
evt_queue.get(id).unwrap().write().unwrap().push_back(
Event::json(&admin_view(&tracking.get(id).unwrap().read().unwrap()))
.event("self_info")
.into(),
);
Ok(EventStream! { Ok(EventStream! {
let mut interval = time::interval(timeout); let mut interval = time::interval(timeout);
loop { loop {