The analysis is an exploration of U.S. citizenship in Corona, Queens,
as part of a bigger research of the socio-demographic conditions in the
neighbourhood. The analysis will be divided to 3 different categories:
U.S. citizenship, U.S. citizenship by naturalisation, and non-U.S.
citizenship. The result will also be compared to neighbouring districts
in Community Board 3 and 4.
Data Processing Preparation
To prepare for the analysis, we will load packages before processing
with our data exploration.
library(tidyverse)
library(tidycensus)
library(scales)
library(sf)
library(RColorBrewer)
library(knitr)
options(scipen = 999)
We will then import variables from American Community Survey
(ACS).
acs201620 <- load_variables(2020, "acs5", cache = T)
For the next step, we will import spatial data, which are the borough
shapefiles from NYC Open Data and Neighborhood Tabulation Areas for
NYC.
boros <- st_read("raw/geo/Borough Boundaries.geojson")
nabes <- st_read("raw/geo/nynta2020.shp")
Data Processing
For our exploration, we will look at the imported ACS variables and
choose the Nativity and Citizenship Status in the United States
(B05001) and create a new dataframe to process the
variables.
- B05001_001 = Estimate!!Total:
- B05001_002 = Estimate!!Total:!!U.S. citizen, born in the United
States
- B05001_005 = Estimate!!Total:!!U.S. citizen by naturalization
- B05001_006 = Estimate!!Total:!!Not a U.S. citizen
raw_citizenship <- get_acs(geography = "tract",
variables = c(`Total Population` = "B05001_001",
`U.S. Citizen` = "B05001_002",
`U.S. Citizen (Naturalisation)` = "B05001_005",
`Non-U.S. Citizen` = "B05001_006"),
state='NY',
county = 'Queens',
geometry = T,
year = 2020,
output = "wide")
We will then process the raw dataframe to process the percentage of
citizenship.
citizenship <- raw_citizenship %>%
mutate(`U.S. Citizenship Percentage` = `U.S. CitizenE`/`Total PopulationE`,
`U.S. Citizenship (Naturalisation) Percentage` = `U.S. Citizen (Naturalisation)E`/`Total PopulationE`,
`Non-U.S. Citizenship Percentage` = `Non-U.S. CitizenE`/`Total PopulationE`)
Notice that the table below shows NaN, which means
that the denominator is zero (the same as N/A). We want to process these
NaNs to actual numbers.
| 36081005000 |
Census Tract 50, Queens County, New York |
0 |
12 |
0 |
12 |
0 |
12 |
0 |
12 |
MULTIPOLYGON (((-73.85767 4… |
NaN |
NaN |
NaN |
| 36081006900 |
Census Tract 69, Queens County, New York |
3785 |
598 |
2492 |
513 |
740 |
228 |
465 |
194 |
MULTIPOLYGON (((-73.92511 4… |
0.6583884 |
0.1955086 |
0.1228534 |
| 36081007500 |
Census Tract 75, Queens County, New York |
3982 |
681 |
2430 |
509 |
1026 |
283 |
464 |
307 |
MULTIPOLYGON (((-73.92915 4… |
0.6102461 |
0.2576595 |
0.1165244 |
Processing N/As
We need to redefine the N/As to numbers. First, we will use
is.na() to look at the rows with N/A.
na_tracts <- citizenship %>%
filter(is.na(`U.S. Citizenship Percentage`)) %>%
filter(is.na(`U.S. Citizenship (Naturalisation) Percentage`)) %>%
filter(is.na(`Non-U.S. Citizenship Percentage`))
We will now convert the NaNs or N/As to numbers with the code chunk
below.
citizenship <- raw_citizenship %>%
mutate(`U.S. Citizenship Percentage` = `U.S. CitizenE`/`Total PopulationE`,
`U.S. Citizenship Percentage` = ifelse(is.nan(`U.S. Citizenship Percentage`),
NA, `U.S. Citizenship Percentage`)) %>%
mutate(`Non-U.S. Citizenship Percentage` = `Non-U.S. CitizenE`/`Total PopulationE`,
`Non-U.S. Citizenship Percentage` = ifelse(is.nan(`Non-U.S. Citizenship Percentage`),
NA, `Non-U.S. Citizenship Percentage`)) %>%
mutate(`U.S. Citizenship (Naturalisation) Percentage` = `U.S. Citizen (Naturalisation)E`/`Total PopulationE`,
`U.S. Citizenship (Naturalisation) Percentage` = ifelse(is.nan(`U.S. Citizenship (Naturalisation) Percentage`),
NA, `U.S. Citizenship (Naturalisation) Percentage`))
| 36081005000 |
Census Tract 50, Queens County, New York |
0 |
12 |
0 |
12 |
0 |
12 |
0 |
12 |
MULTIPOLYGON (((-73.85767 4… |
NA |
NA |
NA |
| 36081006900 |
Census Tract 69, Queens County, New York |
3785 |
598 |
2492 |
513 |
740 |
228 |
465 |
194 |
MULTIPOLYGON (((-73.92511 4… |
0.6583884 |
0.1228534 |
0.1955086 |
| 36081007500 |
Census Tract 75, Queens County, New York |
3982 |
681 |
2430 |
509 |
1026 |
283 |
464 |
307 |
MULTIPOLYGON (((-73.92915 4… |
0.6102461 |
0.1165244 |
0.2576595 |
Selecting Census Tract and Spatial Join
For the next step, we will choose the census tract for Corona.
Before that, we have to transform the spatial projection to prepare for
the map.
We will check the projection for the census tract with
st_crs() to print spatial data frames projections in
the console, which will show that the EPSG (code for
projection) is 4269.
st_crs(citizenship)
Check projection for the NTA data, which shows that
the EPSG is 2263.
st_crs(nabes)
Whenever we are working with a New York City data, we want
the projection to be 2263, therefore we will change the
projection using st_transform.
citizenship_2263 <- st_transform(citizenship, 2263)
Check projection again to make sure it works and it will show that
the EPSG is now 2263.
st_crs(citizenship_2263)
We will select the fields from NTA to add to citizenship and remove
unnecessary fields in the neighbourhood shapefile.
nabes_selected <- nabes %>%
select(BoroName, BoroName, NTA2020, NTAName)
We can now perform spatial join!
citizenship_nabes <- citizenship_2263 %>%
st_join(nabes_selected,
left = TRUE, # left -> defines it as left_join -- meaning all census tract are kept
join = st_intersects, # join -> defines the join definition as "if they intersect"
largest = TRUE) # largest -> if a census tract overlaps with more than one neighbourhood, name/join it is as the largest neighbourhood
Selecting Corona
corona <- citizenship_nabes %>%
filter(NTAName == "Corona" | NTAName == "North Corona")
Output
Maps
For this step, we can process the maps for each categories.

The map above shows the percentage of U.S. citizenship in Corona (by
census tract). In general, the rate of U.S. citizenship in Corona is
below 50%, with a concentration of higher percentage in the lower border
and top-left corner of the neighbourhood.

The percentage of naturalised U.S. citizens in Corona has a low
average of 20%, with the highest rate of 32% in census tract area
401.

Contrasting to the maps above, there is a higher average of non-U.S.
citizenship in Corona with the highest percentage of 70%, especially in
the center part the neighbourhood. The lowest percentage is illustrated
on the bottom-left of the map, which is the LeFrak City Apartments.
Summary Statistics for Corona and Neighbouring Districts (CB 3 and
4)
As we have insights on the citizenships in Corona, we can look at the
rate in other neighbourhoods in Community Board 3 and 4 to further
examine the data.
qcb3and4_citizenship_nabes_stats <- st_drop_geometry(citizenship_nabes) %>%
group_by(NTAName) %>%
filter(NTAName == "Corona" | NTAName == "North Corona" | NTAName == "East Elmhurst" | NTAName == "Jackson Heights" | NTAName == "Elmhurst") %>%
summarise(Borough = first(BoroName),
`Est. Total Population` = sum(`Total PopulationE`),
`Est. Total U.S. Citizenship` = sum(`U.S. CitizenE`),
`Est. Total U.S. Citizenship (Naturalisation)` = sum(`U.S. Citizen (Naturalisation)E`),
`Est. Total Non-U.S. Citizenship` = sum(`Non-U.S. CitizenE`)) %>%
mutate(`Est. U.S. Citizenship Percentage` = percent(`Est. Total U.S. Citizenship`/`Est. Total Population`, accuracy = 1L),
`Est. U.S. Citizenship (Naturalisation) Percentage` = percent(`Est. Total U.S. Citizenship (Naturalisation)`/`Est. Total Population`, accuracy = 1L),
`Est. Non-U.S. Citizenship Percentage` = percent(`Est. Total Non-U.S. Citizenship`/`Est. Total Population`, accuracy = 1L))
| Corona |
Queens |
69333 |
27728 |
16108 |
24183 |
40% |
23% |
35% |
| East Elmhurst |
Queens |
24321 |
10537 |
7492 |
5806 |
43% |
31% |
24% |
| Elmhurst |
Queens |
98560 |
31225 |
31629 |
33757 |
32% |
32% |
34% |
| Jackson Heights |
Queens |
89628 |
36016 |
25695 |
25539 |
40% |
29% |
28% |
| North Corona |
Queens |
39263 |
13955 |
7552 |
17113 |
36% |
19% |
44% |
From the table above, we can see that Corona (North Corona
and Corona) has the highest percentage of non-U.S. citizenship compared
to other CB 3 and 4 neighbourhoods. However, we understand that
there is a discrete number of undocumented residents in Corona, hence it
can be assumed that the rate of non-U.S. citizens in Corona is higher
than the indicated number.
LS0tCnRpdGxlOiAiVS5TLiBDaXRpemVuc2hpcCBpbiBDb3JvbmEsIFF1ZWVucyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBub25lCi0tLQoKVGhlIGFuYWx5c2lzIGlzIGFuIGV4cGxvcmF0aW9uIG9mIFUuUy4gY2l0aXplbnNoaXAgaW4gQ29yb25hLCBRdWVlbnMsIGFzIHBhcnQgb2YgYSBiaWdnZXIgcmVzZWFyY2ggb2YgdGhlIHNvY2lvLWRlbW9ncmFwaGljIGNvbmRpdGlvbnMgaW4gdGhlIG5laWdoYm91cmhvb2QuIFRoZSBhbmFseXNpcyB3aWxsIGJlIGRpdmlkZWQgdG8gMyBkaWZmZXJlbnQgY2F0ZWdvcmllczogVS5TLiBjaXRpemVuc2hpcCwgVS5TLiBjaXRpemVuc2hpcCBieSBuYXR1cmFsaXNhdGlvbiwgYW5kIG5vbi1VLlMuIGNpdGl6ZW5zaGlwLiBUaGUgcmVzdWx0IHdpbGwgYWxzbyBiZSBjb21wYXJlZCB0byBuZWlnaGJvdXJpbmcgZGlzdHJpY3RzIGluIENvbW11bml0eSBCb2FyZCAzIGFuZCA0LgoKCiMjIyBEYXRhIFByb2Nlc3NpbmcgUHJlcGFyYXRpb24KClRvIHByZXBhcmUgZm9yIHRoZSBhbmFseXNpcywgd2Ugd2lsbCBsb2FkIHBhY2thZ2VzIGJlZm9yZSBwcm9jZXNzaW5nIHdpdGggb3VyIGRhdGEgZXhwbG9yYXRpb24uCmBgYHtyIFBhY2thZ2VzfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0aWR5Y2Vuc3VzKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShzZikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoa25pdHIpCm9wdGlvbnMoc2NpcGVuID0gOTk5KQpgYGAKCgpXZSB3aWxsIHRoZW4gaW1wb3J0IHZhcmlhYmxlcyBmcm9tIEFtZXJpY2FuIENvbW11bml0eSBTdXJ2ZXkgKEFDUykuCmBgYHtyIEFDUyBWYXJpYWJsZX0KYWNzMjAxNjIwIDwtIGxvYWRfdmFyaWFibGVzKDIwMjAsICJhY3M1IiwgY2FjaGUgPSBUKQpgYGAKCgpGb3IgdGhlIG5leHQgc3RlcCwgd2Ugd2lsbCBpbXBvcnQgc3BhdGlhbCBkYXRhLCB3aGljaCBhcmUgdGhlIGJvcm91Z2ggc2hhcGVmaWxlcyBmcm9tIE5ZQyBPcGVuIERhdGEgYW5kIE5laWdoYm9yaG9vZCBUYWJ1bGF0aW9uIEFyZWFzIGZvciBOWUMuCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmJvcm9zIDwtIHN0X3JlYWQoInJhdy9nZW8vQm9yb3VnaCBCb3VuZGFyaWVzLmdlb2pzb24iKQoKbmFiZXMgPC0gc3RfcmVhZCgicmF3L2dlby9ueW50YTIwMjAuc2hwIikKYGBgCgojIyMgRGF0YSBQcm9jZXNzaW5nCkZvciBvdXIgZXhwbG9yYXRpb24sIHdlIHdpbGwgbG9vayBhdCB0aGUgaW1wb3J0ZWQgQUNTIHZhcmlhYmxlcyBhbmQgY2hvb3NlIHRoZSBfX05hdGl2aXR5IGFuZCBDaXRpemVuc2hpcCBTdGF0dXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgKEIwNTAwMSlfXyBhbmQgY3JlYXRlIGEgbmV3IGRhdGFmcmFtZSB0byBwcm9jZXNzIHRoZSB2YXJpYWJsZXMuCgoqIEIwNTAwMV8wMDEgPSBFc3RpbWF0ZSEhVG90YWw6CiogQjA1MDAxXzAwMiA9IEVzdGltYXRlISFUb3RhbDohIVUuUy4gY2l0aXplbiwgYm9ybiBpbiB0aGUgVW5pdGVkIFN0YXRlcwoqIEIwNTAwMV8wMDUgPSBFc3RpbWF0ZSEhVG90YWw6ISFVLlMuIGNpdGl6ZW4gYnkgbmF0dXJhbGl6YXRpb24KKiBCMDUwMDFfMDA2ID0gRXN0aW1hdGUhIVRvdGFsOiEhTm90IGEgVS5TLiBjaXRpemVuCgpgYGB7cn0KcmF3X2NpdGl6ZW5zaGlwIDwtIGdldF9hY3MoZ2VvZ3JhcGh5ID0gInRyYWN0IiwKICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGVzID0gYyhgVG90YWwgUG9wdWxhdGlvbmAgPSAiQjA1MDAxXzAwMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFUuUy4gQ2l0aXplbmAgPSAiQjA1MDAxXzAwMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFUuUy4gQ2l0aXplbiAoTmF0dXJhbGlzYXRpb24pYCA9ICJCMDUwMDFfMDA1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm9uLVUuUy4gQ2l0aXplbmAgPSAiQjA1MDAxXzAwNiIpLAogICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZT0nTlknLAogICAgICAgICAgICAgICAgICAgICAgICBjb3VudHkgPSAnUXVlZW5zJywKICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnkgPSBULAogICAgICAgICAgICAgICAgICAgICAgICB5ZWFyID0gMjAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gIndpZGUiKQpgYGAKCgpXZSB3aWxsIHRoZW4gcHJvY2VzcyB0aGUgcmF3IGRhdGFmcmFtZSB0byBwcm9jZXNzIHRoZSBwZXJjZW50YWdlIG9mIGNpdGl6ZW5zaGlwLgpgYGB7cn0KY2l0aXplbnNoaXAgPC0gcmF3X2NpdGl6ZW5zaGlwICU+JSAKICBtdXRhdGUoYFUuUy4gQ2l0aXplbnNoaXAgUGVyY2VudGFnZWAgPSBgVS5TLiBDaXRpemVuRWAvYFRvdGFsIFBvcHVsYXRpb25FYCwKICAgICAgICAgYFUuUy4gQ2l0aXplbnNoaXAgKE5hdHVyYWxpc2F0aW9uKSBQZXJjZW50YWdlYCA9IGBVLlMuIENpdGl6ZW4gKE5hdHVyYWxpc2F0aW9uKUVgL2BUb3RhbCBQb3B1bGF0aW9uRWAsCiAgICAgICAgIGBOb24tVS5TLiBDaXRpemVuc2hpcCBQZXJjZW50YWdlYCA9IGBOb24tVS5TLiBDaXRpemVuRWAvYFRvdGFsIFBvcHVsYXRpb25FYCkKYGBgCgoKTm90aWNlIHRoYXQgdGhlIHRhYmxlIGJlbG93IHNob3dzIF9fTmFOX18sIHdoaWNoIG1lYW5zIHRoYXQgdGhlIGRlbm9taW5hdG9yIGlzIHplcm8gKHRoZSBzYW1lIGFzIE4vQSkuIFdlIHdhbnQgdG8gcHJvY2VzcyB0aGVzZSBOYU5zIHRvIGFjdHVhbCBudW1iZXJzLgpgYGB7ciBlY2hvPUZBTFNFfQprYWJsZShoZWFkKGNpdGl6ZW5zaGlwLCBuID0gMykpCmBgYAoKKioqCgojIyMjIyBQcm9jZXNzaW5nIE4vQXMKV2UgbmVlZCB0byByZWRlZmluZSB0aGUgTi9BcyB0byBudW1iZXJzLiBGaXJzdCwgd2Ugd2lsbCB1c2UgX19pcy5uYSgpX18gdG8gbG9vayBhdCB0aGUgcm93cyB3aXRoIE4vQS4KYGBge3J9Cm5hX3RyYWN0cyA8LSBjaXRpemVuc2hpcCAlPiUgCiAgZmlsdGVyKGlzLm5hKGBVLlMuIENpdGl6ZW5zaGlwIFBlcmNlbnRhZ2VgKSkgJT4lCiAgZmlsdGVyKGlzLm5hKGBVLlMuIENpdGl6ZW5zaGlwIChOYXR1cmFsaXNhdGlvbikgUGVyY2VudGFnZWApKSAlPiUgCiAgZmlsdGVyKGlzLm5hKGBOb24tVS5TLiBDaXRpemVuc2hpcCBQZXJjZW50YWdlYCkpCmBgYAoKYGBge3IgZWNobz1GQUxTRX0Ka2FibGUoaGVhZChuYV90cmFjdHMsIG4gPSAzKSkKYGBgCgpXZSB3aWxsIG5vdyBjb252ZXJ0IHRoZSBOYU5zIG9yIE4vQXMgdG8gbnVtYmVycyB3aXRoIHRoZSBjb2RlIGNodW5rIGJlbG93LgoKYGBge3J9CmNpdGl6ZW5zaGlwIDwtIHJhd19jaXRpemVuc2hpcCAlPiUgCiAgbXV0YXRlKGBVLlMuIENpdGl6ZW5zaGlwIFBlcmNlbnRhZ2VgID0gYFUuUy4gQ2l0aXplbkVgL2BUb3RhbCBQb3B1bGF0aW9uRWAsCiAgICAgICAgIGBVLlMuIENpdGl6ZW5zaGlwIFBlcmNlbnRhZ2VgID0gaWZlbHNlKGlzLm5hbihgVS5TLiBDaXRpemVuc2hpcCBQZXJjZW50YWdlYCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLCBgVS5TLiBDaXRpemVuc2hpcCBQZXJjZW50YWdlYCkpICU+JQogIG11dGF0ZShgTm9uLVUuUy4gQ2l0aXplbnNoaXAgUGVyY2VudGFnZWAgPSBgTm9uLVUuUy4gQ2l0aXplbkVgL2BUb3RhbCBQb3B1bGF0aW9uRWAsCiAgICAgICAgIGBOb24tVS5TLiBDaXRpemVuc2hpcCBQZXJjZW50YWdlYCA9IGlmZWxzZShpcy5uYW4oYE5vbi1VLlMuIENpdGl6ZW5zaGlwIFBlcmNlbnRhZ2VgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsIGBOb24tVS5TLiBDaXRpemVuc2hpcCBQZXJjZW50YWdlYCkpICU+JSAKICBtdXRhdGUoYFUuUy4gQ2l0aXplbnNoaXAgKE5hdHVyYWxpc2F0aW9uKSBQZXJjZW50YWdlYCA9IGBVLlMuIENpdGl6ZW4gKE5hdHVyYWxpc2F0aW9uKUVgL2BUb3RhbCBQb3B1bGF0aW9uRWAsCiAgICAgICAgIGBVLlMuIENpdGl6ZW5zaGlwIChOYXR1cmFsaXNhdGlvbikgUGVyY2VudGFnZWAgPSBpZmVsc2UoaXMubmFuKGBVLlMuIENpdGl6ZW5zaGlwIChOYXR1cmFsaXNhdGlvbikgUGVyY2VudGFnZWApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsIGBVLlMuIENpdGl6ZW5zaGlwIChOYXR1cmFsaXNhdGlvbikgUGVyY2VudGFnZWApKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CmthYmxlKGhlYWQoY2l0aXplbnNoaXAsIG4gPSAzKSkKYGBgCgoqKioKCiMjIyMjIFNlbGVjdGluZyBDZW5zdXMgVHJhY3QgYW5kIFNwYXRpYWwgSm9pbgpGb3IgdGhlIG5leHQgc3RlcCwgd2Ugd2lsbCBjaG9vc2UgdGhlIGNlbnN1cyB0cmFjdCBmb3IgQ29yb25hLiAgCkJlZm9yZSB0aGF0LCB3ZSBoYXZlIHRvIHRyYW5zZm9ybSB0aGUgc3BhdGlhbCBwcm9qZWN0aW9uIHRvIHByZXBhcmUgZm9yIHRoZSBtYXAuCgoKV2Ugd2lsbCBjaGVjayB0aGUgcHJvamVjdGlvbiBmb3IgdGhlIGNlbnN1cyB0cmFjdCB3aXRoIF9fc3RfY3JzKClfXyB0byBwcmludCBzcGF0aWFsIGRhdGEgZnJhbWVzIHByb2plY3Rpb25zIGluIHRoZSBjb25zb2xlLCB3aGljaCB3aWxsIHNob3cgdGhhdCB0aGUgX19FUFNHX18gKGNvZGUgZm9yIHByb2plY3Rpb24pIGlzIF9fNDI2OV9fLgpgYGB7cn0Kc3RfY3JzKGNpdGl6ZW5zaGlwKQpgYGAKCkNoZWNrIHByb2plY3Rpb24gZm9yIHRoZSBfX05UQSBkYXRhX18sIHdoaWNoIHNob3dzIHRoYXQgdGhlIF9fRVBTR19fIGlzIF9fMjI2M19fLgpgYGB7cn0Kc3RfY3JzKG5hYmVzKQpgYGAKCl9fV2hlbmV2ZXIgd2UgYXJlIHdvcmtpbmcgd2l0aCBhIE5ldyBZb3JrIENpdHkgZGF0YSwgd2Ugd2FudCB0aGUgcHJvamVjdGlvbiB0byBiZSAyMjYzX18sIHRoZXJlZm9yZSB3ZSB3aWxsIGNoYW5nZSB0aGUgcHJvamVjdGlvbiB1c2luZyBzdF90cmFuc2Zvcm0uCmBgYHtyfQpjaXRpemVuc2hpcF8yMjYzIDwtICBzdF90cmFuc2Zvcm0oY2l0aXplbnNoaXAsIDIyNjMpCmBgYAoKQ2hlY2sgcHJvamVjdGlvbiBhZ2FpbiB0byBtYWtlIHN1cmUgaXQgd29ya3MgYW5kIGl0IHdpbGwgc2hvdyB0aGF0IHRoZSBfX0VQU0cgaXMgbm93IDIyNjNfXy4KYGBge3J9CnN0X2NycyhjaXRpemVuc2hpcF8yMjYzKQpgYGAKCgpXZSB3aWxsIHNlbGVjdCB0aGUgZmllbGRzIGZyb20gTlRBIHRvIGFkZCB0byBjaXRpemVuc2hpcCBhbmQgcmVtb3ZlIHVubmVjZXNzYXJ5IGZpZWxkcyBpbiB0aGUgbmVpZ2hib3VyaG9vZCBzaGFwZWZpbGUuCmBgYHtyfQpuYWJlc19zZWxlY3RlZCA8LSBuYWJlcyAlPiUKICBzZWxlY3QoQm9yb05hbWUsIEJvcm9OYW1lLCBOVEEyMDIwLCBOVEFOYW1lKQpgYGAKCgpXZSBjYW4gbm93IHBlcmZvcm0gc3BhdGlhbCBqb2luIQpgYGB7cn0KY2l0aXplbnNoaXBfbmFiZXMgPC0gY2l0aXplbnNoaXBfMjI2MyAlPiUKICBzdF9qb2luKG5hYmVzX3NlbGVjdGVkLCAKICAgICAgICAgIGxlZnQgPSBUUlVFLCAjIGxlZnQgLT4gZGVmaW5lcyBpdCBhcyBsZWZ0X2pvaW4gLS0gbWVhbmluZyBhbGwgY2Vuc3VzIHRyYWN0IGFyZSBrZXB0CiAgICAgICAgICBqb2luID0gc3RfaW50ZXJzZWN0cywgIyBqb2luIC0+IGRlZmluZXMgdGhlIGpvaW4gZGVmaW5pdGlvbiBhcyAiaWYgdGhleSBpbnRlcnNlY3QiCiAgICAgICAgICBsYXJnZXN0ID0gVFJVRSkgIyBsYXJnZXN0IC0+IGlmIGEgY2Vuc3VzIHRyYWN0IG92ZXJsYXBzIHdpdGggbW9yZSB0aGFuIG9uZSBuZWlnaGJvdXJob29kLCBuYW1lL2pvaW4gaXQgaXMgYXMgdGhlIGxhcmdlc3QgbmVpZ2hib3VyaG9vZAoKYGBgCgoqKioKCiMjIyMjIFNlbGVjdGluZyBDb3JvbmEKYGBge3J9CmNvcm9uYSA8LSBjaXRpemVuc2hpcF9uYWJlcyAlPiUgCiAgZmlsdGVyKE5UQU5hbWUgPT0gIkNvcm9uYSIgfCBOVEFOYW1lID09ICJOb3J0aCBDb3JvbmEiKQpgYGAKCgojIyMgT3V0cHV0CiMjIyMjIE1hcHMKRm9yIHRoaXMgc3RlcCwgd2UgY2FuIHByb2Nlc3MgdGhlIG1hcHMgZm9yIGVhY2ggY2F0ZWdvcmllcy4gIAoKCmBgYHtyIGVjaG89RkFMU0V9CmdncGxvdCgpICArIAogIGdlb21fc2YoZGF0YSA9IGNvcm9uYSwgbWFwcGluZyA9IGFlcyhmaWxsID0gYFUuUy4gQ2l0aXplbnNoaXAgUGVyY2VudGFnZWApLCAKICAgICAgICAgIGNvbG9yID0gIiNmZmZmZmYiLAogICAgICAgICAgbHdkID0gMCkgKyAjIHJlbW92ZXMgdGhlIGNlbnN1cyB0cmFjdCBvdXRsaW5lCiAgdGhlbWVfdm9pZCgpICsKICBzY2FsZV9maWxsX2Rpc3RpbGxlcihicmVha3MgPSBjKDAsIC4yLCAuNCwgLjYsIC44LCAxKSwKICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAxLAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlUuUy4gQ2l0aXplbnNoaXAgKCUpIiwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDFMKSkgKwogIGxhYnModGl0bGUgPSAiQ29yb25hLCBRdWVlbnMsIFUuUy4gQ2l0aXplbnNoaXAgYnkgQ2Vuc3VzIFRyYWN0IiwKICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBBbWVyaWNhbiBDb21tdW5pdHkgU3VydmV5LCAyMDE2LTIwIikgKyAKICBnZW9tX3NmKGRhdGEgPSBuYWJlcyAlPiUgCiAgICAgICAgICAgIGZpbHRlcihOVEFOYW1lID09ICJDb3JvbmEiIHwgTlRBTmFtZSA9PSAiTm9ydGggQ29yb25hIiksCiAgICAgICAgICBjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgbHdkID0gMC41KQpgYGAKVGhlIG1hcCBhYm92ZSBzaG93cyB0aGUgcGVyY2VudGFnZSBvZiBVLlMuIGNpdGl6ZW5zaGlwIGluIENvcm9uYSAoYnkgY2Vuc3VzIHRyYWN0KS4gSW4gZ2VuZXJhbCwgdGhlIHJhdGUgb2YgVS5TLiBjaXRpemVuc2hpcCBpbiBDb3JvbmEgaXMgYmVsb3cgNTAlLCB3aXRoIGEgY29uY2VudHJhdGlvbiBvZiBoaWdoZXIgcGVyY2VudGFnZSBpbiB0aGUgbG93ZXIgYm9yZGVyIGFuZCB0b3AtbGVmdCBjb3JuZXIgb2YgdGhlIG5laWdoYm91cmhvb2QuICAKCgpgYGB7ciBlY2hvPUZBTFNFfQpnZ3Bsb3QoKSAgKyAKICBnZW9tX3NmKGRhdGEgPSBjb3JvbmEsIG1hcHBpbmcgPSBhZXMoZmlsbCA9IGBVLlMuIENpdGl6ZW5zaGlwIChOYXR1cmFsaXNhdGlvbikgUGVyY2VudGFnZWApLCAKICAgICAgICAgIGNvbG9yID0gIiNmZmZmZmYiLAogICAgICAgICAgbHdkID0gMCkgKyAjIHJlbW92ZXMgdGhlIGNlbnN1cyB0cmFjdCBvdXRsaW5lCiAgdGhlbWVfdm9pZCgpICsKICBzY2FsZV9maWxsX2Rpc3RpbGxlcihicmVha3MgPSBjKDAsIC4yLCAuNCwgLjYsIC44LCAxKSwKICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAxLAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlUuUy4gQ2l0aXplbnNoaXAgKE5hdHVyYWxpc2F0aW9uKSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMUwpKSArCiAgbGFicyh0aXRsZSA9ICJDb3JvbmEsIFF1ZWVucywgVS5TLiBDaXRpemVuc2hpcCAoTmF0dXJhbGlzYXRpb24pIGJ5IENlbnN1cyBUcmFjdCIsCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleSwgMjAxNi0yMCIpICsgCiAgZ2VvbV9zZihkYXRhID0gbmFiZXMgJT4lIAogICAgICAgICAgICBmaWx0ZXIoTlRBTmFtZSA9PSAiQ29yb25hIiB8IE5UQU5hbWUgPT0gIk5vcnRoIENvcm9uYSIpLAogICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIGx3ZCA9IDAuNSkKYGBgClRoZSBwZXJjZW50YWdlIG9mIG5hdHVyYWxpc2VkIFUuUy4gY2l0aXplbnMgaW4gQ29yb25hIGhhcyBhIGxvdyBhdmVyYWdlIG9mIDIwJSwgd2l0aCB0aGUgaGlnaGVzdCByYXRlIG9mIDMyJSBpbiBjZW5zdXMgdHJhY3QgYXJlYSA0MDEuCgpgYGB7ciBlY2hvPUZBTFNFfQpnZ3Bsb3QoKSAgKyAKICBnZW9tX3NmKGRhdGEgPSBjb3JvbmEsIG1hcHBpbmcgPSBhZXMoZmlsbCA9IGBOb24tVS5TLiBDaXRpemVuc2hpcCBQZXJjZW50YWdlYCksIAogICAgICAgICAgY29sb3IgPSAiI2ZmZmZmZiIsCiAgICAgICAgICBsd2QgPSAwKSArICMgcmVtb3ZlcyB0aGUgY2Vuc3VzIHRyYWN0IG91dGxpbmUKICB0aGVtZV92b2lkKCkgKwogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKGJyZWFrcyA9IGMoMCwgLjIsIC40LCAuNiwgLjgsIDEpLAogICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiTm9uLVUuUy4gQ2l0aXplbnNoaXAgKCUpIiwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDFMKSkgKwogIGxhYnModGl0bGUgPSAiQ29yb25hLCBRdWVlbnMsIE5vbi1VLlMuIENpdGl6ZW5zaGlwIGJ5IENlbnN1cyBUcmFjdCIsCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleSwgMjAxNi0yMCIpICsgCiAgZ2VvbV9zZihkYXRhID0gbmFiZXMgJT4lIAogICAgICAgICAgICBmaWx0ZXIoTlRBTmFtZSA9PSAiQ29yb25hIiB8IE5UQU5hbWUgPT0gIk5vcnRoIENvcm9uYSIpLAogICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIGx3ZCA9IDAuNSkKYGBgCkNvbnRyYXN0aW5nIHRvIHRoZSBtYXBzIGFib3ZlLCB0aGVyZSBpcyBhIGhpZ2hlciBhdmVyYWdlIG9mIG5vbi1VLlMuIGNpdGl6ZW5zaGlwIGluIENvcm9uYSB3aXRoIHRoZSBoaWdoZXN0IHBlcmNlbnRhZ2Ugb2YgNzAlLCBlc3BlY2lhbGx5IGluIHRoZSBjZW50ZXIgcGFydCB0aGUgbmVpZ2hib3VyaG9vZC4gVGhlIGxvd2VzdCBwZXJjZW50YWdlIGlzIGlsbHVzdHJhdGVkIG9uIHRoZSBib3R0b20tbGVmdCBvZiB0aGUgbWFwLCB3aGljaCBpcyB0aGUgTGVGcmFrIENpdHkgQXBhcnRtZW50cy4KCioqKgoKIyMjIyMgU3VtbWFyeSBTdGF0aXN0aWNzIGZvciBDb3JvbmEgYW5kIE5laWdoYm91cmluZyBEaXN0cmljdHMgKENCIDMgYW5kIDQpCkFzIHdlIGhhdmUgaW5zaWdodHMgb24gdGhlIGNpdGl6ZW5zaGlwcyBpbiBDb3JvbmEsIHdlIGNhbiBsb29rIGF0IHRoZSByYXRlIGluIG90aGVyIG5laWdoYm91cmhvb2RzIGluIENvbW11bml0eSBCb2FyZCAzIGFuZCA0IHRvIGZ1cnRoZXIgZXhhbWluZSB0aGUgZGF0YS4KCmBgYHtyfQpxY2IzYW5kNF9jaXRpemVuc2hpcF9uYWJlc19zdGF0cyA8LSBzdF9kcm9wX2dlb21ldHJ5KGNpdGl6ZW5zaGlwX25hYmVzKSAlPiUgCiAgZ3JvdXBfYnkoTlRBTmFtZSkgJT4lIAogIGZpbHRlcihOVEFOYW1lID09ICJDb3JvbmEiIHwgTlRBTmFtZSA9PSAiTm9ydGggQ29yb25hIiB8IE5UQU5hbWUgPT0gIkVhc3QgRWxtaHVyc3QiIHwgTlRBTmFtZSA9PSAiSmFja3NvbiBIZWlnaHRzIiB8IE5UQU5hbWUgPT0gIkVsbWh1cnN0IikgJT4lIAogIHN1bW1hcmlzZShCb3JvdWdoID0gZmlyc3QoQm9yb05hbWUpLAogICAgICAgICAgICBgRXN0LiBUb3RhbCBQb3B1bGF0aW9uYCA9IHN1bShgVG90YWwgUG9wdWxhdGlvbkVgKSwKICAgICAgICAgICAgYEVzdC4gVG90YWwgVS5TLiBDaXRpemVuc2hpcGAgPSBzdW0oYFUuUy4gQ2l0aXplbkVgKSwKICAgICAgICAgICAgYEVzdC4gVG90YWwgVS5TLiBDaXRpemVuc2hpcCAoTmF0dXJhbGlzYXRpb24pYCA9IHN1bShgVS5TLiBDaXRpemVuIChOYXR1cmFsaXNhdGlvbilFYCksCiAgICAgICAgICAgIGBFc3QuIFRvdGFsIE5vbi1VLlMuIENpdGl6ZW5zaGlwYCA9IHN1bShgTm9uLVUuUy4gQ2l0aXplbkVgKSkgJT4lIAogIG11dGF0ZShgRXN0LiBVLlMuIENpdGl6ZW5zaGlwIFBlcmNlbnRhZ2VgID0gcGVyY2VudChgRXN0LiBUb3RhbCBVLlMuIENpdGl6ZW5zaGlwYC9gRXN0LiBUb3RhbCBQb3B1bGF0aW9uYCxhY2N1cmFjeSA9IDFMKSwKICAgICAgICAgYEVzdC4gVS5TLiBDaXRpemVuc2hpcCAoTmF0dXJhbGlzYXRpb24pIFBlcmNlbnRhZ2VgID0gcGVyY2VudChgRXN0LiBUb3RhbCBVLlMuIENpdGl6ZW5zaGlwIChOYXR1cmFsaXNhdGlvbilgL2BFc3QuIFRvdGFsIFBvcHVsYXRpb25gLCBhY2N1cmFjeSA9IDFMKSwKICAgICAgICAgYEVzdC4gTm9uLVUuUy4gQ2l0aXplbnNoaXAgUGVyY2VudGFnZWAgPSBwZXJjZW50KGBFc3QuIFRvdGFsIE5vbi1VLlMuIENpdGl6ZW5zaGlwYC9gRXN0LiBUb3RhbCBQb3B1bGF0aW9uYCwgYWNjdXJhY3kgPSAxTCkpCmBgYAoKYGBge3IgZWNobz1GQUxTRX0Ka2FibGUoaGVhZChxY2IzYW5kNF9jaXRpemVuc2hpcF9uYWJlc19zdGF0cykpCmBgYApGcm9tIHRoZSB0YWJsZSBhYm92ZSwgd2UgY2FuIHNlZSB0aGF0IF9fQ29yb25hIChOb3J0aCBDb3JvbmEgYW5kIENvcm9uYSkgaGFzIHRoZSBoaWdoZXN0IHBlcmNlbnRhZ2Ugb2Ygbm9uLVUuUy4gY2l0aXplbnNoaXAgY29tcGFyZWQgdG8gb3RoZXIgQ0IgMyBhbmQgNCBuZWlnaGJvdXJob29kc19fLiBIb3dldmVyLCB3ZSB1bmRlcnN0YW5kIHRoYXQgdGhlcmUgaXMgYSBkaXNjcmV0ZSBudW1iZXIgb2YgdW5kb2N1bWVudGVkIHJlc2lkZW50cyBpbiBDb3JvbmEsIGhlbmNlIGl0IGNhbiBiZSBhc3N1bWVkIHRoYXQgdGhlIHJhdGUgb2Ygbm9uLVUuUy4gY2l0aXplbnMgaW4gQ29yb25hIGlzIGhpZ2hlciB0aGFuIHRoZSBpbmRpY2F0ZWQgbnVtYmVyLgoKCgoKCgoKCgoK