From 683d7ef7a34c9a1abfdc9a23d35db3bfb2f23764 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sun, 27 Nov 2022 00:22:49 -0500 Subject: [PATCH] Calculate scores, make a table, print the board --- challenge/src/main.rs | 136 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 6 deletions(-) diff --git a/challenge/src/main.rs b/challenge/src/main.rs index ea79be9..d41a1f7 100644 --- a/challenge/src/main.rs +++ b/challenge/src/main.rs @@ -6,7 +6,7 @@ const INPUT_DATA: &str = include_str!("../680754.json"); const TEAMS: &str = include_str!("../teams.yaml"); #[derive(Clone, Debug, Deserialize)] -struct Board { +struct Leaderboard { members: HashMap, } @@ -23,7 +23,64 @@ struct Team { members: Vec, } -async fn request_board(session_token: &str, year: &str, board_id: &str) -> Board { +#[derive(Clone, Debug)] +struct Scoreboard(HashMap); + +impl Scoreboard { + fn table(&self) -> Table { + let mut table = Vec::new(); + + let team_names = self.0.keys().cloned().collect::>(); + + { + let row = vec!["".to_owned()]; + let row = row + .into_iter() + .chain(team_names.clone()) + .collect::>(); + table.push(row); + } + + { + let mut row = vec!["Score".to_owned()]; + for name in team_names.clone() { + let score = self.0.get(&name).unwrap(); + row.push(format!("{}", score.total_score)); + } + table.push(row); + } + + { + let mut row = vec!["Stars".to_owned()]; + for name in team_names.clone() { + let score = self.0.get(&name).unwrap(); + row.push(format!("{}", score.total_stars)); + } + table.push(row); + } + + Table::from(table) + } +} + +#[derive(Clone, Debug)] +struct Score { + total_stars: u32, + total_score: u32, + members: Vec, +} + +impl Default for Score { + fn default() -> Self { + Self { + total_stars: 0, + total_score: 0, + members: vec![], + } + } +} + +async fn request_board(session_token: &str, year: &str, board_id: &str) -> Leaderboard { let jar = reqwest::cookie::Jar::default(); let url = "https://adventofcode.com/".parse::().unwrap(); jar.add_cookie_str(&format!("session={}", session_token), &url); @@ -47,8 +104,76 @@ async fn request_board(session_token: &str, year: &str, board_id: &str) -> Board .unwrap() } +fn score(teams: Vec, leaderboard: Leaderboard) -> Scoreboard { + let mut scores = HashMap::new(); + + for team in teams { + let score = leaderboard + .members + .values() + .fold(Score::default(), |score, member| { + if team.members.contains(&member.name) { + let mut members = score.members.clone(); + members.push(member.name.clone()); + Score { + total_stars: score.total_stars + member.stars, + total_score: score.total_score + member.local_score, + members, + } + } else { + score + } + }); + scores.insert(team.name.clone(), score); + } + + Scoreboard(scores) +} + +struct Table { + table: Vec>, + column_sizes: Vec, +} + +impl From>> for Table { + fn from(lst: Vec>) -> Table { + let column_sizes = (0..lst[0].len()) + .map(|idx| { + lst.iter() + .fold(0, |cur, r| std::cmp::max(cur, r[idx].len())) + }) + .collect(); + + Table { + table: lst, + column_sizes, + } + } +} + +impl Table { + fn print(&self) { + for row in self.table.iter() { + for (width, field) in self.column_sizes.iter().zip(row.iter()) { + let val = pad(field.clone(), *width); + print!("| {} ", val); + } + println!("|"); + } + } +} + +fn pad(mut val: String, size: usize) -> String { + while val.len() < size { + val.push(' '); + } + val +} + #[tokio::main] async fn main() { + let teams: Vec = serde_yaml::from_str(TEAMS).unwrap(); + /* let session_token = std::env::vars() .find_map(|(key, value)| { @@ -63,8 +188,7 @@ async fn main() { let board = request_board(&session_token, "2022", "680754"); */ - let teams: Vec = serde_yaml::from_str(TEAMS).unwrap(); - let board: Board = serde_json::from_str(INPUT_DATA).unwrap(); - println!("resulting text: {:?}", teams); - println!("resulting text: {:?}", board); + let board: Leaderboard = serde_json::from_str(INPUT_DATA).unwrap(); + let scoreboard = score(teams, board); + scoreboard.table().print(); }