Preparing data

Libraries

fpackage.check <- function(packages) { # (c) Jochem Tolsma
  lapply(packages, FUN = function(x) {
    if (!require(x, character.only = TRUE)) {
      install.packages(x, dependencies = TRUE)
      library(x, character.only = TRUE)
    }
  })
}
packages = c("tidyverse", "viridis", "kableExtra","ggridges", "viridis", "ggdark", "ggplot2", "patchwork", "sjPlot")
fpackage.check(packages)

Import the NSUM data and recreate the NSUM module.

#import nells file.
load(file = "data_analysis/data/data_processed/nells_data/2022-11-09_nells-nsum-prepped-data.rds")

Import the model estimates from the estimated NSUM models. I have choosen the model which uses Ibrahim for the ethnic names.

Main analysis results

if (file.exists(
  "data_analysis/results/nsum_output/main/combined_data/df_models_nsum_long.rds"
)) {
  load(file = "data_analysis/results/nsum_output/main/combined_data/df_models_nsum_long.rds")
} else {
  list_files <-
    as.list(
      dir(
        "data_analysis/results/nsum_output/main/model/",
        full.names = T
      )
    )
  #create loop lists
  kds <- list()
  kdssd <- list()
  data <- list()
  list_df <- list()
  
  #loop to extract information
  for (i in 1:length(list_files)) {
    #i = 1
    print(paste0("Number ", i, " of ", length(list_files)))
    load(list_files[[i]])
    kds[[i]] <-
      rowMeans(degree$d.values, na.rm = TRUE) # calculate rowmean of netsize iterations: so the retained chains
    kdssd[[i]] <-
      matrixStats::rowSds(degree$d.values) # calculate sd of 4k estimates per row: sd for those values
    data[[i]] <- cbind(kds[[i]], kdssd[[i]]) # combine them
    list_df[[i]] <-
      cbind(as_tibble(data[[i]]), nells_nsum$id) # add NELLS id variable
    strings <-
      str_split(str_extract(list_files[[i]][1], pattern = "estimates.+"),
                pattern = "_")  # add holdout number
    list_df[[i]] <- list_df[[i]] %>%
      mutate(
        holdout = as.numeric(str_extract(strings[[1]][2], pattern = "[[:digit:]]{1,}")))
  }
    #combine results and save
    df_models_nsum_long <- list_df %>%
      bind_rows() %>%
      rename(mean = V1,
             sd = V2,
             id = 3)
    #save image
    save(df_models_nsum_long, file = "data_analysis/results/nsum_output/main/combined_data/df_models_nsum_long.rds")
}

Holdout sensitivity analysis

In the estimation we need to set one of the known populations to missing. We will now check how sensitive variables ommission is for the network size estimate and see whether some groups are more sensitive to this than others.

First of all, create a table of median, mean, and the SD of network size for each unknown variable.

#create summary table
nsum_sum_long <- df_models_nsum_long %>%
  mutate(Unknown = factor(
    holdout,
    levels = 1:16,
    labels = c(
      "Daan",
      "Kevin",
      "Edwin",
      "Albert",
      "Emma",
      "Linda",
      "Ingrid",
      "Willemina",
      "Ibrahim",
      "Prison",
      "MBO",
      "HBO",
      "University",
      "Secundary education",
      "Owns second home",
      "Unemployed"
    )
  )) %>%
  group_by(Unknown) %>%
  summarise(
    Mean = mean(mean),
    Median = median(mean),
    SD = mean(sd),
    .groups = "drop"
  )

nsum_sum_long %>% 
  kbl() %>% 
  kable_paper(full_width = F,
              )
Unknown Mean Median SD
Daan 935.0754 699.8811 337.5926
Kevin 969.7256 736.7016 351.2121
Edwin 1003.2393 766.4572 355.3362
Albert 1042.2279 788.9354 364.7517
Emma 960.7677 720.3704 340.0373
Linda 996.7474 765.4803 349.0902
Ingrid 1040.9216 800.1643 373.5502
Willemina 1023.1083 776.8069 361.9219
Ibrahim 803.5329 629.7463 265.5233
Prison 1035.6435 797.1834 369.2989
MBO 1025.8919 802.1888 352.6240
HBO 1035.5729 811.7983 358.5143
University 1018.8204 782.1697 349.7081
Secundary education 1034.6165 809.8754 361.0537
Owns second home 1025.6079 789.9623 357.7683
Unemployed 1034.3700 801.8969 363.9277

In mean network size there is realtively litte difference in the different size estimates with different unkown populations. The exception is when we set ibrahim to unknown, the mean and median size drops marekdly. Also, the median of network sizes is more sensitive than the mean network size. In the figure below, we show the differneces in boxplot which shows a similar pciture. Overall, bar the exception of Ibrahim, differences are small and neglible.

df_models_nsum_long %>%
  mutate(ommitted = factor(
    holdout,
    levels = 1:16,
    labels = c(
      "Daan",
      "Kevin",
      "Edwin",
      "Albert",
      "Emma",
      "Linda",
      "Ingrid",
      "Willemina",
      "Ibrahim",
      "Prison",
      "MBO",
      "HBO",
      "University",
      "Secundary education",
      "Owns second home",
      "Unemployed"
    )
  )) %>% 
  ggplot(aes(x = mean,
             y = ommitted)) +
  geom_boxplot(position = position_dodge(width = 1)) + 
  scale_fill_viridis_d(option = "D") +
  scale_color_viridis_d(option = "D") + 
  theme_minimal() +
  theme(legend.position = 'none',
        #plot.background = element_rect(fill = '#404040', colour = '#404040'),
        #panel.background = element_rect(fill = '#404040', colour = '#404040'),
        axis.title.y = element_text(hjust = 1),
        axis.title.x = element_text(hjust = 1),
        text = element_text(colour = "black"),
        strip.text = element_text(colour = "black")
        ) +
  labs(y = "Unknown population",
       x = "Extended network size",
       title = "Fig.1: Network size estimates for different unknown populations")

This only showed differences at the aggregate level. We also want to know whether these different size estimates are also robust on the individual. For this reason we created a correlation plot which shows the correlation between network size of the different unknown populations. OVerall these seem reliable ( r > 0.85), however, we find a discrepancy between names and categories. The within correlation between these is larger (~95) than the between these groups (~85).

#create wide file for correlation plot
df_models_nsum_wide <- df_models_nsum_long %>% 
  mutate(Ommitted = factor(
    holdout,
    levels = 1:16,
    labels = c(
      "Daan",
      "Kevin",
      "Edwin",
      "Albert",
      "Emma",
      "Linda",
      "Ingrid",
      "Willemina",
      "Ibrahim",
      "Prison",
      "MBO",
      "HBO",
      "University",
      "Secundary education",
      "Owns second home",
      "Unemployed"
    )
  )) %>% 
  arrange(id, Ommitted) %>% 
  select(-sd, -holdout) %>% 
  tidyr::pivot_wider(names_from = c(Ommitted),
              values_from = c(mean)) 

#create correlation file
cor_df <- df_models_nsum_wide %>% 
  select(-id) %>% 
  select(!contains("sd")) %>% 
  cor() %>% 
  as_tibble() %>% 
  mutate(variable_x = factor(1:16,
                             levels = 1:16,
                             labels = c(
      "Daan",
      "Kevin",
      "Edwin",
      "Albert",
      "Emma",
      "Linda",
      "Ingrid",
      "Willemina",
      "Ibrahim",
      "Prison",
      "MBO",
      "HBO",
      "University",
      "Secundary education",
      "Owns second home",
      "Unemployed"
    ))) %>% 
  tidyr::pivot_longer(1:16,
               names_to = "variable_y",
               values_to = "value")  %>% 
  mutate(variable_y = fct_relevel(variable_y,
                                  c(
      "Daan",
      "Kevin",
      "Edwin",
      "Albert",
      "Emma",
      "Linda",
      "Ingrid",
      "Willemina",
      "Ibrahim",
      "Prison",
      "MBO",
      "HBO",
      "University",
      "Secundary education",
      "Owns second home",
      "Unemployed"
    )))

#correlation plot
cor_df %>% 
  ggplot(aes(x = variable_x, y = variable_y, fill = value)) +
  geom_tile(alpha = 0.5) +
  geom_text(aes(label = round(value, 2))) +
  theme_minimal() +
  scale_fill_viridis(option = "D") + 
  theme(axis.text.x = element_text(angle = 45,
                                   vjust = 0.4),
        #plot.background = element_rect(fill = "#D4D9DE", colour = "#D4D9DE"),
        #panel.background = element_rect(fill ="#D4D9DE", colour = "#D4D9DE"),
        axis.title.y = element_text(hjust = 1),
        axis.title.x = element_text(hjust = 1),
        text = element_text(colour = "black"),
        strip.text = element_text(colour = "black")
        ) +
  labs(x = "Unknown population",
       y = "Unknown population",
       title = "Fig.2: Correlations between network size estimates from models with different unknown populations")

Since we are interested in group differences in network size, we would want to know whether groups differ in their sensitivity to different specifications of the main NSUM model. Based on the figure presented below, there are no major group differences bar Ibrahim.

nells_test_df <- df_models_nsum_long %>% 
  left_join(nells_nsum) 

nells_test_df %>% 
  mutate(ommitted = factor(holdout,
                           levels = 1:16,
                             labels = c(
      "Daan",
      "Kevin",
      "Edwin",
      "Albert",
      "Emma",
      "Linda",
      "Ingrid",
      "Willemina",
      "Ibrahim",
      "Prison",
      "MBO",
      "HBO",
      "University",
      "Secundary education",
      "Owns second home",
      "Unemployed"
    ))) %>% 
  ggplot(aes(x = mean,
             y = ommitted,
             color = migration_background_fac)) +
  geom_boxplot(position = position_dodge(width = 1)
               #,
               #fill = "#D4D9DE"
               ) +
  facet_wrap(vars(migration_background_fac)) +
  scale_fill_viridis_d(option = "D") +
  scale_color_viridis_d(option = "D") + 
  theme_minimal() +
  theme(legend.position = 'none',
        #plot.background = element_rect(fill = "#D4D9DE", colour = "#D4D9DE"),
        #panel.background = element_rect(fill ="#D4D9DE", colour = "#D4D9DE"),
        axis.title.y = element_text(hjust = 1),
        axis.title.x = element_text(hjust = 1),
        text = element_text(colour = "black"),
        strip.text = element_text(colour = "black")
        ) +
  labs(y = "Unknown population",
       x = "Extended network size",
       title = "Fig.3: Group differences in sensitivy to different unknown populations")

LS0tDQp0aXRsZTogIlNpemUgUm9idXN0bmVzcyBBbmFseXNpcyINCmF1dGhvcjogIlRoaWptZW4gSmVyb2Vuc2UiDQpkYXRlOiAiTGFzdCBjb21waWxlZCBvbiBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZGVwdGg6IDMNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQotLS0NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChjYWNoZSA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCByZXN1bHRzID0gImFzaXMiLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0KYGBgDQoNCiMgUHJlcGFyaW5nIGRhdGENCg0KTGlicmFyaWVzDQoNCmBgYHtyIGxpYnJhcmllcyBhbmQgZmlsZXMsIHJlc3VsdHM9J2hpZGUnfQ0KZnBhY2thZ2UuY2hlY2sgPC0gZnVuY3Rpb24ocGFja2FnZXMpIHsgIyAoYykgSm9jaGVtIFRvbHNtYQ0KICBsYXBwbHkocGFja2FnZXMsIEZVTiA9IGZ1bmN0aW9uKHgpIHsNCiAgICBpZiAoIXJlcXVpcmUoeCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgew0KICAgICAgaW5zdGFsbC5wYWNrYWdlcyh4LCBkZXBlbmRlbmNpZXMgPSBUUlVFKQ0KICAgICAgbGlicmFyeSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpDQogICAgfQ0KICB9KQ0KfQ0KcGFja2FnZXMgPSBjKCJ0aWR5dmVyc2UiLCAidmlyaWRpcyIsICJrYWJsZUV4dHJhIiwiZ2dyaWRnZXMiLCAidmlyaWRpcyIsICJnZ2RhcmsiLCAiZ2dwbG90MiIsICJwYXRjaHdvcmsiLCAic2pQbG90IikNCmZwYWNrYWdlLmNoZWNrKHBhY2thZ2VzKQ0KYGBgDQoNCkltcG9ydCB0aGUgTlNVTSBkYXRhIGFuZCByZWNyZWF0ZSB0aGUgTlNVTSBtb2R1bGUuIA0KDQpgYGB7ciBmaWxlc30NCiNpbXBvcnQgbmVsbHMgZmlsZS4NCmxvYWQoZmlsZSA9ICJkYXRhX2FuYWx5c2lzL2RhdGEvZGF0YV9wcm9jZXNzZWQvbmVsbHNfZGF0YS8yMDIyLTExLTA5X25lbGxzLW5zdW0tcHJlcHBlZC1kYXRhLnJkcyIpDQoNCmBgYA0KDQpJbXBvcnQgdGhlIG1vZGVsIGVzdGltYXRlcyBmcm9tIHRoZSBlc3RpbWF0ZWQgTlNVTSBtb2RlbHMuIEkgaGF2ZSBjaG9vc2VuIHRoZSBtb2RlbCB3aGljaCB1c2VzIElicmFoaW0gZm9yIHRoZSBldGhuaWMgbmFtZXMuDQoNCiMgTWFpbiBhbmFseXNpcyByZXN1bHRzDQpgYGB7ciBpbXBvcnQgcmVzdWx0cywgcmVzdWx0cz0naGlkZSd9DQoNCmlmIChmaWxlLmV4aXN0cygNCiAgImRhdGFfYW5hbHlzaXMvcmVzdWx0cy9uc3VtX291dHB1dC9tYWluL2NvbWJpbmVkX2RhdGEvZGZfbW9kZWxzX25zdW1fbG9uZy5yZHMiDQopKSB7DQogIGxvYWQoZmlsZSA9ICJkYXRhX2FuYWx5c2lzL3Jlc3VsdHMvbnN1bV9vdXRwdXQvbWFpbi9jb21iaW5lZF9kYXRhL2RmX21vZGVsc19uc3VtX2xvbmcucmRzIikNCn0gZWxzZSB7DQogIGxpc3RfZmlsZXMgPC0NCiAgICBhcy5saXN0KA0KICAgICAgZGlyKA0KICAgICAgICAiZGF0YV9hbmFseXNpcy9yZXN1bHRzL25zdW1fb3V0cHV0L21haW4vbW9kZWwvIiwNCiAgICAgICAgZnVsbC5uYW1lcyA9IFQNCiAgICAgICkNCiAgICApDQogICNjcmVhdGUgbG9vcCBsaXN0cw0KICBrZHMgPC0gbGlzdCgpDQogIGtkc3NkIDwtIGxpc3QoKQ0KICBkYXRhIDwtIGxpc3QoKQ0KICBsaXN0X2RmIDwtIGxpc3QoKQ0KICANCiAgI2xvb3AgdG8gZXh0cmFjdCBpbmZvcm1hdGlvbg0KICBmb3IgKGkgaW4gMTpsZW5ndGgobGlzdF9maWxlcykpIHsNCiAgICAjaSA9IDENCiAgICBwcmludChwYXN0ZTAoIk51bWJlciAiLCBpLCAiIG9mICIsIGxlbmd0aChsaXN0X2ZpbGVzKSkpDQogICAgbG9hZChsaXN0X2ZpbGVzW1tpXV0pDQogICAga2RzW1tpXV0gPC0NCiAgICAgIHJvd01lYW5zKGRlZ3JlZSRkLnZhbHVlcywgbmEucm0gPSBUUlVFKSAjIGNhbGN1bGF0ZSByb3dtZWFuIG9mIG5ldHNpemUgaXRlcmF0aW9uczogc28gdGhlIHJldGFpbmVkIGNoYWlucw0KICAgIGtkc3NkW1tpXV0gPC0NCiAgICAgIG1hdHJpeFN0YXRzOjpyb3dTZHMoZGVncmVlJGQudmFsdWVzKSAjIGNhbGN1bGF0ZSBzZCBvZiA0ayBlc3RpbWF0ZXMgcGVyIHJvdzogc2QgZm9yIHRob3NlIHZhbHVlcw0KICAgIGRhdGFbW2ldXSA8LSBjYmluZChrZHNbW2ldXSwga2Rzc2RbW2ldXSkgIyBjb21iaW5lIHRoZW0NCiAgICBsaXN0X2RmW1tpXV0gPC0NCiAgICAgIGNiaW5kKGFzX3RpYmJsZShkYXRhW1tpXV0pLCBuZWxsc19uc3VtJGlkKSAjIGFkZCBORUxMUyBpZCB2YXJpYWJsZQ0KICAgIHN0cmluZ3MgPC0NCiAgICAgIHN0cl9zcGxpdChzdHJfZXh0cmFjdChsaXN0X2ZpbGVzW1tpXV1bMV0sIHBhdHRlcm4gPSAiZXN0aW1hdGVzLisiKSwNCiAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIl8iKSAgIyBhZGQgaG9sZG91dCBudW1iZXINCiAgICBsaXN0X2RmW1tpXV0gPC0gbGlzdF9kZltbaV1dICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBob2xkb3V0ID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdChzdHJpbmdzW1sxXV1bMl0sIHBhdHRlcm4gPSAiW1s6ZGlnaXQ6XV17MSx9IikpKQ0KICB9DQogICAgI2NvbWJpbmUgcmVzdWx0cyBhbmQgc2F2ZQ0KICAgIGRmX21vZGVsc19uc3VtX2xvbmcgPC0gbGlzdF9kZiAlPiUNCiAgICAgIGJpbmRfcm93cygpICU+JQ0KICAgICAgcmVuYW1lKG1lYW4gPSBWMSwNCiAgICAgICAgICAgICBzZCA9IFYyLA0KICAgICAgICAgICAgIGlkID0gMykNCiAgICAjc2F2ZSBpbWFnZQ0KICAgIHNhdmUoZGZfbW9kZWxzX25zdW1fbG9uZywgZmlsZSA9ICJkYXRhX2FuYWx5c2lzL3Jlc3VsdHMvbnN1bV9vdXRwdXQvbWFpbi9jb21iaW5lZF9kYXRhL2RmX21vZGVsc19uc3VtX2xvbmcucmRzIikNCn0NCmBgYA0KDQoNCiMgSG9sZG91dCBzZW5zaXRpdml0eSBhbmFseXNpcw0KDQpJbiB0aGUgZXN0aW1hdGlvbiB3ZSBuZWVkIHRvIHNldCBvbmUgb2YgdGhlIGtub3duIHBvcHVsYXRpb25zIHRvIG1pc3NpbmcuIFdlIHdpbGwgbm93IGNoZWNrIGhvdyBzZW5zaXRpdmUgdmFyaWFibGVzIG9tbWlzc2lvbiBpcyBmb3IgdGhlIG5ldHdvcmsgc2l6ZSBlc3RpbWF0ZSBhbmQgc2VlIHdoZXRoZXIgc29tZSBncm91cHMgYXJlIG1vcmUgc2Vuc2l0aXZlIHRvIHRoaXMgdGhhbiBvdGhlcnMuIA0KDQpGaXJzdCBvZiBhbGwsIGNyZWF0ZSBhIHRhYmxlIG9mIG1lZGlhbiwgbWVhbiwgYW5kIHRoZSBTRCBvZiBuZXR3b3JrIHNpemUgZm9yIGVhY2ggdW5rbm93biB2YXJpYWJsZS4gDQoNCmBgYHtyIFVua25vd24gdGFibGV9DQojY3JlYXRlIHN1bW1hcnkgdGFibGUNCm5zdW1fc3VtX2xvbmcgPC0gZGZfbW9kZWxzX25zdW1fbG9uZyAlPiUNCiAgbXV0YXRlKFVua25vd24gPSBmYWN0b3IoDQogICAgaG9sZG91dCwNCiAgICBsZXZlbHMgPSAxOjE2LA0KICAgIGxhYmVscyA9IGMoDQogICAgICAiRGFhbiIsDQogICAgICAiS2V2aW4iLA0KICAgICAgIkVkd2luIiwNCiAgICAgICJBbGJlcnQiLA0KICAgICAgIkVtbWEiLA0KICAgICAgIkxpbmRhIiwNCiAgICAgICJJbmdyaWQiLA0KICAgICAgIldpbGxlbWluYSIsDQogICAgICAiSWJyYWhpbSIsDQogICAgICAiUHJpc29uIiwNCiAgICAgICJNQk8iLA0KICAgICAgIkhCTyIsDQogICAgICAiVW5pdmVyc2l0eSIsDQogICAgICAiU2VjdW5kYXJ5IGVkdWNhdGlvbiIsDQogICAgICAiT3ducyBzZWNvbmQgaG9tZSIsDQogICAgICAiVW5lbXBsb3llZCINCiAgICApDQogICkpICU+JQ0KICBncm91cF9ieShVbmtub3duKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1lYW4gPSBtZWFuKG1lYW4pLA0KICAgIE1lZGlhbiA9IG1lZGlhbihtZWFuKSwNCiAgICBTRCA9IG1lYW4oc2QpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQpuc3VtX3N1bV9sb25nICU+JSANCiAga2JsKCkgJT4lIA0KICBrYWJsZV9wYXBlcihmdWxsX3dpZHRoID0gRiwNCiAgICAgICAgICAgICAgKQ0KYGBgDQpJbiBtZWFuIG5ldHdvcmsgc2l6ZSB0aGVyZSBpcyByZWFsdGl2ZWx5IGxpdHRlIGRpZmZlcmVuY2UgaW4gdGhlIGRpZmZlcmVudCBzaXplIGVzdGltYXRlcyB3aXRoIGRpZmZlcmVudCB1bmtvd24gcG9wdWxhdGlvbnMuIFRoZSBleGNlcHRpb24gaXMgd2hlbiB3ZSBzZXQgaWJyYWhpbSB0byB1bmtub3duLCB0aGUgbWVhbiBhbmQgbWVkaWFuIHNpemUgZHJvcHMgbWFyZWtkbHkuIEFsc28sIHRoZSBtZWRpYW4gb2YgbmV0d29yayBzaXplcyBpcyBtb3JlIHNlbnNpdGl2ZSB0aGFuIHRoZSBtZWFuIG5ldHdvcmsgc2l6ZS4gSW4gdGhlIGZpZ3VyZSBiZWxvdywgd2Ugc2hvdyB0aGUgZGlmZmVybmVjZXMgaW4gYm94cGxvdCB3aGljaCBzaG93cyBhIHNpbWlsYXIgcGNpdHVyZS4gT3ZlcmFsbCwgYmFyIHRoZSBleGNlcHRpb24gb2YgSWJyYWhpbSwgZGlmZmVyZW5jZXMgYXJlIHNtYWxsIGFuZCBuZWdsaWJsZS4gIA0KDQpgYGB7ciBVbmtub3duIHN1bSBncmFwaH0NCmRmX21vZGVsc19uc3VtX2xvbmcgJT4lDQogIG11dGF0ZShvbW1pdHRlZCA9IGZhY3RvcigNCiAgICBob2xkb3V0LA0KICAgIGxldmVscyA9IDE6MTYsDQogICAgbGFiZWxzID0gYygNCiAgICAgICJEYWFuIiwNCiAgICAgICJLZXZpbiIsDQogICAgICAiRWR3aW4iLA0KICAgICAgIkFsYmVydCIsDQogICAgICAiRW1tYSIsDQogICAgICAiTGluZGEiLA0KICAgICAgIkluZ3JpZCIsDQogICAgICAiV2lsbGVtaW5hIiwNCiAgICAgICJJYnJhaGltIiwNCiAgICAgICJQcmlzb24iLA0KICAgICAgIk1CTyIsDQogICAgICAiSEJPIiwNCiAgICAgICJVbml2ZXJzaXR5IiwNCiAgICAgICJTZWN1bmRhcnkgZWR1Y2F0aW9uIiwNCiAgICAgICJPd25zIHNlY29uZCBob21lIiwNCiAgICAgICJVbmVtcGxveWVkIg0KICAgICkNCiAgKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBtZWFuLA0KICAgICAgICAgICAgIHkgPSBvbW1pdHRlZCkpICsNCiAgZ2VvbV9ib3hwbG90KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSkgKyANCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uID0gIkQiKSArDQogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZChvcHRpb24gPSAiRCIpICsgDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJywNCiAgICAgICAgI3Bsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gJyM0MDQwNDAnLCBjb2xvdXIgPSAnIzQwNDA0MCcpLA0KICAgICAgICAjcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gJyM0MDQwNDAnLCBjb2xvdXIgPSAnIzQwNDA0MCcpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMSksDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsYWNrIiksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsYWNrIikNCiAgICAgICAgKSArDQogIGxhYnMoeSA9ICJVbmtub3duIHBvcHVsYXRpb24iLA0KICAgICAgIHggPSAiRXh0ZW5kZWQgbmV0d29yayBzaXplIiwNCiAgICAgICB0aXRsZSA9ICJGaWcuMTogTmV0d29yayBzaXplIGVzdGltYXRlcyBmb3IgZGlmZmVyZW50IHVua25vd24gcG9wdWxhdGlvbnMiKQ0KDQoNCmBgYA0KVGhpcyBvbmx5IHNob3dlZCBkaWZmZXJlbmNlcyBhdCB0aGUgYWdncmVnYXRlIGxldmVsLiBXZSBhbHNvIHdhbnQgdG8ga25vdyB3aGV0aGVyIHRoZXNlIGRpZmZlcmVudCBzaXplIGVzdGltYXRlcyBhcmUgYWxzbyByb2J1c3Qgb24gdGhlIGluZGl2aWR1YWwuIEZvciB0aGlzIHJlYXNvbiB3ZSBjcmVhdGVkIGEgY29ycmVsYXRpb24gcGxvdCB3aGljaCBzaG93cyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBuZXR3b3JrIHNpemUgb2YgdGhlIGRpZmZlcmVudCB1bmtub3duIHBvcHVsYXRpb25zLiBPVmVyYWxsIHRoZXNlIHNlZW0gcmVsaWFibGUgKCByID4gMC44NSksIGhvd2V2ZXIsIHdlIGZpbmQgYSBkaXNjcmVwYW5jeSBiZXR3ZWVuIG5hbWVzIGFuZCBjYXRlZ29yaWVzLiBUaGUgd2l0aGluIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlc2UgaXMgbGFyZ2VyICh+OTUpIHRoYW4gdGhlIGJldHdlZW4gdGhlc2UgZ3JvdXBzICh+ODUpLg0KDQpgYGB7ciBjb3JyIHBsb3QsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTAsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQ0KI2NyZWF0ZSB3aWRlIGZpbGUgZm9yIGNvcnJlbGF0aW9uIHBsb3QNCmRmX21vZGVsc19uc3VtX3dpZGUgPC0gZGZfbW9kZWxzX25zdW1fbG9uZyAlPiUgDQogIG11dGF0ZShPbW1pdHRlZCA9IGZhY3RvcigNCiAgICBob2xkb3V0LA0KICAgIGxldmVscyA9IDE6MTYsDQogICAgbGFiZWxzID0gYygNCiAgICAgICJEYWFuIiwNCiAgICAgICJLZXZpbiIsDQogICAgICAiRWR3aW4iLA0KICAgICAgIkFsYmVydCIsDQogICAgICAiRW1tYSIsDQogICAgICAiTGluZGEiLA0KICAgICAgIkluZ3JpZCIsDQogICAgICAiV2lsbGVtaW5hIiwNCiAgICAgICJJYnJhaGltIiwNCiAgICAgICJQcmlzb24iLA0KICAgICAgIk1CTyIsDQogICAgICAiSEJPIiwNCiAgICAgICJVbml2ZXJzaXR5IiwNCiAgICAgICJTZWN1bmRhcnkgZWR1Y2F0aW9uIiwNCiAgICAgICJPd25zIHNlY29uZCBob21lIiwNCiAgICAgICJVbmVtcGxveWVkIg0KICAgICkNCiAgKSkgJT4lIA0KICBhcnJhbmdlKGlkLCBPbW1pdHRlZCkgJT4lIA0KICBzZWxlY3QoLXNkLCAtaG9sZG91dCkgJT4lIA0KICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGMoT21taXR0ZWQpLA0KICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGMobWVhbikpIA0KDQojY3JlYXRlIGNvcnJlbGF0aW9uIGZpbGUNCmNvcl9kZiA8LSBkZl9tb2RlbHNfbnN1bV93aWRlICU+JSANCiAgc2VsZWN0KC1pZCkgJT4lIA0KICBzZWxlY3QoIWNvbnRhaW5zKCJzZCIpKSAlPiUgDQogIGNvcigpICU+JSANCiAgYXNfdGliYmxlKCkgJT4lIA0KICBtdXRhdGUodmFyaWFibGVfeCA9IGZhY3RvcigxOjE2LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSAxOjE2LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKA0KICAgICAgIkRhYW4iLA0KICAgICAgIktldmluIiwNCiAgICAgICJFZHdpbiIsDQogICAgICAiQWxiZXJ0IiwNCiAgICAgICJFbW1hIiwNCiAgICAgICJMaW5kYSIsDQogICAgICAiSW5ncmlkIiwNCiAgICAgICJXaWxsZW1pbmEiLA0KICAgICAgIklicmFoaW0iLA0KICAgICAgIlByaXNvbiIsDQogICAgICAiTUJPIiwNCiAgICAgICJIQk8iLA0KICAgICAgIlVuaXZlcnNpdHkiLA0KICAgICAgIlNlY3VuZGFyeSBlZHVjYXRpb24iLA0KICAgICAgIk93bnMgc2Vjb25kIGhvbWUiLA0KICAgICAgIlVuZW1wbG95ZWQiDQogICAgKSkpICU+JSANCiAgdGlkeXI6OnBpdm90X2xvbmdlcigxOjE2LA0KICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAidmFyaWFibGVfeSIsDQogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiKSAgJT4lIA0KICBtdXRhdGUodmFyaWFibGVfeSA9IGZjdF9yZWxldmVsKHZhcmlhYmxlX3ksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygNCiAgICAgICJEYWFuIiwNCiAgICAgICJLZXZpbiIsDQogICAgICAiRWR3aW4iLA0KICAgICAgIkFsYmVydCIsDQogICAgICAiRW1tYSIsDQogICAgICAiTGluZGEiLA0KICAgICAgIkluZ3JpZCIsDQogICAgICAiV2lsbGVtaW5hIiwNCiAgICAgICJJYnJhaGltIiwNCiAgICAgICJQcmlzb24iLA0KICAgICAgIk1CTyIsDQogICAgICAiSEJPIiwNCiAgICAgICJVbml2ZXJzaXR5IiwNCiAgICAgICJTZWN1bmRhcnkgZWR1Y2F0aW9uIiwNCiAgICAgICJPd25zIHNlY29uZCBob21lIiwNCiAgICAgICJVbmVtcGxveWVkIg0KICAgICkpKQ0KDQojY29ycmVsYXRpb24gcGxvdA0KY29yX2RmICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gdmFyaWFibGVfeCwgeSA9IHZhcmlhYmxlX3ksIGZpbGwgPSB2YWx1ZSkpICsNCiAgZ2VvbV90aWxlKGFscGhhID0gMC41KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh2YWx1ZSwgMikpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpcyhvcHRpb24gPSAiRCIpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZqdXN0ID0gMC40KSwNCiAgICAgICAgI3Bsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNENEQ5REUiLCBjb2xvdXIgPSAiI0Q0RDlERSIpLA0KICAgICAgICAjcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0iI0Q0RDlERSIsIGNvbG91ciA9ICIjRDREOURFIiksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDEpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siKQ0KICAgICAgICApICsNCiAgbGFicyh4ID0gIlVua25vd24gcG9wdWxhdGlvbiIsDQogICAgICAgeSA9ICJVbmtub3duIHBvcHVsYXRpb24iLA0KICAgICAgIHRpdGxlID0gIkZpZy4yOiBDb3JyZWxhdGlvbnMgYmV0d2VlbiBuZXR3b3JrIHNpemUgZXN0aW1hdGVzIGZyb20gbW9kZWxzIHdpdGggZGlmZmVyZW50IHVua25vd24gcG9wdWxhdGlvbnMiKQ0KYGBgDQoNClNpbmNlIHdlIGFyZSBpbnRlcmVzdGVkIGluIGdyb3VwIGRpZmZlcmVuY2VzIGluIG5ldHdvcmsgc2l6ZSwgd2Ugd291bGQgd2FudCB0byBrbm93IHdoZXRoZXIgZ3JvdXBzIGRpZmZlciBpbiB0aGVpciBzZW5zaXRpdml0eSB0byBkaWZmZXJlbnQgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIG1haW4gTlNVTSBtb2RlbC4gQmFzZWQgb24gdGhlIGZpZ3VyZSBwcmVzZW50ZWQgYmVsb3csIHRoZXJlIGFyZSBubyBtYWpvciBncm91cCBkaWZmZXJlbmNlcyBiYXIgSWJyYWhpbS4gDQoNCmBgYHtyIGhvbGRvdXQgMiwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9N30NCm5lbGxzX3Rlc3RfZGYgPC0gZGZfbW9kZWxzX25zdW1fbG9uZyAlPiUgDQogIGxlZnRfam9pbihuZWxsc19uc3VtKSANCg0KbmVsbHNfdGVzdF9kZiAlPiUgDQogIG11dGF0ZShvbW1pdHRlZCA9IGZhY3Rvcihob2xkb3V0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gMToxNiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygNCiAgICAgICJEYWFuIiwNCiAgICAgICJLZXZpbiIsDQogICAgICAiRWR3aW4iLA0KICAgICAgIkFsYmVydCIsDQogICAgICAiRW1tYSIsDQogICAgICAiTGluZGEiLA0KICAgICAgIkluZ3JpZCIsDQogICAgICAiV2lsbGVtaW5hIiwNCiAgICAgICJJYnJhaGltIiwNCiAgICAgICJQcmlzb24iLA0KICAgICAgIk1CTyIsDQogICAgICAiSEJPIiwNCiAgICAgICJVbml2ZXJzaXR5IiwNCiAgICAgICJTZWN1bmRhcnkgZWR1Y2F0aW9uIiwNCiAgICAgICJPd25zIHNlY29uZCBob21lIiwNCiAgICAgICJVbmVtcGxveWVkIg0KICAgICkpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IG1lYW4sDQogICAgICAgICAgICAgeSA9IG9tbWl0dGVkLA0KICAgICAgICAgICAgIGNvbG9yID0gbWlncmF0aW9uX2JhY2tncm91bmRfZmFjKSkgKw0KICBnZW9tX2JveHBsb3QocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpDQogICAgICAgICAgICAgICAjLA0KICAgICAgICAgICAgICAgI2ZpbGwgPSAiI0Q0RDlERSINCiAgICAgICAgICAgICAgICkgKw0KICBmYWNldF93cmFwKHZhcnMobWlncmF0aW9uX2JhY2tncm91bmRfZmFjKSkgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfZChvcHRpb24gPSAiRCIpICsNCiAgc2NhbGVfY29sb3JfdmlyaWRpc19kKG9wdGlvbiA9ICJEIikgKyANCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnLA0KICAgICAgICAjcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0Q0RDlERSIsIGNvbG91ciA9ICIjRDREOURFIiksDQogICAgICAgICNwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSIjRDREOURFIiwgY29sb3VyID0gIiNENEQ5REUiKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDEpLA0KICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIpDQogICAgICAgICkgKw0KICBsYWJzKHkgPSAiVW5rbm93biBwb3B1bGF0aW9uIiwNCiAgICAgICB4ID0gIkV4dGVuZGVkIG5ldHdvcmsgc2l6ZSIsDQogICAgICAgdGl0bGUgPSAiRmlnLjM6IEdyb3VwIGRpZmZlcmVuY2VzIGluIHNlbnNpdGl2eSB0byBkaWZmZXJlbnQgdW5rbm93biBwb3B1bGF0aW9ucyIpDQoNCmBgYA0KDQoNCg0K


Copyright © 2024 Jeroense Thijmen