ddstats/src/database/models/map.rs

136 lines
4.2 KiB
Rust

use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use crate::database::DatabaseHandler;
#[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)]
pub struct Map {
pub map: String,
pub mappers: Vec<String>,
pub category: String,
pub points: i16,
pub stars: i16,
pub release: Option<NaiveDateTime>,
pub width: Option<i16>,
pub height: Option<i16>,
pub tiles: Option<Vec<String>>,
}
impl Map {
/// This gets all maps in the map database.
pub async fn get_all_maps(db: &DatabaseHandler) -> Result<Vec<Map>, sqlx::Error> {
sqlx::query_file_as!(Map, "sql/maps/get_all_maps.sql")
.fetch_all(&db.pool)
.await
}
/// This gets a map from the database via its name.
/// Returns an Err<sqlx::Error> if no map exists with the given name.
pub async fn get_map_by_name(db: &DatabaseHandler, map: &str) -> Result<Map, sqlx::Error> {
sqlx::query_file_as!(Map, "sql/maps/get_map_by_name.sql", map)
.fetch_one(&db.pool)
.await
}
/// This gets all maps from the database via their category.
/// Valid values are: Novice, Moderate, Brutal, Insane, Dummy, DDmaX.Easy, DDmaX.Next, DDmaX.Pro, DDmaX.Nut, Oldschool, Solo, Race, Fun
/// FIXME: Returns an empty array on invalid category!
pub async fn get_maps_by_category(
db: &DatabaseHandler,
category: &str,
) -> Result<Vec<Map>, sqlx::Error> {
sqlx::query_file_as!(Map, "sql/maps/get_maps_by_category.sql", category)
.fetch_all(&db.pool)
.await
}
/// This gets all the maps in the database made by a specific mapper.
/// Mappers are stored as an array, so if that array contains the given mapper, the entry is returned.
/// FIXME: Returns an empty array on non-existant mapper!
pub async fn get_maps_by_mapper(
db: &DatabaseHandler,
mapper: &str,
) -> Result<Vec<Map>, sqlx::Error> {
sqlx::query_file_as!(Map, "sql/maps/get_maps_by_mapper.sql", mapper)
.fetch_all(&db.pool)
.await
}
/// Experimental function to search for maps.
pub async fn search_maps(
db: &DatabaseHandler,
map: Option<&str>,
mappers: Option<Vec<String>>,
category: Option<&str>,
stars: Option<Vec<i16>>,
release_after: Option<NaiveDateTime>,
release_before: Option<NaiveDateTime>,
tiles: Option<Vec<String>>,
orderby: Option<&str>,
sort: Option<&str>,
) -> Result<Vec<Map>, sqlx::Error> {
let stars = stars.unwrap_or((0..=5).collect());
let mappers = mappers.unwrap_or(vec![]);
let tiles = tiles.unwrap_or(vec![]);
sqlx::query_file_as!(
Map,
"sql/maps/search_maps.sql",
map.map(|map| format!("%{}%", map)),
mappers.as_slice(),
category,
stars.as_slice(),
release_after,
release_before,
tiles.as_slice(),
orderby,
sort,
)
.fetch_all(&db.pool)
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_all_maps() {
async fn test() {
let db = match DatabaseHandler::create().await {
Ok(db) => db,
Err(err) => panic!("Error while connecting to database! {:?}", err),
};
let maps = match Map::get_all_maps(&db).await {
Ok(maps) => maps,
Err(err) => panic!("Error while getting all maps! {:?}", err),
};
for map in maps {
println!("{:?}", map);
}
}
tokio_test::block_on(test());
}
#[test]
fn test_get_map_by_name() {
async fn test() {
let db = match DatabaseHandler::create().await {
Ok(db) => db,
Err(err) => panic!("Error while connecting to database! {:?}", err),
};
let map = match Map::get_map_by_name(&db, "Kobra").await {
Ok(map) => map,
Err(err) => panic!("Error while getting all maps! {:?}", err),
};
println!("{:?}", map);
}
tokio_test::block_on(test());
}
}