"Anstehende Proben Termine"
@@ -75,87 +75,87 @@ fn Sessions(config: SessionConfig) -> impl IntoView {
#[component]
fn DatedSession(session: DatedSession) -> impl IntoView {
- match session {
- DatedSession::Regular { session, day, .. } => view! {
+ match session {
+ DatedSession::Regular { session, day, .. } => view! {
""
{localize_day(&day)}
{session.note}
}
- .into_any(),
- DatedSession::Extra(session) => view! {
+ .into_any(),
+ DatedSession::Extra(session) => view! {
""
{localize_day(&session.day)}
{session.note}
}
- .into_any(),
- DatedSession::Canceled { regular, day, .. } => view! {
+ .into_any(),
+ DatedSession::Canceled { regular, day, .. } => view! {
""
{localize_day(&day)}
{regular.note}
}
- .into_any(),
- DatedSession::Altered {
- regular,
- day,
- cause,
- ..
- } => {
- let day = move || match cause.new_day {
- None => view! { {localize_day(&day)} }.into_any(),
- Some(new_day) => view! {
+ .into_any(),
+ DatedSession::Altered {
+ regular,
+ day,
+ cause,
+ ..
+ } => {
+ let day = move || match cause.new_day {
+ None => view! { {localize_day(&day)} }.into_any(),
+ Some(new_day) => view! {
{localize_day(&day)}
" "
{localize_day(&new_day)}
}
- .into_any(),
- };
+ .into_any(),
+ };
- view! {
+ view! {
"<Änderung>"
{day}
{cause.note.or(regular.note)}
}
- .into_any()
+ .into_any()
+ }
}
- }
}
async fn load_config
(name: &str) -> Result, String>
where
- T: for<'a> Deserialize<'a>,
+ T: for<'a> Deserialize<'a>,
{
- let response = Request::get(&format!("./{name}.json"))
- .send()
- .await
- .map_err(|e| format!("HTTP error: {e}"))?;
- if response
- .headers()
- .get("content-type")
- .is_none_or(|content_type| content_type != "application/json")
- {
- return Ok(None);
- }
+ let response = Request::get(&format!("./{name}.json"))
+ .send()
+ .await
+ .map_err(|e| format!("HTTP error: {e}"))?;
+ if response
+ .headers()
+ .get("content-type")
+ .is_none_or(|content_type| content_type != "application/json")
+ {
+ return Ok(None);
+ }
- let config = response
- .json()
- .await
- .map_err(|e| format!("JSON error: {e}"))?;
- Ok(Some(config))
+ let config = response
+ .json()
+ .await
+ .map_err(|e| format!("JSON error: {e}"))?;
+ Ok(Some(config))
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct SessionConfig {
- pub motd: Option,
- pub sessions: Vec,
+ pub motd: Option,
+ pub sessions: Vec,
}
macro_rules! date {
@@ -165,49 +165,49 @@ macro_rules! date {
}
impl Default for SessionConfig {
- fn default() -> Self {
- const YEAR: i32 = 2024;
- const NEXT_TUE_SESSION: NaiveDate = date!(18, 2, YEAR);
- const NEXT_SUN_SESSION: NaiveDate = date!(2, 3, YEAR);
- let next_next_sun_session = {
- let some_day_next_month = NEXT_SUN_SESSION.checked_add_months(Months::new(1)).unwrap();
- NaiveDate::from_weekday_of_month_opt(
- some_day_next_month.year(),
- some_day_next_month.month(),
- Weekday::Sun,
- 1,
- )
- .unwrap()
- };
+ fn default() -> Self {
+ const YEAR: i32 = 2024;
+ const NEXT_TUE_SESSION: NaiveDate = date!(18, 2, YEAR);
+ const NEXT_SUN_SESSION: NaiveDate = date!(2, 3, YEAR);
+ let next_next_sun_session = {
+ let some_day_next_month = NEXT_SUN_SESSION.checked_add_months(Months::new(1)).unwrap();
+ NaiveDate::from_weekday_of_month_opt(
+ some_day_next_month.year(),
+ some_day_next_month.month(),
+ Weekday::Sun,
+ 1,
+ )
+ .unwrap()
+ };
- Self {
- motd: Some("Jeder 1. Sonntag und 3. Dienstag im Monat".into()),
- sessions: vec![
- RegularSession::from(WeekdayOfMonth::new(1, Weekday::Sun))
- .with_note("10:00 Uhr")
- .except(
- NEXT_SUN_SESSION,
- Alternation {
- new_day: Some(NEXT_SUN_SESSION.checked_sub_days(Days::new(1)).unwrap().into()),
- ..Default::default()
- },
- )
- .except(
- next_next_sun_session,
- Alternation {
- note: Some("11 Uhr".into()),
- ..Default::default()
- },
- )
- .into(),
- RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue))
- .with_note("18:30 Uhr")
- .except(NEXT_TUE_SESSION, Cancellation::new())
- .into(),
- ExtraSession::from(NEXT_TUE_SESSION.checked_add_days(Days::new(2)).unwrap())
- .with_note("18 Uhr")
- .into(),
- ],
+ Self {
+ motd: Some("Jeder 1. Sonntag und 3. Dienstag im Monat".into()),
+ sessions: vec![
+ RegularSession::from(WeekdayOfMonth::new(1, Weekday::Sun))
+ .with_note("10:00 Uhr")
+ .except(
+ NEXT_SUN_SESSION,
+ Alternation {
+ new_day: Some(NEXT_SUN_SESSION.checked_sub_days(Days::new(1)).unwrap().into()),
+ ..Default::default()
+ },
+ )
+ .except(
+ next_next_sun_session,
+ Alternation {
+ note: Some("11 Uhr".into()),
+ ..Default::default()
+ },
+ )
+ .into(),
+ RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue))
+ .with_note("18:30 Uhr")
+ .except(NEXT_TUE_SESSION, Cancellation::new())
+ .into(),
+ ExtraSession::from(NEXT_TUE_SESSION.checked_add_days(Days::new(2)).unwrap())
+ .with_note("18 Uhr")
+ .into(),
+ ],
+ }
}
- }
}
diff --git a/leptos_webpage/styles.css b/leptos_webpage/styles.css
index 5763e7a..0df9cb7 100644
--- a/leptos_webpage/styles.css
+++ b/leptos_webpage/styles.css
@@ -1,93 +1,112 @@
:root {
- --darkred: darkred;
- --darkgreen: #196e0a;
- --darkgray: #292929;
- --gray: #606060;
- --white: white;
- --black: black;
- --red: red;
- --yellow: #bbbb11;
- --green: #1fd51f;
+ --darkred: darkred;
+ --darkgreen: #196e0a;
+ --darkgray: #292929;
+ --gray: #606060;
+ --white: white;
+ --black: black;
+ --red: red;
+ --yellow: #bbbb11;
+ --green: #1fd51f;
}
+
ul {
- list-style-position: inside;
+ list-style-position: inside;
}
+
body {
- font-size: 2rem;
+ font-size: 2rem;
}
+
html, body {
- margin: 0;
- padding: 0;
+ margin: 0;
+ padding: 0;
}
+
p {
- margin: 0;
+ margin: 0;
}
+
@media screen and (max-width: 1000px) {
- body {
- font-size: 3rem;
- }
+ body {
+ font-size: 3rem;
+ }
}
+
.background {
- background-color: var(--darkgray);
- color: var(--white);
- font-family: Arial, sans-serif;
- display: flex;
- justify-content: center;
- align-items: center;
- height: 100vh;
- margin: 0;
- overflow: scroll;
+ background-color: var(--darkgray);
+ color: var(--white);
+ font-family: Arial, sans-serif;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ margin: 0;
+ overflow: scroll;
}
+
.column {
- display: flex;
- flex-direction: column;
- gap: 10px;
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
}
+
.box {
- padding: 20px;
- border-radius: 10px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- text-align: center;
- justify-content: center;
- align-items: center;
- margin: 0 auto;
- width: 80%;
- max-width: 800px;
- box-sizing: border-box;
+ padding: 20px;
+ border-radius: 10px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+ margin: 0 auto;
+ width: 80%;
+ max-width: 800px;
+ box-sizing: border-box;
}
+
.wide {
- width: 100%;
- max-width: 1000px;
+ width: 100%;
+ max-width: 1000px;
}
+
.button {
- cursor: pointer;
+ cursor: pointer;
}
+
.button:hover {
- filter: brightness(1.2);
+ filter: brightness(1.2);
}
+
.elem-background {
- background-color: var(--darkgreen);
+ background-color: var(--darkgreen);
}
+
.error-background {
- background-color: var(--darkred);
+ background-color: var(--darkred);
}
+
.highlight-background {
- background-color: var(--green);
+ background-color: var(--green);
}
+
.cancel-background {
- background-color: var(--red);
+ background-color: var(--red);
}
+
.change-background {
- background-color: var(--yellow);
+ background-color: var(--yellow);
}
+
.small-text {
- color: var(--darkgray);
- font-size: 1rem;
- text-align: left;
+ color: var(--darkgray);
+ font-size: 1rem;
+ text-align: left;
}
+
.strikethrough {
- text-decoration: line-through;
+ text-decoration: line-through;
}
+
.bold {
- font-weight: bold;
+ font-weight: bold;
}
\ No newline at end of file
diff --git a/session_iter/src/day.rs b/session_iter/src/day.rs
index 4db6ced..5f74995 100644
--- a/session_iter/src/day.rs
+++ b/session_iter/src/day.rs
@@ -5,45 +5,45 @@ use std::ops::Deref;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
#[repr(transparent)]
pub struct Day {
- date: NaiveDate,
+ date: NaiveDate,
}
impl From for Day {
- fn from(date: NaiveDate) -> Self {
- Self { date }
- }
+ fn from(date: NaiveDate) -> Self {
+ Self { date }
+ }
}
impl Default for Day {
- fn default() -> Self {
- Self::from(Local::now().date_naive())
- }
+ fn default() -> Self {
+ Self::from(Local::now().date_naive())
+ }
}
impl Day {
- pub fn date(&self) -> NaiveDate {
- self.date
- }
+ pub fn date(&self) -> NaiveDate {
+ self.date
+ }
- pub fn weekday(&self) -> Weekday {
- self.date.weekday()
- }
+ pub fn weekday(&self) -> Weekday {
+ self.date.weekday()
+ }
- pub fn weekday_of_month(&self) -> u8 {
- self.date.day0() as u8 / 7 + 1
- }
+ pub fn weekday_of_month(&self) -> u8 {
+ self.date.day0() as u8 / 7 + 1
+ }
}
impl Deref for Day {
- type Target = NaiveDate;
+ type Target = NaiveDate;
- fn deref(&self) -> &Self::Target {
- &self.date
- }
+ fn deref(&self) -> &Self::Target {
+ &self.date
+ }
}
impl From for NaiveDate {
- fn from(day: Day) -> Self {
- day.date
- }
+ fn from(day: Day) -> Self {
+ day.date
+ }
}
\ No newline at end of file
diff --git a/session_iter/src/session.rs b/session_iter/src/session.rs
index 5276905..8282334 100644
--- a/session_iter/src/session.rs
+++ b/session_iter/src/session.rs
@@ -64,8 +64,8 @@ macro_rules! impl_from {
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum Session {
- Regular(RegularSession),
- Extra(ExtraSession),
+ Regular(RegularSession),
+ Extra(ExtraSession),
}
impl_from!(RegularSession for Session as Regular);
@@ -73,42 +73,42 @@ impl_from!(ExtraSession for Session as Extra);
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct RegularSession {
- pub rule: SessionRule,
- pub note: Note,
- #[serde(with = "serde_json_any_key::any_key_map")]
- pub except: BTreeMap,
+ pub rule: SessionRule,
+ pub note: Note,
+ #[serde(with = "serde_json_any_key::any_key_map")]
+ pub except: BTreeMap,
}
impl From for RegularSession {
- fn from(rule: SessionRule) -> Self {
- Self {
- rule,
- note: None,
- except: Default::default(),
+ fn from(rule: SessionRule) -> Self {
+ Self {
+ rule,
+ note: None,
+ except: Default::default(),
+ }
}
- }
}
impl RegularSession {
- pub fn except(mut self, day: D, except: E) -> Self
- where
- D: Into,
- E: Into,
- {
- self.except.insert(day.into(), except.into());
- self
- }
+ pub fn except(mut self, day: D, except: E) -> Self
+ where
+ D: Into,
+ E: Into,
+ {
+ self.except.insert(day.into(), except.into());
+ self
+ }
- ///gets the next session day, where no except applies. Can possibly return the `current_date`.
- pub fn next_regular_session_day(&self, current_date: D) -> Option
- where
- D: Into,
- {
- self
- .rule
- .to_session_day_iter(current_date)
- .find(|day| !self.except.contains_key(day))
- }
+ ///gets the next session day, where no except applies. Can possibly return the `current_date`.
+ pub fn next_regular_session_day(&self, current_date: D) -> Option
+ where
+ D: Into,
+ {
+ self
+ .rule
+ .to_session_day_iter(current_date)
+ .find(|day| !self.except.contains_key(day))
+ }
}
impl_from!(WeekdayOfMonth for RegularSession by SessionRule);
@@ -117,14 +117,14 @@ impl_with_note!(RegularSession);
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub struct ExtraSession {
- pub day: Day,
- pub note: Note,
+ pub day: Day,
+ pub note: Note,
}
impl From for ExtraSession {
- fn from(day: Day) -> Self {
- Self { day, note: None }
- }
+ fn from(day: Day) -> Self {
+ Self { day, note: None }
+ }
}
impl_from!(NaiveDate for ExtraSession by Day);
@@ -132,15 +132,15 @@ impl_opt_noted!(ExtraSession);
impl_with_note!(ExtraSession);
impl Dated for ExtraSession {
- fn day(&self) -> Day {
- self.day
- }
+ fn day(&self) -> Day {
+ self.day
+ }
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum Except {
- Alternation(Alternation),
- Cancellation(Cancellation),
+ Alternation(Alternation),
+ Cancellation(Cancellation),
}
impl_from!(Alternation for Except);
@@ -149,18 +149,18 @@ impl_opt_noted!(Except with Alternation, Cancellation);
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
pub struct Alternation {
- pub note: Note,
- ///the date when the alternation should show up in the calendar, or the original date
- pub new_day: Option,
+ pub note: Note,
+ ///the date when the alternation should show up in the calendar, or the original date
+ pub new_day: Option,
}
impl From for Alternation {
- fn from(day: Day) -> Self {
- Self {
- new_day: Some(day),
- ..Default::default()
+ fn from(day: Day) -> Self {
+ Self {
+ new_day: Some(day),
+ ..Default::default()
+ }
}
- }
}
impl_from!(NaiveDate for Alternation by Day);
@@ -170,27 +170,27 @@ impl_with_note!(Alternation);
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Cancellation {
- pub note: Note,
+ pub note: Note,
}
impl Cancellation {
- pub fn new() -> Self {
- Self::default()
- }
+ pub fn new() -> Self {
+ Self::default()
+ }
}
impl_opt_noted!(Cancellation);
impl_with_note!(Cancellation);
pub trait Dated {
- /// The day when this should show up in a calendar
- fn day(&self) -> Day;
+ /// The day when this should show up in a calendar
+ fn day(&self) -> Day;
}
pub trait OptNoted {
- fn note(&self) -> Option<&str>;
+ fn note(&self) -> Option<&str>;
}
pub trait WithNote {
- fn with_note(self, note: &str) -> Self;
+ fn with_note(self, note: &str) -> Self;
}
diff --git a/session_iter/src/session/iter.rs b/session_iter/src/session/iter.rs
index 78643a3..d49e21b 100644
--- a/session_iter/src/session/iter.rs
+++ b/session_iter/src/session/iter.rs
@@ -1,7 +1,7 @@
use crate::day::Day;
use crate::session::rule::SessionRuleLike;
use crate::session::{
- Alternation, Cancellation, Dated, Except, ExtraSession, OptNoted, RegularSession, Session,
+ Alternation, Cancellation, Dated, Except, ExtraSession, OptNoted, RegularSession, Session,
};
use chrono::Days;
use serde::{Deserialize, Serialize};
@@ -10,308 +10,308 @@ use std::hash::Hash;
#[derive(Debug, Clone)]
pub struct DatedSessionIter {
- sessions: BTreeMap>,
+ sessions: BTreeMap>,
}
impl DatedSessionIter {
- pub fn new(start_date: D, sessions: S) -> DatedSessionIter
- where
- D: Into,
- S: IntoIterator- ,
- {
- let current_date = start_date.into();
+ pub fn new
(start_date: D, sessions: S) -> DatedSessionIter
+ where
+ D: Into,
+ S: IntoIterator- ,
+ {
+ let current_date = start_date.into();
- //map every session and their excepts to a date when they should show up in the calendar
- let sessions =
- sessions
- .into_iter()
- .flat_map(|session| match session {
- Session::Regular(session) => session
- .except
- .iter()
- .filter(|(&day, _)| session.rule.accepts(day))
- .map(|(&day, except)| match except {
- Except::Alternation(alternation) => DatedSession::Altered {
- day,
- regular: session.clone(),
- cause: alternation.clone(),
- },
- Except::Cancellation(cancellation) => DatedSession::Canceled {
- day,
- regular: session.clone(),
- cause: cancellation.clone(),
- },
- })
- .chain(session.next_regular_session_day(current_date).map(|day| {
- DatedSession::Regular {
- day,
- session: session.clone(),
- }
- }))
- .collect(),
- Session::Extra(extra) => vec![extra.into()],
- })
- //filter out and entries which would lay in the past
- .filter(|dated_session| dated_session.day() >= current_date)
- //group sessions on the same day together
- .fold(
- BTreeMap::<_, VecDeque<_>>::new(),
- |mut map, dated_session| {
- map
- .entry(dated_session.day())
- .or_default()
- .push_back(dated_session);
- map
- },
- );
+ //map every session and their excepts to a date when they should show up in the calendar
+ let sessions =
+ sessions
+ .into_iter()
+ .flat_map(|session| match session {
+ Session::Regular(session) => session
+ .except
+ .iter()
+ .filter(|(&day, _)| session.rule.accepts(day))
+ .map(|(&day, except)| match except {
+ Except::Alternation(alternation) => DatedSession::Altered {
+ day,
+ regular: session.clone(),
+ cause: alternation.clone(),
+ },
+ Except::Cancellation(cancellation) => DatedSession::Canceled {
+ day,
+ regular: session.clone(),
+ cause: cancellation.clone(),
+ },
+ })
+ .chain(session.next_regular_session_day(current_date).map(|day| {
+ DatedSession::Regular {
+ day,
+ session: session.clone(),
+ }
+ }))
+ .collect(),
+ Session::Extra(extra) => vec![extra.into()],
+ })
+ //filter out and entries which would lay in the past
+ .filter(|dated_session| dated_session.day() >= current_date)
+ //group sessions on the same day together
+ .fold(
+ BTreeMap::<_, VecDeque<_>>::new(),
+ |mut map, dated_session| {
+ map
+ .entry(dated_session.day())
+ .or_default()
+ .push_back(dated_session);
+ map
+ },
+ );
- Self { sessions }
- }
+ Self { sessions }
+ }
}
impl Iterator for DatedSessionIter {
- type Item = DatedSession;
+ type Item = DatedSession;
- fn next(&mut self) -> Option
{
- let mut entry = self.sessions.first_entry()?;
- let session = entry.get_mut().pop_front()?;
- if entry.get().is_empty() {
- entry.remove();
- }
-
- //make sure regular sessions remain in map
- if let DatedSession::Regular { ref session, day } = session {
- //calculate next day, because next_regular_session_day of a session day returns that very session day
- if let Some(next_day) = day.checked_add_days(Days::new(1)) {
- if let Some(next_session_day) = session.next_regular_session_day(next_day) {
- self
- .sessions
- .entry(next_session_day)
- .or_default()
- .push_back(DatedSession::Regular {
- day: next_session_day,
- session: session.clone(),
- })
+ fn next(&mut self) -> Option {
+ let mut entry = self.sessions.first_entry()?;
+ let session = entry.get_mut().pop_front()?;
+ if entry.get().is_empty() {
+ entry.remove();
}
- }
+
+ //make sure regular sessions remain in map
+ if let DatedSession::Regular { ref session, day } = session {
+ //calculate next day, because next_regular_session_day of a session day returns that very session day
+ if let Some(next_day) = day.checked_add_days(Days::new(1)) {
+ if let Some(next_session_day) = session.next_regular_session_day(next_day) {
+ self
+ .sessions
+ .entry(next_session_day)
+ .or_default()
+ .push_back(DatedSession::Regular {
+ day: next_session_day,
+ session: session.clone(),
+ })
+ }
+ }
+ }
+ Some(session)
}
- Some(session)
- }
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum DatedSession {
- Regular {
- day: Day,
- session: RegularSession,
- },
- Extra(ExtraSession),
- Canceled {
- day: Day,
- regular: RegularSession,
- cause: Cancellation,
- },
- Altered {
- ///the day when the regular session would have applied
- day: Day,
- regular: RegularSession,
- cause: Alternation,
- },
+ Regular {
+ day: Day,
+ session: RegularSession,
+ },
+ Extra(ExtraSession),
+ Canceled {
+ day: Day,
+ regular: RegularSession,
+ cause: Cancellation,
+ },
+ Altered {
+ ///the day when the regular session would have applied
+ day: Day,
+ regular: RegularSession,
+ cause: Alternation,
+ },
}
impl From for DatedSession {
- fn from(value: ExtraSession) -> Self {
- Self::Extra(value)
- }
+ fn from(value: ExtraSession) -> Self {
+ Self::Extra(value)
+ }
}
impl Dated for DatedSession {
- fn day(&self) -> Day {
- match *self {
- DatedSession::Regular { day, .. } => day,
- DatedSession::Extra(ref extra) => extra.day(),
- DatedSession::Canceled { day, .. } => day,
- DatedSession::Altered { day, ref cause, .. } => cause.new_day.unwrap_or(day),
+ fn day(&self) -> Day {
+ match *self {
+ DatedSession::Regular { day, .. } => day,
+ DatedSession::Extra(ref extra) => extra.day(),
+ DatedSession::Canceled { day, .. } => day,
+ DatedSession::Altered { day, ref cause, .. } => cause.new_day.unwrap_or(day),
+ }
}
- }
}
impl OptNoted for DatedSession {
- fn note(&self) -> Option<&str> {
- match self {
- DatedSession::Regular { session, .. } => session.note(),
- DatedSession::Extra(extra) => extra.note(),
- DatedSession::Canceled { cause, .. } => cause.note(),
- DatedSession::Altered { cause, .. } => cause.note(),
+ fn note(&self) -> Option<&str> {
+ match self {
+ DatedSession::Regular { session, .. } => session.note(),
+ DatedSession::Extra(extra) => extra.note(),
+ DatedSession::Canceled { cause, .. } => cause.note(),
+ DatedSession::Altered { cause, .. } => cause.note(),
+ }
}
- }
}
#[cfg(test)]
mod test {
- use crate::session::iter::{DatedSession, DatedSessionIter};
- use crate::session::rule::WeekdayOfMonth;
- use crate::session::{Alternation, Cancellation, ExtraSession, RegularSession, WithNote};
- use crate::test_util::{date, day};
- use chrono::Weekday;
+ use crate::session::iter::{DatedSession, DatedSessionIter};
+ use crate::session::rule::WeekdayOfMonth;
+ use crate::session::{Alternation, Cancellation, ExtraSession, RegularSession, WithNote};
+ use crate::test_util::{date, day};
+ use chrono::Weekday;
- #[test]
- fn test_regular() {
- let tue_session = RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue));
- let sun_session = RegularSession::from(WeekdayOfMonth::new(1, Weekday::Sun));
- let mut iter = DatedSessionIter::new(
- date(17, 2, 2025),
- [tue_session.clone().into(), sun_session.clone().into()],
- );
+ #[test]
+ fn test_regular() {
+ let tue_session = RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue));
+ let sun_session = RegularSession::from(WeekdayOfMonth::new(1, Weekday::Sun));
+ let mut iter = DatedSessionIter::new(
+ date(17, 2, 2025),
+ [tue_session.clone().into(), sun_session.clone().into()],
+ );
- assert_eq!(
- iter.next(),
- Some(DatedSession::Regular {
- day: day(18, 2, 2025),
- session: tue_session.clone()
- })
- );
- assert_eq!(
- iter.next(),
- Some(DatedSession::Regular {
- day: day(2, 3, 2025),
- session: sun_session.clone()
- })
- );
- assert_eq!(
- iter.next(),
- Some(DatedSession::Regular {
- day: day(18, 3, 2025),
- session: tue_session.clone()
- })
- );
- }
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Regular {
+ day: day(18, 2, 2025),
+ session: tue_session.clone()
+ })
+ );
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Regular {
+ day: day(2, 3, 2025),
+ session: sun_session.clone()
+ })
+ );
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Regular {
+ day: day(18, 3, 2025),
+ session: tue_session.clone()
+ })
+ );
+ }
- #[test]
- fn test_old() {
- let extra_session = ExtraSession::from(day(15, 2, 2025));
- let regular_session = RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue))
- .with_note("18:30 Uhr")
- .except(day(18, 2, 2025), Cancellation::new())
- .except(day(18, 3, 2025), Alternation::from(day(21, 1, 2025)));
+ #[test]
+ fn test_old() {
+ let extra_session = ExtraSession::from(day(15, 2, 2025));
+ let regular_session = RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue))
+ .with_note("18:30 Uhr")
+ .except(day(18, 2, 2025), Cancellation::new())
+ .except(day(18, 3, 2025), Alternation::from(day(21, 1, 2025)));
- let mut iter = DatedSessionIter::new(
- day(19, 2, 2025),
- [regular_session.clone().into(), extra_session.into()],
- );
+ let mut iter = DatedSessionIter::new(
+ day(19, 2, 2025),
+ [regular_session.clone().into(), extra_session.into()],
+ );
- assert_eq!(
- iter.next(),
- Some(DatedSession::Regular {
- day: day(15, 4, 2025),
- session: regular_session.clone(),
- })
- );
- }
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Regular {
+ day: day(15, 4, 2025),
+ session: regular_session.clone(),
+ })
+ );
+ }
- #[test]
- fn test_invalid_except() {
- let regular_session = RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue))
- .except(day(17, 2, 2025), Cancellation::new());
+ #[test]
+ fn test_invalid_except() {
+ let regular_session = RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue))
+ .except(day(17, 2, 2025), Cancellation::new());
- let mut iter = DatedSessionIter::new(day(17, 2, 2025), [regular_session.clone().into()]);
+ let mut iter = DatedSessionIter::new(day(17, 2, 2025), [regular_session.clone().into()]);
- assert_eq!(
- iter.next(),
- Some(DatedSession::Regular {
- day: day(18, 2, 2025),
- session: regular_session.clone()
- })
- );
- }
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Regular {
+ day: day(18, 2, 2025),
+ session: regular_session.clone()
+ })
+ );
+ }
- #[test]
- fn test_extra_altered_and_canceled() {
- //an extra session on the same day as a tuesday session
- let extra_session = ExtraSession::from(day(18, 2, 2025)).with_note("morning session");
- //an alternation of a tuesday session without moving it
- let (note_alternation_day, note_alternation) = (
- day(18, 3, 2025),
- Alternation {
- note: Some("a little different today".into()),
- ..Default::default()
- },
- );
- let tue_session = RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue))
- .except(note_alternation_day, note_alternation.clone());
- //a sunday session moved in front of a tuesday session
- let moved_sun_session_day = day(16, 2, 2025);
- let (day_alternation_day, day_alternation) =
- (day(2, 3, 2025), Alternation::from(moved_sun_session_day));
- //a canceled sunday session
- let (cancel_day, cancellation) = (day(6, 4, 2025), Cancellation::new());
- let sun_session = RegularSession::from(WeekdayOfMonth::new(1, Weekday::Sun))
- .except(day_alternation_day, day_alternation.clone())
- .except(cancel_day, cancellation.clone());
+ #[test]
+ fn test_extra_altered_and_canceled() {
+ //an extra session on the same day as a tuesday session
+ let extra_session = ExtraSession::from(day(18, 2, 2025)).with_note("morning session");
+ //an alternation of a tuesday session without moving it
+ let (note_alternation_day, note_alternation) = (
+ day(18, 3, 2025),
+ Alternation {
+ note: Some("a little different today".into()),
+ ..Default::default()
+ },
+ );
+ let tue_session = RegularSession::from(WeekdayOfMonth::new(3, Weekday::Tue))
+ .except(note_alternation_day, note_alternation.clone());
+ //a sunday session moved in front of a tuesday session
+ let moved_sun_session_day = day(16, 2, 2025);
+ let (day_alternation_day, day_alternation) =
+ (day(2, 3, 2025), Alternation::from(moved_sun_session_day));
+ //a canceled sunday session
+ let (cancel_day, cancellation) = (day(6, 4, 2025), Cancellation::new());
+ let sun_session = RegularSession::from(WeekdayOfMonth::new(1, Weekday::Sun))
+ .except(day_alternation_day, day_alternation.clone())
+ .except(cancel_day, cancellation.clone());
- let mut iter = DatedSessionIter::new(
- day(15, 2, 2025),
- [
- extra_session.clone().into(),
- tue_session.clone().into(),
- sun_session.clone().into(),
- ],
- );
+ let mut iter = DatedSessionIter::new(
+ day(15, 2, 2025),
+ [
+ extra_session.clone().into(),
+ tue_session.clone().into(),
+ sun_session.clone().into(),
+ ],
+ );
- //at first comes the moved sunday
- assert_eq!(
- iter.next(),
- Some(DatedSession::Altered {
- day: day_alternation_day,
- regular: sun_session.clone(),
- cause: day_alternation.clone(),
- })
- );
- //then comes the extra session on tuesday (because it was first in the list)
- assert_eq!(
- iter.next(),
- Some(DatedSession::Extra(extra_session.clone()))
- );
- //after that comes a regular tuesday session
- assert_eq!(
- iter.next(),
- Some(DatedSession::Regular {
- day: day(18, 2, 2025),
- session: tue_session.clone()
- })
- );
- //now we have an altered but not moved tuesday session
- assert_eq!(
- iter.next(),
- Some(DatedSession::Altered {
- day: note_alternation_day,
- regular: tue_session.clone(),
- cause: note_alternation.clone(),
- })
- );
- //the next sunday session was canceled
- assert_eq!(
- iter.next(),
- Some(DatedSession::Canceled {
- day: cancel_day,
- regular: sun_session.clone(),
- cause: cancellation.clone(),
- })
- );
- //and now we are back to regular sessions
- assert_eq!(
- iter.next(),
- Some(DatedSession::Regular {
- day: day(15, 4, 2025),
- session: tue_session.clone()
- })
- );
- assert_eq!(
- iter.next(),
- Some(DatedSession::Regular {
- day: day(4, 5, 2025),
- session: sun_session.clone()
- })
- );
- }
+ //at first comes the moved sunday
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Altered {
+ day: day_alternation_day,
+ regular: sun_session.clone(),
+ cause: day_alternation.clone(),
+ })
+ );
+ //then comes the extra session on tuesday (because it was first in the list)
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Extra(extra_session.clone()))
+ );
+ //after that comes a regular tuesday session
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Regular {
+ day: day(18, 2, 2025),
+ session: tue_session.clone()
+ })
+ );
+ //now we have an altered but not moved tuesday session
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Altered {
+ day: note_alternation_day,
+ regular: tue_session.clone(),
+ cause: note_alternation.clone(),
+ })
+ );
+ //the next sunday session was canceled
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Canceled {
+ day: cancel_day,
+ regular: sun_session.clone(),
+ cause: cancellation.clone(),
+ })
+ );
+ //and now we are back to regular sessions
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Regular {
+ day: day(15, 4, 2025),
+ session: tue_session.clone()
+ })
+ );
+ assert_eq!(
+ iter.next(),
+ Some(DatedSession::Regular {
+ day: day(4, 5, 2025),
+ session: sun_session.clone()
+ })
+ );
+ }
}
diff --git a/session_iter/src/session/rule.rs b/session_iter/src/session/rule.rs
index b7793b2..3d3155c 100644
--- a/session_iter/src/session/rule.rs
+++ b/session_iter/src/session/rule.rs
@@ -5,148 +5,148 @@ use std::ops::Deref;
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum SessionRule {
- WeekdayOfMonth(WeekdayOfMonth),
+ WeekdayOfMonth(WeekdayOfMonth),
}
impl From for SessionRule {
- fn from(value: WeekdayOfMonth) -> Self {
- Self::WeekdayOfMonth(value)
- }
+ fn from(value: WeekdayOfMonth) -> Self {
+ Self::WeekdayOfMonth(value)
+ }
}
impl SessionRule {
- pub fn to_session_day_iter(&self, start_date: D) -> SessionDayIter<&Self>
- where
- D: Into,
- {
- SessionDayIter {
- rule: self,
- start_date: Some(start_date.into()),
+ pub fn to_session_day_iter(&self, start_date: D) -> SessionDayIter<&Self>
+ where
+ D: Into,
+ {
+ SessionDayIter {
+ rule: self,
+ start_date: Some(start_date.into()),
+ }
}
- }
}
impl SessionRuleLike for SessionRule {
- fn determine_next_date(&self, current_date: Day) -> Option {
- match self {
- SessionRule::WeekdayOfMonth(weekday_of_month) => {
- weekday_of_month.determine_next_date(current_date)
- }
+ fn determine_next_date(&self, current_date: Day) -> Option {
+ match self {
+ SessionRule::WeekdayOfMonth(weekday_of_month) => {
+ weekday_of_month.determine_next_date(current_date)
+ }
+ }
}
- }
- fn accepts(&self, day: Day) -> bool {
- match self {
- SessionRule::WeekdayOfMonth(weekday_of_month) => weekday_of_month.accepts(day),
+ fn accepts(&self, day: Day) -> bool {
+ match self {
+ SessionRule::WeekdayOfMonth(weekday_of_month) => weekday_of_month.accepts(day),
+ }
}
- }
}
#[derive(Debug, Clone)]
pub struct SessionDayIter {
- pub rule: R,
- pub start_date: Option,
+ pub rule: R,
+ pub start_date: Option,
}
impl Iterator for SessionDayIter
where
- R: Deref,
- S: SessionRuleLike,
+ R: Deref,
+ S: SessionRuleLike,
{
- type Item = Day;
+ type Item = Day;
- fn next(&mut self) -> Option {
- let start_date = self.start_date?;
- let session_date = self.rule.determine_next_date(start_date);
- self.start_date = session_date
- .and_then(|session_date| session_date.checked_add_days(Days::new(1)))
- .map(Day::from);
- session_date
- }
+ fn next(&mut self) -> Option {
+ let start_date = self.start_date?;
+ let session_date = self.rule.determine_next_date(start_date);
+ self.start_date = session_date
+ .and_then(|session_date| session_date.checked_add_days(Days::new(1)))
+ .map(Day::from);
+ session_date
+ }
}
impl SessionDayIter
where
- R: Deref,
+ R: Deref,
{
- pub fn to_owned(&self) -> SessionDayIter {
- SessionDayIter {
- rule: self.rule.clone(),
- start_date: self.start_date,
+ pub fn to_owned(&self) -> SessionDayIter {
+ SessionDayIter {
+ rule: self.rule.clone(),
+ start_date: self.start_date,
+ }
}
- }
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct WeekdayOfMonth {
- pub n: u8,
- pub weekday: Weekday,
+ pub n: u8,
+ pub weekday: Weekday,
}
impl WeekdayOfMonth {
- pub fn new(n: u8, weekday: Weekday) -> Self {
- Self { n, weekday }
- }
+ pub fn new(n: u8, weekday: Weekday) -> Self {
+ Self { n, weekday }
+ }
}
impl SessionRuleLike for WeekdayOfMonth {
- fn determine_next_date(&self, current_date: Day) -> Option {
- let session_this_month = NaiveDate::from_weekday_of_month_opt(
- current_date.year(),
- current_date.month(),
- self.weekday,
- self.n,
- )?;
+ fn determine_next_date(&self, current_date: Day) -> Option {
+ let session_this_month = NaiveDate::from_weekday_of_month_opt(
+ current_date.year(),
+ current_date.month(),
+ self.weekday,
+ self.n,
+ )?;
- let date = if session_this_month >= current_date.date() {
- session_this_month
- } else {
- let session_next_month = current_date.checked_add_months(Months::new(1))?;
- NaiveDate::from_weekday_of_month_opt(
- session_next_month.year(),
- session_next_month.month(),
- self.weekday,
- self.n,
- )?
- };
+ let date = if session_this_month >= current_date.date() {
+ session_this_month
+ } else {
+ let session_next_month = current_date.checked_add_months(Months::new(1))?;
+ NaiveDate::from_weekday_of_month_opt(
+ session_next_month.year(),
+ session_next_month.month(),
+ self.weekday,
+ self.n,
+ )?
+ };
- Some(date.into())
- }
+ Some(date.into())
+ }
- fn accepts(&self, day: Day) -> bool {
- day.weekday() == self.weekday && day.weekday_of_month() == self.n
- }
+ fn accepts(&self, day: Day) -> bool {
+ day.weekday() == self.weekday && day.weekday_of_month() == self.n
+ }
}
pub trait SessionRuleLike {
- /// Determines the next session date in form of a [Day], possibly including the `current_date`.
- fn determine_next_date(&self, current_date: Day) -> Option;
+ /// Determines the next session date in form of a [Day], possibly including the `current_date`.
+ fn determine_next_date(&self, current_date: Day) -> Option;
- /// Whether this rule would be able to produce the given `day`.
- fn accepts(&self, day: Day) -> bool;
+ /// Whether this rule would be able to produce the given `day`.
+ fn accepts(&self, day: Day) -> bool;
}
#[cfg(test)]
mod test_weekday_of_month {
- use crate::session::rule::{SessionRuleLike, WeekdayOfMonth};
- use crate::test_util::day;
- use chrono::Weekday;
+ use crate::session::rule::{SessionRuleLike, WeekdayOfMonth};
+ use crate::test_util::day;
+ use chrono::Weekday;
- #[test]
- fn test_next_date() {
- let rule = WeekdayOfMonth::new(3, Weekday::Tue);
+ #[test]
+ fn test_next_date() {
+ let rule = WeekdayOfMonth::new(3, Weekday::Tue);
- assert_eq!(
- rule.determine_next_date(day(17, 2, 2025)),
- Some(day(18, 2, 2025))
- );
- assert_eq!(
- rule.determine_next_date(day(18, 2, 2025)),
- Some(day(18, 2, 2025))
- );
- assert_eq!(
- rule.determine_next_date(day(19, 2, 2025)),
- Some(day(18, 3, 2025))
- );
- }
+ assert_eq!(
+ rule.determine_next_date(day(17, 2, 2025)),
+ Some(day(18, 2, 2025))
+ );
+ assert_eq!(
+ rule.determine_next_date(day(18, 2, 2025)),
+ Some(day(18, 2, 2025))
+ );
+ assert_eq!(
+ rule.determine_next_date(day(19, 2, 2025)),
+ Some(day(18, 3, 2025))
+ );
+ }
}
diff --git a/session_iter/src/test_util.rs b/session_iter/src/test_util.rs
index 9261d54..b138f7d 100644
--- a/session_iter/src/test_util.rs
+++ b/session_iter/src/test_util.rs
@@ -2,9 +2,9 @@ use crate::day::Day;
use chrono::NaiveDate;
pub fn date(day: u32, month: u32, year: i32) -> NaiveDate {
- NaiveDate::from_ymd_opt(year, month, day).expect("valid date")
+ NaiveDate::from_ymd_opt(year, month, day).expect("valid date")
}
pub fn day(day: u32, month: u32, year: i32) -> Day {
- date(day, month, year).into()
+ date(day, month, year).into()
}
\ No newline at end of file