Files
Genarrative/server-rs/crates/module-progression/src/lib.rs

163 lines
5.5 KiB
Rust

mod application;
mod commands;
mod domain;
mod errors;
mod events;
pub use application::*;
pub use commands::*;
pub use domain::*;
pub use errors::*;
pub use events::*;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn create_initial_player_progression_starts_from_level_one() {
let snapshot =
create_initial_player_progression("user_001".to_string(), 10).expect("should build");
assert_eq!(snapshot.level, 1);
assert_eq!(snapshot.total_xp, 0);
assert_eq!(snapshot.current_level_xp, 0);
assert_eq!(snapshot.xp_to_next_level, 60);
assert_eq!(snapshot.last_granted_source, None);
}
#[test]
fn grant_player_experience_promotes_level_from_quest_reward() {
let current = build_player_progression_snapshot("user_001".to_string(), 50, None, 10, 10)
.expect("current snapshot should build");
let next = grant_player_experience(
current,
PlayerProgressionGrantInput {
user_id: "user_001".to_string(),
amount: 40,
source: PlayerProgressionGrantSource::Quest,
updated_at_micros: 20,
},
)
.expect("grant should succeed");
assert_eq!(next.level, 2);
assert_eq!(next.total_xp, 90);
assert_eq!(next.current_level_xp, 30);
assert_eq!(next.xp_to_next_level, 88);
assert_eq!(next.pending_level_ups, 1);
assert_eq!(
next.last_granted_source,
Some(PlayerProgressionGrantSource::Quest)
);
}
#[test]
fn build_level_benchmark_matches_node_curve() {
let benchmark = build_level_benchmark(5);
assert_eq!(benchmark.level, 5);
assert_eq!(benchmark.xp_to_next_level, 268);
assert_eq!(benchmark.cumulative_xp_required, 472);
assert_eq!(benchmark.reference_strength, 260);
assert_eq!(benchmark.base_hp, 436);
}
#[test]
fn chapter_boundary_pseudo_level_millis_grows_with_chapter_index() {
let first = resolve_chapter_boundary_pseudo_level_millis(1, 3);
let second = resolve_chapter_boundary_pseudo_level_millis(2, 3);
let third = resolve_chapter_boundary_pseudo_level_millis(3, 3);
assert!(second > first);
assert!(third > second);
}
#[test]
fn build_chapter_auto_level_profile_applies_role_offset() {
let standard = build_chapter_auto_level_profile(ChapterAutoLevelProfileInput {
chapter_id: "chapter-3".to_string(),
chapter_index: 3,
entry_pseudo_level_millis: 6_200,
exit_pseudo_level_millis: 8_800,
stage_progress_millis: 1_000,
progression_role: ProgressionRole::HostileStandard,
})
.expect("standard profile should build");
let boss = build_chapter_auto_level_profile(ChapterAutoLevelProfileInput {
chapter_id: "chapter-3".to_string(),
chapter_index: 3,
entry_pseudo_level_millis: 6_200,
exit_pseudo_level_millis: 8_800,
stage_progress_millis: 1_000,
progression_role: ProgressionRole::HostileBoss,
})
.expect("boss profile should build");
assert_eq!(standard.progression_role, ProgressionRole::HostileStandard);
assert_eq!(boss.progression_role, ProgressionRole::HostileBoss);
assert!(boss.level >= standard.level + 2);
assert_eq!(boss.source, LevelProfileSource::ChapterAuto);
}
#[test]
fn build_hostile_experience_reward_matches_existing_fallback_expectation() {
let level_profile = RuntimeEntityLevelProfile {
level: 5,
reference_strength: 260,
chapter_id: None,
chapter_index: None,
progression_role: ProgressionRole::HostileStandard,
source: LevelProfileSource::Manual,
};
let reward = build_hostile_experience_reward(5, &level_profile, 1_000, None);
let hp = resolve_hostile_battle_max_hp(&level_profile);
assert_eq!(reward, 20);
assert_eq!(hp, 48);
}
#[test]
fn apply_chapter_progression_ledger_accumulates_actual_values() {
let current = build_chapter_progression_snapshot(ChapterProgressionInput {
user_id: "user_001".to_string(),
chapter_id: "chapter-1".to_string(),
chapter_index: 1,
total_chapters: 3,
entry_pseudo_level_millis: 1_000,
exit_pseudo_level_millis: 5_000,
entry_level: 1,
exit_level: 5,
planned_total_xp: 320,
planned_quest_xp: 200,
planned_hostile_xp: 120,
expected_hostile_defeat_count: 3,
level_at_entry: 1,
pace_band: ChapterPaceBand::OpeningFast,
updated_at_micros: 10,
})
.expect("chapter snapshot should build");
let next = apply_chapter_progression_ledger(
current,
ChapterProgressionLedgerInput {
user_id: "user_001".to_string(),
chapter_id: "chapter-1".to_string(),
granted_quest_xp: 60,
granted_hostile_xp: 20,
hostile_defeat_increment: 1,
level_at_exit: Some(2),
updated_at_micros: 20,
},
)
.expect("ledger apply should succeed");
assert_eq!(next.actual_quest_xp, 60);
assert_eq!(next.actual_hostile_xp, 20);
assert_eq!(next.actual_hostile_defeat_count, 1);
assert_eq!(next.level_at_exit, Some(2));
}
}