Managing the Volunteers Netlogo and HubNet activity

Managing the Volunteers Netlogo and HubNet activity preview image

1 collaborator

Denis_havlik Denis Havlik (Author)



Tagged by Denis Havlik about 9 years ago


Tagged by Denis Havlik about 9 years ago


Tagged by Denis Havlik about 9 years ago

Model group Volunteers | Visible to everyone | Changeable by group members (Volunteers)
Model was written in NetLogo 5.1.0 • Viewed 397 times • Downloaded 31 times • Run 0 times
Download the 'Managing the Volunteers Netlogo and HubNet activity' modelDownload this modelEmbed this model

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


This model is a proof of concept for a crowdtasking integration tool. It shows how to realize a client-server application which allows a human operator ("manager") to define task requests and ask for the volunteers. The volunteers are modelled as (rather stupid) agents who will always accept and execute such tasks if they are free to do so.


Manager is a human, and interacts with the model using the HubNet interface. Manager (turtle breed) can define a tasking area by clicking and dragging a mouse on the map, choose one of the issues, decide how many volunteers should be tasked and post a tasking request (links from manager to issues). Alternatively, the manager can use the "Task-nearest?" switch to signal the system that the nearest free volunteer should be tasked.

Tasking requests are queued.

Volunteers walk randomly around unless they are tasked. As soon as a free volunteer arrives to a tasking area, it receives a task. This is repeated until the requested number of volunteers has received (and accepted) the task. Motivation and free will play no role in this model. If the "Task-nearest?" switch is on, the tasking area is ignored and the task is given to volunteers nearest to the issue.

Once they receive a task, volunteers will head straight towards the issue which they need to report on. This model does not implement roads or terrain modifiers.

Once the volunteer is near the issue, it will report an observation and the task will be resolved.


On the "server" side, it is possible to adjust the world size and the number of volunteers, as well as two more subtle parameters

  • Reset, Run and Step 1 buttons have the usual meanings.
  • Nr-issues determines the number of issues which need to be discovered.
  • Size-world determines the size of the world in patches (both x and y dimension)
  • R-discover determines the distance from which the issues can be spotted by
  • Nr. Volunteers allows adjusting the number of volunteers.

On the client side, it is possible to jump between "open" issues, choose a tasking area and change the number of volunteers which will receive each of the tasks.

"Task-nearest?" switch has the same meaning on client and on server side. See "How it works" section.


Combination of "many issues", "distinct tasking areas" and "many volunteers" will quickly discourage even the best manager. This is exactly the type of issues the model should expose in integration tests. Using the "Task-nearest?" option means less work for the manager and the tasking is usually more efficient in terms of the distance the volunteers have to walk and the time needed to finalize the tasks.


Observe the difference between "using the same tasking area all the time" and "choosing the area for each issue".

Observe the difference in average "tasking distance" with and without "Task-nearest?" option.



In this model it is OK to choose the whole world as the tasking area and randomly assign tasks to some volunteers. This is awfully inefficient and also a great way to discourage volunteers:

1) if everyone gets all task requests, our volunteers will quickly will flip out (spamming). 2) If the task sends volunteers far-away, they will spend most time walking. Frustration is sure to happen.

There is more to motivation than this, e.g. thanking the volunteers, making their results visible ("hall of fame"), we could even have some monetary compensations.

"Task-nearest?" option makes the tasking more efficient, but further optimization could be achieved if the volunteers are able to look ahead and choose several nearby tasks to resolve at once.


In the real world, people live in houses, work in offices and usually walk or drive on the roads. Their movement is also constrained by topography.

On top of this, they move at certain speeds (e.g. 4-5km/h for walking), eat, sleep, etc. Eventually, at least some of these features need to be modelled.

Observation content, errors and quality assurance

In this model, the volunteers will never make an error and return false observation. In fact, there is no content in "observations" at all.

TRUST and other attributes

In this model, there is no difference between volunteers. In reality, we will assign difficult tasks to people who are trusted and able to perform them and less critical tasks to a mass of untrusted volunteers.

In addition, some tasks will require special skills or tools - this needs to be introduced in the volunteer data model.


We can come far by adding a few parameters (e.g. "time to finish this task" nor "possible observation responses") to "issues", but there is one notable exception: this model can't simulate the volunteers response to generic requests such as "visit your neighbour and report weather a medical assistance is needed.".


  • Uses "breeds" to differ between various types of agents.
  • Uses links to model the task requests, tasks and observations.
  • Custom shapes, sizes and colours of various turtle breeds.
  • HubNet code
  • Mouse events
  • Time events


See other "Volunteers" models by the same author.


If you mention this model in a publication, we ask that you include these citations for the model itself and for the NetLogo software:


Copyright 2015 Denis Havlik


This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License. To view a copy of this license, visit or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

To inquire about commercial licenses and model extensions, please contact Denis Havlik at


This model is an indirect consequence of my work in ENVIROFI and DRIVER EU projects. In these projects we have developed some mobile applications for crowdsourcing and crowdtasking, which got me interested in the factors which govern the behaviour of the volunteers. For now I'm developing this as a hobby, but future versions of this model may be directly related to and used in the DRIVER project.

Comments and Questions

File Error (Question)

It is not possible to open the zip file. An error occurs. Is it possible to upload it again?

Posted about 8 years ago

Click to Run Model

; globals and definitions ;

breed [volunteers volunteer]
volunteers-own [ v_motivation xhome yhome tasking-distance ]

breed [issues issue]
; i_resolved? is set to true when we have enough reports.
issues-own [ i_tasked? i_resolved? i_generated i_tasked i_resolved ]

directed-link-breed [task-requests task-request] ; task requests are special links from the manager to the issue.
                                                 ; task requests are used to generate tasks later on.
task-requests-own [ t_manager-id t_generated-at t_resolved? t_x1 t_x2 t_y1 t_y2 t_outstanding t_issue-ID]
  ; t_outstanding is set to number of requested confirmations initially, and one is substrqcted every time a new volunteer accepts the task
  ; t_resolved is set to true once all the v_tasks generated by this task request have been resolved. 

directed-link-breed [ v_tasks v_task ] ; these are the actual tasks - links from volunteers to issues
directed-link-breed [ observations observation ] ; report is reserved word, so we'll use observation.

; not sure what we need in this link...
observations-own [ timestamp correct?]
; every task is requested by one manager and has a task ID. 
; this is not unique! Same manager + task ID combination is shared with Nr-volunters other v_tasks!
v_tasks-own [ manager-ID task-ID ]


;; create a breed of turtles that represents the crisis manager(s). 
;; Crisis managers manage the tasks - in this model the manager will be a human and volunteers software agents.
breed [ managers manager ]

  user-id          ;; Managers choose a user name when they log in.
                   ;; Each hubnet message from a manager will contain this ID as hubnet-message-source
  x1 y1            ;; one vertice of the BB
  x2 y2            ;; second vertice
  Nr-confirmations ;; number of requested volunteers
  Window-size      ;; size of the world-window shown to manager
  ;; more to come

;; the STARTUP procedure runs only once at the beginning of the model
;; at this point we just initialize the hubnet

to startup

;; HubNet Procedures

to hn-setup-managers
  ask managers
    set Nr-confirmations 3
    hn-inform-me "Nr-confirmations" 3
    set x1 random Size-World - 20
    set y1 random Size-World - 20
    set x2 x1 + 10
    set y2 y1 + 10
    set Task-type "resolve-issue"            ;; right now we have only one type
    set Window-size floor ( Size-world / 5 ) ;; 
    ;; set Issue-ID [who] of one-of issues
    ;; hubnet-send user-id "step-size" step-size

;; when a new user logs in create a manager turtle
;; this turtle will store any state on the client
;; values of sliders, etc.

to hn-create-new-manager
  create-managers 1
    ;; This is for housekeeping purpose. We need to know who is who.
    set user-id hubnet-message-source
    set label user-id

    set Nr-confirmations 3
    set x1 random Size-World - 20
    set y1 random Size-World - 20
    set x2 x1 + 10
    set y2 y1 + 10
    set Task-type "resolve-issue"
    set Issue-ID [who] of one-of issues
    ;; update the clients with any information you have set

;; when a user logs out make sure to clean up the turtle
;; that was associated with that user (so you don't try to
;; send messages to it after it is gone) also if any other
;; turtles of variables reference this turtle make sure to clean
;; up those references too.

to hn-remove-manager
  ask managers with [user-id = hubnet-message-source]
  [ die ]

to hn-process-clients
  ;; as long as there are more messages from the clients
  ;; keep processing them.
  while [ hubnet-message-waiting? ]
    ;; get the first message in the queue
    if hubnet-enter-message? [ hn-create-new-manager stop ] ;; when clients enter we get a special message
    if hubnet-exit-message?  [ hn-remove-manager     stop ] ;; when clients exit we get a special message
    print (word "new hubnet message " hubnet-message-tag)
    ask managers with [user-id = hubnet-message-source]
      [ hn-execute-command hubnet-message-tag ] 
    ;; I want to always center on currently chosen issue
    if (hubnet-message-tag = "Prev-Issue" or hubnet-message-tag = "Next-Issue") [
      let ID [Issue-ID] of one-of managers with [user-id = hubnet-message-source]
      hubnet-send-watch hubnet-message-source issue ID
      ;; getting the system to center on one of issues is not as simple as I expected. :-(
      ;; it also complicates the definition of the task area because of the wrapping.
      ;; for now we'll therefore stay with full view
      ;hubnet-send-follow hubnet-message-source issue ID 10
    if (hubnet-message-tag = "Mouse Up") [
      ;; context can be quite an annoying topic in netlogo. :-(
      let px1 0 let py1 0
      let px2 0 let py2 0
      ask one-of managers with [user-id = hubnet-message-source] [
        set px1 x1 set py1 y1
        set px2 x2 set py2 y2
      hn-fill-tasking-area blue px1 py1 px2 py2       ;; this will make the tasking area visible 

;; Other messages correspond to users manipulating the
;; client interface, handle these individually.

to hn-execute-command [command]
  ;; you should have one if statement for each widget that
  ;; can affect the outcome of the model, buttons, sliders, switches
  ;; choosers and the view, if the user clicks on the view you will receive
  ;; a message with the tag "View" and the hubnet-message will be a
  ;; two item list of the coordinates
  print (word "command=" command "(" hubnet-message ")") 

  ;;if command = "Task-type" [ set Task-type item 0 hubnet-message stop ]
  if command = "Nr-confirmations" [ set Nr-confirmations hubnet-message stop ]
  if command = "Nr-confirmations" [ set Nr-confirmations hubnet-message stop ]
  if command = "Task-nearest?"    [ set Task-nearest? hubnet-message stop ]

  ;; find next unresolved issue which is eligible for tasking.
  if command = "Next-Issue" [
    let next_issue min-one-of ( issues with [ who > [Issue-ID] of myself and not i_tasked?  ] ) [ who ]
    if not is-issue? next_issue [ set next_issue min-one-of issues with [ not i_tasked?  ] [ who ] ]
    print (word "Issue-ID=" Issue-ID " next-issue=" next_issue)
    ifelse is-issue? next_issue [
      set Issue-ID [who] of next_issue
      hn-inform-me "Issue-ID" Issue-ID        
      set color blue 
      ; manager "moves" to the issue.
      set xcor [xcor] of next_issue
      set ycor [ycor] of next_issue
      ;; TODO: if this does not work either, there are no issues left. What now? 
  ;; find previous unresolved issue which is eligible for tasking.
  if command = "Prev-Issue" [
    let prev_issue max-one-of ( issues with [ who < [Issue-ID] of myself and not i_tasked?  ] ) [ who ]
    if not is-issue? prev_issue [ set prev_issue max-one-of issues with [ not i_tasked?  ] [ who ] ]
    ifelse is-issue? prev_issue [
      set Issue-ID [who] of prev_issue
      hn-inform-me "Issue-ID" Issue-ID        
      set color blue 
      print (word "Issue-ID=" Issue-ID " prev-issue=" prev_issue)
      ; manager "moves" to the issue.
      set xcor [xcor] of prev_issue
      set ycor [ycor] of prev_issue
      ;; TODO: if this does not work either, there are no issues left. What now? 

  ;; Tasking area is chosen by mouse klick ("View"), drag and letting go ("Mouse up") 
  if command = "View"
    set x1 floor item 0 hubnet-message
    set y1 floor item 1 hubnet-message 
    hn-inform-me "x1" x1
    hn-inform-me "y1" y1
    print (word "x1=" x1 ", y1=" y1) ;; debug
  if command = "Mouse Up"
    set x2 floor item 0 hubnet-message
    set y2 floor item 1 hubnet-message 
    hn-inform-me "x2" x2
    hn-inform-me "y2" y2
    print (word "x2=" x2 ", y2=" y2) ;; debug
  ;; And now it gets serious. We have to add a new task request to the queue.
  if command = "Submit"
    print (word "Time to do the tasking to issue " Issue-ID )

;; generate a new tasking request. Called after pressing "Submit" buton.
;; Note: for now this must be called in manager context.

to hn-gen-task-request
  ;; This should assure we never sending the task to same issue twice.
  if [i_tasked?] of issue Issue-ID [ stop ]
  create-task-request-to issue Issue-ID [ 
    set t_manager-id [user-id] of myself
    set t_generated-at ticks
    set t_x1 [x1] of myself ; coordinates of the tasking area
    set t_x2 [x2] of myself
    set t_y1 [y1] of myself
    set t_y2 [y2] of myself
    set t_outstanding [Nr-confirmations] of myself
    set t_issue-ID [Issue-ID] of myself
    set color black
  ask issue Issue-ID [
    set i_tasked? true
    set i_tasked ticks

;; whenever something in world changes that should be displayed in
;; a monitor on the client send the information back to the client

to hn-update-me ;; turtle procedure
  hubnet-send user-id "x1" x1
  hubnet-send user-id "y1" y1

to hn-inform-me [variable value] ;; turtle procedure
  hubnet-send user-id variable value

;; make the current tasking area visible for manager

to hn-fill-tasking-area [the_color px1 py1 px2 py2 ]
  ask patches [ 
    ifelse ( pxcor >= min (list px1 px2)
      and pxcor <= max (list px1 px2)
      and pycor >= min (list py1 py2) 
      and pycor <= max (list py1 py2))
    [ set pcolor the_color ] 
    [ set pcolor grey + 4 ]

; setup procedures ;

to setup
  ; clear-all - this would also kill the manager. no-no.
  ask turtles with [breed != managers] [die]

; initially all patches are just grey = unknown.

to setup-world
  resize-world 0 Size-world 0 Size-world ; world can be of different sizes
  set-patch-size 1000 / Size-world       ; but the world illustration is always the same size. 
  ask patches [
      set pcolor grey + 4

; randomly add some taskable volunteers to the world

to setup-volunteers
  set-default-shape volunteers "person"
  create-volunteers Nr-volunteers [ 
    setxy random-xcor random-ycor
    set color green                  ; green indicates the volunteer is free and ready to get a task.
    set size 1

    ; Variables below aren't used yet (code not implemented)
    set xhome xcor                   ; Just in case we want to send volunteers back home again. 
    set yhome ycor 
    set v_motivation init-motivation ; motivation is not used at the moment either!

; Procedures governing the world development ;

to go 
  every Issue-period [ add-issues 1 ] ; new issues are added every Issue-period sec.
  every 0.1 [ hn-process-clients ] ;; every 0.1 sec should be more than enough?
  every Issue-period [ export-world (word "volounteers-WS-" ticks)]

; adds N (normally just one) new issues to the world when called
; issues have a generation time & later also a discovery time

to add-issues [ N ]
  set-default-shape issues "target"
  create-issues N [ 
    setxy random-xcor random-ycor
    set i_generated ticks            ; this could be used to generate issues as we go.
    set i_resolved? false
    set i_tasked? false
    set color red
    set size 1

; task requests are defined by manager, but we still have to assign them to volunteers 
; since the tasking area may not have enough volunteers at first, 
; we need to work with queue.

to assign-tasks
  ;; vol,unteer can't have >1 tasks at any given moment.
  let free_volunteers volunteers with [not any? out-v_task-neighbors]
  ;; t_outstanding will be zero if we have enough volunteers set on a task.
  ask task-requests with [t_outstanding > 0 ] [
    let this_ID t_issue-ID
    ask ifelse-value Task-nearest? [
      min-n-of t_outstanding free_volunteers [ distance (issue this_ID) ]
    ] [
    n-of t_outstanding free_volunteers with [ 
      xcor >= [min (list t_x1 t_x2)] of myself and 
        xcor <= [max (list t_x1 t_x2)] of myself and 
        ycor >= [min (list t_y1 t_y2)] of myself and 
        ycor <= [max (list t_y1 t_y2)] of myself ]
      ;; TODO: check if this assures we don't task too many people!
      if [t_outstanding] of myself > 0 [
        set tasking-distance distance issue this_ID ; store the tasking distance of latest task in volunteers variable.
        create-v_task-to issue this_ID [
          if show-tasks? [ set color orange ]
          if debug? [ print word "created task:" self ]
          ;; back to volunters context.
          ;; lets make the tesked v. better visible!        

          ask myself [         ;; myself = volunteer here!
            set color orange
            set size size + 1
        ask myself [ ;; one outstanding task-request less to go!
                     ;; myself = task request here
          set t_outstanding t_outstanding - 1

;; volunters will move randomly if not tasked and towards the issue if tasked

to move-volunteers
  ask volunteers [
    ; current target?
    ; normally there should be only one, so "one-of" is the same as

    ; If we have a task, let's go for it!
    ifelse any? out-v_task-neighbors [
      face min-one-of (out-v_task-neighbors)  [distance myself ] ;; this will work even if we set several tasks on the volunteer at once.   
      forward 1
    ; else we'll stroll arround
      right random 360 
    forward 1
    ; motivation always goes down, unless an issue is discovered
    ; TODO: this is not implemented yet
    ;if v_motivation > 0 [
    ;  set v_motivation v_motivation - 1

    ;; othervise we'll do nothing.

; tasked volunteers move towards their task or at random if no task defined.

; report observations on nearby issues

to report-issues
  ask volunteers with [any? out-v_task-neighbors] [ ;; in this model ONLY the tasked volunteers can send reports.
    ;;let this_volunteer self
    ask one-of out-v_task-neighbors [      ;; that would be the relevant issue
                                           ;; there can be only one since we allow one task per volunteer    
      if distance myself <= R-discover [;; if the issue is near enough, let's report.
                                           ;; we are in issue context
                                           ;; issue = self, volunteer = myself
        create-observation-from myself [   ;; volunteer should report (create) an observation to this issue 
                                           ;; now we are in onservation (link) context!
          set timestamp ticks  ;; when was the observation made?
          if show-observations? [ 
            set color green ;; this will make the observation link visible
          if debug? [print self]
        ask myself [                    ;; this should be the volunteer, we are back in issue context.
          set color green               ;; volunteer is free to take a new task again
          set size size - 1             ;; Disable this to see good reporters growing.
          ask one-of my-out-v_tasks [die]  ;; delete the task from a caling turtle to this issue

to manage-issues 
  ask task-requests with [ t_outstanding <= 0 ] [ ;; should never be < 0, but just in case.
    ;; t_outstanding = 0 means we have tasked enough v.
    ask issue t_issue-ID [
      if not any? in-v_task-neighbors [ ;; if no tasks are left, all volunteers heve reported 
        set i_resolved? true
        set i_resolved ticks
        set color black
        ; ask myself [die] ;; this would kill the task request.

There are 3 versions of this model.

Uploaded by When Description Download
Denis Havlik about 9 years ago spell-checked the documentation Download this version
Denis Havlik about 9 years ago Just a minor improvement in documentation Download this version
Denis Havlik about 9 years ago Initial upload Download this version

Attached files

File Type Description Last updated
Managing the Volunteers Netlogo and HubNet activity.png preview Preview showing the main window and the HubNet view about 9 years ago, by Denis Havlik Download

This model does not have any ancestors.

This model does not have any descendants.