drracket代写:CSC104 Project II

; CSC104 2017 Fall, Project II.
;
; A Program to Model and Visualize the Spread of an Infection.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; AFTER YOU HAVE IMPLEMENTED THE ENTIRE PROGRAM, play with it, adjusting the settings.
;
; Try to find some settings that produce a delicate balance of the spread of infection:
; when running it a few times with those settings can produce visibly different outcomes.
; Also try large and small values, and view the effects.
; Write a couple of paragraphs here summarizing some of your findings:
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; IMPLEMENTATION REQUIREMENTS.
; For each function: uncomment any commented-out check-expects, study them and the description
; of the function, and if you are asked to implement or fix the function then do so.
; Uncomment any definitions that use those functions.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Some list functions.

(require (only-in racket take drop)) ; Imports two fast list functions.
; take : list number → list
; drop : list number → list
; These function take a list, and a number for how many elements to keep or remove:
(check-expect (take (list “gnu” “fox” “bee”) 2) (list “gnu” “fox”))
(check-expect (drop (list “gnu” “fox” “bee”) 2) (list “bee”))

; A function to make a list with a repeated element.
; constant-list : number any → list
(check-expect (constant-list 3 “cat”) (list “cat” “cat” “cat”))
(check-expect (constant-list 3 “cat”) (repeated identity “cat” 3))

; Fix constant-list.
(define (constant-list a-length an-element)
(list))

; Functions to move elements from the front to the back of a list, or vice versa.
; left-cycle : list number → list
; right-cycle : list number → list
#;(check-expect (left-cycle (list “gnu” “fox” “bee”) 0) (list “gnu” “fox” “bee”))
#;(check-expect (left-cycle (list “gnu” “fox” “bee”) 1) (list “fox” “bee” “gnu”))
#;(check-expect (left-cycle (list “gnu” “fox” “bee”) 2) (list “bee” “gnu” “fox”))
#;(check-expect (left-cycle (list “gnu” “fox” “bee”) 2) (append (list “bee”) (list “gnu” “fox”)))
#;(check-expect (right-cycle (list “gnu” “fox” “bee”) 0) (list “gnu” “fox” “bee”))
#;(check-expect (right-cycle (list “gnu” “fox” “bee”) 1) (list “bee” “gnu” “fox”))
#;(check-expect (right-cycle (list “gnu” “fox” “bee”) 2) (list “fox” “bee” “gnu”))
#;(check-expect (right-cycle (list “gnu” “fox” “bee”) 2)
(append (drop (list “gnu” “fox” “bee”) (- 3 2))
(take (list “gnu” “fox” “bee”) (- 3 2))))

; Implement left-cycle.

; Implement right-cycle.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Managing the Statuses of the Subjects in the Simulation.

; The behaviour of the simulation depends on three numeric settings:
;
; Virulence – how likely an infectable person becomes infected
; Duration – how long an infected person stays infected
; Immunity – how long a person stays immune after an infection ends
;
; Those settings will be stored and passed around in a list.
;
; Using setting names for functions that access them helps us keep track of the order.
;
; virulence : list → number
; duration : list → number
; immunity : list → number

(check-expect (virulence (list 20 10 15)) 20)
(define virulence first)
; That could also have been defined by:
#;(define (virulence some-settings) (first some-settings))

#;(check-expect (duration (list 20 10 15)) 10)
; Implement duration.

#;(check-expect (immunity (list 20 10 15)) 15)
; Implement immunity.

#;(check-expect (virulence-duration-immunity 20 10 15) (list 20 10 15))
; Implement virulence-duration-immunity.

; Some initial settings for the simulation.
#;(define initial-settings (virulence-duration-immunity 20 10 15))

; Infection Status.
;
; A person is either:
;
; Infectable.
; This is represented by zero, and shown as a blue dot.
;
; Infected, with a certain number of days of infection left.
; This is represented by a number which is the *negative* of the number
; of days of infection left, and shown as a red dot.
;
; Immune, with a certain number of days of immunity left.
; This is represented by a *positive* number which is the number of days
; of immunity left, and shown as a green dot.

; Predicates to make reading the code more meaningful:
; infectable? : number → boolean
; infected? : number → boolean
; immune? : number → boolean

#;(check-expect (infectable? -2) #false)
#;(check-expect (infectable? 0) #true)
#;(check-expect (infectable? 3) #false)
#;(check-expect (infected? -2) #true)
#;(check-expect (infected? 0) #false)
#;(check-expect (infected? 3) #false)
#;(check-expect (immune? -2) #false)
#;(check-expect (immune? 0) #false)
#;(check-expect (immune? 3) #true)

; Implement those three functions, and use them where appropriate when checking statuses later.

; A function to produce the initial list of unifected statuses, except for one person on the edge
; of the wrap-around world who starts infected for Duration days.
; initial-statuses : number number list → list
#;(define (initial-statuses width height some-settings)
(local [(define dots (* width height))
(define dots/2 (quotient dots 2))]
(append (constant-list dots/2 0)
(list (- (duration some-settings)))
(constant-list (- (- dots dots/2) 1) 0))))
#;(check-expect (initial-statuses 2 3 (virulence-duration-immunity 20 10 15))
(list 0 0
0 -10
0 0))

; A function to produce the colour representing a person’s status.
; status-colour : number → list
#;(check-expect (status-colour -2) (list 100 0 0))
#;(check-expect (status-colour 0) (list 0 0 100))
#;(check-expect (status-colour 3) (list 0 100 0))

; Fix status-colour.
#;(define (status-colour a-status)
(cond [(infected? a-status) (list 0 0 0)]
[else (list 0 0 0)]))

; A function to update a person’s status.
;
; update-status : number → number
;
; If infectable, stay infectable.
; If infected, become infected for one less day, except if that makes the person uninfected
; then they become immune for the number of days of immunity specified in the settings.
; If immune, become immune for one less day.

#;(check-expect (update-status 0 (virulence-duration-immunity 20 10 15)) 0)
#;(check-expect (update-status -2 (virulence-duration-immunity 20 10 15)) -1)
#;(check-expect (update-status -1 (virulence-duration-immunity 20 10 15)) 15)
#;(check-expect (update-status 3 (virulence-duration-immunity 20 10 15)) 2)

; Fix update-status.
#;(define (update-status a-status some-settings)
a-status)

; A function to update everyone’s duration of infection and immunity in a list of statuses.
; update-statuses : list-of-numbers → list-of-numbers
#;(check-expect (update-statuses (list 3 -1 0 -2)
(virulence-duration-immunity 20 10 15))
(list 2 15 0 -1))
#;(check-expect (update-statuses (list 3 -1 0 -2)
(virulence-duration-immunity 20 10 15))
(local [(define (update a-status)
(update-status a-status
(virulence-duration-immunity 20 10 15)))]
(list (update 3)
(update -1)
(update 0)
(update -2))))

; Fix update-statuses.
#;(define (update-statuses some-statuses some-settings)
some-statuses)

; A function to possibly infect a subject.
;
; Produce the status representing an infection of Duration days if:
; the status represents someone infectable,
; neighbour-0 or neighbour-1 or neighbour-2 or neighbour-3 is a status for someone infected, and
; the Virulence is more than this randomly chosen number: (random 100).
; Otherwise: leave the subject alone.
;
; infect : number number number number number list → number

#;(check-expect (or (infectable? (infect 0 -1 2 -3 4 (virulence-duration-immunity 20 10 15)))
(infected? (infect 0 -1 2 -3 4 (virulence-duration-immunity 20 10 15))))
#true)
#;(check-expect (infectable? (infect 0 -1 2 -3 4 (virulence-duration-immunity 0 10 15)))
#true)
#;(check-expect (infected? (infect 0 -1 2 -3 4 (virulence-duration-immunity 100 10 15)))
#true)
#;(check-expect (infectable? (infect 0 1 -2 3 -4 (virulence-duration-immunity 0 10 15)))
#true)
#;(check-expect (infected? (infect 0 1 -2 3 -4 (virulence-duration-immunity 100 10 15)))
#true)
#;(check-expect (infect 0 1 -2 3 -4 (virulence-duration-immunity 100 10 15))
(- (duration (virulence-duration-immunity 100 10 15))))
#;(check-expect (infect 0 -1 2 -3 4 (virulence-duration-immunity 100 10 15))
(- (duration (virulence-duration-immunity 100 10 15))))
#;(check-expect (infect -1 0 -2 3 -4 (virulence-duration-immunity 20 10 15))
-1)
#;(check-expect (infect 2 0 3 -4 5 (virulence-duration-immunity 20 10 15))
2)
#;(check-expect (infect 0 1 0 2 0 (virulence-duration-immunity 20 10 15))
0)

; Due to the randomness, a check-expect that tests that an infectable subject can be infected
; is a bit tricky to do properly. Here is an approach that should rarely fail.
#;(define (try-to-infect unused-parameter)
(infect 0 -1 2 -3 4 (virulence-duration-immunity 20 10 15)))
#;(check-expect (member? (- (duration (virulence-duration-immunity 20 10 15)))
(map try-to-infect (range 0 10000 1)))
#true)
#;(check-expect (member? 0
(map try-to-infect (range 0 10000 1)))
#true)

; Fix infect.
#;(define (infect subject neighbour-0 neighbour-1 neighbour-2 neighbour-3
some-settings)
subject)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Settings Management and big-bang Functions.
;
; These are all implemented: you can uncomment any commented-out definitions, and the big-bang
; expression that is at the end of the file.

; The width and height of the world.
(define WIDTH 100)
(define HEIGHT 100)

; The current settings and list of statuses are bundled together in a list.
(define settings-and-statuses list)
(define settings first)
(define statuses second)

(require (only-in racket map)) ; Imports a version of map that works with more than two lists.

; Update each person’s status, possibly infecting some of them, based on the settings.
; day-tick : list → list
#;(define (day-tick the-settings-and-statuses)
(local [(define the-statuses (statuses the-settings-and-statuses))
(define the-settings (settings the-settings-and-statuses))
(define (infector status n-0 n-1 n-2 n-3)
(infect status n-0 n-1 n-2 n-3 the-settings))]
(settings-and-statuses the-settings
(update-statuses (map infector
the-statuses
(left-cycle the-statuses 1)
(right-cycle the-statuses 1)
(left-cycle the-statuses WIDTH)
(right-cycle the-statuses WIDTH))
the-settings))))

; An image showing name and number, separated by a colon and space.
; setting->image : string number → image
(define (setting->image name number)
(string->image (string-append name “: ” (number->string number)) 16 “black”))

; An image of the grid of the statuses, with settings drawn underneath.
; draw-statuses : list → image
#;(define (draw-statuses the-settings-and-statuses)
(above (colors->image (map status-colour (statuses the-settings-and-statuses))
WIDTH HEIGHT)
(setting->image “virulence” (virulence (settings the-settings-and-statuses)))
(setting->image “duration” (duration (settings the-settings-and-statuses)))
(setting->image “immunity” (immunity (settings the-settings-and-statuses)))))

; Update the settings and reset the statuses, when a key is pressed.
; change-settings : list string → list
#;(define (change-settings the-settings-and-statuses a-key)
(local [(define the-settings (settings the-settings-and-statuses))
(define (with-new-settings virulence-change duration-change immunity-change)
(local [(define new-settings (virulence-duration-immunity
(+ (virulence the-settings) virulence-change)
(+ (duration the-settings) duration-change)
(+ (immunity the-settings) immunity-change)))]
(settings-and-statuses new-settings (initial-statuses WIDTH HEIGHT new-settings))))]
(cond [(equal? a-key “1”) (with-new-settings -1 0 0)]
[(equal? a-key “2”) (with-new-settings +1 0 0)]
[(equal? a-key “3”) (with-new-settings 0 -1 0)]
[(equal? a-key “4”) (with-new-settings 0 +1 0)]
[(equal? a-key “5”) (with-new-settings 0 0 -1)]
[(equal? a-key “6”) (with-new-settings 0 0 +1)]
[else (with-new-settings 0 0 0)])))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Uncomment the big-bang expression and run the file to play with the simulation!
;
; You can adjust the settings by pressing one of the keys: 1, 2, 3, 4, 5, or 6.
; Pressing any other key starts the simulation again, without changing the current settings.

#;(big-bang (settings-and-statuses initial-settings (initial-statuses WIDTH HEIGHT initial-settings))
[on-tick day-tick]
[to-draw draw-statuses]
[on-key change-settings])