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. 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
[30m── [1mAttaching packages[22m ───────────────────────────────────────────────────────────── tidyverse 1.3.0 ──[39m
[30m[32m✓[30m [34mggplot2[30m 3.3.0 [32m✓[30m [34mpurrr [30m 0.3.4
[32m✓[30m [34mtibble [30m 3.0.1 [32m✓[30m [34mdplyr [30m 0.8.5
[32m✓[30m [34mtidyr [30m 1.0.3 [32m✓[30m [34mstringr[30m 1.4.0
[32m✓[30m [34mreadr [30m 1.3.1 [32m✓[30m [34mforcats[30m 0.5.0[39m
[30m── [1mConflicts[22m ──────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
[31mx[30m [34mdplyr[30m::[32mfilter()[30m masks [34mstats[30m::filter()
[31mx[30m [34mdplyr[30m::[32mlag()[30m masks [34mstats[30m::lag()[39m
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.
[90mThis warning is displayed once every 8 hours.[39m
[90mCall `lifecycle::last_warnings()` to see where this warning was generated.[39m
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")
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