The data

We will start with a preload data set called mtcars

RStudio Community is a great place to get help:
https://community.rstudio.com/c/tidyverse.
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
manufacturer model displ year cyl trans drv cty hwy fl class
mercury mountaineer 4wd 4.0 2008 6 auto(l5) 4 13 19 r suv
volkswagen gti 2.0 1999 4 auto(l4) f 19 26 r compact
dodge ram 1500 pickup 4wd 4.7 2008 8 manual(m6) 4 9 12 e pickup
dodge durango 4wd 4.7 2008 8 auto(l5) 4 13 17 r suv
volkswagen new beetle 1.9 1999 4 manual(m5) f 35 44 d subcompact
dodge caravan 2wd 4.0 2008 6 auto(l6) f 16 23 r minivan
volkswagen new beetle 2.5 2008 5 manual(m5) f 20 28 r subcompact
volkswagen new beetle 2.5 2008 5 auto(s6) f 20 29 r subcompact
ford explorer 4wd 4.0 1999 6 auto(l5) 4 14 17 r suv
audi a4 quattro 1.8 1999 4 auto(l5) 4 16 25 p compact

Simple plot

Boxplots

  • Box plot group by year as numbers
ggplot(mpg) + geom_boxplot(mapping=aes(group=year,y=displ,
                                       fill=year))

  • Box plot group by year as factors
ggplot(mpg) + geom_boxplot(mapping=aes(group=year,y=displ,
                                       fill=factor(year)))

ggplot(mpg, aes(drv))+geom_bar(color=c("red","blue","green"))  + facet_grid(rows=vars(factor(cyl)),cols=vars(year))
Error: Aesthetics must be either length 1 or the same as the data (16): colour

ggplot(mpg) + geom_point(mapping=aes(x=hwy,y=cty,size=displ,color=factor(cyl))) + facet_grid(rows=vars(drv),cols=vars(year))

Plotting distribution

Simple plots

  • Histogram
  • Histogram of densities
ggplot(mpg,aes(x=hwy,y=..density..)) + geom_histogram(col="#FF000099", fill="#CCCC0099",bins=16)

  • Density plot
ggplot(mpg,aes(x=hwy)) + geom_density(col="#FF000099", fill="#99000099")

require(gridExtra) # also loads grid
 require(lattice)
 x <- seq(pi/4, 5 * pi, length.out = 100)
 y <- seq(pi/4, 5 * pi, length.out = 100)
 r <- as.vector(sqrt(outer(x^2, y^2, "+")))

 grid <- expand.grid(x=x, y=y)
 grid$z <- cos(r^2) * exp(-r/(pi^3))
 plot1 <- levelplot(z~x*y, grid, cuts = 50, scales=list(log="e"), xlab="",
           ylab="", main="Weird Function", sub="with log scales",
           colorkey = FALSE, region = TRUE)

 plot2 <- levelplot(z~x*y, grid, cuts = 50, scales=list(log="e"), xlab="",
           ylab="", main="Weird Function", sub="with log scales",
           colorkey = FALSE, region = TRUE)
 grid.arrange(plot1,plot2, ncol=2)

require(gridExtra) # also loads grid
require(lattice)
x <- seq(pi/4, 5 * pi, length.out = 100)
y <- seq(pi/4, 5 * pi, length.out = 100)
r <- as.vector(sqrt(outer(x^2, y^2, "+")))

grid <- expand.grid(x=x, y=y)


s = 10000
pop = 1:s
h = rnorm(s,50,10)

plist = ggplot()
est = rep(0,7)
sizes = c("005","010","020","040","080","160","320")
ss = c(5,10,20,40,80,160,320)

p <- ggplot(ylim=c(0,8))

for (i in 1:7) {
  meanest = rep(0,20)
  
  for(j in 1:20) {
    d = density(h[sample(pop,ss[i])])
    meanest[j] = mean(sum(d$x * d$y) / sum(d$y))
    p <- p + geom_line(mapping=aes(x= d$x,
          y = (d$y + (j/10.0)), color=factor(j)),
           alpha=0.8,color=i)
  }

  

  if (i > 1)
  {
    est = cbind(est,meanest)
  }
  else
  {
    est = meanest
  }
}

p + scale_color_hue() + labs(color="Sample size") + 
    ggtitle(paste("Distribution of Samples (sized",i,")")) +
            xlab("values") + ylab("density")

colnames(est) = sizes
ggplot(mpg,aes(x=hwy)) + geom_density(col="#FF000099", fill="#99000099")

h = rnorm(160,50,10)

ggplot()+
  geom_line(mapping=aes(x=h[1:5],y=..density..,color=5),stat="density",lwd=3.5)+
  geom_line(mapping=aes(x=h[1:10],y=..density..,color=10),stat="density",lwd=3) +
  geom_line(mapping=aes(x=h[1:20],y=..density..,color=20),stat="density",lwd=2.5) +
  geom_line(mapping=aes(x=h[1:40],y=..density..,color=40),stat="density",lwd=2) +
  labs(color="Sample size")

Comparison of distributions

  • Parallel plots
ggplot(mpg,aes(x=hwy)) + geom_density(col="#FF000099", fill="#99000099") + facet_grid(rows=vars(year))

  • Superimposed density curves
ggplot(mpg,aes(x=hwy,group=year)) + geom_density(mapping=aes(color=factor(year)),size=1.2)

  • Density curve over a histogram
ggplot(mpg,aes(x=hwy, y=..density..)) + 
geom_histogram(color="red", fill="orange", bins=16) +
  geom_line(stat='density', color="red", lwd=1.2, lty=1, adjust=.4)

  • Comparison of superimposed density plots for different years
ggplot(mpg) + geom_density(mapping =aes(x=hwy), col="#FF000099", fill="#99000099") + geom_density(mapping =aes(x=cty), col="#0000FF99", fill="#0000FF99") + facet_grid(rows=vars(year))

** Mapping


ggplot(nz,aes(long,lat,group=group)) + geom_polygon(fill="red", color ="black")+coord_quickmap()

library(sp)
library(GADMTools)
library(ggplot2)
MAP <- gadm_sf.loadCountries("THA", level = 0)
plotmap(MAP)

# thai = GADMTools::subset(MAP, level=0, regions=c("THA"))

THA2 <- gadm_getBackground(MAP, "THA", "osm")
plotmap(THA2,title='Thailand')

THA = gadm_sf_loadCountries("THA", level=1, basefile="./")
plotmap(THA)

listNames(THA,level=1)
 [1] "Amnat Charoen"           
 [2] "Ang Thong"               
 [3] "Bangkok Metropolis"      
 [4] "Bueng Kan"               
 [5] "Buri Ram"                
 [6] "Chachoengsao"            
 [7] "Chai Nat"                
 [8] "Chaiyaphum"              
 [9] "Chanthaburi"             
[10] "Chiang Mai"              
[11] "Chiang Rai"              
[12] "Chon Buri"               
[13] "Chumphon"                
[14] "Kalasin"                 
[15] "Kamphaeng Phet"          
[16] "Kanchanaburi"            
[17] "Khon Kaen"               
[18] "Krabi"                   
[19] "Lampang"                 
[20] "Lamphun"                 
[21] "Loei"                    
[22] "Lop Buri"                
[23] "Mae Hong Son"            
[24] "Maha Sarakham"           
[25] "Mukdahan"                
[26] "Nakhon Nayok"            
[27] "Nakhon Pathom"           
[28] "Nakhon Phanom"           
[29] "Nakhon Ratchasima"       
[30] "Nakhon Sawan"            
[31] "Nakhon Si Thammarat"     
[32] "Nan"                     
[33] "Narathiwat"              
[34] "Nong Bua Lam Phu"        
[35] "Nong Khai"               
[36] "Nonthaburi"              
[37] "Pathum Thani"            
[38] "Pattani"                 
[39] "Phangnga"                
[40] "Phatthalung"             
[41] "Phayao"                  
[42] "Phetchabun"              
[43] "Phetchaburi"             
[44] "Phichit"                 
[45] "Phitsanulok"             
[46] "Phra Nakhon Si Ayutthaya"
[47] "Phrae"                   
[48] "Phuket"                  
[49] "Prachin Buri"            
[50] "Prachuap Khiri Khan"     
[51] "Ranong"                  
[52] "Ratchaburi"              
[53] "Rayong"                  
[54] "Roi Et"                  
[55] "Sa Kaeo"                 
[56] "Sakon Nakhon"            
[57] "Samut Prakan"            
[58] "Samut Sakhon"            
[59] "Samut Songkhram"         
[60] "Saraburi"                
[61] "Satun"                   
[62] "Si Sa Ket"               
[63] "Sing Buri"               
[64] "Songkhla"                
[65] "Sukhothai"               
[66] "Suphan Buri"             
[67] "Surat Thani"             
[68] "Surin"                   
[69] "Tak"                     
[70] "Trang"                   
[71] "Trat"                    
[72] "Ubon Ratchathani"        
[73] "Udon Thani"              
[74] "Uthai Thani"             
[75] "Uttaradit"               
[76] "Yala"                    
[77] "Yasothon"                
lanna = gadm_subset(THA, 1, c("Chiang Rai","Chiang Mai","Mae Hong Son","Lamphun","Lampang"))
THA2 <- gadm_getBackground(lanna, "THA", "osm")
plotmap(THA2)

longitude <- runif(6, min=98.0, max = 100.5)
latitude <- runif(6, min=18.0, max = 20.5)
Cases <- runif(6, 25, 112)
DAT <- data.frame(longitude, latitude, Cases)
dots(lanna, DAT, color="red", size = 8, value = "Cases")

propDots(lanna, data = DAT, value="Cases",
         breaks=c(0, 12.5, 25, 50, 100), range = c(0, 100))


regions =  c("Chiang Rai","Chiang Mai","Mae Hong Son","Lamphun","Lampang")
values  = c(20,100,5,18,31)
DAT2 = data.frame(regions,values)
choropleth(lanna,DAT2,adm.join="regions",
            value = "values",
           breaks = "sd",
           palette="Oranges",
           legend = "Population",
           title="Population of Lanna Tai")
n same as number of different finite values\neach different finite value is a separate classColumn `NAME_1` joining character vector and factor, coercing into character vector


library(ggpubr)
Loading required package: magrittr
data("ToothGrowth")
ToothGrowth$dose <- as.factor(ToothGrowth$dose)
# Box plot
p <- ggplot(ToothGrowth, aes(x = dose, y = len)) + 
  geom_boxplot(aes(fill = supp), position = position_dodge(0.9)) +
  scale_fill_manual(values = c("#00AFBB", "#E7B800"))
p



library(ggplot2)
library("ggpubr")
theme_set(
  theme_bw() +
    theme(legend.position = "top")
  )


# Load data and convert dose to a factor variable
data("ToothGrowth")
ToothGrowth$dose <- as.factor(ToothGrowth$dose)
# Box plot
p <- ggplot(ToothGrowth, aes(x = dose, y = len)) + 
  geom_boxplot(aes(fill = supp), position = position_dodge(0.9)) +
  scale_fill_manual(values = c("#00AFBB", "#E7B800"))
p



# Split in vertical direction
p + facet_grid(rows = vars(supp))


# Split in horizontal direction
p + facet_grid(cols = vars(supp))


p + facet_grid(rows = vars(dose), cols = vars(supp))


p + facet_wrap(vars(dose))


p + facet_wrap(vars(dose), ncol=2)


# 1. Create a box plot (bp)
p <- ggplot(ToothGrowth, aes(x = dose, y = len))
bxp <- p + geom_boxplot(aes(color = dose)) +
  scale_color_manual(values = c("red","green","blue"))

# 2. Create a dot plot (dp)
dp <- p + geom_dotplot(aes(color = dose, fill = dose), 
                       binaxis='y', stackdir='center') +
  scale_color_manual(values = c("red","green","blue")) + 
  scale_fill_manual(values = c("red","green","blue"))

# 3. Create a line plot
lp <- ggplot(economics, aes(x = date, y = psavert)) + 
  geom_line(color = "#E46726") 


figure <- ggarrange(bxp, dp, lp,
                    labels = c("A", "B", "C"),
                    ncol = 2, nrow = 2)
`stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.
figure


ggarrange(
  lp,                # First row with line plot
  # Second row with box and dot plots
  ggarrange(bxp, dp, ncol = 2, labels = c("B", "C")), 
  nrow = 2, 
  labels = "A"       # Label of the line plot
  ) 
`stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.

h = rnorm(1000000,50,10)
sizes = c(5,10,20,40,80,160,320)
avglist = ""
for (s in sizes)
{
  dlist = ""
  
  for (i in 1:20)
  {
    d1 = density(h[sample(h,s)],adjust=4)
    
    d2 = cbind(d1$x,d1$y,rep(s,length(d1$x)),rep(i,length(d1$x)))
    a1 = c(s,mean(d1$x * d1$y))
    
    if (length(avglist) < 2)
    {
      avglist = a1
    }  
    else
    {
      avglist = rbind(avglist,a1)
    }
        
    if (length(dlist) < 4)
    {
      dlist = d2
    }  
    else
    {
      dlist = rbind(dlist,d2)
    }
  }

dlist = as.data.frame(dlist)
colnames(dlist) = c("x","y","s","g")
if (s == 5)
{
 grA = ggplot(dlist, aes(x=x,y=y)) + geom_line(mapping=aes(group=g),color="#FF000033",lwd=1.5) + ylab("Density") + ylim(0,0.1) + ggtitle("(n = 5)")
}
else if (s==10)
{
  grB = ggplot(dlist, aes(x=x,y=y)) + geom_line(mapping=aes(group=g),color="#FF000033",lwd=1.5) + ylab("Density") + ylim(0,0.1) + ggtitle("(n = 10)")
}
else if (s==20)
{
  grC = ggplot(dlist, aes(x=x,y=y)) + geom_line(mapping=aes(group=g),color="#FF000033",lwd=1) + ylab("Density") + ylim(0,0.07) + ggtitle("(n = 20)")
}
else if (s==40)
{
  grD = ggplot(dlist, aes(x=x,y=y)) + geom_line(mapping=aes(group=g),color="#FF000033",lwd=1) + ylab("Density") + ylim(0,0.07) + ggtitle("(n = 40)")
}
else if (s==80)
{
  grE = ggplot(dlist, aes(x=x,y=y)) + geom_line(mapping=aes(group=g),color="#FF000033",lwd=1) + ylab("Density") + ylim(0,0.06) + ggtitle("(n = 80)")
}
else if (s==160)
{
  grF = ggplot(dlist, aes(x=x,y=y)) + geom_line(mapping=aes(group=g),color="#FF000033",lwd=1) + ylab("Density") + ylim(0,0.06) + ggtitle("(n = 160)")
}
else if (s==320)
{
  grG = ggplot(dlist, aes(x=x,y=y)) + geom_line(mapping=aes(group=g),color="#FF000033",lwd=1) + ylab("Density") +  ggtitle("(n = 320)")
}

}

d1 = density(h[sample(h,s)],adjust=4)
    
d2 = cbind(d1$x,d1$y,rep(s,length(d1$x)),rep(i,length(d1$x)))
a1 = c(1000000,mean(d1$x * d1$y))
avglist = rbind(avglist,a1)

grH = ggplot() + geom_line(mapping=aes(x=d1$x,y=d1$y),color="red",lwd=1) + ylab("Density") + xlab("x") + ggtitle("(n = 1,000,000)")


figure <- ggarrange(grA,grB, grC, grD, grE, grF, grG,grH,
      labels = c("A","B","C","D","E","F","G"),
      ncol = 2, nrow = 4)
figure


  
colnames(avglist) = c("siz","mean")
avglist = as.data.frame(avglist)

grA = ggplot(avglist,aes(x=factor(siz),y=mean)) + 
  geom_boxplot(mapping=aes(group=siz),color="red")+
  xlab("Sample size") + ylab("Calculated Mean")

grB = ggplot(avglist,aes(x=factor(siz),y=mean)) + 
  geom_violin(mapping=aes(group=siz),color="blue",fill="blue") +
  xlab("Sample size") + ylab("Calculated Mean")

grC = ggplot(avglist,aes(x=factor(siz),y=mean)) + 
  geom_boxplot(mapping=aes(group=siz),color="red")+
  geom_violin(mapping=aes(group=siz),color="#000099",fill="#00009999") +
  xlab("Sample size") + ylab("Calculated Mean")

figure <- ggarrange(grA,grB, grC,
      labels = c("A","B","C"),
      ncol = 1, nrow = 3)
figure

LS0tDQp0aXRsZTogIkRhdGEgVmlzdWFsaXphdGlvbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KZmlnLndpZHRoOiA3DQpmaWcuaGVpZ2h0OiAzDQotLS0NCg0KDQojIFRoZSBkYXRhDQoNCldlIHdpbGwgc3RhcnQgd2l0aCBhIHByZWxvYWQgZGF0YSBzZXQgY2FsbGVkIGBtdGNhcnNgDQoNCg0KYGBge3IsZWNobz1GQUxTRSxmaWcuY2FwPSIxMCBSYW5kb20gZW50cmllcyBmcm9tIHRoZSBtdGNhcnMgZGF0YSBmcmFtZXdvcmsifQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoZ2dwbG90MikNCmtuaXRyOjprYWJsZShoZWFkKG1wZ1tzYW1wbGUoMjM0KSxdLDEwKSxjYXB0aW9uID0iMTAgUmFuZG9tIGVudHJpZXMgZnJvbSBtcGciKQ0KYGBgDQoNCiMgU2ltcGxlIHBsb3QNCg0KIyMgQm94cGxvdHMNCg0KKiBCb3ggcGxvdCBncm91cCBieSB5ZWFyIGFzIG51bWJlcnMNCg0KYGBge3J9DQpnZ3Bsb3QobXBnKSArIGdlb21fYm94cGxvdChtYXBwaW5nPWFlcyhncm91cD15ZWFyLHk9ZGlzcGwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPXllYXIpKQ0KYGBgDQoNCiogQm94IHBsb3QgZ3JvdXAgYnkgeWVhciBhcyBmYWN0b3JzDQoNCmBgYHtyfQ0KZ2dwbG90KG1wZykgKyBnZW9tX2JveHBsb3QobWFwcGluZz1hZXMoZ3JvdXA9eWVhcix5PWRpc3BsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1mYWN0b3IoeWVhcikpKQ0KYGBgDQoNCg0KDQoNCg0KYGBge3J9DQpnZ3Bsb3QobXBnLCBhZXMoZHJ2KSkrZ2VvbV9iYXIoY29sb3I9YygicmVkIiwiYmx1ZSIsImdyZWVuIikpICArIGZhY2V0X2dyaWQocm93cz12YXJzKGZhY3RvcihjeWwpKSxjb2xzPXZhcnMoeWVhcikpDQoNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChtcGcpICsgZ2VvbV9wb2ludChtYXBwaW5nPWFlcyh4PWh3eSx5PWN0eSxzaXplPWRpc3BsLGNvbG9yPWZhY3RvcihjeWwpKSkgKyBmYWNldF9ncmlkKHJvd3M9dmFycyhkcnYpLGNvbHM9dmFycyh5ZWFyKSkNCmBgYA0KDQojIyBQbG90dGluZyBkaXN0cmlidXRpb24NCg0KIyMjIFNpbXBsZSBwbG90cw0KDQoNCg0KKiBIaXN0b2dyYW0NCmBgYHtyLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9MyxmaWcuY2FwPSJTaW1wbGUgSGlzdG9ncmFtIn0NCmdncGxvdChtcGcsYWVzKHg9aHd5KSkgKyBnZW9tX2hpc3RvZ3JhbShjb2w9IiNGRjAwMDA5OSIsIGZpbGw9IiM5OTAwMDA5OSIsYmlucz0xNikNCmBgYA0KDQoqIEhpc3RvZ3JhbSBvZiBkZW5zaXRpZXMNCmBgYHtyLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9MyxmaWcuY2FwPSJTaW1wbGUgSGlzdG9ncmFtIn0NCmdncGxvdChtcGcsYWVzKHg9aHd5LHk9Li5kZW5zaXR5Li4pKSArIGdlb21faGlzdG9ncmFtKGNvbD0iI0ZGMDAwMDk5IiwgZmlsbD0iI0NDQ0MwMDk5IixiaW5zPTE2KQ0KYGBgDQoNCg0KDQoNCiogRGVuc2l0eSBwbG90DQoNCmBgYHtyfQ0KZ2dwbG90KG1wZyxhZXMoeD1od3kpKSArIGdlb21fZGVuc2l0eShjb2w9IiNGRjAwMDA5OSIsIGZpbGw9IiM5OTAwMDA5OSIpDQpgYGANCg0KYGBge3J9DQpyZXF1aXJlKGdyaWRFeHRyYSkgIyBhbHNvIGxvYWRzIGdyaWQNCiByZXF1aXJlKGxhdHRpY2UpDQogeCA8LSBzZXEocGkvNCwgNSAqIHBpLCBsZW5ndGgub3V0ID0gMTAwKQ0KIHkgPC0gc2VxKHBpLzQsIDUgKiBwaSwgbGVuZ3RoLm91dCA9IDEwMCkNCiByIDwtIGFzLnZlY3RvcihzcXJ0KG91dGVyKHheMiwgeV4yLCAiKyIpKSkNCg0KIGdyaWQgPC0gZXhwYW5kLmdyaWQoeD14LCB5PXkpDQogZ3JpZCR6IDwtIGNvcyhyXjIpICogZXhwKC1yLyhwaV4zKSkNCiBwbG90MSA8LSBsZXZlbHBsb3Qoen54KnksIGdyaWQsIGN1dHMgPSA1MCwgc2NhbGVzPWxpc3QobG9nPSJlIiksIHhsYWI9IiIsDQogICAgICAgICAgIHlsYWI9IiIsIG1haW49IldlaXJkIEZ1bmN0aW9uIiwgc3ViPSJ3aXRoIGxvZyBzY2FsZXMiLA0KICAgICAgICAgICBjb2xvcmtleSA9IEZBTFNFLCByZWdpb24gPSBUUlVFKQ0KDQogcGxvdDIgPC0gbGV2ZWxwbG90KHp+eCp5LCBncmlkLCBjdXRzID0gNTAsIHNjYWxlcz1saXN0KGxvZz0iZSIpLCB4bGFiPSIiLA0KICAgICAgICAgICB5bGFiPSIiLCBtYWluPSJXZWlyZCBGdW5jdGlvbiIsIHN1Yj0id2l0aCBsb2cgc2NhbGVzIiwNCiAgICAgICAgICAgY29sb3JrZXkgPSBGQUxTRSwgcmVnaW9uID0gVFJVRSkNCiBncmlkLmFycmFuZ2UocGxvdDEscGxvdDIsIG5jb2w9MikNCmBgYA0KDQoNCmBgYHtyLGZpZy5oZWlnaHQ9NyxmaWcud2lkdGg9NyxmaWcuY2FwPSJFZmZlY3Qgb2Ygc2FtcGxlIHNpemUifQ0KcmVxdWlyZShncmlkRXh0cmEpICMgYWxzbyBsb2FkcyBncmlkDQpyZXF1aXJlKGxhdHRpY2UpDQp4IDwtIHNlcShwaS80LCA1ICogcGksIGxlbmd0aC5vdXQgPSAxMDApDQp5IDwtIHNlcShwaS80LCA1ICogcGksIGxlbmd0aC5vdXQgPSAxMDApDQpyIDwtIGFzLnZlY3RvcihzcXJ0KG91dGVyKHheMiwgeV4yLCAiKyIpKSkNCg0KZ3JpZCA8LSBleHBhbmQuZ3JpZCh4PXgsIHk9eSkNCg0KDQpzID0gMTAwMDANCnBvcCA9IDE6cw0KaCA9IHJub3JtKHMsNTAsMTApDQoNCnBsaXN0ID0gZ2dwbG90KCkNCmVzdCA9IHJlcCgwLDcpDQpzaXplcyA9IGMoIjAwNSIsIjAxMCIsIjAyMCIsIjA0MCIsIjA4MCIsIjE2MCIsIjMyMCIpDQpzcyA9IGMoNSwxMCwyMCw0MCw4MCwxNjAsMzIwKQ0KDQpwIDwtIGdncGxvdCh5bGltPWMoMCw4KSkNCg0KZm9yIChpIGluIDE6Nykgew0KICBtZWFuZXN0ID0gcmVwKDAsMjApDQogIA0KICBmb3IoaiBpbiAxOjIwKSB7DQogICAgZCA9IGRlbnNpdHkoaFtzYW1wbGUocG9wLHNzW2ldKV0pDQogICAgbWVhbmVzdFtqXSA9IG1lYW4oc3VtKGQkeCAqIGQkeSkgLyBzdW0oZCR5KSkNCiAgICBwIDwtIHAgKyBnZW9tX2xpbmUobWFwcGluZz1hZXMoeD0gZCR4LA0KICAgICAgICAgIHkgPSAoZCR5ICsgKGovMTAuMCkpLCBjb2xvcj1mYWN0b3IoaikpLA0KICAgICAgICAgICBhbHBoYT0wLjgsY29sb3I9aSkNCiAgfQ0KDQogIA0KDQogIGlmIChpID4gMSkNCiAgew0KICAgIGVzdCA9IGNiaW5kKGVzdCxtZWFuZXN0KQ0KICB9DQogIGVsc2UNCiAgew0KICAgIGVzdCA9IG1lYW5lc3QNCiAgfQ0KfQ0KDQpwICsgc2NhbGVfY29sb3JfaHVlKCkgKyBsYWJzKGNvbG9yPSJTYW1wbGUgc2l6ZSIpICsgDQogICAgZ2d0aXRsZShwYXN0ZSgiRGlzdHJpYnV0aW9uIG9mIFNhbXBsZXMgKHNpemVkIixpLCIpIikpICsNCiAgICAgICAgICAgIHhsYWIoInZhbHVlcyIpICsgeWxhYigiZGVuc2l0eSIpDQoNCmNvbG5hbWVzKGVzdCkgPSBzaXplcw0KDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QobXBnLGFlcyh4PWh3eSkpICsgZ2VvbV9kZW5zaXR5KGNvbD0iI0ZGMDAwMDk5IiwgZmlsbD0iIzk5MDAwMDk5IikNCmBgYA0KDQpgYGB7cixmaWcuaGVpZ2h0PTMsZmlnLndpZHRoPTd9DQpoID0gcm5vcm0oMTYwLDUwLDEwKQ0KDQpnZ3Bsb3QoKSsNCiAgZ2VvbV9saW5lKG1hcHBpbmc9YWVzKHg9aFsxOjVdLHk9Li5kZW5zaXR5Li4sY29sb3I9NSksc3RhdD0iZGVuc2l0eSIsbHdkPTMuNSkrDQogIGdlb21fbGluZShtYXBwaW5nPWFlcyh4PWhbMToxMF0seT0uLmRlbnNpdHkuLixjb2xvcj0xMCksc3RhdD0iZGVuc2l0eSIsbHdkPTMpICsNCiAgZ2VvbV9saW5lKG1hcHBpbmc9YWVzKHg9aFsxOjIwXSx5PS4uZGVuc2l0eS4uLGNvbG9yPTIwKSxzdGF0PSJkZW5zaXR5Iixsd2Q9Mi41KSArDQogIGdlb21fbGluZShtYXBwaW5nPWFlcyh4PWhbMTo0MF0seT0uLmRlbnNpdHkuLixjb2xvcj00MCksc3RhdD0iZGVuc2l0eSIsbHdkPTIpICsNCiAgbGFicyhjb2xvcj0iU2FtcGxlIHNpemUiKQ0KDQpgYGANCg0KDQoNCg0KIyMjIENvbXBhcmlzb24gb2YgZGlzdHJpYnV0aW9ucw0KDQoqIFBhcmFsbGVsIHBsb3RzDQoNCmBgYHtyfQ0KZ2dwbG90KG1wZyxhZXMoeD1od3kpKSArIGdlb21fZGVuc2l0eShjb2w9IiNGRjAwMDA5OSIsIGZpbGw9IiM5OTAwMDA5OSIpICsgZmFjZXRfZ3JpZChyb3dzPXZhcnMoeWVhcikpDQpgYGANCg0KKiBTdXBlcmltcG9zZWQgZGVuc2l0eSBjdXJ2ZXMNCg0KYGBge3IsZmlnLmNhcD0iQ29tcGFyaXNvbiBvZiBNUEcgYnkgWWVhciIsZmlnLndpZHRoPTcsZmlnLmhlaWdodD0zfQ0KZ2dwbG90KG1wZyxhZXMoeD1od3ksZ3JvdXA9eWVhcikpICsNCiAgZ2VvbV9kZW5zaXR5KG1hcHBpbmc9YWVzKGNvbG9yPWZhY3Rvcih5ZWFyKSksc2l6ZT0xLjIpDQpgYGANCg0KKiBEZW5zaXR5IGN1cnZlIG92ZXIgYSBoaXN0b2dyYW0NCg0KYGBge3IsZmlnLmNhcD0iQ29tcGFyaXNvbiBvZiBEZW5zaXR5IHRvIEhpc3RvZ3JhbSIsZmlnLndpZHRoPTcsZmlnLmhlaWdodD0zfQ0KZ2dwbG90KG1wZyxhZXMoeD1od3ksIHk9Li5kZW5zaXR5Li4pKSArIA0KZ2VvbV9oaXN0b2dyYW0oY29sb3I9InJlZCIsIGZpbGw9Im9yYW5nZSIsIGJpbnM9MTYpICsNCiAgZ2VvbV9saW5lKHN0YXQ9J2RlbnNpdHknLCBjb2xvcj0icmVkIiwgbHdkPTEuMiwgbHR5PTEsIGFkanVzdD0uNCkgKw0KYGBgDQoNCiogQ29tcGFyaXNvbiBvZiBzdXBlcmltcG9zZWQgZGVuc2l0eSBwbG90cyBmb3IgZGlmZmVyZW50IHllYXJzDQoNCg0KYGBge3IsZmlnLmNhcD0iRGVuc2l0eSBvZiBDdHkgYW5kIEh3eSBNUEcgYnkgeWVhciIsZmlnLndpZHRoPTcsZmlnLmhlaWdodD0zfQ0KZ2dwbG90KG1wZykgKyBnZW9tX2RlbnNpdHkobWFwcGluZyA9YWVzKHg9aHd5KSwgY29sPSIjRkYwMDAwOTkiLCBmaWxsPSIjOTkwMDAwOTkiKSArIGdlb21fZGVuc2l0eShtYXBwaW5nID1hZXMoeD1jdHkpLCBjb2w9IiMwMDAwRkY5OSIsIGZpbGw9IiMwMDAwRkY5OSIpICsgZmFjZXRfZ3JpZChyb3dzPXZhcnMoeWVhcikpDQpgYGANCioqIE1hcHBpbmcNCg0KYGBge3J9DQoNCmdncGxvdChueixhZXMobG9uZyxsYXQsZ3JvdXA9Z3JvdXApKSArIGdlb21fcG9seWdvbihmaWxsPSJyZWQiLCBjb2xvciA9ImJsYWNrIikrY29vcmRfcXVpY2ttYXAoKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShzcCkNCmxpYnJhcnkoR0FETVRvb2xzKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KTUFQIDwtIGdhZG1fc2YubG9hZENvdW50cmllcygiVEhBIiwgbGV2ZWwgPSAwKQ0KcGxvdG1hcChNQVApDQojIHRoYWkgPSBHQURNVG9vbHM6OnN1YnNldChNQVAsIGxldmVsPTAsIHJlZ2lvbnM9YygiVEhBIikpDQoNClRIQTIgPC0gZ2FkbV9nZXRCYWNrZ3JvdW5kKE1BUCwgIlRIQSIsICJvc20iKQ0KcGxvdG1hcChUSEEyLHRpdGxlPSdUaGFpbGFuZCcpDQpUSEEgPSBnYWRtX3NmX2xvYWRDb3VudHJpZXMoIlRIQSIsIGxldmVsPTEsIGJhc2VmaWxlPSIuLyIpDQpwbG90bWFwKFRIQSkNCmxpc3ROYW1lcyhUSEEsbGV2ZWw9MSkNCmxhbm5hID0gZ2FkbV9zdWJzZXQoVEhBLCAxLCBjKCJDaGlhbmcgUmFpIiwiQ2hpYW5nIE1haSIsIk1hZSBIb25nIFNvbiIsIkxhbXBodW4iLCJMYW1wYW5nIikpDQpwbG90bWFwKGxhbm5hKQ0KbG9uZ2l0dWRlIDwtIHJ1bmlmKDYsIG1pbj05OC4wLCBtYXggPSAxMDAuNSkNCmxhdGl0dWRlIDwtIHJ1bmlmKDYsIG1pbj0xOC4wLCBtYXggPSAyMC41KQ0KQ2FzZXMgPC0gcnVuaWYoNiwgMjUsIDExMikNCkRBVCA8LSBkYXRhLmZyYW1lKGxvbmdpdHVkZSwgbGF0aXR1ZGUsIENhc2VzKQ0KZG90cyhsYW5uYSwgREFULCBjb2xvcj0icmVkIiwgc2l6ZSA9IDgsIHZhbHVlID0gIkNhc2VzIikNCnByb3BEb3RzKGxhbm5hLCBkYXRhID0gREFULCB2YWx1ZT0iQ2FzZXMiLA0KICAgICAgICAgYnJlYWtzPWMoMCwgMTIuNSwgMjUsIDUwLCAxMDApLCByYW5nZSA9IGMoMCwgMTAwKSkNCg0KcmVnaW9ucyA9ICBjKCJDaGlhbmcgUmFpIiwiQ2hpYW5nIE1haSIsIk1hZSBIb25nIFNvbiIsIkxhbXBodW4iLCJMYW1wYW5nIikNCnZhbHVlcyAgPSBjKDIwLDEwMCw1LDE4LDMxKQ0KREFUMiA9IGRhdGEuZnJhbWUocmVnaW9ucyx2YWx1ZXMpDQpjaG9yb3BsZXRoKGxhbm5hLERBVDIsYWRtLmpvaW49InJlZ2lvbnMiLA0KICAgICAgICAgICAgdmFsdWUgPSAidmFsdWVzIiwNCiAgICAgICAgICAgYnJlYWtzID0gInNkIiwNCiAgICAgICAgICAgcGFsZXR0ZT0iT3JhbmdlcyIsDQogICAgICAgICAgIGxlZ2VuZCA9ICJQb3B1bGF0aW9uIiwNCiAgICAgICAgICAgdGl0bGU9IlBvcHVsYXRpb24gb2YgTGFubmEgVGFpIikNCg0KYGBgDQoNCg0KYGBge3J9DQoNCmxpYnJhcnkoZ2dwdWJyKQ0KZGF0YSgiVG9vdGhHcm93dGgiKQ0KVG9vdGhHcm93dGgkZG9zZSA8LSBhcy5mYWN0b3IoVG9vdGhHcm93dGgkZG9zZSkNCiMgQm94IHBsb3QNCnAgPC0gZ2dwbG90KFRvb3RoR3Jvd3RoLCBhZXMoeCA9IGRvc2UsIHkgPSBsZW4pKSArIA0KICBnZW9tX2JveHBsb3QoYWVzKGZpbGwgPSBzdXBwKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwMEFGQkIiLCAiI0U3QjgwMCIpKQ0KcA0KDQoNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoImdncHViciIpDQp0aGVtZV9zZXQoDQogIHRoZW1lX2J3KCkgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQ0KICApDQoNCg0KIyBMb2FkIGRhdGEgYW5kIGNvbnZlcnQgZG9zZSB0byBhIGZhY3RvciB2YXJpYWJsZQ0KZGF0YSgiVG9vdGhHcm93dGgiKQ0KVG9vdGhHcm93dGgkZG9zZSA8LSBhcy5mYWN0b3IoVG9vdGhHcm93dGgkZG9zZSkNCiMgQm94IHBsb3QNCnAgPC0gZ2dwbG90KFRvb3RoR3Jvd3RoLCBhZXMoeCA9IGRvc2UsIHkgPSBsZW4pKSArIA0KICBnZW9tX2JveHBsb3QoYWVzKGZpbGwgPSBzdXBwKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwMEFGQkIiLCAiI0U3QjgwMCIpKQ0KcA0KDQoNCiMgU3BsaXQgaW4gdmVydGljYWwgZGlyZWN0aW9uDQpwICsgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhzdXBwKSkNCg0KIyBTcGxpdCBpbiBob3Jpem9udGFsIGRpcmVjdGlvbg0KcCArIGZhY2V0X2dyaWQoY29scyA9IHZhcnMoc3VwcCkpDQoNCnAgKyBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKGRvc2UpLCBjb2xzID0gdmFycyhzdXBwKSkNCg0KcCArIGZhY2V0X3dyYXAodmFycyhkb3NlKSkNCg0KcCArIGZhY2V0X3dyYXAodmFycyhkb3NlKSwgbmNvbD0yKQ0KDQojIDEuIENyZWF0ZSBhIGJveCBwbG90IChicCkNCnAgPC0gZ2dwbG90KFRvb3RoR3Jvd3RoLCBhZXMoeCA9IGRvc2UsIHkgPSBsZW4pKQ0KYnhwIDwtIHAgKyBnZW9tX2JveHBsb3QoYWVzKGNvbG9yID0gZG9zZSkpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsImdyZWVuIiwiYmx1ZSIpKQ0KDQojIDIuIENyZWF0ZSBhIGRvdCBwbG90IChkcCkNCmRwIDwtIHAgKyBnZW9tX2RvdHBsb3QoYWVzKGNvbG9yID0gZG9zZSwgZmlsbCA9IGRvc2UpLCANCiAgICAgICAgICAgICAgICAgICAgICAgYmluYXhpcz0neScsIHN0YWNrZGlyPSdjZW50ZXInKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJyZWQiLCJncmVlbiIsImJsdWUiKSkgKyANCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygicmVkIiwiZ3JlZW4iLCJibHVlIikpDQoNCiMgMy4gQ3JlYXRlIGEgbGluZSBwbG90DQpscCA8LSBnZ3Bsb3QoZWNvbm9taWNzLCBhZXMoeCA9IGRhdGUsIHkgPSBwc2F2ZXJ0KSkgKyANCiAgZ2VvbV9saW5lKGNvbG9yID0gIiNFNDY3MjYiKSANCg0KDQpmaWd1cmUgPC0gZ2dhcnJhbmdlKGJ4cCwgZHAsIGxwLA0KICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJBIiwgIkIiLCAiQyIpLA0KICAgICAgICAgICAgICAgICAgICBuY29sID0gMiwgbnJvdyA9IDIpDQpmaWd1cmUNCg0KZ2dhcnJhbmdlKA0KICBscCwgICAgICAgICAgICAgICAgIyBGaXJzdCByb3cgd2l0aCBsaW5lIHBsb3QNCiAgIyBTZWNvbmQgcm93IHdpdGggYm94IGFuZCBkb3QgcGxvdHMNCiAgZ2dhcnJhbmdlKGJ4cCwgZHAsIG5jb2wgPSAyLCBsYWJlbHMgPSBjKCJCIiwgIkMiKSksIA0KICBucm93ID0gMiwgDQogIGxhYmVscyA9ICJBIiAgICAgICAjIExhYmVsIG9mIHRoZSBsaW5lIHBsb3QNCiAgKSANCmBgYA0KDQpgYGB7cixmaWcud2lkdGg9NywgZmlnLmhlaWdodD03fQ0KaCA9IHJub3JtKDEwMDAwMDAsNTAsMTApDQpzaXplcyA9IGMoNSwxMCwyMCw0MCw4MCwxNjAsMzIwKQ0KYXZnbGlzdCA9ICIiDQpmb3IgKHMgaW4gc2l6ZXMpDQp7DQogIGRsaXN0ID0gIiINCiAgDQogIGZvciAoaSBpbiAxOjIwKQ0KICB7DQogICAgZDEgPSBkZW5zaXR5KGhbc2FtcGxlKGgscyldLGFkanVzdD00KQ0KICAgIA0KICAgIGQyID0gY2JpbmQoZDEkeCxkMSR5LHJlcChzLGxlbmd0aChkMSR4KSkscmVwKGksbGVuZ3RoKGQxJHgpKSkNCiAgICBhMSA9IGMocyxtZWFuKGQxJHggKiBkMSR5KSkNCiAgICANCiAgICBpZiAobGVuZ3RoKGF2Z2xpc3QpIDwgMikNCiAgICB7DQogICAgICBhdmdsaXN0ID0gYTENCiAgICB9ICANCiAgICBlbHNlDQogICAgew0KICAgICAgYXZnbGlzdCA9IHJiaW5kKGF2Z2xpc3QsYTEpDQogICAgfQ0KICAgICAgICANCiAgICBpZiAobGVuZ3RoKGRsaXN0KSA8IDQpDQogICAgew0KICAgICAgZGxpc3QgPSBkMg0KICAgIH0gIA0KICAgIGVsc2UNCiAgICB7DQogICAgICBkbGlzdCA9IHJiaW5kKGRsaXN0LGQyKQ0KICAgIH0NCiAgfQ0KDQpkbGlzdCA9IGFzLmRhdGEuZnJhbWUoZGxpc3QpDQpjb2xuYW1lcyhkbGlzdCkgPSBjKCJ4IiwieSIsInMiLCJnIikNCmlmIChzID09IDUpDQp7DQogZ3JBID0gZ2dwbG90KGRsaXN0LCBhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKG1hcHBpbmc9YWVzKGdyb3VwPWcpLGNvbG9yPSIjRkYwMDAwMzMiLGx3ZD0xLjUpICsgeWxhYigiRGVuc2l0eSIpICsgeWxpbSgwLDAuMSkgKyBnZ3RpdGxlKCIobiA9IDUpIikNCn0NCmVsc2UgaWYgKHM9PTEwKQ0Kew0KICBnckIgPSBnZ3Bsb3QoZGxpc3QsIGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUobWFwcGluZz1hZXMoZ3JvdXA9ZyksY29sb3I9IiNGRjAwMDAzMyIsbHdkPTEuNSkgKyB5bGFiKCJEZW5zaXR5IikgKyB5bGltKDAsMC4xKSArIGdndGl0bGUoIihuID0gMTApIikNCn0NCmVsc2UgaWYgKHM9PTIwKQ0Kew0KICBnckMgPSBnZ3Bsb3QoZGxpc3QsIGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUobWFwcGluZz1hZXMoZ3JvdXA9ZyksY29sb3I9IiNGRjAwMDAzMyIsbHdkPTEpICsgeWxhYigiRGVuc2l0eSIpICsgeWxpbSgwLDAuMDcpICsgZ2d0aXRsZSgiKG4gPSAyMCkiKQ0KfQ0KZWxzZSBpZiAocz09NDApDQp7DQogIGdyRCA9IGdncGxvdChkbGlzdCwgYWVzKHg9eCx5PXkpKSArIGdlb21fbGluZShtYXBwaW5nPWFlcyhncm91cD1nKSxjb2xvcj0iI0ZGMDAwMDMzIixsd2Q9MSkgKyB5bGFiKCJEZW5zaXR5IikgKyB5bGltKDAsMC4wNykgKyBnZ3RpdGxlKCIobiA9IDQwKSIpDQp9DQplbHNlIGlmIChzPT04MCkNCnsNCiAgZ3JFID0gZ2dwbG90KGRsaXN0LCBhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKG1hcHBpbmc9YWVzKGdyb3VwPWcpLGNvbG9yPSIjRkYwMDAwMzMiLGx3ZD0xKSArIHlsYWIoIkRlbnNpdHkiKSArIHlsaW0oMCwwLjA2KSArIGdndGl0bGUoIihuID0gODApIikNCn0NCmVsc2UgaWYgKHM9PTE2MCkNCnsNCiAgZ3JGID0gZ2dwbG90KGRsaXN0LCBhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKG1hcHBpbmc9YWVzKGdyb3VwPWcpLGNvbG9yPSIjRkYwMDAwMzMiLGx3ZD0xKSArIHlsYWIoIkRlbnNpdHkiKSArIHlsaW0oMCwwLjA2KSArIGdndGl0bGUoIihuID0gMTYwKSIpDQp9DQplbHNlIGlmIChzPT0zMjApDQp7DQogIGdyRyA9IGdncGxvdChkbGlzdCwgYWVzKHg9eCx5PXkpKSArIGdlb21fbGluZShtYXBwaW5nPWFlcyhncm91cD1nKSxjb2xvcj0iI0ZGMDAwMDMzIixsd2Q9MSkgKyB5bGFiKCJEZW5zaXR5IikgKyAgZ2d0aXRsZSgiKG4gPSAzMjApIikNCn0NCg0KfQ0KDQpkMSA9IGRlbnNpdHkoaFtzYW1wbGUoaCxzKV0sYWRqdXN0PTQpDQogICAgDQpkMiA9IGNiaW5kKGQxJHgsZDEkeSxyZXAocyxsZW5ndGgoZDEkeCkpLHJlcChpLGxlbmd0aChkMSR4KSkpDQphMSA9IGMoMTAwMDAwMCxtZWFuKGQxJHggKiBkMSR5KSkNCmF2Z2xpc3QgPSByYmluZChhdmdsaXN0LGExKQ0KDQpnckggPSBnZ3Bsb3QoKSArIGdlb21fbGluZShtYXBwaW5nPWFlcyh4PWQxJHgseT1kMSR5KSxjb2xvcj0icmVkIixsd2Q9MSkgKyB5bGFiKCJEZW5zaXR5IikgKyB4bGFiKCJ4IikgKyBnZ3RpdGxlKCIobiA9IDEsMDAwLDAwMCkiKQ0KDQoNCmZpZ3VyZSA8LSBnZ2FycmFuZ2UoZ3JBLGdyQiwgZ3JDLCBnckQsIGdyRSwgZ3JGLCBnckcsZ3JILA0KICAgICAgbGFiZWxzID0gYygiQSIsIkIiLCJDIiwiRCIsIkUiLCJGIiwiRyIpLA0KICAgICAgbmNvbCA9IDIsIG5yb3cgPSA0KQ0KZmlndXJlDQoNCmBgYA0KDQpgYGB7cixmaWcud2lkdGg9NyxmaWcuaGVpZ2h0PTd9DQoNCiAgDQpjb2xuYW1lcyhhdmdsaXN0KSA9IGMoInNpeiIsIm1lYW4iKQ0KYXZnbGlzdCA9IGFzLmRhdGEuZnJhbWUoYXZnbGlzdCkNCg0KZ3JBID0gZ2dwbG90KGF2Z2xpc3QsYWVzKHg9ZmFjdG9yKHNpeikseT1tZWFuKSkgKyANCiAgZ2VvbV9ib3hwbG90KG1hcHBpbmc9YWVzKGdyb3VwPXNpeiksY29sb3I9InJlZCIpKw0KICB4bGFiKCJTYW1wbGUgc2l6ZSIpICsgeWxhYigiQ2FsY3VsYXRlZCBNZWFuIikNCg0KZ3JCID0gZ2dwbG90KGF2Z2xpc3QsYWVzKHg9ZmFjdG9yKHNpeikseT1tZWFuKSkgKyANCiAgZ2VvbV92aW9saW4obWFwcGluZz1hZXMoZ3JvdXA9c2l6KSxjb2xvcj0iYmx1ZSIsZmlsbD0iYmx1ZSIpICsNCiAgeGxhYigiU2FtcGxlIHNpemUiKSArIHlsYWIoIkNhbGN1bGF0ZWQgTWVhbiIpDQoNCmdyQyA9IGdncGxvdChhdmdsaXN0LGFlcyh4PWZhY3RvcihzaXopLHk9bWVhbikpICsgDQogIGdlb21fYm94cGxvdChtYXBwaW5nPWFlcyhncm91cD1zaXopLGNvbG9yPSJyZWQiKSsNCiAgZ2VvbV92aW9saW4obWFwcGluZz1hZXMoZ3JvdXA9c2l6KSxjb2xvcj0iIzAwMDA5OSIsZmlsbD0iIzAwMDA5OTk5IikgKw0KICB4bGFiKCJTYW1wbGUgc2l6ZSIpICsgeWxhYigiQ2FsY3VsYXRlZCBNZWFuIikNCg0KZmlndXJlIDwtIGdnYXJyYW5nZShnckEsZ3JCLCBnckMsDQogICAgICBsYWJlbHMgPSBjKCJBIiwiQiIsIkMiKSwNCiAgICAgIG5jb2wgPSAxLCBucm93ID0gMykNCmZpZ3VyZQ0KDQpgYGANCg0K