advent-of-code/src/holt59/aoc/__main__.py
Mikaël Capelle d61d9d4559
Some checks failed
continuous-integration/drone/push Build is failing
2024 day 24.
2024-12-24 12:33:53 +01:00

146 lines
3.9 KiB
Python

import argparse
import importlib
import logging
import logging.handlers
import sys
from datetime import datetime
from pathlib import Path
from .base import BaseSolver
from .utils.api import FileHandlerAPI, LoggerAPIHandler, ProgressAPI, dump_answer
from .utils.files import SimpleFileHandler
from .utils.progress import ProgressNone, ProgressTQDM
def find_input_file(folder: Path, day: int, target: Path | None):
if (path := folder.joinpath(f"day{day}.txt")).exists():
return path
if (
target is not None
and (path := folder.joinpath(f"day{day}_v{target}.txt")).exists()
):
return path
try:
return next(path for path in sorted(folder.glob(f"day{day}*.txt")))
except StopIteration:
...
return folder.joinpath(f"day{day}.txt")
def main():
parser = argparse.ArgumentParser("Holt59 Advent-Of-Code Runner")
parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode")
parser.add_argument("-t", "--test", action="store_true", help="test mode")
parser.add_argument("-a", "--api", action="store_true", help="API mode")
parser.add_argument(
"-o",
"--output",
type=Path,
default=Path("files"),
help="output folder for created files",
)
parser.add_argument(
"-u", "--user", type=str, default="holt59", help="user input to use"
)
parser.add_argument(
"--stdin",
action="store_true",
default=False,
help="use stdin as input",
)
parser.add_argument(
"-i",
"--input",
type=Path,
default=None,
help="input to use (override user and test)",
)
parser.add_argument("-y", "--year", type=int, help="year to run", default=2024)
parser.add_argument("day", type=int, help="day to run")
args = parser.parse_args()
verbose: bool = args.verbose
api: bool = args.api
test: bool = args.test
stdin: bool = args.stdin
user: str = args.user
files_output: Path = args.output
input_path: Path | None = args.input
year: int = args.year
day: int = args.day
logging.basicConfig(
level=logging.INFO if verbose else logging.WARNING,
handlers=[LoggerAPIHandler()] if api else None,
)
if input_path is None or not input_path.exists():
input_path = find_input_file(
Path(__file__).parent.joinpath(
"inputs", "tests" if test else user, str(year)
),
day,
input_path,
)
assert input_path.exists(), f"{input_path} missing"
solver_class: type[BaseSolver] = importlib.import_module(
f".{year}.day{day}", __package__
).Solver
solver = solver_class(
logging.getLogger("AOC"),
verbose=verbose,
year=year,
day=day,
progress=ProgressAPI()
if api
else ProgressTQDM()
if verbose
else ProgressNone(), # type: ignore
files=FileHandlerAPI(files_output)
if api and verbose
else SimpleFileHandler(logging.getLogger("AOC"), files_output)
if verbose
else None,
)
data: str
if stdin:
data = sys.stdin.read()
else:
with open(input_path) as fp:
data = fp.read()
start = datetime.now()
last = start
it = solver.solve(data.rstrip())
if it is None:
solver.logger.error(f"no implementation for {year} day {day}")
exit()
for i_answer, answer in enumerate(it):
current = datetime.now()
if api:
dump_answer(
part=i_answer + 1,
answer=answer,
answer_time=current - last,
total_time=current - start,
)
else:
print(
f"answer {i_answer + 1} is {answer} (found in {(current - last).total_seconds():.2f}s)"
)
last = current