From b6d58077f64d9b5cf7965a662ec96d358359ca8f Mon Sep 17 00:00:00 2001 From: philipp Date: Tue, 3 Sep 2024 22:55:58 +0300 Subject: [PATCH 1/3] start with aequatorpreis --- src/model/user.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/model/user.rs b/src/model/user.rs index d5f8a41..e56e611 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -24,6 +24,71 @@ use crate::{ SCHECKBUCH, STUDENT_OR_PUPIL, UNTERSTUETZEND, }; +mod aequatorpreis { + use chrono::{Datelike, Local, NaiveDate}; + + use super::User; + + enum AgeBracket { + Till14, + From14Till18, + From19Till30, + From31Till60, + From61Till75, + From76, + } + + impl TryFrom<&User> for AgeBracket { + type Error = String; + + fn try_from(value: &User) -> Result { + if let Some(birthdate) = value.birthdate.clone() { + let today = Local::now().date_naive(); + let birthdate = NaiveDate::parse_from_str(&birthdate, "%Y-%m-%d").unwrap(); + + let age = today.year() - birthdate.year(); + if age <= 14 { + Ok(AgeBracket::Till14) + } else if age <= 18 { + Ok(AgeBracket::From14Till18) + } else if age <= 30 { + Ok(AgeBracket::From19Till30) + } else if age <= 60 { + Ok(AgeBracket::From31Till60) + } else if age <= 75 { + Ok(AgeBracket::From61Till75) + } else { + Ok(AgeBracket::From76) + } + } else { + Err("User has no birthdate".to_string()) + } + } + } + + fn cat(value: &AgeBracket) -> &str { + match value { + AgeBracket::Till14 => "Schülerinnen und Schüler bis 14 Jahre", + AgeBracket::From14Till18 => "Juniorinnen und Junioren, Para-Ruderer bis 18 Jahre", + AgeBracket::From19Till30 => "Frauen und Männer, Para-Ruderer bis 30 Jahre", + AgeBracket::From31Till60 => "Frauen und Männer, Para-Ruderer von 31 bis 60 Jahre", + AgeBracket::From61Till75 => "Frauen und Männer, Para-Ruderer von 61 bis 75 Jahre", + AgeBracket::From76 => "Frauen und Männer, Para-Ruderer ab 76 Jahre", + } + } + + fn dist_in_km(value: &AgeBracket) -> u32 { + match value { + AgeBracket::Till14 => 500, + AgeBracket::From14Till18 => 1000, + AgeBracket::From19Till30 => 1200, + AgeBracket::From31Till60 => 1000, + AgeBracket::From61Till75 => 800, + AgeBracket::From76 => 600, + } + } +} + #[derive(FromRow, Serialize, Deserialize, Clone, Debug, Eq, Hash, PartialEq)] pub struct User { pub id: i64, From f41b5e9fefa70ad18df2c48807093d7bc4af8c4e Mon Sep 17 00:00:00 2001 From: philipp Date: Wed, 4 Sep 2024 10:01:59 +0300 Subject: [PATCH 2/3] restructure for equatorprice --- src/model/mod.rs | 1 + src/model/personal/equatorprice.rs | 58 ++++++++++++++++++++++++++ src/model/personal/mod.rs | 21 ++++++++++ src/model/personal/rowingbadge.rs | 62 ++++++++++++++++++++++++++++ src/model/user.rs | 65 ------------------------------ src/tera/mod.rs | 2 + templates/index.html.tera | 26 ++++++++++++ 7 files changed, 170 insertions(+), 65 deletions(-) create mode 100644 src/model/personal/equatorprice.rs create mode 100644 src/model/personal/mod.rs create mode 100644 src/model/personal/rowingbadge.rs diff --git a/src/model/mod.rs b/src/model/mod.rs index 1af7c21..46446db 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -25,6 +25,7 @@ pub mod logbook; pub mod logtype; pub mod mail; pub mod notification; +pub mod personal; pub mod role; pub mod rower; pub mod stat; diff --git a/src/model/personal/equatorprice.rs b/src/model/personal/equatorprice.rs new file mode 100644 index 0000000..ef67ce5 --- /dev/null +++ b/src/model/personal/equatorprice.rs @@ -0,0 +1,58 @@ +use serde::Serialize; + +#[derive(Serialize)] +enum Level { + BRONZE, + SILVER, + GOLD, + DIAMOND, + DONE, +} + +impl Level { + fn required_km(&self) -> i32 { + match self { + Level::BRONZE => 40000, + Level::SILVER => 80000, + Level::GOLD => 100000, + Level::DIAMOND => 200000, + Level::DONE => 0, + } + } + + fn next_level(km: i32) -> Self { + if km < Level::BRONZE.required_km() { + Level::BRONZE + } else if km < Level::SILVER.required_km() { + Level::SILVER + } else if km < Level::GOLD.required_km() { + Level::GOLD + } else if km < Level::DIAMOND.required_km() { + Level::BRONZE + } else { + Level::DONE + } + } +} + +#[derive(Serialize)] +pub(crate) struct Next { + level: Level, + missing_km: i32, + required_km: i32, + rowed_km: i32, +} + +impl Next { + pub(crate) fn rowed_km(km: i32) -> Self { + let level = Level::next_level(km); + let required_km = level.required_km(); + let missing_km = required_km - km; + Self { + level, + missing_km, + required_km, + rowed_km: km, + } + } +} diff --git a/src/model/personal/mod.rs b/src/model/personal/mod.rs new file mode 100644 index 0000000..a1dd59c --- /dev/null +++ b/src/model/personal/mod.rs @@ -0,0 +1,21 @@ +use serde::Serialize; +use sqlx::SqlitePool; + +use super::{stat::Stat, user::User}; + +pub(crate) mod equatorprice; +pub(crate) mod rowingbadge; + +#[derive(Serialize)] +pub(crate) struct Achievements { + equatorprice: equatorprice::Next, +} + +impl Achievements { + pub(crate) async fn for_user(db: &SqlitePool, user: &User) -> Self { + let rowed_km = Stat::person(db, None, user).await.rowed_km; + Self { + equatorprice: equatorprice::Next::rowed_km(rowed_km), + } + } +} diff --git a/src/model/personal/rowingbadge.rs b/src/model/personal/rowingbadge.rs new file mode 100644 index 0000000..006d7e9 --- /dev/null +++ b/src/model/personal/rowingbadge.rs @@ -0,0 +1,62 @@ +use chrono::{Datelike, Local, NaiveDate}; + +use crate::model::user::User; + +enum AgeBracket { + Till14, + From14Till18, + From19Till30, + From31Till60, + From61Till75, + From76, +} + +impl TryFrom<&User> for AgeBracket { + type Error = String; + + fn try_from(value: &User) -> Result { + if let Some(birthdate) = value.birthdate.clone() { + let today = Local::now().date_naive(); + let birthdate = NaiveDate::parse_from_str(&birthdate, "%Y-%m-%d").unwrap(); + + let age = today.year() - birthdate.year(); + if age <= 14 { + Ok(AgeBracket::Till14) + } else if age <= 18 { + Ok(AgeBracket::From14Till18) + } else if age <= 30 { + Ok(AgeBracket::From19Till30) + } else if age <= 60 { + Ok(AgeBracket::From31Till60) + } else if age <= 75 { + Ok(AgeBracket::From61Till75) + } else { + Ok(AgeBracket::From76) + } + } else { + Err("User has no birthdate".to_string()) + } + } +} + +fn cat(value: &AgeBracket) -> &str { + match value { + AgeBracket::Till14 => "Schülerinnen und Schüler bis 14 Jahre", + AgeBracket::From14Till18 => "Juniorinnen und Junioren, Para-Ruderer bis 18 Jahre", + AgeBracket::From19Till30 => "Frauen und Männer, Para-Ruderer bis 30 Jahre", + AgeBracket::From31Till60 => "Frauen und Männer, Para-Ruderer von 31 bis 60 Jahre", + AgeBracket::From61Till75 => "Frauen und Männer, Para-Ruderer von 61 bis 75 Jahre", + AgeBracket::From76 => "Frauen und Männer, Para-Ruderer ab 76 Jahre", + } +} + +fn dist_in_km(value: &AgeBracket) -> u32 { + match value { + AgeBracket::Till14 => 500, + AgeBracket::From14Till18 => 1000, + AgeBracket::From19Till30 => 1200, + AgeBracket::From31Till60 => 1000, + AgeBracket::From61Till75 => 800, + AgeBracket::From76 => 600, + } +} diff --git a/src/model/user.rs b/src/model/user.rs index e56e611..d5f8a41 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -24,71 +24,6 @@ use crate::{ SCHECKBUCH, STUDENT_OR_PUPIL, UNTERSTUETZEND, }; -mod aequatorpreis { - use chrono::{Datelike, Local, NaiveDate}; - - use super::User; - - enum AgeBracket { - Till14, - From14Till18, - From19Till30, - From31Till60, - From61Till75, - From76, - } - - impl TryFrom<&User> for AgeBracket { - type Error = String; - - fn try_from(value: &User) -> Result { - if let Some(birthdate) = value.birthdate.clone() { - let today = Local::now().date_naive(); - let birthdate = NaiveDate::parse_from_str(&birthdate, "%Y-%m-%d").unwrap(); - - let age = today.year() - birthdate.year(); - if age <= 14 { - Ok(AgeBracket::Till14) - } else if age <= 18 { - Ok(AgeBracket::From14Till18) - } else if age <= 30 { - Ok(AgeBracket::From19Till30) - } else if age <= 60 { - Ok(AgeBracket::From31Till60) - } else if age <= 75 { - Ok(AgeBracket::From61Till75) - } else { - Ok(AgeBracket::From76) - } - } else { - Err("User has no birthdate".to_string()) - } - } - } - - fn cat(value: &AgeBracket) -> &str { - match value { - AgeBracket::Till14 => "Schülerinnen und Schüler bis 14 Jahre", - AgeBracket::From14Till18 => "Juniorinnen und Junioren, Para-Ruderer bis 18 Jahre", - AgeBracket::From19Till30 => "Frauen und Männer, Para-Ruderer bis 30 Jahre", - AgeBracket::From31Till60 => "Frauen und Männer, Para-Ruderer von 31 bis 60 Jahre", - AgeBracket::From61Till75 => "Frauen und Männer, Para-Ruderer von 61 bis 75 Jahre", - AgeBracket::From76 => "Frauen und Männer, Para-Ruderer ab 76 Jahre", - } - } - - fn dist_in_km(value: &AgeBracket) -> u32 { - match value { - AgeBracket::Till14 => 500, - AgeBracket::From14Till18 => 1000, - AgeBracket::From19Till30 => 1200, - AgeBracket::From31Till60 => 1000, - AgeBracket::From61Till75 => 800, - AgeBracket::From76 => 600, - } - } -} - #[derive(FromRow, Serialize, Deserialize, Clone, Debug, Eq, Hash, PartialEq)] pub struct User { pub id: i64, diff --git a/src/tera/mod.rs b/src/tera/mod.rs index 7bcc1ba..e49e053 100644 --- a/src/tera/mod.rs +++ b/src/tera/mod.rs @@ -24,6 +24,7 @@ use crate::{ model::{ logbook::Logbook, notification::Notification, + personal::Achievements, role::Role, user::{User, UserWithDetails}, }, @@ -62,6 +63,7 @@ async fn index(db: &State, user: User, flash: Option {% endif %} {% if "Donau Linz" in loggedin_user.roles and "Unterstützend" not in loggedin_user.roles and "Förderndes Mitglied" not in loggedin_user.roles %} + {% endmacro show %} -{% macro show_old(log, state, allowed_to_close=false, allowed_to_edit=false, index) %} +{% macro show_old(log, state, allowed_to_close=false, allowed_to_edit=false, index, hide_type=false) %}
- {% if log.logtype %} + {% if log.logtype and not hide_type %}
{% if log.logtype == 1 %} Wanderfahrt diff --git a/templates/index.html.tera b/templates/index.html.tera index 6177c0f..40286c6 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -79,25 +79,79 @@

Persönliches

-

Äquatorpreis

+

+ {% if achievements.rowingbadge and achievements.rowingbadge.achieved %}🎉{% endif %} + Fahrtenabzeichen + {% if achievements.rowingbadge %}{{ achievements.rowingbadge.year }}{% endif %} + ? +

+ {% if achievements.rowingbadge %} + {% set badge = achievements.rowingbadge %} +
{{ badge.category }}
+ + +

Wanderfahrten

+
Nur 1 muss erreicht werden
+
    +
  1. + {% if badge.multi_day_trips_over_required_distance | length >= 1 %} + ✅ + {% else %} + ❌ + {% endif %} + 1 mehrtägige Wanderfahrt > {{ badge.multi_day_trips_required_distance }} km +
  2. +
  3. + {% if badge.single_day_trips_over_required_distance | length >= 2 %} + ✅ + {% else %} + ❌ + {% endif %} + 2 eintägige Wanderfahrten > {{ badge.single_day_trips_required_distance }} km +
  4. +
+
+ Details zu den Wanderfahrten +
+ {% for log in badge.single_day_trips_over_required_distance %} + {{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index) }} + {% endfor %} + {% for log in badge.multi_day_trips_over_required_distance %} + {{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index) }} + {% endfor %} +
+
+ {% else %} + Wir haben leider kein Geburtsdatum von dir und können dir leider deinen heurigen Status für das Fahrtenabzeichen nicht anzeigen. Wenn du dein Geburtsdatum an it@rudernlinz.at schreibst, lässt sich das ändern :-) + {% endif %} +
+
+

+ Äquatorpreis + ? +

{% set price = achievements.equatorprice %} {% if price.level == "DONE" %} - Gratuliere, du hast alles erreicht, was es beim Äquatorpreis zu erreichen gibt. + Gratuliere, du hast alles in deinem Rudererleben erreicht, was es (beim Äquatorpreis) zu erreichen gibt. {% else %} - +
Details - Du bist insgesamt {{ price.rowed_km }} km gerudert. Um den Äquatorpreis in {{ price.level }} zu erhalten, benötigst du noch {{ price.missing_km }} um die notwendigen {{ price.required_km }} km zu erreichen. + Du bist insgesamt {{ price.rowed_km }} km gerudert. Um den Äquatorpreis in {{ price.level }} zu erhalten, benötigst du noch {{ price.missing_km }} km um die notwendigen {{ price.required_km }} km zu erreichen.
{% endif %}
-
-

Fahrtenabzeichen

-
Nachricht ausschreiben +
  • + Abzeichen +
  • {% endif %}