Required packages

library(dplyr)
library(stringr)
library(knitr)
library(lubridate)
library(magrittr)

Data

Dataset Description

This assessment includes 2 datasets relate to the fatal crashes on Victorian roads during the latest five year reporting period. Road Safety data is provided by VicRoads for educational and research purposes with Creative Commons license 4.0. This data is in Web Mercator (Auxiliary Sphere) projection.(Vicroads,2021) The two datasets include:

  1. “Road_Crashes_for_five_Years_Victoria.csv” (https://vicroadsopendata-vicroadsmaps.opendata.arcgis.com/datasets/vicroadsmaps::road-crashes-for-five-years-victoria/about) (Full citation in the reference list)

This dataset is about ‘Fatal and injury crashes on Victorian roads during the latest five year reporting period.’ (Victoria Department of Transport Open Data Hub). The time period is between 25/05/2015 and 5/10/2021.

  1. "Fatal_Crashes_-_Lives_Lost%2C_Last_5_Years_to_Date.csv" (https://vicroadsopendata-vicroadsmaps.opendata.arcgis.com/datasets/vicroadsmaps::fatal-crashes-lives-lost-last-5-years-to-date-160421/about) (Full citation in the reference list)

This dataset is about the fatal crashes on Victorian roads during the latest five complete years and current year to the 5th of August 2021. (Vicroads,2021)

Variables Description

This descriptions just provided only the variables used in the data preprocessing process.

Preparation

step 1.1 Import the datasets by using the read.csv() to read the .csv files and assign “na.string” argument with “U”,“Unknown”, " “,”Not known" to tell R R to treat these values as NA(not available) value. * Assign the “Road_Crashes_for_five_Years_Victoria.csv” to “Crashes” dataframe and "Fatal_Crashes_-_Lives_Lost%2C_Last_5_Years_to_Date.csv" to “Fatal”dataframe.

step 1.2 Check the dataset for pre-processing data.

step 1.3 Select the following variables that I think they are useful and drop the rest using the select() function from dplyr:

step 1.5 Rename some of variables to make them more sensible and also rename the “ACCIDENT_N” variable to “ACCIDENT_NO” to match with the variable “ACCIDENT_NO” in “Crashes” dataframe that I am going to use it to join the two dataframe in the next step. Use the rename() function from dplyr package to rename the “ACCIDENT_N” variale into “ACCIDENT_NO”, “RD_U_DESC” into “ROAD_USER”, “ACCIDENT_D” into “DATE” and “ACCIDENT_T” into “TIME”.

step 1.6 Merge 2 datasets by keeping only the observation in both dataframe using the inner_join() function from dplyr package. Joining both datasets together by variable “ACCIDENT_NO” using the argument “by” and assign the result into “Lives_lost” dataframe.

step 1.7 Rearrange the variables order by assign the positions of the variable in order that I want to arrange by using square brackets and the c() function. Leaving the rows selection part blank to subset every rows.


Crashes<- read.csv("Road_Crashes_for_five_Years_Victoria.csv", na.strings = c("U","Unknown", " ", "Not known"))
Fatal <- read.csv("Fatal_Crashes_-_Lives_Lost%2C_Last_5_Years_to_Date.csv",na.strings = c("U","Unknown", " ","Not known"))

str(Fatal)
str(Crashes)


Crashes %<>% select(ACCIDENT_NO, ACCIDENT_TYPE, DAY_OF_WEEK, SPEED_ZONE, LGA_NAME ,NO_OF_VEHICLES, ALCOHOL_RELATED)
Fatal %<>% select(ACCIDENT_N, ACCIDENT_D, ACC_TIME, AGE, RD_U_DESC)
Fatal %<>% rename(c("ACCIDENT_NO" = ACCIDENT_N, "ROAD_USER" = RD_U_DESC, "DATE" = ACCIDENT_D, "TIME" = ACC_TIME)) 

Lives_lost <- inner_join(Crashes, Fatal, by = "ACCIDENT_NO")
Lives_lost <- Lives_lost[,c(1, 8, 9, 3, 2, 6, 10, 11, 4, 5, 7 )] 
head(Lives_lost)

Understand

step 2.1 Check the structure of the dataset by using the str() function and the attributes. The result shown:

step 2.2 Variables conversion

Lives_lost %>% str()
Lives_lost %>% attributes()

Lives_lost$ACCIDENT_NO %<>% as.factor()
Lives_lost$ACCIDENT_TYPE %<>% as.factor()
Lives_lost$ROAD_USER %<>% as.factor()

Lives_lost$DAY_OF_WEEK %<>% factor(levels=c("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"), ordered=TRUE)
Lives_lost$AGE %<>% factor(levels = c(1:99), ordered = TRUE)
Lives_lost$SPEED_ZONE %<>% factor(levels = c("Camping grounds or off road", "40 km/hr","50 km/hr", "60 km/hr", "70 km/hr","75 km/hr", "80 km/hr", "90 km/hr", "100 km/hr", "110 km/hr", "Other speed limit"), ordered = TRUE)

Lives_lost$ALCOHOL_RELATED<-gsub("No", "FALSE", Lives_lost$ALCOHOL_RELATED)
Lives_lost$ALCOHOL_RELATED<-gsub("Yes", "TRUE", Lives_lost$ALCOHOL_RELATED)
Lives_lost$ALCOHOL_RELATED %<>% as.logical() 

Lives_lost %>% str()

Tidy & Manipulate Data I

Step 3 Determine whether the dataset is tidy or untidy.

To determine if my dataset is tidy or not, I used the three interrelated rules:

  1. Each variable must have its own column.
  2. Each observation must have its own row.
  3. Each value must have its own cell. (Hadley Wickham and Garrett Grolemund 2016)

From my point of view my dataset “Live_lost” is already in a tidy format as each variable have got its own column, each Observation have got its own row and Each value have got its own cell.

Tidy & Manipulate Data II

Step 4.1 Shape the format of the values from “DATE” variable by keeping the value from the first position to 10th and drop the rest by using the substr() function. Assign the “start” argument with “1” and the “stop” argument with “10” to indicate the range of position that I want to keep.

Step 4.2 Shape “TIME” variable into the easy format in preparing to use the ymd_hms() function in step 4.4 by using the str_replace_all() function from stringr package to replace “.:” with “:” and replace “.00” with “0.00”. Use the head() function to review the result.

Step 4.3 Create the new variable “DATE” by combining variable “DATE” and “TIME” together.

Step 4.4 Convert the variable “DATE” into POSIXct class using ymd_hms() function from “lubridate” package.

Step 4.5 Drop variables “TIME” by using the select() function with the c() function and the “-” operator to assign the column name “TIME” that I want to drop. Use the str() function to check the result. The result shown that:


Lives_lost$DATE %<>% substr(start = 1, stop = 10) 

Lives_lost$TIME %<>% str_replace_all(".:", ":")
Lives_lost$TIME %<>% str_replace_all(".00", "0:00")
head(Lives_lost)

Lives_lost %<>% mutate (DATE = paste(DATE, TIME, sep = " "))
Lives_lost$DATE %<>% ymd_hms()
Lives_lost %<>% select(-TIME) 
str(Lives_lost)

Scan I

Step 5.1 Check the amount of NA in each column by using the is.na() function to check for the NA value and the colSum() function to sum up the total of NA value in each column. The result found:

Step 5.2 Replace the missing values in “DAY_OF_WEEK” variable :

Step 5.2 Check the amount of NA in the whole dataset by:

Step 5.3 Subsetting the observations with NA values into the dataframe called “NA_relation_check” to be able to have a better look for the relation of the missing value with other variable.

Step 5.4 After checking, I could not find any relation to the other variable or between the observation. The missing value look like Missing completely at random (MCAR) for me. “A rule of thumb says that when the data include less than 5% random missingness which does not depend on observed or unobserved values, complete case analysis may be an acceptable approach, too”(Hannah Roos, 2021).

Step 5.5 Exclude the observations with missing values:


is.na(Lives_lost) %>% colSums()

Lives_lost$DAY_OF_WEEK <- weekdays(Lives_lost$DATE)
Lives_lost$DAY_OF_WEEK %<>% factor(levels=c("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"), ordered=TRUE)
is.na(Lives_lost$DAY_OF_WEEK) %>% which() %>% length()

is.na(Lives_lost) %>% which() %>% length()
NA_relation_check <- Lives_lost[rowSums(is.na(Lives_lost)) > 0, ]
NA_relation_check %>% head

((NA_relation_check %>% nrow)/(Lives_lost%>% nrow())) * 100
Lives_lost2<-Lives_lost[complete.cases(Lives_lost), ]
is.na(Lives_lost2)%>% which() %>% length()

Scan II

I am using the univariate outlier detection method with Non-parametric method (Box plot), to approach the “NO_OF_VEHICLES” variable because I am just focusing on one particular variable and I assume that the data is not normally distribute. For the handling process, I choose to delete all the outliers because imputing with mean does not makesense as the value indicate number of vehicles which should be integer (mean is 1.651 which is not integer) and imputing with median is not going to suit with the other variables in the observation. The processes is as following:

Step 6.1 Create Boxplot of the variable “NO_OF_VEHICLES” to see the big picture of the data and the outliers by using the boxplot() function.

Step 6.2 Apply the univariate outlier detection by:

Step 6.3 Handle the outliers by exclude them using the squre bracket and “-” operator to drop the “up_outlier” positions from the “Lives_lost2$NO_OF_VEHICLES” and assign the result into the “Vehicle_clean” object.


Lives_lost2$NO_OF_VEHICLES %>%  
  boxplot(main = "Box Plot of Number of vehicle", ylab = "Number of vehicle", col = "orange") 

summary(Lives_lost2$NO_OF_VEHICLES)

q1 <- summary(Lives_lost2$NO_OF_VEHICLES)[[2]]
q3 <- summary(Lives_lost2$NO_OF_VEHICLES)[[5]]
iqr <- q3 - q1

lower_fence <- q1 - (1.5 * iqr)
upper_fence <- q3 + (1.5 * iqr)

up_outliers <- which(Lives_lost2$NO_OF_VEHICLES > upper_fence)
low_outliers <- which(Lives_lost2$NO_OF_VEHICLES < lower_fence)

low_outliers %>% length()
up_outliers %>% length()

Vehicle_clean<- Lives_lost2$NO_OF_VEHICLES[-up_outliers]

bp<- boxplot(Vehicle_clean)
bp$out %>% length()

Transform

Step 7 Transformation : I choose to transform the “AGE” variable. I convert the variable from ordered factor into numeric by using the as.numeric() function to be able to plot the graph and transform. Then, extract just the “AGE” variable into “Age” object so this process does not change the type of the variable in the big dataset.

Step 7.1 Create a histogram of the “Age” by using the hist() function.

The result shown that the data appear to be right-skewed.

Step 7.2 Transform the Age data to decrease the skewness by using square root transformation as the square root transformation is used for reducing right-skewness.


Age<-as.numeric(Lives_lost2$AGE)

hist(Age,
main="Histogram of Age",
xlab="Age(years old)",
col= "darkslategrey")

par(mfrow=c(1,2))
hist(Age, col = "darkslategrey")
sqrt <- Age^(1/2)
hist(sqrt, col = "darkslategray3")

library(moments)
skewness(Age)
skewness(sqrt)

References:

Calculate Skewness in R n.d., ProgrammingR, viewed 14 October 2021, https://www.programmingr.com/statistics/skewness/

Hadley Wickham and Garrett Grolemund, R for Data Science, R4DS, viewed 18 September 2021, https://r4ds.had.co.nz/tidy-data.html

Mangiafico, S.S. 2016, Summary and Analysis of Extension Program Evaluation in R, viewed 14 October 2021, https://rcompanion.org/handbook/I_12.html

Victoria Department of Transport 2021, Crashes_Last_Five_Years - Open Data, data file, Victoria Department of Transport Open Data Hub, viewed 10 October 2021, https://vicroadsopendata-vicroadsmaps.opendata.arcgis.com/datasets/vicroadsmaps::road-crashes-for-five-years-victoria/about.

Victoria Department of Transport, Fatal Crashes - Lives Lost, Last 5 Years to Date, the Fatal Crashes - Lives Lost Year to Date dataset, data file, Department of Transport Open Data Hub, viewed 10 October 2021, https://vicroadsopendata-vicroadsmaps.opendata.arcgis.com/datasets/vicroadsmaps::road-crashes-for-five-years-victoria/about.

Hannah Roos 2021, Smart handling of missing data in R, Towards Data Science, viewed 10 October 2021, https://towardsdatascience.com/smart-handling-of-missing-data-in-r-6425f8a559f2





LS0tCnRpdGxlOiAiRGF0YSBXcmFuZ2xpbmciCmF1dGhvcjogTmFhbSBNYXJzaGFsbApzdWJ0aXRsZTogIlZpY3RvcmlhIEZhdGFsIENyYXNoZXMgaW4gdGhlIGxhc3QgNSB5ZWFycyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgoKCiMjIFJlcXVpcmVkIHBhY2thZ2VzIAogIAoqIGRwbHlyIHBhY2thZ2UgZm9yICAKICArIHNlbGVjdCgpCiAgKyBpbm5lcl9qb2luKCkKICArIG11dGF0ZSgpCiAgKyByZW5hbWUoKQogIAoqIGx1YnJpZGF0ZSBmb3IgCiAgKyB5bWRfaG1zKCkKICAKKiBtYWdyaXR0ciBmb3IKICArICU+JSAKICArICU8PiUgCiAgCiogc3RyaW5nciBmb3IKICArIHN0cl9yZXBsYWNlX2FsbCgpCgpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShrbml0cikKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkobWFncml0dHIpCgpgYGAKCgojIyBEYXRhIAoKKipEYXRhc2V0IERlc2NyaXB0aW9uKioKClRoaXMgYXNzZXNzbWVudCBpbmNsdWRlcyAyIGRhdGFzZXRzIHJlbGF0ZSB0byB0aGUgZmF0YWwgY3Jhc2hlcyBvbiBWaWN0b3JpYW4gcm9hZHMgZHVyaW5nIHRoZSBsYXRlc3QgZml2ZSB5ZWFyIHJlcG9ydGluZyBwZXJpb2QuIFJvYWQgU2FmZXR5IGRhdGEgaXMgcHJvdmlkZWQgYnkgVmljUm9hZHMgZm9yIGVkdWNhdGlvbmFsIGFuZCByZXNlYXJjaCBwdXJwb3NlcyB3aXRoIENyZWF0aXZlIENvbW1vbnMgbGljZW5zZSA0LjAuIFRoaXMgZGF0YSBpcyBpbiBXZWIgTWVyY2F0b3IgKEF1eGlsaWFyeSBTcGhlcmUpIHByb2plY3Rpb24uKFZpY3JvYWRzLDIwMjEpIFRoZSB0d28gZGF0YXNldHMgaW5jbHVkZTogIAoKMS4gIlJvYWRfQ3Jhc2hlc19mb3JfZml2ZV9ZZWFyc19WaWN0b3JpYS5jc3YiIChodHRwczovL3ZpY3JvYWRzb3BlbmRhdGEtdmljcm9hZHNtYXBzLm9wZW5kYXRhLmFyY2dpcy5jb20vZGF0YXNldHMvdmljcm9hZHNtYXBzOjpyb2FkLWNyYXNoZXMtZm9yLWZpdmUteWVhcnMtdmljdG9yaWEvYWJvdXQpIChGdWxsIGNpdGF0aW9uIGluIHRoZSByZWZlcmVuY2UgbGlzdCkKClRoaXMgZGF0YXNldCBpcyBhYm91dCAnRmF0YWwgYW5kIGluanVyeSBjcmFzaGVzIG9uIFZpY3RvcmlhbiByb2FkcyBkdXJpbmcgdGhlIGxhdGVzdCBmaXZlIHllYXIgcmVwb3J0aW5nIHBlcmlvZC4nIChWaWN0b3JpYSBEZXBhcnRtZW50IG9mIFRyYW5zcG9ydCBPcGVuIERhdGEgSHViKS4gVGhlIHRpbWUgcGVyaW9kIGlzIGJldHdlZW4gMjUvMDUvMjAxNSBhbmQgNS8xMC8yMDIxLgoKMi4gIkZhdGFsX0NyYXNoZXNfLV9MaXZlc19Mb3N0JTJDX0xhc3RfNV9ZZWFyc190b19EYXRlLmNzdiIKKGh0dHBzOi8vdmljcm9hZHNvcGVuZGF0YS12aWNyb2Fkc21hcHMub3BlbmRhdGEuYXJjZ2lzLmNvbS9kYXRhc2V0cy92aWNyb2Fkc21hcHM6OmZhdGFsLWNyYXNoZXMtbGl2ZXMtbG9zdC1sYXN0LTUteWVhcnMtdG8tZGF0ZS0xNjA0MjEvYWJvdXQpIChGdWxsIGNpdGF0aW9uIGluIHRoZSByZWZlcmVuY2UgbGlzdCkKClRoaXMgZGF0YXNldCBpcyBhYm91dCB0aGUgZmF0YWwgY3Jhc2hlcyBvbiBWaWN0b3JpYW4gcm9hZHMgZHVyaW5nIHRoZSBsYXRlc3QgZml2ZSBjb21wbGV0ZSB5ZWFycyBhbmQgY3VycmVudCB5ZWFyIHRvIHRoZSA1dGggb2YgQXVndXN0IDIwMjEuIChWaWNyb2FkcywyMDIxKQoKKipWYXJpYWJsZXMgRGVzY3JpcHRpb24qKgoKVGhpcyBkZXNjcmlwdGlvbnMganVzdCBwcm92aWRlZCBvbmx5IHRoZSB2YXJpYWJsZXMgdXNlZCBpbiB0aGUgZGF0YSBwcmVwcm9jZXNzaW5nIHByb2Nlc3MuCgoqICoqQUNDSURFTlRfTk8qKiBpcyBhIGNoYXJlY3RvciBmaWVsZCBpbmRpY2F0ZXMgdGhlIHVuaXF1ZSBJRCB0aGF0IGlkZW50aWZ5IHBhcnRpY3VsYXIgYWNjaWRlbnQgdGhhdCBvY2N1cmVkLiBDb250YWlucyAxMiBjaGFyYWN0ZXJzLCBzdGFydGluZyB3aXRoIFQgKGZvciBleGFtcGxlLCBUMjAwNjAxMjM0NTYpIFdoZXJlIGNoYXJhY3RlcnMgMiB0byA1IGFyZSB0aGUgeWVhciBpbiB3aGljaCBhY2NpZGVudCB3YXMgcmVnaXN0ZXJlZDsgV2hlcmUgY2hhcmFjdGVycyA2IHRvIDEyIGFyZSBhIG51bWVyaWMgc2VxdWVuY2luZyBudW1iZXJzCiogKipEQVRFKiogaXMgYSBmaWVsZCBpbmRpY2F0ZXMgdGhlIGRhdGUgdGhhdCB0aGUgYWNjaWRlbnQgb2NjdXJyZWQuIAoqICoqVElNRSoqIGlzIGEgZmllbGQgaW5kaWNhdGluZyB0aGUgdGltZSB0aGF0IHRoZSBhY2NpZGVudCBvY2N1cnJlZC4KKiAqKkRBWV9PRl9XRUVLKiogaXMgaXMgYSBjaGFyZWN0b3IgZmllbGQgaW5kaWNhdGVzIHRoZSBkYXkgb2YgdGhlIHdlZWsgdGhhdCB0aGUgYWNjaWRlbnQgb2NjdXJyZWQuCiogKipBQ0NJREVOVF9UWVBFKiogaXMgYSBjaGFyYWN0ZXIgZmllbGQgaW5kaWNhdGVzIHRoZSB0eXBlIG9mIHRoZSBhY2NpZGVudC4gSXQgaXMgYSBiYXNpYyBkZXNjcmlwdGlvbiBvZiB3aGF0IG9jY3VycmVkLCBiYXNlZCBvbiBuaW5lIGNhdGVnb3JpZXMgYXMgZm9sbG93aW5nOiAgCiAgKyBDb2xsaXNpb24gd2l0aCB2ZWhpY2xlCiAgKyBTdHJ1Y2sgcGVkZXN0cmlhbgogICsgU3RydWNrIGFuaW1hbAogICsgQ29sbGlzaW9uIHdpdGggYSBmaXhlZCBvYmplY3QKICArIENvbGxpc2lvbiB3aXRoIHNvbWUgb3RoZXIgb2JqZWN0CiAgKyBWZWhpY2xlIG92ZXJ0dXJuZWQgKG5vIGNvbGxpc2lvbikKICArIEZhbGwgZnJvbSBvciBpbiBtb3ZpbmcgdmVoaWNsZQogICsgTm8gY29sbGlzaW9uIGFuZCBubyBvYmplY3Qgc3RydWNrCiAgKyBPdGhlciBhY2NpZGVudAoqICoqTk9fT0ZfVkVISUNMRVMqKiBpcyBhIG51bWVyaWMgZmllbGQgaW5kaWNhdGVzIHRoZSBudW1iZXIgb2YgdmVoaWNsZXMgaW52b2x2ZWQgaW4gdGhlIGNyYXNoLgoqICoqQUdFKiogaXMgYSBmaWVsZCBpbmRpY2F0ZXMgaG93IG9sZCB0aGUgcGVyc29uIHdhcyBhdCB0aGUgdGltZSBvZiB0aGUgYWNjaWRlbnQuIEl0IGlzIGNhbGN1bGF0ZWQgYnkgc3VidHJhY3RpbmcgdGhlIHBlcnNvbuKAmXMgYmlydGggZGF0ZSBmcm9tIHRoZSBhY2NpZGVudCBkYXRlIHRvIGdpdmUgdGhlIHBlcnNvbuKAmXMgYWdlIGluIHllYXJzLgoqICoqUk9BRF9VU0VSKiogaXMgYSBjaGFyYWN0ZXIgZmllbGQgaW5kaWNhdGVzIHdoYXQgdGhlIHJvbGUgb2YgdGhlIHBlcnNvbiB3YXMgYXQgdGhlIHRpbWUgb2YgdGhlIGFjY2lkZW50IGFzIGZvbGxvd2luZzogIAogICsgUGVkZXN0cmlhbgogICsgRHJpdmVyCiAgKyBQYXNzZW5nZXIKICArIE1vdG9yY3ljbGlzdAogICsgUGlsbGlvbiBQYXNzZW5nZXIKICArIEJpY3ljbGlzdCAoaW5jbC5wYXNzZW5nZXJzKQogICsgT3RoZXIgZHJpdmVyCiAgKyBPdGhlciBwYXNzZW5nZXIKICArIE5vdCBrbm93bgoqICoqU1BFRURfWk9ORSoqIGlzIGEgY2hhcmFjdGVyIGZpZWxkIGluZGljYXRlcyB0aGUgc3BlZWQgem9uZSAoa20vaHIpIGF0IHRoZSBsb2NhdGlvbiBvZiB0aGUgYWNjaWRlbnQuIFRoZSBzcGVlZCB6b25lIGlzIGdlbmVyYWxseSBhc3NpZ25lZCB0byB0aGUgbWFpbiB2ZWhpY2xlIGludm9sdmVkLgoqICoqTEdBX05BTUUqKiBpcyBhIGNoYXJhY3RlciBmaWVsZCBjb250YWlucyB0aGUgbG9jYWwgZ292ZXJubWVudCBhcmVhIG5hbWUgdGhhdCB0aGUgYWNjZW50IG9jY3VyZWQuIAoqICoqQUxDT0hPTF9SRUxBVEVEKiogaXMgYSBmaWVsZCBvZiB2YWx1ZSAiTm8iIGFuZCAiWWVzIiB3aGljaCAiWWVzIiBtZWFucyB0aGUgcGFydGljdWxhciBhY2NpZGVudCBpcyBhbGNvaG9sIHJlbGF0ZWQgd2hpY2ggQmxvb2QvQnJlYXRoIEFsY29ob2wgQ29uY2VudHJhdGlvbj4wLjAwMSBpbiB0aGUgcm9hZCB1c2VyIHR5cGU6IGRyaXZlcixyaWRlcixjeWNsaXN0IGFuZCBwZWRlc3RyaWFuLgoKIyMgUHJlcGFyYXRpb24KIAogKipzdGVwIDEuMSoqIEltcG9ydCB0aGUgZGF0YXNldHMgYnkgdXNpbmcgdGhlIHJlYWQuY3N2KCkgdG8gcmVhZCB0aGUgLmNzdiBmaWxlcyBhbmQgYXNzaWduICJuYS5zdHJpbmciIGFyZ3VtZW50IHdpdGggIlUiLCJVbmtub3duIiwgIiAiLCAiTm90IGtub3duIiB0byB0ZWxsIFIgUiB0byB0cmVhdCB0aGVzZSB2YWx1ZXMgYXMgTkEobm90IGF2YWlsYWJsZSkgdmFsdWUuIAoqIEFzc2lnbiB0aGUgIlJvYWRfQ3Jhc2hlc19mb3JfZml2ZV9ZZWFyc19WaWN0b3JpYS5jc3YiIHRvICJDcmFzaGVzIiBkYXRhZnJhbWUgYW5kICJGYXRhbF9DcmFzaGVzXy1fTGl2ZXNfTG9zdCUyQ19MYXN0XzVfWWVhcnNfdG9fRGF0ZS5jc3YiIHRvICJGYXRhbCJkYXRhZnJhbWUuCgoqKnN0ZXAgMS4yKiogQ2hlY2sgdGhlIGRhdGFzZXQgZm9yIHByZS1wcm9jZXNzaW5nIGRhdGEuICAKCiogQ2hlY2sgdGhlIHN0cnVjdHVyZSBvZiBib3RoIGRhdGFzZXRzIHVzaW5nIHRoZSBzdHIoKSBmdW5jdGlvbi4gVGhlIHJlc3VsdCBzaG93biB0aGF0OgogICsgVGhleSBib3RoIGFyZSBkYXRhZnJhbWUuIFRoZSByZXN1bHRzIGFsc28gc2hvdyB0aGUgbmFtZXMgYW5kIHR5cGVzIG9mIHRoZSB2YXJpYWJsZXMgdG9nZXRoZXIgd2l0aCB0aGUgZXhhbXBsZSBvZiBzb21lIHZhbHVlcyBpbiB0aGUgdmFyaWFibGUuIAogICsgRm9yIHRoZSAiQ3Jhc2hlcyIgZGF0YXNldCwgdGhlcmUgYXJlIDc1LDMyMCBvYnNlcnZhdGlvbnMgYW5kIDY1IHZhcmlhYmxlcy4KICArIEZvciB0aGUgIkZhdGFsIiBkYXRhc2V0LCB0aGVyZSBhcmUgMSwyNjQgb2JzZXJ2YXRpb25zIGFuZCAzMSB2YXJpYWJsZXMuCgoqKnN0ZXAgMS4zKiogU2VsZWN0IHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzIHRoYXQgSSB0aGluayB0aGV5IGFyZSB1c2VmdWwgYW5kIGRyb3AgdGhlIHJlc3QgdXNpbmcgdGhlIHNlbGVjdCgpIGZ1bmN0aW9uIGZyb20gZHBseXI6IAoKKiBGb3IgIkNyYXNoZXMiIGRhdGFmcmFtZSBzZWxlY3Q6CiAgKyBBQ0NJREVOVF9OTwogICsgQUNDSURFTlRfVFlQRQogICsgREFZX09GX1dFRUsKICArIFNQRUVEX1pPTkUKICArIExHQV9OQU1FCiAgKyBOT19PRl9WRUhJQ0xFUwogICsgQUxDT0hPTF9SRUxBVEVECiAgCiogRm9yICJGYXRhbCIgZGF0YWZyYW1lIHNlbGVjdDogCiAgKyBBQ0NJREVOVF9OCiAgKyBBR0UKICArIFJEX1VfREVTQwogICsgQUNDSURFTlRfRAogICsgQUNDSURFTlRfVAoKKipzdGVwIDEuNSoqIFJlbmFtZSBzb21lIG9mIHZhcmlhYmxlcyB0byBtYWtlIHRoZW0gbW9yZSBzZW5zaWJsZSBhbmQgYWxzbyByZW5hbWUgdGhlICJBQ0NJREVOVF9OIiB2YXJpYWJsZSB0byAiQUNDSURFTlRfTk8iIHRvIG1hdGNoIHdpdGggdGhlIHZhcmlhYmxlICJBQ0NJREVOVF9OTyIgaW4gIkNyYXNoZXMiIGRhdGFmcmFtZSB0aGF0IEkgYW0gZ29pbmcgdG8gdXNlIGl0IHRvIGpvaW4gdGhlIHR3byBkYXRhZnJhbWUgaW4gdGhlIG5leHQgc3RlcC4gVXNlIHRoZSByZW5hbWUoKSBmdW5jdGlvbiBmcm9tIGRwbHlyIHBhY2thZ2UgdG8gcmVuYW1lIHRoZSAiQUNDSURFTlRfTiIgdmFyaWFsZSBpbnRvICJBQ0NJREVOVF9OTyIsICJSRF9VX0RFU0MiIGludG8gIlJPQURfVVNFUiIsICJBQ0NJREVOVF9EIiBpbnRvICJEQVRFIiBhbmQgIkFDQ0lERU5UX1QiIGludG8gIlRJTUUiLgoKKipzdGVwIDEuNioqIE1lcmdlIDIgZGF0YXNldHMgYnkga2VlcGluZyBvbmx5IHRoZSBvYnNlcnZhdGlvbiBpbiBib3RoIGRhdGFmcmFtZSB1c2luZyB0aGUgaW5uZXJfam9pbigpIGZ1bmN0aW9uIGZyb20gZHBseXIgcGFja2FnZS4gSm9pbmluZyBib3RoIGRhdGFzZXRzIHRvZ2V0aGVyIGJ5IHZhcmlhYmxlICJBQ0NJREVOVF9OTyIgdXNpbmcgdGhlIGFyZ3VtZW50ICJieSIgYW5kIGFzc2lnbiB0aGUgcmVzdWx0IGludG8gIkxpdmVzX2xvc3QiIGRhdGFmcmFtZS4gCgoqKnN0ZXAgMS43KiogUmVhcnJhbmdlIHRoZSB2YXJpYWJsZXMgb3JkZXIgYnkgYXNzaWduIHRoZSBwb3NpdGlvbnMgb2YgdGhlIHZhcmlhYmxlIGluIG9yZGVyIHRoYXQgSSB3YW50IHRvIGFycmFuZ2UgYnkgdXNpbmcgc3F1YXJlIGJyYWNrZXRzIGFuZCB0aGUgYygpIGZ1bmN0aW9uLiBMZWF2aW5nIHRoZSByb3dzIHNlbGVjdGlvbiBwYXJ0IGJsYW5rIHRvIHN1YnNldCBldmVyeSByb3dzLgoKYGBge3J9CgpDcmFzaGVzPC0gcmVhZC5jc3YoIlJvYWRfQ3Jhc2hlc19mb3JfZml2ZV9ZZWFyc19WaWN0b3JpYS5jc3YiLCBuYS5zdHJpbmdzID0gYygiVSIsIlVua25vd24iLCAiICIsICJOb3Qga25vd24iKSkKRmF0YWwgPC0gcmVhZC5jc3YoIkZhdGFsX0NyYXNoZXNfLV9MaXZlc19Mb3N0JTJDX0xhc3RfNV9ZZWFyc190b19EYXRlLmNzdiIsbmEuc3RyaW5ncyA9IGMoIlUiLCJVbmtub3duIiwgIiAiLCJOb3Qga25vd24iKSkKCnN0cihGYXRhbCkKc3RyKENyYXNoZXMpCgoKQ3Jhc2hlcyAlPD4lIHNlbGVjdChBQ0NJREVOVF9OTywgQUNDSURFTlRfVFlQRSwgREFZX09GX1dFRUssIFNQRUVEX1pPTkUsIExHQV9OQU1FICxOT19PRl9WRUhJQ0xFUywgQUxDT0hPTF9SRUxBVEVEKQpGYXRhbCAlPD4lIHNlbGVjdChBQ0NJREVOVF9OLCBBQ0NJREVOVF9ELCBBQ0NfVElNRSwgQUdFLCBSRF9VX0RFU0MpCkZhdGFsICU8PiUgcmVuYW1lKGMoIkFDQ0lERU5UX05PIiA9IEFDQ0lERU5UX04sICJST0FEX1VTRVIiID0gUkRfVV9ERVNDLCAiREFURSIgPSBBQ0NJREVOVF9ELCAiVElNRSIgPSBBQ0NfVElNRSkpIAoKTGl2ZXNfbG9zdCA8LSBpbm5lcl9qb2luKENyYXNoZXMsIEZhdGFsLCBieSA9ICJBQ0NJREVOVF9OTyIpCkxpdmVzX2xvc3QgPC0gTGl2ZXNfbG9zdFssYygxLCA4LCA5LCAzLCAyLCA2LCAxMCwgMTEsIDQsIDUsIDcgKV0gCmhlYWQoTGl2ZXNfbG9zdCkKYGBgCiMjIFVuZGVyc3RhbmQgCgoqKnN0ZXAgMi4xKiogQ2hlY2sgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldCBieSB1c2luZyB0aGUgc3RyKCkgZnVuY3Rpb24gYW5kIHRoZSBhdHRyaWJ1dGVzLiBUaGUgcmVzdWx0IHNob3duOiAgCgoqIFRoZSBkYXRhc2V0IGlzIGEgZGF0YWZyYW1lIGNvbnRhaW5zIDEsMjY0IE9ic2VydmF0aW9ucyBhbmQgMTEgdmFyaWFibGVzLgoqIFRoZSB2YXJpYWJsZSAiQUNDSURFTlRfTk8iLCAiREFZX09GX1dFRUsiLCAiQUNDSURFTlRfVFlQRSIsICJST0FEX1VTRVIiLCAiU1BFRURfWk9ORSIsICJMR0FfTkFNRSIsICJBTENPSE9MX1JFTEFURUQiLCAiREFURSIgYW5kICJUSU1FIiBhcmUgYSBjaGFyYWN0ZXIgdHlwZS4gSSB3aWxsIGxlYXZlIHRoZSAiREFURSIgYW5kICJUSU1FIiB2YXJpYWJsZSBhcyB0aGV5IGFyZSBhcyBJIGFtIGdvaW5nIHRvIGNvbWJpbmUgdGhlbSB0b2dldGhlciBhbmQgY29udmVydCB0aGVtIGludG8gUE9TSVhjdCBjbGFzcyBpbiBTdGVwIDQuCiogVGhlIHZhcmlhYmxlICJBR0UiIGFuZCAiTk9fT0ZfVkVISUNMRVMiIGFyZSBpbnRlZ2VyIHR5cGUuIEkgd2lsbCBsZWF2ZSB0aGUgIk5PX09GX1ZFSElDTEVTIiBhcyB0aGV5IGFyZSBiZWNhdXNlIGludGVnZXIgaXMgdGhlIHJpZ2h0IHR5cGUgZm9yIGl0LgoKKipzdGVwIDIuMioqIFZhcmlhYmxlcyBjb252ZXJzaW9uICAKCiogQ29udmVydCB0aGUgdmFyaWFibGVzICJBQ0NJREVOVF9OTyIsICJBQ0NJREVOVF9UWVBFIiBhbmQgIlJPQURfVVNFUiIgdG8gYmUgZmFjdG9yIHVzaW5nIHRoZSBhcy5mYWN0b3IoKSBmdW5jdGlvbi4KKiBDb252ZXJ0IHRoZSB2YXJpYWJsZXMgIkRBWV9PRl9XRUVLIiwgIkFHRSIgYW5kICJTUEVFRF9aT05FIiBpbnRvIGFuIG9yZGVyZWQgZmFjdG9yIHZhcmlhbGJsZXMgYnkgdXNpbmcgdGhlIGZhY3RvcigpIGZ1bmN0aW9uIGFuZCBvcmRlcmluZyB0aGVtIHVzaW5nIHRoZSAibGV2ZWxzIiBhcmd1bWVudCB3aXRoIHRoZSBjKCkgZnVuY3Rpb24gYW5kIGFzc2lnbiBhcmd1bWVudCAib3JkZXJlZCIgdG8gYmUgIlRSVUUiIHNvIHRoZSBsZXZlbHMgYXJlIHJlZ2FyZGVkIGFzIG9yZGVyZWQuCiogQ29udmVydCB0aGUgdmFyaWFibGUgIkFMQ09IT0xfUkVMQVRFRCIgaW50byBsb2dpY2FsIHR5cGUgYnk6CiAgKyBSZXBsYWNlIHZhbHVlcyAiTm8iIHdpdGggIkZBTFNFIiBhbmQgdmFsdWVzICJZZXMiIHdpdGggIlRSVUUiLgogICsgVXNlIHRoZSBhcy5sb2dpY2FsKCkgZnVuY3Rpb24gdG8gY29udmVydCB0aGVtIGludG8gbG9naWNhbCB0eXBlLgoqIENoZWNrIHRoZSByZXN1bHQgb2YgdGhlIGNvbnZlcnNpb24gYnkgdXNpbmcgdGhlIHN0cigpIGZ1bmN0aW9uLiBUaGUgcmVzdWx0IHNob3duIHRoYXQ6ICAKICArIFRoZSAiQUNDSURFTlRfTk8iLCAiQUNDSURFTlRfVFlQRSIgYW5kICJST0FEX1VTRVIiIGhhdmUgY29udmVydGVkIGludG8gZmFjdG9yIHR5cGUuCiAgKyBUaGUgIkRBWV9PRl9XRUVLIiwgIkFHRSIgYW5kICJTUEVFRF9aT05FIiBoYXZlIGNvbnZlcnRlZCBpbnRvIG9yZGVyZWQgZmFjdG9yIHR5cGUKICArIFRoZSAiQUxDT0hPTF9SRUxBVEVEIiBoYXZlIGNvbnZlcnRlZCBpbnRvIGxvZ2ljYWwgdHlwZS4KCgpgYGB7cn0KTGl2ZXNfbG9zdCAlPiUgc3RyKCkKTGl2ZXNfbG9zdCAlPiUgYXR0cmlidXRlcygpCgpMaXZlc19sb3N0JEFDQ0lERU5UX05PICU8PiUgYXMuZmFjdG9yKCkKTGl2ZXNfbG9zdCRBQ0NJREVOVF9UWVBFICU8PiUgYXMuZmFjdG9yKCkKTGl2ZXNfbG9zdCRST0FEX1VTRVIgJTw+JSBhcy5mYWN0b3IoKQoKTGl2ZXNfbG9zdCREQVlfT0ZfV0VFSyAlPD4lIGZhY3RvcihsZXZlbHM9YygiU3VuZGF5IiwiTW9uZGF5IiwiVHVlc2RheSIsIldlZG5lc2RheSIsIlRodXJzZGF5IiwiRnJpZGF5IiwiU2F0dXJkYXkiKSwgb3JkZXJlZD1UUlVFKQpMaXZlc19sb3N0JEFHRSAlPD4lIGZhY3RvcihsZXZlbHMgPSBjKDE6OTkpLCBvcmRlcmVkID0gVFJVRSkKTGl2ZXNfbG9zdCRTUEVFRF9aT05FICU8PiUgZmFjdG9yKGxldmVscyA9IGMoIkNhbXBpbmcgZ3JvdW5kcyBvciBvZmYgcm9hZCIsICI0MCBrbS9ociIsIjUwIGttL2hyIiwgIjYwIGttL2hyIiwgIjcwIGttL2hyIiwiNzUga20vaHIiLCAiODAga20vaHIiLCAiOTAga20vaHIiLCAiMTAwIGttL2hyIiwgIjExMCBrbS9ociIsICJPdGhlciBzcGVlZCBsaW1pdCIpLCBvcmRlcmVkID0gVFJVRSkKCkxpdmVzX2xvc3QkQUxDT0hPTF9SRUxBVEVEPC1nc3ViKCJObyIsICJGQUxTRSIsIExpdmVzX2xvc3QkQUxDT0hPTF9SRUxBVEVEKQpMaXZlc19sb3N0JEFMQ09IT0xfUkVMQVRFRDwtZ3N1YigiWWVzIiwgIlRSVUUiLCBMaXZlc19sb3N0JEFMQ09IT0xfUkVMQVRFRCkKTGl2ZXNfbG9zdCRBTENPSE9MX1JFTEFURUQgJTw+JSBhcy5sb2dpY2FsKCkgCgpMaXZlc19sb3N0ICU+JSBzdHIoKQoKYGBgCgoKIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJIAoKKipTdGVwIDMqKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZGF0YXNldCBpcyB0aWR5IG9yIHVudGlkeS4gCgpUbyBkZXRlcm1pbmUgaWYgbXkgZGF0YXNldCBpcyB0aWR5IG9yIG5vdCwgSSB1c2VkIHRoZSB0aHJlZSBpbnRlcnJlbGF0ZWQgcnVsZXM6CgoxLiBFYWNoIHZhcmlhYmxlIG11c3QgaGF2ZSBpdHMgb3duIGNvbHVtbi4KMi4gRWFjaCBvYnNlcnZhdGlvbiBtdXN0IGhhdmUgaXRzIG93biByb3cuCjMuIEVhY2ggdmFsdWUgbXVzdCBoYXZlIGl0cyBvd24gY2VsbC4KKEhhZGxleSBXaWNraGFtIGFuZCBHYXJyZXR0IEdyb2xlbXVuZCAyMDE2KQoKRnJvbSBteSBwb2ludCBvZiB2aWV3IG15IGRhdGFzZXQgIkxpdmVfbG9zdCIgaXMgYWxyZWFkeSBpbiBhIHRpZHkgZm9ybWF0IGFzIGVhY2ggdmFyaWFibGUgaGF2ZSBnb3QgaXRzIG93biBjb2x1bW4sIGVhY2ggT2JzZXJ2YXRpb24gaGF2ZSBnb3QgaXRzIG93biByb3cgYW5kIEVhY2ggdmFsdWUgaGF2ZSBnb3QgaXRzIG93biBjZWxsLgoKYGBge3J9CgpgYGAKCgojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJIAoKKipTdGVwIDQuMSoqIFNoYXBlIHRoZSBmb3JtYXQgb2YgdGhlIHZhbHVlcyBmcm9tICJEQVRFIiB2YXJpYWJsZSBieSBrZWVwaW5nIHRoZSB2YWx1ZSBmcm9tIHRoZSBmaXJzdCBwb3NpdGlvbiB0byAxMHRoIGFuZCBkcm9wIHRoZSByZXN0IGJ5IHVzaW5nIHRoZSBzdWJzdHIoKSBmdW5jdGlvbi4gQXNzaWduIHRoZSAic3RhcnQiIGFyZ3VtZW50IHdpdGggIjEiIGFuZCB0aGUgInN0b3AiIGFyZ3VtZW50IHdpdGggIjEwIiB0byBpbmRpY2F0ZSB0aGUgcmFuZ2Ugb2YgcG9zaXRpb24gdGhhdCBJIHdhbnQgdG8ga2VlcC4gIAoKKipTdGVwIDQuMioqIFNoYXBlICJUSU1FIiB2YXJpYWJsZSBpbnRvIHRoZSBlYXN5IGZvcm1hdCBpbiBwcmVwYXJpbmcgdG8gdXNlIHRoZSB5bWRfaG1zKCkgZnVuY3Rpb24gaW4gc3RlcCA0LjQgYnkgdXNpbmcgdGhlIHN0cl9yZXBsYWNlX2FsbCgpIGZ1bmN0aW9uIGZyb20gc3RyaW5nciBwYWNrYWdlIHRvIHJlcGxhY2UgIi46IiB3aXRoICI6IiBhbmQgcmVwbGFjZSAiLjAwIiB3aXRoICIwLjAwIi4gVXNlIHRoZSBoZWFkKCkgZnVuY3Rpb24gdG8gcmV2aWV3IHRoZSByZXN1bHQuIAoKKipTdGVwIDQuMyoqIENyZWF0ZSB0aGUgbmV3IHZhcmlhYmxlICJEQVRFIiBieSBjb21iaW5pbmcgdmFyaWFibGUgIkRBVEUiIGFuZCAiVElNRSIgdG9nZXRoZXIuICAKCiogVXNpbmcgdGhlIG11dGF0ZSgpIGZ1bmN0aW9uIGZyb20gdGhlIGRwbHlyIHBhY2thZ2UgdG8gY3JlYXRlIGEgbmV3IHZhcmlhYmxlIGNhbGxlZCAiREFURSIuCiogVXNpbmcgdGhlIHBhc3RlKCkgZnVuY3Rpb24gdG86ICAKICArIFB1dCB0aGUgdmFsdWUgZnJvbSB0aGUgb2xkIHZhcmlhYmxlICJEQVRFIiBhbmQgZm9sbG93IHdpdGggdGhlIHZhbHVlcyBmcm9tIHRoZSB2YXJpYWJsZSAiVElNRSIuCiAgKyBBc3NpZ24gdGhlIGFyZ3VtZW50ICJzZXAiIHdpdGggIiAiKGJsYW5rKSB0byBpbmRpY2F0ZSB0aGUgc2VwYXJhdG9yIGJldHdlZW4gdGhlIHZhbHVlcy4gIAogIAoqKlN0ZXAgNC40KiogQ29udmVydCB0aGUgdmFyaWFibGUgIkRBVEUiIGludG8gUE9TSVhjdCBjbGFzcyB1c2luZyB5bWRfaG1zKCkgZnVuY3Rpb24gZnJvbSAibHVicmlkYXRlIiBwYWNrYWdlLgoKKipTdGVwIDQuNSoqIERyb3AgdmFyaWFibGVzICJUSU1FIiBieSB1c2luZyB0aGUgc2VsZWN0KCkgZnVuY3Rpb24gd2l0aCB0aGUgYygpIGZ1bmN0aW9uIGFuZCB0aGUgIi0iIG9wZXJhdG9yIHRvIGFzc2lnbiB0aGUgY29sdW1uIG5hbWUgIlRJTUUiIHRoYXQgSSB3YW50IHRvIGRyb3AuIFVzZSB0aGUgc3RyKCkgZnVuY3Rpb24gdG8gY2hlY2sgdGhlIHJlc3VsdC4gVGhlIHJlc3VsdCBzaG93biB0aGF0OiAgCgoKKiBUaGUgIkRBVEUiIHZhcmlhYmxlIGhhdmUgY29udmVydCBpbnRvIGNsYXNzIFBPU0lYY3Qgd2hpY2ggcmVwcmVzZW50aW5nIGNhbGVuZGFyIGRhdGVzIGFuZCB0aW1lcy4KKiBUaGUgIkRBVEUiIHZhcmlhYmxlIGZvcm1hdCBjaGFuZ2UgaW50byAieXl5eS1tbS1kZCBoaDptbTpzcyIuCiogVGhlICJUSU1FIiB2YXJpYWJsZSBoYXMgZHJvcHBlZC4KCgpgYGB7cn0KCkxpdmVzX2xvc3QkREFURSAlPD4lIHN1YnN0cihzdGFydCA9IDEsIHN0b3AgPSAxMCkgCgpMaXZlc19sb3N0JFRJTUUgJTw+JSBzdHJfcmVwbGFjZV9hbGwoIi46IiwgIjoiKQpMaXZlc19sb3N0JFRJTUUgJTw+JSBzdHJfcmVwbGFjZV9hbGwoIi4wMCIsICIwOjAwIikKaGVhZChMaXZlc19sb3N0KQoKTGl2ZXNfbG9zdCAlPD4lIG11dGF0ZSAoREFURSA9IHBhc3RlKERBVEUsIFRJTUUsIHNlcCA9ICIgIikpCkxpdmVzX2xvc3QkREFURSAlPD4lIHltZF9obXMoKQpMaXZlc19sb3N0ICU8PiUgc2VsZWN0KC1USU1FKSAKc3RyKExpdmVzX2xvc3QpCgpgYGAKCiMjCVNjYW4gSSAKCioqU3RlcCA1LjEqKiBDaGVjayB0aGUgYW1vdW50IG9mIE5BIGluIGVhY2ggY29sdW1uIGJ5IHVzaW5nIHRoZSBpcy5uYSgpIGZ1bmN0aW9uIHRvIGNoZWNrIGZvciB0aGUgTkEgdmFsdWUgYW5kIHRoZSBjb2xTdW0oKSBmdW5jdGlvbiB0byBzdW0gdXAgdGhlIHRvdGFsIG9mIE5BIHZhbHVlIGluIGVhY2ggY29sdW1uLiBUaGUgcmVzdWx0IGZvdW5kOiAgCgogICogMiBvZiB0aGUgdmFsdWVzIGluICJEQVlfT0ZfV0VFSyIgdmFyaWFibGUgYXJlIE5BLiAgCiAgKiA1IG9mIHRoZSB2YWx1ZXMgaW4gIkFHRSIgdmFyaWFibGUgYXJlIE5BLiAgCiAgKiAxNiBvZiB0aGUgdmFsdWVzIGluICJTUEVFRF9aT05FIiBhcmUgTkEuCgoqKlN0ZXAgNS4yKiogUmVwbGFjZSB0aGUgbWlzc2luZyB2YWx1ZXMgaW4gIkRBWV9PRl9XRUVLIiB2YXJpYWJsZSA6ICAKCiogVGhlIDIgb2YgdGhlIHZhbHVlIGluICJEQVlfT0ZfV0VFSyIgdmFyaWFibGUgYXJlIE5BIGJ1dCB0aGUgIkRBVEUiIHZhcmlhYmxlIGhhdmUgbm8gTkEgdmFsdWUgbWVhbnMgSSBjYW4gcmVwbGFjZSB0aGUgbWlzc2luZyB2YWx1ZSBieSB1c2luZyB0aGUgd2Vla2RheXMoKSBmdW5jdGlvbiB0byBmaW5kIHRoZSBkYXkgb2YgdGhlIHdlZWsgYW5kIGFzc2lnbiB0aGUgdmFsdWUgYmFjayB0byBjb2x1bW4gIkRBWV9PRl9XRUVLIi4gCiogQnkgZG9pbmcgdGhpcyByZXBsYWNlbWVudCBjYXVzaW5nIHRoZSAiREFZX09GX1dFRUsiIHZhcmlhYmxlIHRvIHR1cm4gaW50byBhIGNoYXJhY3RlciB0eXBlIHNvIEkgY29udmVydCBpdCBiYWNrIGluIHRvIGFuIG9yZGVyZWQgZmFjdG9yIGJ5IHVzaW5nIHRoZSBzYW1lIG1ldGhvZCBhcyB0aGUgc3RlcCAyLjIuCiogQ2hlY2sgdGhlIE5BIHZhbHVlcyBpbiB0aGUgY29sdW1uICJEQVlfT0ZfV0VFSyIgdG8gbWFrZSBzdXJlIHRoZXJlIGlzIG5vbmUgTkEgdmFsdWUgbGVmdCBpbiAiREFZX09GX1dFRUsiIGNvbHVtbiBieSB1c2luZyB0aGUgaXMubmEoKSBmdW5jdGlvbiB0b2dldGhlciB3aXRoIHRoZSB3aGljaCgpIGZ1bmN0aW9uIGFuZCB0aGUgbGVuZ3RoKCkgZnVuY3Rpb24uIFRoZSByZXN1bHQgc2hvd24gdGhhdCB0aGVyZSBpcyBubyBOQSB2YWx1ZSBpbiAiREFZX09GX1dFRUsiIHZhcmlhYmxlLgoKKipTdGVwIDUuMioqIENoZWNrIHRoZSBhbW91bnQgb2YgTkEgaW4gdGhlIHdob2xlIGRhdGFzZXQgYnk6ICAKCiogVXNlIHRoZSBpcy5uYSgpIGZ1bmN0aW9uIHRvIGNoZWNrIGZvciB0aGUgTkEgdmFsdWUuCiogVXNlIHRoZSB3aGljaCgpIGZ1bmN0aW9uIHRvIGlkZW50aWZ5IHRoZSBwb3NpdGlvbiBvZiBOQSB2YWx1ZS4KKiBVc2UgbGVuZ3RoKCkgZnVuY3Rpb24gdG8gZ2V0IHRoZSBudW1iZXIgb2YgdGhlIE5BIHZhbHVlLgoqIFVzaW5nIHBpcGVzIG9wZXJhdG9yIGJldHdlZW4gdGhlIGZ1bmN0aW9uIHRvIHBhc3MgdGhlIHJlc3VsdCBvZiBvbmUgZnVuY3Rpb24gdG8gdGhlIG90aGVyIG9uZSBpbiBzZXF1ZW5jZS4KCioqU3RlcCA1LjMqKiBTdWJzZXR0aW5nIHRoZSBvYnNlcnZhdGlvbnMgd2l0aCBOQSB2YWx1ZXMgaW50byB0aGUgZGF0YWZyYW1lIGNhbGxlZCAiTkFfcmVsYXRpb25fY2hlY2siIHRvIGJlIGFibGUgdG8gaGF2ZSBhIGJldHRlciBsb29rIGZvciB0aGUgcmVsYXRpb24gb2YgdGhlIG1pc3NpbmcgdmFsdWUgd2l0aCBvdGhlciB2YXJpYWJsZS4gIAoKKiBVc2UgdGhlIGlzLm5hKCkgZnVuY3Rpb24gdG8gZmluZCB0aGUgTkEgdmFsdWUgaW4gdGhlIGRhdGFzZXQuCiogVXNlIHRoZSByb3dTdW1zKCkgZnVuY3Rpb24gdG8gc3VtIHVwIHRoZSBtaXNzaW5nIHZhbHVlIGluIGVhY2ggb2JzZXJ2YXRpb24uCiogU3Vic2V0IGp1c3QgdGhlIG9ic2VydmF0aW9uIHdpdGggbWlzc2luZyB2YWx1ZXMgKD4wKSBhbmQgcHV0IGluIHRoZSBkYXRhZnJhbWUgIk5BX3JlbGF0aW9uX2NoZWNrIi4KCioqU3RlcCA1LjQqKgpBZnRlciBjaGVja2luZywgSSBjb3VsZCBub3QgZmluZCBhbnkgcmVsYXRpb24gdG8gdGhlIG90aGVyIHZhcmlhYmxlIG9yIGJldHdlZW4gdGhlIG9ic2VydmF0aW9uLiBUaGUgbWlzc2luZyB2YWx1ZSBsb29rIGxpa2UgTWlzc2luZyBjb21wbGV0ZWx5IGF0IHJhbmRvbSAoTUNBUikgZm9yIG1lLiAiQSBydWxlIG9mIHRodW1iIHNheXMgdGhhdCB3aGVuIHRoZSBkYXRhIGluY2x1ZGUgbGVzcyB0aGFuIDUlIHJhbmRvbSBtaXNzaW5nbmVzcyB3aGljaCBkb2VzIG5vdCBkZXBlbmQgb24gb2JzZXJ2ZWQgb3IgdW5vYnNlcnZlZCB2YWx1ZXMsIGNvbXBsZXRlIGNhc2UgYW5hbHlzaXMgbWF5IGJlIGFuIGFjY2VwdGFibGUgYXBwcm9hY2gsIHRvbyIoSGFubmFoIFJvb3MsIDIwMjEpLiAKCiogQ2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mIHRoZSBvYnNlcnZhdGlvbiB3aXRoIG1pc3NpbmcgdmFsdWUgYnkgZGV2aWRpbmcgdGhlIG51bWJlciBvZiB0aGUgb2JzZXJ2YXRpb25zIHdpdGggdGhlIG1pc3NpbmcgdmFsdWVzIGJ5IHRoZSBudW1iZXIgb2YgYWxsIHRoZSBvYnNlcnZhdGlvbnMgaW4gdGhlIGRhdGFzZXQgYW5kIHRoZW4gbXVsdGlwbHkgYnkgMTAwLiBUaGUgcmVzdWx0IHNob3duIHRoYXQgdGhlIG9ic2VydmF0aW9ucyB3aXRoIHRoZSBtaXNzaW5nIHZhbHVlcyBpcyBqdXN0IDEuNjYlIG9mIGFsbCBvYnNlcnZhdGlvbnMuIEJlY2F1c2Ugb2YgdGhlIGluZm9ybWF0aW9uIGFib3ZlLCBJIGNob29zZSB0byBleGNsdWRlIGFsbCB0aGUgb2JzZXJ2YXRpb24gd2l0aCB0aGUgbWlzc2luZyB2YWx1ZS4KCioqU3RlcCA1LjUqKiBFeGNsdWRlIHRoZSBvYnNlcnZhdGlvbnMgd2l0aCBtaXNzaW5nIHZhbHVlczogIAoKKiBVc2UgdGhlIGNvbXBsZXRlLmNhc2VzKCkgZnVuY3Rpb24gdG8gaWRlbnRpZnkgY29tcGxldGUgcm93IG9mIHRoZSBkYXRhZnJhbWUgYW5kIHRoZSBzcXVhcmUgYnJhY2tldHMgdG8gc3Vic2V0IHRob3NlIHJvdyB3aXRoIGFsbCBjb2x1bW4uIEFzc2lnbiB0aGUgcmVzdWx0IHRvIGRhdGFmcmFtZSBjYWxsZWQgIkxpdmVzX2xvc3QyIi4KKiBDaGVjayBpZiB0aGVyZSBpcyBhbnkgTkEgdmFsdWUgbGVmdCBpbiB0aGUgZGF0YWZyYW1lIHdpdGggdGhlIHNhbWUgZnVuY3Rpb24gYXMgc3RlcCA1LjIuCiogVGhlIHJlc3VsdCBzaG93biB0aGF0IHRoZXJlIGlzIG5vIE5BIHZhbHVlIGxlZnQgaW4gdGhlIGRhdGFmcmFtZSAiTGl2ZXNfbG9zdDIiLgoKYGBge3J9Cgppcy5uYShMaXZlc19sb3N0KSAlPiUgY29sU3VtcygpCgpMaXZlc19sb3N0JERBWV9PRl9XRUVLIDwtIHdlZWtkYXlzKExpdmVzX2xvc3QkREFURSkKTGl2ZXNfbG9zdCREQVlfT0ZfV0VFSyAlPD4lIGZhY3RvcihsZXZlbHM9YygiU3VuZGF5IiwiTW9uZGF5IiwiVHVlc2RheSIsIldlZG5lc2RheSIsIlRodXJzZGF5IiwiRnJpZGF5IiwiU2F0dXJkYXkiKSwgb3JkZXJlZD1UUlVFKQppcy5uYShMaXZlc19sb3N0JERBWV9PRl9XRUVLKSAlPiUgd2hpY2goKSAlPiUgbGVuZ3RoKCkKCmlzLm5hKExpdmVzX2xvc3QpICU+JSB3aGljaCgpICU+JSBsZW5ndGgoKQpOQV9yZWxhdGlvbl9jaGVjayA8LSBMaXZlc19sb3N0W3Jvd1N1bXMoaXMubmEoTGl2ZXNfbG9zdCkpID4gMCwgXQpOQV9yZWxhdGlvbl9jaGVjayAlPiUgaGVhZAoKKChOQV9yZWxhdGlvbl9jaGVjayAlPiUgbnJvdykvKExpdmVzX2xvc3QlPiUgbnJvdygpKSkgKiAxMDAKTGl2ZXNfbG9zdDI8LUxpdmVzX2xvc3RbY29tcGxldGUuY2FzZXMoTGl2ZXNfbG9zdCksIF0KaXMubmEoTGl2ZXNfbG9zdDIpJT4lIHdoaWNoKCkgJT4lIGxlbmd0aCgpCmBgYAoKIyMJU2NhbiBJSQoKSSBhbSB1c2luZyB0aGUgdW5pdmFyaWF0ZSBvdXRsaWVyIGRldGVjdGlvbiBtZXRob2Qgd2l0aCBOb24tcGFyYW1ldHJpYyBtZXRob2QgKEJveCBwbG90KSwgdG8gYXBwcm9hY2ggdGhlICJOT19PRl9WRUhJQ0xFUyIgdmFyaWFibGUgYmVjYXVzZSBJIGFtIGp1c3QgZm9jdXNpbmcgb24gb25lIHBhcnRpY3VsYXIgdmFyaWFibGUgYW5kIEkgYXNzdW1lIHRoYXQgdGhlIGRhdGEgaXMgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGUuIEZvciB0aGUgaGFuZGxpbmcgcHJvY2VzcywgSSBjaG9vc2UgdG8gZGVsZXRlIGFsbCB0aGUgb3V0bGllcnMgYmVjYXVzZSBpbXB1dGluZyB3aXRoIG1lYW4gZG9lcyBub3QgbWFrZXNlbnNlIGFzIHRoZSB2YWx1ZSBpbmRpY2F0ZSBudW1iZXIgb2YgdmVoaWNsZXMgd2hpY2ggc2hvdWxkIGJlIGludGVnZXIgKG1lYW4gaXMgMS42NTEgd2hpY2ggaXMgbm90IGludGVnZXIpIGFuZCBpbXB1dGluZyB3aXRoIG1lZGlhbiBpcyBub3QgZ29pbmcgdG8gc3VpdCB3aXRoIHRoZSBvdGhlciB2YXJpYWJsZXMgaW4gdGhlIG9ic2VydmF0aW9uLiBUaGUgcHJvY2Vzc2VzIGlzIGFzIGZvbGxvd2luZzogIAoKKipTdGVwIDYuMSoqIENyZWF0ZSBCb3hwbG90IG9mIHRoZSB2YXJpYWJsZSAiTk9fT0ZfVkVISUNMRVMiIHRvIHNlZSB0aGUgYmlnIHBpY3R1cmUgb2YgdGhlIGRhdGEgYW5kIHRoZSBvdXRsaWVycyBieSB1c2luZyB0aGUgYm94cGxvdCgpIGZ1bmN0aW9uLiAgCgoqIEFzc2lnbiB0aGUgYXJndW1lbnQgIm1haW4iIHdpdGggdGhlIHRpdGxlIG9mIHRoZSBib3hwbG90LCBpbiB0aGlzIGNhc2UgIkJveCBQbG90IG9mIE51bWJlciBvZiB2ZWhpY2xlcyIuICAKKiBBc3NpZ24gdGhlIGFyZ3VtZW50ICJ5bGFiIiB3aXRoIHRoZSB5LWF4aXMgYW5ub3RhdGlvbiwgaW4gdGhpcyBjYXNlICJOdW1iZXIgb2YgdmVoaWNsZXMiLgoqIEFzc2lnbiB0aGUgYXJndW1lbnQgImNvbCIgd2l0aCB0aGUgY29sb3IgcHJlZmVyZW5jZSBmb3IgdGhlIGJvZGllcyBvZiB0aGUgYm94IHBsb3QsIGluIHRoaXMgY2FzZSBJIGNob29zZSAib3JhbmdlIi4KCioqU3RlcCA2LjIqKiBBcHBseSB0aGUgdW5pdmFyaWF0ZSBvdXRsaWVyIGRldGVjdGlvbiBieTogIAoKKiBHZXR0aW5nIHRoZSBRMSBhbmQgUTMgdmFsdWVzIGJ5IHVzaW5nIHRoZSBzdW1tYXJ5KCkgZnVuY3Rpb24uIFRoZSByZXN1bHQgc2hvd246ICAKICArIFRoZSBmaXJzdCBwb3NpdGlvbjogbWluaW11bSB2YWx1ZSA9IDEuMDAuCiAgKyBUaGUgc2Vjb25kIHBvc2l0aW9uOiBRMSA9IDEuMDAuCiAgKyBUaGUgdGhpcmQgcG9zaXRpb246IG1lZGlhbiA9IDEuMDAgCiAgKyBUaGUgNHRoIHBvc2l0aW9uOiBtZWFuID0gMS42NQogICsgVGhlIDV0aCBwb3NpdGlvbjogUTMgPSAyLjAwCiAgKyBUaGUgNnRoIHBvc2l0aW9uOiBtYXhpbXVtIHZhbHVlID0gMTEuMDAKKiBFeHRyYWN0IHRoZSBRMSB2YWx1ZSBieSB1c2luZyB0aGUgZG91YmxlIHNxdWFyZSBicmFja2V0cyB0byBzdWJzZXQgdGhlIHZhbHVlIGZyb20gdGhlIDJuZCBwb3NpdGlvbiBvZiB0aGUgc3VtbWFyeSgpIGZ1bmN0aW9uJ3MgcmVzdWx0IGFuZCBhc3NpZ24gdG8gInExIi4KKiBFeHRyYWN0IHRoZSBRMyB2YWx1ZSBieSB1c2luZyB0aGUgZG91YmxlIHNxdWFyZSBicmFja2V0cyB0byBzdWJzZXQgdGhlIHZhbHVlIGZyb20gdGhlIDV0aCBwb3NpdGlvbiBvZiB0aGUgc3VtbWFyeSgpIGZ1bmN0aW9uJ3MgcmVzdWx0IGFuZCBhc3NpZ24gdG8gInEzIi4KKiBDYWxjdWxhdGUgdGhlIGludGVycXVhcnRpbGUgcmFuZ2UoSVFSKSBieSBzdWJ0cmFjdCBxMSB2YWx1ZSBmcm9tIHEzIHZhbHVlIGFuZCBhc3NpZ24gdG8gImlxciIuCiogQ2FsY3VsYXRlIHRoZSB1cHBlciBmZW5jZSBieSBhZGQgdGhlIDEuNSB0aW1lcyBvZiBpcXIgdG8gcTMgYW5kIGFzc2lnbiB0aGUgdmFsdWUgdG8gInVwcGVyX2ZlbmNlIi4KKiBDYWxjdWxhdGUgdGhlIGxvd2VyIGZlbmNlIGJ5IHN1YnRyYWN0IHRoZSAxLjUgdGltZXMgb2YgaXFyIGZyb20gcTEgYW5kIGFzc2lnbiB0aGUgdmFsdWUgdG8gImxvd2VyX2ZlbmNlIi4KKiBFeHRyYWN0IHRoZSBwb3NpdGlvbiBvZiB0aGUgb3V0bGllcnMgYnkgdXNpbmcgdGhlIHdoaWNoKCkgZnVuY3Rpb24sIHBpY2tpbmcganVzdCB0aGUgdmFsdWVzIHRoYXQgaXMgbW9yZSB0aGFuIHRoZSAidXBwZXJfZmVuY2UiIHZhbHVlIGFuZCBsZXNzIHRoYW4gdGhlICJsb3dlcl9mZW5jZSIgdmFsdWUuIEFzc2lnbiB0aGUgb3V0bGllcnMgb3ZlciB0aGUgInVwcGVyX2ZlbmNlIiB2YWx1ZSBpbnRvICJ1cF9vdXRsaWVycyIgYW5kIGFzc2lnbiB0aGUgb3V0bGllcnMgYmVsb3cgdGhlICJsb3dlcl9mZW5jZSIgdmFsdWUgaW50byAibG93X291dGxpZXJzIi4KKiBTdW0gdXAgdGhlIGFtb3VudCBvZiBvdXRsaWVycyBpbiBlYWNoIG9mIHRoZSBvYmplY3QgKHRoZSAidXBfb3V0bGllcnMiIGFuZCB0aGUgImxvd19vdXRsaWVycyIpIGJ5IHVzaW5nIHRoZSAibGVuZ3RoIiBmdW5jdGlvbi4gdGhlIHJlc3VsdCBzaG93biB0aGF0IHRoZSBhbW91bnQgb2YgdGhlIG91dGxpZXIgYWJvdmUgdGhlICJ1cHBlcl9mZW5jZSIgdmFsdWUgaXMgMzcgb3V0bGllcnMgYnV0IHRoZXJlIGlzIG5vbmUgb3V0bGllciBiZWxvdyB0aGUgImxvd2VyX2ZlbmNlIgoKKipTdGVwIDYuMyoqIEhhbmRsZSB0aGUgb3V0bGllcnMgYnkgZXhjbHVkZSB0aGVtIHVzaW5nIHRoZSBzcXVyZSBicmFja2V0IGFuZCAiLSIgb3BlcmF0b3IgdG8gZHJvcCB0aGUgInVwX291dGxpZXIiIHBvc2l0aW9ucyBmcm9tIHRoZSAiTGl2ZXNfbG9zdDIkTk9fT0ZfVkVISUNMRVMiIGFuZCBhc3NpZ24gdGhlIHJlc3VsdCBpbnRvIHRoZSAiVmVoaWNsZV9jbGVhbiIgb2JqZWN0LgoKKiBDaGVjayB0aGUgcmVzdWx0IGJ5IHVzaW5nIHRoZSBib3hwbG90KCkgZnVuY3Rpb24gYW5kIGFzc2lnbiB0aGUgbGlzdCBpbnRvICJicCIgYW5kIHRoZW4gdXNlIHRoZSBsZW5ndGgoKSBmdW5jdGlvbiB0byBzdW0gdXAgdGhlIGFtb3VudCBvZiB0aGUgb3V0bGllciBpbiB0aGUgIm91dCIgZWxlbWVudCBpbiB0aGUgImJwIiBsaXN0LiBUaGUgcmVzdWx0IHNob3dtIHRoYXQgdGhlcmUgaXMgbm9uIG91dGxpZXIgbGVmdCBpbiB0aGUgb2JqZWN0ICJWZWhpY2FsX2NsZWFuIi4KCmBgYHtyfQoKTGl2ZXNfbG9zdDIkTk9fT0ZfVkVISUNMRVMgJT4lICAKICBib3hwbG90KG1haW4gPSAiQm94IFBsb3Qgb2YgTnVtYmVyIG9mIHZlaGljbGUiLCB5bGFiID0gIk51bWJlciBvZiB2ZWhpY2xlIiwgY29sID0gIm9yYW5nZSIpIAoKc3VtbWFyeShMaXZlc19sb3N0MiROT19PRl9WRUhJQ0xFUykKCnExIDwtIHN1bW1hcnkoTGl2ZXNfbG9zdDIkTk9fT0ZfVkVISUNMRVMpW1syXV0KcTMgPC0gc3VtbWFyeShMaXZlc19sb3N0MiROT19PRl9WRUhJQ0xFUylbWzVdXQppcXIgPC0gcTMgLSBxMQoKbG93ZXJfZmVuY2UgPC0gcTEgLSAoMS41ICogaXFyKQp1cHBlcl9mZW5jZSA8LSBxMyArICgxLjUgKiBpcXIpCgp1cF9vdXRsaWVycyA8LSB3aGljaChMaXZlc19sb3N0MiROT19PRl9WRUhJQ0xFUyA+IHVwcGVyX2ZlbmNlKQpsb3dfb3V0bGllcnMgPC0gd2hpY2goTGl2ZXNfbG9zdDIkTk9fT0ZfVkVISUNMRVMgPCBsb3dlcl9mZW5jZSkKCmxvd19vdXRsaWVycyAlPiUgbGVuZ3RoKCkKdXBfb3V0bGllcnMgJT4lIGxlbmd0aCgpCgpWZWhpY2xlX2NsZWFuPC0gTGl2ZXNfbG9zdDIkTk9fT0ZfVkVISUNMRVNbLXVwX291dGxpZXJzXQoKYnA8LSBib3hwbG90KFZlaGljbGVfY2xlYW4pCmJwJG91dCAlPiUgbGVuZ3RoKCkKCmBgYAoKIyMJVHJhbnNmb3JtIAoKKipTdGVwIDcqKiBUcmFuc2Zvcm1hdGlvbiA6IEkgY2hvb3NlIHRvIHRyYW5zZm9ybSB0aGUgIkFHRSIgdmFyaWFibGUuIEkgY29udmVydCB0aGUgdmFyaWFibGUgZnJvbSBvcmRlcmVkIGZhY3RvciBpbnRvIG51bWVyaWMgYnkgdXNpbmcgdGhlIGFzLm51bWVyaWMoKSBmdW5jdGlvbiB0byBiZSBhYmxlIHRvIHBsb3QgdGhlIGdyYXBoIGFuZCB0cmFuc2Zvcm0uIFRoZW4sIGV4dHJhY3QganVzdCB0aGUgIkFHRSIgdmFyaWFibGUgaW50byAiQWdlIiBvYmplY3Qgc28gdGhpcyBwcm9jZXNzIGRvZXMgbm90IGNoYW5nZSB0aGUgdHlwZSBvZiB0aGUgdmFyaWFibGUgaW4gdGhlIGJpZyBkYXRhc2V0LgoKKipTdGVwIDcuMSoqIENyZWF0ZSBhIGhpc3RvZ3JhbSBvZiB0aGUgIkFnZSIgYnkgdXNpbmcgdGhlIGhpc3QoKSBmdW5jdGlvbi4gIAoKKiBBc3NpZ24gdGhlIGFyZ3VtZW50ICJtYWluIiB3aXRoIHRoZSB0aXRsZSBvZiB0aGUgaGlzdG9ncmFtICJIaXN0b2dyYW0gb2YgQWdlIi4KKiBBc3NpZ24gdGhlIGFyZ3VtZW50ICJ4bGFiIiB3aXRoIHRoZSB4LWF4aXMgYW5ub3RhdGlvbiAiQWdlKHllYXJzIG9sZCkiLgoqIEFzc2lnbiB0aGUgYXJndW1lbnQgImNvbCIgd2l0aCB0aGUgY29sb3IgcHJlZmVyZW5jZSBmb3IgdGhlIGJhci4gCgpUaGUgcmVzdWx0IHNob3duIHRoYXQgdGhlIGRhdGEgYXBwZWFyIHRvIGJlIHJpZ2h0LXNrZXdlZC4gCgoqKlN0ZXAgNy4yKiogVHJhbnNmb3JtIHRoZSBBZ2UgZGF0YSB0byBkZWNyZWFzZSB0aGUgc2tld25lc3MgYnkgdXNpbmcgc3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24gYXMgdGhlIHNxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uIGlzIHVzZWQgZm9yIHJlZHVjaW5nIHJpZ2h0LXNrZXduZXNzLiAgCgoqIFByb2Nlc3MgdGhlIHNxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uIGJ5IHRha2luZyB0aGUgIkFnZSIgdmFyaWFibGUgdmFsdWVzIHRvIHRoZSBwb3dlciBvZiAxLzIuCiogUmV2aWV3IHRoZSByZXN1bHRzIG9mIHRoZSBkYXRhIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIHRyYW5zZm9ybWF0aW9uIHNpZGUgYnkgc2lkZSBieSB1c2luZyB0aGUgcGFyKCkgZnVuY3Rpb24gdG8gc2V0IHRoZSBncmFwaGljYWwgcGFyYW1ldGVyIG9mIHRoZSBncmFwaC4gVXNlIHRoZSAibWZyb3ciIGFyZ3VtZW50IHRvIHBsb3QgdGhlIGdyYXBoIHRvIDIgY29sdW5tcyBpbiAxIHJvdy4gCiogVXNpbmcgdGhlIGhpc3QoKSBmdW5jdGlvbiB0byBwbG90IGJvdGggZ3JhcGguCiogVGhlIHJlc3VsdCBzaG93biB0aGF0IHRoZSBzcXVhcmUgcm9vdCB0cmFuc2Zvcm1hdGlvbiByZWR1Y2VkIHRoZSByaWdodC1za2V3bmVzcyBvZiB0aGUgIkFnZSIgZGF0YS4gCiogKipUaGUgbW9tZW50cyBwYWNrYWdlIGlzIG5vdCBpbiB0aGUgYXNzZXNzbWVudCByZXF1aXJtZW50IGJ1dCBJIGp1c3Qgd2FudCB0byBleHBsYWluIGhvdyBJIGNoZWNrZWQgdGhlIHNrZXduZXNzIG9mIHRoZSBncmFwaC4gSSB1c2UgdGhlIHNrZXduZXNzKCkgZnVuY3Rpb24gZnJvbSB0aGUgbW9tZW50cyBwYWNrYWdlIHRvIG1ha2Ugc3VyZSB0aGUgZGF0YSBpcyBsZXNzIHNrZXdlZC4gVGhlIHJlc3VsdCBzaG93biB0aGF0IHRoZSBBZ2Ugc2tld25lc3Mgd2FzIDAuMzQgdG8gdGhlIHJpZ2h0IGJ1dCBhZnRlciB0aGUgdHJhbnNmb3JtYXRpb24gdGhlIHNrZXduZXNzIHdhcyAwLjEyIHRvIHRoZSBsZWZ0IHdoaWNoIGlzIGxlc3Mgc2tld2VkLioqCiAKCmBgYHtyfQoKQWdlPC1hcy5udW1lcmljKExpdmVzX2xvc3QyJEFHRSkKCmhpc3QoQWdlLAptYWluPSJIaXN0b2dyYW0gb2YgQWdlIiwKeGxhYj0iQWdlKHllYXJzIG9sZCkiLApjb2w9ICJkYXJrc2xhdGVncmV5IikKCnBhcihtZnJvdz1jKDEsMikpCmhpc3QoQWdlLCBjb2wgPSAiZGFya3NsYXRlZ3JleSIpCnNxcnQgPC0gQWdlXigxLzIpCmhpc3Qoc3FydCwgY29sID0gImRhcmtzbGF0ZWdyYXkzIikKCmxpYnJhcnkobW9tZW50cykKc2tld25lc3MoQWdlKQpza2V3bmVzcyhzcXJ0KQoKYGBgCgoKIyMgUmVmZXJlbmNlczoKCl9DYWxjdWxhdGUgU2tld25lc3MgaW4gUl8gbi5kLiwgUHJvZ3JhbW1pbmdSLCB2aWV3ZWQgMTQgT2N0b2JlciAyMDIxLCA8aHR0cHM6Ly93d3cucHJvZ3JhbW1pbmdyLmNvbS9zdGF0aXN0aWNzL3NrZXduZXNzLz4KCkhhZGxleSBXaWNraGFtIGFuZCBHYXJyZXR0IEdyb2xlbXVuZCwgX1IgZm9yIERhdGEgU2NpZW5jZV8sIFI0RFMsIHZpZXdlZCAxOCBTZXB0ZW1iZXIgMjAyMSwgPGh0dHBzOi8vcjRkcy5oYWQuY28ubnovdGlkeS1kYXRhLmh0bWw+CgpNYW5naWFmaWNvLCBTLlMuIDIwMTYsIFN1bW1hcnkgYW5kIEFuYWx5c2lzIG9mIEV4dGVuc2lvbiBQcm9ncmFtIEV2YWx1YXRpb24gaW4gUiwgdmlld2VkIDE0IE9jdG9iZXIgMjAyMSwgPGh0dHBzOi8vcmNvbXBhbmlvbi5vcmcvaGFuZGJvb2svSV8xMi5odG1sPgoKVmljdG9yaWEgRGVwYXJ0bWVudCBvZiBUcmFuc3BvcnQgMjAyMSwgX0NyYXNoZXNfTGFzdF9GaXZlX1llYXJzIC0gT3BlbiBEYXRhXywgZGF0YSBmaWxlLCBWaWN0b3JpYSBEZXBhcnRtZW50IG9mIFRyYW5zcG9ydCBPcGVuIERhdGEgSHViLCB2aWV3ZWQgMTAgT2N0b2JlciAyMDIxLCA8aHR0cHM6Ly92aWNyb2Fkc29wZW5kYXRhLXZpY3JvYWRzbWFwcy5vcGVuZGF0YS5hcmNnaXMuY29tL2RhdGFzZXRzL3ZpY3JvYWRzbWFwczo6cm9hZC1jcmFzaGVzLWZvci1maXZlLXllYXJzLXZpY3RvcmlhL2Fib3V0Pi4KClZpY3RvcmlhIERlcGFydG1lbnQgb2YgVHJhbnNwb3J0LCBfRmF0YWwgQ3Jhc2hlcyAtIExpdmVzIExvc3QsIExhc3QgNSBZZWFycyB0byBEYXRlXywgdGhlIEZhdGFsIENyYXNoZXMgLSBMaXZlcyBMb3N0IFllYXIgdG8gRGF0ZSBkYXRhc2V0LCBkYXRhIGZpbGUsIERlcGFydG1lbnQgb2YgVHJhbnNwb3J0IE9wZW4gRGF0YSBIdWIsIHZpZXdlZCAxMCBPY3RvYmVyIDIwMjEsIDxodHRwczovL3ZpY3JvYWRzb3BlbmRhdGEtdmljcm9hZHNtYXBzLm9wZW5kYXRhLmFyY2dpcy5jb20vZGF0YXNldHMvdmljcm9hZHNtYXBzOjpyb2FkLWNyYXNoZXMtZm9yLWZpdmUteWVhcnMtdmljdG9yaWEvYWJvdXQ+LgoKSGFubmFoIFJvb3MgMjAyMSwgX1NtYXJ0IGhhbmRsaW5nIG9mIG1pc3NpbmcgZGF0YSBpbiBSXywgVG93YXJkcyBEYXRhIFNjaWVuY2UsIHZpZXdlZCAxMCBPY3RvYmVyIDIwMjEsCjxodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vc21hcnQtaGFuZGxpbmctb2YtbWlzc2luZy1kYXRhLWluLXItNjQyNWY4YTU1OWYyPiAKCjxicj4KPGJyPgo8YnI+Cjxicj4K