library(flexdashboard)
library(tidyverse)
library(sf)
library(lubridate)
library(jsonlite)
library(plotly)
library(hablar)
library(RColorBrewer)
# devtools::install_github("hadley/emo")
library(emo)
library(tmap)
library(rsconnect)
library(ggplot2)
install.packages("tidycensus")
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/tidycensus_1.3.2.tgz'
Content type 'application/x-gzip' length 3254143 bytes (3.1 MB)
==================================================
downloaded 3.1 MB

The downloaded binary packages are in
    /var/folders/3c/_nnr32td5vj918mbvndpd3fw0000gn/T//RtmpFKMIwn/downloaded_packages
library(tidycensus)
install.packages('gganimate')
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/gganimate_1.0.8.tgz'
Content type 'application/x-gzip' length 1294329 bytes (1.2 MB)
==================================================
downloaded 1.2 MB

The downloaded binary packages are in
    /var/folders/3c/_nnr32td5vj918mbvndpd3fw0000gn/T//RtmpFKMIwn/downloaded_packages
library(gganimate)

Attaching package: ‘gganimate’

The following object is masked from ‘package:raster’:

    animate
#install.packages("transformr")
library(transformr)

Attaching package: ‘transformr’

The following object is masked from ‘package:sf’:

    st_normalize

In the following section, I manipulate and map population data provided by the American Community Survey. It is important to note that the data selected is for Wayne County, where the city of Detroit resides. The reasoning for this is twofold: 1. It was easier to download tract level data for the entire county. 2. I believe that mapping that illustrates changes in population of one specific region (in this case the city of Detroit) should include the surrounding area. Perhaps this mapping will find that as people move in or out of Detroit, the rest of Wayne County may have the opposite reaction (i.e., people moving from the city center to the suburbs, etc.)


# Downloading population data from TidyCensus for mapping. Population is one of they key factors looked into for this research project, as it marks the influx/exodus of people in Detroit. I limited my time period to 2010-2021, as I wanted to see changes in the Detroit area in the most recent decade.


pop21 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2021)
pop20 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2020)
pop19 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2019)
pop18 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2018)
pop17 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2017)
pop16 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2016)
pop15 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2015)
pop14 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2014)
pop13 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2013)
pop12 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2012)
pop11 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2011)
pop10 <- get_acs(geography = "tract", variables = "B01003_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2010)

# This data is pulled from the American Community Survey (ACS) and uses the 1-year estimate. This means that this data has a margin of error.

# Tidying my data
stastibble <- function(pop){as_tibble(pop)}
pop21_tibble <- stastibble(pop21)
pop20_tibble <- stastibble(pop20)
pop19_tibble <- stastibble(pop19)
pop18_tibble <- stastibble(pop18)
pop17_tibble <- stastibble(pop17)
pop16_tibble <- stastibble(pop16)
pop15_tibble <- stastibble(pop15)
pop14_tibble <- stastibble(pop14)
pop13_tibble <- stastibble(pop13)
pop12_tibble <- stastibble(pop12)
pop11_tibble <- stastibble(pop11)
pop10_tibble <- stastibble(pop10)

# Joining the data, making one dataframe with all of the years collected (2010 - 2021)

pop_joined <- left_join(pop21_tibble, pop20_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop19_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop18_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop17_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop16_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop15_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop14_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop13_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop12_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop11_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

pop_joined <- left_join(pop_joined, pop10_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')
# Transforming my data into an object with geographical/spatial information (an SF object)
pop_joined <- drop_na(pop_joined)
pop_joined_sf <- st_as_sf(pop_joined, sf_column_name = 'geometry', crs = 4326)
# Renaming columns

colnames(pop_joined_sf)[4] = "estimate21"
colnames(pop_joined_sf)[7] = "estimate20"
colnames(pop_joined_sf)[8] = "estimate19"
colnames(pop_joined_sf)[9] = "estimate18"
colnames(pop_joined_sf)[10] = "estimate17"
colnames(pop_joined_sf)[11] = "estimate16"
colnames(pop_joined_sf)[12] = "estimate15"
colnames(pop_joined_sf)[13] = "estimate14"
colnames(pop_joined_sf)[14] = "estimate13"
colnames(pop_joined_sf)[15] = "estimate12"
colnames(pop_joined_sf)[16] = "estimate11"
colnames(pop_joined_sf)[17] = "estimate10"
str(pop_joined_sf)
# Making a static map first to test out aesthetics

detroit_map_population <- ggplot() + geom_sf(data = pop_joined_sf, color = "black", aes(fill = estimate21)) + theme_light(base_size = 10) + scale_fill_gradient(low = "lightblue1", high = "indianred4")

detroit_map_population
# to utilize the gganimate package, you have to turn you data from wide format to long format
 pop_joined_Sf_long <- pivot_longer(data = pop_joined_sf, cols =c(estimate21, estimate20:estimate10))
# remapping my data that is now in long format
pop_joined_Sf_long %>% group_by(name)
detroit_map_pop_forgif <- ggplot() + geom_sf(data = pop_joined_Sf_long, color = "black", aes(fill = value)) + theme_light(base_size = 10) + scale_fill_gradient(low = "lightblue1", high = "indianred4")
detroit_map_pop_forgif

In the following section, I will map changes in vacancies in Detroit in the 2010s and early 2020s.

detroit_vacancies <- read_csv("detroitvac.characteristics.compiled - Sheet1 (2).csv")
Rows: 11 Columns: 9── Column specification ─────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
dbl (2): Year, For migrant workers
num (7): Total, For rent, Rented, not occupied, For sale only, Sold, not occupied, For seasonal, recr...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
detroit_vacancies$`Rented, not occupied`<- as.integer(detroit_vacancies$`Rented, not occupied`)

detroit_line_graph_vacancies_1 <- ggplot() +  geom_point(data = detroit_vacancies, aes(x = Year, y= `Rented, not occupied`)) + transition_time(Year) + labs(title = "Rented, not Occupied Vacancies in Detroit by Year: {frame_time}")

detroit_line_graph_vacancies_1
detroit_line_graph_vacancies_2 <- ggplot() + geom_point(data = detroit_vacancies, aes(x = Year, y= `Sold, not occupied`)) + transition_time(Year) + labs(title = "Sold, not Occupied Vacancies in Detroit by Year: {frame_time}")

detroit_line_graph_vacancies_2

# Downloading vacancy data for Wayne County from the ACS at the Tract Level

vacancy_tract_21 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2021)
vacancy_tract_20 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2020)
vacancy_tract_19 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2019)
vacancy_tract_18 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2018)
vacancy_tract_17 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2017)
vacancy_tract_16 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2016)
vacancy_tract_15 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2015)
vacancy_tract_14 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2014)
vacancy_tract_13 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2013)
vacancy_tract_12 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2012)
vacancy_tract_11 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2011)
vacancy_tract_10 <- get_acs(geography = "tract", variables = "B25004_001",
                state = "MI", county = "Wayne", geometry = TRUE, year = 2010)
stastibble <- function(vacancy){as_tibble(vacancy)}
vacancy_tract_21_tibble <- stastibble(vacancy_tract_21)
vacancy_tract_20_tibble <- stastibble(vacancy_tract_20)
vacancy_tract_19_tibble <- stastibble(vacancy_tract_19)
vacancy_tract_18_tibble <- stastibble(vacancy_tract_18)
vacancy_tract_17_tibble <- stastibble(vacancy_tract_17)
vacancy_tract_16_tibble <- stastibble(vacancy_tract_16)
vacancy_tract_15_tibble <- stastibble(vacancy_tract_15)
vacancy_tract_14_tibble <- stastibble(vacancy_tract_14)
vacancy_tract_13_tibble <- stastibble(vacancy_tract_13)
vacancy_tract_12_tibble <- stastibble(vacancy_tract_12)
vacancy_tract_11_tibble <- stastibble(vacancy_tract_11)
vacancy_tract_10_tibble <- stastibble(vacancy_tract_10)
vacancy_joined <- left_join(vacancy_tract_21_tibble, vacancy_tract_20_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_19_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_18_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_17_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_16_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_15_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_14_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_13_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_12_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined<- left_join(vacancy_joined, vacancy_tract_11_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')

vacancy_joined <- left_join(vacancy_joined, vacancy_tract_10_tibble %>% dplyr::select(estimate, GEOID), by = 'GEOID')
colnames(vacancy_joined)[4] = "est2021"
colnames(vacancy_joined)[7] = "est2020"
colnames(vacancy_joined)[8] = "est2019"
colnames(vacancy_joined)[9] = "est2018"
colnames(vacancy_joined)[10] = "est2017"
colnames(vacancy_joined)[11] = "est2016"
colnames(vacancy_joined)[12] = "est2015"
colnames(vacancy_joined)[13] = "est2014"
colnames(vacancy_joined)[14] = "est2013"
colnames(vacancy_joined)[15] = "est2012"
colnames(vacancy_joined)[16] = "est2011"
colnames(vacancy_joined)[17] = "est2010"
vacancy_joined_sf <- st_as_sf(vacancy_joined, sf_column_name = 'geometry', crs = 4326)
Warning: st_crs<- : replacing crs does not reproject data; use st_transform for that
vacancy_joined_sf <- drop_na(vacancy_joined_sf)

vacancy_joined_Sf_long <- pivot_longer(data = vacancy_joined_sf, cols =c(est2021, est2020:est2010))

vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2021'] <- '2021'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2020'] <- '2020'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2019'] <- '2019'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2018'] <- '2018'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2017'] <- '2017'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2016'] <- '2016'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2015'] <- '2015'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2014'] <- '2014'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2013'] <- '2013'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2012'] <- '2012'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2011'] <- '2011'
vacancy_joined_Sf_long$name[vacancy_joined_Sf_long$name == 'est2010'] <- '2010'
colnames(vacancy_joined_Sf_long)[6] <- 'year' 
vacancy_joined_Sf_long$year <- as.integer(vacancy_joined_Sf_long$year)

detroit_map_vacancy_gif <- ggplot() + geom_sf(data = vacancy_joined_Sf_long, color = "black", aes(fill = value)) + theme_light(base_size = 10) + scale_fill_gradient(low = "lightyellow1", high = "darkorchid4") + transition_time(year) + labs(title = "Vacancy by Census Tract by Year: {frame_time}")

detroit_map_vacancy_gif
Detroit_sidelots <- read_json("Side_Lots_Sold.geojson")
Detroit_propertysales <- read_csv("property_sales.csv")
Rows: 377839 Columns: 16── Column specification ──────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (10): parcel_number, address, grantor, grantee, liberpage, sale_terms, verified_by, sale_...
dbl   (4): object_id, sale_number, sale_price, sale_trans
lgl   (1): geom
date  (1): sale_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
detroit_property_sales_year <- format(as.Date(Detroit_propertysales$sale_date, format="%Y/%m/%d"),"%Y")
data.frame(detroit_property_sales_year)
detroit_propsales_year_1 <- cbind(detroit_property_sales_year, Detroit_propertysales)
detroit_propsales_year_1

Detroit_propertysales_2011 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2011)
Detroit_propertysales_2012 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2012)
Detroit_propertysales_2013 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2013)
Detroit_propertysales_2014 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2014)
Detroit_propertysales_2015 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2015)
Detroit_propertysales_2016 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2016)
Detroit_propertysales_2017 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2017)
Detroit_propertysales_2018 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2018)
Detroit_propertysales_2019 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2019)
Detroit_propertysales_2020 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2020)
Detroit_propertysales_2021 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2021)
Detroit_propertysales_2022 <- detroit_propsales_year_1 %>% filter(detroit_property_sales_year == 2022)
sum_detroit_propsales_year_1 <- aggregate(x = detroit_propsales_year_1$sale_price,               
          by = list(detroit_propsales_year_1$detroit_property_sales_year),            
          FUN = sum) 
colnames(sum_detroit_propsales_year_1)[1] = 'year'
colnames(sum_detroit_propsales_year_1)[2] = 'price'

sum_detroit_propsales_year_1$year <- as.integer(sum_detroit_propsales_year_1$year)

detroit_line_graph_salesprices <- ggplot()+ geom_point(data = sum_detroit_propsales_year_1, aes(x = year, y= price)) + theme_bw() + transition_time(year) + labs(title = "Real Estate Prices in Detroit by Year: {frame_time}")

detroit_line_graph_salesprices
avg_detroit_propsales_year_1 <- aggregate(x = detroit_propsales_year_1$sale_price,               
          by = list(detroit_propsales_year_1$detroit_property_sales_year),            
          FUN = mean) 

colnames(avg_detroit_propsales_year_1)[1] = 'year'
colnames(avg_detroit_propsales_year_1)[2] = 'price'

avg_detroit_propsales_year_1$year <- as.integer(avg_detroit_propsales_year_1$year)

detroit_line_graph_salesprices_avg <- ggplot()+ geom_point(data = avg_detroit_propsales_year_1, aes(x = year, y= price)) + theme_bw() + transition_time(year) + labs(title = " Average Real Estate Prices in Detroit by Year: {frame_time}")

detroit_line_graph_salesprices_avg
detroitsales_401 <- detroit_propsales_year_1 %>% dplyr::filter(., property_class == 401)

detroitsales_402 <- detroit_propsales_year_1 %>% dplyr::filter(., property_class == 402)
sum_detroit_propsales_year_401 <- aggregate(x = detroitsales_401$sale_price,               
          by = list(detroitsales_401$detroit_property_sales_year),            
          FUN = sum) 
colnames(sum_detroit_propsales_year_401)[1] = 'year'
colnames(sum_detroit_propsales_year_401)[2] = 'price'

sum_detroit_propsales_year_401$year <- as.integer(sum_detroit_propsales_year_401$year)

detroit_line_graph_salesprices_401 <- ggplot()+ geom_point(data = sum_detroit_propsales_year_401, aes(x = year, y= price)) + theme_bw() + transition_time(year) + labs(title = "Real Estate Prices - Residential in Nature and Improved in Detroit by Year: {frame_time}")

detroit_line_graph_salesprices_401
avg_detroit_propsales_year_401 <- aggregate(x = detroitsales_401$sale_price,               
          by = list(detroitsales_401$detroit_property_sales_year),            
          FUN = mean) 
colnames(avg_detroit_propsales_year_401)[1] = 'year'
colnames(avg_detroit_propsales_year_401)[2] = 'price'

avg_detroit_propsales_year_401$year <- as.integer(avg_detroit_propsales_year_401$year)

detroit_line_graph_salesprices_401_avg <- ggplot()+ geom_point(data = avg_detroit_propsales_year_401, aes(x = year, y= price)) + theme_bw() + transition_time(year) + labs(title = " Average Real Estate Prices - Residential in Nature and Improved in Detroit by Year: {frame_time}")

detroit_line_graph_salesprices_401_avg
sum_detroit_propsales_year_402 <- aggregate(x = detroitsales_402$sale_price,               
          by = list(detroitsales_402$detroit_property_sales_year),            
          FUN = sum) 
colnames(sum_detroit_propsales_year_402)[1] = 'year'
colnames(sum_detroit_propsales_year_402)[2] = 'price'

sum_detroit_propsales_year_402$year <- as.integer(sum_detroit_propsales_year_402$year)

detroit_line_graph_salesprices_402 <- ggplot()+ geom_point(data = sum_detroit_propsales_year_402, aes(x = year, y= price), color = "royalblue", size = 4) + theme_bw() + transition_time(year) + labs(title = "Real Estate Prices - Residential and Vacant in Detroit by Year: {frame_time}")

detroit_line_graph_salesprices_402
avg_detroit_propsales_year_402 <- aggregate(x = detroitsales_402$sale_price,               
          by = list(detroitsales_402$detroit_property_sales_year),            
          FUN = mean) 
colnames(avg_detroit_propsales_year_402)[1] = 'year'
colnames(avg_detroit_propsales_year_402)[2] = 'price'

avg_detroit_propsales_year_402$year <- as.integer(avg_detroit_propsales_year_402$year)

detroit_line_graph_salesprices_402_avg <- ggplot()+ geom_point(data = avg_detroit_propsales_year_402, aes(x = year, y= price)) + theme_bw() + transition_time(year) + labs(title = " Average Real Estate Prices - Residential and Vacant in Detroit by Year: {frame_time}")

detroit_line_graph_salesprices_402_avg
residential_demolitions <- read_csv("Completed_Residential_Demolitions.csv")
Rows: 25604 Columns: 21── Column specification ──────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (13): address, parcel_id, contractor_name, funding_source, demolition_date, demo_rfp_group...
dbl  (8): X, Y, price, council_district, street_number, property_longitude, property_latitude,...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
year_demo<- format(as.Date(residential_demolitions$demolition_date, format="%Y/%m/%d"),"%Y")
data.frame(residential_demolitions)
residential_demo_year <- cbind(year_demo, residential_demolitions)
residential_demo_year
residential_demo_year <- st_as_sf(residential_demo_year, coords = c("X", "Y"), crs = 4326)
residential_demo_year$year_demo <- as.integer(residential_demo_year$year_demo)

detroit_map_demo_gif <- ggplot() + geom_sf(data = residential_demo_year, color = "darkgreen", aes(fill = year_demo), size = .05, alpha = .5) + theme_light(base_size = 10) + scale_fill_gradient(low = "lightyellow1", high = "darkorchid4") 

detroit_map_demo_gif

residential_demo_year$year_demo <- as.integer(residential_demo_year$year_demo)

detroit_map_demo_gif <- ggplot() + geom_sf(data = residential_demo_year, color = "darkgreen", aes(fill = year_demo), size = .05, alpha = .5) + theme_light(base_size = 10) + scale_fill_gradient(low = "lightyellow1", high = "darkorchid4") + transition_time(year_demo) + labs(title = "Demolitions by Year: {frame_time}")

detroit_map_demo_gif
anim_save("detroit_map_demo_gif.gif", detroit_map_demo_gif)
anim_save("detroit_map_pop_gif.gif", detroit_map_pop_gif)
anim_save("detroit_line_graph_population.gif", detroit_line_graph_population)
anim_save("detroit_line_graph_vacancies_1.gif", detroit_line_graph_vacancies_1)
anim_save("detroit_line_graph_vacancies_2.gif", detroit_line_graph_vacancies_2)
anim_save("detroit_map_vacancy_gif.gif", detroit_map_vacancy_gif)
anim_save("detroit_line_graph_salesprices.gif", detroit_line_graph_salesprices)
anim_save("detroit_line_graph_salesprices_401.gif", detroit_line_graph_salesprices_401) 
anim_save("detroit_line_graph_salesprices_402.gif", detroit_line_graph_salesprices_402) 
anim_save("detroit_line_graph_salesprices_401_avg.gif", detroit_line_graph_salesprices_401_avg) 
anim_save("detroit_line_graph_salesprices_402_avg.gif", detroit_line_graph_salesprices_402_avg)
anim_save("detroit_line_graph_salesprices_avg.gif", detroit_line_graph_salesprices_avg)
install.packages("gifski")
Error in install.packages : Updating loaded packages
library(gifski)
library(rsconnect)
LS0tCnRpdGxlOiAiVmlzdWFsaXppbmcgVXJiYW4gRGVjYXk6IERldHJvaXQiCnN1YnRpdGxlOiAiUGxhbiA2MTIyIFRlcm0gUHJvamVjdCIKYXV0aG9yOiBUaGVvZG9yYSBDYXRyaW5hCmRhdGU6IE1heSAxMSwgMjAyMwpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmBgYHtyfQoKIyBMb2FkaW5nIGFuZCBJbnN0YWxsaW5nIGFsbCBOZWNlc3NhcnkgUGFja2FnZXMKCmxpYnJhcnkoZmxleGRhc2hib2FyZCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGpzb25saXRlKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShoYWJsYXIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQojIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiaGFkbGV5L2VtbyIpCmxpYnJhcnkoZW1vKQpsaWJyYXJ5KHRtYXApCmxpYnJhcnkocnNjb25uZWN0KQpsaWJyYXJ5KGdncGxvdDIpCmBgYApgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygidGlkeWNlbnN1cyIpCmBgYApgYGB7cn0KbGlicmFyeSh0aWR5Y2Vuc3VzKQppbnN0YWxsLnBhY2thZ2VzKCdnZ2FuaW1hdGUnKQpsaWJyYXJ5KGdnYW5pbWF0ZSkKYGBgCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygidHJhbnNmb3JtciIpCmxpYnJhcnkodHJhbnNmb3JtcikKYGBgCkluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbiwgSSBtYW5pcHVsYXRlIGFuZCBtYXAgcG9wdWxhdGlvbiBkYXRhIHByb3ZpZGVkIGJ5IHRoZSBBbWVyaWNhbiBDb21tdW5pdHkgU3VydmV5LiBJdCBpcyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHRoZSBkYXRhIHNlbGVjdGVkIGlzIGZvciBXYXluZSBDb3VudHksIHdoZXJlIHRoZSBjaXR5IG9mIERldHJvaXQgcmVzaWRlcy4gVGhlIHJlYXNvbmluZyBmb3IgdGhpcyBpcyB0d29mb2xkOgogIDEuIEl0IHdhcyBlYXNpZXIgdG8gZG93bmxvYWQgdHJhY3QgbGV2ZWwgZGF0YSBmb3IgdGhlIGVudGlyZSBjb3VudHkuCiAgMi4gSSBiZWxpZXZlIHRoYXQgbWFwcGluZyB0aGF0IGlsbHVzdHJhdGVzIGNoYW5nZXMgaW4gcG9wdWxhdGlvbiBvZiBvbmUgc3BlY2lmaWMgcmVnaW9uIChpbiB0aGlzIGNhc2UgdGhlIGNpdHkgb2YgRGV0cm9pdCkgc2hvdWxkIGluY2x1ZGUgdGhlIHN1cnJvdW5kaW5nIGFyZWEuIFBlcmhhcHMgdGhpcyBtYXBwaW5nIHdpbGwgZmluZCB0aGF0IGFzIHBlb3BsZSBtb3ZlIGluIG9yIG91dCBvZiBEZXRyb2l0LCB0aGUgcmVzdCBvZiBXYXluZSBDb3VudHkgbWF5IGhhdmUgdGhlIG9wcG9zaXRlIHJlYWN0aW9uIChpLmUuLCBwZW9wbGUgbW92aW5nIGZyb20gdGhlIGNpdHkgY2VudGVyIHRvIHRoZSBzdWJ1cmJzLCBldGMuKQoKYGBge3J9CgojIERvd25sb2FkaW5nIHBvcHVsYXRpb24gZGF0YSBmcm9tIFRpZHlDZW5zdXMgZm9yIG1hcHBpbmcuIFBvcHVsYXRpb24gaXMgb25lIG9mIHRoZXkga2V5IGZhY3RvcnMgbG9va2VkIGludG8gZm9yIHRoaXMgcmVzZWFyY2ggcHJvamVjdCwgYXMgaXQgbWFya3MgdGhlIGluZmx1eC9leG9kdXMgb2YgcGVvcGxlIGluIERldHJvaXQuIEkgbGltaXRlZCBteSB0aW1lIHBlcmlvZCB0byAyMDEwLTIwMjEsIGFzIEkgd2FudGVkIHRvIHNlZSBjaGFuZ2VzIGluIHRoZSBEZXRyb2l0IGFyZWEgaW4gdGhlIG1vc3QgcmVjZW50IGRlY2FkZS4KCgpwb3AyMSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMDEwMDNfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAyMSkKcG9wMjAgPC0gZ2V0X2FjcyhnZW9ncmFwaHkgPSAidHJhY3QiLCB2YXJpYWJsZXMgPSAiQjAxMDAzXzAwMSIsCiAgICAgICAgICAgICAgICBzdGF0ZSA9ICJNSSIsIGNvdW50eSA9ICJXYXluZSIsIGdlb21ldHJ5ID0gVFJVRSwgeWVhciA9IDIwMjApCnBvcDE5IDwtIGdldF9hY3MoZ2VvZ3JhcGh5ID0gInRyYWN0IiwgdmFyaWFibGVzID0gIkIwMTAwM18wMDEiLAogICAgICAgICAgICAgICAgc3RhdGUgPSAiTUkiLCBjb3VudHkgPSAiV2F5bmUiLCBnZW9tZXRyeSA9IFRSVUUsIHllYXIgPSAyMDE5KQpwb3AxOCA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMDEwMDNfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxOCkKcG9wMTcgPC0gZ2V0X2FjcyhnZW9ncmFwaHkgPSAidHJhY3QiLCB2YXJpYWJsZXMgPSAiQjAxMDAzXzAwMSIsCiAgICAgICAgICAgICAgICBzdGF0ZSA9ICJNSSIsIGNvdW50eSA9ICJXYXluZSIsIGdlb21ldHJ5ID0gVFJVRSwgeWVhciA9IDIwMTcpCnBvcDE2IDwtIGdldF9hY3MoZ2VvZ3JhcGh5ID0gInRyYWN0IiwgdmFyaWFibGVzID0gIkIwMTAwM18wMDEiLAogICAgICAgICAgICAgICAgc3RhdGUgPSAiTUkiLCBjb3VudHkgPSAiV2F5bmUiLCBnZW9tZXRyeSA9IFRSVUUsIHllYXIgPSAyMDE2KQpwb3AxNSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMDEwMDNfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxNSkKcG9wMTQgPC0gZ2V0X2FjcyhnZW9ncmFwaHkgPSAidHJhY3QiLCB2YXJpYWJsZXMgPSAiQjAxMDAzXzAwMSIsCiAgICAgICAgICAgICAgICBzdGF0ZSA9ICJNSSIsIGNvdW50eSA9ICJXYXluZSIsIGdlb21ldHJ5ID0gVFJVRSwgeWVhciA9IDIwMTQpCnBvcDEzIDwtIGdldF9hY3MoZ2VvZ3JhcGh5ID0gInRyYWN0IiwgdmFyaWFibGVzID0gIkIwMTAwM18wMDEiLAogICAgICAgICAgICAgICAgc3RhdGUgPSAiTUkiLCBjb3VudHkgPSAiV2F5bmUiLCBnZW9tZXRyeSA9IFRSVUUsIHllYXIgPSAyMDEzKQpwb3AxMiA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMDEwMDNfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxMikKcG9wMTEgPC0gZ2V0X2FjcyhnZW9ncmFwaHkgPSAidHJhY3QiLCB2YXJpYWJsZXMgPSAiQjAxMDAzXzAwMSIsCiAgICAgICAgICAgICAgICBzdGF0ZSA9ICJNSSIsIGNvdW50eSA9ICJXYXluZSIsIGdlb21ldHJ5ID0gVFJVRSwgeWVhciA9IDIwMTEpCnBvcDEwIDwtIGdldF9hY3MoZ2VvZ3JhcGh5ID0gInRyYWN0IiwgdmFyaWFibGVzID0gIkIwMTAwM18wMDEiLAogICAgICAgICAgICAgICAgc3RhdGUgPSAiTUkiLCBjb3VudHkgPSAiV2F5bmUiLCBnZW9tZXRyeSA9IFRSVUUsIHllYXIgPSAyMDEwKQoKIyBUaGlzIGRhdGEgaXMgcHVsbGVkIGZyb20gdGhlIEFtZXJpY2FuIENvbW11bml0eSBTdXJ2ZXkgKEFDUykgYW5kIHVzZXMgdGhlIDEteWVhciBlc3RpbWF0ZS4gVGhpcyBtZWFucyB0aGF0IHRoaXMgZGF0YSBoYXMgYSBtYXJnaW4gb2YgZXJyb3IuCgpgYGAKCgpgYGB7cn0KCiMgVGlkeWluZyBteSBkYXRhCnN0YXN0aWJibGUgPC0gZnVuY3Rpb24ocG9wKXthc190aWJibGUocG9wKX0KcG9wMjFfdGliYmxlIDwtIHN0YXN0aWJibGUocG9wMjEpCnBvcDIwX3RpYmJsZSA8LSBzdGFzdGliYmxlKHBvcDIwKQpwb3AxOV90aWJibGUgPC0gc3Rhc3RpYmJsZShwb3AxOSkKcG9wMThfdGliYmxlIDwtIHN0YXN0aWJibGUocG9wMTgpCnBvcDE3X3RpYmJsZSA8LSBzdGFzdGliYmxlKHBvcDE3KQpwb3AxNl90aWJibGUgPC0gc3Rhc3RpYmJsZShwb3AxNikKcG9wMTVfdGliYmxlIDwtIHN0YXN0aWJibGUocG9wMTUpCnBvcDE0X3RpYmJsZSA8LSBzdGFzdGliYmxlKHBvcDE0KQpwb3AxM190aWJibGUgPC0gc3Rhc3RpYmJsZShwb3AxMykKcG9wMTJfdGliYmxlIDwtIHN0YXN0aWJibGUocG9wMTIpCnBvcDExX3RpYmJsZSA8LSBzdGFzdGliYmxlKHBvcDExKQpwb3AxMF90aWJibGUgPC0gc3Rhc3RpYmJsZShwb3AxMCkKYGBgCgpgYGB7cn0KCiMgSm9pbmluZyB0aGUgZGF0YSwgbWFraW5nIG9uZSBkYXRhZnJhbWUgd2l0aCBhbGwgb2YgdGhlIHllYXJzIGNvbGxlY3RlZCAoMjAxMCAtIDIwMjEpCgpwb3Bfam9pbmVkIDwtIGxlZnRfam9pbihwb3AyMV90aWJibGUsIHBvcDIwX3RpYmJsZSAlPiUgZHBseXI6OnNlbGVjdChlc3RpbWF0ZSwgR0VPSUQpLCBieSA9ICdHRU9JRCcpCgpwb3Bfam9pbmVkIDwtIGxlZnRfam9pbihwb3Bfam9pbmVkLCBwb3AxOV90aWJibGUgJT4lIGRwbHlyOjpzZWxlY3QoZXN0aW1hdGUsIEdFT0lEKSwgYnkgPSAnR0VPSUQnKQoKcG9wX2pvaW5lZCA8LSBsZWZ0X2pvaW4ocG9wX2pvaW5lZCwgcG9wMThfdGliYmxlICU+JSBkcGx5cjo6c2VsZWN0KGVzdGltYXRlLCBHRU9JRCksIGJ5ID0gJ0dFT0lEJykKCnBvcF9qb2luZWQgPC0gbGVmdF9qb2luKHBvcF9qb2luZWQsIHBvcDE3X3RpYmJsZSAlPiUgZHBseXI6OnNlbGVjdChlc3RpbWF0ZSwgR0VPSUQpLCBieSA9ICdHRU9JRCcpCgpwb3Bfam9pbmVkIDwtIGxlZnRfam9pbihwb3Bfam9pbmVkLCBwb3AxNl90aWJibGUgJT4lIGRwbHlyOjpzZWxlY3QoZXN0aW1hdGUsIEdFT0lEKSwgYnkgPSAnR0VPSUQnKQoKcG9wX2pvaW5lZCA8LSBsZWZ0X2pvaW4ocG9wX2pvaW5lZCwgcG9wMTVfdGliYmxlICU+JSBkcGx5cjo6c2VsZWN0KGVzdGltYXRlLCBHRU9JRCksIGJ5ID0gJ0dFT0lEJykKCnBvcF9qb2luZWQgPC0gbGVmdF9qb2luKHBvcF9qb2luZWQsIHBvcDE0X3RpYmJsZSAlPiUgZHBseXI6OnNlbGVjdChlc3RpbWF0ZSwgR0VPSUQpLCBieSA9ICdHRU9JRCcpCgpwb3Bfam9pbmVkIDwtIGxlZnRfam9pbihwb3Bfam9pbmVkLCBwb3AxM190aWJibGUgJT4lIGRwbHlyOjpzZWxlY3QoZXN0aW1hdGUsIEdFT0lEKSwgYnkgPSAnR0VPSUQnKQoKcG9wX2pvaW5lZCA8LSBsZWZ0X2pvaW4ocG9wX2pvaW5lZCwgcG9wMTJfdGliYmxlICU+JSBkcGx5cjo6c2VsZWN0KGVzdGltYXRlLCBHRU9JRCksIGJ5ID0gJ0dFT0lEJykKCnBvcF9qb2luZWQgPC0gbGVmdF9qb2luKHBvcF9qb2luZWQsIHBvcDExX3RpYmJsZSAlPiUgZHBseXI6OnNlbGVjdChlc3RpbWF0ZSwgR0VPSUQpLCBieSA9ICdHRU9JRCcpCgpwb3Bfam9pbmVkIDwtIGxlZnRfam9pbihwb3Bfam9pbmVkLCBwb3AxMF90aWJibGUgJT4lIGRwbHlyOjpzZWxlY3QoZXN0aW1hdGUsIEdFT0lEKSwgYnkgPSAnR0VPSUQnKQoKYGBgCgoKYGBge3J9CiMgVHJhbnNmb3JtaW5nIG15IGRhdGEgaW50byBhbiBvYmplY3Qgd2l0aCBnZW9ncmFwaGljYWwvc3BhdGlhbCBpbmZvcm1hdGlvbiAoYW4gU0Ygb2JqZWN0KQpwb3Bfam9pbmVkIDwtIGRyb3BfbmEocG9wX2pvaW5lZCkKcG9wX2pvaW5lZF9zZiA8LSBzdF9hc19zZihwb3Bfam9pbmVkLCBzZl9jb2x1bW5fbmFtZSA9ICdnZW9tZXRyeScsIGNycyA9IDQzMjYpCgpgYGAKCmBgYHtyfQojIFJlbmFtaW5nIGNvbHVtbnMKCmNvbG5hbWVzKHBvcF9qb2luZWRfc2YpWzRdID0gImVzdGltYXRlMjEiCmNvbG5hbWVzKHBvcF9qb2luZWRfc2YpWzddID0gImVzdGltYXRlMjAiCmNvbG5hbWVzKHBvcF9qb2luZWRfc2YpWzhdID0gImVzdGltYXRlMTkiCmNvbG5hbWVzKHBvcF9qb2luZWRfc2YpWzldID0gImVzdGltYXRlMTgiCmNvbG5hbWVzKHBvcF9qb2luZWRfc2YpWzEwXSA9ICJlc3RpbWF0ZTE3Igpjb2xuYW1lcyhwb3Bfam9pbmVkX3NmKVsxMV0gPSAiZXN0aW1hdGUxNiIKY29sbmFtZXMocG9wX2pvaW5lZF9zZilbMTJdID0gImVzdGltYXRlMTUiCmNvbG5hbWVzKHBvcF9qb2luZWRfc2YpWzEzXSA9ICJlc3RpbWF0ZTE0Igpjb2xuYW1lcyhwb3Bfam9pbmVkX3NmKVsxNF0gPSAiZXN0aW1hdGUxMyIKY29sbmFtZXMocG9wX2pvaW5lZF9zZilbMTVdID0gImVzdGltYXRlMTIiCmNvbG5hbWVzKHBvcF9qb2luZWRfc2YpWzE2XSA9ICJlc3RpbWF0ZTExIgpjb2xuYW1lcyhwb3Bfam9pbmVkX3NmKVsxN10gPSAiZXN0aW1hdGUxMCIKCgpgYGAKCmBgYHtyfQpzdHIocG9wX2pvaW5lZF9zZikKYGBgCgoKYGBge3J9CiMgTWFraW5nIGEgc3RhdGljIG1hcCBmaXJzdCB0byB0ZXN0IG91dCBhZXN0aGV0aWNzCgpkZXRyb2l0X21hcF9wb3B1bGF0aW9uIDwtIGdncGxvdCgpICsgZ2VvbV9zZihkYXRhID0gcG9wX2pvaW5lZF9zZiwgY29sb3IgPSAiYmxhY2siLCBhZXMoZmlsbCA9IGVzdGltYXRlMjEpKSArIHRoZW1lX2xpZ2h0KGJhc2Vfc2l6ZSA9IDEwKSArIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImxpZ2h0Ymx1ZTEiLCBoaWdoID0gImluZGlhbnJlZDQiKQoKZGV0cm9pdF9tYXBfcG9wdWxhdGlvbgpgYGAKCmBgYHtyfQojIHRvIHV0aWxpemUgdGhlIGdnYW5pbWF0ZSBwYWNrYWdlLCB5b3UgaGF2ZSB0byB0dXJuIHlvdSBkYXRhIGZyb20gd2lkZSBmb3JtYXQgdG8gbG9uZyBmb3JtYXQKIHBvcF9qb2luZWRfU2ZfbG9uZyA8LSBwaXZvdF9sb25nZXIoZGF0YSA9IHBvcF9qb2luZWRfc2YsIGNvbHMgPWMoZXN0aW1hdGUyMSwgZXN0aW1hdGUyMDplc3RpbWF0ZTEwKSkKYGBgCgpgYGB7cn0KIyByZW1hcHBpbmcgbXkgZGF0YSB0aGF0IGlzIG5vdyBpbiBsb25nIGZvcm1hdApwb3Bfam9pbmVkX1NmX2xvbmcgJT4lIGdyb3VwX2J5KG5hbWUpCmRldHJvaXRfbWFwX3BvcF9mb3JnaWYgPC0gZ2dwbG90KCkgKyBnZW9tX3NmKGRhdGEgPSBwb3Bfam9pbmVkX1NmX2xvbmcsIGNvbG9yID0gImJsYWNrIiwgYWVzKGZpbGwgPSB2YWx1ZSkpICsgdGhlbWVfbGlnaHQoYmFzZV9zaXplID0gMTApICsgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAibGlnaHRibHVlMSIsIGhpZ2ggPSAiaW5kaWFucmVkNCIpCmRldHJvaXRfbWFwX3BvcF9mb3JnaWYKYGBgCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CgojIFJlbmFtaW5nIGNvbHVtbnMKCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTIxJ10gPC0gJzIwMjEnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTIwJ10gPC0gJzIwMjAnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTE5J10gPC0gJzIwMTknCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTE4J10gPC0gJzIwMTgnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTE3J10gPC0gJzIwMTcnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTE2J10gPC0gJzIwMTYnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTE1J10gPC0gJzIwMTUnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTE0J10gPC0gJzIwMTQnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTEzJ10gPC0gJzIwMTMnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTEyJ10gPC0gJzIwMTInCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTExJ10gPC0gJzIwMTEnCnBvcF9qb2luZWRfU2ZfbG9uZyRuYW1lW3BvcF9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3RpbWF0ZTEwJ10gPC0gJzIwMTAnCgojIFRyYW5zZm9ybWluZyB0aGUgeWVhciBjb2x1bW4gZnJvbSBjaGFyYWN0ZXIgdmVjdG9ycyB0byBpbnRlZ2VycwoKY29sbmFtZXMocG9wX2pvaW5lZF9TZl9sb25nKVs2XSA8LSAneWVhcicKcG9wX2pvaW5lZF9TZl9sb25nJHllYXIgPC0gYXMuaW50ZWdlcihwb3Bfam9pbmVkX1NmX2xvbmckeWVhcikKYGBgCgoKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQoKIyBDcmVhdGluZyB0aGUgZ2lmIG9mIHRoZSBwb3B1bGF0aW9uIG1hcCB1c2luZyBnZ2FuaW1hdGUgcGFja2FnZQoKCmRldHJvaXRfbWFwX3BvcF9naWYgPC0gZ2dwbG90KCkgKyBnZW9tX3NmKGRhdGEgPSBwb3Bfam9pbmVkX1NmX2xvbmcsIGNvbG9yID0gImJsYWNrIiwgYWVzKGZpbGwgPSB2YWx1ZSkpICsgdGhlbWVfbGlnaHQoYmFzZV9zaXplID0gMTApICsgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAibGlnaHRibHVlMSIsIGhpZ2ggPSAiaW5kaWFucmVkNCIpICsgdHJhbnNpdGlvbl90aW1lKHllYXIpICsgbGFicyh0aXRsZSA9ICJQb3B1bGF0aW9uIGJ5IENlbnN1cyBUcmFjdCBieSBZZWFyOiB7ZnJhbWVfdGltZX0iKQoKZGV0cm9pdF9tYXBfcG9wX2dpZgpgYGAKCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CgojIE1ha2luZyBhIGdyYXBoIHRoYXQgc2hvd3MgcG9wdWxhdGlvbiBmbHVjdHVhdGlvbiBvdmVyIHRpbWUuIFdoaWxlIHRoIGVtYXAgZ2lmIGlzIGNvcnJlY3QgYW5kIGZ1bmN0aW9uYWwsIHRoZSBjaGFuZ2UgaW4gcG9wdWxhdGlvbiBpcyB0b28gbGltaXRlZCB0byBhY2N1cmF0ZWx5IGFzc2VzcyBjaGFuZ2UuIEl0IGlzIHN1cHBsZW1lbnRlZCB3aXRoIHRoaXMgZ2lmIHRvIHByb3ZpZGUgYSBiZXR0ZXIgdmlzdWFsaXphdGlvbiBvZiBwb3B1bGF0aW9uIGNoYW5nZS4gCgpzdW1fcG9wX2pvaW5lZF9TZl9sb25nIDwtIGFnZ3JlZ2F0ZSh4ID0gcG9wX2pvaW5lZF9TZl9sb25nJHZhbHVlLCAgICAgICAgICAgICAgIAogICAgICAgICAgYnkgPSBsaXN0KHBvcF9qb2luZWRfU2ZfbG9uZyR5ZWFyKSwgICAgICAgICAgICAKICAgICAgICAgIEZVTiA9IHN1bSkgCgpjb2xuYW1lcyhzdW1fcG9wX2pvaW5lZF9TZl9sb25nKVsxXSA9ICd5ZWFyJwpjb2xuYW1lcyhzdW1fcG9wX2pvaW5lZF9TZl9sb25nKVsyXSA9ICd2YWx1ZScKCmRldHJvaXRfbGluZV9ncmFwaF9wb3B1bGF0aW9uIDwtIGdncGxvdCgpKyBnZW9tX3BvaW50KGRhdGEgPSBzdW1fcG9wX2pvaW5lZF9TZl9sb25nLCBhZXMoeCA9IHllYXIsIHk9IHZhbHVlKSkgKyB0cmFuc2l0aW9uX3RpbWUoeWVhcikgKyBsYWJzKHRpdGxlID0gIlBvcHVsYXRpb24gVG90YWwgaW4gRGV0cm9pdCBieSBZZWFyOiB7ZnJhbWVfdGltZX0iKQoKZGV0cm9pdF9saW5lX2dyYXBoX3BvcHVsYXRpb24KCmBgYAoKSW4gdGhlIGZvbGxvd2luZyBzZWN0aW9uLCBJIHdpbGwgbWFwIGNoYW5nZXMgaW4gdmFjYW5jaWVzIGluIERldHJvaXQgaW4gdGhlIDIwMTBzIGFuZCBlYXJseSAyMDIwcy4KCmBgYHtyfQojIERvd25sb2FkaW5nIHZhY2FuY3kgZGF0YSwgdGhpcyBkYXRhIGlzIGFsc28gdGFrZW4gZnJvbSB0aGUgQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleSwgYnV0IGhhcyBiZWVuIGVkaXRlZC90aWRpZWQgb3V0c2lkZSBvZiBSIHN0dWRpby4gCgojIFZhY2FuY3kgRGF0YSAtIDEgWWVhciBFc3RpbWF0ZXMgZnJvbSB0aGUgQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleQoKZGV0cm9pdF92YWNhbmNpZXMgPC0gcmVhZF9jc3YoImRldHJvaXR2YWMuY2hhcmFjdGVyaXN0aWNzLmNvbXBpbGVkIC0gU2hlZXQxICgyKS5jc3YiKQpgYGAKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQoKIyBNYWtpbmcgdGhlIEdJRiEKCmRldHJvaXRfdmFjYW5jaWVzJFllYXIgPC0gYXMuaW50ZWdlcihkZXRyb2l0X3ZhY2FuY2llcyRZZWFyKQoKZGV0cm9pdF9saW5lX2dyYXBoX3ZhY2FuY2llcyA8LSBnZ3Bsb3QoKSsgZ2VvbV9wb2ludChkYXRhID0gZGV0cm9pdF92YWNhbmNpZXMsIGFlcyh4ID0gWWVhciwgeT0gVG90YWwpKSArIHRyYW5zaXRpb25fdGltZShZZWFyKSArIGxhYnModGl0bGUgPSAiVG90YWwgVmFjYW5jaWVzIGluIERldHJvaXQgYnkgWWVhcjoge2ZyYW1lX3RpbWV9IikKCmRldHJvaXRfbGluZV9ncmFwaF92YWNhbmNpZXMKYGBgCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CgojIEZpbHRlcmluZyB0byBvbmx5ICdyZW50ZWQgbm90IG9jY3VwaWVkJyB2YWNhbmNpZXMgaW4gdGhlIERldHJvaXQgYXJlYQoKZGV0cm9pdF92YWNhbmNpZXMkYFJlbnRlZCwgbm90IG9jY3VwaWVkYDwtIGFzLmludGVnZXIoZGV0cm9pdF92YWNhbmNpZXMkYFJlbnRlZCwgbm90IG9jY3VwaWVkYCkKCmRldHJvaXRfbGluZV9ncmFwaF92YWNhbmNpZXNfMSA8LSBnZ3Bsb3QoKSArICBnZW9tX3BvaW50KGRhdGEgPSBkZXRyb2l0X3ZhY2FuY2llcywgYWVzKHggPSBZZWFyLCB5PSBgUmVudGVkLCBub3Qgb2NjdXBpZWRgKSkgKyB0cmFuc2l0aW9uX3RpbWUoWWVhcikgKyBsYWJzKHRpdGxlID0gIlJlbnRlZCwgbm90IE9jY3VwaWVkIFZhY2FuY2llcyBpbiBEZXRyb2l0IGJ5IFllYXI6IHtmcmFtZV90aW1lfSIpCgpkZXRyb2l0X2xpbmVfZ3JhcGhfdmFjYW5jaWVzXzEKYGBgCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CiMgRmlsdGVyaW5nIHRvIG9ubHkgJ3NvbGQsIG5vdCBvY2N1cGllZCcgdmFjYW5jaWVzIGluIHRoZSBEZXRyb2l0IGFyZWEKCmRldHJvaXRfbGluZV9ncmFwaF92YWNhbmNpZXNfMiA8LSBnZ3Bsb3QoKSArIGdlb21fcG9pbnQoZGF0YSA9IGRldHJvaXRfdmFjYW5jaWVzLCBhZXMoeCA9IFllYXIsIHk9IGBTb2xkLCBub3Qgb2NjdXBpZWRgKSkgKyB0cmFuc2l0aW9uX3RpbWUoWWVhcikgKyBsYWJzKHRpdGxlID0gIlNvbGQsIG5vdCBPY2N1cGllZCBWYWNhbmNpZXMgaW4gRGV0cm9pdCBieSBZZWFyOiB7ZnJhbWVfdGltZX0iKQoKZGV0cm9pdF9saW5lX2dyYXBoX3ZhY2FuY2llc18yCmBgYAoKCgpgYGB7cn0KCiMgRG93bmxvYWRpbmcgdmFjYW5jeSBkYXRhIGZvciBXYXluZSBDb3VudHkgZnJvbSB0aGUgQUNTIGF0IHRoZSBUcmFjdCBMZXZlbAoKdmFjYW5jeV90cmFjdF8yMSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAyMSkKdmFjYW5jeV90cmFjdF8yMCA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAyMCkKdmFjYW5jeV90cmFjdF8xOSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxOSkKdmFjYW5jeV90cmFjdF8xOCA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxOCkKdmFjYW5jeV90cmFjdF8xNyA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxNykKdmFjYW5jeV90cmFjdF8xNiA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxNikKdmFjYW5jeV90cmFjdF8xNSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxNSkKdmFjYW5jeV90cmFjdF8xNCA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxNCkKdmFjYW5jeV90cmFjdF8xMyA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxMykKdmFjYW5jeV90cmFjdF8xMiA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxMikKdmFjYW5jeV90cmFjdF8xMSA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxMSkKdmFjYW5jeV90cmFjdF8xMCA8LSBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIHZhcmlhYmxlcyA9ICJCMjUwMDRfMDAxIiwKICAgICAgICAgICAgICAgIHN0YXRlID0gIk1JIiwgY291bnR5ID0gIldheW5lIiwgZ2VvbWV0cnkgPSBUUlVFLCB5ZWFyID0gMjAxMCkKYGBgCgoKCmBgYHtyfQojIFRpZHlpbmcgdGhlIHZhY2FuY3kgZGF0YQoKc3Rhc3RpYmJsZSA8LSBmdW5jdGlvbih2YWNhbmN5KXthc190aWJibGUodmFjYW5jeSl9CnZhY2FuY3lfdHJhY3RfMjFfdGliYmxlIDwtIHN0YXN0aWJibGUodmFjYW5jeV90cmFjdF8yMSkKdmFjYW5jeV90cmFjdF8yMF90aWJibGUgPC0gc3Rhc3RpYmJsZSh2YWNhbmN5X3RyYWN0XzIwKQp2YWNhbmN5X3RyYWN0XzE5X3RpYmJsZSA8LSBzdGFzdGliYmxlKHZhY2FuY3lfdHJhY3RfMTkpCnZhY2FuY3lfdHJhY3RfMThfdGliYmxlIDwtIHN0YXN0aWJibGUodmFjYW5jeV90cmFjdF8xOCkKdmFjYW5jeV90cmFjdF8xN190aWJibGUgPC0gc3Rhc3RpYmJsZSh2YWNhbmN5X3RyYWN0XzE3KQp2YWNhbmN5X3RyYWN0XzE2X3RpYmJsZSA8LSBzdGFzdGliYmxlKHZhY2FuY3lfdHJhY3RfMTYpCnZhY2FuY3lfdHJhY3RfMTVfdGliYmxlIDwtIHN0YXN0aWJibGUodmFjYW5jeV90cmFjdF8xNSkKdmFjYW5jeV90cmFjdF8xNF90aWJibGUgPC0gc3Rhc3RpYmJsZSh2YWNhbmN5X3RyYWN0XzE0KQp2YWNhbmN5X3RyYWN0XzEzX3RpYmJsZSA8LSBzdGFzdGliYmxlKHZhY2FuY3lfdHJhY3RfMTMpCnZhY2FuY3lfdHJhY3RfMTJfdGliYmxlIDwtIHN0YXN0aWJibGUodmFjYW5jeV90cmFjdF8xMikKdmFjYW5jeV90cmFjdF8xMV90aWJibGUgPC0gc3Rhc3RpYmJsZSh2YWNhbmN5X3RyYWN0XzExKQp2YWNhbmN5X3RyYWN0XzEwX3RpYmJsZSA8LSBzdGFzdGliYmxlKHZhY2FuY3lfdHJhY3RfMTApCmBgYAoKYGBge3J9CgojIEpvaW5pbmcgdmFjYW5jeSBkYXRhIHRvIG1ha2UgYSBjb21waWxlZCBkYXRhIGZyYW1lIHRoYXQgaGFzIGFsbCB5ZWFycy4KdmFjYW5jeV9qb2luZWQgPC0gbGVmdF9qb2luKHZhY2FuY3lfdHJhY3RfMjFfdGliYmxlLCB2YWNhbmN5X3RyYWN0XzIwX3RpYmJsZSAlPiUgZHBseXI6OnNlbGVjdChlc3RpbWF0ZSwgR0VPSUQpLCBieSA9ICdHRU9JRCcpCgp2YWNhbmN5X2pvaW5lZCA8LSBsZWZ0X2pvaW4odmFjYW5jeV9qb2luZWQsIHZhY2FuY3lfdHJhY3RfMTlfdGliYmxlICU+JSBkcGx5cjo6c2VsZWN0KGVzdGltYXRlLCBHRU9JRCksIGJ5ID0gJ0dFT0lEJykKCnZhY2FuY3lfam9pbmVkIDwtIGxlZnRfam9pbih2YWNhbmN5X2pvaW5lZCwgdmFjYW5jeV90cmFjdF8xOF90aWJibGUgJT4lIGRwbHlyOjpzZWxlY3QoZXN0aW1hdGUsIEdFT0lEKSwgYnkgPSAnR0VPSUQnKQoKdmFjYW5jeV9qb2luZWQgPC0gbGVmdF9qb2luKHZhY2FuY3lfam9pbmVkLCB2YWNhbmN5X3RyYWN0XzE3X3RpYmJsZSAlPiUgZHBseXI6OnNlbGVjdChlc3RpbWF0ZSwgR0VPSUQpLCBieSA9ICdHRU9JRCcpCgp2YWNhbmN5X2pvaW5lZCA8LSBsZWZ0X2pvaW4odmFjYW5jeV9qb2luZWQsIHZhY2FuY3lfdHJhY3RfMTZfdGliYmxlICU+JSBkcGx5cjo6c2VsZWN0KGVzdGltYXRlLCBHRU9JRCksIGJ5ID0gJ0dFT0lEJykKCnZhY2FuY3lfam9pbmVkIDwtIGxlZnRfam9pbih2YWNhbmN5X2pvaW5lZCwgdmFjYW5jeV90cmFjdF8xNV90aWJibGUgJT4lIGRwbHlyOjpzZWxlY3QoZXN0aW1hdGUsIEdFT0lEKSwgYnkgPSAnR0VPSUQnKQoKdmFjYW5jeV9qb2luZWQgPC0gbGVmdF9qb2luKHZhY2FuY3lfam9pbmVkLCB2YWNhbmN5X3RyYWN0XzE0X3RpYmJsZSAlPiUgZHBseXI6OnNlbGVjdChlc3RpbWF0ZSwgR0VPSUQpLCBieSA9ICdHRU9JRCcpCgp2YWNhbmN5X2pvaW5lZCA8LSBsZWZ0X2pvaW4odmFjYW5jeV9qb2luZWQsIHZhY2FuY3lfdHJhY3RfMTNfdGliYmxlICU+JSBkcGx5cjo6c2VsZWN0KGVzdGltYXRlLCBHRU9JRCksIGJ5ID0gJ0dFT0lEJykKCnZhY2FuY3lfam9pbmVkIDwtIGxlZnRfam9pbih2YWNhbmN5X2pvaW5lZCwgdmFjYW5jeV90cmFjdF8xMl90aWJibGUgJT4lIGRwbHlyOjpzZWxlY3QoZXN0aW1hdGUsIEdFT0lEKSwgYnkgPSAnR0VPSUQnKQoKdmFjYW5jeV9qb2luZWQ8LSBsZWZ0X2pvaW4odmFjYW5jeV9qb2luZWQsIHZhY2FuY3lfdHJhY3RfMTFfdGliYmxlICU+JSBkcGx5cjo6c2VsZWN0KGVzdGltYXRlLCBHRU9JRCksIGJ5ID0gJ0dFT0lEJykKCnZhY2FuY3lfam9pbmVkIDwtIGxlZnRfam9pbih2YWNhbmN5X2pvaW5lZCwgdmFjYW5jeV90cmFjdF8xMF90aWJibGUgJT4lIGRwbHlyOjpzZWxlY3QoZXN0aW1hdGUsIEdFT0lEKSwgYnkgPSAnR0VPSUQnKQpgYGAKCmBgYHtyfQpjb2xuYW1lcyh2YWNhbmN5X2pvaW5lZClbNF0gPSAiZXN0MjAyMSIKY29sbmFtZXModmFjYW5jeV9qb2luZWQpWzddID0gImVzdDIwMjAiCmNvbG5hbWVzKHZhY2FuY3lfam9pbmVkKVs4XSA9ICJlc3QyMDE5Igpjb2xuYW1lcyh2YWNhbmN5X2pvaW5lZClbOV0gPSAiZXN0MjAxOCIKY29sbmFtZXModmFjYW5jeV9qb2luZWQpWzEwXSA9ICJlc3QyMDE3Igpjb2xuYW1lcyh2YWNhbmN5X2pvaW5lZClbMTFdID0gImVzdDIwMTYiCmNvbG5hbWVzKHZhY2FuY3lfam9pbmVkKVsxMl0gPSAiZXN0MjAxNSIKY29sbmFtZXModmFjYW5jeV9qb2luZWQpWzEzXSA9ICJlc3QyMDE0Igpjb2xuYW1lcyh2YWNhbmN5X2pvaW5lZClbMTRdID0gImVzdDIwMTMiCmNvbG5hbWVzKHZhY2FuY3lfam9pbmVkKVsxNV0gPSAiZXN0MjAxMiIKY29sbmFtZXModmFjYW5jeV9qb2luZWQpWzE2XSA9ICJlc3QyMDExIgpjb2xuYW1lcyh2YWNhbmN5X2pvaW5lZClbMTddID0gImVzdDIwMTAiCmBgYAoKYGBge3J9CnZhY2FuY3lfam9pbmVkX3NmIDwtIHN0X2FzX3NmKHZhY2FuY3lfam9pbmVkLCBzZl9jb2x1bW5fbmFtZSA9ICdnZW9tZXRyeScsIGNycyA9IDQzMjYpCgp2YWNhbmN5X2pvaW5lZF9zZiA8LSBkcm9wX25hKHZhY2FuY3lfam9pbmVkX3NmKQoKdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyA8LSBwaXZvdF9sb25nZXIoZGF0YSA9IHZhY2FuY3lfam9pbmVkX3NmLCBjb2xzID1jKGVzdDIwMjEsIGVzdDIwMjA6ZXN0MjAxMCkpCgp2YWNhbmN5X2pvaW5lZF9TZl9sb25nJG5hbWVbdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3QyMDIxJ10gPC0gJzIwMjEnCnZhY2FuY3lfam9pbmVkX1NmX2xvbmckbmFtZVt2YWNhbmN5X2pvaW5lZF9TZl9sb25nJG5hbWUgPT0gJ2VzdDIwMjAnXSA8LSAnMjAyMCcKdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyRuYW1lW3ZhY2FuY3lfam9pbmVkX1NmX2xvbmckbmFtZSA9PSAnZXN0MjAxOSddIDwtICcyMDE5Jwp2YWNhbmN5X2pvaW5lZF9TZl9sb25nJG5hbWVbdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3QyMDE4J10gPC0gJzIwMTgnCnZhY2FuY3lfam9pbmVkX1NmX2xvbmckbmFtZVt2YWNhbmN5X2pvaW5lZF9TZl9sb25nJG5hbWUgPT0gJ2VzdDIwMTcnXSA8LSAnMjAxNycKdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyRuYW1lW3ZhY2FuY3lfam9pbmVkX1NmX2xvbmckbmFtZSA9PSAnZXN0MjAxNiddIDwtICcyMDE2Jwp2YWNhbmN5X2pvaW5lZF9TZl9sb25nJG5hbWVbdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3QyMDE1J10gPC0gJzIwMTUnCnZhY2FuY3lfam9pbmVkX1NmX2xvbmckbmFtZVt2YWNhbmN5X2pvaW5lZF9TZl9sb25nJG5hbWUgPT0gJ2VzdDIwMTQnXSA8LSAnMjAxNCcKdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyRuYW1lW3ZhY2FuY3lfam9pbmVkX1NmX2xvbmckbmFtZSA9PSAnZXN0MjAxMyddIDwtICcyMDEzJwp2YWNhbmN5X2pvaW5lZF9TZl9sb25nJG5hbWVbdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyRuYW1lID09ICdlc3QyMDEyJ10gPC0gJzIwMTInCnZhY2FuY3lfam9pbmVkX1NmX2xvbmckbmFtZVt2YWNhbmN5X2pvaW5lZF9TZl9sb25nJG5hbWUgPT0gJ2VzdDIwMTEnXSA8LSAnMjAxMScKdmFjYW5jeV9qb2luZWRfU2ZfbG9uZyRuYW1lW3ZhY2FuY3lfam9pbmVkX1NmX2xvbmckbmFtZSA9PSAnZXN0MjAxMCddIDwtICcyMDEwJwoKCgoKYGBgCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CiMgTWFraW5nIHRoZSB2YWNhbmN5IGRhdGEgZ2lmCgpjb2xuYW1lcyh2YWNhbmN5X2pvaW5lZF9TZl9sb25nKVs2XSA8LSAneWVhcicgCnZhY2FuY3lfam9pbmVkX1NmX2xvbmckeWVhciA8LSBhcy5pbnRlZ2VyKHZhY2FuY3lfam9pbmVkX1NmX2xvbmckeWVhcikKCmRldHJvaXRfbWFwX3ZhY2FuY3lfZ2lmIDwtIGdncGxvdCgpICsgZ2VvbV9zZihkYXRhID0gdmFjYW5jeV9qb2luZWRfU2ZfbG9uZywgY29sb3IgPSAiYmxhY2siLCBhZXMoZmlsbCA9IHZhbHVlKSkgKyB0aGVtZV9saWdodChiYXNlX3NpemUgPSAxMCkgKyBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJsaWdodHllbGxvdzEiLCBoaWdoID0gImRhcmtvcmNoaWQ0IikgKyB0cmFuc2l0aW9uX3RpbWUoeWVhcikgKyBsYWJzKHRpdGxlID0gIlZhY2FuY3kgYnkgQ2Vuc3VzIFRyYWN0IGJ5IFllYXI6IHtmcmFtZV90aW1lfSIpCgpkZXRyb2l0X21hcF92YWNhbmN5X2dpZgpgYGAKCmBgYHtyfQojIERvd25sb2FkaW5nIHByb3BlcnR5IHNhbGVzIGZyb20gWmlsbG93J3Mgb3BlbiBkYXRhIHBvcnRhbAoKRGV0cm9pdF9wcm9wZXJ0eXNhbGVzIDwtIHJlYWRfY3N2KCJwcm9wZXJ0eV9zYWxlcy5jc3YiKQpgYGAKCgoKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQpkZXRyb2l0X3Byb3BlcnR5X3NhbGVzX3llYXIgPC0gZm9ybWF0KGFzLkRhdGUoRGV0cm9pdF9wcm9wZXJ0eXNhbGVzJHNhbGVfZGF0ZSwgZm9ybWF0PSIlWS8lbS8lZCIpLCIlWSIpCmRhdGEuZnJhbWUoZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyKQpkZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEgPC0gY2JpbmQoZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyLCBEZXRyb2l0X3Byb3BlcnR5c2FsZXMpCmRldHJvaXRfcHJvcHNhbGVzX3llYXJfMQoKRGV0cm9pdF9wcm9wZXJ0eXNhbGVzXzIwMTEgPC0gZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xICU+JSBmaWx0ZXIoZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyID09IDIwMTEpCkRldHJvaXRfcHJvcGVydHlzYWxlc18yMDEyIDwtIGRldHJvaXRfcHJvcHNhbGVzX3llYXJfMSAlPiUgZmlsdGVyKGRldHJvaXRfcHJvcGVydHlfc2FsZXNfeWVhciA9PSAyMDEyKQpEZXRyb2l0X3Byb3BlcnR5c2FsZXNfMjAxMyA8LSBkZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEgJT4lIGZpbHRlcihkZXRyb2l0X3Byb3BlcnR5X3NhbGVzX3llYXIgPT0gMjAxMykKRGV0cm9pdF9wcm9wZXJ0eXNhbGVzXzIwMTQgPC0gZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xICU+JSBmaWx0ZXIoZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyID09IDIwMTQpCkRldHJvaXRfcHJvcGVydHlzYWxlc18yMDE1IDwtIGRldHJvaXRfcHJvcHNhbGVzX3llYXJfMSAlPiUgZmlsdGVyKGRldHJvaXRfcHJvcGVydHlfc2FsZXNfeWVhciA9PSAyMDE1KQpEZXRyb2l0X3Byb3BlcnR5c2FsZXNfMjAxNiA8LSBkZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEgJT4lIGZpbHRlcihkZXRyb2l0X3Byb3BlcnR5X3NhbGVzX3llYXIgPT0gMjAxNikKRGV0cm9pdF9wcm9wZXJ0eXNhbGVzXzIwMTcgPC0gZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xICU+JSBmaWx0ZXIoZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyID09IDIwMTcpCkRldHJvaXRfcHJvcGVydHlzYWxlc18yMDE4IDwtIGRldHJvaXRfcHJvcHNhbGVzX3llYXJfMSAlPiUgZmlsdGVyKGRldHJvaXRfcHJvcGVydHlfc2FsZXNfeWVhciA9PSAyMDE4KQpEZXRyb2l0X3Byb3BlcnR5c2FsZXNfMjAxOSA8LSBkZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEgJT4lIGZpbHRlcihkZXRyb2l0X3Byb3BlcnR5X3NhbGVzX3llYXIgPT0gMjAxOSkKRGV0cm9pdF9wcm9wZXJ0eXNhbGVzXzIwMjAgPC0gZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xICU+JSBmaWx0ZXIoZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyID09IDIwMjApCkRldHJvaXRfcHJvcGVydHlzYWxlc18yMDIxIDwtIGRldHJvaXRfcHJvcHNhbGVzX3llYXJfMSAlPiUgZmlsdGVyKGRldHJvaXRfcHJvcGVydHlfc2FsZXNfeWVhciA9PSAyMDIxKQpEZXRyb2l0X3Byb3BlcnR5c2FsZXNfMjAyMiA8LSBkZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEgJT4lIGZpbHRlcihkZXRyb2l0X3Byb3BlcnR5X3NhbGVzX3llYXIgPT0gMjAyMikKYGBgCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KIyBhZGRpbmcgYWxsIGRldHJvaXQgcHJvcGVydHkgc2FsZXMgYW5kIGNyZWF0aW5nIGEgZ2lmIHRoYXQgaWxsdXN0cmF0ZXMgdGhlIGNoYW5nZSBpbiB0b3RhbCBzYWxlIHByaWNlIGJ5IHllYXIuIAoKc3VtX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfMSA8LSBhZ2dyZWdhdGUoeCA9IGRldHJvaXRfcHJvcHNhbGVzX3llYXJfMSRzYWxlX3ByaWNlLCAgICAgICAgICAgICAgIAogICAgICAgICAgYnkgPSBsaXN0KGRldHJvaXRfcHJvcHNhbGVzX3llYXJfMSRkZXRyb2l0X3Byb3BlcnR5X3NhbGVzX3llYXIpLCAgICAgICAgICAgIAogICAgICAgICAgRlVOID0gc3VtKSAKY29sbmFtZXMoc3VtX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfMSlbMV0gPSAneWVhcicKY29sbmFtZXMoc3VtX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfMSlbMl0gPSAncHJpY2UnCgpzdW1fZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xJHllYXIgPC0gYXMuaW50ZWdlcihzdW1fZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xJHllYXIpCgpkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXMgPC0gZ2dwbG90KCkrIGdlb21fcG9pbnQoZGF0YSA9IHN1bV9kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEsIGFlcyh4ID0geWVhciwgeT0gcHJpY2UpKSArIHRoZW1lX2J3KCkgKyB0cmFuc2l0aW9uX3RpbWUoeWVhcikgKyBsYWJzKHRpdGxlID0gIlJlYWwgRXN0YXRlIFByaWNlcyBpbiBEZXRyb2l0IGJ5IFllYXI6IHtmcmFtZV90aW1lfSIpCgpkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXMKCmBgYAoKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KCiMgR3JhcGhpbmcgdGhlIGF2ZXJhZ2Ugc2FsZSBwcmljZXMgaW4gRGV0cm9pdAoKYXZnX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfMSA8LSBhZ2dyZWdhdGUoeCA9IGRldHJvaXRfcHJvcHNhbGVzX3llYXJfMSRzYWxlX3ByaWNlLCAgICAgICAgICAgICAgIAogICAgICAgICAgYnkgPSBsaXN0KGRldHJvaXRfcHJvcHNhbGVzX3llYXJfMSRkZXRyb2l0X3Byb3BlcnR5X3NhbGVzX3llYXIpLCAgICAgICAgICAgIAogICAgICAgICAgRlVOID0gbWVhbikgCgpjb2xuYW1lcyhhdmdfZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xKVsxXSA9ICd5ZWFyJwpjb2xuYW1lcyhhdmdfZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xKVsyXSA9ICdwcmljZScKCmF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEkeWVhciA8LSBhcy5pbnRlZ2VyKGF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEkeWVhcikKCmRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlc19hdmcgPC0gZ2dwbG90KCkrIGdlb21fcG9pbnQoZGF0YSA9IGF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEsIGFlcyh4ID0geWVhciwgeT0gcHJpY2UpKSArIHRoZW1lX2J3KCkgKyB0cmFuc2l0aW9uX3RpbWUoeWVhcikgKyBsYWJzKHRpdGxlID0gIiBBdmVyYWdlIFJlYWwgRXN0YXRlIFByaWNlcyBpbiBEZXRyb2l0IGJ5IFllYXI6IHtmcmFtZV90aW1lfSIpCgpkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfYXZnCgpgYGAKCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CiMgRmlsdGVyaW5nIHRvIHByb3BlcnR5IGNsYXNzIDQwMSwgd2hpY2ggcmVmZXJzIHRvIHJlc2lkZW50aWFsIGluIG5hdHVyZSBhbmQgcmVjZW50bHkgaW1wcm92ZWQuCmRldHJvaXRzYWxlc180MDEgPC0gZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl8xICU+JSBkcGx5cjo6ZmlsdGVyKC4sIHByb3BlcnR5X2NsYXNzID09IDQwMSkKCiMgRmlsdGVyaW5nIHRvIHByb3BlcnR5IGNsYXNzIDQwMiwgd2hpY2ggcmVmZXJzIHRvIHJlc2lkZW50aWFsIGFuZCBuYXR1cmUgYW5kIHZhY2FudC4KZGV0cm9pdHNhbGVzXzQwMiA8LSBkZXRyb2l0X3Byb3BzYWxlc195ZWFyXzEgJT4lIGRwbHlyOjpmaWx0ZXIoLiwgcHJvcGVydHlfY2xhc3MgPT0gNDAyKQoKYGBgCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CiMgR3JhcGhpbmcgdGhlIHRvdGFsIHNhbGUgcHJpY2VzIGluIERldHJvaXQgLSBieSBwcm9wZXJ0eSBjbGFzcyA0MDEKCnN1bV9kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMSA8LSBhZ2dyZWdhdGUoeCA9IGRldHJvaXRzYWxlc180MDEkc2FsZV9wcmljZSwgICAgICAgICAgICAgICAKICAgICAgICAgIGJ5ID0gbGlzdChkZXRyb2l0c2FsZXNfNDAxJGRldHJvaXRfcHJvcGVydHlfc2FsZXNfeWVhciksICAgICAgICAgICAgCiAgICAgICAgICBGVU4gPSBzdW0pIApjb2xuYW1lcyhzdW1fZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl80MDEpWzFdID0gJ3llYXInCmNvbG5hbWVzKHN1bV9kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMSlbMl0gPSAncHJpY2UnCgpzdW1fZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl80MDEkeWVhciA8LSBhcy5pbnRlZ2VyKHN1bV9kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMSR5ZWFyKQoKZGV0cm9pdF9saW5lX2dyYXBoX3NhbGVzcHJpY2VzXzQwMSA8LSBnZ3Bsb3QoKSsgZ2VvbV9wb2ludChkYXRhID0gc3VtX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfNDAxLCBhZXMoeCA9IHllYXIsIHk9IHByaWNlKSkgKyB0aGVtZV9idygpICsgdHJhbnNpdGlvbl90aW1lKHllYXIpICsgbGFicyh0aXRsZSA9ICJSZWFsIEVzdGF0ZSBQcmljZXMgLSBSZXNpZGVudGlhbCBpbiBOYXR1cmUgYW5kIEltcHJvdmVkIGluIERldHJvaXQgYnkgWWVhcjoge2ZyYW1lX3RpbWV9IikKCmRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlc180MDEKYGBgCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CiMgR3JhcGhpbmcgdGhlIGF2ZXJhZ2Ugc2FsZSBwcmljZXMgaW4gRGV0cm9pdCAtIGJ5IHByb3BlcnR5IGNsYXNzIDQwMQoKYXZnX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfNDAxIDwtIGFnZ3JlZ2F0ZSh4ID0gZGV0cm9pdHNhbGVzXzQwMSRzYWxlX3ByaWNlLCAgICAgICAgICAgICAgIAogICAgICAgICAgYnkgPSBsaXN0KGRldHJvaXRzYWxlc180MDEkZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyKSwgICAgICAgICAgICAKICAgICAgICAgIEZVTiA9IG1lYW4pIApjb2xuYW1lcyhhdmdfZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl80MDEpWzFdID0gJ3llYXInCmNvbG5hbWVzKGF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMSlbMl0gPSAncHJpY2UnCgphdmdfZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl80MDEkeWVhciA8LSBhcy5pbnRlZ2VyKGF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMSR5ZWFyKQoKZGV0cm9pdF9saW5lX2dyYXBoX3NhbGVzcHJpY2VzXzQwMV9hdmcgPC0gZ2dwbG90KCkrIGdlb21fcG9pbnQoZGF0YSA9IGF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMSwgYWVzKHggPSB5ZWFyLCB5PSBwcmljZSkpICsgdGhlbWVfYncoKSArIHRyYW5zaXRpb25fdGltZSh5ZWFyKSArIGxhYnModGl0bGUgPSAiIEF2ZXJhZ2UgUmVhbCBFc3RhdGUgUHJpY2VzIC0gUmVzaWRlbnRpYWwgaW4gTmF0dXJlIGFuZCBJbXByb3ZlZCBpbiBEZXRyb2l0IGJ5IFllYXI6IHtmcmFtZV90aW1lfSIpCgpkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfNDAxX2F2ZwpgYGAKCgoKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KIyBHcmFwaGluZyB0aGUgdG90YWwgc2FsZSBwcmljZXMgaW4gRGV0cm9pdCAtIGJ5IHByb3BlcnR5IGNsYXNzIDQwMgoKc3VtX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfNDAyIDwtIGFnZ3JlZ2F0ZSh4ID0gZGV0cm9pdHNhbGVzXzQwMiRzYWxlX3ByaWNlLCAgICAgICAgICAgICAgIAogICAgICAgICAgYnkgPSBsaXN0KGRldHJvaXRzYWxlc180MDIkZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyKSwgICAgICAgICAgICAKICAgICAgICAgIEZVTiA9IHN1bSkgCmNvbG5hbWVzKHN1bV9kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMilbMV0gPSAneWVhcicKY29sbmFtZXMoc3VtX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfNDAyKVsyXSA9ICdwcmljZScKCnN1bV9kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMiR5ZWFyIDwtIGFzLmludGVnZXIoc3VtX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfNDAyJHllYXIpCgpkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfNDAyIDwtIGdncGxvdCgpKyBnZW9tX3BvaW50KGRhdGEgPSBzdW1fZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl80MDIsIGFlcyh4ID0geWVhciwgeT0gcHJpY2UpLCBjb2xvciA9ICJyb3lhbGJsdWUiLCBzaXplID0gNCkgKyB0aGVtZV9idygpICsgdHJhbnNpdGlvbl90aW1lKHllYXIpICsgbGFicyh0aXRsZSA9ICJSZWFsIEVzdGF0ZSBQcmljZXMgLSBSZXNpZGVudGlhbCBhbmQgVmFjYW50IGluIERldHJvaXQgYnkgWWVhcjoge2ZyYW1lX3RpbWV9IikKCmRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlc180MDIKYGBgCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CiMgR3JhcGhpbmcgdGhlIGF2ZXJhZ2Ugc2FsZSBwcmljZXMgaW4gRGV0cm9pdCAtIGJ5IHByb3BlcnR5IGNsYXNzIDQwMgoKYXZnX2RldHJvaXRfcHJvcHNhbGVzX3llYXJfNDAyIDwtIGFnZ3JlZ2F0ZSh4ID0gZGV0cm9pdHNhbGVzXzQwMiRzYWxlX3ByaWNlLCAgICAgICAgICAgICAgIAogICAgICAgICAgYnkgPSBsaXN0KGRldHJvaXRzYWxlc180MDIkZGV0cm9pdF9wcm9wZXJ0eV9zYWxlc195ZWFyKSwgICAgICAgICAgICAKICAgICAgICAgIEZVTiA9IG1lYW4pIApjb2xuYW1lcyhhdmdfZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl80MDIpWzFdID0gJ3llYXInCmNvbG5hbWVzKGF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMilbMl0gPSAncHJpY2UnCgphdmdfZGV0cm9pdF9wcm9wc2FsZXNfeWVhcl80MDIkeWVhciA8LSBhcy5pbnRlZ2VyKGF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMiR5ZWFyKQoKZGV0cm9pdF9saW5lX2dyYXBoX3NhbGVzcHJpY2VzXzQwMl9hdmcgPC0gZ2dwbG90KCkrIGdlb21fcG9pbnQoZGF0YSA9IGF2Z19kZXRyb2l0X3Byb3BzYWxlc195ZWFyXzQwMiwgYWVzKHggPSB5ZWFyLCB5PSBwcmljZSkpICsgdGhlbWVfYncoKSArIHRyYW5zaXRpb25fdGltZSh5ZWFyKSArIGxhYnModGl0bGUgPSAiIEF2ZXJhZ2UgUmVhbCBFc3RhdGUgUHJpY2VzIC0gUmVzaWRlbnRpYWwgYW5kIFZhY2FudCBpbiBEZXRyb2l0IGJ5IFllYXI6IHtmcmFtZV90aW1lfSIpCgpkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfNDAyX2F2ZwpgYGAKCgoKYGBge3J9CiMgRG93bmxvYWRpbmcgcmVzaWRlbnRpYWwgZGVtb2xpdGlvbiBkYXRhIC0gZnJvbSBEZXRyb2l0J3MgT3BlbiBEYXRhIFBvcnRhbAoKcmVzaWRlbnRpYWxfZGVtb2xpdGlvbnMgPC0gcmVhZF9jc3YoIkNvbXBsZXRlZF9SZXNpZGVudGlhbF9EZW1vbGl0aW9ucy5jc3YiKQpgYGAKCmBgYHtyfQojIFRpZHlpbmcgZGVtb2xpdGlvbiBkYXRhLi4uCgp5ZWFyX2RlbW88LSBmb3JtYXQoYXMuRGF0ZShyZXNpZGVudGlhbF9kZW1vbGl0aW9ucyRkZW1vbGl0aW9uX2RhdGUsIGZvcm1hdD0iJVkvJW0vJWQiKSwiJVkiKQpkYXRhLmZyYW1lKHJlc2lkZW50aWFsX2RlbW9saXRpb25zKQpyZXNpZGVudGlhbF9kZW1vX3llYXIgPC0gY2JpbmQoeWVhcl9kZW1vLCByZXNpZGVudGlhbF9kZW1vbGl0aW9ucykKcmVzaWRlbnRpYWxfZGVtb195ZWFyCmBgYAoKYGBge3J9CiMgVHJhbnNmb3JtaW5nIGl0IGludG8gYSBzcGF0aWFsIG9iamVjdAoKcmVzaWRlbnRpYWxfZGVtb195ZWFyIDwtIHN0X2FzX3NmKHJlc2lkZW50aWFsX2RlbW9feWVhciwgY29vcmRzID0gYygiWCIsICJZIiksIGNycyA9IDQzMjYpCmBgYAoKYGBge3J9CiMgTWFwcGluZyByZXNpZGVudGlhbCBkZW1vbGl0aW9ucyBmcm9tIDIwMTQgLSAyMDIyICgyMDE0IGlzIHRoZSBlYXJsaWVzdCBkYXRlIGF2YWlsYWJsZSkKcmVzaWRlbnRpYWxfZGVtb195ZWFyJHllYXJfZGVtbyA8LSBhcy5pbnRlZ2VyKHJlc2lkZW50aWFsX2RlbW9feWVhciR5ZWFyX2RlbW8pCgpkZXRyb2l0X21hcF9kZW1vIDwtIGdncGxvdCgpICsgZ2VvbV9zZihkYXRhID0gcmVzaWRlbnRpYWxfZGVtb195ZWFyLCBjb2xvciA9ICJkYXJrZ3JlZW4iLCBhZXMoZmlsbCA9IHllYXJfZGVtbyksIHNpemUgPSAuMDUsIGFscGhhID0gLjUpICsgdGhlbWVfbGlnaHQoYmFzZV9zaXplID0gMTApICsgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAibGlnaHR5ZWxsb3cxIiwgaGlnaCA9ICJkYXJrb3JjaGlkNCIpIAoKZGV0cm9pdF9tYXBfZGVtbwpgYGAKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQoKIyBNYWtpbmcgaXQgaW50byBhIGdpZiEKCnJlc2lkZW50aWFsX2RlbW9feWVhciR5ZWFyX2RlbW8gPC0gYXMuaW50ZWdlcihyZXNpZGVudGlhbF9kZW1vX3llYXIkeWVhcl9kZW1vKQoKZGV0cm9pdF9tYXBfZGVtb19naWYgPC0gZ2dwbG90KCkgKyBnZW9tX3NmKGRhdGEgPSByZXNpZGVudGlhbF9kZW1vX3llYXIsIGNvbG9yID0gImRhcmtncmVlbiIsIGFlcyhmaWxsID0geWVhcl9kZW1vKSwgc2l6ZSA9IC4wNSwgYWxwaGEgPSAuNSkgKyB0aGVtZV9saWdodChiYXNlX3NpemUgPSAxMCkgKyBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJsaWdodHllbGxvdzEiLCBoaWdoID0gImRhcmtvcmNoaWQ0IikgKyB0cmFuc2l0aW9uX3RpbWUoeWVhcl9kZW1vKSArIGxhYnModGl0bGUgPSAiRGVtb2xpdGlvbnMgYnkgWWVhcjoge2ZyYW1lX3RpbWV9IikKCmRldHJvaXRfbWFwX2RlbW9fZ2lmCgoKYGBgCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X21hcF9kZW1vX2dpZi5naWYiLCBkZXRyb2l0X21hcF9kZW1vX2dpZikKYGBgCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9CmFuaW1fc2F2ZSgiZGV0cm9pdF9tYXBfcG9wX2dpZi5naWYiLCBkZXRyb2l0X21hcF9wb3BfZ2lmKQpgYGAKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X2xpbmVfZ3JhcGhfcG9wdWxhdGlvbi5naWYiLCBkZXRyb2l0X2xpbmVfZ3JhcGhfcG9wdWxhdGlvbikKYGBgCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X2xpbmVfZ3JhcGhfdmFjYW5jaWVzXzEuZ2lmIiwgZGV0cm9pdF9saW5lX2dyYXBoX3ZhY2FuY2llc18xKQpgYGAKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X2xpbmVfZ3JhcGhfdmFjYW5jaWVzXzIuZ2lmIiwgZGV0cm9pdF9saW5lX2dyYXBoX3ZhY2FuY2llc18yKQpgYGAKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X21hcF92YWNhbmN5X2dpZi5naWYiLCBkZXRyb2l0X21hcF92YWNhbmN5X2dpZikKYGBgCgoKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQphbmltX3NhdmUoImRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlcy5naWYiLCBkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXMpCmBgYAoKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfNDAxLmdpZiIsIGRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlc180MDEpIApgYGAKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfNDAyLmdpZiIsIGRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlc180MDIpIApgYGAKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfNDAxX2F2Zy5naWYiLCBkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfNDAxX2F2ZykgCmBgYAoKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQphbmltX3NhdmUoImRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlc180MDJfYXZnLmdpZiIsIGRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlc180MDJfYXZnKQpgYGAKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KYW5pbV9zYXZlKCJkZXRyb2l0X2xpbmVfZ3JhcGhfc2FsZXNwcmljZXNfYXZnLmdpZiIsIGRldHJvaXRfbGluZV9ncmFwaF9zYWxlc3ByaWNlc19hdmcpCgpgYGAKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoImdpZnNraSIpCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2lmc2tpKQpsaWJyYXJ5KHJzY29ubmVjdCkKCmBgYAoKCg==