Created
November 15, 2015 21:40
-
-
Save jadudm/123762e609c8d85ed685 to your computer and use it in GitHub Desktop.
Upper-division enrollment model (20151115)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(define (new-calc allstu | |
;; Grad year... for generating new students | |
;; who will graduate in 2019, by default. | |
#:grad-year [grad-year 2019] | |
;; We assume 20 seats per course, default | |
#:seats-available [seats-available 20] | |
;; Three upper vision courses per term | |
#:num-upper-div [num-upper-div 3] | |
;; Enrollment push from 226 ... represents | |
;; how many new students enter the pipeline | |
#:enroll [enroll 67] | |
;; How many semesters to look forward. | |
#:semesters [semesters 4] | |
#:max-per-term [max-per-term 2] | |
#:cannot-register [cannot-register 5]) | |
;; Grow the number of students we are considering. | |
;; The function "grow-students" takes the student hash and | |
;; adds "enroll" new students to that table. By default, we add | |
;; 67 new students to the table, and all of them need | |
;; three 3xx courses and one 4xx course. | |
(define students (grow-students-by allstu enroll grad-year)) | |
;; For each semester we are considering... | |
;; By default, we consider 4 semesters, or two years from the | |
;; time they take 226. Semester 0 is a fall semester, so even | |
;; semesters are when we run primarily 4xx courses. | |
(for ([sem (range 0 semesters)]) | |
(debug (bracket (format "Semester: ~a" sem))) | |
;; Calcualte how many seats we have available | |
(define seats (* seats-available num-upper-div)) | |
;; Now, make multiple passes through, and handle the students | |
;; with the least time left first. Students with zero semesters | |
;; left are already done. By default, I'm looping with | |
;; the time-left variable being valued from 1 to 8. | |
(for ([time-left (range 1 (add1 (* 2 (- grad-year 2015))))]) | |
(debug (bracket (format "Time Left: ~a" time-left))) | |
;; For each student | |
(for ([(name stu) students]) | |
;; Make sure we're considering a student with the "current" | |
;; amount of time left. This guarantees that seniors get | |
;; first opportunity to ratchet down the courses they need. | |
(when (= (hash-ref stu "time-to-grad") time-left) | |
(debug "~a time left: ~a~n" name time-left) | |
;; The student now has one less semester remaining. | |
;; We knock that down by one. | |
(hash-set! stu "time-to-grad" | |
(sub1 (hash-ref stu "time-to-grad"))) | |
;; If it is an even semester, we're running mostly | |
;; 4xx courses. So, we can run down both 4xx and 3xx courses. | |
;; Students with no time left will have to do this. | |
;; If it is an odd semester, we can only run down 3xx courses. | |
(define types (make-parameter '())) | |
(define labels (make-parameter '())) | |
(cond | |
[(even? sem) | |
(types '("fours" "threes")) | |
(labels '("4xx" "3xx"))] | |
[(odd? sem) | |
(types '("threes")) | |
(labels '("3xx"))]) | |
;; The reason for this flow is so that, in a term where | |
;; 4xx courses are offered, we can let students take a | |
;; 4xx course and have it count as a 3xx in their | |
;; accounting process. | |
(for ([type (types)] | |
[label (labels)]) | |
;; Lets assume students do not take more than | |
;; (by default) two courses in CSC per term. | |
(define stu-per-term max-per-term) | |
;; Lets loop over the number of courses the student has | |
;; remaining. We're going to do this for every type of | |
;; course being considered this term. That means, during | |
;; even terms, we try and take both 4xx and 3xx courses | |
;; (by using seats in a 4xx course as a proxy). | |
(let loop ([remaining (hash-ref stu type)]) | |
;; We now know how many courses in this category | |
;; they need to graduate. When that number | |
;; is greater than zero, and there are seats, and | |
;; they're not overloading... | |
(when (and (> seats 0) | |
(> remaining 0) | |
(> stu-per-term 0) | |
(> (random 100) cannot-register)) | |
;; Remove a seat | |
(set! seats (sub1 seats)) | |
;; Count down on the number per term | |
(set! stu-per-term (sub1 stu-per-term)) | |
;; Lower the req for the student | |
(hash-set! stu type (sub1 (hash-ref stu type))) | |
(debug "\t~a: ~a -> ~a~n" | |
name label (hash-ref stu type)) | |
;; Loop with one less | |
;; We only loop if the "when" statement was true. | |
;; So, if we run out of seats, or we don't need any | |
;; more courses in the 3xx or 4xx category, or | |
;; we can't take any more courses this term (because | |
;; we only advise 2x per term), we're not going to loop. | |
(loop (sub1 remaining))))) | |
)))) | |
;; Now, what's left? | |
(define needed-threes 0) | |
(define needed-fours 0) | |
;; Go through every student in the hash table. | |
(for ([(name stu) students]) | |
;; Find out how many 3xx and 4xx courses they have left. | |
(define threes (hash-ref stu "threes")) | |
(define fours (hash-ref stu "fours")) | |
;; Increment the global count for each category by the number | |
;; that the student still has not taken. | |
(when (> threes 0) | |
(set! needed-threes (+ threes needed-threes))) | |
(when (> fours 0) | |
(set! needed-fours (+ fours needed-fours)))) | |
;; Return two values: the number they need in the 3xx category, | |
;; and the number in the 4xx category. | |
(values needed-threes needed-fours) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment