use super::config::CultureConfig;
use super::types::{Alignment, CultureEffect, CultureTag, Member, PersonalityTrait};
use std::collections::HashSet;
#[derive(Debug, Clone, Copy, Default)]
pub struct CultureService;
impl CultureService {
pub fn check_alignment(member: &Member, culture_tags: &HashSet<CultureTag>) -> Alignment {
let personality_traits = &member.personality_traits;
if personality_traits.contains(&PersonalityTrait::Cautious)
&& culture_tags.contains(&CultureTag::Bureaucratic)
{
return Alignment::Aligned { fervor_bonus: 0.05 };
}
if personality_traits.contains(&PersonalityTrait::Bold)
&& culture_tags.contains(&CultureTag::RiskTaking)
{
return Alignment::Aligned { fervor_bonus: 0.06 };
}
if personality_traits.contains(&PersonalityTrait::Zealous)
&& culture_tags.contains(&CultureTag::Fanatic)
{
return Alignment::Aligned { fervor_bonus: 0.08 };
}
if personality_traits.contains(&PersonalityTrait::Workaholic)
&& culture_tags.contains(&CultureTag::Overwork)
{
return Alignment::Aligned { fervor_bonus: 0.05 };
}
if personality_traits.contains(&PersonalityTrait::Collaborative)
&& culture_tags.contains(&CultureTag::PsychologicalSafety)
{
return Alignment::Aligned { fervor_bonus: 0.04 };
}
if personality_traits.contains(&PersonalityTrait::Competitive)
&& culture_tags.contains(&CultureTag::Ruthless)
{
return Alignment::Aligned { fervor_bonus: 0.05 };
}
if personality_traits.contains(&PersonalityTrait::Cautious)
&& culture_tags.contains(&CultureTag::RiskTaking)
{
return Alignment::Misaligned {
stress_rate: 0.08,
reason: "Cautious personality in risk-taking culture".to_string(),
};
}
if personality_traits.contains(&PersonalityTrait::Bold)
&& culture_tags.contains(&CultureTag::Bureaucratic)
{
return Alignment::Misaligned {
stress_rate: 0.06,
reason: "Bold personality in bureaucratic culture".to_string(),
};
}
if personality_traits.contains(&PersonalityTrait::Pragmatic)
&& culture_tags.contains(&CultureTag::Fanatic)
{
return Alignment::Misaligned {
stress_rate: 0.10,
reason: "Pragmatic personality in fanatic culture".to_string(),
};
}
if personality_traits.contains(&PersonalityTrait::Balanced)
&& culture_tags.contains(&CultureTag::Overwork)
{
return Alignment::Misaligned {
stress_rate: 0.07,
reason: "Balanced personality in overwork culture".to_string(),
};
}
if personality_traits.contains(&PersonalityTrait::Collaborative)
&& culture_tags.contains(&CultureTag::Ruthless)
{
return Alignment::Misaligned {
stress_rate: 0.09,
reason: "Collaborative personality in ruthless culture".to_string(),
};
}
Alignment::Neutral
}
pub fn calculate_stress_change(
current_stress: f32,
alignment: &Alignment,
config: &CultureConfig,
culture_strength: f32,
) -> f32 {
let new_stress = match alignment {
Alignment::Aligned { .. } => {
if config.enable_stress_decay {
(current_stress - config.stress_decay_rate * 2.0).max(0.0)
} else {
current_stress
}
}
Alignment::Misaligned { stress_rate, .. } => {
let stress_increase = stress_rate * config.base_stress_rate * culture_strength;
current_stress + stress_increase
}
Alignment::Neutral => {
if config.enable_stress_decay {
(current_stress - config.stress_decay_rate).max(0.0)
} else {
current_stress
}
}
};
new_stress.clamp(0.0, 1.0)
}
pub fn calculate_fervor_change(
current_fervor: f32,
alignment: &Alignment,
config: &CultureConfig,
culture_strength: f32,
) -> f32 {
let new_fervor = match alignment {
Alignment::Aligned { fervor_bonus } => {
let fervor_increase =
fervor_bonus * config.base_fervor_growth_rate * culture_strength;
current_fervor + fervor_increase
}
Alignment::Misaligned { .. } => {
(current_fervor - 0.01).max(0.0)
}
Alignment::Neutral => {
current_fervor
}
};
new_fervor.clamp(0.0, 1.0)
}
pub fn is_stressed_out(member: &Member, config: &CultureConfig) -> bool {
member.stress >= config.stress_breakdown_threshold
}
pub fn is_fanatical(member: &Member, config: &CultureConfig) -> bool {
member.fervor >= config.fervor_fanaticism_threshold
}
pub fn get_culture_effects(
culture_tags: &HashSet<CultureTag>,
culture_strength: f32,
) -> Vec<CultureEffect> {
let mut effects = Vec::new();
for tag in culture_tags {
match tag {
CultureTag::RiskTaking => {
effects.push(CultureEffect::IncreasedRiskTaking {
magnitude: 0.3 * culture_strength,
});
}
CultureTag::PsychologicalSafety => {
effects.push(CultureEffect::ImprovedReporting {
magnitude: 0.4 * culture_strength,
});
}
CultureTag::Ruthless => {
effects.push(CultureEffect::IncreasedCompetition {
magnitude: 0.5 * culture_strength,
});
}
CultureTag::Bureaucratic => {
effects.push(CultureEffect::IncreasedCaution {
magnitude: 0.4 * culture_strength,
});
}
CultureTag::Fanatic => {
effects.push(CultureEffect::Fearless);
}
CultureTag::Overwork => {
effects.push(CultureEffect::IncreasedProductivity {
stress_cost: 0.05 * culture_strength,
});
}
CultureTag::Martyrdom => {
effects.push(CultureEffect::SelfSacrifice {
probability: 0.2 * culture_strength,
});
}
CultureTag::Custom(_) => {
}
}
}
effects
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_member_with_trait(trait_: PersonalityTrait) -> Member {
Member::new("m1", "Test").with_trait(trait_)
}
fn create_culture_tags(tags: Vec<CultureTag>) -> HashSet<CultureTag> {
tags.into_iter().collect()
}
#[test]
fn test_alignment_cautious_bureaucratic() {
let member = create_member_with_trait(PersonalityTrait::Cautious);
let tags = create_culture_tags(vec![CultureTag::Bureaucratic]);
let alignment = CultureService::check_alignment(&member, &tags);
match alignment {
Alignment::Aligned { fervor_bonus } => {
assert_eq!(fervor_bonus, 0.05);
}
_ => panic!("Expected Aligned"),
}
}
#[test]
fn test_alignment_bold_risk_taking() {
let member = create_member_with_trait(PersonalityTrait::Bold);
let tags = create_culture_tags(vec![CultureTag::RiskTaking]);
let alignment = CultureService::check_alignment(&member, &tags);
match alignment {
Alignment::Aligned { fervor_bonus } => {
assert_eq!(fervor_bonus, 0.06);
}
_ => panic!("Expected Aligned"),
}
}
#[test]
fn test_misalignment_cautious_risk_taking() {
let member = create_member_with_trait(PersonalityTrait::Cautious);
let tags = create_culture_tags(vec![CultureTag::RiskTaking]);
let alignment = CultureService::check_alignment(&member, &tags);
match alignment {
Alignment::Misaligned { stress_rate, .. } => {
assert_eq!(stress_rate, 0.08);
}
_ => panic!("Expected Misaligned"),
}
}
#[test]
fn test_alignment_neutral() {
let member = create_member_with_trait(PersonalityTrait::Balanced);
let tags = create_culture_tags(vec![CultureTag::PsychologicalSafety]);
let alignment = CultureService::check_alignment(&member, &tags);
assert_eq!(alignment, Alignment::Neutral);
}
#[test]
fn test_stress_increase_misaligned() {
let config = CultureConfig::default();
let alignment = Alignment::Misaligned {
stress_rate: 0.08,
reason: "Test".to_string(),
};
let new_stress = CultureService::calculate_stress_change(0.5, &alignment, &config, 1.0);
assert!(new_stress > 0.5);
assert!(new_stress < 0.51);
}
#[test]
fn test_stress_decrease_aligned() {
let config = CultureConfig::default();
let alignment = Alignment::Aligned { fervor_bonus: 0.05 };
let new_stress = CultureService::calculate_stress_change(0.5, &alignment, &config, 1.0);
assert!(new_stress < 0.5);
}
#[test]
fn test_fervor_increase_aligned() {
let config = CultureConfig::default();
let alignment = Alignment::Aligned { fervor_bonus: 0.06 };
let new_fervor = CultureService::calculate_fervor_change(0.5, &alignment, &config, 1.0);
assert!(new_fervor > 0.5);
assert!(new_fervor < 0.51);
}
#[test]
fn test_fervor_decrease_misaligned() {
let config = CultureConfig::default();
let alignment = Alignment::Misaligned {
stress_rate: 0.08,
reason: "Test".to_string(),
};
let new_fervor = CultureService::calculate_fervor_change(0.5, &alignment, &config, 1.0);
assert_eq!(new_fervor, 0.49);
}
#[test]
fn test_is_stressed_out() {
let config = CultureConfig::default();
let member = Member::new("m1", "Test").with_stress(0.85);
assert!(CultureService::is_stressed_out(&member, &config));
}
#[test]
fn test_is_not_stressed_out() {
let config = CultureConfig::default();
let member = Member::new("m1", "Test").with_stress(0.5);
assert!(!CultureService::is_stressed_out(&member, &config));
}
#[test]
fn test_is_fanatical() {
let config = CultureConfig::default();
let member = Member::new("m1", "Test").with_fervor(0.95);
assert!(CultureService::is_fanatical(&member, &config));
}
#[test]
fn test_is_not_fanatical() {
let config = CultureConfig::default();
let member = Member::new("m1", "Test").with_fervor(0.7);
assert!(!CultureService::is_fanatical(&member, &config));
}
#[test]
fn test_get_culture_effects_risk_taking() {
let tags = create_culture_tags(vec![CultureTag::RiskTaking]);
let effects = CultureService::get_culture_effects(&tags, 1.0);
assert_eq!(effects.len(), 1);
match &effects[0] {
CultureEffect::IncreasedRiskTaking { magnitude } => {
assert_eq!(*magnitude, 0.3);
}
_ => panic!("Expected IncreasedRiskTaking"),
}
}
#[test]
fn test_get_culture_effects_multiple() {
let tags = create_culture_tags(vec![
CultureTag::RiskTaking,
CultureTag::PsychologicalSafety,
CultureTag::Fanatic,
]);
let effects = CultureService::get_culture_effects(&tags, 1.0);
assert_eq!(effects.len(), 3);
}
#[test]
fn test_get_culture_effects_with_strength() {
let tags = create_culture_tags(vec![CultureTag::RiskTaking]);
let effects = CultureService::get_culture_effects(&tags, 2.0);
match &effects[0] {
CultureEffect::IncreasedRiskTaking { magnitude } => {
assert_eq!(*magnitude, 0.6); }
_ => panic!("Expected IncreasedRiskTaking"),
}
}
#[test]
fn test_stress_clamping() {
let config = CultureConfig::default();
let alignment = Alignment::Misaligned {
stress_rate: 1.0, reason: "Test".to_string(),
};
let new_stress = CultureService::calculate_stress_change(
0.95, &alignment, &config, 10.0, );
assert_eq!(new_stress, 1.0);
}
#[test]
fn test_fervor_clamping() {
let config = CultureConfig::default();
let alignment = Alignment::Aligned { fervor_bonus: 1.0 };
let new_fervor = CultureService::calculate_fervor_change(0.95, &alignment, &config, 10.0);
assert_eq!(new_fervor, 1.0);
}
}