auto submit answers lol

This commit is contained in:
xenia 2020-12-02 03:49:57 -05:00
parent d3988a432d
commit b55369a332
5 changed files with 88 additions and 9 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.envrc .envrc
/inputs/* /inputs/*
!/inputs/.gitkeep !/inputs/.gitkeep
/.status.rktd

View File

@ -1,19 +1,26 @@
#lang racket #lang racket
;; library to interact with the AoC API and track solutions progress
(require net/uri-codec net/http-client) (require net/uri-codec net/http-client)
(provide aoc-fetch-input aoc-fetch-challenge aoc-submit-answer) (provide aoc-fetch-input aoc-fetch-challenge aoc-submit-answer
aoc-complete? aoc-set-complete!)
(define *host* "adventofcode.com") (define *host* "adventofcode.com")
(define *status-file* ".status.rktd")
;; generates API paths
(define/contract (puzzle-path year day endpoint) (define/contract (puzzle-path year day endpoint)
(-> string? string? (or/c "input" "answer" false/c) path?) (-> string? string? (or/c "input" "answer" false/c) path?)
(define base (build-path "/" year "day" day)) (define base (build-path "/" year "day" day))
(if endpoint (build-path base endpoint) base)) (if endpoint (build-path base endpoint) base))
;; sets up necessary headers for API
(define (make-headers session) (define (make-headers session)
(list (string-append "Cookie: session=" session) (list (string-append "Cookie: session=" session)
"Content-Type: application/x-www-form-urlencoded")) "Content-Type: application/x-www-form-urlencoded"))
;; http request helper
(define (aoc-request year day endpoint session [method 'GET] [data #f]) (define (aoc-request year day endpoint session [method 'GET] [data #f])
(define (parse-headers hlist) (define (parse-headers hlist)
(for/list ([h (in-list hlist)]) (for/list ([h (in-list hlist)])
@ -43,10 +50,12 @@
(port->bytes content))])) (port->bytes content))]))
(do-request (path->string (puzzle-path year day endpoint)) (make-headers session) method data)) (do-request (path->string (puzzle-path year day endpoint)) (make-headers session) method data))
;; gets the input file for a challenge
(define/contract (aoc-fetch-input year day session) (define/contract (aoc-fetch-input year day session)
(-> string? string? string? input-port?) (-> string? string? string? input-port?)
(aoc-request year day "input" session)) (aoc-request year day "input" session))
;; submits an answer to the server
(define/contract (aoc-submit-answer year day session part answer) (define/contract (aoc-submit-answer year day session part answer)
(-> string? string? string? (or/c 1 2 "1" "2") string? (or/c symbol? bytes?)) (-> string? string? string? (or/c 1 2 "1" "2") string? (or/c symbol? bytes?))
(define data `((level . ,(~a part)) (define data `((level . ,(~a part))
@ -55,11 +64,41 @@
(port->bytes (aoc-request year day "answer" session 'POST (alist->form-urlencoded data)))) (port->bytes (aoc-request year day "answer" session 'POST (alist->form-urlencoded data))))
(match resp (match resp
[(pregexp #px"That's the right answer") 'answer-correct] [(pregexp #px"That's the right answer")
(aoc-set-complete! day part)
'answer-correct]
[(pregexp #px"That's not the right answer") 'answer-incorrect] [(pregexp #px"That's not the right answer") 'answer-incorrect]
[(pregexp #px"Did you already complete it?") 'already-completed] [(pregexp #px"Did you already complete it?")
(aoc-set-complete! day part)
'already-completed]
[x x])) [x x]))
;; fetches the HTML page for a challenge
(define/contract (aoc-fetch-challenge year day session) (define/contract (aoc-fetch-challenge year day session)
(-> string? string? string? input-port?) (-> string? string? string? input-port?)
(aoc-request year day #f session)) (aoc-request year day #f session))
;; helper to generate entries for the challenge status file
(define (day+part->key day part)
(when (string? day)
(set! day (string->number day)))
(when (string? part)
(set! part (string->number part)))
(cons day part))
;; get the challenge status file
(define (aoc-get-status)
(cond [(file-exists? *status-file*)
(call-with-input-file *status-file* read)]
[else '()]))
;; is a challenge complete already?
(define (aoc-complete? day part)
(set-member? (aoc-get-status) (day+part->key day part)))
;; mark a challenge as completed
(define (aoc-set-complete! day part)
(define status (set-add (aoc-get-status) (day+part->key day part)))
(call-with-output-file
*status-file* (lambda (out) (write status out))
#:mode 'binary #:exists 'replace))

25
scripts/aoc.rkt Normal file
View File

@ -0,0 +1,25 @@
#lang racket
;; utilities for every challenge script
(require "aoc-lib.rkt")
(provide answer dbg)
;; in-expression debug print, uwu
(define (dbg x)
(pretty-write x)
x)
;; submit a solution to the server if not already submitted
(define (answer day part answer)
(printf "answer ~a.~a: ~s\n" day part answer)
(unless (aoc-complete? day part)
(printf "submit? [Y/n]: ")
(match (string-downcase (string-trim (read-line)))
[(or "" "y" "yes")
(printf "submitting...\n")
(define resp
(aoc-submit-answer (getenv "AOC_YEAR") (~a day) (getenv "AOC_SESSION") (~a part)
(~a answer)))
(printf "server responded: ~a\n" resp)]
[_ (printf "not submitting\n")])))

View File

@ -2,7 +2,8 @@
#lang racket #lang racket
(require racket/runtime-path (require racket/runtime-path
scribble/text (rename-in scribble/text/output [output scribble-output])) scribble/text (rename-in scribble/text/output [output scribble-output])
"aoc-lib.rkt")
(define-runtime-path template "template.rktrkt") (define-runtime-path template "template.rktrkt")
@ -17,11 +18,14 @@
(eval `(include/text (file ,file))))) (eval `(include/text (file ,file)))))
(scribble-output output-exp port)) (scribble-output output-exp port))
(command-line (command-line
#:program "make-day" #:program "make-day"
#:args (day) #:args (day)
;; make solution file
(call-with-output-file (call-with-output-file
(format "~a.rkt" day) (format "~a.rkt" day)
(lambda (out) (lambda (out)
(eval-template (path->string template) (hash 'day day) out)))) (eval-template (path->string template) (hash 'day day) out)))
;; get input
(define in (aoc-fetch-input (getenv "AOC_YEAR") day (getenv "AOC_SESSION")))
(call-with-output-file (build-path "inputs" day) (lambda (out) (copy-port in out))))

View File

@ -1,20 +1,30 @@
#lang racket #lang racket
(require "scripts/aoc.rkt")
;; solution for day @day ;; solution for day @day
;; helper functions here ;; helper functions here
(define (part1 input)
;; ...
(void))
(define (part2 input)
;; ...
(void))
(module+ test (module+ test
(require rackunit) (require rackunit)
;; tests here ;; tests here
(void)) (displayln "no tests :("))
(module+ main (module+ main
(define input (file->... "inputs/@day")) (define input (file->... "inputs/@day"))
;; part 1 ;; part 1
;; ... (answer @day 1 (part1 input))
;; part 2 ;; part 2
;; ... (answer @day 2 (part2 input))
(displayln "meow")) (displayln "meow"))