use super::state::TerritoryState;
use super::types::TerritoryId;
use crate::context::ResourceContext;
#[derive(Debug, Clone, Default)]
pub struct TerritoryService;
impl TerritoryService {
pub fn new() -> Self {
Self
}
pub fn calculate_control_change(current_control: f32, delta: f32) -> (f32, f32) {
let new_control = (current_control + delta).clamp(0.0, 1.0);
let actual_delta = new_control - current_control;
(new_control, actual_delta)
}
pub fn calculate_development_cost(
base_cost: i64,
current_level: u32,
cost_multiplier: f32,
) -> i64 {
let level_scaling = 1.5_f32.powi(current_level as i32);
let final_cost = base_cost as f32 * level_scaling * cost_multiplier;
final_cost.max(0.0).round() as i64
}
pub fn calculate_adjacency_bonus(
controlled_neighbors: usize,
total_neighbors: usize,
max_bonus: f32,
) -> f32 {
if total_neighbors == 0 {
return 0.0; }
let ratio = controlled_neighbors as f32 / total_neighbors as f32;
ratio * max_bonus
}
pub async fn get_control(territory_id: &TerritoryId, resources: &ResourceContext) -> f32 {
if let Some(state) = resources.get::<TerritoryState>().await {
state.get_control(territory_id).unwrap_or(0.0)
} else {
0.0
}
}
pub async fn get_development(territory_id: &TerritoryId, resources: &ResourceContext) -> u32 {
if let Some(state) = resources.get::<TerritoryState>().await {
state.get_development(territory_id).unwrap_or(0)
} else {
0
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_control_change() {
let (new, delta) = TerritoryService::calculate_control_change(0.5, 0.3);
assert!((new - 0.8).abs() < 0.001);
assert!((delta - 0.3).abs() < 0.001);
let (new, delta) = TerritoryService::calculate_control_change(0.7, 0.5);
assert_eq!(new, 1.0);
assert!((delta - 0.3).abs() < 0.001);
let (new, delta) = TerritoryService::calculate_control_change(0.5, -0.2);
assert!((new - 0.3).abs() < 0.001);
assert!((delta - (-0.2)).abs() < 0.001);
let (new, delta) = TerritoryService::calculate_control_change(0.3, -0.5);
assert_eq!(new, 0.0);
assert!((delta - (-0.3)).abs() < 0.001);
let (new, delta) = TerritoryService::calculate_control_change(0.5, 0.0);
assert_eq!(new, 0.5);
assert_eq!(delta, 0.0);
let (new, delta) = TerritoryService::calculate_control_change(1.0, 0.1);
assert_eq!(new, 1.0);
assert_eq!(delta, 0.0);
let (new, delta) = TerritoryService::calculate_control_change(0.0, -0.1);
assert_eq!(new, 0.0);
assert_eq!(delta, 0.0);
}
#[test]
fn test_calculate_development_cost() {
let cost = TerritoryService::calculate_development_cost(1000, 0, 1.0);
assert_eq!(cost, 1000);
let cost = TerritoryService::calculate_development_cost(1000, 1, 1.0);
assert_eq!(cost, 1500);
let cost = TerritoryService::calculate_development_cost(1000, 2, 1.0);
assert_eq!(cost, 2250);
let cost = TerritoryService::calculate_development_cost(1000, 3, 1.0);
assert_eq!(cost, 3375);
let cost = TerritoryService::calculate_development_cost(1000, 2, 0.5);
assert_eq!(cost, 1125);
let cost = TerritoryService::calculate_development_cost(1000, 1, 2.0);
assert_eq!(cost, 3000);
let cost = TerritoryService::calculate_development_cost(0, 5, 1.0);
assert_eq!(cost, 0);
}
#[test]
fn test_calculate_adjacency_bonus() {
let bonus = TerritoryService::calculate_adjacency_bonus(0, 4, 0.5);
assert!((bonus - 0.0).abs() < 0.001);
let bonus = TerritoryService::calculate_adjacency_bonus(2, 4, 0.5);
assert!((bonus - 0.25).abs() < 0.001);
let bonus = TerritoryService::calculate_adjacency_bonus(4, 4, 0.5);
assert!((bonus - 0.5).abs() < 0.001);
let bonus = TerritoryService::calculate_adjacency_bonus(1, 3, 0.6);
assert!((bonus - 0.2).abs() < 0.001);
let bonus = TerritoryService::calculate_adjacency_bonus(0, 0, 0.5);
assert_eq!(bonus, 0.0);
let bonus = TerritoryService::calculate_adjacency_bonus(3, 3, 1.0);
assert!((bonus - 1.0).abs() < 0.001);
}
}