Now races and teamraces are paginated.
This commit is contained in:
parent
71ed4d8b70
commit
504c580dfd
|
@ -1,24 +1,34 @@
|
|||
use rocket::{serde::json::Json, Route, State};
|
||||
|
||||
use crate::database::{models::race::Race, DatabaseHandler};
|
||||
use crate::database::{
|
||||
models::{
|
||||
race::Race,
|
||||
search_result::{get_page_number_as_i32_from_str, SearchResult},
|
||||
},
|
||||
DatabaseHandler,
|
||||
};
|
||||
|
||||
#[get("/player/<player>")]
|
||||
#[get("/player/<player>?<page>")]
|
||||
async fn get_races_by_player(
|
||||
db: &State<DatabaseHandler>,
|
||||
player: &str,
|
||||
) -> Result<Json<Vec<Race>>, String> {
|
||||
match Race::get_races_by_player(db, player).await {
|
||||
page: Option<&str>,
|
||||
) -> Result<Json<SearchResult<Race>>, String> {
|
||||
let page_num = get_page_number_as_i32_from_str(page);
|
||||
match Race::get_races_by_player(db, player, page_num).await {
|
||||
Ok(maps) => Ok(Json(maps)),
|
||||
Err(err) => Err(format!("Error: {}", err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/map/<map>")]
|
||||
#[get("/map/<map>?<page>")]
|
||||
async fn get_races_by_map(
|
||||
db: &State<DatabaseHandler>,
|
||||
map: &str,
|
||||
) -> Result<Json<Vec<Race>>, String> {
|
||||
match Race::get_races_by_map(db, map).await {
|
||||
page: Option<&str>,
|
||||
) -> Result<Json<SearchResult<Race>>, String> {
|
||||
let page_num = get_page_number_as_i32_from_str(page);
|
||||
match Race::get_races_by_map(db, map, page_num).await {
|
||||
Ok(maps) => Ok(Json(maps)),
|
||||
Err(err) => Err(format!("Error: {}", err)),
|
||||
}
|
||||
|
|
|
@ -1,24 +1,34 @@
|
|||
use rocket::{serde::json::Json, Route, State};
|
||||
|
||||
use crate::database::{models::teamrace::Teamrace, DatabaseHandler};
|
||||
use crate::database::{
|
||||
models::{
|
||||
search_result::{get_page_number_as_i32_from_str, SearchResult},
|
||||
teamrace::Teamrace,
|
||||
},
|
||||
DatabaseHandler,
|
||||
};
|
||||
|
||||
#[get("/player/<player>")]
|
||||
#[get("/player/<player>?<page>")]
|
||||
async fn get_teamrace_by_player(
|
||||
db: &State<DatabaseHandler>,
|
||||
player: &str,
|
||||
) -> Result<Json<Vec<Teamrace>>, String> {
|
||||
match Teamrace::get_teamrace_by_player(db, player).await {
|
||||
page: Option<&str>,
|
||||
) -> Result<Json<SearchResult<Teamrace>>, String> {
|
||||
let page_num = get_page_number_as_i32_from_str(page);
|
||||
match Teamrace::get_teamrace_by_player(db, player, page_num).await {
|
||||
Ok(maps) => Ok(Json(maps)),
|
||||
Err(err) => Err(format!("Error: {}", err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/map/<map>")]
|
||||
#[get("/map/<map>?<page>")]
|
||||
async fn get_teamrace_by_map(
|
||||
db: &State<DatabaseHandler>,
|
||||
map: &str,
|
||||
) -> Result<Json<Vec<Teamrace>>, String> {
|
||||
match Teamrace::get_teamrace_by_map(db, map).await {
|
||||
page: Option<&str>,
|
||||
) -> Result<Json<SearchResult<Teamrace>>, String> {
|
||||
let page_num = get_page_number_as_i32_from_str(page);
|
||||
match Teamrace::get_teamrace_by_map(db, map, page_num).await {
|
||||
Ok(maps) => Ok(Json(maps)),
|
||||
Err(err) => Err(format!("Error: {}", err)),
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub mod map;
|
||||
pub mod race;
|
||||
pub mod search_result;
|
||||
pub mod teamrace;
|
||||
|
|
|
@ -3,6 +3,8 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::database::DatabaseHandler;
|
||||
|
||||
use super::search_result::{SearchResult, ROWS_PER_PAGE};
|
||||
|
||||
#[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)]
|
||||
pub struct Race {
|
||||
pub name: String,
|
||||
|
@ -19,8 +21,9 @@ impl Race {
|
|||
pub async fn get_races_by_player(
|
||||
db: &DatabaseHandler,
|
||||
player: &str,
|
||||
) -> Result<Vec<Race>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
page: i32,
|
||||
) -> Result<SearchResult<Race>, sqlx::Error> {
|
||||
let results = sqlx::query_as!(
|
||||
Race,
|
||||
"
|
||||
SELECT name,
|
||||
|
@ -42,35 +45,73 @@ impl Race {
|
|||
player
|
||||
)
|
||||
.fetch_all(&db.pool)
|
||||
.await
|
||||
.await?;
|
||||
|
||||
let total_pages = sqlx::query!(
|
||||
"SELECT ceil(count(*) / $2) + 1 as total_pages FROM record_race WHERE name = $1",
|
||||
player,
|
||||
ROWS_PER_PAGE as i64
|
||||
)
|
||||
.fetch_one(&db.pool)
|
||||
.await?
|
||||
.total_pages
|
||||
.map_or_else(|| 0, |as_i64| as_i64 as i32);
|
||||
|
||||
Ok(SearchResult {
|
||||
results,
|
||||
total_pages,
|
||||
current_page: page,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_races_by_map(
|
||||
db: &DatabaseHandler,
|
||||
map: &str,
|
||||
) -> Result<Vec<Race>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
page: i32,
|
||||
) -> Result<SearchResult<Race>, sqlx::Error> {
|
||||
let results = sqlx::query_as!(
|
||||
Race,
|
||||
"
|
||||
SELECT name,
|
||||
SELECT
|
||||
name,
|
||||
map,
|
||||
time,
|
||||
timestamp,
|
||||
server,
|
||||
ARRAY[cp1, cp2, cp3, cp4, cp5,
|
||||
cp6, cp7, cp8, cp9, cp10,
|
||||
cp11, cp12, cp13, cp14, cp15,
|
||||
cp16, cp17, cp18, cp19, cp20,
|
||||
cp21, cp22, cp23, cp24, cp25
|
||||
cp6, cp7, cp8, cp9, cp10,
|
||||
cp11, cp12, cp13, cp14, cp15,
|
||||
cp16, cp17, cp18, cp19, cp20,
|
||||
cp21, cp22, cp23, cp24, cp25
|
||||
] AS checkpoints,
|
||||
gameid,
|
||||
ddnet7
|
||||
FROM record_race WHERE map = $1
|
||||
ORDER BY map, time
|
||||
OFFSET (($2 - 1) * $3)
|
||||
FETCH NEXT $3 ROWS ONLY
|
||||
",
|
||||
map
|
||||
map,
|
||||
page,
|
||||
ROWS_PER_PAGE
|
||||
)
|
||||
.fetch_all(&db.pool)
|
||||
.await
|
||||
.await?;
|
||||
|
||||
let total_pages = sqlx::query!(
|
||||
"SELECT ceil(count(*) / $2) + 1 as total_pages FROM record_race WHERE map = $1",
|
||||
map,
|
||||
ROWS_PER_PAGE as i64
|
||||
)
|
||||
.fetch_one(&db.pool)
|
||||
.await?
|
||||
.total_pages
|
||||
.map_or_else(|| 0, |as_i64| as_i64 as i32);
|
||||
|
||||
Ok(SearchResult {
|
||||
results,
|
||||
total_pages,
|
||||
current_page: page,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
16
src/database/models/search_result.rs
Normal file
16
src/database/models/search_result.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct SearchResult<T> {
|
||||
pub results: Vec<T>,
|
||||
pub current_page: i32,
|
||||
pub total_pages: i32,
|
||||
}
|
||||
|
||||
/// This constant should be used everywhere so that it can easily changed.
|
||||
pub const ROWS_PER_PAGE: i32 = 200;
|
||||
|
||||
/// This gets an i32 from an Option<&str>. It is very fail safe of any bad value, where it will return 1 instead of an error.
|
||||
pub fn get_page_number_as_i32_from_str(page_as_str: Option<&str>) -> i32 {
|
||||
str::parse(page_as_str.unwrap_or("1")).unwrap_or(1)
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
use chrono::NaiveDateTime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::database::DatabaseHandler;
|
||||
use crate::database::{models::search_result::ROWS_PER_PAGE, DatabaseHandler};
|
||||
|
||||
use super::search_result::SearchResult;
|
||||
|
||||
#[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)]
|
||||
pub struct Teamrace {
|
||||
|
@ -15,25 +17,76 @@ impl Teamrace {
|
|||
pub async fn get_teamrace_by_player(
|
||||
db: &DatabaseHandler,
|
||||
player: &str,
|
||||
) -> Result<Vec<Teamrace>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
page: i32,
|
||||
) -> Result<SearchResult<Teamrace>, sqlx::Error> {
|
||||
let results = sqlx::query_as!(
|
||||
Teamrace,
|
||||
"SELECT players, map, time, timestamp FROM record_teamrace_array WHERE $1 = ANY(players)",
|
||||
player
|
||||
).fetch_all(&db.pool)
|
||||
.await
|
||||
"
|
||||
SELECT players, map, time, timestamp
|
||||
FROM record_teamrace_array
|
||||
WHERE $1 = ANY(players)
|
||||
OFFSET (($2 - 1) * $3)
|
||||
FETCH NEXT $3 ROWS ONLY
|
||||
",
|
||||
player,
|
||||
page,
|
||||
ROWS_PER_PAGE
|
||||
)
|
||||
.fetch_all(&db.pool)
|
||||
.await?;
|
||||
|
||||
let total_pages = sqlx::query!(
|
||||
"SELECT ceil(count(*) / $2) + 1 as total_pages FROM record_teamrace_array WHERE $1 = ANY(players)",
|
||||
player,
|
||||
ROWS_PER_PAGE as i64
|
||||
)
|
||||
.fetch_one(&db.pool)
|
||||
.await?
|
||||
.total_pages
|
||||
.map_or_else(|| 0, |as_i64| as_i64 as i32);
|
||||
|
||||
Ok(SearchResult {
|
||||
results,
|
||||
total_pages,
|
||||
current_page: page,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_teamrace_by_map(
|
||||
db: &DatabaseHandler,
|
||||
map: &str,
|
||||
) -> Result<Vec<Teamrace>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
page: i32,
|
||||
) -> Result<SearchResult<Teamrace>, sqlx::Error> {
|
||||
let results = sqlx::query_as!(
|
||||
Teamrace,
|
||||
"SELECT players, map, time, timestamp FROM record_teamrace_array WHERE map = $1",
|
||||
map
|
||||
"
|
||||
SELECT players, map, time, timestamp
|
||||
FROM record_teamrace_array
|
||||
WHERE map = $1
|
||||
OFFSET (($2 - 1) * $3)
|
||||
FETCH NEXT $3 ROWS ONLY
|
||||
",
|
||||
map,
|
||||
page,
|
||||
ROWS_PER_PAGE
|
||||
)
|
||||
.fetch_all(&db.pool)
|
||||
.await
|
||||
.await?;
|
||||
|
||||
let total_pages = sqlx::query!(
|
||||
"SELECT ceil(count(*) / $2) + 1 as total_pages FROM record_teamrace_array WHERE map = $1",
|
||||
map,
|
||||
ROWS_PER_PAGE as i64
|
||||
)
|
||||
.fetch_one(&db.pool)
|
||||
.await?
|
||||
.total_pages
|
||||
.map_or_else(|| 0, |as_i64| as_i64 as i32);
|
||||
|
||||
Ok(SearchResult {
|
||||
results,
|
||||
total_pages,
|
||||
current_page: page,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user