#ggplot2

Uno de los paquetes más populares para la visualización de datos en R es ggplot2, cuyas iniciales se refieren a “Gramática de Gráficos”.

La particularidad de este paquete es que cada grafica que construye se conforma de una serie de capas y cada una de ellas, le aporta un atributo diferente a la misma.

Es necesario instalarlo para poder cubrir a detalle las capas más importantes de cada grafico pues es importante saber como se comportan y tener una mayor libertad al momento de graficar y obtener mejores resultados.

Hay una capa que especifica los datos del grafo, otra capa que determina las variables que van a ocupar los ejes y otra que determina la forma de la grafica (lineas, puntos, barras), entre otras.

Como instalar ggplot2

Para instalarlo hacemos los siguientes pasos.

1.- Nos dirijimos a ‘Herramientas’, ‘Tools’ en ingles. 2.- Seleccionamos ‘Instalar paquetes’, ‘Install Packeges’ en ingles. 3.- Escribimos ‘ggplot2’

Una vez instalado el paquete cargamos las funciones a la librería de R mediante el siguiente chunk.

library(ggplot2)

Gramática de ggplo2

Es muy importante conocer la gramática al momento de definir las graficas en R pues según el posicionamiento de nuestras instrucciones sera la grafica resultante.

Cada grafico en R se compone, principalmente, de 3 capas, también llamados gramática de gráficos:

1.-Datos 2.Estética 3.Geometría

Explicaremos cada uno.

Datos.

Los datos se refiere a la base de datos que queremos graficar.

Estética.

La estética se refiere a como queremos asignar las variables de nuestra base en la grafica.

EJEMPLO:

Cual variable estará en el eje X y cual en el eje Y.

Geometría.

La geometría se refiere a la figura geométrica que queremos utilizar en el grafico, es decir, si queremos hacer una grafica de dispersión utilizamos puntos, y un histograma utilizamos barras.

Aprenderemos a manejar esta gramática de datos.

NOTA: Existen otras capas que se pueden agregar al grafico como las facetas, estadísticas, coordenadas, temas, etc. Pero no serán comentadas en este apartado.

Importamos el archivo de Excel con nombre ‘Precios’

#DESIGNAMOS A LA VARIABLE Archivo_Excel_Precios EL ARCHIVO CSV

Archivo_Excel_Precios <- read.csv("Precios.csv")

#LA COLUMNA 'PETROLEO' CONTIENE INFORMACION SOBRE EL PRECIO DEL BARRIL EN DOLARES POR LITRO
#LA COLUMNA 'DOLAR' MARCA LA TASA DE CAMBIO DE DOLAR EN PESOS MEXICANOS
#LA COLUMNA 'DIA' Y 'MES' MARCA LA FECHA QUE FUE REALIZADO.

Archivo_Excel_Precios

Construiremos un grafico con los datos del precio del petroleo conforme transcurren los dias.


#PRIMERO AGREGAREMOS LA CAPA DE LOS DATOS, ES DECIR, LE DECIMOS A R DE DONDE OBTENER LOS DATOS

Grafico_Fluctuacion_Precio_Petroleo <- ggplot(Archivo_Excel_Precios)

#AGREGAMOS LA CAPA DE LA ESTETICA, INDICAMOS QUE 'INDICE' SERAN LAS X Y 'DOLAR' SERAN LAS Y

Grafico_Fluctuacion_Precio_Petroleo <- Grafico_Fluctuacion_Precio_Petroleo + aes( x = Indice, y = Dolar)

#AGREGAMOS LA CAPA DE LA GEOMETRIA, EN ESTE CASO VAMOS A ASIGNAR UNA VARIABLE QUE TENGA UNA GEOMETRIA CON LINEAS.

Grafico_Fluctuacion_Precio_Petroleo_Lineas <- Grafico_Fluctuacion_Precio_Petroleo + geom_line()

#IMPRIMIMOS EL GRAFICO Y NOTAMOS QUE CONTIENE LAS 3 CAPAS QUE LE ESPECIFICAMOS A R.

Grafico_Fluctuacion_Precio_Petroleo_Lineas

Veremos ahora, con una segunda grafica, como se relaciona el precio del dolar y del petroleo.


#AGREGAMOS LA CAPA DE LOS DATOS

Grafico_Relacion_Precio_Petroleo_Dolar <- ggplot(Archivo_Excel_Precios)

#AGREGAMOS LA CAPA DE LA ESTETICA

Grafico_Relacion_Precio_Petroleo_Dolar <- Grafico_Relacion_Precio_Petroleo_Dolar + aes(x = Petroleo, y = Dolar)

#AGREGAMOS LA CAPA DE LA GEOMETRIA CON UNA FIGURA DE PUNTOS

Grafico_Relacion_Precio_Petroleo_Dolar_Puntos <- Grafico_Relacion_Precio_Petroleo_Dolar + geom_point()

#IMPRIMIMOS EL GRAFICO Y NOTAMOS QUE CONTIENE LAS 3 CAPAS DESCRITAS.

Grafico_Relacion_Precio_Petroleo_Dolar_Puntos

Propiedades de la Geometría Line y Point

Nosotros sabemos ya que las tres capas principales de un gráfico son: Datos, Estética y Geometría. Ademas, vimos en particular la geometría de línea y puntos, geom_line() y geom_point() respectivamente, ambas tienen atributos que pueden ser modificados.

Vamos a rehacer el gráfico realizado en la leccion anterior.

#PONEMOS LA CAPA DE LOS DATOS

Grafico_Fluctuacion_Dolar <- ggplot(Archivo_Excel_Precios)

#PONEMOS LA CAPA DE LA ESTETICA

Grafico_Fluctuacion_Dolar <- Grafico_Fluctuacion_Dolar + aes( x = Indice, y = Dolar)

#PONEMOS LA CAPA DE LA GEOMETRIA

Grafico_Fluctuacion_Dolar_Lineas <- Grafico_Fluctuacion_Dolar + geom_line()

#IMPRIMIMOS EL GRAFICO

Grafico_Fluctuacion_Dolar_Lineas

La primera variación que podemos hacer en el apartado ‘geom_line()’ es el estilo de línea. Por defecto, la función dibuja una linea continua pero podemos pedirle a R que dibuje una linea punteada o con guiones.

Para hacer esto agregamos ‘linetype’ dentro de los parámetros de la función y, dependiendo de la línea que queramos es el numero que le vamos a asignar.

Sintaxis.

Variable_Grafo <- Variable_Grafo + geom_line(linetype = Numero)

Variable_Grafo hace referencia a la variable que almacena el grafo en si mismo, Numero hace referencia a la variacion que haremos a la linea.

A continuacion veremos los 6 tipos de modificaciones que acepta linetype.

  1. Línea sólida
  2. Línea guíon
  3. Línea punteada
  4. Línea punto-guíon
  5. Línea guíon largo
  6. Línea dos guiones
#ASIGNAMOS A LA VARIABLE 'Grafico_Fluctuacion_Dola_Linetype_6' LA MODIFICACION DE LINETYPE CON LINEA PUNTEADA.

Grafico_Fluctuacion_Dolar_Linetype_6 <- Grafico_Fluctuacion_Dolar + geom_line(linetype = 6)

#IMPRIMIMOS EL GRAFICO CON LA MODIFICACION EN LAS LINEAS TIPO 6.

Grafico_Fluctuacion_Dolar_Linetype_6

La segunda variacíon que podemos hacer al apartado ‘geom_line()’ es el grosor de la línea.

Para hacer esto agregamos ‘size’ al parametro de la función y entre más grande sea el valor otorgado, más sera el grosor de la línea.

#TOMAREMOS EL GRAFICO ANTERIOR Y SOLO AGRANDAREMOS EL GROSOR DE LA LINEA 3

Grafico_Fluctuacion_Dolar_Linetype_6_Size_3 <- Grafico_Fluctuacion_Dolar_Linetype_6 + geom_line(linetype = 6, size = 3)

#IMPRIMIMOS EL GRAFICO

Grafico_Fluctuacion_Dolar_Linetype_6_Size_3

La tercera variación que podemos hacer a ‘geom_line()’ es el color.

Para hacer esto agregamos ‘colour’ al parametro de la funcion y designando el nombre del color deseado en ingles.

EJEMPLO.

#TOMAREMOS EL GRAFICO ANTERIOR Y LE CAMBIAREMOS EL COLOR A AMARILLO

Grafico_Fluctuacion_Dolar_Linetype_6_Size_3_Colour_Red <- Grafico_Fluctuacion_Dolar_Linetype_6_Size_3 + geom_line(linetype = 6, size = 3, colour = "red")

#IMPRIMIMOS EL GRAFICO

Grafico_Fluctuacion_Dolar_Linetype_6_Size_3_Colour_Red

La cuarta variacion que podemos hacer a ‘geom_line()’ es la intensidad del color.

Para hacer esto tenemos que agregar ‘alpha’ al parametro de la funcion y escribiendo un numero entre 0 y 1 podemos designar la intensidad del color asignado.

EJEMPLO.

#TOMAREMOS EL GRAFICO ANTERIOR Y LE CAMBIAREMOS LA INTENSIDAD DEL COLOR AMARILLO

Grafico_Fluctuacion_Dolar_Linetype_6_Size_3_Colour_Red_Alpha_0.3 <- Grafico_Fluctuacion_Dolar_Linetype_6_Size_3_Colour_Red + geom_line(linetype = 6, size = 3, colour = "red", alpha = 0.3)

#IMPRIMIMOS EL GRAFICO

Grafico_Fluctuacion_Dolar_Linetype_6_Size_3_Colour_Red_Alpha_0.3

Una propiedad que puede ser muy util es la combinacion de ‘geom_line()’ y ‘geom_point()’. Es decir que si tenemos un grafo con lineas, es posible dibujarle puntos encima.

Para hacer esto se agrega la capa a la variable que contiene el grafico con ‘geom_line()’.

EJEMPLO.

#TOMAREMOS EL GRAFICO ANTERIOR Y LE ANEXAREMOS UN CAPA DE PUNTOS

Grafico_Fluctuacion_Dolar_Linetype_6_Size_3_Colour_Red_Alpha_0.3 <- Grafico_Fluctuacion_Dolar_Linetype_6_Size_3_Colour_Red_Alpha_0.3 + geom_point()

#IMPRIMIMOS EL GRAFO

Grafico_Fluctuacion_Dolar_Linetype_6_Size_3_Colour_Red_Alpha_0.3

Vamos a graficar ahora la fluctuacion del dolar pero con puntos, sin embargo, esta ocasion incluiremos en una misma linea todas las propiedades que pueden ser agregadas a la funcion ‘geom_point()’.

#AGREGAMOS LA CAPA DE LOS DATOS

Grafico_Fluctuacion_Dolar_Puntos <- ggplot(Archivo_Excel_Precios)

#AGREGAMOS LA CAPA DE LA ESTETICA

Grafico_Fluctuacion_Dolar_Puntos <- Grafico_Fluctuacion_Dolar_Puntos + aes( x = Indice, y = Dolar )

#AGREGAMOS LA CAPA DE LA GEOMETRIA

Grafico_Fluctuacion_Dolar_Puntos <- Grafico_Fluctuacion_Dolar_Puntos + geom_point(shape = 9, size = 3.5, colour = "blue", alpha = 0.72)

#IMPRIMIMOS EL GRAFICO

Grafico_Fluctuacion_Dolar_Puntos

Notemos que la funcion ‘geom_line()’ y ‘geom_point()’ comparten casi todas las variaciones, sin embargo, linetype no sirve con ‘geom_point’, en cambio, shape modifica la forma de los puntos. A continuacion enumeraremos las propiedades correspondientes a cada funcion:

FUNCION ‘geom_line()’.

  1. linetype. Modifica la forma de la linea, 6 tipos de lineas.
  2. size. Modifica el grosor de la linea.
  3. colour. Modifica el color de la linea.
  4. alpha. Modifica la intensidad del color.

FUNCION ‘geom_point()’.

  1. shape. Modifica la forma del punto.20 tipos de puntos.
  2. size. Modifica el grosor del punto.
  3. colour. Modifica el color del punto.
  4. alpha. Modifica la intensidad del punto.

Respecto a las formas que puede tomar el punto, se anexa un link que tiene las imagenes correspondientes a cada valor.

[Symbols point shapes][1] [1]: http://www.sthda.com/english/wiki/r-plot-pch-symbols-the-different-point-shapes-available-in-r

Notemos que al poner la capa de la Estetica agregamos la funcion ‘aes()’ donde declaramos los datos al eje x y los datos al eje y. En este mismo apartado podemos modificar la forma de los puntos, shape, y el color, colour, sin embargo, realizar esto otorga resultados diferentes a que lo hicieramos en la capa de Geometria.

La sintaxis es la siguiente.

Variable_Grafo <- Variable_Grafo + aes( x= Columna_i, y= Columna_j, colour= Columna_k, shape= Columna_n)

Variable_Grafo hace referencia a la variable que le asignamos la capa de los datos, cada ‘Columna_i’ simboliza el nombre de la columna que se representara con la indicacion correspondiente.

En particular, al asignar colour estamos diciendo que a los valores de dicha columna se le asignaran distintos colores, al asignar shape estamos diciendo que a los valores de dicha columna se le asignara distintas formas.

#PONEMOS LA CAPA DE LOS DATOS

Grafo <- ggplot(Archivo_Excel_Precios)

#PONEMOS LA CAPA ESTETICA

Grafo <- Grafo + aes(x = Petroleo, y = Dolar, colour = Mes, shape = Mes)

#PONEMOS LA CAPA GEOMETRICA

Grafo <- Grafo + geom_point()

#IMPRIMIMOS EL GRAFO.

Grafo

IMPORTANTE: Si nosotros modificamos ‘colour’ y ‘shape’ en ‘geom_point()’, entonces estos ajustes seran dados de manera general en el grafico, por lo tanto, es a decision del usuario donde modificar estos dos puntos.

Si el usuario implementó ‘shape’ y ‘colour’ en la capa de la Estetica y desea modificar alguna de las figuras y el color que R le asigno a un dato, se hace de la siguiente manera.

PARA LAS FIGURAS.

Variable_Grafo <- Variable_Grafo + scale_shape_manual( values = c(Numero1,Numero2,Numero3,...,NumeroK) )

PARA LOS COLORES

Variable_Grafo <- Variable_Grafo + scale_colour_manual( values = c("Color1","Color2",...,"ColorK") )

NOTA: Esto se asigna despues de declarar la capa de la Estetica, es decir, despues de añadir ‘shape’ y ‘color’ en el argumento de aes().

Variable_Grafo hace referencia a la variable que contiene el grafo en cuestion, NumeroI hace referencia a la figura que deseamos que le corresponda a cada uno de los valores contenidos en la columna que se le asigna el shape, “ColorI” hace referencia al color que deseamos que le corresponda a cada uno de los valores contenidos en la columna asignada a shape.

En el grafo anterior, tenemos 4 meses y R le asigno a cada uno una figura, recordemos que existen 20 tipos de puntos, por lo tanto, asignaremos 4 distintas formas a cada mes y 4 colores.

#LE ASIGNAREMOS A LA VARIABLE 'Grafo2' EL GRAFO CON LAS DIFERENTES FORMAS A CADA MES.

#AGREGAMOS LA CAPA DE LOS DATOS

Grafo2 <- ggplot(Archivo_Excel_Precios)

#AGREGAMOS LA CAPA DE ESTETICA

Grafo2 <- Grafo2 + aes( x = Petroleo, y = Dolar, colour = Mes, shape = Mes)

#Modificamos figura

Grafo2 <- Grafo2 + scale_shape_manual( values = c(16,17,15,18) ) #AL MES DE ABRIL LE ASIGNAMOS LA FORMA CON NUMERO 16, AL MES FEBRERO LE ASIGNAMOS EL DE 17 Y SUCESIVAMENTE.

#Modificamos color

Grafo2 <- Grafo2 + scale_colour_manual( values = c("green","red","blue","brown") )

#AGREGAMOS LA CAPA GEOMETRICA

Grafo2 <- Grafo2 + geom_point()

#IMPRIMIMOS EL GRAFO

Grafo2

Personalización de ejes

Con el paquete ggplot2 se puede editar los nombres de los ejes, es decir, tomar valores de cierta columna y al momento de graficar cambiar su nombre. Mas aun, se puede agregar titulo y subtitulo al grafo.

Para hacer lo anterior mencionado se utiliza los comandos ‘xlab(“Nombre deseado”)’ para dar nombre al eje de las X, ‘ylab(“Nombre deseado”)’ para dar nombre al eje de las Y, ‘ggtitle(“Nombre titulo”, subtitle = “Nombre subtitulo”)’

Diseñaremos un Data Frame que indique valores de la X y Y.

Valores_X=c(2,4,6,8,10,12,14)
Valores_Y=c(1,3,6,9,12,16,18)
Data_Frame=data.frame(Valores_X,Valores_Y)

Graficamos.

#PONEMOS LA CAPA DE LOS DATOS

Grafo_Data_Frame <- ggplot(Data_Frame)

#PONEMOS LA CAPA DE LA ESTETICA

Grafo_Data_Frame <- Grafo_Data_Frame + aes( x = Valores_X, y = Valores_Y)

#PONEMOS LA CAPA DE GEOMETRIA

Grafo_Data_Frame <- Grafo_Data_Frame + geom_line(size=2.5,colour="green", alpha = 0.5)

#IMPRIMIMOS EL GRAFICO

Grafo_Data_Frame

Modificaremos los nombres de los ejes, agregaremos un titulo y subtitulo al grafo.

#CAMBIAREMOS EL NOMBRES DE LOS EJES.

Grafo_Data_Frame <- Grafo_Data_Frame + xlab("Entradas")

Grafo_Data_Frame <- Grafo_Data_Frame + ylab("Salidas")

#AGREGAMOS TITULO Y SUBTITULO

Grafo_Data_Frame <- Grafo_Data_Frame + ggtitle("Consumo del mes", subtitle = "Agosto-2020")

#IMPRIMIMOS EL GRAFO

Grafo_Data_Frame

Gráfico de barras

Ademas de las lineas y puntos para graficar, en la parte geometrica, es posible hacer graficos de barras y pastel en R.

En este apartado nos enfocaremos a estudiar los graficos de barras.

Las graficas de barras al igual que las graficas de lineas y puntos consta de 3 capas, principalmente, es decir: Datos, Estetica y Geometria.

Su implementacion, respecto a la capa de los datos es exactamente igual a un grafico de lineas o puntos, sin embargo, al implementar la estetica solo especificamos la variable que esta en el eje x pues el eje y siempre sera un conteo de las veces que aparece dicha variable que escribimos en el eje x (ver el ejemplo), por ultimo pero no menos importante, la implementacion de la capa geometrica define que queremos un grafico de barras mediante ‘geom_bar()’.

IMPORTANTE: En los graficos de barras, la variable que se asigna al eje x debe ser categorica.

Para un uso practico, haremos uso de la base de datos contenida en el archivo Excel con nombre ‘COVID19MX’ que contiene informacion sobre personas contagiadas con coronavirus en dos entidades de la Republica Mexicana.

Los datos incluidos en la base de datos son: Sexo del paciente, entidad a la que pertenece, si fue hospitalizado, edad, enfermedades cronicas (obesidad, diabetes, hipertension) y deceso.

Es claro que tenemos diferentes variables para poder graficar, sin embargo, nos enfocaremos a graficar el numero de personas contagiadas que hay por entidad.

Asignamos a la variable COVIDMX la base de datos almacenada en el archivo Excel

COVIDMX <- read.csv("COVID19MX.csv")

Asignamos las capas al grafico de barras.

#ASIGNAMOS LA CAPA DE LOS DATOS

Barras_Covid <- ggplot(COVIDMX)

#ASIGNAMOS LA CAPA ESTETICA

Barras_Covid <- Barras_Covid + aes( x = ENTIDAD)

#ASIGNAMOS LA CAPA GEOMETRICA

Barras_Covid <- Barras_Covid + geom_bar()

#IMPRIMIMOS EL GRAFICO

Barras_Covid

Existe una analogia al cambio de color de cada barra al igual que el cambio de color de linea y punto, se hace mediante la condicion ‘fill’.

Es necesario recordar que depende del lugar donde declaremos fill es el resultado obtenido, es decir, si implementamos el color en la capa Geometrica este se aplicara a todo el grafo, sin embargo, si lo hacemos en la capa estetica este se implementara en el conteo de las variables de la columna asignada.

EJEMPLO CAMBIO GENERAL DE COLOR.

#A LA VARIABLE Barras_Covid_2 LE ASIGNAREMOS UN CAMBIO GENERAL DE COLOR.

Barras_Covid_2 <- Barras_Covid + geom_bar(fill = "green")

#IMPRIMIMOS

Barras_Covid_2

#A LA VARIABLE Barras_Covid_3 LE ASIGNAREMOS UN CAMBIO POR VARIABLE DE COLOR

Barras_Covid_3 <- Barras_Covid + aes(x = ENTIDAD, fill = ENTIDAD)

#LE ASIGNAMOS UNA GEOMETRIA DE BARRAS

Barras_Covid_3 <- Barras_Covid_3 + geom_bar()

#IMPRIMIMOS

Barras_Covid_3

Mas aun, podemos nosotros asignar a cada variable un color en especifico mediante la instruccion ‘scale_fill_manual()’.

La sintaxis es la siguiente.

Variable_Grafo <- Variable_Grafo + scale_fill_manual( values = c(“Color1”,“Color2”,…,“ColorN”) )

Variable_Grafo hace referencia a la variable que contiene el grafo en cuestion, “ColorI” hace referencia al color que le asignamos a la variable en la posicion I que corresponde al eje X.

EJEMPLO.

#A LA VARIABLE Barras_Covid_4 ASIGNAREMOS DOS COLORES DIFERENTES A LAS BARRAS MOSTRADAS.

Barras_Covid_4 <- Barras_Covid + aes(x = ENTIDAD, fill = ENTIDAD)

#ASIGNAMOS EL COLOR AZUL A CIUDAD DE MEXICO Y VERDE A ESTADO DE MEXIO

Barras_Covid_4 <- Barras_Covid_4 + scale_fill_manual( values = c("blue","green") )

#LE ASIGNAMOS UNA GEOMETRIA DE BARRAS

Barras_Covid_4 <- Barras_Covid_4 + geom_bar()

#IMPRIMIMOS EL GRAFO

Barras_Covid_4

De manera similar al cambio de ancho de una linea o punto, podemos modificar la anchura de las barras mediante la instruccion ‘width’ en el apartado Geometrico.

El valor de width tiene que estar entre 0 y 1.

#ASIGNAMOS LA CAPA DE LOS DATOS

Barras_Covid_5 <- ggplot(COVIDMX)

#ASIGNAMOS LA CAPA ESTETICA

Barras_Covid_5 <- Barras_Covid_5 + aes( x = ENTIDAD, fill = ENTIDAD)

#MODIFICAMOS LOS COLORES DE LAS BARRAS

Barras_Covid_5 <- Barras_Covid_5 + scale_fill_manual( values = c("red","brown"))

#ASIGNAMOS LA CAPA GEOMETRICA Y ACHICAMOS LAS BARRAS

Barras_Covid_5 <- Barras_Covid_5 + geom_bar(width = 0.2)

#IMPRIMIMOS EL GRAFO

Barras_Covid_5

Es importante señalar que podemos subdivir las barras, es decir, tener una barra que este contida en otra. Por ejemplo, sabemos que en la CDMX tenemos mas de 75000 contagiados y en el Estado de Mexico menos de 25000, queremos saber cuantos de ellos han muerto. Para ello utilizamos la instruccion ‘fill’ antes mencionada pero especificando que grafique y coloree los datos contenidos en dicha columna.

EJEMPLO.

#ASIGNAMOS LA CAPA DE LOS DATOS

Barras_Covid_6 <- ggplot(COVIDMX)

#ASIGNAMOS LA CAPA ESTETICA Y ESPECIFICAMOS QUE COLOREE LOS QUE HAN FALLECIDO Y LOS QUE NO.

Barras_Covid_6 <- Barras_Covid_6 + aes( x = ENTIDAD, fill = DEFUNCION)

#CAMBIAMOS EL COLOR DEL FILTRO REALIZADO

Barras_Covid_6 <- Barras_Covid_6 + scale_fill_manual( values = c("green","red") )

#ASIGNAMOS LA CAPA GEOMETRICA Y MODIFICAMOS LA ANCHURA

Barras_Covid_6 <- Barras_Covid_6 + geom_bar(width = 0.25)

#IMPRIMIMOS EL GRAFO

Barras_Covid_6

Por ultimo y solo como demostrativo, mostraremos un grafico que muestre la proporcion de diabeticos por entidad y agregaremos titulos y subtitulos al grafico.

Grafo <- ggplot(COVIDMX)
Grafo <- Grafo + aes(x=ENTIDAD,fill=DIABETES)
Grafo <- Grafo + scale_fill_manual( values = c("yellow","orange") )
Grafo <- Grafo + geom_bar(width = 0.2)
Grafo <- Grafo + xlab("Entidad Federativa de Mexico")
Grafo <- Grafo + ylab("Numero de infectados")
Grafo <- Grafo + ggtitle("Datos COVID19 MEXICO", subtitle="FEB-JUNIO 2020")
Grafo

Gráfico de pastel

Vimos los graficos de linea, puntos y barra, ahora toca analizar las graficas de pastel. Antes de empezar, es necesario aclarar que la libreria ‘ggplot2’ no tiene una geometria especifica para construir graficos de pastel, sin embargo, es posible hacerlos a partir de un grafico de barras.

Para poder crear un grafico de pastel en funcion de un grafico de barras, necesitamos diseñar primero nuestra grafica de barras, despues filtrar la barra que deseamos formar como pastel y despues agregar el comando ‘coord_polar()’ para diseñar el grafo correspondiente.

La sintaxis general es:

Datos <- read.csv("Nombre_Archivo_Excel")
Datos <- filter(Datos, Nombre_Columna_a_filtrar == "Nombre_Dato")
Variable_Grafo <- ggplot(Datos)
Variable_Grafo <- Variable_Grafo + aes(x = Nombre_Columna_a_filtrar, fill = Nombre_Columna)
Variable_Grafo <- Variable_Grafo + scale_fill_manual( values = c("Color1","Color2",...,"ColorN") )
Variable_Grafo <- Variable_Grafo + geom_bar(width = #)
Variable_Grafo <- Variable_Grafo + xlab("Nombre_eje_X")
Variable_Grafo <- Variable_Grafo + ylab("Nombre_eje_Y")
Variable_Grafo <- Variable_Grafo + ggtitle("Titulo_Grafo", subtitle="Subtitulo_Grafo")
Variable_Grafo <- Variable_Grafo + coord_polar("y")

Para efectos practicos, vamos a extraer la informacion de la base de datos almacenada en el Excel ‘COVID19MX’. Ademas, como vamos a diseñar un grafico de barras inicialmente, necesitamos importar la libreria ‘ggplot2’ y aparte la libreria ‘dplyr’ para agregar las modificaciones necesarias al momento de diseñar un grafico de pastel.

#IMPORTAMOS LA LIBRERIA
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

Leemos la base de datos.

Archivo_Excel <- read.csv("COVID19MX.csv")

Diseñamos el grafico de barras.

#CAPA DATOS
Grafo_Barra <- ggplot(Archivo_Excel)
#CAPA ESTETICA
Grafo_Barra <- Grafo_Barra + aes(x = ENTIDAD, fill= DIABETES)
#MODIFICAMOS EL COLOR DE 'fill'
Grafo_Barra <- Grafo_Barra + scale_fill_manual( values = c("green","red"))
#CAPA GEOMETRICA
Grafo_Barra <- Grafo_Barra + geom_bar(width = 0.25)
#AGREGAMOS NOMBRE A LOS EJES
Grafo_Barra <- Grafo_Barra + xlab("ENTIDAD FEDERATIVA")
Grafo_Barra <- Grafo_Barra + ylab("Numero de infectados")
#AGREGAMOS TITULO Y SUBTITULO
Grafo_Barra <- Grafo_Barra + ggtitle("COVID MEXICO", subtitle = "FEB-JUN 2020")
#IMPRIMIMOS EL GRAFICO
Grafo_Barra

Vamos a diseñar como grafica de pastel ambos estados.

CIUDAD DE MEXICO

Primero vamos a filtrar, para ello, volveremos a leer la base de datos.

#LEEMOS BASE DE DATOS
Datos_CDMX <- read.csv("COVID19MX.csv")
#FILTRAMOS ESTADO
Datos_CDMX <- filter(Datos_CDMX, ENTIDAD == "CIUDAD DE MEXICO")
#CAPA DATOS
G_CDMX <- ggplot(Datos_CDMX)
#CAPA ESTETICA
G_CDMX <- G_CDMX + aes(x = ENTIDAD, fill = DIABETES)
#CAPA GEOMETRICA
G_CDMX <- G_CDMX + geom_bar()
#NOMBRE DE EJES
G_CDMX <- G_CDMX + ylab("INFECTADOS")
#TITULO
G_CDMX <- G_CDMX + ggtitle("COVID MEXICO", subtitle="FEB_JUN 2020")
#DISEñAMOS GRAFICA DE PASTEL
G_CDMX <- G_CDMX + coord_polar("y")
#IMPRIMIMOS EL GRAFICO
G_CDMX

ESTADO DE MEXICO

#LEEMOS LOS DATOS
Datos_EMX <- read.csv("COVID19MX.csv")
#APLICAMOS EL FILTRO
Datos_EMX <- filter(Datos_EMX, ENTIDAD == "ESTADO DE MEXICO")
#APLICAMOS CAPA DE DATOS
G_EMX <- ggplot(Datos_EMX)
#APLICAMOS CAPA DE ESTETICA
G_EMX <- G_EMX + aes(x = ENTIDAD, fill = DIABETES)
#APLICAMOS CAPA DE GEOMETRIA
G_EMX <- G_EMX + geom_bar(width = 0.25)
#NOMBRE A LOS EJES
G_EMX <- G_EMX + ylab("INFECTADOS")
#TITULO
G_EMX <- G_EMX + ggtitle("COVID MEXICO", subtitle = "FEB_JUN 2020")
#DISEñAMOS GRAFICA DE PASTEL
G_EMX <- G_EMX + coord_polar("y")
#IMPRIMIMOS EL GRAFICO
G_EMX

Si no deseamos utilizar una grafica de barras para construir un grafico de pastel, podemos realizarlo mediante la funcion ‘pie()’ ajena a la paqueteria ‘ggplot2’, por lo tanto, no es necesario destacar las 3 capas (Datos, Estetica, Geometria).

Sintaxis.

pie(x = Variable_Numerica, labels = Variable_Nombres, col = Variable_Colores)

Variable_Numerica hace referencia a la variable que contiene los valores de los porcentaje a graficar, en decimal, es decir, 88.1, Variable_Nombres hace referencia a los nombres en porcentaje de la cantidad ingresada, es decir, “88.1%”, Variable_Colores hace referencia a los colores que nosotros le asignamos a cada variable a graficar.

La desventaja de este proceso es calcular de manera manual los porcentajes a mostrar.

Retomaremos el apartado anterior, en esta ocasion solo trabajaremos con la CIUDAD DE MEXICO.

Primero leemos el archivo, despues filtramos, luego filtramos columna y procedemos analizar los datos contenidos en dicha columna.

Esto lo hacemos para poder calcular el porcentaje de manera manual.

Archivo <- read.csv("COVID19MX.csv")
Archivo_CDMX <- filter(Archivo, ENTIDAD == "CIUDAD DE MEXICO")
Diabetes <- Archivo_CDMX$DIABETES
table(Diabetes)
Diabetes
   NO    SI 
76619 10161 

Podemos notar que existen 76619 personas SIN diabetes y 10161 CON diabetes, entonces, entre los dos tenemos un total de 86780, por lo tanto, 76619 corresponde a un 88% del total y 10161 corresponde a un 11% del total.

Por lo tanto, con los porcentajes, procedemos a diseñar 3 vectores, uno numerico, para indicar el numero del porcentaje, y uno categorico, para indicar el nombre correspondiente al pocentaje, el tercero es para indicar los colores.

Porcentajes <- c(88,11)
Etiquetas <- c("88%","11%")
Colores <- c("green","red")

Utilizamos la funcion pie con base a los 3 vectores diseñados con anterioridad.

Pastel1 <- pie(x = Porcentajes, labels = Etiquetas, col = Colores)

La grafica anterior se puede modifcar agregando un titulo, para hacerlo, en el mismo argumento de la funcion ‘pie()’ agregamos main y posteriormente escribimos el titulo deseado.

EJEMPLO

Pastel2 <- pie (x = Porcentajes, labels = Etiquetas, col = Colores, main = "Casos de diabetes COVID19 en la Ciudad de Mexico.")

Por ultimo, podemos agregar las categorias que le corresponde a cada seccion, para ello necesitamos diseñar un vector con las categorias deseadas, ademas, de usar la funcion ‘legend()’.

EJEMPLO

Diseñamos las categorias y usamos la funcion ‘legend()’.

Pastel3 <- pie (x = Porcentajes, labels = Etiquetas, col = Colores, main = "Casos de diabetes COVID19 en la Ciudad de Mexico.")
Categorias <- c("SI","NO")
legend("topright",legend = Categorias, fill = Colores)

Histograma

Los histogramas de frecuencia son similares a las graficas de barra con la diferencia de que la variable que se le asigna al eje x debe ser numerica, esta puede ser diseñada con la pqueteria ‘ggplot2’, eso significa que tenemos que especificar las 3 capas esenciales donde la capa de geometria viene con la instruccion ‘geom_histogram()’.

Es importante denotar que en la capa estetica especificamos solo el eje x pues las y sera un conteo de la misma generando un histograma de frecuencias.

Para ejemplificar lo anterior, usaremos la base de datos con nombre ‘COVID19MX’ de archivo tipo Excel.

Datos <- read.csv("COVID19MX.csv")

Al ver nuestra base de datos nos damos cuenta que la unica columna con datos numericos es la columna de la edad, por lo tanto, construiremos un Histograma con esos datos.

Realizamos las tres capas.

#CAPA DE DATOS
Histograma <- ggplot(Datos)
#CAPA ESTETICA
Histograma <- Histograma + aes(x = EDAD)
#CAPA GEOMETRICA
Histograma <- Histograma + geom_histogram()
#IMPRIMIMOS HISTOGRAMA
Histograma

Un atributo extra que podemos anexar al histograma es poder cambiar el color del contorno de las mismas barras, esto se hace con la instruccion ‘colour()’.

Sintaxis.

Variable_Grafo <- Variable_Grafo + aes( x = Nombre_Columna, colour = Nombre_Columna2)
Variable_Grafo <- Variable_Grafo + scale_color_manual( values = c("Color1","Color2",...,"ColorN") )

Dividiremos el histograma anterior en colores segun el sexo, esta instruccion lo haremos en la capa de Estetica.

Volvemos a construir todo con variables distintas.

#CAPA DATOS
Histograma2 <- ggplot(Datos)
#CAPA ESTETICA
Histograma2 <- Histograma2 + aes(x = EDAD, colour = SEXO)
Histograma2 <- Histograma2 + scale_color_manual( values = c("blue","pink") )
#CAPA GEOMETRIA
Histograma2 <- Histograma2 + geom_histogram()
#IMPRIMIMOS
Histograma2

Por ultimo, tenemos la opcion de cambiar el color dentro de las barras de manera general, tambien podemos cambiar el ancho de las barras y podemos agregar etiquetas a los ejes asi como titulo y subtitulos.

Diferencias con la grafica de barras.

En el histograma para para cambiar el ancho de las barras usamos la instruccion ‘binwith’ en el apartado geometrico.

El histograma anterior lo presentaremos con todas las caracteristicas enseñadas.

#CAPA DATOS
Histograma_Final <- ggplot(Datos)
#CAPA ESTETICA
Histograma_Final <- Histograma_Final + aes(x = EDAD, colour = SEXO)
Histograma_Final <- Histograma_Final + scale_color_manual( values = c("blue","pink") )
#CAPA GEOMETRIA
Histograma_Final <- Histograma_Final + geom_histogram(fill = "white", binwidth = 2)
#NOMBRES EJES
Histograma_Final <- Histograma_Final + xlab("Edad")
Histograma_Final <- Histograma_Final + ylab("Numero de infectados")
#TITULO
Histograma_Final <- Histograma_Final + ggtitle("Datos COVID19 MX",subtitle = "FEB - JUN 2020")
#IMPRIMIMOS
Histograma_Final

NOTA DEL AUTOR : Disculpe las faltas de ortografía, dado que el español no es el lenguaje natural de los lenguajes de programación y, por costumbre, escribir en inglés y sin acentos mientras programo olvido algunas reglas de escritura al español.

LS0tCnRpdGxlOiAiR3LDoWZpY29zIGVuIFIgbWVkaWFudGUgZ2dwbG90MiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKI2dncGxvdDIKClVubyBkZSBsb3MgcGFxdWV0ZXMgbcOhcyBwb3B1bGFyZXMgcGFyYSBsYSB2aXN1YWxpemFjacOzbiBkZSBkYXRvcyBlbiBSIGVzIGdncGxvdDIsIGN1eWFzIGluaWNpYWxlcyBzZSByZWZpZXJlbiBhICJHcmFtw6F0aWNhIGRlIEdyw6FmaWNvcyIuCgoKTGEgcGFydGljdWxhcmlkYWQgZGUgZXN0ZSBwYXF1ZXRlIGVzIHF1ZSBjYWRhIGdyYWZpY2EgcXVlIGNvbnN0cnV5ZSBzZSBjb25mb3JtYSBkZSB1bmEgc2VyaWUgZGUgY2FwYXMgeSBjYWRhIHVuYSBkZSBlbGxhcywgbGUgYXBvcnRhIHVuIGF0cmlidXRvIGRpZmVyZW50ZSBhIGxhIG1pc21hLgoKCkVzIG5lY2VzYXJpbyBpbnN0YWxhcmxvIHBhcmEgcG9kZXIgY3VicmlyIGEgZGV0YWxsZSBsYXMgY2FwYXMgbcOhcyBpbXBvcnRhbnRlcyBkZSBjYWRhIGdyYWZpY28gcHVlcyBlcyBpbXBvcnRhbnRlIHNhYmVyIGNvbW8gc2UgY29tcG9ydGFuIHkgdGVuZXIgdW5hIG1heW9yIGxpYmVydGFkIGFsIG1vbWVudG8gZGUgZ3JhZmljYXIgeSBvYnRlbmVyIG1lam9yZXMgcmVzdWx0YWRvcy4KCgpIYXkgdW5hIGNhcGEgcXVlIGVzcGVjaWZpY2EgbG9zIGRhdG9zIGRlbCBncmFmbywgb3RyYSBjYXBhIHF1ZSBkZXRlcm1pbmEgbGFzIHZhcmlhYmxlcyBxdWUgdmFuIGEgb2N1cGFyIGxvcyBlamVzIHkgb3RyYSBxdWUgZGV0ZXJtaW5hIGxhIGZvcm1hIGRlIGxhIGdyYWZpY2EgKGxpbmVhcywgcHVudG9zLCBiYXJyYXMpLCBlbnRyZSBvdHJhcy4KCgojIyBDb21vIGluc3RhbGFyIGdncGxvdDIKCgpQYXJhIGluc3RhbGFybG8gaGFjZW1vcyBsb3Mgc2lndWllbnRlcyBwYXNvcy4KCgoxLi0gTm9zIGRpcmlqaW1vcyBhICdIZXJyYW1pZW50YXMnLCAnVG9vbHMnIGVuIGluZ2xlcy4KMi4tIFNlbGVjY2lvbmFtb3MgJ0luc3RhbGFyIHBhcXVldGVzJywgJ0luc3RhbGwgUGFja2VnZXMnIGVuIGluZ2xlcy4KMy4tIEVzY3JpYmltb3MgJ2dncGxvdDInCgoKVW5hIHZleiBpbnN0YWxhZG8gZWwgcGFxdWV0ZSBjYXJnYW1vcyBsYXMgZnVuY2lvbmVzIGEgbGEgbGlicmVyw61hIGRlIFIgbWVkaWFudGUgZWwgc2lndWllbnRlIGNodW5rLgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKYGBgCgojIyBHcmFtw6F0aWNhIGRlIGdncGxvMgoKRXMgbXV5IGltcG9ydGFudGUgY29ub2NlciBsYSBncmFtw6F0aWNhIGFsIG1vbWVudG8gZGUgZGVmaW5pciBsYXMgZ3JhZmljYXMgZW4gUiBwdWVzIHNlZ8O6biBlbCBwb3NpY2lvbmFtaWVudG8gZGUgbnVlc3RyYXMgaW5zdHJ1Y2Npb25lcyBzZXJhIGxhIGdyYWZpY2EgcmVzdWx0YW50ZS4KCgpDYWRhIGdyYWZpY28gZW4gUiBzZSBjb21wb25lLCBwcmluY2lwYWxtZW50ZSwgZGUgMyBjYXBhcywgdGFtYmnDqW4gbGxhbWFkb3MgZ3JhbcOhdGljYSBkZSBncsOhZmljb3M6CgoKMS4tRGF0b3MKMi5Fc3TDqXRpY2EKMy5HZW9tZXRyw61hCgpFeHBsaWNhcmVtb3MgY2FkYSB1bm8uCgoKIyMjIERhdG9zLgoKCkxvcyBkYXRvcyBzZSByZWZpZXJlIGEgbGEgYmFzZSBkZSBkYXRvcyBxdWUgcXVlcmVtb3MgZ3JhZmljYXIuCgoKIyMjIEVzdMOpdGljYS4KCgpMYSBlc3TDqXRpY2Egc2UgcmVmaWVyZSBhIGNvbW8gcXVlcmVtb3MgYXNpZ25hciBsYXMgdmFyaWFibGVzIGRlIG51ZXN0cmEgYmFzZSBlbiBsYSBncmFmaWNhLgoKCkVKRU1QTE86CgoKQ3VhbCB2YXJpYWJsZSBlc3RhcsOhIGVuIGVsIGVqZSBYIHkgY3VhbCBlbiBlbCBlamUgWS4KCgojIyMgR2VvbWV0csOtYS4KCgpMYSBnZW9tZXRyw61hIHNlIHJlZmllcmUgYSBsYSBmaWd1cmEgZ2VvbcOpdHJpY2EgcXVlIHF1ZXJlbW9zIHV0aWxpemFyIGVuIGVsIGdyYWZpY28sIGVzIGRlY2lyLCBzaSBxdWVyZW1vcyBoYWNlciB1bmEgZ3JhZmljYSBkZSBkaXNwZXJzacOzbiB1dGlsaXphbW9zIHB1bnRvcywgeSB1biBoaXN0b2dyYW1hIHV0aWxpemFtb3MgYmFycmFzLgoKCkFwcmVuZGVyZW1vcyBhIG1hbmVqYXIgZXN0YSBncmFtw6F0aWNhIGRlIGRhdG9zLgoKCipOT1RBKjogRXhpc3RlbiBvdHJhcyBjYXBhcyBxdWUgc2UgcHVlZGVuIGFncmVnYXIgYWwgZ3JhZmljbyBjb21vIGxhcyBmYWNldGFzLCBlc3RhZMOtc3RpY2FzLCBjb29yZGVuYWRhcywgdGVtYXMsIGV0Yy4gUGVybyBubyBzZXLDoW4gY29tZW50YWRhcyBlbiBlc3RlIGFwYXJ0YWRvLgoKSW1wb3J0YW1vcyBlbCBhcmNoaXZvIGRlIEV4Y2VsIGNvbiBub21icmUgJ1ByZWNpb3MnCgpgYGB7ciBBcmNoaXZvIEVYQ0VMIFByZWNpb3N9CiNERVNJR05BTU9TIEEgTEEgVkFSSUFCTEUgQXJjaGl2b19FeGNlbF9QcmVjaW9zIEVMIEFSQ0hJVk8gQ1NWCgpBcmNoaXZvX0V4Y2VsX1ByZWNpb3MgPC0gcmVhZC5jc3YoIlByZWNpb3MuY3N2IikKCiNMQSBDT0xVTU5BICdQRVRST0xFTycgQ09OVElFTkUgSU5GT1JNQUNJT04gU09CUkUgRUwgUFJFQ0lPIERFTCBCQVJSSUwgRU4gRE9MQVJFUyBQT1IgTElUUk8KI0xBIENPTFVNTkEgJ0RPTEFSJyBNQVJDQSBMQSBUQVNBIERFIENBTUJJTyBERSBET0xBUiBFTiBQRVNPUyBNRVhJQ0FOT1MKI0xBIENPTFVNTkEgJ0RJQScgWSAnTUVTJyBNQVJDQSBMQSBGRUNIQSBRVUUgRlVFIFJFQUxJWkFETy4KCkFyY2hpdm9fRXhjZWxfUHJlY2lvcwpgYGAKQ29uc3RydWlyZW1vcyB1biBncmFmaWNvIGNvbiBsb3MgZGF0b3MgZGVsIHByZWNpbyBkZWwgcGV0cm9sZW8gY29uZm9ybWUgdHJhbnNjdXJyZW4gbG9zIGRpYXMuCgpgYGB7ciBGbHVjdHVhY2lvbiBwcmVjaW8gcGV0cm8gR1JBRklDT30KCiNQUklNRVJPIEFHUkVHQVJFTU9TIExBIENBUEEgREUgTE9TIERBVE9TLCBFUyBERUNJUiwgTEUgREVDSU1PUyBBIFIgREUgRE9OREUgT0JURU5FUiBMT1MgREFUT1MKCkdyYWZpY29fRmx1Y3R1YWNpb25fUHJlY2lvX1BldHJvbGVvIDwtIGdncGxvdChBcmNoaXZvX0V4Y2VsX1ByZWNpb3MpCgojQUdSRUdBTU9TIExBIENBUEEgREUgTEEgRVNURVRJQ0EsIElORElDQU1PUyBRVUUgJ0lORElDRScgU0VSQU4gTEFTIFggWSAnRE9MQVInIFNFUkFOIExBUyBZCgpHcmFmaWNvX0ZsdWN0dWFjaW9uX1ByZWNpb19QZXRyb2xlbyA8LSBHcmFmaWNvX0ZsdWN0dWFjaW9uX1ByZWNpb19QZXRyb2xlbyArIGFlcyggeCA9IEluZGljZSwgeSA9IERvbGFyKQoKI0FHUkVHQU1PUyBMQSBDQVBBIERFIExBIEdFT01FVFJJQSwgRU4gRVNURSBDQVNPIFZBTU9TIEEgQVNJR05BUiBVTkEgVkFSSUFCTEUgUVVFIFRFTkdBIFVOQSBHRU9NRVRSSUEgQ09OIExJTkVBUy4KCkdyYWZpY29fRmx1Y3R1YWNpb25fUHJlY2lvX1BldHJvbGVvX0xpbmVhcyA8LSBHcmFmaWNvX0ZsdWN0dWFjaW9uX1ByZWNpb19QZXRyb2xlbyArIGdlb21fbGluZSgpCgojSU1QUklNSU1PUyBFTCBHUkFGSUNPIFkgTk9UQU1PUyBRVUUgQ09OVElFTkUgTEFTIDMgQ0FQQVMgUVVFIExFIEVTUEVDSUZJQ0FNT1MgQSBSLgoKR3JhZmljb19GbHVjdHVhY2lvbl9QcmVjaW9fUGV0cm9sZW9fTGluZWFzCgpgYGAKClZlcmVtb3MgYWhvcmEsIGNvbiB1bmEgc2VndW5kYSBncmFmaWNhLCBjb21vIHNlIHJlbGFjaW9uYSBlbCBwcmVjaW8gZGVsIGRvbGFyIHkgZGVsIHBldHJvbGVvLgoKYGBge3IgUmVsYWNpb24gcHJlY2lvIGRvbGFyIHkgcGV0cm8gR1JBRklDT30KCiNBR1JFR0FNT1MgTEEgQ0FQQSBERSBMT1MgREFUT1MKCkdyYWZpY29fUmVsYWNpb25fUHJlY2lvX1BldHJvbGVvX0RvbGFyIDwtIGdncGxvdChBcmNoaXZvX0V4Y2VsX1ByZWNpb3MpCgojQUdSRUdBTU9TIExBIENBUEEgREUgTEEgRVNURVRJQ0EKCkdyYWZpY29fUmVsYWNpb25fUHJlY2lvX1BldHJvbGVvX0RvbGFyIDwtIEdyYWZpY29fUmVsYWNpb25fUHJlY2lvX1BldHJvbGVvX0RvbGFyICsgYWVzKHggPSBQZXRyb2xlbywgeSA9IERvbGFyKQoKI0FHUkVHQU1PUyBMQSBDQVBBIERFIExBIEdFT01FVFJJQSBDT04gVU5BIEZJR1VSQSBERSBQVU5UT1MKCkdyYWZpY29fUmVsYWNpb25fUHJlY2lvX1BldHJvbGVvX0RvbGFyX1B1bnRvcyA8LSBHcmFmaWNvX1JlbGFjaW9uX1ByZWNpb19QZXRyb2xlb19Eb2xhciArIGdlb21fcG9pbnQoKQoKI0lNUFJJTUlNT1MgRUwgR1JBRklDTyBZIE5PVEFNT1MgUVVFIENPTlRJRU5FIExBUyAzIENBUEFTIERFU0NSSVRBUy4KCkdyYWZpY29fUmVsYWNpb25fUHJlY2lvX1BldHJvbGVvX0RvbGFyX1B1bnRvcwoKYGBgCgojIyBQcm9waWVkYWRlcyBkZSBsYSBHZW9tZXRyw61hIExpbmUgeSBQb2ludAoKTm9zb3Ryb3Mgc2FiZW1vcyB5YSBxdWUgbGFzIHRyZXMgY2FwYXMgcHJpbmNpcGFsZXMgZGUgdW4gZ3LDoWZpY28gc29uOiBEYXRvcywgRXN0w6l0aWNhIHkgR2VvbWV0csOtYS4gQWRlbWFzLCB2aW1vcyBlbiBwYXJ0aWN1bGFyIGxhIGdlb21ldHLDrWEgZGUgbMOtbmVhIHkgcHVudG9zLCBnZW9tX2xpbmUoKSB5IGdlb21fcG9pbnQoKSByZXNwZWN0aXZhbWVudGUsIGFtYmFzIHRpZW5lbiBhdHJpYnV0b3MgcXVlIHB1ZWRlbiBzZXIgbW9kaWZpY2Fkb3MuCgpWYW1vcyBhIHJlaGFjZXIgZWwgZ3LDoWZpY28gcmVhbGl6YWRvIGVuIGxhIGxlY2Npb24gYW50ZXJpb3IuCgpgYGB7ciBGbHVjdHVhY2lvbiBEb2xhciBHUkFGSUNPfQojUE9ORU1PUyBMQSBDQVBBIERFIExPUyBEQVRPUwoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhciA8LSBnZ3Bsb3QoQXJjaGl2b19FeGNlbF9QcmVjaW9zKQoKI1BPTkVNT1MgTEEgQ0FQQSBERSBMQSBFU1RFVElDQQoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhciA8LSBHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyICsgYWVzKCB4ID0gSW5kaWNlLCB5ID0gRG9sYXIpCgojUE9ORU1PUyBMQSBDQVBBIERFIExBIEdFT01FVFJJQQoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9MaW5lYXMgPC0gR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhciArIGdlb21fbGluZSgpCgojSU1QUklNSU1PUyBFTCBHUkFGSUNPCgpHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX0xpbmVhcwpgYGAKCgpMYSBwcmltZXJhIHZhcmlhY2nDs24gcXVlIHBvZGVtb3MgaGFjZXIgZW4gZWwgYXBhcnRhZG8gJ2dlb21fbGluZSgpJyBlcyBlbCBlc3RpbG8gZGUgbMOtbmVhLiBQb3IgZGVmZWN0bywgbGEgZnVuY2nDs24gZGlidWphIHVuYSBsaW5lYSBjb250aW51YSBwZXJvIHBvZGVtb3MgcGVkaXJsZSBhIFIgcXVlIGRpYnVqZSB1bmEgbGluZWEgcHVudGVhZGEgbyBjb24gZ3Vpb25lcy4KCgpQYXJhIGhhY2VyIGVzdG8gYWdyZWdhbW9zICdsaW5ldHlwZScgZGVudHJvIGRlIGxvcyBwYXLDoW1ldHJvcyBkZSBsYSBmdW5jacOzbiB5LCBkZXBlbmRpZW5kbyBkZSBsYSBsw61uZWEgcXVlIHF1ZXJhbW9zIGVzIGVsIG51bWVybyBxdWUgbGUgdmFtb3MgYSBhc2lnbmFyLgoKClNpbnRheGlzLgoKYGBgClZhcmlhYmxlX0dyYWZvIDwtIFZhcmlhYmxlX0dyYWZvICsgZ2VvbV9saW5lKGxpbmV0eXBlID0gTnVtZXJvKQpgYGAKClZhcmlhYmxlX0dyYWZvIGhhY2UgcmVmZXJlbmNpYSBhIGxhIHZhcmlhYmxlIHF1ZSBhbG1hY2VuYSBlbCBncmFmbyBlbiBzaSBtaXNtbywgTnVtZXJvIGhhY2UgcmVmZXJlbmNpYSBhIGxhIHZhcmlhY2lvbiBxdWUgaGFyZW1vcyBhIGxhIGxpbmVhLiAKCkEgY29udGludWFjaW9uIHZlcmVtb3MgbG9zIDYgdGlwb3MgZGUgbW9kaWZpY2FjaW9uZXMgcXVlIGFjZXB0YSBsaW5ldHlwZS4KCjEuIEzDrW5lYSBzw7NsaWRhCjIuIEzDrW5lYSBndcOtb24KMy4gTMOtbmVhIHB1bnRlYWRhCjQuIEzDrW5lYSBwdW50by1ndcOtb24KNS4gTMOtbmVhIGd1w61vbiBsYXJnbwo2LiBMw61uZWEgZG9zIGd1aW9uZXMKCmBgYHtyIEZsdWN0dWFjaW9uIGRvbGFyIEdSQUZJQ08gTW9kaWZpY2FjaW9uIGxpbmV0eXBlIFRJUE8gTElORUF9CiNBU0lHTkFNT1MgQSBMQSBWQVJJQUJMRSAnR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhX0xpbmV0eXBlXzYnIExBIE1PRElGSUNBQ0lPTiBERSBMSU5FVFlQRSBDT04gTElORUEgUFVOVEVBREEuCgpHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX0xpbmV0eXBlXzYgPC0gR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhciArIGdlb21fbGluZShsaW5ldHlwZSA9IDYpCgojSU1QUklNSU1PUyBFTCBHUkFGSUNPIENPTiBMQSBNT0RJRklDQUNJT04gRU4gTEFTIExJTkVBUyBUSVBPIDYuCgpHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX0xpbmV0eXBlXzYKYGBgCgpMYSBzZWd1bmRhIHZhcmlhY8Otb24gcXVlIHBvZGVtb3MgaGFjZXIgYWwgYXBhcnRhZG8gJ2dlb21fbGluZSgpJyBlcyBlbCBncm9zb3IgZGUgbGEgbMOtbmVhLiAKClBhcmEgaGFjZXIgZXN0byBhZ3JlZ2Ftb3MgJ3NpemUnIGFsIHBhcmFtZXRybyBkZSBsYSBmdW5jacOzbiB5IGVudHJlIG3DoXMgZ3JhbmRlIHNlYSBlbCB2YWxvciBvdG9yZ2FkbywgbcOhcyBzZXJhIGVsIGdyb3NvciBkZSBsYSBsw61uZWEuCgpgYGB7ciBGbHVjdHVhY2lvbiBkb2xhciBHUkFGSUNPIE1vZGlmaWNhY2lvbiBsaW5ldHlwZSBUSVBPIEdST1NPUn0KI1RPTUFSRU1PUyBFTCBHUkFGSUNPIEFOVEVSSU9SIFkgU09MTyBBR1JBTkRBUkVNT1MgRUwgR1JPU09SIERFIExBIExJTkVBIDMKCkdyYWZpY29fRmx1Y3R1YWNpb25fRG9sYXJfTGluZXR5cGVfNl9TaXplXzMgPC0gR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9MaW5ldHlwZV82ICsgZ2VvbV9saW5lKGxpbmV0eXBlID0gNiwgc2l6ZSA9IDMpCgojSU1QUklNSU1PUyBFTCBHUkFGSUNPCgpHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX0xpbmV0eXBlXzZfU2l6ZV8zCmBgYAoKCkxhIHRlcmNlcmEgdmFyaWFjacOzbiBxdWUgcG9kZW1vcyBoYWNlciBhICdnZW9tX2xpbmUoKScgZXMgZWwgY29sb3IuCgpQYXJhIGhhY2VyIGVzdG8gYWdyZWdhbW9zICdjb2xvdXInIGFsIHBhcmFtZXRybyBkZSBsYSBmdW5jaW9uIHkgZGVzaWduYW5kbyBlbCBub21icmUgZGVsIGNvbG9yIGRlc2VhZG8gZW4gaW5nbGVzLgoKRUpFTVBMTy4KCmBgYHtyIEZsdWN0dWFjaW9uIGRvbGFyIEdSQUZJQ08gTW9kaWZpY2FjaW9uIGxpbmV0eXBlIFRJUE8gQ09MT1J9CiNUT01BUkVNT1MgRUwgR1JBRklDTyBBTlRFUklPUiBZIExFIENBTUJJQVJFTU9TIEVMIENPTE9SIEEgQU1BUklMTE8KCkdyYWZpY29fRmx1Y3R1YWNpb25fRG9sYXJfTGluZXR5cGVfNl9TaXplXzNfQ29sb3VyX1JlZCA8LSBHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX0xpbmV0eXBlXzZfU2l6ZV8zICsgZ2VvbV9saW5lKGxpbmV0eXBlID0gNiwgc2l6ZSA9IDMsIGNvbG91ciA9ICJyZWQiKQoKI0lNUFJJTUlNT1MgRUwgR1JBRklDTwoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9MaW5ldHlwZV82X1NpemVfM19Db2xvdXJfUmVkCmBgYAoKTGEgY3VhcnRhIHZhcmlhY2lvbiBxdWUgcG9kZW1vcyBoYWNlciBhICdnZW9tX2xpbmUoKScgZXMgbGEgaW50ZW5zaWRhZCBkZWwgY29sb3IuCgpQYXJhIGhhY2VyIGVzdG8gdGVuZW1vcyBxdWUgYWdyZWdhciAnYWxwaGEnIGFsIHBhcmFtZXRybyBkZSBsYSBmdW5jaW9uIHkgZXNjcmliaWVuZG8gdW4gbnVtZXJvIGVudHJlIDAgeSAxIHBvZGVtb3MgZGVzaWduYXIgbGEgaW50ZW5zaWRhZCBkZWwgY29sb3IgYXNpZ25hZG8uCgpFSkVNUExPLgoKYGBge3IgRmx1Y3R1YWNpb24gZG9sYXIgR1JBRklDTyBNb2RpZmljYWNpb24gbGluZXR5cGUgVElQTyBJTlRFTlNJREFEfQojVE9NQVJFTU9TIEVMIEdSQUZJQ08gQU5URVJJT1IgWSBMRSBDQU1CSUFSRU1PUyBMQSBJTlRFTlNJREFEIERFTCBDT0xPUiBBTUFSSUxMTwoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9MaW5ldHlwZV82X1NpemVfM19Db2xvdXJfUmVkX0FscGhhXzAuMyA8LSBHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX0xpbmV0eXBlXzZfU2l6ZV8zX0NvbG91cl9SZWQgKyBnZW9tX2xpbmUobGluZXR5cGUgPSA2LCBzaXplID0gMywgY29sb3VyID0gInJlZCIsIGFscGhhID0gMC4zKQoKI0lNUFJJTUlNT1MgRUwgR1JBRklDTwoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9MaW5ldHlwZV82X1NpemVfM19Db2xvdXJfUmVkX0FscGhhXzAuMwpgYGAKClVuYSBwcm9waWVkYWQgcXVlIHB1ZWRlIHNlciBtdXkgdXRpbCBlcyBsYSBjb21iaW5hY2lvbiBkZSAnZ2VvbV9saW5lKCknIHkgJ2dlb21fcG9pbnQoKScuIEVzIGRlY2lyIHF1ZSBzaSB0ZW5lbW9zIHVuIGdyYWZvIGNvbiBsaW5lYXMsIGVzIHBvc2libGUgZGlidWphcmxlIHB1bnRvcyBlbmNpbWEuIAoKUGFyYSBoYWNlciBlc3RvIHNlIGFncmVnYSBsYSBjYXBhIGEgbGEgdmFyaWFibGUgcXVlIGNvbnRpZW5lIGVsIGdyYWZpY28gY29uICdnZW9tX2xpbmUoKScuCgpFSkVNUExPLgoKYGBge3IgRmx1Y3R1YWNpb24gZG9sYXIgR1JBRklDTyBNb2RpZmljYWNpb24gbGluZSgpIHkgcG9pbnQoKX0KI1RPTUFSRU1PUyBFTCBHUkFGSUNPIEFOVEVSSU9SIFkgTEUgQU5FWEFSRU1PUyBVTiBDQVBBIERFIFBVTlRPUwoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9MaW5ldHlwZV82X1NpemVfM19Db2xvdXJfUmVkX0FscGhhXzAuMyA8LSBHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX0xpbmV0eXBlXzZfU2l6ZV8zX0NvbG91cl9SZWRfQWxwaGFfMC4zICsgZ2VvbV9wb2ludCgpCgojSU1QUklNSU1PUyBFTCBHUkFGTwoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9MaW5ldHlwZV82X1NpemVfM19Db2xvdXJfUmVkX0FscGhhXzAuMwpgYGAKClZhbW9zIGEgZ3JhZmljYXIgYWhvcmEgbGEgZmx1Y3R1YWNpb24gZGVsIGRvbGFyIHBlcm8gY29uIHB1bnRvcywgc2luIGVtYmFyZ28sIGVzdGEgb2Nhc2lvbiBpbmNsdWlyZW1vcyBlbiB1bmEgbWlzbWEgbGluZWEgdG9kYXMgbGFzIHByb3BpZWRhZGVzIHF1ZSBwdWVkZW4gc2VyIGFncmVnYWRhcyBhIGxhIGZ1bmNpb24gJ2dlb21fcG9pbnQoKScuCgpgYGB7cn0KI0FHUkVHQU1PUyBMQSBDQVBBIERFIExPUyBEQVRPUwoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9QdW50b3MgPC0gZ2dwbG90KEFyY2hpdm9fRXhjZWxfUHJlY2lvcykKCiNBR1JFR0FNT1MgTEEgQ0FQQSBERSBMQSBFU1RFVElDQQoKR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9QdW50b3MgPC0gR3JhZmljb19GbHVjdHVhY2lvbl9Eb2xhcl9QdW50b3MgKyBhZXMoIHggPSBJbmRpY2UsIHkgPSBEb2xhciApCgojQUdSRUdBTU9TIExBIENBUEEgREUgTEEgR0VPTUVUUklBCgpHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX1B1bnRvcyA8LSBHcmFmaWNvX0ZsdWN0dWFjaW9uX0RvbGFyX1B1bnRvcyArIGdlb21fcG9pbnQoc2hhcGUgPSA5LCBzaXplID0gMy41LCBjb2xvdXIgPSAiYmx1ZSIsIGFscGhhID0gMC43MikKCiNJTVBSSU1JTU9TIEVMIEdSQUZJQ08KCkdyYWZpY29fRmx1Y3R1YWNpb25fRG9sYXJfUHVudG9zCmBgYAoKCk5vdGVtb3MgcXVlIGxhIGZ1bmNpb24gJ2dlb21fbGluZSgpJyB5ICdnZW9tX3BvaW50KCknIGNvbXBhcnRlbiBjYXNpIHRvZGFzIGxhcyB2YXJpYWNpb25lcywgc2luIGVtYmFyZ28sIGxpbmV0eXBlIG5vIHNpcnZlIGNvbiAnZ2VvbV9wb2ludCcsIGVuIGNhbWJpbywgc2hhcGUgbW9kaWZpY2EgbGEgZm9ybWEgZGUgbG9zIHB1bnRvcy4gQSBjb250aW51YWNpb24gZW51bWVyYXJlbW9zIGxhcyBwcm9waWVkYWRlcyBjb3JyZXNwb25kaWVudGVzIGEgY2FkYSBmdW5jaW9uOgoKRlVOQ0lPTiAnZ2VvbV9saW5lKCknLgoKMS4gbGluZXR5cGUuIE1vZGlmaWNhIGxhIGZvcm1hIGRlIGxhIGxpbmVhLCA2IHRpcG9zIGRlIGxpbmVhcy4KMi4gc2l6ZS4gTW9kaWZpY2EgZWwgZ3Jvc29yIGRlIGxhIGxpbmVhLgozLiBjb2xvdXIuIE1vZGlmaWNhIGVsIGNvbG9yIGRlIGxhIGxpbmVhLgo0LiBhbHBoYS4gTW9kaWZpY2EgbGEgaW50ZW5zaWRhZCBkZWwgY29sb3IuCgpGVU5DSU9OICdnZW9tX3BvaW50KCknLgoKMS4gc2hhcGUuIE1vZGlmaWNhIGxhIGZvcm1hIGRlbCBwdW50by4yMCB0aXBvcyBkZSBwdW50b3MuCjIuIHNpemUuIE1vZGlmaWNhIGVsIGdyb3NvciBkZWwgcHVudG8uCjMuIGNvbG91ci4gTW9kaWZpY2EgZWwgY29sb3IgZGVsIHB1bnRvLgo0LiBhbHBoYS4gTW9kaWZpY2EgbGEgaW50ZW5zaWRhZCBkZWwgcHVudG8uCgpSZXNwZWN0byBhIGxhcyBmb3JtYXMgcXVlIHB1ZWRlIHRvbWFyIGVsIHB1bnRvLCBzZSBhbmV4YSB1biBsaW5rIHF1ZSB0aWVuZSBsYXMgaW1hZ2VuZXMgY29ycmVzcG9uZGllbnRlcyBhIGNhZGEgdmFsb3IuIAoKW1N5bWJvbHMgcG9pbnQgc2hhcGVzXVsxXQpbMV06IGh0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvd2lraS9yLXBsb3QtcGNoLXN5bWJvbHMtdGhlLWRpZmZlcmVudC1wb2ludC1zaGFwZXMtYXZhaWxhYmxlLWluLXIKCk5vdGVtb3MgcXVlIGFsIHBvbmVyIGxhIGNhcGEgZGUgbGEgRXN0ZXRpY2EgYWdyZWdhbW9zIGxhIGZ1bmNpb24gJ2FlcygpJyBkb25kZSBkZWNsYXJhbW9zIGxvcyBkYXRvcyBhbCBlamUgeCB5IGxvcyBkYXRvcyBhbCBlamUgeS4gRW4gZXN0ZSBtaXNtbyBhcGFydGFkbyBwb2RlbW9zIG1vZGlmaWNhciBsYSBmb3JtYSBkZSBsb3MgcHVudG9zLCBzaGFwZSwgeSBlbCBjb2xvciwgY29sb3VyLCBzaW4gZW1iYXJnbywgcmVhbGl6YXIgZXN0byBvdG9yZ2EgcmVzdWx0YWRvcyBkaWZlcmVudGVzIGEgcXVlIGxvIGhpY2llcmFtb3MgZW4gbGEgY2FwYSBkZSBHZW9tZXRyaWEuCgpMYSBzaW50YXhpcyBlcyBsYSBzaWd1aWVudGUuCgpgYGAKVmFyaWFibGVfR3JhZm8gPC0gVmFyaWFibGVfR3JhZm8gKyBhZXMoIHg9IENvbHVtbmFfaSwgeT0gQ29sdW1uYV9qLCBjb2xvdXI9IENvbHVtbmFfaywgc2hhcGU9IENvbHVtbmFfbikKYGBgCgpWYXJpYWJsZV9HcmFmbyBoYWNlIHJlZmVyZW5jaWEgYSBsYSB2YXJpYWJsZSBxdWUgbGUgYXNpZ25hbW9zIGxhIGNhcGEgZGUgbG9zIGRhdG9zLCBjYWRhICdDb2x1bW5hX2knIHNpbWJvbGl6YSBlbCBub21icmUgZGUgbGEgY29sdW1uYSBxdWUgc2UgcmVwcmVzZW50YXJhIGNvbiBsYSBpbmRpY2FjaW9uIGNvcnJlc3BvbmRpZW50ZS4KCkVuIHBhcnRpY3VsYXIsIGFsIGFzaWduYXIgY29sb3VyIGVzdGFtb3MgZGljaWVuZG8gcXVlIGEgbG9zIHZhbG9yZXMgZGUgZGljaGEgY29sdW1uYSBzZSBsZSBhc2lnbmFyYW4gZGlzdGludG9zIGNvbG9yZXMsIGFsIGFzaWduYXIgc2hhcGUgZXN0YW1vcyBkaWNpZW5kbyBxdWUgYSBsb3MgdmFsb3JlcyBkZSBkaWNoYSBjb2x1bW5hIHNlIGxlIGFzaWduYXJhIGRpc3RpbnRhcyBmb3JtYXMuCgpgYGB7cn0KI1BPTkVNT1MgTEEgQ0FQQSBERSBMT1MgREFUT1MKCkdyYWZvIDwtIGdncGxvdChBcmNoaXZvX0V4Y2VsX1ByZWNpb3MpCgojUE9ORU1PUyBMQSBDQVBBIEVTVEVUSUNBCgpHcmFmbyA8LSBHcmFmbyArIGFlcyh4ID0gUGV0cm9sZW8sIHkgPSBEb2xhciwgY29sb3VyID0gTWVzLCBzaGFwZSA9IE1lcykKCiNQT05FTU9TIExBIENBUEEgR0VPTUVUUklDQQoKR3JhZm8gPC0gR3JhZm8gKyBnZW9tX3BvaW50KCkKCiNJTVBSSU1JTU9TIEVMIEdSQUZPLgoKR3JhZm8KYGBgCgoqKklNUE9SVEFOVEUqKjogU2kgbm9zb3Ryb3MgbW9kaWZpY2Ftb3MgJ2NvbG91cicgeSAnc2hhcGUnIGVuICdnZW9tX3BvaW50KCknLCBlbnRvbmNlcyBlc3RvcyBhanVzdGVzIHNlcmFuIGRhZG9zIGRlIG1hbmVyYSBnZW5lcmFsIGVuIGVsIGdyYWZpY28sIHBvciBsbyB0YW50bywgZXMgYSBkZWNpc2lvbiBkZWwgdXN1YXJpbyBkb25kZSBtb2RpZmljYXIgZXN0b3MgZG9zIHB1bnRvcy4KClNpIGVsIHVzdWFyaW8gaW1wbGVtZW50w7MgJ3NoYXBlJyB5ICdjb2xvdXInIGVuIGxhIGNhcGEgZGUgbGEgRXN0ZXRpY2EgeSBkZXNlYSBtb2RpZmljYXIgYWxndW5hIGRlIGxhcyBmaWd1cmFzIHkgZWwgY29sb3IgcXVlIFIgbGUgYXNpZ25vIGEgdW4gZGF0bywgc2UgaGFjZSBkZSBsYSBzaWd1aWVudGUgbWFuZXJhLgoKKlBBUkEgTEFTIEZJR1VSQVMqLgoKYGBgClZhcmlhYmxlX0dyYWZvIDwtIFZhcmlhYmxlX0dyYWZvICsgc2NhbGVfc2hhcGVfbWFudWFsKCB2YWx1ZXMgPSBjKE51bWVybzEsTnVtZXJvMixOdW1lcm8zLC4uLixOdW1lcm9LKSApCmBgYAoKKlBBUkEgTE9TIENPTE9SRVMqCgpgYGAKVmFyaWFibGVfR3JhZm8gPC0gVmFyaWFibGVfR3JhZm8gKyBzY2FsZV9jb2xvdXJfbWFudWFsKCB2YWx1ZXMgPSBjKCJDb2xvcjEiLCJDb2xvcjIiLC4uLiwiQ29sb3JLIikgKQpgYGAKCipOT1RBKjogRXN0byBzZSBhc2lnbmEgZGVzcHVlcyBkZSBkZWNsYXJhciBsYSBjYXBhIGRlIGxhIEVzdGV0aWNhLCBlcyBkZWNpciwgZGVzcHVlcyBkZSBhw7FhZGlyICdzaGFwZScgeSAnY29sb3InIGVuIGVsIGFyZ3VtZW50byBkZSBhZXMoKS4KClZhcmlhYmxlX0dyYWZvIGhhY2UgcmVmZXJlbmNpYSBhIGxhIHZhcmlhYmxlIHF1ZSBjb250aWVuZSBlbCBncmFmbyBlbiBjdWVzdGlvbiwgTnVtZXJvSSBoYWNlIHJlZmVyZW5jaWEgYSBsYSBmaWd1cmEgcXVlIGRlc2VhbW9zIHF1ZSBsZSBjb3JyZXNwb25kYSBhIGNhZGEgdW5vIGRlIGxvcyB2YWxvcmVzIGNvbnRlbmlkb3MgZW4gbGEgY29sdW1uYSBxdWUgc2UgbGUgYXNpZ25hIGVsIHNoYXBlLCAiQ29sb3JJIiBoYWNlIHJlZmVyZW5jaWEgYWwgY29sb3IgcXVlIGRlc2VhbW9zIHF1ZSBsZSBjb3JyZXNwb25kYSBhIGNhZGEgdW5vIGRlIGxvcyB2YWxvcmVzIGNvbnRlbmlkb3MgZW4gbGEgY29sdW1uYSBhc2lnbmFkYSBhIHNoYXBlLgoKRW4gZWwgZ3JhZm8gYW50ZXJpb3IsIHRlbmVtb3MgNCBtZXNlcyB5IFIgbGUgYXNpZ25vIGEgY2FkYSB1bm8gdW5hIGZpZ3VyYSwgcmVjb3JkZW1vcyBxdWUgZXhpc3RlbiAyMCB0aXBvcyBkZSBwdW50b3MsIHBvciBsbyB0YW50bywgYXNpZ25hcmVtb3MgNCBkaXN0aW50YXMgZm9ybWFzIGEgY2FkYSBtZXMgeSA0IGNvbG9yZXMuCgpgYGB7cn0KI0xFIEFTSUdOQVJFTU9TIEEgTEEgVkFSSUFCTEUgJ0dyYWZvMicgRUwgR1JBRk8gQ09OIExBUyBESUZFUkVOVEVTIEZPUk1BUyBBIENBREEgTUVTLgoKI0FHUkVHQU1PUyBMQSBDQVBBIERFIExPUyBEQVRPUwoKR3JhZm8yIDwtIGdncGxvdChBcmNoaXZvX0V4Y2VsX1ByZWNpb3MpCgojQUdSRUdBTU9TIExBIENBUEEgREUgRVNURVRJQ0EKCkdyYWZvMiA8LSBHcmFmbzIgKyBhZXMoIHggPSBQZXRyb2xlbywgeSA9IERvbGFyLCBjb2xvdXIgPSBNZXMsIHNoYXBlID0gTWVzKQoKI01vZGlmaWNhbW9zIGZpZ3VyYQoKR3JhZm8yIDwtIEdyYWZvMiArIHNjYWxlX3NoYXBlX21hbnVhbCggdmFsdWVzID0gYygxNiwxNywxNSwxOCkgKSAjQUwgTUVTIERFIEFCUklMIExFIEFTSUdOQU1PUyBMQSBGT1JNQSBDT04gTlVNRVJPIDE2LCBBTCBNRVMgRkVCUkVSTyBMRSBBU0lHTkFNT1MgRUwgREUgMTcgWSBTVUNFU0lWQU1FTlRFLgoKI01vZGlmaWNhbW9zIGNvbG9yCgpHcmFmbzIgPC0gR3JhZm8yICsgc2NhbGVfY29sb3VyX21hbnVhbCggdmFsdWVzID0gYygiZ3JlZW4iLCJyZWQiLCJibHVlIiwiYnJvd24iKSApCgojQUdSRUdBTU9TIExBIENBUEEgR0VPTUVUUklDQQoKR3JhZm8yIDwtIEdyYWZvMiArIGdlb21fcG9pbnQoKQoKI0lNUFJJTUlNT1MgRUwgR1JBRk8KCkdyYWZvMgpgYGAKCiMjIFBlcnNvbmFsaXphY2nDs24gZGUgZWplcwoKQ29uIGVsIHBhcXVldGUgZ2dwbG90MiBzZSBwdWVkZSBlZGl0YXIgbG9zIG5vbWJyZXMgZGUgbG9zIGVqZXMsIGVzIGRlY2lyLCB0b21hciB2YWxvcmVzIGRlIGNpZXJ0YSBjb2x1bW5hIHkgYWwgbW9tZW50byBkZSBncmFmaWNhciBjYW1iaWFyIHN1IG5vbWJyZS4KTWFzIGF1biwgc2UgcHVlZGUgYWdyZWdhciB0aXR1bG8geSBzdWJ0aXR1bG8gYWwgZ3JhZm8uCgpQYXJhIGhhY2VyIGxvIGFudGVyaW9yIG1lbmNpb25hZG8gc2UgdXRpbGl6YSBsb3MgY29tYW5kb3MgJ3hsYWIoIk5vbWJyZSBkZXNlYWRvIiknIHBhcmEgZGFyIG5vbWJyZSBhbCBlamUgZGUgbGFzIFgsICd5bGFiKCJOb21icmUgZGVzZWFkbyIpJyBwYXJhIGRhciBub21icmUgYWwgZWplIGRlIGxhcyBZLCAnZ2d0aXRsZSgiTm9tYnJlIHRpdHVsbyIsIHN1YnRpdGxlID0gIk5vbWJyZSBzdWJ0aXR1bG8iKScKCkRpc2XDsWFyZW1vcyB1biBEYXRhIEZyYW1lIHF1ZSBpbmRpcXVlIHZhbG9yZXMgZGUgbGEgWCB5IFkuCgpgYGB7cn0KVmFsb3Jlc19YPWMoMiw0LDYsOCwxMCwxMiwxNCkKVmFsb3Jlc19ZPWMoMSwzLDYsOSwxMiwxNiwxOCkKRGF0YV9GcmFtZT1kYXRhLmZyYW1lKFZhbG9yZXNfWCxWYWxvcmVzX1kpCmBgYAoKR3JhZmljYW1vcy4KCmBgYHtyfQojUE9ORU1PUyBMQSBDQVBBIERFIExPUyBEQVRPUwoKR3JhZm9fRGF0YV9GcmFtZSA8LSBnZ3Bsb3QoRGF0YV9GcmFtZSkKCiNQT05FTU9TIExBIENBUEEgREUgTEEgRVNURVRJQ0EKCkdyYWZvX0RhdGFfRnJhbWUgPC0gR3JhZm9fRGF0YV9GcmFtZSArIGFlcyggeCA9IFZhbG9yZXNfWCwgeSA9IFZhbG9yZXNfWSkKCiNQT05FTU9TIExBIENBUEEgREUgR0VPTUVUUklBCgpHcmFmb19EYXRhX0ZyYW1lIDwtIEdyYWZvX0RhdGFfRnJhbWUgKyBnZW9tX2xpbmUoc2l6ZT0yLjUsY29sb3VyPSJncmVlbiIsIGFscGhhID0gMC41KQoKI0lNUFJJTUlNT1MgRUwgR1JBRklDTwoKR3JhZm9fRGF0YV9GcmFtZQpgYGAKCk1vZGlmaWNhcmVtb3MgbG9zIG5vbWJyZXMgZGUgbG9zIGVqZXMsIGFncmVnYXJlbW9zIHVuIHRpdHVsbyB5IHN1YnRpdHVsbyBhbCBncmFmby4KCmBgYHtyfQojQ0FNQklBUkVNT1MgRUwgTk9NQlJFUyBERSBMT1MgRUpFUy4KCkdyYWZvX0RhdGFfRnJhbWUgPC0gR3JhZm9fRGF0YV9GcmFtZSArIHhsYWIoIkVudHJhZGFzIikKCkdyYWZvX0RhdGFfRnJhbWUgPC0gR3JhZm9fRGF0YV9GcmFtZSArIHlsYWIoIlNhbGlkYXMiKQoKI0FHUkVHQU1PUyBUSVRVTE8gWSBTVUJUSVRVTE8KCkdyYWZvX0RhdGFfRnJhbWUgPC0gR3JhZm9fRGF0YV9GcmFtZSArIGdndGl0bGUoIkNvbnN1bW8gZGVsIG1lcyIsIHN1YnRpdGxlID0gIkFnb3N0by0yMDIwIikKCiNJTVBSSU1JTU9TIEVMIEdSQUZPCgpHcmFmb19EYXRhX0ZyYW1lCmBgYAoKIyMgR3LDoWZpY28gZGUgYmFycmFzCgpBZGVtYXMgZGUgbGFzIGxpbmVhcyB5IHB1bnRvcyBwYXJhIGdyYWZpY2FyLCBlbiBsYSBwYXJ0ZSBnZW9tZXRyaWNhLCBlcyBwb3NpYmxlIGhhY2VyIGdyYWZpY29zIGRlIGJhcnJhcyB5IHBhc3RlbCBlbiBSLgoKRW4gZXN0ZSBhcGFydGFkbyBub3MgZW5mb2NhcmVtb3MgYSBlc3R1ZGlhciBsb3MgZ3JhZmljb3MgZGUgYmFycmFzLgoKTGFzIGdyYWZpY2FzIGRlIGJhcnJhcyBhbCBpZ3VhbCBxdWUgbGFzIGdyYWZpY2FzIGRlIGxpbmVhcyB5IHB1bnRvcyBjb25zdGEgZGUgMyBjYXBhcywgcHJpbmNpcGFsbWVudGUsIGVzIGRlY2lyOiBEYXRvcywgRXN0ZXRpY2EgeSBHZW9tZXRyaWEuCgpTdSBpbXBsZW1lbnRhY2lvbiwgcmVzcGVjdG8gYSBsYSBjYXBhIGRlIGxvcyBkYXRvcyBlcyBleGFjdGFtZW50ZSBpZ3VhbCBhIHVuIGdyYWZpY28gZGUgbGluZWFzIG8gcHVudG9zLCBzaW4gZW1iYXJnbywgYWwgaW1wbGVtZW50YXIgbGEgZXN0ZXRpY2Egc29sbyBlc3BlY2lmaWNhbW9zIGxhIHZhcmlhYmxlIHF1ZSBlc3RhIGVuIGVsIGVqZSB4IHB1ZXMgZWwgZWplIHkgc2llbXByZSBzZXJhIHVuIGNvbnRlbyBkZSBsYXMgdmVjZXMgcXVlIGFwYXJlY2UgZGljaGEgdmFyaWFibGUgcXVlIGVzY3JpYmltb3MgZW4gZWwgZWplIHggKHZlciBlbCBlamVtcGxvKSwgcG9yIHVsdGltbyBwZXJvIG5vIG1lbm9zIGltcG9ydGFudGUsIGxhIGltcGxlbWVudGFjaW9uIGRlIGxhIGNhcGEgZ2VvbWV0cmljYSBkZWZpbmUgcXVlIHF1ZXJlbW9zIHVuIGdyYWZpY28gZGUgYmFycmFzIG1lZGlhbnRlICdnZW9tX2JhcigpJy4KCioqSU1QT1JUQU5URSoqOiBFbiBsb3MgZ3JhZmljb3MgZGUgYmFycmFzLCBsYSB2YXJpYWJsZSBxdWUgc2UgYXNpZ25hIGFsIGVqZSB4IGRlYmUgc2VyIGNhdGVnb3JpY2EuCgpQYXJhIHVuIHVzbyBwcmFjdGljbywgaGFyZW1vcyB1c28gZGUgbGEgYmFzZSBkZSBkYXRvcyBjb250ZW5pZGEgZW4gZWwgYXJjaGl2byBFeGNlbCBjb24gbm9tYnJlICdDT1ZJRDE5TVgnIHF1ZSBjb250aWVuZSBpbmZvcm1hY2lvbiBzb2JyZSBwZXJzb25hcyBjb250YWdpYWRhcyBjb24gY29yb25hdmlydXMgZW4gZG9zIGVudGlkYWRlcyBkZSBsYSBSZXB1YmxpY2EgTWV4aWNhbmEuCgpMb3MgZGF0b3MgaW5jbHVpZG9zIGVuIGxhIGJhc2UgZGUgZGF0b3Mgc29uOiBTZXhvIGRlbCBwYWNpZW50ZSwgZW50aWRhZCBhIGxhIHF1ZSBwZXJ0ZW5lY2UsIHNpIGZ1ZSBob3NwaXRhbGl6YWRvLCBlZGFkLCBlbmZlcm1lZGFkZXMgY3JvbmljYXMgKG9iZXNpZGFkLCBkaWFiZXRlcywgaGlwZXJ0ZW5zaW9uKSB5IGRlY2Vzby4KCkVzIGNsYXJvIHF1ZSB0ZW5lbW9zIGRpZmVyZW50ZXMgdmFyaWFibGVzIHBhcmEgcG9kZXIgZ3JhZmljYXIsIHNpbiBlbWJhcmdvLCBub3MgZW5mb2NhcmVtb3MgYSBncmFmaWNhciBlbCBudW1lcm8gZGUgcGVyc29uYXMgY29udGFnaWFkYXMgcXVlIGhheSBwb3IgZW50aWRhZC4gCgpBc2lnbmFtb3MgYSBsYSB2YXJpYWJsZSBDT1ZJRE1YIGxhIGJhc2UgZGUgZGF0b3MgYWxtYWNlbmFkYSBlbiBlbCBhcmNoaXZvIEV4Y2VsCgpgYGB7cn0KQ09WSURNWCA8LSByZWFkLmNzdigiQ09WSUQxOU1YLmNzdiIpCmBgYAoKQXNpZ25hbW9zIGxhcyBjYXBhcyBhbCBncmFmaWNvIGRlIGJhcnJhcy4KCmBgYHtyfQojQVNJR05BTU9TIExBIENBUEEgREUgTE9TIERBVE9TCgpCYXJyYXNfQ292aWQgPC0gZ2dwbG90KENPVklETVgpCgojQVNJR05BTU9TIExBIENBUEEgRVNURVRJQ0EKCkJhcnJhc19Db3ZpZCA8LSBCYXJyYXNfQ292aWQgKyBhZXMoIHggPSBFTlRJREFEKQoKI0FTSUdOQU1PUyBMQSBDQVBBIEdFT01FVFJJQ0EKCkJhcnJhc19Db3ZpZCA8LSBCYXJyYXNfQ292aWQgKyBnZW9tX2JhcigpCgojSU1QUklNSU1PUyBFTCBHUkFGSUNPCgpCYXJyYXNfQ292aWQKYGBgCgpFeGlzdGUgdW5hIGFuYWxvZ2lhIGFsIGNhbWJpbyBkZSBjb2xvciBkZSBjYWRhIGJhcnJhIGFsIGlndWFsIHF1ZSBlbCBjYW1iaW8gZGUgY29sb3IgZGUgbGluZWEgeSBwdW50bywgc2UgaGFjZSBtZWRpYW50ZSBsYSBjb25kaWNpb24gJ2ZpbGwnLgoKRXMgbmVjZXNhcmlvIHJlY29yZGFyIHF1ZSBkZXBlbmRlIGRlbCBsdWdhciBkb25kZSBkZWNsYXJlbW9zIGZpbGwgZXMgZWwgcmVzdWx0YWRvIG9idGVuaWRvLCBlcyBkZWNpciwgc2kgaW1wbGVtZW50YW1vcyBlbCBjb2xvciBlbiBsYSBjYXBhIEdlb21ldHJpY2EgZXN0ZSBzZSBhcGxpY2FyYSBhIHRvZG8gZWwgZ3JhZm8sIHNpbiBlbWJhcmdvLCBzaSBsbyBoYWNlbW9zIGVuIGxhIGNhcGEgZXN0ZXRpY2EgZXN0ZSBzZSBpbXBsZW1lbnRhcmEgZW4gZWwgY29udGVvIGRlIGxhcyB2YXJpYWJsZXMgZGUgbGEgY29sdW1uYSBhc2lnbmFkYS4KCkVKRU1QTE8gQ0FNQklPIEdFTkVSQUwgREUgQ09MT1IuCgpgYGB7cn0KI0EgTEEgVkFSSUFCTEUgQmFycmFzX0NvdmlkXzIgTEUgQVNJR05BUkVNT1MgVU4gQ0FNQklPIEdFTkVSQUwgREUgQ09MT1IuCgpCYXJyYXNfQ292aWRfMiA8LSBCYXJyYXNfQ292aWQgKyBnZW9tX2JhcihmaWxsID0gImdyZWVuIikKCiNJTVBSSU1JTU9TCgpCYXJyYXNfQ292aWRfMgpgYGAKCgpgYGB7cn0KI0EgTEEgVkFSSUFCTEUgQmFycmFzX0NvdmlkXzMgTEUgQVNJR05BUkVNT1MgVU4gQ0FNQklPIFBPUiBWQVJJQUJMRSBERSBDT0xPUgoKQmFycmFzX0NvdmlkXzMgPC0gQmFycmFzX0NvdmlkICsgYWVzKHggPSBFTlRJREFELCBmaWxsID0gRU5USURBRCkKCiNMRSBBU0lHTkFNT1MgVU5BIEdFT01FVFJJQSBERSBCQVJSQVMKCkJhcnJhc19Db3ZpZF8zIDwtIEJhcnJhc19Db3ZpZF8zICsgZ2VvbV9iYXIoKQoKI0lNUFJJTUlNT1MKCkJhcnJhc19Db3ZpZF8zCmBgYAoKTWFzIGF1biwgcG9kZW1vcyBub3NvdHJvcyBhc2lnbmFyIGEgY2FkYSB2YXJpYWJsZSB1biBjb2xvciBlbiBlc3BlY2lmaWNvIG1lZGlhbnRlIGxhIGluc3RydWNjaW9uICdzY2FsZV9maWxsX21hbnVhbCgpJy4KCkxhIHNpbnRheGlzIGVzIGxhIHNpZ3VpZW50ZS4KClZhcmlhYmxlX0dyYWZvIDwtIFZhcmlhYmxlX0dyYWZvICsgc2NhbGVfZmlsbF9tYW51YWwoIHZhbHVlcyA9IGMoIkNvbG9yMSIsIkNvbG9yMiIsLi4uLCJDb2xvck4iKSApCgpWYXJpYWJsZV9HcmFmbyBoYWNlIHJlZmVyZW5jaWEgYSBsYSB2YXJpYWJsZSBxdWUgY29udGllbmUgZWwgZ3JhZm8gZW4gY3Vlc3Rpb24sICJDb2xvckkiIGhhY2UgcmVmZXJlbmNpYSBhbCBjb2xvciBxdWUgbGUgYXNpZ25hbW9zIGEgbGEgdmFyaWFibGUgZW4gbGEgcG9zaWNpb24gSSBxdWUgY29ycmVzcG9uZGUgYWwgZWplIFguCgpFSkVNUExPLgoKYGBge3J9CiNBIExBIFZBUklBQkxFIEJhcnJhc19Db3ZpZF80IEFTSUdOQVJFTU9TIERPUyBDT0xPUkVTIERJRkVSRU5URVMgQSBMQVMgQkFSUkFTIE1PU1RSQURBUy4KCkJhcnJhc19Db3ZpZF80IDwtIEJhcnJhc19Db3ZpZCArIGFlcyh4ID0gRU5USURBRCwgZmlsbCA9IEVOVElEQUQpCgojQVNJR05BTU9TIEVMIENPTE9SIEFaVUwgQSBDSVVEQUQgREUgTUVYSUNPIFkgVkVSREUgQSBFU1RBRE8gREUgTUVYSU8KCkJhcnJhc19Db3ZpZF80IDwtIEJhcnJhc19Db3ZpZF80ICsgc2NhbGVfZmlsbF9tYW51YWwoIHZhbHVlcyA9IGMoImJsdWUiLCJncmVlbiIpICkKCiNMRSBBU0lHTkFNT1MgVU5BIEdFT01FVFJJQSBERSBCQVJSQVMKCkJhcnJhc19Db3ZpZF80IDwtIEJhcnJhc19Db3ZpZF80ICsgZ2VvbV9iYXIoKQoKI0lNUFJJTUlNT1MgRUwgR1JBRk8KCkJhcnJhc19Db3ZpZF80CmBgYAoKRGUgbWFuZXJhIHNpbWlsYXIgYWwgY2FtYmlvIGRlIGFuY2hvIGRlIHVuYSBsaW5lYSBvIHB1bnRvLCBwb2RlbW9zIG1vZGlmaWNhciBsYSBhbmNodXJhIGRlIGxhcyBiYXJyYXMgbWVkaWFudGUgbGEgaW5zdHJ1Y2Npb24gJ3dpZHRoJyBlbiBlbCBhcGFydGFkbyBHZW9tZXRyaWNvLgoKRWwgdmFsb3IgZGUgd2lkdGggdGllbmUgcXVlIGVzdGFyIGVudHJlIDAgeSAxLgoKYGBge3J9CiNBU0lHTkFNT1MgTEEgQ0FQQSBERSBMT1MgREFUT1MKCkJhcnJhc19Db3ZpZF81IDwtIGdncGxvdChDT1ZJRE1YKQoKI0FTSUdOQU1PUyBMQSBDQVBBIEVTVEVUSUNBCgpCYXJyYXNfQ292aWRfNSA8LSBCYXJyYXNfQ292aWRfNSArIGFlcyggeCA9IEVOVElEQUQsIGZpbGwgPSBFTlRJREFEKQoKI01PRElGSUNBTU9TIExPUyBDT0xPUkVTIERFIExBUyBCQVJSQVMKCkJhcnJhc19Db3ZpZF81IDwtIEJhcnJhc19Db3ZpZF81ICsgc2NhbGVfZmlsbF9tYW51YWwoIHZhbHVlcyA9IGMoInJlZCIsImJyb3duIikpCgojQVNJR05BTU9TIExBIENBUEEgR0VPTUVUUklDQSBZIEFDSElDQU1PUyBMQVMgQkFSUkFTCgpCYXJyYXNfQ292aWRfNSA8LSBCYXJyYXNfQ292aWRfNSArIGdlb21fYmFyKHdpZHRoID0gMC4yKQoKI0lNUFJJTUlNT1MgRUwgR1JBRk8KCkJhcnJhc19Db3ZpZF81CmBgYAoKCkVzIGltcG9ydGFudGUgc2XDsWFsYXIgcXVlIHBvZGVtb3Mgc3ViZGl2aXIgbGFzIGJhcnJhcywgZXMgZGVjaXIsIHRlbmVyIHVuYSBiYXJyYSBxdWUgZXN0ZSBjb250aWRhIGVuIG90cmEuIFBvciBlamVtcGxvLCBzYWJlbW9zIHF1ZSBlbiBsYSBDRE1YIHRlbmVtb3MgbWFzIGRlIDc1MDAwIGNvbnRhZ2lhZG9zIHkgZW4gZWwgRXN0YWRvIGRlIE1leGljbyBtZW5vcyBkZSAyNTAwMCwgcXVlcmVtb3Mgc2FiZXIgY3VhbnRvcyBkZSBlbGxvcyBoYW4gbXVlcnRvLiBQYXJhIGVsbG8gdXRpbGl6YW1vcyBsYSBpbnN0cnVjY2lvbiAnZmlsbCcgYW50ZXMgbWVuY2lvbmFkYSBwZXJvIGVzcGVjaWZpY2FuZG8gcXVlIGdyYWZpcXVlIHkgY29sb3JlZSBsb3MgZGF0b3MgY29udGVuaWRvcyBlbiBkaWNoYSBjb2x1bW5hLgoKRUpFTVBMTy4KCmBgYHtyfQojQVNJR05BTU9TIExBIENBUEEgREUgTE9TIERBVE9TCgpCYXJyYXNfQ292aWRfNiA8LSBnZ3Bsb3QoQ09WSURNWCkKCiNBU0lHTkFNT1MgTEEgQ0FQQSBFU1RFVElDQSBZIEVTUEVDSUZJQ0FNT1MgUVVFIENPTE9SRUUgTE9TIFFVRSBIQU4gRkFMTEVDSURPIFkgTE9TIFFVRSBOTy4KCkJhcnJhc19Db3ZpZF82IDwtIEJhcnJhc19Db3ZpZF82ICsgYWVzKCB4ID0gRU5USURBRCwgZmlsbCA9IERFRlVOQ0lPTikKCiNDQU1CSUFNT1MgRUwgQ09MT1IgREVMIEZJTFRSTyBSRUFMSVpBRE8KCkJhcnJhc19Db3ZpZF82IDwtIEJhcnJhc19Db3ZpZF82ICsgc2NhbGVfZmlsbF9tYW51YWwoIHZhbHVlcyA9IGMoImdyZWVuIiwicmVkIikgKQoKI0FTSUdOQU1PUyBMQSBDQVBBIEdFT01FVFJJQ0EgWSBNT0RJRklDQU1PUyBMQSBBTkNIVVJBCgpCYXJyYXNfQ292aWRfNiA8LSBCYXJyYXNfQ292aWRfNiArIGdlb21fYmFyKHdpZHRoID0gMC4yNSkKCiNJTVBSSU1JTU9TIEVMIEdSQUZPCgpCYXJyYXNfQ292aWRfNgpgYGAKClBvciB1bHRpbW8geSBzb2xvIGNvbW8gZGVtb3N0cmF0aXZvLCBtb3N0cmFyZW1vcyB1biBncmFmaWNvIHF1ZSBtdWVzdHJlIGxhIHByb3BvcmNpb24gZGUgZGlhYmV0aWNvcyBwb3IgZW50aWRhZCB5IGFncmVnYXJlbW9zIHRpdHVsb3MgeSBzdWJ0aXR1bG9zIGFsIGdyYWZpY28uCgpgYGB7cn0KR3JhZm8gPC0gZ2dwbG90KENPVklETVgpCkdyYWZvIDwtIEdyYWZvICsgYWVzKHg9RU5USURBRCxmaWxsPURJQUJFVEVTKQpHcmFmbyA8LSBHcmFmbyArIHNjYWxlX2ZpbGxfbWFudWFsKCB2YWx1ZXMgPSBjKCJ5ZWxsb3ciLCJvcmFuZ2UiKSApCkdyYWZvIDwtIEdyYWZvICsgZ2VvbV9iYXIod2lkdGggPSAwLjIpCkdyYWZvIDwtIEdyYWZvICsgeGxhYigiRW50aWRhZCBGZWRlcmF0aXZhIGRlIE1leGljbyIpCkdyYWZvIDwtIEdyYWZvICsgeWxhYigiTnVtZXJvIGRlIGluZmVjdGFkb3MiKQpHcmFmbyA8LSBHcmFmbyArIGdndGl0bGUoIkRhdG9zIENPVklEMTkgTUVYSUNPIiwgc3VidGl0bGU9IkZFQi1KVU5JTyAyMDIwIikKR3JhZm8KYGBgCgojIyBHcsOhZmljbyBkZSBwYXN0ZWwKClZpbW9zIGxvcyBncmFmaWNvcyBkZSBsaW5lYSwgcHVudG9zIHkgYmFycmEsIGFob3JhIHRvY2EgYW5hbGl6YXIgbGFzIGdyYWZpY2FzIGRlIHBhc3RlbC4gQW50ZXMgZGUgZW1wZXphciwgZXMgbmVjZXNhcmlvIGFjbGFyYXIgcXVlIGxhIGxpYnJlcmlhICdnZ3Bsb3QyJyBubyB0aWVuZSB1bmEgZ2VvbWV0cmlhIGVzcGVjaWZpY2EgcGFyYSBjb25zdHJ1aXIgZ3JhZmljb3MgZGUgcGFzdGVsLCBzaW4gZW1iYXJnbywgZXMgcG9zaWJsZSBoYWNlcmxvcyBhIHBhcnRpciBkZSB1biBncmFmaWNvIGRlIGJhcnJhcy4KClBhcmEgcG9kZXIgY3JlYXIgdW4gZ3JhZmljbyBkZSBwYXN0ZWwgZW4gZnVuY2lvbiBkZSB1biBncmFmaWNvIGRlIGJhcnJhcywgbmVjZXNpdGFtb3MgZGlzZcOxYXIgcHJpbWVybyBudWVzdHJhIGdyYWZpY2EgZGUgYmFycmFzLCBkZXNwdWVzIGZpbHRyYXIgbGEgYmFycmEgcXVlIGRlc2VhbW9zIGZvcm1hciBjb21vIHBhc3RlbCB5IGRlc3B1ZXMgYWdyZWdhciBlbCBjb21hbmRvICdjb29yZF9wb2xhcigpJyBwYXJhIGRpc2XDsWFyIGVsIGdyYWZvIGNvcnJlc3BvbmRpZW50ZS4KCkxhIHNpbnRheGlzIGdlbmVyYWwgZXM6CgpgYGAKRGF0b3MgPC0gcmVhZC5jc3YoIk5vbWJyZV9BcmNoaXZvX0V4Y2VsIikKRGF0b3MgPC0gZmlsdGVyKERhdG9zLCBOb21icmVfQ29sdW1uYV9hX2ZpbHRyYXIgPT0gIk5vbWJyZV9EYXRvIikKVmFyaWFibGVfR3JhZm8gPC0gZ2dwbG90KERhdG9zKQpWYXJpYWJsZV9HcmFmbyA8LSBWYXJpYWJsZV9HcmFmbyArIGFlcyh4ID0gTm9tYnJlX0NvbHVtbmFfYV9maWx0cmFyLCBmaWxsID0gTm9tYnJlX0NvbHVtbmEpClZhcmlhYmxlX0dyYWZvIDwtIFZhcmlhYmxlX0dyYWZvICsgc2NhbGVfZmlsbF9tYW51YWwoIHZhbHVlcyA9IGMoIkNvbG9yMSIsIkNvbG9yMiIsLi4uLCJDb2xvck4iKSApClZhcmlhYmxlX0dyYWZvIDwtIFZhcmlhYmxlX0dyYWZvICsgZ2VvbV9iYXIod2lkdGggPSAjKQpWYXJpYWJsZV9HcmFmbyA8LSBWYXJpYWJsZV9HcmFmbyArIHhsYWIoIk5vbWJyZV9lamVfWCIpClZhcmlhYmxlX0dyYWZvIDwtIFZhcmlhYmxlX0dyYWZvICsgeWxhYigiTm9tYnJlX2VqZV9ZIikKVmFyaWFibGVfR3JhZm8gPC0gVmFyaWFibGVfR3JhZm8gKyBnZ3RpdGxlKCJUaXR1bG9fR3JhZm8iLCBzdWJ0aXRsZT0iU3VidGl0dWxvX0dyYWZvIikKVmFyaWFibGVfR3JhZm8gPC0gVmFyaWFibGVfR3JhZm8gKyBjb29yZF9wb2xhcigieSIpCmBgYAoKUGFyYSBlZmVjdG9zIHByYWN0aWNvcywgdmFtb3MgYSBleHRyYWVyIGxhIGluZm9ybWFjaW9uIGRlIGxhIGJhc2UgZGUgZGF0b3MgYWxtYWNlbmFkYSBlbiBlbCBFeGNlbCAnQ09WSUQxOU1YJy4gQWRlbWFzLCBjb21vIHZhbW9zIGEgZGlzZcOxYXIgdW4gZ3JhZmljbyBkZSBiYXJyYXMgaW5pY2lhbG1lbnRlLCBuZWNlc2l0YW1vcyBpbXBvcnRhciBsYSBsaWJyZXJpYSAnZ2dwbG90MicgeSBhcGFydGUgbGEgbGlicmVyaWEgJ2RwbHlyJyBwYXJhIGFncmVnYXIgbGFzIG1vZGlmaWNhY2lvbmVzIG5lY2VzYXJpYXMgYWwgbW9tZW50byBkZSBkaXNlw7FhciB1biBncmFmaWNvIGRlIHBhc3RlbC4KCmBgYHtyfQojSU1QT1JUQU1PUyBMQSBMSUJSRVJJQQpsaWJyYXJ5KGRwbHlyKQpgYGAKCkxlZW1vcyBsYSBiYXNlIGRlIGRhdG9zLgoKYGBge3J9CkFyY2hpdm9fRXhjZWwgPC0gcmVhZC5jc3YoIkNPVklEMTlNWC5jc3YiKQpgYGAKCkRpc2XDsWFtb3MgZWwgZ3JhZmljbyBkZSBiYXJyYXMuCgpgYGB7cn0KI0NBUEEgREFUT1MKR3JhZm9fQmFycmEgPC0gZ2dwbG90KEFyY2hpdm9fRXhjZWwpCiNDQVBBIEVTVEVUSUNBCkdyYWZvX0JhcnJhIDwtIEdyYWZvX0JhcnJhICsgYWVzKHggPSBFTlRJREFELCBmaWxsPSBESUFCRVRFUykKI01PRElGSUNBTU9TIEVMIENPTE9SIERFICdmaWxsJwpHcmFmb19CYXJyYSA8LSBHcmFmb19CYXJyYSArIHNjYWxlX2ZpbGxfbWFudWFsKCB2YWx1ZXMgPSBjKCJncmVlbiIsInJlZCIpKQojQ0FQQSBHRU9NRVRSSUNBCkdyYWZvX0JhcnJhIDwtIEdyYWZvX0JhcnJhICsgZ2VvbV9iYXIod2lkdGggPSAwLjI1KQojQUdSRUdBTU9TIE5PTUJSRSBBIExPUyBFSkVTCkdyYWZvX0JhcnJhIDwtIEdyYWZvX0JhcnJhICsgeGxhYigiRU5USURBRCBGRURFUkFUSVZBIikKR3JhZm9fQmFycmEgPC0gR3JhZm9fQmFycmEgKyB5bGFiKCJOdW1lcm8gZGUgaW5mZWN0YWRvcyIpCiNBR1JFR0FNT1MgVElUVUxPIFkgU1VCVElUVUxPCkdyYWZvX0JhcnJhIDwtIEdyYWZvX0JhcnJhICsgZ2d0aXRsZSgiQ09WSUQgTUVYSUNPIiwgc3VidGl0bGUgPSAiRkVCLUpVTiAyMDIwIikKI0lNUFJJTUlNT1MgRUwgR1JBRklDTwpHcmFmb19CYXJyYQpgYGAKClZhbW9zIGEgZGlzZcOxYXIgY29tbyBncmFmaWNhIGRlIHBhc3RlbCBhbWJvcyBlc3RhZG9zLgoKQ0lVREFEIERFIE1FWElDTwoKUHJpbWVybyB2YW1vcyBhIGZpbHRyYXIsIHBhcmEgZWxsbywgdm9sdmVyZW1vcyBhIGxlZXIgbGEgYmFzZSBkZSBkYXRvcy4KCmBgYHtyIFBhc3RlbCBDRE1YfQojTEVFTU9TIEJBU0UgREUgREFUT1MKRGF0b3NfQ0RNWCA8LSByZWFkLmNzdigiQ09WSUQxOU1YLmNzdiIpCiNGSUxUUkFNT1MgRVNUQURPCkRhdG9zX0NETVggPC0gZmlsdGVyKERhdG9zX0NETVgsIEVOVElEQUQgPT0gIkNJVURBRCBERSBNRVhJQ08iKQojQ0FQQSBEQVRPUwpHX0NETVggPC0gZ2dwbG90KERhdG9zX0NETVgpCiNDQVBBIEVTVEVUSUNBCkdfQ0RNWCA8LSBHX0NETVggKyBhZXMoeCA9IEVOVElEQUQsIGZpbGwgPSBESUFCRVRFUykKI0NBUEEgR0VPTUVUUklDQQpHX0NETVggPC0gR19DRE1YICsgZ2VvbV9iYXIoKQojTk9NQlJFIERFIEVKRVMKR19DRE1YIDwtIEdfQ0RNWCArIHlsYWIoIklORkVDVEFET1MiKQojVElUVUxPCkdfQ0RNWCA8LSBHX0NETVggKyBnZ3RpdGxlKCJDT1ZJRCBNRVhJQ08iLCBzdWJ0aXRsZT0iRkVCX0pVTiAyMDIwIikKI0RJU0XDsUFNT1MgR1JBRklDQSBERSBQQVNURUwKR19DRE1YIDwtIEdfQ0RNWCArIGNvb3JkX3BvbGFyKCJ5IikKI0lNUFJJTUlNT1MgRUwgR1JBRklDTwpHX0NETVgKCmBgYAoKRVNUQURPIERFIE1FWElDTwoKYGBge3J9CiNMRUVNT1MgTE9TIERBVE9TCkRhdG9zX0VNWCA8LSByZWFkLmNzdigiQ09WSUQxOU1YLmNzdiIpCiNBUExJQ0FNT1MgRUwgRklMVFJPCkRhdG9zX0VNWCA8LSBmaWx0ZXIoRGF0b3NfRU1YLCBFTlRJREFEID09ICJFU1RBRE8gREUgTUVYSUNPIikKI0FQTElDQU1PUyBDQVBBIERFIERBVE9TCkdfRU1YIDwtIGdncGxvdChEYXRvc19FTVgpCiNBUExJQ0FNT1MgQ0FQQSBERSBFU1RFVElDQQpHX0VNWCA8LSBHX0VNWCArIGFlcyh4ID0gRU5USURBRCwgZmlsbCA9IERJQUJFVEVTKQojQVBMSUNBTU9TIENBUEEgREUgR0VPTUVUUklBCkdfRU1YIDwtIEdfRU1YICsgZ2VvbV9iYXIod2lkdGggPSAwLjI1KQojTk9NQlJFIEEgTE9TIEVKRVMKR19FTVggPC0gR19FTVggKyB5bGFiKCJJTkZFQ1RBRE9TIikKI1RJVFVMTwpHX0VNWCA8LSBHX0VNWCArIGdndGl0bGUoIkNPVklEIE1FWElDTyIsIHN1YnRpdGxlID0gIkZFQl9KVU4gMjAyMCIpCiNESVNFw7FBTU9TIEdSQUZJQ0EgREUgUEFTVEVMCkdfRU1YIDwtIEdfRU1YICsgY29vcmRfcG9sYXIoInkiKQojSU1QUklNSU1PUyBFTCBHUkFGSUNPCkdfRU1YCmBgYAoKU2kgbm8gZGVzZWFtb3MgdXRpbGl6YXIgdW5hIGdyYWZpY2EgZGUgYmFycmFzIHBhcmEgY29uc3RydWlyIHVuIGdyYWZpY28gZGUgcGFzdGVsLCBwb2RlbW9zIHJlYWxpemFybG8gbWVkaWFudGUgbGEgZnVuY2lvbiAncGllKCknIGFqZW5hIGEgbGEgcGFxdWV0ZXJpYSAnZ2dwbG90MicsIHBvciBsbyB0YW50bywgbm8gZXMgbmVjZXNhcmlvIGRlc3RhY2FyIGxhcyAzIGNhcGFzIChEYXRvcywgRXN0ZXRpY2EsIEdlb21ldHJpYSkuCgpTaW50YXhpcy4KCmBgYApwaWUoeCA9IFZhcmlhYmxlX051bWVyaWNhLCBsYWJlbHMgPSBWYXJpYWJsZV9Ob21icmVzLCBjb2wgPSBWYXJpYWJsZV9Db2xvcmVzKQpgYGAKClZhcmlhYmxlX051bWVyaWNhIGhhY2UgcmVmZXJlbmNpYSBhIGxhIHZhcmlhYmxlIHF1ZSBjb250aWVuZSBsb3MgdmFsb3JlcyBkZSBsb3MgcG9yY2VudGFqZSBhIGdyYWZpY2FyLCBlbiBkZWNpbWFsLCBlcyBkZWNpciwgODguMSwgVmFyaWFibGVfTm9tYnJlcyBoYWNlIHJlZmVyZW5jaWEgYSBsb3Mgbm9tYnJlcyBlbiBwb3JjZW50YWplIGRlIGxhIGNhbnRpZGFkIGluZ3Jlc2FkYSwgZXMgZGVjaXIsICI4OC4xJSIsIFZhcmlhYmxlX0NvbG9yZXMgaGFjZSByZWZlcmVuY2lhIGEgbG9zIGNvbG9yZXMgcXVlIG5vc290cm9zIGxlIGFzaWduYW1vcyBhIGNhZGEgdmFyaWFibGUgYSBncmFmaWNhci4KCkxhIGRlc3ZlbnRhamEgZGUgZXN0ZSBwcm9jZXNvIGVzIGNhbGN1bGFyIGRlIG1hbmVyYSBtYW51YWwgbG9zIHBvcmNlbnRhamVzIGEgbW9zdHJhci4KClJldG9tYXJlbW9zIGVsIGFwYXJ0YWRvIGFudGVyaW9yLCBlbiBlc3RhIG9jYXNpb24gc29sbyB0cmFiYWphcmVtb3MgY29uIGxhIENJVURBRCBERSBNRVhJQ08uCgpQcmltZXJvIGxlZW1vcyBlbCBhcmNoaXZvLCBkZXNwdWVzIGZpbHRyYW1vcywgbHVlZ28gZmlsdHJhbW9zIGNvbHVtbmEgeSBwcm9jZWRlbW9zIGFuYWxpemFyIGxvcyBkYXRvcyBjb250ZW5pZG9zIGVuIGRpY2hhIGNvbHVtbmEuCgpFc3RvIGxvIGhhY2Vtb3MgcGFyYSBwb2RlciBjYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIG1hbmVyYSBtYW51YWwuCgpgYGB7cn0KQXJjaGl2byA8LSByZWFkLmNzdigiQ09WSUQxOU1YLmNzdiIpCkFyY2hpdm9fQ0RNWCA8LSBmaWx0ZXIoQXJjaGl2bywgRU5USURBRCA9PSAiQ0lVREFEIERFIE1FWElDTyIpCkRpYWJldGVzIDwtIEFyY2hpdm9fQ0RNWCRESUFCRVRFUwp0YWJsZShEaWFiZXRlcykKYGBgCgpQb2RlbW9zIG5vdGFyIHF1ZSBleGlzdGVuIDc2NjE5IHBlcnNvbmFzIFNJTiBkaWFiZXRlcyB5IDEwMTYxIENPTiBkaWFiZXRlcywgZW50b25jZXMsIGVudHJlIGxvcyBkb3MgdGVuZW1vcyB1biB0b3RhbCBkZSA4Njc4MCwgcG9yIGxvIHRhbnRvLCA3NjYxOSBjb3JyZXNwb25kZSBhIHVuIDg4JSBkZWwgdG90YWwgeSAxMDE2MSBjb3JyZXNwb25kZSBhIHVuIDExJSBkZWwgdG90YWwuCgpQb3IgbG8gdGFudG8sIGNvbiBsb3MgcG9yY2VudGFqZXMsIHByb2NlZGVtb3MgYSBkaXNlw7FhciAzIHZlY3RvcmVzLCB1bm8gbnVtZXJpY28sIHBhcmEgaW5kaWNhciBlbCBudW1lcm8gZGVsIHBvcmNlbnRhamUsIHkgdW5vIGNhdGVnb3JpY28sIHBhcmEgaW5kaWNhciBlbCBub21icmUgY29ycmVzcG9uZGllbnRlIGFsIHBvY2VudGFqZSwgZWwgdGVyY2VybyBlcyBwYXJhIGluZGljYXIgbG9zIGNvbG9yZXMuCgpgYGB7cn0KUG9yY2VudGFqZXMgPC0gYyg4OCwxMSkKRXRpcXVldGFzIDwtIGMoIjg4JSIsIjExJSIpCkNvbG9yZXMgPC0gYygiZ3JlZW4iLCJyZWQiKQpgYGAKClV0aWxpemFtb3MgbGEgZnVuY2lvbiBwaWUgY29uIGJhc2UgYSBsb3MgMyB2ZWN0b3JlcyBkaXNlw7FhZG9zIGNvbiBhbnRlcmlvcmlkYWQuCgpgYGB7cn0KUGFzdGVsMSA8LSBwaWUoeCA9IFBvcmNlbnRhamVzLCBsYWJlbHMgPSBFdGlxdWV0YXMsIGNvbCA9IENvbG9yZXMpCmBgYAoKTGEgZ3JhZmljYSBhbnRlcmlvciBzZSBwdWVkZSBtb2RpZmNhciBhZ3JlZ2FuZG8gdW4gdGl0dWxvLCBwYXJhIGhhY2VybG8sIGVuIGVsIG1pc21vIGFyZ3VtZW50byBkZSBsYSBmdW5jaW9uICdwaWUoKScgYWdyZWdhbW9zIG1haW4geSBwb3N0ZXJpb3JtZW50ZSBlc2NyaWJpbW9zIGVsIHRpdHVsbyBkZXNlYWRvLgoKRUpFTVBMTwoKYGBge3J9ClBhc3RlbDIgPC0gcGllICh4ID0gUG9yY2VudGFqZXMsIGxhYmVscyA9IEV0aXF1ZXRhcywgY29sID0gQ29sb3JlcywgbWFpbiA9ICJDYXNvcyBkZSBkaWFiZXRlcyBDT1ZJRDE5IGVuIGxhIENpdWRhZCBkZSBNZXhpY28uIikKYGBgCgpQb3IgdWx0aW1vLCBwb2RlbW9zIGFncmVnYXIgbGFzIGNhdGVnb3JpYXMgcXVlIGxlIGNvcnJlc3BvbmRlIGEgY2FkYSBzZWNjaW9uLCBwYXJhIGVsbG8gbmVjZXNpdGFtb3MgZGlzZcOxYXIgdW4gdmVjdG9yIGNvbiBsYXMgY2F0ZWdvcmlhcyBkZXNlYWRhcywgYWRlbWFzLCBkZSB1c2FyIGxhIGZ1bmNpb24gJ2xlZ2VuZCgpJy4KCkVKRU1QTE8KCkRpc2XDsWFtb3MgbGFzIGNhdGVnb3JpYXMgeSB1c2Ftb3MgbGEgZnVuY2lvbiAnbGVnZW5kKCknLgoKYGBge3J9ClBhc3RlbDMgPC0gcGllICh4ID0gUG9yY2VudGFqZXMsIGxhYmVscyA9IEV0aXF1ZXRhcywgY29sID0gQ29sb3JlcywgbWFpbiA9ICJDYXNvcyBkZSBkaWFiZXRlcyBDT1ZJRDE5IGVuIGxhIENpdWRhZCBkZSBNZXhpY28uIikKQ2F0ZWdvcmlhcyA8LSBjKCJTSSIsIk5PIikKbGVnZW5kKCJ0b3ByaWdodCIsbGVnZW5kID0gQ2F0ZWdvcmlhcywgZmlsbCA9IENvbG9yZXMpCmBgYAoKIyMgSGlzdG9ncmFtYQoKTG9zIGhpc3RvZ3JhbWFzIGRlIGZyZWN1ZW5jaWEgc29uIHNpbWlsYXJlcyBhIGxhcyBncmFmaWNhcyBkZSBiYXJyYSBjb24gbGEgZGlmZXJlbmNpYSBkZSBxdWUgbGEgdmFyaWFibGUgcXVlIHNlIGxlIGFzaWduYSBhbCBlamUgeCBkZWJlIHNlciBudW1lcmljYSwgZXN0YSBwdWVkZSBzZXIgZGlzZcOxYWRhIGNvbiBsYSBwcXVldGVyaWEgJ2dncGxvdDInLCBlc28gc2lnbmlmaWNhIHF1ZSB0ZW5lbW9zIHF1ZSBlc3BlY2lmaWNhciBsYXMgMyBjYXBhcyBlc2VuY2lhbGVzIGRvbmRlIGxhIGNhcGEgZGUgZ2VvbWV0cmlhIHZpZW5lIGNvbiBsYSBpbnN0cnVjY2lvbiAnZ2VvbV9oaXN0b2dyYW0oKScuCgpFcyBpbXBvcnRhbnRlIGRlbm90YXIgcXVlIGVuIGxhIGNhcGEgZXN0ZXRpY2EgZXNwZWNpZmljYW1vcyBzb2xvIGVsIGVqZSB4IHB1ZXMgbGFzIHkgc2VyYSB1biBjb250ZW8gZGUgbGEgbWlzbWEgZ2VuZXJhbmRvIHVuIGhpc3RvZ3JhbWEgZGUgZnJlY3VlbmNpYXMuCgpQYXJhIGVqZW1wbGlmaWNhciBsbyBhbnRlcmlvciwgdXNhcmVtb3MgbGEgYmFzZSBkZSBkYXRvcyBjb24gbm9tYnJlICdDT1ZJRDE5TVgnIGRlIGFyY2hpdm8gdGlwbyBFeGNlbC4KCmBgYHtyfQpEYXRvcyA8LSByZWFkLmNzdigiQ09WSUQxOU1YLmNzdiIpCmBgYAoKQWwgdmVyIG51ZXN0cmEgYmFzZSBkZSBkYXRvcyBub3MgZGFtb3MgY3VlbnRhIHF1ZSBsYSB1bmljYSBjb2x1bW5hIGNvbiBkYXRvcyBudW1lcmljb3MgZXMgbGEgY29sdW1uYSBkZSBsYSBlZGFkLCBwb3IgbG8gdGFudG8sIGNvbnN0cnVpcmVtb3MgdW4gSGlzdG9ncmFtYSBjb24gZXNvcyBkYXRvcy4KClJlYWxpemFtb3MgbGFzIHRyZXMgY2FwYXMuCgpgYGB7cn0KI0NBUEEgREUgREFUT1MKSGlzdG9ncmFtYSA8LSBnZ3Bsb3QoRGF0b3MpCiNDQVBBIEVTVEVUSUNBCkhpc3RvZ3JhbWEgPC0gSGlzdG9ncmFtYSArIGFlcyh4ID0gRURBRCkKI0NBUEEgR0VPTUVUUklDQQpIaXN0b2dyYW1hIDwtIEhpc3RvZ3JhbWEgKyBnZW9tX2hpc3RvZ3JhbSgpCiNJTVBSSU1JTU9TIEhJU1RPR1JBTUEKSGlzdG9ncmFtYQpgYGAKClVuIGF0cmlidXRvIGV4dHJhIHF1ZSBwb2RlbW9zIGFuZXhhciBhbCBoaXN0b2dyYW1hIGVzIHBvZGVyIGNhbWJpYXIgZWwgY29sb3IgZGVsIGNvbnRvcm5vIGRlIGxhcyBtaXNtYXMgYmFycmFzLCBlc3RvIHNlIGhhY2UgY29uIGxhIGluc3RydWNjaW9uICdjb2xvdXIoKScuCgpTaW50YXhpcy4KCmBgYApWYXJpYWJsZV9HcmFmbyA8LSBWYXJpYWJsZV9HcmFmbyArIGFlcyggeCA9IE5vbWJyZV9Db2x1bW5hLCBjb2xvdXIgPSBOb21icmVfQ29sdW1uYTIpClZhcmlhYmxlX0dyYWZvIDwtIFZhcmlhYmxlX0dyYWZvICsgc2NhbGVfY29sb3JfbWFudWFsKCB2YWx1ZXMgPSBjKCJDb2xvcjEiLCJDb2xvcjIiLC4uLiwiQ29sb3JOIikgKQpgYGAKCkRpdmlkaXJlbW9zIGVsIGhpc3RvZ3JhbWEgYW50ZXJpb3IgZW4gY29sb3JlcyBzZWd1biBlbCBzZXhvLCBlc3RhIGluc3RydWNjaW9uIGxvIGhhcmVtb3MgZW4gbGEgY2FwYSBkZSBFc3RldGljYS4KClZvbHZlbW9zIGEgY29uc3RydWlyIHRvZG8gY29uIHZhcmlhYmxlcyBkaXN0aW50YXMuCgpgYGB7cn0KI0NBUEEgREFUT1MKSGlzdG9ncmFtYTIgPC0gZ2dwbG90KERhdG9zKQojQ0FQQSBFU1RFVElDQQpIaXN0b2dyYW1hMiA8LSBIaXN0b2dyYW1hMiArIGFlcyh4ID0gRURBRCwgY29sb3VyID0gU0VYTykKSGlzdG9ncmFtYTIgPC0gSGlzdG9ncmFtYTIgKyBzY2FsZV9jb2xvcl9tYW51YWwoIHZhbHVlcyA9IGMoImJsdWUiLCJwaW5rIikgKQojQ0FQQSBHRU9NRVRSSUEKSGlzdG9ncmFtYTIgPC0gSGlzdG9ncmFtYTIgKyBnZW9tX2hpc3RvZ3JhbSgpCiNJTVBSSU1JTU9TCkhpc3RvZ3JhbWEyCmBgYAoKUG9yIHVsdGltbywgdGVuZW1vcyBsYSBvcGNpb24gZGUgY2FtYmlhciBlbCBjb2xvciBkZW50cm8gZGUgbGFzIGJhcnJhcyBkZSBtYW5lcmEgZ2VuZXJhbCwgdGFtYmllbiBwb2RlbW9zIGNhbWJpYXIgZWwgYW5jaG8gZGUgbGFzIGJhcnJhcyB5IHBvZGVtb3MgYWdyZWdhciBldGlxdWV0YXMgYSBsb3MgZWplcyBhc2kgY29tbyB0aXR1bG8geSBzdWJ0aXR1bG9zLgoKRGlmZXJlbmNpYXMgY29uIGxhIGdyYWZpY2EgZGUgYmFycmFzLgoKRW4gZWwgaGlzdG9ncmFtYSBwYXJhIHBhcmEgY2FtYmlhciBlbCBhbmNobyBkZSBsYXMgYmFycmFzIHVzYW1vcyBsYSBpbnN0cnVjY2lvbiAnYmlud2l0aCcgZW4gZWwgYXBhcnRhZG8gZ2VvbWV0cmljby4KCkVsIGhpc3RvZ3JhbWEgYW50ZXJpb3IgbG8gcHJlc2VudGFyZW1vcyBjb24gdG9kYXMgbGFzIGNhcmFjdGVyaXN0aWNhcyBlbnNlw7FhZGFzLgoKYGBge3J9CiNDQVBBIERBVE9TCkhpc3RvZ3JhbWFfRmluYWwgPC0gZ2dwbG90KERhdG9zKQojQ0FQQSBFU1RFVElDQQpIaXN0b2dyYW1hX0ZpbmFsIDwtIEhpc3RvZ3JhbWFfRmluYWwgKyBhZXMoeCA9IEVEQUQsIGNvbG91ciA9IFNFWE8pCkhpc3RvZ3JhbWFfRmluYWwgPC0gSGlzdG9ncmFtYV9GaW5hbCArIHNjYWxlX2NvbG9yX21hbnVhbCggdmFsdWVzID0gYygiYmx1ZSIsInBpbmsiKSApCiNDQVBBIEdFT01FVFJJQQpIaXN0b2dyYW1hX0ZpbmFsIDwtIEhpc3RvZ3JhbWFfRmluYWwgKyBnZW9tX2hpc3RvZ3JhbShmaWxsID0gIndoaXRlIiwgYmlud2lkdGggPSAyKQojTk9NQlJFUyBFSkVTCkhpc3RvZ3JhbWFfRmluYWwgPC0gSGlzdG9ncmFtYV9GaW5hbCArIHhsYWIoIkVkYWQiKQpIaXN0b2dyYW1hX0ZpbmFsIDwtIEhpc3RvZ3JhbWFfRmluYWwgKyB5bGFiKCJOdW1lcm8gZGUgaW5mZWN0YWRvcyIpCiNUSVRVTE8KSGlzdG9ncmFtYV9GaW5hbCA8LSBIaXN0b2dyYW1hX0ZpbmFsICsgZ2d0aXRsZSgiRGF0b3MgQ09WSUQxOSBNWCIsc3VidGl0bGUgPSAiRkVCIC0gSlVOIDIwMjAiKQojSU1QUklNSU1PUwpIaXN0b2dyYW1hX0ZpbmFsCgpgYGAKCioqTk9UQSBERUwgQVVUT1IqKiA6IERpc2N1bHBlIGxhcyBmYWx0YXMgZGUgb3J0b2dyYWbDrWEsIGRhZG8gcXVlIGVsIGVzcGHDsW9sIG5vIGVzIGVsIGxlbmd1YWplIG5hdHVyYWwgZGUgbG9zIGxlbmd1YWplcyBkZSBwcm9ncmFtYWNpw7NuIHksIHBvciBjb3N0dW1icmUsIGVzY3JpYmlyIGVuIGluZ2zDqXMgeSBzaW4gYWNlbnRvcyBtaWVudHJhcyBwcm9ncmFtbyBvbHZpZG8gYWxndW5hcyByZWdsYXMgZGUgZXNjcml0dXJhIGFsIGVzcGHDsW9sLg==