125 lines
3.1 KiB
Rust
125 lines
3.1 KiB
Rust
use aide::axum::{
|
|
routing::{get_with, post_with},
|
|
ApiRouter,
|
|
};
|
|
use axum::{
|
|
extract::{Path, Query},
|
|
http::StatusCode,
|
|
Json,
|
|
};
|
|
use schemars::JsonSchema;
|
|
use serde::{Deserialize, Serialize};
|
|
use sqlx::FromRow;
|
|
|
|
mod size;
|
|
|
|
pub fn routes() -> ApiRouter {
|
|
ApiRouter::new()
|
|
.api_route(
|
|
"/discover",
|
|
post_with(discover, |docs| {
|
|
docs.response::<200, Json<Star>>()
|
|
.summary("add a new planet")
|
|
.id("discover")
|
|
.tag("stars")
|
|
}),
|
|
)
|
|
.api_route(
|
|
"/chart",
|
|
get_with(chart, |docs| {
|
|
docs.response::<200, Json<Vec<Protostar>>>()
|
|
.summary("the whole chart")
|
|
.id("chart")
|
|
.tag("stars")
|
|
}),
|
|
)
|
|
.api_route_with(
|
|
"/visit/",
|
|
get_with(visit, |docs| {
|
|
docs.response::<200, Json<Star>>()
|
|
.summary("visit a single planet")
|
|
.id("visit")
|
|
.tag("stars")
|
|
}),
|
|
|docs| docs,
|
|
)
|
|
}
|
|
|
|
/// this gets stored in the db,
|
|
/// the other stuff is generated using
|
|
/// the id as a seed
|
|
#[derive(Serialize, FromRow, Clone, Deserialize, JsonSchema)]
|
|
pub struct Protostar {
|
|
pub id: i32,
|
|
/// hex code of the stars color
|
|
pub color: String,
|
|
}
|
|
|
|
impl Protostar {
|
|
fn seed(&self) -> u64 {
|
|
self.id.abs() as u64
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, JsonSchema)]
|
|
pub struct Star {
|
|
pub size: size::Size,
|
|
pub core: Protostar,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, JsonSchema)]
|
|
pub struct DiscoveryLog {
|
|
pub color: String,
|
|
}
|
|
|
|
impl Into<Star> for Protostar {
|
|
fn into(self) -> Star {
|
|
let seed = self.seed();
|
|
Star {
|
|
core: self,
|
|
size: size::Size::random(seed),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// discover a new star in the solar system
|
|
async fn discover(Json(log): Json<DiscoveryLog>) -> Result<Json<Star>, StatusCode> {
|
|
let query = "INSERT INTO stars (color) VALUES ($1) RETURNING id, color";
|
|
|
|
let protostar: Protostar = sqlx::query_as(query)
|
|
.bind(log.color)
|
|
.fetch_one(crate::db::pool().await)
|
|
.await
|
|
.or(Err(StatusCode::INTERNAL_SERVER_ERROR))?;
|
|
let star: Star = protostar.into();
|
|
Ok(Json(star))
|
|
}
|
|
|
|
/// show all stars
|
|
async fn chart() -> Json<Vec<Protostar>> {
|
|
let query = "SELECT * FROM stars ORDER BY id DESC";
|
|
let protostars: Vec<Protostar> = sqlx::query_as(query)
|
|
.fetch_all(crate::db::pool().await)
|
|
.await
|
|
.unwrap_or_default();
|
|
Json(protostars)
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, JsonSchema)]
|
|
struct VisitorData {
|
|
/// the planet to visit
|
|
planet_id: i32,
|
|
}
|
|
|
|
async fn visit(data: Query<VisitorData>) -> Result<Json<Star>, StatusCode> {
|
|
let query = "SELECT * FROM stars WHERE id = ($1)";
|
|
let star: Protostar = sqlx::query_as(query)
|
|
.bind(data.planet_id)
|
|
.fetch_one(crate::db::pool().await)
|
|
.await
|
|
.unwrap();
|
|
//.or(Err(StatusCode::NOT_FOUND))?;
|
|
let star: Star = star.into();
|
|
Ok(Json(star))
|
|
}
|