Objetivo
Queremos realizar diferentes gráficos en R para comprender como son nuestros datos. Dependiendo de la naturaleza de nuestras variables debemos optar por uno u otro. Se trata de poder hacer un primer análisis visual de nuestros datos, y a partir de ellos empezar a sacar las primeras conclusiones preliminares.
Nota: Algunos graficos no poseen la mejor asimetria y/o apariencia, esto es debido a las bases de datos utilizados en algunos de ellos, el objetivo del documento es ver como es la sintaxis para realizar los graficos.
1. importacion de los datos
library(readr)
library(dplyr)
package <U+393C><U+3E31>dplyr<U+393C><U+3E32> was built under R version 3.5.3
Attaching package: <U+393C><U+3E31>dplyr<U+393C><U+3E32>
The following objects are masked from <U+393C><U+3E31>package:stats<U+393C><U+3E32>:
filter, lag
The following objects are masked from <U+393C><U+3E31>package:base<U+393C><U+3E32>:
intersect, setdiff, setequal, union
datos <-read_csv("C:/Users/74/Desktop/practica R/graficos.csv")
Parsed with column specification:
cols(
Y = [32mcol_double()[39m,
X1 = [32mcol_double()[39m,
X2 = [32mcol_double()[39m
)
head(datos,n=6)
2. BARRAS
Gráfico de barras. Es adecuado para variables dependientes agrupadas por tratamientos (por ejemplo la altura media de los ciudadanos de tres ciudades). No se puede hacer directamente, se requiere el cálculo de la media y la desviación de nuestras variables dependientes en función del tratamiento.
Primero hay que calcular la media y la desviación de nuestros datos en función del tratamiento y para cada variable:
mediasvar1<-aggregate(datos$X1~datos$Y, FUN=mean)
sdvar1<-aggregate(datos$X1~datos$Y, FUN=sd)
mediasvar1
library(plyr)
medvar1<-ddply(datos,.(Y), summarize, mean=mean(X1))
sdvar1<-ddply(datos,.(Y), summarize, sd=sd(X1))
str(medvar1)
'data.frame': 5 obs. of 2 variables:
$ Y : num 1 2 3 4 5
$ mean: num 3.45 3.2 6.62 9.75 32.54
Ahora representamos esas medias en función de cada tratamiento:
BARRAS<-barplot(medvar1$mean, axes=FALSE,axisname=FALSE, ylim=c(0,100),
col=c('green', 'gray','blue','dimgray','yellow'),main="Titulo",
xlab="Y", ylab="X1")
axis(1,labels=c("control", "T1","T2","T3","T4"), at=BARRAS)
axis(2,at=seq(0,100,by=10))

Barras de error
Las barras de error son representaciones gráficas de la variabilidad de los datos, y se usan en gráficos para indicar el error o la incertidumbre en una determinada medida. Dan una idea general de lo precisa que es una medición o, a la inversa, a qué distancia del valor indicado puede estar el valor verdadero (sin errores) del elemento medido. Las barras de error a menudo representan una incertidumbre utilizando una desviación típica, un error estándar o un intervalo de confianza particular (por ejemplo, un intervalo del 95%). Estas cantidades no expresan necesariamente valores coincidentes, por lo que debe indicarse explícitamente en el gráfico o en el texto de apoyo cuál es el indicador del error utilizado.
Se pueden usar para comparar visualmente dos cantidades, e implicitamente, si se cumplen determinadas condiciones, permiten determinar a simple vista si las diferencias son de significación estadística. Las barras de error también pueden sugerir la bondad de ajuste de una función dada, es decir, la exactitud con la que la función describe los datos.
BARRAS<-barplot(medvar1$mean, axes=FALSE,axisname=FALSE, ylim=c(0,100),
col=c('blue', 'red','yellow','dimgray','green'),main="Título",
xlab="Y", ylab="X1")
axis(1,labels=c("control", "T1","T2","T3","T4"), at=BARRAS)
axis(2,at=seq(0,100,by=10))
segments(BARRAS-0.1,medvar1$mean-sdvar1$sd,BARRAS+0.1,medvar1$mean-sdvar1$sd,lwd=2)
segments(BARRAS-0.1,medvar1$mean+sdvar1$sd,BARRAS+0.1,medvar1$mean+sdvar1$sd,lwd=2)
segments(BARRAS,medvar1$mean-sdvar1$sd,BARRAS,medvar1$mean+sdvar1$sd,lwd=2)

3. BOXPLOT
También conocido como diagrama de caja y bigote, box plot, box-plot o boxplot. Es un método estandarizado para representar gráficamente una serie de datos numéricos a través de sus cuartiles. De esta manera, el diagrama de caja muestra a simple vista la mediana y los cuartiles de los datos, pudiendo también representar los valores atípicos de estos.
boxplot(X1 ~ Y, data=datos, col="green", cex.axis=0.7,las = 2, ylab="X1", xlab="Y", cex.lab=0.75)

boxplot(X2 ~ Y, data=datos, col="red", cex.axis=0.7,las = 2, ylab="X2", xlab="y", cex.lab=0.75)

Estos gráficos se interpretan de la siguiente manera: LA LÍNEA que separa el rectángulo en dos es la MEDIANA (varible en posición central de un conjunto de datos). LOS EXTREMOS DEL RECTÁNGULO son los cuartiles extremos, es decir en el recuadro están el 75% de nuestros datos.
4. BAGPLOT
Un diagrama de bolsas, o diagrama de explosión estelar, es un método en estadísticas robustas para visualizar datos estadísticos bidimensionales o tridimensionales, análogos al diagrama de caja unidimensional.
library(aplpack)
package <U+393C><U+3E31>aplpack<U+393C><U+3E32> was built under R version 3.5.3
bagplot(datos$X1,datos$X2,xlab="X1", ylab="X2", main="Bagplot Example")

La zona sombreada recoge el 50% de los datos, los puntos con líneas son outlayers.
4. DISPERSIÓN
El diagrama de dispersión permite estudiar las relaciones entre dos conjuntos asociados de datos que aparecen en pares (por ejemplo, (x,y), uno de cada conjunto). El diagrama muestra estos pares como una nube de puntos.
Las relaciones entre los conjuntos asociados de datos se infieren a partir de la forma de las nubes.
Una relación positiva entre x y y significa que los valores crecientes de x están asociados con los valores crecientes de y.
Una relación negativa significa que los valores crecientes de x están asociados con los valores decrecientes de y.
with(datos, plot(X1, X2, col=Y))
abline(h = 12, lwd = 2, lty = 2)

Un gráfico de dispersión de X1 frente a X2 para cada uno de los tratamientos.
par(mfrow = c(1, 2), mar = c(5, 4, 2, 1))
with(subset(datos, Y == "1"), plot(X1, X2, main = "Tratamiento 1"))
with(subset(datos, Y == "2"), plot(X1, X2, main = "Tratamiento 2"))

with(subset(datos, Y == "3"), plot(X1, X2, main = "Tratamiento 3"))

with(subset(datos, Y == "4"), plot(X1, X2, main = "Tratamiento 4"))

with(subset(datos, Y == "5"), plot(X1, X2, main = "Tratamiento 5"))

5. HISTOGRAMA
En estadística, un histograma es una representación gráfica de una variable en forma de barras, donde la superficie de cada barra es proporcional a la frecuencia de los valores representados. Sirven para obtener una “primera vista” general, o panorama, de la distribución de la población, o de la muestra, respecto a una característica, cuantitativa y continua (como la longitud o el peso). De esta manera ofrece una visión de grupo permitiendo observar una preferencia, o tendencia, por parte de la muestra o población por ubicarse hacia una determinada región de valores dentro del espectro de valores posibles (sean infinitos o no) que pueda adquirir la característica. Así pues, podemos evidenciar comportamientos, observar el grado de homogeneidad, acuerdo o concisión entre los valores de todas las partes que componen la población o la muestra, o, en contraposición, poder observar el grado de variabilidad, y por ende, la dispersión de todos los valores que toman las partes, también es posible no evidenciar ninguna tendencia y obtener que cada miembro de la población toma por su lado y adquiere un valor de la característica aleatoriamente sin mostrar ninguna preferencia o tendencia, entre otras cosas.
hist(datos$X1, col = "green")

hist(datos$X2, col = "yellow")

Podemos romper en más columnas el histograma
hist(datos$X1, col = "green", breaks = 100)

hist(datos$X2, col = "YELLOW", breaks = 100)

6. HISTOGRAMA SIMULTÁNEO
par(mfrow = c(2, 1), mar = c(4, 4, 2, 1))
hist(datos$X1, col = "green")
hist(datos$X2, col = "red")

7. KERNEL DENSITY PLOTS
En estadística , la estimación de densidad de kernel ( KDE ) es una forma no paramétrica de estimar la función de densidad de probabilidad de una variable aleatoria . La estimación de la densidad del núcleo es un problema fundamental de suavización de datos en el que se hacen inferencias sobre la población , basadas en una muestra de datos finitos. En algunos campos, como el procesamiento de señales y la econometría , también se denomina método de ventana Parzen-Rosenblatt , después de Emanuel Parzen y Murray Rosenblatt , a quienes generalmente se les atribuye la creación independiente en su forma actual.
density1 <- density(datos$X1)
plot(density1)
polygon(density1, col="green", border="black")

density2 <- density(datos$X2)
plot(density2)
polygon(density2, col="red", border="black")

library(readr)
library(dplyr)
datos55 <-read_csv("C:/Users/74/Desktop/practica R/Ventas.csv")
Parsed with column specification:
cols(
ventas = [32mcol_double()[39m,
publicidad = [32mcol_double()[39m,
vendedores = [32mcol_double()[39m
)
head(datos55,n=6)
Representacion “grafico de dispersion”
plot(ventas~publicidad,data=datos55,pch=16)
abline(lm(ventas~publicidad,data=datos55),col="red")

Parametros
model_ventas<-lm(ventas~publicidad+vendedores,data=datos55)
summary(model_ventas)
Call:
lm(formula = ventas ~ publicidad + vendedores, data = datos55)
Residuals:
Min 1Q Median 3Q Max
-597.59 -84.32 67.11 138.80 295.37
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -441.66 322.16 -1.371 0.2076
publicidad -38.60 35.33 -1.093 0.3063
vendedores 259.59 88.49 2.934 0.0189 *
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 287.3 on 8 degrees of freedom
Multiple R-squared: 0.8285, Adjusted R-squared: 0.7856
F-statistic: 19.32 on 2 and 8 DF, p-value: 0.0008653
Usando ggplot2
library(ggplot2)
package <U+393C><U+3E31>ggplot2<U+393C><U+3E32> was built under R version 3.5.3
qplot(datos55$publicidad,datos55$ventas)

qplot(datos55$vendedores,datos55$ventas)

NA
Uniendo los puntos
qplot(publicidad,ventas,data=datos55,geom=c("point", "line"))

qplot(vendedores,ventas,data=datos55,geom=c("point", "line"))

Ahora representamos un modelo sobre la nube de puntos
qplot(publicidad,ventas,data=datos55,geom = c("point", "smooth"))

qplot(vendedores,ventas,data=datos55,geom = c("point", "smooth"))

8. REPRESENTACION POR CATEGORIAS
Representamos los vendedores en nuestra figura:
qplot(publicidad,ventas,data=datos55, color=factor(vendedores), geom=c("point"))

Ahora incluimos modelo para cada vendedor
qplot(publicidad,ventas,data=datos55, color=factor(vendedores), geom=c("point","smooth"))

HISTOGRAMAS “VIOLIN”
Podemos representar como un violín (nos informa de lo dispersos o agrupados que se encuentran los datos)
qplot(publicidad, ventas, data = datos55,
geom=c("violin"), trim = FALSE)

qplot(vendedores,publicidad, data = datos55,
geom=c("violin"), trim = FALSE)

9. OTROS GRAFICOS IMPORTANTES
Facetas
par(mfrow=c(1,2))
with(subset(airquality, Month <= 6),
plot(Wind, Ozone, col = "red", pch=16, main="Semestre 1"))
model1 <- lm(Ozone ~ Wind, subset(airquality, Month <= 6))
abline(model1, lwd = 1, col= "green")
with(subset(airquality, Month > 6),
plot(Wind, Ozone, col = "blue", pch=16, main="Semestre 2"))
model2 <- lm(Ozone ~ Wind, subset(airquality, Month > 6))
abline(model2, lwd = 1, col= "green")

Sistema gráfico Lattice
Se basa en la utilización de los paquetes:
Lattice. Funciones gráficas xyplot() bwplot(), etc. Grid. Para gráficos condicionados (Facetas). Características:
No es muy intuitivo Llamado de una sola función. Layouts (margenes,espacios,etc) se fijan automáticamente
library(lattice)
airquality <- transform(airquality, Month = as.factor (Month))
graf <- xyplot(Ozone~Wind | Month, data = airquality, layout=c(5,1), panel= function(x, y){
panel.xyplot(x, y, pch=16)
panel.lmline(x, y, col = "green")})
print(graf)

Sistema gráfico ggplot2
Ggplot2 es el sistema de gràficos resultante de la combinaciòn de las carateristicas de los sistemas base y lattice. Fue desarrollado por Hardley Wickham como una implementación de la gramàtica de gràficos (Grammar of Graphics) propuesta por Leland Wilkinson.
Base + Lattice = ggplot2
ggplot2 se encuentra disponible en el repositorio CRAN, se puede instalar y cargar en el àrea de trabajo directamente ejecutando las lineas de còdigo siguientes:
library(ggplot2)
g <- ggplot(mpg, aes(x=displ, y=hwy, color=drv))
g + geom_point() + geom_smooth(method="lm")

Histogramas
library(ggplot2)
g <- ggplot(mpg, aes(x=displ, fill=drv))
g + geom_histogram(binwidth=0.5, alpha = 0.8, colour="gray60")

Diagrama de Barras
library(ggplot2)
g <- ggplot(mpg, aes(x=fl, fill=drv))
g + geom_bar()

Diagrama de pie
library(ggplot2)
g <- ggplot(mpg, aes(x=TRUE, fill=fl)) + geom_bar(width=1)
g + coord_polar(theta = "y")

Gráficos múltiples de distribución
Los paquetes se instalan una sola vez y deben ser cargados en cada inicio de sesión
library(ggplot2)
g <- ggplot(mpg, aes(x=drv, y=hwy, fill=drv))
g + geom_boxplot(width=0.4, colour="green", outlier.colour = "yellow")

Grafico de linea
mes <- 1:300; ruido <- rnorm(300,0,1)
d <- data.frame(mes,ruido)
g <- ggplot(d, aes(x=mes, y=ruido))
g + geom_line(colour="cadetblue", size=0.3)

Gráfico de lineas múltiples
library(ggplot2)
mes <- 1:300; ruido <- rnorm(300,0,1); grupo <- factor(rep(1:3,100))
d <- data.frame(mes,ruido,grupo)
g <- ggplot(d, aes(x=mes, y=ruido, colour=grupo))
g + geom_line(size=0.3)

LS0tDQp0aXRsZTogIlByYWN0aWNhIEdyYWZpY29zIg0KYXV0aG9yOiAiRGVuaXMgRmVybmFuZG8gRmxhbWVuY28gTm9sYXNjbyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIHRvYzogeWVzDQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGRmX3ByaW50OiBrYWJsZQ0KICAgIHRvYzogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KDQpPYmpldGl2bw0KDQpRdWVyZW1vcyByZWFsaXphciBkaWZlcmVudGVzIGdy4WZpY29zIGVuIFIgcGFyYSBjb21wcmVuZGVyIGNvbW8gc29uIG51ZXN0cm9zIGRhdG9zLiBEZXBlbmRpZW5kbyBkZSBsYSBuYXR1cmFsZXphIGRlIG51ZXN0cmFzIHZhcmlhYmxlcyBkZWJlbW9zIG9wdGFyIHBvciB1bm8gdSBvdHJvLiBTZSB0cmF0YSBkZSBwb2RlciBoYWNlciB1biBwcmltZXIgYW7hbGlzaXMgdmlzdWFsIGRlIG51ZXN0cm9zIGRhdG9zLCB5IGEgcGFydGlyIGRlIGVsbG9zIGVtcGV6YXIgYSBzYWNhciBsYXMgcHJpbWVyYXMgY29uY2x1c2lvbmVzIHByZWxpbWluYXJlcy4NCg0KTm90YTogQWxndW5vcyBncmFmaWNvcyBubyBwb3NlZW4gbGEgbWVqb3IgYXNpbWV0cmlhIHkvbyBhcGFyaWVuY2lhLCBlc3RvIGVzIGRlYmlkbyBhIGxhcyBiYXNlcyBkZSBkYXRvcyB1dGlsaXphZG9zIGVuIGFsZ3Vub3MgZGUgZWxsb3MsIGVsIG9iamV0aXZvIGRlbCBkb2N1bWVudG8gZXMgdmVyIGNvbW8gZXMgbGEgc2ludGF4aXMgcGFyYSByZWFsaXphciBsb3MgZ3JhZmljb3MuDQoNCiMgMS4gaW1wb3J0YWNpb24gZGUgbG9zIGRhdG9zDQoNCmBgYHtyfQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoZHBseXIpDQpkYXRvcyA8LXJlYWRfY3N2KCJDOi9Vc2Vycy83NC9EZXNrdG9wL3ByYWN0aWNhIFIvZ3JhZmljb3MuY3N2IikNCmhlYWQoZGF0b3Msbj02KQ0KYGBgDQoNCiMgMi4gQkFSUkFTDQpHcuFmaWNvIGRlIGJhcnJhcy4gRXMgYWRlY3VhZG8gcGFyYSB2YXJpYWJsZXMgZGVwZW5kaWVudGVzIGFncnVwYWRhcyBwb3IgdHJhdGFtaWVudG9zIChwb3IgZWplbXBsbyBsYSBhbHR1cmEgbWVkaWEgZGUgbG9zIGNpdWRhZGFub3MgZGUgdHJlcyBjaXVkYWRlcykuIE5vIHNlIHB1ZWRlIGhhY2VyIGRpcmVjdGFtZW50ZSwgc2UgcmVxdWllcmUgZWwgY+FsY3VsbyBkZSBsYSBtZWRpYSB5IGxhIGRlc3ZpYWNp824gZGUgbnVlc3RyYXMgdmFyaWFibGVzIGRlcGVuZGllbnRlcyBlbiBmdW5jafNuIGRlbCB0cmF0YW1pZW50by4NCg0KUHJpbWVybyBoYXkgcXVlIGNhbGN1bGFyIGxhIG1lZGlhIHkgbGEgZGVzdmlhY2nzbiBkZSBudWVzdHJvcyBkYXRvcyBlbiBmdW5jafNuIGRlbCB0cmF0YW1pZW50byB5IHBhcmEgY2FkYSB2YXJpYWJsZToNCg0KYGBge3J9DQptZWRpYXN2YXIxPC1hZ2dyZWdhdGUoZGF0b3MkWDF+ZGF0b3MkWSwgRlVOPW1lYW4pDQpzZHZhcjE8LWFnZ3JlZ2F0ZShkYXRvcyRYMX5kYXRvcyRZLCBGVU49c2QpDQptZWRpYXN2YXIxDQpgYGANCmBgYHtyfQ0KbGlicmFyeShwbHlyKQ0KbWVkdmFyMTwtZGRwbHkoZGF0b3MsLihZKSwgc3VtbWFyaXplLCBtZWFuPW1lYW4oWDEpKQ0Kc2R2YXIxPC1kZHBseShkYXRvcywuKFkpLCBzdW1tYXJpemUsIHNkPXNkKFgxKSkNCnN0cihtZWR2YXIxKQ0KYGBgDQoNCg0KQWhvcmEgcmVwcmVzZW50YW1vcyBlc2FzIG1lZGlhcyBlbiBmdW5jafNuIGRlIGNhZGEgdHJhdGFtaWVudG86DQoNCmBgYHtyfQ0KQkFSUkFTPC1iYXJwbG90KG1lZHZhcjEkbWVhbiwgYXhlcz1GQUxTRSxheGlzbmFtZT1GQUxTRSwgeWxpbT1jKDAsMTAwKSwNCiAgICAgICAgY29sPWMoJ2dyZWVuJywgJ2dyYXknLCdibHVlJywnZGltZ3JheScsJ3llbGxvdycpLG1haW49IlRpdHVsbyIsDQogICAgICAgIHhsYWI9IlkiLCB5bGFiPSJYMSIpDQpheGlzKDEsbGFiZWxzPWMoImNvbnRyb2wiLCAiVDEiLCJUMiIsIlQzIiwiVDQiKSwgYXQ9QkFSUkFTKQ0KYXhpcygyLGF0PXNlcSgwLDEwMCxieT0xMCkpDQpgYGANCg0KQmFycmFzIGRlIGVycm9yDQoNCkxhcyBiYXJyYXMgZGUgZXJyb3Igc29uIHJlcHJlc2VudGFjaW9uZXMgZ3LhZmljYXMgZGUgbGEgdmFyaWFiaWxpZGFkIGRlIGxvcyBkYXRvcywgeSBzZSB1c2FuIGVuIGdy4WZpY29zIHBhcmEgaW5kaWNhciBlbCBlcnJvciBvIGxhIGluY2VydGlkdW1icmUgZW4gdW5hIGRldGVybWluYWRhIG1lZGlkYS4gRGFuIHVuYSBpZGVhIGdlbmVyYWwgZGUgbG8gcHJlY2lzYSBxdWUgZXMgdW5hIG1lZGljafNuIG8sIGEgbGEgaW52ZXJzYSwgYSBxdekgZGlzdGFuY2lhIGRlbCB2YWxvciBpbmRpY2FkbyBwdWVkZSBlc3RhciBlbCB2YWxvciB2ZXJkYWRlcm8gKHNpbiBlcnJvcmVzKSBkZWwgZWxlbWVudG8gbWVkaWRvLiBMYXMgYmFycmFzIGRlIGVycm9yIGEgbWVudWRvIHJlcHJlc2VudGFuIHVuYSBpbmNlcnRpZHVtYnJlIHV0aWxpemFuZG8gdW5hIGRlc3ZpYWNp824gdO1waWNhLCB1biBlcnJvciBlc3ThbmRhciBvIHVuIGludGVydmFsbyBkZSBjb25maWFuemEgcGFydGljdWxhciAocG9yIGVqZW1wbG8sIHVuIGludGVydmFsbyBkZWwgOTUlKS4gRXN0YXMgY2FudGlkYWRlcyBubyBleHByZXNhbiBuZWNlc2FyaWFtZW50ZSB2YWxvcmVzIGNvaW5jaWRlbnRlcywgcG9yIGxvIHF1ZSBkZWJlIGluZGljYXJzZSBleHBs7WNpdGFtZW50ZSBlbiBlbCBncuFmaWNvIG8gZW4gZWwgdGV4dG8gZGUgYXBveW8gY3XhbCBlcyBlbCBpbmRpY2Fkb3IgZGVsIGVycm9yIHV0aWxpemFkby4NCg0KU2UgcHVlZGVuIHVzYXIgcGFyYSBjb21wYXJhciB2aXN1YWxtZW50ZSBkb3MgY2FudGlkYWRlcywgZSBpbXBsaWNpdGFtZW50ZSwgc2kgc2UgY3VtcGxlbiBkZXRlcm1pbmFkYXMgY29uZGljaW9uZXMsIHBlcm1pdGVuIGRldGVybWluYXIgYSBzaW1wbGUgdmlzdGEgc2kgbGFzIGRpZmVyZW5jaWFzIHNvbiBkZSBzaWduaWZpY2FjafNuIGVzdGFk7XN0aWNhLiBMYXMgYmFycmFzIGRlIGVycm9yIHRhbWJp6W4gcHVlZGVuIHN1Z2VyaXIgbGEgYm9uZGFkIGRlIGFqdXN0ZSBkZSB1bmEgZnVuY2nzbiBkYWRhLCBlcyBkZWNpciwgbGEgZXhhY3RpdHVkIGNvbiBsYSBxdWUgbGEgZnVuY2nzbiBkZXNjcmliZSBsb3MgZGF0b3MuDQoNCmBgYHtyfQ0KQkFSUkFTPC1iYXJwbG90KG1lZHZhcjEkbWVhbiwgYXhlcz1GQUxTRSxheGlzbmFtZT1GQUxTRSwgeWxpbT1jKDAsMTAwKSwNCiAgICAgICAgY29sPWMoJ2JsdWUnLCAncmVkJywneWVsbG93JywnZGltZ3JheScsJ2dyZWVuJyksbWFpbj0iVO10dWxvIiwNCiAgICAgICAgeGxhYj0iWSIsIHlsYWI9IlgxIikNCmF4aXMoMSxsYWJlbHM9YygiY29udHJvbCIsICJUMSIsIlQyIiwiVDMiLCJUNCIpLCBhdD1CQVJSQVMpDQpheGlzKDIsYXQ9c2VxKDAsMTAwLGJ5PTEwKSkNCnNlZ21lbnRzKEJBUlJBUy0wLjEsbWVkdmFyMSRtZWFuLXNkdmFyMSRzZCxCQVJSQVMrMC4xLG1lZHZhcjEkbWVhbi1zZHZhcjEkc2QsbHdkPTIpDQpzZWdtZW50cyhCQVJSQVMtMC4xLG1lZHZhcjEkbWVhbitzZHZhcjEkc2QsQkFSUkFTKzAuMSxtZWR2YXIxJG1lYW4rc2R2YXIxJHNkLGx3ZD0yKQ0Kc2VnbWVudHMoQkFSUkFTLG1lZHZhcjEkbWVhbi1zZHZhcjEkc2QsQkFSUkFTLG1lZHZhcjEkbWVhbitzZHZhcjEkc2QsbHdkPTIpDQpgYGANCg0KIyAzLiBCT1hQTE9UDQoNClRhbWJp6W4gY29ub2NpZG8gY29tbyBkaWFncmFtYSBkZSBjYWphIHkgYmlnb3RlLCBib3ggcGxvdCwgYm94LXBsb3QgbyBib3hwbG90LiBFcyB1biBt6XRvZG8gZXN0YW5kYXJpemFkbyBwYXJhIHJlcHJlc2VudGFyIGdy4WZpY2FtZW50ZSB1bmEgc2VyaWUgZGUgZGF0b3MgbnVt6XJpY29zIGEgdHJhdulzIGRlIHN1cyBjdWFydGlsZXMuIERlIGVzdGEgbWFuZXJhLCBlbCBkaWFncmFtYSBkZSBjYWphIG11ZXN0cmEgYSBzaW1wbGUgdmlzdGEgbGEgbWVkaWFuYSB5IGxvcyBjdWFydGlsZXMgZGUgbG9zIGRhdG9zLCBwdWRpZW5kbyB0YW1iaeluIHJlcHJlc2VudGFyIGxvcyB2YWxvcmVzIGF07XBpY29zIGRlIGVzdG9zLg0KDQpgYGB7cn0NCmJveHBsb3QoWDEgfiBZLCBkYXRhPWRhdG9zLCBjb2w9ImdyZWVuIiwgY2V4LmF4aXM9MC43LGxhcyA9IDIsIHlsYWI9IlgxIiwgeGxhYj0iWSIsIGNleC5sYWI9MC43NSkNCmBgYA0KDQoNCmBgYHtyfQ0KYm94cGxvdChYMiB+IFksIGRhdGE9ZGF0b3MsIGNvbD0icmVkIiwgY2V4LmF4aXM9MC43LGxhcyA9IDIsIHlsYWI9IlgyIiwgeGxhYj0ieSIsIGNleC5sYWI9MC43NSkNCmBgYA0KDQpFc3RvcyBncuFmaWNvcyBzZSBpbnRlcnByZXRhbiBkZSBsYSBzaWd1aWVudGUgbWFuZXJhOiBMQSBMzU5FQSBxdWUgc2VwYXJhIGVsIHJlY3Thbmd1bG8gZW4gZG9zIGVzIGxhIE1FRElBTkEgKHZhcmlibGUgZW4gcG9zaWNp824gY2VudHJhbCBkZSB1biBjb25qdW50byBkZSBkYXRvcykuIExPUyBFWFRSRU1PUyBERUwgUkVDVMFOR1VMTyBzb24gbG9zIGN1YXJ0aWxlcyBleHRyZW1vcywgZXMgZGVjaXIgZW4gZWwgcmVjdWFkcm8gZXN04W4gZWwgNzUlIGRlIG51ZXN0cm9zIGRhdG9zLg0KDQoNCiMgNC4gQkFHUExPVA0KDQpVbiBkaWFncmFtYSBkZSBib2xzYXMsIG8gZGlhZ3JhbWEgZGUgZXhwbG9zafNuIGVzdGVsYXIsIGVzIHVuIG3pdG9kbyBlbiBlc3RhZO1zdGljYXMgcm9idXN0YXMgcGFyYSB2aXN1YWxpemFyIGRhdG9zIGVzdGFk7XN0aWNvcyBiaWRpbWVuc2lvbmFsZXMgbyB0cmlkaW1lbnNpb25hbGVzLCBhbuFsb2dvcyBhbCBkaWFncmFtYSBkZSBjYWphIHVuaWRpbWVuc2lvbmFsLg0KDQpgYGB7cn0NCmxpYnJhcnkoYXBscGFjaykNCmJhZ3Bsb3QoZGF0b3MkWDEsZGF0b3MkWDIseGxhYj0iWDEiLCB5bGFiPSJYMiIsIG1haW49IkJhZ3Bsb3QgRXhhbXBsZSIpDQpgYGANCg0KDQpMYSB6b25hIHNvbWJyZWFkYSByZWNvZ2UgZWwgNTAlIGRlIGxvcyBkYXRvcywgbG9zIHB1bnRvcyBjb24gbO1uZWFzIHNvbiBvdXRsYXllcnMuDQoNCiMgNC4gRElTUEVSU0nTTg0KDQpFbCBkaWFncmFtYSBkZSBkaXNwZXJzafNuIHBlcm1pdGUgZXN0dWRpYXIgbGFzIHJlbGFjaW9uZXMgZW50cmUgZG9zIGNvbmp1bnRvcyBhc29jaWFkb3MgZGUgZGF0b3MgcXVlIGFwYXJlY2VuIGVuIHBhcmVzIChwb3IgZWplbXBsbywgKHgseSksIHVubyBkZSBjYWRhIGNvbmp1bnRvKS4gRWwgZGlhZ3JhbWEgbXVlc3RyYSBlc3RvcyBwYXJlcyBjb21vIHVuYSBudWJlIGRlIHB1bnRvcy4NCg0KTGFzIHJlbGFjaW9uZXMgZW50cmUgbG9zIGNvbmp1bnRvcyBhc29jaWFkb3MgZGUgZGF0b3Mgc2UgaW5maWVyZW4gYSBwYXJ0aXIgZGUgbGEgZm9ybWEgZGUgbGFzIG51YmVzLg0KDQpVbmEgcmVsYWNp824gcG9zaXRpdmEgZW50cmUgeCB5IHkgc2lnbmlmaWNhIHF1ZSBsb3MgdmFsb3JlcyBjcmVjaWVudGVzIGRlIHggZXN04W4gYXNvY2lhZG9zIGNvbiBsb3MgdmFsb3JlcyBjcmVjaWVudGVzIGRlIHkuDQoNClVuYSByZWxhY2nzbiBuZWdhdGl2YSBzaWduaWZpY2EgcXVlIGxvcyB2YWxvcmVzIGNyZWNpZW50ZXMgZGUgeCBlc3ThbiBhc29jaWFkb3MgY29uIGxvcyB2YWxvcmVzIGRlY3JlY2llbnRlcyBkZSB5LiANCg0KYGBge3J9DQp3aXRoKGRhdG9zLCBwbG90KFgxLCBYMiwgY29sPVkpKQ0KYWJsaW5lKGggPSAxMiwgbHdkID0gMiwgbHR5ID0gMikNCmBgYA0KDQoNClVuIGdy4WZpY28gZGUgZGlzcGVyc2nzbiBkZSBYMSBmcmVudGUgYSBYMiBwYXJhIGNhZGEgdW5vIGRlIGxvcyB0cmF0YW1pZW50b3MuDQoNCmBgYHtyfQ0KcGFyKG1mcm93ID0gYygxLCAyKSwgbWFyID0gYyg1LCA0LCAyLCAxKSkNCndpdGgoc3Vic2V0KGRhdG9zLCBZID09ICIxIiksIHBsb3QoWDEsIFgyLCBtYWluID0gIlRyYXRhbWllbnRvIDEiKSkNCndpdGgoc3Vic2V0KGRhdG9zLCBZID09ICIyIiksIHBsb3QoWDEsIFgyLCBtYWluID0gIlRyYXRhbWllbnRvIDIiKSkNCmBgYA0KDQpgYGB7cn0NCndpdGgoc3Vic2V0KGRhdG9zLCBZID09ICIzIiksIHBsb3QoWDEsIFgyLCBtYWluID0gIlRyYXRhbWllbnRvIDMiKSkNCndpdGgoc3Vic2V0KGRhdG9zLCBZID09ICI0IiksIHBsb3QoWDEsIFgyLCBtYWluID0gIlRyYXRhbWllbnRvIDQiKSkNCndpdGgoc3Vic2V0KGRhdG9zLCBZID09ICI1IiksIHBsb3QoWDEsIFgyLCBtYWluID0gIlRyYXRhbWllbnRvIDUiKSkNCmBgYA0KDQoNCiMgNS4gSElTVE9HUkFNQQ0KDQoNCkVuIGVzdGFk7XN0aWNhLCB1biBoaXN0b2dyYW1hIGVzIHVuYSByZXByZXNlbnRhY2nzbiBncuFmaWNhIGRlIHVuYSB2YXJpYWJsZSBlbiBmb3JtYSBkZSBiYXJyYXMsIGRvbmRlIGxhIHN1cGVyZmljaWUgZGUgY2FkYSBiYXJyYSBlcyBwcm9wb3JjaW9uYWwgYSBsYSBmcmVjdWVuY2lhIGRlIGxvcyB2YWxvcmVzIHJlcHJlc2VudGFkb3MuIFNpcnZlbiBwYXJhIG9idGVuZXIgdW5hICJwcmltZXJhIHZpc3RhIiBnZW5lcmFsLCBvIHBhbm9yYW1hLCBkZSBsYSBkaXN0cmlidWNp824gZGUgbGEgcG9ibGFjafNuLCBvIGRlIGxhIG11ZXN0cmEsIHJlc3BlY3RvIGEgdW5hIGNhcmFjdGVy7XN0aWNhLCBjdWFudGl0YXRpdmEgeSBjb250aW51YSAoY29tbyBsYSBsb25naXR1ZCBvIGVsIHBlc28pLiBEZSBlc3RhIG1hbmVyYSBvZnJlY2UgdW5hIHZpc2nzbiBkZSBncnVwbyBwZXJtaXRpZW5kbyBvYnNlcnZhciB1bmEgcHJlZmVyZW5jaWEsIG8gdGVuZGVuY2lhLCBwb3IgcGFydGUgZGUgbGEgbXVlc3RyYSBvIHBvYmxhY2nzbiBwb3IgdWJpY2Fyc2UgaGFjaWEgdW5hIGRldGVybWluYWRhIHJlZ2nzbiBkZSB2YWxvcmVzIGRlbnRybyBkZWwgZXNwZWN0cm8gZGUgdmFsb3JlcyBwb3NpYmxlcyAoc2VhbiBpbmZpbml0b3MgbyBubykgcXVlIHB1ZWRhIGFkcXVpcmlyIGxhIGNhcmFjdGVy7XN0aWNhLiBBc+0gcHVlcywgcG9kZW1vcyBldmlkZW5jaWFyIGNvbXBvcnRhbWllbnRvcywgb2JzZXJ2YXIgZWwgZ3JhZG8gZGUgaG9tb2dlbmVpZGFkLCBhY3VlcmRvIG8gY29uY2lzafNuIGVudHJlIGxvcyB2YWxvcmVzIGRlIHRvZGFzIGxhcyBwYXJ0ZXMgcXVlIGNvbXBvbmVuIGxhIHBvYmxhY2nzbiBvIGxhIG11ZXN0cmEsIG8sIGVuIGNvbnRyYXBvc2ljafNuLCBwb2RlciBvYnNlcnZhciBlbCBncmFkbyBkZSB2YXJpYWJpbGlkYWQsIHkgcG9yIGVuZGUsIGxhIGRpc3BlcnNp824gZGUgdG9kb3MgbG9zIHZhbG9yZXMgcXVlIHRvbWFuIGxhcyBwYXJ0ZXMsIHRhbWJp6W4gZXMgcG9zaWJsZSBubyBldmlkZW5jaWFyIG5pbmd1bmEgdGVuZGVuY2lhIHkgb2J0ZW5lciBxdWUgY2FkYSBtaWVtYnJvIGRlIGxhIHBvYmxhY2nzbiB0b21hIHBvciBzdSBsYWRvIHkgYWRxdWllcmUgdW4gdmFsb3IgZGUgbGEgY2FyYWN0ZXLtc3RpY2EgYWxlYXRvcmlhbWVudGUgc2luIG1vc3RyYXIgbmluZ3VuYSBwcmVmZXJlbmNpYSBvIHRlbmRlbmNpYSwgZW50cmUgb3RyYXMgY29zYXMuDQoNCg0KYGBge3J9DQpoaXN0KGRhdG9zJFgxLCBjb2wgPSAiZ3JlZW4iKQ0KaGlzdChkYXRvcyRYMiwgY29sID0gInllbGxvdyIpDQpgYGANCg0KDQpQb2RlbW9zIHJvbXBlciBlbiBt4XMgY29sdW1uYXMgZWwgaGlzdG9ncmFtYQ0KDQpgYGB7cn0NCmhpc3QoZGF0b3MkWDEsIGNvbCA9ICJncmVlbiIsIGJyZWFrcyA9IDEwMCkNCmhpc3QoZGF0b3MkWDIsIGNvbCA9ICJZRUxMT1ciLCBicmVha3MgPSAxMDApDQpgYGANCg0KDQojIDYuIEhJU1RPR1JBTUEgU0lNVUxUwU5FTw0KDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMoMiwgMSksIG1hciA9IGMoNCwgNCwgMiwgMSkpDQpoaXN0KGRhdG9zJFgxLCBjb2wgPSAiZ3JlZW4iKQ0KaGlzdChkYXRvcyRYMiwgY29sID0gInJlZCIpDQpgYGANCg0KIyA3LiBLRVJORUwgREVOU0lUWSBQTE9UUw0KDQpFbiBlc3RhZO1zdGljYSAsIGxhIGVzdGltYWNp824gZGUgZGVuc2lkYWQgZGUga2VybmVsICggS0RFICkgZXMgdW5hIGZvcm1hIG5vIHBhcmFt6XRyaWNhIGRlIGVzdGltYXIgbGEgZnVuY2nzbiBkZSBkZW5zaWRhZCBkZSBwcm9iYWJpbGlkYWQgZGUgdW5hIHZhcmlhYmxlIGFsZWF0b3JpYSAuIExhIGVzdGltYWNp824gZGUgbGEgZGVuc2lkYWQgZGVsIG76Y2xlbyBlcyB1biBwcm9ibGVtYSBmdW5kYW1lbnRhbCBkZSBzdWF2aXphY2nzbiBkZSBkYXRvcyBlbiBlbCBxdWUgc2UgaGFjZW4gaW5mZXJlbmNpYXMgc29icmUgbGEgcG9ibGFjafNuICwgYmFzYWRhcyBlbiB1bmEgbXVlc3RyYSBkZSBkYXRvcyBmaW5pdG9zLiBFbiBhbGd1bm9zIGNhbXBvcywgY29tbyBlbCBwcm9jZXNhbWllbnRvIGRlIHNl8WFsZXMgeSBsYSBlY29ub21ldHLtYSAsIHRhbWJp6W4gc2UgZGVub21pbmEgbel0b2RvIGRlIHZlbnRhbmEgUGFyemVuLVJvc2VuYmxhdHQgLCBkZXNwdelzIGRlIEVtYW51ZWwgUGFyemVuIHkgTXVycmF5IFJvc2VuYmxhdHQgLCBhIHF1aWVuZXMgZ2VuZXJhbG1lbnRlIHNlIGxlcyBhdHJpYnV5ZSBsYSBjcmVhY2nzbiBpbmRlcGVuZGllbnRlIGVuIHN1IGZvcm1hIGFjdHVhbC4NCg0KYGBge3J9DQpkZW5zaXR5MSA8LSBkZW5zaXR5KGRhdG9zJFgxKSANCnBsb3QoZGVuc2l0eTEpDQpwb2x5Z29uKGRlbnNpdHkxLCBjb2w9ImdyZWVuIiwgYm9yZGVyPSJibGFjayIpDQoNCmBgYA0KDQpgYGB7cn0NCmRlbnNpdHkyIDwtIGRlbnNpdHkoZGF0b3MkWDIpIA0KcGxvdChkZW5zaXR5MikNCnBvbHlnb24oZGVuc2l0eTIsIGNvbD0icmVkIiwgYm9yZGVyPSJibGFjayIpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShkcGx5cikNCmRhdG9zNTUgPC1yZWFkX2NzdigiQzovVXNlcnMvNzQvRGVza3RvcC9wcmFjdGljYSBSL1ZlbnRhcy5jc3YiKQ0KaGVhZChkYXRvczU1LG49NikNCmBgYA0KDQojIFJlcHJlc2VudGFjaW9uICJncmFmaWNvIGRlIGRpc3BlcnNpb24iDQoNCmBgYHtyfQ0KcGxvdCh2ZW50YXN+cHVibGljaWRhZCxkYXRhPWRhdG9zNTUscGNoPTE2KQ0KYWJsaW5lKGxtKHZlbnRhc35wdWJsaWNpZGFkLGRhdGE9ZGF0b3M1NSksY29sPSJyZWQiKQ0KYGBgDQoNCiMgUGFyYW1ldHJvcw0KDQpgYGB7cn0NCm1vZGVsX3ZlbnRhczwtbG0odmVudGFzfnB1YmxpY2lkYWQrdmVuZGVkb3JlcyxkYXRhPWRhdG9zNTUpDQpzdW1tYXJ5KG1vZGVsX3ZlbnRhcykNCmBgYA0KDQoNCiMgVXNhbmRvIGdncGxvdDINCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpxcGxvdChkYXRvczU1JHB1YmxpY2lkYWQsZGF0b3M1NSR2ZW50YXMpDQpxcGxvdChkYXRvczU1JHZlbmRlZG9yZXMsZGF0b3M1NSR2ZW50YXMpDQogDQpgYGANCg0KDQojIFVuaWVuZG8gbG9zIHB1bnRvcw0KDQpgYGB7cn0NCnFwbG90KHB1YmxpY2lkYWQsdmVudGFzLGRhdGE9ZGF0b3M1NSxnZW9tPWMoInBvaW50IiwgImxpbmUiKSkNCnFwbG90KHZlbmRlZG9yZXMsdmVudGFzLGRhdGE9ZGF0b3M1NSxnZW9tPWMoInBvaW50IiwgImxpbmUiKSkNCmBgYA0KDQojIEFob3JhIHJlcHJlc2VudGFtb3MgdW4gbW9kZWxvIHNvYnJlIGxhIG51YmUgZGUgcHVudG9zDQoNCmBgYHtyfQ0KcXBsb3QocHVibGljaWRhZCx2ZW50YXMsZGF0YT1kYXRvczU1LGdlb20gPSBjKCJwb2ludCIsICJzbW9vdGgiKSkNCnFwbG90KHZlbmRlZG9yZXMsdmVudGFzLGRhdGE9ZGF0b3M1NSxnZW9tID0gYygicG9pbnQiLCAic21vb3RoIikpDQpgYGANCg0KDQojIDguIFJFUFJFU0VOVEFDSU9OIFBPUiBDQVRFR09SSUFTDQoNCiNSZXByZXNlbnRhbW9zIGxvcyB2ZW5kZWRvcmVzIGVuIG51ZXN0cmEgZmlndXJhOg0KDQpgYGB7cn0NCnFwbG90KHB1YmxpY2lkYWQsdmVudGFzLGRhdGE9ZGF0b3M1NSwgY29sb3I9ZmFjdG9yKHZlbmRlZG9yZXMpLCBnZW9tPWMoInBvaW50IikpDQpgYGANCg0KI0Fob3JhIGluY2x1aW1vcyBtb2RlbG8gcGFyYSBjYWRhIHZlbmRlZG9yDQoNCmBgYHtyfQ0KcXBsb3QocHVibGljaWRhZCx2ZW50YXMsZGF0YT1kYXRvczU1LCBjb2xvcj1mYWN0b3IodmVuZGVkb3JlcyksIGdlb209YygicG9pbnQiLCJzbW9vdGgiKSkNCmBgYA0KDQoNCiNISVNUT0dSQU1BUyAiVklPTElOIg0KDQpQb2RlbW9zIHJlcHJlc2VudGFyIGNvbW8gdW4gdmlvbO1uIChub3MgaW5mb3JtYSBkZSBsbyBkaXNwZXJzb3MgbyBhZ3J1cGFkb3MgcXVlIHNlIGVuY3VlbnRyYW4gbG9zIGRhdG9zKQ0KDQogDQpgYGB7cn0NCnFwbG90KHB1YmxpY2lkYWQsIHZlbnRhcywgZGF0YSA9IGRhdG9zNTUsIA0KICAgICAgZ2VvbT1jKCJ2aW9saW4iKSwgdHJpbSA9IEZBTFNFKQ0KDQpxcGxvdCh2ZW5kZWRvcmVzLHB1YmxpY2lkYWQsIGRhdGEgPSBkYXRvczU1LCANCiAgICAgIGdlb209YygidmlvbGluIiksIHRyaW0gPSBGQUxTRSkNCg0KYGBgDQoNCg0KDQojIDkuIE9UUk9TIEdSQUZJQ09TIElNUE9SVEFOVEVTDQoNCiMgRmFjZXRhcw0KDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCndpdGgoc3Vic2V0KGFpcnF1YWxpdHksIE1vbnRoIDw9IDYpLA0KcGxvdChXaW5kLCBPem9uZSwgY29sID0gInJlZCIsIHBjaD0xNiwgbWFpbj0iU2VtZXN0cmUgMSIpKSANCm1vZGVsMSA8LSBsbShPem9uZSB+IFdpbmQsIHN1YnNldChhaXJxdWFsaXR5LCBNb250aCA8PSA2KSkgDQphYmxpbmUobW9kZWwxLCBsd2QgPSAxLCBjb2w9ICJncmVlbiIpDQp3aXRoKHN1YnNldChhaXJxdWFsaXR5LCBNb250aCA+IDYpLA0KcGxvdChXaW5kLCBPem9uZSwgY29sID0gImJsdWUiLCBwY2g9MTYsIG1haW49IlNlbWVzdHJlIDIiKSkNCm1vZGVsMiA8LSBsbShPem9uZSB+IFdpbmQsIHN1YnNldChhaXJxdWFsaXR5LCBNb250aCA+IDYpKQ0KYWJsaW5lKG1vZGVsMiwgbHdkID0gMSwgY29sPSAiZ3JlZW4iKQ0KYGBgDQoNCiMgU2lzdGVtYSBncuFmaWNvIExhdHRpY2UNCg0KU2UgYmFzYSBlbiBsYSB1dGlsaXphY2nzbiBkZSBsb3MgcGFxdWV0ZXM6DQoNCkxhdHRpY2UuIEZ1bmNpb25lcyBncuFmaWNhcyB4eXBsb3QoKSBid3Bsb3QoKSwgZXRjLiBHcmlkLiBQYXJhIGdy4WZpY29zIGNvbmRpY2lvbmFkb3MgKEZhY2V0YXMpLg0KQ2FyYWN0ZXLtc3RpY2FzOg0KDQpObyBlcyBtdXkgaW50dWl0aXZvDQpMbGFtYWRvIGRlIHVuYSBzb2xhIGZ1bmNp824uDQpMYXlvdXRzIChtYXJnZW5lcyxlc3BhY2lvcyxldGMpIHNlIGZpamFuIGF1dG9t4XRpY2FtZW50ZQ0KDQpgYGB7cn0NCmxpYnJhcnkobGF0dGljZSkNCmFpcnF1YWxpdHkgPC0gdHJhbnNmb3JtKGFpcnF1YWxpdHksIE1vbnRoID0gYXMuZmFjdG9yIChNb250aCkpDQpncmFmIDwtIHh5cGxvdChPem9uZX5XaW5kIHwgTW9udGgsIGRhdGEgPSBhaXJxdWFsaXR5LCBsYXlvdXQ9Yyg1LDEpLCBwYW5lbD0gZnVuY3Rpb24oeCwgeSl7DQogIHBhbmVsLnh5cGxvdCh4LCB5LCBwY2g9MTYpDQogIHBhbmVsLmxtbGluZSh4LCB5LCBjb2wgPSAiZ3JlZW4iKX0pDQpwcmludChncmFmKQ0KYGBgDQoNCiNTaXN0ZW1hIGdy4WZpY28gZ2dwbG90Mg0KDQpHZ3Bsb3QyIGVzIGVsIHNpc3RlbWEgZGUgZ3LgZmljb3MgcmVzdWx0YW50ZSBkZSBsYSBjb21iaW5hY2nybiBkZSBsYXMgY2FyYXRlcmlzdGljYXMgZGUgbG9zIHNpc3RlbWFzIGJhc2UgeSBsYXR0aWNlLiBGdWUgZGVzYXJyb2xsYWRvIHBvciBIYXJkbGV5IFdpY2toYW0gY29tbyB1bmEgaW1wbGVtZW50YWNp824gZGUgbGEgZ3JhbeB0aWNhIGRlIGdy4GZpY29zIChHcmFtbWFyIG9mIEdyYXBoaWNzKSBwcm9wdWVzdGEgcG9yIExlbGFuZCBXaWxraW5zb24uDQoNCkJhc2UgKyBMYXR0aWNlID0gZ2dwbG90Mg0KDQpnZ3Bsb3QyIHNlIGVuY3VlbnRyYSBkaXNwb25pYmxlIGVuIGVsIHJlcG9zaXRvcmlvIENSQU4sIHNlIHB1ZWRlIGluc3RhbGFyIHkgY2FyZ2FyIGVuIGVsIOByZWEgZGUgdHJhYmFqbyBkaXJlY3RhbWVudGUgZWplY3V0YW5kbyBsYXMgbGluZWFzIGRlIGPyZGlnbyBzaWd1aWVudGVzOg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmcgPC0gZ2dwbG90KG1wZywgYWVzKHg9ZGlzcGwsIHk9aHd5LCBjb2xvcj1kcnYpKQ0KZyArIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKQ0KYGBgDQoNCiMgSGlzdG9ncmFtYXMNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpnIDwtIGdncGxvdChtcGcsIGFlcyh4PWRpc3BsLCBmaWxsPWRydikpDQpnICsgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MC41LCBhbHBoYSA9IDAuOCwgY29sb3VyPSJncmF5NjAiKQ0KYGBgDQoNCiNEaWFncmFtYSBkZSBCYXJyYXMNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpnIDwtIGdncGxvdChtcGcsIGFlcyh4PWZsLCBmaWxsPWRydikpDQpnICsgZ2VvbV9iYXIoKQ0KYGBgDQoNCg0KI0RpYWdyYW1hIGRlIHBpZQ0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmcgPC0gZ2dwbG90KG1wZywgYWVzKHg9VFJVRSwgZmlsbD1mbCkpICsgZ2VvbV9iYXIod2lkdGg9MSkNCmcgKyBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikNCmBgYA0KDQoNCiNHcuFmaWNvcyBt+mx0aXBsZXMgZGUgZGlzdHJpYnVjafNuDQoNCkxvcyBwYXF1ZXRlcyBzZSBpbnN0YWxhbiB1bmEgc29sYSB2ZXogeSBkZWJlbiBzZXIgY2FyZ2Fkb3MgZW4gY2FkYSBpbmljaW8gZGUgc2VzafNuDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZyA8LSBnZ3Bsb3QobXBnLCBhZXMoeD1kcnYsIHk9aHd5LCBmaWxsPWRydikpDQpnICsgZ2VvbV9ib3hwbG90KHdpZHRoPTAuNCwgY29sb3VyPSJncmVlbiIsIG91dGxpZXIuY29sb3VyID0gInllbGxvdyIpDQpgYGANCg0KIyBHcmFmaWNvIGRlIGxpbmVhDQoNCmBgYHtyfQ0KbWVzIDwtIDE6MzAwOyBydWlkbyA8LSBybm9ybSgzMDAsMCwxKQ0KZCA8LSBkYXRhLmZyYW1lKG1lcyxydWlkbykNCmcgPC0gZ2dwbG90KGQsIGFlcyh4PW1lcywgeT1ydWlkbykpDQpnICsgZ2VvbV9saW5lKGNvbG91cj0iY2FkZXRibHVlIiwgc2l6ZT0wLjMpDQpgYGANCg0KIyBHcuFmaWNvIGRlIGxpbmVhcyBt+mx0aXBsZXMNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQptZXMgPC0gMTozMDA7IHJ1aWRvIDwtIHJub3JtKDMwMCwwLDEpOyBncnVwbyA8LSBmYWN0b3IocmVwKDE6MywxMDApKQ0KZCA8LSBkYXRhLmZyYW1lKG1lcyxydWlkbyxncnVwbykNCmcgPC0gZ2dwbG90KGQsIGFlcyh4PW1lcywgeT1ydWlkbywgY29sb3VyPWdydXBvKSkNCmcgKyBnZW9tX2xpbmUoc2l6ZT0wLjMpDQpgYGANCg0KDQoNCg0KDQoNCg0KDQo=