event stream

This commit is contained in:
catvayor 2024-05-16 22:24:47 +02:00
parent 9ebf7b0f0a
commit a0ec314cac
5 changed files with 120 additions and 25 deletions

1
Cargo.lock generated
View file

@ -1085,6 +1085,7 @@ dependencies = [
"rocket_codegen",
"rocket_http",
"serde",
"serde_json",
"state",
"tempfile",
"time",

View file

@ -5,8 +5,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = "0.5.0"
[dependencies.rocket]
version = "0.5.0"
features = ["json"]
[dependencies.rocket_dyn_templates]
version = "0.1.0"

View file

@ -3,5 +3,5 @@ let
fenix = import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { };
in
pkgs.mkShell {
buildInputs = with fenix.latest; [ cargo rustc ];
buildInputs = with fenix.latest; [ cargo rustc rustfmt ];
}

View file

@ -1,11 +1,17 @@
#[macro_use] extern crate rocket;
use rocket::fs::{FileServer, relative};
use rocket::State;
use std::{
collections::HashMap,
sync::RwLock,
#[macro_use]
extern crate rocket;
use rocket::{
fs::{relative, FileServer},
response::stream::{Event, EventStream},
serde::Serialize,
tokio::{
select,
time::{self, Duration},
},
Shutdown, State,
};
use rocket_dyn_templates::{Template, context};
use rocket_dyn_templates::{context, Template};
use std::{collections::HashMap, sync::RwLock};
enum TrackedState {
Conscrit {
@ -19,7 +25,7 @@ enum TrackedState {
Vieux {
color: u8,
invisible: bool,
}
},
}
struct Tracked {
@ -28,20 +34,90 @@ struct Tracked {
state: TrackedState,
}
fn build_conscrit(name: String) -> Tracked {
Tracked {
name: name,
pos: (0.0, 0.0),
state: TrackedState::Conscrit {
invisible: false,
blurred: false,
captured: false,
malette: false,
invisibility_codes: 0,
blur_codes: 0,
},
}
}
fn build_vieux(name: String) -> Tracked {
Tracked {
name: name,
pos: (0.0, 0.0),
state: TrackedState::Vieux {
invisible: true,
color: 1,
},
}
}
type Tracking = RwLock<HashMap<String, RwLock<Tracked>>>;
#[get("/track/conscrit")]
fn conscrit() -> Template{
Template::render("conscrit", context!{
name: "un nom",
id: "ID",
gpslog: "no"
})
#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
struct TrackedInfo {
name: String,
pos: (f32, f32),
}
#[get("/track/<id>?<gpslog>")]
fn tracked_view(id: &str, gpslog: Option<bool>, tracking: &State<Tracking>) -> Option<Template> {
if let Some(tracked) = tracking.read().unwrap().get(&id.to_string()) {
Some(Template::render(
match tracked.read().unwrap().state {
TrackedState::Vieux { .. } => "vieux",
TrackedState::Conscrit { .. } => "conscrit",
},
context! {
name: &tracked.read().unwrap().name,
id: &id,
gpslog: gpslog.unwrap_or(true)
},
))
} else {
None
}
}
#[get("/track/<id>/events")]
fn tracked_events<'a>(
id: &'a str,
tracking: &'a State<Tracking>,
mut shutdown: Shutdown,
) -> Option<EventStream![Event + 'a]> {
if tracking.read().unwrap().contains_key(&id.to_string()) {
Some(EventStream! {
let mut interval = time::interval(Duration::from_secs(5));
loop {
select!{
_ = interval.tick() => {
let info = TrackedInfo {
name: id.to_string(),
pos: tracking.read().unwrap().get(&id.to_string()).unwrap().read().unwrap().pos
};
yield Event::json(&info).event("coords")
},
_ = &mut shutdown => break
}
}
})
} else {
None
}
}
#[put("/track/<id>?<lat>&<long>")]
fn store_pos(id: String, lat: f32, long: f32, tracking: &State<Tracking>){
if let Some(tracked) = tracking.read().unwrap().get(&id) {
fn store_pos(id: &str, lat: f32, long: f32, tracking: &State<Tracking>) {
if let Some(tracked) = tracking.read().unwrap().get(&id.to_string()) {
tracked.write().unwrap().pos = (lat, long);
}
}
@ -54,10 +130,26 @@ fn index() -> &'static str {
#[launch]
fn rocket() -> _ {
let tracking = HashMap::<String, RwLock<Tracked>>::from([
(
"team00".to_string(),
RwLock::new(build_conscrit("Équipe 0".to_string())),
),
(
"team01".to_string(),
RwLock::new(build_conscrit("Équipe 1".to_string())),
),
(
"npc0".to_string(),
RwLock::new(build_vieux("PNJ 0".to_string())),
),
(
"npc1".to_string(),
RwLock::new(build_vieux("PNJ 1".to_string())),
),
]);
rocket::build()
.attach(Template::fairing())
.manage(RwLock::new(tracking))
.mount("/", routes![index, store_pos, conscrit])
.mount("/", routes![index, store_pos, tracked_view, tracked_events])
.mount("/", FileServer::from(relative!("static")))
}

View file

@ -13,9 +13,6 @@
integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
crossorigin=""></script>
<!-- SOCKET.IO INCLUDE -->
<script src="/socket.io/socket.io.js"></script>
<style type="text/css">
#map { height: 600px; }
#codes {
@ -27,7 +24,7 @@
}
</style>
<script type="text/javascript" src="/utils.js"></script>
<!-- <script type="text/javascript" src="/utils.js"></script> -->
</head>
<body>
<div id="map"></div><br/>
@ -39,6 +36,10 @@
</div>
<script type="text/javascript">
const evtSource = new EventSource("/track/{{id}}/events");
evtSource.addEventListener("coords", (event) => {
console.log(event);
});
// //////////////////////////////////////////////////////////////////////////////
// // SETUP MAP