MagdalenaOlewinska-GroceryStoreLines-EECS- 372

MagdalenaOlewinska-GroceryStoreLines-EECS- 372 preview image

1 collaborator

Tags

(This model has yet to be categorized with any tags)
Model group MAM-2016 | Visible to everyone | Changeable by everyone
Model was written in NetLogo 6.0-M5 • Viewed 486 times • Downloaded 42 times • Run 0 times
Download the 'MagdalenaOlewinska-GroceryStoreLines-EECS- 372' modelDownload this modelEmbed this model

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


Info tab cannot be displayed because of an encoding error

Comments and Questions

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

Click to Run Model

globals [

  ;;NOTE: SAVED INPUT, so if user changes parameters after pressing setup, model characteristics will not change thus running model will still be correct

  ;; model characteristics
  stations                 ;; patches that are designated stations

  ;; business characteristics
  closing-at               ;; tick count at which no more customers should arrive
  hourly-pay               ;; employee hourly rate
  dynamic?                 ;; true if stations can dynamically open & close
  dynamic-check-range      ;; evaluate whether to open/close stations every X hours (increments in half hour units)
  short-line-length        ;; close a station (if possible) if a station's line is shorter than this number @half hour marks
  long-line-length         ;; open a new station (if possible) if a station's line is longer than this number @half hour marks

  ;; customer characteristics
  distraction-level        ;; decreases a customer's sense of wait-time by % of distraction provided
  impatience?              ;; allows unsatisfied customers to balk if average wait of store is large or renege when perceived wait while in line too large
  ideal-wait               ;; time (in min) believed to be best waiting time at this particular grocery store
  avg-arrival-count        ;; average number of customers arriving per tick
  arrival-schedule         ;; schedule of customer arrival with average as avg-arrival-count: uniform, oscillating

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  ;; running totals
  all-total-wait           ;; running total of all wait time of all customers since store opening

  total-customers          ;; running total of all arrivals
  total-checkout-customers ;; running total of all customers who successfully checked out
  total-balk-customers     ;; running total of all customers who arrived but left because avg. wait time too long
  total-renege-customers ;; running total of all customers who waited but left because his/her wait time too long in line

  general-total-wait       ;; running total of all wait time of customers serviced at a general checkout station since store opening
  general-total-customers  ;; running total of all customers serviced at a general checkout station since store opening

  express-total-wait       ;; running total of all wait time of customers serviced at an express checkout station since store opening
  express-total-customers  ;; running total of all customers serviced at an express checkout station since store opening

  self-total-wait          ;; running total of all wait time of customers serviced at a self-checkout station since store opening
  self-total-customers     ;; running total of all customers serviced at a self-checkout station since store opening

  ;; report to user statistics
  average-wait             ;; tracks average total time waited of a customer now "checking-out" and leaving
  general-average-wait     ;; average-wait but for general stations
  express-average-wait     ;; average-wait but for express stations
  self-average-wait        ;; average-wait but for self stations

  current-cost             ;; tracks cost of operation depending on how many and what types of checkout stations are open
  total-general            ;; current cost of general stations
  total-express            ;; current cost of express stations
  total-self               ;; current cost of self checkout stations
]




breed [customers customer]

patches-own [
  max-items                 ;; depending on type of station, how many max
  scan-rate                 ;; how many items per tick stations scans

  line-length               ;; keeps track of line length; 0 if no one is in line
  interested-customers      ;; keeps track of count of customers who have selected this line (location = here , state "found-line" or "in-line")

  total-items-scanned       ;; keeps track of number of items scanned
  total-customers-helped    ;; keeps track how many customers serviced

  last-number-served        ;; keeps track ensures next customer being served has larger wait-number
  about-to-close?           ;; if true, inefficient so will close as soon as customers in line serviced, no new customers accepted

  #-renege-customers        ;; keeps track how many customers left line because wait too long
]

customers-own [
  state                     ;; no-line, found-line, in-line, checking-out
  grocery-items             ;; number items needed to be checked out
  wait-number               ;; indicates place in line
  wait-time                 ;; counts how long has been "in-line"
  perceived-wait-time       ;; how long the customer perceives he/she is in line dependent on distractions
  location                  ;; checkout station the customer has selected
]


;;; setup procedures

to setup
  clear-all
  set-store-characteristics
  setup-stations
  reset-ticks
end 

;; go procedure

to go

  if ticks > closing-at and count customers = 0 ;;end simulation after all customers leave and it is past closing time
    [stop]

  if ticks > 0 and ticks mod dynamic-check-range = 0 and dynamic? [adjust-open-stations] ;;access layout and make changes every evaluation period

  if impatience? [balk-customers]

  check-out-customers

  find-line

  move-forward

  if impatience? [renege-customers]

  leave-customers

  if dynamic? [close-stations]

  if ticks < closing-at [arrive-customers] ;;keep doors open to customers for indicated period

  color-customers

  update-graphs

  update-plots

  tick
end 



;;; setup helper procedure
;;; set up global variables. this includes using user inputs to initialize store characteristics

to set-store-characteristics

  set closing-at (closing-time * 60) ;convert hours to tick count (1 tick = 1 minute)
  set dynamic-check-range (evaluate-every-X-hours * 60)
  set distraction-level distracted-in-line
  set impatience? impatient-customers?
  set ideal-wait ideal-wait-time
  set hourly-pay employee-hourly-rate
  set dynamic? dynamic-layout?
  set short-line-length line-too-short
  set long-line-length line-too-long
  set arrival-schedule customer-arrival-schedule
  set avg-arrival-count avg-#-customers-arriving
end 

;; patch procedure
;; set up checkout stations based on user parameters

to setup-stations

  ;; floor is white
  ask patches [set pcolor grey + 3 ]

  ;; create stations of each type
  let new-station 0 ;;not used for initial creation
  open-new-station blue general-stations new-station
  open-new-station green express-stations new-station
  open-new-station yellow self-stations new-station
end 

;; patch procedure
;; open new-station-count amount of stations with pcolor checkout-type

to open-new-station [checkout-type new-station-count new-station-loc]

  ;; set up check out area on y axis = 6
  let station-space patches with [pycor = 14 and pxcor mod 2 = 0]
  set station-space station-space with [pcolor = grey + 3]

  let express-space station-space with [pxcor >= 16]
  let general-space station-space with [pxcor > -16 and pxcor < 16]
  let self-space station-space with [pxcor <= -16]

  if checkout-type = blue [set station-space n-of new-station-count general-space]
  if checkout-type = green [set station-space min-n-of new-station-count express-space [pxcor]]
  if checkout-type = yellow [set station-space max-n-of new-station-count self-space [pxcor]]

  ;;create num-to-open patches of checkout-type (pcolor indicating type)
  ask station-space
    [set pcolor checkout-type
      if-else pcolor = green
        [set max-items 15] ;;express types have grocery-item count restriction of <= 15 items
        [set max-items 1000]
      if-else pcolor = yellow
        [set scan-rate 10] ;;self-checkout types have slower scan-rates
        [set scan-rate 15]
      set line-length 0
      set interested-customers 0
      set total-items-scanned 0
      set total-customers-helped 0
      set last-number-served 0
      set #-renege-customers 0
      set about-to-close? false
      set new-station-loc self]

  set stations patches with [pcolor != grey + 3]
end 



;;customer procedure
;; queueing theory: balking - just arrived customer chooses not to join queue because wait time is too long

to balk-customers
  ask customers with [state = "no-line"]
  [
    ;; leave if model's wait time is 20% higher than ideal wait
    if impatience? and average-wait > (1.20 * ideal-wait)
      [set total-balk-customers total-balk-customers + 1
        die]
  ]
end 


;;customer procedure
;; queueing theory: reneging - leaving queue without being serviced because wait is too long

to renege-customers

  ask customers with [state = "in-line"]
  [
    ;; leave if customer's preceived wait time is 20% higher than ideal wait
    if perceived-wait-time > (1.20 * ideal-wait)
      [ask location
        [;set line-length line-length - 1
          set interested-customers interested-customers - 1
          set #-renege-customers #-renege-customers + 1
          ask customers with [state = "in-line" and location = self] [set wait-number wait-number - 1]
        ]
      set total-renege-customers total-renege-customers + 1
      die]
  ]

  ask stations with [#-renege-customers > 0]
  [
    let reg #-renege-customers
    ask customers with [location = myself and state = "in-line"] [if reg >= 2 [move-to patch-ahead (reg - 2)]]
    set #-renege-customers 0
  ]
end 


;; patch procedure
;; at every user indicated dynamic-range-check increment in time, if dynamic-layout? is switched on:
;; evaluate line-length per station (note: stations open cannot exceed max allowed for store: 5 - express, self; 15 - general)
;; if line-length <= close-if-line-shorter-than: mark station to be closed,
;;        customers "found-line" heading to this underwhelmed station will have to pick new station
;;        current customers "in-line" will still be serviced
;; if line-length >= open-if-line-longer-than: open new station of same type,
;;        customers "found-line" heading to this overwhelmed station will be redirected to new station

to adjust-open-stations
  ask patches with [pcolor = green or pcolor = blue or pcolor = yellow]
  [
    let given-color pcolor
    let my-type-of-stations stations with [pcolor = given-color]

    if count my-type-of-stations with [about-to-close? = false] > 1  ;;range for any given checkout type is to have between 1-15 stations open at any time
    [

      if line-length <= short-line-length  ;; line too short and at least one type of this station open
        [set about-to-close? true
         ask patch pxcor (pycor + 1) [set pcolor red]]
    ]

    let current-line line-length
    let max-amount 5  ;; max amount of express or self checkout stations is 5
    if pcolor = blue [set max-amount 15] ;; max amount of general stations is 15
    if count my-type-of-stations < max-amount
      [

        if line-length >= long-line-length ;; line too long and still room for more stations so open a station like this
          [let new-station self
            open-new-station pcolor 1 new-station
            ask customers with [location = myself and state = "found-line"] ;;relocate customers who chose this line but havent arrived yet to redirect to new open station
              [set location new-station
                ask new-station [set about-to-close? false set interested-customers interested-customers + 1]
                ask location [set interested-customers interested-customers - 1]
                face location]
          ]

      ]
      set stations patches with [pcolor != grey + 3]
  ]
end 

;; patch procedure
;; if dynamic-layout? switched on and marked to close ASAP,
;; actually close when all customers who were already in line serviced

to close-stations
  ask stations with [about-to-close? = true and count customers-here = 0 and interested-customers = 0]
    [set pcolor grey + 3
      ask patch pxcor (pycor + 1) [set pcolor grey + 3]
      set stations patches with [pcolor != grey + 3]]
end 

;; customer procedure
;; if you have no more grocery items while checking out, leave the store,
;; decrease the station's line-length, increase the station's customers helped count,
;; and decrease the wait-number of everyone who was in your checkout line

to leave-customers
  ask customers with [state = "checking-out"]
  [if grocery-items <= 0
    [let num wait-number
      ask location
        [set line-length line-length - 1
          set interested-customers interested-customers - 1
          set total-customers-helped total-customers-helped + 1]
      update-statistics
      die]
  ]
end 

;; customer procedure
;; if checking-out, decrease your grocery-items by the scan-rate of the station
;; and increase the total-items-scanned count of the station by the number of items scanned
;; if in-line, increase your wait time, if you are the smallest wait-number in your patch,
;; move up and set state to checking-out

to check-out-customers

  ask customers with [state = "checking-out"]
  [
    let scan 0
    let num wait-number
    let just-arrived false
    ask patch-here
       [set scan scan-rate
        if last-number-served != num
            [set just-arrived true
             set last-number-served num]
        ]

    if just-arrived = false ;; every station has 1 minute of transaction overall
    [
      if grocery-items < scan [set scan grocery-items]
      set grocery-items grocery-items - scan
      ask patch-here
      [set total-items-scanned total-items-scanned + scan]
     ]
  ]
end 

;; customer procedure
;; if station is in front of you, ask the station to increase its line-length, assign
;; yourself a customer of the day number as your wait-number, and set your state to in-line
;; if station is not in front of you, keep moving forward toward your selected station

to move-forward

    ask customers with [state = "in-line"]
  [
    set wait-time wait-time + 1
    set perceived-wait-time perceived-wait-time + (1 - (distraction-level / 100))


    if-else patch-here = location

    [set state "checking-out"
        set label-color red
        set color white]


    [let customers-ahead 1000
    ask patch-ahead 1
       [set customers-ahead count customers-here]

    if customers-ahead = 0 and wait-number = min [wait-number] of customers-here

    [ if patch-here != location
      [move-to patch-ahead  1
      let temp 0
      ask patch-ahead 1 [ask customers-here with [state = "in-line" or state = "checking-out"] with-max [wait-number] [set temp wait-number]]
      if temp > wait-number and patch-here != location [move-to patch-ahead 1]]

      if patch-here = location
      [set state "checking-out"
        set label-color red
        set color white]]
     ;; ask patch-here [if last-number-served >= [wait-number] of myself [type "ERROR: queueing out of order at station: " type pxcor type " " type last-number-served type " > " print [wait-number] of myself]]]

  ]]



  ask customers with [state = "found-line"]
  [
    let w 1000
    let new-x pxcor
    let new-y pycor

    if-else patch-ahead 1 = location

    [ask location
      [set line-length line-length + 1
        set new-x pxcor
        set new-y pycor - line-length
       ; if count customers-here with [state = "checking-out"] > 0 [set new-y new-y + 1]
        set w total-customers-helped + line-length]
    set state "in-line"
    set color grey
    set wait-number w
    set heading 0

    if-else new-y > -18
    [move-to patch new-x new-y]  ;; move to end of line
    [move-to patch new-x -18];; end of line would be off screen, so group together at the last patch

     ]

    [fd 1]
  ]
end 

;; customers procedure
;; for customers with no-line state, pick the shortest lines closet to you and set
;; state to found-line

to find-line
  ask customers with [state = "no-line"]
  [

    let my-items grocery-items
    let options 0
    if-else random 101  <= 33
    [set location stations with [max-items >= my-items and about-to-close? = false] with-min [interested-customers]
      let selection min-one-of location [distance myself]
      set location selection
      ask location [set interested-customers interested-customers + 1]
    ]
    [set location  stations with [max-items >= my-items and about-to-close? = false and pcolor != yellow] with-min [interested-customers]
      let selection min-one-of location [distance myself]
      set location selection
      ask location [set interested-customers interested-customers + 1]
      ]


    set state "found-line"
    face location
  ]
end 

;; customers procedure
;; create customers based on arrival-schedule preference set;
;; uniform creates X amount of customers at every tick (x user input value
;; max store capacity set at 500

to arrive-customers

  let num-arriving 0
  let customer-count floor(avg-arrival-count)

  if-else customer-count <= 0
    [user-message "Error: Number of customers arriving must be greather than zero."]

  [if arrival-schedule = "uniform"  ;; arrive user input # of customers per tick
    [set num-arriving customer-count]

  if arrival-schedule = "oscillating"  ;; arrive variable customers with max of user input #
    [set customer-count customer-count * 2
      set num-arriving ticks mod (customer-count * 2) + 1
      if num-arriving > customer-count ;; past max magnitude of oscillation needs to count backwards
        [set num-arriving -1 * (num-arriving - (customer-count * 2))]
    ]

  if arrival-schedule = "poisson"  ;; arrive with poisson distribution of user input # average
      [set num-arriving random-poisson customer-count]

  ]

  create-customers num-arriving
  [
    setxy random 28 - 14 18         ;; enter at the top of screen in the middle
    set shape "person"
    set state "no-line"             ;; no decision on any line at first
    set grocery-items 1 + random 99 ;; random amount of items 1 - 100
    set wait-number 1000            ;; default head to very back
    set wait-time 0                 ;; start off with no wait time
    set perceived-wait-time 0       ;; start off with no perceived wait time
    set size 1
    ;set label grocery-items
    set label-color white

  ]

  set total-customers (total-customers + num-arriving)
end 

;;customer procedure
;; customers go across the violet color spectrum with deeper violets indicating longer
;; perceived-wait-times as compared to the ideal wait

to color-customers
  ask customers with [state = "in-line"]
     [set color scale-color violet perceived-wait-time (1.20 * ideal-wait) 0]
end 

;; calculates current-cost, per checkout cost,
;; overall average wait, per checkout type average wait

to update-graphs

  let general-count count stations with [pcolor = blue]
  let express-count count stations with [pcolor = green]
  let self-count count stations with [pcolor = yellow]

  let temp-g general-count * 2 * (hourly-pay / 60)  ;; 2 employees for general station (scanner + bagger)
  let temp-e express-count * (hourly-pay / 60)      ;; 1  employee for express station (scanner)

  let temp-s 0
  if self-count > 0                                        ;; 1 employee oversees all self checkouts
    [set temp-s (hourly-pay / 60)]

  set total-general total-general + temp-g
  set total-express total-express + temp-e
  set total-self total-self + temp-s
  set current-cost current-cost + temp-g + temp-e + temp-s

  if total-checkout-customers > 0
    [set average-wait all-total-wait / total-checkout-customers]

  if general-total-customers > 0
    [set general-average-wait general-total-wait / general-total-customers]

  if express-total-customers > 0
    [set express-average-wait express-total-wait / express-total-customers]

  if self-total-customers > 0
    [set self-average-wait self-total-wait / self-total-customers]
end 


;; after customers check out,
;; update global statistics across all checkout station types

to update-statistics

  set all-total-wait all-total-wait + wait-time
  set total-checkout-customers total-checkout-customers + 1

  let type-checkout ""

  ask patch-here
    [if pcolor = blue
      [set type-checkout "general"]
    if pcolor = green
      [set type-checkout "express"]
    if pcolor = yellow
      [set type-checkout "self"]]

  if type-checkout = "general"
    [set general-total-wait general-total-wait + wait-time
      set general-total-customers  general-total-customers + 1]

  if type-checkout = "express"
    [set express-total-wait express-total-wait + wait-time
      set express-total-customers  express-total-customers + 1]

  if type-checkout = "self"
    [set self-total-wait self-total-wait + wait-time
      set self-total-customers  self-total-customers + 1]
end 

There are 4 versions of this model.

Uploaded by When Description Download
Magdalena Olewinska almost 8 years ago fixed spelling errors! Download this version
Magdalena Olewinska almost 8 years ago Final Copy Download this version
Magdalena Olewinska almost 8 years ago correctly labeled file Download this version
Magdalena Olewinska almost 8 years ago Initial upload Download this version

Attached files

File Type Description Last updated
MagdalenaOlewinska-GroceryStoreLines-EECS- 372.png preview Preview for 'MagdalenaOlewinska-GroceryStoreLines-EECS- 372' almost 8 years ago, by Magdalena Olewinska Download
MagdalenaOlewinska_May16.docx word Progress Report 2 almost 8 years ago, by Magdalena Olewinska Download
MagdalenaOlewinska_May23.docx word Progress Report 3 almost 8 years ago, by Magdalena Olewinska Download
MagdalenaOlewinska_May9.docx word Progress Report 1 almost 8 years ago, by Magdalena Olewinska Download

This model does not have any ancestors.

This model does not have any descendants.