WaDemEsT
Model was written in NetLogo 6.4.0
•
Viewed 3 times
•
Downloaded 2 times
•
Run 0 times
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
extensıons [csv] ;; Import the CSV extension for handling data files globals [ ;; Define global variables accessible throughout the model data ;; Stores the dataset read from a CSV file data-source ;; Specifies the file path or source of the data data-pointer ;; Tracks the current position in the dataset data-length ;; Holds the total number of data entries data-date ;; Stores the date information for data entries (e.g., "01.01.2020") DayofYear ;; Represents the day number in a year (1-365 or 1-366 for leap years) DayofMonth ;; Represents the day number in a month (1-31) Month ;; Stores the month number (1-12) Week ;; Stores the week number of the year data-weekday ;; Stores the day of the week (e.g., Monday, Tuesday) data-vacation ;; Indicates if the day is a vacation day (e.g., "none", "weekend", or another label) data-temp ;; Stores temperature data for each day data-prcp ;; Stores precipitation data for each day data-housesMonthly ;; Tracks the number of houses per month from the CSV data-popMonthly ;; Tracks the population per month from the CSV data-totalMonthly ;; Stores the total consumption per month from the CSV HeuristicMonthlyTotal ;; Stores heuristic estimates for monthly total consumption from the CSV data-avgDaily ;; Stores the average daily consumption from the CSV HeuristicDailyTotal ;; Stores heuristic estimates for daily total consumption from the CSV AverageWeekly ;; Stores the average weekly consumption from the CSV HeuristicWeekly ;; Stores heuristic estimates for weekly consumption from the CSV fwcf ;; Represents the weather correction factor (float) from the CSV file number-of-humans ;; Stores the total number of humans in the model number-of-houses ;; Stores the total number of houses in the model remaining ;; Tracks the remaining number of houses to be added into the world in each simulation time workingPeople ;; Stores the count of working individuals (i.e., is-outsider?) vacationistPeople ;; Stores the count of vacationists weekenderPeople ;; Stores the count of people who go outside on weekends num-under5 ;; Stores the number of children under 5 years old num-5&17 ;; Stores the number of children aged 5 to 17 num-seniors ;; Stores the number of senior citizens (e.g., > 65) num-adults ;; Stores the number of adults (e.g., 18-65) num-singles ;; Stores the number of single individuals num-2adults ;; Stores the number of households with two adults num-1parent+child ;; Stores the number of single-parent households with children start-res ;; Represents the number of starting residents on each tick water-consumption ;; Stores the total water consumption of the district at each tick worldSize ;; Stores the size of the simulated world (used to calculate worldDmnsn) worldDmnsn ;; Stores the dimensions of the simulated world (sqrt of worldSize) logfile ;; Stores the log file name or path previous-outsiders ;; Stores the count of outsiders from the previous period previous-weekenders ;; Stores the count of weekenders from the previous period previous-vacationists ;; Stores the count of vacationers from the previous period temp-outsiders ;; Temporary storage for outsider ratio temp-weekenders ;; Temporary storage for weekender ratio temp-vacationists ;; Temporary storage for vacationist ratio temp-change-active? ;; Flag indicating whether a temporary ratio change is active temp-change-pending? ;; Flag indicating whether a temporary ratio change is scheduled (waiting to start) temp-change-start-tick ;; The tick at which the temporary ratio change started temp-change-end-tick ;; The tick at which the temporary ratio change ends daily-consumption ;; Tracks daily water consumption monthly-consumption ;; Tracks monthly water consumption weekly-consumption ;; Tracks weekly water consumption yearly-consumption ;; Tracks yearly water consumption (if needed) data-loaded? ;; Indicates if data has been loaded successfully simulation-start-date ;; Numerical representation of the start date from CSV simulation-end-date ;; Numerical representation of the end date from CSV current-month ;; Tracks the current month (for aggregating monthly consumption) current-week ;; Tracks the current week (for aggregating weekly consumption) current-data-index ;; An index to navigate through unique months/weeks if needed unique-custom-months ;; A list of unique "custom months" (if used) unique-months ;; A list of unique months read from CSV unique-weeks ;; A list of unique weeks read from CSV current-custom-month ;; Tracks a custom month index if needed unique-custom-weeks ;; A list of unique "custom weeks" if used average-monthly-consumption ;; Average monthly consumption (running average over the simulation) average-weekly-consumption ;; Average weekly consumption (running average over the simulation) average-daily-consumption ;; Average daily consumption (running average over the simulation) monthly-consumption-list ;; A list collecting monthly consumption values weekly-consumption-list ;; A list collecting weekly consumption values daily-consumption-list ;; A list collecting daily consumption values total-water-consumption ;; Accumulated water consumption since start of sim weekday-consumption ;; Water consumption recorded for weekdays weekend-consumption ;; Water consumption recorded for weekends vacation-consumption ;; Water consumption recorded for vacation days weekday-consumption-total ;; Total water consumption for all weekdays so far weekend-consumption-total ;; Total water consumption for all weekends so far vacation-consumption-total ;; Total water consumption for all vacation days so far weekday-count ;; Number of weekday ticks encountered so far weekend-count ;; Number of weekend ticks encountered so far vacation-count ;; Number of vacation-day ticks encountered so far avg-weekday-consumption ;; Average consumption for weekdays avg-weekend-consumption ;; Average consumption for weekends avg-vacation-consumption ;; Average consumption for vacation days ] breed [humans human] ;; Define a "humans" breed of turtles humans-own [ age house workplace category education-age clmt-strtgy daily-strtgy status is-outsider? is-weekender? is-vacationist? ] patches-own [ hhs ;; The number of humans (household size) associated with a patch working ;; Number of "working" humans in that patch employees ;; Possibly used to store employees in that patch income ;; Household income or patch-level income if used hhtype ;; String describing patch type: "outside", "household", "workplace" avgHHAge ;; Average household age lvng-strtgy ;; Lifestyle strategy placeholder eat-strategy ;; Eating strategy placeholder clean-strategy ;; Cleaning strategy placeholder maintenance-strategy;; Maintenance strategy placeholder water-cnsmptn ;; Total water consumption in that patch tap-water ;; Water consumption from tap usage dw-water ;; Water consumption from dishwasher usage wm-water ;; Water consumption from washing machine usage toilet-water ;; Water consumption from toilet flushing shower-water ;; Water consumption from shower usage tap-use ;; Frequency or usage intensity for tap dw-use ;; Frequency or usage intensity for dishwasher wm-use ;; Frequency or usage intensity for washing machine toilet-use ;; Frequency or usage intensity for toilet shower-use ;; Frequency or usage intensity for shower eat-and-drink-water ;; Subtotal consumption for eating/drinking cleaning-water ;; Subtotal consumption for cleaning maintenance-water ;; Subtotal consumption for maintenance insiders ;; Number of "insider" humans in this patch dw-load ;; A running counter to track when a dishwasher load is triggered wm-load ;; A running counter to track when a washing machine load is triggered weekender ;; A counter or flag for weekenders in this patch vacationist ;; A counter or flag for vacationists in this patch tap-eat-drink ;; Detailed breakdown of tap usage for eating/drinking tap-clean-up ;; Detailed breakdown of tap usage for cleaning tap-maintenance ;; Detailed breakdown of tap usage for maintenance dw-eat-drink ;; Detailed breakdown of dishwasher usage for eating/drinking dw-clean-up ;; Detailed breakdown of dishwasher usage for cleaning wm-clean-up ;; Detailed breakdown of washing machine usage for cleaning wm-maintenance ;; Detailed breakdown of washing machine usage for maintenance ] ; ===== SETUP PROCEDURES ===== to setup ;; Primary setup procedure. Calls various sub-setup procedures only if data is loaded. ifelse data != 0 and data != false [ ;; Only proceed if 'data' is not empty or false. This checks if the user has loaded CSV data. clear-all-plots clear-patches clear-turtles clear-drawing clear-all-plots reset-ticks ;; Initialize simulation environment set-globals set-the-world set-the-household setup-human-types ;; Set up data tracking variables set data-length length data set current-data-index 0 set current-month 0 set current-week 0 set monthly-consumption 0 set weekly-consumption 0 set total-water-consumption 0 ;; Initialize consumption tracking counters set weekday-consumption-total 0 set weekend-consumption-total 0 set vacation-consumption-total 0 set weekday-count 0 set weekend-count 0 set vacation-count 0 ;; Initialize consumption tracking lists set monthly-consumption-list [] set weekly-consumption-list [] set daily-consumption-list [] ;; Set up logging set logfile "simulation_log.txt" ;; Default log file name ;; Extract simulation date range from data (the first and last rows) if not empty? data [ set simulation-start-date date-to-number item 0 (item 0 data) set simulation-start-date date-to-number item 0 (item 0 data) set simulation-end-date date-to-number item 0 (last data) set unique-months remove-duplicates map [d -> extract-month item 0 d] data set unique-weeks remove-duplicates map [d -> extract-week item 0 d] data ] ;; setup-water-consumption-plots (if you have a separate procedure for that) set simulation-start-date date-to-number (item 0 (item 0 data)) ;; Convert first row's date to a number set simulation-end-date date-to-number (item 0 (last data)) ;; Convert last row's date to a number ;; Initialize temporary change tracking set temp-change-active? false set temp-change-pending? false set temp-change-start-tick 0 set temp-change-end-tick 0 ;; Store initial population ratios set previous-outsiders Outsiders set previous-weekenders Weekenders set previous-vacationists Vacationists ;; Update population ratios once at the start update-population-ratios output-print "Simulation environment has been set up succesfully." ] [ user-message "Please first load the data using 'Load Data' button." ] end ; ===== DATA LOADING AND MANAGEMENT ===== to startup ;; This procedure runs automatically when the model is first opened. We initialize empty data structures. set data [] set data-length 0 set data-loaded? false end to Data-Load ;; Called from a button to load a CSV file. Uses the NetLogo 'carefully' to catch any errors during file operations. carefully [ let file user-file ifelse file != false [ ;; If the user selected a file: ;; Check if file is CSV format by checking the last 4 chars ifelse (substring file (length file - 4) length file) = ".csv" [ set data csv:from-file file ;; Use the CSV extension to read the file into 'data' if not empty? data [ ;; If data is not empty, store file info and handle potential header row set data-source file ;; Remove header row if the first row has strings in item 0 if length first data > 0 and is-string? item 0 first data [ set data but-first data ] set data-pointer 0 set data-length length data set-current-vals ;; Load values from the first row into the model's global variables output-print (word "Data has been successfully loaded: " data-source) output-print (word "Number of data points: " data-length) ] ] [ ;; If the file doesn't end with ".csv", show an error user-message "Please select a CSV file. The selected file does not appear to be a CSV file." output-print "Error: Non-CSV file selected." ] ] [ ;; If user canceled or no file selected output-print "No file was selected or the operation was cancelled." ] ] [ ;; 'carefully' error block: if anything goes wrong, show a user message user-message (word "An unexpected error has occurred while reading the file: " error-message) output-print (word "Error Details: " error-message) ;; Save error log if needed carefully [ file-open "error_log.txt" file-print (word date-and-time " - File Reading Error: " error-message) file-close ] [] ] end to-report read-data [ file-name ] ;; A helper reporter to read CSV data from a file let rows [] if file-name != false [ set data-source file-name file-open file-name set rows csv:from-file file-name file-close ] report rows end to update-population-ratios ;; Reassigns humans to outsider, weekender, or vacationist groups based on global ratio variables let total-humans count humans let new-outsiders round (total-humans * Outsiders) let new-weekenders round (total-humans * Weekenders) let new-vacationists round (total-humans * Vacationists) ;; Reset all humans to default (no special type) ask humans [ set is-outsider? false set is-weekender? false set is-vacationist? false ] ;; Assign 'Outsiders' let available-humans humans let outsiders-to-assign min (list new-outsiders count available-humans) ask n-of outsiders-to-assign available-humans [ set is-outsider? true ] ;; Update who is left set available-humans humans with [not is-outsider?] ;; Assign 'Weekenders' let weekenders-to-assign min (list new-weekenders count available-humans) ask n-of weekenders-to-assign available-humans [ set is-weekender? true ] ;; Update who is left set available-humans humans with [not is-outsider? and not is-weekender?] ;; Assign 'Vacationists' let vacationists-to-assign min (list new-vacationists count available-humans) ask n-of vacationists-to-assign available-humans [ set is-vacationist? true ] ;; Update global reference sets set workingPeople humans with [is-outsider?] set weekenderPeople humans with [is-weekender?] set vacationistPeople humans with [is-vacationist?] ;; Update any dependent variables or patch-level variables update-dependent-variables end to set-current-vals ;; Reads the current row in 'data' at 'data-pointer' and sets global variables. let vals-list item data-pointer data set data-date item 0 vals-list set DayofYear item 1 vals-list set DayofMonth item 2 vals-list set Month item 3 vals-list set Week item 4 vals-list set data-weekday item 5 vals-list set data-vacation item 6 vals-list set data-temp item 7 vals-list set data-prcp item 8 vals-list set data-housesMonthly item 9 vals-list set data-popMonthly item 10 vals-list set data-totalMonthly item 11 vals-list set HeuristicMonthlyTotal item 12 vals-list set data-avgDaily item 13 vals-list set HeuristicDailyTotal item 14 vals-list set AverageWeekly item 15 vals-list set HeuristicWeekly item 16 vals-list set fwcf item 17 vals-list end to set-globals ;; Initialize some global variables at setup set number-of-houses data-housesMonthly set start-res count patches with [pcolor = yellow] set number-of-humans count humans with [pcolor = yellow] end to set-the-world ;; Resizes and configures the NetLogo world based on the number of houses set worldSize number-of-houses * 3 set worldDmnsn sqrt worldSize resize-world (- worldDmnsn) worldDmnsn (- worldDmnsn) worldDmnsn ask patches [ set pcolor black set hhtype "outside" ] ;; Color some patches yellow to represent houses ask n-of number-of-houses patches [ set pcolor yellow set hhtype "household" ] ;; Convert a fraction of patches into workplaces ask n-of (number-of-houses * (100 - residenceRatio) * 0.01) patches with [pcolor = black] [ set pcolor grey set hhtype "workplace" ] end to set-the-household ;; Assign household sizes (hhs) to each household patch and create humans ask patches with [hhtype = "household"] [ set hhs round random-normal householdSize varHHS while [hhs < 1] [set hhs round random-normal householdSize varHHS] ] ;; Calculate sub-population sizes set num-under5 round (data-popMonthly * %Under5) set num-5&17 round (data-popMonthly * %5&17) set num-seniors round (data-popMonthly * %Seniors) set num-adults (data-popMonthly - num-under5 - num-5&17 - num-seniors) ;; Create humans in total equal to 'data-popMonthly' create-humans data-popMonthly [ set house one-of patches with [hhtype = "household"] move-to house set age assign-age set-human-category ] end to-report assign-age ;; Randomly assign an age to a new human based on population percentages let r random-float 1 (ifelse r < %Under5 [report random 5] r < (%Under5 + %5&17) [report 5 + random 13] r < (1 - %Seniors) [report 18 + random 48] [report 66 + random 35]) end to set-human-category ;; Assign a category (infant, school-age, adult, senior) and color (ifelse age < 6 [set category "infant" set color lime] age >= 6 and age < 18 [set category "school-age" set color cyan] age >= 18 and age < 66 [set category "adult" set color sky] [set category "senior" set color blue]) end to setup-human-types ;; Assign each human a boolean for is-outsider?, is-weekender?, is-vacationist? ask humans [ set is-outsider? random-float 1 < Outsiders set is-weekender? random-float 1 < Weekenders set is-vacationist? random-float 1 < Vacationists ] end ; ===== SIMULATION CONTROL PROCEDURES ===== to go ;; Main simulation loop, typically called by a "go" button ;; 1. Check for temporary population ratio changes if temp-change-active? and ticks >= temp-change-end-tick [ ;; If the current tick passes the end tick for a temporary change, revert revert-to-original-ratios ] ;; 2. Update population ratios if needed check-and-update-ratios ;; 3. Update the current date (if you store or display it) update-current-date ;; 4. Stop if we've reached the end of data if data-pointer >= data-length [stop] ;; 5. Execute main simulation steps get-next-record check-for-change ;; Check if number of houses changed this month move-humans ;; Humans move to workplaces, outside, or stay at home consume-water ;; Calculate water usage ;; 6. Update consumption tracking update-water-consumption set total-water-consumption total-water-consumption + water-consumption track-water-consumption ;; 7. Log results for analysis specifics-logfile tick ;; Advance NetLogo's time end to get-next-record ;; Moves the data pointer to the next row in 'data' set data-pointer data-pointer + 1 if data-pointer >= data-length [stop] set-current-vals end to check-and-update-ratios ;; Adjust population ratios if the global ratio variables changed or if a temporary change is in effect ifelse temp-change-active? [ ;; If a temporary change is active, ensure the ratio variables match the temporary ones if Outsiders != temp-outsiders or Weekenders != temp-weekenders or Vacationists != temp-vacationists [ set Outsiders temp-outsiders set Weekenders temp-weekenders set Vacationists temp-vacationists update-population-ratios ] ] [ ;; If not in a temporary change, watch if the user changed the ratio sliders if previous-outsiders != Outsiders or previous-weekenders != Weekenders or previous-vacationists != Vacationists [ update-population-ratios set previous-outsiders Outsiders set previous-weekenders Weekenders set previous-vacationists Vacationists ] ] end to check-for-change ;; If the monthly data shows a different # of houses than we currently have, adjust the world if data-housesMonthly != number-of-houses [ let diff data-housesMonthly - number-of-houses ifelse diff > 0 [create-new-houses diff] [remove-houses (- diff)] ] set number-of-houses data-housesMonthly end to create-new-houses [n] ;; Convert 'n' black patches into households, and create humans in each new house ask n-of n patches with [pcolor = black] [ set pcolor yellow set hhtype "household" set hhs round random-normal householdSize varHHS sprout-humans hhs [ set house patch-here set age assign-age set-human-category setup-human-types ] ] end to remove-houses [n] ;; Convert 'n' household patches back to black patches, killing any humans there ask n-of n patches with [hhtype = "household"] [ ask humans-here [die] set pcolor black set hhtype "outside" ] end ; ===== HUMAN MOVEMENT AND BEHAVIOR ===== to move-humans ;; Control movement of human agents based on their type and current conditions ask humans [ ifelse should-go-out? [ ;; If this human should go out, decide where based on type of day ifelse is-outsider? and data-vacation = "none" and not member? data-weekday ["Saturday" "Sunday"] ;; 1. Outsiders go to workplace on weekdays if not a vacation day [move-to one-of patches with [hhtype = "workplace"]] ;; 2. Otherwise, if it's a weekend or a vacation day, go 'outside' [if (is-weekender? and member? data-weekday ["Saturday" "Sunday"]) or (is-vacationist? and data-vacation != "none") [move-to one-of patches with [hhtype = "outside"]]] ] ;; If the human isn't going out, stay (or return) to their house [move-to house] ] end to-report should-go-out? ;; Decide probabilistically if a human should leave home based on temperature, precip, day-type, etc. let temp-factor temperature-factor data-temp let precip-factor precipitation-factor data-prcp let day-factor day-type-factor data-weekday data-vacation let go-out-probability temp-factor * precip-factor * day-factor ;; Younger than 5 or older than 65 => reduce their likelihood by 50% if age < 5 or age > 65 [set go-out-probability go-out-probability * 0.5] report random-float 1 < go-out-probability and (is-outsider? or is-weekender? or is-vacationist?) end to-report temperature-factor [temp] ;; Simple example that modifies a factor based on temperature ranges (ifelse temp < -10 [report 0.5] temp < 4 [report 0.5 + (temp + 10) / 28] temp < 13 [report 0.75 + (temp - 4) / 36] temp < 26 [report 1] [report 1 - (temp - 26) / 74]) end to-report precipitation-factor [precip] ;; A simple linear factor to reduce the probability if precipitation is high report 1 - (precip / 100) end to-report day-type-factor [weekday vacation] ;; Returns a factor based on day type or vacation ifelse vacation != "none" [report Vacationists] [ifelse member? weekday ["Saturday" "Sunday"] [report Weekenders] [report Outsiders]] end ; ===== WATER CONSUMPTION CALCULATIONS ===== to consume-water ;; Calculates water consumption in each household patch and sums the total let total-consumption 0 ask patches with [hhtype = "household"] [ let occupants count humans-here ifelse occupants > 0 [ ;; If there are occupants, calculate usage let tap-consumption occupants * tapUse * Tap-Lt-m set tap-eat-drink tap-consumption set tap-clean-up tap-consumption set tap-maintenance tap-consumption ;; Dishwasher usage set dw-eat-drink calculate-dw-usage occupants set dw-clean-up calculate-dw-usage occupants ;; Washing machine usage set wm-clean-up calculate-wm-usage occupants set wm-maintenance calculate-wm-usage occupants ;; Personal usage for toilet & shower set toilet-water occupants * toiletUse * Flush-Lt set shower-water occupants * showerUse * Shower-Lt-m ;; Group consumption by activity set eat-and-drink-water tap-eat-drink + dw-eat-drink set cleaning-water tap-clean-up + dw-clean-up + wm-clean-up + shower-water + toilet-water set maintenance-water tap-maintenance + wm-maintenance ;; Sum the consumption from all devices let total-appliance-consumption eat-and-drink-water + cleaning-water + maintenance-water ;; Apply weather correction factor (fwcf) from the CSV let adjusted-consumption ifelse-value (fwcf < 0) [total-appliance-consumption - (total-appliance-consumption * abs fwcf)] [total-appliance-consumption + (total-appliance-consumption * fwcf)] ;; Ensure at least a minimum consumption (base-demand-per-capita * occupants) set water-cnsmptn max list (occupants * base-demand-per-capita) adjusted-consumption ;; If we had to bump up consumption to meet the min threshold, scale each component if water-cnsmptn > adjusted-consumption [ let scaling-factor water-cnsmptn / adjusted-consumption set eat-and-drink-water eat-and-drink-water * scaling-factor set cleaning-water cleaning-water * scaling-factor set maintenance-water maintenance-water * scaling-factor ] ][ ;; If no occupants, consumption is 0 set water-cnsmptn 0 set eat-and-drink-water 0 set cleaning-water 0 set maintenance-water 0 ] set total-consumption total-consumption + water-cnsmptn ] set water-consumption total-consumption end to-report calculate-dw-usage [occupants] ;; Tracks dishwasher usage. If dw-load >= 1, we run the dishwasher once (DW-Lt). set dw-load dw-load + (dwUse * occupants) ifelse dw-load >= 1 [ set dw-load dw-load - 1 report DW-Lt ][ report 0 ] end to-report calculate-wm-usage [occupants] ;; Tracks washing machine usage. If wm-load >= 1, we run the washing machine once (WM-Lt). set wm-load wm-load + (wmUse * occupants) ifelse wm-load >= 1 [ set wm-load wm-load - 1 report WM-Lt ][ report 0 ] end to specifics-logfile ;; Creates a log entry for the current tick/day and writes it to file or output let monthly-water-use ifelse-value monthly-consumption != [] [precision (monthly-consumption / 1000) 0] [0] let weekly-water-use ifelse-value weekly-consumption != [] [precision (weekly-consumption / 1000) 0] [0] let log-entry (word "date:" data-date " weekday:" data-weekday " vacation:" data-vacation " temp:" data-temp " prcp:" data-prcp " NumberOfHumans:" count humans " NumberOfHouses:" number-of-houses " TotalWaterUse:" (total-water-consumption / 1000) " MonthlyWaterUse:" monthly-water-use " WeeklyWaterUse:" weekly-water-use " NumAdults:" count humans with [age > 17 and age < 66] " NumSeniors:" count humans with [ age > 65] " NumSchAge:" count humans with [ age > 5 and age < 18] " NumInfants:" count humans with [age < 6] " TapWater:" (sum [tap-eat-drink + tap-clean-up + tap-maintenance] of patches / 1000 ) " ToiletWater:" (sum [toilet-water] of patches / 1000) " ShowerWater:" (sum [shower-water] of patches / 1000) " WMWater:" (sum [wm-maintenance + wm-clean-up] of patches / 1000) " DWWater:" (sum [dw-eat-drink + dw-clean-up] of patches / 1000) ) if print-to-logfile? [ print-to-file log-entry ] if print-to-output? [ output-print log-entry ] end to print-to-file [file-text] ;; Appends a line to the log file (if logfile is valid) if is-string? logfile and logfile != "" [ carefully [ file-open logfile file-print file-text file-close ] [ print (word "Error writing to log file: " error-message) ] ] end to restart-data ;; Resets the data pointer and re-initializes consumption counters set data-pointer 0 set data-length length data set-current-vals output-print "Reset to first record" let log-entry (word "\r -- New Session -- " date-and-time) if print-to-logfile? [ carefully [ print-to-file log-entry print-to-file logfile print-to-file data-source ] [ print "Error writing to log file" ] ] ;; Reset tracking variables set monthly-consumption [] set weekly-consumption [] set weekday-consumption 0 set weekend-consumption 0 set vacation-consumption 0 set weekday-consumption-total 0 set weekend-consumption-total 0 set vacation-consumption-total 0 set weekday-count 0 set weekend-count 0 set vacation-count 0 ask patches [ set water-cnsmptn 0 set eat-and-drink-water 0 set cleaning-water 0 set maintenance-water 0 ] set water-consumption 0 specifics-logfile clear-plots reset-ticks end to delete-logfile ;; Deletes the current log file if it exists if is-string? logfile and file-exists? logfile [ file-delete logfile output-print "Log file deleted" ] end to go-data ;; If you want to just advance one day in the data, call get-next-record and log, then consume get-next-record specifics-logfile consume-water tick end to report-ratio-achievement ;; Prints how close we are to the desired ratio of outsiders/weekenders/vacationists let total-humans count humans let actual-outsiders count humans with [is-outsider?] let actual-weekenders count humans with [is-weekender?] let actual-vacationists count humans with [is-vacationist?] print (word "Desired Outsiders: " Outsiders " Actual: " (actual-outsiders / total-humans)) print (word "Desired Weekenders: " Weekenders " Actual: " (actual-weekenders / total-humans)) print (word "Desired Vacationists: " Vacationists " Actual: " (actual-vacationists / total-humans)) end to parse-and-set-temp-change [input-string new-outsiders new-weekenders new-vacationists] ;; Reads the user input string in format "DD.MM.YYYY duration" and sets temporary ratio changes let parts read-from-string (word "[" input-string "]") if length parts != 2 [ user-message "Invalid input format. Please use 'DD.MM.YYYY duration' format." stop ] set temp-outsiders new-outsiders set temp-weekenders new-weekenders set temp-vacationists new-vacationists set temp-change-pending? true end to activate-temporary-change ;; Activates a previously scheduled temporary ratio change set temp-change-active? true set temp-change-pending? false set temp-change-start-tick ticks set previous-outsiders Outsiders set previous-weekenders Weekenders set previous-vacationists Vacationists set Outsiders temp-outsiders set Weekenders temp-weekenders set Vacationists temp-vacationists update-population-ratios end to revert-to-original-ratios ;; Reverts from the temporary ratios back to the original ones set Outsiders previous-outsiders set Weekenders previous-weekenders set Vacationists previous-vacationists set temp-change-active? false update-population-ratios end to-report date-to-comparable [date-string] ;; An example procedure to convert a string date into a comparable numeric value let parts remove "." date-string report read-from-string (word (item 4 parts) (item 2 parts) (item 0 parts)) end to-report date-to-number [date-string] ;; Converts date "DD.MM.YYYY" into a single integer YYYYMMDD let parts splitt date-string "." if length parts != 3 [ user-message (word "Invalid date format: " date-string ". Please use DD.MM.YYYY format.") report false ] let day read-from-string item 0 parts set month read-from-string item 1 parts let year read-from-string item 2 parts report (year * 10000) + (month * 100) + day end to-report splitt [string delimiter] ;; Splits a string on a given delimiter and returns a list let result [] while [not empty? string] [ let index position delimiter string ifelse index != false [ set result lput (substring string 0 index) result set string substring string (index + 1) length string ] [ set result lput string result set string "" ] ] report result end to-report extract-month [date-string] ;; Extracts the month portion from a "DD.MM.YYYY" string as a number let parts split date-string "." if length parts != 3 [ user-message (word "Invalid date format: " date-string ". Please use DD.MM.YYYY format.") report false ] report read-from-string item 1 parts end to-report extract-week [date-string] ;; Approximate function to get a week number from a date (not ISO standard) let parts split date-string "." if length parts != 3 [ user-message (word "Invalid date format: " date-string ". Please use DD.MM.YYYY format.") report false ] let day read-from-string item 0 parts set month read-from-string item 1 parts let year read-from-string item 2 parts ;; Rough calculation (this is not calendar-accurate but might work for your needs) report (((month - 1) * 30 + day) / 7) + 1 end to update-current-date ;; A placeholder that could update data-date or other date variables each tick if needed. ;; For example: ;; set data-date read-next-date-from-file end to apply-temporary-ratio-change [start-date new-outsiders new-weekenders new-vacationists duration] ;; Another placeholder for a user command that schedules a ratio change set temp-outsiders read-from-string2 new-outsiders set temp-weekenders read-from-string2 new-weekenders set temp-vacationists read-from-string2 new-vacationists set temp-change-pending? true end to-report read-from-string2 [str] report read-from-string str end to-report date-to-list [date-string] ;; Converts "DD.MM.YYYY" to a list [day month year] report map [ s -> read-from-string s ] split date-string "." end to-report split [string delimiter] ;; Another version of 'split', similar to 'splitt' above let result [] while [not empty? string] [ let index position delimiter string ifelse index != false [ set result lput (substring string 0 index) result set string substring string (index + 1) length string ] [ set result lput string result set string "" ] ] report result end to update-water-consumption ;; Aggregates daily consumption into monthly and weekly totals, storing them in lists ifelse Month != current-month [ ;; If we have a new month, store the old month's consumption in a list if monthly-consumption > 0 [ set monthly-consumption-list lput monthly-consumption monthly-consumption-list ] set monthly-consumption water-consumption set current-month Month ] [ set monthly-consumption monthly-consumption + water-consumption ] ifelse Week != current-week [ ;; If we have a new week, store the old week's consumption in a list if weekly-consumption > 0 [ set weekly-consumption-list lput weekly-consumption weekly-consumption-list ] set weekly-consumption water-consumption set current-week Week ] [ set weekly-consumption weekly-consumption + water-consumption ] ;; Track daily usage in a list set daily-consumption-list lput water-consumption daily-consumption-list ;; Update overall average values update-average-consumptions end to update-average-consumptions ;; Calculate running averages for monthly, weekly, daily consumption set average-monthly-consumption ifelse-value not empty? monthly-consumption-list [mean monthly-consumption-list] [0] set average-weekly-consumption ifelse-value not empty? weekly-consumption-list [mean weekly-consumption-list] [0] set average-daily-consumption ifelse-value not empty? daily-consumption-list [mean daily-consumption-list] [0] end to clear-plots ;; Clears named plots so they can be re-drawn set-current-plot "Simulation Starters" clear-plot set-current-plot "Water Demand Estimation" clear-plot set-current-plot "Household Consumption" clear-plot set-current-plot "Monthly Water Consumption" clear-plot set-current-plot "Weekly Water Consumption" clear-plot set-current-plot "Water Consumption Based on Day Type" clear-plot end to update-dependent-variables ;; Update any variables that depend on outsider/weekender/vacationist counts ask patches with [hhtype = "household"] [ set working count humans-here with [is-outsider?] set weekender count humans-here with [is-weekender?] set vacationist count humans-here with [is-vacationist?] ] end to go-until ;; Run the simulation until a user-specified 'date-to-stop' if empty? date-to-stop [ user-message "Please enter a date to stop in the 'date-to-stop' input box." stop ] let start-date-list date-to-list data-date let stop-date-list date-to-list date-to-stop if not is-valid-date? start-date-list or not is-valid-date? stop-date-list [ ;; If either date is invalid, stop stop ] let days-to-run days-between start-date-list stop-date-list if days-to-run < 0 [ user-message "Stop date must be after the current simulation date." stop ] let target-tick ticks + days-to-run while [ticks < target-tick and data-pointer < data-length] [ go ] if ticks >= target-tick [ output-print (word "Simulation stopped at " data-date) ] if data-pointer >= data-length [ output-print "Reached end of data before stop date." ] end to-report days-between [start-date-list stop-date-list] ;; Calculate how many days are between two dates (day, month, year) let start-day item 0 start-date-list let start-month item 1 start-date-list let start-year item 2 start-date-list let stop-day item 0 stop-date-list let stop-month item 1 stop-date-list let stop-year item 2 stop-date-list let days 0 ;; Increment day-by-day until start date == stop date while [start-year < stop-year or (start-year = stop-year and start-month < stop-month) or (start-year = stop-year and start-month = stop-month and start-day < stop-day)] [ set days days + 1 set start-day start-day + 1 if start-day > days-in-month start-month start-year [ set start-day 1 set start-month start-month + 1 if start-month > 12 [ set start-month 1 set start-year start-year + 1 ] ] ] report days end to-report is-valid-date? [date-list] ;; Quick check that day, month, year are in plausible ranges if length date-list != 3 [ user-message "Invalid date format. Please use DD.MM.YYYY format." report false ] let day item 0 date-list set month item 1 date-list let year item 2 date-list if day < 1 or day > 31 or month < 1 or month > 12 or year < 1900 or year > 2100 [ user-message "Invalid date values. Please check your input." report false ] report true end to-report days-in-month [month-num year] ;; Returns the number of days in a given month, accounting for leap years in February let days-list [31 28 31 30 31 30 31 31 30 31 30 31] if month-num = 2 and is-leap-year? year [ report 29 ] report item (month-num - 1) days-list end to-report is-leap-year? [year] ;; Standard leap-year check report (year mod 4 = 0 and year mod 100 != 0) or (year mod 400 = 0) end to track-water-consumption ;; Categorizes today's water consumption into weekday, weekend, or vacation set weekday-consumption 0 set weekend-consumption 0 set vacation-consumption 0 ;; If it's not a vacation day if data-vacation = "none" [ ;; Check if it's a weekday or weekend ifelse not member? data-weekday ["Saturday" "Sunday"] [ ;; Weekday set weekday-consumption water-consumption set weekday-consumption-total weekday-consumption-total + water-consumption set weekday-count weekday-count + 1 ] ;; Weekend [ set weekend-consumption water-consumption set weekend-consumption-total weekend-consumption-total + water-consumption set weekend-count weekend-count + 1 ] ] ;; If it is a vacation day, decide if it's specifically "weekend" or other ifelse data-vacation = "weekend" [ set weekend-consumption water-consumption set weekend-consumption-total weekend-consumption-total + water-consumption set weekend-count weekend-count + 1 ] [ if data-vacation != "none" [ set vacation-consumption water-consumption set vacation-consumption-total vacation-consumption-total + water-consumption set vacation-count vacation-count + 1 ] ] ;; Update average usage for each day type set avg-weekday-consumption ifelse-value weekday-count > 0 [weekday-consumption-total / weekday-count] [0] set avg-weekend-consumption ifelse-value weekend-count > 0 [weekend-consumption-total / weekend-count] [0] set avg-vacation-consumption ifelse-value vacation-count > 0 [vacation-consumption-total / vacation-count] [0] end
There is only one version of this model, created 16 days ago by Kamil Aybuğa.
Attached files
File | Type | Description | Last updated | |
---|---|---|---|---|
WaDemEsT.png | preview | Preview for 'WaDemEsT' | 16 days ago, by Kamil Aybuğa | Download |
This model does not have any ancestors.
This model does not have any descendants.