Group members(3)

Guannan Shi PID:A98051827 1st Year Graduate Electrical Engineering
Hao Jiang PID:A91426797 1st Year Graduate Electrical Engineering
Wenhao Sheng PID:A99033876 1st Year Graduate Electrical Engineering


1.Introduction


#set wd
setwd("C:/Users/weshe/Desktop/Math 289C/HWs/HW2")
data <- read.table("videodata.txt",header=TRUE)
#install package
install.packages("moments")
install.packages("tree")
install.packages("randomForest")
#input library
library(ggplot2)
library(MASS)
library(moments)
library(tree)
library(party)
library(randomForest)

2.Analysis

2.1 Scenario 1

We begin by providing an estimate for the fraction of students who played a video game in the week prior to the survey. First of all, we cleaned up the data by excluding answers which are encoded as 99 because those are considered invalid or improper answers. Then, we only need to consider the “time”" column of the data. Based on the figure above, we can filter out the students who played video games a week prior to the exam by picking the nonzero data points in the “time” column of the data. The point estimate is the ratio of the number of students who played over the number of students who provided a valid answer.

We convert information contained in the “time”" column of the original data to a “TRUE/FALSE”" indicator column vector, named ‘data.play‘. The procedure of this conversion is simple. We check whether an entry in the ‘time’ column is larger than 0. If it is, we put a 1 in the corresponding location in ‘data.play’, otherwise, we put a 0 there. Therefore, ‘data.play’ can be used as an indicator to whether the students played video games in the week prior to the survey. Now, we make the mean of the entries in the indicator vector equal to the point estimate.

data[data == 99] <- NA
data.play <- data$time>0
play <- sum(data.play, na.rm=TRUE)
point.estimate <- play/length(data$time)
point.estimate
[1] 0.3736264



Our point estimate for the fraction of students who played a video game a week prior to the exam is about 37%.

To provide an interval estimate of this estimator, since n is large but n/N = 91/314 is not small, we need to use bootstrap to check if we can use normal approximation. Through bootstrapping, we are able to collect more samples from the population. Therefore we can get a range of possible values that the estimate could potentially fall into if we increase the number of data. Given that the data is drawn from a population with size of \(N = 314\), we first create a Bootstrap population of this size by repeating every sample for \(314/91 = 3.45\) times. Then we randomly draw \(n = 91\) samples from the Bootstrap population. And we store each Bootstrap sample. In this problem, we have a total of 4000 Bootstrap samples. For each Bootstrap sample, we calculate its mean. Then, we plot the histogram of these Bootstrap sample means.

To check for normality, we used three methods: the Q-Q plot, skewness and Kurtosis test.

boot.time <- rep(data.play, length.out = 314)
set.seed(189289)
B = 4000 # the number of bootstrap samples we want
boot.sample <- array(dim = c(B, 91))
for (i in 1:B) {
  boot.sample[i, ] <- sample(boot.time, size = 91, replace = FALSE)
}
boot.mean = apply(X = boot.sample, MARGIN = 1, FUN = mean)
hist(boot.mean,  breaks = 20, probability = TRUE, density = 20, col = 3, border = 3, main = "Histogram of the percentage", xlab = "percentage")
lines(density(boot.mean, adjust = 2), col = 2)
#check normality by Q-Q plot 
par(pty = 's')

qqnorm(boot.mean)
qqline(boot.mean)

#compare the kurtosis and skewness.  We installed the 'moments' package
skewness(boot.mean)
[1] 0.009829578
kurtosis(boot.mean)
[1] 2.958165

We get a skewness of 0.009829578, which is close to 0, and a Kurtosis of 2.958165, which is smaller than 3. Also, the Q-Q plot is quite close to the standard line, we are able to conclude that the Bootstrap samples distribution is close to be a normal distribution.

#construct the 95% interval estimate using boostrap means
int.boot <- c(quantile(boot.mean, 0.025), quantile(boot.mean, 0.975))
int.boot
     2.5%     97.5% 
0.2747253 0.4505495 

As a result of normality, the 95% confidence interval is obtained using quantile analysis of a normal distribution as shown above. A detailed proof about sample mean and standard error required by the professor is in the appendices.

2.2 Scenario 2

In the second scenario, we analyze how the amount of time spent playing video games in the week prior to the survey compares to the reported frequency of play. By comparing the acutal amount of time students played to the reported frequency, we are able to determine how the fact that there was an exam prior to the survey affect the amount of time students spent on video games.

To draw the comparison, we first separate all the students into 4 categories based on their reported frequency of play. Then we calculate the number of students who actually played video games in the week prior to the exam.

#Numerical Method#
#Daily player who actually played the week prior to exam
index.daily <- which(data$freq %in% c(1))
a.1 <- length(index.daily)
a.2 <- sum(data$time[index.daily]>0)
#Weekly player who actually played the week prior to exam
index.weekly <- which(data$freq %in% c(2))
b.1 <- length(index.weekly)
b.2 <- sum(data$time[index.weekly]>0)
#Monthly player who actually played the week prior to exam
index.monthly <- which(data$freq %in% c(3))
c.1 <- length(index.monthly)
c.2 <- sum(data$time[index.monthly]>0)
#Semesterly player who actually played the week prior to exam
index.semesterly <- which(data$freq %in% c(4))
d.1 <- length(index.semesterly)
d.2 <- sum(data$time[index.semesterly]>0)
senerio.2 <- matrix(c(a.1,a.2,b.1,b.2,c.1,c.2,d.1,d.2), ncol=2,byrow=TRUE)
colnames(senerio.2) <- c("# of people play games","# of people played last week")
rownames(senerio.2) <- c("Daily","Weekly","Monthly","Semesterly")
senerio.2 <- as.table(senerio.2)
senerio.2
           # of people play games # of people played last week
Daily                           9                            7
Weekly                         28                           24
Monthly                        18                            2
Semesterly                     23                            1

From the above table, it shows that 9 students reported that they play games daily and 7 of them played last week; 28 students reported that they play weekly and 24 of them played last week; 18 students play games monthly but only 2 of them played last week; 23 students play games semesterly but only 1 of them played last week. Therefore, we can conclude that having an incoming exam greatly reduce the amount of time spent on video games for those students who play games monthly and semesterly. However, students who play games daily and weekly are more likely to continue playing video games, whether or not they have exam in the following week.

2.3 Scenario 3

In the third scenario, we provide an interval estimate for average amount of time spent on playing video games in the week prior to the survey. In order to accomplish this, we first use the bootstrap simulation technique to randomly select 4000 samples of size 91 from a population of size 314.

##make an interval estimate for the average amount of time spent playing video games in the week prior to survey ##
boot.population <- rep(data$time, length.out = 314)
set.seed(189289)
boot.time_sample <- array(dim=c(4000,91))
for (i in 1:4000)
{
  boot.time_sample[i,] <- sample(boot.population, size = 91, replace = FALSE)
}

Then we proceed to calculate the mean of each sample and plot them in a histogram.

boot.time_mean <- apply(X = boot.time_sample, MARGIN = 1,  FUN = mean)
hist(boot.time_mean, breaks = 20, probability = TRUE, density = 20, col = 3, border = 3, xlab = 'time spent on video games', ylab = 'count', main = 'Histogram of time spent on video games')
lines(density(boot.time_mean, adjust = 2), col = 2)

To provide an interval estimation for the average time, we first plot the Q-Q plot and perform the Shapiro-Wilk test to determine of the average time is normally distributed.

#check normality by Q-Q plot 
par(pty = 's')
qqnorm(boot.time_mean)
qqline(boot.time_mean)

skewness(boot.time_mean)
[1] 0.3682332
kurtosis(boot.time_mean)
[1] 2.8243

We get a skewness of 0.3682 and a Kurtosis of 2.8243, which is smaller than 3. Also, the Q-Q plot is quite close to the standard line, we are able to conclude that the Bootstrap samples distribution is close to be a normal distribution.

#construct the 95% confidence internval
int.boot <- c(quantile(boot.time_mean, 0.025), quantile(boot.time_mean, 0.975))
int.boot
     2.5%     97.5% 
0.6010714 1.7824451 

As a result of normality, the 95% confidence interval is obtained using quantile analysis of a normal distribution as shown above.

2.4 Scenario 4

In this scenario, We analyze the “like” column in the dataset to determine whether or not students enjoy playing video games. Noticing the fact that, not all students answered this question, we need to get rid of some of the data. After data-cleaning, we counted for how many students answered positively (e.g. very much and somewhat) to this question and how many of them answered negatively (e.g. never played, not really, and not at all).

#do you think the students enjoy playing video games?
likeindex <- which(!is.na(data$like))
data.like <- data[likeindex,]
data.like['like_01'] <- rep(NA,dim(data.like)[1]) # create 91X1 matrix, NA for all elements
for ( i in 1:dim(data.like)[1]){
  like <- data.like[i,'like']
  if(like == 1 || like == 4 || like == 5){
    data.like[i,'like_01'] <- 0
  }else{
    data.like[i,'like_01'] <- 1
  }
}
table(data.like$like_01)

The result showing above with 0 representing students who don’t enjoy playing video games and 1 being the students who do. It is clear that, out of 90 students who provided a valid answer to this question, more than 75% said that they actually enjoy playing video games.


In lecture, professor also presented some follow-up surveys in addition to the data set we have. In those follow up surveys, more information about why students like or dislike to play video games is unveiled.


For instance, the table above shows what the primary reasons are for those who enjoy playing video games. Therefore, if I’m to give a list of the reasons why the students like playing video games, my list would look like:
1.Relaxation
2.Feeling of mastery
3.Bored
4.Graphics/Realism
5.Mental Challenge



Similarly, given the table above, we could list the reasons why the students dislike playing video games:
1.Too much time
2.Cost too much
3.It is pointless
4.Frustrating
5.Too many rules


2.5 Scenario 5

To appraoch this scenario, we will make several tables and bar plots to view the the relationship between the level of like to play and the factor owning a PC and the relationship between the level of like to play and the factor how long students working. Besides, a randomForest function will be applied to view relation between other facts with the like. After plotting the bar plots, we will analyze the data combined with the results from the follow up survey.

#randomForest
set.seed(189289)
relation <- randomForest(data.like$like_01 ~ sex+home+educ+age+busy+math+work+own+cdrom+grade, data = data.like, importance = TRUE, na.action = na.omit)
varImpPlot(relation)

The randomForest approach is just for fun ^_^. I am not sure whether it is a good approach though. Anyway, I installed the randomForest package, and implemented the algorithm in hope that it could return some useful information about the relationship between whether the students like or dislike playing video games versus other factors in the data set. To my knowledge, the %IncMSE is the most robust and informative measure. It is the increase in mse of predictions as a result of variable being permuted. As a conclusion, if the factor has a higher %IncMSE number, the important that factor is to whether students like or dislike to play video games. In this problem, since we are only concerned about there factors, namely, ‘sex’, ‘work’, and ‘own’, I would predict, from the result of randomForest, that ‘sex’, and ‘work’ are more important than ‘own’.

#table
#calculate the total male and female students
sex_1_like_1 = sum(data.like$sex == 1 & data.like$like == 1)
sex_1_like_2 = sum(data.like$sex == 1 & data.like$like == 2)
sex_1_like_3 = sum(data.like$sex == 1 & data.like$like == 3)
sex_1_like_4 = sum(data.like$sex == 1 & data.like$like == 4)
sex_1_like_5 = sum(data.like$sex == 1 & data.like$like == 5)

sex_0_like_1 = sum(data.like$sex == 0 & data.like$like == 1)
sex_0_like_2 = sum(data.like$sex == 0 & data.like$like == 2)
sex_0_like_3 = sum(data.like$sex == 0 & data.like$like == 3)
sex_0_like_4 = sum(data.like$sex == 0 & data.like$like == 4)
sex_0_like_5 = sum(data.like$sex == 0 & data.like$like == 5)

sex <- matrix(c(0,5,21,8,4,38,1,18,25,5,3,52),ncol=6,byrow=TRUE)
colnames(sex) <- c("Never played","Very much","Somewhat","Not really","Not at all","Total")
rownames(sex) <- c("Female","Male")
sex <- as.table(sex)
sex

sex1 <- matrix(c(0,5,21,8,4,1,18,25,5,3),ncol=5,byrow=TRUE)
colnames(sex1) <- c("Never played","Very much","Somewhat","Not really","Not at all")
rownames(sex1) <- c("Female","Male")
sex1 <- as.table(sex1)


barplot(sex1,main="student sex v.s. their Like to Play level",names.arg = colnames(sex1),xlab="Sex",col=c("darkblue","red"),legend = rownames(sex1), beside=TRUE)

This is the bar plot of students’ sex vs. their like to play level. The total numbers of female and male students considered are 38 and 52, and there is one student does not answer properly in “like to play” level, so we only consider 90 samples in total in this scenario. As the bar plot showing, majority of the female students chose like to play somewhat and most male students chose like to play very much or somewhat. Besides, even though there are less female students in this sample, the number of the female students that chose not really like to video games and not like video games at all is apparently still bigger than the number of the male students that chose not really like to video games and not like video games at all. Thus, compared with the male students, these female students in this sample are more likely dislike the video games or do not like video games very much.

#count the like and own
own_1_like_1 = sum(data.like$own == 1 & data.like$like == 1)
own_1_like_2 = sum(data.like$own == 1 & data.like$like == 2)
own_1_like_3 = sum(data.like$own == 1 & data.like$like == 3)
own_1_like_4 = sum(data.like$own == 1 & data.like$like == 4)
own_1_like_5 = sum(data.like$own == 1 & data.like$like == 5)

own_0_like_1 = sum(data.like$own == 0 & data.like$like == 1)
own_0_like_2 = sum(data.like$own == 0 & data.like$like == 2)
own_0_like_3 = sum(data.like$own == 0 & data.like$like == 3)
own_0_like_4 = sum(data.like$own == 0 & data.like$like == 4)
own_0_like_5 = sum(data.like$own == 0 & data.like$like == 5)

own <- matrix(c(0,5,16,1,2,24,1,18,30,12,5,66),ncol=6,byrow=TRUE)
colnames(own) <- c("Never played","Very much","Somewhat","Not really","Not at all","Total")
rownames(own) <- c("Not Own PC","Own PC")
own <- as.table(own)
own

own1 <- matrix(c(0,5,16,1,2,1,18,30,12,5),ncol=5,byrow=TRUE)
colnames(own1) <- c("Never played","Very much","Somewhat","Not really","Not at all")
rownames(own1) <- c("Not Own PC","Own PC")
own1 <- as.table(own1)

barplot(own1,main="student own PC or not v.s. their Like to Play level",names.arg = colnames(own1),xlab="Own PC or Not",col=c("darkblue","red"),legend = rownames(own1), beside=TRUE)

This is a bar plot used to investigate whether student own PC or not will affect their like to play level. In this sample, there are 66 out of 90 students own a PC, and most of these people who own a PC are like to play video game very much or somewhat. There is still a small portion of these students own a PC that are does not like to play video games. Besides, most of those students who do not own a PC also like to play video games somewhat or even very much. Therefore, the factor owning a PC will not affect the students’ like to play level.


# working hours 1:[0 10),2:[10,20),3:[20,and more)
work_1_like_1 = sum(!is.na(data.like$work) & data.like$work<10 & data.like$like == 1)
work_1_like_2 = sum(!is.na(data.like$work) & data.like$work<10 & data.like$like == 2)
work_1_like_3 = sum(!is.na(data.like$work) & data.like$work<10 & data.like$like == 3)
work_1_like_4 = sum(!is.na(data.like$work) & data.like$work<10 & data.like$like == 4)
work_1_like_5 = sum(!is.na(data.like$work) & data.like$work<10 & data.like$like == 5)

work_2_like_1 = sum(!is.na(data.like$work) & data.like$work>=10 & data.like$work<20  & data.like$like == 1)
work_2_like_2 = sum(!is.na(data.like$work) & data.like$work>=10 & data.like$work<20  & data.like$like == 2)
work_2_like_3 = sum(!is.na(data.like$work) & data.like$work>=10 & data.like$work<20  & data.like$like == 3)
work_2_like_4 = sum(!is.na(data.like$work) & data.like$work>=10 & data.like$work<20  & data.like$like == 4)
work_2_like_5 = sum(!is.na(data.like$work) & data.like$work>=10 & data.like$work<20  & data.like$like == 5)

work_3_like_1 = sum(!is.na(data.like$work) & data.like$work>=20 & data.like$like == 1)
work_3_like_2 = sum(!is.na(data.like$work) & data.like$work>=20 & data.like$like == 2)
work_3_like_3 = sum(!is.na(data.like$work) & data.like$work>=20 & data.like$like == 3)
work_3_like_4 = sum(!is.na(data.like$work) & data.like$work>=20 & data.like$like == 4)
work_3_like_5 = sum(!is.na(data.like$work) & data.like$work>=20 & data.like$like == 5)


work <- matrix(c(0,12,26,12,4,54,1,6,16,1,2,26,0,5,1,0,1,7),ncol=6,byrow=TRUE)
colnames(work) <- c("Never played","Very much","Somewhat","Not really","Not at all","Total")
rownames(work) <- c("working hours in [0,10)","working hours in [10,20)","working hours more than 20")
work <- as.table(work)
work

work1 <- matrix(c(0,12,26,12,4,1,6,16,1,2,0,5,1,0,1),ncol=5,byrow=TRUE)
colnames(work1) <- c("Never played","Very much","Somewhat","Not really","Not at all")
rownames(work1) <- c("working hours in [0,10)","working hours in [10,20)","working hours more than 20")
work1 <- as.table(work1)


barplot(work1,main="student working hrs v.s. their Like to Play level",names.arg = colnames(work1),xlab="working hours",col=c("darkblue","red","yellow"),legend = rownames(work1), beside=TRUE)

In this part, we divide the working hours of students into three part, working hours less than 10 hours, between 10 and 20 hours and more than 20 hours. The reason why we choose 20 as a limit is that most of the students usually do not work more than 20 hours. As the bar plot showing, majority of the students who working less than 10 hours are like to play the video game somewhat, and the “Not really” and the “very much” choices are chosen by about the same amount. As a conclusion for the student working less than 10 hours, these students are likely to play video games but there is still a big amount of them does not like to play. Most of the students whose working hour is between 10 and 20 hours are likely to play the video games, because most of them choose “very much” or “somewhat”, and the portion of “never played”, “not really” and “not at all” is very small. However, those students who work more than 20 hours are also likely to play video as the bar plot showing, and interestingly, most of these busy students like to play video games very much.


Using the follow up survey in the notes, most of the student (66%) playing video game for relaxation, and we can observe that students who are busy but still like to play video games very much may still have the reason that they treat playing games as a relaxation. Those students who work less than 10 hours a week may feel bored so that they are likely to play video, as the survey showing that 27% students take bored as a reason for playing video games. Besides, the popularity types of games may result in more male students than female students like to play video games, but we can’t determine which types of games are more popular among male students due to the limitation of the data.

2.6 Scenario 6

This part is done for fun and this is not reqired due to our backgroud according to what Professor said. We first make a table to see the percentage of each expected grade from the sample, and clearly it does not follow the distribution used in grade assignment of 20% A’s, 30%B’s,40% c’s and 10%D’s or lower. We decide to add more people that expects D grade to the sample, and the result will be discussed.

numA = sum(data$grade == 4 & !is.na(data$grade))
numB = sum(data$grade == 3 & !is.na(data$grade))
numC = sum(data$grade == 2 & !is.na(data$grade))
numD = sum(data$grade == 1 & !is.na(data$grade))
numNA = sum(is.na(data$grade))
Tgrade <- matrix(c(numA,numB,numC,numD,numA/91,numB/91,numC/91,numD/91),ncol = 4, byrow = TRUE)
colnames(Tgrade) <- c("Expected A","Expected B","Expected C","Expected D")
rownames(Tgrade) <- c("Counts","Percentage")
Tgrade <- as.table(Tgrade)
Tgrade

Clearly it does not follow the distribution used in grade assignment of 20% A’s, 30%B’s,40% c’s and 10%D’s or lower. We decide to add some data that people think they will get D to make the D to be about 10%. The number of new students should be 10 people. Here, We will add 10 persons, thus the total population will be 101.

Tgrade1 <- matrix(c(numA,numB,numC,numD+10,numA/101,numB/101,numC/101,(numD+10)/101),ncol = 4, byrow = TRUE)
colnames(Tgrade1) <- c("Expected A","Expected B","Expected C","Expected D")
rownames(Tgrade1) <- c("Counts","Percentage")
Tgrade1 <- as.table(Tgrade1)
Tgrade1

According to the result, after adding 10 more students who thinks their will get grade D, the percentage of expected grade A and of expected grade B are still higher than the 20% and 30%, which means that people are expecting a higher grade than they will get. As a conclusion, the nonrespondents are failing students who no longer bothered to come to the discussion section will not change the picture.


3.Conclusion

Given the UC Berkeley’s survey data, we explore the data features with the intention of providing useful information about students to the designers of the new computer lab. The data set is tested within six different scenarios. In the first scenario, we estimate the percentage of students that played video games prior the survey is in the interval from 0.2747253 to the 0.4505495 with our 95% confidence. In the second scenario, we list out a table about how long does student play prior the survey given that the information about the hours the spend on video games in other weeks. From that table, we conclude that the exam in the previous week do affect the time students spent on video games. In the third scenario, we estimate that the average amount of time spent playing video games in the week prior to the survey is in the interval from 0.6 hour to 1.78 hours with our 95% confidence. In the fourth scenario, to answer whether the students enjoy playing video games, we directly used the ‘like’ column of the data set. And, we can get 69 out 80 students answered ‘yes’, while the other 21 students answered ‘no’ when they are asked whether they enjoyed playing video games. Then, we made use of the follow-up surveys to look for important reasons for why the students like or dislike playing video games. In the fifth scenario, we explore the factor whether the sex, owning a PC and working hours will affect the students attitude to video games, and the owning a PC is the only factor among these three features that is not affect the students attitude towards the video games. In the last scenario, from the given data, we conclude that students are expecting higher grade when they handing the survey. ***

4.Appendices

proof

  1. To prove \[E[X_I(j)] = \mu\] Based on the definition of the expectation of a random variable, we can show that

given \(P(I(j)=i) = \frac{1}{N}\) \[E[X_I(j)] = \sum_{i=1}^{N}X_iP(I(j)=i) = \sum_{i=1}^{N}(X_i\frac{1}{N})= \frac{1}{N}\sum_{i=1}^{N}X_i = \mu\]

The expected value of a random sample is equal to the mean of the population.

  1. To prove \[E[\bar{x}] = \mu\] We can show that \[E[\bar{x}] = E[\frac{1}{n}\sum_{j=1}^{n}X_I(j)] = \frac{1}{n}\sum_{j=1}^{n}E[X_I(j)]=\frac{1}{n}\sum_{j=1}^{n}\mu = \mu\]

  2. To prove \[Var(X_J(j)) = \sigma^2\] Based on the definition of variance, we can show that \[Var(X_J(j)) = E[(X_I(j) - E[X_I(j)])^2]=E[(X_I(j) - \mu)^2] = \sum_{i=1}^{N}(X_I(j) - \mu)^2P(I(j)=i) = \frac{1}{N}\sum_{i=1}^{N}(X_I(j) - \mu)^2 = \sigma^2\]

  3. To find \(Var(\bar{x})\)

Note that \(X_I(j)\) and \(X_I(k)\) are not independent, we can show that \[Var(\bar{x}) = Var(\frac{1}{n}\sum_{j=1}^{n}X_I(j)) =\frac{1}{n^2}Var(\sum_{j=1}^{n}X_I(j)) =\frac{1}{n^2}\sum_{j=1}^{n}Var(X_I(j))+\frac{1}{n^2}\sum_{j \neq k}^{n}Cov(X_I(j),X_I(k)) = \frac{1}{n}\sigma^2 + \frac{n-1}{n}Cov(X_I(1),X_I(2))\]

Now we need to find \(Cov(X_I(1),X_I(2))\) \[Cov(X_I(1),X_I(2)) = E[(X_I(1)-E[X_I(1)])(X_I(2)-E[X_I(2)]) = E[(X_I(1)-\mu)(X_I(2)-\mu)] =E[X_I(1)X_I(2)]-\mu E[X_I(1)]-\mu E[X_I(2)]+\mu^2 = -\frac{\sigma^2}{N-1}\]

LS0tDQp0aXRsZTogIk1BVEggMjg5QyBIVzIiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KKioqDQoNCiMjIyBHcm91cCBtZW1iZXJzKDMpDQpHdWFubmFuIFNoaSBQSUQ6QTk4MDUxODI3ICAxc3QgWWVhciBHcmFkdWF0ZSBFbGVjdHJpY2FsIEVuZ2luZWVyaW5nPGJyIC8+DQpIYW8gSmlhbmcgUElEOkE5MTQyNjc5NyAgMXN0IFllYXIgR3JhZHVhdGUgRWxlY3RyaWNhbCBFbmdpbmVlcmluZzxiciAvPg0KV2VuaGFvIFNoZW5nIFBJRDpBOTkwMzM4NzYgICAxc3QgWWVhciBHcmFkdWF0ZSBFbGVjdHJpY2FsIEVuZ2luZWVyaW5nPGJyIC8+DQoNCioqKg0KDQojIzEuSW50cm9kdWN0aW9uDQoqICMjIyNTdW1tYXJ5IG9mIHRoZSBzdHVkeSBhbmQgZGF0YTxiciAvPg0KVGhlIHN1cnZleSBjb25kdWN0ZWQgYnkgVUMgQmVya2VsZXkgZHVyaW5nIGEgc3RhdGlzdGljcyBjbGFzcyBhaW1zIHRvIGRldGVybWluZSB0aGUgZXh0ZW50IHRvIHdoaWNoIHRoZSBzdHVkZW50cyBwbGF5IHZpZGVvIGdhbWVzIGFuZCB3aGljaCBhc3BlY3RzIG9mIHZpZGVvIGdhbWVzIHRoZXkgZmluZCBtb3N0IGFuZCBsZWFzdCBmdW4uICBUaGV5IGRldmVsb3BlZCBxdWVzdGlvbm5haXJlLCBhbmQgcmFuZG9tbHkgc2VsZWN0ZWQgOTUgb3V0IG9mIDMxNCBzdHVkZW50cyB3aG8gd2VyZSBlbnJvbGxlZCBpbiB0aGF0IGNvdXJzZSB0byBwYXJ0aWNpcGF0ZSBpbiB0aGUgc3VydmV5LiAgQ29tcGxldGUgc3VydmV5cyB3ZXJlIG9idGFpbmVkIGZyb20gOTEgb3V0IG9mIDk1IHN0dWRlbnRzLiAgVGhlIGRhdGEgaXMgcHJvdmlkZWQgaW4gdGhlIKGudmlkZW9kYXRhLnR4dKGvIGZpbGUuICBUaGUgYW5zd2VycyB0byBxdWVzdGlvbnMgaW4gdGhlIHF1ZXN0aW9ubmFpcmUgd2VyZSBjb2RlZCBudW1lcmljYWxseSBhcyBkZXNjcmliZWQgaGVyZTogDQo8YnI+PGJyPg0KIVtdKEM6L1VzZXJzL3dlc2hlL0Rlc2t0b3AvTWF0aCAyODlDL0hXcy9IVzIvQ29udGVudF9vZl90aGVfZGF0YS5qcGcpDQo8YnI+PGJyPg0KDQogKiAjIyMjUXVlc3Rpb25zIHRvIGJlIGFuc3dlcmVkIGJ5IG91ciBkYXRhIGFuYWx5c2lzPGJyIC8+DQogICAxLlByb3ZpZGUgYW4gZXN0aW1hdGUgZm9yIHRoZSBmcmFjdGlvbiBvZiBzdHVkZW50cyB3aG8gcGxheWVkIGEgdmlkZW8gZ2FtZSBpbiB0aGUgd2VlayBwcmlvciB0byB0aGUgc3VydmV5LiAgQWxzbyBwcm92aWRlIGFuIGludGVybmFsIGVzdGltYXRlLjxicj4NCiAgIDIuQ2hlY2sgd2hldGhlciB0aGUgZmFjdCB0aGF0IHRoZXJlIHdhcyBhbiBleGFtIGluIHRoZSB3ZWVrIHByaW9yIHRvIHRoZSBzdXJ2ZXkgYWZmZWN0IG91ciBwcmV2aW91cyBlc3RpbWF0ZXMgYnkgY29tcGFyaW5nIHRoZSByZXBvcnRlZCBmcmVxdWVuY3kgb2YgcGxheSB3aXRoIHRoZSBhbW91bnQgb2YgdGltZSBzcGVudCBwbGF5aW5nIHZpZGVvIGdhbWVzIGluIHRoZSB3ZWVrIHByaW9yIHRvIHRoZSBzdXJ2ZXkuPGJyPg0KICAzLlByb3ZpZGUgYW4gaW50ZXJ2YWwgZXN0aW1hdGUgZm9yIHRoZSBhdmVyYWdlIGFtb3VudCBvZiB0aW1lIHNwZW50IHBsYXlpbmcgdmlkZW8gZ2FtZXMgaW4gdGhlIHdlZWsgcHJpb3IgdG8gdGhlIHN1cnZleS48YnI+DQogIDQuRG8gc3R1ZGVudHMgZW5qb3kgcGxheWluZyB2aWRlbyBnYW1lcyBpbiBnZW5lcmFsPyAgV2hhdCBhcmUgdGhlIG1vc3QgaW1wb3J0YW50IHJlYXNvbnMgd2h5IHRoZXkgbGlrZS9kaXNsaWtlIHZpZGVvIGdhbWVzPzxicj4NCiAgNS5FeHBsb3JlIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRob3NlIHdobyBsaWtlIHRvIHBsYXkgdmlkZW8gZ2FtZXMgYW5kIHRob3NlIHdobyBkb26hr3QuICBUbyBkbyB0aGlzLCBtYWtlIGNvbXBhcmlzb25zIGJldHdlZW4gbWFsZSBhbmQgZmVtYWxlIHN0dWRlbnRzLCB0aG9zZSB3aG8gd29yayBmb3IgcGF5IGFuZCB0aG9zZSB3aG8gZG9uoa90LCB0aG9zZSB3aG8gb3duIGEgY29tcHV0ZXIgYW5kIHRob3NlIHdobyBkb26hr3QuPGJyPg0KPGJyPjxicj4NCg0KKiAjIyMjT3V0bGluZSBvZiB0aGUgcmVtYWluZGVyIG9mIHBhcGVyPGJyPg0KVGhlIGZvbGxvd2luZyBwb3J0aW9uIG9mIHRoZSByZXBvcnQgZGVhbHMgd2l0aCBlYWNoIHF1ZXN0aW9uIHByZXNlbnRlZCBhYm92ZS4gIFdlIHdpbGwgaW5jbHVkZSBkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiB0aGUgZGF0YSBhbmFseXNpcyBtZXRob2RzIHRoYXQgd2UgdXNlLCBhbmQgdGhlIG91ciBhbnN3ZXIgdG8gdGhlIHF1ZXN0aW9ucy4NCg0KKioqDQpgYGB7cn0NCiNzZXQgd2QNCnNldHdkKCJDOi9Vc2Vycy93ZXNoZS9EZXNrdG9wL01hdGggMjg5Qy9IV3MvSFcyIikNCmRhdGEgPC0gcmVhZC50YWJsZSgidmlkZW9kYXRhLnR4dCIsaGVhZGVyPVRSVUUpDQpgYGANCg0KYGBge3J9DQojaW5zdGFsbCBwYWNrYWdlDQppbnN0YWxsLnBhY2thZ2VzKCJtb21lbnRzIikNCmluc3RhbGwucGFja2FnZXMoInRyZWUiKQ0KaW5zdGFsbC5wYWNrYWdlcygicmFuZG9tRm9yZXN0IikNCmBgYA0KDQpgYGB7cn0NCiNpbnB1dCBsaWJyYXJ5DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KG1vbWVudHMpDQpsaWJyYXJ5KHRyZWUpDQpsaWJyYXJ5KHBhcnR5KQ0KbGlicmFyeShyYW5kb21Gb3Jlc3QpDQpgYGANCg0KIyMyLkFuYWx5c2lzDQojIyMjMi4xIFNjZW5hcmlvIDENCldlIGJlZ2luIGJ5IHByb3ZpZGluZyBhbiBlc3RpbWF0ZSBmb3IgdGhlIGZyYWN0aW9uIG9mIHN0dWRlbnRzIHdobyBwbGF5ZWQgYSB2aWRlbyBnYW1lIGluIHRoZSB3ZWVrIHByaW9yIHRvIHRoZSBzdXJ2ZXkuICBGaXJzdCBvZiBhbGwsIHdlIGNsZWFuZWQgdXAgdGhlIGRhdGEgYnkgZXhjbHVkaW5nIGFuc3dlcnMgd2hpY2ggYXJlIGVuY29kZWQgYXMgOTkgYmVjYXVzZSB0aG9zZSBhcmUgY29uc2lkZXJlZCBpbnZhbGlkIG9yIGltcHJvcGVyIGFuc3dlcnMuICBUaGVuLCB3ZSBvbmx5IG5lZWQgdG8gY29uc2lkZXIgdGhlICJ0aW1lIiIgY29sdW1uIG9mIHRoZSBkYXRhLiAgQmFzZWQgb24gdGhlIGZpZ3VyZSBhYm92ZSwgd2UgY2FuIGZpbHRlciBvdXQgdGhlIHN0dWRlbnRzIHdobyBwbGF5ZWQgdmlkZW8gZ2FtZXMgYSB3ZWVrIHByaW9yIHRvIHRoZSBleGFtIGJ5IHBpY2tpbmcgdGhlIG5vbnplcm8gZGF0YSBwb2ludHMgaW4gdGhlICJ0aW1lIiBjb2x1bW4gb2YgdGhlIGRhdGEuICBUaGUgcG9pbnQgZXN0aW1hdGUgaXMgdGhlIHJhdGlvIG9mIHRoZSBudW1iZXIgb2Ygc3R1ZGVudHMgd2hvIHBsYXllZCBvdmVyIHRoZSBudW1iZXIgb2Ygc3R1ZGVudHMgd2hvIHByb3ZpZGVkIGEgdmFsaWQgYW5zd2VyLiA8YnI+PGJyPg0KDQpXZSBjb252ZXJ0IGluZm9ybWF0aW9uIGNvbnRhaW5lZCBpbiB0aGUgInRpbWUiIiBjb2x1bW4gb2YgdGhlIG9yaWdpbmFsIGRhdGEgdG8gYSAiVFJVRS9GQUxTRSIiIGluZGljYXRvciBjb2x1bW4gdmVjdG9yLCBuYW1lZCChrmRhdGEucGxheaGuLiAgVGhlIHByb2NlZHVyZSBvZiB0aGlzIGNvbnZlcnNpb24gaXMgc2ltcGxlLiAgV2UgY2hlY2sgd2hldGhlciBhbiBlbnRyeSBpbiB0aGUgoa50aW1loa8gY29sdW1uIGlzIGxhcmdlciB0aGFuIDAuICBJZiBpdCBpcywgd2UgcHV0IGEgKioxKiogaW4gdGhlIGNvcnJlc3BvbmRpbmcgbG9jYXRpb24gaW4goa5kYXRhLnBsYXmhrywgb3RoZXJ3aXNlLCB3ZSBwdXQgYSAqKjAqKiB0aGVyZS4gIFRoZXJlZm9yZSwgoa5kYXRhLnBsYXmhryBjYW4gYmUgdXNlZCBhcyBhbiBpbmRpY2F0b3IgdG8gd2hldGhlciB0aGUgc3R1ZGVudHMgcGxheWVkIHZpZGVvIGdhbWVzIGluIHRoZSB3ZWVrIHByaW9yIHRvIHRoZSBzdXJ2ZXkuICBOb3csIHdlIG1ha2UgdGhlIG1lYW4gb2YgdGhlIGVudHJpZXMgaW4gdGhlIGluZGljYXRvciB2ZWN0b3IgZXF1YWwgdG8gdGhlIHBvaW50IGVzdGltYXRlLg0KDQpgYGB7cn0NCmRhdGFbZGF0YSA9PSA5OV0gPC0gTkENCmRhdGEucGxheSA8LSBkYXRhJHRpbWU+MA0KcGxheSA8LSBzdW0oZGF0YS5wbGF5LCBuYS5ybT1UUlVFKQ0KcG9pbnQuZXN0aW1hdGUgPC0gcGxheS9sZW5ndGgoZGF0YSR0aW1lKQ0KcG9pbnQuZXN0aW1hdGUNCmBgYA0KPGJyPjxicj4NCk91ciBwb2ludCBlc3RpbWF0ZSBmb3IgdGhlIGZyYWN0aW9uIG9mIHN0dWRlbnRzIHdobyBwbGF5ZWQgYSB2aWRlbyBnYW1lIGEgd2VlayBwcmlvciB0byB0aGUgZXhhbSBpcyBhYm91dCAqKjM3JSoqLg0KPGJyPjxicj4NCg0KVG8gcHJvdmlkZSBhbiBpbnRlcnZhbCBlc3RpbWF0ZSBvZiB0aGlzIGVzdGltYXRvciwgc2luY2UgbiBpcyBsYXJnZSBidXQgbi9OID0gOTEvMzE0IGlzIG5vdCBzbWFsbCwgd2UgbmVlZCB0byB1c2UgYm9vdHN0cmFwIHRvIGNoZWNrIGlmIHdlIGNhbiB1c2Ugbm9ybWFsIGFwcHJveGltYXRpb24uICBUaHJvdWdoIGJvb3RzdHJhcHBpbmcsIHdlIGFyZSBhYmxlIHRvIGNvbGxlY3QgbW9yZSBzYW1wbGVzIGZyb20gdGhlIHBvcHVsYXRpb24uICBUaGVyZWZvcmUgd2UgY2FuIGdldCBhIHJhbmdlIG9mIHBvc3NpYmxlIHZhbHVlcyB0aGF0IHRoZSBlc3RpbWF0ZSBjb3VsZCBwb3RlbnRpYWxseSBmYWxsIGludG8gaWYgd2UgaW5jcmVhc2UgdGhlIG51bWJlciBvZiBkYXRhLiAgR2l2ZW4gdGhhdCB0aGUgZGF0YSBpcyBkcmF3biBmcm9tIGEgcG9wdWxhdGlvbiB3aXRoIHNpemUgb2YgJE4gPSAzMTQkLCB3ZSBmaXJzdCBjcmVhdGUgYSBCb290c3RyYXAgcG9wdWxhdGlvbiBvZiB0aGlzIHNpemUgYnkgcmVwZWF0aW5nIGV2ZXJ5IHNhbXBsZSBmb3IgJDMxNC85MSA9IDMuNDUkIHRpbWVzLiAgVGhlbiB3ZSByYW5kb21seSBkcmF3ICRuID0gOTEkIHNhbXBsZXMgZnJvbSB0aGUgQm9vdHN0cmFwIHBvcHVsYXRpb24uICBBbmQgd2Ugc3RvcmUgZWFjaCBCb290c3RyYXAgc2FtcGxlLiAgSW4gdGhpcyBwcm9ibGVtLCB3ZSBoYXZlIGEgdG90YWwgb2YgNDAwMCBCb290c3RyYXAgc2FtcGxlcy4gIEZvciBlYWNoIEJvb3RzdHJhcCBzYW1wbGUsIHdlIGNhbGN1bGF0ZSBpdHMgbWVhbi4gIFRoZW4sIHdlIHBsb3QgdGhlIGhpc3RvZ3JhbSBvZiB0aGVzZSBCb290c3RyYXAgc2FtcGxlIG1lYW5zLiAgPGJyPjxicj4NClRvIGNoZWNrIGZvciBub3JtYWxpdHksIHdlIHVzZWQgdGhyZWUgbWV0aG9kczogdGhlIFEtUSBwbG90LCBza2V3bmVzcyBhbmQgS3VydG9zaXMgdGVzdC48YnI+PGJyPg0KYGBge3J9DQpib290LnRpbWUgPC0gcmVwKGRhdGEucGxheSwgbGVuZ3RoLm91dCA9IDMxNCkNCnNldC5zZWVkKDE4OTI4OSkNCkIgPSA0MDAwICMgdGhlIG51bWJlciBvZiBib290c3RyYXAgc2FtcGxlcyB3ZSB3YW50DQpib290LnNhbXBsZSA8LSBhcnJheShkaW0gPSBjKEIsIDkxKSkNCmZvciAoaSBpbiAxOkIpIHsNCiAgYm9vdC5zYW1wbGVbaSwgXSA8LSBzYW1wbGUoYm9vdC50aW1lLCBzaXplID0gOTEsIHJlcGxhY2UgPSBGQUxTRSkNCn0NCmJvb3QubWVhbiA9IGFwcGx5KFggPSBib290LnNhbXBsZSwgTUFSR0lOID0gMSwgRlVOID0gbWVhbikNCmhpc3QoYm9vdC5tZWFuLCAgYnJlYWtzID0gMjAsIHByb2JhYmlsaXR5ID0gVFJVRSwgZGVuc2l0eSA9IDIwLCBjb2wgPSAzLCBib3JkZXIgPSAzLCBtYWluID0gIkhpc3RvZ3JhbSBvZiB0aGUgcGVyY2VudGFnZSIsIHhsYWIgPSAicGVyY2VudGFnZSIpDQpsaW5lcyhkZW5zaXR5KGJvb3QubWVhbiwgYWRqdXN0ID0gMiksIGNvbCA9IDIpDQojY2hlY2sgbm9ybWFsaXR5IGJ5IFEtUSBwbG90IA0KcGFyKHB0eSA9ICdzJykNCnFxbm9ybShib290Lm1lYW4pDQpxcWxpbmUoYm9vdC5tZWFuKQ0KI2NvbXBhcmUgdGhlIGt1cnRvc2lzIGFuZCBza2V3bmVzcy4gIFdlIGluc3RhbGxlZCB0aGUgJ21vbWVudHMnIHBhY2thZ2UNCnNrZXduZXNzKGJvb3QubWVhbikNCmt1cnRvc2lzKGJvb3QubWVhbikNCmBgYA0KV2UgZ2V0IGEgc2tld25lc3Mgb2YgMC4wMDk4Mjk1NzgsIHdoaWNoIGlzIGNsb3NlIHRvIDAsIGFuZCBhIEt1cnRvc2lzIG9mIDIuOTU4MTY1LCB3aGljaCBpcyBzbWFsbGVyIHRoYW4gMy4gIEFsc28sIHRoZSBRLVEgcGxvdCBpcyBxdWl0ZSBjbG9zZSB0byB0aGUgc3RhbmRhcmQgbGluZSwgd2UgYXJlIGFibGUgdG8gY29uY2x1ZGUgdGhhdCB0aGUgQm9vdHN0cmFwIHNhbXBsZXMgZGlzdHJpYnV0aW9uIGlzIGNsb3NlIHRvIGJlIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi48YnI+PGJyPiANCg0KYGBge3J9DQojY29uc3RydWN0IHRoZSA5NSUgaW50ZXJ2YWwgZXN0aW1hdGUgdXNpbmcgYm9vc3RyYXAgbWVhbnMNCmludC5ib290IDwtIGMocXVhbnRpbGUoYm9vdC5tZWFuLCAwLjAyNSksIHF1YW50aWxlKGJvb3QubWVhbiwgMC45NzUpKQ0KaW50LmJvb3QNCmBgYA0KQXMgYSByZXN1bHQgb2Ygbm9ybWFsaXR5LCB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgb2J0YWluZWQgdXNpbmcgcXVhbnRpbGUgYW5hbHlzaXMgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGFzIHNob3duIGFib3ZlLiAgQSBkZXRhaWxlZCBwcm9vZiBhYm91dCBzYW1wbGUgbWVhbiBhbmQgc3RhbmRhcmQgZXJyb3IgcmVxdWlyZWQgYnkgdGhlIHByb2Zlc3NvciBpcyBpbiB0aGUgYXBwZW5kaWNlcy48YnI+PGJyPg0KDQojIyMjMi4yIFNjZW5hcmlvIDINCg0KSW4gdGhlIHNlY29uZCBzY2VuYXJpbywgd2UgYW5hbHl6ZSBob3cgdGhlIGFtb3VudCBvZiB0aW1lIHNwZW50IHBsYXlpbmcgdmlkZW8gZ2FtZXMgaW4gdGhlIHdlZWsgcHJpb3IgdG8gdGhlIHN1cnZleSBjb21wYXJlcyB0byB0aGUgcmVwb3J0ZWQgZnJlcXVlbmN5IG9mIHBsYXkuIEJ5IGNvbXBhcmluZyB0aGUgYWN1dGFsIGFtb3VudCBvZiB0aW1lIHN0dWRlbnRzIHBsYXllZCB0byB0aGUgcmVwb3J0ZWQgZnJlcXVlbmN5LCB3ZSBhcmUgYWJsZSB0byBkZXRlcm1pbmUgaG93IHRoZSBmYWN0IHRoYXQgdGhlcmUgd2FzIGFuIGV4YW0gcHJpb3IgdG8gdGhlIHN1cnZleSBhZmZlY3QgdGhlIGFtb3VudCBvZiB0aW1lIHN0dWRlbnRzIHNwZW50IG9uIHZpZGVvIGdhbWVzLjxicj48YnI+DQpUbyBkcmF3IHRoZSBjb21wYXJpc29uLCB3ZSBmaXJzdCBzZXBhcmF0ZSBhbGwgdGhlIHN0dWRlbnRzIGludG8gNCBjYXRlZ29yaWVzIGJhc2VkIG9uIHRoZWlyIHJlcG9ydGVkIGZyZXF1ZW5jeSBvZiBwbGF5LiBUaGVuIHdlIGNhbGN1bGF0ZSB0aGUgbnVtYmVyIG9mIHN0dWRlbnRzIHdobyBhY3R1YWxseSBwbGF5ZWQgdmlkZW8gZ2FtZXMgaW4gdGhlIHdlZWsgcHJpb3IgdG8gdGhlIGV4YW0uPGJyPjxicj4NCmBgYHtyfQ0KI051bWVyaWNhbCBNZXRob2QjDQojRGFpbHkgcGxheWVyIHdobyBhY3R1YWxseSBwbGF5ZWQgdGhlIHdlZWsgcHJpb3IgdG8gZXhhbQ0KaW5kZXguZGFpbHkgPC0gd2hpY2goZGF0YSRmcmVxICVpbiUgYygxKSkNCmEuMSA8LSBsZW5ndGgoaW5kZXguZGFpbHkpDQphLjIgPC0gc3VtKGRhdGEkdGltZVtpbmRleC5kYWlseV0+MCkNCiNXZWVrbHkgcGxheWVyIHdobyBhY3R1YWxseSBwbGF5ZWQgdGhlIHdlZWsgcHJpb3IgdG8gZXhhbQ0KaW5kZXgud2Vla2x5IDwtIHdoaWNoKGRhdGEkZnJlcSAlaW4lIGMoMikpDQpiLjEgPC0gbGVuZ3RoKGluZGV4LndlZWtseSkNCmIuMiA8LSBzdW0oZGF0YSR0aW1lW2luZGV4LndlZWtseV0+MCkNCiNNb250aGx5IHBsYXllciB3aG8gYWN0dWFsbHkgcGxheWVkIHRoZSB3ZWVrIHByaW9yIHRvIGV4YW0NCmluZGV4Lm1vbnRobHkgPC0gd2hpY2goZGF0YSRmcmVxICVpbiUgYygzKSkNCmMuMSA8LSBsZW5ndGgoaW5kZXgubW9udGhseSkNCmMuMiA8LSBzdW0oZGF0YSR0aW1lW2luZGV4Lm1vbnRobHldPjApDQojU2VtZXN0ZXJseSBwbGF5ZXIgd2hvIGFjdHVhbGx5IHBsYXllZCB0aGUgd2VlayBwcmlvciB0byBleGFtDQppbmRleC5zZW1lc3Rlcmx5IDwtIHdoaWNoKGRhdGEkZnJlcSAlaW4lIGMoNCkpDQpkLjEgPC0gbGVuZ3RoKGluZGV4LnNlbWVzdGVybHkpDQpkLjIgPC0gc3VtKGRhdGEkdGltZVtpbmRleC5zZW1lc3Rlcmx5XT4wKQ0Kc2VuZXJpby4yIDwtIG1hdHJpeChjKGEuMSxhLjIsYi4xLGIuMixjLjEsYy4yLGQuMSxkLjIpLCBuY29sPTIsYnlyb3c9VFJVRSkNCmNvbG5hbWVzKHNlbmVyaW8uMikgPC0gYygiIyBvZiBwZW9wbGUgcGxheSBnYW1lcyIsIiMgb2YgcGVvcGxlIHBsYXllZCBsYXN0IHdlZWsiKQ0Kcm93bmFtZXMoc2VuZXJpby4yKSA8LSBjKCJEYWlseSIsIldlZWtseSIsIk1vbnRobHkiLCJTZW1lc3Rlcmx5IikNCnNlbmVyaW8uMiA8LSBhcy50YWJsZShzZW5lcmlvLjIpDQpzZW5lcmlvLjINCmBgYA0KRnJvbSB0aGUgYWJvdmUgdGFibGUsIGl0IHNob3dzIHRoYXQgOSBzdHVkZW50cyByZXBvcnRlZCB0aGF0IHRoZXkgcGxheSBnYW1lcyBkYWlseSBhbmQgNyBvZiB0aGVtIHBsYXllZCBsYXN0IHdlZWs7IDI4IHN0dWRlbnRzIHJlcG9ydGVkIHRoYXQgdGhleSBwbGF5IHdlZWtseSBhbmQgMjQgb2YgdGhlbSBwbGF5ZWQgbGFzdCB3ZWVrOyAxOCBzdHVkZW50cyBwbGF5IGdhbWVzIG1vbnRobHkgYnV0IG9ubHkgMiBvZiB0aGVtIHBsYXllZCBsYXN0IHdlZWs7IDIzIHN0dWRlbnRzIHBsYXkgZ2FtZXMgc2VtZXN0ZXJseSBidXQgb25seSAxIG9mIHRoZW0gcGxheWVkIGxhc3Qgd2Vlay4gVGhlcmVmb3JlLCB3ZSBjYW4gY29uY2x1ZGUgdGhhdCBoYXZpbmcgYW4gaW5jb21pbmcgZXhhbSBncmVhdGx5IHJlZHVjZSB0aGUgYW1vdW50IG9mIHRpbWUgc3BlbnQgb24gdmlkZW8gZ2FtZXMgZm9yIHRob3NlIHN0dWRlbnRzIHdobyBwbGF5IGdhbWVzIG1vbnRobHkgYW5kIHNlbWVzdGVybHkuIEhvd2V2ZXIsIHN0dWRlbnRzIHdobyBwbGF5IGdhbWVzIGRhaWx5IGFuZCB3ZWVrbHkgYXJlIG1vcmUgbGlrZWx5IHRvIGNvbnRpbnVlIHBsYXlpbmcgdmlkZW8gZ2FtZXMsIHdoZXRoZXIgb3Igbm90IHRoZXkgaGF2ZSBleGFtIGluIHRoZSBmb2xsb3dpbmcgd2Vlay4NCjxicj48YnI+DQoNCiMjIyMyLjMgU2NlbmFyaW8gMw0KSW4gdGhlIHRoaXJkIHNjZW5hcmlvLCB3ZSBwcm92aWRlIGFuIGludGVydmFsIGVzdGltYXRlIGZvciBhdmVyYWdlIGFtb3VudCBvZiB0aW1lIHNwZW50IG9uIHBsYXlpbmcgdmlkZW8gZ2FtZXMgaW4gdGhlIHdlZWsgcHJpb3IgdG8gdGhlIHN1cnZleS4gSW4gb3JkZXIgdG8gYWNjb21wbGlzaCB0aGlzLCB3ZSBmaXJzdCB1c2UgdGhlIGJvb3RzdHJhcCBzaW11bGF0aW9uIHRlY2huaXF1ZSB0byByYW5kb21seSBzZWxlY3QgNDAwMCBzYW1wbGVzIG9mIHNpemUgOTEgZnJvbSBhIHBvcHVsYXRpb24gb2Ygc2l6ZSAzMTQuDQoNCmBgYHtyfQ0KIyNtYWtlIGFuIGludGVydmFsIGVzdGltYXRlIGZvciB0aGUgYXZlcmFnZSBhbW91bnQgb2YgdGltZSBzcGVudCBwbGF5aW5nIHZpZGVvIGdhbWVzIGluIHRoZSB3ZWVrIHByaW9yIHRvIHN1cnZleSAjIw0KYm9vdC5wb3B1bGF0aW9uIDwtIHJlcChkYXRhJHRpbWUsIGxlbmd0aC5vdXQgPSAzMTQpDQpzZXQuc2VlZCgxODkyODkpDQpib290LnRpbWVfc2FtcGxlIDwtIGFycmF5KGRpbT1jKDQwMDAsOTEpKQ0KZm9yIChpIGluIDE6NDAwMCkNCnsNCiAgYm9vdC50aW1lX3NhbXBsZVtpLF0gPC0gc2FtcGxlKGJvb3QucG9wdWxhdGlvbiwgc2l6ZSA9IDkxLCByZXBsYWNlID0gRkFMU0UpDQp9DQpgYGANCg0KVGhlbiB3ZSBwcm9jZWVkIHRvIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiBlYWNoIHNhbXBsZSBhbmQgcGxvdCB0aGVtIGluIGEgaGlzdG9ncmFtLg0KDQpgYGB7cn0NCmJvb3QudGltZV9tZWFuIDwtIGFwcGx5KFggPSBib290LnRpbWVfc2FtcGxlLCBNQVJHSU4gPSAxLCAgRlVOID0gbWVhbikNCmhpc3QoYm9vdC50aW1lX21lYW4sIGJyZWFrcyA9IDIwLCBwcm9iYWJpbGl0eSA9IFRSVUUsIGRlbnNpdHkgPSAyMCwgY29sID0gMywgYm9yZGVyID0gMywgeGxhYiA9ICd0aW1lIHNwZW50IG9uIHZpZGVvIGdhbWVzJywgeWxhYiA9ICdjb3VudCcsIG1haW4gPSAnSGlzdG9ncmFtIG9mIHRpbWUgc3BlbnQgb24gdmlkZW8gZ2FtZXMnKQ0KbGluZXMoZGVuc2l0eShib290LnRpbWVfbWVhbiwgYWRqdXN0ID0gMiksIGNvbCA9IDIpDQpgYGANClRvIHByb3ZpZGUgYW4gaW50ZXJ2YWwgZXN0aW1hdGlvbiBmb3IgdGhlIGF2ZXJhZ2UgdGltZSwgd2UgZmlyc3QgcGxvdCB0aGUgUS1RIHBsb3QgYW5kIHBlcmZvcm0gdGhlIFNoYXBpcm8tV2lsayB0ZXN0IHRvIGRldGVybWluZSBvZiB0aGUgYXZlcmFnZSB0aW1lIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLg0KDQpgYGB7cn0NCiNjaGVjayBub3JtYWxpdHkgYnkgUS1RIHBsb3QgDQpwYXIocHR5ID0gJ3MnKQ0KcXFub3JtKGJvb3QudGltZV9tZWFuKQ0KcXFsaW5lKGJvb3QudGltZV9tZWFuKQ0Kc2tld25lc3MoYm9vdC50aW1lX21lYW4pDQprdXJ0b3Npcyhib290LnRpbWVfbWVhbikNCmBgYA0KDQpXZSBnZXQgYSBza2V3bmVzcyBvZiAwLjM2ODIgYW5kIGEgS3VydG9zaXMgb2YgMi44MjQzLCB3aGljaCBpcyBzbWFsbGVyIHRoYW4gMy4gIEFsc28sIHRoZSBRLVEgcGxvdCBpcyBxdWl0ZSBjbG9zZSB0byB0aGUgc3RhbmRhcmQgbGluZSwgd2UgYXJlIGFibGUgdG8gY29uY2x1ZGUgdGhhdCB0aGUgQm9vdHN0cmFwIHNhbXBsZXMgZGlzdHJpYnV0aW9uIGlzIGNsb3NlIHRvIGJlIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi48YnI+PGJyPiANCg0KYGBge3J9DQojY29uc3RydWN0IHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcm52YWwNCmludC5ib290IDwtIGMocXVhbnRpbGUoYm9vdC50aW1lX21lYW4sIDAuMDI1KSwgcXVhbnRpbGUoYm9vdC50aW1lX21lYW4sIDAuOTc1KSkNCmludC5ib290DQpgYGANCkFzIGEgcmVzdWx0IG9mIG5vcm1hbGl0eSwgdGhlIDk1JSBjb25maWRlbmNlIGludGVydmFsIGlzIG9idGFpbmVkIHVzaW5nIHF1YW50aWxlIGFuYWx5c2lzIG9mIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhcyBzaG93biBhYm92ZS48YnI+PGJyPg0KDQoNCiMjIyMyLjQgU2NlbmFyaW8gNA0KSW4gdGhpcyBzY2VuYXJpbywgV2UgYW5hbHl6ZSB0aGUgImxpa2UiIGNvbHVtbiBpbiB0aGUgZGF0YXNldCB0byBkZXRlcm1pbmUgd2hldGhlciBvciBub3Qgc3R1ZGVudHMgZW5qb3kgcGxheWluZyB2aWRlbyBnYW1lcy4gTm90aWNpbmcgdGhlIGZhY3QgdGhhdCwgbm90IGFsbCBzdHVkZW50cyBhbnN3ZXJlZCB0aGlzIHF1ZXN0aW9uLCB3ZSBuZWVkIHRvIGdldCByaWQgb2Ygc29tZSBvZiB0aGUgZGF0YS4gIEFmdGVyIGRhdGEtY2xlYW5pbmcsIHdlIGNvdW50ZWQgZm9yIGhvdyBtYW55IHN0dWRlbnRzIGFuc3dlcmVkIHBvc2l0aXZlbHkgKGUuZy4gdmVyeSBtdWNoIGFuZCBzb21ld2hhdCkgdG8gdGhpcyBxdWVzdGlvbiBhbmQgaG93IG1hbnkgb2YgdGhlbSBhbnN3ZXJlZCBuZWdhdGl2ZWx5IChlLmcuIG5ldmVyIHBsYXllZCwgbm90IHJlYWxseSwgYW5kIG5vdCBhdCBhbGwpLiAgPGJyPjxicj4NCg0KYGBge3J9DQojZG8geW91IHRoaW5rIHRoZSBzdHVkZW50cyBlbmpveSBwbGF5aW5nIHZpZGVvIGdhbWVzPw0KbGlrZWluZGV4IDwtIHdoaWNoKCFpcy5uYShkYXRhJGxpa2UpKQ0KZGF0YS5saWtlIDwtIGRhdGFbbGlrZWluZGV4LF0NCmRhdGEubGlrZVsnbGlrZV8wMSddIDwtIHJlcChOQSxkaW0oZGF0YS5saWtlKVsxXSkgIyBjcmVhdGUgOTFYMSBtYXRyaXgsIE5BIGZvciBhbGwgZWxlbWVudHMNCmZvciAoIGkgaW4gMTpkaW0oZGF0YS5saWtlKVsxXSl7DQogIGxpa2UgPC0gZGF0YS5saWtlW2ksJ2xpa2UnXQ0KICBpZihsaWtlID09IDEgfHwgbGlrZSA9PSA0IHx8IGxpa2UgPT0gNSl7DQogICAgZGF0YS5saWtlW2ksJ2xpa2VfMDEnXSA8LSAwDQogIH1lbHNlew0KICAgIGRhdGEubGlrZVtpLCdsaWtlXzAxJ10gPC0gMQ0KICB9DQp9DQp0YWJsZShkYXRhLmxpa2UkbGlrZV8wMSkNCmBgYA0KDQpUaGUgcmVzdWx0IHNob3dpbmcgYWJvdmUgd2l0aCAqKjAqKiByZXByZXNlbnRpbmcgc3R1ZGVudHMgd2hvIGRvbqGvdCBlbmpveSBwbGF5aW5nIHZpZGVvIGdhbWVzIGFuZCAqKjEqKiBiZWluZyB0aGUgc3R1ZGVudHMgd2hvIGRvLiAgSXQgaXMgY2xlYXIgdGhhdCwgb3V0IG9mIDkwIHN0dWRlbnRzIHdobyBwcm92aWRlZCBhIHZhbGlkIGFuc3dlciB0byB0aGlzIHF1ZXN0aW9uLCBtb3JlIHRoYW4gNzUlIHNhaWQgdGhhdCB0aGV5IGFjdHVhbGx5IGVuam95IHBsYXlpbmcgdmlkZW8gZ2FtZXMuICANCjxicj48YnI+DQpJbiBsZWN0dXJlLCBwcm9mZXNzb3IgYWxzbyBwcmVzZW50ZWQgc29tZSBmb2xsb3ctdXAgc3VydmV5cyBpbiBhZGRpdGlvbiB0byB0aGUgZGF0YSBzZXQgd2UgaGF2ZS4gIEluIHRob3NlIGZvbGxvdyB1cCBzdXJ2ZXlzLCBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHdoeSBzdHVkZW50cyBsaWtlIG9yIGRpc2xpa2UgdG8gcGxheSB2aWRlbyBnYW1lcyBpcyB1bnZlaWxlZC4gIDxicj48YnI+DQohW10oQzovVXNlcnMvd2VzaGUvRGVza3RvcC9NYXRoIDI4OUMvSFdzL0hXMi9SZWFzb25fZm9yX1BsYXlpbmcuanBnKTxicj4NCkZvciBpbnN0YW5jZSwgdGhlIHRhYmxlIGFib3ZlIHNob3dzIHdoYXQgdGhlIHByaW1hcnkgcmVhc29ucyBhcmUgZm9yIHRob3NlIHdobyBlbmpveSBwbGF5aW5nIHZpZGVvIGdhbWVzLiAgVGhlcmVmb3JlLCBpZiBJoa9tIHRvIGdpdmUgYSBsaXN0IG9mIHRoZSByZWFzb25zIHdoeSB0aGUgc3R1ZGVudHMgbGlrZSBwbGF5aW5nIHZpZGVvIGdhbWVzLCBteSBsaXN0IHdvdWxkIGxvb2sgbGlrZTogPGJyPg0KMS5SZWxheGF0aW9uPGJyPg0KMi5GZWVsaW5nIG9mIG1hc3Rlcnk8YnI+DQozLkJvcmVkPGJyPg0KNC5HcmFwaGljcy9SZWFsaXNtPGJyPg0KNS5NZW50YWwgQ2hhbGxlbmdlPGJyPg0KPGJyPjxicj4NCiFbXShDOi9Vc2Vycy93ZXNoZS9EZXNrdG9wL01hdGggMjg5Qy9IV3MvSFcyL1JlYXNvbl9mb3JfRGlzbGlraW5nLmpwZyk8YnI+DQpTaW1pbGFybHksIGdpdmVuIHRoZSB0YWJsZSBhYm92ZSwgd2UgY291bGQgbGlzdCB0aGUgcmVhc29ucyB3aHkgdGhlIHN0dWRlbnRzIGRpc2xpa2UgcGxheWluZyB2aWRlbyBnYW1lczo8YnI+DQoxLlRvbyBtdWNoIHRpbWU8YnI+DQoyLkNvc3QgdG9vIG11Y2g8YnI+DQozLkl0IGlzIHBvaW50bGVzczxicj4NCjQuRnJ1c3RyYXRpbmc8YnI+DQo1LlRvbyBtYW55IHJ1bGVzPGJyPg0KPGJyPjxicj4NCg0KIyMjIzIuNSBTY2VuYXJpbyA1DQpUbyBhcHByYW9jaCB0aGlzIHNjZW5hcmlvLCB3ZSB3aWxsIG1ha2Ugc2V2ZXJhbCB0YWJsZXMgYW5kIGJhciBwbG90cyB0byB2aWV3IHRoZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGxldmVsIG9mIGxpa2UgdG8gcGxheSBhbmQgdGhlIGZhY3RvciBvd25pbmcgYSBQQyBhbmQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBsZXZlbCBvZiBsaWtlIHRvIHBsYXkgYW5kIHRoZSBmYWN0b3IgaG93IGxvbmcgc3R1ZGVudHMgd29ya2luZy4gQmVzaWRlcywgYSByYW5kb21Gb3Jlc3QgZnVuY3Rpb24gd2lsbCBiZSBhcHBsaWVkIHRvIHZpZXcgcmVsYXRpb24gYmV0d2VlbiBvdGhlciBmYWN0cyB3aXRoIHRoZSBsaWtlLiANCkFmdGVyIHBsb3R0aW5nIHRoZSBiYXIgcGxvdHMsIHdlIHdpbGwgYW5hbHl6ZSB0aGUgZGF0YSBjb21iaW5lZCB3aXRoIHRoZSByZXN1bHRzIGZyb20gdGhlIGZvbGxvdyB1cCBzdXJ2ZXkuPGJyPjxicj4NCmBgYHtyfQ0KI3JhbmRvbUZvcmVzdA0Kc2V0LnNlZWQoMTg5Mjg5KQ0KcmVsYXRpb24gPC0gcmFuZG9tRm9yZXN0KGRhdGEubGlrZSRsaWtlXzAxIH4gc2V4K2hvbWUrZWR1YythZ2UrYnVzeSttYXRoK3dvcmsrb3duK2Nkcm9tK2dyYWRlLCBkYXRhID0gZGF0YS5saWtlLCBpbXBvcnRhbmNlID0gVFJVRSwgbmEuYWN0aW9uID0gbmEub21pdCkNCnZhckltcFBsb3QocmVsYXRpb24pDQpgYGANClRoZSByYW5kb21Gb3Jlc3QgYXBwcm9hY2ggaXMganVzdCBmb3IgZnVuIF5fXi4gIEkgYW0gbm90IHN1cmUgd2hldGhlciBpdCBpcyBhIGdvb2QgYXBwcm9hY2ggdGhvdWdoLiAgQW55d2F5LCBJIGluc3RhbGxlZCB0aGUgcmFuZG9tRm9yZXN0IHBhY2thZ2UsIGFuZCBpbXBsZW1lbnRlZCB0aGUgYWxnb3JpdGhtIGluIGhvcGUgdGhhdCBpdCBjb3VsZCByZXR1cm4gc29tZSB1c2VmdWwgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHdoZXRoZXIgdGhlIHN0dWRlbnRzIGxpa2Ugb3IgZGlzbGlrZSBwbGF5aW5nIHZpZGVvIGdhbWVzIHZlcnN1cyBvdGhlciBmYWN0b3JzIGluIHRoZSBkYXRhIHNldC4gIFRvIG15IGtub3dsZWRnZSwgdGhlICVJbmNNU0UgaXMgdGhlIG1vc3Qgcm9idXN0IGFuZCBpbmZvcm1hdGl2ZSBtZWFzdXJlLiAgSXQgaXMgdGhlIGluY3JlYXNlIGluIG1zZSBvZiBwcmVkaWN0aW9ucyBhcyBhIHJlc3VsdCBvZiB2YXJpYWJsZSBiZWluZyBwZXJtdXRlZC4gIEFzIGEgY29uY2x1c2lvbiwgaWYgdGhlIGZhY3RvciBoYXMgYSBoaWdoZXIgJUluY01TRSBudW1iZXIsIHRoZSBpbXBvcnRhbnQgdGhhdCBmYWN0b3IgaXMgdG8gd2hldGhlciBzdHVkZW50cyBsaWtlIG9yIGRpc2xpa2UgdG8gcGxheSB2aWRlbyBnYW1lcy4gIEluIHRoaXMgcHJvYmxlbSwgc2luY2Ugd2UgYXJlIG9ubHkgY29uY2VybmVkIGFib3V0IHRoZXJlIGZhY3RvcnMsIG5hbWVseSwgJ3NleCcsICd3b3JrJywgYW5kICdvd24nLCBJIHdvdWxkIHByZWRpY3QsIGZyb20gdGhlIHJlc3VsdCBvZiByYW5kb21Gb3Jlc3QsIHRoYXQgJ3NleCcsIGFuZCAnd29yaycgYXJlIG1vcmUgaW1wb3J0YW50IHRoYW4gJ293bicuPGJyPjxicj4NCmBgYHtyfQ0KI3RhYmxlDQojY2FsY3VsYXRlIHRoZSB0b3RhbCBtYWxlIGFuZCBmZW1hbGUgc3R1ZGVudHMNCnNleF8xX2xpa2VfMSA9IHN1bShkYXRhLmxpa2Ukc2V4ID09IDEgJiBkYXRhLmxpa2UkbGlrZSA9PSAxKQ0Kc2V4XzFfbGlrZV8yID0gc3VtKGRhdGEubGlrZSRzZXggPT0gMSAmIGRhdGEubGlrZSRsaWtlID09IDIpDQpzZXhfMV9saWtlXzMgPSBzdW0oZGF0YS5saWtlJHNleCA9PSAxICYgZGF0YS5saWtlJGxpa2UgPT0gMykNCnNleF8xX2xpa2VfNCA9IHN1bShkYXRhLmxpa2Ukc2V4ID09IDEgJiBkYXRhLmxpa2UkbGlrZSA9PSA0KQ0Kc2V4XzFfbGlrZV81ID0gc3VtKGRhdGEubGlrZSRzZXggPT0gMSAmIGRhdGEubGlrZSRsaWtlID09IDUpDQoNCnNleF8wX2xpa2VfMSA9IHN1bShkYXRhLmxpa2Ukc2V4ID09IDAgJiBkYXRhLmxpa2UkbGlrZSA9PSAxKQ0Kc2V4XzBfbGlrZV8yID0gc3VtKGRhdGEubGlrZSRzZXggPT0gMCAmIGRhdGEubGlrZSRsaWtlID09IDIpDQpzZXhfMF9saWtlXzMgPSBzdW0oZGF0YS5saWtlJHNleCA9PSAwICYgZGF0YS5saWtlJGxpa2UgPT0gMykNCnNleF8wX2xpa2VfNCA9IHN1bShkYXRhLmxpa2Ukc2V4ID09IDAgJiBkYXRhLmxpa2UkbGlrZSA9PSA0KQ0Kc2V4XzBfbGlrZV81ID0gc3VtKGRhdGEubGlrZSRzZXggPT0gMCAmIGRhdGEubGlrZSRsaWtlID09IDUpDQoNCnNleCA8LSBtYXRyaXgoYygwLDUsMjEsOCw0LDM4LDEsMTgsMjUsNSwzLDUyKSxuY29sPTYsYnlyb3c9VFJVRSkNCmNvbG5hbWVzKHNleCkgPC0gYygiTmV2ZXIgcGxheWVkIiwiVmVyeSBtdWNoIiwiU29tZXdoYXQiLCJOb3QgcmVhbGx5IiwiTm90IGF0IGFsbCIsIlRvdGFsIikNCnJvd25hbWVzKHNleCkgPC0gYygiRmVtYWxlIiwiTWFsZSIpDQpzZXggPC0gYXMudGFibGUoc2V4KQ0Kc2V4DQoNCnNleDEgPC0gbWF0cml4KGMoMCw1LDIxLDgsNCwxLDE4LDI1LDUsMyksbmNvbD01LGJ5cm93PVRSVUUpDQpjb2xuYW1lcyhzZXgxKSA8LSBjKCJOZXZlciBwbGF5ZWQiLCJWZXJ5IG11Y2giLCJTb21ld2hhdCIsIk5vdCByZWFsbHkiLCJOb3QgYXQgYWxsIikNCnJvd25hbWVzKHNleDEpIDwtIGMoIkZlbWFsZSIsIk1hbGUiKQ0Kc2V4MSA8LSBhcy50YWJsZShzZXgxKQ0KDQoNCmJhcnBsb3Qoc2V4MSxtYWluPSJzdHVkZW50IHNleCB2LnMuIHRoZWlyIExpa2UgdG8gUGxheSBsZXZlbCIsbmFtZXMuYXJnID0gY29sbmFtZXMoc2V4MSkseGxhYj0iU2V4Iixjb2w9YygiZGFya2JsdWUiLCJyZWQiKSxsZWdlbmQgPSByb3duYW1lcyhzZXgxKSwgYmVzaWRlPVRSVUUpDQoNCmBgYA0KDQpUaGlzIGlzIHRoZSBiYXIgcGxvdCBvZiBzdHVkZW50c6GvIHNleCB2cy4gdGhlaXIgbGlrZSB0byBwbGF5IGxldmVsLiBUaGUgdG90YWwgbnVtYmVycyBvZiBmZW1hbGUgYW5kIG1hbGUgc3R1ZGVudHMgY29uc2lkZXJlZCBhcmUgMzggYW5kIDUyLCBhbmQgdGhlcmUgaXMgb25lIHN0dWRlbnQgZG9lcyBub3QgYW5zd2VyIHByb3Blcmx5IGluIKGwbGlrZSB0byBwbGF5obEgbGV2ZWwsIHNvIHdlIG9ubHkgY29uc2lkZXIgOTAgc2FtcGxlcyBpbiB0b3RhbCBpbiB0aGlzIHNjZW5hcmlvLiBBcyB0aGUgYmFyIHBsb3Qgc2hvd2luZywgbWFqb3JpdHkgb2YgdGhlIGZlbWFsZSBzdHVkZW50cyBjaG9zZSBsaWtlIHRvIHBsYXkgc29tZXdoYXQgYW5kIG1vc3QgbWFsZSBzdHVkZW50cyBjaG9zZSBsaWtlIHRvIHBsYXkgdmVyeSBtdWNoIG9yIHNvbWV3aGF0LiBCZXNpZGVzLCBldmVuIHRob3VnaCB0aGVyZSBhcmUgbGVzcyBmZW1hbGUgc3R1ZGVudHMgaW4gdGhpcyBzYW1wbGUsIHRoZSBudW1iZXIgb2YgdGhlIGZlbWFsZSBzdHVkZW50cyB0aGF0IGNob3NlIG5vdCByZWFsbHkgbGlrZSB0byB2aWRlbyBnYW1lcyBhbmQgbm90IGxpa2UgdmlkZW8gZ2FtZXMgYXQgYWxsIGlzIGFwcGFyZW50bHkgc3RpbGwgYmlnZ2VyIHRoYW4gdGhlIG51bWJlciBvZiB0aGUgbWFsZSBzdHVkZW50cyB0aGF0IGNob3NlIG5vdCByZWFsbHkgbGlrZSB0byB2aWRlbyBnYW1lcyBhbmQgbm90IGxpa2UgdmlkZW8gZ2FtZXMgYXQgYWxsLiBUaHVzLCBjb21wYXJlZCB3aXRoIHRoZSBtYWxlIHN0dWRlbnRzLCB0aGVzZSBmZW1hbGUgc3R1ZGVudHMgaW4gdGhpcyBzYW1wbGUgYXJlIG1vcmUgbGlrZWx5IGRpc2xpa2UgdGhlIHZpZGVvIGdhbWVzIG9yIGRvIG5vdCBsaWtlIHZpZGVvIGdhbWVzIHZlcnkgbXVjaC4NCjxicj48YnI+DQpgYGB7cn0NCiNjb3VudCB0aGUgbGlrZSBhbmQgb3duDQpvd25fMV9saWtlXzEgPSBzdW0oZGF0YS5saWtlJG93biA9PSAxICYgZGF0YS5saWtlJGxpa2UgPT0gMSkNCm93bl8xX2xpa2VfMiA9IHN1bShkYXRhLmxpa2Ukb3duID09IDEgJiBkYXRhLmxpa2UkbGlrZSA9PSAyKQ0Kb3duXzFfbGlrZV8zID0gc3VtKGRhdGEubGlrZSRvd24gPT0gMSAmIGRhdGEubGlrZSRsaWtlID09IDMpDQpvd25fMV9saWtlXzQgPSBzdW0oZGF0YS5saWtlJG93biA9PSAxICYgZGF0YS5saWtlJGxpa2UgPT0gNCkNCm93bl8xX2xpa2VfNSA9IHN1bShkYXRhLmxpa2Ukb3duID09IDEgJiBkYXRhLmxpa2UkbGlrZSA9PSA1KQ0KDQpvd25fMF9saWtlXzEgPSBzdW0oZGF0YS5saWtlJG93biA9PSAwICYgZGF0YS5saWtlJGxpa2UgPT0gMSkNCm93bl8wX2xpa2VfMiA9IHN1bShkYXRhLmxpa2Ukb3duID09IDAgJiBkYXRhLmxpa2UkbGlrZSA9PSAyKQ0Kb3duXzBfbGlrZV8zID0gc3VtKGRhdGEubGlrZSRvd24gPT0gMCAmIGRhdGEubGlrZSRsaWtlID09IDMpDQpvd25fMF9saWtlXzQgPSBzdW0oZGF0YS5saWtlJG93biA9PSAwICYgZGF0YS5saWtlJGxpa2UgPT0gNCkNCm93bl8wX2xpa2VfNSA9IHN1bShkYXRhLmxpa2Ukb3duID09IDAgJiBkYXRhLmxpa2UkbGlrZSA9PSA1KQ0KDQpvd24gPC0gbWF0cml4KGMoMCw1LDE2LDEsMiwyNCwxLDE4LDMwLDEyLDUsNjYpLG5jb2w9NixieXJvdz1UUlVFKQ0KY29sbmFtZXMob3duKSA8LSBjKCJOZXZlciBwbGF5ZWQiLCJWZXJ5IG11Y2giLCJTb21ld2hhdCIsIk5vdCByZWFsbHkiLCJOb3QgYXQgYWxsIiwiVG90YWwiKQ0Kcm93bmFtZXMob3duKSA8LSBjKCJOb3QgT3duIFBDIiwiT3duIFBDIikNCm93biA8LSBhcy50YWJsZShvd24pDQpvd24NCg0Kb3duMSA8LSBtYXRyaXgoYygwLDUsMTYsMSwyLDEsMTgsMzAsMTIsNSksbmNvbD01LGJ5cm93PVRSVUUpDQpjb2xuYW1lcyhvd24xKSA8LSBjKCJOZXZlciBwbGF5ZWQiLCJWZXJ5IG11Y2giLCJTb21ld2hhdCIsIk5vdCByZWFsbHkiLCJOb3QgYXQgYWxsIikNCnJvd25hbWVzKG93bjEpIDwtIGMoIk5vdCBPd24gUEMiLCJPd24gUEMiKQ0Kb3duMSA8LSBhcy50YWJsZShvd24xKQ0KDQpiYXJwbG90KG93bjEsbWFpbj0ic3R1ZGVudCBvd24gUEMgb3Igbm90IHYucy4gdGhlaXIgTGlrZSB0byBQbGF5IGxldmVsIixuYW1lcy5hcmcgPSBjb2xuYW1lcyhvd24xKSx4bGFiPSJPd24gUEMgb3IgTm90Iixjb2w9YygiZGFya2JsdWUiLCJyZWQiKSxsZWdlbmQgPSByb3duYW1lcyhvd24xKSwgYmVzaWRlPVRSVUUpDQoNCmBgYA0KVGhpcyBpcyBhIGJhciBwbG90IHVzZWQgdG8gaW52ZXN0aWdhdGUgd2hldGhlciBzdHVkZW50IG93biBQQyBvciBub3Qgd2lsbCBhZmZlY3QgdGhlaXIgbGlrZSB0byBwbGF5IGxldmVsLiBJbiB0aGlzIHNhbXBsZSwgdGhlcmUgYXJlIDY2IG91dCBvZiA5MCBzdHVkZW50cyBvd24gYSBQQywgYW5kIG1vc3Qgb2YgdGhlc2UgcGVvcGxlIHdobyBvd24gYSBQQyBhcmUgbGlrZSB0byBwbGF5IHZpZGVvIGdhbWUgdmVyeSBtdWNoIG9yIHNvbWV3aGF0LiBUaGVyZSBpcyBzdGlsbCBhIHNtYWxsIHBvcnRpb24gb2YgdGhlc2Ugc3R1ZGVudHMgb3duIGEgUEMgdGhhdCBhcmUgZG9lcyBub3QgbGlrZSB0byBwbGF5IHZpZGVvIGdhbWVzLiBCZXNpZGVzLCBtb3N0IG9mIHRob3NlIHN0dWRlbnRzIHdobyBkbyBub3Qgb3duIGEgUEMgYWxzbyBsaWtlIHRvIHBsYXkgdmlkZW8gZ2FtZXMgc29tZXdoYXQgb3IgZXZlbiB2ZXJ5IG11Y2guIFRoZXJlZm9yZSwgdGhlIGZhY3RvciBvd25pbmcgYSBQQyB3aWxsIG5vdCBhZmZlY3QgdGhlIHN0dWRlbnRzoa8gbGlrZSB0byBwbGF5IGxldmVsLiANCjxicj48YnI+DQpgYGB7cn0NCg0KIyB3b3JraW5nIGhvdXJzIDE6WzAgMTApLDI6WzEwLDIwKSwzOlsyMCxhbmQgbW9yZSkNCndvcmtfMV9saWtlXzEgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPDEwICYgZGF0YS5saWtlJGxpa2UgPT0gMSkNCndvcmtfMV9saWtlXzIgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPDEwICYgZGF0YS5saWtlJGxpa2UgPT0gMikNCndvcmtfMV9saWtlXzMgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPDEwICYgZGF0YS5saWtlJGxpa2UgPT0gMykNCndvcmtfMV9saWtlXzQgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPDEwICYgZGF0YS5saWtlJGxpa2UgPT0gNCkNCndvcmtfMV9saWtlXzUgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPDEwICYgZGF0YS5saWtlJGxpa2UgPT0gNSkNCg0Kd29ya18yX2xpa2VfMSA9IHN1bSghaXMubmEoZGF0YS5saWtlJHdvcmspICYgZGF0YS5saWtlJHdvcms+PTEwICYgZGF0YS5saWtlJHdvcms8MjAgICYgZGF0YS5saWtlJGxpa2UgPT0gMSkNCndvcmtfMl9saWtlXzIgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPj0xMCAmIGRhdGEubGlrZSR3b3JrPDIwICAmIGRhdGEubGlrZSRsaWtlID09IDIpDQp3b3JrXzJfbGlrZV8zID0gc3VtKCFpcy5uYShkYXRhLmxpa2Ukd29yaykgJiBkYXRhLmxpa2Ukd29yaz49MTAgJiBkYXRhLmxpa2Ukd29yazwyMCAgJiBkYXRhLmxpa2UkbGlrZSA9PSAzKQ0Kd29ya18yX2xpa2VfNCA9IHN1bSghaXMubmEoZGF0YS5saWtlJHdvcmspICYgZGF0YS5saWtlJHdvcms+PTEwICYgZGF0YS5saWtlJHdvcms8MjAgICYgZGF0YS5saWtlJGxpa2UgPT0gNCkNCndvcmtfMl9saWtlXzUgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPj0xMCAmIGRhdGEubGlrZSR3b3JrPDIwICAmIGRhdGEubGlrZSRsaWtlID09IDUpDQoNCndvcmtfM19saWtlXzEgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPj0yMCAmIGRhdGEubGlrZSRsaWtlID09IDEpDQp3b3JrXzNfbGlrZV8yID0gc3VtKCFpcy5uYShkYXRhLmxpa2Ukd29yaykgJiBkYXRhLmxpa2Ukd29yaz49MjAgJiBkYXRhLmxpa2UkbGlrZSA9PSAyKQ0Kd29ya18zX2xpa2VfMyA9IHN1bSghaXMubmEoZGF0YS5saWtlJHdvcmspICYgZGF0YS5saWtlJHdvcms+PTIwICYgZGF0YS5saWtlJGxpa2UgPT0gMykNCndvcmtfM19saWtlXzQgPSBzdW0oIWlzLm5hKGRhdGEubGlrZSR3b3JrKSAmIGRhdGEubGlrZSR3b3JrPj0yMCAmIGRhdGEubGlrZSRsaWtlID09IDQpDQp3b3JrXzNfbGlrZV81ID0gc3VtKCFpcy5uYShkYXRhLmxpa2Ukd29yaykgJiBkYXRhLmxpa2Ukd29yaz49MjAgJiBkYXRhLmxpa2UkbGlrZSA9PSA1KQ0KDQoNCndvcmsgPC0gbWF0cml4KGMoMCwxMiwyNiwxMiw0LDU0LDEsNiwxNiwxLDIsMjYsMCw1LDEsMCwxLDcpLG5jb2w9NixieXJvdz1UUlVFKQ0KY29sbmFtZXMod29yaykgPC0gYygiTmV2ZXIgcGxheWVkIiwiVmVyeSBtdWNoIiwiU29tZXdoYXQiLCJOb3QgcmVhbGx5IiwiTm90IGF0IGFsbCIsIlRvdGFsIikNCnJvd25hbWVzKHdvcmspIDwtIGMoIndvcmtpbmcgaG91cnMgaW4gWzAsMTApIiwid29ya2luZyBob3VycyBpbiBbMTAsMjApIiwid29ya2luZyBob3VycyBtb3JlIHRoYW4gMjAiKQ0Kd29yayA8LSBhcy50YWJsZSh3b3JrKQ0Kd29yaw0KDQp3b3JrMSA8LSBtYXRyaXgoYygwLDEyLDI2LDEyLDQsMSw2LDE2LDEsMiwwLDUsMSwwLDEpLG5jb2w9NSxieXJvdz1UUlVFKQ0KY29sbmFtZXMod29yazEpIDwtIGMoIk5ldmVyIHBsYXllZCIsIlZlcnkgbXVjaCIsIlNvbWV3aGF0IiwiTm90IHJlYWxseSIsIk5vdCBhdCBhbGwiKQ0Kcm93bmFtZXMod29yazEpIDwtIGMoIndvcmtpbmcgaG91cnMgaW4gWzAsMTApIiwid29ya2luZyBob3VycyBpbiBbMTAsMjApIiwid29ya2luZyBob3VycyBtb3JlIHRoYW4gMjAiKQ0Kd29yazEgPC0gYXMudGFibGUod29yazEpDQoNCg0KYmFycGxvdCh3b3JrMSxtYWluPSJzdHVkZW50IHdvcmtpbmcgaHJzIHYucy4gdGhlaXIgTGlrZSB0byBQbGF5IGxldmVsIixuYW1lcy5hcmcgPSBjb2xuYW1lcyh3b3JrMSkseGxhYj0id29ya2luZyBob3VycyIsY29sPWMoImRhcmtibHVlIiwicmVkIiwieWVsbG93IiksbGVnZW5kID0gcm93bmFtZXMod29yazEpLCBiZXNpZGU9VFJVRSkNCg0KYGBgDQpJbiB0aGlzIHBhcnQsIHdlIGRpdmlkZSB0aGUgd29ya2luZyBob3VycyBvZiBzdHVkZW50cyBpbnRvIHRocmVlIHBhcnQsIHdvcmtpbmcgaG91cnMgbGVzcyB0aGFuIDEwIGhvdXJzLCBiZXR3ZWVuIDEwIGFuZCAyMCBob3VycyBhbmQgbW9yZSB0aGFuIDIwIGhvdXJzLiBUaGUgcmVhc29uIHdoeSB3ZSBjaG9vc2UgMjAgYXMgYSBsaW1pdCBpcyB0aGF0IG1vc3Qgb2YgdGhlIHN0dWRlbnRzIHVzdWFsbHkgZG8gbm90IHdvcmsgbW9yZSB0aGFuIDIwIGhvdXJzLg0KQXMgdGhlIGJhciBwbG90IHNob3dpbmcsIG1ham9yaXR5IG9mIHRoZSBzdHVkZW50cyB3aG8gd29ya2luZyBsZXNzIHRoYW4gMTAgaG91cnMgYXJlIGxpa2UgdG8gcGxheSB0aGUgdmlkZW8gZ2FtZSBzb21ld2hhdCwgYW5kIHRoZSChsE5vdCByZWFsbHmhsSBhbmQgdGhlIKGwdmVyeSBtdWNoobEgY2hvaWNlcyBhcmUgY2hvc2VuIGJ5IGFib3V0IHRoZSBzYW1lIGFtb3VudC4gQXMgYSBjb25jbHVzaW9uIGZvciB0aGUgc3R1ZGVudCB3b3JraW5nIGxlc3MgdGhhbiAxMCBob3VycywgdGhlc2Ugc3R1ZGVudHMgYXJlIGxpa2VseSB0byBwbGF5IHZpZGVvIGdhbWVzIGJ1dCB0aGVyZSBpcyBzdGlsbCBhIGJpZyBhbW91bnQgb2YgdGhlbSBkb2VzIG5vdCBsaWtlIHRvIHBsYXkuDQpNb3N0IG9mIHRoZSBzdHVkZW50cyB3aG9zZSB3b3JraW5nIGhvdXIgaXMgYmV0d2VlbiAxMCBhbmQgMjAgaG91cnMgYXJlIGxpa2VseSB0byBwbGF5IHRoZSB2aWRlbyBnYW1lcywgYmVjYXVzZSBtb3N0IG9mIHRoZW0gY2hvb3NlIKGwdmVyeSBtdWNoobEgb3IgobBzb21ld2hhdKGxLCBhbmQgdGhlIHBvcnRpb24gb2YgobBuZXZlciBwbGF5ZWShsSwgobBub3QgcmVhbGx5obEgYW5kIKGwbm90IGF0IGFsbKGxIGlzIHZlcnkgc21hbGwuIEhvd2V2ZXIsIHRob3NlIHN0dWRlbnRzIHdobyB3b3JrIG1vcmUgdGhhbiAyMCBob3VycyBhcmUgYWxzbyBsaWtlbHkgdG8gcGxheSB2aWRlbyBhcyB0aGUgYmFyIHBsb3Qgc2hvd2luZywgYW5kIGludGVyZXN0aW5nbHksIG1vc3Qgb2YgdGhlc2UgYnVzeSBzdHVkZW50cyBsaWtlIHRvIHBsYXkgdmlkZW8gZ2FtZXMgdmVyeSBtdWNoLiANCjxicj48YnI+DQoNCiFbXShDOi9Vc2Vycy93ZXNoZS9EZXNrdG9wL01hdGggMjg5Qy9IV3MvSFcyL1JlYXNvbl9mb3JfUGxheWluZy5qcGcpDQohW10oQzovVXNlcnMvd2VzaGUvRGVza3RvcC9NYXRoIDI4OUMvSFdzL0hXMi9UeXBlc19vZl9HYW1lc19QbGF5ZWQuanBnKTxicj4NClVzaW5nIHRoZSBmb2xsb3cgdXAgc3VydmV5IGluIHRoZSBub3RlcywgbW9zdCBvZiB0aGUgc3R1ZGVudCAoNjYlKSBwbGF5aW5nIHZpZGVvIGdhbWUgZm9yIHJlbGF4YXRpb24sIGFuZCB3ZSBjYW4gb2JzZXJ2ZSB0aGF0IHN0dWRlbnRzIHdobyBhcmUgYnVzeSBidXQgc3RpbGwgbGlrZSB0byBwbGF5IHZpZGVvIGdhbWVzIHZlcnkgbXVjaCBtYXkgc3RpbGwgaGF2ZSB0aGUgcmVhc29uIHRoYXQgdGhleSB0cmVhdCBwbGF5aW5nIGdhbWVzIGFzIGEgcmVsYXhhdGlvbi4gVGhvc2Ugc3R1ZGVudHMgd2hvIHdvcmsgbGVzcyB0aGFuIDEwIGhvdXJzIGEgd2VlayBtYXkgZmVlbCBib3JlZCBzbyB0aGF0IHRoZXkgYXJlIGxpa2VseSB0byBwbGF5IHZpZGVvLCBhcyB0aGUgc3VydmV5IHNob3dpbmcgdGhhdCAyNyUgc3R1ZGVudHMgdGFrZSBib3JlZCBhcyBhIHJlYXNvbiBmb3IgcGxheWluZyB2aWRlbyBnYW1lcy4NCkJlc2lkZXMsIHRoZSBwb3B1bGFyaXR5IHR5cGVzIG9mIGdhbWVzIG1heSByZXN1bHQgaW4gbW9yZSBtYWxlIHN0dWRlbnRzIHRoYW4gZmVtYWxlIHN0dWRlbnRzIGxpa2UgdG8gcGxheSB2aWRlbyBnYW1lcywgYnV0IHdlIGNhbqGvdCBkZXRlcm1pbmUgd2hpY2ggdHlwZXMgb2YgZ2FtZXMgYXJlIG1vcmUgcG9wdWxhciBhbW9uZyBtYWxlIHN0dWRlbnRzIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgZGF0YS4NCg0KIyMjIzIuNiBTY2VuYXJpbyA2DQpUaGlzIHBhcnQgaXMgZG9uZSBmb3IgZnVuIGFuZCB0aGlzIGlzIG5vdCByZXFpcmVkIGR1ZSB0byBvdXIgYmFja2dyb3VkIGFjY29yZGluZyB0byB3aGF0IFByb2Zlc3NvciBzYWlkLg0KV2UgZmlyc3QgbWFrZSBhIHRhYmxlIHRvIHNlZSB0aGUgcGVyY2VudGFnZSBvZiBlYWNoIGV4cGVjdGVkIGdyYWRlIGZyb20gdGhlIHNhbXBsZSwgYW5kIGNsZWFybHkgaXQgZG9lcyBub3QgZm9sbG93IHRoZSBkaXN0cmlidXRpb24gdXNlZCBpbiBncmFkZSBhc3NpZ25tZW50IG9mDQoyMCUgQaGvcywgMzAlQqGvcyw0MCUgY6GvcyBhbmQgMTAlRKGvcyBvciBsb3dlci4gV2UgZGVjaWRlIHRvIGFkZCBtb3JlIHBlb3BsZSB0aGF0IGV4cGVjdHMgRCBncmFkZSB0byB0aGUgc2FtcGxlLCBhbmQgdGhlIHJlc3VsdCB3aWxsIGJlIGRpc2N1c3NlZC4NCmBgYHtyfQ0KbnVtQSA9IHN1bShkYXRhJGdyYWRlID09IDQgJiAhaXMubmEoZGF0YSRncmFkZSkpDQpudW1CID0gc3VtKGRhdGEkZ3JhZGUgPT0gMyAmICFpcy5uYShkYXRhJGdyYWRlKSkNCm51bUMgPSBzdW0oZGF0YSRncmFkZSA9PSAyICYgIWlzLm5hKGRhdGEkZ3JhZGUpKQ0KbnVtRCA9IHN1bShkYXRhJGdyYWRlID09IDEgJiAhaXMubmEoZGF0YSRncmFkZSkpDQpudW1OQSA9IHN1bShpcy5uYShkYXRhJGdyYWRlKSkNClRncmFkZSA8LSBtYXRyaXgoYyhudW1BLG51bUIsbnVtQyxudW1ELG51bUEvOTEsbnVtQi85MSxudW1DLzkxLG51bUQvOTEpLG5jb2wgPSA0LCBieXJvdyA9IFRSVUUpDQpjb2xuYW1lcyhUZ3JhZGUpIDwtIGMoIkV4cGVjdGVkIEEiLCJFeHBlY3RlZCBCIiwiRXhwZWN0ZWQgQyIsIkV4cGVjdGVkIEQiKQ0Kcm93bmFtZXMoVGdyYWRlKSA8LSBjKCJDb3VudHMiLCJQZXJjZW50YWdlIikNClRncmFkZSA8LSBhcy50YWJsZShUZ3JhZGUpDQpUZ3JhZGUNCmBgYA0KQ2xlYXJseSBpdCBkb2VzIG5vdCBmb2xsb3cgdGhlIGRpc3RyaWJ1dGlvbiB1c2VkIGluIGdyYWRlIGFzc2lnbm1lbnQgb2YgMjAlIEGhr3MsIDMwJUKhr3MsNDAlIGOhr3MgYW5kIDEwJUShr3Mgb3IgbG93ZXIuIFdlIGRlY2lkZSB0byBhZGQgc29tZSBkYXRhIHRoYXQgcGVvcGxlIHRoaW5rIHRoZXkgd2lsbCBnZXQgRCB0byBtYWtlIHRoZSBEIHRvIGJlIGFib3V0IDEwJS4gVGhlIG51bWJlciBvZiBuZXcgc3R1ZGVudHMgc2hvdWxkIGJlIDEwIHBlb3BsZS4gSGVyZSwgV2Ugd2lsbCBhZGQgMTAgcGVyc29ucywgdGh1cyB0aGUgdG90YWwgcG9wdWxhdGlvbiB3aWxsIGJlIDEwMS4gDQpgYGB7cn0NClRncmFkZTEgPC0gbWF0cml4KGMobnVtQSxudW1CLG51bUMsbnVtRCsxMCxudW1BLzEwMSxudW1CLzEwMSxudW1DLzEwMSwobnVtRCsxMCkvMTAxKSxuY29sID0gNCwgYnlyb3cgPSBUUlVFKQ0KY29sbmFtZXMoVGdyYWRlMSkgPC0gYygiRXhwZWN0ZWQgQSIsIkV4cGVjdGVkIEIiLCJFeHBlY3RlZCBDIiwiRXhwZWN0ZWQgRCIpDQpyb3duYW1lcyhUZ3JhZGUxKSA8LSBjKCJDb3VudHMiLCJQZXJjZW50YWdlIikNClRncmFkZTEgPC0gYXMudGFibGUoVGdyYWRlMSkNClRncmFkZTENCmBgYA0KDQpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgYWZ0ZXIgYWRkaW5nIDEwIG1vcmUgc3R1ZGVudHMgd2hvIHRoaW5rcyB0aGVpciB3aWxsIGdldCBncmFkZSBELCB0aGUgcGVyY2VudGFnZSBvZiBleHBlY3RlZCBncmFkZSBBIGFuZCBvZiBleHBlY3RlZCBncmFkZSBCIGFyZSBzdGlsbCBoaWdoZXIgdGhhbiB0aGUgMjAlIGFuZCAzMCUsIHdoaWNoIG1lYW5zIHRoYXQgcGVvcGxlIGFyZSBleHBlY3RpbmcgYSBoaWdoZXIgZ3JhZGUgdGhhbiB0aGV5IHdpbGwgZ2V0LiBBcyBhIGNvbmNsdXNpb24sIHRoZSBub25yZXNwb25kZW50cyBhcmUgZmFpbGluZyBzdHVkZW50cyB3aG8gbm8gbG9uZ2VyIGJvdGhlcmVkIHRvIGNvbWUgdG8gdGhlIGRpc2N1c3Npb24gc2VjdGlvbiB3aWxsIG5vdCBjaGFuZ2UgdGhlIHBpY3R1cmUuDQoNCioqKg0KDQojIzMuQ29uY2x1c2lvbg0KR2l2ZW4gdGhlIFVDIEJlcmtlbGV5oa9zIHN1cnZleSBkYXRhLCB3ZSBleHBsb3JlIHRoZSBkYXRhIGZlYXR1cmVzIHdpdGggdGhlIGludGVudGlvbiBvZiBwcm92aWRpbmcgdXNlZnVsIGluZm9ybWF0aW9uIGFib3V0IHN0dWRlbnRzIHRvIHRoZSBkZXNpZ25lcnMgb2YgdGhlIG5ldyBjb21wdXRlciBsYWIuIFRoZSBkYXRhIHNldCBpcyB0ZXN0ZWQgd2l0aGluIHNpeCBkaWZmZXJlbnQgc2NlbmFyaW9zLiBJbiB0aGUgZmlyc3Qgc2NlbmFyaW8sIHdlIGVzdGltYXRlIHRoZSBwZXJjZW50YWdlIG9mIHN0dWRlbnRzIHRoYXQgcGxheWVkIHZpZGVvIGdhbWVzIHByaW9yIHRoZSBzdXJ2ZXkgaXMgaW4gdGhlIGludGVydmFsIGZyb20gMC4yNzQ3MjUzIHRvIHRoZSAwLjQ1MDU0OTUgd2l0aCBvdXIgOTUlIGNvbmZpZGVuY2UuIEluIHRoZSBzZWNvbmQgc2NlbmFyaW8sIHdlIGxpc3Qgb3V0IGEgdGFibGUgYWJvdXQgaG93IGxvbmcgZG9lcyBzdHVkZW50IHBsYXkgcHJpb3IgdGhlIHN1cnZleSBnaXZlbiB0aGF0IHRoZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgaG91cnMgdGhlIHNwZW5kIG9uIHZpZGVvIGdhbWVzIGluIG90aGVyIHdlZWtzLiBGcm9tIHRoYXQgdGFibGUsIHdlIGNvbmNsdWRlIHRoYXQgdGhlIGV4YW0gaW4gdGhlIHByZXZpb3VzIHdlZWsgZG8gYWZmZWN0IHRoZSB0aW1lIHN0dWRlbnRzIHNwZW50IG9uIHZpZGVvIGdhbWVzLiBJbiB0aGUgdGhpcmQgc2NlbmFyaW8sIHdlIGVzdGltYXRlIHRoYXQgdGhlIGF2ZXJhZ2UgYW1vdW50IG9mIHRpbWUgc3BlbnQgcGxheWluZyB2aWRlbyBnYW1lcyBpbiB0aGUgd2VlayBwcmlvciB0byB0aGUgc3VydmV5IGlzIGluIHRoZSBpbnRlcnZhbCBmcm9tIDAuNiBob3VyIHRvIDEuNzggaG91cnMgd2l0aCBvdXIgOTUlIGNvbmZpZGVuY2UuIEluIHRoZSBmb3VydGggc2NlbmFyaW8sIHRvIGFuc3dlciB3aGV0aGVyIHRoZSBzdHVkZW50cyBlbmpveSBwbGF5aW5nIHZpZGVvIGdhbWVzLCB3ZSBkaXJlY3RseSB1c2VkIHRoZSChrmxpa2WhryBjb2x1bW4gb2YgdGhlIGRhdGEgc2V0LiAgQW5kLCB3ZSBjYW4gZ2V0IDY5IG91dCA4MCBzdHVkZW50cyBhbnN3ZXJlZCChrnllc6GvLCB3aGlsZSB0aGUgb3RoZXIgMjEgc3R1ZGVudHMgYW5zd2VyZWQgoa5ub6GvIHdoZW4gdGhleSBhcmUgYXNrZWQgd2hldGhlciB0aGV5IGVuam95ZWQgcGxheWluZyB2aWRlbyBnYW1lcy4gIFRoZW4sIHdlIG1hZGUgdXNlIG9mIHRoZSBmb2xsb3ctdXAgc3VydmV5cyB0byBsb29rIGZvciBpbXBvcnRhbnQgcmVhc29ucyBmb3Igd2h5IHRoZSBzdHVkZW50cyBsaWtlIG9yIGRpc2xpa2UgcGxheWluZyB2aWRlbyBnYW1lcy4gSW4gdGhlIGZpZnRoIHNjZW5hcmlvLCB3ZSBleHBsb3JlIHRoZSBmYWN0b3Igd2hldGhlciB0aGUgc2V4LCBvd25pbmcgYSBQQyBhbmQgd29ya2luZyBob3VycyB3aWxsIGFmZmVjdCB0aGUgc3R1ZGVudHMgYXR0aXR1ZGUgdG8gdmlkZW8gZ2FtZXMsIGFuZCB0aGUgb3duaW5nIGEgUEMgaXMgdGhlIG9ubHkgZmFjdG9yIGFtb25nIHRoZXNlIHRocmVlIGZlYXR1cmVzIHRoYXQgaXMgbm90IGFmZmVjdCB0aGUgc3R1ZGVudHMgYXR0aXR1ZGUgdG93YXJkcyB0aGUgdmlkZW8gZ2FtZXMuIEluIHRoZSBsYXN0IHNjZW5hcmlvLCBmcm9tIHRoZSBnaXZlbiBkYXRhLCB3ZSBjb25jbHVkZSB0aGF0IHN0dWRlbnRzIGFyZSBleHBlY3RpbmcgaGlnaGVyIGdyYWRlIHdoZW4gdGhleSBoYW5kaW5nIHRoZSBzdXJ2ZXkuIA0KKioqDQoNCiMjNC5BcHBlbmRpY2VzDQoNCiMjI3Byb29mDQoxLiBUbyBwcm92ZSAkJEVbWF9JKGopXSA9IFxtdSQkDQpCYXNlZCBvbiB0aGUgZGVmaW5pdGlvbiBvZiB0aGUgZXhwZWN0YXRpb24gb2YgYSByYW5kb20gdmFyaWFibGUsIHdlIGNhbiBzaG93IHRoYXQNCg0KZ2l2ZW4gJFAoSShqKT1pKSA9IFxmcmFjezF9e059JA0KJCRFW1hfSShqKV0gPSBcc3VtX3tpPTF9XntOfVhfaVAoSShqKT1pKSA9IFxzdW1fe2k9MX1ee059KFhfaVxmcmFjezF9e059KT0gXGZyYWN7MX17Tn1cc3VtX3tpPTF9XntOfVhfaSA9IFxtdSQkDQoNClRoZSBleHBlY3RlZCB2YWx1ZSBvZiBhIHJhbmRvbSBzYW1wbGUgaXMgZXF1YWwgdG8gdGhlIG1lYW4gb2YgdGhlIHBvcHVsYXRpb24uDQoNCjIuIFRvIHByb3ZlICQkRVtcYmFye3h9XSA9IFxtdSQkDQpXZSBjYW4gc2hvdyB0aGF0DQokJEVbXGJhcnt4fV0gPSBFW1xmcmFjezF9e259XHN1bV97aj0xfV57bn1YX0koaildID0gXGZyYWN7MX17bn1cc3VtX3tqPTF9XntufUVbWF9JKGopXT1cZnJhY3sxfXtufVxzdW1fe2o9MX1ee259XG11ID0gXG11JCQNCg0KMy4gVG8gcHJvdmUgJCRWYXIoWF9KKGopKSA9IFxzaWdtYV4yJCQNCkJhc2VkIG9uIHRoZSBkZWZpbml0aW9uIG9mIHZhcmlhbmNlLCB3ZSBjYW4gc2hvdyB0aGF0DQokJFZhcihYX0ooaikpID0gRVsoWF9JKGopIC0gRVtYX0koaildKV4yXT1FWyhYX0koaikgLSBcbXUpXjJdID0gXHN1bV97aT0xfV57Tn0oWF9JKGopIC0gXG11KV4yUChJKGopPWkpID0gXGZyYWN7MX17Tn1cc3VtX3tpPTF9XntOfShYX0koaikgLSBcbXUpXjIgPSBcc2lnbWFeMiQkDQoNCjQuIFRvIGZpbmQgJFZhcihcYmFye3h9KSQNCg0KTm90ZSB0aGF0ICRYX0koaikkIGFuZCAkWF9JKGspJCBhcmUgbm90IGluZGVwZW5kZW50LCB3ZSBjYW4gc2hvdyB0aGF0DQokJFZhcihcYmFye3h9KSA9IFZhcihcZnJhY3sxfXtufVxzdW1fe2o9MX1ee259WF9JKGopKSA9XGZyYWN7MX17bl4yfVZhcihcc3VtX3tqPTF9XntufVhfSShqKSkgPVxmcmFjezF9e25eMn1cc3VtX3tqPTF9XntufVZhcihYX0koaikpK1xmcmFjezF9e25eMn1cc3VtX3tqIFxuZXEga31ee259Q292KFhfSShqKSxYX0koaykpID0gXGZyYWN7MX17bn1cc2lnbWFeMiArIFxmcmFje24tMX17bn1Db3YoWF9JKDEpLFhfSSgyKSkkJA0KDQpOb3cgd2UgbmVlZCB0byBmaW5kICRDb3YoWF9JKDEpLFhfSSgyKSkkDQokJENvdihYX0koMSksWF9JKDIpKSA9IEVbKFhfSSgxKS1FW1hfSSgxKV0pKFhfSSgyKS1FW1hfSSgyKV0pID0gRVsoWF9JKDEpLVxtdSkoWF9JKDIpLVxtdSldID1FW1hfSSgxKVhfSSgyKV0tXG11IEVbWF9JKDEpXS1cbXUgRVtYX0koMildK1xtdV4yID0gLVxmcmFje1xzaWdtYV4yfXtOLTF9JCQNCg0K