#[macro_use] extern crate rocket; use rocket::fs::FileServer; use rocket::response::Redirect; use rocket::State; use rocket_dyn_templates::tera; use rocket_dyn_templates::Template; use rand::distributions::Uniform; use rand::Rng; use std::collections::HashMap; use std::ops::Deref; use std::sync::Arc; use chgk_ledb_lib::async_db; use chgk_ledb_lib::questions::Question; use mini_moka::sync::Cache; use std::time::Duration; const DB_FILENAME: &str = "db.dat"; trait ErrorEmpty { type Output; fn err_empty(self) -> Result; } impl ErrorEmpty for Result { type Output = T; fn err_empty(self) -> Result { self.map_err(|_| ()) } } #[derive(Debug, Responder)] enum WebError { #[response(status = 404)] NotFound(Template), } impl WebError { fn not_found() -> Self { let context: HashMap = HashMap::new(); WebError::NotFound(Template::render("404", context)) } } #[derive(Clone)] struct ArcTemplateData { value: Arc, } impl ArcTemplateData { fn new(value: tera::Value) -> ArcTemplateData { ArcTemplateData { value: Arc::new(value), } } fn render(&self, name: &'static str) -> Template { Template::render(name, self.value.deref()) } } type TemplateCache = mini_moka::sync::Cache; type DataBaseInner = async_db::Reader; type DataBase = Arc; struct AppState { db: DataBase, database_distribution: Uniform, } impl From for AppState { fn from(db: DataBaseInner) -> Self { let last_id = db.len(); let database_distribution = rand::distributions::Uniform::new_inclusive(1usize, last_id); let db = Arc::new(db); Self { db, database_distribution, } } } fn random_question_id(database_distribution: &Uniform) -> usize { let mut rng = rand::thread_rng(); rng.sample(database_distribution) } async fn get_question(db: &DataBase, id: usize) -> Result { db.get(id - 1).await.err_empty() } async fn show_question_details( template_name: &'static str, data: &AppState, cache: &TemplateCache, id: usize, ) -> Option