drracket代写: CSC104 Project I

;; The first three lines of this file were inserted by DrRacket. They record metadata
;; about the language level of this file in a form that our tools can easily process.
#reader(lib “2017-fall-reader.rkt” “csc104”)((modname Sneeze) (compthink-settings #hash((prefix-types? . #f))))
; CSC104 2018 Winter, Project I : A Program to Model and Visualize the Spread of an Infection
; ===========================================================================================
; Due: Tuesday, March 13th at 6PM.

; What To Do
; ———-
; 1. 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.
;
; Also, when you encounter definitions that use those functions, uncomment those definitions.
;
; 2. After you have implemented the entire program: run it.
;
; You should see a window appear with an animation of an infection spreading across “the world”:
; each coloured dot represents a person, and the colour represents the status of their infection.
;
; Underneath the animation are the values of the three “parameters” that the simulation depends on.
; Press one of the keys “1”, “2”, “3”, “4”, “5”, or “6”: those adjust the parameters and restart
; the simulation. Pressing any other key restarts the simulation without affecting the parameters.
; Because the simulation involves some randomness, the results might change.
;
; 3. Explore some ranges of the parameters.
;
; In particular, keep increasing or decreasing one of the parameters until there is a clear visibly
; different progress of the simulation, and/or of its long-term outcome. Can you find a value where,
; when you restart the simulation a few times, it sometimes has one outcome, and sometimes another?
;
; Write a couple of paragraphs here summarizing some of the results of your exploration:
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

; Some List Functions
; ——————-

; 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 4 “cat”) (repeated identity “cat” 4))

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

; Functions ‘take’ and ‘drop’ from the full racket language.
; 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”))
; We’ll get fast versions of them from the full racket language:
(require (only-in racket take drop)) ; Imports two fast list functions.

; Use those functions in ‘left-cycle’ and ‘right-cycle’ below.

; 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.
; If the person has one day of infection left, we’ll say they are “almost well”.
;
; 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
; almost-well? : 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? -1) #true)
#;(check-expect (infected? 0) #false)
#;(check-expect (infected? 3) #false)
#;(check-expect (almost-well? -2) #false)
#;(check-expect (almost-well? -1) #true)
#;(check-expect (almost-well? 0) #false)
#;(check-expect (almost-well? 3) #false)
#;(check-expect (immune? -2) #false)
#;(check-expect (immune? 0) #false)
#;(check-expect (immune? 3) #true)

; Implement those four 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 by one day.
;
; update-status : number → number
;
; If infectable, stay infectable.
; If infected, become infected for one less day, except: if almost well, 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 -4 -1 0 5 -2)
(virulence-duration-immunity 20 10 15))
(list 2 -3 15 0 4 -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

; Some tests, in situations that aren’t affected by randomness:
#;(check-expect (infected? (infect 0 1 0 2 0 (virulence-duration-immunity 100 10 15)))
#false)
#;(check-expect (infectable? (infect 0 2 0 0 1 (virulence-duration-immunity 100 10 15)))
#true)
#;(check-expect (infectable? (infect 0 -1 -3 0 2 (virulence-duration-immunity 0 10 15)))
#true)
#;(check-expect (infected? (infect 0 1 2 4 -3 (virulence-duration-immunity 100 10 15)))
#true)
#;(check-expect (infectable? (infect 0 -1 -2 -3 0 (virulence-duration-immunity 0 10 15)))
#true)
#;(check-expect (infected? (infect 0 -2 3 -4 -1 (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 100 10 15))
-1)
#;(check-expect (infect 2 0 2 3 -4 (virulence-duration-immunity 100 10 15))
2)

; 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 for you already: 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])