diff --git a/src/main.rs b/src/main.rs index 8174811..40dbbd0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,8 @@ use actix_web::{ App, Error, HttpRequest, HttpResponse, HttpServer, Result, }; -use rand::seq::IteratorRandom; +use rand::distributions::Uniform; +use rand::Rng; use ledb::{Options, Storage}; @@ -102,6 +103,21 @@ struct Question { struct AppState { storage: Storage, template: tera::Tera, + database_distribution: Uniform, +} + +fn get_database_distribution(storage: &Storage) -> Uniform { + let collection = storage + .collection("questions") + .expect("collection \"questions\""); + let last_id = collection.last_id().expect("\"questions\" last_id"); + + rand::distributions::Uniform::new_inclusive(1u32, last_id) +} + +fn random_question_id(database_distribution: &Uniform) -> u32 { + let mut rng = rand::thread_rng(); + rng.sample(database_distribution) } fn get_question(storage: &Storage, id: u32) -> Result, Error> { @@ -134,7 +150,12 @@ fn show_question_details(template_file: &str, data: web::Data, id: web if question.is_some() { let question = question.unwrap(); - let body = data.template.render(template_file, &question).unwrap(); + let mut context = serde_json::to_value(question).expect("question serialize"); + if context.is_object() { + let next_id = random_question_id(&data.database_distribution); + context["next"] = serde_json::to_value(next_id).expect("question id serialize"); + } + let body = data.template.render(template_file, &context).expect("template render - show_question_details"); Ok(HttpResponse::Ok().content_type("text/html").body(body)) } else { Ok(HttpResponse::PermanentRedirect() @@ -159,10 +180,7 @@ fn show_answer(data: web::Data, id: web::Path) -> Result, _req: HttpRequest) -> Result { - let collection = data.storage.collection("questions").expect("collection questions"); - let mut rng = rand::thread_rng(); - let last_id = collection.last_id().expect("questions last id"); - let id = (1..=last_id).choose(&mut rng).expect("random id"); + let id = random_question_id(&data.database_distribution); let url = format!("/q/{}", id); @@ -184,10 +202,14 @@ fn main() { let storage = Storage::new("db", options).expect("db open"); HttpServer::new(move || { - let data = AppState { + let mut data = AppState { storage: storage.clone(), template: compile_templates!("./templates/**/*"), + database_distribution: Uniform::new(1, 3), }; + data.database_distribution = get_database_distribution(&data.storage); + let data = data; + App::new() .wrap(Logger::default()) .data(data)