163 lines
4.8 KiB
Rust
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,
|
|
}
|