Add back in race commands
This commit is contained in:
7 files changed
+290
-302
No files matched your search
@@ -3,5 +3,6 @@ pub mod birthday;
|
||||
pub mod insult_compliment;
|
||||
pub mod lil_fren;
|
||||
pub mod motivation;
|
||||
pub mod race;
|
||||
pub mod random;
|
||||
pub mod task;
|
||||
@@ -0,0 +1,203 @@
|
||||
use crate::error::Error;
|
||||
use crate::user::UserError;
|
||||
use j_db::database::Database;
|
||||
use j_db::error::JDbError;
|
||||
use j_db::model::JdbModel;
|
||||
use poise::serenity_prelude::{Emoji, EmojiId, MessageBuilder, UserId};
|
||||
use rand::{rng, Rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub const RACE_SIZE: usize = 25;
|
||||
const BASE_SPEED: f32 = 0.5;
|
||||
pub const NUMBER_OF_RACERS: usize = 5;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RaceError {
|
||||
RacerNotFound,
|
||||
BetFundError(UserError),
|
||||
UserHasBet,
|
||||
GenericError(Error),
|
||||
}
|
||||
|
||||
impl Display for RaceError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
RaceError::RacerNotFound => write!(f, "Racer not found"),
|
||||
RaceError::BetFundError(e) => write!(f, "Fund error: {}", e),
|
||||
RaceError::UserHasBet => write!(f, "User already bet"),
|
||||
RaceError::GenericError(e) => write!(f, "Sorry the horse died: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UserError> for RaceError {
|
||||
fn from(value: UserError) -> Self {
|
||||
Self::BetFundError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for RaceError {
|
||||
fn from(value: Error) -> Self {
|
||||
Self::GenericError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for RaceError {}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Bet {
|
||||
id: Option<u64>,
|
||||
pub emoji: EmojiId,
|
||||
pub amount: u32,
|
||||
pub author: UserId,
|
||||
}
|
||||
|
||||
impl JdbModel for Bet {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"Bet".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Bet {
|
||||
pub fn new(emoji: EmojiId, amount: u32, author: UserId) -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
emoji,
|
||||
amount,
|
||||
author,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_bet(db: &Database, bet: Self) -> Result<Self, Error> {
|
||||
Ok(db.insert(bet)?)
|
||||
}
|
||||
|
||||
pub fn get_bets(db: &Database) -> Result<Vec<Self>, Error> {
|
||||
Ok(db.filter(|_, _bet: &Self| true)?.collect())
|
||||
}
|
||||
|
||||
pub fn clear_bet(db: &Database) -> Result<(), Error> {
|
||||
let bets = Self::get_bets(db)?;
|
||||
|
||||
for bet in &bets {
|
||||
db.remove::<Self>(bet.id().unwrap())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn has_user_bet(db: &Database, user: UserId) -> Result<bool, Error> {
|
||||
Ok(db
|
||||
.filter(|_, bet: &Self| bet.author == user)?
|
||||
.next()
|
||||
.is_some())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Racer {
|
||||
id: Option<u64>,
|
||||
pub emoji: Emoji,
|
||||
pub speed: f32,
|
||||
pub pos: f32,
|
||||
}
|
||||
|
||||
impl PartialEq<Self> for Racer {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.emoji.id == other.emoji.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Racer {}
|
||||
|
||||
impl Racer {
|
||||
pub fn new(emoji: Emoji) -> Self {
|
||||
let genetic_stat = (emoji.id.get() & 0xff) as f32 / 255.0;
|
||||
let random_stat = rng().random_range(0.0..0.5);
|
||||
let speed = BASE_SPEED + (0.50 * genetic_stat) + (0.50 * random_stat);
|
||||
|
||||
Racer {
|
||||
id: None,
|
||||
emoji,
|
||||
speed,
|
||||
pos: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_pos(&mut self) {
|
||||
let speed_boost = rng().gen_range(-0.75..0.75);
|
||||
self.pos += self.speed + (self.speed * speed_boost);
|
||||
|
||||
self.pos = self.pos.clamp(0.0, RACE_SIZE as f32);
|
||||
}
|
||||
|
||||
pub fn get_race_pos(&self) -> usize {
|
||||
self.pos.floor() as usize
|
||||
}
|
||||
|
||||
pub fn add_racer(db: &Database, emoji: Emoji) -> Result<Self, Error> {
|
||||
let racer = Self::new(emoji);
|
||||
let racer = db.insert(racer)?;
|
||||
Ok(racer)
|
||||
}
|
||||
|
||||
pub fn get_racers(db: &Database) -> Result<Vec<Self>, Error> {
|
||||
Ok(db.filter(|_, _racer: &Self| true)?.collect())
|
||||
}
|
||||
|
||||
pub fn clear_racers(db: &Database) -> Result<(), Error> {
|
||||
let racers = Self::get_racers(db)?;
|
||||
|
||||
for racer in &racers {
|
||||
db.remove::<Self>(racer.id().unwrap())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl JdbModel for Racer {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"Racer".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_race(racers: &Vec<Racer>) -> String {
|
||||
let mut msg = MessageBuilder::default();
|
||||
|
||||
for racer in racers {
|
||||
let mut race_line = MessageBuilder::new();
|
||||
race_line.push("|");
|
||||
race_line.push("=".repeat(racer.get_race_pos()));
|
||||
race_line.push("E");
|
||||
|
||||
if race_line.0.len() < RACE_SIZE {
|
||||
let padding_needed = RACE_SIZE - race_line.0.len() - 1;
|
||||
race_line.push("=".repeat(padding_needed));
|
||||
race_line.push("🔳");
|
||||
}
|
||||
|
||||
let line = race_line.build();
|
||||
let line = line.replace('E', &racer.emoji.to_string());
|
||||
msg.push_line(line);
|
||||
}
|
||||
|
||||
msg.build()
|
||||
}
|
||||
Reference in new issue
Block a user