Task (instructions):

For any statistical test you run, you need to check, and fully report, each of the assumptions associated with the relevant statistical test. If assumptions are violated, you need to assess what that means for your analysis.

Please note, that large participant samples with multiple conditions often show some violations of normality as assessed by a p value of a specific statistical test. Instead of blindly following these results, please in addition use graphs to assess whether distributions are roughly normal, which is usually sufficient for the ANOVA family of tests. It is also important to ensure that skewness and kurtosis values fall within the range from -2 to +2. If no assumptions are violated, you still need to explicitly report that this is the case. You should report all relevant assumptions for each test, and discuss for each one whether they are violated or not, and eventually decide on your decision for what test to run based on this.

If there are outliers, based on any criterion you have set, or due to data input error, or because participants responded inappropriately or incorrectly to items or questions, you need to assess what the impact of these outliers/participants may be. You then need to decide on whether to include or exclude these participants. In all cases, you should report if outliers are present (or not) and what you have decided to do with them, i.e. how many outliers are removed from the analysis and why. Remember, outliers can come from a number of sources, such as evidence of not carrying out the tasks correctly, or extreme values, so you will need to inspect the data carefully.

Research Questions:

  1. Does a person’s deepfake detection performance change depending on the quality of deepfake (ie., between good vs bad fakes), and depending on the proportion of trials which were fake compared to real videos? And is there an interaction between the two factors?

  2. Are people better at detecting fake or real videos? And does accuracy depend on the quality of the fake video they see?

  3. Which of the following variables significantly predict overall deepfake detection accuracy: confidence, inspection time, gen AI use, gen AI image use, and age?

  4. Which of the following variables - inspection time, gen AI use, gen AI image use, and age - predict overall deepfake detection performance, over and above (i.e. controlling for) confidence?

Variables codebook:

datafile1
datafile1
datafile2
datafile2

What was done

What I (Yuni) did:

  1. two-way between-subjects ANOVA
  2. mixed-design ANOVA
  3. multiple linear regression
  4. multiple linear regression

so if I understand correctly RQs 3 and 4 are answered with the same model, right?


Reply:

Yes and no. For RQ4, I compared the model used in RQ3 with a base model which only has percent_correct and mean_confidence to control for confidence. It looks like:

data5_base = lm(percent_correct ~ mean_confidence,data5)

data5_additional = lm(percent_correct ~ mean_confidence + inspection_time + AI_use + AI_img_use + age, data5)

knitr::opts_chunk$set(echo = T,message = F,warning = F)


rm(list=ls())

#setwd("~/R/Psi_Chi_R")

library(tidyverse)

#total for bottom row
sum_rows = function(x) {
  x = as.data.frame(x)
  sums = sapply(x,function(col) if (is.numeric(col)) sum(col, na.rm = T) else NA)
  sums = as.data.frame(t(sums))
  names(sums) = names(x)
  rbind(x, sums)
}

## right column for total
sum_cols = function(x) {
  x$Total = rowSums(x[sapply(x, is.numeric)], na.rm = T)
  x
}

#dollar format function
dollars = function(x) {
  paste0("$",format(x,big.mark= ",",scientific=F))
}

desc_stats = function(x){
  c(min = min(x,na.rm=T),
    median = median(x,na.rm=T),
    max = max(x,na.rm=T),
    mean = mean(x,na.rm=T),
    sd = sd(x,na.rm=T))
}

#numeric notations
options(scipen=9999)
## Clean and EDA
data1 = read.csv('yuni_datafile1.csv')

data2 = read.csv('yuni_datafile2.csv')

#join datasets together
data3 = data1 %>% 
  inner_join(data2,by=join_by(participant==participant,condition==condition,sex==sex,age==age,prop_fake==prop_fake,fake_qual==fake_qual))

data4 = data3 %>% 
  mutate(prop_fake = as.factor(prop_fake),
         fake_qual = as.factor(fake_qual),
         condition = as.factor(condition),
         sex = as.factor(sex))
#SmartEDA::ExpData(data3,type = 2) %>%   arrange(desc(Per_of_Missing))

1. Does a person’s deepfake detection performance change (DV) depending on the quality of deepfake (ie., between good vs bad fakes), and depending on the proportion of trials which were fake compared to real videos?

DV: percent_correct

IV: fake_qual, prop_fake

RQ1_main = aov(percent_correct ~ fake_qual * prop_fake, data4)

1.1a. Assumptions check

Normality

residuals_RQ1_main =residuals(RQ1_main)

hist(residuals_RQ1_main)

qqnorm(residuals_RQ1_main)

qqline(residuals_RQ1_main)

shapiro.test(residuals_RQ1_main)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals_RQ1_main
## W = 0.99051, p-value = 0.4692

Plot and test assumptions passed.

Homogeneity

par(mfrow = c(2,2))
plot(RQ1_main)

var.test(data4$percent_correct[data4$fake_qual == "Good_fake"],data4$percent_correct[data4$fake_qual == "Bad_fake"])
## 
##  F test to compare two variances
## 
## data:  data4$percent_correct[data4$fake_qual == "Good_fake"] and data4$percent_correct[data4$fake_qual == "Bad_fake"]
## F = 0.79364, num df = 68, denom df = 69, p-value = 0.3416
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  0.4924805 1.2800513
## sample estimates:
## ratio of variances 
##          0.7936433
# tapply(data4$percent_correct, interaction(data4$fake_qual, data4$prop_fake), var) %>% data.frame() %>% 
#   select(variance = 1) %>% 
#   arrange(variance) %>% 
#   print()

Plots appear fine overall. Some outliers here and there, but nothing severe to exclude them from the analysis.

F-test shows no evidence of violating homogeneity (p-val. = 0.3416).

1.1b. ANOVA test

print(anova(RQ1_main))
## Analysis of Variance Table
## 
## Response: percent_correct
##                      Df  Sum Sq Mean Sq  F value              Pr(>F)    
## fake_qual             1 21485.5 21485.5 511.0962 <0.0000000000000002 ***
## prop_fake             1    10.6    10.6   0.2515              0.6168    
## fake_qual:prop_fake   1    29.1    29.1   0.6919              0.4070    
## Residuals           135  5675.1    42.0                                 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

1.1c. Answer

Yes, a person’s percent_correct changes depending on fake_qual (p-val: 0.0000000000000002), but not on prop_fake (p-val: 0.6168).

Detection of bad vs good deepfakes is significant (p-val. = 0.0000000000000002).

Changing the proportion of fakes doesn’t impact performance (p-val. = 0.6168).

No interaction between fake_qual and prop_fake (p.val = 0.4070). The impact of fake_qual stays consistent regardless of how many fake trials were shown.

1.2. And is there an interaction between the two factors?

No, p-value is (fake_qual:prop_fake) 0.4070. There’s no interaction between fake_qual and prop_fake.

Interaction of fake_qual and prop_fake

data4 %>%
  group_by(fake_qual, prop_fake) %>%
  summarise(
  mean_accuracy = mean(percent_correct),
  se = sd(percent_correct) / sqrt(n()),
  n = n(),
  .groups = "drop") %>%
  ggplot(aes(x = prop_fake, y = mean_accuracy, fill = fake_qual)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), color = "black", width = 0.6) +
  geom_errorbar(aes(ymin = mean_accuracy - se, ymax = mean_accuracy + se),
                position = position_dodge(width = 0.8), width = 0.2) +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  labs(title = "Interaction of Fake Quality by Proportion of Fakes",
       y = "Mean Accuracy") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))+
  geom_text(aes(label = paste0(n, "\n(", round(mean_accuracy, 1), "%)")),position = position_dodge(width = 0.8),
          vjust = 5,hjust=.5, size = 3, color = "black")

Bar chart shows no differences for interaction between the two factors. The pink bars look the same in either group, and the same with the teal bars as well. No differences seen.

This is the line chart replica of the above bar chart:

data4 %>%
  group_by(fake_qual, prop_fake) %>%
  summarise(
  mean_accuracy = mean(percent_correct),
  se = sd(percent_correct) / sqrt(n()),
  n = n(),
  .groups = "drop") %>%
  ggplot(aes(x = prop_fake, y = mean_accuracy, color = fake_qual, group = fake_qual)) +
  geom_line(size = 1) +
  geom_point(size = 3) +
  geom_errorbar(aes(ymin = mean_accuracy - se, ymax = mean_accuracy + se),
                width = 0.1) +
  labs(title = "Interaction of Fake Quality and Proportion of Fakes",
       y = "Mean Accuracy") +
  theme_bw()+
  theme(plot.title = element_text(hjust =.5))+
  scale_y_continuous(labels = scales::percent_format(scale = 1))+
  geom_text(aes(label = paste0(n, "\n(", round(mean_accuracy, 1), "%)")),
          position = position_dodge(width = 0.8), size = 3, color = "black")

2. Are people better at detecting fake or real videos?

percent_correct_fake (PCF) vs. percent_correct_real (PCR)

2.1a. Assumptions check

Normality

shapiro.test(data4$percent_correct_fake)
## 
##  Shapiro-Wilk normality test
## 
## data:  data4$percent_correct_fake
## W = 0.93846, p-value = 0.000008619
shapiro.test(data4$percent_correct_real)
## 
##  Shapiro-Wilk normality test
## 
## data:  data4$percent_correct_real
## W = 0.99036, p-value = 0.4554
hist(data4$percent_correct_fake)

hist(data4$percent_correct_real)

PCF violates normality, but PCR doesn’t.

Check the difference of scores
shapiro.test(data4$percent_correct_fake - data4$percent_correct_real)
## 
##  Shapiro-Wilk normality test
## 
## data:  data4$percent_correct_fake - data4$percent_correct_real
## W = 0.98828, p-value = 0.2899

Normality met - p.val > .05.

Homogeneity

var.test(data4$percent_correct_fake,data4$percent_correct_real)
## 
##  F test to compare two variances
## 
## data:  data4$percent_correct_fake and data4$percent_correct_real
## F = 2.5027, num df = 138, denom df = 138, p-value = 0.0000001231
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  1.790188 3.498935
## sample estimates:
## ratio of variances 
##           2.502749

Variances are statistically different (p-val. = 0.0000001231). PCR is 2.5x smaller than PCF.

2.1b. Paired t-test

t.test(data4$percent_correct_real,data4$percent_correct_fake, paired = T)
## 
##  Paired t-test
## 
## data:  data4$percent_correct_real and data4$percent_correct_fake
## t = 2.5966, df = 138, p-value = 0.01043
## alternative hypothesis: true mean difference is not equal to 0
## 95 percent confidence interval:
##  1.011367 7.469153
## sample estimates:
## mean difference 
##         4.24026
data4.1 = data4 %>%
  select(participant, percent_correct_fake, percent_correct_real) %>%
  pivot_longer(cols = c(percent_correct_fake, percent_correct_real),
               names_to = "video_type",
               values_to = "accuracy")

data4.1_AOV = aov(accuracy ~ video_type + Error(participant/video_type), data4.1)

summary(data4.1_AOV)
## 
## Error: participant
##           Df Sum Sq Mean Sq F value Pr(>F)
## Residuals  1   23.4    23.4               
## 
## Error: participant:video_type
##            Df Sum Sq Mean Sq
## video_type  1    574     574
## 
## Error: Within
##             Df Sum Sq Mean Sq F value Pr(>F)  
## video_type   1    867   867.1   2.976 0.0857 .
## Residuals  274  79838   291.4                 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Boxplot

data4_long = pivot_longer(data4, cols = c(percent_correct_fake, percent_correct_real), 
                          names_to = "Video_Type", values_to = "Percent_Correct")

ggplot(data4_long, aes(x = Video_Type, y = Percent_Correct)) +
  geom_boxplot(fill = "steelblue") +
  stat_summary(fun = mean, geom = "point", shape = 20, size = 3, color = "red") +
  theme_bw()+
  labs(title = "percent_correct_fake vs. percent_correct_real")+
  theme(plot.title = element_text(hjust = .5))

2.1c. Answer

Yes, there’s a significance (p-val. = 0.01043) in that participants scored an average difference of 4.24 more points in percent_correct_real compared to percent_correct_fake.

2.2 And does accuracy depend on the quality of the fake video they see?

IV: fake_qual

DV: percent_correct

2.2a Assumptions check

Normality

shapiro.test(data4$percent_correct[data4$fake_qual == "Good_fake"])
## 
##  Shapiro-Wilk normality test
## 
## data:  data4$percent_correct[data4$fake_qual == "Good_fake"]
## W = 0.99045, p-value = 0.8811
shapiro.test(data4$percent_correct[data4$fake_qual == "Bad_fake"])
## 
##  Shapiro-Wilk normality test
## 
## data:  data4$percent_correct[data4$fake_qual == "Bad_fake"]
## W = 0.98064, p-value = 0.3516

p-val. > 0.05. Normality met; proceed with homogeneity check.

Homogeneity

var.test(data4$percent_correct[data4$fake_qual == "Good_fake"],data4$percent_correct[data4$fake_qual == "Bad_fake"])
## 
##  F test to compare two variances
## 
## data:  data4$percent_correct[data4$fake_qual == "Good_fake"] and data4$percent_correct[data4$fake_qual == "Bad_fake"]
## F = 0.79364, num df = 68, denom df = 69, p-value = 0.3416
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  0.4924805 1.2800513
## sample estimates:
## ratio of variances 
##          0.7936433

No significant difference between the two groups — homogeneity of variances is fine and variances are similar enough (p-val. = 0.3416).

2.2b. Two sample t-test

t.test(data4$percent_correct ~ data4$fake_qual)
## 
##  Welch Two Sample t-test
## 
## data:  data4$percent_correct by data4$fake_qual
## t = 22.714, df = 135.63, p-value < 0.00000000000000022
## alternative hypothesis: true difference in means between group Bad_fake and group Good_fake is not equal to 0
## 95 percent confidence interval:
##  22.70104 27.03099
## sample estimates:
##  mean in group Bad_fake mean in group Good_fake 
##                82.90115                58.03513
#t.test(data4$percent_correct_fake~data4$percent_correct_real)

p-val. = 0.00000000000000022.

2.2c. ANOVA

aov(data4$percent_correct ~ data4$fake_qual) %>% summary()
##                  Df Sum Sq Mean Sq F value              Pr(>F)    
## data4$fake_qual   1  21485   21485   515.1 <0.0000000000000002 ***
## Residuals       137   5715      42                                
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

p-val. <= 0.05.

2.2d. Answer

Yes, there’s a difference of percent_correct in good_fake and bad_fake in fake_qual.

3. Which of the following variables significantly predict overall deepfake detection accuracy: confidence, inspection time, gen AI use, gen AI image use, and age?

“Predict overall deepfake detection performance” = percent_correct.

IV: mean_confidence, inspection_time, AI_use, AI_img_use, age

DV: percent_correct

model_4.1 = lm(percent_correct ~ mean_confidence + inspection_time + AI_use+ AI_img_use+ age,data4)

3.1a. Assumptions check

Normality

par(mfrow = c(2,2))
plot(model_4.1)

shapiro.test(residuals(model_4.1))
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(model_4.1)
## W = 0.97628, p-value = 0.01597

Shapiro test shows violation, but plot shows they aren’t severe and linear model could be used. Use generalized linear model instead to allow for flexibility of outliers.

summary(data4$percent_correct)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   42.59   58.51   68.33   70.56   82.35   98.73
shapiro.test(data4$percent_correct)
## 
##  Shapiro-Wilk normality test
## 
## data:  data4$percent_correct
## W = 0.9453, p-value = 0.00002767
hist(data4$percent_correct)

percent_check appears to be a bimodal distribution.

3.1b. Quasibinomial GLM

data5 = data4 %>%
  mutate(prop_percent_correct = (percent_correct + 0.01) / 100)

#this model replaces model_4.1
data5_GLM = data5 %>%
  mutate(predicted = predict(glm(prop_percent_correct ~ mean_confidence + inspection_time + AI_use + AI_img_use + age, family = quasibinomial(), data = data5),type = "response"))

Fitness

model=glm(prop_percent_correct ~ mean_confidence + inspection_time + AI_use + AI_img_use + age,
             family = quasibinomial(), data = data5)

dispersion <- sum(residuals(model, type = "deviance")^2) / model$df.residual

print(dispersion)
## [1] 0.06719602
plot(model$fitted.values, residuals(model, type = "deviance"),
     xlab = "Fitted values", ylab = "Deviance residuals",
     main = "Residuals vs Fitted")
abline(h = 0, col = "red")

Dispersion is within parameters (anything over 1 indicates overdispersion). Plot shows line straight and nearing 0.

Given that percent_correct is a proportion and is bimodally distributed, use quasibinomial GLM.

data5_GLM_model = glm(prop_percent_correct ~ mean_confidence + inspection_time + AI_use + AI_img_use + age,family = quasibinomial(), data5_GLM)

summary(data5_GLM_model)
## 
## Call:
## glm(formula = prop_percent_correct ~ mean_confidence + inspection_time + 
##     AI_use + AI_img_use + age, family = quasibinomial(), data = data5_GLM)
## 
## Coefficients:
##                   Estimate Std. Error t value           Pr(>|t|)    
## (Intercept)     -1.7084030  0.3865151  -4.420 0.0000203024643544 ***
## mean_confidence  1.0608461  0.1264319   8.391 0.0000000000000622 ***
## inspection_time  0.0004333  0.0019077   0.227             0.8207    
## AI_use           0.0846463  0.0452686   1.870             0.0637 .  
## AI_img_use      -0.0142102  0.0516985  -0.275             0.7838    
## age             -0.0064289  0.0024781  -2.594             0.0105 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for quasibinomial family taken to be 0.0666086)
## 
##     Null deviance: 14.0458  on 138  degrees of freedom
## Residual deviance:  8.9371  on 133  degrees of freedom
## AIC: NA
## 
## Number of Fisher Scoring iterations: 4

Scatter plot of model

ggplot(data5_GLM, aes(x = mean_confidence, y =prop_percent_correct)) +
  geom_point(alpha = 0.6) +
  geom_line(aes(y = predicted), color = "red", size = .5) +
  labs(title = "Predicted percent_correct by mean_confidence") +
  theme_bw()+
  theme(plot.title = element_text(hjust = .5))

ggplot(data5_GLM, aes(x = mean_confidence, y =prop_percent_correct)) +
  geom_point(alpha = 0.6) +
  geom_line(aes(y = predicted), color = "red", size = .5) +
  labs(title = "Predicted percent_correct by mean_confidence faceted by AI_use") +
  theme_bw()+
  theme(plot.title = element_text(hjust = .5),
        plot.subtitle = element_text(hjust = .5))+
  facet_wrap(~AI_use)

3.1c. Answer

mean_confidence (p-val. = 0.0000000000000622) had a positive impact on percent_correct while age (p-val. = 0.0105) had a negative impact on percent_correct. AI_use showed near significance, but not quite enough. Looking at the split scatter plot above, AI_use of 3 appears different from the other groups.

Higher confidence correlates with higher accuracy, whereas older age showed less accuracy in deepfake detection.

4. Which of the following variables - inspection time, gen AI use, gen AI image use, and age - predict overall deepfake detection performance, over and above (i.e. controlling for) confidence?

“Predict overall deepfake detection performance” = percent_correct. Create two models to compare them against each other. One model is the control and the other is the manipulation.

IV: mean_confidence, inspection_time, AI_use, AI_img_use, age

DV: percent_correct

#base model to control for confidence
data5_base = lm(percent_correct ~ mean_confidence,data5)

#add IVs for manipulation
data5_additional= lm(percent_correct ~ mean_confidence + inspection_time + AI_use + AI_img_use + age, data5)

4.1a Assumptions check

Fitness

par(mfrow = c(2,2))
plot(data5_base,main='base model')

par(mfrow = c(2,2))
plot(data5_additional,main='additional model')

Some mildness in Residuals vs Fitted, but nothing severe.

Multicollinearity

data5_cor_matrix = data5 %>%
  select(mean_confidence, inspection_time, AI_use,AI_img_use, age) %>%
  cor(use = "complete.obs")

data5_cor_plot = as.data.frame(as.table(data5_cor_matrix))

ggplot(data5_cor_plot, aes(Var1, Var2, fill = Freq)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(Freq, 2)), color = "black", size = 4) +
  scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0) +
  labs(title = "Correlation of IVs",
       x = "", y = "", fill = "Correlation %") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        plot.title = element_text(hjust = .5))

Values not >= 0.70 or <= -0.70 means multicollinearity isn’t violated. Proceed with hierarchical regression.

4.1b. Hierarchical regression

anova(data5_base,data5_additional) %>% print()
## Analysis of Variance Table
## 
## Model 1: percent_correct ~ mean_confidence
## Model 2: percent_correct ~ mean_confidence + inspection_time + AI_use + 
##     AI_img_use + age
##   Res.Df   RSS Df Sum of Sq      F  Pr(>F)  
## 1    137 17921                              
## 2    133 16543  4    1378.5 2.7708 0.02984 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
summary(data5_additional)
## 
## Call:
## lm(formula = percent_correct ~ mean_confidence + inspection_time + 
##     AI_use + AI_img_use + age, data = data5)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -27.5340  -7.6219   0.2639   8.2718  22.2999 
## 
## Coefficients:
##                  Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)     16.407914   7.652055   2.144              0.0338 *  
## mean_confidence 22.010164   2.454837   8.966 0.00000000000000247 ***
## inspection_time  0.008713   0.036350   0.240              0.8109    
## AI_use           1.668879   0.864559   1.930              0.0557 .  
## AI_img_use      -0.204375   1.001871  -0.204              0.8387    
## age             -0.133828   0.051680  -2.590              0.0107 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 11.15 on 133 degrees of freedom
## Multiple R-squared:  0.3918, Adjusted R-squared:  0.369 
## F-statistic: 17.14 on 5 and 133 DF,  p-value: 0.0000000000004626

The p-val. = 0.0000000000004626 shows that this model is significant, and that the adjusted R-squared shows 36.9% of the variance in percent_correct can be explained by the IVs.

mean_confidence (p-val. = 0.00000000000000247) and age (p-val. = 0.0107) showed significance. mean_confidence with percent_correct is 22.010164 while age with percent_correct is -0.133828. This means each point of mean_confidence increased accuracy by 22, while each point of age decreased accuracy by 0.13.

4.1c. Answer

Adding age with mean_confidence significantly improves the model for predicting percent_correct. The other IVs showed no impact, while AI_use was near significance.


LS0tDQp0aXRsZTogImRlZXBmYWtlcyINCiNkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgbGlnaHRib3g6IHRydWUNCiAgICB0aGVtZTogcmVhZGFibGUNCiAgICBhbHdheXNfYWxsb3dfaHRtbDogeWVzDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICBhbmNob3Jfc2VjdGlvbnM6IFRSVUUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KVGFzayAoaW5zdHJ1Y3Rpb25zKToNCg0KRm9yIGFueSBzdGF0aXN0aWNhbCB0ZXN0IHlvdSBydW4sIHlvdSBuZWVkIHRvIGNoZWNrLCBhbmQgZnVsbHkgcmVwb3J0LCBlYWNoIG9mIHRoZSBhc3N1bXB0aW9ucyBhc3NvY2lhdGVkIHdpdGggdGhlIHJlbGV2YW50IHN0YXRpc3RpY2FsIHRlc3QuIElmIGFzc3VtcHRpb25zIGFyZSB2aW9sYXRlZCwgeW91IG5lZWQgdG8gYXNzZXNzIHdoYXQgdGhhdCBtZWFucyBmb3IgeW91ciBhbmFseXNpcy4NCg0KUGxlYXNlIG5vdGUsIHRoYXQgbGFyZ2UgcGFydGljaXBhbnQgc2FtcGxlcyB3aXRoIG11bHRpcGxlIGNvbmRpdGlvbnMgb2Z0ZW4gc2hvdyBzb21lIHZpb2xhdGlvbnMgb2Ygbm9ybWFsaXR5IGFzIGFzc2Vzc2VkIGJ5IGEgcCB2YWx1ZSBvZiBhIHNwZWNpZmljIHN0YXRpc3RpY2FsIHRlc3QuICoqSW5zdGVhZCBvZiBibGluZGx5IGZvbGxvd2luZyB0aGVzZSByZXN1bHRzLCBwbGVhc2UgaW4gYWRkaXRpb24gdXNlIGdyYXBocyB0byBhc3Nlc3Mgd2hldGhlciBkaXN0cmlidXRpb25zIGFyZSByb3VnaGx5IG5vcm1hbCoqLCB3aGljaCBpcyB1c3VhbGx5IHN1ZmZpY2llbnQgZm9yIHRoZSBBTk9WQSBmYW1pbHkgb2YgdGVzdHMuIEl0IGlzIGFsc28gaW1wb3J0YW50IHRvIGVuc3VyZSB0aGF0IHNrZXduZXNzIGFuZCBrdXJ0b3NpcyB2YWx1ZXMgZmFsbCB3aXRoaW4gdGhlIHJhbmdlIGZyb20gLTIgdG8gKzIuIElmIG5vIGFzc3VtcHRpb25zIGFyZSB2aW9sYXRlZCwgeW91IHN0aWxsIG5lZWQgdG8gZXhwbGljaXRseSByZXBvcnQgdGhhdCB0aGlzIGlzIHRoZSBjYXNlLiBZb3Ugc2hvdWxkIHJlcG9ydCBhbGwgcmVsZXZhbnQgYXNzdW1wdGlvbnMgZm9yIGVhY2ggdGVzdCwgYW5kIGRpc2N1c3MgZm9yIGVhY2ggb25lIHdoZXRoZXIgdGhleSBhcmUgdmlvbGF0ZWQgb3Igbm90LCBhbmQgZXZlbnR1YWxseSBkZWNpZGUgb24geW91ciBkZWNpc2lvbiBmb3Igd2hhdCB0ZXN0IHRvIHJ1biBiYXNlZCBvbiB0aGlzLg0KDQpJZiB0aGVyZSBhcmUgb3V0bGllcnMsIGJhc2VkIG9uIGFueSBjcml0ZXJpb24geW91IGhhdmUgc2V0LCBvciBkdWUgdG8gZGF0YSBpbnB1dCBlcnJvciwgb3IgYmVjYXVzZSBwYXJ0aWNpcGFudHMgcmVzcG9uZGVkIGluYXBwcm9wcmlhdGVseSBvciBpbmNvcnJlY3RseSB0byBpdGVtcyBvciBxdWVzdGlvbnMsIHlvdSBuZWVkIHRvIGFzc2VzcyB3aGF0IHRoZSBpbXBhY3Qgb2YgdGhlc2Ugb3V0bGllcnMvcGFydGljaXBhbnRzIG1heSBiZS4gWW91IHRoZW4gKipuZWVkIHRvIGRlY2lkZSBvbiB3aGV0aGVyIHRvIGluY2x1ZGUgb3IgZXhjbHVkZSB0aGVzZSBwYXJ0aWNpcGFudHMuKiogSW4gYWxsIGNhc2VzLCB5b3Ugc2hvdWxkIHJlcG9ydCBpZiBvdXRsaWVycyBhcmUgcHJlc2VudCAob3Igbm90KSBhbmQgd2hhdCB5b3UgaGF2ZSBkZWNpZGVkIHRvIGRvIHdpdGggdGhlbSwgaS5lLiBob3cgbWFueSBvdXRsaWVycyBhcmUgcmVtb3ZlZCBmcm9tIHRoZSBhbmFseXNpcyBhbmQgd2h5LiBSZW1lbWJlciwgb3V0bGllcnMgY2FuIGNvbWUgZnJvbSBhIG51bWJlciBvZiBzb3VyY2VzLCBzdWNoIGFzIGV2aWRlbmNlIG9mIG5vdCBjYXJyeWluZyBvdXQgdGhlIHRhc2tzIGNvcnJlY3RseSwgb3IgZXh0cmVtZSB2YWx1ZXMsIHNvIHlvdSB3aWxsIG5lZWQgdG8gaW5zcGVjdCB0aGUgZGF0YSBjYXJlZnVsbHkuDQoNCiMgUmVzZWFyY2ggUXVlc3Rpb25zOg0KDQoxLiAgRG9lcyBhIHBlcnNvbidzIGRlZXBmYWtlIGRldGVjdGlvbiBwZXJmb3JtYW5jZSBjaGFuZ2UgZGVwZW5kaW5nIG9uIHRoZSBxdWFsaXR5IG9mIGRlZXBmYWtlIChpZS4sIGJldHdlZW4gZ29vZCB2cyBiYWQgZmFrZXMpLCBhbmQgZGVwZW5kaW5nIG9uIHRoZSBwcm9wb3J0aW9uIG9mIHRyaWFscyB3aGljaCB3ZXJlIGZha2UgY29tcGFyZWQgdG8gcmVhbCB2aWRlb3M/IEFuZCBpcyB0aGVyZSBhbiBpbnRlcmFjdGlvbiBiZXR3ZWVuIHRoZSB0d28gZmFjdG9ycz8NCg0KMi4gIEFyZSBwZW9wbGUgYmV0dGVyIGF0IGRldGVjdGluZyBmYWtlIG9yIHJlYWwgdmlkZW9zPyBBbmQgZG9lcyBhY2N1cmFjeSBkZXBlbmQgb24gdGhlIHF1YWxpdHkgb2YgdGhlIGZha2UgdmlkZW8gdGhleSBzZWU/DQoNCjMuICBXaGljaCBvZiB0aGUgZm9sbG93aW5nIHZhcmlhYmxlcyBzaWduaWZpY2FudGx5IHByZWRpY3Qgb3ZlcmFsbCBkZWVwZmFrZSBkZXRlY3Rpb24gYWNjdXJhY3k6IGNvbmZpZGVuY2UsIGluc3BlY3Rpb24gdGltZSwgZ2VuIEFJIHVzZSwgZ2VuIEFJIGltYWdlIHVzZSwgYW5kIGFnZT8NCg0KNC4gIFdoaWNoIG9mIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzIC0gaW5zcGVjdGlvbiB0aW1lLCBnZW4gQUkgdXNlLCBnZW4gQUkgaW1hZ2UgdXNlLCBhbmQgYWdlIC0gcHJlZGljdCBvdmVyYWxsIGRlZXBmYWtlIGRldGVjdGlvbiBwZXJmb3JtYW5jZSwgb3ZlciBhbmQgYWJvdmUgKGkuZS4gY29udHJvbGxpbmcgZm9yKSBjb25maWRlbmNlPw0KDQpWYXJpYWJsZXMgY29kZWJvb2s6DQoNCiFbZGF0YWZpbGUxXSh5dW5pX2RhdGFmaWxlMWNvbmRpdGlvbnMucG5nKXt3aWR0aD0iNTIzIn0NCg0KIVtkYXRhZmlsZTJdKHl1bmlfZGF0YWZpbGUyY29uZGl0aW9ucy5wbmcpe3dpZHRoPSI1MjMifQ0KDQojIyMjIFdoYXQgd2FzIGRvbmUNCg0KV2hhdCBJIChZdW5pKSBkaWQ6DQoNCjEuIHR3by13YXkgYmV0d2Vlbi1zdWJqZWN0cyBBTk9WQQ0KMi4gbWl4ZWQtZGVzaWduIEFOT1ZBDQozLiBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbg0KNC4gbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24NCg0Kc28gaWYgSSB1bmRlcnN0YW5kIGNvcnJlY3RseSBSUXMgMyBhbmQgNCBhcmUgYW5zd2VyZWQgd2l0aCB0aGUgc2FtZSBtb2RlbCwgcmlnaHQ/DQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KUmVwbHk6DQoNClllcyBhbmQgbm8uIEZvciBSUTQsIEkgY29tcGFyZWQgdGhlIG1vZGVsIHVzZWQgaW4gUlEzIHdpdGggYSBiYXNlIG1vZGVsIHdoaWNoIG9ubHkgaGFzIGBwZXJjZW50X2NvcnJlY3RgIGFuZCBgbWVhbl9jb25maWRlbmNlYCB0byBjb250cm9sIGZvciBjb25maWRlbmNlLiBJdCBsb29rcyBsaWtlOg0KDQpkYXRhNV9iYXNlID0gbG0ocGVyY2VudF9jb3JyZWN0IH4gbWVhbl9jb25maWRlbmNlLGRhdGE1KQ0KDQpkYXRhNV9hZGRpdGlvbmFsID0gbG0ocGVyY2VudF9jb3JyZWN0IH4gbWVhbl9jb25maWRlbmNlICsgaW5zcGVjdGlvbl90aW1lICsgQUlfdXNlICsgQUlfaW1nX3VzZSArIGFnZSwgZGF0YTUpDQoNCmBgYHtyIHdhcm5pbmc9RixtZXNzYWdlPUZ9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFQsbWVzc2FnZSA9IEYsd2FybmluZyA9IEYpDQoNCg0Kcm0obGlzdD1scygpKQ0KDQojc2V0d2QoIn4vUi9Qc2lfQ2hpX1IiKQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KI3RvdGFsIGZvciBib3R0b20gcm93DQpzdW1fcm93cyA9IGZ1bmN0aW9uKHgpIHsNCiAgeCA9IGFzLmRhdGEuZnJhbWUoeCkNCiAgc3VtcyA9IHNhcHBseSh4LGZ1bmN0aW9uKGNvbCkgaWYgKGlzLm51bWVyaWMoY29sKSkgc3VtKGNvbCwgbmEucm0gPSBUKSBlbHNlIE5BKQ0KICBzdW1zID0gYXMuZGF0YS5mcmFtZSh0KHN1bXMpKQ0KICBuYW1lcyhzdW1zKSA9IG5hbWVzKHgpDQogIHJiaW5kKHgsIHN1bXMpDQp9DQoNCiMjIHJpZ2h0IGNvbHVtbiBmb3IgdG90YWwNCnN1bV9jb2xzID0gZnVuY3Rpb24oeCkgew0KICB4JFRvdGFsID0gcm93U3Vtcyh4W3NhcHBseSh4LCBpcy5udW1lcmljKV0sIG5hLnJtID0gVCkNCiAgeA0KfQ0KDQojZG9sbGFyIGZvcm1hdCBmdW5jdGlvbg0KZG9sbGFycyA9IGZ1bmN0aW9uKHgpIHsNCiAgcGFzdGUwKCIkIixmb3JtYXQoeCxiaWcubWFyaz0gIiwiLHNjaWVudGlmaWM9RikpDQp9DQoNCmRlc2Nfc3RhdHMgPSBmdW5jdGlvbih4KXsNCiAgYyhtaW4gPSBtaW4oeCxuYS5ybT1UKSwNCiAgICBtZWRpYW4gPSBtZWRpYW4oeCxuYS5ybT1UKSwNCiAgICBtYXggPSBtYXgoeCxuYS5ybT1UKSwNCiAgICBtZWFuID0gbWVhbih4LG5hLnJtPVQpLA0KICAgIHNkID0gc2QoeCxuYS5ybT1UKSkNCn0NCg0KI251bWVyaWMgbm90YXRpb25zDQpvcHRpb25zKHNjaXBlbj05OTk5KQ0KYGBgDQoNCmBgYHtyfQ0KIyMgQ2xlYW4gYW5kIEVEQQ0KZGF0YTEgPSByZWFkLmNzdigneXVuaV9kYXRhZmlsZTEuY3N2JykNCg0KZGF0YTIgPSByZWFkLmNzdigneXVuaV9kYXRhZmlsZTIuY3N2JykNCg0KI2pvaW4gZGF0YXNldHMgdG9nZXRoZXINCmRhdGEzID0gZGF0YTEgJT4lIA0KICBpbm5lcl9qb2luKGRhdGEyLGJ5PWpvaW5fYnkocGFydGljaXBhbnQ9PXBhcnRpY2lwYW50LGNvbmRpdGlvbj09Y29uZGl0aW9uLHNleD09c2V4LGFnZT09YWdlLHByb3BfZmFrZT09cHJvcF9mYWtlLGZha2VfcXVhbD09ZmFrZV9xdWFsKSkNCg0KZGF0YTQgPSBkYXRhMyAlPiUgDQogIG11dGF0ZShwcm9wX2Zha2UgPSBhcy5mYWN0b3IocHJvcF9mYWtlKSwNCiAgICAgICAgIGZha2VfcXVhbCA9IGFzLmZhY3RvcihmYWtlX3F1YWwpLA0KICAgICAgICAgY29uZGl0aW9uID0gYXMuZmFjdG9yKGNvbmRpdGlvbiksDQogICAgICAgICBzZXggPSBhcy5mYWN0b3Ioc2V4KSkNCmBgYA0KDQpgYGB7cn0NCiNTbWFydEVEQTo6RXhwRGF0YShkYXRhMyx0eXBlID0gMikgJT4lICAgYXJyYW5nZShkZXNjKFBlcl9vZl9NaXNzaW5nKSkNCmBgYA0KDQojIyAxLiBEb2VzIGEgcGVyc29uJ3MgZGVlcGZha2UgZGV0ZWN0aW9uIHBlcmZvcm1hbmNlIGNoYW5nZSAoRFYpIGRlcGVuZGluZyBvbiB0aGUgcXVhbGl0eSBvZiBkZWVwZmFrZSAoaWUuLCBiZXR3ZWVuIGdvb2QgdnMgYmFkIGZha2VzKSwgYW5kIGRlcGVuZGluZyBvbiB0aGUgcHJvcG9ydGlvbiBvZiB0cmlhbHMgd2hpY2ggd2VyZSBmYWtlIGNvbXBhcmVkIHRvIHJlYWwgdmlkZW9zPw0KDQpEVjogcGVyY2VudF9jb3JyZWN0DQoNCklWOiBmYWtlX3F1YWwsIHByb3BfZmFrZQ0KDQpgYGB7cn0NClJRMV9tYWluID0gYW92KHBlcmNlbnRfY29ycmVjdCB+IGZha2VfcXVhbCAqIHByb3BfZmFrZSwgZGF0YTQpDQpgYGANCg0KIyMjIDEuMWEuIEFzc3VtcHRpb25zIGNoZWNrDQoNCiMjIyMgTm9ybWFsaXR5DQoNCmBgYHtyfQ0KcmVzaWR1YWxzX1JRMV9tYWluID1yZXNpZHVhbHMoUlExX21haW4pDQoNCmhpc3QocmVzaWR1YWxzX1JRMV9tYWluKQ0KDQpxcW5vcm0ocmVzaWR1YWxzX1JRMV9tYWluKQ0KDQpxcWxpbmUocmVzaWR1YWxzX1JRMV9tYWluKQ0KDQpzaGFwaXJvLnRlc3QocmVzaWR1YWxzX1JRMV9tYWluKQ0KYGBgDQoNClBsb3QgYW5kIHRlc3QgYXNzdW1wdGlvbnMgcGFzc2VkLg0KDQojIyMjIEhvbW9nZW5laXR5DQoNCmBgYHtyfQ0KcGFyKG1mcm93ID0gYygyLDIpKQ0KcGxvdChSUTFfbWFpbikNCg0KdmFyLnRlc3QoZGF0YTQkcGVyY2VudF9jb3JyZWN0W2RhdGE0JGZha2VfcXVhbCA9PSAiR29vZF9mYWtlIl0sZGF0YTQkcGVyY2VudF9jb3JyZWN0W2RhdGE0JGZha2VfcXVhbCA9PSAiQmFkX2Zha2UiXSkNCg0KIyB0YXBwbHkoZGF0YTQkcGVyY2VudF9jb3JyZWN0LCBpbnRlcmFjdGlvbihkYXRhNCRmYWtlX3F1YWwsIGRhdGE0JHByb3BfZmFrZSksIHZhcikgJT4lIGRhdGEuZnJhbWUoKSAlPiUgDQojICAgc2VsZWN0KHZhcmlhbmNlID0gMSkgJT4lIA0KIyAgIGFycmFuZ2UodmFyaWFuY2UpICU+JSANCiMgICBwcmludCgpDQpgYGANCg0KUGxvdHMgYXBwZWFyIGZpbmUgb3ZlcmFsbC4gU29tZSBvdXRsaWVycyBoZXJlIGFuZCB0aGVyZSwgYnV0IG5vdGhpbmcgc2V2ZXJlIHRvIGV4Y2x1ZGUgdGhlbSBmcm9tIHRoZSBhbmFseXNpcy4NCg0KRi10ZXN0IHNob3dzIG5vIGV2aWRlbmNlIG9mIHZpb2xhdGluZyBob21vZ2VuZWl0eSAocC12YWwuID0gMC4zNDE2KS4NCg0KYGBge3IgZXZhbD1GLGluY2x1ZGU9Rn0NCiNncm91cCB2YXJpYW5jZSBwbG90OyBzdXNwZW5kDQpkYXRhNCA9IGRhdGE0ICU+JQ0KICBtdXRhdGUoZ3JvdXAgPSBpbnRlcmFjdGlvbihmYWtlX3F1YWwsIHByb3BfZmFrZSwgc2VwID0gIi4iKSkNCg0KZ3JvdXBfdmFyaWFuY2VzID0gZGF0YTQgJT4lDQogIGdyb3VwX2J5KGdyb3VwKSAlPiUNCiAgc3VtbWFyaXNlKHZhcmlhbmNlID0gdmFyKHBlcmNlbnRfY29ycmVjdCksIC5ncm91cHMgPSAiZHJvcCIpDQoNCmdncGxvdChkYXRhNCwgYWVzKHggPSBncm91cCwgeSA9IHBlcmNlbnRfY29ycmVjdCwgZmlsbCA9IGdyb3VwKSkgKw0KICBnZW9tX2JveHBsb3Qoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBnZW9tX3RleHQoZGF0YSA9IGdyb3VwX3ZhcmlhbmNlcywNCiAgICAgICAgICAgIGFlcyh4ID0gZ3JvdXAsIHkgPSBtYXgoZGF0YTQkcGVyY2VudF9jb3JyZWN0KSArIDIsbGFiZWwgPSBwYXN0ZTAoIlZhciA9ICIsIHJvdW5kKHZhcmlhbmNlLCAxKSkpLGluaGVyaXQuYWVzID0gRkFMU0UsIHNpemUgPSAzLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgcGVyY2VudF9jb3JyZWN0IGJ5IHByb3BfZmFrZSIsc3VidGl0bGUgPSAiV2l0aGluLWdyb3VwIHZhcmlhbmNlcyIseD0iIikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSxwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLjUpLHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAuNSkpDQoNCmBgYA0KDQojIyMgMS4xYi4gQU5PVkEgdGVzdA0KDQpgYGB7cn0NCnByaW50KGFub3ZhKFJRMV9tYWluKSkNCmBgYA0KDQojIyMgMS4xYy4gQW5zd2VyDQoNClllcywgYSBwZXJzb24ncyBgcGVyY2VudF9jb3JyZWN0YCBjaGFuZ2VzIGRlcGVuZGluZyBvbiBgZmFrZV9xdWFsYCAocC12YWw6IDAuMDAwMDAwMDAwMDAwMDAwMiksIGJ1dCBub3Qgb24gYHByb3BfZmFrZWAgKHAtdmFsOiAwLjYxNjgpLg0KDQpEZXRlY3Rpb24gb2YgYmFkIHZzIGdvb2QgZGVlcGZha2VzIGlzIHNpZ25pZmljYW50IChwLXZhbC4gPSAwLjAwMDAwMDAwMDAwMDAwMDIpLg0KDQpDaGFuZ2luZyB0aGUgcHJvcG9ydGlvbiBvZiBmYWtlcyBkb2Vzbid0IGltcGFjdCBwZXJmb3JtYW5jZSAocC12YWwuID0gMC42MTY4KS4NCg0KTm8gaW50ZXJhY3Rpb24gYmV0d2VlbiBmYWtlX3F1YWwgYW5kIHByb3BfZmFrZSAocC52YWwgPSAwLjQwNzApLiBUaGUgaW1wYWN0IG9mIGZha2VfcXVhbCBzdGF5cyBjb25zaXN0ZW50IHJlZ2FyZGxlc3Mgb2YgaG93IG1hbnkgZmFrZSB0cmlhbHMgd2VyZSBzaG93bi4NCg0KDQojIyAxLjIuIEFuZCBpcyB0aGVyZSBhbiBpbnRlcmFjdGlvbiBiZXR3ZWVuIHRoZSB0d28gZmFjdG9ycz8NCg0KTm8sIHAtdmFsdWUgaXMgKGZha2VfcXVhbDpwcm9wX2Zha2UpIDAuNDA3MC4gVGhlcmUncyBubyBpbnRlcmFjdGlvbiBiZXR3ZWVuIGBmYWtlX3F1YWxgIGFuZCBgcHJvcF9mYWtlYC4NCg0KIyMjIyBJbnRlcmFjdGlvbiBvZiBmYWtlX3F1YWwgYW5kIHByb3BfZmFrZQ0KDQpgYGB7cn0NCmRhdGE0ICU+JQ0KICBncm91cF9ieShmYWtlX3F1YWwsIHByb3BfZmFrZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgbWVhbl9hY2N1cmFjeSA9IG1lYW4ocGVyY2VudF9jb3JyZWN0KSwNCiAgc2UgPSBzZChwZXJjZW50X2NvcnJlY3QpIC8gc3FydChuKCkpLA0KICBuID0gbigpLA0KICAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gcHJvcF9mYWtlLCB5ID0gbWVhbl9hY2N1cmFjeSwgZmlsbCA9IGZha2VfcXVhbCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCBjb2xvciA9ICJibGFjayIsIHdpZHRoID0gMC42KSArDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuX2FjY3VyYWN5IC0gc2UsIHltYXggPSBtZWFuX2FjY3VyYWN5ICsgc2UpLA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCB3aWR0aCA9IDAuMikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChzY2FsZSA9IDEpKSArDQogIGxhYnModGl0bGUgPSAiSW50ZXJhY3Rpb24gb2YgRmFrZSBRdWFsaXR5IGJ5IFByb3BvcnRpb24gb2YgRmFrZXMiLA0KICAgICAgIHkgPSAiTWVhbiBBY2N1cmFjeSIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChuLCAiXG4oIiwgcm91bmQobWVhbl9hY2N1cmFjeSwgMSksICIlKSIpKSxwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwNCiAgICAgICAgICB2anVzdCA9IDUsaGp1c3Q9LjUsIHNpemUgPSAzLCBjb2xvciA9ICJibGFjayIpDQoNCg0KYGBgDQoNCkJhciBjaGFydCBzaG93cyBubyBkaWZmZXJlbmNlcyBmb3IgaW50ZXJhY3Rpb24gYmV0d2VlbiB0aGUgdHdvIGZhY3RvcnMuIFRoZSBwaW5rIGJhcnMgbG9vayB0aGUgc2FtZSBpbiBlaXRoZXIgZ3JvdXAsIGFuZCB0aGUgc2FtZSB3aXRoIHRoZSB0ZWFsIGJhcnMgYXMgd2VsbC4gTm8gZGlmZmVyZW5jZXMgc2Vlbi4NCg0KVGhpcyBpcyB0aGUgbGluZSBjaGFydCByZXBsaWNhIG9mIHRoZSBhYm92ZSBiYXIgY2hhcnQ6DQoNCmBgYHtyfQ0KZGF0YTQgJT4lDQogIGdyb3VwX2J5KGZha2VfcXVhbCwgcHJvcF9mYWtlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICBtZWFuX2FjY3VyYWN5ID0gbWVhbihwZXJjZW50X2NvcnJlY3QpLA0KICBzZSA9IHNkKHBlcmNlbnRfY29ycmVjdCkgLyBzcXJ0KG4oKSksDQogIG4gPSBuKCksDQogIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBwcm9wX2Zha2UsIHkgPSBtZWFuX2FjY3VyYWN5LCBjb2xvciA9IGZha2VfcXVhbCwgZ3JvdXAgPSBmYWtlX3F1YWwpKSArDQogIGdlb21fbGluZShzaXplID0gMSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzKSArDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuX2FjY3VyYWN5IC0gc2UsIHltYXggPSBtZWFuX2FjY3VyYWN5ICsgc2UpLA0KICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xKSArDQogIGxhYnModGl0bGUgPSAiSW50ZXJhY3Rpb24gb2YgRmFrZSBRdWFsaXR5IGFuZCBQcm9wb3J0aW9uIG9mIEZha2VzIiwNCiAgICAgICB5ID0gIk1lYW4gQWNjdXJhY3kiKSArDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPS41KSkrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KHNjYWxlID0gMSkpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKG4sICJcbigiLCByb3VuZChtZWFuX2FjY3VyYWN5LCAxKSwgIiUpIikpLA0KICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCBzaXplID0gMywgY29sb3IgPSAiYmxhY2siKQ0KYGBgDQoNCiMjIDIuIEFyZSBwZW9wbGUgYmV0dGVyIGF0IGRldGVjdGluZyBmYWtlIG9yIHJlYWwgdmlkZW9zPyANCg0KcGVyY2VudF9jb3JyZWN0X2Zha2UgKFBDRikgdnMuIHBlcmNlbnRfY29ycmVjdF9yZWFsIChQQ1IpDQoNCiMjIyAyLjFhLiBBc3N1bXB0aW9ucyBjaGVjaw0KDQojIyMjIE5vcm1hbGl0eQ0KDQpgYGB7cn0NCnNoYXBpcm8udGVzdChkYXRhNCRwZXJjZW50X2NvcnJlY3RfZmFrZSkNCg0Kc2hhcGlyby50ZXN0KGRhdGE0JHBlcmNlbnRfY29ycmVjdF9yZWFsKQ0KDQpoaXN0KGRhdGE0JHBlcmNlbnRfY29ycmVjdF9mYWtlKQ0KDQpoaXN0KGRhdGE0JHBlcmNlbnRfY29ycmVjdF9yZWFsKQ0KYGBgDQoNClBDRiB2aW9sYXRlcyBub3JtYWxpdHksIGJ1dCBQQ1IgZG9lc24ndC4NCg0KIyMjIyMgQ2hlY2sgdGhlIGRpZmZlcmVuY2Ugb2Ygc2NvcmVzDQoNCmBgYHtyfQ0Kc2hhcGlyby50ZXN0KGRhdGE0JHBlcmNlbnRfY29ycmVjdF9mYWtlIC0gZGF0YTQkcGVyY2VudF9jb3JyZWN0X3JlYWwpDQoNCmBgYA0KDQpOb3JtYWxpdHkgbWV0IC0gcC52YWwgPiAuMDUuDQoNCiMjIyMgSG9tb2dlbmVpdHkNCg0KYGBge3J9DQp2YXIudGVzdChkYXRhNCRwZXJjZW50X2NvcnJlY3RfZmFrZSxkYXRhNCRwZXJjZW50X2NvcnJlY3RfcmVhbCkNCmBgYA0KDQpWYXJpYW5jZXMgYXJlIHN0YXRpc3RpY2FsbHkgZGlmZmVyZW50IChwLXZhbC4gPSAwLjAwMDAwMDEyMzEpLiBgUENSYCBpcyAyLjV4IHNtYWxsZXIgdGhhbiBgUENGYC4NCg0KIyMjIDIuMWIuIFBhaXJlZCB0LXRlc3QNCg0KYGBge3J9DQp0LnRlc3QoZGF0YTQkcGVyY2VudF9jb3JyZWN0X3JlYWwsZGF0YTQkcGVyY2VudF9jb3JyZWN0X2Zha2UsIHBhaXJlZCA9IFQpDQpgYGANCg0KYGBge3J9DQpkYXRhNC4xID0gZGF0YTQgJT4lDQogIHNlbGVjdChwYXJ0aWNpcGFudCwgcGVyY2VudF9jb3JyZWN0X2Zha2UsIHBlcmNlbnRfY29ycmVjdF9yZWFsKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKHBlcmNlbnRfY29ycmVjdF9mYWtlLCBwZXJjZW50X2NvcnJlY3RfcmVhbCksDQogICAgICAgICAgICAgICBuYW1lc190byA9ICJ2aWRlb190eXBlIiwNCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJhY2N1cmFjeSIpDQoNCmRhdGE0LjFfQU9WID0gYW92KGFjY3VyYWN5IH4gdmlkZW9fdHlwZSArIEVycm9yKHBhcnRpY2lwYW50L3ZpZGVvX3R5cGUpLCBkYXRhNC4xKQ0KDQpzdW1tYXJ5KGRhdGE0LjFfQU9WKQ0KDQpgYGANCg0KIyMjIyBCb3hwbG90DQoNCmBgYHtyfQ0KZGF0YTRfbG9uZyA9IHBpdm90X2xvbmdlcihkYXRhNCwgY29scyA9IGMocGVyY2VudF9jb3JyZWN0X2Zha2UsIHBlcmNlbnRfY29ycmVjdF9yZWFsKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZpZGVvX1R5cGUiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudF9Db3JyZWN0IikNCg0KZ2dwbG90KGRhdGE0X2xvbmcsIGFlcyh4ID0gVmlkZW9fVHlwZSwgeSA9IFBlcmNlbnRfQ29ycmVjdCkpICsNCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAic3RlZWxibHVlIikgKw0KICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsIHNoYXBlID0gMjAsIHNpemUgPSAzLCBjb2xvciA9ICJyZWQiKSArDQogIHRoZW1lX2J3KCkrDQogIGxhYnModGl0bGUgPSAicGVyY2VudF9jb3JyZWN0X2Zha2UgdnMuIHBlcmNlbnRfY29ycmVjdF9yZWFsIikrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAuNSkpDQpgYGANCg0KIyMjIDIuMWMuIEFuc3dlcg0KDQpZZXMsIHRoZXJlJ3MgYSBzaWduaWZpY2FuY2UgKHAtdmFsLiA9IDAuMDEwNDMpIGluIHRoYXQgcGFydGljaXBhbnRzIHNjb3JlZCBhbiBhdmVyYWdlIGRpZmZlcmVuY2Ugb2YgNC4yNCBtb3JlIHBvaW50cyBpbiBgcGVyY2VudF9jb3JyZWN0X3JlYWxgIGNvbXBhcmVkIHRvIGBwZXJjZW50X2NvcnJlY3RfZmFrZWAuDQoNCiMjIDIuMiBBbmQgZG9lcyBhY2N1cmFjeSBkZXBlbmQgb24gdGhlIHF1YWxpdHkgb2YgdGhlIGZha2UgdmlkZW8gdGhleSBzZWU/DQoNCklWOiBgZmFrZV9xdWFsYA0KDQpEVjogYHBlcmNlbnRfY29ycmVjdGANCg0KIyMjIDIuMmEgQXNzdW1wdGlvbnMgY2hlY2sNCg0KIyMjIyBOb3JtYWxpdHkNCg0KYGBge3J9DQpzaGFwaXJvLnRlc3QoZGF0YTQkcGVyY2VudF9jb3JyZWN0W2RhdGE0JGZha2VfcXVhbCA9PSAiR29vZF9mYWtlIl0pDQoNCnNoYXBpcm8udGVzdChkYXRhNCRwZXJjZW50X2NvcnJlY3RbZGF0YTQkZmFrZV9xdWFsID09ICJCYWRfZmFrZSJdKQ0KYGBgDQoNCnAtdmFsLiA+IDAuMDUuIE5vcm1hbGl0eSBtZXQ7IHByb2NlZWQgd2l0aCBob21vZ2VuZWl0eSBjaGVjay4NCg0KIyMjIyBIb21vZ2VuZWl0eQ0KDQpgYGB7cn0NCnZhci50ZXN0KGRhdGE0JHBlcmNlbnRfY29ycmVjdFtkYXRhNCRmYWtlX3F1YWwgPT0gIkdvb2RfZmFrZSJdLGRhdGE0JHBlcmNlbnRfY29ycmVjdFtkYXRhNCRmYWtlX3F1YWwgPT0gIkJhZF9mYWtlIl0pDQpgYGANCg0KTm8gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gZ3JvdXBzIOKAlCBob21vZ2VuZWl0eSBvZiB2YXJpYW5jZXMgaXMgZmluZSBhbmQgdmFyaWFuY2VzIGFyZSBzaW1pbGFyIGVub3VnaCAocC12YWwuID0gMC4zNDE2KS4NCg0KIyMjIDIuMmIuIFR3byBzYW1wbGUgdC10ZXN0DQoNCmBgYHtyfQ0KdC50ZXN0KGRhdGE0JHBlcmNlbnRfY29ycmVjdCB+IGRhdGE0JGZha2VfcXVhbCkNCg0KI3QudGVzdChkYXRhNCRwZXJjZW50X2NvcnJlY3RfZmFrZX5kYXRhNCRwZXJjZW50X2NvcnJlY3RfcmVhbCkNCmBgYA0KDQpwLXZhbC4gPSAwLjAwMDAwMDAwMDAwMDAwMDIyLg0KDQojIyMgMi4yYy4gQU5PVkENCg0KYGBge3J9DQphb3YoZGF0YTQkcGVyY2VudF9jb3JyZWN0IH4gZGF0YTQkZmFrZV9xdWFsKSAlPiUgc3VtbWFyeSgpDQpgYGANCg0KcC12YWwuIDw9IDAuMDUuDQoNCiMjIyAyLjJkLiBBbnN3ZXINCg0KWWVzLCB0aGVyZSdzIGEgZGlmZmVyZW5jZSBvZiBgcGVyY2VudF9jb3JyZWN0YCBpbiBnb29kX2Zha2UgYW5kIGJhZF9mYWtlIGluIGBmYWtlX3F1YWxgLg0KDQojIyAzLiBXaGljaCBvZiB0aGUgZm9sbG93aW5nIHZhcmlhYmxlcyBzaWduaWZpY2FudGx5IHByZWRpY3Qgb3ZlcmFsbCBkZWVwZmFrZSBkZXRlY3Rpb24gYWNjdXJhY3k6IGNvbmZpZGVuY2UsIGluc3BlY3Rpb24gdGltZSwgZ2VuIEFJIHVzZSwgZ2VuIEFJIGltYWdlIHVzZSwgYW5kIGFnZT8NCg0KIlByZWRpY3QgKipvdmVyYWxsKiogZGVlcGZha2UgZGV0ZWN0aW9uIHBlcmZvcm1hbmNlIiA9IHBlcmNlbnRfY29ycmVjdC4NCg0KSVY6IG1lYW5fY29uZmlkZW5jZSwgaW5zcGVjdGlvbl90aW1lLCBBSV91c2UsIEFJX2ltZ191c2UsIGFnZQ0KDQpEVjogcGVyY2VudF9jb3JyZWN0DQoNCmBgYHtyfQ0KbW9kZWxfNC4xID0gbG0ocGVyY2VudF9jb3JyZWN0IH4gbWVhbl9jb25maWRlbmNlICsgaW5zcGVjdGlvbl90aW1lICsgQUlfdXNlKyBBSV9pbWdfdXNlKyBhZ2UsZGF0YTQpDQoNCmBgYA0KDQojIyMgMy4xYS4gQXNzdW1wdGlvbnMgY2hlY2sNCg0KIyMjIyBOb3JtYWxpdHkNCg0KYGBge3J9DQpwYXIobWZyb3cgPSBjKDIsMikpDQpwbG90KG1vZGVsXzQuMSkNCg0Kc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtb2RlbF80LjEpKQ0KDQpgYGANCg0KU2hhcGlybyB0ZXN0IHNob3dzIHZpb2xhdGlvbiwgYnV0IHBsb3Qgc2hvd3MgdGhleSBhcmVuJ3Qgc2V2ZXJlIGFuZCBsaW5lYXIgbW9kZWwgY291bGQgYmUgdXNlZC4gVXNlIGdlbmVyYWxpemVkIGxpbmVhciBtb2RlbCBpbnN0ZWFkIHRvIGFsbG93IGZvciBmbGV4aWJpbGl0eSBvZiBvdXRsaWVycy4NCg0KYGBge3J9DQpzdW1tYXJ5KGRhdGE0JHBlcmNlbnRfY29ycmVjdCkNCg0Kc2hhcGlyby50ZXN0KGRhdGE0JHBlcmNlbnRfY29ycmVjdCkNCg0KaGlzdChkYXRhNCRwZXJjZW50X2NvcnJlY3QpDQpgYGANCg0KYHBlcmNlbnRfY2hlY2tgIGFwcGVhcnMgdG8gYmUgYSBiaW1vZGFsIGRpc3RyaWJ1dGlvbi4NCg0KIyMjIDMuMWIuIFF1YXNpYmlub21pYWwgR0xNIA0KDQpgYGB7cn0NCmRhdGE1ID0gZGF0YTQgJT4lDQogIG11dGF0ZShwcm9wX3BlcmNlbnRfY29ycmVjdCA9IChwZXJjZW50X2NvcnJlY3QgKyAwLjAxKSAvIDEwMCkNCg0KI3RoaXMgbW9kZWwgcmVwbGFjZXMgbW9kZWxfNC4xDQpkYXRhNV9HTE0gPSBkYXRhNSAlPiUNCiAgbXV0YXRlKHByZWRpY3RlZCA9IHByZWRpY3QoZ2xtKHByb3BfcGVyY2VudF9jb3JyZWN0IH4gbWVhbl9jb25maWRlbmNlICsgaW5zcGVjdGlvbl90aW1lICsgQUlfdXNlICsgQUlfaW1nX3VzZSArIGFnZSwgZmFtaWx5ID0gcXVhc2liaW5vbWlhbCgpLCBkYXRhID0gZGF0YTUpLHR5cGUgPSAicmVzcG9uc2UiKSkNCmBgYA0KDQojIyMjIEZpdG5lc3MNCg0KYGBge3J9DQptb2RlbD1nbG0ocHJvcF9wZXJjZW50X2NvcnJlY3QgfiBtZWFuX2NvbmZpZGVuY2UgKyBpbnNwZWN0aW9uX3RpbWUgKyBBSV91c2UgKyBBSV9pbWdfdXNlICsgYWdlLA0KICAgICAgICAgICAgIGZhbWlseSA9IHF1YXNpYmlub21pYWwoKSwgZGF0YSA9IGRhdGE1KQ0KDQpkaXNwZXJzaW9uIDwtIHN1bShyZXNpZHVhbHMobW9kZWwsIHR5cGUgPSAiZGV2aWFuY2UiKV4yKSAvIG1vZGVsJGRmLnJlc2lkdWFsDQoNCnByaW50KGRpc3BlcnNpb24pDQoNCnBsb3QobW9kZWwkZml0dGVkLnZhbHVlcywgcmVzaWR1YWxzKG1vZGVsLCB0eXBlID0gImRldmlhbmNlIiksDQogICAgIHhsYWIgPSAiRml0dGVkIHZhbHVlcyIsIHlsYWIgPSAiRGV2aWFuY2UgcmVzaWR1YWxzIiwNCiAgICAgbWFpbiA9ICJSZXNpZHVhbHMgdnMgRml0dGVkIikNCmFibGluZShoID0gMCwgY29sID0gInJlZCIpDQoNCmBgYA0KDQpEaXNwZXJzaW9uIGlzIHdpdGhpbiBwYXJhbWV0ZXJzIChhbnl0aGluZyBvdmVyIDEgaW5kaWNhdGVzIG92ZXJkaXNwZXJzaW9uKS4gUGxvdCBzaG93cyBsaW5lIHN0cmFpZ2h0IGFuZCBuZWFyaW5nIDAuDQoNCkdpdmVuIHRoYXQgYHBlcmNlbnRfY29ycmVjdGAgaXMgYSBwcm9wb3J0aW9uIGFuZCBpcyBiaW1vZGFsbHkgZGlzdHJpYnV0ZWQsIHVzZSBxdWFzaWJpbm9taWFsIEdMTS4NCg0KYGBge3J9DQpkYXRhNV9HTE1fbW9kZWwgPSBnbG0ocHJvcF9wZXJjZW50X2NvcnJlY3QgfiBtZWFuX2NvbmZpZGVuY2UgKyBpbnNwZWN0aW9uX3RpbWUgKyBBSV91c2UgKyBBSV9pbWdfdXNlICsgYWdlLGZhbWlseSA9IHF1YXNpYmlub21pYWwoKSwgZGF0YTVfR0xNKQ0KDQpzdW1tYXJ5KGRhdGE1X0dMTV9tb2RlbCkNCmBgYA0KDQojIyMjIFNjYXR0ZXIgcGxvdCBvZiBtb2RlbA0KDQpgYGB7cn0NCmdncGxvdChkYXRhNV9HTE0sIGFlcyh4ID0gbWVhbl9jb25maWRlbmNlLCB5ID1wcm9wX3BlcmNlbnRfY29ycmVjdCkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBwcmVkaWN0ZWQpLCBjb2xvciA9ICJyZWQiLCBzaXplID0gLjUpICsNCiAgbGFicyh0aXRsZSA9ICJQcmVkaWN0ZWQgcGVyY2VudF9jb3JyZWN0IGJ5IG1lYW5fY29uZmlkZW5jZSIpICsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IC41KSkNCg0KZ2dwbG90KGRhdGE1X0dMTSwgYWVzKHggPSBtZWFuX2NvbmZpZGVuY2UsIHkgPXByb3BfcGVyY2VudF9jb3JyZWN0KSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC42KSArDQogIGdlb21fbGluZShhZXMoeSA9IHByZWRpY3RlZCksIGNvbG9yID0gInJlZCIsIHNpemUgPSAuNSkgKw0KICBsYWJzKHRpdGxlID0gIlByZWRpY3RlZCBwZXJjZW50X2NvcnJlY3QgYnkgbWVhbl9jb25maWRlbmNlIGZhY2V0ZWQgYnkgQUlfdXNlIikgKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLjUpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLjUpKSsNCiAgZmFjZXRfd3JhcCh+QUlfdXNlKQ0KDQpgYGANCg0KIyMjIDMuMWMuIEFuc3dlcg0KDQpgbWVhbl9jb25maWRlbmNlYCAocC12YWwuID0gMC4wMDAwMDAwMDAwMDAwNjIyKSBoYWQgYSBwb3NpdGl2ZSBpbXBhY3Qgb24gYHBlcmNlbnRfY29ycmVjdGAgd2hpbGUgYGFnZWAgKHAtdmFsLiA9IDAuMDEwNSkgaGFkIGEgbmVnYXRpdmUgaW1wYWN0IG9uIGBwZXJjZW50X2NvcnJlY3RgLiBgQUlfdXNlYCBzaG93ZWQgbmVhciBzaWduaWZpY2FuY2UsIGJ1dCBub3QgcXVpdGUgZW5vdWdoLiBMb29raW5nIGF0IHRoZSBzcGxpdCBzY2F0dGVyIHBsb3QgYWJvdmUsIGBBSV91c2VgIG9mIDMgYXBwZWFycyBkaWZmZXJlbnQgZnJvbSB0aGUgb3RoZXIgZ3JvdXBzLg0KDQpIaWdoZXIgY29uZmlkZW5jZSBjb3JyZWxhdGVzIHdpdGggaGlnaGVyIGFjY3VyYWN5LCB3aGVyZWFzIG9sZGVyIGFnZSBzaG93ZWQgbGVzcyBhY2N1cmFjeSBpbiBkZWVwZmFrZSBkZXRlY3Rpb24uDQoNCiMjIDQuIFdoaWNoIG9mIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzIC0gaW5zcGVjdGlvbiB0aW1lLCBnZW4gQUkgdXNlLCBnZW4gQUkgaW1hZ2UgdXNlLCBhbmQgYWdlIC0gcHJlZGljdCBvdmVyYWxsIGRlZXBmYWtlIGRldGVjdGlvbiBwZXJmb3JtYW5jZSwgb3ZlciBhbmQgYWJvdmUgKGkuZS4gY29udHJvbGxpbmcgZm9yKSBjb25maWRlbmNlPw0KDQoiUHJlZGljdCAqKm92ZXJhbGwqKiBkZWVwZmFrZSBkZXRlY3Rpb24gcGVyZm9ybWFuY2UiID0gcGVyY2VudF9jb3JyZWN0LiBDcmVhdGUgdHdvIG1vZGVscyB0byBjb21wYXJlIHRoZW0gYWdhaW5zdCBlYWNoIG90aGVyLiBPbmUgbW9kZWwgaXMgdGhlIGNvbnRyb2wgYW5kIHRoZSBvdGhlciBpcyB0aGUgbWFuaXB1bGF0aW9uLg0KDQpJVjogbWVhbl9jb25maWRlbmNlLCBpbnNwZWN0aW9uX3RpbWUsIEFJX3VzZSwgQUlfaW1nX3VzZSwgYWdlDQoNCkRWOiBwZXJjZW50X2NvcnJlY3QNCg0KYGBge3J9DQojYmFzZSBtb2RlbCB0byBjb250cm9sIGZvciBjb25maWRlbmNlDQpkYXRhNV9iYXNlID0gbG0ocGVyY2VudF9jb3JyZWN0IH4gbWVhbl9jb25maWRlbmNlLGRhdGE1KQ0KDQojYWRkIElWcyBmb3IgbWFuaXB1bGF0aW9uDQpkYXRhNV9hZGRpdGlvbmFsPSBsbShwZXJjZW50X2NvcnJlY3QgfiBtZWFuX2NvbmZpZGVuY2UgKyBpbnNwZWN0aW9uX3RpbWUgKyBBSV91c2UgKyBBSV9pbWdfdXNlICsgYWdlLCBkYXRhNSkNCmBgYA0KDQojIyMgNC4xYSBBc3N1bXB0aW9ucyBjaGVjaw0KDQojIyMjIEZpdG5lc3MNCg0KYGBge3J9DQpwYXIobWZyb3cgPSBjKDIsMikpDQpwbG90KGRhdGE1X2Jhc2UsbWFpbj0nYmFzZSBtb2RlbCcpDQoNCnBhcihtZnJvdyA9IGMoMiwyKSkNCnBsb3QoZGF0YTVfYWRkaXRpb25hbCxtYWluPSdhZGRpdGlvbmFsIG1vZGVsJykNCmBgYA0KDQpTb21lIG1pbGRuZXNzIGluIFJlc2lkdWFscyB2cyBGaXR0ZWQsIGJ1dCBub3RoaW5nIHNldmVyZS4NCg0KIyMjIyBNdWx0aWNvbGxpbmVhcml0eQ0KDQpgYGB7cn0NCmRhdGE1X2Nvcl9tYXRyaXggPSBkYXRhNSAlPiUNCiAgc2VsZWN0KG1lYW5fY29uZmlkZW5jZSwgaW5zcGVjdGlvbl90aW1lLCBBSV91c2UsQUlfaW1nX3VzZSwgYWdlKSAlPiUNCiAgY29yKHVzZSA9ICJjb21wbGV0ZS5vYnMiKQ0KDQpkYXRhNV9jb3JfcGxvdCA9IGFzLmRhdGEuZnJhbWUoYXMudGFibGUoZGF0YTVfY29yX21hdHJpeCkpDQoNCmdncGxvdChkYXRhNV9jb3JfcGxvdCwgYWVzKFZhcjEsIFZhcjIsIGZpbGwgPSBGcmVxKSkgKw0KICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChGcmVxLCAyKSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDQpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBtaWQgPSAid2hpdGUiLCBoaWdoID0gInJlZCIsIG1pZHBvaW50ID0gMCkgKw0KICBsYWJzKHRpdGxlID0gIkNvcnJlbGF0aW9uIG9mIElWcyIsDQogICAgICAgeCA9ICIiLCB5ID0gIiIsIGZpbGwgPSAiQ29ycmVsYXRpb24gJSIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAuNSkpDQoNCmBgYA0KDQpWYWx1ZXMgbm90ID49IDAuNzAgb3IgPD0gLTAuNzAgbWVhbnMgbXVsdGljb2xsaW5lYXJpdHkgaXNuJ3QgdmlvbGF0ZWQuIFByb2NlZWQgd2l0aCBoaWVyYXJjaGljYWwgcmVncmVzc2lvbi4NCg0KIyMjIDQuMWIuIEhpZXJhcmNoaWNhbCByZWdyZXNzaW9uDQoNCmBgYHtyfQ0KYW5vdmEoZGF0YTVfYmFzZSxkYXRhNV9hZGRpdGlvbmFsKSAlPiUgcHJpbnQoKQ0KDQpzdW1tYXJ5KGRhdGE1X2FkZGl0aW9uYWwpDQoNCmBgYA0KDQpUaGUgcC12YWwuID0gMC4wMDAwMDAwMDAwMDA0NjI2IHNob3dzIHRoYXQgdGhpcyBtb2RlbCBpcyBzaWduaWZpY2FudCwgYW5kIHRoYXQgdGhlIGFkanVzdGVkIFItc3F1YXJlZCBzaG93cyAzNi45JSBvZiB0aGUgdmFyaWFuY2UgaW4gYHBlcmNlbnRfY29ycmVjdGAgY2FuIGJlIGV4cGxhaW5lZCBieSB0aGUgSVZzLg0KDQpgbWVhbl9jb25maWRlbmNlYCAocC12YWwuID0gMC4wMDAwMDAwMDAwMDAwMDI0NykgYW5kIGBhZ2VgIChwLXZhbC4gPSAwLjAxMDcpIHNob3dlZCBzaWduaWZpY2FuY2UuIGBtZWFuX2NvbmZpZGVuY2VgIHdpdGggYHBlcmNlbnRfY29ycmVjdGAgaXMgMjIuMDEwMTY0IHdoaWxlIGBhZ2VgIHdpdGggYHBlcmNlbnRfY29ycmVjdGAgaXMgLTAuMTMzODI4LiBUaGlzIG1lYW5zIGVhY2ggcG9pbnQgb2YgYG1lYW5fY29uZmlkZW5jZWAgaW5jcmVhc2VkIGFjY3VyYWN5IGJ5IDIyLCB3aGlsZSBlYWNoIHBvaW50IG9mIGBhZ2VgIGRlY3JlYXNlZCBhY2N1cmFjeSBieSAwLjEzLg0KDQojIyMgNC4xYy4gQW5zd2VyDQoNCkFkZGluZyBgYWdlYCB3aXRoIGBtZWFuX2NvbmZpZGVuY2VgIHNpZ25pZmljYW50bHkgaW1wcm92ZXMgdGhlIG1vZGVsIGZvciBwcmVkaWN0aW5nIGBwZXJjZW50X2NvcnJlY3RgLiBUaGUgb3RoZXIgSVZzIHNob3dlZCBubyBpbXBhY3QsIHdoaWxlIGBBSV91c2VgIHdhcyBuZWFyIHNpZ25pZmljYW5jZS4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpgYGB7ciBpbmNsdWRlPUZ9DQojYmVlcCB3aGVuIGRvbmUNCmlmIChyZXF1aXJlKCJiZWVwciIpKQ0KICBiZWVwcjo6YmVlcCgyKQ0KYGBg