FrenBot/src/models/lil_fren.rs
2023-07-07 19:47:03 -06:00

268 lines
8.6 KiB
Rust

use crate::config::GlobalData;
use crate::error::Error;
use j_db::database::Database;
use j_db::model::JdbModel;
use rand::distributions::Standard;
use rand::prelude::Distribution;
use rand::{thread_rng, Rng};
use serde::{Deserialize, Serialize};
use serenity::model::guild::Emoji;
use serenity::model::id::{EmojiId, GuildId};
use serenity::prelude::Context;
use serenity::utils::MessageBuilder;
use std::time::Duration;
pub fn draw_standing(emoji: &Emoji) -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push(":blue_square::blue_square:");
msg.emoji(emoji);
msg.push_line(":blue_square::blue_square:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
pub fn draw_dancing(emoji: &Emoji) -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::notes::blue_square:");
msg.push_line(":blue_square::notes::blue_square::notes::blue_square:");
msg.push(":blue_square::blue_square:");
msg.emoji(emoji);
msg.push_line(":blue_square::blue_square:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
pub fn draw_tax_fraud(emoji: &Emoji) -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push(":blue_square::page_with_curl:");
msg.emoji(emoji);
msg.push_line(":blue_square::blue_square:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
pub fn draw_sick(emoji: &Emoji) -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push(":blue_square::bucket:");
msg.emoji(emoji);
msg.push_line(":roll_of_paper::blue_square:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
pub fn draw_sleep(emoji: &Emoji) -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push(":blue_square::blue_square:");
msg.emoji(emoji);
msg.push_line(":blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::bed::blue_square::blue_square:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
pub fn draw_dead() -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::headstone::blue_square::blue_square:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
pub fn draw_feed(emoji: &Emoji, food: &str) -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push(":blue_square::blue_square:");
msg.emoji(emoji);
msg.push(food);
msg.push_line(":blue_square:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialOrd, PartialEq)]
pub enum LilFrenState {
Standing,
TaxFraud,
Sick,
Dancing,
Sleep,
}
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum AliveState {
Alive,
DiedOfBoredom,
DiedOfHunger,
DiedOfThirst,
}
impl Distribution<LilFrenState> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> LilFrenState {
match rng.gen_range(0..100) {
0..=30 => LilFrenState::Standing,
31..=40 => LilFrenState::TaxFraud,
41..=50 => LilFrenState::Sick,
51..=70 => LilFrenState::Dancing,
_ => LilFrenState::Sleep,
}
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct LilFren {
id: Option<u64>,
pub emoji: EmojiId,
pub hunger: f32,
pub thirst: f32,
pub entertainment: f32,
pub state: LilFrenState,
pub smarts: f32,
pub metabolism: f32,
}
impl JdbModel for LilFren {
fn id(&self) -> Option<u64> {
self.id
}
fn set_id(&mut self, id: u64) {
self.id = Some(id)
}
fn tree() -> String {
"LilFren".to_string()
}
}
impl LilFren {
pub fn new(emoji: EmojiId) -> Self {
Self {
id: None,
emoji,
hunger: 1.0,
thirst: 1.0,
entertainment: 1.0,
state: LilFrenState::Standing,
smarts: thread_rng().gen_range(0.1..1.0),
metabolism: thread_rng().gen_range(0.1..1.0),
}
}
pub fn create_new_lil_fren(db: &Database, emoji: EmojiId) -> Result<Self, Error> {
let lil_fren: Option<Self> = Self::get_lil_fren(db)?;
if let Some(lil_fren) = lil_fren {
db.remove::<LilFren>(lil_fren.id().unwrap())?;
}
let lil_fren = db.insert(Self::new(emoji))?;
Ok(lil_fren)
}
pub fn get_lil_fren(db: &Database) -> Result<Option<Self>, Error> {
Ok(db.filter(|_, _fren: &Self| true)?.next())
}
pub fn update_fren(&mut self, db: &Database) -> Result<(), Error> {
if let Some(mut lil_fren) = Self::get_lil_fren(db)? {
let (hunger_diff, thirst_diff, entertainment_diff) = match lil_fren.state {
LilFrenState::Standing => (-0.01, -0.02, -0.01),
LilFrenState::TaxFraud => (-0.01, -0.02, 0.01),
LilFrenState::Sick => (-0.1, -0.15, -0.01),
LilFrenState::Dancing => (-0.05, -0.8, 0.05),
LilFrenState::Sleep => (-0.005, -0.01, 0.00),
};
lil_fren.hunger -= hunger_diff * self.metabolism;
lil_fren.thirst -= thirst_diff * self.metabolism;
lil_fren.entertainment -= entertainment_diff * self.smarts;
if thread_rng().gen_bool(0.75) {
println!("fren is now {:?}", self.state);
lil_fren.state = thread_rng().gen();
}
db.insert(lil_fren)?;
}
Ok(())
}
pub fn is_alive(&self) -> AliveState {
if self.thirst < 0.0 {
AliveState::DiedOfThirst
} else if self.entertainment < 0.0 {
AliveState::DiedOfBoredom
} else if self.hunger < 0.0 {
AliveState::DiedOfHunger
} else {
AliveState::Alive
}
}
fn draw_activity(&self, emoji: &Emoji) -> String {
match self.state {
LilFrenState::Standing => draw_standing(emoji),
LilFrenState::TaxFraud => draw_tax_fraud(emoji),
LilFrenState::Sick => draw_sick(emoji),
LilFrenState::Dancing => draw_dancing(emoji),
LilFrenState::Sleep => draw_sleep(emoji),
}
}
pub async fn draw(&self, ctx: &Context, guild: &GuildId) -> String {
let emoji = guild.emoji(&ctx.http, self.emoji).await.unwrap();
let alive_state = self.is_alive();
if let AliveState::Alive = alive_state {
self.draw_activity(&emoji)
} else {
draw_dead()
}
}
}
pub async fn lil_fren_task(ctx: &Context) {
tokio::time::sleep(Duration::from_secs(60)).await;
let data = ctx.data.read().await;
let global_data = data.get::<GlobalData>().unwrap();
let fren = LilFren::get_lil_fren(&global_data.db).unwrap();
if let Some(mut fren) = fren {
fren.update_fren(&global_data.db).unwrap();
}
}