From 5b4c6b50aeeb9941e64a47b700df3a13d74de130 Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Wed, 6 Aug 2025 19:04:16 -0600 Subject: [PATCH] Update GR to be less op (plz nerf) --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/error.rs | 14 +++-- src/models/gogurt_reserves.rs | 110 +++++++++++++++++++++++++++++----- src/models/task.rs | 20 +++++-- 5 files changed, 120 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d0aeb8..d83adc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1093,7 +1093,7 @@ dependencies = [ [[package]] name = "fren" -version = "2.2.1" +version = "2.3.0" dependencies = [ "axum 0.8.1", "base64 0.22.1", diff --git a/Cargo.toml b/Cargo.toml index f50bba8..e5e0366 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fren" -version = "2.2.1" +version = "2.3.0" edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/error.rs b/src/error.rs index b41f72c..d03d826 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,6 @@ use crate::discord::voices::VoiceError; use crate::image_manipulation::ModifyImageArgError; +use crate::models::gogurt_reserves::GogurtError; use crate::user; use magick_rust::MagickError; use serde::ser::StdError; @@ -26,7 +27,7 @@ pub enum Error { NoImageFound, PipelineArgumentError(ModifyImageArgError), NoRandomFound, - NotEnoughGogurt, + GogurtError(GogurtError), } impl StdError for Error {} @@ -97,6 +98,12 @@ impl From for Error { } } +impl From for Error { + fn from(value: GogurtError) -> Self { + Self::GogurtError(value) + } +} + impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -117,10 +124,7 @@ impl Display for Error { Error::NoImageFound => write!(f, "Image not found"), Error::PipelineArgumentError(err) => write!(f, "{err}"), Error::NoRandomFound => write!(f, "No random found"), - Error::NotEnoughGogurt => write!( - f, - "Wow, you really don't have enough gogurt. What are you 12?? Just got buy some poor." - ), + Error::GogurtError(err) => write!(f, "{err}"), } } } diff --git a/src/models/gogurt_reserves.rs b/src/models/gogurt_reserves.rs index 123b1da..028f866 100644 --- a/src/models/gogurt_reserves.rs +++ b/src/models/gogurt_reserves.rs @@ -1,12 +1,27 @@ use crate::error::Error; use crate::user::User; -use chrono::Utc; +use chrono::{DateTime, NaiveTime, TimeZone, Utc}; use j_db::database::Database; use log::info; use poise::serenity_prelude::UserId; +use rand::{Rng, rng}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use std::f32::consts::PI; +use thiserror::Error; + +const OPENING_HOUR: u32 = 8; +const UPDATE_HOUR: u32 = 12; +const CLOSING_HOUR: u32 = 16; + +#[derive(Debug, Error)] +pub enum GogurtError { + #[error("Wow, you really don't have enough gogurt. What are you 12?? Just got buy some poor.")] + NotEnoughGogurt, + #[error( + "Sorry, gogurt can only be bought and sold between the hours of 8AM to 4PM Naperville Time." + )] + OutsideOfGogurtTradingHours, +} #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct GogurtReserves { @@ -37,7 +52,30 @@ impl GogurtReserves { .unwrap_or(Self::default())) } + pub fn market_opening_time() -> NaiveTime { + NaiveTime::from_hms_opt(OPENING_HOUR, 0, 0).unwrap() + } + + pub fn market_update_time() -> NaiveTime { + NaiveTime::from_hms_opt(UPDATE_HOUR, 0, 0).unwrap() + } + + pub fn market_closing_time() -> NaiveTime { + NaiveTime::from_hms_opt(CLOSING_HOUR, 0, 0).unwrap() + } + + pub fn check_if_in_trading_hours(time: &DateTime) -> bool { + let chicago_time = chrono_tz::America::Chicago.from_utc_datetime(&time.naive_utc()); + + chicago_time.time() >= Self::market_opening_time() + && chicago_time.time() < Self::market_closing_time() + } + pub fn add_contribution(db: &Database, user: UserId, fc_amount: u64) -> Result { + if !Self::check_if_in_trading_hours(&Utc::now()) { + return Err(GogurtError::OutsideOfGogurtTradingHours.into()); + } + let mut gogurt_reserve = Self::get_gogurt_reserve(db)?; let gogurt_amount = gogurt_reserve.convert_fc_to_pounds(fc_amount); @@ -59,6 +97,10 @@ impl GogurtReserves { user: UserId, pounds_of_gogurt: f64, ) -> Result { + if !Self::check_if_in_trading_hours(&Utc::now()) { + return Err(GogurtError::OutsideOfGogurtTradingHours.into()); + } + let mut gogurt_reserve = Self::get_gogurt_reserve(db)?; let contribution = gogurt_reserve .reserve_contributors @@ -72,7 +114,7 @@ impl GogurtReserves { } if pounds_of_gogurt > *contribution { - Err(Error::NotEnoughGogurt) + Err(GogurtError::NotEnoughGogurt.into()) } else { *contribution -= pounds_of_gogurt; let fc_profit = gogurt_reserve.convert_pounds_to_fc(pounds_of_gogurt); @@ -120,24 +162,23 @@ impl GogurtReserves { } } - pub fn market_function(time: i64) -> f64 { - let x = time as f64; - (x.sin() + (PI as f64 * x).cos() + (PI as f64 * x).sin() + x.cos() - - (x * 4.0).sin() - - (x * 3.0).cos()) - .clamp(0.01, 6.0) + pub fn market_function() -> f64 { + match rng().random_range(0..100) { + 0..10 => rng().random_range(8.5..10.0), + 90..98 => rng().random_range(10.0..12.0), + 98..100 => rng().random_range(12.0..14.0), + _ => rng().random_range(9.0..11.0), + } } - pub fn calculate_new_rate(time: i64) -> f64 { - Self::market_function(time) + pub fn calculate_new_rate() -> f64 { + Self::market_function() } pub fn update_rate(db: &Database) -> Result<(), Error> { let mut reserves = Self::get_gogurt_reserve(db)?; - let time = Utc::now().timestamp(); - - let new_rate = Self::calculate_new_rate(time); + let new_rate = Self::calculate_new_rate(); info!("Updating rate to '{new_rate}'"); reserves.gogurt_rate_per_pound = Some(new_rate); @@ -151,13 +192,50 @@ impl GogurtReserves { #[cfg(test)] mod test { use crate::models::gogurt_reserves::GogurtReserves; + use chrono::{DateTime, NaiveTime, TimeZone, Utc}; #[test] fn test_avg_market_function() { - let sum: f64 = (0..100000).map(GogurtReserves::market_function).sum(); + let sum: f64 = (0..100000).map(|_| GogurtReserves::market_function()).sum(); let avg = sum / 100000.0; println!("Average = {avg}"); - assert!(avg < 1.0 && avg > 0.0) + assert!(avg < 11.0 && avg > 9.0) + } + + fn gen_time(hour: u32, min: u32, sec: u32) -> DateTime { + chrono_tz::America::Chicago + .from_utc_datetime(&Utc::now().naive_utc()) + .with_time(NaiveTime::from_hms_opt(hour, min, sec).unwrap()) + .unwrap() + .to_utc() + } + + #[test] + fn test_is_market_open_before_open() { + assert!(!GogurtReserves::check_if_in_trading_hours(&gen_time( + 7, 59, 0 + ))); + } + + #[test] + fn test_is_market_open_after_open() { + assert!(GogurtReserves::check_if_in_trading_hours(&gen_time( + 8, 0, 0 + ))); + } + + #[test] + fn test_is_market_open_before_close() { + assert!(GogurtReserves::check_if_in_trading_hours(&gen_time( + 15, 59, 0 + ))); + } + + #[test] + fn test_is_market_open_after_close() { + assert!(!GogurtReserves::check_if_in_trading_hours(&gen_time( + 16, 0, 0 + ))); } } diff --git a/src/models/task.rs b/src/models/task.rs index 2e374c3..ae5d918 100644 --- a/src/models/task.rs +++ b/src/models/task.rs @@ -202,11 +202,21 @@ impl Task { TaskType::UpdateGogurtRate => { GogurtReserves::update_rate(&data.db)?; - Task::add_task( - &data.db, - TaskType::UpdateGogurtRate, - Utc::now() + Duration::minutes(5), - )?; + let chicago_time = + chrono_tz::America::Chicago.from_utc_datetime(&Utc::now().naive_utc()); + + let market_open_time = GogurtReserves::market_opening_time(); + let midday_update_time = GogurtReserves::market_update_time(); + + let next_check = if chicago_time.time() >= midday_update_time { + chicago_time.with_time(market_open_time) + } else { + chicago_time.with_time(midday_update_time) + }; + + let next_check = next_check.unwrap().with_timezone(&Utc); + + Task::add_task(&data.db, TaskType::UpdateGogurtRate, next_check)?; } }