use crate::error::Error; use j_db::database::Database; use j_db::error::JDbError; use poise::serenity_prelude::UserId; use reqwest::Url; use serde::{Deserialize, Serialize}; use std::collections::HashMap; pub const LOWER_RATING: f32 = -10.0; pub const UPPER_RATING: f32 = 10.0; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Movie { id: Option, pub name: String, pub rating_object: String, pub poster: Url, pub ratings: HashMap, } impl j_db::model::JdbModel for Movie { fn id(&self) -> Option { self.id } fn set_id(&mut self, id: u64) { self.id = Some(id) } fn tree() -> String { "Movie".to_string() } fn check_unique(&self, other: &Self) -> bool { !self.name.eq_ignore_ascii_case(&other.name) } } impl Movie { pub fn add_movie( db: &Database, name: String, rating_object: String, poster: Url, ) -> Result { Ok(db.insert(Self { id: None, name, rating_object, poster, ratings: Default::default(), })?) } pub fn get_movie(db: &Database, name: &str) -> Result { Ok(db .filter(|_, movie: &Movie| movie.name.eq_ignore_ascii_case(name))? .next() .ok_or(JDbError::NotFound)?) } pub fn get_movies(db: &Database) -> Result, Error> { Ok(db .filter(|_, _movie: &Movie| true)? .collect()) } pub fn remove_movie(db: &Database, name: &str) -> Result { let movie = Self::get_movie(db, name)?; db.remove::(movie.id.unwrap())?; Ok(movie) } pub fn add_rating(db: &Database, name: &str, user: UserId, rating: f32) -> Result<(), Error> { let mut movie = Self::get_movie(db, name)?; movie.ratings.insert(user, rating); db.insert(movie)?; Ok(()) } pub fn calculate_rating(&self) -> f32 { if self.ratings.is_empty() { 0.0 } else { self.ratings.values().copied().sum::() / self.ratings.len() as f32 } } }