R PACKAGES

R Package: Downloader

install.packages('downloader')
library(downloader)

# Specify URL where file is stored
url <- "https://www.stats.govt.nz/assets/Uploads/Alcohol-available-for-consumption/Alcohol-available-for-consumption-Year-ended-December-2020/Download-data/alcohol-available-for-consumption-year-ended-december-2020-csv.csv"

# Specify destination where file should be saved
destfile<-"C:/Users/Name/Desktop/FE_HW2/alcohol for consumption.csv"
download.file(url,destfile)

R package: ggplot2

install.packages('ggplot2')
library(ggplot2)
#ggplot2: example 1 (boxplot)
P1 <- ggplot(msleep) +  #first layer
  geom_boxplot(aes(x = sleep_total, #second layer
                   y = vore,
                   fill = vore))
P1

#ggplot2: example 2 (line chart)
P2 <- ggplot(msleep) +
  geom_bar(aes(y = vore, fill = vore))
P2

#ggplot2: example 3 (scatterplot)
P3 <- ggplot(msleep) +
  geom_point(aes(x = bodywt,
                 y = sleep_total,
                 colour = vore))+
  scale_x_log10()
P3

## ggplot2ç example 4 (histogram=
P4<-ggplot(faithful) + 
  geom_histogram(aes(x = eruptions, fill = waiting < 60), position = 'dodge', alpha = 15, stat_bin = 30)   #all the specification of the histogram are
# made in the second layer, but if we wanted our graph more general we should have added a third layer.
P4

R Package: knitr

#Update all existing packages first
update.packages(ask = FALSE, repos = 'https://cran.r-project.org')
install.packages('knitr',repos = c('https://xran.yihui.org','https://cran.r-project.org'))
library(knitr)
# If options are not explicitly specified, knitr will try to guess reaasonable default settings
# A few manuals are available, such as the main manual and the graphics manual
# For a more organized reference, see knirt book

R Package: Knitr usng RMarkdown to create a report

Knitr Package: Introduction

Knitr is a package that allows for the creation of reports directly from R. The package enables to present in the form of a report the conglomerate of three major factors, namely chuncks of text, R code and the related output or result of the code. The report generated when employing the knitr package can have three formats: html, pdf and word.For more details on using Knitr, refer to https://yihui.org/knitr/.

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

summary(cars)

Including a chart without the code

It is also possible to insert charts in the report without showing the code, for example:

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot. ``

Including a chart with the code

It is possible as well to include a chart in the report and display the related code, for example:

plot(cars)

R Package: TTR

install.packages('TTR')
library(TTR)

R Package: urca

#Install and Load needed packages
install.packages("urca")
install.packages("AER")
library(urca)
library(AER)

#Dataset
data("EuStockMarkets")
DAXData<-EuStockMarkets[1:204,1]
plot(DAXData)

#Urca Package: Dickey-Fuller Test
DAX0 <- summary(ur.df(DAXData))
DAX0

#Test with type=none: no intercept, no trend
DAX1<- summary(ur.df(DAXData,type = "none",lags = 1))
DAX1

#Test with type=drift:intercept, no trend
DAX2<-summary(ur.df(DAXData,type = "drift",lags = 1,selectlags = "Fixed"))
DAX2

#Test with type=trend: intercept and trend
DAX3<- summary(ur.df(DAXData,type = "trend",lags = 1,selectlags = "Fixed"))
DAX3

R Package: zoo

# R PACKAGE: zoo
install.packages('zoo')
library('quantmod','zoo')

#Zoo Example 1
Data<-getSymbols('^GSPC',from='2021-01-01')

chartSeries(GSPC,theme = 'white',
            TA = 'addVo();addBBands();addCCI()',majorticks = 'weeks',majorticks='weeks',multicolor=T)

#Zoo Example 2
Data1 <- getSymbols('^DJI',from='2021-01-01')
chartSeries(DJI, theme = 'white',
            TA = 'addVo();addBBands();addCCI()',majorticks = 'weeks',majorticks = 'weeks',multicolor=T)

R FUNCTIONS

R Functions: creating mysum function example

GSPC_INDEX <- read.csv('C:\\Users\\Domenico\\Desktop\\Domenico\\University\\Erasmus courses\\Financial Econometrics\\GSPC.csv',
                       header = T)
my_data <- GSPC_INDEX$GSPC.Adjusted
diff_sum <- function(Y)
{
  Y = na.omit(Y)
  N = matrix(0, nrow = length(my_data), ncol = 1)
  N[1] = Y[1]
  for (i in 1:length(Y)-1)
  {
    N[i] = Y[i] - Y[i+1]
  }
  return(sum(N))
}
diff_sum(my_data)
sum(my_data)

R Function: plot()- generic X-Y plotting

#Install and load needed packages
install.packages('tidyverse')
library(tidyverse)

#Example 1: sin plot function
Sin_plot <- plot(
  sin, 
  from = -pi, 
  to   = 2 * pi,
  axes = FALSE,
  main = "Sin function"
)
axis(
  1,    # bottom axis
  pi * (-1:2), 
  c(expression(-pi), 0, expression(pi), expression(2 * pi))
)
axis(2) # left axis

#Example 2
#linear regression plot
linreg <- lm(dist ~ speed, cars) #linear regression, distance regressed on speed
linreg_coeffs <- coef(linreg) #coefficients of the linear regression
lineq <- paste("distance = ", linreg_coeffs[2], " * speed + ", linreg_coeffs[1])  # concatenate the vector and making the arguments characters
plot(cars, main = "Car distance by speed", sub = lineq, xlab = "speed", ylab = "distance", pch = 19) #plot
abline(linreg, col = "blue")  #add line of the regression

R Functions: SMA() and EMA()

#R PACKAGE TTR
install.packages('TTR')
install.packages('tidyquant')
library(TTR)
library(ggplot2)
library(quantmod)
library(tidyquant)

#SMA() Function

#Create a dataframe
AMZN_Data<-getSymbols("AMZN", from ='2020-01-01', to ='2021-01-01', warnings = FALSE, auto.assign = FALSE)
AMZN_Data <- data.frame(AMZN_Data)

#Change Names in the Dataframe
names(AMZN_Data)<-c('Open','High','Low','Close','Volume','Adjusted')

#Convert row names to a column
AMZN_Data$Date<-as.Date(rownames(AMZN_Data))

#Calculate the 5 and 25 days moving average
AMZN_Data$SMA5<-TTR::SMA(AMZN_Data$Close,n=5, na.omit = T)
AMZN_Data$SMA25<-TTR::SMA(AMZN_Data$Close,n=25, na.omit = T)
AMZN_Data <- na.omit(AMZN_Data)

#Plot the moving average
AMZN_SMA<-ggplot(AMZN_Data) +
  aes( y = AMZN_Data$Close, x=AMZN_Data$Date) +
  geom_line(aes(y=Close,color="Close")) +
  geom_line(aes(y=SMA5,color="SMA5")) +
  geom_line(aes(y=SMA25,color="SMA25")) +
  theme(panel.grid = element_line(colour="grey"),
  legend.position = 'top') +
  labs(title="SMA AMZ (Jan2020-Jan2021)",
  color="Prices")
AMZN_SMA

#EMA() Function
#Calculate the 5 and 25 days exponential moving average
AMZN_Data$EMA5<-TTR::EMA(AMZN_Data$Close,n=5,wilder = FALSE,ratio = NULL)
AMZN_Data$EMA25<-TTR::EMA(AMZN_Data$Close,n=25, wilder = FALSE,ratio = NULL)
AMZN_Data <- na.omit(AMZN_Data)

#Plot the moving average
AMZN_EMA<-ggplot(AMZN_Data, aes(x=Date)) +
  geom_candlestick(aes(ymin = AMZN_Data$Low, ymax = AMZN_Data$High, fill_up = 'green') +
  geom_line(aes(y=EMA5,color="EMA5")) +
  geom_line(aes(y=EMA25,color="EMA25")) +
  theme(panel.grid.major.y = element_line(colour="grey")) +
  theme(panel.grid.minor.y = element_line(colour="grey"),
  legend.position = "top") +
  labs(title="EMA AMZ (Jan2020-Jan2021)") +
  labs(color="Green"))
AMZN_EMA

R Function: FitAR

install.packages('FitAR')
library(FitAR)
library(quantmod)

#clear previous graphic
graphics.off()

#fetch data: monthly U.S. unemployment rate
getSymbols("UNRATE",src="FRED")
chartSeries(UNRATE)

#create a regular vector, instead of a xts-object
unrate <- as.numeric(UNRATE) 

#print last data
tail(UNRATE)

#fit exact MLE to AR(4)
ans1<-FitAR(unrate,4, lag.max = 'default')

#plot original data
TimeSeriesPlot(unrate, aspect=0.2,ylab = "Unemployment Rate",main = "Unemployment")

#simulate the fitted AR
w <-Boot.FitAR(ans1, R = 1, ARModel = ARp)
w1 <- Boot.FitAR(ans1, R = 1, ARModel = ARz)

#plot simulated data in green
lines(w, col='green')
lines(w1, col = 'red')

R CODE UNDERSTANDING

R Code Understanding: data.new<-merge(Ad(GSPC),Ad(DJI))

#Install and Load needed packages
install.packages('quantmod')
library('quantmod')

Data <- getSymbols('^GSPC', from = '2021-01-01')
chartSeries(GSPC, theme = 'white',
            TA='addVo();addBBands();addCCI()', majorticks = 'weeks', majorticks = 'weeks', multicolor = T)
Data_1 <- getSymbols('^DJI', from = '2021-01-01')
chartSeries(DJI, theme = 'white',
            TA='addVo();addBBands();addCCI()', majorticks = 'weeks', majorticks = 'weeks', multicolor = T)
Output <- merge(Ad(GSPC), Ad(DJI))
chart_Series(Ad(DJI))
chart_Series(Ad(GSPC))

R Code Understanding: sp.data<-getSymbols(^GSPC“,start=”1990-01-01", auto.assign=FALSE)

#Install and Load needed package
install.packages("quantmod")
library(quantmod)

#Read and return the data file for S&P500
#Option 1
sp.data<- getSymbols("^GSPC",start="1990-01-01",auto.assign = FALSE)

#Option 2
my_startdate <- as.Date("1990-01-01")
sp.data<- getSymbols("^GSPC",from=my_startdate,auto.assign = FALSE)

#Option 3
sp.data<- getSymbols("^GSPC",from="1990-01-01",auto.assign = FALSE)

R DATASETS

R Datasets: Rearrangement (unemployment datasets example)

#R DATASETS REARRANGEMENT: (une_rt_m.tsv and unemployment.csv)
#Load the Dataset
install.packages('tidyverse')
library('tidyverse')

une_rt_m <- read_tsv("C:\\Users\\Elisa\\Desktop\\FE_Assignment_6_data/une_rt_m.tsv")

#Delete one column (geographical info)
une_rt_m2 <- subset(une_rt_m,select = 2:50)

#Reverse order of columns 
une_rt_m2 <- une_rt_m2[,order(ncol(une_rt_m2):1)]

#Tidy Data (from columns to rows)
une_rt_m2 <- tidyr::pivot_longer(une_rt_m2, cols = 1:49, names_to = 'MonthYear', values_to = 'UnRate')
une_rt_m2 <- data.frame(une_rt_m2)

#Change Columns Name
names(une_rt_m2)[1]<-"MonthYear"
names(une_rt_m2)[2]<-"UnRate"
une_rt_m2 <- separate(une_rt_m2, MonthYear, sep = 'M', into = c('Year', 'Month'))
une_rt_m2 <- unite(une_rt_m2,Month, Year, col = "MonthYear", sep = "-")
as.Date(une_rt_m2$MonthYear, format('%M-%Y'))
as.numeric(une_rt_m2$UnRate)
na.omit(une_rt_m2$UnRate)

#Add Column
install.packages("dplyr")
library(dplyr)
une_rt_m2$RowID<-c(1:2131)
une_rt_m2<-une_rt_m2%>%relocate(RowID,.before = MonthYear)

R Datasets: Creation, Combination,Working and Summary (Fama-French and French Datasets example)

#Create a Dataset and combine the data
#Load datasets
Developed_3_Factors <- read.csv('C:\\Users\\Domenico\\Desktop\\Assignment_5\\Developed_3_Factors_YearMonth.csv', 
                                header = T)
mydata <- read.csv('C:\\Users\\Domenico\\Desktop\\Assignment_5\\F-F_Size_Portfolios_formed_on_ME_Value_Weight_Returns_Monthly.csv', 
                   header = T)

#Remove unnecessary columns and/or rows
F_F_Size <- mydata[-c(1:768),-c(2,3,4,5)]

#Merge datasets
New_data <- merge(F_F_Size, Developed_3_Factors)


#Create a CAPM for Lo Portfolio
#Linear Regression Function
Lo.10.capm <- lm(New_data$"Lo.10" ~ New_data$Mkt.RF)

#Coefficients
coef(Lo.10.capm)

#Summary of coefficients and important statistics tests
mod.s1<-summary(Lo.10.capm)

values1<-vector() #Empty vector
values1[1]<-mod.s1$r.squared
values1[2]<-mod.s1$adj.r.squared
f.stat<-mod.s1$fstatistic
values1[3]<-f.stat[1]
values1[4]<-f.stat[2]
values1[5]<-f.stat[3]
values1[6]<-pf(values1[3],values1[4],values1[5],lower.tail = FALSE) #Create F-Distribution
values1[7]<-values1[1]/(1-values1[1])
values1.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2") #Names of the variables put in the vector
values1.m<-cbind(round(values1,digits=5)) #bind by columns
rownames(values1.m)<-values1.et #Assign names to the binded row vectors
colnames(values1.m) <- c('Lo.10.capm') #Name of the column

#Summary
ris1<-cbind(coef(mod.s1)[,1],coef(mod.s1)[,3:4])
colnames(ris1) <- c('Estimate', 't-value', 'Pr>|t|')
####################################
Qnt2.capm <- lm(New_data$"Qnt.2" ~ New_data$Mkt.RF)
coef(Qnt2.capm)
mod.s2<-summary(Qnt2.capm)
values2<-vector()
values2[1]<-mod.s2$r.squared
values2[2]<-mod.s2$adj.r.squared
f.stat<-mod.s2$fstatistic
values2[3]<-f.stat[1]
values2[4]<-f.stat[2]
values2[5]<-f.stat[3]
values2[6]<-pf(values2[3],values2[4],values2[5],lower.tail = FALSE)
values2[7]<-values2[1]/(1-values2[1])
values2.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values2.m<-cbind(round(values2,digits=5))
rownames(values2.m)<-values2.et
colnames(values2.m) <- c('Qnt2.capm')

ris2<-cbind(coef(mod.s2)[,1],coef(mod.s2)[,3:4])
colnames(ris2) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
Qnt3.capm <- lm(New_data$"Qnt.3" ~ New_data$Mkt.RF)
coef(Qnt2.capm)
mod.s3<-summary(Qnt2.capm)
values3<-vector()
values3[1]<-mod.s3$r.squared
values3[2]<-mod.s3$adj.r.squared
f.stat<-mod.s3$fstatistic
values3[3]<-f.stat[1]
values3[4]<-f.stat[2]
values3[5]<-f.stat[3]
values3[6]<-pf(values3[3],values3[4],values3[5],lower.tail = FALSE)
values3[7]<-values2[1]/(1-values2[1])
values3.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values3.m<-cbind(round(values3,digits=5))
rownames(values3.m)<-values3.et
colnames(values3.m) <- c('Qnt3.capm')

ris3<-cbind(coef(mod.s3)[,1],coef(mod.s3)[,3:4])
colnames(ris3) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
Qnt4.capm <- lm(New_data$"Qnt.4" ~ New_data$Mkt.RF)
coef(Qnt4.capm)
mod.s4<-summary(Qnt4.capm)
values4<-vector()
values4[1]<-mod.s4$r.squared
values4[2]<-mod.s4$adj.r.squared
f.stat<-mod.s4$fstatistic
values4[3]<-f.stat[1]
values4[4]<-f.stat[2]
values4[5]<-f.stat[3]
values4[6]<-pf(values4[3],values4[4],values4[5],lower.tail = FALSE)
values4[7]<-values4[1]/(1-values4[1])
values4.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values4.m<-cbind(round(values4,digits=5))
rownames(values4.m)<-values4.et
colnames(values4.m) <- c('Qnt4.capm')

ris4<-cbind(coef(mod.s4)[,1],coef(mod.s4)[,3:4])
colnames(ris4) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
Hi.20.capm <- lm(New_data$"Hi.20" ~ New_data$Mkt.RF)
coef(Hi.20.capm)
mod.s5<-summary(Hi.20.capm)
values5<-vector()
values5[1]<-mod.s5$r.squared
values5[2]<-mod.s5$adj.r.squared
f.stat<-mod.s5$fstatistic
values5[3]<-f.stat[1]
values5[4]<-f.stat[2]
values5[5]<-f.stat[3]
values5[6]<-pf(values5[3],values5[4],values5[5],lower.tail = FALSE)
values5[7]<-values5[1]/(1-values5[1])
values5.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values5.m<-cbind(round(values5,digits=5))
rownames(values5.m)<-values5.et
colnames(values5.m) <- c('Hi.20.capm')


ris5<-cbind(coef(mod.s5)[,1],coef(mod.s5)[,3:4])
colnames(ris5) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
Dec.2.capm <- lm(New_data$"Dec.2" ~ New_data$Mkt.RF)
coef(Dec.2.capm)
mod.s6<-summary(Dec.2.capm)
values6<-vector()
values6[1]<-mod.s6$r.squared
values6[2]<-mod.s6$adj.r.squared
f.stat<-mod.s6$fstatistic
values6[3]<-f.stat[1]
values6[4]<-f.stat[2]
values6[5]<-f.stat[3]
values6[6]<-pf(values6[3],values6[4],values6[5],lower.tail = FALSE)
values6[7]<-values6[1]/(1-values6[1])
values6.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values6.m<-cbind(round(values6,digits=5))
rownames(values6.m)<-values6.et
colnames(values6.m) <- c('Dec.2.capm')

ris6<-cbind(coef(mod.s6)[,1],coef(mod.s6)[,3:4])
colnames(ris6) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
Dec.3.capm <- lm(New_data$"Dec.3" ~ New_data$Mkt.RF)
coef(Dec.3.capm)
mod.s7<-summary(Dec.3.capm)
values7<-vector()
values7[1]<-mod.s7$r.squared
values7[2]<-mod.s7$adj.r.squared
f.stat<-mod.s7$fstatistic
values7[3]<-f.stat[1]
values7[4]<-f.stat[2]
values7[5]<-f.stat[3]
values7[6]<-pf(values7[3],values7[4],values7[5],lower.tail = FALSE)
values7[7]<-values7[1]/(1-values7[1])
values7.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values7.m<-cbind(round(values7,digits=5))
rownames(values6.m)<-values7.et
colnames(values6.m) <- c('Dec.3.capm')

ris7<-cbind(coef(mod.s7)[,1],coef(mod.s7)[,3:4])
colnames(ris7) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
Dec.4.capm <- lm(New_data$"Dec.4" ~ New_data$Mkt.RF)
coef(Dec.4.capm)
mod.s8<-summary(Dec.4.capm)
values8<-vector()
values8[1]<-mod.s8$r.squared
values8[2]<-mod.s8$adj.r.squared
f.stat<-mod.s8$fstatistic
values8[3]<-f.stat[1]
values8[4]<-f.stat[2]
values8[5]<-f.stat[3]
values8[6]<-pf(values8[3],values8[4],values8[5],lower.tail = FALSE)
values8[7]<-values8[1]/(1-values8[1])
values8.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values8.m<-cbind(round(values8,digits=5))
rownames(values8.m)<-values8.et
colnames(values8.m) <- c('Dec.4.capm')

ris8<-cbind(coef(mod.s8)[,1],coef(mod.s8)[,3:4])
colnames(ris8) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
Dec.5.capm <- lm(New_data$"Dec.5" ~ New_data$Mkt.RF)
coef(Dec.5.capm)
mod.s9<-summary(Dec.5.capm)
values9<-vector()
values9[1]<-mod.s9$r.squared
values9[2]<-mod.s9$adj.r.squared
f.stat<-mod.s9$fstatistic
values9[3]<-f.stat[1]
values9[4]<-f.stat[2]
values9[5]<-f.stat[3]
values9[6]<-pf(values9[3],values9[4],values9[5],lower.tail = FALSE)
values9[7]<-values9[1]/(1-values9[1])
values9.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values9.m<-cbind(round(values6,digits=5))
rownames(values9.m)<-values6.et
colnames(values9.m) <- c('Dec.5.capm')

ris9<-cbind(coef(mod.s9)[,1],coef(mod.s9)[,3:4])
colnames(ris9) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
Dec.6.capm <- lm(New_data$"Dec.6" ~ New_data$Mkt.RF)
coef(Dec.6.capm)
mod.s10<-summary(Dec.6.capm)
values10<-vector()
values10[1]<-mod.s10$r.squared
values10[2]<-mod.s10$adj.r.squared
f.stat<-mod.s10$fstatistic
values10[3]<-f.stat[1]
values10[4]<-f.stat[2]
values10[5]<-f.stat[3]
values10[6]<-pf(values10[3],values10[4],values10[5],lower.tail = FALSE)
values10[7]<-values10[1]/(1-values10[1])
values10.et<-c("R^2","adj R^2","F","df num.","df den.","p(F)","f^2")
values10.m<-cbind(round(values10,digits=5))
rownames(values10.m)<-values10.et
colnames(values10.m) <- c('Dec.6.capm')

ris10<-cbind(coef(mod.s10)[,1],coef(mod.s10)[,3:4])
colnames(ris10) <- c('Estimate', 't-value', 'Pr>|t|')
#####################################
SUMMARY <-cbind(values1.m, values2.m, values3.m, values4.m, values5.m, values6.m, values7.m, values8.m, values9.m, values10.m)
T_values <- rbind(ris1, ris2, ris3, ris4, ris5, ris6, ris7, ris8, ris9, ris10)
LS0tDQp0aXRsZTogIkZFIC0gQW5hbHlzaXMgUmVwb3J0Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQpncm91cDogIkdST1VQIEEiDQphdXRob3JzOiAiQ2hyaXN0b3BoZXIgRnJ1dGgsIERvbWVuaWNvIEQnRWxpYSwgRWxpc2EgTWVkZW90LCBKb2hhbm5hIFVsZW5pdXMtUGVudHRpbmVuLCBaZXdlbCBIYXNpYnVyIC0gTUJDaSAyMDIwIg0KLS0tDQoNCiMgUiBQQUNLQUdFUw0KDQojIyBSIFBhY2thZ2U6IERvd25sb2FkZXINCg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCdkb3dubG9hZGVyJykNCmxpYnJhcnkoZG93bmxvYWRlcikNCg0KIyBTcGVjaWZ5IFVSTCB3aGVyZSBmaWxlIGlzIHN0b3JlZA0KdXJsIDwtICJodHRwczovL3d3dy5zdGF0cy5nb3Z0Lm56L2Fzc2V0cy9VcGxvYWRzL0FsY29ob2wtYXZhaWxhYmxlLWZvci1jb25zdW1wdGlvbi9BbGNvaG9sLWF2YWlsYWJsZS1mb3ItY29uc3VtcHRpb24tWWVhci1lbmRlZC1EZWNlbWJlci0yMDIwL0Rvd25sb2FkLWRhdGEvYWxjb2hvbC1hdmFpbGFibGUtZm9yLWNvbnN1bXB0aW9uLXllYXItZW5kZWQtZGVjZW1iZXItMjAyMC1jc3YuY3N2Ig0KDQojIFNwZWNpZnkgZGVzdGluYXRpb24gd2hlcmUgZmlsZSBzaG91bGQgYmUgc2F2ZWQNCmRlc3RmaWxlPC0iQzovVXNlcnMvTmFtZS9EZXNrdG9wL0ZFX0hXMi9hbGNvaG9sIGZvciBjb25zdW1wdGlvbi5jc3YiDQpkb3dubG9hZC5maWxlKHVybCxkZXN0ZmlsZSkNCmBgYA0KDQojIyBSIHBhY2thZ2U6IGdncGxvdDINCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygnZ2dwbG90MicpDQpsaWJyYXJ5KGdncGxvdDIpDQojZ2dwbG90MjogZXhhbXBsZSAxIChib3hwbG90KQ0KUDEgPC0gZ2dwbG90KG1zbGVlcCkgKyAgI2ZpcnN0IGxheWVyDQogIGdlb21fYm94cGxvdChhZXMoeCA9IHNsZWVwX3RvdGFsLCAjc2Vjb25kIGxheWVyDQogICAgICAgICAgICAgICAgICAgeSA9IHZvcmUsDQogICAgICAgICAgICAgICAgICAgZmlsbCA9IHZvcmUpKQ0KUDENCg0KI2dncGxvdDI6IGV4YW1wbGUgMiAobGluZSBjaGFydCkNClAyIDwtIGdncGxvdChtc2xlZXApICsNCiAgZ2VvbV9iYXIoYWVzKHkgPSB2b3JlLCBmaWxsID0gdm9yZSkpDQpQMg0KDQojZ2dwbG90MjogZXhhbXBsZSAzIChzY2F0dGVycGxvdCkNClAzIDwtIGdncGxvdChtc2xlZXApICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGJvZHl3dCwNCiAgICAgICAgICAgICAgICAgeSA9IHNsZWVwX3RvdGFsLA0KICAgICAgICAgICAgICAgICBjb2xvdXIgPSB2b3JlKSkrDQogIHNjYWxlX3hfbG9nMTAoKQ0KUDMNCg0KIyMgZ2dwbG90MsOnIGV4YW1wbGUgNCAoaGlzdG9ncmFtPQ0KUDQ8LWdncGxvdChmYWl0aGZ1bCkgKyANCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBlcnVwdGlvbnMsIGZpbGwgPSB3YWl0aW5nIDwgNjApLCBwb3NpdGlvbiA9ICdkb2RnZScsIGFscGhhID0gMTUsIHN0YXRfYmluID0gMzApICAgI2FsbCB0aGUgc3BlY2lmaWNhdGlvbiBvZiB0aGUgaGlzdG9ncmFtIGFyZQ0KIyBtYWRlIGluIHRoZSBzZWNvbmQgbGF5ZXIsIGJ1dCBpZiB3ZSB3YW50ZWQgb3VyIGdyYXBoIG1vcmUgZ2VuZXJhbCB3ZSBzaG91bGQgaGF2ZSBhZGRlZCBhIHRoaXJkIGxheWVyLg0KUDQNCmBgYA0KDQojIyBSIFBhY2thZ2U6IGtuaXRyDQpgYGB7cn0NCiNVcGRhdGUgYWxsIGV4aXN0aW5nIHBhY2thZ2VzIGZpcnN0DQp1cGRhdGUucGFja2FnZXMoYXNrID0gRkFMU0UsIHJlcG9zID0gJ2h0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnJykNCmluc3RhbGwucGFja2FnZXMoJ2tuaXRyJyxyZXBvcyA9IGMoJ2h0dHBzOi8veHJhbi55aWh1aS5vcmcnLCdodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZycpKQ0KbGlicmFyeShrbml0cikNCiMgSWYgb3B0aW9ucyBhcmUgbm90IGV4cGxpY2l0bHkgc3BlY2lmaWVkLCBrbml0ciB3aWxsIHRyeSB0byBndWVzcyByZWFhc29uYWJsZSBkZWZhdWx0IHNldHRpbmdzDQojIEEgZmV3IG1hbnVhbHMgYXJlIGF2YWlsYWJsZSwgc3VjaCBhcyB0aGUgbWFpbiBtYW51YWwgYW5kIHRoZSBncmFwaGljcyBtYW51YWwNCiMgRm9yIGEgbW9yZSBvcmdhbml6ZWQgcmVmZXJlbmNlLCBzZWUga25pcnQgYm9vaw0KYGBgDQoNCiMjIFIgUGFja2FnZTogS25pdHIgdXNuZyBSTWFya2Rvd24gdG8gY3JlYXRlIGEgcmVwb3J0DQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIyBLbml0ciBQYWNrYWdlOiBJbnRyb2R1Y3Rpb24NCg0KS25pdHIgaXMgYSBwYWNrYWdlICB0aGF0IGFsbG93cyBmb3IgdGhlIGNyZWF0aW9uIG9mIHJlcG9ydHMgZGlyZWN0bHkgZnJvbSBSLiBUaGUgcGFja2FnZSBlbmFibGVzIHRvIHByZXNlbnQgaW4gdGhlIGZvcm0gb2YgYSByZXBvcnQgdGhlIGNvbmdsb21lcmF0ZSBvZiB0aHJlZSBtYWpvciBmYWN0b3JzLCBuYW1lbHkgY2h1bmNrcyBvZiB0ZXh0LCBSIGNvZGUgYW5kIHRoZSByZWxhdGVkIG91dHB1dCBvciByZXN1bHQgb2YgdGhlIGNvZGUuIFRoZSByZXBvcnQgZ2VuZXJhdGVkIHdoZW4gZW1wbG95aW5nIHRoZSBrbml0ciBwYWNrYWdlIGNhbiBoYXZlIHRocmVlIGZvcm1hdHM6IGh0bWwsIHBkZiBhbmQgd29yZC5Gb3IgbW9yZSBkZXRhaWxzIG9uIHVzaW5nIEtuaXRyLCByZWZlciB0byA8aHR0cHM6Ly95aWh1aS5vcmcva25pdHIvPi4NCg0KV2hlbiB5b3UgY2xpY2sgdGhlICoqS25pdCoqIGJ1dHRvbiBhIGRvY3VtZW50IHdpbGwgYmUgZ2VuZXJhdGVkIHRoYXQgaW5jbHVkZXMgYm90aCBjb250ZW50IGFzIHdlbGwgYXMgdGhlIG91dHB1dCBvZiBhbnkgZW1iZWRkZWQgUiBjb2RlIGNodW5rcyB3aXRoaW4gdGhlIGRvY3VtZW50LiBZb3UgY2FuIGVtYmVkIGFuIFIgY29kZSBjaHVuayBsaWtlIHRoaXM6DQoNCmBgYHtyIGNhcnN9DQpzdW1tYXJ5KGNhcnMpDQpgYGANCg0KIyMgSW5jbHVkaW5nIGEgY2hhcnQgd2l0aG91dCB0aGUgY29kZQ0KDQpJdCBpcyBhbHNvIHBvc3NpYmxlIHRvIGluc2VydCBjaGFydHMgaW4gdGhlIHJlcG9ydCB3aXRob3V0IHNob3dpbmcgdGhlIGNvZGUsIGZvciBleGFtcGxlOg0KDQpgYGB7ciBwcmVzc3VyZSwgZWNobz1GQUxTRX0NCnBsb3QoY2FycykNCmBgYA0KDQpOb3RlIHRoYXQgdGhlIGBlY2hvID0gRkFMU0VgIHBhcmFtZXRlciB3YXMgYWRkZWQgdG8gdGhlIGNvZGUgY2h1bmsgdG8gcHJldmVudCBwcmludGluZyBvZiB0aGUgUiBjb2RlIHRoYXQgZ2VuZXJhdGVkIHRoZSBwbG90Lg0KYGANCg0KIyMgSW5jbHVkaW5nIGEgY2hhcnQgd2l0aCB0aGUgY29kZQ0KDQpJdCBpcyBwb3NzaWJsZSBhcyB3ZWxsIHRvIGluY2x1ZGUgYSBjaGFydCBpbiB0aGUgcmVwb3J0IGFuZCBkaXNwbGF5IHRoZSByZWxhdGVkIGNvZGUsIGZvciBleGFtcGxlOg0KDQpgYGB7ciBkZXByZXNzdXJlLCBlY2hvPVRSVUV9DQpwbG90KGNhcnMpDQpgYGANCg0KDQojIyBSIFBhY2thZ2U6IFRUUg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCdUVFInKQ0KbGlicmFyeShUVFIpDQpgYGANCg0KDQojIyBSIFBhY2thZ2U6IHVyY2ENCmBgYHtyfQ0KI0luc3RhbGwgYW5kIExvYWQgbmVlZGVkIHBhY2thZ2VzDQppbnN0YWxsLnBhY2thZ2VzKCJ1cmNhIikNCmluc3RhbGwucGFja2FnZXMoIkFFUiIpDQpsaWJyYXJ5KHVyY2EpDQpsaWJyYXJ5KEFFUikNCg0KI0RhdGFzZXQNCmRhdGEoIkV1U3RvY2tNYXJrZXRzIikNCkRBWERhdGE8LUV1U3RvY2tNYXJrZXRzWzE6MjA0LDFdDQpwbG90KERBWERhdGEpDQoNCiNVcmNhIFBhY2thZ2U6IERpY2tleS1GdWxsZXIgVGVzdA0KREFYMCA8LSBzdW1tYXJ5KHVyLmRmKERBWERhdGEpKQ0KREFYMA0KDQojVGVzdCB3aXRoIHR5cGU9bm9uZTogbm8gaW50ZXJjZXB0LCBubyB0cmVuZA0KREFYMTwtIHN1bW1hcnkodXIuZGYoREFYRGF0YSx0eXBlID0gIm5vbmUiLGxhZ3MgPSAxKSkNCkRBWDENCg0KI1Rlc3Qgd2l0aCB0eXBlPWRyaWZ0OmludGVyY2VwdCwgbm8gdHJlbmQNCkRBWDI8LXN1bW1hcnkodXIuZGYoREFYRGF0YSx0eXBlID0gImRyaWZ0IixsYWdzID0gMSxzZWxlY3RsYWdzID0gIkZpeGVkIikpDQpEQVgyDQoNCiNUZXN0IHdpdGggdHlwZT10cmVuZDogaW50ZXJjZXB0IGFuZCB0cmVuZA0KREFYMzwtIHN1bW1hcnkodXIuZGYoREFYRGF0YSx0eXBlID0gInRyZW5kIixsYWdzID0gMSxzZWxlY3RsYWdzID0gIkZpeGVkIikpDQpEQVgzDQpgYGANCg0KDQojIyBSIFBhY2thZ2U6IHpvbw0KYGBge3J9DQojIFIgUEFDS0FHRTogem9vDQppbnN0YWxsLnBhY2thZ2VzKCd6b28nKQ0KbGlicmFyeSgncXVhbnRtb2QnLCd6b28nKQ0KDQojWm9vIEV4YW1wbGUgMQ0KRGF0YTwtZ2V0U3ltYm9scygnXkdTUEMnLGZyb209JzIwMjEtMDEtMDEnKQ0KDQpjaGFydFNlcmllcyhHU1BDLHRoZW1lID0gJ3doaXRlJywNCiAgICAgICAgICAgIFRBID0gJ2FkZFZvKCk7YWRkQkJhbmRzKCk7YWRkQ0NJKCknLG1ham9ydGlja3MgPSAnd2Vla3MnLG1ham9ydGlja3M9J3dlZWtzJyxtdWx0aWNvbG9yPVQpDQoNCiNab28gRXhhbXBsZSAyDQpEYXRhMSA8LSBnZXRTeW1ib2xzKCdeREpJJyxmcm9tPScyMDIxLTAxLTAxJykNCmNoYXJ0U2VyaWVzKERKSSwgdGhlbWUgPSAnd2hpdGUnLA0KICAgICAgICAgICAgVEEgPSAnYWRkVm8oKTthZGRCQmFuZHMoKTthZGRDQ0koKScsbWFqb3J0aWNrcyA9ICd3ZWVrcycsbWFqb3J0aWNrcyA9ICd3ZWVrcycsbXVsdGljb2xvcj1UKQ0KYGBgDQoNCg0KIyBSIEZVTkNUSU9OUw0KIyBSIEZ1bmN0aW9uczogY3JlYXRpbmcgbXlzdW0gZnVuY3Rpb24gZXhhbXBsZQ0KYGBge3J9DQpHU1BDX0lOREVYIDwtIHJlYWQuY3N2KCdDOlxcVXNlcnNcXERvbWVuaWNvXFxEZXNrdG9wXFxEb21lbmljb1xcVW5pdmVyc2l0eVxcRXJhc211cyBjb3Vyc2VzXFxGaW5hbmNpYWwgRWNvbm9tZXRyaWNzXFxHU1BDLmNzdicsDQogICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFQpDQpteV9kYXRhIDwtIEdTUENfSU5ERVgkR1NQQy5BZGp1c3RlZA0KZGlmZl9zdW0gPC0gZnVuY3Rpb24oWSkNCnsNCiAgWSA9IG5hLm9taXQoWSkNCiAgTiA9IG1hdHJpeCgwLCBucm93ID0gbGVuZ3RoKG15X2RhdGEpLCBuY29sID0gMSkNCiAgTlsxXSA9IFlbMV0NCiAgZm9yIChpIGluIDE6bGVuZ3RoKFkpLTEpDQogIHsNCiAgICBOW2ldID0gWVtpXSAtIFlbaSsxXQ0KICB9DQogIHJldHVybihzdW0oTikpDQp9DQpkaWZmX3N1bShteV9kYXRhKQ0Kc3VtKG15X2RhdGEpDQpgYGANCg0KDQojIyBSIEZ1bmN0aW9uOiBwbG90KCktIGdlbmVyaWMgWC1ZIHBsb3R0aW5nIA0KYGBge3J9DQojSW5zdGFsbCBhbmQgbG9hZCBuZWVkZWQgcGFja2FnZXMNCmluc3RhbGwucGFja2FnZXMoJ3RpZHl2ZXJzZScpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KI0V4YW1wbGUgMTogc2luIHBsb3QgZnVuY3Rpb24NClNpbl9wbG90IDwtIHBsb3QoDQogIHNpbiwgDQogIGZyb20gPSAtcGksIA0KICB0byAgID0gMiAqIHBpLA0KICBheGVzID0gRkFMU0UsDQogIG1haW4gPSAiU2luIGZ1bmN0aW9uIg0KKQ0KYXhpcygNCiAgMSwgICAgIyBib3R0b20gYXhpcw0KICBwaSAqICgtMToyKSwgDQogIGMoZXhwcmVzc2lvbigtcGkpLCAwLCBleHByZXNzaW9uKHBpKSwgZXhwcmVzc2lvbigyICogcGkpKQ0KKQ0KYXhpcygyKSAjIGxlZnQgYXhpcw0KDQojRXhhbXBsZSAyDQojbGluZWFyIHJlZ3Jlc3Npb24gcGxvdA0KbGlucmVnIDwtIGxtKGRpc3QgfiBzcGVlZCwgY2FycykgI2xpbmVhciByZWdyZXNzaW9uLCBkaXN0YW5jZSByZWdyZXNzZWQgb24gc3BlZWQNCmxpbnJlZ19jb2VmZnMgPC0gY29lZihsaW5yZWcpICNjb2VmZmljaWVudHMgb2YgdGhlIGxpbmVhciByZWdyZXNzaW9uDQpsaW5lcSA8LSBwYXN0ZSgiZGlzdGFuY2UgPSAiLCBsaW5yZWdfY29lZmZzWzJdLCAiICogc3BlZWQgKyAiLCBsaW5yZWdfY29lZmZzWzFdKSAgIyBjb25jYXRlbmF0ZSB0aGUgdmVjdG9yIGFuZCBtYWtpbmcgdGhlIGFyZ3VtZW50cyBjaGFyYWN0ZXJzDQpwbG90KGNhcnMsIG1haW4gPSAiQ2FyIGRpc3RhbmNlIGJ5IHNwZWVkIiwgc3ViID0gbGluZXEsIHhsYWIgPSAic3BlZWQiLCB5bGFiID0gImRpc3RhbmNlIiwgcGNoID0gMTkpICNwbG90DQphYmxpbmUobGlucmVnLCBjb2wgPSAiYmx1ZSIpICAjYWRkIGxpbmUgb2YgdGhlIHJlZ3Jlc3Npb24NCg0KYGBgDQoNCg0KIyMgUiBGdW5jdGlvbnM6IFNNQSgpIGFuZCBFTUEoKQ0KDQpgYGB7cn0NCiNSIFBBQ0tBR0UgVFRSDQppbnN0YWxsLnBhY2thZ2VzKCdUVFInKQ0KaW5zdGFsbC5wYWNrYWdlcygndGlkeXF1YW50JykNCmxpYnJhcnkoVFRSKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShxdWFudG1vZCkNCmxpYnJhcnkodGlkeXF1YW50KQ0KDQojU01BKCkgRnVuY3Rpb24NCg0KI0NyZWF0ZSBhIGRhdGFmcmFtZQ0KQU1aTl9EYXRhPC1nZXRTeW1ib2xzKCJBTVpOIiwgZnJvbSA9JzIwMjAtMDEtMDEnLCB0byA9JzIwMjEtMDEtMDEnLCB3YXJuaW5ncyA9IEZBTFNFLCBhdXRvLmFzc2lnbiA9IEZBTFNFKQ0KQU1aTl9EYXRhIDwtIGRhdGEuZnJhbWUoQU1aTl9EYXRhKQ0KDQojQ2hhbmdlIE5hbWVzIGluIHRoZSBEYXRhZnJhbWUNCm5hbWVzKEFNWk5fRGF0YSk8LWMoJ09wZW4nLCdIaWdoJywnTG93JywnQ2xvc2UnLCdWb2x1bWUnLCdBZGp1c3RlZCcpDQoNCiNDb252ZXJ0IHJvdyBuYW1lcyB0byBhIGNvbHVtbg0KQU1aTl9EYXRhJERhdGU8LWFzLkRhdGUocm93bmFtZXMoQU1aTl9EYXRhKSkNCg0KI0NhbGN1bGF0ZSB0aGUgNSBhbmQgMjUgZGF5cyBtb3ZpbmcgYXZlcmFnZQ0KQU1aTl9EYXRhJFNNQTU8LVRUUjo6U01BKEFNWk5fRGF0YSRDbG9zZSxuPTUsIG5hLm9taXQgPSBUKQ0KQU1aTl9EYXRhJFNNQTI1PC1UVFI6OlNNQShBTVpOX0RhdGEkQ2xvc2Usbj0yNSwgbmEub21pdCA9IFQpDQpBTVpOX0RhdGEgPC0gbmEub21pdChBTVpOX0RhdGEpDQoNCiNQbG90IHRoZSBtb3ZpbmcgYXZlcmFnZQ0KQU1aTl9TTUE8LWdncGxvdChBTVpOX0RhdGEpICsNCiAgYWVzKCB5ID0gQU1aTl9EYXRhJENsb3NlLCB4PUFNWk5fRGF0YSREYXRlKSArDQogIGdlb21fbGluZShhZXMoeT1DbG9zZSxjb2xvcj0iQ2xvc2UiKSkgKw0KICBnZW9tX2xpbmUoYWVzKHk9U01BNSxjb2xvcj0iU01BNSIpKSArDQogIGdlb21fbGluZShhZXMoeT1TTUEyNSxjb2xvcj0iU01BMjUiKSkgKw0KICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9saW5lKGNvbG91cj0iZ3JleSIpLA0KICBsZWdlbmQucG9zaXRpb24gPSAndG9wJykgKw0KICBsYWJzKHRpdGxlPSJTTUEgQU1aIChKYW4yMDIwLUphbjIwMjEpIiwNCiAgY29sb3I9IlByaWNlcyIpDQpBTVpOX1NNQQ0KDQojRU1BKCkgRnVuY3Rpb24NCiNDYWxjdWxhdGUgdGhlIDUgYW5kIDI1IGRheXMgZXhwb25lbnRpYWwgbW92aW5nIGF2ZXJhZ2UNCkFNWk5fRGF0YSRFTUE1PC1UVFI6OkVNQShBTVpOX0RhdGEkQ2xvc2Usbj01LHdpbGRlciA9IEZBTFNFLHJhdGlvID0gTlVMTCkNCkFNWk5fRGF0YSRFTUEyNTwtVFRSOjpFTUEoQU1aTl9EYXRhJENsb3NlLG49MjUsIHdpbGRlciA9IEZBTFNFLHJhdGlvID0gTlVMTCkNCkFNWk5fRGF0YSA8LSBuYS5vbWl0KEFNWk5fRGF0YSkNCg0KI1Bsb3QgdGhlIG1vdmluZyBhdmVyYWdlDQpBTVpOX0VNQTwtZ2dwbG90KEFNWk5fRGF0YSwgYWVzKHg9RGF0ZSkpICsNCiAgZ2VvbV9jYW5kbGVzdGljayhhZXMoeW1pbiA9IEFNWk5fRGF0YSRMb3csIHltYXggPSBBTVpOX0RhdGEkSGlnaCwgZmlsbF91cCA9ICdncmVlbicpICsNCiAgZ2VvbV9saW5lKGFlcyh5PUVNQTUsY29sb3I9IkVNQTUiKSkgKw0KICBnZW9tX2xpbmUoYWVzKHk9RU1BMjUsY29sb3I9IkVNQTI1IikpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG91cj0iZ3JleSIpKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfbGluZShjb2xvdXI9ImdyZXkiKSwNCiAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsNCiAgbGFicyh0aXRsZT0iRU1BIEFNWiAoSmFuMjAyMC1KYW4yMDIxKSIpICsNCiAgbGFicyhjb2xvcj0iR3JlZW4iKSkNCkFNWk5fRU1BDQpgYGANCg0KDQojIyBSIEZ1bmN0aW9uOiBGaXRBUg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCdGaXRBUicpDQpsaWJyYXJ5KEZpdEFSKQ0KbGlicmFyeShxdWFudG1vZCkNCg0KI2NsZWFyIHByZXZpb3VzIGdyYXBoaWMNCmdyYXBoaWNzLm9mZigpDQoNCiNmZXRjaCBkYXRhOiBtb250aGx5IFUuUy4gdW5lbXBsb3ltZW50IHJhdGUNCmdldFN5bWJvbHMoIlVOUkFURSIsc3JjPSJGUkVEIikNCmNoYXJ0U2VyaWVzKFVOUkFURSkNCg0KI2NyZWF0ZSBhIHJlZ3VsYXIgdmVjdG9yLCBpbnN0ZWFkIG9mIGEgeHRzLW9iamVjdA0KdW5yYXRlIDwtIGFzLm51bWVyaWMoVU5SQVRFKSANCg0KI3ByaW50IGxhc3QgZGF0YQ0KdGFpbChVTlJBVEUpDQoNCiNmaXQgZXhhY3QgTUxFIHRvIEFSKDQpDQphbnMxPC1GaXRBUih1bnJhdGUsNCwgbGFnLm1heCA9ICdkZWZhdWx0JykNCg0KI3Bsb3Qgb3JpZ2luYWwgZGF0YQ0KVGltZVNlcmllc1Bsb3QodW5yYXRlLCBhc3BlY3Q9MC4yLHlsYWIgPSAiVW5lbXBsb3ltZW50IFJhdGUiLG1haW4gPSAiVW5lbXBsb3ltZW50IikNCg0KI3NpbXVsYXRlIHRoZSBmaXR0ZWQgQVINCncgPC1Cb290LkZpdEFSKGFuczEsIFIgPSAxLCBBUk1vZGVsID0gQVJwKQ0KdzEgPC0gQm9vdC5GaXRBUihhbnMxLCBSID0gMSwgQVJNb2RlbCA9IEFSeikNCg0KI3Bsb3Qgc2ltdWxhdGVkIGRhdGEgaW4gZ3JlZW4NCmxpbmVzKHcsIGNvbD0nZ3JlZW4nKQ0KbGluZXModzEsIGNvbCA9ICdyZWQnKQ0KYGBgDQoNCg0KIyBSIENPREUgVU5ERVJTVEFORElORw0KIyMgUiBDb2RlIFVuZGVyc3RhbmRpbmc6IGRhdGEubmV3PC1tZXJnZShBZChHU1BDKSxBZChESkkpKQ0KYGBge3J9DQojSW5zdGFsbCBhbmQgTG9hZCBuZWVkZWQgcGFja2FnZXMNCmluc3RhbGwucGFja2FnZXMoJ3F1YW50bW9kJykNCmxpYnJhcnkoJ3F1YW50bW9kJykNCg0KRGF0YSA8LSBnZXRTeW1ib2xzKCdeR1NQQycsIGZyb20gPSAnMjAyMS0wMS0wMScpDQpjaGFydFNlcmllcyhHU1BDLCB0aGVtZSA9ICd3aGl0ZScsDQogICAgICAgICAgICBUQT0nYWRkVm8oKTthZGRCQmFuZHMoKTthZGRDQ0koKScsIG1ham9ydGlja3MgPSAnd2Vla3MnLCBtYWpvcnRpY2tzID0gJ3dlZWtzJywgbXVsdGljb2xvciA9IFQpDQpEYXRhXzEgPC0gZ2V0U3ltYm9scygnXkRKSScsIGZyb20gPSAnMjAyMS0wMS0wMScpDQpjaGFydFNlcmllcyhESkksIHRoZW1lID0gJ3doaXRlJywNCiAgICAgICAgICAgIFRBPSdhZGRWbygpO2FkZEJCYW5kcygpO2FkZENDSSgpJywgbWFqb3J0aWNrcyA9ICd3ZWVrcycsIG1ham9ydGlja3MgPSAnd2Vla3MnLCBtdWx0aWNvbG9yID0gVCkNCk91dHB1dCA8LSBtZXJnZShBZChHU1BDKSwgQWQoREpJKSkNCmNoYXJ0X1NlcmllcyhBZChESkkpKQ0KY2hhcnRfU2VyaWVzKEFkKEdTUEMpKQ0KYGBgDQoNCg0KIyMgUiBDb2RlIFVuZGVyc3RhbmRpbmc6IHNwLmRhdGE8LWdldFN5bWJvbHMoXkdTUEMiLHN0YXJ0PSIxOTkwLTAxLTAxIiwgYXV0by5hc3NpZ249RkFMU0UpDQpgYGB7cn0NCiNJbnN0YWxsIGFuZCBMb2FkIG5lZWRlZCBwYWNrYWdlDQppbnN0YWxsLnBhY2thZ2VzKCJxdWFudG1vZCIpDQpsaWJyYXJ5KHF1YW50bW9kKQ0KDQojUmVhZCBhbmQgcmV0dXJuIHRoZSBkYXRhIGZpbGUgZm9yIFMmUDUwMA0KI09wdGlvbiAxDQpzcC5kYXRhPC0gZ2V0U3ltYm9scygiXkdTUEMiLHN0YXJ0PSIxOTkwLTAxLTAxIixhdXRvLmFzc2lnbiA9IEZBTFNFKQ0KDQojT3B0aW9uIDINCm15X3N0YXJ0ZGF0ZSA8LSBhcy5EYXRlKCIxOTkwLTAxLTAxIikNCnNwLmRhdGE8LSBnZXRTeW1ib2xzKCJeR1NQQyIsZnJvbT1teV9zdGFydGRhdGUsYXV0by5hc3NpZ24gPSBGQUxTRSkNCg0KI09wdGlvbiAzDQpzcC5kYXRhPC0gZ2V0U3ltYm9scygiXkdTUEMiLGZyb209IjE5OTAtMDEtMDEiLGF1dG8uYXNzaWduID0gRkFMU0UpDQoNCmBgYA0KDQoNCiMgUiBEQVRBU0VUUw0KIyBSIERhdGFzZXRzOiBSZWFycmFuZ2VtZW50ICh1bmVtcGxveW1lbnQgZGF0YXNldHMgZXhhbXBsZSkNCmBgYHtyfQ0KI1IgREFUQVNFVFMgUkVBUlJBTkdFTUVOVDogKHVuZV9ydF9tLnRzdiBhbmQgdW5lbXBsb3ltZW50LmNzdikNCiNMb2FkIHRoZSBEYXRhc2V0DQppbnN0YWxsLnBhY2thZ2VzKCd0aWR5dmVyc2UnKQ0KbGlicmFyeSgndGlkeXZlcnNlJykNCg0KdW5lX3J0X20gPC0gcmVhZF90c3YoIkM6XFxVc2Vyc1xcRWxpc2FcXERlc2t0b3BcXEZFX0Fzc2lnbm1lbnRfNl9kYXRhL3VuZV9ydF9tLnRzdiIpDQoNCiNEZWxldGUgb25lIGNvbHVtbiAoZ2VvZ3JhcGhpY2FsIGluZm8pDQp1bmVfcnRfbTIgPC0gc3Vic2V0KHVuZV9ydF9tLHNlbGVjdCA9IDI6NTApDQoNCiNSZXZlcnNlIG9yZGVyIG9mIGNvbHVtbnMgDQp1bmVfcnRfbTIgPC0gdW5lX3J0X20yWyxvcmRlcihuY29sKHVuZV9ydF9tMik6MSldDQoNCiNUaWR5IERhdGEgKGZyb20gY29sdW1ucyB0byByb3dzKQ0KdW5lX3J0X20yIDwtIHRpZHlyOjpwaXZvdF9sb25nZXIodW5lX3J0X20yLCBjb2xzID0gMTo0OSwgbmFtZXNfdG8gPSAnTW9udGhZZWFyJywgdmFsdWVzX3RvID0gJ1VuUmF0ZScpDQp1bmVfcnRfbTIgPC0gZGF0YS5mcmFtZSh1bmVfcnRfbTIpDQoNCiNDaGFuZ2UgQ29sdW1ucyBOYW1lDQpuYW1lcyh1bmVfcnRfbTIpWzFdPC0iTW9udGhZZWFyIg0KbmFtZXModW5lX3J0X20yKVsyXTwtIlVuUmF0ZSINCnVuZV9ydF9tMiA8LSBzZXBhcmF0ZSh1bmVfcnRfbTIsIE1vbnRoWWVhciwgc2VwID0gJ00nLCBpbnRvID0gYygnWWVhcicsICdNb250aCcpKQ0KdW5lX3J0X20yIDwtIHVuaXRlKHVuZV9ydF9tMixNb250aCwgWWVhciwgY29sID0gIk1vbnRoWWVhciIsIHNlcCA9ICItIikNCmFzLkRhdGUodW5lX3J0X20yJE1vbnRoWWVhciwgZm9ybWF0KCclTS0lWScpKQ0KYXMubnVtZXJpYyh1bmVfcnRfbTIkVW5SYXRlKQ0KbmEub21pdCh1bmVfcnRfbTIkVW5SYXRlKQ0KDQojQWRkIENvbHVtbg0KaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQ0KbGlicmFyeShkcGx5cikNCnVuZV9ydF9tMiRSb3dJRDwtYygxOjIxMzEpDQp1bmVfcnRfbTI8LXVuZV9ydF9tMiU+JXJlbG9jYXRlKFJvd0lELC5iZWZvcmUgPSBNb250aFllYXIpDQpgYGANCg0KDQojIyBSIERhdGFzZXRzOiBDcmVhdGlvbiwgQ29tYmluYXRpb24sV29ya2luZyBhbmQgU3VtbWFyeSAoRmFtYS1GcmVuY2ggYW5kIEZyZW5jaCBEYXRhc2V0cyBleGFtcGxlKQ0KYGBge3J9DQojQ3JlYXRlIGEgRGF0YXNldCBhbmQgY29tYmluZSB0aGUgZGF0YQ0KI0xvYWQgZGF0YXNldHMNCkRldmVsb3BlZF8zX0ZhY3RvcnMgPC0gcmVhZC5jc3YoJ0M6XFxVc2Vyc1xcRG9tZW5pY29cXERlc2t0b3BcXEFzc2lnbm1lbnRfNVxcRGV2ZWxvcGVkXzNfRmFjdG9yc19ZZWFyTW9udGguY3N2JywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFQpDQpteWRhdGEgPC0gcmVhZC5jc3YoJ0M6XFxVc2Vyc1xcRG9tZW5pY29cXERlc2t0b3BcXEFzc2lnbm1lbnRfNVxcRi1GX1NpemVfUG9ydGZvbGlvc19mb3JtZWRfb25fTUVfVmFsdWVfV2VpZ2h0X1JldHVybnNfTW9udGhseS5jc3YnLCANCiAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUKQ0KDQojUmVtb3ZlIHVubmVjZXNzYXJ5IGNvbHVtbnMgYW5kL29yIHJvd3MNCkZfRl9TaXplIDwtIG15ZGF0YVstYygxOjc2OCksLWMoMiwzLDQsNSldDQoNCiNNZXJnZSBkYXRhc2V0cw0KTmV3X2RhdGEgPC0gbWVyZ2UoRl9GX1NpemUsIERldmVsb3BlZF8zX0ZhY3RvcnMpDQoNCg0KI0NyZWF0ZSBhIENBUE0gZm9yIExvIFBvcnRmb2xpbw0KI0xpbmVhciBSZWdyZXNzaW9uIEZ1bmN0aW9uDQpMby4xMC5jYXBtIDwtIGxtKE5ld19kYXRhJCJMby4xMCIgfiBOZXdfZGF0YSRNa3QuUkYpDQoNCiNDb2VmZmljaWVudHMNCmNvZWYoTG8uMTAuY2FwbSkNCg0KI1N1bW1hcnkgb2YgY29lZmZpY2llbnRzIGFuZCBpbXBvcnRhbnQgc3RhdGlzdGljcyB0ZXN0cw0KbW9kLnMxPC1zdW1tYXJ5KExvLjEwLmNhcG0pDQoNCnZhbHVlczE8LXZlY3RvcigpICNFbXB0eSB2ZWN0b3INCnZhbHVlczFbMV08LW1vZC5zMSRyLnNxdWFyZWQNCnZhbHVlczFbMl08LW1vZC5zMSRhZGouci5zcXVhcmVkDQpmLnN0YXQ8LW1vZC5zMSRmc3RhdGlzdGljDQp2YWx1ZXMxWzNdPC1mLnN0YXRbMV0NCnZhbHVlczFbNF08LWYuc3RhdFsyXQ0KdmFsdWVzMVs1XTwtZi5zdGF0WzNdDQp2YWx1ZXMxWzZdPC1wZih2YWx1ZXMxWzNdLHZhbHVlczFbNF0sdmFsdWVzMVs1XSxsb3dlci50YWlsID0gRkFMU0UpICNDcmVhdGUgRi1EaXN0cmlidXRpb24NCnZhbHVlczFbN108LXZhbHVlczFbMV0vKDEtdmFsdWVzMVsxXSkNCnZhbHVlczEuZXQ8LWMoIlJeMiIsImFkaiBSXjIiLCJGIiwiZGYgbnVtLiIsImRmIGRlbi4iLCJwKEYpIiwiZl4yIikgI05hbWVzIG9mIHRoZSB2YXJpYWJsZXMgcHV0IGluIHRoZSB2ZWN0b3INCnZhbHVlczEubTwtY2JpbmQocm91bmQodmFsdWVzMSxkaWdpdHM9NSkpICNiaW5kIGJ5IGNvbHVtbnMNCnJvd25hbWVzKHZhbHVlczEubSk8LXZhbHVlczEuZXQgI0Fzc2lnbiBuYW1lcyB0byB0aGUgYmluZGVkIHJvdyB2ZWN0b3JzDQpjb2xuYW1lcyh2YWx1ZXMxLm0pIDwtIGMoJ0xvLjEwLmNhcG0nKSAjTmFtZSBvZiB0aGUgY29sdW1uDQoNCiNTdW1tYXJ5DQpyaXMxPC1jYmluZChjb2VmKG1vZC5zMSlbLDFdLGNvZWYobW9kLnMxKVssMzo0XSkNCmNvbG5hbWVzKHJpczEpIDwtIGMoJ0VzdGltYXRlJywgJ3QtdmFsdWUnLCAnUHI+fHR8JykNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KUW50Mi5jYXBtIDwtIGxtKE5ld19kYXRhJCJRbnQuMiIgfiBOZXdfZGF0YSRNa3QuUkYpDQpjb2VmKFFudDIuY2FwbSkNCm1vZC5zMjwtc3VtbWFyeShRbnQyLmNhcG0pDQp2YWx1ZXMyPC12ZWN0b3IoKQ0KdmFsdWVzMlsxXTwtbW9kLnMyJHIuc3F1YXJlZA0KdmFsdWVzMlsyXTwtbW9kLnMyJGFkai5yLnNxdWFyZWQNCmYuc3RhdDwtbW9kLnMyJGZzdGF0aXN0aWMNCnZhbHVlczJbM108LWYuc3RhdFsxXQ0KdmFsdWVzMls0XTwtZi5zdGF0WzJdDQp2YWx1ZXMyWzVdPC1mLnN0YXRbM10NCnZhbHVlczJbNl08LXBmKHZhbHVlczJbM10sdmFsdWVzMls0XSx2YWx1ZXMyWzVdLGxvd2VyLnRhaWwgPSBGQUxTRSkNCnZhbHVlczJbN108LXZhbHVlczJbMV0vKDEtdmFsdWVzMlsxXSkNCnZhbHVlczIuZXQ8LWMoIlJeMiIsImFkaiBSXjIiLCJGIiwiZGYgbnVtLiIsImRmIGRlbi4iLCJwKEYpIiwiZl4yIikNCnZhbHVlczIubTwtY2JpbmQocm91bmQodmFsdWVzMixkaWdpdHM9NSkpDQpyb3duYW1lcyh2YWx1ZXMyLm0pPC12YWx1ZXMyLmV0DQpjb2xuYW1lcyh2YWx1ZXMyLm0pIDwtIGMoJ1FudDIuY2FwbScpDQoNCnJpczI8LWNiaW5kKGNvZWYobW9kLnMyKVssMV0sY29lZihtb2QuczIpWywzOjRdKQ0KY29sbmFtZXMocmlzMikgPC0gYygnRXN0aW1hdGUnLCAndC12YWx1ZScsICdQcj58dHwnKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KUW50My5jYXBtIDwtIGxtKE5ld19kYXRhJCJRbnQuMyIgfiBOZXdfZGF0YSRNa3QuUkYpDQpjb2VmKFFudDIuY2FwbSkNCm1vZC5zMzwtc3VtbWFyeShRbnQyLmNhcG0pDQp2YWx1ZXMzPC12ZWN0b3IoKQ0KdmFsdWVzM1sxXTwtbW9kLnMzJHIuc3F1YXJlZA0KdmFsdWVzM1syXTwtbW9kLnMzJGFkai5yLnNxdWFyZWQNCmYuc3RhdDwtbW9kLnMzJGZzdGF0aXN0aWMNCnZhbHVlczNbM108LWYuc3RhdFsxXQ0KdmFsdWVzM1s0XTwtZi5zdGF0WzJdDQp2YWx1ZXMzWzVdPC1mLnN0YXRbM10NCnZhbHVlczNbNl08LXBmKHZhbHVlczNbM10sdmFsdWVzM1s0XSx2YWx1ZXMzWzVdLGxvd2VyLnRhaWwgPSBGQUxTRSkNCnZhbHVlczNbN108LXZhbHVlczJbMV0vKDEtdmFsdWVzMlsxXSkNCnZhbHVlczMuZXQ8LWMoIlJeMiIsImFkaiBSXjIiLCJGIiwiZGYgbnVtLiIsImRmIGRlbi4iLCJwKEYpIiwiZl4yIikNCnZhbHVlczMubTwtY2JpbmQocm91bmQodmFsdWVzMyxkaWdpdHM9NSkpDQpyb3duYW1lcyh2YWx1ZXMzLm0pPC12YWx1ZXMzLmV0DQpjb2xuYW1lcyh2YWx1ZXMzLm0pIDwtIGMoJ1FudDMuY2FwbScpDQoNCnJpczM8LWNiaW5kKGNvZWYobW9kLnMzKVssMV0sY29lZihtb2QuczMpWywzOjRdKQ0KY29sbmFtZXMocmlzMykgPC0gYygnRXN0aW1hdGUnLCAndC12YWx1ZScsICdQcj58dHwnKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KUW50NC5jYXBtIDwtIGxtKE5ld19kYXRhJCJRbnQuNCIgfiBOZXdfZGF0YSRNa3QuUkYpDQpjb2VmKFFudDQuY2FwbSkNCm1vZC5zNDwtc3VtbWFyeShRbnQ0LmNhcG0pDQp2YWx1ZXM0PC12ZWN0b3IoKQ0KdmFsdWVzNFsxXTwtbW9kLnM0JHIuc3F1YXJlZA0KdmFsdWVzNFsyXTwtbW9kLnM0JGFkai5yLnNxdWFyZWQNCmYuc3RhdDwtbW9kLnM0JGZzdGF0aXN0aWMNCnZhbHVlczRbM108LWYuc3RhdFsxXQ0KdmFsdWVzNFs0XTwtZi5zdGF0WzJdDQp2YWx1ZXM0WzVdPC1mLnN0YXRbM10NCnZhbHVlczRbNl08LXBmKHZhbHVlczRbM10sdmFsdWVzNFs0XSx2YWx1ZXM0WzVdLGxvd2VyLnRhaWwgPSBGQUxTRSkNCnZhbHVlczRbN108LXZhbHVlczRbMV0vKDEtdmFsdWVzNFsxXSkNCnZhbHVlczQuZXQ8LWMoIlJeMiIsImFkaiBSXjIiLCJGIiwiZGYgbnVtLiIsImRmIGRlbi4iLCJwKEYpIiwiZl4yIikNCnZhbHVlczQubTwtY2JpbmQocm91bmQodmFsdWVzNCxkaWdpdHM9NSkpDQpyb3duYW1lcyh2YWx1ZXM0Lm0pPC12YWx1ZXM0LmV0DQpjb2xuYW1lcyh2YWx1ZXM0Lm0pIDwtIGMoJ1FudDQuY2FwbScpDQoNCnJpczQ8LWNiaW5kKGNvZWYobW9kLnM0KVssMV0sY29lZihtb2QuczQpWywzOjRdKQ0KY29sbmFtZXMocmlzNCkgPC0gYygnRXN0aW1hdGUnLCAndC12YWx1ZScsICdQcj58dHwnKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KSGkuMjAuY2FwbSA8LSBsbShOZXdfZGF0YSQiSGkuMjAiIH4gTmV3X2RhdGEkTWt0LlJGKQ0KY29lZihIaS4yMC5jYXBtKQ0KbW9kLnM1PC1zdW1tYXJ5KEhpLjIwLmNhcG0pDQp2YWx1ZXM1PC12ZWN0b3IoKQ0KdmFsdWVzNVsxXTwtbW9kLnM1JHIuc3F1YXJlZA0KdmFsdWVzNVsyXTwtbW9kLnM1JGFkai5yLnNxdWFyZWQNCmYuc3RhdDwtbW9kLnM1JGZzdGF0aXN0aWMNCnZhbHVlczVbM108LWYuc3RhdFsxXQ0KdmFsdWVzNVs0XTwtZi5zdGF0WzJdDQp2YWx1ZXM1WzVdPC1mLnN0YXRbM10NCnZhbHVlczVbNl08LXBmKHZhbHVlczVbM10sdmFsdWVzNVs0XSx2YWx1ZXM1WzVdLGxvd2VyLnRhaWwgPSBGQUxTRSkNCnZhbHVlczVbN108LXZhbHVlczVbMV0vKDEtdmFsdWVzNVsxXSkNCnZhbHVlczUuZXQ8LWMoIlJeMiIsImFkaiBSXjIiLCJGIiwiZGYgbnVtLiIsImRmIGRlbi4iLCJwKEYpIiwiZl4yIikNCnZhbHVlczUubTwtY2JpbmQocm91bmQodmFsdWVzNSxkaWdpdHM9NSkpDQpyb3duYW1lcyh2YWx1ZXM1Lm0pPC12YWx1ZXM1LmV0DQpjb2xuYW1lcyh2YWx1ZXM1Lm0pIDwtIGMoJ0hpLjIwLmNhcG0nKQ0KDQoNCnJpczU8LWNiaW5kKGNvZWYobW9kLnM1KVssMV0sY29lZihtb2QuczUpWywzOjRdKQ0KY29sbmFtZXMocmlzNSkgPC0gYygnRXN0aW1hdGUnLCAndC12YWx1ZScsICdQcj58dHwnKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KRGVjLjIuY2FwbSA8LSBsbShOZXdfZGF0YSQiRGVjLjIiIH4gTmV3X2RhdGEkTWt0LlJGKQ0KY29lZihEZWMuMi5jYXBtKQ0KbW9kLnM2PC1zdW1tYXJ5KERlYy4yLmNhcG0pDQp2YWx1ZXM2PC12ZWN0b3IoKQ0KdmFsdWVzNlsxXTwtbW9kLnM2JHIuc3F1YXJlZA0KdmFsdWVzNlsyXTwtbW9kLnM2JGFkai5yLnNxdWFyZWQNCmYuc3RhdDwtbW9kLnM2JGZzdGF0aXN0aWMNCnZhbHVlczZbM108LWYuc3RhdFsxXQ0KdmFsdWVzNls0XTwtZi5zdGF0WzJdDQp2YWx1ZXM2WzVdPC1mLnN0YXRbM10NCnZhbHVlczZbNl08LXBmKHZhbHVlczZbM10sdmFsdWVzNls0XSx2YWx1ZXM2WzVdLGxvd2VyLnRhaWwgPSBGQUxTRSkNCnZhbHVlczZbN108LXZhbHVlczZbMV0vKDEtdmFsdWVzNlsxXSkNCnZhbHVlczYuZXQ8LWMoIlJeMiIsImFkaiBSXjIiLCJGIiwiZGYgbnVtLiIsImRmIGRlbi4iLCJwKEYpIiwiZl4yIikNCnZhbHVlczYubTwtY2JpbmQocm91bmQodmFsdWVzNixkaWdpdHM9NSkpDQpyb3duYW1lcyh2YWx1ZXM2Lm0pPC12YWx1ZXM2LmV0DQpjb2xuYW1lcyh2YWx1ZXM2Lm0pIDwtIGMoJ0RlYy4yLmNhcG0nKQ0KDQpyaXM2PC1jYmluZChjb2VmKG1vZC5zNilbLDFdLGNvZWYobW9kLnM2KVssMzo0XSkNCmNvbG5hbWVzKHJpczYpIDwtIGMoJ0VzdGltYXRlJywgJ3QtdmFsdWUnLCAnUHI+fHR8JykNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCkRlYy4zLmNhcG0gPC0gbG0oTmV3X2RhdGEkIkRlYy4zIiB+IE5ld19kYXRhJE1rdC5SRikNCmNvZWYoRGVjLjMuY2FwbSkNCm1vZC5zNzwtc3VtbWFyeShEZWMuMy5jYXBtKQ0KdmFsdWVzNzwtdmVjdG9yKCkNCnZhbHVlczdbMV08LW1vZC5zNyRyLnNxdWFyZWQNCnZhbHVlczdbMl08LW1vZC5zNyRhZGouci5zcXVhcmVkDQpmLnN0YXQ8LW1vZC5zNyRmc3RhdGlzdGljDQp2YWx1ZXM3WzNdPC1mLnN0YXRbMV0NCnZhbHVlczdbNF08LWYuc3RhdFsyXQ0KdmFsdWVzN1s1XTwtZi5zdGF0WzNdDQp2YWx1ZXM3WzZdPC1wZih2YWx1ZXM3WzNdLHZhbHVlczdbNF0sdmFsdWVzN1s1XSxsb3dlci50YWlsID0gRkFMU0UpDQp2YWx1ZXM3WzddPC12YWx1ZXM3WzFdLygxLXZhbHVlczdbMV0pDQp2YWx1ZXM3LmV0PC1jKCJSXjIiLCJhZGogUl4yIiwiRiIsImRmIG51bS4iLCJkZiBkZW4uIiwicChGKSIsImZeMiIpDQp2YWx1ZXM3Lm08LWNiaW5kKHJvdW5kKHZhbHVlczcsZGlnaXRzPTUpKQ0Kcm93bmFtZXModmFsdWVzNi5tKTwtdmFsdWVzNy5ldA0KY29sbmFtZXModmFsdWVzNi5tKSA8LSBjKCdEZWMuMy5jYXBtJykNCg0KcmlzNzwtY2JpbmQoY29lZihtb2QuczcpWywxXSxjb2VmKG1vZC5zNylbLDM6NF0pDQpjb2xuYW1lcyhyaXM3KSA8LSBjKCdFc3RpbWF0ZScsICd0LXZhbHVlJywgJ1ByPnx0fCcpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpEZWMuNC5jYXBtIDwtIGxtKE5ld19kYXRhJCJEZWMuNCIgfiBOZXdfZGF0YSRNa3QuUkYpDQpjb2VmKERlYy40LmNhcG0pDQptb2Quczg8LXN1bW1hcnkoRGVjLjQuY2FwbSkNCnZhbHVlczg8LXZlY3RvcigpDQp2YWx1ZXM4WzFdPC1tb2Quczgkci5zcXVhcmVkDQp2YWx1ZXM4WzJdPC1tb2QuczgkYWRqLnIuc3F1YXJlZA0KZi5zdGF0PC1tb2QuczgkZnN0YXRpc3RpYw0KdmFsdWVzOFszXTwtZi5zdGF0WzFdDQp2YWx1ZXM4WzRdPC1mLnN0YXRbMl0NCnZhbHVlczhbNV08LWYuc3RhdFszXQ0KdmFsdWVzOFs2XTwtcGYodmFsdWVzOFszXSx2YWx1ZXM4WzRdLHZhbHVlczhbNV0sbG93ZXIudGFpbCA9IEZBTFNFKQ0KdmFsdWVzOFs3XTwtdmFsdWVzOFsxXS8oMS12YWx1ZXM4WzFdKQ0KdmFsdWVzOC5ldDwtYygiUl4yIiwiYWRqIFJeMiIsIkYiLCJkZiBudW0uIiwiZGYgZGVuLiIsInAoRikiLCJmXjIiKQ0KdmFsdWVzOC5tPC1jYmluZChyb3VuZCh2YWx1ZXM4LGRpZ2l0cz01KSkNCnJvd25hbWVzKHZhbHVlczgubSk8LXZhbHVlczguZXQNCmNvbG5hbWVzKHZhbHVlczgubSkgPC0gYygnRGVjLjQuY2FwbScpDQoNCnJpczg8LWNiaW5kKGNvZWYobW9kLnM4KVssMV0sY29lZihtb2QuczgpWywzOjRdKQ0KY29sbmFtZXMocmlzOCkgPC0gYygnRXN0aW1hdGUnLCAndC12YWx1ZScsICdQcj58dHwnKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KRGVjLjUuY2FwbSA8LSBsbShOZXdfZGF0YSQiRGVjLjUiIH4gTmV3X2RhdGEkTWt0LlJGKQ0KY29lZihEZWMuNS5jYXBtKQ0KbW9kLnM5PC1zdW1tYXJ5KERlYy41LmNhcG0pDQp2YWx1ZXM5PC12ZWN0b3IoKQ0KdmFsdWVzOVsxXTwtbW9kLnM5JHIuc3F1YXJlZA0KdmFsdWVzOVsyXTwtbW9kLnM5JGFkai5yLnNxdWFyZWQNCmYuc3RhdDwtbW9kLnM5JGZzdGF0aXN0aWMNCnZhbHVlczlbM108LWYuc3RhdFsxXQ0KdmFsdWVzOVs0XTwtZi5zdGF0WzJdDQp2YWx1ZXM5WzVdPC1mLnN0YXRbM10NCnZhbHVlczlbNl08LXBmKHZhbHVlczlbM10sdmFsdWVzOVs0XSx2YWx1ZXM5WzVdLGxvd2VyLnRhaWwgPSBGQUxTRSkNCnZhbHVlczlbN108LXZhbHVlczlbMV0vKDEtdmFsdWVzOVsxXSkNCnZhbHVlczkuZXQ8LWMoIlJeMiIsImFkaiBSXjIiLCJGIiwiZGYgbnVtLiIsImRmIGRlbi4iLCJwKEYpIiwiZl4yIikNCnZhbHVlczkubTwtY2JpbmQocm91bmQodmFsdWVzNixkaWdpdHM9NSkpDQpyb3duYW1lcyh2YWx1ZXM5Lm0pPC12YWx1ZXM2LmV0DQpjb2xuYW1lcyh2YWx1ZXM5Lm0pIDwtIGMoJ0RlYy41LmNhcG0nKQ0KDQpyaXM5PC1jYmluZChjb2VmKG1vZC5zOSlbLDFdLGNvZWYobW9kLnM5KVssMzo0XSkNCmNvbG5hbWVzKHJpczkpIDwtIGMoJ0VzdGltYXRlJywgJ3QtdmFsdWUnLCAnUHI+fHR8JykNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCkRlYy42LmNhcG0gPC0gbG0oTmV3X2RhdGEkIkRlYy42IiB+IE5ld19kYXRhJE1rdC5SRikNCmNvZWYoRGVjLjYuY2FwbSkNCm1vZC5zMTA8LXN1bW1hcnkoRGVjLjYuY2FwbSkNCnZhbHVlczEwPC12ZWN0b3IoKQ0KdmFsdWVzMTBbMV08LW1vZC5zMTAkci5zcXVhcmVkDQp2YWx1ZXMxMFsyXTwtbW9kLnMxMCRhZGouci5zcXVhcmVkDQpmLnN0YXQ8LW1vZC5zMTAkZnN0YXRpc3RpYw0KdmFsdWVzMTBbM108LWYuc3RhdFsxXQ0KdmFsdWVzMTBbNF08LWYuc3RhdFsyXQ0KdmFsdWVzMTBbNV08LWYuc3RhdFszXQ0KdmFsdWVzMTBbNl08LXBmKHZhbHVlczEwWzNdLHZhbHVlczEwWzRdLHZhbHVlczEwWzVdLGxvd2VyLnRhaWwgPSBGQUxTRSkNCnZhbHVlczEwWzddPC12YWx1ZXMxMFsxXS8oMS12YWx1ZXMxMFsxXSkNCnZhbHVlczEwLmV0PC1jKCJSXjIiLCJhZGogUl4yIiwiRiIsImRmIG51bS4iLCJkZiBkZW4uIiwicChGKSIsImZeMiIpDQp2YWx1ZXMxMC5tPC1jYmluZChyb3VuZCh2YWx1ZXMxMCxkaWdpdHM9NSkpDQpyb3duYW1lcyh2YWx1ZXMxMC5tKTwtdmFsdWVzMTAuZXQNCmNvbG5hbWVzKHZhbHVlczEwLm0pIDwtIGMoJ0RlYy42LmNhcG0nKQ0KDQpyaXMxMDwtY2JpbmQoY29lZihtb2QuczEwKVssMV0sY29lZihtb2QuczEwKVssMzo0XSkNCmNvbG5hbWVzKHJpczEwKSA8LSBjKCdFc3RpbWF0ZScsICd0LXZhbHVlJywgJ1ByPnx0fCcpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpTVU1NQVJZIDwtY2JpbmQodmFsdWVzMS5tLCB2YWx1ZXMyLm0sIHZhbHVlczMubSwgdmFsdWVzNC5tLCB2YWx1ZXM1Lm0sIHZhbHVlczYubSwgdmFsdWVzNy5tLCB2YWx1ZXM4Lm0sIHZhbHVlczkubSwgdmFsdWVzMTAubSkNClRfdmFsdWVzIDwtIHJiaW5kKHJpczEsIHJpczIsIHJpczMsIHJpczQsIHJpczUsIHJpczYsIHJpczcsIHJpczgsIHJpczksIHJpczEwKQ0KDQpgYGANCg0K