--- title: "extending-resources" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{extending-resources} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} library(plotly) library(villager) ``` # Extending Resources To create resources that have additional properties, subclass the `resource` class. To add new members to the resource class, 1. Copy the _resource_ class source definition 2. Create the new member variable 3. Add it as a parameter to the `initialize` function 4. Make an entry for it in the `as_table` function ## Resource with an expiration date To demonstrate how to subclass and run a model with a custom _resource_ class, consier an example of corn and rice resources that expire. To do this, a new variable is added to the resource class, `creation_date` which gets updated when the resource is created. When the model runs, the date at each time step is used to check against the creation date of each resource. ### Custom resource class ```{r} resource_expiration <- R6::R6Class("resource", cloneable = TRUE, public = list( name = NA, quantity = NA, creation_date = NA, #' Creates a new resource. #' #' @description Creates a new resource object #' @param name The name of the resource #' @param quantity The quantity present #' @param creation_date The date that the resource was created initialize = function(name = NA, quantity = 0, creation_date=NA) { self$name <- name self$quantity <- quantity self$creation_date <- creation_date # New member variable to track the creation date }, #' Returns a data.frame representation of the resource #' #' @return A data.frame of resources as_table = function() { return(data.frame(name = self$name, quantity = self$quantity)) } ) ) ``` ### Initial Condition The initial condition is a village that has two resource types, corn and rice. ``` {r} initial_condition <- function(current_state, model_data, agent_mgr, resource_mgr) { for (i in 1:10) { name <- runif(1, 0.0, 100) new_agent <- agent$new(first_name <- name, last_name <- "Smith") agent_mgr$add_agent(new_agent) } # Create two new resources at the current date (The first day) corn <- resource_expiration$new("Corn", 10, current_state$step) rice <- resource_expiration$new("Rice", 20, current_state$step) resource_mgr$add_resource(corn) resource_mgr$add_resource(rice) } ``` ### Model The model checks the current date against the expiration dates on each resource. When the threshold limits are reached, the quantity is set to zero. ```{r} # Create the model that, each day, checks to see whether or not any resource expire model <- function(current_state, previous_state, model_data, agent_mgr, resource_mgr, village_mgr) { # Loop over all of the resources and check if any expire for (resource in resource_mgr$get_resources()) { # Figure out how many days have passed days_passed <- current_state$step - resource$creation_date if (resource$name == "Corn") { if (days_passed > 10 && resource$quantity > 0) { print("Setting Corn quantity to 0") resource$quantity <- 0 } } else if (resource$name == "Rice" && resource$quantity > 0) { if (days_passed > 20) { print("Setting Rice quantity to 0") resource$quantity <- 0 } } } } ``` ### Running With the required model components complete, we can create a simulation that runs for 15 days. By the end of it, there should be no more corn left, and the rice stocks should still be full. ```{r} # Create the village and simulation coastal_village <- village$new("Expiring_Resources", initial_condition, model, resource_class=) simulator <- simulation$new(16, villages = list(coastal_village)) simulator$run_model() ``` ### Results A timeseries of each resource type is plotted below. The _rice_ resource has clearly not expired while the _corn_ resource has after 10 days. ```{r} # Load in data time_series_data <- readr::read_csv("results/Expiring_Resources/resources.csv") # Get unique dates unique_step<- sort(unique(time_series_data$step)) # Get corn & rice quantities and dates corn_date_quantities <- dplyr::filter(time_series_data, name=="Corn") rice_date_quantities <- dplyr::filter(time_series_data, name=="Rice") # create data frame for sorted data reordered_time_series <- data.frame(step = unique_step, Corn = 0, Rice = 0) for (i in 1:nrow(reordered_time_series)){ reordered_time_series[i,2] = corn_date_quantities[which(corn_date_quantities$step == reordered_time_series$step[i]),2] reordered_time_series[i,3] = rice_date_quantities[which(rice_date_quantities$step == reordered_time_series$step[i]),2] } # Plot graph plotly::plot_ly(reordered_time_series, x = ~step) %>% plotly::add_trace(y = ~Corn, name = 'Corn', type = 'scatter', mode = 'lines') %>% plotly::add_trace(y = ~Rice, name = 'Rice', type = 'scatter', mode = 'lines') %>% plotly::layout(title = 'Resource Counts', xaxis = list(title = 'Time Step'), yaxis = list(title = 'Quantity'), legend = list(title=list(text='Crop Type'))) ```