Bring in the SW audit file from the BARI shared Google Drive and take a look at it. This should be the Sidewalk Audit conducted in… what year?
sw_pts <- st_read(dsn = "~/Google Drive/BARI Research Team Data Library/StreetCaster/Sidewalk Conditions T1/",layer="Sidewalk Centroids")
Reading layer `Sidewalk Centroids' from data source `/Users/justin/Google Drive/BARI Research Team Data Library/StreetCaster/Sidewalk Conditions T1' using driver `ESRI Shapefile'
Simple feature collection with 27388 features and 28 fields
geometry type: POINT
dimension: XY
bbox: xmin: 741131.2 ymin: 2909796 xmax: 801864.4 ymax: 2969943
epsg (SRID): NA
proj4string: +proj=lcc +lat_1=41.71666666666667 +lat_2=42.68333333333333 +lat_0=41 +lon_0=-71.5 +x_0=199999.9999999999 +y_0=750000 +datum=NAD83 +units=us-ft +no_defs
sw_pts <- st_read(dsn = "~/Google Drive/BARI Research Team Data Library/StreetCaster/Sidewalk Conditions T1/",layer="Sidewalk Centroids")
Reading layer `Sidewalk Centroids' from data source `/Users/justin/Google Drive/BARI Research Team Data Library/StreetCaster/Sidewalk Conditions T1' using driver `ESRI Shapefile'
Simple feature collection with 27388 features and 28 fields
geometry type: POINT
dimension: XY
bbox: xmin: 741131.2 ymin: 2909796 xmax: 801864.4 ymax: 2969943
epsg (SRID): NA
proj4string: +proj=lcc +lat_1=41.71666666666667 +lat_2=42.68333333333333 +lat_0=41 +lon_0=-71.5 +x_0=199999.9999999999 +y_0=750000 +datum=NAD83 +units=us-ft +no_defs
sw_poly <- st_read(dsn = "~/Google Drive/BARI Research Team Data Library/StreetCaster/Sidewalk Conditions T1/",layer="SWK_ANALYSIS")
Reading layer `SWK_ANALYSIS' from data source `/Users/justin/Google Drive/BARI Research Team Data Library/StreetCaster/Sidewalk Conditions T1' using driver `ESRI Shapefile'
Simple feature collection with 27388 features and 27 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 741058.7 ymin: 2909733 xmax: 801961.7 ymax: 2969955
epsg (SRID): NA
proj4string: +proj=lcc +lat_1=41.71666666666667 +lat_2=42.68333333333333 +lat_0=41 +lon_0=-71.5 +x_0=199999.9999999999 +y_0=750000 +datum=NAD83 +units=us-ft +no_defs
Basic summary stats:
summary(sw_pts$TIMESTAMP)
2/2/2012 3/26/2012 11/18/2011 3/27/2012 2009-08-05 10:20:04 1/16/2012
214 144 143 136 129 123
2/14/2012 2/6/2012 11/15/2011 2/9/2012 12/16/2011 12/31/2011
117 115 112 108 107 106
2/7/2012 11/21/2011 12/12/2011 2/23/2012 1/3/2012 1/9/2012
105 103 99 98 95 95
2/1/2012 12/6/2011 1/24/2012 12/13/2011 1/18/2012 11/28/2011
93 92 90 89 88 88
2/13/2012 2/8/2012 1/25/2012 12/8/2011 12/9/2011 11/29/2011
88 88 85 85 84 82
12/1/2011 1/5/2012 12/15/2011 1/26/2012 2/15/2012 2/24/2012
80 78 78 76 75 74
11/22/2011 1/6/2012 12/14/2011 2/21/2012 11/30/2011 1/19/2012
73 72 71 71 69 68
1/31/2012 1/27/2012 11/23/2011 1/30/2012 11/16/2011 12/7/2011
66 65 65 57 56 55
11/17/2011 2/22/2012 2011-12-05 16:09:00 2/3/2012 2012-01-09 14:39:29 2009-11-20 14:26:02
54 52 33 31 29 23
2012-02-29 10:29:09 2012-01-09 12:15:19 12/2/2011 2012-01-13 15:06:08 2010-03-10 12:06:45 2011-10-24 15:18:40
23 22 21 19 18 18
2010-06-16 11:50:03 2011-12-05 16:47:10 2012-01-23 10:57:42 2011-12-05 16:48:23 2012-02-29 10:27:13 2011-07-25 11:48:10
16 16 16 15 15 14
2011-08-29 11:21:35 2011-10-24 15:15:45 2012-02-29 10:37:03 2010-03-10 15:23:10 2010-06-16 11:43:44 2011-05-05 14:03:15
14 14 14 13 13 13
2011-05-05 14:04:02 2012-02-29 10:32:33 2011-10-24 15:17:45 2012-01-09 14:00:13 2012-02-28 07:50:13 2012-02-29 10:36:30
13 13 12 12 12 12
2010-02-23 10:22:11 2010-03-10 16:04:42 2010-06-18 12:57:31 2011-08-01 09:57:05 2012-01-03 12:16:36 2012-01-09 10:04:34
11 11 11 11 11 11
2012-01-23 11:28:56 2012-02-29 10:32:01 2012-05-19 15:18:01 2010-03-10 15:36:40 2011-04-11 16:42:58 2011-11-16 15:20:42
11 11 11 10 10 10
2011-12-05 11:58:05 2012-01-09 10:23:32 2012-02-22 11:39:59 2009-12-04 08:57:15 2011-04-25 11:53:19 2012-01-03 15:41:12
10 10 10 9 9 9
2012-01-11 14:02:05 2012-02-13 09:06:34 2012-02-29 10:38:25 (Other)
9 9 9 22135
sw_pts$date2 <- parse_date_time(x = as.character(sw_pts$TIMESTAMP),
orders=c("mdY","Ymd HMS"), truncated = 3)
summary(sw_pts$date2) # goes from 2008 through 2012
Min. 1st Qu. Median Mean 3rd Qu.
"2008-12-04 12:59:15" "2011-06-03 08:27:06" "2011-12-16 12:57:41" "2011-09-02 00:27:31" "2012-02-10 08:48:37"
Max.
"2012-05-31 14:22:01"
# pdf("figures/audit1_timeline.pdf",height=4,width=10)
hist(sw_pts$date2,breaks = "months",main="Timeline of Audit 1",xlab="Date of Assessment") # mostly in the early part of 2012.

# dev.off()
(dateplot1 <- ggplot(sw_pts) +
geom_histogram(aes(x=date2)) +
scale_x_datetime("Date of Assessment",date_minor_breaks="months",date_labels="%b %Y") +
theme_bw())

rr ggsave(dateplot1,file=/timeline1.pdf)
Saving 7 x 7 in image
So, it looks like this is the quality of the sidewalks
Okay, time to bring in the SCI report from T2:
summary(sw_pts_t2)
SWK_ID MATERIAL SWK_WIDTH DISTRICT SWK_AREA PARENT SEG_ID
24478 : 13 CC :19494 6 :4434 SOUTH DORCHESTER: 3017 1135 : 20 WASHI1 : 285 TLBRO1_14828: 14
17868 : 6 BR : 1266 6.5 :3768 NORTH DORCHESTER: 2666 1210 : 19 CENTR6 : 239 DOONE1_122 : 6
17836 : 5 BC : 897 7 :2206 WEST ROXBURY : 2537 1163 : 18 DORCH1 : 196 SHAWM2_7336 : 6
372 : 5 CB : 526 7.5 :1634 DOWNTOWN : 2055 1334 : 18 RIVER1 : 162 SUMME9_1224 : 6
10342 : 4 UNK : 303 0 :1454 ALLSTON/BRIGHTON: 2041 1452 : 18 WASHI5 : 127 WESTV1_0 : 6
(Other):23297 (Other): 177 (Other):9839 (Other) :11014 (Other):23237 (Other):22321 (Other) :23292
NA's : 21 NA's : 688 NA's : 16 NA's : 21 NA's : 21 NA's : 21 NA's : 21
SIDE CG_ID Rpr_Yr New_SCI Recon_Date geometry
LEFT :11563 24258 : 13 Min. : 0.0 Min. : 0.00 Min. :2010-05-05 POINT :23351
RIGHT:11766 17759 : 6 1st Qu.: 0.0 1st Qu.: 45.00 1st Qu.:2014-04-16 epsg:NA : 0
NA's : 22 17728 : 5 Median : 0.0 Median : 73.00 Median :2015-08-10 +proj=lcc ...: 0
10277 : 4 Mean : 262.1 Mean : 65.48 Mean :2015-03-21
18301 : 4 3rd Qu.: 0.0 3rd Qu.: 91.00 3rd Qu.:2016-07-21
(Other):22901 Max. :2016.0 Max. :100.00 Max. :2016-11-18
NA's : 418 NA's :23094
Basic descriptives:
summary(sw_poly_t2$SWK_ID) # 5-digit ID numbers, but not unique?
24478 17868 17836 372 10342 17286 17289 18411 22898 23153 23614 24230 9830 11012 11206
13 6 5 5 4 4 4 4 4 4 4 4 4 3 3
17839 17855 17861 17959 18460 19071 19135 19233 19682 21372 21443 21746 21846 22041 22116
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
22145 22170 22181 22221 22600 23144 23645 24159 24395 24446 24487 24488 24633 5271 5505
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
10861 11202 11280 11611 11697 11731 11736 12181 12434 13964 15753 16593 16740 16741 16744
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
16748 16821 16890 16957 16968 17018 17090 17142 17496 17834 17835 17860 17968 1829 18401
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
18404 18405 18534 18555 18605 18836 18948 19007 1937 20553 20666 21204 21209 21368 21447
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
21702 21887 21892 21897 21934 21937 22043 22099 (Other) NA's
2 2 2 2 2 2 2 2 23063 21
summary(sw_poly_t2$New_SCI) # 0-100 Sidewalk Condition Index
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.00 45.00 73.00 65.48 91.00 100.00
Spatial visuals
Plot SCI:
New data:
Trying to match up geographies across two audits:


So no, those don’t match up. That’s a pain.
Check if the sidewalk segments match up from T1 to T2 at all
st_crs(sw_poly); st_crs(sw_poly_t2)
Coordinate Reference System:
No EPSG code
proj4string: "+proj=lcc +lat_1=41.71666666666667 +lat_2=42.68333333333333 +lat_0=41 +lon_0=-71.5 +x_0=199999.9999999999 +y_0=750000 +datum=NAD83 +units=us-ft +no_defs"
Coordinate Reference System:
No EPSG code
proj4string: "+proj=lcc +lat_1=41.71666666666667 +lat_2=42.68333333333333 +lat_0=41 +lon_0=-71.5 +x_0=199999.9999999999 +y_0=750000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=us-ft +no_defs"
Let’s look at some subsets to see how to match them spatially

Matching sidewalks segments across waves of audits
trying with centroid points:
rr
sw_pts_t2 <- st_transform(sw_pts_t2,st_crs(sw_pts)) # distmat <- st_distance(sw_pts,sw_pts_t2) # in ft (US) # closest <- apply(distmat,1,function(x){which(x==min(x))}) # closest_dist <- apply(distmat,1,min) # distance in feet # closest[10875] # plot(st_geometry(sw_poly_t2[c(13584,22947),_SCI])) # these are duplicates, that’s why! # closest[10875] <- 13584 # manual fix # matchtable <- tibble(index_t1 = 1:length(unlist(closest)), # closest_index = unlist(closest), # closest_dist = closest_dist, # SWK_ID_t1 = sw_pts\(SWK_ID) # matchtable\)SWK_ID_t2 <- sw_pts_t2\(SWK_ID[matchtable\)closest_index] # summary(matchtable\(closest_dist) # plot(st_geometry(sw_poly %>% filter(SWK_ID %in% matchtable\)SWK_ID_t1[8]))) # these should be overlapping # plot(st_geometry(sw_poly_t2 %>% filter(SWK_ID %in% matchtable$SWK_ID_t2[8])),add=T,col=) # shows that 44 ft apart in centroids not much
What about looking at some segments that are farther apart?
rr # matchtable %>% filter(closest_dist>1000)
rr # plot(st_geometry(sw_poly %>% filter(SWK_ID %in% matchtable\(SWK_ID_t1[8]))) # these should be overlapping # plot(st_geometry(sw_poly_t2 %>% filter(SWK_ID %in% matchtable\)SWK_ID_t2[8])),add=T,col=) # shows that 44 ft apart in centroids not much # plot(st_geometry(sw_poly %>% filter(SWK_ID %in% matchtable\(SWK_ID_t1[1181]))) # these should be overlapping # plot(st_geometry(sw_poly_t2 %>% filter(SWK_ID %in% matchtable\)SWK_ID_t2[1181])),add=T,col=) # shows that even 1047 ft apart in centroids not much, and probably a correct match! # #{r} # plot(st_geometry(sw_poly %>% filter(SWK_ID %in% matchtable\(SWK_ID_t1[1181:1187]))) # these should be overlapping # plot(st_geometry(sw_poly_t2 %>% filter(SWK_ID %in% matchtable\)SWK_ID_t2[1181:1187])),add=T,col=) # shows that even 1047 ft apart in centroids not much, and probably a correct match!
What this seems to be showing is that actually there are just some sidewalk segments that are missing in Wave 2 of the SCI survey. Shows we should also do the matching in the opposite direction - e.g. find closest segment to each SWK in wave 2 from wave 1.
Matching in opposite direction (wave 1 to wave 2):
rr # distmat2 <- st_distance(sw_pts_t2,sw_pts) # in ft (US) # closest2 <- apply(distmat2,1,function(x){which(x==min(x))}) # closest_dist2 <- apply(distmat2,1,min) # distance in feet # matchtable2 <- tibble(index_t2 = 1:length(unlist(closest2)), # closest_index = unlist(closest2), # closest_dist = closest_dist2, # SWK_ID_t2 = as.numeric(as.character(sw_pts_t2\(SWK_ID))) # matchtable2\)SWK_ID_t1 <- sw_pts\(SWK_ID[matchtable2\)closest_index] # summary(matchtable2$closest_dist) # maximum 1114 ft, which is totally allowable
Now, time to match and create over-time change metrics
rr # matchtable2\(SCI_t1 <- sw_pts\)SCI[match(matchtable2\(SWK_ID_t1,sw_pts\)SWK_ID)] # matchtable2\(SCI_t2 <- sw_pts_t2\)New_SCI[match(matchtable2\(SWK_ID_t2,sw_pts_t2\)SWK_ID)] # matchtable2 <- matchtable2 %>% # mutate(SCI_change = SCI_t2-SCI_t1, # SCI_change_perc = SCI_change/SCI_t1) # summary(matchtable2) # on average, got better by 0.1, but median = -1.39. percent messed up b/c some have SCI=0
Time to match these data back to the polygons
summary(sw_poly_t2)
SWK_ID MATERIAL SWK_WIDTH DISTRICT SWK_AREA PARENT
Min. : 1 CC :20160 6 : 4584 SOUTH DORCHESTER: 3117 20209 : 169 WASHI1 : 295
1st Qu.: 6355 BR : 1368 6.5 : 3800 NORTH DORCHESTER: 2710 16857 : 36 CENTR6 : 241
Median :12724 BC : 909 7 : 2272 WEST ROXBURY : 2543 12951 : 25 DORCH1 : 198
Mean :12628 CB : 562 7.5 : 1654 DOWNTOWN : 2151 18198 : 25 TLBRO1 : 180
3rd Qu.:18907 UNK : 312 0 : 1510 ALLSTON/BRIGHTON: 2063 2598 : 22 RIVER1 : 162
Max. :24778 (Other): 191 (Other):10371 (Other) :11502 (Other):23809 (Other):23010
NA's :441 NA's : 1025 NA's : 336 NA's : 441 NA's : 441 NA's : 441
SEG_ID SIDE CG_ID Rpr_Yr New_SCI Recon_Date index_t2
TLBRO1_14828: 170 LEFT :11839 24258 : 169 Min. : 0.0 Min. : 0.00 Min. :2010-05-05 Min. : 1
SUMME9_1224 : 36 RIGHT:12245 17759 : 36 1st Qu.: 0.0 1st Qu.: 45.00 1st Qu.:2013-09-23 1st Qu.: 6118
SHAWM2_7336 : 26 NA's : 443 17728 : 25 Median : 0.0 Median : 73.00 Median :2014-03-31 Median :12235
AMERI1_1688 : 25 10277 : 16 Mean : 254.7 Mean : 65.67 Mean :2014-07-21 Mean :12204
DOONE1_122 : 20 18301 : 16 3rd Qu.: 0.0 3rd Qu.: 92.00 3rd Qu.:2015-08-24 3rd Qu.:18352
(Other) :23809 (Other):23407 Max. :2016.0 Max. :100.00 Max. :2016-11-18 Max. :23351
NA's : 441 NA's : 858 NA's :23833
closest_index closest_dist SWK_ID_t1 SCI_t1 SCI_t2 SCI_change SCI_change_perc
Min. : 1 Min. : 0.000 Min. : 2 Min. : 0.00 Min. : 0.00 Min. :-100.0000 Min. :-1.0000
1st Qu.: 7038 1st Qu.: 1.953 1st Qu.: 8472 1st Qu.: 44.97 1st Qu.: 45.00 1st Qu.: -10.3604 1st Qu.:-0.1636
Median :13800 Median : 4.838 Median :15801 Median : 71.65 Median : 73.00 Median : -1.2045 Median :-0.0185
Mean :13801 Mean : 20.522 Mean :15854 Mean : 65.45 Mean : 65.69 Mean : 0.2373 Mean : Inf
3rd Qu.:20685 3rd Qu.: 15.781 3rd Qu.:23574 3rd Qu.: 91.56 3rd Qu.: 92.00 3rd Qu.: 4.5861 3rd Qu.: 0.0898
Max. :27388 Max. :1114.329 Max. :30757 Max. :100.00 Max. :100.00 Max. : 100.0000 Max. : Inf
NA's :350
TLID BG_GEOID CT_GEOID geometry
Min. : 85694288 Min. :2.503e+11 Min. :2.503e+10 MULTIPOLYGON :24527
1st Qu.: 85701197 1st Qu.:2.503e+11 1st Qu.:2.503e+10 epsg:NA : 0
Median : 85705981 Median :2.503e+11 Median :2.503e+10 +proj=lcc ...: 0
Mean :130739389 Mean :2.503e+11 Mean :2.503e+10
3rd Qu.: 85720558 3rd Qu.:2.503e+11 3rd Qu.:2.503e+10
Max. :645513578 Max. :2.503e+11 Max. :2.503e+10
NA's :41 NA's :71
Matching to Census geographies:
Loading Census geographies:
Map Census geographies:

# nicer plots:
boston_base <- get_map(location="Boston Latin Academy, Boston, MA",zoom=12, color="color",maptype="terrain",crop=T,source="google")
Error in data.frame(ll.lat = ll[1], ll.lon = ll[2], ur.lat = ur[1], ur.lon = ur[2]) :
arguments imply differing number of rows: 0, 1
rr (b1 <- b0 + geom_sf(data=boston_tracts,color = ,alpha=0.4,inherit.aes = F,guide=F,aes(fill=GEOID)) )
Error in UseMethod(\element_grob\) :
no applicable method for 'element_grob' applied to an object of class \NULL\

First match up the closest TLID
sum(!is.na(sw_pts_streets$TLID)) # got all of them!
[1] 24527
Visualize
Next, going to plot the sidewalk conditions at various geographies:

Street-level SCI changes
tmap_mode("view")
Error in tmap_mode("view") : could not find function "tmap_mode"
This map shows where sidewalk conditions got better between these two surveys (areas in green, with positive values of change in SCI) and where conditions got worse (red, or negative values of change in SCI). Looks like things improved in Jamaica Plain and East Bostn, but got worse in Dorchester and the northern edges of Charlestown.
Sidewalk conditions within tracts:
# join in CT of sidewalk segment:
boston_tracts <- st_transform(boston_tracts,st_crs(sw_pts_streets))
Error in st_crs(sw_pts_streets) : object 'sw_pts_streets' not found
Tract SCI changes
(b2 <- b0 +
geom_polygon(data=boston_tracts3,aes(x=long,y=lat,group=group,fill = mean_change_sci)) +
theme(legend.key.width = unit(0.75, "cm"),legend.key.height = unit(2, "cm"),
axis.line = NULL,panel.border = NULL,panel.grid = NULL) +
theme_bw()
)
Error: object 'b0' not found
rr ggsave(b2,filename = /ct_mean_change_sci.png) # interactive plot: tmap_mode() tm_shape(boston_tracts2) + tm_fill(col = _change_sci,title = in SCI, palette=, n=20,midpoint=0, id = )
As with the segment-level map, this shows that conditions improved in JP and East Boston, but got worse in Mattapan/Dorchester and Charlestown.
Replicate this for BGs:
rr # join in BG of sidewalk segment: boston_bg <- st_transform(boston_bg,st_crs(sw_pts_streets)) sw_pts_bg <- st_join(x=sw_pts_streets,y=boston_bg,join=st_within,left=T)
bg_summ <- sw_pts_bg %>% as_tibble() %>% group_by(GEOID) %>% summarize(mean_sci_t1 = mean(SCI_t1,na.rm=T), mean_sci_t2 = mean(SCI_t2,na.rm=T), mean_change_sci = mean(SCI_change,na.rm=T))
boston_bg2 <- left_join(boston_bg,bg_summ,by=) # Output the BG-level sf data for other uses: save(boston_bg2,file = /boston_bg_sci.RData)
rr (b2 <- ggplot() + geom_sf(data=boston_bg2,aes(fill = mean_change_sci),alpha=1,inherit.aes = F,show.legend = ) )
BG SCI changes
rr ggsave(b2,filename = /bg_mean_change_sci.png) # interactive plot: tm_shape(boston_bg2) + tm_fill(col = _change_sci,title = in SCI, palette=, n=20,midpoint=0, id = )
This BG-level map corroborates the tract- and street-level visuals.
Adding census geographies back to crosswalk table
rr # matchtable2\(TLID <- sw_pts_streets\)TLID[match(matchtable2\(SWK_ID_t2,sw_pts_streets\)SWK_ID)] # matchtable2\(BG_GEOID <- sw_pts_bg\)GEOID[match(matchtable2\(SWK_ID_t2,sw_pts_bg\)SWK_ID)] # matchtable2\(CT_GEOID <- sw_pts_ct\)GEOID[match(matchtable2\(SWK_ID_t2,sw_pts_ct\)SWK_ID)] # write.csv(matchtable2,/SWK_matched_cwalk.csv,row.names = F) matchtable2 <- read.csv(/SWK_matched_cwalk.csv,stringsAsFactors = F)
Adding 311 data to analyses
First need to bring in 311 data from between the two sidewalk audits:
Matching 311 calls to census geographies:
rr sw_calls_pts\(SWK_ID_t2 <- NA for(i in 1:nrow(sw_calls)){ sw_calls_pts\)SWK_ID_t2[i] <- as.character( # match to closest sidewalk segment centroid sw_pts_streets\(SWK_ID[which.min(st_distance(sw_calls_pts[i,\geometry\], sw_pts_streets))] ) } sum(!is.na(sw_calls_pts\)SWK_ID_t2)) sw_calls_pts\(TLID <- matchtable2\)TLID[match(sw_calls_pts\(SWK_ID_t2,matchtable2\)SWK_ID_t2)] sw_calls_pts\(BG_GEOID <- matchtable2\)BG_GEOID[match(sw_calls_pts\(SWK_ID_t2,matchtable2\)SWK_ID_t2)] sw_calls_pts\(CT_GEOID <- matchtable2\)CT_GEOID[match(sw_calls_pts\(SWK_ID_t2,matchtable2\)SWK_ID_t2)] # save(sw_calls_pts,file = /sw_calls_geomatched.RData) load(file = /sw_calls_geomatched.RData)
Aggregating 311 data at geographic levels:
Street-level 311 visuals:
rr streets_summ_311 <- sw_calls_pts %>% as_tibble() %>% group_by(TLID) %>% summarize(n_calls = n()) %>% as.data.frame()
boston_streets_sci\(TLID <- as.numeric(boston_streets_sci\)TLID) boston_streets_sci <- left_join(boston_streets_sci,streets_summ_311,by=) boston_streets_sci\(n_calls[is.na(boston_streets_sci\)n_calls)] <- 0 boston_streets_sci\(nonzero_calls <- as.numeric(boston_streets_sci\)n_calls>0) boston_streets_sci\(log_calls <- log1p(boston_streets_sci\)n_calls) boston_streets_sci\(bin_calls <- cut(boston_streets_sci\)n_calls,breaks = c(-Inf,1,2,4,6,Inf), labels=c(,-2,-4,-6,+)) boston_streets_sci <- boston_streets_sci %>% mutate(change_sci_binned = cut(mean_change_sci, breaks=c(-Inf, -30, 30, Inf), labels=c(,,))) tm_shape(boston_streets_sci) + tm_lines(col = _calls,title.col = # of 311 Sidewalk Calls,lwd=2, palette=, n=5, id = )
Tract 311 visuals:
rr ct_summ_311 <- sw_calls_pts %>% as_tibble() %>% group_by(CT_GEOID) %>% summarize(n_calls = n()) %>% as.data.frame()
boston_tracts2\(GEOID <- as.numeric(boston_tracts2\)GEOID) boston_tracts2 <- left_join(boston_tracts2,ct_summ_311,by=c(Â = _GEOID)) boston_tracts2\(n_calls[is.na(boston_tracts2\)n_calls)] <- 0 boston_tracts2\(log_calls <- log1p(boston_tracts2\)n_calls) boston_tracts2\(bin_calls <- cut(boston_tracts2\)n_calls,breaks = c(-Inf,10,25,40,55,Inf), labels=c(-10,1-25,6-40,1-55,6+)) boston_tracts2 <- boston_tracts2 %>% mutate(change_sci_binned = cut(mean_change_sci, breaks=c(-Inf, -10, 10, Inf), labels=c(,,)))
tm_shape(boston_tracts2) + tm_fill(col = _calls,title = # of 311 Sidewalk Calls, palette=, n=5,midpoint=, id = )
How do 311 calls and SW quality differences match up at various aggregate levels?
Tract-level:
summary(lm((boston_tracts2$change_sci_binned=="Better") ~ boston_tracts2$n_calls*(boston_tracts2$mean_sci_t1>median(boston_tracts2$mean_sci_t1,na.rm=T)))) # differential impact of calls: all insig except less likely to get better if nicer area
Call:
lm(formula = (boston_tracts2$change_sci_binned == "Better") ~
boston_tracts2$n_calls * (boston_tracts2$mean_sci_t1 > median(boston_tracts2$mean_sci_t1,
na.rm = T)))
Residuals:
Min 1Q Median 3Q Max
-0.40948 -0.31796 -0.06491 -0.04193 0.94358
Coefficients:
Estimate Std. Error
(Intercept) 0.412433 0.066670
boston_tracts2$n_calls -0.001476 0.001228
boston_tracts2$mean_sci_t1 > median(boston_tracts2$mean_sci_t1, na.rm = T)TRUE -0.336210 0.083694
boston_tracts2$n_calls:boston_tracts2$mean_sci_t1 > median(boston_tracts2$mean_sci_t1, na.rm = T)TRUE 0.001123 0.001349
t value Pr(>|t|)
(Intercept) 6.186 4.32e-09 ***
boston_tracts2$n_calls -1.202 0.231
boston_tracts2$mean_sci_t1 > median(boston_tracts2$mean_sci_t1, na.rm = T)TRUE -4.017 8.77e-05 ***
boston_tracts2$n_calls:boston_tracts2$mean_sci_t1 > median(boston_tracts2$mean_sci_t1, na.rm = T)TRUE 0.832 0.406
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3775 on 173 degrees of freedom
(1 observation deleted due to missingness)
Multiple R-squared: 0.1403, Adjusted R-squared: 0.1254
F-statistic: 9.409 on 3 and 173 DF, p-value: 8.565e-06
BG-level:
summary(lm((boston_bg2$change_sci_binned=="Better") ~ (boston_bg2$n_calls)*(boston_bg2$mean_sci_t1>median(boston_bg2$mean_sci_t1,na.rm=T)))) # differential impact of calls: nothing significant except nicer areas less likely to get better
Call:
lm(formula = (boston_bg2$change_sci_binned == "Better") ~ (boston_bg2$n_calls) *
(boston_bg2$mean_sci_t1 > median(boston_bg2$mean_sci_t1,
na.rm = T)))
Residuals:
Min 1Q Median 3Q Max
-0.35772 -0.34536 -0.04819 -0.03306 0.97703
Coefficients:
Estimate Std. Error t value
(Intercept) 3.577e-01 2.479e-02 14.429
boston_bg2$n_calls -6.178e-04 7.037e-04 -0.878
boston_bg2$mean_sci_t1 > median(boston_bg2$mean_sci_t1, na.rm = T)TRUE -3.051e-01 4.044e-02 -7.544
boston_bg2$n_calls:boston_bg2$mean_sci_t1 > median(boston_bg2$mean_sci_t1, na.rm = T)TRUE -1.257e-05 1.699e-03 -0.007
Pr(>|t|)
(Intercept) < 2e-16 ***
boston_bg2$n_calls 0.380
boston_bg2$mean_sci_t1 > median(boston_bg2$mean_sci_t1, na.rm = T)TRUE 1.88e-13 ***
boston_bg2$n_calls:boston_bg2$mean_sci_t1 > median(boston_bg2$mean_sci_t1, na.rm = T)TRUE 0.994
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3674 on 553 degrees of freedom
(1 observation deleted due to missingness)
Multiple R-squared: 0.1487, Adjusted R-squared: 0.1441
F-statistic: 32.2 on 3 and 553 DF, p-value: < 2.2e-16
street-level:
stats::cor(boston_streets_sci$mean_change_sci,y=boston_streets_sci$n_calls,use = "complete.obs")
Error in stats::cor(boston_streets_sci$mean_change_sci, y = boston_streets_sci$n_calls, :
supply both 'x' and 'y' or a matrix-like 'x'
Visualizing correlation between calls and change in sidewalk conditions:
rr plot(log1p(boston_streets_sci\(n_calls),boston_streets_sci\)mean_change_sci,xlim=c(0,4),pch=16,col=,main=segment-level,ylab=in sidewalk conditions,xlab=of 311 calls) # lines(lowess(boston_streets_sci\(mean_change_sci ~ log1p(boston_streets_sci\)n_calls)),col=) lines(lowess(boston_streets_sci\(mean_change_sci[which(boston_streets_sci\)mean_sci_t1<median(boston_streets_sci\(mean_sci_t1,na.rm=T))] ~ log1p(boston_streets_sci\)n_calls[which(boston_streets_sci\(mean_sci_t1<median(boston_streets_sci\)mean_sci_t1,na.rm=T))])),col=,lwd=2) lines(lowess(boston_streets_sci\(mean_change_sci[which(boston_streets_sci\)mean_sci_t1>median(boston_streets_sci\(mean_sci_t1,na.rm=T))] ~ log1p(boston_streets_sci\)n_calls[which(boston_streets_sci\(mean_sci_t1>median(boston_streets_sci\)mean_sci_t1,na.rm=T))])),col=,lwd=2)


Nicer bivariate visuals:


rr (street_bivariate <- ggplot(boston_streets_sci) + geom_point(aes(x=n_calls,y=mean_change_sci),col=) + scale_x_continuous(of 311 calls(log scale),trans=10,limits=c(0.8,50),breaks=c(1,5,10,20,40)) + scale_y_continuous(in sidewalk conditions, limits=c(-100,100), breaks=seq(-100,100,50), labels=c(\n-100(Worse),-50,,0,\(Better)\n100\n\)) + geom_smooth(data=subset(boston_streets_sci,mean_sci_t1>median(boston_streets_sci\(mean_sci_t1,na.rm=T)), aes(x=n_calls,y=mean_change_sci),col=\blue\,lwd=1,method=\loess\,se=F) + geom_smooth(data=subset(boston_streets_sci,mean_sci_t1<=median(boston_streets_sci\)mean_sci_t1,na.rm=T)), aes(x=n_calls,y=mean_change_sci),col=,lwd=1,method=,se=F) + annotate(,x=0.8,y=15,label=street segments in 2012,col=,size=3,hjust=0) + annotate(,x=0.8,y=-15,label=street segments in 2012,col=,size=3,hjust=0) + theme_bw() )
# Saving visuals
ggsave(tract_bivariate,file="figures/calls_changeSCI_ct.pdf",height=4,width=6)
ggsave(bg_bivariate,file="figures/calls_changeSCI_bg.pdf",height=4,width=6)
ggsave(street_bivariate,file="figures/calls_changeSCI_streets.pdf",height=4,width=6)
Demographic analyses
Now lets bring in demographics to do something more than bivariate analyses:
summary(lm(mean_change_sci ~ log1p(n_calls)*B19013_001E, data = boston_tracts3)) # nothing sig
Call:
lm(formula = mean_change_sci ~ log1p(n_calls) * B19013_001E,
data = boston_tracts3)
Residuals:
Min 1Q Median 3Q Max
-26.193 -6.871 -1.547 3.899 38.867
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.18393946 7.27526449 -0.025 0.980
log1p(n_calls) 0.39596671 2.15971702 0.183 0.855
B19013_001E 0.00006832 0.00010417 0.656 0.513
log1p(n_calls):B19013_001E -0.00001809 0.00002833 -0.639 0.524
Residual standard error: 12.23 on 165 degrees of freedom
(9 observations deleted due to missingness)
Multiple R-squared: 0.004897, Adjusted R-squared: -0.0132
F-statistic: 0.2707 on 3 and 165 DF, p-value: 0.8465
The main lessons coming out of these analyses are that: (1) Whiter and higher income tracts and BGs were more likely to have improvement in sidewalk conditions between the two sidewalk conditions audits; and (2) In tracts and BGs with more white residents and with higher levels of education, the number of 311 calls doesn’t seem to correlate with improvements in sidewalk conditions, but in tracts and BGs with fewer white residents and lower levels of education, the number of 311 calls is positively correlated with improvements in sidewalk conditions.
Visualizing these dynamics:





# saving plots:
ggsave(tract_bivariate_inc,file="figures/calls_changeSCI_ct_inc.pdf",height=4,width=6)
ggsave(bg_bivariate_inc,file="figures/calls_changeSCI_bg_inc.pdf",height=4,width=6)
ggsave(bg_bivariate_inc_lm,file="figures/calls_changeSCI_bg_inc_lm.pdf",height=4,width=6)
LS0tCnRpdGxlOiAiU3RyZWV0Y2FzdGVyIFNpZGV3YWxrIEF1ZGl0cyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0aWR5dGV4dCkKbGlicmFyeShtYXB0b29scykgCmxpYnJhcnkocmdkYWwpIApsaWJyYXJ5KFJnb29nbGVNYXBzKSAjIGdvb2dsZW1hcHMgQVBJIHRvb2wKbGlicmFyeShjbGFzc0ludCkgCmxpYnJhcnkoUkNvbG9yQnJld2VyKSAKbGlicmFyeShnZ3Bsb3QyKTsgbGlicmFyeShnZ21hcCkgCmxpYnJhcnkobWFwcyk7bGlicmFyeShtYXBkYXRhKQpsaWJyYXJ5KHJnZW9zKQpsaWJyYXJ5KHRpZHljZW5zdXMpCmNlbnN1c19hcGlfa2V5KFN5cy5nZXRlbnYoIkNFTlNVU19BUElfS0VZIikpCmxpYnJhcnkodGlncmlzKSAjIHRvIHB1bGwgY2Vuc3VzIHNoYXBlZmlsZXMgZnJvbSB0aGUgd2ViIEFQSQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHNwKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkobHVicmlkYXRlKQojIGxpYnJhcnkodG1hcCkKbGlicmFyeShmb3JlaWduKQojIGxpYnJhcnkobmxtZSkKYGBgCgoKCkJyaW5nIGluIHRoZSBTVyBhdWRpdCBmaWxlIGZyb20gdGhlIEJBUkkgc2hhcmVkIEdvb2dsZSBEcml2ZSBhbmQgdGFrZSBhIGxvb2sgYXQgaXQuClRoaXMgc2hvdWxkIGJlIHRoZSBTaWRld2FsayBBdWRpdCBjb25kdWN0ZWQgaW4uLi4gd2hhdCB5ZWFyPwpgYGB7ciwgZWNobz1UUlVFfQpzd19wdHMgPC0gc3RfcmVhZChkc24gPSAifi9Hb29nbGUgRHJpdmUvQkFSSSBSZXNlYXJjaCBUZWFtIERhdGEgTGlicmFyeS9TdHJlZXRDYXN0ZXIvU2lkZXdhbGsgQ29uZGl0aW9ucyBUMS8iLGxheWVyPSJTaWRld2FsayBDZW50cm9pZHMiKQpzd19wb2x5IDwtIHN0X3JlYWQoZHNuID0gIn4vR29vZ2xlIERyaXZlL0JBUkkgUmVzZWFyY2ggVGVhbSBEYXRhIExpYnJhcnkvU3RyZWV0Q2FzdGVyL1NpZGV3YWxrIENvbmRpdGlvbnMgVDEvIixsYXllcj0iU1dLX0FOQUxZU0lTIikKc3VtbWFyeShzd19wdHMpCmBgYAoKCkJhc2ljIHN1bW1hcnkgc3RhdHM6CmBgYHtyfQpzdW1tYXJ5KHN3X3B0cyRUSU1FU1RBTVApCnN3X3B0cyRkYXRlMiA8LSBwYXJzZV9kYXRlX3RpbWUoeCA9IGFzLmNoYXJhY3Rlcihzd19wdHMkVElNRVNUQU1QKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVycz1jKCJtZFkiLCJZbWQgSE1TIiksIHRydW5jYXRlZCA9IDMpCnN1bW1hcnkoc3dfcHRzJGRhdGUyKSAjIGdvZXMgZnJvbSAyMDA4IHRocm91Z2ggMjAxMgojIHBkZigiZmlndXJlcy9hdWRpdDFfdGltZWxpbmUucGRmIixoZWlnaHQ9NCx3aWR0aD0xMCkKaGlzdChzd19wdHMkZGF0ZTIsYnJlYWtzID0gIm1vbnRocyIsbWFpbj0iVGltZWxpbmUgb2YgQXVkaXQgMSIseGxhYj0iRGF0ZSBvZiBBc3Nlc3NtZW50IikgIyBtb3N0bHkgaW4gdGhlIGVhcmx5IHBhcnQgb2YgMjAxMi4KIyBkZXYub2ZmKCkKKGRhdGVwbG90MSA8LSBnZ3Bsb3Qoc3dfcHRzKSArIAogICAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeD1kYXRlMikpICsgCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoIkRhdGUgb2YgQXNzZXNzbWVudCIsZGF0ZV9taW5vcl9icmVha3M9Im1vbnRocyIsZGF0ZV9sYWJlbHM9IiViICVZIikgKyAKICAgICAgdGhlbWVfYncoKSkKYGBgCgpgYGB7cn0KZ2dzYXZlKGRhdGVwbG90MSxmaWxlPSJmaWd1cmVzL3RpbWVsaW5lMS5wZGYiLGhlaWdodD00LHdpZHRoPTcpCiMgdGFibGUoc3dfcHRzJElOU1ApICMgbm90IHN1cmUgd2hhdCB0aGlzIG1lYW5zCiMgdGFibGUoc3dfcHRzJE5PVEVTKSAjIHRoaXMgbG9va3MgbW9yZSBxdWFsaXRhdGl2ZQpzdW1tYXJ5KHN3X3B0cyRTQ0kpICMgMC0xMDAgU2lkZXdhbGsgQ29uZGl0aW9uIEluZGV4CmBgYApTbywgaXQgbG9va3MgbGlrZSB0aGlzIGlzIHRoZSBxdWFsaXR5IG9mIHRoZSBzaWRld2Fsa3MKCk9rYXksIHRpbWUgdG8gYnJpbmcgaW4gdGhlIFNDSSByZXBvcnQgZnJvbSBUMjoKYGBge3J9CnN3X3BvbHlfdDIgPC0gc3RfcmVhZChkc24gPSAifi9Hb29nbGUgRHJpdmUvQkFSSSBSZXNlYXJjaCBUZWFtIERhdGEgTGlicmFyeS9TdHJlZXRDYXN0ZXIvU2lkZXdhbGsgQ29uZGl0aW9ucyBUMi8iLGxheWVyPSJTaWRld2Fsa3MiKQojIG5lZWQgdG8gcmVtb3ZlIGVtcHRpZXMgYmVmb3JlIGZpbmRpbmcgY2VudHJvaWRzOgpzd19wb2x5X3QyIDwtIHN3X3BvbHlfdDJbLXdoaWNoKGlzLm5hKHN0X2RpbWVuc2lvbihzd19wb2x5X3QyLE5BX2lmX2VtcHR5ID0gVCkpKSxdCiMgZmluZGluZyBjZW50cm9pZHMgdG8gdXNlIGFzIHBvaW50IGRhdGE6CnN3X3B0c190MiA8LSBzdF9jZW50cm9pZChzd19wb2x5X3QyKQpzdW1tYXJ5KHN3X3B0c190MikKYGBgCgpCYXNpYyBkZXNjcmlwdGl2ZXM6CgpgYGB7cn0Kc3VtbWFyeShzd19wb2x5X3QyJFNXS19JRCkgIyA1LWRpZ2l0IElEIG51bWJlcnMsIGJ1dCBub3QgdW5pcXVlPwpgYGAKCmBgYHtyfQpzdW1tYXJ5KHN3X3BvbHlfdDIkTmV3X1NDSSkgIyAwLTEwMCBTaWRld2FsayBDb25kaXRpb24gSW5kZXgKCmBgYAoKCiMgU3BhdGlhbCB2aXN1YWxzCgpQbG90IFNDSToKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQojIHBsb3Qoc3RfZ2VvbWV0cnkoc3dfcHRzKSxjb2w9IlNDSSIpCmdncGxvdChzd19wdHNbIlNDSSJdKSArIAogICAgICBnZW9tX3NmKGFlcyhjb2xvcj1TQ0ksZmlsbD1TQ0kpKQpgYGAKCk5ldyBkYXRhOgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KcGxvdChzd19wdHNfdDJbIk5ld19TQ0kiXSkKZ2dwbG90KHN3X3B0c190MlsiTmV3X1NDSSJdKSArIAogICAgICBnZW9tX3NmKGFlcyhjb2xvcj1OZXdfU0NJKSkKYGBgClRyeWluZyB0byBtYXRjaCB1cCBnZW9ncmFwaGllcyBhY3Jvc3MgdHdvIGF1ZGl0czoKYGBge3J9CnN3X3BvbHlfaWQxIDwtIHN3X3BvbHkgJT4lIAogICAgICBmaWx0ZXIoU1dLX0lEPT0iMSIpCnN3X3BvbHlfdDJfaWQxIDwtIHN3X3BvbHlfdDIgJT4lIAogICAgICBmaWx0ZXIoU1dLX0lEPT0iMSIpCiMgcGxvdChzd19wb2x5X2lkMVsiU0NJIl0pCnBsb3Qoc3RfZ2VvbWV0cnkoc3dfcG9seV9pZDEpKQoKYGBgCmBgYHtyfQojIHBsb3Qoc3dfcG9seV90Ml9pZDFbIk5ld19TQ0kiXSkKcGxvdChzdF9nZW9tZXRyeShzd19wb2x5X3QyX2lkMSkpCmBgYApTbyBubywgdGhvc2UgZG9uJ3QgbWF0Y2ggdXAuIFRoYXQncyBhIHBhaW4uCgpDaGVjayBpZiB0aGUgc2lkZXdhbGsgc2VnbWVudHMgbWF0Y2ggdXAgZnJvbSBUMSB0byBUMiBhdCBhbGwKYGBge3J9CnN0X2Nycyhzd19wb2x5KTsgc3RfY3JzKHN3X3BvbHlfdDIpCnN3X3BvbHlfdDIgPC0gc3RfdHJhbnNmb3JtKHN3X3BvbHlfdDIsc3RfY3JzKHN3X3BvbHkpKQojIHN3X3BvbHlfbWF0Y2ggPC0gc3RfZXF1YWxzX2V4YWN0KHN3X3BvbHksc3dfcG9seV90MixzcGFyc2U9VCxwYXI9MC4wMDEpCiMgYXBwbHkoc3dfcG9seV9tYXRjaCwxLGFueSkKIyBzdW0oYXBwbHkoWCA9IHN3X3BvbHlfbWF0Y2gsMSxGVU4gPSBmdW5jdGlvbih4KXtsZW5ndGgoeCk+MH0pKQojIHN3X3BvbHlfbWF0Y2ggPC0gc3RfY29udGFpbnMoc3dfcG9seSxzd19wb2x5X3QyLHNwYXJzZT1UKQojIHN3X3BvbHlfY29tcGFjdCA8LSBzd19wb2x5ICU+JQojICAgICAgIHNlbGVjdChTV0tfSUQsU0NJKSAlPiUKIyAgICAgICByZW5hbWUoU1dLX0lEX3QxID0gU1dLX0lELAojICAgICAgICAgICAgICBTQ0lfdDEgPSBTQ0kpCiMgc3dfcG9seV90Ml9tYXRjaGVkIDwtIHN0X2pvaW4oc3dfcG9seV90Mixzd19wb2x5X2NvbXBhY3Qsam9pbj1zdF8pCiMgbWVhbighaXMubmEoc3dfcG9seV90Ml9tYXRjaGVkJFNDSV90MSkpKjEwMCAjIG9ubHkgd29ya2VkIGZvciAwLjE0JQpgYGAKCkxldCdzIGxvb2sgYXQgc29tZSBzdWJzZXRzIHRvIHNlZSBob3cgdG8gbWF0Y2ggdGhlbSBzcGF0aWFsbHkKYGBge3J9CnN3X3BvbHlfdDIgPC0gc3RfdHJhbnNmb3JtKHN3X3BvbHlfdDIsc3RfY3JzKHN3X3BvbHkpKQoKc3dfcG9seV9jdG93biA8LSBzd19wb2x5ICU+JSAKICAgICAgZmlsdGVyKERJU1RSSUNUPT0iQ0hBUkxFU1RPV04iKQpzd19wb2x5X3QyX2N0b3duIDwtIHN3X3BvbHlfdDIgJT4lIAogICAgICBmaWx0ZXIoRElTVFJJQ1Q9PSJDSEFSTEVTVE9XTiIpCnBsb3Qoc3RfZ2VvbWV0cnkoc3dfcG9seV9jdG93bikpCnBsb3Qoc3RfZ2VvbWV0cnkoc3dfcG9seV90Ml9jdG93biksY29sPSJyZWQiLGFkZD1UKQojIGNvbnQxIDwtIHN0X2NvbnRhaW5zKHN3X3BvbHlfY3Rvd24sc3dfcG9seV90Ml9jdG93bixzcGFyc2U9VCkKIyBjb250MV9pbmQgPC0gd2hpY2goYXBwbHkoY29udDEsMSxhbnkpKSAjIGlkZW50aWZpZXMgd2hpY2ggb25lcyBpbiB0MSBjb250YWluIGFueSBpbiB0MgojICMgdmlzdWFsaXplIHNvbWUgb2YgdGhlc2U6CiMgcGxvdChzdF9nZW9tZXRyeShzdWJzZXQoc3dfcG9seV9jdG93bixhcHBseShjb250MSwxLGFueSkpKSkKIyBwbG90KHN0X2dlb21ldHJ5KHN3X3BvbHlfdDJfY3Rvd24pLGFkZD1ULGNvbD0icmVkIikKIyBwbG90KHN0X2dlb21ldHJ5KHN3X3BvbHlfY3Rvd24pLGFkZD1ULGNvbD0iYmx1ZSIpICMgdGhleSBkZWZpbml0ZWx5IG92ZXJsYXAgLSBzbyB0aGlzIGlzIHdlaXJkCmBgYAojIE1hdGNoaW5nIHNpZGV3YWxrcyBzZWdtZW50cyBhY3Jvc3Mgd2F2ZXMgb2YgYXVkaXRzIAojIyB0cnlpbmcgd2l0aCBjZW50cm9pZCBwb2ludHM6CmBgYHtyfQoKc3dfcHRzX3QyIDwtIHN0X3RyYW5zZm9ybShzd19wdHNfdDIsc3RfY3JzKHN3X3B0cykpCiMgZGlzdG1hdCA8LSBzdF9kaXN0YW5jZShzd19wdHMsc3dfcHRzX3QyKSAjIGluIGZ0IChVUykKIyBjbG9zZXN0IDwtIGFwcGx5KGRpc3RtYXQsMSxmdW5jdGlvbih4KXt3aGljaCh4PT1taW4oeCkpfSkKIyBjbG9zZXN0X2Rpc3QgPC0gYXBwbHkoZGlzdG1hdCwxLG1pbikgIyBkaXN0YW5jZSBpbiBmZWV0CiMgY2xvc2VzdFsxMDg3NV0KIyBwbG90KHN0X2dlb21ldHJ5KHN3X3BvbHlfdDJbYygxMzU4NCwyMjk0NyksIk5ld19TQ0kiXSkpICMgdGhlc2UgYXJlIGR1cGxpY2F0ZXMsIHRoYXQncyB3aHkhCiMgY2xvc2VzdFsxMDg3NV0gPC0gMTM1ODQgIyBtYW51YWwgZml4CiMgbWF0Y2h0YWJsZSA8LSB0aWJibGUoaW5kZXhfdDEgPSAxOmxlbmd0aCh1bmxpc3QoY2xvc2VzdCkpLAojICAgICAgICAgICAgICAgICAgICAgIGNsb3Nlc3RfaW5kZXggPSB1bmxpc3QoY2xvc2VzdCksCiMgICAgICAgICAgICAgICAgICAgICAgY2xvc2VzdF9kaXN0ID0gY2xvc2VzdF9kaXN0LAojICAgICAgICAgICAgICAgICAgICAgIFNXS19JRF90MSA9IHN3X3B0cyRTV0tfSUQpCiMgbWF0Y2h0YWJsZSRTV0tfSURfdDIgPC0gc3dfcHRzX3QyJFNXS19JRFttYXRjaHRhYmxlJGNsb3Nlc3RfaW5kZXhdCiMgc3VtbWFyeShtYXRjaHRhYmxlJGNsb3Nlc3RfZGlzdCkKIyBwbG90KHN0X2dlb21ldHJ5KHN3X3BvbHkgJT4lIGZpbHRlcihTV0tfSUQgJWluJSBtYXRjaHRhYmxlJFNXS19JRF90MVs4XSkpKSAjIHRoZXNlIHNob3VsZCBiZSBvdmVybGFwcGluZwojIHBsb3Qoc3RfZ2VvbWV0cnkoc3dfcG9seV90MiAlPiUgZmlsdGVyKFNXS19JRCAlaW4lIG1hdGNodGFibGUkU1dLX0lEX3QyWzhdKSksYWRkPVQsY29sPSJyZWQiKSAjIHNob3dzIHRoYXQgNDQgZnQgYXBhcnQgaW4gY2VudHJvaWRzIG5vdCBtdWNoCgpgYGAKV2hhdCBhYm91dCBsb29raW5nIGF0IHNvbWUgc2VnbWVudHMgdGhhdCBhcmUgZmFydGhlciBhcGFydD8KYGBge3J9CiMgbWF0Y2h0YWJsZSAlPiUgZmlsdGVyKGNsb3Nlc3RfZGlzdD4xMDAwKQpgYGAKCmBgYHtyfQojIHBsb3Qoc3RfZ2VvbWV0cnkoc3dfcG9seSAlPiUgZmlsdGVyKFNXS19JRCAlaW4lIG1hdGNodGFibGUkU1dLX0lEX3QxWzhdKSkpICMgdGhlc2Ugc2hvdWxkIGJlIG92ZXJsYXBwaW5nCiMgcGxvdChzdF9nZW9tZXRyeShzd19wb2x5X3QyICU+JSBmaWx0ZXIoU1dLX0lEICVpbiUgbWF0Y2h0YWJsZSRTV0tfSURfdDJbOF0pKSxhZGQ9VCxjb2w9InJlZCIpICMgc2hvd3MgdGhhdCA0NCBmdCBhcGFydCBpbiBjZW50cm9pZHMgbm90IG11Y2gKIyBwbG90KHN0X2dlb21ldHJ5KHN3X3BvbHkgJT4lIGZpbHRlcihTV0tfSUQgJWluJSBtYXRjaHRhYmxlJFNXS19JRF90MVsxMTgxXSkpKSAjIHRoZXNlIHNob3VsZCBiZSBvdmVybGFwcGluZwojIHBsb3Qoc3RfZ2VvbWV0cnkoc3dfcG9seV90MiAlPiUgZmlsdGVyKFNXS19JRCAlaW4lIG1hdGNodGFibGUkU1dLX0lEX3QyWzExODFdKSksYWRkPVQsY29sPSJyZWQiKSAjIHNob3dzIHRoYXQgZXZlbiAxMDQ3IGZ0IGFwYXJ0IGluIGNlbnRyb2lkcyBub3QgbXVjaCwgYW5kIHByb2JhYmx5IGEgY29ycmVjdCBtYXRjaCEKIyBgYGAKIyBgYGB7cn0KIyBwbG90KHN0X2dlb21ldHJ5KHN3X3BvbHkgJT4lIGZpbHRlcihTV0tfSUQgJWluJSBtYXRjaHRhYmxlJFNXS19JRF90MVsxMTgxOjExODddKSkpICMgdGhlc2Ugc2hvdWxkIGJlIG92ZXJsYXBwaW5nCiMgcGxvdChzdF9nZW9tZXRyeShzd19wb2x5X3QyICU+JSBmaWx0ZXIoU1dLX0lEICVpbiUgbWF0Y2h0YWJsZSRTV0tfSURfdDJbMTE4MToxMTg3XSkpLGFkZD1ULGNvbD0icmVkIikgIyBzaG93cyB0aGF0IGV2ZW4gMTA0NyBmdCBhcGFydCBpbiBjZW50cm9pZHMgbm90IG11Y2gsIGFuZCBwcm9iYWJseSBhIGNvcnJlY3QgbWF0Y2ghCmBgYApXaGF0IHRoaXMgc2VlbXMgdG8gYmUgc2hvd2luZyBpcyB0aGF0IGFjdHVhbGx5IHRoZXJlIGFyZSBqdXN0IHNvbWUgc2lkZXdhbGsgc2VnbWVudHMgdGhhdCBhcmUgbWlzc2luZyBpbiBXYXZlIDIgb2YgdGhlIFNDSSBzdXJ2ZXkuIFNob3dzIHdlIHNob3VsZCBhbHNvIGRvIHRoZSBtYXRjaGluZyBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uIC0gZS5nLiBmaW5kIGNsb3Nlc3Qgc2VnbWVudCB0byBlYWNoIFNXSyBpbiB3YXZlIDIgZnJvbSB3YXZlIDEuCgojIyBNYXRjaGluZyBpbiBvcHBvc2l0ZSBkaXJlY3Rpb24gKHdhdmUgMSB0byB3YXZlIDIpOgpgYGB7cn0KIyBkaXN0bWF0MiA8LSBzdF9kaXN0YW5jZShzd19wdHNfdDIsc3dfcHRzKSAjIGluIGZ0IChVUykKIyBjbG9zZXN0MiA8LSBhcHBseShkaXN0bWF0MiwxLGZ1bmN0aW9uKHgpe3doaWNoKHg9PW1pbih4KSl9KQojIGNsb3Nlc3RfZGlzdDIgPC0gYXBwbHkoZGlzdG1hdDIsMSxtaW4pICMgZGlzdGFuY2UgaW4gZmVldAojIG1hdGNodGFibGUyIDwtIHRpYmJsZShpbmRleF90MiA9IDE6bGVuZ3RoKHVubGlzdChjbG9zZXN0MikpLAojICAgICAgICAgICAgICAgICAgICAgIGNsb3Nlc3RfaW5kZXggPSB1bmxpc3QoY2xvc2VzdDIpLAojICAgICAgICAgICAgICAgICAgICAgIGNsb3Nlc3RfZGlzdCA9IGNsb3Nlc3RfZGlzdDIsCiMgICAgICAgICAgICAgICAgICAgICAgU1dLX0lEX3QyID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoc3dfcHRzX3QyJFNXS19JRCkpKQojIG1hdGNodGFibGUyJFNXS19JRF90MSA8LSBzd19wdHMkU1dLX0lEW21hdGNodGFibGUyJGNsb3Nlc3RfaW5kZXhdCiMgc3VtbWFyeShtYXRjaHRhYmxlMiRjbG9zZXN0X2Rpc3QpICMgbWF4aW11bSAxMTE0IGZ0LCB3aGljaCBpcyB0b3RhbGx5IGFsbG93YWJsZQpgYGAKTm93LCB0aW1lIHRvIG1hdGNoIGFuZCBjcmVhdGUgb3Zlci10aW1lIGNoYW5nZSBtZXRyaWNzCmBgYHtyfQojIG1hdGNodGFibGUyJFNDSV90MSA8LSBzd19wdHMkU0NJW21hdGNoKG1hdGNodGFibGUyJFNXS19JRF90MSxzd19wdHMkU1dLX0lEKV0KIyBtYXRjaHRhYmxlMiRTQ0lfdDIgPC0gc3dfcHRzX3QyJE5ld19TQ0lbbWF0Y2gobWF0Y2h0YWJsZTIkU1dLX0lEX3QyLHN3X3B0c190MiRTV0tfSUQpXQojIG1hdGNodGFibGUyIDwtIG1hdGNodGFibGUyICU+JQojICAgICAgIG11dGF0ZShTQ0lfY2hhbmdlID0gU0NJX3QyLVNDSV90MSwKIyAgICAgICAgICAgICAgU0NJX2NoYW5nZV9wZXJjID0gU0NJX2NoYW5nZS9TQ0lfdDEpCiMgc3VtbWFyeShtYXRjaHRhYmxlMikgIyBvbiBhdmVyYWdlLCBnb3QgYmV0dGVyIGJ5IDAuMSwgYnV0IG1lZGlhbiA9IC0xLjM5LiBwZXJjZW50IG1lc3NlZCB1cCBiL2Mgc29tZSBoYXZlIFNDST0wCmBgYApUaW1lIHRvIG1hdGNoIHRoZXNlIGRhdGEgYmFjayB0byB0aGUgcG9seWdvbnMKYGBge3J9CiMgd3JpdGUuY3N2KG1hdGNodGFibGUyLCJ0YWJsZXMvU1dLX21hdGNoZWRfY3dhbGsuY3N2Iixyb3cubmFtZXMgPSBGKQptYXRjaHRhYmxlMiA8LSByZWFkLmNzdigidGFibGVzL1NXS19tYXRjaGVkX2N3YWxrLmNzdiIsc3RyaW5nc0FzRmFjdG9ycyA9IEYpCnN3X3BvbHlfdDIkU1dLX0lEID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoc3dfcG9seV90MiRTV0tfSUQpKQpzd19wb2x5X3QyIDwtIGxlZnRfam9pbihzd19wb2x5X3QyLG1hdGNodGFibGUyLGJ5PWMoIlNXS19JRCIgPSAiU1dLX0lEX3QyIikpCnN1bW1hcnkoc3dfcG9seV90MikKYGBgCgojIE1hdGNoaW5nIHRvIENlbnN1cyBnZW9ncmFwaGllczoKCiMjIExvYWRpbmcgQ2Vuc3VzIGdlb2dyYXBoaWVzOgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kb3B0aW9ucyh0aWdyaXNfY2xhc3MgPSAic2YiLHRpZ3Jpc191c2VfY2FjaGUgPSBUKQpiZyA8LSB0aWdyaXM6OmJsb2NrX2dyb3VwcygiTUEiLCJTdWZmb2xrIix5ZWFyID0gIjIwMTUiKQp0cmFjdHMgPC0gdGlncmlzOjp0cmFjdHMoIk1BIiwiU3VmZm9sayIseWVhciA9ICIyMDE1IikKc3RyZWV0cyA8LSB0aWdyaXM6OnJvYWRzKCJNQSIsIlN1ZmZvbGsiLHllYXIgPSAiMjAxNSIpCnRvd25zIDwtIHRpZ3Jpczo6Y291bnR5X3N1YmRpdmlzaW9ucygiTUEiLCJTdWZmb2xrIix5ZWFyID0gIjIwMTUiKQpib3N0b24gPC0gc3Vic2V0KHRvd25zLE5BTUUgPT0gIkJvc3RvbiIpCmJvc3Rvbl9iZyA8LSBiZ1t1bmxpc3Qoc3RfY29udGFpbnMoYm9zdG9uLGJnKSksXQpib3N0b25fdHJhY3RzIDwtIHRyYWN0c1t1bmxpc3Qoc3RfY29udGFpbnMoYm9zdG9uLHRyYWN0cykpLF0KIyBib3N0b25fc3RyZWV0cyA8LSBzdHJlZXRzW3VubGlzdChzdF9jb250YWlucyhib3N0b24sc3RyZWV0cykpLF0KYm9zdG9uX3N0cmVldHMgPC0gcmVhZE9HUihkc249cGFzdGUwKCIuLi9HZW9ncmFwaGljYWwgSW5mcmFzdHJ1Y3R1cmUvRGF0YS9HZW9ncmFwaGljYWwgSW5mcmFzdHJ1Y3R1cmUgMjAxOC9PdGhlci90bF8yMDE3XzI1MDI1X2FkZHJmZWF0LyIpLCBsYXllcj0idGxfMjAxN18yNTAyNV9hZGRyZmVhdCIpCmJvc3Rvbl9zdHJlZXRzIDwtIHN0X2FzX3NmKGJvc3Rvbl9zdHJlZXRzKQpgYGAKCiMjIE1hcCBDZW5zdXMgZ2VvZ3JhcGhpZXM6CgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdChzdF9nZW9tZXRyeShib3N0b25fc3RyZWV0cykpCmBgYAoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgbmljZXIgcGxvdHM6CmJvc3Rvbl9iYXNlIDwtIGdldF9tYXAobG9jYXRpb249IkJvc3RvbiBMYXRpbiBBY2FkZW15LCBCb3N0b24sIE1BIix6b29tPTEyLCBjb2xvcj0iY29sb3IiLG1hcHR5cGU9InRlcnJhaW4iLGNyb3A9VCxzb3VyY2U9Imdvb2dsZSIpCgpiMCA8LSBnZ21hcChib3N0b25fYmFzZSwgZXh0ZW50PSJkZXZpY2UiLGxlZ2VuZD0ibm9uZSIsbWFwcmFuZ2U9VCkKCihiMSA8LSBiMCArIAogICAgICBnZW9tX3NmKGRhdGE9Ym9zdG9uX2JnLGNvbG9yID0gImJsYWNrIixhbHBoYT0wLjQsaW5oZXJpdC5hZXM9RikpCgpgYGAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQooYjEgPC0gYjAgKyAKICAgICAgZ2VvbV9zZihkYXRhPWJvc3Rvbl90cmFjdHMsY29sb3IgPSAiYmxhY2siLGFscGhhPTAuNCxpbmhlcml0LmFlcyA9IEYsZ3VpZGU9RixhZXMoZmlsbD1HRU9JRCkpCiApCmBgYAoKIyMgRmlyc3QgbWF0Y2ggdXAgdGhlIGNsb3Nlc3QgVExJRAoKYGBge3J9CmJvc3Rvbl9zdHJlZXRzIDwtIHN0X3RyYW5zZm9ybShib3N0b25fc3RyZWV0cyxzdF9jcnMoc3dfcG9seV90MikpCnN3X3B0c190MiA8LSBzdF90cmFuc2Zvcm0oc3dfcHRzX3QyLHN0X2Nycyhib3N0b25fc3RyZWV0cykpCiMjIG5vbmUgb2YgdGhlc2UgbWV0aG9kcyBzZWVtIHRvIGJlIHdvcmtpbmcgZm9yIG1hdGNoaW5nIGJ5IGludGVyc2VjdGlvbiBvZiBwb2x5Z29ucyBhbmQgVEwgc2VnbWVudHM6CiMgc3dfcG9seV9zdHJlZXRzIDwtIHN0X2pvaW4oeD1zd19wb2x5X3QyLHk9Ym9zdG9uX3N0cmVldHMsam9pbj1zdF9pbnRlcnNlY3RzLGxlZnQ9VCkKIyBzd19wdHNfc3RyZWV0cyA8LSBzdF9qb2luKHg9c3dfcHRzX3QyLHk9Ym9zdG9uX3N0cmVldHMsam9pbj1zdF93aXRoaW4sbGVmdD1UKQojIHN0cmVldHNfam9pbmVkIDwtIHN0X2pvaW4oeD1ib3N0b25fc3RyZWV0cyx5PXN3X3BvbHlfdDIsam9pbj1zdF9pbnRlcnNlY3RzLGxlZnQ9RikKIyBzdW0oIWlzLm5hKHN3X3BvbHlfc3RyZWV0cyRUTElEKSkKIyMgaW5zdGVhZCwgZ29pbmcgdG8gZG8gYSBtaW4tZGlzdGFuY2UgbWF0Y2ggYmV0d2VlbiBjZW50cm9pZHMgb2YgU1cgYW5kIHRoZSBUTCBzdHJlZXQgc2VnbWVudHM6CiMgc3dfcHRzX3N0cmVldHMgPC0gc3dfcHRzX3QyCiMgc3dfcHRzX3N0cmVldHMkVExJRCA8LSBOQQojIGZvcihpIGluIDE6bnJvdyhzd19wdHNfc3RyZWV0cykpewojICAgICAgIHN3X3B0c19zdHJlZXRzJFRMSURbaV0gPC0gYXMuY2hhcmFjdGVyKGJvc3Rvbl9zdHJlZXRzJFRMSURbd2hpY2gubWluKHN0X2Rpc3RhbmNlKHN3X3B0c19zdHJlZXRzW2ksImdlb21ldHJ5Il0sIGJvc3Rvbl9zdHJlZXRzKSldKQojIH0KIyBzd19wdHNfc3RyZWV0cyRTV0tfSUQgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoc3dfcHRzX3N0cmVldHMkU1dLX0lEKSkKIyBzd19wdHNfc3RyZWV0cyA8LSBsZWZ0X2pvaW4oc3dfcHRzX3N0cmVldHMsbWF0Y2h0YWJsZTIsYnk9YygiU1dLX0lEIiA9ICJTV0tfSURfdDIiKSkKIyBzYXZlKHN3X3B0c19zdHJlZXRzLGZpbGUgPSAidGFibGVzL3N3X3B0c190Ml9zdHJlZXRzLlJEYXRhIikKbG9hZChmaWxlID0gInRhYmxlcy9zd19wdHNfdDJfc3RyZWV0cy5SRGF0YSIpCnN1bSghaXMubmEoc3dfcHRzX3N0cmVldHMkVExJRCkpICMgZ290IGFsbCBvZiB0aGVtIQpzdHJlZXRzX3N1bW0gPC0gc3dfcHRzX3N0cmVldHMgJT4lCiAgICAgIGdyb3VwX2J5KFRMSUQpICU+JQogICAgICBzdW1tYXJpemUobWVhbl9zY2lfdDEgPSBtZWFuKFNDSV90MSxuYS5ybT1UKSwKICAgICAgICAgICAgICAgIG1lYW5fc2NpX3QyID0gbWVhbihTQ0lfdDIsbmEucm09VCksCiAgICAgICAgICAgICAgICBtZWFuX2NoYW5nZV9zY2kgPSBtZWFuKFNDSV9jaGFuZ2UsbmEucm09VCkpCgpib3N0b25fc3RyZWV0c19zY2kgPC0gbGVmdF9qb2luKHg9Ym9zdG9uX3N0cmVldHMseT1hcy5kYXRhLmZyYW1lKHN0cmVldHNfc3VtbSksYnk9IlRMSUQiKSAlPiUKICAgICAgZmlsdGVyKCFpcy5uYShtZWFuX2NoYW5nZV9zY2kpKQojIHNhdmUoYm9zdG9uX3N0cmVldHNfc2NpLGZpbGUgPSAidGFibGVzL2Jvc3Rvbl9zdHJlZXRzX3NjaS5SRGF0YSIpCmxvYWQoZmlsZSA9ICJ0YWJsZXMvYm9zdG9uX3N0cmVldHNfc2NpLlJEYXRhIikKYGBgCgojIFZpc3VhbGl6ZQpOZXh0LCBnb2luZyB0byBwbG90IHRoZSBzaWRld2FsayBjb25kaXRpb25zIGF0IHZhcmlvdXMgZ2VvZ3JhcGhpZXM6CgpgYGB7cn0KYjIgPC0gZ2dwbG90KCkgKyAKICAgICAgZ2VvbV9zZihkYXRhPWJvc3Rvbl9zdHJlZXRzX3NjaSxhZXMoY29sb3IgPSBjdXRfaW50ZXJ2YWwobWVhbl9jaGFuZ2Vfc2NpLDEwKSksaW5oZXJpdC5hZXM9RixzaG93LmxlZ2VuZCA9ICJwb2x5Z29uIikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJSZFlsR24iLG5hbWU9IkNoYW5nZSBpbiBTQ0kiKSArIAogICAgICAgIyB0aGVtZV9idygpICsgCiAgICAgICMgdGhlbWVfdm9pZCgpCiAgICAgICB0aGVtZShheGlzLmxpbmU9ZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSxheGlzLnRpY2tzPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkscGFuZWwuYm9yZGVyPWVsZW1lbnRfYmxhbmsoKSxwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICd0cmFuc3BhcmVudCcpLAogICAgICAgICAgcGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCkscGxvdC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSkKICAKYGBgCgojIyMgU3RyZWV0LWxldmVsIFNDSSBjaGFuZ2VzCgpgYGB7cn0KZ2dzYXZlKGIyLGZpbGVuYW1lID0gImZpZ3VyZXMvdGxpZF9tZWFuX2NoYW5nZV9zY2kucG5nIikKIyBpbnRlcmFjdGl2ZSBwbG90Ogp0bWFwX21vZGUoInZpZXciKQp0bV9zaGFwZShib3N0b25fc3RyZWV0c19zY2kpICsgCiAgICAgIHRtX2xpbmVzKGNvbCA9ICJtZWFuX2NoYW5nZV9zY2kiLHRpdGxlLmNvbCA9ICJDaGFuZ2UgaW4gU0NJIixsd2Q9MiwKICAgICAgICAgICAgICAgcGFsZXR0ZT0iUmRZbEduIiwgbj0yMCxtaWRwb2ludD0wLAogICAgICAgICAgICAgIGlkID0gIlRMSUQiKQpgYGAKVGhpcyBtYXAgc2hvd3Mgd2hlcmUgc2lkZXdhbGsgY29uZGl0aW9ucyBnb3QgYmV0dGVyIGJldHdlZW4gdGhlc2UgdHdvIHN1cnZleXMgKGFyZWFzIGluIGdyZWVuLCB3aXRoIHBvc2l0aXZlIHZhbHVlcyBvZiBjaGFuZ2UgaW4gU0NJKSBhbmQgd2hlcmUgY29uZGl0aW9ucyBnb3Qgd29yc2UgKHJlZCwgb3IgbmVnYXRpdmUgdmFsdWVzIG9mIGNoYW5nZSBpbiBTQ0kpLiBMb29rcyBsaWtlIHRoaW5ncyBpbXByb3ZlZCBpbiBKYW1haWNhIFBsYWluIGFuZCBFYXN0IEJvc3RuLCBidXQgZ290IHdvcnNlIGluIERvcmNoZXN0ZXIgYW5kIHRoZSBub3J0aGVybiBlZGdlcyBvZiBDaGFybGVzdG93bi4KClNpZGV3YWxrIGNvbmRpdGlvbnMgd2l0aGluIHRyYWN0czoKCmBgYHtyfQojIGJyaW5nIFNDSSBkYXRhIGludG8gcG9pbnRzIGRhdGFzZXRzOgojIHN3X3B0c190MiRTV0tfSUQgPSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcihzd19wdHNfdDIkU1dLX0lEKSkKIyBzd19wdHNfdDIgPC0gbGVmdF9qb2luKHN3X3B0c190MixtYXRjaHRhYmxlMixieT1jKCJTV0tfSUQiID0gIlNXS19JRF90MiIpKQoKIyBqb2luIGluIENUIG9mIHNpZGV3YWxrIHNlZ21lbnQ6CmJvc3Rvbl90cmFjdHMgPC0gc3RfdHJhbnNmb3JtKGJvc3Rvbl90cmFjdHMsc3RfY3JzKHN3X3B0c19zdHJlZXRzKSkKIyBzd19vdmVyIDwtIG92ZXIoYXMoc3dfcHRzLCJTcGF0aWFsIiksYXMoYm9zdG9uX3RyYWN0cywiU3BhdGlhbCIpKQpzd19wdHNfY3QgPC0gc3Rfam9pbih4PXN3X3B0c19zdHJlZXRzLHk9Ym9zdG9uX3RyYWN0cyxqb2luPXN0X3dpdGhpbixsZWZ0PVQpCgpjdF9zdW1tIDwtIHN3X3B0c19jdCAlPiUKICAgICAgYXNfdGliYmxlKCkgJT4lCiAgICAgIGdyb3VwX2J5KEdFT0lEKSAlPiUKICAgICAgc3VtbWFyaXplKG1lYW5fc2NpX3QxID0gbWVhbihTQ0lfdDEsbmEucm09VCksCiAgICAgICAgICAgICAgICBtZWFuX3NjaV90MiA9IG1lYW4oU0NJX3QyLG5hLnJtPVQpLAogICAgICAgICAgICAgICAgbWVhbl9jaGFuZ2Vfc2NpID0gbWVhbihTQ0lfY2hhbmdlLG5hLnJtPVQpKQogICAgICAKYm9zdG9uX3RyYWN0czIgPC0gbGVmdF9qb2luKGJvc3Rvbl90cmFjdHMsY3Rfc3VtbSxieT0iR0VPSUQiKQojIHNhdmUoYm9zdG9uX3RyYWN0czIsZmlsZSA9ICJ0YWJsZXMvYm9zdG9uX3RyYWN0c19zY2kuUkRhdGEiKQpsb2FkKGZpbGUgPSAidGFibGVzL2Jvc3Rvbl90cmFjdHNfc2NpLlJEYXRhIikKYGBgCgojIyMgVHJhY3QgU0NJIGNoYW5nZXMKCmBgYHtyfQpib3N0b25fdHJhY3RzMyA8LSBhcyhib3N0b25fdHJhY3RzMiwiU3BhdGlhbCIpCmJvc3Rvbl90cmFjdHMzQGRhdGEkaWQgPC0gcm93bmFtZXMoYm9zdG9uX3RyYWN0czNAZGF0YSkKYm9zdG9uX3RyYWN0czQgPC0gZm9ydGlmeShib3N0b25fdHJhY3RzMyxyZWdpb249ImlkIikgIyBzZXBhcmF0ZXMgcG9seWdvbnMgaW50byBpbmRpdmlkdWFsIHZlcnRpY2VzCmJvc3Rvbl90cmFjdHMzIDwtIG1lcmdlKGJvc3Rvbl90cmFjdHM0LGJvc3Rvbl90cmFjdHMzQGRhdGEsYnk9ImlkIikgIyBtZXJnZSBpbiBhbGwgdGhlIG90aGVyIHBvbHkgZGF0YSBmb3IgZWFjaAoKKGIyIDwtIGIwICsgCiAgICAgIGdlb21fcG9seWdvbihkYXRhPWJvc3Rvbl90cmFjdHMzLGFlcyh4PWxvbmcseT1sYXQsZ3JvdXA9Z3JvdXAsZmlsbCA9IG1lYW5fY2hhbmdlX3NjaSkpICsKICAgICAgdGhlbWUobGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMC43NSwgImNtIiksbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDIsICJjbSIpLAogICAgICAgICAgICBheGlzLmxpbmUgPSBOVUxMLHBhbmVsLmJvcmRlciA9IE5VTEwscGFuZWwuZ3JpZCA9IE5VTEwpICsgCiAgICAgICAgICAgIHRoZW1lX2J3KCkKICkKYGBgCgpgYGB7cn0KZ2dzYXZlKGIyLGZpbGVuYW1lID0gImZpZ3VyZXMvY3RfbWVhbl9jaGFuZ2Vfc2NpLnBuZyIpCiMgaW50ZXJhY3RpdmUgcGxvdDoKdG1hcF9tb2RlKCJ2aWV3IikKdG1fc2hhcGUoYm9zdG9uX3RyYWN0czIpICsgCiAgICAgIHRtX2ZpbGwoY29sID0gIm1lYW5fY2hhbmdlX3NjaSIsdGl0bGUgPSAiQ2hhbmdlIGluIFNDSSIsCiAgICAgICAgICAgICAgIHBhbGV0dGU9IlJkWWxHbiIsIG49MjAsbWlkcG9pbnQ9MCwKICAgICAgICAgICAgICBpZCA9ICJUUkFDVENFIikKYGBgCkFzIHdpdGggdGhlIHNlZ21lbnQtbGV2ZWwgbWFwLCB0aGlzIHNob3dzIHRoYXQgY29uZGl0aW9ucyBpbXByb3ZlZCBpbiBKUCBhbmQgRWFzdCBCb3N0b24sIGJ1dCBnb3Qgd29yc2UgaW4gTWF0dGFwYW4vRG9yY2hlc3RlciBhbmQgQ2hhcmxlc3Rvd24uCgpSZXBsaWNhdGUgdGhpcyBmb3IgQkdzOgoKYGBge3J9CiMgam9pbiBpbiBCRyBvZiBzaWRld2FsayBzZWdtZW50Ogpib3N0b25fYmcgPC0gc3RfdHJhbnNmb3JtKGJvc3Rvbl9iZyxzdF9jcnMoc3dfcHRzX3N0cmVldHMpKQpzd19wdHNfYmcgPC0gc3Rfam9pbih4PXN3X3B0c19zdHJlZXRzLHk9Ym9zdG9uX2JnLGpvaW49c3Rfd2l0aGluLGxlZnQ9VCkKCmJnX3N1bW0gPC0gc3dfcHRzX2JnICU+JQogICAgICBhc190aWJibGUoKSAlPiUKICAgICAgZ3JvdXBfYnkoR0VPSUQpICU+JQogICAgICBzdW1tYXJpemUobWVhbl9zY2lfdDEgPSBtZWFuKFNDSV90MSxuYS5ybT1UKSwKICAgICAgICAgICAgICAgIG1lYW5fc2NpX3QyID0gbWVhbihTQ0lfdDIsbmEucm09VCksCiAgICAgICAgICAgICAgICBtZWFuX2NoYW5nZV9zY2kgPSBtZWFuKFNDSV9jaGFuZ2UsbmEucm09VCkpCiAgICAgIApib3N0b25fYmcyIDwtIGxlZnRfam9pbihib3N0b25fYmcsYmdfc3VtbSxieT0iR0VPSUQiKQojIE91dHB1dCB0aGUgQkctbGV2ZWwgc2YgZGF0YSBmb3Igb3RoZXIgdXNlczoKc2F2ZShib3N0b25fYmcyLGZpbGUgPSAidGFibGVzL2Jvc3Rvbl9iZ19zY2kuUkRhdGEiKQpgYGAKCgpgYGB7cn0KKGIyIDwtIGdncGxvdCgpICsgCiAgICAgIGdlb21fc2YoZGF0YT1ib3N0b25fYmcyLGFlcyhmaWxsID0gbWVhbl9jaGFuZ2Vfc2NpKSxhbHBoYT0xLGluaGVyaXQuYWVzID0gRixzaG93LmxlZ2VuZCA9ICJwb2x5Z29uIikgCiApCmBgYAojIyMgQkcgU0NJIGNoYW5nZXMKYGBge3J9Cmdnc2F2ZShiMixmaWxlbmFtZSA9ICJmaWd1cmVzL2JnX21lYW5fY2hhbmdlX3NjaS5wbmciKQojIGludGVyYWN0aXZlIHBsb3Q6CnRtX3NoYXBlKGJvc3Rvbl9iZzIpICsgCiAgICAgIHRtX2ZpbGwoY29sID0gIm1lYW5fY2hhbmdlX3NjaSIsdGl0bGUgPSAiQ2hhbmdlIGluIFNDSSIsCiAgICAgICAgICAgICAgIHBhbGV0dGU9IlJkWWxHbiIsIG49MjAsbWlkcG9pbnQ9MCwKICAgICAgICAgICAgICBpZCA9ICJHRU9JRCIpCmBgYApUaGlzIEJHLWxldmVsIG1hcCBjb3Jyb2JvcmF0ZXMgdGhlIHRyYWN0LSBhbmQgc3RyZWV0LWxldmVsIHZpc3VhbHMuCgojIyBBZGRpbmcgY2Vuc3VzIGdlb2dyYXBoaWVzIGJhY2sgdG8gY3Jvc3N3YWxrIHRhYmxlCmBgYHtyfQojIG1hdGNodGFibGUyJFRMSUQgPC0gc3dfcHRzX3N0cmVldHMkVExJRFttYXRjaChtYXRjaHRhYmxlMiRTV0tfSURfdDIsc3dfcHRzX3N0cmVldHMkU1dLX0lEKV0KIyBtYXRjaHRhYmxlMiRCR19HRU9JRCA8LSBzd19wdHNfYmckR0VPSURbbWF0Y2gobWF0Y2h0YWJsZTIkU1dLX0lEX3QyLHN3X3B0c19iZyRTV0tfSUQpXQojIG1hdGNodGFibGUyJENUX0dFT0lEIDwtIHN3X3B0c19jdCRHRU9JRFttYXRjaChtYXRjaHRhYmxlMiRTV0tfSURfdDIsc3dfcHRzX2N0JFNXS19JRCldCiMgd3JpdGUuY3N2KG1hdGNodGFibGUyLCJ0YWJsZXMvU1dLX21hdGNoZWRfY3dhbGsuY3N2Iixyb3cubmFtZXMgPSBGKQptYXRjaHRhYmxlMiA8LSByZWFkLmNzdigidGFibGVzL1NXS19tYXRjaGVkX2N3YWxrLmNzdiIsc3RyaW5nc0FzRmFjdG9ycyA9IEYpCmBgYAoKIyBBZGRpbmcgMzExIGRhdGEgdG8gYW5hbHlzZXMKRmlyc3QgbmVlZCB0byBicmluZyBpbiAzMTEgZGF0YSBmcm9tIGJldHdlZW4gdGhlIHR3byBzaWRld2FsayBhdWRpdHM6CmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CiMjIG9sZCBkYXRhIGF3IFNXLWxldmVsOgojIGRhdDMxMSA8LSByZWFkLmR0YSgiU2lkZXdhbGtzIGZvciBITE0uZHRhIikgIyB0aGVzZSBhcmVuJ3QgcmVhbGx5IGNhbGxzLi4uIHRoZXkgc2VlbSB0byBiZSBjYWxscyBhdCB0aGUgc2lkZXdhbGstdW5pdCBsZXZlbD8gbm8gZ2VvZ3JhcGhpYyBpbmZvIG90aGVyIHRoYW4gU1dLX0lELCBCR19JRCwgYW5kIENUX0lECiMgc3dfcHRzX3N0cmVldHMkY2FsbHNfb2xkIDwtIGRhdDMxMSRjYWxsc1ttYXRjaChzd19wdHNfc3RyZWV0cyRTV0tfSURfdDEsZGF0MzExJFNXS19JRCldCmRhdDMxMSA8LSByZWFkX2NzdigiLi4vMzExIENSTSBTZXJ2aWNlIFJlcXVlc3RzL0RhdGEvUmF3IEZpbGVzL2xhZ2FuMzExc2VydmljZXJlcXVlc3RzLmNzdiIpCnRhYmxlKGRhdDMxMSRSRUFTT04pCnRhYmxlKGRhdDMxMSRUWVBFKQpzd19jYWxscyA8LSBkYXQzMTEgJT4lCiAgICAgIGZpbHRlcihSRUFTT04gPT0iU2lkZXdhbGsgQ292ZXIgLyBNYW5ob2xlIiB8IAogICAgICAgICAgICAgICAgICAgVFlQRSAlaW4lIGMoIlNpZGV3YWxrIENvdmVyIC8gTWFuaG9sZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICJHcm91bmQgTWFpbnRlbmFuY2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNpZGV3YWxrIFJlcGFpciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2lkZXdhbGsgUmVwYWlyIChJbnRlcm5hbCkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNpZGV3YWxrIFJlcGFpciAoTWFrZSBTYWZlKSIpKSAlPiUKICAgICAgIyBUeXBlIExJS0UgJyVTaWRld2FsayUnIEFORCBUWVBFIE5vdCBMSUtFICclQ292ZXIlJyBBTkQgU291cmNlIH49ICdFbXBsb3llZSBHZW5lcmF0ZWQnIEFORCBTb3VyY2Ugfj0gJ0NpdHkgV29ya2VyIEFwcCc7KSAjIGZyb20gRGFuJ3MgU0FTIGNvZGU/CiAgICAgIGZpbHRlcihTb3VyY2UgIT0gIkVtcGxveWVlIEdlbmVyYXRlZCIgJiAKICAgICAgICAgICAgICAgICAgIFNvdXJjZSAhPSAiQ2l0eSBXb3JrZXIgQXBwIikgJT4lCiAgICAgIGZpbHRlcihMb2NhdGlvbiAhPSAiMTAwIENpdHkgSGFsbCBQbHogQm9zdG9uIE1BIDAyMTA4IiAmCiAgICAgICAgICAgICAgICAgICBMb2NhdGlvbiAhPSAiMSBDaXR5IEhhbGwgUGx6IEJvc3RvbiBNQSAwMjEwOCIpCiAgICAgIGZpbHRlcihvcGVuX2R0ID49IGFzLkRhdGUoIjIwMTItMDEtMDEiKSAmIG9wZW5fZHQgPCBhcy5EYXRlKCIyMDE1LTAxLTAxIikpICMgaW4gdGltZSB3aW5kb3cKc3dfY2FsbHMgJT4lIGdyb3VwX2J5KExvY2F0aW9uKSAlPiUgc3VtbWFyaXplKHN1bWNhbGxzID0gbigpKSAlPiUgYXJyYW5nZShkZXNjKHN1bWNhbGxzKSkKCnN3X2NhbGxzX3B0cyA8LSBzdF9hc19zZihzd19jYWxscyxjb29yZHM9YygiTG9uZ2l0dWRlIiwiTGF0aXR1ZGUiKSxjcnM9Iitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0IikKc3dfY2FsbHNfcHRzIDwtIHN0X3RyYW5zZm9ybShzd19jYWxsc19wdHMsc3RfY3JzKHN3X3B0c19zdHJlZXRzKSkKYGBgCgojIyBNYXRjaGluZyAzMTEgY2FsbHMgdG8gY2Vuc3VzIGdlb2dyYXBoaWVzOgpgYGB7cn0Kc3dfY2FsbHNfcHRzJFNXS19JRF90MiA8LSBOQQpmb3IoaSBpbiAxOm5yb3coc3dfY2FsbHMpKXsKICAgICAgc3dfY2FsbHNfcHRzJFNXS19JRF90MltpXSA8LSBhcy5jaGFyYWN0ZXIoICMgbWF0Y2ggdG8gY2xvc2VzdCBzaWRld2FsayBzZWdtZW50IGNlbnRyb2lkCiAgICAgICAgICAgIHN3X3B0c19zdHJlZXRzJFNXS19JRFt3aGljaC5taW4oc3RfZGlzdGFuY2Uoc3dfY2FsbHNfcHRzW2ksImdlb21ldHJ5Il0sIHN3X3B0c19zdHJlZXRzKSldCiAgICAgICAgICAgICkKfQpzdW0oIWlzLm5hKHN3X2NhbGxzX3B0cyRTV0tfSURfdDIpKQpzd19jYWxsc19wdHMkVExJRCA8LSBtYXRjaHRhYmxlMiRUTElEW21hdGNoKHN3X2NhbGxzX3B0cyRTV0tfSURfdDIsbWF0Y2h0YWJsZTIkU1dLX0lEX3QyKV0Kc3dfY2FsbHNfcHRzJEJHX0dFT0lEIDwtIG1hdGNodGFibGUyJEJHX0dFT0lEW21hdGNoKHN3X2NhbGxzX3B0cyRTV0tfSURfdDIsbWF0Y2h0YWJsZTIkU1dLX0lEX3QyKV0Kc3dfY2FsbHNfcHRzJENUX0dFT0lEIDwtIG1hdGNodGFibGUyJENUX0dFT0lEW21hdGNoKHN3X2NhbGxzX3B0cyRTV0tfSURfdDIsbWF0Y2h0YWJsZTIkU1dLX0lEX3QyKV0KIyBzYXZlKHN3X2NhbGxzX3B0cyxmaWxlID0gInRhYmxlcy9zd19jYWxsc19nZW9tYXRjaGVkLlJEYXRhIikKbG9hZChmaWxlID0gInRhYmxlcy9zd19jYWxsc19nZW9tYXRjaGVkLlJEYXRhIikKYGBgCgojIyBBZ2dyZWdhdGluZyAzMTEgZGF0YSBhdCBnZW9ncmFwaGljIGxldmVsczoKIyMjIFN0cmVldC1sZXZlbCAzMTEgdmlzdWFsczoKCmBgYHtyfQpzdHJlZXRzX3N1bW1fMzExIDwtIHN3X2NhbGxzX3B0cyAlPiUKICAgICAgYXNfdGliYmxlKCkgJT4lCiAgICAgIGdyb3VwX2J5KFRMSUQpICU+JQogICAgICBzdW1tYXJpemUobl9jYWxscyA9IG4oKSkgJT4lCiAgICAgIGFzLmRhdGEuZnJhbWUoKQoKYm9zdG9uX3N0cmVldHNfc2NpJFRMSUQgPC0gYXMubnVtZXJpYyhib3N0b25fc3RyZWV0c19zY2kkVExJRCkKYm9zdG9uX3N0cmVldHNfc2NpIDwtIGxlZnRfam9pbihib3N0b25fc3RyZWV0c19zY2ksc3RyZWV0c19zdW1tXzMxMSxieT0iVExJRCIpCmJvc3Rvbl9zdHJlZXRzX3NjaSRuX2NhbGxzW2lzLm5hKGJvc3Rvbl9zdHJlZXRzX3NjaSRuX2NhbGxzKV0gPC0gMApib3N0b25fc3RyZWV0c19zY2kkbm9uemVyb19jYWxscyA8LSBhcy5udW1lcmljKGJvc3Rvbl9zdHJlZXRzX3NjaSRuX2NhbGxzPjApCmJvc3Rvbl9zdHJlZXRzX3NjaSRsb2dfY2FsbHMgPC0gbG9nMXAoYm9zdG9uX3N0cmVldHNfc2NpJG5fY2FsbHMpCmJvc3Rvbl9zdHJlZXRzX3NjaSRiaW5fY2FsbHMgPC0gY3V0KGJvc3Rvbl9zdHJlZXRzX3NjaSRuX2NhbGxzLGJyZWFrcyA9IGMoLUluZiwxLDIsNCw2LEluZiksIGxhYmVscz1jKCIwIiwiMS0yIiwiMi00IiwiNC02IiwiNisiKSkKYm9zdG9uX3N0cmVldHNfc2NpIDwtIGJvc3Rvbl9zdHJlZXRzX3NjaSAlPiUKICAgICAgbXV0YXRlKGNoYW5nZV9zY2lfYmlubmVkID0gY3V0KG1lYW5fY2hhbmdlX3NjaSwgYnJlYWtzPWMoLUluZiwgLTMwLCAzMCwgSW5mKSwgbGFiZWxzPWMoIldvcnNlIiwiU2ltaWxhciIsIkJldHRlciIpKSkKdG1fc2hhcGUoYm9zdG9uX3N0cmVldHNfc2NpKSArIAogICAgICB0bV9saW5lcyhjb2wgPSAiYmluX2NhbGxzIix0aXRsZS5jb2wgPSAiIyBvZiAzMTEgU2lkZXdhbGsgQ2FsbHMiLGx3ZD0yLAogICAgICAgICAgICAgICBwYWxldHRlPSJZbEduIiwgbj01LAogICAgICAgICAgICAgIGlkID0gIlRMSUQiKQpgYGAKCiMjIyBCbG9ja2dyb3VwIDMxMSB2aXN1YWxzOgpgYGB7cn0KYmdfc3VtbV8zMTEgPC0gc3dfY2FsbHNfcHRzICU+JQogICAgICBhc190aWJibGUoKSAlPiUKICAgICAgZ3JvdXBfYnkoQkdfR0VPSUQpICU+JQogICAgICBzdW1tYXJpemUobl9jYWxscyA9IG4oKSkgJT4lCiAgICAgIGFzLmRhdGEuZnJhbWUoKQoKYm9zdG9uX2JnMiRHRU9JRCA8LSBhcy5udW1lcmljKGJvc3Rvbl9iZzIkR0VPSUQpCmJvc3Rvbl9iZzIgPC0gbGVmdF9qb2luKGJvc3Rvbl9iZzIsYmdfc3VtbV8zMTEsYnk9YygiR0VPSUQiID0gIkJHX0dFT0lEIikpCmJvc3Rvbl9iZzIkbl9jYWxsc1tpcy5uYShib3N0b25fYmcyJG5fY2FsbHMpXSA8LSAwCmJvc3Rvbl9iZzIkbG9nX2NhbGxzIDwtIGxvZzFwKGJvc3Rvbl9iZzIkbl9jYWxscykKYm9zdG9uX2JnMiRiaW5fY2FsbHMgPC0gY3V0KGJvc3Rvbl9iZzIkbl9jYWxscyxicmVha3MgPSBjKC1JbmYsMyw2LDEyLDI0LEluZiksIGxhYmVscz1jKCIwLTMiLCI0LTYiLCI3LTEyIiwiMTMtMjQiLCIyNSsiKSkKYm9zdG9uX2JnMiA8LSBib3N0b25fYmcyICU+JQogICAgICBtdXRhdGUoY2hhbmdlX3NjaV9iaW5uZWQgPSBjdXQobWVhbl9jaGFuZ2Vfc2NpLCBicmVha3M9YygtSW5mLCAtMTAsIDEwLCBJbmYpLCBsYWJlbHM9YygiV29yc2UiLCJTaW1pbGFyIiwiQmV0dGVyIikpKQp0bV9zaGFwZShib3N0b25fYmcyKSArIAogICAgICB0bV9maWxsKGNvbCA9ICJiaW5fY2FsbHMiLHRpdGxlID0gIiMgb2YgMzExIFNpZGV3YWxrIENhbGxzIiwKICAgICAgICAgICAgICAgcGFsZXR0ZT0iWWxHbiIsIG49NSwKICAgICAgICAgICAgICBpZCA9ICJHRU9JRCIpCmBgYAojIyMgVHJhY3QgMzExIHZpc3VhbHM6CgpgYGB7cn0KY3Rfc3VtbV8zMTEgPC0gc3dfY2FsbHNfcHRzICU+JQogICAgICBhc190aWJibGUoKSAlPiUKICAgICAgZ3JvdXBfYnkoQ1RfR0VPSUQpICU+JQogICAgICBzdW1tYXJpemUobl9jYWxscyA9IG4oKSkgJT4lCiAgICAgIGFzLmRhdGEuZnJhbWUoKQoKYm9zdG9uX3RyYWN0czIkR0VPSUQgPC0gYXMubnVtZXJpYyhib3N0b25fdHJhY3RzMiRHRU9JRCkKYm9zdG9uX3RyYWN0czIgPC0gbGVmdF9qb2luKGJvc3Rvbl90cmFjdHMyLGN0X3N1bW1fMzExLGJ5PWMoIkdFT0lEIiA9ICJDVF9HRU9JRCIpKQpib3N0b25fdHJhY3RzMiRuX2NhbGxzW2lzLm5hKGJvc3Rvbl90cmFjdHMyJG5fY2FsbHMpXSA8LSAwCmJvc3Rvbl90cmFjdHMyJGxvZ19jYWxscyA8LSBsb2cxcChib3N0b25fdHJhY3RzMiRuX2NhbGxzKQpib3N0b25fdHJhY3RzMiRiaW5fY2FsbHMgPC0gY3V0KGJvc3Rvbl90cmFjdHMyJG5fY2FsbHMsYnJlYWtzID0gYygtSW5mLDEwLDI1LDQwLDU1LEluZiksIGxhYmVscz1jKCIwLTEwIiwiMTEtMjUiLCIyNi00MCIsIjQxLTU1IiwiNTYrIikpCmJvc3Rvbl90cmFjdHMyIDwtIGJvc3Rvbl90cmFjdHMyICU+JQogICAgICBtdXRhdGUoY2hhbmdlX3NjaV9iaW5uZWQgPSBjdXQobWVhbl9jaGFuZ2Vfc2NpLCBicmVha3M9YygtSW5mLCAtMTAsIDEwLCBJbmYpLCBsYWJlbHM9YygiV29yc2UiLCJTaW1pbGFyIiwiQmV0dGVyIikpKQoKdG1fc2hhcGUoYm9zdG9uX3RyYWN0czIpICsgCiAgICAgIHRtX2ZpbGwoY29sID0gImJpbl9jYWxscyIsdGl0bGUgPSAiIyBvZiAzMTEgU2lkZXdhbGsgQ2FsbHMiLAogICAgICAgICAgICAgICBwYWxldHRlPSJZbEduIiwgbj01LG1pZHBvaW50PSwKICAgICAgICAgICAgICBpZCA9ICJUUkFDVENFIikKYGBgCgojIyBIb3cgZG8gMzExIGNhbGxzIGFuZCBTVyBxdWFsaXR5IGRpZmZlcmVuY2VzIG1hdGNoIHVwIGF0IHZhcmlvdXMgYWdncmVnYXRlIGxldmVscz8KVHJhY3QtbGV2ZWw6CmBgYHtyfQpzdGF0czo6Y29yKGJvc3Rvbl90cmFjdHMyJG1lYW5fY2hhbmdlX3NjaSx5PWJvc3Rvbl90cmFjdHMyJG5fY2FsbHMsdXNlID0gImNvbXBsZXRlLm9icyIpCnN0YXRzOjpjb3IoYm9zdG9uX3RyYWN0czIkbWVhbl9jaGFuZ2Vfc2NpLHk9bG9nMXAoYm9zdG9uX3RyYWN0czIkbl9jYWxscyksdXNlID0gImNvbXBsZXRlLm9icyIpCnN1bW1hcnkobG0oYm9zdG9uX3RyYWN0czIkbWVhbl9jaGFuZ2Vfc2NpIH4gYm9zdG9uX3RyYWN0czIkbl9jYWxscykpICMgbmVnLCBpbnNpZwpzdW1tYXJ5KGxtKChib3N0b25fdHJhY3RzMiRjaGFuZ2Vfc2NpX2Jpbm5lZD09IkJldHRlciIpIH4gbG9nMXAoYm9zdG9uX3RyYWN0czIkbl9jYWxscykpKSAjIG5lZywgc2lnbmlmaWNhbnQKc3VtbWFyeShsbSgoYm9zdG9uX3RyYWN0czIkY2hhbmdlX3NjaV9iaW5uZWQ9PSJCZXR0ZXIiKSB+IGJvc3Rvbl90cmFjdHMyJG5fY2FsbHMqKGJvc3Rvbl90cmFjdHMyJG1lYW5fc2NpX3QxPm1lZGlhbihib3N0b25fdHJhY3RzMiRtZWFuX3NjaV90MSxuYS5ybT1UKSkpKSAjIGRpZmZlcmVudGlhbCBpbXBhY3Qgb2YgY2FsbHM6IGFsbCBpbnNpZyBleGNlcHQgbGVzcyBsaWtlbHkgdG8gZ2V0IGJldHRlciBpZiBuaWNlciBhcmVhCgpgYGAKCkJHLWxldmVsOgpgYGB7cn0Kc3RhdHM6OmNvcihib3N0b25fYmcyJG1lYW5fY2hhbmdlX3NjaSx5PWJvc3Rvbl9iZzIkbl9jYWxscyx1c2UgPSAiY29tcGxldGUub2JzIikgIyBwb3NpdGl2ZQpzdGF0czo6Y29yKGJvc3Rvbl9iZzIkbWVhbl9jaGFuZ2Vfc2NpLHk9bG9nMXAoYm9zdG9uX2JnMiRuX2NhbGxzKSx1c2UgPSAiY29tcGxldGUub2JzIikgIyBuZWcKIyBzdW1tYXJ5KGxtKGJvc3Rvbl9iZzIkbWVhbl9jaGFuZ2Vfc2NpIH4gKGJvc3Rvbl9iZzIkbl9jYWxscz4wKSkpCnN1bW1hcnkobG0oKGJvc3Rvbl9iZzIkY2hhbmdlX3NjaV9iaW5uZWQ9PSJCZXR0ZXIiKSB+IGxvZzFwKGJvc3Rvbl9iZzIkbl9jYWxscykpKSAjIG5lZywgaW5zaWcKc3VtbWFyeShsbSgoYm9zdG9uX2JnMiRjaGFuZ2Vfc2NpX2Jpbm5lZD09IkJldHRlciIpIH4gKGJvc3Rvbl9iZzIkbl9jYWxscykqKGJvc3Rvbl9iZzIkbWVhbl9zY2lfdDE+bWVkaWFuKGJvc3Rvbl9iZzIkbWVhbl9zY2lfdDEsbmEucm09VCkpKSkgIyBkaWZmZXJlbnRpYWwgaW1wYWN0IG9mIGNhbGxzOiBub3RoaW5nIHNpZ25pZmljYW50IGV4Y2VwdCBuaWNlciBhcmVhcyBsZXNzIGxpa2VseSB0byBnZXQgYmV0dGVyCmBgYAoKc3RyZWV0LWxldmVsOgpgYGB7cn0Kc3RhdHM6OmNvcihib3N0b25fc3RyZWV0c19zY2kkbWVhbl9jaGFuZ2Vfc2NpLHk9Ym9zdG9uX3N0cmVldHNfc2NpJG5fY2FsbHMsdXNlID0gImNvbXBsZXRlLm9icyIpCnN0YXRzOjpjb3IoYm9zdG9uX3N0cmVldHNfc2NpJG1lYW5fY2hhbmdlX3NjaSx5PWxvZzFwKGJvc3Rvbl9zdHJlZXRzX3NjaSRuX2NhbGxzKSx1c2UgPSAiY29tcGxldGUub2JzIikKc3VtbWFyeShsbShib3N0b25fc3RyZWV0c19zY2kkbWVhbl9jaGFuZ2Vfc2NpIH4gKGJvc3Rvbl9zdHJlZXRzX3NjaSRuX2NhbGxzPjApKSkKc3VtbWFyeShsbShib3N0b25fc3RyZWV0c19zY2kkbWVhbl9jaGFuZ2Vfc2NpIH4gbG9nMXAoYm9zdG9uX3N0cmVldHNfc2NpJG5fY2FsbHMpKSkKc3VtbWFyeShsbSgoYm9zdG9uX3N0cmVldHNfc2NpJGNoYW5nZV9zY2k9PSJCZXR0ZXIiKSB+IGxvZzFwKGJvc3Rvbl9zdHJlZXRzX3NjaSRuX2NhbGxzKSkpICMgbmVnYXRpdmUsIGluc2lnCnN1bW1hcnkobG0oKGJvc3Rvbl9zdHJlZXRzX3NjaSRjaGFuZ2Vfc2NpPT0iQmV0dGVyIikgfiBib3N0b25fc3RyZWV0c19zY2kkbl9jYWxscyooYm9zdG9uX3N0cmVldHNfc2NpJG1lYW5fc2NpX3QxPm1lZGlhbihib3N0b25fc3RyZWV0c19zY2kkbWVhbl9zY2lfdDEpKSkpICMgZGlmZmVyZW50aWFsIGltcGFjdCBvZiBjYWxsczogbm90aGluZyBzaWcgZXhjZXB0IG5pY2VyIGFyZWFzIGxlc3MgbGlrZWx5IHRvIGdldCBiZXR0ZXIKYGBgCgojIFZpc3VhbGl6aW5nIGNvcnJlbGF0aW9uIGJldHdlZW4gY2FsbHMgYW5kIGNoYW5nZSBpbiBzaWRld2FsayBjb25kaXRpb25zOgpgYGB7cn0KcGxvdChsb2cxcChib3N0b25fc3RyZWV0c19zY2kkbl9jYWxscyksYm9zdG9uX3N0cmVldHNfc2NpJG1lYW5fY2hhbmdlX3NjaSx4bGltPWMoMCw0KSxwY2g9MTYsY29sPSJncmV5IixtYWluPSJTdHJlZXQgc2VnbWVudC1sZXZlbCIseWxhYj0iQ2hhbmdlIGluIHNpZGV3YWxrIGNvbmRpdGlvbnMiLHhsYWI9Ik51bWJlciBvZiAzMTEgY2FsbHMiKQojIGxpbmVzKGxvd2Vzcyhib3N0b25fc3RyZWV0c19zY2kkbWVhbl9jaGFuZ2Vfc2NpIH4gbG9nMXAoYm9zdG9uX3N0cmVldHNfc2NpJG5fY2FsbHMpKSxjb2w9InJlZCIpCmxpbmVzKGxvd2Vzcyhib3N0b25fc3RyZWV0c19zY2kkbWVhbl9jaGFuZ2Vfc2NpW3doaWNoKGJvc3Rvbl9zdHJlZXRzX3NjaSRtZWFuX3NjaV90MTxtZWRpYW4oYm9zdG9uX3N0cmVldHNfc2NpJG1lYW5fc2NpX3QxLG5hLnJtPVQpKV0gfiBsb2cxcChib3N0b25fc3RyZWV0c19zY2kkbl9jYWxsc1t3aGljaChib3N0b25fc3RyZWV0c19zY2kkbWVhbl9zY2lfdDE8bWVkaWFuKGJvc3Rvbl9zdHJlZXRzX3NjaSRtZWFuX3NjaV90MSxuYS5ybT1UKSldKSksY29sPSJyZWQiLGx3ZD0yKQpsaW5lcyhsb3dlc3MoYm9zdG9uX3N0cmVldHNfc2NpJG1lYW5fY2hhbmdlX3NjaVt3aGljaChib3N0b25fc3RyZWV0c19zY2kkbWVhbl9zY2lfdDE+bWVkaWFuKGJvc3Rvbl9zdHJlZXRzX3NjaSRtZWFuX3NjaV90MSxuYS5ybT1UKSldIH4gbG9nMXAoYm9zdG9uX3N0cmVldHNfc2NpJG5fY2FsbHNbd2hpY2goYm9zdG9uX3N0cmVldHNfc2NpJG1lYW5fc2NpX3QxPm1lZGlhbihib3N0b25fc3RyZWV0c19zY2kkbWVhbl9zY2lfdDEsbmEucm09VCkpXSkpLGNvbD0iYmx1ZSIsbHdkPTIpCmBgYApgYGB7cn0KcGxvdChsb2cxcChib3N0b25fYmcyJG5fY2FsbHMpLGJvc3Rvbl9iZzIkbWVhbl9jaGFuZ2Vfc2NpLHhsaW09YygwLDUpLHBjaD0xNixjb2w9ImdyZXkiLG1haW49IkJsb2NrZ3JvdXAtbGV2ZWwiLHlsYWI9IkNoYW5nZSBpbiBzaWRld2FsayBjb25kaXRpb25zIix4bGFiPSJOdW1iZXIgb2YgMzExIGNhbGxzIikKIyBsaW5lcyhsb3dlc3MoYm9zdG9uX2JnMiRtZWFuX2NoYW5nZV9zY2kgfiBsb2cxcChib3N0b25fYmcyJG5fY2FsbHMpKSxjb2w9InJlZCIpCmxpbmVzKGxvd2Vzcyhib3N0b25fYmcyJG1lYW5fY2hhbmdlX3NjaVt3aGljaChib3N0b25fYmcyJG1lYW5fc2NpX3QxPm1lZGlhbihib3N0b25fYmcyJG1lYW5fc2NpX3QxLG5hLnJtPVQpKV0gfiBsb2cxcChib3N0b25fYmcyJG5fY2FsbHNbd2hpY2goYm9zdG9uX2JnMiRtZWFuX3NjaV90MT5tZWRpYW4oYm9zdG9uX2JnMiRtZWFuX3NjaV90MSxuYS5ybT1UKSldKSksY29sPSJibHVlIixsd2Q9MikKbGluZXMobG93ZXNzKGJvc3Rvbl9iZzIkbWVhbl9jaGFuZ2Vfc2NpW3doaWNoKGJvc3Rvbl9iZzIkbWVhbl9zY2lfdDE8PW1lZGlhbihib3N0b25fYmcyJG1lYW5fc2NpX3QxLG5hLnJtPVQpKV0gfiBsb2cxcChib3N0b25fYmcyJG5fY2FsbHNbd2hpY2goYm9zdG9uX2JnMiRtZWFuX3NjaV90MTw9bWVkaWFuKGJvc3Rvbl9iZzIkbWVhbl9zY2lfdDEsbmEucm09VCkpXSkpLGNvbD0icmVkIixsd2Q9MikKYGBgCgpgYGB7cn0KcGxvdChsb2cxcChib3N0b25fdHJhY3RzMiRuX2NhbGxzKSxib3N0b25fdHJhY3RzMiRtZWFuX2NoYW5nZV9zY2kseGxpbT1jKDAsNSkscGNoPTE2LGNvbD0iZ3JleSIsbWFpbj0iVHJhY3QtbGV2ZWwiLHlsYWI9IkNoYW5nZSBpbiBzaWRld2FsayBjb25kaXRpb25zIix4bGFiPSJOdW1iZXIgb2YgMzExIGNhbGxzIikKIyBsaW5lcyhsb3dlc3MoYm9zdG9uX3RyYWN0czIkbWVhbl9jaGFuZ2Vfc2NpIH4gbG9nMXAoYm9zdG9uX3RyYWN0czIkbl9jYWxscykpLGNvbD0icmVkIikKbGluZXMobG93ZXNzKGJvc3Rvbl90cmFjdHMyJG1lYW5fY2hhbmdlX3NjaVt3aGljaChib3N0b25fdHJhY3RzMiRtZWFuX3NjaV90MT5tZWRpYW4oYm9zdG9uX3RyYWN0czIkbWVhbl9zY2lfdDEsbmEucm09VCkpXSB+IGxvZzFwKGJvc3Rvbl90cmFjdHMyJG5fY2FsbHNbd2hpY2goYm9zdG9uX3RyYWN0czIkbWVhbl9zY2lfdDE+bWVkaWFuKGJvc3Rvbl90cmFjdHMyJG1lYW5fc2NpX3QxLG5hLnJtPVQpKV0pKSxjb2w9ImJsdWUiLGx3ZD0yKQpsaW5lcyhsb3dlc3MoYm9zdG9uX3RyYWN0czIkbWVhbl9jaGFuZ2Vfc2NpW3doaWNoKGJvc3Rvbl90cmFjdHMyJG1lYW5fc2NpX3QxPD1tZWRpYW4oYm9zdG9uX3RyYWN0czIkbWVhbl9zY2lfdDEsbmEucm09VCkpXSB+IGxvZzFwKGJvc3Rvbl90cmFjdHMyJG5fY2FsbHNbd2hpY2goYm9zdG9uX3RyYWN0czIkbWVhbl9zY2lfdDE8PW1lZGlhbihib3N0b25fdHJhY3RzMiRtZWFuX3NjaV90MSxuYS5ybT1UKSldKSksY29sPSJyZWQiLGx3ZD0yKQpgYGAKCgojIyBOaWNlciBiaXZhcmlhdGUgdmlzdWFsczoKYGBge3J9Cih0cmFjdF9iaXZhcmlhdGUgPC0gZ2dwbG90KGJvc3Rvbl90cmFjdHMyKSArIAogICAgICBnZW9tX3BvaW50KGFlcyh4PW5fY2FsbHMseT1tZWFuX2NoYW5nZV9zY2kpLGNvbD0iZ3JleSIpICsgCiAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMoIk51bWJlciBvZiAzMTEgY2FsbHNcbihsb2cgc2NhbGUpIix0cmFucz0ibG9nMTAiLGJyZWFrcz1jKDEsMTAsNTAsMTAwKSkgKyAKICAgICAgIHNjYWxlX3lfY29udGludW91cygiQ2hhbmdlIGluIHNpZGV3YWxrIGNvbmRpdGlvbnMiLGxpbWl0cz1jKC00MCw0MCksYnJlYWtzPXNlcSgtNDAsNDAsMjApLGxhYmVscz1jKCJcbi00MFxuKFdvcnNlKSIsIi0yMCIsIjAiLCIyMCIsIihCZXR0ZXIpXG40MFxuIikpICsgCiAgICAgICBnZW9tX3Ntb290aChkYXRhPXN1YnNldChib3N0b25fdHJhY3RzMixtZWFuX3NjaV90MT5tZWRpYW4oYm9zdG9uX3RyYWN0czIkbWVhbl9zY2lfdDEsbmEucm09VCkpLAogICAgICAgICAgICAgICAgICAgYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJibHVlIixsd2Q9MSxtZXRob2Q9ImxvZXNzIixzZT1GKSArIAogICAgICAgZ2VvbV9zbW9vdGgoZGF0YT1zdWJzZXQoYm9zdG9uX3RyYWN0czIsbWVhbl9zY2lfdDE8PW1lZGlhbihib3N0b25fdHJhY3RzMiRtZWFuX3NjaV90MSxuYS5ybT1UKSksCiAgICAgICAgICAgICAgICAgICBhZXMoeD1uX2NhbGxzLHk9bWVhbl9jaGFuZ2Vfc2NpKSxjb2w9InJlZCIsbHdkPTEsbWV0aG9kPSJsb2VzcyIsc2U9RikgKyAKICAgICAgIGFubm90YXRlKCJ0ZXh0Iix4PTEuNSx5PTIwLGxhYmVsPSJXb3JzZSB0cmFjdHMgaW4gMjAxMiIsY29sPSJyZWQiLHNpemU9MyxoanVzdD0wKSArCiAgICAgICBhbm5vdGF0ZSgidGV4dCIseD0xLHk9LTUsbGFiZWw9IkJldHRlciB0cmFjdHMgaW4gMjAxMiIsY29sPSJibHVlIixzaXplPTMsaGp1c3Q9MCkgKwogICAgICAgdGhlbWVfYncoKQopCmBgYApgYGB7cn0KKGJnX2JpdmFyaWF0ZSA8LSBnZ3Bsb3QoYm9zdG9uX2JnMikgKyAKICAgICAgZ2VvbV9wb2ludChhZXMoeD1uX2NhbGxzLHk9bWVhbl9jaGFuZ2Vfc2NpKSxjb2w9ImdyZXkiKSArIAogICAgICAgc2NhbGVfeF9jb250aW51b3VzKCJOdW1iZXIgb2YgMzExIGNhbGxzXG4obG9nIHNjYWxlKSIsdHJhbnM9ImxvZzEwIixsaW1pdHM9YygwLjgsMTIwKSxicmVha3M9YygxLDUsMTAsNTAsMTAwKSkgKyAKICAgICAgIHNjYWxlX3lfY29udGludW91cygiQ2hhbmdlIGluIHNpZGV3YWxrIGNvbmRpdGlvbnMiLCBsaW1pdHM9YygtNDAsNDApLCBicmVha3M9c2VxKC00MCw0MCwyMCksIGxhYmVscz1jKCJcbi00MFxuKFdvcnNlKSIsIi0yMCIsIjAiLCIyMCIsIihCZXR0ZXIpXG40MFxuIikpICsgCiAgICAgICBnZW9tX3Ntb290aChkYXRhPXN1YnNldChib3N0b25fYmcyLG1lYW5fc2NpX3QxPm1lZGlhbihib3N0b25fYmcyJG1lYW5fc2NpX3QxLG5hLnJtPVQpKSwKICAgICAgICAgICAgICAgICAgIGFlcyh4PW5fY2FsbHMseT1tZWFuX2NoYW5nZV9zY2kpLGNvbD0iYmx1ZSIsbHdkPTEsbWV0aG9kPSJsb2VzcyIsc2U9RikgKyAKICAgICAgIGdlb21fc21vb3RoKGRhdGE9c3Vic2V0KGJvc3Rvbl9iZzIsbWVhbl9zY2lfdDE8PW1lZGlhbihib3N0b25fYmcyJG1lYW5fc2NpX3QxLG5hLnJtPVQpKSwKICAgICAgICAgICAgICAgICAgIGFlcyh4PW5fY2FsbHMseT1tZWFuX2NoYW5nZV9zY2kpLGNvbD0icmVkIixsd2Q9MSxtZXRob2Q9ImxvZXNzIixzZT1GKSArIAogICAgICAgYW5ub3RhdGUoInRleHQiLHg9MS4wLHk9MTAsbGFiZWw9IldvcnNlIGJsb2NrZ3JvdXBzIGluIDIwMTIiLGNvbD0icmVkIixzaXplPTMsaGp1c3Q9MCkgKwogICAgICAgYW5ub3RhdGUoInRleHQiLHg9MSx5PS04LGxhYmVsPSJCZXR0ZXIgYmxvY2tncm91cHMgaW4gMjAxMiIsY29sPSJibHVlIixzaXplPTMsaGp1c3Q9MCkgKwogICAgICAgdGhlbWVfYncoKQopCmBgYAoKYGBge3J9CihzdHJlZXRfYml2YXJpYXRlIDwtIGdncGxvdChib3N0b25fc3RyZWV0c19zY2kpICsgCiAgICAgIGdlb21fcG9pbnQoYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJncmV5IikgKyAKICAgICAgIHNjYWxlX3hfY29udGludW91cygiTnVtYmVyIG9mIDMxMSBjYWxsc1xuKGxvZyBzY2FsZSkiLHRyYW5zPSJsb2cxMCIsbGltaXRzPWMoMC44LDUwKSxicmVha3M9YygxLDUsMTAsMjAsNDApKSArIAogICAgICAgc2NhbGVfeV9jb250aW51b3VzKCJDaGFuZ2UgaW4gc2lkZXdhbGsgY29uZGl0aW9ucyIsIGxpbWl0cz1jKC0xMDAsMTAwKSwgYnJlYWtzPXNlcSgtMTAwLDEwMCw1MCksIGxhYmVscz1jKCJcbi0xMDBcbihXb3JzZSkiLCItNTAiLCIwIiwiNTAiLCIoQmV0dGVyKVxuMTAwXG4iKSkgKyAKICAgICAgIGdlb21fc21vb3RoKGRhdGE9c3Vic2V0KGJvc3Rvbl9zdHJlZXRzX3NjaSxtZWFuX3NjaV90MT5tZWRpYW4oYm9zdG9uX3N0cmVldHNfc2NpJG1lYW5fc2NpX3QxLG5hLnJtPVQpKSwKICAgICAgICAgICAgICAgICAgIGFlcyh4PW5fY2FsbHMseT1tZWFuX2NoYW5nZV9zY2kpLGNvbD0iYmx1ZSIsbHdkPTEsbWV0aG9kPSJsb2VzcyIsc2U9RikgKyAKICAgICAgIGdlb21fc21vb3RoKGRhdGE9c3Vic2V0KGJvc3Rvbl9zdHJlZXRzX3NjaSxtZWFuX3NjaV90MTw9bWVkaWFuKGJvc3Rvbl9zdHJlZXRzX3NjaSRtZWFuX3NjaV90MSxuYS5ybT1UKSksCiAgICAgICAgICAgICAgICAgICBhZXMoeD1uX2NhbGxzLHk9bWVhbl9jaGFuZ2Vfc2NpKSxjb2w9InJlZCIsbHdkPTEsbWV0aG9kPSJsb2VzcyIsc2U9RikgKyAKICAgICAgIGFubm90YXRlKCJ0ZXh0Iix4PTAuOCx5PTE1LGxhYmVsPSJXb3JzZSBzdHJlZXQgc2VnbWVudHMgaW4gMjAxMiIsY29sPSJyZWQiLHNpemU9MyxoanVzdD0wKSArCiAgICAgICBhbm5vdGF0ZSgidGV4dCIseD0wLjgseT0tMTUsbGFiZWw9IkJldHRlciBzdHJlZXQgc2VnbWVudHMgaW4gMjAxMiIsY29sPSJibHVlIixzaXplPTMsaGp1c3Q9MCkgKwogICAgICAgdGhlbWVfYncoKQopCmBgYAoKCmBgYHtyfQojIFNhdmluZyB2aXN1YWxzCmdnc2F2ZSh0cmFjdF9iaXZhcmlhdGUsZmlsZT0iZmlndXJlcy9jYWxsc19jaGFuZ2VTQ0lfY3QucGRmIixoZWlnaHQ9NCx3aWR0aD02KQpnZ3NhdmUoYmdfYml2YXJpYXRlLGZpbGU9ImZpZ3VyZXMvY2FsbHNfY2hhbmdlU0NJX2JnLnBkZiIsaGVpZ2h0PTQsd2lkdGg9NikKZ2dzYXZlKHN0cmVldF9iaXZhcmlhdGUsZmlsZT0iZmlndXJlcy9jYWxsc19jaGFuZ2VTQ0lfc3RyZWV0cy5wZGYiLGhlaWdodD00LHdpZHRoPTYpCmBgYAoKCiMgRGVtb2dyYXBoaWMgYW5hbHlzZXMKCk5vdyBsZXRzIGJyaW5nIGluIGRlbW9ncmFwaGljcyB0byBkbyBzb21ldGhpbmcgbW9yZSB0aGFuIGJpdmFyaWF0ZSBhbmFseXNlczoKYGBge3J9CmJnc19kYXQgPC0gdGlkeWNlbnN1czo6Z2V0X2FjcyhnZW9ncmFwaHkgPSAiYmxvY2sgZ3JvdXAiLHN0YXRlPSJNYXNzYWNodXNldHRzIix5ZWFyID0gMjAxNixvdXRwdXQgPSAid2lkZSIsCgkJCQkJCQkJCQkJCQkJCQkJdmFyaWFibGVzID0gYygiQjAxMDAzXzAwMSIsICMgdG90YWwgcG9wCgkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCSJCMTkwMTNfMDAxIiwgIyBtZWRpYW4gaW5jb21lCgkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCSJCMDEwMDJfMDAyIiwgIyBtZWRpYW4gYWdlCgkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCSJCMTYwMTBfMDQxIiwgIyAlIGJhY2hlbG9yJ3MgZGVncmVlIG9yIGhpZ2hlcgoJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkiQjIzMDA2XzAyMyIsICMgYWxzbyBiYWNoZWxvcidzIGRlZ3JlZT8KCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJIkIwMjAwMV8wMDIiICMgd2hpdGUgcG9wIGFsb25lCgkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCSkpICU+JQoJbXV0YXRlKEdFT0lEID0gYXMubnVtZXJpYyhHRU9JRCkpCiMjIGpvaW4gQUNTIGRhdGEgdG8gc2hhcGVzOgpib3N0b25fYmczIDwtIGxlZnRfam9pbihib3N0b25fYmcyLGJnc19kYXQsYnk9IkdFT0lEIikKYm9zdG9uX2JnMyA8LSBib3N0b25fYmczICU+JQoJbXV0YXRlKAoJCWhpX2luYyA9IGFzLm51bWVyaWMoQjE5MDEzXzAwMUU+PW1lZGlhbihCMTkwMTNfMDAxRSxuYS5ybT1UKSksCgkJYmFjaF9kZWdyZWVfcGVyYyA9IEIxNjAxMF8wNDFFL0IwMTAwM18wMDFFLAoJCWhpX2VkdWMgPSBhcy5udW1lcmljKGJhY2hfZGVncmVlX3BlcmM+PW1lZGlhbihiYWNoX2RlZ3JlZV9wZXJjLG5hLnJtPVQpKSwKCQl3aGl0ZV9wZXJjID0gQjAyMDAxXzAwMkUvQjAxMDAzXzAwMUUsCgkJaGlfd2hpdGUgPSBhcy5udW1lcmljKHdoaXRlX3BlcmM+PW1lZGlhbih3aGl0ZV9wZXJjLG5hLnJtPVQpKQoJCQkJICkKCmN0c19kYXQgPC0gdGlkeWNlbnN1czo6Z2V0X2FjcyhnZW9ncmFwaHkgPSAidHJhY3QiLHN0YXRlPSJNYXNzYWNodXNldHRzIix5ZWFyID0gMjAxNixvdXRwdXQgPSAid2lkZSIsCgkJCQkJCQkJCQkJCQkJCSB2YXJpYWJsZXMgPSBjKCJCMDEwMDNfMDAxIiwgIyB0b3RhbCBwb3AKCQkJCQkJCQkJCQkJCQkJIAkJCQkJCQkiQjE5MDEzXzAwMSIsICMgbWVkaWFuIGluY29tZQoJCQkJCQkJCQkJCQkJCQkgCQkJCQkJCSJCMDEwMDJfMDAyIiwgIyBtZWRpYW4gYWdlCgkJCQkJCQkJCQkJCQkJCSAJCQkJCQkJIkIxNjAxMF8wNDEiLCAjICUgYmFjaGVsb3IncyBkZWdyZWUgb3IgaGlnaGVyCgkJCQkJCQkJCQkJCQkJCSAJCQkJCQkJIkIyMzAwNl8wMjMiLCAjIGFsc28gYmFjaGVsb3IncyBkZWdyZWU/CgkJCQkJCQkJCQkJCQkJCSAJCQkJCQkJIkIwMjAwMV8wMDIiICMgd2hpdGUgcG9wIGFsb25lCgkJCQkJCQkJCQkJCQkJCSApKSAlPiUKCW11dGF0ZShHRU9JRCA9IGFzLm51bWVyaWMoR0VPSUQpKQojIyBqb2luIEFDUyBkYXRhIHRvIHNoYXBlczoKYm9zdG9uX3RyYWN0czMgPC0gbGVmdF9qb2luKGJvc3Rvbl90cmFjdHMyLGN0c19kYXQsYnk9IkdFT0lEIikKIyBjcmVhdGUgYmlubmVkIHZhcmlhYmxlczoKYm9zdG9uX3RyYWN0czMgPC0gYm9zdG9uX3RyYWN0czMgJT4lCgltdXRhdGUoCgkJaGlfaW5jID0gYXMubnVtZXJpYyhCMTkwMTNfMDAxRT49bWVkaWFuKEIxOTAxM18wMDFFLG5hLnJtPVQpKSwKCQliYWNoX2RlZ3JlZV9wZXJjID0gQjE2MDEwXzA0MUUvQjAxMDAzXzAwMUUsCgkJaGlfZWR1YyA9IGFzLm51bWVyaWMoYmFjaF9kZWdyZWVfcGVyYz49bWVkaWFuKGJhY2hfZGVncmVlX3BlcmMsbmEucm09VCkpLAoJCXdoaXRlX3BlcmMgPSBCMDIwMDFfMDAyRS9CMDEwMDNfMDAxRSwKCQloaV93aGl0ZSA9IGFzLm51bWVyaWMod2hpdGVfcGVyYz49bWVkaWFuKHdoaXRlX3BlcmMsbmEucm09VCkpCgkJCQkgKQoKIyMjIEJhc2ljIGFuYWx5c2VzIG9mIGltcHJvdmVtZW50IGluIGNvbmRpdGlvbnMKIyMgVHJhY3QtbGV2ZWw6CiMgaW5jb21lOgpzdW1tYXJ5KGxtKGJvc3Rvbl90cmFjdHMzJG1lYW5fY2hhbmdlX3NjaSB+IChib3N0b25fdHJhY3RzMyRuX2NhbGxzPjApKSkKc3VtbWFyeShsbShib3N0b25fdHJhY3RzMyRtZWFuX2NoYW5nZV9zY2kgfiBsb2cxcChib3N0b25fdHJhY3RzMyRuX2NhbGxzKSkpCnN1bW1hcnkobG0oKGJvc3Rvbl90cmFjdHMzJGNoYW5nZV9zY2k9PSJCZXR0ZXIiKSB+IGxvZzFwKGJvc3Rvbl90cmFjdHMzJG5fY2FsbHMpKSkgIyBuZWdhdGl2ZSwgaW5zaWcKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBoaV9pbmMsZGF0YT1ib3N0b25fdHJhY3RzMykpICMgaW5zaWcgcG9zaXRpdmUgZWZmZWN0CnN1bW1hcnkobG0oY2hhbmdlX3NjaV9iaW5uZWQ9PSJCZXR0ZXIiIH4gaGlfaW5jLGRhdGE9Ym9zdG9uX3RyYWN0czMpKSAjIGluc2lnIG5lZyBlZmZlY3QKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBCMTkwMTNfMDAxRSxkYXRhPWJvc3Rvbl90cmFjdHMzKSkgIyBpbnNpZyBuZWcgZWZmZWN0CnN1bW1hcnkobG0oY2hhbmdlX3NjaV9iaW5uZWQ9PSJCZXR0ZXIiIH4gQjE5MDEzXzAwMUUsZGF0YT1ib3N0b25fdHJhY3RzMykpICMgaW5zaWcgbmVnIGVmZmVjdAoKc3VtbWFyeShsbSgoY2hhbmdlX3NjaV9iaW5uZWQ9PSJCZXR0ZXIiKSB+IG5fY2FsbHMqQjE5MDEzXzAwMUUsIGRhdGEgPSBib3N0b25fdHJhY3RzMykpICMgZGlmZmVyZW50aWFsIGltcGFjdCBvZiBjYWxsczogbm90aGluZyBzaWcsIGhpZ2hlciBpbmNvbWUgYXJlYXMgc2xpZ2h0bHkgc21hbGxlciBlZmZlY3Qgb2Ygbl9jYWxscwpzdW1tYXJ5KGxtKG1lYW5fY2hhbmdlX3NjaSB+IG5fY2FsbHMqQjE5MDEzXzAwMUUsIGRhdGEgPSBib3N0b25fdHJhY3RzMykpICMgbm90aGluZyBzaWcKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBsb2cxcChuX2NhbGxzKSpCMTkwMTNfMDAxRSwgZGF0YSA9IGJvc3Rvbl90cmFjdHMzKSkgIyBub3RoaW5nIHNpZwpzdW1tYXJ5KGxtKChjaGFuZ2Vfc2NpX2Jpbm5lZD09IkJldHRlciIpIH4gbG9nMXAobl9jYWxscykqQjE5MDEzXzAwMUUsIGRhdGEgPSBib3N0b25fdHJhY3RzMykpICMgZGlmZmVyZW50aWFsIGltcGFjdCBvZiBjYWxsczogbm90aGluZyBzaWcsIGhpZ2hlciBpbmNvbWUgYXJlYXMgc2xpZ2h0bHkgc21hbGxlciBlZmZlY3Qgb2Ygbl9jYWxscwpzdW1tYXJ5KGxtKG1lYW5fY2hhbmdlX3NjaSB+IGxvZzFwKG5fY2FsbHMpKkIxOTAxM18wMDFFLCBkYXRhID0gYm9zdG9uX3RyYWN0czMpKSAjIGRpZmZlcmVudGlhbCBpbXBhY3Qgb2YgY2FsbHM6IG5vdGhpbmcgc2lnCgojIHJhY2U6CnN1bW1hcnkobG0obWVhbl9jaGFuZ2Vfc2NpIH4gd2hpdGVfcGVyYywgZGF0YSA9IGJvc3Rvbl90cmFjdHMzKSkgIyB3aGl0ZXIgdHJhY3RzIGhhdmUgbXVjaCBiZXR0ZXIgaW1wcm92ZW1lbnQKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBoaV93aGl0ZSwgZGF0YSA9IGJvc3Rvbl90cmFjdHMzKSkgIyB3aGl0ZXIgdHJhY3RzIGhhdmUgbXVjaCBiZXR0ZXIgaW1wcm92ZW1lbnQKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBsb2cxcChuX2NhbGxzKSp3aGl0ZV9wZXJjLCBkYXRhID0gYm9zdG9uX3RyYWN0czMpKSAjIHdoaXRlciB0cmFjdHMgaGF2ZSBtb3JlIGltcHJvdmVtZW50LCBtYXJnaW5hbCBuZWcgaW50eApzdW1tYXJ5KGxtKG1lYW5fY2hhbmdlX3NjaSB+IGxvZzFwKG5fY2FsbHMpKmhpX3doaXRlLCBkYXRhID0gYm9zdG9uX3RyYWN0czMpKSAjIHdoaXRlciB0cmFjdHMgaGF2ZSBtb3JlIGltcHJvdmVtZW50LCBzaWcgbmVnIGludHgKc3VtbWFyeShsbShjaGFuZ2Vfc2NpX2Jpbm5lZD09IkJldHRlciIgfiBsb2cxcChuX2NhbGxzKSp3aGl0ZV9wZXJjLCBkYXRhID0gYm9zdG9uX3RyYWN0czMpKSAjIHdoaXRlciB0cmFjdHMgaGF2ZSBtb3JlIGltcHJvdmVtZW50LCBtYXJnaW5hbCBuZWcgaW50eApzdW1tYXJ5KGxtKGNoYW5nZV9zY2lfYmlubmVkPT0iQmV0dGVyIiB+IGxvZzFwKG5fY2FsbHMpKmhpX3doaXRlLCBkYXRhID0gYm9zdG9uX3RyYWN0czMpKSAjIHdoaXRlciB0cmFjdHMgaGF2ZSBtb3JlIGltcHJvdmVtZW50LCBzaWcgbmVnIGludHgKCiMjIEJHLWxldmVsCiMgaW5jb21lOgpzdW1tYXJ5KGxtKG1lYW5fY2hhbmdlX3NjaSB+IChuX2NhbGxzPjApLGRhdGE9Ym9zdG9uX2JnMykpICMgaW5zaWcgcG9zaXRpdmUKc3VtbWFyeShsbSgoY2hhbmdlX3NjaV9iaW5uZWQ9PSJCZXR0ZXIiKSB+IGxvZzFwKG5fY2FsbHMpLGRhdGE9Ym9zdG9uX2JnMykpICMgaW5zaWcgbmVnYXRpdmUKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBoaV9pbmMsZGF0YT1ib3N0b25fYmczKSkgIyBpbnNpZyBwb3NpdGl2ZSBlZmZlY3QKc3VtbWFyeShsbShjaGFuZ2Vfc2NpX2Jpbm5lZD09IkJldHRlciIgfiBoaV9pbmMsZGF0YT1ib3N0b25fYmczKSkgIyBpbnNpZyBwb3MgZWZmZWN0CnN1bW1hcnkobG0obWVhbl9jaGFuZ2Vfc2NpIH4gQjE5MDEzXzAwMUUsZGF0YT1ib3N0b25fYmczKSkgIyBpbnNpZyBwb3MgZWZmZWN0CnN1bW1hcnkobG0oY2hhbmdlX3NjaV9iaW5uZWQ9PSJCZXR0ZXIiIH4gQjE5MDEzXzAwMUUsZGF0YT1ib3N0b25fYmczKSkgIyBpbnNpZyBwb3MgZWZmZWN0CgpzdW1tYXJ5KGxtKChjaGFuZ2Vfc2NpX2Jpbm5lZD09IkJldHRlciIpIH4gbl9jYWxscypCMTkwMTNfMDAxRSwgZGF0YSA9IGJvc3Rvbl9iZzMpKSAjIGRpZmZlcmVudGlhbCBpbXBhY3Qgb2YgY2FsbHM6IG5vdGhpbmcgc2lnLCBoaWdoZXIgaW5jb21lIGFyZWFzIHNsaWdodGx5IHNtYWxsZXIgZWZmZWN0IG9mIG5fY2FsbHMKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBuX2NhbGxzKkIxOTAxM18wMDFFLCBkYXRhID0gYm9zdG9uX2JnMykpICMgZGlmZmVyZW50aWFsIGltcGFjdCBvZiBjYWxsczogbm90aGluZyBzaWcKc3VtbWFyeShsbSgoY2hhbmdlX3NjaV9iaW5uZWQ9PSJCZXR0ZXIiKSB+IGxvZzFwKG5fY2FsbHMpKkIxOTAxM18wMDFFLCBkYXRhID0gYm9zdG9uX2JnMykpICMgZGlmZmVyZW50aWFsIGltcGFjdCBvZiBjYWxsczogbm90aGluZyBzaWcsIGhpZ2hlciBpbmNvbWUgYXJlYXMgc2xpZ2h0bHkgc21hbGxlciBlZmZlY3Qgb2Ygbl9jYWxscwpzdW1tYXJ5KGxtKG1lYW5fY2hhbmdlX3NjaSB+IGxvZzFwKG5fY2FsbHMpKkIxOTAxM18wMDFFLCBkYXRhID0gYm9zdG9uX2JnMykpICMgcG9zIHNpZyBlZmZlY3Qgb2YgY2FsbHMsIHBvcyBzaWcgZWZmZWN0IG9mIGluY29tZSwgbmVnIHNpZyBpbnR4OiBjYWxscyBoYXZlIGxlc3MgaW1wYWN0IGluIHdlYWx0aGllciBCR3MKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBsb2cxcChuX2NhbGxzKSpoaV9pbmMsIGRhdGEgPSBib3N0b25fYmczKSkgIyBwb3Mgc2lnIGVmZmVjdCBvZiBjYWxscywgcG9zIHNpZyBlZmZlY3Qgb2YgaW5jb21lLCBuZWcgc2lnIGludHgKc3VtbWFyeShsbShtZWFuX2NoYW5nZV9zY2kgfiBsb2cxcChuX2NhbGxzKSwgZGF0YSA9IHN1YnNldChib3N0b25fYmczLCBoaV9pbmM9PTEpKSkgIyBuZWcgaW5zaWcgZWZmZWN0IGFtb25nIGhpLWluY29tZQpzdW1tYXJ5KGxtKG1lYW5fY2hhbmdlX3NjaSB+IGxvZzFwKG5fY2FsbHMpLCBkYXRhID0gc3Vic2V0KGJvc3Rvbl9iZzMsIGhpX2luYz09MCkpKSAjIHBvcyBzaWcgZWZmZWN0IGFtb25nIGxvdy1pbmNvbWUKc3VtbWFyeShsbShjaGFuZ2Vfc2NpX2Jpbm5lZD09IkJldHRlciIgfiBsb2cxcChuX2NhbGxzKSpoaV9pbmMsIGRhdGEgPSBib3N0b25fYmczKSkgIyBhbGwgaW5zaWcKc3VtbWFyeShsbShjaGFuZ2Vfc2NpX2Jpbm5lZD09IkJldHRlciIgfiAobl9jYWxscykqaGlfaW5jLCBkYXRhID0gYm9zdG9uX2JnMykpICMgbWFyZ2luYWwgbmVnIGludHgKCgojIHJhY2U6CnN1bW1hcnkobG0obWVhbl9jaGFuZ2Vfc2NpIH4gd2hpdGVfcGVyYywgZGF0YSA9IGJvc3Rvbl9iZzMpKSAjIHdoaXRlciBCR3MgaGF2ZSBtdWNoIGJldHRlciBpbXByb3ZlbWVudApzdW1tYXJ5KGxtKG1lYW5fY2hhbmdlX3NjaSB+IGhpX3doaXRlLCBkYXRhID0gYm9zdG9uX2JnMykpICMgd2hpdGVyIEJHcyBoYXZlIG11Y2ggYmV0dGVyIGltcHJvdmVtZW50CnN1bW1hcnkobG0obWVhbl9jaGFuZ2Vfc2NpIH4gbG9nMXAobl9jYWxscykqd2hpdGVfcGVyYywgZGF0YSA9IGJvc3Rvbl9iZzMpKSAjIHBvcyBzaWcgZWZmZWN0IG9mIGNhbGxzLCBwb3Mgc2lnIGVmZmVjdCBvZiB3aGl0ZSwgbmVnIHNpZyBpbnR4CnN1bW1hcnkobG0obWVhbl9jaGFuZ2Vfc2NpIH4gbG9nMXAobl9jYWxscykqaGlfd2hpdGUsIGRhdGEgPSBib3N0b25fYmczKSkgIyBwb3Mgc2lnIGVmZmVjdCBvZiBjYWxscywgcG9zIHNpZyBlZmZlY3Qgb2Ygd2hpdGUsIG5lZyBzaWcgaW50eApzdW1tYXJ5KGxtKGNoYW5nZV9zY2lfYmlubmVkPT0iQmV0dGVyIiB+IGxvZzFwKG5fY2FsbHMpKndoaXRlX3BlcmMsIGRhdGEgPSBib3N0b25fYmczKSkgIyBwb3Mgc2lnIGVmZmVjdCBvZiBjYWxscywgcG9zIHNpZyBlZmZlY3Qgb2Ygd2hpdGUsIG5lZyBzaWcgaW50eApzdW1tYXJ5KGxtKGNoYW5nZV9zY2lfYmlubmVkPT0iQmV0dGVyIiB+IGxvZzFwKG5fY2FsbHMpKmhpX3doaXRlLCBkYXRhID0gYm9zdG9uX2JnMykpICMgcG9zIGluc2lnIGVmZmVjdCBvZiBjYWxscywgcG9zIHNpZyBlZmZlY3Qgb2Ygd2hpdGUsIG5lZyBzaWcgaW50eApgYGAKVGhlIG1haW4gbGVzc29ucyBjb21pbmcgb3V0IG9mIHRoZXNlIGFuYWx5c2VzIGFyZSB0aGF0OgooMSkgV2hpdGVyIGFuZCBoaWdoZXIgaW5jb21lIHRyYWN0cyBhbmQgQkdzIHdlcmUgbW9yZSBsaWtlbHkgdG8gaGF2ZSBpbXByb3ZlbWVudCBpbiBzaWRld2FsayBjb25kaXRpb25zIGJldHdlZW4gdGhlIHR3byBzaWRld2FsayBjb25kaXRpb25zIGF1ZGl0czsgYW5kCigyKSBJbiB0cmFjdHMgYW5kIEJHcyB3aXRoIG1vcmUgd2hpdGUgcmVzaWRlbnRzIGFuZCB3aXRoIGhpZ2hlciBsZXZlbHMgb2YgZWR1Y2F0aW9uLCB0aGUgbnVtYmVyIG9mIDMxMSBjYWxscyBkb2Vzbid0IHNlZW0gdG8gY29ycmVsYXRlIHdpdGggaW1wcm92ZW1lbnRzIGluIHNpZGV3YWxrIGNvbmRpdGlvbnMsIGJ1dCBpbiB0cmFjdHMgYW5kIEJHcyB3aXRoICpmZXdlciogd2hpdGUgcmVzaWRlbnRzIGFuZCAqbG93ZXIqIGxldmVscyBvZiBlZHVjYXRpb24sIHRoZSBudW1iZXIgb2YgMzExIGNhbGxzIGlzIHBvc2l0aXZlbHkgY29ycmVsYXRlZCB3aXRoIGltcHJvdmVtZW50cyBpbiBzaWRld2FsayBjb25kaXRpb25zLgoKCiMjIFZpc3VhbGl6aW5nIHRoZXNlIGR5bmFtaWNzOgpgYGB7cn0KKHRyYWN0X2JpdmFyaWF0ZV9yYWNlIDwtIGdncGxvdChib3N0b25fdHJhY3RzMykgKyAKICAgICAgZ2VvbV9wb2ludChhZXMoeD1uX2NhbGxzLHk9bWVhbl9jaGFuZ2Vfc2NpKSxjb2w9ImdyZXkiKSArIAogICAgICAgc2NhbGVfeF9jb250aW51b3VzKCJOdW1iZXIgb2YgMzExIGNhbGxzXG4obG9nIHNjYWxlKSIsdHJhbnM9ImxvZzEwIixicmVha3M9YygxLDEwLDUwLDEwMCkpICsgCiAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoIkNoYW5nZSBpbiBzaWRld2FsayBjb25kaXRpb25zIiwgbGltaXRzPWMoLTQwLDQwKSwgYnJlYWtzPXNlcSgtNDAsNDAsMjApLCBsYWJlbHM9YygiXG4tNDBcbihXb3JzZSkiLCItMjAiLCIwIiwiMjAiLCIoQmV0dGVyKVxuNDBcbiIpKSArIAogICAgICAgZ2VvbV9zbW9vdGgoZGF0YT1zdWJzZXQoYm9zdG9uX3RyYWN0czMsIGhpX3doaXRlPT0xKSwKICAgICAgICAgICAgICAgICAgIGFlcyh4PW5fY2FsbHMseT1tZWFuX2NoYW5nZV9zY2kpLGNvbD0icmVkIixsd2Q9MSxtZXRob2Q9ImxvZXNzIixzZT1GKSArIAogICAgICAgZ2VvbV9zbW9vdGgoZGF0YT1zdWJzZXQoYm9zdG9uX3RyYWN0czMsaGlfd2hpdGU9PTApLAogICAgICAgICAgICAgICAgICAgYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJibHVlIixsd2Q9MSxtZXRob2Q9ImxvZXNzIixzZT1GKSArIAogICAgICAgYW5ub3RhdGUoInRleHQiLHg9MS41LHk9MjUsbGFiZWw9IkFib3ZlIG1lZGlhbiAlIHdoaXRlIixjb2w9InJlZCIsc2l6ZT0zLGhqdXN0PTApICsKICAgICAgIGFubm90YXRlKCJ0ZXh0Iix4PTEseT0tNSxsYWJlbD0iQmVsb3cgbWVkaWFuICUgd2hpdGUiLGNvbD0iYmx1ZSIsc2l6ZT0zLGhqdXN0PTApICsKICAgICAgIHRoZW1lX2J3KCkKKQpgYGAKCgpgYGB7cn0KKGJnX2JpdmFyaWF0ZV9yYWNlIDwtIGdncGxvdChib3N0b25fYmczKSArIAogICAgICBnZW9tX3BvaW50KGFlcyh4PW5fY2FsbHMseT1tZWFuX2NoYW5nZV9zY2kpLGNvbD0iZ3JleSIpICsgCiAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMoIk51bWJlciBvZiAzMTEgY2FsbHNcbihsb2cgc2NhbGUpIix0cmFucz0ibG9nMTAiLGJyZWFrcz1jKDEsMTAsNTAsMTAwKSkgKyAKICAgICAgIHNjYWxlX3lfY29udGludW91cygiQ2hhbmdlIGluIHNpZGV3YWxrIGNvbmRpdGlvbnMiLCBsaW1pdHM9YygtNDAsNDApLCBicmVha3M9c2VxKC00MCw0MCwyMCksIGxhYmVscz1jKCJcbi00MFxuKFdvcnNlKSIsIi0yMCIsIjAiLCIyMCIsIihCZXR0ZXIpXG40MFxuIikpICsgCiAgICAgICBnZW9tX3Ntb290aChkYXRhPXN1YnNldChib3N0b25fYmczLCBoaV93aGl0ZT09MSksCiAgICAgICAgICAgICAgICAgICBhZXMoeD1uX2NhbGxzLHk9bWVhbl9jaGFuZ2Vfc2NpKSxjb2w9InJlZCIsbHdkPTEsbWV0aG9kPSJsb2VzcyIsc2U9RikgKyAKICAgICAgIGdlb21fc21vb3RoKGRhdGE9c3Vic2V0KGJvc3Rvbl9iZzMsaGlfd2hpdGU9PTApLAogICAgICAgICAgICAgICAgICAgYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJibHVlIixsd2Q9MSxtZXRob2Q9ImxvZXNzIixzZT1GKSArIAogICAgICAgYW5ub3RhdGUoInRleHQiLHg9MSx5PTEyLGxhYmVsPSJBYm92ZSBtZWRpYW4gJSB3aGl0ZSIsY29sPSJyZWQiLHNpemU9MyxoanVzdD0wKSArCiAgICAgICBhbm5vdGF0ZSgidGV4dCIseD0xLHk9LTksbGFiZWw9IkJlbG93IG1lZGlhbiAlIHdoaXRlIixjb2w9ImJsdWUiLHNpemU9MyxoanVzdD0wKSArCiAgICAgICB0aGVtZV9idygpCikKYGBgCgoKCmBgYHtyfQpnZ3NhdmUodHJhY3RfYml2YXJpYXRlX3JhY2UsZmlsZT0iZmlndXJlcy9jYWxsc19jaGFuZ2VTQ0lfY3RfcmFjZS5wZGYiLGhlaWdodD00LHdpZHRoPTYpCmdnc2F2ZShiZ19iaXZhcmlhdGVfcmFjZSxmaWxlPSJmaWd1cmVzL2NhbGxzX2NoYW5nZVNDSV9iZ19yYWNlLnBkZiIsaGVpZ2h0PTQsd2lkdGg9NikKYGBgCgoKCmBgYHtyfQoodHJhY3RfYml2YXJpYXRlX2luYyA8LSBnZ3Bsb3QoYm9zdG9uX3RyYWN0czMpICsgCiAgICAgIGdlb21fcG9pbnQoYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJncmV5IikgKyAKICAgICAgIHNjYWxlX3hfY29udGludW91cygiTnVtYmVyIG9mIDMxMSBjYWxsc1xuKGxvZyBzY2FsZSkiLHRyYW5zPSJsb2cxMCIsYnJlYWtzPWMoMSwxMCw1MCwxMDApKSArIAogICAgICAgc2NhbGVfeV9jb250aW51b3VzKCJDaGFuZ2UgaW4gc2lkZXdhbGsgY29uZGl0aW9ucyIsIGxpbWl0cz1jKC00MCw0MCksIGJyZWFrcz1zZXEoLTQwLDQwLDIwKSwgbGFiZWxzPWMoIlxuLTQwXG4oV29yc2UpIiwiLTIwIiwiMCIsIjIwIiwiKEJldHRlcilcbjQwXG4iKSkgKyAKICAgICAgIGdlb21fc21vb3RoKGRhdGE9c3Vic2V0KGJvc3Rvbl90cmFjdHMzLCBoaV9pbmM9PTEpLAogICAgICAgICAgICAgICAgICAgYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJyZWQiLGx3ZD0xLG1ldGhvZD0ibG9lc3MiLHNlPUYpICsgCiAgICAgICBnZW9tX3Ntb290aChkYXRhPXN1YnNldChib3N0b25fdHJhY3RzMyxoaV9pbmM9PTApLAogICAgICAgICAgICAgICAgICAgYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJibHVlIixsd2Q9MSxtZXRob2Q9ImxvZXNzIixzZT1GKSArIAogICAgICAgYW5ub3RhdGUoInRleHQiLHg9MTAseT0xNSxsYWJlbD0iQWJvdmUgbWVkaWFuIGluY29tZSIsY29sPSJyZWQiLHNpemU9MyxoanVzdD0wKSArCiAgICAgICBhbm5vdGF0ZSgidGV4dCIseD0xLHk9LTUsbGFiZWw9IkJlbG93IG1lZGlhbiBpbmNvbWUiLGNvbD0iYmx1ZSIsc2l6ZT0zLGhqdXN0PTApICsKICAgICAgIHRoZW1lX2J3KCkKKQpgYGAKCgpgYGB7cn0KKGJnX2JpdmFyaWF0ZV9pbmMgPC0gZ2dwbG90KGJvc3Rvbl9iZzMpICsgCiAgICAgIGdlb21fcG9pbnQoYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJncmV5IikgKyAKICAgICAgIHNjYWxlX3hfY29udGludW91cygiTnVtYmVyIG9mIDMxMSBjYWxsc1xuKGxvZyBzY2FsZSkiLHRyYW5zPSJsb2cxMCIsYnJlYWtzPWMoMSwxMCw1MCwxMDApKSArIAogICAgICAgc2NhbGVfeV9jb250aW51b3VzKCJDaGFuZ2UgaW4gc2lkZXdhbGsgY29uZGl0aW9ucyIsIGxpbWl0cz1jKC00MCw0MCksIGJyZWFrcz1zZXEoLTQwLDQwLDIwKSwgbGFiZWxzPWMoIlxuLTQwXG4oV29yc2UpIiwiLTIwIiwiMCIsIjIwIiwiKEJldHRlcilcbjQwXG4iKSkgKyAKICAgICAgIGdlb21fc21vb3RoKGRhdGE9c3Vic2V0KGJvc3Rvbl9iZzMsIGhpX2luYz09MSksCiAgICAgICAgICAgICAgICAgICBhZXMoeD1uX2NhbGxzLHk9bWVhbl9jaGFuZ2Vfc2NpKSxjb2w9InJlZCIsbHdkPTEsbWV0aG9kPSJsb2VzcyIsc2U9RikgKyAKICAgICAgIGdlb21fc21vb3RoKGRhdGE9c3Vic2V0KGJvc3Rvbl9iZzMsaGlfaW5jPT0wKSwKICAgICAgICAgICAgICAgICAgIGFlcyh4PW5fY2FsbHMseT1tZWFuX2NoYW5nZV9zY2kpLGNvbD0iYmx1ZSIsbHdkPTEsbWV0aG9kPSJsb2VzcyIsc2U9RikgKyAKICAgICAgIGFubm90YXRlKCJ0ZXh0Iix4PTEseT0xMCxsYWJlbD0iQWJvdmUgbWVkaWFuIGluY29tZSIsY29sPSJyZWQiLHNpemU9MyxoanVzdD0wKSArCiAgICAgICBhbm5vdGF0ZSgidGV4dCIseD0xLHk9LTksbGFiZWw9IkJlbG93IG1lZGlhbiBpbmNvbWUiLGNvbD0iYmx1ZSIsc2l6ZT0zLGhqdXN0PTApICsKICAgICAgIHRoZW1lX2J3KCkKKQpgYGAKYGBge3J9CihiZ19iaXZhcmlhdGVfaW5jX2xtIDwtIGdncGxvdChib3N0b25fYmczKSArIAogICAgICBnZW9tX3BvaW50KGFlcyh4PW5fY2FsbHMseT1tZWFuX2NoYW5nZV9zY2kpLGNvbD0iZ3JleSIpICsgCiAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMoIk51bWJlciBvZiAzMTEgY2FsbHNcbihsb2cgc2NhbGUpIix0cmFucz0ibG9nMTAiLGJyZWFrcz1jKDEsMTAsNTAsMTAwKSkgKyAKICAgICAgIHNjYWxlX3lfY29udGludW91cygiQ2hhbmdlIGluIHNpZGV3YWxrIGNvbmRpdGlvbnMiLCBsaW1pdHM9YygtNDAsNDApLCBicmVha3M9c2VxKC00MCw0MCwyMCksIGxhYmVscz1jKCJcbi00MFxuKFdvcnNlKSIsIi0yMCIsIjAiLCIyMCIsIihCZXR0ZXIpXG40MFxuIikpICsgCiAgICAgICBnZW9tX3Ntb290aChkYXRhPXN1YnNldChib3N0b25fYmczLCBoaV9pbmM9PTEpLAogICAgICAgICAgICAgICAgICAgYWVzKHg9bl9jYWxscyx5PW1lYW5fY2hhbmdlX3NjaSksY29sPSJyZWQiLGx3ZD0xLG1ldGhvZD0ibG0iLHNlPUYpICsgCiAgICAgICBnZW9tX3Ntb290aChkYXRhPXN1YnNldChib3N0b25fYmczLGhpX2luYz09MCksCiAgICAgICAgICAgICAgICAgICBhZXMoeD1uX2NhbGxzLHk9bWVhbl9jaGFuZ2Vfc2NpKSxjb2w9ImJsdWUiLGx3ZD0xLG1ldGhvZD0ibG0iLHNlPUYpICsgCiAgICAgICBhbm5vdGF0ZSgidGV4dCIseD0xLHk9MTAsbGFiZWw9IkFib3ZlIG1lZGlhbiBpbmNvbWUiLGNvbD0icmVkIixzaXplPTMsaGp1c3Q9MCkgKwogICAgICAgYW5ub3RhdGUoInRleHQiLHg9MSx5PS05LGxhYmVsPSJCZWxvdyBtZWRpYW4gaW5jb21lIixjb2w9ImJsdWUiLHNpemU9MyxoanVzdD0wKSArCiAgICAgICB0aGVtZV9idygpCikKYGBgCgpgYGB7cn0KIyBzYXZpbmcgcGxvdHM6Cmdnc2F2ZSh0cmFjdF9iaXZhcmlhdGVfaW5jLGZpbGU9ImZpZ3VyZXMvY2FsbHNfY2hhbmdlU0NJX2N0X2luYy5wZGYiLGhlaWdodD00LHdpZHRoPTYpCmdnc2F2ZShiZ19iaXZhcmlhdGVfaW5jLGZpbGU9ImZpZ3VyZXMvY2FsbHNfY2hhbmdlU0NJX2JnX2luYy5wZGYiLGhlaWdodD00LHdpZHRoPTYpCmdnc2F2ZShiZ19iaXZhcmlhdGVfaW5jX2xtLGZpbGU9ImZpZ3VyZXMvY2FsbHNfY2hhbmdlU0NJX2JnX2luY19sbS5wZGYiLGhlaWdodD00LHdpZHRoPTYpCmBgYAoKCmBgYHtyfQojIHNhdmluZyBpbWFnZSBvZiB3b3JrCnNhdmUuaW1hZ2UoInN0cmVldGNhc3Rlcl93c18xODEwMzAuUkRhdGEiKQpgYGA=