Commit a1fb5c7a authored by 陈冲's avatar 陈冲

feat: 已上榜玩家当天重玩已上榜的游戏不再显示

parent aa23cfba
drop table if exists tb_room;
create table tb_room
(
batch_no VARCHAR(50) PRIMARY KEY, -- 批次
item_num int not null check (item_num between 1 and 6), -- 游戏项目(1到6)
player_count int not null default 0, -- 房间人数
create_date timestamptz -- 创建时间
);
drop table if exists tb_game;
create table tb_game
(
......
DROP TABLE IF EXISTS tb_room;
CREATE TABLE tb_room
(
batch_no VARCHAR(50) PRIMARY KEY,
item_num INT NOT NULL,
player_count INT NOT NULL DEFAULT 0,
create_date DATETIME
);
DROP TABLE IF EXISTS tb_game;
CREATE TABLE tb_game
(
......
......@@ -2,7 +2,7 @@ use crate::{
commons::utils::CONFIG as config,
db::models::{get_i32, get_string, log::Log},
};
use chrono::{DateTime, NaiveDate, Utc};
use chrono::{DateTime, Utc};
use serde_json::json;
pub struct Game {
......@@ -65,16 +65,22 @@ impl Game {
}
}
}
pub async fn get_rank(wechat_id: &str) -> i32 {
pub async fn get_rank(wechat_id: &str, item_num: i32) -> i32 {
let Some(_) = &config.db else {
println!("没有配置数据库, get_rank return 0;");
return 0;
};
let res = crate::db::db_query(
r#"SELECT COUNT(1) AS rank_count FROM tb_game WHERE wechat_id = ?
AND game_rank <= 10"#,
vec![json!(&wechat_id)],
r#"SELECT COUNT(1) AS rank_count
FROM tb_game g
INNER JOIN tb_room r ON r.batch_no = g.batch_no
WHERE g.wechat_id = ?
AND g.item_num = ?
AND r.item_num = ?
AND g.game_rank BETWEEN 1 AND 10
AND DATE(r.create_date) = CURRENT_DATE"#,
vec![json!(&wechat_id), json!(item_num), json!(item_num)],
)
.await;
match res {
......
......@@ -3,6 +3,7 @@ use serde_json::Value;
pub mod game;
pub mod log;
pub mod manager;
pub mod room;
pub fn get_i32(row: &Value, key: &str) -> Result<i32, String> {
row.get(key)
......
use crate::commons::utils::CONFIG as config;
use chrono::{DateTime, Utc};
use serde_json::json;
pub struct GameRoom {
pub batch_no: String,
pub item_num: i32,
pub player_count: i32,
pub create_date: Option<DateTime<Utc>>,
}
impl GameRoom {
pub async fn insert(&self) -> bool {
let Some(_) = &config.db else {
println!("没有配置数据库, room insert return true;");
return true;
};
let res = crate::db::db_query(
r#"insert into tb_room(batch_no,item_num,player_count,create_date) values(?,?,?,now());"#,
vec![
json!(&self.batch_no),
json!(&self.item_num),
json!(&self.player_count),
],
)
.await;
match res {
Ok(_) => true,
Err(err) => {
println!("room insert failed: {err}");
false
}
}
}
}
......@@ -2,6 +2,7 @@ use crate::commons::utils::{self, CONFIG as config};
use crate::db::models::game::Game;
use crate::db::models::log::Log;
use crate::db::models::manager::*;
use crate::db::models::room::GameRoom;
use bytes::Bytes;
use dashmap::DashMap;
use dashmap::mapref::entry::Entry;
......@@ -95,6 +96,7 @@ struct RoomState {
players: HashMap<String, RoomPlayer>, // 玩家列表,key 是 userid
next_entry_order: usize,
current_game_id: Option<String>,
current_item_num: i32,
batch_no: String,
round_started_at: Option<Instant>,
}
......@@ -262,6 +264,8 @@ impl RoomState {
self.players.clear();
self.next_entry_order = 0;
self.current_game_id = None;
self.current_item_num = 0;
self.batch_no.clear();
self.round_started_at = None;
}
}
......@@ -320,6 +324,15 @@ fn valid_user(userid: &str, validuser: &str) -> bool {
}
}
fn parse_item_num(game_id: &str) -> i32 {
game_id
.trim()
.strip_prefix("game")
.unwrap_or_else(|| game_id.trim())
.parse::<i32>()
.unwrap_or(0)
}
fn decode_msgpack(data: &Data<Bytes>) -> Result<Value, rmp_serde::decode::Error> {
rmp_serde::from_slice(data.0.as_ref())
}
......@@ -677,6 +690,7 @@ async fn handle_room_command(
}
state.reset();
state.current_game_id = Some(game_id);
state.current_item_num = index as i32;
state.status = RoomStatus::Loading;
// let snapshot = state.snapshot();
drop(state);
......@@ -712,10 +726,8 @@ async fn handle_room_command(
.and_then(|value| value.as_str())
.unwrap_or("")
.to_string();
let already_top_ranked = CLIENT_TOP_RANKED_MAP
.get(userid)
.map(|value| *value)
.unwrap_or(false);
let already_top_ranked = Game::get_rank(userid, parse_item_num(&gameId)).await > 0;
CLIENT_TOP_RANKED_MAP.insert(userid.to_string(), already_top_ranked);
if let Ok(mut state) = ROOM_STATE.lock() {
// 当前h5进入的不是大屏开启的游戏房间
......@@ -809,7 +821,7 @@ async fn handle_room_command(
return;
}
let game_index = data.as_str().unwrap_or("");
if let Ok(mut state) = ROOM_STATE.lock() {
let start_info = if let Ok(mut state) = ROOM_STATE.lock() {
if state.players.is_empty() {
drop(state);
emit_msgpack(&socket, evt, &err_resp("房间中没有玩家", Some(json!(1))));
......@@ -823,16 +835,46 @@ async fn handle_room_command(
state.status = RoomStatus::Running;
state.current_game_id = Some(game_index.to_string());
if state.current_item_num <= 0 {
state.current_item_num = parse_item_num(game_index);
}
state.round_started_at = Some(Instant::now());
let round_id = GAME_ROUND_ID.fetch_add(1, Ordering::SeqCst) + 1;
// let snapshot = state.snapshot();
let play_len = state.players.len();
let item_num = state.current_item_num;
//每次开始房间时记录当前批次
let batch_no = format!("{}-{}", utils::get_current_timestamp(), play_len);
state.batch_no = batch_no.clone();
drop(state);
Some((round_id, batch_no, item_num, play_len))
//通知所有玩家倒计时60秒,实际上还有3秒倒计时,以前2秒统计结果,所以是65
} else {
None
};
let Some((round_id, batch_no, item_num, play_len)) = start_info else {
return;
};
{
let room = GameRoom {
batch_no: batch_no.clone(),
item_num,
player_count: play_len as i32,
create_date: None,
};
if !room.insert().await {
if let Ok(mut state) = ROOM_STATE.lock() {
if state.batch_no == batch_no {
state.status = RoomStatus::Loading;
state.batch_no.clear();
state.round_started_at = None;
}
}
emit_msgpack(&socket, evt, &err_resp("房间批次保存失败", None));
return;
}
spawn_game_timeout(
round_id,
GAME_START_COUNTDOWN_SECS + GAME_RUNNING_SECS + GAME_RESULT_WAIT_SECS,
......@@ -989,6 +1031,11 @@ async fn handle_room_command(
if game.insert().await {
if !already_top_ranked && (1..=ROOM_SCORE_RANK_LIMIT as i64).contains(&rank) {
CLIENT_TOP_RANKED_MAP.insert(userid.to_string(), true);
if let Ok(mut state) = ROOM_STATE.lock() {
if let Some(player) = state.players.get_mut(userid) {
player.already_top_ranked = true;
}
}
}
let mut payload = json!({
......@@ -1126,8 +1173,7 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
}
}
} else {
let already_top_ranked = Game::get_rank(&userid).await > 0;
CLIENT_TOP_RANKED_MAP.insert(userid.clone(), already_top_ranked);
CLIENT_TOP_RANKED_MAP.insert(userid.clone(), false);
if get_admin_count() == 0 {
match CLIENT_PLAYER_MAP.entry(userid.clone()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment