360 lines
13 KiB
Rust
360 lines
13 KiB
Rust
use crate::config::GlobalData;
|
|
use crate::error::Error;
|
|
use j_db::database::Database;
|
|
use j_db::model::JdbModel;
|
|
use rand::distributions::{Distribution, Standard};
|
|
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_frankenstein(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::alembic:");
|
|
msg.emoji(emoji);
|
|
msg.push_line(":microscope::test_tube:");
|
|
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_magic(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::tophat:");
|
|
msg.emoji(emoji);
|
|
msg.push_line(":magic_wand::rabbit2:");
|
|
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
|
|
|
|
msg.build()
|
|
}
|
|
|
|
pub fn draw_resonance_cascade(emoji: &Emoji) -> String {
|
|
let mut msg = MessageBuilder::new();
|
|
|
|
msg.push_line(":blue_square::blue_square::orange_square::blue_square::blue_square:");
|
|
msg.push_line(":yellow_circle::zap::black_large_square::zap::yellow_circle:");
|
|
msg.push_line(":blue_square::blue_square::zap::blue_square::blue_square:");
|
|
msg.push(":blue_square::gun:");
|
|
msg.emoji(emoji);
|
|
msg.push_line(":gem::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_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_mining(emoji: &Emoji) -> String {
|
|
let mut msg = MessageBuilder::new();
|
|
|
|
msg.push_line(":black_medium_square::black_medium_square::black_medium_square::black_medium_square::black_medium_square:");
|
|
msg.push_line(":black_medium_square::black_medium_square::black_medium_square::black_medium_square::black_medium_square:");
|
|
msg.push_line(":black_medium_square::black_medium_square::black_medium_square::black_medium_square::black_medium_square:");
|
|
msg.push(":black_medium_square::pick:");
|
|
msg.emoji(emoji);
|
|
msg.push_line(":gem::black_medium_square:");
|
|
msg.push_line(":brown_square::brown_square::brown_square::brown_square::brown_square:");
|
|
|
|
msg.build()
|
|
}
|
|
|
|
pub fn draw_gone() -> 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::blue_square::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,
|
|
Magic,
|
|
AttemptingToCircumventDeath,
|
|
AttemptingToNotCauseAResonanceCascade,
|
|
Mining,
|
|
PhasedIntoYourReality,
|
|
}
|
|
|
|
impl Distribution<LilFrenState> for Standard {
|
|
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> LilFrenState {
|
|
match rng.gen_range(0..10) {
|
|
0 => LilFrenState::Standing,
|
|
1 => LilFrenState::TaxFraud,
|
|
2 => LilFrenState::Sick,
|
|
3 => LilFrenState::Dancing,
|
|
4 => LilFrenState::Sleep,
|
|
5 => LilFrenState::Magic,
|
|
6 => LilFrenState::AttemptingToCircumventDeath,
|
|
7 => LilFrenState::AttemptingToNotCauseAResonanceCascade,
|
|
8 => LilFrenState::Mining,
|
|
_ => LilFrenState::PhasedIntoYourReality,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialOrd, PartialEq)]
|
|
pub enum AliveState {
|
|
Alive,
|
|
DiedOfBoredom,
|
|
DiedOfHunger,
|
|
DiedOfThirst,
|
|
}
|
|
|
|
#[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.0..0.5),
|
|
metabolism: thread_rng().gen_range(0.2..0.75),
|
|
}
|
|
}
|
|
|
|
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)? {
|
|
if lil_fren.is_alive() != AliveState::Alive {
|
|
return Ok(());
|
|
}
|
|
|
|
let (hunger_diff, thirst_diff, entertainment_diff) = match lil_fren.state {
|
|
LilFrenState::Standing => (-0.002, -0.002, -0.001),
|
|
LilFrenState::TaxFraud => (-0.002, -0.002, 0.001),
|
|
LilFrenState::Sick => (-0.005, -0.005, -0.001),
|
|
LilFrenState::Dancing => (-0.005, -0.008, 0.01),
|
|
LilFrenState::Sleep => (-0.001, -0.002, 0.00),
|
|
LilFrenState::Magic => (-0.002, -0.002, 0.001),
|
|
LilFrenState::AttemptingToCircumventDeath => (-0.002, -0.002, 0.001),
|
|
LilFrenState::AttemptingToNotCauseAResonanceCascade => (-0.004, -0.004, 0.004),
|
|
LilFrenState::Mining => (-0.006, -0.006, 0.001),
|
|
LilFrenState::PhasedIntoYourReality => (0.0, 0.0, 0.0),
|
|
};
|
|
|
|
lil_fren.hunger = (lil_fren.hunger + hunger_diff * self.metabolism).clamp(-1.0, 1.0);
|
|
lil_fren.thirst = (lil_fren.thirst + thirst_diff * self.metabolism).clamp(-1.0, 1.0);
|
|
lil_fren.thirst =
|
|
(lil_fren.entertainment + entertainment_diff * self.smarts).clamp(-1.0, 1.0);
|
|
|
|
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),
|
|
LilFrenState::Magic => draw_magic(emoji),
|
|
LilFrenState::AttemptingToCircumventDeath => draw_frankenstein(emoji),
|
|
LilFrenState::AttemptingToNotCauseAResonanceCascade => draw_resonance_cascade(emoji),
|
|
LilFrenState::Mining => draw_mining(emoji),
|
|
LilFrenState::PhasedIntoYourReality => draw_gone(),
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|