Mendelian Randomization

Import Exposure

library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     ── Conflicts ──────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(TwoSampleMR)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
TwoSampleMR version 0.6.11 

  [>] New authentication requirements: https://mrcieu.github.io/ieugwasr/articles/guide.html#authentication.
  [>] Major upgrades to our servers completed to improve service and stability.
  [>] We need your help to shape our emerging roadmap!
      Please take 2 minutes to give us feedback -
      https://forms.office.com/e/eSr7EFAfCG

Warning:
You are running an old version of the TwoSampleMR package.
This version:   0.6.11
Latest version: 0.6.30
Please consider updating using remotes::install_github('MRCIEU/TwoSampleMR')
library(LDlinkR)      # LD and proxy snps
library(ieugwasr)
OpenGWAS updates:
  Date: 2024-05-17
  [>] OpenGWAS is growing!
  [>] Please take 2 minutes to give us feedback -
  [>] It will help directly shape our emerging roadmap
  [>] https://forms.office.com/e/eSr7EFAfCG

Attaching package: ‘ieugwasr’

The following object is masked from ‘package:TwoSampleMR’:

    ld_matrix
library(fixtuRes)
exposure_path_A2 = "gwas_resources/A2EUR_GRCH38.tsv.gz"
exposure_c1 <- read_tsv(exposure_path_A2,comment = "##", 
                        col_select = c(1,2,3,4,5,6,7,8,9,14,15))
colnames(exposure_c1)<- c("CHR","POS","effect_allele.exposure","other_allele.exposure","SNP","N","beta.exposure","se.exposure","pval","eaf.exposure","rsid")
exposure_c1$exposure <- rep(c("A2_severe_respiratory_COVID19"),times=nrow(exposure_c1));
clump_id<- "a2grch"
#calculate z value
exposure_c1$z.exposure <- exposure_c1$beta.exposure/exposure_c1$se.exposure;
exposure_c1$id.exposure <- rep(c(clump_id),times=nrow(exposure_c1));


exposure_dat1 <- filter(exposure_c1, pval < 5e-8)
exposure_clump1 <-ld_clump(
    #dplyr::tibble(rsid=exposure_c1$rsid, pval=exposure_c1$pval, id=exposure_c1$trait_id),
    dat = exposure_dat1,
    plink_bin = genetics.binaRies::get_plink_binary(),
    bfile = "1kgv3/EUR"
    
)

write_csv(exposure_clump1, "data/exposure_A2GRCH38.csv", append = FALSE)
exposure_path_B2 = "gwas_resources/B2EUR_GRCH38.tsv.gz"
exposure_c2 <- read_tsv(exposure_path_B2,comment = "##", 
                        col_select = c(1,2,3,4,5,6,7,8,9,14,15))
colnames(exposure_c2)<- c("CHR","POS","effect_allele.exposure","other_allele.exposure","SNP","N","beta.exposure","se.exposure","pval","eaf.exposure","rsid")
exposure_c2$exposure <- rep(c("B2_hospitalized_COVID19"),times=nrow(exposure_c2));
clump_id<- "b2grch"
#calculate z value
exposure_c2$z.exposure <- exposure_c2$beta.exposure/exposure_c2$se.exposure;
exposure_c2$id.exposure <- rep(c(clump_id),times=nrow(exposure_c2));


exposure_dat2 <- filter(exposure_c2, pval < 5e-8)
exposure_clump2 <-ld_clump(
    #dplyr::tibble(rsid=exposure_c1$rsid, pval=exposure_c1$pval, id=exposure_c1$trait_id),
    dat = exposure_dat2,
    plink_bin = genetics.binaRies::get_plink_binary(),
    bfile = "1kgv3/EUR"
    
)

write_csv(exposure_clump2, "data/exposure_B2GRCH38.csv", append = FALSE)
exposure_path_C2 = "gwas_resources/C2EUR_GRCH38.tsv.gz"
exposure_c3 <- read_tsv(exposure_path_C2,comment = "##", 
                        col_select = c(1,2,3,4,5,6,7,8,9,14,15))
colnames(exposure_c3)<- c("CHR","POS","effect_allele.exposure","other_allele.exposure","SNP","N","beta.exposure","se.exposure","pval","eaf.exposure","rsid")
exposure_c3$exposure <- rep(c("C2_COVID19"),times=nrow(exposure_c3));
clump_id<- "c2grch"
#calculate z value
exposure_c3$z.exposure <- exposure_c3$beta.exposure/exposure_c3$se.exposure;
exposure_c3$id.exposure <- rep(c(clump_id),times=nrow(exposure_c3));


exposure_dat3 <- filter(exposure_c3, pval < 5e-8)
exposure_clump3 <-ld_clump(
    #dplyr::tibble(rsid=exposure_c1$rsid, pval=exposure_c1$pval, id=exposure_c1$trait_id),
    dat = exposure_dat3,
    plink_bin = genetics.binaRies::get_plink_binary(),
    bfile = "1kgv3/EUR"
    
)

write_csv(exposure_clump3, "data/exposure_C2GRCH38.csv", append = FALSE)

Import Outcome

outcome1 <- read_tsv('gwas_resources/AKIJiangL2021h.tsv.gz', col_select = c(2,3,4,5,6,7,11,12,18, 21,22))
colnames(outcome1)<- c("rsid","CHR","POS","other_allele.outcome","effect_allele.outcome","beta.outcome","eaf.outcome","code","N","se.outcome","pval.outcome")
outcome1$outcome <- rep(c("PheCode 585.1"),times=nrow(outcome1));
clump_id <- "jiangl2021";
outcome1$id.outcome <- rep(c(clump_id),times=nrow(outcome1));
exposure_snps <- read_csv("data/exposure_A2GRCH38.csv") 
#filter outcome on SNPs in the exposure
outcome_clumped <- filter(outcome1, rsid %in% exposure_snps$rsid)
#harmonise data
mr_dat <- harmonise_data(dplyr::tibble(SNP=exposure_snps$rsid, beta.exposure=exposure_snps$beta.exposure, se.exposure=exposure_snps$se.exposure, effect_allele.exposure = exposure_snps$effect_allele.exposure, other_allele.exposure = exposure_snps$other_allele.exposure,eaf.exposure = exposure_snps$eaf.exposure, id.exposure = exposure_snps$id.exposure, exposure = exposure_snps$exposure, pval.exposure = exposure_snps$pval), dplyr::tibble(SNP=outcome_clumped$rsid, beta.outcome=outcome_clumped$beta.outcome, se.outcome=outcome_clumped$se.outcome, effect_allele.outcome = outcome_clumped$effect_allele.outcome, other_allele.outcome = outcome_clumped$other_allele.outcome,eaf.outcome = outcome_clumped$eaf.outcome , outcome = outcome_clumped$outcome, id.outcome = outcome_clumped$id.outcome, pval.outcome= outcome_clumped$pval.outcome), action = 2) %>% 
  filter(pval.exposure < 5e-8 & SNP != "rs17885848")
write_csv(mr_dat, "harmonized/harmonized_A2_JiangL")
outcome2 <- read_tsv('gwas_resources/DouvilleNJModel1h.tsv.gz', col_select = c(1,2,3,4,5,6,7,8,9,13))
colnames(outcome2)<- c("CHR","POS","effect_allele.outcome","other_allele.outcome","beta.outcome","se.outcome","eaf.outcome","pval.outcome","rsid","N")
outcome2$outcome <- rep(c("Sepsis AKI"),times=nrow(outcome2));
clump_id <- "DouvilleNJ2025";
outcome2$id.outcome <- rep(c(clump_id),times=nrow(outcome2));


exposure_snps <- read_csv("data/exposure_A2GRCH38.csv") 
#filter outcome on SNPs in the exposure
outcome_clumped <- filter(outcome2, rsid %in% exposure_snps$rsid)
#harmonise data
mr_dat <- harmonise_data(dplyr::tibble(SNP=exposure_snps$rsid, beta.exposure=exposure_snps$beta.exposure, se.exposure=exposure_snps$se.exposure, effect_allele.exposure = exposure_snps$effect_allele.exposure, other_allele.exposure = exposure_snps$other_allele.exposure,eaf.exposure = exposure_snps$eaf.exposure, id.exposure = exposure_snps$id.exposure, exposure = exposure_snps$exposure, pval.exposure = exposure_snps$pval), dplyr::tibble(SNP=outcome_clumped$rsid, beta.outcome=outcome_clumped$beta.outcome, se.outcome=outcome_clumped$se.outcome, effect_allele.outcome = outcome_clumped$effect_allele.outcome, other_allele.outcome = outcome_clumped$other_allele.outcome,eaf.outcome = outcome_clumped$eaf.outcome , outcome = outcome_clumped$outcome, id.outcome = outcome_clumped$id.outcome, pval.outcome= outcome_clumped$pval.outcome), action = 2) %>% 
  filter(pval.exposure < 5e-6)
write_csv(mr_dat, "harmonized/harmonized_A2_Douville")
outcome3 <- read_tsv('gwas_resources/AKIVermaAh.tsv.gz', col_select = c(1,2,3,4,5,6,7,8,9,13))
colnames(outcome3)<- c("CHR","POS","effect_allele.outcome","other_allele.outcome","oddsratio.outcome","se.outcome","eaf.outcome","pval.outcome","rsid","N")
outcome3$outcome <- rep(c("PheCode 585.1 (Verma)"),times=nrow(outcome3));
clump_id <- "vermaA2024";
outcome3$id.outcome <- rep(c(clump_id),times=nrow(outcome3));
outcome3$beta.outcome <- log(outcome3$oddsratio.outcome)


exposure_snps <- read_csv("data/exposure_A2GRCH38.csv") 
#filter outcome on SNPs in the exposure
outcome_clumped <- filter(outcome3, rsid %in% exposure_snps$rsid)
#harmonise data
mr_dat <- harmonise_data(dplyr::tibble(SNP=exposure_snps$rsid, beta.exposure=exposure_snps$beta.exposure, se.exposure=exposure_snps$se.exposure, effect_allele.exposure = exposure_snps$effect_allele.exposure, other_allele.exposure = exposure_snps$other_allele.exposure,eaf.exposure = exposure_snps$eaf.exposure, id.exposure = exposure_snps$id.exposure, exposure = exposure_snps$exposure, pval.exposure = exposure_snps$pval), dplyr::tibble(SNP=outcome_clumped$rsid, beta.outcome=outcome_clumped$beta.outcome, se.outcome=outcome_clumped$se.outcome, effect_allele.outcome = outcome_clumped$effect_allele.outcome, other_allele.outcome = outcome_clumped$other_allele.outcome,eaf.outcome = outcome_clumped$eaf.outcome , outcome = outcome_clumped$outcome, id.outcome = outcome_clumped$id.outcome, pval.outcome= outcome_clumped$pval.outcome), action = 2) %>% 
  filter(pval.exposure < 5e-8)

write_csv(mr_dat, "harmonized/harmonized_A2_VermaA")

MR Analysis

library(tidyverse)    # Data wrangling 
library(knitr)
library(TwoSampleMR)  # MR 
library(gt)
library(LDlinkR)      # LD and proxy snps
library(RadialMR)     # Radial MR sensetivity analysis 
library(phenoscanner)

Dataset 1

mr_dat <- read_csv("harmonized/harmonized_A2_JiangL")
Rows: 27 Columns: 24── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (9): SNP, effect_allele.exposure, other_allele.exposure, effect_allele.outcome, other_allele.outcome, id.outcome, outcome, id.e...
dbl (10): beta.exposure, beta.outcome, eaf.exposure, eaf.outcome, se.outcome, pval.outcome, se.exposure, pval.exposure, action, SNP_...
lgl  (5): remove, palindromic, ambiguous, mr_keep, samplesize.outcome
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
mr_pleiotrophy_result <- mr_pleiotropy_test(mr_dat)
View(mr_pleiotrophy_result)
mr_res <- mr(mr_dat, method_list = c(
  "mr_two_sample_ml",  "mr_egger_regression", 
  "mr_simple_median", "mr_weighted_median", 
  "mr_ivw_fe", "mr_ivw_mre",
  "mr_simple_mode", "mr_weighted_mode"
  ))
Analysing 'a2grch' on 'jiangl2021'
res_single <- mr_singlesnp(mr_dat, all_method = c("mr_ivw_fe", "mr_egger_regression", "mr_weighted_median", "mr_weighted_mode")) %>% as_tibble()
View(res_single)
odd <- generate_odds_ratios(mr_res)
print("Finished Analyzing")
[1] "Finished Analyzing"
write.csv(odd,"results/A2/jiangla2_oddsratios.csv")
write.csv(res_single,"results/A2/jiangla2_res_single.csv")
scatter_p <- mr_scatter_plot(mr_res, mr_dat) 
scatter_out_p <- scatter_p[[1]] + theme_bw() + 
  guides(color=guide_legend(ncol =1)) + 
  theme(
    text = element_text(size = 8), 
  )

scatter_out_p
ggsave("results/A2/scatterplotA2JiangL.png", plot = scatter_out_p, units = 'in', height = 4, width = 9)

forrest_p <- mr_forest_plot(res_single)
forrest_p[[1]]
ggsave("results/A2/forrestplotA2JiangL.png", plot =forrest_p[[1]] + theme(text = element_text(size = 8)), units = 'in', height = 9, width = 9)


res_loo <- mr_leaveoneout(mr_dat, method = mr_ivw_fe) %>% as_tibble()
loo_p <- mr_leaveoneout_plot(res_loo)
loo_p[[1]]
ggsave("results/A2/looA2JiangL.png",plot = loo_p[[1]], units = 'in', height = 9, width = 9)


funnel_p <- mr_funnel_plot(res_single)
funnel_out_p <- funnel_p[[1]] + theme_bw() + 
  guides(color=guide_legend(ncol =1)) + 
  theme(
    text = element_text(size = 8), 
  )

funnel_out_p
ggsave("results/A2/funnelplotA2JiangL.png", plot = funnel_out_p, units = 'in', height = 4, width = 9)

Dataset 2


mr_dat <- read_csv("harmonized/harmonized_A2_Douville")
Rows: 28 Columns: 24── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (9): SNP, effect_allele.exposure, other_allele.exposure, effect_allele.outcome, other_allele.outcome, id.outcome, outcome, id.e...
dbl (10): beta.exposure, beta.outcome, eaf.exposure, eaf.outcome, se.outcome, pval.outcome, se.exposure, pval.exposure, action, SNP_...
lgl  (5): remove, palindromic, ambiguous, mr_keep, samplesize.outcome
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
mr_res <- mr(mr_dat, method_list = c(
  "mr_two_sample_ml",  "mr_egger_regression", 
  "mr_simple_median", "mr_weighted_median", 
  "mr_ivw_fe", "mr_ivw_mre",
  "mr_simple_mode", "mr_weighted_mode"
  ))
Analysing 'a2grch' on 'DouvilleNJ2025'
res_single <- mr_singlesnp(mr_dat, all_method = c("mr_ivw_fe", "mr_egger_regression", "mr_weighted_median", "mr_weighted_mode")) %>% as_tibble()
View(res_single)
odd <- generate_odds_ratios(mr_res)
print("Finished Analyzing")
[1] "Finished Analyzing"
write.csv(odd,"results/A2/douvillea2_oddsratios.csv")
write.csv(res_single,"results/A2/douvillea2_res_single.csv")

scatter_p <- mr_scatter_plot(mr_res, mr_dat) 
scatter_out_p <- scatter_p[[1]] + theme_bw() + 
  guides(color=guide_legend(ncol =1)) + 
  theme(
    text = element_text(size = 8), 
  )

scatter_out_p
ggsave("results/A2/scatterplotA2Douville.png", plot = scatter_out_p, units = 'in', height = 4, width = 9)

forrest_p <- mr_forest_plot(res_single)
forrest_p[[1]]
ggsave("results/A2/forrestplotA2Douville.png", plot =forrest_p[[1]] + theme(text = element_text(size = 8)), units = 'in', height = 9, width = 9)


res_loo <- mr_leaveoneout(mr_dat, method = mr_ivw_fe) %>% as_tibble()
loo_p <- mr_leaveoneout_plot(res_loo)
loo_p[[1]]
ggsave("results/A2/looA2Douville.png",plot = loo_p[[1]], units = 'in', height = 9, width = 9)

funnel_p <- mr_funnel_plot(res_single)
funnel_out_p <- funnel_p[[1]] + theme_bw() + 
  guides(color=guide_legend(ncol =1)) + 
  theme(
    text = element_text(size = 8), 
  )

funnel_out_p
ggsave("results/A2/funnelplotA2Douville.png", plot = funnel_out_p, units = 'in', height = 4, width = 9)

library(tidyverse)    # Data wrangling 
library(TwoSampleMR)  # MR 
library(ggman)
tc_path = "gwas_resources/DouvilleNJModel1h.tsv.gz"
tc_ss <- read_tsv(tc_path)
Rows: 14248310 Columns: 21── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr  (6): effect_allele, other_allele, rsid, SNPID, hm_coordinate_conversion, variant_id
dbl (15): chromosome, base_pair_location, beta, standard_error, effect_allele_frequency, p_value, effect_allele_count, imputationInf...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Filter on p < 0.5 to reduce compute
ggman(filter(tc_ss, p_value < 0.5 & p_value > 1e-100), snp = "SNPID", bp = "base_pair_location", chrom = "chromosome", pvalue = "p_value", relative.positions = TRUE) + 
  theme_classic()

LS0tCnRpdGxlOiAiTVItQW5hbHlzaXMgMi0yNi0yMDI2IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIE1lbmRlbGlhbiBSYW5kb21pemF0aW9uCgojIyBJbXBvcnQgRXhwb3N1cmUKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShUd29TYW1wbGVNUikKbGlicmFyeShMRGxpbmtSKSAgICAgICMgTEQgYW5kIHByb3h5IHNucHMKbGlicmFyeShpZXVnd2FzcikKbGlicmFyeShmaXh0dVJlcykKYGBgCgpgYGB7cixldmFsPUZBTFNFfQoKZXhwb3N1cmVfcGF0aF9BMiA9ICJnd2FzX3Jlc291cmNlcy9BMkVVUl9HUkNIMzgudHN2Lmd6IgpleHBvc3VyZV9jMSA8LSByZWFkX3RzdihleHBvc3VyZV9wYXRoX0EyLGNvbW1lbnQgPSAiIyMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29sX3NlbGVjdCA9IGMoMSwyLDMsNCw1LDYsNyw4LDksMTQsMTUpKQpjb2xuYW1lcyhleHBvc3VyZV9jMSk8LSBjKCJDSFIiLCJQT1MiLCJlZmZlY3RfYWxsZWxlLmV4cG9zdXJlIiwib3RoZXJfYWxsZWxlLmV4cG9zdXJlIiwiU05QIiwiTiIsImJldGEuZXhwb3N1cmUiLCJzZS5leHBvc3VyZSIsInB2YWwiLCJlYWYuZXhwb3N1cmUiLCJyc2lkIikKZXhwb3N1cmVfYzEkZXhwb3N1cmUgPC0gcmVwKGMoIkEyX3NldmVyZV9yZXNwaXJhdG9yeV9DT1ZJRDE5IiksdGltZXM9bnJvdyhleHBvc3VyZV9jMSkpOwpjbHVtcF9pZDwtICJhMmdyY2giCiNjYWxjdWxhdGUgeiB2YWx1ZQpleHBvc3VyZV9jMSR6LmV4cG9zdXJlIDwtIGV4cG9zdXJlX2MxJGJldGEuZXhwb3N1cmUvZXhwb3N1cmVfYzEkc2UuZXhwb3N1cmU7CmV4cG9zdXJlX2MxJGlkLmV4cG9zdXJlIDwtIHJlcChjKGNsdW1wX2lkKSx0aW1lcz1ucm93KGV4cG9zdXJlX2MxKSk7CgoKZXhwb3N1cmVfZGF0MSA8LSBmaWx0ZXIoZXhwb3N1cmVfYzEsIHB2YWwgPCA1ZS04KQpleHBvc3VyZV9jbHVtcDEgPC1sZF9jbHVtcCgKICAgICNkcGx5cjo6dGliYmxlKHJzaWQ9ZXhwb3N1cmVfYzEkcnNpZCwgcHZhbD1leHBvc3VyZV9jMSRwdmFsLCBpZD1leHBvc3VyZV9jMSR0cmFpdF9pZCksCiAgICBkYXQgPSBleHBvc3VyZV9kYXQxLAogICAgcGxpbmtfYmluID0gZ2VuZXRpY3MuYmluYVJpZXM6OmdldF9wbGlua19iaW5hcnkoKSwKICAgIGJmaWxlID0gIjFrZ3YzL0VVUiIKICAgIAopCgp3cml0ZV9jc3YoZXhwb3N1cmVfY2x1bXAxLCAiZGF0YS9leHBvc3VyZV9BMkdSQ0gzOC5jc3YiLCBhcHBlbmQgPSBGQUxTRSkKCgpgYGAKCmBgYHtyLGV2YWw9RkFMU0V9CmV4cG9zdXJlX3BhdGhfQjIgPSAiZ3dhc19yZXNvdXJjZXMvQjJFVVJfR1JDSDM4LnRzdi5neiIKZXhwb3N1cmVfYzIgPC0gcmVhZF90c3YoZXhwb3N1cmVfcGF0aF9CMixjb21tZW50ID0gIiMjIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbF9zZWxlY3QgPSBjKDEsMiwzLDQsNSw2LDcsOCw5LDE0LDE1KSkKY29sbmFtZXMoZXhwb3N1cmVfYzIpPC0gYygiQ0hSIiwiUE9TIiwiZWZmZWN0X2FsbGVsZS5leHBvc3VyZSIsIm90aGVyX2FsbGVsZS5leHBvc3VyZSIsIlNOUCIsIk4iLCJiZXRhLmV4cG9zdXJlIiwic2UuZXhwb3N1cmUiLCJwdmFsIiwiZWFmLmV4cG9zdXJlIiwicnNpZCIpCmV4cG9zdXJlX2MyJGV4cG9zdXJlIDwtIHJlcChjKCJCMl9ob3NwaXRhbGl6ZWRfQ09WSUQxOSIpLHRpbWVzPW5yb3coZXhwb3N1cmVfYzIpKTsKY2x1bXBfaWQ8LSAiYjJncmNoIgojY2FsY3VsYXRlIHogdmFsdWUKZXhwb3N1cmVfYzIkei5leHBvc3VyZSA8LSBleHBvc3VyZV9jMiRiZXRhLmV4cG9zdXJlL2V4cG9zdXJlX2MyJHNlLmV4cG9zdXJlOwpleHBvc3VyZV9jMiRpZC5leHBvc3VyZSA8LSByZXAoYyhjbHVtcF9pZCksdGltZXM9bnJvdyhleHBvc3VyZV9jMikpOwoKCmV4cG9zdXJlX2RhdDIgPC0gZmlsdGVyKGV4cG9zdXJlX2MyLCBwdmFsIDwgNWUtOCkKZXhwb3N1cmVfY2x1bXAyIDwtbGRfY2x1bXAoCiAgICAjZHBseXI6OnRpYmJsZShyc2lkPWV4cG9zdXJlX2MxJHJzaWQsIHB2YWw9ZXhwb3N1cmVfYzEkcHZhbCwgaWQ9ZXhwb3N1cmVfYzEkdHJhaXRfaWQpLAogICAgZGF0ID0gZXhwb3N1cmVfZGF0MiwKICAgIHBsaW5rX2JpbiA9IGdlbmV0aWNzLmJpbmFSaWVzOjpnZXRfcGxpbmtfYmluYXJ5KCksCiAgICBiZmlsZSA9ICIxa2d2My9FVVIiCiAgICAKKQoKd3JpdGVfY3N2KGV4cG9zdXJlX2NsdW1wMiwgImRhdGEvZXhwb3N1cmVfQjJHUkNIMzguY3N2IiwgYXBwZW5kID0gRkFMU0UpCmBgYAoKYGBge3IsZXZhbD1GQUxTRX0KZXhwb3N1cmVfcGF0aF9DMiA9ICJnd2FzX3Jlc291cmNlcy9DMkVVUl9HUkNIMzgudHN2Lmd6IgpleHBvc3VyZV9jMyA8LSByZWFkX3RzdihleHBvc3VyZV9wYXRoX0MyLGNvbW1lbnQgPSAiIyMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29sX3NlbGVjdCA9IGMoMSwyLDMsNCw1LDYsNyw4LDksMTQsMTUpKQpjb2xuYW1lcyhleHBvc3VyZV9jMyk8LSBjKCJDSFIiLCJQT1MiLCJlZmZlY3RfYWxsZWxlLmV4cG9zdXJlIiwib3RoZXJfYWxsZWxlLmV4cG9zdXJlIiwiU05QIiwiTiIsImJldGEuZXhwb3N1cmUiLCJzZS5leHBvc3VyZSIsInB2YWwiLCJlYWYuZXhwb3N1cmUiLCJyc2lkIikKZXhwb3N1cmVfYzMkZXhwb3N1cmUgPC0gcmVwKGMoIkMyX0NPVklEMTkiKSx0aW1lcz1ucm93KGV4cG9zdXJlX2MzKSk7CmNsdW1wX2lkPC0gImMyZ3JjaCIKI2NhbGN1bGF0ZSB6IHZhbHVlCmV4cG9zdXJlX2MzJHouZXhwb3N1cmUgPC0gZXhwb3N1cmVfYzMkYmV0YS5leHBvc3VyZS9leHBvc3VyZV9jMyRzZS5leHBvc3VyZTsKZXhwb3N1cmVfYzMkaWQuZXhwb3N1cmUgPC0gcmVwKGMoY2x1bXBfaWQpLHRpbWVzPW5yb3coZXhwb3N1cmVfYzMpKTsKCgpleHBvc3VyZV9kYXQzIDwtIGZpbHRlcihleHBvc3VyZV9jMywgcHZhbCA8IDVlLTgpCmV4cG9zdXJlX2NsdW1wMyA8LWxkX2NsdW1wKAogICAgI2RwbHlyOjp0aWJibGUocnNpZD1leHBvc3VyZV9jMSRyc2lkLCBwdmFsPWV4cG9zdXJlX2MxJHB2YWwsIGlkPWV4cG9zdXJlX2MxJHRyYWl0X2lkKSwKICAgIGRhdCA9IGV4cG9zdXJlX2RhdDMsCiAgICBwbGlua19iaW4gPSBnZW5ldGljcy5iaW5hUmllczo6Z2V0X3BsaW5rX2JpbmFyeSgpLAogICAgYmZpbGUgPSAiMWtndjMvRVVSIgogICAgCikKCndyaXRlX2NzdihleHBvc3VyZV9jbHVtcDMsICJkYXRhL2V4cG9zdXJlX0MyR1JDSDM4LmNzdiIsIGFwcGVuZCA9IEZBTFNFKQpgYGAKCiMjIEltcG9ydCBPdXRjb21lCgpgYGB7cixldmFsPUZBTFNFfQpvdXRjb21lMSA8LSByZWFkX3RzdignZ3dhc19yZXNvdXJjZXMvQUtJSmlhbmdMMjAyMWgudHN2Lmd6JywgY29sX3NlbGVjdCA9IGMoMiwzLDQsNSw2LDcsMTEsMTIsMTgsIDIxLDIyKSkKY29sbmFtZXMob3V0Y29tZTEpPC0gYygicnNpZCIsIkNIUiIsIlBPUyIsIm90aGVyX2FsbGVsZS5vdXRjb21lIiwiZWZmZWN0X2FsbGVsZS5vdXRjb21lIiwiYmV0YS5vdXRjb21lIiwiZWFmLm91dGNvbWUiLCJjb2RlIiwiTiIsInNlLm91dGNvbWUiLCJwdmFsLm91dGNvbWUiKQpvdXRjb21lMSRvdXRjb21lIDwtIHJlcChjKCJQaGVDb2RlIDU4NS4xIiksdGltZXM9bnJvdyhvdXRjb21lMSkpOwpjbHVtcF9pZCA8LSAiamlhbmdsMjAyMSI7Cm91dGNvbWUxJGlkLm91dGNvbWUgPC0gcmVwKGMoY2x1bXBfaWQpLHRpbWVzPW5yb3cob3V0Y29tZTEpKTsKYGBgCgpgYGB7cixldmFsPUZBTFNFfQpleHBvc3VyZV9zbnBzIDwtIHJlYWRfY3N2KCJkYXRhL2V4cG9zdXJlX0EyR1JDSDM4LmNzdiIpIAojZmlsdGVyIG91dGNvbWUgb24gU05QcyBpbiB0aGUgZXhwb3N1cmUKb3V0Y29tZV9jbHVtcGVkIDwtIGZpbHRlcihvdXRjb21lMSwgcnNpZCAlaW4lIGV4cG9zdXJlX3NucHMkcnNpZCkKI2hhcm1vbmlzZSBkYXRhCm1yX2RhdCA8LSBoYXJtb25pc2VfZGF0YShkcGx5cjo6dGliYmxlKFNOUD1leHBvc3VyZV9zbnBzJHJzaWQsIGJldGEuZXhwb3N1cmU9ZXhwb3N1cmVfc25wcyRiZXRhLmV4cG9zdXJlLCBzZS5leHBvc3VyZT1leHBvc3VyZV9zbnBzJHNlLmV4cG9zdXJlLCBlZmZlY3RfYWxsZWxlLmV4cG9zdXJlID0gZXhwb3N1cmVfc25wcyRlZmZlY3RfYWxsZWxlLmV4cG9zdXJlLCBvdGhlcl9hbGxlbGUuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJG90aGVyX2FsbGVsZS5leHBvc3VyZSxlYWYuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJGVhZi5leHBvc3VyZSwgaWQuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJGlkLmV4cG9zdXJlLCBleHBvc3VyZSA9IGV4cG9zdXJlX3NucHMkZXhwb3N1cmUsIHB2YWwuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJHB2YWwpLCBkcGx5cjo6dGliYmxlKFNOUD1vdXRjb21lX2NsdW1wZWQkcnNpZCwgYmV0YS5vdXRjb21lPW91dGNvbWVfY2x1bXBlZCRiZXRhLm91dGNvbWUsIHNlLm91dGNvbWU9b3V0Y29tZV9jbHVtcGVkJHNlLm91dGNvbWUsIGVmZmVjdF9hbGxlbGUub3V0Y29tZSA9IG91dGNvbWVfY2x1bXBlZCRlZmZlY3RfYWxsZWxlLm91dGNvbWUsIG90aGVyX2FsbGVsZS5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJG90aGVyX2FsbGVsZS5vdXRjb21lLGVhZi5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJGVhZi5vdXRjb21lICwgb3V0Y29tZSA9IG91dGNvbWVfY2x1bXBlZCRvdXRjb21lLCBpZC5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJGlkLm91dGNvbWUsIHB2YWwub3V0Y29tZT0gb3V0Y29tZV9jbHVtcGVkJHB2YWwub3V0Y29tZSksIGFjdGlvbiA9IDIpICU+JSAKICBmaWx0ZXIocHZhbC5leHBvc3VyZSA8IDVlLTggJiBTTlAgIT0gInJzMTc4ODU4NDgiKQp3cml0ZV9jc3YobXJfZGF0LCAiaGFybW9uaXplZC9oYXJtb25pemVkX0EyX0ppYW5nTCIpCmBgYAoKYGBge3IsZXZhbD1GQUxTRX0Kb3V0Y29tZTIgPC0gcmVhZF90c3YoJ2d3YXNfcmVzb3VyY2VzL0RvdXZpbGxlTkpNb2RlbDFoLnRzdi5neicsIGNvbF9zZWxlY3QgPSBjKDEsMiwzLDQsNSw2LDcsOCw5LDEzKSkKY29sbmFtZXMob3V0Y29tZTIpPC0gYygiQ0hSIiwiUE9TIiwiZWZmZWN0X2FsbGVsZS5vdXRjb21lIiwib3RoZXJfYWxsZWxlLm91dGNvbWUiLCJiZXRhLm91dGNvbWUiLCJzZS5vdXRjb21lIiwiZWFmLm91dGNvbWUiLCJwdmFsLm91dGNvbWUiLCJyc2lkIiwiTiIpCm91dGNvbWUyJG91dGNvbWUgPC0gcmVwKGMoIlNlcHNpcyBBS0kiKSx0aW1lcz1ucm93KG91dGNvbWUyKSk7CmNsdW1wX2lkIDwtICJEb3V2aWxsZU5KMjAyNSI7Cm91dGNvbWUyJGlkLm91dGNvbWUgPC0gcmVwKGMoY2x1bXBfaWQpLHRpbWVzPW5yb3cob3V0Y29tZTIpKTsKCgpleHBvc3VyZV9zbnBzIDwtIHJlYWRfY3N2KCJkYXRhL2V4cG9zdXJlX0EyR1JDSDM4LmNzdiIpIAojZmlsdGVyIG91dGNvbWUgb24gU05QcyBpbiB0aGUgZXhwb3N1cmUKb3V0Y29tZV9jbHVtcGVkIDwtIGZpbHRlcihvdXRjb21lMiwgcnNpZCAlaW4lIGV4cG9zdXJlX3NucHMkcnNpZCkKI2hhcm1vbmlzZSBkYXRhCm1yX2RhdCA8LSBoYXJtb25pc2VfZGF0YShkcGx5cjo6dGliYmxlKFNOUD1leHBvc3VyZV9zbnBzJHJzaWQsIGJldGEuZXhwb3N1cmU9ZXhwb3N1cmVfc25wcyRiZXRhLmV4cG9zdXJlLCBzZS5leHBvc3VyZT1leHBvc3VyZV9zbnBzJHNlLmV4cG9zdXJlLCBlZmZlY3RfYWxsZWxlLmV4cG9zdXJlID0gZXhwb3N1cmVfc25wcyRlZmZlY3RfYWxsZWxlLmV4cG9zdXJlLCBvdGhlcl9hbGxlbGUuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJG90aGVyX2FsbGVsZS5leHBvc3VyZSxlYWYuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJGVhZi5leHBvc3VyZSwgaWQuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJGlkLmV4cG9zdXJlLCBleHBvc3VyZSA9IGV4cG9zdXJlX3NucHMkZXhwb3N1cmUsIHB2YWwuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJHB2YWwpLCBkcGx5cjo6dGliYmxlKFNOUD1vdXRjb21lX2NsdW1wZWQkcnNpZCwgYmV0YS5vdXRjb21lPW91dGNvbWVfY2x1bXBlZCRiZXRhLm91dGNvbWUsIHNlLm91dGNvbWU9b3V0Y29tZV9jbHVtcGVkJHNlLm91dGNvbWUsIGVmZmVjdF9hbGxlbGUub3V0Y29tZSA9IG91dGNvbWVfY2x1bXBlZCRlZmZlY3RfYWxsZWxlLm91dGNvbWUsIG90aGVyX2FsbGVsZS5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJG90aGVyX2FsbGVsZS5vdXRjb21lLGVhZi5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJGVhZi5vdXRjb21lICwgb3V0Y29tZSA9IG91dGNvbWVfY2x1bXBlZCRvdXRjb21lLCBpZC5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJGlkLm91dGNvbWUsIHB2YWwub3V0Y29tZT0gb3V0Y29tZV9jbHVtcGVkJHB2YWwub3V0Y29tZSksIGFjdGlvbiA9IDIpICU+JSAKICBmaWx0ZXIocHZhbC5leHBvc3VyZSA8IDVlLTYpCndyaXRlX2Nzdihtcl9kYXQsICJoYXJtb25pemVkL2hhcm1vbml6ZWRfQTJfRG91dmlsbGUiKQpgYGAKCmBgYHtyLGV2YWw9RkFMU0V9Cm91dGNvbWUzIDwtIHJlYWRfdHN2KCdnd2FzX3Jlc291cmNlcy9BS0lWZXJtYUFoLnRzdi5neicsIGNvbF9zZWxlY3QgPSBjKDEsMiwzLDQsNSw2LDcsOCw5LDEzKSkKY29sbmFtZXMob3V0Y29tZTMpPC0gYygiQ0hSIiwiUE9TIiwiZWZmZWN0X2FsbGVsZS5vdXRjb21lIiwib3RoZXJfYWxsZWxlLm91dGNvbWUiLCJvZGRzcmF0aW8ub3V0Y29tZSIsInNlLm91dGNvbWUiLCJlYWYub3V0Y29tZSIsInB2YWwub3V0Y29tZSIsInJzaWQiLCJOIikKb3V0Y29tZTMkb3V0Y29tZSA8LSByZXAoYygiUGhlQ29kZSA1ODUuMSAoVmVybWEpIiksdGltZXM9bnJvdyhvdXRjb21lMykpOwpjbHVtcF9pZCA8LSAidmVybWFBMjAyNCI7Cm91dGNvbWUzJGlkLm91dGNvbWUgPC0gcmVwKGMoY2x1bXBfaWQpLHRpbWVzPW5yb3cob3V0Y29tZTMpKTsKb3V0Y29tZTMkYmV0YS5vdXRjb21lIDwtIGxvZyhvdXRjb21lMyRvZGRzcmF0aW8ub3V0Y29tZSkKCgpleHBvc3VyZV9zbnBzIDwtIHJlYWRfY3N2KCJkYXRhL2V4cG9zdXJlX0EyR1JDSDM4LmNzdiIpIAojZmlsdGVyIG91dGNvbWUgb24gU05QcyBpbiB0aGUgZXhwb3N1cmUKb3V0Y29tZV9jbHVtcGVkIDwtIGZpbHRlcihvdXRjb21lMywgcnNpZCAlaW4lIGV4cG9zdXJlX3NucHMkcnNpZCkKI2hhcm1vbmlzZSBkYXRhCm1yX2RhdCA8LSBoYXJtb25pc2VfZGF0YShkcGx5cjo6dGliYmxlKFNOUD1leHBvc3VyZV9zbnBzJHJzaWQsIGJldGEuZXhwb3N1cmU9ZXhwb3N1cmVfc25wcyRiZXRhLmV4cG9zdXJlLCBzZS5leHBvc3VyZT1leHBvc3VyZV9zbnBzJHNlLmV4cG9zdXJlLCBlZmZlY3RfYWxsZWxlLmV4cG9zdXJlID0gZXhwb3N1cmVfc25wcyRlZmZlY3RfYWxsZWxlLmV4cG9zdXJlLCBvdGhlcl9hbGxlbGUuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJG90aGVyX2FsbGVsZS5leHBvc3VyZSxlYWYuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJGVhZi5leHBvc3VyZSwgaWQuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJGlkLmV4cG9zdXJlLCBleHBvc3VyZSA9IGV4cG9zdXJlX3NucHMkZXhwb3N1cmUsIHB2YWwuZXhwb3N1cmUgPSBleHBvc3VyZV9zbnBzJHB2YWwpLCBkcGx5cjo6dGliYmxlKFNOUD1vdXRjb21lX2NsdW1wZWQkcnNpZCwgYmV0YS5vdXRjb21lPW91dGNvbWVfY2x1bXBlZCRiZXRhLm91dGNvbWUsIHNlLm91dGNvbWU9b3V0Y29tZV9jbHVtcGVkJHNlLm91dGNvbWUsIGVmZmVjdF9hbGxlbGUub3V0Y29tZSA9IG91dGNvbWVfY2x1bXBlZCRlZmZlY3RfYWxsZWxlLm91dGNvbWUsIG90aGVyX2FsbGVsZS5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJG90aGVyX2FsbGVsZS5vdXRjb21lLGVhZi5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJGVhZi5vdXRjb21lICwgb3V0Y29tZSA9IG91dGNvbWVfY2x1bXBlZCRvdXRjb21lLCBpZC5vdXRjb21lID0gb3V0Y29tZV9jbHVtcGVkJGlkLm91dGNvbWUsIHB2YWwub3V0Y29tZT0gb3V0Y29tZV9jbHVtcGVkJHB2YWwub3V0Y29tZSksIGFjdGlvbiA9IDIpICU+JSAKICBmaWx0ZXIocHZhbC5leHBvc3VyZSA8IDVlLTgpCgp3cml0ZV9jc3YobXJfZGF0LCAiaGFybW9uaXplZC9oYXJtb25pemVkX0EyX1Zlcm1hQSIpCmBgYAoKIyBNUiBBbmFseXNpcwoKYGBge3IsZXZhbD1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpICAgICMgRGF0YSB3cmFuZ2xpbmcgCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoVHdvU2FtcGxlTVIpICAjIE1SIApsaWJyYXJ5KGd0KQpsaWJyYXJ5KExEbGlua1IpICAgICAgIyBMRCBhbmQgcHJveHkgc25wcwpsaWJyYXJ5KFJhZGlhbE1SKSAgICAgIyBSYWRpYWwgTVIgc2Vuc2V0aXZpdHkgYW5hbHlzaXMgCmxpYnJhcnkocGhlbm9zY2FubmVyKQoKYGBgCgojIyMjIERhdGFzZXQgMQoKYGBge3J9Cm1yX2RhdCA8LSByZWFkX2NzdigiaGFybW9uaXplZC9oYXJtb25pemVkX0EyX0ppYW5nTCIpCm1yX3BsZWlvdHJvcGh5X3Jlc3VsdCA8LSBtcl9wbGVpb3Ryb3B5X3Rlc3QobXJfZGF0KQpWaWV3KG1yX3BsZWlvdHJvcGh5X3Jlc3VsdCkKbXJfcmVzIDwtIG1yKG1yX2RhdCwgbWV0aG9kX2xpc3QgPSBjKAogICJtcl90d29fc2FtcGxlX21sIiwgICJtcl9lZ2dlcl9yZWdyZXNzaW9uIiwgCiAgIm1yX3NpbXBsZV9tZWRpYW4iLCAibXJfd2VpZ2h0ZWRfbWVkaWFuIiwgCiAgIm1yX2l2d19mZSIsICJtcl9pdndfbXJlIiwKICAibXJfc2ltcGxlX21vZGUiLCAibXJfd2VpZ2h0ZWRfbW9kZSIKICApKQpyZXNfc2luZ2xlIDwtIG1yX3NpbmdsZXNucChtcl9kYXQsIGFsbF9tZXRob2QgPSBjKCJtcl9pdndfZmUiLCAibXJfZWdnZXJfcmVncmVzc2lvbiIsICJtcl93ZWlnaHRlZF9tZWRpYW4iLCAibXJfd2VpZ2h0ZWRfbW9kZSIpKSAlPiUgYXNfdGliYmxlKCkKVmlldyhyZXNfc2luZ2xlKQpvZGQgPC0gZ2VuZXJhdGVfb2Rkc19yYXRpb3MobXJfcmVzKQpwcmludCgiRmluaXNoZWQgQW5hbHl6aW5nIikKd3JpdGUuY3N2KG9kZCwicmVzdWx0cy9BMi9qaWFuZ2xhMl9vZGRzcmF0aW9zLmNzdiIpCndyaXRlLmNzdihyZXNfc2luZ2xlLCJyZXN1bHRzL0EyL2ppYW5nbGEyX3Jlc19zaW5nbGUuY3N2IikKc2NhdHRlcl9wIDwtIG1yX3NjYXR0ZXJfcGxvdChtcl9yZXMsIG1yX2RhdCkgCnNjYXR0ZXJfb3V0X3AgPC0gc2NhdHRlcl9wW1sxXV0gKyB0aGVtZV9idygpICsgCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChuY29sID0xKSkgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCAKICApCgpzY2F0dGVyX291dF9wCmdnc2F2ZSgicmVzdWx0cy9BMi9zY2F0dGVycGxvdEEySmlhbmdMLnBuZyIsIHBsb3QgPSBzY2F0dGVyX291dF9wLCB1bml0cyA9ICdpbicsIGhlaWdodCA9IDQsIHdpZHRoID0gOSkKZm9ycmVzdF9wIDwtIG1yX2ZvcmVzdF9wbG90KHJlc19zaW5nbGUpCmZvcnJlc3RfcFtbMV1dCmdnc2F2ZSgicmVzdWx0cy9BMi9mb3JyZXN0cGxvdEEySmlhbmdMLnBuZyIsIHBsb3QgPWZvcnJlc3RfcFtbMV1dICsgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpLCB1bml0cyA9ICdpbicsIGhlaWdodCA9IDksIHdpZHRoID0gOSkKCnJlc19sb28gPC0gbXJfbGVhdmVvbmVvdXQobXJfZGF0LCBtZXRob2QgPSBtcl9pdndfZmUpICU+JSBhc190aWJibGUoKQpsb29fcCA8LSBtcl9sZWF2ZW9uZW91dF9wbG90KHJlc19sb28pCmxvb19wW1sxXV0KZ2dzYXZlKCJyZXN1bHRzL0EyL2xvb0EySmlhbmdMLnBuZyIscGxvdCA9IGxvb19wW1sxXV0sIHVuaXRzID0gJ2luJywgaGVpZ2h0ID0gOSwgd2lkdGggPSA5KQoKZnVubmVsX3AgPC0gbXJfZnVubmVsX3Bsb3QocmVzX3NpbmdsZSkKZnVubmVsX291dF9wIDwtIGZ1bm5lbF9wW1sxXV0gKyB0aGVtZV9idygpICsgCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChuY29sID0xKSkgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCAKICApCgpmdW5uZWxfb3V0X3AKZ2dzYXZlKCJyZXN1bHRzL0EyL2Z1bm5lbHBsb3RBMkppYW5nTC5wbmciLCBwbG90ID0gZnVubmVsX291dF9wLCB1bml0cyA9ICdpbicsIGhlaWdodCA9IDQsIHdpZHRoID0gOSkKCmBgYAoKIyMjIyBEYXRhc2V0IDIKCmBgYHtyfQoKbXJfZGF0IDwtIHJlYWRfY3N2KCJoYXJtb25pemVkL2hhcm1vbml6ZWRfQTJfRG91dmlsbGUiKQptcl9yZXMgPC0gbXIobXJfZGF0LCBtZXRob2RfbGlzdCA9IGMoCiAgIm1yX3R3b19zYW1wbGVfbWwiLCAgIm1yX2VnZ2VyX3JlZ3Jlc3Npb24iLCAKICAibXJfc2ltcGxlX21lZGlhbiIsICJtcl93ZWlnaHRlZF9tZWRpYW4iLCAKICAibXJfaXZ3X2ZlIiwgIm1yX2l2d19tcmUiLAogICJtcl9zaW1wbGVfbW9kZSIsICJtcl93ZWlnaHRlZF9tb2RlIgogICkpCnJlc19zaW5nbGUgPC0gbXJfc2luZ2xlc25wKG1yX2RhdCwgYWxsX21ldGhvZCA9IGMoIm1yX2l2d19mZSIsICJtcl9lZ2dlcl9yZWdyZXNzaW9uIiwgIm1yX3dlaWdodGVkX21lZGlhbiIsICJtcl93ZWlnaHRlZF9tb2RlIikpICU+JSBhc190aWJibGUoKQpWaWV3KHJlc19zaW5nbGUpCm9kZCA8LSBnZW5lcmF0ZV9vZGRzX3JhdGlvcyhtcl9yZXMpCnByaW50KCJGaW5pc2hlZCBBbmFseXppbmciKQp3cml0ZS5jc3Yob2RkLCJyZXN1bHRzL0EyL2RvdXZpbGxlYTJfb2Rkc3JhdGlvcy5jc3YiKQp3cml0ZS5jc3YocmVzX3NpbmdsZSwicmVzdWx0cy9BMi9kb3V2aWxsZWEyX3Jlc19zaW5nbGUuY3N2IikKCnNjYXR0ZXJfcCA8LSBtcl9zY2F0dGVyX3Bsb3QobXJfcmVzLCBtcl9kYXQpIApzY2F0dGVyX291dF9wIDwtIHNjYXR0ZXJfcFtbMV1dICsgdGhlbWVfYncoKSArIAogIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQobmNvbCA9MSkpICsgCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwgCiAgKQoKc2NhdHRlcl9vdXRfcApnZ3NhdmUoInJlc3VsdHMvQTIvc2NhdHRlcnBsb3RBMkRvdXZpbGxlLnBuZyIsIHBsb3QgPSBzY2F0dGVyX291dF9wLCB1bml0cyA9ICdpbicsIGhlaWdodCA9IDQsIHdpZHRoID0gOSkKZm9ycmVzdF9wIDwtIG1yX2ZvcmVzdF9wbG90KHJlc19zaW5nbGUpCmZvcnJlc3RfcFtbMV1dCmdnc2F2ZSgicmVzdWx0cy9BMi9mb3JyZXN0cGxvdEEyRG91dmlsbGUucG5nIiwgcGxvdCA9Zm9ycmVzdF9wW1sxXV0gKyB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSksIHVuaXRzID0gJ2luJywgaGVpZ2h0ID0gOSwgd2lkdGggPSA5KQoKcmVzX2xvbyA8LSBtcl9sZWF2ZW9uZW91dChtcl9kYXQsIG1ldGhvZCA9IG1yX2l2d19mZSkgJT4lIGFzX3RpYmJsZSgpCmxvb19wIDwtIG1yX2xlYXZlb25lb3V0X3Bsb3QocmVzX2xvbykKbG9vX3BbWzFdXQpnZ3NhdmUoInJlc3VsdHMvQTIvbG9vQTJEb3V2aWxsZS5wbmciLHBsb3QgPSBsb29fcFtbMV1dLCB1bml0cyA9ICdpbicsIGhlaWdodCA9IDksIHdpZHRoID0gOSkKZnVubmVsX3AgPC0gbXJfZnVubmVsX3Bsb3QocmVzX3NpbmdsZSkKZnVubmVsX291dF9wIDwtIGZ1bm5lbF9wW1sxXV0gKyB0aGVtZV9idygpICsgCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChuY29sID0xKSkgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCAKICApCgpmdW5uZWxfb3V0X3AKZ2dzYXZlKCJyZXN1bHRzL0EyL2Z1bm5lbHBsb3RBMkRvdXZpbGxlLnBuZyIsIHBsb3QgPSBmdW5uZWxfb3V0X3AsIHVuaXRzID0gJ2luJywgaGVpZ2h0ID0gNCwgd2lkdGggPSA5KQoKYGBgCgpgYGB7cn0KCgpgYGAKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkgICAgIyBEYXRhIHdyYW5nbGluZyAKbGlicmFyeShUd29TYW1wbGVNUikgICMgTVIgCmxpYnJhcnkoZ2dtYW4pCnRjX3BhdGggPSAiZ3dhc19yZXNvdXJjZXMvRG91dmlsbGVOSk1vZGVsMWgudHN2Lmd6Igp0Y19zcyA8LSByZWFkX3Rzdih0Y19wYXRoKQoKIyBGaWx0ZXIgb24gcCA8IDAuNSB0byByZWR1Y2UgY29tcHV0ZQpnZ21hbihmaWx0ZXIodGNfc3MsIHBfdmFsdWUgPCAwLjUgJiBwX3ZhbHVlID4gMWUtMTAwKSwgc25wID0gIlNOUElEIiwgYnAgPSAiYmFzZV9wYWlyX2xvY2F0aW9uIiwgY2hyb20gPSAiY2hyb21vc29tZSIsIHB2YWx1ZSA9ICJwX3ZhbHVlIiwgcmVsYXRpdmUucG9zaXRpb25zID0gVFJVRSkgKyAKICB0aGVtZV9jbGFzc2ljKCkKYGBgCg==