<commit_before>#lang racket
;; TODO: clean up
;; TODO: Somethings are fragile with respect to paths, current directory
(require 
  file/zip
  net/smtp
  net/base64
  openssl
  net/head
  net/mime
  "gradebook.rkt"
  "students.rkt"
  "graders.rkt"
  "problem-set.rkt"
  "config.rkt")
(provide
  send-assignments-to-graders
  ;grader-assignment
  ;grader
  ;email-grader
  sanity-check-grades
  post-grades)

;; grader x (listof group)
(struct grader-assignment (grader ps groups) #:prefab)
;; (listof user) x path
(struct group (users dir) #:prefab)

;; send-assignments-to-graders
;; (problem-set) -> void
;; assigns graders in tutors.txt a rougly equal number of assignments
;; to grade from each problem-set. each grader is sent a seperate email
;; for each problem-set.

;; The email will be in the following format:
;;
;; To: <grader-email> 
;; From: <head-ta-email>
;; Subject: <course-name> Grading, <problem-set>
;; Body: <any>
;; Attachments: <problem-set>.zip
;; 
;; <problem-set>.zip will contain a folder named <username> for
;; each student. The folder will contain all material handed in for
;; <problem-set>
(define (send-assignments-to-graders problem-sets)
  (let* ([gras (flatten (map assign-graders problem-sets))]
         [files (map tar-assignments gras)]) 
    (for-each (lambda (x y) (printf "Would email ~a ~a" x y)) gras files)
    #;(for-each email-grader gras files)
    (for-each delete-file files)))

;; TODO: Run local smtp server to test email functions
#;(module+ test
  (require rackunit)
  (parameterize ([server-dir "/tmp/"]
                 [graders (list (grader "grader1" "grader1" "<EMAIL>")
                                (grader "grader2" "grader2" "<EMAIL>"))])
    (for-each (compose (lambda (dir) 
                         (unless (directory-exists? dir) (make-directory* dir))
                         (unless (directory-exists? (build-path dir "grading")) 
                            (make-directory* (build-path dir "grading")))
                         (with-output-to-file (build-path dir "grading" "text.rkt")
                                              (thunk (display 120))
                           #:exists 'truncate/replace)
                         (with-output-to-file (build-path dir "handin.rkt")
                           (thunk (display 120))
                           #:exists 'truncate/replace)) 
                       (curry build-path "/tmp/test") symbol->string)
      '(test1 test2 test3 test4 test5 test6))
    (send-assignments-to-graders (list (problem-set "test" "test" 1234 1234))))
  (delete-directory/files "/tmp/test"))

;; assign-graders
;; problem-set -> (listof grader-assignment)
;; assigns each grader an about equal  number of users based on the
;; number of turned-in assignments
(define (assign-graders ps) 
  (let* ([users (map (lambda (x) 
                       (call-with-values (thunk (split-path x)) 
                         (lambda (z path y)
                            (group (string->students (path->string path)) 
                                   (build-path (problem-set-dir ps) path)))))
                 (directory-list (build-path (server-dir) (problem-set-dir ps))))]
         [users users]
         [graders (graders)]
    (map (lambda (grader) 
           (grader-assignment grader ps (filter (lambda (x) (eq? (student-grader) (grader-user grader))) users)))
         graders))))<commit_msg>Fixed typoes<commit_after>#lang racket
;; TODO: clean up
;; TODO: Somethings are fragile with respect to paths, current directory
(require 
  file/zip
  net/smtp
  net/base64
  openssl
  net/head
  net/mime
  "gradebook.rkt"
  "students.rkt"
  "graders.rkt"
  "problem-set.rkt"
  "config.rkt")
(provide
  send-assignments-to-graders
  ;grader-assignment
  ;grader
  ;email-grader
  sanity-check-grades
  post-grades)

;; grader x (listof group)
(struct grader-assignment (grader ps groups) #:prefab)
;; (listof user) x path
(struct group (users dir) #:prefab)

;; send-assignments-to-graders
;; (problem-set) -> void
;; assigns graders in tutors.txt a rougly equal number of assignments
;; to grade from each problem-set. each grader is sent a seperate email
;; for each problem-set.

;; The email will be in the following format:
;;
;; To: <grader-email> 
;; From: <head-ta-email>
;; Subject: <course-name> Grading, <problem-set>
;; Body: <any>
;; Attachments: <problem-set>.zip
;; 
;; <problem-set>.zip will contain a folder named <username> for
;; each student. The folder will contain all material handed in for
;; <problem-set>
(define (send-assignments-to-graders problem-sets)
  (let* ([gras (flatten (map assign-graders problem-sets))]
         [files (map tar-assignments gras)]) 
    (for-each (lambda (x y) (printf "Would email ~a ~a" x y)) gras files)
    #;(for-each email-grader gras files)
    (for-each delete-file files)))

;; TODO: Run local smtp server to test email functions
#;(module+ test
  (require rackunit)
  (parameterize ([server-dir "/tmp/"]
                 [graders (list (grader "grader1" "grader1" "<EMAIL>")
                                (grader "grader2" "grader2" "<EMAIL>"))])
    (for-each (compose (lambda (dir) 
                         (unless (directory-exists? dir) (make-directory* dir))
                         (unless (directory-exists? (build-path dir "grading")) 
                            (make-directory* (build-path dir "grading")))
                         (with-output-to-file (build-path dir "grading" "text.rkt")
                                              (thunk (display 120))
                           #:exists 'truncate/replace)
                         (with-output-to-file (build-path dir "handin.rkt")
                           (thunk (display 120))
                           #:exists 'truncate/replace)) 
                       (curry build-path "/tmp/test") symbol->string)
      '(test1 test2 test3 test4 test5 test6))
    (send-assignments-to-graders (list (problem-set "test" "test" 1234 1234))))
  (delete-directory/files "/tmp/test"))

;; assign-graders
;; problem-set -> (listof grader-assignment)
;; assigns each grader an about equal  number of users based on the
;; number of turned-in assignments
(define (assign-graders ps) 
  (let* ([users (map (lambda (x) 
                       (call-with-values (thunk (split-path x)) 
                         (lambda (z path y)
                            (group (string->students (path->string path)) 
                                   (build-path (problem-set-dir ps) path)))))
                 (directory-list (build-path (server-dir) (problem-set-dir ps))))]
         [graders (graders)])
    (map (lambda (grader) 
           (grader-assignment grader ps (filter (lambda (x) (eq? (student-grader) (grader-user grader))) users)))
         graders)))
{'fraction_non_alphanumeric': 0.13624299616632263, 'fraction_numerical': 0.007667354762606901, 'mean_word_length': 2.2975206611570247, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2942805', 'n_tokens_mistral': 2184, 'n_tokens_neox': 2073, 'n_words': 606}