The following scripts can be used to replicate the data-set for the preregistered Experiment 3 of Dederichs et al. (2025). It may also be obtained by downloading: Download conjoint_trial.Rda


1 Getting started

To copy the code, click the button in the upper right corner of the code-chunks.

1.1 Clean up

rm(list = ls())
gc()


1.2 general custom functions

  • fpackage.check: Check if packages are installed (and install if not) in R
  • fsave: Function to save data with time stamp in correct directory
  • fload: Function to load R-objects under new names
  • fshowdf: Print objects (tibble / data.frame) nicely on screen in .Rmd
  • ftheme: pretty ggplot2 theme
fpackage.check <- function(packages) {
    lapply(packages, FUN = function(x) {
        if (!require(x, character.only = TRUE)) {
            install.packages(x, dependencies = TRUE)
            library(x, character.only = TRUE)
        }
    })
}

fsave <- function(x, file, location = "./data/processed/", ...) {
    if (!dir.exists(location))
        dir.create(location)
    datename <- substr(gsub("[:-]", "", Sys.time()), 1, 8)
    totalname <- paste(location, datename, file, sep = "")
    print(paste("SAVED: ", totalname, sep = ""))
    save(x, file = totalname)
}


fload <- function(fileName) {
    load(fileName)
    get(ls()[ls() != "fileName"])
}


fshowdf <- function(x, ...) {
    knitr::kable(x, digits = 2, "html", ...) %>%
        kableExtra::kable_styling(bootstrap_options = c("striped", "hover")) %>%
        kableExtra::scroll_box(width = "100%", height = "300px")
}

ftheme <- function() {
    # download font at https://fonts.google.com/specimen/Jost/
    theme_minimal(base_family = "Jost") + theme(panel.grid.minor = element_blank(), plot.title = element_text(family = "Jost",
        face = "bold"), axis.title = element_text(family = "Jost Medium"), axis.title.x = element_text(hjust = 0),
        axis.title.y = element_text(hjust = 1), strip.text = element_text(family = "Jost", face = "bold",
            size = rel(0.75), hjust = 0), strip.background = element_rect(fill = "grey90", color = NA),
        legend.position = "bottom")
}


1.3 Necessary packages

  • tidyverse: data wrangling
  • haven: read and write various data formats
  • sjlabelled: work with labelled (SPSS) data
packages = c("tidyverse", "haven", "sjlabelled")
fpackage.check(packages)
rm(packages)



2 Download data files

The data of our survey module will be available at a later date through DANS Data Station SSH, but parts of the data needed for replication can be retrieved by downloading: Download public_trial.Rda.

Download the data-file and put it in the ./data/ folder. But first, make a ./data/ folder:

ifelse(!dir.exists("data"), dir.create("data"), FALSE)

3 Import data

Import and unlabel the downloaded data of wave 3 of the TRIAL survey.

df <- fload("./data/public_trial.Rda")
df <- sjlabelled::unlabel(df, verbose = FALSE)



4 wrangling data

#make respondent id 
df$id <- 1:nrow(df)

#interaction variables: educational level and migration/cultural background of ego
df$education <- ifelse(!is.na(df$V79.x), df$V79.x, df$V79.y)
df$tert_educ <- ifelse(df$education %in% c(6,7), 1, 0)
df$migration <- ifelse(df$ETNICITEIT %in% c(2, 3), 1, 0) 
df$migration_nw <- ifelse(df$ETNICITEIT == 3, 1, ifelse(df$ETNICITEIT == 1, 0 , NA)) # non-western only vs dutch background

#current club/team composition
#Note: in the course of wave 3, a number of respondents were excluded from questions regarding the current club/team due to routing errors. This issue was rectified in a  follow-up questionnaire. For respondents who provided a response during wave 3, that response is considered. In cases where no response was obtained during wave 3, the follow-up questionnaire responses are taken
df$percent_migrant_club <- ifelse(!is.na(df$V122_1), df$V122_1, df$V122_1_extra)
df$percent_migrant_team <- ifelse(!is.na(df$V122_2), df$V122_2, df$V122_2_extra)
df$percent_migrant_buurt <- df$V122_3
df$percent_migrant_straat <- df$V122_4

df$percent_terteduc_club <- ifelse(!is.na(df$V123_1), df$V123_1, df$V123_1_extra)
df$percent_terteduc_team <- ifelse(!is.na(df$V123_2), df$V123_2, df$V123_2_extra)
df$percent_terteduc_buurt <- df$V123_3
df$percent_terteduc_straat <- df$V123_4

df$inv_sportclub <- ifelse(df$V7a_1 == 1, 1, 0)

#to long format

#each list element contains the choices for each set:
#thus, reistijd.list[[3]][2] is the level of the travel time attribute of club 2 in choice-set 3.

reistijd.list <- list(
  c("Reistijd_A1", "Reistijd_A2"),
  c("Reistijd_B1", "Reistijd_B2"),
  c("Reistijd_C1", "Reistijd_C2")
)

frequentie.list <- list(
  c("Trainningsfrequentie_A1", "Trainningsfrequentie_A2"),
  c("Trainningsfrequentie_B1", "Trainningsfrequentie_B2"),
  c("Trainningsfrequentie_C1", "Trainningsfrequentie_C2")
)

webpagina.list <- list(
  c("Webpagina_A1", "Webpagina_A2"),
  c("Webpagina_B1", "Webpagina_B2"),
  c("Webpagina_C1", "Webpagina_C2")
)

bekenden.list <- list(
  c("Bekenden_A1", "Bekenden_A2"),
  c("Bekenden_B1", "Bekenden_B2"),
  c("Bekenden_C1", "Bekenden_C2")
)

clubopleiding.list  <- list(
  c("Clubleden_opleiding_A1", "Clubleden_opleiding_A2"),
  c("Clubleden_opleiding_B1", "Clubleden_opleiding_B2"),
  c("Clubleden_opleiding_C1", "Clubleden_opleiding_C2")
)

clubmigratie.list  <- list(
  c("Clubleden_migratieachtergrond_A1", "Clubleden_migratieachtergrond_A2"),
  c("Clubleden_migratieachtergrond_B1", "Clubleden_migratieachtergrond_B2"),
  c("Clubleden_migratieachtergrond_C1", "Clubleden_migratieachtergrond_C2")
)

teamopleiding.list  <- list(
  c("Trainingsgroep_opleiding_A1", "Trainingsgroep_opleiding_A2"),
  c("Trainingsgroep_opleiding_B1", "Trainingsgroep_opleiding_B2"),
  c("Trainingsgroep_opleiding_C1", "Trainingsgroep_opleiding_C2")
)

teammigratie.list  <- list(
  c("Trainingsgroep_migratieachtergrond_A1", "Trainingsgroep_migratieachtergrond_A2"),
  c("Trainingsgroep_migratieachtergrond_B1", "Trainingsgroep_migratieachtergrond_B2"),
  c("Trainingsgroep_migratieachtergrond_C1", "Trainingsgroep_migratieachtergrond_C2")
)

chosen <- c("V107_1", "V107_2", "V107_3")

for (set in 1:3) {

  # to long format
  
  for (choice in 1:2) {
    
    data <- as.data.frame(df)
    data$set <- set
    data$options <- choice
    data$traveltime <- data[, names(data) == reistijd.list[[set]][choice]]
    data$trainfreq <- data[, names(data) == frequentie.list[[set]][choice]]
    data$webpage <- data[, names(data) == webpagina.list[[set]][choice]]
    data$acquaintances <- data[, names(data) == bekenden.list[[set]][choice]]
    data$educ_club <- data[, names(data) == clubopleiding.list[[set]][choice]]
    data$educ_team <- data[, names(data) == teamopleiding.list[[set]][choice]]
    data$migrant_club <- data[, names(data) == clubmigratie.list[[set]][choice]]
    data$migrant_team <- data[, names(data) == teammigratie.list[[set]][choice]]
    data$chosen <- data[, names(data) == chosen[set]]
    
    data <- data[, names(data) %in% c("id", "tert_educ", "migration", "migration_nw", "LEEFTIJD", "GESLACHT2", "inv_sportclub", "percent_migrant_club", "percent_migrant_team", "percent_migrant_buurt", "percent_migrant_straat", "percent_terteduc_club", "percent_terteduc_team", "percent_terteduc_buurt", "percent_terteduc_straat", "set", "options", "traveltime", "trainfreq", "webpage", "acquaintances", "educ_club", "educ_team", "migrant_club", "migrant_team", "chosen")]
    
    if(set == 1 & choice == 1) {
      df_long <- data
    } else {
      df_long <- rbind(df_long, data)
    }
  }
}

# reorder
df_long <- df_long[order(df_long$id, df_long$set, df_long$options), ]

# define the choice
df_long$choice <- (df_long$chosen == c(1, 2)[df_long$options])

# recode numeric levels, and make of class factor
df_long <- df_long %>% mutate(
  
  traveltime = case_when(
    traveltime == 1 ~ "travel time: 5 minutes",
    traveltime == 2 ~ "travel time: 15 minutes",
    traveltime == 3 ~ "travel time: 30 minutes"),
  
  trainfreq = case_when(
    trainfreq == 1 ~ "training frequency: once a week",
    trainfreq == 2 ~ "training frequency: more than once a week"),
  
  webpage = case_when(
    webpage == 1 ~ "webpage statement: 'exercising together is building friendships!'",
    webpage == 2 ~ "webpage statement: 'lift yourself to a higher level!'"),
  
  acquaintances = case_when(
    acquaintances == 1 ~ "acquaintances: multiple",
    acquaintances == 2 ~ "acquaintances: none"),
    
  educ_club = case_when(
    educ_club == 1 ~ "club members with tertiary education: a quarter (25%)",
    educ_club == 2 ~ "club members with tertiary education: half (50%)",
    educ_club == 3 ~ "club members with tertiary education: three quarters (75%)"),
  
  migrant_club = case_when(
    migrant_club == 1 ~ "club members with migration background: a few (5%)",
    migrant_club == 2 ~ "club members with migration background: minority (10%)",
    migrant_club == 3 ~ "club members with migration background: a quarter (25%)"),
    
  educ_team = case_when(
    educ_team == 1 ~ "contacts with tertiary education: minority (10%)",
    educ_team == 2 ~ "contacts with tertiary education: a quarter (25%)",
    educ_team == 3 ~ "contacts with tertiary education: half (50%)",
    educ_team == 4 ~ "contacts with tertiary education: three quarters (75%)",
    educ_team == 5 ~ "contacts with tertiary education: majority (90%)"),
    
  migrant_team = case_when(
    migrant_team == 1 ~ "contacts with migration background: none (0%)",
    migrant_team == 2 ~ "contacts with migration background: a few (5%)",
    migrant_team == 3 ~ "contacts with migration background: minority (10%)",
    migrant_team == 4 ~ "contacts with migration background: a quarter (25%)",      
    migrant_team == 5 ~ "contacts with migration background: half (50%)")
  )

row.names(df_long) <- 1:nrow(df_long)

#remove "chosen" and "options"
names(df_long)
df_long <- df_long[, -c(26, 17)]

#last, reorder attribute levels
df_long$traveltime <- factor(df_long$traveltime, levels = rev(c("travel time: 5 minutes", "travel time: 15 minutes", "travel time: 30 minutes")))
df_long$trainfreq <- factor(df_long$trainfreq, levels = rev(c("training frequency: once a week", "training frequency: more than once a week")))
df_long$webpage <- factor(df_long$webpage, levels = rev(c("webpage statement: 'exercising together is building friendships!'", "webpage statement: 'lift yourself to a higher level!'")))
df_long$acquaintances <- factor(df_long$acquaintances, levels = rev(c("acquaintances: none", "acquaintances: multiple")))
df_long$educ_club <- factor(df_long$educ_club, levels = rev(c("club members with tertiary education: a quarter (25%)", "club members with tertiary education: half (50%)", "club members with tertiary education: three quarters (75%)")))
df_long$migrant_club <- factor(df_long$migrant_club, levels = rev(c("club members with migration background: a few (5%)", "club members with migration background: minority (10%)", "club members with migration background: a quarter (25%)")))
df_long$educ_team <- factor(df_long$educ_team, levels = rev(c("contacts with tertiary education: minority (10%)", "contacts with tertiary education: a quarter (25%)", "contacts with tertiary education: half (50%)", "contacts with tertiary education: three quarters (75%)", "contacts with tertiary education: majority (90%)")))
df_long$migrant_team <- factor(df_long$migrant_team, levels = rev(c("contacts with migration background: none (0%)", "contacts with migration background: a few (5%)", "contacts with migration background: minority (10%)", "contacts with migration background: a quarter (25%)", "contacts with migration background: half (50%)")))



5 Save data

fsave(df_long, "conjoint_trial.Rda")

References

Dederichs, Kasimir, Rob Franken, Dingeman Wiertz, and Jochem Tolsma. 2025. Ingroup Preferences, Segregation, and Intergroup Contact in Neighborhoods and Civic Organizations.” PNAS Nexus.
LS0tDQp0aXRsZTogIkRhdGEgcHJlcGFyYXRpb24iDQpiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliDQpsaW5rLWNpdGF0aW9uczogdHJ1ZQ0KZGF0ZTogIkxhc3QgY29tcGlsZWQgb24gYHIgZm9ybWF0KFN5cy50aW1lKCksICclZC0lbS0lWScpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY3NzOiB0d2Vha3MuY3NzDQogICAgdG9jOiAgdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KLS0tDQoNCmBgYHtyLCBnbG9iYWxzZXR0aW5ncywgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9DQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpvcHRzX2NodW5rJHNldCh0aWR5Lm9wdHM9bGlzdCh3aWR0aC5jdXRvZmY9MTAwKSx0aWR5PVRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLGNvbW1lbnQgPSAiIz4iLCBjYWNoZT1UUlVFLCBjbGFzcy5zb3VyY2U9YygidGVzdCIpLCBjbGFzcy5vdXRwdXQ9YygidGVzdDMiKSkNCm9wdGlvbnMod2lkdGggPSAxMDApDQpyZ2w6OnNldHVwS25pdHIoKQ0KDQpjb2xvcml6ZSA8LSBmdW5jdGlvbih4LCBjb2xvcikge3NwcmludGYoIjxzcGFuIHN0eWxlPSdjb2xvcjogJXM7Jz4lczwvc3Bhbj4iLCBjb2xvciwgeCkgfQ0KYGBgDQoNCg0KYGBge3Iga2xpcHB5LCBlY2hvPUZBTFNFLCBpbmNsdWRlPVRSVUV9DQprbGlwcHk6OmtsaXBweShwb3NpdGlvbiA9IGMoJ3RvcCcsICdyaWdodCcpKQ0KI2tsaXBweTo6a2xpcHB5KGNvbG9yID0gJ2RhcmtyZWQnKQ0KI2tsaXBweTo6a2xpcHB5KHRvb2x0aXBfbWVzc2FnZSA9ICdDbGljayB0byBjb3B5JywgdG9vbHRpcF9zdWNjZXNzID0gJ0RvbmUnKQ0KYGBgDQoNCg0KLS0tDQoNClRoZSBmb2xsb3dpbmcgc2NyaXB0cyBjYW4gYmUgdXNlZCB0byByZXBsaWNhdGUgdGhlIGRhdGEtc2V0IGZvciB0aGUgW3ByZXJlZ2lzdGVyZWRdKGh0dHBzOi8vb3NmLmlvLzJ3enYzLykgRXhwZXJpbWVudCAzIG9mIEBhdXRob3JzMjAyNS4gSXQgbWF5IGFsc28gYmUgb2J0YWluZWQgYnkgZG93bmxvYWRpbmc6IGByIHhmdW46OmVtYmVkX2ZpbGUoIi4vZGF0YV9zaGFyZWQvY29uam9pbnRfdHJpYWwuUmRhIilgDQoNCi0tLSAgDQoNCiMgR2V0dGluZyBzdGFydGVkDQoNClRvIGNvcHkgdGhlIGNvZGUsIGNsaWNrIHRoZSBidXR0b24gaW4gdGhlIHVwcGVyIHJpZ2h0IGNvcm5lciBvZiB0aGUgY29kZS1jaHVua3MuDQoNCg0KIyMgQ2xlYW4gdXANCg0KYGBge3IsIHJlc3VsdHM9J2hpZGUnfQ0Kcm0obGlzdD1scygpKQ0KZ2MoKQ0KYGBgDQoNCjxicj4NCg0KIyMgZ2VuZXJhbCBjdXN0b20gZnVuY3Rpb25zDQoNCi0gYGZwYWNrYWdlLmNoZWNrYDogQ2hlY2sgaWYgcGFja2FnZXMgYXJlIGluc3RhbGxlZCAoYW5kIGluc3RhbGwgaWYgbm90KSBpbiBSDQotIGBmc2F2ZWA6IEZ1bmN0aW9uIHRvIHNhdmUgZGF0YSB3aXRoIHRpbWUgc3RhbXAgaW4gY29ycmVjdCBkaXJlY3RvcnkNCi0gYGZsb2FkYDogRnVuY3Rpb24gdG8gbG9hZCBSLW9iamVjdHMgdW5kZXIgbmV3IG5hbWVzDQotIGBmc2hvd2RmYDogUHJpbnQgb2JqZWN0cyAoYHRpYmJsZWAgLyBgZGF0YS5mcmFtZWApIG5pY2VseSBvbiBzY3JlZW4gaW4gYC5SbWRgDQotIGBmdGhlbWVgOiBwcmV0dHkgZ2dwbG90MiB0aGVtZQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmZwYWNrYWdlLmNoZWNrIDwtIGZ1bmN0aW9uKHBhY2thZ2VzKSB7DQogICAgbGFwcGx5KHBhY2thZ2VzLCBGVU4gPSBmdW5jdGlvbih4KSB7DQogICAgICAgIGlmICghcmVxdWlyZSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSB7DQogICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKHgsIGRlcGVuZGVuY2llcyA9IFRSVUUpDQogICAgICAgICAgICBsaWJyYXJ5KHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCiAgICAgICAgfQ0KICAgIH0pDQp9DQoNCmZzYXZlIDwtIGZ1bmN0aW9uKHgsIGZpbGUsIGxvY2F0aW9uID0gIi4vZGF0YS9wcm9jZXNzZWQvIiwgLi4uKSB7DQogICAgaWYgKCFkaXIuZXhpc3RzKGxvY2F0aW9uKSkNCiAgICAgICAgZGlyLmNyZWF0ZShsb2NhdGlvbikNCiAgICBkYXRlbmFtZSA8LSBzdWJzdHIoZ3N1YigiWzotXSIsICIiLCBTeXMudGltZSgpKSwgMSwgOCkNCiAgICB0b3RhbG5hbWUgPC0gcGFzdGUobG9jYXRpb24sIGRhdGVuYW1lLCBmaWxlLCBzZXAgPSAiIikNCiAgICBwcmludChwYXN0ZSgiU0FWRUQ6ICIsIHRvdGFsbmFtZSwgc2VwID0gIiIpKQ0KICAgIHNhdmUoeCwgZmlsZSA9IHRvdGFsbmFtZSkNCn0NCg0KDQpmbG9hZCAgPC0gZnVuY3Rpb24oZmlsZU5hbWUpew0KICBsb2FkKGZpbGVOYW1lKQ0KICBnZXQobHMoKVtscygpICE9ICJmaWxlTmFtZSJdKQ0KfQ0KDQoNCmZzaG93ZGYgPC0gZnVuY3Rpb24oeCwgLi4uKSB7DQogICAga25pdHI6OmthYmxlKHgsIGRpZ2l0cyA9IDIsICJodG1sIiwgLi4uKSAlPiUNCiAgICAgICAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSkgJT4lDQogICAgICAgIGthYmxlRXh0cmE6OnNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIzMDBweCIpDQp9DQoNCmZ0aGVtZSA8LSBmdW5jdGlvbigpIHsNCiAgI2Rvd25sb2FkIGZvbnQgYXQgaHR0cHM6Ly9mb250cy5nb29nbGUuY29tL3NwZWNpbWVuL0pvc3QvDQogIHRoZW1lX21pbmltYWwoYmFzZV9mYW1pbHkgPSAiSm9zdCIpICsNCiAgICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkpvc3QiLCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJKb3N0IE1lZGl1bSIpLA0KICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApLA0KICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDEpLA0KICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkpvc3QiLCBmYWNlID0gImJvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IHJlbCgwLjc1KSwgaGp1c3QgPSAwKSwNCiAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JleTkwIiwgY29sb3IgPSBOQSksDQogICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQp9DQpgYGANCg0KDQo8YnI+DQoNCiMjIE5lY2Vzc2FyeSBwYWNrYWdlcw0KDQotIGB0aWR5dmVyc2VgOiBkYXRhIHdyYW5nbGluZw0KLSBgaGF2ZW5gOiByZWFkIGFuZCB3cml0ZSB2YXJpb3VzIGRhdGEgZm9ybWF0cw0KLSBgc2psYWJlbGxlZGA6IHdvcmsgd2l0aCBsYWJlbGxlZCAoU1BTUykgZGF0YQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCnBhY2thZ2VzID0gYygidGlkeXZlcnNlIiwgImhhdmVuIiwgInNqbGFiZWxsZWQiKQ0KZnBhY2thZ2UuY2hlY2socGFja2FnZXMpDQpybShwYWNrYWdlcykNCmBgYA0KPGJyPg0KDQotLS0NCg0KIyBEb3dubG9hZCBkYXRhIGZpbGVzDQoNClRoZSBkYXRhIG9mIG91ciBzdXJ2ZXkgbW9kdWxlIHdpbGwgYmUgYXZhaWxhYmxlIGF0IGEgbGF0ZXIgZGF0ZSB0aHJvdWdoIERBTlMgRGF0YSBTdGF0aW9uIFNTSCwgYnV0IHBhcnRzIG9mIHRoZSBkYXRhIG5lZWRlZCBmb3IgcmVwbGljYXRpb24gY2FuIGJlIHJldHJpZXZlZCBieSBkb3dubG9hZGluZzogKipgciB4ZnVuOjplbWJlZF9maWxlKCIuL2RhdGFfc2hhcmVkL3B1YmxpY190cmlhbC5SZGEiKWAqKi4NCg0KRG93bmxvYWQgdGhlIGRhdGEtZmlsZSBhbmQgcHV0IGl0IGluIHRoZSBgLi9kYXRhL2AgZm9sZGVyLiBCdXQgZmlyc3QsIG1ha2UgYSBgLi9kYXRhL2AgZm9sZGVyOg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmlmZWxzZSghZGlyLmV4aXN0cygiZGF0YSIpLCBkaXIuY3JlYXRlKCJkYXRhIiksIEZBTFNFKQ0KYGBgIA0KDQoNCi0tLQ0KDQojIEltcG9ydCBkYXRhDQoNCkltcG9ydCBhbmQgdW5sYWJlbCB0aGUgZG93bmxvYWRlZCBkYXRhIG9mIHdhdmUgMyBvZiB0aGUgVFJJQUwgc3VydmV5Lg0KDQpgYGB7ciwgaW1wb3J0LCBldmFsPUZBTFNFfQ0KZGYgPC0gZmxvYWQoIi4vZGF0YS9wdWJsaWNfdHJpYWwuUmRhIikNCmRmIDwtIHNqbGFiZWxsZWQ6OnVubGFiZWwoZGYsIHZlcmJvc2UgPSBGQUxTRSkNCmBgYA0KDQo8YnI+IA0KDQotLS0NCg0KIyB3cmFuZ2xpbmcgZGF0YQ0KDQpgYGB7ciwgZGNlZGF0LCBldmFsPUZBTFNFfQ0KI21ha2UgcmVzcG9uZGVudCBpZCANCmRmJGlkIDwtIDE6bnJvdyhkZikNCg0KI2ludGVyYWN0aW9uIHZhcmlhYmxlczogZWR1Y2F0aW9uYWwgbGV2ZWwgYW5kIG1pZ3JhdGlvbi9jdWx0dXJhbCBiYWNrZ3JvdW5kIG9mIGVnbw0KZGYkZWR1Y2F0aW9uIDwtIGlmZWxzZSghaXMubmEoZGYkVjc5LngpLCBkZiRWNzkueCwgZGYkVjc5LnkpDQpkZiR0ZXJ0X2VkdWMgPC0gaWZlbHNlKGRmJGVkdWNhdGlvbiAlaW4lIGMoNiw3KSwgMSwgMCkNCmRmJG1pZ3JhdGlvbiA8LSBpZmVsc2UoZGYkRVROSUNJVEVJVCAlaW4lIGMoMiwgMyksIDEsIDApIA0KZGYkbWlncmF0aW9uX253IDwtIGlmZWxzZShkZiRFVE5JQ0lURUlUID09IDMsIDEsIGlmZWxzZShkZiRFVE5JQ0lURUlUID09IDEsIDAgLCBOQSkpICMgbm9uLXdlc3Rlcm4gb25seSB2cyBkdXRjaCBiYWNrZ3JvdW5kDQoNCiNjdXJyZW50IGNsdWIvdGVhbSBjb21wb3NpdGlvbg0KI05vdGU6IGluIHRoZSBjb3Vyc2Ugb2Ygd2F2ZSAzLCBhIG51bWJlciBvZiByZXNwb25kZW50cyB3ZXJlIGV4Y2x1ZGVkIGZyb20gcXVlc3Rpb25zIHJlZ2FyZGluZyB0aGUgY3VycmVudCBjbHViL3RlYW0gZHVlIHRvIHJvdXRpbmcgZXJyb3JzLiBUaGlzIGlzc3VlIHdhcyByZWN0aWZpZWQgaW4gYSAgZm9sbG93LXVwIHF1ZXN0aW9ubmFpcmUuIEZvciByZXNwb25kZW50cyB3aG8gcHJvdmlkZWQgYSByZXNwb25zZSBkdXJpbmcgd2F2ZSAzLCB0aGF0IHJlc3BvbnNlIGlzIGNvbnNpZGVyZWQuIEluIGNhc2VzIHdoZXJlIG5vIHJlc3BvbnNlIHdhcyBvYnRhaW5lZCBkdXJpbmcgd2F2ZSAzLCB0aGUgZm9sbG93LXVwIHF1ZXN0aW9ubmFpcmUgcmVzcG9uc2VzIGFyZSB0YWtlbg0KZGYkcGVyY2VudF9taWdyYW50X2NsdWIgPC0gaWZlbHNlKCFpcy5uYShkZiRWMTIyXzEpLCBkZiRWMTIyXzEsIGRmJFYxMjJfMV9leHRyYSkNCmRmJHBlcmNlbnRfbWlncmFudF90ZWFtIDwtIGlmZWxzZSghaXMubmEoZGYkVjEyMl8yKSwgZGYkVjEyMl8yLCBkZiRWMTIyXzJfZXh0cmEpDQpkZiRwZXJjZW50X21pZ3JhbnRfYnV1cnQgPC0gZGYkVjEyMl8zDQpkZiRwZXJjZW50X21pZ3JhbnRfc3RyYWF0IDwtIGRmJFYxMjJfNA0KDQpkZiRwZXJjZW50X3RlcnRlZHVjX2NsdWIgPC0gaWZlbHNlKCFpcy5uYShkZiRWMTIzXzEpLCBkZiRWMTIzXzEsIGRmJFYxMjNfMV9leHRyYSkNCmRmJHBlcmNlbnRfdGVydGVkdWNfdGVhbSA8LSBpZmVsc2UoIWlzLm5hKGRmJFYxMjNfMiksIGRmJFYxMjNfMiwgZGYkVjEyM18yX2V4dHJhKQ0KZGYkcGVyY2VudF90ZXJ0ZWR1Y19idXVydCA8LSBkZiRWMTIzXzMNCmRmJHBlcmNlbnRfdGVydGVkdWNfc3RyYWF0IDwtIGRmJFYxMjNfNA0KDQpkZiRpbnZfc3BvcnRjbHViIDwtIGlmZWxzZShkZiRWN2FfMSA9PSAxLCAxLCAwKQ0KDQojdG8gbG9uZyBmb3JtYXQNCg0KI2VhY2ggbGlzdCBlbGVtZW50IGNvbnRhaW5zIHRoZSBjaG9pY2VzIGZvciBlYWNoIHNldDoNCiN0aHVzLCByZWlzdGlqZC5saXN0W1szXV1bMl0gaXMgdGhlIGxldmVsIG9mIHRoZSB0cmF2ZWwgdGltZSBhdHRyaWJ1dGUgb2YgY2x1YiAyIGluIGNob2ljZS1zZXQgMy4NCg0KcmVpc3RpamQubGlzdCA8LSBsaXN0KA0KICBjKCJSZWlzdGlqZF9BMSIsICJSZWlzdGlqZF9BMiIpLA0KICBjKCJSZWlzdGlqZF9CMSIsICJSZWlzdGlqZF9CMiIpLA0KICBjKCJSZWlzdGlqZF9DMSIsICJSZWlzdGlqZF9DMiIpDQopDQoNCmZyZXF1ZW50aWUubGlzdCA8LSBsaXN0KA0KICBjKCJUcmFpbm5pbmdzZnJlcXVlbnRpZV9BMSIsICJUcmFpbm5pbmdzZnJlcXVlbnRpZV9BMiIpLA0KICBjKCJUcmFpbm5pbmdzZnJlcXVlbnRpZV9CMSIsICJUcmFpbm5pbmdzZnJlcXVlbnRpZV9CMiIpLA0KICBjKCJUcmFpbm5pbmdzZnJlcXVlbnRpZV9DMSIsICJUcmFpbm5pbmdzZnJlcXVlbnRpZV9DMiIpDQopDQoNCndlYnBhZ2luYS5saXN0IDwtIGxpc3QoDQogIGMoIldlYnBhZ2luYV9BMSIsICJXZWJwYWdpbmFfQTIiKSwNCiAgYygiV2VicGFnaW5hX0IxIiwgIldlYnBhZ2luYV9CMiIpLA0KICBjKCJXZWJwYWdpbmFfQzEiLCAiV2VicGFnaW5hX0MyIikNCikNCg0KYmVrZW5kZW4ubGlzdCA8LSBsaXN0KA0KICBjKCJCZWtlbmRlbl9BMSIsICJCZWtlbmRlbl9BMiIpLA0KICBjKCJCZWtlbmRlbl9CMSIsICJCZWtlbmRlbl9CMiIpLA0KICBjKCJCZWtlbmRlbl9DMSIsICJCZWtlbmRlbl9DMiIpDQopDQoNCmNsdWJvcGxlaWRpbmcubGlzdCAgPC0gbGlzdCgNCiAgYygiQ2x1YmxlZGVuX29wbGVpZGluZ19BMSIsICJDbHVibGVkZW5fb3BsZWlkaW5nX0EyIiksDQogIGMoIkNsdWJsZWRlbl9vcGxlaWRpbmdfQjEiLCAiQ2x1YmxlZGVuX29wbGVpZGluZ19CMiIpLA0KICBjKCJDbHVibGVkZW5fb3BsZWlkaW5nX0MxIiwgIkNsdWJsZWRlbl9vcGxlaWRpbmdfQzIiKQ0KKQ0KDQpjbHVibWlncmF0aWUubGlzdCAgPC0gbGlzdCgNCiAgYygiQ2x1YmxlZGVuX21pZ3JhdGllYWNodGVyZ3JvbmRfQTEiLCAiQ2x1YmxlZGVuX21pZ3JhdGllYWNodGVyZ3JvbmRfQTIiKSwNCiAgYygiQ2x1YmxlZGVuX21pZ3JhdGllYWNodGVyZ3JvbmRfQjEiLCAiQ2x1YmxlZGVuX21pZ3JhdGllYWNodGVyZ3JvbmRfQjIiKSwNCiAgYygiQ2x1YmxlZGVuX21pZ3JhdGllYWNodGVyZ3JvbmRfQzEiLCAiQ2x1YmxlZGVuX21pZ3JhdGllYWNodGVyZ3JvbmRfQzIiKQ0KKQ0KDQp0ZWFtb3BsZWlkaW5nLmxpc3QgIDwtIGxpc3QoDQogIGMoIlRyYWluaW5nc2dyb2VwX29wbGVpZGluZ19BMSIsICJUcmFpbmluZ3Nncm9lcF9vcGxlaWRpbmdfQTIiKSwNCiAgYygiVHJhaW5pbmdzZ3JvZXBfb3BsZWlkaW5nX0IxIiwgIlRyYWluaW5nc2dyb2VwX29wbGVpZGluZ19CMiIpLA0KICBjKCJUcmFpbmluZ3Nncm9lcF9vcGxlaWRpbmdfQzEiLCAiVHJhaW5pbmdzZ3JvZXBfb3BsZWlkaW5nX0MyIikNCikNCg0KdGVhbW1pZ3JhdGllLmxpc3QgIDwtIGxpc3QoDQogIGMoIlRyYWluaW5nc2dyb2VwX21pZ3JhdGllYWNodGVyZ3JvbmRfQTEiLCAiVHJhaW5pbmdzZ3JvZXBfbWlncmF0aWVhY2h0ZXJncm9uZF9BMiIpLA0KICBjKCJUcmFpbmluZ3Nncm9lcF9taWdyYXRpZWFjaHRlcmdyb25kX0IxIiwgIlRyYWluaW5nc2dyb2VwX21pZ3JhdGllYWNodGVyZ3JvbmRfQjIiKSwNCiAgYygiVHJhaW5pbmdzZ3JvZXBfbWlncmF0aWVhY2h0ZXJncm9uZF9DMSIsICJUcmFpbmluZ3Nncm9lcF9taWdyYXRpZWFjaHRlcmdyb25kX0MyIikNCikNCg0KY2hvc2VuIDwtIGMoIlYxMDdfMSIsICJWMTA3XzIiLCAiVjEwN18zIikNCg0KZm9yIChzZXQgaW4gMTozKSB7DQoNCiAgIyB0byBsb25nIGZvcm1hdA0KICANCiAgZm9yIChjaG9pY2UgaW4gMToyKSB7DQogICAgDQogICAgZGF0YSA8LSBhcy5kYXRhLmZyYW1lKGRmKQ0KICAgIGRhdGEkc2V0IDwtIHNldA0KICAgIGRhdGEkb3B0aW9ucyA8LSBjaG9pY2UNCiAgICBkYXRhJHRyYXZlbHRpbWUgPC0gZGF0YVssIG5hbWVzKGRhdGEpID09IHJlaXN0aWpkLmxpc3RbW3NldF1dW2Nob2ljZV1dDQogICAgZGF0YSR0cmFpbmZyZXEgPC0gZGF0YVssIG5hbWVzKGRhdGEpID09IGZyZXF1ZW50aWUubGlzdFtbc2V0XV1bY2hvaWNlXV0NCiAgICBkYXRhJHdlYnBhZ2UgPC0gZGF0YVssIG5hbWVzKGRhdGEpID09IHdlYnBhZ2luYS5saXN0W1tzZXRdXVtjaG9pY2VdXQ0KICAgIGRhdGEkYWNxdWFpbnRhbmNlcyA8LSBkYXRhWywgbmFtZXMoZGF0YSkgPT0gYmVrZW5kZW4ubGlzdFtbc2V0XV1bY2hvaWNlXV0NCiAgICBkYXRhJGVkdWNfY2x1YiA8LSBkYXRhWywgbmFtZXMoZGF0YSkgPT0gY2x1Ym9wbGVpZGluZy5saXN0W1tzZXRdXVtjaG9pY2VdXQ0KICAgIGRhdGEkZWR1Y190ZWFtIDwtIGRhdGFbLCBuYW1lcyhkYXRhKSA9PSB0ZWFtb3BsZWlkaW5nLmxpc3RbW3NldF1dW2Nob2ljZV1dDQogICAgZGF0YSRtaWdyYW50X2NsdWIgPC0gZGF0YVssIG5hbWVzKGRhdGEpID09IGNsdWJtaWdyYXRpZS5saXN0W1tzZXRdXVtjaG9pY2VdXQ0KICAgIGRhdGEkbWlncmFudF90ZWFtIDwtIGRhdGFbLCBuYW1lcyhkYXRhKSA9PSB0ZWFtbWlncmF0aWUubGlzdFtbc2V0XV1bY2hvaWNlXV0NCiAgICBkYXRhJGNob3NlbiA8LSBkYXRhWywgbmFtZXMoZGF0YSkgPT0gY2hvc2VuW3NldF1dDQogICAgDQogICAgZGF0YSA8LSBkYXRhWywgbmFtZXMoZGF0YSkgJWluJSBjKCJpZCIsICJ0ZXJ0X2VkdWMiLCAibWlncmF0aW9uIiwgIm1pZ3JhdGlvbl9udyIsICJMRUVGVElKRCIsICJHRVNMQUNIVDIiLCAiaW52X3Nwb3J0Y2x1YiIsICJwZXJjZW50X21pZ3JhbnRfY2x1YiIsICJwZXJjZW50X21pZ3JhbnRfdGVhbSIsICJwZXJjZW50X21pZ3JhbnRfYnV1cnQiLCAicGVyY2VudF9taWdyYW50X3N0cmFhdCIsICJwZXJjZW50X3RlcnRlZHVjX2NsdWIiLCAicGVyY2VudF90ZXJ0ZWR1Y190ZWFtIiwgInBlcmNlbnRfdGVydGVkdWNfYnV1cnQiLCAicGVyY2VudF90ZXJ0ZWR1Y19zdHJhYXQiLCAic2V0IiwgIm9wdGlvbnMiLCAidHJhdmVsdGltZSIsICJ0cmFpbmZyZXEiLCAid2VicGFnZSIsICJhY3F1YWludGFuY2VzIiwgImVkdWNfY2x1YiIsICJlZHVjX3RlYW0iLCAibWlncmFudF9jbHViIiwgIm1pZ3JhbnRfdGVhbSIsICJjaG9zZW4iKV0NCiAgICANCiAgICBpZihzZXQgPT0gMSAmIGNob2ljZSA9PSAxKSB7DQogICAgICBkZl9sb25nIDwtIGRhdGENCiAgICB9IGVsc2Ugew0KICAgICAgZGZfbG9uZyA8LSByYmluZChkZl9sb25nLCBkYXRhKQ0KICAgIH0NCiAgfQ0KfQ0KDQojIHJlb3JkZXINCmRmX2xvbmcgPC0gZGZfbG9uZ1tvcmRlcihkZl9sb25nJGlkLCBkZl9sb25nJHNldCwgZGZfbG9uZyRvcHRpb25zKSwgXQ0KDQojIGRlZmluZSB0aGUgY2hvaWNlDQpkZl9sb25nJGNob2ljZSA8LSAoZGZfbG9uZyRjaG9zZW4gPT0gYygxLCAyKVtkZl9sb25nJG9wdGlvbnNdKQ0KDQojIHJlY29kZSBudW1lcmljIGxldmVscywgYW5kIG1ha2Ugb2YgY2xhc3MgZmFjdG9yDQpkZl9sb25nIDwtIGRmX2xvbmcgJT4lIG11dGF0ZSgNCiAgDQogIHRyYXZlbHRpbWUgPSBjYXNlX3doZW4oDQogICAgdHJhdmVsdGltZSA9PSAxIH4gInRyYXZlbCB0aW1lOiA1IG1pbnV0ZXMiLA0KICAgIHRyYXZlbHRpbWUgPT0gMiB+ICJ0cmF2ZWwgdGltZTogMTUgbWludXRlcyIsDQogICAgdHJhdmVsdGltZSA9PSAzIH4gInRyYXZlbCB0aW1lOiAzMCBtaW51dGVzIiksDQogIA0KICB0cmFpbmZyZXEgPSBjYXNlX3doZW4oDQogICAgdHJhaW5mcmVxID09IDEgfiAidHJhaW5pbmcgZnJlcXVlbmN5OiBvbmNlIGEgd2VlayIsDQogICAgdHJhaW5mcmVxID09IDIgfiAidHJhaW5pbmcgZnJlcXVlbmN5OiBtb3JlIHRoYW4gb25jZSBhIHdlZWsiKSwNCiAgDQogIHdlYnBhZ2UgPSBjYXNlX3doZW4oDQogICAgd2VicGFnZSA9PSAxIH4gIndlYnBhZ2Ugc3RhdGVtZW50OiAnZXhlcmNpc2luZyB0b2dldGhlciBpcyBidWlsZGluZyBmcmllbmRzaGlwcyEnIiwNCiAgICB3ZWJwYWdlID09IDIgfiAid2VicGFnZSBzdGF0ZW1lbnQ6ICdsaWZ0IHlvdXJzZWxmIHRvIGEgaGlnaGVyIGxldmVsISciKSwNCiAgDQogIGFjcXVhaW50YW5jZXMgPSBjYXNlX3doZW4oDQogICAgYWNxdWFpbnRhbmNlcyA9PSAxIH4gImFjcXVhaW50YW5jZXM6IG11bHRpcGxlIiwNCiAgICBhY3F1YWludGFuY2VzID09IDIgfiAiYWNxdWFpbnRhbmNlczogbm9uZSIpLA0KICAgIA0KICBlZHVjX2NsdWIgPSBjYXNlX3doZW4oDQogICAgZWR1Y19jbHViID09IDEgfiAiY2x1YiBtZW1iZXJzIHdpdGggdGVydGlhcnkgZWR1Y2F0aW9uOiBhIHF1YXJ0ZXIgKDI1JSkiLA0KICAgIGVkdWNfY2x1YiA9PSAyIH4gImNsdWIgbWVtYmVycyB3aXRoIHRlcnRpYXJ5IGVkdWNhdGlvbjogaGFsZiAoNTAlKSIsDQogICAgZWR1Y19jbHViID09IDMgfiAiY2x1YiBtZW1iZXJzIHdpdGggdGVydGlhcnkgZWR1Y2F0aW9uOiB0aHJlZSBxdWFydGVycyAoNzUlKSIpLA0KICANCiAgbWlncmFudF9jbHViID0gY2FzZV93aGVuKA0KICAgIG1pZ3JhbnRfY2x1YiA9PSAxIH4gImNsdWIgbWVtYmVycyB3aXRoIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kOiBhIGZldyAoNSUpIiwNCiAgICBtaWdyYW50X2NsdWIgPT0gMiB+ICJjbHViIG1lbWJlcnMgd2l0aCBtaWdyYXRpb24gYmFja2dyb3VuZDogbWlub3JpdHkgKDEwJSkiLA0KICAgIG1pZ3JhbnRfY2x1YiA9PSAzIH4gImNsdWIgbWVtYmVycyB3aXRoIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kOiBhIHF1YXJ0ZXIgKDI1JSkiKSwNCiAgICANCiAgZWR1Y190ZWFtID0gY2FzZV93aGVuKA0KICAgIGVkdWNfdGVhbSA9PSAxIH4gImNvbnRhY3RzIHdpdGggdGVydGlhcnkgZWR1Y2F0aW9uOiBtaW5vcml0eSAoMTAlKSIsDQogICAgZWR1Y190ZWFtID09IDIgfiAiY29udGFjdHMgd2l0aCB0ZXJ0aWFyeSBlZHVjYXRpb246IGEgcXVhcnRlciAoMjUlKSIsDQogICAgZWR1Y190ZWFtID09IDMgfiAiY29udGFjdHMgd2l0aCB0ZXJ0aWFyeSBlZHVjYXRpb246IGhhbGYgKDUwJSkiLA0KICAgIGVkdWNfdGVhbSA9PSA0IH4gImNvbnRhY3RzIHdpdGggdGVydGlhcnkgZWR1Y2F0aW9uOiB0aHJlZSBxdWFydGVycyAoNzUlKSIsDQogICAgZWR1Y190ZWFtID09IDUgfiAiY29udGFjdHMgd2l0aCB0ZXJ0aWFyeSBlZHVjYXRpb246IG1ham9yaXR5ICg5MCUpIiksDQogICAgDQogIG1pZ3JhbnRfdGVhbSA9IGNhc2Vfd2hlbigNCiAgICBtaWdyYW50X3RlYW0gPT0gMSB+ICJjb250YWN0cyB3aXRoIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kOiBub25lICgwJSkiLA0KICAgIG1pZ3JhbnRfdGVhbSA9PSAyIH4gImNvbnRhY3RzIHdpdGggbWlncmF0aW9uIGJhY2tncm91bmQ6IGEgZmV3ICg1JSkiLA0KICAgIG1pZ3JhbnRfdGVhbSA9PSAzIH4gImNvbnRhY3RzIHdpdGggbWlncmF0aW9uIGJhY2tncm91bmQ6IG1pbm9yaXR5ICgxMCUpIiwNCiAgICBtaWdyYW50X3RlYW0gPT0gNCB+ICJjb250YWN0cyB3aXRoIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kOiBhIHF1YXJ0ZXIgKDI1JSkiLCAgICAgIA0KICAgIG1pZ3JhbnRfdGVhbSA9PSA1IH4gImNvbnRhY3RzIHdpdGggbWlncmF0aW9uIGJhY2tncm91bmQ6IGhhbGYgKDUwJSkiKQ0KICApDQoNCnJvdy5uYW1lcyhkZl9sb25nKSA8LSAxOm5yb3coZGZfbG9uZykNCg0KI3JlbW92ZSAiY2hvc2VuIiBhbmQgIm9wdGlvbnMiDQpuYW1lcyhkZl9sb25nKQ0KZGZfbG9uZyA8LSBkZl9sb25nWywgLWMoMjYsIDE3KV0NCg0KI2xhc3QsIHJlb3JkZXIgYXR0cmlidXRlIGxldmVscw0KZGZfbG9uZyR0cmF2ZWx0aW1lIDwtIGZhY3RvcihkZl9sb25nJHRyYXZlbHRpbWUsIGxldmVscyA9IHJldihjKCJ0cmF2ZWwgdGltZTogNSBtaW51dGVzIiwgInRyYXZlbCB0aW1lOiAxNSBtaW51dGVzIiwgInRyYXZlbCB0aW1lOiAzMCBtaW51dGVzIikpKQ0KZGZfbG9uZyR0cmFpbmZyZXEgPC0gZmFjdG9yKGRmX2xvbmckdHJhaW5mcmVxLCBsZXZlbHMgPSByZXYoYygidHJhaW5pbmcgZnJlcXVlbmN5OiBvbmNlIGEgd2VlayIsICJ0cmFpbmluZyBmcmVxdWVuY3k6IG1vcmUgdGhhbiBvbmNlIGEgd2VlayIpKSkNCmRmX2xvbmckd2VicGFnZSA8LSBmYWN0b3IoZGZfbG9uZyR3ZWJwYWdlLCBsZXZlbHMgPSByZXYoYygid2VicGFnZSBzdGF0ZW1lbnQ6ICdleGVyY2lzaW5nIHRvZ2V0aGVyIGlzIGJ1aWxkaW5nIGZyaWVuZHNoaXBzISciLCAid2VicGFnZSBzdGF0ZW1lbnQ6ICdsaWZ0IHlvdXJzZWxmIHRvIGEgaGlnaGVyIGxldmVsISciKSkpDQpkZl9sb25nJGFjcXVhaW50YW5jZXMgPC0gZmFjdG9yKGRmX2xvbmckYWNxdWFpbnRhbmNlcywgbGV2ZWxzID0gcmV2KGMoImFjcXVhaW50YW5jZXM6IG5vbmUiLCAiYWNxdWFpbnRhbmNlczogbXVsdGlwbGUiKSkpDQpkZl9sb25nJGVkdWNfY2x1YiA8LSBmYWN0b3IoZGZfbG9uZyRlZHVjX2NsdWIsIGxldmVscyA9IHJldihjKCJjbHViIG1lbWJlcnMgd2l0aCB0ZXJ0aWFyeSBlZHVjYXRpb246IGEgcXVhcnRlciAoMjUlKSIsICJjbHViIG1lbWJlcnMgd2l0aCB0ZXJ0aWFyeSBlZHVjYXRpb246IGhhbGYgKDUwJSkiLCAiY2x1YiBtZW1iZXJzIHdpdGggdGVydGlhcnkgZWR1Y2F0aW9uOiB0aHJlZSBxdWFydGVycyAoNzUlKSIpKSkNCmRmX2xvbmckbWlncmFudF9jbHViIDwtIGZhY3RvcihkZl9sb25nJG1pZ3JhbnRfY2x1YiwgbGV2ZWxzID0gcmV2KGMoImNsdWIgbWVtYmVycyB3aXRoIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kOiBhIGZldyAoNSUpIiwgImNsdWIgbWVtYmVycyB3aXRoIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kOiBtaW5vcml0eSAoMTAlKSIsICJjbHViIG1lbWJlcnMgd2l0aCBtaWdyYXRpb24gYmFja2dyb3VuZDogYSBxdWFydGVyICgyNSUpIikpKQ0KZGZfbG9uZyRlZHVjX3RlYW0gPC0gZmFjdG9yKGRmX2xvbmckZWR1Y190ZWFtLCBsZXZlbHMgPSByZXYoYygiY29udGFjdHMgd2l0aCB0ZXJ0aWFyeSBlZHVjYXRpb246IG1pbm9yaXR5ICgxMCUpIiwgImNvbnRhY3RzIHdpdGggdGVydGlhcnkgZWR1Y2F0aW9uOiBhIHF1YXJ0ZXIgKDI1JSkiLCAiY29udGFjdHMgd2l0aCB0ZXJ0aWFyeSBlZHVjYXRpb246IGhhbGYgKDUwJSkiLCAiY29udGFjdHMgd2l0aCB0ZXJ0aWFyeSBlZHVjYXRpb246IHRocmVlIHF1YXJ0ZXJzICg3NSUpIiwgImNvbnRhY3RzIHdpdGggdGVydGlhcnkgZWR1Y2F0aW9uOiBtYWpvcml0eSAoOTAlKSIpKSkNCmRmX2xvbmckbWlncmFudF90ZWFtIDwtIGZhY3RvcihkZl9sb25nJG1pZ3JhbnRfdGVhbSwgbGV2ZWxzID0gcmV2KGMoImNvbnRhY3RzIHdpdGggbWlncmF0aW9uIGJhY2tncm91bmQ6IG5vbmUgKDAlKSIsICJjb250YWN0cyB3aXRoIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kOiBhIGZldyAoNSUpIiwgImNvbnRhY3RzIHdpdGggbWlncmF0aW9uIGJhY2tncm91bmQ6IG1pbm9yaXR5ICgxMCUpIiwgImNvbnRhY3RzIHdpdGggbWlncmF0aW9uIGJhY2tncm91bmQ6IGEgcXVhcnRlciAoMjUlKSIsICJjb250YWN0cyB3aXRoIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kOiBoYWxmICg1MCUpIikpKQ0KYGBgIA0KDQo8YnI+DQoNCi0tLQ0KDQojIFNhdmUgZGF0YQ0KDQpgYGB7ciwgc2F2ZSwgZXZhbD1GQUxTRX0NCmZzYXZlKGRmX2xvbmcsICJjb25qb2ludF90cmlhbC5SZGEiKQ0KYGBgDQoNCi0tLQ0KDQojIFJlZmVyZW5jZXMNCg0KDQo=


Copyright © Rob Franken / Kasimir Dederichs / Dingeman Wiertz / Jochem Tolsma