use serde::{Deserialize, Serialize};
use crate::types::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SplitOperation {
pub teams: Vec<Team>,
pub results: Vec<TeamResult>,
pub recombined: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Team {
pub id: String,
pub name: String,
pub objective: String,
pub members: Vec<CharacterId>,
pub synergy: TeamSynergy,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TeamSynergy {
Strong,
Functional,
Volatile,
Hostile,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TeamResult {
pub team_id: String,
pub success: bool,
pub report: String,
pub relationship_deltas: Vec<(CharacterId, CharacterId, i32)>,
pub flags: Vec<(String, FlagValue)>,
}
pub fn evaluate_synergy(members: &[CharacterId]) -> TeamSynergy {
let ids: Vec<&str> = members.iter().map(|m| m.0.as_str()).collect();
if ids.contains(&"galen") && ids.contains(&"eli") { return TeamSynergy::Strong; }
if ids.contains(&"rosa") && ids.contains(&"miriam") { return TeamSynergy::Strong; }
if ids.contains(&"galen") && ids.contains(&"ada") { return TeamSynergy::Strong; }
if ids.contains(&"eli") && ids.contains(&"ada") { return TeamSynergy::Strong; }
if ids.contains(&"eli") && ids.contains(&"lucien") { return TeamSynergy::Volatile; }
if ids.contains(&"miriam") && ids.contains(&"lucien") { return TeamSynergy::Volatile; }
if ids.contains(&"rosa") && ids.contains(&"lucien") { return TeamSynergy::Hostile; }
TeamSynergy::Functional
}
pub fn resolve_team(team: &Team) -> TeamResult {
let ids: Vec<&str> = team.members.iter().map(|m| m.0.as_str()).collect();
let members_str = ids.join(" and ");
let (success, report, deltas) = match (team.id.as_str(), &team.synergy) {
("wire_office", TeamSynergy::Strong) => (
true,
format!("{members_str} held the wire office. The dispatch got through."),
vec![],
),
("wire_office", _) => (
true,
format!("{members_str} held the wire office under pressure."),
vec![],
),
("signal_tower", TeamSynergy::Hostile) => {
let report = if ids.contains(&"rosa") && ids.contains(&"lucien") {
"Rosa held Pine Signal. Lucien disarmed the mast charge. \
Rosa has not thanked him. She won't.".to_string()
} else {
"The signal tower held, barely.".to_string()
};
(true, report, vec![
(CharacterId::new("rosa"), CharacterId::new("lucien"), 1), ])
},
("signal_tower", _) => (
true,
format!("{members_str} secured the signal tower."),
vec![],
),
("witness_route", _) if ids.contains(&"eli") && ids.contains(&"miriam") => (
true,
"Miriam and Eli kept the witness safe. Neither agrees on how.".to_string(),
vec![
(CharacterId::new("eli"), CharacterId::new("miriam"), 2),
],
),
("witness_route", _) => (
true,
format!("{members_str} secured the witness route."),
vec![],
),
_ => (
true,
format!("Team {} completed their objective.", team.id),
vec![],
),
};
TeamResult {
team_id: team.id.clone(),
success,
report,
relationship_deltas: deltas,
flags: if success {
vec![(format!("{}_held", team.id), FlagValue::Bool(true))]
} else {
vec![(format!("{}_lost", team.id), FlagValue::Bool(true))]
},
}
}
pub fn long_wire_split(
wire_team: Vec<CharacterId>,
signal_team: Vec<CharacterId>,
witness_team: Vec<CharacterId>,
) -> SplitOperation {
let wire_synergy = evaluate_synergy(&wire_team);
let signal_synergy = evaluate_synergy(&signal_team);
let witness_synergy = evaluate_synergy(&witness_team);
let teams = vec![
Team {
id: "wire_office".to_string(),
name: "Wire Office".to_string(),
objective: "Hold the telegraph office and transmit the party's version".to_string(),
members: wire_team,
synergy: wire_synergy,
},
Team {
id: "signal_tower".to_string(),
name: "Signal Tower".to_string(),
objective: "Secure the relay tower and delay the counter-narrative".to_string(),
members: signal_team,
synergy: signal_synergy,
},
Team {
id: "witness_route".to_string(),
name: "Witness Route".to_string(),
objective: "Protect the witness and get their testimony through".to_string(),
members: witness_team,
synergy: witness_synergy,
},
];
let results = teams.iter().map(resolve_team).collect();
SplitOperation {
teams,
results,
recombined: false,
}
}