1 The sore throat dataset

The sore throat dataset contains results of a study on throat soarness upon surgery with general anaesthesia. The variable sore encodes whether a patient experienced a sore throat on waking (0: no, 1: yes) as a function of the duration of the surgery (duration) in minutes and the type of device (variable type) used to secure the airway: laryngeal mask (“mask”) or tracheal tube (“tube”) (Data taken from Agresti 2002).

2 Goals

  • Explore the dataset
  • Fit a logit model using “type” and interpret the parameter estimate
  • Fit a logit model considering all predictors, interpret parameter estimates, and conduct inference about the effects.

This file contains many details for explaining the models to students. We do not expect that reports are this extensive. I.e. a report on the exercise typically would contain as much information as in the soreBase rmarkdown file.

library(tidyverse)
library(car)

3 Import data

sore <- read_csv("https://raw.githubusercontent.com/GTPB/PSLS20/master/data/sore.csv")
head(sore)
## # A tibble: 6 x 3
##   duration type   sore
##      <dbl> <chr> <dbl>
## 1       45 mask      0
## 2       15 mask      0
## 3       40 mask      1
## 4       83 tube      1
## 5       90 tube      1
## 6       25 tube      1
## set the type and sore variables as factors
sore <- sore %>%
  mutate(type = as.factor(type), sore = as.factor(sore))

4 Data Exploration

table(sore[,c("type","sore")])
##       sore
## type    0  1
##   mask  4 14
##   tube  9  8
plot(as.double(sore)~duration,pch=as.double(type),col=as.double(type), data=sore)
legend("bottomright",pch=1:2,col=1:2,legend=levels(sore$type))

5 Analysis: logistic regression

5.1 Type variable as only predictor

fitType=glm(sore~type,data=sore,family=binomial)
#inference/interpretation
summary(fitType)
## 
## Call:
## glm(formula = sore ~ type, family = binomial, data = sore)
## 
## Deviance Residuals: 
##    Min      1Q  Median      3Q     Max  
## -1.734  -1.128   0.709   0.709   1.228  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)  
## (Intercept)   1.2528     0.5669   2.210   0.0271 *
## typetube     -1.3705     0.7467  -1.836   0.0664 .
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 46.180  on 34  degrees of freedom
## Residual deviance: 42.578  on 33  degrees of freedom
## AIC: 46.578
## 
## Number of Fisher Scoring iterations: 4
confint(fitType)
## Waiting for profiling to be done...
##                  2.5 %     97.5 %
## (Intercept)  0.2275566 2.51346332
## typetube    -2.9292777 0.04379487
anova(fitType,test="LRT")
## Analysis of Deviance Table
## 
## Model: binomial, link: logit
## 
## Response: sore
## 
## Terms added sequentially (first to last)
## 
## 
##      Df Deviance Resid. Df Resid. Dev Pr(>Chi)  
## NULL                    34     46.180           
## type  1   3.6022        33     42.578   0.0577 .
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Interpretation of the model coefficients:

14/4 # odds on sore throat when wearing mask
## [1] 3.5
exp(fitType$coef[1]) # odds on sore throat when wearing mask
## (Intercept) 
##         3.5
8/9 # odds on sore throat when having tube
## [1] 0.8888889
exp(fitType$coef[1]+fitType$coef[2]) # odds on sore throat when having tube
## (Intercept) 
##   0.8888889
(8/9)/(14/4) # odds ration type
## [1] 0.2539683
exp(fitType$coef[2]) # odds ration type
##  typetube 
## 0.2539683

Note that the model above did not account for differences in the duration of the treatment.

5.2 Model Selection

We first will fit a model with a main effects for type, duration and a type x duration interaction.

fitTypeDurationInt=glm(sore~type*duration,data=sore,family=binomial)
summary(fitTypeDurationInt,cor=TRUE)
## 
## Call:
## glm(formula = sore ~ type * duration, family = binomial, data = sore)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.9707  -0.3779   0.3448   0.7292   1.9961  
## 
## Coefficients:
##                   Estimate Std. Error z value Pr(>|z|)  
## (Intercept)        0.04979    1.46940   0.034   0.9730  
## typetube          -4.47224    2.46707  -1.813   0.0699 .
## duration           0.02848    0.03429   0.831   0.4062  
## typetube:duration  0.07460    0.05777   1.291   0.1966  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 46.180  on 34  degrees of freedom
## Residual deviance: 28.321  on 31  degrees of freedom
## AIC: 36.321
## 
## Number of Fisher Scoring iterations: 6
## 
## Correlation of Coefficients:
##                   (Intercept) typetube duration
## typetube          -0.60                        
## duration          -0.92        0.55            
## typetube:duration  0.55       -0.91    -0.59
Anova(fitTypeDurationInt,test="LR",type=3)
## Analysis of Deviance Table (Type III tests)
## 
## Response: sore
##               LR Chisq Df Pr(>Chisq)  
## type            3.9458  1    0.04699 *
## duration        0.8069  1    0.36904  
## type:duration   1.8169  1    0.17768  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

We can also fit the model without the interaction effect:

fitTypeDurationNoInt=glm(sore~type+duration,data=sore,family=binomial)
summary(fitTypeDurationNoInt,cor=TRUE)
## 
## Call:
## glm(formula = sore ~ type + duration, family = binomial, data = sore)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.3802  -0.5358   0.3047   0.7308   1.7821  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)   
## (Intercept) -1.41734    1.09457  -1.295  0.19536   
## typetube    -1.65895    0.92285  -1.798  0.07224 . 
## duration     0.06868    0.02641   2.600  0.00931 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 46.180  on 34  degrees of freedom
## Residual deviance: 30.138  on 32  degrees of freedom
## AIC: 36.138
## 
## Number of Fisher Scoring iterations: 5
## 
## Correlation of Coefficients:
##          (Intercept) typetube
## typetube -0.25               
## duration -0.83       -0.16
Anova(fitTypeDurationNoInt,test="LR",type=3)
## Analysis of Deviance Table (Type III tests)
## 
## Response: sore
##          LR Chisq Df Pr(>Chisq)    
## type       3.5134  1  0.0608744 .  
## duration  12.4396  1  0.0004203 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
confint(fitTypeDurationNoInt)
## Waiting for profiling to be done...
##                   2.5 %     97.5 %
## (Intercept) -3.80786158 0.61635531
## typetube    -3.64627873 0.07434058
## duration     0.02547651 0.13216711

We assessed the significance of the different covariates in the model by using a likelihood ratio tests (Anova function in R) because the p-values are more accurate than the p-values of the Wald-tests (summary function in R). The interaction between type and duration is not significant (p=0.177). Hence the interaction term can be removed from the model. In the model with main effects for type and duration, the duration effect is extremely significant (p$<$0.001). The effect of type is not significant (p=0.061). However, since the effect of type is close to being statistically significant we will leave it in the model so as to estimate a “pure” effect for duration. If we remove type from the model and if the effect truly exists but there was not enough power for detecting it, then removing the type from the model might result in a biased parameter estimate for duration as it might captures a part of the effect of type.

6 Interpretation of the different models

6.1 Model Type

# Model 1 only type
plot(sore~duration,pch=as.double(type),col=type,data=sore,main="Type",xlim=c(0,120))
## Warning in spineplot.default(x, y, ...): x axis is on a cumulative probability
## scale, 'xlim' must be in [0,1]
legend("bottomright",pch=c(1:2,NA,NA),lty=c(0,0,1,1),col=c(1,2,1,2),legend=rep(levels(sore$type),2))

#construct new data to make a nice plot (predict data using the model)
x=seq(0,120,1)

#use type response in order to predict probabilities
newdataMask=data.frame(duration=x,type=factor("mask",levels=levels(sore$type)))
yPredMask=predict(fitType,newdataMask,type="response")
lines(x,yPredMask)

#use type response in order to predict probabilities
newdataTube=data.frame(duration=x,type=factor("tube",levels=levels(sore$type)))
yPredTube=predict(fitType,newdataTube,type="response")
lines(x,yPredTube,col=2)

The model for the log odds on a sore throat after surgery in function of anaesthesia type is given:

\[ \log \text{Odds}_i=\beta_0+\beta_\text{tube}x_\text{tube,i} \]

with \(x_\text{tube,i}=0\) when the patient was anaesthesized with a mask and \(x_\text{tube,i}=1\) when a tube was used. Based on this model we can estimate the log odds on a sore throat after surgery when wearing a mask with

\[ \log \widehat{\text{Odds}}^\text{mask}=\hat \beta_0. \]

Hence, the intercept has the interpretation of the log odds on a sore throat after a surgery with mask anaesthesia. The logg odds on a sore throat after a surgery with a tube is estimated as

\[ \log \widehat{\text{Odds}}^\text{tube}=\hat \beta_0+\hat\beta_{tube}. \]

The log odds ratio on a sore throat between tube and mask can then be estimated as:

\[ \log \widehat{\text{Odds}}^\text{tube}-\log \widehat{\text{Odds}}^\text{mask}=\hat \beta_0+\hat\beta_{tube}-\hat\beta_{0}=\hat\beta_\text{tube}. \]

Hence, the slope for the dummy variable tube has the interpretation of the log odds ratio on a sore throat between tube and mask.

Interpretation based on the parameter estimates: The probability on a sore throat when wearing a mask is on average 3.5 times higher than the probability to wake up from surgery without a sore throat when wearing a mask (95% CI [1.3,12.3]). The odds on a sore throat after surgery with anaesthesia using a tube is on average 4 times smaller than the odds with a mask, but this odds ratio is not statistically significant ( 95% CI [0.05,1.04]).

6.2 Model Duration

fitDuration=glm(sore~duration,data=sore,family=binomial)
summary(fitDuration,cor=TRUE)
## 
## Call:
## glm(formula = sore ~ duration, family = binomial, data = sore)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.0964  -0.7392   0.3020   0.8711   1.3753  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)   
## (Intercept) -2.21358    0.99874  -2.216  0.02667 * 
## duration     0.07038    0.02667   2.639  0.00831 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 46.180  on 34  degrees of freedom
## Residual deviance: 33.651  on 33  degrees of freedom
## AIC: 37.651
## 
## Number of Fisher Scoring iterations: 5
## 
## Correlation of Coefficients:
##          (Intercept)
## duration -0.91
Anova(fitDuration,test="LR",type=3)
## Analysis of Deviance Table (Type III tests)
## 
## Response: sore
##          LR Chisq Df Pr(>Chisq)    
## duration   12.528  1  0.0004008 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
confint(fitDuration)
## Waiting for profiling to be done...
##                   2.5 %     97.5 %
## (Intercept) -4.45076704 -0.4359574
## duration     0.02639986  0.1334656
plot(sore~duration,pch=as.double(type),col=type,data=sore,main="Type",xlim=c(0,120))
## Warning in spineplot.default(x, y, ...): x axis is on a cumulative probability
## scale, 'xlim' must be in [0,1]
legend("bottomright",pch=c(1:2,NA,NA),lty=c(0,0,1,1),col=c(1,2,1,2),legend=rep(levels(sore$type),2))

#construct new data to make a nice plot (predict data using the model)
x=seq(0,120,1)

#use type response in order to predict probabilities
newdataMask=data.frame(duration=x,type=factor("mask",levels=levels(sore$type)))
yPredMask=predict(fitDuration,newdataMask,type="response")
lines(x,yPredMask)

#use type response in order to predict probabilities
newdataTube=data.frame(duration=x,type=factor("tube",levels=levels(sore$type)))
yPredTube=predict(fitDuration,newdataTube,type="response")
lines(x,yPredTube,col=2)

The model for the log odds on a sore throat after surgery in function of the surgery time can be denoted as: \[ \log \text{Odds}_i=\beta_0+\beta_\text{time}t_\text{i} \]

Then the intercept has the interpretation of the odds on a sore throat when the surgery took \(t=0\) minutes. Note, that this parameter does not have a useful interpretation in practice. Moreover, it also involves an extrapolation. The intercept in a model were the time is centered, however, has a different interpretation: it is the odds on a sore throat when the surgery took 48.0 minutes, i.e. the average duration of surgery in the dataset.

The odds on a surgery that took 30 minutes can be estimated as:

\[ \log \text{Odds}^{30min}=\beta_0+\beta_\text{time}30 \]

and the odds on a surgery that took 31 minutes can be estimated as:

\[ \log \widehat{\text{Odds}}^{31min}=\beta_0+\hat \beta_\text{time}31, \]

hence the slope \(\beta_\text{time}\) has the interpretation of the log odds ratio between surgeries with a one minute difference in duration.

6.3 Model Type + Duration

plot(sore~duration,pch=as.double(type),col=type,data=sore,main="Type",xlim=c(0,120))
## Warning in spineplot.default(x, y, ...): x axis is on a cumulative probability
## scale, 'xlim' must be in [0,1]
legend("bottomright",pch=c(1:2,NA,NA),lty=c(0,0,1,1),col=c(1,2,1,2),legend=rep(levels(sore$type),2))

#construct new data to make a nice plot (predict data using the model)
x=seq(0,120,1)

#use type response in order to predict probabilities
newdataMask=data.frame(duration=x,type=factor("mask",levels=levels(sore$type)))
yPredMask=predict(fitTypeDurationNoInt,newdataMask,type="response")
lines(x,yPredMask)

#use type response in order to predict probabilities
newdataTube=data.frame(duration=x,type=factor("tube",levels=levels(sore$type)))
yPredTube=predict(fitTypeDurationNoInt,newdataTube,type="response")
lines(x,yPredTube,col=2)

summary(fitTypeDurationNoInt)
## 
## Call:
## glm(formula = sore ~ type + duration, family = binomial, data = sore)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.3802  -0.5358   0.3047   0.7308   1.7821  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)   
## (Intercept) -1.41734    1.09457  -1.295  0.19536   
## typetube    -1.65895    0.92285  -1.798  0.07224 . 
## duration     0.06868    0.02641   2.600  0.00931 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 46.180  on 34  degrees of freedom
## Residual deviance: 30.138  on 32  degrees of freedom
## AIC: 36.138
## 
## Number of Fisher Scoring iterations: 5

The model for the log odds on a sore throat after surgery with a main effect for surgery time and type can be written as:

\[ \log \text{Odds}_i=\beta_0+\beta_\text{tube}x_\text{tube}+\beta_\text{time}t_i \]

  • The intercept has the interpretation of the log odds on a sore throat for patients that were anaesthetised with a mask (\(x_\text{tube}=0\)) and that had surgery that had a duration of 0 minutes (\(t=0\)). Again this log odds does not have a useful interpretation.

  • The slope for tube again has the interpretation of the log odds ratio on a sore throat between groups of patients that were anaesthetised with tubes vs masks and got a surgery with the same duration. This can be rephrased as the log odds ratio on a sore throat between groups of patients that were anaesthetised with tubes vs groups of patients masks after correcting for the duration of the surgery. (This will result in a shift of the curve between patients with mask and tubes.)

  • The slope for time has the interpretation of the log odds ratio on a sore throat between groups of patients that had surgery with a one minute duration difference and were anaesthetised with the same type, i.e. the log odds ratio on a sore throat between groups of patients that had surgery with a one minute duration difference after correction for the anaesthesia type.

6.4 Model Type x Duration

plot(sore~duration,pch=as.double(type),col=type,data=sore,main="Type",xlim=c(0,120))
## Warning in spineplot.default(x, y, ...): x axis is on a cumulative probability
## scale, 'xlim' must be in [0,1]
legend("bottomright",pch=c(1:2,NA,NA),lty=c(0,0,1,1),col=c(1,2,1,2),legend=rep(levels(sore$type),2))

#construct new data to make a nice plot (predict data using the model)
x=seq(0,120,1)

#use type response in order to predict probabilities
newdataMask=data.frame(duration=x,type=factor("mask",levels=levels(sore$type)))
yPredMask=predict(fitTypeDurationInt,newdataMask,type="response")
lines(x,yPredMask)

#use type response in order to predict probabilities
newdataTube=data.frame(duration=x,type=factor("tube",levels=levels(sore$type)))
yPredTube=predict(fitTypeDurationInt,newdataTube,type="response")
lines(x,yPredTube,col=2)

summary(fitTypeDurationInt)
## 
## Call:
## glm(formula = sore ~ type * duration, family = binomial, data = sore)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.9707  -0.3779   0.3448   0.7292   1.9961  
## 
## Coefficients:
##                   Estimate Std. Error z value Pr(>|z|)  
## (Intercept)        0.04979    1.46940   0.034   0.9730  
## typetube          -4.47224    2.46707  -1.813   0.0699 .
## duration           0.02848    0.03429   0.831   0.4062  
## typetube:duration  0.07460    0.05777   1.291   0.1966  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 46.180  on 34  degrees of freedom
## Residual deviance: 28.321  on 31  degrees of freedom
## AIC: 36.321
## 
## Number of Fisher Scoring iterations: 6

The model for the log odds on a sore throat after surgery with a main effect for surgery time and type and a time-type interaction is given by:

\[ \log \text{Odds}_i=\beta_0+\beta_\text{tube}x_\text{tube}+\beta_\text{time}t_i+\beta_\text{time-tube}x_\text{tube,i}t_i \]

Hence, for patients with a mask the odds can be predicted in function of time by

\[ \log \text{Odds}^\text{mask}=\beta_0+\beta_\text{time}t \]

and the odds on a sore throat for patients that were anaesthetised with a tube in function of time by

\[ \log \text{Odds}^\text{tube}=\beta_0+\beta_\text{tube}+(\beta_\text{time}+\beta_\text{time-tube})t \]

  • The intercept \(\beta_0\) is again the log odds on a sore throat for patients that were anaesthetised with a mask (\(x_\text{tube}=0\)) and that had surgery that had a duration of 0 minutes (\(t=0\)).

  • The slope \(\beta_\text{tube}\) has the interpretation of the log odds ratio on a sore throat for patients that were anaesthetised with a tube (\(x_\text{tube}=0\)) vs patients that were anaesthetised with a mask and that had surgery that had a duration of 0 minutes (\(t=0\)). Again these two parameters do not have a useful interpretation.

  • The parameter \(\beta_\text{time}\) has the interpretation of the log odds ratio on a sore throat between groups of patients that had surgery with a one minute duration difference and were anaesthetised with mask.

  • The parameter \(\beta_\text{time-tube}\) allows for a different log odds ratio on a sore throat for patients that had surgery with a one minute duration difference in groups of patients that were anaesthetised with a tube than that within patient groups with a mask, i.e. it allows for a different odds profile in function of time for patients with a tube than for patients with a mask.

7 Conclusion

The effect of the duration of surgery on the odds on a sore throat is extremely significant (p<0.001). If the time of surgery increases, patients have a higher probability to wake up with a sore throat. The odds ratio for a one minute increase in surgery duration is 1.07 (95% CI [1.03,1.14]). There is no significant interaction between the type of anaesthesia and duration of the surgery (p=0.117). While there is some evidence in the data suggesting that the use of a tube is beneficial, i.e. the odds on a sore throat is more than a factor of 5 lower when using an anaesthesia with a tube than with a mask (OR=0.19, 95% CI [0.02,1.08]), the latter effect is not statistically significant (p=0.061).

LS0tCnRpdGxlOiAiVHV0b3JpYWwgMTAuMjogTG9naXN0aWMgcmVncmVzc2lvbiBvbiB0aGUgc29yZSB0aHJvYXQgZGF0YXNldCIgICAKb3V0cHV0OgogICAgaHRtbF9kb2N1bWVudDoKICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZSAgICAKICAgICAgdGhlbWU6IGNvc21vCiAgICAgIHRvYzogdHJ1ZQogICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKLS0tCgoKIyBUaGUgc29yZSB0aHJvYXQgZGF0YXNldAoKVGhlIHNvcmUgdGhyb2F0IGRhdGFzZXQgY29udGFpbnMgcmVzdWx0cyBvZiBhIHN0dWR5IG9uIHRocm9hdCBzb2FybmVzcyB1cG9uIHN1cmdlcnkgd2l0aCBnZW5lcmFsIGFuYWVzdGhlc2lhLiAgVGhlIHZhcmlhYmxlIHNvcmUgZW5jb2RlcyB3aGV0aGVyIGEgcGF0aWVudCBleHBlcmllbmNlZCBhIHNvcmUgdGhyb2F0IG9uIHdha2luZyAoMDogbm8sIDE6IHllcykgIGFzIGEgZnVuY3Rpb24gb2YgdGhlIGR1cmF0aW9uIG9mIHRoZSBzdXJnZXJ5IChkdXJhdGlvbikgaW4gbWludXRlcyBhbmQgdGhlIHR5cGUgb2YgZGV2aWNlICh2YXJpYWJsZSB0eXBlKSB1c2VkIHRvIHNlY3VyZSB0aGUgYWlyd2F5OiBsYXJ5bmdlYWwgbWFzayAoIm1hc2siKSBvciB0cmFjaGVhbCB0dWJlICgidHViZSIpIChEYXRhIHRha2VuIGZyb20gQWdyZXN0aSAyMDAyKS4KCiMgR29hbHMKCi0gRXhwbG9yZSB0aGUgZGF0YXNldAotIEZpdCBhIGxvZ2l0IG1vZGVsIHVzaW5nICJ0eXBlIiBhbmQgaW50ZXJwcmV0IHRoZSBwYXJhbWV0ZXIgZXN0aW1hdGUKLSBGaXQgYSBsb2dpdCBtb2RlbCBjb25zaWRlcmluZyBhbGwgcHJlZGljdG9ycywgaW50ZXJwcmV0IHBhcmFtZXRlciBlc3RpbWF0ZXMsIGFuZCBjb25kdWN0IGluZmVyZW5jZSBhYm91dCB0aGUgZWZmZWN0cy4KClRoaXMgZmlsZSBjb250YWlucyBtYW55IGRldGFpbHMgZm9yIGV4cGxhaW5pbmcgdGhlIG1vZGVscyB0byBzdHVkZW50cy4gV2UgZG8gbm90IGV4cGVjdCB0aGF0IHJlcG9ydHMgYXJlIHRoaXMgZXh0ZW5zaXZlLiBJLmUuIGEgcmVwb3J0IG9uIHRoZSBleGVyY2lzZSB0eXBpY2FsbHkgd291bGQgY29udGFpbiBhcyBtdWNoIGluZm9ybWF0aW9uIGFzIGluIHRoZSBzb3JlQmFzZSBybWFya2Rvd24gZmlsZS4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShjYXIpCmBgYAoKIyBJbXBvcnQgZGF0YQoKYGBge3IsIG1lc3NhZ2UgPUZBTFNFfQpzb3JlIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vR1RQQi9QU0xTMjAvbWFzdGVyL2RhdGEvc29yZS5jc3YiKQpoZWFkKHNvcmUpCmBgYAoKYGBge3J9CiMjIHNldCB0aGUgdHlwZSBhbmQgc29yZSB2YXJpYWJsZXMgYXMgZmFjdG9ycwpzb3JlIDwtIHNvcmUgJT4lCiAgbXV0YXRlKHR5cGUgPSBhcy5mYWN0b3IodHlwZSksIHNvcmUgPSBhcy5mYWN0b3Ioc29yZSkpCmBgYAoKIyBEYXRhIEV4cGxvcmF0aW9uCgpgYGB7cn0KdGFibGUoc29yZVssYygidHlwZSIsInNvcmUiKV0pCmBgYAoKYGBge3J9CnBsb3QoYXMuZG91YmxlKHNvcmUpfmR1cmF0aW9uLHBjaD1hcy5kb3VibGUodHlwZSksY29sPWFzLmRvdWJsZSh0eXBlKSwgZGF0YT1zb3JlKQpsZWdlbmQoImJvdHRvbXJpZ2h0IixwY2g9MToyLGNvbD0xOjIsbGVnZW5kPWxldmVscyhzb3JlJHR5cGUpKQpgYGAKCgojIEFuYWx5c2lzOiBsb2dpc3RpYyByZWdyZXNzaW9uCgojIyBUeXBlIHZhcmlhYmxlIGFzIG9ubHkgcHJlZGljdG9yCgpgYGB7cn0KZml0VHlwZT1nbG0oc29yZX50eXBlLGRhdGE9c29yZSxmYW1pbHk9Ymlub21pYWwpCiNpbmZlcmVuY2UvaW50ZXJwcmV0YXRpb24Kc3VtbWFyeShmaXRUeXBlKQpjb25maW50KGZpdFR5cGUpCmFub3ZhKGZpdFR5cGUsdGVzdD0iTFJUIikKYGBgCgpJbnRlcnByZXRhdGlvbiBvZiB0aGUgbW9kZWwgY29lZmZpY2llbnRzOgoKYGBge3J9CjE0LzQgIyBvZGRzIG9uIHNvcmUgdGhyb2F0IHdoZW4gd2VhcmluZyBtYXNrCmV4cChmaXRUeXBlJGNvZWZbMV0pICMgb2RkcyBvbiBzb3JlIHRocm9hdCB3aGVuIHdlYXJpbmcgbWFzawoKOC85ICMgb2RkcyBvbiBzb3JlIHRocm9hdCB3aGVuIGhhdmluZyB0dWJlCmV4cChmaXRUeXBlJGNvZWZbMV0rZml0VHlwZSRjb2VmWzJdKSAjIG9kZHMgb24gc29yZSB0aHJvYXQgd2hlbiBoYXZpbmcgdHViZQoKKDgvOSkvKDE0LzQpICMgb2RkcyByYXRpb24gdHlwZQpleHAoZml0VHlwZSRjb2VmWzJdKSAjIG9kZHMgcmF0aW9uIHR5cGUKYGBgCgpOb3RlIHRoYXQgdGhlIG1vZGVsIGFib3ZlIGRpZCBub3QgYWNjb3VudCBmb3IgZGlmZmVyZW5jZXMgaW4gdGhlIGR1cmF0aW9uIG9mIHRoZSB0cmVhdG1lbnQuCgojIyBNb2RlbCBTZWxlY3Rpb24KCldlIGZpcnN0IHdpbGwgZml0IGEgbW9kZWwgd2l0aCBhIG1haW4gZWZmZWN0cyBmb3IgdHlwZSwgZHVyYXRpb24gYW5kIGEgdHlwZSB4IGR1cmF0aW9uIGludGVyYWN0aW9uLgoKYGBge3J9CmZpdFR5cGVEdXJhdGlvbkludD1nbG0oc29yZX50eXBlKmR1cmF0aW9uLGRhdGE9c29yZSxmYW1pbHk9Ymlub21pYWwpCnN1bW1hcnkoZml0VHlwZUR1cmF0aW9uSW50LGNvcj1UUlVFKQpBbm92YShmaXRUeXBlRHVyYXRpb25JbnQsdGVzdD0iTFIiLHR5cGU9MykKYGBgCgpXZSBjYW4gYWxzbyBmaXQgdGhlIG1vZGVsIHdpdGhvdXQgdGhlIGludGVyYWN0aW9uIGVmZmVjdDoKCmBgYHtyfQpmaXRUeXBlRHVyYXRpb25Ob0ludD1nbG0oc29yZX50eXBlK2R1cmF0aW9uLGRhdGE9c29yZSxmYW1pbHk9Ymlub21pYWwpCnN1bW1hcnkoZml0VHlwZUR1cmF0aW9uTm9JbnQsY29yPVRSVUUpCkFub3ZhKGZpdFR5cGVEdXJhdGlvbk5vSW50LHRlc3Q9IkxSIix0eXBlPTMpCmNvbmZpbnQoZml0VHlwZUR1cmF0aW9uTm9JbnQpCmBgYAoKV2UgYXNzZXNzZWQgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGUgZGlmZmVyZW50IGNvdmFyaWF0ZXMgaW4gdGhlIG1vZGVsIGJ5IHVzaW5nIGEgbGlrZWxpaG9vZCByYXRpbyB0ZXN0cyAoQW5vdmEgZnVuY3Rpb24gaW4gUikgYmVjYXVzZSB0aGUgcC12YWx1ZXMgYXJlIG1vcmUgYWNjdXJhdGUgdGhhbiB0aGUgcC12YWx1ZXMgb2YgdGhlIFdhbGQtdGVzdHMgIChzdW1tYXJ5IGZ1bmN0aW9uIGluIFIpLiAKVGhlIGludGVyYWN0aW9uIGJldHdlZW4gdHlwZSBhbmQgZHVyYXRpb24gaXMgbm90IHNpZ25pZmljYW50IChwPTAuMTc3KS4gSGVuY2UgdGhlIGludGVyYWN0aW9uIHRlcm0gY2FuIGJlIHJlbW92ZWQgZnJvbSB0aGUgbW9kZWwuIApJbiB0aGUgbW9kZWwgd2l0aCBtYWluIGVmZmVjdHMgZm9yIHR5cGUgYW5kIGR1cmF0aW9uLCB0aGUgZHVyYXRpb24gZWZmZWN0IGlzIGV4dHJlbWVseSBzaWduaWZpY2FudCAocCQ8JDAuMDAxKS4gVGhlIGVmZmVjdCBvZiB0eXBlIGlzIG5vdCBzaWduaWZpY2FudCAocD0wLjA2MSkuIApIb3dldmVyLCBzaW5jZSB0aGUgZWZmZWN0IG9mIHR5cGUgaXMgY2xvc2UgdG8gYmVpbmcgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCB3ZSB3aWxsIGxlYXZlIGl0IGluIHRoZSBtb2RlbCBzbyBhcyB0byBlc3RpbWF0ZSBhICJwdXJlIiBlZmZlY3QgZm9yIGR1cmF0aW9uLiAKSWYgd2UgcmVtb3ZlIHR5cGUgZnJvbSB0aGUgbW9kZWwgYW5kIGlmIHRoZSBlZmZlY3QgdHJ1bHkgZXhpc3RzIGJ1dCB0aGVyZSB3YXMgbm90IGVub3VnaCBwb3dlciBmb3IgZGV0ZWN0aW5nIGl0LCB0aGVuIHJlbW92aW5nIHRoZSB0eXBlIGZyb20gdGhlIG1vZGVsIG1pZ2h0IHJlc3VsdCBpbiBhIGJpYXNlZCBwYXJhbWV0ZXIgZXN0aW1hdGUgZm9yIGR1cmF0aW9uIGFzIGl0IG1pZ2h0IGNhcHR1cmVzIGEgcGFydCBvZiB0aGUgZWZmZWN0IG9mIHR5cGUuIAoKIyBJbnRlcnByZXRhdGlvbiBvZiB0aGUgZGlmZmVyZW50IG1vZGVscwojIyBNb2RlbCBUeXBlCgpgYGB7cn0KIyBNb2RlbCAxIG9ubHkgdHlwZQpwbG90KHNvcmV+ZHVyYXRpb24scGNoPWFzLmRvdWJsZSh0eXBlKSxjb2w9dHlwZSxkYXRhPXNvcmUsbWFpbj0iVHlwZSIseGxpbT1jKDAsMTIwKSkKbGVnZW5kKCJib3R0b21yaWdodCIscGNoPWMoMToyLE5BLE5BKSxsdHk9YygwLDAsMSwxKSxjb2w9YygxLDIsMSwyKSxsZWdlbmQ9cmVwKGxldmVscyhzb3JlJHR5cGUpLDIpKQoKI2NvbnN0cnVjdCBuZXcgZGF0YSB0byBtYWtlIGEgbmljZSBwbG90IChwcmVkaWN0IGRhdGEgdXNpbmcgdGhlIG1vZGVsKQp4PXNlcSgwLDEyMCwxKQoKI3VzZSB0eXBlIHJlc3BvbnNlIGluIG9yZGVyIHRvIHByZWRpY3QgcHJvYmFiaWxpdGllcwpuZXdkYXRhTWFzaz1kYXRhLmZyYW1lKGR1cmF0aW9uPXgsdHlwZT1mYWN0b3IoIm1hc2siLGxldmVscz1sZXZlbHMoc29yZSR0eXBlKSkpCnlQcmVkTWFzaz1wcmVkaWN0KGZpdFR5cGUsbmV3ZGF0YU1hc2ssdHlwZT0icmVzcG9uc2UiKQpsaW5lcyh4LHlQcmVkTWFzaykKCiN1c2UgdHlwZSByZXNwb25zZSBpbiBvcmRlciB0byBwcmVkaWN0IHByb2JhYmlsaXRpZXMKbmV3ZGF0YVR1YmU9ZGF0YS5mcmFtZShkdXJhdGlvbj14LHR5cGU9ZmFjdG9yKCJ0dWJlIixsZXZlbHM9bGV2ZWxzKHNvcmUkdHlwZSkpKQp5UHJlZFR1YmU9cHJlZGljdChmaXRUeXBlLG5ld2RhdGFUdWJlLHR5cGU9InJlc3BvbnNlIikKbGluZXMoeCx5UHJlZFR1YmUsY29sPTIpCmBgYAoKVGhlIG1vZGVsIGZvciB0aGUgbG9nIG9kZHMgb24gYSBzb3JlIHRocm9hdCBhZnRlciBzdXJnZXJ5IGluIGZ1bmN0aW9uIG9mIGFuYWVzdGhlc2lhIHR5cGUgaXMgZ2l2ZW46CgokJApcbG9nIFx0ZXh0e09kZHN9X2k9XGJldGFfMCtcYmV0YV9cdGV4dHt0dWJlfXhfXHRleHR7dHViZSxpfQokJAoKd2l0aCAkeF9cdGV4dHt0dWJlLGl9PTAkIHdoZW4gdGhlIHBhdGllbnQgd2FzIGFuYWVzdGhlc2l6ZWQgd2l0aCBhIG1hc2sgYW5kICAkeF9cdGV4dHt0dWJlLGl9PTEkIHdoZW4gYSB0dWJlIHdhcyB1c2VkLiAKQmFzZWQgb24gdGhpcyBtb2RlbCB3ZSBjYW4gZXN0aW1hdGUgdGhlIGxvZyBvZGRzIG9uIGEgc29yZSB0aHJvYXQgYWZ0ZXIgc3VyZ2VyeSB3aGVuIHdlYXJpbmcgYSBtYXNrIHdpdGgKCiQkClxsb2cgXHdpZGVoYXR7XHRleHR7T2Rkc319Xlx0ZXh0e21hc2t9PVxoYXQgXGJldGFfMC4KJCQKCkhlbmNlLCB0aGUgaW50ZXJjZXB0IGhhcyB0aGUgaW50ZXJwcmV0YXRpb24gb2YgdGhlIGxvZyBvZGRzIG9uIGEgc29yZSB0aHJvYXQgYWZ0ZXIgYSBzdXJnZXJ5IHdpdGggbWFzayBhbmFlc3RoZXNpYS4KVGhlIGxvZ2cgb2RkcyBvbiBhIHNvcmUgdGhyb2F0IGFmdGVyIGEgc3VyZ2VyeSB3aXRoIGEgdHViZSBpcyBlc3RpbWF0ZWQgYXMKCiQkClxsb2cgXHdpZGVoYXR7XHRleHR7T2Rkc319Xlx0ZXh0e3R1YmV9PVxoYXQgXGJldGFfMCtcaGF0XGJldGFfe3R1YmV9LgokJAoKVGhlIGxvZyBvZGRzIHJhdGlvIG9uIGEgc29yZSB0aHJvYXQgYmV0d2VlbiB0dWJlIGFuZCBtYXNrIGNhbiB0aGVuIGJlIGVzdGltYXRlZCBhczoKCiQkClxsb2cgXHdpZGVoYXR7XHRleHR7T2Rkc319Xlx0ZXh0e3R1YmV9LVxsb2cgXHdpZGVoYXR7XHRleHR7T2Rkc319Xlx0ZXh0e21hc2t9PVxoYXQgXGJldGFfMCtcaGF0XGJldGFfe3R1YmV9LVxoYXRcYmV0YV97MH09XGhhdFxiZXRhX1x0ZXh0e3R1YmV9LgokJAoKSGVuY2UsIHRoZSBzbG9wZSBmb3IgdGhlIGR1bW15IHZhcmlhYmxlIHR1YmUgaGFzIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgbG9nIG9kZHMgcmF0aW8gb24gYSBzb3JlIHRocm9hdCBiZXR3ZWVuIHR1YmUgYW5kIG1hc2suCgpJbnRlcnByZXRhdGlvbiBiYXNlZCBvbiB0aGUgcGFyYW1ldGVyIGVzdGltYXRlczoKVGhlIHByb2JhYmlsaXR5IG9uIGEgc29yZSB0aHJvYXQgd2hlbiB3ZWFyaW5nIGEgbWFzayBpcyBvbiBhdmVyYWdlIDMuNSB0aW1lcyBoaWdoZXIgdGhhbiB0aGUgcHJvYmFiaWxpdHkgdG8gd2FrZSB1cCBmcm9tIHN1cmdlcnkgd2l0aG91dCBhIHNvcmUgdGhyb2F0IHdoZW4gd2VhcmluZyBhIG1hc2sgKDk1XCUgQ0kgWzEuMywxMi4zXSkuClRoZSBvZGRzIG9uIGEgc29yZSB0aHJvYXQgYWZ0ZXIgc3VyZ2VyeSB3aXRoIGFuYWVzdGhlc2lhIHVzaW5nIGEgdHViZSBpcyBvbiBhdmVyYWdlIDQgdGltZXMgc21hbGxlciB0aGFuIHRoZSBvZGRzIHdpdGggYSBtYXNrLCBidXQgdGhpcyBvZGRzIHJhdGlvIGlzIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50ICggOTVcJSBDSSBbMC4wNSwxLjA0XSkuIAoKIyMgTW9kZWwgRHVyYXRpb24KCmBgYHtyfQpmaXREdXJhdGlvbj1nbG0oc29yZX5kdXJhdGlvbixkYXRhPXNvcmUsZmFtaWx5PWJpbm9taWFsKQpzdW1tYXJ5KGZpdER1cmF0aW9uLGNvcj1UUlVFKQpBbm92YShmaXREdXJhdGlvbix0ZXN0PSJMUiIsdHlwZT0zKQpjb25maW50KGZpdER1cmF0aW9uKQoKcGxvdChzb3JlfmR1cmF0aW9uLHBjaD1hcy5kb3VibGUodHlwZSksY29sPXR5cGUsZGF0YT1zb3JlLG1haW49IlR5cGUiLHhsaW09YygwLDEyMCkpCmxlZ2VuZCgiYm90dG9tcmlnaHQiLHBjaD1jKDE6MixOQSxOQSksbHR5PWMoMCwwLDEsMSksY29sPWMoMSwyLDEsMiksbGVnZW5kPXJlcChsZXZlbHMoc29yZSR0eXBlKSwyKSkKCiNjb25zdHJ1Y3QgbmV3IGRhdGEgdG8gbWFrZSBhIG5pY2UgcGxvdCAocHJlZGljdCBkYXRhIHVzaW5nIHRoZSBtb2RlbCkKeD1zZXEoMCwxMjAsMSkKCiN1c2UgdHlwZSByZXNwb25zZSBpbiBvcmRlciB0byBwcmVkaWN0IHByb2JhYmlsaXRpZXMKbmV3ZGF0YU1hc2s9ZGF0YS5mcmFtZShkdXJhdGlvbj14LHR5cGU9ZmFjdG9yKCJtYXNrIixsZXZlbHM9bGV2ZWxzKHNvcmUkdHlwZSkpKQp5UHJlZE1hc2s9cHJlZGljdChmaXREdXJhdGlvbixuZXdkYXRhTWFzayx0eXBlPSJyZXNwb25zZSIpCmxpbmVzKHgseVByZWRNYXNrKQoKI3VzZSB0eXBlIHJlc3BvbnNlIGluIG9yZGVyIHRvIHByZWRpY3QgcHJvYmFiaWxpdGllcwpuZXdkYXRhVHViZT1kYXRhLmZyYW1lKGR1cmF0aW9uPXgsdHlwZT1mYWN0b3IoInR1YmUiLGxldmVscz1sZXZlbHMoc29yZSR0eXBlKSkpCnlQcmVkVHViZT1wcmVkaWN0KGZpdER1cmF0aW9uLG5ld2RhdGFUdWJlLHR5cGU9InJlc3BvbnNlIikKbGluZXMoeCx5UHJlZFR1YmUsY29sPTIpCmBgYAoKClRoZSBtb2RlbCBmb3IgdGhlIGxvZyBvZGRzIG9uIGEgc29yZSB0aHJvYXQgYWZ0ZXIgc3VyZ2VyeSBpbiBmdW5jdGlvbiBvZiB0aGUgc3VyZ2VyeSB0aW1lIGNhbiBiZSBkZW5vdGVkIGFzOgokJApcbG9nIFx0ZXh0e09kZHN9X2k9XGJldGFfMCtcYmV0YV9cdGV4dHt0aW1lfXRfXHRleHR7aX0KJCQKClRoZW4gdGhlIGludGVyY2VwdCBoYXMgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBvZGRzIG9uIGEgc29yZSB0aHJvYXQgd2hlbiB0aGUgc3VyZ2VyeSB0b29rICR0PTAkIG1pbnV0ZXMuIApOb3RlLCB0aGF0IHRoaXMgcGFyYW1ldGVyIGRvZXMgbm90IGhhdmUgYSB1c2VmdWwgaW50ZXJwcmV0YXRpb24gaW4gcHJhY3RpY2UuIE1vcmVvdmVyLCBpdCBhbHNvIGludm9sdmVzIGFuIGV4dHJhcG9sYXRpb24uIApUaGUgaW50ZXJjZXB0IGluIGEgbW9kZWwgd2VyZSB0aGUgdGltZSBpcyBjZW50ZXJlZCwgaG93ZXZlciwgaGFzIGEgZGlmZmVyZW50IGludGVycHJldGF0aW9uOiBpdCBpcyB0aGUgb2RkcyBvbiBhIHNvcmUgdGhyb2F0IHdoZW4gdGhlIHN1cmdlcnkgdG9vayA0OC4wIG1pbnV0ZXMsIGkuZS4gdGhlIGF2ZXJhZ2UgZHVyYXRpb24gb2Ygc3VyZ2VyeSBpbiB0aGUgZGF0YXNldC4gCgoKVGhlIG9kZHMgb24gYSBzdXJnZXJ5IHRoYXQgdG9vayAzMCBtaW51dGVzIGNhbiBiZSBlc3RpbWF0ZWQgYXM6CgokJCAKXGxvZyBcdGV4dHtPZGRzfV57MzBtaW59PVxiZXRhXzArXGJldGFfXHRleHR7dGltZX0zMAokJAoKIGFuZCB0aGUgb2RkcyBvbiBhIHN1cmdlcnkgdGhhdCB0b29rIDMxIG1pbnV0ZXMgY2FuIGJlIGVzdGltYXRlZCBhczoKCiQkClxsb2cgXHdpZGVoYXR7XHRleHR7T2Rkc319XnszMW1pbn09XGJldGFfMCtcaGF0IFxiZXRhX1x0ZXh0e3RpbWV9MzEsCiQkCgpoZW5jZSB0aGUgc2xvcGUgJFxiZXRhX1x0ZXh0e3RpbWV9JCBoYXMgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBsb2cgb2RkcyByYXRpbyBiZXR3ZWVuIHN1cmdlcmllcyB3aXRoIGEgb25lIG1pbnV0ZSBkaWZmZXJlbmNlIGluIGR1cmF0aW9uLiAKCiMjIE1vZGVsIFR5cGUgKyBEdXJhdGlvbgoKYGBge3J9CnBsb3Qoc29yZX5kdXJhdGlvbixwY2g9YXMuZG91YmxlKHR5cGUpLGNvbD10eXBlLGRhdGE9c29yZSxtYWluPSJUeXBlIix4bGltPWMoMCwxMjApKQpsZWdlbmQoImJvdHRvbXJpZ2h0IixwY2g9YygxOjIsTkEsTkEpLGx0eT1jKDAsMCwxLDEpLGNvbD1jKDEsMiwxLDIpLGxlZ2VuZD1yZXAobGV2ZWxzKHNvcmUkdHlwZSksMikpCgojY29uc3RydWN0IG5ldyBkYXRhIHRvIG1ha2UgYSBuaWNlIHBsb3QgKHByZWRpY3QgZGF0YSB1c2luZyB0aGUgbW9kZWwpCng9c2VxKDAsMTIwLDEpCgojdXNlIHR5cGUgcmVzcG9uc2UgaW4gb3JkZXIgdG8gcHJlZGljdCBwcm9iYWJpbGl0aWVzCm5ld2RhdGFNYXNrPWRhdGEuZnJhbWUoZHVyYXRpb249eCx0eXBlPWZhY3RvcigibWFzayIsbGV2ZWxzPWxldmVscyhzb3JlJHR5cGUpKSkKeVByZWRNYXNrPXByZWRpY3QoZml0VHlwZUR1cmF0aW9uTm9JbnQsbmV3ZGF0YU1hc2ssdHlwZT0icmVzcG9uc2UiKQpsaW5lcyh4LHlQcmVkTWFzaykKCiN1c2UgdHlwZSByZXNwb25zZSBpbiBvcmRlciB0byBwcmVkaWN0IHByb2JhYmlsaXRpZXMKbmV3ZGF0YVR1YmU9ZGF0YS5mcmFtZShkdXJhdGlvbj14LHR5cGU9ZmFjdG9yKCJ0dWJlIixsZXZlbHM9bGV2ZWxzKHNvcmUkdHlwZSkpKQp5UHJlZFR1YmU9cHJlZGljdChmaXRUeXBlRHVyYXRpb25Ob0ludCxuZXdkYXRhVHViZSx0eXBlPSJyZXNwb25zZSIpCmxpbmVzKHgseVByZWRUdWJlLGNvbD0yKQoKc3VtbWFyeShmaXRUeXBlRHVyYXRpb25Ob0ludCkKYGBgCgpUaGUgbW9kZWwgZm9yIHRoZSBsb2cgb2RkcyBvbiBhIHNvcmUgdGhyb2F0IGFmdGVyIHN1cmdlcnkgd2l0aCBhIG1haW4gZWZmZWN0IGZvciBzdXJnZXJ5IHRpbWUgYW5kIHR5cGUgY2FuIGJlIHdyaXR0ZW4gYXM6CgokJApcbG9nIFx0ZXh0e09kZHN9X2k9XGJldGFfMCtcYmV0YV9cdGV4dHt0dWJlfXhfXHRleHR7dHViZX0rXGJldGFfXHRleHR7dGltZX10X2kKJCQKCi0gVGhlIGludGVyY2VwdCBoYXMgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBsb2cgb2RkcyBvbiBhIHNvcmUgdGhyb2F0IGZvciBwYXRpZW50cyB0aGF0IHdlcmUgYW5hZXN0aGV0aXNlZCB3aXRoIGEgbWFzayAoJHhfXHRleHR7dHViZX09MCQpIGFuZCB0aGF0IGhhZCBzdXJnZXJ5IHRoYXQgaGFkIGEgZHVyYXRpb24gb2YgMCBtaW51dGVzICgkdD0wJCkuIEFnYWluIHRoaXMgbG9nIG9kZHMgZG9lcyBub3QgaGF2ZSBhIHVzZWZ1bCBpbnRlcnByZXRhdGlvbi4gCgotIFRoZSBzbG9wZSBmb3IgdHViZSBhZ2FpbiBoYXMgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBsb2cgb2RkcyByYXRpbyBvbiBhIHNvcmUgdGhyb2F0IGJldHdlZW4gZ3JvdXBzIG9mIHBhdGllbnRzIHRoYXQgd2VyZSBhbmFlc3RoZXRpc2VkIHdpdGggdHViZXMgdnMgbWFza3MgYW5kIGdvdCBhIHN1cmdlcnkgd2l0aCB0aGUgc2FtZSBkdXJhdGlvbi4gClRoaXMgY2FuIGJlIHJlcGhyYXNlZCBhcyB0aGUgbG9nIG9kZHMgcmF0aW8gb24gYSBzb3JlIHRocm9hdCBiZXR3ZWVuIGdyb3VwcyBvZiBwYXRpZW50cyB0aGF0IHdlcmUgYW5hZXN0aGV0aXNlZCB3aXRoIHR1YmVzIHZzIGdyb3VwcyBvZiBwYXRpZW50cyBtYXNrcyBhZnRlciBjb3JyZWN0aW5nIGZvciB0aGUgZHVyYXRpb24gb2YgdGhlIHN1cmdlcnkuIChUaGlzIHdpbGwgcmVzdWx0IGluIGEgc2hpZnQgb2YgdGhlIGN1cnZlIGJldHdlZW4gcGF0aWVudHMgd2l0aCBtYXNrIGFuZCB0dWJlcy4pCgotIFRoZSBzbG9wZSBmb3IgdGltZSBoYXMgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBsb2cgb2RkcyByYXRpbyBvbiBhIHNvcmUgdGhyb2F0IGJldHdlZW4gZ3JvdXBzIG9mIHBhdGllbnRzIHRoYXQgaGFkIHN1cmdlcnkgd2l0aCBhIG9uZSBtaW51dGUgZHVyYXRpb24gZGlmZmVyZW5jZSBhbmQgd2VyZSBhbmFlc3RoZXRpc2VkIHdpdGggdGhlIHNhbWUgdHlwZSwgaS5lLiB0aGUgbG9nIG9kZHMgcmF0aW8gb24gYSBzb3JlIHRocm9hdCBiZXR3ZWVuIGdyb3VwcyBvZiBwYXRpZW50cyB0aGF0IGhhZCBzdXJnZXJ5IHdpdGggYSBvbmUgbWludXRlIGR1cmF0aW9uIGRpZmZlcmVuY2UgYWZ0ZXIgY29ycmVjdGlvbiBmb3IgdGhlIGFuYWVzdGhlc2lhIHR5cGUuCgojIyBNb2RlbCBUeXBlIHggRHVyYXRpb24KCmBgYHtyfQpwbG90KHNvcmV+ZHVyYXRpb24scGNoPWFzLmRvdWJsZSh0eXBlKSxjb2w9dHlwZSxkYXRhPXNvcmUsbWFpbj0iVHlwZSIseGxpbT1jKDAsMTIwKSkKbGVnZW5kKCJib3R0b21yaWdodCIscGNoPWMoMToyLE5BLE5BKSxsdHk9YygwLDAsMSwxKSxjb2w9YygxLDIsMSwyKSxsZWdlbmQ9cmVwKGxldmVscyhzb3JlJHR5cGUpLDIpKQoKI2NvbnN0cnVjdCBuZXcgZGF0YSB0byBtYWtlIGEgbmljZSBwbG90IChwcmVkaWN0IGRhdGEgdXNpbmcgdGhlIG1vZGVsKQp4PXNlcSgwLDEyMCwxKQoKI3VzZSB0eXBlIHJlc3BvbnNlIGluIG9yZGVyIHRvIHByZWRpY3QgcHJvYmFiaWxpdGllcwpuZXdkYXRhTWFzaz1kYXRhLmZyYW1lKGR1cmF0aW9uPXgsdHlwZT1mYWN0b3IoIm1hc2siLGxldmVscz1sZXZlbHMoc29yZSR0eXBlKSkpCnlQcmVkTWFzaz1wcmVkaWN0KGZpdFR5cGVEdXJhdGlvbkludCxuZXdkYXRhTWFzayx0eXBlPSJyZXNwb25zZSIpCmxpbmVzKHgseVByZWRNYXNrKQoKI3VzZSB0eXBlIHJlc3BvbnNlIGluIG9yZGVyIHRvIHByZWRpY3QgcHJvYmFiaWxpdGllcwpuZXdkYXRhVHViZT1kYXRhLmZyYW1lKGR1cmF0aW9uPXgsdHlwZT1mYWN0b3IoInR1YmUiLGxldmVscz1sZXZlbHMoc29yZSR0eXBlKSkpCnlQcmVkVHViZT1wcmVkaWN0KGZpdFR5cGVEdXJhdGlvbkludCxuZXdkYXRhVHViZSx0eXBlPSJyZXNwb25zZSIpCmxpbmVzKHgseVByZWRUdWJlLGNvbD0yKQoKc3VtbWFyeShmaXRUeXBlRHVyYXRpb25JbnQpCmBgYAoKVGhlIG1vZGVsIGZvciB0aGUgbG9nIG9kZHMgb24gYSBzb3JlIHRocm9hdCBhZnRlciBzdXJnZXJ5IHdpdGggYSBtYWluIGVmZmVjdCBmb3Igc3VyZ2VyeSB0aW1lIGFuZCB0eXBlIGFuZCBhIHRpbWUtdHlwZSBpbnRlcmFjdGlvbiBpcyBnaXZlbiBieToKCiQkClxsb2cgXHRleHR7T2Rkc31faT1cYmV0YV8wK1xiZXRhX1x0ZXh0e3R1YmV9eF9cdGV4dHt0dWJlfStcYmV0YV9cdGV4dHt0aW1lfXRfaStcYmV0YV9cdGV4dHt0aW1lLXR1YmV9eF9cdGV4dHt0dWJlLGl9dF9pCiQkCiAKSGVuY2UsIGZvciBwYXRpZW50cyB3aXRoIGEgbWFzayB0aGUgb2RkcyBjYW4gYmUgcHJlZGljdGVkIGluIGZ1bmN0aW9uIG9mIHRpbWUgYnkKCiQkClxsb2cgXHRleHR7T2Rkc31eXHRleHR7bWFza309XGJldGFfMCtcYmV0YV9cdGV4dHt0aW1lfXQKJCQKCmFuZCB0aGUgb2RkcyBvbiBhIHNvcmUgdGhyb2F0IGZvciBwYXRpZW50cyB0aGF0IHdlcmUgYW5hZXN0aGV0aXNlZCB3aXRoIGEgdHViZSBpbiBmdW5jdGlvbiBvZiB0aW1lIGJ5CgokJApcbG9nIFx0ZXh0e09kZHN9Xlx0ZXh0e3R1YmV9PVxiZXRhXzArXGJldGFfXHRleHR7dHViZX0rKFxiZXRhX1x0ZXh0e3RpbWV9K1xiZXRhX1x0ZXh0e3RpbWUtdHViZX0pdAokJAoKCi0gVGhlIGludGVyY2VwdCAkXGJldGFfMCQgaXMgYWdhaW4gdGhlIGxvZyBvZGRzIG9uIGEgc29yZSB0aHJvYXQgZm9yIHBhdGllbnRzIHRoYXQgd2VyZSBhbmFlc3RoZXRpc2VkIHdpdGggYSBtYXNrICgkeF9cdGV4dHt0dWJlfT0wJCkgYW5kIHRoYXQgaGFkIHN1cmdlcnkgdGhhdCBoYWQgYSBkdXJhdGlvbiBvZiAwIG1pbnV0ZXMgKCR0PTAkKS4KCi0gVGhlIHNsb3BlICRcYmV0YV9cdGV4dHt0dWJlfSQgaGFzIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgbG9nIG9kZHMgcmF0aW8gb24gYSBzb3JlIHRocm9hdCBmb3IgcGF0aWVudHMgdGhhdCB3ZXJlIGFuYWVzdGhldGlzZWQgd2l0aCBhIHR1YmUgKCR4X1x0ZXh0e3R1YmV9PTAkKSB2cyBwYXRpZW50cyB0aGF0IHdlcmUgYW5hZXN0aGV0aXNlZCB3aXRoIGEgbWFzayBhbmQgdGhhdCBoYWQgc3VyZ2VyeSB0aGF0IGhhZCBhIGR1cmF0aW9uIG9mIDAgbWludXRlcyAoJHQ9MCQpLgpBZ2FpbiB0aGVzZSB0d28gcGFyYW1ldGVycyBkbyBub3QgaGF2ZSBhIHVzZWZ1bCBpbnRlcnByZXRhdGlvbi4KIAotIFRoZSBwYXJhbWV0ZXIgJFxiZXRhX1x0ZXh0e3RpbWV9JCBoYXMgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBsb2cgb2RkcyByYXRpbyBvbiBhIHNvcmUgdGhyb2F0IGJldHdlZW4gZ3JvdXBzIG9mIHBhdGllbnRzIHRoYXQgaGFkIHN1cmdlcnkgd2l0aCBhIG9uZSBtaW51dGUgZHVyYXRpb24gZGlmZmVyZW5jZSBhbmQgd2VyZSBhbmFlc3RoZXRpc2VkIHdpdGggbWFzay4KIAotIFRoZSBwYXJhbWV0ZXIgJFxiZXRhX1x0ZXh0e3RpbWUtdHViZX0kIGFsbG93cyBmb3IgYSBkaWZmZXJlbnQgbG9nIG9kZHMgcmF0aW8gb24gYSBzb3JlIHRocm9hdCBmb3IgcGF0aWVudHMgdGhhdCBoYWQgc3VyZ2VyeSB3aXRoIGEgb25lIG1pbnV0ZSBkdXJhdGlvbiBkaWZmZXJlbmNlIGluIGdyb3VwcyBvZiBwYXRpZW50cyB0aGF0IHdlcmUgYW5hZXN0aGV0aXNlZCB3aXRoIGEgdHViZSB0aGFuIHRoYXQgd2l0aGluIHBhdGllbnQgZ3JvdXBzIHdpdGggYSBtYXNrLCBpLmUuIGl0IGFsbG93cyBmb3IgYSBkaWZmZXJlbnQgb2RkcyBwcm9maWxlIGluIGZ1bmN0aW9uIG9mIHRpbWUgZm9yIHBhdGllbnRzIHdpdGggYSB0dWJlIHRoYW4gZm9yIHBhdGllbnRzIHdpdGggYSBtYXNrLiAKCgojIENvbmNsdXNpb24KVGhlIGVmZmVjdCBvZiB0aGUgZHVyYXRpb24gb2Ygc3VyZ2VyeSBvbiB0aGUgb2RkcyBvbiBhIHNvcmUgdGhyb2F0IGlzIGV4dHJlbWVseSBzaWduaWZpY2FudCAocDwwLjAwMSkuIElmIHRoZSB0aW1lIG9mIHN1cmdlcnkgaW5jcmVhc2VzLCBwYXRpZW50cyBoYXZlIGEgaGlnaGVyIHByb2JhYmlsaXR5IHRvIHdha2UgdXAgd2l0aCBhIHNvcmUgdGhyb2F0LiBUaGUgb2RkcyByYXRpbyBmb3IgYSBvbmUgbWludXRlICBpbmNyZWFzZSBpbiBzdXJnZXJ5IGR1cmF0aW9uIGlzIDEuMDcgKDk1XCUgQ0kgIFsxLjAzLDEuMTRdKS4KVGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiB0aGUgdHlwZSBvZiBhbmFlc3RoZXNpYSBhbmQgZHVyYXRpb24gb2YgdGhlIHN1cmdlcnkgKHA9MC4xMTcpLiAKV2hpbGUgdGhlcmUgaXMgc29tZSBldmlkZW5jZSBpbiB0aGUgZGF0YSBzdWdnZXN0aW5nIHRoYXQgdGhlIHVzZSBvZiBhIHR1YmUgaXMgYmVuZWZpY2lhbCwgaS5lLiB0aGUgb2RkcyBvbiBhIHNvcmUgdGhyb2F0IGlzIG1vcmUgdGhhbiBhIGZhY3RvciBvZiA1IGxvd2VyIHdoZW4gdXNpbmcgYW4gYW5hZXN0aGVzaWEgd2l0aCBhIHR1YmUgdGhhbiB3aXRoIGEgbWFzayAoT1I9MC4xOSwgOTVcJSBDSSBbMC4wMiwxLjA4XSksIHRoZSBsYXR0ZXIgZWZmZWN0IGlzIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwPTAuMDYxKS4gIAoKCg==