Alternative title + sign from the rally at the MA State House today: Melt the ICE

intro

This project is motivated by recent (Monday 7/6) ICE news here.

The NSF puts out data on doctoral degree earners and their citizenship – the most recent data covers 2006-2016. See table 7-4 here.

I use this data to show summary stats, and graphs related to the prevalence of international students (temporary residents in the NSF) in S&E PhD programs.

prep/clean

The NSF data is not in a natural shape for me to plot it. So, first things first. I need to clean it up.1 I just care about the permanent resident/US citizen and temporary resident dichotomy for now.

library(tidyverse);library(readxl)
Registered S3 method overwritten by 'dplyr':
  method           from
  print.rowwise_df     
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ───────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.0     ✓ purrr   0.3.4
✓ tibble  3.0.1     ✓ dplyr   0.8.5
✓ tidyr   1.0.3     ✓ stringr 1.4.0
✓ readr   1.3.1     ✓ forcats 0.5.0
── Conflicts ──────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
nsf<-read_xlsx("degrees_nsf.xlsx")
New names:
* `` -> ...2
* `` -> ...3
* `` -> ...4
* `` -> ...5
* `` -> ...6
* ...
#remove unneeded rows
nsf1<-nsf%>%
  slice(-(1:2))%>%
  filter(`Table 7-4`!="Hispanic or Latinoa" &
           `Table 7-4`!="Non-Hispanic or Latino" &
           `Table 7-4`!="American Indian or Alaska Native" &
           `Table 7-4`!="Asian" &
           `Table 7-4`!="Asian or Pacific Islanderb" &
           `Table 7-4`!="Black or African American" &
           `Table 7-4`!="Native Hawaiian or Other Pacific Islander" &
           `Table 7-4`!="White" &
           `Table 7-4`!="More than one racec" &
           `Table 7-4`!="Other or unknown race and ethnicity")

names(nsf1)<-nsf1[1,]
The `value` argument of ``names<-`()` must be a character vector as of tibble 3.0.0.
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.
nsf1<-nsf1[-1,]

types<-nsf1%>%
  filter(`Field, citizenship, ethnicity, and race`!="U.S. citizen and permanent resident" &
          `Field, citizenship, ethnicity, and race`!="Temporary resident")%>%
  select(`Field, citizenship, ethnicity, and race`)%>%
  mutate(order=row_number())

types3<-types%>%
  bind_rows(types)%>%
  bind_rows(types)%>%
  arrange(order)

nsf2<-nsf1%>%
  bind_cols(types3)%>%select(-order)%>%
  rename(citizen=`Field, citizenship, ethnicity, and race`)%>%
  rename(type=`Field, citizenship, ethnicity, and race1`)%>%
  filter(citizen=="U.S. citizen and permanent resident" | citizen=="Temporary resident")

nsf_long<-nsf2%>%
  pivot_longer(cols = starts_with("2"),
               names_to = "year")%>%
  mutate(value1=as.double(value))%>%
  filter(type!="Other")

summary stats

What % of all doctoral degree recipients are temporary residents?

nsf_long%>%
  filter(type=="All degrees")%>%
  group_by(citizen)%>%
  summarise(n=sum(value1))
188492/(188492+503012)
[1] 0.2725827

What % of S+E doctoral degree recipients are temporary residents?

nsf_long%>%
  filter(type=="All S&E")%>%
  group_by(citizen)%>%
  summarise(n=sum(value1))
145999/(145999+239995)
[1] 0.3782416

Economics?

nsf_long%>%
  filter(type=="Economics")%>%
  group_by(citizen)%>%
  summarise(n=sum(value1))
7894/(7894+5177)
[1] 0.6039324

Graph for raw counts by citizenship and field

# select most detailed field
nsf_long_fields<-nsf_long%>%
  filter(type!="All degrees" &
           type!="All S&E" &type!="Non-S&E" &
           type!="Science" & 
           type!="Engineering" & 
           type!="Earth, atmospheric, and ocean sciences" &
           type!="Physical sciences" & 
           type!="Social sciences")%>%
  mutate(type=replace(type, type=="Political science and public administration", 
                      "Poli sci & public admin"))%>%
  mutate(type=replace(type, type=="Mathematics and statistics", 
                      "Mathematics & statistics"))%>%
  mutate(type=replace(type, type=="Ethnic and area studies", 
                      "Ethnic & area studies"))%>%
  mutate(citizen=replace(citizen, citizen=="U.S. citizen and permanent resident", 
                      "U.S. citizen or permanent resident"))
  
ggplot(data=nsf_long_fields, aes(x=year, y=value1, fill=citizen, group=citizen)) + 
  theme_minimal()+ theme(text=element_text(family="Palatino", size=13),
                         plot.title.position = "plot",
                         legend.position = "top",
                         plot.title = element_text(size=22),
                         axis.title.y = element_text(size=15))+
  geom_area(aes(fill=citizen), position='stack')+
  scale_fill_manual(values = c("#009E73", "#999999"), name="Citizenship") + 
  facet_wrap(~type, scales="free")+ expand_limits(y = 0)+
  scale_x_discrete(labels = c("'06", "", "'08", "", "'10", "", "'12", "", "'14", "", "'16"))+
  labs(x="", y="Number of Doctoral Degrees Awarded", caption="Viz by Alex Albright")+
  ggtitle("How Many Science & Engineering Doctoral Degree Earners are International Students?", 
          subtitle= "NSF Data on Doctoral Degrees, 2006-2016")

ggsave("phd_count_by_citizenship.png", width=12, height=10, dpi=300)

Graph by percent temporary resident within field

Nightingale plot

nsf_long_fields1<-nsf_long_fields%>%
  group_by(year, type)%>%
  mutate(tot=sum(value1))%>%
  filter(citizen=="Temporary resident")%>%
  mutate(temp_perc=value1/tot,
         cit_perm_perc=1-temp_perc)%>%
  select(-c(value, value1, tot))%>%
  pivot_longer(cols = 4:5)%>%
  mutate(name=replace(name, name=="temp_perc", 
                      "% Temporary resident"))%>%
  mutate(name=replace(name, name=="cit_perm_perc", 
                      "% U.S. citizen or permanent resident"))

ggplot(data=nsf_long_fields1, aes(x=year, y=value, fill=name, group=name)) + 
  theme_minimal()+ theme(text=element_text(family="Palatino", size=13), 
                         plot.margin = margin(0.1, 0.1, 0.1, 0.1, "cm"),
                         plot.title.position = "plot",
                         legend.position = "top",
                         plot.title = element_text(size=21),
                         strip.text = element_text(size=9),
                         axis.text.x = element_text(size=8),
                         axis.title.y = element_text(size=15))+
  geom_bar(stat="identity", aes(fill=name), position='stack')+ 
  coord_polar()+ facet_wrap(~type, nrow=5)+
  scale_fill_manual(values = c("#009E73", "#999999"), name="Citizenship") + 
  scale_x_discrete(labels = c("'06", "'07", "'08", "'09", "'10", 
                              "'11", "'12", "'13", "'14", "'15", "'16"))+
  scale_y_continuous(labels = scales::percent)+
  labs(x="", y="Percent of Doctoral Degrees Awarded", caption="Viz by Alex Albright")+
  ggtitle("What % of Science & Engineering Doctoral Degree Earners\nare International Students?", 
          subtitle= "NSF Data on Doctoral Degrees, 2006-2016")

ggsave("phd_per_by_citizenship.png", width=8, height=10, dpi=300)

just a simple bar chart

Color economics for emphasis.

field_p<-nsf_long_fields%>%
  ungroup()%>%
  group_by(type)%>%
  mutate(tot=sum(value1))%>%
  filter(citizen=="Temporary resident")%>%
  mutate(temp=sum(value1))%>%
  mutate(temp_perc=temp/tot)%>%
  select(type, temp_perc)%>% unique()%>%
  mutate(econ=if_else(type=="Economics", 1, 0))

ggplot(data=field_p, aes(x=reorder(type, -temp_perc), 
                         y=temp_perc, fill=factor(econ), group=factor(econ))) + 
  theme_minimal()+ theme(text=element_text(family="Palatino", size=13),
                         legend.position = "none", plot.title.position = "plot",
                         plot.title = element_text(size=20.5),
                         strip.text = element_text(size=9),
                         axis.title.x = element_text(size=18),
                         axis.text = element_text(size=15))+
  geom_bar(stat="identity")+ coord_flip()+
  scale_fill_manual(values = c("#999999", "#E69F00")) + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1), breaks=seq(0,.7, .1))+
  labs(x="", y="Percent of Doctoral Degrees Awarded to Temporary Residents", 
       caption="Viz by Alex Albright")+
  ggtitle("What % of Science & Engineering Doctoral Degree Earners are International Students?", 
          subtitle= "NSF Data on Doctoral Degrees, 2006-2016")

ggsave("phd_per_temp.png", width=11, height=10, dpi=300)

diagram for how NSF categorizes things

See here for source. More on the DiagrammeR package here.

library(DiagrammeR)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
library(DiagrammeRsvg)
library(magrittr)

Attaching package: ‘magrittr’

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

    set_names

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

    extract
library(rsvg)

graph<-"digraph  {
      graph [layout = dot, rankdir = LR]
      # node definitions with substituted label text
      node [fontname = Palatino, shape = rectangle]        
      tab1 [label = '@@1']
      
      tab2 [label = '@@2']
      tab3 [label = '@@3']
      
      tab4 [label = '@@4']
      tab5 [label = '@@5']
      
      tab6 [label = '@@6']
      tab7 [label = '@@7']
      tab8 [label = '@@8']
      tab9 [label = '@@9']
      tab10 [label = '@@10']
      tab11 [label = '@@11']
      tab12 [label = '@@12']
      tab13 [label = '@@13']
      
      tab14 [label = '@@14']
      tab15 [label = '@@15']
      tab16 [label = '@@16']
      tab17 [label = '@@17']
      tab18 [label = '@@18']
      tab19 [label = '@@19']
      tab20 [label = '@@20']
      tab21 [label = '@@21']
      
      tab22 [label = '@@22']
      tab23 [label = '@@23']
      tab24 [label = '@@24']
      
      tab25 [label = '@@25']
      tab26 [label = '@@26']
      tab27 [label = '@@27']
      tab28 [label = '@@28']
      
      tab29 [label = '@@29']
      tab30 [label = '@@30']
      tab31 [label = '@@31']
      tab32 [label = '@@32']
      tab33 [label = '@@33']
      tab34 [label = '@@34']
      tab35 [label = '@@35']
      tab36 [label = '@@36']

      # edge definitions with the node IDs
      tab1 -> tab2;
      tab1 -> tab3;
      
      tab2 -> tab4;
      tab2 -> tab5;
      
      tab4 -> tab6;
      tab4 -> tab7;
      tab4 -> tab8;
      tab4 -> tab9;
      tab4 -> tab10;
      tab4 -> tab11;
      tab4 -> tab12;
      tab4 -> tab13;
      
      tab5 -> tab14;
      tab5 -> tab15;
      tab5 -> tab16;
      tab5 -> tab17;
      tab5 -> tab18;
      tab5 -> tab19;
      tab5 -> tab20;
      tab5 -> tab21;
      
      tab9 -> tab22;
      tab9 -> tab23;
      tab9 -> tab24;
      
      tab11 -> tab25;
      tab11 -> tab26;
      tab11 -> tab27;
      tab11 -> tab28;
      
      tab13 -> tab29;
      tab13 -> tab30;
      tab13 -> tab31;
      tab13 -> tab32;
      tab13 -> tab33;
      tab13 -> tab34;
      tab13 -> tab35;
      tab13 -> tab36;
      }

      [1]: 'All PhDs'
      [2]: 'S&E'
      [3]: 'Non-S&E'
      [4]: 'Science'
      [5]: 'Engineering'
      [6]: 'Agricultural Sciences'
      [7]: 'Biological Sciences'
      [8]: 'Computer Sciences'
      [9]: 'Earth, Atmospheric, & Ocean Sciences'
      [10]: 'Mathematics and statistics'
      [11]: 'Physical sciences'
      [12]: 'Psychology'
      [13]: 'Social sciences'
      [14]: 'Aerospace'
      [15]: 'Chemical'
      [16]: 'Civil'
      [17]: 'Electrical'
      [18]: 'Industrial'
      [19]: 'Materials'
      [20]: 'Mechanical'
      [21]: 'Other'
      [22]: 'Atmospheric sciences'
      [23]: 'Earth sciences'
      [24]: 'Ocean sciences'
      [25]: 'Astronomy'
      [26]: 'Chemistry'
      [27]: 'Physics'
      [28]: 'Other'
      [29]: 'Anthropology'
      [30]: 'Area and ethnic studies'
      [31]: 'Economics'
      [32]: 'History of science'
      [33]: 'Linguistics'
      [34]: 'Political science & public administration'
      [35]: 'Sociology'
      [36]: 'Other'
      "

grViz(graph) %>%
    export_svg %>% charToRaw %>% rsvg_png("nsf_cat.png")

  1. A few years ago when I used this data, I had to do it by hand because I had no idea how to clean it with code. Progress!

LS0tCnRpdGxlOiAiSUNFIGFuZCBTJkUgUGhEcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKQWx0ZXJuYXRpdmUgdGl0bGUgKyBzaWduIGZyb20gdGhlIHJhbGx5IGF0IHRoZSBNQSBTdGF0ZSBIb3VzZSB0b2RheTogTWVsdCB0aGUgSUNFIAoKIyBpbnRybyAKClRoaXMgcHJvamVjdCBpcyBtb3RpdmF0ZWQgYnkgcmVjZW50IChNb25kYXkgNy82KSBJQ0UgbmV3cyBbaGVyZS5dKGh0dHBzOi8vd3d3LmljZS5nb3YvbmV3cy9yZWxlYXNlcy9zZXZwLW1vZGlmaWVzLXRlbXBvcmFyeS1leGVtcHRpb25zLW5vbmltbWlncmFudC1zdHVkZW50cy10YWtpbmctb25saW5lLWNvdXJzZXMtZHVyaW5nKQoKVGhlIE5TRiBwdXRzIG91dCBkYXRhIG9uIGRvY3RvcmFsIGRlZ3JlZSBlYXJuZXJzIGFuZCB0aGVpciBjaXRpemVuc2hpcCAtLSB0aGUgbW9zdCByZWNlbnQgZGF0YSBjb3ZlcnMgMjAwNi0yMDE2LiBTZWUgdGFibGUgNy00IFtoZXJlXShodHRwczovL25jc2VzLm5zZi5nb3YvcHVicy9uc2YxOTMwNC9kYXRhKS4KCkkgdXNlIHRoaXMgZGF0YSB0byBzaG93IHN1bW1hcnkgc3RhdHMsIGFuZCBncmFwaHMgcmVsYXRlZCB0byB0aGUgcHJldmFsZW5jZSBvZiBpbnRlcm5hdGlvbmFsIHN0dWRlbnRzICh0ZW1wb3JhcnkgcmVzaWRlbnRzIGluIHRoZSBOU0YpIGluIFMmRSBQaEQgcHJvZ3JhbXMuIAoKIyBwcmVwL2NsZWFuCgpUaGUgTlNGIGRhdGEgaXMgbm90IGluIGEgbmF0dXJhbCBzaGFwZSBmb3IgbWUgdG8gcGxvdCBpdC4gU28sIGZpcnN0IHRoaW5ncyBmaXJzdC4gSSBuZWVkIHRvIGNsZWFuIGl0IHVwLl5bQSBbZmV3IHllYXJzIGFnb10oaHR0cHM6Ly90aGVsaXR0bGVkYXRhc2V0LmNvbS8yMDE1LzEyLzMxL3RoaXMtcG9zdC1pcy1icm91Z2h0LXRvLXlvdS1ieS10aGUtbmF0aW9uYWwtc2NpZW5jZS1mb3VuZGF0aW9uLykgd2hlbiBJIHVzZWQgdGhpcyBkYXRhLCBJIGhhZCB0byBkbyBpdCBieSBoYW5kIGJlY2F1c2UgSSBoYWQgbm8gaWRlYSBob3cgdG8gY2xlYW4gaXQgd2l0aCBjb2RlLiBQcm9ncmVzcyFdIEkganVzdCBjYXJlIGFib3V0IHRoZSBwZXJtYW5lbnQgcmVzaWRlbnQvVVMgY2l0aXplbiBhbmQgdGVtcG9yYXJ5IHJlc2lkZW50IGRpY2hvdG9teSBmb3Igbm93LgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKTtsaWJyYXJ5KHJlYWR4bCkKbnNmPC1yZWFkX3hsc3goImRlZ3JlZXNfbnNmLnhsc3giKQoKI3JlbW92ZSB1bm5lZWRlZCByb3dzCm5zZjE8LW5zZiU+JQogIHNsaWNlKC0oMToyKSklPiUKICBmaWx0ZXIoYFRhYmxlIDctNGAhPSJIaXNwYW5pYyBvciBMYXRpbm9hIiAmCiAgICAgICAgICAgYFRhYmxlIDctNGAhPSJOb24tSGlzcGFuaWMgb3IgTGF0aW5vIiAmCiAgICAgICAgICAgYFRhYmxlIDctNGAhPSJBbWVyaWNhbiBJbmRpYW4gb3IgQWxhc2thIE5hdGl2ZSIgJgogICAgICAgICAgIGBUYWJsZSA3LTRgIT0iQXNpYW4iICYKICAgICAgICAgICBgVGFibGUgNy00YCE9IkFzaWFuIG9yIFBhY2lmaWMgSXNsYW5kZXJiIiAmCiAgICAgICAgICAgYFRhYmxlIDctNGAhPSJCbGFjayBvciBBZnJpY2FuIEFtZXJpY2FuIiAmCiAgICAgICAgICAgYFRhYmxlIDctNGAhPSJOYXRpdmUgSGF3YWlpYW4gb3IgT3RoZXIgUGFjaWZpYyBJc2xhbmRlciIgJgogICAgICAgICAgIGBUYWJsZSA3LTRgIT0iV2hpdGUiICYKICAgICAgICAgICBgVGFibGUgNy00YCE9Ik1vcmUgdGhhbiBvbmUgcmFjZWMiICYKICAgICAgICAgICBgVGFibGUgNy00YCE9Ik90aGVyIG9yIHVua25vd24gcmFjZSBhbmQgZXRobmljaXR5IikKCm5hbWVzKG5zZjEpPC1uc2YxWzEsXQoKbnNmMTwtbnNmMVstMSxdCgp0eXBlczwtbnNmMSU+JQogIGZpbHRlcihgRmllbGQsIGNpdGl6ZW5zaGlwLCBldGhuaWNpdHksIGFuZCByYWNlYCE9IlUuUy4gY2l0aXplbiBhbmQgcGVybWFuZW50IHJlc2lkZW50IiAmCiAgICAgICAgICBgRmllbGQsIGNpdGl6ZW5zaGlwLCBldGhuaWNpdHksIGFuZCByYWNlYCE9IlRlbXBvcmFyeSByZXNpZGVudCIpJT4lCiAgc2VsZWN0KGBGaWVsZCwgY2l0aXplbnNoaXAsIGV0aG5pY2l0eSwgYW5kIHJhY2VgKSU+JQogIG11dGF0ZShvcmRlcj1yb3dfbnVtYmVyKCkpCgp0eXBlczM8LXR5cGVzJT4lCiAgYmluZF9yb3dzKHR5cGVzKSU+JQogIGJpbmRfcm93cyh0eXBlcyklPiUKICBhcnJhbmdlKG9yZGVyKQoKbnNmMjwtbnNmMSU+JQogIGJpbmRfY29scyh0eXBlczMpJT4lc2VsZWN0KC1vcmRlciklPiUKICByZW5hbWUoY2l0aXplbj1gRmllbGQsIGNpdGl6ZW5zaGlwLCBldGhuaWNpdHksIGFuZCByYWNlYCklPiUKICByZW5hbWUodHlwZT1gRmllbGQsIGNpdGl6ZW5zaGlwLCBldGhuaWNpdHksIGFuZCByYWNlMWApJT4lCiAgZmlsdGVyKGNpdGl6ZW49PSJVLlMuIGNpdGl6ZW4gYW5kIHBlcm1hbmVudCByZXNpZGVudCIgfCBjaXRpemVuPT0iVGVtcG9yYXJ5IHJlc2lkZW50IikKCm5zZl9sb25nPC1uc2YyJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzdGFydHNfd2l0aCgiMiIpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJ5ZWFyIiklPiUKICBtdXRhdGUodmFsdWUxPWFzLmRvdWJsZSh2YWx1ZSkpJT4lCiAgZmlsdGVyKHR5cGUhPSJPdGhlciIpCmBgYAoKIyBzdW1tYXJ5IHN0YXRzCgpXaGF0ICUgb2YgYWxsIGRvY3RvcmFsIGRlZ3JlZSByZWNpcGllbnRzIGFyZSB0ZW1wb3JhcnkgcmVzaWRlbnRzPwoKYGBge3J9Cm5zZl9sb25nJT4lCiAgZmlsdGVyKHR5cGU9PSJBbGwgZGVncmVlcyIpJT4lCiAgZ3JvdXBfYnkoY2l0aXplbiklPiUKICBzdW1tYXJpc2Uobj1zdW0odmFsdWUxKSkKYGBgCmBgYHtyfQoxODg0OTIvKDE4ODQ5Mis1MDMwMTIpCmBgYAoKV2hhdCAlIG9mIFMrRSBkb2N0b3JhbCBkZWdyZWUgcmVjaXBpZW50cyBhcmUgdGVtcG9yYXJ5IHJlc2lkZW50cz8KCmBgYHtyfQpuc2ZfbG9uZyU+JQogIGZpbHRlcih0eXBlPT0iQWxsIFMmRSIpJT4lCiAgZ3JvdXBfYnkoY2l0aXplbiklPiUKICBzdW1tYXJpc2Uobj1zdW0odmFsdWUxKSkKYGBgCmBgYHtyfQoxNDU5OTkvKDE0NTk5OSsyMzk5OTUpCmBgYAoKRWNvbm9taWNzPwoKCmBgYHtyfQpuc2ZfbG9uZyU+JQogIGZpbHRlcih0eXBlPT0iRWNvbm9taWNzIiklPiUKICBncm91cF9ieShjaXRpemVuKSU+JQogIHN1bW1hcmlzZShuPXN1bSh2YWx1ZTEpKQpgYGAKCmBgYHtyfQo3ODk0Lyg3ODk0KzUxNzcpCmBgYAoKIyBHcmFwaCBmb3IgcmF3IGNvdW50cyBieSBjaXRpemVuc2hpcCBhbmQgZmllbGQKCmBgYHtyfQojIHNlbGVjdCBtb3N0IGRldGFpbGVkIGZpZWxkCm5zZl9sb25nX2ZpZWxkczwtbnNmX2xvbmclPiUKICBmaWx0ZXIodHlwZSE9IkFsbCBkZWdyZWVzIiAmCiAgICAgICAgICAgdHlwZSE9IkFsbCBTJkUiICZ0eXBlIT0iTm9uLVMmRSIgJgogICAgICAgICAgIHR5cGUhPSJTY2llbmNlIiAmIAogICAgICAgICAgIHR5cGUhPSJFbmdpbmVlcmluZyIgJiAKICAgICAgICAgICB0eXBlIT0iRWFydGgsIGF0bW9zcGhlcmljLCBhbmQgb2NlYW4gc2NpZW5jZXMiICYKICAgICAgICAgICB0eXBlIT0iUGh5c2ljYWwgc2NpZW5jZXMiICYgCiAgICAgICAgICAgdHlwZSE9IlNvY2lhbCBzY2llbmNlcyIpJT4lCiAgbXV0YXRlKHR5cGU9cmVwbGFjZSh0eXBlLCB0eXBlPT0iUG9saXRpY2FsIHNjaWVuY2UgYW5kIHB1YmxpYyBhZG1pbmlzdHJhdGlvbiIsIAogICAgICAgICAgICAgICAgICAgICAgIlBvbGkgc2NpICYgcHVibGljIGFkbWluIikpJT4lCiAgbXV0YXRlKHR5cGU9cmVwbGFjZSh0eXBlLCB0eXBlPT0iTWF0aGVtYXRpY3MgYW5kIHN0YXRpc3RpY3MiLCAKICAgICAgICAgICAgICAgICAgICAgICJNYXRoZW1hdGljcyAmIHN0YXRpc3RpY3MiKSklPiUKICBtdXRhdGUodHlwZT1yZXBsYWNlKHR5cGUsIHR5cGU9PSJFdGhuaWMgYW5kIGFyZWEgc3R1ZGllcyIsIAogICAgICAgICAgICAgICAgICAgICAgIkV0aG5pYyAmIGFyZWEgc3R1ZGllcyIpKSU+JQogIG11dGF0ZShjaXRpemVuPXJlcGxhY2UoY2l0aXplbiwgY2l0aXplbj09IlUuUy4gY2l0aXplbiBhbmQgcGVybWFuZW50IHJlc2lkZW50IiwgCiAgICAgICAgICAgICAgICAgICAgICAiVS5TLiBjaXRpemVuIG9yIHBlcm1hbmVudCByZXNpZGVudCIpKQogIApnZ3Bsb3QoZGF0YT1uc2ZfbG9uZ19maWVsZHMsIGFlcyh4PXllYXIsIHk9dmFsdWUxLCBmaWxsPWNpdGl6ZW4sIGdyb3VwPWNpdGl6ZW4pKSArIAogIHRoZW1lX21pbmltYWwoKSsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoZmFtaWx5PSJQYWxhdGlubyIsIHNpemU9MTMpLAogICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwKICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTIyKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSkrCiAgZ2VvbV9hcmVhKGFlcyhmaWxsPWNpdGl6ZW4pLCBwb3NpdGlvbj0nc3RhY2snKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDA5RTczIiwgIiM5OTk5OTkiKSwgbmFtZT0iQ2l0aXplbnNoaXAiKSArIAogIGZhY2V0X3dyYXAofnR5cGUsIHNjYWxlcz0iZnJlZSIpKyBleHBhbmRfbGltaXRzKHkgPSAwKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIicwNiIsICIiLCAiJzA4IiwgIiIsICInMTAiLCAiIiwgIicxMiIsICIiLCAiJzE0IiwgIiIsICInMTYiKSkrCiAgbGFicyh4PSIiLCB5PSJOdW1iZXIgb2YgRG9jdG9yYWwgRGVncmVlcyBBd2FyZGVkIiwgY2FwdGlvbj0iVml6IGJ5IEFsZXggQWxicmlnaHQiKSsKICBnZ3RpdGxlKCJIb3cgTWFueSBTY2llbmNlICYgRW5naW5lZXJpbmcgRG9jdG9yYWwgRGVncmVlIEVhcm5lcnMgYXJlIEludGVybmF0aW9uYWwgU3R1ZGVudHM/IiwgCiAgICAgICAgICBzdWJ0aXRsZT0gIk5TRiBEYXRhIG9uIERvY3RvcmFsIERlZ3JlZXMsIDIwMDYtMjAxNiIpCgpnZ3NhdmUoInBoZF9jb3VudF9ieV9jaXRpemVuc2hpcC5wbmciLCB3aWR0aD0xMiwgaGVpZ2h0PTEwLCBkcGk9MzAwKQpgYGAKCiMgR3JhcGggYnkgcGVyY2VudCB0ZW1wb3JhcnkgcmVzaWRlbnQgd2l0aGluIGZpZWxkCgojIyBOaWdodGluZ2FsZSBwbG90CgpgYGB7cn0KbnNmX2xvbmdfZmllbGRzMTwtbnNmX2xvbmdfZmllbGRzJT4lCiAgZ3JvdXBfYnkoeWVhciwgdHlwZSklPiUKICBtdXRhdGUodG90PXN1bSh2YWx1ZTEpKSU+JQogIGZpbHRlcihjaXRpemVuPT0iVGVtcG9yYXJ5IHJlc2lkZW50IiklPiUKICBtdXRhdGUodGVtcF9wZXJjPXZhbHVlMS90b3QsCiAgICAgICAgIGNpdF9wZXJtX3BlcmM9MS10ZW1wX3BlcmMpJT4lCiAgc2VsZWN0KC1jKHZhbHVlLCB2YWx1ZTEsIHRvdCkpJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSA0OjUpJT4lCiAgbXV0YXRlKG5hbWU9cmVwbGFjZShuYW1lLCBuYW1lPT0idGVtcF9wZXJjIiwgCiAgICAgICAgICAgICAgICAgICAgICAiJSBUZW1wb3JhcnkgcmVzaWRlbnQiKSklPiUKICBtdXRhdGUobmFtZT1yZXBsYWNlKG5hbWUsIG5hbWU9PSJjaXRfcGVybV9wZXJjIiwgCiAgICAgICAgICAgICAgICAgICAgICAiJSBVLlMuIGNpdGl6ZW4gb3IgcGVybWFuZW50IHJlc2lkZW50IikpCgpnZ3Bsb3QoZGF0YT1uc2ZfbG9uZ19maWVsZHMxLCBhZXMoeD15ZWFyLCB5PXZhbHVlLCBmaWxsPW5hbWUsIGdyb3VwPW5hbWUpKSArIAogIHRoZW1lX21pbmltYWwoKSsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoZmFtaWx5PSJQYWxhdGlubyIsIHNpemU9MTMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAuMSwgMC4xLCAwLjEsIDAuMSwgImNtIiksCiAgICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTkpLAogICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT04KSwKICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSkrCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBhZXMoZmlsbD1uYW1lKSwgcG9zaXRpb249J3N0YWNrJykrIAogIGNvb3JkX3BvbGFyKCkrIGZhY2V0X3dyYXAofnR5cGUsIG5yb3c9NSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzAwOUU3MyIsICIjOTk5OTk5IiksIG5hbWU9IkNpdGl6ZW5zaGlwIikgKyAKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIicwNiIsICInMDciLCAiJzA4IiwgIicwOSIsICInMTAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIicxMSIsICInMTIiLCAiJzEzIiwgIicxNCIsICInMTUiLCAiJzE2IikpKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpKwogIGxhYnMoeD0iIiwgeT0iUGVyY2VudCBvZiBEb2N0b3JhbCBEZWdyZWVzIEF3YXJkZWQiLCBjYXB0aW9uPSJWaXogYnkgQWxleCBBbGJyaWdodCIpKwogIGdndGl0bGUoIldoYXQgJSBvZiBTY2llbmNlICYgRW5naW5lZXJpbmcgRG9jdG9yYWwgRGVncmVlIEVhcm5lcnNcbmFyZSBJbnRlcm5hdGlvbmFsIFN0dWRlbnRzPyIsIAogICAgICAgICAgc3VidGl0bGU9ICJOU0YgRGF0YSBvbiBEb2N0b3JhbCBEZWdyZWVzLCAyMDA2LTIwMTYiKQoKZ2dzYXZlKCJwaGRfcGVyX2J5X2NpdGl6ZW5zaGlwLnBuZyIsIHdpZHRoPTgsIGhlaWdodD0xMCwgZHBpPTMwMCkKYGBgCgojIyBqdXN0IGEgc2ltcGxlIGJhciBjaGFydAoKQ29sb3IgZWNvbm9taWNzIGZvciBlbXBoYXNpcy4KCmBgYHtyfQpmaWVsZF9wPC1uc2ZfbG9uZ19maWVsZHMlPiUKICB1bmdyb3VwKCklPiUKICBncm91cF9ieSh0eXBlKSU+JQogIG11dGF0ZSh0b3Q9c3VtKHZhbHVlMSkpJT4lCiAgZmlsdGVyKGNpdGl6ZW49PSJUZW1wb3JhcnkgcmVzaWRlbnQiKSU+JQogIG11dGF0ZSh0ZW1wPXN1bSh2YWx1ZTEpKSU+JQogIG11dGF0ZSh0ZW1wX3BlcmM9dGVtcC90b3QpJT4lCiAgc2VsZWN0KHR5cGUsIHRlbXBfcGVyYyklPiUgdW5pcXVlKCklPiUKICBtdXRhdGUoZWNvbj1pZl9lbHNlKHR5cGU9PSJFY29ub21pY3MiLCAxLCAwKSkKCmdncGxvdChkYXRhPWZpZWxkX3AsIGFlcyh4PXJlb3JkZXIodHlwZSwgLXRlbXBfcGVyYyksIAogICAgICAgICAgICAgICAgICAgICAgICAgeT10ZW1wX3BlcmMsIGZpbGw9ZmFjdG9yKGVjb24pLCBncm91cD1mYWN0b3IoZWNvbikpKSArIAogIHRoZW1lX21pbmltYWwoKSsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoZmFtaWx5PSJQYWxhdGlubyIsIHNpemU9MTMpLAogICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTIwLjUpLAogICAgICAgICAgICAgICAgICAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTkpLAogICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTgpLAogICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTUpKSsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKyBjb29yZF9mbGlwKCkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzk5OTk5OSIsICIjRTY5RjAwIikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwgYnJlYWtzPXNlcSgwLC43LCAuMSkpKwogIGxhYnMoeD0iIiwgeT0iUGVyY2VudCBvZiBEb2N0b3JhbCBEZWdyZWVzIEF3YXJkZWQgdG8gVGVtcG9yYXJ5IFJlc2lkZW50cyIsIAogICAgICAgY2FwdGlvbj0iVml6IGJ5IEFsZXggQWxicmlnaHQiKSsKICBnZ3RpdGxlKCJXaGF0ICUgb2YgU2NpZW5jZSAmIEVuZ2luZWVyaW5nIERvY3RvcmFsIERlZ3JlZSBFYXJuZXJzIGFyZSBJbnRlcm5hdGlvbmFsIFN0dWRlbnRzPyIsIAogICAgICAgICAgc3VidGl0bGU9ICJOU0YgRGF0YSBvbiBEb2N0b3JhbCBEZWdyZWVzLCAyMDA2LTIwMTYiKQoKZ2dzYXZlKCJwaGRfcGVyX3RlbXAucG5nIiwgd2lkdGg9MTEsIGhlaWdodD0xMCwgZHBpPTMwMCkKYGBgCgojIGRpYWdyYW0gZm9yIGhvdyBOU0YgY2F0ZWdvcml6ZXMgdGhpbmdzCgpTZWUgW2hlcmVdKGh0dHBzOi8vbmNzZXMubnNmLmdvdi9wdWJzL25zZjE5MzA0L2RhdGEpIGZvciBzb3VyY2UuIE1vcmUgb24gdGhlIGBEaWFncmFtbWVSYCBwYWNrYWdlIFtoZXJlLl0oaHR0cHM6Ly9taWtleWhhcnBlci51ay9mbG93Y2hhcnRzLWluLXItdXNpbmctZGlhZ3JhbW1lci8pCgpgYGB7cn0KbGlicmFyeShEaWFncmFtbWVSKQpsaWJyYXJ5KERpYWdyYW1tZVJzdmcpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkocnN2ZykKCmdyYXBoPC0iZGlncmFwaCAgewogICAgICBncmFwaCBbbGF5b3V0ID0gZG90LCByYW5rZGlyID0gTFJdCiAgICAgICMgbm9kZSBkZWZpbml0aW9ucyB3aXRoIHN1YnN0aXR1dGVkIGxhYmVsIHRleHQKICAgICAgbm9kZSBbZm9udG5hbWUgPSBQYWxhdGlubywgc2hhcGUgPSByZWN0YW5nbGVdICAgICAgICAKICAgICAgdGFiMSBbbGFiZWwgPSAnQEAxJ10KICAgICAgCiAgICAgIHRhYjIgW2xhYmVsID0gJ0BAMiddCiAgICAgIHRhYjMgW2xhYmVsID0gJ0BAMyddCiAgICAgIAogICAgICB0YWI0IFtsYWJlbCA9ICdAQDQnXQogICAgICB0YWI1IFtsYWJlbCA9ICdAQDUnXQogICAgICAKICAgICAgdGFiNiBbbGFiZWwgPSAnQEA2J10KICAgICAgdGFiNyBbbGFiZWwgPSAnQEA3J10KICAgICAgdGFiOCBbbGFiZWwgPSAnQEA4J10KICAgICAgdGFiOSBbbGFiZWwgPSAnQEA5J10KICAgICAgdGFiMTAgW2xhYmVsID0gJ0BAMTAnXQogICAgICB0YWIxMSBbbGFiZWwgPSAnQEAxMSddCiAgICAgIHRhYjEyIFtsYWJlbCA9ICdAQDEyJ10KICAgICAgdGFiMTMgW2xhYmVsID0gJ0BAMTMnXQogICAgICAKICAgICAgdGFiMTQgW2xhYmVsID0gJ0BAMTQnXQogICAgICB0YWIxNSBbbGFiZWwgPSAnQEAxNSddCiAgICAgIHRhYjE2IFtsYWJlbCA9ICdAQDE2J10KICAgICAgdGFiMTcgW2xhYmVsID0gJ0BAMTcnXQogICAgICB0YWIxOCBbbGFiZWwgPSAnQEAxOCddCiAgICAgIHRhYjE5IFtsYWJlbCA9ICdAQDE5J10KICAgICAgdGFiMjAgW2xhYmVsID0gJ0BAMjAnXQogICAgICB0YWIyMSBbbGFiZWwgPSAnQEAyMSddCiAgICAgIAogICAgICB0YWIyMiBbbGFiZWwgPSAnQEAyMiddCiAgICAgIHRhYjIzIFtsYWJlbCA9ICdAQDIzJ10KICAgICAgdGFiMjQgW2xhYmVsID0gJ0BAMjQnXQogICAgICAKICAgICAgdGFiMjUgW2xhYmVsID0gJ0BAMjUnXQogICAgICB0YWIyNiBbbGFiZWwgPSAnQEAyNiddCiAgICAgIHRhYjI3IFtsYWJlbCA9ICdAQDI3J10KICAgICAgdGFiMjggW2xhYmVsID0gJ0BAMjgnXQogICAgICAKICAgICAgdGFiMjkgW2xhYmVsID0gJ0BAMjknXQogICAgICB0YWIzMCBbbGFiZWwgPSAnQEAzMCddCiAgICAgIHRhYjMxIFtsYWJlbCA9ICdAQDMxJ10KICAgICAgdGFiMzIgW2xhYmVsID0gJ0BAMzInXQogICAgICB0YWIzMyBbbGFiZWwgPSAnQEAzMyddCiAgICAgIHRhYjM0IFtsYWJlbCA9ICdAQDM0J10KICAgICAgdGFiMzUgW2xhYmVsID0gJ0BAMzUnXQogICAgICB0YWIzNiBbbGFiZWwgPSAnQEAzNiddCgogICAgICAjIGVkZ2UgZGVmaW5pdGlvbnMgd2l0aCB0aGUgbm9kZSBJRHMKICAgICAgdGFiMSAtPiB0YWIyOwogICAgICB0YWIxIC0+IHRhYjM7CiAgICAgIAogICAgICB0YWIyIC0+IHRhYjQ7CiAgICAgIHRhYjIgLT4gdGFiNTsKICAgICAgCiAgICAgIHRhYjQgLT4gdGFiNjsKICAgICAgdGFiNCAtPiB0YWI3OwogICAgICB0YWI0IC0+IHRhYjg7CiAgICAgIHRhYjQgLT4gdGFiOTsKICAgICAgdGFiNCAtPiB0YWIxMDsKICAgICAgdGFiNCAtPiB0YWIxMTsKICAgICAgdGFiNCAtPiB0YWIxMjsKICAgICAgdGFiNCAtPiB0YWIxMzsKICAgICAgCiAgICAgIHRhYjUgLT4gdGFiMTQ7CiAgICAgIHRhYjUgLT4gdGFiMTU7CiAgICAgIHRhYjUgLT4gdGFiMTY7CiAgICAgIHRhYjUgLT4gdGFiMTc7CiAgICAgIHRhYjUgLT4gdGFiMTg7CiAgICAgIHRhYjUgLT4gdGFiMTk7CiAgICAgIHRhYjUgLT4gdGFiMjA7CiAgICAgIHRhYjUgLT4gdGFiMjE7CiAgICAgIAogICAgICB0YWI5IC0+IHRhYjIyOwogICAgICB0YWI5IC0+IHRhYjIzOwogICAgICB0YWI5IC0+IHRhYjI0OwogICAgICAKICAgICAgdGFiMTEgLT4gdGFiMjU7CiAgICAgIHRhYjExIC0+IHRhYjI2OwogICAgICB0YWIxMSAtPiB0YWIyNzsKICAgICAgdGFiMTEgLT4gdGFiMjg7CiAgICAgIAogICAgICB0YWIxMyAtPiB0YWIyOTsKICAgICAgdGFiMTMgLT4gdGFiMzA7CiAgICAgIHRhYjEzIC0+IHRhYjMxOwogICAgICB0YWIxMyAtPiB0YWIzMjsKICAgICAgdGFiMTMgLT4gdGFiMzM7CiAgICAgIHRhYjEzIC0+IHRhYjM0OwogICAgICB0YWIxMyAtPiB0YWIzNTsKICAgICAgdGFiMTMgLT4gdGFiMzY7CiAgICAgIH0KCiAgICAgIFsxXTogJ0FsbCBQaERzJwogICAgICBbMl06ICdTJkUnCiAgICAgIFszXTogJ05vbi1TJkUnCiAgICAgIFs0XTogJ1NjaWVuY2UnCiAgICAgIFs1XTogJ0VuZ2luZWVyaW5nJwogICAgICBbNl06ICdBZ3JpY3VsdHVyYWwgU2NpZW5jZXMnCiAgICAgIFs3XTogJ0Jpb2xvZ2ljYWwgU2NpZW5jZXMnCiAgICAgIFs4XTogJ0NvbXB1dGVyIFNjaWVuY2VzJwogICAgICBbOV06ICdFYXJ0aCwgQXRtb3NwaGVyaWMsICYgT2NlYW4gU2NpZW5jZXMnCiAgICAgIFsxMF06ICdNYXRoZW1hdGljcyBhbmQgc3RhdGlzdGljcycKICAgICAgWzExXTogJ1BoeXNpY2FsIHNjaWVuY2VzJwogICAgICBbMTJdOiAnUHN5Y2hvbG9neScKICAgICAgWzEzXTogJ1NvY2lhbCBzY2llbmNlcycKICAgICAgWzE0XTogJ0Flcm9zcGFjZScKICAgICAgWzE1XTogJ0NoZW1pY2FsJwogICAgICBbMTZdOiAnQ2l2aWwnCiAgICAgIFsxN106ICdFbGVjdHJpY2FsJwogICAgICBbMThdOiAnSW5kdXN0cmlhbCcKICAgICAgWzE5XTogJ01hdGVyaWFscycKICAgICAgWzIwXTogJ01lY2hhbmljYWwnCiAgICAgIFsyMV06ICdPdGhlcicKICAgICAgWzIyXTogJ0F0bW9zcGhlcmljIHNjaWVuY2VzJwogICAgICBbMjNdOiAnRWFydGggc2NpZW5jZXMnCiAgICAgIFsyNF06ICdPY2VhbiBzY2llbmNlcycKICAgICAgWzI1XTogJ0FzdHJvbm9teScKICAgICAgWzI2XTogJ0NoZW1pc3RyeScKICAgICAgWzI3XTogJ1BoeXNpY3MnCiAgICAgIFsyOF06ICdPdGhlcicKICAgICAgWzI5XTogJ0FudGhyb3BvbG9neScKICAgICAgWzMwXTogJ0FyZWEgYW5kIGV0aG5pYyBzdHVkaWVzJwogICAgICBbMzFdOiAnRWNvbm9taWNzJwogICAgICBbMzJdOiAnSGlzdG9yeSBvZiBzY2llbmNlJwogICAgICBbMzNdOiAnTGluZ3Vpc3RpY3MnCiAgICAgIFszNF06ICdQb2xpdGljYWwgc2NpZW5jZSAmIHB1YmxpYyBhZG1pbmlzdHJhdGlvbicKICAgICAgWzM1XTogJ1NvY2lvbG9neScKICAgICAgWzM2XTogJ090aGVyJwogICAgICAiCgpnclZpeihncmFwaCkgJT4lCiAgICBleHBvcnRfc3ZnICU+JSBjaGFyVG9SYXcgJT4lIHJzdmdfcG5nKCJuc2ZfY2F0LnBuZyIpCmBgYAoK