Questions

Question 1: Does method of fungal exposure affect TTD?
Question 2: Does pathogen exposure type influence space use?
Question 3: Does pathogen exposure type influence fragmentation?

Load libraries and data

#Stegodyphus-metarhizium analysis
####Load Libraries####
library(conflicted) # Conflicted functions
library(tidyverse) # Data carpentry
library(ggfortify) # plot survival curve
library(survival) # survival analysis
library(survminer) # plot survival
library(coxme) # proportional hazards model
library(emmeans) # Estimated marginal means
library(glmmTMB) # Another generalized linear mixed effects model package
library(DHARMa) # checking regression assumptions
library(ggstatsplot) # Chi Squared
library(rstatix) # Chi squared pairwise comparisons

# Fixed conflicted functions
conflicted::conflicts_prefer(dplyr::filter)
[conflicted] Removing existing preference.
[conflicted] Will prefer dplyr::filter over any other package.
conflicted::conflicts_prefer(dplyr::select)
[conflicted] Removing existing preference.
[conflicted] Will prefer dplyr::select over any other package.
####Load csv files from R project folder####
survival <- read.csv("data/ttd_2.csv")
location <- read.csv("data/exposure_location.csv") # 4=out and 5=dead
pilot <- read.csv("data/survival_pilot_2020.csv")

Body Condition

Calculate body condition

#Calculate SMI from Parthasarathy et al. 2018
SMI <- function(mass, prosoma){
  cw_bar <- mean(prosoma, na.rm=T)
  m <- lm(prosoma ~ mass)
  slope <- summary(m)[[4]][2]
  cor <- cor(mass, prosoma)
  
  smi <- mass*(cw_bar/prosoma)^(slope/cor)
  return(smi)
}

#Combine SMI vector with body size dataframe
smi <- SMI(survival$initial_mass, survival$initial_prosoma_width);survival <- cbind(survival, SMI=smi)

##Q0: Pilot study

Question 1: Does fungal exposure affect Time To Death (TTD)?

Model: Cox Proportional hazards model

Dependent Variable: TTD

Independent Variable:
(1) Treatment

Random Effect:
(1) Colony ID
(2) Spider age (juvenile or adult)

Run Cox model and polt survival curve

#### Q0: Analyze individual mortality with a proportional hazards mixed model####
# Cox model containing mixed (random and fixed) effects
# [ttdfit0]Average ttd when S. dumicola exposed to M. robertsii
ttdfit0 <- coxme(Surv(TTD) ~ treatment + (1|colony.ID) + (1|age), data = pilot)

print(ttdfit0)
Cox mixed-effects model fit by maximum likelihood
  Data: pilot
  events, n = 49, 49 (1 observation deleted due to missingness)
  Iterations= 6 34 
                    NULL Integrated  Fitted
Log-likelihood -144.5657  -129.7258 -128.01

                  Chisq   df          p   AIC   BIC
Integrated loglik 29.68 3.00 1.6115e-06 23.68 18.00
 Penalized loglik 33.11 1.92 5.5979e-08 29.28 25.65

Model:  Surv(TTD) ~ treatment + (1 | colony.ID) + (1 | age) 
Fixed coefficients
               coef exp(coef)  se(coef)    z     p
treatmentE 2.066782  7.899364 0.4224541 4.89 1e-06

Random effects
 Group     Variable  Std Dev      Variance    
 colony.ID Intercept 0.0197955955 0.0003918656
 age       Intercept 0.9273314196 0.8599435617
# Fit to model without random effects for plot
fit <- survfit(Surv(TTD) ~ treatment, data = pilot)

# Plot pilot survival curve
ggsurvplot(fit, data = pilot, size = 1, palette = c("#2E9FDF", "darkolivegreen3"), 
           risk.table = FALSE, 
           conf.int = TRUE,
           pval = TRUE,legend.labs = c("Control", "Exposed"),
           ggtheme = theme(panel.grid.major = element_blank(),
                           panel.grid.minor = element_blank(),
                           panel.background = element_blank(),
                           axis.line = element_line(colour ="black"),
           text = element_text(size=15)))


ggsave("figures/pilot_surv_curve.png")
Saving 7.29 x 4.51 in image

##Q1: Survival

Question 1: Does method of fungal exposure affect Time To Death (TTD)?

Model: Cox Proportional hazards model

Dependent Variable: TTD

Independent Variable:
(1) Treatment (2) SMI

Random Effect:
(1) Colony ID
(2) Block

Run Cox model

Raw data

#### Q1: Analyze individual mortality with a proportional hazards mixed model####
# Cox model containing mixed (random and fixed) effects
# [ttdfit1]Average ttd when S. dumicola exposed to M. robertsii
ttdfit1 <- coxme(Surv(ttd_2, censor) ~ treatment + SMI + (1|colony_id) + (1|block) + (1|source_retreat), data = survival)

print(ttdfit1)
Cox mixed-effects model fit by maximum likelihood
  Data: survival
  events, n = 74, 140
  Iterations= 9 58 
                    NULL Integrated    Fitted
Log-likelihood -341.6881  -291.3376 -275.7682

                   Chisq    df p   AIC   BIC
Integrated loglik 100.70  7.00 0  86.7 70.57
 Penalized loglik 131.84 14.92 0 102.0 67.62

Model:  Surv(ttd_2, censor) ~ treatment + SMI + (1 | colony_id) + (1 |      block) + (1 | source_retreat) 
Fixed coefficients
                         coef   exp(coef)    se(coef)     z       p
treatmentcricket  3.773037240  43.5120208 1.088314428  3.47 5.3e-04
treatmentpaper    2.982937042  19.7457256 1.096389045  2.72 6.5e-03
treatmentspider   5.063165038 158.0900864 1.089922271  4.65 3.4e-06
SMI              -0.002033213   0.9979689 0.005245269 -0.39 7.0e-01

Random effects
 Group          Variable  Std Dev      Variance    
 colony_id      Intercept 0.6835888057 0.4672936553
 block          Intercept 0.0199795322 0.0003991817
 source_retreat Intercept 0.0199861315 0.0003994455
# Pairwise comparisons for original data
pairwise_original <- pairwise_survdiff(Surv(ttd_2, censor) ~ treatment, data = survival)
print(pairwise_original)

    Pairwise comparisons using Log-Rank test 

data:  survival and treatment 

        control cricket paper  
cricket 7.0e-08 -       -      
paper   4.8e-05 0.031   -      
spider  1.4e-15 1.7e-05 8.3e-10

P value adjustment method: BH 

No primary cases

#### Re-analyze individual immunity with a proportional hazards mixed model with primary cases removed####
# Remove primary cases from curve
survival_no_primary <- filter(survival, primary_case=="n", died_before_meta == "n")

# Cox model containing mixed (random and fixed) effects
# [ttdfit3]Average ttd when Stegos exposed to metarhizium without primary cases
ttdfit2 <- coxme(Surv(ttd_2, censor) ~ treatment + SMI + (1|colony_id) + (1|block) + (1|source_retreat), data = survival_no_primary)
print(ttdfit2)
Cox mixed-effects model fit by maximum likelihood
  Data: survival_no_primary
  events, n = 66, 132
  Iterations= 9 58 
                    NULL Integrated    Fitted
Log-likelihood -302.3586  -257.5749 -241.6802

                   Chisq    df          p   AIC   BIC
Integrated loglik  89.57  7.00 1.1102e-16 75.57 60.24
 Penalized loglik 121.36 15.12 0.0000e+00 91.12 58.02

Model:  Surv(ttd_2, censor) ~ treatment + SMI + (1 | colony_id) + (1 |      block) + (1 | source_retreat) 
Fixed coefficients
                          coef  exp(coef)    se(coef)     z       p
treatmentcricket  3.8187701525  45.548157 1.097666555  3.48 5.0e-04
treatmentpaper    2.9400010268  18.915866 1.107455271  2.65 7.9e-03
treatmentspider   5.0157183003 150.764392 1.103419060  4.55 5.5e-06
SMI              -0.0009024413   0.999098 0.005537331 -0.16 8.7e-01

Random effects
 Group          Variable  Std Dev      Variance    
 colony_id      Intercept 0.7314800247 0.5350630266
 block          Intercept 0.0199960245 0.0003998410
 source_retreat Intercept 0.0199965029 0.0003998601
# Pairwise comparisons with no primaries
pairwise_no_primary <- pairwise_survdiff(Surv(ttd_2, censor) ~ treatment, data = survival_no_primary)
print(pairwise_no_primary)

    Pairwise comparisons using Log-Rank test 

data:  survival_no_primary and treatment 

        control cricket paper
cricket 7e-08   -       -    
paper   0.00010 0.01857 -    
spider  2e-14   0.00026 5e-09

P value adjustment method: BH 

Plot survival

Raw data

#### Plot Survival curve ####
# Filter out spiders that died before metarhizium exposure
surv <- survival %>% 
  filter(died_before_meta == "n")

# Fit to model without random effects for plot
fit <- survfit(Surv(ttd_2, censor) ~ treatment, data = surv)

# Plot with primary cases
plot_primary <- ggsurvplot(fit, data = surv, size = 1, palette = c("#2E9FDF", "orange4", "bisque3", "darkgreen"), 
                           risk.table = FALSE, 
                           conf.int = TRUE,
                           pval = FALSE,
                           legend.title = "Treatment",
                           legend.labs = c("Control", "Cricket", "Paper", "Spider"),
                           xlim = c(0, 30),
                           xlab = "Days",
                           ggtheme = theme(panel.grid.major = element_blank(),
                                           panel.grid.minor = element_blank(),
                                           panel.background = element_blank(),
                                           axis.line = element_line(colour ="black"),
                                           text = element_text(size=23)))

# Change x-axis scale to intervals of 5 days and add significance letters
plot_primary$plot <- plot_primary$plot + 
  scale_x_continuous(breaks = seq(0, 30, by = 5)) +
  annotate("text",
           x = 29, y = 0.98,
           label = "a", size = 7) +
  annotate("text",
           x = 29, y = 0.56,
           label = "b", size = 7) +
  annotate("text",
           x = 29, y = 0.3,
           label = "c", size = 7) +
  annotate("text",
           x = 29, y = 0.04,
           label = "d", size = 7)
Scale for x is already present.
Adding another scale for x, which will replace the existing scale.
# View plot
plot_primary


# Save plot to figures folder
ggsave("figures/surv_curve.png", width = 9, height = 6, units = "in")

Polt with no primary cases

# Fit to model without primary cases and random effects for plot
fit2 <- survfit(Surv(ttd_2, censor) ~ treatment, data = survival_no_primary)

# Plot without primary cases
plot_no_primary <- ggsurvplot(fit2, data = survival_no_primary, size = 1, palette = c("#2E9FDF", "orange4", "bisque3", "darkgreen"), 
                              risk.table = FALSE, 
                              conf.int = TRUE,
                              pval = FALSE,
                              legend.title = "Treatment",
                              legend.labs = c("Control", "Cricket", "Paper", "Spider"),
                              xlim = c(0, 30),
                              xlab = "Days",
                              ggtheme = theme(panel.grid.major = element_blank(),
                                              panel.grid.minor = element_blank(),
                                              panel.background = element_blank(),
                                              axis.line = element_line(colour ="black"),
                                              text = element_text(size=18)))

# Change x-axis scale to intervals of 7 days
plot_no_primary$plot <- plot_no_primary$plot + 
  scale_x_continuous(breaks = seq(0, 30, by = 5)) +
  annotate("text",
           x = 29, y = 0.98,
           label = "a", size = 6) +
  annotate("text",
           x = 29, y = 0.56,
           label = "b", size = 6) +
  annotate("text",
           x = 29, y = 0.3,
           label = "c", size = 6) +
  annotate("text",
           x = 29, y = 0.04,
           label = "d", size = 6)
Scale for x is already present.
Adding another scale for x, which will replace the existing scale.
# View plot
print(plot_no_primary)


# Save plot to figures folder
ggsave("figures/surv_curve_no_primary.png", width = 9, height = 6, units = "in")

##Q2: Space use

Question 2: Does pathogen exposure affect the proportion of time individuals spend inside vs outside their nest?

Model: GLMM

Dependent Variable: Proportion of time individuals spent inside nest

Independent Variable:
(1) Treatment

Random Effect:
(1) Colony ID
(2) Block

Wrangle TTD data

#### Q2: Pathogen exposure space use analysis ####
# Apply the pivot_longer() function to reshape the data
location_long <- location %>% 
  pivot_longer(cols = contains("location"), # Select columns containing "location"
               names_to = "spider_id", # Name for the new column with spider IDs 
               values_to = "location") # Name for the new column with location

# Filter rows by unique 'colony_id'
filtered_survival <- survival %>%
  distinct(colony_id, .keep_all = TRUE)

# Merge the datasets by 'colony_id'
merged_location <- location_long %>%
  left_join(dplyr::select(filtered_survival, colony_id, treatment), by = "colony_id") %>%
  filter(location != "5") %>%
  unite(subject_id, spider_id, colony_id, sep = "_", remove = FALSE) %>% 
  filter(subject_id != "yellow_location_13")

# Merge location and ttd data
merged_location_ttd <- merged_location %>%
  left_join(survival[,c("subject_id","ttd_2", "primary_case", "source_retreat", "censor")], by = c("subject_id"="subject_id"))

# Calculate the count of individuals at each location
location_in <- merged_location_ttd %>%
  filter(location < 4, date >= "2023-06-08") %>% 
  group_by(date, subject_id) %>%
  mutate(Count = n()) %>% 
  ungroup() %>%
  group_by(subject_id) %>%
  mutate(sumCount = sum(Count)/ttd_2) %>% 
  ungroup() %>% 
  filter(!duplicated(subject_id))

# Calculate summary statistics for space use by treatment
summary_space_use_stats <- location_in %>%
  group_by(treatment.y) %>%
  summarise(mean = mean(sumCount),
            median = median(sumCount),
            sd = sd(sumCount),
            min = min(sumCount),
            max = max(sumCount))

# Print the summary statistics
print(summary_space_use_stats)

Run GLMM

# Distribution of space use by treatment
ggplot(data = location_in) +
  geom_histogram(aes(x = sumCount, fill = treatment.y), bins = 10, color = "black") +
  scale_fill_manual(values = c("#2E9FDF", "orange4", "bisque3", "darkgreen")) +
  facet_wrap(~ treatment.y) 


# Fit a GLMM
space_glmm <- glmmTMB(sumCount ~ treatment.y + (1 | block) + (1 | colony_id) + (1|source_retreat), data = location_in)

# Display model summary
summary(space_glmm)
 Family: gaussian  ( identity )
Formula:          sumCount ~ treatment.y + (1 | block) + (1 | colony_id) + (1 |      source_retreat)
Data: location_in

     AIC      BIC   logLik deviance df.resid 
  -354.6   -331.1    185.3   -370.6      131 

Random effects:

Conditional model:
 Groups         Name        Variance  Std.Dev.
 block          (Intercept) 1.437e-05 0.003791
 colony_id      (Intercept) 1.132e-03 0.033648
 source_retreat (Intercept) 1.969e-04 0.014034
 Residual                   3.271e-03 0.057191
Number of obs: 139, groups:  block, 7; colony_id, 28; source_retreat, 4

Dispersion estimate for gaussian family (sigma^2): 0.00327 

Conditional model:
                   Estimate Std. Error z value Pr(>|z|)    
(Intercept)         0.99095    0.01761   56.27  < 2e-16 ***
treatment.ycricket -0.03434    0.02281   -1.51    0.132    
treatment.ypaper   -0.03045    0.02286   -1.33    0.183    
treatment.yspider  -0.13275    0.02259   -5.88 4.21e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Inside: Check your model / regression assumptions
plot(simulateResiduals(space_glmm))

testDispersion(simulateResiduals(space_glmm))

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 1.0213, p-value = 0.8
alternative hypothesis: two.sided

# Test significance
# Use type III sums of squares
Anova(space_glmm, type=3)
Analysis of Deviance Table (Type III Wald chisquare tests)

Response: sumCount
               Chisq Df Pr(>Chisq)    
(Intercept) 3165.958  1  < 2.2e-16 ***
treatment.y   38.904  3  1.818e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Posthoc Tukey
# Extract least squares means
pairs(emmeans(space_glmm, specs="treatment.y", type="response"))
 contrast          estimate     SE  df t.ratio p.value
 control - cricket  0.03434 0.0228 131   1.506  0.4370
 control - paper    0.03045 0.0229 131   1.332  0.5443
 control - spider   0.13275 0.0226 131   5.876  <.0001
 cricket - paper   -0.00389 0.0227 131  -0.172  0.9982
 cricket - spider   0.09841 0.0228 131   4.315  0.0002
 paper - spider     0.10230 0.0229 131   4.475  0.0001

P value adjustment: tukey method for comparing a family of 4 estimates 

Plot space use

All spiders

# Plot with raw data
raw_proportions <- ggplot(location_in, aes(x = factor(treatment.y, levels = c("control", "paper", "cricket", "spider")), y = sumCount, color = treatment.y, fill = treatment.y,
                                           shape = as.character(censor))) +
  geom_jitter(size = 2.75, width = 0.35, alpha = 0.5) +
  ylim(0.4,1.05) +
  stat_summary(fun = mean, size = 1.15, shape = 21, color = "black") + 
  stat_summary(aes(x = factor(treatment.y, levels = c("control", "paper", "cricket", "spider")), 
                    y = sumCount, color = treatment.y, color = treatment.y),
                geom="errorbar", width = 0.2, size = 1.25, inherit.aes = F) +
  scale_color_manual(values = c("#2E9FDF", "orange4", "bisque3", "darkgreen")) +
  scale_fill_manual(values = c("#2E9FDF", "orange4", "bisque3", "darkgreen")) +
  guides(color = "none") +
  labs(x = "Treatment", y = "Proportion of days inside nest", color = "", fill = "Treatments") +
  scale_x_discrete(labels=c("Control", "Paper", "Cricket", "Spider")) +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_blank(),
        axis.line = element_line(colour ="black"),
        text = element_text(size=23), legend.position = "none")
Warning: Duplicated aesthetics after name standardisation: colour
raw_proportions +
  annotate("text", x = unique(location_in$treatment.y), 
           y = rep(max(location_in$sumCount) + 0.04,length(unique(location_in$treatment.y))),
           label = c("a", "a", "a", "b"), color = "black", size = 7)
No summary function supplied, defaulting to `mean_se()`
Warning: Removed 4 rows containing missing values (`geom_segment()`).
ggsave("figures/space_use.png", width = 9, height = 6, units = "in")
No summary function supplied, defaulting to `mean_se()`
Warning: Removed 4 rows containing missing values (`geom_segment()`).

Only dead spiders

# Plot with raw data on only spiders that died
# Filter out living spiders
location_in_dead <- location_in %>% 
  filter(ttd_2 < 28)

# Plot
raw_proportions_dead <- ggplot(location_in_dead, aes(x = factor(treatment.y, 
                                                                levels = c("control", "paper", "cricket", "spider")), 
                                                     y = sumCount, color = treatment.y, fill = treatment.y)) +
  geom_jitter(width = 0.25, alpha = 0.5) +
  stat_summary(fun = mean, size = 1, shape = 21, color = "black") + 
  stat_summary(geom="errorbar", width = 0.2, size = 1.25) +
  scale_color_manual(values = c("#2E9FDF", "orange4", "bisque3", "darkgreen")) +
  scale_fill_manual(values = c("#2E9FDF", "orange4", "bisque3", "darkgreen")) +
  guides(color = "none") +
  labs(x = "Treatment", y = "Proportion of days inside nest", color = "", fill = "Treatments") +
  scale_x_discrete(labels=c("Control", "Paper", "Cricket", "Spider")) +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_blank(),
        axis.line = element_line(colour ="black"),
        text = element_text(size=18), legend.position = "none")

raw_proportions_dead +
  annotate("text", x = unique(location_in$treatment.y), 
           y = rep(max(location_in$sumCount) + 0.04,length(unique(location_in$treatment.y))),
           label = c("a", "a", "a", "b"), color = "black", size = 6)
No summary function supplied, defaulting to `mean_se()`
Warning: Removed 4 rows containing missing values (`geom_segment()`).
ggsave("figures/space_use_dead.png", width = 9, height = 6, units = "in")
No summary function supplied, defaulting to `mean_se()`
Warning: Removed 4 rows containing missing values (`geom_segment()`).

##Q3: Polydomy

Question 3: Does pathogen exposure mode influence the construction of new nests?

Model: Logistic regression/Chi squared

Dependent Variable: Polydomy y/n

Independent Variable:
(1) treatment

Wrangle data

#### Polydomy Analysis ####
# Filter out just last day of data
location_last <- location %>% 
  filter(date == "2023-07-06") %>% 
  dplyr::select(poly, treatment)

# Convert variables to factors
location_last$poly <- as.factor(location_last$poly)
location_last$treatment <- as.factor(location_last$treatment)

Run chi squared

# Chi squared comparing between treatments
contingency_table <- table(location_last$poly, location_last$treatment)

chi <- chisq.test(contingency_table)
Warning in chisq.test(contingency_table) :
  Chi-squared approximation may be incorrect
print(chi)

    Pearson's Chi-squared test

data:  contingency_table
X-squared = 3.1111, df = 3, p-value = 0.3748
ggplot(location_last, aes(treatment, fill = poly)) +
  geom_bar(colour="black", position = "fill") +
  scale_fill_manual(values = c("lightblue", "darkblue"),
                    labels = c("Monodomous", "Polydomous"),
                    name = "Fragmentation") +
  ylab("Proportion") +
  xlab("Treatment") +
  scale_x_discrete(labels=c("Control", "Cricket", "Paper", "Spider")) +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_blank(),
        axis.line = element_line(colour ="black"),
        text = element_text(size=15),
        legend.position = "top")


ggsave("figures/polydomy_treatment.png", width = 5, height = 5, units = "in")

LS0tCnRpdGxlOiAiUGF0aG9nZW4gRXhwb3N1cmUgQW5hbHlzaXMiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KPHAgc3R5bGU9ImZvbnQtc2l6ZToxNnB0Ij4KIyMgUXVlc3Rpb25zCjwvcD4KClF1ZXN0aW9uIDE6IERvZXMgbWV0aG9kIG9mIGZ1bmdhbCBleHBvc3VyZSBhZmZlY3QgVFREPyA8YnIgLz4KUXVlc3Rpb24gMjogRG9lcyBwYXRob2dlbiBleHBvc3VyZSB0eXBlIGluZmx1ZW5jZSBzcGFjZSB1c2U/IDxiciAvPgpRdWVzdGlvbiAzOiBEb2VzIHBhdGhvZ2VuIGV4cG9zdXJlIHR5cGUgaW5mbHVlbmNlIGZyYWdtZW50YXRpb24/IDxiciAvPgoKIyMjIyBMb2FkIGxpYnJhcmllcyBhbmQgZGF0YQpgYGB7cn0KI1N0ZWdvZHlwaHVzLW1ldGFyaGl6aXVtIGFuYWx5c2lzCiMjIyNMb2FkIExpYnJhcmllcyMjIyMKbGlicmFyeShjb25mbGljdGVkKSAjIENvbmZsaWN0ZWQgZnVuY3Rpb25zCmxpYnJhcnkodGlkeXZlcnNlKSAjIERhdGEgY2FycGVudHJ5CmxpYnJhcnkoZ2dmb3J0aWZ5KSAjIHBsb3Qgc3Vydml2YWwgY3VydmUKbGlicmFyeShzdXJ2aXZhbCkgIyBzdXJ2aXZhbCBhbmFseXNpcwpsaWJyYXJ5KHN1cnZtaW5lcikgIyBwbG90IHN1cnZpdmFsCmxpYnJhcnkoY294bWUpICMgcHJvcG9ydGlvbmFsIGhhemFyZHMgbW9kZWwKbGlicmFyeShlbW1lYW5zKSAjIEVzdGltYXRlZCBtYXJnaW5hbCBtZWFucwpsaWJyYXJ5KGdsbW1UTUIpICMgQW5vdGhlciBnZW5lcmFsaXplZCBsaW5lYXIgbWl4ZWQgZWZmZWN0cyBtb2RlbCBwYWNrYWdlCmxpYnJhcnkoREhBUk1hKSAjIGNoZWNraW5nIHJlZ3Jlc3Npb24gYXNzdW1wdGlvbnMKbGlicmFyeShnZ3N0YXRzcGxvdCkgIyBDaGkgU3F1YXJlZApsaWJyYXJ5KHJzdGF0aXgpICMgQ2hpIHNxdWFyZWQgcGFpcndpc2UgY29tcGFyaXNvbnMKCiMgRml4ZWQgY29uZmxpY3RlZCBmdW5jdGlvbnMKY29uZmxpY3RlZDo6Y29uZmxpY3RzX3ByZWZlcihkcGx5cjo6ZmlsdGVyKQoKY29uZmxpY3RlZDo6Y29uZmxpY3RzX3ByZWZlcihkcGx5cjo6c2VsZWN0KQoKIyMjI0xvYWQgY3N2IGZpbGVzIGZyb20gUiBwcm9qZWN0IGZvbGRlciMjIyMKc3Vydml2YWwgPC0gcmVhZC5jc3YoImRhdGEvdHRkXzIuY3N2IikKbG9jYXRpb24gPC0gcmVhZC5jc3YoImRhdGEvZXhwb3N1cmVfbG9jYXRpb24uY3N2IikgIyA0PW91dCBhbmQgNT1kZWFkCnBpbG90IDwtIHJlYWQuY3N2KCJkYXRhL3N1cnZpdmFsX3BpbG90XzIwMjAuY3N2IikKYGBgCjxwIHN0eWxlPSJmb250LXNpemU6MjBwdCI+CiMjIEJvZHkgQ29uZGl0aW9uCjwvcD4KCkNhbGN1bGF0ZSBib2R5IGNvbmRpdGlvbiAKCmBgYHtyfQojQ2FsY3VsYXRlIFNNSSBmcm9tIFBhcnRoYXNhcmF0aHkgZXQgYWwuIDIwMTgKU01JIDwtIGZ1bmN0aW9uKG1hc3MsIHByb3NvbWEpewogIGN3X2JhciA8LSBtZWFuKHByb3NvbWEsIG5hLnJtPVQpCiAgbSA8LSBsbShwcm9zb21hIH4gbWFzcykKICBzbG9wZSA8LSBzdW1tYXJ5KG0pW1s0XV1bMl0KICBjb3IgPC0gY29yKG1hc3MsIHByb3NvbWEpCiAgCiAgc21pIDwtIG1hc3MqKGN3X2Jhci9wcm9zb21hKV4oc2xvcGUvY29yKQogIHJldHVybihzbWkpCn0KCiNDb21iaW5lIFNNSSB2ZWN0b3Igd2l0aCBib2R5IHNpemUgZGF0YWZyYW1lCnNtaSA8LSBTTUkoc3Vydml2YWwkaW5pdGlhbF9tYXNzLCBzdXJ2aXZhbCRpbml0aWFsX3Byb3NvbWFfd2lkdGgpO3N1cnZpdmFsIDwtIGNiaW5kKHN1cnZpdmFsLCBTTUk9c21pKQpgYGAKCjxwIHN0eWxlPSJmb250LXNpemU6MjBwdCI+CiMjUTA6IFBpbG90IHN0dWR5CjwvcD4KClF1ZXN0aW9uIDE6IERvZXMgZnVuZ2FsIGV4cG9zdXJlIGFmZmVjdCBUaW1lIFRvIERlYXRoIChUVEQpPyAKCk1vZGVsOiBDb3ggUHJvcG9ydGlvbmFsIGhhemFyZHMgbW9kZWwKCkRlcGVuZGVudCBWYXJpYWJsZTogVFRECgpJbmRlcGVuZGVudCBWYXJpYWJsZTogPGJyIC8+CigxKSBUcmVhdG1lbnQKClJhbmRvbSBFZmZlY3Q6IDxiciAvPgooMSkgQ29sb255IElEIDxiciAvPgooMikgU3BpZGVyIGFnZSAoanV2ZW5pbGUgb3IgYWR1bHQpIDxiciAvPgoKIyMjIyBSdW4gQ294IG1vZGVsIGFuZCBwb2x0IHN1cnZpdmFsIGN1cnZlCgpgYGB7cn0KIyMjIyBRMDogQW5hbHl6ZSBpbmRpdmlkdWFsIG1vcnRhbGl0eSB3aXRoIGEgcHJvcG9ydGlvbmFsIGhhemFyZHMgbWl4ZWQgbW9kZWwjIyMjCiMgQ294IG1vZGVsIGNvbnRhaW5pbmcgbWl4ZWQgKHJhbmRvbSBhbmQgZml4ZWQpIGVmZmVjdHMKIyBbdHRkZml0MF1BdmVyYWdlIHR0ZCB3aGVuIFMuIGR1bWljb2xhIGV4cG9zZWQgdG8gTS4gcm9iZXJ0c2lpCnR0ZGZpdDAgPC0gY294bWUoU3VydihUVEQpIH4gdHJlYXRtZW50ICsgKDF8Y29sb255LklEKSArICgxfGFnZSksIGRhdGEgPSBwaWxvdCkKCnByaW50KHR0ZGZpdDApCgojIEZpdCB0byBtb2RlbCB3aXRob3V0IHJhbmRvbSBlZmZlY3RzIGZvciBwbG90CmZpdCA8LSBzdXJ2Zml0KFN1cnYoVFREKSB+IHRyZWF0bWVudCwgZGF0YSA9IHBpbG90KQoKIyBQbG90IHBpbG90IHN1cnZpdmFsIGN1cnZlCmdnc3VydnBsb3QoZml0LCBkYXRhID0gcGlsb3QsIHNpemUgPSAxLCBwYWxldHRlID0gYygiIzJFOUZERiIsICJkYXJrb2xpdmVncmVlbjMiKSwgCiAgICAgICAgICAgcmlzay50YWJsZSA9IEZBTFNFLCAKICAgICAgICAgICBjb25mLmludCA9IFRSVUUsCiAgICAgICAgICAgcHZhbCA9IFRSVUUsbGVnZW5kLmxhYnMgPSBjKCJDb250cm9sIiwgIkV4cG9zZWQiKSwKICAgICAgICAgICBnZ3RoZW1lID0gdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ImJsYWNrIiksCiAgICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSkpCgpnZ3NhdmUoImZpZ3VyZXMvcGlsb3Rfc3Vydl9jdXJ2ZS5wbmciKQpgYGAKCjxwIHN0eWxlPSJmb250LXNpemU6MjBwdCI+CiMjUTE6IFN1cnZpdmFsCjwvcD4KClF1ZXN0aW9uIDE6IERvZXMgbWV0aG9kIG9mIGZ1bmdhbCBleHBvc3VyZSBhZmZlY3QgVGltZSBUbyBEZWF0aCAoVFREKT8gCgpNb2RlbDogQ294IFByb3BvcnRpb25hbCBoYXphcmRzIG1vZGVsCgpEZXBlbmRlbnQgVmFyaWFibGU6IFRURAoKSW5kZXBlbmRlbnQgVmFyaWFibGU6IDxiciAvPgooMSkgVHJlYXRtZW50CigyKSBTTUkKClJhbmRvbSBFZmZlY3Q6IDxiciAvPgooMSkgQ29sb255IElEIDxiciAvPgooMikgQmxvY2sKCiMjIyMgUnVuIENveCBtb2RlbAoKUmF3IGRhdGEKCmBgYHtyfQojIyMjIFExOiBBbmFseXplIGluZGl2aWR1YWwgbW9ydGFsaXR5IHdpdGggYSBwcm9wb3J0aW9uYWwgaGF6YXJkcyBtaXhlZCBtb2RlbCMjIyMKIyBDb3ggbW9kZWwgY29udGFpbmluZyBtaXhlZCAocmFuZG9tIGFuZCBmaXhlZCkgZWZmZWN0cwojIFt0dGRmaXQxXUF2ZXJhZ2UgdHRkIHdoZW4gUy4gZHVtaWNvbGEgZXhwb3NlZCB0byBNLiByb2JlcnRzaWkKdHRkZml0MSA8LSBjb3htZShTdXJ2KHR0ZF8yLCBjZW5zb3IpIH4gdHJlYXRtZW50ICsgU01JICsgKDF8Y29sb255X2lkKSArICgxfGJsb2NrKSArICgxfHNvdXJjZV9yZXRyZWF0KSwgZGF0YSA9IHN1cnZpdmFsKQoKcHJpbnQodHRkZml0MSkKCiMgUGFpcndpc2UgY29tcGFyaXNvbnMgZm9yIG9yaWdpbmFsIGRhdGEKcGFpcndpc2Vfb3JpZ2luYWwgPC0gcGFpcndpc2Vfc3VydmRpZmYoU3Vydih0dGRfMiwgY2Vuc29yKSB+IHRyZWF0bWVudCwgZGF0YSA9IHN1cnZpdmFsKQpwcmludChwYWlyd2lzZV9vcmlnaW5hbCkKYGBgCgpObyBwcmltYXJ5IGNhc2VzCgpgYGB7cn0KIyMjIyBSZS1hbmFseXplIGluZGl2aWR1YWwgaW1tdW5pdHkgd2l0aCBhIHByb3BvcnRpb25hbCBoYXphcmRzIG1peGVkIG1vZGVsIHdpdGggcHJpbWFyeSBjYXNlcyByZW1vdmVkIyMjIwojIFJlbW92ZSBwcmltYXJ5IGNhc2VzIGZyb20gY3VydmUKc3Vydml2YWxfbm9fcHJpbWFyeSA8LSBmaWx0ZXIoc3Vydml2YWwsIHByaW1hcnlfY2FzZT09Im4iLCBkaWVkX2JlZm9yZV9tZXRhID09ICJuIikKCiMgQ294IG1vZGVsIGNvbnRhaW5pbmcgbWl4ZWQgKHJhbmRvbSBhbmQgZml4ZWQpIGVmZmVjdHMKIyBbdHRkZml0M11BdmVyYWdlIHR0ZCB3aGVuIFN0ZWdvcyBleHBvc2VkIHRvIG1ldGFyaGl6aXVtIHdpdGhvdXQgcHJpbWFyeSBjYXNlcwp0dGRmaXQyIDwtIGNveG1lKFN1cnYodHRkXzIsIGNlbnNvcikgfiB0cmVhdG1lbnQgKyBTTUkgKyAoMXxjb2xvbnlfaWQpICsgKDF8YmxvY2spICsgKDF8c291cmNlX3JldHJlYXQpLCBkYXRhID0gc3Vydml2YWxfbm9fcHJpbWFyeSkKcHJpbnQodHRkZml0MikKCiMgUGFpcndpc2UgY29tcGFyaXNvbnMgd2l0aCBubyBwcmltYXJpZXMKcGFpcndpc2Vfbm9fcHJpbWFyeSA8LSBwYWlyd2lzZV9zdXJ2ZGlmZihTdXJ2KHR0ZF8yLCBjZW5zb3IpIH4gdHJlYXRtZW50LCBkYXRhID0gc3Vydml2YWxfbm9fcHJpbWFyeSkKcHJpbnQocGFpcndpc2Vfbm9fcHJpbWFyeSkKYGBgCgojIyMjIFBsb3Qgc3Vydml2YWwKClJhdyBkYXRhCgpgYGB7cn0KIyMjIyBQbG90IFN1cnZpdmFsIGN1cnZlICMjIyMKIyBGaWx0ZXIgb3V0IHNwaWRlcnMgdGhhdCBkaWVkIGJlZm9yZSBtZXRhcmhpeml1bSBleHBvc3VyZQpzdXJ2IDwtIHN1cnZpdmFsICU+JSAKICBmaWx0ZXIoZGllZF9iZWZvcmVfbWV0YSA9PSAibiIpCgojIEZpdCB0byBtb2RlbCB3aXRob3V0IHJhbmRvbSBlZmZlY3RzIGZvciBwbG90CmZpdCA8LSBzdXJ2Zml0KFN1cnYodHRkXzIsIGNlbnNvcikgfiB0cmVhdG1lbnQsIGRhdGEgPSBzdXJ2KQoKIyBQbG90IHdpdGggcHJpbWFyeSBjYXNlcwpwbG90X3ByaW1hcnkgPC0gZ2dzdXJ2cGxvdChmaXQsIGRhdGEgPSBzdXJ2LCBzaXplID0gMSwgcGFsZXR0ZSA9IGMoIiMyRTlGREYiLCAib3JhbmdlNCIsICJiaXNxdWUzIiwgImRhcmtncmVlbiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgcmlzay50YWJsZSA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZi5pbnQgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9ICJUcmVhdG1lbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQubGFicyA9IGMoIkNvbnRyb2wiLCAiQ3JpY2tldCIsICJQYXBlciIsICJTcGlkZXIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgeGxpbSA9IGMoMCwgMzApLAogICAgICAgICAgICAgICAgICAgICAgICAgICB4bGFiID0gIkRheXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3RoZW1lID0gdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ImJsYWNrIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MjMpKSkKCiMgQ2hhbmdlIHgtYXhpcyBzY2FsZSB0byBpbnRlcnZhbHMgb2YgNSBkYXlzIGFuZCBhZGQgc2lnbmlmaWNhbmNlIGxldHRlcnMKcGxvdF9wcmltYXJ5JHBsb3QgPC0gcGxvdF9wcmltYXJ5JHBsb3QgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDMwLCBieSA9IDUpKSArCiAgYW5ub3RhdGUoInRleHQiLAogICAgICAgICAgIHggPSAyOSwgeSA9IDAuOTgsCiAgICAgICAgICAgbGFiZWwgPSAiYSIsIHNpemUgPSA3KSArCiAgYW5ub3RhdGUoInRleHQiLAogICAgICAgICAgIHggPSAyOSwgeSA9IDAuNTYsCiAgICAgICAgICAgbGFiZWwgPSAiYiIsIHNpemUgPSA3KSArCiAgYW5ub3RhdGUoInRleHQiLAogICAgICAgICAgIHggPSAyOSwgeSA9IDAuMywKICAgICAgICAgICBsYWJlbCA9ICJjIiwgc2l6ZSA9IDcpICsKICBhbm5vdGF0ZSgidGV4dCIsCiAgICAgICAgICAgeCA9IDI5LCB5ID0gMC4wNCwKICAgICAgICAgICBsYWJlbCA9ICJkIiwgc2l6ZSA9IDcpCgojIFZpZXcgcGxvdApwbG90X3ByaW1hcnkKCiMgU2F2ZSBwbG90IHRvIGZpZ3VyZXMgZm9sZGVyCmdnc2F2ZSgiZmlndXJlcy9zdXJ2X2N1cnZlLnBuZyIsIHdpZHRoID0gOSwgaGVpZ2h0ID0gNiwgdW5pdHMgPSAiaW4iKQpgYGAKClBvbHQgd2l0aCBubyBwcmltYXJ5IGNhc2VzCgpgYGB7cn0KIyBGaXQgdG8gbW9kZWwgd2l0aG91dCBwcmltYXJ5IGNhc2VzIGFuZCByYW5kb20gZWZmZWN0cyBmb3IgcGxvdApmaXQyIDwtIHN1cnZmaXQoU3Vydih0dGRfMiwgY2Vuc29yKSB+IHRyZWF0bWVudCwgZGF0YSA9IHN1cnZpdmFsX25vX3ByaW1hcnkpCgojIFBsb3Qgd2l0aG91dCBwcmltYXJ5IGNhc2VzCnBsb3Rfbm9fcHJpbWFyeSA8LSBnZ3N1cnZwbG90KGZpdDIsIGRhdGEgPSBzdXJ2aXZhbF9ub19wcmltYXJ5LCBzaXplID0gMSwgcGFsZXR0ZSA9IGMoIiMyRTlGREYiLCAib3JhbmdlNCIsICJiaXNxdWUzIiwgImRhcmtncmVlbiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmlzay50YWJsZSA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZi5pbnQgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9ICJUcmVhdG1lbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQubGFicyA9IGMoIkNvbnRyb2wiLCAiQ3JpY2tldCIsICJQYXBlciIsICJTcGlkZXIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeGxpbSA9IGMoMCwgMzApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bGFiID0gIkRheXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3RoZW1lID0gdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ImJsYWNrIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTgpKSkKCiMgQ2hhbmdlIHgtYXhpcyBzY2FsZSB0byBpbnRlcnZhbHMgb2YgNyBkYXlzCnBsb3Rfbm9fcHJpbWFyeSRwbG90IDwtIHBsb3Rfbm9fcHJpbWFyeSRwbG90ICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAzMCwgYnkgPSA1KSkgKwogIGFubm90YXRlKCJ0ZXh0IiwKICAgICAgICAgICB4ID0gMjksIHkgPSAwLjk4LAogICAgICAgICAgIGxhYmVsID0gImEiLCBzaXplID0gNikgKwogIGFubm90YXRlKCJ0ZXh0IiwKICAgICAgICAgICB4ID0gMjksIHkgPSAwLjU2LAogICAgICAgICAgIGxhYmVsID0gImIiLCBzaXplID0gNikgKwogIGFubm90YXRlKCJ0ZXh0IiwKICAgICAgICAgICB4ID0gMjksIHkgPSAwLjMsCiAgICAgICAgICAgbGFiZWwgPSAiYyIsIHNpemUgPSA2KSArCiAgYW5ub3RhdGUoInRleHQiLAogICAgICAgICAgIHggPSAyOSwgeSA9IDAuMDQsCiAgICAgICAgICAgbGFiZWwgPSAiZCIsIHNpemUgPSA2KQoKIyBWaWV3IHBsb3QKcHJpbnQocGxvdF9ub19wcmltYXJ5KQoKIyBTYXZlIHBsb3QgdG8gZmlndXJlcyBmb2xkZXIKZ2dzYXZlKCJmaWd1cmVzL3N1cnZfY3VydmVfbm9fcHJpbWFyeS5wbmciLCB3aWR0aCA9IDksIGhlaWdodCA9IDYsIHVuaXRzID0gImluIikKYGBgCjxwIHN0eWxlPSJmb250LXNpemU6MjBwdCI+CiMjUTI6IFNwYWNlIHVzZQo8L3A+CgpRdWVzdGlvbiAyOiBEb2VzIHBhdGhvZ2VuIGV4cG9zdXJlIGFmZmVjdCB0aGUgcHJvcG9ydGlvbiBvZiB0aW1lIGluZGl2aWR1YWxzIHNwZW5kIGluc2lkZSB2cyBvdXRzaWRlIHRoZWlyIG5lc3Q/CgpNb2RlbDogR0xNTQoKRGVwZW5kZW50IFZhcmlhYmxlOiBQcm9wb3J0aW9uIG9mIHRpbWUgaW5kaXZpZHVhbHMgc3BlbnQgaW5zaWRlIG5lc3QKCkluZGVwZW5kZW50IFZhcmlhYmxlOiA8YnIgLz4KKDEpIFRyZWF0bWVudCA8YnIgLz4KClJhbmRvbSBFZmZlY3Q6IDxiciAvPgooMSkgQ29sb255IElEIDxiciAvPgooMikgQmxvY2sgPGJyIC8+CgojIyMjIFdyYW5nbGUgVFREIGRhdGEKCmBgYHtyfQojIyMjIFEyOiBQYXRob2dlbiBleHBvc3VyZSBzcGFjZSB1c2UgYW5hbHlzaXMgIyMjIwojIEFwcGx5IHRoZSBwaXZvdF9sb25nZXIoKSBmdW5jdGlvbiB0byByZXNoYXBlIHRoZSBkYXRhCmxvY2F0aW9uX2xvbmcgPC0gbG9jYXRpb24gJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gY29udGFpbnMoImxvY2F0aW9uIiksICMgU2VsZWN0IGNvbHVtbnMgY29udGFpbmluZyAibG9jYXRpb24iCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInNwaWRlcl9pZCIsICMgTmFtZSBmb3IgdGhlIG5ldyBjb2x1bW4gd2l0aCBzcGlkZXIgSURzIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAibG9jYXRpb24iKSAjIE5hbWUgZm9yIHRoZSBuZXcgY29sdW1uIHdpdGggbG9jYXRpb24KCiMgRmlsdGVyIHJvd3MgYnkgdW5pcXVlICdjb2xvbnlfaWQnCmZpbHRlcmVkX3N1cnZpdmFsIDwtIHN1cnZpdmFsICU+JQogIGRpc3RpbmN0KGNvbG9ueV9pZCwgLmtlZXBfYWxsID0gVFJVRSkKCiMgTWVyZ2UgdGhlIGRhdGFzZXRzIGJ5ICdjb2xvbnlfaWQnCm1lcmdlZF9sb2NhdGlvbiA8LSBsb2NhdGlvbl9sb25nICU+JQogIGxlZnRfam9pbihkcGx5cjo6c2VsZWN0KGZpbHRlcmVkX3N1cnZpdmFsLCBjb2xvbnlfaWQsIHRyZWF0bWVudCksIGJ5ID0gImNvbG9ueV9pZCIpICU+JQogIGZpbHRlcihsb2NhdGlvbiAhPSAiNSIpICU+JQogIHVuaXRlKHN1YmplY3RfaWQsIHNwaWRlcl9pZCwgY29sb255X2lkLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFKSAlPiUgCiAgZmlsdGVyKHN1YmplY3RfaWQgIT0gInllbGxvd19sb2NhdGlvbl8xMyIpCgojIE1lcmdlIGxvY2F0aW9uIGFuZCB0dGQgZGF0YQptZXJnZWRfbG9jYXRpb25fdHRkIDwtIG1lcmdlZF9sb2NhdGlvbiAlPiUKICBsZWZ0X2pvaW4oc3Vydml2YWxbLGMoInN1YmplY3RfaWQiLCJ0dGRfMiIsICJwcmltYXJ5X2Nhc2UiLCAic291cmNlX3JldHJlYXQiLCAiY2Vuc29yIildLCBieSA9IGMoInN1YmplY3RfaWQiPSJzdWJqZWN0X2lkIikpCgojIENhbGN1bGF0ZSB0aGUgY291bnQgb2YgaW5kaXZpZHVhbHMgYXQgZWFjaCBsb2NhdGlvbgpsb2NhdGlvbl9pbiA8LSBtZXJnZWRfbG9jYXRpb25fdHRkICU+JQogIGZpbHRlcihsb2NhdGlvbiA8IDQsIGRhdGUgPj0gIjIwMjMtMDYtMDgiKSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSwgc3ViamVjdF9pZCkgJT4lCiAgbXV0YXRlKENvdW50ID0gbigpKSAlPiUgCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHN1YmplY3RfaWQpICU+JQogIG11dGF0ZShzdW1Db3VudCA9IHN1bShDb3VudCkvdHRkXzIpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcighZHVwbGljYXRlZChzdWJqZWN0X2lkKSkKCiMgQ2FsY3VsYXRlIHN1bW1hcnkgc3RhdGlzdGljcyBmb3Igc3BhY2UgdXNlIGJ5IHRyZWF0bWVudApzdW1tYXJ5X3NwYWNlX3VzZV9zdGF0cyA8LSBsb2NhdGlvbl9pbiAlPiUKICBncm91cF9ieSh0cmVhdG1lbnQueSkgJT4lCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHN1bUNvdW50KSwKICAgICAgICAgICAgbWVkaWFuID0gbWVkaWFuKHN1bUNvdW50KSwKICAgICAgICAgICAgc2QgPSBzZChzdW1Db3VudCksCiAgICAgICAgICAgIG1pbiA9IG1pbihzdW1Db3VudCksCiAgICAgICAgICAgIG1heCA9IG1heChzdW1Db3VudCkpCgojIFByaW50IHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MKcHJpbnQoc3VtbWFyeV9zcGFjZV91c2Vfc3RhdHMpCmBgYAoKIyMjIyBSdW4gR0xNTQoKYGBge3J9CiMgRGlzdHJpYnV0aW9uIG9mIHNwYWNlIHVzZSBieSB0cmVhdG1lbnQKZ2dwbG90KGRhdGEgPSBsb2NhdGlvbl9pbikgKwogIGdlb21faGlzdG9ncmFtKGFlcyh4ID0gc3VtQ291bnQsIGZpbGwgPSB0cmVhdG1lbnQueSksIGJpbnMgPSAxMCwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzJFOUZERiIsICJvcmFuZ2U0IiwgImJpc3F1ZTMiLCAiZGFya2dyZWVuIikpICsKICBmYWNldF93cmFwKH4gdHJlYXRtZW50LnkpIAoKIyBGaXQgYSBHTE1NCnNwYWNlX2dsbW0gPC0gZ2xtbVRNQihzdW1Db3VudCB+IHRyZWF0bWVudC55ICsgKDEgfCBibG9jaykgKyAoMSB8IGNvbG9ueV9pZCkgKyAoMXxzb3VyY2VfcmV0cmVhdCksIGRhdGEgPSBsb2NhdGlvbl9pbikKCiMgRGlzcGxheSBtb2RlbCBzdW1tYXJ5CnN1bW1hcnkoc3BhY2VfZ2xtbSkKCiMgSW5zaWRlOiBDaGVjayB5b3VyIG1vZGVsIC8gcmVncmVzc2lvbiBhc3N1bXB0aW9ucwpwbG90KHNpbXVsYXRlUmVzaWR1YWxzKHNwYWNlX2dsbW0pKQp0ZXN0RGlzcGVyc2lvbihzaW11bGF0ZVJlc2lkdWFscyhzcGFjZV9nbG1tKSkKCiMgVGVzdCBzaWduaWZpY2FuY2UKIyBVc2UgdHlwZSBJSUkgc3VtcyBvZiBzcXVhcmVzCkFub3ZhKHNwYWNlX2dsbW0sIHR5cGU9MykKCiMgUG9zdGhvYyBUdWtleQojIEV4dHJhY3QgbGVhc3Qgc3F1YXJlcyBtZWFucwpwYWlycyhlbW1lYW5zKHNwYWNlX2dsbW0sIHNwZWNzPSJ0cmVhdG1lbnQueSIsIHR5cGU9InJlc3BvbnNlIikpCmBgYAoKIyMjIyBQbG90IHNwYWNlIHVzZQoKQWxsIHNwaWRlcnMKCmBgYHtyfQojIFBsb3Qgd2l0aCByYXcgZGF0YQpyYXdfcHJvcG9ydGlvbnMgPC0gZ2dwbG90KGxvY2F0aW9uX2luLCBhZXMoeCA9IGZhY3Rvcih0cmVhdG1lbnQueSwgbGV2ZWxzID0gYygiY29udHJvbCIsICJwYXBlciIsICJjcmlja2V0IiwgInNwaWRlciIpKSwgeSA9IHN1bUNvdW50LCBjb2xvciA9IHRyZWF0bWVudC55LCBmaWxsID0gdHJlYXRtZW50LnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IGFzLmNoYXJhY3RlcihjZW5zb3IpKSkgKwogIGdlb21faml0dGVyKHNpemUgPSAyLjc1LCB3aWR0aCA9IDAuMzUsIGFscGhhID0gMC41KSArCiAgeWxpbSgwLjQsMS4wNSkgKwogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCBzaXplID0gMS4xNSwgc2hhcGUgPSAyMSwgY29sb3IgPSAiYmxhY2siKSArIAogIHN0YXRfc3VtbWFyeShhZXMoeCA9IGZhY3Rvcih0cmVhdG1lbnQueSwgbGV2ZWxzID0gYygiY29udHJvbCIsICJwYXBlciIsICJjcmlja2V0IiwgInNwaWRlciIpKSwgCiAgICAgICAgICAgICAgICAgICAgeSA9IHN1bUNvdW50LCBjb2xvciA9IHRyZWF0bWVudC55LCBjb2xvciA9IHRyZWF0bWVudC55KSwKICAgICAgICAgICAgICAgIGdlb209ImVycm9yYmFyIiwgd2lkdGggPSAwLjIsIHNpemUgPSAxLjI1LCBpbmhlcml0LmFlcyA9IEYpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzJFOUZERiIsICJvcmFuZ2U0IiwgImJpc3F1ZTMiLCAiZGFya2dyZWVuIikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMkU5RkRGIiwgIm9yYW5nZTQiLCAiYmlzcXVlMyIsICJkYXJrZ3JlZW4iKSkgKwogIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogIGxhYnMoeCA9ICJUcmVhdG1lbnQiLCB5ID0gIlByb3BvcnRpb24gb2YgZGF5cyBpbnNpZGUgbmVzdCIsIGNvbG9yID0gIiIsIGZpbGwgPSAiVHJlYXRtZW50cyIpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJDb250cm9sIiwgIlBhcGVyIiwgIkNyaWNrZXQiLCAiU3BpZGVyIikpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0iYmxhY2siKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MjMpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpyYXdfcHJvcG9ydGlvbnMgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IHVuaXF1ZShsb2NhdGlvbl9pbiR0cmVhdG1lbnQueSksIAogICAgICAgICAgIHkgPSByZXAobWF4KGxvY2F0aW9uX2luJHN1bUNvdW50KSArIDAuMDQsbGVuZ3RoKHVuaXF1ZShsb2NhdGlvbl9pbiR0cmVhdG1lbnQueSkpKSwKICAgICAgICAgICBsYWJlbCA9IGMoImEiLCAiYSIsICJhIiwgImIiKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNykKCmdnc2F2ZSgiZmlndXJlcy9zcGFjZV91c2UucG5nIiwgd2lkdGggPSA5LCBoZWlnaHQgPSA2LCB1bml0cyA9ICJpbiIpCmBgYAoKT25seSBkZWFkIHNwaWRlcnMKCmBgYHtyfQojIFBsb3Qgd2l0aCByYXcgZGF0YSBvbiBvbmx5IHNwaWRlcnMgdGhhdCBkaWVkCiMgRmlsdGVyIG91dCBsaXZpbmcgc3BpZGVycwpsb2NhdGlvbl9pbl9kZWFkIDwtIGxvY2F0aW9uX2luICU+JSAKICBmaWx0ZXIodHRkXzIgPCAyOCkKCiMgUGxvdApyYXdfcHJvcG9ydGlvbnNfZGVhZCA8LSBnZ3Bsb3QobG9jYXRpb25faW5fZGVhZCwgYWVzKHggPSBmYWN0b3IodHJlYXRtZW50LnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29udHJvbCIsICJwYXBlciIsICJjcmlja2V0IiwgInNwaWRlciIpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHN1bUNvdW50LCBjb2xvciA9IHRyZWF0bWVudC55LCBmaWxsID0gdHJlYXRtZW50LnkpKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjI1LCBhbHBoYSA9IDAuNSkgKwogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCBzaXplID0gMSwgc2hhcGUgPSAyMSwgY29sb3IgPSAiYmxhY2siKSArIAogIHN0YXRfc3VtbWFyeShnZW9tPSJlcnJvcmJhciIsIHdpZHRoID0gMC4yLCBzaXplID0gMS4yNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMkU5RkRGIiwgIm9yYW5nZTQiLCAiYmlzcXVlMyIsICJkYXJrZ3JlZW4iKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMyRTlGREYiLCAib3JhbmdlNCIsICJiaXNxdWUzIiwgImRhcmtncmVlbiIpKSArCiAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArCiAgbGFicyh4ID0gIlRyZWF0bWVudCIsIHkgPSAiUHJvcG9ydGlvbiBvZiBkYXlzIGluc2lkZSBuZXN0IiwgY29sb3IgPSAiIiwgZmlsbCA9ICJUcmVhdG1lbnRzIikgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkNvbnRyb2wiLCAiUGFwZXIiLCAiQ3JpY2tldCIsICJTcGlkZXIiKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSJibGFjayIpLAogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xOCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCnJhd19wcm9wb3J0aW9uc19kZWFkICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSB1bmlxdWUobG9jYXRpb25faW4kdHJlYXRtZW50LnkpLCAKICAgICAgICAgICB5ID0gcmVwKG1heChsb2NhdGlvbl9pbiRzdW1Db3VudCkgKyAwLjA0LGxlbmd0aCh1bmlxdWUobG9jYXRpb25faW4kdHJlYXRtZW50LnkpKSksCiAgICAgICAgICAgbGFiZWwgPSBjKCJhIiwgImEiLCAiYSIsICJiIiksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDYpCgpnZ3NhdmUoImZpZ3VyZXMvc3BhY2VfdXNlX2RlYWQucG5nIiwgd2lkdGggPSA5LCBoZWlnaHQgPSA2LCB1bml0cyA9ICJpbiIpCgpgYGAKPHAgc3R5bGU9ImZvbnQtc2l6ZToyMHB0Ij4KIyNRMzogUG9seWRvbXkKPC9wPgoKUXVlc3Rpb24gMzogRG9lcyBwYXRob2dlbiBleHBvc3VyZSBtb2RlIGluZmx1ZW5jZSB0aGUgY29uc3RydWN0aW9uIG9mIG5ldyBuZXN0cz8KCk1vZGVsOiBMb2dpc3RpYyByZWdyZXNzaW9uL0NoaSBzcXVhcmVkCgpEZXBlbmRlbnQgVmFyaWFibGU6IFBvbHlkb215IHkvbgoKSW5kZXBlbmRlbnQgVmFyaWFibGU6IDxiciAvPgooMSkgdHJlYXRtZW50IDxiciAvPgoKIyMjIyBXcmFuZ2xlIGRhdGEKCmBgYHtyfQojIyMjIFBvbHlkb215IEFuYWx5c2lzICMjIyMKIyBGaWx0ZXIgb3V0IGp1c3QgbGFzdCBkYXkgb2YgZGF0YQpsb2NhdGlvbl9sYXN0IDwtIGxvY2F0aW9uICU+JSAKICBmaWx0ZXIoZGF0ZSA9PSAiMjAyMy0wNy0wNiIpICU+JSAKICBkcGx5cjo6c2VsZWN0KHBvbHksIHRyZWF0bWVudCkKCiMgQ29udmVydCB2YXJpYWJsZXMgdG8gZmFjdG9ycwpsb2NhdGlvbl9sYXN0JHBvbHkgPC0gYXMuZmFjdG9yKGxvY2F0aW9uX2xhc3QkcG9seSkKbG9jYXRpb25fbGFzdCR0cmVhdG1lbnQgPC0gYXMuZmFjdG9yKGxvY2F0aW9uX2xhc3QkdHJlYXRtZW50KQpgYGAKCiMjIyMgUnVuIGNoaSBzcXVhcmVkCgpgYGB7cn0KIyBDaGkgc3F1YXJlZCBjb21wYXJpbmcgYmV0d2VlbiB0cmVhdG1lbnRzCmNvbnRpbmdlbmN5X3RhYmxlIDwtIHRhYmxlKGxvY2F0aW9uX2xhc3QkcG9seSwgbG9jYXRpb25fbGFzdCR0cmVhdG1lbnQpCgpjaGkgPC0gY2hpc3EudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoY2hpKQoKZ2dwbG90KGxvY2F0aW9uX2xhc3QsIGFlcyh0cmVhdG1lbnQsIGZpbGwgPSBwb2x5KSkgKwogIGdlb21fYmFyKGNvbG91cj0iYmxhY2siLCBwb3NpdGlvbiA9ICJmaWxsIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImxpZ2h0Ymx1ZSIsICJkYXJrYmx1ZSIpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1vbm9kb21vdXMiLCAiUG9seWRvbW91cyIpLAogICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiRnJhZ21lbnRhdGlvbiIpICsKICB5bGFiKCJQcm9wb3J0aW9uIikgKwogIHhsYWIoIlRyZWF0bWVudCIpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJDb250cm9sIiwgIkNyaWNrZXQiLCAiUGFwZXIiLCAiU3BpZGVyIikpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0iYmxhY2siKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTUpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKCmdnc2F2ZSgiZmlndXJlcy9wb2x5ZG9teV90cmVhdG1lbnQucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSA1LCB1bml0cyA9ICJpbiIpCmBgYAo=