Race/ethnicity predictions

# looking at only US affiliation
pubmed_race_pmids <- corr_authors %>% 
  tidyr::separate_rows(countries, sep = ',') %>% 
  filter(countries == 'US') %>%
  rename('surname' = last_name_simple) %>% 
  predict_race(surname.only = T, impute.missing = F) 
## [1] "Proceeding with surname-only predictions..."
## Warning in merge_surnames(voter.file, impute.missing =
## impute.missing): 5166 surnames were not matched.
pubmed_us_race <- pubmed_race_pmids %>% 
  group_by(pmid, journal, publication_date, year, adjusted_citations) %>% 
  summarise_at(vars(contains('pred.')), mean, na.rm = T, .groups = 'drop') %>% 
  {.}

iscb_us_race <- keynotes %>%
  rename('surname' = last_name_simple) %>%
  predict_race(surname.only = T, impute.missing = F)
## [1] "Proceeding with surname-only predictions..."
## Warning in merge_surnames(voter.file, impute.missing =
## impute.missing): 100 surnames were not matched.
my_jours <- unique(pubmed_us_race$journal)
my_confs <- unique(iscb_us_race$conference)
n_jours <- length(my_jours)
n_confs <- length(my_confs)
iscb_pubmed <- iscb_us_race %>%
  rename('journal' = conference) %>% 
  select(year, journal, contains('pred')) %>%
  mutate(publication_date = year,
         type = 'Keynote speakers/Fellows',
         adjusted_citations = 1) %>%
  bind_rows(
    pubmed_us_race %>%
      select(year, journal, contains('pred'), publication_date, adjusted_citations) %>%
      mutate(type = 'Pubmed authors')
  ) %>%
  mutate(pred_sum_others = pred.his + pred.oth + pred.bla) %>% 
  tidyr::pivot_longer(contains('pred'),
                      names_to = 'Race',
                      values_to = 'probabilities') %>%
  filter(!is.na(probabilities)) %>% 
  recode_race() %>%
  group_by(type, year, Race) %>%
  mutate(
    pmc_citations_year = mean(adjusted_citations),
    weight = adjusted_citations/pmc_citations_year,
    weighted_probs = probabilities*weight
  )
## Adding missing grouping variables: `pmid`
iscb_pubmed_sum <- iscb_pubmed %>% 
  summarise(
    mean_prob = mean(weighted_probs),
    mean_raw = mean(probabilities),
    se_prob = sqrt(var(probabilities) * sum(weight^2)/(sum(weight)^2)),
    me_prob = alpha_threshold * se_prob,
    .groups = 'drop'
  )
iscb_race <- vector('list', length = n_confs)
i <- 0
for (conf in my_confs){
  i <- i + 1
  iscb_race[[i]] <- iscb_pubmed %>%
    filter(type != 'Pubmed authors' & journal == conf & (Race != 'Other categories')) %>%
    group_by(year, Race, journal) %>%
    summarise(mean_prob = mean(probabilities, na.rm = T), .groups = 'drop') %>%
    # ungroup() %>% 
    {.}
}
save(iscb_pubmed, iscb_race, file = 'Rdata/iscb-us-race.Rdata')
fig_stats <- iscb_pubmed_sum %>% 
  filter(Race %in% c('White', 'Asian', 'Other categories')) %>% 
  gam_and_ci(
    df2 = iscb_pubmed %>% 
      filter(Race %in% c('White', 'Asian', 'Other categories')),
    start_y = start_year, end_y = end_year) + 
  theme(legend.position = c(0.84, 0.78),
        panel.grid.minor = element_blank(),
        legend.margin = margin(-0.5, 0, 0, 0, unit='cm')) +
  facet_wrap(vars(forcats::fct_rev(Race)))

fig_2a <- iscb_pubmed_sum %>%
  mutate(type = fct_rev(as.factor(type))) %>% 
  filter(Race != 'Other categories') %>%
  # group_by(year, type, Race) %>%
  # summarise(mean_prob = mean(probabilities, na.rm = T), .groups = 'drop') %>%
  race_breakdown(category = 'main', race_levels, type)

fig_2 <- cowplot::plot_grid(
  fig_2a, fig_stats, labels = 'AUTO', ncol = 1, rel_heights = c(1.5,1))
## `geom_smooth()` using formula 'y ~ s(x, bs = "cs")'
fig_2

ggsave('figs/us_racial_makeup.png', fig_2, width = 6.5, height = 5.5)
ggsave('figs/us_racial_makeup.svg', fig_2, width = 6.5, height = 5.5)

Hypothesis testing

Regression of the probability of a name of a certain race on the type of scientists (authors vs. speakers) and year (interaction term included):

main_lm <- function(racei){
  lm(weighted_probs ~ year + type, 
     data = iscb_pubmed %>% 
       ungroup() %>% 
       filter(Race == racei, !is.na(weighted_probs)) %>% 
       mutate(year = c(scale(year)),
              type = relevel(as.factor(type), ref = 'Pubmed authors')))
}
inte_lm <- function(racei){
  lm(weighted_probs ~ year * type, 
     data = iscb_pubmed %>% 
       ungroup() %>% 
       filter(Race == racei, !is.na(weighted_probs)) %>% 
       mutate(year = c(scale(year)),
              type = relevel(as.factor(type), ref = 'Pubmed authors')))
}
inte_list <- lapply(c('White', 'Asian', 'Other categories'), main_lm)
lapply(inte_list, summary)
## [[1]]
## 
## Call:
## lm(formula = weighted_probs ~ year + type, data = iscb_pubmed %>% 
##     ungroup() %>% filter(Race == racei, !is.na(weighted_probs)) %>% 
##     mutate(year = c(scale(year)), type = relevel(as.factor(type), 
##         ref = "Pubmed authors")))
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.8113 -0.5414 -0.0942  0.2651 16.6148 
## 
## Coefficients:
##                               Estimate Std. Error t value
## (Intercept)                   0.612841   0.004475 136.937
## year                         -0.041522   0.004554  -9.118
## typeKeynote speakers/Fellows  0.083082   0.038991   2.131
##                              Pr(>|t|)    
## (Intercept)                    <2e-16 ***
## year                           <2e-16 ***
## typeKeynote speakers/Fellows   0.0331 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.6672 on 22553 degrees of freedom
## Multiple R-squared:  0.004462,   Adjusted R-squared:  0.004374 
## F-statistic: 50.54 on 2 and 22553 DF,  p-value: < 2.2e-16
## 
## 
## [[2]]
## 
## Call:
## lm(formula = weighted_probs ~ year + type, data = iscb_pubmed %>% 
##     ungroup() %>% filter(Race == racei, !is.na(weighted_probs)) %>% 
##     mutate(year = c(scale(year)), type = relevel(as.factor(type), 
##         ref = "Pubmed authors")))
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.2870 -0.2596 -0.2303  0.1112  6.2454 
## 
## Coefficients:
##                               Estimate Std. Error t value
## (Intercept)                   0.247463   0.003178  77.861
## year                          0.043328   0.003234  13.397
## typeKeynote speakers/Fellows -0.099391   0.027691  -3.589
##                              Pr(>|t|)    
## (Intercept)                   < 2e-16 ***
## year                          < 2e-16 ***
## typeKeynote speakers/Fellows 0.000332 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.4739 on 22553 degrees of freedom
## Multiple R-squared:  0.009848,   Adjusted R-squared:  0.00976 
## F-statistic: 112.2 on 2 and 22553 DF,  p-value: < 2.2e-16
## 
## 
## [[3]]
## 
## Call:
## lm(formula = weighted_probs ~ year + type, data = iscb_pubmed %>% 
##     ungroup() %>% filter(Race == racei, !is.na(weighted_probs)) %>% 
##     mutate(year = c(scale(year)), type = relevel(as.factor(type), 
##         ref = "Pubmed authors")))
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.1573 -0.1143 -0.0837  0.0159  9.6671 
## 
## Coefficients:
##                               Estimate Std. Error t value
## (Intercept)                   0.139696   0.001617  86.395
## year                         -0.001807   0.001645  -1.098
## typeKeynote speakers/Fellows  0.016309   0.014088   1.158
##                              Pr(>|t|)    
## (Intercept)                    <2e-16 ***
## year                            0.272    
## typeKeynote speakers/Fellows    0.247    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2411 on 22553 degrees of freedom
## Multiple R-squared:  0.0001446,  Adjusted R-squared:  5.593e-05 
## F-statistic: 1.631 on 2 and 22553 DF,  p-value: 0.1958

Should we include interaction terms?

Interaction terms do not predict probabilities over and above the main effect of group of scientists and year.

compare_lm <- function(racei) anova(main_lm(racei), inte_lm(racei))
lapply(c('White', 'Asian', 'Other categories'), compare_lm)
## [[1]]
## Analysis of Variance Table
## 
## Model 1: weighted_probs ~ year + type
## Model 2: weighted_probs ~ year * type
##   Res.Df   RSS Df Sum of Sq      F Pr(>F)
## 1  22553 10041                           
## 2  22552 10040  1   0.39995 0.8983 0.3432
## 
## [[2]]
## Analysis of Variance Table
## 
## Model 1: weighted_probs ~ year + type
## Model 2: weighted_probs ~ year * type
##   Res.Df    RSS Df Sum of Sq      F Pr(>F)
## 1  22553 5064.0                           
## 2  22552 5063.6  1   0.43339 1.9302 0.1647
## 
## [[3]]
## Analysis of Variance Table
## 
## Model 1: weighted_probs ~ year + type
## Model 2: weighted_probs ~ year * type
##   Res.Df    RSS Df  Sum of Sq      F Pr(>F)
## 1  22553 1310.7                            
## 2  22552 1310.7  1 0.00067119 0.0115 0.9144

Conclusion

Specifically, a name coming from the group of honorees has significantly higher probability of being white (\(\beta_\textrm{white} =\) 0.083082, p = 0.033118) and lower probability of being Asian, (\(\beta_\textrm{Asian} =\) -0.099391, p = 0.00033221). The two groups of scientists did not have a significant association with names predicted to be in Other categories (p = 0.24699).

LS0tCnRpdGxlOiAiUmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgcmFjZS9ldGhuaWNpdHkgaW4gdGhlIFVTIgotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGJyb29tKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShmb3JjYXRzKQoKc291cmNlKCd1dGlscy9yLXV0aWxzLlInKQpsaWJyYXJ5KHdydSkKdGhlbWVfc2V0KHRoZW1lX2J3KCkgKyAKICAgICAgICAgICAgdGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSkKCmxvYWQoJ1JkYXRhL3Jhd3MuUmRhdGEnKQoKYWxwaGFfdGhyZXNob2xkIDwtIHFub3JtKDAuOTc1KQpzdGFydF95ZWFyIDwtICcxOTkzLTAxLTAxJwplbmRfeWVhciA8LSAnMjAxOS0xMi0zMScKbl95ZWFycyA8LSB5ZWFyKGVuZF95ZWFyKSAtIHllYXIoc3RhcnRfeWVhcikKCnJhY2VfbGV2ZWxzIDwtIGMoJ1doaXRlJywgJ0FzaWFuJywgJ0JsYWNrJywgJ0hpc3BhbmljJywgJ090aGVyJywgJ090aGVyIGNhdGVnb3JpZXMnKQpgYGAKCiMjIFJhY2UvZXRobmljaXR5IHByZWRpY3Rpb25zCgpgYGB7cn0KIyBsb29raW5nIGF0IG9ubHkgVVMgYWZmaWxpYXRpb24KcHVibWVkX3JhY2VfcG1pZHMgPC0gY29ycl9hdXRob3JzICU+JSAKICB0aWR5cjo6c2VwYXJhdGVfcm93cyhjb3VudHJpZXMsIHNlcCA9ICcsJykgJT4lIAogIGZpbHRlcihjb3VudHJpZXMgPT0gJ1VTJykgJT4lCiAgcmVuYW1lKCdzdXJuYW1lJyA9IGxhc3RfbmFtZV9zaW1wbGUpICU+JSAKICBwcmVkaWN0X3JhY2Uoc3VybmFtZS5vbmx5ID0gVCwgaW1wdXRlLm1pc3NpbmcgPSBGKSAKCnB1Ym1lZF91c19yYWNlIDwtIHB1Ym1lZF9yYWNlX3BtaWRzICU+JSAKICBncm91cF9ieShwbWlkLCBqb3VybmFsLCBwdWJsaWNhdGlvbl9kYXRlLCB5ZWFyLCBhZGp1c3RlZF9jaXRhdGlvbnMpICU+JSAKICBzdW1tYXJpc2VfYXQodmFycyhjb250YWlucygncHJlZC4nKSksIG1lYW4sIG5hLnJtID0gVCwgLmdyb3VwcyA9ICdkcm9wJykgJT4lIAogIHsufQoKaXNjYl91c19yYWNlIDwtIGtleW5vdGVzICU+JQogIHJlbmFtZSgnc3VybmFtZScgPSBsYXN0X25hbWVfc2ltcGxlKSAlPiUKICBwcmVkaWN0X3JhY2Uoc3VybmFtZS5vbmx5ID0gVCwgaW1wdXRlLm1pc3NpbmcgPSBGKQoKbXlfam91cnMgPC0gdW5pcXVlKHB1Ym1lZF91c19yYWNlJGpvdXJuYWwpCm15X2NvbmZzIDwtIHVuaXF1ZShpc2NiX3VzX3JhY2UkY29uZmVyZW5jZSkKbl9qb3VycyA8LSBsZW5ndGgobXlfam91cnMpCm5fY29uZnMgPC0gbGVuZ3RoKG15X2NvbmZzKQpgYGAKCgpgYGB7cn0KaXNjYl9wdWJtZWQgPC0gaXNjYl91c19yYWNlICU+JQogIHJlbmFtZSgnam91cm5hbCcgPSBjb25mZXJlbmNlKSAlPiUgCiAgc2VsZWN0KHllYXIsIGpvdXJuYWwsIGNvbnRhaW5zKCdwcmVkJykpICU+JQogIG11dGF0ZShwdWJsaWNhdGlvbl9kYXRlID0geWVhciwKICAgICAgICAgdHlwZSA9ICdLZXlub3RlIHNwZWFrZXJzL0ZlbGxvd3MnLAogICAgICAgICBhZGp1c3RlZF9jaXRhdGlvbnMgPSAxKSAlPiUKICBiaW5kX3Jvd3MoCiAgICBwdWJtZWRfdXNfcmFjZSAlPiUKICAgICAgc2VsZWN0KHllYXIsIGpvdXJuYWwsIGNvbnRhaW5zKCdwcmVkJyksIHB1YmxpY2F0aW9uX2RhdGUsIGFkanVzdGVkX2NpdGF0aW9ucykgJT4lCiAgICAgIG11dGF0ZSh0eXBlID0gJ1B1Ym1lZCBhdXRob3JzJykKICApICU+JQogIG11dGF0ZShwcmVkX3N1bV9vdGhlcnMgPSBwcmVkLmhpcyArIHByZWQub3RoICsgcHJlZC5ibGEpICU+JSAKICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGNvbnRhaW5zKCdwcmVkJyksCiAgICAgICAgICAgICAgICAgICAgICBuYW1lc190byA9ICdSYWNlJywKICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICdwcm9iYWJpbGl0aWVzJykgJT4lCiAgZmlsdGVyKCFpcy5uYShwcm9iYWJpbGl0aWVzKSkgJT4lIAogIHJlY29kZV9yYWNlKCkgJT4lCiAgZ3JvdXBfYnkodHlwZSwgeWVhciwgUmFjZSkgJT4lCiAgbXV0YXRlKAogICAgcG1jX2NpdGF0aW9uc195ZWFyID0gbWVhbihhZGp1c3RlZF9jaXRhdGlvbnMpLAogICAgd2VpZ2h0ID0gYWRqdXN0ZWRfY2l0YXRpb25zL3BtY19jaXRhdGlvbnNfeWVhciwKICAgIHdlaWdodGVkX3Byb2JzID0gcHJvYmFiaWxpdGllcyp3ZWlnaHQKICApCgppc2NiX3B1Ym1lZF9zdW0gPC0gaXNjYl9wdWJtZWQgJT4lIAogIHN1bW1hcmlzZSgKICAgIG1lYW5fcHJvYiA9IG1lYW4od2VpZ2h0ZWRfcHJvYnMpLAogICAgbWVhbl9yYXcgPSBtZWFuKHByb2JhYmlsaXRpZXMpLAogICAgc2VfcHJvYiA9IHNxcnQodmFyKHByb2JhYmlsaXRpZXMpICogc3VtKHdlaWdodF4yKS8oc3VtKHdlaWdodCleMikpLAogICAgbWVfcHJvYiA9IGFscGhhX3RocmVzaG9sZCAqIHNlX3Byb2IsCiAgICAuZ3JvdXBzID0gJ2Ryb3AnCiAgKQpgYGAKCmBgYHtyfQppc2NiX3JhY2UgPC0gdmVjdG9yKCdsaXN0JywgbGVuZ3RoID0gbl9jb25mcykKaSA8LSAwCmZvciAoY29uZiBpbiBteV9jb25mcyl7CiAgaSA8LSBpICsgMQogIGlzY2JfcmFjZVtbaV1dIDwtIGlzY2JfcHVibWVkICU+JQogICAgZmlsdGVyKHR5cGUgIT0gJ1B1Ym1lZCBhdXRob3JzJyAmIGpvdXJuYWwgPT0gY29uZiAmIChSYWNlICE9ICdPdGhlciBjYXRlZ29yaWVzJykpICU+JQogICAgZ3JvdXBfYnkoeWVhciwgUmFjZSwgam91cm5hbCkgJT4lCiAgICBzdW1tYXJpc2UobWVhbl9wcm9iID0gbWVhbihwcm9iYWJpbGl0aWVzLCBuYS5ybSA9IFQpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUKICAgICMgdW5ncm91cCgpICU+JSAKICAgIHsufQp9CmBgYAoKYGBge3J9CnNhdmUoaXNjYl9wdWJtZWQsIGlzY2JfcmFjZSwgZmlsZSA9ICdSZGF0YS9pc2NiLXVzLXJhY2UuUmRhdGEnKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9N30KZmlnX3N0YXRzIDwtIGlzY2JfcHVibWVkX3N1bSAlPiUgCiAgZmlsdGVyKFJhY2UgJWluJSBjKCdXaGl0ZScsICdBc2lhbicsICdPdGhlciBjYXRlZ29yaWVzJykpICU+JSAKICBnYW1fYW5kX2NpKAogICAgZGYyID0gaXNjYl9wdWJtZWQgJT4lIAogICAgICBmaWx0ZXIoUmFjZSAlaW4lIGMoJ1doaXRlJywgJ0FzaWFuJywgJ090aGVyIGNhdGVnb3JpZXMnKSksCiAgICBzdGFydF95ID0gc3RhcnRfeWVhciwgZW5kX3kgPSBlbmRfeWVhcikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuODQsIDAuNzgpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLm1hcmdpbiA9IG1hcmdpbigtMC41LCAwLCAwLCAwLCB1bml0PSdjbScpKSArCiAgZmFjZXRfd3JhcCh2YXJzKGZvcmNhdHM6OmZjdF9yZXYoUmFjZSkpKQoKZmlnXzJhIDwtIGlzY2JfcHVibWVkX3N1bSAlPiUKICBtdXRhdGUodHlwZSA9IGZjdF9yZXYoYXMuZmFjdG9yKHR5cGUpKSkgJT4lIAogIGZpbHRlcihSYWNlICE9ICdPdGhlciBjYXRlZ29yaWVzJykgJT4lCiAgIyBncm91cF9ieSh5ZWFyLCB0eXBlLCBSYWNlKSAlPiUKICAjIHN1bW1hcmlzZShtZWFuX3Byb2IgPSBtZWFuKHByb2JhYmlsaXRpZXMsIG5hLnJtID0gVCksIC5ncm91cHMgPSAnZHJvcCcpICU+JQogIHJhY2VfYnJlYWtkb3duKGNhdGVnb3J5ID0gJ21haW4nLCByYWNlX2xldmVscywgdHlwZSkKCmZpZ18yIDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZCgKICBmaWdfMmEsIGZpZ19zdGF0cywgbGFiZWxzID0gJ0FVVE8nLCBuY29sID0gMSwgcmVsX2hlaWdodHMgPSBjKDEuNSwxKSkKZmlnXzIKCmdnc2F2ZSgnZmlncy91c19yYWNpYWxfbWFrZXVwLnBuZycsIGZpZ18yLCB3aWR0aCA9IDYuNSwgaGVpZ2h0ID0gNS41KQpnZ3NhdmUoJ2ZpZ3MvdXNfcmFjaWFsX21ha2V1cC5zdmcnLCBmaWdfMiwgd2lkdGggPSA2LjUsIGhlaWdodCA9IDUuNSkKYGBgCgojIyBIeXBvdGhlc2lzIHRlc3RpbmcKClJlZ3Jlc3Npb24gb2YgdGhlIHByb2JhYmlsaXR5IG9mIGEgbmFtZSBvZiBhIGNlcnRhaW4gcmFjZSBvbiB0aGUgdHlwZSBvZiBzY2llbnRpc3RzIChhdXRob3JzIHZzLiBzcGVha2VycykgYW5kIHllYXIgKGludGVyYWN0aW9uIHRlcm0gaW5jbHVkZWQpOgoKYGBge3J9Cm1haW5fbG0gPC0gZnVuY3Rpb24ocmFjZWkpewogIGxtKHdlaWdodGVkX3Byb2JzIH4geWVhciArIHR5cGUsIAogICAgIGRhdGEgPSBpc2NiX3B1Ym1lZCAlPiUgCiAgICAgICB1bmdyb3VwKCkgJT4lIAogICAgICAgZmlsdGVyKFJhY2UgPT0gcmFjZWksICFpcy5uYSh3ZWlnaHRlZF9wcm9icykpICU+JSAKICAgICAgIG11dGF0ZSh5ZWFyID0gYyhzY2FsZSh5ZWFyKSksCiAgICAgICAgICAgICAgdHlwZSA9IHJlbGV2ZWwoYXMuZmFjdG9yKHR5cGUpLCByZWYgPSAnUHVibWVkIGF1dGhvcnMnKSkpCn0KaW50ZV9sbSA8LSBmdW5jdGlvbihyYWNlaSl7CiAgbG0od2VpZ2h0ZWRfcHJvYnMgfiB5ZWFyICogdHlwZSwgCiAgICAgZGF0YSA9IGlzY2JfcHVibWVkICU+JSAKICAgICAgIHVuZ3JvdXAoKSAlPiUgCiAgICAgICBmaWx0ZXIoUmFjZSA9PSByYWNlaSwgIWlzLm5hKHdlaWdodGVkX3Byb2JzKSkgJT4lIAogICAgICAgbXV0YXRlKHllYXIgPSBjKHNjYWxlKHllYXIpKSwKICAgICAgICAgICAgICB0eXBlID0gcmVsZXZlbChhcy5mYWN0b3IodHlwZSksIHJlZiA9ICdQdWJtZWQgYXV0aG9ycycpKSkKfQppbnRlX2xpc3QgPC0gbGFwcGx5KGMoJ1doaXRlJywgJ0FzaWFuJywgJ090aGVyIGNhdGVnb3JpZXMnKSwgbWFpbl9sbSkKbGFwcGx5KGludGVfbGlzdCwgc3VtbWFyeSkKYGBgCgpgYGB7ciBlY2hvID0gRn0KZ2V0X3AgPC0gZnVuY3Rpb24oaSwgY29sdSl7CiAgdGlkeShpbnRlX2xpc3RbW2ldXSkgJT4lIAogICAgZmlsdGVyKHRlcm0gPT0gJ3R5cGVLZXlub3RlIHNwZWFrZXJzL0ZlbGxvd3MnKSAlPiUgCiAgICBwdWxsKGNvbHUpICU+JSAKICAgIHNwcmludGYoIiUwLjVnIiwgLikKfQpgYGAKCiMjIyBTaG91bGQgd2UgaW5jbHVkZSBpbnRlcmFjdGlvbiB0ZXJtcz8KCkludGVyYWN0aW9uIHRlcm1zIGRvIG5vdCBwcmVkaWN0IGBwcm9iYWJpbGl0aWVzYCBvdmVyIGFuZCBhYm92ZSB0aGUgbWFpbiBlZmZlY3Qgb2YgZ3JvdXAgb2Ygc2NpZW50aXN0cyBhbmQgeWVhci4KYGBge3J9CmNvbXBhcmVfbG0gPC0gZnVuY3Rpb24ocmFjZWkpIGFub3ZhKG1haW5fbG0ocmFjZWkpLCBpbnRlX2xtKHJhY2VpKSkKbGFwcGx5KGMoJ1doaXRlJywgJ0FzaWFuJywgJ090aGVyIGNhdGVnb3JpZXMnKSwgY29tcGFyZV9sbSkKYGBgCgojIyBDb25jbHVzaW9uCgpTcGVjaWZpY2FsbHksIGEgbmFtZSBjb21pbmcgZnJvbSB0aGUgZ3JvdXAgb2YgaG9ub3JlZXMgaGFzIHNpZ25pZmljYW50bHkgaGlnaGVyIHByb2JhYmlsaXR5IG9mIGJlaW5nIHdoaXRlICgkXGJldGFfXHRleHRybXt3aGl0ZX0gPSQgYHIgZ2V0X3AoMSwgJ2VzdGltYXRlJylgLCBfcF8gPSBgciBnZXRfcCgxLCAncC52YWx1ZScpYCkgYW5kIGxvd2VyIHByb2JhYmlsaXR5IG9mIGJlaW5nIEFzaWFuLCAoJFxiZXRhX1x0ZXh0cm17QXNpYW59ID0kIGByIGdldF9wKDIsICdlc3RpbWF0ZScpYCwgX3BfID0gYHIgZ2V0X3AoMiwgJ3AudmFsdWUnKWApLgpUaGUgdHdvIGdyb3VwcyBvZiBzY2llbnRpc3RzIGRpZCBub3QgaGF2ZSBhIHNpZ25pZmljYW50IGFzc29jaWF0aW9uIHdpdGggbmFtZXMgcHJlZGljdGVkIHRvIGJlIGluIE90aGVyIGNhdGVnb3JpZXMgKF9wXyA9IGByIGdldF9wKDMsICdwLnZhbHVlJylgKS4KCg==