Skip to content

Commit e6c9c39

Browse files
committed
feat: allow do download input
1 parent 681ec65 commit e6c9c39

File tree

6 files changed

+72
-5
lines changed

6 files changed

+72
-5
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SESSION_COOKIE_ENV_VAR=

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
.idea
44
/resources/*/inputs/*.in
55
/resources/*/outputs/*.out
6-
Cargo.lock
6+
Cargo.lock
7+
.env

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9+
aoc-client = "0.2.0"
910
clap = { version = "4.5.21", features = ["derive"]}
11+
dotenv = "0.15.0"
1012
regex = "1.11.1"
1113
itertools = "0.13.0"

src/main.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ use crate::utils::year::Year;
33
use clap::{Parser, Subcommand};
44
use std::fmt::{Display, Formatter};
55
use std::time::{Duration, Instant};
6+
use aoc_client::{AocClient};
7+
use dotenv::dotenv;
68
use utils::day_number::DayNumber;
79
use utils::file_system::{read_input, read_output};
810
use utils::year::Year::Year2023;
11+
use crate::utils::file_system::write_input;
912

1013
mod solutions;
1114
mod utils;
@@ -24,8 +27,12 @@ struct Args {
2427

2528
#[derive(Subcommand, Debug)]
2629
enum Command {
30+
/// Run solver for given puzzle
2731
#[clap(short_flag = 's')]
2832
Solve,
33+
/// Downloads and saves input for given puzzle
34+
#[clap(short_flag = 'i')]
35+
Input,
2936
}
3037

3138
fn parse_day(s: &str) -> Result<u8, String> {
@@ -37,6 +44,8 @@ fn parse_day(s: &str) -> Result<u8, String> {
3744
}
3845

3946
fn main() {
47+
dotenv().ok();
48+
4049
let cli = Args::parse();
4150
let command = cli.command.unwrap_or(Command::Solve);
4251
let day = cli.day.unwrap_or(1);
@@ -48,20 +57,26 @@ fn main() {
4857

4958
match command {
5059
Command::Solve => solve(&day_number, year),
60+
Command::Input => download_input(day_number, year),
5161
}
5262
}
5363

5464
fn solve(day_number: &DayNumber, year: Year) {
5565
let solution = solution(&day_number, year.clone());
5666

57-
let input = read_input(day_number.to_string().as_str(), year.clone());
67+
let input = match read_input(day_number.to_string().as_str(), year.clone()) {
68+
Ok(val) => val,
69+
Err(_) => panic!("Failed to read input. Download it first."), // todo better handle errors
70+
};
71+
5872
let output = read_output(day_number.to_string().as_str(), year);
5973

6074
let expected: Vec<String> = output
6175
.unwrap_or(String::from(""))
6276
.lines()
6377
.map(|s| s.to_string())
6478
.collect();
79+
6580
let expected_part_one = expected.first();
6681
let expected_part_two = expected.get(1);
6782

@@ -75,6 +90,30 @@ fn solve(day_number: &DayNumber, year: Year) {
7590
);
7691
}
7792

93+
fn download_input(day_number: DayNumber, year: Year) {
94+
let input = read_input(day_number.to_string().as_str(), year.clone());
95+
96+
match input {
97+
Ok(_) => println!("Input already exists."),
98+
Err(_) => {
99+
println!("Downloading...");
100+
let session = std::env::var("SESSION_COOKIE_ENV_VAR").unwrap();
101+
102+
let client = AocClient::builder()
103+
.session_cookie(session).unwrap()
104+
.year(year.clone() as i32).unwrap()
105+
.day(u32::from(day_number)).unwrap()
106+
.build().unwrap();
107+
108+
let input = client.get_input().unwrap();
109+
110+
write_input(&day_number.to_string(), year.clone(), &input).unwrap();
111+
112+
println!("Input downloaded");
113+
}
114+
}
115+
}
116+
78117
fn run<'a>(
79118
part: &str,
80119
solve_fn: &'a dyn Fn() -> String,

src/utils/day_number.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ impl From<DayNumber> for u8 {
3737
}
3838
}
3939

40+
impl From<DayNumber> for u32 {
41+
fn from(day: DayNumber) -> Self {
42+
day.number as u32
43+
}
44+
}
45+
4046
impl Display for DayNumber {
4147
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
4248
write!(f, "{:0>2}", self.number)

src/utils/file_system.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::utils::year::Year;
22
use std::fmt::{Display, Formatter};
3+
use std::fs;
34
use std::fs::read_to_string;
45

56
enum ResourceType {
@@ -22,8 +23,14 @@ impl Display for ResourceType {
2223
}
2324
}
2425

25-
pub fn read_input(day: &str, year: Year) -> String {
26-
read(ResourceType::Inputs, day, year).unwrap()
26+
pub fn write_input(day: &str, year: Year, data: &str) -> std::io::Result<()> {
27+
let file_path = build_path(ResourceType::Inputs, day, year);
28+
29+
fs::write(file_path, data)
30+
}
31+
32+
pub fn read_input(day: &str, year: Year) -> std::io::Result<String> {
33+
read(ResourceType::Inputs, day, year)
2734
}
2835

2936
pub fn read_output(day: &str, year: Year) -> std::io::Result<String> {
@@ -36,7 +43,18 @@ pub fn read_example(day: &str, year: Year) -> String {
3643
}
3744

3845
fn read(resource_type: ResourceType, day: &str, year: Year) -> std::io::Result<String> {
39-
let file_path = format!("resources/{}/{}/{}.in", year, resource_type, day);
46+
let file_path = build_path(resource_type, day, year);
4047

4148
read_to_string(file_path)
4249
}
50+
51+
fn build_path(resource_type: ResourceType, day: &str, year: Year) -> String {
52+
let format = match resource_type {
53+
ResourceType::Inputs => "in",
54+
ResourceType::Outputs => "out",
55+
#[cfg(test)]
56+
ResourceType::Examples => "in",
57+
};
58+
59+
format!("resources/{}/{}/{}.{}", year, resource_type, day, format)
60+
}

0 commit comments

Comments
 (0)