Author information:

Date: “9/22/2019”

Author (analysis): Divya Panicker

Study: Cetacean distribution and diversity in Lakshadweep Islands: October 2015 to April 2016

Funding: Rufford Small Grants for Nature Conservation

Institutions: University of Washington, National Centre for Biological Sciences, Centre for Wildlife Studies

Email for correspondence: dpanic@uw.edu

Citation: Panicker, D., Sutaria, D., Kumar, A., Stafford, K. (2019) ‘Cetacean distribution and diversity in Lakshadweep Islands, India using platforms of opportunity: Oct 2015 to Apr 2016’. ResearchWorks. University of Washington.


Corresponding datasets:

Dataset ‘Panicker_et_al_2019_surveyeffortdataset.csv’ contains the effort for all the surveys. Read into the program as ‘effdat’

Dataset ‘Panicker_et_al_2019_cetaceandataset.csv’ is the sightings dataset which include both on survey effort and opportunistic sightings. The sightings data set also include variables such as depth at boat location, slope, aspect and nearest distance to land. Depth was obtained from GeoMapApp (Ryan et al. 2009). Slope, aspect and nearest distance to land was calculated using ArcGIS. The file is read into the program as ‘cetenvdat’.

Dataset ‘Panicker_et_al_2019_beaufortdataset.csv’ is the dataset with corresponding beaufort states. This sheet has the distance covered in each beaufort state per season, per route, per day. Read into the program as ‘effbeaudist’


Names of subsets from data csv files within this notebook:

  1. ‘idcetenvdat’ is the subset for identified sightings including opportunistic sightings.
  2. ‘oncetenvdat’ is the subset for on survey effort sightings.
  3. ‘idcetenvdatstats’ is the subset for identified sightings with the exception of baleen whale and pygmy whale sightings as n=1. This file is used for all statistical analysis.
  4. ‘comidcetenvdatstats’ is the sightings data for identified sightings of three of the most commonly sighted species (spinnner, bottlenose and pilot).
  5. ‘routenames’ is a dataset created for a list of survey routes and corresponding route numbers.

Note: If subsets have inter or ne at the end, it corresponds to inter-monsoon or northeast monsoon seasons


R Setup

Working directory for R studio, Reading Data files and Data preparation

Run line by line to avoid masking

#knitr::opts_chunk$set(echo = FALSE)
rm(list = ls()) # clears workspace
# Working directory on your computer! CHANGE AS YOU NEED
# set the working directory to your home directory where data files are stored
setwd("/Volumes/GoogleDrive/My Drive/Laksh I project/design & data/Data Entry/Laksh R files/Panicker_2019_Cetaceans_Lakshadweep/") 
# Required Packages and libraries
library(lubridate)
library(gdata)
library(plotrix)
library(psych)
library(devtools)
library(reshape2)
library(ggplot2)
# Reading in data files
effdat<-read.csv("Panicker_et_al_2019_surveyeffortdataset.csv", header = T, stringsAsFactors = F) # effort dataset
cetenvdat<-read.csv("Panicker_et_al_2019_cetaceandataset.csv", header = T, stringsAsFactors = F) # cetacean dataset
effbeaudist<-read.csv("Panicker_et_al_2019_beaufortdataset.csv", header = T, stringsAsFactors = F) # beaufort dataset
# Data preparation for analysis
# Creating a dataset of routenames and corresponding route numbers
routenames<-data.frame((c(1,2,3,4,5,6,7,8,9,10,11,12)),(c("AGT-AKC","KVT-AGT","BTR-AKC","KVT-AKC","CHT-AKC","KLT-AKC","KVT-AND","BTR-KVT","KLT-CHT","KVT-KLP","AMN-KDT","KVT-KLT")))
colnames(routenames) <- c("routeno", "route")
# Creating a subset for the identified species
idcetenvdat<-subset(cetenvdat, !cetenvdat$species == "blackfish" & !cetenvdat$species == "uniddolphin" & !cetenvdat$species == "unidcet" & !cetenvdat$species=="unidsmallwhale" & !cetenvdat$species == "unidwhale" & !cetenvdat$species == "unidsmalldolphin" )
# Creating a subset for on survey effort sightings
oncetenvdat<-subset(cetenvdat, !cetenvdat$eff == "off")
# Removing baleen and pgymykiller whale from identified species as sample size is 1 for these species (This step needed for stats analysis)
idcetenvdatstats<-drop.levels(subset(idcetenvdat,!idcetenvdat$species == "baleen" & !idcetenvdat$species == "pygmykiller"))
# Creating a subset for identified commonly sighted species (n>10 namely, spinner dolphin, bottlenose dolphin and pilot whale)
comidcetenvdatstats<-rbind(subset(idcetenvdat, idcetenvdat$species == "spinner"), subset(idcetenvdat, idcetenvdat$species == "bottlenose"), subset(idcetenvdat, idcetenvdat$species == "pilot"))
# Creating a subset for identified species in northeast monsoon season
idcetenvdatstatsne<-subset(idcetenvdatstats, idcetenvdatstats$seas == 'ne')
# Creating a subset for identified species in northeast monsoon season for commonly sighted species (n>10 namely, spinner dolphin, bottlenose dolphin and pilot whale)
comidcetenvdatstatsne<-subset(comidcetenvdatstats, comidcetenvdatstats$seas == 'ne')
# Creating a subset for identified species in inter monsoon season
idcetenvdatstatsinter<-subset(idcetenvdatstats, idcetenvdatstats$seas == 'inter')
# Creating a subset for identified species in inter monsoon season for commonly sighted species (n>10 namely, spinner dolphin, bottlenose dolphin and pilot whale)
comidcetenvdatstatsinter<-subset(comidcetenvdatstats, comidcetenvdatstats$seas == 'inter')
print ("SETUP DONE AND DATA READ INTO R")
[1] "SETUP DONE AND DATA READ INTO R"

Table of Contents

Structure of data

No. of sightings, survey effort and beaufort states

Encounter rates

Species list

Group sizes (Table 1)

Seafloor depths at sighting locations(Table 1)

Cetacean sightings across season (Figure 4)

Cetacean species across distance to nearest landmass

Cetacean species across seafloor slope gradient

Cetacean species across seafloor depth

Plot of cetacean species across nearest distance to land and slope gradient (Figure 5)



Structure of data

Note: Column header details are given in ReadMe file.

Effort dataset (effdat)

# structure of effort
effdat$date<-as.Date(effdat$date, "%m/%d/%y") # setting data format
str(effdat)
'data.frame':   78 obs. of  13 variables:
 $ date            : Date, format: "2015-10-28" "2015-10-31" "2015-10-31" "2015-11-01" ...
 $ seas            : chr  "ne" "ne" "ne" "ne" ...
 $ HSV             : chr  "small" "large" "large" "small" ...
 $ routeno         : int  10 9 5 3 8 4 11 2 6 9 ...
 $ route           : chr  "KVT KLP" "KLT CHT" "CHT AKC" "BTR AKC" ...
 $ tripno          : int  1 1 1 1 1 1 1 1 1 2 ...
 $ dist            : num  69.6 31.3 33.5 69.1 58.6 ...
 $ hr.dec          : num  2.83 1.25 1.03 2.28 2.08 1.92 0.37 1.88 1.15 1.08 ...
 $ hrs             : chr  "2:50" "1:15" "1:02" "2:17" ...
 $ starttimewbreaks: chr  "8:35" "12:55" "14:43" "9:59" ...
 $ endtimewbreaks  : chr  "12:01" "13:53" "15:45" "12:40" ...
 $ sight           : chr  "Y" "Y" "Y" "Y" ...
 $ no.sight        : int  2 2 1 2 1 1 1 4 1 0 ...

Cetacean dataset (cetenvdat)

str(cetenvdat)
'data.frame':   139 obs. of  19 variables:
 $ sno       : int  32 33 76 77 91 92 93 94 95 102 ...
 $ mon       : int  11 11 12 12 3 3 3 3 3 3 ...
 $ date      : int  18 18 11 11 11 11 11 11 11 18 ...
 $ year      : int  2015 2015 2015 2015 2016 2016 2016 2016 2016 2016 ...
 $ seas      : chr  "ne" "ne" "ne" "ne" ...
 $ HSV       : chr  "large" "large" "large" "large" ...
 $ eff       : chr  "on" "on" "on" "on" ...
 $ routeno   : int  1 1 1 1 1 1 1 1 1 1 ...
 $ route     : chr  "AGT AKC" "AGT AKC" "AGT AKC" "AGT AKC" ...
 $ time      : chr  "12:10" "12:20" "12:36" "12:36" ...
 $ species   : chr  "spinner" "unidcet" "uniddolphin" "unidsmalldolphin" ...
 $ class     : chr  "smalldolphin" "cetacean" "dolphin" "smalldolphin" ...
 $ lat       : num  11 11 11 11 10.9 ...
 $ long      : num  72.5 72.4 72.5 72.5 72.3 ...
 $ grpsize   : int  20 2 1 2 6 12 1 4 15 6 ...
 $ depth     : int  -1604 -1525 -1140 -1140 -655 -198 -51 -948 -1561 -966 ...
 $ neardistkm: num  19.13 13.62 14.26 14.26 2.93 ...
 $ slope     : num  3.08 6.07 14.41 14.41 17.24 ...
 $ beaufort  : int  4 4 3 3 1 1 1 1 1 3 ...



No. of sightings, survey effort and beaufort states

Refer to subheading of results section of manuscript

Survey effort

# Total hours spent on survey effort
toteffhours<-sum(effdat$hr.dec)
paste ("Total hours spent on survey effort =", toteffhours)
[1] "Total hours spent on survey effort = 128.75"
# Total distance covered during survey effort
toteffdist<-sum(effdat$dist)
paste("Total distance (km) covered during survey effort = ", toteffdist)
[1] "Total distance (km) covered during survey effort =  3880.33"
# Number of surveys hours each day
paste("Average number of hours on survey effort per day = ", round(mean(effdat$hr.dec),2), "+/-", round(std.error(effdat$hr.dec),1))
[1] "Average number of hours on survey effort per day =  1.65 +/- 0.1"
paste("Min hours on survey effort in a day = ", round(min(effdat$hr.dec),1))
[1] "Min hours on survey effort in a day =  0.2"
paste("Max hours on survey effort in a day = ", round(max(effdat$hr.dec),1))
[1] "Max hours on survey effort in a day =  3.2"

No. of sightings

# note: Off effort and opporunistic is the same!
# Total number of cetacean group sightings (including opportunistic sightings)
paste ("Total no of cetacean group sightings (on and off survey effort) =", nrow(cetenvdat))
[1] "Total no of cetacean group sightings (on and off survey effort) = 139"
# No: of cetacean group sightings (on survey effort)
paste ("No. of cetacean group sightings on survey effort =", length(which(cetenvdat == "on")))
[1] "No. of cetacean group sightings on survey effort = 78"
# No: of cetacean group sightings (off survey effort/opportunistic)
paste ("No. of cetacean group sightings off survey effort =", length(which(cetenvdat == "off")))
[1] "No. of cetacean group sightings off survey effort = 61"
# Total number of identified cetacean groups (on and off survey effort)
paste ("Total no of identified cetacean groups (on and off survey effort) =", nrow(idcetenvdat))
[1] "Total no of identified cetacean groups (on and off survey effort) = 74"
# Number of identified cetacean groups (on survey effort)
paste ("No. of identified cetacean groups on survey effort =", length(which(idcetenvdat == "on")))
[1] "No. of identified cetacean groups on survey effort = 31"

Beaufort states recorded during survey effort

Table of distance (km) for each beaufort state

beau.table<-tapply((effbeaudist$Distance),(effbeaudist$Beaufort),FUN=sum)
beau.table
      0       1       2       3       4       5       6 
  17.00  775.48 1139.90 1206.70  603.42  115.57   34.80 

Percentages of the distances with respect to the total distance traveled in a particular beaufort state (e.g. 80.63% distance traveled in 0-3 state, note that this includes not just 0 but 0-3, 15.5% in beaufort 4, 2.96% in beaufort 5 and 0.89% in beaufort 6)

beau.one.two.three.percent<-round(((beau.table[1]+beau.table[2]+beau.table[3]+beau.table[4])/sum(beau.table))*100,1)
beau.one.two.three.percent
   0 
80.6 
beau.four.percent<-round(((beau.table[5])/sum(beau.table))*100,1)
beau.four.percent
   4 
15.5 
beau.five.percent<-round(((beau.table[6])/sum(beau.table))*100,1)
beau.five.percent
5 
3 
beau.six.percent<-round(((beau.table[7])/sum(beau.table))*100,1)
beau.six.percent
  6 
0.9 
rm(beau.table, beau.one.two.three.percent, beau.four.percent, beau.five.percent, beau.six.percent)



Encounter rates

Overall Encounter rate
totencratedist<-round (((nrow(oncetenvdat)/toteffdist)*100),2)
paste("Overall encounter rate (per 100km) of cetacean groups for the entire study area =", totencratedist)
[1] "Overall encounter rate (per 100km) of cetacean groups for the entire study area = 2.01"
Route-wise encounter rate (per 100 km)
step1<-aggregate(effdat$dist ~ effdat$routeno, FUN=sum) # extracting sum of distances for routes
step2<-aggregate(effdat$no.sight ~ effdat$routeno, FUN=sum) # extracting sum of sightings for routes
step3<-step2$`effdat$no.sight`/step1$`effdat$dist` # encrate/km for each route = sighting/distance for each route, step dataframes can be removed from workspace after running. 
route_encrate<-round(step3*100,2) # enc rate/distance * 100 kms and rounded to two decimal points
rm(step1, step2, step3)
route_encrate <- data.frame(routenames,route_encrate)
route_encrate 


Species list

Refer to the second subheading of the results section

Species list and most commonly sighted

Eight toothed whale and one baleen whale were encountered. Note: Balaenoptera sp identified till genus, Tursiops sp (includes aduncus and truncatus)

species<- c("Baleen whale", "Blackfish", "Bottlenose dolphin", "False killer whale", "Pilot whale", "Pygmy killer whale", "Risso's dolphin", "Spinner dolphin","Spotted dolphin", "Striped dolphin", "Unidentified cetacean", "Unidentified dolphin", "Unidentified small dolphin", "Unidentified small whale", "Unidentified whale")
freq<-table(cetenvdat$species)
freq<-as.vector(freq)
species_counts<-data.frame(species, freq)
species_counts
rm(freq)

Season-wise species lists

Baleen; Baleen whale; Balaenoptera sp, Bottlenose; Tursiops sp, False Killer whale; Pseudorca crassidens, pilot; Globicephala machrorhynchus, pygmykiller; Feresa attenuata, risso; Grampus griseus, spinner; * Stenella longirostris, spotted; Stenella attenuata, striped; Stenella coruleoalba*, unidcet; unidentified cetacean, uniddolphin; unidentified dolphin, unidsmalldolphin; unidentified small dolphin, unidsmallwhale; unidentified small whale, unidwhale; unidentified whale.

Species sighted during the northeast monsoon season

# No: of species in ne monsoon season
table(idcetenvdatstatsne$species)

 bottlenose falsekiller       pilot       risso     spinner     spotted     striped 
         11           3          10           5           8           1           4 

Species sighted during the inter monsoon season

# No: of species in inter monsoon season
table(idcetenvdatstatsinter$species)

 bottlenose falsekiller       pilot       risso     spinner     spotted     striped 
          7           1           3           2          14           2           1 



Group sizes (Table 1)

Average group size, standard errors and minimum and maximum group sizes for each species

meangrpsize<-round(tapply(cetenvdat$grpsize,cetenvdat$species, mean, na.rm = TRUE),2)
meangrpsize<-as.vector(meangrpsize)
SEgrpsize<-round(tapply(cetenvdat$grpsize,cetenvdat$species, std.error, na.rm = TRUE),2)
SEgrpsize<-as.vector(SEgrpsize)
SEgrpsize<-round(SEgrpsize,1)
mingrpsize<-tapply(cetenvdat$grpsize,cetenvdat$species, min, na.rm = TRUE)
mingrpsize<-as.vector(mingrpsize)
maxgrpsize<-tapply(cetenvdat$grpsize,cetenvdat$species, max, na.rm = TRUE)
maxgrpsize<-as.vector(maxgrpsize)
species_grpsize<-data.frame(species, meangrpsize, SEgrpsize, mingrpsize, maxgrpsize)
species_grpsize<-species_grpsize[1:10,]
species_grpsize
rm(meangrpsize, SEgrpsize, mingrpsize, maxgrpsize)


Seafloor depths at sighting locations(Table 1)

Average depth for cetacean sightings in the entire study area (in metres)

paste("Average depth =", round(mean(cetenvdat$depth),2), "+/-" ,round(std.error(cetenvdat$depth),2))
[1] "Average depth = -1179.1 +/- 57.34"
paste("Minimum depth =", round(min(cetenvdat$depth),2))
[1] "Minimum depth = -2259"
paste("Maximum  depth =", round(max(cetenvdat$depth),2))
[1] "Maximum  depth = -5"

Average depths, standard errors and minimum and maximum group sizes for each species

meandepth<-round(tapply(cetenvdat$depth,cetenvdat$species, mean, na.rm = TRUE),2)
meandepth<-as.vector(meandepth)
SEdepth<-round(tapply(cetenvdat$depth,cetenvdat$species, std.error, na.rm = TRUE),2)
SEdepth<-as.vector(SEdepth)
mindepth<-tapply(cetenvdat$depth,cetenvdat$species, min, na.rm = TRUE)
mindepth<-as.vector(mindepth)
maxdepth<-tapply(cetenvdat$depth,cetenvdat$species, max, na.rm = TRUE)
maxdepth<-as.vector(maxdepth)
species_depth<-data.frame(species, meandepth, SEdepth, mindepth, maxdepth)
species_depth<-species_depth[1:10,]
species_depth
rm(maxdepth, meandepth, mindepth, SEdepth)



Cetacean sightings across season (Figure 4)

Cetacean sightings in northeast monsoon and inter monsoon season (only on survey effort)

# on effort sightings
table(oncetenvdat$seas)

inter    ne 
   27    51 

Effort (in km) across season

# Distances (effort) in each season
test<-subset(effdat, effdat$seas == "ne")
test2<-subset(effdat, !effdat$seas == "ne")
paste("Dist (km) in north east monsoon = ", sum(test$dist), "and Dist (km) in inter monsoon = ", sum(test2$dist))
[1] "Dist (km) in north east monsoon =  1720.9 and Dist (km) in inter monsoon =  2159.43"
# Proprotion of effort in each season
paste("Proportion traveled in north east monsoon = ", round((sum(test$dist)/toteffdist)*100,2), "%", "and Proportion traveled in inter monsoon = ", round((sum(test2$dist)/toteffdist)*100,2), "%")
[1] "Proportion traveled in north east monsoon =  44.35 % and Proportion traveled in inter monsoon =  55.65 %"
rm(test2)
rm(test)
Error in names(frame)[names(frame) == "x"] <- name : 
  names() applied to a non-vector
Barplot of observed and expected cetacean sightings across season (on survey effort)

Expected ratio’s correspond to distance traveled in a season

par(mar = c(7,6,4,4)) # sets the outer margin, order = left,bottom,top,right
#par(oma=c(0,0,0,5.8))
obsexpseas<-as.matrix(data.frame(inter=c(27, 43.41), ne=c(51,34.59))) # creating a matrix with observed and expected cetacean sighting values for intermonsoon (27 & 43.41) and ne monsoon (51,34.59)
onseasbarplot<-barplot(obsexpseas, beside=TRUE, 
                       width = 0.5, 
                       xlab = "Season", 
                       ylab="No: of cetacean sightings", 
                       names.arg=c("Inter monsoon (n=27)","Northeast monsoon (n=51)"), 
                       cex.lab = 0.9, 
                       cex.axis = 1, 
                       cex.names = 0.7, 
                       col=c("grey80", "grey20"), 
                       density = c(100,100), 
                       ylim = c(0,80), 
                       xlim=c(0.3,5))
legend("topleft",  c("Cetacean sightings on survey", "Expected cetacean sighting based on effort"), fill = c("grey80", "grey20"), cex=0.7, bty='n')

Non parameteric statistical test - Chi-Square Goodness of Fit

Chi square goodness of fit test between observed and expected values. Expected values are calculated as effort (distance traveled in each season). The test is significant and the null hypothesis is rejected.

Null hypotheis: Sightings are equally distributed across the two seasons as per the distance traveled during survey effort.

Alternate Hypothesis: Sightings are differentially distributed across the two seasons as per the distance traveled during survey effort.

# chi square test for on effort sightings in each season - goodness of fit according to distance traveled
effdatne<-subset(effdat, effdat$seas == 'ne') # effort dataset for only ne monsoon
effdatinter<-subset(effdat, effdat$seas == 'inter') # effort dataset for only inter monsoon
toteffdistne<-sum(effdatne$dist) # total distance traveled for northeast monsoon
toteffdistinter<-sum(effdatinter$dist) # total distance traveled for inter monsoon
# table(oncetenvdat$seas) # sightings per season on effort
# chisquare goodness of fit test for no: of sightings in each season to expected number of sightings based on distance travelled.
table(oncetenvdat$seas)

inter    ne 
   27    51 
seasallchisq<-chisq.test( (table(oncetenvdat$seas)),
             p=c((toteffdistinter/toteffdist),(toteffdistne/toteffdist)) ) 
seasallchisq

    Chi-squared test for given probabilities

data:  (table(oncetenvdat$seas))
X-squared = 13.984, df = 1, p-value = 0.0001844
paste('Expected value for inter monsoon period is', round(seasallchisq$expected[1],2))
[1] "Expected value for inter monsoon period is 43.41"
paste('Expected values for north east monsoon is', round(seasallchisq$expected[2],2))
[1] "Expected values for north east monsoon is 34.59"
# formula chi.sq.test ( no: of seas sightings 27 (inter), 51(ne), probability = 0.5565068 (inter), 0.4434932 (ne) )



Cetacean species across distance to nearest landmass

Boxplot of distance to nearest landmass for all species

Species codes; bal = Baleen whale, T = Bottlenose dolphin, PC = False killer whale, GM = Short finned pilot whale, FA = Pgymy killer whale, GG = Rissos dolphin, SL = Spinner dolphin, SA = Spotted dolphin, SC = Striped dolphin

par(mar = c(5,5,3,3)) # sets the outer margin, order = left,bottom,top,right
neardistboxplot<-boxplot(idcetenvdatstats$neardistkm~idcetenvdatstats$species, xlab = "Species (n)", ylab="Nearest distance (km)", main = "Nearest distance to land for each species", names=c("T (18)","PC(4)","GM(13)","GG(7)","SL(22)","SA(3)","SC(5)"), cex.lab = 1.2, cex.main = 1, col="mediumaquamarine")

# species codes; bal = Baleen whale, T = Bottlenose dolphin, PC = False killer whale, GM = Short finned pilot whale, FA = Pgymy killer whale, GG = Rissos dolphin, SL = Spinner dolphin, SA = Spotted dolphin, SC = Striped dolphin
Non parameteric statistical test - Kruskal-Wallis test

Null hypothesis: All species are uniformly distributed with respect to the nearest landmass on the ferry routes.

Alternate hypothesis: Species are differentially distributed with respect to the nearest landmass on the ferry routes.

Kruskal Wallis test was performed and test was significant. Therefore the Null hypothsis is rejected.

# for all sps (except baleen and pygmy)
kruskal.test(as.factor(idcetenvdatstats$neardistkm)~as.factor(idcetenvdatstats$species), data=idcetenvdatstats)

    Kruskal-Wallis rank sum test

data:  as.factor(idcetenvdatstats$neardistkm) by as.factor(idcetenvdatstats$species)
Kruskal-Wallis chi-squared = 16.962, df = 6, p-value = 0.009425

Medians for nearest and furthest species

paste ("Spinner dolphins median (in km) =", round(neardistboxplot$stats[3,5],2))
[1] "Spinner dolphins median (in km) = 1.82"
paste ("Spotted dolphins median (in km) =", round(neardistboxplot$stats[3,6],2))
[1] "Spotted dolphins median (in km) = 43.28"
paste ("Striped dolphins median (in km) =", round(neardistboxplot$stats[3,7],2))
[1] "Striped dolphins median (in km) = 24.72"


Cetacean species across seafloor slope gradient

Boxplot of slope distribution for all species

Species codes; bal = Baleen whale, T = Bottlenose dolphin, PC = False killer whale, GM = Short finned pilot whale, FA = Pgymy killer whale, GG = Rissos dolphin, SL = Spinner dolphin, SA = Spotted dolphin, SC = Striped dolphin

par(mar = c(5,5,3,3)) # sets the outer margin, order = left,bottom,top,right
slopeboxplot<-boxplot(idcetenvdatstats$slope~idcetenvdatstats$species, xlab = "Species (n)", ylab="Slope", main = "Slope distribution for each species", names=c("T (18)","PC(4)","GM(13)", "GG(7)","SL(22)","SA(3)","SC(5)"), cex.lab = 1.2, cex.main = 1, col="mediumaquamarine")

# species codes; bal = Baleen whale, T = Bottlenose dolphin, PC = False killer whale, GM = Short finned pilot whale, FA = Pgymy killer whale, GG = Rissos dolphin, SL = Spinner dolphin, SA = Spotted dolphin, SC = Striped dolphin
Non parameteric statistical test - Kruskal-Wallis test

Null hypothesis: All species are uniformly distributed across slope gradients along the ferry routes.

Alternate hypothesis: Species are differentially distributed across slope gradients along the ferry routes.

Kruskal Wallis test was performed and test was significant. Therefore the Null hypothsis is rejected.

# for common sps
kruskal.test(as.factor(idcetenvdatstats$slope)~as.factor(idcetenvdatstats$species), data=idcetenvdatstats)

    Kruskal-Wallis rank sum test

data:  as.factor(idcetenvdatstats$slope) by as.factor(idcetenvdatstats$species)
Kruskal-Wallis chi-squared = 15.542, df = 6, p-value = 0.01643

Medians for species in the flatest and steepest slopes

paste ("Spinner dolphins median steepest slope =", round(slopeboxplot$stats[3,5],2))
[1] "Spinner dolphins median steepest slope = 13.54"
paste ("Spotted dolphins median flat slope =", round(slopeboxplot$stats[3,6],2))
[1] "Spotted dolphins median flat slope = 1.51"
paste ("Striped dolphins median flat slope =", round(slopeboxplot$stats[3,7],2))
[1] "Striped dolphins median flat slope = 1.65"


Cetacean species across seafloor depth

Boxplot between cetacean species and seafloor depth

Species codes; bal = Baleen whale, T = Bottlenose dolphin, PC = False killer whale, GM = Short finned pilot whale, FA = Pgymy killer whale, GG = Rissos dolphin, SL = Spinner dolphin, SA = Spotted dolphin, SC = Striped dolphin

# All species and depth
par(mar = c(5,5,3,3)) # sets the outer margin, order = left,bottom,top,right
depthboxplot<-boxplot(idcetenvdatstats$depth~idcetenvdatstats$species, xlab = "Species (n)", ylab="Seafloor depth(m)", main = "Seafloor depth distribution for each species", names=c("T (18)","PC(4)","GM(13)","GG(7)","SL(22)","SA(3)","SC(5)"), cex.lab = 1.2, cex.main = 1, col="mediumaquamarine") # xlab = x label, ylab = y label, cex.lab = label font size, cex.main = title font size, main = title

# species codes; bal = Baleen whale, T = Bottlenose dolphin, PC = False killer whale, GM = Short finned pilot whale, FA = Pgymy killer whale, GG = Rissos dolphin, SL = Spinner dolphin, SA = Spotted dolphin, SC = Striped dolphin
Non parameteric statistical test species and depth - Kruskal-Wallis test

Null hypothesis: All species are uniformly distributed away across seafloor depths.

Alternate hypothesis: Species are differentially distributed across seafloor depths.

Kruskal Wallis test was performed and test was not significant. Therefore the Null hypothsis is not rejected.

# for all sps (except baleen and pygmy)
kruskal.test(as.factor(idcetenvdatstats$depth)~as.factor(idcetenvdatstats$species), data=idcetenvdatstats)

    Kruskal-Wallis rank sum test

data:  as.factor(idcetenvdatstats$depth) by as.factor(idcetenvdatstats$species)
Kruskal-Wallis chi-squared = 10.912, df = 6, p-value = 0.09114


Plot of cetacean species across nearest distance to land and slope gradient (Figure 5)

### Plotting significant results together 
##### Slope and nearest distance to land across species
# collapse the data frame
x<-melt(data = idcetenvdatstats, id.vars = "species", measure.vars = c("slope", "neardistkm"))
require(ggplot2)
slopedistplot<-ggplot(data = x, aes(x=species, y=value)) + 
  # specify boxplot and variable to be filled in this case 'slope' & 'neardist'
  geom_boxplot(aes(fill=variable)) +
  # name x and y axis
  xlab("Species (n)") + ylab("Slope (percent)") +
  # add a second y axis on the right and specify values w.r.t to x axis (*1x)
  scale_y_continuous(sec.axis = sec_axis(~.*1, name = "Distance to nearest land (km)")) +
  
  theme(text = element_text(size=12), axis.text.x = element_text(angle=90)) +
  
  theme(plot.margin=unit(c(1,0.8,0.5,0.5),"cm")) +
  
  # change the legend labels
  scale_fill_discrete(name="", labels=c("Slope", "Distance to nearest land")) +
  # change the legend position (0,0) = bottom left & (1,1) = top right
  theme(legend.position = c(0.16, 0.9)) +
  # size of legend text
  theme(legend.text=element_text(size=rel(0.5))) +
  # remove the legend background
  theme(legend.background = element_blank()) +
  # adding sample sizes to the plot
  scale_x_discrete(labels=c("bottlenose" = "bottlenose dolphin (18)", 
                              "falsekiller" = "false killer whale(4)", 
                                "pilot" = "pilot whale(13)",
                            "risso" = "Risso's dolphin (7)",
                            "spinner" ="spinner dolphin(22)",
                            "spotted" ="spotted dolphin(3)",
                            "striped" = "striped dolphin(5)")) 
#stat_summary(fun.y=mean,shape=1,col='red',geom='point')
slopedistplot

rm(x)



Route Information

step1<-table(effdat$route) # No. of times a route was traversed
step1<-step1[c(1,8,3,9,5,6,10,4,7,11,2,12)] # reorder to match corresponding columns in route_encrate dataframe
step1<-as.vector(step1) # making into a vector
step2<-aggregate(effdat$dist ~ effdat$routeno, FUN=sum) # extracting sum of distances for routes
step3<-aggregate(effdat$no.sight ~ effdat$routeno, FUN=sum) # extracting sum of sightings for routes
route_info<-data.frame(route_encrate, step1, step2, step3) # Making a data frame with route no, route name, no: of times a route was tranversed, route distance, route sightings and route enc rate
route_info<-route_info[c(1,2,4,6,8,3)] # reorder
colnames(route_info)<-c("Route No.", "Route name", "No. of times", "Distance (km)", "No. of sightings", "Encounter rate")
route_info
rm(step1, step2, step3)
#write.csv(route_info, file = "/Volumes/GoogleDrive/My Drive/Laksh I project/design & data/Data Entry/Laksh R files/Panicker_2019_LD_analysis_manuscript_link/Sightings and effort for each route.csv")



THE END

LS0tCnRpdGxlOiAiQ2V0YWNlYW4gZGlzdHJpYnV0aW9uIGFuZCBkaXZlcnNpdHkgaW4gTGFrc2hhZHdlZXAgSXNsYW5kcywgSW5kaWEgdXNpbmcgYSBwbGF0Zm9ybSBvZiBvcHBvcnR1bml0eTogT2N0b2JlciAyMDE1IHRvIEFwcmlsIDIwMTYgLSBEYXRhIEFuYWx5c2lzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyMgQXV0aG9yIGluZm9ybWF0aW9uOgoKRGF0ZTogIjkvMjIvMjAxOSIKCkF1dGhvciAoYW5hbHlzaXMpOiBEaXZ5YSBQYW5pY2tlcgoKU3R1ZHk6IENldGFjZWFuIGRpc3RyaWJ1dGlvbiBhbmQgZGl2ZXJzaXR5IGluIExha3NoYWR3ZWVwIElzbGFuZHM6IE9jdG9iZXIgMjAxNSB0byBBcHJpbCAyMDE2CgpGdW5kaW5nOiBSdWZmb3JkIFNtYWxsIEdyYW50cyBmb3IgTmF0dXJlIENvbnNlcnZhdGlvbgoKSW5zdGl0dXRpb25zOiBVbml2ZXJzaXR5IG9mIFdhc2hpbmd0b24sIE5hdGlvbmFsIENlbnRyZSBmb3IgQmlvbG9naWNhbCBTY2llbmNlcywgQ2VudHJlIGZvciBXaWxkbGlmZSBTdHVkaWVzCgpFbWFpbCBmb3IgY29ycmVzcG9uZGVuY2U6IGRwYW5pY0B1dy5lZHUKCkNpdGF0aW9uOiBQYW5pY2tlciwgRC4sIFN1dGFyaWEsIEQuLCBLdW1hciwgQS4sIFN0YWZmb3JkLCBLLiAoMjAxOSkgJ0NldGFjZWFuIGRpc3RyaWJ1dGlvbiBhbmQgZGl2ZXJzaXR5IGluIExha3NoYWR3ZWVwIElzbGFuZHMsIEluZGlhIHVzaW5nIHBsYXRmb3JtcyBvZiBvcHBvcnR1bml0eTogT2N0IDIwMTUgdG8gQXByIDIwMTYnLiBSZXNlYXJjaFdvcmtzLiBVbml2ZXJzaXR5IG9mIFdhc2hpbmd0b24uCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIyBDb3JyZXNwb25kaW5nIGRhdGFzZXRzOgoKRGF0YXNldCAqJ1Bhbmlja2VyX2V0X2FsXzIwMTlfc3VydmV5ZWZmb3J0ZGF0YXNldC5jc3YnKiBjb250YWlucyB0aGUgZWZmb3J0IGZvciBhbGwgdGhlIHN1cnZleXMuIFJlYWQgaW50byB0aGUgcHJvZ3JhbSBhcyAqJ2VmZmRhdCcqCgpEYXRhc2V0IConUGFuaWNrZXJfZXRfYWxfMjAxOV9jZXRhY2VhbmRhdGFzZXQuY3N2JyogaXMgdGhlIHNpZ2h0aW5ncyBkYXRhc2V0IHdoaWNoIGluY2x1ZGUgYm90aCBvbiBzdXJ2ZXkgZWZmb3J0IGFuZCBvcHBvcnR1bmlzdGljIHNpZ2h0aW5ncy4gVGhlIHNpZ2h0aW5ncyBkYXRhIHNldCBhbHNvIGluY2x1ZGUgdmFyaWFibGVzIHN1Y2ggYXMgZGVwdGggYXQgYm9hdCBsb2NhdGlvbiwgc2xvcGUsIGFzcGVjdCBhbmQgbmVhcmVzdCBkaXN0YW5jZSB0byBsYW5kLiBEZXB0aCB3YXMgb2J0YWluZWQgZnJvbSBHZW9NYXBBcHAgKFJ5YW4gZXQgYWwuIDIwMDkpLiBTbG9wZSwgYXNwZWN0IGFuZCBuZWFyZXN0IGRpc3RhbmNlIHRvIGxhbmQgd2FzIGNhbGN1bGF0ZWQgdXNpbmcgQXJjR0lTLiBUaGUgZmlsZSBpcyByZWFkIGludG8gdGhlIHByb2dyYW0gYXMgKidjZXRlbnZkYXQnKi4KCkRhdGFzZXQgKidQYW5pY2tlcl9ldF9hbF8yMDE5X2JlYXVmb3J0ZGF0YXNldC5jc3YnKiBpcyB0aGUgZGF0YXNldCB3aXRoIGNvcnJlc3BvbmRpbmcgYmVhdWZvcnQgc3RhdGVzLiBUaGlzIHNoZWV0IGhhcyB0aGUgZGlzdGFuY2UgY292ZXJlZCBpbiBlYWNoIGJlYXVmb3J0IHN0YXRlIHBlciBzZWFzb24sIHBlciByb3V0ZSwgcGVyIGRheS4gUmVhZCBpbnRvIHRoZSBwcm9ncmFtIGFzIConZWZmYmVhdWRpc3QnKgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyMgTmFtZXMgb2Ygc3Vic2V0cyBmcm9tIGRhdGEgY3N2IGZpbGVzIHdpdGhpbiB0aGlzIG5vdGVib29rOgoKMS4gKidpZGNldGVudmRhdCcqIGlzIHRoZSBzdWJzZXQgZm9yIGlkZW50aWZpZWQgc2lnaHRpbmdzIGluY2x1ZGluZyBvcHBvcnR1bmlzdGljIHNpZ2h0aW5ncy4KMi4gKidvbmNldGVudmRhdCcqIGlzIHRoZSBzdWJzZXQgZm9yIG9uIHN1cnZleSBlZmZvcnQgc2lnaHRpbmdzLgozLiAqJ2lkY2V0ZW52ZGF0c3RhdHMnKiBpcyB0aGUgc3Vic2V0IGZvciBpZGVudGlmaWVkIHNpZ2h0aW5ncyB3aXRoIHRoZSBleGNlcHRpb24gb2YgYmFsZWVuIHdoYWxlIGFuZCBweWdteSB3aGFsZSBzaWdodGluZ3MgYXMgbj0xLiBUaGlzIGZpbGUgaXMgdXNlZCBmb3IgYWxsIHN0YXRpc3RpY2FsIGFuYWx5c2lzLiAKNC4gKidjb21pZGNldGVudmRhdHN0YXRzJyogaXMgdGhlIHNpZ2h0aW5ncyBkYXRhIGZvciBpZGVudGlmaWVkIHNpZ2h0aW5ncyBvZiB0aHJlZSBvZiB0aGUgbW9zdCBjb21tb25seSBzaWdodGVkIHNwZWNpZXMgKHNwaW5ubmVyLCBib3R0bGVub3NlIGFuZCBwaWxvdCkuIAo1LiAqJ3JvdXRlbmFtZXMnKiBpcyBhIGRhdGFzZXQgY3JlYXRlZCBmb3IgYSBsaXN0IG9mIHN1cnZleSByb3V0ZXMgYW5kIGNvcnJlc3BvbmRpbmcgcm91dGUgbnVtYmVycy4KCl8qKk5vdGUqKl86IElmIHN1YnNldHMgaGF2ZSBpbnRlciBvciBuZSBhdCB0aGUgZW5kLCBpdCBjb3JyZXNwb25kcyB0byBpbnRlci1tb25zb29uIG9yIG5vcnRoZWFzdCBtb25zb29uIHNlYXNvbnMKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMjIFIgU2V0dXAKIyMjIyMgV29ya2luZyBkaXJlY3RvcnkgZm9yIFIgc3R1ZGlvLCBSZWFkaW5nIERhdGEgZmlsZXMgYW5kIERhdGEgcHJlcGFyYXRpb24KUnVuIGxpbmUgYnkgbGluZSB0byBhdm9pZCBtYXNraW5nIApgYGB7ciBzZXR1cH0KI2tuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UpCnJtKGxpc3QgPSBscygpKSAjIGNsZWFycyB3b3Jrc3BhY2UKCiMgV29ya2luZyBkaXJlY3Rvcnkgb24geW91ciBjb21wdXRlciEgQ0hBTkdFIEFTIFlPVSBORUVECiMgc2V0IHRoZSB3b3JraW5nIGRpcmVjdG9yeSB0byB5b3VyIGhvbWUgZGlyZWN0b3J5IHdoZXJlIGRhdGEgZmlsZXMgYXJlIHN0b3JlZApzZXR3ZCgiL1ZvbHVtZXMvR29vZ2xlRHJpdmUvTXkgRHJpdmUvTGFrc2ggSSBwcm9qZWN0L2Rlc2lnbiAmIGRhdGEvRGF0YSBFbnRyeS9MYWtzaCBSIGZpbGVzL1Bhbmlja2VyXzIwMTlfQ2V0YWNlYW5zX0xha3NoYWR3ZWVwLyIpIAoKIyBSZXF1aXJlZCBQYWNrYWdlcyBhbmQgbGlicmFyaWVzCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGdkYXRhKQpsaWJyYXJ5KHBsb3RyaXgpCmxpYnJhcnkocHN5Y2gpCmxpYnJhcnkoZGV2dG9vbHMpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoZ2dwbG90MikKCiMgUmVhZGluZyBpbiBkYXRhIGZpbGVzCmVmZmRhdDwtcmVhZC5jc3YoIlBhbmlja2VyX2V0X2FsXzIwMTlfc3VydmV5ZWZmb3J0ZGF0YXNldC5jc3YiLCBoZWFkZXIgPSBULCBzdHJpbmdzQXNGYWN0b3JzID0gRikgIyBlZmZvcnQgZGF0YXNldApjZXRlbnZkYXQ8LXJlYWQuY3N2KCJQYW5pY2tlcl9ldF9hbF8yMDE5X2NldGFjZWFuZGF0YXNldC5jc3YiLCBoZWFkZXIgPSBULCBzdHJpbmdzQXNGYWN0b3JzID0gRikgIyBjZXRhY2VhbiBkYXRhc2V0CmVmZmJlYXVkaXN0PC1yZWFkLmNzdigiUGFuaWNrZXJfZXRfYWxfMjAxOV9iZWF1Zm9ydGRhdGFzZXQuY3N2IiwgaGVhZGVyID0gVCwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpICMgYmVhdWZvcnQgZGF0YXNldAoKIyBEYXRhIHByZXBhcmF0aW9uIGZvciBhbmFseXNpcwoKIyBDcmVhdGluZyBhIGRhdGFzZXQgb2Ygcm91dGVuYW1lcyBhbmQgY29ycmVzcG9uZGluZyByb3V0ZSBudW1iZXJzCnJvdXRlbmFtZXM8LWRhdGEuZnJhbWUoKGMoMSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIpKSwoYygiQUdULUFLQyIsIktWVC1BR1QiLCJCVFItQUtDIiwiS1ZULUFLQyIsIkNIVC1BS0MiLCJLTFQtQUtDIiwiS1ZULUFORCIsIkJUUi1LVlQiLCJLTFQtQ0hUIiwiS1ZULUtMUCIsIkFNTi1LRFQiLCJLVlQtS0xUIikpKQpjb2xuYW1lcyhyb3V0ZW5hbWVzKSA8LSBjKCJyb3V0ZW5vIiwgInJvdXRlIikKCiMgQ3JlYXRpbmcgYSBzdWJzZXQgZm9yIHRoZSBpZGVudGlmaWVkIHNwZWNpZXMKaWRjZXRlbnZkYXQ8LXN1YnNldChjZXRlbnZkYXQsICFjZXRlbnZkYXQkc3BlY2llcyA9PSAiYmxhY2tmaXNoIiAmICFjZXRlbnZkYXQkc3BlY2llcyA9PSAidW5pZGRvbHBoaW4iICYgIWNldGVudmRhdCRzcGVjaWVzID09ICJ1bmlkY2V0IiAmICFjZXRlbnZkYXQkc3BlY2llcz09InVuaWRzbWFsbHdoYWxlIiAmICFjZXRlbnZkYXQkc3BlY2llcyA9PSAidW5pZHdoYWxlIiAmICFjZXRlbnZkYXQkc3BlY2llcyA9PSAidW5pZHNtYWxsZG9scGhpbiIgKQoKIyBDcmVhdGluZyBhIHN1YnNldCBmb3Igb24gc3VydmV5IGVmZm9ydCBzaWdodGluZ3MKb25jZXRlbnZkYXQ8LXN1YnNldChjZXRlbnZkYXQsICFjZXRlbnZkYXQkZWZmID09ICJvZmYiKQoKIyBSZW1vdmluZyBiYWxlZW4gYW5kIHBneW15a2lsbGVyIHdoYWxlIGZyb20gaWRlbnRpZmllZCBzcGVjaWVzIGFzIHNhbXBsZSBzaXplIGlzIDEgZm9yIHRoZXNlIHNwZWNpZXMgKFRoaXMgc3RlcCBuZWVkZWQgZm9yIHN0YXRzIGFuYWx5c2lzKQppZGNldGVudmRhdHN0YXRzPC1kcm9wLmxldmVscyhzdWJzZXQoaWRjZXRlbnZkYXQsIWlkY2V0ZW52ZGF0JHNwZWNpZXMgPT0gImJhbGVlbiIgJiAhaWRjZXRlbnZkYXQkc3BlY2llcyA9PSAicHlnbXlraWxsZXIiKSkKCiMgQ3JlYXRpbmcgYSBzdWJzZXQgZm9yIGlkZW50aWZpZWQgY29tbW9ubHkgc2lnaHRlZCBzcGVjaWVzIChuPjEwIG5hbWVseSwgc3Bpbm5lciBkb2xwaGluLCBib3R0bGVub3NlIGRvbHBoaW4gYW5kIHBpbG90IHdoYWxlKQpjb21pZGNldGVudmRhdHN0YXRzPC1yYmluZChzdWJzZXQoaWRjZXRlbnZkYXQsIGlkY2V0ZW52ZGF0JHNwZWNpZXMgPT0gInNwaW5uZXIiKSwgc3Vic2V0KGlkY2V0ZW52ZGF0LCBpZGNldGVudmRhdCRzcGVjaWVzID09ICJib3R0bGVub3NlIiksIHN1YnNldChpZGNldGVudmRhdCwgaWRjZXRlbnZkYXQkc3BlY2llcyA9PSAicGlsb3QiKSkKCiMgQ3JlYXRpbmcgYSBzdWJzZXQgZm9yIGlkZW50aWZpZWQgc3BlY2llcyBpbiBub3J0aGVhc3QgbW9uc29vbiBzZWFzb24KaWRjZXRlbnZkYXRzdGF0c25lPC1zdWJzZXQoaWRjZXRlbnZkYXRzdGF0cywgaWRjZXRlbnZkYXRzdGF0cyRzZWFzID09ICduZScpCgojIENyZWF0aW5nIGEgc3Vic2V0IGZvciBpZGVudGlmaWVkIHNwZWNpZXMgaW4gbm9ydGhlYXN0IG1vbnNvb24gc2Vhc29uIGZvciBjb21tb25seSBzaWdodGVkIHNwZWNpZXMgKG4+MTAgbmFtZWx5LCBzcGlubmVyIGRvbHBoaW4sIGJvdHRsZW5vc2UgZG9scGhpbiBhbmQgcGlsb3Qgd2hhbGUpCmNvbWlkY2V0ZW52ZGF0c3RhdHNuZTwtc3Vic2V0KGNvbWlkY2V0ZW52ZGF0c3RhdHMsIGNvbWlkY2V0ZW52ZGF0c3RhdHMkc2VhcyA9PSAnbmUnKQoKIyBDcmVhdGluZyBhIHN1YnNldCBmb3IgaWRlbnRpZmllZCBzcGVjaWVzIGluIGludGVyIG1vbnNvb24gc2Vhc29uCmlkY2V0ZW52ZGF0c3RhdHNpbnRlcjwtc3Vic2V0KGlkY2V0ZW52ZGF0c3RhdHMsIGlkY2V0ZW52ZGF0c3RhdHMkc2VhcyA9PSAnaW50ZXInKQoKIyBDcmVhdGluZyBhIHN1YnNldCBmb3IgaWRlbnRpZmllZCBzcGVjaWVzIGluIGludGVyIG1vbnNvb24gc2Vhc29uIGZvciBjb21tb25seSBzaWdodGVkIHNwZWNpZXMgKG4+MTAgbmFtZWx5LCBzcGlubmVyIGRvbHBoaW4sIGJvdHRsZW5vc2UgZG9scGhpbiBhbmQgcGlsb3Qgd2hhbGUpCmNvbWlkY2V0ZW52ZGF0c3RhdHNpbnRlcjwtc3Vic2V0KGNvbWlkY2V0ZW52ZGF0c3RhdHMsIGNvbWlkY2V0ZW52ZGF0c3RhdHMkc2VhcyA9PSAnaW50ZXInKQoKcHJpbnQgKCJTRVRVUCBET05FIEFORCBEQVRBIFJFQUQgSU5UTyBSIikKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIyBUYWJsZSBvZiBDb250ZW50cwoKW1N0cnVjdHVyZSBvZiBkYXRhXSAKCi0gKltFZmZvcnQgZGF0YXNldCAoZWZmZGF0KV0qCi0gKltDZXRhY2VhbiBkYXRhc2V0IChjZXRlbnZkYXQpXSoKCltOby4gb2Ygc2lnaHRpbmdzLCBzdXJ2ZXkgZWZmb3J0IGFuZCBiZWF1Zm9ydCBzdGF0ZXNdIAoKLSAqW1N1cnZleSBlZmZvcnRdKgotICpbTm8uIG9mIHNpZ2h0aW5nc10qCi0gKltCZWF1Zm9ydCBzdGF0ZXMgcmVjb3JkZWQgZHVyaW5nIHN1cnZleSBlZmZvcnRdKgoKW0VuY291bnRlciByYXRlc10gCgotICpbT3ZlcmFsbCBFbmNvdW50ZXIgcmF0ZV0qCi0gKltSb3V0ZS13aXNlIGVuY291bnRlciByYXRlIChwZXIgMTAwIGttKV0qCgpbU3BlY2llcyBsaXN0XSAKCi0gKltTcGVjaWVzIGxpc3QgYW5kIG1vc3QgY29tbW9ubHkgc2lnaHRlZF0qCi0gKltTZWFzb24td2lzZSBzcGVjaWVzIGxpc3RzXSoKCltHcm91cCBzaXplcyAoVGFibGUgMSldIAoKLSAqW0F2ZXJhZ2UgZ3JvdXAgc2l6ZSwgc3RhbmRhcmQgZXJyb3JzIGFuZCBtaW5pbXVtIGFuZCBtYXhpbXVtIGdyb3VwIHNpemVzIGZvciBlYWNoIHNwZWNpZXNdKgoKW1NlYWZsb29yIGRlcHRocyBhdCBzaWdodGluZyBsb2NhdGlvbnMoVGFibGUgMSldIAoKLSAqW0F2ZXJhZ2UgZGVwdGhzLCBzdGFuZGFyZCBlcnJvcnMgYW5kIG1pbmltdW0gYW5kIG1heGltdW0gZ3JvdXAgc2l6ZXMgZm9yIGVhY2ggc3BlY2llc10qCgpbQ2V0YWNlYW4gc2lnaHRpbmdzIGFjcm9zcyBzZWFzb24gKEZpZ3VyZSA0KV0KCi0gKltCYXJwbG90IG9mIG9ic2VydmVkIGFuZCBleHBlY3RlZCBjZXRhY2VhbiBzaWdodGluZ3MgYWNyb3NzIHNlYXNvbiAob24gc3VydmV5IGVmZm9ydCldKgotICpbTm9uIHBhcmFtZXRlcmljIHN0YXRpc3RpY2FsIHRlc3QgLSBDaGktU3F1YXJlIEdvb2RuZXNzIG9mIEZpdF0qCgpbQ2V0YWNlYW4gc3BlY2llcyBhY3Jvc3MgZGlzdGFuY2UgdG8gbmVhcmVzdCBsYW5kbWFzc10KCi0gKltCb3hwbG90IG9mIGRpc3RhbmNlIHRvIG5lYXJlc3QgbGFuZG1hc3MgZm9yIGFsbCBzcGVjaWVzXSoKLSAqW05vbiBwYXJhbWV0ZXJpYyBzdGF0aXN0aWNhbCB0ZXN0IC0gS3J1c2thbC1XYWxsaXMgdGVzdF0qCgpbQ2V0YWNlYW4gc3BlY2llcyBhY3Jvc3Mgc2VhZmxvb3Igc2xvcGUgZ3JhZGllbnRdIAoKLSAqW0JveHBsb3Qgb2Ygc2xvcGUgZGlzdHJpYnV0aW9uIGZvciBhbGwgc3BlY2llc10qCi0gKltOb24gcGFyYW1ldGVyaWMgc3RhdGlzdGljYWwgdGVzdCAtIEtydXNrYWwtV2FsbGlzIHRlc3RdKgoKW0NldGFjZWFuIHNwZWNpZXMgYWNyb3NzIHNlYWZsb29yIGRlcHRoXSAKCi0gKltCb3hwbG90IGJldHdlZW4gY2V0YWNlYW4gc3BlY2llcyBhbmQgc2VhZmxvb3IgZGVwdGhdKgotICpbTm9uIHBhcmFtZXRlcmljIHN0YXRpc3RpY2FsIHRlc3Qgc3BlY2llcyBhbmQgZGVwdGggLSBLcnVza2FsLVdhbGxpcyB0ZXN0XSoKCltQbG90IG9mIGNldGFjZWFuIHNwZWNpZXMgYWNyb3NzIG5lYXJlc3QgZGlzdGFuY2UgdG8gbGFuZCBhbmQgc2xvcGUgZ3JhZGllbnQgKEZpZ3VyZSA1KV0gCgo8YnI+CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIFN0cnVjdHVyZSBvZiBkYXRhCgpfKipOb3RlKipfOiBDb2x1bW4gaGVhZGVyIGRldGFpbHMgYXJlIGdpdmVuIGluIFJlYWRNZSBmaWxlLiAKCiMjIyMgRWZmb3J0IGRhdGFzZXQgKGVmZmRhdCkKYGBge3Igc3RydWN0dXJlIGVmZm9ydCBkYXRhc2V0fQojIHN0cnVjdHVyZSBvZiBlZmZvcnQKZWZmZGF0JGRhdGU8LWFzLkRhdGUoZWZmZGF0JGRhdGUsICIlbS8lZC8leSIpICMgc2V0dGluZyBkYXRhIGZvcm1hdApzdHIoZWZmZGF0KQpgYGAKCiMjIyMgQ2V0YWNlYW4gZGF0YXNldCAoY2V0ZW52ZGF0KQpgYGB7ciBzdHJ1Y3R1cmUgc2lnaHRpbmdzIGRhdGFzZXR9CnN0cihjZXRlbnZkYXQpCmBgYAoKPGJyPgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyBOby4gb2Ygc2lnaHRpbmdzLCBzdXJ2ZXkgZWZmb3J0IGFuZCBiZWF1Zm9ydCBzdGF0ZXMKClJlZmVyIHRvIHN1YmhlYWRpbmcgb2YgcmVzdWx0cyBzZWN0aW9uIG9mIG1hbnVzY3JpcHQKCiMjIyMgU3VydmV5IGVmZm9ydApgYGB7ciBUb3RhbCBzdXJ2ZXkgZWZmb3J0IGRldGFpbHN9CiMgVG90YWwgaG91cnMgc3BlbnQgb24gc3VydmV5IGVmZm9ydAp0b3RlZmZob3Vyczwtc3VtKGVmZmRhdCRoci5kZWMpCnBhc3RlICgiVG90YWwgaG91cnMgc3BlbnQgb24gc3VydmV5IGVmZm9ydCA9IiwgdG90ZWZmaG91cnMpCgojIFRvdGFsIGRpc3RhbmNlIGNvdmVyZWQgZHVyaW5nIHN1cnZleSBlZmZvcnQKdG90ZWZmZGlzdDwtc3VtKGVmZmRhdCRkaXN0KQpwYXN0ZSgiVG90YWwgZGlzdGFuY2UgKGttKSBjb3ZlcmVkIGR1cmluZyBzdXJ2ZXkgZWZmb3J0ID0gIiwgdG90ZWZmZGlzdCkKCiMgTnVtYmVyIG9mIHN1cnZleXMgaG91cnMgZWFjaCBkYXkKcGFzdGUoIkF2ZXJhZ2UgbnVtYmVyIG9mIGhvdXJzIG9uIHN1cnZleSBlZmZvcnQgcGVyIGRheSA9ICIsIHJvdW5kKG1lYW4oZWZmZGF0JGhyLmRlYyksMiksICIrLy0iLCByb3VuZChzdGQuZXJyb3IoZWZmZGF0JGhyLmRlYyksMSkpCnBhc3RlKCJNaW4gaG91cnMgb24gc3VydmV5IGVmZm9ydCBpbiBhIGRheSA9ICIsIHJvdW5kKG1pbihlZmZkYXQkaHIuZGVjKSwxKSkKcGFzdGUoIk1heCBob3VycyBvbiBzdXJ2ZXkgZWZmb3J0IGluIGEgZGF5ID0gIiwgcm91bmQobWF4KGVmZmRhdCRoci5kZWMpLDEpKQpgYGAKCiMjIyMgTm8uIG9mIHNpZ2h0aW5ncwoKYGBge3IgTm8uIG9mIHNpZ2h0aW5nc30KIyBub3RlOiBPZmYgZWZmb3J0IGFuZCBvcHBvcnVuaXN0aWMgaXMgdGhlIHNhbWUhCiMgVG90YWwgbnVtYmVyIG9mIGNldGFjZWFuIGdyb3VwIHNpZ2h0aW5ncyAoaW5jbHVkaW5nIG9wcG9ydHVuaXN0aWMgc2lnaHRpbmdzKQpwYXN0ZSAoIlRvdGFsIG5vIG9mIGNldGFjZWFuIGdyb3VwIHNpZ2h0aW5ncyAob24gYW5kIG9mZiBzdXJ2ZXkgZWZmb3J0KSA9IiwgbnJvdyhjZXRlbnZkYXQpKQoKIyBObzogb2YgY2V0YWNlYW4gZ3JvdXAgc2lnaHRpbmdzIChvbiBzdXJ2ZXkgZWZmb3J0KQpwYXN0ZSAoIk5vLiBvZiBjZXRhY2VhbiBncm91cCBzaWdodGluZ3Mgb24gc3VydmV5IGVmZm9ydCA9IiwgbGVuZ3RoKHdoaWNoKGNldGVudmRhdCA9PSAib24iKSkpCgojIE5vOiBvZiBjZXRhY2VhbiBncm91cCBzaWdodGluZ3MgKG9mZiBzdXJ2ZXkgZWZmb3J0L29wcG9ydHVuaXN0aWMpCnBhc3RlICgiTm8uIG9mIGNldGFjZWFuIGdyb3VwIHNpZ2h0aW5ncyBvZmYgc3VydmV5IGVmZm9ydCA9IiwgbGVuZ3RoKHdoaWNoKGNldGVudmRhdCA9PSAib2ZmIikpKQoKIyBUb3RhbCBudW1iZXIgb2YgaWRlbnRpZmllZCBjZXRhY2VhbiBncm91cHMgKG9uIGFuZCBvZmYgc3VydmV5IGVmZm9ydCkKcGFzdGUgKCJUb3RhbCBubyBvZiBpZGVudGlmaWVkIGNldGFjZWFuIGdyb3VwcyAob24gYW5kIG9mZiBzdXJ2ZXkgZWZmb3J0KSA9IiwgbnJvdyhpZGNldGVudmRhdCkpCgojIE51bWJlciBvZiBpZGVudGlmaWVkIGNldGFjZWFuIGdyb3VwcyAob24gc3VydmV5IGVmZm9ydCkKcGFzdGUgKCJOby4gb2YgaWRlbnRpZmllZCBjZXRhY2VhbiBncm91cHMgb24gc3VydmV5IGVmZm9ydCA9IiwgbGVuZ3RoKHdoaWNoKGlkY2V0ZW52ZGF0ID09ICJvbiIpKSkKYGBgCgojIyMjIEJlYXVmb3J0IHN0YXRlcyByZWNvcmRlZCBkdXJpbmcgc3VydmV5IGVmZm9ydAoKVGFibGUgb2YgZGlzdGFuY2UgKGttKSBmb3IgZWFjaCBiZWF1Zm9ydCBzdGF0ZQpgYGB7ciBCZWF1Zm9ydCBpbiBLbX0KYmVhdS50YWJsZTwtdGFwcGx5KChlZmZiZWF1ZGlzdCREaXN0YW5jZSksKGVmZmJlYXVkaXN0JEJlYXVmb3J0KSxGVU49c3VtKQpiZWF1LnRhYmxlCmBgYAoKUGVyY2VudGFnZXMgb2YgdGhlIGRpc3RhbmNlcyB3aXRoIHJlc3BlY3QgdG8gdGhlIHRvdGFsIGRpc3RhbmNlIHRyYXZlbGVkIGluIGEgcGFydGljdWxhciBiZWF1Zm9ydCBzdGF0ZSAoZS5nLiA4MC42MyUgZGlzdGFuY2UgdHJhdmVsZWQgaW4gMC0zIHN0YXRlLCBub3RlIHRoYXQgdGhpcyBpbmNsdWRlcyBub3QganVzdCAwIGJ1dCAwLTMsIDE1LjUlIGluIGJlYXVmb3J0IDQsIDIuOTYlIGluIGJlYXVmb3J0IDUgYW5kIDAuODklIGluIGJlYXVmb3J0IDYpCmBgYHtyIEJlYXVmb3J0IFBlcmNlbnRhZ2VzfQpiZWF1Lm9uZS50d28udGhyZWUucGVyY2VudDwtcm91bmQoKChiZWF1LnRhYmxlWzFdK2JlYXUudGFibGVbMl0rYmVhdS50YWJsZVszXStiZWF1LnRhYmxlWzRdKS9zdW0oYmVhdS50YWJsZSkpKjEwMCwxKQpiZWF1Lm9uZS50d28udGhyZWUucGVyY2VudApiZWF1LmZvdXIucGVyY2VudDwtcm91bmQoKChiZWF1LnRhYmxlWzVdKS9zdW0oYmVhdS50YWJsZSkpKjEwMCwxKQpiZWF1LmZvdXIucGVyY2VudApiZWF1LmZpdmUucGVyY2VudDwtcm91bmQoKChiZWF1LnRhYmxlWzZdKS9zdW0oYmVhdS50YWJsZSkpKjEwMCwxKQpiZWF1LmZpdmUucGVyY2VudApiZWF1LnNpeC5wZXJjZW50PC1yb3VuZCgoKGJlYXUudGFibGVbN10pL3N1bShiZWF1LnRhYmxlKSkqMTAwLDEpCmJlYXUuc2l4LnBlcmNlbnQKcm0oYmVhdS50YWJsZSwgYmVhdS5vbmUudHdvLnRocmVlLnBlcmNlbnQsIGJlYXUuZm91ci5wZXJjZW50LCBiZWF1LmZpdmUucGVyY2VudCwgYmVhdS5zaXgucGVyY2VudCkKYGBgCgo8YnI+CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIEVuY291bnRlciByYXRlcwoKIyMjIyMgT3ZlcmFsbCBFbmNvdW50ZXIgcmF0ZQpgYGB7ciBlbmMgcmF0ZS9kaXN0IHRvdH0KdG90ZW5jcmF0ZWRpc3Q8LXJvdW5kICgoKG5yb3cob25jZXRlbnZkYXQpL3RvdGVmZmRpc3QpKjEwMCksMikKcGFzdGUoIk92ZXJhbGwgZW5jb3VudGVyIHJhdGUgKHBlciAxMDBrbSkgb2YgY2V0YWNlYW4gZ3JvdXBzIGZvciB0aGUgZW50aXJlIHN0dWR5IGFyZWEgPSIsIHRvdGVuY3JhdGVkaXN0KQpgYGAKCiMjIyMjIFJvdXRlLXdpc2UgZW5jb3VudGVyIHJhdGUgKHBlciAxMDAga20pCgpgYGB7ciBlbmMgcmF0ZS8xMDBrbSByb3V0ZXN9CnN0ZXAxPC1hZ2dyZWdhdGUoZWZmZGF0JGRpc3QgfiBlZmZkYXQkcm91dGVubywgRlVOPXN1bSkgIyBleHRyYWN0aW5nIHN1bSBvZiBkaXN0YW5jZXMgZm9yIHJvdXRlcwpzdGVwMjwtYWdncmVnYXRlKGVmZmRhdCRuby5zaWdodCB+IGVmZmRhdCRyb3V0ZW5vLCBGVU49c3VtKSAjIGV4dHJhY3Rpbmcgc3VtIG9mIHNpZ2h0aW5ncyBmb3Igcm91dGVzCnN0ZXAzPC1zdGVwMiRgZWZmZGF0JG5vLnNpZ2h0YC9zdGVwMSRgZWZmZGF0JGRpc3RgICMgZW5jcmF0ZS9rbSBmb3IgZWFjaCByb3V0ZSA9IHNpZ2h0aW5nL2Rpc3RhbmNlIGZvciBlYWNoIHJvdXRlLCBzdGVwIGRhdGFmcmFtZXMgY2FuIGJlIHJlbW92ZWQgZnJvbSB3b3Jrc3BhY2UgYWZ0ZXIgcnVubmluZy4gCnJvdXRlX2VuY3JhdGU8LXJvdW5kKHN0ZXAzKjEwMCwyKSAjIGVuYyByYXRlL2Rpc3RhbmNlICogMTAwIGttcyBhbmQgcm91bmRlZCB0byB0d28gZGVjaW1hbCBwb2ludHMKcm0oc3RlcDEsIHN0ZXAyLCBzdGVwMykKcm91dGVfZW5jcmF0ZSA8LSBkYXRhLmZyYW1lKHJvdXRlbmFtZXMscm91dGVfZW5jcmF0ZSkKcm91dGVfZW5jcmF0ZSAKYGBgCgo8YnI+Ci0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMgU3BlY2llcyBsaXN0CgpSZWZlciB0byB0aGUgc2Vjb25kIHN1YmhlYWRpbmcgb2YgdGhlIHJlc3VsdHMgc2VjdGlvbgoKIyMjIyBTcGVjaWVzIGxpc3QgYW5kIG1vc3QgY29tbW9ubHkgc2lnaHRlZAoKRWlnaHQgdG9vdGhlZCB3aGFsZSBhbmQgb25lIGJhbGVlbiB3aGFsZSB3ZXJlIGVuY291bnRlcmVkLgoqTm90ZSo6ICpCYWxhZW5vcHRlcmEqIHNwIGlkZW50aWZpZWQgdGlsbCBnZW51cywgKlR1cnNpb3BzKiBzcCAoaW5jbHVkZXMgYWR1bmN1cyBhbmQgdHJ1bmNhdHVzKQpgYGB7ciBkaXZlcnNpdHl9CgpzcGVjaWVzPC0gYygiQmFsZWVuIHdoYWxlIiwgIkJsYWNrZmlzaCIsICJCb3R0bGVub3NlIGRvbHBoaW4iLCAiRmFsc2Uga2lsbGVyIHdoYWxlIiwgIlBpbG90IHdoYWxlIiwgIlB5Z215IGtpbGxlciB3aGFsZSIsICJSaXNzbydzIGRvbHBoaW4iLCAiU3Bpbm5lciBkb2xwaGluIiwiU3BvdHRlZCBkb2xwaGluIiwgIlN0cmlwZWQgZG9scGhpbiIsICJVbmlkZW50aWZpZWQgY2V0YWNlYW4iLCAiVW5pZGVudGlmaWVkIGRvbHBoaW4iLCAiVW5pZGVudGlmaWVkIHNtYWxsIGRvbHBoaW4iLCAiVW5pZGVudGlmaWVkIHNtYWxsIHdoYWxlIiwgIlVuaWRlbnRpZmllZCB3aGFsZSIpCgpmcmVxPC10YWJsZShjZXRlbnZkYXQkc3BlY2llcykKZnJlcTwtYXMudmVjdG9yKGZyZXEpCnNwZWNpZXNfY291bnRzPC1kYXRhLmZyYW1lKHNwZWNpZXMsIGZyZXEpCnNwZWNpZXNfY291bnRzCnJtKGZyZXEpCmBgYAoKIyMjIyBTZWFzb24td2lzZSBzcGVjaWVzIGxpc3RzCgpCYWxlZW47IEJhbGVlbiB3aGFsZTsgKkJhbGFlbm9wdGVyYSBzcCosIEJvdHRsZW5vc2U7ICpUdXJzaW9wcyBzcCosIEZhbHNlIEtpbGxlciB3aGFsZTsgKlBzZXVkb3JjYSBjcmFzc2lkZW5zKiwgcGlsb3Q7ICpHbG9iaWNlcGhhbGEgbWFjaHJvcmh5bmNodXMqLCBweWdteWtpbGxlcjsgKkZlcmVzYSBhdHRlbnVhdGEqLCByaXNzbzsgKkdyYW1wdXMgZ3Jpc2V1cyosIHNwaW5uZXI7ICogU3RlbmVsbGEgbG9uZ2lyb3N0cmlzKiwgc3BvdHRlZDsgKlN0ZW5lbGxhIGF0dGVudWF0YSosIHN0cmlwZWQ7ICpTdGVuZWxsYSBjb3J1bGVvYWxiYSosIHVuaWRjZXQ7IHVuaWRlbnRpZmllZCBjZXRhY2VhbiwgdW5pZGRvbHBoaW47IHVuaWRlbnRpZmllZCBkb2xwaGluLCB1bmlkc21hbGxkb2xwaGluOyB1bmlkZW50aWZpZWQgc21hbGwgZG9scGhpbiwgdW5pZHNtYWxsd2hhbGU7IHVuaWRlbnRpZmllZCBzbWFsbCB3aGFsZSwgdW5pZHdoYWxlOyB1bmlkZW50aWZpZWQgd2hhbGUuIAoKU3BlY2llcyBzaWdodGVkIGR1cmluZyB0aGUgbm9ydGhlYXN0IG1vbnNvb24gc2Vhc29uCmBgYHtyIHNwcyBkaXZlcnNpdHkgbmV9CiMgTm86IG9mIHNwZWNpZXMgaW4gbmUgbW9uc29vbiBzZWFzb24KdGFibGUoaWRjZXRlbnZkYXRzdGF0c25lJHNwZWNpZXMpCmBgYAoKU3BlY2llcyBzaWdodGVkIGR1cmluZyB0aGUgaW50ZXIgbW9uc29vbiBzZWFzb24KYGBge3Igc3BzIGRpdmVyc2l0eSBpbnRlcn0KIyBObzogb2Ygc3BlY2llcyBpbiBpbnRlciBtb25zb29uIHNlYXNvbgp0YWJsZShpZGNldGVudmRhdHN0YXRzaW50ZXIkc3BlY2llcykKYGBgCgo8YnI+CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIEdyb3VwIHNpemVzIChUYWJsZSAxKQoKIyMjIyBBdmVyYWdlIGdyb3VwIHNpemUsIHN0YW5kYXJkIGVycm9ycyBhbmQgbWluaW11bSBhbmQgbWF4aW11bSBncm91cCBzaXplcyBmb3IgZWFjaCBzcGVjaWVzCgpgYGB7ciBtZWFuIGdyb3VwIHNpemUgLSBzcGVjaWVzIHdpc2V9Cm1lYW5ncnBzaXplPC1yb3VuZCh0YXBwbHkoY2V0ZW52ZGF0JGdycHNpemUsY2V0ZW52ZGF0JHNwZWNpZXMsIG1lYW4sIG5hLnJtID0gVFJVRSksMikKbWVhbmdycHNpemU8LWFzLnZlY3RvcihtZWFuZ3Jwc2l6ZSkKU0VncnBzaXplPC1yb3VuZCh0YXBwbHkoY2V0ZW52ZGF0JGdycHNpemUsY2V0ZW52ZGF0JHNwZWNpZXMsIHN0ZC5lcnJvciwgbmEucm0gPSBUUlVFKSwyKQpTRWdycHNpemU8LWFzLnZlY3RvcihTRWdycHNpemUpClNFZ3Jwc2l6ZTwtcm91bmQoU0VncnBzaXplLDEpCm1pbmdycHNpemU8LXRhcHBseShjZXRlbnZkYXQkZ3Jwc2l6ZSxjZXRlbnZkYXQkc3BlY2llcywgbWluLCBuYS5ybSA9IFRSVUUpCm1pbmdycHNpemU8LWFzLnZlY3RvcihtaW5ncnBzaXplKQptYXhncnBzaXplPC10YXBwbHkoY2V0ZW52ZGF0JGdycHNpemUsY2V0ZW52ZGF0JHNwZWNpZXMsIG1heCwgbmEucm0gPSBUUlVFKQptYXhncnBzaXplPC1hcy52ZWN0b3IobWF4Z3Jwc2l6ZSkKc3BlY2llc19ncnBzaXplPC1kYXRhLmZyYW1lKHNwZWNpZXMsIG1lYW5ncnBzaXplLCBTRWdycHNpemUsIG1pbmdycHNpemUsIG1heGdycHNpemUpCnNwZWNpZXNfZ3Jwc2l6ZTwtc3BlY2llc19ncnBzaXplWzE6MTAsXQpzcGVjaWVzX2dycHNpemUKcm0obWVhbmdycHNpemUsIFNFZ3Jwc2l6ZSwgbWluZ3Jwc2l6ZSwgbWF4Z3Jwc2l6ZSkKYGBgCgoKPGJyPgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIFNlYWZsb29yIGRlcHRocyBhdCBzaWdodGluZyBsb2NhdGlvbnMoVGFibGUgMSkKCiMjIyMgQXZlcmFnZSBkZXB0aCBmb3IgY2V0YWNlYW4gc2lnaHRpbmdzIGluIHRoZSBlbnRpcmUgc3R1ZHkgYXJlYSAoaW4gbWV0cmVzKQoKYGBge3IgZGVwdGggdG90YWx9CnBhc3RlKCJBdmVyYWdlIGRlcHRoID0iLCByb3VuZChtZWFuKGNldGVudmRhdCRkZXB0aCksMiksICIrLy0iICxyb3VuZChzdGQuZXJyb3IoY2V0ZW52ZGF0JGRlcHRoKSwyKSkKcGFzdGUoIk1pbmltdW0gZGVwdGggPSIsIHJvdW5kKG1pbihjZXRlbnZkYXQkZGVwdGgpLDIpKQpwYXN0ZSgiTWF4aW11bSAgZGVwdGggPSIsIHJvdW5kKG1heChjZXRlbnZkYXQkZGVwdGgpLDIpKQpgYGAKCiMjIyMgQXZlcmFnZSBkZXB0aHMsIHN0YW5kYXJkIGVycm9ycyBhbmQgbWluaW11bSBhbmQgbWF4aW11bSBncm91cCBzaXplcyBmb3IgZWFjaCBzcGVjaWVzCmBgYHtyIGRlcHRoIHNwZWNpZXMgbWVhbn0KbWVhbmRlcHRoPC1yb3VuZCh0YXBwbHkoY2V0ZW52ZGF0JGRlcHRoLGNldGVudmRhdCRzcGVjaWVzLCBtZWFuLCBuYS5ybSA9IFRSVUUpLDIpCm1lYW5kZXB0aDwtYXMudmVjdG9yKG1lYW5kZXB0aCkKU0VkZXB0aDwtcm91bmQodGFwcGx5KGNldGVudmRhdCRkZXB0aCxjZXRlbnZkYXQkc3BlY2llcywgc3RkLmVycm9yLCBuYS5ybSA9IFRSVUUpLDIpClNFZGVwdGg8LWFzLnZlY3RvcihTRWRlcHRoKQptaW5kZXB0aDwtdGFwcGx5KGNldGVudmRhdCRkZXB0aCxjZXRlbnZkYXQkc3BlY2llcywgbWluLCBuYS5ybSA9IFRSVUUpCm1pbmRlcHRoPC1hcy52ZWN0b3IobWluZGVwdGgpCm1heGRlcHRoPC10YXBwbHkoY2V0ZW52ZGF0JGRlcHRoLGNldGVudmRhdCRzcGVjaWVzLCBtYXgsIG5hLnJtID0gVFJVRSkKbWF4ZGVwdGg8LWFzLnZlY3RvcihtYXhkZXB0aCkKc3BlY2llc19kZXB0aDwtZGF0YS5mcmFtZShzcGVjaWVzLCBtZWFuZGVwdGgsIFNFZGVwdGgsIG1pbmRlcHRoLCBtYXhkZXB0aCkKc3BlY2llc19kZXB0aDwtc3BlY2llc19kZXB0aFsxOjEwLF0Kc3BlY2llc19kZXB0aApybShtYXhkZXB0aCwgbWVhbmRlcHRoLCBtaW5kZXB0aCwgU0VkZXB0aCkKYGBgCgo8YnI+CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIENldGFjZWFuIHNpZ2h0aW5ncyBhY3Jvc3Mgc2Vhc29uIChGaWd1cmUgNCkKCkNldGFjZWFuIHNpZ2h0aW5ncyBpbiBub3J0aGVhc3QgbW9uc29vbiBhbmQgaW50ZXIgbW9uc29vbiBzZWFzb24gKG9ubHkgb24gc3VydmV5IGVmZm9ydCkKCmBgYHtyIHNlYXNvbiBhbGwgc2lnaHQgb24gZWZmb3J0fQojIG9uIGVmZm9ydCBzaWdodGluZ3MKdGFibGUob25jZXRlbnZkYXQkc2VhcykKYGBgCgpFZmZvcnQgKGluIGttKSBhY3Jvc3Mgc2Vhc29uCgpgYGB7ciBFZmZvcnQgYWNyb3NzIHNlYXNvbn0KCiMgRGlzdGFuY2VzIChlZmZvcnQpIGluIGVhY2ggc2Vhc29uCnRlc3Q8LXN1YnNldChlZmZkYXQsIGVmZmRhdCRzZWFzID09ICJuZSIpCnRlc3QyPC1zdWJzZXQoZWZmZGF0LCAhZWZmZGF0JHNlYXMgPT0gIm5lIikKcGFzdGUoIkRpc3QgKGttKSBpbiBub3J0aCBlYXN0IG1vbnNvb24gPSAiLCBzdW0odGVzdCRkaXN0KSwgImFuZCBEaXN0IChrbSkgaW4gaW50ZXIgbW9uc29vbiA9ICIsIHN1bSh0ZXN0MiRkaXN0KSkKCiMgUHJvcHJvdGlvbiBvZiBlZmZvcnQgaW4gZWFjaCBzZWFzb24KcGFzdGUoIlByb3BvcnRpb24gdHJhdmVsZWQgaW4gbm9ydGggZWFzdCBtb25zb29uID0gIiwgcm91bmQoKHN1bSh0ZXN0JGRpc3QpL3RvdGVmZmRpc3QpKjEwMCwyKSwgIiUiLCAiYW5kIFByb3BvcnRpb24gdHJhdmVsZWQgaW4gaW50ZXIgbW9uc29vbiA9ICIsIHJvdW5kKChzdW0odGVzdDIkZGlzdCkvdG90ZWZmZGlzdCkqMTAwLDIpLCAiJSIpCgpybSh0ZXN0MikKcm0odGVzdCkKYGBgCgoKIyMjIyMgQmFycGxvdCBvZiBvYnNlcnZlZCBhbmQgZXhwZWN0ZWQgY2V0YWNlYW4gc2lnaHRpbmdzIGFjcm9zcyBzZWFzb24gKG9uIHN1cnZleSBlZmZvcnQpCgpFeHBlY3RlZCByYXRpbydzIGNvcnJlc3BvbmQgdG8gZGlzdGFuY2UgdHJhdmVsZWQgaW4gYSBzZWFzb24KCmBgYHtyIHBsb3QgYWxsIHNpZ2h0IG9uIGVmZm9ydH0KcGFyKG1hciA9IGMoNyw2LDQsNCkpICMgc2V0cyB0aGUgb3V0ZXIgbWFyZ2luLCBvcmRlciA9IGxlZnQsYm90dG9tLHRvcCxyaWdodAojcGFyKG9tYT1jKDAsMCwwLDUuOCkpCm9ic2V4cHNlYXM8LWFzLm1hdHJpeChkYXRhLmZyYW1lKGludGVyPWMoMjcsIDQzLjQxKSwgbmU9Yyg1MSwzNC41OSkpKSAjIGNyZWF0aW5nIGEgbWF0cml4IHdpdGggb2JzZXJ2ZWQgYW5kIGV4cGVjdGVkIGNldGFjZWFuIHNpZ2h0aW5nIHZhbHVlcyBmb3IgaW50ZXJtb25zb29uICgyNyAmIDQzLjQxKSBhbmQgbmUgbW9uc29vbiAoNTEsMzQuNTkpCm9uc2Vhc2JhcnBsb3Q8LWJhcnBsb3Qob2JzZXhwc2VhcywgYmVzaWRlPVRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICB4bGFiID0gIlNlYXNvbiIsIAogICAgICAgICAgICAgICAgICAgICAgIHlsYWI9Ik5vOiBvZiBjZXRhY2VhbiBzaWdodGluZ3MiLCAKICAgICAgICAgICAgICAgICAgICAgICBuYW1lcy5hcmc9YygiSW50ZXIgbW9uc29vbiAobj0yNykiLCJOb3J0aGVhc3QgbW9uc29vbiAobj01MSkiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgY2V4LmxhYiA9IDAuOSwgCiAgICAgICAgICAgICAgICAgICAgICAgY2V4LmF4aXMgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICBjZXgubmFtZXMgPSAwLjcsIAogICAgICAgICAgICAgICAgICAgICAgIGNvbD1jKCJncmV5ODAiLCAiZ3JleTIwIiksIAogICAgICAgICAgICAgICAgICAgICAgIGRlbnNpdHkgPSBjKDEwMCwxMDApLCAKICAgICAgICAgICAgICAgICAgICAgICB5bGltID0gYygwLDgwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgeGxpbT1jKDAuMyw1KSkKbGVnZW5kKCJ0b3BsZWZ0IiwgIGMoIkNldGFjZWFuIHNpZ2h0aW5ncyBvbiBzdXJ2ZXkiLCAiRXhwZWN0ZWQgY2V0YWNlYW4gc2lnaHRpbmcgYmFzZWQgb24gZWZmb3J0IiksIGZpbGwgPSBjKCJncmV5ODAiLCAiZ3JleTIwIiksIGNleD0wLjcsIGJ0eT0nbicpCmBgYAoKIyMjIyMgTm9uIHBhcmFtZXRlcmljIHN0YXRpc3RpY2FsIHRlc3QgLSBDaGktU3F1YXJlIEdvb2RuZXNzIG9mIEZpdAoKQ2hpIHNxdWFyZSBnb29kbmVzcyBvZiBmaXQgdGVzdCBiZXR3ZWVuIG9ic2VydmVkIGFuZCBleHBlY3RlZCB2YWx1ZXMuIEV4cGVjdGVkIHZhbHVlcyBhcmUgY2FsY3VsYXRlZCBhcyBlZmZvcnQgKGRpc3RhbmNlIHRyYXZlbGVkIGluIGVhY2ggc2Vhc29uKS4gVGhlIHRlc3QgaXMgc2lnbmlmaWNhbnQgYW5kIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgcmVqZWN0ZWQuIAoKTnVsbCBoeXBvdGhlaXM6IFNpZ2h0aW5ncyBhcmUgZXF1YWxseSBkaXN0cmlidXRlZCBhY3Jvc3MgdGhlIHR3byBzZWFzb25zIGFzIHBlciB0aGUgZGlzdGFuY2UgdHJhdmVsZWQgZHVyaW5nIHN1cnZleSBlZmZvcnQuCgpBbHRlcm5hdGUgSHlwb3RoZXNpczogU2lnaHRpbmdzIGFyZSBkaWZmZXJlbnRpYWxseSBkaXN0cmlidXRlZCBhY3Jvc3MgdGhlIHR3byBzZWFzb25zIGFzIHBlciB0aGUgZGlzdGFuY2UgdHJhdmVsZWQgZHVyaW5nIHN1cnZleSBlZmZvcnQuCgpgYGB7ciBjaGkgc3F1YXJlIGdvb2RuZXNzIG9uIGVmZm9ydCBhbGwgc2lnaHRpbmdzfQojIGNoaSBzcXVhcmUgdGVzdCBmb3Igb24gZWZmb3J0IHNpZ2h0aW5ncyBpbiBlYWNoIHNlYXNvbiAtIGdvb2RuZXNzIG9mIGZpdCBhY2NvcmRpbmcgdG8gZGlzdGFuY2UgdHJhdmVsZWQKZWZmZGF0bmU8LXN1YnNldChlZmZkYXQsIGVmZmRhdCRzZWFzID09ICduZScpICMgZWZmb3J0IGRhdGFzZXQgZm9yIG9ubHkgbmUgbW9uc29vbgplZmZkYXRpbnRlcjwtc3Vic2V0KGVmZmRhdCwgZWZmZGF0JHNlYXMgPT0gJ2ludGVyJykgIyBlZmZvcnQgZGF0YXNldCBmb3Igb25seSBpbnRlciBtb25zb29uCnRvdGVmZmRpc3RuZTwtc3VtKGVmZmRhdG5lJGRpc3QpICMgdG90YWwgZGlzdGFuY2UgdHJhdmVsZWQgZm9yIG5vcnRoZWFzdCBtb25zb29uCnRvdGVmZmRpc3RpbnRlcjwtc3VtKGVmZmRhdGludGVyJGRpc3QpICMgdG90YWwgZGlzdGFuY2UgdHJhdmVsZWQgZm9yIGludGVyIG1vbnNvb24KIyB0YWJsZShvbmNldGVudmRhdCRzZWFzKSAjIHNpZ2h0aW5ncyBwZXIgc2Vhc29uIG9uIGVmZm9ydAojIGNoaXNxdWFyZSBnb29kbmVzcyBvZiBmaXQgdGVzdCBmb3Igbm86IG9mIHNpZ2h0aW5ncyBpbiBlYWNoIHNlYXNvbiB0byBleHBlY3RlZCBudW1iZXIgb2Ygc2lnaHRpbmdzIGJhc2VkIG9uIGRpc3RhbmNlIHRyYXZlbGxlZC4KdGFibGUob25jZXRlbnZkYXQkc2VhcykKc2Vhc2FsbGNoaXNxPC1jaGlzcS50ZXN0KCAodGFibGUob25jZXRlbnZkYXQkc2VhcykpLAogICAgICAgICAgICAgcD1jKCh0b3RlZmZkaXN0aW50ZXIvdG90ZWZmZGlzdCksKHRvdGVmZmRpc3RuZS90b3RlZmZkaXN0KSkgKSAKc2Vhc2FsbGNoaXNxCnBhc3RlKCdFeHBlY3RlZCB2YWx1ZSBmb3IgaW50ZXIgbW9uc29vbiBwZXJpb2QgaXMnLCByb3VuZChzZWFzYWxsY2hpc3EkZXhwZWN0ZWRbMV0sMikpCnBhc3RlKCdFeHBlY3RlZCB2YWx1ZXMgZm9yIG5vcnRoIGVhc3QgbW9uc29vbiBpcycsIHJvdW5kKHNlYXNhbGxjaGlzcSRleHBlY3RlZFsyXSwyKSkKIyBmb3JtdWxhIGNoaS5zcS50ZXN0ICggbm86IG9mIHNlYXMgc2lnaHRpbmdzIDI3IChpbnRlciksIDUxKG5lKSwgcHJvYmFiaWxpdHkgPSAwLjU1NjUwNjggKGludGVyKSwgMC40NDM0OTMyIChuZSkgKQoKYGBgCgo8YnI+CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIENldGFjZWFuIHNwZWNpZXMgYWNyb3NzIGRpc3RhbmNlIHRvIG5lYXJlc3QgbGFuZG1hc3MKCiMjIyMjIEJveHBsb3Qgb2YgZGlzdGFuY2UgdG8gbmVhcmVzdCBsYW5kbWFzcyBmb3IgYWxsIHNwZWNpZXMKClNwZWNpZXMgY29kZXM7IGJhbCA9IEJhbGVlbiB3aGFsZSwgVCA9IEJvdHRsZW5vc2UgZG9scGhpbiwgUEMgPSBGYWxzZSBraWxsZXIgd2hhbGUsIEdNID0gU2hvcnQgZmlubmVkIHBpbG90IHdoYWxlLCBGQSA9IFBneW15IGtpbGxlciB3aGFsZSwgR0cgPSBSaXNzb3MgZG9scGhpbiwgU0wgPSBTcGlubmVyIGRvbHBoaW4sIFNBID0gU3BvdHRlZCBkb2xwaGluLCBTQyA9IFN0cmlwZWQgZG9scGhpbgpgYGB7ciBuZWFyZXN0IGRpc3RhbmNlfQpwYXIobWFyID0gYyg1LDUsMywzKSkgIyBzZXRzIHRoZSBvdXRlciBtYXJnaW4sIG9yZGVyID0gbGVmdCxib3R0b20sdG9wLHJpZ2h0Cm5lYXJkaXN0Ym94cGxvdDwtYm94cGxvdChpZGNldGVudmRhdHN0YXRzJG5lYXJkaXN0a21+aWRjZXRlbnZkYXRzdGF0cyRzcGVjaWVzLCB4bGFiID0gIlNwZWNpZXMgKG4pIiwgeWxhYj0iTmVhcmVzdCBkaXN0YW5jZSAoa20pIiwgbWFpbiA9ICJOZWFyZXN0IGRpc3RhbmNlIHRvIGxhbmQgZm9yIGVhY2ggc3BlY2llcyIsIG5hbWVzPWMoIlQgKDE4KSIsIlBDKDQpIiwiR00oMTMpIiwiR0coNykiLCJTTCgyMikiLCJTQSgzKSIsIlNDKDUpIiksIGNleC5sYWIgPSAxLjIsIGNleC5tYWluID0gMSwgY29sPSJtZWRpdW1hcXVhbWFyaW5lIikKIyBzcGVjaWVzIGNvZGVzOyBiYWwgPSBCYWxlZW4gd2hhbGUsIFQgPSBCb3R0bGVub3NlIGRvbHBoaW4sIFBDID0gRmFsc2Uga2lsbGVyIHdoYWxlLCBHTSA9IFNob3J0IGZpbm5lZCBwaWxvdCB3aGFsZSwgRkEgPSBQZ3lteSBraWxsZXIgd2hhbGUsIEdHID0gUmlzc29zIGRvbHBoaW4sIFNMID0gU3Bpbm5lciBkb2xwaGluLCBTQSA9IFNwb3R0ZWQgZG9scGhpbiwgU0MgPSBTdHJpcGVkIGRvbHBoaW4KYGBgCgojIyMjIyBOb24gcGFyYW1ldGVyaWMgc3RhdGlzdGljYWwgdGVzdCAtIEtydXNrYWwtV2FsbGlzIHRlc3QKCk51bGwgaHlwb3RoZXNpczogQWxsIHNwZWNpZXMgYXJlIHVuaWZvcm1seSBkaXN0cmlidXRlZCB3aXRoIHJlc3BlY3QgdG8gdGhlIG5lYXJlc3QgbGFuZG1hc3Mgb24gdGhlIGZlcnJ5IHJvdXRlcy4KCkFsdGVybmF0ZSBoeXBvdGhlc2lzOiBTcGVjaWVzIGFyZSBkaWZmZXJlbnRpYWxseSBkaXN0cmlidXRlZCB3aXRoIHJlc3BlY3QgdG8gdGhlIG5lYXJlc3QgbGFuZG1hc3Mgb24gdGhlIGZlcnJ5IHJvdXRlcy4gCgpLcnVza2FsIFdhbGxpcyB0ZXN0IHdhcyBwZXJmb3JtZWQgYW5kIHRlc3Qgd2FzIHNpZ25pZmljYW50LiBUaGVyZWZvcmUgdGhlIE51bGwgaHlwb3Roc2lzIGlzIHJlamVjdGVkLgoKYGBge3Igbm9uIHBhcmEgbmVhcmRpc3QgYWxsIHNwc30KCiMgZm9yIGFsbCBzcHMgKGV4Y2VwdCBiYWxlZW4gYW5kIHB5Z215KQprcnVza2FsLnRlc3QoYXMuZmFjdG9yKGlkY2V0ZW52ZGF0c3RhdHMkbmVhcmRpc3RrbSl+YXMuZmFjdG9yKGlkY2V0ZW52ZGF0c3RhdHMkc3BlY2llcyksIGRhdGE9aWRjZXRlbnZkYXRzdGF0cykKYGBgCgoKTWVkaWFucyBmb3IgbmVhcmVzdCBhbmQgZnVydGhlc3Qgc3BlY2llcwoKYGBge3IgTWVkaWFucyBmb3IgbmVhcmVzdCBhbmQgZnVydGhlc3Qgc3BlY2llc30KcGFzdGUgKCJTcGlubmVyIGRvbHBoaW5zIG1lZGlhbiAoaW4ga20pID0iLCByb3VuZChuZWFyZGlzdGJveHBsb3Qkc3RhdHNbMyw1XSwyKSkKcGFzdGUgKCJTcG90dGVkIGRvbHBoaW5zIG1lZGlhbiAoaW4ga20pID0iLCByb3VuZChuZWFyZGlzdGJveHBsb3Qkc3RhdHNbMyw2XSwyKSkKcGFzdGUgKCJTdHJpcGVkIGRvbHBoaW5zIG1lZGlhbiAoaW4ga20pID0iLCByb3VuZChuZWFyZGlzdGJveHBsb3Qkc3RhdHNbMyw3XSwyKSkKYGBgCgo8YnI+Ci0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMgQ2V0YWNlYW4gc3BlY2llcyBhY3Jvc3Mgc2VhZmxvb3Igc2xvcGUgZ3JhZGllbnQKCiMjIyMjIEJveHBsb3Qgb2Ygc2xvcGUgZGlzdHJpYnV0aW9uIGZvciBhbGwgc3BlY2llcwoKU3BlY2llcyBjb2RlczsgYmFsID0gQmFsZWVuIHdoYWxlLCBUID0gQm90dGxlbm9zZSBkb2xwaGluLCBQQyA9IEZhbHNlIGtpbGxlciB3aGFsZSwgR00gPSBTaG9ydCBmaW5uZWQgcGlsb3Qgd2hhbGUsIEZBID0gUGd5bXkga2lsbGVyIHdoYWxlLCBHRyA9IFJpc3NvcyBkb2xwaGluLCBTTCA9IFNwaW5uZXIgZG9scGhpbiwgU0EgPSBTcG90dGVkIGRvbHBoaW4sIFNDID0gU3RyaXBlZCBkb2xwaGluCgpgYGB7ciBzbG9wZSBwbG90IGFsbCBzcGVjaWVzfQpwYXIobWFyID0gYyg1LDUsMywzKSkgIyBzZXRzIHRoZSBvdXRlciBtYXJnaW4sIG9yZGVyID0gbGVmdCxib3R0b20sdG9wLHJpZ2h0CnNsb3BlYm94cGxvdDwtYm94cGxvdChpZGNldGVudmRhdHN0YXRzJHNsb3BlfmlkY2V0ZW52ZGF0c3RhdHMkc3BlY2llcywgeGxhYiA9ICJTcGVjaWVzIChuKSIsIHlsYWI9IlNsb3BlIiwgbWFpbiA9ICJTbG9wZSBkaXN0cmlidXRpb24gZm9yIGVhY2ggc3BlY2llcyIsIG5hbWVzPWMoIlQgKDE4KSIsIlBDKDQpIiwiR00oMTMpIiwgIkdHKDcpIiwiU0woMjIpIiwiU0EoMykiLCJTQyg1KSIpLCBjZXgubGFiID0gMS4yLCBjZXgubWFpbiA9IDEsIGNvbD0ibWVkaXVtYXF1YW1hcmluZSIpCiMgc3BlY2llcyBjb2RlczsgYmFsID0gQmFsZWVuIHdoYWxlLCBUID0gQm90dGxlbm9zZSBkb2xwaGluLCBQQyA9IEZhbHNlIGtpbGxlciB3aGFsZSwgR00gPSBTaG9ydCBmaW5uZWQgcGlsb3Qgd2hhbGUsIEZBID0gUGd5bXkga2lsbGVyIHdoYWxlLCBHRyA9IFJpc3NvcyBkb2xwaGluLCBTTCA9IFNwaW5uZXIgZG9scGhpbiwgU0EgPSBTcG90dGVkIGRvbHBoaW4sIFNDID0gU3RyaXBlZCBkb2xwaGluCmBgYAoKIyMjIyMgTm9uIHBhcmFtZXRlcmljIHN0YXRpc3RpY2FsIHRlc3QgLSBLcnVza2FsLVdhbGxpcyB0ZXN0CgpOdWxsIGh5cG90aGVzaXM6IEFsbCBzcGVjaWVzIGFyZSB1bmlmb3JtbHkgZGlzdHJpYnV0ZWQgYWNyb3NzIHNsb3BlIGdyYWRpZW50cyBhbG9uZyB0aGUgZmVycnkgcm91dGVzLgoKQWx0ZXJuYXRlIGh5cG90aGVzaXM6IFNwZWNpZXMgYXJlIGRpZmZlcmVudGlhbGx5IGRpc3RyaWJ1dGVkIGFjcm9zcyBzbG9wZSBncmFkaWVudHMgYWxvbmcgdGhlIGZlcnJ5IHJvdXRlcy4gCgpLcnVza2FsIFdhbGxpcyB0ZXN0IHdhcyBwZXJmb3JtZWQgYW5kIHRlc3Qgd2FzIHNpZ25pZmljYW50LiBUaGVyZWZvcmUgdGhlIE51bGwgaHlwb3Roc2lzIGlzIHJlamVjdGVkLgoKYGBge3Igbm9uIHBhcmEgc2xvcGUgYWxsIHNwZWNpZXN9CiMgZm9yIGNvbW1vbiBzcHMKa3J1c2thbC50ZXN0KGFzLmZhY3RvcihpZGNldGVudmRhdHN0YXRzJHNsb3BlKX5hcy5mYWN0b3IoaWRjZXRlbnZkYXRzdGF0cyRzcGVjaWVzKSwgZGF0YT1pZGNldGVudmRhdHN0YXRzKQoKYGBgCgpNZWRpYW5zIGZvciBzcGVjaWVzIGluIHRoZSBmbGF0ZXN0IGFuZCBzdGVlcGVzdCBzbG9wZXMKCmBgYHtyIE1lZGlhbnMgZm9yIGZsYXQgYW5kIHN0ZWVwIHNsb3BlIHNwZWNpZXN9CnBhc3RlICgiU3Bpbm5lciBkb2xwaGlucyBtZWRpYW4gc3RlZXBlc3Qgc2xvcGUgPSIsIHJvdW5kKHNsb3BlYm94cGxvdCRzdGF0c1szLDVdLDIpKQpwYXN0ZSAoIlNwb3R0ZWQgZG9scGhpbnMgbWVkaWFuIGZsYXQgc2xvcGUgPSIsIHJvdW5kKHNsb3BlYm94cGxvdCRzdGF0c1szLDZdLDIpKQpwYXN0ZSAoIlN0cmlwZWQgZG9scGhpbnMgbWVkaWFuIGZsYXQgc2xvcGUgPSIsIHJvdW5kKHNsb3BlYm94cGxvdCRzdGF0c1szLDddLDIpKQpgYGAKCjxicj4KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyBDZXRhY2VhbiBzcGVjaWVzIGFjcm9zcyBzZWFmbG9vciBkZXB0aAoKIyMjIyMgQm94cGxvdCBiZXR3ZWVuIGNldGFjZWFuIHNwZWNpZXMgYW5kIHNlYWZsb29yIGRlcHRoIAoKU3BlY2llcyBjb2RlczsgYmFsID0gQmFsZWVuIHdoYWxlLCBUID0gQm90dGxlbm9zZSBkb2xwaGluLCBQQyA9IEZhbHNlIGtpbGxlciB3aGFsZSwgR00gPSBTaG9ydCBmaW5uZWQgcGlsb3Qgd2hhbGUsIEZBID0gUGd5bXkga2lsbGVyIHdoYWxlLCBHRyA9IFJpc3NvcyBkb2xwaGluLCBTTCA9IFNwaW5uZXIgZG9scGhpbiwgU0EgPSBTcG90dGVkIGRvbHBoaW4sIFNDID0gU3RyaXBlZCBkb2xwaGluCgpgYGB7ciBkZXB0aCBwbG90IGFsbCBzcGVjaWVzfQoKIyBBbGwgc3BlY2llcyBhbmQgZGVwdGgKcGFyKG1hciA9IGMoNSw1LDMsMykpICMgc2V0cyB0aGUgb3V0ZXIgbWFyZ2luLCBvcmRlciA9IGxlZnQsYm90dG9tLHRvcCxyaWdodApkZXB0aGJveHBsb3Q8LWJveHBsb3QoaWRjZXRlbnZkYXRzdGF0cyRkZXB0aH5pZGNldGVudmRhdHN0YXRzJHNwZWNpZXMsIHhsYWIgPSAiU3BlY2llcyAobikiLCB5bGFiPSJTZWFmbG9vciBkZXB0aChtKSIsIG1haW4gPSAiU2VhZmxvb3IgZGVwdGggZGlzdHJpYnV0aW9uIGZvciBlYWNoIHNwZWNpZXMiLCBuYW1lcz1jKCJUICgxOCkiLCJQQyg0KSIsIkdNKDEzKSIsIkdHKDcpIiwiU0woMjIpIiwiU0EoMykiLCJTQyg1KSIpLCBjZXgubGFiID0gMS4yLCBjZXgubWFpbiA9IDEsIGNvbD0ibWVkaXVtYXF1YW1hcmluZSIpICMgeGxhYiA9IHggbGFiZWwsIHlsYWIgPSB5IGxhYmVsLCBjZXgubGFiID0gbGFiZWwgZm9udCBzaXplLCBjZXgubWFpbiA9IHRpdGxlIGZvbnQgc2l6ZSwgbWFpbiA9IHRpdGxlCiMgc3BlY2llcyBjb2RlczsgYmFsID0gQmFsZWVuIHdoYWxlLCBUID0gQm90dGxlbm9zZSBkb2xwaGluLCBQQyA9IEZhbHNlIGtpbGxlciB3aGFsZSwgR00gPSBTaG9ydCBmaW5uZWQgcGlsb3Qgd2hhbGUsIEZBID0gUGd5bXkga2lsbGVyIHdoYWxlLCBHRyA9IFJpc3NvcyBkb2xwaGluLCBTTCA9IFNwaW5uZXIgZG9scGhpbiwgU0EgPSBTcG90dGVkIGRvbHBoaW4sIFNDID0gU3RyaXBlZCBkb2xwaGluCmBgYAoKIyMjIyMgTm9uIHBhcmFtZXRlcmljIHN0YXRpc3RpY2FsIHRlc3Qgc3BlY2llcyBhbmQgZGVwdGggLSBLcnVza2FsLVdhbGxpcyB0ZXN0CgpOdWxsIGh5cG90aGVzaXM6IEFsbCBzcGVjaWVzIGFyZSB1bmlmb3JtbHkgZGlzdHJpYnV0ZWQgYXdheSBhY3Jvc3Mgc2VhZmxvb3IgZGVwdGhzLgoKQWx0ZXJuYXRlIGh5cG90aGVzaXM6IFNwZWNpZXMgYXJlIGRpZmZlcmVudGlhbGx5IGRpc3RyaWJ1dGVkIGFjcm9zcyBzZWFmbG9vciBkZXB0aHMuIAoKS3J1c2thbCBXYWxsaXMgdGVzdCB3YXMgcGVyZm9ybWVkIGFuZCB0ZXN0IHdhcyBub3Qgc2lnbmlmaWNhbnQuIFRoZXJlZm9yZSB0aGUgTnVsbCBoeXBvdGhzaXMgaXMgbm90IHJlamVjdGVkLgoKYGBge3IgZGVwdGggbm9uIHBhcmEgYWxsIHNwZWNpZXN9CgojIGZvciBhbGwgc3BzIChleGNlcHQgYmFsZWVuIGFuZCBweWdteSkKa3J1c2thbC50ZXN0KGFzLmZhY3RvcihpZGNldGVudmRhdHN0YXRzJGRlcHRoKX5hcy5mYWN0b3IoaWRjZXRlbnZkYXRzdGF0cyRzcGVjaWVzKSwgZGF0YT1pZGNldGVudmRhdHN0YXRzKQpgYGAKCjxicj4KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyBQbG90IG9mIGNldGFjZWFuIHNwZWNpZXMgYWNyb3NzIG5lYXJlc3QgZGlzdGFuY2UgdG8gbGFuZCBhbmQgc2xvcGUgZ3JhZGllbnQgKEZpZ3VyZSA1KQoKYGBge3IgU2xvcGUgYW5kIG5lYXJlc3QgZGlzdGFuY2UgdG8gbGFuZCBhY3Jvc3Mgc3BlY2llc30KIyMjIFBsb3R0aW5nIHNpZ25pZmljYW50IHJlc3VsdHMgdG9nZXRoZXIgCiMjIyMjIFNsb3BlIGFuZCBuZWFyZXN0IGRpc3RhbmNlIHRvIGxhbmQgYWNyb3NzIHNwZWNpZXMKCiMgY29sbGFwc2UgdGhlIGRhdGEgZnJhbWUKeDwtbWVsdChkYXRhID0gaWRjZXRlbnZkYXRzdGF0cywgaWQudmFycyA9ICJzcGVjaWVzIiwgbWVhc3VyZS52YXJzID0gYygic2xvcGUiLCAibmVhcmRpc3RrbSIpKQpyZXF1aXJlKGdncGxvdDIpCnNsb3BlZGlzdHBsb3Q8LWdncGxvdChkYXRhID0geCwgYWVzKHg9c3BlY2llcywgeT12YWx1ZSkpICsgCiAgIyBzcGVjaWZ5IGJveHBsb3QgYW5kIHZhcmlhYmxlIHRvIGJlIGZpbGxlZCBpbiB0aGlzIGNhc2UgJ3Nsb3BlJyAmICduZWFyZGlzdCcKICBnZW9tX2JveHBsb3QoYWVzKGZpbGw9dmFyaWFibGUpKSArCiAgIyBuYW1lIHggYW5kIHkgYXhpcwogIHhsYWIoIlNwZWNpZXMgKG4pIikgKyB5bGFiKCJTbG9wZSAocGVyY2VudCkiKSArCiAgIyBhZGQgYSBzZWNvbmQgeSBheGlzIG9uIHRoZSByaWdodCBhbmQgc3BlY2lmeSB2YWx1ZXMgdy5yLnQgdG8geCBheGlzICgqMXgpCiAgc2NhbGVfeV9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXMofi4qMSwgbmFtZSA9ICJEaXN0YW5jZSB0byBuZWFyZXN0IGxhbmQgKGttKSIpKSArCiAgCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTApKSArCiAgCiAgdGhlbWUocGxvdC5tYXJnaW49dW5pdChjKDEsMC44LDAuNSwwLjUpLCJjbSIpKSArCiAgCiAgIyBjaGFuZ2UgdGhlIGxlZ2VuZCBsYWJlbHMKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IiIsIGxhYmVscz1jKCJTbG9wZSIsICJEaXN0YW5jZSB0byBuZWFyZXN0IGxhbmQiKSkgKwogICMgY2hhbmdlIHRoZSBsZWdlbmQgcG9zaXRpb24gKDAsMCkgPSBib3R0b20gbGVmdCAmICgxLDEpID0gdG9wIHJpZ2h0CiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjE2LCAwLjkpKSArCiAgIyBzaXplIG9mIGxlZ2VuZCB0ZXh0CiAgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9cmVsKDAuNSkpKSArCiAgIyByZW1vdmUgdGhlIGxlZ2VuZCBiYWNrZ3JvdW5kCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICAjIGFkZGluZyBzYW1wbGUgc2l6ZXMgdG8gdGhlIHBsb3QKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJib3R0bGVub3NlIiA9ICJib3R0bGVub3NlIGRvbHBoaW4gKDE4KSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmFsc2VraWxsZXIiID0gImZhbHNlIGtpbGxlciB3aGFsZSg0KSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwaWxvdCIgPSAicGlsb3Qgd2hhbGUoMTMpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJyaXNzbyIgPSAiUmlzc28ncyBkb2xwaGluICg3KSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAic3Bpbm5lciIgPSJzcGlubmVyIGRvbHBoaW4oMjIpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzcG90dGVkIiA9InNwb3R0ZWQgZG9scGhpbigzKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAic3RyaXBlZCIgPSAic3RyaXBlZCBkb2xwaGluKDUpIikpIAojc3RhdF9zdW1tYXJ5KGZ1bi55PW1lYW4sc2hhcGU9MSxjb2w9J3JlZCcsZ2VvbT0ncG9pbnQnKQoKc2xvcGVkaXN0cGxvdApybSh4KQoKCmBgYAoKCjxicj4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMgUm91dGUgSW5mb3JtYXRpb24KYGBge3IgUm91dGUgaW5mb3JtYXRpb259CnN0ZXAxPC10YWJsZShlZmZkYXQkcm91dGUpICMgTm8uIG9mIHRpbWVzIGEgcm91dGUgd2FzIHRyYXZlcnNlZApzdGVwMTwtc3RlcDFbYygxLDgsMyw5LDUsNiwxMCw0LDcsMTEsMiwxMildICMgcmVvcmRlciB0byBtYXRjaCBjb3JyZXNwb25kaW5nIGNvbHVtbnMgaW4gcm91dGVfZW5jcmF0ZSBkYXRhZnJhbWUKc3RlcDE8LWFzLnZlY3RvcihzdGVwMSkgIyBtYWtpbmcgaW50byBhIHZlY3RvcgpzdGVwMjwtYWdncmVnYXRlKGVmZmRhdCRkaXN0IH4gZWZmZGF0JHJvdXRlbm8sIEZVTj1zdW0pICMgZXh0cmFjdGluZyBzdW0gb2YgZGlzdGFuY2VzIGZvciByb3V0ZXMKc3RlcDM8LWFnZ3JlZ2F0ZShlZmZkYXQkbm8uc2lnaHQgfiBlZmZkYXQkcm91dGVubywgRlVOPXN1bSkgIyBleHRyYWN0aW5nIHN1bSBvZiBzaWdodGluZ3MgZm9yIHJvdXRlcwpyb3V0ZV9pbmZvPC1kYXRhLmZyYW1lKHJvdXRlX2VuY3JhdGUsIHN0ZXAxLCBzdGVwMiwgc3RlcDMpICMgTWFraW5nIGEgZGF0YSBmcmFtZSB3aXRoIHJvdXRlIG5vLCByb3V0ZSBuYW1lLCBubzogb2YgdGltZXMgYSByb3V0ZSB3YXMgdHJhbnZlcnNlZCwgcm91dGUgZGlzdGFuY2UsIHJvdXRlIHNpZ2h0aW5ncyBhbmQgcm91dGUgZW5jIHJhdGUKcm91dGVfaW5mbzwtcm91dGVfaW5mb1tjKDEsMiw0LDYsOCwzKV0gIyByZW9yZGVyCmNvbG5hbWVzKHJvdXRlX2luZm8pPC1jKCJSb3V0ZSBOby4iLCAiUm91dGUgbmFtZSIsICJOby4gb2YgdGltZXMiLCAiRGlzdGFuY2UgKGttKSIsICJOby4gb2Ygc2lnaHRpbmdzIiwgIkVuY291bnRlciByYXRlIikKcm91dGVfaW5mbwpybShzdGVwMSwgc3RlcDIsIHN0ZXAzKQojd3JpdGUuY3N2KHJvdXRlX2luZm8sIGZpbGUgPSAiL1ZvbHVtZXMvR29vZ2xlRHJpdmUvTXkgRHJpdmUvTGFrc2ggSSBwcm9qZWN0L2Rlc2lnbiAmIGRhdGEvRGF0YSBFbnRyeS9MYWtzaCBSIGZpbGVzL1Bhbmlja2VyXzIwMTlfTERfYW5hbHlzaXNfbWFudXNjcmlwdF9saW5rL1NpZ2h0aW5ncyBhbmQgZWZmb3J0IGZvciBlYWNoIHJvdXRlLmNzdiIpCmBgYAoKPGJyPgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyBUSEUgRU5ECgoKCgoKCgo=