#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

  1. Filter to those with ages under 6 (corrective age)

  2. Filter those who tested positive for a Blood Smear

  3. 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)
n
1546

Question 2

How Many Rapid Tests for Children Under 5?

Steps

  1. Filter to children under 6 based on their corrective age.

  2. Filter to where rapid blood test *hml35) is equal to positive, negative, or missing indicating a test was making

  3. 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)
n
10815

Question 3

How many Microscopy Positive Results for Children?

STEPS

  1. Using blood smear test as the microscopy result

  2. filtered to those that tested positive for the blood smear

  3. Also filtered to those that were selected for a microscopy

  4. Use corrective age to ensure age under 18

  5. 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)
n
1546

Question 4

How many Positive Rapid Tests for Children?

STEPS

  1. Filter by corrective age to under 18 and rapid test to positive

  2. 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)
n
3229

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

  1. Filtered by Children under 5

  2. Create categories for rural/urban, positive status/ negative status using new fields

  3. Ensure no duplicate IDs

  4. Reformat table

  5. 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

  1. Use Question 5 analysis

  2. Calculate proportions

  3. Calculate pie chart positioning

  4. 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

  1. Filter by positive rapid or positive blood smear, along with under 18 corrective age

  2. Add new feild for count

  3. Ensure no duplicate IDs

  4. Group by State

  5. Sum Count

  6. Join state data to survey data

  7. 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

  1. Import Raster

  2. Transform to Poly

  3. Transform to SF Class

  4. Intersect Nigerian Stateboundaries with SF Class

  5. Group by State

  6. Summarise average housing quality

  7. 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

  1. Identified mortality dataset of Balitmore

  2. Downloaded all associed data

  3. 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

  4. Alter table to prepare for a facet wrap map

  5. Create map

  6. 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