use std::process::ExitCode;
use net_backend_server::axum::routing::post;
use net_backend_server::axum::Json;
use net_backend_server::{ApiJson, AppError, AppState, Config, NetBackendServer};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct Roll {
sides: u32,
}
#[derive(Serialize)]
struct Rolled {
sides: u32,
value: u32,
at: i64,
}
async fn roll(state: net_backend_server::axum::extract::State<AppState>, ApiJson(roll): ApiJson<Roll>) -> Result<Json<Rolled>, AppError> {
if !(2..=1000).contains(&roll.sides) {
let mut details = net_backend_server::protocol::ValidationDetails::new();
details.add("sides", "must be between 2 and 1000");
return Err(AppError::validation(details));
}
let now = state.now();
let value = u32::try_from(now.get().rem_euclid(i64::from(roll.sides))).unwrap_or(0) + 1;
Ok(Json(Rolled { sides: roll.sides, value, at: now.get() }))
}
#[tokio::main]
async fn main() -> ExitCode {
let config = match Config::load() {
Ok(config) => config,
Err(error) => {
eprintln!("{error}");
return ExitCode::FAILURE;
}
};
let server = NetBackendServer::new(config).route("/v1/game/roll", post(roll));
match server.run().await {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("{error}");
ExitCode::FAILURE
}
}
}