add improvements system and night market
This commit is contained in:
parent
9f48d91b32
commit
2b5182a876
39
Cargo.lock
generated
39
Cargo.lock
generated
@ -1093,7 +1093,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fren"
|
name = "fren"
|
||||||
version = "2.4.1"
|
version = "2.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum 0.8.1",
|
"axum 0.8.1",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
@ -1118,9 +1118,11 @@ dependencies = [
|
|||||||
"sha3",
|
"sha3",
|
||||||
"songbird",
|
"songbird",
|
||||||
"structopt",
|
"structopt",
|
||||||
|
"strum 0.27.2",
|
||||||
"symphonia",
|
"symphonia",
|
||||||
"tera",
|
"tera",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
|
"thousands",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
@ -1464,7 +1466,7 @@ dependencies = [
|
|||||||
"hex",
|
"hex",
|
||||||
"shorthand",
|
"shorthand",
|
||||||
"stable-vec",
|
"stable-vec",
|
||||||
"strum",
|
"strum 0.17.1",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1998,7 +2000,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3881,7 +3883,16 @@ version = "0.17.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "530efb820d53b712f4e347916c5e7ed20deb76a4f0457943b3182fb889b06d2c"
|
checksum = "530efb820d53b712f4e347916c5e7ed20deb76a4f0457943b3182fb889b06d2c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"strum_macros",
|
"strum_macros 0.17.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf"
|
||||||
|
dependencies = [
|
||||||
|
"strum_macros 0.27.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3896,6 +3907,18 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.5.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
@ -4228,6 +4251,12 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thousands"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.8"
|
version = "1.1.8"
|
||||||
@ -5147,7 +5176,7 @@ version = "0.1.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fren"
|
name = "fren"
|
||||||
version = "2.4.1"
|
version = "2.5.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@ -33,6 +33,8 @@ log = "0.4.26"
|
|||||||
cta-api = { version = "0.5.0", registry = "ahines"}
|
cta-api = { version = "0.5.0", registry = "ahines"}
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
tracing-core = "0.1.33"
|
tracing-core = "0.1.33"
|
||||||
|
strum = { version = "0.27.2", features = ["derive"] }
|
||||||
|
thousands = "0.2.0"
|
||||||
|
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1.35.1"
|
version = "1.35.1"
|
||||||
|
|||||||
73
src/discord/improvements.rs
Normal file
73
src/discord/improvements.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use crate::discord::Context;
|
||||||
|
use crate::error::Error;
|
||||||
|
use crate::models::improvements::{ImprovementType, Improvements};
|
||||||
|
use crate::user::User;
|
||||||
|
use poise::serenity_prelude::MessageBuilder;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
use thousands::Separable;
|
||||||
|
|
||||||
|
/// List out all the improvements available for the bot
|
||||||
|
#[poise::command(prefix_command, guild_only, category = "Improvements")]
|
||||||
|
pub async fn improvements(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
|
let mut msg_builder = MessageBuilder::new();
|
||||||
|
|
||||||
|
msg_builder.push_line("# Fren Bot Improvements");
|
||||||
|
msg_builder.push_line("Anything can be improved with enough Fren Coins!");
|
||||||
|
msg_builder.push_line("");
|
||||||
|
|
||||||
|
for improvement_type in ImprovementType::iter() {
|
||||||
|
msg_builder.push("* ");
|
||||||
|
if let Some(improvement) = Improvements::get_improvement(&ctx.data().db, improvement_type)?
|
||||||
|
{
|
||||||
|
if improvement_type.has_levels() {
|
||||||
|
msg_builder.push(format!(" (✅ Level={}) ", improvement.level));
|
||||||
|
} else {
|
||||||
|
msg_builder.push(" (✅) ");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg_builder.push(format!(
|
||||||
|
"({} FC) ",
|
||||||
|
improvement_type.price().separate_with_commas()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_builder.push_line(format!(
|
||||||
|
"**{}**: {}",
|
||||||
|
improvement_type.name(),
|
||||||
|
improvement_type.description()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.reply(msg_builder.build()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Buy an improvement for the bot!
|
||||||
|
#[poise::command(prefix_command, guild_only, category = "Improvements")]
|
||||||
|
pub async fn buy_improvement(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "Improvement to buy"]
|
||||||
|
#[rest]
|
||||||
|
improvement_type: ImprovementType,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
if Improvements::get_improvement(&ctx.data().db, improvement_type)?.is_some()
|
||||||
|
&& !improvement_type.has_levels()
|
||||||
|
{
|
||||||
|
ctx.reply("Sorry, that improvement has already been purchased.")
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
User::try_take_funds(
|
||||||
|
&ctx.data().db,
|
||||||
|
ctx.author().id,
|
||||||
|
improvement_type.price() as u32,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Improvements::increment_improvement(&ctx.data().db, improvement_type)?;
|
||||||
|
|
||||||
|
ctx.reply(improvement_type.post_buy_description()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ mod color;
|
|||||||
mod emoji_race;
|
mod emoji_race;
|
||||||
mod fren_coin;
|
mod fren_coin;
|
||||||
mod image;
|
mod image;
|
||||||
|
pub mod improvements;
|
||||||
mod joke;
|
mod joke;
|
||||||
mod little_fren;
|
mod little_fren;
|
||||||
mod movie;
|
mod movie;
|
||||||
@ -356,6 +357,8 @@ pub async fn run_bot(global_data: GlobalData) {
|
|||||||
image::green_screen(),
|
image::green_screen(),
|
||||||
image::overlay(),
|
image::overlay(),
|
||||||
image::edit_img(),
|
image::edit_img(),
|
||||||
|
improvements::improvements(),
|
||||||
|
improvements::buy_improvement(),
|
||||||
movie::add_movie(),
|
movie::add_movie(),
|
||||||
movie::list_movies(),
|
movie::list_movies(),
|
||||||
movie::rate_movie(),
|
movie::rate_movie(),
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use crate::discord::voices::VoiceError;
|
use crate::discord::voices::VoiceError;
|
||||||
use crate::image_manipulation::ModifyImageArgError;
|
use crate::image_manipulation::ModifyImageArgError;
|
||||||
use crate::models::gogurt_reserves::GogurtError;
|
use crate::models::gogurt_reserves::GogurtError;
|
||||||
|
use crate::models::improvements::ImprovementError;
|
||||||
use crate::user;
|
use crate::user;
|
||||||
use magick_rust::MagickError;
|
use magick_rust::MagickError;
|
||||||
use serde::ser::StdError;
|
use serde::ser::StdError;
|
||||||
@ -28,6 +29,7 @@ pub enum Error {
|
|||||||
PipelineArgumentError(ModifyImageArgError),
|
PipelineArgumentError(ModifyImageArgError),
|
||||||
NoRandomFound,
|
NoRandomFound,
|
||||||
GogurtError(GogurtError),
|
GogurtError(GogurtError),
|
||||||
|
ImprovementError(ImprovementError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdError for Error {}
|
impl StdError for Error {}
|
||||||
@ -104,6 +106,12 @@ impl From<GogurtError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ImprovementError> for Error {
|
||||||
|
fn from(value: ImprovementError) -> Self {
|
||||||
|
Self::ImprovementError(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -125,6 +133,7 @@ impl Display for Error {
|
|||||||
Error::PipelineArgumentError(err) => write!(f, "{err}"),
|
Error::PipelineArgumentError(err) => write!(f, "{err}"),
|
||||||
Error::NoRandomFound => write!(f, "No random found"),
|
Error::NoRandomFound => write!(f, "No random found"),
|
||||||
Error::GogurtError(err) => write!(f, "{err}"),
|
Error::GogurtError(err) => write!(f, "{err}"),
|
||||||
|
Error::ImprovementError(err) => write!(f, "{err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::config::GlobalData;
|
use crate::config::GlobalData;
|
||||||
|
use crate::discord::get_role;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::inventory::{ItemData, ItemType};
|
use crate::inventory::{ItemData, ItemType};
|
||||||
use crate::user::{User, UserRole};
|
use crate::user::{User, UserRole};
|
||||||
@ -12,7 +13,6 @@ use rand::{Rng, rng};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use crate::discord::get_role;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
@ -245,10 +245,17 @@ impl Listener {
|
|||||||
}
|
}
|
||||||
Action::Ghoulify { hours } => {
|
Action::Ghoulify { hours } => {
|
||||||
// slight hack to prevent ghoul spamming
|
// slight hack to prevent ghoul spamming
|
||||||
let ghoul_role = get_role(&ctx.http, data.cfg.guild_id, &UserRole::Ghoul.to_string()).await?;
|
let ghoul_role =
|
||||||
if let Ok(user) = data.cfg.guild_id.member(&ctx.http(), trigger_event.triggerer).await
|
get_role(&ctx.http, data.cfg.guild_id, &UserRole::Ghoul.to_string())
|
||||||
|
.await?;
|
||||||
|
if let Ok(user) = data
|
||||||
|
.cfg
|
||||||
|
.guild_id
|
||||||
|
.member(&ctx.http(), trigger_event.triggerer)
|
||||||
|
.await
|
||||||
&& let Some(ghoul_role) = ghoul_role
|
&& let Some(ghoul_role) = ghoul_role
|
||||||
&& user.roles.contains(&ghoul_role) {
|
&& user.roles.contains(&ghoul_role)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
use crate::models::improvements::{ImprovementType, Improvements};
|
||||||
use crate::user::User;
|
use crate::user::User;
|
||||||
use chrono::{DateTime, NaiveTime, TimeZone, Utc};
|
use chrono::{DateTime, Days, NaiveTime, TimeZone, Utc};
|
||||||
use j_db::database::Database;
|
use j_db::database::Database;
|
||||||
use log::info;
|
use log::info;
|
||||||
use poise::serenity_prelude::UserId;
|
use poise::serenity_prelude::UserId;
|
||||||
@ -13,13 +14,13 @@ const OPENING_HOUR: u32 = 7;
|
|||||||
const UPDATE_HOUR: u32 = 12;
|
const UPDATE_HOUR: u32 = 12;
|
||||||
const CLOSING_HOUR: u32 = 18;
|
const CLOSING_HOUR: u32 = 18;
|
||||||
|
|
||||||
|
const NIGHT_MARKET_CLOSE: u32 = 23;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum GogurtError {
|
pub enum GogurtError {
|
||||||
#[error("Wow, you really don't have enough gogurt. What are you 12?? Just got buy some poor.")]
|
#[error("Wow, you really don't have enough gogurt. What are you 12?? Just got buy some poor.")]
|
||||||
NotEnoughGogurt,
|
NotEnoughGogurt,
|
||||||
#[error(
|
#[error("Sorry, gogurt can only be bought and sold when the market is open!")]
|
||||||
"Sorry, gogurt can only be bought and sold between the hours of 7AM to 6PM Naperville Time."
|
|
||||||
)]
|
|
||||||
OutsideOfGogurtTradingHours,
|
OutsideOfGogurtTradingHours,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,27 +53,79 @@ impl GogurtReserves {
|
|||||||
.unwrap_or(Self::default()))
|
.unwrap_or(Self::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn market_time(time: u32) -> NaiveTime {
|
||||||
|
NaiveTime::from_hms_opt(time, 0, 0).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn market_opening_time() -> NaiveTime {
|
pub fn market_opening_time() -> NaiveTime {
|
||||||
NaiveTime::from_hms_opt(OPENING_HOUR, 0, 0).unwrap()
|
Self::market_time(OPENING_HOUR)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn market_update_time() -> NaiveTime {
|
pub fn market_update_time() -> NaiveTime {
|
||||||
NaiveTime::from_hms_opt(UPDATE_HOUR, 0, 0).unwrap()
|
Self::market_time(UPDATE_HOUR)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn market_closing_time() -> NaiveTime {
|
pub fn normal_market_closing_time() -> NaiveTime {
|
||||||
NaiveTime::from_hms_opt(CLOSING_HOUR, 0, 0).unwrap()
|
Self::market_time(CLOSING_HOUR)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_if_in_trading_hours(time: &DateTime<Utc>) -> bool {
|
pub fn night_market_closing_time() -> NaiveTime {
|
||||||
|
Self::market_time(NIGHT_MARKET_CLOSE)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn market_closing_time(db: &Database) -> Result<NaiveTime, Error> {
|
||||||
|
let closing_time = if Self::has_night_market(db)? {
|
||||||
|
Self::night_market_closing_time()
|
||||||
|
} else {
|
||||||
|
Self::normal_market_closing_time()
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(closing_time)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_night_market(db: &Database) -> Result<bool, Error> {
|
||||||
|
Ok(Improvements::get_improvement(db, ImprovementType::GogurtNightMarket)?.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_next_market_update_time(db: &Database) -> Result<DateTime<Utc>, Error> {
|
||||||
|
let chicago_time = chrono_tz::America::Chicago.from_utc_datetime(&Utc::now().naive_utc());
|
||||||
|
|
||||||
|
let mut update_times = vec![Self::market_opening_time(), Self::market_update_time()];
|
||||||
|
|
||||||
|
if Self::has_night_market(db)? {
|
||||||
|
update_times.push(Self::normal_market_closing_time())
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_update_of_the_day = *update_times.last().unwrap();
|
||||||
|
let next_check = if chicago_time.time() > last_update_of_the_day {
|
||||||
|
chicago_time
|
||||||
|
.with_time(update_times[0])
|
||||||
|
.unwrap()
|
||||||
|
.checked_add_days(Days::new(1))
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
let time = update_times
|
||||||
|
.into_iter()
|
||||||
|
.find(|t| &chicago_time.time() < t)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
chicago_time.with_time(time).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let next_check = next_check.with_timezone(&Utc);
|
||||||
|
|
||||||
|
Ok(next_check)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_if_in_trading_hours(db: &Database, time: &DateTime<Utc>) -> Result<bool, Error> {
|
||||||
let chicago_time = chrono_tz::America::Chicago.from_utc_datetime(&time.naive_utc());
|
let chicago_time = chrono_tz::America::Chicago.from_utc_datetime(&time.naive_utc());
|
||||||
|
|
||||||
chicago_time.time() >= Self::market_opening_time()
|
Ok(chicago_time.time() >= Self::market_opening_time()
|
||||||
&& chicago_time.time() < Self::market_closing_time()
|
&& chicago_time.time() < Self::market_closing_time(db)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_contribution(db: &Database, user: UserId, fc_amount: u64) -> Result<f64, Error> {
|
pub fn add_contribution(db: &Database, user: UserId, fc_amount: u64) -> Result<f64, Error> {
|
||||||
if !Self::check_if_in_trading_hours(&Utc::now()) {
|
if !Self::check_if_in_trading_hours(db, &Utc::now())? {
|
||||||
return Err(GogurtError::OutsideOfGogurtTradingHours.into());
|
return Err(GogurtError::OutsideOfGogurtTradingHours.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +150,7 @@ impl GogurtReserves {
|
|||||||
user: UserId,
|
user: UserId,
|
||||||
pounds_of_gogurt: f64,
|
pounds_of_gogurt: f64,
|
||||||
) -> Result<u64, Error> {
|
) -> Result<u64, Error> {
|
||||||
if !Self::check_if_in_trading_hours(&Utc::now()) {
|
if !Self::check_if_in_trading_hours(db, &Utc::now())? {
|
||||||
return Err(GogurtError::OutsideOfGogurtTradingHours.into());
|
return Err(GogurtError::OutsideOfGogurtTradingHours.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
140
src/models/improvements.rs
Normal file
140
src/models/improvements.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use crate::error::Error;
|
||||||
|
use j_db::database::Database;
|
||||||
|
use j_db::model::JdbModel;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use strum::EnumIter;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ImprovementError {
|
||||||
|
UnknownImprovement,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ImprovementError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ImprovementError::UnknownImprovement => write!(
|
||||||
|
f,
|
||||||
|
"I don't know what that improvement is, sounds lame and cringe!"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for ImprovementError {}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, Hash, Eq, PartialEq, Copy, EnumIter)]
|
||||||
|
pub enum ImprovementType {
|
||||||
|
GogurtNightMarket,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImprovementType {
|
||||||
|
pub fn description(&self) -> String {
|
||||||
|
match self {
|
||||||
|
ImprovementType::GogurtNightMarket => {
|
||||||
|
"Keep the Gogurt Market open until 11 PM NST".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn price(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
ImprovementType::GogurtNightMarket => 200_000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_levels(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> String {
|
||||||
|
match self {
|
||||||
|
ImprovementType::GogurtNightMarket => "Gogurt Night Market".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn post_buy_description(&self) -> String {
|
||||||
|
match self {
|
||||||
|
ImprovementType::GogurtNightMarket => "Congrats on investing in the night market. The first day of night trading will start tomorrow!".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for ImprovementType {
|
||||||
|
type Err = ImprovementError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let name = s.to_lowercase();
|
||||||
|
|
||||||
|
match name.as_str() {
|
||||||
|
"gogurt night market" => Ok(Self::GogurtNightMarket),
|
||||||
|
_ => Err(ImprovementError::UnknownImprovement),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
|
||||||
|
pub struct Improvement {
|
||||||
|
pub level: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||||
|
pub struct Improvements {
|
||||||
|
id: Option<u64>,
|
||||||
|
pub improvements: HashMap<ImprovementType, Improvement>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Improvements {
|
||||||
|
pub fn get_improvement_config(db: &Database) -> Result<Self, Error> {
|
||||||
|
Ok(db.filter(|_, _: &Self| true)?.next().unwrap_or(Self {
|
||||||
|
id: None,
|
||||||
|
improvements: HashMap::new(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_improvement(
|
||||||
|
db: &Database,
|
||||||
|
improvement_type: ImprovementType,
|
||||||
|
) -> Result<Option<Improvement>, Error> {
|
||||||
|
let improvements = Self::get_improvement_config(db)?;
|
||||||
|
|
||||||
|
Ok(improvements.improvements.get(&improvement_type).cloned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn increment_improvement(
|
||||||
|
db: &Database,
|
||||||
|
improvement_type: ImprovementType,
|
||||||
|
) -> Result<u32, Error> {
|
||||||
|
let mut improvements = Self::get_improvement_config(db)?;
|
||||||
|
|
||||||
|
let entry = improvements
|
||||||
|
.improvements
|
||||||
|
.entry(improvement_type)
|
||||||
|
.or_insert(Improvement { level: 1 })
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
db.insert(improvements)?;
|
||||||
|
|
||||||
|
Ok(entry.level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JdbModel for Improvements {
|
||||||
|
fn id(&self) -> Option<u64> {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_id(&mut self, id: u64) {
|
||||||
|
self.id = Some(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree() -> String {
|
||||||
|
"Improvements".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_unique(&self, _: &Self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
pub mod api_key;
|
pub mod api_key;
|
||||||
pub mod birthday;
|
pub mod birthday;
|
||||||
pub mod gogurt_reserves;
|
pub mod gogurt_reserves;
|
||||||
|
pub mod improvements;
|
||||||
pub mod insult_compliment;
|
pub mod insult_compliment;
|
||||||
pub mod lil_fren;
|
pub mod lil_fren;
|
||||||
pub mod managed_roles;
|
pub mod managed_roles;
|
||||||
|
|||||||
@ -201,26 +201,11 @@ impl Task {
|
|||||||
}
|
}
|
||||||
TaskType::UpdateGogurtRate => {
|
TaskType::UpdateGogurtRate => {
|
||||||
GogurtReserves::update_rate(&data.db)?;
|
GogurtReserves::update_rate(&data.db)?;
|
||||||
|
Task::add_task(
|
||||||
let chicago_time =
|
&data.db,
|
||||||
chrono_tz::America::Chicago.from_utc_datetime(&Utc::now().naive_utc());
|
TaskType::UpdateGogurtRate,
|
||||||
|
GogurtReserves::get_next_market_update_time(&data.db)?,
|
||||||
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)
|
|
||||||
.unwrap()
|
|
||||||
.checked_add_days(Days::new(1))
|
|
||||||
.unwrap()
|
|
||||||
} else {
|
|
||||||
chicago_time.with_time(midday_update_time).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let next_check = next_check.with_timezone(&Utc);
|
|
||||||
|
|
||||||
Task::add_task(&data.db, TaskType::UpdateGogurtRate, next_check)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user