About the company

In 2016, Divvy launched a successful bike-share offering. Since then, the program has grown to a fleet of 5824 bicycles that are geotracked and locked into a network of 692 stations across Chicago. The bikes can be unlocked from one station and returned to any other station in the system anytime.

Customers who purchase single-ride or full-day passes are referred to as “Casual” Riders. Customers who purchase annual memberships are “Member” Riders.

Task

The primary objective is to find the difference between casual riders and member riders, how they use the Divvy bikes differently. On that basis, the company shall build a new model which will attract casual riders to enroll for the annual membership.

Data Sources

The data set from the year 2013-2021 is used (the data is available till October, 2021). The data provides details about how customers are using the bicycle service. The data is provided by Motivate International Inc under this license. for public use. The data is downloaded and organized in folders in ascending order. The data provides the details about the trips and stations used by the customers with single or full-day passes, and individuals with annual memberships. “Casual Rider” is a rider who purchased single ride or 24-hour pass, whereas “Member Rider” is a rider who purchased an Annual Membership.

Libraries used during the case study

library(tidyverse)     # Collection of R packages for preparing, wrangling and visualizing data
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✓ ggplot2 3.3.5     ✓ purrr   0.3.4
✓ tibble  3.1.6     ✓ dplyr   1.0.7
✓ tidyr   1.1.4     ✓ stringr 1.4.0
✓ readr   2.1.0     ✓ forcats 0.5.1
── Conflicts ───────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(readxl)        # package for extracting data from Excel
library(lubridate)     # Makes easier to format dates

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(modeest)       # used for mode estimation 
Registered S3 method overwritten by 'rmutil':
  method         from
  print.response httr
library(pivottabler)   # Creates pivot tables
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
library(scales)        # Scales functionds for visualisation

Attaching package: ‘scales’

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

    discard

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

    col_factor
library(gridExtra)     # arrange multiple grid-based plots on a page, and draw tables.

Attaching package: ‘gridExtra’

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

    combine
library(anytime)       # for converting to datetime formats/

Importing and combining the data files

The data sets of the respective years (2013-2021) are imported and combined into one file. The data type of every column is set during importing process to avoid errors.

Data Transformation and Wrangling

In some parts of the data the column names are consistent. Renaming is done to avoid any misunderstanding during the data analysis process. The new columns are created to get for proper understanding of the data. The unnecessary columns are excluded to make data more consistent and extract the answers to the business question.

Improper entries like empty cell, improper data type or data structure are excluded during data analysis process. Microsoft Excel is used at some point of transformation like renaming column, formatting dates.

Data Analysis

The analysis is carried to get the answer to the business question. To better understand the data set, statistical formulas are used on the data set, and pivot tables are generated. For understanding the rider’s behaviour during the years, the visualization tool is used to get the overall picture of the data set and explain the difference between Casual Riders and Annual Member Riders.

Cyclistic Bike Share 2013 Data Set


# Importing and Combining all related datasets
trips_2013 <- read_csv("Data sources/Divvy_Trips_2013.csv"
                       ,col_types = cols(trip_id = "i"
                                         ,bikeid = "i"
                                         ,tripduration = "d"
                                         ,from_station_id = "i"
                                         ,from_station_name = "c"
                                         ,to_station_id = "i"
                                         ,to_station_name = "c"
                                         ,usertype = "c"
                                         ,gender = "c"
                                         ,birthday = "i"))
# Data transformation & wrangling
trips_2013 <- select(trips_2013, -birthday, -gender, -from_station_id, -to_station_id)
trips_2013$usertype[trips_2013$usertype == 'Customer'] <- "Casual"
trips_2013$usertype[trips_2013$usertype == 'Subscriber'] <- "Member"
trips_2013$day <- wday(trips_2013$starttime, label = TRUE, abbr = FALSE)
trips_2013$month <- month(trips_2013$starttime, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2013:", round(mean(trips_2013$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2013: 1239.47 seconds"
paste("The longest duration a rider used the bike in 2013 was", max(trips_2013$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2013 was 86399 seconds"
paste("The most popular day of booking was", mfv(trips_2013$day), "in 2013")
[1] "The most popular day of booking was Saturday in 2013"
paste("The most popular month of booking was", mfv(trips_2013$month))
[1] "The most popular month of booking was September"
#generating new data frame
trips_2013_pivot <- trips_2013 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2013$starttime), .groups = 'drop')
trips_2013_pivot <- unique(trips_2013_pivot)

  
#pivot table
qhpvt(trips_2013, rows = "day", columns = "usertype", calculations = c("Avg_ride_length" = "round(mean(tripduration), digits =2)", "no_of_riders" = "length(trip_id)"))

Data Visualisation

#function to set plot size
fig <- function(width, height){
  options(repr.plot.width = width, repr.plot.height = height)
}
p1 <- ggplot(trips_2013, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = "dodge")+ scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) + 
  labs(x = "Week Days", y = "Number of Riders", 
       title = "Divvy bikes riders data",
       subtitle = "Year: 2013 (Weekly)")+
  scale_fill_discrete(name = "Type of Riders", labels = c("Casual Riders", "Member Riders")) +
theme(text = element_text(size = 10))
# Trip duration of riders in 2013
p2 <- ggplot(trips_2013, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2013)",
       subtitle = "The graph represents the total trip duration of riders on everday of the week in 2013.") +
    theme(axis.text.x = element_text(angle =45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Divvy bikes 2014 dataset

# importing & combining all related datasets
trips_2014 <- rbind(read_csv("Data sources/Divvy_Trips_2014_Q1Q2.csv"
                       ,col_types = cols(trip_id = "i"
                                         ,bikeid = "i"
                                         ,tripduration = "d"
                                         ,from_station_id = "i"
                                         ,from_station_name = "c"
                                         ,to_station_id = "i"
                                         ,to_station_name = "c"
                                         ,usertype = "c"
                                         ,gender = "c"
                                         ,birthyear = "i"))
                    ,read_csv("Data sources/Divvy_Trips_2014-Q3-07.csv"
                       ,col_types = cols(trip_id = "i"
                                         ,bikeid = "i"
                                         ,tripduration = "d"
                                         ,from_station_id = "i"
                                         ,from_station_name = "c"
                                         ,to_station_id = "i"
                                         ,to_station_name = "c"
                                         ,usertype = "c"
                                         ,gender = "c"
                                         ,birthyear = "i"))
                    ,read_csv("Data sources/Divvy_Trips_2014-Q3-0809.csv"
                       ,col_types = cols(trip_id = "i"
                                         ,bikeid = "i"
                                         ,tripduration = "d"
                                         ,from_station_id = "i"
                                         ,from_station_name = "c"
                                         ,to_station_id = "i"
                                         ,to_station_name = "c"
                                         ,usertype = "c"
                                         ,gender = "c"
                                         ,birthyear = "i"))
                    ,read_csv("Data sources/Divvy_Trips_2014-Q4.csv"
                       ,col_types = cols(trip_id = "i"
                                         ,bikeid = "i"
                                         ,tripduration = "d"
                                         ,from_station_id = "i"
                                         ,from_station_name = "c"
                                         ,to_station_id = "i"
                                         ,to_station_name = "c"
                                         ,usertype = "c"
                                         ,gender = "c"
                                         ,birthyear = "i")))
# Data transformation & wrangling
trips_2014 <- select(trips_2014, -birthyear, -gender, -to_station_id, -from_station_id)
trips_2014$start_time <- anytime(trips_2014$starttime)
trips_2014$starttime <- mdy_hms(trips_2014$starttime)
trips_2014$stoptime <- mdy_hms(trips_2014$stoptime)
trips_2014$day <- wday(trips_2014$starttime, label = TRUE, abbr = FALSE)
trips_2014$usertype[trips_2014$usertype == 'Customer'] <- "Casual"
trips_2014$usertype[trips_2014$usertype == 'Subscriber'] <- "Member"
trips_2014$month <- month(trips_2014$starttime, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2014:", round(mean(trips_2014$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2014: 1024.94 seconds"
paste("The longest duration a rider used the bike in 2014 was", max(trips_2014$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2014 was 86392 seconds"
paste("The most popular day of booking was", mfv(trips_2014$day), "in 2014")
[1] "The most popular day of booking was Sunday in 2014"
paste("The most popular month of booking was", mfv(trips_2014$month))
[1] "The most popular month of booking was July"
#generating new data frame
trips_2014_pivot <- trips_2014 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2014$starttime), .groups = 'drop')
trips_2014_pivot <- unique(trips_2014_pivot)


#pivot table
qhpvt(trips_2014, rows = "day", columns = "usertype", calculations = c("Avg_ride_length" = "round(mean(tripduration), digits =2)", "no_of_riders" = "length(trip_id)"))

Data Visualisation

#function to set plot size
fig <- function(width, height){
  options(repr.plot.width = width, repr.plot.height = height)
}
p1 <- ggplot(trips_2014, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = "dodge")+ scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) + 
  labs(x = "Week Days", y = "Number of Riders", 
       title = "Divvy bikes riders data",
       subtitle = "Year: 2014 (Weekly)")+
  scale_fill_discrete(name = "Type of Riders", labels = c("Casual Riders", "Member Riders")) +
  theme(text = element_text(size = 10))
# Trip duration of riders in 2013
p2 <- ggplot(trips_2014, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2014)",
       subtitle = "The graph represents the total trip duration of riders on everday of the week in 2013.") +
  theme(axis.text.x = element_text(angle =45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Divvy bikes 2015 Dataset

# importing and combining all related datasets
trips_2015 <- rbind(read_csv("Data sources/Divvy_Trips_2015-Q1.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2015-Q2.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2015_07.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2015_08.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2015_09.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2015_Q4.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i")))
# data transformation and wrangling
trips_2015 <- select(trips_2015, -birthyear, -gender, -from_station_id, -to_station_id)
trips_2015$usertype[trips_2015$usertype == 'Subscriber'] <- "Member"
trips_2015$usertype[trips_2015$usertype == 'Customer'] <- "Casual"
trips_2015$starttime <- anytime(trips_2015$starttime)
trips_2015$day <- wday(trips_2015$starttime, label = TRUE, abbr = FALSE)
trips_2015$month <- month(trips_2015$starttime, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2015:", round(mean(trips_2015$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2015: 1024.03 seconds"
paste("The longest duration a rider used the bike in 2015 was", max(trips_2015$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2015 was 86362 seconds"
paste("The most popular day of booking was", mfv(trips_2015$day), "in 2015")
[1] "The most popular day of booking was Wednesday in 2015"
paste("The most popular month of booking was", mfv(trips_2015$month))
[1] "The most popular month of booking was July"
# creating a new dataframe
trips_2015_pivot <- trips_2015 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2015$starttime), .groups = 'drop')
trips_2015_pivot <- unique(trips_2015_pivot)

# pivot table
qhpvt(trips_2015, rows = 'day', columns = 'usertype', calculations = c("Average Ride Length" = "round(mean(tripduration), digits = 2)", "Number of rides" = "length(trip_id)"))

Data visualisation

# Number of riders in 2015
p1 <- ggplot(trips_2015, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = 'dodge') + scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) +
  labs(x = "Weekdays", y = "Number of Riders"
       ,title = " Divvy Bikes riders data"
       ,subtitle = "Year : 2015 (Weekly)" +
         scale_fill_discrete(name = "Type of Riders", labels = c("Casual Riders","Annual Member Riders" ,"Dependent")) +
theme(text = element_text(size = 10))) 

# Trip duration of riders in 2015
p2 <- ggplot(trips_2015, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2015)",
       subtitle = "The graph represents the total trip duration of riders on everday of the week in 2015.") +
    theme(axis.text.x = element_text(angle =45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Divvy bikes 2016 Dataset

# importing and combining all related datasets
trips_2016 <- rbind(read_csv("Data sources/Divvy_Trips_2016_Q1.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2016_04.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2016_05.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2016_06.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2016_Q3.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2016_Q4.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i")))
# data transformation and wrangling
trips_2016 <- select(trips_2016, -birthyear, -gender, -from_station_id, -to_station_id)
trips_2016$usertype[trips_2016$usertype == 'Subscriber'] <- "Member"
trips_2016$usertype[trips_2016$usertype == 'Customer'] <- "Casual"
trips_2016$starttime <- anytime(trips_2016$starttime)
trips_2016$day <- wday(trips_2016$starttime, label = TRUE, abbr = FALSE)
trips_2016$month <- month(trips_2016$starttime, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2016:", round(mean(trips_2016$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2016: 993.34 seconds"
paste("The longest duration a rider used the bike in 2016 was", max(trips_2016$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2016 was 86365 seconds"
paste("The most popular day of booking was", mfv(trips_2016$day), "in 2016")
[1] "The most popular day of booking was Monday in 2016"
paste("The most popular month of booking was", mfv(trips_2016$month))
[1] "The most popular month of booking was July"
# creating a new dataframe
trips_2016_pivot <- trips_2016 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2016$starttime), .groups = 'drop')
trips_2016_pivot <- unique(trips_2016_pivot)

# pivot table
qhpvt(trips_2016, rows = 'day', columns = 'usertype', calculations = c("Average Ride Length" = "round(mean(tripduration), digits = 2)", "Number of rides" = "length(trip_id)"))

Data visualisation

# Number of riders in 2016
p1 <- ggplot(trips_2016, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = 'dodge') + scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) +
  labs(x = "Weekdays", y = "Number of Riders"
       ,title = " Divvy Bikes riders data"
       ,subtitle = "Year : 2016 (Weekly)" +
         scale_fill_discrete(name = "Type of Riders", labels = c("Casual Riders","Annual Member Riders" ,"Dependent")) +
theme(text = element_text(size = 10))) 

# Trip duration of riders in 2017
p2 <- ggplot(trips_2016, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2016)",
       subtitle = "The graph represents the total trip duration of riders everday of the week in 2016.") +
    theme(axis.text.x = element_text(angle =45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Divvy bikes 2017 Dataset

# importing and combining all related datasets
trips_2017 <- rbind(read_csv("Data sources/Divvy_Trips_2017_Q1.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2017_Q2.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2017_Q3.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2017_Q4.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,tripduration = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i")))
                            
# data transformation and wrangling
trips_2017 <- select(trips_2017,  -from_station_id, -to_station_id)
trips_2017$usertype[trips_2017$usertype == 'Subscriber'] <- "Member"
trips_2017$usertype[trips_2017$usertype == 'Customer'] <- "Casual"
trips_2017$start_time <- anytime(trips_2017$start_time)
trips_2017$day <- wday(trips_2017$start_time, label = TRUE, abbr = FALSE)
trips_2017$month <- month(trips_2017$start_time, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2017:", round(mean(trips_2017$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2017: 955.63 seconds"
paste("The longest duration a rider used the bike in 2017 was", max(trips_2017$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2017 was 86338 seconds"
paste("The most popular day of booking was", mfv(trips_2017$day), "in 2017")
[1] "The most popular day of booking was Monday in 2017"
paste("The most popular month of booking was", mfv(trips_2017$month))
[1] "The most popular month of booking was July"
# creating a new dataframe
trips_2017_pivot <- trips_2017 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2017$start_time), .groups = 'drop')
trips_2017_pivot <- unique(trips_2017_pivot)

# pivot table
qhpvt(trips_2017, rows = 'day', columns = 'usertype', calculations = c("Average Ride Length" = "round(mean(tripduration), digits = 2)", "Number of rides" = "length(trip_id)"))

Data visualisation

# Number of riders in 2017
p1 <- ggplot(trips_2017, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = 'dodge') + scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) +
  labs(x = "Weekdays", y = "Number of Riders"
       ,title = " Divvy Bikes riders data"
       ,subtitle = "Year : 2017 (Weekly)" +
         scale_fill_discrete(name = "Type of Riders", labels = c("Casual Riders","Annual Member Riders" ,"Dependent")) +
theme(text = element_text(size = 10))) 

# Trip duration of riders in 2017
p2 <- ggplot(trips_2017, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2017)",
       subtitle = "The graph represents the total trip duration of riders everday of the week in 2017.") +
    theme(axis.text.x = element_text(angle =45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Divvy bikes 2018 Dataset

# importing and combining all related datasets
trips_2018_q1 <- read_csv("Data sources/Divvy_Trips_2018_Q1.csv"
                             ,col_types = cols('01 - Rental Details Rental ID' = "i"
                                               ,'01 - Rental Details Bike ID' = "i"
                                               ,'03 - Rental Start Station ID' = "i"
                                               ,'03 - Rental Start Station Name' = "c"
                                               ,'02 - Rental End Station ID' = "i"
                                               ,'02 - Rental End Station Name' = "c"
                                               ,'User Type' = "c"
                                               ,'Member Gender' = "c"
                                               ,'05 - Member Details Member Birthday Year' = "i"))
trips_2018_q1 <- rename(trips_2018_q1, trip_id = `01 - Rental Details Rental ID`
                        ,start_time = `01 - Rental Details Local Start Time`
                        ,end_time = `01 - Rental Details Local End Time`
                        ,bikeid = `01 - Rental Details Bike ID`
                        ,tripduration = `01 - Rental Details Duration In Seconds Uncapped`
                        ,from_station_id = `03 - Rental Start Station ID`
                        ,from_station_name = `03 - Rental Start Station Name`
                        ,to_station_id = `02 - Rental End Station ID`
                        ,to_station_name = `02 - Rental End Station Name`
                        ,usertype = `User Type`
                        ,gender = `Member Gender`
                        ,birthyear = `05 - Member Details Member Birthday Year`)
trips_2018_q2q3q4<- rbind(read_csv("Data sources/Divvy_Trips_2018_Q2.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2018_Q3.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
                             ,read_csv("Data sources/Divvy_Trips_2018_Q4.csv"
                             ,col_types = cols( trip_id = "i"
                                               ,bikeid = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i")))
trips_2018 <- rbind(trips_2018_q1, trips_2018_q2q3q4)
                            
# data transformation and wrangling
trips_2018 <- select(trips_2018, -birthyear, -gender, -from_station_id, -to_station_id)
trips_2018$usertype[trips_2018$usertype == 'Subscriber'] <- "Member"
trips_2018$usertype[trips_2018$usertype == 'Customer'] <- "Casual"
trips_2018$start_time <- anytime(trips_2018$start_time)
trips_2018$day <- wday(trips_2018$start_time, label = TRUE, abbr = FALSE)
trips_2018$month <- month(trips_2018$start_time, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2018:", round(mean(trips_2018$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2018: 1413.17 seconds"
paste("The longest duration a rider used the bike in 2018 was", max(trips_2018$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2018 was 14336400 seconds"
paste("The most popular day of booking was", mfv(trips_2018$day), "in 2018")
[1] "The most popular day of booking was Wednesday in 2018"
paste("The most popular month of booking was", mfv(trips_2018$month))
[1] "The most popular month of booking was July"
# creating a new dataframe
trips_2018_pivot <- trips_2018 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2018$start_time), .groups = 'drop')
trips_2018_pivot <- unique(trips_2018_pivot)

# pivot table
qhpvt(trips_2018, rows = 'day', columns = 'usertype', calculations = c("Average Ride Length" = "round(mean(tripduration), digits = 2)", "Number of rides" = "length(trip_id)"))

Data visualisation

# Number of riders in 2018
p1 <- ggplot(trips_2018, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = 'dodge') + scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) +
  labs(x = "Weekdays", y = "Number of Riders"
       ,title = " Divvy Bikes riders data"
       ,subtitle = "Year : 2018 (Weekly)" +
         scale_fill_discrete(name = "Type of Riders", labels = c("Casual Riders","Annual Member Riders")) +
theme(text = element_text(size = 10))) 

# Trip duration of riders in 2018
p2 <- ggplot(trips_2018, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2018)",
       subtitle = "The graph represents the total trip duration of riders everday of the week in 2018.") +
    theme(axis.text.x = element_text(angle = 45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Divvy bikes 2019 Dataset

# importing and combining all related datasets
trips_2019_q2 <- read_csv("Data sources/Divvy_Trips_2019_Q2.csv"
                             ,col_types = cols('01 - Rental Details Rental ID' = "i"
                                               ,'01 - Rental Details Bike ID' = "i"
                                               ,'03 - Rental Start Station ID' = "i"
                                               ,'03 - Rental Start Station Name' = "c"
                                               ,'02 - Rental End Station ID' = "i"
                                               ,'02 - Rental End Station Name' = "c"
                                               ,'User Type' = "c"
                                               ,'Member Gender' = "c"
                                               ,'05 - Member Details Member Birthday Year' = "i"))
trips_2019_q2 <- rename(trips_2019_q2, trip_id = `01 - Rental Details Rental ID`
                        ,start_time = `01 - Rental Details Local Start Time`
                        ,end_time = `01 - Rental Details Local End Time`
                        ,bikeid = `01 - Rental Details Bike ID`
                        ,tripduration = `01 - Rental Details Duration In Seconds Uncapped`
                        ,from_station_id = `03 - Rental Start Station ID`
                        ,from_station_name = `03 - Rental Start Station Name`
                        ,to_station_id = `02 - Rental End Station ID`
                        ,to_station_name = `02 - Rental End Station Name`
                        ,usertype = `User Type`
                        ,gender = `Member Gender`
                        ,birthyear = `05 - Member Details Member Birthday Year`)
trips_2019_q1<- read_csv("Data sources/Divvy_Trips_2019_Q1.csv"
                             ,col_types = cols(trip_id = "i"
                                               ,bikeid = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
trips_2019_q3 <- read_csv("Data sources/Divvy_Trips_2019_Q3.csv"
                          ,col_types = cols(trip_id = "i"
                                            ,bikeid = "i"
                                            ,from_station_id = "i"
                                            ,from_station_name = "c"
                                            ,to_station_id = "i"
                                            ,to_station_name = "c"
                                            ,usertype = "c"
                                            ,gender = "c"
                                            ,birthyear = "i"))
trips_2019_q4 <- read_csv("Data sources/Divvy_Trips_2019_Q4.csv"
                             ,col_types = cols( trip_id = "i"
                                               ,bikeid = "i"
                                               ,from_station_id = "i"
                                               ,from_station_name = "c"
                                               ,to_station_id = "i"
                                               ,to_station_name = "c"
                                               ,usertype = "c"
                                               ,gender = "c"
                                               ,birthyear = "i"))
trips_2019 <- rbind(trips_2019_q1, trips_2019_q2, trips_2019_q3, trips_2019_q4)
                            
# data transformation and wrangling
trips_2019 <- select(trips_2019, -birthyear, -gender, -from_station_id, -to_station_id)
trips_2019$usertype[trips_2019$usertype == 'Subscriber'] <- "Member"
trips_2019$usertype[trips_2019$usertype == 'Customer'] <- "Casual"
trips_2019$start_time <- anytime(trips_2019$start_time)
trips_2019$day <- wday(trips_2019$start_time, label = TRUE, abbr = FALSE)
trips_2019$month <- month(trips_2019$start_time, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2019:", round(mean(trips_2019$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2019: 1450.2 seconds"
paste("The longest duration a rider used the bike in 2019 was", max(trips_2019$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2019 was 10628400 seconds"
paste("The most popular day of booking was", mfv(trips_2019$day), "in 2019")
[1] "The most popular day of booking was Thursday in 2019"
paste("The most popular month of booking was", mfv(trips_2019$month))
[1] "The most popular month of booking was August"
# creating a new dataframe
trips_2019_pivot <- trips_2019 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2019$start_time), .groups = 'drop')
trips_2019_pivot <- unique(trips_2019_pivot)

# pivot table
qhpvt(trips_2019, rows = 'day', columns = 'usertype', calculations = c("Average Ride Length" = "round(mean(tripduration), digits = 2)", "Number of rides" = "length(trip_id)"))

Data visualisation

# Number of riders in 2019
p1 <- ggplot(trips_2019, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = 'dodge') + scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) +
  labs(x = "Weekdays", y = "Number of Riders"
       ,title = " Divvy Bikes riders data"
       ,subtitle = "Year : 2019 (Weekly)" +
         scale_fill_discrete(name = "Type of Riders", labels = c("Casual Riders","Annual Member Riders")) +
theme(text = element_text(size = 10))) 

# Trip duration of riders in 2019
p2 <- ggplot(trips_2019, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2019)",
       subtitle = "The graph represents the total trip duration of riders everday of the week in 2019.") +
    theme(axis.text.x = element_text(angle = 45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Divvy bikes 2020 Dataset

# importing and combining all related datasets
trips_2020 <- rbind(read_csv("Data sources/Divvy_Trips_2020_Q1.csv"), read_csv("Data sources/202004-divvy-tripdata.csv"), read_csv("Data sources/202005-divvy-tripdata.csv"), read_csv("Data sources/202006-divvy-tripdata.csv"), read_csv("Data sources/202007-divvy-tripdata.csv"), read_csv("Data sources/202008-divvy-tripdata.csv"), read_csv("Data sources/202009-divvy-tripdata.csv"), read_csv("Data sources/202010-divvy-tripdata.csv"), read_csv("Data sources/202011-divvy-tripdata.csv"), read_csv("Data sources/202012-divvy-tripdata.csv"))

trips_2020 <- rename(trips_2020, trip_id = ride_id
                     ,start_time = started_at
                     ,end_time = ended_at
                     ,usertype = member_casual)
trips_2020 <- mutate(trips_2020, tripduration = abs(end_time - start_time))
                            
# data transformation and wrangling
trips_2020 <- select(trips_2020, -start_station_id, -end_station_id)
trips_2020$usertype[trips_2020$usertype == 'Subscriber'] <- "Member"
trips_2020$usertype[trips_2020$usertype == 'Customer'] <- "Casual"
trips_2020$start_time <- anytime(trips_2020$start_time)
trips_2020$day <- wday(trips_2020$start_time, label = TRUE, abbr = FALSE)
trips_2020$month <- month(trips_2020$start_time, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2020:", round(mean(trips_2020$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2020: 1856.56 seconds"
paste("The longest duration a rider used the bike in 2020 was", max(trips_2020$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2020 was 9387024 seconds"
paste("The most popular day of booking was", mfv(trips_2020$day), "in 2020")
[1] "The most popular day of booking was Saturday in 2020"
paste("The most popular month of booking was", mfv(trips_2020$month))
[1] "The most popular month of booking was August"
# creating a new dataframe
trips_2020_pivot <- trips_2020 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2020$start_time), .groups = 'drop')
trips_2020_pivot <- unique(trips_2020_pivot)

# pivot table
qhpvt(trips_2020, rows = 'day', columns = 'usertype', calculations = c("Average Ride Length" = "round(mean(as.integer(tripduration)), digits = 2)", "Number of rides" = "length(trip_id)"))

Data visualisation

# Number of riders in 2020
p1 <- ggplot(trips_2020, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = 'dodge') + scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) +
  labs(x = "Weekdays", y = "Number of Riders"
       ,title = " Divvy Bikes riders data"
       ,subtitle = "Year : 2020 (Weekly)" +
         scale_fill_discrete(name = "Type of Riders", labels = c("Casual","Member")) +
theme(text = element_text(size = 10))) 

# Trip duration of riders in 2020
p2 <- ggplot(trips_2020, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2020)",
       subtitle = "The graph represents the total trip duration of riders everday of the week in 2020.") +
    theme(axis.text.x = element_text(angle = 45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Divvy bikes 2020 Dataset

# importing and combining all related datasets
trips_2021 <- rbind(read_csv("Data sources/202101-divvy-tripdata.csv"), read_csv("Data sources/202102-divvy-tripdata.csv"), read_csv("Data sources/202103-divvy-tripdata.csv"), read_csv("Data sources/202104-divvy-tripdata.csv"), read_csv("Data sources/202105-divvy-tripdata.csv"), read_csv("Data sources/202106-divvy-tripdata.csv"), read_csv("Data sources/202107-divvy-tripdata.csv"), read_csv("Data sources/202108-divvy-tripdata.csv"), read_csv("Data sources/202109-divvy-tripdata.csv"), read_csv("Data sources/202110-divvy-tripdata.csv"))

trips_2021 <- rename(trips_2021, trip_id = ride_id
                     ,start_time = started_at
                     ,end_time = ended_at
                     ,usertype = member_casual)
trips_2021 <- mutate(trips_2021, tripduration = abs(end_time - start_time))
                            
# data transformation and wrangling
trips_2021 <- select(trips_2021, -start_station_id, -end_station_id)
trips_2021$usertype[trips_2021$usertype == 'Subscriber'] <- "Member"
trips_2021$usertype[trips_2021$usertype == 'Customer'] <- "Casual"
trips_2021$start_time <- anytime(trips_2021$start_time)
trips_2021$day <- wday(trips_2021$start_time, label = TRUE, abbr = FALSE)
trips_2021$month <- month(trips_2021$start_time, label = TRUE, abbr = FALSE)

Data Analysis

paste("The Average time riders spent riding bikes in 2021:", round(mean(trips_2021$tripduration), digits = 2), "seconds")
[1] "The Average time riders spent riding bikes in 2021: 1369.04 seconds"
paste("The longest duration a rider used the bike in 2021 was", max(trips_2021$tripduration), "seconds")
[1] "The longest duration a rider used the bike in 2021 was 3356649 seconds"
paste("The most popular day of booking was", mfv(trips_2021$day), "in 2021")
[1] "The most popular day of booking was Saturday in 2021"
paste("The most popular month of booking was", mfv(trips_2021$month))
[1] "The most popular month of booking was July"
# creating a new dataframe
trips_2021_pivot <- trips_2021 %>%
  group_by(usertype) %>%
  summarize("Average Ride Length" = round(mean(tripduration), digits = 2),
            "Number of Rides" = length(trip_id),
            "Year" = year(trips_2021$start_time), .groups = 'drop')
trips_2021_pivot <- unique(trips_2021_pivot)

# pivot table
qhpvt(trips_2021, rows = 'day', columns = 'usertype', calculations = c("Average Ride Length" = "round(mean(as.integer(tripduration)), digits = 2)", "Number of rides" = "length(trip_id)"))

Data visualisation

# Data Visualization
# Number of Riders in the year of 2021
p1 <- ggplot(trips_2021, mapping = aes(x = day, fill = usertype)) +
  geom_bar(position = "dodge")+ scale_y_continuous(labels = unit_format(unit = "K", scale = 1e-3)) + 
  labs(x = "Week Days", y = "Number of Riders", 
       title = "Divvy bikes riders data",
       subtitle = "Year: 2021 (Weekly)" ) +
  scale_fill_discrete(name = "Type of Riders", labels = c("Casual Riders","Member Riders")) +
theme(text = element_text(size = 10)) 

# Trip duration of riders in 2021
p2 <- ggplot(trips_2021, mapping = aes(x = day, y = tripduration)) + 
  geom_col() + facet_wrap(~usertype) + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Week Days", y = "Total Trip Duration (in Seconds)", 
       title = "Trip Duration of the Riders (Year: 2021)",
       subtitle = "The graph represents the total trip duration of riders on everday of the week in 2021.") +
    theme(axis.text.x = element_text(angle =45), text = element_text(size = 10))
fig(18, 15)
grid.arrange(p1, p2)

Conclusive study

# data combining
data <- rbind(trips_2013_pivot, trips_2014_pivot, trips_2015_pivot, trips_2016_pivot, trips_2017_pivot, trips_2018_pivot, trips_2019_pivot, trips_2020_pivot, trips_2021_pivot)

data <- as.data.frame(data)
data$usertype[data$usertype == 'casual'] <- "Casual"
data$usertype[data$usertype == 'member'] <- "Member"

# Data Visualization
# Average Ride Length of Riders from 2013 to 2021
p1 <- ggplot(data = data, aes(x = factor(Year), shape = usertype)) +
  geom_point(aes(y = `Average Ride Length`, color = usertype), size = 3.5) +
  labs(x = "Years", y = "Average Ride Length (in seconds)", 
       title = "Average Ride Length spent by Riders every year",
       subtitle = "The graph shows average length or time spent by the Casual Riders is significantly higher 
than Dependent and Annual Member Riders.")+
theme(text = element_text(size = 10)) 

# Number of Rides taken by Riders from 2013 to 2021
p2<- ggplot(data, mapping = aes(x = factor(Year), y = `Number of Rides`, fill = `usertype`)) +
  geom_bar(stat = 'identity') + scale_y_continuous(labels = unit_format(unit = "M", scale = 1e-6)) +
  labs(x = "Years", y = "Number of Rides", 
       title = "Number of Rides taken by Riders from 2013-2021",
       subtitle = "The graph shows that Annual Member Riders have taken more rides than Casual Riders.")+
theme(text = element_text(size = 10)) 
fig(18, 15)
grid.arrange(p1, p2)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCiMjIyBBYm91dCB0aGUgY29tcGFueQoKSW4gMjAxNiwgRGl2dnkgbGF1bmNoZWQgYSBzdWNjZXNzZnVsIGJpa2Utc2hhcmUgb2ZmZXJpbmcuIFNpbmNlIHRoZW4sIHRoZSBwcm9ncmFtIGhhcyBncm93biB0byBhIGZsZWV0IG9mIDU4MjQgYmljeWNsZXMgdGhhdCBhcmUgZ2VvdHJhY2tlZCBhbmQgbG9ja2VkIGludG8gYSBuZXR3b3JrIG9mIDY5MiBzdGF0aW9ucyBhY3Jvc3MgQ2hpY2Fnby4gVGhlIGJpa2VzIGNhbiBiZSB1bmxvY2tlZCBmcm9tIG9uZSBzdGF0aW9uIGFuZCByZXR1cm5lZCB0byBhbnkgb3RoZXIgc3RhdGlvbiBpbiB0aGUgc3lzdGVtIGFueXRpbWUuCgpDdXN0b21lcnMgd2hvIHB1cmNoYXNlIHNpbmdsZS1yaWRlIG9yIGZ1bGwtZGF5IHBhc3NlcyBhcmUgcmVmZXJyZWQgdG8gYXMgIkNhc3VhbCIgUmlkZXJzLgpDdXN0b21lcnMgd2hvIHB1cmNoYXNlIGFubnVhbCBtZW1iZXJzaGlwcyBhcmUgIk1lbWJlciIgUmlkZXJzLgoKIyMjIFRhc2sKClRoZSBwcmltYXJ5IG9iamVjdGl2ZSBpcyB0byBmaW5kIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gY2FzdWFsIHJpZGVycyBhbmQgbWVtYmVyIHJpZGVycywgaG93IHRoZXkgdXNlIHRoZSBEaXZ2eSAgYmlrZXMgZGlmZmVyZW50bHkuIE9uIHRoYXQgYmFzaXMsIHRoZSBjb21wYW55IHNoYWxsIGJ1aWxkIGEgbmV3IG1vZGVsIHdoaWNoIHdpbGwgYXR0cmFjdCBjYXN1YWwgcmlkZXJzIHRvIGVucm9sbCBmb3IgdGhlIGFubnVhbCBtZW1iZXJzaGlwLgoKIyMjIERhdGEgU291cmNlcwoKVGhlIGRhdGEgc2V0IGZyb20gdGhlIHllYXIgMjAxMy0yMDIxIGlzIHVzZWQgKHRoZSBkYXRhIGlzIGF2YWlsYWJsZSB0aWxsIE9jdG9iZXIsIDIwMjEpLiBUaGUgZGF0YSBwcm92aWRlcyBkZXRhaWxzIGFib3V0IGhvdyBjdXN0b21lcnMgYXJlIHVzaW5nIHRoZSBiaWN5Y2xlIHNlcnZpY2UuIFRoZSBkYXRhIGlzIHByb3ZpZGVkIGJ5IE1vdGl2YXRlIEludGVybmF0aW9uYWwgSW5jIHVuZGVyIHRoaXMgbGljZW5zZS4gZm9yIHB1YmxpYyB1c2UuIFRoZSBkYXRhIGlzIGRvd25sb2FkZWQgYW5kIG9yZ2FuaXplZCBpbiBmb2xkZXJzIGluIGFzY2VuZGluZyBvcmRlci4gVGhlIGRhdGEgcHJvdmlkZXMgdGhlIGRldGFpbHMgYWJvdXQgdGhlIHRyaXBzIGFuZCBzdGF0aW9ucyB1c2VkIGJ5IHRoZSBjdXN0b21lcnMgd2l0aCBzaW5nbGUgb3IgZnVsbC1kYXkgcGFzc2VzLCBhbmQgaW5kaXZpZHVhbHMgd2l0aCBhbm51YWwgbWVtYmVyc2hpcHMuICJDYXN1YWwgUmlkZXIiIGlzIGEgcmlkZXIgd2hvIHB1cmNoYXNlZCBzaW5nbGUgcmlkZSBvciAyNC1ob3VyIHBhc3MsIHdoZXJlYXMgIk1lbWJlciBSaWRlciIgaXMgYSByaWRlciB3aG8gcHVyY2hhc2VkIGFuIEFubnVhbCBNZW1iZXJzaGlwLgoKIyMjIExpYnJhcmllcyB1c2VkIGR1cmluZyB0aGUgY2FzZSBzdHVkeQoKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkgICAgICMgQ29sbGVjdGlvbiBvZiBSIHBhY2thZ2VzIGZvciBwcmVwYXJpbmcsIHdyYW5nbGluZyBhbmQgdmlzdWFsaXppbmcgZGF0YQpsaWJyYXJ5KHJlYWR4bCkgICAgICAgICMgcGFja2FnZSBmb3IgZXh0cmFjdGluZyBkYXRhIGZyb20gRXhjZWwKbGlicmFyeShsdWJyaWRhdGUpICAgICAjIE1ha2VzIGVhc2llciB0byBmb3JtYXQgZGF0ZXMKbGlicmFyeShtb2RlZXN0KSAgICAgICAjIHVzZWQgZm9yIG1vZGUgZXN0aW1hdGlvbiAKbGlicmFyeShwaXZvdHRhYmxlcikgICAjIENyZWF0ZXMgcGl2b3QgdGFibGVzCmxpYnJhcnkoc2NhbGVzKSAgICAgICAgIyBTY2FsZXMgZnVuY3Rpb25kcyBmb3IgdmlzdWFsaXNhdGlvbgpsaWJyYXJ5KGdyaWRFeHRyYSkgICAgICMgYXJyYW5nZSBtdWx0aXBsZSBncmlkLWJhc2VkIHBsb3RzIG9uIGEgcGFnZSwgYW5kIGRyYXcgdGFibGVzLgpsaWJyYXJ5KGFueXRpbWUpICAgICAgICMgZm9yIGNvbnZlcnRpbmcgdG8gZGF0ZXRpbWUgZm9ybWF0cy8KYGBgCgojIyMgSW1wb3J0aW5nIGFuZCBjb21iaW5pbmcgdGhlIGRhdGEgZmlsZXMKClRoZSBkYXRhIHNldHMgb2YgdGhlIHJlc3BlY3RpdmUgeWVhcnMgKDIwMTMtMjAyMSkgYXJlIGltcG9ydGVkIGFuZCBjb21iaW5lZCBpbnRvIG9uZSBmaWxlLiBUaGUgZGF0YSB0eXBlIG9mIGV2ZXJ5IGNvbHVtbiBpcyBzZXQgZHVyaW5nIGltcG9ydGluZyBwcm9jZXNzIHRvIGF2b2lkIGVycm9ycy4KCiMjIyBEYXRhIFRyYW5zZm9ybWF0aW9uIGFuZCBXcmFuZ2xpbmcKCkluIHNvbWUgcGFydHMgb2YgdGhlIGRhdGEgdGhlIGNvbHVtbiBuYW1lcyBhcmUgY29uc2lzdGVudC4gUmVuYW1pbmcgaXMgZG9uZSB0byBhdm9pZCBhbnkgbWlzdW5kZXJzdGFuZGluZyBkdXJpbmcgdGhlIGRhdGEgYW5hbHlzaXMgcHJvY2Vzcy4gVGhlIG5ldyBjb2x1bW5zIGFyZSBjcmVhdGVkIHRvIGdldCBmb3IgcHJvcGVyIHVuZGVyc3RhbmRpbmcgb2YgdGhlIGRhdGEuIFRoZSB1bm5lY2Vzc2FyeSBjb2x1bW5zIGFyZSBleGNsdWRlZCB0byBtYWtlIGRhdGEgbW9yZSBjb25zaXN0ZW50IGFuZCBleHRyYWN0IHRoZSBhbnN3ZXJzIHRvIHRoZSBidXNpbmVzcyBxdWVzdGlvbi4KCkltcHJvcGVyIGVudHJpZXMgbGlrZSBlbXB0eSBjZWxsLCBpbXByb3BlciBkYXRhIHR5cGUgb3IgZGF0YSBzdHJ1Y3R1cmUgYXJlIGV4Y2x1ZGVkIGR1cmluZyBkYXRhIGFuYWx5c2lzIHByb2Nlc3MuIE1pY3Jvc29mdCBFeGNlbCBpcyB1c2VkIGF0IHNvbWUgcG9pbnQgb2YgdHJhbnNmb3JtYXRpb24gbGlrZSByZW5hbWluZyBjb2x1bW4sIGZvcm1hdHRpbmcgZGF0ZXMuCgojIyMgRGF0YSBBbmFseXNpcwoKVGhlIGFuYWx5c2lzIGlzIGNhcnJpZWQgdG8gZ2V0IHRoZSBhbnN3ZXIgdG8gdGhlIGJ1c2luZXNzIHF1ZXN0aW9uLiBUbyBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgZGF0YSBzZXQsIHN0YXRpc3RpY2FsIGZvcm11bGFzIGFyZSB1c2VkIG9uIHRoZSBkYXRhIHNldCwgYW5kIHBpdm90IHRhYmxlcyBhcmUgZ2VuZXJhdGVkLiBGb3IgdW5kZXJzdGFuZGluZyB0aGUgcmlkZXIncyBiZWhhdmlvdXIgZHVyaW5nIHRoZSB5ZWFycywgdGhlIHZpc3VhbGl6YXRpb24gdG9vbCBpcyB1c2VkIHRvIGdldCB0aGUgb3ZlcmFsbCBwaWN0dXJlIG9mIHRoZSBkYXRhIHNldCBhbmQgZXhwbGFpbiB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIENhc3VhbCBSaWRlcnMgYW5kIEFubnVhbCBNZW1iZXIgUmlkZXJzLgoKIyBDeWNsaXN0aWMgQmlrZSBTaGFyZSAyMDEzIERhdGEgU2V0CmBgYHtyfQoKIyBJbXBvcnRpbmcgYW5kIENvbWJpbmluZyBhbGwgcmVsYXRlZCBkYXRhc2V0cwp0cmlwc18yMDEzIDwtIHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxMy5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHModHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdHJpcGR1cmF0aW9uID0gImQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGhkYXkgPSAiaSIpKQojIERhdGEgdHJhbnNmb3JtYXRpb24gJiB3cmFuZ2xpbmcKdHJpcHNfMjAxMyA8LSBzZWxlY3QodHJpcHNfMjAxMywgLWJpcnRoZGF5LCAtZ2VuZGVyLCAtZnJvbV9zdGF0aW9uX2lkLCAtdG9fc3RhdGlvbl9pZCkKdHJpcHNfMjAxMyR1c2VydHlwZVt0cmlwc18yMDEzJHVzZXJ0eXBlID09ICdDdXN0b21lciddIDwtICJDYXN1YWwiCnRyaXBzXzIwMTMkdXNlcnR5cGVbdHJpcHNfMjAxMyR1c2VydHlwZSA9PSAnU3Vic2NyaWJlciddIDwtICJNZW1iZXIiCnRyaXBzXzIwMTMkZGF5IDwtIHdkYXkodHJpcHNfMjAxMyRzdGFydHRpbWUsIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFKQp0cmlwc18yMDEzJG1vbnRoIDwtIG1vbnRoKHRyaXBzXzIwMTMkc3RhcnR0aW1lLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSkKYGBgCgojIyMgRGF0YSBBbmFseXNpcwpgYGB7cn0KcGFzdGUoIlRoZSBBdmVyYWdlIHRpbWUgcmlkZXJzIHNwZW50IHJpZGluZyBiaWtlcyBpbiAyMDEzOiIsIHJvdW5kKG1lYW4odHJpcHNfMjAxMyR0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIGxvbmdlc3QgZHVyYXRpb24gYSByaWRlciB1c2VkIHRoZSBiaWtlIGluIDIwMTMgd2FzIiwgbWF4KHRyaXBzXzIwMTMkdHJpcGR1cmF0aW9uKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIG1vc3QgcG9wdWxhciBkYXkgb2YgYm9va2luZyB3YXMiLCBtZnYodHJpcHNfMjAxMyRkYXkpLCAiaW4gMjAxMyIpCnBhc3RlKCJUaGUgbW9zdCBwb3B1bGFyIG1vbnRoIG9mIGJvb2tpbmcgd2FzIiwgbWZ2KHRyaXBzXzIwMTMkbW9udGgpKQoKI2dlbmVyYXRpbmcgbmV3IGRhdGEgZnJhbWUKdHJpcHNfMjAxM19waXZvdCA8LSB0cmlwc18yMDEzICU+JQogIGdyb3VwX2J5KHVzZXJ0eXBlKSAlPiUKICBzdW1tYXJpemUoIkF2ZXJhZ2UgUmlkZSBMZW5ndGgiID0gcm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgIk51bWJlciBvZiBSaWRlcyIgPSBsZW5ndGgodHJpcF9pZCksCiAgICAgICAgICAgICJZZWFyIiA9IHllYXIodHJpcHNfMjAxMyRzdGFydHRpbWUpLCAuZ3JvdXBzID0gJ2Ryb3AnKQp0cmlwc18yMDEzX3Bpdm90IDwtIHVuaXF1ZSh0cmlwc18yMDEzX3Bpdm90KQoKICAKI3Bpdm90IHRhYmxlCnFocHZ0KHRyaXBzXzIwMTMsIHJvd3MgPSAiZGF5IiwgY29sdW1ucyA9ICJ1c2VydHlwZSIsIGNhbGN1bGF0aW9ucyA9IGMoIkF2Z19yaWRlX2xlbmd0aCIgPSAicm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPTIpIiwgIm5vX29mX3JpZGVycyIgPSAibGVuZ3RoKHRyaXBfaWQpIikpCmBgYAojIyMgRGF0YSBWaXN1YWxpc2F0aW9uCmBgYHtyfQojZnVuY3Rpb24gdG8gc2V0IHBsb3Qgc2l6ZQpmaWcgPC0gZnVuY3Rpb24od2lkdGgsIGhlaWdodCl7CiAgb3B0aW9ucyhyZXByLnBsb3Qud2lkdGggPSB3aWR0aCwgcmVwci5wbG90LmhlaWdodCA9IGhlaWdodCkKfQoKYGBgCgpgYGB7cn0KcDEgPC0gZ2dwbG90KHRyaXBzXzIwMTMsIG1hcHBpbmcgPSBhZXMoeCA9IGRheSwgZmlsbCA9IHVzZXJ0eXBlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikrIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSB1bml0X2Zvcm1hdCh1bml0ID0gIksiLCBzY2FsZSA9IDFlLTMpKSArIAogIGxhYnMoeCA9ICJXZWVrIERheXMiLCB5ID0gIk51bWJlciBvZiBSaWRlcnMiLCAKICAgICAgIHRpdGxlID0gIkRpdnZ5IGJpa2VzIHJpZGVycyBkYXRhIiwKICAgICAgIHN1YnRpdGxlID0gIlllYXI6IDIwMTMgKFdlZWtseSkiKSsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiVHlwZSBvZiBSaWRlcnMiLCBsYWJlbHMgPSBjKCJDYXN1YWwgUmlkZXJzIiwgIk1lbWJlciBSaWRlcnMiKSkgKwp0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCmBgYApgYGB7cn0KIyBUcmlwIGR1cmF0aW9uIG9mIHJpZGVycyBpbiAyMDEzCnAyIDwtIGdncGxvdCh0cmlwc18yMDEzLCBtYXBwaW5nID0gYWVzKHggPSBkYXksIHkgPSB0cmlwZHVyYXRpb24pKSArIAogIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH51c2VydHlwZSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJNIiwgc2NhbGUgPSAxZS02KSkgKwogIGxhYnMoeCA9ICJXZWVrIERheXMiLCB5ID0gIlRvdGFsIFRyaXAgRHVyYXRpb24gKGluIFNlY29uZHMpIiwgCiAgICAgICB0aXRsZSA9ICJUcmlwIER1cmF0aW9uIG9mIHRoZSBSaWRlcnMgKFllYXI6IDIwMTMpIiwKICAgICAgIHN1YnRpdGxlID0gIlRoZSBncmFwaCByZXByZXNlbnRzIHRoZSB0b3RhbCB0cmlwIGR1cmF0aW9uIG9mIHJpZGVycyBvbiBldmVyZGF5IG9mIHRoZSB3ZWVrIGluIDIwMTMuIikgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPTQ1KSwgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQpmaWcoMTgsIDE1KQpncmlkLmFycmFuZ2UocDEsIHAyKQoKYGBgCiMgRGl2dnkgYmlrZXMgMjAxNCBkYXRhc2V0CmBgYHtyfQojIGltcG9ydGluZyAmIGNvbWJpbmluZyBhbGwgcmVsYXRlZCBkYXRhc2V0cwp0cmlwc18yMDE0IDwtIHJiaW5kKHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxNF9RMVEyLmNzdiIKICAgICAgICAgICAgICAgICAgICAgICAsY29sX3R5cGVzID0gY29scyh0cmlwX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpa2VpZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0cmlwZHVyYXRpb24gPSAiZCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKQogICAgICAgICAgICAgICAgICAgICxyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTQtUTMtMDcuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRyaXBkdXJhdGlvbiA9ICJkIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpcnRoeWVhciA9ICJpIikpCiAgICAgICAgICAgICAgICAgICAgLHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxNC1RMy0wODA5LmNzdiIKICAgICAgICAgICAgICAgICAgICAgICAsY29sX3R5cGVzID0gY29scyh0cmlwX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpa2VpZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0cmlwZHVyYXRpb24gPSAiZCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKQogICAgICAgICAgICAgICAgICAgICxyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTQtUTQuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRyaXBkdXJhdGlvbiA9ICJkIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpcnRoeWVhciA9ICJpIikpKQpgYGAKYGBge3J9CiMgRGF0YSB0cmFuc2Zvcm1hdGlvbiAmIHdyYW5nbGluZwp0cmlwc18yMDE0IDwtIHNlbGVjdCh0cmlwc18yMDE0LCAtYmlydGh5ZWFyLCAtZ2VuZGVyLCAtdG9fc3RhdGlvbl9pZCwgLWZyb21fc3RhdGlvbl9pZCkKdHJpcHNfMjAxNCRzdGFydF90aW1lIDwtIGFueXRpbWUodHJpcHNfMjAxNCRzdGFydHRpbWUpCnRyaXBzXzIwMTQkc3RhcnR0aW1lIDwtIG1keV9obXModHJpcHNfMjAxNCRzdGFydHRpbWUpCnRyaXBzXzIwMTQkc3RvcHRpbWUgPC0gbWR5X2htcyh0cmlwc18yMDE0JHN0b3B0aW1lKQp0cmlwc18yMDE0JGRheSA8LSB3ZGF5KHRyaXBzXzIwMTQkc3RhcnR0aW1lLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSkKdHJpcHNfMjAxNCR1c2VydHlwZVt0cmlwc18yMDE0JHVzZXJ0eXBlID09ICdDdXN0b21lciddIDwtICJDYXN1YWwiCnRyaXBzXzIwMTQkdXNlcnR5cGVbdHJpcHNfMjAxNCR1c2VydHlwZSA9PSAnU3Vic2NyaWJlciddIDwtICJNZW1iZXIiCnRyaXBzXzIwMTQkbW9udGggPC0gbW9udGgodHJpcHNfMjAxNCRzdGFydHRpbWUsIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFKQoKYGBgCgoKIyMjIERhdGEgQW5hbHlzaXMKYGBge3J9CnBhc3RlKCJUaGUgQXZlcmFnZSB0aW1lIHJpZGVycyBzcGVudCByaWRpbmcgYmlrZXMgaW4gMjAxNDoiLCByb3VuZChtZWFuKHRyaXBzXzIwMTQkdHJpcGR1cmF0aW9uKSwgZGlnaXRzID0gMiksICJzZWNvbmRzIikKcGFzdGUoIlRoZSBsb25nZXN0IGR1cmF0aW9uIGEgcmlkZXIgdXNlZCB0aGUgYmlrZSBpbiAyMDE0IHdhcyIsIG1heCh0cmlwc18yMDE0JHRyaXBkdXJhdGlvbiksICJzZWNvbmRzIikKcGFzdGUoIlRoZSBtb3N0IHBvcHVsYXIgZGF5IG9mIGJvb2tpbmcgd2FzIiwgbWZ2KHRyaXBzXzIwMTQkZGF5KSwgImluIDIwMTQiKQpwYXN0ZSgiVGhlIG1vc3QgcG9wdWxhciBtb250aCBvZiBib29raW5nIHdhcyIsIG1mdih0cmlwc18yMDE0JG1vbnRoKSkKCiNnZW5lcmF0aW5nIG5ldyBkYXRhIGZyYW1lCnRyaXBzXzIwMTRfcGl2b3QgPC0gdHJpcHNfMjAxNCAlPiUKICBncm91cF9ieSh1c2VydHlwZSkgJT4lCiAgc3VtbWFyaXplKCJBdmVyYWdlIFJpZGUgTGVuZ3RoIiA9IHJvdW5kKG1lYW4odHJpcGR1cmF0aW9uKSwgZGlnaXRzID0gMiksCiAgICAgICAgICAgICJOdW1iZXIgb2YgUmlkZXMiID0gbGVuZ3RoKHRyaXBfaWQpLAogICAgICAgICAgICAiWWVhciIgPSB5ZWFyKHRyaXBzXzIwMTQkc3RhcnR0aW1lKSwgLmdyb3VwcyA9ICdkcm9wJykKdHJpcHNfMjAxNF9waXZvdCA8LSB1bmlxdWUodHJpcHNfMjAxNF9waXZvdCkKCgojcGl2b3QgdGFibGUKcWhwdnQodHJpcHNfMjAxNCwgcm93cyA9ICJkYXkiLCBjb2x1bW5zID0gInVzZXJ0eXBlIiwgY2FsY3VsYXRpb25zID0gYygiQXZnX3JpZGVfbGVuZ3RoIiA9ICJyb3VuZChtZWFuKHRyaXBkdXJhdGlvbiksIGRpZ2l0cyA9MikiLCAibm9fb2ZfcmlkZXJzIiA9ICJsZW5ndGgodHJpcF9pZCkiKSkKYGBgCiMjIyBEYXRhIFZpc3VhbGlzYXRpb24KYGBge3J9CiNmdW5jdGlvbiB0byBzZXQgcGxvdCBzaXplCmZpZyA8LSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KXsKICBvcHRpb25zKHJlcHIucGxvdC53aWR0aCA9IHdpZHRoLCByZXByLnBsb3QuaGVpZ2h0ID0gaGVpZ2h0KQp9CgpgYGAKCmBgYHtyfQpwMSA8LSBnZ3Bsb3QodHJpcHNfMjAxNCwgbWFwcGluZyA9IGFlcyh4ID0gZGF5LCBmaWxsID0gdXNlcnR5cGUpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiKSsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHVuaXRfZm9ybWF0KHVuaXQgPSAiSyIsIHNjYWxlID0gMWUtMykpICsgCiAgbGFicyh4ID0gIldlZWsgRGF5cyIsIHkgPSAiTnVtYmVyIG9mIFJpZGVycyIsIAogICAgICAgdGl0bGUgPSAiRGl2dnkgYmlrZXMgcmlkZXJzIGRhdGEiLAogICAgICAgc3VidGl0bGUgPSAiWWVhcjogMjAxNCAoV2Vla2x5KSIpKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJUeXBlIG9mIFJpZGVycyIsIGxhYmVscyA9IGMoIkNhc3VhbCBSaWRlcnMiLCAiTWVtYmVyIFJpZGVycyIpKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQpgYGAKYGBge3J9CiMgVHJpcCBkdXJhdGlvbiBvZiByaWRlcnMgaW4gMjAxMwpwMiA8LSBnZ3Bsb3QodHJpcHNfMjAxNCwgbWFwcGluZyA9IGFlcyh4ID0gZGF5LCB5ID0gdHJpcGR1cmF0aW9uKSkgKyAKICBnZW9tX2NvbCgpICsgZmFjZXRfd3JhcCh+dXNlcnR5cGUpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHVuaXRfZm9ybWF0KHVuaXQgPSAiTSIsIHNjYWxlID0gMWUtNikpICsKICBsYWJzKHggPSAiV2VlayBEYXlzIiwgeSA9ICJUb3RhbCBUcmlwIER1cmF0aW9uIChpbiBTZWNvbmRzKSIsIAogICAgICAgdGl0bGUgPSAiVHJpcCBEdXJhdGlvbiBvZiB0aGUgUmlkZXJzIChZZWFyOiAyMDE0KSIsCiAgICAgICBzdWJ0aXRsZSA9ICJUaGUgZ3JhcGggcmVwcmVzZW50cyB0aGUgdG90YWwgdHJpcCBkdXJhdGlvbiBvZiByaWRlcnMgb24gZXZlcmRheSBvZiB0aGUgd2VlayBpbiAyMDEzLiIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9NDUpLCB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCmZpZygxOCwgMTUpCmdyaWQuYXJyYW5nZShwMSwgcDIpCgpgYGAKIyBEaXZ2eSBiaWtlcyAyMDE1IERhdGFzZXQKYGBge3J9CiMgaW1wb3J0aW5nIGFuZCBjb21iaW5pbmcgYWxsIHJlbGF0ZWQgZGF0YXNldHMKdHJpcHNfMjAxNSA8LSByYmluZChyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTUtUTEuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRyaXBkdXJhdGlvbiA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpcnRoeWVhciA9ICJpIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxNS1RMi5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHModHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdHJpcGR1cmF0aW9uID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAscmVhZF9jc3YoIkRhdGEgc291cmNlcy9EaXZ2eV9Ucmlwc18yMDE1XzA3LmNzdiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsY29sX3R5cGVzID0gY29scyh0cmlwX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpa2VpZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0cmlwZHVyYXRpb24gPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTVfMDguY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRyaXBkdXJhdGlvbiA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpcnRoeWVhciA9ICJpIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxNV8wOS5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHModHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdHJpcGR1cmF0aW9uID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAscmVhZF9jc3YoIkRhdGEgc291cmNlcy9EaXZ2eV9Ucmlwc18yMDE1X1E0LmNzdiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsY29sX3R5cGVzID0gY29scyh0cmlwX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpa2VpZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0cmlwZHVyYXRpb24gPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKSkKIyBkYXRhIHRyYW5zZm9ybWF0aW9uIGFuZCB3cmFuZ2xpbmcKdHJpcHNfMjAxNSA8LSBzZWxlY3QodHJpcHNfMjAxNSwgLWJpcnRoeWVhciwgLWdlbmRlciwgLWZyb21fc3RhdGlvbl9pZCwgLXRvX3N0YXRpb25faWQpCnRyaXBzXzIwMTUkdXNlcnR5cGVbdHJpcHNfMjAxNSR1c2VydHlwZSA9PSAnU3Vic2NyaWJlciddIDwtICJNZW1iZXIiCnRyaXBzXzIwMTUkdXNlcnR5cGVbdHJpcHNfMjAxNSR1c2VydHlwZSA9PSAnQ3VzdG9tZXInXSA8LSAiQ2FzdWFsIgp0cmlwc18yMDE1JHN0YXJ0dGltZSA8LSBhbnl0aW1lKHRyaXBzXzIwMTUkc3RhcnR0aW1lKQp0cmlwc18yMDE1JGRheSA8LSB3ZGF5KHRyaXBzXzIwMTUkc3RhcnR0aW1lLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSkKdHJpcHNfMjAxNSRtb250aCA8LSBtb250aCh0cmlwc18yMDE1JHN0YXJ0dGltZSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpCgoKYGBgCgojIyMgRGF0YSBBbmFseXNpcwpgYGB7cn0KcGFzdGUoIlRoZSBBdmVyYWdlIHRpbWUgcmlkZXJzIHNwZW50IHJpZGluZyBiaWtlcyBpbiAyMDE1OiIsIHJvdW5kKG1lYW4odHJpcHNfMjAxNSR0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIGxvbmdlc3QgZHVyYXRpb24gYSByaWRlciB1c2VkIHRoZSBiaWtlIGluIDIwMTUgd2FzIiwgbWF4KHRyaXBzXzIwMTUkdHJpcGR1cmF0aW9uKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIG1vc3QgcG9wdWxhciBkYXkgb2YgYm9va2luZyB3YXMiLCBtZnYodHJpcHNfMjAxNSRkYXkpLCAiaW4gMjAxNSIpCnBhc3RlKCJUaGUgbW9zdCBwb3B1bGFyIG1vbnRoIG9mIGJvb2tpbmcgd2FzIiwgbWZ2KHRyaXBzXzIwMTUkbW9udGgpKQoKIyBjcmVhdGluZyBhIG5ldyBkYXRhZnJhbWUKdHJpcHNfMjAxNV9waXZvdCA8LSB0cmlwc18yMDE1ICU+JQogIGdyb3VwX2J5KHVzZXJ0eXBlKSAlPiUKICBzdW1tYXJpemUoIkF2ZXJhZ2UgUmlkZSBMZW5ndGgiID0gcm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgIk51bWJlciBvZiBSaWRlcyIgPSBsZW5ndGgodHJpcF9pZCksCiAgICAgICAgICAgICJZZWFyIiA9IHllYXIodHJpcHNfMjAxNSRzdGFydHRpbWUpLCAuZ3JvdXBzID0gJ2Ryb3AnKQp0cmlwc18yMDE1X3Bpdm90IDwtIHVuaXF1ZSh0cmlwc18yMDE1X3Bpdm90KQoKIyBwaXZvdCB0YWJsZQpxaHB2dCh0cmlwc18yMDE1LCByb3dzID0gJ2RheScsIGNvbHVtbnMgPSAndXNlcnR5cGUnLCBjYWxjdWxhdGlvbnMgPSBjKCJBdmVyYWdlIFJpZGUgTGVuZ3RoIiA9ICJyb3VuZChtZWFuKHRyaXBkdXJhdGlvbiksIGRpZ2l0cyA9IDIpIiwgIk51bWJlciBvZiByaWRlcyIgPSAibGVuZ3RoKHRyaXBfaWQpIikpCmBgYAojIyMgRGF0YSB2aXN1YWxpc2F0aW9uIApgYGB7cn0KIyBOdW1iZXIgb2YgcmlkZXJzIGluIDIwMTUKcDEgPC0gZ2dwbG90KHRyaXBzXzIwMTUsIG1hcHBpbmcgPSBhZXMoeCA9IGRheSwgZmlsbCA9IHVzZXJ0eXBlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gJ2RvZGdlJykgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zKSkgKwogIGxhYnMoeCA9ICJXZWVrZGF5cyIsIHkgPSAiTnVtYmVyIG9mIFJpZGVycyIKICAgICAgICx0aXRsZSA9ICIgRGl2dnkgQmlrZXMgcmlkZXJzIGRhdGEiCiAgICAgICAsc3VidGl0bGUgPSAiWWVhciA6IDIwMTUgKFdlZWtseSkiICsKICAgICAgICAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIlR5cGUgb2YgUmlkZXJzIiwgbGFiZWxzID0gYygiQ2FzdWFsIFJpZGVycyIsIkFubnVhbCBNZW1iZXIgUmlkZXJzIiAsIkRlcGVuZGVudCIpKSArCnRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkpIAoKIyBUcmlwIGR1cmF0aW9uIG9mIHJpZGVycyBpbiAyMDE1CnAyIDwtIGdncGxvdCh0cmlwc18yMDE1LCBtYXBwaW5nID0gYWVzKHggPSBkYXksIHkgPSB0cmlwZHVyYXRpb24pKSArIAogIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH51c2VydHlwZSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJNIiwgc2NhbGUgPSAxZS02KSkgKwogIGxhYnMoeCA9ICJXZWVrIERheXMiLCB5ID0gIlRvdGFsIFRyaXAgRHVyYXRpb24gKGluIFNlY29uZHMpIiwgCiAgICAgICB0aXRsZSA9ICJUcmlwIER1cmF0aW9uIG9mIHRoZSBSaWRlcnMgKFllYXI6IDIwMTUpIiwKICAgICAgIHN1YnRpdGxlID0gIlRoZSBncmFwaCByZXByZXNlbnRzIHRoZSB0b3RhbCB0cmlwIGR1cmF0aW9uIG9mIHJpZGVycyBvbiBldmVyZGF5IG9mIHRoZSB3ZWVrIGluIDIwMTUuIikgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPTQ1KSwgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQpmaWcoMTgsIDE1KQpncmlkLmFycmFuZ2UocDEsIHAyKQpgYGAKIyBEaXZ2eSBiaWtlcyAyMDE2IERhdGFzZXQKYGBge3J9CiMgaW1wb3J0aW5nIGFuZCBjb21iaW5pbmcgYWxsIHJlbGF0ZWQgZGF0YXNldHMKdHJpcHNfMjAxNiA8LSByYmluZChyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTZfUTEuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRyaXBkdXJhdGlvbiA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpcnRoeWVhciA9ICJpIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxNl8wNC5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHModHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdHJpcGR1cmF0aW9uID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAscmVhZF9jc3YoIkRhdGEgc291cmNlcy9EaXZ2eV9Ucmlwc18yMDE2XzA1LmNzdiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsY29sX3R5cGVzID0gY29scyh0cmlwX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpa2VpZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0cmlwZHVyYXRpb24gPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTZfMDYuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRyaXBkdXJhdGlvbiA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpcnRoeWVhciA9ICJpIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxNl9RMy5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHModHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdHJpcGR1cmF0aW9uID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAscmVhZF9jc3YoIkRhdGEgc291cmNlcy9EaXZ2eV9Ucmlwc18yMDE2X1E0LmNzdiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsY29sX3R5cGVzID0gY29scyh0cmlwX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpa2VpZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0cmlwZHVyYXRpb24gPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKSkKIyBkYXRhIHRyYW5zZm9ybWF0aW9uIGFuZCB3cmFuZ2xpbmcKdHJpcHNfMjAxNiA8LSBzZWxlY3QodHJpcHNfMjAxNiwgLWJpcnRoeWVhciwgLWdlbmRlciwgLWZyb21fc3RhdGlvbl9pZCwgLXRvX3N0YXRpb25faWQpCnRyaXBzXzIwMTYkdXNlcnR5cGVbdHJpcHNfMjAxNiR1c2VydHlwZSA9PSAnU3Vic2NyaWJlciddIDwtICJNZW1iZXIiCnRyaXBzXzIwMTYkdXNlcnR5cGVbdHJpcHNfMjAxNiR1c2VydHlwZSA9PSAnQ3VzdG9tZXInXSA8LSAiQ2FzdWFsIgp0cmlwc18yMDE2JHN0YXJ0dGltZSA8LSBhbnl0aW1lKHRyaXBzXzIwMTYkc3RhcnR0aW1lKQp0cmlwc18yMDE2JGRheSA8LSB3ZGF5KHRyaXBzXzIwMTYkc3RhcnR0aW1lLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSkKdHJpcHNfMjAxNiRtb250aCA8LSBtb250aCh0cmlwc18yMDE2JHN0YXJ0dGltZSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpCgoKYGBgCgojIyMgRGF0YSBBbmFseXNpcwpgYGB7cn0KcGFzdGUoIlRoZSBBdmVyYWdlIHRpbWUgcmlkZXJzIHNwZW50IHJpZGluZyBiaWtlcyBpbiAyMDE2OiIsIHJvdW5kKG1lYW4odHJpcHNfMjAxNiR0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIGxvbmdlc3QgZHVyYXRpb24gYSByaWRlciB1c2VkIHRoZSBiaWtlIGluIDIwMTYgd2FzIiwgbWF4KHRyaXBzXzIwMTYkdHJpcGR1cmF0aW9uKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIG1vc3QgcG9wdWxhciBkYXkgb2YgYm9va2luZyB3YXMiLCBtZnYodHJpcHNfMjAxNiRkYXkpLCAiaW4gMjAxNiIpCnBhc3RlKCJUaGUgbW9zdCBwb3B1bGFyIG1vbnRoIG9mIGJvb2tpbmcgd2FzIiwgbWZ2KHRyaXBzXzIwMTYkbW9udGgpKQoKIyBjcmVhdGluZyBhIG5ldyBkYXRhZnJhbWUKdHJpcHNfMjAxNl9waXZvdCA8LSB0cmlwc18yMDE2ICU+JQogIGdyb3VwX2J5KHVzZXJ0eXBlKSAlPiUKICBzdW1tYXJpemUoIkF2ZXJhZ2UgUmlkZSBMZW5ndGgiID0gcm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgIk51bWJlciBvZiBSaWRlcyIgPSBsZW5ndGgodHJpcF9pZCksCiAgICAgICAgICAgICJZZWFyIiA9IHllYXIodHJpcHNfMjAxNiRzdGFydHRpbWUpLCAuZ3JvdXBzID0gJ2Ryb3AnKQp0cmlwc18yMDE2X3Bpdm90IDwtIHVuaXF1ZSh0cmlwc18yMDE2X3Bpdm90KQoKIyBwaXZvdCB0YWJsZQpxaHB2dCh0cmlwc18yMDE2LCByb3dzID0gJ2RheScsIGNvbHVtbnMgPSAndXNlcnR5cGUnLCBjYWxjdWxhdGlvbnMgPSBjKCJBdmVyYWdlIFJpZGUgTGVuZ3RoIiA9ICJyb3VuZChtZWFuKHRyaXBkdXJhdGlvbiksIGRpZ2l0cyA9IDIpIiwgIk51bWJlciBvZiByaWRlcyIgPSAibGVuZ3RoKHRyaXBfaWQpIikpCmBgYAojIyMgRGF0YSB2aXN1YWxpc2F0aW9uIApgYGB7cn0KIyBOdW1iZXIgb2YgcmlkZXJzIGluIDIwMTYKcDEgPC0gZ2dwbG90KHRyaXBzXzIwMTYsIG1hcHBpbmcgPSBhZXMoeCA9IGRheSwgZmlsbCA9IHVzZXJ0eXBlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gJ2RvZGdlJykgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zKSkgKwogIGxhYnMoeCA9ICJXZWVrZGF5cyIsIHkgPSAiTnVtYmVyIG9mIFJpZGVycyIKICAgICAgICx0aXRsZSA9ICIgRGl2dnkgQmlrZXMgcmlkZXJzIGRhdGEiCiAgICAgICAsc3VidGl0bGUgPSAiWWVhciA6IDIwMTYgKFdlZWtseSkiICsKICAgICAgICAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIlR5cGUgb2YgUmlkZXJzIiwgbGFiZWxzID0gYygiQ2FzdWFsIFJpZGVycyIsIkFubnVhbCBNZW1iZXIgUmlkZXJzIiAsIkRlcGVuZGVudCIpKSArCnRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkpIAoKIyBUcmlwIGR1cmF0aW9uIG9mIHJpZGVycyBpbiAyMDE3CnAyIDwtIGdncGxvdCh0cmlwc18yMDE2LCBtYXBwaW5nID0gYWVzKHggPSBkYXksIHkgPSB0cmlwZHVyYXRpb24pKSArIAogIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH51c2VydHlwZSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJNIiwgc2NhbGUgPSAxZS02KSkgKwogIGxhYnMoeCA9ICJXZWVrIERheXMiLCB5ID0gIlRvdGFsIFRyaXAgRHVyYXRpb24gKGluIFNlY29uZHMpIiwgCiAgICAgICB0aXRsZSA9ICJUcmlwIER1cmF0aW9uIG9mIHRoZSBSaWRlcnMgKFllYXI6IDIwMTYpIiwKICAgICAgIHN1YnRpdGxlID0gIlRoZSBncmFwaCByZXByZXNlbnRzIHRoZSB0b3RhbCB0cmlwIGR1cmF0aW9uIG9mIHJpZGVycyBldmVyZGF5IG9mIHRoZSB3ZWVrIGluIDIwMTYuIikgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPTQ1KSwgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQpmaWcoMTgsIDE1KQpncmlkLmFycmFuZ2UocDEsIHAyKQpgYGAKCgojIERpdnZ5IGJpa2VzIDIwMTcgRGF0YXNldApgYGB7cn0KIyBpbXBvcnRpbmcgYW5kIGNvbWJpbmluZyBhbGwgcmVsYXRlZCBkYXRhc2V0cwp0cmlwc18yMDE3IDwtIHJiaW5kKHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxN19RMS5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHModHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdHJpcGR1cmF0aW9uID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAscmVhZF9jc3YoIkRhdGEgc291cmNlcy9EaXZ2eV9Ucmlwc18yMDE3X1EyLmNzdiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsY29sX3R5cGVzID0gY29scyh0cmlwX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpa2VpZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0cmlwZHVyYXRpb24gPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTdfUTMuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRyaXBkdXJhdGlvbiA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpcnRoeWVhciA9ICJpIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxN19RNC5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHModHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdHJpcGR1cmF0aW9uID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKIyBkYXRhIHRyYW5zZm9ybWF0aW9uIGFuZCB3cmFuZ2xpbmcKdHJpcHNfMjAxNyA8LSBzZWxlY3QodHJpcHNfMjAxNywgIC1mcm9tX3N0YXRpb25faWQsIC10b19zdGF0aW9uX2lkKQp0cmlwc18yMDE3JHVzZXJ0eXBlW3RyaXBzXzIwMTckdXNlcnR5cGUgPT0gJ1N1YnNjcmliZXInXSA8LSAiTWVtYmVyIgp0cmlwc18yMDE3JHVzZXJ0eXBlW3RyaXBzXzIwMTckdXNlcnR5cGUgPT0gJ0N1c3RvbWVyJ10gPC0gIkNhc3VhbCIKdHJpcHNfMjAxNyRzdGFydF90aW1lIDwtIGFueXRpbWUodHJpcHNfMjAxNyRzdGFydF90aW1lKQp0cmlwc18yMDE3JGRheSA8LSB3ZGF5KHRyaXBzXzIwMTckc3RhcnRfdGltZSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpCnRyaXBzXzIwMTckbW9udGggPC0gbW9udGgodHJpcHNfMjAxNyRzdGFydF90aW1lLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSkKCgpgYGAKCiMjIyBEYXRhIEFuYWx5c2lzCmBgYHtyfQpwYXN0ZSgiVGhlIEF2ZXJhZ2UgdGltZSByaWRlcnMgc3BlbnQgcmlkaW5nIGJpa2VzIGluIDIwMTc6Iiwgcm91bmQobWVhbih0cmlwc18yMDE3JHRyaXBkdXJhdGlvbiksIGRpZ2l0cyA9IDIpLCAic2Vjb25kcyIpCnBhc3RlKCJUaGUgbG9uZ2VzdCBkdXJhdGlvbiBhIHJpZGVyIHVzZWQgdGhlIGJpa2UgaW4gMjAxNyB3YXMiLCBtYXgodHJpcHNfMjAxNyR0cmlwZHVyYXRpb24pLCAic2Vjb25kcyIpCnBhc3RlKCJUaGUgbW9zdCBwb3B1bGFyIGRheSBvZiBib29raW5nIHdhcyIsIG1mdih0cmlwc18yMDE3JGRheSksICJpbiAyMDE3IikKcGFzdGUoIlRoZSBtb3N0IHBvcHVsYXIgbW9udGggb2YgYm9va2luZyB3YXMiLCBtZnYodHJpcHNfMjAxNyRtb250aCkpCgojIGNyZWF0aW5nIGEgbmV3IGRhdGFmcmFtZQp0cmlwc18yMDE3X3Bpdm90IDwtIHRyaXBzXzIwMTcgJT4lCiAgZ3JvdXBfYnkodXNlcnR5cGUpICU+JQogIHN1bW1hcml6ZSgiQXZlcmFnZSBSaWRlIExlbmd0aCIgPSByb3VuZChtZWFuKHRyaXBkdXJhdGlvbiksIGRpZ2l0cyA9IDIpLAogICAgICAgICAgICAiTnVtYmVyIG9mIFJpZGVzIiA9IGxlbmd0aCh0cmlwX2lkKSwKICAgICAgICAgICAgIlllYXIiID0geWVhcih0cmlwc18yMDE3JHN0YXJ0X3RpbWUpLCAuZ3JvdXBzID0gJ2Ryb3AnKQp0cmlwc18yMDE3X3Bpdm90IDwtIHVuaXF1ZSh0cmlwc18yMDE3X3Bpdm90KQoKIyBwaXZvdCB0YWJsZQpxaHB2dCh0cmlwc18yMDE3LCByb3dzID0gJ2RheScsIGNvbHVtbnMgPSAndXNlcnR5cGUnLCBjYWxjdWxhdGlvbnMgPSBjKCJBdmVyYWdlIFJpZGUgTGVuZ3RoIiA9ICJyb3VuZChtZWFuKHRyaXBkdXJhdGlvbiksIGRpZ2l0cyA9IDIpIiwgIk51bWJlciBvZiByaWRlcyIgPSAibGVuZ3RoKHRyaXBfaWQpIikpCmBgYAojIyMgRGF0YSB2aXN1YWxpc2F0aW9uIApgYGB7cn0KIyBOdW1iZXIgb2YgcmlkZXJzIGluIDIwMTcKcDEgPC0gZ2dwbG90KHRyaXBzXzIwMTcsIG1hcHBpbmcgPSBhZXMoeCA9IGRheSwgZmlsbCA9IHVzZXJ0eXBlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gJ2RvZGdlJykgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zKSkgKwogIGxhYnMoeCA9ICJXZWVrZGF5cyIsIHkgPSAiTnVtYmVyIG9mIFJpZGVycyIKICAgICAgICx0aXRsZSA9ICIgRGl2dnkgQmlrZXMgcmlkZXJzIGRhdGEiCiAgICAgICAsc3VidGl0bGUgPSAiWWVhciA6IDIwMTcgKFdlZWtseSkiICsKICAgICAgICAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIlR5cGUgb2YgUmlkZXJzIiwgbGFiZWxzID0gYygiQ2FzdWFsIFJpZGVycyIsIkFubnVhbCBNZW1iZXIgUmlkZXJzIiAsIkRlcGVuZGVudCIpKSArCnRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkpIAoKIyBUcmlwIGR1cmF0aW9uIG9mIHJpZGVycyBpbiAyMDE3CnAyIDwtIGdncGxvdCh0cmlwc18yMDE3LCBtYXBwaW5nID0gYWVzKHggPSBkYXksIHkgPSB0cmlwZHVyYXRpb24pKSArIAogIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH51c2VydHlwZSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJNIiwgc2NhbGUgPSAxZS02KSkgKwogIGxhYnMoeCA9ICJXZWVrIERheXMiLCB5ID0gIlRvdGFsIFRyaXAgRHVyYXRpb24gKGluIFNlY29uZHMpIiwgCiAgICAgICB0aXRsZSA9ICJUcmlwIER1cmF0aW9uIG9mIHRoZSBSaWRlcnMgKFllYXI6IDIwMTcpIiwKICAgICAgIHN1YnRpdGxlID0gIlRoZSBncmFwaCByZXByZXNlbnRzIHRoZSB0b3RhbCB0cmlwIGR1cmF0aW9uIG9mIHJpZGVycyBldmVyZGF5IG9mIHRoZSB3ZWVrIGluIDIwMTcuIikgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPTQ1KSwgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQpmaWcoMTgsIDE1KQpncmlkLmFycmFuZ2UocDEsIHAyKQpgYGAKIyBEaXZ2eSBiaWtlcyAyMDE4IERhdGFzZXQKYGBge3J9CiMgaW1wb3J0aW5nIGFuZCBjb21iaW5pbmcgYWxsIHJlbGF0ZWQgZGF0YXNldHMKdHJpcHNfMjAxOF9xMSA8LSByZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMThfUTEuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKCcwMSAtIFJlbnRhbCBEZXRhaWxzIFJlbnRhbCBJRCcgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJzAxIC0gUmVudGFsIERldGFpbHMgQmlrZSBJRCcgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJzAzIC0gUmVudGFsIFN0YXJ0IFN0YXRpb24gSUQnID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCcwMyAtIFJlbnRhbCBTdGFydCBTdGF0aW9uIE5hbWUnID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCcwMiAtIFJlbnRhbCBFbmQgU3RhdGlvbiBJRCcgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJzAyIC0gUmVudGFsIEVuZCBTdGF0aW9uIE5hbWUnID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCdVc2VyIFR5cGUnID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCdNZW1iZXIgR2VuZGVyJyA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwnMDUgLSBNZW1iZXIgRGV0YWlscyBNZW1iZXIgQmlydGhkYXkgWWVhcicgPSAiaSIpKQp0cmlwc18yMDE4X3ExIDwtIHJlbmFtZSh0cmlwc18yMDE4X3ExLCB0cmlwX2lkID0gYDAxIC0gUmVudGFsIERldGFpbHMgUmVudGFsIElEYAogICAgICAgICAgICAgICAgICAgICAgICAsc3RhcnRfdGltZSA9IGAwMSAtIFJlbnRhbCBEZXRhaWxzIExvY2FsIFN0YXJ0IFRpbWVgCiAgICAgICAgICAgICAgICAgICAgICAgICxlbmRfdGltZSA9IGAwMSAtIFJlbnRhbCBEZXRhaWxzIExvY2FsIEVuZCBUaW1lYAogICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gYDAxIC0gUmVudGFsIERldGFpbHMgQmlrZSBJRGAKICAgICAgICAgICAgICAgICAgICAgICAgLHRyaXBkdXJhdGlvbiA9IGAwMSAtIFJlbnRhbCBEZXRhaWxzIER1cmF0aW9uIEluIFNlY29uZHMgVW5jYXBwZWRgCiAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSBgMDMgLSBSZW50YWwgU3RhcnQgU3RhdGlvbiBJRGAKICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gYDAzIC0gUmVudGFsIFN0YXJ0IFN0YXRpb24gTmFtZWAKICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSBgMDIgLSBSZW50YWwgRW5kIFN0YXRpb24gSURgCiAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSBgMDIgLSBSZW50YWwgRW5kIFN0YXRpb24gTmFtZWAKICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gYFVzZXIgVHlwZWAKICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9IGBNZW1iZXIgR2VuZGVyYAogICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gYDA1IC0gTWVtYmVyIERldGFpbHMgTWVtYmVyIEJpcnRoZGF5IFllYXJgKQp0cmlwc18yMDE4X3EycTNxNDwtIHJiaW5kKHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxOF9RMi5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHModHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMThfUTMuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAscmVhZF9jc3YoIkRhdGEgc291cmNlcy9EaXZ2eV9Ucmlwc18yMDE4X1E0LmNzdiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsY29sX3R5cGVzID0gY29scyggdHJpcF9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9uYW1lID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGdlbmRlciA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSAiaSIpKSkKdHJpcHNfMjAxOCA8LSByYmluZCh0cmlwc18yMDE4X3ExLCB0cmlwc18yMDE4X3EycTNxNCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAojIGRhdGEgdHJhbnNmb3JtYXRpb24gYW5kIHdyYW5nbGluZwp0cmlwc18yMDE4IDwtIHNlbGVjdCh0cmlwc18yMDE4LCAtYmlydGh5ZWFyLCAtZ2VuZGVyLCAtZnJvbV9zdGF0aW9uX2lkLCAtdG9fc3RhdGlvbl9pZCkKdHJpcHNfMjAxOCR1c2VydHlwZVt0cmlwc18yMDE4JHVzZXJ0eXBlID09ICdTdWJzY3JpYmVyJ10gPC0gIk1lbWJlciIKdHJpcHNfMjAxOCR1c2VydHlwZVt0cmlwc18yMDE4JHVzZXJ0eXBlID09ICdDdXN0b21lciddIDwtICJDYXN1YWwiCnRyaXBzXzIwMTgkc3RhcnRfdGltZSA8LSBhbnl0aW1lKHRyaXBzXzIwMTgkc3RhcnRfdGltZSkKdHJpcHNfMjAxOCRkYXkgPC0gd2RheSh0cmlwc18yMDE4JHN0YXJ0X3RpbWUsIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFKQp0cmlwc18yMDE4JG1vbnRoIDwtIG1vbnRoKHRyaXBzXzIwMTgkc3RhcnRfdGltZSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpCgoKYGBgCgojIyMgRGF0YSBBbmFseXNpcwpgYGB7cn0KcGFzdGUoIlRoZSBBdmVyYWdlIHRpbWUgcmlkZXJzIHNwZW50IHJpZGluZyBiaWtlcyBpbiAyMDE4OiIsIHJvdW5kKG1lYW4odHJpcHNfMjAxOCR0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIGxvbmdlc3QgZHVyYXRpb24gYSByaWRlciB1c2VkIHRoZSBiaWtlIGluIDIwMTggd2FzIiwgbWF4KHRyaXBzXzIwMTgkdHJpcGR1cmF0aW9uKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIG1vc3QgcG9wdWxhciBkYXkgb2YgYm9va2luZyB3YXMiLCBtZnYodHJpcHNfMjAxOCRkYXkpLCAiaW4gMjAxOCIpCnBhc3RlKCJUaGUgbW9zdCBwb3B1bGFyIG1vbnRoIG9mIGJvb2tpbmcgd2FzIiwgbWZ2KHRyaXBzXzIwMTgkbW9udGgpKQoKIyBjcmVhdGluZyBhIG5ldyBkYXRhZnJhbWUKdHJpcHNfMjAxOF9waXZvdCA8LSB0cmlwc18yMDE4ICU+JQogIGdyb3VwX2J5KHVzZXJ0eXBlKSAlPiUKICBzdW1tYXJpemUoIkF2ZXJhZ2UgUmlkZSBMZW5ndGgiID0gcm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgIk51bWJlciBvZiBSaWRlcyIgPSBsZW5ndGgodHJpcF9pZCksCiAgICAgICAgICAgICJZZWFyIiA9IHllYXIodHJpcHNfMjAxOCRzdGFydF90aW1lKSwgLmdyb3VwcyA9ICdkcm9wJykKdHJpcHNfMjAxOF9waXZvdCA8LSB1bmlxdWUodHJpcHNfMjAxOF9waXZvdCkKCiMgcGl2b3QgdGFibGUKcWhwdnQodHJpcHNfMjAxOCwgcm93cyA9ICdkYXknLCBjb2x1bW5zID0gJ3VzZXJ0eXBlJywgY2FsY3VsYXRpb25zID0gYygiQXZlcmFnZSBSaWRlIExlbmd0aCIgPSAicm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSIsICJOdW1iZXIgb2YgcmlkZXMiID0gImxlbmd0aCh0cmlwX2lkKSIpKQpgYGAKIyMjIERhdGEgdmlzdWFsaXNhdGlvbiAKYGBge3J9CiMgTnVtYmVyIG9mIHJpZGVycyBpbiAyMDE4CnAxIDwtIGdncGxvdCh0cmlwc18yMDE4LCBtYXBwaW5nID0gYWVzKHggPSBkYXksIGZpbGwgPSB1c2VydHlwZSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICdkb2RnZScpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHVuaXRfZm9ybWF0KHVuaXQgPSAiSyIsIHNjYWxlID0gMWUtMykpICsKICBsYWJzKHggPSAiV2Vla2RheXMiLCB5ID0gIk51bWJlciBvZiBSaWRlcnMiCiAgICAgICAsdGl0bGUgPSAiIERpdnZ5IEJpa2VzIHJpZGVycyBkYXRhIgogICAgICAgLHN1YnRpdGxlID0gIlllYXIgOiAyMDE4IChXZWVrbHkpIiArCiAgICAgICAgIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJUeXBlIG9mIFJpZGVycyIsIGxhYmVscyA9IGMoIkNhc3VhbCBSaWRlcnMiLCJBbm51YWwgTWVtYmVyIFJpZGVycyIpKSArCnRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkpIAoKIyBUcmlwIGR1cmF0aW9uIG9mIHJpZGVycyBpbiAyMDE4CnAyIDwtIGdncGxvdCh0cmlwc18yMDE4LCBtYXBwaW5nID0gYWVzKHggPSBkYXksIHkgPSB0cmlwZHVyYXRpb24pKSArIAogIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH51c2VydHlwZSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJNIiwgc2NhbGUgPSAxZS02KSkgKwogIGxhYnMoeCA9ICJXZWVrIERheXMiLCB5ID0gIlRvdGFsIFRyaXAgRHVyYXRpb24gKGluIFNlY29uZHMpIiwgCiAgICAgICB0aXRsZSA9ICJUcmlwIER1cmF0aW9uIG9mIHRoZSBSaWRlcnMgKFllYXI6IDIwMTgpIiwKICAgICAgIHN1YnRpdGxlID0gIlRoZSBncmFwaCByZXByZXNlbnRzIHRoZSB0b3RhbCB0cmlwIGR1cmF0aW9uIG9mIHJpZGVycyBldmVyZGF5IG9mIHRoZSB3ZWVrIGluIDIwMTguIikgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSksIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKZmlnKDE4LCAxNSkKZ3JpZC5hcnJhbmdlKHAxLCBwMikKCmBgYAojIERpdnZ5IGJpa2VzIDIwMTkgRGF0YXNldApgYGB7cn0KIyBpbXBvcnRpbmcgYW5kIGNvbWJpbmluZyBhbGwgcmVsYXRlZCBkYXRhc2V0cwp0cmlwc18yMDE5X3EyIDwtIHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvRGl2dnlfVHJpcHNfMjAxOV9RMi5jc3YiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGNvbF90eXBlcyA9IGNvbHMoJzAxIC0gUmVudGFsIERldGFpbHMgUmVudGFsIElEJyA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwnMDEgLSBSZW50YWwgRGV0YWlscyBCaWtlIElEJyA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwnMDMgLSBSZW50YWwgU3RhcnQgU3RhdGlvbiBJRCcgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJzAzIC0gUmVudGFsIFN0YXJ0IFN0YXRpb24gTmFtZScgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJzAyIC0gUmVudGFsIEVuZCBTdGF0aW9uIElEJyA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwnMDIgLSBSZW50YWwgRW5kIFN0YXRpb24gTmFtZScgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJ1VzZXIgVHlwZScgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsJ01lbWJlciBHZW5kZXInID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCcwNSAtIE1lbWJlciBEZXRhaWxzIE1lbWJlciBCaXJ0aGRheSBZZWFyJyA9ICJpIikpCnRyaXBzXzIwMTlfcTIgPC0gcmVuYW1lKHRyaXBzXzIwMTlfcTIsIHRyaXBfaWQgPSBgMDEgLSBSZW50YWwgRGV0YWlscyBSZW50YWwgSURgCiAgICAgICAgICAgICAgICAgICAgICAgICxzdGFydF90aW1lID0gYDAxIC0gUmVudGFsIERldGFpbHMgTG9jYWwgU3RhcnQgVGltZWAKICAgICAgICAgICAgICAgICAgICAgICAgLGVuZF90aW1lID0gYDAxIC0gUmVudGFsIERldGFpbHMgTG9jYWwgRW5kIFRpbWVgCiAgICAgICAgICAgICAgICAgICAgICAgICxiaWtlaWQgPSBgMDEgLSBSZW50YWwgRGV0YWlscyBCaWtlIElEYAogICAgICAgICAgICAgICAgICAgICAgICAsdHJpcGR1cmF0aW9uID0gYDAxIC0gUmVudGFsIERldGFpbHMgRHVyYXRpb24gSW4gU2Vjb25kcyBVbmNhcHBlZGAKICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9IGAwMyAtIFJlbnRhbCBTdGFydCBTdGF0aW9uIElEYAogICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSBgMDMgLSBSZW50YWwgU3RhcnQgU3RhdGlvbiBOYW1lYAogICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9IGAwMiAtIFJlbnRhbCBFbmQgU3RhdGlvbiBJRGAKICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9IGAwMiAtIFJlbnRhbCBFbmQgU3RhdGlvbiBOYW1lYAogICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSBgVXNlciBUeXBlYAogICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gYE1lbWJlciBHZW5kZXJgCiAgICAgICAgICAgICAgICAgICAgICAgICxiaXJ0aHllYXIgPSBgMDUgLSBNZW1iZXIgRGV0YWlscyBNZW1iZXIgQmlydGhkYXkgWWVhcmApCnRyaXBzXzIwMTlfcTE8LSByZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTlfUTEuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkKdHJpcHNfMjAxOV9xMyA8LSByZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTlfUTMuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKHRyaXBfaWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlrZWlkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGZyb21fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHRvX3N0YXRpb25fbmFtZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx1c2VydHlwZSA9ICJjIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxnZW5kZXIgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYmlydGh5ZWFyID0gImkiKSkKdHJpcHNfMjAxOV9xNCA8LSByZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMTlfUTQuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjb2xfdHlwZXMgPSBjb2xzKCB0cmlwX2lkID0gImkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpa2VpZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxmcm9tX3N0YXRpb25faWQgPSAiaSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZnJvbV9zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9fc3RhdGlvbl9pZCA9ICJpIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICx0b19zdGF0aW9uX25hbWUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdXNlcnR5cGUgPSAiYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsZ2VuZGVyID0gImMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGJpcnRoeWVhciA9ICJpIikpCnRyaXBzXzIwMTkgPC0gcmJpbmQodHJpcHNfMjAxOV9xMSwgdHJpcHNfMjAxOV9xMiwgdHJpcHNfMjAxOV9xMywgdHJpcHNfMjAxOV9xNCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAojIGRhdGEgdHJhbnNmb3JtYXRpb24gYW5kIHdyYW5nbGluZwp0cmlwc18yMDE5IDwtIHNlbGVjdCh0cmlwc18yMDE5LCAtYmlydGh5ZWFyLCAtZ2VuZGVyLCAtZnJvbV9zdGF0aW9uX2lkLCAtdG9fc3RhdGlvbl9pZCkKdHJpcHNfMjAxOSR1c2VydHlwZVt0cmlwc18yMDE5JHVzZXJ0eXBlID09ICdTdWJzY3JpYmVyJ10gPC0gIk1lbWJlciIKdHJpcHNfMjAxOSR1c2VydHlwZVt0cmlwc18yMDE5JHVzZXJ0eXBlID09ICdDdXN0b21lciddIDwtICJDYXN1YWwiCnRyaXBzXzIwMTkkc3RhcnRfdGltZSA8LSBhbnl0aW1lKHRyaXBzXzIwMTkkc3RhcnRfdGltZSkKdHJpcHNfMjAxOSRkYXkgPC0gd2RheSh0cmlwc18yMDE5JHN0YXJ0X3RpbWUsIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFKQp0cmlwc18yMDE5JG1vbnRoIDwtIG1vbnRoKHRyaXBzXzIwMTkkc3RhcnRfdGltZSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpCgoKYGBgCgojIyMgRGF0YSBBbmFseXNpcwpgYGB7cn0KcGFzdGUoIlRoZSBBdmVyYWdlIHRpbWUgcmlkZXJzIHNwZW50IHJpZGluZyBiaWtlcyBpbiAyMDE5OiIsIHJvdW5kKG1lYW4odHJpcHNfMjAxOSR0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIGxvbmdlc3QgZHVyYXRpb24gYSByaWRlciB1c2VkIHRoZSBiaWtlIGluIDIwMTkgd2FzIiwgbWF4KHRyaXBzXzIwMTkkdHJpcGR1cmF0aW9uKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIG1vc3QgcG9wdWxhciBkYXkgb2YgYm9va2luZyB3YXMiLCBtZnYodHJpcHNfMjAxOSRkYXkpLCAiaW4gMjAxOSIpCnBhc3RlKCJUaGUgbW9zdCBwb3B1bGFyIG1vbnRoIG9mIGJvb2tpbmcgd2FzIiwgbWZ2KHRyaXBzXzIwMTkkbW9udGgpKQoKIyBjcmVhdGluZyBhIG5ldyBkYXRhZnJhbWUKdHJpcHNfMjAxOV9waXZvdCA8LSB0cmlwc18yMDE5ICU+JQogIGdyb3VwX2J5KHVzZXJ0eXBlKSAlPiUKICBzdW1tYXJpemUoIkF2ZXJhZ2UgUmlkZSBMZW5ndGgiID0gcm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgIk51bWJlciBvZiBSaWRlcyIgPSBsZW5ndGgodHJpcF9pZCksCiAgICAgICAgICAgICJZZWFyIiA9IHllYXIodHJpcHNfMjAxOSRzdGFydF90aW1lKSwgLmdyb3VwcyA9ICdkcm9wJykKdHJpcHNfMjAxOV9waXZvdCA8LSB1bmlxdWUodHJpcHNfMjAxOV9waXZvdCkKCiMgcGl2b3QgdGFibGUKcWhwdnQodHJpcHNfMjAxOSwgcm93cyA9ICdkYXknLCBjb2x1bW5zID0gJ3VzZXJ0eXBlJywgY2FsY3VsYXRpb25zID0gYygiQXZlcmFnZSBSaWRlIExlbmd0aCIgPSAicm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSIsICJOdW1iZXIgb2YgcmlkZXMiID0gImxlbmd0aCh0cmlwX2lkKSIpKQpgYGAKIyMjIERhdGEgdmlzdWFsaXNhdGlvbiAKYGBge3J9CiMgTnVtYmVyIG9mIHJpZGVycyBpbiAyMDE5CnAxIDwtIGdncGxvdCh0cmlwc18yMDE5LCBtYXBwaW5nID0gYWVzKHggPSBkYXksIGZpbGwgPSB1c2VydHlwZSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICdkb2RnZScpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHVuaXRfZm9ybWF0KHVuaXQgPSAiSyIsIHNjYWxlID0gMWUtMykpICsKICBsYWJzKHggPSAiV2Vla2RheXMiLCB5ID0gIk51bWJlciBvZiBSaWRlcnMiCiAgICAgICAsdGl0bGUgPSAiIERpdnZ5IEJpa2VzIHJpZGVycyBkYXRhIgogICAgICAgLHN1YnRpdGxlID0gIlllYXIgOiAyMDE5IChXZWVrbHkpIiArCiAgICAgICAgIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJUeXBlIG9mIFJpZGVycyIsIGxhYmVscyA9IGMoIkNhc3VhbCBSaWRlcnMiLCJBbm51YWwgTWVtYmVyIFJpZGVycyIpKSArCnRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkpIAoKIyBUcmlwIGR1cmF0aW9uIG9mIHJpZGVycyBpbiAyMDE5CnAyIDwtIGdncGxvdCh0cmlwc18yMDE5LCBtYXBwaW5nID0gYWVzKHggPSBkYXksIHkgPSB0cmlwZHVyYXRpb24pKSArIAogIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH51c2VydHlwZSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJNIiwgc2NhbGUgPSAxZS02KSkgKwogIGxhYnMoeCA9ICJXZWVrIERheXMiLCB5ID0gIlRvdGFsIFRyaXAgRHVyYXRpb24gKGluIFNlY29uZHMpIiwgCiAgICAgICB0aXRsZSA9ICJUcmlwIER1cmF0aW9uIG9mIHRoZSBSaWRlcnMgKFllYXI6IDIwMTkpIiwKICAgICAgIHN1YnRpdGxlID0gIlRoZSBncmFwaCByZXByZXNlbnRzIHRoZSB0b3RhbCB0cmlwIGR1cmF0aW9uIG9mIHJpZGVycyBldmVyZGF5IG9mIHRoZSB3ZWVrIGluIDIwMTkuIikgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSksIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKZmlnKDE4LCAxNSkKZ3JpZC5hcnJhbmdlKHAxLCBwMikKCmBgYAoKIyBEaXZ2eSBiaWtlcyAyMDIwIERhdGFzZXQKYGBge3J9CiMgaW1wb3J0aW5nIGFuZCBjb21iaW5pbmcgYWxsIHJlbGF0ZWQgZGF0YXNldHMKdHJpcHNfMjAyMCA8LSByYmluZChyZWFkX2NzdigiRGF0YSBzb3VyY2VzL0RpdnZ5X1RyaXBzXzIwMjBfUTEuY3N2IiksIHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvMjAyMDA0LWRpdnZ5LXRyaXBkYXRhLmNzdiIpLCByZWFkX2NzdigiRGF0YSBzb3VyY2VzLzIwMjAwNS1kaXZ2eS10cmlwZGF0YS5jc3YiKSwgcmVhZF9jc3YoIkRhdGEgc291cmNlcy8yMDIwMDYtZGl2dnktdHJpcGRhdGEuY3N2IiksIHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvMjAyMDA3LWRpdnZ5LXRyaXBkYXRhLmNzdiIpLCByZWFkX2NzdigiRGF0YSBzb3VyY2VzLzIwMjAwOC1kaXZ2eS10cmlwZGF0YS5jc3YiKSwgcmVhZF9jc3YoIkRhdGEgc291cmNlcy8yMDIwMDktZGl2dnktdHJpcGRhdGEuY3N2IiksIHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvMjAyMDEwLWRpdnZ5LXRyaXBkYXRhLmNzdiIpLCByZWFkX2NzdigiRGF0YSBzb3VyY2VzLzIwMjAxMS1kaXZ2eS10cmlwZGF0YS5jc3YiKSwgcmVhZF9jc3YoIkRhdGEgc291cmNlcy8yMDIwMTItZGl2dnktdHJpcGRhdGEuY3N2IikpCgp0cmlwc18yMDIwIDwtIHJlbmFtZSh0cmlwc18yMDIwLCB0cmlwX2lkID0gcmlkZV9pZAogICAgICAgICAgICAgICAgICAgICAsc3RhcnRfdGltZSA9IHN0YXJ0ZWRfYXQKICAgICAgICAgICAgICAgICAgICAgLGVuZF90aW1lID0gZW5kZWRfYXQKICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gbWVtYmVyX2Nhc3VhbCkKdHJpcHNfMjAyMCA8LSBtdXRhdGUodHJpcHNfMjAyMCwgdHJpcGR1cmF0aW9uID0gYWJzKGVuZF90aW1lIC0gc3RhcnRfdGltZSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKIyBkYXRhIHRyYW5zZm9ybWF0aW9uIGFuZCB3cmFuZ2xpbmcKdHJpcHNfMjAyMCA8LSBzZWxlY3QodHJpcHNfMjAyMCwgLXN0YXJ0X3N0YXRpb25faWQsIC1lbmRfc3RhdGlvbl9pZCkKdHJpcHNfMjAyMCR1c2VydHlwZVt0cmlwc18yMDIwJHVzZXJ0eXBlID09ICdTdWJzY3JpYmVyJ10gPC0gIk1lbWJlciIKdHJpcHNfMjAyMCR1c2VydHlwZVt0cmlwc18yMDIwJHVzZXJ0eXBlID09ICdDdXN0b21lciddIDwtICJDYXN1YWwiCnRyaXBzXzIwMjAkc3RhcnRfdGltZSA8LSBhbnl0aW1lKHRyaXBzXzIwMjAkc3RhcnRfdGltZSkKdHJpcHNfMjAyMCRkYXkgPC0gd2RheSh0cmlwc18yMDIwJHN0YXJ0X3RpbWUsIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFKQp0cmlwc18yMDIwJG1vbnRoIDwtIG1vbnRoKHRyaXBzXzIwMjAkc3RhcnRfdGltZSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpCgoKYGBgCgojIyMgRGF0YSBBbmFseXNpcwpgYGB7cn0KcGFzdGUoIlRoZSBBdmVyYWdlIHRpbWUgcmlkZXJzIHNwZW50IHJpZGluZyBiaWtlcyBpbiAyMDIwOiIsIHJvdW5kKG1lYW4odHJpcHNfMjAyMCR0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIGxvbmdlc3QgZHVyYXRpb24gYSByaWRlciB1c2VkIHRoZSBiaWtlIGluIDIwMjAgd2FzIiwgbWF4KHRyaXBzXzIwMjAkdHJpcGR1cmF0aW9uKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIG1vc3QgcG9wdWxhciBkYXkgb2YgYm9va2luZyB3YXMiLCBtZnYodHJpcHNfMjAyMCRkYXkpLCAiaW4gMjAyMCIpCnBhc3RlKCJUaGUgbW9zdCBwb3B1bGFyIG1vbnRoIG9mIGJvb2tpbmcgd2FzIiwgbWZ2KHRyaXBzXzIwMjAkbW9udGgpKQoKIyBjcmVhdGluZyBhIG5ldyBkYXRhZnJhbWUKdHJpcHNfMjAyMF9waXZvdCA8LSB0cmlwc18yMDIwICU+JQogIGdyb3VwX2J5KHVzZXJ0eXBlKSAlPiUKICBzdW1tYXJpemUoIkF2ZXJhZ2UgUmlkZSBMZW5ndGgiID0gcm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgIk51bWJlciBvZiBSaWRlcyIgPSBsZW5ndGgodHJpcF9pZCksCiAgICAgICAgICAgICJZZWFyIiA9IHllYXIodHJpcHNfMjAyMCRzdGFydF90aW1lKSwgLmdyb3VwcyA9ICdkcm9wJykKdHJpcHNfMjAyMF9waXZvdCA8LSB1bmlxdWUodHJpcHNfMjAyMF9waXZvdCkKCiMgcGl2b3QgdGFibGUKcWhwdnQodHJpcHNfMjAyMCwgcm93cyA9ICdkYXknLCBjb2x1bW5zID0gJ3VzZXJ0eXBlJywgY2FsY3VsYXRpb25zID0gYygiQXZlcmFnZSBSaWRlIExlbmd0aCIgPSAicm91bmQobWVhbihhcy5pbnRlZ2VyKHRyaXBkdXJhdGlvbikpLCBkaWdpdHMgPSAyKSIsICJOdW1iZXIgb2YgcmlkZXMiID0gImxlbmd0aCh0cmlwX2lkKSIpKQpgYGAKIyMjIERhdGEgdmlzdWFsaXNhdGlvbiAKYGBge3J9CiMgTnVtYmVyIG9mIHJpZGVycyBpbiAyMDIwCnAxIDwtIGdncGxvdCh0cmlwc18yMDIwLCBtYXBwaW5nID0gYWVzKHggPSBkYXksIGZpbGwgPSB1c2VydHlwZSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICdkb2RnZScpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHVuaXRfZm9ybWF0KHVuaXQgPSAiSyIsIHNjYWxlID0gMWUtMykpICsKICBsYWJzKHggPSAiV2Vla2RheXMiLCB5ID0gIk51bWJlciBvZiBSaWRlcnMiCiAgICAgICAsdGl0bGUgPSAiIERpdnZ5IEJpa2VzIHJpZGVycyBkYXRhIgogICAgICAgLHN1YnRpdGxlID0gIlllYXIgOiAyMDIwIChXZWVrbHkpIiArCiAgICAgICAgIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJUeXBlIG9mIFJpZGVycyIsIGxhYmVscyA9IGMoIkNhc3VhbCIsIk1lbWJlciIpKSArCnRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkpIAoKIyBUcmlwIGR1cmF0aW9uIG9mIHJpZGVycyBpbiAyMDIwCnAyIDwtIGdncGxvdCh0cmlwc18yMDIwLCBtYXBwaW5nID0gYWVzKHggPSBkYXksIHkgPSB0cmlwZHVyYXRpb24pKSArIAogIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH51c2VydHlwZSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJNIiwgc2NhbGUgPSAxZS02KSkgKwogIGxhYnMoeCA9ICJXZWVrIERheXMiLCB5ID0gIlRvdGFsIFRyaXAgRHVyYXRpb24gKGluIFNlY29uZHMpIiwgCiAgICAgICB0aXRsZSA9ICJUcmlwIER1cmF0aW9uIG9mIHRoZSBSaWRlcnMgKFllYXI6IDIwMjApIiwKICAgICAgIHN1YnRpdGxlID0gIlRoZSBncmFwaCByZXByZXNlbnRzIHRoZSB0b3RhbCB0cmlwIGR1cmF0aW9uIG9mIHJpZGVycyBldmVyZGF5IG9mIHRoZSB3ZWVrIGluIDIwMjAuIikgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSksIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKZmlnKDE4LCAxNSkKZ3JpZC5hcnJhbmdlKHAxLCBwMikKCmBgYAoKCiMgRGl2dnkgYmlrZXMgMjAyMCBEYXRhc2V0CmBgYHtyfQojIGltcG9ydGluZyBhbmQgY29tYmluaW5nIGFsbCByZWxhdGVkIGRhdGFzZXRzCnRyaXBzXzIwMjEgPC0gcmJpbmQocmVhZF9jc3YoIkRhdGEgc291cmNlcy8yMDIxMDEtZGl2dnktdHJpcGRhdGEuY3N2IiksIHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvMjAyMTAyLWRpdnZ5LXRyaXBkYXRhLmNzdiIpLCByZWFkX2NzdigiRGF0YSBzb3VyY2VzLzIwMjEwMy1kaXZ2eS10cmlwZGF0YS5jc3YiKSwgcmVhZF9jc3YoIkRhdGEgc291cmNlcy8yMDIxMDQtZGl2dnktdHJpcGRhdGEuY3N2IiksIHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvMjAyMTA1LWRpdnZ5LXRyaXBkYXRhLmNzdiIpLCByZWFkX2NzdigiRGF0YSBzb3VyY2VzLzIwMjEwNi1kaXZ2eS10cmlwZGF0YS5jc3YiKSwgcmVhZF9jc3YoIkRhdGEgc291cmNlcy8yMDIxMDctZGl2dnktdHJpcGRhdGEuY3N2IiksIHJlYWRfY3N2KCJEYXRhIHNvdXJjZXMvMjAyMTA4LWRpdnZ5LXRyaXBkYXRhLmNzdiIpLCByZWFkX2NzdigiRGF0YSBzb3VyY2VzLzIwMjEwOS1kaXZ2eS10cmlwZGF0YS5jc3YiKSwgcmVhZF9jc3YoIkRhdGEgc291cmNlcy8yMDIxMTAtZGl2dnktdHJpcGRhdGEuY3N2IikpCgp0cmlwc18yMDIxIDwtIHJlbmFtZSh0cmlwc18yMDIxLCB0cmlwX2lkID0gcmlkZV9pZAogICAgICAgICAgICAgICAgICAgICAsc3RhcnRfdGltZSA9IHN0YXJ0ZWRfYXQKICAgICAgICAgICAgICAgICAgICAgLGVuZF90aW1lID0gZW5kZWRfYXQKICAgICAgICAgICAgICAgICAgICAgLHVzZXJ0eXBlID0gbWVtYmVyX2Nhc3VhbCkKdHJpcHNfMjAyMSA8LSBtdXRhdGUodHJpcHNfMjAyMSwgdHJpcGR1cmF0aW9uID0gYWJzKGVuZF90aW1lIC0gc3RhcnRfdGltZSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKIyBkYXRhIHRyYW5zZm9ybWF0aW9uIGFuZCB3cmFuZ2xpbmcKdHJpcHNfMjAyMSA8LSBzZWxlY3QodHJpcHNfMjAyMSwgLXN0YXJ0X3N0YXRpb25faWQsIC1lbmRfc3RhdGlvbl9pZCkKdHJpcHNfMjAyMSR1c2VydHlwZVt0cmlwc18yMDIxJHVzZXJ0eXBlID09ICdTdWJzY3JpYmVyJ10gPC0gIk1lbWJlciIKdHJpcHNfMjAyMSR1c2VydHlwZVt0cmlwc18yMDIxJHVzZXJ0eXBlID09ICdDdXN0b21lciddIDwtICJDYXN1YWwiCnRyaXBzXzIwMjEkc3RhcnRfdGltZSA8LSBhbnl0aW1lKHRyaXBzXzIwMjEkc3RhcnRfdGltZSkKdHJpcHNfMjAyMSRkYXkgPC0gd2RheSh0cmlwc18yMDIxJHN0YXJ0X3RpbWUsIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFKQp0cmlwc18yMDIxJG1vbnRoIDwtIG1vbnRoKHRyaXBzXzIwMjEkc3RhcnRfdGltZSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpCgoKYGBgCgojIyMgRGF0YSBBbmFseXNpcwpgYGB7cn0KcGFzdGUoIlRoZSBBdmVyYWdlIHRpbWUgcmlkZXJzIHNwZW50IHJpZGluZyBiaWtlcyBpbiAyMDIxOiIsIHJvdW5kKG1lYW4odHJpcHNfMjAyMSR0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIGxvbmdlc3QgZHVyYXRpb24gYSByaWRlciB1c2VkIHRoZSBiaWtlIGluIDIwMjEgd2FzIiwgbWF4KHRyaXBzXzIwMjEkdHJpcGR1cmF0aW9uKSwgInNlY29uZHMiKQpwYXN0ZSgiVGhlIG1vc3QgcG9wdWxhciBkYXkgb2YgYm9va2luZyB3YXMiLCBtZnYodHJpcHNfMjAyMSRkYXkpLCAiaW4gMjAyMSIpCnBhc3RlKCJUaGUgbW9zdCBwb3B1bGFyIG1vbnRoIG9mIGJvb2tpbmcgd2FzIiwgbWZ2KHRyaXBzXzIwMjEkbW9udGgpKQoKIyBjcmVhdGluZyBhIG5ldyBkYXRhZnJhbWUKdHJpcHNfMjAyMV9waXZvdCA8LSB0cmlwc18yMDIxICU+JQogIGdyb3VwX2J5KHVzZXJ0eXBlKSAlPiUKICBzdW1tYXJpemUoIkF2ZXJhZ2UgUmlkZSBMZW5ndGgiID0gcm91bmQobWVhbih0cmlwZHVyYXRpb24pLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgIk51bWJlciBvZiBSaWRlcyIgPSBsZW5ndGgodHJpcF9pZCksCiAgICAgICAgICAgICJZZWFyIiA9IHllYXIodHJpcHNfMjAyMSRzdGFydF90aW1lKSwgLmdyb3VwcyA9ICdkcm9wJykKdHJpcHNfMjAyMV9waXZvdCA8LSB1bmlxdWUodHJpcHNfMjAyMV9waXZvdCkKCiMgcGl2b3QgdGFibGUKcWhwdnQodHJpcHNfMjAyMSwgcm93cyA9ICdkYXknLCBjb2x1bW5zID0gJ3VzZXJ0eXBlJywgY2FsY3VsYXRpb25zID0gYygiQXZlcmFnZSBSaWRlIExlbmd0aCIgPSAicm91bmQobWVhbihhcy5pbnRlZ2VyKHRyaXBkdXJhdGlvbikpLCBkaWdpdHMgPSAyKSIsICJOdW1iZXIgb2YgcmlkZXMiID0gImxlbmd0aCh0cmlwX2lkKSIpKQpgYGAKIyMjIERhdGEgdmlzdWFsaXNhdGlvbiAKYGBge3J9CiMgRGF0YSBWaXN1YWxpemF0aW9uCiMgTnVtYmVyIG9mIFJpZGVycyBpbiB0aGUgeWVhciBvZiAyMDIxCnAxIDwtIGdncGxvdCh0cmlwc18yMDIxLCBtYXBwaW5nID0gYWVzKHggPSBkYXksIGZpbGwgPSB1c2VydHlwZSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zKSkgKyAKICBsYWJzKHggPSAiV2VlayBEYXlzIiwgeSA9ICJOdW1iZXIgb2YgUmlkZXJzIiwgCiAgICAgICB0aXRsZSA9ICJEaXZ2eSBiaWtlcyByaWRlcnMgZGF0YSIsCiAgICAgICBzdWJ0aXRsZSA9ICJZZWFyOiAyMDIxIChXZWVrbHkpIiApICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiVHlwZSBvZiBSaWRlcnMiLCBsYWJlbHMgPSBjKCJDYXN1YWwgUmlkZXJzIiwiTWVtYmVyIFJpZGVycyIpKSArCnRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgCgojIFRyaXAgZHVyYXRpb24gb2YgcmlkZXJzIGluIDIwMjEKcDIgPC0gZ2dwbG90KHRyaXBzXzIwMjEsIG1hcHBpbmcgPSBhZXMoeCA9IGRheSwgeSA9IHRyaXBkdXJhdGlvbikpICsgCiAgZ2VvbV9jb2woKSArIGZhY2V0X3dyYXAofnVzZXJ0eXBlKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSB1bml0X2Zvcm1hdCh1bml0ID0gIk0iLCBzY2FsZSA9IDFlLTYpKSArCiAgbGFicyh4ID0gIldlZWsgRGF5cyIsIHkgPSAiVG90YWwgVHJpcCBEdXJhdGlvbiAoaW4gU2Vjb25kcykiLCAKICAgICAgIHRpdGxlID0gIlRyaXAgRHVyYXRpb24gb2YgdGhlIFJpZGVycyAoWWVhcjogMjAyMSkiLAogICAgICAgc3VidGl0bGUgPSAiVGhlIGdyYXBoIHJlcHJlc2VudHMgdGhlIHRvdGFsIHRyaXAgZHVyYXRpb24gb2YgcmlkZXJzIG9uIGV2ZXJkYXkgb2YgdGhlIHdlZWsgaW4gMjAyMS4iKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9NDUpLCB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCmZpZygxOCwgMTUpCmdyaWQuYXJyYW5nZShwMSwgcDIpCmBgYAoKIyBDb25jbHVzaXZlIHN0dWR5CmBgYHtyfQojIGRhdGEgY29tYmluaW5nCmRhdGEgPC0gcmJpbmQodHJpcHNfMjAxM19waXZvdCwgdHJpcHNfMjAxNF9waXZvdCwgdHJpcHNfMjAxNV9waXZvdCwgdHJpcHNfMjAxNl9waXZvdCwgdHJpcHNfMjAxN19waXZvdCwgdHJpcHNfMjAxOF9waXZvdCwgdHJpcHNfMjAxOV9waXZvdCwgdHJpcHNfMjAyMF9waXZvdCwgdHJpcHNfMjAyMV9waXZvdCkKCmRhdGEgPC0gYXMuZGF0YS5mcmFtZShkYXRhKQpkYXRhJHVzZXJ0eXBlW2RhdGEkdXNlcnR5cGUgPT0gJ2Nhc3VhbCddIDwtICJDYXN1YWwiCmRhdGEkdXNlcnR5cGVbZGF0YSR1c2VydHlwZSA9PSAnbWVtYmVyJ10gPC0gIk1lbWJlciIKCiMgRGF0YSBWaXN1YWxpemF0aW9uCiMgQXZlcmFnZSBSaWRlIExlbmd0aCBvZiBSaWRlcnMgZnJvbSAyMDEzIHRvIDIwMjEKcDEgPC0gZ2dwbG90KGRhdGEgPSBkYXRhLCBhZXMoeCA9IGZhY3RvcihZZWFyKSwgc2hhcGUgPSB1c2VydHlwZSkpICsKICBnZW9tX3BvaW50KGFlcyh5ID0gYEF2ZXJhZ2UgUmlkZSBMZW5ndGhgLCBjb2xvciA9IHVzZXJ0eXBlKSwgc2l6ZSA9IDMuNSkgKwogIGxhYnMoeCA9ICJZZWFycyIsIHkgPSAiQXZlcmFnZSBSaWRlIExlbmd0aCAoaW4gc2Vjb25kcykiLCAKICAgICAgIHRpdGxlID0gIkF2ZXJhZ2UgUmlkZSBMZW5ndGggc3BlbnQgYnkgUmlkZXJzIGV2ZXJ5IHllYXIiLAogICAgICAgc3VidGl0bGUgPSAiVGhlIGdyYXBoIHNob3dzIGF2ZXJhZ2UgbGVuZ3RoIG9yIHRpbWUgc3BlbnQgYnkgdGhlIENhc3VhbCBSaWRlcnMgaXMgc2lnbmlmaWNhbnRseSBoaWdoZXIgCnRoYW4gRGVwZW5kZW50IGFuZCBBbm51YWwgTWVtYmVyIFJpZGVycy4iKSsKdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSAKCiMgTnVtYmVyIG9mIFJpZGVzIHRha2VuIGJ5IFJpZGVycyBmcm9tIDIwMTMgdG8gMjAyMQpwMjwtIGdncGxvdChkYXRhLCBtYXBwaW5nID0gYWVzKHggPSBmYWN0b3IoWWVhciksIHkgPSBgTnVtYmVyIG9mIFJpZGVzYCwgZmlsbCA9IGB1c2VydHlwZWApKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHVuaXRfZm9ybWF0KHVuaXQgPSAiTSIsIHNjYWxlID0gMWUtNikpICsKICBsYWJzKHggPSAiWWVhcnMiLCB5ID0gIk51bWJlciBvZiBSaWRlcyIsIAogICAgICAgdGl0bGUgPSAiTnVtYmVyIG9mIFJpZGVzIHRha2VuIGJ5IFJpZGVycyBmcm9tIDIwMTMtMjAyMSIsCiAgICAgICBzdWJ0aXRsZSA9ICJUaGUgZ3JhcGggc2hvd3MgdGhhdCBBbm51YWwgTWVtYmVyIFJpZGVycyBoYXZlIHRha2VuIG1vcmUgcmlkZXMgdGhhbiBDYXN1YWwgUmlkZXJzLiIpKwp0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpIApmaWcoMTgsIDE1KQpncmlkLmFycmFuZ2UocDEsIHAyKQpgYGAK