Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added a command to print all the stars and the ASCII art #49

Merged
merged 5 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Generated by Cargo
# will have compiled files and executables
/target/
\.vscode

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Expand Down
5 changes: 0 additions & 5 deletions .vscode/settings.json

This file was deleted.

12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ instead of the webpage. So far `elv` supports:
- downloading a riddle's input for a given year and day
- submitting answers to a riddle
- automatically guessing what part of the riddle you want to submit
- showing your star progress for a given year including the ASCII art
- getting the official leaderboards for a given year
- guessing the year and day of a riddle based on the current date
- caching `AoC` responses whenever possible, so you minimize your
Expand Down Expand Up @@ -259,6 +260,17 @@ elv submit -y 2021 -d 1 <SOLUTION> one
elv submit -y 2021 -d 1 <SOLUTION> two
```

### Getting the stars and the ASCII art

`elv` can print the ASCII art and the stars you have collected so far
for each year:

```console
elv stars # prints the stars for the latest year
elv stars <YEAR> # prints the stars for the given year
elv stars 2019 # prints the stars for the year 2019
```

### Getting the leaderboard

#### Getting the leaderboard for this year
Expand Down
22 changes: 20 additions & 2 deletions src/application/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ impl ElvCli {
CliCommand::Leaderboard { token_args, year } => {
handle_get_leaderboard(token_args, year)
}
CliCommand::Stars { year } => handle_get_stars(year),
CliCommand::ClearCache => handle_clear_cache_command(),
CliCommand::ListDirs => handle_list_dirs_command(),
CliCommand::Config { cmd } => match cmd {
Expand Down Expand Up @@ -170,14 +171,22 @@ impl ElvCli {
}
}

fn handle_get_leaderboard(token_args: TokenArgs, year: Option<u16>) {
fn handle_get_leaderboard(token_args: TokenArgs, year: Option<i32>) {
let driver = get_driver(Some(token_args), None);
match driver.get_leaderboard(year.unwrap_or_else(|| chrono::Utc::now().year() as u16)) {
match driver.get_leaderboard(year.unwrap_or_else(determine_year)) {
Ok(text) => println!("{text}"),
Err(e) => eprintln!("❌ Error when getting the leaderboards: {}", e.to_string()),
}
}

fn handle_get_stars(year: Option<i32>) {
let driver = get_driver(None, None);
match driver.get_stars(year.unwrap_or_else(determine_year)) {
Ok(stars) => println!("{}", stars),
Err(e) => eprintln!("❌ Failure: {}", e.to_string()),
}
}

fn handle_get_config() {
match Driver::get_config_map() {
Ok(map) => map
Expand All @@ -201,6 +210,15 @@ impl ElvCli {
Ok((best_guess_date.year, best_guess_date.day))
}

fn determine_year() -> i32 {
let est_now = chrono::Utc::now() - chrono::Duration::hours(4);
if est_now.month() == 12 {
est_now.year()
} else {
est_now.year() - 1
}
}

fn build_configuration(
token_args: Option<TokenArgs>,
terminal_width: Option<usize>,
Expand Down
25 changes: 20 additions & 5 deletions src/application/cli/cli_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ pub struct RiddleArgs {
/// The day of the challenge
///
/// If you do not supply a day, the current day of the month will be used
/// (if the current month is December). If the current month is not December
/// and you do not supply the year, the previous year will be used.
/// (if the current month is December). If the current month is not December,
/// the application will not be able to guess the day.
#[arg(short, long, value_parser = clap::value_parser!(i32))]
pub day: Option<i32>,
}
Expand Down Expand Up @@ -122,8 +122,20 @@ pub enum CliCommand {
///
/// If you do not supply a year, this command will pull the leaderboards from
/// the latest event.
#[arg(short, long, value_parser = clap::value_parser!(u16))]
year: Option<u16>,
#[arg(short, long, value_parser = clap::value_parser!(i32))]
year: Option<i32>,
},

/// ⭐ Show the stars page
///
/// This command downloads the star page and displays the ASCII pattern along with
/// the stars.
Stars {
/// The year of the challenge
///
/// If you do not supply a year, this command will pull the leaderboards from
/// the latest event.
year: Option<i32>,
},

/// 🗑️ Clear the cache
Expand All @@ -141,7 +153,10 @@ pub enum CliCommand {

/// 🔍 Show and edit the configuration
///
/// Governs the configuration of the application.
/// Token management
/// You can save your Advent of Code token using this command.
/// See `elv --help` and `elv config set --help` for more information.
#[command(verbatim_doc_comment)]
Config {
#[clap(subcommand)]
cmd: ConfigSubcommand,
Expand Down
6 changes: 4 additions & 2 deletions src/application/cli/cli_config_subcommand.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#[derive(clap::Parser, Debug)]
pub enum ConfigSubcommand {
/// Lists all the configuration keys and their respective values
/// List all the configuration keys and their respective values
#[command(visible_aliases = ["l"])]
List {},

/// Updates the value of the specified configuration key
/// Update the value of the specified configuration key
///
/// Examples:
/// elv config set aoc.token abscdft123145
/// elv config set cli.output_width 150
///
/// See `elv config list` for all available configuration keys.
#[command(verbatim_doc_comment)]
Set {
/// The updated configuration key
Expand Down
10 changes: 9 additions & 1 deletion src/application/cli/cli_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@ use super::cli_command::CliCommand;
/// 🎄 Your Advent of Code CLI 🎄
///
/// This CLI is a tool to help you with your Advent of Code challenges.
///
/// Token management
/// You need an Advent of Code session token to interact with its API. `elv`
/// does not support authentication to the API on its own, so you need to
/// get your token beforehand, and pass it to `elv`. There are a number of ways
/// of setting the token. See `elv config set --help` if you want to set it
/// once and not be bothered by passing it to the `--token` parameter every
/// time you use the CLI.
#[derive(Debug, clap::Parser)]
#[command(version)]
#[command(version, verbatim_doc_comment)]
pub struct CliInterface {
#[command(subcommand)]
pub command: CliCommand,
Expand Down
2 changes: 2 additions & 0 deletions src/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ mod leaderboard;
pub mod ports;
mod riddle_date;
mod riddle_part;
pub(crate) mod solved_parts;
pub mod stars;
mod submission;
mod submission_result;
mod submission_status;
Expand Down
1 change: 1 addition & 0 deletions src/domain/ports.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub(crate) mod aoc_client;
pub(crate) mod errors;
pub(crate) mod get_leaderboard;
pub(crate) mod get_stars;
pub(crate) mod input_cache;
3 changes: 3 additions & 0 deletions src/domain/ports/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub enum AocClientError {

#[error("Network error")]
NetworkError(#[from] reqwest::Error),

#[error("Failed to get stars page")]
GetStarsError,
}

impl From<LeaderboardError> for AocClientError {
Expand Down
2 changes: 1 addition & 1 deletion src/domain/ports/get_leaderboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ use super::super::leaderboard::Leaderboard;
use super::errors::AocClientError;

pub trait GetLeaderboard {
fn get_leaderboard(&self, year: u16) -> Result<Leaderboard, AocClientError>;
fn get_leaderboard(&self, year: i32) -> Result<Leaderboard, AocClientError>;
}
5 changes: 5 additions & 0 deletions src/domain/ports/get_stars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use super::{super::stars::Stars, errors::AocClientError};

pub trait GetStars {
fn get_stars(&self, year: i32) -> Result<Stars, AocClientError>;
}
6 changes: 6 additions & 0 deletions src/domain/solved_parts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SolvedParts {
None,
One,
Both,
}
18 changes: 18 additions & 0 deletions src/domain/stars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use super::solved_parts::SolvedParts;

pub struct Stars {
pub stars: Vec<SolvedParts>,
pub pattern: Vec<String>,
}

impl Stars {
pub fn new(stars: Vec<SolvedParts>, pattern: Vec<String>) -> Self {
Stars { stars, pattern }
}
}

impl core::fmt::Display for Stars {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}\n", self.pattern.join("\n").to_string())
}
}
1 change: 1 addition & 0 deletions src/infrastructure/aoc_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ mod aoc_api_impl;
pub mod aoc_client_impl;
pub mod find_riddle_part_impl;
pub mod get_leaderboard_impl;
pub mod get_stars_impl;
2 changes: 1 addition & 1 deletion src/infrastructure/aoc_api/find_riddle_part_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{domain::RiddlePart, infrastructure::find_riddle_part::FindRiddlePart
use super::AocApi;

impl FindRiddlePart for AocApi {
fn find(&self, year: i32, day: i32) -> Result<RiddlePart, anyhow::Error> {
fn find_unsolved_part(&self, year: i32, day: i32) -> Result<RiddlePart, anyhow::Error> {
let description = Self::get_description::<HttpDescription>(&self, year, day)?;
match (description.part_one_answer(), description.part_two_answer()) {
(None, _) => Ok(RiddlePart::One),
Expand Down
2 changes: 1 addition & 1 deletion src/infrastructure/aoc_api/get_leaderboard_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl AocApi {
}

impl GetLeaderboard for AocApi {
fn get_leaderboard(&self, year: u16) -> Result<Leaderboard, AocClientError> {
fn get_leaderboard(&self, year: i32) -> Result<Leaderboard, AocClientError> {
let url = reqwest::Url::parse(&format!("{}/{}/leaderboard", AOC_URL, year))?;
let mut response = self.http_client.get(url).send()?.error_for_status()?;
let mut body = String::from("");
Expand Down
Loading