2.3
Download the file tute1.csv from the book website, open it in Excel (or
some other spreadsheet application), and review its contents. You should
find four columns of information. Columns B through D each contain a
quarterly series, labelled Sales, AdBudget and GDP. Sales contains the
quarterly sales for a small company over the period 1981-2005. AdBudget
is the advertising budget and GDP is the gross domestic product. All
series have been adjusted for inflation.
a.
You can read the data into R with the following script:
df_tute1 <- readr::read_csv(tute1_csv)
head(df_tute1,20)
NA
b.
Convert the data to time series
mytimeseries <- df_tute1 |>
mutate(Quarter = yearquarter(Quarter)) |>
as_tsibble(index = Quarter)
c.
Construct time series plots of each of the three series
mytimeseries |>
pivot_longer(-Quarter) |>
ggplot(aes(x = Quarter, y = value, colour = name)) +
geom_line() +
facet_grid(name ~ ., scales = "free_y")

mytimeseries %>%
pivot_longer(-Quarter)%>%
ggplot(aes(x = Quarter, y = value, colour = name)) +
geom_line() #+

# facet_grid(name ~ ., scales = "free_y")
The plot is encompassed in one plot without the
facet_grid() function.
2.4
The USgas package contains data on the demand for
natural gas in the US.
- Install the
USgas package.
- Create a
tsibble from us_total with year
as the index and state as the key.
- Plot the annual natural gas consumption by state for the New England
area (comprising the states of Maine, Vermont, New Hampshire,
Massachusetts, Connecticut and Rhode Island).
i
str(USgas::us_total)
'data.frame': 1266 obs. of 3 variables:
$ year : int 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 ...
$ state: chr "Alabama" "Alabama" "Alabama" "Alabama" ...
$ y : int 324158 329134 337270 353614 332693 379343 350345 382367 353156 391093 ...
ii
Example
Forecasting
Principles & Practice: 2.1 tsibble objects
Template
mydata <- tsibble(
year = 2015:2019,
y=c(123,39,78,52,110),
index = year
)
mydata
mydata <- tsibble(
state = us_total$state,
year = us_total$year,
value = us_total$y,
index = year,
key = state
)%>%
filter(state %in% c("Maine", "Vermont", "New Hampshire", "Massachusetts", "Connecticut", "Rhode Island"))
iii
ggplot(mydata, aes(x = year, y = value, color = state)) +
geom_line() +
labs(
title = "Annual Natural Gas Consumption for New England Area (by state)",
x = "Year",
y = "Natural Gas Consumption",
color = "State"
)

2.5
a.
Download tourism.xlsx from the book website and read it into R
using readxl::read_excel().
PATH<-"C:/Users/Lenny/Documents/GitableGabe/Data624_Data/"
tourism_str <- paste(PATH,"tourism.xlsx", sep = "")
df_tourism <- readxl::read_excel(tourism_str)
rm(tourism_str)
tourism
b.
Create a tsibble which is identical to the tourism
tsibble from the tsibble package.
str(df_tourism)
tibble [24,320 × 5] (S3: tbl_df/tbl/data.frame)
$ Quarter: chr [1:24320] "1998-01-01" "1998-04-01" "1998-07-01" "1998-10-01" ...
$ Region : chr [1:24320] "Adelaide" "Adelaide" "Adelaide" "Adelaide" ...
$ State : chr [1:24320] "South Australia" "South Australia" "South Australia" "South Australia" ...
$ Purpose: chr [1:24320] "Business" "Business" "Business" "Business" ...
$ Trips : num [1:24320] 135 110 166 127 137 ...
Example
Forecasting
Principles & Practice: 2.1 tsibble objects
Template
prison<- read::read_csv("data/prison_population.csv") %>%
mutate(Quarter = yearquarter(date)) %>%
select(-date) %>%
as_tsibble(
index = Quarter,
key=c(state,gender,legal,indigenous)
)
tibble_tourism <- df_tourism %>%
mutate(Quarter = yearquarter(Quarter)) %>%
as_tsibble(index=Quarter,
key = c("Region", "State", "Purpose"))
tibble_tourism
NA
c.
Find what combination of Region and Purpose had the maximum number of
overnight trips on average.
tibble_tourism %>%
group_by(Region,Purpose)%>%
summarize(TripsAvg = mean(Trips))%>%
filter(TripsAvg == max(TripsAvg))%>%
arrange(desc(TripsAvg))
NA
d.
Create a new tsibble which combines the Purposes and
Regions, and just has total trips by State.
tibble_tourism_v2 <- tibble_tourism %>%
group_by(State)%>%
summarize(Total=sum(Trips))
tibble_tourism_v2
2.8
Use the following graphics functions: autoplot(),
gg_season(), gg_subseries(),
gg_lag(), ACF() and explore features from the
following time series: “Total Private” Employed from
us_employment, Bricks from
aus_production, Hare from pelt,
“H02” Cost from PBS, and Barrels
from us_gasoline.
- Can you spot any seasonality, cyclicity and trend?
- What do you learn about the series?
- What can you say about the seasonal patterns?
- Can you identify any unusual years?
Total Private
Example
vic_elec |> gg_season(Demand, period = "day") +
theme(legend.position = "none") +
labs(y="MWh", title="Electricity demand: Victoria")
us_employment
us_employment%>%
filter(Title=="Total Private")%>%
autoplot(Employed,period="month")
Warning: Ignoring unknown parameters: `period`

us_employment%>%
filter(Title=="Total Private")%>%
gg_season(Employed, polar = FALSE)

us_employment%>%
filter(Title=="Total Private")%>%
gg_season(Employed, polar = TRUE)

us_employment%>%
filter(Title=="Total Private")%>%
gg_subseries(Employed)

us_employment%>%
filter(Title=="Total Private")%>%
gg_lag(Employed)

us_employment%>%
filter(Title=="Total Private")%>%
ACF(us_employment$Employed)%>%
autoplot()

i
There is a clear upwards trend in small increments for the data.
ii
Growth has been consistent without any extreme spike or drop.
iii
No Seasonality is noted indicating there is not particular season
with an affect on employment positive or negative.
iv
A small dip around 2010 which I believe aligns with the
recession.
Bricks
aus_production%>%
select(Bricks)%>%
autoplot(period="quarter")
Plot variable not specified, automatically selected `.vars = Bricks`Warning: Ignoring unknown parameters: `period`

aus_production%>%
select(Bricks)%>%
gg_season( polar = FALSE)
Plot variable not specified, automatically selected `y = Bricks`

aus_production%>%
select(Bricks)%>%
gg_season( polar = TRUE)
Plot variable not specified, automatically selected `y = Bricks`

aus_production%>%
select(Bricks)%>%
gg_subseries()
Plot variable not specified, automatically selected `y = Bricks`

aus_production%>%
select(Bricks)%>%
gg_lag()
Plot variable not specified, automatically selected `y = Bricks`Warning: Removed 20 rows containing missing values (gg_lag).

aus_production%>%
select(Bricks)%>%
ACF(aus_production$Bricks)%>%
autoplot()

i
There is lots of cyclicity with frequent spikes and dips, but it does
not appear to be consistent to a time period.There is a positive upward
trend in the long term.
ii
The data being broken down to Quarters my influence how well we can
assess the potential seasonality. As is, there does seem to be one.
iii
There seems to be some seasonality as far as Q1 and Q3 is
concerned.
iv
The early 1980s has a significant dip so I would be curious to
understand what may have cause this.
Hare
pelt%>%
select(Hare)%>%
autoplot(period="year")
Plot variable not specified, automatically selected `.vars = Hare`Warning: Ignoring unknown parameters: `period`

#Not possible
# pelt%>%
# select(Hare)%>%
# gg_season( polar = FALSE)
#
# pelt%>%
# select(Hare)%>%
# gg_season( polar = TRUE)
pelt%>%
select(Hare)%>%
gg_subseries()
Plot variable not specified, automatically selected `y = Hare`

pelt%>%
select(Hare)%>%
gg_lag()
Plot variable not specified, automatically selected `y = Hare`

pelt%>%
select(Hare)%>%
ACF()%>%
autoplot()
Response variable not specified, automatically selected `var = Hare`

i
The data is definitely cyclical but its not possible to teal
seasonality since its at a annual basis.
ii
The data does not trend and varies a great deal. But seems to have a
pattern at a 5 year interval.
iv
Im curious what caused the peak in the early 1860s
Cost
PBS%>%
filter(ATC2=="H02")%>%
autoplot(Cost)

PBS %>%
filter(ATC2 == "H02") %>%
gg_season(Cost, polar = FALSE)

PBS %>%
filter(ATC2 == "H02") %>%
gg_subseries(Cost)

# PBS %>%
# filter(ATC2 == "H02") %>%
# gg_lag(Cost)
PBS %>%
filter(ATC2 == "H02") %>%
ACF(Cost)%>%
autoplot()

i
The data is hard to interpret but it appears to trend upwards with
cyclicity and seasonality. ### ii
the data is very volatile but spikes mainly end of year it
appears.
iii
The seasonality is at the end of the year.
iv
No year stands out, outside of the latest year having the highest
cost.
Barrels
us_gasoline%>%
select(Barrels)%>%
autoplot()
Plot variable not specified, automatically selected `.vars = Barrels`

us_gasoline%>%
select(Barrels)%>%
gg_season(polar = FALSE)
Plot variable not specified, automatically selected `y = Barrels`

us_gasoline%>%
select(Barrels)%>%
gg_season( polar = TRUE)
Plot variable not specified, automatically selected `y = Barrels`

us_gasoline%>%
select(Barrels)%>%
gg_subseries()
Plot variable not specified, automatically selected `y = Barrels`

us_gasoline%>%
select(Barrels)%>%
gg_lag()
Plot variable not specified, automatically selected `y = Barrels`

us_gasoline %>%
select(Barrels) %>%
ACF()%>%
autoplot()
Response variable not specified, automatically selected `var = Barrels`

i
Primarily an upward trend with a dip near the most recent year
ii
Its possible the barrels value is impacted by supply.
iii
There does not appear to be seasonality of cyclicity
iv
The most recent dip is interesting and I wonder if its just a data
collection issue.
LS0tDQp0aXRsZTogJ0RBVEEgNjI0OiBQUkVESUNUSVZFIEFOQUxZVElDUyBIVzEnDQphdXRob3I6ICJHYWJyaWVsIENhbXBvcyINCmRhdGU6ICJMYXN0IGVkaXRlZCBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBnZW9tZXRyeTogbGVmdD0wLjVjbSxyaWdodD0wLjVjbSx0b3A9MWNtLGJvdHRvbT0yY20NCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgcGRmX2RvY3VtZW50Og0KICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleA0KdXJsY29sb3I6IGJsdWUNCi0tLQ0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoJ2ZwcDMnKQ0KbGlicmFyeSgndHNpYmJsZScpDQpsaWJyYXJ5KCdnZ3Bsb3QyJykNCmxpYnJhcnkoJ1VTZ2FzJykNCmxpYnJhcnkoJ3JlYWRyJykNCmxpYnJhcnkoJ3pvbycpDQpgYGANCg0KDQojIElOU1RSVUNUSU9OUw0KDQpQbGVhc2Ugc3VibWl0IGV4ZXJjaXNlcyAyLjEsIDIuMiwgMi4zLCAyLjQsIDIuNSBhbmQgMi44IGZyb20gdGhlIEh5bmRtYW4gb25saW5lIEZvcmVjYXN0aW5nIGJvb2suICBQbGVhc2Ugc3VibWl0IGJvdGggeW91ciBScHVicyBsaW5rIGFzIHdlbGwgYXMgYXR0YWNoIHRoZSAucGRmIGZpbGUgd2l0aCB5b3VyIGNvZGUuDQoNCiMgMi4xDQoNCjEuICBFeHBsb3JlIHRoZSBmb2xsb3dpbmcgZm91ciB0aW1lIHNlcmllczogYEJyaWNrc2AgZnJvbSBgYXVzX3Byb2R1Y3Rpb25gLCBgTHlueGAgZnJvbSBgcGVsdGAsIGBDbG9zZWAgZnJvbSBgZ2FmYV9zdG9ja2AsIGBEZW1hbmRgIGZyb20gYHZpY19lbGVjYC4NCg0KICAgIGkuIFVzZSA/IChvciBoZWxwKCkpIHRvIGZpbmQgb3V0IGFib3V0IHRoZSBkYXRhIGluIGVhY2ggc2VyaWVzLg0KICAgIGlpLiBXaGF0IGlzIHRoZSB0aW1lIGludGVydmFsIG9mIGVhY2ggc2VyaWVzPw0KICAgIGlpaS4gVXNlIGF1dG9wbG90KCkgdG8gcHJvZHVjZSBhIHRpbWUgcGxvdCBvZiBlYWNoIHNlcmllcy4NCiAgICBpdi4gRm9yIHRoZSBsYXN0IHBsb3QsIG1vZGlmeSB0aGUgYXhpcyBsYWJlbHMgYW5kIHRpdGxlLg0KICAgIA0KICAgIA0KYGBge3J9DQpkYXRhKCJhdXNfcHJvZHVjdGlvbiIpDQpkYXRhKCJwZWx0IikNCmRhdGEoImdhZmFfc3RvY2siKQ0KZGF0YSgidmljX2VsZWMiKQ0KYGBgDQoNCiMjIEJyaWNrcw0KDQojIyMgaQ0KDQoqRGV0YWlscyoNClF1YXJ0ZXJseSBlc3RpbWF0ZXMgb2Ygc2VsZWN0ZWQgaW5kaWNhdG9ycyBvZiBtYW51ZmFjdHVyaW5nIHByb2R1Y3Rpb24gaW4gQXVzdHJhbGlhLg0KDQoqQnJpY2tzOioJQ2xheSBicmljayBwcm9kdWN0aW9uIGluIG1pbGxpb25zIG9mIGJyaWNrcy4NCg0KIyMjIGlpDQoNClF1YXJ0ZXJseQ0KDQpgYGB7cn0NCmF1c19wcm9kdWN0aW9uJT4lDQogIHNlbGVjdChCcmlja3MpDQpgYGANCiMjIyBpaWkNCg0KYGBge3J9DQphdXRvcGxvdChhdXNfcHJvZHVjdGlvbixCcmlja3MpICsNCiAgbGFicyh0aXRsZSA9ICJUaW1lIFBsb3Qgb2YgQnJpY2tzIFNlcmllcyIsDQogICAgICAgeCA9ICJRdWFydGVybHkiLA0KICAgICAgIHkgPSAiQnJpY2tzIFByb2R1Y3Rpb24gY291bnQiKQ0KYGBgDQoNCiMjIEx5bngNCg0KIyMjIGkNCg0KcGVsdCBpcyBhbiBhbm51YWwgdHNpYmJsZSB3aXRoIHR3byB2YWx1ZXM6DQoNCkhhcmU6CVRoZSBudW1iZXIgb2YgU25vd3Nob2UgSGFyZSBwZWx0cyB0cmFkZWQuDQpMeW54OglUaGUgbnVtYmVyIG9mIENhbmFkaWFuIEx5bnggcGVsdHMgdHJhZGVkLg0KDQojIyMgaWkNCg0KYGBge3J9DQpwZWx0ICU+JQ0KICBzZWxlY3QoTHlueCkNCmBgYA0KDQojIyMgaWlpDQoNCmBgYHtyfQ0KDQphdXRvcGxvdChwZWx0LEx5bngpICsNCiAgbGFicyh0aXRsZSA9ICJUaW1lIFBsb3Qgb2YgbHlueCBTZXJpZXMgKDE4NDUgdG8xOTM1KSIsDQogICAgICAgeCA9ICJBbm51YWxseSIsDQogICAgICAgeSA9ICJMeW54IHBlbHRzIHRyYWRlZCBDb3VudCIpDQoNCmBgYA0KDQojIyBDbG9zZQ0KDQojIyMgaQ0KDQpEZXRhaWxzDQpnYWZhX3N0b2NrIGlzIGEgdHNpYmJsZSBjb250YWluaW5nIGRhdGEgb24gaXJyZWd1bGFyIHRyYWRpbmcgZGF5czoNCg0KT3BlbjoJVGhlIG9wZW5pbmcgcHJpY2UgZm9yIHRoZSBzdG9jay4NCkhpZ2g6CVRoZSBzdG9jaydzIGhpZ2hlc3QgdHJhZGluZyBwcmljZS4NCkxvdzoJVGhlIHN0b2NrJ3MgbG93ZXN0IHRyYWRpbmcgcHJpY2UuDQpDbG9zZToJVGhlIGNsb3NpbmcgcHJpY2UgZm9yIHRoZSBzdG9jay4NCkFkal9DbG9zZToJVGhlIGFkanVzdGVkIGNsb3NpbmcgcHJpY2UgZm9yIHRoZSBzdG9jay4NClZvbHVtZToJVGhlIGFtb3VudCBvZiBzdG9jayB0cmFkZWQuDQpFYWNoIHN0b2NrIGlzIHVuaXF1ZWx5IGlkZW50aWZpZWQgYnkgb25lIGtleToNCg0KU3ltYm9sOglUaGUgdGlja2VyIHN5bWJvbCBmb3IgdGhlIHN0b2NrLg0KDQojIyMgaWkNCg0KYGBge3J9DQpnYWZhX3N0b2NrJT4lDQogIHNlbGVjdChDbG9zZSkNCmBgYA0KDQpUaGUgYGdhZmFfc3RvY2tgIGlzIGRhaWx5IGRhdGENCg0KIyMjIGlpaQ0KDQpgYGB7cn0NCg0KYXV0b3Bsb3QoZ2FmYV9zdG9jayxDbG9zZSkgKw0KICBsYWJzKHRpdGxlID0gIlRpbWUgUGxvdCBvZiBDbG9zaW5nIFN0b2NrIFByaWNlICgnWWFob28gRmluYW5jZScgMjAxNC0yMDE4KSIsDQogICAgICAgeCA9ICJEYWlseSIsDQogICAgICAgeSA9ICJDbG9zaW5nIHByaWNlIikNCg0KYGBgDQoNCiMjIERlbWFuZA0KDQojIyMgaQ0KDQoqKkRlc2NyaXB0aW9uKioqDQoNCmB2aWNfZWxlY2AgaXMgYSBoYWxmLWhvdXJseSBgdHNpYmJsZWAgd2l0aCB0aHJlZSB2YWx1ZXM6DQoNCkRlbWFuZDoJVG90YWwgZWxlY3RyaWNpdHkgZGVtYW5kIGluIE1XaC4NClRlbXBlcmF0dXJlOglUZW1wZXJhdHVyZSBvZiBNZWxib3VybmUgKEJPTSBzaXRlIDA4NjA3MSkuDQpIb2xpZGF5OglJbmRpY2F0b3IgZm9yIGlmIHRoYXQgZGF5IGlzIGEgcHVibGljIGhvbGlkYXkuDQoNCiMjIyBpaQ0KDQpgYGB7cn0NCg0KdmljX2VsZWMgJT4lDQogIHNlbGVjdChEZW1hbmQpDQoNCmBgYA0KDQoNCiMjIyBpaWkgJiB2aQ0KDQpgYGB7cn0NCmF1dG9wbG90KHZpY19lbGVjLERlbWFuZCkgKw0KICBsYWJzKHRpdGxlID0gIlRpbWUgUGxvdCBvZiBFbGVjdHJpY2l0eSBEZW1hbmQgVmljdG9yaWEsIEF1c3RyYWxpYSIsDQogICAgICAgeCA9ICJUaW1lKDMwbWluIEludGVydmFscyIsDQogICAgICAgeSA9ICJEZW1hbmQgaW4gTVdoIikNCmBgYA0KDQojIDIuMg0KDQpVc2UgZmlsdGVyKCkgdG8gZmluZCB3aGF0IGRheXMgY29ycmVzcG9uZGVkIHRvIHRoZSBwZWFrIGNsb3NpbmcgcHJpY2UgZm9yIGVhY2ggb2YgdGhlIGZvdXIgc3RvY2tzIGluIGdhZmFfc3RvY2suDQoNCg0KYGBge3J9DQpjb2xuYW1lcyhnYWZhX3N0b2NrKQ0KYGBgDQoNCmBgYHtyfQ0KDQogZ2FmYV9zdG9jayAlPiUNCiAgZ3JvdXBfYnkoU3ltYm9sKSAlPiUNCiAgZmlsdGVyKENsb3NlID09IG1heChDbG9zZSkpDQoNCmBgYA0KDQoNCiMgMi4zDQoNCkRvd25sb2FkIHRoZSBmaWxlIGB0dXRlMS5jc3ZgIGZyb20gdGhlIFtib29rIHdlYnNpdGVdKGh0dHBzOi8vYml0Lmx5L2ZwcHR1dGUxKSwgb3BlbiBpdCBpbiBFeGNlbCAob3Igc29tZSBvdGhlciBzcHJlYWRzaGVldCBhcHBsaWNhdGlvbiksIGFuZCByZXZpZXcgaXRzIGNvbnRlbnRzLiBZb3Ugc2hvdWxkIGZpbmQgZm91ciBjb2x1bW5zIG9mIGluZm9ybWF0aW9uLiBDb2x1bW5zIEIgdGhyb3VnaCBEIGVhY2ggY29udGFpbiBhIHF1YXJ0ZXJseSBzZXJpZXMsIGxhYmVsbGVkIFNhbGVzLCBBZEJ1ZGdldCBhbmQgR0RQLiBTYWxlcyBjb250YWlucyB0aGUgcXVhcnRlcmx5IHNhbGVzIGZvciBhIHNtYWxsIGNvbXBhbnkgb3ZlciB0aGUgcGVyaW9kIDE5ODEtMjAwNS4gQWRCdWRnZXQgaXMgdGhlIGFkdmVydGlzaW5nIGJ1ZGdldCBhbmQgR0RQIGlzIHRoZSBncm9zcyBkb21lc3RpYyBwcm9kdWN0LiBBbGwgc2VyaWVzIGhhdmUgYmVlbiBhZGp1c3RlZCBmb3IgaW5mbGF0aW9uLg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnR1dGUxX2NzdjwtImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9HaXRhYmxlR2FiZS9EYXRhNjI0X0RhdGEvbWFpbi90dXRlMS5jc3YiDQpgYGANCg0KIyMgYS4NCg0KWW91IGNhbiByZWFkIHRoZSBkYXRhIGludG8gUiB3aXRoIHRoZSBmb2xsb3dpbmcgc2NyaXB0Og0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCg0KZGZfdHV0ZTEgPC0gcmVhZHI6OnJlYWRfY3N2KHR1dGUxX2NzdikNCmhlYWQoZGZfdHV0ZTEsMjApDQoNCmBgYA0KDQojIyBiLg0KDQpDb252ZXJ0IHRoZSBkYXRhIHRvIHRpbWUgc2VyaWVzDQoNCmBgYHtyfQ0KbXl0aW1lc2VyaWVzIDwtIGRmX3R1dGUxIHw+DQogIG11dGF0ZShRdWFydGVyID0geWVhcnF1YXJ0ZXIoUXVhcnRlcikpIHw+DQogIGFzX3RzaWJibGUoaW5kZXggPSBRdWFydGVyKQ0KYGBgDQoNCiMjIGMuDQoNCkNvbnN0cnVjdCB0aW1lIHNlcmllcyBwbG90cyBvZiBlYWNoIG9mIHRoZSB0aHJlZSBzZXJpZXMNCg0KYGBge3J9DQpteXRpbWVzZXJpZXMgfD4NCiAgcGl2b3RfbG9uZ2VyKC1RdWFydGVyKSB8Pg0KICBnZ3Bsb3QoYWVzKHggPSBRdWFydGVyLCB5ID0gdmFsdWUsIGNvbG91ciA9IG5hbWUpKSArDQogIGdlb21fbGluZSgpICsNCiAgZmFjZXRfZ3JpZChuYW1lIH4gLiwgc2NhbGVzID0gImZyZWVfeSIpDQpgYGANCg0KYGBge3J9DQpteXRpbWVzZXJpZXMgJT4lDQogIHBpdm90X2xvbmdlcigtUXVhcnRlciklPiUNCiAgZ2dwbG90KGFlcyh4ID0gUXVhcnRlciwgeSA9IHZhbHVlLCBjb2xvdXIgPSBuYW1lKSkgKw0KICBnZW9tX2xpbmUoKSAjKw0KICAjIGZhY2V0X2dyaWQobmFtZSB+IC4sIHNjYWxlcyA9ICJmcmVlX3kiKQ0KYGBgDQoNClRoZSBwbG90IGlzIGVuY29tcGFzc2VkIGluIG9uZSBwbG90IHdpdGhvdXQgdGhlIGBmYWNldF9ncmlkKClgIGZ1bmN0aW9uLg0KDQojIDIuNA0KDQpUaGUgYFVTZ2FzYCBwYWNrYWdlIGNvbnRhaW5zIGRhdGEgb24gdGhlIGRlbWFuZCBmb3IgbmF0dXJhbCBnYXMgaW4gdGhlIFVTLg0KDQppLiBJbnN0YWxsIHRoZSBgVVNnYXNgIHBhY2thZ2UuDQppaS4gQ3JlYXRlIGEgYHRzaWJibGVgIGZyb20gYHVzX3RvdGFsYCB3aXRoIHllYXIgYXMgdGhlIGluZGV4IGFuZCBzdGF0ZSBhcyB0aGUga2V5Lg0KaWlpLiBQbG90IHRoZSBhbm51YWwgbmF0dXJhbCBnYXMgY29uc3VtcHRpb24gYnkgc3RhdGUgZm9yIHRoZSBOZXcgRW5nbGFuZCBhcmVhIChjb21wcmlzaW5nIHRoZSBzdGF0ZXMgb2YgTWFpbmUsIFZlcm1vbnQsIE5ldyBIYW1wc2hpcmUsIE1hc3NhY2h1c2V0dHMsIENvbm5lY3RpY3V0IGFuZCBSaG9kZSBJc2xhbmQpLg0KDQojIyBpDQpgYGB7cn0NCnN0cihVU2dhczo6dXNfdG90YWwpDQpgYGANCg0KIyMgaWkNCioqRXhhbXBsZSoqDQoNCltGb3JlY2FzdGluZyBQcmluY2lwbGVzICYgUHJhY3RpY2U6IDIuMSB0c2liYmxlIG9iamVjdHNdKGh0dHBzOi8veW91dHUuYmUvRXdqdkEyT2NkSHM/c2k9eXRVaENyc3dfSWhQTzFvWSZ0PTMxNikNCg0KKlRlbXBsYXRlKg0KICAgICAgICANCiAgICAgICAgbXlkYXRhIDwtIHRzaWJibGUoDQogICAgICAgICAgICB5ZWFyID0gMjAxNToyMDE5LA0KICAgICAgICAgICAgeT1jKDEyMywzOSw3OCw1MiwxMTApLA0KICAgICAgICAgICAgaW5kZXggPSB5ZWFyDQogICAgICAgICkNCiAgICAgICAgbXlkYXRhDQoNCmBgYHtyfQ0KDQpteWRhdGEgPC0gdHNpYmJsZSgNCiAgc3RhdGUgPSB1c190b3RhbCRzdGF0ZSwNCiAgeWVhciA9IHVzX3RvdGFsJHllYXIsDQogIHZhbHVlID0gdXNfdG90YWwkeSwNCiAgaW5kZXggPSB5ZWFyLA0KICBrZXkgPSBzdGF0ZQ0KKSU+JQ0KICBmaWx0ZXIoc3RhdGUgJWluJSBjKCJNYWluZSIsICJWZXJtb250IiwgIk5ldyBIYW1wc2hpcmUiLCAiTWFzc2FjaHVzZXR0cyIsICJDb25uZWN0aWN1dCIsICJSaG9kZSBJc2xhbmQiKSkNCg0KYGBgDQoNCiMjIGlpaQ0KDQpgYGB7cn0NCg0KZ2dwbG90KG15ZGF0YSwgYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGNvbG9yID0gc3RhdGUpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJBbm51YWwgTmF0dXJhbCBHYXMgQ29uc3VtcHRpb24gZm9yIE5ldyBFbmdsYW5kIEFyZWEgKGJ5IHN0YXRlKSIsDQogICAgeCA9ICJZZWFyIiwNCiAgICB5ID0gIk5hdHVyYWwgR2FzIENvbnN1bXB0aW9uIiwNCiAgICBjb2xvciA9ICJTdGF0ZSINCiAgKQ0KYGBgDQoNCiMgMi41DQoNCiMjIGEuIA0KDQpEb3dubG9hZCBgdG91cmlzbS54bHN4YCBmcm9tIHRoZSBbYm9vayB3ZWJzaXRlXShodHRwczovL2JpdC5seS9mcHB0b3VyaXNtKSBhbmQgcmVhZCBpdCBpbnRvIFIgdXNpbmcgYHJlYWR4bDo6cmVhZF9leGNlbCgpYC4NCg0KYGBge3J9DQpQQVRIPC0iQzovVXNlcnMvTGVubnkvRG9jdW1lbnRzL0dpdGFibGVHYWJlL0RhdGE2MjRfRGF0YS8iDQpgYGANCg0KDQpgYGB7cn0NCnRvdXJpc21fc3RyIDwtIHBhc3RlKFBBVEgsInRvdXJpc20ueGxzeCIsIHNlcCA9ICIiKQ0KZGZfdG91cmlzbSA8LSByZWFkeGw6OnJlYWRfZXhjZWwodG91cmlzbV9zdHIpDQpybSh0b3VyaXNtX3N0cikNCnRvdXJpc20NCmBgYA0KDQoNCg0KIyMgYi4NCg0KQ3JlYXRlIGEgYHRzaWJibGVgIHdoaWNoIGlzIGlkZW50aWNhbCB0byB0aGUgdG91cmlzbSBgdHNpYmJsZWAgZnJvbSB0aGUgYHRzaWJibGVgIHBhY2thZ2UuDQoNCmBgYHtyfQ0Kc3RyKGRmX3RvdXJpc20pDQpgYGANCg0KKipFeGFtcGxlKioNCg0KW0ZvcmVjYXN0aW5nIFByaW5jaXBsZXMgJiBQcmFjdGljZTogMi4xIHRzaWJibGUgb2JqZWN0c10oaHR0cHM6Ly95b3V0dS5iZS9Fd2p2QTJPY2RIcz9zaT10Zy13VzRPT1IzcWxuMDVsJnQ9NjYxKQ0KDQoqVGVtcGxhdGUqDQoNCiAgICAgIHByaXNvbjwtIHJlYWQ6OnJlYWRfY3N2KCJkYXRhL3ByaXNvbl9wb3B1bGF0aW9uLmNzdiIpICU+JQ0KICAgICAgICAgICAgICAgIG11dGF0ZShRdWFydGVyID0geWVhcnF1YXJ0ZXIoZGF0ZSkpICU+JQ0KICAgICAgICAgICAgICAgICAgc2VsZWN0KC1kYXRlKSAlPiUNCiAgICAgICAgICAgICAgICAgIGFzX3RzaWJibGUoDQogICAgICAgICAgICAgICAgICBpbmRleCA9IFF1YXJ0ZXIsDQogICAgICAgICAgICAgICAgICBrZXk9YyhzdGF0ZSxnZW5kZXIsbGVnYWwsaW5kaWdlbm91cykNCiAgICAgICAgICAgICAgICAgICkNCg0KDQpgYGB7cn0NCnRpYmJsZV90b3VyaXNtIDwtIGRmX3RvdXJpc20gJT4lDQogIG11dGF0ZShRdWFydGVyID0geWVhcnF1YXJ0ZXIoUXVhcnRlcikpICU+JQ0KICBhc190c2liYmxlKGluZGV4PVF1YXJ0ZXIsDQogICAgICAgICAgICAga2V5ID0gYygiUmVnaW9uIiwgIlN0YXRlIiwgIlB1cnBvc2UiKSkNCg0KdGliYmxlX3RvdXJpc20NCg0KYGBgDQoNCiMjIGMuDQoNCkZpbmQgd2hhdCBjb21iaW5hdGlvbiBvZiBSZWdpb24gYW5kIFB1cnBvc2UgaGFkIHRoZSBtYXhpbXVtIG51bWJlciBvZiBvdmVybmlnaHQgdHJpcHMgb24gYXZlcmFnZS4NCg0KYGBge3J9DQoNCnRpYmJsZV90b3VyaXNtICU+JSANCiAgZ3JvdXBfYnkoUmVnaW9uLFB1cnBvc2UpJT4lDQogIHN1bW1hcml6ZShUcmlwc0F2ZyA9IG1lYW4oVHJpcHMpKSU+JQ0KICBmaWx0ZXIoVHJpcHNBdmcgPT0gbWF4KFRyaXBzQXZnKSklPiUNCiAgYXJyYW5nZShkZXNjKFRyaXBzQXZnKSkNCg0KYGBgDQoNCg0KDQojIyBkLg0KDQpDcmVhdGUgYSBuZXcgYHRzaWJibGVgIHdoaWNoIGNvbWJpbmVzIHRoZSBQdXJwb3NlcyBhbmQgUmVnaW9ucywgYW5kIGp1c3QgaGFzIHRvdGFsIHRyaXBzIGJ5IFN0YXRlLg0KDQoNCmBgYHtyfQ0KdGliYmxlX3RvdXJpc21fdjIgPC0gdGliYmxlX3RvdXJpc20gJT4lDQogIGdyb3VwX2J5KFN0YXRlKSU+JQ0KICBzdW1tYXJpemUoVG90YWw9c3VtKFRyaXBzKSkNCg0KdGliYmxlX3RvdXJpc21fdjINCmBgYA0KDQojIDIuOA0KDQpVc2UgdGhlIGZvbGxvd2luZyBncmFwaGljcyBmdW5jdGlvbnM6IGBhdXRvcGxvdCgpYCwgYGdnX3NlYXNvbigpYCwgYGdnX3N1YnNlcmllcygpYCwgYGdnX2xhZygpYCwgYEFDRigpYCBhbmQgZXhwbG9yZSBmZWF0dXJlcyBmcm9tIHRoZSBmb2xsb3dpbmcgdGltZSBzZXJpZXM6IOKAnFRvdGFsIFByaXZhdGXigJ0gYEVtcGxveWVkYCBmcm9tIGB1c19lbXBsb3ltZW50YCwgYEJyaWNrc2AgZnJvbSBgYXVzX3Byb2R1Y3Rpb25gLCBgSGFyZWAgZnJvbSBgcGVsdGAsIOKAnEgwMuKAnSBgQ29zdGAgZnJvbSBgUEJTYCwgYW5kIGBCYXJyZWxzYCBmcm9tIGB1c19nYXNvbGluZWAuDQoNCmkuIENhbiB5b3Ugc3BvdCBhbnkgc2Vhc29uYWxpdHksIGN5Y2xpY2l0eSBhbmQgdHJlbmQ/DQppaS4gV2hhdCBkbyB5b3UgbGVhcm4gYWJvdXQgdGhlIHNlcmllcz8NCmlpaS4gV2hhdCBjYW4geW91IHNheSBhYm91dCB0aGUgc2Vhc29uYWwgcGF0dGVybnM/DQppdi4gQ2FuIHlvdSBpZGVudGlmeSBhbnkgdW51c3VhbCB5ZWFycz8NCg0KIyMgVG90YWwgUHJpdmF0ZQ0KDQoqKkV4YW1wbGUqKg0KDQogICAgICB2aWNfZWxlYyB8PiBnZ19zZWFzb24oRGVtYW5kLCBwZXJpb2QgPSAiZGF5IikgKw0KICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgICAgICAgbGFicyh5PSJNV2giLCB0aXRsZT0iRWxlY3RyaWNpdHkgZGVtYW5kOiBWaWN0b3JpYSIpDQoNCmBgYHtyfQ0KdXNfZW1wbG95bWVudA0KYGBgDQoNCg0KYGBge3J9DQp1c19lbXBsb3ltZW50JT4lDQogIGZpbHRlcihUaXRsZT09IlRvdGFsIFByaXZhdGUiKSU+JQ0KICBhdXRvcGxvdChFbXBsb3llZCxwZXJpb2Q9Im1vbnRoIikgDQoNCnVzX2VtcGxveW1lbnQlPiUNCiAgZmlsdGVyKFRpdGxlPT0iVG90YWwgUHJpdmF0ZSIpJT4lDQogIGdnX3NlYXNvbihFbXBsb3llZCwgcG9sYXIgPSBGQUxTRSkNCg0KdXNfZW1wbG95bWVudCU+JQ0KICBmaWx0ZXIoVGl0bGU9PSJUb3RhbCBQcml2YXRlIiklPiUNCiAgZ2dfc2Vhc29uKEVtcGxveWVkLCBwb2xhciA9IFRSVUUpIA0KDQp1c19lbXBsb3ltZW50JT4lDQogIGZpbHRlcihUaXRsZT09IlRvdGFsIFByaXZhdGUiKSU+JQ0KICBnZ19zdWJzZXJpZXMoRW1wbG95ZWQpDQoNCnVzX2VtcGxveW1lbnQlPiUNCiAgZmlsdGVyKFRpdGxlPT0iVG90YWwgUHJpdmF0ZSIpJT4lDQogIGdnX2xhZyhFbXBsb3llZCkNCg0KYGBgDQoNCmBgYHtyfQ0KdXNfZW1wbG95bWVudCU+JQ0KICBmaWx0ZXIoVGl0bGU9PSJUb3RhbCBQcml2YXRlIiklPiUNCiAgQUNGKHVzX2VtcGxveW1lbnQkRW1wbG95ZWQpJT4lDQogIGF1dG9wbG90KCkNCmBgYA0KDQojIyMgaQ0KDQpUaGVyZSBpcyBhIGNsZWFyIHVwd2FyZHMgdHJlbmQgaW4gc21hbGwgaW5jcmVtZW50cyBmb3IgdGhlIGRhdGEuDQoNCiMjIyBpaQ0KDQpHcm93dGggaGFzIGJlZW4gY29uc2lzdGVudCB3aXRob3V0IGFueSBleHRyZW1lIHNwaWtlIG9yIGRyb3AuDQoNCiMjIyBpaWkNCg0KTm8gU2Vhc29uYWxpdHkgaXMgbm90ZWQgaW5kaWNhdGluZyB0aGVyZSBpcyBub3QgcGFydGljdWxhciBzZWFzb24gd2l0aCBhbiBhZmZlY3Qgb24gZW1wbG95bWVudCBwb3NpdGl2ZSBvciBuZWdhdGl2ZS4NCg0KIyMjIGl2DQoNCkEgc21hbGwgZGlwIGFyb3VuZCAyMDEwIHdoaWNoIEkgYmVsaWV2ZSBhbGlnbnMgd2l0aCB0aGUgcmVjZXNzaW9uLg0KDQojIyBCcmlja3MNCg0KYGBge3J9DQphdXNfcHJvZHVjdGlvbg0KYGBgDQoNCg0KYGBge3J9DQphdXNfcHJvZHVjdGlvbiU+JQ0KICBzZWxlY3QoQnJpY2tzKSU+JQ0KICBhdXRvcGxvdChwZXJpb2Q9InF1YXJ0ZXIiKSANCg0KYXVzX3Byb2R1Y3Rpb24lPiUNCiAgc2VsZWN0KEJyaWNrcyklPiUNCiAgZ2dfc2Vhc29uKCBwb2xhciA9IEZBTFNFKQ0KDQphdXNfcHJvZHVjdGlvbiU+JQ0KICBzZWxlY3QoQnJpY2tzKSU+JQ0KICBnZ19zZWFzb24oIHBvbGFyID0gVFJVRSkgDQogDQphdXNfcHJvZHVjdGlvbiU+JQ0KICBzZWxlY3QoQnJpY2tzKSU+JQ0KICBnZ19zdWJzZXJpZXMoKQ0KDQphdXNfcHJvZHVjdGlvbiU+JQ0KICBzZWxlY3QoQnJpY2tzKSU+JQ0KICBnZ19sYWcoKQ0KDQpgYGANCg0KYGBge3J9DQphdXNfcHJvZHVjdGlvbiU+JQ0KICBzZWxlY3QoQnJpY2tzKSU+JQ0KICBBQ0YoYXVzX3Byb2R1Y3Rpb24kQnJpY2tzKSU+JQ0KICBhdXRvcGxvdCgpDQpgYGANCg0KIyMjIGkNCg0KVGhlcmUgaXMgbG90cyBvZiBjeWNsaWNpdHkgd2l0aCBmcmVxdWVudCBzcGlrZXMgYW5kIGRpcHMsIGJ1dCBpdCBkb2VzIG5vdCBhcHBlYXIgdG8gYmUgY29uc2lzdGVudCB0byBhIHRpbWUgcGVyaW9kLlRoZXJlIGlzIGEgcG9zaXRpdmUgdXB3YXJkIHRyZW5kIGluIHRoZSBsb25nIHRlcm0uDQoNCiMjIyBpaQ0KDQpUaGUgZGF0YSBiZWluZyBicm9rZW4gZG93biB0byBRdWFydGVycyBteSBpbmZsdWVuY2UgaG93IHdlbGwgd2UgY2FuIGFzc2VzcyB0aGUgcG90ZW50aWFsIHNlYXNvbmFsaXR5LiBBcyBpcywgdGhlcmUgZG9lcyAgc2VlbSB0byBiZSBvbmUuDQoNCiMjIyBpaWkNCg0KVGhlcmUgc2VlbXMgdG8gYmUgc29tZSBzZWFzb25hbGl0eSBhcyBmYXIgYXMgUTEgYW5kIFEzIGlzIGNvbmNlcm5lZC4NCg0KIyMjIGl2DQoNClRoZSBlYXJseSAxOTgwcyBoYXMgYSBzaWduaWZpY2FudCBkaXAgc28gSSB3b3VsZCBiZSBjdXJpb3VzIHRvIHVuZGVyc3RhbmQgd2hhdCBtYXkgaGF2ZSBjYXVzZSB0aGlzLg0KDQojIyBIYXJlDQoNCmBgYHtyfQ0KcGVsdA0KYGBgDQoNCg0KYGBge3J9DQpwZWx0JT4lDQogIHNlbGVjdChIYXJlKSU+JQ0KICBhdXRvcGxvdChwZXJpb2Q9InllYXIiKSANCg0KI05vdCBwb3NzaWJsZQ0KIyBwZWx0JT4lDQojICAgc2VsZWN0KEhhcmUpJT4lDQojICAgZ2dfc2Vhc29uKCBwb2xhciA9IEZBTFNFKQ0KIyANCiMgcGVsdCU+JQ0KIyAgIHNlbGVjdChIYXJlKSU+JQ0KIyAgIGdnX3NlYXNvbiggcG9sYXIgPSBUUlVFKSANCiANCnBlbHQlPiUNCiAgc2VsZWN0KEhhcmUpJT4lDQogIGdnX3N1YnNlcmllcygpDQoNCnBlbHQlPiUNCiAgc2VsZWN0KEhhcmUpJT4lDQogIGdnX2xhZygpDQpgYGANCmBgYHtyfQ0KcGVsdCU+JQ0KICBzZWxlY3QoSGFyZSklPiUNCiAgQUNGKCklPiUNCiAgYXV0b3Bsb3QoKQ0KYGBgDQoNCiMjIyBpDQoNClRoZSBkYXRhIGlzIGRlZmluaXRlbHkgY3ljbGljYWwgYnV0IGl0cyBub3QgcG9zc2libGUgdG8gdGVhbCBzZWFzb25hbGl0eSBzaW5jZSBpdHMgYXQgYSBhbm51YWwgYmFzaXMuDQoNCiMjIyBpaQ0KDQpUaGUgZGF0YSBkb2VzIG5vdCB0cmVuZCBhbmQgdmFyaWVzIGEgZ3JlYXQgZGVhbC4gQnV0IHNlZW1zIHRvIGhhdmUgYSBwYXR0ZXJuIGF0IGEgNSB5ZWFyIGludGVydmFsLg0KDQojIyMgaWlpDQoNCkFnYWluIG5vIHNlYXNvbmFsaXR5DQoNCiMjIyBpdg0KDQpJbSBjdXJpb3VzIHdoYXQgY2F1c2VkIHRoZSBwZWFrIGluIHRoZSBlYXJseSAxODYwcw0KDQojIyBDb3N0DQoNCmBgYHtyfQ0KUEJTDQpgYGANCg0KDQpgYGB7cn0NClBCUyU+JQ0KICBmaWx0ZXIoQVRDMj09IkgwMiIpJT4lDQogIGF1dG9wbG90KENvc3QpIA0KDQpQQlMgJT4lIA0KICBmaWx0ZXIoQVRDMiA9PSAiSDAyIikgJT4lDQogIGdnX3NlYXNvbihDb3N0LCBwb2xhciA9IEZBTFNFKQ0KDQpQQlMgJT4lIA0KICBmaWx0ZXIoQVRDMiA9PSAiSDAyIikgJT4lDQogIGdnX3N1YnNlcmllcyhDb3N0KQ0KDQojIFBCUyAlPiUgDQojICAgZmlsdGVyKEFUQzIgPT0gIkgwMiIpICU+JQ0KIyAgIGdnX2xhZyhDb3N0KQ0KDQpgYGANCg0KYGBge3J9DQpQQlMgJT4lIA0KICBmaWx0ZXIoQVRDMiA9PSAiSDAyIikgJT4lDQogIEFDRihDb3N0KSU+JQ0KICBhdXRvcGxvdCgpDQpgYGANCg0KIyMjIGkgDQoNClRoZSBkYXRhIGlzIGhhcmQgdG8gaW50ZXJwcmV0IGJ1dCBpdCBhcHBlYXJzIHRvIHRyZW5kIHVwd2FyZHMgd2l0aCBjeWNsaWNpdHkgYW5kIHNlYXNvbmFsaXR5Lg0KIyMjIGlpDQoNCnRoZSBkYXRhIGlzIHZlcnkgdm9sYXRpbGUgYnV0IHNwaWtlcyBtYWlubHkgZW5kIG9mIHllYXIgaXQgYXBwZWFycy4NCg0KIyMjIGlpaQ0KDQpUaGUgc2Vhc29uYWxpdHkgaXMgYXQgdGhlIGVuZCBvZiB0aGUgeWVhci4NCg0KIyMjIGl2DQoNCk5vIHllYXIgc3RhbmRzIG91dCwgb3V0c2lkZSBvZiB0aGUgbGF0ZXN0IHllYXIgaGF2aW5nIHRoZSBoaWdoZXN0IGNvc3QuDQoNCiMjIEJhcnJlbHMNCg0KYGBge3J9DQp1c19nYXNvbGluZQ0KYGBgDQoNCg0KYGBge3J9DQp1c19nYXNvbGluZSU+JQ0KICBzZWxlY3QoQmFycmVscyklPiUNCiAgYXV0b3Bsb3QoKSANCg0KdXNfZ2Fzb2xpbmUlPiUNCiAgc2VsZWN0KEJhcnJlbHMpJT4lDQogIGdnX3NlYXNvbihwb2xhciA9IEZBTFNFKQ0KDQp1c19nYXNvbGluZSU+JQ0KICBzZWxlY3QoQmFycmVscyklPiUNCiAgZ2dfc2Vhc29uKCBwb2xhciA9IFRSVUUpIA0KDQp1c19nYXNvbGluZSU+JQ0KICBzZWxlY3QoQmFycmVscyklPiUNCiAgZ2dfc3Vic2VyaWVzKCkNCg0KdXNfZ2Fzb2xpbmUlPiUNCiAgc2VsZWN0KEJhcnJlbHMpJT4lDQogIGdnX2xhZygpDQoNCmBgYA0KDQpgYGB7cn0NCnVzX2dhc29saW5lICU+JSANCiAgc2VsZWN0KEJhcnJlbHMpICU+JQ0KICBBQ0YoKSU+JQ0KICBhdXRvcGxvdCgpDQpgYGANCg0KIyMjIGkNCg0KUHJpbWFyaWx5IGFuIHVwd2FyZCB0cmVuZCB3aXRoIGEgZGlwIG5lYXIgdGhlIG1vc3QgcmVjZW50IHllYXINCg0KIyMjIGlpDQoNCkl0cyBwb3NzaWJsZSB0aGUgYmFycmVscyB2YWx1ZSBpcyBpbXBhY3RlZCBieSBzdXBwbHkuDQoNCiMjIyBpaWkNCg0KVGhlcmUgZG9lcyBub3QgYXBwZWFyIHRvIGJlIHNlYXNvbmFsaXR5IG9mIGN5Y2xpY2l0eQ0KDQojIyMgaXYNCg0KVGhlIG1vc3QgcmVjZW50IGRpcCBpcyBpbnRlcmVzdGluZyBhbmQgSSB3b25kZXIgaWYgaXRzIGp1c3QgYSBkYXRhIGNvbGxlY3Rpb24gaXNzdWUuDQo=