use axum::{ response::Html, routing::{get, post}, Json, Router, }; use once_cell::sync::Lazy; use rand::{thread_rng, Rng}; use rand::seq::SliceRandom; use serde::Deserialize; use std::net::SocketAddr; use tokio::sync::Mutex; use log::debug; use log::error; use log::info; use log::warn; #[macro_use] extern crate log; #[tokio::main] async fn main() { env_logger::init(); // tracing_subscriber::fmt::init(); // build our application with some routes let app = Router::new() .route("/", get(|| async { Html(INDEX_HTML.as_str()) })) .route("/api", post(input)); // run it with hyper let addr = SocketAddr::from(([127, 0, 0, 1], 3067)); axum::Server::bind(&addr) .serve(app.into_make_service()) .await .unwrap(); } static INDEX_HTML: Lazy = Lazy::new(|| { let content = include_str!("index.html"); let options: String = everyone() .into_iter() .map(|person| format!(r#""#)) .collect(); content.replace("__OPTIONS__", &options) }); static STATE: Lazy> = Lazy::new(Mutex::default); struct State { participants: Vec, remaining: Vec, } fn everyone() -> Vec { vec!["Alice".into(), "Bob".into(), "Carol".into(), "Dave".into()] } impl Default for State { fn default() -> Self { let mut p = everyone(); p.shuffle(&mut thread_rng()); info!("distribution : {:?}", p.join(" => ")); return Self { participants: p, remaining: everyone() } } } #[derive(Deserialize, Debug)] struct Input { person: String, } async fn input(Json(input): Json) -> String { let mut state = STATE.lock().await; if state.remaining.is_empty() { return "ERROR (everybody drew already)".into(); } info!("joueurs qui restent : {:?}", state.remaining.join(",")); match state.remaining.iter().position(|p| input.person == *p).map(|e| state.remaining.remove(e)) { Some(rem) => { match state.participants.iter().position(|p| input.person == *p) { Some(pos) => { info!("joueur qui pioche : {:?}", state.participants[pos]); return match state.participants.iter().nth(pos+1) { Some(x) => { info!("joueur qui suit : {:?}", x); return x.to_string(); } None => return match state.participants.first() { Some(x) => { info!("joueur qui suit : {:?}", x); return x.to_string(); } None => "ERROR".to_string() } } } None => "ERROR".to_string() } } None => "Vous avez déja pioché !".to_string() } }