use super::types::RankId;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Copy)]
pub enum AuthorityLevel {
Private,
SquadLeader,
Captain,
Commander,
SupremeCommander,
}
impl AuthorityLevel {
pub fn value(&self) -> u8 {
match self {
AuthorityLevel::Private => 0,
AuthorityLevel::SquadLeader => 1,
AuthorityLevel::Captain => 2,
AuthorityLevel::Commander => 3,
AuthorityLevel::SupremeCommander => 4,
}
}
pub fn can_command(&self, other: &AuthorityLevel) -> bool {
self > other
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct RankDefinition {
pub id: RankId,
pub name: String,
pub level: u32,
pub authority_level: AuthorityLevel,
pub max_direct_subordinates: usize,
}
impl RankDefinition {
pub fn new(
id: impl Into<String>,
name: impl Into<String>,
level: u32,
authority_level: AuthorityLevel,
) -> Self {
Self {
id: id.into(),
name: name.into(),
level,
authority_level,
max_direct_subordinates: match authority_level {
AuthorityLevel::Private => 0,
AuthorityLevel::SquadLeader => 5,
AuthorityLevel::Captain => 20,
AuthorityLevel::Commander => 50,
AuthorityLevel::SupremeCommander => 100,
},
}
}
pub fn with_max_subordinates(mut self, max: usize) -> Self {
self.max_direct_subordinates = max;
self
}
pub fn can_promote_to(&self, other: &RankDefinition) -> bool {
other.level == self.level + 1
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RankDefinitions {
ranks: HashMap<RankId, RankDefinition>,
}
impl crate::resources::Resource for RankDefinitions {}
impl RankDefinitions {
pub fn new() -> Self {
Self {
ranks: HashMap::new(),
}
}
pub fn add(&mut self, rank: RankDefinition) {
self.ranks.insert(rank.id.clone(), rank);
}
pub fn get(&self, rank_id: &RankId) -> Option<&RankDefinition> {
self.ranks.get(rank_id)
}
pub fn get_next_rank(&self, current_rank: &RankId) -> Option<&RankDefinition> {
let current = self.get(current_rank)?;
self.ranks.values().find(|r| r.level == current.level + 1)
}
pub fn get_all_sorted(&self) -> Vec<&RankDefinition> {
let mut ranks: Vec<_> = self.ranks.values().collect();
ranks.sort_by_key(|r| r.level);
ranks
}
pub fn len(&self) -> usize {
self.ranks.len()
}
pub fn is_empty(&self) -> bool {
self.ranks.is_empty()
}
pub fn get_by_level(&self, level: u32) -> Option<&RankDefinition> {
self.ranks.values().find(|r| r.level == level)
}
}
impl Default for RankDefinitions {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_authority_level_ordering() {
assert!(AuthorityLevel::Private < AuthorityLevel::SquadLeader);
assert!(AuthorityLevel::SquadLeader < AuthorityLevel::Captain);
assert!(AuthorityLevel::Captain < AuthorityLevel::Commander);
assert!(AuthorityLevel::Commander < AuthorityLevel::SupremeCommander);
}
#[test]
fn test_authority_level_value() {
assert_eq!(AuthorityLevel::Private.value(), 0);
assert_eq!(AuthorityLevel::SquadLeader.value(), 1);
assert_eq!(AuthorityLevel::Captain.value(), 2);
assert_eq!(AuthorityLevel::Commander.value(), 3);
assert_eq!(AuthorityLevel::SupremeCommander.value(), 4);
}
#[test]
fn test_authority_can_command() {
let captain = AuthorityLevel::Captain;
let squad_leader = AuthorityLevel::SquadLeader;
let private = AuthorityLevel::Private;
assert!(captain.can_command(&squad_leader));
assert!(captain.can_command(&private));
assert!(squad_leader.can_command(&private));
assert!(!private.can_command(&squad_leader));
assert!(!squad_leader.can_command(&captain));
}
#[test]
fn test_rank_definition_creation() {
let rank = RankDefinition::new("private", "Private", 0, AuthorityLevel::Private);
assert_eq!(rank.id, "private");
assert_eq!(rank.name, "Private");
assert_eq!(rank.level, 0);
assert_eq!(rank.authority_level, AuthorityLevel::Private);
assert_eq!(rank.max_direct_subordinates, 0);
}
#[test]
fn test_rank_definition_default_subordinates() {
let private = RankDefinition::new("private", "Private", 0, AuthorityLevel::Private);
let squad_leader =
RankDefinition::new("sergeant", "Sergeant", 1, AuthorityLevel::SquadLeader);
let captain = RankDefinition::new("captain", "Captain", 2, AuthorityLevel::Captain);
assert_eq!(private.max_direct_subordinates, 0);
assert_eq!(squad_leader.max_direct_subordinates, 5);
assert_eq!(captain.max_direct_subordinates, 20);
}
#[test]
fn test_rank_definition_with_custom_subordinates() {
let rank = RankDefinition::new("sergeant", "Sergeant", 1, AuthorityLevel::SquadLeader)
.with_max_subordinates(10);
assert_eq!(rank.max_direct_subordinates, 10);
}
#[test]
fn test_rank_can_promote_to() {
let private = RankDefinition::new("private", "Private", 0, AuthorityLevel::Private);
let sergeant = RankDefinition::new("sergeant", "Sergeant", 1, AuthorityLevel::SquadLeader);
let captain = RankDefinition::new("captain", "Captain", 2, AuthorityLevel::Captain);
assert!(private.can_promote_to(&sergeant));
assert!(!private.can_promote_to(&captain)); assert!(sergeant.can_promote_to(&captain));
assert!(!sergeant.can_promote_to(&private)); }
#[test]
fn test_rank_definitions_add_and_get() {
let mut defs = RankDefinitions::new();
let rank = RankDefinition::new("private", "Private", 0, AuthorityLevel::Private);
defs.add(rank.clone());
assert_eq!(defs.len(), 1);
assert_eq!(defs.get(&"private".to_string()), Some(&rank));
}
#[test]
fn test_rank_definitions_get_next_rank() {
let mut defs = RankDefinitions::new();
defs.add(RankDefinition::new(
"private",
"Private",
0,
AuthorityLevel::Private,
));
defs.add(RankDefinition::new(
"sergeant",
"Sergeant",
1,
AuthorityLevel::SquadLeader,
));
defs.add(RankDefinition::new(
"captain",
"Captain",
2,
AuthorityLevel::Captain,
));
let next = defs.get_next_rank(&"private".to_string());
assert!(next.is_some());
assert_eq!(next.unwrap().id, "sergeant");
let next = defs.get_next_rank(&"sergeant".to_string());
assert!(next.is_some());
assert_eq!(next.unwrap().id, "captain");
let next = defs.get_next_rank(&"captain".to_string());
assert!(next.is_none()); }
#[test]
fn test_rank_definitions_get_all_sorted() {
let mut defs = RankDefinitions::new();
defs.add(RankDefinition::new(
"captain",
"Captain",
2,
AuthorityLevel::Captain,
));
defs.add(RankDefinition::new(
"private",
"Private",
0,
AuthorityLevel::Private,
));
defs.add(RankDefinition::new(
"sergeant",
"Sergeant",
1,
AuthorityLevel::SquadLeader,
));
let sorted = defs.get_all_sorted();
assert_eq!(sorted.len(), 3);
assert_eq!(sorted[0].id, "private");
assert_eq!(sorted[1].id, "sergeant");
assert_eq!(sorted[2].id, "captain");
}
#[test]
fn test_rank_definitions_get_by_level() {
let mut defs = RankDefinitions::new();
defs.add(RankDefinition::new(
"private",
"Private",
0,
AuthorityLevel::Private,
));
defs.add(RankDefinition::new(
"sergeant",
"Sergeant",
1,
AuthorityLevel::SquadLeader,
));
let rank = defs.get_by_level(0);
assert!(rank.is_some());
assert_eq!(rank.unwrap().id, "private");
let rank = defs.get_by_level(1);
assert!(rank.is_some());
assert_eq!(rank.unwrap().id, "sergeant");
let rank = defs.get_by_level(99);
assert!(rank.is_none());
}
#[test]
fn test_rank_definitions_is_empty() {
let mut defs = RankDefinitions::new();
assert!(defs.is_empty());
defs.add(RankDefinition::new(
"private",
"Private",
0,
AuthorityLevel::Private,
));
assert!(!defs.is_empty());
}
#[test]
fn test_rank_serialization() {
let rank = RankDefinition::new("private", "Private", 0, AuthorityLevel::Private);
let json = serde_json::to_string(&rank).unwrap();
let deserialized: RankDefinition = serde_json::from_str(&json).unwrap();
assert_eq!(rank, deserialized);
}
#[test]
fn test_rank_definitions_serialization() {
let mut defs = RankDefinitions::new();
defs.add(RankDefinition::new(
"private",
"Private",
0,
AuthorityLevel::Private,
));
let json = serde_json::to_string(&defs).unwrap();
let deserialized: RankDefinitions = serde_json::from_str(&json).unwrap();
assert_eq!(defs.len(), deserialized.len());
assert_eq!(
defs.get(&"private".to_string()),
deserialized.get(&"private".to_string())
);
}
}