Aspiration, Attainment and Success (JASSS 2013)

Aspiration, Attainment and Success (JASSS 2013) preview image

1 collaborator

Jm1_vsm James Millington (Author)

Tags

education 

Tagged by James Millington over 11 years ago

geography 

Tagged by James Millington over 11 years ago

inequality 

Tagged by James Millington over 11 years ago

schools 

Tagged by James Millington over 11 years ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 5.0 • Viewed 810 times • Downloaded 48 times • Run 0 times
Download the 'Aspiration, Attainment and Success (JASSS 2013)' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                                              ;;
;;                School Choice   November 2012                                 ;;
;;                                                                              ;;
;;  Code licenced by James D.A. Millington (http://www.landscapemodelling.net)  ;;
;;  under a Creative Commons Attribution-Noncommercial-Share Alike 3.0          ;;
;;  Unported License (see http://creativecommons.org/licenses/by-nc-sa/3.0/)    ;;
;;                                                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;Full documentation at ...


extensions [ shell r ]


globals 
[ 
  schoolRadii 
  empty-rankings
  
  directory 
  exp-index ;experiment number (for files/directories)
  
  ;Moran's i summary
  asp-moran-i    ;Aspiration Moran's i
  asp-moran-i-p  ;Aspiration Moran's i p-value
  att-moran-i    ;Attainment Moran's i
  att-moran-i-p  ;Attainment Moran's i p-value
  
  ;relationships summary
  GA-m ;GCSE vs AppRatio coefficient
  GA-r ;GCSE vs AppRatio Pearson r
  GA-p ;GCSE vs AppRatio p value
  
  GMx-m ;GCSE vs Max Distance coefficient
  GMx-r ;GCSE vs Max Pearson r
  GMx-p ;GCSE vs Max p value
  
  GMn-m ;GCSE vs Mean Distance coefficient
  GMn-r ;GCSE vs Mean Pearson r
  GMn-p ;GCSE vs Mean p value
  
  AMx-m ;AppRatio vs Max Distance coefficient
  AMx-r ;AppRatio vs Max Distance Pearson r
  AMx-p ;AppRatio vs Max Distance p value
  
  AMn-m ;AppRatio vs Mean Distance coefficient
  AMn-r ;AppRatio vs Mean Distance Pearson r
  AMn-p ;AppRatio vs Mean Distance p value
] 



breed [parents parent]
breed [schools school]

parents-own 
[
  strategy ;indicator of which ranking method agent used
  rankings ;list of schools that are worthy of ranking (transfered into specific ranks rank1, rank2... etc)
  distances ;list of schools in ascending of order of distance 
 
  allocated-school ;school allocated
  allocated-distance ;distance to allocated school
  aspiration ;aspiration level of parent
  
  success-by-rank  ;rank of allocated school (1 is top rank, i.e. most preferred)
  success-rank1  ;true if allocated to top-ranked school, else false (or -1 if not allocated)
  success-by-aspiration   ;true if allocated school GCSE-score > aspiration at time of allocation

  considered ; list of schools considered acceptable given aspiration
  catchment ; list of schools the parent believes they are in the catchment of (given last 3 years catchments) - 3? or memory?
  avoided ; list of schools the parent wishes to avoid because school GCSE-score is some level below their aspiration
  
  child-age ;age of child. children apply for school when 10 years old (therefore only rank and allocate when child = 10)
  child-attainment ; initially set to parent aspiration, can increase during school years
    
  want-to-move ;true or false - does this parent want to move?
  have-moved ; true or false - has this parent moved? if so cannot move again
  move-target ;if parent wants to move, this is the preferred school
  initialHome ;patch where Parent initially lives
  newHome ;patch where Parent moves to   
]

schools-own
[
  school-type ;state or new?
  id ;school id
  
  GCSE-score ;measure of school quality
  ;GCSE-z-score ;z-score of school GCSE score
  GCSE-scores ; list containing last MEMORY years GCSE-scores 
  value-added; % by which incoming students aspiration is increased year-on-year to y11
  mean-aspiration
  mean-attainment ;added v6
  
  places ;pupil places available at the school for each year
  last-growth ;last tick in which school expanded
  y7pupils ;number of pupils allocated this year
  all-pupils ;total number of pupils in the school
  
  allocated  ;list holding allocated parents
  all-applicants ;list holding all applicants for this year with given criteria (see below)
  applicants ;list holding applicants for this year - changes through application process (allocate-places)
  app-ratio ;ratio of applications to places
  max-distance ;distance of farthest allocated parent
  max-distances ;list of last Parent-Memory years' max distances
  mean-distance ; mean distance of parents 
  mean-distances ;list of last Parent-Memory years' mean distances
  
  y7Parents ;list of parents with children in year 7 (initially this is simply a value specifying that year's GCSE score, through time becomes a list which is updated each year)
  y8Parents ;list of parents with children in year 8 (initially this is simply a value specifying that year's GCSE score, through time becomes a list which is updated each year)
  y9Parents ;list of parents with children in year 9 (initially this is simply a value specifying that year's GCSE score, through time becomes a list which is updated each year)
  y10Parents ;list of parents with children in year 10 (initially this is simply a value specifying that year's GCSE score, through time becomes a list which is updated each year)
  y11Parents ;list of parents with children in year 11 (initially this is simply a value specifying that year's GCSE score, through time becomes a list which is updated each year)
  
  catchmentPatches ; patches within school's max-distance with no parents in them
  
]

patches-own
[
  location-value ;value of location for moving
  p-aspiration ;aspiration of parent on this patch (for calculating Moran's I)
  p-attainment ;child-attainment of parent on this patch (for calculating Moran's I)
]


;;----------------------------------
;;SETUP
;;----------------------------------

to setup

  clear-all
  if(calc-Moran?) [ setup-R ]
  random-seed seed
  setup-empty-rankings
    
  set schoolRadii sqrt((SchoolSize * 5) / pi) ;specifies the radius of a circle with area equal to the number of places at a school (i.e. 5 years of pupils)
  
  if(Random-Schools = false)
  [
    set Families 100 ;slider - describes number of parents per school to add at each tick
    set SchoolSize 100 ;slider - initial size of a single year group at school
    set Number-of-Schools 9 ;slider - initial number of schools
  ]  
      
  setup-Parents 
  setup-Schools
  setup-Patches
  
  reset-ticks
  plotting
end 

to setup-Patches

  print "setting up patches"
  set-patch-attributes
end 

to setup-empty-rankings
  
  set empty-rankings[]
  
  let thisRank length empty-rankings
  
  while[thisRank < Number-of-Ranks]
  [
    set empty-rankings lput -1 empty-rankings
    set thisRank thisRank + 1
  ]
end 

to setup-Schools
  
  print "setting up schools"
  
  ;if schools are randomly positioned in space 
  ifelse(Random-Schools)
  [
    while[count schools < Number-of-Schools]
    [
      ask one-of patches
      [
        ;minimum spacing requirement
        if(not any? other schools with [distance myself < world-width * Min-School-Spacing ])
        [  
          set plabel 1
          set plabel-color black
          
          ;move any parents already at this location - schools and parents cannot share a location
          ask parents-here
          [
            let unoccupiedPatch one-of patches with [not any? turtles-here]
            move-to unoccupiedPatch 
          ]
          
          ;create the school
          sprout-schools 1
          [
            set size 3
            set shape "house"
            set school-type "state"
            
            set GCSE-score -1 
            
            while [GCSE-score < 0 or GCSE-score > 100]
            [ 
              if(Initial-School-GCSE-Distribution = "uniform") [ set GCSE-score 1 ]
              if(Initial-School-GCSE-Distribution = "normal") [ set GCSE-score random-normal 50 20 ]
              if(Initial-School-GCSE-Distribution = "negative-exponential") [ set GCSE-score random-exponential 25 ]
            ]

            set GCSE-scores []
            
            set value-added -2 
            if(School-Value-Added)
            [
              while [value-added < -1 or value-added > 1 ]
              [
                if(School-Value-Added-Distribution = "uniform") [ set value-added 0.1 ]
                if(School-Value-Added-Distribution = "normal") [ set value-added random-normal 0 0.1 ]              
                
                if(value-added < 0) [ set value-added (value-added * -1) ] ;do not allow value-added to be negative
                
                ;to check influence of increased value-added
                ;set value-added value-added + 0.1
              ]
            ]
            
            ;lists that will hold parents in each year group (initially empty)
            set y7Parents []
            set y8Parents []
            set y9Parents []
            set y10Parents []
            set y11Parents []
            
            set places SchoolSize
            set last-growth 0 
            set id (count schools - 1)      ;first school has id of zero
            set color (count schools - 1) * 10 + 15  ;first school will be red 
                                                     ;set size 0
            
            set max-distances []
            set mean-distances []
            set allocated []
            set applicants []
            
            set mean-distance 0
            
          ]
        ]
      ]
    ]
  ]
  
  ;else schools are on a grid
  [
    while[count schools < 9]
    [
      
      let school-xcor 0
      let school-ycor 0
      
      let third-x (world-width / 3)
      let third-y (world-height / 3)
      
      if(count schools = 6) [ set school-xcor floor(third-x * -1) set school-ycor floor(third-y * -1) ]
      if(count schools = 7) [ set school-xcor 0 set school-ycor floor(third-y * -1) ]
      if(count schools = 8) [ set school-xcor floor(third-x) set school-ycor floor(third-y * -1) ]
      if(count schools = 3) [ set school-xcor floor(third-x * -1) set school-ycor 0 ]
      if(count schools = 5) [ set school-xcor floor(third-x) set school-ycor 0 ]
      if(count schools = 0) [ set school-xcor floor(third-x * -1) set school-ycor floor(third-y) ]
      if(count schools = 1) [ set school-xcor 0 set school-ycor floor(third-y) ]
      if(count schools = 2) [ set school-xcor floor(third-x) set school-ycor floor(third-y) ]
      
      
      ask patches with [pxcor = school-xcor and pycor = school-ycor]
      [
        if(not any? other schools with [distance myself < world-width * Min-School-Spacing ])
        [  
          set plabel 1
          set plabel-color black
          ask parents-here
          [
            let unoccupiedPatch one-of patches with [not any? turtles-here]
            move-to unoccupiedPatch 
          ]
          
          sprout-schools 1
          [
            set size 3
            set shape "house"
            set school-type "state"
            
            set GCSE-score -1 
            
            while [GCSE-score < 0 or GCSE-score > 100]
            [ 
              if(Initial-School-GCSE-Distribution = "uniform") [ set GCSE-score 1 ]
              if(Initial-School-GCSE-Distribution = "normal") [ set GCSE-score random-normal 50 20 ]
              if(Initial-School-GCSE-Distribution = "negative-exponential") [ set GCSE-score random-exponential 25 ]
            ]
            
            set GCSE-scores []
            
            set value-added -2 
            if(School-Value-Added)
            [
              while [value-added < -1 or value-added > 1 ]
              [
                if(School-Value-Added-Distribution = "uniform") [ set value-added 0.1 ]
                if(School-Value-Added-Distribution = "normal") [ set value-added random-normal 0 0.1 ]
                
                if(value-added < 0) [ set value-added (value-added * -1) ] ;do not allow value-added to be negative   
                
                ;to check influence of increased value-added
                ;set value-added value-added + 0.1                             
              ]
            ]
            
            set y7Parents []
            set y8Parents []
            set y9Parents []
            set y10Parents []
            set y11Parents []
            
            set places SchoolSize
            set id (count schools - 1)      ;first school has id of zero
            set color (count schools - 1) * 10 + 15  ;first school will be red 
                                                     ;set size 0
            
            set max-distances []
            set mean-distances []
            set allocated []
            set applicants []
            
            set mean-distance 0
            
          ]
        ]
      ]
    ]
  ]
end 

to setup-Parents
     
  print "setting up parents"   
  ;initially set 7 x Families * Number-of-Schools with evenly distributed child ages (9-15)
    
  let addedParents 0
  
  while [addedParents < (Families * Number-of-Schools * 7)]
  [
    ask one-of patches
    [
      if(not any? turtles-here)
      [
        sprout-parents 1
        [ 
          set color grey
          set size 1
          facexy 0 0
          set shape "circle"
          
          set aspiration -1
          while [aspiration < 0 or aspiration > 100]
          [ 
            if(Parent-Aspiration-Distribution = "uniform") [ set aspiration random (Aspiration-Mean * 2) ]
            if(Parent-Aspiration-Distribution = "normal") [ set aspiration random-normal Aspiration-Mean 20 ]
            
            if(Parent-Aspiration-Distribution = "negative-exponential") [ set aspiration random-exponential 25 ]
            if(Parent-Aspiration-Distribution = "exponential") [ set aspiration random-exponential 25 ]
          ]
          if(Parent-Aspiration-Distribution = "exponential") [ set aspiration 100 - aspiration ] 
          
          ifelse(attainment=aspiration?)
          [ set child-attainment aspiration ]
          [
            set child-attainment -1 
            while [child-attainment < 0 or child-attainment > 100]
            [ 
              if(Child-Attainment-Distribution = "uniform") [ set child-attainment random (Attainment-Mean * 2) ]
              if(Child-Attainment-Distribution = "normal") [ set child-attainment random-normal Attainment-Mean 20 ]
              
              if(Child-Attainment-Distribution = "negative-exponential") [ set child-attainment random-exponential 25 ]
              if(Child-Attainment-Distribution = "exponential") [ set child-attainment random-exponential 25 ]
            ]
            if(Child-Attainment-Distribution = "exponential") [ set child-attainment 100 - child-attainment ] 
          ]
          
          set child-age (floor ((addedParents + 1) / (Families * Number-of-Schools))) + 9
          
          set allocated-school 0
          
          set have-moved false
          set want-to-move true
          set initialHome myself
          set newHome nobody
          
          set rankings []
          
          set success-by-rank -1
          set success-rank1 -1
          set success-by-aspiration -1  
          set strategy -1        
        ]
        set addedParents addedParents + 1
      ]
    ]
  ]
  
  ;there always seems to be one parent with child-age = 16 which 'should' be 9. this fixes that 
  if(any? parents with [child-age = 16])
  [
    ask parents with [child-age = 16] [ set child-age 9 ]
  ]
end 

to set-parent-school-distance
  
  set distances sort-by [distance ?1 < distance ?2] schools
end 
;;----------------------------------
;;END SETUP
;;----------------------------------





 
;;----------------------------------
;;SIMULATION
;;----------------------------------

to go
   
  if(ticks = 0)
  [
    with-local-randomness
    [
      if(Export-Summary-Data or Export-World-Data or Export-Movie)
      [
        ;create a new directory for this model run
        set directory "J:\\SchoolChoice"
        ;set directory "C:\\Users\\James\\Dropbox\\Research\\OngoingProjects\\SchoolChoice"
        set-current-directory directory
        shell:cd directory
        print directory
        print shell:pwd 
        
        ;create a dummy file to check what new name to give the directory (checked in next-index procedure)
        let dummy "Experiment"
        let suffix ".txt"  
        set exp-index next-index dummy suffix
        let filename (word shell:pwd "\\" dummy exp-index suffix)
        file-open filename
        write-experiment-data
        file-close
        
        ;set the new directory name and create  
        set directory (word shell:pwd "\\" dummy exp-index) ;set
        show(shell:exec "cmd" "/c" "md" directory) ;create
        set-current-directory directory ;update
        shell:cd directory ;update
      ] 
      
      if(Export-Summary-Data) [ ExportSummaryData_header ]
      if(Export-World-Data) [ ExportWorldData_initial ]
      if(Export-Movie)
      [
        movie-start "movie.mov"
        movie-set-frame-rate 2
        movie-grab-view
      ]
    ]
         
      
      ask parents [set-parent-school-distance]
      set-SchoolCatchments 
      rank-Schools
      move
  ]
  
  
   show "Adding new parents and aging children"
  age-children
  age-PupilCohorts ;move cohorts of students up one year
  add-NewParents ;add new parents for this tick
  set-schoolCatchments ;find patches in catchment available to move into this tick (do this after adding new parents)
  
    
  show "Parents ranking schools"
  rank-Schools  ;parents set their school ranking
  
  show "Allocating places"
  allocate-Places ;schools allocate places to parents with child-age = 10

  show "Moving agents" 
  move ;parents with child-age = 9 potentially move to a better location
 
  set-patch-attributes
      
  show "Updating Schools"
  calc-catchment-size  ;schools calculate mean and max allocated distance of their parents
  update-SchoolGCSE ;update schools' GCSE-score 
    
 
  with-local-randomness
  [  
    show "Plotting etc"  
    check-success
    update-colours
    plotting 
    
    if(Export-Summary-Data) 
    [ 
      calc-Moran
      calc-relationships
      ExportSummaryData 
    ]
    
    if(Export-World-Data) [ ExportWorldData ]
    if(Export-Movie) [ movie-grab-view ]
  ]
  
  tick
 
  if(ticks = run-length)
  [
    if(Export-Movie) [ movie-close ]
    if(Export-Summary-Data) 
    [ 
      export-worldview
      ZipParents_Data 
    ]
    stop
  ]
end 

to distribute-parents-worst-best [ worst best ] ;distributes parents currently at worst (school) to best
  
   ask worst
    [
      ask best [ set y7Parents sentence y7Parents [y7Parents] of myself ]
      ask best[ set y8Parents sentence y8Parents [y8Parents] of myself ]
      ask best[ set y9Parents sentence y9Parents [y9Parents] of myself ]
      ask best[ set y10Parents sentence y10Parents [y10Parents] of myself ]
      ask best[ set y11Parents sentence y11Parents [y11Parents] of myself ]
      ask best[ set allocated sentence allocated [allocated] of myself ]
    ]
    
    ask parents with [allocated-school = worst] [ set allocated-school best ]
        
    ask best[ set places length allocated ]

    ask worst [ die ]
    
    ask parents [ set-parent-school-distance ]
    
    update-Colours
end 

to distribute-parents-equally [ worst ] ;distributes parents currently at worst (school) equally among other schools 
  
  ask worst
  [
    ;show "moving y7Parents"
    set y7Parents shuffle y7Parents
    while[length y7Parents > 0]
    [
      ask one-of other schools  
      [ 
        set y7Parents sentence y7Parents first [y7Parents] of myself 
      ]
      set y7Parents remove-item 0 y7Parents
    ]

    ;show "moving y8Parents"
    set y8Parents shuffle y8Parents
    while[length y8Parents > 0]
    [
      ask one-of other schools  
      [ 
        set y8Parents sentence y8Parents first [y8Parents] of myself 
      ]
      set y8Parents remove-item 0 y8Parents
    ]
        
    ;show "moving y9Parents"
    set y9Parents shuffle y9Parents
    while[length y9Parents > 0]
    [
      ask one-of other schools  
      [ 
        set y9Parents sentence y9Parents first [y9Parents] of myself 
      ]
      set y9Parents remove-item 0 y9Parents
    ]
    
    ;show "moving y10Parents"
    set y10Parents shuffle y10Parents
    while[length y10Parents > 0]
    [
      ask one-of other schools  
      [ 
        set y10Parents sentence y10Parents first [y10Parents] of myself 
      ]
      set y10Parents remove-item 0 y10Parents
    ]

    ;show "moving y11Parents"
    set y11Parents shuffle y11Parents
    while[length y11Parents > 0]
    [
      ask one-of other schools  
      [ 
        set y11Parents sentence y11Parents first [y11Parents] of myself 
      ]
      set y11Parents remove-item 0 y11Parents
    ]
    
    ;show "moving allocated"
    set allocated shuffle allocated
    while[length allocated > 0]
    [
      ask one-of other schools  
      [ 
        set allocated sentence allocated first [allocated] of myself 
      ]
      set allocated remove-item 0 allocated
    ]
  ]
   
  
  ask worst [ die ]

  ask schools
  [
    foreach y7Parents [ ask ? [ if(allocated-school != myself) [ set allocated-school myself ] ] ]
    foreach y8Parents [ ask ? [ if(allocated-school != myself) [ set allocated-school myself ] ] ]
    foreach y9Parents [ ask ? [ if(allocated-school != myself) [ set allocated-school myself ] ] ] 
    foreach y10Parents [ ask ? [ if(allocated-school != myself) [ set allocated-school myself ] ] ]  
    foreach y11Parents [ ask ? [ if(allocated-school != myself) [ set allocated-school myself ] ] ]
    foreach allocated [ ask ? [ if(allocated-school != myself) [ set allocated-school myself ] ] ]   
  ]
  
  ask schools 
  [ 
    if(places < length allocated)
    [set places length allocated ]  ;don't decreease places, only increase if necessary
  ]
  
  ask parents [ set-parent-school-distance ]
  
  update-Colours
end 

to-report remove-first-n-list-items [ thisList n ]
  
  if(length thisList > 0)
  [
    let removed 0
    while[removed < n and length thisList > 0]
    [ 
      set thisList remove-item 0 thisList
      set removed removed + 1
    ] 
  ]
  
  report thisList
end 

to add-NewParents

  let addedParents 0
    
  while [addedParents < Families * Number-of-Schools]
  [
    let sprouting-patch nobody
    
    ifelse(Location-Rules = false)  ;if new parents can be located randomly on the grid
    [ 
      ask one-of patches
      [
         if(not any? turtles-here) 
         [
           create-parent
           set addedParents addedParents + 1
         ]
      ]
    ]
    
    ;otherwise only allow parents to move to patches with location-value lower than their aspiration
    [
      ask patch 0 0 [ create-parent ]
      
      ask parents-on patch 0 0
      [
        let newPatch patch-here
        let myAspiration aspiration
        
        set newPatch max-one-of patches with [not any? turtles-here and location-value < myAspiration ] [location-value]
        
        if(newPatch = nobody) [set newPatch min-one-of patches with [not any? turtles-here ] [location-value]] ;if there are no patches with patchVAlue < aspiration, move to patch available with minimum location-value
        move-to newPatch
        set initialHome newPatch
      ]

      set addedParents addedParents + 1
    ]      
  ]
end 

to create-parent
  
   sprout-parents 1
   [ 
     set color grey 
     if(Show-Unallocated = false) [ set hidden? true ]
     
     set size 1
     facexy 0 0
     set shape "circle"
     
     set aspiration -1
     while [aspiration < 0 or aspiration > 100]
     [ 
       if(Parent-Aspiration-Distribution = "uniform") [ set aspiration random (Aspiration-Mean * 2) ]
       if(Parent-Aspiration-Distribution = "normal") [ set aspiration random-normal Aspiration-Mean 20 ]
       
       if(Parent-Aspiration-Distribution = "negative-exponential") [ set aspiration random-exponential 25 ]
       if(Parent-Aspiration-Distribution = "exponential") [ set aspiration random-exponential 25 ]
     ]
     if(Parent-Aspiration-Distribution = "exponential") [ set aspiration 100 - aspiration ] 
     
     ifelse(attainment=aspiration?)
     [ set child-attainment aspiration ]
     [
       set child-attainment -1 
       while [child-attainment < 0 or child-attainment > 100]
       [ 
         if(Child-Attainment-Distribution = "uniform") [ set child-attainment random (Attainment-Mean * 2) ]
         if(Child-Attainment-Distribution = "normal") [ set child-attainment random-normal Attainment-Mean 20 ]
         
         if(Child-Attainment-Distribution = "negative-exponential") [ set child-attainment random-exponential 25 ]
         if(Child-Attainment-Distribution = "exponential") [ set child-attainment random-exponential 25 ]
       ]
       if(Child-Attainment-Distribution = "exponential") [ set child-attainment 100 - child-attainment ] 
     ]
     
          
     set child-age 9
     
     set have-moved false
     set want-to-move true
     set initialHome myself
     set newHome nobody
     
     set allocated-school 0
     set rankings []
     set-parent-school-distance
     
     set success-by-rank -1
     set success-rank1 -1
     set success-by-aspiration -1  
     set strategy -1                
     
   ]
end 

to age-children
  
  ask parents
  [
    set child-age child-age + 1
  ]
  
  ;kill parents with children that have left school
  ask parents with [child-age = 16] [die ]
end 

to age-PupilCohorts

  ;move each cohort of students up one year (by replacing parent lists with previous year's parent list)
  ;create y7Parents from the allocated list for the school
  ;don't age cohorts in the first tick because there no pupils have been allocated yet  
  if(ticks > 0)
  [
    ask schools
    [
      set y11Parents []
      foreach y10Parents [ set y11Parents fput ? y11Parents]
      
      set y10Parents []
      foreach y9Parents [ set y10Parents fput ? y10Parents]
      
      set y9Parents []
      foreach y8Parents [ set y9Parents fput ? y9Parents]
      
      set y8Parents []
      foreach y7Parents [ set y8Parents fput ? y8Parents]
      
      set y7Parents []
      foreach allocated [set y7Parents fput ? y7Parents ]  ;copy allocated to y7Parents (allocated are parents with child-age = 10 last year, now child-age = 11)
    ]
  ]
end 

to allocate-Places
  
  ask schools
  [
    set all-applicants [] 
    set all-applicants parents with [child-age = 10 and member? myself rankings and allocated-school = 0]
    set app-ratio (count all-applicants) / places   
    
    set y7pupils 0 ;re-set number of year 7 pupils for this year of allocations 
    set allocated []  
  ]  
    
    ;all schools allocate applicants that ranked them highest first (potentially using distance if there are too many applicants) 
    ;then school allocate applicants that ranked them second (again, potentially using distance if there are too many applicants), third, fourth, etc.
    ;schools that have remaining places after all ranked preferences have been allocated, allocate remaining places on distance or randomly
    
    let thisRank 0
    
    while[thisRank < Number-of-Ranks]
    [ 
      ask schools
      [    
        if(y7pupils < places)
        [
          set applicants parents with [child-age = 10 and item thisRank rankings = myself and allocated-school = 0]   ;add parents to applicants list if they have ranked this school highest        
          if(school-type = "state") 
          [ 
            set applicants sort-by [distance ?1 < distance ?2] applicants  ;sort the list of applicants, closest is first in list NOTE: this sorting changes agentset to a list
          ]
          
          if(school-type = "new") [ set applicants sort-by [[child-attainment] of ?1 > [child-attainment] of ?2] applicants ]  ;sort the list of applicants, highest attainment is first in list NOTE: this sorting changes agentset to a list
          
          ifelse(length applicants > (places - y7pupils))  ;if there are more applicants than places available at the school, allocate by distance
          [    
            while [y7pupils < places]  ;while not all places have been allocated
            [
              ask first applicants [ set allocated-school myself ]  ;allocate the closest applicant
              ;ask first applicants [ set allocated-school myself set rankings empty-rankings ]  ;allocate the current 'best' applicant
              set allocated lput first applicants allocated          ;add this current 'best' applicant to the allocated list
              set applicants remove-item 0 applicants                ;remove this current 'best' applicant from the applicants list
              set y7pupils y7pupils + 1                              ;increase number of places allocated by 1
            ]
          ]
          
          ;if there are more places than applicants allocate all applicants a place
          [
            foreach applicants 
            [ 
              ask ? [set allocated-school myself ]
              ;ask ? [set allocated-school myself set rankings empty-rankings ]
              set allocated lput ? allocated          ;add this applicant to the allocated list
            ]
            set y7pupils (y7pupils + length applicants)
            ;set applicants []
          ]
        ]
      ]  
      
      set thisRank thisRank + 1 
    ]
    
  
    ;finally, for schools with unallocated places, allocate unallocated applicants by distance
    ;first allocated to parents of which this school is closest, then second closest etc.
    let thisDist 0
    
    while[thisDist < Number-of-Schools]
    [
      ask schools with [y7pupils < places]
      [
        set applicants parents with [child-age = 10 and allocated-school = 0 and item thisDist distances = myself]
        set applicants sort-by [distance ?1 < distance ?2] applicants
        
        ifelse(length applicants > (places - y7pupils))
        [ 
          while [y7pupils < places]
          [
            ask first applicants [ set allocated-school myself ]
            ;ask first applicants [ set allocated-school myself set rankings empty-rankings ]
            set allocated lput first applicants allocated          ;add this closest applicant to the allocated list
            set applicants remove-item 0 applicants                ;remove this closest applicant from the applicants list
            set y7pupils y7pupils + 1
          ]
        ]
        
        ;if there are more places than applicants allocate all applicants a place
        [ 
          without-interruption
          [
            foreach applicants 
            [ 
              ask ? [set allocated-school myself ]
              ;ask ? [set allocated-school myself set rankings empty-rankings ]
              set allocated lput ? allocated          ;add this applicant to the allocated list
            ]
            set y7pupils (y7pupils + length applicants)
            ;set applicants []
          ]
        ]
      ]
      
      set thisDist thisDist + 1
    ]

    
    
    ask schools
    [
      set all-pupils (length y7parents + length y8parents + length y9parents + length y10parents + length y11parents)
    ]
    
    ask parents with [child-age = 10 ]
    [
      set allocated-distance distance allocated-school
    ]
end 

to calc-catchment-size

  ;calculates mean and max allocated parent distances 

  ifelse(ticks > 0) ;initially schools have no parents
  [
    ask schools with [school-type = "state"]
    [
      let all-parents parents with [ allocated-school = myself ]

      ifelse(not any? all-parents)
      [ 
        set max-distance -1 ;if no places were allocated set a no data value
        set max-distances lput 0 max-distances ;add the max distance to the list of max distances
        if(length max-distances > Parent-Memory) [ set max-distances remove-item 0 max-distances ]  ;only keep track of last *Memory* years distances
        
        set mean-distance -1 ;if no places were allocated set a no data value
        set mean-distances lput 0 mean-distances ;add the mean distance to the list of mean distances
        if(length mean-distances > Parent-Memory) [ set mean-distances remove-item 0 mean-distances ]  ;only keep track of last *Memory* years distances
      ]
      [
        set max-distance max [allocated-distance] of all-parents ;if places were allocated find the distance of the furthest allocated parent
        set max-distances lput max-distance max-distances ;add the max distance to the list of max distances
        if(length max-distances > Parent-Memory) [ set max-distances remove-item 0 max-distances ]  ;only keep track of last *Memory* years distances
       
        set mean-distance mean [allocated-distance] of all-parents  ;if places were allocated find the mean distance of allocated parents
        set mean-distances lput mean-distance mean-distances ;add the mean distance to the list of mean distances
        if(length mean-distances > Parent-Memory) [ set mean-distances remove-item 0 mean-distances ]  ;only keep track of last *Memory* years distances
      ] 
    ]
    
    ask schools with [school-type = "new"]
    [
      set max-distances fput (2 * world-width) max-distances
      set mean-distances fput (2 * world-width) mean-distances
    ]
    
  ]

  ;instead just set catchment to larger than the world
  [
    ask schools
    [
      set max-distances fput (2 * world-width) max-distances
      set mean-distances fput (2 * world-width) mean-distances
    ]
  ]
end 

to check-success
  
  ask parents with [child-age = 10 ] 
  [ 
    let thisRank 0
    while[thisRank < Number-of-Ranks]
    [
      if(allocated-school = item thisRank rankings) [ set success-by-rank thisRank + 1 ]
      set thisRank thisRank + 1
    ]
    
    if(success-by-rank != -1) [ set success-rank1 0 ]
    if(success-by-rank = 1) [ set success-rank1 1 ]
    
    ifelse(aspiration < [GCSE-score] of allocated-school) 
    [ set success-by-aspiration  1 ]
    [ set success-by-aspiration 0 ]
  ]
end 

to set-child-attainment [ yParents ]
  
  if(not empty? yParents)
  [
    ask turtle-set yParents 
    [ 
      if(School-Value-Added = true) [ set child-attainment child-attainment * (1 + [value-added] of myself) ]
      set child-attainment (child-attainment * (1 - School-Peer-Effect - Parent-Effect)) + ([mean-attainment] of myself * School-Peer-Effect) + (aspiration * Parent-Effect)
      
      if(child-attainment > 100) [ set child-attainment 100 ]
    ]
  ]
end 

to update-SchoolGCSE
  
  ;first update child-attainment for this year
  ask schools
  [
    ;show mean-aspiration
    set-child-attainment y7Parents
    set-child-attainment y8Parents
    set-child-attainment y9Parents
    set-child-attainment y10Parents
    set-child-attainment y11Parents
  ]
  
  ;set mean and max child-attainment  
  ask schools
  [
    let myParents (turtle-set y7parents y8parents y9parents y10parents y11parents)
    
    ifelse(any? myParents)
    [ 
      set mean-aspiration mean [aspiration] of myParents
      set mean-attainment mean [child-attainment] of myParents 
    ]
    [ 
      set mean-aspiration 0 
      set mean-attainment 0
    ] 
  ]
  
  ;only start updating GCSE-score once first cohort of allocated students has reached year 11 (before this y11Parents will be empty)
  if(ticks > 5)
  [ 
    ask schools
    [
      let sumAttainment 0
      
      if(not empty? y11Parents)
      [
        set sumAttainment sum [child-attainment] of turtle-set y11Parents 
        set GCSE-score sumAttainment / length y11Parents 
        if(GCSE-score > 100) [ set GCSE-score 100 ]
      ]
    ]
  ]  
  
  ;GCSE-score is the mean of the last Parent-Memory years, just like max-distances
  ask schools
  [
    set GCSE-scores lput GCSE-score GCSE-scores ;add the GCSE-scores to the list of GCSE-scores
    if(length GCSE-scores > Parent-Memory) [ set GCSE-scores remove-item 0 GCSE-scores ]  ;only keep track of last *Memory* years distances
  ] 
  
  ask schools [ set GCSE-score mean GCSE-scores ]
end 

to set-SchoolCatchments
  
  ;creates a list of patches within the school catchment that are free to move into this timestep
  
  ;if this is the first tick (ticks = 0) max-distances will not have been set
  ifelse(ticks > 0)
  [
    ask schools
    [
      set catchmentPatches []       
      set catchmentPatches sort patches with [distance myself < min [mean-distances] of myself and not any? turtles-here] 
    ]
  ]
  
  [
    ask schools
    [
      set catchmentPatches []       
      set catchmentPatches sort patches with [distance myself < (2 * world-width) and not any? turtles-here] 
    ]
  ]
end 

to move
   
  ask parents [ if(child-age = 10 and have-moved = false) [set want-to-move false ] ] ;don't move once child-age > 10

  let movers no-turtles
  
  set movers parents with [child-age = 9 and want-to-move = true and have-moved = false]

  ask schools
  [
    ifelse(Move-Closest = true) 
    [ set catchmentPatches sort-by [ [distance myself] of ?1 < [distance myself] of ?2] catchmentPatches ]
    [ set catchmentPatches shuffle catchmentPatches ]
  ]   
  
  
    
  ask movers
  [ 
    let thisRank 0
    
    while[thisRank < Number-of-Ranks]
    [
      if(newHome = nobody)
      [
        let thisSchool item thisRank [rankings] of self
        
        ;check if I think I am already in this school's catchment
        ;if so, only move if can move closer AND to a patch with greater value than current location value (but still less than my aspiration)
        ;no need to check other schools in rankings once this has been done...
        
        ;if not, and I am checking this school, it must be higher ranked than the school catchment I am currently in so move there regardless of patchvalue (although still less than my aspiration)
        
        if(is-agent? thisSchool and [school-type] of thisSchool != "new") ;ranking may contain non-Schools (i.e. -1 values) - do not try to move near to 'new' schools (no need as they do not allocate on distance. Also, catchment is entire world so make little point in moving anywhere within the world)
        [
          if(not empty? [catchmentPatches] of thisSchool) ;if this school has available patches in its catchment
          [            
            ;if there is a restriction on where to move
            ifelse(Location-Rules = true)
            [
              let location-value-max aspiration 
              
              ;for each available patch in the school catchment, check if location-value is less than parent's aspiration
              let tempCatchment patch-set [catchmentPatches] of thisSchool
              set tempCatchment tempCatchment with [location-value < location-value-max or location-value = -1]
              
              ;if parent should maximise proximity to school
              ifelse(Move-Closest = true)
              [
                if(any? tempCatchment) 
                [ 
                  set newHome min-one-of tempCatchment [distance thisSchool]
                  set move-target thisSchool
                ]
              ]
              
              ;else move to any patch
              [ 
                if(any? tempCatchment) 
                [ 
                  set newHome one-of tempCatchment 
                  set move-target thisSchool 
                ]
              ]
            ]
            
            ;else move anywhere within school catchment
            [
              
              ;if parent should maximise proximity to school
              ifelse(Move-Closest = true)
              [
                let shortDistance 9999 ;holder for distance to closest available patch
                
                ask(thisSchool)
                [                   
                  set shortDistance distance first catchmentPatches
                ]
                
                ;if closest available patch is closer than my current position, move
                if(distance thisSchool > shortDistance)
                [ 
                  set newHome first [catchmentPatches] of thisSchool 
                  set move-target thisSchool
                ] 
              ]
              
              ;else parent should move anywhere in catchment
              [
                set newHome first [catchmentPatches] of thisSchool
                set move-target thisSchool
              ]
            ]   
            
            if(newHome != nobody)
            [
              ;show initialHome
              ask schools 
              [ 
                ;if(member? [newHome] of myself catchmentPatches) [ show word "removing newHome: " [newHome] of myself ] 
                ask [newHome] of myself [if(any? parents-here) [ show "error - already a parent at new home!" ] ]
                set catchmentPatches remove [newHome] of myself catchmentPatches 
              ] 
              
              ask schools [ add-available-home-to-catchment [initialHome] of myself ]
            ]
          ]
        ]
        
        if(newHome != nobody) 
        [ 
          move-to newHome 
          
          if(any? other parents-here) ;Error check 
          [ 
            let pid [who] of other parents-here 
            show word "Error: another parent already here, agent:" pid  
          ]           
          
          set have-moved true
          ask(initialHome) 
          [ 
            set-location-value ;this works because parent can only move once.
            if(any? parents-here) [ show "error - still a parent here!" ]
          ] 
        ]
      ]
        
      set thisRank thisRank + 1    
    ]
    
    set-parent-school-distance ;update distances list
  ]
end 

to add-available-home-to-catchment [ availableHome ]
    
  let add false  
  ifelse(ticks = 0) ;if ticks = 0, mean-distances will be empty causing an error when checked with an if statement (and catchmentPatches will contain all patches so always add when ticks = 0)
  [set add true ] 
  [ if(distance availableHome < min mean-distances) [ set add true ] ] 
    
  if(add)  
  [
    ;show word "adding availableHome: " availableHome
    
    set catchmentPatches sentence availableHome catchmentPatches
    
    ifelse(Move-Closest = true) 
    [ set catchmentPatches sort-by [ [distance myself] of ?1 < [distance myself] of ?2] catchmentPatches ]
    [ set catchmentPatches shuffle catchmentPatches ]
  ] 
end 

to rank-Schools

  let reporter nobody
  
  ask parents with [child-age = 10 or (have-moved = false and child-age = 9)]
  [
    ;parents calculate which catchments they are in by comparing their distance to each school with mean of last [memory] years of mean-distances 
    set rankings []
    
    ifelse(ticks >= 1) ;mean-distances (catchment) will not have been calculated in first step
    [  set catchment schools with [ distance myself < min [mean-distances] of self ] ] ;creates agentset of schools parent belives they are in the catchment for
    [  set catchment schools with [ distance myself < (world-width * 2) ]  ] ;creates agentset of schools parent belives they are in the catchment for
      
    if(any? catchment) [ set catchment sort-by [ [GCSE-score] of ?1 > [GCSE-score] of ?2 ] catchment ] ;changes agentset to list and ranks on GCSE score (descending) 
      
    set considered schools with [ GCSE-score >= [aspiration] of myself ] ;creates agentset of school parent believes are good enough
    if(any? considered) [ set considered sort-by [ [GCSE-score] of ?1 > [GCSE-score] of ?2 ] considered ] ;changes agentset to list and ranks on GCSE score (descending)
    
    set avoided schools with [ GCSE-score < ([aspiration] of myself * Avoided-Threshold) ] ;avoided threshold must be >0 and <1
    
    if(Avoid-Schools = true) ;if not considering avoided schools, avoided is not changed to a list and therefore is assumed empty below
    [
      if(any? avoided) [ set avoided sort-by [ [GCSE-score] of ?1 > [GCSE-score] of ?2 ] avoided ] ;changes agentset to list and ranks on GCSE score (descending)
    ]
 
    ;ranking for moving (when child-age = 9) is different for ranking for allocating (when child-age = 10)
    ;for moving, parent ranks solely on GCSE score (and then evaluate which school catchments they are in and whether this is acceptable)
    ;for allocating, parents consider GCSE score AND distance

 
    ;rank for moving
    ;parents try to position themselves in considered (preferred) school catchments but not in avoided school catchments
   
    ;check if I want to move (don't move if I am in a considered school catchment AND am not in an avoided school catchment)  
    if(child-age = 9 and want-to-move = true and have-moved = false)
    [   
      let considered-present false
      let avoided-present false
      
      if(is-list? catchment) ;if is a list it has schools in it
      [  
        if(is-list? considered)  ;if is a list it has schools in it
        [
          foreach catchment [ if(member? ? considered and [school-type] of ? != "new") [ set considered-present true ] ] ;only consider state school catchments (will always be in the catchment of new schools which do not select on distance)
        ]
        
        if(is-list? avoided) ;if is a list it has schools in it
        [
          foreach catchment [ if(member? ? avoided) [ set avoided-present true ] ]
        ]
        
        if(considered-present = true) [ set want-to-move false ]  ;if there is a considered school in my catchment I will not move (move function will not execute if moved is true) 
        if(avoided-present = true) [ set want-to-move true ]  ;but if there is also an avoided school in my catchment, I will try to move
      ]      
     

      ;if I still want to move
      if(child-age = 9 and want-to-move = true)  
      [
        ;if there are considered schools, rank considered schools on GCSE-score
        ifelse(is-list? considered)
        [
          set rankings sort-by [ [GCSE-score] of ?1 > [GCSE-score] of ?2 ] considered  ;considered schools will never be avoided schools
          
          ;if I want to move and avoided is a list (i.e. there is something in it) I must be in the catchment of one of the avoided schools
          ;so add as many non-avoided schools as possible, in descending order of GCSE score
          if(is-list? avoided) 
          [
            let tempSchools sort-by [ [GCSE-score] of ?1 > [GCSE-score] of ?2 ] schools        
        
            ;add schools from tempSchools to end of rankings, unless it is already in rankings or is in avoided         
            foreach tempSchools
            [           
              if(not member? ? rankings and not member? ? avoided) [ set rankings lput ? rankings ]
            ] 
          ]
        ]
        
        ;if there are no considered schools, rank all schools by GCSE-score but do not include avoided
        [
          set rankings [] ;check there's nothing in rankings
          let tempSchools sort-by [ [GCSE-score] of ?1 > [GCSE-score] of ?2 ] schools     
           
          ifelse(is-list? avoided) ;will be a list if it has something in it
          [ 
            foreach tempSchools
            [
              ;if this school is not in the avoided list, add it to the rankings list
              if(not member? ? avoided) [ set rankings lput ? rankings ]
            ]
          ]
          
          ;if there is nothing in avoided add all schools
          [
            foreach tempSchools 
            [ 
              if(not member? ? rankings) [set rankings lput ? rankings ]
            ] 
          ]
        ]
      ]
    ] 
      
       
    ;rank for allocating
    if(child-age = 10)  
    [      
      ifelse(is-agentset? catchment) ;if still an agentsent (and not converted to list) it is empty
      [
        ifelse(is-agentset? considered) ;if still an agentsent (and not converted to list) it is empty
        [
          ;catchment and considered are both empty (i.e. there are no schools with GCSE-score higher than my aspiration and I am not near any school)      
          ;strategy here is to rank all schools on distance, but do not include avoided in the rankings
          
          set strategy 1 
          
          ifelse(is-list? avoided) ;will be a list if it has something in it
          [
            set strategy 2  
            
            let tempSchools sort-by [ [distance myself] of ?1 < [distance myself] of ?2 ] schools     
            
            foreach tempSchools
            [
              ;if this school is not in the avoided list, add it to the rankings list
              if(not member? ? rankings and not member? ? avoided) [ set rankings lput ? rankings ]
            ]
          ]
          
          ;if nothing in avoided add all schools to ranking based on distance
          [ set rankings sort-by [ [distance myself] of ?1 < [distance myself] of ?2 ] schools ]
        ]        
        
        [
          ;catchment is empty, considered is not empty (i.e. there are schools with GCSE-score higher than my aspiration and but I am not near any of them [or any school])  
          ;strategy here is to rank considered schools on distance, then all schools on distance but do not include avoided
          
          set strategy 3   
          
          set rankings sort-by [ [distance myself] of ?1 < [distance myself] of ?2 ] considered  ;considered schools will never be avoided schools
          let tempSchools sort-by [ [distance myself] of ?1 < [distance myself] of ?2 ] schools        
          
          ifelse(is-list? avoided) ;will be a list if it has something in it
          [
            set strategy 4  
                      
            ;add schools from tempSchools to end of rankings, unless it is already in rankings or is in avoided         
            foreach tempSchools
            [           
              if(not member? ? rankings and not member? ? avoided) [ set rankings lput ? rankings ]
            ] 
          ]
          
          [
            ;else if nothing in avoided, add tempSchools to end of rankings
            foreach tempSchools
            [           
              if(not member? ? rankings) [ set rankings lput ? rankings ]
            ] 
          ] 
        ]
      ] 
  
      [
        ;catchment has schools in it [always full if distance-allocation = T]
        
        ifelse(is-agentset? considered) ;if still an agentsent (and not converted to list) it is empty
        [
          ;catchment is not empty but considered is (i.e. there are schools I will likely be allocated but I do not consider them good enough)
          ;strategy here is to rank catchment on GCSE-score (descending), then all other schools on distance, but do not include avoided schools
          ;[justfied to still rank on distance when distance-allocatin = F as parents still like their kids to go to school nearby]
          
          set strategy 5   
          
          let tempCatchment catchment ;already sorted by GCSE
          let tempSchools sort-by [ [distance myself] of ?1 < [distance myself] of ?2 ] schools  
          
          
          ;reporting code for debugging
          ;if(reporter = nobody)
          ;[
          ;  set reporter self
          ;  show tempCatchment
          ;  show tempSchools
          ;  show rankings
          ;]
          
          ifelse(is-list? avoided) ;will be a list if it has something in it
          [
            set strategy 6   
            
            ;add schools from tempCatchment to rankings, unless it is in avoided         
            foreach tempCatchment
            [           
              if(not member? ? rankings and not member? ? avoided) [ set rankings lput ? rankings ]
            ]
            
            ;add schools from tempSchools to end of rankings, unless it is already in rankings or is in avoided         
            foreach tempSchools
            [           
              if(not member? ? rankings and not member? ? avoided) [ set rankings lput ? rankings ]
            ]
          ]
          
          ;else if nothing in avoided, add tempCatchment and tempSchools to end of rankings
          [
            foreach tempCatchment [ if(not member? ? rankings) [ set rankings lput ? rankings ] ]
            foreach tempSchools [ if(not member? ? rankings) [ set rankings lput ? rankings ] ]
          ] 
          
          ;reporting code for debugging          
          ;if(reporter = self)
          ;[
          ;  show tempCatchment
          ;  show tempSchools
          ;  show rankings
          ;]
        ]
        
        
        [          
          ;neither catchment nor considered is empty
          ;rank catchment on GCSE-score (descending), then considered on distance, then all other schools on distance but do not include avoided
          
          set strategy 7     
           
          let tempCatchment catchment ;already sorted by GCSE
          let tempConsidered sort-by [ [distance myself] of ?1 < [distance myself] of ?2 ] considered
          let tempSchools sort-by [ [distance myself] of ?1 < [distance myself] of ?2 ] schools  
        
         
          
          ifelse(is-list? avoided) ;will be a list if it has something in it
          [
            set strategy 8   
            
            ;if this school is not in the avoided list, add it to the rankings list
            foreach tempCatchment
            [
              if(not member? ? rankings and not member? ? avoided) [ set rankings lput ? rankings ]
            ]
            
            ;add schools from tempConsidered to end of rankings, unless it is already in rankings or is in avoided         
            foreach tempConsidered
            [           
              if(not member? ? rankings and not member? ? avoided) [ set rankings lput ? rankings ]
            ] 
            
            ;add schools from tempSchools to end of rankings, unless it is already in rankings or is in avoided         
            foreach tempSchools
            [           
              if(not member? ? rankings and not member? ? avoided) [ set rankings lput ? rankings ]
            ]  
          ] 
          
          ;else if nothing in avoided, add tempRankings, tempConsidered and tempSchools to end of rankings
          [
            foreach tempCatchment [ if(not member? ? rankings) [ set rankings lput ? rankings ] ]
            foreach tempConsidered [ if(not member? ? rankings) [ set rankings lput ? rankings ] ]
            foreach tempSchools [ if(not member? ? rankings) [ set rankings lput ? rankings ] ]
          ]    
        ]
      ]
      
    ]
      
 
    if(not empty? rankings)
    [
      ;rankings may be too long, if so remove items 
      if(length rankings > Number-of-Ranks)
      [
        set rankings reverse rankings ;its faster to remove from the front (and don't need to know length of rankings)
        
        while[length rankings > Number-of-Ranks]
        [
          set rankings remove-item 0 rankings
        ]
        
        set rankings reverse rankings
      ]
    ]
    
    
          
    ;rankings always needs to be of length Number-of-Ranks to prevent out-of-list search in allocate-Places function (so add dummy values to fill list)
    if(length rankings < Number-of-Ranks)
    [
      let thisRank length rankings
      
      while[thisRank < Number-of-Ranks]
      [
        set rankings lput -1 rankings
        set thisRank thisRank + 1
      ]
      
      ;set rankings empty-rankings
    ]
    
    
    ;reporting code for debugging
    ;if(reporter = self)
    ;    [
    ;      show rankings
    ;      set reporter true
    ;    ]

  ]
end 

to set-patch-attributes ;for ALL patches
  
  ask patches 
  [ 
    set location-value 0 
    set p-aspiration 0
    set p-attainment 0
  ]
  
  ask patches
  [
    ifelse(School-Quality-Effect > 0)
    [
      let nearestSchools sort-by [[distance myself] of ?1 < [distance myself] of ?2] schools
      let schoolValue [GCSE-score] of first nearestSchools
      
      let dist distance first nearestSchools
      
      ifelse(dist < (schoolRadii * 2))    
      [ set schoolValue (1 - ( dist / (schoolRadii * 2))^ 0.5) * schoolValue ]
      [ set schoolValue 0 ]
      
      ifelse(any? parents-on neighbors)
      [ set location-value ((mean [aspiration] of parents-on neighbors) * (1 - School-Quality-Effect)) + (schoolValue * School-Quality-Effect) ]
      [ set location-value 0 + (schoolValue * School-Quality-Effect) ]
    ]
    
    [
      if(any? parents-on neighbors) [ set location-value mean [aspiration] of parents-on neighbors ]
    ]
  ]
  
  ask patches with [location-value = 0]
  [
    print "zero location-value on neighbours"
    set location-value mean [location-value] of neighbors
  ]
  
  ask patches with [any? parents-here ] 
  [ 
    set p-aspiration mean [aspiration] of parents-here        ;use mean to prevent run time error when checking patches without parents below 
    set p-attainment mean [child-attainment] of parents-here  ;use mean to prevent run time error when checking patches without parents below
  ]
 
  ask patches with [not any? parents-here] [ set p-aspiration mean [p-aspiration] of neighbors ]
  ask patches with [not any? parents-here] [ set p-attainment mean [p-attainment] of neighbors ]
end  

to set-location-value  ;for a SINGLE patch

  ifelse(School-Quality-Effect > 0)
  [
    let nearestSchools sort-by [[distance myself] of ?1 < [distance myself] of ?2] schools
    let schoolValue [GCSE-score] of first nearestSchools
    
    let dist distance first nearestSchools
    
    ifelse(dist < (schoolRadii * 2))    
    [ set schoolValue (1 - ( dist / (schoolRadii * 2))^ 0.5) * schoolValue ]
    [ set schoolValue 0 ]
    
    ifelse(any? parents-on neighbors)
    [ set location-value ((mean [aspiration] of parents-on neighbors) * (1 - School-Quality-Effect)) + (schoolValue * School-Quality-Effect) ]
    [ set location-value 0 + (schoolValue * School-Quality-Effect) ]
  ]
  
  [
    ifelse(any? parents-on neighbors)
    [ set location-value mean [aspiration] of parents-on neighbors ]
    [ set location-value mean [location-value] of neighbors ]
  ]
end  


;;----------------------------------
;;END SIMULATION
;;----------------------------------







;;----------------------------------
;;PLOTTING
;;----------------------------------

to plotting
  
  do-line-plots
  do-bar-plots
  do-scatter-plots
end 

to do-line-plots
  
    
  set-current-plot "GCSE-score-trend"
  

  set-current-plot-pen "max"
  ask max-one-of schools [GCSE-score] 
  [ 
    set-plot-pen-color (id * 10) + 15
    plot GCSE-score 
  ]
  
  set-current-plot-pen "mean"
  let mGCSE mean [GCSE-score] of schools
  plot mGCSE
  
  set-current-plot-pen "min"
  ask min-one-of schools [GCSE-score] 
  [ 
    set-plot-pen-color (id * 10) + 15
    plot GCSE-score 
  ]
  
  set-current-plot "Max-Distances"
  
  set-current-plot-pen "max"
  ask max-one-of schools [GCSE-score] 
  [ 
    set-plot-pen-color (id * 10) + 15
    plot max-distance 
  ]
  
  set-current-plot-pen "min"
  ask min-one-of schools [GCSE-score]
  [ 
    set-plot-pen-color (id * 10) + 15
    plot max-distance 
  ]
  
  let mean-max-distances mean [max-distance] of schools
  set-current-plot-pen "mean"
  plot mean-max-distances
  
  
  set-current-plot "Mean-Distance"
  
  set-current-plot-pen "max"
  ask max-one-of schools [GCSE-score] 
  [ 
    set-plot-pen-color (id * 10) + 15
    plot mean-distance 
  ]
  
  set-current-plot-pen "min"
  ask min-one-of schools [GCSE-score] 
  [ 
    set-plot-pen-color (id * 10) + 15
    plot mean-distance 
  ]
  
  let mean-mean-distances mean [mean-distance] of schools
  set-current-plot-pen "mean"
  plot mean-mean-distances
  
  
  set-current-plot "Satisfaction"
  if(Success-Type = "ranking")
  [

    let dcolor Number-of-Ranks / 3 ;set top third of ranks green, second third yellow, bottom third orange, unranked red
    if(Number-of-Ranks < 3) [ set dcolor Number-of-Ranks ]          
          
    let count-green 0
    let count-yellow 0
    let count-orange 0
    let count-red 0      

    let totParents count parents with [child-age = 11]
                
    ask parents with [child-age = 11]
    [

      let thisRank 0 
      
      ;if the allocated-school was ranked
      ifelse(member? allocated-school rankings)
      [       
        while[thisRank < length rankings]
        [
          if(item thisRank rankings = allocated-school)
          [ 
            ifelse(thisRank < dcolor) [ set count-green count-green + 1 ]
            [ 
              ifelse(thisRank < dcolor * 2) [ set count-yellow count-yellow + 1 ]
              [ set count-orange count-orange + 1]
            ]
          ]
          set thisRank thisRank + 1
        ]
      ]
      
      ;if the allocated-school was not ranked set color red
      [ set count-red count-red + 1 ]
    ]
    
    if(ticks > 0)
    [
      set-current-plot-pen "green"
      plot count-green / totParents
      
      set-current-plot-pen "yellow"
      plot count-yellow / totParents
      
      set-current-plot-pen "orange"
      plot count-orange / totParents
      
      set-current-plot-pen "red"
      plot count-red / totParents 
    ]
  ]
  
  if(Success-Type = "aspiration")
  [
    let count-green 0
    let count-red 0
    let totAlloc count parents with [allocated-school != 0]
    
    ask parents with [allocated-school != 0]
    [
      if(aspiration > [GCSE-score] of allocated-school) [ set count-green count-green + 1 ]
      if(aspiration < [GCSE-score] of allocated-school) [ set count-red count-red + 1 ] 
    ]
    
    if(ticks > 0)
    [
      set-current-plot-pen "green"
      plot count-green / totAlloc
      
      set-current-plot-pen "red"
      plot count-red / totAlloc
    ]
  ]
end 

to do-bar-plots
  
    
  set-current-plot "Application-Ratio"
  clear-plot
  set-current-plot-pen "s"
  set-plot-pen-color black
    
  ifelse(Ordered-Plots = false) 
  [ ask-concurrent schools [ plotxy id app-ratio ] ]
  [ 
    let tempSchools sort-by [ [app-ratio] of ?1 > [app-ratio] of ?2 ] schools
    foreach tempSchools [ plot [app-ratio] of ? ]
  ]
   
  set-current-plot "GCSE-scores"
  clear-plot
  set-current-plot-pen "s"
  
  ifelse(Ordered-Plots = false) 
  [ ask-concurrent schools [ plotxy id GCSE-score ]  ]
  [ 
    let tempSchools sort-by [ [GCSE-score] of ?1 > [GCSE-score] of ?2 ] schools
    foreach tempSchools [ plot [GCSE-score] of ? ]
  ]
  
  set-current-plot "Max-Distance"
  clear-plot
  set-current-plot-pen "s"

  ifelse(Ordered-Plots = false) 
  [ ask-concurrent schools [ plotxy id max-distance ] ]
  [
    let tempSchools sort-by [ [max-distance] of ?1 > [max-distance] of ?2 ] schools
    foreach tempSchools [ plot [max-distance] of ? ]
  ]
end 

to do-scatter-plots
    
  set-current-plot "MaxDistance-GCSE"
  clear-plot
  set-current-plot-pen "max"
  ask schools
  [
    ;set-plot-pen-color (id * 10) + 15
    set-plot-pen-color black
    plotxy GCSE-score max-distance
  ]
  
   set-current-plot "MaxDistance-App"
  clear-plot
  set-current-plot-pen "default"
  ask schools
  [
    ;set-plot-pen-color (id * 10) + 15
    set-plot-pen-color black
    plotxy app-ratio max-distance
  ]
  
  ;set-current-plot "MeanDistance-GCSE"
  ;clear-plot
  ;set-current-plot-pen "default"
  ;ask schools
  ;[
  ;  set-plot-pen-color (id * 10) + 15
  ;  plotxy GCSE-score mean-distance
  ;]
  
  ;set-current-plot "MeanDistance-App"
  ;clear-plot
  ;set-current-plot-pen "default"
  ;ask schools
  ;[
  ;  set-plot-pen-color (id * 10) + 15
  ;  plotxy app-ratio mean-distance
  ;]
    
  set-current-plot "AppRatio-GCSE"
  clear-plot
  set-current-plot-pen "default"
  ask schools
  [
    ;set-plot-pen-color (id * 10) + 15
    set-plot-pen-color black
    plotxy GCSE-score app-ratio
  ]
  
  if(School-Value-Added)
  [
    set-current-plot "AppRatio-ValueAdded"
    clear-plot
    set-current-plot-pen "default"
    ask schools
    [
      ;set-plot-pen-color (id * 10) + 15
      set-plot-pen-color black
      plotxy app-ratio value-added
    ]
  ]
end 
;;----------------------------------
;;END PLOTTING
;;----------------------------------






;;----------------------------------
;;DISPLAY
;;----------------------------------

to update-Colours
  
  let bestSchool max-one-of schools [GCSE-score]
  let worstSchool min-one-of schools [GCSE-score]
  
  ;show parents with specified colours
  ifelse(Patch-Value = false)
  [
    ask patches [ set pcolor black ]
      
    ask parents
    [
      set hidden? false
      
      if(Parent-Colours = "satisfaction")
      [
        ifelse(child-age < 10 or allocated-school = 0)
        [ set color grey ]
        
        [
          if(Success-Type = "ranking")
          [
            let dcolor Number-of-Ranks / 3 ;set top third of ranks green, second third yellow, bottom third orange, unranked red
            if(Number-of-Ranks < 3) [ set dcolor Number-of-Ranks ]          
            
            let thisRank 0
            
            ;if the allocated-school was ranked
            ifelse(member? allocated-school rankings)
            [       
              while[thisRank < length rankings]
              [
                if(item thisRank rankings = allocated-school)
                [ 
                  ifelse(thisRank < dcolor) [ set color green ]
                  [ 
                    ifelse(thisRank < dcolor * 2) [ set color yellow ]
                    [ set color orange ]
                  ]
                ]
                set thisRank thisRank + 1
              ]
            ]
            
            ;if the allocated-school was not ranked set color red
            [ set color red ]
          ]
          
          if(Success-Type = "aspiration")
          [
            ifelse(aspiration < [GCSE-score] of allocated-school) 
            [ set color green ]
            [ set color red ]
          ]
          
          if(Success-Type = "attainment")
          [
            ifelse(child-attainment >= aspiration) 
            [ set color green ]
            [ set color red ]
          ]
          
        ]
      ] 
      
      
      
      if(Parent-Colours = "school")
      [
        ifelse(child-age < 10 or allocated-school = 0) 
        [ set color grey ]
        [ set color [id] of allocated-school * 10 + 15 ]
      ]
      
      if(Parent-Colours = "aspiration")
      [
        ifelse(aspiration = 100) 
        [ set color 19.9 ]
        [ set color (aspiration / 10) + 10 ]
      ]
      
      if(Parent-Colours = "attainment")
      [
        ifelse(allocated-school = 0)
        [ set color grey ]
        [
          ifelse(child-attainment = 100) 
          [ set color 29.9 ]
          [ set color (child-attainment / 10) + 20 ]
        ]
      ]
      
      if(Parent-Colours = "attainment-change")
      [
        ifelse(allocated-school = 0)
        [ set color grey ]
        [
          let diffc child-attainment - aspiration
          
          ifelse(diffc < 0)
          [            
            ifelse(diffc = -100) 
            [ set color 22 ]
            [ set color 27 - (diffc / -20) ]
          ]
          
          [
            ifelse(diffc = 100) 
            [ set color 62 ]
            [ set color 67 - (diffc / 20) ]
          ]
          
        ]
      ]
      
      if(Parent-Colours = "moved")
      [
        ifelse(allocated-school = 0)
        [ set color grey ]
        [
          ifelse(have-moved = true)
          [ set color green ]
          [ set color red ]
        ]
      ]
      
      if(Parent-Colours = "best school allocation")
      [
        ifelse(allocated-school = 0)
        [ set color grey ]
        [
          ifelse(member? bestSchool rankings)
          ;ifelse(item 0 rankings = bestSchool)
          [
            ifelse(allocated-school = bestSchool)
            [ set color green ]
            [ set color red ]
          ]
          [ set color grey]
        ]
      ]
      
      if(Parent-Colours = "worst school allocation")
      [
        ifelse(allocated-school = 0)
        [ set color grey ]
        [
          ifelse(member? worstSchool rankings)
          ;ifelse(item 0 rankings = worstSchool)
          [
            ifelse(allocated-school = worstSchool)
            [ set color green ]
            [ set color red ]
          ]
          [ set color grey]
        ]
      ]
      
      
      if(Parent-Colours = "strategy")
      [
        ifelse(allocated-school = 0)
        [ set color grey ]
        [ set color ((strategy * 10 + 4)) ]
      ] 
      
      if(Parent-Colours = "age")
      [
        if(child-age = 9) [ set color 19 ]
        if(child-age = 10) [ set color 18 ]
        if(child-age = 11) [ set color 17 ]
        if(child-age = 12) [ set color 16 ]
        if(child-age = 13) [ set color 15 ]
        if(child-age = 14) [ set color 14 ]
        if(child-age = 15) [ set color 13 ]
        if(child-age = 16) [ set color 12 ]
      ] 
      
      if(Parent-Colours = "allocated-distance")
      [
        set color (allocated-distance / 8) + 122
      ]
             
    ]
    
    if(Show-Unallocated = false)
    [
      ask parents with [allocated-school = 0] [ set hidden? true ] 
    ] 


    if(ChildAge = "<9") [ ask parents with [child-age > 8] [ set color grey ] ]
    if(ChildAge = "9") [ ask parents with [child-age != 9] [ set color grey ] ]
    if(ChildAge = "10") [ ask parents with [child-age != 10] [ set color grey ] ]
    if(ChildAge = "11") [ ask parents with [child-age != 11] [ set color grey ] ]
    if(ChildAge = "12") [ ask parents with [child-age != 12] [ set color grey ] ]
    if(ChildAge = "13") [ ask parents with [child-age != 13] [ set color grey ] ]
    if(ChildAge = "14") [ ask parents with [child-age != 14] [ set color grey ] ]
    if(ChildAge = "15") [ ask parents with [child-age != 15] [ set color grey ] ]
    if(ChildAge = "16") [ ask parents with [child-age != 16] [ set color grey ] ]
    if(ChildAge = ">16") [ ask parents with [child-age < 17] [ set color grey ] ]
    if(ChildAge = "SchoolAge") [ ask parents with [child-age < 10 or child-age > 16 ] [ set color grey ] ]
    
    if(DistanceClass = "0-10") [ ask parents with [allocated-distance > 10] [ set color grey ] ]
    if(DistanceClass = "10-20") [ ask parents with [allocated-distance <= 10 or allocated-distance > 20] [ set color grey ] ]
    if(DistanceClass = "20-30") [ ask parents with [allocated-distance <= 20 or allocated-distance > 30] [ set color grey ] ]
    if(DistanceClass = "30-40") [ ask parents with [allocated-distance <= 30 or allocated-distance > 40] [ set color grey ] ]
    if(DistanceClass = "40-50") [ ask parents with [allocated-distance <= 40 or allocated-distance > 50] [ set color grey ] ]
    if(DistanceClass = "50-60") [ ask parents with [allocated-distance <= 50 or allocated-distance > 60] [ set color grey ] ]
    if(DistanceClass = ">60") [ ask parents with [allocated-distance <= 60 ] [ set color grey ] ]
    
    if(AspirationClass = "0-10") [ ask parents with [aspiration > 10] [ set color grey ] ]
    if(AspirationClass = "10-20") [ ask parents with [aspiration <= 10 or aspiration > 20] [ set color grey ] ]
    if(AspirationClass = "20-30") [ ask parents with [aspiration <= 20 or aspiration > 30] [ set color grey ] ]
    if(AspirationClass = "30-40") [ ask parents with [aspiration <= 30 or aspiration > 40] [ set color grey ] ]
    if(AspirationClass = "40-50") [ ask parents with [aspiration <= 40 or aspiration > 50] [ set color grey ] ]
    if(AspirationClass = "50-60") [ ask parents with [aspiration <= 50 or aspiration > 60] [ set color grey ] ]
    if(AspirationClass = "60-70") [ ask parents with [aspiration <= 60 or aspiration > 70] [ set color grey ] ]
    if(AspirationClass = "70-80") [ ask parents with [aspiration <= 70 or aspiration > 80] [ set color grey ] ]
    if(AspirationClass = "80-90") [ ask parents with [aspiration <= 80 or aspiration > 90] [ set color grey ] ]
    if(AspirationClass = "90-100") [ ask parents with [aspiration <= 90 or aspiration > 100] [ set color grey ] ]

  ]
  
  
  
  ;else don't show parents and show location value
  [
    ask parents [ set hidden? true ]
    
    ifelse(Parent-Colours = "aspiration")
    [
      ask patches
      [        
        ifelse(p-aspiration = 100) 
        [ set pcolor 19.9 ]
        [ set pcolor (p-aspiration / 10) + 10 ]
      ]
    ]
    
    [
      ask patches
      [
        ifelse(location-value = -1)
        [ set pcolor black ]
        [ set pcolor (location-value / 10) + 10 ]
      ]
    ]
  ]
  
  
  
  ;always show schools
  let max-ratio max [app-ratio] of schools
  let max-value-added max [value-added] of schools
  let min-value-added min [value-added] of schools
      
  ask schools
  [
    if(School-Colours = "id")
    [
      set color (id * 10) + 15  ;first school will be red 
    ]
    
    
    if(School-Colours = "GCSE")
    [
      ifelse(GCSE-score = 100) 
      [ set color 49.9 ]
      [ set color (GCSE-score / 10) + 40 ]  
    ]
    
    if(School-Colours = "app-ratio")
    [
      if(max-ratio != 0)
      [
        let scaled-ratio app-ratio / max-ratio
        ifelse(scaled-ratio = 1) 
        [ set color 59.9 ]
        [ set color (scaled-ratio * 10) + 50 ] 
      ]
    ]
     
    
    if(School-Colours = "value-added")
    [
      ifelse(value-added < 0)
      [
        let scaled-va value-added / (min-value-added * 2)
        ifelse(scaled-va = 0.5) 
        [ set color 80.5 ]      ;don't set to 80 b/c unable to see icon on the grid
        [ set color 85 - (scaled-va * 10) ] 
      ]
      [ 
        let scaled-va value-added / (max-value-added * 2)
        ifelse(scaled-va = 0.5) 
        [ set color 89.9 ]
        [ set color (scaled-va * 10) + 85 ] 
      ]
    ]
    
    if(Parent-Colours = "best school allocation")
    [
      ifelse(id != [id] of bestSchool) 
      [ set color grey ]
      [ set color yellow ]
    ]
    
    if(Parent-Colours = "worst school allocation")
    [
      ifelse(id != [id] of worstSchool) 
      [ set color grey ]
      [ set color yellow ]
    ]
    
  ]
  
  
  if(Single-School)
  [
    ask parents 
    [
      ifelse(allocated-school = 0)
      [set color grey]
      [ if([id] of allocated-school != Shown-School) [ set color grey ] ]
    ]
    
    ask schools with [id != Shown-School ] [ set color grey ]
  ]
end 
;;----------------------------------
;;END DISPLAY
;;----------------------------------






;;----------------------------------
;;DATA EXPORT
;;----------------------------------

to ExportPlots
  
  let prefix "plots"
  let suffix ".csv"
  let index next-index prefix suffix
  let filename (word prefix index suffix)

  export-all-plots filename
end 

to ExportView
  
  let prefix "interface"
  let suffix ".png"
  let index next-index prefix suffix
  let filename (word prefix index suffix)

  export-view filename
end 

;from TurtleZero?

to-report next-index [ prefix suffix ]
  let index 0
  let filename (word prefix index suffix )
  while [ file-exists? filename ]
  [ 
    set index index + 1
    set filename (word prefix index suffix )
  ]
  report index
end 

to ExportSummaryData
  
  show "Exporting summary data"
    
  ;file-open "Schools_SummaryData.csv"
  
  let dummy "Schools_SummaryData_Exp"
  let suffix ".csv"  
  let filename (word dummy exp-index suffix)
  file-open filename
     
  ask schools
  [
    
    ;summarise y7 parents
    let max-distance_y7 max-one-of turtle-set y7Parents [distance myself]
    ifelse(max-distance_y7 = nobody)
    [ set max-distance_y7 -1 ]
    [ set max-distance_y7 distance max-distance_y7 ]
    
    
    let mean-distance_y7 0
    let mean-aspiration_y7 0
    let mean-attainment_y7 0
    let parents_moved_y7 0
    let parents_strategy1_y7 0
    let parents_strategy2_y7 0
    let parents_strategy3_y7 0
    let parents_strategy4_y7 0
    let parents_strategy5_y7 0
    let parents_strategy6_y7 0
    let parents_strategy7_y7 0
    let parents_strategy8_y7 0
    let success-aspiration 0
    
    foreach y7Parents
    [
      set mean-distance_y7 mean-distance_y7 + distance ?
      set mean-aspiration_y7 mean-aspiration_y7 + [aspiration] of ?
      set mean-attainment_y7 mean-attainment_y7 + [child-attainment] of ? 
      if([have-moved] of ? = true) [ set parents_moved_y7 parents_moved_y7 + 1 ] 
      
      if([strategy] of ? = 1) [ set  parents_strategy1_y7  parents_strategy1_y7 + 1 ]
      if([strategy] of ? = 2) [ set  parents_strategy2_y7  parents_strategy2_y7 + 1 ]
      if([strategy] of ? = 3) [ set  parents_strategy3_y7  parents_strategy3_y7 + 1 ]
      if([strategy] of ? = 4) [ set  parents_strategy4_y7  parents_strategy4_y7 + 1 ]
      if([strategy] of ? = 5) [ set  parents_strategy5_y7  parents_strategy5_y7 + 1 ]
      if([strategy] of ? = 6) [ set  parents_strategy6_y7  parents_strategy6_y7 + 1 ]
      if([strategy] of ? = 7) [ set  parents_strategy7_y7  parents_strategy7_y7 + 1 ]
      if([strategy] of ? = 8) [ set  parents_strategy8_y7  parents_strategy8_y7 + 1 ]
      
      if(GCSE-score < [aspiration] of ?) [ set success-aspiration success-aspiration + 1 ]
    ]  
    
    
    ifelse(length y7Parents > 0)
    [ 
      set mean-distance_y7 mean-distance_y7 / length y7Parents
      set mean-aspiration_y7 mean-aspiration_y7 / length y7Parents
      set mean-attainment_y7 mean-attainment_y7 / length y7Parents 
      
    ]
    [ 
      set mean-distance_y7 -1 
      set mean-aspiration_y7 -1
      set mean-attainment_y7 -1
    ]
    
    
    
    ;summarise y11 parents
    let max-distance_y11 max-one-of turtle-set y11Parents [distance myself]
    ifelse(max-distance_y11 = nobody)
    [ set max-distance_y11 -1 ]
    [ set max-distance_y11 distance max-distance_y11 ]
 
    
    let mean-distance_y11 0
    let mean-aspiration_y11 0
    let mean-attainment_y11 0
    let success-attainment 0
    
    
    foreach y11Parents
    [
      set mean-distance_y11 mean-distance_y11 + distance ?
      set mean-aspiration_y11 mean-aspiration_y11 + [aspiration] of ?
      set mean-attainment_y11 mean-attainment_y11 + [child-attainment] of ?
      if([child-attainment] of ? > [aspiration] of ?) [ set success-attainment success-attainment + 1 ]
    ] 
    
    ifelse(length y11Parents > 0)
    [ 
      set mean-distance_y11 mean-distance_y11 / length y11Parents
      set mean-aspiration_y11 mean-aspiration_y11 / length y11Parents
      set mean-attainment_y11 mean-attainment_y11 / length y11Parents  
    ]
    
    [ 
      set mean-distance_y11 -1
      set mean-aspiration_y11 -1
      set mean-attainment_y11 -1 
    ]
    

    let mean-attainment_change_y11 0
    let count-attainment_change+_y11 0
    let count-attainment_change-_y11 0
    
    ask turtle-set y11Parents
    [
      let my-attainment-change child-attainment - aspiration
      set mean-attainment_change_y11 mean-attainment_change_y11 + my-attainment-change 
      
      ifelse(my-attainment-change > 0)
      [ set count-attainment_change+_y11 count-attainment_change+_y11 + 1 ]
      [ set count-attainment_change-_y11 count-attainment_change-_y11 + 1 ]
    ]
    
    ifelse(length y11Parents > 0)
    [ set mean-attainment_change_y11 mean-attainment_change_y11 / length y11Parents ]
    [ set mean-attainment_change_y11 -1 ]
    
    
    let unallocated []
    let all-applicants-list sort all-applicants 
    foreach all-applicants-list
    [ 
      if(not member? ? allocated) [set unallocated lput ? unallocated]
    ]
    let max-distance_unallocated max-one-of turtle-set unallocated [distance myself]
    ifelse(max-distance_unallocated = nobody)
    [ set max-distance_unallocated -1 ]
    [ set max-distance_unallocated distance max-distance_unallocated ]


    let mean-aspiration_unallocated 0
    let mean-distance_unallocated 0
    
    foreach unallocated
    [
      set mean-aspiration_unallocated mean-aspiration_unallocated + [aspiration] of ?
      set mean-distance_unallocated mean-distance_unallocated + distance ?
    ]
    
    ifelse(length unallocated > 0)
    [ 
      set mean-aspiration_unallocated mean-aspiration_unallocated / length unallocated
      set mean-distance_unallocated mean-distance_unallocated / length unallocated
    ]
    [ 
      set mean-aspiration_unallocated -1
      set mean-distance_unallocated -1
    ]

      

    let myRanks [ 0 0 0 0 0 0 ]  
    ask turtle-set allocated
    [

      let thisRank 0
      
      if(length rankings > 1)
      [
        while[thisRank < Number-of-Ranks]
        [
          if(item thisRank rankings = myself) [ set myRanks replace-item thisRank myRanks (item thisRank myRanks + 1) ]
          set thisRank thisRank + 1
        ]
      ]      
    ]
    
    let parents_rank1_y7 item 0 myRanks
    let parents_rank2_y7 item 1 myRanks
    let parents_rank3_y7 item 2 myRanks
    let parents_rank4_y7 item 3 myRanks
    let parents_rank5_y7 item 4 myRanks
    let parents_rank6_y7 item 5 myRanks
        
    let parents_unranked_y7 0
    ask turtle-set allocated [ if(not member? myself rankings) [ set parents_unranked_y7 parents_unranked_y7 + 1 ] ]
          
        
    let parents_avoiding_y7 0
    ask parents with [child-age = 11]
    [
      if(member? myself avoided) [ set parents_avoiding_y7 parents_avoiding_y7 + 1 ]
    ]
    
 
 
   
    file-type ticks
    file-type ","
    file-type id
    file-type ","
    file-type school-type
    file-type ","
    file-type xcor
    file-type ","
    file-type ycor
    file-type ","
    file-type all-pupils
    file-type ","
    file-type precision value-added 2
    file-type ","
    file-type precision GCSE-score 2
    file-type ","
    file-type precision app-ratio 2
    file-type ","
    file-type precision max-distance_y7 2
    file-type ","
    file-type precision max-distance_y11 2
    file-type ","
    file-type precision max-distance_unallocated 2
    file-type ","
    file-type precision mean-distance_y7 2
    file-type ","
    file-type precision mean-distance_y11 2
    file-type ","
    file-type precision mean-distance_unallocated 2
    file-type ","
    file-type precision mean-aspiration_y7 2
    file-type ","
    file-type precision mean-aspiration_y11 2
    file-type ","
    file-type precision mean-aspiration_unallocated 2
    file-type ","
    file-type precision mean-attainment_y7 2
    file-type ","
    file-type precision mean-attainment_y11 2
    file-type ","
    file-type precision parents_rank1_y7 2
    file-type ","
    file-type precision parents_rank2_y7 2
    file-type ","
    file-type precision parents_rank3_y7 2
    file-type ","
    file-type precision parents_rank4_y7 2
    file-type ","
    file-type precision parents_rank5_y7 2
    file-type ","
    file-type precision parents_rank6_y7 2
    file-type ","
    file-type precision parents_unranked_y7 2
    file-type ","
    file-type precision success-aspiration 2
    file-type ","
    file-type precision success-attainment 2
    file-type ","
    file-type precision parents_avoiding_y7 2
    file-type ","
    file-type precision parents_moved_y7 2
    file-type ","
    file-type precision mean-attainment_change_y11 2
    file-type ","
    file-type precision count-attainment_change+_y11 2
    file-type ","
    file-type precision count-attainment_change-_y11 2
    file-type ","
    file-type precision parents_strategy1_y7 2
    file-type ","
    file-type precision parents_strategy2_y7 2
    file-type ","
    file-type precision parents_strategy3_y7 2
    file-type ","
    file-type precision parents_strategy4_y7 2
    file-type ","
    file-type precision parents_strategy5_y7 2
    file-type ","
    file-type precision parents_strategy6_y7 2
    file-type ","
    file-type precision parents_strategy7_y7 2
    file-type ","
    file-print precision parents_strategy8_y7 2
    
  ]
      
    file-close

    ;file-open "Parents_Data.csv"
  
    set dummy "Parents_Data_Exp"
    set filename (word dummy exp-index suffix)
    file-open filename
   
    ask parents
    [
       file-type ticks
       file-type ","
       file-type who
       file-type ","
       file-type xcor
       file-type ","
       file-type ycor
       file-type ","
       file-type precision aspiration 2
       file-type ","
       file-type child-age
       file-type ","

       ifelse(allocated-school != 0)
       [ 
         file-type [id] of allocated-school
         file-type ","
       
         file-type precision allocated-distance 2 ;07Sept12 moved this line here from next ifelse to ensure distance is always output
         file-type ","
     
         ifelse(is-turtle? first rankings)  
         [
           file-type [id] of first rankings
           file-type ","
         ]
         [
           file-type -1
           file-type ","
         ]
         
         file-type success-by-rank
         file-type ","
         
         file-type success-rank1
         file-type ","
         
         file-type precision child-attainment 2
         file-type ","
                  
         file-type strategy
         file-type ","
         
         ifelse(have-moved) 
         [ file-print 1 ]
         [ file-print 0 ]
       ]
       
         
    
       [
         file-type -1
         file-type ","
         file-type -1
         file-type ","
         file-type -1
         file-type ","
         file-type -1
         file-type ","
         file-type -1
         file-type ","
         file-type -1
         file-type ","
         file-type -1
         file-type ","
         file-print -1
       ]
    ]
    
    file-close

    ;file-open "World_SummaryData.csv"
    
    set dummy "World_SummaryData_Exp"
    set filename (word dummy exp-index suffix)
    file-open filename
  
    file-type ticks
    file-type ","
    file-type mean [GCSE-score] of schools
    file-type ","
    file-type ((max [GCSE-score] of schools) - (min [GCSE-score] of schools))
    file-type ","
    file-type mean [app-ratio] of schools
    file-type ","
    file-type ((max [app-ratio] of schools) - (min [app-ratio] of schools))
    file-type ","
    file-type asp-moran-i
    file-type ","
    file-type asp-moran-i-p
    file-type ","
    file-type att-moran-i
    file-type ","
    file-type att-moran-i-p
    file-type ","
    file-type GA-m
    file-type ","
    file-type GA-r
    file-type ","
    file-type GA-p
    file-type ","
    file-type GMx-m
    file-type ","
    file-type GMx-r
    file-type ","
    file-type GMx-p
    file-type ","
    file-type GMn-m
    file-type ","
    file-type GMn-r
    file-type ","
    file-type GMn-p
    file-type ","
    file-type AMx-m
    file-type ","
    file-type AMx-r
    file-type ","
    file-type AMx-p
    file-type ","
    file-type AMn-m
    file-type ","
    file-type AMn-r
    file-type ","
    file-print AMn-p
    
    file-close
end 

to ExportSummaryData_header

  show "Exporting summary data"

  let dummy "Schools_SummaryData_Exp"
  let suffix ".csv"  
  let filename (word dummy exp-index suffix)
  file-open filename
  write-experiment-data
  file-print "Tick,School_id,school-type,school-x-cor,school-y-cor,all-pupils,Value-Added,GCSE-score,App-ratio,max-distance_y7,max-distance_y11,max-distance_unallocated,mean-distance_y7,mean-distance_y11,mean-distance_unallocated,mean-aspiration_y7,mean-aspiration_y11,mean-aspiration_unallocated,mean-attainment_y7,mean-attainment_y11,parents_rank1_y7,parents_rank2_y7,parents_rank3_y7,parents_rank4_y7,parents_rank5_y7,parents_rank6_y7,parents_unranked_y7,success-aspiration_y7,success-attainment_y11,parents_avoiding_y7,parents_moved_y7,mean-attainment_change_y11,count-attainment_change+_y11,count-attainment_change-_y11,parents_strategy1_y7,parents_strategy2_y7,parents_strategy3_y7,parents_strategy4_y7,parents_strategy5_y7,parents_strategy6_y7,parents_strategy7_y7,parents_strategy8_y7"
  file-close
  
  set dummy "Parents_Data_Exp"
  set filename (word dummy exp-index suffix)
  file-open filename
  file-print word "Date/time: " date-and-time
  file-print "Tick,parent,x-cor,y-cor,aspiration,child-age,allocated-school,allocated-distance,preferred-school,allocated-rank,success-rank1,child-attainment,strategy,have-moved"
  file-close
  
  set dummy "World_SummaryData_Exp"
  set filename (word dummy exp-index suffix)
  file-open filename
  write-experiment-data
  file-print "Tick,MeanGCSE,RangeGCSE,MeanAppRatio,RangeAppRatio,asp-moran-i,asp-moran-i-p,pv-moran-i,pv-moran-i-p,GA-m,GA-r,GA-p,GMx-m,GMx-r,GMx-p,GMn-m,GMn-r,GMn-p,AMx-m,AMx-r,AMx-p,AMn-m,AMn-r,AMn-p"
  file-close
end 

to write-experiment-data
  
  ;FILE MUST ALREADY BE OPEN!
  file-print word "Date/time: " date-and-time
  file-print word "seed," seed
  file-print word "Families," Families
  file-print word "Parent-Memory," Parent-Memory
  file-print word "SchoolSize," SchoolSize
  file-print word "Number-of-Schools," Number-of-Schools
  file-print word "Departure-Probability," 1
  file-print word "Number-of-Ranks," Number-of-Ranks
  file-print word "Random-Schools," Random-Schools
  file-print word "Min-School-Spacing," Min-School-Spacing
  file-print word "Initial-School-GCSE-Distribution," Initial-School-GCSE-Distribution
  file-print word "School-Value-Added," School-Value-Added
  file-print word "Parent-Aspiration-Distribution," Parent-Aspiration-Distribution
  file-print word "Aspiration-Mean," Aspiration-Mean
  file-print word "School-Value-Added-Distribution," School-Value-Added-Distribution
  file-print word "Location-Rules," Location-Rules
  file-print word "Move-Closest," Move-Closest
  file-print word "Avoid-Schools," Avoid-Schools
  file-print word "Avoided-Threshold," Avoided-Threshold
  file-print word "School-Peer-Effect," School-Peer-Effect
  file-print word "School-Quality-Effect," School-Quality-Effect
  file-print word "Parent-Effect," Parent-Effect
  file-print word "Attainment=Aspiration?," attainment=aspiration?
end 

to ExportWorldData
  
  show "Exporting world data"
  
  let dummy "World_Exp"
  let filename (word dummy exp-index "_Tick" ticks ".csv")
  export-world filename
  
  let cmd (word "C:\\Program Files\\WinRAR\\WinRAR.exe\" A -dr -ep -ibck " directory "\\" "World_tick" ticks ".rar " directory "\\" filename) 
  ;show cmd
  show shell:exec cmd  
end 

to ExportWorldData_initial
  
  show "Exporting world data"
  let filename (word "World_Exp" exp-index "_Tick_initial.csv")  
  export-world filename
  
  let cmd (word "C:\\Program Files\\WinRAR\\WinRAR.exe\" A -dr -ep -ibck " directory "\\" "World_tick_initial.rar " directory "\\" filename) 
  ;show cmd
  show shell:exec cmd  
end 

to ZipParents_Data
  
  let filename (word "Parents_Data_Exp" exp-index ".csv")
  
  let cmd (word "C:\\Program Files\\WinRAR\\WinRAR.exe\" A -dr -ep -ibck " directory "\\" "Parents_Data.rar " directory "\\" filename) 
  show shell:exec cmd
end 

to export-worldview
  
  show "Exporting world view"
  let filename (word "WorldView_Exp" exp-index "_Tick" ticks ".png")
  export-view filename
end 


;;----------------------------------
;;END DATA EXPORT
;;----------------------------------
  

;;----------------------------------
;;DATA IMPORT
;;----------------------------------

to import
  
  ;Jul12 - this needs to be updated to reflect recent changes
  
  ;; (for this model to work with NetLogo's new plotting features,
  ;; __clear-all-and-reset-ticks should be replaced with clear-all at
  ;; the beginning of your setup procedure and reset-ticks at the end
  ;; of the procedure.)
  __clear-all-and-reset-ticks
  random-seed seed
  
  set schoolRadii sqrt((SchoolSize * 5) / pi) 
  
  if(Random-Schools = false)
  [
    set Families 100
    set SchoolSize 100
    set Number-of-Schools 9
  ]  
    
  
  setup-Parents 
  setup-Schools
  ;setup-Patches
  
  
  
  plotting
  
  
  import-world user-file
end 
;;----------------------------------
;;END DATA IMPORT
;;----------------------------------
  
  
  
;;----------------------------------
;;STATS
;;----------------------------------

to setup-R
  
  print "setting up R"
  
  r:clear
  r:eval("library(spdep)")
  
  r:put "nrow" world-height
  r:put "ncol" world-width
  
  let corner-d 100
  
  ask patch max-pxcor max-pycor [ set corner-d distancexy min-pxcor min-pycor]  
  ifelse(corner-d < 2)
  [ r:eval("grid.nb <- cell2nb(nrow, ncol, type='queen', torus=TRUE)") ]
  [ r:eval("grid.nb <- cell2nb(nrow, ncol, type='queen', torus=FALSE)") ]
  
  r:eval("grid.listw <- nb2listw(grid.nb, style='C')")

  set asp-moran-i 0
  set asp-moran-i-p 0
  set att-moran-i 0
  set att-moran-i-p 0

  set GA-m 0
  set GA-r 0
  set GA-p 0
  
  set GMx-m 0
  set GMx-r 0
  set GMx-p 0
  
  set GMn-m 0
  set GMn-r 0
  set GMn-p 0
  
  set AMx-m 0
  set AMx-r 0
  set AMx-p 0
  
  set AMn-m 0
  set AMn-r 0
  set AMn-p 0
end 

to calc-Moran

;17Jul12
;need to use patch attribute values for spatial autocorrelation (b/c using cell2nb in R to deal with toroid) 
  ifelse(calc-Moran? and ticks >= 20) ;ticks >= 20 to speed execution time for analysis
  [
    print "calc Moran's I (R)"
    
    ;aspiration
    r:put "p.aspiration" map [[p-aspiration] of ?] sort patches
    ;print map [[p-aspiration] of ?] sort patches
    
    r:eval("asp.i <- moran.test(p.aspiration, grid.listw)")
    
    set asp-moran-i r:get("asp.i$estimate[1]")
    set asp-moran-i-p r:get("asp.i$p.value")
    
    print word "Moran's i (aspiration): " asp-moran-i
    print word "Moran's i, p-value: " asp-moran-i-p
    
    ;r:setPlotDevice
    ;r:eval("moran.plot(p.aspiration, grid.listw)")
    
    
    ;attain
    r:put "p.attainment" map [[p-attainment] of ?] sort patches
    ;print map [[p-attainment] of ?] sort patches
    
    r:eval("att.i <- moran.test(p.attainment, grid.listw)")
    
    set att-moran-i r:get("att.i$estimate[1]")
    set att-moran-i-p r:get("att.i$p.value")
    
    print word "Moran's i (attainment): " att-moran-i
    print word "Moran's i, p-value: " att-moran-i-p
    
    ;r:setPlotDevice
    ;r:eval("moran.plot(p.attainment, grid.listw)") 
  ]
  
  [
    ;create dummy values
    set asp-moran-i -99
    set asp-moran-i-p -99
    
    set att-moran-i -99
    set att-moran-i-p -99
  ]
end 

to calc-relationships

print "calc relationships (R)"

r:put "sGCSEs" map [ [GCSE-score] of ? ] sort schools  
r:put "sAppRatios" map [ [app-ratio] of ? ] sort schools   
r:put "sMaxDists" map [ [max-distance] of ? ] sort schools     
r:put "sMeanDists" map [ [mean-distance] of ? ] sort schools       

r:eval("dat <- cbind(sGCSEs, sAppRatios, sMaxDists, sMeanDists)")
r:eval("dat <- as.data.frame(dat)")
  
r:eval("GCSEvsAppRatioLM <- lm(sGCSEs ~ sAppRatios, data = dat)")
r:eval("GCSEvsMaxDistLM <- lm(sGCSEs ~ sMaxDists, data = dat)")
r:eval("GCSEvsMeanDistLM <- lm(sGCSEs ~ sMeanDists, data = dat)")
r:eval("AppRatiovsMaxDistLM <- lm(sAppRatios ~ sMaxDists, data = dat)")
r:eval("AppRatiovsMeanDistLM <- lm(sAppRatios ~ sMeanDists, data = dat)")

set GA-m r:get("summary(GCSEvsAppRatioLM)$coefficients[2]")
set GA-r r:get("summary(GCSEvsAppRatioLM)$r.squared")
set GA-p r:get("anova(GCSEvsAppRatioLM)$'Pr(>F)'[1]")

set GMx-m r:get("summary(GCSEvsMaxDistLM)$coefficients[2]")
set GMx-r r:get("summary(GCSEvsMaxDistLM)$r.squared")
set GMx-p r:get("anova(GCSEvsMaxDistLM)$'Pr(>F)'[1]")

set GMn-m r:get("summary(GCSEvsMeanDistLM)$coefficients[2]")
set GMn-r r:get("summary(GCSEvsMeanDistLM)$r.squared")
set GMn-p r:get("anova(GCSEvsMeanDistLM)$'Pr(>F)'[1]")

set AMx-m r:get("summary(AppRatiovsMaxDistLM)$coefficients[2]")
set AMx-r r:get("summary(AppRatiovsMaxDistLM)$r.squared")
set AMx-p r:get("anova(AppRatiovsMaxDistLM)$'Pr(>F)'[1]")

set AMn-m r:get("summary(AppRatiovsMeanDistLM)$coefficients[2]")
set AMn-r r:get("summary(AppRatiovsMeanDistLM)$r.squared")
set AMn-p r:get("anova(AppRatiovsMeanDistLM)$'Pr(>F)'[1]")
end 

;;----------------------------------
;;END STATS
;;----------------------------------

There is only one version of this model, created over 11 years ago by James Millington.

Attached files

File Type Description Last updated
Aspiration, Attainment and Success (JASSS 2013).png preview Preview for 'Aspiration, Attainment and Success (JASSS 2013)' over 11 years ago, by James Millington Download

This model does not have any ancestors.

This model does not have any descendants.