two-buttons_2009


Information

Created with NetLogo version NetLogo 4.0.4
Running with NetLogoLite.jar version 404.


WHAT IS IT?


This model demonstrates a technique to enforce a rule that only one of two 'forever' buttons may be operated at a time.

HOW IT WORKS


Pushing a button causes the button to first check the state variable (goN?) of the other button. If the other button seems to be in the running state, the button sends a "stop request" to the other button. It does this by changing the other button's status flag from 2 (running) to 3 (please stop).
If a buttons status is 3, then it changes its own status to 0, and stops.
If a button's status is 0 (and it is running) that means one of two things:
1. the button was stopped, and the user pressed it, OR
2. the button was already pressed, but was waiting for the other button to stop.
Which one this is is determined by the other button's status flag. In either case, if the other button's status is now 0 (stopped), then this button's status is raised to 2 (running) and the button continues to run.
However, since a non-pressed button will never acknowledge the stop request, some trickery is used. A monitor runs code that repeatedly sets a flag for the running buttons to FALSE as the last thing the monitor does. The next time the monitor runs, it checks the status of these flags. If a supposedly "running" button (a button with status other than 0) has not set its flag to "true", then the monitor deduces that the button is not pressed, and sets that button's status to 0, letting the other button start running.
Since monitors run less often to allow slow/dense code to run, the monitor will, under most circumstances, not stop a running button by accident, even if the button code is very slow.

HOW TO USE IT


This code is designed to be easily integrated into an existing model.
1. Copy the three procedures GO1-CONTROL, GO2-CONTROL, and BUTTON-STATE into your own model.
2. Include the four global variables: go1? go2? button-1 button-2 mon-ticks
3. In the -CONTROL procedures, change the name of GO1 and GO2 in the procedures to the names of your own GO procedures.
4. Add a monitor with the reporter "button-status"
5. Add your GO1, GO2 and STOP-ALL buttons as FOREVER buttons.
If you wish to hide the button-status monitor, you can put other controls on top of it. A blank text-box or an output-box work well.

NETLOGO FEATURES


This model takes advantage of the idea that user-defined reporters can change the state of other areas of the model, not just report a result. This is called a "side-effect" of a reporter. This model also takes advantage of the way the monitors work: they run the code in their reporters repeatedly, even if no button is pressed; and they run slower when button code is running, to give the button code time to complete.

Procedures

NetLogo Version: NetLogo 4.0.4

;;;; SUMMARY
;; There can be only one! (Non-concurrent buttons)
;;;; COPYRIGHT
;; Copyright (C) 2006 James P. Steiner
;; Some Rights Reserved
;; Licensed under Creative Commons 2.5 at-nc-sa license
;;
globals
[ go1? go2? button-1 button-2 mon-ticks ;; non-concurrent buttons
  greeting? ;; used by startup greeting procedures
]

to startup
   setup
end   

to setup
   ca
   set go1? 0
   set go2? 0
   crt 1000
   [ jump 5 ]
   show-greeting
end   

to go1
   if greeting? = true [ clear-greeting ]
   
   ask patches [ set pcolor blue + 3 * sin ( timer * 100 + pycor) * cos (timer * 95 + abs pxcor) ]
   tick
end


to go2
   if greeting? = true [ clear-greeting ]
   ask turtles
   [ jump .5
     rt -5 + random-float 10
   ]
   tick
end

;; @@@@@@@@@@@@@@@@@@@@@@@@
;;
;; Greeting code here
;;
;; @@@@@@@@@@@@@@@@@@@@@@@@

to show-greeting
   ask patch max-pxcor (max-pycor - 2)
   [ set plabel "Click GO1 or GO2 to begin." ]
   set greeting? true
end   

to clear-greeting
   set greeting? false
   ask patch max-pxcor (max-pycor - 2)
   [ set plabel "" ]
end  

;; @@@@@@@@@@@@@@@@@@@@@
;;
;; END OF GREETING CODE
;;
;; @@@@@@@@@@@@@@@@@@@@@


;; ####################################
;; 
;;  Non-Concurrent Button Code follows
;;
;; ####################################

to stop-all
   ;; if go1 is running, tell it to stop...
   if go1? = 2 [ set go1? 3 ]
   ;; if go2? is running, tell it to stop...
   if go2? = 2 [ set go2? 3 ]
   ;; if both have acknowledged the stop
   ;; (or the monitor has done so),
   ;; stop this button (all stop complete)
   if go1? = 0 and go2? = 0 [ stop ]
end
 
to go1-control
   ;; 0 = stopped
   ;; 2 = started
   ;; 3 = stop requested
   ifelse( go1? = 2 and go2? = 0 )
   [ ;; run
     set button-1 true
     ;;;; #############################
     ;;;;
     go1  ;; <<<===  GO COMMAND ONE GOES HERE
     ;;;;
     ;;;;###############################
   ]
   [ ;; is a stop request from the other pending?
     ifelse go1? = 3
     [ ;; yes, show stop complete
       set go1? 0 ;; stopped
       stop ;; stop this button
     ] 
     [ ;; This is a new start request (go? = 0 and button was pushed)
       ;; is other stopped?
       ifelse go2? = 0
       [ ;; yes.
         ;; indicate start completed.
         set go1? 2
       ]
       [ ;; no.
         ;; request other to stop
         set go2? 3
       ]
     ]
   ]  
end

to go2-control
   ;; same as go1-control, comments removed
   ifelse( go2? = 2 and go1? = 0 )
   [ set button-2 true
     ;;;; #############################
     ;;;;
     go2  ;; <<<===  GO COMMAND TWO GOES HERE
     ;;;;
     ;;;;###############################
   ]
   [ ifelse go2? = 3 [ set go2? 0 set go1? 2 stop ]
     [ ifelse go1? = 0 [ set go2? 2 ] [ set go1? 3 ]
   ] ] 
end

to-report button-status
   ;; has button 1 asserted itself as running while the
   ;; go flag is in a non-stopped state recently?
   if button-1 = false and go1? != 0
   [ ;;no, so confirm that button-1 is off.
     set go1? 0
   ]
   if button-2 = false and go2? != 0
   [ set go2? 0
   ]
   set button-1 false
   set button-2 false
   ;; NOTE that mon-ticks is optional, and used mainly to update the 
   ;; monitor display.
   set mon-ticks mon-ticks + 1
   let td1 item (mon-ticks mod 4) [ "    (" "   ( " "  (  " " (   " "(    " ]
   let td2 item (mon-ticks mod 4) [ ")    " " )   " "  )  " "   ) " "    )" ]
   let b1 item go1? [ "off" "" "on" "stopping" ]
   let b2 item go2? [ "off" "" "on" "stopping" ]
   
   ;; you can alter the output as desired.
   ;; to show no output, change to ""
   report (word td1 " 1:" b1 " -- "  "2:" b2 " " td2 )
end      

;; #####################################
;;
;; END OF NON-CONCURRENT BUTTON CODE
;;
;; #####################################

                    


Download Link

View or download the complete model file (to download: right-click, save-link-as):
-- Download two-buttons_2009 --