Introduction

Boston is one of the largest cities in the United States and is an integral part of the Northeast Economic Corridor. Over time, it has become a center for culture and innovation. The high density of higher education institutes like Harvard and MIT have brought Boston to the forefront of scientific research. Boston is also major hub for various industries, including finance, technology, healthcare, and biotechnology.

Boston’s rapid transit system, known as the “T,” is a vital component of the city’s public transportation network. Operated by the Massachusetts Bay Transportation Authority (MBTA), it consists of four subway lines (Red, Orange, Blue, and Green), serving both the city and surrounding suburbs. Transit-Oriented Development (TOD) in Boston, like many other cities, is aimed at creating vibrant, mixed-use communities around the city’s extensive public transit network, particularly the rapid transit subway lines.

This policy brief attempts to address the value and citzen settlement patterns of transit-rich neighborhoods, comparing them to the city at large. It makes extensive use of the American Community Survey data, along with publically available information on the MBTA’s rapid transit routes and stops.

This code is built upon the classwork discussed here.

R Setup and Installing Packages

This code chunk handles the essential tasks of loading necessary packages, configuring the Census API key, defining class functions, specifying a color palette, and managing global environment settings.

library(tidyverse)
library(tidycensus)
library(sf)
library(kableExtra)
library(tidyr)
library(ggplot2)
library(viridis)
library(prettydoc)
library(stringr)

options(scipen=999)
options(tigris_class = "sf")

#these are functions developed for this class, so it takes you especially to the book to get those

source("https://raw.githubusercontent.com/urbanSpatial/Public-Policy-Analytics-Landing/master/functions.r")

palette5 <- c("#fde725","#5ec962","#21918c","#3b528b","#440154")

census_api_key('bf2d507651b5a621dbadd44533fb4f3deaab26bf', overwrite = TRUE)

Loading Census Data

The years chosen for analysis are 2016 and 2020. Over this period, Boston’s Rapid Transit went through significant changes, the most notable one being the planning and construction of the extended Green Line. By extending the Green Line into historically under-served areas like Somerville and Medford, it has not only eased commuting for residents but also bolstered ridership across the entire line, reducing congestion and offering more accessible transit options to thousands of daily commuters.

acs_variable_list.2020 <- load_variables(2020, #year
                                         "acs5", #five year ACS estimates
                                         cache = TRUE)

acs_variable_list.2016 <- load_variables(2016, #year
                                         "acs5", #five year ACS estimates
                                         cache = TRUE)

The variables chosen for this analysis include:

  1. Total Population in Occupied Housing Units: This variable is related to TOD because the success of transit-oriented development often depends on population density. Higher population density typically leads to more demand for public transportation services. TOD areas are designed to accommodate a larger population within a compact, walkable neighborhood, which can reduce reliance on personal vehicles and promote the use of public transit.

  2. Median household Income in the past 12 months: Income levels are relevant to TOD because they influence both the demand for public transportation and the types of amenities and services that can be supported in a TOD area. Low- to moderate-income households may rely more on public transit, making it crucial to have affordable transportation options in TOD developments. Additionally, higher-income residents can support a range of businesses and services within the TOD area.

  3. Median Rent over the past 12 months: Rent levels are important in TOD areas because they can affect housing affordability, which is a critical factor for attracting residents who want to live near transit hubs. Affordable housing options in TODs can encourage people to choose public transportation over private cars, as they can live closer to work and amenities without a long commute.

  4. Number of People employed in the Business, Arts or Sciences sector: Boston is known as a hub for these industries, with numerous prestigious universities and cultural institutions located in the area. If residents engaged in this sector are choosing to located within TOD districts, it’s indicative of what future routes and access should be prioritized.

  5. Median gross rent as a percentage of household income: This variable relates to housing affordability, which is a key aspect of TOD. The percentage of household income spent on rent can indicate whether housing is affordable for the local population. Lower rent as a percentage of income suggests greater affordability, which can attract a diverse mix of residents, including those who rely on public transit. It also relates to the previous indicator, as the Business, Arts and Sciences sector typically involves high paying jobs for residents.

tracts16 <- 
  get_acs(geography = "tract", 
          variables = c("B25026_001E",#pop
                        "B19013_001E", #med inc
                        "B25058_001E", #rent
                        "B24011_002E", #ppl in business science arts 
                        "B25071_001E"), #inc as % of rent
          year=2016, 
          state = 25,
          county=025, #using the boston/suffolk county FIPS code
          geometry=TRUE, output="wide")%>%
  st_transform('ESRI:102728') %>%
  rename(TotalPop = B25026_001E, 
         MedInc = B19013_001E,
         MedRent = B25058_001E, 
         BusArtsScience = B24011_002E,
         IncSpentOnRentPCt = B25071_001E)%>%
  dplyr::select(-NAME, -ends_with("M")) %>%
  mutate(year = "2016") 

# 2020

tracts20 <- 
   get_acs(geography = "tract", 
          variables = c("B25026_001E",#pop
                        "B19013_001E", #med inc
                        "B25058_001E", #rent
                        "B24011_002E", #ppl in business science arts 
                        "B25071_001E"), #inc as % of rent
          year=2020, 
          state = 25,
          county=025, #using the boston/suffolk county FIPS code
          geometry=TRUE, output="wide")%>%
  st_transform('ESRI:102728') %>%
  rename(TotalPop = B25026_001E, 
         MedInc = B19013_001E,
         MedRent = B25058_001E, 
         BusArtsScience = B24011_002E,
         IncSpentOnRentPCt = B25071_001E)%>%
  dplyr::select(-NAME, -ends_with("M")) %>%
  mutate(year = "2020") 


#binding the data
allTracts <- rbind(tracts16,tracts20)

Loading MBTA Stops

MBTA Rapid Transit data represents the station stops on the five subway, streetcar/trolley and Silver Line bus “T” lines (Blue, Green, Orange, Red and Silver) in the Massachusetts Bay Transportation Authority’s rapid transit rail network. The layers were developed by the Central Transportation Planning Staff (CTPS), with additional editing by MassGIS based on current aerial imagery and information from this source.

url <-"https://gis.massdot.state.ma.us/arcgis/rest/services/Multimodal/GTFS_Systemwide/MapServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json"

MBTAStops <- st_read(url) %>% 
  st_transform(st_crs(tracts16))  
#clipping to tracts boundaries 

clippedMBTA <- 
  st_intersection(MBTAStops, tracts16)

#plotting

ggplot() + 
  geom_sf(data=st_union(tracts16)) +
  geom_sf(data=clippedMBTA) +
  labs(title="MBTA Stops", 
       subtitle="Boston, MA", 
       caption="Figure 1.1") +
  mapTheme()

Data Analysis

This section is focused on examining various socio-economic indicators in relation to transit-oriented development (TOD) and non-TOD areas within the context of Boston’s public transit system. It makes use of the ggplot and kable packages for effective visualizations.

Creating Buffers and Selecting Census Tracts

Half mile buffers were created as half a mile translates to a roughly 10 minute walkshed, making it reasonable to assume that the area within those buffers are the most significantly affected by the presence of transit.

#creating a buffer

MBTABuffers <- 
  rbind(
    st_buffer(clippedMBTA, 2640) %>% #the number at the end is in feet, because our CRS is in feet
      mutate(Legend = "Buffer") %>%
      dplyr::select(Legend),
    st_union(st_buffer(clippedMBTA, 2640)) %>%
      st_sf() %>%
      mutate(Legend = "Unioned Buffer")) #all st functions will be spatial related stuff

ggplot() +
  geom_sf(data=MBTABuffers) +
  geom_sf(data=clippedMBTA, show.legend = "point") +
  facet_wrap(~Legend) + 
  labs(caption = "Figure 2.1") +
  mapTheme()

#just the buffers

buffer <- filter(MBTABuffers, Legend=="Unioned Buffer")

The study was done by selecting census tracts based on the “Select by Centroids” method as the dataset for the MBTA stops was point based, and studying the range of geographies serviced by transit was best represented by the central location of the census tract features.

#selecting the TOD tracts by centroid

selectCentroids <-
  rbind(
    st_centroid(tracts16)[buffer,] %>%
  st_drop_geometry() %>%
  left_join(., dplyr::select(tracts16, GEOID), by = "GEOID") %>%
  st_sf() %>%
  mutate(Selection_Type = "Select by Centroids"),
  st_centroid(tracts20)[buffer,] %>%
  st_drop_geometry() %>%
  left_join(., dplyr::select(tracts16, GEOID), by = "GEOID") %>%
  st_sf() %>%
  mutate(Selection_Type = "Select by Centroids"))

ggplot() +
  geom_sf(data=selectCentroids, aes()) +
  geom_sf(data=clippedMBTA, show.legend = "point") +
  labs(title = "Selected TOD Tracts", caption = "Figure 2.2") +
  mapTheme()

Comparing TOD vs non-TOD Indicators

This section compares various socio-economic indicators between TOD and non-TOD areas. This involves calculating indicators related to population, median income, median rent, percentage of income spent on rent, and the number of residents employed in the business, arts, and science sector for both types of areas. The code segment generates visualizations using ggplot for each indicator, providing a comparative analysis between TOD and non-TOD areas over time. A majority of the following visualization have been defined using 5 classes of variables, defined as a “quintile break”.

#comparing TOD vs non TOD indicators 

allTracts.group <- 
  rbind(
    st_centroid(allTracts)[buffer,] %>%
      st_drop_geometry() %>%
      left_join(allTracts) %>%
      st_sf() %>%
      mutate(TOD = "TOD"),
    st_centroid(allTracts)[buffer, op = st_disjoint] %>%
      st_drop_geometry() %>%
      left_join(allTracts) %>%
      st_sf() %>%
      mutate(TOD = "Non-TOD")) %>%
  mutate(MedRent.inf = ifelse(year == "2016", MedRent * 1.10, MedRent)) 

Total Population

The entire city of Boston has witnessed a slow but steady decline in population between the years of 2016 and 2020. The same change is also witnessed within the TOD districts. However, the change within the TOD districts seems to be more pronounced, with numerous census tracts moving to lower quintiles within these years. To understand the cause and effect of this decline, it is important to understand other indicators such as income and rent.

#plotting total pop

ggplot()+
  geom_sf(data = allTracts.group, aes(fill = q5(TotalPop)), color="transparent")+
   scale_fill_manual(values = palette5,
                    labels = c("0 - 2040", "2040 - 2780", "2780 - 3655", "3655 - 4810", "4810 - 9620"),
                    name = "Popluation\n(Quintile Breaks)") + mapTheme() +
  facet_wrap(~year)+
  geom_sf(data = allTracts.group %>%
            filter(TOD == "TOD") %>%
            st_union(),
          color = "red",
          fill = "transparent",
          linewidth = 0.8)+
  labs(
    title = "Total Population, 2016-2020",
    subtitle = "Boston MBTA, TOD vs non TOD tracts",
    caption = "Figure 2.3, Data: US Census Bureau, ACS 5-year estimates",
    fill = "Total Population")

Median Income

The median income within the TOD districts appears to have increased between 2016 - 2020. a large number of census tracts across the city, and specifically within the TOD districts appear to have jumped to a higher quintile break.

Combined with the decrease in population density, we can infer that while certain medium to high income residents may have been able to stay in the city, lower income residents could have been forced to move due to unaffordability. But to draw this conclusion, we must look at the rent and affordability statistics.

#plotting med inc
ggplot()+
  geom_sf(data = allTracts.group, aes(fill = q5(MedInc)), color="transparent")+
  scale_fill_manual(values = palette5,
                    labels = qBr(allTracts.group, "MedInc"), 
                    name = "Median Income\n(Quintile Breaks)") + mapTheme() +
  facet_wrap(~year)+
  geom_sf(data = allTracts.group %>%
            filter(TOD == "TOD") %>%
            st_union(),
          color = "red",
          fill = "transparent", linewidth = 0.8)+
  labs(
    title = "Median Income in 2020 adjusted Dollars, 2016-2020",
    subtitle = "Boston MBTA, TOD vs non TOD tracts",
    caption = "Figure 2.4, Data: US Census Bureau, ACS 5-year estimates",
    fill = "Median Income")

Median Rent

Median rent has witnessed a significant increase within the TOD districts. This reflects the growing demand for housing in proximity to transit hubs. This upward trend in rental prices underscores the changing dynamics of urban development in these areas. However, the increase in rent seems to be consistent with changes across the city. Most, if not all census tracts seems to have jumped up a quintile.

However, it can also be a reason for the declining populations in the transit rich areas, with low income residents moving out due to affordability issues. It is difficult to make these conclusions without taking a more comprehensive look at the different factors affecting these changes. A deeper spatial analysis, looking into the factors and their correlations would make a more compelling case.

#plotting med rent
ggplot()+
  geom_sf(data = allTracts.group, aes(fill = q5(MedRent)), color="transparent")+
  scale_fill_manual(values = palette5,
                    labels = qBr(allTracts.group, "MedRent"),
                    name = "Median Rent\n(Quintile Breaks)") + mapTheme() +
  facet_wrap(~year)+
  geom_sf(data = allTracts.group %>%
            filter(TOD == "TOD") %>%
            st_union(),
          color = "red",
          fill = "transparent",linewidth = 0.8)+
    
  labs(
    title = "Median Rent in 2020 adjusted Dollars, 2016-2020",
    subtitle = "Boston MBTA, TOD vs non TOD tracts",
    caption = "Figure 2.5, Data: US Census Bureau, ACS 5-year estimates",
    fill = "Median Rent")

Percentage of Income Spent on Rent

The percentage of income spent on rent is the gross rent of each household, expressed as a fraction of the household income. This is a good indicator of affordability, with rent burdened and severely rent burdened populations being defined as households that spend more than 30% and 50% of their incomes on rent, respectively.

It is hard to make a meaningful conclusion looking at this map as the quintiles make it hard to distinguish changes in each individual census tract.

#plotting pct income spent on rent
ggplot()+
  geom_sf(data = allTracts.group, aes(fill = q5(IncSpentOnRentPCt)), color="transparent")+
  scale_fill_manual(values = palette5,
labels = ((qBr(allTracts.group, "IncSpentOnRentPCt", rnd=FALSE))),
                    name = "Percentage\n(Quintile Breaks)") + 
  mapTheme() +
  facet_wrap(~year)+
  geom_sf(data = allTracts.group %>%
            filter(TOD == "TOD") %>%
            st_union(),
          color = "red",
          fill = "transparent", linewidth = 0.8)+
    
  labs(title = "Percent of Income Spent on Rent: Quintiles", subtitle = "Boston MBTA, TOD vs non TOD tracts", caption = "Figure 2.6, ACS 5-Year") 

To fix this problem, we can adjust the breaks in the map so that we can see a more defined picture of the rent burden in the city of Boston. By adjusting these breaks to color code all the rent burdened tracts, we can see how this indicator is different within and outside of the census tract boundaries. Most tracts in Boston are experiencing some level or rent burden, with the small exception of tracts in the downtown area, within the TOD tracts. This can be explained due to the higher income levels of residents living in the area. However, this is not the norm. As we move further away from the city center we can see how the rent burden drastically increases, in both 2016 and 2020. The lack of affordable housing in Boston, particularly in proximity to transit is an issue.

breaks <- c(0, 15, 20, 25, 30, 100)  
labels <- c("0-15 %", "16-20 %", "21-25 %", "26-30 %", "31+ %") 

ggplot(allTracts.group) +
  geom_sf(data = allTracts) +
  geom_sf(aes(fill = cut(IncSpentOnRentPCt, breaks = breaks, labels = labels))) +
  geom_sf(data = allTracts.group %>%
            filter(TOD == "TOD") %>%
            st_union(),
          color = "red",
          fill = "transparent", linewidth = 0.8) + 
  scale_fill_manual(values = palette5,  
    name = "Rent Burdened",
    breaks = labels) +
  labs(title = "Percent of Income Spent on Rent", subtitle = "Boston MBTA, TOD vs non TOD tracts", caption = "Figure 2.7, ACS 5-Year") +
  facet_wrap(~year) +
  mapTheme() 

Residents employed in Business, Arts or Sciences

In these maps we can clearly see a concentration of individuals working in business, arts, and sciences living in the Central Business District (CBD) or Transit-Oriented Development (TOD).

Proximity to the workplace for creative/tech-based professions within the CBD or accessible TOD areas significantly reduces commute times for professionals, explaining this concentration.

#plotting BusArtSciences

breaks <- c(0, 32500, 65000, 97500, 130000, 188250)  
labels <- c("0 - 32,500", "32,500 - 65,000", "65,000 - 97,500", "97,500 - 13,000", "13,000+") 

ggplot(allTracts.group) +
  geom_sf(data = allTracts) +
  geom_sf(aes(fill = cut(BusArtsScience, breaks = breaks, labels = labels))) +
  geom_sf(data = allTracts.group %>%
            filter(TOD == "TOD") %>%
            st_union(),
          color = "red",
          fill = "transparent", linewidth = 0.8) + 
  scale_fill_manual(values = palette5,  
    name = "Number of Residents",
    breaks = labels) +
  labs(title = "Residents Employed in the Business, Arts and Science Sector", subtitle = "Boston MBTA, TOD vs non TOD tracts", caption = "Figure 2.8, ACS 5-Year") +
  facet_wrap(~year) +
  mapTheme() 

Tabulating the Data

This figure tabulates the summarized data for various indicators, broken down by year and TOD status. It computes summary statistics (e.g., mean values) for population, rent, income, business, arts, sciences employment, and the percentage of income spent on rent. Based on the data, we can see that:

  1. The population has witnessed very little change (decline) over the 2016 - 2020. for all variables.

  2. The gap in Median Income has widened over the years. Average income in both TOD and non-TOD areas increased substantially from 2016 to 2020, with TOD areas having higher income levels in both years.

  3. Average rent prices increased in both TOD and non-TOD areas from 2016 to 2020, with TOD areas consistently having higher rent values, indicating a willingness from residents to live in transit rich neighborhoods.

  4. The percentage of income spent on rent decreased in TOD areas from 2016 to 2020, indicating improved affordability, while it increased slightly in non-TOD areas.

  5. The number of Business, Arts and Science employees increased by nearly 20% within the TOD districts. The downtown clearly has an effect on this trend.

# tables 

allTracts.Summary <- 
  st_drop_geometry(allTracts.group) %>% #best to go non spatial here because we're just making a table
  group_by(year, TOD) %>%
  summarize(Population = mean(TotalPop, na.rm = T),
            Rent = mean(MedRent, na.rm = T),
            Income = mean(MedInc, na.rm = T),
            Bus_Art_Sciences = mean(BusArtsScience, na.rm = T),
            Percent_Inc_on_Rent = mean(IncSpentOnRentPCt, na.rm = T))

allTracts.Summary %>%
  unite(year.TOD, year, TOD, sep = ": ", remove = T) %>%
  gather(Variable, Value, -year.TOD) %>%
  mutate(Value = round(Value, 2)) %>%
  spread(year.TOD, Value) %>%
  kable(., col.names = c("Mean Variables","non-TOD","TOD","non-TOD","TOD"), align="lrrrr") %>%
  kable_styling() %>%
  footnote(general_title = "\n",
           general = "Table 2.1")%>% 
      add_header_above(., header = c(" "=1, "2016" = 2, "2020" = 2))
2016
2020
Mean Variables non-TOD TOD non-TOD TOD
Bus_Art_Sciences 56847.32 56306.43 66755.11 72593.21
Income 60561.86 63027.75 78208.02 84099.83
Percent_Inc_on_Rent 32.16 31.50 32.65 30.16
Population 3661.81 3389.58 3588.64 2865.01
Rent 1134.73 1340.18 1434.84 1731.78

Table 2.1

Plotting Graphs

The final section of the code involves creating grouped bar graphs to visualize the differences in indicators across time and space (TOD vs. non-TOD). These charts further validate the inferences illustrated by the previous chart.

#grouped bar graphs

allTracts.Summary %>%
  gather(Variable, Value, -year, -TOD) %>%
  ggplot(aes(year, Value, fill = TOD)) +
    geom_bar(stat = "identity", position = "dodge") +
    facet_wrap(~Variable, scales = "free", ncol=3) +
    scale_fill_manual(values = c("#bae4bc", "#0868ac")) +
    labs(title = "Indicator differences across time and space") +
    theme(legend.position="top")+
  labs(x=NULL, y=NULL) +
    theme(panel.spacing = unit(1, "lines")) + 
    plotTheme()

Discussing Spatial Biases

Spatial biases wield a substantial influence on metrics like rent concerning their relationship with transit accessibility. These biases can originate from several sources, with human error constituting a notable concern. During the data collection and analysis phases, inaccuracies may emerge due to misclassifications of geographic locations and inconsistent or incomplete data recording. These errors, while unintended, can substantially distort the resulting metrics, making it essential to implement rigorous data quality control measures. Furthermore, the presence of spatial autocorrelation, where nearby areas exhibit similar characteristics, can also introduce biases. This spatial autocorrelation can be a consequence of unmodeled spatial processes, leading to erroneous assumptions of independence in statistical analyses. Additionally, data analysis must be conducted with an acute awareness of the presence of uncontrolled variables and unaccounted data issues, such as the margin of error inherent in census data or addressing missing values (NAs). Failing to address these facets can introduce unintended biases and uncertainties into the analysis, potentially undermining the reliability of conclusions drawn from spatial assessments. Thus, meticulous data validation, rigorous cleaning procedures, and the comprehensive consideration of various influential factors are vital steps to mitigate spatial biases in analyses of this nature.

The Downtown Effect

For many of the trends observed, they are not solely contingent on transit accessibility. They are influenced by a multifaceted web of factors, including neighborhood amenities, housing policies, and socioeconomic disparities. Overlooking the significance of Boston’s Central Business District (CBD), a thriving hub of employment and economic activity, can lead to an inherent upward skew in rent rates near this area.

While transit accessibility is pivotal to TOD, it should be viewed within the broader context of Boston’s urban dynamics. The CBD’s significance as an employment and economic center underscores the need for strategic planning that promotes balanced growth, affordability, and equitable access to transportation options.

More Data Analysis

This section extends the preceding data analysis on Transit-Oriented Development. It incorporates graduated symbol maps and graphs depicting the relationship between rent and distance from transit.

Graduated Symbol Maps

The following visualizations are a proportional display of rent and populations of census tracts intersecting the half mile buffers of transit stops.

buffers_stops <- filter(MBTABuffers, Legend=="Buffer")

buffers_stops$ID <- seq_along(buffers_stops$geometry) 

intersected_buffer <- selectCentroids %>% 
  st_intersection(buffers_stops, selectCentroids)

total_stops <- intersected_buffer %>%
  st_drop_geometry() %>%
  group_by(ID, GEOID, year) %>%
  summarise(pop = sum(TotalPop), rent = mean(MedRent, na.rm = TRUE))

labels_n <- clippedMBTA %>%
  select(GEOID, geometry) %>%
  left_join(total_stops,
            by = "GEOID") 

Population within 1/2 mile

Here, in contrast to the “sum” of census tract populations surrounding the transit stations, the study makes use of the average populations of surrounding census tracts. This was done so that the analysis offers a more nuanced and representative perspective. Mean values take into account the distribution of data points, providing an average that reflects the central tendency. As each census tract intersects multiple buffers, the sum total of the populations was reaching 5-digit numbers for each transit stop, giving a misleading representation of the population within the city.

The first observable difference in the 2016 and 2020 is the loss of data - many of the transit stops are missing from the 2020 maps. This can be a result of an erraneous data join, considering the shape of census tracts changed between those years as a result of fluctuating populations. Part of the data loss is also a result of missing data from census.

Despite these errors, we can see a difference in 2020, with a decline in population, most distinctly observed in the CBD/downtown area. We can see a high concentration of residents both at the center and southern part of the city, likely due to a concentration of jobs and universities.

ggplot() +
  geom_sf(data = tracts20, fill = "transparent") +  
  geom_sf(data = tracts16, fill = "transparent") +  
  geom_sf(data = labels_n %>%
             filter(!is.na(year)),  
          aes(fill = pop, size= pop),
          shape = 21, 
          alpha = 0.2) + 
  scale_size_continuous(range = c(0.5, 4), name = "Average Population") +
  scale_fill_gradientn(colors = hcl.colors(5, "viridis", rev = TRUE, alpha = 0.9), name = "")  +
  labs(size = "Point Size") +
   labs(title = "Average Population within half-mile of MBTA Stops", subtitle = "Proportional Symbol Map", caption = "Figure 4.1, ACS 5-Year") +
  facet_wrap(~year) +
  mapTheme()

Rent within 1/2 mile

The rent maps show similar inconsistencies in data across the two years. The downtown and Back Bay areas (located at the most transit rich regions of the map) have consistently remained the most desirable and expensive areas throughout. The rent is lowest in areas in and around Roxbury, making it a rare affordable yet transit rich neighborhood. The presence of universities also lowers the cost of rent especially in South Boston.

ggplot() +
  geom_sf(data = tracts20, fill = "transparent") +   
  geom_sf(data = tracts16, fill = "transparent") +  
  geom_sf(data = labels_n%>%
             filter(!is.na(year)), 
          aes(fill = rent, size= rent),
          shape = 21, 
          alpha = 0.2) + 
  scale_size_continuous(range = c(0.5, 4), name = "Average Rent") +
  scale_fill_gradientn(colors = hcl.colors(5, "viridis", rev = TRUE, alpha = 0.9), name = "") +
  labs(size = "Point Size") +
  labs(title = "Average Rent within half-mile of MBTA Stops", subtitle = "Proportional Symbol Map", caption = "Figure 4.2, ACS 5-Year") +
  facet_wrap(~year) +
  mapTheme()

Rent as a function of distance from the transit stops

This is a valuable metric as it reveals how housing costs change with proximity to public transportation. It informs accessibility, transportation cost savings, environmental impact, and equity considerations, aiding urban planning and policy decisions. It empowers individuals to make informed housing choices and helps developers identify investment opportunities. Nevertheless, it should be considered alongside other factors like amenities and job accessibility, and its impact may vary by location and transit quality.

MBTA_MRB <- multipleRingBuffer(st_union(clippedMBTA),
                                maxDistance = 34320,
                                interval =  2640)

# Your ggplot code
ggplot() +
  geom_sf(data = MBTA_MRB, aes(color = distance), fill = "transparent", linewidth = 0.5, alpha = 0.1 ) +
  geom_sf(data = clippedMBTA, size = 1) +
  geom_sf(data = st_union(tracts16), fill = NA, linewidth = 0.7) +
  labs(title = "Half mile buffers") +
  scale_color_viridis(name = "Distance\n(feet)") +
  mapTheme()

tracts20.rings <- tracts20 %>% 
  select(GEOID, year) %>% 
  st_centroid() %>% 
  st_join(MBTA_MRB, join = st_intersects) %>%
  st_drop_geometry() %>%
  left_join(dplyr::select(tracts20, GEOID, MedRent, year), 
            by=c("GEOID"="GEOID", "year"="year")) %>%
  st_sf() %>%
  mutate(distance = distance / 5280) 

tracts20.rings.summary <- st_drop_geometry(tracts20.rings) %>%
    group_by(distance, year) %>%
    summarize(Mean_Rent = mean(MedRent, na.rm=T))

tracts16.rings <- tracts16 %>% 
  select(GEOID, year) %>% 
  st_centroid() %>% 
  st_join(MBTA_MRB, join = st_intersects) %>%
  st_drop_geometry() %>%
  left_join(dplyr::select(tracts16, GEOID, MedRent, year), 
            by=c("GEOID"="GEOID", "year"="year")) %>%
  st_sf() %>%
  mutate(distance = distance / 5280) 

tracts16.rings.summary <- st_drop_geometry(tracts16.rings) %>%
    group_by(distance, year) %>%
    summarize(Mean_Rent = mean(MedRent, na.rm=T))


summary_bind <- rbind((tracts16.rings.summary%>%
        filter(!is.na(Mean_Rent) & !is.nan(Mean_Rent))), 
       tracts20.rings.summary%>%
        filter(!is.na(Mean_Rent) & !is.nan(Mean_Rent))
)

The first obvious conclusion is that rent is significantly higher in the year 2020 than in 2016. Further, the decrease in rent as one moves away from transit stops can be attributed to several factors. Firstly, properties located closer to transit stops are more convenient for commuters, reducing the need for private transportation and saving on commuting costs. This increased accessibility and reduced transportation expenses make these areas more desirable, leading to higher demand and, consequently, higher rents.

ggplot(summary_bind,
       aes(distance, Mean_Rent, colour=year)) +
       scale_colour_manual(values = palette5, name = "Year") +
       geom_point(size=3) + 
       geom_line(size=2) + 
    labs(
    title = "Half mile buffers",
    x = "Distance in Miles",  # Change the X-axis label
    y = "Rent in Dollars"   # Change the Y-axis label
  ) +
       plotTheme()

In contrast, as one moves further away from transit stops, the convenience of access to public transportation diminishes. As a result, the demand for properties in these areas decreases, which puts downward pressure on rent prices. Additionally, properties farther from transit hubs may offer larger spaces or different amenities that can offset the inconvenience of a longer commute, further contributing to the decline in rent prices as we move away from transit stops. These combined factors create a rent gradient with transit proximity at its core.

Policy Recommendations

Based on this report, the following policy broad recommendations can be made:

  1. Affordable Housing: Given the rise in rent and increasing rent burden, policies should focus on the development of affordable housing options near transit hubs. Affordable housing initiatives can help retain a diverse population and promote transit use.

  2. Transit Accessibility: Continue investments in improving transit infrastructure and accessibility to ensure that residents can easily access public transportation. Enhancements can include expanding transit networks, improving station facilities, and increasing service frequency.

  3. Data Monitoring: Establish a comprehensive data monitoring system to regularly assess changes in population, income, and rent in TOD districts. This data-driven approach will enable policymakers to make timely adjustments to housing and transportation policies.

Boston’s Transit-Oriented Development presents both opportunities and challenges. While it offers the potential for sustainable urban growth and reduced car dependency, it also requires careful planning and policies to address issues of housing affordability and equitable development. By implementing the recommended policies and closely monitoring demographic and economic changes, Boston can create vibrant and inclusive neighborhoods around its transit network.

LS0tDQp0aXRsZTogIlRyYW5zaXQgT3JpZW50ZWQgRGV2ZWxvcG1lbnQ6IEFuYWx5emluZyBCb3N0b24ncyBSYXBpZCBUcmFuc2l0Ig0Kc3VidGl0bGU6ICJNVVNBIDUwOCwgQXNzaWdubWVudCAyIg0KYXV0aG9yOiAiU2FtcmlkZGhpIEtoYXJlLCBVbml2ZXJzaXR5IG9mIFBlbm5zeWx2YW5pYSINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IGNlcnVsZWFuIA0KLS0tDQoNCiMgSW50cm9kdWN0aW9uDQoNCkJvc3RvbiBpcyBvbmUgb2YgdGhlIGxhcmdlc3QgY2l0aWVzIGluIHRoZSBVbml0ZWQgU3RhdGVzIGFuZCBpcyBhbiBpbnRlZ3JhbCBwYXJ0IG9mIHRoZSBOb3J0aGVhc3QgRWNvbm9taWMgQ29ycmlkb3IuIE92ZXIgdGltZSwgaXQgaGFzIGJlY29tZSBhIGNlbnRlciBmb3IgY3VsdHVyZSBhbmQgaW5ub3ZhdGlvbi4gVGhlIGhpZ2ggZGVuc2l0eSBvZiBoaWdoZXIgZWR1Y2F0aW9uIGluc3RpdHV0ZXMgbGlrZSBIYXJ2YXJkIGFuZCBNSVQgaGF2ZSBicm91Z2h0IEJvc3RvbiB0byB0aGUgZm9yZWZyb250IG9mIHNjaWVudGlmaWMgcmVzZWFyY2guIEJvc3RvbiBpcyBhbHNvIG1ham9yIGh1YiBmb3IgdmFyaW91cyBpbmR1c3RyaWVzLCBpbmNsdWRpbmcgZmluYW5jZSwgdGVjaG5vbG9neSwgaGVhbHRoY2FyZSwgYW5kIGJpb3RlY2hub2xvZ3kuICAgIA0KDQo8aW1nIHNyYz0iRDovRmFsbF8yMDIzL1BQQS9Bc3NpZ25tZW50Mi9pbWFnZXMvTUJUQV9SYXBpZFRyYW5zaXRfMTFfMjAyMl8yMDAwcHguanBnIiB3aWR0aD0iMzAwIiBhbGlnbj0icmlnaHQiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG1hcmdpbjogMCAxMHB4OyIvPg0KDQpCb3N0b24ncyByYXBpZCB0cmFuc2l0IHN5c3RlbSwga25vd24gYXMgdGhlICJULCIgaXMgYSB2aXRhbCBjb21wb25lbnQgb2YgdGhlIGNpdHkncyBwdWJsaWMgdHJhbnNwb3J0YXRpb24gbmV0d29yay4gT3BlcmF0ZWQgYnkgdGhlIE1hc3NhY2h1c2V0dHMgQmF5IFRyYW5zcG9ydGF0aW9uIEF1dGhvcml0eSAoTUJUQSksIGl0IGNvbnNpc3RzIG9mIGZvdXIgc3Vid2F5IGxpbmVzIChSZWQsIE9yYW5nZSwgQmx1ZSwgYW5kIEdyZWVuKSwgc2VydmluZyBib3RoIHRoZSBjaXR5IGFuZCBzdXJyb3VuZGluZyBzdWJ1cmJzLiBUcmFuc2l0LU9yaWVudGVkIERldmVsb3BtZW50IChUT0QpIGluIEJvc3RvbiwgbGlrZSBtYW55IG90aGVyIGNpdGllcywgaXMgYWltZWQgYXQgY3JlYXRpbmcgdmlicmFudCwgbWl4ZWQtdXNlIGNvbW11bml0aWVzIGFyb3VuZCB0aGUgY2l0eSdzIGV4dGVuc2l2ZSBwdWJsaWMgdHJhbnNpdCBuZXR3b3JrLCBwYXJ0aWN1bGFybHkgdGhlIHJhcGlkIHRyYW5zaXQgc3Vid2F5IGxpbmVzLiANCg0KDQoNCg0KVGhpcyBwb2xpY3kgYnJpZWYgYXR0ZW1wdHMgdG8gYWRkcmVzcyB0aGUgdmFsdWUgYW5kIGNpdHplbiBzZXR0bGVtZW50IHBhdHRlcm5zIG9mIHRyYW5zaXQtcmljaCBuZWlnaGJvcmhvb2RzLCBjb21wYXJpbmcgdGhlbSB0byB0aGUgY2l0eSBhdCBsYXJnZS4gSXQgbWFrZXMgZXh0ZW5zaXZlIHVzZSBvZiB0aGUgQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleSBkYXRhLCBhbG9uZyB3aXRoIHB1YmxpY2FsbHkgYXZhaWxhYmxlIGluZm9ybWF0aW9uIG9uIHRoZSBNQlRBJ3MgcmFwaWQgdHJhbnNpdCByb3V0ZXMgYW5kIHN0b3BzLiANCg0KVGhpcyBjb2RlIGlzIGJ1aWx0IHVwb24gdGhlIGNsYXNzd29yayBkaXNjdXNzZWQgW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9tYWZpY2htYW4vbXVzYV81MDgwXzIwMjMvdHJlZS9tYWluKS4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQogIGtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgICBlY2hvID0gVFJVRSwNCiAgICB3YXJuaW5nID0gRkFMU0UsDQogICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgIG91dC53aWR0aCA9ICcxMDAlJywNCiAgICBmaWcucmV0aW5hID0zDQogICkNCmBgYA0KDQojIyBSIFNldHVwIGFuZCBJbnN0YWxsaW5nIFBhY2thZ2VzDQoNClRoaXMgY29kZSBjaHVuayBoYW5kbGVzIHRoZSBlc3NlbnRpYWwgdGFza3Mgb2YgbG9hZGluZyBuZWNlc3NhcnkgcGFja2FnZXMsIGNvbmZpZ3VyaW5nIHRoZSBDZW5zdXMgQVBJIGtleSwgZGVmaW5pbmcgY2xhc3MgZnVuY3Rpb25zLCBzcGVjaWZ5aW5nIGEgY29sb3IgcGFsZXR0ZSwgYW5kIG1hbmFnaW5nIGdsb2JhbCBlbnZpcm9ubWVudCBzZXR0aW5ncy4NCg0KYGBge3Igc2V0dXBfcGFja2FnZXMsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkodGlkeWNlbnN1cykNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeShwcmV0dHlkb2MpDQpsaWJyYXJ5KHN0cmluZ3IpDQoNCm9wdGlvbnMoc2NpcGVuPTk5OSkNCm9wdGlvbnModGlncmlzX2NsYXNzID0gInNmIikNCg0KI3RoZXNlIGFyZSBmdW5jdGlvbnMgZGV2ZWxvcGVkIGZvciB0aGlzIGNsYXNzLCBzbyBpdCB0YWtlcyB5b3UgZXNwZWNpYWxseSB0byB0aGUgYm9vayB0byBnZXQgdGhvc2UNCg0Kc291cmNlKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vdXJiYW5TcGF0aWFsL1B1YmxpYy1Qb2xpY3ktQW5hbHl0aWNzLUxhbmRpbmcvbWFzdGVyL2Z1bmN0aW9ucy5yIikNCg0KcGFsZXR0ZTUgPC0gYygiI2ZkZTcyNSIsIiM1ZWM5NjIiLCIjMjE5MThjIiwiIzNiNTI4YiIsIiM0NDAxNTQiKQ0KDQpjZW5zdXNfYXBpX2tleSgnYmYyZDUwNzY1MWI1YTYyMWRiYWRkNDQ1MzNmYjRmM2RlYWFiMjZiZicsIG92ZXJ3cml0ZSA9IFRSVUUpDQoNCmBgYA0KDQoNCiMjIExvYWRpbmcgQ2Vuc3VzIERhdGENCg0KVGhlIHllYXJzIGNob3NlbiBmb3IgYW5hbHlzaXMgYXJlIDIwMTYgYW5kIDIwMjAuIE92ZXIgdGhpcyBwZXJpb2QsIEJvc3RvbidzIFJhcGlkIFRyYW5zaXQgd2VudCB0aHJvdWdoIHNpZ25pZmljYW50IGNoYW5nZXMsIHRoZSBtb3N0IG5vdGFibGUgb25lIGJlaW5nIHRoZSBwbGFubmluZyBhbmQgY29uc3RydWN0aW9uIG9mIHRoZSBleHRlbmRlZCBHcmVlbiBMaW5lLiBCeSBleHRlbmRpbmcgdGhlIEdyZWVuIExpbmUgaW50byBoaXN0b3JpY2FsbHkgdW5kZXItc2VydmVkIGFyZWFzIGxpa2UgU29tZXJ2aWxsZSBhbmQgTWVkZm9yZCwgaXQgaGFzIG5vdCBvbmx5IGVhc2VkIGNvbW11dGluZyBmb3IgcmVzaWRlbnRzIGJ1dCBhbHNvIGJvbHN0ZXJlZCByaWRlcnNoaXAgYWNyb3NzIHRoZSBlbnRpcmUgbGluZSwgcmVkdWNpbmcgY29uZ2VzdGlvbiBhbmQgb2ZmZXJpbmcgbW9yZSBhY2Nlc3NpYmxlIHRyYW5zaXQgb3B0aW9ucyB0byB0aG91c2FuZHMgb2YgZGFpbHkgY29tbXV0ZXJzLg0KDQoNCmBgYHtyIGxvYWRfdmFyaWFibGVzLCBjYWNoZT1UUlVFfQ0KDQphY3NfdmFyaWFibGVfbGlzdC4yMDIwIDwtIGxvYWRfdmFyaWFibGVzKDIwMjAsICN5ZWFyDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJhY3M1IiwgI2ZpdmUgeWVhciBBQ1MgZXN0aW1hdGVzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlID0gVFJVRSkNCg0KYWNzX3ZhcmlhYmxlX2xpc3QuMjAxNiA8LSBsb2FkX3ZhcmlhYmxlcygyMDE2LCAjeWVhcg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYWNzNSIsICNmaXZlIHllYXIgQUNTIGVzdGltYXRlcw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IFRSVUUpDQpgYGANCg0KVGhlIHZhcmlhYmxlcyBjaG9zZW4gZm9yIHRoaXMgYW5hbHlzaXMgaW5jbHVkZTogDQoNCjEuIFRvdGFsIFBvcHVsYXRpb24gaW4gT2NjdXBpZWQgSG91c2luZyBVbml0czogVGhpcyB2YXJpYWJsZSBpcyByZWxhdGVkIHRvIFRPRCBiZWNhdXNlIHRoZSBzdWNjZXNzIG9mIHRyYW5zaXQtb3JpZW50ZWQgZGV2ZWxvcG1lbnQgb2Z0ZW4gZGVwZW5kcyBvbiBwb3B1bGF0aW9uIGRlbnNpdHkuIEhpZ2hlciBwb3B1bGF0aW9uIGRlbnNpdHkgdHlwaWNhbGx5IGxlYWRzIHRvIG1vcmUgZGVtYW5kIGZvciBwdWJsaWMgdHJhbnNwb3J0YXRpb24gc2VydmljZXMuIFRPRCBhcmVhcyBhcmUgZGVzaWduZWQgdG8gYWNjb21tb2RhdGUgYSBsYXJnZXIgcG9wdWxhdGlvbiB3aXRoaW4gYSBjb21wYWN0LCB3YWxrYWJsZSBuZWlnaGJvcmhvb2QsIHdoaWNoIGNhbiByZWR1Y2UgcmVsaWFuY2Ugb24gcGVyc29uYWwgdmVoaWNsZXMgYW5kIHByb21vdGUgdGhlIHVzZSBvZiBwdWJsaWMgdHJhbnNpdC4NCg0KMi4gTWVkaWFuIGhvdXNlaG9sZCBJbmNvbWUgaW4gdGhlIHBhc3QgMTIgbW9udGhzOiBJbmNvbWUgbGV2ZWxzIGFyZSByZWxldmFudCB0byBUT0QgYmVjYXVzZSB0aGV5IGluZmx1ZW5jZSBib3RoIHRoZSBkZW1hbmQgZm9yIHB1YmxpYyB0cmFuc3BvcnRhdGlvbiBhbmQgdGhlIHR5cGVzIG9mIGFtZW5pdGllcyBhbmQgc2VydmljZXMgdGhhdCBjYW4gYmUgc3VwcG9ydGVkIGluIGEgVE9EIGFyZWEuIExvdy0gdG8gbW9kZXJhdGUtaW5jb21lIGhvdXNlaG9sZHMgbWF5IHJlbHkgbW9yZSBvbiBwdWJsaWMgdHJhbnNpdCwgbWFraW5nIGl0IGNydWNpYWwgdG8gaGF2ZSBhZmZvcmRhYmxlIHRyYW5zcG9ydGF0aW9uIG9wdGlvbnMgaW4gVE9EIGRldmVsb3BtZW50cy4gQWRkaXRpb25hbGx5LCBoaWdoZXItaW5jb21lIHJlc2lkZW50cyBjYW4gc3VwcG9ydCBhIHJhbmdlIG9mIGJ1c2luZXNzZXMgYW5kIHNlcnZpY2VzIHdpdGhpbiB0aGUgVE9EIGFyZWEuDQoNCjMuIE1lZGlhbiBSZW50IG92ZXIgdGhlIHBhc3QgMTIgbW9udGhzOiBSZW50IGxldmVscyBhcmUgaW1wb3J0YW50IGluIFRPRCBhcmVhcyBiZWNhdXNlIHRoZXkgY2FuIGFmZmVjdCBob3VzaW5nIGFmZm9yZGFiaWxpdHksIHdoaWNoIGlzIGEgY3JpdGljYWwgZmFjdG9yIGZvciBhdHRyYWN0aW5nIHJlc2lkZW50cyB3aG8gd2FudCB0byBsaXZlIG5lYXIgdHJhbnNpdCBodWJzLiBBZmZvcmRhYmxlIGhvdXNpbmcgb3B0aW9ucyBpbiBUT0RzIGNhbiBlbmNvdXJhZ2UgcGVvcGxlIHRvIGNob29zZSBwdWJsaWMgdHJhbnNwb3J0YXRpb24gb3ZlciBwcml2YXRlIGNhcnMsIGFzIHRoZXkgY2FuIGxpdmUgY2xvc2VyIHRvIHdvcmsgYW5kIGFtZW5pdGllcyB3aXRob3V0IGEgbG9uZyBjb21tdXRlLg0KDQo0LiBOdW1iZXIgb2YgUGVvcGxlIGVtcGxveWVkIGluIHRoZSBCdXNpbmVzcywgQXJ0cyBvciBTY2llbmNlcyBzZWN0b3I6IEJvc3RvbiBpcyBrbm93biBhcyBhIGh1YiBmb3IgdGhlc2UgaW5kdXN0cmllcywgd2l0aCBudW1lcm91cyBwcmVzdGlnaW91cyB1bml2ZXJzaXRpZXMgYW5kIGN1bHR1cmFsIGluc3RpdHV0aW9ucyBsb2NhdGVkIGluIHRoZSBhcmVhLiBJZiByZXNpZGVudHMgZW5nYWdlZCBpbiB0aGlzIHNlY3RvciBhcmUgY2hvb3NpbmcgdG8gbG9jYXRlZCB3aXRoaW4gVE9EIGRpc3RyaWN0cywgaXQncyBpbmRpY2F0aXZlIG9mIHdoYXQgZnV0dXJlIHJvdXRlcyBhbmQgYWNjZXNzIHNob3VsZCBiZSBwcmlvcml0aXplZC4gIA0KDQo1LiBNZWRpYW4gZ3Jvc3MgcmVudCBhcyBhIHBlcmNlbnRhZ2Ugb2YgaG91c2Vob2xkIGluY29tZTogVGhpcyB2YXJpYWJsZSByZWxhdGVzIHRvIGhvdXNpbmcgYWZmb3JkYWJpbGl0eSwgd2hpY2ggaXMgYSBrZXkgYXNwZWN0IG9mIFRPRC4gVGhlIHBlcmNlbnRhZ2Ugb2YgaG91c2Vob2xkIGluY29tZSBzcGVudCBvbiByZW50IGNhbiBpbmRpY2F0ZSB3aGV0aGVyIGhvdXNpbmcgaXMgYWZmb3JkYWJsZSBmb3IgdGhlIGxvY2FsIHBvcHVsYXRpb24uIExvd2VyIHJlbnQgYXMgYSBwZXJjZW50YWdlIG9mIGluY29tZSBzdWdnZXN0cyBncmVhdGVyIGFmZm9yZGFiaWxpdHksIHdoaWNoIGNhbiBhdHRyYWN0IGEgZGl2ZXJzZSBtaXggb2YgcmVzaWRlbnRzLCBpbmNsdWRpbmcgdGhvc2Ugd2hvIHJlbHkgb24gcHVibGljIHRyYW5zaXQuIEl0IGFsc28gcmVsYXRlcyB0byB0aGUgcHJldmlvdXMgaW5kaWNhdG9yLCBhcyB0aGUgQnVzaW5lc3MsIEFydHMgYW5kIFNjaWVuY2VzIHNlY3RvciB0eXBpY2FsbHkgaW52b2x2ZXMgaGlnaCBwYXlpbmcgam9icyBmb3IgcmVzaWRlbnRzLiANCg0KYGBge3IgY2h1bmt5LCByZXN1bHRzPSdoaWRlJ30NCg0KdHJhY3RzMTYgPC0gDQogIGdldF9hY3MoZ2VvZ3JhcGh5ID0gInRyYWN0IiwgDQogICAgICAgICAgdmFyaWFibGVzID0gYygiQjI1MDI2XzAwMUUiLCNwb3ANCiAgICAgICAgICAgICAgICAgICAgICAgICJCMTkwMTNfMDAxRSIsICNtZWQgaW5jDQogICAgICAgICAgICAgICAgICAgICAgICAiQjI1MDU4XzAwMUUiLCAjcmVudA0KICAgICAgICAgICAgICAgICAgICAgICAgIkIyNDAxMV8wMDJFIiwgI3BwbCBpbiBidXNpbmVzcyBzY2llbmNlIGFydHMgDQogICAgICAgICAgICAgICAgICAgICAgICAiQjI1MDcxXzAwMUUiKSwgI2luYyBhcyAlIG9mIHJlbnQNCiAgICAgICAgICB5ZWFyPTIwMTYsIA0KICAgICAgICAgIHN0YXRlID0gMjUsDQogICAgICAgICAgY291bnR5PTAyNSwgI3VzaW5nIHRoZSBib3N0b24vc3VmZm9sayBjb3VudHkgRklQUyBjb2RlDQogICAgICAgICAgZ2VvbWV0cnk9VFJVRSwgb3V0cHV0PSJ3aWRlIiklPiUNCiAgc3RfdHJhbnNmb3JtKCdFU1JJOjEwMjcyOCcpICU+JQ0KICByZW5hbWUoVG90YWxQb3AgPSBCMjUwMjZfMDAxRSwgDQogICAgICAgICBNZWRJbmMgPSBCMTkwMTNfMDAxRSwNCiAgICAgICAgIE1lZFJlbnQgPSBCMjUwNThfMDAxRSwgDQogICAgICAgICBCdXNBcnRzU2NpZW5jZSA9IEIyNDAxMV8wMDJFLA0KICAgICAgICAgSW5jU3BlbnRPblJlbnRQQ3QgPSBCMjUwNzFfMDAxRSklPiUNCiAgZHBseXI6OnNlbGVjdCgtTkFNRSwgLWVuZHNfd2l0aCgiTSIpKSAlPiUNCiAgbXV0YXRlKHllYXIgPSAiMjAxNiIpIA0KDQojIDIwMjANCg0KdHJhY3RzMjAgPC0gDQogICBnZXRfYWNzKGdlb2dyYXBoeSA9ICJ0cmFjdCIsIA0KICAgICAgICAgIHZhcmlhYmxlcyA9IGMoIkIyNTAyNl8wMDFFIiwjcG9wDQogICAgICAgICAgICAgICAgICAgICAgICAiQjE5MDEzXzAwMUUiLCAjbWVkIGluYw0KICAgICAgICAgICAgICAgICAgICAgICAgIkIyNTA1OF8wMDFFIiwgI3JlbnQNCiAgICAgICAgICAgICAgICAgICAgICAgICJCMjQwMTFfMDAyRSIsICNwcGwgaW4gYnVzaW5lc3Mgc2NpZW5jZSBhcnRzIA0KICAgICAgICAgICAgICAgICAgICAgICAgIkIyNTA3MV8wMDFFIiksICNpbmMgYXMgJSBvZiByZW50DQogICAgICAgICAgeWVhcj0yMDIwLCANCiAgICAgICAgICBzdGF0ZSA9IDI1LA0KICAgICAgICAgIGNvdW50eT0wMjUsICN1c2luZyB0aGUgYm9zdG9uL3N1ZmZvbGsgY291bnR5IEZJUFMgY29kZQ0KICAgICAgICAgIGdlb21ldHJ5PVRSVUUsIG91dHB1dD0id2lkZSIpJT4lDQogIHN0X3RyYW5zZm9ybSgnRVNSSToxMDI3MjgnKSAlPiUNCiAgcmVuYW1lKFRvdGFsUG9wID0gQjI1MDI2XzAwMUUsIA0KICAgICAgICAgTWVkSW5jID0gQjE5MDEzXzAwMUUsDQogICAgICAgICBNZWRSZW50ID0gQjI1MDU4XzAwMUUsIA0KICAgICAgICAgQnVzQXJ0c1NjaWVuY2UgPSBCMjQwMTFfMDAyRSwNCiAgICAgICAgIEluY1NwZW50T25SZW50UEN0ID0gQjI1MDcxXzAwMUUpJT4lDQogIGRwbHlyOjpzZWxlY3QoLU5BTUUsIC1lbmRzX3dpdGgoIk0iKSkgJT4lDQogIG11dGF0ZSh5ZWFyID0gIjIwMjAiKSANCg0KDQojYmluZGluZyB0aGUgZGF0YQ0KYWxsVHJhY3RzIDwtIHJiaW5kKHRyYWN0czE2LHRyYWN0czIwKQ0KDQpgYGANCg0KIyMgTG9hZGluZyBNQlRBIFN0b3BzDQoNCk1CVEEgUmFwaWQgVHJhbnNpdCBkYXRhIHJlcHJlc2VudHMgdGhlIHN0YXRpb24gc3RvcHMgb24gdGhlIGZpdmUgc3Vid2F5LCBzdHJlZXRjYXIvdHJvbGxleSBhbmQgU2lsdmVyIExpbmUgYnVzICJUIiBsaW5lcyAoQmx1ZSwgR3JlZW4sIE9yYW5nZSwgUmVkIGFuZCBTaWx2ZXIpIGluIHRoZSBNYXNzYWNodXNldHRzIEJheSBUcmFuc3BvcnRhdGlvbiBBdXRob3JpdHkncyByYXBpZCB0cmFuc2l0IHJhaWwgbmV0d29yay4gVGhlIGxheWVycyB3ZXJlIGRldmVsb3BlZCBieSB0aGUgQ2VudHJhbCBUcmFuc3BvcnRhdGlvbiBQbGFubmluZyBTdGFmZiAoQ1RQUyksIHdpdGggYWRkaXRpb25hbCBlZGl0aW5nIGJ5IE1hc3NHSVMgYmFzZWQgb24gY3VycmVudCBhZXJpYWwgaW1hZ2VyeSBhbmQgaW5mb3JtYXRpb24gZnJvbSBbdGhpcyBzb3VyY2UuXShodHRwczovL2h1Yi5hcmNnaXMuY29tL21hcHMvbWFzc2dpczo6bWJ0YS1yYXBpZC10cmFuc2l0L2Fib3V0KQ0KDQpgYGB7ciBuYW1lLCByZXN1bHRzID0gJ2hpZGUnfQ0KDQp1cmwgPC0iaHR0cHM6Ly9naXMubWFzc2RvdC5zdGF0ZS5tYS51cy9hcmNnaXMvcmVzdC9zZXJ2aWNlcy9NdWx0aW1vZGFsL0dURlNfU3lzdGVtd2lkZS9NYXBTZXJ2ZXIvMC9xdWVyeT93aGVyZT0xJTNEMSZvdXRGaWVsZHM9KiZvdXRTUj00MzI2JmY9anNvbiINCg0KTUJUQVN0b3BzIDwtIHN0X3JlYWQodXJsKSAlPiUgDQogIHN0X3RyYW5zZm9ybShzdF9jcnModHJhY3RzMTYpKSAgDQpgYGANCg0KYGBge3J9DQoNCiNjbGlwcGluZyB0byB0cmFjdHMgYm91bmRhcmllcyANCg0KY2xpcHBlZE1CVEEgPC0gDQogIHN0X2ludGVyc2VjdGlvbihNQlRBU3RvcHMsIHRyYWN0czE2KQ0KDQojcGxvdHRpbmcNCg0KZ2dwbG90KCkgKyANCiAgZ2VvbV9zZihkYXRhPXN0X3VuaW9uKHRyYWN0czE2KSkgKw0KICBnZW9tX3NmKGRhdGE9Y2xpcHBlZE1CVEEpICsNCiAgbGFicyh0aXRsZT0iTUJUQSBTdG9wcyIsIA0KICAgICAgIHN1YnRpdGxlPSJCb3N0b24sIE1BIiwgDQogICAgICAgY2FwdGlvbj0iRmlndXJlIDEuMSIpICsNCiAgbWFwVGhlbWUoKQ0KYGBgDQoNCiMgRGF0YSBBbmFseXNpcw0KDQpUaGlzIHNlY3Rpb24gaXMgZm9jdXNlZCBvbiBleGFtaW5pbmcgdmFyaW91cyBzb2Npby1lY29ub21pYyBpbmRpY2F0b3JzIGluIHJlbGF0aW9uIHRvIHRyYW5zaXQtb3JpZW50ZWQgZGV2ZWxvcG1lbnQgKFRPRCkgYW5kIG5vbi1UT0QgYXJlYXMgd2l0aGluIHRoZSBjb250ZXh0IG9mIEJvc3RvbidzIHB1YmxpYyB0cmFuc2l0IHN5c3RlbS4gSXQgbWFrZXMgdXNlIG9mIHRoZSBgZ2dwbG90YCBhbmQgYGthYmxlYCBwYWNrYWdlcyBmb3IgZWZmZWN0aXZlIHZpc3VhbGl6YXRpb25zLiANCg0KIyMgQ3JlYXRpbmcgQnVmZmVycyBhbmQgU2VsZWN0aW5nIENlbnN1cyBUcmFjdHMNCg0KSGFsZiBtaWxlIGJ1ZmZlcnMgd2VyZSBjcmVhdGVkIGFzIGhhbGYgYSBtaWxlIHRyYW5zbGF0ZXMgdG8gYSByb3VnaGx5IDEwIG1pbnV0ZSB3YWxrc2hlZCwgbWFraW5nIGl0IHJlYXNvbmFibGUgdG8gYXNzdW1lIHRoYXQgdGhlIGFyZWEgd2l0aGluIHRob3NlIGJ1ZmZlcnMgYXJlIHRoZSBtb3N0IHNpZ25pZmljYW50bHkgYWZmZWN0ZWQgYnkgdGhlIHByZXNlbmNlIG9mIHRyYW5zaXQuDQoNCmBgYHtyfQ0KI2NyZWF0aW5nIGEgYnVmZmVyDQoNCk1CVEFCdWZmZXJzIDwtIA0KICByYmluZCgNCiAgICBzdF9idWZmZXIoY2xpcHBlZE1CVEEsIDI2NDApICU+JSAjdGhlIG51bWJlciBhdCB0aGUgZW5kIGlzIGluIGZlZXQsIGJlY2F1c2Ugb3VyIENSUyBpcyBpbiBmZWV0DQogICAgICBtdXRhdGUoTGVnZW5kID0gIkJ1ZmZlciIpICU+JQ0KICAgICAgZHBseXI6OnNlbGVjdChMZWdlbmQpLA0KICAgIHN0X3VuaW9uKHN0X2J1ZmZlcihjbGlwcGVkTUJUQSwgMjY0MCkpICU+JQ0KICAgICAgc3Rfc2YoKSAlPiUNCiAgICAgIG11dGF0ZShMZWdlbmQgPSAiVW5pb25lZCBCdWZmZXIiKSkgI2FsbCBzdCBmdW5jdGlvbnMgd2lsbCBiZSBzcGF0aWFsIHJlbGF0ZWQgc3R1ZmYNCg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGE9TUJUQUJ1ZmZlcnMpICsNCiAgZ2VvbV9zZihkYXRhPWNsaXBwZWRNQlRBLCBzaG93LmxlZ2VuZCA9ICJwb2ludCIpICsNCiAgZmFjZXRfd3JhcCh+TGVnZW5kKSArIA0KICBsYWJzKGNhcHRpb24gPSAiRmlndXJlIDIuMSIpICsNCiAgbWFwVGhlbWUoKQ0KDQojanVzdCB0aGUgYnVmZmVycw0KDQpidWZmZXIgPC0gZmlsdGVyKE1CVEFCdWZmZXJzLCBMZWdlbmQ9PSJVbmlvbmVkIEJ1ZmZlciIpDQoNCg0KYGBgDQoNClRoZSBzdHVkeSB3YXMgZG9uZSBieSBzZWxlY3RpbmcgY2Vuc3VzIHRyYWN0cyBiYXNlZCBvbiB0aGUgIlNlbGVjdCBieSBDZW50cm9pZHMiIG1ldGhvZCBhcyB0aGUgZGF0YXNldCBmb3IgdGhlIE1CVEEgc3RvcHMgd2FzIHBvaW50IGJhc2VkLCBhbmQgc3R1ZHlpbmcgdGhlIHJhbmdlIG9mIGdlb2dyYXBoaWVzIHNlcnZpY2VkIGJ5IHRyYW5zaXQgd2FzIGJlc3QgcmVwcmVzZW50ZWQgYnkgdGhlIGNlbnRyYWwgbG9jYXRpb24gb2YgdGhlIGNlbnN1cyB0cmFjdCBmZWF0dXJlcy4gDQoNCmBgYHtyfQ0KDQojc2VsZWN0aW5nIHRoZSBUT0QgdHJhY3RzIGJ5IGNlbnRyb2lkDQoNCnNlbGVjdENlbnRyb2lkcyA8LQ0KICByYmluZCgNCiAgICBzdF9jZW50cm9pZCh0cmFjdHMxNilbYnVmZmVyLF0gJT4lDQogIHN0X2Ryb3BfZ2VvbWV0cnkoKSAlPiUNCiAgbGVmdF9qb2luKC4sIGRwbHlyOjpzZWxlY3QodHJhY3RzMTYsIEdFT0lEKSwgYnkgPSAiR0VPSUQiKSAlPiUNCiAgc3Rfc2YoKSAlPiUNCiAgbXV0YXRlKFNlbGVjdGlvbl9UeXBlID0gIlNlbGVjdCBieSBDZW50cm9pZHMiKSwNCiAgc3RfY2VudHJvaWQodHJhY3RzMjApW2J1ZmZlcixdICU+JQ0KICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lDQogIGxlZnRfam9pbiguLCBkcGx5cjo6c2VsZWN0KHRyYWN0czE2LCBHRU9JRCksIGJ5ID0gIkdFT0lEIikgJT4lDQogIHN0X3NmKCkgJT4lDQogIG11dGF0ZShTZWxlY3Rpb25fVHlwZSA9ICJTZWxlY3QgYnkgQ2VudHJvaWRzIikpDQoNCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhPXNlbGVjdENlbnRyb2lkcywgYWVzKCkpICsNCiAgZ2VvbV9zZihkYXRhPWNsaXBwZWRNQlRBLCBzaG93LmxlZ2VuZCA9ICJwb2ludCIpICsNCiAgbGFicyh0aXRsZSA9ICJTZWxlY3RlZCBUT0QgVHJhY3RzIiwgY2FwdGlvbiA9ICJGaWd1cmUgMi4yIikgKw0KICBtYXBUaGVtZSgpDQoNCmBgYA0KDQojIyBDb21wYXJpbmcgVE9EIHZzIG5vbi1UT0QgSW5kaWNhdG9ycyANCg0KVGhpcyBzZWN0aW9uIGNvbXBhcmVzIHZhcmlvdXMgc29jaW8tZWNvbm9taWMgaW5kaWNhdG9ycyBiZXR3ZWVuIFRPRCBhbmQgbm9uLVRPRCBhcmVhcy4gVGhpcyBpbnZvbHZlcyBjYWxjdWxhdGluZyBpbmRpY2F0b3JzIHJlbGF0ZWQgdG8gcG9wdWxhdGlvbiwgbWVkaWFuIGluY29tZSwgbWVkaWFuIHJlbnQsIHBlcmNlbnRhZ2Ugb2YgaW5jb21lIHNwZW50IG9uIHJlbnQsIGFuZCB0aGUgbnVtYmVyIG9mIHJlc2lkZW50cyBlbXBsb3llZCBpbiB0aGUgYnVzaW5lc3MsIGFydHMsIGFuZCBzY2llbmNlIHNlY3RvciBmb3IgYm90aCB0eXBlcyBvZiBhcmVhcy4gVGhlIGNvZGUgc2VnbWVudCBnZW5lcmF0ZXMgdmlzdWFsaXphdGlvbnMgdXNpbmcgZ2dwbG90IGZvciBlYWNoIGluZGljYXRvciwgcHJvdmlkaW5nIGEgY29tcGFyYXRpdmUgYW5hbHlzaXMgYmV0d2VlbiBUT0QgYW5kIG5vbi1UT0QgYXJlYXMgb3ZlciB0aW1lLiBBIG1ham9yaXR5IG9mIHRoZSBmb2xsb3dpbmcgdmlzdWFsaXphdGlvbiBoYXZlIGJlZW4gZGVmaW5lZCB1c2luZyA1IGNsYXNzZXMgb2YgdmFyaWFibGVzLCBkZWZpbmVkIGFzIGEgInF1aW50aWxlIGJyZWFrIi4gIA0KDQoNCmBgYHtyfQ0KDQojY29tcGFyaW5nIFRPRCB2cyBub24gVE9EIGluZGljYXRvcnMgDQoNCmFsbFRyYWN0cy5ncm91cCA8LSANCiAgcmJpbmQoDQogICAgc3RfY2VudHJvaWQoYWxsVHJhY3RzKVtidWZmZXIsXSAlPiUNCiAgICAgIHN0X2Ryb3BfZ2VvbWV0cnkoKSAlPiUNCiAgICAgIGxlZnRfam9pbihhbGxUcmFjdHMpICU+JQ0KICAgICAgc3Rfc2YoKSAlPiUNCiAgICAgIG11dGF0ZShUT0QgPSAiVE9EIiksDQogICAgc3RfY2VudHJvaWQoYWxsVHJhY3RzKVtidWZmZXIsIG9wID0gc3RfZGlzam9pbnRdICU+JQ0KICAgICAgc3RfZHJvcF9nZW9tZXRyeSgpICU+JQ0KICAgICAgbGVmdF9qb2luKGFsbFRyYWN0cykgJT4lDQogICAgICBzdF9zZigpICU+JQ0KICAgICAgbXV0YXRlKFRPRCA9ICJOb24tVE9EIikpICU+JQ0KICBtdXRhdGUoTWVkUmVudC5pbmYgPSBpZmVsc2UoeWVhciA9PSAiMjAxNiIsIE1lZFJlbnQgKiAxLjEwLCBNZWRSZW50KSkgDQoNCmBgYA0KDQoNCiMjIyBUb3RhbCBQb3B1bGF0aW9uDQoNCg0KVGhlIGVudGlyZSBjaXR5IG9mIEJvc3RvbiBoYXMgd2l0bmVzc2VkIGEgc2xvdyBidXQgc3RlYWR5IGRlY2xpbmUgaW4gcG9wdWxhdGlvbiBiZXR3ZWVuIHRoZSB5ZWFycyBvZiAyMDE2IGFuZCAyMDIwLiBUaGUgc2FtZSBjaGFuZ2UgaXMgYWxzbyB3aXRuZXNzZWQgd2l0aGluIHRoZSBUT0QgZGlzdHJpY3RzLiBIb3dldmVyLCB0aGUgY2hhbmdlIHdpdGhpbiB0aGUgVE9EIGRpc3RyaWN0cyBzZWVtcyB0byBiZSBtb3JlIHByb25vdW5jZWQsIHdpdGggbnVtZXJvdXMgY2Vuc3VzIHRyYWN0cyBtb3ZpbmcgdG8gbG93ZXIgcXVpbnRpbGVzIHdpdGhpbiB0aGVzZSB5ZWFycy4gVG8gdW5kZXJzdGFuZCB0aGUgY2F1c2UgYW5kIGVmZmVjdCBvZiB0aGlzIGRlY2xpbmUsIGl0IGlzIGltcG9ydGFudCB0byB1bmRlcnN0YW5kIG90aGVyIGluZGljYXRvcnMgc3VjaCBhcyBpbmNvbWUgYW5kIHJlbnQuICANCg0KYGBge3J9DQojcGxvdHRpbmcgdG90YWwgcG9wDQoNCmdncGxvdCgpKw0KICBnZW9tX3NmKGRhdGEgPSBhbGxUcmFjdHMuZ3JvdXAsIGFlcyhmaWxsID0gcTUoVG90YWxQb3ApKSwgY29sb3I9InRyYW5zcGFyZW50IikrDQogICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlNSwNCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiMCAtIDIwNDAiLCAiMjA0MCAtIDI3ODAiLCAiMjc4MCAtIDM2NTUiLCAiMzY1NSAtIDQ4MTAiLCAiNDgxMCAtIDk2MjAiKSwNCiAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJQb3BsdWF0aW9uXG4oUXVpbnRpbGUgQnJlYWtzKSIpICsgbWFwVGhlbWUoKSArDQogIGZhY2V0X3dyYXAofnllYXIpKw0KICBnZW9tX3NmKGRhdGEgPSBhbGxUcmFjdHMuZ3JvdXAgJT4lDQogICAgICAgICAgICBmaWx0ZXIoVE9EID09ICJUT0QiKSAlPiUNCiAgICAgICAgICAgIHN0X3VuaW9uKCksDQogICAgICAgICAgY29sb3IgPSAicmVkIiwNCiAgICAgICAgICBmaWxsID0gInRyYW5zcGFyZW50IiwNCiAgICAgICAgICBsaW5ld2lkdGggPSAwLjgpKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlRvdGFsIFBvcHVsYXRpb24sIDIwMTYtMjAyMCIsDQogICAgc3VidGl0bGUgPSAiQm9zdG9uIE1CVEEsIFRPRCB2cyBub24gVE9EIHRyYWN0cyIsDQogICAgY2FwdGlvbiA9ICJGaWd1cmUgMi4zLCBEYXRhOiBVUyBDZW5zdXMgQnVyZWF1LCBBQ1MgNS15ZWFyIGVzdGltYXRlcyIsDQogICAgZmlsbCA9ICJUb3RhbCBQb3B1bGF0aW9uIikNCiAgDQpgYGANCg0KIyMjIE1lZGlhbiBJbmNvbWUNCg0KVGhlIG1lZGlhbiBpbmNvbWUgd2l0aGluIHRoZSBUT0QgZGlzdHJpY3RzIGFwcGVhcnMgdG8gaGF2ZSBpbmNyZWFzZWQgYmV0d2VlbiAyMDE2IC0gMjAyMC4gYSBsYXJnZSBudW1iZXIgb2YgY2Vuc3VzIHRyYWN0cyBhY3Jvc3MgdGhlIGNpdHksIGFuZCBzcGVjaWZpY2FsbHkgd2l0aGluIHRoZSBUT0QgZGlzdHJpY3RzIGFwcGVhciB0byBoYXZlIGp1bXBlZCB0byBhIGhpZ2hlciBxdWludGlsZSBicmVhay4gDQoNCkNvbWJpbmVkIHdpdGggdGhlIGRlY3JlYXNlIGluIHBvcHVsYXRpb24gZGVuc2l0eSwgd2UgY2FuIGluZmVyIHRoYXQgd2hpbGUgY2VydGFpbiBtZWRpdW0gdG8gaGlnaCBpbmNvbWUgcmVzaWRlbnRzIG1heSBoYXZlIGJlZW4gYWJsZSB0byBzdGF5IGluIHRoZSBjaXR5LCBsb3dlciBpbmNvbWUgcmVzaWRlbnRzIGNvdWxkIGhhdmUgYmVlbiBmb3JjZWQgdG8gbW92ZSBkdWUgdG8gdW5hZmZvcmRhYmlsaXR5LiBCdXQgdG8gZHJhdyB0aGlzIGNvbmNsdXNpb24sIHdlIG11c3QgbG9vayBhdCB0aGUgcmVudCBhbmQgYWZmb3JkYWJpbGl0eSBzdGF0aXN0aWNzLiAgIA0KDQpgYGB7cn0NCiNwbG90dGluZyBtZWQgaW5jDQpnZ3Bsb3QoKSsNCiAgZ2VvbV9zZihkYXRhID0gYWxsVHJhY3RzLmdyb3VwLCBhZXMoZmlsbCA9IHE1KE1lZEluYykpLCBjb2xvcj0idHJhbnNwYXJlbnQiKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZTUsDQogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHFCcihhbGxUcmFjdHMuZ3JvdXAsICJNZWRJbmMiKSwgDQogICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiTWVkaWFuIEluY29tZVxuKFF1aW50aWxlIEJyZWFrcykiKSArIG1hcFRoZW1lKCkgKw0KICBmYWNldF93cmFwKH55ZWFyKSsNCiAgZ2VvbV9zZihkYXRhID0gYWxsVHJhY3RzLmdyb3VwICU+JQ0KICAgICAgICAgICAgZmlsdGVyKFRPRCA9PSAiVE9EIikgJT4lDQogICAgICAgICAgICBzdF91bmlvbigpLA0KICAgICAgICAgIGNvbG9yID0gInJlZCIsDQogICAgICAgICAgZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGxpbmV3aWR0aCA9IDAuOCkrDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTWVkaWFuIEluY29tZSBpbiAyMDIwIGFkanVzdGVkIERvbGxhcnMsIDIwMTYtMjAyMCIsDQogICAgc3VidGl0bGUgPSAiQm9zdG9uIE1CVEEsIFRPRCB2cyBub24gVE9EIHRyYWN0cyIsDQogICAgY2FwdGlvbiA9ICJGaWd1cmUgMi40LCBEYXRhOiBVUyBDZW5zdXMgQnVyZWF1LCBBQ1MgNS15ZWFyIGVzdGltYXRlcyIsDQogICAgZmlsbCA9ICJNZWRpYW4gSW5jb21lIikNCiAgDQpgYGANCg0KIyMjIE1lZGlhbiBSZW50DQoNCk1lZGlhbiByZW50IGhhcyB3aXRuZXNzZWQgYSBzaWduaWZpY2FudCBpbmNyZWFzZSB3aXRoaW4gdGhlIFRPRCBkaXN0cmljdHMuIFRoaXMgcmVmbGVjdHMgdGhlIGdyb3dpbmcgZGVtYW5kIGZvciBob3VzaW5nIGluIHByb3hpbWl0eSB0byB0cmFuc2l0IGh1YnMuIFRoaXMgdXB3YXJkIHRyZW5kIGluIHJlbnRhbCBwcmljZXMgdW5kZXJzY29yZXMgdGhlIGNoYW5naW5nIGR5bmFtaWNzIG9mIHVyYmFuIGRldmVsb3BtZW50IGluIHRoZXNlIGFyZWFzLiBIb3dldmVyLCB0aGUgaW5jcmVhc2UgaW4gcmVudCBzZWVtcyB0byBiZSBjb25zaXN0ZW50IHdpdGggY2hhbmdlcyBhY3Jvc3MgdGhlIGNpdHkuIE1vc3QsIGlmIG5vdCBhbGwgY2Vuc3VzIHRyYWN0cyBzZWVtcyB0byBoYXZlIGp1bXBlZCB1cCBhIHF1aW50aWxlLg0KDQpIb3dldmVyLCBpdCBjYW4gYWxzbyBiZSBhIHJlYXNvbiBmb3IgdGhlIGRlY2xpbmluZyBwb3B1bGF0aW9ucyBpbiB0aGUgdHJhbnNpdCByaWNoIGFyZWFzLCB3aXRoIGxvdyBpbmNvbWUgcmVzaWRlbnRzIG1vdmluZyBvdXQgZHVlIHRvIGFmZm9yZGFiaWxpdHkgaXNzdWVzLiBJdCBpcyBkaWZmaWN1bHQgdG8gbWFrZSB0aGVzZSBjb25jbHVzaW9ucyB3aXRob3V0IHRha2luZyBhIG1vcmUgY29tcHJlaGVuc2l2ZSBsb29rIGF0IHRoZSBkaWZmZXJlbnQgZmFjdG9ycyBhZmZlY3RpbmcgdGhlc2UgY2hhbmdlcy4gQSBkZWVwZXIgc3BhdGlhbCBhbmFseXNpcywgbG9va2luZyBpbnRvIHRoZSBmYWN0b3JzIGFuZCB0aGVpciBjb3JyZWxhdGlvbnMgd291bGQgbWFrZSBhIG1vcmUgY29tcGVsbGluZyBjYXNlLiANCg0KYGBge3J9DQojcGxvdHRpbmcgbWVkIHJlbnQNCmdncGxvdCgpKw0KICBnZW9tX3NmKGRhdGEgPSBhbGxUcmFjdHMuZ3JvdXAsIGFlcyhmaWxsID0gcTUoTWVkUmVudCkpLCBjb2xvcj0idHJhbnNwYXJlbnQiKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZTUsDQogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHFCcihhbGxUcmFjdHMuZ3JvdXAsICJNZWRSZW50IiksDQogICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiTWVkaWFuIFJlbnRcbihRdWludGlsZSBCcmVha3MpIikgKyBtYXBUaGVtZSgpICsNCiAgZmFjZXRfd3JhcCh+eWVhcikrDQogIGdlb21fc2YoZGF0YSA9IGFsbFRyYWN0cy5ncm91cCAlPiUNCiAgICAgICAgICAgIGZpbHRlcihUT0QgPT0gIlRPRCIpICU+JQ0KICAgICAgICAgICAgc3RfdW5pb24oKSwNCiAgICAgICAgICBjb2xvciA9ICJyZWQiLA0KICAgICAgICAgIGZpbGwgPSAidHJhbnNwYXJlbnQiLGxpbmV3aWR0aCA9IDAuOCkrDQogICAgDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTWVkaWFuIFJlbnQgaW4gMjAyMCBhZGp1c3RlZCBEb2xsYXJzLCAyMDE2LTIwMjAiLA0KICAgIHN1YnRpdGxlID0gIkJvc3RvbiBNQlRBLCBUT0QgdnMgbm9uIFRPRCB0cmFjdHMiLA0KICAgIGNhcHRpb24gPSAiRmlndXJlIDIuNSwgRGF0YTogVVMgQ2Vuc3VzIEJ1cmVhdSwgQUNTIDUteWVhciBlc3RpbWF0ZXMiLA0KICAgIGZpbGwgPSAiTWVkaWFuIFJlbnQiKQ0KICANCmBgYA0KDQojIyMgUGVyY2VudGFnZSBvZiBJbmNvbWUgU3BlbnQgb24gUmVudA0KDQpUaGUgcGVyY2VudGFnZSBvZiBpbmNvbWUgc3BlbnQgb24gcmVudCBpcyB0aGUgZ3Jvc3MgcmVudCBvZiBlYWNoIGhvdXNlaG9sZCwgZXhwcmVzc2VkIGFzIGEgZnJhY3Rpb24gb2YgdGhlIGhvdXNlaG9sZCBpbmNvbWUuIFRoaXMgaXMgYSBnb29kIGluZGljYXRvciBvZiBhZmZvcmRhYmlsaXR5LCB3aXRoIHJlbnQgYnVyZGVuZWQgYW5kIHNldmVyZWx5IHJlbnQgYnVyZGVuZWQgcG9wdWxhdGlvbnMgYmVpbmcgZGVmaW5lZCBhcyBob3VzZWhvbGRzIHRoYXQgc3BlbmQgbW9yZSB0aGFuIDMwJSBhbmQgNTAlIG9mIHRoZWlyIGluY29tZXMgb24gcmVudCwgcmVzcGVjdGl2ZWx5LiANCg0KSXQgaXMgaGFyZCB0byBtYWtlIGEgbWVhbmluZ2Z1bCBjb25jbHVzaW9uIGxvb2tpbmcgYXQgdGhpcyBtYXAgYXMgdGhlIHF1aW50aWxlcyBtYWtlIGl0IGhhcmQgdG8gZGlzdGluZ3Vpc2ggY2hhbmdlcyBpbiBlYWNoIGluZGl2aWR1YWwgY2Vuc3VzIHRyYWN0LiANCg0KYGBge3J9DQojcGxvdHRpbmcgcGN0IGluY29tZSBzcGVudCBvbiByZW50DQpnZ3Bsb3QoKSsNCiAgZ2VvbV9zZihkYXRhID0gYWxsVHJhY3RzLmdyb3VwLCBhZXMoZmlsbCA9IHE1KEluY1NwZW50T25SZW50UEN0KSksIGNvbG9yPSJ0cmFuc3BhcmVudCIpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlNSwNCmxhYmVscyA9ICgocUJyKGFsbFRyYWN0cy5ncm91cCwgIkluY1NwZW50T25SZW50UEN0Iiwgcm5kPUZBTFNFKSkpLA0KICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlBlcmNlbnRhZ2VcbihRdWludGlsZSBCcmVha3MpIikgKyANCiAgbWFwVGhlbWUoKSArDQogIGZhY2V0X3dyYXAofnllYXIpKw0KICBnZW9tX3NmKGRhdGEgPSBhbGxUcmFjdHMuZ3JvdXAgJT4lDQogICAgICAgICAgICBmaWx0ZXIoVE9EID09ICJUT0QiKSAlPiUNCiAgICAgICAgICAgIHN0X3VuaW9uKCksDQogICAgICAgICAgY29sb3IgPSAicmVkIiwNCiAgICAgICAgICBmaWxsID0gInRyYW5zcGFyZW50IiwgbGluZXdpZHRoID0gMC44KSsNCiAgICANCiAgbGFicyh0aXRsZSA9ICJQZXJjZW50IG9mIEluY29tZSBTcGVudCBvbiBSZW50OiBRdWludGlsZXMiLCBzdWJ0aXRsZSA9ICJCb3N0b24gTUJUQSwgVE9EIHZzIG5vbiBUT0QgdHJhY3RzIiwgY2FwdGlvbiA9ICJGaWd1cmUgMi42LCBBQ1MgNS1ZZWFyIikgDQogIA0KYGBgDQoNClRvIGZpeCB0aGlzIHByb2JsZW0sIHdlIGNhbiBhZGp1c3QgdGhlIGJyZWFrcyBpbiB0aGUgbWFwIHNvIHRoYXQgd2UgY2FuIHNlZSBhIG1vcmUgZGVmaW5lZCBwaWN0dXJlIG9mIHRoZSByZW50IGJ1cmRlbiBpbiB0aGUgY2l0eSBvZiBCb3N0b24uIEJ5IGFkanVzdGluZyB0aGVzZSBicmVha3MgdG8gY29sb3IgY29kZSBhbGwgdGhlIHJlbnQgYnVyZGVuZWQgdHJhY3RzLCB3ZSBjYW4gc2VlIGhvdyB0aGlzIGluZGljYXRvciBpcyBkaWZmZXJlbnQgd2l0aGluIGFuZCBvdXRzaWRlIG9mIHRoZSBjZW5zdXMgdHJhY3QgYm91bmRhcmllcy4gTW9zdCB0cmFjdHMgaW4gQm9zdG9uIGFyZSBleHBlcmllbmNpbmcgc29tZSBsZXZlbCBvciByZW50IGJ1cmRlbiwgd2l0aCB0aGUgc21hbGwgZXhjZXB0aW9uIG9mIHRyYWN0cyBpbiB0aGUgZG93bnRvd24gYXJlYSwgd2l0aGluIHRoZSBUT0QgdHJhY3RzLiBUaGlzIGNhbiBiZSBleHBsYWluZWQgZHVlIHRvIHRoZSBoaWdoZXIgaW5jb21lIGxldmVscyBvZiByZXNpZGVudHMgbGl2aW5nIGluIHRoZSBhcmVhLiBIb3dldmVyLCB0aGlzIGlzIG5vdCB0aGUgbm9ybS4gQXMgd2UgbW92ZSBmdXJ0aGVyIGF3YXkgZnJvbSB0aGUgY2l0eSBjZW50ZXIgd2UgY2FuIHNlZSBob3cgdGhlIHJlbnQgYnVyZGVuIGRyYXN0aWNhbGx5IGluY3JlYXNlcywgaW4gYm90aCAyMDE2IGFuZCAyMDIwLiBUaGUgbGFjayBvZiBhZmZvcmRhYmxlIGhvdXNpbmcgaW4gQm9zdG9uLCBwYXJ0aWN1bGFybHkgaW4gcHJveGltaXR5IHRvIHRyYW5zaXQgaXMgYW4gaXNzdWUuDQoNCmBgYHtyIFJFTlQ6SU5DT01FfQ0KDQpicmVha3MgPC0gYygwLCAxNSwgMjAsIDI1LCAzMCwgMTAwKSAgDQpsYWJlbHMgPC0gYygiMC0xNSAlIiwgIjE2LTIwICUiLCAiMjEtMjUgJSIsICIyNi0zMCAlIiwgIjMxKyAlIikgDQoNCmdncGxvdChhbGxUcmFjdHMuZ3JvdXApICsNCiAgZ2VvbV9zZihkYXRhID0gYWxsVHJhY3RzKSArDQogIGdlb21fc2YoYWVzKGZpbGwgPSBjdXQoSW5jU3BlbnRPblJlbnRQQ3QsIGJyZWFrcyA9IGJyZWFrcywgbGFiZWxzID0gbGFiZWxzKSkpICsNCiAgZ2VvbV9zZihkYXRhID0gYWxsVHJhY3RzLmdyb3VwICU+JQ0KICAgICAgICAgICAgZmlsdGVyKFRPRCA9PSAiVE9EIikgJT4lDQogICAgICAgICAgICBzdF91bmlvbigpLA0KICAgICAgICAgIGNvbG9yID0gInJlZCIsDQogICAgICAgICAgZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGxpbmV3aWR0aCA9IDAuOCkgKyANCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZTUsICANCiAgICBuYW1lID0gIlJlbnQgQnVyZGVuZWQiLA0KICAgIGJyZWFrcyA9IGxhYmVscykgKw0KICBsYWJzKHRpdGxlID0gIlBlcmNlbnQgb2YgSW5jb21lIFNwZW50IG9uIFJlbnQiLCBzdWJ0aXRsZSA9ICJCb3N0b24gTUJUQSwgVE9EIHZzIG5vbiBUT0QgdHJhY3RzIiwgY2FwdGlvbiA9ICJGaWd1cmUgMi43LCBBQ1MgNS1ZZWFyIikgKw0KICBmYWNldF93cmFwKH55ZWFyKSArDQogIG1hcFRoZW1lKCkgDQoNCmBgYA0KDQojIyMgUmVzaWRlbnRzIGVtcGxveWVkIGluIEJ1c2luZXNzLCBBcnRzIG9yIFNjaWVuY2VzIA0KDQpJbiB0aGVzZSBtYXBzIHdlIGNhbiBjbGVhcmx5IHNlZSBhIGNvbmNlbnRyYXRpb24gb2YgaW5kaXZpZHVhbHMgd29ya2luZyBpbiBidXNpbmVzcywgYXJ0cywgYW5kIHNjaWVuY2VzIGxpdmluZyBpbiB0aGUgQ2VudHJhbCBCdXNpbmVzcyBEaXN0cmljdCAoQ0JEKSBvciBUcmFuc2l0LU9yaWVudGVkIERldmVsb3BtZW50IChUT0QpLiANCg0KUHJveGltaXR5IHRvIHRoZSB3b3JrcGxhY2UgZm9yIGNyZWF0aXZlL3RlY2gtYmFzZWQgcHJvZmVzc2lvbnMgd2l0aGluIHRoZSBDQkQgb3IgYWNjZXNzaWJsZSBUT0QgYXJlYXMgc2lnbmlmaWNhbnRseSByZWR1Y2VzIGNvbW11dGUgdGltZXMgZm9yIHByb2Zlc3Npb25hbHMsIGV4cGxhaW5pbmcgdGhpcyBjb25jZW50cmF0aW9uLiANCg0KYGBge3J9DQojcGxvdHRpbmcgQnVzQXJ0U2NpZW5jZXMNCg0KYnJlYWtzIDwtIGMoMCwgMzI1MDAsIDY1MDAwLCA5NzUwMCwgMTMwMDAwLCAxODgyNTApICANCmxhYmVscyA8LSBjKCIwIC0gMzIsNTAwIiwgIjMyLDUwMCAtIDY1LDAwMCIsICI2NSwwMDAgLSA5Nyw1MDAiLCAiOTcsNTAwIC0gMTMsMDAwIiwgIjEzLDAwMCsiKSANCg0KZ2dwbG90KGFsbFRyYWN0cy5ncm91cCkgKw0KICBnZW9tX3NmKGRhdGEgPSBhbGxUcmFjdHMpICsNCiAgZ2VvbV9zZihhZXMoZmlsbCA9IGN1dChCdXNBcnRzU2NpZW5jZSwgYnJlYWtzID0gYnJlYWtzLCBsYWJlbHMgPSBsYWJlbHMpKSkgKw0KICBnZW9tX3NmKGRhdGEgPSBhbGxUcmFjdHMuZ3JvdXAgJT4lDQogICAgICAgICAgICBmaWx0ZXIoVE9EID09ICJUT0QiKSAlPiUNCiAgICAgICAgICAgIHN0X3VuaW9uKCksDQogICAgICAgICAgY29sb3IgPSAicmVkIiwNCiAgICAgICAgICBmaWxsID0gInRyYW5zcGFyZW50IiwgbGluZXdpZHRoID0gMC44KSArIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlNSwgIA0KICAgIG5hbWUgPSAiTnVtYmVyIG9mIFJlc2lkZW50cyIsDQogICAgYnJlYWtzID0gbGFiZWxzKSArDQogIGxhYnModGl0bGUgPSAiUmVzaWRlbnRzIEVtcGxveWVkIGluIHRoZSBCdXNpbmVzcywgQXJ0cyBhbmQgU2NpZW5jZSBTZWN0b3IiLCBzdWJ0aXRsZSA9ICJCb3N0b24gTUJUQSwgVE9EIHZzIG5vbiBUT0QgdHJhY3RzIiwgY2FwdGlvbiA9ICJGaWd1cmUgMi44LCBBQ1MgNS1ZZWFyIikgKw0KICBmYWNldF93cmFwKH55ZWFyKSArDQogIG1hcFRoZW1lKCkgDQoNCmBgYA0KDQojIyBUYWJ1bGF0aW5nIHRoZSBEYXRhDQoNClRoaXMgZmlndXJlIHRhYnVsYXRlcyB0aGUgc3VtbWFyaXplZCBkYXRhIGZvciB2YXJpb3VzIGluZGljYXRvcnMsIGJyb2tlbiBkb3duIGJ5IHllYXIgYW5kIFRPRCBzdGF0dXMuIEl0IGNvbXB1dGVzIHN1bW1hcnkgc3RhdGlzdGljcyAoZS5nLiwgbWVhbiB2YWx1ZXMpIGZvciBwb3B1bGF0aW9uLCByZW50LCBpbmNvbWUsIGJ1c2luZXNzLCBhcnRzLCBzY2llbmNlcyBlbXBsb3ltZW50LCBhbmQgdGhlIHBlcmNlbnRhZ2Ugb2YgaW5jb21lIHNwZW50IG9uIHJlbnQuIEJhc2VkIG9uIHRoZSBkYXRhLCB3ZSBjYW4gc2VlIHRoYXQ6IA0KDQoxLiBUaGUgcG9wdWxhdGlvbiBoYXMgd2l0bmVzc2VkIHZlcnkgbGl0dGxlIGNoYW5nZSAoZGVjbGluZSkgb3ZlciB0aGUgMjAxNiAtIDIwMjAuIGZvciBhbGwgdmFyaWFibGVzLiANCg0KMi4gVGhlIGdhcCBpbiBNZWRpYW4gSW5jb21lIGhhcyB3aWRlbmVkIG92ZXIgdGhlIHllYXJzLiBBdmVyYWdlIGluY29tZSBpbiBib3RoIFRPRCBhbmQgbm9uLVRPRCBhcmVhcyBpbmNyZWFzZWQgc3Vic3RhbnRpYWxseSBmcm9tIDIwMTYgdG8gMjAyMCwgd2l0aCBUT0QgYXJlYXMgaGF2aW5nIGhpZ2hlciBpbmNvbWUgbGV2ZWxzIGluIGJvdGggeWVhcnMuDQoNCjMuIEF2ZXJhZ2UgcmVudCBwcmljZXMgaW5jcmVhc2VkIGluIGJvdGggVE9EIGFuZCBub24tVE9EIGFyZWFzIGZyb20gMjAxNiB0byAyMDIwLCB3aXRoIFRPRCBhcmVhcyBjb25zaXN0ZW50bHkgaGF2aW5nIGhpZ2hlciByZW50IHZhbHVlcywgaW5kaWNhdGluZyBhIHdpbGxpbmduZXNzIGZyb20gcmVzaWRlbnRzIHRvIGxpdmUgaW4gdHJhbnNpdCByaWNoIG5laWdoYm9yaG9vZHMuIA0KDQo0LiBUaGUgcGVyY2VudGFnZSBvZiBpbmNvbWUgc3BlbnQgb24gcmVudCBkZWNyZWFzZWQgaW4gVE9EIGFyZWFzIGZyb20gMjAxNiB0byAyMDIwLCBpbmRpY2F0aW5nIGltcHJvdmVkIGFmZm9yZGFiaWxpdHksIHdoaWxlIGl0IGluY3JlYXNlZCBzbGlnaHRseSBpbiBub24tVE9EIGFyZWFzLg0KDQo1LiBUaGUgbnVtYmVyIG9mIEJ1c2luZXNzLCBBcnRzIGFuZCBTY2llbmNlIGVtcGxveWVlcyBpbmNyZWFzZWQgYnkgbmVhcmx5IDIwJSB3aXRoaW4gdGhlIFRPRCBkaXN0cmljdHMuIFRoZSBkb3dudG93biBjbGVhcmx5IGhhcyBhbiBlZmZlY3Qgb24gdGhpcyB0cmVuZC4gDQoNCmBgYHtyfQ0KDQojIHRhYmxlcyANCg0KYWxsVHJhY3RzLlN1bW1hcnkgPC0gDQogIHN0X2Ryb3BfZ2VvbWV0cnkoYWxsVHJhY3RzLmdyb3VwKSAlPiUgI2Jlc3QgdG8gZ28gbm9uIHNwYXRpYWwgaGVyZSBiZWNhdXNlIHdlJ3JlIGp1c3QgbWFraW5nIGEgdGFibGUNCiAgZ3JvdXBfYnkoeWVhciwgVE9EKSAlPiUNCiAgc3VtbWFyaXplKFBvcHVsYXRpb24gPSBtZWFuKFRvdGFsUG9wLCBuYS5ybSA9IFQpLA0KICAgICAgICAgICAgUmVudCA9IG1lYW4oTWVkUmVudCwgbmEucm0gPSBUKSwNCiAgICAgICAgICAgIEluY29tZSA9IG1lYW4oTWVkSW5jLCBuYS5ybSA9IFQpLA0KICAgICAgICAgICAgQnVzX0FydF9TY2llbmNlcyA9IG1lYW4oQnVzQXJ0c1NjaWVuY2UsIG5hLnJtID0gVCksDQogICAgICAgICAgICBQZXJjZW50X0luY19vbl9SZW50ID0gbWVhbihJbmNTcGVudE9uUmVudFBDdCwgbmEucm0gPSBUKSkNCg0KYWxsVHJhY3RzLlN1bW1hcnkgJT4lDQogIHVuaXRlKHllYXIuVE9ELCB5ZWFyLCBUT0QsIHNlcCA9ICI6ICIsIHJlbW92ZSA9IFQpICU+JQ0KICBnYXRoZXIoVmFyaWFibGUsIFZhbHVlLCAteWVhci5UT0QpICU+JQ0KICBtdXRhdGUoVmFsdWUgPSByb3VuZChWYWx1ZSwgMikpICU+JQ0KICBzcHJlYWQoeWVhci5UT0QsIFZhbHVlKSAlPiUNCiAga2FibGUoLiwgY29sLm5hbWVzID0gYygiTWVhbiBWYXJpYWJsZXMiLCJub24tVE9EIiwiVE9EIiwibm9uLVRPRCIsIlRPRCIpLCBhbGlnbj0ibHJycnIiKSAlPiUNCiAga2FibGVfc3R5bGluZygpICU+JQ0KICBmb290bm90ZShnZW5lcmFsX3RpdGxlID0gIlxuIiwNCiAgICAgICAgICAgZ2VuZXJhbCA9ICJUYWJsZSAyLjEiKSU+JSANCiAgICAgIGFkZF9oZWFkZXJfYWJvdmUoLiwgaGVhZGVyID0gYygiICI9MSwgIjIwMTYiID0gMiwgIjIwMjAiID0gMikpDQpgYGANCiMjIFBsb3R0aW5nIEdyYXBocw0KDQpUaGUgZmluYWwgc2VjdGlvbiBvZiB0aGUgY29kZSBpbnZvbHZlcyBjcmVhdGluZyBncm91cGVkIGJhciBncmFwaHMgdG8gdmlzdWFsaXplIHRoZSBkaWZmZXJlbmNlcyBpbiBpbmRpY2F0b3JzIGFjcm9zcyB0aW1lIGFuZCBzcGFjZSAoVE9EIHZzLiBub24tVE9EKS4gVGhlc2UgY2hhcnRzIGZ1cnRoZXIgdmFsaWRhdGUgdGhlIGluZmVyZW5jZXMgaWxsdXN0cmF0ZWQgYnkgdGhlIHByZXZpb3VzIGNoYXJ0Lg0KDQpgYGB7cn0NCiNncm91cGVkIGJhciBncmFwaHMNCg0KYWxsVHJhY3RzLlN1bW1hcnkgJT4lDQogIGdhdGhlcihWYXJpYWJsZSwgVmFsdWUsIC15ZWFyLCAtVE9EKSAlPiUNCiAgZ2dwbG90KGFlcyh5ZWFyLCBWYWx1ZSwgZmlsbCA9IFRPRCkpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICAgZmFjZXRfd3JhcCh+VmFyaWFibGUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbD0zKSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2JhZTRiYyIsICIjMDg2OGFjIikpICsNCiAgICBsYWJzKHRpdGxlID0gIkluZGljYXRvciBkaWZmZXJlbmNlcyBhY3Jvc3MgdGltZSBhbmQgc3BhY2UiKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKSsNCiAgbGFicyh4PU5VTEwsIHk9TlVMTCkgKw0KICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcgPSB1bml0KDEsICJsaW5lcyIpKSArIA0KICAgIHBsb3RUaGVtZSgpDQpgYGANCg0KDQojIERpc2N1c3NpbmcgU3BhdGlhbCBCaWFzZXMNCg0KU3BhdGlhbCBiaWFzZXMgd2llbGQgYSBzdWJzdGFudGlhbCBpbmZsdWVuY2Ugb24gbWV0cmljcyBsaWtlIHJlbnQgY29uY2VybmluZyB0aGVpciByZWxhdGlvbnNoaXAgd2l0aCB0cmFuc2l0IGFjY2Vzc2liaWxpdHkuIFRoZXNlIGJpYXNlcyBjYW4gb3JpZ2luYXRlIGZyb20gc2V2ZXJhbCBzb3VyY2VzLCB3aXRoIGh1bWFuIGVycm9yIGNvbnN0aXR1dGluZyBhIG5vdGFibGUgY29uY2Vybi4gRHVyaW5nIHRoZSBkYXRhIGNvbGxlY3Rpb24gYW5kIGFuYWx5c2lzIHBoYXNlcywgaW5hY2N1cmFjaWVzIG1heSBlbWVyZ2UgZHVlIHRvIG1pc2NsYXNzaWZpY2F0aW9ucyBvZiBnZW9ncmFwaGljIGxvY2F0aW9ucyBhbmQgaW5jb25zaXN0ZW50IG9yIGluY29tcGxldGUgZGF0YSByZWNvcmRpbmcuIFRoZXNlIGVycm9ycywgd2hpbGUgdW5pbnRlbmRlZCwgY2FuIHN1YnN0YW50aWFsbHkgZGlzdG9ydCB0aGUgcmVzdWx0aW5nIG1ldHJpY3MsIG1ha2luZyBpdCBlc3NlbnRpYWwgdG8gaW1wbGVtZW50IHJpZ29yb3VzIGRhdGEgcXVhbGl0eSBjb250cm9sIG1lYXN1cmVzLiBGdXJ0aGVybW9yZSwgdGhlIHByZXNlbmNlIG9mIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uLCB3aGVyZSBuZWFyYnkgYXJlYXMgZXhoaWJpdCBzaW1pbGFyIGNoYXJhY3RlcmlzdGljcywgY2FuIGFsc28gaW50cm9kdWNlIGJpYXNlcy4gVGhpcyBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBjYW4gYmUgYSBjb25zZXF1ZW5jZSBvZiB1bm1vZGVsZWQgc3BhdGlhbCBwcm9jZXNzZXMsIGxlYWRpbmcgdG8gZXJyb25lb3VzIGFzc3VtcHRpb25zIG9mIGluZGVwZW5kZW5jZSBpbiBzdGF0aXN0aWNhbCBhbmFseXNlcy4gQWRkaXRpb25hbGx5LCBkYXRhIGFuYWx5c2lzIG11c3QgYmUgY29uZHVjdGVkIHdpdGggYW4gYWN1dGUgYXdhcmVuZXNzIG9mIHRoZSBwcmVzZW5jZSBvZiB1bmNvbnRyb2xsZWQgdmFyaWFibGVzIGFuZCB1bmFjY291bnRlZCBkYXRhIGlzc3Vlcywgc3VjaCBhcyB0aGUgbWFyZ2luIG9mIGVycm9yIGluaGVyZW50IGluIGNlbnN1cyBkYXRhIG9yIGFkZHJlc3NpbmcgbWlzc2luZyB2YWx1ZXMgKE5BcykuIEZhaWxpbmcgdG8gYWRkcmVzcyB0aGVzZSBmYWNldHMgY2FuIGludHJvZHVjZSB1bmludGVuZGVkIGJpYXNlcyBhbmQgdW5jZXJ0YWludGllcyBpbnRvIHRoZSBhbmFseXNpcywgcG90ZW50aWFsbHkgdW5kZXJtaW5pbmcgdGhlIHJlbGlhYmlsaXR5IG9mIGNvbmNsdXNpb25zIGRyYXduIGZyb20gc3BhdGlhbCBhc3Nlc3NtZW50cy4gVGh1cywgbWV0aWN1bG91cyBkYXRhIHZhbGlkYXRpb24sIHJpZ29yb3VzIGNsZWFuaW5nIHByb2NlZHVyZXMsIGFuZCB0aGUgY29tcHJlaGVuc2l2ZSBjb25zaWRlcmF0aW9uIG9mIHZhcmlvdXMgaW5mbHVlbnRpYWwgZmFjdG9ycyBhcmUgdml0YWwgc3RlcHMgdG8gbWl0aWdhdGUgc3BhdGlhbCBiaWFzZXMgaW4gYW5hbHlzZXMgb2YgdGhpcyBuYXR1cmUuDQoNCiMjIFRoZSBEb3dudG93biBFZmZlY3QNCg0KPGltZyBzcmM9IkQ6L0ZhbGxfMjAyMy9QUEEvQXNzaWdubWVudDIvaW1hZ2VzL1NjcmVlbnNob3QgMjAyMy0wOS0yMSAyMTA4MzkuanBnIiB3aWR0aD0iMzAwIiBhbGlnbj0icmlnaHQiIHN0eWxlPSJkaXNwbGF5OmlubGluZTsgbWFyZ2luOiAwIDEwcHg7Ii8+DQoNCkZvciBtYW55IG9mIHRoZSB0cmVuZHMgb2JzZXJ2ZWQsIHRoZXkgYXJlIG5vdCBzb2xlbHkgY29udGluZ2VudCBvbiB0cmFuc2l0IGFjY2Vzc2liaWxpdHkuIFRoZXkgYXJlIGluZmx1ZW5jZWQgYnkgYSBtdWx0aWZhY2V0ZWQgd2ViIG9mIGZhY3RvcnMsIGluY2x1ZGluZyBuZWlnaGJvcmhvb2QgYW1lbml0aWVzLCBob3VzaW5nIHBvbGljaWVzLCBhbmQgc29jaW9lY29ub21pYyBkaXNwYXJpdGllcy4gT3Zlcmxvb2tpbmcgdGhlIHNpZ25pZmljYW5jZSBvZiBCb3N0b24ncyBDZW50cmFsIEJ1c2luZXNzIERpc3RyaWN0IChDQkQpLCBhIHRocml2aW5nIGh1YiBvZiBlbXBsb3ltZW50IGFuZCBlY29ub21pYyBhY3Rpdml0eSwgY2FuIGxlYWQgdG8gYW4gaW5oZXJlbnQgdXB3YXJkIHNrZXcgaW4gcmVudCByYXRlcyBuZWFyIHRoaXMgYXJlYS4gDQoNCldoaWxlIHRyYW5zaXQgYWNjZXNzaWJpbGl0eSBpcyBwaXZvdGFsIHRvIFRPRCwgaXQgc2hvdWxkIGJlIHZpZXdlZCB3aXRoaW4gdGhlIGJyb2FkZXIgY29udGV4dCBvZiBCb3N0b24ncyB1cmJhbiBkeW5hbWljcy4gVGhlIENCRCdzIHNpZ25pZmljYW5jZSBhcyBhbiBlbXBsb3ltZW50IGFuZCBlY29ub21pYyBjZW50ZXIgdW5kZXJzY29yZXMgdGhlIG5lZWQgZm9yIHN0cmF0ZWdpYyBwbGFubmluZyB0aGF0IHByb21vdGVzIGJhbGFuY2VkIGdyb3d0aCwgYWZmb3JkYWJpbGl0eSwgYW5kIGVxdWl0YWJsZSBhY2Nlc3MgdG8gdHJhbnNwb3J0YXRpb24gb3B0aW9ucy4NCg0KIyBNb3JlIERhdGEgQW5hbHlzaXMNCg0KVGhpcyBzZWN0aW9uIGV4dGVuZHMgdGhlIHByZWNlZGluZyBkYXRhIGFuYWx5c2lzIG9uIFRyYW5zaXQtT3JpZW50ZWQgRGV2ZWxvcG1lbnQuIEl0IGluY29ycG9yYXRlcyBncmFkdWF0ZWQgc3ltYm9sIG1hcHMgYW5kIGdyYXBocyBkZXBpY3RpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHJlbnQgYW5kIGRpc3RhbmNlIGZyb20gdHJhbnNpdC4NCg0KIyMgR3JhZHVhdGVkIFN5bWJvbCBNYXBzDQoNClRoZSBmb2xsb3dpbmcgdmlzdWFsaXphdGlvbnMgYXJlIGEgcHJvcG9ydGlvbmFsIGRpc3BsYXkgb2YgcmVudCBhbmQgcG9wdWxhdGlvbnMgb2YgY2Vuc3VzIHRyYWN0cyBpbnRlcnNlY3RpbmcgdGhlIGhhbGYgbWlsZSBidWZmZXJzIG9mIHRyYW5zaXQgc3RvcHMuICAgDQoNCmBgYHtyIHNldHRpbmcgdXAgdGhlIGdyYWQgc3ltYm9sc30NCg0KYnVmZmVyc19zdG9wcyA8LSBmaWx0ZXIoTUJUQUJ1ZmZlcnMsIExlZ2VuZD09IkJ1ZmZlciIpDQoNCmJ1ZmZlcnNfc3RvcHMkSUQgPC0gc2VxX2Fsb25nKGJ1ZmZlcnNfc3RvcHMkZ2VvbWV0cnkpIA0KDQppbnRlcnNlY3RlZF9idWZmZXIgPC0gc2VsZWN0Q2VudHJvaWRzICU+JSANCiAgc3RfaW50ZXJzZWN0aW9uKGJ1ZmZlcnNfc3RvcHMsIHNlbGVjdENlbnRyb2lkcykNCg0KdG90YWxfc3RvcHMgPC0gaW50ZXJzZWN0ZWRfYnVmZmVyICU+JQ0KICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lDQogIGdyb3VwX2J5KElELCBHRU9JRCwgeWVhcikgJT4lDQogIHN1bW1hcmlzZShwb3AgPSBzdW0oVG90YWxQb3ApLCByZW50ID0gbWVhbihNZWRSZW50LCBuYS5ybSA9IFRSVUUpKQ0KDQpsYWJlbHNfbiA8LSBjbGlwcGVkTUJUQSAlPiUNCiAgc2VsZWN0KEdFT0lELCBnZW9tZXRyeSkgJT4lDQogIGxlZnRfam9pbih0b3RhbF9zdG9wcywNCiAgICAgICAgICAgIGJ5ID0gIkdFT0lEIikgDQoNCmBgYA0KDQojIyMgUG9wdWxhdGlvbiB3aXRoaW4gMS8yIG1pbGUNCg0KSGVyZSwgaW4gY29udHJhc3QgdG8gdGhlICJzdW0iIG9mIGNlbnN1cyB0cmFjdCBwb3B1bGF0aW9ucyBzdXJyb3VuZGluZyB0aGUgdHJhbnNpdCBzdGF0aW9ucywgdGhlIHN0dWR5IG1ha2VzIHVzZSBvZiB0aGUgYXZlcmFnZSBwb3B1bGF0aW9ucyBvZiBzdXJyb3VuZGluZyBjZW5zdXMgdHJhY3RzLiBUaGlzIHdhcyBkb25lIHNvIHRoYXQgdGhlIGFuYWx5c2lzIG9mZmVycyBhIG1vcmUgbnVhbmNlZCBhbmQgcmVwcmVzZW50YXRpdmUgcGVyc3BlY3RpdmUuIE1lYW4gdmFsdWVzIHRha2UgaW50byBhY2NvdW50IHRoZSBkaXN0cmlidXRpb24gb2YgZGF0YSBwb2ludHMsIHByb3ZpZGluZyBhbiBhdmVyYWdlIHRoYXQgcmVmbGVjdHMgdGhlIGNlbnRyYWwgdGVuZGVuY3kuIEFzIGVhY2ggY2Vuc3VzIHRyYWN0IGludGVyc2VjdHMgbXVsdGlwbGUgYnVmZmVycywgdGhlIHN1bSB0b3RhbCBvZiB0aGUgcG9wdWxhdGlvbnMgd2FzIHJlYWNoaW5nIDUtZGlnaXQgbnVtYmVycyBmb3IgZWFjaCB0cmFuc2l0IHN0b3AsIGdpdmluZyBhIG1pc2xlYWRpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvcHVsYXRpb24gd2l0aGluIHRoZSBjaXR5Lg0KDQpUaGUgZmlyc3Qgb2JzZXJ2YWJsZSBkaWZmZXJlbmNlIGluIHRoZSAyMDE2IGFuZCAyMDIwIGlzIHRoZSBsb3NzIG9mIGRhdGEgLSBtYW55IG9mIHRoZSB0cmFuc2l0IHN0b3BzIGFyZSBtaXNzaW5nIGZyb20gdGhlIDIwMjAgbWFwcy4gVGhpcyBjYW4gYmUgYSByZXN1bHQgb2YgYW4gZXJyYW5lb3VzIGRhdGEgam9pbiwgY29uc2lkZXJpbmcgdGhlIHNoYXBlIG9mIGNlbnN1cyB0cmFjdHMgY2hhbmdlZCBiZXR3ZWVuIHRob3NlIHllYXJzIGFzIGEgcmVzdWx0IG9mIGZsdWN0dWF0aW5nIHBvcHVsYXRpb25zLiBQYXJ0IG9mIHRoZSBkYXRhIGxvc3MgaXMgYWxzbyBhIHJlc3VsdCBvZiBtaXNzaW5nIGRhdGEgZnJvbSBjZW5zdXMuIA0KDQpEZXNwaXRlIHRoZXNlIGVycm9ycywgd2UgY2FuIHNlZSBhIGRpZmZlcmVuY2UgaW4gMjAyMCwgd2l0aCBhIGRlY2xpbmUgaW4gcG9wdWxhdGlvbiwgbW9zdCBkaXN0aW5jdGx5IG9ic2VydmVkIGluIHRoZSBDQkQvZG93bnRvd24gYXJlYS4gV2UgY2FuIHNlZSBhIGhpZ2ggY29uY2VudHJhdGlvbiBvZiByZXNpZGVudHMgYm90aCBhdCB0aGUgY2VudGVyIGFuZCBzb3V0aGVybiBwYXJ0IG9mIHRoZSBjaXR5LCBsaWtlbHkgZHVlIHRvIGEgY29uY2VudHJhdGlvbiBvZiBqb2JzIGFuZCB1bml2ZXJzaXRpZXMuIA0KDQpgYGB7ciBwb3B1bGF0aW9uIGdyYWQgc3ltYm9sc30NCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gdHJhY3RzMjAsIGZpbGwgPSAidHJhbnNwYXJlbnQiKSArICANCiAgZ2VvbV9zZihkYXRhID0gdHJhY3RzMTYsIGZpbGwgPSAidHJhbnNwYXJlbnQiKSArICANCiAgZ2VvbV9zZihkYXRhID0gbGFiZWxzX24gJT4lDQogICAgICAgICAgICAgZmlsdGVyKCFpcy5uYSh5ZWFyKSksICANCiAgICAgICAgICBhZXMoZmlsbCA9IHBvcCwgc2l6ZT0gcG9wKSwNCiAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICBhbHBoYSA9IDAuMikgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygwLjUsIDQpLCBuYW1lID0gIkF2ZXJhZ2UgUG9wdWxhdGlvbiIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gaGNsLmNvbG9ycyg1LCAidmlyaWRpcyIsIHJldiA9IFRSVUUsIGFscGhhID0gMC45KSwgbmFtZSA9ICIiKSAgKw0KICBsYWJzKHNpemUgPSAiUG9pbnQgU2l6ZSIpICsNCiAgIGxhYnModGl0bGUgPSAiQXZlcmFnZSBQb3B1bGF0aW9uIHdpdGhpbiBoYWxmLW1pbGUgb2YgTUJUQSBTdG9wcyIsIHN1YnRpdGxlID0gIlByb3BvcnRpb25hbCBTeW1ib2wgTWFwIiwgY2FwdGlvbiA9ICJGaWd1cmUgNC4xLCBBQ1MgNS1ZZWFyIikgKw0KICBmYWNldF93cmFwKH55ZWFyKSArDQogIG1hcFRoZW1lKCkNCg0KYGBgDQoNCg0KIyMjIFJlbnQgd2l0aGluIDEvMiBtaWxlDQoNClRoZSByZW50IG1hcHMgc2hvdyBzaW1pbGFyIGluY29uc2lzdGVuY2llcyBpbiBkYXRhIGFjcm9zcyB0aGUgdHdvIHllYXJzLiBUaGUgZG93bnRvd24gYW5kIEJhY2sgQmF5IGFyZWFzIChsb2NhdGVkIGF0IHRoZSBtb3N0IHRyYW5zaXQgcmljaCByZWdpb25zIG9mIHRoZSBtYXApIGhhdmUgY29uc2lzdGVudGx5IHJlbWFpbmVkIHRoZSBtb3N0IGRlc2lyYWJsZSBhbmQgZXhwZW5zaXZlIGFyZWFzIHRocm91Z2hvdXQuIFRoZSByZW50IGlzIGxvd2VzdCBpbiBhcmVhcyBpbiBhbmQgYXJvdW5kIFJveGJ1cnksIG1ha2luZyBpdCBhIHJhcmUgYWZmb3JkYWJsZSB5ZXQgdHJhbnNpdCByaWNoIG5laWdoYm9yaG9vZC4gVGhlIHByZXNlbmNlIG9mIHVuaXZlcnNpdGllcyBhbHNvIGxvd2VycyB0aGUgY29zdCBvZiByZW50IGVzcGVjaWFsbHkgaW4gU291dGggQm9zdG9uLg0KDQoNCmBgYHtyIHJlbnQgZ3JhZCBzeW1ib2x9DQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IHRyYWN0czIwLCBmaWxsID0gInRyYW5zcGFyZW50IikgKyAgIA0KICBnZW9tX3NmKGRhdGEgPSB0cmFjdHMxNiwgZmlsbCA9ICJ0cmFuc3BhcmVudCIpICsgIA0KICBnZW9tX3NmKGRhdGEgPSBsYWJlbHNfbiU+JQ0KICAgICAgICAgICAgIGZpbHRlcighaXMubmEoeWVhcikpLCANCiAgICAgICAgICBhZXMoZmlsbCA9IHJlbnQsIHNpemU9IHJlbnQpLA0KICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgIGFscGhhID0gMC4yKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuNSwgNCksIG5hbWUgPSAiQXZlcmFnZSBSZW50IikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvcnMgPSBoY2wuY29sb3JzKDUsICJ2aXJpZGlzIiwgcmV2ID0gVFJVRSwgYWxwaGEgPSAwLjkpLCBuYW1lID0gIiIpICsNCiAgbGFicyhzaXplID0gIlBvaW50IFNpemUiKSArDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBSZW50IHdpdGhpbiBoYWxmLW1pbGUgb2YgTUJUQSBTdG9wcyIsIHN1YnRpdGxlID0gIlByb3BvcnRpb25hbCBTeW1ib2wgTWFwIiwgY2FwdGlvbiA9ICJGaWd1cmUgNC4yLCBBQ1MgNS1ZZWFyIikgKw0KICBmYWNldF93cmFwKH55ZWFyKSArDQogIG1hcFRoZW1lKCkNCg0KYGBgDQoNCiMjIFJlbnQgYXMgYSBmdW5jdGlvbiBvZiBkaXN0YW5jZSBmcm9tIHRoZSB0cmFuc2l0IHN0b3BzDQoNClRoaXMgaXMgYSB2YWx1YWJsZSBtZXRyaWMgYXMgaXQgcmV2ZWFscyBob3cgaG91c2luZyBjb3N0cyBjaGFuZ2Ugd2l0aCBwcm94aW1pdHkgdG8gcHVibGljIHRyYW5zcG9ydGF0aW9uLiBJdCBpbmZvcm1zIGFjY2Vzc2liaWxpdHksIHRyYW5zcG9ydGF0aW9uIGNvc3Qgc2F2aW5ncywgZW52aXJvbm1lbnRhbCBpbXBhY3QsIGFuZCBlcXVpdHkgY29uc2lkZXJhdGlvbnMsIGFpZGluZyB1cmJhbiBwbGFubmluZyBhbmQgcG9saWN5IGRlY2lzaW9ucy4gSXQgZW1wb3dlcnMgaW5kaXZpZHVhbHMgdG8gbWFrZSBpbmZvcm1lZCBob3VzaW5nIGNob2ljZXMgYW5kIGhlbHBzIGRldmVsb3BlcnMgaWRlbnRpZnkgaW52ZXN0bWVudCBvcHBvcnR1bml0aWVzLiBOZXZlcnRoZWxlc3MsIGl0IHNob3VsZCBiZSBjb25zaWRlcmVkIGFsb25nc2lkZSBvdGhlciBmYWN0b3JzIGxpa2UgYW1lbml0aWVzIGFuZCBqb2IgYWNjZXNzaWJpbGl0eSwgYW5kIGl0cyBpbXBhY3QgbWF5IHZhcnkgYnkgbG9jYXRpb24gYW5kIHRyYW5zaXQgcXVhbGl0eS4NCg0KYGBge3IgTVJCfQ0KDQpNQlRBX01SQiA8LSBtdWx0aXBsZVJpbmdCdWZmZXIoc3RfdW5pb24oY2xpcHBlZE1CVEEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhEaXN0YW5jZSA9IDM0MzIwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbCA9ICAyNjQwKQ0KDQojIFlvdXIgZ2dwbG90IGNvZGUNCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gTUJUQV9NUkIsIGFlcyhjb2xvciA9IGRpc3RhbmNlKSwgZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGxpbmV3aWR0aCA9IDAuNSwgYWxwaGEgPSAwLjEgKSArDQogIGdlb21fc2YoZGF0YSA9IGNsaXBwZWRNQlRBLCBzaXplID0gMSkgKw0KICBnZW9tX3NmKGRhdGEgPSBzdF91bmlvbih0cmFjdHMxNiksIGZpbGwgPSBOQSwgbGluZXdpZHRoID0gMC43KSArDQogIGxhYnModGl0bGUgPSAiSGFsZiBtaWxlIGJ1ZmZlcnMiKSArDQogIHNjYWxlX2NvbG9yX3ZpcmlkaXMobmFtZSA9ICJEaXN0YW5jZVxuKGZlZXQpIikgKw0KICBtYXBUaGVtZSgpDQoNCmBgYA0KDQpgYGB7ciBzZXR0aW5nIHVwIHRoZSBidWZmZXJzfQ0KDQp0cmFjdHMyMC5yaW5ncyA8LSB0cmFjdHMyMCAlPiUgDQogIHNlbGVjdChHRU9JRCwgeWVhcikgJT4lIA0KICBzdF9jZW50cm9pZCgpICU+JSANCiAgc3Rfam9pbihNQlRBX01SQiwgam9pbiA9IHN0X2ludGVyc2VjdHMpICU+JQ0KICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lDQogIGxlZnRfam9pbihkcGx5cjo6c2VsZWN0KHRyYWN0czIwLCBHRU9JRCwgTWVkUmVudCwgeWVhciksIA0KICAgICAgICAgICAgYnk9YygiR0VPSUQiPSJHRU9JRCIsICJ5ZWFyIj0ieWVhciIpKSAlPiUNCiAgc3Rfc2YoKSAlPiUNCiAgbXV0YXRlKGRpc3RhbmNlID0gZGlzdGFuY2UgLyA1MjgwKSANCg0KdHJhY3RzMjAucmluZ3Muc3VtbWFyeSA8LSBzdF9kcm9wX2dlb21ldHJ5KHRyYWN0czIwLnJpbmdzKSAlPiUNCiAgICBncm91cF9ieShkaXN0YW5jZSwgeWVhcikgJT4lDQogICAgc3VtbWFyaXplKE1lYW5fUmVudCA9IG1lYW4oTWVkUmVudCwgbmEucm09VCkpDQoNCnRyYWN0czE2LnJpbmdzIDwtIHRyYWN0czE2ICU+JSANCiAgc2VsZWN0KEdFT0lELCB5ZWFyKSAlPiUgDQogIHN0X2NlbnRyb2lkKCkgJT4lIA0KICBzdF9qb2luKE1CVEFfTVJCLCBqb2luID0gc3RfaW50ZXJzZWN0cykgJT4lDQogIHN0X2Ryb3BfZ2VvbWV0cnkoKSAlPiUNCiAgbGVmdF9qb2luKGRwbHlyOjpzZWxlY3QodHJhY3RzMTYsIEdFT0lELCBNZWRSZW50LCB5ZWFyKSwgDQogICAgICAgICAgICBieT1jKCJHRU9JRCI9IkdFT0lEIiwgInllYXIiPSJ5ZWFyIikpICU+JQ0KICBzdF9zZigpICU+JQ0KICBtdXRhdGUoZGlzdGFuY2UgPSBkaXN0YW5jZSAvIDUyODApIA0KDQp0cmFjdHMxNi5yaW5ncy5zdW1tYXJ5IDwtIHN0X2Ryb3BfZ2VvbWV0cnkodHJhY3RzMTYucmluZ3MpICU+JQ0KICAgIGdyb3VwX2J5KGRpc3RhbmNlLCB5ZWFyKSAlPiUNCiAgICBzdW1tYXJpemUoTWVhbl9SZW50ID0gbWVhbihNZWRSZW50LCBuYS5ybT1UKSkNCg0KDQpzdW1tYXJ5X2JpbmQgPC0gcmJpbmQoKHRyYWN0czE2LnJpbmdzLnN1bW1hcnklPiUNCiAgICAgICAgZmlsdGVyKCFpcy5uYShNZWFuX1JlbnQpICYgIWlzLm5hbihNZWFuX1JlbnQpKSksIA0KICAgICAgIHRyYWN0czIwLnJpbmdzLnN1bW1hcnklPiUNCiAgICAgICAgZmlsdGVyKCFpcy5uYShNZWFuX1JlbnQpICYgIWlzLm5hbihNZWFuX1JlbnQpKQ0KKQ0KDQpgYGANCg0KVGhlIGZpcnN0IG9idmlvdXMgY29uY2x1c2lvbiBpcyB0aGF0IHJlbnQgaXMgc2lnbmlmaWNhbnRseSBoaWdoZXIgaW4gdGhlIHllYXIgMjAyMCB0aGFuIGluIDIwMTYuIEZ1cnRoZXIsIHRoZSBkZWNyZWFzZSBpbiByZW50IGFzIG9uZSBtb3ZlcyBhd2F5IGZyb20gdHJhbnNpdCBzdG9wcyBjYW4gYmUgYXR0cmlidXRlZCB0byBzZXZlcmFsIGZhY3RvcnMuIEZpcnN0bHksIHByb3BlcnRpZXMgbG9jYXRlZCBjbG9zZXIgdG8gdHJhbnNpdCBzdG9wcyBhcmUgbW9yZSBjb252ZW5pZW50IGZvciBjb21tdXRlcnMsIHJlZHVjaW5nIHRoZSBuZWVkIGZvciBwcml2YXRlIHRyYW5zcG9ydGF0aW9uIGFuZCBzYXZpbmcgb24gY29tbXV0aW5nIGNvc3RzLiBUaGlzIGluY3JlYXNlZCBhY2Nlc3NpYmlsaXR5IGFuZCByZWR1Y2VkIHRyYW5zcG9ydGF0aW9uIGV4cGVuc2VzIG1ha2UgdGhlc2UgYXJlYXMgbW9yZSBkZXNpcmFibGUsIGxlYWRpbmcgdG8gaGlnaGVyIGRlbWFuZCBhbmQsIGNvbnNlcXVlbnRseSwgaGlnaGVyIHJlbnRzLg0KDQoNCmBgYHtyIHRhYmxpbmcgdGhlIHJlbnQgdnMgZGlzdGFuY2V9DQoNCg0KDQpnZ3Bsb3Qoc3VtbWFyeV9iaW5kLA0KICAgICAgIGFlcyhkaXN0YW5jZSwgTWVhbl9SZW50LCBjb2xvdXI9eWVhcikpICsNCiAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGU1LCBuYW1lID0gIlllYXIiKSArDQogICAgICAgZ2VvbV9wb2ludChzaXplPTMpICsgDQogICAgICAgZ2VvbV9saW5lKHNpemU9MikgKyANCiAgICBsYWJzKA0KICAgIHRpdGxlID0gIkhhbGYgbWlsZSBidWZmZXJzIiwNCiAgICB4ID0gIkRpc3RhbmNlIGluIE1pbGVzIiwgICMgQ2hhbmdlIHRoZSBYLWF4aXMgbGFiZWwNCiAgICB5ID0gIlJlbnQgaW4gRG9sbGFycyIgICAjIENoYW5nZSB0aGUgWS1heGlzIGxhYmVsDQogICkgKw0KICAgICAgIHBsb3RUaGVtZSgpDQoNCmBgYA0KDQpJbiBjb250cmFzdCwgYXMgb25lIG1vdmVzIGZ1cnRoZXIgYXdheSBmcm9tIHRyYW5zaXQgc3RvcHMsIHRoZSBjb252ZW5pZW5jZSBvZiBhY2Nlc3MgdG8gcHVibGljIHRyYW5zcG9ydGF0aW9uIGRpbWluaXNoZXMuIEFzIGEgcmVzdWx0LCB0aGUgZGVtYW5kIGZvciBwcm9wZXJ0aWVzIGluIHRoZXNlIGFyZWFzIGRlY3JlYXNlcywgd2hpY2ggcHV0cyBkb3dud2FyZCBwcmVzc3VyZSBvbiByZW50IHByaWNlcy4gQWRkaXRpb25hbGx5LCBwcm9wZXJ0aWVzIGZhcnRoZXIgZnJvbSB0cmFuc2l0IGh1YnMgbWF5IG9mZmVyIGxhcmdlciBzcGFjZXMgb3IgZGlmZmVyZW50IGFtZW5pdGllcyB0aGF0IGNhbiBvZmZzZXQgdGhlIGluY29udmVuaWVuY2Ugb2YgYSBsb25nZXIgY29tbXV0ZSwgZnVydGhlciBjb250cmlidXRpbmcgdG8gdGhlIGRlY2xpbmUgaW4gcmVudCBwcmljZXMgYXMgd2UgbW92ZSBhd2F5IGZyb20gdHJhbnNpdCBzdG9wcy4gVGhlc2UgY29tYmluZWQgZmFjdG9ycyBjcmVhdGUgYSByZW50IGdyYWRpZW50IHdpdGggdHJhbnNpdCBwcm94aW1pdHkgYXQgaXRzIGNvcmUuDQoNCiMgUG9saWN5IFJlY29tbWVuZGF0aW9ucyANCg0KQmFzZWQgb24gdGhpcyByZXBvcnQsIHRoZSBmb2xsb3dpbmcgcG9saWN5IGJyb2FkIHJlY29tbWVuZGF0aW9ucyBjYW4gYmUgbWFkZTogDQoNCjEuIEFmZm9yZGFibGUgSG91c2luZzogR2l2ZW4gdGhlIHJpc2UgaW4gcmVudCBhbmQgaW5jcmVhc2luZyByZW50IGJ1cmRlbiwgcG9saWNpZXMgc2hvdWxkIGZvY3VzIG9uIHRoZSBkZXZlbG9wbWVudCBvZiBhZmZvcmRhYmxlIGhvdXNpbmcgb3B0aW9ucyBuZWFyIHRyYW5zaXQgaHVicy4gQWZmb3JkYWJsZSBob3VzaW5nIGluaXRpYXRpdmVzIGNhbiBoZWxwIHJldGFpbiBhIGRpdmVyc2UgcG9wdWxhdGlvbiBhbmQgcHJvbW90ZSB0cmFuc2l0IHVzZS4NCg0KMi4gVHJhbnNpdCBBY2Nlc3NpYmlsaXR5OiBDb250aW51ZSBpbnZlc3RtZW50cyBpbiBpbXByb3ZpbmcgdHJhbnNpdCBpbmZyYXN0cnVjdHVyZSBhbmQgYWNjZXNzaWJpbGl0eSB0byBlbnN1cmUgdGhhdCByZXNpZGVudHMgY2FuIGVhc2lseSBhY2Nlc3MgcHVibGljIHRyYW5zcG9ydGF0aW9uLiBFbmhhbmNlbWVudHMgY2FuIGluY2x1ZGUgZXhwYW5kaW5nIHRyYW5zaXQgbmV0d29ya3MsIGltcHJvdmluZyBzdGF0aW9uIGZhY2lsaXRpZXMsIGFuZCBpbmNyZWFzaW5nIHNlcnZpY2UgZnJlcXVlbmN5Lg0KDQozLiBEYXRhIE1vbml0b3Jpbmc6IEVzdGFibGlzaCBhIGNvbXByZWhlbnNpdmUgZGF0YSBtb25pdG9yaW5nIHN5c3RlbSB0byByZWd1bGFybHkgYXNzZXNzIGNoYW5nZXMgaW4gcG9wdWxhdGlvbiwgaW5jb21lLCBhbmQgcmVudCBpbiBUT0QgZGlzdHJpY3RzLiBUaGlzIGRhdGEtZHJpdmVuIGFwcHJvYWNoIHdpbGwgZW5hYmxlIHBvbGljeW1ha2VycyB0byBtYWtlIHRpbWVseSBhZGp1c3RtZW50cyB0byBob3VzaW5nIGFuZCB0cmFuc3BvcnRhdGlvbiBwb2xpY2llcy4NCg0KQm9zdG9uJ3MgVHJhbnNpdC1PcmllbnRlZCBEZXZlbG9wbWVudCBwcmVzZW50cyBib3RoIG9wcG9ydHVuaXRpZXMgYW5kIGNoYWxsZW5nZXMuIFdoaWxlIGl0IG9mZmVycyB0aGUgcG90ZW50aWFsIGZvciBzdXN0YWluYWJsZSB1cmJhbiBncm93dGggYW5kIHJlZHVjZWQgY2FyIGRlcGVuZGVuY3ksIGl0IGFsc28gcmVxdWlyZXMgY2FyZWZ1bCBwbGFubmluZyBhbmQgcG9saWNpZXMgdG8gYWRkcmVzcyBpc3N1ZXMgb2YgaG91c2luZyBhZmZvcmRhYmlsaXR5IGFuZCBlcXVpdGFibGUgZGV2ZWxvcG1lbnQuIEJ5IGltcGxlbWVudGluZyB0aGUgcmVjb21tZW5kZWQgcG9saWNpZXMgYW5kIGNsb3NlbHkgbW9uaXRvcmluZyBkZW1vZ3JhcGhpYyBhbmQgZWNvbm9taWMgY2hhbmdlcywgQm9zdG9uIGNhbiBjcmVhdGUgdmlicmFudCBhbmQgaW5jbHVzaXZlIG5laWdoYm9yaG9vZHMgYXJvdW5kIGl0cyB0cmFuc2l0IG5ldHdvcmsu