send info when connecting
This commit is contained in:
parent
ebc217ce2a
commit
799724b122
5 changed files with 109 additions and 76 deletions
|
@ -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
85
src/coords.rs
Normal 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -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,
|
||||||
|
|
17
src/track.rs
17
src/track.rs
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue