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.

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.

GEOID NAME Total PopulationE Total PopulationM U.S. CitizenE U.S. CitizenM U.S. Citizen (Naturalisation)E U.S. Citizen (Naturalisation)M Non-U.S. CitizenE Non-U.S. CitizenM geometry U.S. Citizenship Percentage U.S. Citizenship (Naturalisation) Percentage Non-U.S. Citizenship Percentage
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`))
GEOID NAME Total PopulationE Total PopulationM U.S. CitizenE U.S. CitizenM U.S. Citizen (Naturalisation)E U.S. Citizen (Naturalisation)M Non-U.S. CitizenE Non-U.S. CitizenM geometry U.S. Citizenship Percentage Non-U.S. Citizenship Percentage 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))
NTAName Borough Est. Total Population Est. Total U.S. Citizenship Est. Total U.S. Citizenship (Naturalisation) Est. Total Non-U.S. Citizenship Est. U.S. Citizenship Percentage Est. U.S. Citizenship (Naturalisation) Percentage Est. Non-U.S. Citizenship Percentage
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