Calculate scores, make a table, print the board

main
Savanni D'Gerinel 2022-11-27 00:22:49 -05:00
parent e37add37df
commit 683d7ef7a3
1 changed files with 130 additions and 6 deletions

View File

@ -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<String, Member>,
}
@ -23,7 +23,64 @@ struct Team {
members: Vec<String>,
}
async fn request_board(session_token: &str, year: &str, board_id: &str) -> Board {
#[derive(Clone, Debug)]
struct Scoreboard(HashMap<String, Score>);
impl Scoreboard {
fn table(&self) -> Table {
let mut table = Vec::new();
let team_names = self.0.keys().cloned().collect::<Vec<String>>();
{
let row = vec!["".to_owned()];
let row = row
.into_iter()
.chain(team_names.clone())
.collect::<Vec<String>>();
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<String>,
}
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::<reqwest::Url>().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<Team>, 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<Vec<String>>,
column_sizes: Vec<usize>,
}
impl From<Vec<Vec<String>>> for Table {
fn from(lst: Vec<Vec<String>>) -> 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<Team> = 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<Team> = 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();
}