Skip to content

Commit dfeeb47

Browse files
committed
feat(chatroom): 增加查看自动猜拳分布功能并保存统计数据
1 parent 752aea8 commit dfeeb47

4 files changed

Lines changed: 91 additions & 12 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ ratatui = "0.29.0"
5959
serde_repr = "0.1.12"
6060
serde_path_to_error = "0.1.17"
6161
lru = "0.12"
62+
once_cell = "1.21.3"
6263

6364
[package.metadata.docs.rs]
6465
all-features = true

client/src/commands/handlers/chatroom.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ impl Command for ChatroomCommand {
8282
:q - 退出
8383
:rp - 红包
8484
:bl - 消息屏蔽/过滤
85+
:rw - 查看自动猜拳分布
8586
"#
8687
}
8788
}
@@ -154,6 +155,10 @@ impl ChatroomCommand {
154155
name: ":bl",
155156
desc: "消息屏蔽/过滤",
156157
},
158+
CommandItem {
159+
name: ":rw",
160+
desc: "查看自动猜拳分布",
161+
},
157162
]);
158163

159164
let prompt = format!("{}", "聊天室> ".green().bold());
@@ -188,6 +193,31 @@ impl ChatroomCommand {
188193
println!("{}", self.help().green());
189194
self.context.show_switch_help();
190195
}
196+
":rw" => {
197+
let stats = crate::utils::GESTURE_STATS.lock().unwrap();
198+
let total: u64 = stats.iter().sum();
199+
if total == 0 {
200+
println!("石头: {}, 剪刀: {}, 布: {},总数: 0", stats[0], stats[1], stats[2]);
201+
} else {
202+
let rock_pct = stats[0] as f64 / total as f64 * 100.0;
203+
let scissors_pct = stats[1] as f64 / total as f64 * 100.0;
204+
let paper_pct = stats[2] as f64 / total as f64 * 100.0;
205+
println!(
206+
"{}: {:>5} ({:>6.2}%)\n{}: {:>5} ({:>6.2}%)\n{}: {:>7} ({:>6.2}%)\n{}: {}",
207+
"石头".yellow(),
208+
stats[0],
209+
rock_pct,
210+
"剪刀".yellow(),
211+
stats[1],
212+
scissors_pct,
213+
"布".yellow(),
214+
stats[2],
215+
paper_pct,
216+
"总数".magenta(),
217+
total
218+
);
219+
}
220+
}
191221
cmd if cmd.starts_with(":history") || cmd.starts_with(":h") => {
192222
let parts: Vec<&str> = cmd.split_whitespace().collect();
193223
let page = if parts.len() > 1 {

client/src/commands/handlers/redpacket.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use colored::*;
55
use fishpi_rust::{GestureType, RedPacketMessage, RedPacketType};
66
use std::collections::HashMap;
77
use std::sync::{Arc, Mutex};
8+
use crate::utils::random_gesture;
89

910
pub struct RedpacketCommand {
1011
context: CommandContext,
@@ -66,8 +67,8 @@ impl RedpacketCommand {
6667

6768
// 只提供了红包ID,则随机生成一个手势
6869
let gesture = if args.len() == 1 {
69-
let rand_num = rand::random_range(0..=2);
70-
match rand_num {
70+
// let rand_num = random_gesture();
71+
match random_gesture() {
7172
0 => GestureType::Rock,
7273
1 => GestureType::Scissors,
7374
_ => GestureType::Paper,
@@ -383,7 +384,7 @@ impl RedpacketCommand {
383384
match args.len() {
384385
0 => {
385386
// 不给参数, 积分32 手势随机
386-
let gesture = match rand::random_range(0..=2) {
387+
let gesture = match random_gesture() {
387388
0 => GestureType::Rock,
388389
1 => GestureType::Scissors,
389390
_ => GestureType::Paper,
@@ -408,7 +409,7 @@ impl RedpacketCommand {
408409
1 => {
409410
// 只给了一个参数,手势随机
410411
let money: i32 = args[0].parse().unwrap_or(default_money);
411-
let gesture = match rand::random_range(0..=2) {
412+
let gesture = match random_gesture() {
412413
0 => GestureType::Rock,
413414
1 => GestureType::Scissors,
414415
_ => GestureType::Paper,
@@ -433,7 +434,7 @@ impl RedpacketCommand {
433434
2 => {
434435
// 两个参数,手势随机,第二个参数msg
435436
let money: i32 = args[0].parse().unwrap_or(default_money);
436-
let gesture = match rand::random_range(0..=2) {
437+
let gesture = match random_gesture() {
437438
0 => GestureType::Rock,
438439
1 => GestureType::Scissors,
439440
2 => GestureType::Paper,
@@ -508,13 +509,13 @@ impl RedpacketCommand {
508509
async fn handle_list_command(&self) -> Result<()> {
509510
let cache = self.redpacket_cache.lock().unwrap();
510511
if cache.is_empty() {
511-
println!("{}", "当前没有可领取的红包".yellow());
512+
println!("\r{}", "当前没有可领取的红包".yellow());
512513
} else {
513-
println!("{}", "当前可领取的红包:".bold());
514+
println!("\r{}", "当前可领取的红包:".bold());
514515
for (id, info) in cache.iter().enumerate() {
515516
let type_name = RedPacketType::to_name(&info.1.type_);
516517
println!(
517-
" {}. {} [{}] {} 个, 共 {} 积分, 已领取 {}/{}",
518+
"\r {}. {} [{}] {} 个, 共 {} 积分, 已领取 {}/{}",
518519
id + 1,
519520
info.0.bright_black(),
520521
type_name.red(),
@@ -531,7 +532,7 @@ impl RedpacketCommand {
531532
/// 自动打开红包
532533
async fn handle_auto_open_command(&self) -> Result<()> {
533534
if self.redpacket_cache.lock().unwrap().is_empty() {
534-
println!("{}", "当前没有可领取的红包".yellow());
535+
println!("\r{}", "当前没有可领取的红包".yellow());
535536
return Ok(());
536537
}
537538
let oids: Vec<(String, RedPacketMessage)> = {
@@ -544,7 +545,7 @@ impl RedpacketCommand {
544545
for (id, msg) in oids {
545546
if msg.type_ == RedPacketType::ROCK_PAPER_SCISSORS {
546547
// 随机生成一个手势
547-
let gesture = match rand::random_range(0..=2) {
548+
let gesture = match random_gesture() {
548549
0 => GestureType::Rock,
549550
1 => GestureType::Scissors,
550551
_ => GestureType::Paper,
@@ -576,13 +577,13 @@ impl RedpacketCommand {
576577
let user_name = self.context.auth.get_user_name().await?;
577578
if let Some(got) = info.who.iter().find(|got| got.user_name == user_name) {
578579
println!(
579-
"你领取了 {} 积分 {} / {}",
580+
"\r你领取了 {} 积分 {} / {}",
580581
got.money.to_string().yellow().bold(),
581582
info.info.got.to_string().cyan(),
582583
info.info.count.to_string().cyan()
583584
);
584585
} else {
585-
println!("{}", "红包已领完".yellow());
586+
println!("\r{}", "红包已领完".yellow());
586587
}
587588
}
588589
}

client/src/utils/mod.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,53 @@ pub use auth::AuthService;
55
use chrono::{Local, TimeZone};
66
use colored::*;
77
use regex::Regex;
8+
use std::sync::{Arc, Mutex};
9+
use once_cell::sync::Lazy;
10+
use std::fs;
11+
use std::path::Path;
12+
use serde::{Serialize, Deserialize};
13+
14+
const GESTURE_STATS_FILE: &str = "gesture_stats.json";
15+
16+
#[derive(Serialize, Deserialize)]
17+
struct GestureStats([u64; 3]);
18+
19+
pub fn save_gesture_stats(stats: &[u64; 3]) {
20+
let data = GestureStats(*stats);
21+
if let Ok(json) = serde_json::to_string(&data) {
22+
let _ = fs::write(GESTURE_STATS_FILE, json);
23+
}
24+
}
25+
26+
pub fn load_gesture_stats() -> [u64; 3] {
27+
if Path::new(GESTURE_STATS_FILE).exists() {
28+
if let Ok(json) = fs::read_to_string(GESTURE_STATS_FILE) {
29+
if let Ok(data) = serde_json::from_str::<GestureStats>(&json) {
30+
return data.0;
31+
}
32+
}
33+
}
34+
[0; 3]
35+
}
36+
37+
pub static GESTURE_STATS: Lazy<Arc<Mutex<[u64; 3]>>> = Lazy::new(|| {
38+
Arc::new(Mutex::new(load_gesture_stats()))
39+
});
40+
41+
//随机猜拳
42+
pub fn random_gesture() -> u8 {
43+
let rand_u32: u32 = rand::random();
44+
let rand_f64 = rand_u32 as f64 / 4294967296.0;
45+
let gesture = (rand_f64 * 3.0).floor() as u8;
46+
{
47+
let mut stats = GESTURE_STATS.lock().unwrap();
48+
if (gesture as usize) < 3 {
49+
stats[gesture as usize] += 1;
50+
save_gesture_stats(&*stats);
51+
}
52+
}
53+
gesture
54+
}
855

956
pub fn strip_html_tags(html: &str) -> String {
1057
let re = Regex::new(r"<[^>]+>").unwrap();

0 commit comments

Comments
 (0)