-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added getting the leaderboard (#31)
* Added a new command to grab the leaderboard of a particular year * Refactored a bit of AocApi Closes #31
- Loading branch information
Showing
21 changed files
with
700 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
[package] | ||
name = "elv" | ||
description = "A little CLI helper for Advent of Code. 🎄" | ||
version = "0.12.2" | ||
version = "0.12.3" | ||
authors = ["Konrad Pagacz <[email protected]>"] | ||
edition = "2021" | ||
readme = "README.md" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
use error_chain::bail; | ||
|
||
use crate::domain::errors::*; | ||
|
||
#[derive(PartialEq, Debug)] | ||
pub struct LeaderboardEntry { | ||
pub position: i32, | ||
pub points: i32, | ||
pub username: String, | ||
} | ||
|
||
impl TryFrom<&str> for LeaderboardEntry { | ||
type Error = Error; | ||
|
||
fn try_from(value: &str) -> Result<Self> { | ||
let values: Vec<&str> = value.split_whitespace().collect(); | ||
let (entry_position, entry_points, entry_username); | ||
if let Some(&position) = values.get(0) { | ||
entry_position = position; | ||
} else { | ||
bail!("No leaderboard position"); | ||
} | ||
if let Some(&points) = values.get(1) { | ||
entry_points = points; | ||
} else { | ||
bail!("No points in a leaderboard entry"); | ||
} | ||
entry_username = values | ||
.iter() | ||
.skip(2) | ||
.map(|x| x.to_string()) | ||
.collect::<Vec<_>>() | ||
.join(" "); | ||
|
||
Ok(Self { | ||
position: entry_position.replace(r")", "").parse().chain_err(|| { | ||
format!("Error parsing a leaderboard position: {}", entry_position) | ||
})?, | ||
points: entry_points | ||
.parse() | ||
.chain_err(|| format!("Error parsing points: {}", entry_points))?, | ||
username: entry_username, | ||
}) | ||
} | ||
} | ||
|
||
#[derive(PartialEq, Debug)] | ||
pub struct Leaderboard { | ||
pub entries: Vec<LeaderboardEntry>, | ||
} | ||
|
||
impl FromIterator<LeaderboardEntry> for Leaderboard { | ||
fn from_iter<T: IntoIterator<Item = LeaderboardEntry>>(iter: T) -> Self { | ||
Self { | ||
entries: iter.into_iter().collect(), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<Vec<String>> for Leaderboard { | ||
type Error = Error; | ||
|
||
fn try_from(value: Vec<String>) -> Result<Self> { | ||
let entries: Result<Vec<LeaderboardEntry>> = value | ||
.iter() | ||
.map(|entry| LeaderboardEntry::try_from(entry.as_ref())) | ||
.collect(); | ||
match entries { | ||
Ok(entries) => Ok(Leaderboard::from_iter(entries)), | ||
Err(e) => bail!(e.chain_err(|| "One of the entries failed parsing")), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
#[test] | ||
fn try_from_for_leaderboard_entry() { | ||
let entry = "1) 3693 betaveros"; | ||
let expected_entry = { | ||
let username = "betaveros".to_owned(); | ||
LeaderboardEntry { | ||
position: 1, | ||
points: 3693, | ||
username, | ||
} | ||
}; | ||
let result_entry = LeaderboardEntry::try_from(entry); | ||
match result_entry { | ||
Ok(result) => assert_eq!(expected_entry, result), | ||
Err(e) => panic!("error parsing the entry: {}", e.description()), | ||
} | ||
} | ||
|
||
#[test] | ||
fn try_from_for_leaderboard_entry_anonymous_user() { | ||
let entry = "3) 3042 (anonymous user #1510407)"; | ||
let expected_entry = { | ||
let username = "(anonymous user #1510407)".to_owned(); | ||
LeaderboardEntry { | ||
position: 3, | ||
points: 3042, | ||
username, | ||
} | ||
}; | ||
let result_entry = LeaderboardEntry::try_from(entry); | ||
match result_entry { | ||
Ok(result) => assert_eq!(expected_entry, result), | ||
Err(e) => panic!("error parsing the entry: {}", e.description()), | ||
} | ||
} | ||
|
||
#[test] | ||
fn try_from_string_vec_for_leaderboard() { | ||
let entries: Vec<String> = vec!["1) 3693 betaveros", "2) 14 me"] | ||
.iter() | ||
.map(|&x| x.to_owned()) | ||
.collect(); | ||
let expected_leaderboard = Leaderboard { | ||
entries: vec![ | ||
LeaderboardEntry { | ||
position: 1, | ||
points: 3693, | ||
username: "betaveros".to_owned(), | ||
}, | ||
LeaderboardEntry { | ||
position: 2, | ||
points: 14, | ||
username: "me".to_owned(), | ||
}, | ||
], | ||
}; | ||
match Leaderboard::try_from(entries) { | ||
Ok(result) => assert_eq!(expected_leaderboard, result), | ||
Err(e) => panic!("Test case failed {}", e.description()), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
mod aoc_client; | ||
mod get_leaderboard; | ||
mod input_cache; | ||
|
||
pub use aoc_client::AocClient; | ||
pub use get_leaderboard::GetLeaderboard; | ||
pub use input_cache::InputCache; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use crate::domain::errors::*; | ||
use crate::domain::Description; | ||
use crate::domain::{Submission, SubmissionResult}; | ||
use crate::infrastructure::aoc_api::aoc_client_impl::InputResponse; | ||
|
||
pub trait AocClient { | ||
fn submit_answer(&self, submission: Submission) -> Result<SubmissionResult>; | ||
fn get_description<Desc>(&self, year: &u16, day: &u8) -> Result<Desc> | ||
where | ||
Desc: Description + TryFrom<reqwest::blocking::Response>; | ||
fn get_input(&self, year: &u16, day: &u8) -> InputResponse; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
use crate::domain::errors::*; | ||
use crate::domain::Leaderboard; | ||
|
||
pub trait GetLeaderboard { | ||
fn get_leaderboard(&self, year: u16) -> Result<Leaderboard>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
use crate::domain::errors::*; | ||
|
||
pub trait InputCache { | ||
fn save(input: &str, year: u16, day: u8) -> Result<()>; | ||
fn load(year: u16, day: u8) -> Result<String>; | ||
fn clear() -> Result<()>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
pub mod aoc_api; | ||
mod cli_display; | ||
mod configuration; | ||
mod http_description; | ||
mod input_cache; | ||
|
||
pub use crate::infrastructure::cli_display::CliDisplay; | ||
pub use crate::infrastructure::configuration::Configuration; | ||
pub use crate::infrastructure::http_description::HttpDescription; | ||
pub use crate::infrastructure::input_cache::FileInputCache; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use crate::Configuration; | ||
|
||
const AOC_URL: &str = "https://adventofcode.com"; | ||
|
||
#[derive(Debug)] | ||
pub struct AocApi { | ||
http_client: reqwest::blocking::Client, | ||
configuration: Configuration, | ||
} | ||
|
||
mod aoc_api_impl; | ||
pub mod aoc_client_impl; | ||
pub mod get_leaderboard_impl; |
Oops, something went wrong.