#Loading all libraries that may be needed
library(sf)
library(tidyverse)
library(dplyr)
library(ggplot2)
library(ggmap)
library(scales)
library(gridExtra)
library(tidycensus)
library(cowplot)
library(OpenStreetMap)
library(rJava)
library(knitr)
library(gganimate)
library(ggmap)
library(transformr)
library(lubridate)
library(rayshader)
library(viridis)
library(rgl)
library(foreign)
library(marmap)
library(raster)
library(ggrepel)
library(RColorBrewer)
root.dir = "https://raw.githubusercontent.com/urbanSpatial/Public-Policy-Analytics-Landing/master/DATA/"
source("https://raw.githubusercontent.com/urbanSpatial/Public-Policy-Analytics-Landing/master/functions.r")
# Loading Geography Data
Data <- st_read("C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\NGPR7ADT\\shapefile\\gadm36_NGA_1.shp")
# Loading Survey Data
Survey <- read.dta("C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\NGPR7ADT\\NGPR7AFL.DTA")
Question 1
How many Positive Blood Smear Test Children under 5?
Steps
Filter to those with ages under 6 (corrective age)
Filter those who tested positive for a Blood Smear
Ensure no repeat Ids so an indiviual is not counted
twice
ANSWER = 1546
#Answering qustion 1 --- filtering the survey by those with a blood smear who tested positive and are under the age of 6 based on their corrective age
Under5_BloodSmear <- Survey%>%
filter(hml16 < 6 & hml32 == 'positive')%>%
## selecting only these three categories
dplyr::select(hml32, hhid)
#Counting, ensuring no repeat IDs
x <- count(distinct(Under5_BloodSmear))
kable(x)
Question 2
How Many Rapid Tests for Children Under 5?
Steps
Filter to children under 6 based on their corrective
age.
Filter to where rapid blood test *hml35) is equal to positive,
negative, or missing indicating a test was making
Ensure there are no duplicate IDs.
ANSWER = 10815
#Filtering by those that either tested negative or positive for the rapid blood test and have a corrective age under the age of 6
Under5_Rapid <- Survey%>%
#Selecting the relevant fields
dplyr::select(hhid, hml16, hml35)%>%
#Filtering
filter(hml16 < 6 & (hml35 == 'positive' | hml35 == 'negative' | hml35 == 'missing'))
# Counting ensuring no repeat ids
x <- count(distinct(Under5_Rapid))
kable(x)
Question 3
How many Microscopy Positive Results for Children?
STEPS
Using blood smear test as the microscopy result
filtered to those that tested positive for the blood
smear
Also filtered to those that were selected for a
microscopy
Use corrective age to ensure age under 18
Remove duplicate Ids
ANSWER = 1546
Microscopy <- Survey%>%
filter(hml16 < 18 & hml32 == 'positive', sbelig == "yes, selected for microscopy")%>%
dplyr::select(hhid, sbelig, hml32)
# Ensuring no duplicate IDs
x <- count(distinct(Microscopy))
kable(x)
Question 4
How many Positive Rapid Tests for Children?
STEPS
Filter by corrective age to under 18 and rapid test to
positive
Ensure no duplicate IDs
ANSWER = 3229
#Filtering by rapid test
RapidChildren <- Survey%>%
filter(hml16 < 18 & hml35 == 'positive') %>%
dplyr::select(hhid, ha50, hml35)
x <- count(distinct(RapidChildren))
kable(x)
Question 5
Make a plot showing the number of U5 children that tested positive
for malaria by microscopy and the number of U5 children that tested
negative for malaria by microscopy in urban and rural areas
STEPS
Filtered by Children under 5
Create categories for rural/urban, positive status/ negative
status using new fields
Ensure no duplicate IDs
Reformat table
Create Graph
GraphQ5 <-
# Take Survey Data
Survey%>%
#Select necessary columns
dplyr::select(hhid, hv025, hml16, sbelig, hml32)%>%
#Filtering by corrective age under 6
filter(hml16 < 6) %>%
# Create new field for rural and negative
mutate(Rural = ifelse(hv025 == 'rural' & hml32 == 'negative' & sbelig == 'yes, selected for microscopy', 1, 0))%>%
# Create new field for urban and negative
mutate(Urban = ifelse(hv025 == 'urban' & hml32 == 'negative' & sbelig == 'yes, selected for microscopy', 1, 0))%>%
#Create new field for positive and rural
mutate(pos = ifelse(hml32 == 'positive' & sbelig == 'yes, selected for microscopy' & hv025 == 'rural', 1, 0))%>%
#Create new field for positive and urban
mutate(pos2 = ifelse(hml32 == 'positive' & sbelig == 'yes, selected for microscopy' & hv025 == 'urban', 1, 0))%>%
#Select new proportion fields and ID
dplyr::select(hhid, Urban, Rural, pos, pos2)%>%
#Filter down to children that euqal 1 for at least one of the four created fields
filter(Urban == 1 | Rural == 1 | pos == 1 | pos2 == 1)%>%
#remove duplicate IDs
distinct()%>%
#Select proportion fields
dplyr::select(Urban, Rural, pos, pos2)%>%
#Sum up each category
summarise(Pos = sum(pos), Pos2 = sum(pos2), Rural = sum(Rural), Urban = sum(Urban))%>%
#Rename fields
rename(`Positive for Malaria ; Rural` = Pos, `Positive for Malaria ; Urban` = Pos2,`Negative for Malaria ; Rural`= Rural, `Negative for Malaria ; Urban` = Urban)%>%
#pivot table to set up for ggplot
pivot_longer(
cols = `Positive for Malaria ; Rural` :`Negative for Malaria ; Urban`,
names_to = "Category",
values_to = "Children")%>%
#Make sure number of children is numeric
mutate(Children = as.numeric(Children))
ggplot()+
geom_bar(data = GraphQ5, aes(x = Category, y = Children, fill = Category ), stat = 'identity')+
labs(title = "Number of Nigerian Children by Malaria Status via Microscopy",
subtitle = "Source: Nigerian Health Survey")+
ylab("Number of Children") +
scale_fill_manual(values = c( '#E59E9E','#E62020', '#00F38A','#008C4F'))+
plotTheme()+
theme(legend.position = "none")

Question 6
Make another plot showing the proportion of U5 children that tested
positive for malaria by microscopy and the proportion of U5 children
that tested negative for malaria by microscopy in urban and rural
areas
STEPS
Use Question 5 analysis
Calculate proportions
Calculate pie chart positioning
Create graph using GGPlot
options(digits = 3)
GraphQ5_Prop <-
#Taking previous analysis from Question 5
GraphQ5%>%
#Calculating proportions for each category
mutate(Proportion = (Children/ sum(GraphQ5$Children)* 100))%>%
#Selecting only category and proportion
dplyr::select(Category, Proportion)%>%
#Field to define label positioning on pie chart
mutate(csum = rev(cumsum(rev(Proportion))),
pos = Proportion/2 + lead(csum, 1),
pos = if_else(is.na(pos), Proportion/2, pos))
ggplot(GraphQ5_Prop, aes(x="", y=Proportion, fill=fct_inorder(Category))) +
geom_col(width = 1) +
coord_polar(theta = "y", start = 0) +
theme_void() +
theme(legend.position = "right")+
labs(title = "Percentage of Children Testing Positive or Negative for Malaria by Geographic Region",
subtitle = "Source: Nigeran Health Survey")+
geom_label_repel(data = GraphQ5_Prop,
aes(y = pos, label = paste0(as.integer(Proportion), "%")),
size = 3.5, nudge_x = 1, show.legend = FALSE)+
scale_fill_manual(values = c( '#00F38A','#008C4F','#E59E9E','#E62020'))+
guides(fill=guide_legend(title="Categories"))

Question 7
Make a map of the number of children that tested positive for malaria
by state
STEPS
Filter by positive rapid or positive blood smear, along with
under 18 corrective age
Add new feild for count
Ensure no duplicate IDs
Group by State
Sum Count
Join state data to survey data
Create map
ByState <-
Survey%>%
#Filter by children positive for rapid test or positive for blood smear
filter((hml32 == 'positive' | hml35 == 'positive') & hml16 < 18) %>%
#New field where count is one (going to be used for aggregation)
mutate(Count = 1)%>%
#Select necessary fields
dplyr::select(hhid, shstate, Count)%>%
#Remmove repeat IDS
distinct() %>%
#Group by state
group_by(shstate) %>%
#Sum by summing up the count field previously created
summarise(ChildCases = sum(Count)) %>%
#Dealing with NA Values
mutate(ChildCases = ifelse(is.na(ChildCases) == T, 0, ChildCases))
Geo <-
Data%>%
#mutating state name to lowercase for join
mutate(shstate = tolower(NAME_1))%>%
#joining by State
left_join(ByState, by = "shstate")
ggplot() +
geom_sf(data = Geo, aes(fill = q5(ChildCases))) +
scale_fill_manual(values = c('#FFEBEB', '#FFAFAD','#FF221F','#E00400', '#A30300' ),
labels = c("0-23", "24-70", "71-99", "100 - 120", "121 - 176", "N/A"),
name = "Child Malaria Cases \n(Quintile Breaks)") +
labs(title = "Nigerian Malaria Cases by Region", subtitle = "Source: Nigerian Health Survey") +
mapTheme()

Question 8
Extract the data from the raster file and make a map showing average
housing quality values for each Nigerian state.
STEPS
Import Raster
Transform to Poly
Transform to SF Class
Intersect Nigerian Stateboundaries with SF Class
Group by State
Summarise average housing quality
Create Map
#Importing Raster
NigerianHousing <- raster("C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\NGPR7ADT\\housing data 2019 nigeria\\2019_Nature_Africa_Housing_2015_NGA.tiff")
#Raster to Poly
poly<- rasterToPolygons(NigerianHousing)
# To SF Class
poly <- st_as_sf(poly)
#Intersecting new poly with nigerian raster
Aggregate <-
st_intersection(poly, Geo)
Aggregate1<-
Aggregate%>%
#Grouping by state
group_by(shstate)%>%
#Summarise by average housing quality
summarise(`Average Housing Quality` = mean(X2019_Nature_Africa_Housing_2015_NGA))
ggplot() +
geom_sf(data = Aggregate1, aes(fill = `Average Housing Quality`)) +
scale_fill_gradient(low = "#EEFFEE", high = "#335533") +
labs(title = "Nigerian Average Housing Quality Score by Region") +
mapTheme()

Question 9
Identify any website of your choice and scrub their data. Pull it
into a csv and make at least one data visualization.
STEPS
Identified mortality dataset of Balitmore
Downloaded all associed data
Joined data with younger populations together — split up from
older populations so that we can have one scale for younger populations
and one scale for older populations as the mortality rate is higher in
older populations
Alter table to prepare for a facet wrap map
Create map
Repeat for older populations
M1To14<- st_read('C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\Mort14__-7131955727435385779.geojson')%>%
dplyr::select(CSA2010, mort14_18)
M15To24<- st_read('C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\Mort24__440437359064296490.geojson')%>%
dplyr::select(CSA2010, mort24_18)
M24To44<- st_read('C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\Mort44__6262205918832827315.geojson')%>%
dplyr::select(CSA2010, mort44_18)
M45To64<- st_read('C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\Mort64__-6209940949464912372.geojson')%>%
dplyr::select(CSA2010, mort64_18)
M45To64<- st_read('C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\Mort64__-6209940949464912372.geojson')%>%
dplyr::select(CSA2010, mort64_18)
M65To84<- st_read('C:\\Users\\Kyle McCarthy\\Documents\\Loyola\\Mort84__7080676275320674118.geojson')%>%
dplyr::select(CSA2010, mort84_18)
MortalityData <-
M1To14%>%
st_drop_geometry()%>%
left_join(., M15To24)%>%
right_join(., M24To44)%>%
rename(`Ages 1 to 14` = mort14_18,
`Ages 15 to 24` = mort24_18,
`Ages 25 to 44` = mort44_18)%>%
pivot_longer(
cols = c(`Ages 1 to 14`,`Ages 15 to 24`,`Ages 25 to 44`) ,
names_to = "Age Category",
values_to = "Mortality")%>%
st_as_sf()
ggplot() +
geom_sf(data = MortalityData, aes(fill = Mortality)) +
scale_fill_gradient(low = "#FFEEEE", high = "#773333") +
labs(title = "Mortality Rate by Balitmore Neighborhood", subtitle = "Younger Populations") +
mapTheme()+
facet_wrap(vars(`Age Category`))

MortalityData_Older <-
M45To64%>%
st_drop_geometry()%>%
left_join(., M65To84)%>%
rename(`Ages 45 to 64` = mort64_18,
`Ages 65 to 84` = mort84_18)%>%
pivot_longer(
cols = c(`Ages 45 to 64`,`Ages 65 to 84`) ,
names_to = "Age Category",
values_to = "Mortality")%>%
st_as_sf()
ggplot() +
geom_sf(data = MortalityData_Older, aes(fill = Mortality)) +
scale_fill_gradient(low = "#FFEEEE", high = "#773333") +
labs(title = "Mortality Rate by Balitmore Neighborhood", subtitle = "Older Populations") +
mapTheme()+
facet_wrap(vars(`Age Category`))

LS0tDQp0aXRsZTogIkxveWFsYSBVbml2ZXJzaXR5IFNjcmVlbmluZyBUZXN0Ig0KYXV0aG9yOiAiS3lsZSBNY0NhcnRoeSINCmRhdGU6ICJBdWd1c3QgNnRoLCAyMDI0Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQpgYGB7ciBTZXRVcCwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRSwgcmVzdWx0cyA9ICdoaWRlJ30NCg0KI0xvYWRpbmcgYWxsIGxpYnJhcmllcyB0aGF0IG1heSBiZSBuZWVkZWQNCg0KbGlicmFyeShzZikgDQpsaWJyYXJ5KHRpZHl2ZXJzZSkgDQpsaWJyYXJ5KGRwbHlyKSANCmxpYnJhcnkoZ2dwbG90MikgDQpsaWJyYXJ5KGdnbWFwKSANCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KHRpZHljZW5zdXMpDQpsaWJyYXJ5KGNvd3Bsb3QpIA0KbGlicmFyeShPcGVuU3RyZWV0TWFwKQ0KbGlicmFyeShySmF2YSkNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGdnYW5pbWF0ZSkNCmxpYnJhcnkoZ2dtYXApDQpsaWJyYXJ5KHRyYW5zZm9ybXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkocmF5c2hhZGVyKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeShyZ2wpDQpsaWJyYXJ5KGZvcmVpZ24pDQpsaWJyYXJ5KG1hcm1hcCkNCmxpYnJhcnkocmFzdGVyKQ0KbGlicmFyeShnZ3JlcGVsKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQoNCnJvb3QuZGlyID0gImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS91cmJhblNwYXRpYWwvUHVibGljLVBvbGljeS1BbmFseXRpY3MtTGFuZGluZy9tYXN0ZXIvREFUQS8iDQpzb3VyY2UoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS91cmJhblNwYXRpYWwvUHVibGljLVBvbGljeS1BbmFseXRpY3MtTGFuZGluZy9tYXN0ZXIvZnVuY3Rpb25zLnIiKQ0KDQpgYGANCg0KDQoNCmBgYHtyIExvYWREYXRhLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBUUlVFLCByZXN1bHRzID0gJ2hpZGUnfQ0KDQojIExvYWRpbmcgR2VvZ3JhcGh5IERhdGENCkRhdGEgPC0gc3RfcmVhZCgiQzpcXFVzZXJzXFxLeWxlIE1jQ2FydGh5XFxEb2N1bWVudHNcXExveW9sYVxcTkdQUjdBRFRcXHNoYXBlZmlsZVxcZ2FkbTM2X05HQV8xLnNocCIpDQoNCiMgTG9hZGluZyBTdXJ2ZXkgRGF0YQ0KU3VydmV5IDwtIHJlYWQuZHRhKCJDOlxcVXNlcnNcXEt5bGUgTWNDYXJ0aHlcXERvY3VtZW50c1xcTG95b2xhXFxOR1BSN0FEVFxcTkdQUjdBRkwuRFRBIikNCg0KDQoNCmBgYA0KDQojIyBRdWVzdGlvbiAxIA0KDQpIb3cgbWFueSBQb3NpdGl2ZSBCbG9vZCBTbWVhciBUZXN0IENoaWxkcmVuIHVuZGVyIDU/IA0KDQpTdGVwcw0KDQoxLiBGaWx0ZXIgdG8gdGhvc2Ugd2l0aCBhZ2VzIHVuZGVyIDYgKGNvcnJlY3RpdmUgYWdlKQ0KDQoyLiBGaWx0ZXIgdGhvc2Ugd2hvIHRlc3RlZCBwb3NpdGl2ZSBmb3IgYSBCbG9vZCBTbWVhcg0KDQozLiBFbnN1cmUgbm8gcmVwZWF0IElkcyBzbyBhbiBpbmRpdml1YWwgaXMgbm90IGNvdW50ZWQgdHdpY2UNCg0KQU5TV0VSID0gMTU0Ng0KDQpgYGB7ciBOdW1iZXIxX0Fuc3dlciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRX0NCg0KI0Fuc3dlcmluZyBxdXN0aW9uIDEgLS0tIGZpbHRlcmluZyB0aGUgc3VydmV5IGJ5IHRob3NlIHdpdGggYSBibG9vZCBzbWVhciB3aG8gdGVzdGVkIHBvc2l0aXZlIGFuZCBhcmUgdW5kZXIgdGhlIGFnZSBvZiA2IGJhc2VkIG9uIHRoZWlyIGNvcnJlY3RpdmUgYWdlDQoNClVuZGVyNV9CbG9vZFNtZWFyIDwtIFN1cnZleSU+JQ0KICBmaWx0ZXIoaG1sMTYgPCA2ICYgaG1sMzIgPT0gJ3Bvc2l0aXZlJyklPiUNCiAgIyMgc2VsZWN0aW5nIG9ubHkgdGhlc2UgdGhyZWUgY2F0ZWdvcmllcw0KICBkcGx5cjo6c2VsZWN0KGhtbDMyLCBoaGlkKQ0KDQojQ291bnRpbmcsIGVuc3VyaW5nIG5vIHJlcGVhdCBJRHMgDQoNCnggPC0gY291bnQoZGlzdGluY3QoVW5kZXI1X0Jsb29kU21lYXIpKQ0KDQprYWJsZSh4KQ0KDQpgYGANCiMjIFF1ZXN0aW9uIDIgDQoNCkhvdyBNYW55IFJhcGlkIFRlc3RzIGZvciBDaGlsZHJlbiBVbmRlciA1PyANCg0KU3RlcHMNCg0KMS4gRmlsdGVyIHRvIGNoaWxkcmVuIHVuZGVyIDYgYmFzZWQgb24gdGhlaXIgY29ycmVjdGl2ZSBhZ2UuIA0KDQoyLiBGaWx0ZXIgdG8gd2hlcmUgcmFwaWQgYmxvb2QgdGVzdCAqaG1sMzUpIGlzIGVxdWFsIHRvIHBvc2l0aXZlLCBuZWdhdGl2ZSwgb3IgbWlzc2luZyBpbmRpY2F0aW5nIGEgdGVzdCB3YXMgbWFraW5nDQoNCjMuIEVuc3VyZSB0aGVyZSBhcmUgbm8gZHVwbGljYXRlIElEcy4gDQoNCg0KQU5TV0VSID0gMTA4MTUNCg0KYGBge3IgTnVtYmVyMl9BbnN3ZXIsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBjYWNoZSA9IFRSVUV9DQojRmlsdGVyaW5nIGJ5IHRob3NlIHRoYXQgZWl0aGVyIHRlc3RlZCBuZWdhdGl2ZSBvciBwb3NpdGl2ZSBmb3IgdGhlIHJhcGlkIGJsb29kIHRlc3QgYW5kIGhhdmUgYSBjb3JyZWN0aXZlIGFnZSB1bmRlciB0aGUgYWdlIG9mIDYNCg0KVW5kZXI1X1JhcGlkIDwtIFN1cnZleSU+JQ0KICAjU2VsZWN0aW5nIHRoZSByZWxldmFudCBmaWVsZHMNCiAgZHBseXI6OnNlbGVjdChoaGlkLCBobWwxNiwgaG1sMzUpJT4lDQogICNGaWx0ZXJpbmcNCiAgZmlsdGVyKGhtbDE2IDwgNiAgJiAoaG1sMzUgPT0gJ3Bvc2l0aXZlJyB8IGhtbDM1ID09ICduZWdhdGl2ZScgfCBobWwzNSA9PSAnbWlzc2luZycpKQ0KDQojIENvdW50aW5nIGVuc3VyaW5nIG5vIHJlcGVhdCBpZHMNCnggPC0gY291bnQoZGlzdGluY3QoVW5kZXI1X1JhcGlkKSkNCg0Ka2FibGUoeCkNCg0KYGBgDQojIyBRdWVzdGlvbiAzIA0KDQpIb3cgbWFueSBNaWNyb3Njb3B5IFBvc2l0aXZlIFJlc3VsdHMgZm9yIENoaWxkcmVuPyANCg0KU1RFUFMNCg0KMS4gVXNpbmcgYmxvb2Qgc21lYXIgdGVzdCBhcyB0aGUgbWljcm9zY29weSByZXN1bHQNCg0KMi4gZmlsdGVyZWQgdG8gdGhvc2UgdGhhdCB0ZXN0ZWQgcG9zaXRpdmUgZm9yIHRoZSBibG9vZCBzbWVhcg0KDQozLiBBbHNvIGZpbHRlcmVkIHRvIHRob3NlIHRoYXQgd2VyZSBzZWxlY3RlZCBmb3IgYSBtaWNyb3Njb3B5DQoNCjQuIFVzZSBjb3JyZWN0aXZlIGFnZSB0byBlbnN1cmUgYWdlIHVuZGVyIDE4DQoNCjUuIFJlbW92ZSBkdXBsaWNhdGUgSWRzDQoNCg0KDQpBTlNXRVIgPSAxNTQ2DQoNCg0KYGBge3IgTnVtYmVyM19BbnN3ZXIsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBjYWNoZSA9IFRSVUV9DQoNCk1pY3Jvc2NvcHkgPC0gU3VydmV5JT4lDQogIGZpbHRlcihobWwxNiA8IDE4ICAmICBobWwzMiA9PSAncG9zaXRpdmUnLCBzYmVsaWcgPT0gInllcywgc2VsZWN0ZWQgZm9yIG1pY3Jvc2NvcHkiKSU+JSANCiAgZHBseXI6OnNlbGVjdChoaGlkLCBzYmVsaWcsIGhtbDMyKQ0KDQogIA0KIyBFbnN1cmluZyBubyBkdXBsaWNhdGUgSURzDQp4IDwtIGNvdW50KGRpc3RpbmN0KE1pY3Jvc2NvcHkpKQ0KDQprYWJsZSh4KQ0KDQpgYGANCiMjIFF1ZXN0aW9uIDQgDQoNCkhvdyBtYW55IFBvc2l0aXZlIFJhcGlkIFRlc3RzIGZvciBDaGlsZHJlbj8NCg0KU1RFUFMNCg0KMS4gRmlsdGVyIGJ5IGNvcnJlY3RpdmUgYWdlIHRvIHVuZGVyIDE4IGFuZCByYXBpZCB0ZXN0IHRvIHBvc2l0aXZlDQoNCjIuIEVuc3VyZSBubyBkdXBsaWNhdGUgSURzDQoNCkFOU1dFUiA9IDMyMjkNCg0KDQpgYGB7ciBOdW1iZXI0X0Fuc3dlciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRX0NCg0KI0ZpbHRlcmluZyBieSByYXBpZCB0ZXN0IA0KUmFwaWRDaGlsZHJlbiA8LSBTdXJ2ZXklPiUNCiAgZmlsdGVyKGhtbDE2IDwgMTggJiBobWwzNSA9PSAncG9zaXRpdmUnKSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoaGhpZCwgaGE1MCwgaG1sMzUpDQoNCnggPC0gY291bnQoZGlzdGluY3QoUmFwaWRDaGlsZHJlbikpDQoNCmthYmxlKHgpDQpgYGANCiMjIFF1ZXN0aW9uIDUgDQoNCk1ha2UgYSBwbG90IHNob3dpbmcgdGhlIG51bWJlciBvZiBVNSBjaGlsZHJlbiB0aGF0IHRlc3RlZCBwb3NpdGl2ZSBmb3IgbWFsYXJpYSBieSBtaWNyb3Njb3B5IGFuZCB0aGUgbnVtYmVyIG9mIFU1IGNoaWxkcmVuIHRoYXQgdGVzdGVkIG5lZ2F0aXZlIGZvciBtYWxhcmlhIGJ5IG1pY3Jvc2NvcHkgaW4gdXJiYW4gYW5kIHJ1cmFsIGFyZWFzDQoNClNURVBTDQoNCjEuIEZpbHRlcmVkIGJ5IENoaWxkcmVuIHVuZGVyIDUNCg0KMi4gQ3JlYXRlIGNhdGVnb3JpZXMgZm9yIHJ1cmFsL3VyYmFuLCBwb3NpdGl2ZSBzdGF0dXMvIG5lZ2F0aXZlIHN0YXR1cyB1c2luZyBuZXcgZmllbGRzDQoNCjMuIEVuc3VyZSBubyBkdXBsaWNhdGUgSURzDQoNCjQuIFJlZm9ybWF0IHRhYmxlDQoNCjUuIENyZWF0ZSBHcmFwaA0KDQpgYGB7ciBOdW1iZXI1X0Fuc3dlciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRSwgZmlnLmhlaWdodD0gNiwgZmlnLndpZHRoPSAxMH0NCg0KR3JhcGhRNSA8LSANCiAgIyBUYWtlIFN1cnZleSBEYXRhDQogIFN1cnZleSU+JSANCiAgI1NlbGVjdCBuZWNlc3NhcnkgY29sdW1ucw0KICBkcGx5cjo6c2VsZWN0KGhoaWQsIGh2MDI1LCBobWwxNiwgc2JlbGlnLCBobWwzMiklPiUNCiAgI0ZpbHRlcmluZyBieSBjb3JyZWN0aXZlIGFnZSB1bmRlciA2DQogIGZpbHRlcihobWwxNiA8IDYpICU+JSANCiAgIyBDcmVhdGUgbmV3IGZpZWxkIGZvciBydXJhbCBhbmQgbmVnYXRpdmUNCiAgbXV0YXRlKFJ1cmFsID0gaWZlbHNlKGh2MDI1ID09ICdydXJhbCcgJiBobWwzMiA9PSAnbmVnYXRpdmUnICYgc2JlbGlnID09ICd5ZXMsIHNlbGVjdGVkIGZvciBtaWNyb3Njb3B5JywgMSwgMCkpJT4lIA0KICAjIENyZWF0ZSBuZXcgZmllbGQgZm9yIHVyYmFuIGFuZCBuZWdhdGl2ZQ0KICBtdXRhdGUoVXJiYW4gPSBpZmVsc2UoaHYwMjUgPT0gJ3VyYmFuJyAmIGhtbDMyID09ICduZWdhdGl2ZScgJiBzYmVsaWcgPT0gJ3llcywgc2VsZWN0ZWQgZm9yIG1pY3Jvc2NvcHknLCAxLCAwKSklPiUgDQogICNDcmVhdGUgbmV3IGZpZWxkIGZvciBwb3NpdGl2ZSBhbmQgcnVyYWwNCiAgbXV0YXRlKHBvcyA9IGlmZWxzZShobWwzMiA9PSAncG9zaXRpdmUnICYgc2JlbGlnID09ICd5ZXMsIHNlbGVjdGVkIGZvciBtaWNyb3Njb3B5JyAmIGh2MDI1ID09ICdydXJhbCcsIDEsIDApKSU+JSANCiAgI0NyZWF0ZSBuZXcgZmllbGQgZm9yIHBvc2l0aXZlIGFuZCB1cmJhbg0KICBtdXRhdGUocG9zMiA9IGlmZWxzZShobWwzMiA9PSAncG9zaXRpdmUnICYgc2JlbGlnID09ICd5ZXMsIHNlbGVjdGVkIGZvciBtaWNyb3Njb3B5JyAmIGh2MDI1ID09ICd1cmJhbicsIDEsIDApKSU+JQ0KICAjU2VsZWN0IG5ldyBwcm9wb3J0aW9uIGZpZWxkcyBhbmQgSUQNCiAgZHBseXI6OnNlbGVjdChoaGlkLCBVcmJhbiwgUnVyYWwsIHBvcywgcG9zMiklPiUgDQogICNGaWx0ZXIgZG93biB0byBjaGlsZHJlbiB0aGF0IGV1cWFsIDEgZm9yIGF0IGxlYXN0IG9uZSBvZiB0aGUgZm91ciBjcmVhdGVkIGZpZWxkcw0KICBmaWx0ZXIoVXJiYW4gPT0gMSAgfCBSdXJhbCA9PSAxIHwgcG9zID09IDEgfCBwb3MyID09IDEpJT4lIA0KICAjcmVtb3ZlIGR1cGxpY2F0ZSBJRHMNCiAgZGlzdGluY3QoKSU+JSANCiAgI1NlbGVjdCBwcm9wb3J0aW9uIGZpZWxkcw0KICBkcGx5cjo6c2VsZWN0KFVyYmFuLCBSdXJhbCwgcG9zLCBwb3MyKSU+JSANCiAgI1N1bSB1cCBlYWNoIGNhdGVnb3J5DQogIHN1bW1hcmlzZShQb3MgPSBzdW0ocG9zKSwgUG9zMiA9IHN1bShwb3MyKSwgIFJ1cmFsID0gc3VtKFJ1cmFsKSwgVXJiYW4gPSBzdW0oVXJiYW4pKSU+JSANCiAgI1JlbmFtZSBmaWVsZHMNCiAgcmVuYW1lKGBQb3NpdGl2ZSBmb3IgTWFsYXJpYSA7IFJ1cmFsYCA9IFBvcywgYFBvc2l0aXZlIGZvciBNYWxhcmlhIDsgVXJiYW5gID0gUG9zMixgTmVnYXRpdmUgZm9yIE1hbGFyaWEgOyBSdXJhbGA9IFJ1cmFsLCBgTmVnYXRpdmUgZm9yIE1hbGFyaWEgOyBVcmJhbmAgPSBVcmJhbiklPiUgDQogICNwaXZvdCB0YWJsZSB0byBzZXQgdXAgZm9yIGdncGxvdA0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGBQb3NpdGl2ZSBmb3IgTWFsYXJpYSA7IFJ1cmFsYCA6YE5lZ2F0aXZlIGZvciBNYWxhcmlhIDsgVXJiYW5gLA0KICAgIG5hbWVzX3RvID0gIkNhdGVnb3J5IiwgDQogICAgdmFsdWVzX3RvID0gIkNoaWxkcmVuIiklPiUgDQogICNNYWtlIHN1cmUgbnVtYmVyIG9mIGNoaWxkcmVuIGlzIG51bWVyaWMNCiAgbXV0YXRlKENoaWxkcmVuID0gYXMubnVtZXJpYyhDaGlsZHJlbikpDQoNCmdncGxvdCgpKyANCiAgZ2VvbV9iYXIoZGF0YSA9IEdyYXBoUTUsIGFlcyh4ID0gQ2F0ZWdvcnksIHkgPSBDaGlsZHJlbiwgZmlsbCA9IENhdGVnb3J5ICksIHN0YXQgPSAnaWRlbnRpdHknKSsgDQogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIE5pZ2VyaWFuIENoaWxkcmVuIGJ5IE1hbGFyaWEgU3RhdHVzIHZpYSBNaWNyb3Njb3B5IiwgDQogICAgICAgc3VidGl0bGUgPSAiU291cmNlOiBOaWdlcmlhbiBIZWFsdGggU3VydmV5IikrIA0KICB5bGFiKCJOdW1iZXIgb2YgQ2hpbGRyZW4iKSArIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCAnI0U1OUU5RScsJyNFNjIwMjAnLCAnIzAwRjM4QScsJyMwMDhDNEYnKSkrDQogIHBsb3RUaGVtZSgpKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQpgYGANCg0KIyMgUXVlc3Rpb24gNiANCg0KTWFrZSBhbm90aGVyIHBsb3Qgc2hvd2luZyB0aGUgcHJvcG9ydGlvbiBvZiBVNSBjaGlsZHJlbiB0aGF0IHRlc3RlZCBwb3NpdGl2ZSBmb3IgbWFsYXJpYSBieSBtaWNyb3Njb3B5IGFuZCB0aGUgcHJvcG9ydGlvbiBvZiBVNSBjaGlsZHJlbiB0aGF0IHRlc3RlZCBuZWdhdGl2ZSBmb3IgbWFsYXJpYSBieSBtaWNyb3Njb3B5IGluIHVyYmFuIGFuZCBydXJhbCBhcmVhcw0KDQpTVEVQUw0KDQoxLiBVc2UgUXVlc3Rpb24gNSBhbmFseXNpcw0KDQoyLiBDYWxjdWxhdGUgcHJvcG9ydGlvbnMNCg0KMy4gQ2FsY3VsYXRlIHBpZSBjaGFydCBwb3NpdGlvbmluZw0KDQo0LiBDcmVhdGUgZ3JhcGggdXNpbmcgR0dQbG90DQoNCmBgYHtyIE51bWJlcjZfQW5zd2VyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBUUlVFLCBmaWcuaGVpZ2h0PSA0LCBmaWcud2lkdGg9IDZ9DQoNCm9wdGlvbnMoZGlnaXRzID0gMykgDQoNCkdyYXBoUTVfUHJvcCA8LSANCiAgI1Rha2luZyBwcmV2aW91cyBhbmFseXNpcyBmcm9tIFF1ZXN0aW9uIDUNCiAgR3JhcGhRNSU+JSANCiAgI0NhbGN1bGF0aW5nIHByb3BvcnRpb25zIGZvciBlYWNoIGNhdGVnb3J5DQogIG11dGF0ZShQcm9wb3J0aW9uID0gKENoaWxkcmVuLyBzdW0oR3JhcGhRNSRDaGlsZHJlbikqIDEwMCkpJT4lDQogICNTZWxlY3Rpbmcgb25seSBjYXRlZ29yeSBhbmQgcHJvcG9ydGlvbg0KICBkcGx5cjo6c2VsZWN0KENhdGVnb3J5LCBQcm9wb3J0aW9uKSU+JQ0KICAjRmllbGQgdG8gZGVmaW5lIGxhYmVsIHBvc2l0aW9uaW5nIG9uIHBpZSBjaGFydA0KICBtdXRhdGUoY3N1bSA9IHJldihjdW1zdW0ocmV2KFByb3BvcnRpb24pKSksIA0KICAgICAgICAgcG9zID0gUHJvcG9ydGlvbi8yICsgbGVhZChjc3VtLCAxKSwNCiAgICAgICAgIHBvcyA9IGlmX2Vsc2UoaXMubmEocG9zKSwgUHJvcG9ydGlvbi8yLCBwb3MpKQ0KDQoNCmdncGxvdChHcmFwaFE1X1Byb3AsIGFlcyh4PSIiLCB5PVByb3BvcnRpb24sIGZpbGw9ZmN0X2lub3JkZXIoQ2F0ZWdvcnkpKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIsIHN0YXJ0ID0gMCkgKw0KICB0aGVtZV92b2lkKCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikrDQogIGxhYnModGl0bGUgPSAiUGVyY2VudGFnZSBvZiBDaGlsZHJlbiBUZXN0aW5nIFBvc2l0aXZlIG9yIE5lZ2F0aXZlIGZvciBNYWxhcmlhIGJ5IEdlb2dyYXBoaWMgUmVnaW9uIiwgDQogICAgICAgc3VidGl0bGUgPSAiU291cmNlOiBOaWdlcmFuIEhlYWx0aCBTdXJ2ZXkiKSsNCiAgICBnZW9tX2xhYmVsX3JlcGVsKGRhdGEgPSBHcmFwaFE1X1Byb3AsDQogICAgICAgICAgICAgICAgICAgYWVzKHkgPSBwb3MsIGxhYmVsID0gcGFzdGUwKGFzLmludGVnZXIoUHJvcG9ydGlvbiksICIlIikpLA0KICAgICAgICAgICAgICAgICAgIHNpemUgPSAzLjUsIG51ZGdlX3ggPSAxLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyggJyMwMEYzOEEnLCcjMDA4QzRGJywnI0U1OUU5RScsJyNFNjIwMjAnKSkrIA0KICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9IkNhdGVnb3JpZXMiKSkNCg0KYGBgDQoNCiMjIFF1ZXN0aW9uIDcgDQoNCk1ha2UgYSBtYXAgb2YgdGhlIG51bWJlciBvZiBjaGlsZHJlbiB0aGF0IHRlc3RlZCBwb3NpdGl2ZSBmb3IgbWFsYXJpYSBieSBzdGF0ZQ0KDQpTVEVQUw0KDQoxLiBGaWx0ZXIgYnkgcG9zaXRpdmUgcmFwaWQgb3IgcG9zaXRpdmUgYmxvb2Qgc21lYXIsIGFsb25nIHdpdGggdW5kZXIgMTggY29ycmVjdGl2ZSBhZ2UNCg0KMi4gQWRkIG5ldyBmZWlsZCBmb3IgY291bnQNCg0KMy4gRW5zdXJlIG5vIGR1cGxpY2F0ZSBJRHMNCg0KNC4gR3JvdXAgYnkgU3RhdGUNCg0KNS4gU3VtIENvdW50DQoNCjYuIEpvaW4gc3RhdGUgZGF0YSB0byBzdXJ2ZXkgZGF0YQ0KDQo3LiBDcmVhdGUgbWFwDQoNCg0KYGBge3IgTnVtYmVyN19BbnN3ZXIsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBjYWNoZSA9IFRSVUUsIGZpZy5oZWlnaHQ9IDYsIGZpZy53aWR0aD0gMTB9DQoNCkJ5U3RhdGUgPC0gDQogIFN1cnZleSU+JQ0KICAjRmlsdGVyIGJ5IGNoaWxkcmVuIHBvc2l0aXZlIGZvciByYXBpZCB0ZXN0IG9yIHBvc2l0aXZlIGZvciBibG9vZCBzbWVhcg0KICBmaWx0ZXIoKGhtbDMyID09ICdwb3NpdGl2ZScgfCBobWwzNSA9PSAncG9zaXRpdmUnKSAmIGhtbDE2IDwgMTgpICU+JQ0KICAjTmV3IGZpZWxkIHdoZXJlIGNvdW50IGlzIG9uZSAoZ29pbmcgdG8gYmUgdXNlZCBmb3IgYWdncmVnYXRpb24pDQogIG11dGF0ZShDb3VudCA9IDEpJT4lDQogICNTZWxlY3QgbmVjZXNzYXJ5IGZpZWxkcw0KICBkcGx5cjo6c2VsZWN0KGhoaWQsIHNoc3RhdGUsIENvdW50KSU+JSANCiAgI1JlbW1vdmUgcmVwZWF0IElEUw0KICBkaXN0aW5jdCgpICU+JSANCiAgI0dyb3VwIGJ5IHN0YXRlDQogIGdyb3VwX2J5KHNoc3RhdGUpICU+JQ0KICAjU3VtIGJ5IHN1bW1pbmcgdXAgdGhlIGNvdW50IGZpZWxkIHByZXZpb3VzbHkgY3JlYXRlZA0KICBzdW1tYXJpc2UoQ2hpbGRDYXNlcyA9IHN1bShDb3VudCkpICU+JSANCiAgI0RlYWxpbmcgd2l0aCBOQSBWYWx1ZXMNCiAgbXV0YXRlKENoaWxkQ2FzZXMgPSBpZmVsc2UoaXMubmEoQ2hpbGRDYXNlcykgPT0gVCwgMCwgQ2hpbGRDYXNlcykpDQoNCkdlbyA8LSANCiAgRGF0YSU+JSANCiAgI211dGF0aW5nIHN0YXRlIG5hbWUgdG8gbG93ZXJjYXNlIGZvciBqb2luDQogIG11dGF0ZShzaHN0YXRlID0gdG9sb3dlcihOQU1FXzEpKSU+JSANCiAgI2pvaW5pbmcgYnkgU3RhdGUNCiAgbGVmdF9qb2luKEJ5U3RhdGUsIGJ5ID0gInNoc3RhdGUiKSANCg0KIGdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gR2VvLCBhZXMoZmlsbCA9IHE1KENoaWxkQ2FzZXMpKSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCcjRkZFQkVCJywgJyNGRkFGQUQnLCcjRkYyMjFGJywnI0UwMDQwMCcsICcjQTMwMzAwJyApLCANCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiMC0yMyIsICIyNC03MCIsICI3MS05OSIsICIxMDAgLSAxMjAiLCAiMTIxIC0gMTc2IiwgIk4vQSIpLCANCiAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJDaGlsZCBNYWxhcmlhIENhc2VzIFxuKFF1aW50aWxlIEJyZWFrcykiKSArDQogIGxhYnModGl0bGUgPSAiTmlnZXJpYW4gTWFsYXJpYSBDYXNlcyBieSBSZWdpb24iLCBzdWJ0aXRsZSA9ICJTb3VyY2U6IE5pZ2VyaWFuIEhlYWx0aCBTdXJ2ZXkiKSArDQogIG1hcFRoZW1lKCkNCg0KDQoNCg0KYGBgDQoNCiMjIFF1ZXN0aW9uIDggDQoNCkV4dHJhY3QgdGhlIGRhdGEgZnJvbSB0aGUgcmFzdGVyIGZpbGUgYW5kIG1ha2UgYSBtYXAgc2hvd2luZyBhdmVyYWdlIGhvdXNpbmcgcXVhbGl0eSB2YWx1ZXMgZm9yIGVhY2ggTmlnZXJpYW4gc3RhdGUuDQoNClNURVBTDQoNCjEuIEltcG9ydCBSYXN0ZXINCg0KMi4gVHJhbnNmb3JtIHRvIFBvbHkNCg0KMy4gVHJhbnNmb3JtIHRvIFNGIENsYXNzDQoNCjQuIEludGVyc2VjdCBOaWdlcmlhbiBTdGF0ZWJvdW5kYXJpZXMgd2l0aCBTRiBDbGFzcw0KDQo1LiBHcm91cCBieSBTdGF0ZQ0KDQo2LiBTdW1tYXJpc2UgYXZlcmFnZSBob3VzaW5nIHF1YWxpdHkNCg0KNy4gQ3JlYXRlIE1hcA0KDQpgYGB7ciBOdW1iZXI4X0Fuc3dlciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRSwgZmlnLmhlaWdodD0gNSwgZmlnLndpZHRoPSA3fQ0KDQojSW1wb3J0aW5nIFJhc3Rlcg0KTmlnZXJpYW5Ib3VzaW5nIDwtIHJhc3RlcigiQzpcXFVzZXJzXFxLeWxlIE1jQ2FydGh5XFxEb2N1bWVudHNcXExveW9sYVxcTkdQUjdBRFRcXGhvdXNpbmcgZGF0YSAyMDE5IG5pZ2VyaWFcXDIwMTlfTmF0dXJlX0FmcmljYV9Ib3VzaW5nXzIwMTVfTkdBLnRpZmYiKQ0KI1Jhc3RlciB0byBQb2x5DQpwb2x5PC0gcmFzdGVyVG9Qb2x5Z29ucyhOaWdlcmlhbkhvdXNpbmcpDQoNCiMgVG8gU0YgQ2xhc3MNCnBvbHkgPC0gc3RfYXNfc2YocG9seSkNCg0KI0ludGVyc2VjdGluZyBuZXcgcG9seSB3aXRoIG5pZ2VyaWFuIHJhc3Rlcg0KQWdncmVnYXRlIDwtIA0KICBzdF9pbnRlcnNlY3Rpb24ocG9seSwgR2VvKQ0KDQpBZ2dyZWdhdGUxPC0gDQogIEFnZ3JlZ2F0ZSU+JQ0KICAjR3JvdXBpbmcgYnkgc3RhdGUNCiAgZ3JvdXBfYnkoc2hzdGF0ZSklPiUNCiAgI1N1bW1hcmlzZSBieSBhdmVyYWdlIGhvdXNpbmcgcXVhbGl0eQ0KICBzdW1tYXJpc2UoYEF2ZXJhZ2UgSG91c2luZyBRdWFsaXR5YCA9IG1lYW4oWDIwMTlfTmF0dXJlX0FmcmljYV9Ib3VzaW5nXzIwMTVfTkdBKSkNCg0KDQogZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBBZ2dyZWdhdGUxLCBhZXMoZmlsbCA9IGBBdmVyYWdlIEhvdXNpbmcgUXVhbGl0eWApKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIiNFRUZGRUUiLCBoaWdoID0gIiMzMzU1MzMiKSAgKw0KICBsYWJzKHRpdGxlID0gIk5pZ2VyaWFuIEF2ZXJhZ2UgSG91c2luZyBRdWFsaXR5IFNjb3JlIGJ5IFJlZ2lvbiIpICsNCiAgbWFwVGhlbWUoKQ0KDQogIA0KYGBgDQoNCiMjIFF1ZXN0aW9uIDkNCg0KSWRlbnRpZnkgYW55IHdlYnNpdGUgb2YgeW91ciBjaG9pY2UgYW5kIHNjcnViIHRoZWlyIGRhdGEuIFB1bGwgaXQgaW50byBhIGNzdiBhbmQgbWFrZSBhdCBsZWFzdCBvbmUgZGF0YSB2aXN1YWxpemF0aW9uLg0KDQpTVEVQUw0KDQoxLiBJZGVudGlmaWVkIG1vcnRhbGl0eSBkYXRhc2V0IG9mIEJhbGl0bW9yZQ0KDQoyLiBEb3dubG9hZGVkIGFsbCBhc3NvY2llZCBkYXRhDQoNCjMuIEpvaW5lZCBkYXRhIHdpdGggeW91bmdlciBwb3B1bGF0aW9ucyB0b2dldGhlciAtLS0gc3BsaXQgdXAgZnJvbSBvbGRlciBwb3B1bGF0aW9ucyBzbyB0aGF0IHdlIGNhbiBoYXZlIG9uZSBzY2FsZSBmb3IgeW91bmdlciBwb3B1bGF0aW9ucyBhbmQgb25lIHNjYWxlIGZvciBvbGRlciBwb3B1bGF0aW9ucyBhcyB0aGUgbW9ydGFsaXR5IHJhdGUgaXMgaGlnaGVyIGluIG9sZGVyIHBvcHVsYXRpb25zDQoNCjQuIEFsdGVyIHRhYmxlIHRvIHByZXBhcmUgZm9yIGEgZmFjZXQgd3JhcCBtYXANCg0KNS4gQ3JlYXRlIG1hcCANCg0KNi4gUmVwZWF0IGZvciBvbGRlciBwb3B1bGF0aW9ucw0KDQoNCmBgYHtyIE51bWJlcjlfRGF0YSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRSwgcmVzdWx0cyA9ICdoaWRlJ30NCg0KTTFUbzE0PC0gc3RfcmVhZCgnQzpcXFVzZXJzXFxLeWxlIE1jQ2FydGh5XFxEb2N1bWVudHNcXExveW9sYVxcTW9ydDE0X18tNzEzMTk1NTcyNzQzNTM4NTc3OS5nZW9qc29uJyklPiUgDQogIGRwbHlyOjpzZWxlY3QoQ1NBMjAxMCwgbW9ydDE0XzE4KQ0KDQpNMTVUbzI0PC0gc3RfcmVhZCgnQzpcXFVzZXJzXFxLeWxlIE1jQ2FydGh5XFxEb2N1bWVudHNcXExveW9sYVxcTW9ydDI0X180NDA0MzczNTkwNjQyOTY0OTAuZ2VvanNvbicpJT4lIA0KICBkcGx5cjo6c2VsZWN0KENTQTIwMTAsIG1vcnQyNF8xOCkNCg0KTTI0VG80NDwtIHN0X3JlYWQoJ0M6XFxVc2Vyc1xcS3lsZSBNY0NhcnRoeVxcRG9jdW1lbnRzXFxMb3lvbGFcXE1vcnQ0NF9fNjI2MjIwNTkxODgzMjgyNzMxNS5nZW9qc29uJyklPiUgDQogIGRwbHlyOjpzZWxlY3QoQ1NBMjAxMCwgbW9ydDQ0XzE4KQ0KDQpNNDVUbzY0PC0gc3RfcmVhZCgnQzpcXFVzZXJzXFxLeWxlIE1jQ2FydGh5XFxEb2N1bWVudHNcXExveW9sYVxcTW9ydDY0X18tNjIwOTk0MDk0OTQ2NDkxMjM3Mi5nZW9qc29uJyklPiUgDQogIGRwbHlyOjpzZWxlY3QoQ1NBMjAxMCwgbW9ydDY0XzE4KQ0KDQpNNDVUbzY0PC0gc3RfcmVhZCgnQzpcXFVzZXJzXFxLeWxlIE1jQ2FydGh5XFxEb2N1bWVudHNcXExveW9sYVxcTW9ydDY0X18tNjIwOTk0MDk0OTQ2NDkxMjM3Mi5nZW9qc29uJyklPiUgDQogIGRwbHlyOjpzZWxlY3QoQ1NBMjAxMCwgbW9ydDY0XzE4KQ0KDQpNNjVUbzg0PC0gc3RfcmVhZCgnQzpcXFVzZXJzXFxLeWxlIE1jQ2FydGh5XFxEb2N1bWVudHNcXExveW9sYVxcTW9ydDg0X183MDgwNjc2Mjc1MzIwNjc0MTE4Lmdlb2pzb24nKSU+JSANCiAgZHBseXI6OnNlbGVjdChDU0EyMDEwLCBtb3J0ODRfMTgpDQoNCmBgYA0KDQpgYGB7ciBOdW1iZXI5X0Fuc3dlciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRSwgZmlnLmhlaWdodD0gNSwgZmlnLndpZHRoPSA3fQ0KDQpNb3J0YWxpdHlEYXRhIDwtIA0KICBNMVRvMTQlPiUNCiAgc3RfZHJvcF9nZW9tZXRyeSgpJT4lIA0KICBsZWZ0X2pvaW4oLiwgTTE1VG8yNCklPiUgDQogIHJpZ2h0X2pvaW4oLiwgTTI0VG80NCklPiUNCiAgcmVuYW1lKGBBZ2VzIDEgdG8gMTRgID0gbW9ydDE0XzE4LCANCiAgICAgICAgIGBBZ2VzIDE1IHRvIDI0YCA9IG1vcnQyNF8xOCwgDQogICAgICAgICBgQWdlcyAyNSB0byA0NGAgPSBtb3J0NDRfMTgpJT4lIA0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGMoYEFnZXMgMSB0byAxNGAsYEFnZXMgMTUgdG8gMjRgLGBBZ2VzIDI1IHRvIDQ0YCkgLA0KICAgIG5hbWVzX3RvID0gIkFnZSBDYXRlZ29yeSIsIA0KICAgIHZhbHVlc190byA9ICJNb3J0YWxpdHkiKSU+JSANCiAgc3RfYXNfc2YoKQ0KDQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IE1vcnRhbGl0eURhdGEsIGFlcyhmaWxsID0gIE1vcnRhbGl0eSkpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiI0ZGRUVFRSIsIGhpZ2ggPSAiIzc3MzMzMyIpICArDQogIGxhYnModGl0bGUgPSAiTW9ydGFsaXR5IFJhdGUgYnkgQmFsaXRtb3JlIE5laWdoYm9yaG9vZCIsIHN1YnRpdGxlID0gIllvdW5nZXIgUG9wdWxhdGlvbnMiKSArDQogIG1hcFRoZW1lKCkrIA0KICBmYWNldF93cmFwKHZhcnMoYEFnZSBDYXRlZ29yeWApKQ0KDQoNCk1vcnRhbGl0eURhdGFfT2xkZXIgPC0gDQogIE00NVRvNjQlPiUNCiAgc3RfZHJvcF9nZW9tZXRyeSgpJT4lIA0KICBsZWZ0X2pvaW4oLiwgTTY1VG84NCklPiUgDQogIHJlbmFtZShgQWdlcyA0NSB0byA2NGAgPSBtb3J0NjRfMTgsIA0KICAgICAgICAgYEFnZXMgNjUgdG8gODRgID0gbW9ydDg0XzE4KSU+JSANCiAgcGl2b3RfbG9uZ2VyKA0KICAgIGNvbHMgPSBjKGBBZ2VzIDQ1IHRvIDY0YCxgQWdlcyA2NSB0byA4NGApICwNCiAgICBuYW1lc190byA9ICJBZ2UgQ2F0ZWdvcnkiLCANCiAgICB2YWx1ZXNfdG8gPSAiTW9ydGFsaXR5IiklPiUgDQogIHN0X2FzX3NmKCkNCg0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBNb3J0YWxpdHlEYXRhX09sZGVyLCBhZXMoZmlsbCA9ICBNb3J0YWxpdHkpKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIiNGRkVFRUUiLCBoaWdoID0gIiM3NzMzMzMiKSAgKw0KICBsYWJzKHRpdGxlID0gIk1vcnRhbGl0eSBSYXRlIGJ5IEJhbGl0bW9yZSBOZWlnaGJvcmhvb2QiLCBzdWJ0aXRsZSA9ICJPbGRlciBQb3B1bGF0aW9ucyIpICsNCiAgbWFwVGhlbWUoKSsgDQogIGZhY2V0X3dyYXAodmFycyhgQWdlIENhdGVnb3J5YCkpDQoNCiAgDQogIA0KDQpgYGANCg0K