Context: My professor wants me to set up an autograder for his class (for gradescope) and I am encountering some difficulties when putting the results into a results.json file
Error:
write-json: expected argument of type <legal JSON key value>; given: "tests"
context...:
.../json/main.rkt:132:2: loop
.../json/main.rkt:94:0: write-json*
.../source/autograder.rkt:48:0: grade
body of '#%mzc:autograder
Code:
(define results-file "../results/results.json")
(define (starter-data-entry name)
(make-hash `(("score" . 0) ("max_score" . 0) ("output" . "Will be manually graded") ("name" . ,name))))
(define results-data
(make-hash `(("tests" . ,(for/list ([i (in-range 1 13)])
(starter-data-entry (format "question~a" i)))))))
(define (grade-question fn-hw fn-sol input-cases id max-score)
(let* ([results
(for/fold ([acc (cons 0 0)]) ; acc is a pair (total-tests . passed-tests)
([input (in-list input-cases)])
(let* ([hw-result (apply fn-hw input)]
[sol-result (apply fn-sol input)]
[total-tests (car acc)]
[passed-tests (cdr acc)])
(if (equal? hw-result sol-result)
(cons (+ total-tests 1) (+ passed-tests 1))
(cons (+ total-tests 1) passed-tests))))]
[total-tests (car results)]
[passed-tests (cdr results)]
[score (floor (* max-score (/ passed-tests total-tests)))]
[output (format "Passed ~a out of ~a test cases." passed-tests total-tests)])
(hash-update! results-data "tests"
(lambda (tests)
(map (lambda (test)
(if (equal? (hash-ref test "name") id)
(hash "name" id "score" score "max_score" max-score "output" output)
test))
tests)))
(void)))
(define (write-json-file filepath data)
(call-with-output-file filepath
(lambda (out)
(write-json data out))
#:exists 'replace))
(define (grade)
(grade-question hw:sequence sol:sequence (sequence-test-case-generator 50) "question1" 7)
(grade-question hw:string-append-map sol:string-append-map (string-append-map-test-case-generator 50) "question2" 7)
; ... more calls to grade-question, not really relevant
(display results-data)
(write-json-file results-file results-data)
)
(grade)
I have a working solution (but it is pretty scuffed - print the results-data hash to std-out and then pass that into a python file that parses the string and writes to the json file), but I am just curious what I am doing wrong because I really cannot figure it out.
There's a lot of holes in my racket knowledge and I'm not that proficient in it so maybe it is due a silly mistake I am unaware of; I know its not a permissions issue with writing to the file and the results.json file already exists. I have tried to write the template "results-data" to the json file also - which gave me the same error - so the hash-update! in grade-question shouldn't be a part of the issue.
The primary JSON library for Racket represents JSON objects as hash tables with symbols as keys, not strings.
Trivial example:
#lang racket/base
(require json)
(define (starter-data-entry name)
(hasheq 'score 0 'max_score 0 'output "Will be manually graded" 'name name))
(write-json (starter-data-entry "foo"))