1 Download Select Model

The final SAM run, the model output, data and config are directly taken from stockassessment.org.

samfit <- fitfromweb("ple.27.21-32_WKBPLAICE_2024_nmG5Fb_mo1_dsmed6")

## extract relevant data from model
asum <- as.data.frame(summary(samfit))
asum$Year <- as.integer(row.names(summary(samfit)))
colnames(asum) <- c("R_age1", "Rlow", "Rhigh", "SSB", "SSBlow", "SSBhigh", "Fbar",
    "Flow", "Fhigh", "Year")

The chosen assessment run, as well as the settings and details on sensitivity runs, etc. are explained in the WKBPLAICE report and the accompanying working documents: WD1 Stock Identity and stock merging WD2 Stock coordination and data overviews WD3 Overview of the assessment runs and sensitivity WD4 New natural mortality WD5 Inclusion of discard survival

2 Create EQ-Sim Input Data

2.1 Inputs from Model

EQSIM requires data in the “FLStock” format. The downloaded SAM object is transformed, adding a description of the stock, computes total weights and add respective units.

stk <- SAM2FLStock(samfit, stock.wt_est = TRUE)

# PJW: Trim off last year of the stock object (only if incomplete data for last
# assessment year)
origStk <- stk
stk <- window(stk, start = range(stk)["minyear"], end = (range(stk)["maxyear"] -
    1))

# add name and description of the stock
name(stk) <- stockName <- "PLE.27.21-32"
desc(stk) <- "Plaice in the Baltic Sea and Kattegat"

## Units
units(catch(stk)) <- units(discards(stk)) <- units(landings(stk)) <- units(stock(stk)) <- "t"
units(catch.n(stk)) <- units(discards.n(stk)) <- units(landings.n(stk)) <- units(stock.n(stk)) <- "1000"
units(catch.wt(stk)) <- units(discards.wt(stk)) <- units(landings.wt(stk)) <- units(stock.wt(stk)) <- "kg"


# overview of data imported into the FLStock (from the SAM output)
summary(stk)
## An object of class "FLStock"
## 
## Name: PLE.27.21-32 
## Description: Plaice in the Baltic Sea and Kattegat 
## Quant: age 
## Dims:  age   year    unit    season  area    iter
##  7   22  1   1   1   1   
## 
## Range:  min  max pgroup  minyear maxyear minfbar maxfbar 
##  1   7   7   2002    2023    3   6   
## 
## Metrics: 
##   rec: 161059 - 7109328  (1000) 
##   ssb: 8698 - 76471  (t) 
##   catch: 2502 - 7438  (t) 
##   fbar: 0.053 - 0.584  (f)

2.2 User specified inputs

Some manual inputs and configuration for EQ-sim are required. For the later calculation of reference points, the data year and time series range are set. The forecast errors are set to default values, while the uncertainties of the last year (sigmaF and sigma SSB) are taken directly from the SAM output.

# Simulation settings
DataYear <- 2023
minYear <- range(stk)["minyear"]
maxYear <- range(stk)["maxyear"]  #PJW: now corresponds with DataYear due to trimming the stock object

## Number of sims
noSims <- 1000  #PJW: Would be better to upgrade to 2000 with final run
rhoRec <- T

## Forecast error
cvF <- 0.25
phiF <- 0.3  # cvF  <- 0.212default values, look in WKMSYREF4 (although confusion with 0.233?)
cvSSB <- 0
phiSSB <- 0

## 5th percentile of SSB in the final year of the assessment
SSB05 <- 0  # used in MSY Btrigger calculation. If set at 0, ignored

## Uncertainty last year PJW: removed -1 because this fixed by trimming stk
## object F
sigmaF <- samfit$sdrep$sd[names(samfit$sdrep$value) == "logfbar"][samfit$data$years %in%
    (max(samfit$data$years))]  # Extracts the last FULL year's sd(log(Fbar)) value from the model object

### SSB
sigmaSSB <- samfit$sdrep$sd[names(samfit$sdrep$value) == "logssb"][samfit$data$years %in%
    (max(samfit$data$years))]  # Extracts the last FULL year's sd(log(SSB)) value from the model object

# Display all settings
all_settings <- data.frame(min_Year = minYear, max_year = maxYear, cvF = cvF, PhiF = phiF,
    cvSSB = cvSSB, phiSSB = phiSSB, SSB05 = SSB05, sigmaF = sigmaF, sigmaSSB = sigmaSSB)

kable(all_settings, caption = "all settings for the refpoint calculations")
(#tab:ref-point setttings)all settings for the refpoint calculations
min_Year max_year cvF PhiF cvSSB phiSSB SSB05 sigmaF sigmaSSB
minyear 2002 2023 0.25 0.3 0 0 0 0.3247452 0.1161913

2.3 calculate landings, discards and catch from input numbers and weight

landings(stk) <- computeLandings(stk)
discards(stk) <- computeDiscards(stk)
# and then the catch slots from both landings and discards
catch(stk) <- computeCatch(stk, slot = "all")

stock(stk) <- computeStock(stk)

plot(stk)
Summary of stock object.

(#fig:compute total weights)Summary of stock object.

plot(metrics(stk, Catch = catch, Landings = landings))

2.4 Selectivity/catchability

Aged-based selectivity/catchability plots as requested by working group.

ages <- samfit$conf$minAge:samfit$conf$maxAge
years <- samfit$data$years
meanFages <- samfit$conf$fbarRange

# ### Elliot's corrected version, of what seems a pointless exchange. . . .
# harvest(stk) <- exp(samfit$pl$logF)[c(ages[-length(ages)], (max(ages)-1)),]

meanF <- apply(harvest(stk)[as.character(meanFages), ], 2, "mean")
sel <- sweep(harvest(stk), 2, meanF, "/")

plot(ages, sel[, ac(max(years) - 1)], type = "l", ylim = c(0, max(sel)), xlab = "Age",
    ylab = "Selectivity", main = "Selectivity")
for (i in ac((maxYear - 19):maxYear)) lines(ages, sel[, i], col = i)
lines(ages, apply(sel[, ac((maxYear - 2):maxYear)], 1, mean), col = 1, lwd = 5)
lines(ages, apply(sel[, ac((maxYear - 4):maxYear)], 1, mean), col = 2, lwd = 5)
lines(ages, apply(sel[, ac((maxYear - 9):maxYear)], 1, mean), col = 3, lwd = 5)
lines(ages, apply(sel[, ac((maxYear - 19):maxYear)], 1, mean), col = 4, lwd = 5)
legend("topleft", legend = c("Mean last 3yrs", "Mean last 5yrs", "Mean last 10yrs",
    "Mean last 20yrs"), lwd = 5, col = 1:4, bty = "n")
Selectivity/Catchability of the stock, over time, by age.

(#fig:catchability plots)Selectivity/Catchability of the stock, over time, by age.

3 Choice of stock recruitment model

Many investigations were made to try and choose an appropriate stock-recruitment model. However, the working group agreed that there was no suitable standard model to fit these data. As can be seen below, the stock starts in a “low productivity” state with relatively low SSB and recruitment, but then rapidly rises in recent history, in an almost linear trend with no sign of reaching an asymptote. Because of this dramatic change and the fact that the stock is still not reaching some form of equilibrium all standard models assume an infinite relationship with no cap on recruitment.

To view the detail of the data at the beginning of the time series, click and drag a rectangle over the bottom left portion of the plot area.

ggplotly(ggplot(asum, mapping = aes(x = SSB, y = R_age1)) + geom_path(colour = ebpal[1]) +
    geom_text(mapping = aes(label = Year), colour = ebpal[2], alpha = 0.5) + xlab("SSB (tonnes)") +
    ylab("Recruitment (numbers)") + theme_clean())

Figure 3.1: Stock Recruitment Relationship.

To better view the trends, across the large shift in scale, we can also visualize this in the log-scale.

ggplotly(ggplot(asum, mapping = aes(x = SSB, y = log(R_age1))) + geom_path(colour = ebpal[1]) +
    geom_text(mapping = aes(label = Year), colour = ebpal[2], alpha = 0.5) + xlab("SSB (tonnes)") +
    ylab("Recruitment (log of numbers)") + theme_clean())

(#fig:SR relation)SRR of ple.27.21-32. R is log-scaled to enhance the resolution of th early years in the time-series.

When we force a segmented regression (hockey-stick) through the data, the result is indicative of the non-equilibrium status of the stock, with no identified break-point.

set.seed(123)
eqfit <- eqsr_fit(stk = stk, nsamp = noSims, models = c("Segreg"))
# models = c('Smooth_hockey','Bevholt', 'Segreg'))
# eqsr_plot(eqfit)
eqsr_plot(eqfit, n = 20000, ggPlot = TRUE, Scale = 1000)  #nicer ggplot colors 
Segmented regression fit of stock-recruitment data.

(#fig:eqsim SR plot fitted)Segmented regression fit of stock-recruitment data.

To further interrogate the potential relationships between ssb and recruitment, we can visualise it another way, using a direct ratio of recruits per SSB.

stockName <- "ple.27.21-32"
df <- data.frame(summary(samfit))
df$year <- rownames(df)
rownames(df) <- NULL

rec <- df[2:nrow(df), "R.age.1."]  # in raw numbers.
ssb <- df[1:(nrow(df) - 1), "SSB"]  # in tonnes.
df$rec.ssb <- c(NA, (rec/ssb))

ggplot(data = df) + geom_point(mapping = aes(x = year, y = rec.ssb), shape = 0) +
    geom_line(mapping = aes(x = year, y = rec.ssb, group = 1), linetype = "dashed") +
    xlab("Year of recruitment") + ylab("Recruitment (000's) /\nSSB of the previous year (tonnes)") +
    theme_clean() + theme(axis.text.x.bottom = element_text(angle = 90, vjust = 0.5))
Recruits per SSB over time.

(#fig:plot R per ssb)Recruits per SSB over time.

4 Preparation of reference point calculation

4.1 Guidelines and other precedents

ICES has specific guidelines for determining reference points. The guidelines can be found here

As demonstrated above, no stock-recruitment relationship can be estimated from the data, so a Stock Type 2 stock-recruitment categorization was ruled out. This was investigated both with and without the 5 last years of data, where the stock appears to be shifting into a new regime.

Although the stock-recruitment pattern was visually similar to a Stock Type 3, this category was ruled out because this plaice stock is caught mainly as a bycatch fishery, and it was not believed by experts that the entire time series could be reflective of an overfished period. It was instead believed that that earliest years could reflect an overfished state with recruitment impairment due to high discarding of plaice in the targeted cod fishery, but it would be difficult to justify a belief that recruitment impairment could be experienced also in the latter portion of the time series.

Therefore, after much discussion, it was determined that this stock falls either into type 1 or 5 (from the aforementioned guidelines).

5 Calculate reference points

Before we begin calculating the various reference points, we must first decide on some data truncation and settings for the simulation.

Because of the rapid changes in stock dynamics in recent years, the decision was made to run simulations for reference points based on the period before stock-weights-at-age began to decline, recruitment increased and SSB increased. It was thought that this most recent period of high recruitment of poor-condition reflects a rare episode of overshooting carrying capacity, so experts expected that this period is unlikely to continue in the long-term.

## Reference points
refPts <- matrix(NA, nrow = 1, ncol = 9, dimnames = list("value", c("Btrigger", "Bpa",
    "Blim", "5thPerc_SSBmsy", "Fpa", "Flim", "Fp05", "Fmsy_unconstr", "Fmsy")))

ssb_med <- median(ssb)
rec_med <- median(rec)

## Years by which to truncate dataset.
rmSRRYrs <- c(2019:maxYear)  # specify here which other years (e.g. early period) should be left out
# PJW removed here redundant maxYear def and added maxYear to above

## Decisions and settings for use in forward simulations How many years to
## average over (resample from) for biological data
numAvgYrsB <- 5  #PJW: I changed this to 5 from 10 for testing... I think we said either was ok
### How many years to sample from for stock variability
numAvgYrsS <- 5  #PJW: I changed this to 5 from 10 for testing... I think we said either was ok
srYears <- setdiff(c(minYear:(maxYear)), rmSRRYrs)
Nruns <- 200
FsToScan <- seq(0, 1, by = 0.005)  #seq(0, 0.9, len = 200) # changed max to 1 - earlier versions you showed did not have leveling off in Flim runs so F needs to be increased

5.1 Calculate/estimate \(B_{lim}\) and \(B_{pa}\)

Blim is the key PA reference point. The other precautionary approach points (Bpa, Flim, and Fpa) are all estimated from Blim. In a few cases, the available information does not allow direct estimation of Blim; Bpa is then estimated directly, and Blim may be derived from Bpa.

While Stock Types 1 and 5 from the guidelines call for using Bloss as Blim, the experts in the working group recognised that Bloss (2010) is less than many other SSB values that were also low and during a period of high fishing mortality (2002-2009). Therefore, setting Blim to Bloss may not be sufficiently precautionary.

Therefore, we also decided to try to apply the rules used for Gulf of Riga herring, namely that we take as Bpa the mean SSB of those years where:

  • SSB <= median SSB AND
  • recruitment >= median recruitment

The logic here, is that we are finding those years where low SSB still results in relatively high recruitment and using the mean ssb of those years to identify Bpa and calculate Blim from there.

refPts[, "Bpa"] <- mean(df[df$R.age.1. >= median(df$R.age.1.) & df$SSB <= median(df$SSB) &
    df$year != 2024, "SSB"])
refPts[, "Blim"] <- refPts[, "Bpa"]/1.4

kable(refPts)
Btrigger Bpa Blim 5thPerc_SSBmsy Fpa Flim Fp05 Fmsy_unconstr Fmsy
value NA 12180.5 8700.357 NA NA NA NA NA NA

This resulted in a Bpa based on two of the lowest observed SSB in the time series, which corresponded to essentially Bloss by other stock category definitions and a Blim value lower than observed in the time series. Furthermore, this method led to a value appeared to be less than 10% of estimates of B0 (calculated subsequently). Therefore this method was also rejected.

In a second approach, Blim was estimated by using the “empirical approach” and using B empirical as Blim. In a review of ICES reference points Silvar-Viladomiu et al. (2022) found that after Bloss, the most used method to define Blim was an empirical method based on identifying the lowest biomass that resulted in good recruitment. The “StockRecruit” R package available in GitHub provides a function that formalizes this method, and identifies the lowest biomasses that results in above median recruitment. Then Blim is defined as the average of the identified set of lowest biomasses that can be formed by just one point or several. WKNEWREF proposed then a fourth method to define Blim , the ‘empirical approach’, in which Blim is defined as “lowest biomass (SSB) that resulted in a good recruitment (i.e., a recruitment above the median).”

## FLSR object
flsr <- as.FLSR(stk)
S <- an(ssb(flsr))
R <- an(rec(flsr))

# Minimum SSB level that resulted in a recruitment higher that the median.

Blim_emp <- calcBlim(S, R, quant = 0.5, type = 1)

Using the definition of WKNEWREF of 2024 and the “StockRecruitSET” package, the Blim empirical is about 8697.8973408 tons. The empirical Blim is very close the the previously estimated Blim value of 8700.3571429 tons and would face similar issues when used as a reference point. The Blim empirical approach was therefore also rejected.

As no standard solution was found, it was decided to modify the definition of Bloss given for Stock Types 1 and 5 to be based on the mean of several similar SSB values that spanned the ranges of having yielded both decent recruitment in two cases (2010 & 2011) and rather low recruitment in 8 cases (2002:2009). As noted above, setting Bloss to be the minimum SSB observed in 2010 was not considered a candidate for Blim because it’s value was less then the 8 values considered to have yielded rather low recruitment earlier in the time series. Any choice of SSB values greater than the 2010 value was therefore arbitrary, so the expert group decided to include as many as possible to reflect the group of similar SSB and recruitment value early in the time series. The 2002 - 2011 values were deemed ‘decent’ because they appeared to sustain rather stable SSB and recruitment values during the mid-range of the time series, before the productivity shift began in 2021. Bloss was therefore considered to be the mean SSB from the first ten years of the time series, where recruitment and SSB both remained rather low, albeit variable. Furthermore, this method led to a value roughly 15% of estimates of B0 (calculated subsequently), and Blim was set to this newly defined Bloss value.

refPts[, "Blim"] <- mean(df[df$year %in% c(2002:2011), "SSB"])

refPts[, "Bpa"] <- refPts[, "Blim"] * exp(1.645 * sigmaSSB)

kable(refPts)
Btrigger Bpa Blim 5thPerc_SSBmsy Fpa Flim Fp05 Fmsy_unconstr Fmsy
value NA 13460.43 11118.6 NA NA NA NA NA NA

Having agreed and established Blim and Bpa, we now move on to other reference points.

5.2 Calculate \(F_{lim}\) and \(F_{pa}\)

## Refit stock recruitment relationship based on truncated time series
set.seed(123)
eqfit <- eqsr_fit(stk = stk, nsamp = noSims, models = c("Segreg"), remove.years = rmSRRYrs)

## Plot
eqsr_plot(eqfit, n = 20000, ggPlot = TRUE, Scale = 1000)

In forward projections, we can use a hockey-stock function to reflect the stock-recruitment relationship, but force it to use our pre-defined Blim as the breakpoint. This requires fitting the “stick” portion of the hockey-stick function above the breakpoint to recruitment observations.

## determine segreg model with Blim breakpoint and (roughly) geomean rec above
## this
SegregBlim <- function(ab, ssb) log(ifelse(ssb >= refPts[, "Blim"], ab$a * refPts[,
    "Blim"], ab$a * ssb))

# ## determine segreg model with Bloss breakpoint and (roughly) geomean rec
# above this SegregBloss <- function(ab, ssb) log(ifelse(ssb >= min(ssb(stk)),
# ab$a * min(ssb(stk)), ab$a * ssb)) ## Remove the last year from FLstock
# object to prevent NA issues further down (as 2024 is based only on one ) stk1
# <- trim(stk, year =
# c((as.numeric(stk@range['minyear'])):((as.numeric(stk@range['maxyear']))-1)))

## Refit stock recruitment relationship based on truncated time series
set.seed(123)
eqfit <- eqsr_fit(stk = stk, nsamp = noSims, models = c("SegregBlim"), remove.years = rmSRRYrs)
## removing (ssb) years:
##  2019, 2020, 2021, 2022
##   from the recruitment fitting procedure.
## Plot
eqsr_plot(eqfit, n = 20000, ggPlot = TRUE, Scale = 1000)
Eqfit Stock-Recruitment Seg-reg model with Blim breakpoint on truncated dataseries.

(#fig:refit eqfit truncated BlimBreak)Eqfit Stock-Recruitment Seg-reg model with Blim breakpoint on truncated dataseries.

Based on this final stock-recruitment relationship, we can begin to estimate MSY reference points. To calculate Flim, we run a series of simulations with fixed biological parameters and no variability in the estimates of F and SSB.

set.seed(123)
SIM_SegregBlim <- eqsim_run(eqfit, bio.years = c((maxYear - numAvgYrsB), maxYear),
    bio.const = TRUE, sel.years = c((maxYear - numAvgYrsS), maxYear), sel.const = TRUE,
    Fcv = 0, Fphi = 0, SSBcv = 0, rhologRec = rhoRec, Btrigger = 0, Blim = refPts[,
        "Blim"], Bpa = refPts[, "Bpa"], Nrun = Nruns, Fscan = FsToScan, verbose = T)

# save MSY and lim values
tmp1 <- t(SIM_SegregBlim$Refs)
eqsim_plot(SIM_SegregBlim, catch = TRUE)
Plots of stock dynamics under simulation as specified for estimation of Flim.

(#fig:Fpa plots update)Plots of stock dynamics under simulation as specified for estimation of Flim.

refPts[, "Flim"] <- tmp1["F50", "catF"]
tmpFpa <- refPts[, "Flim"] * exp(-sigmaF * 1.645)
# PJW: This is fine but keep in mind later when reporting that this Fpa
# definition is outdated and now based on Fp05
if (tmpFpa < 0.2) refPts[, "Fpa"] <- round(tmpFpa, 3) else refPts[, "Fpa"] <- round(tmpFpa,
    2)
kable(data.frame(refPts[, "Flim"], refPts[, "Fpa"]), col.names = c("Flim", "Fpa"))
Flim Fpa
0.2759123 0.162

The calculated values for Flim and Fpa are quite low and did not reasonably reflect the stock. The low values show a mismatch between the retained recruitment series (before 2019) and the resampled biological variables (last 5 years). Thus, the truncation of the sampled years for the B and S calculation was increased to include the last 10 years (instead of 5 years) to tackle the mismatch between the natural mortality values and the recruitment.

The Recruitment-autocorrelation (RhoLogRec) is also high (>0.9) when estimated from SAM directly and is influencing the estimation of the reference points. The high value seems to be driven by the exceptionally high R in the latest year classes which, for that reason, were already excluded from the Blim estimation (see above). Generally, Rho is much smaller in fish and not easy to estimate within assessment models without bias because it is a random effect, so that Johnson et al. (2016) recommends to do the estimation outside the model and then fix it.

The Recruitment-autocorrelation (RhoLogRec) was set to a conservative level at 0.6, which is similar to other Rho values for plaice derived from FISHLIFE (i.e., 0.58 for plaice, Thorson et al., 2023).

# Testing whether mismatch between natural mortality values in the last 5 years
# vs recruitment values previously could also be a culprit

numAvgYrsB <- numAvgYrsS <- 10

refPts3 <- matrix(NA, nrow = 1, ncol = 9, dimnames = list("value", c("Btrigger",
    "Bpa", "Blim", "5thPerc_SSBmsy", "Fpa", "Flim", "Fp05", "Fmsy_unconstr", "Fmsy")))

refPts3[, "Blim"] <- mean(df[df$year %in% c(2002:2011), "SSB"])  # refPts3[,'Blim'] <- refPts[,'Blim']
refPts3[, "Bpa"] <- refPts3[, "Blim"] * exp(1.645 * sigmaSSB)  # refPts3[,'Bpa'] <- refPts[,'Bpa'] 

set.seed(123)
SIM_SegregBlim_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c((maxYear -
    numAvgYrsB), maxYear), bio.const = TRUE, sel.years = c((maxYear - numAvgYrsS),
    maxYear), sel.const = TRUE, Fcv = 0, Fphi = 0, SSBcv = 0, rhologRec = c(0.6),
    Btrigger = 0, Blim = refPts3[, "Blim"], Bpa = refPts3[, "Bpa"], Nrun = Nruns,
    Fscan = FsToScan, verbose = T)
tmp1 <- t(SIM_SegregBlim_lowerRhohighernumAvgYrs$Refs)
refPts3[, "Flim"] <- tmp1["F50", "catF"]
# tmpFpa <- refPts3[,'Flim'] * exp(-sigmaF * 1.645) PJW: This is fine but keep
# in mind later when reporting that this Fpa definition is outdated and now
# based on Fp05
tmpFpa <- refPts3[, "Fpa"] <- refPts3[, "Fp05"] <- tmp1["F05", "catF"]

if (tmpFpa < 0.2) refPts3[, "Fpa"] <- round(tmpFpa, 3) else refPts3[, "Fpa"] <- round(tmpFpa,
    2)

The resulting Flim and Fpa reference points were closer to similar values in other plaice stocks and more fitting to the development of the stocks since 2019 and thus were kept for the following calculations.

kable(data.frame(refPts3[, "Flim"], refPts3[, "Fpa"]), col.names = c("Flim", "Fpa"))
Flim Fpa
0.5727089 0.21
eqsim_plot(SIM_SegregBlim_lowerRhohighernumAvgYrs, catch = TRUE)
Plots of stock dynamics under simulation as specified for estimation of Flim.

(#fig:Fpa plots updated with 10yr avg)Plots of stock dynamics under simulation as specified for estimation of Flim.

However, while Flim may still be derived from Blim (and used to assess the F that drives the stock to Blim, based on the equilibrium curve of stock), it is no longer used by ICES as basis of precautionary approach (PA) and MSY reference points to assess the state of stocks and exploitation, and to provide advice on fishing opportunities WKNEWREF4, ICES 2024d). It is therefore only used for information, but not recognized as reference point for the assessment and advice and not included in the final reference point list.

5.3 calculate \(F_{MSY}\) (unconstrained)

Unlike the simulations used to estimate Flim, the unconstrained FMSY should initially be calculated based on a constant F evaluation with the inclusion of stochasticity in population and exploitation as well as assessment/advice error. Appropriate SRRs should be specified.

Also here, value was recalculated using the 10 year avg instead of 5 years

set.seed(123)
SIM_Segreg_noTrig_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c(maxYear -
    numAvgYrsB, maxYear), bio.const = FALSE, sel.years = c(maxYear - numAvgYrsS,
    maxYear), sel.const = FALSE, Fcv = cvF, Fphi = phiF, SSBcv = cvSSB, rhologRec = c(0.6),
    keep.sims = TRUE, Btrigger = 0, Blim = refPts3[, "Blim"], Bpa = refPts3[, "Bpa"],
    Nrun = Nruns, Fscan = FsToScan, verbose = T)

tmp2 <- t(SIM_Segreg_noTrig_lowerRhohighernumAvgYrs$Refs)
Fmsy_tmp <- tmp2["medianMSY", "catF"]  #note:  was previously landings F for Fmsy, from the wrong output (refs2 output tables)

tmpFpa <- refPts3[, "Fpa"] <- refPts3[, "Fp05"] <- tmp2["F05", "catF"]


refPts3[, "Fmsy_unconstr"] <- Fmsy_tmp
if (Fmsy_tmp > refPts3[, "Fpa"]) {
    refPts3[, "Fmsy"] <- refPts3[, "Fpa"]  #PJW: make sure this is Fp05
} else {
    refPts3[, "Fmsy"] <- Fmsy_tmp
}

The resulting unconstrained FMSY is about0.46. The unconstrained value is used as basis for the next steps in the reference point calculations.

eqsim_plot(SIM_Segreg_noTrig_lowerRhohighernumAvgYrs, catch = TRUE)
Plots of stock dynamics under simulation as specified for estimation of FMSY.

(#fig:FMSY plots updated with 10yr avg)Plots of stock dynamics under simulation as specified for estimation of FMSY.

5.4 \(MSY_{B trigger}\)

MSY B trigger is a lower bound of the SSB distribution when the stock is fished at F MSY (ICES, 2021). As stated in the ICES technical guidelines, recent fishing mortality estimates need to be considered to set MSY B trigger as for most stocks that lack data on fishing at F MSY, MSY B trigger is set at Bpa. Here, the stock has been fished below F MSY (0.137358) for the last 5 years. Next step is to look if the 5th percentile of B MSY > Bpa.

data.05 <- SIM_Segreg_noTrig_lowerRhohighernumAvgYrs$rbp
x.05 <- data.05[data.05$variable == "Spawning stock biomass", ]$Ftarget
b.05 <- data.05[data.05$variable == "Spawning stock biomass", ]$p05
# plot(b.05~x.05, ylab='SSB', xlab='F')
b.lm <- loess(b.05 ~ x.05)
refPts3[, "5thPerc_SSBmsy"] <- predict(b.lm, refPts3[, "Fmsy"])

The group agreed to use a simple version to set B trigger as Bpa

### simplified solution after web meeting with Colin (smoothing function is
### creating a weird B trigger)

refPts3[, "Btrigger"] <- refPts[, "Bpa"]
# This plot is only needed if you are going to use 5th percentile definition,
# and according to the above this stock doesn't qualify anyway, even if we
# thought it was a goood idea to use it. I added eval = FALSE to the chunk
# code. Side note - I think the loess smoother needs more nodes or something
# because it doesn't look like its fitting anyway.

ggplotly(ggplot(data = NULL, mapping = aes(x = x.05, y = b.05)) + geom_point(shape = 21) +
    geom_smooth(method = "loess", se = F, colour = ebpal[1]) + ylab("SSB (tonnes) with F that gives\n5% chance of going below Bpa") +
    xlab("Fishing pressure (F)") + theme_clean())

In this case the 5th percentile of B MSY is not greater than Bpa. Therefore following the ICES technical guidelines the MSY B trigger will be equal to Bpa , MSY B trigger = 1.3460426^{4} tonnes.MSY Btrigger should be selected to safeguard against an undesirable or unexpected low SSB when fishing at FMSY.

require(kableExtra)  #PJW: Added this

dt <- refPts3[, c(1, 2, 4)]

dt %>%
    kbl(booktabs = TRUE, caption = "Btrigger and Bpa reference points for ple.27.21-32") %>%
    kable_material_dark()
(#tab:intermediate btrigger table)Btrigger and Bpa reference points for ple.27.21-32
x
Btrigger 13460.43
Bpa 13460.43
5thPerc_SSBmsy 11251.37

5.5 final \(F_{MSY}\)

The ICES MSY Advice Rule should be evaluated to check that the FMSY and MSY Btrigger combination adheres to precautionary considerations: * in the long term, P(SSB<Blim)<5% The evaluation must include: * realistic assessment (advice) error * stochasticity in population biology and fishery exploitation. * Appropriate SRRs should be specified (here using segregation model with fixed breakpoint)

set.seed(123)
SIM_Segreg_Trig_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c(maxYear -
    numAvgYrsB, maxYear), bio.const = FALSE, sel.years = c(maxYear - numAvgYrsS,
    maxYear), sel.const = FALSE, Fcv = cvF, Fphi = phiF, SSBcv = cvSSB, rhologRec = c(0.6),
    keep.sims = TRUE, Btrigger = refPts3[, "Btrigger"], Blim = refPts3[, "Blim"],
    Bpa = refPts3[, "Bpa"], Nrun = Nruns, Fscan = FsToScan, verbose = TRUE)
tmp3 <- t(SIM_Segreg_Trig_lowerRhohighernumAvgYrs$Refs)
refPts3[, "Fp05"] <- refPts3[, "Fpa"] <- tmp3["F05", "catF"]  #note: catch F for Fp05


refPts3[, "Fmsy_unconstr"] <- Fmsy_tmp
if (Fmsy_tmp > refPts3[, "Fpa"]) {
    refPts3[, "Fmsy"] <- refPts3[, "Fpa"]
} else {
    refPts3[, "Fmsy"] <- Fmsy_tmp
}
# This shows that the mismatch between the recruitment series we retained
# (before 2019) and the biological variables we resampled (last 5 years), also
# caused some confusion. I think it is best to continue with this version above
# - look for a reasonable rho value (in the range 0.3 - 0.6 I think), and keep
# the last 10 years for sampling.
sim <- SIM_Segreg_Trig_lowerRhohighernumAvgYrs
# sim <- SIM_Segreg_noTrig_lowerRhohighernumAvgYrs # this one for unconstrained
# FMSY upper and lower
interval = 0.95
data.95 <- sim$rbp
x.95 <- data.95[data.95$variable == "Catch", ]$Ftarget
y.95 <- data.95[data.95$variable == "Catch", ]$Mean

yield.p95 <- interval * max(y.95, na.rm = TRUE)

# Fit loess smoother to curve
x.lm <- stats::loess(y.95 ~ x.95, span = 0.2)
lm.pred <- data.frame(x = seq(min(x.95), max(x.95), length = 1000), y = rep(NA, 1000))
lm.pred$y <- stats::predict(x.lm, newdata = lm.pred$x)

# Limit fitted curve to values greater than the 95% cutoff
lm.pred.95 <- lm.pred[lm.pred$y >= yield.p95, ]
fmsy.lower <- min(lm.pred.95$x)
fmsy.upper <- max(lm.pred.95$x)

fmsy.lower.mean <- fmsy.lower
fmsy.upper.mean <- fmsy.upper
catch.lower.mean <- lm.pred.95[lm.pred.95$x == fmsy.lower.mean, ]$y
catch.upper.mean <- lm.pred.95[lm.pred.95$x == fmsy.upper.mean, ]$y

# Repeat for 95% of yield at F(05):
f05 <- sim$Refs["catF", "F05"]
yield.f05 <- stats::predict(x.lm, newdata = f05)
yield.f05.95 <- interval * yield.f05
lm.pred.f05.95 <- lm.pred[lm.pred$y >= yield.f05.95, ]
f05.lower <- min(lm.pred.f05.95$x)
f05.upper <- max(lm.pred.f05.95$x)

# add upper and lower estimates to Ref2 table
SIM_Segreg_Trig_lowerRhohighernumAvgYrs$Refs2["catF", "Meanlower"] <- f05.lower
SIM_Segreg_Trig_lowerRhohighernumAvgYrs$Refs2["catF", "Meanupper"] <- f05.upper

To ensure consistency between the precautionary and the MSY frameworks, FMSY is not allowed to be above Fp05; therefore, if the initial FMSY value is above Fp05, FMSY is reduced to Fp05. Fp05 was calculated by running EqSim with assessment/advice error, with advice rule, and with a segmented regression with breaking point fixed at Bpa to ensure that the long-term risk of SSB < Blim of any F used does not exceed 5% when applying the advice rule. Fp05 was estimated to be 0.1491946 (F05 for catF). Therefore, as explained above, 0.1491946. The upper and lower ranges are given in the following table.

dt2 <- refPts3[, c(7, 9)]

dt2$Fmsy_lower <- SIM_Segreg_Trig_lowerRhohighernumAvgYrs$Refs2["catF", "Meanlower"]
dt2$Fmsy_upper <- SIM_Segreg_Trig_lowerRhohighernumAvgYrs$Refs2["catF", "Meanupper"]
dt2 <- t(dt2)

dt2 %>%
    kbl(booktabs = TRUE, caption = "Fp05 and Fmsy reference points for ple.27.21-32",
        digits = 4) %>%
    kable_material_dark()
(#tab:final fmsy table update)Fp05 and Fmsy reference points for ple.27.21-32
Fp05 Fmsy Fmsy_lower Fmsy_upper
0.149194630872483 0.149194630872483 0.137137137137137 1

In case of limitation by FMSY = Fpa, the upper FMSY limit equals the (capped) FMSY and the lower limit is re-calculated using the capped FMSY value (in this case, FMSY = NA instead of using the unconstrained FMSY = 0.46)

5.6 final graphs

What final graphs do we really want to see?

eqsim_plot_range(SIM_Segreg_noTrig_lowerRhohighernumAvgYrs, type = "mean")

eqsim_plot_range(SIM_Segreg_noTrig_lowerRhohighernumAvgYrs, type = "median")

eqsim_plot_range(SIM_Segreg_Trig_lowerRhohighernumAvgYrs, type = "ssb")

eqsim_plot_range(SIM_Segreg_Trig_lowerRhohighernumAvgYrs, type = "mean")

6 final reference point table

The final reference points are reflecting the changes of the stock since the last benchmark. The new values cannot be compared with the old reference points directly. Not only did the stock unit change by merging two stocks, but also the biological parameter in the assessment have been changed (e.g., by using sliding window averages for weight-at-age and maturity, as well as incorporating new natural mortality estimates and discard survival). Additionally, the stock is displaying an exceptional increase in biomass, which has not been present at the last benchmark. As Fpa = Fp05 (ICES 2024d), only the Fpa value is displayed in the table.

# RefPointTable <- as.data.frame(t(refPts3)) RefPointTable$ReferencePoint <-
# rownames(RefPointTable) rownames(RefPointTable) <- NULL RefPointTable$Units
# <- c('t', 't', 't', 't', 'F', 'F', 'F', 'F', 'F') RefPointTable <-
# RefPointTable[, c(2,1,3)] RefPointTable$RoundedValue <-
# ifelse(RefPointTable$Units == 'F', ifelse(RefPointTable$value<0.2,
# round(RefPointTable$value, 3), round(RefPointTable$value, 2)),
# round(RefPointTable$value, 0))
refPts4 <- refPts3[, c(1, 2, 3, 4, 5, 8, 9)]

t(refPts4) %>%
    kbl(booktabs = TRUE, caption = "reference points for ple.27.21-32") %>%
    kable_material_dark()
(#tab:final refpoint table)reference points for ple.27.21-32
Btrigger Bpa Blim 5thPerc_SSBmsy Fpa Fmsy_unconstr Fmsy
13460.43 13460.43 11118.6 11251.37 0.1491946 0.46 0.1491946

7 additional scenarios:

7.1 non-truncated Recruitment series

Sensitivity run using the non-truncated recruit time series. All other settings are identical to the final settings of the reference point calculation above: - Blim as average SSB of the first ten years of the time series - last 10 years of biological data used for S and B estimation in the reference point models - autocorrelation of recruitment fixed to RhoLogRec = 0.6

# set up new Ref table for untruncated series
refPts5 <- matrix(NA, nrow = 1, ncol = 9, dimnames = list("value", c("Btrigger",
    "Bpa", "Blim", "5thPerc_SSBmsy", "Fpa", "Flim", "Fp05", "Fmsy_unconstr", "Fmsy")))

# keep Blim and Bpa
refPts5[, "Blim"] <- mean(df[df$year %in% c(2002:2011), "SSB"])
refPts5[, "Bpa"] <- refPts[, "Blim"] * exp(1.645 * sigmaSSB)

# no truncation
rmSRRYrs <- 0

SegregBlim <- function(ab, ssb) log(ifelse(ssb >= refPts[, "Blim"], ab$a * refPts[,
    "Blim"], ab$a * ssb))

## Refit stock recruitment relationship based on truncated time series
set.seed(123)
eqfit <- eqsr_fit(stk = stk, nsamp = noSims, models = c("SegregBlim"), remove.years = rmSRRYrs)
## Plot
eqsr_plot(eqfit, n = 20000, ggPlot = TRUE, Scale = 1000)
set.seed(123)
SIM_SegregBlim_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c((maxYear -
    numAvgYrsB), maxYear), bio.const = TRUE, sel.years = c((maxYear - numAvgYrsS),
    maxYear), sel.const = TRUE, Fcv = 0, Fphi = 0, SSBcv = 0, rhologRec = c(0.6),
    Btrigger = 0, Blim = refPts5[, "Blim"], Bpa = refPts5[, "Bpa"], Nrun = Nruns,
    Fscan = FsToScan, verbose = T)

tmp1 <- t(SIM_SegregBlim_lowerRhohighernumAvgYrs$Refs)

refPts5[, "Flim"] <- tmp1["F50", "catF"]

tmpFpa <- refPts5[, "Fpa"] <- refPts5[, "Fp05"] <- tmp1["F05", "catF"]

if (tmpFpa < 0.2) refPts5[, "Fpa"] <- round(tmpFpa, 3) else refPts5[, "Fpa"] <- round(tmpFpa,
    2)

set.seed(123)
SIM_Segreg_noTrig_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c(maxYear -
    numAvgYrsB, maxYear), bio.const = FALSE, sel.years = c(maxYear - numAvgYrsS,
    maxYear), sel.const = FALSE, Fcv = cvF, Fphi = phiF, SSBcv = cvSSB, rhologRec = c(0.6),
    keep.sims = TRUE, Btrigger = 0, Blim = refPts5[, "Blim"], Bpa = refPts5[, "Bpa"],
    Nrun = Nruns, Fscan = FsToScan, verbose = T)

tmp2 <- t(SIM_Segreg_noTrig_lowerRhohighernumAvgYrs$Refs)
Fmsy_tmp <- tmp2["medianMSY", "catF"]  #note:  was previously landings F for Fmsy, from the wrong output (refs2 output tables)

tmpFpa <- refPts5[, "Fpa"] <- refPts5[, "Fp05"] <- tmp2["F05", "catF"]


refPts5[, "Fmsy_unconstr"] <- Fmsy_tmp
if (Fmsy_tmp > refPts5[, "Fpa"]) {
    refPts5[, "Fmsy"] <- refPts5[, "Fpa"]  #PJW: make sure this is Fp05
} else {
    refPts5[, "Fmsy"] <- Fmsy_tmp
}


data.05 <- SIM_Segreg_noTrig_lowerRhohighernumAvgYrs$rbp
x.05 <- data.05[data.05$variable == "Spawning stock biomass", ]$Ftarget
b.05 <- data.05[data.05$variable == "Spawning stock biomass", ]$p05
# plot(b.05~x.05, ylab='SSB', xlab='F')
b.lm <- loess(b.05 ~ x.05)
refPts5[, "5thPerc_SSBmsy"] <- predict(b.lm, refPts5[, "Fmsy"])


refPts5[, "Btrigger"] <- refPts[, "Bpa"]

set.seed(123)
SIM_Segreg_Trig_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c(maxYear -
    numAvgYrsB, maxYear), bio.const = FALSE, sel.years = c(maxYear - numAvgYrsS,
    maxYear), sel.const = FALSE, Fcv = cvF, Fphi = phiF, SSBcv = cvSSB, rhologRec = c(0.6),
    keep.sims = TRUE, Btrigger = refPts5[, "Btrigger"], Blim = refPts5[, "Blim"],
    Bpa = refPts5[, "Bpa"], Nrun = Nruns, Fscan = FsToScan, verbose = TRUE)
tmp3 <- t(SIM_Segreg_Trig_lowerRhohighernumAvgYrs$Refs)
refPts5[, "Fp05"] <- refPts5[, "Fpa"] <- tmp3["F05", "catF"]  #note: catch F for Fp05


refPts5[, "Fmsy_unconstr"] <- Fmsy_tmp
if (Fmsy_tmp > refPts5[, "Fpa"]) {
    refPts5[, "Fmsy"] <- refPts5[, "Fpa"]
} else {
    refPts5[, "Fmsy"] <- Fmsy_tmp
}
refPts6 <- refPts5[, c(1, 2, 3, 4, 5, 8, 9)]

t(refPts6) %>%
    kbl(booktabs = TRUE, caption = "reference points for ple.27.21-32, using the non-truncated recruitment") %>%
    kable_material_dark()
(#tab:final table of ref points, no truncation)reference points for ple.27.21-32, using the non-truncated recruitment
Btrigger Bpa Blim 5thPerc_SSBmsy Fpa Fmsy_unconstr Fmsy
13460.43 13460.43 11118.6 11435.24 0.1893137 0.8275 0.1893137

7.2 lower RhoLogRec value

Sensitivity run assuming a lower autocorrelation in the recruitment, RhoLogRec = 0.3. All other settings are identical to the final settings of the reference point calculation above: - Blim as average SSB of the first ten years of the time series - last 10 years of biological data used for S and B estimation in the reference point models - SSR time series truncated, only using the data before the exceptionally strong increase in 2019

refPts7 <- matrix(NA, nrow = 1, ncol = 9, dimnames = list("value", c("Btrigger",
    "Bpa", "Blim", "5thPerc_SSBmsy", "Fpa", "Flim", "Fp05", "Fmsy_unconstr", "Fmsy")))

# keep Blim and Bpa
refPts7[, "Blim"] <- mean(df[df$year %in% c(2002:2011), "SSB"])
refPts7[, "Bpa"] <- refPts[, "Blim"] * exp(1.645 * sigmaSSB)

# add truncation
rmSRRYrs <- c(2019:maxYear)  # specify here which other years (e.g. early period) should be left out

SegregBlim <- function(ab, ssb) log(ifelse(ssb >= refPts[, "Blim"], ab$a * refPts[,
    "Blim"], ab$a * ssb))

## Refit stock recruitment relationship based on truncated time series
set.seed(123)
eqfit <- eqsr_fit(stk = stk, nsamp = noSims, models = c("SegregBlim"), remove.years = rmSRRYrs)
## Plot
eqsr_plot(eqfit, n = 20000, ggPlot = TRUE, Scale = 1000)
set.seed(123)
SIM_SegregBlim_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c((maxYear -
    numAvgYrsB), maxYear), bio.const = TRUE, sel.years = c((maxYear - numAvgYrsS),
    maxYear), sel.const = TRUE, Fcv = 0, Fphi = 0, SSBcv = 0, rhologRec = c(0.3),
    Btrigger = 0, Blim = refPts7[, "Blim"], Bpa = refPts7[, "Bpa"], Nrun = Nruns,
    Fscan = FsToScan, verbose = T)

tmp1 <- t(SIM_SegregBlim_lowerRhohighernumAvgYrs$Refs)

refPts7[, "Flim"] <- tmp1["F50", "catF"]

tmpFpa <- refPts7[, "Fpa"] <- refPts7[, "Fp05"] <- tmp1["F05", "catF"]

if (tmpFpa < 0.2) refPts7[, "Fpa"] <- round(tmpFpa, 3) else refPts7[, "Fpa"] <- round(tmpFpa,
    2)

set.seed(123)
SIM_Segreg_noTrig_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c(maxYear -
    numAvgYrsB, maxYear), bio.const = FALSE, sel.years = c(maxYear - numAvgYrsS,
    maxYear), sel.const = FALSE, Fcv = cvF, Fphi = phiF, SSBcv = cvSSB, rhologRec = c(0.3),
    keep.sims = TRUE, Btrigger = 0, Blim = refPts7[, "Blim"], Bpa = refPts7[, "Bpa"],
    Nrun = Nruns, Fscan = FsToScan, verbose = T)

tmp2 <- t(SIM_Segreg_noTrig_lowerRhohighernumAvgYrs$Refs)
Fmsy_tmp <- tmp2["medianMSY", "catF"]  #note:  was previously landings F for Fmsy, from the wrong output (refs2 output tables)

tmpFpa <- refPts7[, "Fpa"] <- refPts7[, "Fp05"] <- tmp2["F05", "catF"]


refPts7[, "Fmsy_unconstr"] <- Fmsy_tmp
if (Fmsy_tmp > refPts7[, "Fpa"]) {
    refPts7[, "Fmsy"] <- refPts7[, "Fpa"]  #PJW: make sure this is Fp05
} else {
    refPts7[, "Fmsy"] <- Fmsy_tmp
}


data.05 <- SIM_Segreg_noTrig_lowerRhohighernumAvgYrs$rbp
x.05 <- data.05[data.05$variable == "Spawning stock biomass", ]$Ftarget
b.05 <- data.05[data.05$variable == "Spawning stock biomass", ]$p05
# plot(b.05~x.05, ylab='SSB', xlab='F')
b.lm <- loess(b.05 ~ x.05)
refPts7[, "5thPerc_SSBmsy"] <- predict(b.lm, refPts7[, "Fmsy"])


refPts7[, "Btrigger"] <- refPts[, "Bpa"]

set.seed(123)
SIM_Segreg_Trig_lowerRhohighernumAvgYrs <- eqsim_run(eqfit, bio.years = c(maxYear -
    numAvgYrsB, maxYear), bio.const = FALSE, sel.years = c(maxYear - numAvgYrsS,
    maxYear), sel.const = FALSE, Fcv = cvF, Fphi = phiF, SSBcv = cvSSB, rhologRec = c(0.3),
    keep.sims = TRUE, Btrigger = refPts7[, "Btrigger"], Blim = refPts7[, "Blim"],
    Bpa = refPts7[, "Bpa"], Nrun = Nruns, Fscan = FsToScan, verbose = TRUE)
tmp3 <- t(SIM_Segreg_Trig_lowerRhohighernumAvgYrs$Refs)
refPts7[, "Fp05"] <- refPts7[, "Fpa"] <- tmp3["F05", "catF"]  #note: catch F for Fp05


refPts7[, "Fmsy_unconstr"] <- Fmsy_tmp
if (Fmsy_tmp > refPts7[, "Fpa"]) {
    refPts7[, "Fmsy"] <- refPts7[, "Fpa"]
} else {
    refPts7[, "Fmsy"] <- Fmsy_tmp
}
refPts8 <- refPts7[, c(1, 2, 3, 4, 5, 8, 9)]

t(refPts8) %>%
    kbl(booktabs = TRUE, caption = "reference points for ple.27.21-32, assuming RhoLogRec = 0.3") %>%
    kable_material_dark()
(#tab:final table of ref points, lower Rho)reference points for ple.27.21-32, assuming RhoLogRec = 0.3
Btrigger Bpa Blim 5thPerc_SSBmsy Fpa Fmsy_unconstr Fmsy
13460.43 13460.43 11118.6 11458.4 0.1944366 0.515 0.1944366
LS0tDQp0aXRsZTogIlBsZS4yNy4yMS0zMiBSZWZlcmVuY2UgUG9pbnQgRXN0aW1hdGlvbiINCmF1dGhvcjoNCiAgLSBuYW1lOiAiU3ZlbiBTdMO2dGVyYSINCiAgLSBuYW1lOiAiRWxsaW90IEouIEJyb3duIg0KICAtIG5hbWU6ICJQYW1lbGEgV29vZHMiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IA0KICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KLS0tDQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoubWFpbi1jb250YWluZXIgew0KbWF4LXdpZHRoOiA5MCUgIWltcG9ydGFudDsNCm1hcmdpbjogYXV0bzsNCn0NCnAuY2FwdGlvbiB7DQpmb250LXNpemU6IDAuOGVtOw0KZm9udC1zdHlsZTogaXRhbGljOw0KfQ0KPC9zdHlsZT4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobz1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgIGV2YWwgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIiwNCiAgICAgICAgICAgICAgICAgICAgICB0aWR5ID0gJ2Zvcm1hdFInLA0KICAgICAgICAgICAgICAgICAgICAgIG91dC53aWR0aCA9ICI5MCUiKQ0KDQojPT09DQojIE1hbnVhbCBzZXR0aW5ncyBmb3IgZmlndXJlIGZvcm1hdHRpbmcNCiM9PT09DQojIGVicGFsIDwtIGMoIiMyRjNFRUEiLCAiIzFGRDA4MiIsICIjMDMwRjRGIiwgIiNGNkQwNEQiLCAiI0ZDNzYzNCIsICIjRjdCQkIxIiwgIiNFODNGNDgiLCAiIzAwODgzNSIsICIjNzkyMzhFIikNCmVicGFsIDwtIGMoIiM4MDAwODAiLCAiIzAwNjQwMCIsICIjRDU1RTAwIiwgIiMwMDcyQjIiLCAiI0YwRTQ0MiIsICIjMDA5RTczIiwgIiNFNjlGMDAiLCAiIzU2QjRFOSIsICIjQ0M3OUE3IiwgIiM1REE1REEiLCAiI0ZGODAwMCIsICIjODlDRkYwIiwgIiNBNTJBMkEiLCAiIzc3REQ3NyIsICIjRkZGQUNEIikNCg0KIz09PQ0KIyBQYWNrYWdlcw0KIz09PT0NCnJlcXVpcmUocmVzaGFwZTIpDQpyZXF1aXJlKGtuaXRyKQ0KcmVxdWlyZShzY2FsZXMpDQpyZXF1aXJlKGJvb2tkb3duKQ0KcmVxdWlyZShnZ3Bsb3QyKQ0KcmVxdWlyZShnZ3Bsb3RGTCkNCnJlcXVpcmUoZHBseXIpDQpyZXF1aXJlKGdndGhlbWVzKQ0KcmVxdWlyZShwbG90bHkpDQpyZXF1aXJlKGljZXNBZHZpY2UpDQpyZXF1aXJlKCJzdG9ja2Fzc2Vzc21lbnQiKSAjIGF2YWlsYWJsZSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9maXNoZm9sbG93ZXIvU0FNDQpyZXF1aXJlKHBhcmFsbGVsKQ0KcmVxdWlyZShtc3kpICAgICAgICAgICAgICAgIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImljZXMtdG9vbHMtcHJvZC9tc3kiKQ0KcmVxdWlyZShGTENvcmUpDQpyZXF1aXJlKEZMU0FNKSAgICAgICAgICAgICAjIGluc3RhbGwucGFja2FnZXMoIkZMU0FNIiwgcmVwb3M9Imh0dHA6Ly9mbHItcHJvamVjdC5vcmcvUiIpDQpyZXF1aXJlKEZMZnNlKSAgICAgICAgICAgICAjIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJzaGZpc2NoZXIvRkxmc2UvRkxmc2UiKQ0KcmVxdWlyZShrYWJsZUV4dHJhKQ0KcmVxdWlyZShTdG9ja1JlY3J1aXRTRVQpICMgZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJtZWJyb29rcy9zdG9ja3JlY3J1aXQvU3RvY2tSZWNydWl0U0VUIiwgYnVpbGRfb3B0cyA9IGMoIi0tbm8tcmVzYXZlLWRhdGEiLCAiLS1uby1tYW51YWwiKSkNCg0KDQojPT09PQ0KYGBgDQoNCjxjZW50ZXI+DQoNCiFbXShpbWFnZS9QTEUucG5nKQ0KPC9jZW50ZXI+DQoNCg0KDQojIERvd25sb2FkIFNlbGVjdCBNb2RlbA0KVGhlIGZpbmFsIFNBTSBydW4sIHRoZSBtb2RlbCBvdXRwdXQsIGRhdGEgYW5kIGNvbmZpZyBhcmUgZGlyZWN0bHkgdGFrZW4gZnJvbSBbc3RvY2thc3Nlc3NtZW50Lm9yZ10oaHR0cHM6Ly93d3cuc3RvY2thc3Nlc3NtZW50Lm9yZykuIA0KYGBge3IgZG93bmxvYWRtb2RlbH0NCnNhbWZpdCA8LSBmaXRmcm9td2ViKCJwbGUuMjcuMjEtMzJfV0tCUExBSUNFXzIwMjRfbm1HNUZiX21vMV9kc21lZDYiKQ0KDQojIyBleHRyYWN0IHJlbGV2YW50IGRhdGEgZnJvbSBtb2RlbA0KYXN1bSA8LSBhcy5kYXRhLmZyYW1lKHN1bW1hcnkoc2FtZml0KSkNCmFzdW0kWWVhciA8LSBhcy5pbnRlZ2VyKHJvdy5uYW1lcyhzdW1tYXJ5KHNhbWZpdCkpKQ0KY29sbmFtZXMoYXN1bSkgPC0gYygiUl9hZ2UxIiwgIlJsb3ciLCAiUmhpZ2giLCAiU1NCIiwgIlNTQmxvdyIsICJTU0JoaWdoIiwgIkZiYXIiLCAiRmxvdyIsICJGaGlnaCIsICJZZWFyIikNCmBgYA0KDQpUaGUgY2hvc2VuIGFzc2Vzc21lbnQgcnVuLCBhcyB3ZWxsIGFzIHRoZSBzZXR0aW5ncyBhbmQgZGV0YWlscyBvbiBzZW5zaXRpdml0eSBydW5zLCBldGMuIGFyZSBleHBsYWluZWQgaW4gdGhlIFdLQlBMQUlDRSByZXBvcnQgYW5kIHRoZSBhY2NvbXBhbnlpbmcgd29ya2luZyBkb2N1bWVudHM6DQpXRDEgCVN0b2NrIElkZW50aXR5IGFuZCBzdG9jayBtZXJnaW5nDQpXRDIgCVN0b2NrIGNvb3JkaW5hdGlvbiBhbmQgZGF0YSBvdmVydmlld3MNCldEMyAJT3ZlcnZpZXcgb2YgdGhlIGFzc2Vzc21lbnQgcnVucyBhbmQgc2Vuc2l0aXZpdHkNCldENCAJTmV3IG5hdHVyYWwgbW9ydGFsaXR5DQpXRDUgCUluY2x1c2lvbiBvZiBkaXNjYXJkIHN1cnZpdmFsDQoNCg0KIyBDcmVhdGUgRVEtU2ltIElucHV0IERhdGENCiMjIElucHV0cyBmcm9tIE1vZGVsDQpFUVNJTSByZXF1aXJlcyBkYXRhIGluIHRoZSAiRkxTdG9jayIgZm9ybWF0LiBUaGUgZG93bmxvYWRlZCBTQU0gb2JqZWN0IGlzIHRyYW5zZm9ybWVkLCBhZGRpbmcgYSBkZXNjcmlwdGlvbiBvZiB0aGUgc3RvY2ssIGNvbXB1dGVzIHRvdGFsIHdlaWdodHMgYW5kIGFkZCByZXNwZWN0aXZlIHVuaXRzLiAgDQpgYGB7ciBzZXQgdW5pdHMgaW4gRkxzdG9ja30NCnN0ayA8LSBTQU0yRkxTdG9jayhzYW1maXQsIHN0b2NrLnd0X2VzdCA9IFRSVUUpDQoNCiNQSlc6DQojIyMgVHJpbSBvZmYgbGFzdCB5ZWFyIG9mIHRoZSBzdG9jayBvYmplY3QgKG9ubHkgaWYgaW5jb21wbGV0ZSBkYXRhIGZvciBsYXN0IGFzc2Vzc21lbnQgeWVhcikNCm9yaWdTdGsgPC0gc3RrDQpzdGsgPC0gd2luZG93KHN0aywgc3RhcnQ9cmFuZ2Uoc3RrKVsibWlueWVhciJdLCBlbmQ9KHJhbmdlKHN0aylbIm1heHllYXIiXS0xKSkNCg0KIyBhZGQgbmFtZSBhbmQgZGVzY3JpcHRpb24gb2YgdGhlIHN0b2NrDQpuYW1lKHN0aykgPC1zdG9ja05hbWU8LSJQTEUuMjcuMjEtMzIiDQpkZXNjKHN0aykgPC0gIlBsYWljZSBpbiB0aGUgQmFsdGljIFNlYSBhbmQgS2F0dGVnYXQiDQoNCiMjIFVuaXRzDQp1bml0cyhjYXRjaChzdGspKSA8LSB1bml0cyhkaXNjYXJkcyhzdGspKSA8LSB1bml0cyhsYW5kaW5ncyhzdGspKSA8LSB1bml0cyhzdG9jayhzdGspKSA8LSAndCcNCnVuaXRzKGNhdGNoLm4oc3RrKSkgPC0gdW5pdHMoZGlzY2FyZHMubihzdGspKSA8LSB1bml0cyhsYW5kaW5ncy5uKHN0aykpIDwtIHVuaXRzKHN0b2NrLm4oc3RrKSkgPC0gJzEwMDAnDQp1bml0cyhjYXRjaC53dChzdGspKSA8LSB1bml0cyhkaXNjYXJkcy53dChzdGspKSA8LSB1bml0cyhsYW5kaW5ncy53dChzdGspKSA8LSB1bml0cyhzdG9jay53dChzdGspKSA8LSAna2cnDQoNCg0KIyBvdmVydmlldyBvZiBkYXRhIGltcG9ydGVkIGludG8gdGhlIEZMU3RvY2sgKGZyb20gdGhlIFNBTSBvdXRwdXQpDQpzdW1tYXJ5KHN0aykNCg0KYGBgDQoNCiMjIFVzZXIgc3BlY2lmaWVkIGlucHV0cw0KU29tZSBtYW51YWwgaW5wdXRzIGFuZCBjb25maWd1cmF0aW9uIGZvciBFUS1zaW0gYXJlIHJlcXVpcmVkLiBGb3IgdGhlIGxhdGVyIGNhbGN1bGF0aW9uIG9mIHJlZmVyZW5jZSBwb2ludHMsIHRoZSBkYXRhIHllYXIgYW5kIHRpbWUgc2VyaWVzIHJhbmdlIGFyZSBzZXQuDQpUaGUgZm9yZWNhc3QgZXJyb3JzIGFyZSBzZXQgdG8gZGVmYXVsdCB2YWx1ZXMsIHdoaWxlIHRoZSB1bmNlcnRhaW50aWVzIG9mIHRoZSBsYXN0IHllYXIgKHNpZ21hRiBhbmQgc2lnbWEgU1NCKSBhcmUgdGFrZW4gZGlyZWN0bHkgZnJvbSB0aGUgU0FNIG91dHB1dC4gDQoNCmBgYHtyIHJlZi1wb2ludCBzZXR0dGluZ3N9DQojIFNpbXVsYXRpb24gc2V0dGluZ3MNCkRhdGFZZWFyIDwtIDIwMjMNCm1pblllYXIgPC0gcmFuZ2Uoc3RrKVsibWlueWVhciJdDQptYXhZZWFyIDwtIHJhbmdlKHN0aylbIm1heHllYXIiXSAjUEpXOiBub3cgY29ycmVzcG9uZHMgd2l0aCBEYXRhWWVhciBkdWUgdG8gdHJpbW1pbmcgdGhlIHN0b2NrIG9iamVjdA0KDQojIyBOdW1iZXIgb2Ygc2ltcw0Kbm9TaW1zIDwtIDEwMDAgI1BKVzogV291bGQgYmUgYmV0dGVyIHRvIHVwZ3JhZGUgdG8gMjAwMCB3aXRoIGZpbmFsIHJ1bg0KcmhvUmVjIDwtIFQNCg0KIyMgRm9yZWNhc3QgZXJyb3INCmN2RiAgPC0gMC4yNQ0KcGhpRiA8LQkwLjMgIyBjdkYgIDwtIDAuMjEyZGVmYXVsdCB2YWx1ZXMsIGxvb2sgaW4gV0tNU1lSRUY0IChhbHRob3VnaCBjb25mdXNpb24gd2l0aCAwLjIzMz8pDQpjdlNTQiA8LSAwDQpwaGlTU0IgPC0gMA0KDQojIyA1dGggcGVyY2VudGlsZSBvZiBTU0IgaW4gdGhlIGZpbmFsIHllYXIgb2YgdGhlIGFzc2Vzc21lbnQNClNTQjA1PC0wICAjIHVzZWQgaW4gTVNZIEJ0cmlnZ2VyIGNhbGN1bGF0aW9uLiBJZiBzZXQgYXQgMCwgaWdub3JlZA0KDQojIyBVbmNlcnRhaW50eSBsYXN0IHllYXINCiMgUEpXOiByZW1vdmVkIC0xIGJlY2F1c2UgdGhpcyBmaXhlZCBieSB0cmltbWluZyBzdGsgb2JqZWN0DQojIyMgRiANCnNpZ21hRiA8LSBzYW1maXQkc2RyZXAkc2RbbmFtZXMoc2FtZml0JHNkcmVwJHZhbHVlKSA9PSAibG9nZmJhciJdW3NhbWZpdCRkYXRhJHllYXJzICVpbiUgKG1heChzYW1maXQkZGF0YSR5ZWFycykpXSAjIEV4dHJhY3RzIHRoZSBsYXN0IEZVTEwgeWVhcidzIHNkKGxvZyhGYmFyKSkgdmFsdWUgZnJvbSB0aGUgbW9kZWwgb2JqZWN0DQoNCiMjIyBTU0IgDQpzaWdtYVNTQiA8LSBzYW1maXQkc2RyZXAkc2RbbmFtZXMoc2FtZml0JHNkcmVwJHZhbHVlKSA9PSAibG9nc3NiIl1bc2FtZml0JGRhdGEkeWVhcnMgJWluJSAobWF4KHNhbWZpdCRkYXRhJHllYXJzKSldICMgRXh0cmFjdHMgdGhlIGxhc3QgRlVMTCB5ZWFyJ3Mgc2QobG9nKFNTQikpIHZhbHVlIGZyb20gdGhlIG1vZGVsIG9iamVjdA0KDQojIERpc3BsYXkgYWxsIHNldHRpbmdzIA0KYWxsX3NldHRpbmdzIDwtIGRhdGEuZnJhbWUobWluX1llYXIgPSBtaW5ZZWFyLCBtYXhfeWVhciA9IG1heFllYXIsIGN2RiA9IGN2RiwgUGhpRiA9IHBoaUYsIGN2U1NCID0gY3ZTU0IsIHBoaVNTQiA9IHBoaVNTQiwgU1NCMDUgPSBTU0IwNSwgc2lnbWFGID0gc2lnbWFGLCBzaWdtYVNTQiA9IHNpZ21hU1NCKQ0KDQprYWJsZShhbGxfc2V0dGluZ3MsIGNhcHRpb249ImFsbCBzZXR0aW5ncyBmb3IgdGhlIHJlZnBvaW50IGNhbGN1bGF0aW9ucyIpDQoNCg0KYGBgDQoNCiMjIGNhbGN1bGF0ZSBsYW5kaW5ncywgZGlzY2FyZHMgYW5kIGNhdGNoIGZyb20gaW5wdXQgbnVtYmVycyBhbmQgd2VpZ2h0DQpgYGB7ciBjb21wdXRlIHRvdGFsIHdlaWdodHMsIGZpZy5jYXA9IlN1bW1hcnkgb2Ygc3RvY2sgb2JqZWN0LiJ9DQpsYW5kaW5ncyhzdGspIDwtIGNvbXB1dGVMYW5kaW5ncyhzdGspDQpkaXNjYXJkcyhzdGspIDwtIGNvbXB1dGVEaXNjYXJkcyhzdGspDQojIGFuZCB0aGVuIHRoZSBjYXRjaCBzbG90cyBmcm9tIGJvdGggbGFuZGluZ3MgYW5kIGRpc2NhcmRzDQpjYXRjaChzdGspIDwtIGNvbXB1dGVDYXRjaChzdGssIHNsb3Q9ImFsbCIpDQoNCnN0b2NrKHN0aykgPC0gY29tcHV0ZVN0b2NrKHN0aykNCg0KcGxvdChzdGspDQpgYGANCg0KYGBge3IgcGxvdCBjYXRjaCBsYW5kaW5ncywgZmlnLmNhcD0iQ2F0Y2hlcyBhbmQgbGFuZGluZ3MsIHRpbWVzZXJpZXMsIGluZGVwZW5kZW50bHkuIiwgZXZhbD1GQUxTRX0NCnBsb3QobWV0cmljcyhzdGssIENhdGNoPWNhdGNoLCBMYW5kaW5ncz1sYW5kaW5ncykpDQpgYGANCg0KIyMgU2VsZWN0aXZpdHkvY2F0Y2hhYmlsaXR5IA0KQWdlZC1iYXNlZCBzZWxlY3Rpdml0eS9jYXRjaGFiaWxpdHkgcGxvdHMgYXMgcmVxdWVzdGVkIGJ5IHdvcmtpbmcgZ3JvdXAuDQoNCg0KDQpgYGB7ciBjYXRjaGFiaWxpdHkgcGxvdHMsIGZpZy5jYXA9IlNlbGVjdGl2aXR5L0NhdGNoYWJpbGl0eSBvZiB0aGUgc3RvY2ssIG92ZXIgdGltZSwgYnkgYWdlLiJ9DQphZ2VzIDwtIHNhbWZpdCRjb25mJG1pbkFnZTpzYW1maXQkY29uZiRtYXhBZ2UNCnllYXJzIDwtIHNhbWZpdCRkYXRhJHllYXJzDQptZWFuRmFnZXMgPC0gc2FtZml0JGNvbmYkZmJhclJhbmdlDQoNCiMgIyMjIEVsbGlvdCdzIGNvcnJlY3RlZCB2ZXJzaW9uLCBvZiB3aGF0IHNlZW1zIGEgcG9pbnRsZXNzIGV4Y2hhbmdlLiAuIC4gLiANCiMgaGFydmVzdChzdGspIDwtIGV4cChzYW1maXQkcGwkbG9nRilbYyhhZ2VzWy1sZW5ndGgoYWdlcyldLCAobWF4KGFnZXMpLTEpKSxdDQoNCm1lYW5GIDwtIGFwcGx5KGhhcnZlc3Qoc3RrKVthcy5jaGFyYWN0ZXIobWVhbkZhZ2VzKSxdLDIsICJtZWFuIikNCnNlbCA8LSBzd2VlcChoYXJ2ZXN0KHN0ayksMixtZWFuRiwiLyIpDQoNCnBsb3QoYWdlcyxzZWxbLGFjKG1heCh5ZWFycyktMSldLCB0eXBlPSJsIiwgeWxpbT1jKDAsbWF4KHNlbCkpLCB4bGFiPSJBZ2UiLCB5bGFiPSJTZWxlY3Rpdml0eSIsIG1haW49IlNlbGVjdGl2aXR5IikNCmZvciAoaSBpbiBhYygobWF4WWVhci0xOSApOm1heFllYXIpKSBsaW5lcyhhZ2VzLHNlbFssaV0sIGNvbD1pKQ0KbGluZXMoYWdlcyxhcHBseShzZWxbLGFjKChtYXhZZWFyLTIpOm1heFllYXIpXSwxLG1lYW4pLCBjb2w9MSwgbHdkPTUpDQpsaW5lcyhhZ2VzLGFwcGx5KHNlbFssYWMoKG1heFllYXItNCk6bWF4WWVhcildLDEsbWVhbiksIGNvbD0yLCBsd2Q9NSkNCmxpbmVzKGFnZXMsYXBwbHkoc2VsWyxhYygobWF4WWVhci05KTptYXhZZWFyKV0sMSxtZWFuKSwgY29sPTMsIGx3ZD01KQ0KbGluZXMoYWdlcyxhcHBseShzZWxbLGFjKChtYXhZZWFyLTE5KTptYXhZZWFyKV0sMSxtZWFuKSwgY29sPTQsIGx3ZD01KQ0KbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPWMoIk1lYW4gbGFzdCAzeXJzIiwiTWVhbiBsYXN0IDV5cnMiLCJNZWFuIGxhc3QgMTB5cnMiLCJNZWFuIGxhc3QgMjB5cnMiKSwgbHdkPTUsIGNvbD0xOjQsIGJ0eT0ibiIpDQoNCg0KYGBgDQoNCiMgQ2hvaWNlIG9mIHN0b2NrIHJlY3J1aXRtZW50IG1vZGVsDQpNYW55IGludmVzdGlnYXRpb25zIHdlcmUgbWFkZSB0byB0cnkgYW5kIGNob29zZSBhbiBhcHByb3ByaWF0ZSBzdG9jay1yZWNydWl0bWVudCBtb2RlbC4gSG93ZXZlciwgdGhlIHdvcmtpbmcgZ3JvdXAgYWdyZWVkIHRoYXQgdGhlcmUgd2FzIG5vIHN1aXRhYmxlIHN0YW5kYXJkIG1vZGVsIHRvIGZpdCB0aGVzZSBkYXRhLiAgQXMgY2FuIGJlIHNlZW4gYmVsb3csIHRoZSBzdG9jayBzdGFydHMgaW4gYSAibG93IHByb2R1Y3Rpdml0eSIgc3RhdGUgd2l0aCByZWxhdGl2ZWx5IGxvdyBTU0IgYW5kIHJlY3J1aXRtZW50LCBidXQgdGhlbiByYXBpZGx5IHJpc2VzIGluIHJlY2VudCBoaXN0b3J5LCBpbiBhbiBhbG1vc3QgbGluZWFyIHRyZW5kIHdpdGggbm8gc2lnbiBvZiByZWFjaGluZyBhbiBhc3ltcHRvdGUuIEJlY2F1c2Ugb2YgdGhpcyBkcmFtYXRpYyBjaGFuZ2UgYW5kIHRoZSBmYWN0IHRoYXQgdGhlIHN0b2NrIGlzIHN0aWxsIG5vdCByZWFjaGluZyBzb21lIGZvcm0gb2YgZXF1aWxpYnJpdW0gYWxsIHN0YW5kYXJkIG1vZGVscyBhc3N1bWUgYW4gaW5maW5pdGUgcmVsYXRpb25zaGlwIHdpdGggbm8gY2FwIG9uIHJlY3J1aXRtZW50Lg0KDQpUbyB2aWV3IHRoZSBkZXRhaWwgb2YgdGhlIGRhdGEgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgdGltZSBzZXJpZXMsIGNsaWNrIGFuZCBkcmFnIGEgcmVjdGFuZ2xlIG92ZXIgdGhlIGJvdHRvbSBsZWZ0IHBvcnRpb24gb2YgdGhlIHBsb3QgYXJlYS4gDQoNCmBgYHtyIGZpZy5jYXA9IlN0b2NrIFJlY3J1aXRtZW50IFJlbGF0aW9uc2hpcC4ifQ0KZ2dwbG90bHkoZ2dwbG90KGFzdW0sDQogICAgICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4PVNTQiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9Ul9hZ2UxKSkgKw0KICAgICAgICAgICBnZW9tX3BhdGgoY29sb3VyID0gZWJwYWxbMV0pICsNCiAgICAgICAgICAgZ2VvbV90ZXh0KG1hcHBpbmcgPSBhZXMobGFiZWw9WWVhciksDQogICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBlYnBhbFsyXSwNCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC41KSArDQogICAgICAgICAgIHhsYWIoIlNTQiAodG9ubmVzKSIpICsNCiAgICAgICAgICAgeWxhYigiUmVjcnVpdG1lbnQgKG51bWJlcnMpIikgKw0KICAgICAgICAgICB0aGVtZV9jbGVhbigpKQ0KYGBgDQoNClRvIGJldHRlciB2aWV3IHRoZSB0cmVuZHMsIGFjcm9zcyB0aGUgbGFyZ2Ugc2hpZnQgaW4gc2NhbGUsIHdlIGNhbiBhbHNvIHZpc3VhbGl6ZSB0aGlzIGluIHRoZSBsb2ctc2NhbGUuIA0KDQpgYGB7ciwgU1IgcmVsYXRpb24sIGZpZy5jYXAgPSAiU1JSIG9mIHBsZS4yNy4yMS0zMi4gUiBpcyBsb2ctc2NhbGVkIHRvIGVuaGFuY2UgdGhlIHJlc29sdXRpb24gb2YgdGggZWFybHkgeWVhcnMgaW4gdGhlIHRpbWUtc2VyaWVzLiJ9DQpnZ3Bsb3RseShnZ3Bsb3QoYXN1bSwNCiAgICAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHg9U1NCLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1sb2coUl9hZ2UxKSkpICsNCiAgICAgICAgICAgZ2VvbV9wYXRoKGNvbG91ciA9IGVicGFsWzFdKSArDQogICAgICAgICAgIGdlb21fdGV4dChtYXBwaW5nID0gYWVzKGxhYmVsPVllYXIpLA0KICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gZWJwYWxbMl0sDQogICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKw0KICAgICAgICAgICB4bGFiKCJTU0IgKHRvbm5lcykiKSArDQogICAgICAgICAgIHlsYWIoIlJlY3J1aXRtZW50IChsb2cgb2YgbnVtYmVycykiKSArDQogICAgICAgICAgIHRoZW1lX2NsZWFuKCkpDQpgYGANCg0KV2hlbiB3ZSBmb3JjZSBhIHNlZ21lbnRlZCByZWdyZXNzaW9uIChob2NrZXktc3RpY2spIHRocm91Z2ggdGhlIGRhdGEsIHRoZSByZXN1bHQgaXMgaW5kaWNhdGl2ZSBvZiB0aGUgbm9uLWVxdWlsaWJyaXVtIHN0YXR1cyBvZiB0aGUgc3RvY2ssIHdpdGggbm8gaWRlbnRpZmllZCBicmVhay1wb2ludC4NCg0KYGBge3IgZml0IGVxc2ltfQ0Kc2V0LnNlZWQoMTIzKQ0KZXFmaXQgPC0gZXFzcl9maXQoc3RrID0gc3RrLA0KICAgICAgICAgICAgICAgICAgbnNhbXAgPSBub1NpbXMsDQogICAgICAgICAgICAgICAgICBtb2RlbHMgPSBjKCJTZWdyZWciKSkNCiMgICAgICAgICAgICAgICAgICBtb2RlbHMgPSBjKCJTbW9vdGhfaG9ja2V5IiwiQmV2aG9sdCIsICJTZWdyZWciKSkNCmBgYA0KDQoNCmBgYHtyIGVxc2ltIFNSIHBsb3QgZml0dGVkLCBmaWcuY2FwPSJTZWdtZW50ZWQgcmVncmVzc2lvbiBmaXQgb2Ygc3RvY2stcmVjcnVpdG1lbnQgZGF0YS4ifQ0KIyBlcXNyX3Bsb3QoZXFmaXQpDQogZXFzcl9wbG90KGVxZml0LG49MmU0LGdnUGxvdD1UUlVFLFNjYWxlPTFlMykgI25pY2VyIGdncGxvdCBjb2xvcnMgDQpgYGANCg0KVG8gZnVydGhlciBpbnRlcnJvZ2F0ZSB0aGUgcG90ZW50aWFsIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBzc2IgYW5kIHJlY3J1aXRtZW50LCB3ZSBjYW4gdmlzdWFsaXNlIGl0IGFub3RoZXIgd2F5LCB1c2luZyBhIGRpcmVjdCByYXRpbyBvZiByZWNydWl0cyBwZXIgU1NCLg0KDQpgYGB7ciBwbG90IFIgcGVyIHNzYiwgZmlnLmNhcD0iUmVjcnVpdHMgcGVyIFNTQiBvdmVyIHRpbWUuIn0NCnN0b2NrTmFtZSA8LSAicGxlLjI3LjIxLTMyIg0KZGYgPC0gZGF0YS5mcmFtZShzdW1tYXJ5KHNhbWZpdCkpDQpkZiR5ZWFyIDwtIHJvd25hbWVzKGRmKQ0Kcm93bmFtZXMoZGYpIDwtIE5VTEwNCg0KcmVjIDwtIGRmWzI6bnJvdyhkZiksICJSLmFnZS4xLiJdICMgaW4gcmF3IG51bWJlcnMuDQpzc2IgPC0gZGZbMToobnJvdyhkZiktMSksICJTU0IiXSAjIGluIHRvbm5lcy4NCmRmJHJlYy5zc2IgPC0gYyhOQSwgKHJlYy9zc2IpKQ0KDQpnZ3Bsb3QoZGF0YSA9IGRmKSArDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0geWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSByZWMuc3NiKSwNCiAgICAgICAgICAgICBzaGFwZSA9IDApICsgIA0KICBnZW9tX2xpbmUobWFwcGluZyA9IGFlcyh4ID0geWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHJlYy5zc2IsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gMSksDQogICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB4bGFiKCJZZWFyIG9mIHJlY3J1aXRtZW50IikgKw0KICB5bGFiKCJSZWNydWl0bWVudCAoMDAwJ3MpIC9cblNTQiBvZiB0aGUgcHJldmlvdXMgeWVhciAodG9ubmVzKSIpICsNCiAgdGhlbWVfY2xlYW4oKSArDQogIHRoZW1lKGF4aXMudGV4dC54LmJvdHRvbSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpDQoNCg0KDQpgYGANCg0KIyBQcmVwYXJhdGlvbiBvZiByZWZlcmVuY2UgcG9pbnQgY2FsY3VsYXRpb24NCiMjIEd1aWRlbGluZXMgYW5kIG90aGVyIHByZWNlZGVudHMNCklDRVMgaGFzIHNwZWNpZmljIGd1aWRlbGluZXMgZm9yIGRldGVybWluaW5nIHJlZmVyZW5jZSBwb2ludHMuIFRoZSBndWlkZWxpbmVzIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly9odHRwczovL2ljZXMtbGlicmFyeS5maWdzaGFyZS5jb20vYXJ0aWNsZXMvcmVwb3J0L1RlY2huaWNhbF9HdWlkZWxpbmVzXy1fSUNFU19maXNoZXJpZXNfbWFuYWdlbWVudF9yZWZlcmVuY2VfcG9pbnRzX2Zvcl9jYXRlZ29yeV8xX2FuZF8yX3N0b2Nrc18yMDIxXy8xODYzODE1MD9maWxlPTMzNDE3NTUxKQ0KDQpBcyBkZW1vbnN0cmF0ZWQgYWJvdmUsIG5vIHN0b2NrLXJlY3J1aXRtZW50IHJlbGF0aW9uc2hpcCBjYW4gYmUgZXN0aW1hdGVkIGZyb20gdGhlIGRhdGEsIHNvIGEgU3RvY2sgVHlwZSAyIHN0b2NrLXJlY3J1aXRtZW50IGNhdGVnb3JpemF0aW9uIHdhcyBydWxlZCBvdXQuICBUaGlzIHdhcyBpbnZlc3RpZ2F0ZWQgYm90aCB3aXRoIGFuZCB3aXRob3V0IHRoZSA1IGxhc3QgeWVhcnMgb2YgZGF0YSwgd2hlcmUgdGhlIHN0b2NrIGFwcGVhcnMgdG8gYmUgc2hpZnRpbmcgaW50byBhIG5ldyByZWdpbWUuDQoNCkFsdGhvdWdoIHRoZSBzdG9jay1yZWNydWl0bWVudCBwYXR0ZXJuIHdhcyB2aXN1YWxseSBzaW1pbGFyIHRvIGEgU3RvY2sgVHlwZSAzLCB0aGlzIGNhdGVnb3J5IHdhcyBydWxlZCBvdXQgYmVjYXVzZSB0aGlzIHBsYWljZSBzdG9jayBpcyBjYXVnaHQgbWFpbmx5IGFzIGEgYnljYXRjaCBmaXNoZXJ5LCBhbmQgaXQgd2FzIG5vdCBiZWxpZXZlZCBieSBleHBlcnRzIHRoYXQgdGhlIGVudGlyZSB0aW1lIHNlcmllcyBjb3VsZCBiZSByZWZsZWN0aXZlIG9mIGFuIG92ZXJmaXNoZWQgcGVyaW9kLiBJdCB3YXMgaW5zdGVhZCBiZWxpZXZlZCB0aGF0IHRoYXQgZWFybGllc3QgeWVhcnMgY291bGQgcmVmbGVjdCBhbiBvdmVyZmlzaGVkIHN0YXRlIHdpdGggcmVjcnVpdG1lbnQgaW1wYWlybWVudCBkdWUgdG8gaGlnaCBkaXNjYXJkaW5nIG9mIHBsYWljZSBpbiB0aGUgdGFyZ2V0ZWQgY29kIGZpc2hlcnksIGJ1dCBpdCB3b3VsZCBiZSBkaWZmaWN1bHQgdG8ganVzdGlmeSBhIGJlbGllZiB0aGF0IHJlY3J1aXRtZW50IGltcGFpcm1lbnQgY291bGQgYmUgZXhwZXJpZW5jZWQgYWxzbyBpbiB0aGUgbGF0dGVyIHBvcnRpb24gb2YgdGhlIHRpbWUgc2VyaWVzLg0KDQpUaGVyZWZvcmUsIGFmdGVyIG11Y2ggZGlzY3Vzc2lvbiwgaXQgd2FzIGRldGVybWluZWQgdGhhdCB0aGlzIHN0b2NrIGZhbGxzIGVpdGhlciBpbnRvIHR5cGUgMSBvciA1IChmcm9tIHRoZSBhZm9yZW1lbnRpb25lZCBndWlkZWxpbmVzKS4gDQoNCiMgQ2FsY3VsYXRlIHJlZmVyZW5jZSBwb2ludHMNCkJlZm9yZSB3ZSBiZWdpbiBjYWxjdWxhdGluZyB0aGUgdmFyaW91cyByZWZlcmVuY2UgcG9pbnRzLCB3ZSBtdXN0IGZpcnN0IGRlY2lkZSBvbiBzb21lIGRhdGEgdHJ1bmNhdGlvbiBhbmQgc2V0dGluZ3MgZm9yIHRoZSBzaW11bGF0aW9uLiANCg0KQmVjYXVzZSBvZiB0aGUgcmFwaWQgY2hhbmdlcyBpbiBzdG9jayBkeW5hbWljcyBpbiByZWNlbnQgeWVhcnMsIHRoZSBkZWNpc2lvbiB3YXMgbWFkZSB0byBydW4gc2ltdWxhdGlvbnMgZm9yIHJlZmVyZW5jZSBwb2ludHMgYmFzZWQgb24gdGhlIHBlcmlvZCBiZWZvcmUgc3RvY2std2VpZ2h0cy1hdC1hZ2UgYmVnYW4gdG8gZGVjbGluZSwgcmVjcnVpdG1lbnQgaW5jcmVhc2VkIGFuZCBTU0IgaW5jcmVhc2VkLiBJdCB3YXMgdGhvdWdodCB0aGF0IHRoaXMgbW9zdCByZWNlbnQgcGVyaW9kIG9mIGhpZ2ggcmVjcnVpdG1lbnQgb2YgcG9vci1jb25kaXRpb24gcmVmbGVjdHMgYSByYXJlIGVwaXNvZGUgb2Ygb3ZlcnNob290aW5nIGNhcnJ5aW5nIGNhcGFjaXR5LCBzbyBleHBlcnRzIGV4cGVjdGVkIHRoYXQgdGhpcyBwZXJpb2QgaXMgdW5saWtlbHkgdG8gY29udGludWUgaW4gdGhlIGxvbmctdGVybS4NCg0KYGBge3IgcmVmcG9pbnR0YWJsZSBhbmQgc2V0dGluZ3N9DQoNCiMjIFJlZmVyZW5jZSBwb2ludHMNCnJlZlB0cyA8LSBtYXRyaXgoTkEsbnJvdz0xLG5jb2w9OSwgZGltbmFtZXM9bGlzdCgidmFsdWUiLGMoIkJ0cmlnZ2VyIiwiQnBhIiwiQmxpbSIsIjV0aFBlcmNfU1NCbXN5IiwiRnBhIiwiRmxpbSIsICJGcDA1IiwiRm1zeV91bmNvbnN0ciIsIkZtc3kiKSkpDQoNCnNzYl9tZWQgPC0gbWVkaWFuKHNzYikNCnJlY19tZWQgPC0gbWVkaWFuKHJlYykNCg0KIyMgWWVhcnMgYnkgd2hpY2ggdG8gdHJ1bmNhdGUgZGF0YXNldC4NCnJtU1JSWXJzIDwtIGMoMjAxOTptYXhZZWFyKSAgIyBzcGVjaWZ5IGhlcmUgd2hpY2ggb3RoZXIgeWVhcnMgKGUuZy4gZWFybHkgcGVyaW9kKSBzaG91bGQgYmUgbGVmdCBvdXQNCiNQSlcgcmVtb3ZlZCBoZXJlIHJlZHVuZGFudCBtYXhZZWFyIGRlZiBhbmQgYWRkZWQgbWF4WWVhciB0byBhYm92ZQ0KDQojIyBEZWNpc2lvbnMgYW5kIHNldHRpbmdzIGZvciB1c2UgaW4gZm9yd2FyZCBzaW11bGF0aW9ucw0KIyMjIEhvdyBtYW55IHllYXJzIHRvIGF2ZXJhZ2Ugb3ZlciAocmVzYW1wbGUgZnJvbSkgZm9yIGJpb2xvZ2ljYWwgZGF0YQ0KbnVtQXZnWXJzQiA8LSA1ICNQSlc6IEkgY2hhbmdlZCB0aGlzIHRvIDUgZnJvbSAxMCBmb3IgdGVzdGluZy4uLiBJIHRoaW5rIHdlIHNhaWQgZWl0aGVyIHdhcyBvaw0KIyMjIEhvdyBtYW55IHllYXJzIHRvIHNhbXBsZSBmcm9tIGZvciBzdG9jayB2YXJpYWJpbGl0eQ0KbnVtQXZnWXJzUyA8LSA1ICNQSlc6IEkgY2hhbmdlZCB0aGlzIHRvIDUgZnJvbSAxMCBmb3IgdGVzdGluZy4uLiBJIHRoaW5rIHdlIHNhaWQgZWl0aGVyIHdhcyBvaw0Kc3JZZWFycyA8LSBzZXRkaWZmKGMobWluWWVhcjoobWF4WWVhcikpLHJtU1JSWXJzKQ0KTnJ1bnMgPC0gMjAwIA0KRnNUb1NjYW4gPC0gIHNlcSgwLDEsIGJ5ID0gMC4wMDUpICNzZXEoMCwgMC45LCBsZW4gPSAyMDApICMgY2hhbmdlZCBtYXggdG8gMSAtIGVhcmxpZXIgdmVyc2lvbnMgeW91IHNob3dlZCBkaWQgbm90IGhhdmUgbGV2ZWxpbmcgb2ZmIGluIEZsaW0gcnVucyBzbyBGIG5lZWRzIHRvIGJlIGluY3JlYXNlZA0KDQpgYGANCg0KIyMgQ2FsY3VsYXRlL2VzdGltYXRlICRCX3tsaW19JCBhbmQgJEJfe3BhfSQNCkJsaW0gaXMgdGhlIGtleSBQQSByZWZlcmVuY2UgcG9pbnQuIFRoZSBvdGhlciBwcmVjYXV0aW9uYXJ5IGFwcHJvYWNoIHBvaW50cyAoQnBhLCBGbGltLCBhbmQgRnBhKSBhcmUgYWxsIGVzdGltYXRlZCBmcm9tIEJsaW0uIEluIGEgZmV3IGNhc2VzLCB0aGUgYXZhaWxhYmxlIGluZm9ybWF0aW9uIGRvZXMgbm90IGFsbG93IGRpcmVjdCBlc3RpbWF0aW9uIG9mIEJsaW07IEJwYSBpcyB0aGVuIGVzdGltYXRlZCBkaXJlY3RseSwgYW5kIEJsaW0gIG1heSBiZSBkZXJpdmVkIGZyb20gQnBhLiANCg0KV2hpbGUgU3RvY2sgVHlwZXMgMSBhbmQgNSBmcm9tIHRoZSBndWlkZWxpbmVzIGNhbGwgZm9yIHVzaW5nIEJsb3NzIGFzIEJsaW0sIHRoZSBleHBlcnRzIGluIHRoZSB3b3JraW5nIGdyb3VwIHJlY29nbmlzZWQgdGhhdCBCbG9zcyAoMjAxMCkgaXMgbGVzcyB0aGFuIG1hbnkgb3RoZXIgU1NCIHZhbHVlcyB0aGF0IHdlcmUgYWxzbyBsb3cgYW5kIGR1cmluZyBhIHBlcmlvZCBvZiBoaWdoIGZpc2hpbmcgbW9ydGFsaXR5ICgyMDAyLTIwMDkpLiBUaGVyZWZvcmUsIHNldHRpbmcgQmxpbSB0byBCbG9zcyBtYXkgbm90IGJlIHN1ZmZpY2llbnRseSBwcmVjYXV0aW9uYXJ5Lg0KDQpUaGVyZWZvcmUsIHdlIGFsc28gZGVjaWRlZCB0byB0cnkgdG8gYXBwbHkgdGhlIHJ1bGVzIHVzZWQgZm9yIEd1bGYgb2YgUmlnYSBoZXJyaW5nLCBuYW1lbHkgdGhhdCB3ZSB0YWtlIGFzIEJwYSB0aGUgbWVhbiBTU0Igb2YgdGhvc2UgeWVhcnMgd2hlcmU6DQoNCiAtIFNTQiA8PSBtZWRpYW4gU1NCIEFORCANCiAtIHJlY3J1aXRtZW50ID49IG1lZGlhbiByZWNydWl0bWVudA0KDQpUaGUgbG9naWMgaGVyZSwgaXMgdGhhdCB3ZSBhcmUgZmluZGluZyB0aG9zZSB5ZWFycyB3aGVyZSBsb3cgU1NCIHN0aWxsIHJlc3VsdHMgaW4gcmVsYXRpdmVseSBoaWdoIHJlY3J1aXRtZW50IGFuZCB1c2luZyB0aGUgbWVhbiBzc2Igb2YgdGhvc2UgeWVhcnMgdG8gaWRlbnRpZnkgQnBhIGFuZCBjYWxjdWxhdGUgQmxpbSBmcm9tIHRoZXJlLiANCg0KYGBge3IgQmxpbSBhbmQgQnBhIGJhc2VkIG9uIEdvUiBIZXJyaW5nfQ0KcmVmUHRzWywgIkJwYSJdIDwtIG1lYW4oZGZbZGYkUi5hZ2UuMS4gPj0gbWVkaWFuKGRmJFIuYWdlLjEuKSAmIGRmJFNTQiA8PSBtZWRpYW4oZGYkU1NCKSAmIGRmJHllYXIgIT0gMjAyNCwgIlNTQiJdKQ0KcmVmUHRzWywiQmxpbSJdICA8LSByZWZQdHNbLCJCcGEiXS8xLjQNCg0Ka2FibGUocmVmUHRzKQ0KYGBgDQoNClRoaXMgcmVzdWx0ZWQgaW4gYSBCcGEgYmFzZWQgb24gdHdvIG9mIHRoZSBsb3dlc3Qgb2JzZXJ2ZWQgU1NCIGluIHRoZSB0aW1lIHNlcmllcywgd2hpY2ggY29ycmVzcG9uZGVkIHRvIGVzc2VudGlhbGx5IEJsb3NzIGJ5IG90aGVyIHN0b2NrIGNhdGVnb3J5IGRlZmluaXRpb25zIGFuZCBhIEJsaW0gdmFsdWUgbG93ZXIgdGhhbiBvYnNlcnZlZCBpbiB0aGUgdGltZSBzZXJpZXMuIEZ1cnRoZXJtb3JlLCB0aGlzIG1ldGhvZCBsZWQgdG8gYSB2YWx1ZSBhcHBlYXJlZCB0byBiZSBsZXNzIHRoYW4gMTAlIG9mIGVzdGltYXRlcyBvZiBCMCAoY2FsY3VsYXRlZCBzdWJzZXF1ZW50bHkpLiBUaGVyZWZvcmUgdGhpcyBtZXRob2Qgd2FzIGFsc28gcmVqZWN0ZWQuDQoNCkluIGEgc2Vjb25kIGFwcHJvYWNoLCBCbGltIHdhcyBlc3RpbWF0ZWQgYnkgdXNpbmcgdGhlICJlbXBpcmljYWwgYXBwcm9hY2giIGFuZCB1c2luZyBCIGVtcGlyaWNhbCBhcyBCbGltLiBJbiBhIHJldmlldyBvZiBJQ0VTIHJlZmVyZW5jZSBwb2ludHMgU2lsdmFyLVZpbGFkb21pdSBldCBhbC4gKDIwMjIpIGZvdW5kIHRoYXQgYWZ0ZXIgQmxvc3MsIHRoZSBtb3N0IHVzZWQgbWV0aG9kIHRvIGRlZmluZSBCbGltIHdhcyBhbiBlbXBpcmljYWwgbWV0aG9kIGJhc2VkIG9uIGlkZW50aWZ5aW5nIHRoZSBsb3dlc3QgYmlvbWFzcyB0aGF0IHJlc3VsdGVkIGluIGdvb2QgcmVjcnVpdG1lbnQuIFRoZSDigJxTdG9ja1JlY3J1aXTigJ0gUiBwYWNrYWdlIGF2YWlsYWJsZSBpbiBHaXRIdWIgcHJvdmlkZXMgYSBmdW5jdGlvbiB0aGF0IGZvcm1hbGl6ZXMgdGhpcyBtZXRob2QsIGFuZCBpZGVudGlmaWVzIHRoZSBsb3dlc3QgYmlvbWFzc2VzIHRoYXQgcmVzdWx0cyBpbiBhYm92ZSBtZWRpYW4gcmVjcnVpdG1lbnQuIA0KVGhlbiBCbGltIGlzIGRlZmluZWQgYXMgdGhlIGF2ZXJhZ2Ugb2YgdGhlIGlkZW50aWZpZWQgc2V0IG9mIGxvd2VzdCBiaW9tYXNzZXMgdGhhdCBjYW4gYmUgZm9ybWVkIGJ5IGp1c3Qgb25lIHBvaW50IG9yIHNldmVyYWwuIFdLTkVXUkVGIHByb3Bvc2VkIHRoZW4gYSBmb3VydGggbWV0aG9kIHRvIGRlZmluZSBCbGltICwgdGhlIOKAmGVtcGlyaWNhbCBhcHByb2FjaCcsIGluIHdoaWNoIEJsaW0gaXMgZGVmaW5lZCBhcyAibG93ZXN0IGJpb21hc3MgKFNTQikgdGhhdCByZXN1bHRlZCBpbiBhIGdvb2QgcmVjcnVpdG1lbnQgKGkuZS4sIGEgcmVjcnVpdG1lbnQgYWJvdmUgdGhlIG1lZGlhbikuIiANCg0KDQpgYGB7ciB1c2UgQmxpbSBlbXByaWNpYWwgaW5zdGVhZCBvZiBCbGltIGNsYXNzaWN9DQoNCiMjIEZMU1Igb2JqZWN0DQpmbHNyIDwtIGFzLkZMU1Ioc3RrKQ0KUyA8LSBhbihzc2IoZmxzcikpDQpSIDwtIGFuKHJlYyhmbHNyKSkNCg0KIyBNaW5pbXVtIFNTQiBsZXZlbCB0aGF0IHJlc3VsdGVkIGluIGEgcmVjcnVpdG1lbnQgaGlnaGVyIHRoYXQgdGhlIG1lZGlhbi4NCg0KQmxpbV9lbXAgPC0gY2FsY0JsaW0oUywgUiwgcXVhbnQgPSAwLjUsIHR5cGUgPSAxKQ0KDQoNCg0KYGBgDQoNClVzaW5nIHRoZSBkZWZpbml0aW9uIG9mIFdLTkVXUkVGIG9mIDIwMjQgYW5kIHRoZSAiU3RvY2tSZWNydWl0U0VUIiBwYWNrYWdlLCB0aGUgQmxpbSBlbXBpcmljYWwgaXMgYWJvdXQgYHIgQmxpbV9lbXBgIHRvbnMuIFRoZSBlbXBpcmljYWwgQmxpbSBpcyB2ZXJ5IGNsb3NlIHRoZSB0aGUgcHJldmlvdXNseSBlc3RpbWF0ZWQgQmxpbSB2YWx1ZSBvZiBgciByZWZQdHNbLCAiQmxpbSJdYCB0b25zIGFuZCB3b3VsZCBmYWNlIHNpbWlsYXIgaXNzdWVzIHdoZW4gdXNlZCBhcyBhIHJlZmVyZW5jZSBwb2ludC4gVGhlIEJsaW0gZW1waXJpY2FsIGFwcHJvYWNoIHdhcyB0aGVyZWZvcmUgYWxzbyByZWplY3RlZC4gDQoNCkFzIG5vIHN0YW5kYXJkIHNvbHV0aW9uIHdhcyBmb3VuZCwgaXQgd2FzIGRlY2lkZWQgdG8gbW9kaWZ5IHRoZSBkZWZpbml0aW9uIG9mIEJsb3NzIGdpdmVuIGZvciBTdG9jayBUeXBlcyAxIGFuZCA1IHRvIGJlIGJhc2VkIG9uIHRoZSBtZWFuIG9mIHNldmVyYWwgc2ltaWxhciBTU0IgdmFsdWVzIHRoYXQgc3Bhbm5lZCB0aGUgcmFuZ2VzIG9mIGhhdmluZyB5aWVsZGVkIGJvdGggZGVjZW50IHJlY3J1aXRtZW50IGluIHR3byBjYXNlcyAoMjAxMCAmIDIwMTEpIGFuZCByYXRoZXIgbG93IHJlY3J1aXRtZW50IGluIDggY2FzZXMgKDIwMDI6MjAwOSkuIEFzIG5vdGVkIGFib3ZlLCBzZXR0aW5nIEJsb3NzIHRvIGJlIHRoZSBtaW5pbXVtIFNTQiBvYnNlcnZlZCBpbiAyMDEwIHdhcyBub3QgY29uc2lkZXJlZCBhIGNhbmRpZGF0ZSBmb3IgQmxpbSBiZWNhdXNlIGl0J3MgdmFsdWUgd2FzIGxlc3MgdGhlbiB0aGUgOCB2YWx1ZXMgY29uc2lkZXJlZCB0byBoYXZlIHlpZWxkZWQgcmF0aGVyIGxvdyByZWNydWl0bWVudCBlYXJsaWVyIGluIHRoZSB0aW1lIHNlcmllcy4gQW55IGNob2ljZSBvZiBTU0IgdmFsdWVzIGdyZWF0ZXIgdGhhbiB0aGUgMjAxMCB2YWx1ZSB3YXMgdGhlcmVmb3JlIGFyYml0cmFyeSwgc28gdGhlIGV4cGVydCBncm91cCBkZWNpZGVkIHRvIGluY2x1ZGUgYXMgbWFueSBhcyBwb3NzaWJsZSB0byByZWZsZWN0IHRoZSBncm91cCBvZiBzaW1pbGFyIFNTQiBhbmQgcmVjcnVpdG1lbnQgdmFsdWUgZWFybHkgaW4gdGhlIHRpbWUgc2VyaWVzLiBUaGUgMjAwMiAtIDIwMTEgdmFsdWVzIHdlcmUgZGVlbWVkICdkZWNlbnQnIGJlY2F1c2UgdGhleSBhcHBlYXJlZCB0byBzdXN0YWluIHJhdGhlciBzdGFibGUgU1NCIGFuZCByZWNydWl0bWVudCB2YWx1ZXMgZHVyaW5nIHRoZSBtaWQtcmFuZ2Ugb2YgdGhlIHRpbWUgc2VyaWVzLCBiZWZvcmUgdGhlIHByb2R1Y3Rpdml0eSBzaGlmdCBiZWdhbiBpbiAyMDIxLiBCbG9zcyB3YXMgdGhlcmVmb3JlIGNvbnNpZGVyZWQgdG8gYmUgdGhlIG1lYW4gU1NCIGZyb20gdGhlIGZpcnN0IHRlbiB5ZWFycyBvZiB0aGUgdGltZSBzZXJpZXMsIHdoZXJlIHJlY3J1aXRtZW50IGFuZCBTU0IgYm90aCByZW1haW5lZCByYXRoZXIgbG93LCBhbGJlaXQgdmFyaWFibGUuIEZ1cnRoZXJtb3JlLCB0aGlzIG1ldGhvZCBsZWQgdG8gYSB2YWx1ZSByb3VnaGx5IDE1JSBvZiBlc3RpbWF0ZXMgb2YgQjAgKGNhbGN1bGF0ZWQgc3Vic2VxdWVudGx5KSwgYW5kIEJsaW0gd2FzIHNldCB0byB0aGlzIG5ld2x5IGRlZmluZWQgQmxvc3MgdmFsdWUuDQoNCmBgYHtyIGNhbGN1bGF0ZSBCcGEgYW5kIEJsaW0gb3B0aW9uIDJ9DQoNCnJlZlB0c1ssIkJsaW0iXSA8LSBtZWFuKGRmW2RmJHllYXIgJWluJSBjKDIwMDI6MjAxMSksICJTU0IiXSkNCg0KcmVmUHRzWywiQnBhIl0gIDwtcmVmUHRzWywiQmxpbSJdKmV4cCgxLjY0NSpzaWdtYVNTQikNCg0Ka2FibGUocmVmUHRzKQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KSGF2aW5nIGFncmVlZCBhbmQgZXN0YWJsaXNoZWQgQmxpbSBhbmQgQnBhLCB3ZSBub3cgbW92ZSBvbiB0byBvdGhlciByZWZlcmVuY2UgcG9pbnRzLg0KDQojIyBDYWxjdWxhdGUgJEZfe2xpbX0kIGFuZCAkRl97cGF9JA0KPCEtLSBQSlc6IFRoaXMgaXMgbm8gbG9uZ2VyIHRydWUgRnBhIGlzIGRlcml2ZWQgZnJvbSBGbGltIGluIHRoZSByZXZlcnNlIG9mIHRoZSB3YXkgQnBhIGlzIGRlcml2ZWQgZnJvbSBCbGltLiAtLT4NCg0KPCEtLSBQSlc6IFRoZXNlIFNlZ1JlZyBtb2RlbHMgd2VyZSBhbHJlYWR5IHByZXNlbnRlZCBlYXJsaWVyIC0gc2tpcCAoSSBhZGRlZCAnZXZhbCA9IEYnIHRvIHRoZSBSIGNodW5rcykgVXNpbmcgYSBzZWdtZW50ZWQgcmVncmVzc2lvbiBvbiB0aGUgdHJ1bmNhdGVkIHRpbWVzZXJpZXMsIHdlIHNlZSBhIHBsYXRlYXUgd2l0aCBhIGJyZWFrcG9pbnQgYXJvdW5kIHRoZSBtYXhpbXVtIG9ic2VydmF0aW9uLiAtLT4NCg0KYGBge3IgcmVmaXQgZXFmaXQgdHJ1bmNhdGVkLCBmaWcuY2FwPSJFcWZpdCBTdG9jay1SZWNydWl0bWVudCBTZWctcmVnIG1vZGVsIG9uIHRydW5jYXRlZCBkYXRhc2VyaWVzLiIsIGV2YWwgPSBGfQ0KIyMgUmVmaXQgc3RvY2sgcmVjcnVpdG1lbnQgcmVsYXRpb25zaGlwIGJhc2VkIG9uIHRydW5jYXRlZCB0aW1lIHNlcmllcw0Kc2V0LnNlZWQoMTIzKQ0KZXFmaXQgPC0gZXFzcl9maXQoc3RrID0gc3RrLA0KICAgICAgICAgICAgICAgICAgbnNhbXAgPSBub1NpbXMsDQogICAgICAgICAgICAgICAgICBtb2RlbHMgPSBjKCJTZWdyZWciKSwNCiAgICAgICAgICAgICAgICAgIHJlbW92ZS55ZWFycyA9IHJtU1JSWXJzKQ0KDQojIyBQbG90DQplcXNyX3Bsb3QoZXFmaXQsbj0yZTQsZ2dQbG90PVRSVUUsU2NhbGU9MWUzKQ0KYGBgDQoNCkluIGZvcndhcmQgcHJvamVjdGlvbnMsIHdlIGNhbiB1c2UgYSBob2NrZXktc3RvY2sgZnVuY3Rpb24gdG8gcmVmbGVjdCB0aGUgc3RvY2stcmVjcnVpdG1lbnQgcmVsYXRpb25zaGlwLCBidXQgZm9yY2UgaXQgdG8gdXNlIG91ciBwcmUtZGVmaW5lZCBCbGltIGFzIHRoZSBicmVha3BvaW50LiBUaGlzIHJlcXVpcmVzIGZpdHRpbmcgdGhlICJzdGljayIgcG9ydGlvbiBvZiB0aGUgaG9ja2V5LXN0aWNrIGZ1bmN0aW9uIGFib3ZlIHRoZSBicmVha3BvaW50IHRvIHJlY3J1aXRtZW50IG9ic2VydmF0aW9ucy4NCg0KYGBge3IgcmVmaXQgZXFmaXQgdHJ1bmNhdGVkIEJsaW1CcmVhaywgZmlnLmNhcD0iRXFmaXQgU3RvY2stUmVjcnVpdG1lbnQgU2VnLXJlZyBtb2RlbCB3aXRoIEJsaW0gYnJlYWtwb2ludCBvbiB0cnVuY2F0ZWQgZGF0YXNlcmllcy4ifQ0KIyMgZGV0ZXJtaW5lIHNlZ3JlZyBtb2RlbCB3aXRoIEJsaW0gYnJlYWtwb2ludCBhbmQgKHJvdWdobHkpIGdlb21lYW4gcmVjIGFib3ZlIHRoaXMNClNlZ3JlZ0JsaW0gIDwtIGZ1bmN0aW9uKGFiLCBzc2IpIGxvZyhpZmVsc2Uoc3NiID49IHJlZlB0c1ssIkJsaW0iXSwgYWIkYSAqIHJlZlB0c1ssIkJsaW0iXSwgYWIkYSAqIHNzYikpDQoNCiMgIyMgZGV0ZXJtaW5lIHNlZ3JlZyBtb2RlbCB3aXRoIEJsb3NzIGJyZWFrcG9pbnQgYW5kIChyb3VnaGx5KSBnZW9tZWFuIHJlYyBhYm92ZSB0aGlzDQojIFNlZ3JlZ0Jsb3NzICA8LSBmdW5jdGlvbihhYiwgc3NiKSBsb2coaWZlbHNlKHNzYiA+PSBtaW4oc3NiKHN0aykpLCBhYiRhICogbWluKHNzYihzdGspKSwgYWIkYSAqIHNzYikpDQojIA0KIyAjIyBSZW1vdmUgdGhlIGxhc3QgeWVhciBmcm9tIEZMc3RvY2sgb2JqZWN0IHRvIHByZXZlbnQgTkEgaXNzdWVzIGZ1cnRoZXIgZG93biAoYXMgMjAyNCBpcyBiYXNlZCBvbmx5IG9uIG9uZSApDQojIHN0azEgPC0gdHJpbShzdGssIHllYXIgPSBjKChhcy5udW1lcmljKHN0a0ByYW5nZVsibWlueWVhciJdKSk6KChhcy5udW1lcmljKHN0a0ByYW5nZVsibWF4eWVhciJdKSktMSkpKQ0KDQojIyBSZWZpdCBzdG9jayByZWNydWl0bWVudCByZWxhdGlvbnNoaXAgYmFzZWQgb24gdHJ1bmNhdGVkIHRpbWUgc2VyaWVzDQpzZXQuc2VlZCgxMjMpDQplcWZpdCA8LSBlcXNyX2ZpdChzdGsgPSBzdGssDQogICAgICAgICAgICAgICAgICBuc2FtcCA9IG5vU2ltcywNCiAgICAgICAgICAgICAgICAgIG1vZGVscyA9IGMoIlNlZ3JlZ0JsaW0iKSwNCiAgICAgICAgICAgICAgICAgIHJlbW92ZS55ZWFycyA9IHJtU1JSWXJzKQ0KDQojIyBQbG90DQplcXNyX3Bsb3QoZXFmaXQsbj0yZTQsZ2dQbG90PVRSVUUsU2NhbGU9MWUzKQ0KYGBgDQoNCkJhc2VkIG9uIHRoaXMgZmluYWwgc3RvY2stcmVjcnVpdG1lbnQgcmVsYXRpb25zaGlwLCB3ZSBjYW4gYmVnaW4gdG8gZXN0aW1hdGUgTVNZIHJlZmVyZW5jZSBwb2ludHMuIFRvIGNhbGN1bGF0ZSBGbGltLCB3ZSBydW4gYSBzZXJpZXMgb2Ygc2ltdWxhdGlvbnMgd2l0aCBmaXhlZCBiaW9sb2dpY2FsIHBhcmFtZXRlcnMgYW5kIG5vIHZhcmlhYmlsaXR5IGluIHRoZSBlc3RpbWF0ZXMgb2YgRiBhbmQgU1NCLg0KDQpgYGB7ciBjYWxjdWxhdGUgRmxpbSBhbmQgRnBhLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQ0KDQpzZXQuc2VlZCgxMjMpDQpTSU1fU2VncmVnQmxpbSA8LSBlcXNpbV9ydW4oZXFmaXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW8ueWVhcnMgPSBjKChtYXhZZWFyLW51bUF2Z1lyc0IpLCBtYXhZZWFyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlvLmNvbnN0ID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLnllYXJzID0gYygobWF4WWVhci1udW1BdmdZcnNTKSwgbWF4WWVhciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC5jb25zdCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZjdiA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZwaGkgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTU0JjdiA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJob2xvZ1JlYyA9IHJob1JlYywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQnRyaWdnZXIgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCbGltID0gcmVmUHRzWywiQmxpbSJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCcGEgPSByZWZQdHNbLCJCcGEiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTnJ1biA9IE5ydW5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGc2NhbiA9IEZzVG9TY2FuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVQpDQoNCiMgc2F2ZSBNU1kgYW5kIGxpbSB2YWx1ZXMNCnRtcDEgPC0gdChTSU1fU2VncmVnQmxpbSRSZWZzKQ0KYGBgDQoNCmBgYHtyIEZwYSBwbG90cyB1cGRhdGUsIGZpZy5jYXA9IlBsb3RzIG9mIHN0b2NrIGR5bmFtaWNzIHVuZGVyIHNpbXVsYXRpb24gYXMgc3BlY2lmaWVkIGZvciBlc3RpbWF0aW9uIG9mIEZsaW0uIn0NCmVxc2ltX3Bsb3QoU0lNX1NlZ3JlZ0JsaW0sIGNhdGNoPVRSVUUpDQpgYGANCg0KYGBge3IgUmVjb3JkIEYgcmVmc30NCnJlZlB0c1ssIkZsaW0iXSA8LSB0bXAxWyJGNTAiLCJjYXRGIl0NCnRtcEZwYSA8LSByZWZQdHNbLCJGbGltIl0gKiBleHAoLXNpZ21hRiAqIDEuNjQ1KQ0KI1BKVzogVGhpcyBpcyBmaW5lIGJ1dCBrZWVwIGluIG1pbmQgbGF0ZXIgd2hlbiByZXBvcnRpbmcgdGhhdCB0aGlzIEZwYSBkZWZpbml0aW9uIGlzIG91dGRhdGVkIGFuZCBub3cgYmFzZWQgb24gRnAwNQ0KaWYgKHRtcEZwYTwwLjIpIHJlZlB0c1ssIkZwYSJdIDwtIHJvdW5kKHRtcEZwYSwgMykgZWxzZSByZWZQdHNbLCJGcGEiXSA8LSByb3VuZCh0bXBGcGEsIDIpDQpgYGANCg0KYGBge3IgRnBhIHRhYmxlIHVwZGF0ZX0NCg0Ka2FibGUoZGF0YS5mcmFtZShyZWZQdHNbLCJGbGltIl0scmVmUHRzWywiRnBhIl0pLCBjb2wubmFtZXMgPWMoIkZsaW0iLCAiRnBhIikpDQogICAgICANCg0KYGBgDQoNClRoZSBjYWxjdWxhdGVkIHZhbHVlcyBmb3IgRmxpbSBhbmQgRnBhIGFyZSBxdWl0ZSBsb3cgYW5kIGRpZCBub3QgcmVhc29uYWJseSByZWZsZWN0IHRoZSBzdG9jay4gVGhlIGxvdyB2YWx1ZXMgc2hvdyBhIG1pc21hdGNoIGJldHdlZW4gdGhlIHJldGFpbmVkIHJlY3J1aXRtZW50IHNlcmllcyAoYmVmb3JlIDIwMTkpIGFuZCB0aGUgcmVzYW1wbGVkIGJpb2xvZ2ljYWwgdmFyaWFibGVzIChsYXN0IDUgeWVhcnMpLiBUaHVzLCB0aGUgdHJ1bmNhdGlvbiBvZiB0aGUgc2FtcGxlZCB5ZWFycyBmb3IgdGhlIEIgYW5kIFMgY2FsY3VsYXRpb24gd2FzIGluY3JlYXNlZCB0byBpbmNsdWRlIHRoZSBsYXN0IDEwIHllYXJzIChpbnN0ZWFkIG9mIDUgeWVhcnMpIHRvIHRhY2tsZSB0aGUgbWlzbWF0Y2ggYmV0d2VlbiB0aGUgbmF0dXJhbCBtb3J0YWxpdHkgdmFsdWVzIGFuZCB0aGUgcmVjcnVpdG1lbnQuIA0KDQpUaGUgUmVjcnVpdG1lbnQtYXV0b2NvcnJlbGF0aW9uIChSaG9Mb2dSZWMpIGlzIGFsc28gaGlnaCAoPjAuOSkgd2hlbiBlc3RpbWF0ZWQgZnJvbSBTQU0gZGlyZWN0bHkgYW5kIGlzIGluZmx1ZW5jaW5nIHRoZSBlc3RpbWF0aW9uIG9mIHRoZSByZWZlcmVuY2UgcG9pbnRzLiBUaGUgaGlnaCB2YWx1ZSBzZWVtcyB0byBiZSBkcml2ZW4gYnkgdGhlIGV4Y2VwdGlvbmFsbHkgaGlnaCBSIGluIHRoZSBsYXRlc3QgeWVhciBjbGFzc2VzIHdoaWNoLCBmb3IgdGhhdCByZWFzb24sIHdlcmUgYWxyZWFkeSBleGNsdWRlZCBmcm9tIHRoZSBCbGltIGVzdGltYXRpb24gKHNlZSBhYm92ZSkuIEdlbmVyYWxseSwgUmhvIGlzIG11Y2ggc21hbGxlciBpbiBmaXNoIGFuZCBub3QgZWFzeSB0byBlc3RpbWF0ZSB3aXRoaW4gYXNzZXNzbWVudCBtb2RlbHMgd2l0aG91dCBiaWFzIGJlY2F1c2UgaXQgaXMgYSByYW5kb20gZWZmZWN0LCBzbyB0aGF0IEpvaG5zb24gZXQgYWwuICgyMDE2KSByZWNvbW1lbmRzIHRvIGRvIHRoZSBlc3RpbWF0aW9uIG91dHNpZGUgdGhlIG1vZGVsIGFuZCB0aGVuIGZpeCBpdC4gDQoNClRoZSBSZWNydWl0bWVudC1hdXRvY29ycmVsYXRpb24gKFJob0xvZ1JlYykgd2FzIHNldCB0byBhIGNvbnNlcnZhdGl2ZSBsZXZlbCBhdCAwLjYsIHdoaWNoIGlzIHNpbWlsYXIgdG8gb3RoZXIgUmhvIHZhbHVlcyBmb3IgcGxhaWNlIGRlcml2ZWQgZnJvbSBGSVNITElGRSAoaS5lLiwgMC41OCBmb3IgcGxhaWNlLCBUaG9yc29uIGV0IGFsLiwgMjAyMykuIA0KDQoNCmBgYHtyIHNpbXNhZ2Fpbmxvd2VyUmhvaGlnaGVybnVtQXZnWXJzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQ0KIyBUZXN0aW5nIHdoZXRoZXIgbWlzbWF0Y2ggYmV0d2VlbiBuYXR1cmFsIG1vcnRhbGl0eSB2YWx1ZXMgaW4gdGhlIGxhc3QgNSB5ZWFycyB2cyByZWNydWl0bWVudCB2YWx1ZXMgcHJldmlvdXNseSBjb3VsZCBhbHNvIGJlIGEgY3VscHJpdA0KDQpudW1BdmdZcnNCIDwtIG51bUF2Z1lyc1MgPC0gMTANCg0KcmVmUHRzMyA8LSBtYXRyaXgoTkEsbnJvdz0xLG5jb2w9OSwgZGltbmFtZXM9bGlzdCgidmFsdWUiLGMoIkJ0cmlnZ2VyIiwiQnBhIiwiQmxpbSIsIjV0aFBlcmNfU1NCbXN5IiwiRnBhIiwiRmxpbSIsICJGcDA1IiwiRm1zeV91bmNvbnN0ciIsIkZtc3kiKSkpDQoNCiByZWZQdHMzWywiQmxpbSJdIDwtIG1lYW4oZGZbZGYkeWVhciAlaW4lIGMoMjAwMjoyMDExKSwgIlNTQiJdKSAjIHJlZlB0czNbLCJCbGltIl0gPC0gcmVmUHRzWywiQmxpbSJdDQogcmVmUHRzM1ssIkJwYSJdICA8LXJlZlB0czNbLCJCbGltIl0qZXhwKDEuNjQ1KnNpZ21hU1NCKSAjIHJlZlB0czNbLCJCcGEiXSA8LSByZWZQdHNbLCJCcGEiXSANCg0Kc2V0LnNlZWQoMTIzKQ0KU0lNX1NlZ3JlZ0JsaW1fbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMgPC0gZXFzaW1fcnVuKGVxZml0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlvLnllYXJzID0gYygobWF4WWVhci1udW1BdmdZcnNCKSwgbWF4WWVhciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpby5jb25zdCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC55ZWFycyA9IGMoKG1heFllYXItbnVtQXZnWXJzUyksIG1heFllYXIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWwuY29uc3QgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGY3YgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGcGhpID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1NCY3YgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICByaG9sb2dSZWMgPSBjKDAuNiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ0cmlnZ2VyID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQmxpbSA9IHJlZlB0czNbLCJCbGltIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJwYSA9IHJlZlB0czNbLCJCcGEiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTnJ1biA9IE5ydW5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGc2NhbiA9IEZzVG9TY2FuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVQpDQp0bXAxIDwtIHQoU0lNX1NlZ3JlZ0JsaW1fbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkUmVmcykNCnJlZlB0czNbLCJGbGltIl0gPC0gdG1wMVsiRjUwIiwiY2F0RiJdDQojdG1wRnBhIDwtIHJlZlB0czNbLCJGbGltIl0gKiBleHAoLXNpZ21hRiAqIDEuNjQ1KQ0KI1BKVzogVGhpcyBpcyBmaW5lIGJ1dCBrZWVwIGluIG1pbmQgbGF0ZXIgd2hlbiByZXBvcnRpbmcgdGhhdCB0aGlzIEZwYSBkZWZpbml0aW9uIGlzIG91dGRhdGVkIGFuZCBub3cgYmFzZWQgb24gRnAwNQ0KdG1wRnBhIDwtIHJlZlB0czNbLCJGcGEiXSA8LSByZWZQdHMzWywiRnAwNSJdIDwtIHRtcDFbIkYwNSIsImNhdEYiXQ0KDQppZiAodG1wRnBhPDAuMikgcmVmUHRzM1ssIkZwYSJdIDwtIHJvdW5kKHRtcEZwYSwgMykgZWxzZSByZWZQdHMzWywiRnBhIl0gPC0gcm91bmQodG1wRnBhLCAyKQ0KDQpgYGANCg0KVGhlIHJlc3VsdGluZyBGbGltIGFuZCBGcGEgcmVmZXJlbmNlIHBvaW50cyB3ZXJlIGNsb3NlciB0byBzaW1pbGFyIHZhbHVlcyBpbiBvdGhlciBwbGFpY2Ugc3RvY2tzIGFuZCBtb3JlIGZpdHRpbmcgdG8gdGhlIGRldmVsb3BtZW50IG9mIHRoZSBzdG9ja3Mgc2luY2UgMjAxOSBhbmQgdGh1cyB3ZXJlIGtlcHQgZm9yIHRoZSBmb2xsb3dpbmcgY2FsY3VsYXRpb25zLg0KDQpgYGB7ciBGcGEgdGFibGUgdXBkYXRlIHdpdGggMTB5ZWFyIGF2ZyB2YWx1ZXN9DQoNCmthYmxlKGRhdGEuZnJhbWUocmVmUHRzM1ssIkZsaW0iXSxyZWZQdHMzWywiRnBhIl0pLCBjb2wubmFtZXMgPWMoIkZsaW0iLCAiRnBhIikpDQogICAgICANCg0KYGBgDQoNCg0KYGBge3IgRnBhIHBsb3RzIHVwZGF0ZWQgd2l0aCAxMHlyIGF2ZywgZmlnLmNhcD0iUGxvdHMgb2Ygc3RvY2sgZHluYW1pY3MgdW5kZXIgc2ltdWxhdGlvbiBhcyBzcGVjaWZpZWQgZm9yIGVzdGltYXRpb24gb2YgRmxpbS4ifQ0KZXFzaW1fcGxvdChTSU1fU2VncmVnQmxpbV9sb3dlclJob2hpZ2hlcm51bUF2Z1lycywgY2F0Y2g9VFJVRSkNCmBgYA0KDQpIb3dldmVyLCB3aGlsZSBGbGltIG1heSBzdGlsbCBiZSBkZXJpdmVkIGZyb20gQmxpbSAoYW5kIHVzZWQgdG8gYXNzZXNzIHRoZSBGIHRoYXQgZHJpdmVzIHRoZSBzdG9jayB0byBCbGltLCBiYXNlZCBvbiB0aGUgZXF1aWxpYnJpdW0gY3VydmUgb2Ygc3RvY2spLCBpdCBpcyBubyBsb25nZXIgdXNlZCBieSBJQ0VTIGFzIGJhc2lzIG9mIHByZWNhdXRpb25hcnkgYXBwcm9hY2ggKFBBKSBhbmQgTVNZIHJlZmVyZW5jZSBwb2ludHMgdG8gYXNzZXNzIHRoZSBzdGF0ZSBvZiBzdG9ja3MgYW5kIGV4cGxvaXRhdGlvbiwgYW5kIHRvIHByb3ZpZGUgYWR2aWNlIG9uIGZpc2hpbmcgb3Bwb3J0dW5pdGllcyBXS05FV1JFRjQsIElDRVMgMjAyNGQpLiBJdCBpcyB0aGVyZWZvcmUgb25seSB1c2VkIGZvciBpbmZvcm1hdGlvbiwgYnV0IG5vdCByZWNvZ25pemVkIGFzIHJlZmVyZW5jZSBwb2ludCBmb3IgdGhlIGFzc2Vzc21lbnQgYW5kIGFkdmljZSBhbmQgbm90IGluY2x1ZGVkIGluIHRoZSBmaW5hbCByZWZlcmVuY2UgcG9pbnQgbGlzdC4NCg0KDQojIyBjYWxjdWxhdGUgJEZfe01TWX0kICh1bmNvbnN0cmFpbmVkKQ0KVW5saWtlIHRoZSBzaW11bGF0aW9ucyB1c2VkIHRvIGVzdGltYXRlIEZsaW0sIHRoZSB1bmNvbnN0cmFpbmVkIEZNU1kgc2hvdWxkIGluaXRpYWxseSBiZSBjYWxjdWxhdGVkIGJhc2VkIG9uIGEgY29uc3RhbnQgRiBldmFsdWF0aW9uIHdpdGggdGhlIGluY2x1c2lvbiBvZiBzdG9jaGFzdGljaXR5IGluIHBvcHVsYXRpb24gYW5kIGV4cGxvaXRhdGlvbiBhcyB3ZWxsIGFzIGFzc2Vzc21lbnQvYWR2aWNlIGVycm9yLiBBcHByb3ByaWF0ZSBTUlJzIHNob3VsZCBiZSBzcGVjaWZpZWQuDQoNCkFsc28gaGVyZSwgdmFsdWUgd2FzIHJlY2FsY3VsYXRlZCB1c2luZyB0aGUgMTAgeWVhciBhdmcgaW5zdGVhZCBvZiA1IHllYXJzDQoNCmBgYHtyIHJlY2FsY3VsYXRlIEZtc3kgd2l0aCAxMHllYXIgYXZnIHZhbHVlcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIGZpZy5zaG93PSdoaWRlJ30NCg0Kc2V0LnNlZWQoMTIzKQ0KU0lNX1NlZ3JlZ19ub1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMgPC0gZXFzaW1fcnVuKGVxZml0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW8ueWVhcnMgPSBjKG1heFllYXItbnVtQXZnWXJzQiwgbWF4WWVhciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlvLmNvbnN0ID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLnllYXJzID0gYyhtYXhZZWFyLW51bUF2Z1lyc1MsIG1heFllYXIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC5jb25zdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZjdj1jdkYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZwaGk9cGhpRiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTU0Jjdj1jdlNTQiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByaG9sb2dSZWM9YygwLjYpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXAuc2ltcyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgQnRyaWdnZXIgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJsaW09cmVmUHRzM1ssIkJsaW0iXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCcGE9cmVmUHRzM1ssIkJwYSJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5ydW49TnJ1bnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRnNjYW4gPSBGc1RvU2NhbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVQpDQoNCnRtcDIgPC0gdChTSU1fU2VncmVnX25vVHJpZ19sb3dlclJob2hpZ2hlcm51bUF2Z1lycyRSZWZzKQ0KRm1zeV90bXAgPC0gdG1wMlsibWVkaWFuTVNZIiwiY2F0RiJdICNub3RlOiAgd2FzIHByZXZpb3VzbHkgbGFuZGluZ3MgRiBmb3IgRm1zeSwgZnJvbSB0aGUgd3Jvbmcgb3V0cHV0IChyZWZzMiBvdXRwdXQgdGFibGVzKQ0KDQp0bXBGcGEgPC0gcmVmUHRzM1ssIkZwYSJdIDwtIHJlZlB0czNbLCJGcDA1Il0gPC0gdG1wMlsiRjA1IiwiY2F0RiJdDQoNCg0KcmVmUHRzM1ssIkZtc3lfdW5jb25zdHIiXSA8LSBGbXN5X3RtcCANCmlmIChGbXN5X3RtcCA+IHJlZlB0czNbLCJGcGEiXSkgew0KICByZWZQdHMzWywiRm1zeSJdIDwtIHJlZlB0czNbLCJGcGEiXSAjUEpXOiBtYWtlIHN1cmUgdGhpcyBpcyBGcDA1DQp9IGVsc2Ugew0KcmVmUHRzM1ssIkZtc3kiXSA8LSBGbXN5X3RtcA0KfQ0KDQoNCmBgYA0KVGhlIHJlc3VsdGluZyB1bmNvbnN0cmFpbmVkIEZNU1kgaXMgYWJvdXRgciByZWZQdHMzWywgIkZtc3lfdW5jb25zdHIiXWAuIFRoZSB1bmNvbnN0cmFpbmVkIHZhbHVlIGlzIHVzZWQgYXMgYmFzaXMgZm9yIHRoZSBuZXh0IHN0ZXBzIGluIHRoZSByZWZlcmVuY2UgcG9pbnQgY2FsY3VsYXRpb25zLg0KDQoNCmBgYHtyIEZNU1kgcGxvdHMgdXBkYXRlZCB3aXRoIDEweXIgYXZnLCBmaWcuY2FwPSJQbG90cyBvZiBzdG9jayBkeW5hbWljcyB1bmRlciBzaW11bGF0aW9uIGFzIHNwZWNpZmllZCBmb3IgZXN0aW1hdGlvbiBvZiBGTVNZLiJ9DQplcXNpbV9wbG90KFNJTV9TZWdyZWdfbm9UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzLCBjYXRjaD1UUlVFKQ0KYGBgDQoNCg0KIyMgJE1TWV97QiB0cmlnZ2VyfSQNCk1TWSBCIHRyaWdnZXIgaXMgYSBsb3dlciBib3VuZCBvZiB0aGUgU1NCIGRpc3RyaWJ1dGlvbiB3aGVuIHRoZSBzdG9jayBpcyBmaXNoZWQgYXQgRiBNU1kgKElDRVMsIDIwMjEpLiANCkFzIHN0YXRlZCBpbiB0aGUgSUNFUyB0ZWNobmljYWwgZ3VpZGVsaW5lcywgcmVjZW50IGZpc2hpbmcgbW9ydGFsaXR5IGVzdGltYXRlcyBuZWVkIHRvIGJlIGNvbnNpZGVyZWQgdG8gc2V0IE1TWSBCIHRyaWdnZXIgYXMgZm9yIG1vc3Qgc3RvY2tzIHRoYXQgbGFjayBkYXRhIG9uIGZpc2hpbmcgYXQgRiBNU1ksIE1TWSBCIHRyaWdnZXIgaXMgc2V0IGF0IEJwYS4gSGVyZSwgdGhlIHN0b2NrIGhhcyBiZWVuIGZpc2hlZCBiZWxvdyBGIE1TWSAoYHIgcmVmUHRzM1ssICJGbXN5Il1gKSBmb3IgdGhlIGxhc3QgNSB5ZWFycy4gTmV4dCBzdGVwIGlzIHRvIGxvb2sgaWYgdGhlIDV0aCBwZXJjZW50aWxlIG9mIEIgTVNZID4gQnBhLiAgDQoNCmBgYHtyIGNhbGN1bGF0ZSA1dGhQZXJjIFNTQk1TWSBmcm9tIFNJTV9TZWdyZWdfbm9UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzfQ0KZGF0YS4wNTwtU0lNX1NlZ3JlZ19ub1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkcmJwDQp4LjA1IDwtIGRhdGEuMDVbZGF0YS4wNSR2YXJpYWJsZSA9PSAiU3Bhd25pbmcgc3RvY2sgYmlvbWFzcyIsIF0kRnRhcmdldA0KYi4wNSA8LSBkYXRhLjA1W2RhdGEuMDUkdmFyaWFibGUgPT0gIlNwYXduaW5nIHN0b2NrIGJpb21hc3MiLCBdJHAwNQ0KIyBwbG90KGIuMDV+eC4wNSwgeWxhYj0iU1NCIiwgeGxhYj0iRiIpDQpiLmxtIDwtIGxvZXNzKGIuMDUgfiB4LjA1KQ0KcmVmUHRzM1ssIjV0aFBlcmNfU1NCbXN5Il0gPC0gcHJlZGljdChiLmxtLCByZWZQdHMzWywiRm1zeSJdKQ0KDQpgYGANCg0KYGBge3IgY2FsY3VsYXRlIEJ0cmlnZ2VyLCBldmFsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0NCg0KIyBjaGVjayBpZiBGPEZtc3kgbGFzdCA1IHllYXJzDQppZiAoc3VtKGFzLm51bWVyaWMoZmJhcihzdGspWyxhYygobWF4WWVhci00KTptYXhZZWFyKV0pPD1yZWZQdHMzWywiRm1zeSJdKTwzKSB7DQogIHJlZlB0czNbLCJCdHJpZ2dlciJdICA8LSByZWZQdHMzWywiQnBhIl0gIA0KfSBlbHNlIHsNCiAgIyBDaGVjayBpZiBCbXN5XzA1PkJwYQ0KICByZWZQdHMzWywiQnRyaWdnZXIiXSA8LWlmZWxzZShyZWZQdHMzWywiNXRoUGVyY19TU0Jtc3kiXT5yZWZQdHMzWywiQnBhIl0scmVmUHRzM1ssIjV0aFBlcmNfU1NCbXN5Il0scmVmUHRzM1ssIkJwYSJdKQ0KICAjIENoZWNrIGlmIEJtc3lfMDUgPiBTU0JjdXJfMDUNCiAgcmVmUHRzM1ssIkJ0cmlnZ2VyIl0gPC1pZmVsc2UocmVmUHRzM1ssIjV0aFBlcmNfU1NCbXN5Il0gPiBTU0IwNSxtYXgocmVmUHRzM1ssIkJwYSJdLFNTQjA1KSxyZWZQdHMzWywiNXRoUGVyY19TU0Jtc3kiXSkgIA0KfQ0KDQoNCmBgYA0KDQpUaGUgZ3JvdXAgYWdyZWVkIHRvIHVzZSBhIHNpbXBsZSB2ZXJzaW9uIHRvIHNldCBCIHRyaWdnZXIgYXMgQnBhDQoNCmBgYHtyIHNpbXBsZSBCIHRyaWdnZXIgdmVyc2lvbn0NCg0KIyMjIHNpbXBsaWZpZWQgc29sdXRpb24gYWZ0ZXIgd2ViIG1lZXRpbmcgd2l0aCBDb2xpbiAoc21vb3RoaW5nIGZ1bmN0aW9uIGlzIGNyZWF0aW5nIGEgd2VpcmQgQiB0cmlnZ2VyKQ0KDQpyZWZQdHMzWywiQnRyaWdnZXIiXSA8LSByZWZQdHNbLCJCcGEiXQ0KDQpgYGANCg0KDQpgYGB7ciBwbG90IHNzYl9QMDUgYXQgRiwgZmlnLmNhcD0iU1NCIGF0IEYgd2l0aCBQMDUgb2YgZ29pbmcgYmVsb3cgQnBhIChsaW5lIGlzIGEgbG9lc3Mgc21vb3RoZXIgdXNlZCB0byBlc3RpbWF0ZSB0aGUgU1NCIHdpdGggNSUgcmlzayBvZiBCcGEgYXQgRm1zeSkuIiwgZXZhbCA9IEZBTFNFfQ0KDQojIFRoaXMgcGxvdCBpcyBvbmx5IG5lZWRlZCBpZiB5b3UgYXJlIGdvaW5nIHRvIHVzZSA1dGggcGVyY2VudGlsZSBkZWZpbml0aW9uLCBhbmQgYWNjb3JkaW5nIHRvIHRoZSBhYm92ZSB0aGlzIHN0b2NrIGRvZXNuJ3QgcXVhbGlmeSBhbnl3YXksIGV2ZW4gaWYgd2UgdGhvdWdodCBpdCB3YXMgYSBnb29vZCBpZGVhIHRvIHVzZSBpdC4gSSBhZGRlZCBldmFsID0gRkFMU0UgdG8gdGhlIGNodW5rIGNvZGUuIFNpZGUgbm90ZSAtIEkgdGhpbmsgdGhlIGxvZXNzIHNtb290aGVyIG5lZWRzIG1vcmUgbm9kZXMgb3Igc29tZXRoaW5nIGJlY2F1c2UgaXQgZG9lc24ndCBsb29rIGxpa2UgaXRzIGZpdHRpbmcgYW55d2F5Lg0KDQpnZ3Bsb3RseShnZ3Bsb3QoZGF0YSA9IE5VTEwsDQogICAgICAgICAgICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4ID0geC4wNSwgeSA9IGIuMDUpKSsNCiAgICAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxKSsNCiAgICAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgc2UgPSBGLA0KICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBlYnBhbFsxXSkgKw0KICAgICAgICAgICB5bGFiKCJTU0IgKHRvbm5lcykgd2l0aCBGIHRoYXQgZ2l2ZXNcbjUlIGNoYW5jZSBvZiBnb2luZyBiZWxvdyBCcGEiKSsNCiAgICAgICAgICAgeGxhYigiRmlzaGluZyBwcmVzc3VyZSAoRikiKSArDQogICAgICAgICAgIHRoZW1lX2NsZWFuKCkNCiAgICAgICAgICAgKQ0KYGBgDQoNCg0KSW4gdGhpcyBjYXNlIHRoZSA1dGggcGVyY2VudGlsZSBvZiBCIE1TWSBpcyBub3QgZ3JlYXRlciB0aGFuIEJwYS4gIFRoZXJlZm9yZSBmb2xsb3dpbmcgdGhlIElDRVMgdGVjaG5pY2FsIGd1aWRlbGluZXMgdGhlIE1TWSBCIHRyaWdnZXIgIHdpbGwgYmUgZXF1YWwgdG8gQnBhICwgTVNZIEIgdHJpZ2dlciAgPSBgciByZWZQdHMzWywgIkJ0cmlnZ2VyIl1gIHRvbm5lcy5NU1kgQnRyaWdnZXIgc2hvdWxkIGJlIHNlbGVjdGVkIHRvIHNhZmVndWFyZCBhZ2FpbnN0IGFuIHVuZGVzaXJhYmxlIG9yIHVuZXhwZWN0ZWQgbG93IFNTQiB3aGVuIGZpc2hpbmcgYXQgRk1TWS4NCg0KDQpgYGB7ciBpbnRlcm1lZGlhdGUgYnRyaWdnZXIgdGFibGV9DQpyZXF1aXJlKGthYmxlRXh0cmEpICNQSlc6IEFkZGVkIHRoaXMNCg0KZHQgPC0gcmVmUHRzM1ssIGMoMSwyLDQpXQ0KDQpkdCAlPiUNCiAga2JsKGJvb2t0YWJzID0gVFJVRSwgY2FwdGlvbj0iQnRyaWdnZXIgYW5kIEJwYSByZWZlcmVuY2UgcG9pbnRzIGZvciBwbGUuMjcuMjEtMzIiKSAlPiUNCiAga2FibGVfbWF0ZXJpYWxfZGFyaygpDQoNCmBgYA0KDQojIyBmaW5hbCAkRl97TVNZfSQgDQpUaGUgSUNFUyBNU1kgQWR2aWNlIFJ1bGUgc2hvdWxkIGJlIGV2YWx1YXRlZCB0byBjaGVjayB0aGF0IHRoZSBGTVNZIGFuZCBNU1kgQnRyaWdnZXIgY29tYmluYXRpb24gYWRoZXJlcyB0byBwcmVjYXV0aW9uYXJ5IGNvbnNpZGVyYXRpb25zOiANCiogaW4gdGhlIGxvbmcgdGVybSwgUChTU0I8QmxpbSk8NSUNClRoZSBldmFsdWF0aW9uIG11c3QgaW5jbHVkZToNCiogcmVhbGlzdGljIGFzc2Vzc21lbnQgKGFkdmljZSkgZXJyb3INCiogc3RvY2hhc3RpY2l0eSBpbiBwb3B1bGF0aW9uIGJpb2xvZ3kgYW5kIGZpc2hlcnkgZXhwbG9pdGF0aW9uLg0KKiBBcHByb3ByaWF0ZSBTUlJzIHNob3VsZCBiZSBzcGVjaWZpZWQgKGhlcmUgdXNpbmcgc2VncmVnYXRpb24gbW9kZWwgd2l0aCBmaXhlZCBicmVha3BvaW50KQ0KDQpgYGB7ciBmaW5hbCBGbXN5IGFuZCB0YWJsZSB1cGRhdGVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQ0Kc2V0LnNlZWQoMTIzKQ0KU0lNX1NlZ3JlZ19UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzIDwtIGVxc2ltX3J1bihlcWZpdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYmlvLnllYXJzID0gYyhtYXhZZWFyLW51bUF2Z1lyc0IsIG1heFllYXIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBiaW8uY29uc3QgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLnllYXJzID0gYyhtYXhZZWFyLW51bUF2Z1lyc1MsIG1heFllYXIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBzZWwuY29uc3QgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgRmN2PWN2RiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgRnBoaT1waGlGLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBTU0Jjdj1jdlNTQiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmhvbG9nUmVjPWMoMC42KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcC5zaW1zID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgQnRyaWdnZXIgPSByZWZQdHMzWywiQnRyaWdnZXIiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgQmxpbT1yZWZQdHMzWywiQmxpbSJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBCcGE9cmVmUHRzM1ssIkJwYSJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBOcnVuPU5ydW5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBGc2NhbiA9IEZzVG9TY2FuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUpDQp0bXAzIDwtIHQoU0lNX1NlZ3JlZ19UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzJFJlZnMpDQpyZWZQdHMzWywiRnAwNSJdIDwtIHJlZlB0czNbLCJGcGEiXSA8LSB0bXAzWyJGMDUiLCJjYXRGIl0gI25vdGU6IGNhdGNoIEYgZm9yIEZwMDUNCg0KDQpyZWZQdHMzWywiRm1zeV91bmNvbnN0ciJdIDwtIEZtc3lfdG1wIA0KaWYgKEZtc3lfdG1wID4gcmVmUHRzM1ssIkZwYSJdKSB7DQogIHJlZlB0czNbLCJGbXN5Il0gPC0gcmVmUHRzM1ssIkZwYSJdDQp9IGVsc2Ugew0KcmVmUHRzM1ssIkZtc3kiXSA8LSBGbXN5X3RtcA0KfQ0KI1RoaXMgc2hvd3MgdGhhdCB0aGUgbWlzbWF0Y2ggYmV0d2VlbiB0aGUgcmVjcnVpdG1lbnQgc2VyaWVzIHdlIHJldGFpbmVkIChiZWZvcmUgMjAxOSkgYW5kIHRoZSBiaW9sb2dpY2FsIHZhcmlhYmxlcyB3ZSByZXNhbXBsZWQgKGxhc3QgNSB5ZWFycyksIGFsc28gY2F1c2VkIHNvbWUgY29uZnVzaW9uLiBJIHRoaW5rIGl0IGlzIGJlc3QgdG8gY29udGludWUgd2l0aCB0aGlzIHZlcnNpb24gYWJvdmUgLSBsb29rIGZvciBhIHJlYXNvbmFibGUgcmhvIHZhbHVlIChpbiB0aGUgcmFuZ2UgMC4zIC0gMC42IEkgdGhpbmspLCBhbmQga2VlcCB0aGUgbGFzdCAxMCB5ZWFycyBmb3Igc2FtcGxpbmcuDQoNCmBgYA0KDQpgYGB7ciBhZGQgdXBwZXIgYW5kIGxvd2VyIE1TWSB2YWx1ZSBmb3IgQ2F0RiBGMDV9DQoNCnNpbSA8LSBTSU1fU2VncmVnX1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMNCiMgc2ltIDwtIFNJTV9TZWdyZWdfbm9UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzICMgdGhpcyBvbmUgZm9yIHVuY29uc3RyYWluZWQgRk1TWSB1cHBlciBhbmQgbG93ZXINCiBpbnRlcnZhbCA9IDAuOTUNCiBkYXRhLjk1IDwtIHNpbSRyYnANCiAgICB4Ljk1IDwtIGRhdGEuOTVbZGF0YS45NSR2YXJpYWJsZSA9PSAiQ2F0Y2giLF0kRnRhcmdldA0KICAgIHkuOTUgPC0gZGF0YS45NVtkYXRhLjk1JHZhcmlhYmxlID09ICJDYXRjaCIsXSRNZWFuDQoNCiAgICB5aWVsZC5wOTUgPC0gaW50ZXJ2YWwgKiBtYXgoeS45NSwgbmEucm0gPSBUUlVFKQ0KICAgDQogICAgIyBGaXQgbG9lc3Mgc21vb3RoZXIgdG8gY3VydmUNCiAgICB4LmxtIDwtIHN0YXRzOjpsb2Vzcyh5Ljk1IH4geC45NSwgc3BhbiA9IDAuMikNCiAgICBsbS5wcmVkIDwtIGRhdGEuZnJhbWUoeCA9IHNlcShtaW4oeC45NSksIG1heCh4Ljk1KSwgbGVuZ3RoID0gMTAwMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSByZXAoTkEsIDEwMDApKQ0KICAgIGxtLnByZWQkeSA8LSBzdGF0czo6cHJlZGljdCh4LmxtLCBuZXdkYXRhID0gbG0ucHJlZCR4KQ0KICANCiAgICAjIExpbWl0IGZpdHRlZCBjdXJ2ZSB0byB2YWx1ZXMgZ3JlYXRlciB0aGFuIHRoZSA5NSUgY3V0b2ZmDQogICAgbG0ucHJlZC45NSA8LSBsbS5wcmVkW2xtLnByZWQkeSA+PSB5aWVsZC5wOTUsXQ0KICAgIGZtc3kubG93ZXIgPC0gbWluKGxtLnByZWQuOTUkeCkNCiAgICBmbXN5LnVwcGVyIDwtIG1heChsbS5wcmVkLjk1JHgpDQogICAgDQogICAgZm1zeS5sb3dlci5tZWFuIDwtIGZtc3kubG93ZXINCiAgICBmbXN5LnVwcGVyLm1lYW4gPC0gZm1zeS51cHBlcg0KICAgIGNhdGNoLmxvd2VyLm1lYW4gPC0gbG0ucHJlZC45NVtsbS5wcmVkLjk1JHggPT0gZm1zeS5sb3dlci5tZWFuLF0keQ0KICAgIGNhdGNoLnVwcGVyLm1lYW4gPC0gbG0ucHJlZC45NVtsbS5wcmVkLjk1JHggPT0gZm1zeS51cHBlci5tZWFuLF0keQ0KDQogICAgIyBSZXBlYXQgZm9yIDk1JSBvZiB5aWVsZCBhdCBGKDA1KToNCiAgICBmMDUgPC0gc2ltJFJlZnNbImNhdEYiLCJGMDUiXQ0KICAgIHlpZWxkLmYwNSA8LSBzdGF0czo6cHJlZGljdCh4LmxtLCBuZXdkYXRhID0gZjA1KQ0KICAgIHlpZWxkLmYwNS45NSA8LSBpbnRlcnZhbCAqIHlpZWxkLmYwNSAgDQogICAgbG0ucHJlZC5mMDUuOTUgPC0gbG0ucHJlZFtsbS5wcmVkJHkgPj0geWllbGQuZjA1Ljk1LF0NCiAgICBmMDUubG93ZXIgPC0gbWluKGxtLnByZWQuZjA1Ljk1JHgpDQogICAgZjA1LnVwcGVyIDwtIG1heChsbS5wcmVkLmYwNS45NSR4KQ0KDQogICMgYWRkIHVwcGVyIGFuZCBsb3dlciBlc3RpbWF0ZXMgdG8gUmVmMiB0YWJsZQ0KICBTSU1fU2VncmVnX1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkUmVmczJbImNhdEYiLCJNZWFubG93ZXIiXSA8LSBmMDUubG93ZXINCiAgU0lNX1NlZ3JlZ19UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzJFJlZnMyWyJjYXRGIiwiTWVhbnVwcGVyIl0gPC0gZjA1LnVwcGVyDQoNCmBgYA0KDQpUbyBlbnN1cmUgY29uc2lzdGVuY3kgYmV0d2VlbiB0aGUgcHJlY2F1dGlvbmFyeSBhbmQgdGhlIE1TWSBmcmFtZXdvcmtzLCBGTVNZIGlzIG5vdCBhbGxvd2VkIHRvIGJlIGFib3ZlIEZwMDU7IHRoZXJlZm9yZSwgaWYgdGhlIGluaXRpYWwgRk1TWSB2YWx1ZSBpcyBhYm92ZSBGcDA1LCBGTVNZIGlzIHJlZHVjZWQgdG8gRnAwNS4gRnAwNSB3YXMgY2FsY3VsYXRlZCBieSBydW5uaW5nIEVxU2ltIHdpdGggYXNzZXNzbWVudC9hZHZpY2UgZXJyb3IsIHdpdGggYWR2aWNlIHJ1bGUsIGFuZCB3aXRoIGEgc2VnbWVudGVkIHJlZ3Jlc3Npb24gd2l0aCBicmVha2luZyBwb2ludCBmaXhlZCBhdCBCcGEgdG8gZW5zdXJlIHRoYXQgdGhlIGxvbmctdGVybSByaXNrIG9mIFNTQiA8IEJsaW0gb2YgYW55IEYgdXNlZCBkb2VzIG5vdCBleGNlZWQgNSUgd2hlbiBhcHBseWluZyB0aGUgYWR2aWNlIHJ1bGUuIEZwMDUgd2FzIGVzdGltYXRlZCB0byBiZSBgciByZWZQdHMzWywgIkZtc3kiXWAgKEYwNSBmb3IgY2F0RikuIFRoZXJlZm9yZSwgYXMgZXhwbGFpbmVkIGFib3ZlLCBgciByZWZQdHMzWywgIkZtc3kiXWAuIFRoZSB1cHBlciBhbmQgbG93ZXIgcmFuZ2VzIGFyZSBnaXZlbiBpbiB0aGUgZm9sbG93aW5nIHRhYmxlLiANCg0KDQpgYGB7ciBmaW5hbCBmbXN5IHRhYmxlIHVwZGF0ZX0NCg0KZHQyIDwtIHJlZlB0czNbLCBjKDcsOSldDQoNCmR0MiRGbXN5X2xvd2VyIDwtICBTSU1fU2VncmVnX1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkUmVmczJbImNhdEYiLCJNZWFubG93ZXIiXSANCmR0MiRGbXN5X3VwcGVyIDwtICBTSU1fU2VncmVnX1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkUmVmczJbImNhdEYiLCJNZWFudXBwZXIiXQ0KZHQyIDwtdChkdDIpDQoNCmR0MiAlPiUNCiAga2JsKGJvb2t0YWJzID0gVFJVRSwgY2FwdGlvbj0iRnAwNSBhbmQgRm1zeSByZWZlcmVuY2UgcG9pbnRzIGZvciBwbGUuMjcuMjEtMzIiLCBkaWdpdHMgPSA0KSAlPiUNCiAga2FibGVfbWF0ZXJpYWxfZGFyaygpDQoNCg0KDQpgYGANCg0KSW4gY2FzZSBvZiBsaW1pdGF0aW9uIGJ5IEZNU1kgPSBGcGEsIHRoZSB1cHBlciBGTVNZIGxpbWl0IGVxdWFscyB0aGUgKGNhcHBlZCkgRk1TWSBhbmQgdGhlIGxvd2VyIGxpbWl0IGlzIHJlLWNhbGN1bGF0ZWQgdXNpbmcgdGhlIGNhcHBlZCBGTVNZIHZhbHVlIChpbiB0aGlzIGNhc2UsIEZNU1kgPSBgciByZWZQdHNbLCAiRm1zeSJdYCBpbnN0ZWFkIG9mIHVzaW5nIHRoZSB1bmNvbnN0cmFpbmVkIEZNU1kgPSBgciByZWZQdHMzWywgIkZtc3lfdW5jb25zdHIiXWApDQoNCg0KDQojIyBmaW5hbCBncmFwaHMNCg0KV2hhdCBmaW5hbCBncmFwaHMgZG8gd2UgcmVhbGx5IHdhbnQgdG8gc2VlPw0KDQpgYGB7ciBmaW5hbCBncmFwaHMsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0KIyBkaXNwbGF5IEVxdWlsaWJyaXVtIHBsb3RzDQoNCg0KcmVmcG9pbnRzPC1hcy5kYXRhLmZyYW1lKFNJTV9TZWdyZWdfVHJpZ19sb3dlclJob2hpZ2hlcm51bUF2Z1lycyRSZWZzKQ0KYXJncyhlcXNyX2ZpdCkNCnN0cihlcWZpdCwgMiwgZ2l2ZS5hdHRyPUZBTFNFKQ0KZXFmaXQkc3IuZGV0DQoNCmVxc3JfcGxvdChlcWZpdCxuPTJlNCxnZ1Bsb3Q9VFJVRSxTY2FsZT0xZTMpDQojc3RyKFNJTV9TZWdyZWdfVHJpZywgMixGIGdpdmUuYXR0ciA9IEZBTFNFKQ0KdChTSU1fU2VncmVnX1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkcmVmc19pbnRlcnZhbCkNCnQoU0lNX1NlZ3JlZ19ub1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkcmVmc19pbnRlcnZhbCkNCnQoU0lNX1NlZ3JlZ19ub1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkUmVmcykNCg0KDQpgYGANCg0KYGBge3IsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0KZXFzaW1fcGxvdChTSU1fU2VncmVnQmxpbV9sb3dlclJob2hpZ2hlcm51bUF2Z1lycywgY2F0Y2g9VFJVRSkNCmBgYA0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFLCBlY2hvID0gRkFMU0V9DQplcXNpbV9wbG90KFNJTV9TZWdyZWdfbm9UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzLCBjYXRjaD1UUlVFKQ0KYGBgDQoNCmBgYHtyLCBldmFsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0NCmVxc2ltX3Bsb3QoU0lNX1NlZ3JlZ19UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzLCBjYXRjaD1UUlVFKQ0KYGBgDQoNCg0KYGBge3IgZmluYWwgZXFzaW0gcmFuZ2UgcGxvdHN9DQoNCmVxc2ltX3Bsb3RfcmFuZ2UoU0lNX1NlZ3JlZ19ub1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMsIHR5cGU9Im1lYW4iKQ0KZXFzaW1fcGxvdF9yYW5nZShTSU1fU2VncmVnX25vVHJpZ19sb3dlclJob2hpZ2hlcm51bUF2Z1lycywgdHlwZT0ibWVkaWFuIikNCmVxc2ltX3Bsb3RfcmFuZ2UoU0lNX1NlZ3JlZ19UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzLCB0eXBlPSJzc2IiKQ0KDQpgYGANCg0KDQoNCmBgYHtyIGZpbmFsIGVxc2ltIGZtc3kgcGxvdH0NCg0KZXFzaW1fcGxvdF9yYW5nZShTSU1fU2VncmVnX1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMsIHR5cGU9Im1lYW4iKQ0KDQpgYGANCg0KDQojIGZpbmFsIHJlZmVyZW5jZSBwb2ludCB0YWJsZQ0KVGhlIGZpbmFsIHJlZmVyZW5jZSBwb2ludHMgYXJlIHJlZmxlY3RpbmcgdGhlIGNoYW5nZXMgb2YgdGhlIHN0b2NrIHNpbmNlIHRoZSBsYXN0IGJlbmNobWFyay4gVGhlIG5ldyB2YWx1ZXMgY2Fubm90IGJlIGNvbXBhcmVkIHdpdGggdGhlIG9sZCByZWZlcmVuY2UgcG9pbnRzIGRpcmVjdGx5LiBOb3Qgb25seSBkaWQgdGhlIHN0b2NrIHVuaXQgY2hhbmdlIGJ5IG1lcmdpbmcgdHdvIHN0b2NrcywgYnV0IGFsc28gdGhlIGJpb2xvZ2ljYWwgcGFyYW1ldGVyIGluIHRoZSBhc3Nlc3NtZW50IGhhdmUgYmVlbiBjaGFuZ2VkIChlLmcuLCBieSB1c2luZyBzbGlkaW5nIHdpbmRvdyBhdmVyYWdlcyBmb3Igd2VpZ2h0LWF0LWFnZSBhbmQgbWF0dXJpdHksIGFzIHdlbGwgYXMgaW5jb3Jwb3JhdGluZyBuZXcgbmF0dXJhbCBtb3J0YWxpdHkgZXN0aW1hdGVzIGFuZCBkaXNjYXJkIHN1cnZpdmFsKS4gQWRkaXRpb25hbGx5LCB0aGUgc3RvY2sgaXMgZGlzcGxheWluZyBhbiBleGNlcHRpb25hbCBpbmNyZWFzZSBpbiBiaW9tYXNzLCB3aGljaCBoYXMgbm90IGJlZW4gcHJlc2VudCBhdCB0aGUgbGFzdCBiZW5jaG1hcmsuIEFzIEZwYSA9IEZwMDUgKElDRVMgMjAyNGQpLCBvbmx5IHRoZSBGcGEgdmFsdWUgaXMgZGlzcGxheWVkIGluIHRoZSB0YWJsZS4gDQoNCg0KYGBge3IgZmluYWwgcmVmcG9pbnQgdGFibGV9DQojUmVmUG9pbnRUYWJsZSA8LSBhcy5kYXRhLmZyYW1lKHQocmVmUHRzMykpDQojUmVmUG9pbnRUYWJsZSRSZWZlcmVuY2VQb2ludCA8LSByb3duYW1lcyhSZWZQb2ludFRhYmxlKQ0KI3Jvd25hbWVzKFJlZlBvaW50VGFibGUpIDwtIE5VTEwNCiNSZWZQb2ludFRhYmxlJFVuaXRzIDwtIGMoInQiLCAidCIsICJ0IiwgInQiLCAiRiIsICJGIiwgIkYiLCAiRiIsICJGIikNCiNSZWZQb2ludFRhYmxlIDwtIFJlZlBvaW50VGFibGVbLCBjKDIsMSwzKV0NCiNSZWZQb2ludFRhYmxlJFJvdW5kZWRWYWx1ZSA8LSBpZmVsc2UoUmVmUG9pbnRUYWJsZSRVbml0cyA9PSAiRiIsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShSZWZQb2ludFRhYmxlJHZhbHVlPDAuMiwgcm91bmQoUmVmUG9pbnRUYWJsZSR2YWx1ZSwgMyksIHJvdW5kKFJlZlBvaW50VGFibGUkdmFsdWUsIDIpKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQoUmVmUG9pbnRUYWJsZSR2YWx1ZSwgMCkpDQpyZWZQdHM0IDwtIHJlZlB0czNbLCBjKDEsMiwzLDQsNSw4LDkpXQ0KDQp0KHJlZlB0czQpICU+JQ0KICAgIGtibChib29rdGFicyA9IFRSVUUsIGNhcHRpb249InJlZmVyZW5jZSBwb2ludHMgZm9yIHBsZS4yNy4yMS0zMiIpICU+JQ0KICAgIGthYmxlX21hdGVyaWFsX2RhcmsoKQ0KDQoNCg0KYGBgDQoNCjxjZW50ZXI+DQoNCiFbXShpbWFnZS9QTEUucG5nKQ0KPC9jZW50ZXI+DQoNCg0KIyBhZGRpdGlvbmFsIHNjZW5hcmlvczogDQojIyBub24tdHJ1bmNhdGVkIFJlY3J1aXRtZW50IHNlcmllcw0KU2Vuc2l0aXZpdHkgcnVuIHVzaW5nIHRoZSBub24tdHJ1bmNhdGVkIHJlY3J1aXQgdGltZSBzZXJpZXMuIEFsbCBvdGhlciBzZXR0aW5ncyBhcmUgaWRlbnRpY2FsIHRvIHRoZSBmaW5hbCBzZXR0aW5ncyBvZiB0aGUgcmVmZXJlbmNlIHBvaW50IGNhbGN1bGF0aW9uIGFib3ZlOg0KLSBCbGltIGFzIGF2ZXJhZ2UgU1NCIG9mIHRoZSBmaXJzdCB0ZW4geWVhcnMgb2YgdGhlIHRpbWUgc2VyaWVzDQotIGxhc3QgMTAgeWVhcnMgb2YgYmlvbG9naWNhbCBkYXRhIHVzZWQgZm9yIFMgYW5kIEIgZXN0aW1hdGlvbiBpbiB0aGUgcmVmZXJlbmNlIHBvaW50IG1vZGVscw0KLSBhdXRvY29ycmVsYXRpb24gb2YgcmVjcnVpdG1lbnQgZml4ZWQgdG8gUmhvTG9nUmVjID0gMC42DQoNCg0KYGBge3Igbm9uIHJlY3J1aXRtZW50IHRydW5jYXRpb24sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCBmaWcuc2hvdz0naGlkZSd9DQoNCiMgc2V0IHVwIG5ldyBSZWYgdGFibGUgZm9yIHVudHJ1bmNhdGVkIHNlcmllcw0KcmVmUHRzNSA8LSBtYXRyaXgoTkEsbnJvdz0xLG5jb2w9OSwgZGltbmFtZXM9bGlzdCgidmFsdWUiLGMoIkJ0cmlnZ2VyIiwiQnBhIiwiQmxpbSIsIjV0aFBlcmNfU1NCbXN5IiwiRnBhIiwiRmxpbSIsICJGcDA1IiwiRm1zeV91bmNvbnN0ciIsIkZtc3kiKSkpDQoNCiMga2VlcCBCbGltIGFuZCBCcGENCnJlZlB0czVbLCJCbGltIl0gPC0gbWVhbihkZltkZiR5ZWFyICVpbiUgYygyMDAyOjIwMTEpLCAiU1NCIl0pDQpyZWZQdHM1WywiQnBhIl0gIDwtcmVmUHRzWywiQmxpbSJdKmV4cCgxLjY0NSpzaWdtYVNTQikNCg0KIyBubyB0cnVuY2F0aW9uDQpybVNSUllycyA8LSAwDQoNClNlZ3JlZ0JsaW0gIDwtIGZ1bmN0aW9uKGFiLCBzc2IpIGxvZyhpZmVsc2Uoc3NiID49IHJlZlB0c1ssIkJsaW0iXSwgYWIkYSAqIHJlZlB0c1ssIkJsaW0iXSwgYWIkYSAqIHNzYikpDQoNCiMjIFJlZml0IHN0b2NrIHJlY3J1aXRtZW50IHJlbGF0aW9uc2hpcCBiYXNlZCBvbiB0cnVuY2F0ZWQgdGltZSBzZXJpZXMNCnNldC5zZWVkKDEyMykNCmVxZml0IDwtIGVxc3JfZml0KHN0ayA9IHN0aywNCiAgICAgICAgICAgICAgICAgIG5zYW1wID0gbm9TaW1zLA0KICAgICAgICAgICAgICAgICAgbW9kZWxzID0gYygiU2VncmVnQmxpbSIpLA0KICAgICAgICAgICAgICAgICAgcmVtb3ZlLnllYXJzID0gcm1TUlJZcnMpDQojIyBQbG90DQplcXNyX3Bsb3QoZXFmaXQsbj0yZTQsZ2dQbG90PVRSVUUsU2NhbGU9MWUzKQ0KDQoNCnNldC5zZWVkKDEyMykNClNJTV9TZWdyZWdCbGltX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzIDwtIGVxc2ltX3J1bihlcWZpdCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpby55ZWFycyA9IGMoKG1heFllYXItbnVtQXZnWXJzQiksIG1heFllYXIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW8uY29uc3QgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWwueWVhcnMgPSBjKChtYXhZZWFyLW51bUF2Z1lyc1MpLCBtYXhZZWFyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLmNvbnN0ID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmN2ID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnBoaSA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNTQmN2ID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmhvbG9nUmVjID0gYygwLjYpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCdHJpZ2dlciA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJsaW0gPSByZWZQdHM1WywiQmxpbSJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCcGEgPSByZWZQdHM1WywiQnBhIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5ydW4gPSBOcnVucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnNjYW4gPSBGc1RvU2NhbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UKQ0KDQp0bXAxIDwtIHQoU0lNX1NlZ3JlZ0JsaW1fbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkUmVmcykNCg0KcmVmUHRzNVssIkZsaW0iXSA8LSB0bXAxWyJGNTAiLCJjYXRGIl0NCg0KdG1wRnBhIDwtIHJlZlB0czVbLCJGcGEiXSA8LSByZWZQdHM1WywiRnAwNSJdIDwtIHRtcDFbIkYwNSIsImNhdEYiXQ0KDQppZiAodG1wRnBhPDAuMikgcmVmUHRzNVssIkZwYSJdIDwtIHJvdW5kKHRtcEZwYSwgMykgZWxzZSByZWZQdHM1WywiRnBhIl0gPC0gcm91bmQodG1wRnBhLCAyKQ0KDQpzZXQuc2VlZCgxMjMpDQpTSU1fU2VncmVnX25vVHJpZ19sb3dlclJob2hpZ2hlcm51bUF2Z1lycyA8LSBlcXNpbV9ydW4oZXFmaXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpby55ZWFycyA9IGMobWF4WWVhci1udW1BdmdZcnNCLCBtYXhZZWFyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW8uY29uc3QgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWwueWVhcnMgPSBjKG1heFllYXItbnVtQXZnWXJzUywgbWF4WWVhciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLmNvbnN0ID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRmN2PWN2RiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRnBoaT1waGlGLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNTQmN2PWN2U1NCLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJob2xvZ1JlYz1jKDAuNiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcC5zaW1zID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCdHJpZ2dlciA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgQmxpbT1yZWZQdHM1WywiQmxpbSJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJwYT1yZWZQdHM1WywiQnBhIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgTnJ1bj1OcnVucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBGc2NhbiA9IEZzVG9TY2FuLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VCkNCg0KdG1wMiA8LSB0KFNJTV9TZWdyZWdfbm9UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzJFJlZnMpDQpGbXN5X3RtcCA8LSB0bXAyWyJtZWRpYW5NU1kiLCJjYXRGIl0gI25vdGU6ICB3YXMgcHJldmlvdXNseSBsYW5kaW5ncyBGIGZvciBGbXN5LCBmcm9tIHRoZSB3cm9uZyBvdXRwdXQgKHJlZnMyIG91dHB1dCB0YWJsZXMpDQoNCnRtcEZwYSA8LSByZWZQdHM1WywiRnBhIl0gPC0gcmVmUHRzNVssIkZwMDUiXSA8LSB0bXAyWyJGMDUiLCJjYXRGIl0NCg0KDQpyZWZQdHM1WywiRm1zeV91bmNvbnN0ciJdIDwtIEZtc3lfdG1wIA0KaWYgKEZtc3lfdG1wID4gcmVmUHRzNVssIkZwYSJdKSB7DQogIHJlZlB0czVbLCJGbXN5Il0gPC0gcmVmUHRzNVssIkZwYSJdICNQSlc6IG1ha2Ugc3VyZSB0aGlzIGlzIEZwMDUNCn0gZWxzZSB7DQpyZWZQdHM1WywiRm1zeSJdIDwtIEZtc3lfdG1wDQp9DQoNCg0KZGF0YS4wNTwtU0lNX1NlZ3JlZ19ub1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkcmJwDQp4LjA1IDwtIGRhdGEuMDVbZGF0YS4wNSR2YXJpYWJsZSA9PSAiU3Bhd25pbmcgc3RvY2sgYmlvbWFzcyIsIF0kRnRhcmdldA0KYi4wNSA8LSBkYXRhLjA1W2RhdGEuMDUkdmFyaWFibGUgPT0gIlNwYXduaW5nIHN0b2NrIGJpb21hc3MiLCBdJHAwNQ0KIyBwbG90KGIuMDV+eC4wNSwgeWxhYj0iU1NCIiwgeGxhYj0iRiIpDQpiLmxtIDwtIGxvZXNzKGIuMDUgfiB4LjA1KQ0KcmVmUHRzNVssIjV0aFBlcmNfU1NCbXN5Il0gPC0gcHJlZGljdChiLmxtLCByZWZQdHM1WywiRm1zeSJdKQ0KDQoNCnJlZlB0czVbLCJCdHJpZ2dlciJdIDwtIHJlZlB0c1ssIkJwYSJdDQoNCnNldC5zZWVkKDEyMykNClNJTV9TZWdyZWdfVHJpZ19sb3dlclJob2hpZ2hlcm51bUF2Z1lycyA8LSBlcXNpbV9ydW4oZXFmaXQsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGJpby55ZWFycyA9IGMobWF4WWVhci1udW1BdmdZcnNCLCBtYXhZZWFyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYmlvLmNvbnN0ID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC55ZWFycyA9IGMobWF4WWVhci1udW1BdmdZcnNTLCBtYXhZZWFyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLmNvbnN0ID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgICAgIEZjdj1jdkYsDQogICAgICAgICAgICAgICAgICAgICAgICAgIEZwaGk9cGhpRiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgU1NCY3Y9Y3ZTU0IsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHJob2xvZ1JlYz1jKDAuNiksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXAuc2ltcyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgIEJ0cmlnZ2VyID0gcmVmUHRzNVssIkJ0cmlnZ2VyIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgIEJsaW09cmVmUHRzNVssIkJsaW0iXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgQnBhPXJlZlB0czVbLCJCcGEiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgTnJ1bj1OcnVucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgRnNjYW4gPSBGc1RvU2NhbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFKQ0KdG1wMyA8LSB0KFNJTV9TZWdyZWdfVHJpZ19sb3dlclJob2hpZ2hlcm51bUF2Z1lycyRSZWZzKQ0KcmVmUHRzNVssIkZwMDUiXSA8LSByZWZQdHM1WywiRnBhIl0gPC0gdG1wM1siRjA1IiwiY2F0RiJdICNub3RlOiBjYXRjaCBGIGZvciBGcDA1DQoNCg0KcmVmUHRzNVssIkZtc3lfdW5jb25zdHIiXSA8LSBGbXN5X3RtcCANCmlmIChGbXN5X3RtcCA+IHJlZlB0czVbLCJGcGEiXSkgew0KICByZWZQdHM1WywiRm1zeSJdIDwtIHJlZlB0czVbLCJGcGEiXQ0KfSBlbHNlIHsNCnJlZlB0czVbLCJGbXN5Il0gPC0gRm1zeV90bXANCn0NCg0KYGBgDQoNCmBgYHtyIGZpbmFsIHRhYmxlIG9mIHJlZiBwb2ludHMsIG5vIHRydW5jYXRpb259DQoNCg0KcmVmUHRzNiA8LSByZWZQdHM1WywgYygxLDIsMyw0LDUsOCw5KV0NCg0KdChyZWZQdHM2KSAlPiUNCiAgICBrYmwoYm9va3RhYnMgPSBUUlVFLCBjYXB0aW9uPSJyZWZlcmVuY2UgcG9pbnRzIGZvciBwbGUuMjcuMjEtMzIsIHVzaW5nIHRoZSBub24tdHJ1bmNhdGVkIHJlY3J1aXRtZW50IikgJT4lDQogICAga2FibGVfbWF0ZXJpYWxfZGFyaygpDQoNCg0KYGBgDQoNCg0KDQojIyBsb3dlciBSaG9Mb2dSZWMgdmFsdWUNClNlbnNpdGl2aXR5IHJ1biBhc3N1bWluZyBhIGxvd2VyIGF1dG9jb3JyZWxhdGlvbiBpbiB0aGUgcmVjcnVpdG1lbnQsIFJob0xvZ1JlYyA9IDAuMy4gQWxsIG90aGVyIHNldHRpbmdzIGFyZSBpZGVudGljYWwgdG8gdGhlIGZpbmFsIHNldHRpbmdzIG9mIHRoZSByZWZlcmVuY2UgcG9pbnQgY2FsY3VsYXRpb24gYWJvdmU6DQotIEJsaW0gYXMgYXZlcmFnZSBTU0Igb2YgdGhlIGZpcnN0IHRlbiB5ZWFycyBvZiB0aGUgdGltZSBzZXJpZXMNCi0gbGFzdCAxMCB5ZWFycyBvZiBiaW9sb2dpY2FsIGRhdGEgdXNlZCBmb3IgUyBhbmQgQiBlc3RpbWF0aW9uIGluIHRoZSByZWZlcmVuY2UgcG9pbnQgbW9kZWxzDQotIFNTUiB0aW1lIHNlcmllcyB0cnVuY2F0ZWQsIG9ubHkgdXNpbmcgdGhlIGRhdGEgYmVmb3JlIHRoZSBleGNlcHRpb25hbGx5IHN0cm9uZyBpbmNyZWFzZSBpbiAyMDE5DQoNCg0KYGBge3IgbG93ZXIgcmhvIHZhbHVlLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgZmlnLnNob3c9J2hpZGUnfQ0KcmVmUHRzNyA8LSBtYXRyaXgoTkEsbnJvdz0xLG5jb2w9OSwgZGltbmFtZXM9bGlzdCgidmFsdWUiLGMoIkJ0cmlnZ2VyIiwiQnBhIiwiQmxpbSIsIjV0aFBlcmNfU1NCbXN5IiwiRnBhIiwiRmxpbSIsICJGcDA1IiwiRm1zeV91bmNvbnN0ciIsIkZtc3kiKSkpDQoNCiMga2VlcCBCbGltIGFuZCBCcGENCnJlZlB0czdbLCJCbGltIl0gPC0gbWVhbihkZltkZiR5ZWFyICVpbiUgYygyMDAyOjIwMTEpLCAiU1NCIl0pDQpyZWZQdHM3WywiQnBhIl0gIDwtcmVmUHRzWywiQmxpbSJdKmV4cCgxLjY0NSpzaWdtYVNTQikNCg0KIyBhZGQgdHJ1bmNhdGlvbg0Kcm1TUlJZcnMgPC0gYygyMDE5Om1heFllYXIpICAjIHNwZWNpZnkgaGVyZSB3aGljaCBvdGhlciB5ZWFycyAoZS5nLiBlYXJseSBwZXJpb2QpIHNob3VsZCBiZSBsZWZ0IG91dA0KDQpTZWdyZWdCbGltICA8LSBmdW5jdGlvbihhYiwgc3NiKSBsb2coaWZlbHNlKHNzYiA+PSByZWZQdHNbLCJCbGltIl0sIGFiJGEgKiByZWZQdHNbLCJCbGltIl0sIGFiJGEgKiBzc2IpKQ0KDQojIyBSZWZpdCBzdG9jayByZWNydWl0bWVudCByZWxhdGlvbnNoaXAgYmFzZWQgb24gdHJ1bmNhdGVkIHRpbWUgc2VyaWVzDQpzZXQuc2VlZCgxMjMpDQplcWZpdCA8LSBlcXNyX2ZpdChzdGsgPSBzdGssDQogICAgICAgICAgICAgICAgICBuc2FtcCA9IG5vU2ltcywNCiAgICAgICAgICAgICAgICAgIG1vZGVscyA9IGMoIlNlZ3JlZ0JsaW0iKSwNCiAgICAgICAgICAgICAgICAgIHJlbW92ZS55ZWFycyA9IHJtU1JSWXJzKQ0KIyMgUGxvdA0KZXFzcl9wbG90KGVxZml0LG49MmU0LGdnUGxvdD1UUlVFLFNjYWxlPTFlMykNCg0KDQpzZXQuc2VlZCgxMjMpDQpTSU1fU2VncmVnQmxpbV9sb3dlclJob2hpZ2hlcm51bUF2Z1lycyA8LSBlcXNpbV9ydW4oZXFmaXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW8ueWVhcnMgPSBjKChtYXhZZWFyLW51bUF2Z1lyc0IpLCBtYXhZZWFyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlvLmNvbnN0ID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLnllYXJzID0gYygobWF4WWVhci1udW1BdmdZcnNTKSwgbWF4WWVhciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC5jb25zdCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZjdiA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZwaGkgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTU0JjdiA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJob2xvZ1JlYyA9IGMoMC4zKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQnRyaWdnZXIgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCbGltID0gcmVmUHRzN1ssIkJsaW0iXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQnBhID0gcmVmUHRzN1ssIkJwYSJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOcnVuID0gTnJ1bnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZzY2FuID0gRnNUb1NjYW4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VCkNCg0KdG1wMSA8LSB0KFNJTV9TZWdyZWdCbGltX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzJFJlZnMpDQoNCnJlZlB0czdbLCJGbGltIl0gPC0gdG1wMVsiRjUwIiwiY2F0RiJdDQoNCnRtcEZwYSA8LSByZWZQdHM3WywiRnBhIl0gPC0gcmVmUHRzN1ssIkZwMDUiXSA8LSB0bXAxWyJGMDUiLCJjYXRGIl0NCg0KaWYgKHRtcEZwYTwwLjIpIHJlZlB0czdbLCJGcGEiXSA8LSByb3VuZCh0bXBGcGEsIDMpIGVsc2UgcmVmUHRzN1ssIkZwYSJdIDwtIHJvdW5kKHRtcEZwYSwgMikNCg0Kc2V0LnNlZWQoMTIzKQ0KU0lNX1NlZ3JlZ19ub1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMgPC0gZXFzaW1fcnVuKGVxZml0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW8ueWVhcnMgPSBjKG1heFllYXItbnVtQXZnWXJzQiwgbWF4WWVhciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlvLmNvbnN0ID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLnllYXJzID0gYyhtYXhZZWFyLW51bUF2Z1lyc1MsIG1heFllYXIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC5jb25zdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZjdj1jdkYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZwaGk9cGhpRiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTU0Jjdj1jdlNTQiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByaG9sb2dSZWM9YygwLjMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXAuc2ltcyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgQnRyaWdnZXIgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJsaW09cmVmUHRzN1ssIkJsaW0iXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCcGE9cmVmUHRzN1ssIkJwYSJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5ydW49TnJ1bnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRnNjYW4gPSBGc1RvU2NhbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVQpDQoNCnRtcDIgPC0gdChTSU1fU2VncmVnX25vVHJpZ19sb3dlclJob2hpZ2hlcm51bUF2Z1lycyRSZWZzKQ0KRm1zeV90bXAgPC0gdG1wMlsibWVkaWFuTVNZIiwiY2F0RiJdICNub3RlOiAgd2FzIHByZXZpb3VzbHkgbGFuZGluZ3MgRiBmb3IgRm1zeSwgZnJvbSB0aGUgd3Jvbmcgb3V0cHV0IChyZWZzMiBvdXRwdXQgdGFibGVzKQ0KDQp0bXBGcGEgPC0gcmVmUHRzN1ssIkZwYSJdIDwtIHJlZlB0czdbLCJGcDA1Il0gPC0gdG1wMlsiRjA1IiwiY2F0RiJdDQoNCg0KcmVmUHRzN1ssIkZtc3lfdW5jb25zdHIiXSA8LSBGbXN5X3RtcCANCmlmIChGbXN5X3RtcCA+IHJlZlB0czdbLCJGcGEiXSkgew0KICByZWZQdHM3WywiRm1zeSJdIDwtIHJlZlB0czdbLCJGcGEiXSAjUEpXOiBtYWtlIHN1cmUgdGhpcyBpcyBGcDA1DQp9IGVsc2Ugew0KcmVmUHRzN1ssIkZtc3kiXSA8LSBGbXN5X3RtcA0KfQ0KDQoNCmRhdGEuMDU8LVNJTV9TZWdyZWdfbm9UcmlnX2xvd2VyUmhvaGlnaGVybnVtQXZnWXJzJHJicA0KeC4wNSA8LSBkYXRhLjA1W2RhdGEuMDUkdmFyaWFibGUgPT0gIlNwYXduaW5nIHN0b2NrIGJpb21hc3MiLCBdJEZ0YXJnZXQNCmIuMDUgPC0gZGF0YS4wNVtkYXRhLjA1JHZhcmlhYmxlID09ICJTcGF3bmluZyBzdG9jayBiaW9tYXNzIiwgXSRwMDUNCiMgcGxvdChiLjA1fnguMDUsIHlsYWI9IlNTQiIsIHhsYWI9IkYiKQ0KYi5sbSA8LSBsb2VzcyhiLjA1IH4geC4wNSkNCnJlZlB0czdbLCI1dGhQZXJjX1NTQm1zeSJdIDwtIHByZWRpY3QoYi5sbSwgcmVmUHRzN1ssIkZtc3kiXSkNCg0KDQpyZWZQdHM3WywiQnRyaWdnZXIiXSA8LSByZWZQdHNbLCJCcGEiXQ0KDQpzZXQuc2VlZCgxMjMpDQpTSU1fU2VncmVnX1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMgPC0gZXFzaW1fcnVuKGVxZml0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICBiaW8ueWVhcnMgPSBjKG1heFllYXItbnVtQXZnWXJzQiwgbWF4WWVhciksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGJpby5jb25zdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBzZWwueWVhcnMgPSBjKG1heFllYXItbnVtQXZnWXJzUywgbWF4WWVhciksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC5jb25zdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBGY3Y9Y3ZGLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBGcGhpPXBoaUYsDQogICAgICAgICAgICAgICAgICAgICAgICAgIFNTQmN2PWN2U1NCLA0KICAgICAgICAgICAgICAgICAgICAgICAgICByaG9sb2dSZWM9YygwLjMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwLnNpbXMgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBCdHJpZ2dlciA9IHJlZlB0czdbLCJCdHJpZ2dlciJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBCbGltPXJlZlB0czdbLCJCbGltIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgIEJwYT1yZWZQdHM3WywiQnBhIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgIE5ydW49TnJ1bnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgIEZzY2FuID0gRnNUb1NjYW4sDQogICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VFJVRSkNCnRtcDMgPC0gdChTSU1fU2VncmVnX1RyaWdfbG93ZXJSaG9oaWdoZXJudW1BdmdZcnMkUmVmcykNCnJlZlB0czdbLCJGcDA1Il0gPC0gcmVmUHRzN1ssIkZwYSJdIDwtIHRtcDNbIkYwNSIsImNhdEYiXSAjbm90ZTogY2F0Y2ggRiBmb3IgRnAwNQ0KDQoNCnJlZlB0czdbLCJGbXN5X3VuY29uc3RyIl0gPC0gRm1zeV90bXAgDQppZiAoRm1zeV90bXAgPiByZWZQdHM3WywiRnBhIl0pIHsNCiAgcmVmUHRzN1ssIkZtc3kiXSA8LSByZWZQdHM3WywiRnBhIl0NCn0gZWxzZSB7DQpyZWZQdHM3WywiRm1zeSJdIDwtIEZtc3lfdG1wDQp9DQoNCmBgYA0KDQoNCg0KYGBge3IgZmluYWwgdGFibGUgb2YgcmVmIHBvaW50cywgbG93ZXIgUmhvfQ0KDQoNCnJlZlB0czggPC0gcmVmUHRzN1ssIGMoMSwyLDMsNCw1LDgsOSldDQoNCnQocmVmUHRzOCkgJT4lDQogICAga2JsKGJvb2t0YWJzID0gVFJVRSwgY2FwdGlvbj0icmVmZXJlbmNlIHBvaW50cyBmb3IgcGxlLjI3LjIxLTMyLCBhc3N1bWluZyBSaG9Mb2dSZWMgPSAwLjMiKSAlPiUNCiAgICBrYWJsZV9tYXRlcmlhbF9kYXJrKCkNCg0KYGBgDQoNCg0KDQoNCg0KDQoNCg==