library(brms)
# load data
load("/Users/michaelgarbo/Documents/CATCH_SOURCES_CHAPTER/CATCH_all_working_R/data_objects/catch_data.rda")
# scaling and centring trip days
dh$zdays<-(dh$tripdays-mean(dh$tripdays))/sd(dh$tripdays)
# load model fit with brm
#hrXMS<- brm(data = dh, family = poisson,
# c ~ 0 + intercept+xF+mF+sF+mF:sF+zdays+(1+zdays|vill)+(1|ht),
# prior = c(prior(normal(0, 10), class = b, coef = intercept),
# prior(normal(0, 1), class = b),
# prior(cauchy(0, 1), class = sd)),
# iter=4000,cores=2,control=list(adapt_delta=0.9))
hrXMS<-readRDS(file="/Users/michaelgarbo/Documents/CATCH_SOURCES_CHAPTER/CATCH_all_working_R/brms_models/hr3XMiSz.rds")
I want to look at covariates that might give insight into ways catch data might become biased. The response variable (c) is the number of animals caught on a hunters’ most recent trip
Covariates are:
xF: whether hunter was accompanied by an extra person on the trip;0=no,1=yes
sF: season (early.dry, late.dry, rainy)
mF: hunting method used on trip (gun, trapper, both)
zdays: duration of trip in days scaled (subract mean, divide by SD)
The random effects are
vill: village ID
ht: hunter ID
The code to fit in package brms was this:
# not run
#hrXMS<- brm(data = dh, family = poisson,
# c ~ 0 + intercept+xF+mF+sF+mF:sF+zdays+(1+zdays|vill)+(1|ht),
# prior = c(prior(normal(0, 10), class = b, coef = intercept),
# prior(normal(0, 1), class = b),
# prior(cauchy(0, 1), class = sd)),
# iter=4000,cores=2,control=list(adapt_delta=0.9))
summary(hrXMS)
Family: poisson
Links: mu = log
Formula: c ~ 0 + intercept + xF + mF + sF + mF:sF + zdays + (1 + zdays | vill) + (1 | ht)
Data: dh (Number of observations: 252)
Samples: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
total post-warmup samples = 8000
Group-Level Effects:
~ht (Number of levels: 208)
Estimate Est.Error l-95% CI u-95% CI Eff.Sample Rhat
sd(Intercept) 0.42 0.04 0.34 0.50 3742 1.00
~vill (Number of levels: 18)
Estimate Est.Error l-95% CI u-95% CI Eff.Sample Rhat
sd(Intercept) 0.53 0.13 0.32 0.82 4150 1.00
sd(zdays) 0.20 0.08 0.09 0.38 4464 1.00
cor(Intercept,zdays) -0.10 0.42 -0.81 0.73 6436 1.00
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Eff.Sample Rhat
intercept 2.07 0.17 1.74 2.40 2810 1.00
xF1 0.29 0.08 0.14 0.44 9174 1.00
mFgun -0.22 0.14 -0.50 0.06 5749 1.00
mFtrapper -0.16 0.15 -0.45 0.14 6038 1.00
sFlate.dry -0.23 0.10 -0.43 -0.03 6921 1.00
sFrainy 0.09 0.14 -0.18 0.36 8388 1.00
zdays 0.28 0.08 0.12 0.43 6265 1.00
mFgun:sFlate.dry -0.12 0.16 -0.44 0.20 5790 1.00
mFtrapper:sFlate.dry -0.21 0.21 -0.62 0.20 7006 1.00
mFgun:sFrainy -0.22 0.21 -0.61 0.19 6967 1.00
mFtrapper:sFrainy -0.65 0.29 -1.23 -0.08 8185 1.00
Samples were drawn using sampling(NUTS). For each parameter, Eff.Sample
is a crude measure of effective sample size, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
Using leave one out cross validation and pareto-smoothed importance sampling (Vehtari, Gelman, and Gabry, 2017) shows that many data points influence the posterior estimates (i.e. acting like outliers).
loo(hrXMS)
Found 83 observations with a pareto_k > 0.7 in model 'hrXMS'. With this many problematic observations, it may be more appropriate to use 'kfold' with argument 'K = 10' to perform 10-fold cross-validation rather than LOO.
Computed from 8000 by 252 log-likelihood matrix
------
Monte Carlo SE of elpd_loo is NA.
Pareto k diagnostic values:
Count Pct. Min. n_eff
(-Inf, 0.5] (good) 73 29.0% 879
(0.5, 0.7] (ok) 96 38.1% 206
(0.7, 1] (bad) 75 29.8% 35
(1, Inf) (very bad) 8 3.2% 7
See help('pareto-k-diagnostic') for details.
I guess this is something to do with high variability between hunters and the fact that most hunters contributed only 1 data point. A model without hunter ID as a varying intercept has fewer problematic observations, but lower out of sample performance based on kfold CV.
Extra notes on loo_compare: elpd = estimated log of loo predictive density, unbiased estimate of log posterior predictive density for new data (i.e. if you have a new data point, log ppd of its value according to the model fit without it) p_loo = can be considered as effective number of parameters lpd - elpd; provides a measure of model complexity, how much the model was able to fit the data.
# hrXMS_b<-update(hrXMS,.~.-(1|ht))
loo(hrXMS_b)
Found 7 observations with a pareto_k > 0.7 in model 'hrXMS_b'. It is recommended to set 'reloo = TRUE' in order to calculate the ELPD without the assumption that these observations are negligible. This will refit the model 7 times to compute the ELPDs for the problematic observations directly.
Computed from 8000 by 252 log-likelihood matrix
------
Monte Carlo SE of elpd_loo is NA.
Pareto k diagnostic values:
Count Pct. Min. n_eff
(-Inf, 0.5] (good) 233 92.5% 370
(0.5, 0.7] (ok) 12 4.8% 145
(0.7, 1] (bad) 4 1.6% 54
(1, Inf) (very bad) 3 1.2% 5
See help('pareto-k-diagnostic') for details.
Comparing models with and without the covariates with kfold CV shows they all perform similarly in terms of out-of-sample prediction (the loo_compare output shows elpd_diff is less than 2* se_elpd_diff). I’m interpretting this as showing there is little value in knowing about covariates because hunters and villages themselves are so variable. I’m interpretting the posterior distributions as providing some evidence that catch is higher if hunters use both snares and guns, if they are accompanied by someone, and that trappers tend to have lower catch per day in the rainy season. Expected effects ignoring hunter and village-level variance look like this (conditional on base factor levels and mean trip duration, 3.9 days)) :
mz<-marginal_effects(hrXMS)
mzp<-plot(mz,ask=F,rug=T)





Including the effects of hunter and village variability reveals the large predictive uncertainty and better captures the spread of the data (points are raw data at the base factor levels) :
mz_re<-marginal_effects(hrXMS,re_formula=NULL)
mzp_re<-plot(mz_re,ask=F,rug=T,points=T,point_args=list(alpha=0.5,width=0.2))





An obvious problem with the model is that the relationship between catch and trip duration is crazy for longer trips, but there weren’t many trips longer than 10 days so I don’t know if I need to worry about this. In general the predictions for the range where most of the data fall look reasonable to me (see below).
Another (potentially more serious?) flaw is that it can predict a negative coeficient for trip duration - which obviously makes no sense. Here is the predicted relationships between catch and trip days for ‘new’ hunters for trips of 1 to 10 days, there are one or two lines that suggest a negative relationship, but again I don’t know if this is a problem that I really need to address given that I don’t care too much about making predictions or trying to get the most accurate parameter estimates, what I’m more interested in is basically that there is maybe some effects of covariates, and lots of variation across hunters and villages.
newd<-data.frame(sF='early.dry',mF=rep(c('both','gun','trapper'),2),xF=rep(c("0","1"),3))
pd<-make_conditions(newd,vars=c('mF','sF','xF'))
md<-marginal_effects(hrXMS, effects = 'zdays',conditions=pd,spaghetti=T,nsamples=200)
md_re<-marginal_effects(hrXMS, effects = 'zdays',conditions=pd,spaghetti=T,nsamples=200,re_formula=NULL)
ppd<-plot(md,points=T,plot=F)[[1]]
ppd_re<-plot(md_re,points=T,plot=F)[[1]]
pd1<-ppd+ggplot2::xlim(-1,2.04)+ggplot2::ylim(0,50)+ggplot2::ggtitle("ignore random effects")
pd2<-ppd_re+ggplot2::xlim(-1,2.04)+ggplot2::ylim(0,50)+ggplot2::ggtitle("include random effects")
pd1;pd2


residuals vs covariates checks look ok as far as I can tell, but there are probably more checks I should do
p0<-pp_check(hrXMS)
Using 10 posterior samples for ppc type 'dens_overlay' by default.
p02<-pp_check(hrXMS,x='zdays',type="error_scatter_avg_vs_x")
Using all posterior samples for ppc type 'error_scatter_avg_vs_x' by default.
p1a<-pp_check(hrXMS,type="scatter_avg_grouped",group="mF",nsamples=100)
p1b<-pp_check(hrXMS,type="scatter_avg_grouped",group="sF",nsamples=100)
p1c<-pp_check(hrXMS,type="scatter_avg_grouped",group="xF",nsamples=100)
p0;p02;p1a;p1b;p1c





Improving the model parameterisation: 1. Use prior predictive simulation to specify more appropriate priors 2. Compare models without random slopes for villages, see if predictions about zdays parameters is improved.
- Better priors: using the argument sample_prior=‘only’ and looking at parameter estimates and implied predictions from the prior distributions to get an idea of priors that are more sensible and don’t have huge probability mass on estimates that are unrealistically high.
Using the same model structure with random slopes and intercepts but more regularising priors made for slightly less crazy prior estimates of hunters catch, but didn’t solve the problem that the relationship with trip duration could be predicted as negative for some hunters.






plot(pmp,ask=F,points=T,point_args=list(width=0.3,alpha=0.6))[[4]]+ggplot2::xlim(-1,2)+ggplot2::ylim(0,40000) # zooming in on the zdays the points are for baseline factor levels only
# including random effects priors can allow negative coefficients for tripdays
rmps<-marginal_effects(m2,re_formula=NULL,spaghetti=T,nsamples=500,plot=F)
plot(rmps,ask=F,points=T,point_args=list(width=0.3,alpha=0.6))[[4]]+ggplot2::xlim(-1,2.04)+ggplot2::ylim(0,400)






# fit the model with better priors and look at implied predictions of the posterior
hrXMS3<- brm(data = dh, family = poisson,
c ~ 0 + intercept +xF+mF+sF+mF:sF+zdays+(1+zdays|vill)+(1|ht),
prior = c(prior(normal(0, 5), class = b, coef = intercept),
prior(normal(0, 0.5), class = b,coef='zdays'),
prior(normal(0, 0.25), class = b),
prior(exponential(2), class = sd)),iter=4000,cores=2,control=list(adapt_delta=0.9),file="/Users/michaelgarbo/Documents/CATCH_SOURCES_CHAPTER/CATCH_all_working_R/brms_models/hrXMiS3")
m2m<-hrXMS3
# spaghetti plot shows one or two zdays coefficients are still negative and there are still some crazy high predictions for longer trips
rmpsP<-marginal_effects(m2m,re_formula=NULL,spaghetti=T,nsamples=500,plot=F)
plot(rmpsP,ask=F,points=T,point_args=list(width=0.3,alpha=0.6))[[4]]+ggplot2::xlim(-1,2.04)+ggplot2::ylim(0,200)
- Changing the model structure to leave out a varying slope at the village level (i.e. the relationship between catch and trip duration is now assumed to be the same across villages) produced only positive predicted relationships and controlled the high values of catch estimated for longer trips. Worth noting that the posterior distribution of the correlation parameter between intercept and slope for trip duration had had a high density over 0 and large variance - so basically the model was really not sure about what, if any, the correlation should be between the average catch at a given village, and the increase you’d expect with longer trips. Since there was also an intercept for each hunter (and many hunters only contribute one data point) it makes sense that there really isn’t enough data to include random slope for villages.






Some basic plots of the error distributions doesn’t flag up anything to me, although the predictive error is pretty large in general.






Next look at the sensitivity of predictions to the priors used, I fit another model with the same structure but less informative priors and visualised the prior distributions and posterior distributions of the parameter estimates. Both the models ended up with similar parameter estimates but the interaction term parameters seemed like they might have been a bit constrained by the priors, so I refit with a wider prior on the coefficients for the fixed effects, (and the predictions etc still looked sensible).


plots of posterior parameter distributions, pretty good evidence that trips that had an extra person had higher catch than those which didn’t (makes sense, especially if hunters report their helpers’ catch as part of their own)
hx
[[1]]

hx2
[[1]]

Also that hunting trips where both guns and trapping were used had higher catch than those only using one method, not shown here the estimate for trappers suggests no difference between trappers and gun hunters
hgun
[[1]]

hgun2
[[1]]

no evidence that trappers did more poorly in the rainy season than the early dry season (which is the factor baseline)
hrtraprainy
[[1]]

hrtraprainy2
[[1]]

and hunters catch more on longer trips (duh).
hdays
[[1]]

hdays2
[[1]]

Changing the priors to be less restrictive on the fixed effects parameters seems like a good idea so I try that
hrXMS3b<- brm(data = dh, family = poisson,
c ~ 0 + intercept +xF+mF+sF+mF:sF+zdays+(1|vill)+(1|ht),
prior = c(prior(normal(0, 5), class = b, coef = intercept),
prior(normal(0, 0.5), class = b),
prior(exponential(2), class = sd)),
iter=4000,cores=2,control=list(adapt_delta=0.9),sample_prior=T,file="/Users/michaelgarbo/Documents/CATCH_SOURCES_CHAPTER/CATCH_all_working_R/brms_models/hrXMiS3b")
summary(hrXMS3b)
and I’m still quite surprised by the posterior of the interaction parameter for trappers in the rainy season, although the other posterior parameters have more mass on 0 but have large uncertainty. Then I learned that the estimate of an interaction has twice the standard error of an estimate for a main effect, so actually this is inevitable. Also it means that I almost certainly don’t have anywhere near enough data to estimate an interaction effect, although I guess that doesn’t mean I should not have it in the model.



looking back at the raw data shows there are only 8 data points for trappers in the rainy season, and their catch is quite variable and there is not obviously a big interaction effect but conditioning on the interaction might help get more reasonable parameter distributions for the main effects.


datap1<-ggplot(dhh,aes(x=mF,y=cpd,alpha=0.5,colour=sF))+geom_point(position=position_jitterdodge())+geom_boxplot(varwidth=T)
datap2<-ggplot(dhh,aes(x=sF,y=cpd,alpha=0.5,colour=mF))+geom_point(position=position_jitterdodge())+geom_boxplot(varwidth=T)
datap3<-ggplot(dhh,aes(x=mF,y=c,alpha=0.5,colour=sF))+geom_point(position=position_jitterdodge())+geom_boxplot(varwidth=T)
datap4<-ggplot(dhh,aes(x=sF,y=c,alpha=0.5,colour=mF))+geom_point(position=position_jitterdodge())+geom_boxplot(varwidth=T)
datap1
datap2
datap3

datap4

Given that there isn’t much data for this condition in the interaction term, I guess theres a risk that whatever priors I choose may influence the posterior somewhat. So I’m going to stick with the normal(0,0.5) option for now, and be cautious about interpreting the effects of the interaction between methods and season. Also I want to look at the out of sample performance for these models….
The LOO-PSIS check still shows that individual data points have substantial impacts on the posterior distributions, so I use kfold cross-validation to see whether taking out any of the covariates makes a big difference in terms of how model fit.
loo_compare(hrXMS3pc,hrXMS3b,hrXMS3a,criterion='kfold')
elpd_diff se_diff
hrXMS3pc 0.0 0.0
hrXMS3a -2.7 9.1
hrXMS3b -16.7 9.6
loo_compare(hrXMS3a,hrXMS4,hrMS5,hrMX4,criterion='kfold')
elpd_diff se_diff
hrXMS3a 0.0 0.0
hrXMS4 -2.7 11.7
hrMX4 -12.6 8.7
hrMS5 -19.2 25.2
The models with different priors, and with and without the interaction term and dropping the fixed effects don’t seem to vary much in their out of sample predictive performance. So just sticking with the original model for now….
Start to explore the posterior in more detail, e.g. look at village and hunter level variation in intercepts

The overall marginal effects of this model (predicted catch for the baseline factor levels) look pretty similar to those in the first model which had a random slope and weaker priors.





mp<-marginal_effects(mod,re_formula=NA,plot=F)
pp<-plot(mp,ask=F,points=T,point_args=list(width=0.3,alpha=0.6))
pp[[4]]+ggplot2::xlim(-1,2)+ggplot2::ylim(0,40) # zooming in on the zdays note the points are for baseline factor levels only

# including the random effects and spaghetti plot
mps<-marginal_effects(mod,re_formula=NULL,spaghetti=T,nsamples=500,plot=F)
plot(mps,ask=F,points=T,point_args=list(width=0.3,alpha=0.6))[[4]]+ggplot2::xlim(-1,2.04)+ggplot2::ylim(0,40)






LS0tCnRpdGxlOiAiQ2F0Y2ggTW9kZWwgRXhwbG9yYXRpb24iCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KYGBge3IgZWNobz1UUlVFfQpsaWJyYXJ5KGJybXMpCgojIGxvYWQgZGF0YQpsb2FkKCIvVXNlcnMvbWljaGFlbGdhcmJvL0RvY3VtZW50cy9DQVRDSF9TT1VSQ0VTX0NIQVBURVIvQ0FUQ0hfYWxsX3dvcmtpbmdfUi9kYXRhX29iamVjdHMvY2F0Y2hfZGF0YS5yZGEiKQojIHNjYWxpbmcgYW5kIGNlbnRyaW5nIHRyaXAgZGF5cwpkaCR6ZGF5czwtKGRoJHRyaXBkYXlzLW1lYW4oZGgkdHJpcGRheXMpKS9zZChkaCR0cmlwZGF5cykKCiMgbG9hZCBtb2RlbCBmaXQgd2l0aCBicm0KI2hyWE1TPC0gYnJtKGRhdGEgPSBkaCwgZmFtaWx5ID0gcG9pc3NvbiwKIyAgICAgICAgICAgICAgICBjIH4gMCArIGludGVyY2VwdCt4RittRitzRittRjpzRit6ZGF5cysoMSt6ZGF5c3x2aWxsKSsoMXxodCksCiMgICAgICAgICAgICAgICAgcHJpb3IgPSBjKHByaW9yKG5vcm1hbCgwLCAxMCksIGNsYXNzID0gYiwgY29lZiA9IGludGVyY2VwdCksCiMgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yKG5vcm1hbCgwLCAxKSwgY2xhc3MgPSBiKSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IoY2F1Y2h5KDAsIDEpLCBjbGFzcyA9IHNkKSksCiMgICAgICAgICAgICAgICAgICAgICAgICAgaXRlcj00MDAwLGNvcmVzPTIsY29udHJvbD1saXN0KGFkYXB0X2RlbHRhPTAuOSkpCmhyWE1TPC1yZWFkUkRTKGZpbGU9Ii9Vc2Vycy9taWNoYWVsZ2FyYm8vRG9jdW1lbnRzL0NBVENIX1NPVVJDRVNfQ0hBUFRFUi9DQVRDSF9hbGxfd29ya2luZ19SL2JybXNfbW9kZWxzL2hyM1hNaVN6LnJkcyIpCgpgYGAKCkkgd2FudCB0byBsb29rIGF0IGNvdmFyaWF0ZXMgdGhhdCBtaWdodCBnaXZlIGluc2lnaHQgaW50byB3YXlzIGNhdGNoIGRhdGEgbWlnaHQgYmVjb21lIGJpYXNlZC4gClRoZSByZXNwb25zZSB2YXJpYWJsZSAoYykgaXMgdGhlIG51bWJlciBvZiBhbmltYWxzIGNhdWdodCBvbiBhIGh1bnRlcnMnIG1vc3QgcmVjZW50IHRyaXAKCkNvdmFyaWF0ZXMgYXJlOgoKeEY6IHdoZXRoZXIgaHVudGVyIHdhcyBhY2NvbXBhbmllZCBieSBhbiBleHRyYSBwZXJzb24gb24gdGhlIHRyaXA7MD1ubywxPXllcwoKc0Y6IHNlYXNvbiAoZWFybHkuZHJ5LCBsYXRlLmRyeSwgcmFpbnkpCgptRjogaHVudGluZyBtZXRob2QgdXNlZCBvbiB0cmlwIChndW4sIHRyYXBwZXIsIGJvdGgpCgp6ZGF5czogZHVyYXRpb24gb2YgdHJpcCBpbiBkYXlzIHNjYWxlZCAoc3VicmFjdCBtZWFuLCBkaXZpZGUgYnkgU0QpCgpUaGUgcmFuZG9tIGVmZmVjdHMgYXJlCgp2aWxsOiB2aWxsYWdlIElECgpodDogaHVudGVyIElECgpUaGUgY29kZSB0byBmaXQgaW4gcGFja2FnZSBicm1zIHdhcyB0aGlzOgogICAgICAgICAgICAgICAgICAgICAgICAgIApgYGB7cn0Kc3VtbWFyeShoclhNUykKYGBgCgpVc2luZyBsZWF2ZSBvbmUgb3V0IGNyb3NzIHZhbGlkYXRpb24gYW5kIHBhcmV0by1zbW9vdGhlZCBpbXBvcnRhbmNlIHNhbXBsaW5nIChWZWh0YXJpLCBHZWxtYW4sIGFuZCBHYWJyeSwgMjAxNykgc2hvd3MgdGhhdCBtYW55IGRhdGEgcG9pbnRzIGluZmx1ZW5jZSB0aGUgcG9zdGVyaW9yIGVzdGltYXRlcyAoaS5lLiBhY3RpbmcgbGlrZSBvdXRsaWVycykuIAoKYGBge3IgbWVzc2FnZT1GQUxTRX0KbG9vKGhyWE1TKQpgYGAKCkkgZ3Vlc3MgdGhpcyBpcyBzb21ldGhpbmcgdG8gZG8gd2l0aCBoaWdoIHZhcmlhYmlsaXR5IGJldHdlZW4gaHVudGVycyBhbmQgdGhlIGZhY3QgdGhhdCBtb3N0IGh1bnRlcnMgY29udHJpYnV0ZWQgb25seSAxIGRhdGEgcG9pbnQuIEEgbW9kZWwgd2l0aG91dCBodW50ZXIgSUQgYXMgYSB2YXJ5aW5nIGludGVyY2VwdCBoYXMgZmV3ZXIgcHJvYmxlbWF0aWMgb2JzZXJ2YXRpb25zLCBidXQgbG93ZXIgb3V0IG9mIHNhbXBsZSBwZXJmb3JtYW5jZSBiYXNlZCBvbiBrZm9sZCBDVi4KCkV4dHJhIG5vdGVzIG9uIGxvb19jb21wYXJlOgplbHBkID0gZXN0aW1hdGVkIGxvZyBvZiBsb28gcHJlZGljdGl2ZSBkZW5zaXR5LCB1bmJpYXNlZCBlc3RpbWF0ZSBvZiBsb2cgcG9zdGVyaW9yIHByZWRpY3RpdmUgZGVuc2l0eSBmb3IgbmV3IGRhdGEgKGkuZS4gaWYgeW91IGhhdmUgYSBuZXcgZGF0YSBwb2ludCwgbG9nIHBwZCBvZiBpdHMgdmFsdWUgYWNjb3JkaW5nIHRvIHRoZSBtb2RlbCBmaXQgd2l0aG91dCBpdCkKcF9sb28gPSBjYW4gYmUgY29uc2lkZXJlZCBhcyBlZmZlY3RpdmUgbnVtYmVyIG9mIHBhcmFtZXRlcnMgbHBkIC0gZWxwZDsgcHJvdmlkZXMgYSBtZWFzdXJlIG9mIG1vZGVsIGNvbXBsZXhpdHksIGhvdyBtdWNoIHRoZSBtb2RlbCB3YXMgYWJsZSB0byBmaXQgdGhlIGRhdGEuCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQojIGhyWE1TX2I8LXVwZGF0ZShoclhNUywufi4tKDF8aHQpKQpsb28oaHJYTVNfYikKcGxvdChsb28oaHJYTVMpKQpwbG90KGxvbyhoclhNU19iKSkKYGBgCgpDb21wYXJpbmcgbW9kZWxzIHdpdGggYW5kIHdpdGhvdXQgdGhlIGNvdmFyaWF0ZXMgd2l0aCBrZm9sZCBDViBzaG93cyB0aGV5IGFsbCBwZXJmb3JtIHNpbWlsYXJseSBpbiB0ZXJtcyBvZiBvdXQtb2Ytc2FtcGxlIHByZWRpY3Rpb24gKHRoZSBsb29fY29tcGFyZSBvdXRwdXQgc2hvd3MgZWxwZF9kaWZmIGlzIGxlc3MgdGhhbiAyKiBzZV9lbHBkX2RpZmYpLiBJJ20gaW50ZXJwcmV0dGluZyB0aGlzIGFzIHNob3dpbmcgdGhlcmUgaXMgbGl0dGxlIHZhbHVlIGluIGtub3dpbmcgYWJvdXQgY292YXJpYXRlcyBiZWNhdXNlIGh1bnRlcnMgYW5kIHZpbGxhZ2VzIHRoZW1zZWx2ZXMgYXJlIHNvIHZhcmlhYmxlLiBJJ20gaW50ZXJwcmV0dGluZyB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbnMgYXMgcHJvdmlkaW5nIHNvbWUgZXZpZGVuY2UgdGhhdCBjYXRjaCBpcyBoaWdoZXIgaWYgaHVudGVycyB1c2UgYm90aCBzbmFyZXMgYW5kIGd1bnMsIGlmIHRoZXkgYXJlIGFjY29tcGFuaWVkIGJ5IHNvbWVvbmUsIGFuZCB0aGF0IHRyYXBwZXJzIHRlbmQgdG8gaGF2ZSBsb3dlciBjYXRjaCBwZXIgZGF5IGluIHRoZSByYWlueSBzZWFzb24uIEV4cGVjdGVkIGVmZmVjdHMgaWdub3JpbmcgaHVudGVyIGFuZCB2aWxsYWdlLWxldmVsIHZhcmlhbmNlIGxvb2sgbGlrZSB0aGlzIChjb25kaXRpb25hbCBvbiBiYXNlIGZhY3RvciBsZXZlbHMgYW5kIG1lYW4gdHJpcCBkdXJhdGlvbiwgMy45IGRheXMpKSA6CmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm16PC1tYXJnaW5hbF9lZmZlY3RzKGhyWE1TKQptenA8LXBsb3QobXosYXNrPUYscnVnPVQpCgpgYGAKCkluY2x1ZGluZyB0aGUgZWZmZWN0cyBvZiBodW50ZXIgYW5kIHZpbGxhZ2UgdmFyaWFiaWxpdHkgcmV2ZWFscyB0aGUgbGFyZ2UgcHJlZGljdGl2ZSB1bmNlcnRhaW50eSBhbmQgYmV0dGVyIGNhcHR1cmVzIHRoZSBzcHJlYWQgb2YgdGhlIGRhdGEgKHBvaW50cyBhcmUgcmF3IGRhdGEgYXQgdGhlIGJhc2UgZmFjdG9yIGxldmVscykgOgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbXpfcmU8LW1hcmdpbmFsX2VmZmVjdHMoaHJYTVMscmVfZm9ybXVsYT1OVUxMKQptenBfcmU8LXBsb3QobXpfcmUsYXNrPUYscnVnPVQscG9pbnRzPVQscG9pbnRfYXJncz1saXN0KGFscGhhPTAuNSx3aWR0aD0wLjIpKQpgYGAKCkFuIG9idmlvdXMgcHJvYmxlbSB3aXRoIHRoZSBtb2RlbCBpcyB0aGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBjYXRjaCBhbmQgdHJpcCBkdXJhdGlvbiBpcyBjcmF6eSBmb3IgbG9uZ2VyIHRyaXBzLCBidXQgdGhlcmUgd2VyZW4ndCBtYW55IHRyaXBzIGxvbmdlciB0aGFuIDEwIGRheXMgc28gSSBkb24ndCBrbm93IGlmIEkgbmVlZCB0byB3b3JyeSBhYm91dCB0aGlzLiBJbiBnZW5lcmFsIHRoZSBwcmVkaWN0aW9ucyBmb3IgdGhlIHJhbmdlIHdoZXJlIG1vc3Qgb2YgdGhlIGRhdGEgZmFsbCBsb29rIHJlYXNvbmFibGUgdG8gbWUgKHNlZSBiZWxvdykuIAoKQW5vdGhlciAocG90ZW50aWFsbHkgbW9yZSBzZXJpb3VzPykgZmxhdyBpcyB0aGF0IGl0IGNhbiBwcmVkaWN0IGEgbmVnYXRpdmUgY29lZmljaWVudCBmb3IgdHJpcCBkdXJhdGlvbiAtIHdoaWNoIG9idmlvdXNseSBtYWtlcyBubyBzZW5zZS4gSGVyZSBpcyB0aGUgcHJlZGljdGVkIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBjYXRjaCBhbmQgdHJpcCBkYXlzIGZvciAnbmV3JyBodW50ZXJzIGZvciB0cmlwcyBvZiAxIHRvIDEwIGRheXMsIHRoZXJlIGFyZSBvbmUgb3IgdHdvIGxpbmVzIHRoYXQgc3VnZ2VzdCBhIG5lZ2F0aXZlIHJlbGF0aW9uc2hpcCwgYnV0IGFnYWluIEkgZG9uJ3Qga25vdyBpZiB0aGlzIGlzIGEgcHJvYmxlbSB0aGF0IEkgcmVhbGx5IG5lZWQgdG8gYWRkcmVzcyBnaXZlbiB0aGF0IEkgZG9uJ3QgY2FyZSB0b28gbXVjaCBhYm91dCBtYWtpbmcgcHJlZGljdGlvbnMgb3IgdHJ5aW5nIHRvIGdldCB0aGUgbW9zdCBhY2N1cmF0ZSBwYXJhbWV0ZXIgZXN0aW1hdGVzLCB3aGF0IEknbSBtb3JlIGludGVyZXN0ZWQgaW4gaXMgYmFzaWNhbGx5IHRoYXQgdGhlcmUgaXMgbWF5YmUgc29tZSBlZmZlY3RzIG9mIGNvdmFyaWF0ZXMsIGFuZCBsb3RzIG9mIHZhcmlhdGlvbiBhY3Jvc3MgaHVudGVycyBhbmQgdmlsbGFnZXMuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpuZXdkPC1kYXRhLmZyYW1lKHNGPSdlYXJseS5kcnknLG1GPXJlcChjKCdib3RoJywnZ3VuJywndHJhcHBlcicpLDIpLHhGPXJlcChjKCIwIiwiMSIpLDMpKQpwZDwtbWFrZV9jb25kaXRpb25zKG5ld2QsdmFycz1jKCdtRicsJ3NGJywneEYnKSkKbWQ8LW1hcmdpbmFsX2VmZmVjdHMoaHJYTVMsIGVmZmVjdHMgPSAnemRheXMnLGNvbmRpdGlvbnM9cGQsc3BhZ2hldHRpPVQsbnNhbXBsZXM9MjAwKQptZF9yZTwtbWFyZ2luYWxfZWZmZWN0cyhoclhNUywgZWZmZWN0cyA9ICd6ZGF5cycsY29uZGl0aW9ucz1wZCxzcGFnaGV0dGk9VCxuc2FtcGxlcz0yMDAscmVfZm9ybXVsYT1OVUxMKQoKcHBkPC1wbG90KG1kLHBvaW50cz1ULHBsb3Q9RilbWzFdXQpwcGRfcmU8LXBsb3QobWRfcmUscG9pbnRzPVQscGxvdD1GKVtbMV1dCgpwZDE8LXBwZCtnZ3Bsb3QyOjp4bGltKC0xLDIuMDQpK2dncGxvdDI6OnlsaW0oMCw1MCkrZ2dwbG90Mjo6Z2d0aXRsZSgiaWdub3JlIHJhbmRvbSBlZmZlY3RzIikKcGQyPC1wcGRfcmUrZ2dwbG90Mjo6eGxpbSgtMSwyLjA0KStnZ3Bsb3QyOjp5bGltKDAsNTApK2dncGxvdDI6OmdndGl0bGUoImluY2x1ZGUgcmFuZG9tIGVmZmVjdHMiKQoKcGQxO3BkMgpgYGAKCgpyZXNpZHVhbHMgdnMgY292YXJpYXRlcyBjaGVja3MgbG9vayBvayBhcyBmYXIgYXMgSSBjYW4gdGVsbCwgYnV0IHRoZXJlIGFyZSBwcm9iYWJseSBtb3JlIGNoZWNrcyBJIHNob3VsZCBkbwoKYGBge3J9CnAwPC1wcF9jaGVjayhoclhNUykKcDAyPC1wcF9jaGVjayhoclhNUyx4PSd6ZGF5cycsdHlwZT0iZXJyb3Jfc2NhdHRlcl9hdmdfdnNfeCIpCgpwMWE8LXBwX2NoZWNrKGhyWE1TLHR5cGU9InNjYXR0ZXJfYXZnX2dyb3VwZWQiLGdyb3VwPSJtRiIsbnNhbXBsZXM9MTAwKQpwMWI8LXBwX2NoZWNrKGhyWE1TLHR5cGU9InNjYXR0ZXJfYXZnX2dyb3VwZWQiLGdyb3VwPSJzRiIsbnNhbXBsZXM9MTAwKQpwMWM8LXBwX2NoZWNrKGhyWE1TLHR5cGU9InNjYXR0ZXJfYXZnX2dyb3VwZWQiLGdyb3VwPSJ4RiIsbnNhbXBsZXM9MTAwKQoKcDA7cDAyO3AxYTtwMWI7cDFjCmBgYAoKSW1wcm92aW5nIHRoZSBtb2RlbCBwYXJhbWV0ZXJpc2F0aW9uOgoxLiBVc2UgcHJpb3IgcHJlZGljdGl2ZSBzaW11bGF0aW9uIHRvIHNwZWNpZnkgbW9yZSBhcHByb3ByaWF0ZSBwcmlvcnMKMi4gQ29tcGFyZSBtb2RlbHMgd2l0aG91dCByYW5kb20gc2xvcGVzIGZvciB2aWxsYWdlcywgc2VlIGlmIHByZWRpY3Rpb25zIGFib3V0IHpkYXlzIHBhcmFtZXRlcnMgaXMgaW1wcm92ZWQuCgoxLiBCZXR0ZXIgcHJpb3JzOiB1c2luZyB0aGUgYXJndW1lbnQgc2FtcGxlX3ByaW9yPSdvbmx5JyBhbmQgbG9va2luZyBhdCBwYXJhbWV0ZXIgZXN0aW1hdGVzIGFuZCBpbXBsaWVkIHByZWRpY3Rpb25zIGZyb20gdGhlIHByaW9yIGRpc3RyaWJ1dGlvbnMgdG8gZ2V0IGFuIGlkZWEgb2YgcHJpb3JzIHRoYXQgYXJlIG1vcmUgc2Vuc2libGUgYW5kIGRvbid0IGhhdmUgaHVnZSBwcm9iYWJpbGl0eSBtYXNzIG9uIGVzdGltYXRlcyB0aGF0IGFyZSB1bnJlYWxpc3RpY2FsbHkgaGlnaC4KClVzaW5nIHRoZSBzYW1lIG1vZGVsIHN0cnVjdHVyZSB3aXRoIHJhbmRvbSBzbG9wZXMgYW5kIGludGVyY2VwdHMgYnV0IG1vcmUgcmVndWxhcmlzaW5nIHByaW9ycyBtYWRlIGZvciBzbGlnaHRseSBsZXNzIGNyYXp5IHByaW9yIGVzdGltYXRlcyBvZiBodW50ZXJzIGNhdGNoLCBidXQgZGlkbid0IHNvbHZlIHRoZSBwcm9ibGVtIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCB3aXRoIHRyaXAgZHVyYXRpb24gY291bGQgYmUgcHJlZGljdGVkIGFzIG5lZ2F0aXZlIGZvciBzb21lIGh1bnRlcnMuCgpgYGB7ciBlY2hvPVRSVUV9CiMgZml0IHRoZSBtb2RlbCB3aXRoIGJldHRlciBwcmlvcnMKCmhyWE1TcHJpb3IzPC0gYnJtKGRhdGEgPSBkaCwgZmFtaWx5ID0gcG9pc3NvbiwKICAgICAgICAgICAgIGMgfiAwICsgaW50ZXJjZXB0ICt4RittRitzRittRjpzRit6ZGF5cysoMSt6ZGF5c3x2aWxsKSsoMXxodCksCiAgICAgICAgICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDUpLCBjbGFzcyA9IGIsIGNvZWYgPSBpbnRlcmNlcHQpLAogICAgICAgICAgICAgICAgICAgICAgIHByaW9yKG5vcm1hbCgwLCAwLjUpLCBjbGFzcyA9IGIsY29lZj0nemRheXMnKSwKICAgICAgICAgICAgICAgICAgICAgICBwcmlvcihub3JtYWwoMCwgMC4yNSksIGNsYXNzID0gYiksCiAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMiksIGNsYXNzID0gc2QpKSwKICAgICAgICAgICAgIGl0ZXI9NDAwMCxjb3Jlcz0yLGNvbnRyb2w9bGlzdChhZGFwdF9kZWx0YT0wLjkpLHNhbXBsZV9wcmlvcj0nb25seScsZmlsZT0iL1VzZXJzL21pY2hhZWxnYXJiby9Eb2N1bWVudHMvQ0FUQ0hfU09VUkNFU19DSEFQVEVSL0NBVENIX2FsbF93b3JraW5nX1IvYnJtc19tb2RlbHMvaHJYTVNwcmlvcjMiKQoKbTI8LWhyWE1TcHJpb3IzCnBtcDwtbWFyZ2luYWxfZWZmZWN0cyhtMixyZV9mb3JtdWxhPU5BLHBsb3Q9RikKcGxvdChwbXAsYXNrPUYscG9pbnRzPVQscG9pbnRfYXJncz1saXN0KHdpZHRoPTAuMyxhbHBoYT0wLjYpKVtbNF1dK2dncGxvdDI6OnhsaW0oLTEsMikrZ2dwbG90Mjo6eWxpbSgwLDQwMDAwKSAjIHpvb21pbmcgaW4gb24gdGhlIHpkYXlzIHRoZSBwb2ludHMgYXJlIGZvciBiYXNlbGluZSBmYWN0b3IgbGV2ZWxzIG9ubHkKCiMgaW5jbHVkaW5nIHJhbmRvbSBlZmZlY3RzIHByaW9ycyBjYW4gYWxsb3cgbmVnYXRpdmUgY29lZmZpY2llbnRzIGZvciB0cmlwZGF5cwpybXBzPC1tYXJnaW5hbF9lZmZlY3RzKG0yLHJlX2Zvcm11bGE9TlVMTCxzcGFnaGV0dGk9VCxuc2FtcGxlcz01MDAscGxvdD1GKQpwbG90KHJtcHMsYXNrPUYscG9pbnRzPVQscG9pbnRfYXJncz1saXN0KHdpZHRoPTAuMyxhbHBoYT0wLjYpKVtbNF1dK2dncGxvdDI6OnhsaW0oLTEsMi4wNCkrZ2dwbG90Mjo6eWxpbSgwLDQwMCkKCmBgYAoKYGBge3IgZWNobz1UUlVFfQojIGZpdCB0aGUgbW9kZWwgd2l0aCBiZXR0ZXIgcHJpb3JzIGFuZCBsb29rIGF0IGltcGxpZWQgcHJlZGljdGlvbnMgb2YgdGhlIHBvc3RlcmlvcgpoclhNUzM8LSBicm0oZGF0YSA9IGRoLCBmYW1pbHkgPSBwb2lzc29uLAogICAgICAgICAgICAgICAgICBjIH4gMCArIGludGVyY2VwdCAreEYrbUYrc0YrbUY6c0YremRheXMrKDEremRheXN8dmlsbCkrKDF8aHQpLAogICAgICAgICAgICAgICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDUpLCBjbGFzcyA9IGIsIGNvZWYgPSBpbnRlcmNlcHQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3Iobm9ybWFsKDAsIDAuNSksIGNsYXNzID0gYixjb2VmPSd6ZGF5cycpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3Iobm9ybWFsKDAsIDAuMjUpLCBjbGFzcyA9IGIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMiksIGNsYXNzID0gc2QpKSxpdGVyPTQwMDAsY29yZXM9Mixjb250cm9sPWxpc3QoYWRhcHRfZGVsdGE9MC45KSxmaWxlPSIvVXNlcnMvbWljaGFlbGdhcmJvL0RvY3VtZW50cy9DQVRDSF9TT1VSQ0VTX0NIQVBURVIvQ0FUQ0hfYWxsX3dvcmtpbmdfUi9icm1zX21vZGVscy9oclhNaVMzIikKCm0ybTwtaHJYTVMzCgojIHNwYWdoZXR0aSBwbG90IHNob3dzIG9uZSBvciB0d28gemRheXMgY29lZmZpY2llbnRzIGFyZSBzdGlsbCBuZWdhdGl2ZSBhbmQgdGhlcmUgYXJlIHN0aWxsIHNvbWUgY3JhenkgaGlnaCBwcmVkaWN0aW9ucyBmb3IgbG9uZ2VyIHRyaXBzCnJtcHNQPC1tYXJnaW5hbF9lZmZlY3RzKG0ybSxyZV9mb3JtdWxhPU5VTEwsc3BhZ2hldHRpPVQsbnNhbXBsZXM9NTAwLHBsb3Q9RikKcGxvdChybXBzUCxhc2s9Rixwb2ludHM9VCxwb2ludF9hcmdzPWxpc3Qod2lkdGg9MC4zLGFscGhhPTAuNikpW1s0XV0rZ2dwbG90Mjo6eGxpbSgtMSwyLjA0KStnZ3Bsb3QyOjp5bGltKDAsMjAwKQpgYGAKCjIuIENoYW5naW5nIHRoZSBtb2RlbCBzdHJ1Y3R1cmUgdG8gbGVhdmUgb3V0IGEgdmFyeWluZyBzbG9wZSBhdCB0aGUgdmlsbGFnZSBsZXZlbCAoaS5lLiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gY2F0Y2ggYW5kIHRyaXAgZHVyYXRpb24gaXMgbm93IGFzc3VtZWQgdG8gYmUgdGhlIHNhbWUgYWNyb3NzIHZpbGxhZ2VzKSBwcm9kdWNlZCBvbmx5IHBvc2l0aXZlIHByZWRpY3RlZCByZWxhdGlvbnNoaXBzIGFuZCBjb250cm9sbGVkIHRoZSBoaWdoIHZhbHVlcyBvZiBjYXRjaCBlc3RpbWF0ZWQgZm9yIGxvbmdlciB0cmlwcy4gV29ydGggbm90aW5nIHRoYXQgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24gb2YgdGhlIGNvcnJlbGF0aW9uIHBhcmFtZXRlciBiZXR3ZWVuIGludGVyY2VwdCBhbmQgc2xvcGUgZm9yIHRyaXAgZHVyYXRpb24gaGFkIGhhZCBhIGhpZ2ggZGVuc2l0eSBvdmVyIDAgYW5kIGxhcmdlIHZhcmlhbmNlIC0gc28gYmFzaWNhbGx5IHRoZSBtb2RlbCB3YXMgcmVhbGx5IG5vdCBzdXJlIGFib3V0IHdoYXQsIGlmIGFueSwgdGhlIGNvcnJlbGF0aW9uIHNob3VsZCBiZSBiZXR3ZWVuIHRoZSBhdmVyYWdlIGNhdGNoIGF0IGEgZ2l2ZW4gdmlsbGFnZSwgYW5kIHRoZSBpbmNyZWFzZSB5b3UnZCBleHBlY3Qgd2l0aCBsb25nZXIgdHJpcHMuIFNpbmNlIHRoZXJlIHdhcyBhbHNvIGFuIGludGVyY2VwdCBmb3IgZWFjaCBodW50ZXIgKGFuZCBtYW55IGh1bnRlcnMgb25seSBjb250cmlidXRlIG9uZSBkYXRhIHBvaW50KSBpdCBtYWtlcyBzZW5zZSB0aGF0IHRoZXJlIHJlYWxseSBpc24ndCBlbm91Z2ggZGF0YSB0byBpbmNsdWRlIHJhbmRvbSBzbG9wZSBmb3IgdmlsbGFnZXMuCgpgYGB7ciBlY2hvPVRSVUV9CgojIHNwZWNpZnkgYSBtb2RlbCB3aXRob3V0IHJhbmRvbSBzbG9wZXMgYW5kIG1vcmUgc2Vuc2libGUgcHJpb3JzCmhyWE1TM2E8LSBicm0oZGF0YSA9IGRoLCBmYW1pbHkgPSBwb2lzc29uLAogICAgICAgICAgICAgYyB+IDAgKyBpbnRlcmNlcHQgK3hGK21GK3NGK21GOnNGK3pkYXlzKygxfHZpbGwpKygxfGh0KSwKICAgICAgICAgICAgIHByaW9yID0gYyhwcmlvcihub3JtYWwoMCwgNSksIGNsYXNzID0gYiwgY29lZiA9IGludGVyY2VwdCksCiAgICAgICAgICAgICAgICAgICAgICAgcHJpb3Iobm9ybWFsKDAsIDAuNSksIGNsYXNzID0gYixjb2VmPSd6ZGF5cycpLAogICAgICAgICAgICAgICAgICAgICAgIHByaW9yKG5vcm1hbCgwLCAwLjI1KSwgY2xhc3MgPSBiKSwKICAgICAgICAgICAgICAgICAgICAgICBwcmlvcihleHBvbmVudGlhbCgyKSwgY2xhc3MgPSBzZCkpLAogICAgICAgICAgICAgaXRlcj00MDAwLGNvcmVzPTIsY29udHJvbD1saXN0KGFkYXB0X2RlbHRhPTAuOSksZmlsZT0iL1VzZXJzL21pY2hhZWxnYXJiby9Eb2N1bWVudHMvQ0FUQ0hfU09VUkNFU19DSEFQVEVSL0NBVENIX2FsbF93b3JraW5nX1IvYnJtc19tb2RlbHMvaHJYTWlTM2EiKQoKIyBkcmF3cyBmcm9tIHRoZSBwb3N0ZXJpb3Igc2hvdyB0aGVyZSBhcmUgbm93IG5vIGh1bnRlcnMgdGhhdCBhcmUgZXhwZWN0ZWQgY2F0Y2ggbGVzcyB0aGUgbG9uZ2VyIHRoZXkgc3BlbmQgaHVudGluZwoKbW9kPC1oclhNUzNhCgojIHF1aWNrIGxvb2sgYXQgY29uZGl0aW9uYWwgcHJlZGljdGVkIHZhbHVlcyBzaG93cyBtdWNoIG1vcmUgc2Vuc2libGUgcmFuZ2Ugb2YgcHJlZGljdGlvbnMgZm9yIGxvbmdlciB0cmlwcyBhbmQgbm8gbmVnYXRpdmUgY29lZmZpY2llbnRzIGZvciB0cmlwIGRheXMKbXBzPC1tYXJnaW5hbF9lZmZlY3RzKG1vZCxyZV9mb3JtdWxhPU5VTEwsc3BhZ2hldHRpPVQsbnNhbXBsZXM9NTAwLHBsb3Q9RikKcGxvdChtcHMsYXNrPUYscG9pbnRzPVQscG9pbnRfYXJncz1saXN0KHdpZHRoPTAuMyxhbHBoYT0wLjYpKVtbNF1dK2dncGxvdDI6OnhsaW0oLTEsMi4wNCkrZ2dwbG90Mjo6eWxpbSgwLDYwKQpgYGAKClNvbWUgYmFzaWMgcGxvdHMgb2YgdGhlIGVycm9yIGRpc3RyaWJ1dGlvbnMgZG9lc24ndCBmbGFnIHVwIGFueXRoaW5nIHRvIG1lLCBhbHRob3VnaCB0aGUgcHJlZGljdGl2ZSBlcnJvciBpcyBwcmV0dHkgbGFyZ2UgaW4gZ2VuZXJhbC4KCmBgYHtyIGVjaG89VFJVRX0KIyBmaXR0ZWQgdmVyc3VzIG9ic2VydmVkIHZhbHVlcwpwZDE8LXBwX2NoZWNrKG1vZCkKcHMxPC1wcF9jaGVjayhtb2QsdHlwZT0iZXJyb3Jfc2NhdHRlcl9hdmdfdnNfeCIseD0iemRheXMiLG5zYW1wbGVzPTEwMDApCgojIGhpc3RvZ3JhbXMgb2YgZGlmZmVyZW5jZXMgYmV0d2VlbiBmaXR0ZWQgYW5kIG9ic2VydmVkIHZhbHVlcywgZWFjaCBwYW5lbCBpcyBhIGRhdGFzZXQgb2YgeXJlcCBkcmF3biBmcm9tIHBvc3RlcmlvcgpoaXN0cDwtcHBfY2hlY2sobW9kLHR5cGU9J2Vycm9yX2hpc3RfZ3JvdXBlZCcsbnNhbXBsZXM9Myxncm91cD0nbUYnKQpoaXN0cHY8LXBwX2NoZWNrKG1vZCx0eXBlPSdlcnJvcl9oaXN0X2dyb3VwZWQnLG5zYW1wbGVzPTMsZ3JvdXA9J3NGJykKaGlzdHB4PC1wcF9jaGVjayhtb2QsdHlwZT0nZXJyb3JfaGlzdF9ncm91cGVkJyxuc2FtcGxlcz01LGdyb3VwPSd4RicpCgpwaDE8LWhpc3RwK2dncGxvdDI6OnhsaW0oLTI1LDIwKStnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9MCkKcGgyPC1oaXN0cHYrZ2dwbG90Mjo6eGxpbSgtMjAsMjApK2dncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdD0wKQpwaDM8LWhpc3RweCtnZ3Bsb3QyOjp4bGltKC0yMCwyMCkrZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0PTApCgojIGV4cGVjdGVkIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgYmFzZWQgb24gbW9kZWwgd2l0aCBvYnNlcnZlZCBkaXN0cmlidXRpb24Kcmc8LXBwX2NoZWNrKG1vZCx0eXBlPSdyb290b2dyYW0nKQoKcGQxO3BzMTtwaDE7cGgyO3BoMztyZwojIE5CIHRoZXNlIGFyZSBzYXZlZCBoZXJlICIvVXNlcnMvbWljaGFlbGdhcmJvL0RvY3VtZW50cy9DQVRDSF9TT1VSQ0VTX0NIQVBURVIvQ0FUQ0hfYWxsX3dvcmtpbmdfUi9icm1zX21vZGVsX2NoZWNrcy9wb3N0cHJlZGNoZWNrczFfaHJYTWlTM2EucGRmIgpgYGAKCk5leHQgbG9vayBhdCB0aGUgc2Vuc2l0aXZpdHkgb2YgcHJlZGljdGlvbnMgdG8gdGhlIHByaW9ycyB1c2VkLCBJIGZpdCBhbm90aGVyIG1vZGVsIHdpdGggdGhlIHNhbWUgc3RydWN0dXJlIGJ1dCBsZXNzIGluZm9ybWF0aXZlIHByaW9ycyBhbmQgdmlzdWFsaXNlZCB0aGUgcHJpb3IgZGlzdHJpYnV0aW9ucyBhbmQgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbnMgb2YgdGhlIHBhcmFtZXRlciBlc3RpbWF0ZXMuIEJvdGggdGhlIG1vZGVscyBlbmRlZCB1cCB3aXRoIHNpbWlsYXIgcGFyYW1ldGVyIGVzdGltYXRlcyBidXQgdGhlIGludGVyYWN0aW9uIHRlcm0gcGFyYW1ldGVycyBzZWVtZWQgbGlrZSB0aGV5IG1pZ2h0IGhhdmUgYmVlbiBhIGJpdCBjb25zdHJhaW5lZCBieSB0aGUgcHJpb3JzLCBzbyBJIHJlZml0IHdpdGggYSB3aWRlciBwcmlvciBvbiB0aGUgY29lZmZpY2llbnRzIGZvciB0aGUgZml4ZWQgZWZmZWN0cywgKGFuZCB0aGUgcHJlZGljdGlvbnMgZXRjIHN0aWxsIGxvb2tlZCBzZW5zaWJsZSkuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1GQUxTRX0KIyBzcGVjaWZ5IGxlc3MgaW5mb3JtYXRpdmUgcHJpb3JzIHRvIGNoZWNrIHNlbnNpdGl2aXR5IHRvIHByaW9ycwpoclhNUzNwYzE8LSBicm0oZGF0YSA9IGRoLCBmYW1pbHkgPSBwb2lzc29uLAogICAgICAgICAgICAgIGMgfiAwICsgaW50ZXJjZXB0ICt4RittRitzRittRjpzRit6ZGF5cysoMXx2aWxsKSsoMXxodCksCiAgICAgICAgICAgICAgcHJpb3IgPSBjKHByaW9yKG5vcm1hbCgwLCAxMCksIGNsYXNzID0gYiwgY29lZiA9IGludGVyY2VwdCksCiAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yKG5vcm1hbCgwLCAxKSwgY2xhc3MgPSBiKSwKICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gc2QpKSxpdGVyPTQwMDAsY29yZXM9Mixjb250cm9sPWxpc3QoYWRhcHRfZGVsdGE9MC45OSksZmlsZT0iL1VzZXJzL21pY2hhZWxnYXJiby9Eb2N1bWVudHMvQ0FUQ0hfU09VUkNFU19DSEFQVEVSL0NBVENIX2FsbF93b3JraW5nX1IvYnJtc19tb2RlbHMvaHJYTVMzcGMxIikKCiMgc2hvdWxkIGhhdmUgaW5jbHVkZWQgdGhlIHNhbXBsZV9wcmlvcnM9VFJVRSBhcmd1bWVudCB3aGVuIEkgZml0IHRoZSBtb2RlbHMgdGhlIGZpcnN0IHRpbWUgc28gZG8gaXQgbm93IHRvIGdldCB0aGUgcHJpb3IgZGlzdHJpYnV0aW9ucyBvZiB0aGUgbW9kZWwKaHJYTVMzYTwtdXBkYXRlKGhyWE1TM2EsLn4uLHNhbXBsZV9wcmlvcj1UUlVFLGZpbGU9Ii9Vc2Vycy9taWNoYWVsZ2FyYm8vRG9jdW1lbnRzL0NBVENIX1NPVVJDRVNfQ0hBUFRFUi9DQVRDSF9hbGxfd29ya2luZ19SL2JybXNfbW9kZWxzL2hyWE1TM2EiKQpoclhNUzNwYzwtdXBkYXRlKGhyWE1TM3BjMSwufi4sY29yZXM9MixzYW1wbGVfcHJpb3I9VFJVRSxmaWxlPSIvVXNlcnMvbWljaGFlbGdhcmJvL0RvY3VtZW50cy9DQVRDSF9TT1VSQ0VTX0NIQVBURVIvQ0FUQ0hfYWxsX3dvcmtpbmdfUi9icm1zX21vZGVscy9oclhNUzNwYyIpCgpoeXBtb2Q8LWhyWE1TM2EKaHlwbW9kMjwtaHJYTVMzcGMKCiMgdXNlIHRoZSBiYXllc3Bsb3QgaHlwb3RoZXNpcyBmdW5jdGlvbiB0byBwbG90IGVhY2ggcGFyYW0gd2l0aCBpdHMgcHJpb3IsIGp1c3QgYSBmZXcgZXhhbXBsZXMgaGVyZSB0aGF0IHNob3cgdGhlcmUgd2FzIGxpdHRsZSBkaWZmZXJlbmNlIHVzaW5nIHRoZSB2YWd1ZSBvciB0aGUgbGVzcyB2YWd1ZSBwcmlvcnMKaHg8LXBsb3QoaHlwb3RoZXNpcyhoeXBtb2QsICJ4RjEgPCAwIikpCmh4MjwtcGxvdChoeXBvdGhlc2lzKGh5cG1vZDIsICJ4RjEgPCAwIikpCgpoZ3VuPC1wbG90KGh5cG90aGVzaXMoaHlwbW9kLCAibUZndW4gPCAwIikpCmhndW4yPC1wbG90KGh5cG90aGVzaXMoaHlwbW9kMiwgIm1GZ3VuIDwgMCIpKQoKaHRyYXA8LXBsb3QoaHlwb3RoZXNpcyhoeXBtb2QsICJtRnRyYXBwZXIgPiAwIikpCmh0cmFwMjwtcGxvdChoeXBvdGhlc2lzKGh5cG1vZDIsICJtRnRyYXBwZXIgPiAwIikpCgpoZ3RyYXA8LXBsb3QoaHlwb3RoZXNpcyhoeXBtb2QsIm1GZ3VuID4gbUZ0cmFwcGVyIikpCmhndHJhcDI8LXBsb3QoaHlwb3RoZXNpcyhoeXBtb2QyLCAibUZndW4gPiBtRnRyYXBwZXIiKSkKCmhsYXRlPC1wbG90KGh5cG90aGVzaXMoaHlwbW9kLCAic0ZsYXRlLmRyeSA8IDAiKSkKaGxhdGUyPC1wbG90KGh5cG90aGVzaXMoaHlwbW9kMiwgInNGbGF0ZS5kcnkgPCAwIikpCgpocmFpbjwtcGxvdChoeXBvdGhlc2lzKGh5cG1vZCwgInNGcmFpbnkgPiAwIikpCmhybGF0ZTwtcGxvdChoeXBvdGhlc2lzKGh5cG1vZCwgInNGbGF0ZS5kcnkgPCBzRnJhaW55IikpCgpocmd1bmxhdGU8LXBsb3QoaHlwb3RoZXNpcyhoeXBtb2QsICJtRmd1bjpzRmxhdGUuZHJ5IDwgMCIpKQpocmd1bmxhdGUyPC1wbG90KGh5cG90aGVzaXMoaHlwbW9kMiwgIm1GZ3VuOnNGbGF0ZS5kcnkgPCAwIikpCgpocnRyYXByYWlueTwtcGxvdChoeXBvdGhlc2lzKGh5cG1vZCwgIm1GdHJhcHBlcjpzRnJhaW55IDwgMCIpKQpocnRyYXByYWlueTI8LXBsb3QoaHlwb3RoZXNpcyhoeXBtb2QyLCAibUZ0cmFwcGVyOnNGcmFpbnkgPCAwIikpCgpoZGF5czwtcGxvdChoeXBvdGhlc2lzKGh5cG1vZCwnemRheXMgPiAwJykpCmhkYXlzMjwtcGxvdChoeXBvdGhlc2lzKGh5cG1vZDIsJ3pkYXlzID4gMCcpKQoKc3VtbWFyeShoeXBtb2QpCnN1bW1hcnkoaHlwbW9kMikKCiNodHJhcDtodHJhcDI7CiNoZ3RyYXA7aGd0cmFwMjsKCgpgYGAKCnBsb3RzIG9mIHBvc3RlcmlvciBwYXJhbWV0ZXIgZGlzdHJpYnV0aW9ucywgcHJldHR5IGdvb2QgZXZpZGVuY2UgdGhhdCB0cmlwcyB0aGF0IGhhZCBhbiBleHRyYSBwZXJzb24gaGFkIGhpZ2hlciBjYXRjaCB0aGFuIHRob3NlIHdoaWNoIGRpZG4ndCAobWFrZXMgc2Vuc2UsIGVzcGVjaWFsbHkgaWYgaHVudGVycyByZXBvcnQgdGhlaXIgaGVscGVycycgY2F0Y2ggYXMgcGFydCBvZiB0aGVpciBvd24pCmBgYHtyfQpoeAoKYGBgCgpgYGB7cn0KaHgyCgpgYGAKCkFsc28gdGhhdCBodW50aW5nIHRyaXBzIHdoZXJlIGJvdGggZ3VucyBhbmQgdHJhcHBpbmcgd2VyZSB1c2VkIGhhZCBoaWdoZXIgY2F0Y2ggdGhhbiB0aG9zZSBvbmx5IHVzaW5nIG9uZSBtZXRob2QsIG5vdCBzaG93biBoZXJlIHRoZSBlc3RpbWF0ZSBmb3IgdHJhcHBlcnMgc3VnZ2VzdHMgbm8gZGlmZmVyZW5jZSBiZXR3ZWVuIHRyYXBwZXJzIGFuZCBndW4gaHVudGVycwoKYGBge3J9CmhndW4KYGBgCgpgYGB7cn0KaGd1bjIKYGBgCgpubyBldmlkZW5jZSB0aGF0IHRyYXBwZXJzIGRpZCBtb3JlIHBvb3JseSBpbiB0aGUgcmFpbnkgc2Vhc29uIHRoYW4gdGhlIGVhcmx5IGRyeSBzZWFzb24gKHdoaWNoIGlzIHRoZSBmYWN0b3IgYmFzZWxpbmUpCgpgYGB7cn0KaHJ0cmFwcmFpbnkKYGBgCgpgYGB7cn0KaHJ0cmFwcmFpbnkyCmBgYAoKYW5kIGh1bnRlcnMgY2F0Y2ggbW9yZSBvbiBsb25nZXIgdHJpcHMgKGR1aCkuCmBgYHtyfQpoZGF5cwpgYGAKCmBgYHtyfQpoZGF5czIKYGBgCgpDaGFuZ2luZyB0aGUgcHJpb3JzIHRvIGJlIGxlc3MgcmVzdHJpY3RpdmUgb24gdGhlIGZpeGVkIGVmZmVjdHMgcGFyYW1ldGVycyBzZWVtcyBsaWtlIGEgZ29vZCBpZGVhIHNvIEkgdHJ5IHRoYXQKCmBgYHtyfQoKaHJYTVMzYjwtIGJybShkYXRhID0gZGgsIGZhbWlseSA9IHBvaXNzb24sCiAgICAgICAgICAgICAgYyB+IDAgKyBpbnRlcmNlcHQgK3hGK21GK3NGK21GOnNGK3pkYXlzKygxfHZpbGwpKygxfGh0KSwKICAgICAgICAgICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDUpLCBjbGFzcyA9IGIsIGNvZWYgPSBpbnRlcmNlcHQpLAogICAgICAgICAgICAgICAgICAgICAgICBwcmlvcihub3JtYWwoMCwgMC41KSwgY2xhc3MgPSBiKSwKICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMiksIGNsYXNzID0gc2QpKSwKICAgICAgICAgICAgICBpdGVyPTQwMDAsY29yZXM9Mixjb250cm9sPWxpc3QoYWRhcHRfZGVsdGE9MC45KSxzYW1wbGVfcHJpb3I9VCxmaWxlPSIvVXNlcnMvbWljaGFlbGdhcmJvL0RvY3VtZW50cy9DQVRDSF9TT1VSQ0VTX0NIQVBURVIvQ0FUQ0hfYWxsX3dvcmtpbmdfUi9icm1zX21vZGVscy9oclhNaVMzYiIpCgpzdW1tYXJ5KGhyWE1TM2IpCmBgYAoKYW5kIEknbSBzdGlsbCBxdWl0ZSBzdXJwcmlzZWQgYnkgdGhlIHBvc3RlcmlvciBvZiB0aGUgaW50ZXJhY3Rpb24gcGFyYW1ldGVyIGZvciB0cmFwcGVycyBpbiB0aGUgcmFpbnkgc2Vhc29uLCBhbHRob3VnaCB0aGUgb3RoZXIgcG9zdGVyaW9yIHBhcmFtZXRlcnMgaGF2ZSBtb3JlIG1hc3Mgb24gMCBidXQgaGF2ZSBsYXJnZSB1bmNlcnRhaW50eS4gVGhlbiBJIGxlYXJuZWQgdGhhdCB0aGUgZXN0aW1hdGUgb2YgYW4gaW50ZXJhY3Rpb24gaGFzIHR3aWNlIHRoZSBzdGFuZGFyZCBlcnJvciBvZiBhbiBlc3RpbWF0ZSBmb3IgYSBtYWluIGVmZmVjdCwgc28gYWN0dWFsbHkgdGhpcyBpcyBpbmV2aXRhYmxlLiBBbHNvIGl0IG1lYW5zIHRoYXQgSSBhbG1vc3QgY2VydGFpbmx5IGRvbid0IGhhdmUgYW55d2hlcmUgbmVhciBlbm91Z2ggZGF0YSB0byBlc3RpbWF0ZSBhbiBpbnRlcmFjdGlvbiBlZmZlY3QsIGFsdGhvdWdoIEkgZ3Vlc3MgdGhhdCBkb2Vzbid0IG1lYW4gSSBzaG91bGQgbm90IGhhdmUgaXQgaW4gdGhlIG1vZGVsLgoKYGBge3J9CmhydHJhcHJhaW55MzwtcGxvdChoeXBvdGhlc2lzKGhyWE1TM2IsICJtRnRyYXBwZXI6c0ZyYWlueSA8IDAiKSkKYGBgCgpgYGB7cn0KcGxvdChoeXBvdGhlc2lzKGhyWE1TM2IsICJtRnRyYXBwZXI6c0ZsYXRlLmRyeSA8IDAiKSkKYGBgCgpgYGB7cn0KcGxvdChoeXBvdGhlc2lzKGhyWE1TM2IsICJtRmd1bjpzRnJhaW55IDwgMCIpKQpgYGAKCmxvb2tpbmcgYmFjayBhdCB0aGUgcmF3IGRhdGEgc2hvd3MgdGhlcmUgYXJlIG9ubHkgOCBkYXRhIHBvaW50cyBmb3IgdHJhcHBlcnMgaW4gdGhlIHJhaW55IHNlYXNvbiwgYW5kIHRoZWlyIGNhdGNoIGlzIHF1aXRlIHZhcmlhYmxlIGFuZCB0aGVyZSBpcyBub3Qgb2J2aW91c2x5IGEgYmlnIGludGVyYWN0aW9uIGVmZmVjdCBidXQgY29uZGl0aW9uaW5nIG9uIHRoZSBpbnRlcmFjdGlvbiBtaWdodCBoZWxwIGdldCBtb3JlIHJlYXNvbmFibGUgcGFyYW1ldGVyIGRpc3RyaWJ1dGlvbnMgZm9yIHRoZSBtYWluIGVmZmVjdHMuCgpgYGB7ciBlY2hvPVRSVUV9CmRoaDwtbXV0YXRlKGRoLGNwZD1jL3RyaXBkYXlzKQoKZGF0YXAxPC1nZ3Bsb3QoZGhoLGFlcyh4PW1GLHk9Y3BkLGFscGhhPTAuNSxjb2xvdXI9c0YpKStnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2ppdHRlcmRvZGdlKCkpK2dlb21fYm94cGxvdCh2YXJ3aWR0aD1UKQpkYXRhcDI8LWdncGxvdChkaGgsYWVzKHg9c0YseT1jcGQsYWxwaGE9MC41LGNvbG91cj1tRikpK2dlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25faml0dGVyZG9kZ2UoKSkrZ2VvbV9ib3hwbG90KHZhcndpZHRoPVQpCmRhdGFwMzwtZ2dwbG90KGRoaCxhZXMoeD1tRix5PWMsYWxwaGE9MC41LGNvbG91cj1zRikpK2dlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25faml0dGVyZG9kZ2UoKSkrZ2VvbV9ib3hwbG90KHZhcndpZHRoPVQpCmRhdGFwNDwtZ2dwbG90KGRoaCxhZXMoeD1zRix5PWMsYWxwaGE9MC41LGNvbG91cj1tRikpK2dlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25faml0dGVyZG9kZ2UoKSkrZ2VvbV9ib3hwbG90KHZhcndpZHRoPVQpCgpkYXRhcDEKZGF0YXAyCmRhdGFwMwpkYXRhcDQKYGBgCgpHaXZlbiB0aGF0IHRoZXJlIGlzbid0IG11Y2ggZGF0YSBmb3IgdGhpcyBjb25kaXRpb24gaW4gdGhlIGludGVyYWN0aW9uIHRlcm0sIEkgZ3Vlc3MgdGhlcmVzIGEgcmlzayB0aGF0IHdoYXRldmVyIHByaW9ycyBJIGNob29zZSBtYXkgaW5mbHVlbmNlIHRoZSBwb3N0ZXJpb3Igc29tZXdoYXQuIFNvIEknbSBnb2luZyB0byBzdGljayB3aXRoIHRoZSBub3JtYWwoMCwwLjUpIG9wdGlvbiBmb3Igbm93LCBhbmQgYmUgY2F1dGlvdXMgYWJvdXQgaW50ZXJwcmV0aW5nIHRoZSBlZmZlY3RzIG9mIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIG1ldGhvZHMgYW5kIHNlYXNvbi4gIEFsc28gSSB3YW50IHRvIGxvb2sgYXQgdGhlIG91dCBvZiBzYW1wbGUgcGVyZm9ybWFuY2UgZm9yIHRoZXNlIG1vZGVscy4uLi4KClRoZSBMT08tUFNJUyBjaGVjayBzdGlsbCBzaG93cyB0aGF0IGluZGl2aWR1YWwgZGF0YSBwb2ludHMgaGF2ZSBzdWJzdGFudGlhbCBpbXBhY3RzIG9uIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9ucywgc28gSSB1c2Uga2ZvbGQgY3Jvc3MtdmFsaWRhdGlvbiB0byBzZWUgd2hldGhlciB0YWtpbmcgb3V0IGFueSBvZiB0aGUgY292YXJpYXRlcyBtYWtlcyBhIGJpZyBkaWZmZXJlbmNlIGluIHRlcm1zIG9mIGhvdyBtb2RlbCBmaXQuCgpgYGB7ciBlY2hvPVRSVUV9CiMgcmVmaXR0aW5nIG1vZGVscyBhbmQgZG9pbmcga2ZvbGQgQ1YuLi5Eb250IHJ1biB0aGlzISBpdCB3aWxsIHRha2UgYWdlcy4KIyB3aXRob3V0IHRoZSBpbnRlcmFjdGlvbgojaHJYTVM0PC11cGRhdGUoaHJYTVMzYSwufi4tbUY6c0YsY29yZXM9MixmaWxlPSIvVXNlcnMvbWljaGFlbGdhcmJvL0RvY3VtZW50cy9DQVRDSF9TT1VSQ0VTX0NIQVBURVIvQ0FUQ0hfYWxsX3dvcmtpbmdfUi9icm1zX21vZGVscy9oclhNUzQiKQoKIyAgd2l0aG91dCBleHRyYSBodW50ZXJzCiNock1TNDwtdXBkYXRlKGhyWE1TM2EsLn4uLXhGLGNvcmVzPTIsZmlsZT0iL1VzZXJzL21pY2hhZWxnYXJiby9Eb2N1bWVudHMvQ0FUQ0hfU09VUkNFU19DSEFQVEVSL0NBVENIX2FsbF93b3JraW5nX1IvYnJtc19tb2RlbHMvaHJNUzQiKQoKIyB3aXRob3V0IGludGVyYWN0aW9uIG9yIGV4dHJhIGh1bnRlcnMKI2hyTVM1PC11cGRhdGUoaHJNUzQsLn4uLW1GOnNGLGNvcmVzPTIsZmlsZT0iL1VzZXJzL21pY2hhZWxnYXJiby9Eb2N1bWVudHMvQ0FUQ0hfU09VUkNFU19DSEFQVEVSL0NBVENIX2FsbF93b3JraW5nX1IvYnJtc19tb2RlbHMvaHJNUzUiKQoKIyB3aXRob3V0IHNlYXNvbgojaHJNWDQ8LXVwZGF0ZShoclhNUzQsLn4uLXNGLGNvcmVzPTIsZmlsZT0iL1VzZXJzL21pY2hhZWxnYXJiby9Eb2N1bWVudHMvQ0FUQ0hfU09VUkNFU19DSEFQVEVSL0NBVENIX2FsbF93b3JraW5nX1IvYnJtc19tb2RlbHMvaHJYTTQiKQoKI2hyWE1TM3BjPC1hZGRfY3JpdGVyaW9uKGhyWE1TM3BjLGNyaXRlcmlvbj0na2ZvbGQnKQojaHJYTVMzYjwtYWRkX2NyaXRlcmlvbihoclhNUzNiLGNyaXRlcmlvbj0na2ZvbGQnKQojaHJYTVMzYTwtYWRkX2NyaXRlcmlvbihoclhNUzNhLGNyaXRlcmlvbj0na2ZvbGQnKQojaHJYTVM0PC1hZGRfY3JpdGVyaW9uKGhyWE1TNCxjcml0ZXJpb249J2tmb2xkJykKI2hyTVM1PC1hZGRfY3JpdGVyaW9uKGhyTVM1LGNyaXRlcmlvbj0na2ZvbGQnKQojaHJNWDQ8LWFkZF9jcml0ZXJpb24oaHJNWDQsY3JpdGVyaW9uPSdrZm9sZCcpCiNock1TNDwtYWRkX2NyaXRlcmlvbihock1TNCxjcml0ZXJpb249J2tmb2xkJykKCiMgYWZ0ZXIgc2F2aW5nIGFsbCB0aGUgYWJvdmUgbW9kZWwgZml0cywgdGhleSBjYW4ganVzdCBiZSBsb2FkZWQgaW50byB0aGUgd29ya3NwYWNlCmhyWE1TM2E8LXJlYWRSRFMoIi9Vc2Vycy9taWNoYWVsZ2FyYm8vRG9jdW1lbnRzL0NBVENIX1NPVVJDRVNfQ0hBUFRFUi9DQVRDSF9hbGxfd29ya2luZ19SL2JybXNfbW9kZWxzL2hyWE1TM2EucmRzIikKaHJYTVM0PC1yZWFkUkRTKCIvVXNlcnMvbWljaGFlbGdhcmJvL0RvY3VtZW50cy9DQVRDSF9TT1VSQ0VTX0NIQVBURVIvQ0FUQ0hfYWxsX3dvcmtpbmdfUi9icm1zX21vZGVscy9oclhNUzQucmRzIikKaHJNUzU8LXJlYWRSRFMoIi9Vc2Vycy9taWNoYWVsZ2FyYm8vRG9jdW1lbnRzL0NBVENIX1NPVVJDRVNfQ0hBUFRFUi9DQVRDSF9hbGxfd29ya2luZ19SL2JybXNfbW9kZWxzL2hyTVM1LnJkcyIpCmhyTVg0PC1yZWFkUkRTKCIvVXNlcnMvbWljaGFlbGdhcmJvL0RvY3VtZW50cy9DQVRDSF9TT1VSQ0VTX0NIQVBURVIvQ0FUQ0hfYWxsX3dvcmtpbmdfUi9icm1zX21vZGVscy9oclhNNC5yZHMiKQpock1TNDwtcmVhZFJEUygiL1VzZXJzL21pY2hhZWxnYXJiby9Eb2N1bWVudHMvQ0FUQ0hfU09VUkNFU19DSEFQVEVSL0NBVENIX2FsbF93b3JraW5nX1IvYnJtc19tb2RlbHMvaHJNUzQucmRzIikKaHJYTVMzcGM8LXJlYWRSRFMoIi9Vc2Vycy9taWNoYWVsZ2FyYm8vRG9jdW1lbnRzL0NBVENIX1NPVVJDRVNfQ0hBUFRFUi9DQVRDSF9hbGxfd29ya2luZ19SL2JybXNfbW9kZWxzL2hyWE1TM3BjLnJkcyIpCgpsb29fY29tcGFyZShoclhNUzNwYyxoclhNUzNiLGhyWE1TM2EsY3JpdGVyaW9uPSdrZm9sZCcpCmxvb19jb21wYXJlKGhyWE1TM2EsaHJYTVM0LGhyTVM1LGhyTVg0LGNyaXRlcmlvbj0na2ZvbGQnKQpgYGAKClRoZSBtb2RlbHMgd2l0aCBkaWZmZXJlbnQgcHJpb3JzLCBhbmQgd2l0aCBhbmQgd2l0aG91dCB0aGUgaW50ZXJhY3Rpb24gdGVybSBhbmQgZHJvcHBpbmcgdGhlIGZpeGVkIGVmZmVjdHMgZG9uJ3Qgc2VlbSB0byB2YXJ5IG11Y2ggaW4gdGhlaXIgb3V0IG9mIHNhbXBsZSBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlLiBTbyBqdXN0IHN0aWNraW5nIHdpdGggdGhlIG9yaWdpbmFsIG1vZGVsIGZvciBub3cuLi4uCgpTdGFydCB0byBleHBsb3JlIHRoZSBwb3N0ZXJpb3IgaW4gbW9yZSBkZXRhaWwsIGUuZy4gbG9vayBhdCB2aWxsYWdlIGFuZCBodW50ZXIgbGV2ZWwgdmFyaWF0aW9uIGluIGludGVyY2VwdHMKCmBgYHtyIGVjaG89VFJVRX0KcmVxdWlyZSh0aWR5YmF5ZXMpCnJlcXVpcmUobWFncml0dHIpCnJlcXVpcmUoZ2dyaWRnZXMpCgojIGxvb2sgYXQgdGhlIHZpbGxhZ2UgbGV2ZWwgdmFyaWFuY2UKcnZpbGxzPC1tb2QgJT4lCiAgc3ByZWFkX2RyYXdzKGJfaW50ZXJjZXB0LCByX3ZpbGxbY29uZGl0aW9uLF0pICU+JQogIG11dGF0ZShjb25kaXRpb25fbWVhbiA9IGJfaW50ZXJjZXB0ICsgcl92aWxsKSAlPiV1bmdyb3VwKCklPiVtdXRhdGUoY29uZGl0aW9uID0gcmVvcmRlcihjb25kaXRpb24sIGNvbmRpdGlvbl9tZWFuKSxyZXNwb25zZV9tZWFuPWV4cChjb25kaXRpb25fbWVhbikpCgojIHBsb3QgcG9zdGVyaW9yIG9mIHZpbGxhZ2UgaW50ZXJjZXB0cyAKdmlsbGludHM8LXJ2aWxscyU+JQogIGdncGxvdDI6OmdncGxvdChnZ3Bsb3QyOjphZXMoeSA9IGNvbmRpdGlvbiwgeCA9IGNvbmRpdGlvbl9tZWFuKSkgK2dlb21faGFsZmV5ZWgoKQoKIyByZXNwb25zZSBzY2FsZSBnaXZlcyBhIGJldHRlciBpZGVhIG9mIHZhcmlhdGlvbgp2aWxsaW50c1I8LXJ2aWxscyU+JQogIGdncGxvdDI6OmdncGxvdChnZ3Bsb3QyOjphZXMoeSA9IGNvbmRpdGlvbiwgeCA9IHJlc3BvbnNlX21lYW4pKSArZ2VvbV9oYWxmZXllaCgpCgojIGxvb2sgYXQgdGhlIHZpbGxhZ2UgYW5kIGh1bnRlciBsZXZlbCB2YXJpYXRpb24gc2ltdWx0YW5lb3VzbHkgd2l0aCBhbGwgb3RoZXIgdmFycyBhdCBiYXNlbGluZSBjb25kaXRpb25zCgojYm90aCBodCBhbmQgdmlsbCBpbnRlcmNlcHRzIGNvbWJpbmVkCnJ2aWxsaHQ8LW1vZCAlPiUKICBzcHJlYWRfZHJhd3MoYl9pbnRlcmNlcHQsIHJfaHRbY29uZGl0aW9uLF0scl92aWxsW3ZpbGxjb25kLF0pICU+JQogIG11dGF0ZShjb25kaXRpb25fbWVhbiA9IGJfaW50ZXJjZXB0ICsgcl9odCtyX3ZpbGwpICU+JXVuZ3JvdXAoKSU+JW11dGF0ZShjb25kaXRpb24gPSByZW9yZGVyKGNvbmRpdGlvbiwgY29uZGl0aW9uX21lYW4pKQoKIyBqdXN0IGxvb2sgYXQgdmlsbGFnZS1odW50ZXIgY29tYmluYXRpb25zIHRoYXQgZXhpc3QgKGh1bnRlcnMgYXJlIG5lc3RlZCBpbiB2aWxsYWdlcykKdmlsbGh0Yzwtc2VsZWN0KGRoLHZpbGwsaHQpJT4lbXV0YXRlKHZoPXBhc3RlKHZpbGwsaHQsc2VwPSIiKSklPiVkaXN0aW5jdCgpCgpydnJlYWw8LW11dGF0ZShydmlsbGh0LHZoPXBhc3RlKGFzLmNoYXJhY3Rlcihjb25kaXRpb24pLHZpbGxjb25kLHNlcD0iIikpJT4lZmlsdGVyKHZoJWluJXZpbGxodGMkdmgpJT4lZHJvcGxldmVscygpCgojIHBsb3RzIHdpdGggYSBwYW5lbCBmb3IgZWFjaCB2aWxsYWdlIGFuZCBwb3N0ZXJpb3IgaW50ZXJjZXB0cyBvZiBodW50ZXJzIHdpdGggZml4ZWQgZWZmZWN0cyBhdCBiYXNlIGxldmVscyBvbiBwcmVkaWN0b3Igc2NhbGUKYm90aGludHMxPC1maWx0ZXIocnZyZWFsLHZpbGxjb25kJWluJWMoMTo5KSklPiVnZ3Bsb3QyOjpnZ3Bsb3QoZ2dwbG90Mjo6YWVzKHkgPSBjb25kaXRpb24sIHggPSBjb25kaXRpb25fbWVhbikpICtnZW9tX2hhbGZleWVoKCkrZ2dwbG90Mjo6ZmFjZXRfd3JhcCh+dmlsbGNvbmQsc2NhbGVzPSdmcmVlX3knKQoKYm90aGludHMyPC1maWx0ZXIocnZyZWFsLHZpbGxjb25kJWluJWMoMTA6MTgpKSU+JWdncGxvdDI6OmdncGxvdChnZ3Bsb3QyOjphZXMoeSA9IGNvbmRpdGlvbiwgeCA9IGNvbmRpdGlvbl9tZWFuKSkgK2dlb21faGFsZmV5ZWgoKStnZ3Bsb3QyOjpmYWNldF93cmFwKH52aWxsY29uZCxzY2FsZXM9J2ZyZWVfeScpCgojIGp1c3QgZGlzcGxheSB2aWxsYWdlIGludGVyY2VwdHMgb24gcmVzcG9uc2Ugc2NhbGUgdG8gc2F2ZSB0aW1lLi4uCgp2aWxsaW50c1IKCmBgYAoKVGhlIG92ZXJhbGwgbWFyZ2luYWwgZWZmZWN0cyBvZiB0aGlzIG1vZGVsIChwcmVkaWN0ZWQgY2F0Y2ggZm9yIHRoZSBiYXNlbGluZSBmYWN0b3IgbGV2ZWxzKSBsb29rIHByZXR0eSBzaW1pbGFyIHRvIHRob3NlIGluIHRoZSBmaXJzdCBtb2RlbCB3aGljaCBoYWQgYSByYW5kb20gc2xvcGUgYW5kIHdlYWtlciBwcmlvcnMuCgpgYGB7ciBlY2hvPVRSVUV9CiMgaWdub3JpbmcgcmFuZG9tIGVmZmVjdHMKbXA8LW1hcmdpbmFsX2VmZmVjdHMobW9kLHJlX2Zvcm11bGE9TkEscGxvdD1GKQpwcDwtcGxvdChtcCxhc2s9Rixwb2ludHM9VCxwb2ludF9hcmdzPWxpc3Qod2lkdGg9MC4zLGFscGhhPTAuNikpCnBwW1s0XV0rZ2dwbG90Mjo6eGxpbSgtMSwyKStnZ3Bsb3QyOjp5bGltKDAsNDApICMgem9vbWluZyBpbiBvbiB0aGUgemRheXMgbm90ZSB0aGUgcG9pbnRzIGFyZSBmb3IgYmFzZWxpbmUgZmFjdG9yIGxldmVscyBvbmx5CgojIGluY2x1ZGluZyB0aGUgcmFuZG9tIGVmZmVjdHMgYW5kIHNwYWdoZXR0aSBwbG90IAptcHM8LW1hcmdpbmFsX2VmZmVjdHMobW9kLHJlX2Zvcm11bGE9TlVMTCxzcGFnaGV0dGk9VCxuc2FtcGxlcz01MDAscGxvdD1GKQpwbG90KG1wcyxhc2s9Rixwb2ludHM9VCxwb2ludF9hcmdzPWxpc3Qod2lkdGg9MC4zLGFscGhhPTAuNikpW1s0XV0rZ2dwbG90Mjo6eGxpbSgtMSwyLjA0KStnZ3Bsb3QyOjp5bGltKDAsNDApCgpgYGAKCg==