Set up

First make sure to install and load all packages needed. This chunk will also load functions related to the analysis.



# Load libraries and functions #

ipak <- function(pkg){
  new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
  if (length(new.pkg)) 
    install.packages(new.pkg, dependencies = TRUE)
  sapply(pkg, require, character.only = TRUE)
}


#### Library ####
packages <- c(
  "readxl", # Read dataframe in excel format
  "dplyr", # Data manipulation
  "tidyr", # Data manipulation
  "ggplot2", #Nice grpahs and spatial analysis
  # "cowplot",
  # "forcasts",
  # "rgdal",
  # "RColorBrewer",
  "knitr",
  "kableExtra",
  "data.table", # Fast read data
  # "ggrepel",
  # "gridExtra",
  # "ggmap",
  # "rgeos",
  "sf",
  # "sp",
  # "rgdal", #Spatial analysis
  "tools", #Spatial analysis
  # "png", # For reading plots in chunk codes
  # "grid" # For reading plots in chunk codes
  "stringr" # For filtering by string
)

ipak(packages)
##__________________FUNCTIONS _________________________##

# Standarization of plots
ggtheme_plot <- function() {
  theme(
    plot.title = element_text(size = rel(1), hjust = 0, face = "bold"),
    panel.background = element_blank(),
    strip.background = element_blank(),
    # strip.text       = element_text(size = base_size, face = "italic"),
    panel.border     = element_blank(),
    panel.grid.minor = element_blank(),
    panel.grid.major = element_blank(),
    axis.ticks = element_blank(),
    axis.text.x = element_text(size = 10,
                               angle = 0,
                               face = "plain"),
    axis.text.y = element_text(size = 12),
    axis.title = element_text(size = 14),
    legend.key = element_rect(colour = NA, fill = NA),
    legend.position  = "top",
    legend.title = element_text(size = 16),
    legend.text = element_text(size = 14),
    strip.text.x = element_text(size = 18, colour = "darkgrey"),
    strip.text = element_text(size = 18)
  )
}

# Standarization of maps
ggtheme_map <- function(base_size = 9, Region = "NA") {
  
  theme(text             = element_text(#family = "Helvetica",
    color = "gray30", size = base_size),
    plot.title       = element_text(size = rel(1.25), hjust = 0, face = "bold"),
    panel.background = element_blank(),
    panel.border     = element_blank(),
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(color = "transparent"),
    strip.background =element_rect(fill = "transparent"),
    strip.text.x = element_text(size = 18, colour = "black",face= "bold.italic", angle = 0),
    axis.line        = element_blank(), # element_line(colour = "grey30", size = .5))
    axis.ticks       = element_blank(),
    axis.text        = element_blank(),
    axis.title       = element_blank(),
    # legend.key       = element_rect(colour = NA, fill = NA, size = 4),
    legend.position = "bottom"#,
    # legend.key.width =unit(6,"line")
  )
}

Overall Map

Loading DBEM data

Data Wrangling

  • We need to make some corrections to the shapefile to project everything with North America centered. Basically solve for the fact that Alaska is in the other side of the globe because the Earth is round, shocking!

  • We also have to include a column referencing the country’s EEZ for the analysis


# LAT LONG Corrections for map projection

DBEM_Corrected <- DBEM_Results %>% 
  filter(INDEX %in% All_EEZs$INDEX) %>% 
  filter(Longitude > 0) %>% 
  mutate(Longitude = Longitude - 360)

DBEM_Corrected <- DBEM_Results %>% 
  filter(INDEX %in% All_EEZs$INDEX) %>% 
  filter(Longitude < 0) %>% 
  bind_rows(DBEM_Corrected)

# head(DBEM_Corrected)

# Just checking #####

# DBEM_Corrected %>%
#   group_by(INDEX, Longitude, Latitude) %>%
#   summarise(n =n()) %>%
#   ggplot(.,
#          aes(x = Longitude,
#              y = Latitude,
#              fill = n
#          ),
#          size = 0.05,
#          alpha = 0.5) +
#   geom_tile() #+
# coord_map(projection = "mercator")


### Get ridd of any Pacific Species in NAFO

NAFO_E <- DBEM_Corrected %>% 
  filter(Longitude >= -100)

Pacific <- DBEM_Corrected %>% 
  filter(Treaty != "NAFO")

DBEM_Corrected <- NAFO_E %>% 
  bind_rows(Pacific)

# unique(DBEM_Corrected$Species)

# Remove salmons...

Salmons <- c("Oncorhynchus keta","Oncorhynchus kisutch","Oncorhynchus nerka","Oncorhynchus tshawytscha","Oncorhynchus gorbuscha","Salmo salar")

Chapter_Data <- DBEM_Corrected %>%
  # filter(!Species %in% Salmons) %>% # Reomve or only analysis with salmons
  left_join(All_EEZs,
            by ="INDEX") %>% 
  select(-EEZID)

# Show table with species 

# names(Chapter_Data)
# head(Chapter_Data)

Chapter_Data %>% 
  group_by(Species, Treaty) %>% 
  summarise(n=n()) %>% 
  ungroup() %>% 
  left_join(exploited_species_list,
            by = "Species") %>% 
  arrange(Treaty) %>% 
  select(Species,CommonName,Treaty) %>% 
  kable()

Loading Spatial data


# Countries included 

Countries <- c("Canada","United States","Alaska")


# World shapefile
path_world <- "~/Documents/R Code/Spatial_Analysis/Data/TM_WORLD_BORDERS-0.3"
file_name <- "TM_WORLD_BORDERS"

World_Land_sf <- st_read(dsn = path_world, 
                         layer = file_path_sans_ext(file_name)
) %>% 
  st_transform(crs = 3832)

North_America_Land <- World_Land_sf %>% 
  filter(NAME %in% Countries)

# Checkpoint 
# unique(North_America_Land$NAME) [1] Canada        Greenland     United States

# Map it? Yup!
# ggplot(North_America_Land) +
# geom_sf()

# EEZs shapefile ####

path_eez<- ("~/Documents/R Code/Spatial_Analysis/Data/World_EEZ_v10_2018")
#The File
fnam_eez <- "eez_boundaries_v10.shp" # Just lines
# fnam_eez <- "eez_v10.shp" # Actual shapefiles (takes 4-ever, for ever ever? fooor eever eeever!?)

eez_world_sf <- st_read(dsn = path_eez, 
layer = file_path_sans_ext(fnam_eez)
) %>% 
  st_transform(crs = 4326) #3832 centered

# head(eez_world_sf)

#Checkpoint  
# unique(eez_world_sf$Territory1) 

# North_America_EEZ <- eez_world_sf %>% 
#   filter(Territory1 %in% Countries) %>% 
#   st_transform(crs = 4326)

#Checkpoint
# unique(North_America_EEZ$Territory1)
# Map it? 
# ggplot(North_America_EEZ) +
#   geom_sf()
# Nope, Alaska is not showing up. Neither East Greenland

# Greenland Shapefile Bug ####
# First lets get all of greenalnd in the map... 
# 
# eez_world_sf %>%
#   filter(str_detect(Territory1,"Canada")) %>%
#   # mutate(Basin = ifelse( x_1 >= -100, "Atlantic","Pacific")) %>%
#   head()
#   ggplot() +
#   # geom_sf(aes(fill = Basin))
#   geom_sf()
# 
# 
# 
# # The chunk missing is from Iceland
# Iceland <-  eez_world_sf %>% 
#   # group_by(Territory1) %>% 
#   # summarise(n()) %>% 
#   # filter(str_detect(Territory1,"Iceland")) # %>% 
#   filter(Line_ID ==135)
#   # ggplot() +
#   # geom_sf()
# 
# eez_world_sf %>%
#   filter(str_detect(Territory1,"Greenland") |
#          Line_ID == 135) %>% # Include this in final map plot
#   ggplot() +
#   geom_sf() #+
#   # geom_sf(data = Iceland)
# 
# # Alaska Shapefile Bug ####
# eez_world_sf %>% 
#   filter(Territory1 %in% Countries) %>% 
#   st_transform(crs = 3832) %>% 
#   ggplot() +
#   geom_sf()
#   
# # The chunk missing is from Russia
# eez_world_sf %>%
#   filter(str_detect(Territory1,"Alaska") |
#            MRGID_Ter2 == 8684) %>% # This includes Russia side (Include in final plot)
#   st_transform(crs = 3832) %>%
#   # View()
#   ggplot() +
#   geom_sf(aes(col=Line_type))
# 
# 
# # South US (Atlantic) Shapefile Bug ####
# 
# # The chunk missing is from ... Mexico and Cuba?... and Bahamas. Nope, just Mexico
# eez_world_sf %>%
#   # filter(str_detect(Territory1"United States")) %>% 
#   filter(Territory1 %in% c ("United States", "Mexico", "Cuba","Bahamas"))
# 
# 
# ### Mexico First (Taht's it! )
# 
# eez_world_sf %>%
#   # filter(str_detect(Territory1"United States")) %>% 
#   filter(Territory1 %in% c ("United States") |
#          MRGID_Ter2 == 2204) %>%  # Inlcude this for Mexico's southern boundary
#   # st_transform(crs = 3832) %>%
#   # View()
#   ggplot() +
#   geom_sf(aes(col=Line_type))


#### The Actual Map ####

# We need to inlcude alaska in here
Countries <- c("Canada","United States", "Alaska")

# Here we go again
North_America_EEZ <- eez_world_sf %>% 
  filter(Territory1 %in% Countries |
           Line_ID == 135 | # # Line missing from Greenland (Iceland)
         MRGID_Ter2 == 8684 |
           MRGID_Ter2 == 2204) %>%  # Line missing from Alaska (Russia)
  st_transform(crs = 3832)

# Finall check! 
# ggplot(North_America_EEZ) +
#   geom_sf()

# Yup! 

# Map both shapefiles to see how it looks

# ggplot() +
#   geom_sf(data = North_America_Land) +
#   geom_sf(data = North_America_EEZ)

# Annnnd.... Is... Done!!!!!!!

# But not really because those are lines and we actually need polygons...
#  Its way easier, they are all there... ¬ ¬ It does take for ever, thou so projection issues should be deal with in the line version. But maybe the line fizes cuz they are polygons? We will see...

North_America_EEZ <- eez_world_sf %>% 
  filter(Territory1 %in% Countries) %>% 
  st_transform(crs = 3832) #3832


# Let's try this... I think It will take 4-ever

# Shapefile_Map <- ggplot() +
#   geom_sf(data = North_America_Land) +
#   geom_sf(data = North_America_EEZ)
# 
#   # 6.26pm and 18:34 on carmelia
#   ggsave("Shapefile_Map.png",
#          plot = last_plot(),
#          width = 12,
#          height = 10,
#          units = "in"
#          )


### Explorting new dataset, hopefully is faster... ####

path_eez<- ("~/Documents/R CODE/Spatial_Analysis/Data/Intersect_EEZ_IHO_v3")
#The File
# fnam_eez <- "eez_boundaries_v10.shp" # Just lines
fnam_eez <- "EEZ_IHO_v3.shp" # Actual shapefiles (takes 4-ever, for ever ever? fooor eever eeever!?)

new_eez_sf <- st_read(dsn = path_eez, 
layer = file_path_sans_ext(fnam_eez)
) #%>% 
  # st_transform(crs = 4326) #3832 centered

# See map
# ggplot(new_eez_sf) +
#   geom_sf()

# head(new_eez_sf)

# new_eez_sf %>% 
#   filter(Territory1 == "Canada",
#     Longitude > -100) %>%
  # tail()
  # filter(Territory1 == "Canada",
         # IHO_Sea %in% c("North Atlantic Ocean")) %>% 
  # head()
  # ggplot() +
  # geom_sf()


# Canada Pacific (Half arctic sea) <- Longitude < -100

Canada_shp <- new_eez_sf %>% 
  filter(Territory1 == "Canada") %>% 
  mutate(Basin = ifelse(Longitude > -100, "Can E","Can W")) %>% 
  select(Territory1,
         Basin,
         geometry)

# head(Canada_shp) yes! 


# US Pacific (Half arctic sea) <- Longitude < -100

US_shp <- new_eez_sf %>% 
  filter(Territory1 == "United States") %>% 
  mutate(Basin = ifelse(Longitude > -100, "USA E","USA W")) %>% 
  select(Territory1,
         Basin,
         geometry)

# Alaska

Alaska_shp <- new_eez_sf %>% 
  filter(Territory1 == "Alaska") %>% 
    mutate(Basin = "Alaska") %>% 
  select(Territory1,
         Basin,
         geometry)


# Greenland

# Greenland_shp <- 
  # new_eez_sf %>% 
  # filter(Territory1 == "Greenland") %>% 
  #   mutate(Basin = "Alaska") %>% 
  # select(Territory1,
  #        Basin,
  #        geometry)
  
  North_America_EEZ_sp <- Alaska_shp %>% 
    rbind(US_shp,Canada_shp)
  

DBEM data analysis for NAFO


Areas <- c(
  "Canada (Arctic)",
  "Canada (East Coast)",
  "Canada (Pacific)",
  "USA (East Coast)",
  "USA (West Coast)",
  "USA (Alaska, Arctic)",
  "USA (Alaska, Subarctic)"
)

RCP = c("GFDL26F1","IPSL26F1","MPI26F1") #Low RCP

Selected_Areas <- EEZIDs_List %>% 
  filter(Name %in% Areas)

# DBEM_Corrected %>% 
#   filter(Treaty == "NAFO") %>% 
#   View()


Overall <- DBEM_Corrected %>%
  left_join(EEZ_CellID,
            by = "INDEX") %>% 
  # head() %>%
  filter(EEZID %in% Selected_Areas$EEZID) %>% 
  mutate( # uncomment to get overall by nation
    Nation = ifelse(EEZID >= 958, "Alaska",
                    ifelse(EEZID == 925,"Can W",
                           ifelse(EEZID == 851, "USA E",
                                  ifelse( EEZID== 848, "USA W","Can E"))
                    )),
    RCP = ifelse(Model %in% RCP,"Low","High"),
    Basin = ifelse(Nation %in% c("USA E","Can E"),"Atlantic","Pacific")
  ) %>% 
  # View()
  group_by(Model,Nation,RCP,Basin,Species) %>%
  summarise_if(is.numeric,sum,na.rm=T) %>%
  group_by(Nation,RCP,Basin,Species) %>% 
  summarise_at(vars(`2005`:`2099`),mean,na.rm=T) %>%  #Average of models
  gather("Year","MCP",`2005`:`2099`)

# Average of each Species MCP today

Today_Mean <- Overall %>% 
  filter(Year >= 2005 & Year <= 2014) %>% 
  group_by(Nation,RCP,Species) %>% 
  summarise(Today_MCP = mean(MCP))

# View(Today_Mean)

#### Change in proportions ####

# Average of each Species MCP today in both nations
Today_Total_MCP <- Overall %>% 
  filter(Year >= 2005 & Year <= 2014) %>% 
  group_by(RCP,Nation,Basin, Species) %>% 
  summarise(Mean_MCP = mean(MCP)) %>% 
  group_by(RCP,Basin,Species) %>% 
  summarise(Total_MCP = sum(Mean_MCP))


Today_Proportion <- Overall %>%
  # mutate(Basin = ifelse(Nation %in% c("USA E","Can E"),"Atlantic","Pacific")) %>% 
  filter(Year >= 2005 & Year <= 2014) %>% 
  group_by(Nation,RCP,Basin,Species) %>% 
  summarise(Today_MCP = mean(MCP)) %>% 
  left_join(Today_Total_MCP,
            by = c("RCP","Basin","Species")
  ) %>% 
  mutate(
    Prop_Today = (Today_MCP/Total_MCP)*100
  ) %>% 
  select(Nation,RCP,Basin,Prop_Today,Species)

### Check point

# Today_Proportion %>% 
#   group_by(RCP,Basin) %>% 
#   summarise(sum(Prop_Today))

### Proportion change ##

Future_Totals <- Overall %>% 
  filter(Year >= 2046) %>% 
  mutate(#Basin = ifelse(Nation %in% c("USA E","Can E"),"Atlantic","Pacific"),
         Period = (ifelse(Year >= 2046 & Year <= 2055,"Mid Century","End Century"))
) %>% 
  # filter(Year >= 2046 & Year <= 2055) %>% 
  group_by(RCP,Nation,Basin,Period,Species) %>% 
  summarise(Mean_MCP = mean(MCP)) %>% 
  group_by(RCP,Basin,Period,Species) %>% 
  summarise(Total_MCP_Fut = sum(Mean_MCP))

Result_Table <- Overall %>%
  mutate(#Basin = ifelse(Nation %in% c("USA E","Can E"),"Atlantic","Pacific"),
         Period = ifelse(Year >= 2046 & Year <= 2055,"Mid Century",
                          ifelse(Year >= 2090 & Year <= 2099,"End Century","Other_Years"))
                   ) %>% 
  filter(Period != "Other_Years") %>%
  group_by(Nation,RCP,Basin,Period,Species) %>% 
  summarise(Fut_MCP = mean(MCP)) %>% 
  # View()
  left_join(Future_Totals,
            by = c("RCP","Basin","Period","Species")
  ) %>% 
  mutate(
    Prop_Fut = (Fut_MCP/Total_MCP_Fut)*100
  ) %>% 
  left_join(Today_Proportion,
            by = c("Nation","RCP","Basin","Species")) %>% 
  mutate(Change = Prop_Fut/Prop_Today,
         Percentage_Mid = round(-(1-Change)*100)
  ) %>% 
  View()
  # select(Species,Nation:Period,Percentage_Mid) %>%
  group_by(Nation,RCP,Period) %>%
  summarise(
    Mean_All = mean(Percentage_Mid, na.rm = T),
    sd_All = sd(Percentage_Mid, na.rm = T)
  ) %>%
  View()


Result_Map <- Result_Table  %>% 
  filter(RCP == "High",
         Period == "Mid Century") %>% 
  ungroup() %>% 
  select(
    Basin= Nation,
    Mean_All
    )

  # COnvert DBEM data to a shapefile (points)
  Mid_Century_Plot <- North_America_EEZ_sp %>% 
    left_join(Result_Map,
              by ="Basin") %>% 
    st_transform(crs = 3832)
  
  # head(Mid_Century_Plot)
  # tail(Mid_Century_Plot)
  # unique(Mid_Century_Plot$)
  
  
  #### Map checking #### Works!!!!
  
  Seq <- seq(-12,12,2)
  
  Plot <- ggplot(Mid_Century_Plot) +
    geom_sf(aes(fill = Mean_All,
                colour=Mean_All)) +
    scale_fill_gradient2(
      limits=c(-12,12),
      breaks = Seq ) +
    scale_colour_gradient2(
      limits=c(-12,12),
      breaks = Seq) +
    # geom_sf(data = North_America_Land) +
    # geom_sf(data = North_America_EEZ, colour = "black") +
    ggtheme_map() +
    theme(legend.key = element_rect(size = 4),
      legend.key.width =unit(6,"line"));Plot
    
  # ggsave("Mid_Century.png", #03:24
  #        plot = Plot,
  #        width = 12,
  #        height = 10,
  #        units = "in"
  #        )
  

Chinook Map

# Run function to get all Data
suppressMessages(
  Chinook_Data <- bind_rows(
    lapply(Acronyms$Sheet,get_chinook_data)
  )
) 
NAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercion
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCiMgU2V0IHVwCgpGaXJzdCBtYWtlIHN1cmUgdG8gaW5zdGFsbCBhbmQgbG9hZCBhbGwgcGFja2FnZXMgbmVlZGVkLiBUaGlzIGNodW5rIHdpbGwgYWxzbyBsb2FkIGZ1bmN0aW9ucyByZWxhdGVkIHRvIHRoZSBhbmFseXNpcy4KCmBgYHtyIHNldHVwLCBldmFsPVQsIGVjaG89VCwgd2FybmluZz1GLG1lc3NhZ2U9RiwgcmVzdWx0cz0naGlkZSd9CgoKIyBMb2FkIGxpYnJhcmllcyBhbmQgZnVuY3Rpb25zICMKCmlwYWsgPC0gZnVuY3Rpb24ocGtnKXsKICBuZXcucGtnIDwtIHBrZ1shKHBrZyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywgIlBhY2thZ2UiXSldCiAgaWYgKGxlbmd0aChuZXcucGtnKSkgCiAgICBpbnN0YWxsLnBhY2thZ2VzKG5ldy5wa2csIGRlcGVuZGVuY2llcyA9IFRSVUUpCiAgc2FwcGx5KHBrZywgcmVxdWlyZSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQp9CgoKIyMjIyBMaWJyYXJ5ICMjIyMKcGFja2FnZXMgPC0gYygKICAicmVhZHhsIiwgIyBSZWFkIGRhdGFmcmFtZSBpbiBleGNlbCBmb3JtYXQKICAiZHBseXIiLCAjIERhdGEgbWFuaXB1bGF0aW9uCiAgInRpZHlyIiwgIyBEYXRhIG1hbmlwdWxhdGlvbgogICJnZ3Bsb3QyIiwgI05pY2UgZ3JwYWhzIGFuZCBzcGF0aWFsIGFuYWx5c2lzCiAgIyAiY293cGxvdCIsCiAgIyAiZm9yY2FzdHMiLAogICMgInJnZGFsIiwKICAjICJSQ29sb3JCcmV3ZXIiLAogICJrbml0ciIsCiAgImthYmxlRXh0cmEiLAogICJkYXRhLnRhYmxlIiwgIyBGYXN0IHJlYWQgZGF0YQogICMgImdncmVwZWwiLAogICMgImdyaWRFeHRyYSIsCiAgIyAiZ2dtYXAiLAogICMgInJnZW9zIiwKICAic2YiLAogICMgInNwIiwKICAjICJyZ2RhbCIsICNTcGF0aWFsIGFuYWx5c2lzCiAgInRvb2xzIiwgI1NwYXRpYWwgYW5hbHlzaXMKICAjICJwbmciLCAjIEZvciByZWFkaW5nIHBsb3RzIGluIGNodW5rIGNvZGVzCiAgIyAiZ3JpZCIgIyBGb3IgcmVhZGluZyBwbG90cyBpbiBjaHVuayBjb2RlcwogICJzdHJpbmdyIiAjIEZvciBmaWx0ZXJpbmcgYnkgc3RyaW5nCikKCmlwYWsocGFja2FnZXMpCgojI19fX19fX19fX19fX19fX19fX0ZVTkNUSU9OUyBfX19fX19fX19fX19fX19fX19fX19fX19fIyMKCiMgU3RhbmRhcml6YXRpb24gb2YgcGxvdHMKZ2d0aGVtZV9wbG90IDwtIGZ1bmN0aW9uKCkgewogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEpLCBoanVzdCA9IDAsIGZhY2UgPSAiYm9sZCIpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAjIHN0cmlwLnRleHQgICAgICAgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSwgZmFjZSA9ICJpdGFsaWMiKSwKICAgIHBhbmVsLmJvcmRlciAgICAgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gInBsYWluIiksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSBOQSwgZmlsbCA9IE5BKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiAgPSAidG9wIiwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgsIGNvbG91ciA9ICJkYXJrZ3JleSIpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpCiAgKQp9CgojIFN0YW5kYXJpemF0aW9uIG9mIG1hcHMKZ2d0aGVtZV9tYXAgPC0gZnVuY3Rpb24oYmFzZV9zaXplID0gOSwgUmVnaW9uID0gIk5BIikgewogIAogIHRoZW1lKHRleHQgICAgICAgICAgICAgPSBlbGVtZW50X3RleHQoI2ZhbWlseSA9ICJIZWx2ZXRpY2EiLAogICAgY29sb3IgPSAiZ3JheTMwIiwgc2l6ZSA9IGJhc2Vfc2l6ZSksCiAgICBwbG90LnRpdGxlICAgICAgID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMS4yNSksIGhqdXN0ID0gMCwgZmFjZSA9ICJib2xkIiksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyICAgICA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gInRyYW5zcGFyZW50IiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID1lbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpLAogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgY29sb3VyID0gImJsYWNrIixmYWNlPSAiYm9sZC5pdGFsaWMiLCBhbmdsZSA9IDApLAogICAgYXhpcy5saW5lICAgICAgICA9IGVsZW1lbnRfYmxhbmsoKSwgIyBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXkzMCIsIHNpemUgPSAuNSkpCiAgICBheGlzLnRpY2tzICAgICAgID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0ICAgICAgICA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUgICAgICAgPSBlbGVtZW50X2JsYW5rKCksCiAgICAjIGxlZ2VuZC5rZXkgICAgICAgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTkEsIGZpbGwgPSBOQSwgc2l6ZSA9IDQpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIjLAogICAgIyBsZWdlbmQua2V5LndpZHRoID11bml0KDYsImxpbmUiKQogICkKfQoKYGBgCgojIE92ZXJhbGwgTWFwCgojIyBMb2FkaW5nIERCRU0gZGF0YQoKYGBge3IgTG9hZF9EQkVNX0RhdGEsIGVjaG8gPSBULCBldmFsID0gVCwgcmVzdWx0cz0naGlkZScsIHdhcm5pbmc9RixtZXNzYWdlPUZ9CgojIExpc3Qgb2YgREJFTSBJTkRFWCB3aXRoaW4gdGhlIEVFWgojRGF0YSBwcm92aWRlZCBieSBWaWNraSBMYW0KRUVaSURzX0xpc3QgPC0gcmVhZF9leGNlbCgifi9Eb2N1bWVudHMvVUJDL09jZWFuc19Qcm9qZWN0L0Rpc3RyaWJ1dGlvbi9CeSBDZWxsL0NlbGxfRGF0YS9VcGRhdGVkX0VFWkxpc3RfMTdKdW5lMjAxNi54bHN4IikKRUVaX0NlbGxJRCA8LSByZWFkX2V4Y2VsKCJ+L0RvY3VtZW50cy9VQkMvT2NlYW5zX1Byb2plY3QvRGlzdHJpYnV0aW9uL0J5IENlbGwvQ2VsbF9EYXRhL0VFWl9DZWxsSUQueGxzeCIpCgpjb2xuYW1lcyhFRVpfQ2VsbElEKSA8LSBjKCJFRVpJRCIsIklOREVYIikKCiMgREJFTSBDb29yZGluYXRlIHN5c3RlbQpDb29yIDwtIGZyZWFkKCJ+L0RvY3VtZW50cy9VQkMvT2NlYW5zX1Byb2plY3QvRGlzdHJpYnV0aW9uL0RCRU0vRGF0YS9Mb25fTGF0X0RCRU0udHh0IixoZWFkZXIgPSBGQUxTRSkKY29sbmFtZXMoQ29vcikgPC0gYygiSU5ERVgiLCJMb25naXR1ZGUiLCJMYXRpdHVkZSIpCgojIEV4cGxvaXRlZCBTcGVjaWVzIGZvciBjb21tb24gbmFtZXMKIyBleHBsb2l0ZWRfc3BlY2llc19saXN0IDwtIGZyZWFkKCIvVm9sdW1lcy9EQVRBL1BST0pFQ1RJT04gZXhwbG9pdGVkIHNwZWNpZXMgRU5NL2V4cGxvaXRlZF9zcGVjaWVzX2xpc3QuY3N2IikgJT4lIAojICAgc2VsZWN0KFNwZWNpZXMgPVRheG9uTmFtZSwKIyAgICAgICAgICBDb21tb25OYW1lKQoKIyBGcm9tICgvVXNlcnMvanBhbGFjaW9zL0RvY3VtZW50cy9VQkMvT2NlYW5zX1Byb2plY3QvRGlzdHJpYnV0aW9uL0J5IENlbGwvQnlfQ2VsbF9BbmFseXNpcy5SbWQpCkRCRU1fUmVzdWx0cyA8LSBkYXRhLnRhYmxlOjpmcmVhZCgifi9Eb2N1bWVudHMvVUJDL09jZWFuc19Qcm9qZWN0L01hbnVzY3JpcHQvRGF0YS9SYXdfRGF0YS5jc3YiKQoKIyMjIyBBbGwgTm9ydGggQW1lcmljYSAjIyMjCgpFRVpzIDwtIGMoCiAgIkNhbmFkYSAoUGFjaWZpYykiLAogICJVU0EgKFdlc3QgQ29hc3QpIiwKICAiVVNBIChBbGFza2EsIEFyY3RpYykiLAogICJVU0EgKEFsYXNrYSwgU3ViYXJjdGljKSIsCiAgIyAiQ2FuYWRhIChBcmN0aWMpIiwKICAiQ2FuYWRhIChFYXN0IENvYXN0KSIsCiAgIlVTQSAoRWFzdCBDb2FzdCkiCikKCkFsbF9FRVpzIDwtIEVFWklEc19MaXN0ICU+JSAKICBmaWx0ZXIoTmFtZSAlaW4lIEVFWnMpICU+JSAKICBsZWZ0X2pvaW4oRUVaX0NlbGxJRCwKICAgICAgICAgICAgYnkgPSAiRUVaSUQiKQoKbmFtZXMoQWxsX0VFWnMpWzNdIDwtICJJTkRFWCIKCmBgYAoKCiMjIERhdGEgV3JhbmdsaW5nCgogLSBXZSBuZWVkIHRvIG1ha2Ugc29tZSBjb3JyZWN0aW9ucyB0byB0aGUgc2hhcGVmaWxlIHRvIHByb2plY3QgZXZlcnl0aGluZyB3aXRoIE5vcnRoIEFtZXJpY2EgY2VudGVyZWQuIEJhc2ljYWxseSBzb2x2ZSBmb3IgdGhlIGZhY3QgdGhhdCBBbGFza2EgaXMgaW4gdGhlIG90aGVyIHNpZGUgb2YgdGhlIGdsb2JlIGJlY2F1c2UgdGhlIEVhcnRoIGlzIHJvdW5kLCBzaG9ja2luZyEgCgotIFdlIGFsc28gaGF2ZSB0byBpbmNsdWRlIGEgY29sdW1uIHJlZmVyZW5jaW5nIHRoZSBjb3VudHJ5J3MgRUVaIGZvciB0aGUgYW5hbHlzaXMKCgpgYGB7ciBDb3JyZWN0X0RCRU1fRGF0YSwgZWNobyA9IFQsIGV2YWwgPSBULCB3YXJuaW5nPUYsbWVzc2FnZT1GLCByZXN1bHRzPSdhc2lzJ30KCiMgTEFUIExPTkcgQ29ycmVjdGlvbnMgZm9yIG1hcCBwcm9qZWN0aW9uCgpEQkVNX0NvcnJlY3RlZCA8LSBEQkVNX1Jlc3VsdHMgJT4lIAogIGZpbHRlcihJTkRFWCAlaW4lIEFsbF9FRVpzJElOREVYKSAlPiUgCiAgZmlsdGVyKExvbmdpdHVkZSA+IDApICU+JSAKICBtdXRhdGUoTG9uZ2l0dWRlID0gTG9uZ2l0dWRlIC0gMzYwKQoKREJFTV9Db3JyZWN0ZWQgPC0gREJFTV9SZXN1bHRzICU+JSAKICBmaWx0ZXIoSU5ERVggJWluJSBBbGxfRUVacyRJTkRFWCkgJT4lIAogIGZpbHRlcihMb25naXR1ZGUgPCAwKSAlPiUgCiAgYmluZF9yb3dzKERCRU1fQ29ycmVjdGVkKQoKIyBoZWFkKERCRU1fQ29ycmVjdGVkKQoKIyBKdXN0IGNoZWNraW5nICMjIyMjCgojIERCRU1fQ29ycmVjdGVkICU+JQojICAgZ3JvdXBfYnkoSU5ERVgsIExvbmdpdHVkZSwgTGF0aXR1ZGUpICU+JQojICAgc3VtbWFyaXNlKG4gPW4oKSkgJT4lCiMgICBnZ3Bsb3QoLiwKIyAgICAgICAgICBhZXMoeCA9IExvbmdpdHVkZSwKIyAgICAgICAgICAgICAgeSA9IExhdGl0dWRlLAojICAgICAgICAgICAgICBmaWxsID0gbgojICAgICAgICAgICksCiMgICAgICAgICAgc2l6ZSA9IDAuMDUsCiMgICAgICAgICAgYWxwaGEgPSAwLjUpICsKIyAgIGdlb21fdGlsZSgpICMrCiMgY29vcmRfbWFwKHByb2plY3Rpb24gPSAibWVyY2F0b3IiKQoKCiMjIyBHZXQgcmlkZCBvZiBhbnkgUGFjaWZpYyBTcGVjaWVzIGluIE5BRk8KCk5BRk9fRSA8LSBEQkVNX0NvcnJlY3RlZCAlPiUgCiAgZmlsdGVyKExvbmdpdHVkZSA+PSAtMTAwKQoKUGFjaWZpYyA8LSBEQkVNX0NvcnJlY3RlZCAlPiUgCiAgZmlsdGVyKFRyZWF0eSAhPSAiTkFGTyIpCgpEQkVNX0NvcnJlY3RlZCA8LSBOQUZPX0UgJT4lIAogIGJpbmRfcm93cyhQYWNpZmljKQoKIyB1bmlxdWUoREJFTV9Db3JyZWN0ZWQkU3BlY2llcykKCiMgUmVtb3ZlIHNhbG1vbnMuLi4KClNhbG1vbnMgPC0gYygiT25jb3JoeW5jaHVzIGtldGEiLCJPbmNvcmh5bmNodXMga2lzdXRjaCIsIk9uY29yaHluY2h1cyBuZXJrYSIsIk9uY29yaHluY2h1cyB0c2hhd3l0c2NoYSIsIk9uY29yaHluY2h1cyBnb3JidXNjaGEiLCJTYWxtbyBzYWxhciIpCgpDaGFwdGVyX0RhdGEgPC0gREJFTV9Db3JyZWN0ZWQgJT4lCiAgIyBmaWx0ZXIoIVNwZWNpZXMgJWluJSBTYWxtb25zKSAlPiUgIyBSZW9tdmUgb3Igb25seSBhbmFseXNpcyB3aXRoIHNhbG1vbnMKICBsZWZ0X2pvaW4oQWxsX0VFWnMsCiAgICAgICAgICAgIGJ5ID0iSU5ERVgiKSAlPiUgCiAgc2VsZWN0KC1FRVpJRCkKCiMgU2hvdyB0YWJsZSB3aXRoIHNwZWNpZXMgCgojIG5hbWVzKENoYXB0ZXJfRGF0YSkKIyBoZWFkKENoYXB0ZXJfRGF0YSkKCkNoYXB0ZXJfRGF0YSAlPiUgCiAgZ3JvdXBfYnkoU3BlY2llcywgVHJlYXR5KSAlPiUgCiAgc3VtbWFyaXNlKG49bigpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBsZWZ0X2pvaW4oZXhwbG9pdGVkX3NwZWNpZXNfbGlzdCwKICAgICAgICAgICAgYnkgPSAiU3BlY2llcyIpICU+JSAKICBhcnJhbmdlKFRyZWF0eSkgJT4lIAogIHNlbGVjdChTcGVjaWVzLENvbW1vbk5hbWUsVHJlYXR5KSAlPiUgCiAga2FibGUoKQoKYGBgCgojIyBMb2FkaW5nIFNwYXRpYWwgZGF0YQoKYGBge3IsIExvYWRfU3BhdGlhbF9EYXRhLCBldmFsID0gVCwgZWNobyA9IFR9CgojIENvdW50cmllcyBpbmNsdWRlZCAKCkNvdW50cmllcyA8LSBjKCJDYW5hZGEiLCJVbml0ZWQgU3RhdGVzIiwiQWxhc2thIikKCgojIFdvcmxkIHNoYXBlZmlsZQpwYXRoX3dvcmxkIDwtICJ+L0RvY3VtZW50cy9SIENvZGUvU3BhdGlhbF9BbmFseXNpcy9EYXRhL1RNX1dPUkxEX0JPUkRFUlMtMC4zIgpmaWxlX25hbWUgPC0gIlRNX1dPUkxEX0JPUkRFUlMiCgpXb3JsZF9MYW5kX3NmIDwtIHN0X3JlYWQoZHNuID0gcGF0aF93b3JsZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBsYXllciA9IGZpbGVfcGF0aF9zYW5zX2V4dChmaWxlX25hbWUpCikgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSAzODMyKQoKTm9ydGhfQW1lcmljYV9MYW5kIDwtIFdvcmxkX0xhbmRfc2YgJT4lIAogIGZpbHRlcihOQU1FICVpbiUgQ291bnRyaWVzKQoKIyBDaGVja3BvaW50IAojIHVuaXF1ZShOb3J0aF9BbWVyaWNhX0xhbmQkTkFNRSkgWzFdIENhbmFkYSAgICAgICAgR3JlZW5sYW5kICAgICBVbml0ZWQgU3RhdGVzCgojIE1hcCBpdD8gWXVwIQojIGdncGxvdChOb3J0aF9BbWVyaWNhX0xhbmQpICsKIyBnZW9tX3NmKCkKCiMgRUVacyBzaGFwZWZpbGUgIyMjIwoKcGF0aF9lZXo8LSAoIn4vRG9jdW1lbnRzL1IgQ29kZS9TcGF0aWFsX0FuYWx5c2lzL0RhdGEvV29ybGRfRUVaX3YxMF8yMDE4IikKI1RoZSBGaWxlCmZuYW1fZWV6IDwtICJlZXpfYm91bmRhcmllc192MTAuc2hwIiAjIEp1c3QgbGluZXMKIyBmbmFtX2VleiA8LSAiZWV6X3YxMC5zaHAiICMgQWN0dWFsIHNoYXBlZmlsZXMgKHRha2VzIDQtZXZlciwgZm9yIGV2ZXIgZXZlcj8gZm9vb3IgZWV2ZXIgZWVldmVyIT8pCgplZXpfd29ybGRfc2YgPC0gc3RfcmVhZChkc24gPSBwYXRoX2VleiwgCmxheWVyID0gZmlsZV9wYXRoX3NhbnNfZXh0KGZuYW1fZWV6KQopICU+JSAKICBzdF90cmFuc2Zvcm0oY3JzID0gNDMyNikgIzM4MzIgY2VudGVyZWQKCiMgaGVhZChlZXpfd29ybGRfc2YpCgojQ2hlY2twb2ludCAgCiMgdW5pcXVlKGVlel93b3JsZF9zZiRUZXJyaXRvcnkxKSAKCiMgTm9ydGhfQW1lcmljYV9FRVogPC0gZWV6X3dvcmxkX3NmICU+JSAKIyAgIGZpbHRlcihUZXJyaXRvcnkxICVpbiUgQ291bnRyaWVzKSAlPiUgCiMgICBzdF90cmFuc2Zvcm0oY3JzID0gNDMyNikKCiNDaGVja3BvaW50CiMgdW5pcXVlKE5vcnRoX0FtZXJpY2FfRUVaJFRlcnJpdG9yeTEpCiMgTWFwIGl0PyAKIyBnZ3Bsb3QoTm9ydGhfQW1lcmljYV9FRVopICsKIyAgIGdlb21fc2YoKQojIE5vcGUsIEFsYXNrYSBpcyBub3Qgc2hvd2luZyB1cC4gTmVpdGhlciBFYXN0IEdyZWVubGFuZAoKIyBHcmVlbmxhbmQgU2hhcGVmaWxlIEJ1ZyAjIyMjCiMgRmlyc3QgbGV0cyBnZXQgYWxsIG9mIGdyZWVuYWxuZCBpbiB0aGUgbWFwLi4uIAojIAojIGVlel93b3JsZF9zZiAlPiUKIyAgIGZpbHRlcihzdHJfZGV0ZWN0KFRlcnJpdG9yeTEsIkNhbmFkYSIpKSAlPiUKIyAgICMgbXV0YXRlKEJhc2luID0gaWZlbHNlKCB4XzEgPj0gLTEwMCwgIkF0bGFudGljIiwiUGFjaWZpYyIpKSAlPiUKIyAgIGhlYWQoKQojICAgZ2dwbG90KCkgKwojICAgIyBnZW9tX3NmKGFlcyhmaWxsID0gQmFzaW4pKQojICAgZ2VvbV9zZigpCiMgCiMgCiMgCiMgIyBUaGUgY2h1bmsgbWlzc2luZyBpcyBmcm9tIEljZWxhbmQKIyBJY2VsYW5kIDwtICBlZXpfd29ybGRfc2YgJT4lIAojICAgIyBncm91cF9ieShUZXJyaXRvcnkxKSAlPiUgCiMgICAjIHN1bW1hcmlzZShuKCkpICU+JSAKIyAgICMgZmlsdGVyKHN0cl9kZXRlY3QoVGVycml0b3J5MSwiSWNlbGFuZCIpKSAjICU+JSAKIyAgIGZpbHRlcihMaW5lX0lEID09MTM1KQojICAgIyBnZ3Bsb3QoKSArCiMgICAjIGdlb21fc2YoKQojIAojIGVlel93b3JsZF9zZiAlPiUKIyAgIGZpbHRlcihzdHJfZGV0ZWN0KFRlcnJpdG9yeTEsIkdyZWVubGFuZCIpIHwKIyAgICAgICAgICBMaW5lX0lEID09IDEzNSkgJT4lICMgSW5jbHVkZSB0aGlzIGluIGZpbmFsIG1hcCBwbG90CiMgICBnZ3Bsb3QoKSArCiMgICBnZW9tX3NmKCkgIysKIyAgICMgZ2VvbV9zZihkYXRhID0gSWNlbGFuZCkKIyAKIyAjIEFsYXNrYSBTaGFwZWZpbGUgQnVnICMjIyMKIyBlZXpfd29ybGRfc2YgJT4lIAojICAgZmlsdGVyKFRlcnJpdG9yeTEgJWluJSBDb3VudHJpZXMpICU+JSAKIyAgIHN0X3RyYW5zZm9ybShjcnMgPSAzODMyKSAlPiUgCiMgICBnZ3Bsb3QoKSArCiMgICBnZW9tX3NmKCkKIyAgIAojICMgVGhlIGNodW5rIG1pc3NpbmcgaXMgZnJvbSBSdXNzaWEKIyBlZXpfd29ybGRfc2YgJT4lCiMgICBmaWx0ZXIoc3RyX2RldGVjdChUZXJyaXRvcnkxLCJBbGFza2EiKSB8CiMgICAgICAgICAgICBNUkdJRF9UZXIyID09IDg2ODQpICU+JSAjIFRoaXMgaW5jbHVkZXMgUnVzc2lhIHNpZGUgKEluY2x1ZGUgaW4gZmluYWwgcGxvdCkKIyAgIHN0X3RyYW5zZm9ybShjcnMgPSAzODMyKSAlPiUKIyAgICMgVmlldygpCiMgICBnZ3Bsb3QoKSArCiMgICBnZW9tX3NmKGFlcyhjb2w9TGluZV90eXBlKSkKIyAKIyAKIyAjIFNvdXRoIFVTIChBdGxhbnRpYykgU2hhcGVmaWxlIEJ1ZyAjIyMjCiMgCiMgIyBUaGUgY2h1bmsgbWlzc2luZyBpcyBmcm9tIC4uLiBNZXhpY28gYW5kIEN1YmE/Li4uIGFuZCBCYWhhbWFzLiBOb3BlLCBqdXN0IE1leGljbwojIGVlel93b3JsZF9zZiAlPiUKIyAgICMgZmlsdGVyKHN0cl9kZXRlY3QoVGVycml0b3J5MSJVbml0ZWQgU3RhdGVzIikpICU+JSAKIyAgIGZpbHRlcihUZXJyaXRvcnkxICVpbiUgYyAoIlVuaXRlZCBTdGF0ZXMiLCAiTWV4aWNvIiwgIkN1YmEiLCJCYWhhbWFzIikpCiMgCiMgCiMgIyMjIE1leGljbyBGaXJzdCAoVGFodCdzIGl0ISApCiMgCiMgZWV6X3dvcmxkX3NmICU+JQojICAgIyBmaWx0ZXIoc3RyX2RldGVjdChUZXJyaXRvcnkxIlVuaXRlZCBTdGF0ZXMiKSkgJT4lIAojICAgZmlsdGVyKFRlcnJpdG9yeTEgJWluJSBjICgiVW5pdGVkIFN0YXRlcyIpIHwKIyAgICAgICAgICBNUkdJRF9UZXIyID09IDIyMDQpICU+JSAgIyBJbmxjdWRlIHRoaXMgZm9yIE1leGljbydzIHNvdXRoZXJuIGJvdW5kYXJ5CiMgICAjIHN0X3RyYW5zZm9ybShjcnMgPSAzODMyKSAlPiUKIyAgICMgVmlldygpCiMgICBnZ3Bsb3QoKSArCiMgICBnZW9tX3NmKGFlcyhjb2w9TGluZV90eXBlKSkKCgojIyMjIFRoZSBBY3R1YWwgTWFwICMjIyMKCiMgV2UgbmVlZCB0byBpbmxjdWRlIGFsYXNrYSBpbiBoZXJlCkNvdW50cmllcyA8LSBjKCJDYW5hZGEiLCJVbml0ZWQgU3RhdGVzIiwgIkFsYXNrYSIpCgojIEhlcmUgd2UgZ28gYWdhaW4KTm9ydGhfQW1lcmljYV9FRVogPC0gZWV6X3dvcmxkX3NmICU+JSAKICBmaWx0ZXIoVGVycml0b3J5MSAlaW4lIENvdW50cmllcyB8CiAgICAgICAgICAgTGluZV9JRCA9PSAxMzUgfCAjICMgTGluZSBtaXNzaW5nIGZyb20gR3JlZW5sYW5kIChJY2VsYW5kKQogICAgICAgICBNUkdJRF9UZXIyID09IDg2ODQgfAogICAgICAgICAgIE1SR0lEX1RlcjIgPT0gMjIwNCkgJT4lICAjIExpbmUgbWlzc2luZyBmcm9tIEFsYXNrYSAoUnVzc2lhKQogIHN0X3RyYW5zZm9ybShjcnMgPSAzODMyKQoKIyBGaW5hbGwgY2hlY2shIAojIGdncGxvdChOb3J0aF9BbWVyaWNhX0VFWikgKwojICAgZ2VvbV9zZigpCgojIFl1cCEgCgojIE1hcCBib3RoIHNoYXBlZmlsZXMgdG8gc2VlIGhvdyBpdCBsb29rcwoKIyBnZ3Bsb3QoKSArCiMgICBnZW9tX3NmKGRhdGEgPSBOb3J0aF9BbWVyaWNhX0xhbmQpICsKIyAgIGdlb21fc2YoZGF0YSA9IE5vcnRoX0FtZXJpY2FfRUVaKQoKIyBBbm5ubmQuLi4uIElzLi4uIERvbmUhISEhISEhCgojIEJ1dCBub3QgcmVhbGx5IGJlY2F1c2UgdGhvc2UgYXJlIGxpbmVzIGFuZCB3ZSBhY3R1YWxseSBuZWVkIHBvbHlnb25zLi4uCiMgIEl0cyB3YXkgZWFzaWVyLCB0aGV5IGFyZSBhbGwgdGhlcmUuLi4gwqwgwqwgSXQgZG9lcyB0YWtlIGZvciBldmVyLCB0aG91IHNvIHByb2plY3Rpb24gaXNzdWVzIHNob3VsZCBiZSBkZWFsIHdpdGggaW4gdGhlIGxpbmUgdmVyc2lvbi4gQnV0IG1heWJlIHRoZSBsaW5lIGZpemVzIGN1eiB0aGV5IGFyZSBwb2x5Z29ucz8gV2Ugd2lsbCBzZWUuLi4KCk5vcnRoX0FtZXJpY2FfRUVaIDwtIGVlel93b3JsZF9zZiAlPiUgCiAgZmlsdGVyKFRlcnJpdG9yeTEgJWluJSBDb3VudHJpZXMpICU+JSAKICBzdF90cmFuc2Zvcm0oY3JzID0gMzgzMikgIzM4MzIKCgojIExldCdzIHRyeSB0aGlzLi4uIEkgdGhpbmsgSXQgd2lsbCB0YWtlIDQtZXZlcgoKIyBTaGFwZWZpbGVfTWFwIDwtIGdncGxvdCgpICsKIyAgIGdlb21fc2YoZGF0YSA9IE5vcnRoX0FtZXJpY2FfTGFuZCkgKwojICAgZ2VvbV9zZihkYXRhID0gTm9ydGhfQW1lcmljYV9FRVopCiMgCiMgICAjIDYuMjZwbSBhbmQgMTg6MzQgb24gY2FybWVsaWEKIyAgIGdnc2F2ZSgiU2hhcGVmaWxlX01hcC5wbmciLAojICAgICAgICAgIHBsb3QgPSBsYXN0X3Bsb3QoKSwKIyAgICAgICAgICB3aWR0aCA9IDEyLAojICAgICAgICAgIGhlaWdodCA9IDEwLAojICAgICAgICAgIHVuaXRzID0gImluIgojICAgICAgICAgICkKCgojIyMgRXhwbG9ydGluZyBuZXcgZGF0YXNldCwgaG9wZWZ1bGx5IGlzIGZhc3Rlci4uLiAjIyMjCgpwYXRoX2VlejwtICgifi9Eb2N1bWVudHMvUiBDT0RFL1NwYXRpYWxfQW5hbHlzaXMvRGF0YS9JbnRlcnNlY3RfRUVaX0lIT192MyIpCiNUaGUgRmlsZQojIGZuYW1fZWV6IDwtICJlZXpfYm91bmRhcmllc192MTAuc2hwIiAjIEp1c3QgbGluZXMKZm5hbV9lZXogPC0gIkVFWl9JSE9fdjMuc2hwIiAjIEFjdHVhbCBzaGFwZWZpbGVzICh0YWtlcyA0LWV2ZXIsIGZvciBldmVyIGV2ZXI/IGZvb29yIGVldmVyIGVlZXZlciE/KQoKbmV3X2Vlel9zZiA8LSBzdF9yZWFkKGRzbiA9IHBhdGhfZWV6LCAKbGF5ZXIgPSBmaWxlX3BhdGhfc2Fuc19leHQoZm5hbV9lZXopCikgIyU+JSAKICAjIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAjMzgzMiBjZW50ZXJlZAoKIyBTZWUgbWFwCiMgZ2dwbG90KG5ld19lZXpfc2YpICsKIyAgIGdlb21fc2YoKQoKIyBoZWFkKG5ld19lZXpfc2YpCgojIG5ld19lZXpfc2YgJT4lIAojICAgZmlsdGVyKFRlcnJpdG9yeTEgPT0gIkNhbmFkYSIsCiMgICAgIExvbmdpdHVkZSA+IC0xMDApICU+JQogICMgdGFpbCgpCiAgIyBmaWx0ZXIoVGVycml0b3J5MSA9PSAiQ2FuYWRhIiwKICAgICAgICAgIyBJSE9fU2VhICVpbiUgYygiTm9ydGggQXRsYW50aWMgT2NlYW4iKSkgJT4lIAogICMgaGVhZCgpCiAgIyBnZ3Bsb3QoKSArCiAgIyBnZW9tX3NmKCkKCgojIENhbmFkYSBQYWNpZmljIChIYWxmIGFyY3RpYyBzZWEpIDwtIExvbmdpdHVkZSA8IC0xMDAKCkNhbmFkYV9zaHAgPC0gbmV3X2Vlel9zZiAlPiUgCiAgZmlsdGVyKFRlcnJpdG9yeTEgPT0gIkNhbmFkYSIpICU+JSAKICBtdXRhdGUoQmFzaW4gPSBpZmVsc2UoTG9uZ2l0dWRlID4gLTEwMCwgIkNhbiBFIiwiQ2FuIFciKSkgJT4lIAogIHNlbGVjdChUZXJyaXRvcnkxLAogICAgICAgICBCYXNpbiwKICAgICAgICAgZ2VvbWV0cnkpCgojIGhlYWQoQ2FuYWRhX3NocCkgeWVzISAKCgojIFVTIFBhY2lmaWMgKEhhbGYgYXJjdGljIHNlYSkgPC0gTG9uZ2l0dWRlIDwgLTEwMAoKVVNfc2hwIDwtIG5ld19lZXpfc2YgJT4lIAogIGZpbHRlcihUZXJyaXRvcnkxID09ICJVbml0ZWQgU3RhdGVzIikgJT4lIAogIG11dGF0ZShCYXNpbiA9IGlmZWxzZShMb25naXR1ZGUgPiAtMTAwLCAiVVNBIEUiLCJVU0EgVyIpKSAlPiUgCiAgc2VsZWN0KFRlcnJpdG9yeTEsCiAgICAgICAgIEJhc2luLAogICAgICAgICBnZW9tZXRyeSkKCiMgQWxhc2thCgpBbGFza2Ffc2hwIDwtIG5ld19lZXpfc2YgJT4lIAogIGZpbHRlcihUZXJyaXRvcnkxID09ICJBbGFza2EiKSAlPiUgCiAgICBtdXRhdGUoQmFzaW4gPSAiQWxhc2thIikgJT4lIAogIHNlbGVjdChUZXJyaXRvcnkxLAogICAgICAgICBCYXNpbiwKICAgICAgICAgZ2VvbWV0cnkpCgoKIyBHcmVlbmxhbmQKCiMgR3JlZW5sYW5kX3NocCA8LSAKICAjIG5ld19lZXpfc2YgJT4lIAogICMgZmlsdGVyKFRlcnJpdG9yeTEgPT0gIkdyZWVubGFuZCIpICU+JSAKICAjICAgbXV0YXRlKEJhc2luID0gIkFsYXNrYSIpICU+JSAKICAjIHNlbGVjdChUZXJyaXRvcnkxLAogICMgICAgICAgIEJhc2luLAogICMgICAgICAgIGdlb21ldHJ5KQogIAogIE5vcnRoX0FtZXJpY2FfRUVaX3NwIDwtIEFsYXNrYV9zaHAgJT4lIAogICAgcmJpbmQoVVNfc2hwLENhbmFkYV9zaHApCiAgCmBgYAoKCiMjIERCRU0gZGF0YSBhbmFseXNpcyBmb3IgTkFGTwoKYGBge3IgQ2hhcHRlcl9GdW5jdGlvbiwgZXZhbCA9VCwgZWNobz1UfQoKQXJlYXMgPC0gYygKICAiQ2FuYWRhIChBcmN0aWMpIiwKICAiQ2FuYWRhIChFYXN0IENvYXN0KSIsCiAgIkNhbmFkYSAoUGFjaWZpYykiLAogICJVU0EgKEVhc3QgQ29hc3QpIiwKICAiVVNBIChXZXN0IENvYXN0KSIsCiAgIlVTQSAoQWxhc2thLCBBcmN0aWMpIiwKICAiVVNBIChBbGFza2EsIFN1YmFyY3RpYykiCikKClJDUCA9IGMoIkdGREwyNkYxIiwiSVBTTDI2RjEiLCJNUEkyNkYxIikgI0xvdyBSQ1AKClNlbGVjdGVkX0FyZWFzIDwtIEVFWklEc19MaXN0ICU+JSAKICBmaWx0ZXIoTmFtZSAlaW4lIEFyZWFzKQoKIyBEQkVNX0NvcnJlY3RlZCAlPiUgCiMgICBmaWx0ZXIoVHJlYXR5ID09ICJOQUZPIikgJT4lIAojICAgVmlldygpCgoKT3ZlcmFsbCA8LSBEQkVNX0NvcnJlY3RlZCAlPiUKICBsZWZ0X2pvaW4oRUVaX0NlbGxJRCwKICAgICAgICAgICAgYnkgPSAiSU5ERVgiKSAlPiUgCiAgIyBoZWFkKCkgJT4lCiAgZmlsdGVyKEVFWklEICVpbiUgU2VsZWN0ZWRfQXJlYXMkRUVaSUQpICU+JSAKICBtdXRhdGUoICMgdW5jb21tZW50IHRvIGdldCBvdmVyYWxsIGJ5IG5hdGlvbgogICAgTmF0aW9uID0gaWZlbHNlKEVFWklEID49IDk1OCwgIkFsYXNrYSIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEVFWklEID09IDkyNSwiQ2FuIFciLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRUVaSUQgPT0gODUxLCAiVVNBIEUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCBFRVpJRD09IDg0OCwgIlVTQSBXIiwiQ2FuIEUiKSkKICAgICAgICAgICAgICAgICAgICApKSwKICAgIFJDUCA9IGlmZWxzZShNb2RlbCAlaW4lIFJDUCwiTG93IiwiSGlnaCIpLAogICAgQmFzaW4gPSBpZmVsc2UoTmF0aW9uICVpbiUgYygiVVNBIEUiLCJDYW4gRSIpLCJBdGxhbnRpYyIsIlBhY2lmaWMiKQogICkgJT4lIAogICMgVmlldygpCiAgZ3JvdXBfYnkoTW9kZWwsTmF0aW9uLFJDUCxCYXNpbixTcGVjaWVzKSAlPiUKICBzdW1tYXJpc2VfaWYoaXMubnVtZXJpYyxzdW0sbmEucm09VCkgJT4lCiAgZ3JvdXBfYnkoTmF0aW9uLFJDUCxCYXNpbixTcGVjaWVzKSAlPiUgCiAgc3VtbWFyaXNlX2F0KHZhcnMoYDIwMDVgOmAyMDk5YCksbWVhbixuYS5ybT1UKSAlPiUgICNBdmVyYWdlIG9mIG1vZGVscwogIGdhdGhlcigiWWVhciIsIk1DUCIsYDIwMDVgOmAyMDk5YCkKCiMgQXZlcmFnZSBvZiBlYWNoIFNwZWNpZXMgTUNQIHRvZGF5CgpUb2RheV9NZWFuIDwtIE92ZXJhbGwgJT4lIAogIGZpbHRlcihZZWFyID49IDIwMDUgJiBZZWFyIDw9IDIwMTQpICU+JSAKICBncm91cF9ieShOYXRpb24sUkNQLFNwZWNpZXMpICU+JSAKICBzdW1tYXJpc2UoVG9kYXlfTUNQID0gbWVhbihNQ1ApKQoKIyBWaWV3KFRvZGF5X01lYW4pCgojIyMjIENoYW5nZSBpbiBwcm9wb3J0aW9ucyAjIyMjCgojIEF2ZXJhZ2Ugb2YgZWFjaCBTcGVjaWVzIE1DUCB0b2RheSBpbiBib3RoIG5hdGlvbnMKVG9kYXlfVG90YWxfTUNQIDwtIE92ZXJhbGwgJT4lIAogIGZpbHRlcihZZWFyID49IDIwMDUgJiBZZWFyIDw9IDIwMTQpICU+JSAKICBncm91cF9ieShSQ1AsTmF0aW9uLEJhc2luLCBTcGVjaWVzKSAlPiUgCiAgc3VtbWFyaXNlKE1lYW5fTUNQID0gbWVhbihNQ1ApKSAlPiUgCiAgZ3JvdXBfYnkoUkNQLEJhc2luLFNwZWNpZXMpICU+JSAKICBzdW1tYXJpc2UoVG90YWxfTUNQID0gc3VtKE1lYW5fTUNQKSkKCgpUb2RheV9Qcm9wb3J0aW9uIDwtIE92ZXJhbGwgJT4lCiAgIyBtdXRhdGUoQmFzaW4gPSBpZmVsc2UoTmF0aW9uICVpbiUgYygiVVNBIEUiLCJDYW4gRSIpLCJBdGxhbnRpYyIsIlBhY2lmaWMiKSkgJT4lIAogIGZpbHRlcihZZWFyID49IDIwMDUgJiBZZWFyIDw9IDIwMTQpICU+JSAKICBncm91cF9ieShOYXRpb24sUkNQLEJhc2luLFNwZWNpZXMpICU+JSAKICBzdW1tYXJpc2UoVG9kYXlfTUNQID0gbWVhbihNQ1ApKSAlPiUgCiAgbGVmdF9qb2luKFRvZGF5X1RvdGFsX01DUCwKICAgICAgICAgICAgYnkgPSBjKCJSQ1AiLCJCYXNpbiIsIlNwZWNpZXMiKQogICkgJT4lIAogIG11dGF0ZSgKICAgIFByb3BfVG9kYXkgPSAoVG9kYXlfTUNQL1RvdGFsX01DUCkqMTAwCiAgKSAlPiUgCiAgc2VsZWN0KE5hdGlvbixSQ1AsQmFzaW4sUHJvcF9Ub2RheSxTcGVjaWVzKQoKIyMjIENoZWNrIHBvaW50CgojIFRvZGF5X1Byb3BvcnRpb24gJT4lIAojICAgZ3JvdXBfYnkoUkNQLEJhc2luKSAlPiUgCiMgICBzdW1tYXJpc2Uoc3VtKFByb3BfVG9kYXkpKQoKIyMjIFByb3BvcnRpb24gY2hhbmdlICMjCgpGdXR1cmVfVG90YWxzIDwtIE92ZXJhbGwgJT4lIAogIGZpbHRlcihZZWFyID49IDIwNDYpICU+JSAKICBtdXRhdGUoI0Jhc2luID0gaWZlbHNlKE5hdGlvbiAlaW4lIGMoIlVTQSBFIiwiQ2FuIEUiKSwiQXRsYW50aWMiLCJQYWNpZmljIiksCiAgICAgICAgIFBlcmlvZCA9IChpZmVsc2UoWWVhciA+PSAyMDQ2ICYgWWVhciA8PSAyMDU1LCJNaWQgQ2VudHVyeSIsIkVuZCBDZW50dXJ5IikpCikgJT4lIAogICMgZmlsdGVyKFllYXIgPj0gMjA0NiAmIFllYXIgPD0gMjA1NSkgJT4lIAogIGdyb3VwX2J5KFJDUCxOYXRpb24sQmFzaW4sUGVyaW9kLFNwZWNpZXMpICU+JSAKICBzdW1tYXJpc2UoTWVhbl9NQ1AgPSBtZWFuKE1DUCkpICU+JSAKICBncm91cF9ieShSQ1AsQmFzaW4sUGVyaW9kLFNwZWNpZXMpICU+JSAKICBzdW1tYXJpc2UoVG90YWxfTUNQX0Z1dCA9IHN1bShNZWFuX01DUCkpCgpSZXN1bHRfVGFibGUgPC0gT3ZlcmFsbCAlPiUKICBtdXRhdGUoI0Jhc2luID0gaWZlbHNlKE5hdGlvbiAlaW4lIGMoIlVTQSBFIiwiQ2FuIEUiKSwiQXRsYW50aWMiLCJQYWNpZmljIiksCiAgICAgICAgIFBlcmlvZCA9IGlmZWxzZShZZWFyID49IDIwNDYgJiBZZWFyIDw9IDIwNTUsIk1pZCBDZW50dXJ5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoWWVhciA+PSAyMDkwICYgWWVhciA8PSAyMDk5LCJFbmQgQ2VudHVyeSIsIk90aGVyX1llYXJzIikpCiAgICAgICAgICAgICAgICAgICApICU+JSAKICBmaWx0ZXIoUGVyaW9kICE9ICJPdGhlcl9ZZWFycyIpICU+JQogIGdyb3VwX2J5KE5hdGlvbixSQ1AsQmFzaW4sUGVyaW9kLFNwZWNpZXMpICU+JSAKICBzdW1tYXJpc2UoRnV0X01DUCA9IG1lYW4oTUNQKSkgJT4lIAogICMgVmlldygpCiAgbGVmdF9qb2luKEZ1dHVyZV9Ub3RhbHMsCiAgICAgICAgICAgIGJ5ID0gYygiUkNQIiwiQmFzaW4iLCJQZXJpb2QiLCJTcGVjaWVzIikKICApICU+JSAKICBtdXRhdGUoCiAgICBQcm9wX0Z1dCA9IChGdXRfTUNQL1RvdGFsX01DUF9GdXQpKjEwMAogICkgJT4lIAogIGxlZnRfam9pbihUb2RheV9Qcm9wb3J0aW9uLAogICAgICAgICAgICBieSA9IGMoIk5hdGlvbiIsIlJDUCIsIkJhc2luIiwiU3BlY2llcyIpKSAlPiUgCiAgbXV0YXRlKENoYW5nZSA9IFByb3BfRnV0L1Byb3BfVG9kYXksCiAgICAgICAgIFBlcmNlbnRhZ2VfTWlkID0gcm91bmQoLSgxLUNoYW5nZSkqMTAwKQogICkgJT4lIAogIFZpZXcoKQogICMgc2VsZWN0KFNwZWNpZXMsTmF0aW9uOlBlcmlvZCxQZXJjZW50YWdlX01pZCkgJT4lCiAgZ3JvdXBfYnkoTmF0aW9uLFJDUCxQZXJpb2QpICU+JQogIHN1bW1hcmlzZSgKICAgIE1lYW5fQWxsID0gbWVhbihQZXJjZW50YWdlX01pZCwgbmEucm0gPSBUKSwKICAgIHNkX0FsbCA9IHNkKFBlcmNlbnRhZ2VfTWlkLCBuYS5ybSA9IFQpCiAgKSAlPiUKICBWaWV3KCkKCgpSZXN1bHRfTWFwIDwtIFJlc3VsdF9UYWJsZSAgJT4lIAogIGZpbHRlcihSQ1AgPT0gIkhpZ2giLAogICAgICAgICBQZXJpb2QgPT0gIk1pZCBDZW50dXJ5IikgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KAogICAgQmFzaW49IE5hdGlvbiwKICAgIE1lYW5fQWxsCiAgICApCgogICMgQ09udmVydCBEQkVNIGRhdGEgdG8gYSBzaGFwZWZpbGUgKHBvaW50cykKICBNaWRfQ2VudHVyeV9QbG90IDwtIE5vcnRoX0FtZXJpY2FfRUVaX3NwICU+JSAKICAgIGxlZnRfam9pbihSZXN1bHRfTWFwLAogICAgICAgICAgICAgIGJ5ID0iQmFzaW4iKSAlPiUgCiAgICBzdF90cmFuc2Zvcm0oY3JzID0gMzgzMikKICAKICAjIGhlYWQoTWlkX0NlbnR1cnlfUGxvdCkKICAjIHRhaWwoTWlkX0NlbnR1cnlfUGxvdCkKICAjIHVuaXF1ZShNaWRfQ2VudHVyeV9QbG90JCkKICAKICAKICAjIyMjIE1hcCBjaGVja2luZyAjIyMjIFdvcmtzISEhIQogIAogIFNlcSA8LSBzZXEoLTEyLDEyLDIpCiAgCiAgUGxvdCA8LSBnZ3Bsb3QoTWlkX0NlbnR1cnlfUGxvdCkgKwogICAgZ2VvbV9zZihhZXMoZmlsbCA9IE1lYW5fQWxsLAogICAgICAgICAgICAgICAgY29sb3VyPU1lYW5fQWxsKSkgKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudDIoCiAgICAgIGxpbWl0cz1jKC0xMiwxMiksCiAgICAgIGJyZWFrcyA9IFNlcSApICsKICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudDIoCiAgICAgIGxpbWl0cz1jKC0xMiwxMiksCiAgICAgIGJyZWFrcyA9IFNlcSkgKwogICAgIyBnZW9tX3NmKGRhdGEgPSBOb3J0aF9BbWVyaWNhX0xhbmQpICsKICAgICMgZ2VvbV9zZihkYXRhID0gTm9ydGhfQW1lcmljYV9FRVosIGNvbG91ciA9ICJibGFjayIpICsKICAgIGdndGhlbWVfbWFwKCkgKwogICAgdGhlbWUobGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChzaXplID0gNCksCiAgICAgIGxlZ2VuZC5rZXkud2lkdGggPXVuaXQoNiwibGluZSIpKTtQbG90CiAgICAKICAjIGdnc2F2ZSgiTWlkX0NlbnR1cnkucG5nIiwgIzAzOjI0CiAgIyAgICAgICAgcGxvdCA9IFBsb3QsCiAgIyAgICAgICAgd2lkdGggPSAxMiwKICAjICAgICAgICBoZWlnaHQgPSAxMCwKICAjICAgICAgICB1bml0cyA9ICJpbiIKICAjICAgICAgICApCiAgCgpgYGAKCiMgQ2hpbm9vayBNYXAKCmBgYHtyIGNoaW5vb2tfbWFwLCBldmFsID0gVH0KCiMgbGlicmFyaWVzIG5lZWRlZApsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHJuYXR1cmFsZWFydGgpCmxpYnJhcnkoc2YpCmxpYnJhcnkod2VzYW5kZXJzb24pCnNvdXJjZSgiLi9GdW5jdGlvbnMvZ2V0X2RhdGFfZnguUiIpCgojIyMjIERhdGEgU291cmNlICMjIwojIERhdGEgc2hhcmVkIGJ5IE1hcmsgTWNNaWxsYW4gdGhhbmtzIHRvIENhdGhlcmluZSBNaWNpZWxzZW5zIGZyb20gUFNDCiMgUmVmZXJlbmNlIGluZm8KIyBJZiB0aGUgMjAxOCByZXBvcnQgaXMgbm90IHlldCBwdWJsaXNoZWQgaXQgbWlnaHQgYmUgYmV0dGVyIHRvIHJlZmVycmVyCiMgdGhlIENoaW5vb2sgVGVjaG5pY2FsIENvbW1pdHRlZSBvZiB0aGUgUGFjaWZpYyBTYWxtb24gQ29tbWlzc2lvbiBhcyB0aGUgc291cmNlLgoKI19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fIwoKIyBNYW51YWxseSBjcmVhdGUgZmlzaGVyaWVzIGxhYmVscyBmb3IgZml4aW5nIGRhdGEKCkZpc2hlcnlfU2V0IDwtIGMoCiAgcmVwKCJTRUsiLDMpLAogIHJlcCgiTkJDIiwyKSwKICByZXAoIldDVkkiLDIpLAogIHJlcCgiTkJDJkNCIiwzKSwKICByZXAoIlNCQyIsMyksCiAgcmVwKCJORiIsMiksCiAgcmVwKCJTRiIsMiksCiAgcmVwKCJXQUsiLDEpLAogIHJlcCgiUFVHIiwyKSwKICByZXAoIlNFSyIsMyksCiAgcmVwKCJDQU4iLDIpLAogIHJlcCgiU1VTIiwzKSwKICAiU3RyYXkiLAogICJFc2MiCikKCiMgQ3JlYXRlIHRhYmVsIHJlbGF0aW9uCkZpc2hlcnlfdG9fQ291bnRyeSA8LSB0aWJibGUoCiAgRmlzaGVyeSA9IGMoIlNFSyIsIk5CQyIsIldDVkkiLCJOQkMmQ0IiLCJTQkMiLCJORiIsIlNGIiwiV0FLIiwiUFVHIiwiQ0FOIiwiU1VTIiwiU3RyYXkiLCJFc2MiKSwKICBGaXNoaW5nX0NvdW50cnkgPSBjKCJVUyBBbGFza2EiLHJlcCgiQ2FuYWRhIiw0KSxyZXAoIlVTIENvbnRpZ3VvdXMgU3RhdGVzIiwyKSxyZXAoIlVTIENvbnRpZ3VvdXMgU3RhdGVzIiwyKSwiQ2FuYWRhIiwiVVMgQ29udGlndW91cyBTdGF0ZXMiLCJTdHJheSIsIkVzYyIpCikKCiMgTG9hZCBGaXNoZXJ5IEFjcm9ueW1zCgpBY3JvbnltcyA8LSByZWFkX2V4Y2VsKCIvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvTlJDQU5fY2hhcHRlci9TcGVjaWVzX0RhdGEvMjAxOCBDaGlub29rIFRvdGFsIE1vcnRhbGl0eSBEaXN0cmlidXRpb24ueGxzeCIsCiAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiRmlzaGVyaWVzIiwgY29sX25hbWVzID0gVFJVRSkgJT4lIAogIGFycmFuZ2UoUmVnaW9uKSAlPiUgCiAgbXV0YXRlKFNoZWV0ID0gcGFzdGUoU3RvY2tBY3JvbnltLCJ0b3RhbCBtb3J0IikpICU+JSAKICBtdXRhdGUoQ291bnRyeSA9IGMocmVwKCJVUyBDb250aWd1b3VzIFN0YXRlcyIsMjIpLHJlcCgiQ2FuYWRhIiw0KSxyZXAoIlVTIENvbnRpZ3VvdXMgU3RhdGVzIiwxOCkscmVwKCJVUyBBbGFza2EiLDMpLHJlcCgiVHJhbnNib3VuZGFyeSIsMiksIkNhbmFkYSIscmVwKCJVUyBDb250aWd1b3VzIFN0YXRlcyIsNCkpCiAgKQoKCgojIFJ1biBmdW5jdGlvbiB0byBnZXQgYWxsIERhdGEKc3VwcHJlc3NNZXNzYWdlcygKICBDaGlub29rX0RhdGEgPC0gYmluZF9yb3dzKAogICAgbGFwcGx5KEFjcm9ueW1zJFNoZWV0LGdldF9jaGlub29rX2RhdGEpCiAgKQopIAoKClRvdGFsX1JlZ2lvbl9DYXRjaCA8LSBDaGlub29rX0RhdGEgJT4lIAogIGdyb3VwX2J5KFJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShUb3RhbF9SZWdfQ2F0Y2ggPSBzdW0oQ2F0Y2hfQ291bnRyeSxuYS5ybT1UKSkgJT4lIAogIGZpbHRlcighaXMubmEoUmVnaW9uKSkKClJlZ2lvbmFsX0Nvb3JkIDwtIHRpYmJsZSgKICBSZWdpb24gPSB1bmlxdWUoVG90YWxfUmVnaW9uX0NhdGNoJFJlZ2lvbiksCiAgTG9uID0gYygxMjIsMTIzLDEzMi45LDEzNywxMjIsMTQ1LDE0MCwxMjgsMTI4KSwKICBMYXQgPSBjKDQzLjUsNTMsNTAuNCw1NCw0OCw1Nyw0OCw0OCw0My41KQopCgpDaGlub29rX1Blcl9SZWdpb24gPC0gQ2hpbm9va19EYXRhICU+JSAKICBncm91cF9ieShGaXNoaW5nX0NvdW50cnksUmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKFRvdGFsX0NvdW50cnlfQ2F0Y2ggPSBzdW0oQ2F0Y2hfQ291bnRyeSxuYS5ybT1UKSkgJT4lIAogIGxlZnRfam9pbihUb3RhbF9SZWdpb25fQ2F0Y2gsIAogICAgICAgICAgICBieSA9ICJSZWdpb24iKSAlPiUgCiAgbXV0YXRlKFJlZ2lvbl9wZXIgPSAoVG90YWxfQ291bnRyeV9DYXRjaC9Ub3RhbF9SZWdfQ2F0Y2gpKjEwMCkgJT4lIAogIGZpbHRlcighaXMubmEoUmVnaW9uKSkgJT4lIAogIGxlZnRfam9pbihSZWdpb25hbF9Db29yZCkKCiMgUGxvdCBQaWUgY2hhcnRzCiMgZ2dwbG90KENoaW5vb2tfUGVyX1JlZ2lvbikgKwojICAgZ2VvbV9iYXIoCiMgICAgIGFlcygKIyAgICAgICB4ID0gIiIsCiMgICAgICAgeSA9IFJlZ2lvbl9wZXIsCiMgICAgICAgZmlsbCA9IEZpc2hpbmdfQ291bnRyeQojICAgICApLAojICAgICBzdGF0ID0iaWRlbnRpdHkiCiMgICApICsKIyAgIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQ9MCkgKwojICAgZmFjZXRfd3JhcCh+UmVnaW9uKQoKCiMjIyMgVGhlIE1hcAoKIyMjIEdpdmUgY29vcmQgZm9yIG1hcAoKVGVzdCA8LSBDaGlub29rX1Blcl9SZWdpb24gJT4lIAogIHNlbGVjdChSZWdpb24sRmlzaGluZ19Db3VudHJ5LFJlZ2lvbl9wZXIpICU+JSAKICBzcHJlYWQoRmlzaGluZ19Db3VudHJ5LFJlZ2lvbl9wZXIpICU+JSAKICBsZWZ0X2pvaW4oUmVnaW9uYWxfQ29vcmQpICU+JSAKICBtdXRhdGUoTG9uID0gTG9uKi0xLAogICAgICAgICByYWRpdXMgPSAzKQoKCiMjIyMgT3B0aW9uIEMKIyBNYXAgRGltZW5zc2lvbnMKeG1pbj0tMTIxCnhtYXg9LTE1MAp5bWluPTMzCnltYXg9NjMKCndvcmxkID0gbWFwX2RhdGEoIndvcmxkIiwgcmVzb2x1dGlvbj0wKQoKcCA8LSBnZ3Bsb3Qod29ybGQsIGFlcyhsb25nLCBsYXQpKSArCiAgZ2VvbV9tYXAobWFwPXdvcmxkLCBhZXMobWFwX2lkPXJlZ2lvbiksIAogICAgICAgICAgIGZpbGw9d2VzX3BhbGV0dGUobmFtZSA9ICJJc2xlb2ZEb2dzMiIpWzFdLAogICAgICAgICAgICMgZmlsbCA9ICJncmV5OTAiLAogICAgICAgICAgIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgc2l6ZSA9IDAuMSkgKwogIGNvb3JkX3F1aWNrbWFwKHhsaW0gPSBjKHhtaW4sIHhtYXgpLCB5bGltID0gYyh5bWluLCB5bWF4KSkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICMgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5OTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc2l6ZSA9IDAuNSksCiAgICAjIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTkwIiwKICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiLAogICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAwLjUpLAogICAgIyBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgIyBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IHdlc19wYWxldHRlKG5hbWUgPSAiRGFyamVlbGluZzIiKVs0XSkKICApCiAgCiMgTWFrZSBtYWdpYyBmb3IgUGllIG5vdCB0byBiZSBkaXN0b3J0ZWQKIyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy81MTM5ODM0NC9yLXBpZS1jaGFydHMtZGlzdG9ydGVkLXdoZW4tYWRkaW5nLXRvLXByb2plY3RlZC1tYXAtdXNpbmctZ2dwbG90CgpwaWUubGlzdCA8LSBUZXN0ICU+JSAKICB0aWR5cjo6Z2F0aGVyKHR5cGUsIHZhbHVlLCAtTG9uLCAtTGF0LCAtcmFkaXVzLCAtUmVnaW9uKSAlPiUKICB0aWR5cjo6bmVzdCh0eXBlLCB2YWx1ZSkgJT4lCiAgIyBtYWtlIGEgcGllIGNoYXJ0IGZyb20gZWFjaCByb3csICYgY29udmVydCB0byBncm9iCiAgbXV0YXRlKHBpZS5ncm9iID0gcHVycnI6Om1hcChkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oZCkgZ2dwbG90R3JvYihnZ3Bsb3QoZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IDEsIHkgPSB2YWx1ZSwgZmlsbCA9IHR5cGUpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UpICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKCJGaXNoaW5nIEVudGl0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYyh3ZXNfcGFsZXR0ZShuYW1lID0gIkRhcmplZWxpbmcxIilbMjo1XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkpKSkgJT4lCiAgCiAgIyBjb252ZXJ0IGVhY2ggZ3JvYiB0byBhbiBhbm5vdGF0aW9uX2N1c3RvbSBsYXllci4gSSd2ZSBhbHNvIGFkanVzdGVkIHRoZSByYWRpdXMKICAjIHZhbHVlIHRvIGEgcmVhc29uYWJsZSBzaXplIChiYXNlZCBvbiBteSBzY3JlZW4gcmVzb2x1dGlvbnMpLgogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUoc3ViZ3JvYiA9IGxpc3QoYW5ub3RhdGlvbl9jdXN0b20oZ3JvYiA9IHBpZS5ncm9iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bWluID0gTG9uIC0gcmFkaXVzLCB4bWF4ID0gTG9uICsgcmFkaXVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5bWluID0gTGF0IC0gcmFkaXVzLCB5bWF4ID0gTGF0ICsgcmFkaXVzKSkKICAgICAgICAgKQoKIyMjIEZpbmFsIE1hcAoKcCArIAogIGdlb21fdGlsZShkYXRhID0gVGVzdCAlPiUgdGlkeXI6OmdhdGhlcih0eXBlLCB2YWx1ZSwgLUxvbiwgLUxhdCwgLXJhZGl1cywtUmVnaW9uKSwKICAgICAgICAgICAgYWVzKHggPSBMb24sIHkgPSBMYXQsIGZpbGwgPSB0eXBlKSwgCiAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgd2lkdGggPSAwLjAxLCBoZWlnaHQgPSAwLjAxLCAKICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKwogIAogIHBpZS5saXN0JHN1Ymdyb2IgKwogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChkYXRhID0gVGVzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IExvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IExhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBSZWdpb24pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2UgPSA1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBudWRnZV94ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51ZGdlX3kgPSAyLjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50LmNvbG9yCT0gTkEKICApICsKICBzY2FsZV9maWxsX21hbnVhbCgiRmlzaGluZyBFbnRpdHkiLAogICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGMod2VzX3BhbGV0dGUobmFtZSA9ICJEYXJqZWVsaW5nMSIpWzI6NV0KICAgICAgICAgICAgICAgICAgICApCiAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJMb25naXR1ZGUiLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoeG1heCwtMTIwLDUpCiAgICAgICAgICAgICAgICAgICAgICkgKwogIHNjYWxlX3lfY29udGludW91cygiTGF0aXR1ZGUiLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMzAsNjUsNSkKICApICsKICBhbm5vdGF0ZSgidGV4dCIsIAogICAgICAgICAgIHggPS0xNDAsCiAgICAgICAgICAgeSA9IDM2LjMsCiAgICAgICAgICAgbGFiZWwgPSAiU2hhcmluZyBDaGlub29rIFNhbG1vbiIsIAogICAgICAgICAgIGNvbG9yPSJibGFjayIsIAogICAgICAgICAgIHNpemU9NiwgCiAgICAgICAgICAgYW5nbGU9MCwgCiAgICAgICAgICAgZm9udGZhY2U9Iml0YWxpYyIsCiAgICAgICAgICAgaGp1c3Q9MCkgKwogIGFubm90YXRlKCJ0ZXh0IiwgCiAgICAgICAgICAgeCA9LTEzMiwKICAgICAgICAgICB5ID0gMzQuOCwKICAgICAgICAgICBsYWJlbCA9ICJSZWdpb25hbCBDaGlub29rIFNhbG1vbiBDYXB0dXJlcyBwZXJcbkZpc2hpbmcgRW50aXR5IEJldHdlZW4gMjAwOSBhbmQgMjAxNyIsIAogICAgICAgICAgIGNvbG9yPSJibGFjayIsIAogICAgICAgICAgIHNpemU9MywgCiAgICAgICAgICAgYW5nbGU9MCwgCiAgICAgICAgICAgIyBmb250ZmFjZT0iaXRhbGljIiwKICAgICAgICAgICBoanVzdD0wLjUpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4xOCwwLjA5KSwKICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSB3ZXNfcGFsZXR0ZShuYW1lID0gIkRhcmplZWxpbmcyIilbNF0pCiAgKQoKCmdnc2F2ZSgiQ29sX0NoaW5vb2tfTWFwLnBuZyIsCiAgICAgICBwbG90ID0gbGFzdF9wbG90KCksCiAgICAgICB3aWR0aCA9IDYsCiAgICAgICBoZWlnaHQgPSA4LAogICAgICAgdW5pdHMgPSAiaW4iKQoKIyMjIE1hcCBmb3IgbWlncmF0aW9uCgp4bWluPS0xMTEKeG1heD0tMTYwCnltaW49NDUKeW1heD02MwoKc3RhdGVzIDwtIG1hcF9kYXRhKCJzdGF0ZSIpCgpnZ3Bsb3Qod29ybGQsIGFlcyhsb25nLCBsYXQpKSArCiAgZ2VvbV9tYXAobWFwPXdvcmxkLCBhZXMobWFwX2lkPXJlZ2lvbiksIAogICAgICAgICAgIGZpbGw9d2VzX3BhbGV0dGUobmFtZSA9ICJJc2xlb2ZEb2dzMiIpWzFdLAogICAgICAgICAgICMgZmlsbCA9ICJncmV5OTAiLAogICAgICAgICAgIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgc2l6ZSA9IDAuMSkgKwogIGdlb21fcG9seWdvbihkYXRhID0gc3RhdGVzLAogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsCiAgICAgICAgICAgICAgICAgICBncm91cCA9IGdyb3VwKSwgCiAgICAgICAgICAgICAgIGZpbGw9d2VzX3BhbGV0dGUobmFtZSA9ICJJc2xlb2ZEb2dzMiIpWzFdLAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICMgZmlsbCA9ICJncmV5OTAiLAogICAgICAgICAgICAgICBzaXplID0gMC4xKSArIAogIGNvb3JkX3F1aWNrbWFwKHhsaW0gPSBjKHhtaW4sIHhtYXgpLCB5bGltID0gYyh5bWluLCB5bWF4KSkgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICMgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5OTAiLAogICAgIyBsaW5ldHlwZSA9ICJkYXNoZWQiLAogICAgIyBzaXplID0gMC41KSwKICAgICMgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5OTAiLAogICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDAuNSksCiAgICAjIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAjIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkKICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IHdlc19wYWxldHRlKG5hbWUgPSAiRGFyamVlbGluZzIiKVs0XSkKICApCgpnZ3NhdmUoImNvbF9taWdyYXRpb25fbWFwLnBuZyIsCiAgICAgICBwbG90ID0gbGFzdF9wbG90KCksCiAgICAgICB3aWR0aCA9IDgsCiAgICAgICBoZWlnaHQgPSA2LAogICAgICAgdW5pdHMgPSAiaW4iKQoKYGBgCgoKCg==