;; GLOBAL BREEDS
breed [house_centres house_centre]                         ;; Breed for households
breed [people person]                                      ;; Breed for the people in the simulation
breed [school_centres school_centre]                       ;; Breed for the schools in the simulation

;; LINK BREEDS
directed-link-breed [familylinks familylink]               ;; Links created between family members
directed-link-breed [schoollinks schoollink]               ;; Links created between students and schools
undirected-link-breed [friendlinks friendlink]             ;; Links created between friends
directed-link-breed [infectorlinks infectorlink]

;; GLOBAL VARIABLES
globals[
  world_halfwidth                                          ;; World variable to store world width for calculations
  simulation_state                                         ;; Used to record simulation status on interface tab
  temp_spouse_stop_command                                 ;; World variable used to store a stop variable if required by formulas
  temp_spouse_friends_agentset                             ;; World variable used to transmit agentsets between agents
  percentage_susceptible                                   ;; Global percentage susceptible
  percentage_infected                                      ;; Global percentage infected
  percentage_immune                                        ;; Global percentage immune
  percentage_ever_infected                                 ;; Global percentage ever infected
  temp_infector_who                                        ;; Transitory variable to transmit who of infectors
  temp_school_who
  temp_ptype_sou
  temp_ptype_rec
  size_modifier
       ]

;; PERSON VARIABLES
people-own[
  ptype                                                    ;; What type of person (1 = adult 2 = student)
  friends_wanted                                           ;; How many friends person would like
  spouse                                                   ;; Are there two adults in family
  spouse_friends_done                                      ;; Stores if friends already transferred                   
  household_who                                            ;; ID of household that made them
  exclude_friend_set                                       ;; Carrier variable used to exclude friends in the linking stage
  person_infective_status                                  ;; 1 = Susceptible 2 = About to be infected 3 = Infected 4 = Recovered 5 = Immune     
  quarantined                                              ;; 0 = none 1 = off school
  infective_recovery_time                                  ;; Days remaining infective
  ever_infected                                            ;; Whether person ever infected
  infected_by_who                                          ;; If infected, records the who of the infector
  infected_by_school                                       ;; Records the who of the school if infected via this route
  people_infected                                          ;; Number of people infected
  ]

;; SCHOOL VARIABLES
school_centres-own[
  school_percentage_infected                               ;; Not in use
  school_infective_risk                                    ;; Not in use
]

;; HOUSEHOLD VARIABLES
house_centres-own[
  family_percentage_infected                               ;; Not in use
  family_infective_risk]                                   ;; Not in use

;; LINK VARIABLES
familylinks-own [
  link_type]
schoollinks-own [
  link_type]
friendlinks-own [
  link_type]
infectorlinks-own [
  age
  initialcolor]

to reset-world
clear-all-plots
ask people [set ever_infected 0 
            set person_infective_status 1 
            set quarantined 0 
            set infected_by_who 0 
            set infective_recovery_time 0 
            set size 0.5 * size_modifier]
ask infectorlinks [die]
ask people with [ptype = 1] [set color magenta]
ask people with [ptype = 2] [set color violet]
ask school_centres [set size 3 * size_modifier set color blue]
vaccinate-people
infect-initial
end

;; ========================================================================
;; SETUP PROCEDURE
;; Sets up world, households, schools, friends, vaccinations and infections 
;; ========================================================================

to setup
  clear-all
  reset-ticks
        set simulation_state "SETTING UP"
  set world_halfwidth world_width / 2
  let temp_patch_size (500 / world_width)
  resize-world (- world_halfwidth) world_halfwidth (- world_halfwidth) world_halfwidth
  set-patch-size temp_patch_size
  
  set size_modifier 2   
        set simulation_state "CREATING HOUSEHOLDS"
  make-households
  set simulation_state "CREATING SCHOOLS" make-schools
        set simulation_state "CREATING ADULT FRIENDS" make-friends
        set simulation_state "VACCINATING PEOPLE" vaccinate-people
        set simulation_state "INFECTING PEOPLE" infect-initial
  hide-links
  generate-values
        set simulation_state "READY TO GO"
end

;; VACCINATE PROCEDURE
to vaccinate-people
ask people with [person_infective_status = 1]                                                   ;; ASK PEOPLE WHO ARE SUSCEPTIBLE
   [IF random-float 100 < vaccinated_percentage                                                 ;; DECIDE IF TO BE VACCINATED
       [set person_infective_status 5 set color 61]]                                            ;; SET THEIR STATUS AND CHANGE COLOUR
end

;; INITIAL INFECTION PROCEDURE
to infect-initial
IFELSE count people with [person_infective_status = 1] < initial_infections                     ;; IF THE NUMBER OF SUSCEPTIBLES IS < REQUIRED INFECTIONS
   [ask people with [person_infective_status = 1]                                               ;; MAKE ALL SUSCEPTIBLES INFECTED
       [become-activeinfected]]
   [ask n-of initial_infections people with [person_infective_status = 1]                       ;; IF NOT, MAKE CORRECT NUMBER OF THEM INFECTED
       [become-activeinfected]]
end

;; MAKE HOUSEHOLDS PROCEDURE
to make-households
create-house_centres Households                                               ;; Create a number of house_centres equivalent to the slider
[set xcor random-float (world_width - 2) - (world_halfwidth - 1)              ;; Distribute house centres through the world
 set ycor random-float (world_width - 2) - (world_halfwidth - 1)              ;; As above but for y axis
 set shape "house" set color blue set size 0.5 * size_modifier]                ;; Set some display attributes

ask house_centres [let temp_numadults_tomake one-of [1 2 2]                   ;; Ask each of these houses to set number of adults 1 or 2
                   let temp_household_who who                                 ;; Create a temp variable of the creating household number
                   hatch-people temp_numadults_tomake                         ;; Ask house centres to make adults
                        [set shape "circle"                                   ;; Set a shape
                         create-familylink-from myself [set link_type 1]      ;; Link the created people to the household creator
                         set xcor xcor + 1                                    ;; Bump them away from creator                                   
                         set color magenta                                    ;; Set a colour
                         set ptype 1                                          ;; Set a type
                         set size 0.5 * size_modifier                         ;; Change size if necessary
                         set household_who temp_household_who                 ;; Store the household creator as a variable in each adult
                         IFELSE temp_numadults_tomake > 1 [set spouse 1]      ;; Mark if spouse exists
                                                          [set spouse 0]      ;; ...or doesn't
                         set friends_wanted 10 + random 11                    ;; Decide how many friends each adults wants (10-20)
                         set quarantined 0                                    ;; Set quarantine state to 0
                         set person_infective_status 1                        ;; Set their state to susceptible
                        ] 
                   ]
ask house_centres with [count out-link-neighbors > 0]                         ;; Ask house centres with adults to make children
                    [let temp_household_who who                               ;; Create a temp variable of the creating household number
                     hatch-people random 3.1
                       [set shape "circle" 
                        create-familylink-from myself [set link_type 2]
                        set ycor ycor - 1
                        set color violet
                        set ptype 2
                        set size 0.5 * size_modifier
                        set household_who temp_household_who
                        set quarantined 0
                        set person_infective_status 1
                        ]
                   ]
ask house_centres [IF count out-link-neighbors = 0 [die]]                     ;; Ask any house centres with no adults/children to die
ask house_centres [                                                           ;; Ask each household to arrange themselves in a circle
  let temp_xcor xcor                                                          ;; Create a temp variable with house_centre x co-ordinate
  let temp_ycor ycor                                                          ;; Create a temp variable with house_centre x co-ordinate
  if count out-link-neighbors = 0 [stop]                                      ;; Stop if no neighbours
  layout-circle out-link-neighbors 0.5 * size_modifier                        ;; Ask my linked neighbours to layout in a circle radius 1 (around centre of map)
  ask out-link-neighbors [set xcor xcor + temp_xcor                           ;; Move this circle to centre on location of household
    set ycor ycor + temp_ycor]
  ] 
end

;; MAKE SCHOOLS PROCEDURE
to make-schools                                                               
  create-school_centres Schools                                               ;; Make some schools
  [set xcor random-float (world_width - 2) - (world_halfwidth - 1)            ;; Scatter schools around map
    set ycor random-float (world_width - 2) - (world_halfwidth - 1)
    set shape "square"                                                        ;; Setup display variables
    set color blue
    set size 3 * size_modifier]
  
  ask people with [ptype = 2]                                                                  ;; Allocate pupils to schools by asking each pupil
  [IFELSE random 3.1 < 3                                                                       ;; 3 times out of 4...
    [create-schoollink-from min-one-of school_centres [distance myself] [set link_type 3]]     ;; ... to link to nearest school
    [create-schoollink-from one-of school_centres [set link_type 3]]                           ;; ... else link to a random school (inc. nearest)
] 
end

;; MAKE CONTACTS PROCEDURE
to make-friends
 ask people with [ptype = 1]      ;; Ask all adults
 [acquire_adult_spouse_friends    ;; Acquire some of their spouses friends
  make_adult_radius_friends       ;; Then make nearby friends
  make_adult_remaining_friends]   ;; Then make remaining friends
end
  
    to acquire_adult_spouse_friends                                                            ;; run by a 'person' agent, not the observer
     IF spouse = 0 [stop]                                                                      ;; Stop if no spouse
     let temp_my_householdwho household_who                                                    ;; Put my household number in a temporary variable
     ask other people with [ptype = 1 AND household_who = temp_my_householdwho]                ;; Ask my spouse (the one with my household number) to run the following;
   
        [IF count my-friendlinks = 0 [stop]                                                                          ;; Stop if spouse doesn't have friends
         IF spouse_friends_done = 1 [set temp_spouse_stop_command 1 stop]                                            ;; Don't run if friends already transferred other way
            set temp_spouse_friends_agentset n-of (round (0.75 * count friendlink-neighbors)) friendlink-neighbors]  ;; Create a temporary agentset of 75% of my spouses friends  (note this is not my-links command)
         IF temp_spouse_stop_command = 1 [set temp_spouse_stop_command 0                                             ;; Once stop command has triggered, reset this back to 0 then...
                                        stop]                                                                        ;; ...stop as my spouse reported they've already taken my links  
         IF temp_spouse_friends_agentset = 0 [stop]                                                                  ;; If that agentset is empty, stop
     
        let temp_spouse_friends_count count temp_spouse_friends_agentset                                              ;; Create a temporary variable of number of spouse friends
        let temp_friends_count count my-friendlinks                                                                   ;; Count how many friends I already have
        let temp_friends_needed (friends_wanted - temp_friends_count)                                                 ;; Count how many friends I still need
        IF temp_friends_needed < 1 [stop]                                                                             ;; Don't run if no friends needed

        IFELSE temp_spouse_friends_count <= temp_friends_needed                                       
           [create-friendlinks-with temp_spouse_friends_agentset [set link_type 6]]                                   ;; if agentset is smaller than friends needed acquire all of them
           [create-friendlinks-with n-of temp_friends_needed temp_spouse_friends_agentset [set link_type 6]]          ;; if agentset is larger than friends needed acquire the number I need from them
        set spouse_friends_done 1                                                                                       ;; set that I have done my spouse friends transfer to make sure we don't do it back the other way
        end

to make_adult_radius_friends                                                                                       ;; THIS IS A VERY HELPFUL PROCESSING STEP ;;
     let temp_existing_friends_set friendlink-neighbors                                                            ;; Create a temporary set of people already friends with me
     let temp_adults_in_radius people with [ptype = 2] in-radius (world_width * 0.15)                                               ;; Create a temporary set of people within 10 of me
     ask temp_adults_in_radius [set exclude_friend_set 1]                                                          ;; Ask everyone in radius to set their exclusion variable to 1
     ask temp_existing_friends_set [set exclude_friend_set 0]                                                      ;; Ask everyone already my friend to set exclusion variable to 0 
     set temp_adults_in_radius temp_adults_in_radius with [exclude_friend_set = 1]                                 ;; Update the temporary set to be only those not identified as a friend already
     
     let temp_friends_count count my-friendlinks                                                                   ;; Set a temp variable as number of existing adult friends
     let temp_friends_needed (friends_wanted - temp_friends_count)                                                 ;; Check how many friends still needed
     let temp_radius_adults count temp_adults_in_radius                                                            ;; Check how many adults are in radius
     IFELSE temp_radius_adults <= temp_friends_needed                                                              ;; If number of friends in radius is less that friends needed
       [create-friendlinks-with n-of temp_radius_adults temp_adults_in_radius [set link_type 4]]                   ;; ...make friends with all of these people
       [create-friendlinks-with n-of temp_friends_needed temp_adults_in_radius [set link_type 4]]                  ;; ...else make friends with number of friends needed from these people   
     ask temp_existing_friends_set [set exclude_friend_set 0]                                                      ;; Reset the temporary group variable
end   

to make_adult_remaining_friends                                                                                    ;; REPEAT FOR ALL ;;
     let temp_existing_friends_set friendlink-neighbors                                                            ;; Create a temporary set of people already friends with me
     let temp_adults_in_radius people with [ptype = 2]                                                             ;; Create a temporary set of adults
     ask temp_adults_in_radius [set exclude_friend_set 1]                                                          ;; Ask everyone to set their exclusion variable to 1
     ask temp_existing_friends_set [set exclude_friend_set 0]                                                      ;; Ask everyone already my friend to set exclusion variable to 0 
     set temp_adults_in_radius temp_adults_in_radius with [exclude_friend_set = 1]                                 ;; Update the temporary set to be only those not identified as a friend already
     
     let temp_friends_count count my-friendlinks                                                                   ;; Set a temp variable as number of my existing adult friends
     let temp_friends_needed (friends_wanted - temp_friends_count)                                                 ;; Check how many friends still needed
     let temp_radius_adults count temp_adults_in_radius                                                            ;; Check how many adults are in radius
     IFELSE temp_radius_adults <= temp_friends_needed                                                              ;; If number of friends in radius is less that friends needed
       [create-friendlinks-with n-of temp_radius_adults temp_adults_in_radius [set link_type 5]]                   ;; ...make friends with all of these people
       [create-friendlinks-with n-of temp_friends_needed temp_adults_in_radius [set link_type 5]]                  ;; ...else make friends with number of friends needed from these people   
     ask temp_existing_friends_set [set exclude_friend_set 0]                                                      ;; Reset the temporary group variable
end

to hide-links
ask links [hide-link]
end

;; ===================
;; ===================
;; MAIN GO PROCEDURE
;; ===================
;; ===================

to go
  set simulation_state "ACTIVE"
  tick
  IF Decay_Infectivity_Paths = TRUE [ask infectorlinks 
                                        [IFELSE age <= 0 
                                            [hide-link] 
                                            [set color (color - decay_turns + age) set age age - 1]]]
     quarantine-children  ;; ASSESS IF ANY CHILDREN QUARANTINED
     infect-schools       ;; RUN SCHOOL INFECTION ASSESSMENTS
     infect-households    ;; RUN FAMILY INFECTION ASSESSMENTS
     infect-friends       ;; RUN FRIEND INFECTION ASSESSMENTS
     activate-infection 
     recover-infection
     generate-values
           if count people with [person_infective_status = 3 OR person_infective_status = 2] = 0           ;; RUN IF NO INFECTIONS STARTED
                                   [IFELSE count people with [ever_infected = 1] <= (initial_infections) 
                                       [infect-initial go]  
                                       [set simulation_state "COMPLETED" stop]] 
     IF simulation_state = "COMPLETED" [stop]
end

to quarantine-children
ASK people with [ptype = 2 AND person_infective_status = 3 and quarantined = 0]
   [IF random-float 1 < 0.3 [set quarantined 1]]
end


to infect-schools                                                                     ;; TO INFECT SCHOOLS
  ask people with [ptype = 2 AND person_infective_status = 3 AND quarantined = 0]     ;; ASK EACH CHILD IN TURN WHO IS INFECTIVE AND IN SCHOOL
     [set temp_infector_who who                                                       ;; TO SET THE TEMP WHO VARIABLE AS THEIR OWN...
      ask in-schoollink-neighbors [                                                    ;; ...AND ASK THEIR CONNECTED SCHOOL...
       set temp_school_who who
       ask out-schoollink-neighbors with [person_infective_status = 1]               ;; ...TO ASK SUSCEPTIBLES THEY ARE CONNECTED TO...
         [IF random-float 1 < school_transmission_prob                                ;; ...TO MAKE AN ASSESSMENT OF WHETHER TO BECOME INFECTED
           [set person_infective_status 2 set infected_by_who temp_infector_who
            set infected_by_school temp_school_who]      ;; ...AND IF SO, TO SET THEMSELEVES AS SO, AND TO RECORD WHO INFECTED THEM
          ]
        ]]
set temp_school_who 0  
end

to infect-households
  ask people with [person_infective_status = 3]                                       ;; ASK INFECTIVE PEOPLE...
      [set temp_infector_who who                                                      ;; TO SET THE TEMP WHO VARIABLE AS THEIR OWN...
        ask in-familylink-neighbors                                                   ;; ...AND ASK THEIR HOUSEHOLD...
        [ask out-familylink-neighbors with [person_infective_status = 1]              ;; ...TO ASK ALL FAMILY MEMBERS WHO ARE SUSCEPTIBLE...
          [IF random-float 1 < family_transmission_prob                               ;; ...TO EVALUATE WHETHER TO BECOME INFECTED...
            [set person_infective_status 2 set infected_by_who temp_infector_who]     ;; ...AND IF SO, TO SET THEMSELVES AS SO, AND TO RECORD WHO INFECTED THEM
          ]]]
end

to infect-friends
ask people with [person_infective_status = 3]                                         ;; ASK INFECTIVE PEOPLE...
      [ set temp_infector_who who                                                     ;; ...TO SET THE TEMP WHO VARIABLE AS THEIR OWN...
         ask friendlink-neighbors with [person_infective_status = 1]                  ;; ...AND TO ASK EACH OF THEIR SUSCEPTIBLE FRIENDS...
             [IF random-float 1 < friend_transmission_prob                            ;; ...TO EVALUATE WHETHER TO BECOME INFECTED...
               [set person_infective_status 2 set infected_by_who temp_infector_who]  ;; ...AND IF SO, TO SET THEMSELVES AS SO, AND TO RECORD WHO INFECTED THEM
           ]] 
end

;; ACTIVATE INFECTED INDIVIDUALS - ONLY WANT INFECTIONS TO DEVELOP AT THE END OF EACH TURN
to activate-infection
ASK people with [person_infective_status = 2]                                         ;; ASK THOSE MARKED TO BE INFECTED TO BECOME INFECTIOUS
   [become-activeinfected]
end

    to become-activeinfected                                                          ;; SUB FUNCTION RUN BY TURTLES
      set infective_recovery_time random 5 + 4                                        ;; SET HOW LONG RECOVERY WILL TAKE
      set person_infective_status 3                                                   ;; SET STATUS TO INFECTIOUS
      set size 1 * size_modifier                                                      ;; SET SIZE
      set color red                                                                   ;; SET COLOUR
      set ever_infected 1                                                             ;; RECORD AS A CASE
      IF infected_by_who <= 0 [stop]                                                  ;; IF AN INITIAL INFECTION, STOP HERE...
      IFELSE infected_by_school > 0 
         [create-infectorlink-from school_centre infected_by_school [set color red set thickness 0.02 set age decay_turns - 1 set initialcolor red]
          let temp_myschool infected_by_school
          ask school_centre temp_myschool [set size 5 set color red]
          ask person infected_by_who [create-infectorlink-to school_centre temp_myschool [set color red set thickness 0.02 set age decay_turns - 1 set initialcolor red]]]
         
         [create-infectorlink-from person infected_by_who [ ask end1 [set temp_ptype_sou ptype]  ;; ELSE CREATE A LINK BASED ON START AND END POINT TURTLES
                                                        ask end2 [set temp_ptype_rec ptype]
                                                        IF temp_ptype_sou = 2 AND temp_ptype_rec = 2 [set color yellow set thickness 0.02 set age decay_turns - 1 set initialcolor yellow]
                                                        IF temp_ptype_sou = 2 AND temp_ptype_rec = 1 [set color cyan set thickness 0.02 set age decay_turns - 1 set initialcolor cyan]
                                                        IF temp_ptype_sou = 1 AND temp_ptype_rec = 1 [set color orange set thickness 0.02 set age decay_turns - 1 set initialcolor orange]
                                                        IF temp_ptype_sou = 1 AND temp_ptype_rec = 2 [set color green set thickness 0.02 set age decay_turns - 1 set initialcolor green]]]
    end

to recover-infection
ASK people with [person_infective_status = 3]                                         ;; ASK ALL THOSE INFECTED
   [set infective_recovery_time infective_recovery_time - 1]                          ;; TO REDUCE THEIR RECOVERY TIME BY 1
ASK people with [person_infective_status = 3 AND infective_recovery_time <= 0]        ;; AND IF THEIR RECOVERY TIME IS 0 OR BELOW
   [set person_infective_status 4 set color yellow set size 0.75 * size_modifier]      ;; TO CHANGE STATUS TO RECOVERED
end

;; VALUES FOR PLOTS AND OUTPUTS ;;
to generate-values 
  set percentage_susceptible 100 * count people with [person_infective_status = 1] / count people
  set percentage_infected 100 * count people with [person_infective_status = 3] / count people
  set percentage_immune 100 * count people with [person_infective_status > 3] / count people
  set percentage_ever_infected 100 * count people with [ever_infected = 1] / count people
  ask people with [person_infective_status > 2][set people_infected count my-out-infectorlinks]
end











;; OLD CODE - KEPT FOR INTEREST

;; to infect-schools
;; ask school_centres
;;     [let temp_infected_children count out-schoollink-neighbors with [(quarantined = 0 AND person_infective_status = 3)]     ;; Temp variable of number of children not quarantined and infected
;;       let temp_attending_children count out-schoollink-neighbors with [quarantined = 0]                                     ;; Temp variable of number of children not quarantined
;;       IF temp_attending_children = 0 [stop]                                                                                 ;; If no children attending, stop
;;       IF temp_infected_children = 0 [stop]                                                                                  ;; If no children infected, stop
;;       set school_percentage_infected temp_infected_children / temp_attending_children                                       ;; Set school_percentage_infected as percentage
;;       set school_infective_risk 0.05                                                                                        ;; set school infective risk at 0.05
;;       IF school_percentage_infected < 0.10 [set school_infective_risk 0.02]                                                 ;; Lower it to 0.02 if less than 10% infected
;;       IF school_percentage_infected < 0.02 [set school_infective_risk 0.01]                                                 ;; Lower it to 0.01 if less than 2% infected
;;       let temp_school_infective_risk school_infective_risk                                                                  ;; Set temporary variable of the schools infective risk
;;       ask out-schoollink-neighbors with [(quarantined = 0 AND person_infective_status = 1)]
;;       [IF random-float 1 < temp_school_infective_risk [SET person_infective_status 2]]                                      ;; Ask each of the schools susceptible pupils to evaluate risk
;;       ]
;; end
;; to infect-households
;; ask house_centres
;;      [let temp_infected_members count out-familylink-neighbors with [person_infective_status = 3]                           ;; Create temp variable of family members infected
;;        let temp_active_members count out-familylink-neighbors                                                               ;; Create temp_variable of all family members
;;        IF temp_active_members = 0 [stop]                                                                                    ;; Stop if no family members (only use if add conditions to above)
;;        IF temp_infected_members = 0 [stop]                                                                                  ;; Stop if no family members infected
;;       set family_percentage_infected temp_infected_members / temp_active_members                                           ;; Percent family infected
;;        set family_infective_risk 0.05                                                                                       
;;        IF family_percentage_infected < 0.10 [set family_infective_risk 0.02]
;;        IF family_percentage_infected < 0.02 [set family_infective_risk 0.01]
;;        let temp_family_infective_risk family_infective_risk
;;        ask out-familylink-neighbors with [person_infective_status = 1]
;;        [IF random-float 1 < temp_family_infective_risk [SET person_infective_status 2]]
;;      ]
;;end
@#$#@#$#@
GRAPHICS-WINDOW
603
10
1116
544
75
75
3.3333333333333335
1
10
1
1
1
0
0
0
1
-75
75
-75
75
1
1
1
ticks
10.0

SLIDER
2
10
220
43
Households
Households
0
2000
1510
10
1
NIL
HORIZONTAL

BUTTON
399
58
595
97
Step 1: SETUP (may take time)
setup
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

SLIDER
2
161
220
194
world_width
world_width
20
200
150
10
1
NIL
HORIZONTAL

SLIDER
2
47
220
80
Schools
Schools
0
10
7
1
1
NIL
HORIZONTAL

MONITOR
399
10
595
55
Simulation State
simulation_state
17
1
11

BUTTON
399
100
595
135
Step 2: GO UNTIL STEADY
Go
T
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

SLIDER
2
123
220
156
initial_infections
initial_infections
1
20
1
1
1
NIL
HORIZONTAL

SLIDER
2
85
220
118
vaccinated_percentage
vaccinated_percentage
0
100
80
1
1
%
HORIZONTAL

PLOT
2
198
385
543
Total Population
Time
Percentage
0.0
10.0
0.0
100.0
true
true
"" ""
PENS
"Susceptible" 1.0 0 -10141563 true "" "plot percentage_susceptible"
"Infected" 1.0 0 -2674135 true "" "plot percentage_infected"
"Immune" 1.0 0 -12087248 true "" "plot percentage_immune"
"Ever Infected" 1.0 0 -955883 true "" "plot percentage_ever_infected"

INPUTBOX
230
10
385
70
school_transmission_prob
0.02
1
0
Number

INPUTBOX
230
72
385
132
family_transmission_prob
0.2
1
0
Number

INPUTBOX
230
134
385
194
friend_transmission_prob
0.0050
1
0
Number

BUTTON
399
173
595
206
Optional: Reset this instance
reset-ticks\nreset-world
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

PLOT
399
209
595
329
2o infections per case
Count of cases
2o Infects
0.0
10.0
0.0
10.0
true
false
"set-histogram-num-bars 10\nset-plot-x-range 1 10" ""
PENS
"pen-0" 1.0 1 -7500403 true "" "histogram [people_infected] of people with [ever_infected = 1]"

BUTTON
399
332
595
365
Toggle  Infectivity Paths
ASK infectorlinks\n  [set color initialcolor\n   set thickness 0.5\n   IFELSE hidden? = TRUE \n      [set hidden? false]\n      [set hidden? true]]
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
0

BUTTON
399
438
595
471
Toggle Friend Links
ASK friendlinks\n  [IFELSE hidden? = TRUE \n      [set hidden? false]\n      [set hidden? true]]
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

BUTTON
399
474
595
507
Toggle Family Links
ASK familylinks\n  [IFELSE hidden? = TRUE \n      [set hidden? false]\n      [set hidden? true]]
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

BUTTON
399
510
595
543
Toggle School Links
ASK schoollinks\n  [IFELSE hidden? = TRUE \n      [set hidden? false]\n      [set hidden? true]]
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

SWITCH
399
369
595
402
Decay_Infectivity_Paths
Decay_Infectivity_Paths
0
1
-1000

SLIDER
399
401
595
434
Decay_Turns
Decay_Turns
0
5
3
1
1
NIL
HORIZONTAL

BUTTON
399
138
595
171
Optional: Go Once
Go
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

@#$#@#$#@
## WHAT IS IT?

This is a proof of concept model on integrating some network features into a SIR type model for an infectious disease. It allows study of the effect of the likelihood of transmission, and vaccination status of the individuals in the model.

## HOW IT WORKS

Model has two phases - setup, and then a go phase. In the setup phase, a network is created. This step is processor intensive, and may take some minutes. The world spawns a defined number of households, and then creates 1 or 2 adults, and 1, 2 or 3 children. Schools are then created, and children allocate themselves with a rule of 75% of the time go to the nearest school, else join any school.

Finally, adults form social networks, by selecting a certain number of nearby friends, and then a remaining number of friends from further afield. If two adults live in the same house, they acquire up to 75% of their spouses friends before seeking any others.

In the Go phase, each infected individual asks each of its links to evaluate whether they will become infected, based on the values entered in the interface. If infection is transmitted, it will become obvious at the end of the current phase. Once infected, a child also has a small possibility each turn they will be 'quarantined', so over time, many will be excluded from school risk, but may still transmit to family.

In highly resistant populations, the initial simulation will sometimes fail. It therefore has a rule that if no infections propagate, reset and start again in the same world automatically.

## HOW TO USE IT

Begin by setting your values. Choose how many households, schools, and what percentage are vaccinated. You can also alter how many are initially infected, and the total world size (patch size will scale proportionately to keep the display the same size. 

When ready, click Setup. Wait until 'Simulation State' reads 'Ready to Go' before clicking GO. If you want to see the networks formed, use the Toggle buttons (note that 'Toggle Infectivity Paths' will only work once the simulation has completed

Click Go to run the simulation.

If the simulation fails, or you wish to rerun the simulation in the same instance of the world (without regenerating new networks), click 'Optional: Reset this instance' and then click 'Go' again.

It may be worth slowing it down slightly to observe how infections focus around different schools at different times.

Notice as well the  small output graph of the number of cases infected by each case. A modified version of this output, in a susceptible population, could be used to work out the Ro for the theoretical disease described.

Legend:
  Circles:    People
  Dark Green: Vaccinated
  Magenta:    Adults Unvaccinated
  Violet:     Children Unvaccinated
  Yellow:     Infected and recovered

  Houses:     Households
  Squares:    Schools

Links:
  Red:        Child to Child Transmission via School
  Cyan:       Child to Adult Transmission
  Green:      Adult to Child Transmission
  Orange:     Adult to Adult Transmission

## THINGS TO NOTICE

Each time an infection transmits, a link is formed between the two individuals (directly, i.e. not through the school). See how these spread, and notice how the focus shifts between schools (as infection has been transmitted within a family)

## THINGS TO TRY

Try changing vaccination status, and infectivity rates to see how the flow and resistance of the community changes.

## EXTENDING THE MODEL

Potential next steps are to add classes to school, more sophisticated vaccination rules based on family preference, and to allow children to form friends outside their own school network. Vary susceptibility by adult or child, or introduce ages into the model and split into cohorts. Also, would like to add a death probability, to highlight real impact of low vaccination.

## NETLOGO FEATURES

The model uses links heavily to allow a real agent based effect, and a lot of calculation time is put into setting up a simple, but more realistic, social network, than simply assuming a whole population effect. 

The 'make_adult_radius_friends' procedure required particular development, and uses a temporary agentset and exclusion variables to ensure that turtles only make a connection once with another turtle. The mechanism for transferring a spouse's friends also required thought.

## CREDITS AND REFERENCES

This model was created by Christopher Chiswell for a tutorial on www.healthintel.co.uk. Please contact me if via my website if you found this model helpful, or want to discuss using it further.
@#$#@#$#@
default
true
0
Polygon -7500403 true true 150 5 40 250 150 205 260 250

airplane
true
0
Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15

arrow
true
0
Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150

box
false
0
Polygon -7500403 true true 150 285 285 225 285 75 150 135
Polygon -7500403 true true 150 135 15 75 150 15 285 75
Polygon -7500403 true true 15 75 15 225 150 285 150 135
Line -16777216 false 150 285 150 135
Line -16777216 false 150 135 15 75
Line -16777216 false 150 135 285 75

bug
true
0
Circle -7500403 true true 96 182 108
Circle -7500403 true true 110 127 80
Circle -7500403 true true 110 75 80
Line -7500403 true 150 100 80 30
Line -7500403 true 150 100 220 30

building institution
false
0
Rectangle -7500403 true true 0 60 300 270
Rectangle -16777216 true false 130 196 168 256
Rectangle -16777216 false false 0 255 300 270
Polygon -7500403 true true 0 60 150 15 300 60
Polygon -16777216 false false 0 60 150 15 300 60
Circle -1 true false 135 26 30
Circle -16777216 false false 135 25 30
Rectangle -16777216 false false 0 60 300 75
Rectangle -16777216 false false 218 75 255 90
Rectangle -16777216 false false 218 240 255 255
Rectangle -16777216 false false 224 90 249 240
Rectangle -16777216 false false 45 75 82 90
Rectangle -16777216 false false 45 240 82 255
Rectangle -16777216 false false 51 90 76 240
Rectangle -16777216 false false 90 240 127 255
Rectangle -16777216 false false 90 75 127 90
Rectangle -16777216 false false 96 90 121 240
Rectangle -16777216 false false 179 90 204 240
Rectangle -16777216 false false 173 75 210 90
Rectangle -16777216 false false 173 240 210 255
Rectangle -16777216 false false 269 90 294 240
Rectangle -16777216 false false 263 75 300 90
Rectangle -16777216 false false 263 240 300 255
Rectangle -16777216 false false 0 240 37 255
Rectangle -16777216 false false 6 90 31 240
Rectangle -16777216 false false 0 75 37 90
Line -16777216 false 112 260 184 260
Line -16777216 false 105 265 196 265

butterfly
true
0
Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
Circle -16777216 true false 135 90 30
Line -16777216 false 150 105 195 60
Line -16777216 false 150 105 105 60

car
false
0
Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
Circle -16777216 true false 180 180 90
Circle -16777216 true false 30 180 90
Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
Circle -7500403 true true 47 195 58
Circle -7500403 true true 195 195 58

circle
false
0
Circle -7500403 true true 0 0 300

circle 2
false
0
Circle -7500403 true true 0 0 300
Circle -16777216 true false 30 30 240

cow
false
0
Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
Polygon -7500403 true true 73 210 86 251 62 249 48 208
Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123

cylinder
false
0
Circle -7500403 true true 0 0 300

dot
false
0
Circle -7500403 true true 90 90 120

face happy
false
0
Circle -7500403 true true 8 8 285
Circle -16777216 true false 60 75 60
Circle -16777216 true false 180 75 60
Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240

face neutral
false
0
Circle -7500403 true true 8 7 285
Circle -16777216 true false 60 75 60
Circle -16777216 true false 180 75 60
Rectangle -16777216 true false 60 195 240 225

face sad
false
0
Circle -7500403 true true 8 8 285
Circle -16777216 true false 60 75 60
Circle -16777216 true false 180 75 60
Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183

fish
false
0
Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
Circle -16777216 true false 215 106 30

flag
false
0
Rectangle -7500403 true true 60 15 75 300
Polygon -7500403 true true 90 150 270 90 90 30
Line -7500403 true 75 135 90 135
Line -7500403 true 75 45 90 45

flower
false
0
Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
Circle -7500403 true true 85 132 38
Circle -7500403 true true 130 147 38
Circle -7500403 true true 192 85 38
Circle -7500403 true true 85 40 38
Circle -7500403 true true 177 40 38
Circle -7500403 true true 177 132 38
Circle -7500403 true true 70 85 38
Circle -7500403 true true 130 25 38
Circle -7500403 true true 96 51 108
Circle -16777216 true false 113 68 74
Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240

house
false
0
Rectangle -7500403 true true 45 120 255 285
Rectangle -16777216 true false 120 210 180 285
Polygon -7500403 true true 15 120 150 15 285 120
Line -16777216 false 30 120 270 120

leaf
false
0
Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195

line
true
0
Line -7500403 true 150 0 150 300

line half
true
0
Line -7500403 true 150 0 150 150

pentagon
false
0
Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120

person
false
0
Circle -7500403 true true 110 5 80
Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
Rectangle -7500403 true true 127 79 172 94
Polygon -7500403 true true 195 90 240 150 225 180 165 105
Polygon -7500403 true true 105 90 60 150 75 180 135 105

person student
false
0
Polygon -13791810 true false 135 90 150 105 135 165 150 180 165 165 150 105 165 90
Polygon -7500403 true true 195 90 240 195 210 210 165 105
Circle -7500403 true true 110 5 80
Rectangle -7500403 true true 127 79 172 94
Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
Polygon -1 true false 100 210 130 225 145 165 85 135 63 189
Polygon -13791810 true false 90 210 120 225 135 165 67 130 53 189
Polygon -1 true false 120 224 131 225 124 210
Line -16777216 false 139 168 126 225
Line -16777216 false 140 167 76 136
Polygon -7500403 true true 105 90 60 195 90 210 135 105

plant
false
0
Rectangle -7500403 true true 135 90 165 300
Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90

sheep
false
0
Rectangle -7500403 true true 151 225 180 285
Rectangle -7500403 true true 47 225 75 285
Rectangle -7500403 true true 15 75 210 225
Circle -7500403 true true 135 75 150
Circle -16777216 true false 165 76 116

square
false
0
Rectangle -7500403 true true 30 30 270 270

square 2
false
0
Rectangle -7500403 true true 30 30 270 270
Rectangle -16777216 true false 60 60 240 240

star
false
0
Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108

target
false
0
Circle -7500403 true true 0 0 300
Circle -16777216 true false 30 30 240
Circle -7500403 true true 60 60 180
Circle -16777216 true false 90 90 120
Circle -7500403 true true 120 120 60

tree
false
0
Circle -7500403 true true 118 3 94
Rectangle -6459832 true false 120 195 180 300
Circle -7500403 true true 65 21 108
Circle -7500403 true true 116 41 127
Circle -7500403 true true 45 90 120
Circle -7500403 true true 104 74 152

triangle
false
0
Polygon -7500403 true true 150 30 15 255 285 255

triangle 2
false
0
Polygon -7500403 true true 150 30 15 255 285 255
Polygon -16777216 true false 151 99 225 223 75 224

truck
false
0
Rectangle -7500403 true true 4 45 195 187
Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
Rectangle -1 true false 195 60 195 105
Polygon -16777216 true false 238 112 252 141 219 141 218 112
Circle -16777216 true false 234 174 42
Rectangle -7500403 true true 181 185 214 194
Circle -16777216 true false 144 174 42
Circle -16777216 true false 24 174 42
Circle -7500403 false true 24 174 42
Circle -7500403 false true 144 174 42
Circle -7500403 false true 234 174 42

turtle
true
0
Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99

wheel
false
0
Circle -7500403 true true 3 3 294
Circle -16777216 true false 30 30 240
Line -7500403 true 150 285 150 15
Line -7500403 true 15 150 285 150
Circle -7500403 true true 120 120 60
Line -7500403 true 216 40 79 269
Line -7500403 true 40 84 269 221
Line -7500403 true 40 216 269 79
Line -7500403 true 84 40 221 269

wolf
false
0
Polygon -7500403 true true 135 285 195 285 270 90 30 90 105 285
Polygon -7500403 true true 270 90 225 15 180 90
Polygon -7500403 true true 30 90 75 15 120 90
Circle -1 true false 183 138 24
Circle -1 true false 93 138 24

x
false
0
Polygon -7500403 true true 270 75 225 30 30 225 75 270
Polygon -7500403 true true 30 75 75 30 270 225 225 270

@#$#@#$#@
NetLogo 5.0.1
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
default
0.0
-0.2 0 0.0 1.0
0.0 1 1.0 0.0
0.2 0 0.0 1.0
link direction
true
0
Line -7500403 true 150 150 135 165
Line -7500403 true 150 150 165 165

line_mine
0.0
-0.2 0 0.0 1.0
0.0 1 1.0 0.0
0.2 0 0.0 1.0
link direction
true
0
Line -7500403 true 150 150 90 180
Line -7500403 true 150 150 210 180

@#$#@#$#@
0
@#$#@#$#@
