Refactor sessions

This commit is contained in:
Leonard Steppy 2025-02-15 17:25:36 +01:00
parent 9439593409
commit 0c2716db8e
3 changed files with 212 additions and 96 deletions

View File

@ -1,102 +1,10 @@
use crate::session_date_calculator::{Day, NthWeekday};
use chrono::{NaiveDate, Weekday};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::session_date_calculator::Day;
use chrono::Weekday;
pub mod session;
pub mod session_date_calculator;
pub mod webpage;
#[derive(Debug, Clone)]
pub struct DatedSession {
pub day: Day,
pub session: Session,
pub applying_exception: Option<Exception>,
}
impl Noted for DatedSession {
fn note(&self) -> Option<&String> {
match &self.applying_exception {
Some(e) => e.note(),
None => self.session.note(),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum Session {
Regular {
rule: NthWeekday,
note: Option<String>,
except: HashMap<NaiveDate, Exception>,
},
Extra {
date: NaiveDate,
note: Option<String>,
},
}
impl Session {
pub fn into_dated(self, day: Day) -> Result<DatedSession, Self> {
if !self.is_applicable_to(&day) {
return Err(self);
}
let dated_session = DatedSession {
applying_exception: match self {
Session::Regular { ref except, .. } => except.get(&day.date).cloned(),
_ => None,
},
session: self,
day,
};
Ok(dated_session)
}
pub fn is_applicable_to(&self, day: &Day) -> bool {
match *self {
Session::Regular { rule, .. } => rule.matches(day),
Session::Extra { date, .. } => day.date == date,
}
}
}
impl Noted for Session {
fn note(&self) -> Option<&String> {
match self {
Session::Regular { note, .. } => note,
Session::Extra { note, .. } => note,
}
.as_ref()
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum Exception {
Cancel {
note: Option<String>,
},
Alter {
#[serde(default)]
date: Option<NaiveDate>,
#[serde(default)]
note: Option<String>,
},
}
impl Noted for Exception {
fn note(&self) -> Option<&String> {
match self {
Exception::Cancel { note, .. } => note,
Exception::Alter { note, .. } => note,
}
.as_ref()
}
}
pub trait Noted {
fn note(&self) -> Option<&String>;
}
pub fn localize_day(day: &Day) -> String {
format!(
"{}, {}",

208
src/session.rs Normal file
View File

@ -0,0 +1,208 @@
use crate::session_date_calculator::{Day, NthWeekday};
use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct DatedSession {
pub day: Day,
pub session: Session,
pub applying_exception: Option<Exception>,
}
impl Noted for DatedSession {
fn get_note(&self) -> Option<&String> {
match &self.applying_exception {
Some(e) => e.get_note(),
None => self.session.get_note(),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum Session {
Regular(RegularSession),
Extra(ExtraSession),
}
impl From<RegularSession> for Session {
fn from(value: RegularSession) -> Self {
Self::Regular(value)
}
}
impl From<ExtraSession> for Session {
fn from(value: ExtraSession) -> Self {
Self::Extra(value)
}
}
impl Session {
pub fn into_dated(self, day: Day) -> Result<DatedSession, Self> {
if !self.is_applicable_to(&day) {
return Err(self);
}
let dated_session = DatedSession {
applying_exception: match self {
Session::Regular(RegularSession { ref except, .. }) => except.get(&day.date).cloned(),
_ => None,
},
session: self,
day,
};
Ok(dated_session)
}
pub fn is_applicable_to(&self, day: &Day) -> bool {
match *self {
Session::Regular(RegularSession { rule, .. }) => rule.matches(day),
Session::Extra(ExtraSession { date, .. }) => day.date == date,
}
}
}
impl Noted for Session {
fn get_note(&self) -> Option<&String> {
match self {
Session::Regular(session) => session.get_note(),
Session::Extra(session) => session.get_note(),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct RegularSession {
pub rule: NthWeekday,
pub note: Option<String>,
pub except: HashMap<NaiveDate, Exception>,
}
impl From<NthWeekday> for RegularSession {
fn from(rule: NthWeekday) -> Self {
Self {
rule,
note: None,
except: Default::default(),
}
}
}
impl RegularSession {
pub fn with_exception<D, E>(mut self, date: D, exception: E) -> Self
where
D: Into<NaiveDate>,
E: Into<Exception>,
{
self.except.insert(date.into(), exception.into());
self
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct ExtraSession {
pub date: NaiveDate,
pub note: Option<String>,
}
impl From<NaiveDate> for ExtraSession {
fn from(date: NaiveDate) -> Self {
Self { date, note: None }
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum Exception {
Cancel(CancelException),
Alter(AlterException),
}
impl From<CancelException> for Exception {
fn from(value: CancelException) -> Self {
Self::Cancel(value)
}
}
impl From<AlterException> for Exception {
fn from(value: AlterException) -> Self {
Self::Alter(value)
}
}
impl Noted for Exception {
fn get_note(&self) -> Option<&String> {
match self {
Exception::Cancel(exception) => exception.get_note(),
Exception::Alter(exception) => exception.get_note(),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct CancelException {
pub note: Option<String>,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct AlterException {
pub date: Option<NaiveDate>,
pub note: Option<String>,
}
impl From<NaiveDate> for AlterException {
fn from(value: NaiveDate) -> Self {
Self {
date: Some(value),
..Self::default()
}
}
}
pub trait Noted {
fn get_note(&self) -> Option<&String>;
}
macro_rules! impl_noted {
($ty: ident) => {
impl Noted for $ty {
fn get_note(&self) -> Option<&String> {
self.note.as_ref()
}
}
};
}
impl_noted!(RegularSession);
impl_noted!(ExtraSession);
impl_noted!(AlterException);
impl_noted!(CancelException);
pub trait WithNote {
fn with_note<S>(self, note: S) -> Self
where
S: ToString;
}
macro_rules! impl_with_node {
($ty: ident) => {
impl WithNote for $ty {
fn with_note<S>(self, note: S) -> Self
where
S: ToString,
{
#[allow(clippy::needless_update)]
Self {
note: Some(note.to_string()),
..self
}
}
}
};
}
impl_with_node!(AlterException);
impl_with_node!(CancelException);
impl_with_node!(ExtraSession);
impl_with_node!(RegularSession);

View File

@ -96,7 +96,7 @@ impl Iterator for DayIter {
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct Day {
pub date: NaiveDate,
pub weekday: Weekday,