fancier boat stats
This commit is contained in:
@ -1,8 +1,82 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::model::user::User;
|
||||
use chrono::Datelike;
|
||||
use serde::Serialize;
|
||||
use sqlx::{FromRow, Row, SqlitePool};
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct BoatStat {
|
||||
pot_years: Vec<i32>,
|
||||
boats: Vec<SingleBoatStat>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct SingleBoatStat {
|
||||
name: String,
|
||||
location: String,
|
||||
years: HashMap<String, i32>,
|
||||
}
|
||||
|
||||
impl BoatStat {
|
||||
pub async fn get(db: &SqlitePool) -> BoatStat {
|
||||
let mut years = Vec::new();
|
||||
let mut boat_stats_map: HashMap<String, SingleBoatStat> = HashMap::new();
|
||||
|
||||
let rows = sqlx::query(
|
||||
"
|
||||
SELECT
|
||||
boat.name,
|
||||
location.name AS location,
|
||||
CAST(strftime('%Y', arrival) AS INTEGER) AS year,
|
||||
CAST(SUM(distance_in_km) AS INTEGER) AS rowed_km
|
||||
FROM
|
||||
logbook
|
||||
INNER JOIN
|
||||
boat ON boat.id = logbook.boat_id
|
||||
INNER JOIN
|
||||
location ON boat.location_id = location.id
|
||||
WHERE
|
||||
boat.name != 'Externes Boot'
|
||||
GROUP BY
|
||||
boat_id, year
|
||||
ORDER BY
|
||||
boat.name, year DESC;
|
||||
",
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
for row in rows {
|
||||
let name: String = row.get("name");
|
||||
let location: String = row.get("location");
|
||||
let year: i32 = row.get("year");
|
||||
if !years.contains(&year) {
|
||||
years.push(year);
|
||||
}
|
||||
|
||||
let year: String = format!("{year}");
|
||||
|
||||
let rowed_km: i32 = row.get("rowed_km");
|
||||
|
||||
let boat_stat = boat_stats_map
|
||||
.entry(name.clone())
|
||||
.or_insert(SingleBoatStat {
|
||||
name,
|
||||
location,
|
||||
years: HashMap::new(),
|
||||
});
|
||||
boat_stat.years.insert(year, rowed_km);
|
||||
}
|
||||
|
||||
BoatStat {
|
||||
pot_years: years,
|
||||
boats: boat_stats_map.into_values().collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromRow, Serialize, Clone)]
|
||||
pub struct Stat {
|
||||
name: String,
|
||||
@ -10,32 +84,6 @@ pub struct Stat {
|
||||
}
|
||||
|
||||
impl Stat {
|
||||
pub async fn boats(db: &SqlitePool, year: Option<i32>) -> Vec<Stat> {
|
||||
let year = match year {
|
||||
Some(year) => year,
|
||||
None => chrono::Local::now().year(),
|
||||
};
|
||||
//TODO: switch to query! macro again (once upgraded to sqlite 3.42 on server)
|
||||
sqlx::query(&format!(
|
||||
"
|
||||
SELECT (SELECT name FROM boat WHERE id=logbook.boat_id) as name, CAST(SUM(distance_in_km) AS INTEGER) AS rowed_km
|
||||
FROM logbook
|
||||
WHERE arrival LIKE '{year}-%' AND name != 'Externes Boot'
|
||||
GROUP BY boat_id
|
||||
ORDER BY rowed_km DESC;
|
||||
")
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|row| Stat {
|
||||
name: row.get("name"),
|
||||
rowed_km: row.get("rowed_km"),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub async fn guest(db: &SqlitePool, year: Option<i32>) -> Stat {
|
||||
let year = match year {
|
||||
Some(year) => year,
|
||||
|
Reference in New Issue
Block a user