Files
Genarrative/server-rs/crates/module-bark-battle/src/domain.rs
kdletters 1d7ef7e4b6
Some checks are pending
CI / verify (pull_request) Waiting to run
feat: wire bark battle platform loop
2026-05-14 18:20:46 +08:00

163 lines
4.8 KiB
Rust

use serde::{Deserialize, Serialize};
pub const BARK_BATTLE_RULESET_VERSION_V1: &str = "bark-battle-ruleset-v1";
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DifficultyPreset {
Easy,
Normal,
Hard,
}
impl DifficultyPreset {
pub fn ai_preset_key(self) -> &'static str {
match self {
Self::Easy => "bark-battle-ai-easy",
Self::Normal => "bark-battle-ai-normal",
Self::Hard => "bark-battle-ai-hard",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct RulesetThresholdsSignature {
pub standard_duration_ms: u64,
pub min_duration_ms: u64,
pub max_duration_ms: u64,
pub min_bark_gap_ms: u64,
pub trigger_count_tolerance: u32,
pub min_volume: f32,
pub max_volume: f32,
pub min_average_volume: f32,
pub max_average_volume: f32,
pub min_final_energy: f32,
pub max_final_energy: f32,
pub min_combo: u32,
pub max_combo: u32,
pub draw_threshold_energy: u32,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct BarkBattleRuleset {
pub version: &'static str,
pub difficulty: DifficultyPreset,
pub ai_preset_key: &'static str,
pub standard_duration_ms: u64,
pub min_duration_ms: u64,
pub max_duration_ms: u64,
pub min_bark_gap_ms: u64,
pub trigger_count_tolerance: u32,
pub min_volume: f32,
pub max_volume: f32,
pub min_average_volume: f32,
pub max_average_volume: f32,
pub min_final_energy: f32,
pub max_final_energy: f32,
pub min_combo: u32,
pub max_combo: u32,
pub draw_threshold_energy: u32,
}
impl BarkBattleRuleset {
pub fn v1() -> Self {
Self::for_difficulty(DifficultyPreset::Normal)
}
pub fn for_difficulty(difficulty: DifficultyPreset) -> Self {
Self {
version: BARK_BATTLE_RULESET_VERSION_V1,
difficulty,
ai_preset_key: difficulty.ai_preset_key(),
standard_duration_ms: 30_000,
min_duration_ms: 28_000,
max_duration_ms: 35_000,
min_bark_gap_ms: 250,
trigger_count_tolerance: 2,
min_volume: 0.0,
max_volume: 1.0,
min_average_volume: 0.0,
max_average_volume: 1.0,
min_final_energy: 0.0,
max_final_energy: 100.0,
min_combo: 0,
max_combo: 999,
draw_threshold_energy: 3,
}
}
pub fn thresholds_signature(&self) -> RulesetThresholdsSignature {
RulesetThresholdsSignature {
standard_duration_ms: self.standard_duration_ms,
min_duration_ms: self.min_duration_ms,
max_duration_ms: self.max_duration_ms,
min_bark_gap_ms: self.min_bark_gap_ms,
trigger_count_tolerance: self.trigger_count_tolerance,
min_volume: self.min_volume,
max_volume: self.max_volume,
min_average_volume: self.min_average_volume,
max_average_volume: self.max_average_volume,
min_final_energy: self.min_final_energy,
max_final_energy: self.max_final_energy,
min_combo: self.min_combo,
max_combo: self.max_combo,
draw_threshold_energy: self.draw_threshold_energy,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct BarkBattleFinishMetrics {
pub duration_ms: u64,
pub trigger_count: u64,
/// 归一化音量,合法范围为 0.0..=1.0。
pub max_volume: f32,
pub average_volume: f32,
pub final_energy: f32,
pub max_combo: u32,
pub finished_at_micros: i64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FinishValidationDecision {
Accepted,
AcceptedWithFlags,
Rejected,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AntiCheatFlag {
DurationTooShort,
DurationTooLong,
TriggerCountTooHigh,
MaxVolumeOutOfRange,
AverageVolumeOutOfRange,
FinalEnergyOutOfRange,
MaxComboOutOfRange,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct FinishValidation {
pub decision: FinishValidationDecision,
pub anti_cheat_flags: Vec<AntiCheatFlag>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BattleResult {
PlayerWin,
OpponentWin,
Draw,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct BarkBattleLeaderboardScore {
pub final_energy_millis: u32,
pub trigger_count: u64,
pub max_volume_millis: u32,
pub duration_closeness_ms: u64,
pub finished_at_micros: i64,
}