Git Product home page Git Product logo

advent-of-code-runner's Introduction

๐ŸŽ… advent-of-code-runner ๐ŸŽ„

A Node.Js CLI solution generator and runner for advent of code.

npm npm node-current codecov

๐Ÿคถ Features

  • Quickly and easily scaffolds an empty directory, creating all required solution files.
  • Runs your solutions (both sync and async) and measures performance.
  • Downloads and caches puzzle input files.
  • Submits answers to advent of code.
  • Tracks submitted answers and prevents duplicate submissions.
  • Stores and outputs statistics to the CLI or your README file.
  • Rate limits submissions to prevent timeout penalties.
  • Tracks your progress and knows which puzzle to run.
  • Uses ECMAScript modules (ESM).

๐ŸฆŒ Table of Contents

๐Ÿฅ› Installation

In an empty directory or a freshly created github repository run the following command

npx advent-of-code-runner init 

You will be asked a few questions, then the following contents will be generated:

your-repository-folder/
โ”œโ”€โ”€ aocr-data.json
โ”œโ”€โ”€ inputs/
โ”œโ”€โ”€ node_modules/
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ package.lock.json
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ day_01.js
โ”‚   โ”œโ”€โ”€ day_02.js
โ”‚   โ”œโ”€โ”€ ...
โ”‚   โ””โ”€โ”€ day_25.js
โ”œโ”€โ”€ .env
โ””โ”€โ”€ .gitignore

Authentication Token

advent of code generates puzzle inputs unique to your account. In order to download inputs and submit answers this CLI needs to store your advent of code authentication token. The token will be stored in a .env file in your project directory. This .env file should not be committed to source control. When you run the init command a .gitignore file is generated which ignores .env files, so your token is safe by default.

Finding your Authentication Token

The authentication token is stored in an advent of code cookie. Navigate to advent of code, and sign in to your account. Once signed in open up your browsers development tools, find the cookies for adventofcode.com and copy the value of the "session" cookie.

Post Installation

Once you run the init command you are ready to start solving the puzzles. Navigate to src/ folder and open up day_01.js. Navigate to the levelOne function and add your code. Run the solve command to see what answer your code returns, if you're happy with the answer run the submit command to see if you got the right answer. From there you can move on to level 2 of day 1 or solve the puzzles in any order you wish. Good luck and have fun!

๐ŸŒŸ Usage

Run the following commands from the root of your repository.

Note: If a command which executes your code (solve or submit) is taking a long time to complete, you can cancel it any any time by pressing Ctrl + c in your terminal.

solve [day] [level]

Runs your code for a specific puzzle, downloads the input file (if not already cached), measures how long your code takes to run, and outputs your answer. This does not submit the answer to advent of code.

This command has different behavior based on which arguments you pass:

No Arguments
npm run solve

If the command is run without any arguments, the CLI will find and solve the next puzzle you have not submitted a correct answer for. This is very useful if you solve puzzles in the order of the advent calendar.

Example:

  • If you've correctly answered days 1-4, then day 5 level 1 will be solved.
  • If you've correctly answered days 1-7 and day 8 level 1, then day 8 level 2 will be solved.
One Argument
npm run solve [day]

If you run the command with just the day argument, then the level one of the days puzzle will be solved.

Example:

  • To solve day 16 level 1: npm run solve 16
  • To solve day 4 level 1: npm run solve 4
Two Arguments
npm run solve [day] [level]

If you run the command with the day and the level argument, then the specified puzzle will be solved.

Example:

  • To solve day 23 level 2: npm run solve 24 2
  • To solve day 15 level 1: npm run solve 15 1

submit [day] [level]

The same behavior as the solve command, however your answer will be submitted to advent of code. Additionally the progress table in your README file will be updated.

This command has different behavior based on which arguments you pass:

No Arguments
npm run submit

If the command is run without any arguments, the CLI will find and submit the next puzzle you have not yet submitted a correct answer for. This is very useful if you solve puzzles in the order of the advent calendar.

One Argument
npm run submit [day]

If you run the command with just the day argument, then the level one of the days puzzle will be submitted.

Example:

  • To submit day 12 level 1: npm run submit 12
  • To submit day 20 level 1: npm run submit 20
Two Arguments
npm run submit [day] [level]

If you run the command with the day and the level argument, then the specified puzzle will be submitted.

Example:

  • To submit day 3 level 2: npm run submit 3 2
  • To submit day 14 level 1: npm run submit 14 1

stats [--save]

Generates a table showing your current statistics for the year. Shows you which puzzles you have completed, how many attempts you made for each puzzle, and the fastest recorded runtime for that puzzle. The table additionally displays your completion percentage for the year, the average number of attempts, and the average runtime.

If you run the command without the --save argument then the table will be printed to the console

npm run stats

If you run the command with the --save argument then the table will be saved to your README file.

npm run stats -- --save

Note you must add -- separator between the command name and the --save argument. See this stackoverflow question for more info.

auth

Creates or updates the .env file with your advent of code authentication token. This is a useful command if you checkout your repository on a new machine, since the .env file is not committed to source control and wont be present on the new machine.

npm run auth

import <day> <level> <answer> [--no-confirm]

Stores the correct answer to a puzzle which was solved outside of advent-of-code-runner. This allows you to use advent-of-code-runner even if you already submitted answers with different tools. Before this command you couldn't let advent-of-code-runner know that you had solved a puzzle already. Once you've imported an answer you will probably want to update the corresponding solution file to add your existing code.

Note: All imported puzzles are set to a runtime of 999 seconds. After importing an answer, run the solve command to update the puzzles runtime to a real value.

Running without the --no-confirm flag is the default behavior. You will be asked to confirm when importing any puzzles which already exist in your aocr-data.json file.

npm run import <day> <level> <answer>

Running with the --no-confirm flag will skip any confirmation for overwriting existing data.

npm run -- import --no-confirm <day> <level> <answer> 

Handling different answer types

Answers are stored as strings, so you usually don't need to wrap your answer with quotes. However there are certain answers which will need special care:

  • An answer with whitespace: wrap in quotes npm run import 1 1 'an answer with spaces'
  • An answer which is a negative number: use -- to escape npm run -- import -- 1 1 -12345

Examples:

  • Import answer 'asdf' for day 10 level 1: npm run import 10 1 asdf
  • Import answer 999100 for day 7 level 2: npm run import 7 2 999100
  • Import answer -4000 for day 1 level 1 and skip confirmation: npm run -- import --no-confirm -- 1 1 -4000

Bulk importing

If you have already solved some puzzles, it would be tedious to manually run the import command a bunch of times. The wiki has a guide for bulk importing puzzle answers using basic linux command line tools.

Projects init before 1.7.0

Projects created using npx advent-of-code-runner init prior to version 1.7.0 will not have an npm script for the import command. You fix this by modifying your package.json file and adding an npm script for the import command:

"scripts": {
  "solve": "advent-of-code-runner solve",
  "submit": "advent-of-code-runner submit",
  "stats": "advent-of-code-runner stats",
  "auth": "advent-of-code-runner auth",
  "help": "advent-of-code-runner help",
  "import": "advent-of-code-runner import"
},

Updating your README file after import

After running the import command you may notice your README progress table does not automatically update. You can fix this by running the stats command with the --save option.

npm run stats -- --save

help

Outputs the help text for the cli

npm run help

โ›„ Solution Files

The init command generates a solution file for each day of advent of code. This is where you will add your code to compute the answer to each puzzle.

Each solution file is expected to export two functions:

  • levelOne({ input: string, lines: string[] }) -> string|number|Promise<string>|Promise<number>
  • levelTwo({ input: string, lines: string[] }) -> string|number|Promise<string>|Promise<number>

These functions:

  • Must return a string or a number.
  • Can be sync or async

Arguments

Solution functions are invoked with a single argument, an object containing the following fields:

  • input: string: A string containing the raw, unprocessed puzzle input. Provided for flexibility and custom parsing.
  • lines: string[]: An array of strings containing the each line of the puzzle input. Provided for convenience and speed.

Depending on the puzzle and its input you might need to parse string values into integers.

๐ŸŒจ๏ธ Caching

This CLI downloads puzzles inputs only once and saves them to the inputs/ folder. If your input file becomes corrupted you can force a re-download by deleting the file and running the solve or submit command. Additionally the CLI tracks the answers you submit to ensure you don't attempt to re-submit a duplicate answer to a question.

๐ŸŽ Misc File Information

aocr-data.json

This file stores your progress. Every time you submit an answer, it is stored in this file to prevent duplicate submissions and track statistics. Additionally it stores the fastest recorded runtime for each puzzle. You should not edit this file manually. This file should be committed to source control.

.ratelimits.json

This file stores rate limit information used when querying the advent of code website. The creator of the website has requested automated tools such as this CLI are conservative in the number of requests made to the website. This file tracks when the last request was made and the CLI uses this data to prevent requests from occurring too frequently. This file is ignored in source control.

.env

This file stores your authentication token, it should not be committed to source control. See the Authentication Token section for more information.

README.md

If you view the plain text markdown, you might notice a section that looks like:

<!--Please do not delete the following comments, they are required to save your stats to this file.-->
<!--START_AUTOGENERATED_COMPLETION_PROGRESS_SECTION-->
<!--END_AUTOGENERATED_COMPLETION_PROGRESS_SECTION-->

The CLI requires this section so it can continually update your readme with your progress table (if using the submit or the stats command).

๐ŸŽ„ Advanced Configuration

You can customize the behavior of this CLI by using the following options in your .env file. Please keep in mind this is where your authentication token is stored and this file should not be committed to source control.

Option Name Accepted Values Default Effect
AOC_DISABLE_README_AUTO_SAVE_PROGRESS see yn package false If enabled, the README file will not be automatically updated with the progress table during the solve or submit commands. You can still update the README manually with the stats command.
AOC_SUPPRESS_FESTIVE see yn package false If enabled, the CLI will not add emojis to the console output.
AOC_LOG_LEVEL error, warn, info, verbose, debug, silly warn Controls the verbosity of logging, a higher level is useful for development

Example .env file

This example modifies the default .env file created by the init command. It sets the AOC_DISABLE_README_AUTO_SAVE_PROGRESS option to true, which disables the progress table being automatically saved to the README file. It also sets the AOC_SUPPRESS_FESTIVE to true which disables emojis in the console output.

# This is an authentication token to advent of code.
# It is a SECRET and should be treated like a password.
# That means this .env file should NOT be committed to source control!
#
# If you created this project using advent-of-code-runner init, 
# then your .gitignore already includes this file, your secret is safe.
AOC_AUTHENTICATION_TOKEN=asdfasdfasdfasdf
AOC_DISABLE_README_AUTO_SAVE_PROGRESS=true
AOC_SUPPRESS_FESTIVE=true

โ„๏ธ Example

I am using this CLI for my own advent of code solutions. You can refer to this project as a real world example of how to use this CLI.

Spoiler Warning: This project contains my solutions to advent of code 2022.

๐Ÿ”” Automation Compliance

This CLI does follow the automation guidelines on the /r/adventofcode community wiki. Specifically:

  • Outbound calls are throttled to every five minutes in rateLimitDecorator.js
  • Once inputs are downloaded, they are cached locally in getPuzzleInput.js. If you suspect your input is corrupted, you can manually request a fresh copy by deleting the downloaded file.
  • The User-Agent header in api.js is set to https://github.com/beakerandjake/advent-of-code-runner by beakerandjake
  • Submitted answers are tracked per puzzle and duplicate submissions are prevented in submit.js.

advent-of-code-runner's People

Contributors

beakerandjake avatar dependabot[bot] avatar github-actions[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

advent-of-code-runner's Issues

Dont require token until absolutely necessary

Currently in order to run most commands a .env file with the auth token must be present, without this token the commands will fail. The .env file is secret and is not meant to be checked into source control. This creates an issue where a users repository can only be ran on their machine.

As a user solves problems their input files are downloaded and cached, and should be committed to source control. Since the input file is present an auth token is not required to solve a puzzle with a cached input file. If another user wants to download someone else's repository and run their solutions they will not be able to even though they technically should be able to.

Change the solve commands to not require auth immediately, instead only attempt to grab the auth token when downloading an input file.

Store version in aocr-data.json

Store version of application that the data was init with, this will help with potential migrations in the future if there are breaking changes.

Require .env file?

Minimum needed is year / token. If these are not present bail.

Don't allow override via command line?

How handle multiple years in one user repo if add this?

Add progress command.

Potential things to output:

  • Fastest solution runtime ever
  • % of year successfully completed
  • Average solution runtime.
  • % correct on first attempt
  • Average number of attempts
  • num of completed problems
  • most failed attempts

Store rate limit data elsewhere

This should probably be stored in an ignored file in the users repository instead of being checked into source control via the user data file. It's annoying to have git changes every time you fail a problem, also you can easily beat the rate limit by just reverting the file.

Init command overwrites .gitignore

If the user has a .gitignore file which does not include the required .env line, the init command will replace the entire file contents instead of appending.

Correct answer is not set

After getting a problem correct, the correct answer field is not set in the user data file, instead it is added to the incorrect answers array.

Recover and resolve certain errors via cmd

Some errors we can provide a fix for. Errors like SolutionFileNotFound or SolutionFileMissingFunction. If these errors are raised, we can prompt the user asking them if they want to fix the problem.

For

  • SolutionFileNotFound - create the solution file
  • SolutionFileMissingFunction - add the function to the end of the file.

Manual set answer command

If user has submitted answers outside of CLI there isn't a way for cli to store the fact that the puzzle has been answered. Add command which lets the user manually set the correct answer for a puzzle.

Enhance CLI Actions

Add decorator / chain of responsibility / builder ability to CLI actions. Instead of passing actual action to the command pass in a special function. The function takes a chain of validators / decorators as its first param and the actual command action as its second param.

The function will create an args object from whatever commander passes to it, then it will invoke each function in the chain of validators lineally. If a function is a validator it can throw an exception if a precondition is not met. A function can also mutate the args passed into it by returning an object, this object will be the args that is passed to the next function and finally to the actual action function.

If none of the validators in the chain throw an exception the action will be invoked with the args object.

Add autosolve / autosubmit command.

Instead of the user having to specify which problem to answer, instead automatically choose the earliest unsolved problem and run that one.

Ex. If they have completed all parts of days 1,2,3,6,7,8 and only part 1 of day 4 and part 2 of day 5, then the command would choose day 4 part 2 because that's the earliest problem they have not solved.

Better data storage

Lots of io when reading / writing to data store json file. Could potentially cache the contents and invalidate cache on write. Might need to watch file for changes too.

Could potentially move to a different solution like sqlite but that would increase module dependencies and size.

Add test command

This command will re-execute every solution file which has a correct answer. It will compare the returned answer with the correct answer and fail the test if the answers do not match.

This can help them ensure that their code still works when they perform refactoring or changes.

Store fastest runtime per problem.

If the user successfully answers the problem, store the execution time. Update this whenever the user re-solves the problem and gets a faster execution time.

Init command - ask user questions

Get user input during the init command. Something interactive like eslint init or npm init. Probably need library like inquirer.

  • Inform user that init will overwrite existing files in the repository - Y/N
  • Bail if no package.json is present - Tell them to run npm init.
  • Warn if package.json isn't of type module - Ask them if they want a fix?
  • Update package.json and add scripts to run
  • Ask for Year
  • Ask for Token
  • Create .env file (use template file)
  • Create .gitignore file (use template file)
  • Create README.MD file (use template file)
  • Create solution files - Ask for folder (default /src/solutions)

Add watch command

Watches for changes in solution files and executes that file. Something like nodemon.

Update Rate Limit on API Failure

An api call is an api call, update the rate limit even if an error is thrown during the api call (for example a bad response)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.