33from pathlib import Path
44from typing import Optional
55
6+ import aocd
67import pytest
78import typer
9+ from aocd import AocdError
10+ from aocd .exceptions import PuzzleLockedError
11+ from aocd .models import Puzzle
812
913app = typer .Typer (no_args_is_help = True )
1014
@@ -46,6 +50,35 @@ def run_challenge(day: int, test_data: bool):
4650 module .Challenge (use_test_data = False ).run ()
4751
4852
53+ def get_puzzle_object (day : int ) -> Puzzle | None :
54+ try :
55+ puzzle = Puzzle (year = 2023 , day = day )
56+ return puzzle
57+ except AocdError :
58+ pass
59+ return None
60+
61+
62+ def write_example_data (puzzle , test_input_data ):
63+ try :
64+ test_input_data .write_text (puzzle .examples [0 ].input_data )
65+ except PuzzleLockedError :
66+ echo (
67+ "Failed writing test input data. Puzzle data is not available yet." ,
68+ fg = typer .colors .YELLOW ,
69+ )
70+
71+
72+ def write_input_data (puzzle , real_input_data ):
73+ try :
74+ real_input_data .write_text (puzzle .input_data )
75+ except PuzzleLockedError :
76+ echo (
77+ "Failed writing user input data. Puzzle data is not available yet." ,
78+ fg = typer .colors .YELLOW ,
79+ )
80+
81+
4982@app .command ()
5083def run (
5184 day : int = typer .Argument (..., help = "Day of the challenge to run." ),
@@ -93,10 +126,35 @@ def verify(
93126 raise typer .Exit (1 )
94127 del locals ()["module" ]
95128 pytest_args .append (module .__file__ )
96- print (pytest_args )
97129 pytest .main (pytest_args )
98130
99131
132+ @app .command ()
133+ def submit (
134+ day : int ,
135+ part : str = typer .Argument (
136+ help = "Which part of the solution to submit. "
137+ "You can use numbers 1/2 or letters a/b."
138+ ),
139+ ):
140+ if part in ("1" , "2" ):
141+ part = chr (ord ("a" ) + int (part ) - 1 )
142+ if part not in ("a" , "b" ):
143+ typer .echo (
144+ typer .style (
145+ f"Invalid part { part } . Must be one of 1, 2, a, b." ,
146+ fg = typer .colors .RED ,
147+ )
148+ )
149+ raise typer .Exit (1 )
150+ module = import_challenge_module (day )
151+ if part == "a" :
152+ solution = module .Challenge (use_test_data = False ).part_1 ()
153+ else :
154+ solution = module .Challenge (use_test_data = False ).part_2 ()
155+ aocd .submit (solution , day = day , year = 2023 , part = part )
156+
157+
100158@app .command ()
101159def new_day (
102160 day : int = typer .Argument (help = "Day for which to create a directory." ),
@@ -108,14 +166,15 @@ def new_day(
108166 ),
109167):
110168 """Create a directory for a new day challenge."""
169+ puzzle = get_puzzle_object (day )
111170 if day < 1 or day > 25 :
112171 typer .echo (typer .style ("Day must be between 1 and 25." , fg = typer .colors .RED ))
113172 raise typer .Exit (1 )
114173 destination = Path (f"src/aoc/day_{ day :02} " )
115174 if destination .exists () and not force :
116175 typer .echo (
117176 typer .style (
118- f"Day { day } already exists. Add -f flag if you want to ovewrite " ,
177+ f"Day { day } already exists. Add -f flag if you want to overwrite " ,
119178 fg = typer .colors .RED ,
120179 )
121180 )
@@ -126,26 +185,33 @@ def new_day(
126185 typer .echo (
127186 typer .style (f"Created solution directory for day { day } ." , fg = typer .colors .GREEN )
128187 )
129- if (real_input_data := Path (f"data/{ day :02} _input.txt" )).exists ():
188+ if (
189+ real_input_data := Path (f"data/{ day :02} _input.txt" )
190+ ).exists () and real_input_data .stat ().st_size :
130191 typer .echo (
131192 typer .style (
132193 f"Input data already exists for day { day } ." , fg = typer .colors .YELLOW
133194 )
134195 )
135196 else :
136197 real_input_data .touch ()
198+ if puzzle is not None :
199+ write_input_data (puzzle , real_input_data )
137200 typer .echo (
138201 typer .style (f"Created input data for day { day } ." , fg = typer .colors .GREEN )
139202 )
140- real_input_data .touch ()
141- if (test_input_data := Path (f"data/{ day :02} _test_input.txt" )).exists ():
203+ if (
204+ test_input_data := Path (f"data/{ day :02} _test_input.txt" )
205+ ).exists () and test_input_data .stat ().st_size :
142206 typer .echo (
143207 typer .style (
144208 f"Test input data already exists for day { day } ." , fg = typer .colors .YELLOW
145209 )
146210 )
147211 else :
148212 test_input_data .touch ()
213+ if puzzle is not None and puzzle .examples :
214+ write_example_data (puzzle , test_input_data )
149215 typer .echo (
150216 typer .style (
151217 f"Created test input data for day { day } ." , fg = typer .colors .GREEN
0 commit comments