use crate::album_manager::{AlbumManager, AlbumQuery, Image}; use crate::error::Error; use j_db::database::Database; use j_db::error::JDbError; use j_db::model::JdbModel; use rand::prelude::{IteratorRandom, SliceRandom}; use rand::thread_rng; use serde::{Deserialize, Serialize}; use std::fmt::Debug; #[derive(Debug, Deserialize, Serialize, Clone)] pub struct MotivationConfig { id: Option, pub album: Vec, pub action: Vec, pub goal: Vec, } impl JdbModel for MotivationConfig { fn id(&self) -> Option { self.id } fn set_id(&mut self, id: u64) { self.id = Some(id) } fn tree() -> String { "Motivation".to_string() } fn check_unique(&self, _: &Self) -> bool { false } } impl MotivationConfig { pub fn get_motivation_config(db: &Database) -> Result { Ok(db .filter(|_, _: &MotivationConfig| true)? .next() .unwrap_or(Self { id: None, album: vec![], action: vec![], goal: vec![], })) } pub fn add_album(db: &Database, id: u64) -> Result<(), Error> { let mut motivation = Self::get_motivation_config(db)?; motivation.album.push(id); db.insert(motivation)?; Ok(()) } pub fn add_action(db: &Database, action: &str) -> Result<(), Error> { let mut motivation = Self::get_motivation_config(db)?; motivation.action.push(action.to_string()); db.insert(motivation)?; Ok(()) } pub fn add_goal(db: &Database, goal: &str) -> Result<(), Error> { let mut motivation = Self::get_motivation_config(db)?; motivation.goal.push(goal.to_string()); db.insert(motivation)?; Ok(()) } pub async fn generate_motivation( db: &Database, picox: &AlbumManager, border_color: &str, album_name: Option, ) -> Result { let motivation = Self::get_motivation_config(db)?; let mut images = Vec::new(); if let Some(album_name) = album_name { let query = AlbumQuery { album_name: Some(album_name), }; let albums = picox.query_album(query).await?; let album = albums.first(); if let Some(album) = album { images.append(&mut album.images.clone()) } else { return Err(Error::from(JDbError::NotFound)); } } else { for album in motivation.album { let album = picox.get_album_by_id(album).await; if let Ok(album) = album { let mut album_images = album.images.clone(); images.append(&mut album_images); } } } let image = images .choose(&mut thread_rng()) .ok_or(Error::NoAlbumFound)?; let action = motivation.action.iter().choose(&mut thread_rng()).unwrap(); let goal = motivation.goal.iter().choose(&mut thread_rng()).unwrap(); let image = picox.get_image_by_id(*image).await.unwrap(); Ok(Motivation { image, action: action.to_string(), goal: goal.to_string(), border_color: border_color.to_string(), }) } } #[derive(Debug, Deserialize, Serialize, Clone)] pub struct Motivation { pub image: Image, pub action: String, pub goal: String, pub border_color: String, }