The BARI Geographic Infrastructure is essentially just property records data along with aggregate versions of these data. BARI releases these at the property, parcel, Census block, Census blockgroup, and Census tract levels.
I wanted to explore some of the dynamics in the use of individual parcels in the property records. For this I’m going to start with the individual parcel-level dataset (Land.Parcels.2018.csv, posted on the BARI Dataverse here ####) rather than one of the geographic aggregated datasets.
# check out the data
names(parcel_data)
[1] "X.1" "Land_Parcel_ID" "full_address" "property_N" "unit_N" "unit_N_orig" "AV_LAND"
[8] "AV_BLDG" "AV_TOTAL" "LAND_SF" "GROSS_AREA" "LIVING_AREA" "LU" "OWN_OCC"
[15] "NUM_FLOORS" "YR_BUILT" "YR_REMOD" "R_BLDG_STYL" "owner_address" "comcenter" "medhos"
[22] "supermkt" "parking" "vacant" "rel" "lib" "bps" "police"
[29] "fire" "private" "X" "Y" "TLID" "Blk_ID_10" "BG_ID_10"
[36] "CT_ID_10" "ALAND10" "AWATER10" "POP100" "HU100" "Type" "Res"
[43] "CT_ID_10.y" "BRA_PD_ID" "BRA_PD" "City_Counc" "WARD" "ISD_Nbhd" "Police_Dis"
[50] "Fire_Distr" "PWD" "geometry"
Neighborhood dynamics
First I’m going to summarize the parcel data using one of the included geographic identifiers - Census Tracts.
parcel_tractsumm <- parcel_data %>%
group_by(CT_ID_10) %>%
summarize(total_area = sum(GROSS_AREA),
perc_parcels_parking = mean(parking,na.rm=T),
perc_area_parking = sum(GROSS_AREA[parking==1],na.rm=T)/total_area)
summary(parcel_tractsumm$perc_area_parking)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
0.000000 0.000000 0.000000 0.006793 0.000000 0.287028 1
So, most census tracts are low in their total percentage of parking parcels - with the caveat that these are only counted as parking if they are OFF-street parking and parking alone, rather than, for instance, a residential parcel with two parking spots.
#percentage plot for different types of permits
(ct_area_parking <- ggplot(parcel_tractsumm) +
geom_histogram(aes(x = perc_area_parking)) +
scale_x_continuous("Proportion of tract's area that is parking") +
theme_bw() +
theme(legend.position="none")
)

ggsave(plot=ct_area_parking,"figures/tracts_percarea_parking.pdf",height=7,width=10)
What about how these vary over neighborhoods that are larger in scale than Census Tracts? To look at this I brought in one of the aggregate versions of data that BARI provides with this dataset - the Tract-level data, (BostonTracts2010) - and connect the georgraphic units in that file with the parcel-level data. This enables me to easily summarize the parcel-level information about parking at various geographic levels. I did this by neighborhoods (as defined by the City’s Inspectional Services Department).
# bring in neighborhoods and other variables:
cts <- read_sf(paste0(BARIdrive_path,"Geographical Infrastructure/Data/Geographical Infrastructure 2018/Data/BostonTracts2010/"),"BostonTracts2010")
cts$GEOID10 <- as.numeric(cts$GEOID10)
parcel_data <- left_join(parcel_data,cts,by=c("CT_ID_10" = "GEOID10"))
parcel_nhsumm <- subset(parcel_data,!is.na(ISD_Nbhd)) %>%
group_by(ISD_Nbhd) %>%
summarize(total_area = sum(GROSS_AREA),
perc_parcels_parking = mean(parking,na.rm=T),
perc_area_parking = sum(GROSS_AREA[parking==1],na.rm=T)/total_area)
parcel_nhsumm
This summarization tells us that the area dedicated to off-site parking parcels varies a lot according to neighborhood. Let’s visualize this:
(nh_area_parking <- ggplot(parcel_nhsumm) +
geom_bar(aes(x=ISD_Nbhd,y = perc_area_parking),stat="identity") +
scale_y_continuous("Percent of area that is parking",labels = paste0(seq(0,1,0.02)*100,"%"),breaks=seq(0,1,0.02)) +
scale_x_discrete("Neighborhood") +
theme_bw() +
theme(legend.position="none",axis.text.x = element_text(angle = 45, hjust = 1))
)

This shows that some of the smallest and densest neighborhoods (e.g. Bay Village and Chinatown) are most heavily dedicated to off-street parking. This is especially interesting considering their proximity to downtown and their proximity to mass transit stations.
ggsave(plot=nh_area_parking,"figures/nh_percarea_parking.pdf",height=7,width=10)
Temporal dynamics
Next, let’s look at how has the existence of parking has fluctuated over time. One way to check this is by seeing when a parcel was developed.
parcel_yearsumm <- parcel_data %>%
group_by(YR_BUILT) %>%
summarize(total_area = sum(GROSS_AREA),
perc_parcels_parking = mean(parking,na.rm=T),
perc_area_parking = sum(GROSS_AREA[parking==1],na.rm=T)/total_area)
summary(parcel_yearsumm$perc_parcels_parking)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000000 0.000000 0.000000 0.001259 0.000000 0.042630
summary(parcel_yearsumm$perc_area_parking)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000000 0.000000 0.000000 0.008046 0.000000 0.430404
parcel_yearsumm_r <- parcel_data %>%
group_by(YR_REMOD) %>%
summarize(total_area = sum(GROSS_AREA),
perc_parcels_parking = mean(parking,na.rm=T),
perc_area_parking = sum(GROSS_AREA[parking==1],na.rm=T)/total_area)
summary(parcel_yearsumm_r$perc_parcels_parking)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000000 0.000000 0.000000 0.000455 0.000000 0.011040
summary(parcel_yearsumm_r$perc_area_parking)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
0.000000 0.000000 0.000000 0.003394 0.000000 0.088492 1
Looks like up to 8% of the total area remodeled in a given year was parking, in some cases! Let’s visualize these patterns.
(yearsumm_parkingprop_plot <- ggplot(parcel_yearsumm_r) +
geom_smooth(aes(x = YR_REMOD, y = perc_area_parking),method="loess",span=0.2,se = F) +
scale_y_continuous('Proportion of total remodeled area in year') +
scale_x_continuous("Year remodeled",limits=c(1970,2018.5),breaks=seq(1900,2020,5)) +
theme_bw()
)
So, overall very little parking square footage is remodeled in most years, with many years having no remodeled parking, but in a few years it jumps up notably – for instance, in 2014.
ggsave(plot=yearsumm_parkingprop_plot,"figures/prop_areaparking_year.pdf",height=7,width=10)
Geographic dynamics
Now let’s see where these parking parcels exist in Boston. To do this we’re going to use the spatial files from BARI.
library(leaflet)
library(RColorBrewer) # color scales
library(classInt) # color scales
Loading required package: spData
To access larger datasets in this package, install the spDataLarge package with:
`install.packages('spDataLarge', repos='https://nowosad.github.io/drat/', type='source'))`
library(scales)
Attaching package: ‘scales’
The following object is masked from ‘package:purrr’:
discard
The following object is masked from ‘package:readr’:
col_factor
parcels_shp <- st_read(dsn=paste0(BARIdrive_path,"Geographical Infrastructure/Data/Geographical Infrastructure 2018/Data/BostonParcels2018"),layer="Parcels2018")
Reading layer `Parcels2018' from data source `/Users/justin/Google Drive/BARI Research Team Data Library/Geographical Infrastructure/Data/Geographical Infrastructure 2018/Data/BostonParcels2018' using driver `ESRI Shapefile'
Simple feature collection with 98930 features and 2 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -71.19091 ymin: 42.22786 xmax: -70.86865 ymax: 42.39701
epsg (SRID): 4326
proj4string: +proj=longlat +datum=WGS84 +no_defs
Now that the data is combined with geographic shapefiles, let’s make some simple visuals
# add parking variable into shapefile:
parcels_shp$parking <- parcel_data$parking[match(parcels_shp$Ln_P_ID,parcel_data$Land_Parcel_ID)]
# pdf("figures/newcon_pp_ct_2017.pdf")
# par(mar=c(2,2,4,2))
plot(st_geometry(subset(parcels_shp,parking==1)),col="grey")

# title(main="Demographic change, pre-2015")
# dev.off()
Now lets make some better maps:
# b1 <- b0 +
# geom_polygon(data=parcels_shp2[which(parcels_shp2$parking==1)], aes(x=lon,y=lat), colour = "red", fill = "grey") +
# geom_polygon(data=parcels_shp2[which(parcels_shp2$parking==0),], aes(x=lon,y=lat), col="blue",fill=NA) +
# theme(legend.position = c(0.85,0.15),plot.margin = unit(c(0.1,0.1,0.1,0.1),"cm"))
(b1 <- b0 +
coord_sf(crs = st_crs(4326)) +
geom_sf(data=cts,col="darkgrey",lwd=0.1,inherit.aes=F) +
geom_sf(data=subset(parcels_shp,parking==1),col=vturq,inherit.aes=F)
)

This map spatially demonstrates what the charts showed: off-street parking (plotted in turquoise on this map) is incredibly concentrated (relative to total area) in the downtown areas of Boston.
ggsave(b1,filename = "figures/parking_parcels_gg.pdf",height=7,width=9)
boston_base_bg <- get_stamenmap(bbox=boston_bbox3, zoom=12, color="bw",
source="stamen",maptype = "toner-lite",crop=T)
b0_bg <- ggmap(boston_base_bg, extent="device",legend="none",maprange=T)
(b1_bg <- b0_bg +
coord_sf(crs = st_crs(4326)) +
geom_sf(data=subset(parcels_shp,parking==1),col=vturq,inherit.aes=F)
)

ggsave(b1_bg,filename = "figures/parking_parcels_lite.pdf",height=7,width=9)
On a policy note, these summaries point out one way in which transportation resources currently exist in the City. As Boston moves towards a more climate-friendly resilience plan, leveraging the area dedicated to cars to instead prioritize non-driving forms of transportation will be important. Currently, dedicating so much of the downtown neighborhoods to parking only serves to increase the number of cars there, which seems counterintuitive for traffic and urban planning more broadly. If the City of Boston wanted to decrease traffic in these central neighborhoods and decrease the number of cars entering such dense neighborhoods, dedicating less of the area in these neighborhoods to cars would be a good first step.
More broadly, these summaries and various visuals together demonstrate the use of BARI’s geographical infrastructure dataset more generally: easily being able to summarize information at various geographic levels across the City.
tm_shape(subset(parcels_shp,parking==1)) +
tm_fill(col = vturq,title = "Parking parcels")
Error in tm_shape(subset(parcels_shp, parking == 1)) :
could not find function "tm_shape"
LS0tCnRpdGxlOiAnV2hlcmUgcGVvcGxlIGNhbiBwYWhrIHRoZWlyIGNhaHIgaW4gQm9zdG9uJwpzdWJ0aXRsZTogJ0EgZGVtb25zdHJhdGlvbiB1c2luZyB0aGUgR2VvZ3JhcGhpY2FsIEluZnJhc3RydWN0dXJlIG9mIHRoZSBDaXR5IG9mIEJvc3RvbicKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKVGhlIEJBUkkgR2VvZ3JhcGhpYyBJbmZyYXN0cnVjdHVyZSBpcyBlc3NlbnRpYWxseSBqdXN0IHByb3BlcnR5IHJlY29yZHMgZGF0YSBhbG9uZyB3aXRoIGFnZ3JlZ2F0ZSB2ZXJzaW9ucyBvZiB0aGVzZSBkYXRhLiBCQVJJIHJlbGVhc2VzIHRoZXNlIGF0IHRoZSBwcm9wZXJ0eSwgcGFyY2VsLCBDZW5zdXMgYmxvY2ssIENlbnN1cyBibG9ja2dyb3VwLCBhbmQgQ2Vuc3VzIHRyYWN0IGxldmVscy4KCkkgd2FudGVkIHRvIGV4cGxvcmUgc29tZSBvZiB0aGUgZHluYW1pY3MgaW4gdGhlIHVzZSBvZiBpbmRpdmlkdWFsIHBhcmNlbHMgaW4gdGhlIHByb3BlcnR5IHJlY29yZHMuIEZvciB0aGlzIEknbSBnb2luZyB0byBzdGFydCB3aXRoIHRoZSBpbmRpdmlkdWFsIHBhcmNlbC1sZXZlbCBkYXRhc2V0IChgTGFuZC5QYXJjZWxzLjIwMTguY3N2YCwgcG9zdGVkIG9uIHRoZSBCQVJJIERhdGF2ZXJzZSBoZXJlICMjIyMpIHJhdGhlciB0aGFuIG9uZSBvZiB0aGUgZ2VvZ3JhcGhpYyBhZ2dyZWdhdGVkIGRhdGFzZXRzLgoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShzZikKIyBjb2xvciBkZWZpbml0aW9uczoKdnB1cnBsZSA9ICcjNDQwMTU0Jwp2dHVycSA9ICcjMjE5MDhDJwoKIyBpbXBvcnRpbmcgdGhlIGRhdGEgIyMjIwpCQVJJZHJpdmVfcGF0aCA8LSAifi9Hb29nbGUgRHJpdmUvQkFSSSBSZXNlYXJjaCBUZWFtIERhdGEgTGlicmFyeS8iCnBhcmNlbF9kYXRhIDwtIHJlYWQuY3N2KHBhc3RlMChCQVJJZHJpdmVfcGF0aCwiR2VvZ3JhcGhpY2FsIEluZnJhc3RydWN0dXJlL0RhdGEvR2VvZ3JhcGhpY2FsIEluZnJhc3RydWN0dXJlIDIwMTgvRGF0YS9MYW5kLlBhcmNlbHMuMjAxOC5jc3YiKSkKCiMgY2hlY2sgb3V0IHRoZSBkYXRhCm5hbWVzKHBhcmNlbF9kYXRhKSAKYGBgCgojIE5laWdoYm9yaG9vZCBkeW5hbWljcwoKRmlyc3QgSSdtIGdvaW5nIHRvIHN1bW1hcml6ZSB0aGUgcGFyY2VsIGRhdGEgdXNpbmcgb25lIG9mIHRoZSBpbmNsdWRlZCBnZW9ncmFwaGljIGlkZW50aWZpZXJzIC0gQ2Vuc3VzIFRyYWN0cy4KYGBge3J9CnBhcmNlbF90cmFjdHN1bW0gPC0gcGFyY2VsX2RhdGEgJT4lCiAgICAgIGdyb3VwX2J5KENUX0lEXzEwKSAlPiUKICAgICAgc3VtbWFyaXplKHRvdGFsX2FyZWEgPSBzdW0oR1JPU1NfQVJFQSksCiAgICAgIAkJCQkJcGVyY19wYXJjZWxzX3BhcmtpbmcgPSBtZWFuKHBhcmtpbmcsbmEucm09VCksCiAgICAgIAkJCQkJcGVyY19hcmVhX3BhcmtpbmcgPSBzdW0oR1JPU1NfQVJFQVtwYXJraW5nPT0xXSxuYS5ybT1UKS90b3RhbF9hcmVhKQoKc3VtbWFyeShwYXJjZWxfdHJhY3RzdW1tJHBlcmNfYXJlYV9wYXJraW5nKQpgYGAKU28sIG1vc3QgY2Vuc3VzIHRyYWN0cyBhcmUgbG93IGluIHRoZWlyIHRvdGFsIHBlcmNlbnRhZ2Ugb2YgcGFya2luZyBwYXJjZWxzIC0gd2l0aCB0aGUgY2F2ZWF0IHRoYXQgdGhlc2UgYXJlIG9ubHkgY291bnRlZCBhcyBwYXJraW5nIGlmIHRoZXkgYXJlIE9GRi1zdHJlZXQgcGFya2luZyBhbmQgcGFya2luZyAqYWxvbmUqLCByYXRoZXIgdGhhbiwgZm9yIGluc3RhbmNlLCBhIHJlc2lkZW50aWFsIHBhcmNlbCB3aXRoIHR3byBwYXJraW5nIHNwb3RzLgoKCmBgYHtyfQojcGVyY2VudGFnZSBwbG90IGZvciBkaWZmZXJlbnQgdHlwZXMgb2YgcGVybWl0cwooY3RfYXJlYV9wYXJraW5nIDwtIGdncGxvdChwYXJjZWxfdHJhY3RzdW1tKSArIAogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBwZXJjX2FyZWFfcGFya2luZykpICsgCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoIlByb3BvcnRpb24gb2YgdHJhY3QncyBhcmVhIHRoYXQgaXMgcGFya2luZyIpICsgCiAgICAgIHRoZW1lX2J3KCkgKyAKICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCiApCmBgYAoKYGBge3J9Cmdnc2F2ZShwbG90PWN0X2FyZWFfcGFya2luZywiZmlndXJlcy90cmFjdHNfcGVyY2FyZWFfcGFya2luZy5wZGYiLGhlaWdodD03LHdpZHRoPTEwKQpgYGAKCldoYXQgYWJvdXQgaG93IHRoZXNlIHZhcnkgb3ZlciBuZWlnaGJvcmhvb2RzIHRoYXQgYXJlIGxhcmdlciBpbiBzY2FsZSB0aGFuIENlbnN1cyBUcmFjdHM/IFRvIGxvb2sgYXQgdGhpcyBJIGJyb3VnaHQgaW4gb25lIG9mIHRoZSBhZ2dyZWdhdGUgdmVyc2lvbnMgb2YgZGF0YSB0aGF0IEJBUkkgcHJvdmlkZXMgd2l0aCB0aGlzIGRhdGFzZXQgLSB0aGUgVHJhY3QtbGV2ZWwgZGF0YSwgKGBCb3N0b25UcmFjdHMyMDEwYCkgLSBhbmQgY29ubmVjdCB0aGUgZ2VvcmdyYXBoaWMgdW5pdHMgaW4gdGhhdCBmaWxlIHdpdGggdGhlIHBhcmNlbC1sZXZlbCBkYXRhLiBUaGlzIGVuYWJsZXMgbWUgdG8gZWFzaWx5IHN1bW1hcml6ZSB0aGUgcGFyY2VsLWxldmVsIGluZm9ybWF0aW9uIGFib3V0IHBhcmtpbmcgYXQgdmFyaW91cyBnZW9ncmFwaGljIGxldmVscy4gSSBkaWQgdGhpcyBieSBuZWlnaGJvcmhvb2RzIChhcyBkZWZpbmVkIGJ5IHRoZSBDaXR5J3MgSW5zcGVjdGlvbmFsIFNlcnZpY2VzIERlcGFydG1lbnQpLgoKYGBge3J9CiMgYnJpbmcgaW4gbmVpZ2hib3Job29kcyBhbmQgb3RoZXIgdmFyaWFibGVzOgpjdHMgPC0gcmVhZF9zZihwYXN0ZTAoQkFSSWRyaXZlX3BhdGgsIkdlb2dyYXBoaWNhbCBJbmZyYXN0cnVjdHVyZS9EYXRhL0dlb2dyYXBoaWNhbCBJbmZyYXN0cnVjdHVyZSAyMDE4L0RhdGEvQm9zdG9uVHJhY3RzMjAxMC8iKSwiQm9zdG9uVHJhY3RzMjAxMCIpCmN0cyRHRU9JRDEwIDwtIGFzLm51bWVyaWMoY3RzJEdFT0lEMTApCnBhcmNlbF9kYXRhIDwtIGxlZnRfam9pbihwYXJjZWxfZGF0YSxjdHMsYnk9YygiQ1RfSURfMTAiID0gIkdFT0lEMTAiKSkKCnBhcmNlbF9uaHN1bW0gPC0gc3Vic2V0KHBhcmNlbF9kYXRhLCFpcy5uYShJU0RfTmJoZCkpICU+JQogICAgICBncm91cF9ieShJU0RfTmJoZCkgJT4lCiAgICAgIHN1bW1hcml6ZSh0b3RhbF9hcmVhID0gc3VtKEdST1NTX0FSRUEpLAogICAgICAJCQkJCXBlcmNfcGFyY2Vsc19wYXJraW5nID0gbWVhbihwYXJraW5nLG5hLnJtPVQpLAogICAgICAJCQkJCXBlcmNfYXJlYV9wYXJraW5nID0gc3VtKEdST1NTX0FSRUFbcGFya2luZz09MV0sbmEucm09VCkvdG90YWxfYXJlYSkKcGFyY2VsX25oc3VtbQpgYGAKVGhpcyBzdW1tYXJpemF0aW9uIHRlbGxzIHVzIHRoYXQgdGhlIGFyZWEgZGVkaWNhdGVkIHRvIG9mZi1zaXRlIHBhcmtpbmcgcGFyY2VscyB2YXJpZXMgYSBsb3QgYWNjb3JkaW5nIHRvIG5laWdoYm9yaG9vZC4gTGV0J3MgdmlzdWFsaXplIHRoaXM6CgpgYGB7cn0KKG5oX2FyZWFfcGFya2luZyA8LSBnZ3Bsb3QocGFyY2VsX25oc3VtbSkgKyAKICAgIGdlb21fYmFyKGFlcyh4PUlTRF9OYmhkLHkgPSBwZXJjX2FyZWFfcGFya2luZyksc3RhdD0iaWRlbnRpdHkiKSArIAogICAgc2NhbGVfeV9jb250aW51b3VzKCJQZXJjZW50IG9mIGFyZWEgdGhhdCBpcyBwYXJraW5nIixsYWJlbHMgPSBwYXN0ZTAoc2VxKDAsMSwwLjAyKSoxMDAsIiUiKSxicmVha3M9c2VxKDAsMSwwLjAyKSkgKyAKIAlzY2FsZV94X2Rpc2NyZXRlKCJOZWlnaGJvcmhvb2QiKSArIAogICAgICB0aGVtZV9idygpICsgCiAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCiApCgpgYGAKClRoaXMgc2hvd3MgdGhhdCBzb21lIG9mIHRoZSBzbWFsbGVzdCBhbmQgZGVuc2VzdCBuZWlnaGJvcmhvb2RzIChlLmcuIEJheSBWaWxsYWdlIGFuZCBDaGluYXRvd24pIGFyZSBtb3N0IGhlYXZpbHkgZGVkaWNhdGVkIHRvIG9mZi1zdHJlZXQgcGFya2luZy4gVGhpcyBpcyBlc3BlY2lhbGx5IGludGVyZXN0aW5nIGNvbnNpZGVyaW5nIHRoZWlyIHByb3hpbWl0eSB0byBkb3dudG93biBhbmQgdGhlaXIgcHJveGltaXR5IHRvIG1hc3MgdHJhbnNpdCBzdGF0aW9ucy4KCmBgYHtyfQpnZ3NhdmUocGxvdD1uaF9hcmVhX3BhcmtpbmcsImZpZ3VyZXMvbmhfcGVyY2FyZWFfcGFya2luZy5wZGYiLGhlaWdodD03LHdpZHRoPTEwKQpgYGAKCiMgVGVtcG9yYWwgZHluYW1pY3MKTmV4dCwgbGV0J3MgbG9vayBhdCBob3cgaGFzIHRoZSBleGlzdGVuY2Ugb2YgcGFya2luZyBoYXMgZmx1Y3R1YXRlZCBvdmVyIHRpbWUuIE9uZSB3YXkgdG8gY2hlY2sgdGhpcyBpcyBieSBzZWVpbmcgd2hlbiBhIHBhcmNlbCB3YXMgZGV2ZWxvcGVkLgoKYGBge3J9CgpwYXJjZWxfeWVhcnN1bW0gPC0gcGFyY2VsX2RhdGEgJT4lCiAgICAgIGdyb3VwX2J5KFlSX0JVSUxUKSAlPiUKICAgICAgc3VtbWFyaXplKHRvdGFsX2FyZWEgPSBzdW0oR1JPU1NfQVJFQSksCiAgICAgIAkJCQkJcGVyY19wYXJjZWxzX3BhcmtpbmcgPSBtZWFuKHBhcmtpbmcsbmEucm09VCksCiAgICAgIAkJCQkJcGVyY19hcmVhX3BhcmtpbmcgPSBzdW0oR1JPU1NfQVJFQVtwYXJraW5nPT0xXSxuYS5ybT1UKS90b3RhbF9hcmVhKQpzdW1tYXJ5KHBhcmNlbF95ZWFyc3VtbSRwZXJjX3BhcmNlbHNfcGFya2luZykKc3VtbWFyeShwYXJjZWxfeWVhcnN1bW0kcGVyY19hcmVhX3BhcmtpbmcpCgpwYXJjZWxfeWVhcnN1bW1fciA8LSBwYXJjZWxfZGF0YSAlPiUKICAgICAgZ3JvdXBfYnkoWVJfUkVNT0QpICU+JQogICAgICBzdW1tYXJpemUodG90YWxfYXJlYSA9IHN1bShHUk9TU19BUkVBKSwKICAgICAgCQkJCQlwZXJjX3BhcmNlbHNfcGFya2luZyA9IG1lYW4ocGFya2luZyxuYS5ybT1UKSwKICAgICAgCQkJCQlwZXJjX2FyZWFfcGFya2luZyA9IHN1bShHUk9TU19BUkVBW3Bhcmtpbmc9PTFdLG5hLnJtPVQpL3RvdGFsX2FyZWEpCnN1bW1hcnkocGFyY2VsX3llYXJzdW1tX3IkcGVyY19wYXJjZWxzX3BhcmtpbmcpCnN1bW1hcnkocGFyY2VsX3llYXJzdW1tX3IkcGVyY19hcmVhX3BhcmtpbmcpCmBgYApMb29rcyBsaWtlIHVwIHRvIDglIG9mIHRoZSB0b3RhbCBhcmVhIHJlbW9kZWxlZCBpbiBhIGdpdmVuIHllYXIgd2FzIHBhcmtpbmcsIGluIHNvbWUgY2FzZXMhIExldCdzIHZpc3VhbGl6ZSB0aGVzZSBwYXR0ZXJucy4KCmBgYHtyLCB3YXJuaW5nPUZ9Cih5ZWFyc3VtbV9wYXJraW5ncHJvcF9wbG90IDwtIGdncGxvdChwYXJjZWxfeWVhcnN1bW1fcikgKyAKICAgIGdlb21fc21vb3RoKGFlcyh4ID0gWVJfUkVNT0QsIHkgPSBwZXJjX2FyZWFfcGFya2luZyksbWV0aG9kPSJsb2VzcyIsc3Bhbj0wLjIsc2UgPSBGKSArIAogICAgc2NhbGVfeV9jb250aW51b3VzKCdQcm9wb3J0aW9uIG9mIHRvdGFsIHJlbW9kZWxlZCBhcmVhIGluIHllYXInKSArIAogICAgICAgc2NhbGVfeF9jb250aW51b3VzKCJZZWFyIHJlbW9kZWxlZCIsbGltaXRzPWMoMTk3MCwyMDE4LjUpLGJyZWFrcz1zZXEoMTkwMCwyMDIwLDUpKSArIAogICAgICB0aGVtZV9idygpCiApCmBgYApTbywgb3ZlcmFsbCB2ZXJ5IGxpdHRsZSBwYXJraW5nIHNxdWFyZSBmb290YWdlIGlzIHJlbW9kZWxlZCBpbiBtb3N0IHllYXJzLCB3aXRoIG1hbnkgeWVhcnMgaGF2aW5nIG5vIHJlbW9kZWxlZCBwYXJraW5nLCBidXQgaW4gYSBmZXcgeWVhcnMgaXQganVtcHMgdXAgbm90YWJseSAtLSBmb3IgaW5zdGFuY2UsIGluIDIwMTQuCgpgYGB7cn0KZ2dzYXZlKHBsb3Q9eWVhcnN1bW1fcGFya2luZ3Byb3BfcGxvdCwiZmlndXJlcy9wcm9wX2FyZWFwYXJraW5nX3llYXIucGRmIixoZWlnaHQ9Nyx3aWR0aD0xMCkKYGBgCgojIEdlb2dyYXBoaWMgZHluYW1pY3MKTm93IGxldCdzIHNlZSB3aGVyZSB0aGVzZSBwYXJraW5nIHBhcmNlbHMgZXhpc3QgaW4gQm9zdG9uLiBUbyBkbyB0aGlzIHdlJ3JlIGdvaW5nIHRvIHVzZSB0aGUgc3BhdGlhbCBmaWxlcyBmcm9tIEJBUkkuCmBgYHtyfQpsaWJyYXJ5KGxlYWZsZXQpCmxpYnJhcnkoUkNvbG9yQnJld2VyKSAjIGNvbG9yIHNjYWxlcwpsaWJyYXJ5KGNsYXNzSW50KSAjIGNvbG9yIHNjYWxlcwpsaWJyYXJ5KHNjYWxlcykKCnBhcmNlbHNfc2hwIDwtIHN0X3JlYWQoZHNuPXBhc3RlMChCQVJJZHJpdmVfcGF0aCwiR2VvZ3JhcGhpY2FsIEluZnJhc3RydWN0dXJlL0RhdGEvR2VvZ3JhcGhpY2FsIEluZnJhc3RydWN0dXJlIDIwMTgvRGF0YS9Cb3N0b25QYXJjZWxzMjAxOCIpLGxheWVyPSJQYXJjZWxzMjAxOCIpCgpgYGAKTm93IHRoYXQgdGhlIGRhdGEgaXMgY29tYmluZWQgd2l0aCBnZW9ncmFwaGljIHNoYXBlZmlsZXMsIGxldCdzIG1ha2Ugc29tZSBzaW1wbGUgdmlzdWFscwoKYGBge3J9CiMgYWRkIHBhcmtpbmcgdmFyaWFibGUgaW50byBzaGFwZWZpbGU6CnBhcmNlbHNfc2hwJHBhcmtpbmcgPC0gcGFyY2VsX2RhdGEkcGFya2luZ1ttYXRjaChwYXJjZWxzX3NocCRMbl9QX0lELHBhcmNlbF9kYXRhJExhbmRfUGFyY2VsX0lEKV0KCgojIHBkZigiZmlndXJlcy9uZXdjb25fcHBfY3RfMjAxNy5wZGYiKQojIHBhcihtYXI9YygyLDIsNCwyKSkKcGxvdChzdF9nZW9tZXRyeShzdWJzZXQocGFyY2Vsc19zaHAscGFya2luZz09MSkpLGNvbD0iZ3JleSIpCiMgdGl0bGUobWFpbj0iRGVtb2dyYXBoaWMgY2hhbmdlLCBwcmUtMjAxNSIpCiMgZGV2Lm9mZigpCmBgYAoKTm93IGxldHMgbWFrZSBzb21lIGJldHRlciBtYXBzOgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShzcCk7bGlicmFyeShtYXB0b29scykKbGlicmFyeShwcm9qNCkKbGlicmFyeShyZ2RhbCkKbGlicmFyeShnZ21hcCkKbGlicmFyeShjbGFzc0ludCkKCgpib3N0b25fYmJveCA8LSBzdF9iYm94KHBhcmNlbHNfc2hwLGY9MC4xKQpib3N0b25fYmJveCA8LSBhcy5udW1lcmljKGJvc3Rvbl9iYm94KQpuYW1lcyhib3N0b25fYmJveCkgPC0gYygibGVmdCIsImJvdHRvbSIsInJpZ2h0IiwidG9wIikKYm9zdG9uX2Jib3gyIDwtIHN0X2Jib3gocGFyY2Vsc19zaHAsZj0wKQpib3N0b25fYmJveDIgPC0gYXMubnVtZXJpYyhib3N0b25fYmJveDIpCm5hbWVzKGJvc3Rvbl9iYm94MikgPC0gYygibGVmdCIsImJvdHRvbSIsInJpZ2h0IiwidG9wIikKCnBhcmNlbHNfc2hwMiA8LSBzZjo6YXNfU3BhdGlhbChwYXJjZWxzX3NocCkKYm9zdG9uX2Jib3gzIDwtIG1ha2VfYmJveChwYXJjZWxzX3NocDJAYmJveFsxLF0scGFyY2Vsc19zaHAyQGJib3hbMixdLGY9MC4xKQoKYm9zdG9uX2Jhc2UgPC0gZ2V0X3N0YW1lbm1hcChiYm94PWJvc3Rvbl9iYm94Mywgem9vbT0xMiwgY29sb3I9ImNvbG9yIiwKICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2UgPSAic3RhbWVuIiwgbWFwdHlwZT0idG9uZXIiLCBjcm9wPVQpCgooYjAgPC0gZ2dtYXAoYm9zdG9uX2Jhc2UsIGV4dGVudD0iZGV2aWNlIixsZWdlbmQ9Im5vbmUiLG1hcHJhbmdlPVQpKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgYjEgPC0gYjAgKyAKIyAgCWdlb21fcG9seWdvbihkYXRhPXBhcmNlbHNfc2hwMlt3aGljaChwYXJjZWxzX3NocDIkcGFya2luZz09MSldLCBhZXMoeD1sb24seT1sYXQpLCBjb2xvdXIgPSAicmVkIiwgZmlsbCA9ICJncmV5IikgKwojICAJZ2VvbV9wb2x5Z29uKGRhdGE9cGFyY2Vsc19zaHAyW3doaWNoKHBhcmNlbHNfc2hwMiRwYXJraW5nPT0wKSxdLCBhZXMoeD1sb24seT1sYXQpLCBjb2w9ImJsdWUiLGZpbGw9TkEpICsgCiMgIAl0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuODUsMC4xNSkscGxvdC5tYXJnaW4gPSB1bml0KGMoMC4xLDAuMSwwLjEsMC4xKSwiY20iKSkKCihiMSA8LSBiMCArIAogIGNvb3JkX3NmKGNycyA9IHN0X2Nycyg0MzI2KSkgKwogCWdlb21fc2YoZGF0YT1jdHMsY29sPSJkYXJrZ3JleSIsbHdkPTAuMSxpbmhlcml0LmFlcz1GKSArCglnZW9tX3NmKGRhdGE9c3Vic2V0KHBhcmNlbHNfc2hwLHBhcmtpbmc9PTEpLGNvbD12dHVycSxpbmhlcml0LmFlcz1GKQopCmBgYApUaGlzIG1hcCBzcGF0aWFsbHkgZGVtb25zdHJhdGVzIHdoYXQgdGhlIGNoYXJ0cyBzaG93ZWQ6IG9mZi1zdHJlZXQgcGFya2luZyAocGxvdHRlZCBpbiB0dXJxdW9pc2Ugb24gdGhpcyBtYXApIGlzIGluY3JlZGlibHkgY29uY2VudHJhdGVkIChyZWxhdGl2ZSB0byB0b3RhbCBhcmVhKSBpbiB0aGUgZG93bnRvd24gYXJlYXMgb2YgQm9zdG9uLgoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cmdnc2F2ZShiMSxmaWxlbmFtZSA9ICJmaWd1cmVzL3BhcmtpbmdfcGFyY2Vsc19nZy5wZGYiLGhlaWdodD03LHdpZHRoPTkpCgpib3N0b25fYmFzZV9iZyA8LSBnZXRfc3RhbWVubWFwKGJib3g9Ym9zdG9uX2Jib3gzLCB6b29tPTEyLCBjb2xvcj0iYnciLAoJCQkJCQkJCQkJCQkJCXNvdXJjZT0ic3RhbWVuIixtYXB0eXBlID0gInRvbmVyLWxpdGUiLGNyb3A9VCkKCmIwX2JnIDwtIGdnbWFwKGJvc3Rvbl9iYXNlX2JnLCBleHRlbnQ9ImRldmljZSIsbGVnZW5kPSJub25lIixtYXByYW5nZT1UKQoKKGIxX2JnIDwtIGIwX2JnICsgCiAgY29vcmRfc2YoY3JzID0gc3RfY3JzKDQzMjYpKSArCglnZW9tX3NmKGRhdGE9c3Vic2V0KHBhcmNlbHNfc2hwLHBhcmtpbmc9PTEpLGNvbD12dHVycSxpbmhlcml0LmFlcz1GKQopCmBgYAoKYGBge3J9Cmdnc2F2ZShiMV9iZyxmaWxlbmFtZSA9ICJmaWd1cmVzL3BhcmtpbmdfcGFyY2Vsc19saXRlLnBkZiIsaGVpZ2h0PTcsd2lkdGg9OSkKYGBgCgoKT24gYSBwb2xpY3kgbm90ZSwgdGhlc2Ugc3VtbWFyaWVzIHBvaW50IG91dCBvbmUgd2F5IGluIHdoaWNoIHRyYW5zcG9ydGF0aW9uIHJlc291cmNlcyBjdXJyZW50bHkgZXhpc3QgaW4gdGhlIENpdHkuIEFzIEJvc3RvbiBtb3ZlcyB0b3dhcmRzIGEgbW9yZSBjbGltYXRlLWZyaWVuZGx5IHJlc2lsaWVuY2UgcGxhbiwgbGV2ZXJhZ2luZyB0aGUgYXJlYSBkZWRpY2F0ZWQgdG8gY2FycyB0byBpbnN0ZWFkIHByaW9yaXRpemUgbm9uLWRyaXZpbmcgZm9ybXMgb2YgdHJhbnNwb3J0YXRpb24gd2lsbCBiZSBpbXBvcnRhbnQuIEN1cnJlbnRseSwgZGVkaWNhdGluZyBzbyBtdWNoIG9mIHRoZSBkb3dudG93biBuZWlnaGJvcmhvb2RzIHRvIHBhcmtpbmcgb25seSBzZXJ2ZXMgdG8gKmluY3JlYXNlKiB0aGUgbnVtYmVyIG9mIGNhcnMgdGhlcmUsIHdoaWNoIHNlZW1zIGNvdW50ZXJpbnR1aXRpdmUgZm9yIHRyYWZmaWMgYW5kIHVyYmFuIHBsYW5uaW5nIG1vcmUgYnJvYWRseS4gSWYgdGhlIENpdHkgb2YgQm9zdG9uIHdhbnRlZCB0byBkZWNyZWFzZSB0cmFmZmljIGluIHRoZXNlIGNlbnRyYWwgbmVpZ2hib3Job29kcyBhbmQgZGVjcmVhc2UgdGhlIG51bWJlciBvZiBjYXJzIGVudGVyaW5nIHN1Y2ggZGVuc2UgbmVpZ2hib3Job29kcywgZGVkaWNhdGluZyAqbGVzcyogb2YgdGhlIGFyZWEgaW4gdGhlc2UgbmVpZ2hib3Job29kcyB0byBjYXJzIHdvdWxkIGJlIGEgZ29vZCBmaXJzdCBzdGVwLgoKTW9yZSBicm9hZGx5LCB0aGVzZSBzdW1tYXJpZXMgYW5kIHZhcmlvdXMgdmlzdWFscyB0b2dldGhlciBkZW1vbnN0cmF0ZSB0aGUgdXNlIG9mIEJBUkkncyBnZW9ncmFwaGljYWwgaW5mcmFzdHJ1Y3R1cmUgZGF0YXNldCBtb3JlIGdlbmVyYWxseTogZWFzaWx5IGJlaW5nIGFibGUgdG8gc3VtbWFyaXplIGluZm9ybWF0aW9uIGF0IHZhcmlvdXMgZ2VvZ3JhcGhpYyBsZXZlbHMgYWNyb3NzIHRoZSBDaXR5LgoKYGBge3J9CiMgdG1fc2hhcGUoc3Vic2V0KHBhcmNlbHNfc2hwLHBhcmtpbmc9PTEpKSArIAojICAgICAgIHRtX2ZpbGwoY29sID0gdnR1cnEsdGl0bGUgPSAiUGFya2luZyBwYXJjZWxzIikKCmBgYA==