Merge pull request 'break team scores per territory' (#1) from ammar into main

Reviewed-on: #1
This commit is contained in:
2025-11-18 05:36:19 +00:00
2 changed files with 29 additions and 17 deletions

View File

@ -1,4 +1,4 @@
use std::{collections::HashMap, error::Error};
use std::{collections::{HashMap, HashSet}, error::Error};
use csv::{Reader, Writer};
use crate::data::{Player, PlayerScore, TeamScore};
@ -29,8 +29,8 @@ pub fn write_player_scores(
// Write data
for score in player_scores {
writer.write_record(&[
&score.username,
&score.team,
&score.player.username,
&score.player.team,
&score.total_score.to_string(),
])?;
}
@ -45,13 +45,27 @@ pub fn write_team_scores(
team_scores: &[TeamScore],
) -> Result<(), Box<dyn Error>> {
let mut writer = Writer::from_path(file_path)?;
let mut territories: HashSet<String> = HashSet::new();
for score in team_scores.iter() {
for (territory, _) in score.territory_scores.clone() {
territories.insert(territory);
}
}
let territories: Vec<String> = territories.into_iter().collect();
// Write header
writer.write_record(&["team", "total_score"])?;
let mut header = vec![String::from("team")];
header.append(&mut territories.clone());
writer.write_record(&header)?;
// Write data
for score in team_scores {
writer.write_record(&[&score.team, &score.total_score.to_string()])?;
let mut scores = vec![score.team.clone()];
let default = 0;
for territory in territories.clone() {
scores.push(score.territory_scores.get(&territory).unwrap_or(&default).to_string());
}
writer.write_record(scores)?;
}
writer.flush()?;
@ -83,7 +97,7 @@ pub fn write_territory_scores(
// Write data
for score in player_scores {
let mut row = vec![score.username.clone(), score.team.clone()];
let mut row = vec![score.player.username.clone(), score.player.team.clone()];
for territory in &territories {
let territory_score = score.territory_scores.get(territory).unwrap_or(&0);
@ -104,8 +118,8 @@ pub fn calculate_team_scores(player_scores: &[PlayerScore]) -> Vec<TeamScore> {
for player_score in player_scores {
let team_score = team_map
.entry(player_score.team.clone())
.or_insert_with(|| TeamScore::new(player_score.team.clone()));
.entry(player_score.player.team.clone())
.or_insert_with(|| TeamScore::new(player_score.player.team.clone()));
for (territory, score) in &player_score.territory_scores {
team_score.add_territory_score(territory.clone(), *score);
@ -187,9 +201,9 @@ mod tests {
write_team_scores(file_path, &team_scores).unwrap();
let content = fs::read_to_string(file_path).unwrap();
assert!(content.contains("team,total_score"));
assert!(content.contains("Red Team,20"));
assert!(content.contains("Blue Team,15"));
assert!(content.contains("team,Capitol Hill,Downtown"));
assert!(content.contains("Red Team,20,0"));
assert!(content.contains("Blue Team,0,15"));
}
#[test]

View File

@ -9,8 +9,7 @@ pub struct Player {
#[derive(Debug, Clone, Serialize)]
pub struct PlayerScore {
pub username: String,
pub team: String,
pub player: Player,
pub total_score: i32,
pub territory_scores: HashMap<String, i32>,
}
@ -18,8 +17,7 @@ pub struct PlayerScore {
impl PlayerScore {
pub fn new(player: Player) -> Self {
PlayerScore {
username: player.username,
team: player.team,
player: player,
total_score: 0,
territory_scores: HashMap::new(),
}
@ -72,8 +70,8 @@ mod tests {
let player_score = PlayerScore::new(player.clone());
assert_eq!(player_score.username, "testuser");
assert_eq!(player_score.team, "TestTeam");
assert_eq!(player_score.player.username, "testuser");
assert_eq!(player_score.player.team, "TestTeam");
assert_eq!(player_score.total_score, 0);
assert!(player_score.territory_scores.is_empty());
}