knitr::opts_chunk$set(cache = TRUE, dev = c("png", "pdf"))
library(here)
source(here("src", "model_quadratic_grampians.R"))
source(here("src", "environmental_distance_metrics.R"))
library(dplyr)
library(ggplot2)
library(gridExtra)
library(rstanarm)
library(tidyr)

The following is a validation of the predictions/inference from a trait-environment model of the Grampians Bioregion ~20 taxa dataset.

The following steps are undertaken:

mds <- local({
  nms1 <-   c(
    "mean_moisture_index_of_low_qtr", "topographic_wetness_index_3sec",
    "relief_1000m_radius", "total_nitrogen"
  )
  nms2 <- c("sla_mm2_per_mg", "seed_mass_mg", "max_height_m")
  vars <- lapply(nms1, function(x) poly(log(grampians[[x]]), 2))
  coefs <- lapply(vars, function(x) attr(x, "coefs"))
  vars <- do.call(cbind, vars)
  vars <- cbind(
    vars, do.call(cbind, lapply(nms2, function(x) log(grampians[[x]])))
  )
  vars <- scale(vars)
  cntrs <- attr(vars, "scaled:center")
  scales <- attr(vars, "scaled:scale")

  vars_new_raw <- na.omit(southeast)
  vars_new <- lapply(
    seq_along(nms1), function(x) {
      poly(log(vars_new_raw[[nms1[x]]]), degree = 2, coefs = coefs[[x]])
    }
  )
  vars_new <- do.call(cbind, vars_new)
  vars_new <- cbind(
    vars_new, do.call(cbind, lapply(nms2, function(x) log(vars_new_raw[[x]])))
  )
  vars_new <- scale(vars_new, center = cntrs, scale = scales)


  setNames(
    data.frame(
      vars_new_raw[, c("occupancy", "taxon", "ibra_subregion")], vars_new
    ),
    c(
      "y", "taxon", "ibra_subregion", "mlq", "mlq2","twi", "twi2", "r1k",
      "r1k2", "tn", "tn2", "sla", "sm", "mh"
    )
  )
})
perf <- local({
  perf <- mapply(
    function(f, re.form) {
      f(
        model_grampians, y, list(taxon, ibra_subregion),
        rbind(mds, mdg[names(mds)]), re.form
      )
    },
    f = rep(list(auroc, pred_inf, dev_explained), each = 2),
    re.form = list(NULL,  NA)
  )
  taxon <- sub("(.*)\\..*", "\\1", rownames(perf))
  ibra_subregion <- sub(".*\\.", "", rownames(perf))
  dim(perf) <- dim(perf) * c(2, .5)
  colnames(perf) <- c("AUC", "mean_predictive_info", "deviance_explained")
  cbind(
    taxon = rep(taxon, 2),
    ibra_subregion = rep(ibra_subregion, 2),
    random_effect = rep(c(TRUE, FALSE), each = nrow(perf) / 2),
    as.data.frame(perf)
  )
})
aucdist <- data.frame(
  perf[c("taxon", "ibra_subregion", "AUC")],
  `Geographic (km)`= dists[as.character(perf$ibra_subregion)],
  Environmental = kldists[as.character(perf$ibra_subregion)],
  Community = community_dist[as.character(perf$ibra_subregion)],
  "Dummy" = "Dummy",
  check.names = FALSE
)

aucdist <- gather(
  aucdist, "distance", "value", `Geographic (km)`, Environmental, Community
)

aucdist <- na.omit(aucdist)

aucdistmean <- summarise(
  group_by(aucdist, ibra_subregion, distance),
  meanauc = mean(AUC), value = mean(value)
)

aucdistplot <- ggplot(aucdist) +
  aes(AUC, value) +
  geom_vline(xintercept = .5, color = "grey", size = 1.5) +
  geom_point(alpha=.1) +
  geom_point(
    aes(meanauc), data = aucdistmean, size = 2, shape = 21, fill = "white"
  ) +
  xlim(0, 1) +
  ylab("Distance") +
  facet_grid(distance ~ ., scales = "free_y") +
  theme_bw() +
  theme(
    axis.title.x = element_blank(),
    axis.text.x = element_blank(),
    axis.ticks.x = element_blank(),
    strip.background = element_blank()
  )

aucbw <- ggplot(aucdist) +
  aes(x = Dummy, y = AUC) +
  geom_boxplot(fill = "grey") +
  coord_flip() +
  facet_grid(Dummy ~ .) +
  ylim(0, 1) +
  scale_x_discrete(labels = "0.95") +
  xlab("Dummy") +
  theme_bw() +
  theme(
    axis.title.y = element_text(color = "transparent"),
    axis.text.y  = element_text(color = "transparent"),
    axis.ticks.y = element_line(color = "transparent"),
    strip.background = element_blank(),
    strip.text.y = element_text(color = "transparent"),
    plot.margin = margin(0, 5.5, 5.5, 5.5)
  )

grid.arrange(aucdistplot, aucbw, ncol = 1, heights = c(.86, .14))

ggplot(
  transform(
    subset(perf, ibra_subregion != "Greater Grampians" & !random_effect),
    ibra_subregion = factor(
      ibra_subregion, names(sort(tapply(AUC, ibra_subregion, median)))
    )
  )
) +
aes(AUC) + geom_histogram() + facet_wrap(~ibra_subregion, 3) +
xlab("AUC") +
ylab("No. of taxa") +
ggtitle(
  paste(
    "Area Under Receiver Operator Curve for taxa within IBRA subregions of",
    "Southeast Australia"
  )
)

ggplot(
  transform(
    subset(perf, ibra_subregion != "Greater Grampians" & !random_effect),
    ibra_subregion = factor(
      ibra_subregion,
      names(sort(tapply(mean_predictive_info, ibra_subregion, median)))
    )
  )
) +
aes(mean_predictive_info) + geom_histogram() + facet_wrap(~ibra_subregion, 3) +
xlab("Mean Predictive Information") +
ylab("No. of taxa") +
ggtitle(
  paste(
    "Mean Predictive Information for taxa within IBRA subregions of",
    "Southeast Australia"
  )
)

ggplot(
  transform(
    subset(perf, taxon %in% mdg$taxon & random_effect),
    taxon = factor(
      taxon,
      names(
        sort(
          tapply(
            AUC[ibra_subregion == "Greater Grampians"],
            taxon[ibra_subregion == "Greater Grampians"],
            median
          )
        )
      )
    )
  )
) +
aes(
  AUC,
  mean_predictive_info,
  col = ifelse(
    ibra_subregion == "Greater Grampians",
    "Grampians",
    "Other Region"
  )
) +
geom_point() +
facet_wrap(~taxon, labeller = label_wrap_gen(40)) +
labs(col = NULL) +
xlab("AUC") +
ylab("Mean Predictive Information") +
ggtitle(
  paste(
    ""
  )
) +
theme(legend.position = "bottom")

model_auc <- stan_glmer(
  (AUC - .001) ~ value + (1 | taxon) + (1 | ibra_subregion),
  family = mgcv::betar,
  iter = 1000, chains = 3,
  data = aucdist,
  subset = ibra_subregion != "Greater Grampians" & distance == "Geographic (km)"
)
summary(model_auc, regex_pars = "^[^b]", probs = c(.025, .975))

Model Info:
 function:     stan_glmer
 family:       beta [logit, link.phi=log]
 formula:      (AUC - 0.001) ~ value + (1 | taxon) + (1 | ibra_subregion)
 algorithm:    sampling
 sample:       1500 (posterior sample size)
 priors:       see help('prior_summary')
 observations: 1120
 groups:       taxon (82), ibra_subregion (18)

Estimates:
                                                mean   sd   2.5%   97.5%
(Intercept)                                    0.9    0.2  0.5    1.4   
value                                          0.0    0.0  0.0    0.0   
(phi)                                          9.9    0.4  9.1   10.8   
Sigma[taxon:(Intercept),(Intercept)]           0.2    0.0  0.1    0.2   
Sigma[ibra_subregion:(Intercept),(Intercept)]  0.1    0.0  0.0    0.1   

Fit Diagnostics:
           mean   sd   2.5%   97.5%
mean_PPD 0.7    0.0  0.7    0.7    

The mean_ppd is the sample average posterior predictive distribution of the outcome variable (for details see help('summary.stanreg')).

MCMC diagnostics
                                              mcse Rhat n_eff
(Intercept)                                   0.0  1.0   751 
value                                         0.0  1.0   723 
(phi)                                         0.0  1.0  2248 
Sigma[taxon:(Intercept),(Intercept)]          0.0  1.0   429 
Sigma[ibra_subregion:(Intercept),(Intercept)] 0.0  1.0   723 
mean_PPD                                      0.0  1.0  1485 
log-posterior                                 0.5  1.0   375 

For each parameter, mcse is Monte Carlo standard error, n_eff is a crude measure of effective sample size, and Rhat is the potential scale reduction factor on split chains (at convergence Rhat=1).
IycgLS0tCiMnIHRpdGxlOiAiVmFsaWRhdGlvbiBvZiBxdWFkcmF0aWMgbW9kZWwiCiMnIGF1dGhvcjogIldpbGxpYW0gSy4gTW9ycmlzIgojJyBkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCiMnIG91dHB1dDoKIycgICBybWFya2Rvd246Omh0bWxfbm90ZWJvb2s6CiMnICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKIycgLS0tCgojKyBzZXR1cCwgbWVzc2FnZT1GQUxTRSwgZmlnLmtlZXA9Im5vbmUiLCBmaWcuc2hvdz0iaGlkZSIKa25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlID0gVFJVRSwgZGV2ID0gYygicG5nIiwgInBkZiIpKQpsaWJyYXJ5KGhlcmUpCnNvdXJjZShoZXJlKCJzcmMiLCAibW9kZWxfcXVhZHJhdGljX2dyYW1waWFucy5SIikpCnNvdXJjZShoZXJlKCJzcmMiLCAiZW52aXJvbm1lbnRhbF9kaXN0YW5jZV9tZXRyaWNzLlIiKSkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShyc3RhbmFybSkKbGlicmFyeSh0aWR5cikKCiMnIFRoZSBmb2xsb3dpbmcgaXMgYSB2YWxpZGF0aW9uIG9mIHRoZSBwcmVkaWN0aW9ucy9pbmZlcmVuY2UgZnJvbSBhCiMnIHRyYWl0LWVudmlyb25tZW50IG1vZGVsIG9mIHRoZSBHcmFtcGlhbnMgQmlvcmVnaW9uIH4yMCB0YXhhIGRhdGFzZXQuCiMnCiMnIFRoZSBmb2xsb3dpbmcgc3RlcHMgYXJlIHVuZGVydGFrZW46CiMnCiMnICogRml0IGEgbW9kZWwgdG8gR3JhbXBpYW5zIGRhdGEuCiMnICogQ2FsY3VsYXRlIFBlcmZvcm1hbmNlIE1ldHJpY3M6CiMnICAgICAqIFByZWRpY3QgcHJvYmFiaWxpdHkgb2Ygb2NjdXJyZW5jZQojJyAgICAgICAgICogUHJlZGljdCB3aXRoaW4gR3JhbXBpYW5zIHRyYWluaW5nIHNldDoKIycgICAgICAgICAgICAgKiBQcmVkaWN0IGZvciBlYWNoIHNwZWNpZXMgaW5jbHVkaW5nIHNwZWNpZXMgcmFuZG9tIGVmZmVjdHMuCiMnICAgICAgICAgICAgICogUHJlZGljdCBmb3IgZWFjaCBzcGVjaWVzIHdpdGhvdXQgc3BlY2llcyByYW5kb20gZWZmZWN0cy4KIycgICAgICAgICAqIFByZWRpY3QgdG8gdGhlIFNvdXRoLWVhc3QgdmFsaWRhdGlvbiBzZXQ6CiMnICAgICAgICAgICAgICogUHJlZGljdCB0byBlYWNoIElCUkEgc3VicmVnaW9uIHdpdGhpbiB0aGUgU291dGgtZWFzdDoKIycgICAgICAgICAgICAgICAgICogUHJlZGljdCBmb3IgZWFjaCBzcGVjaWVzIGNvbW1vbiB0byBHcmFtcGlhbnMgYW5kIFNvdXRoLWVhc3QKIycgICAgICAgICAgICAgICAgICAgc3VicmVnaW9uOgojJyAgICAgICAgICAgICAgICAgICAgICogUHJlZGljdCBpbmNsdWRpbmcgc3BlY2llcyByYW5kb20gZWZmZWN0cy4KIycgICAgICAgICAgICAgICAgICAgICAqIFByZWRpY3Qgd2l0aG91dCBzcGVjaWVzIHJhbmRvbSBlZmZlY3RzLgojJyAgICAgICAgICAgICAgICAgKiBQcmVkaWN0IGZvciBlYWNoIHNwZWNpZXMgbm90IGZvdW5kIGluIHRoZSBHcmFtcGlhbnMKIycgICAgICAgICAgICAgICAgICAgdHJhaW5pbmcgc2V0LgojJyAgICAgKiBGb3IgZWFjaCBwcmVkaWN0aW9uIHR5cGUgKHdpdGhpbi1zYW1wbGUvb3V0LW9mLXNhbXBsZSwKIycgICAgICAgd2l0aC1yZS93aXRob3V0LXJlLCBhbmQgbW9kZWxsZWQtc3BlY2llcy91bm1vZGVsbGVkLXNwZWNpZXMpLAojJyAgICAgICBiaW9yZWdpb24sIGFuZCBzcGVjaWVzIChhbmQgdGhlaXIgY29tYmluYXRpb25zKSBjYWxjdWxhdGUgcGVyZm9ybWFuY2UKIycgICAgICAgbWV0cmljcwoKIysgbWRzCm1kcyA8LSBsb2NhbCh7CiAgbm1zMSA8LSAgIGMoCiAgICAibWVhbl9tb2lzdHVyZV9pbmRleF9vZl9sb3dfcXRyIiwgInRvcG9ncmFwaGljX3dldG5lc3NfaW5kZXhfM3NlYyIsCiAgICAicmVsaWVmXzEwMDBtX3JhZGl1cyIsICJ0b3RhbF9uaXRyb2dlbiIKICApCiAgbm1zMiA8LSBjKCJzbGFfbW0yX3Blcl9tZyIsICJzZWVkX21hc3NfbWciLCAibWF4X2hlaWdodF9tIikKICB2YXJzIDwtIGxhcHBseShubXMxLCBmdW5jdGlvbih4KSBwb2x5KGxvZyhncmFtcGlhbnNbW3hdXSksIDIpKQogIGNvZWZzIDwtIGxhcHBseSh2YXJzLCBmdW5jdGlvbih4KSBhdHRyKHgsICJjb2VmcyIpKQogIHZhcnMgPC0gZG8uY2FsbChjYmluZCwgdmFycykKICB2YXJzIDwtIGNiaW5kKAogICAgdmFycywgZG8uY2FsbChjYmluZCwgbGFwcGx5KG5tczIsIGZ1bmN0aW9uKHgpIGxvZyhncmFtcGlhbnNbW3hdXSkpKQogICkKICB2YXJzIDwtIHNjYWxlKHZhcnMpCiAgY250cnMgPC0gYXR0cih2YXJzLCAic2NhbGVkOmNlbnRlciIpCiAgc2NhbGVzIDwtIGF0dHIodmFycywgInNjYWxlZDpzY2FsZSIpCgogIHZhcnNfbmV3X3JhdyA8LSBuYS5vbWl0KHNvdXRoZWFzdCkKICB2YXJzX25ldyA8LSBsYXBwbHkoCiAgICBzZXFfYWxvbmcobm1zMSksIGZ1bmN0aW9uKHgpIHsKICAgICAgcG9seShsb2codmFyc19uZXdfcmF3W1tubXMxW3hdXV0pLCBkZWdyZWUgPSAyLCBjb2VmcyA9IGNvZWZzW1t4XV0pCiAgICB9CiAgKQogIHZhcnNfbmV3IDwtIGRvLmNhbGwoY2JpbmQsIHZhcnNfbmV3KQogIHZhcnNfbmV3IDwtIGNiaW5kKAogICAgdmFyc19uZXcsIGRvLmNhbGwoY2JpbmQsIGxhcHBseShubXMyLCBmdW5jdGlvbih4KSBsb2codmFyc19uZXdfcmF3W1t4XV0pKSkKICApCiAgdmFyc19uZXcgPC0gc2NhbGUodmFyc19uZXcsIGNlbnRlciA9IGNudHJzLCBzY2FsZSA9IHNjYWxlcykKCgogIHNldE5hbWVzKAogICAgZGF0YS5mcmFtZSgKICAgICAgdmFyc19uZXdfcmF3WywgYygib2NjdXBhbmN5IiwgInRheG9uIiwgImlicmFfc3VicmVnaW9uIildLCB2YXJzX25ldwogICAgKSwKICAgIGMoCiAgICAgICJ5IiwgInRheG9uIiwgImlicmFfc3VicmVnaW9uIiwgIm1scSIsICJtbHEyIiwidHdpIiwgInR3aTIiLCAicjFrIiwKICAgICAgInIxazIiLCAidG4iLCAidG4yIiwgInNsYSIsICJzbSIsICJtaCIKICAgICkKICApCn0pCgojKyBwZXJmCnBlcmYgPC0gbG9jYWwoewogIHBlcmYgPC0gbWFwcGx5KAogICAgZnVuY3Rpb24oZiwgcmUuZm9ybSkgewogICAgICBmKAogICAgICAgIG1vZGVsX2dyYW1waWFucywgeSwgbGlzdCh0YXhvbiwgaWJyYV9zdWJyZWdpb24pLAogICAgICAgIHJiaW5kKG1kcywgbWRnW25hbWVzKG1kcyldKSwgcmUuZm9ybQogICAgICApCiAgICB9LAogICAgZiA9IHJlcChsaXN0KGF1cm9jLCBwcmVkX2luZiwgZGV2X2V4cGxhaW5lZCksIGVhY2ggPSAyKSwKICAgIHJlLmZvcm0gPSBsaXN0KE5VTEwsICBOQSkKICApCiAgdGF4b24gPC0gc3ViKCIoLiopXFwuLioiLCAiXFwxIiwgcm93bmFtZXMocGVyZikpCiAgaWJyYV9zdWJyZWdpb24gPC0gc3ViKCIuKlxcLiIsICIiLCByb3duYW1lcyhwZXJmKSkKICBkaW0ocGVyZikgPC0gZGltKHBlcmYpICogYygyLCAuNSkKICBjb2xuYW1lcyhwZXJmKSA8LSBjKCJBVUMiLCAibWVhbl9wcmVkaWN0aXZlX2luZm8iLCAiZGV2aWFuY2VfZXhwbGFpbmVkIikKICBjYmluZCgKICAgIHRheG9uID0gcmVwKHRheG9uLCAyKSwKICAgIGlicmFfc3VicmVnaW9uID0gcmVwKGlicmFfc3VicmVnaW9uLCAyKSwKICAgIHJhbmRvbV9lZmZlY3QgPSByZXAoYyhUUlVFLCBGQUxTRSksIGVhY2ggPSBucm93KHBlcmYpIC8gMiksCiAgICBhcy5kYXRhLmZyYW1lKHBlcmYpCiAgKQp9KQoKIysgcGxvdC1hdWMtZGlzdCwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGZpZy53aWR0aCA9IDMuNSwgZmlnLmhlaWdodCA9IDcKYXVjZGlzdCA8LSBkYXRhLmZyYW1lKAogIHBlcmZbYygidGF4b24iLCAiaWJyYV9zdWJyZWdpb24iLCAiQVVDIildLAogIGBHZW9ncmFwaGljIChrbSlgPSBkaXN0c1thcy5jaGFyYWN0ZXIocGVyZiRpYnJhX3N1YnJlZ2lvbildLAogIEVudmlyb25tZW50YWwgPSBrbGRpc3RzW2FzLmNoYXJhY3RlcihwZXJmJGlicmFfc3VicmVnaW9uKV0sCiAgQ29tbXVuaXR5ID0gY29tbXVuaXR5X2Rpc3RbYXMuY2hhcmFjdGVyKHBlcmYkaWJyYV9zdWJyZWdpb24pXSwKICAiRHVtbXkiID0gIkR1bW15IiwKICBjaGVjay5uYW1lcyA9IEZBTFNFCikKCmF1Y2Rpc3QgPC0gZ2F0aGVyKAogIGF1Y2Rpc3QsICJkaXN0YW5jZSIsICJ2YWx1ZSIsIGBHZW9ncmFwaGljIChrbSlgLCBFbnZpcm9ubWVudGFsLCBDb21tdW5pdHkKKQoKYXVjZGlzdCA8LSBuYS5vbWl0KGF1Y2Rpc3QpCgphdWNkaXN0bWVhbiA8LSBzdW1tYXJpc2UoCiAgZ3JvdXBfYnkoYXVjZGlzdCwgaWJyYV9zdWJyZWdpb24sIGRpc3RhbmNlKSwKICBtZWFuYXVjID0gbWVhbihBVUMpLCB2YWx1ZSA9IG1lYW4odmFsdWUpCikKCmF1Y2Rpc3RwbG90IDwtIGdncGxvdChhdWNkaXN0KSArCiAgYWVzKEFVQywgdmFsdWUpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAuNSwgY29sb3IgPSAiZ3JleSIsIHNpemUgPSAxLjUpICsKICBnZW9tX3BvaW50KGFscGhhPS4xKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyhtZWFuYXVjKSwgZGF0YSA9IGF1Y2Rpc3RtZWFuLCBzaXplID0gMiwgc2hhcGUgPSAyMSwgZmlsbCA9ICJ3aGl0ZSIKICApICsKICB4bGltKDAsIDEpICsKICB5bGFiKCJEaXN0YW5jZSIpICsKICBmYWNldF9ncmlkKGRpc3RhbmNlIH4gLiwgc2NhbGVzID0gImZyZWVfeSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKQogICkKCmF1Y2J3IDwtIGdncGxvdChhdWNkaXN0KSArCiAgYWVzKHggPSBEdW1teSwgeSA9IEFVQykgKwogIGdlb21fYm94cGxvdChmaWxsID0gImdyZXkiKSArCiAgY29vcmRfZmxpcCgpICsKICBmYWNldF9ncmlkKER1bW15IH4gLikgKwogIHlsaW0oMCwgMSkgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gIjAuOTUiKSArCiAgeGxhYigiRHVtbXkiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAidHJhbnNwYXJlbnQiKSwKICAgIGF4aXMudGV4dC55ICA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJ0cmFuc3BhcmVudCIpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9saW5lKGNvbG9yID0gInRyYW5zcGFyZW50IiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gInRyYW5zcGFyZW50IiksCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCA1LjUsIDUuNSwgNS41KQogICkKCmdyaWQuYXJyYW5nZShhdWNkaXN0cGxvdCwgYXVjYncsIG5jb2wgPSAxLCBoZWlnaHRzID0gYyguODYsIC4xNCkpCgojKyBwbG90LWF1YywgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGZpZy53aWR0aCA9IDExCmdncGxvdCgKICB0cmFuc2Zvcm0oCiAgICBzdWJzZXQocGVyZiwgaWJyYV9zdWJyZWdpb24gIT0gIkdyZWF0ZXIgR3JhbXBpYW5zIiAmICFyYW5kb21fZWZmZWN0KSwKICAgIGlicmFfc3VicmVnaW9uID0gZmFjdG9yKAogICAgICBpYnJhX3N1YnJlZ2lvbiwgbmFtZXMoc29ydCh0YXBwbHkoQVVDLCBpYnJhX3N1YnJlZ2lvbiwgbWVkaWFuKSkpCiAgICApCiAgKQopICsKYWVzKEFVQykgKyBnZW9tX2hpc3RvZ3JhbSgpICsgZmFjZXRfd3JhcCh+aWJyYV9zdWJyZWdpb24sIDMpICsKeGxhYigiQVVDIikgKwp5bGFiKCJOby4gb2YgdGF4YSIpICsKZ2d0aXRsZSgKICBwYXN0ZSgKICAgICJBcmVhIFVuZGVyIFJlY2VpdmVyIE9wZXJhdG9yIEN1cnZlIGZvciB0YXhhIHdpdGhpbiBJQlJBIHN1YnJlZ2lvbnMgb2YiLAogICAgIlNvdXRoZWFzdCBBdXN0cmFsaWEiCiAgKQopCgojKyBwbG90LXByZWQtaW5mbywgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGZpZy53aWR0aCA9IDExCmdncGxvdCgKICB0cmFuc2Zvcm0oCiAgICBzdWJzZXQocGVyZiwgaWJyYV9zdWJyZWdpb24gIT0gIkdyZWF0ZXIgR3JhbXBpYW5zIiAmICFyYW5kb21fZWZmZWN0KSwKICAgIGlicmFfc3VicmVnaW9uID0gZmFjdG9yKAogICAgICBpYnJhX3N1YnJlZ2lvbiwKICAgICAgbmFtZXMoc29ydCh0YXBwbHkobWVhbl9wcmVkaWN0aXZlX2luZm8sIGlicmFfc3VicmVnaW9uLCBtZWRpYW4pKSkKICAgICkKICApCikgKwphZXMobWVhbl9wcmVkaWN0aXZlX2luZm8pICsgZ2VvbV9oaXN0b2dyYW0oKSArIGZhY2V0X3dyYXAofmlicmFfc3VicmVnaW9uLCAzKSArCnhsYWIoIk1lYW4gUHJlZGljdGl2ZSBJbmZvcm1hdGlvbiIpICsKeWxhYigiTm8uIG9mIHRheGEiKSArCmdndGl0bGUoCiAgcGFzdGUoCiAgICAiTWVhbiBQcmVkaWN0aXZlIEluZm9ybWF0aW9uIGZvciB0YXhhIHdpdGhpbiBJQlJBIHN1YnJlZ2lvbnMgb2YiLAogICAgIlNvdXRoZWFzdCBBdXN0cmFsaWEiCiAgKQopCgojKyBwbG90LWdyYW1waWFucy10YXhhLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZmlnLndpZHRoID0gMTEKZ2dwbG90KAogIHRyYW5zZm9ybSgKICAgIHN1YnNldChwZXJmLCB0YXhvbiAlaW4lIG1kZyR0YXhvbiAmIHJhbmRvbV9lZmZlY3QpLAogICAgdGF4b24gPSBmYWN0b3IoCiAgICAgIHRheG9uLAogICAgICBuYW1lcygKICAgICAgICBzb3J0KAogICAgICAgICAgdGFwcGx5KAogICAgICAgICAgICBBVUNbaWJyYV9zdWJyZWdpb24gPT0gIkdyZWF0ZXIgR3JhbXBpYW5zIl0sCiAgICAgICAgICAgIHRheG9uW2licmFfc3VicmVnaW9uID09ICJHcmVhdGVyIEdyYW1waWFucyJdLAogICAgICAgICAgICBtZWRpYW4KICAgICAgICAgICkKICAgICAgICApCiAgICAgICkKICAgICkKICApCikgKwphZXMoCiAgQVVDLAogIG1lYW5fcHJlZGljdGl2ZV9pbmZvLAogIGNvbCA9IGlmZWxzZSgKICAgIGlicmFfc3VicmVnaW9uID09ICJHcmVhdGVyIEdyYW1waWFucyIsCiAgICAiR3JhbXBpYW5zIiwKICAgICJPdGhlciBSZWdpb24iCiAgKQopICsKZ2VvbV9wb2ludCgpICsKZmFjZXRfd3JhcCh+dGF4b24sIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4oNDApKSArCmxhYnMoY29sID0gTlVMTCkgKwp4bGFiKCJBVUMiKSArCnlsYWIoIk1lYW4gUHJlZGljdGl2ZSBJbmZvcm1hdGlvbiIpICsKZ2d0aXRsZSgKICBwYXN0ZSgKICAgICIiCiAgKQopICsKdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCgojKyBtb2RlbGF1YywgcmVzdWx0cyA9ICJoaWRlIiwgbWVzc2FnZSA9IEZBTFNFCm1vZGVsX2F1YyA8LSBzdGFuX2dsbWVyKAogIChBVUMgLSAuMDAxKSB+IHZhbHVlICsgKDEgfCB0YXhvbikgKyAoMSB8IGlicmFfc3VicmVnaW9uKSwKICBmYW1pbHkgPSBtZ2N2OjpiZXRhciwKICBpdGVyID0gMTAwMCwgY2hhaW5zID0gMywKICBkYXRhID0gYXVjZGlzdCwKICBzdWJzZXQgPSBpYnJhX3N1YnJlZ2lvbiAhPSAiR3JlYXRlciBHcmFtcGlhbnMiICYgZGlzdGFuY2UgPT0gIkdlb2dyYXBoaWMgKGttKSIKKQoKIysgc3VtbWFyeV9hdWMKc3VtbWFyeShtb2RlbF9hdWMsIHJlZ2V4X3BhcnMgPSAiXlteYl0iLCBwcm9icyA9IGMoLjAyNSwgLjk3NSkpCg==