Packages

Loading relevant packages:

library(lme4) # Hierarchical models
library(stargazer) # Regression tables
library(dplyr) # Data wrangling and pipes
library(ggplot2) # Graphics
library(ggeffects) # ggpredict

Data

Loading the relevant data:

load('/Users/davidhamad/Documents/Cand.Scient.Pol/2. Semester/Statistical models beyond linear regression - applied statistics for political scientists/6-7) Logistic regression/Data.rda')

df <- Reappointments

Exercise 1

Q1: Replicate model 2.

A1: I have replicated both models.

mod1 <- glm(exit ~ free_economy_diff 
            + performance,
            family = binomial(link = "logit"),
            df)
mod2 <- glm(exit ~ free_economy_diff 
           + performance
           + age
           + tenure
           + attendance
           + court,
           family = binomial(link = "logit"), 
           df)
stargazer(mod1, mod2, type = "text")

==============================================
                      Dependent variable:     
                  ----------------------------
                              exit            
                       (1)            (2)     
----------------------------------------------
free_economy_diff    1.505***      1.490***   
                     (0.386)        (0.443)   
                                              
performance           -0.184        -0.556*   
                     (0.272)        (0.307)   
                                              
age                                0.132***   
                                    (0.027)   
                                              
tenure                               0.045    
                                    (0.036)   
                                              
attendance                          -0.015*   
                                    (0.009)   
                                              
courtGC                             0.809**   
                                    (0.376)   
                                              
Constant            -1.383***      -9.746***  
                     (0.308)        (1.759)   
                                              
----------------------------------------------
Observations           250            235     
Log Likelihood       -137.610      -110.922   
Akaike Inf. Crit.    281.220        235.844   
==============================================
Note:              *p<0.1; **p<0.05; ***p<0.01

Q2: What is the marginal effect of a one-unit increase in the following predictors on the probab the probability that a judge is replaced (exit == 1)? Ideology: free_economy_diff. Past performance/influence: performance

A2: The coefficient for free_economy_diff is positive (1.490) and highly significant (p < 0.01), indicating that greater political distance between appointing and reappointing governments increases the likelihood of a judge being replaced. The coefficient for performance is negative (-0.556) and weakly significant (p < 0.1), suggesting that higher-performing judges are somewhat less likely to be replaced.

A one-unit increase in political distance (free_economy_diff) multiplies the odds of a judge being replaced by a factor of 4.4. A one-unit increase in judge performance reduces the odds of replacement by approximately 43%.

coefficients(mod2)[2] * 1
free_economy_diff 
         1.489554 
exp(1.490)
[1] 4.437096
coefficients(mod2)[3] * 1
performance 
 -0.5558463 
exp(-0.556)
[1] 0.5734985
(exp(-0.556) - 1) * 100
[1] -42.65015

Q3: What would you say is a good increment for a “high-performing” judge? Can you make a partial scenario and report the marginal effect of judges’ performance on governments’ decision to replace a judge?

A3: The interquartile range (the difference between Q3 and Q1 –> Q3 - Q1) of performance (≈ 0.38) represents a reasonable increment for comparing a low-performing to a high-performing judge. Moving from Q1 to Q3 in performance reduces the odds of being replaced by approximately 19%. While this is a meaningful relative effect, it is considerably smaller than the effect of political distance, suggesting that merit offers some protection, but ideology matters more.

change_perf <- IQR(df$performance, na.rm = TRUE)
change_perf
[1] 0.3779062
coefficients(mod2)["performance"] * change_perf
performance 
 -0.2100578 
exp(coefficients(mod2)["performance"] * change_perf)
performance 
  0.8105374 
(exp(coefficients(mod2)["performance"] * change_perf) - 1) * 100
performance 
  -18.94626 

Q4: Can you illustrate the two effects graphically?

A4: Illustration is seen below.

eff_ideology <- ggpredict(mod2, terms = "free_economy_diff[all]")
plot(eff_ideology) +
  ylab("Probability of replacing the judge") +
  xlab("Political distance between governments") +
  ggtitle("Effect of political distance on judge replacement")


eff_performance <- ggpredict(mod2, terms = "performance[all]")
plot(eff_performance) +
  ylab("Probability of replacing the judge") +
  xlab("Judge performance (relative to court average)") +
  ggtitle("Effect of performance on judge replacement")


Q5: What is the marginal effect of a left-right overturn in government during a judge’s mandate on their probability of being replaced? To find a good increment, draw on the descriptive statistics.

A5: When a left-wing government replaces a right-wing one (or vice versa), the odds that the incumbent judge is replaced more than double (a 126% increase in odds), suggesting that political turnover has substantial consequences for judicial tenure at the CJEU.

df %>%
  group_by(family_id, family_id_ren) %>%
  reframe(
    n = n(),
    mean_dist = mean(free_economy_diff, na.rm = TRUE),
    median_dist = median(free_economy_diff, na.rm = TRUE)
  )
left_right_shift <- df %>%
  filter(
    (family_id == "Social democracy" & family_id_ren == "Conservative") |
    (family_id == "Conservative" & family_id_ren == "Social democracy")
  )
left_right_shift %>%
  group_by(family_id, family_id_ren) %>%
  reframe(
    n = n(),
    median_dist = median(free_economy_diff, na.rm = TRUE)
  )
left_right_shift %>%
  reframe(
    n = n(),
    mean_dist = mean(free_economy_diff, na.rm = TRUE),
    median_dist = median(free_economy_diff, na.rm = TRUE)
  )
change <- median(left_right_shift$free_economy_diff, na.rm = TRUE)
change
[1] 0.5485304
coefficients(mod2)["free_economy_diff"] * change
free_economy_diff 
        0.8170654 
exp(coefficients(mod2)["free_economy_diff"] * change)
free_economy_diff 
         2.263847 
(exp(coefficients(mod2)["free_economy_diff"] * change) - 1) * 100
free_economy_diff 
         126.3847 

Q6: Calculate the first difference: Consider four scenarios and compare the predicted probabilities that a judge exits the Court for high and low levels of both performance and political distance.

  1. what are the predicted probabilities for the two groups?
  2. What is the effect of ideology among high-performing judges?
  3. What is the effect among low-performing judges?
  4. Who stands the most to win by performing better?

A6: See the text below.

  1. Predicted probabilities for the four scenarios: A low-performing judge (Q1 = 0.71) facing a politically aligned government (Q1 = 0.07) has a 13.9% probability of being replaced. The same judge facing a politically distant government (Q3 = 0.46) has a 22.4% probability. A high-performing judge (Q3 = 1.09) facing an aligned government has an 11.6% probability of exit, rising to 19.0% when facing a distant government.

  2. Effect of ideology among high-performing judges: Among high-performing judges, moving from low to high political distance increases the probability of exit by 7.4 percentage points (from 11.6% to 19.0%).

  3. Effect of ideology among low-performing judges: Among low-performing judges, the same shift in political distance increases the probability of exit by 8.5 percentage points (from 13.9% to 22.4%). The effect of ideology is thus somewhat larger for low-performing judges, illustrating the built-in interaction effect in the logistic model.

  4. Who stands the most to win by performing better? Judges facing politically distant governments benefit the most from higher performance: their probability of exit drops by 3.4 percentage points (from 22.4% to 19.0%), compared to 2.3 percentage points for judges facing aligned governments (from 13.9% to 11.6%). Politically exposed judges thus have the most to gain from strong performance, though the protection it offers remains modest.

summary(df$free_economy_diff)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
0.00000 0.07139 0.24067 0.34545 0.46069 2.58621      17 
summary(df$performance)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
 0.0000  0.7144  0.9745  0.9251  1.0923  3.8537       1 
scenarios <- data.frame(
  free_economy_diff = rep(
    quantile(df$free_economy_diff, probs = c(0.25, 0.75), na.rm = TRUE), 
    2),
  performance = c(
    rep(quantile(df$performance, probs = 0.25, na.rm = TRUE), 2),
    rep(quantile(df$performance, probs = 0.75, na.rm = TRUE), 2)
  ),
  age = median(df$age),
  tenure = 6,
  attendance = 0,
  court = "CJ"
)
scenarios
scenarios <- scenarios %>%
  mutate(
    preds = predict(mod2, scenarios, type = "response")
  )
scenarios
scenarios <- scenarios %>%
  group_by(performance) %>%
  mutate(
    effect_ideology = preds - lag(preds)
  )
scenarios
scenarios <- scenarios %>%
  group_by(free_economy_diff) %>%
  mutate(
    effect_performance = preds - lag(preds)
  )
scenarios

Q7: Explore the compensation threshold: How much better must a judge perform to compensate for a median political distance in government preferences (i.e. free_economy_diff == 0.24)? Given the distribution of performance, how realistic is it for judges to survive based on merit alone?

A7: The compensation equation gives us: performance = -(β₁/β₂) × free_economy_diff = 0.64. This means a judge must increase their performance by 0.64 units to fully offset a median level of political distance. Given that the interquartile range of performance is only about 0.38 (from 0.71 to 1.09), a compensating increase of 0.64 far exceeds the variation we typically observe among judges. It is therefore unrealistic for most judges to survive based on merit alone when facing even a moderate level of political misalignment.

beta1 <- coefficients(mod2)["free_economy_diff"]
beta2 <- coefficients(mod2)["performance"]
compensation <- -(beta1/beta2) * 0.24
compensation
free_economy_diff 
        0.6431506 
summary(df$performance)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
 0.0000  0.7144  0.9745  0.9251  1.0923  3.8537       1 

Exercise 2

Q1: Calculate the probability, then the odds, then the logodds that a judge will exit (exit).

A1: To calculate the intercept of an intercept-only logistic regression, we work through the logit transformation step by step. In the data, 75 judges exited the court (successes) and 193 remained (failures). The probability of exit is therefore 75/268 = 0.280. The odds of exit are 75/193 = 0.389; meaning that for roughly every judge who exits, about 2.6 remain (193/75 = 2.57). Taking the natural logarithm of the odds gives us the log-odds: log(0.389) = -0.945. This value corresponds exactly to the intercept in an intercept-only logistic regression, confirming that the intercept simply represents the overall log-odds of the event in the data when no predictors are included.

successes <- sum(df$exit == 1)
successes
[1] 75
failures <- sum(df$exit == 0)
failures
[1] 193
p <- successes / (successes + failures)
p
[1] 0.2798507
odds <- successes / failures
odds
[1] 0.388601
logodds <- log(odds)
logodds
[1] -0.9452021

Q2: Run a binomial regression with only an intercept.

A2: See below.

mod0 <- glm(exit ~ 1,
            family = "binomial",
            df)
summary(mod0)

Call:
glm(formula = exit ~ 1, family = "binomial", data = df)

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  -0.9452     0.1361  -6.947 3.74e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 317.75  on 267  degrees of freedom
Residual deviance: 317.75  on 267  degrees of freedom
AIC: 319.75

Number of Fisher Scoring iterations: 4

Exercise 3

Q1: Calculate the odds of exiting the court among young and old judges

A1: Among young judges (under 60), 23 exited the court and 109 remained, giving odds of 23/109 = 0.211. Among older judges (60+), 52 exited and 84 remained, giving odds of 52/84 = 0.619. The odds of exiting are thus roughly three times higher for older judges than for younger ones, consistent with the expectation that older judges are more likely to leave: whether voluntarily (retirement) or because governments see an opportunity to appoint a replacement.

successes_young <- sum(df$exit[df$age60 == 0] == 1)
successes_young
[1] 23
failures_young <- sum(df$exit[df$age60 == 0] == 0)
failures_young
[1] 109
odds_young <- successes_young / failures_young
odds_young
[1] 0.2110092
successes_old <- sum(df$exit[df$age60 == 1] == 1)
successes_old
[1] 52
failures_old <- sum(df$exit[df$age60 == 1] == 0)
failures_old
[1] 84
odds_old <- successes_old / failures_old
odds_old
[1] 0.6190476

Q2: Calculate the intercept.

A2: See below.

alpha <- log(odds_young)
alpha
[1] -1.555854

Q3: Calculate the slope parameter.

A3: See below.

odds_ratio <- odds_old / odds_young
odds_ratio
[1] 2.933747
beta <- log(odds_ratio)
beta
[1] 1.076281

Q4: Run the model in R and compare. Did you find the same thing?

A4: Yes.

mod3 <- glm(exit ~
age60,
family = "binomial",
df)
summary(mod3)

Call:
glm(formula = exit ~ age60, family = "binomial", data = df)

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  -1.5559     0.2295  -6.780  1.2e-11 ***
age60         1.0763     0.2895   3.718 0.000201 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 317.75  on 267  degrees of freedom
Residual deviance: 303.05  on 266  degrees of freedom
AIC: 307.05

Number of Fisher Scoring iterations: 4
LS0tCnRpdGxlOiAiTG9naXN0aWMgcmVncmVzc2lvbiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge2NzcywgZWNobz1GQUxTRX0KYm9keXt0ZXh0LWFsaWduOiBKdXN0aWZ5O30KaDEudGl0bGUge2JvcmRlci1ib3R0b206IDNweCBzb2xpZCBibGFjazsgcGFkZGluZy1ib3R0b206IDEwcHg7fQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQpzZXR3ZCgnL1VzZXJzL2RhdmlkaGFtYWQvRG9jdW1lbnRzL0NhbmQuU2NpZW50LlBvbC8yLiBTZW1lc3Rlci9TdGF0aXN0aWNhbCBtb2RlbHMgYmV5b25kIGxpbmVhciByZWdyZXNzaW9uIC0gYXBwbGllZCBzdGF0aXN0aWNzIGZvciBwb2xpdGljYWwgc2NpZW50aXN0cy82LTcpIExvZ2lzdGljIHJlZ3Jlc3Npb24nKQpgYGAKCiMjIyBQYWNrYWdlcwpMb2FkaW5nIHJlbGV2YW50IHBhY2thZ2VzOgoKYGBge3J9CmxpYnJhcnkobG1lNCkgIyBIaWVyYXJjaGljYWwgbW9kZWxzCmxpYnJhcnkoc3RhcmdhemVyKSAjIFJlZ3Jlc3Npb24gdGFibGVzCmxpYnJhcnkoZHBseXIpICMgRGF0YSB3cmFuZ2xpbmcgYW5kIHBpcGVzCmxpYnJhcnkoZ2dwbG90MikgIyBHcmFwaGljcwpsaWJyYXJ5KGdnZWZmZWN0cykgIyBnZ3ByZWRpY3QKYGBgCgotLS0KCiMjIyBEYXRhCkxvYWRpbmcgdGhlIHJlbGV2YW50IGRhdGE6CgpgYGB7cn0KbG9hZCgnL1VzZXJzL2RhdmlkaGFtYWQvRG9jdW1lbnRzL0NhbmQuU2NpZW50LlBvbC8yLiBTZW1lc3Rlci9TdGF0aXN0aWNhbCBtb2RlbHMgYmV5b25kIGxpbmVhciByZWdyZXNzaW9uIC0gYXBwbGllZCBzdGF0aXN0aWNzIGZvciBwb2xpdGljYWwgc2NpZW50aXN0cy82LTcpIExvZ2lzdGljIHJlZ3Jlc3Npb24vRGF0YS5yZGEnKQoKZGYgPC0gUmVhcHBvaW50bWVudHMKYGBgCgotLS0KCiMjIyBFeGVyY2lzZSAxCioqUTE6KiogUmVwbGljYXRlIG1vZGVsIDIuCgoqKkExOioqIEkgaGF2ZSByZXBsaWNhdGVkIGJvdGggbW9kZWxzLgoKYGBge3J9Cm1vZDEgPC0gZ2xtKGV4aXQgfiBmcmVlX2Vjb25vbXlfZGlmZiAKICAgICAgICAgICAgKyBwZXJmb3JtYW5jZSwKICAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpLAogICAgICAgICAgICBkZikKYGBgCgoKYGBge3J9Cm1vZDIgPC0gZ2xtKGV4aXQgfiBmcmVlX2Vjb25vbXlfZGlmZiAKICAgICAgICAgICArIHBlcmZvcm1hbmNlCiAgICAgICAgICAgKyBhZ2UKICAgICAgICAgICArIHRlbnVyZQogICAgICAgICAgICsgYXR0ZW5kYW5jZQogICAgICAgICAgICsgY291cnQsCiAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpLCAKICAgICAgICAgICBkZikKYGBgCgpgYGB7cn0Kc3RhcmdhemVyKG1vZDEsIG1vZDIsIHR5cGUgPSAidGV4dCIpCmBgYAoKLS0tCgoqKlEyOioqIFdoYXQgaXMgdGhlIG1hcmdpbmFsIGVmZmVjdCBvZiBhIG9uZS11bml0IGluY3JlYXNlIGluIHRoZSBmb2xsb3dpbmcgcHJlZGljdG9ycyBvbiB0aGUgcHJvYmFiIHRoZQpwcm9iYWJpbGl0eSB0aGF0IGEganVkZ2UgaXMgcmVwbGFjZWQgKGV4aXQgPT0gMSk/IElkZW9sb2d5OiBmcmVlX2Vjb25vbXlfZGlmZi4gUGFzdCBwZXJmb3JtYW5jZS9pbmZsdWVuY2U6IHBlcmZvcm1hbmNlCgoqKkEyOioqIFRoZSBjb2VmZmljaWVudCBmb3IgZnJlZV9lY29ub215X2RpZmYgaXMgcG9zaXRpdmUgKDEuNDkwKSBhbmQgaGlnaGx5IHNpZ25pZmljYW50IChwIDwgMC4wMSksIGluZGljYXRpbmcgdGhhdCBncmVhdGVyIHBvbGl0aWNhbCBkaXN0YW5jZSBiZXR3ZWVuIGFwcG9pbnRpbmcgYW5kIHJlYXBwb2ludGluZyBnb3Zlcm5tZW50cyBpbmNyZWFzZXMgdGhlIGxpa2VsaWhvb2Qgb2YgYSBqdWRnZSBiZWluZyByZXBsYWNlZC4gVGhlIGNvZWZmaWNpZW50IGZvciBwZXJmb3JtYW5jZSBpcyBuZWdhdGl2ZSAoLTAuNTU2KSBhbmQgd2Vha2x5IHNpZ25pZmljYW50IChwIDwgMC4xKSwgc3VnZ2VzdGluZyB0aGF0IGhpZ2hlci1wZXJmb3JtaW5nIGp1ZGdlcyBhcmUgc29tZXdoYXQgbGVzcyBsaWtlbHkgdG8gYmUgcmVwbGFjZWQuCgpBIG9uZS11bml0IGluY3JlYXNlIGluIHBvbGl0aWNhbCBkaXN0YW5jZSAoZnJlZV9lY29ub215X2RpZmYpIG11bHRpcGxpZXMgdGhlIG9kZHMgb2YgYSBqdWRnZSBiZWluZyByZXBsYWNlZCBieSBhIGZhY3RvciBvZiA0LjQuIEEgb25lLXVuaXQgaW5jcmVhc2UgaW4ganVkZ2UgcGVyZm9ybWFuY2UgcmVkdWNlcyB0aGUgb2RkcyBvZiByZXBsYWNlbWVudCBieSBhcHByb3hpbWF0ZWx5IDQzJS4KCmBgYHtyfQpjb2VmZmljaWVudHMobW9kMilbMl0gKiAxCmBgYAoKYGBge3J9CmV4cCgxLjQ5MCkKYGBgCgpgYGB7cn0KY29lZmZpY2llbnRzKG1vZDIpWzNdICogMQpgYGAKCmBgYHtyfQpleHAoLTAuNTU2KQpgYGAKCmBgYHtyfQooZXhwKC0wLjU1NikgLSAxKSAqIDEwMApgYGAKCi0tLQoKKipRMzoqKiBXaGF0IHdvdWxkIHlvdSBzYXkgaXMgYSBnb29kIGluY3JlbWVudCBmb3IgYSDigJxoaWdoLXBlcmZvcm1pbmfigJ0ganVkZ2U/IENhbiB5b3UgbWFrZSBhIHBhcnRpYWwgc2NlbmFyaW8gYW5kIHJlcG9ydCB0aGUgbWFyZ2luYWwgZWZmZWN0IG9mIGp1ZGdlc+KAmSBwZXJmb3JtYW5jZSBvbiBnb3Zlcm5tZW50c+KAmSBkZWNpc2lvbiB0byByZXBsYWNlIGEganVkZ2U/CgoqKkEzOioqIFRoZSBpbnRlcnF1YXJ0aWxlIHJhbmdlICh0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIFEzIGFuZCBRMSAtLT4gUTMgLSBRMSkgb2YgcGVyZm9ybWFuY2UgKOKJiCAwLjM4KSByZXByZXNlbnRzIGEgcmVhc29uYWJsZSBpbmNyZW1lbnQgZm9yIGNvbXBhcmluZyBhIGxvdy1wZXJmb3JtaW5nIHRvIGEgaGlnaC1wZXJmb3JtaW5nIGp1ZGdlLiBNb3ZpbmcgZnJvbSBRMSB0byBRMyBpbiBwZXJmb3JtYW5jZSByZWR1Y2VzIHRoZSBvZGRzIG9mIGJlaW5nIHJlcGxhY2VkIGJ5IGFwcHJveGltYXRlbHkgMTklLiBXaGlsZSB0aGlzIGlzIGEgbWVhbmluZ2Z1bCByZWxhdGl2ZSBlZmZlY3QsIGl0IGlzIGNvbnNpZGVyYWJseSBzbWFsbGVyIHRoYW4gdGhlIGVmZmVjdCBvZiBwb2xpdGljYWwgZGlzdGFuY2UsIHN1Z2dlc3RpbmcgdGhhdCBtZXJpdCBvZmZlcnMgc29tZSBwcm90ZWN0aW9uLCBidXQgaWRlb2xvZ3kgbWF0dGVycyBtb3JlLgoKYGBge3J9CmNoYW5nZV9wZXJmIDwtIElRUihkZiRwZXJmb3JtYW5jZSwgbmEucm0gPSBUUlVFKQpjaGFuZ2VfcGVyZgpgYGAKCmBgYHtyfQpjb2VmZmljaWVudHMobW9kMilbInBlcmZvcm1hbmNlIl0gKiBjaGFuZ2VfcGVyZgpgYGAKCmBgYHtyfQpleHAoY29lZmZpY2llbnRzKG1vZDIpWyJwZXJmb3JtYW5jZSJdICogY2hhbmdlX3BlcmYpCmBgYAoKYGBge3J9CihleHAoY29lZmZpY2llbnRzKG1vZDIpWyJwZXJmb3JtYW5jZSJdICogY2hhbmdlX3BlcmYpIC0gMSkgKiAxMDAKYGBgCgotLS0KCioqUTQ6KiogQ2FuIHlvdSBpbGx1c3RyYXRlIHRoZSB0d28gZWZmZWN0cyBncmFwaGljYWxseT8KCioqQTQ6KiogSWxsdXN0cmF0aW9uIGlzIHNlZW4gYmVsb3cuCgpgYGB7cn0KZWZmX2lkZW9sb2d5IDwtIGdncHJlZGljdChtb2QyLCB0ZXJtcyA9ICJmcmVlX2Vjb25vbXlfZGlmZlthbGxdIikKcGxvdChlZmZfaWRlb2xvZ3kpICsKICB5bGFiKCJQcm9iYWJpbGl0eSBvZiByZXBsYWNpbmcgdGhlIGp1ZGdlIikgKwogIHhsYWIoIlBvbGl0aWNhbCBkaXN0YW5jZSBiZXR3ZWVuIGdvdmVybm1lbnRzIikgKwogIGdndGl0bGUoIkVmZmVjdCBvZiBwb2xpdGljYWwgZGlzdGFuY2Ugb24ganVkZ2UgcmVwbGFjZW1lbnQiKQoKZWZmX3BlcmZvcm1hbmNlIDwtIGdncHJlZGljdChtb2QyLCB0ZXJtcyA9ICJwZXJmb3JtYW5jZVthbGxdIikKcGxvdChlZmZfcGVyZm9ybWFuY2UpICsKICB5bGFiKCJQcm9iYWJpbGl0eSBvZiByZXBsYWNpbmcgdGhlIGp1ZGdlIikgKwogIHhsYWIoIkp1ZGdlIHBlcmZvcm1hbmNlIChyZWxhdGl2ZSB0byBjb3VydCBhdmVyYWdlKSIpICsKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgcGVyZm9ybWFuY2Ugb24ganVkZ2UgcmVwbGFjZW1lbnQiKQpgYGAKCi0tLQoKKipRNToqKiBXaGF0IGlzIHRoZSBtYXJnaW5hbCBlZmZlY3Qgb2YgYSBsZWZ0LXJpZ2h0IG92ZXJ0dXJuIGluIGdvdmVybm1lbnQgZHVyaW5nIGEganVkZ2XigJlzIG1hbmRhdGUgb24gdGhlaXIKcHJvYmFiaWxpdHkgb2YgYmVpbmcgcmVwbGFjZWQ/IFRvIGZpbmQgYSBnb29kIGluY3JlbWVudCwgZHJhdyBvbiB0aGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcy4KCioqQTU6KiogV2hlbiBhIGxlZnQtd2luZyBnb3Zlcm5tZW50IHJlcGxhY2VzIGEgcmlnaHQtd2luZyBvbmUgKG9yIHZpY2UgdmVyc2EpLCB0aGUgb2RkcyB0aGF0IHRoZSBpbmN1bWJlbnQganVkZ2UgaXMgcmVwbGFjZWQgbW9yZSB0aGFuIGRvdWJsZSAoYSAxMjYlIGluY3JlYXNlIGluIG9kZHMpLCBzdWdnZXN0aW5nIHRoYXQgcG9saXRpY2FsIHR1cm5vdmVyIGhhcyBzdWJzdGFudGlhbCBjb25zZXF1ZW5jZXMgZm9yIGp1ZGljaWFsIHRlbnVyZSBhdCB0aGUgQ0pFVS4KCmBgYHtyfQpkZiAlPiUKICBncm91cF9ieShmYW1pbHlfaWQsIGZhbWlseV9pZF9yZW4pICU+JQogIHJlZnJhbWUoCiAgICBuID0gbigpLAogICAgbWVhbl9kaXN0ID0gbWVhbihmcmVlX2Vjb25vbXlfZGlmZiwgbmEucm0gPSBUUlVFKSwKICAgIG1lZGlhbl9kaXN0ID0gbWVkaWFuKGZyZWVfZWNvbm9teV9kaWZmLCBuYS5ybSA9IFRSVUUpCiAgKQpgYGAKCmBgYHtyfQpsZWZ0X3JpZ2h0X3NoaWZ0IDwtIGRmICU+JQogIGZpbHRlcigKICAgIChmYW1pbHlfaWQgPT0gIlNvY2lhbCBkZW1vY3JhY3kiICYgZmFtaWx5X2lkX3JlbiA9PSAiQ29uc2VydmF0aXZlIikgfAogICAgKGZhbWlseV9pZCA9PSAiQ29uc2VydmF0aXZlIiAmIGZhbWlseV9pZF9yZW4gPT0gIlNvY2lhbCBkZW1vY3JhY3kiKQogICkKYGBgCgpgYGB7cn0KbGVmdF9yaWdodF9zaGlmdCAlPiUKICBncm91cF9ieShmYW1pbHlfaWQsIGZhbWlseV9pZF9yZW4pICU+JQogIHJlZnJhbWUoCiAgICBuID0gbigpLAogICAgbWVkaWFuX2Rpc3QgPSBtZWRpYW4oZnJlZV9lY29ub215X2RpZmYsIG5hLnJtID0gVFJVRSkKICApCmBgYAoKYGBge3J9CmxlZnRfcmlnaHRfc2hpZnQgJT4lCiAgcmVmcmFtZSgKICAgIG4gPSBuKCksCiAgICBtZWFuX2Rpc3QgPSBtZWFuKGZyZWVfZWNvbm9teV9kaWZmLCBuYS5ybSA9IFRSVUUpLAogICAgbWVkaWFuX2Rpc3QgPSBtZWRpYW4oZnJlZV9lY29ub215X2RpZmYsIG5hLnJtID0gVFJVRSkKICApCmBgYAoKYGBge3J9CmNoYW5nZSA8LSBtZWRpYW4obGVmdF9yaWdodF9zaGlmdCRmcmVlX2Vjb25vbXlfZGlmZiwgbmEucm0gPSBUUlVFKQpjaGFuZ2UKYGBgCgpgYGB7cn0KY29lZmZpY2llbnRzKG1vZDIpWyJmcmVlX2Vjb25vbXlfZGlmZiJdICogY2hhbmdlCmBgYAoKYGBge3J9CmV4cChjb2VmZmljaWVudHMobW9kMilbImZyZWVfZWNvbm9teV9kaWZmIl0gKiBjaGFuZ2UpCmBgYAoKYGBge3J9CihleHAoY29lZmZpY2llbnRzKG1vZDIpWyJmcmVlX2Vjb25vbXlfZGlmZiJdICogY2hhbmdlKSAtIDEpICogMTAwCmBgYAoKLS0tCgoqKlE2OioqIENhbGN1bGF0ZSB0aGUgZmlyc3QgZGlmZmVyZW5jZTogQ29uc2lkZXIgZm91ciBzY2VuYXJpb3MgYW5kIGNvbXBhcmUgdGhlIHByZWRpY3RlZCBwcm9iYWJpbGl0aWVzIHRoYXQgYQpqdWRnZSBleGl0cyB0aGUgQ291cnQgZm9yIGhpZ2ggYW5kIGxvdyBsZXZlbHMgb2YgYm90aCBwZXJmb3JtYW5jZSBhbmQgcG9saXRpY2FsIGRpc3RhbmNlLiAKCjEpIHdoYXQgYXJlIHRoZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdGllcyBmb3IgdGhlIHR3byBncm91cHM/IAoyKSBXaGF0IGlzIHRoZSBlZmZlY3Qgb2YgaWRlb2xvZ3kgYW1vbmcgaGlnaC1wZXJmb3JtaW5nIGp1ZGdlcz8gCjMpIFdoYXQgaXMgdGhlIGVmZmVjdCBhbW9uZyBsb3ctcGVyZm9ybWluZyBqdWRnZXM/CjQpIFdobyBzdGFuZHMgdGhlIG1vc3QgdG8gd2luIGJ5IHBlcmZvcm1pbmcgYmV0dGVyPwoKKipBNjoqKiBTZWUgdGhlIHRleHQgYmVsb3cuCgoxKSBQcmVkaWN0ZWQgcHJvYmFiaWxpdGllcyBmb3IgdGhlIGZvdXIgc2NlbmFyaW9zOiBBIGxvdy1wZXJmb3JtaW5nIGp1ZGdlIChRMSA9IDAuNzEpIGZhY2luZyBhIHBvbGl0aWNhbGx5IGFsaWduZWQgZ292ZXJubWVudCAoUTEgPSAwLjA3KSBoYXMgYSAxMy45JSBwcm9iYWJpbGl0eSBvZiBiZWluZyByZXBsYWNlZC4gVGhlIHNhbWUganVkZ2UgZmFjaW5nIGEgcG9saXRpY2FsbHkgZGlzdGFudCBnb3Zlcm5tZW50IChRMyA9IDAuNDYpIGhhcyBhIDIyLjQlIHByb2JhYmlsaXR5LiBBIGhpZ2gtcGVyZm9ybWluZyBqdWRnZSAoUTMgPSAxLjA5KSBmYWNpbmcgYW4gYWxpZ25lZCBnb3Zlcm5tZW50IGhhcyBhbiAxMS42JSBwcm9iYWJpbGl0eSBvZiBleGl0LCByaXNpbmcgdG8gMTkuMCUgd2hlbiBmYWNpbmcgYSBkaXN0YW50IGdvdmVybm1lbnQuCgoyKSBFZmZlY3Qgb2YgaWRlb2xvZ3kgYW1vbmcgaGlnaC1wZXJmb3JtaW5nIGp1ZGdlczogQW1vbmcgaGlnaC1wZXJmb3JtaW5nIGp1ZGdlcywgbW92aW5nIGZyb20gbG93IHRvIGhpZ2ggcG9saXRpY2FsIGRpc3RhbmNlIGluY3JlYXNlcyB0aGUgcHJvYmFiaWxpdHkgb2YgZXhpdCBieSA3LjQgcGVyY2VudGFnZSBwb2ludHMgKGZyb20gMTEuNiUgdG8gMTkuMCUpLgoKMykgRWZmZWN0IG9mIGlkZW9sb2d5IGFtb25nIGxvdy1wZXJmb3JtaW5nIGp1ZGdlczogQW1vbmcgbG93LXBlcmZvcm1pbmcganVkZ2VzLCB0aGUgc2FtZSBzaGlmdCBpbiBwb2xpdGljYWwgZGlzdGFuY2UgaW5jcmVhc2VzIHRoZSBwcm9iYWJpbGl0eSBvZiBleGl0IGJ5IDguNSBwZXJjZW50YWdlIHBvaW50cyAoZnJvbSAxMy45JSB0byAyMi40JSkuIFRoZSBlZmZlY3Qgb2YgaWRlb2xvZ3kgaXMgdGh1cyBzb21ld2hhdCBsYXJnZXIgZm9yIGxvdy1wZXJmb3JtaW5nIGp1ZGdlcywgaWxsdXN0cmF0aW5nIHRoZSBidWlsdC1pbiBpbnRlcmFjdGlvbiBlZmZlY3QgaW4gdGhlIGxvZ2lzdGljIG1vZGVsLgoKNCkgV2hvIHN0YW5kcyB0aGUgbW9zdCB0byB3aW4gYnkgcGVyZm9ybWluZyBiZXR0ZXI/IEp1ZGdlcyBmYWNpbmcgcG9saXRpY2FsbHkgZGlzdGFudCBnb3Zlcm5tZW50cyBiZW5lZml0IHRoZSBtb3N0IGZyb20gaGlnaGVyIHBlcmZvcm1hbmNlOiB0aGVpciBwcm9iYWJpbGl0eSBvZiBleGl0IGRyb3BzIGJ5IDMuNCBwZXJjZW50YWdlIHBvaW50cyAoZnJvbSAyMi40JSB0byAxOS4wJSksIGNvbXBhcmVkIHRvIDIuMyBwZXJjZW50YWdlIHBvaW50cyBmb3IganVkZ2VzIGZhY2luZyBhbGlnbmVkIGdvdmVybm1lbnRzIChmcm9tIDEzLjklIHRvIDExLjYlKS4gUG9saXRpY2FsbHkgZXhwb3NlZCBqdWRnZXMgdGh1cyBoYXZlIHRoZSBtb3N0IHRvIGdhaW4gZnJvbSBzdHJvbmcgcGVyZm9ybWFuY2UsIHRob3VnaCB0aGUgcHJvdGVjdGlvbiBpdCBvZmZlcnMgcmVtYWlucyBtb2Rlc3QuCgpgYGB7cn0Kc3VtbWFyeShkZiRmcmVlX2Vjb25vbXlfZGlmZikKYGBgCgpgYGB7cn0Kc3VtbWFyeShkZiRwZXJmb3JtYW5jZSkKYGBgCgpgYGB7cn0Kc2NlbmFyaW9zIDwtIGRhdGEuZnJhbWUoCiAgZnJlZV9lY29ub215X2RpZmYgPSByZXAoCiAgICBxdWFudGlsZShkZiRmcmVlX2Vjb25vbXlfZGlmZiwgcHJvYnMgPSBjKDAuMjUsIDAuNzUpLCBuYS5ybSA9IFRSVUUpLCAKICAgIDIpLAogIHBlcmZvcm1hbmNlID0gYygKICAgIHJlcChxdWFudGlsZShkZiRwZXJmb3JtYW5jZSwgcHJvYnMgPSAwLjI1LCBuYS5ybSA9IFRSVUUpLCAyKSwKICAgIHJlcChxdWFudGlsZShkZiRwZXJmb3JtYW5jZSwgcHJvYnMgPSAwLjc1LCBuYS5ybSA9IFRSVUUpLCAyKQogICksCiAgYWdlID0gbWVkaWFuKGRmJGFnZSksCiAgdGVudXJlID0gNiwKICBhdHRlbmRhbmNlID0gMCwKICBjb3VydCA9ICJDSiIKKQpgYGAKCmBgYHtyfQpzY2VuYXJpb3MKYGBgCgpgYGB7cn0Kc2NlbmFyaW9zIDwtIHNjZW5hcmlvcyAlPiUKICBtdXRhdGUoCiAgICBwcmVkcyA9IHByZWRpY3QobW9kMiwgc2NlbmFyaW9zLCB0eXBlID0gInJlc3BvbnNlIikKICApCmBgYAoKYGBge3J9CnNjZW5hcmlvcwpgYGAKCmBgYHtyfQpzY2VuYXJpb3MgPC0gc2NlbmFyaW9zICU+JQogIGdyb3VwX2J5KHBlcmZvcm1hbmNlKSAlPiUKICBtdXRhdGUoCiAgICBlZmZlY3RfaWRlb2xvZ3kgPSBwcmVkcyAtIGxhZyhwcmVkcykKICApCmBgYAoKYGBge3J9CnNjZW5hcmlvcwpgYGAKCmBgYHtyfQpzY2VuYXJpb3MgPC0gc2NlbmFyaW9zICU+JQogIGdyb3VwX2J5KGZyZWVfZWNvbm9teV9kaWZmKSAlPiUKICBtdXRhdGUoCiAgICBlZmZlY3RfcGVyZm9ybWFuY2UgPSBwcmVkcyAtIGxhZyhwcmVkcykKICApCmBgYAoKYGBge3J9CnNjZW5hcmlvcwpgYGAKCi0tLQoKKipRNzoqKiBFeHBsb3JlIHRoZSBjb21wZW5zYXRpb24gdGhyZXNob2xkOiBIb3cgbXVjaCBiZXR0ZXIgbXVzdCBhIGp1ZGdlIHBlcmZvcm0gdG8gY29tcGVuc2F0ZSBmb3IgYQptZWRpYW4gcG9saXRpY2FsIGRpc3RhbmNlIGluIGdvdmVybm1lbnQgcHJlZmVyZW5jZXMgKGkuZS4gZnJlZV9lY29ub215X2RpZmYgPT0gMC4yNCk/IEdpdmVuIHRoZSBkaXN0cmlidXRpb24gb2YgcGVyZm9ybWFuY2UsIGhvdyByZWFsaXN0aWMgaXMgaXQgZm9yIGp1ZGdlcyB0byBzdXJ2aXZlIGJhc2VkIG9uIG1lcml0IGFsb25lPwoKKipBNzoqKiBUaGUgY29tcGVuc2F0aW9uIGVxdWF0aW9uIGdpdmVzIHVzOiBwZXJmb3JtYW5jZSA9IC0ozrLigoEvzrLigoIpIMOXIGZyZWVfZWNvbm9teV9kaWZmID0gMC42NC4gVGhpcyBtZWFucyBhIGp1ZGdlIG11c3QgaW5jcmVhc2UgdGhlaXIgcGVyZm9ybWFuY2UgYnkgMC42NCB1bml0cyB0byBmdWxseSBvZmZzZXQgYSBtZWRpYW4gbGV2ZWwgb2YgcG9saXRpY2FsIGRpc3RhbmNlLiBHaXZlbiB0aGF0IHRoZSBpbnRlcnF1YXJ0aWxlIHJhbmdlIG9mIHBlcmZvcm1hbmNlIGlzIG9ubHkgYWJvdXQgMC4zOCAoZnJvbSAwLjcxIHRvIDEuMDkpLCBhIGNvbXBlbnNhdGluZyBpbmNyZWFzZSBvZiAwLjY0IGZhciBleGNlZWRzIHRoZSB2YXJpYXRpb24gd2UgdHlwaWNhbGx5IG9ic2VydmUgYW1vbmcganVkZ2VzLiBJdCBpcyB0aGVyZWZvcmUgdW5yZWFsaXN0aWMgZm9yIG1vc3QganVkZ2VzIHRvIHN1cnZpdmUgYmFzZWQgb24gbWVyaXQgYWxvbmUgd2hlbiBmYWNpbmcgZXZlbiBhIG1vZGVyYXRlIGxldmVsIG9mIHBvbGl0aWNhbCBtaXNhbGlnbm1lbnQuCgpgYGB7cn0KYmV0YTEgPC0gY29lZmZpY2llbnRzKG1vZDIpWyJmcmVlX2Vjb25vbXlfZGlmZiJdCmBgYAoKYGBge3J9CmJldGEyIDwtIGNvZWZmaWNpZW50cyhtb2QyKVsicGVyZm9ybWFuY2UiXQpgYGAKCmBgYHtyfQpjb21wZW5zYXRpb24gPC0gLShiZXRhMS9iZXRhMikgKiAwLjI0CmBgYAoKYGBge3J9CmNvbXBlbnNhdGlvbgpgYGAKCmBgYHtyfQpzdW1tYXJ5KGRmJHBlcmZvcm1hbmNlKQpgYGAKCi0tLQoKIyMjIEV4ZXJjaXNlIDIKKipRMToqKiBDYWxjdWxhdGUgdGhlIHByb2JhYmlsaXR5LCB0aGVuIHRoZSBvZGRzLCB0aGVuIHRoZSBsb2dvZGRzIHRoYXQgYSBqdWRnZSB3aWxsIGV4aXQgKGV4aXQpLiAKCioqQTE6KiogVG8gY2FsY3VsYXRlIHRoZSBpbnRlcmNlcHQgb2YgYW4gaW50ZXJjZXB0LW9ubHkgbG9naXN0aWMgcmVncmVzc2lvbiwgd2Ugd29yayB0aHJvdWdoIHRoZSBsb2dpdCB0cmFuc2Zvcm1hdGlvbiBzdGVwIGJ5IHN0ZXAuIEluIHRoZSBkYXRhLCA3NSBqdWRnZXMgZXhpdGVkIHRoZSBjb3VydCAoc3VjY2Vzc2VzKSBhbmQgMTkzIHJlbWFpbmVkIChmYWlsdXJlcykuIFRoZSBwcm9iYWJpbGl0eSBvZiBleGl0IGlzIHRoZXJlZm9yZSA3NS8yNjggPSAwLjI4MC4gVGhlIG9kZHMgb2YgZXhpdCBhcmUgNzUvMTkzID0gMC4zODk7IG1lYW5pbmcgdGhhdCBmb3Igcm91Z2hseSBldmVyeSBqdWRnZSB3aG8gZXhpdHMsIGFib3V0IDIuNiByZW1haW4gKDE5My83NSA9IDIuNTcpLiBUYWtpbmcgdGhlIG5hdHVyYWwgbG9nYXJpdGhtIG9mIHRoZSBvZGRzIGdpdmVzIHVzIHRoZSBsb2ctb2RkczogbG9nKDAuMzg5KSA9IC0wLjk0NS4gVGhpcyB2YWx1ZSBjb3JyZXNwb25kcyBleGFjdGx5IHRvIHRoZSBpbnRlcmNlcHQgaW4gYW4gaW50ZXJjZXB0LW9ubHkgbG9naXN0aWMgcmVncmVzc2lvbiwgY29uZmlybWluZyB0aGF0IHRoZSBpbnRlcmNlcHQgc2ltcGx5IHJlcHJlc2VudHMgdGhlIG92ZXJhbGwgbG9nLW9kZHMgb2YgdGhlIGV2ZW50IGluIHRoZSBkYXRhIHdoZW4gbm8gcHJlZGljdG9ycyBhcmUgaW5jbHVkZWQuCgpgYGB7cn0Kc3VjY2Vzc2VzIDwtIHN1bShkZiRleGl0ID09IDEpCnN1Y2Nlc3NlcwpgYGAKCmBgYHtyfQpmYWlsdXJlcyA8LSBzdW0oZGYkZXhpdCA9PSAwKQpmYWlsdXJlcwpgYGAKCmBgYHtyfQpwIDwtIHN1Y2Nlc3NlcyAvIChzdWNjZXNzZXMgKyBmYWlsdXJlcykKcApgYGAKCmBgYHtyfQpvZGRzIDwtIHN1Y2Nlc3NlcyAvIGZhaWx1cmVzCm9kZHMKYGBgCgpgYGB7cn0KbG9nb2RkcyA8LSBsb2cob2RkcykKbG9nb2RkcwpgYGAKCi0tLQoKKipRMjoqKiBSdW4gYSBiaW5vbWlhbCByZWdyZXNzaW9uIHdpdGggb25seSBhbiBpbnRlcmNlcHQuCgoqKkEyOioqIFNlZSBiZWxvdy4KCmBgYHtyfQptb2QwIDwtIGdsbShleGl0IH4gMSwKICAgICAgICAgICAgZmFtaWx5ID0gImJpbm9taWFsIiwKICAgICAgICAgICAgZGYpCmBgYAoKYGBge3J9CnN1bW1hcnkobW9kMCkKYGBgCgotLS0KCiMjIyBFeGVyY2lzZSAzCioqUTE6KiogQ2FsY3VsYXRlIHRoZSBvZGRzIG9mIGV4aXRpbmcgdGhlIGNvdXJ0IGFtb25nIHlvdW5nIGFuZCBvbGQganVkZ2VzCgoqKkExOioqIEFtb25nIHlvdW5nIGp1ZGdlcyAodW5kZXIgNjApLCAyMyBleGl0ZWQgdGhlIGNvdXJ0IGFuZCAxMDkgcmVtYWluZWQsIGdpdmluZyBvZGRzIG9mIDIzLzEwOSA9IDAuMjExLiBBbW9uZyBvbGRlciBqdWRnZXMgKDYwKyksIDUyIGV4aXRlZCBhbmQgODQgcmVtYWluZWQsIGdpdmluZyBvZGRzIG9mIDUyLzg0ID0gMC42MTkuIFRoZSBvZGRzIG9mIGV4aXRpbmcgYXJlIHRodXMgcm91Z2hseSB0aHJlZSB0aW1lcyBoaWdoZXIgZm9yIG9sZGVyIGp1ZGdlcyB0aGFuIGZvciB5b3VuZ2VyIG9uZXMsIGNvbnNpc3RlbnQgd2l0aCB0aGUgZXhwZWN0YXRpb24gdGhhdCBvbGRlciBqdWRnZXMgYXJlIG1vcmUgbGlrZWx5IHRvIGxlYXZlOiB3aGV0aGVyIHZvbHVudGFyaWx5IChyZXRpcmVtZW50KSBvciBiZWNhdXNlIGdvdmVybm1lbnRzIHNlZSBhbiBvcHBvcnR1bml0eSB0byBhcHBvaW50IGEgcmVwbGFjZW1lbnQuCgpgYGB7cn0Kc3VjY2Vzc2VzX3lvdW5nIDwtIHN1bShkZiRleGl0W2RmJGFnZTYwID09IDBdID09IDEpCnN1Y2Nlc3Nlc195b3VuZwpgYGAKCmBgYHtyfQpmYWlsdXJlc195b3VuZyA8LSBzdW0oZGYkZXhpdFtkZiRhZ2U2MCA9PSAwXSA9PSAwKQpmYWlsdXJlc195b3VuZwpgYGAKCmBgYHtyfQpvZGRzX3lvdW5nIDwtIHN1Y2Nlc3Nlc195b3VuZyAvIGZhaWx1cmVzX3lvdW5nCm9kZHNfeW91bmcKYGBgCgpgYGB7cn0Kc3VjY2Vzc2VzX29sZCA8LSBzdW0oZGYkZXhpdFtkZiRhZ2U2MCA9PSAxXSA9PSAxKQpzdWNjZXNzZXNfb2xkCmBgYAoKYGBge3J9CmZhaWx1cmVzX29sZCA8LSBzdW0oZGYkZXhpdFtkZiRhZ2U2MCA9PSAxXSA9PSAwKQpmYWlsdXJlc19vbGQKYGBgCgpgYGB7cn0Kb2Rkc19vbGQgPC0gc3VjY2Vzc2VzX29sZCAvIGZhaWx1cmVzX29sZApvZGRzX29sZApgYGAKCi0tLQoKKipRMjoqKiBDYWxjdWxhdGUgdGhlIGludGVyY2VwdC4KCioqQTI6KiogU2VlIGJlbG93LgoKYGBge3J9CmFscGhhIDwtIGxvZyhvZGRzX3lvdW5nKQphbHBoYQpgYGAKCi0tLQoKKipRMzoqKiBDYWxjdWxhdGUgdGhlIHNsb3BlIHBhcmFtZXRlci4KCioqQTM6KiogU2VlIGJlbG93LgoKYGBge3J9Cm9kZHNfcmF0aW8gPC0gb2Rkc19vbGQgLyBvZGRzX3lvdW5nCm9kZHNfcmF0aW8KYGBgCgpgYGB7cn0KYmV0YSA8LSBsb2cob2Rkc19yYXRpbykKYmV0YQpgYGAKCi0tLQoKKipRNDoqKiBSdW4gdGhlIG1vZGVsIGluIFIgYW5kIGNvbXBhcmUuIERpZCB5b3UgZmluZCB0aGUgc2FtZSB0aGluZz8KCioqQTQ6KiogWWVzLgoKYGBge3J9Cm1vZDMgPC0gZ2xtKGV4aXQgfgphZ2U2MCwKZmFtaWx5ID0gImJpbm9taWFsIiwKZGYpCmBgYAoKYGBge3J9CnN1bW1hcnkobW9kMykKYGBg