The Data
Before introducing our project’s research question we would like
to introduce you to our data file first. Our data can be downloaded in
the following link:
The used excel file in this project contains more than one table
some are primary tables and some are children of those primary table.
Please check the following graph to know more about the tables structure
in our plain excel file.
Tables Structure Graph
In this project we will be making our own table that we found
most optimal for the methods we decided to use to answer our research
question.
All the tables in the data have the same columns and they
are:
- Unadjusted Number of paid employees: count of
employees without any adjustments for seasonal or calendar
variations.
- Calendar adjusted Number of paid employees: count
of employees adjusted to account for calendar-related variations, such
as the number of working days in a month or year.
- Calendar adjusted Annual change (%): the percentage
change in the number of paid employees on a year-over-year basis after
adjusting for calendar-related variations.
- Seasonally adjusted Number of paid employees: count
of employees adjusted to account for seasonal variations, such as
changes in hiring patterns that occur regularly throughout the
year.
- Seasonally adjusted Monthly change (%): the
percentage change in the number of paid employees on a month-over-month
basis after adjusting for seasonal variations.
Here’s a look into the excel file
Research Question & Project Flow
In this project we try to use mention above data to answer the
questions:
“Across the years, which sectors’ employment rate have
fallen/ risen?”
“Do we expect a specific sector employment rate to keep
declining/ rising?”
We will firstly construct the optimal table then we will try to
answer the question using representative graphs and statistical tests to
check the confidence levels of our findings.
Table Construction
Let’s start with reading in the tables.
We will first read in the “Year” & “Month” columns to attach them
to the created tables that lost it because they aren’t the first table.
We will also use the zoo function na.locf to
fill in the missing spaces in “Year” with the last year entry.
library(readxl)
library(zoo)
yearMonth = read_xls('paid employee statistics.xls', range= "A7:B182", col_names = FALSE) |>
na.locf(na.rm = FALSE)
colnames(yearMonth) = c("year", "month")
Now lets read in the following tables: Industry,
Construction, Trade & Services, and the sum of all
table…
summTable = read_xls('paid employee statistics.xls', range= "C7:G182", col_names = FALSE)
industry = read_xls('paid employee statistics.xls', range= "I7:M182", col_names = FALSE)
construction = read_xls('paid employee statistics.xls', range= "AM7:AQ182", col_names = FALSE)
trade_ser = read_xls('paid employee statistics.xls', range= "AS7:AW182", col_names = FALSE)
Now we will:
Make a function to rename the columns, attach the “year” and
“month” columns, drop the last two columns (Seasonally adjusted
Number of paid employees, Monthly change (%)) as we are our
question has a much larger scope so seasonally adjusted columns won’t be
of much use.
Map that function onto the list of our tables
library(purrr)
# table tidying function
process_table = function(table) {
colnames(table) = c("unadj_num_of_emp", "cal_adj_num_of_emp", "Annual_change_perc",
"sea_adj_num_of_emp", "Monthly change perc")
table = table[, -c(length(colnames(table))-1, length(colnames(table)))]
table = cbind(yearMonth, table)
}
proc_tables = list(summTable, industry, construction, trade_ser) |>
map(process_table)
The created proc_tables variable now is a list of each
table in the list processed we will now reassign each table to its
corresponding processed table…
summTable = proc_tables[[1]]
industry = proc_tables[[2]]
construction = proc_tables[[3]]
trade_ser = proc_tables[[4]]
Now to make our optimal table we will add a column to each table that
specifies its sector (industry, construction or trade and
services) and then join them all to one table and that will be the
table we will use for most of our data exploration and question
answering…
library(dplyr)
industry['sectors'] = 'industry'
construction['sectors'] = 'construction'
trade_ser['sectors'] = 'trade & services'
sectors_data = rbind(industry, construction, trade_ser)
sectors_data |>
mutate(sectors = factor(sectors)) -> sectors_data
Let’s have a look at the head of our table…
print(head(sectors_data))
Data Cleaning & Wrangling
NA Values
the na values in our table come from the first 12 values in each
sector in the Annual change perc. This is very expected because
we don’t have the previous year’s data. Now there are multiple ways to
deal with those na values: - we can fill those values with the mean of
the column which isn’t a wise choice because we know regarding if the
amount of the increase is significant or not, the employment rate kept
increasing through out the years so the filled values would lead us to
make false assumptions if filled with the mean. - we can fill it with
the median but it is even a worse choice than the mean for its high
bias. - we can, if the number of values isn’t significant, completely
omit those na values. The third option seems the most reasonable so we
will check the ratio of na values just to be sure
na_ratio = colMeans(is.na(sectors_data))
print(na_ratio)
As seen the ratio is only 6% of the data meaning the number isn’t
that significant so we will proceed with omitting the missing
values…
sectors_data = na.omit(sectors_data)
summTable = na.omit(summTable)
Data Wrangling
Now that we are done cleaning let’s have a look into our data and see
what we have to work with…
str(sectors_data)
we see that month is actually read as a character lets change that
quickly
library(dplyr)
sectors_data |>
mutate(month = as.numeric(month)) -> sectors_data
str(sectors_data)
Because we performed omit on our table the indices of those values
got removed and our table now has indices missing so we don’t face any
trouble later lets reset our index column…
row.names(sectors_data) <- NULL
Before applying any statistical tests let’s make a table that
calculates the rate of change for a specific sector in a specific year.
This table helps us make a bar plot and compare the sectors rate of
change in one year rather than, like in the data set, compare the month
to the month in the previous year. This table is useful because of the
small but summative data set which allows us to make plots that are more
useful when there’s a small data set like bar plots, pie charts..etc.
sectors_data |>
arrange(year, month) |>
group_by(year, sectors) |>
summarise(rate_of_change = mean(diff(unadj_num_of_emp) / lag(unadj_num_of_emp), na.rm = TRUE) * 100) -> diff_tab
print(head(diff_tab))
Visualizations
In this section we will be showing you a few graphs that we will
later use to answer our questions and validate our assumptions and
speculation. We prepared three graphs each representing a different
point of view from our data so please pay attention to the axes names
and data used as there are two different tables that have been used.
Bar plot of employments:
Now that we have our table lets make a bar plot to compare the
years…
library(ggplot2)
library(repr)
ggplot(diff_tab, aes(x = year, y = rate_of_change, fill = sectors)) +
geom_bar(stat = "identity", position = "dodge") +
theme(axis.text.x = element_text(angle = 45, vjust = 0.5)) +
scale_x_continuous(labels=as.character(diff_tab$year), breaks=diff_tab$year) +
labs(x = "Years", y = "Rate Of Change By The Year") +
ggtitle("Rate Of Change In The Number Of Employees Across The Years")
We now notice the following trend in employment across the years:
- The 2018 sudden plunge in employment can be tracked back to the
Turkish currency and debt crisis. We can assume that
economic crisis led to workplaces firing employees to avoid losing more
profit.
- The industry sector is the most unstable as it steadily plummets
then goes back up this will be more clear with the to be displayed line
plots. - The trade and services sector was always the highest in hiring
numbers.
- We can assume that the low hiring rate in 2016 is because of the
unfortunate coup events that happened that year.
- We can also assume that turkey is a very quick recoverer from
economic crises.
- The 2020 low hiring numbers in the trade & services sector can
also be tracked back to the Corona health crisis the world has went
through.
Linear Models
Lets now try making a linear model for each of the sectors…
sectors_data$month_date <- as.Date(paste(sectors_data$year, sectors_data$month, "01", sep = "-"))
ggplot(sectors_data, aes(x = month_date, y = unadj_num_of_emp)) +
geom_point(size = 1) +
geom_smooth(method = 'lm', formula = y ~ x, se = FALSE, color = 'red') +
facet_wrap(~ sectors) +
labs(x = "Years", y = "Unadjusted # Of Employments \n IN MILLIONS",
title = "Linear Model For Each Sector Across The Years Since 2010") +
scale_x_date(date_breaks = "1 year", date_labels = "%Y", expand = c(0.02, 0)) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_y_continuous(labels = scales::comma_format(scale = 1e-6))
From the linear models we can see that the order of the rate of
growth (slope) is :
Trade & Services > Industry >
Construction.
- we also notice a continuous pattern in the trade & services
sector indicating constant firing and employment which might mean
unstableness in the sector but also can mean a more active sector.
Line plots for the annual change rate
ggplot(sectors_data, aes(x = month_date, y = Annual_change_perc)) +
geom_line(color = 'red', size=1) +
facet_wrap(~ sectors) +
labs(x = "Years", y = "Annual change percentages",
title = "Annual Year Percentages Of Each Sector Across The Years Since 2010") +
scale_x_date(date_breaks = "1 year", date_labels = "%Y", expand = c(0.02, 0)) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
This is a very interesting output. From the linear model we can see
that construction has the least change rate (slope) of the employees
numbers is very low but now that we see the raw annual change percentage
we notice a very sudden decrease and then rocketing in the variable.
However after the spikes it quickly recovers to a more stable pattern
and we can notice that the pattern isn’t a decreasing one like the other
two sectors. In the other two sectors we can see that the change
percentage is slowly decreasing in the recent three years which is very
concerning. This might mean if more opportunities are not offered we
might run into an unemployment crisis in the coming 3-4 years in those
sectors.
BONUS: Statistical Test
Mann Kendall Trend Test
This statistical non-parametric test that tests if data, collected
over time, has consistently increasing or decreasing trends in the y
values. Here’s the hypothesis of this test for anyone interested:
- H0: the data has no monotonic
trend in its time the series.
- Ha: a trend exists. This trend
can be positive, negative, or non-null.
Because this test can only be applied to one time series we will use
the tables we made for each sector but first we will omit the na values
then pass the unadjusted employees number…
- Industry
library(Kendall)
industry = na.omit(industry)
MannKendall(industry$unadj_num_of_emp)
Looking at the test statistic (tau) we notice the very close value to
1 this is a very high value because the upper bound of the test
statistic is 1. A high test value means a very strong trend in the
unudjusted number of employees column and because the p-values is very
small we are statistically very confident in our deduction.
- Construction
construction = na.omit(construction)
MannKendall(construction$unadj_num_of_emp)
We also reject the null hypothesis here but we notice that the test
value isn’t very high which means the trend is a weak one.
- Trade & Services
trade_ser = na.omit(trade_ser)
MannKendall(trade_ser$unadj_num_of_emp)
In this test as well, we reject the null hypothesis and looking at
the test statistic the trend is strong but not as strong as the industry
sector.
- overall we can say that in all sectors the number of employees have
a trend however this doesn’t neglect the fact that the employment rate
is declining by the years. This might mean that the number of employees
by the coming years is going to keep rising but not at the same rate it
used to.
CONCLUSION
Now our tests and graphs help us answer the first part of our
question. The number of employments in all sectors have significantly
changed with the type of change being uncertain according to the
statistical test we performed. However, looking at the graphs we can say
the type of change is increase with different rates of increase for
different sectors.
The second part of the research is more of a speculation part. We
need to answer the question for each sector so we will be left with
three answers. For the construction sector, we can see very dramatic and
sudden increase and decrease, so it’s hard to speculate on later years,
however using the information we obtained in the statistical test we can
say that the trend in the construction sector might not last for long if
more new jobs aren’t introduced to the industry, the trend might not
last long. For both the industry and trade & service, we notice a
more stable pattern however from the latest months we can notice a drop,
so our speculation is, if more employment opportunities aren’t offered,
we expect it to keep declining. However, this issue has risen in all
parts of the world and we should be able to face it with the help of the
government encouraging and placing rules in favor of the country’s
economy.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIFRoZSBEYXRhIHsjc2VjLXRoZS1kYXRhfQ0KDQotICAgQmVmb3JlIGludHJvZHVjaW5nIG91ciBwcm9qZWN0J3MgcmVzZWFyY2ggcXVlc3Rpb24gd2Ugd291bGQgbGlrZSB0byBpbnRyb2R1Y2UgeW91IHRvIG91ciBkYXRhIGZpbGUgZmlyc3QuIE91ciBkYXRhIGNhbiBiZSBkb3dubG9hZGVkIGluIHRoZSBmb2xsb3dpbmcgbGluazogW1x0ZXh0Y29sb3J7Ymx1ZX17UGFpZCBFbXBsb3llZSBTdGF0aXN0aWN9XShodHRwczovL2RhdGEudHVpay5nb3YudHIvYnVsdGVuL0Rvd25sb2FkSXN0YXRpc3Rpa3NlbFRhYmxvP3A9cXJNa1VxUW9KNjZYU2Yvb1NoQmNaRmFLcTZZcTkvcHI4UXdjZUk0ekpSSWFyUFlvWExiT1JkdUdaZDhUU0J5aCkNCg0KLSAgIFRoZSB1c2VkIGV4Y2VsIGZpbGUgaW4gdGhpcyBwcm9qZWN0IGNvbnRhaW5zIG1vcmUgdGhhbiBvbmUgdGFibGUgc29tZSBhcmUgcHJpbWFyeSB0YWJsZXMgYW5kIHNvbWUgYXJlIGNoaWxkcmVuIG9mIHRob3NlIHByaW1hcnkgdGFibGUuIFBsZWFzZSBjaGVjayB0aGUgZm9sbG93aW5nIGdyYXBoIHRvIGtub3cgbW9yZSBhYm91dCB0aGUgdGFibGVzIHN0cnVjdHVyZSBpbiBvdXIgcGxhaW4gZXhjZWwgZmlsZS4NCg0KICAgICFbVGFibGVzIFN0cnVjdHVyZSBHcmFwaF0oaW1hZ2VzL1RhYmxlcyUyMFN0cnVjdHVyZSUyMEdyYXBoLnBuZyl7d2lkdGg9IjMuMTNpbiJ9DQoNCi0gICBJbiB0aGlzIHByb2plY3Qgd2Ugd2lsbCBiZSBtYWtpbmcgb3VyIG93biB0YWJsZSB0aGF0IHdlIGZvdW5kIG1vc3Qgb3B0aW1hbCBmb3IgdGhlIG1ldGhvZHMgd2UgZGVjaWRlZCB0byB1c2UgdG8gYW5zd2VyIG91ciByZXNlYXJjaCBxdWVzdGlvbi4NCg0KLSAgIEFsbCB0aGUgdGFibGVzIGluIHRoZSBkYXRhIGhhdmUgdGhlIHNhbWUgY29sdW1ucyBhbmQgdGhleSBhcmU6DQoNCiAgICAtICAgKipVbmFkanVzdGVkIE51bWJlciBvZiBwYWlkIGVtcGxveWVlcyoqOiBjb3VudCBvZiBlbXBsb3llZXMgd2l0aG91dCBhbnkgYWRqdXN0bWVudHMgZm9yIHNlYXNvbmFsIG9yIGNhbGVuZGFyIHZhcmlhdGlvbnMuDQogICAgLSAgICoqQ2FsZW5kYXIgYWRqdXN0ZWQgTnVtYmVyIG9mIHBhaWQgZW1wbG95ZWVzKio6IGNvdW50IG9mIGVtcGxveWVlcyBhZGp1c3RlZCB0byBhY2NvdW50IGZvciBjYWxlbmRhci1yZWxhdGVkIHZhcmlhdGlvbnMsIHN1Y2ggYXMgdGhlIG51bWJlciBvZiB3b3JraW5nIGRheXMgaW4gYSBtb250aCBvciB5ZWFyLg0KICAgIC0gICAqKkNhbGVuZGFyIGFkanVzdGVkIEFubnVhbCBjaGFuZ2UgKCUpKio6IHRoZSBwZXJjZW50YWdlIGNoYW5nZSBpbiB0aGUgbnVtYmVyIG9mIHBhaWQgZW1wbG95ZWVzIG9uIGEgeWVhci1vdmVyLXllYXIgYmFzaXMgYWZ0ZXIgYWRqdXN0aW5nIGZvciBjYWxlbmRhci1yZWxhdGVkIHZhcmlhdGlvbnMuDQogICAgLSAgICoqU2Vhc29uYWxseSBhZGp1c3RlZCBOdW1iZXIgb2YgcGFpZCBlbXBsb3llZXMqKjogY291bnQgb2YgZW1wbG95ZWVzIGFkanVzdGVkIHRvIGFjY291bnQgZm9yIHNlYXNvbmFsIHZhcmlhdGlvbnMsIHN1Y2ggYXMgY2hhbmdlcyBpbiBoaXJpbmcgcGF0dGVybnMgdGhhdCBvY2N1ciByZWd1bGFybHkgdGhyb3VnaG91dCB0aGUgeWVhci4NCiAgICAtICAgKipTZWFzb25hbGx5IGFkanVzdGVkIE1vbnRobHkgY2hhbmdlICglKSoqOiB0aGUgcGVyY2VudGFnZSBjaGFuZ2UgaW4gdGhlIG51bWJlciBvZiBwYWlkIGVtcGxveWVlcyBvbiBhIG1vbnRoLW92ZXItbW9udGggYmFzaXMgYWZ0ZXIgYWRqdXN0aW5nIGZvciBzZWFzb25hbCB2YXJpYXRpb25zLg0KDQogICAgIVtIZXJlJ3MgYSBsb29rIGludG8gdGhlIGV4Y2VsIGZpbGVdKGltYWdlcy9jbGlwYm9hcmQtNzIzNTMwMDc5LnBuZyl7d2lkdGg9IjUwMSJ9DQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIFJlc2VhcmNoIFF1ZXN0aW9uICYgUHJvamVjdCBGbG93DQoNCkluIHRoaXMgcHJvamVjdCB3ZSB0cnkgdG8gdXNlIG1lbnRpb24gYWJvdmUgZGF0YSB0byBhbnN3ZXIgdGhlIHF1ZXN0aW9uczoNCg0KKioqIkFjcm9zcyB0aGUgeWVhcnMsIHdoaWNoIHNlY3RvcnPigJkgZW1wbG95bWVudCByYXRlIGhhdmUgZmFsbGVuLyByaXNlbj8iKioqDQoNCioqKiJEbyB3ZSBleHBlY3QgYSBzcGVjaWZpYyBzZWN0b3IgZW1wbG95bWVudCByYXRlIHRvIGtlZXAgZGVjbGluaW5nLyByaXNpbmc/IioqKg0KDQpXZSB3aWxsIGZpcnN0bHkgY29uc3RydWN0IHRoZSBvcHRpbWFsIHRhYmxlIHRoZW4gd2Ugd2lsbCB0cnkgdG8gYW5zd2VyIHRoZSBxdWVzdGlvbiB1c2luZyByZXByZXNlbnRhdGl2ZSBncmFwaHMgYW5kIHN0YXRpc3RpY2FsIHRlc3RzIHRvIGNoZWNrIHRoZSBjb25maWRlbmNlIGxldmVscyBvZiBvdXIgZmluZGluZ3MuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIFRhYmxlIENvbnN0cnVjdGlvbg0KDQpMZXQncyBzdGFydCB3aXRoIHJlYWRpbmcgaW4gdGhlIHRhYmxlcy4NCg0KV2Ugd2lsbCBmaXJzdCByZWFkIGluIHRoZSAiWWVhciIgJiAiTW9udGgiIGNvbHVtbnMgdG8gYXR0YWNoIHRoZW0gdG8gdGhlIGNyZWF0ZWQgdGFibGVzIHRoYXQgbG9zdCBpdCBiZWNhdXNlIHRoZXkgYXJlbid0IHRoZSBmaXJzdCB0YWJsZS4gV2Ugd2lsbCBhbHNvIHVzZSB0aGUgYHpvb2AgZnVuY3Rpb24gYG5hLmxvY2ZgIHRvIGZpbGwgaW4gdGhlIG1pc3Npbmcgc3BhY2VzIGluICJZZWFyIiB3aXRoIHRoZSBsYXN0IHllYXIgZW50cnkuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQogIGxpYnJhcnkocmVhZHhsKQ0KICBsaWJyYXJ5KHpvbykNCiAgDQogIHllYXJNb250aCA9IHJlYWRfeGxzKCdwYWlkIGVtcGxveWVlIHN0YXRpc3RpY3MueGxzJywgcmFuZ2U9ICJBNzpCMTgyIiwgY29sX25hbWVzID0gRkFMU0UpIHw+DQogICAgICAgICAgICAgICAgbmEubG9jZihuYS5ybSA9IEZBTFNFKQ0KICBjb2xuYW1lcyh5ZWFyTW9udGgpID0gYygieWVhciIsICJtb250aCIpDQpgYGANCg0KTm93IGxldHMgcmVhZCBpbiB0aGUgZm9sbG93aW5nIHRhYmxlczogKkluZHVzdHJ5KiwgKkNvbnN0cnVjdGlvbiosICpUcmFkZSAmIFNlcnZpY2VzLCBhbmQgdGhlIHN1bSBvZiBhbGwgdGFibGUuLi4qDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHNpemUgPSAidGlueSJ9DQogIHN1bW1UYWJsZSA9IHJlYWRfeGxzKCdwYWlkIGVtcGxveWVlIHN0YXRpc3RpY3MueGxzJywgcmFuZ2U9ICJDNzpHMTgyIiwgY29sX25hbWVzID0gRkFMU0UpDQogIGluZHVzdHJ5ID0gcmVhZF94bHMoJ3BhaWQgZW1wbG95ZWUgc3RhdGlzdGljcy54bHMnLCByYW5nZT0gIkk3Ok0xODIiLCBjb2xfbmFtZXMgPSBGQUxTRSkNCiAgY29uc3RydWN0aW9uID0gcmVhZF94bHMoJ3BhaWQgZW1wbG95ZWUgc3RhdGlzdGljcy54bHMnLCByYW5nZT0gIkFNNzpBUTE4MiIsIGNvbF9uYW1lcyA9IEZBTFNFKQ0KICB0cmFkZV9zZXIgPSByZWFkX3hscygncGFpZCBlbXBsb3llZSBzdGF0aXN0aWNzLnhscycsIHJhbmdlPSAiQVM3OkFXMTgyIiwgY29sX25hbWVzID0gRkFMU0UpDQpgYGANCg0KTm93IHdlIHdpbGw6DQoNCi0gICBNYWtlIGEgZnVuY3Rpb24gdG8gcmVuYW1lIHRoZSBjb2x1bW5zLCBhdHRhY2ggdGhlICJ5ZWFyIiBhbmQgIm1vbnRoIiBjb2x1bW5zLCBkcm9wIHRoZSBsYXN0IHR3byBjb2x1bW5zICgqU2Vhc29uYWxseSBhZGp1c3RlZCBOdW1iZXIgb2YgcGFpZCBlbXBsb3llZXMsIE1vbnRobHkgY2hhbmdlICglKSopIGFzIHdlIGFyZSBvdXIgcXVlc3Rpb24gaGFzIGEgbXVjaCBsYXJnZXIgc2NvcGUgc28gc2Vhc29uYWxseSBhZGp1c3RlZCBjb2x1bW5zIHdvbid0IGJlIG9mIG11Y2ggdXNlLg0KDQotICAgTWFwIHRoYXQgZnVuY3Rpb24gb250byB0aGUgbGlzdCBvZiBvdXIgdGFibGVzDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIHNpemUgPSAidGlueSJ9DQogIGxpYnJhcnkocHVycnIpDQogIA0KICAjIHRhYmxlIHRpZHlpbmcgZnVuY3Rpb24NCiAgcHJvY2Vzc190YWJsZSA9IGZ1bmN0aW9uKHRhYmxlKSB7DQogIGNvbG5hbWVzKHRhYmxlKSA9IGMoInVuYWRqX251bV9vZl9lbXAiLCAiY2FsX2Fkal9udW1fb2ZfZW1wIiwgIkFubnVhbF9jaGFuZ2VfcGVyYyIsDQogICAgICAgICAgICAgICAgICAgICAgInNlYV9hZGpfbnVtX29mX2VtcCIsICJNb250aGx5IGNoYW5nZSBwZXJjIikgDQogIHRhYmxlID0gdGFibGVbLCAtYyhsZW5ndGgoY29sbmFtZXModGFibGUpKS0xLCBsZW5ndGgoY29sbmFtZXModGFibGUpKSldDQogIHRhYmxlID0gY2JpbmQoeWVhck1vbnRoLCB0YWJsZSkNCiAgfQ0KICANCiAgcHJvY190YWJsZXMgPSBsaXN0KHN1bW1UYWJsZSwgaW5kdXN0cnksIGNvbnN0cnVjdGlvbiwgdHJhZGVfc2VyKSB8PiANCiAgICAgICAgICAgICAgICAgIG1hcChwcm9jZXNzX3RhYmxlKQ0KYGBgDQoNClRoZSBjcmVhdGVkIGBwcm9jX3RhYmxlc2AgdmFyaWFibGUgbm93IGlzIGEgbGlzdCBvZiBlYWNoIHRhYmxlIGluIHRoZSBsaXN0IHByb2Nlc3NlZCB3ZSB3aWxsIG5vdyByZWFzc2lnbiBlYWNoIHRhYmxlIHRvIGl0cyBjb3JyZXNwb25kaW5nIHByb2Nlc3NlZCB0YWJsZS4uLg0KDQpgYGB7cn0NCiAgc3VtbVRhYmxlID0gcHJvY190YWJsZXNbWzFdXQ0KICBpbmR1c3RyeSA9IHByb2NfdGFibGVzW1syXV0NCiAgY29uc3RydWN0aW9uID0gcHJvY190YWJsZXNbWzNdXQ0KICB0cmFkZV9zZXIgPSBwcm9jX3RhYmxlc1tbNF1dDQpgYGANCg0KTm93IHRvIG1ha2Ugb3VyIG9wdGltYWwgdGFibGUgd2Ugd2lsbCBhZGQgYSBjb2x1bW4gdG8gZWFjaCB0YWJsZSB0aGF0IHNwZWNpZmllcyBpdHMgc2VjdG9yICgqaW5kdXN0cnksIGNvbnN0cnVjdGlvbiogb3IgKnRyYWRlIGFuZCBzZXJ2aWNlcyopIGFuZCB0aGVuIGpvaW4gdGhlbSBhbGwgdG8gb25lIHRhYmxlIGFuZCB0aGF0IHdpbGwgYmUgdGhlIHRhYmxlIHdlIHdpbGwgdXNlIGZvciBtb3N0IG9mIG91ciBkYXRhIGV4cGxvcmF0aW9uIGFuZCBxdWVzdGlvbiBhbnN3ZXJpbmcuLi4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiAgbGlicmFyeShkcGx5cikNCg0KICBpbmR1c3RyeVsnc2VjdG9ycyddID0gJ2luZHVzdHJ5Jw0KICBjb25zdHJ1Y3Rpb25bJ3NlY3RvcnMnXSA9ICdjb25zdHJ1Y3Rpb24nDQogIHRyYWRlX3Nlclsnc2VjdG9ycyddID0gJ3RyYWRlICYgc2VydmljZXMnDQogIA0KICBzZWN0b3JzX2RhdGEgPSByYmluZChpbmR1c3RyeSwgY29uc3RydWN0aW9uLCB0cmFkZV9zZXIpDQogIHNlY3RvcnNfZGF0YSB8Pg0KICAgIG11dGF0ZShzZWN0b3JzID0gZmFjdG9yKHNlY3RvcnMpKSAtPiBzZWN0b3JzX2RhdGENCmBgYA0KDQpMZXQncyBoYXZlIGEgbG9vayBhdCB0aGUgaGVhZCBvZiBvdXIgdGFibGUuLi4NCg0KYGBge3J9DQogIHByaW50KGhlYWQoc2VjdG9yc19kYXRhKSkNCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBEYXRhIENsZWFuaW5nICYgV3JhbmdsaW5nDQoNCiMjIE5BIFZhbHVlcw0KDQp0aGUgbmEgdmFsdWVzIGluIG91ciB0YWJsZSBjb21lIGZyb20gdGhlIGZpcnN0IDEyIHZhbHVlcyBpbiBlYWNoIHNlY3RvciBpbiB0aGUgKkFubnVhbCBjaGFuZ2UgcGVyYyouIFRoaXMgaXMgdmVyeSBleHBlY3RlZCBiZWNhdXNlIHdlIGRvbid0IGhhdmUgdGhlIHByZXZpb3VzIHllYXIncyBkYXRhLiBOb3cgdGhlcmUgYXJlIG11bHRpcGxlIHdheXMgdG8gZGVhbCB3aXRoIHRob3NlIG5hIHZhbHVlczogLSB3ZSBjYW4gZmlsbCB0aG9zZSB2YWx1ZXMgd2l0aCB0aGUgbWVhbiBvZiB0aGUgY29sdW1uIHdoaWNoIGlzbid0IGEgd2lzZSBjaG9pY2UgYmVjYXVzZSB3ZSBrbm93IHJlZ2FyZGluZyBpZiB0aGUgYW1vdW50IG9mIHRoZSBpbmNyZWFzZSBpcyBzaWduaWZpY2FudCBvciBub3QsIHRoZSBlbXBsb3ltZW50IHJhdGUga2VwdCBpbmNyZWFzaW5nIHRocm91Z2ggb3V0IHRoZSB5ZWFycyBzbyB0aGUgZmlsbGVkIHZhbHVlcyB3b3VsZCBsZWFkIHVzIHRvIG1ha2UgZmFsc2UgYXNzdW1wdGlvbnMgaWYgZmlsbGVkIHdpdGggdGhlIG1lYW4uIC0gd2UgY2FuIGZpbGwgaXQgd2l0aCB0aGUgbWVkaWFuIGJ1dCBpdCBpcyBldmVuIGEgd29yc2UgY2hvaWNlIHRoYW4gdGhlIG1lYW4gZm9yIGl0cyBoaWdoIGJpYXMuIC0gd2UgY2FuLCBpZiB0aGUgbnVtYmVyIG9mIHZhbHVlcyBpc24ndCBzaWduaWZpY2FudCwgY29tcGxldGVseSBvbWl0IHRob3NlIG5hIHZhbHVlcy4gVGhlIHRoaXJkIG9wdGlvbiBzZWVtcyB0aGUgbW9zdCByZWFzb25hYmxlIHNvIHdlIHdpbGwgY2hlY2sgdGhlIHJhdGlvIG9mIG5hIHZhbHVlcyBqdXN0IHRvIGJlIHN1cmUNCg0KYGBge3J9DQogIG5hX3JhdGlvID0gY29sTWVhbnMoaXMubmEoc2VjdG9yc19kYXRhKSkNCiAgcHJpbnQobmFfcmF0aW8pDQpgYGANCg0KQXMgc2VlbiB0aGUgcmF0aW8gaXMgb25seSA2JSBvZiB0aGUgZGF0YSBtZWFuaW5nIHRoZSBudW1iZXIgaXNuJ3QgdGhhdCBzaWduaWZpY2FudCBzbyB3ZSB3aWxsIHByb2NlZWQgd2l0aCBvbWl0dGluZyB0aGUgbWlzc2luZyB2YWx1ZXMuLi4NCg0KYGBge3J9DQogIHNlY3RvcnNfZGF0YSA9IG5hLm9taXQoc2VjdG9yc19kYXRhKQ0KICBzdW1tVGFibGUgPSBuYS5vbWl0KHN1bW1UYWJsZSkNCmBgYA0KDQojIyBEYXRhIFdyYW5nbGluZw0KDQpOb3cgdGhhdCB3ZSBhcmUgZG9uZSBjbGVhbmluZyBsZXQncyBoYXZlIGEgbG9vayBpbnRvIG91ciBkYXRhIGFuZCBzZWUgd2hhdCB3ZSBoYXZlIHRvIHdvcmsgd2l0aC4uLg0KDQpgYGB7cn0NCiAgc3RyKHNlY3RvcnNfZGF0YSkNCmBgYA0KDQpcYnJlYWsNCg0Kd2Ugc2VlIHRoYXQgbW9udGggaXMgYWN0dWFsbHkgcmVhZCBhcyBhIGNoYXJhY3RlciBsZXRzIGNoYW5nZSB0aGF0IHF1aWNrbHkNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiAgbGlicmFyeShkcGx5cikNCiAgc2VjdG9yc19kYXRhIHw+DQogICAgbXV0YXRlKG1vbnRoID0gYXMubnVtZXJpYyhtb250aCkpIC0+IHNlY3RvcnNfZGF0YQ0KICBzdHIoc2VjdG9yc19kYXRhKQ0KYGBgDQoNCkJlY2F1c2Ugd2UgcGVyZm9ybWVkIG9taXQgb24gb3VyIHRhYmxlIHRoZSBpbmRpY2VzIG9mIHRob3NlIHZhbHVlcyBnb3QgcmVtb3ZlZCBhbmQgb3VyIHRhYmxlIG5vdyBoYXMgaW5kaWNlcyBtaXNzaW5nIHNvIHdlIGRvbid0IGZhY2UgYW55IHRyb3VibGUgbGF0ZXIgbGV0cyByZXNldCBvdXIgaW5kZXggY29sdW1uLi4uDQoNCmBgYHtyfQ0KICByb3cubmFtZXMoc2VjdG9yc19kYXRhKSA8LSBOVUxMDQpgYGANCg0KQmVmb3JlIGFwcGx5aW5nIGFueSBzdGF0aXN0aWNhbCB0ZXN0cyBsZXQncyBtYWtlIGEgdGFibGUgdGhhdCBjYWxjdWxhdGVzIHRoZSByYXRlIG9mIGNoYW5nZSBmb3IgYSBzcGVjaWZpYyBzZWN0b3IgaW4gYSBzcGVjaWZpYyB5ZWFyLiBUaGlzIHRhYmxlIGhlbHBzIHVzIG1ha2UgYSBiYXIgcGxvdCBhbmQgY29tcGFyZSB0aGUgc2VjdG9ycyByYXRlIG9mIGNoYW5nZSBpbiBvbmUgeWVhciByYXRoZXIgdGhhbiwgbGlrZSBpbiB0aGUgZGF0YSBzZXQsIGNvbXBhcmUgdGhlIG1vbnRoIHRvIHRoZSBtb250aCBpbiB0aGUgcHJldmlvdXMgeWVhci4gVGhpcyB0YWJsZSBpcyB1c2VmdWwgYmVjYXVzZSBvZiB0aGUgc21hbGwgYnV0IHN1bW1hdGl2ZSBkYXRhIHNldCB3aGljaCBhbGxvd3MgdXMgdG8gbWFrZSBwbG90cyB0aGF0IGFyZSBtb3JlIHVzZWZ1bCB3aGVuIHRoZXJlJ3MgYSBzbWFsbCBkYXRhIHNldCBsaWtlIGJhciBwbG90cywgcGllIGNoYXJ0cy4uZXRjLiBcZm9vdG5vdGVzaXplDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQogIHNlY3RvcnNfZGF0YSB8Pg0KICAgIGFycmFuZ2UoeWVhciwgbW9udGgpIHw+DQogICAgZ3JvdXBfYnkoeWVhciwgc2VjdG9ycykgfD4NCiAgICBzdW1tYXJpc2UocmF0ZV9vZl9jaGFuZ2UgPSBtZWFuKGRpZmYodW5hZGpfbnVtX29mX2VtcCkgLyBsYWcodW5hZGpfbnVtX29mX2VtcCksIG5hLnJtID0gVFJVRSkgKiAxMDApIC0+IGRpZmZfdGFiDQogIHByaW50KGhlYWQoZGlmZl90YWIpKQ0KYGBgDQoNClxub3JtYWxzaXplDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIFZpc3VhbGl6YXRpb25zDQoNCkluIHRoaXMgc2VjdGlvbiB3ZSB3aWxsIGJlIHNob3dpbmcgeW91IGEgZmV3IGdyYXBocyB0aGF0IHdlIHdpbGwgbGF0ZXIgdXNlIHRvIGFuc3dlciBvdXIgcXVlc3Rpb25zIGFuZCB2YWxpZGF0ZSBvdXIgYXNzdW1wdGlvbnMgYW5kIHNwZWN1bGF0aW9uLiBXZSBwcmVwYXJlZCB0aHJlZSBncmFwaHMgZWFjaCByZXByZXNlbnRpbmcgYSBkaWZmZXJlbnQgcG9pbnQgb2YgdmlldyBmcm9tIG91ciBkYXRhIHNvIHBsZWFzZSBwYXkgYXR0ZW50aW9uIHRvIHRoZSBheGVzIG5hbWVzIGFuZCBkYXRhIHVzZWQgYXMgdGhlcmUgYXJlIHR3byBkaWZmZXJlbnQgdGFibGVzIHRoYXQgaGF2ZSBiZWVuIHVzZWQuDQoNClxicmVhaw0KDQojIyBCYXIgcGxvdCBvZiBlbXBsb3ltZW50czoNCg0KTm93IHRoYXQgd2UgaGF2ZSBvdXIgdGFibGUgbGV0cyBtYWtlIGEgYmFyIHBsb3QgdG8gY29tcGFyZSB0aGUgeWVhcnMuLi4NCg0KYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTIsIHdhcm5pbmc9RkFMU0V9DQogIGxpYnJhcnkoZ2dwbG90MikNCiAgbGlicmFyeShyZXByKQ0KDQogIGdncGxvdChkaWZmX3RhYiwgYWVzKHggPSB5ZWFyLCB5ID0gcmF0ZV9vZl9jaGFuZ2UsIGZpbGwgPSBzZWN0b3JzKSkgKw0KICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsgDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAwLjUpKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscz1hcy5jaGFyYWN0ZXIoZGlmZl90YWIkeWVhciksIGJyZWFrcz1kaWZmX3RhYiR5ZWFyKSArDQogICAgbGFicyh4ID0gIlllYXJzIiwgeSA9ICJSYXRlIE9mIENoYW5nZSBCeSBUaGUgWWVhciIpICsNCiAgICBnZ3RpdGxlKCJSYXRlIE9mIENoYW5nZSBJbiBUaGUgTnVtYmVyIE9mIEVtcGxveWVlcyBBY3Jvc3MgVGhlIFllYXJzIikNCmBgYA0KDQpXZSBub3cgbm90aWNlIHRoZSBmb2xsb3dpbmcgdHJlbmQgaW4gZW1wbG95bWVudCBhY3Jvc3MgdGhlIHllYXJzOg0KDQotICAgVGhlIDIwMTggc3VkZGVuIHBsdW5nZSBpbiBlbXBsb3ltZW50IGNhbiBiZSB0cmFja2VkIGJhY2sgdG8gdGhlICoqVHVya2lzaCBjdXJyZW5jeSBhbmQgZGVidCBjcmlzaXMuKiogV2UgY2FuIGFzc3VtZSB0aGF0IGVjb25vbWljIGNyaXNpcyBsZWQgdG8gd29ya3BsYWNlcyBmaXJpbmcgZW1wbG95ZWVzIHRvIGF2b2lkIGxvc2luZyBtb3JlIHByb2ZpdC4NCi0gICBUaGUgaW5kdXN0cnkgc2VjdG9yIGlzIHRoZSBtb3N0IHVuc3RhYmxlIGFzIGl0IHN0ZWFkaWx5IHBsdW1tZXRzIHRoZW4gZ29lcyBiYWNrIHVwIHRoaXMgd2lsbCBiZSBtb3JlIGNsZWFyIHdpdGggdGhlIHRvIGJlIGRpc3BsYXllZCBsaW5lIHBsb3RzLiAtIFRoZSB0cmFkZSBhbmQgc2VydmljZXMgc2VjdG9yIHdhcyBhbHdheXMgdGhlIGhpZ2hlc3QgaW4gaGlyaW5nIG51bWJlcnMuDQotICAgV2UgY2FuIGFzc3VtZSB0aGF0IHRoZSBsb3cgaGlyaW5nIHJhdGUgaW4gMjAxNiBpcyBiZWNhdXNlIG9mIHRoZSB1bmZvcnR1bmF0ZSBjb3VwIGV2ZW50cyB0aGF0IGhhcHBlbmVkIHRoYXQgeWVhci4NCi0gICBXZSBjYW4gYWxzbyBhc3N1bWUgdGhhdCB0dXJrZXkgaXMgYSB2ZXJ5IHF1aWNrIHJlY292ZXJlciBmcm9tIGVjb25vbWljIGNyaXNlcy4NCi0gICBUaGUgMjAyMCBsb3cgaGlyaW5nIG51bWJlcnMgaW4gdGhlIHRyYWRlICYgc2VydmljZXMgc2VjdG9yIGNhbiBhbHNvIGJlIHRyYWNrZWQgYmFjayB0byB0aGUgQ29yb25hIGhlYWx0aCBjcmlzaXMgdGhlIHdvcmxkIGhhcyB3ZW50IHRocm91Z2guDQoNCiMjIExpbmVhciBNb2RlbHMNCg0KTGV0cyBub3cgdHJ5IG1ha2luZyBhIGxpbmVhciBtb2RlbCBmb3IgZWFjaCBvZiB0aGUgc2VjdG9ycy4uLg0KDQpgYGB7ciAgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTJ9DQogIHNlY3RvcnNfZGF0YSRtb250aF9kYXRlIDwtIGFzLkRhdGUocGFzdGUoc2VjdG9yc19kYXRhJHllYXIsIHNlY3RvcnNfZGF0YSRtb250aCwgIjAxIiwgc2VwID0gIi0iKSkNCiAgDQogIGdncGxvdChzZWN0b3JzX2RhdGEsIGFlcyh4ID0gbW9udGhfZGF0ZSwgeSA9IHVuYWRqX251bV9vZl9lbXApKSArDQogICAgZ2VvbV9wb2ludChzaXplID0gMSkgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScsIGZvcm11bGEgPSB5IH4geCwgc2UgPSBGQUxTRSwgY29sb3IgPSAncmVkJykgKw0KICAgIGZhY2V0X3dyYXAofiBzZWN0b3JzKSArDQogICAgbGFicyh4ID0gIlllYXJzIiwgeSA9ICJVbmFkanVzdGVkICMgT2YgRW1wbG95bWVudHMgXG4gSU4gTUlMTElPTlMiLCANCiAgICAgICAgIHRpdGxlID0gIkxpbmVhciBNb2RlbCBGb3IgRWFjaCBTZWN0b3IgQWNyb3NzIFRoZSBZZWFycyBTaW5jZSAyMDEwIikgKw0KICAgIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsIGV4cGFuZCA9IGMoMC4wMiwgMCkpICsNCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWFfZm9ybWF0KHNjYWxlID0gMWUtNikpDQogIA0KYGBgDQoNCkZyb20gdGhlIGxpbmVhciBtb2RlbHMgd2UgY2FuIHNlZSB0aGF0IHRoZSBvcmRlciBvZiB0aGUgcmF0ZSBvZiBncm93dGggKHNsb3BlKSBpcyA6DQoNCioqKlRyYWRlICYgU2VydmljZXMgXD4gSW5kdXN0cnkgXD4gQ29uc3RydWN0aW9uLioqKg0KDQotICAgd2UgYWxzbyBub3RpY2UgYSBjb250aW51b3VzIHBhdHRlcm4gaW4gdGhlIHRyYWRlICYgc2VydmljZXMgc2VjdG9yIGluZGljYXRpbmcgY29uc3RhbnQgZmlyaW5nIGFuZCBlbXBsb3ltZW50IHdoaWNoIG1pZ2h0IG1lYW4gdW5zdGFibGVuZXNzIGluIHRoZSBzZWN0b3IgYnV0IGFsc28gY2FuIG1lYW4gYSBtb3JlIGFjdGl2ZSBzZWN0b3IuDQoNCiMjIExpbmUgcGxvdHMgZm9yIHRoZSBhbm51YWwgY2hhbmdlIHJhdGUNCg0KYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQogIGdncGxvdChzZWN0b3JzX2RhdGEsIGFlcyh4ID0gbW9udGhfZGF0ZSwgeSA9IEFubnVhbF9jaGFuZ2VfcGVyYykpICsNCiAgICBnZW9tX2xpbmUoY29sb3IgPSAncmVkJywgc2l6ZT0xKSArDQogICAgZmFjZXRfd3JhcCh+IHNlY3RvcnMpICsNCiAgICBsYWJzKHggPSAiWWVhcnMiLCB5ID0gIkFubnVhbCBjaGFuZ2UgcGVyY2VudGFnZXMiLCANCiAgICAgICAgICAgdGl0bGUgPSAiQW5udWFsIFllYXIgUGVyY2VudGFnZXMgT2YgRWFjaCBTZWN0b3IgQWNyb3NzIFRoZSBZZWFycyBTaW5jZSAyMDEwIikgKw0KICAgIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsIGV4cGFuZCA9IGMoMC4wMiwgMCkpICsNCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQoNClRoaXMgaXMgYSB2ZXJ5IGludGVyZXN0aW5nIG91dHB1dC4gRnJvbSB0aGUgbGluZWFyIG1vZGVsIHdlIGNhbiBzZWUgdGhhdCBjb25zdHJ1Y3Rpb24gaGFzIHRoZSBsZWFzdCBjaGFuZ2UgcmF0ZSAoc2xvcGUpIG9mIHRoZSBlbXBsb3llZXMgbnVtYmVycyBpcyB2ZXJ5IGxvdyBidXQgbm93IHRoYXQgd2Ugc2VlIHRoZSByYXcgYW5udWFsIGNoYW5nZSBwZXJjZW50YWdlIHdlIG5vdGljZSBhIHZlcnkgc3VkZGVuIGRlY3JlYXNlIGFuZCB0aGVuIHJvY2tldGluZyBpbiB0aGUgdmFyaWFibGUuIEhvd2V2ZXIgYWZ0ZXIgdGhlIHNwaWtlcyBpdCBxdWlja2x5IHJlY292ZXJzIHRvIGEgbW9yZSBzdGFibGUgcGF0dGVybiBhbmQgd2UgY2FuIG5vdGljZSB0aGF0IHRoZSBwYXR0ZXJuIGlzbid0IGEgZGVjcmVhc2luZyBvbmUgbGlrZSB0aGUgb3RoZXIgdHdvIHNlY3RvcnMuIEluIHRoZSBvdGhlciB0d28gc2VjdG9ycyB3ZSBjYW4gc2VlIHRoYXQgdGhlIGNoYW5nZSBwZXJjZW50YWdlIGlzIHNsb3dseSBkZWNyZWFzaW5nIGluIHRoZSByZWNlbnQgdGhyZWUgeWVhcnMgd2hpY2ggaXMgdmVyeSBjb25jZXJuaW5nLiBUaGlzIG1pZ2h0IG1lYW4gaWYgbW9yZSBvcHBvcnR1bml0aWVzIGFyZSBub3Qgb2ZmZXJlZCB3ZSBtaWdodCBydW4gaW50byBhbiB1bmVtcGxveW1lbnQgY3Jpc2lzIGluIHRoZSBjb21pbmcgMy00IHllYXJzIGluIHRob3NlIHNlY3RvcnMuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIEJPTlVTOiBTdGF0aXN0aWNhbCBUZXN0DQoNCiMjIE1hbm4gS2VuZGFsbCBUcmVuZCBUZXN0DQoNClRoaXMgc3RhdGlzdGljYWwgbm9uLXBhcmFtZXRyaWMgdGVzdCB0aGF0IHRlc3RzIGlmIGRhdGEsIGNvbGxlY3RlZCBvdmVyIHRpbWUsIGhhcyBjb25zaXN0ZW50bHkgaW5jcmVhc2luZyBvciBkZWNyZWFzaW5nIHRyZW5kcyBpbiB0aGUgeSB2YWx1ZXMuIEhlcmUncyB0aGUgaHlwb3RoZXNpcyBvZiB0aGlzIHRlc3QgZm9yIGFueW9uZSBpbnRlcmVzdGVkOg0KDQotICAgKioqSH4wfioqKjogdGhlIGRhdGEgaGFzIG5vIG1vbm90b25pYyB0cmVuZCBpbiBpdHMgdGltZSB0aGUgc2VyaWVzLg0KLSAgICoqKkh+YX4qKio6IGEgdHJlbmQgZXhpc3RzLiBUaGlzIHRyZW5kIGNhbiBiZSBwb3NpdGl2ZSwgbmVnYXRpdmUsIG9yIG5vbi1udWxsLg0KDQpCZWNhdXNlIHRoaXMgdGVzdCBjYW4gb25seSBiZSBhcHBsaWVkIHRvIG9uZSB0aW1lIHNlcmllcyB3ZSB3aWxsIHVzZSB0aGUgdGFibGVzIHdlIG1hZGUgZm9yIGVhY2ggc2VjdG9yIGJ1dCBmaXJzdCB3ZSB3aWxsIG9taXQgdGhlIG5hIHZhbHVlcyB0aGVuIHBhc3MgdGhlIHVuYWRqdXN0ZWQgZW1wbG95ZWVzIG51bWJlci4uLg0KDQoxLiAgKipJbmR1c3RyeSoqDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0V9DQogIGxpYnJhcnkoS2VuZGFsbCkNCiAgaW5kdXN0cnkgPSAgbmEub21pdChpbmR1c3RyeSkNCiAgTWFubktlbmRhbGwoaW5kdXN0cnkkdW5hZGpfbnVtX29mX2VtcCkNCmBgYA0KDQpMb29raW5nIGF0IHRoZSB0ZXN0IHN0YXRpc3RpYyAodGF1KSB3ZSBub3RpY2UgdGhlIHZlcnkgY2xvc2UgdmFsdWUgdG8gMSB0aGlzIGlzIGEgdmVyeSBoaWdoIHZhbHVlIGJlY2F1c2UgdGhlIHVwcGVyIGJvdW5kIG9mIHRoZSB0ZXN0IHN0YXRpc3RpYyBpcyAxLiBBIGhpZ2ggdGVzdCB2YWx1ZSBtZWFucyBhIHZlcnkgc3Ryb25nIHRyZW5kIGluIHRoZSB1bnVkanVzdGVkIG51bWJlciBvZiBlbXBsb3llZXMgY29sdW1uIGFuZCBiZWNhdXNlIHRoZSBwLXZhbHVlcyBpcyB2ZXJ5IHNtYWxsIHdlIGFyZSBzdGF0aXN0aWNhbGx5IHZlcnkgY29uZmlkZW50IGluIG91ciBkZWR1Y3Rpb24uDQoNCjIuICAqKkNvbnN0cnVjdGlvbioqDQoNCmBgYHtyIHdhcm5pbmc9VFJVRX0NCiAgY29uc3RydWN0aW9uID0gIG5hLm9taXQoY29uc3RydWN0aW9uKQ0KICBNYW5uS2VuZGFsbChjb25zdHJ1Y3Rpb24kdW5hZGpfbnVtX29mX2VtcCkNCmBgYA0KDQpXZSBhbHNvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGhlcmUgYnV0IHdlIG5vdGljZSB0aGF0IHRoZSB0ZXN0IHZhbHVlIGlzbid0IHZlcnkgaGlnaCB3aGljaCBtZWFucyB0aGUgdHJlbmQgaXMgYSB3ZWFrIG9uZS4NCg0KMy4gICoqVHJhZGUgJiBTZXJ2aWNlcyoqDQoNCmBgYHtyIHdhcm5pbmc9VFJVRX0NCiAgdHJhZGVfc2VyID0gIG5hLm9taXQodHJhZGVfc2VyKQ0KICBNYW5uS2VuZGFsbCh0cmFkZV9zZXIkdW5hZGpfbnVtX29mX2VtcCkNCmBgYA0KDQpJbiB0aGlzIHRlc3QgYXMgd2VsbCwgd2UgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgYW5kIGxvb2tpbmcgYXQgdGhlIHRlc3Qgc3RhdGlzdGljIHRoZSB0cmVuZCBpcyBzdHJvbmcgYnV0IG5vdCBhcyBzdHJvbmcgYXMgdGhlIGluZHVzdHJ5IHNlY3Rvci4NCg0KLSAgIG92ZXJhbGwgd2UgY2FuIHNheSB0aGF0IGluIGFsbCBzZWN0b3JzIHRoZSBudW1iZXIgb2YgZW1wbG95ZWVzIGhhdmUgYSB0cmVuZCBob3dldmVyIHRoaXMgZG9lc24ndCBuZWdsZWN0IHRoZSBmYWN0IHRoYXQgdGhlIGVtcGxveW1lbnQgcmF0ZSBpcyBkZWNsaW5pbmcgYnkgdGhlIHllYXJzLiBUaGlzIG1pZ2h0IG1lYW4gdGhhdCB0aGUgbnVtYmVyIG9mIGVtcGxveWVlcyBieSB0aGUgY29taW5nIHllYXJzIGlzIGdvaW5nIHRvIGtlZXAgcmlzaW5nIGJ1dCBub3QgYXQgdGhlIHNhbWUgcmF0ZSBpdCB1c2VkIHRvLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBDT05DTFVTSU9ODQoNCk5vdyBvdXIgdGVzdHMgYW5kIGdyYXBocyBoZWxwIHVzIGFuc3dlciB0aGUgZmlyc3QgcGFydCBvZiBvdXIgcXVlc3Rpb24uIFRoZSBudW1iZXIgb2YgZW1wbG95bWVudHMgaW4gYWxsIHNlY3RvcnMgaGF2ZSBzaWduaWZpY2FudGx5IGNoYW5nZWQgd2l0aCB0aGUgdHlwZSBvZiBjaGFuZ2UgYmVpbmcgdW5jZXJ0YWluIGFjY29yZGluZyB0byB0aGUgc3RhdGlzdGljYWwgdGVzdCB3ZSBwZXJmb3JtZWQuIEhvd2V2ZXIsIGxvb2tpbmcgYXQgdGhlIGdyYXBocyB3ZSBjYW4gc2F5IHRoZSB0eXBlIG9mIGNoYW5nZSBpcyBpbmNyZWFzZSB3aXRoIGRpZmZlcmVudCByYXRlcyBvZiBpbmNyZWFzZSBmb3IgZGlmZmVyZW50IHNlY3RvcnMuDQoNClRoZSBzZWNvbmQgcGFydCBvZiB0aGUgcmVzZWFyY2ggaXMgbW9yZSBvZiBhIHNwZWN1bGF0aW9uIHBhcnQuIFdlIG5lZWQgdG8gYW5zd2VyIHRoZSBxdWVzdGlvbiBmb3IgZWFjaCBzZWN0b3Igc28gd2Ugd2lsbCBiZSBsZWZ0IHdpdGggdGhyZWUgYW5zd2Vycy4gRm9yIHRoZSBjb25zdHJ1Y3Rpb24gc2VjdG9yLCB3ZSBjYW4gc2VlIHZlcnkgZHJhbWF0aWMgYW5kIHN1ZGRlbiBpbmNyZWFzZSBhbmQgZGVjcmVhc2UsIHNvIGl0J3MgaGFyZCB0byBzcGVjdWxhdGUgb24gbGF0ZXIgeWVhcnMsIGhvd2V2ZXIgdXNpbmcgdGhlIGluZm9ybWF0aW9uIHdlIG9idGFpbmVkIGluIHRoZSBzdGF0aXN0aWNhbCB0ZXN0IHdlIGNhbiBzYXkgdGhhdCB0aGUgdHJlbmQgaW4gdGhlIGNvbnN0cnVjdGlvbiBzZWN0b3IgbWlnaHQgbm90IGxhc3QgZm9yIGxvbmcgaWYgbW9yZSBuZXcgam9icyBhcmVuJ3QgaW50cm9kdWNlZCB0byB0aGUgaW5kdXN0cnksIHRoZSB0cmVuZCBtaWdodCBub3QgbGFzdCBsb25nLiBGb3IgYm90aCB0aGUgaW5kdXN0cnkgYW5kIHRyYWRlICYgc2VydmljZSwgd2Ugbm90aWNlIGEgbW9yZSBzdGFibGUgcGF0dGVybiBob3dldmVyIGZyb20gdGhlIGxhdGVzdCBtb250aHMgd2UgY2FuIG5vdGljZSBhIGRyb3AsIHNvIG91ciBzcGVjdWxhdGlvbiBpcywgaWYgbW9yZSBlbXBsb3ltZW50IG9wcG9ydHVuaXRpZXMgYXJlbid0IG9mZmVyZWQsIHdlIGV4cGVjdCBpdCB0byBrZWVwIGRlY2xpbmluZy4gSG93ZXZlciwgdGhpcyBpc3N1ZSBoYXMgcmlzZW4gaW4gYWxsIHBhcnRzIG9mIHRoZSB3b3JsZCBhbmQgd2Ugc2hvdWxkIGJlIGFibGUgdG8gZmFjZSBpdCB3aXRoIHRoZSBoZWxwIG9mIHRoZSBnb3Zlcm5tZW50IGVuY291cmFnaW5nIGFuZCBwbGFjaW5nIHJ1bGVzIGluIGZhdm9yIG9mIHRoZSBjb3VudHJ5J3MgZWNvbm9teS4NCg==