use crate::database::mysql::SlotsBetRatios;
use crate::des;
use crate::packers::BroadSlotMarquess;
use crate::peer::BonusState;
use crate::robot_service::IRobotService;
use crate::services::LotteryInfo;
use crate::static_def::{get_game_setting, BROADCAST_SERVICE, MASTER_SERVICE};
use anyhow::Result;
use rand::prelude::IteratorRandom;
use rand::Rng;
use std::time::Instant;
#[derive(Default, Debug)]
pub enum RobotState {
#[default]
Start,
Gaming(usize, usize),
Leave,
}
#[derive(Debug)]
pub struct Robot {
pub id: i32,
pub nickname: String,
pub avatar_id: i32,
pub vip_level: i32,
pub bet_info: SlotsBetRatios,
pub seating_time: u32,
pub leave_time: u32,
pub spin_time: u32,
pub last_seating_time: Instant,
pub last_leave_time: Instant,
pub last_spin_time_time: Instant,
pub state: RobotState,
}
impl Robot {
pub async fn update(
&mut self,
rand: &mut rand_chacha::ChaCha20Rng,
lottery: &[LotteryInfo],
robot_service: &impl IRobotService,
) -> Result<()> {
match self.state {
RobotState::Start => {
if rand.random_range(0..2) == 1 {
if let Some((table_id, seat_id)) = robot_service
.robot_seat(self.id, self.nickname.clone(), self.avatar_id)
.await
{
self.last_seating_time = Instant::now();
self.state = RobotState::Gaming(table_id, seat_id);
} else {
self.last_leave_time = Instant::now();
self.state = RobotState::Leave;
}
} else {
self.last_leave_time = Instant::now();
self.state = RobotState::Leave;
}
}
RobotState::Gaming(table_id, seat_id) => {
if self.last_seating_time.elapsed().as_secs() > self.seating_time as u64 {
robot_service.robot_remove_seat(table_id, seat_id).await?;
self.last_leave_time = Instant::now();
self.state = RobotState::Leave;
} else if self.last_spin_time_time.elapsed().as_secs() > self.spin_time as u64 {
self.last_spin_time_time = Instant::now();
let lottery_id = lottery
.iter()
.filter_map(|x| {
if x.bet_or_money == 1 {
Some(x.lottery_id)
} else {
None
}
})
.choose(rand);
if let Some(lottery_id) = lottery_id {
let win = MASTER_SERVICE
.robot_lottery_spin(1, lottery_id, self.bet_info.bet_money)
.await?;
if win > 0 {
log::info!("robot_service win lottery:{lottery_id} money:{win}");
let config = get_game_setting();
if win as f64 >= config.marquee_money_limit
&& (win / self.bet_info.bet_money as i64) as u32
> config.marquee_bet_limit
{
let nickname = self.nickname.clone();
let vip_level = self.vip_level;
let bonus_state = BonusState::Grand as u8;
tokio::spawn(async move {
let send_broad_slot_marquess = async move {
let res = BroadSlotMarquess {
game_id: config.game_id,
nickname: &nickname,
vip_level,
bonus_state,
win,
};
let data = des!(res);
BROADCAST_SERVICE.broadcast_to_all_users(&data).await
};
if let Err(err) = send_broad_slot_marquess.await {
log::error!("send_broad_slot_marquess error:{err}");
}
});
}
}
}
}
}
RobotState::Leave => {
if self.last_leave_time.elapsed().as_secs() >= self.leave_time as u64 {
self.id = rand.random_range(10000000..100000000);
self.nickname = self.id.to_string();
self.avatar_id = rand.random_range(0..10);
if let Some((table_id, seat_id)) = robot_service
.robot_seat(self.id, self.nickname.clone(), self.avatar_id)
.await
{
self.last_seating_time = Instant::now();
self.state = RobotState::Gaming(table_id, seat_id);
} else {
self.last_leave_time = Instant::now();
self.state = RobotState::Leave;
}
}
}
}
Ok(())
}
}