Contexto

El paquete nycflights13 contiene información sore todos los vuelos que partieron desde Nueva York(EWR, JFL, LGA) en destinos a los Estados Unidos en 2013. Fueron 336,776 vuelos en total. Para ayudar a comprender las causas de los retrasos, también incluye otros conjuntos de datos útiles.

Este paquete incluye las siguientes tablas:

  • flights = todos los vuelos que salieron de NUeva York en el 2013
  • weather = datos metereológicos por hora de cada aeropuerto
  • planes = información de construcción de cada avión
  • airports = nombres y ublicaciones de aeropuertos
  • airlines = relación entre nombres y códigos de las aerolíneas

Fuente: Origen de los datos

Reporte Ejecutivo

En esta evidencia se trabajó con el paquete nycflights, el cual nos permitió analizar información acerca de los vuelos, destinos, aerolíneas, retrasos, entre otros; registrados en los aeropuertos de Nueva York en el 2013. Se utilizaron las funciones más comunes del análisis exploratorio, el cual es el primer paso para cualquier trabajo de manipulación de datos.

La situación problema que se buscaba resolver es saber el por qué los vuelos se retrasan, ya sea en la partida o en la llegada, en los aeropuertos en Nueva York. Con la información brindada en las bases de datos, se pudo realizar un análisis tomando en cuenta diferentes variables, ya sea el clima, el tipo de avión que se utilizaba, la aerolínea, el día de la semana, las temporadas vacacionales e incluso hasta el horario del día. Al analizar esta información se obtuvieron datos que nos permitirían evaluar cuál es el verdadero motivo por el que los vuelos se retrasan.

Para este proyecto diferentes metodologías fueron puestas a prueba, las cuales ayudaron a generar conclusiones del análisis general de retrasos en partidas y llegadas. El uso de visualizaciones de gráficas de barras, histogramas, diagramas de dispersión, entre otros, fueron herramientas importantes para el análisis visual.

A medida con la que se avanzaba en el análisis, podíamos ir descartando que variables no servían de mucho y cuales sí tenían un mayor impacto para resolver la situación problema. Esto nos permitía generar un mayor enfoque en aquellos aspectos más relevantes y posteriormente, con creatividad, generar propuestas para la disminución de retrasos en salidas y llegadas.

A continuación se presenta la evidencia final, con análisis, interpretaciones, elementos visuales y recomendaciones para las aerolíneas, aeropuertos y pasajeros, todo esto con el propósito de brindar solución a los retrasos generados.

Instalar paquetes y llamar librerías

#install.packages("nycflight13")
library(nycflights13)
#install.packages("tidyverse")
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.0     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
#install.packages("dplyr")
library(dplyr)
#install.packages("ggplot2")
library(ggplot2)
data("flights")

Guardar base de datos

flights <- flights
weather <- weather
planes <- planes
airports <- airports
airlines <- airlines

Relación entre las bases de datos

Relación existente

df <- merge(flights,airlines, by="carrier")
df <- left_join(df,planes, by="tailnum")
df <- left_join(df,weather, by=c("origin","time_hour"))

Data Wrangling

1. Funciones básicas de manejo de datos

Select

La función select sirve para seleccionar columnos de un table (data frame).

df1 <- flights %>% select(carrier, flight) # Selección de columnas específicas
df2 <- flights %>% select(carrier:distance) # Selección de rango de columnas
df3 <- flights %>% select(-carrier, -flight) # Eliminar columnas específicas
df4 <- flights %>% select(-carrier: -flight) # Eliminar rango de columnas
df5 <- flights %>% select(aerolinea = carrier) # Selecciona una columna y le cambia el nombre
df6 <- flights %>% rename(aerolinea = carrier) # Cambia el nombre de una columna

Filter

La función Filter sirve para seleccionar renglones de un tabla(data frame).

df7 <- flights %>% filter(dep_delay >=500) # Extrae renglones que cumplan condición
# Condicionales: Igual ==, Desigual =!=, Mayor que >, Mayor o igual que >=, Menor o igual que <=
# Operadores lógicos: AND &, OR |, NOT !
df8 <- flights %>% filter(dep_delay >=500, dep_delay <=600) # Extrae renglones que cumplan con dos condiciones
df9 <- flights %>% slice(1000: 1099) # Extrae los números de los renglones indicados, sin importar sus valores

Distinct

La función distinct sirve para eliminar renglones duplicados.

df10 <- distinct(flights) # Dejar solo los renglones diferentes, borra todos los repetidos.

Merge

La función merge sirve para juntar bases de datos.

bdgrande <- merge(flights, airlines, by="carrier")
bdgrande2 <- merge(bdgrande,planes, by="tailnum")

Mutate

bdgrande3 <- mutate(bdgrande2, dist_mts = distance*1.609)
#Agrega variables nuevas caluladas a partir de variables existentes en la base de datos.

Ejercicios

  1. Encuentra todos los vuelos que tuvieron un atraso en llegada de 2 horas o más.
ejercicio1 <- bdgrande2 %>% filter(arr_delay>=120)
  1. Encuentra todos los vuelos que llegaron a Houston (IAN O HOU)
ejercicio2 <- bdgrande2 %>% filter(dest== "IAH" | dest == "HOU")
  1. Encuentra todos los vuelos operados por United, American o Delta.
ejercicio3 <- bdgrande2 %>% filter(carrier %in% c("UA", "AA", "DL"))
  1. Encuentra todos los vuelos que despegaron en Julio, Agosto o Septiembre
ejercicio4 <- bdgrande2 %>% filter(month %in% c(7, 8, 9))
ejercicio4a <- bdgrande2 %>% filter(month == 7 | month == 8 | month == 9) 
  1. Encuentra todos los vuelos que arrivaron más de 2 horas tarde, pero no despegaron tarde.
ejercicio5 <- bdgrande2 %>% filter(arr_delay>120 & dep_time == sched_dep_time)
ejercicio5a <- bdgrande2 %>% filter(arr_delay>120 & dep_delay<=0)
  1. Encuentra todos los vuelos que se retrasaron al menos 1 hora, pero que llegaron antes 30 minutos o más.
ejercicio6 <- bdgrande2 %>% filter(dep_delay>=60 & arr_delay<=-30)
  1. Encuentra todos los vuelos que salieron entre la medianoche y las 6 a.m.
ejercicio7 <- bdgrande2 %>% filter(dep_time %in% c("2400", "100", "200", "300", "400", "500", "600"))
ejercicio7a <- bdgrande2 %>% filter(dep_time==2400 | dep_time<=600) #CORRECTA
ejercicio7b <- bdgrande2 %>% filter(hour %in% c("0", "1", "2", "3", "4", "5", "6"))

Arrange

Similar a filter () pero en lugar de seleccionar renglones, los ordena de menor a mayor.

df11 <- arrange(bdgrande2, year.x, month, day)

Para acomodar de mayor a menor.

df12 <- arrange(bdgrande2, year.x, desc(month), day)

Summarize

Colapsa una tabla a un sólo renglón

# Obtén el retraso promedio de salida de despegue de todos los vuelos
summarize(bdgrande2, mean(dep_delay, na.rm=TRUE))
##   mean(dep_delay, na.rm = TRUE)
## 1                      13.17979

Group by

Agrupa tabla basado en algunas columnas.

# Obtener el retraso promedio de despegue por día
por_dia <- group_by(bdgrande2, year.x, month, day)
summarize(por_dia, mean(dep_delay, na.rm=TRUE))
## `summarise()` has grouped output by 'year.x', 'month'. You can override using
## the `.groups` argument.
## # A tibble: 365 × 4
## # Groups:   year.x, month [12]
##    year.x month   day `mean(dep_delay, na.rm = TRUE)`
##     <int> <int> <int>                           <dbl>
##  1   2013     1     1                           10.7 
##  2   2013     1     2                           14.4 
##  3   2013     1     3                           11.1 
##  4   2013     1     4                           10.0 
##  5   2013     1     5                            5.70
##  6   2013     1     6                            7.98
##  7   2013     1     7                            6.49
##  8   2013     1     8                            3.10
##  9   2013     1     9                            3.17
## 10   2013     1    10                            1.89
## # ℹ 355 more rows

Evidencia: Parte 1

1. Cargar en memoria la tabla “flights” y mostrar su contenido

# La carga a memoria se hizo en el paso anterior, consulta de dataframe para recordar su contenido.
view(flights)

2. Datos descriptivos de “flights”

# Identifica la media de las distancias recorridas en millas.
summary(flights)
##       year          month             day           dep_time    sched_dep_time
##  Min.   :2013   Min.   : 1.000   Min.   : 1.00   Min.   :   1   Min.   : 106  
##  1st Qu.:2013   1st Qu.: 4.000   1st Qu.: 8.00   1st Qu.: 907   1st Qu.: 906  
##  Median :2013   Median : 7.000   Median :16.00   Median :1401   Median :1359  
##  Mean   :2013   Mean   : 6.549   Mean   :15.71   Mean   :1349   Mean   :1344  
##  3rd Qu.:2013   3rd Qu.:10.000   3rd Qu.:23.00   3rd Qu.:1744   3rd Qu.:1729  
##  Max.   :2013   Max.   :12.000   Max.   :31.00   Max.   :2400   Max.   :2359  
##                                                  NA's   :8255                 
##    dep_delay          arr_time    sched_arr_time   arr_delay       
##  Min.   : -43.00   Min.   :   1   Min.   :   1   Min.   : -86.000  
##  1st Qu.:  -5.00   1st Qu.:1104   1st Qu.:1124   1st Qu.: -17.000  
##  Median :  -2.00   Median :1535   Median :1556   Median :  -5.000  
##  Mean   :  12.64   Mean   :1502   Mean   :1536   Mean   :   6.895  
##  3rd Qu.:  11.00   3rd Qu.:1940   3rd Qu.:1945   3rd Qu.:  14.000  
##  Max.   :1301.00   Max.   :2400   Max.   :2359   Max.   :1272.000  
##  NA's   :8255      NA's   :8713                  NA's   :9430      
##    carrier              flight       tailnum             origin         
##  Length:336776      Min.   :   1   Length:336776      Length:336776     
##  Class :character   1st Qu.: 553   Class :character   Class :character  
##  Mode  :character   Median :1496   Mode  :character   Mode  :character  
##                     Mean   :1972                                        
##                     3rd Qu.:3465                                        
##                     Max.   :8500                                        
##                                                                         
##      dest              air_time        distance         hour      
##  Length:336776      Min.   : 20.0   Min.   :  17   Min.   : 1.00  
##  Class :character   1st Qu.: 82.0   1st Qu.: 502   1st Qu.: 9.00  
##  Mode  :character   Median :129.0   Median : 872   Median :13.00  
##                     Mean   :150.7   Mean   :1040   Mean   :13.18  
##                     3rd Qu.:192.0   3rd Qu.:1389   3rd Qu.:17.00  
##                     Max.   :695.0   Max.   :4983   Max.   :23.00  
##                     NA's   :9430                                  
##      minute        time_hour                     
##  Min.   : 0.00   Min.   :2013-01-01 05:00:00.00  
##  1st Qu.: 8.00   1st Qu.:2013-04-04 13:00:00.00  
##  Median :29.00   Median :2013-07-03 10:00:00.00  
##  Mean   :26.23   Mean   :2013-07-03 05:22:54.64  
##  3rd Qu.:44.00   3rd Qu.:2013-10-01 07:00:00.00  
##  Max.   :59.00   Max.   :2013-12-31 23:00:00.00  
## 

3. Criterios para encontrar aerolíneas

#Crea un nuevo data frame que filtre solamente a las aeorlíneas que han recorrido una distancia superior a la media, se desean ver los campos carrier, distance, origin, dest en forma descendente por distance.

#Criterio 1: se selecciona las variables.
Criterio1 <- flights %>% select(carrier, distance, origin, dest)

#Criterio 2: se filtran a las aerolineas que tengan una media superior a 1040 en millas recorridas. 
Criterio2 <- Criterio1 %>% filter(distance >1040)

#Criterio 3: se ordena en descendente por la distancia recorrida 
Criterio3 <- Criterio2 %>% arrange(desc(distance))

4. Suma y Media de las distancias recorridas

# Se encuentra la suma y la media de las distancias recorridas por carrier, elimina los NA’S e interpreta que significa la suma y la media de las distancias recorridas.

Criterio4 <- Criterio3 %>% group_by(carrier,origin,dest) %>%  
  summarize(distancesuma=sum(distance, na.rm=TRUE), distancepromedio=mean(distance, na.rm=TRUE))
## `summarise()` has grouped output by 'carrier', 'origin'. You can override using
## the `.groups` argument.
# Posteriormente, se ordena de forma descendente en base a la distancia recorrida.
Descendente <- Criterio4 %>% arrange(carrier,distancesuma)

5. Interpretaciones: Parte 1

En esta primera parte se realizan los pasos básicos para comenzar a analizar una base de datos. Es un analisis inicial donde se visualiza el contenido de los datos disponibles y se obtienen los datos descriptivos básicos para comprender mejor la información de vuelos. En los datos descriptivos podemos encontrar la media, el mínimo, máximo, entre otros, de las diferentes variables con las que cuenta la base de datos. En la problemática se nos pide encontrar la media de las millas recorridas, utilizando summary nos arroja un resultado de 1040 millas recorridas como media.

En el siguiente punto se utilizaron diferentes criterios para filtrar las aerolíneas que han recorrido una distancia mayor a la media. Para esto, primero seleccionamos las variables con la función select en donde se obtenía la aerolínea, la distancia, el origen y el destino. Posteriormente con la función filter, se filtraron las aerolíneas con una media superior a las 1040 millas recorridas, para después ordenarlas en formato descendente.

Por último, se nos pide obtener la suma y la media de las distancias recorridas, así como eliminar los NA’S, utilizando las funciones group_by y summarize, se obtuvo la distancia en suma y en promedio; como paso final ordenamos esto, nuevamente, en formato descendente.

6. Identificar aerolíneas líderes en los aeropuertos

#En esta parte se identifica si las aerolíneas líderes son las mismas en los tres aeropuertos cuyo origen es Nueva York ya sea el John F. Kennedy (JFK), el de LaGuardia (LGA) o el de Newark Liberty (EWR). Se genera un dataframe para cada aeropuerto.

Aeropuerto_JFK = Descendente %>% filter(origin == "JFK")  %>% arrange(carrier, desc(distancesuma))
Aeropuerto_LGA = Descendente %>% filter(origin == "LGA")  %>% arrange(carrier, desc(distancesuma))
Aeropuerto_EWR = Descendente %>% filter(origin == "EWR")  %>% arrange(carrier, desc(distancesuma))

7. Conclusión: Parte 1

Dando cierre a la parte 1 de la evidencia, se identificó cuales eran las aerolíneas líderes en los tres aeropuertos de Nueva York creando un dataframe por cada aeropuerto. En el caso del aeropuerto Newark Liberty (EWR), la aerolínea con mayor distancia recorrida es United Airlines (UA), con un total del 1,811,495 millas recorridas. Para el aeropuerto de LaGuardia (LGA) sería American Airlines (AA) con una suma de 6,717,204 millas recorridas. Por último, en el aeropuerto de John F. Kennedy (JFK), de igual manera el primer puesto lo obtiene American Airlines con un total de 7,962,075 millas recorridas.

En conclusión, se realizó una exploración inicial, obteniendo datos descriptivos como la media de millas recorridas, revelando un promedio de 1040 millas. Luego, se aplicaron criterios para identificar aerolíneas que operan vuelos de larga distancia, resultando en la suma y media de las distancias recorridas, proporcionando una visión clara de los patrones de vuelo y distancias. Además, se examina si las aerolíneas líderes son consistentes en los aeropuertos de Nueva York (JFK, LGA y EWR), en donde se destaca que American Airlines obtiene el primer puesto en dos de los tres aeropuertos existentes.

Evidencia: Parte 2

1. Consulta del dataframe

#Al consultar/llamar el DataFrame nos permite visualizar la base de datos *flights*.
view(flights)

2. Información de cada vuelo

#Se necesita saber de cada vuelo, la aerolínea, el aeropuerto de origen y el aeropuerto destino
vuelos <- flights %>% select(carrier, origin, dest)

#De la consulta anterior se requiere saber el nombre de la aerolínea
aerolínea <- vuelos %>% left_join (airlines, by = "carrier")

3. Cantidad de vuelos por destino

#De la consulta anterior se requiere saber el nombre de la aerolínea 

summary_delay <- df %>%
  group_by(dest, name) %>%
  summarise(avg_delay = mean(dep_delay, na.rm = TRUE),
            total_flights = n(),
            total_delayed_flights = sum(dep_delay > 0, na.rm = TRUE),
            perc_delayed_flights = total_delayed_flights / total_flights * 100)
## `summarise()` has grouped output by 'dest'. You can override using the
## `.groups` argument.

4. Aerolíneas y Destinos: Mañana, Tarde, Noche y Madrugada

#Se necesita conocer las aerolíneas (clave y nombre) y destinos que vuelan por la Mañana: de 6 a 12, Tarde: de 12 a 19 , Noche: de 19 a 24 y Madrugada de 24 a 6.

turno_carrier <- flights %>% select (carrier, dest, sched_dep_time) %>% left_join (airlines, by = "carrier")

turno_MTNM<- mutate(turno_carrier, clas_horario = ifelse(sched_dep_time %in% 600:1159,"Mañana",ifelse(sched_dep_time %in% 1200:1859,"Tarde",ifelse(sched_dep_time %in% 1900:2400,"Noche", "Madrugada"))))

5. Cantidad de vuelos: Mañana, Tarde y Noche

#Se presenta la cantidad de vuelos por aerolínea y destino que hay en cada turno, ya sea en la mañana, tarde, noche o madrugada.

cantidad_turno_MTNM <- turno_MTNM %>% group_by(carrier, dest, clas_horario) %>% count()

6. Destinos a los que vuela American Airlines en Madrugada

AA_destinos_mad <- turno_MTNM %>% select(carrier,name, dest,clas_horario) %>% filter(carrier == "AA" & clas_horario == "Madrugada") %>% group_by(carrier,name, dest,clas_horario)

7. Aviones que utiliza American Airlines

#Se presenta la aerolínea, tipo, motor, número de asientos y la cantidad de vuelos que se han realizado con cada uno de los aviones.
AA_aviones <- flights %>% left_join(planes, by = "tailnum") %>% select(carrier, type, engine, seats) %>% filter(carrier == "AA", !is.na(type)) %>% group_by(carrier,type,engine,seats) %>% count()

8. Interpretaciones: Parte 2

En esta segunda parte se comienza visualizando la base de datos flights y la obtención de información de cada vuelo, en este caso, la aerolínea, el aeropuerto de origen y el de destino. Con esto se pudo obtener la cantidad de vuelos por destino y el promedio de retraso que tiene cada uno de ellos, además de mencionar que aerolínea maneja cada destino. Por ejemplo, el destino con mayor cantidad de vuelos es Atlanta (ATL) con un total de 10,571 vuelos, con la aerolínea Delta Air Lines Inc. Por otra parte, hay un total de 17 destinos con la menor cantidad de vuelos, o sea 1 vuelo solamente hacia cada uno de esos 17 destinos, es por eso que en este caso las aerolíneas correspondientes varían.

Continuando con el análisis, se obtiene la clave y el nombre de la aerolínea y los diferentes destinos que se operan en los turnos de mañana, tarde, noche y madrugada. Con esto se obtuvo un total de 336,776 vuelos con las 5 variables a analizar: carrier, dest, sched_dep_time, name y clas_horario. Después se presenta la cantidad de vuelos por aerolínea y destino que hay en cada turno, se destaca que la aerolínea Delta (DL) con destino a Atlanta (ATL) tiene la mayor cantidad de vuelos en un horario de tarde con un total de 4967 vuelos. De nuevo, los de menor cantidad varían, ya que existen varias aerolíneas con un solo vuelo, a un solo destino y en un solo horario.

Por último, para especificar más el caso, nos enfocamos completamente en American Airlines y se encontró que dicha aerolínea tuvo un total de 365 vuelos de madrugada a un único destino, en este caso al aeropuerto de Miami (MIA). Después se logró presentar los aviones que utiliza American Airlines, por ejemplo el avión con mayor cantidad de asientos, con un total de 330, es un Fixed wing multi engine con un motor de Turbo-fan, por otra parte el avión con menor cantidad de asientos, con un total de 2, es un Fixed wing single engine con un motor de Reciprocating.

9. Visualización de Datos

Visualizaciones de la aerolínea American Airlines para los ejecutivos con las siguientes características. Dentro de las aerolíneas el retraso tanto en la hora de partida como en la hora de llegada a su destino van generando indicadores negativos.

Vuelos con retraso en ida y regreso

#Vuelos de American Airlines que si tienen retraso en la partida también tienen retraso en la hora de llegada.

vuelos_aa <- flights %>% filter(carrier == "AA")
retrasopartida <- mutate(vuelos_aa, dep_delay = dep_time - sched_dep_time)
retrasollegada <- mutate(vuelos_aa, arr_delay = arr_time - sched_arr_time)
partidaAAretrasos <- filter(retrasollegada, dep_delay > 0)
llegadaAAretrasos <- filter(retrasollegada, arr_delay > 0)
AAretrasos_lp <- intersect(partidaAAretrasos, llegadaAAretrasos)
ggplot(AAretrasos_lp, aes(x = dep_delay, y = arr_delay)) +
  geom_point() +
  labs(x = "Retraso en la partida)", y = "Retraso en la llegada") +
  theme_void()

Tendencia de la temperatura

#Tendencia de la temperatura durante los primeros 15 días del mes de Enero en los vuelos que parten del aeropuerto “Newark, EWR”, se utiliza una gráfica de línea.

EWRenero15 <- weather %>% filter(origin == "EWR", month == 1, day <= 15)
EWRenero15Temp <- select(EWRenero15, day, temp)

EWRenero15TempProm <- EWRenero15Temp %>% group_by(day) %>% summarise(promediotemp = mean(temp, na.rm=TRUE))

ggplot(EWRenero15TempProm, aes(x = day, y = promediotemp)) +
  geom_line() +
  labs(x = "Dia", y = "Temperatura (°C)") +
  theme_void()

Temperatura más frecuente

#Visualiza la temperatura más frecuente en los primeros 15 días del mes de Enero, utilizar un histrograma.
datos_enero <- df %>%
  filter(month.x == 1, day.x <= 15)

# Convertir a celsius
datos_enero_celsius <- mutate(datos_enero, celsius=(temp-32)*(5/9))


# Crear el histograma de temperatura
ggplot(datos_enero, aes(x = temp)) +
  geom_histogram(binwidth = 5, color = "white", fill = "purple") +
  labs(title = "Histograma de Temperatura en los Primeros 15 Dias de Enero",
       x = "Temperatura", y = "Frecuencia") +
  theme_minimal()
## Warning: Removed 52 rows containing non-finite outside the scale range
## (`stat_bin()`).

Facets

#Utiliza Facets para observar cómo varía la temperatura en cada mes en él histograma del punto anterior

datos <- df %>%
  select(month.x, temp)

datos$temp <- (datos$temp - 32) * 5/9

ggplot(datos, aes(x = temp)) +
  geom_histogram(binwidth = 3, color = "white", fill = "skyblue") +
  facet_wrap(~month.x, nrow = 3) + # Facetar por mes, con 3 paneles por fila
  labs(title = "Histograma de Temperatura por Mes",
       x = "Temperatura", y = "Frecuencia") +
  theme_minimal()
## Warning: Removed 1573 rows containing non-finite outside the scale range
## (`stat_bin()`).

Vuelos que salieron de Nueva York en el 2013

#Se presentan el número de vuelos que salieron de Nueva York en 2013 por aerolínea y con las 10 aerolínes con más vuelos se realiza una gráfica de barras.
vuelos_cantidad2 <- flights %>% select (carrier, dest) %>% count(carrier)
vuelos_orden <- arrange(vuelos_cantidad2, desc(n))
head(vuelos_orden, 10)
## # A tibble: 10 × 2
##    carrier     n
##    <chr>   <int>
##  1 UA      58665
##  2 B6      54635
##  3 EV      54173
##  4 DL      48110
##  5 AA      32729
##  6 MQ      26397
##  7 US      20536
##  8 9E      18460
##  9 WN      12275
## 10 VX       5162
grafico_barras <- ggplot(head(vuelos_orden, 10), aes(x = carrier, y = n)) +
  geom_bar(stat = "identity") +
  labs(x = "Aerolinea", y = "Cantidad de Vuelos")
grafico_barras

Grafica de pie

grafico_pastel <- grafico_barras +
  coord_polar("y", start = 0)
grafico_pastel

#### Interpretaciones: Visualización de Datos Para la visualización de datos, primero se obtuvieron los vuelos de American Airlines que si tienen retraso en la partida, también tienen retraso en la hora de llegada, para esto se implementó un diagrama de dispersión, el cual nos muestra la relación entre el retraso de partida y el retraso en la llegada. Después se obtuvo la tendencia en temperatura durante los primeros 15 días del mes de Enero en los vuelos que parten del aeropuerto “Newark, EWR”, para esto se utiliza una gráfica de línea.

En la siguiente visualización se obtiene la temperatura más frecuente en los primeros 15 días del mes de Enero, pero ahora utilizando un histograma, en esta parte utilizamos la conversión de farenheit a celsius y a simple vista se podría destacar que la temperatura que más se repite se encuentra entre los 40 y 50 grados centígrados, nuestra estimación personal son 45°C con una repetición cerca de 4000 vuelos.

En el siguiente análisis se utiliza facets para observar cómo varía la temperatura en cada mes en él histograma del punto anterior, de igual manera, en esta parte utilizamos la conversión de farenheit a celsius, como resultado se obtuvo un histograma de temperatura por mes.

Continuando, se presentan el número de vuelos que salieron de Nueva York en 2013 por aerolínea, después se obtiene las 10 aerolíneas con más vuelos y se realiza una gráfica de barras con ellas. Se destaca que United Airlines (UA) se encuentra en el primer puesto con un total de 58,665 vuelos, a esta le sigue JetBlue Airways (B6) con un total de 54,635 vuelos. En el tercer puesto se encuentra ExpressJet Airlines Inc. con un total de 54,173 vuelos. En el cuarto puesto Delta Air Lines Inc. con un total de 48,110 vuelos. En el quinto puesto se encuentra presente American Airlines con un total de 32,729 vuelos. En el puesto número seis, se encuentra Envoy Air (MQ) con un total de 26,397 vuelos. En séptimo lugar, US Airways Inc. con un total de 20,536 vuelos. Para el octavo puesto se encuentra Endeavor Air Inc. (9E) con un total de 18,460 vuelos. En el penúltimo puesto, se integra Southwest Airlines Co. con un total de 12,275 vuelos. Por último lugar se encuentra Virgin America con un total de 5162 vuelos. Para poder representar todos estos números de vuelos por aerolíneas, se implementó una gráfica de barras, haciendo que sea más atractivo la manera de visualizar el resultado. De igual manera, se realiza un grafico de pie, con los mismos datos del Top 10 de aerolíneas con más vuelos.

Relación Flights and Airports

#Relaciona el data frame flights con el data frame airports a través del campo destino ¿cómo lograr estas relaciones?
df <- merge(flights,airlines, by="carrier")
df <- left_join(df,planes, by="tailnum")
df <- left_join(df,weather, by=c("origin","time_hour"))

#Estas relaciones se logran a través del uso de funciones como merge y left_join,que permiten encontra las relaciones entre los diferentes data frames. Este paso se realizó al inico del programa para el desarrollo de los otros puntos de análisis.

Visualizaciones Flights and Airports

Visualizaciones Flights 1: Gráfico de Barras

Cantidad de Vuelos por Aerolínea

ggplot(data = vuelos_cantidad2, aes(x = carrier, y = n)) +
  geom_bar(stat = "identity") +
  labs(title = "Cantidad de Vuelos por Aerolinea",
       x = "Aerolinea",
       y = "Cantidad de Vuelos") +
  theme_minimal()

#### Visualizaciones Flights 2: Gráfico de Pastel Proporción de vuelos por aerolínea

ggplot(data = vuelos_cantidad2, aes(x = "", y = n, fill = carrier)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y") +
  labs(title = "Proporcion de Vuelos por Aerolinea",
       x = NULL,
       y = NULL) +
  theme_void()

#### Visualizaciones Flights 3: Gráfico de Barras Número de vuelos por mes con y sin retraso

flights_filtered <- flights %>%
  mutate(flights = ifelse(dep_delay > 0, "Delayed", "Not Delayed")) %>% 
  group_by(month, flights) %>%
  summarise(count = n()) %>%
  mutate(percent = count / sum(count) * 100)
## `summarise()` has grouped output by 'month'. You can override using the
## `.groups` argument.
ggplot(flights_filtered, aes(x = factor(month), y = count, fill = flights)) +
  geom_bar(stat = "identity", position = "stack") + 
  scale_fill_manual(values = c("seashell2", "rosybrown2")) +
  labs(title = "Número de vuelos por mes con y sin retraso",
       x = "Mes",
       y = "Número de vuelos",
       fill = "Retraso") +
  theme_minimal()

Visualizaciones Flights 4: Gráfico de Barras

Retrasos en la partida

ggplot(flights, aes(x = dep_delay)) + geom_bar() + labs(title = "Retrasos en la Partida")
## Warning: Removed 8255 rows containing non-finite outside the scale range
## (`stat_count()`).

#### Interpretaciones: Visualizaciones Flights En esta parte se realiza un mayor enfoque en las visualizaciones de la base de datos flights, para esto optamos por gráficos de barras y de pastel. La primera visualización que se presenta es la cantidad de vuelos por Aerolínea, muy similar a la del Top 10 de aerolíneas con más vuelos, sin embargo en esta gráfica de barras si se presentan las 16 aerolíneas participantes en los aeropuertos de Nueva York.

Continuamos con un gráfico de pastel, el cuál en un formato atractivo muestra la proporción de vuelos por aerolínea, que a simple vista se destacan 5 principales: American Airlines Inc. (AA), United Air Lines Inc. (UA), Delta Air Lines Inc. (DL), ExpressJet Airlines Inc (EV) y JetBlue Airways (B6).

En el tercer gráfico se presenta el número de vuelos por mes con y sin retraso, esto por medio de una gráfica de barras, se destaca que la mayoría de los vuelos, en todos los meses, no se retrasan. Pero por ejemplo, en el mes número 7, o sea Julio, es de los más bajos con vuelos no retrasados y de los más altos con vuelos con retraso, esto sin duda nos ayuda a confirmar una de nuestras conclusiones de por qué los vuelos se retrasan, aquí hay un claro ejemplo, que la temporada alta de vacaciones de verano, es un factor para los retrasos en los vuelos. Por último agregamos una cuarta visualización, en ella se presenta los retrasos en la partida.

Visualizaciones Airports 1: Gráfico de Dispersión

Relación entre coordenadas de aeropuertos

ggplot(airports, aes(x = lon, y = lat)) + geom_point() + labs(title = "Relacion entre Coordenadas de Aeropuertos")

#### Visualizaciones Airports 2: Gráfico de Barras Aquí falta el tercer visualización

top_10_airports <- head(airports[order(-airports$alt), ], 10)

ggplot(top_10_airports, aes(x = reorder(name, -alt), y = alt, fill = name)) +
  geom_bar(stat = "identity", size = 2) +
  labs(title = "Top 10 Aeropuertos Más Altos",
       x = "Aeropuerto",
       y = "Altura") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 3))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Interpretaciones: Visualizaciones Airports

En las visualizaciones de Airports se utilizaron un gráfico de dispersión y un gráfico de barras. En el primero se presenta la relación existente entre las coordenadas de los aeropuertos, si se mantemos un ataención, se puede destacar que en las coordenadas se presenta una parte de Estados Unidos y la otra parte sería de Alaska. En la segunda visualización, con una gráfica de barras, se obtiene el Top 10 de aeropuertos más altos, en el primer puesto se encuentra Telluride, en el top 5 se encuentra el Bryce Canyon y en el top 10 Mammoth Yosemit Airport.

10. Conclusión: Parte 2

En esta segunda parte se pudieron poner en práctica diferentes habilidades de programación, principalmente al momento de realizar gráficos y analizarlos. Se logró obtener la información de cada vuelo, de los destinos más concurridos y hasta la divisón de vuelos en los diferentes turnos de oferta de vuelos. Se generó un enfoque en American Airlines y con las visualizaciones de la última parte de la evidencia, se logró realizar un análisis más profundo en los retrasos, encontrar las relaciones entre la base de datos flights y la de airports y cómo es que cada una de ellas nos sirve para encontrar diferentes variables para el desarrollo de análisis de retrasos. En las interpretaciones anteriores, se explica de manera más detallada, los resultados obtenidos, pero sin duda, el uso de visualizaciones fue clave para poder entender mejor como funcionan el tema de los vuelos, aerolíneas, destinos, entre otros.

¿Por qué se retrasan los vuelos en Nueva York?

#Atrasos de origen, carrier y mes.
atraso_por_origen <- flights %>% group_by(origin) %>% summarise(tiempo_atraso_promedio = mean(dep_delay, na.rm = TRUE))

atraso_por_carrier <- flights %>% group_by(carrier) %>% summarise(tiempo_atraso_promedio = mean(dep_delay, na.rm = TRUE))

atraso_por_mes <- flights %>% group_by(month) %>% summarise(tiempo_atraso_promedio = mean(dep_delay, na.rm = TRUE))

# Resumen por origen
summary_by_origin <- flights %>% group_by(origin) %>% summarize(Media_Dep_Delay = mean(dep_delay, na.rm = TRUE),
Mediana_Dep_Delay = median(dep_delay, na.rm = TRUE), Min_Dep_Delay = min(dep_delay, na.rm = TRUE), Max_Dep_Delay = max(dep_delay, na.rm = TRUE))

# Resumen por aerolínea
summary_by_carrier <- flights %>% group_by(carrier) %>% summarize(Media_Dep_Delay = mean(dep_delay, na.rm = TRUE),
    Mediana_Dep_Delay = median(dep_delay, na.rm = TRUE),
    Min_Dep_Delay = min(dep_delay, na.rm = TRUE),
    Max_Dep_Delay = max(dep_delay, na.rm = TRUE))

# Calcular resumen estadístico por destino
summary_by_dest <- flights %>%
  group_by(dest) %>%
  summarize(Media_Dep_Delay = mean(dep_delay, na.rm = TRUE),
    Mediana_Dep_Delay = median(dep_delay, na.rm = TRUE),
    Min_Dep_Delay = min(dep_delay, na.rm = TRUE),
    Max_Dep_Delay = max(dep_delay, na.rm = TRUE))
## Warning: There were 2 warnings in `summarize()`.
## The first warning was:
## ℹ In argument: `Min_Dep_Delay = min(dep_delay, na.rm = TRUE)`.
## ℹ In group 52: `dest = "LGA"`.
## Caused by warning in `min()`:
## ! no non-missing arguments to min; returning Inf
## ℹ Run `dplyr::last_dplyr_warnings()` to see the 1 remaining warning.
# Crear un conjunto de datos combinando las variables de interés
modelo_data <- flights %>%
  select(dep_delay, carrier, origin, month)

# Ajustar el modelo de regresión lineal
modelo <- lm(dep_delay ~ carrier + origin + month, data = modelo_data)

# Resumen del modelo
summary(modelo)
## 
## Call:
## lm(formula = dep_delay ~ carrier + origin + month, data = modelo_data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
##  -54.81  -17.38  -12.48   -1.76 1294.85 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  18.80974    0.38810  48.466  < 2e-16 ***
## carrierAA    -7.79414    0.38286 -20.358  < 2e-16 ***
## carrierAS   -11.48010    1.54124  -7.449 9.46e-14 ***
## carrierB6    -3.77186    0.34822 -10.832  < 2e-16 ***
## carrierDL    -7.07511    0.36085 -19.607  < 2e-16 ***
## carrierEV     2.97023    0.39186   7.580 3.47e-14 ***
## carrierF9     4.51664    1.56852   2.880 0.003983 ** 
## carrierFL     2.89628    0.78763   3.677 0.000236 ***
## carrierHA   -12.03652    2.18212  -5.516 3.47e-08 ***
## carrierMQ    -5.61979    0.40732 -13.797  < 2e-16 ***
## carrierOO    -2.92665    7.42779  -0.394 0.693571    
## carrierUA    -4.90557    0.38340 -12.795  < 2e-16 ***
## carrierUS   -12.43204    0.43216 -28.767  < 2e-16 ***
## carrierVX    -4.02855    0.63644  -6.330 2.46e-10 ***
## carrierWN     1.25021    0.49683   2.516 0.011858 *  
## carrierYV     3.37925    1.74606   1.935 0.052947 .  
## originJFK    -0.38387    0.23214  -1.654 0.098213 .  
## originLGA    -1.54708    0.21363  -7.242 4.44e-13 ***
## month        -0.23726    0.02045 -11.604  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 39.96 on 328502 degrees of freedom
##   (8255 observations deleted due to missingness)
## Multiple R-squared:  0.01256,    Adjusted R-squared:  0.01251 
## F-statistic: 232.2 on 18 and 328502 DF,  p-value: < 2.2e-16
ggplot(modelo_data, aes(x = as.factor(month), y = dep_delay, group = 1)) +
  geom_line(stat = "summary", fun = "mean", linetype = "solid", size = 1) +
  labs(title = "Promedio del Retraso de Salida en función del Mes",
       x = "Mes",
       y = "Promedio de Retraso de Salida")
## Warning: Removed 8255 rows containing non-finite outside the scale range
## (`stat_summary()`).

df_combinado <- bdgrande2 %>%
  merge(weather) 

df_combinado <- as.data.frame(df_combinado)
regresion <- lm(dep_delay ~ tailnum + carrier + year.x + month + day + dep_time + arr_delay + flight + origin + dest + air_time + distance  + minute  + name + year.y + type + model + speed + engine   + temp + dewp + humid + wind_dir + wind_speed + precip + pressure + visib, data=df_combinado)
summary(regresion)
## 
## Call:
## lm(formula = dep_delay ~ tailnum + carrier + year.x + month + 
##     day + dep_time + arr_delay + flight + origin + dest + air_time + 
##     distance + minute + name + year.y + type + model + speed + 
##     engine + temp + dewp + humid + wind_dir + wind_speed + precip + 
##     pressure + visib, data = df_combinado)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -92.604  -6.806   0.925   7.482  48.286 
## 
## Coefficients: (28 not defined because of singularities)
##                                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                   1.222e+03  4.863e+02   2.513 0.012181 *  
## tailnumN202AA                 3.793e-01  3.278e+00   0.116 0.907900    
## tailnumN350AA                 1.254e+03  5.471e+02   2.292 0.022183 *  
## tailnumN364AA                 1.264e+03  5.471e+02   2.310 0.021168 *  
## tailnumN378AA                 1.262e+03  5.471e+02   2.307 0.021315 *  
## tailnumN381AA                 1.258e+03  5.471e+02   2.300 0.021736 *  
## tailnumN425AA                 1.790e+00  3.046e+00   0.588 0.556961    
## tailnumN508AA                 9.769e-01  3.091e+00   0.316 0.752098    
## tailnumN519MQ                -8.513e+00  5.698e+00  -1.494 0.135593    
## tailnumN525AA                -2.005e+00  3.008e+00  -0.666 0.505336    
## tailnumN545AA                 1.375e+00  3.076e+00   0.447 0.654995    
## tailnumN567AA                 5.660e-01  2.741e+00   0.206 0.836484    
## tailnumN600TR                 8.454e-01  1.231e+01   0.069 0.945266    
## tailnumN615AA                 1.251e+03  5.478e+02   2.284 0.022644 *  
## tailnumN621AA                 1.256e+03  5.477e+02   2.294 0.022073 *  
## tailnumN675MC                -6.093e+00  1.095e+01  -0.556 0.578180    
## tailnumN737MQ                -1.334e+01  6.480e+00  -2.058 0.039892 *  
## tailnumN762NC                 6.355e-01  8.416e+00   0.076 0.939825    
## tailnumN767NC                 3.382e+00  8.085e+00   0.418 0.675860    
## tailnumN774NC                 2.663e+00  9.732e+00   0.274 0.784437    
## tailnumN777NC                -2.218e+00  9.227e+00  -0.240 0.810081    
## tailnumN779NC                 2.675e-01  8.636e+00   0.031 0.975299    
## tailnumN782NC                -4.396e+00  8.239e+00  -0.534 0.593792    
## carrierDL                            NA         NA      NA       NA    
## carrierMQ                            NA         NA      NA       NA    
## year.x                               NA         NA      NA       NA    
## month                        -7.767e-01  2.052e-01  -3.786 0.000166 ***
## day                          -1.052e-01  5.701e-02  -1.845 0.065398 .  
## dep_time                      4.866e-03  1.266e-03   3.844 0.000132 ***
## arr_delay                     8.416e-01  1.313e-02  64.095  < 2e-16 ***
## flight                        1.752e-04  1.306e-03   0.134 0.893279    
## originJFK                     1.702e+01  8.600e+00   1.979 0.048133 *  
## originLGA                     2.462e+01  1.066e+01   2.309 0.021212 *  
## destBNA                       4.149e+00  3.468e+00   1.197 0.231869    
## destCLE                      -5.136e+02  2.223e+02  -2.310 0.021161 *  
## destCLT                      -3.256e+02  1.414e+02  -2.302 0.021591 *  
## destCMH                      -4.251e+02  1.829e+02  -2.324 0.020381 *  
## destCRW                      -4.811e+02  2.060e+02  -2.336 0.019766 *  
## destDCA                      -8.213e+02  3.530e+02  -2.327 0.020250 *  
## destDFW                       9.620e+02  4.078e+02   2.359 0.018595 *  
## destDTW                      -3.854e+02  1.682e+02  -2.291 0.022233 *  
## destEGE                       2.635e+02  9.702e+01   2.716 0.006755 ** 
## destLAS                       1.028e+03  4.222e+02   2.435 0.015139 *  
## destMCO                      -9.695e+02  4.246e+02  -2.284 0.022678 *  
## destMIA                      -7.483e+02  3.298e+02  -2.269 0.023563 *  
## destMSP                       3.958e+02  1.678e+02   2.359 0.018601 *  
## destORD                      -3.511e+01  1.823e+01  -1.926 0.054447 .  
## destRDU                      -5.011e+02  2.145e+02  -2.336 0.019756 *  
## destSAN                       1.320e+03  5.514e+02   2.395 0.016877 *  
## destSFO                       1.522e+03  6.424e+02   2.369 0.018083 *  
## destSJU                              NA         NA      NA       NA    
## destSTL                       1.884e+02  8.334e+01   2.260 0.024090 *  
## destXNA                       5.998e+02  2.508e+02   2.392 0.017016 *  
## air_time                     -8.760e-01  5.292e-02 -16.553  < 2e-16 ***
## distance                     -1.410e+00  6.492e-01  -2.171 0.030229 *  
## minute                       -3.598e-02  2.902e-02  -1.240 0.215533    
## nameDelta Air Lines Inc.             NA         NA      NA       NA    
## nameEnvoy Air                        NA         NA      NA       NA    
## year.y                               NA         NA      NA       NA    
## typeFixed wing single engine         NA         NA      NA       NA    
## typeRotorcraft                       NA         NA      NA       NA    
## model172E                            NA         NA      NA       NA    
## model172M                            NA         NA      NA       NA    
## model172N                            NA         NA      NA       NA    
## model206B                            NA         NA      NA       NA    
## model310Q                            NA         NA      NA       NA    
## model421C                            NA         NA      NA       NA    
## model65-A90                          NA         NA      NA       NA    
## modelA185F                           NA         NA      NA       NA    
## modelDC-7BF                          NA         NA      NA       NA    
## modelDC-9-51                         NA         NA      NA       NA    
## modelOTTER DHC-3                     NA         NA      NA       NA    
## modelPA-28-180                       NA         NA      NA       NA    
## modelPA-31-350                       NA         NA      NA       NA    
## modelPA-32R-300                      NA         NA      NA       NA    
## speed                                NA         NA      NA       NA    
## engineReciprocating                  NA         NA      NA       NA    
## engineTurbo-jet                      NA         NA      NA       NA    
## engineTurbo-prop                     NA         NA      NA       NA    
## engineTurbo-shaft                    NA         NA      NA       NA    
## temp                          6.254e-02  3.224e-01   0.194 0.846215    
## dewp                         -2.769e-01  3.474e-01  -0.797 0.425728    
## humid                         7.996e-02  1.819e-01   0.440 0.660343    
## wind_dir                      1.795e-03  5.273e-03   0.340 0.733660    
## wind_speed                   -2.425e-01  1.043e-01  -2.324 0.020386 *  
## precip                       -1.372e+01  5.567e+01  -0.246 0.805410    
## pressure                     -6.109e-02  7.786e-02  -0.785 0.432973    
## visib                         1.186e-01  4.541e-01   0.261 0.793995    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 13.58 on 742 degrees of freedom
##   (282028 observations deleted due to missingness)
## Multiple R-squared:  0.8754, Adjusted R-squared:  0.8655 
## F-statistic: 88.33 on 59 and 742 DF,  p-value: < 2.2e-16

Análisis Retrasos

Gráfico - Atraso promedio por origen

Gráfico - Atraso promedio por origen

ggplot(atraso_por_origen, aes(x=origin, y=tiempo_atraso_promedio)) +
  geom_bar(stat="identity", fill="lightblue1") +
  theme_minimal() +
  labs(title="Atraso promedio por origen", x="Origen", y="Tiempo de atraso promedio")

Gráfico - Atraso promedio por carrier

Gráfico - Atraso promedio por carrier

ggplot(atraso_por_carrier, aes(x=carrier, y=tiempo_atraso_promedio)) +
  geom_bar(stat="identity", fill="cadetblue3") +
  theme_minimal() +
  labs(title="Atraso promedio por carrier", x="Carrier", y="Tiempo de atraso promedio")

Gráfico - Atraso promedio por mes

Gráfico - Atraso promedio por mes

ggplot(atraso_por_mes, aes(x=month, y=tiempo_atraso_promedio)) +
  geom_line(group=1, colour="darkslategray3") +
  theme_minimal() +
  labs(title="Atraso promedio por mes", x="Mes", y="Tiempo de atraso promedio")

Interpretaciones: Retrasos

Acercándonos más hacia el análisis final del por qué los vuelos se retrasan en los aeropuertos de Nueva York, se obtuvo el atraso en tiepo promedio por aerolínea, origen y mes. En la gráfica de barras se muestra el primer análisis de atraso promedio por origen, dando como resultado que el aeropuerto EWR es el que cuenta con un mayor atraso promedio, con un total del 15.11 minutos de atraso, a este le sigue JK con un total de 12.11 minutos de atraso, y con el menor promedio se encuentra LGA con un total de 10.35 mintos de atraso.

En la segunda gráfica de barras se presenta el atraso promedio por carrier, dando como resultados principales que Frontier Airlines Inc. (F9) es la aerolínea que cuenta con un mayor atraso promedio de de 20.22 minutos, en cambio la aerolínea con el menor atraso promedio es US Airways Inc. con un total de 3.78 minutos de atraso.

Para la tercera gráfica de línea, se presenta el atraso promedio por mes, en donde se destaca que el mes de Julio es el que cuenta con un mayor tiempo de atraso en promedio, con un total de 21.73 minutos. En segundo lugar se encuentra Junio, con un tiempo de atraso en promedio de 20.85 minutos, y en tercer lugar se encuentra diciembre, con un total de atraso promedio de 16.57 minutos. El atraso promedio en el mes, se puede deber al principal factor de temporadas altas vacacionales.

Retraso por tipo de avión

Retraso por tipo de avión

# Retraso por tipo de avión
retraso_por_avion <- flights %>%
  left_join(planes, by = "tailnum") %>%
  group_by(type) %>%
  summarize(avg_delay = mean(dep_delay, na.rm = TRUE))

# Gráfico de barras para retraso por tipo de avión
ggplot(retraso_por_avion, aes(x = type, y = avg_delay)) +
  geom_bar(stat = "identity", fill = "skyblue") +
  labs(title = "Retraso Promedio por Tipo de Avión",
       x = "Tipo de Avión",
       y = "Retraso Promedio") +
  theme_minimal()

Retraso por día de la semana

Retraso por día de la semana

# Retraso por día de la semana
retraso_por_dia_semana <- flights %>%
  mutate(weekday = weekdays(as.Date(paste(year, month, day, sep = "-")))) %>%
  group_by(weekday) %>%
  summarize(avg_delay = mean(dep_delay, na.rm = TRUE))

# Ordenar días de la semana
retraso_por_dia_semana$weekday <- factor(retraso_por_dia_semana$weekday, levels = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))

# Gráfico de barras para retraso por día de la semana
ggplot(retraso_por_dia_semana, aes(x = weekday, y = avg_delay)) +
  geom_bar(stat = "identity", fill = "blue") +
  labs(title = "Retraso Promedio por Dia de la Semana",
       x = "Dia de la Semana",
       y = "Retraso Promedio") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Retraso por hora del día

Retraso por hora del día

# Retraso por hora del día
flights$hour <- as.integer(flights$hour) 
mean_delay_per_hour <- aggregate(dep_delay ~ hour, flights, mean)
ggplot(data = mean_delay_per_hour, aes(x = hour, y = dep_delay)) +
  geom_bar(stat = "identity", fill = "skyblue") +
  labs(x = "Hora del día", y = "Retraso promedio (minutos)", 
       title = "Retraso promedio por hora del día") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

Interpretaciones: Retrasos

En el análisis anterior, ahora se toma en cuenta el retraso promedio por tipo de avión, el retraso por día de la semana, y retraso por hora del día.

El primer retraso analizado fue por el tipo de avión, el cual nos presenta que los tipos de aviones Rotorcraft son los que cuentan con un mayor atraso promedio, dando como resultado un total de 14.17 minutos de retraso. A este le sigue los tipos de aviones de Fixed wing multi engine con un total de 13.19 minutos de retraso. Por último el tipo de avión con menor cantidad de retraso promedio es el Fixed wing single engine con un total de 10.50 minutos. A pesar de que existen esos tres tipos de aviones, la gráfica también nos muestra los NA con un total de 9.5 minutos de atraso promedio.

En la segunda gráfica se presenta el atraso promedio por día de la semana, donde se destaca que los jueves son los días con mayor atraso promedio, con un total de 16.15 minutos. Por otra parte, el día con menor atraso promedio son los sábados, con un total de 7.65 minutos.

En la tercer gráfica se muestra el atraso promedio por hora del día, en la cuál es visible un crecimiento en retrasos entre los horarios de las 15:00 y 20:00 horas, después de esto disminuye para los vuelos de las 5:00 a 10:00 horas.

Análisis del Clima

Retraso promedio por humedad relativa

flights_weather<- merge(weather, flights)
flights_weather %>%
  group_by(humid) %>%
  summarise(delay = mean(dep_delay, na.rm = TRUE)) %>%
  ggplot(aes(x = humid, y = delay)) +
  labs(x = "Humedad relativa", y = "Retraso promedio (minutos)", fill = "Aeoropuerto") +
  ggtitle("Retraso promedio por humedad relativa") +
  geom_line() + geom_point()+ theme(plot.title= element_text(hjust=0.5))

### Retraso promedio por temperatura

flights_weather %>%
  group_by(temp) %>%
  summarise(delay = mean(dep_delay, na.rm = TRUE)) %>%
  ggplot(aes(x = temp, y = delay)) +
  labs(x = "Temperatura", y = "Retraso promedio (minutos)", fill = "Aeoropuerto") +
  ggtitle("Retraso promedio por Temperatura") +
  geom_point() +
  geom_smooth()+ theme(plot.title= element_text(hjust=0.5))
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

### Retraso promedio por velocidad del viento

flights_weather %>%
  group_by(wind_speed) %>%
  summarise(delay = mean(dep_delay, na.rm = TRUE)) %>%
  ggplot(aes(x = wind_speed, y = delay)) +
  labs(x = "Velocidad del Viento", y = "Retraso promedio (minutos)") +
  ggtitle("Retraso promedio por Velocidad del Viento") +
  geom_smooth()+ theme(plot.title= element_text(hjust=0.5))
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

### Retraso promedio por dirección del viento

flights_weather %>%
  group_by(wind_dir) %>%
  summarise(delay = mean(dep_delay, na.rm = TRUE)) %>%
  ggplot(aes(x = wind_dir, y = delay)) +
  labs(x = "Dirección del Viento", y = "Retraso promedio (minutos)") +
  ggtitle("Retraso promedio por Dirección del Viento") +
  geom_bar(stat = "identity") + 
  theme(plot.title=element_text(hjust=0.5))

Retraso promedio por visibilidad en el aire

flights_weather %>%
  group_by(visib) %>%
  summarise(delay = mean(dep_delay, na.rm = TRUE)) %>%
  ggplot(aes(x = visib, y = delay)) +
  labs(x = "Visibilidad", y = "Retraso promedio (minutos)") +
  ggtitle("Retraso promedio por Visibilidad en el aire") +
  geom_line() + 
  theme(plot.title=element_text(hjust=0.5))

Interpretaciones: Análisis del Clima

En el análisis del clima, primero se obtuvo el retraso promedio por humedad relativa, en donde muestra que hay atrasos de una mayor cantidad de tiempo entre el 75% y 100% de la humedad relativa. Después, se obtuvo el atraso promedio por la temperatura, en este gráfico se destaca que puede variar mucho la temperatura y el tiempo que se retrasa los vuelos.

El tercer análisis utiliza el retraso promedio por velocidad del viento, en donde si la velocidad se encuentra entre el 30 y 40, existe la probabilidad de que los atrasos sean mayores a los 20 minutos. Después se obtuvo el atraso promedio por dirección del viento, que gracias a la visualización de la gráfica de barras, si la dirección del viento se encuentra en un estimado entre 80 y 150, existe un atraso promedio mayor. Por último se obtuvo el atraso promedio por la visibilidad en el aire, en el que haciendo un estimado, si la visibilidad se encunetra entre 0.0 y 2.5, los vuelos tienden a tener un mayor atraso promedio, de alrededor de 30 a 50 minutos.

Conclusiones de retrasos

En esta actividad de manera grupal, determinamos el por qué se retrasan los vuelos en los aeropuertos de Nueva York. Se obtuvo información muy interesante a través de los diferentes análisis de las bases de datos.

En primera instancia se obtuvo el atraso por origen, en donde nos mostró el tiempo de atraso promedio en cada uno de los tres aeropuertos disponibles, dando como resultado que el aeropuerto con mayor atraso en promedio es el EWR. El siguiente análisis fue el atraso por Carrier, en donde se obtuvo el atraso promedio por aerolínea; 9E (Endevoir Air) obtuvo el mayor resultado en atraso promedio.

Despúes nos enfocamos más en el mes en el que había mayores retrasos, dando como resultado temporadas altas para viajar, por ejemplo en primer lugar del mes con mayor retraso se encontraba Julio, aproximadamente solo por un minuto mayor a Junio, y a este le seguía diciembre en el tercer puesto. Si tomamos en cuenta que muchas personas viajan en dichas temporados por el verano y las fiestas decembrinas, lo que ocasiona que haya mayor cantidad de personas en movilidad en aeropuertos, podría ser un importante factor del por qué los vuelos se retrasan más en dichas temporadas.

Realizamos un modelo del promedio del retraso de salida en función del mes, lo que nos muestra con mayor claridad, que las temporadas altas de viajes son un factor que influye en los retrasos generados en los aeropuertos de Nueva York.

Por último se realizaron los análisis del clima, considerando diferentes variables, ya sea la dirección de viento, su visibilidad, la humedad relativa y la temperatura, en los cuáles se nos muestra que sin duda son un factor importante a considerar dentro del por qué los vuelos se retrasan, este punto es explicado con mayor detenimiento en las interpretaciones anteriores.

Ejercicios de evidencia en clase

Extra 1. Consulta la estructura de “flights”

str(flights)
## tibble [336,776 × 19] (S3: tbl_df/tbl/data.frame)
##  $ year          : int [1:336776] 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month         : int [1:336776] 1 1 1 1 1 1 1 1 1 1 ...
##  $ day           : int [1:336776] 1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_time      : int [1:336776] 517 533 542 544 554 554 555 557 557 558 ...
##  $ sched_dep_time: int [1:336776] 515 529 540 545 600 558 600 600 600 600 ...
##  $ dep_delay     : num [1:336776] 2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_time      : int [1:336776] 830 850 923 1004 812 740 913 709 838 753 ...
##  $ sched_arr_time: int [1:336776] 819 830 850 1022 837 728 854 723 846 745 ...
##  $ arr_delay     : num [1:336776] 11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ carrier       : chr [1:336776] "UA" "UA" "AA" "B6" ...
##  $ flight        : int [1:336776] 1545 1714 1141 725 461 1696 507 5708 79 301 ...
##  $ tailnum       : chr [1:336776] "N14228" "N24211" "N619AA" "N804JB" ...
##  $ origin        : chr [1:336776] "EWR" "LGA" "JFK" "JFK" ...
##  $ dest          : chr [1:336776] "IAH" "IAH" "MIA" "BQN" ...
##  $ air_time      : num [1:336776] 227 227 160 183 116 150 158 53 140 138 ...
##  $ distance      : num [1:336776] 1400 1416 1089 1576 762 ...
##  $ hour          : int [1:336776] 5 5 5 5 6 5 6 6 6 6 ...
##  $ minute        : num [1:336776] 15 29 40 45 0 58 0 0 0 0 ...
##  $ time_hour     : POSIXct[1:336776], format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...
# int: entero (sin decimales)
# num: numérico (con decimales)
# chr: caractér (letras)
# Date: fecha (en R va año-mes-día)
# POSIXct: formato fecha y hora

Extra 2. ¿Cuál es la clase de “flights” y que significa?

class(flights)
## [1] "tbl_df"     "tbl"        "data.frame"
# Las 5 clases de objetos son:
# 1. numeric: Número real o decimales.
# 2. integer: Númweos enteros
# 3. complex: Números complejos
# 4. character: carácteres
# 5. logical: TRUE O FALSE

# Las 4 clases de objetos compuestos son:
# 1. list: lista
# 2. matrix: matriz
# 3. array: colección de objetos
# 4. data.frame: base de datos

Extra 3. ¿Cuántas columnas y renglones tiene “flights”? ¿Cuál es su dimensión?

# Número de columnas
ncol(flights)
## [1] 19
# Número de renglones
nrow(flights)
## [1] 336776
# Dimensión
dim(flights)
## [1] 336776     19

Extra 4. Muestra los primeros 6 renglones de “flights”. También los últimos 6.

head(flights)
## # A tibble: 6 × 19
##    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
## 1  2013     1     1      517            515         2      830            819
## 2  2013     1     1      533            529         4      850            830
## 3  2013     1     1      542            540         2      923            850
## 4  2013     1     1      544            545        -1     1004           1022
## 5  2013     1     1      554            600        -6      812            837
## 6  2013     1     1      554            558        -4      740            728
## # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## #   hour <int>, minute <dbl>, time_hour <dttm>
tail(flights)
## # A tibble: 6 × 19
##    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
## 1  2013     9    30       NA           1842        NA       NA           2019
## 2  2013     9    30       NA           1455        NA       NA           1634
## 3  2013     9    30       NA           2200        NA       NA           2312
## 4  2013     9    30       NA           1210        NA       NA           1330
## 5  2013     9    30       NA           1159        NA       NA           1344
## 6  2013     9    30       NA            840        NA       NA           1020
## # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## #   hour <int>, minute <dbl>, time_hour <dttm>
# Si quisieramos 7 renglones: head(flights,7)

Compromiso ético y ciudadano

El valor de la integridad, según las Naciones Unidas, viene de la práctica de ser una persona honesta, que se adhiere a sus valores y que la toma de decisiones es sistemáticamente positiva. La integridad es la forma de actuar de acuerdo a los principios, a diferencia de la honestidad que es el acto de ser veraz. (Naciones Unidas)
Por la parte del compromiso ético, según miembros de la Universitat de Barcelona, es la capacidad de actuar con las virtudes personales y profesionales que requiere el correcto ejerccio de una profesión, el desarrollo personal y la ciudadanía democrática, todo esto dentro de un contexto universitario. (Mauri-Álvarez, Margarita, et al)

Por último, el compromiso ciudadano lo podemos diferenciar de la participación ciudadana. El compromiso busca un diálogo activo entre la toma de decisiones y los ciudadanos.(Lodewijckx, Ilona) Tener un compromiso ético y ciudadano fue un punto clave para la elaboración de esta evidencia.

Reflexión Personal: Nancy Marroquín

  • Reflexión personal: El respeto y la honestidad forman parte de los valores que trato de representar en mi día a día. En cualquie tipo de proyecto en el que participo, busco que este se lleve a cabo de manera más tranparente, fomentando la comunicación y la escucha activa. En el mundo de los negocios fomentar estos valores tan importantes, son clave para el éxito de las empresas. El actua de manera honesta y con respeto hacia los demás, te permite tener un mejor desarrollo personal y profesional. Si nos enfocamos más, hacia la parte de análisis de datos y el uso de datos de las empresas, el repeto y la honestidad, no son los únicos valores que se promueven, sino que también la confianza, el compromiso y la integridad. Al trabajar con información de la empresas es necesario tener mucho cuidado cómo es que se utiliza y cuál es su propósito. De esta manera es posible generar una mejor toma de decisiones repecto al uso y desarrollo de dichos datos.

Reflexión Personal: Kevin Meza

  • Reflexión personal: La responsabilidad, es un valor el cual va de la mano con transparencia e integridad. El serlo al llevar a cabo en el uso de datos, es asumir las consecuencias de las acciones tomadas y garantizar que se cumplan los principio éticos y legales del momento. Otro punto relevante a considerar es la ética en la toma de decisiones basadas en datos. Es fundamental que las decisiones empresariales se tomen considerando no solo la información disponible, sino también los valores éticos que guían el comportamiento de quienes gestionan dichos datos.
    Asimismo, se puede destacar la importancia de la confianza como resultado de la combinación de estos valores éticos. La confianza tanto interna como externa se construye a partir de la coherencia entre lo que se dice y lo que se hace en relación con los datos empresariales.

Reflexión Personal: Adrián Morales

  • Reflexión personal: Desde mi punto de vista, considero que la integridad es fundamental para la honestidad y la coherencia en todos los aspectos de la vida. En el campo de la inteligencia de negocios, donde me desempeño como estudiante, el código ético de nuestra disciplina actúa como el guía que orienta mi comportamiento profesional. Este código no solamente establece la obligación de manejar la información de forma precisa y confidencial, sino que también resalta la importancia de utilizar el conocimiento adquirido de manera equitativa y clara. Tener acceso a la información de una empresa conlleva una gran responsabilidad de manejarla con cuidado, garantizando la confidencialidad y evitando conflictos de interés, aplicando análisis éticos que beneficie a la organización y a la sociedad en general. Al final del día, mantener la integridad en la gestión de datos de la empresa no solo muestra mi dedicación a la ética laboral, sino que también aumenta la confianza y credibilidad en el campo de la inteligencia empresarial

Reflexión Personal: Karla López

  • Reflexión personal: La integridad se puede definir como la calidad de ser honesto, ético y moral en todas las acciones y decisiones. En el contexto de mi disciplina académica, la integridad es fundamental para mis trabajos individuales y grupales, ya que representa la relación de mis acciones, valores, principios y resultados. Asimismo, en mi disciplina personal, me impulsa a ser honesta, transparente y responsable en mis actividades, asegurando que mis acciones siempre reflejen mis valores morales y éticos. Por otro lado, en el ámbito profesional, en una empresa no solo se busca contar con un compromiso con la información proporcionada sino también con el equipo y las herramientas, ya que es fundamental mantener una conducta ética tanto en las relaciones con los compañeros como en el uso de los recursos disponibles para el desarrollo y el éxito de la empresa.

Conclusión General

Tras examinar el modelo de regresión lineal, se pudo observar que el 88.68% de la variabilidad en la variable dependiente (retraso en los vuelos) se puede explicar utilizando las variables independientes. Las cuales se identificaron ciertas variables que muestran una significancia estadística, con valores de p menores a 0.001, lo que demuestra que tienen un impacto significativo, lo que significa que tienen una relación directa y lógica con el retraso de los vuelos, las cuales fueron:

dep_time: Razones por las cuales el tiempo de salida puede afectar a los vuelos pueden ser problemas de gestión por parte de las aerolíneas, como dificultades operativas relacionadas con el equipo o el personal, o problemas en el aeropuerto.(***)

arr_delay: Relación significativa en la conexión de las llegadas tardías con las salidas. (***)

air_time: Al estar más expuestos en el aire, los vuelos pueden sufrir problemas climáticos, escalas, procesos de seguridad, entre otros. (***)

dest: Los vuelos pueden verse afectados por algunos destinos donde hay tráfico aéreo, condiciones meteorológicas locales o congestión del aeropuerto de destino, que sucede frecuentemente en ciudades grandes.(***)

wind_speed: Relación entre la velocidad del viento y los retrasos en la salida de los vuelos. Puede ser ocasionado por operación en el vuelo o de seguridad, procedimientos de seguridad, entre otros. (**)

wind_dir: Relación entre la dirección del viento y los retrasos, que pueden ser debidos por las condiciones de vuelo, procedimientos de despegue, entre otros. (**)

Por lo cual, sugiere que una variedad de variables, tanto relacionadas con la operación de las aerolíneas como con las condiciones meteorológicas, pueden contribuir a los retrasos en la salida de los vuelos.

Bibliografías

*Berrendero, J. R. (n.d.). Una breve introducción a ggplot2. http://verso.mat.uam.es/~joser.berrendero/R/introggplot2.html

LS0tCnRpdGxlOiAnRXZpZGVuY2lhIEZpbmFsOiBBbmFsw610aWNhIERlc2NyaXB0aXZhIHwgRXh0cmFjY2nDs24sIE1hbmlwdWxhY2nDs24gZSBJbnRlZ3JhY2nDs24gZGUgRGF0b3MnCmF1dGhvcjogIk5hbmN5IE1hcnJvcXXDrW4gLSBBMDExOTg1NTMsIEFkcmnDoW4gTW9yYWxlcyAtIEEwMTcyMjUzMiwgS2V2aW4gTWV6YSAtIEEwMDgzNjExMywgS2FybGEgTMOzcGV6IC0gQTAwMjI3NDExIgpkYXRlOiAiMjAyNC0wMy0wNCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiBUUlVFCiAgICB0b2NfZmxvYXQ6IFRSVUUKICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUKICAgIHRoZW1lOiBjb3NtbwotLS0KIVtdKEM6XFxVc2Vyc1xcbGVub3ZvXFxEb3dubG9hZHNcXGxsZWdhci1hZXJvcHVlcnRvLW51ZXZhLXlvcmstNC5qcGcpCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPkNvbnRleHRvPC9zcGFuPiAKRWwgcGFxdWV0ZSAqKm55Y2ZsaWdodHMxMyoqIGNvbnRpZW5lIGluZm9ybWFjacOzbiBzb3JlIHRvZG9zIGxvcyB2dWVsb3MgcXVlIHBhcnRpZXJvbiBkZXNkZSBOdWV2YSBZb3JrKEVXUiwgSkZMLCBMR0EpIGVuIGRlc3Rpbm9zIGEgbG9zIEVzdGFkb3MgVW5pZG9zIGVuIDIwMTMuIEZ1ZXJvbiAzMzYsNzc2IHZ1ZWxvcyBlbiB0b3RhbC4gUGFyYSBheXVkYXIgYSBjb21wcmVuZGVyIGxhcyBjYXVzYXMgZGUgbG9zIHJldHJhc29zLCB0YW1iacOpbiBpbmNsdXllIG90cm9zIGNvbmp1bnRvcyBkZSBkYXRvcyDDunRpbGVzLiAgCgpFc3RlIHBhcXVldGUgaW5jbHV5ZSBsYXMgc2lndWllbnRlcyB0YWJsYXM6CgorIGZsaWdodHMgPSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSBzYWxpZXJvbiBkZSBOVWV2YSBZb3JrIGVuIGVsIDIwMTMgIAorIHdlYXRoZXIgPSBkYXRvcyBtZXRlcmVvbMOzZ2ljb3MgcG9yIGhvcmEgZGUgY2FkYSBhZXJvcHVlcnRvICAKKyBwbGFuZXMgPSBpbmZvcm1hY2nDs24gZGUgY29uc3RydWNjacOzbiBkZSBjYWRhIGF2acOzbiAgCisgYWlycG9ydHMgPSBub21icmVzIHkgdWJsaWNhY2lvbmVzIGRlIGFlcm9wdWVydG9zICAKKyBhaXJsaW5lcyA9IHJlbGFjacOzbiBlbnRyZSBub21icmVzIHkgY8OzZGlnb3MgZGUgbGFzIGFlcm9sw61uZWFzICAKCkZ1ZW50ZToKW09yaWdlbiBkZSBsb3MgZGF0b3NdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ueWNmbGlnaHRzMTMvbnljZmxpZ2h0czEzLnBkZikKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+UmVwb3J0ZSBFamVjdXRpdm88L3NwYW4+IApFbiBlc3RhIGV2aWRlbmNpYSBzZSB0cmFiYWrDsyBjb24gZWwgcGFxdWV0ZSAqKm55Y2ZsaWdodHMqKiwgZWwgY3VhbCBub3MgcGVybWl0acOzIGFuYWxpemFyIGluZm9ybWFjacOzbiBhY2VyY2EgZGUgbG9zIHZ1ZWxvcywgZGVzdGlub3MsIGFlcm9sw61uZWFzLCByZXRyYXNvcywgZW50cmUgb3Ryb3M7IHJlZ2lzdHJhZG9zIGVuIGxvcyBhZXJvcHVlcnRvcyBkZSBOdWV2YSBZb3JrIGVuIGVsIDIwMTMuIFNlIHV0aWxpemFyb24gbGFzIGZ1bmNpb25lcyBtw6FzIGNvbXVuZXMgZGVsIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8sIGVsIGN1YWwgZXMgZWwgcHJpbWVyIHBhc28gcGFyYSBjdWFscXVpZXIgdHJhYmFqbyBkZSBtYW5pcHVsYWNpw7NuIGRlIGRhdG9zLiAgCgpMYSBzaXR1YWNpw7NuIHByb2JsZW1hIHF1ZSBzZSBidXNjYWJhIHJlc29sdmVyIGVzIHNhYmVyIGVsIHBvciBxdcOpIGxvcyB2dWVsb3Mgc2UgcmV0cmFzYW4sIHlhIHNlYSBlbiBsYSBwYXJ0aWRhIG8gZW4gbGEgbGxlZ2FkYSwgZW4gbG9zIGFlcm9wdWVydG9zIGVuIE51ZXZhIFlvcmsuIENvbiBsYSBpbmZvcm1hY2nDs24gYnJpbmRhZGEgZW4gbGFzIGJhc2VzIGRlIGRhdG9zLCBzZSBwdWRvIHJlYWxpemFyIHVuIGFuw6FsaXNpcyB0b21hbmRvIGVuIGN1ZW50YSBkaWZlcmVudGVzIHZhcmlhYmxlcywgeWEgc2VhIGVsIGNsaW1hLCBlbCB0aXBvIGRlIGF2acOzbiBxdWUgc2UgdXRpbGl6YWJhLCBsYSBhZXJvbMOtbmVhLCBlbCBkw61hIGRlIGxhIHNlbWFuYSwgbGFzIHRlbXBvcmFkYXMgdmFjYWNpb25hbGVzIGUgaW5jbHVzbyBoYXN0YSBlbCBob3JhcmlvIGRlbCBkw61hLiBBbCBhbmFsaXphciBlc3RhIGluZm9ybWFjacOzbiBzZSBvYnR1dmllcm9uIGRhdG9zIHF1ZSBub3MgcGVybWl0aXLDrWFuIGV2YWx1YXIgY3XDoWwgZXMgZWwgdmVyZGFkZXJvIG1vdGl2byBwb3IgZWwgcXVlIGxvcyB2dWVsb3Mgc2UgcmV0cmFzYW4uIAoKUGFyYSBlc3RlIHByb3llY3RvIGRpZmVyZW50ZXMgbWV0b2RvbG9nw61hcyBmdWVyb24gcHVlc3RhcyBhIHBydWViYSwgbGFzIGN1YWxlcyBheXVkYXJvbiBhIGdlbmVyYXIgY29uY2x1c2lvbmVzIGRlbCBhbsOhbGlzaXMgZ2VuZXJhbCBkZSByZXRyYXNvcyBlbiBwYXJ0aWRhcyB5IGxsZWdhZGFzLiBFbCB1c28gZGUgdmlzdWFsaXphY2lvbmVzIGRlIGdyw6FmaWNhcyBkZSBiYXJyYXMsIGhpc3RvZ3JhbWFzLCBkaWFncmFtYXMgZGUgZGlzcGVyc2nDs24sIGVudHJlIG90cm9zLCBmdWVyb24gaGVycmFtaWVudGFzIGltcG9ydGFudGVzIHBhcmEgZWwgYW7DoWxpc2lzIHZpc3VhbC4KCkEgbWVkaWRhIGNvbiBsYSBxdWUgc2UgYXZhbnphYmEgZW4gZWwgYW7DoWxpc2lzLCBwb2TDrWFtb3MgaXIgZGVzY2FydGFuZG8gcXVlIHZhcmlhYmxlcyBubyBzZXJ2w61hbiBkZSBtdWNobyB5IGN1YWxlcyBzw60gdGVuw61hbiB1biBtYXlvciBpbXBhY3RvIHBhcmEgcmVzb2x2ZXIgbGEgc2l0dWFjacOzbiBwcm9ibGVtYS4gRXN0byBub3MgcGVybWl0w61hIGdlbmVyYXIgdW4gbWF5b3IgZW5mb3F1ZSBlbiBhcXVlbGxvcyBhc3BlY3RvcyBtw6FzIHJlbGV2YW50ZXMgeSBwb3N0ZXJpb3JtZW50ZSwgY29uIGNyZWF0aXZpZGFkLCBnZW5lcmFyIHByb3B1ZXN0YXMgcGFyYSBsYSBkaXNtaW51Y2nDs24gZGUgcmV0cmFzb3MgZW4gc2FsaWRhcyB5IGxsZWdhZGFzLgoKQSBjb250aW51YWNpw7NuIHNlIHByZXNlbnRhIGxhIGV2aWRlbmNpYSBmaW5hbCwgY29uIGFuw6FsaXNpcywgaW50ZXJwcmV0YWNpb25lcywgZWxlbWVudG9zIHZpc3VhbGVzIHkgcmVjb21lbmRhY2lvbmVzIHBhcmEgbGFzIGFlcm9sw61uZWFzLCBhZXJvcHVlcnRvcyB5IHBhc2FqZXJvcywgdG9kbyBlc3RvIGNvbiBlbCBwcm9ww7NzaXRvIGRlIGJyaW5kYXIgc29sdWNpw7NuIGEgbG9zIHJldHJhc29zIGdlbmVyYWRvcy4KCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+SW5zdGFsYXIgcGFxdWV0ZXMgeSBsbGFtYXIgbGlicmVyw61hczwvc3Bhbj4KYGBge3Igd2FybmluZz1GQUxTRX0KI2luc3RhbGwucGFja2FnZXMoIm55Y2ZsaWdodDEzIikKbGlicmFyeShueWNmbGlnaHRzMTMpCiNpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKI2luc3RhbGwucGFja2FnZXMoImRwbHlyIikKbGlicmFyeShkcGx5cikKI2luc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQpsaWJyYXJ5KGdncGxvdDIpCmRhdGEoImZsaWdodHMiKQpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+R3VhcmRhciBiYXNlIGRlIGRhdG9zPC9zcGFuPiAKYGBge3J9CmZsaWdodHMgPC0gZmxpZ2h0cwp3ZWF0aGVyIDwtIHdlYXRoZXIKcGxhbmVzIDwtIHBsYW5lcwphaXJwb3J0cyA8LSBhaXJwb3J0cwphaXJsaW5lcyA8LSBhaXJsaW5lcwpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+UmVsYWNpw7NuIGVudHJlIGxhcyBiYXNlcyBkZSBkYXRvczwvc3Bhbj4gCiFbXShDOlxcVXNlcnNcXGxlbm92b1xcRG93bmxvYWRzXFxyZWxhdGlvbmFsLW55Y2ZsaWdodHMucG5nKQoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+UmVsYWNpw7NuIGV4aXN0ZW50ZTwvc3Bhbj4gCmBgYHtyfQpkZiA8LSBtZXJnZShmbGlnaHRzLGFpcmxpbmVzLCBieT0iY2FycmllciIpCmRmIDwtIGxlZnRfam9pbihkZixwbGFuZXMsIGJ5PSJ0YWlsbnVtIikKZGYgPC0gbGVmdF9qb2luKGRmLHdlYXRoZXIsIGJ5PWMoIm9yaWdpbiIsInRpbWVfaG91ciIpKQpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+RGF0YSBXcmFuZ2xpbmc8L3NwYW4+IAojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPjEuIEZ1bmNpb25lcyBiw6FzaWNhcyBkZSBtYW5lam8gZGUgZGF0b3M8L3NwYW4+IAojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlNlbGVjdDwvc3Bhbj4gCkxhIGZ1bmNpw7NuICpzZWxlY3QqIHNpcnZlIHBhcmEgc2VsZWNjaW9uYXIgY29sdW1ub3MgZGUgdW4gdGFibGUgKCpkYXRhIGZyYW1lKikuCmBgYHtyfQpkZjEgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KGNhcnJpZXIsIGZsaWdodCkgIyBTZWxlY2Npw7NuIGRlIGNvbHVtbmFzIGVzcGVjw61maWNhcwpkZjIgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KGNhcnJpZXI6ZGlzdGFuY2UpICMgU2VsZWNjacOzbiBkZSByYW5nbyBkZSBjb2x1bW5hcwpkZjMgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KC1jYXJyaWVyLCAtZmxpZ2h0KSAjIEVsaW1pbmFyIGNvbHVtbmFzIGVzcGVjw61maWNhcwpkZjQgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KC1jYXJyaWVyOiAtZmxpZ2h0KSAjIEVsaW1pbmFyIHJhbmdvIGRlIGNvbHVtbmFzCmRmNSA8LSBmbGlnaHRzICU+JSBzZWxlY3QoYWVyb2xpbmVhID0gY2FycmllcikgIyBTZWxlY2Npb25hIHVuYSBjb2x1bW5hIHkgbGUgY2FtYmlhIGVsIG5vbWJyZQpkZjYgPC0gZmxpZ2h0cyAlPiUgcmVuYW1lKGFlcm9saW5lYSA9IGNhcnJpZXIpICMgQ2FtYmlhIGVsIG5vbWJyZSBkZSB1bmEgY29sdW1uYQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+RmlsdGVyPC9zcGFuPiAKTGEgZnVuY2nDs24gKkZpbHRlciogc2lydmUgcGFyYSBzZWxlY2Npb25hciByZW5nbG9uZXMgZGUgdW4gdGFibGEoKmRhdGEgZnJhbWUqKS4KYGBge3J9CmRmNyA8LSBmbGlnaHRzICU+JSBmaWx0ZXIoZGVwX2RlbGF5ID49NTAwKSAjIEV4dHJhZSByZW5nbG9uZXMgcXVlIGN1bXBsYW4gY29uZGljacOzbgojIENvbmRpY2lvbmFsZXM6IElndWFsID09LCBEZXNpZ3VhbCA9IT0sIE1heW9yIHF1ZSA+LCBNYXlvciBvIGlndWFsIHF1ZSA+PSwgTWVub3IgbyBpZ3VhbCBxdWUgPD0KIyBPcGVyYWRvcmVzIGzDs2dpY29zOiBBTkQgJiwgT1IgfCwgTk9UICEKZGY4IDwtIGZsaWdodHMgJT4lIGZpbHRlcihkZXBfZGVsYXkgPj01MDAsIGRlcF9kZWxheSA8PTYwMCkgIyBFeHRyYWUgcmVuZ2xvbmVzIHF1ZSBjdW1wbGFuIGNvbiBkb3MgY29uZGljaW9uZXMKZGY5IDwtIGZsaWdodHMgJT4lIHNsaWNlKDEwMDA6IDEwOTkpICMgRXh0cmFlIGxvcyBuw7ptZXJvcyBkZSBsb3MgcmVuZ2xvbmVzIGluZGljYWRvcywgc2luIGltcG9ydGFyIHN1cyB2YWxvcmVzCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5EaXN0aW5jdDwvc3Bhbj4gCkxhIGZ1bmNpw7NuICpkaXN0aW5jdCogc2lydmUgcGFyYSBlbGltaW5hciByZW5nbG9uZXMgZHVwbGljYWRvcy4KYGBge3J9CmRmMTAgPC0gZGlzdGluY3QoZmxpZ2h0cykgIyBEZWphciBzb2xvIGxvcyByZW5nbG9uZXMgZGlmZXJlbnRlcywgYm9ycmEgdG9kb3MgbG9zIHJlcGV0aWRvcy4KYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPk1lcmdlPC9zcGFuPiAKTGEgZnVuY2nDs24gKm1lcmdlKiBzaXJ2ZSBwYXJhIGp1bnRhciBiYXNlcyBkZSBkYXRvcy4KYGBge3J9CmJkZ3JhbmRlIDwtIG1lcmdlKGZsaWdodHMsIGFpcmxpbmVzLCBieT0iY2FycmllciIpCmJkZ3JhbmRlMiA8LSBtZXJnZShiZGdyYW5kZSxwbGFuZXMsIGJ5PSJ0YWlsbnVtIikKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPk11dGF0ZTwvc3Bhbj4gCmBgYHtyfQpiZGdyYW5kZTMgPC0gbXV0YXRlKGJkZ3JhbmRlMiwgZGlzdF9tdHMgPSBkaXN0YW5jZSoxLjYwOSkKI0FncmVnYSB2YXJpYWJsZXMgbnVldmFzIGNhbHVsYWRhcyBhIHBhcnRpciBkZSB2YXJpYWJsZXMgZXhpc3RlbnRlcyBlbiBsYSBiYXNlIGRlIGRhdG9zLgpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+RWplcmNpY2lvczwvc3Bhbj4gCjEuIEVuY3VlbnRyYSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSB0dXZpZXJvbiB1biBhdHJhc28gZW4gbGxlZ2FkYSBkZSAyIGhvcmFzIG8gbcOhcy4KYGBge3J9CmVqZXJjaWNpbzEgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIoYXJyX2RlbGF5Pj0xMjApCmBgYAoKMi4gRW5jdWVudHJhIHRvZG9zIGxvcyB2dWVsb3MgcXVlIGxsZWdhcm9uIGEgSG91c3RvbiAoSUFOIE8gSE9VKQpgYGB7cn0KZWplcmNpY2lvMiA8LSBiZGdyYW5kZTIgJT4lIGZpbHRlcihkZXN0PT0gIklBSCIgfCBkZXN0ID09ICJIT1UiKQpgYGAKCjMuIEVuY3VlbnRyYSB0b2RvcyBsb3MgdnVlbG9zIG9wZXJhZG9zIHBvciBVbml0ZWQsIEFtZXJpY2FuIG8gRGVsdGEuCmBgYHtyfQplamVyY2ljaW8zIDwtIGJkZ3JhbmRlMiAlPiUgZmlsdGVyKGNhcnJpZXIgJWluJSBjKCJVQSIsICJBQSIsICJETCIpKQpgYGAKCjQuIEVuY3VlbnRyYSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSBkZXNwZWdhcm9uIGVuIEp1bGlvLCBBZ29zdG8gbyBTZXB0aWVtYnJlCmBgYHtyfQplamVyY2ljaW80IDwtIGJkZ3JhbmRlMiAlPiUgZmlsdGVyKG1vbnRoICVpbiUgYyg3LCA4LCA5KSkKZWplcmNpY2lvNGEgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIobW9udGggPT0gNyB8IG1vbnRoID09IDggfCBtb250aCA9PSA5KSAKYGBgCgo1LiBFbmN1ZW50cmEgdG9kb3MgbG9zIHZ1ZWxvcyBxdWUgYXJyaXZhcm9uIG3DoXMgZGUgMiBob3JhcyB0YXJkZSwgcGVybyBubyBkZXNwZWdhcm9uIHRhcmRlLgpgYGB7cn0KZWplcmNpY2lvNSA8LSBiZGdyYW5kZTIgJT4lIGZpbHRlcihhcnJfZGVsYXk+MTIwICYgZGVwX3RpbWUgPT0gc2NoZWRfZGVwX3RpbWUpCmVqZXJjaWNpbzVhIDwtIGJkZ3JhbmRlMiAlPiUgZmlsdGVyKGFycl9kZWxheT4xMjAgJiBkZXBfZGVsYXk8PTApCmBgYAoKNi4gRW5jdWVudHJhIHRvZG9zIGxvcyB2dWVsb3MgcXVlIHNlIHJldHJhc2Fyb24gYWwgbWVub3MgMSBob3JhLCBwZXJvIHF1ZSBsbGVnYXJvbiBhbnRlcyAzMCBtaW51dG9zIG8gbcOhcy4KYGBge3J9CmVqZXJjaWNpbzYgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIoZGVwX2RlbGF5Pj02MCAmIGFycl9kZWxheTw9LTMwKQpgYGAKCjcuIEVuY3VlbnRyYSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSBzYWxpZXJvbiBlbnRyZSBsYSBtZWRpYW5vY2hlIHkgbGFzIDYgYS5tLgpgYGB7cn0KZWplcmNpY2lvNyA8LSBiZGdyYW5kZTIgJT4lIGZpbHRlcihkZXBfdGltZSAlaW4lIGMoIjI0MDAiLCAiMTAwIiwgIjIwMCIsICIzMDAiLCAiNDAwIiwgIjUwMCIsICI2MDAiKSkKZWplcmNpY2lvN2EgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIoZGVwX3RpbWU9PTI0MDAgfCBkZXBfdGltZTw9NjAwKSAjQ09SUkVDVEEKZWplcmNpY2lvN2IgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIoaG91ciAlaW4lIGMoIjAiLCAiMSIsICIyIiwgIjMiLCAiNCIsICI1IiwgIjYiKSkKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPkFycmFuZ2U8L3NwYW4+IApTaW1pbGFyIGEgZmlsdGVyICgpIHBlcm8gZW4gbHVnYXIgZGUgc2VsZWNjaW9uYXIgcmVuZ2xvbmVzLCBsb3Mgb3JkZW5hIGRlIG1lbm9yIGEgbWF5b3IuCmBgYHtyfQpkZjExIDwtIGFycmFuZ2UoYmRncmFuZGUyLCB5ZWFyLngsIG1vbnRoLCBkYXkpCmBgYAoKUGFyYSBhY29tb2RhciBkZSBtYXlvciBhIG1lbm9yLgpgYGB7cn0KZGYxMiA8LSBhcnJhbmdlKGJkZ3JhbmRlMiwgeWVhci54LCBkZXNjKG1vbnRoKSwgZGF5KQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+U3VtbWFyaXplPC9zcGFuPiAKQ29sYXBzYSB1bmEgdGFibGEgYSB1biBzw7NsbyByZW5nbMOzbgpgYGB7cn0KIyBPYnTDqW4gZWwgcmV0cmFzbyBwcm9tZWRpbyBkZSBzYWxpZGEgZGUgZGVzcGVndWUgZGUgdG9kb3MgbG9zIHZ1ZWxvcwpzdW1tYXJpemUoYmRncmFuZGUyLCBtZWFuKGRlcF9kZWxheSwgbmEucm09VFJVRSkpCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5Hcm91cCBieTwvc3Bhbj4gCkFncnVwYSB0YWJsYSBiYXNhZG8gZW4gYWxndW5hcyBjb2x1bW5hcy4KYGBge3J9CiMgT2J0ZW5lciBlbCByZXRyYXNvIHByb21lZGlvIGRlIGRlc3BlZ3VlIHBvciBkw61hCnBvcl9kaWEgPC0gZ3JvdXBfYnkoYmRncmFuZGUyLCB5ZWFyLngsIG1vbnRoLCBkYXkpCnN1bW1hcml6ZShwb3JfZGlhLCBtZWFuKGRlcF9kZWxheSwgbmEucm09VFJVRSkpCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5FdmlkZW5jaWE6IFBhcnRlIDE8L3NwYW4+IAojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPjEuIENhcmdhciBlbiBtZW1vcmlhIGxhIHRhYmxhICJmbGlnaHRzIiB5IG1vc3RyYXIgc3UgY29udGVuaWRvPC9zcGFuPiAKYGBge3J9CiMgTGEgY2FyZ2EgYSBtZW1vcmlhIHNlIGhpem8gZW4gZWwgcGFzbyBhbnRlcmlvciwgY29uc3VsdGEgZGUgZGF0YWZyYW1lIHBhcmEgcmVjb3JkYXIgc3UgY29udGVuaWRvLgp2aWV3KGZsaWdodHMpCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij4yLiBEYXRvcyBkZXNjcmlwdGl2b3MgZGUgImZsaWdodHMiPC9zcGFuPiAKYGBge3J9CiMgSWRlbnRpZmljYSBsYSBtZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzIGVuIG1pbGxhcy4Kc3VtbWFyeShmbGlnaHRzKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+My4gQ3JpdGVyaW9zIHBhcmEgZW5jb250cmFyIGFlcm9sw61uZWFzPC9zcGFuPiAKYGBge3J9CiNDcmVhIHVuIG51ZXZvIGRhdGEgZnJhbWUgcXVlIGZpbHRyZSBzb2xhbWVudGUgYSBsYXMgYWVvcmzDrW5lYXMgcXVlIGhhbiByZWNvcnJpZG8gdW5hIGRpc3RhbmNpYSBzdXBlcmlvciBhIGxhIG1lZGlhLCBzZSBkZXNlYW4gdmVyIGxvcyBjYW1wb3MgY2FycmllciwgZGlzdGFuY2UsIG9yaWdpbiwgZGVzdCBlbiBmb3JtYSBkZXNjZW5kZW50ZSBwb3IgZGlzdGFuY2UuCgojQ3JpdGVyaW8gMTogc2Ugc2VsZWNjaW9uYSBsYXMgdmFyaWFibGVzLgpDcml0ZXJpbzEgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KGNhcnJpZXIsIGRpc3RhbmNlLCBvcmlnaW4sIGRlc3QpCgojQ3JpdGVyaW8gMjogc2UgZmlsdHJhbiBhIGxhcyBhZXJvbGluZWFzIHF1ZSB0ZW5nYW4gdW5hIG1lZGlhIHN1cGVyaW9yIGEgMTA0MCBlbiBtaWxsYXMgcmVjb3JyaWRhcy4gCkNyaXRlcmlvMiA8LSBDcml0ZXJpbzEgJT4lIGZpbHRlcihkaXN0YW5jZSA+MTA0MCkKCiNDcml0ZXJpbyAzOiBzZSBvcmRlbmEgZW4gZGVzY2VuZGVudGUgcG9yIGxhIGRpc3RhbmNpYSByZWNvcnJpZGEgCkNyaXRlcmlvMyA8LSBDcml0ZXJpbzIgJT4lIGFycmFuZ2UoZGVzYyhkaXN0YW5jZSkpCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij40LiBTdW1hIHkgTWVkaWEgZGUgbGFzIGRpc3RhbmNpYXMgcmVjb3JyaWRhczwvc3Bhbj4gCmBgYHtyfQojIFNlIGVuY3VlbnRyYSBsYSBzdW1hIHkgbGEgbWVkaWEgZGUgbGFzIGRpc3RhbmNpYXMgcmVjb3JyaWRhcyBwb3IgY2FycmllciwgZWxpbWluYSBsb3MgTkHigJlTIGUgaW50ZXJwcmV0YSBxdWUgc2lnbmlmaWNhIGxhIHN1bWEgeSBsYSBtZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzLgoKQ3JpdGVyaW80IDwtIENyaXRlcmlvMyAlPiUgZ3JvdXBfYnkoY2FycmllcixvcmlnaW4sZGVzdCkgJT4lICAKICBzdW1tYXJpemUoZGlzdGFuY2VzdW1hPXN1bShkaXN0YW5jZSwgbmEucm09VFJVRSksIGRpc3RhbmNlcHJvbWVkaW89bWVhbihkaXN0YW5jZSwgbmEucm09VFJVRSkpCgojIFBvc3Rlcmlvcm1lbnRlLCBzZSBvcmRlbmEgZGUgZm9ybWEgZGVzY2VuZGVudGUgZW4gYmFzZSBhIGxhIGRpc3RhbmNpYSByZWNvcnJpZGEuCkRlc2NlbmRlbnRlIDwtIENyaXRlcmlvNCAlPiUgYXJyYW5nZShjYXJyaWVyLGRpc3RhbmNlc3VtYSkKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPjUuIEludGVycHJldGFjaW9uZXM6IFBhcnRlIDE8L3NwYW4+IApFbiBlc3RhIHByaW1lcmEgcGFydGUgc2UgcmVhbGl6YW4gbG9zIHBhc29zIGLDoXNpY29zIHBhcmEgY29tZW56YXIgYSBhbmFsaXphciB1bmEgYmFzZSBkZSBkYXRvcy4gRXMgdW4gYW5hbGlzaXMgaW5pY2lhbCBkb25kZSBzZSB2aXN1YWxpemEgZWwgY29udGVuaWRvIGRlIGxvcyBkYXRvcyBkaXNwb25pYmxlcyB5IHNlIG9idGllbmVuIGxvcyBkYXRvcyBkZXNjcmlwdGl2b3MgYsOhc2ljb3MgcGFyYSBjb21wcmVuZGVyIG1lam9yIGxhIGluZm9ybWFjacOzbiBkZSB2dWVsb3MuIEVuIGxvcyBkYXRvcyBkZXNjcmlwdGl2b3MgcG9kZW1vcyBlbmNvbnRyYXIgbGEgbWVkaWEsIGVsIG3DrW5pbW8sIG3DoXhpbW8sIGVudHJlIG90cm9zLCBkZSBsYXMgZGlmZXJlbnRlcyB2YXJpYWJsZXMgY29uIGxhcyBxdWUgY3VlbnRhIGxhIGJhc2UgZGUgZGF0b3MuIEVuIGxhIHByb2JsZW3DoXRpY2Egc2Ugbm9zIHBpZGUgZW5jb250cmFyIGxhIG1lZGlhIGRlIGxhcyBtaWxsYXMgcmVjb3JyaWRhcywgdXRpbGl6YW5kbyAqc3VtbWFyeSogbm9zIGFycm9qYSB1biByZXN1bHRhZG8gZGUgMTA0MCBtaWxsYXMgcmVjb3JyaWRhcyBjb21vIG1lZGlhLiAgCgpFbiBlbCBzaWd1aWVudGUgcHVudG8gc2UgdXRpbGl6YXJvbiBkaWZlcmVudGVzIGNyaXRlcmlvcyBwYXJhIGZpbHRyYXIgbGFzIGFlcm9sw61uZWFzIHF1ZSBoYW4gcmVjb3JyaWRvIHVuYSBkaXN0YW5jaWEgbWF5b3IgYSBsYSBtZWRpYS4gUGFyYSBlc3RvLCBwcmltZXJvIHNlbGVjY2lvbmFtb3MgbGFzIHZhcmlhYmxlcyBjb24gbGEgZnVuY2nDs24gKnNlbGVjdCogZW4gZG9uZGUgc2Ugb2J0ZW7DrWEgbGEgYWVyb2zDrW5lYSwgbGEgZGlzdGFuY2lhLCBlbCBvcmlnZW4geSBlbCBkZXN0aW5vLiBQb3N0ZXJpb3JtZW50ZSBjb24gbGEgZnVuY2nDs24gKmZpbHRlciosIHNlIGZpbHRyYXJvbiBsYXMgYWVyb2zDrW5lYXMgY29uIHVuYSBtZWRpYSBzdXBlcmlvciBhIGxhcyAxMDQwIG1pbGxhcyByZWNvcnJpZGFzLCBwYXJhIGRlc3B1w6lzIG9yZGVuYXJsYXMgZW4gZm9ybWF0byBkZXNjZW5kZW50ZS4KClBvciDDumx0aW1vLCBzZSBub3MgcGlkZSBvYnRlbmVyIGxhIHN1bWEgeSBsYSBtZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzLCBhc8OtIGNvbW8gZWxpbWluYXIgbG9zICpOQSdTKiwgdXRpbGl6YW5kbyBsYXMgZnVuY2lvbmVzICpncm91cF9ieSogeSAqc3VtbWFyaXplKiwgc2Ugb2J0dXZvIGxhIGRpc3RhbmNpYSBlbiBzdW1hIHkgZW4gcHJvbWVkaW87IGNvbW8gcGFzbyBmaW5hbCBvcmRlbmFtb3MgZXN0bywgbnVldmFtZW50ZSwgZW4gZm9ybWF0byBkZXNjZW5kZW50ZS4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+Ni4gSWRlbnRpZmljYXIgYWVyb2zDrW5lYXMgbMOtZGVyZXMgZW4gbG9zIGFlcm9wdWVydG9zPC9zcGFuPgpgYGB7cn0KI0VuIGVzdGEgcGFydGUgc2UgaWRlbnRpZmljYSBzaSBsYXMgYWVyb2zDrW5lYXMgbMOtZGVyZXMgc29uIGxhcyBtaXNtYXMgZW4gbG9zIHRyZXMgYWVyb3B1ZXJ0b3MgY3V5byBvcmlnZW4gZXMgTnVldmEgWW9yayB5YSBzZWEgZWwgSm9obiBGLiBLZW5uZWR5IChKRkspLCBlbCBkZSBMYUd1YXJkaWEgKExHQSkgbyBlbCBkZSBOZXdhcmsgTGliZXJ0eSAoRVdSKS4gU2UgZ2VuZXJhIHVuIGRhdGFmcmFtZSBwYXJhIGNhZGEgYWVyb3B1ZXJ0by4KCkFlcm9wdWVydG9fSkZLID0gRGVzY2VuZGVudGUgJT4lIGZpbHRlcihvcmlnaW4gPT0gIkpGSyIpICAlPiUgYXJyYW5nZShjYXJyaWVyLCBkZXNjKGRpc3RhbmNlc3VtYSkpCkFlcm9wdWVydG9fTEdBID0gRGVzY2VuZGVudGUgJT4lIGZpbHRlcihvcmlnaW4gPT0gIkxHQSIpICAlPiUgYXJyYW5nZShjYXJyaWVyLCBkZXNjKGRpc3RhbmNlc3VtYSkpCkFlcm9wdWVydG9fRVdSID0gRGVzY2VuZGVudGUgJT4lIGZpbHRlcihvcmlnaW4gPT0gIkVXUiIpICAlPiUgYXJyYW5nZShjYXJyaWVyLCBkZXNjKGRpc3RhbmNlc3VtYSkpCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij43LiBDb25jbHVzacOzbjogUGFydGUgMTwvc3Bhbj4KRGFuZG8gY2llcnJlIGEgbGEgcGFydGUgMSBkZSBsYSBldmlkZW5jaWEsIHNlIGlkZW50aWZpY8OzIGN1YWxlcyBlcmFuIGxhcyBhZXJvbMOtbmVhcyBsw61kZXJlcyBlbiBsb3MgdHJlcyBhZXJvcHVlcnRvcyBkZSBOdWV2YSBZb3JrIGNyZWFuZG8gdW4gZGF0YWZyYW1lIHBvciBjYWRhIGFlcm9wdWVydG8uIEVuIGVsIGNhc28gZGVsIGFlcm9wdWVydG8gKipOZXdhcmsgTGliZXJ0eSoqIChFV1IpLCBsYSBhZXJvbMOtbmVhIGNvbiBtYXlvciBkaXN0YW5jaWEgcmVjb3JyaWRhIGVzICpVbml0ZWQgQWlybGluZXMqIChVQSksIGNvbiB1biB0b3RhbCBkZWwgMSw4MTEsNDk1IG1pbGxhcyByZWNvcnJpZGFzLiBQYXJhIGVsIGFlcm9wdWVydG8gZGUgKipMYUd1YXJkaWEqKiAoTEdBKSBzZXLDrWEgKkFtZXJpY2FuIEFpcmxpbmVzKiAoQUEpIGNvbiB1bmEgc3VtYSBkZSA2LDcxNywyMDQgbWlsbGFzIHJlY29ycmlkYXMuIFBvciDDumx0aW1vLCBlbiBlbCBhZXJvcHVlcnRvIGRlICoqSm9obiBGLiBLZW5uZWR5KiogKEpGSyksIGRlIGlndWFsIG1hbmVyYSBlbCBwcmltZXIgcHVlc3RvIGxvIG9idGllbmUgKkFtZXJpY2FuIEFpcmxpbmVzKiBjb24gdW4gdG90YWwgZGUgNyw5NjIsMDc1IG1pbGxhcyByZWNvcnJpZGFzLgoKRW4gY29uY2x1c2nDs24sIHNlIHJlYWxpesOzIHVuYSBleHBsb3JhY2nDs24gaW5pY2lhbCwgb2J0ZW5pZW5kbyBkYXRvcyBkZXNjcmlwdGl2b3MgY29tbyBsYSBtZWRpYSBkZSBtaWxsYXMgcmVjb3JyaWRhcywgcmV2ZWxhbmRvIHVuIHByb21lZGlvIGRlIDEwNDAgbWlsbGFzLiBMdWVnbywgc2UgYXBsaWNhcm9uIGNyaXRlcmlvcyBwYXJhIGlkZW50aWZpY2FyIGFlcm9sw61uZWFzIHF1ZSBvcGVyYW4gdnVlbG9zIGRlIGxhcmdhIGRpc3RhbmNpYSwgcmVzdWx0YW5kbyBlbiBsYSBzdW1hIHkgbWVkaWEgZGUgbGFzIGRpc3RhbmNpYXMgcmVjb3JyaWRhcywgcHJvcG9yY2lvbmFuZG8gdW5hIHZpc2nDs24gY2xhcmEgZGUgbG9zIHBhdHJvbmVzIGRlIHZ1ZWxvIHkgZGlzdGFuY2lhcy4gQWRlbcOhcywgc2UgZXhhbWluYSBzaSBsYXMgYWVyb2zDrW5lYXMgbMOtZGVyZXMgc29uIGNvbnNpc3RlbnRlcyBlbiBsb3MgYWVyb3B1ZXJ0b3MgZGUgTnVldmEgWW9yayAoSkZLLCBMR0EgeSBFV1IpLCBlbiBkb25kZSBzZSBkZXN0YWNhIHF1ZSAqQW1lcmljYW4gQWlybGluZXMqIG9idGllbmUgZWwgcHJpbWVyIHB1ZXN0byBlbiBkb3MgZGUgbG9zIHRyZXMgYWVyb3B1ZXJ0b3MgZXhpc3RlbnRlcy4KCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+RXZpZGVuY2lhOiBQYXJ0ZSAyPC9zcGFuPiAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+MS4gQ29uc3VsdGEgZGVsIGRhdGFmcmFtZTwvc3Bhbj4KYGBge3J9CiNBbCBjb25zdWx0YXIvbGxhbWFyIGVsIERhdGFGcmFtZSBub3MgcGVybWl0ZSB2aXN1YWxpemFyIGxhIGJhc2UgZGUgZGF0b3MgKmZsaWdodHMqLgp2aWV3KGZsaWdodHMpCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij4yLiBJbmZvcm1hY2nDs24gZGUgY2FkYSB2dWVsbzwvc3Bhbj4KYGBge3J9CiNTZSBuZWNlc2l0YSBzYWJlciBkZSBjYWRhIHZ1ZWxvLCBsYSBhZXJvbMOtbmVhLCBlbCBhZXJvcHVlcnRvIGRlIG9yaWdlbiB5IGVsIGFlcm9wdWVydG8gZGVzdGlubwp2dWVsb3MgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KGNhcnJpZXIsIG9yaWdpbiwgZGVzdCkKCiNEZSBsYSBjb25zdWx0YSBhbnRlcmlvciBzZSByZXF1aWVyZSBzYWJlciBlbCBub21icmUgZGUgbGEgYWVyb2zDrW5lYQphZXJvbMOtbmVhIDwtIHZ1ZWxvcyAlPiUgbGVmdF9qb2luIChhaXJsaW5lcywgYnkgPSAiY2FycmllciIpCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij4zLiBDYW50aWRhZCBkZSB2dWVsb3MgcG9yIGRlc3Rpbm88L3NwYW4+CmBgYHtyfSAKI0RlIGxhIGNvbnN1bHRhIGFudGVyaW9yIHNlIHJlcXVpZXJlIHNhYmVyIGVsIG5vbWJyZSBkZSBsYSBhZXJvbMOtbmVhIAoKc3VtbWFyeV9kZWxheSA8LSBkZiAlPiUKICBncm91cF9ieShkZXN0LCBuYW1lKSAlPiUKICBzdW1tYXJpc2UoYXZnX2RlbGF5ID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHRvdGFsX2ZsaWdodHMgPSBuKCksCiAgICAgICAgICAgIHRvdGFsX2RlbGF5ZWRfZmxpZ2h0cyA9IHN1bShkZXBfZGVsYXkgPiAwLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwZXJjX2RlbGF5ZWRfZmxpZ2h0cyA9IHRvdGFsX2RlbGF5ZWRfZmxpZ2h0cyAvIHRvdGFsX2ZsaWdodHMgKiAxMDApCgpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+NC4gQWVyb2zDrW5lYXMgeSBEZXN0aW5vczogTWHDsWFuYSwgVGFyZGUsIE5vY2hlIHkgTWFkcnVnYWRhPC9zcGFuPgpgYGB7cn0KI1NlIG5lY2VzaXRhIGNvbm9jZXIgbGFzIGFlcm9sw61uZWFzIChjbGF2ZSB5IG5vbWJyZSkgeSBkZXN0aW5vcyBxdWUgdnVlbGFuIHBvciBsYSBNYcOxYW5hOiBkZSA2IGEgMTIsIFRhcmRlOiBkZSAxMiBhIDE5ICwgTm9jaGU6IGRlIDE5IGEgMjQgeSBNYWRydWdhZGEgZGUgMjQgYSA2LgoKdHVybm9fY2FycmllciA8LSBmbGlnaHRzICU+JSBzZWxlY3QgKGNhcnJpZXIsIGRlc3QsIHNjaGVkX2RlcF90aW1lKSAlPiUgbGVmdF9qb2luIChhaXJsaW5lcywgYnkgPSAiY2FycmllciIpCgp0dXJub19NVE5NPC0gbXV0YXRlKHR1cm5vX2NhcnJpZXIsIGNsYXNfaG9yYXJpbyA9IGlmZWxzZShzY2hlZF9kZXBfdGltZSAlaW4lIDYwMDoxMTU5LCJNYcOxYW5hIixpZmVsc2Uoc2NoZWRfZGVwX3RpbWUgJWluJSAxMjAwOjE4NTksIlRhcmRlIixpZmVsc2Uoc2NoZWRfZGVwX3RpbWUgJWluJSAxOTAwOjI0MDAsIk5vY2hlIiwgIk1hZHJ1Z2FkYSIpKSkpCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij41LiBDYW50aWRhZCBkZSB2dWVsb3M6IE1hw7FhbmEsIFRhcmRlIHkgTm9jaGU8L3NwYW4+CmBgYHtyfQojU2UgcHJlc2VudGEgbGEgY2FudGlkYWQgZGUgdnVlbG9zIHBvciBhZXJvbMOtbmVhIHkgZGVzdGlubyBxdWUgaGF5IGVuIGNhZGEgdHVybm8sIHlhIHNlYSBlbiBsYSBtYcOxYW5hLCB0YXJkZSwgbm9jaGUgbyBtYWRydWdhZGEuCgpjYW50aWRhZF90dXJub19NVE5NIDwtIHR1cm5vX01UTk0gJT4lIGdyb3VwX2J5KGNhcnJpZXIsIGRlc3QsIGNsYXNfaG9yYXJpbykgJT4lIGNvdW50KCkKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPjYuIERlc3Rpbm9zIGEgbG9zIHF1ZSB2dWVsYSBBbWVyaWNhbiBBaXJsaW5lcyBlbiBNYWRydWdhZGE8L3NwYW4+CmBgYHtyfQpBQV9kZXN0aW5vc19tYWQgPC0gdHVybm9fTVROTSAlPiUgc2VsZWN0KGNhcnJpZXIsbmFtZSwgZGVzdCxjbGFzX2hvcmFyaW8pICU+JSBmaWx0ZXIoY2FycmllciA9PSAiQUEiICYgY2xhc19ob3JhcmlvID09ICJNYWRydWdhZGEiKSAlPiUgZ3JvdXBfYnkoY2FycmllcixuYW1lLCBkZXN0LGNsYXNfaG9yYXJpbykKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPjcuIEF2aW9uZXMgcXVlIHV0aWxpemEgQW1lcmljYW4gQWlybGluZXM8L3NwYW4+CmBgYHtyfQojU2UgcHJlc2VudGEgbGEgYWVyb2zDrW5lYSwgdGlwbywgbW90b3IsIG7Dum1lcm8gZGUgYXNpZW50b3MgeSBsYSBjYW50aWRhZCBkZSB2dWVsb3MgcXVlIHNlIGhhbiByZWFsaXphZG8gY29uIGNhZGEgdW5vIGRlIGxvcyBhdmlvbmVzLgpBQV9hdmlvbmVzIDwtIGZsaWdodHMgJT4lIGxlZnRfam9pbihwbGFuZXMsIGJ5ID0gInRhaWxudW0iKSAlPiUgc2VsZWN0KGNhcnJpZXIsIHR5cGUsIGVuZ2luZSwgc2VhdHMpICU+JSBmaWx0ZXIoY2FycmllciA9PSAiQUEiLCAhaXMubmEodHlwZSkpICU+JSBncm91cF9ieShjYXJyaWVyLHR5cGUsZW5naW5lLHNlYXRzKSAlPiUgY291bnQoKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+OC4gSW50ZXJwcmV0YWNpb25lczogUGFydGUgMjwvc3Bhbj4KRW4gZXN0YSBzZWd1bmRhIHBhcnRlIHNlIGNvbWllbnphIHZpc3VhbGl6YW5kbyBsYSBiYXNlIGRlIGRhdG9zICpmbGlnaHRzKiB5IGxhIG9idGVuY2nDs24gZGUgaW5mb3JtYWNpw7NuIGRlIGNhZGEgdnVlbG8sIGVuIGVzdGUgY2FzbywgbGEgYWVyb2zDrW5lYSwgZWwgYWVyb3B1ZXJ0byBkZSBvcmlnZW4geSBlbCBkZSBkZXN0aW5vLiBDb24gZXN0byBzZSBwdWRvIG9idGVuZXIgbGEgY2FudGlkYWQgZGUgdnVlbG9zIHBvciBkZXN0aW5vIHkgZWwgcHJvbWVkaW8gZGUgcmV0cmFzbyBxdWUgdGllbmUgY2FkYSB1bm8gZGUgZWxsb3MsIGFkZW3DoXMgZGUgbWVuY2lvbmFyIHF1ZSBhZXJvbMOtbmVhIG1hbmVqYSBjYWRhIGRlc3Rpbm8uIFBvciBlamVtcGxvLCBlbCBkZXN0aW5vIGNvbiBtYXlvciBjYW50aWRhZCBkZSB2dWVsb3MgZXMgQXRsYW50YSAoQVRMKSBjb24gdW4gdG90YWwgZGUgMTAsNTcxIHZ1ZWxvcywgY29uIGxhIGFlcm9sw61uZWEgKkRlbHRhIEFpciBMaW5lcyBJbmMqLiBQb3Igb3RyYSBwYXJ0ZSwgaGF5IHVuIHRvdGFsIGRlIDE3IGRlc3Rpbm9zIGNvbiBsYSBtZW5vciBjYW50aWRhZCBkZSB2dWVsb3MsIG8gc2VhIDEgdnVlbG8gc29sYW1lbnRlIGhhY2lhIGNhZGEgdW5vIGRlIGVzb3MgMTcgZGVzdGlub3MsIGVzIHBvciBlc28gcXVlIGVuIGVzdGUgY2FzbyBsYXMgYWVyb2zDrW5lYXMgY29ycmVzcG9uZGllbnRlcyB2YXLDrWFuLiAKCkNvbnRpbnVhbmRvIGNvbiBlbCBhbsOhbGlzaXMsIHNlIG9idGllbmUgbGEgY2xhdmUgeSBlbCBub21icmUgZGUgbGEgYWVyb2zDrW5lYSB5IGxvcyBkaWZlcmVudGVzIGRlc3Rpbm9zIHF1ZSBzZSBvcGVyYW4gZW4gbG9zIHR1cm5vcyBkZSBtYcOxYW5hLCB0YXJkZSwgbm9jaGUgeSBtYWRydWdhZGEuIENvbiBlc3RvIHNlIG9idHV2byB1biB0b3RhbCBkZSAzMzYsNzc2IHZ1ZWxvcyBjb24gbGFzIDUgdmFyaWFibGVzIGEgYW5hbGl6YXI6ICpjYXJyaWVyKiwgKmRlc3QqLCAqc2NoZWRfZGVwX3RpbWUqLCAqbmFtZSogeSAqY2xhc19ob3JhcmlvKi4gRGVzcHXDqXMgc2UgcHJlc2VudGEgbGEgY2FudGlkYWQgZGUgdnVlbG9zIHBvciBhZXJvbMOtbmVhIHkgZGVzdGlubyBxdWUgaGF5IGVuIGNhZGEgdHVybm8sIHNlIGRlc3RhY2EgcXVlIGxhIGFlcm9sw61uZWEgKkRlbHRhKiAoREwpIGNvbiBkZXN0aW5vIGEgQXRsYW50YSAoQVRMKSB0aWVuZSBsYSBtYXlvciBjYW50aWRhZCBkZSB2dWVsb3MgZW4gdW4gaG9yYXJpbyBkZSB0YXJkZSBjb24gdW4gdG90YWwgZGUgNDk2NyB2dWVsb3MuIERlIG51ZXZvLCBsb3MgZGUgbWVub3IgY2FudGlkYWQgdmFyw61hbiwgeWEgcXVlIGV4aXN0ZW4gdmFyaWFzIGFlcm9sw61uZWFzIGNvbiB1biBzb2xvIHZ1ZWxvLCBhIHVuIHNvbG8gZGVzdGlubyB5IGVuIHVuIHNvbG8gaG9yYXJpby4KClBvciDDumx0aW1vLCBwYXJhIGVzcGVjaWZpY2FyIG3DoXMgZWwgY2Fzbywgbm9zIGVuZm9jYW1vcyBjb21wbGV0YW1lbnRlIGVuICpBbWVyaWNhbiBBaXJsaW5lcyogeSBzZSBlbmNvbnRyw7MgcXVlIGRpY2hhIGFlcm9sw61uZWEgdHV2byB1biB0b3RhbCBkZSAzNjUgdnVlbG9zIGRlIG1hZHJ1Z2FkYSBhIHVuIMO6bmljbyBkZXN0aW5vLCBlbiBlc3RlIGNhc28gYWwgYWVyb3B1ZXJ0byBkZSBNaWFtaSAoTUlBKS4gRGVzcHXDqXMgc2UgbG9ncsOzIHByZXNlbnRhciBsb3MgYXZpb25lcyBxdWUgdXRpbGl6YSAqQW1lcmljYW4gQWlybGluZXMqLCBwb3IgZWplbXBsbyBlbCBhdmnDs24gY29uIG1heW9yIGNhbnRpZGFkIGRlIGFzaWVudG9zLCBjb24gdW4gdG90YWwgZGUgMzMwLCBlcyB1biAqRml4ZWQgd2luZyBtdWx0aSBlbmdpbmUqIGNvbiB1biBtb3RvciBkZSAqVHVyYm8tZmFuKiwgcG9yIG90cmEgcGFydGUgZWwgYXZpw7NuIGNvbiBtZW5vciBjYW50aWRhZCBkZSBhc2llbnRvcywgY29uIHVuIHRvdGFsIGRlIDIsIGVzIHVuICpGaXhlZCB3aW5nIHNpbmdsZSBlbmdpbmUqIGNvbiB1biBtb3RvciBkZSAqUmVjaXByb2NhdGluZyouCgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij45LiBWaXN1YWxpemFjacOzbiBkZSBEYXRvczwvc3Bhbj4KVmlzdWFsaXphY2lvbmVzIGRlIGxhIGFlcm9sw61uZWEgQW1lcmljYW4gQWlybGluZXMgcGFyYSBsb3MgZWplY3V0aXZvcyBjb24gbGFzIHNpZ3VpZW50ZXMgY2FyYWN0ZXLDrXN0aWNhcy4gRGVudHJvIGRlIGxhcyBhZXJvbMOtbmVhcyBlbCByZXRyYXNvIHRhbnRvIGVuIGxhIGhvcmEgZGUgcGFydGlkYSBjb21vIGVuIGxhIGhvcmEgZGUgbGxlZ2FkYSBhIHN1IGRlc3Rpbm8gdmFuIGdlbmVyYW5kbyBpbmRpY2Fkb3JlcyBuZWdhdGl2b3MuCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlZ1ZWxvcyBjb24gcmV0cmFzbyBlbiBpZGEgeSByZWdyZXNvPC9zcGFuPgpgYGB7cn0KI1Z1ZWxvcyBkZSBBbWVyaWNhbiBBaXJsaW5lcyBxdWUgc2kgdGllbmVuIHJldHJhc28gZW4gbGEgcGFydGlkYSB0YW1iacOpbiB0aWVuZW4gcmV0cmFzbyBlbiBsYSBob3JhIGRlIGxsZWdhZGEuCgp2dWVsb3NfYWEgPC0gZmxpZ2h0cyAlPiUgZmlsdGVyKGNhcnJpZXIgPT0gIkFBIikKcmV0cmFzb3BhcnRpZGEgPC0gbXV0YXRlKHZ1ZWxvc19hYSwgZGVwX2RlbGF5ID0gZGVwX3RpbWUgLSBzY2hlZF9kZXBfdGltZSkKcmV0cmFzb2xsZWdhZGEgPC0gbXV0YXRlKHZ1ZWxvc19hYSwgYXJyX2RlbGF5ID0gYXJyX3RpbWUgLSBzY2hlZF9hcnJfdGltZSkKcGFydGlkYUFBcmV0cmFzb3MgPC0gZmlsdGVyKHJldHJhc29sbGVnYWRhLCBkZXBfZGVsYXkgPiAwKQpsbGVnYWRhQUFyZXRyYXNvcyA8LSBmaWx0ZXIocmV0cmFzb2xsZWdhZGEsIGFycl9kZWxheSA+IDApCkFBcmV0cmFzb3NfbHAgPC0gaW50ZXJzZWN0KHBhcnRpZGFBQXJldHJhc29zLCBsbGVnYWRhQUFyZXRyYXNvcykKZ2dwbG90KEFBcmV0cmFzb3NfbHAsIGFlcyh4ID0gZGVwX2RlbGF5LCB5ID0gYXJyX2RlbGF5KSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4ID0gIlJldHJhc28gZW4gbGEgcGFydGlkYSkiLCB5ID0gIlJldHJhc28gZW4gbGEgbGxlZ2FkYSIpICsKICB0aGVtZV92b2lkKCkKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlRlbmRlbmNpYSBkZSBsYSB0ZW1wZXJhdHVyYTwvc3Bhbj4KYGBge3J9CiNUZW5kZW5jaWEgZGUgbGEgdGVtcGVyYXR1cmEgZHVyYW50ZSBsb3MgcHJpbWVyb3MgMTUgZMOtYXMgZGVsIG1lcyBkZSBFbmVybyBlbiBsb3MgdnVlbG9zIHF1ZSBwYXJ0ZW4gZGVsIGFlcm9wdWVydG8g4oCcTmV3YXJrLCBFV1LigJ0sIHNlIHV0aWxpemEgdW5hIGdyw6FmaWNhIGRlIGzDrW5lYS4KCkVXUmVuZXJvMTUgPC0gd2VhdGhlciAlPiUgZmlsdGVyKG9yaWdpbiA9PSAiRVdSIiwgbW9udGggPT0gMSwgZGF5IDw9IDE1KQpFV1JlbmVybzE1VGVtcCA8LSBzZWxlY3QoRVdSZW5lcm8xNSwgZGF5LCB0ZW1wKQoKRVdSZW5lcm8xNVRlbXBQcm9tIDwtIEVXUmVuZXJvMTVUZW1wICU+JSBncm91cF9ieShkYXkpICU+JSBzdW1tYXJpc2UocHJvbWVkaW90ZW1wID0gbWVhbih0ZW1wLCBuYS5ybT1UUlVFKSkKCmdncGxvdChFV1JlbmVybzE1VGVtcFByb20sIGFlcyh4ID0gZGF5LCB5ID0gcHJvbWVkaW90ZW1wKSkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHggPSAiRGlhIiwgeSA9ICJUZW1wZXJhdHVyYSAowrBDKSIpICsKICB0aGVtZV92b2lkKCkKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlRlbXBlcmF0dXJhIG3DoXMgZnJlY3VlbnRlPC9zcGFuPgpgYGB7cn0KI1Zpc3VhbGl6YSBsYSB0ZW1wZXJhdHVyYSBtw6FzIGZyZWN1ZW50ZSBlbiBsb3MgcHJpbWVyb3MgMTUgZMOtYXMgZGVsIG1lcyBkZSBFbmVybywgdXRpbGl6YXIgdW4gaGlzdHJvZ3JhbWEuCmRhdG9zX2VuZXJvIDwtIGRmICU+JQogIGZpbHRlcihtb250aC54ID09IDEsIGRheS54IDw9IDE1KQoKIyBDb252ZXJ0aXIgYSBjZWxzaXVzCmRhdG9zX2VuZXJvX2NlbHNpdXMgPC0gbXV0YXRlKGRhdG9zX2VuZXJvLCBjZWxzaXVzPSh0ZW1wLTMyKSooNS85KSkKCgojIENyZWFyIGVsIGhpc3RvZ3JhbWEgZGUgdGVtcGVyYXR1cmEKZ2dwbG90KGRhdG9zX2VuZXJvLCBhZXMoeCA9IHRlbXApKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAicHVycGxlIikgKwogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtYSBkZSBUZW1wZXJhdHVyYSBlbiBsb3MgUHJpbWVyb3MgMTUgRGlhcyBkZSBFbmVybyIsCiAgICAgICB4ID0gIlRlbXBlcmF0dXJhIiwgeSA9ICJGcmVjdWVuY2lhIikgKwogIHRoZW1lX21pbmltYWwoKQoKYGBgCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5GYWNldHM8L3NwYW4+CmBgYHtyfQojVXRpbGl6YSBGYWNldHMgcGFyYSBvYnNlcnZhciBjw7NtbyB2YXLDrWEgbGEgdGVtcGVyYXR1cmEgZW4gY2FkYSBtZXMgZW4gw6lsIGhpc3RvZ3JhbWEgZGVsIHB1bnRvIGFudGVyaW9yCgpkYXRvcyA8LSBkZiAlPiUKICBzZWxlY3QobW9udGgueCwgdGVtcCkKCmRhdG9zJHRlbXAgPC0gKGRhdG9zJHRlbXAgLSAzMikgKiA1LzkKCmdncGxvdChkYXRvcywgYWVzKHggPSB0ZW1wKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMywgY29sb3IgPSAid2hpdGUiLCBmaWxsID0gInNreWJsdWUiKSArCiAgZmFjZXRfd3JhcCh+bW9udGgueCwgbnJvdyA9IDMpICsgIyBGYWNldGFyIHBvciBtZXMsIGNvbiAzIHBhbmVsZXMgcG9yIGZpbGEKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbWEgZGUgVGVtcGVyYXR1cmEgcG9yIE1lcyIsCiAgICAgICB4ID0gIlRlbXBlcmF0dXJhIiwgeSA9ICJGcmVjdWVuY2lhIikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+VnVlbG9zIHF1ZSBzYWxpZXJvbiBkZSBOdWV2YSBZb3JrIGVuIGVsIDIwMTM8L3NwYW4+CmBgYHtyfQojU2UgcHJlc2VudGFuIGVsIG7Dum1lcm8gZGUgdnVlbG9zIHF1ZSBzYWxpZXJvbiBkZSBOdWV2YSBZb3JrIGVuIDIwMTMgcG9yIGFlcm9sw61uZWEgeSBjb24gbGFzIDEwIGFlcm9sw61uZXMgY29uIG3DoXMgdnVlbG9zIHNlIHJlYWxpemEgdW5hIGdyw6FmaWNhIGRlIGJhcnJhcy4KdnVlbG9zX2NhbnRpZGFkMiA8LSBmbGlnaHRzICU+JSBzZWxlY3QgKGNhcnJpZXIsIGRlc3QpICU+JSBjb3VudChjYXJyaWVyKQp2dWVsb3Nfb3JkZW4gPC0gYXJyYW5nZSh2dWVsb3NfY2FudGlkYWQyLCBkZXNjKG4pKQpoZWFkKHZ1ZWxvc19vcmRlbiwgMTApCgpncmFmaWNvX2JhcnJhcyA8LSBnZ3Bsb3QoaGVhZCh2dWVsb3Nfb3JkZW4sIDEwKSwgYWVzKHggPSBjYXJyaWVyLCB5ID0gbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGxhYnMoeCA9ICJBZXJvbGluZWEiLCB5ID0gIkNhbnRpZGFkIGRlIFZ1ZWxvcyIpCmdyYWZpY29fYmFycmFzCgpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+R3JhZmljYSBkZSBwaWU8L3NwYW4+CmBgYHtyfQpncmFmaWNvX3Bhc3RlbCA8LSBncmFmaWNvX2JhcnJhcyArCiAgY29vcmRfcG9sYXIoInkiLCBzdGFydCA9IDApCmdyYWZpY29fcGFzdGVsCmBgYAojIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5JbnRlcnByZXRhY2lvbmVzOiBWaXN1YWxpemFjacOzbiBkZSBEYXRvczwvc3Bhbj4KUGFyYSBsYSB2aXN1YWxpemFjacOzbiBkZSBkYXRvcywgcHJpbWVybyBzZSBvYnR1dmllcm9uIGxvcyB2dWVsb3MgZGUgKkFtZXJpY2FuIEFpcmxpbmVzKiBxdWUgc2kgdGllbmVuIHJldHJhc28gZW4gbGEgcGFydGlkYSwgdGFtYmnDqW4gdGllbmVuIHJldHJhc28gZW4gbGEgaG9yYSBkZSBsbGVnYWRhLCBwYXJhIGVzdG8gc2UgaW1wbGVtZW50w7MgdW4gZGlhZ3JhbWEgZGUgZGlzcGVyc2nDs24sIGVsIGN1YWwgbm9zIG11ZXN0cmEgbGEgcmVsYWNpw7NuIGVudHJlIGVsIHJldHJhc28gZGUgcGFydGlkYSB5IGVsIHJldHJhc28gZW4gbGEgbGxlZ2FkYS4gRGVzcHXDqXMgc2Ugb2J0dXZvIGxhIHRlbmRlbmNpYSBlbiB0ZW1wZXJhdHVyYSBkdXJhbnRlIGxvcyBwcmltZXJvcyAxNSBkw61hcyBkZWwgbWVzIGRlIEVuZXJvIGVuIGxvcyB2dWVsb3MgcXVlIHBhcnRlbiBkZWwgYWVyb3B1ZXJ0byDigJxOZXdhcmssIEVXUuKAnSwgcGFyYSBlc3RvIHNlIHV0aWxpemEgdW5hIGdyw6FmaWNhIGRlIGzDrW5lYS4KCkVuIGxhIHNpZ3VpZW50ZSB2aXN1YWxpemFjacOzbiBzZSBvYnRpZW5lIGxhIHRlbXBlcmF0dXJhIG3DoXMgZnJlY3VlbnRlIGVuIGxvcyBwcmltZXJvcyAxNSBkw61hcyBkZWwgbWVzIGRlIEVuZXJvLCBwZXJvIGFob3JhIHV0aWxpemFuZG8gdW4gaGlzdG9ncmFtYSwgZW4gZXN0YSBwYXJ0ZSB1dGlsaXphbW9zIGxhIGNvbnZlcnNpw7NuIGRlICpmYXJlbmhlaXQqIGEgKmNlbHNpdXMqIHkgYSBzaW1wbGUgdmlzdGEgc2UgcG9kcsOtYSBkZXN0YWNhciBxdWUgbGEgdGVtcGVyYXR1cmEgcXVlIG3DoXMgc2UgcmVwaXRlIHNlIGVuY3VlbnRyYSBlbnRyZSBsb3MgNDAgeSA1MCBncmFkb3MgY2VudMOtZ3JhZG9zLCBudWVzdHJhIGVzdGltYWNpw7NuIHBlcnNvbmFsIHNvbiA0NcKwQyBjb24gdW5hIHJlcGV0aWNpw7NuIGNlcmNhIGRlIDQwMDAgdnVlbG9zLgoKRW4gZWwgc2lndWllbnRlIGFuw6FsaXNpcyBzZSB1dGlsaXphICpmYWNldHMqIHBhcmEgb2JzZXJ2YXIgY8OzbW8gdmFyw61hIGxhIHRlbXBlcmF0dXJhIGVuIGNhZGEgbWVzIGVuIMOpbCBoaXN0b2dyYW1hIGRlbCBwdW50byBhbnRlcmlvciwgZGUgaWd1YWwgbWFuZXJhLCBlbiBlc3RhIHBhcnRlIHV0aWxpemFtb3MgbGEgY29udmVyc2nDs24gZGUgKmZhcmVuaGVpdCogYSAqY2Vsc2l1cyosIGNvbW8gcmVzdWx0YWRvIHNlIG9idHV2byB1biBoaXN0b2dyYW1hIGRlIHRlbXBlcmF0dXJhIHBvciBtZXMuCgpDb250aW51YW5kbywgc2UgcHJlc2VudGFuIGVsIG7Dum1lcm8gZGUgdnVlbG9zIHF1ZSBzYWxpZXJvbiBkZSBOdWV2YSBZb3JrIGVuIDIwMTMgcG9yIGFlcm9sw61uZWEsIGRlc3B1w6lzIHNlIG9idGllbmUgbGFzIDEwIGFlcm9sw61uZWFzIGNvbiBtw6FzIHZ1ZWxvcyB5IHNlIHJlYWxpemEgdW5hIGdyw6FmaWNhIGRlIGJhcnJhcyBjb24gZWxsYXMuIFNlIGRlc3RhY2EgcXVlICpVbml0ZWQgQWlybGluZXMqIChVQSkgc2UgZW5jdWVudHJhIGVuIGVsIHByaW1lciBwdWVzdG8gY29uIHVuIHRvdGFsIGRlIDU4LDY2NSB2dWVsb3MsIGEgZXN0YSBsZSBzaWd1ZSAqSmV0Qmx1ZSBBaXJ3YXlzKiAoQjYpIGNvbiB1biB0b3RhbCBkZSA1NCw2MzUgdnVlbG9zLiBFbiBlbCB0ZXJjZXIgcHVlc3RvIHNlIGVuY3VlbnRyYSAqRXhwcmVzc0pldCBBaXJsaW5lcyBJbmMuKiBjb24gdW4gdG90YWwgZGUgNTQsMTczIHZ1ZWxvcy4gRW4gZWwgY3VhcnRvIHB1ZXN0byAqRGVsdGEgQWlyIExpbmVzIEluYy4qIGNvbiB1biB0b3RhbCBkZSA0OCwxMTAgdnVlbG9zLiBFbiBlbCBxdWludG8gcHVlc3RvIHNlIGVuY3VlbnRyYSBwcmVzZW50ZSAqQW1lcmljYW4gQWlybGluZXMqIGNvbiB1biB0b3RhbCBkZSAzMiw3MjkgdnVlbG9zLiBFbiBlbCBwdWVzdG8gbsO6bWVybyBzZWlzLCBzZSBlbmN1ZW50cmEgKkVudm95IEFpciogKE1RKSBjb24gdW4gdG90YWwgZGUgMjYsMzk3IHZ1ZWxvcy4gRW4gc8OpcHRpbW8gbHVnYXIsICpVUyBBaXJ3YXlzIEluYy4qIGNvbiB1biB0b3RhbCBkZSAyMCw1MzYgdnVlbG9zLiBQYXJhIGVsIG9jdGF2byBwdWVzdG8gc2UgZW5jdWVudHJhICpFbmRlYXZvciBBaXIgSW5jLiogKDlFKSBjb24gdW4gdG90YWwgZGUgMTgsNDYwIHZ1ZWxvcy4gRW4gZWwgcGVuw7psdGltbyBwdWVzdG8sIHNlIGludGVncmEgKlNvdXRod2VzdCBBaXJsaW5lcyBDby4qIGNvbiB1biB0b3RhbCBkZSAxMiwyNzUgdnVlbG9zLiBQb3Igw7psdGltbyBsdWdhciBzZSBlbmN1ZW50cmEgKlZpcmdpbiBBbWVyaWNhKiBjb24gdW4gdG90YWwgZGUgNTE2MiB2dWVsb3MuIFBhcmEgcG9kZXIgcmVwcmVzZW50YXIgdG9kb3MgZXN0b3MgbsO6bWVyb3MgZGUgdnVlbG9zIHBvciBhZXJvbMOtbmVhcywgc2UgaW1wbGVtZW50w7MgdW5hIGdyw6FmaWNhIGRlIGJhcnJhcywgaGFjaWVuZG8gcXVlIHNlYSBtw6FzIGF0cmFjdGl2byBsYSBtYW5lcmEgZGUgdmlzdWFsaXphciBlbCByZXN1bHRhZG8uIERlIGlndWFsIG1hbmVyYSwgc2UgcmVhbGl6YSB1biBncmFmaWNvIGRlIHBpZSwgY29uIGxvcyBtaXNtb3MgZGF0b3MgZGVsIFRvcCAxMCBkZSBhZXJvbMOtbmVhcyBjb24gbcOhcyB2dWVsb3MuCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5SZWxhY2nDs24gRmxpZ2h0cyBhbmQgQWlycG9ydHM8L3NwYW4+CmBgYHtyfQojUmVsYWNpb25hIGVsIGRhdGEgZnJhbWUgZmxpZ2h0cyBjb24gZWwgZGF0YSBmcmFtZSBhaXJwb3J0cyBhIHRyYXbDqXMgZGVsIGNhbXBvIGRlc3Rpbm8gwr9jw7NtbyBsb2dyYXIgZXN0YXMgcmVsYWNpb25lcz8KZGYgPC0gbWVyZ2UoZmxpZ2h0cyxhaXJsaW5lcywgYnk9ImNhcnJpZXIiKQpkZiA8LSBsZWZ0X2pvaW4oZGYscGxhbmVzLCBieT0idGFpbG51bSIpCmRmIDwtIGxlZnRfam9pbihkZix3ZWF0aGVyLCBieT1jKCJvcmlnaW4iLCJ0aW1lX2hvdXIiKSkKCiNFc3RhcyByZWxhY2lvbmVzIHNlIGxvZ3JhbiBhIHRyYXbDqXMgZGVsIHVzbyBkZSBmdW5jaW9uZXMgY29tbyBtZXJnZSB5IGxlZnRfam9pbixxdWUgcGVybWl0ZW4gZW5jb250cmEgbGFzIHJlbGFjaW9uZXMgZW50cmUgbG9zIGRpZmVyZW50ZXMgZGF0YSBmcmFtZXMuIEVzdGUgcGFzbyBzZSByZWFsaXrDsyBhbCBpbmljbyBkZWwgcHJvZ3JhbWEgcGFyYSBlbCBkZXNhcnJvbGxvIGRlIGxvcyBvdHJvcyBwdW50b3MgZGUgYW7DoWxpc2lzLgpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+VmlzdWFsaXphY2lvbmVzIEZsaWdodHMgYW5kIEFpcnBvcnRzPC9zcGFuPgoKIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IG9yYW5nZTsiPlZpc3VhbGl6YWNpb25lcyBGbGlnaHRzIDE6IEdyw6FmaWNvIGRlIEJhcnJhczwvc3Bhbj4KQ2FudGlkYWQgZGUgVnVlbG9zIHBvciBBZXJvbMOtbmVhCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IHZ1ZWxvc19jYW50aWRhZDIsIGFlcyh4ID0gY2FycmllciwgeSA9IG4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBsYWJzKHRpdGxlID0gIkNhbnRpZGFkIGRlIFZ1ZWxvcyBwb3IgQWVyb2xpbmVhIiwKICAgICAgIHggPSAiQWVyb2xpbmVhIiwKICAgICAgIHkgPSAiQ2FudGlkYWQgZGUgVnVlbG9zIikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IG9yYW5nZTsiPlZpc3VhbGl6YWNpb25lcyBGbGlnaHRzIDI6IEdyw6FmaWNvIGRlIFBhc3RlbDwvc3Bhbj4KUHJvcG9yY2nDs24gZGUgdnVlbG9zIHBvciBhZXJvbMOtbmVhCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IHZ1ZWxvc19jYW50aWRhZDIsIGFlcyh4ID0gIiIsIHkgPSBuLCBmaWxsID0gY2FycmllcikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAxKSArCiAgY29vcmRfcG9sYXIoInkiKSArCiAgbGFicyh0aXRsZSA9ICJQcm9wb3JjaW9uIGRlIFZ1ZWxvcyBwb3IgQWVyb2xpbmVhIiwKICAgICAgIHggPSBOVUxMLAogICAgICAgeSA9IE5VTEwpICsKICB0aGVtZV92b2lkKCkKYGBgCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBvcmFuZ2U7Ij5WaXN1YWxpemFjaW9uZXMgRmxpZ2h0cyAzOiBHcsOhZmljbyBkZSBCYXJyYXM8L3NwYW4+Ck7Dum1lcm8gZGUgdnVlbG9zIHBvciBtZXMgY29uIHkgc2luIHJldHJhc28KYGBge3J9CmZsaWdodHNfZmlsdGVyZWQgPC0gZmxpZ2h0cyAlPiUKICBtdXRhdGUoZmxpZ2h0cyA9IGlmZWxzZShkZXBfZGVsYXkgPiAwLCAiRGVsYXllZCIsICJOb3QgRGVsYXllZCIpKSAlPiUgCiAgZ3JvdXBfYnkobW9udGgsIGZsaWdodHMpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnQgPSBjb3VudCAvIHN1bShjb3VudCkgKiAxMDApCgpnZ3Bsb3QoZmxpZ2h0c19maWx0ZXJlZCwgYWVzKHggPSBmYWN0b3IobW9udGgpLCB5ID0gY291bnQsIGZpbGwgPSBmbGlnaHRzKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJzdGFjayIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygic2Vhc2hlbGwyIiwgInJvc3licm93bjIiKSkgKwogIGxhYnModGl0bGUgPSAiTsO6bWVybyBkZSB2dWVsb3MgcG9yIG1lcyBjb24geSBzaW4gcmV0cmFzbyIsCiAgICAgICB4ID0gIk1lcyIsCiAgICAgICB5ID0gIk7Dum1lcm8gZGUgdnVlbG9zIiwKICAgICAgIGZpbGwgPSAiUmV0cmFzbyIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogb3JhbmdlOyI+VmlzdWFsaXphY2lvbmVzIEZsaWdodHMgNDogR3LDoWZpY28gZGUgQmFycmFzPC9zcGFuPgpSZXRyYXNvcyBlbiBsYSBwYXJ0aWRhCmBgYHtyfQpnZ3Bsb3QoZmxpZ2h0cywgYWVzKHggPSBkZXBfZGVsYXkpKSArIGdlb21fYmFyKCkgKyBsYWJzKHRpdGxlID0gIlJldHJhc29zIGVuIGxhIFBhcnRpZGEiKQpgYGAKIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+SW50ZXJwcmV0YWNpb25lczogVmlzdWFsaXphY2lvbmVzIEZsaWdodHM8L3NwYW4+CkVuIGVzdGEgcGFydGUgc2UgcmVhbGl6YSB1biBtYXlvciBlbmZvcXVlIGVuIGxhcyB2aXN1YWxpemFjaW9uZXMgZGUgbGEgYmFzZSBkZSBkYXRvcyAqZmxpZ2h0cyosIHBhcmEgZXN0byBvcHRhbW9zIHBvciBncsOhZmljb3MgZGUgYmFycmFzIHkgZGUgcGFzdGVsLiBMYSBwcmltZXJhIHZpc3VhbGl6YWNpw7NuIHF1ZSBzZSBwcmVzZW50YSBlcyBsYSBjYW50aWRhZCBkZSB2dWVsb3MgcG9yIEFlcm9sw61uZWEsIG11eSBzaW1pbGFyIGEgbGEgZGVsIFRvcCAxMCBkZSBhZXJvbMOtbmVhcyBjb24gbcOhcyB2dWVsb3MsIHNpbiBlbWJhcmdvIGVuIGVzdGEgZ3LDoWZpY2EgZGUgYmFycmFzIHNpIHNlIHByZXNlbnRhbiBsYXMgMTYgYWVyb2zDrW5lYXMgcGFydGljaXBhbnRlcyBlbiBsb3MgYWVyb3B1ZXJ0b3MgZGUgTnVldmEgWW9yay4KCkNvbnRpbnVhbW9zIGNvbiB1biBncsOhZmljbyBkZSBwYXN0ZWwsIGVsIGN1w6FsIGVuIHVuIGZvcm1hdG8gYXRyYWN0aXZvIG11ZXN0cmEgbGEgcHJvcG9yY2nDs24gZGUgdnVlbG9zIHBvciBhZXJvbMOtbmVhLCBxdWUgYSBzaW1wbGUgdmlzdGEgc2UgZGVzdGFjYW4gNSBwcmluY2lwYWxlczogKkFtZXJpY2FuIEFpcmxpbmVzIEluYy4qIChBQSksICpVbml0ZWQgQWlyIExpbmVzIEluYy4qIChVQSksICpEZWx0YSBBaXIgTGluZXMgSW5jLiogKERMKSwgKkV4cHJlc3NKZXQgQWlybGluZXMgSW5jKiAoRVYpIHkgKkpldEJsdWUgQWlyd2F5cyogKEI2KS4KCkVuIGVsIHRlcmNlciBncsOhZmljbyBzZSBwcmVzZW50YSBlbCBuw7ptZXJvIGRlIHZ1ZWxvcyBwb3IgbWVzIGNvbiB5IHNpbiByZXRyYXNvLCBlc3RvIHBvciBtZWRpbyBkZSB1bmEgZ3LDoWZpY2EgZGUgYmFycmFzLCBzZSBkZXN0YWNhIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgdnVlbG9zLCBlbiB0b2RvcyBsb3MgbWVzZXMsIG5vIHNlIHJldHJhc2FuLiBQZXJvIHBvciBlamVtcGxvLCBlbiBlbCBtZXMgbsO6bWVybyA3LCBvIHNlYSBKdWxpbywgZXMgZGUgbG9zIG3DoXMgYmFqb3MgY29uIHZ1ZWxvcyBubyByZXRyYXNhZG9zIHkgZGUgbG9zIG3DoXMgYWx0b3MgY29uIHZ1ZWxvcyBjb24gcmV0cmFzbywgZXN0byBzaW4gZHVkYSBub3MgYXl1ZGEgYSBjb25maXJtYXIgdW5hIGRlIG51ZXN0cmFzIGNvbmNsdXNpb25lcyBkZSBwb3IgcXXDqSBsb3MgdnVlbG9zIHNlIHJldHJhc2FuLCBhcXXDrSBoYXkgdW4gY2xhcm8gZWplbXBsbywgcXVlIGxhIHRlbXBvcmFkYSBhbHRhIGRlIHZhY2FjaW9uZXMgZGUgdmVyYW5vLCBlcyB1biBmYWN0b3IgcGFyYSBsb3MgcmV0cmFzb3MgZW4gbG9zIHZ1ZWxvcy4gUG9yIMO6bHRpbW8gYWdyZWdhbW9zIHVuYSBjdWFydGEgdmlzdWFsaXphY2nDs24sIGVuIGVsbGEgc2UgcHJlc2VudGEgbG9zIHJldHJhc29zIGVuIGxhIHBhcnRpZGEuCgojIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogb3JhbmdlOyI+VmlzdWFsaXphY2lvbmVzIEFpcnBvcnRzIDE6IEdyw6FmaWNvIGRlIERpc3BlcnNpw7NuPC9zcGFuPgpSZWxhY2nDs24gZW50cmUgY29vcmRlbmFkYXMgZGUgYWVyb3B1ZXJ0b3MKYGBge3J9CmdncGxvdChhaXJwb3J0cywgYWVzKHggPSBsb24sIHkgPSBsYXQpKSArIGdlb21fcG9pbnQoKSArIGxhYnModGl0bGUgPSAiUmVsYWNpb24gZW50cmUgQ29vcmRlbmFkYXMgZGUgQWVyb3B1ZXJ0b3MiKQpgYGAKIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IG9yYW5nZTsiPlZpc3VhbGl6YWNpb25lcyBBaXJwb3J0cyAyOiBHcsOhZmljbyBkZSBCYXJyYXM8L3NwYW4+CkFxdcOtIGZhbHRhIGVsIHRlcmNlciB2aXN1YWxpemFjacOzbgpgYGB7cn0KdG9wXzEwX2FpcnBvcnRzIDwtIGhlYWQoYWlycG9ydHNbb3JkZXIoLWFpcnBvcnRzJGFsdCksIF0sIDEwKQoKZ2dwbG90KHRvcF8xMF9haXJwb3J0cywgYWVzKHggPSByZW9yZGVyKG5hbWUsIC1hbHQpLCB5ID0gYWx0LCBmaWxsID0gbmFtZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgc2l6ZSA9IDIpICsKICBsYWJzKHRpdGxlID0gIlRvcCAxMCBBZXJvcHVlcnRvcyBNw6FzIEFsdG9zIiwKICAgICAgIHggPSAiQWVyb3B1ZXJ0byIsCiAgICAgICB5ID0gIkFsdHVyYSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAzKSkKYGBgCgoKIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+SW50ZXJwcmV0YWNpb25lczogVmlzdWFsaXphY2lvbmVzIEFpcnBvcnRzPC9zcGFuPgpFbiBsYXMgdmlzdWFsaXphY2lvbmVzIGRlICpBaXJwb3J0cyogc2UgdXRpbGl6YXJvbiB1biBncsOhZmljbyBkZSBkaXNwZXJzacOzbiB5IHVuIGdyw6FmaWNvIGRlIGJhcnJhcy4gRW4gZWwgcHJpbWVybyBzZSBwcmVzZW50YSBsYSByZWxhY2nDs24gZXhpc3RlbnRlIGVudHJlIGxhcyBjb29yZGVuYWRhcyBkZSBsb3MgYWVyb3B1ZXJ0b3MsIHNpIHNlIG1hbnRlbW9zIHVuIGF0YWVuY2nDs24sIHNlIHB1ZWRlIGRlc3RhY2FyIHF1ZSBlbiBsYXMgY29vcmRlbmFkYXMgc2UgcHJlc2VudGEgdW5hIHBhcnRlIGRlIEVzdGFkb3MgVW5pZG9zIHkgbGEgb3RyYSBwYXJ0ZSBzZXLDrWEgZGUgQWxhc2thLiBFbiBsYSBzZWd1bmRhIHZpc3VhbGl6YWNpw7NuLCBjb24gdW5hIGdyw6FmaWNhIGRlIGJhcnJhcywgc2Ugb2J0aWVuZSBlbCBUb3AgMTAgZGUgYWVyb3B1ZXJ0b3MgbcOhcyBhbHRvcywgZW4gZWwgcHJpbWVyIHB1ZXN0byBzZSBlbmN1ZW50cmEgKlRlbGx1cmlkZSosIGVuIGVsIHRvcCA1IHNlIGVuY3VlbnRyYSBlbCAqQnJ5Y2UgQ2FueW9uKiB5IGVuIGVsIHRvcCAxMCAqTWFtbW90aCBZb3NlbWl0IEFpcnBvcnQqLgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij4xMC4gQ29uY2x1c2nDs246IFBhcnRlIDI8L3NwYW4+CkVuIGVzdGEgc2VndW5kYSBwYXJ0ZSBzZSBwdWRpZXJvbiBwb25lciBlbiBwcsOhY3RpY2EgZGlmZXJlbnRlcyBoYWJpbGlkYWRlcyBkZSBwcm9ncmFtYWNpw7NuLCBwcmluY2lwYWxtZW50ZSBhbCBtb21lbnRvIGRlIHJlYWxpemFyIGdyw6FmaWNvcyB5IGFuYWxpemFybG9zLiBTZSBsb2dyw7Mgb2J0ZW5lciBsYSBpbmZvcm1hY2nDs24gZGUgY2FkYSB2dWVsbywgZGUgbG9zIGRlc3Rpbm9zIG3DoXMgY29uY3Vycmlkb3MgeSBoYXN0YSBsYSBkaXZpc8OzbiBkZSB2dWVsb3MgZW4gbG9zIGRpZmVyZW50ZXMgdHVybm9zIGRlIG9mZXJ0YSBkZSB2dWVsb3MuIFNlIGdlbmVyw7MgdW4gZW5mb3F1ZSBlbiAqQW1lcmljYW4gQWlybGluZXMqIHkgY29uIGxhcyB2aXN1YWxpemFjaW9uZXMgZGUgbGEgw7psdGltYSBwYXJ0ZSBkZSBsYSBldmlkZW5jaWEsIHNlIGxvZ3LDsyByZWFsaXphciB1biBhbsOhbGlzaXMgbcOhcyBwcm9mdW5kbyBlbiBsb3MgcmV0cmFzb3MsIGVuY29udHJhciBsYXMgcmVsYWNpb25lcyBlbnRyZSBsYSBiYXNlIGRlIGRhdG9zICpmbGlnaHRzKiB5IGxhIGRlICphaXJwb3J0cyogeSBjw7NtbyBlcyBxdWUgY2FkYSB1bmEgZGUgZWxsYXMgbm9zIHNpcnZlIHBhcmEgZW5jb250cmFyIGRpZmVyZW50ZXMgdmFyaWFibGVzIHBhcmEgZWwgZGVzYXJyb2xsbyBkZSBhbsOhbGlzaXMgZGUgcmV0cmFzb3MuIEVuIGxhcyBpbnRlcnByZXRhY2lvbmVzIGFudGVyaW9yZXMsIHNlIGV4cGxpY2EgZGUgbWFuZXJhIG3DoXMgZGV0YWxsYWRhLCBsb3MgcmVzdWx0YWRvcyBvYnRlbmlkb3MsIHBlcm8gc2luIGR1ZGEsIGVsIHVzbyBkZSB2aXN1YWxpemFjaW9uZXMgZnVlIGNsYXZlIHBhcmEgcG9kZXIgZW50ZW5kZXIgbWVqb3IgY29tbyBmdW5jaW9uYW4gZWwgdGVtYSBkZSBsb3MgdnVlbG9zLCBhZXJvbMOtbmVhcywgZGVzdGlub3MsIGVudHJlIG90cm9zLgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij7Cv1BvciBxdcOpIHNlIHJldHJhc2FuIGxvcyB2dWVsb3MgZW4gTnVldmEgWW9yaz88L3NwYW4+CmBgYHtyfQojQXRyYXNvcyBkZSBvcmlnZW4sIGNhcnJpZXIgeSBtZXMuCmF0cmFzb19wb3Jfb3JpZ2VuIDwtIGZsaWdodHMgJT4lIGdyb3VwX2J5KG9yaWdpbikgJT4lIHN1bW1hcmlzZSh0aWVtcG9fYXRyYXNvX3Byb21lZGlvID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSkpCgphdHJhc29fcG9yX2NhcnJpZXIgPC0gZmxpZ2h0cyAlPiUgZ3JvdXBfYnkoY2FycmllcikgJT4lIHN1bW1hcmlzZSh0aWVtcG9fYXRyYXNvX3Byb21lZGlvID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSkpCgphdHJhc29fcG9yX21lcyA8LSBmbGlnaHRzICU+JSBncm91cF9ieShtb250aCkgJT4lIHN1bW1hcmlzZSh0aWVtcG9fYXRyYXNvX3Byb21lZGlvID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSkpCgojIFJlc3VtZW4gcG9yIG9yaWdlbgpzdW1tYXJ5X2J5X29yaWdpbiA8LSBmbGlnaHRzICU+JSBncm91cF9ieShvcmlnaW4pICU+JSBzdW1tYXJpemUoTWVkaWFfRGVwX0RlbGF5ID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksCk1lZGlhbmFfRGVwX0RlbGF5ID0gbWVkaWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSwgTWluX0RlcF9EZWxheSA9IG1pbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksIE1heF9EZXBfRGVsYXkgPSBtYXgoZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKQoKIyBSZXN1bWVuIHBvciBhZXJvbMOtbmVhCnN1bW1hcnlfYnlfY2FycmllciA8LSBmbGlnaHRzICU+JSBncm91cF9ieShjYXJyaWVyKSAlPiUgc3VtbWFyaXplKE1lZGlhX0RlcF9EZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpLAogICAgTWVkaWFuYV9EZXBfRGVsYXkgPSBtZWRpYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpLAogICAgTWluX0RlcF9EZWxheSA9IG1pbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksCiAgICBNYXhfRGVwX0RlbGF5ID0gbWF4KGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkKCiMgQ2FsY3VsYXIgcmVzdW1lbiBlc3RhZMOtc3RpY28gcG9yIGRlc3Rpbm8Kc3VtbWFyeV9ieV9kZXN0IDwtIGZsaWdodHMgJT4lCiAgZ3JvdXBfYnkoZGVzdCkgJT4lCiAgc3VtbWFyaXplKE1lZGlhX0RlcF9EZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpLAogICAgTWVkaWFuYV9EZXBfRGVsYXkgPSBtZWRpYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpLAogICAgTWluX0RlcF9EZWxheSA9IG1pbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksCiAgICBNYXhfRGVwX0RlbGF5ID0gbWF4KGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkKCiMgQ3JlYXIgdW4gY29uanVudG8gZGUgZGF0b3MgY29tYmluYW5kbyBsYXMgdmFyaWFibGVzIGRlIGludGVyw6lzCm1vZGVsb19kYXRhIDwtIGZsaWdodHMgJT4lCiAgc2VsZWN0KGRlcF9kZWxheSwgY2Fycmllciwgb3JpZ2luLCBtb250aCkKCiMgQWp1c3RhciBlbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwKbW9kZWxvIDwtIGxtKGRlcF9kZWxheSB+IGNhcnJpZXIgKyBvcmlnaW4gKyBtb250aCwgZGF0YSA9IG1vZGVsb19kYXRhKQoKIyBSZXN1bWVuIGRlbCBtb2RlbG8Kc3VtbWFyeShtb2RlbG8pCgpnZ3Bsb3QobW9kZWxvX2RhdGEsIGFlcyh4ID0gYXMuZmFjdG9yKG1vbnRoKSwgeSA9IGRlcF9kZWxheSwgZ3JvdXAgPSAxKSkgKwogIGdlb21fbGluZShzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVhbiIsIGxpbmV0eXBlID0gInNvbGlkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHRpdGxlID0gIlByb21lZGlvIGRlbCBSZXRyYXNvIGRlIFNhbGlkYSBlbiBmdW5jacOzbiBkZWwgTWVzIiwKICAgICAgIHggPSAiTWVzIiwKICAgICAgIHkgPSAiUHJvbWVkaW8gZGUgUmV0cmFzbyBkZSBTYWxpZGEiKQpgYGAKCgpgYGB7cn0KZGZfY29tYmluYWRvIDwtIGJkZ3JhbmRlMiAlPiUKICBtZXJnZSh3ZWF0aGVyKSAKCmRmX2NvbWJpbmFkbyA8LSBhcy5kYXRhLmZyYW1lKGRmX2NvbWJpbmFkbykKYGBgCgpgYGB7cn0KcmVncmVzaW9uIDwtIGxtKGRlcF9kZWxheSB+IHRhaWxudW0gKyBjYXJyaWVyICsgeWVhci54ICsgbW9udGggKyBkYXkgKyBkZXBfdGltZSArIGFycl9kZWxheSArIGZsaWdodCArIG9yaWdpbiArIGRlc3QgKyBhaXJfdGltZSArIGRpc3RhbmNlICArIG1pbnV0ZSAgKyBuYW1lICsgeWVhci55ICsgdHlwZSArIG1vZGVsICsgc3BlZWQgKyBlbmdpbmUgICArIHRlbXAgKyBkZXdwICsgaHVtaWQgKyB3aW5kX2RpciArIHdpbmRfc3BlZWQgKyBwcmVjaXAgKyBwcmVzc3VyZSArIHZpc2liLCBkYXRhPWRmX2NvbWJpbmFkbykKc3VtbWFyeShyZWdyZXNpb24pCmBgYAojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPkFuw6FsaXNpcyBSZXRyYXNvczwvc3Bhbj4KCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+R3LDoWZpY28gLSBBdHJhc28gcHJvbWVkaW8gcG9yIG9yaWdlbjwvc3Bhbj4KR3LDoWZpY28gLSBBdHJhc28gcHJvbWVkaW8gcG9yIG9yaWdlbgpgYGB7cn0KZ2dwbG90KGF0cmFzb19wb3Jfb3JpZ2VuLCBhZXMoeD1vcmlnaW4sIHk9dGllbXBvX2F0cmFzb19wcm9tZWRpbykpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIGZpbGw9ImxpZ2h0Ymx1ZTEiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlPSJBdHJhc28gcHJvbWVkaW8gcG9yIG9yaWdlbiIsIHg9Ik9yaWdlbiIsIHk9IlRpZW1wbyBkZSBhdHJhc28gcHJvbWVkaW8iKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+R3LDoWZpY28gLSBBdHJhc28gcHJvbWVkaW8gcG9yIGNhcnJpZXI8L3NwYW4+Ckdyw6FmaWNvIC0gQXRyYXNvIHByb21lZGlvIHBvciBjYXJyaWVyCmBgYHtyfQpnZ3Bsb3QoYXRyYXNvX3Bvcl9jYXJyaWVyLCBhZXMoeD1jYXJyaWVyLCB5PXRpZW1wb19hdHJhc29fcHJvbWVkaW8pKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBmaWxsPSJjYWRldGJsdWUzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZT0iQXRyYXNvIHByb21lZGlvIHBvciBjYXJyaWVyIiwgeD0iQ2FycmllciIsIHk9IlRpZW1wbyBkZSBhdHJhc28gcHJvbWVkaW8iKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+R3LDoWZpY28gLSBBdHJhc28gcHJvbWVkaW8gcG9yIG1lczwvc3Bhbj4KR3LDoWZpY28gLSBBdHJhc28gcHJvbWVkaW8gcG9yIG1lcwpgYGB7cn0KZ2dwbG90KGF0cmFzb19wb3JfbWVzLCBhZXMoeD1tb250aCwgeT10aWVtcG9fYXRyYXNvX3Byb21lZGlvKSkgKwogIGdlb21fbGluZShncm91cD0xLCBjb2xvdXI9ImRhcmtzbGF0ZWdyYXkzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZT0iQXRyYXNvIHByb21lZGlvIHBvciBtZXMiLCB4PSJNZXMiLCB5PSJUaWVtcG8gZGUgYXRyYXNvIHByb21lZGlvIikKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPkludGVycHJldGFjaW9uZXM6IFJldHJhc29zPC9zcGFuPgpBY2VyY8OhbmRvbm9zIG3DoXMgaGFjaWEgZWwgYW7DoWxpc2lzIGZpbmFsIGRlbCBwb3IgcXXDqSBsb3MgdnVlbG9zIHNlIHJldHJhc2FuIGVuIGxvcyBhZXJvcHVlcnRvcyBkZSBOdWV2YSBZb3JrLCBzZSBvYnR1dm8gZWwgYXRyYXNvIGVuIHRpZXBvIHByb21lZGlvIHBvciBhZXJvbMOtbmVhLCBvcmlnZW4geSBtZXMuCkVuIGxhIGdyw6FmaWNhIGRlIGJhcnJhcyBzZSBtdWVzdHJhIGVsIHByaW1lciBhbsOhbGlzaXMgZGUgYXRyYXNvIHByb21lZGlvIHBvciBvcmlnZW4sIGRhbmRvIGNvbW8gcmVzdWx0YWRvIHF1ZSBlbCBhZXJvcHVlcnRvICoqRVdSKiogZXMgZWwgcXVlIGN1ZW50YSBjb24gdW4gbWF5b3IgYXRyYXNvIHByb21lZGlvLCBjb24gdW4gdG90YWwgZGVsIDE1LjExIG1pbnV0b3MgZGUgYXRyYXNvLCBhIGVzdGUgbGUgc2lndWUgKipKSyoqIGNvbiB1biB0b3RhbCBkZSAxMi4xMSBtaW51dG9zIGRlIGF0cmFzbywgeSBjb24gZWwgbWVub3IgcHJvbWVkaW8gc2UgZW5jdWVudHJhICoqTEdBKiogY29uIHVuIHRvdGFsIGRlIDEwLjM1IG1pbnRvcyBkZSBhdHJhc28uIAoKRW4gbGEgc2VndW5kYSBncsOhZmljYSBkZSBiYXJyYXMgc2UgcHJlc2VudGEgZWwgYXRyYXNvIHByb21lZGlvIHBvciBjYXJyaWVyLCBkYW5kbyBjb21vIHJlc3VsdGFkb3MgcHJpbmNpcGFsZXMgcXVlICpGcm9udGllciBBaXJsaW5lcyBJbmMuKiAoRjkpIGVzIGxhIGFlcm9sw61uZWEgcXVlIGN1ZW50YSBjb24gdW4gbWF5b3IgYXRyYXNvIHByb21lZGlvIGRlIGRlIDIwLjIyIG1pbnV0b3MsIGVuIGNhbWJpbyBsYSBhZXJvbMOtbmVhIGNvbiBlbCBtZW5vciBhdHJhc28gcHJvbWVkaW8gZXMgKlVTIEFpcndheXMgSW5jLiogY29uIHVuIHRvdGFsIGRlIDMuNzggbWludXRvcyBkZSBhdHJhc28uCgpQYXJhIGxhIHRlcmNlcmEgZ3LDoWZpY2EgZGUgbMOtbmVhLCBzZSBwcmVzZW50YSBlbCBhdHJhc28gcHJvbWVkaW8gcG9yIG1lcywgZW4gZG9uZGUgc2UgZGVzdGFjYSBxdWUgZWwgbWVzIGRlIEp1bGlvIGVzIGVsIHF1ZSBjdWVudGEgY29uIHVuIG1heW9yIHRpZW1wbyBkZSBhdHJhc28gZW4gcHJvbWVkaW8sIGNvbiB1biB0b3RhbCBkZSAyMS43MyBtaW51dG9zLiBFbiBzZWd1bmRvIGx1Z2FyIHNlIGVuY3VlbnRyYSBKdW5pbywgY29uIHVuIHRpZW1wbyBkZSBhdHJhc28gZW4gcHJvbWVkaW8gZGUgMjAuODUgbWludXRvcywgeSBlbiB0ZXJjZXIgbHVnYXIgc2UgZW5jdWVudHJhIGRpY2llbWJyZSwgY29uIHVuIHRvdGFsIGRlIGF0cmFzbyBwcm9tZWRpbyBkZSAxNi41NyBtaW51dG9zLiBFbCBhdHJhc28gcHJvbWVkaW8gZW4gZWwgbWVzLCBzZSBwdWVkZSBkZWJlciBhbCBwcmluY2lwYWwgZmFjdG9yIGRlIHRlbXBvcmFkYXMgYWx0YXMgdmFjYWNpb25hbGVzLgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5SZXRyYXNvIHBvciB0aXBvIGRlIGF2acOzbjwvc3Bhbj4KUmV0cmFzbyBwb3IgdGlwbyBkZSBhdmnDs24KYGBge3J9CiMgUmV0cmFzbyBwb3IgdGlwbyBkZSBhdmnDs24KcmV0cmFzb19wb3JfYXZpb24gPC0gZmxpZ2h0cyAlPiUKICBsZWZ0X2pvaW4ocGxhbmVzLCBieSA9ICJ0YWlsbnVtIikgJT4lCiAgZ3JvdXBfYnkodHlwZSkgJT4lCiAgc3VtbWFyaXplKGF2Z19kZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKQoKIyBHcsOhZmljbyBkZSBiYXJyYXMgcGFyYSByZXRyYXNvIHBvciB0aXBvIGRlIGF2acOzbgpnZ3Bsb3QocmV0cmFzb19wb3JfYXZpb24sIGFlcyh4ID0gdHlwZSwgeSA9IGF2Z19kZWxheSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJza3libHVlIikgKwogIGxhYnModGl0bGUgPSAiUmV0cmFzbyBQcm9tZWRpbyBwb3IgVGlwbyBkZSBBdmnDs24iLAogICAgICAgeCA9ICJUaXBvIGRlIEF2acOzbiIsCiAgICAgICB5ID0gIlJldHJhc28gUHJvbWVkaW8iKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+UmV0cmFzbyBwb3IgZMOtYSBkZSBsYSBzZW1hbmE8L3NwYW4+ClJldHJhc28gcG9yIGTDrWEgZGUgbGEgc2VtYW5hCmBgYHtyfQojIFJldHJhc28gcG9yIGTDrWEgZGUgbGEgc2VtYW5hCnJldHJhc29fcG9yX2RpYV9zZW1hbmEgPC0gZmxpZ2h0cyAlPiUKICBtdXRhdGUod2Vla2RheSA9IHdlZWtkYXlzKGFzLkRhdGUocGFzdGUoeWVhciwgbW9udGgsIGRheSwgc2VwID0gIi0iKSkpKSAlPiUKICBncm91cF9ieSh3ZWVrZGF5KSAlPiUKICBzdW1tYXJpemUoYXZnX2RlbGF5ID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSkpCgojIE9yZGVuYXIgZMOtYXMgZGUgbGEgc2VtYW5hCnJldHJhc29fcG9yX2RpYV9zZW1hbmEkd2Vla2RheSA8LSBmYWN0b3IocmV0cmFzb19wb3JfZGlhX3NlbWFuYSR3ZWVrZGF5LCBsZXZlbHMgPSBjKCJNb25kYXkiLCAiVHVlc2RheSIsICJXZWRuZXNkYXkiLCAiVGh1cnNkYXkiLCAiRnJpZGF5IiwgIlNhdHVyZGF5IiwgIlN1bmRheSIpKQoKIyBHcsOhZmljbyBkZSBiYXJyYXMgcGFyYSByZXRyYXNvIHBvciBkw61hIGRlIGxhIHNlbWFuYQpnZ3Bsb3QocmV0cmFzb19wb3JfZGlhX3NlbWFuYSwgYWVzKHggPSB3ZWVrZGF5LCB5ID0gYXZnX2RlbGF5KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gImJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJSZXRyYXNvIFByb21lZGlvIHBvciBEaWEgZGUgbGEgU2VtYW5hIiwKICAgICAgIHggPSAiRGlhIGRlIGxhIFNlbWFuYSIsCiAgICAgICB5ID0gIlJldHJhc28gUHJvbWVkaW8iKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQoKYGBgCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5SZXRyYXNvIHBvciBob3JhIGRlbCBkw61hPC9zcGFuPgpSZXRyYXNvIHBvciBob3JhIGRlbCBkw61hCmBgYHtyfQojIFJldHJhc28gcG9yIGhvcmEgZGVsIGTDrWEKZmxpZ2h0cyRob3VyIDwtIGFzLmludGVnZXIoZmxpZ2h0cyRob3VyKSAKbWVhbl9kZWxheV9wZXJfaG91ciA8LSBhZ2dyZWdhdGUoZGVwX2RlbGF5IH4gaG91ciwgZmxpZ2h0cywgbWVhbikKZ2dwbG90KGRhdGEgPSBtZWFuX2RlbGF5X3Blcl9ob3VyLCBhZXMoeCA9IGhvdXIsIHkgPSBkZXBfZGVsYXkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIpICsKICBsYWJzKHggPSAiSG9yYSBkZWwgZMOtYSIsIHkgPSAiUmV0cmFzbyBwcm9tZWRpbyAobWludXRvcykiLCAKICAgICAgIHRpdGxlID0gIlJldHJhc28gcHJvbWVkaW8gcG9yIGhvcmEgZGVsIGTDrWEiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPkludGVycHJldGFjaW9uZXM6IFJldHJhc29zPC9zcGFuPgpFbiBlbCBhbsOhbGlzaXMgYW50ZXJpb3IsIGFob3JhIHNlIHRvbWEgZW4gY3VlbnRhIGVsIHJldHJhc28gcHJvbWVkaW8gcG9yIHRpcG8gZGUgYXZpw7NuLCBlbCByZXRyYXNvIHBvciBkw61hIGRlIGxhIHNlbWFuYSwgeSByZXRyYXNvIHBvciBob3JhIGRlbCBkw61hLiAKCkVsIHByaW1lciByZXRyYXNvIGFuYWxpemFkbyBmdWUgcG9yIGVsIHRpcG8gZGUgYXZpw7NuLCBlbCBjdWFsIG5vcyBwcmVzZW50YSBxdWUgbG9zIHRpcG9zIGRlIGF2aW9uZXMgKlJvdG9yY3JhZnQqIHNvbiBsb3MgcXVlIGN1ZW50YW4gY29uIHVuIG1heW9yIGF0cmFzbyBwcm9tZWRpbywgZGFuZG8gY29tbyByZXN1bHRhZG8gdW4gdG90YWwgZGUgMTQuMTcgbWludXRvcyBkZSByZXRyYXNvLiBBIGVzdGUgbGUgc2lndWUgbG9zIHRpcG9zIGRlIGF2aW9uZXMgZGUgKkZpeGVkIHdpbmcgbXVsdGkgZW5naW5lKiBjb24gdW4gdG90YWwgZGUgMTMuMTkgbWludXRvcyBkZSByZXRyYXNvLiBQb3Igw7psdGltbyBlbCB0aXBvIGRlIGF2acOzbiBjb24gbWVub3IgY2FudGlkYWQgZGUgcmV0cmFzbyBwcm9tZWRpbyBlcyBlbCAqRml4ZWQgd2luZyBzaW5nbGUgZW5naW5lKiBjb24gdW4gdG90YWwgZGUgMTAuNTAgbWludXRvcy4gQSBwZXNhciBkZSBxdWUgZXhpc3RlbiBlc29zIHRyZXMgdGlwb3MgZGUgYXZpb25lcywgbGEgZ3LDoWZpY2EgdGFtYmnDqW4gbm9zIG11ZXN0cmEgbG9zIE5BIGNvbiB1biB0b3RhbCBkZSA5LjUgbWludXRvcyBkZSBhdHJhc28gcHJvbWVkaW8uCgpFbiBsYSBzZWd1bmRhIGdyw6FmaWNhIHNlIHByZXNlbnRhIGVsIGF0cmFzbyBwcm9tZWRpbyBwb3IgZMOtYSBkZSBsYSBzZW1hbmEsIGRvbmRlIHNlIGRlc3RhY2EgcXVlIGxvcyBqdWV2ZXMgc29uIGxvcyBkw61hcyBjb24gbWF5b3IgYXRyYXNvIHByb21lZGlvLCBjb24gdW4gdG90YWwgZGUgMTYuMTUgbWludXRvcy4gUG9yIG90cmEgcGFydGUsIGVsIGTDrWEgY29uIG1lbm9yIGF0cmFzbyBwcm9tZWRpbyBzb24gbG9zIHPDoWJhZG9zLCBjb24gdW4gdG90YWwgZGUgNy42NSBtaW51dG9zLgoKRW4gbGEgdGVyY2VyIGdyw6FmaWNhIHNlIG11ZXN0cmEgZWwgYXRyYXNvIHByb21lZGlvIHBvciBob3JhIGRlbCBkw61hLCBlbiBsYSBjdcOhbCBlcyB2aXNpYmxlIHVuIGNyZWNpbWllbnRvIGVuIHJldHJhc29zIGVudHJlIGxvcyBob3JhcmlvcyBkZSBsYXMgMTU6MDAgeSAyMDowMCBob3JhcywgZGVzcHXDqXMgZGUgZXN0byBkaXNtaW51eWUgcGFyYSBsb3MgdnVlbG9zIGRlIGxhcyA1OjAwIGEgMTA6MDAgaG9yYXMuCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPkFuw6FsaXNpcyBkZWwgQ2xpbWE8L3NwYW4+CiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+UmV0cmFzbyBwcm9tZWRpbyBwb3IgaHVtZWRhZCByZWxhdGl2YTwvc3Bhbj4KYGBge3Igd2FybmluZz1GQUxTRX0KZmxpZ2h0c193ZWF0aGVyPC0gbWVyZ2Uod2VhdGhlciwgZmxpZ2h0cykKZmxpZ2h0c193ZWF0aGVyICU+JQogIGdyb3VwX2J5KGh1bWlkKSAlPiUKICBzdW1tYXJpc2UoZGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gaHVtaWQsIHkgPSBkZWxheSkpICsKICBsYWJzKHggPSAiSHVtZWRhZCByZWxhdGl2YSIsIHkgPSAiUmV0cmFzbyBwcm9tZWRpbyAobWludXRvcykiLCBmaWxsID0gIkFlb3JvcHVlcnRvIikgKwogIGdndGl0bGUoIlJldHJhc28gcHJvbWVkaW8gcG9yIGh1bWVkYWQgcmVsYXRpdmEiKSArCiAgZ2VvbV9saW5lKCkgKyBnZW9tX3BvaW50KCkrIHRoZW1lKHBsb3QudGl0bGU9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUpKQpgYGAKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5SZXRyYXNvIHByb21lZGlvIHBvciB0ZW1wZXJhdHVyYTwvc3Bhbj4KYGBge3Igd2FybmluZz1GQUxTRX0KZmxpZ2h0c193ZWF0aGVyICU+JQogIGdyb3VwX2J5KHRlbXApICU+JQogIHN1bW1hcmlzZShkZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB0ZW1wLCB5ID0gZGVsYXkpKSArCiAgbGFicyh4ID0gIlRlbXBlcmF0dXJhIiwgeSA9ICJSZXRyYXNvIHByb21lZGlvIChtaW51dG9zKSIsIGZpbGwgPSAiQWVvcm9wdWVydG8iKSArCiAgZ2d0aXRsZSgiUmV0cmFzbyBwcm9tZWRpbyBwb3IgVGVtcGVyYXR1cmEiKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aCgpKyB0aGVtZShwbG90LnRpdGxlPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41KSkKYGBgCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+UmV0cmFzbyBwcm9tZWRpbyBwb3IgdmVsb2NpZGFkIGRlbCB2aWVudG88L3NwYW4+CmBgYHtyIHdhcm5pbmc9RkFMU0V9CmZsaWdodHNfd2VhdGhlciAlPiUKICBncm91cF9ieSh3aW5kX3NwZWVkKSAlPiUKICBzdW1tYXJpc2UoZGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gd2luZF9zcGVlZCwgeSA9IGRlbGF5KSkgKwogIGxhYnMoeCA9ICJWZWxvY2lkYWQgZGVsIFZpZW50byIsIHkgPSAiUmV0cmFzbyBwcm9tZWRpbyAobWludXRvcykiKSArCiAgZ2d0aXRsZSgiUmV0cmFzbyBwcm9tZWRpbyBwb3IgVmVsb2NpZGFkIGRlbCBWaWVudG8iKSArCiAgZ2VvbV9zbW9vdGgoKSsgdGhlbWUocGxvdC50aXRsZT0gZWxlbWVudF90ZXh0KGhqdXN0PTAuNSkpCmBgYAojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlJldHJhc28gcHJvbWVkaW8gcG9yIGRpcmVjY2nDs24gZGVsIHZpZW50bzwvc3Bhbj4KYGBge3Igd2FybmluZz1GQUxTRX0KZmxpZ2h0c193ZWF0aGVyICU+JQogIGdyb3VwX2J5KHdpbmRfZGlyKSAlPiUKICBzdW1tYXJpc2UoZGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gd2luZF9kaXIsIHkgPSBkZWxheSkpICsKICBsYWJzKHggPSAiRGlyZWNjacOzbiBkZWwgVmllbnRvIiwgeSA9ICJSZXRyYXNvIHByb21lZGlvIChtaW51dG9zKSIpICsKICBnZ3RpdGxlKCJSZXRyYXNvIHByb21lZGlvIHBvciBEaXJlY2Npw7NuIGRlbCBWaWVudG8iKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsgCiAgdGhlbWUocGxvdC50aXRsZT1lbGVtZW50X3RleHQoaGp1c3Q9MC41KSkKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlJldHJhc28gcHJvbWVkaW8gcG9yIHZpc2liaWxpZGFkIGVuIGVsIGFpcmU8L3NwYW4+CmBgYHtyIHdhcm5pbmc9RkFMU0V9CmZsaWdodHNfd2VhdGhlciAlPiUKICBncm91cF9ieSh2aXNpYikgJT4lCiAgc3VtbWFyaXNlKGRlbGF5ID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSkpICU+JQogIGdncGxvdChhZXMoeCA9IHZpc2liLCB5ID0gZGVsYXkpKSArCiAgbGFicyh4ID0gIlZpc2liaWxpZGFkIiwgeSA9ICJSZXRyYXNvIHByb21lZGlvIChtaW51dG9zKSIpICsKICBnZ3RpdGxlKCJSZXRyYXNvIHByb21lZGlvIHBvciBWaXNpYmlsaWRhZCBlbiBlbCBhaXJlIikgKwogIGdlb21fbGluZSgpICsgCiAgdGhlbWUocGxvdC50aXRsZT1lbGVtZW50X3RleHQoaGp1c3Q9MC41KSkKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPkludGVycHJldGFjaW9uZXM6IEFuw6FsaXNpcyBkZWwgQ2xpbWE8L3NwYW4+CkVuIGVsIGFuw6FsaXNpcyBkZWwgY2xpbWEsIHByaW1lcm8gc2Ugb2J0dXZvIGVsIHJldHJhc28gcHJvbWVkaW8gcG9yIGh1bWVkYWQgcmVsYXRpdmEsIGVuIGRvbmRlIG11ZXN0cmEgcXVlIGhheSAgYXRyYXNvcyBkZSB1bmEgbWF5b3IgY2FudGlkYWQgZGUgdGllbXBvIGVudHJlIGVsIDc1JSB5IDEwMCUgZGUgbGEgaHVtZWRhZCByZWxhdGl2YS4gRGVzcHXDqXMsIHNlIG9idHV2byBlbCBhdHJhc28gcHJvbWVkaW8gcG9yIGxhIHRlbXBlcmF0dXJhLCBlbiBlc3RlIGdyw6FmaWNvIHNlIGRlc3RhY2EgcXVlIHB1ZWRlIHZhcmlhciBtdWNobyBsYSB0ZW1wZXJhdHVyYSB5IGVsIHRpZW1wbyBxdWUgc2UgcmV0cmFzYSBsb3MgdnVlbG9zLiAKCkVsIHRlcmNlciBhbsOhbGlzaXMgdXRpbGl6YSBlbCByZXRyYXNvIHByb21lZGlvIHBvciB2ZWxvY2lkYWQgZGVsIHZpZW50bywgZW4gZG9uZGUgc2kgbGEgdmVsb2NpZGFkIHNlIGVuY3VlbnRyYSBlbnRyZSBlbCAzMCB5IDQwLCBleGlzdGUgbGEgcHJvYmFiaWxpZGFkIGRlIHF1ZSBsb3MgYXRyYXNvcyBzZWFuIG1heW9yZXMgYSBsb3MgMjAgbWludXRvcy4gRGVzcHXDqXMgc2Ugb2J0dXZvIGVsIGF0cmFzbyBwcm9tZWRpbyBwb3IgZGlyZWNjacOzbiBkZWwgdmllbnRvLCBxdWUgZ3JhY2lhcyBhIGxhIHZpc3VhbGl6YWNpw7NuIGRlIGxhIGdyw6FmaWNhIGRlIGJhcnJhcywgc2kgbGEgZGlyZWNjacOzbiBkZWwgdmllbnRvIHNlIGVuY3VlbnRyYSBlbiB1biBlc3RpbWFkbyBlbnRyZSA4MCB5IDE1MCwgZXhpc3RlIHVuIGF0cmFzbyBwcm9tZWRpbyBtYXlvci4gUG9yIMO6bHRpbW8gc2Ugb2J0dXZvIGVsIGF0cmFzbyBwcm9tZWRpbyBwb3IgbGEgdmlzaWJpbGlkYWQgZW4gZWwgYWlyZSwgZW4gZWwgcXVlIGhhY2llbmRvIHVuIGVzdGltYWRvLCBzaSBsYSB2aXNpYmlsaWRhZCBzZSBlbmN1bmV0cmEgZW50cmUgMC4wIHkgMi41LCBsb3MgdnVlbG9zIHRpZW5kZW4gYSB0ZW5lciB1biBtYXlvciBhdHJhc28gcHJvbWVkaW8sIGRlIGFscmVkZWRvciBkZSAzMCBhIDUwIG1pbnV0b3MuCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPkNvbmNsdXNpb25lcyBkZSByZXRyYXNvczwvc3Bhbj4KRW4gZXN0YSBhY3RpdmlkYWQgZGUgbWFuZXJhIGdydXBhbCwgZGV0ZXJtaW5hbW9zIGVsIHBvciBxdcOpIHNlIHJldHJhc2FuIGxvcyB2dWVsb3MgZW4gbG9zIGFlcm9wdWVydG9zIGRlIE51ZXZhIFlvcmsuIFNlIG9idHV2byBpbmZvcm1hY2nDs24gbXV5IGludGVyZXNhbnRlIGEgdHJhdsOpcyBkZSBsb3MgZGlmZXJlbnRlcyBhbsOhbGlzaXMgZGUgbGFzIGJhc2VzIGRlIGRhdG9zLiAgCgpFbiBwcmltZXJhIGluc3RhbmNpYSBzZSBvYnR1dm8gZWwgYXRyYXNvIHBvciBvcmlnZW4sIGVuIGRvbmRlIG5vcyBtb3N0csOzIGVsIHRpZW1wbyBkZSBhdHJhc28gcHJvbWVkaW8gZW4gY2FkYSB1bm8gZGUgbG9zIHRyZXMgYWVyb3B1ZXJ0b3MgZGlzcG9uaWJsZXMsIGRhbmRvIGNvbW8gcmVzdWx0YWRvIHF1ZSBlbCBhZXJvcHVlcnRvIGNvbiBtYXlvciBhdHJhc28gZW4gcHJvbWVkaW8gZXMgZWwgKipFV1IqKi4gRWwgc2lndWllbnRlIGFuw6FsaXNpcyBmdWUgZWwgYXRyYXNvIHBvciBDYXJyaWVyLCBlbiBkb25kZSBzZSBvYnR1dm8gZWwgYXRyYXNvIHByb21lZGlvIHBvciBhZXJvbMOtbmVhOyA5RSAoKkVuZGV2b2lyIEFpciopIG9idHV2byBlbCBtYXlvciByZXN1bHRhZG8gZW4gYXRyYXNvIHByb21lZGlvLiAgCgpEZXNww7plcyBub3MgZW5mb2NhbW9zIG3DoXMgZW4gZWwgbWVzIGVuIGVsIHF1ZSBoYWLDrWEgbWF5b3JlcyByZXRyYXNvcywgZGFuZG8gY29tbyByZXN1bHRhZG8gdGVtcG9yYWRhcyBhbHRhcyBwYXJhIHZpYWphciwgcG9yIGVqZW1wbG8gZW4gcHJpbWVyIGx1Z2FyIGRlbCBtZXMgY29uIG1heW9yIHJldHJhc28gc2UgZW5jb250cmFiYSBKdWxpbywgYXByb3hpbWFkYW1lbnRlIHNvbG8gcG9yIHVuIG1pbnV0byBtYXlvciBhIEp1bmlvLCB5IGEgZXN0ZSBsZSBzZWd1w61hIGRpY2llbWJyZSBlbiBlbCB0ZXJjZXIgcHVlc3RvLiBTaSB0b21hbW9zIGVuIGN1ZW50YSBxdWUgbXVjaGFzIHBlcnNvbmFzIHZpYWphbiBlbiBkaWNoYXMgdGVtcG9yYWRvcyBwb3IgZWwgdmVyYW5vIHkgbGFzIGZpZXN0YXMgZGVjZW1icmluYXMsIGxvIHF1ZSBvY2FzaW9uYSBxdWUgaGF5YSBtYXlvciBjYW50aWRhZCBkZSBwZXJzb25hcyBlbiBtb3ZpbGlkYWQgZW4gYWVyb3B1ZXJ0b3MsIHBvZHLDrWEgc2VyIHVuIGltcG9ydGFudGUgZmFjdG9yIGRlbCBwb3IgcXXDqSBsb3MgdnVlbG9zIHNlIHJldHJhc2FuIG3DoXMgZW4gZGljaGFzIHRlbXBvcmFkYXMuICAKClJlYWxpemFtb3MgdW4gbW9kZWxvIGRlbCBwcm9tZWRpbyBkZWwgcmV0cmFzbyBkZSBzYWxpZGEgZW4gZnVuY2nDs24gZGVsIG1lcywgbG8gcXVlIG5vcyBtdWVzdHJhIGNvbiBtYXlvciBjbGFyaWRhZCwgcXVlIGxhcyB0ZW1wb3JhZGFzIGFsdGFzIGRlIHZpYWplcyBzb24gdW4gZmFjdG9yIHF1ZSBpbmZsdXllIGVuIGxvcyByZXRyYXNvcyBnZW5lcmFkb3MgZW4gbG9zIGFlcm9wdWVydG9zIGRlIE51ZXZhIFlvcmsuCgpQb3Igw7psdGltbyBzZSByZWFsaXphcm9uIGxvcyBhbsOhbGlzaXMgZGVsIGNsaW1hLCBjb25zaWRlcmFuZG8gZGlmZXJlbnRlcyB2YXJpYWJsZXMsIHlhIHNlYSBsYSBkaXJlY2Npw7NuIGRlIHZpZW50bywgc3UgdmlzaWJpbGlkYWQsIGxhIGh1bWVkYWQgcmVsYXRpdmEgeSBsYSB0ZW1wZXJhdHVyYSwgZW4gbG9zIGN1w6FsZXMgc2Ugbm9zIG11ZXN0cmEgcXVlIHNpbiBkdWRhIHNvbiB1biBmYWN0b3IgaW1wb3J0YW50ZSBhIGNvbnNpZGVyYXIgZGVudHJvIGRlbCBwb3IgcXXDqSBsb3MgdnVlbG9zIHNlIHJldHJhc2FuLCBlc3RlIHB1bnRvIGVzIGV4cGxpY2FkbyBjb24gbWF5b3IgZGV0ZW5pbWllbnRvIGVuIGxhcyBpbnRlcnByZXRhY2lvbmVzIGFudGVyaW9yZXMuCgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5FamVyY2ljaW9zIGRlIGV2aWRlbmNpYSBlbiBjbGFzZTwvc3Bhbj4gCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+RXh0cmEgMS4gQ29uc3VsdGEgbGEgZXN0cnVjdHVyYSBkZSAiZmxpZ2h0cyI8L3NwYW4+IApgYGB7cn0Kc3RyKGZsaWdodHMpCiMgaW50OiBlbnRlcm8gKHNpbiBkZWNpbWFsZXMpCiMgbnVtOiBudW3DqXJpY28gKGNvbiBkZWNpbWFsZXMpCiMgY2hyOiBjYXJhY3TDqXIgKGxldHJhcykKIyBEYXRlOiBmZWNoYSAoZW4gUiB2YSBhw7FvLW1lcy1kw61hKQojIFBPU0lYY3Q6IGZvcm1hdG8gZmVjaGEgeSBob3JhCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5FeHRyYSAyLiDCv0N1w6FsIGVzIGxhIGNsYXNlIGRlICJmbGlnaHRzIiB5IHF1ZSBzaWduaWZpY2E/PC9zcGFuPiAKYGBge3J9CmNsYXNzKGZsaWdodHMpCgojIExhcyA1IGNsYXNlcyBkZSBvYmpldG9zIHNvbjoKIyAxLiBudW1lcmljOiBOw7ptZXJvIHJlYWwgbyBkZWNpbWFsZXMuCiMgMi4gaW50ZWdlcjogTsO6bXdlb3MgZW50ZXJvcwojIDMuIGNvbXBsZXg6IE7Dum1lcm9zIGNvbXBsZWpvcwojIDQuIGNoYXJhY3RlcjogY2Fyw6FjdGVyZXMKIyA1LiBsb2dpY2FsOiBUUlVFIE8gRkFMU0UKCiMgTGFzIDQgY2xhc2VzIGRlIG9iamV0b3MgY29tcHVlc3RvcyBzb246CiMgMS4gbGlzdDogbGlzdGEKIyAyLiBtYXRyaXg6IG1hdHJpegojIDMuIGFycmF5OiBjb2xlY2Npw7NuIGRlIG9iamV0b3MKIyA0LiBkYXRhLmZyYW1lOiBiYXNlIGRlIGRhdG9zCgpgYGAKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5FeHRyYSAzLiDCv0N1w6FudGFzIGNvbHVtbmFzIHkgcmVuZ2xvbmVzIHRpZW5lICJmbGlnaHRzIj8gwr9DdcOhbCBlcyBzdSBkaW1lbnNpw7NuPzwvc3Bhbj4gCmBgYHtyfQojIE7Dum1lcm8gZGUgY29sdW1uYXMKbmNvbChmbGlnaHRzKQojIE7Dum1lcm8gZGUgcmVuZ2xvbmVzCm5yb3coZmxpZ2h0cykKIyBEaW1lbnNpw7NuCmRpbShmbGlnaHRzKQpgYGAKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5FeHRyYSA0LiBNdWVzdHJhIGxvcyBwcmltZXJvcyA2IHJlbmdsb25lcyBkZSAiZmxpZ2h0cyIuIFRhbWJpw6luIGxvcyDDumx0aW1vcyA2Ljwvc3Bhbj4gCmBgYHtyfQpoZWFkKGZsaWdodHMpCnRhaWwoZmxpZ2h0cykKIyBTaSBxdWlzaWVyYW1vcyA3IHJlbmdsb25lczogaGVhZChmbGlnaHRzLDcpCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5Db21wcm9taXNvIMOpdGljbyB5IGNpdWRhZGFubzwvc3Bhbj4gCkVsIHZhbG9yIGRlIGxhIGludGVncmlkYWQsIHNlZ8O6biBsYXMgTmFjaW9uZXMgVW5pZGFzLCB2aWVuZSBkZSBsYSBwcsOhY3RpY2EgZGUgc2VyIHVuYSBwZXJzb25hIGhvbmVzdGEsIHF1ZSBzZSBhZGhpZXJlIGEgc3VzIHZhbG9yZXMgeSBxdWUgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGVzIHNpc3RlbcOhdGljYW1lbnRlIHBvc2l0aXZhLiBMYSBpbnRlZ3JpZGFkIGVzIGxhIGZvcm1hIGRlIGFjdHVhciBkZSBhY3VlcmRvIGEgbG9zIHByaW5jaXBpb3MsIGEgZGlmZXJlbmNpYSBkZSBsYSBob25lc3RpZGFkIHF1ZSBlcyBlbCBhY3RvIGRlIHNlciB2ZXJhei4gKE5hY2lvbmVzIFVuaWRhcykgIApQb3IgbGEgcGFydGUgZGVsIGNvbXByb21pc28gw6l0aWNvLCBzZWfDum4gbWllbWJyb3MgZGUgbGEgVW5pdmVyc2l0YXQgZGUgQmFyY2Vsb25hLCBlcyBsYSBjYXBhY2lkYWQgZGUgYWN0dWFyIGNvbiBsYXMgdmlydHVkZXMgcGVyc29uYWxlcyB5IHByb2Zlc2lvbmFsZXMgcXVlIHJlcXVpZXJlIGVsIGNvcnJlY3RvIGVqZXJjY2lvIGRlIHVuYSBwcm9mZXNpw7NuLCBlbCBkZXNhcnJvbGxvIHBlcnNvbmFsIHkgbGEgY2l1ZGFkYW7DrWEgZGVtb2Nyw6F0aWNhLCB0b2RvIGVzdG8gZGVudHJvIGRlIHVuIGNvbnRleHRvIHVuaXZlcnNpdGFyaW8uIChNYXVyaS3DgWx2YXJleiwgTWFyZ2FyaXRhLCBldCBhbCkKClBvciDDumx0aW1vLCBlbCBjb21wcm9taXNvIGNpdWRhZGFubyBsbyBwb2RlbW9zIGRpZmVyZW5jaWFyIGRlIGxhIHBhcnRpY2lwYWNpw7NuIGNpdWRhZGFuYS4gRWwgY29tcHJvbWlzbyBidXNjYSB1biBkacOhbG9nbyBhY3Rpdm8gZW50cmUgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIHkgbG9zIGNpdWRhZGFub3MuKExvZGV3aWpja3gsIElsb25hKSAKVGVuZXIgdW4gY29tcHJvbWlzbyDDqXRpY28geSBjaXVkYWRhbm8gZnVlIHVuIHB1bnRvIGNsYXZlIHBhcmEgbGEgZWxhYm9yYWNpw7NuIGRlIGVzdGEgZXZpZGVuY2lhLgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5SZWZsZXhpw7NuIFBlcnNvbmFsOiBOYW5jeSBNYXJyb3F1w61uPC9zcGFuPiAKLSBSZWZsZXhpw7NuIHBlcnNvbmFsOiBFbCByZXNwZXRvIHkgbGEgaG9uZXN0aWRhZCBmb3JtYW4gcGFydGUgZGUgbG9zIHZhbG9yZXMgcXVlIHRyYXRvIGRlIHJlcHJlc2VudGFyIGVuIG1pIGTDrWEgYSBkw61hLiBFbiBjdWFscXVpZSB0aXBvIGRlIHByb3llY3RvIGVuIGVsIHF1ZSBwYXJ0aWNpcG8sIGJ1c2NvIHF1ZSBlc3RlIHNlIGxsZXZlIGEgY2FibyBkZSBtYW5lcmEgbcOhcyB0cmFucGFyZW50ZSwgZm9tZW50YW5kbyBsYSBjb211bmljYWNpw7NuIHkgbGEgZXNjdWNoYSBhY3RpdmEuIEVuIGVsIG11bmRvIGRlIGxvcyBuZWdvY2lvcyBmb21lbnRhciBlc3RvcyB2YWxvcmVzIHRhbiBpbXBvcnRhbnRlcywgc29uIGNsYXZlIHBhcmEgZWwgw6l4aXRvIGRlIGxhcyBlbXByZXNhcy4gRWwgYWN0dWEgZGUgbWFuZXJhIGhvbmVzdGEgeSBjb24gcmVzcGV0byBoYWNpYSBsb3MgZGVtw6FzLCB0ZSBwZXJtaXRlIHRlbmVyIHVuIG1lam9yIGRlc2Fycm9sbG8gcGVyc29uYWwgeSBwcm9mZXNpb25hbC4gU2kgbm9zIGVuZm9jYW1vcyBtw6FzLCBoYWNpYSBsYSBwYXJ0ZSBkZSBhbsOhbGlzaXMgZGUgZGF0b3MgeSBlbCB1c28gZGUgZGF0b3MgZGUgbGFzIGVtcHJlc2FzLCBlbCByZXBldG8geSBsYSBob25lc3RpZGFkLCBubyBzb24gbG9zIMO6bmljb3MgdmFsb3JlcyBxdWUgc2UgcHJvbXVldmVuLCBzaW5vIHF1ZSB0YW1iacOpbiBsYSBjb25maWFuemEsIGVsIGNvbXByb21pc28geSBsYSBpbnRlZ3JpZGFkLiBBbCB0cmFiYWphciBjb24gaW5mb3JtYWNpw7NuIGRlIGxhIGVtcHJlc2FzIGVzIG5lY2VzYXJpbyB0ZW5lciBtdWNobyBjdWlkYWRvIGPDs21vIGVzIHF1ZSBzZSB1dGlsaXphIHkgY3XDoWwgZXMgc3UgcHJvcMOzc2l0by4gRGUgZXN0YSBtYW5lcmEgZXMgcG9zaWJsZSBnZW5lcmFyIHVuYSBtZWpvciB0b21hIGRlIGRlY2lzaW9uZXMgcmVwZWN0byBhbCB1c28geSBkZXNhcnJvbGxvIGRlIGRpY2hvcyBkYXRvcy4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+UmVmbGV4acOzbiBQZXJzb25hbDogS2V2aW4gTWV6YTwvc3Bhbj4gCi0gUmVmbGV4acOzbiBwZXJzb25hbDogTGEgcmVzcG9uc2FiaWxpZGFkLCBlcyB1biB2YWxvciBlbCBjdWFsIHZhIGRlIGxhIG1hbm8gY29uIHRyYW5zcGFyZW5jaWEgZSBpbnRlZ3JpZGFkLiBFbCBzZXJsbyBhbCBsbGV2YXIgYSBjYWJvIGVuIGVsIHVzbyBkZSBkYXRvcywgZXMgYXN1bWlyIGxhcyBjb25zZWN1ZW5jaWFzIGRlIGxhcyBhY2Npb25lcyB0b21hZGFzIHkgZ2FyYW50aXphciBxdWUgc2UgY3VtcGxhbiBsb3MgcHJpbmNpcGlvIMOpdGljb3MgeSBsZWdhbGVzIGRlbCBtb21lbnRvLiBPdHJvIHB1bnRvIHJlbGV2YW50ZSBhIGNvbnNpZGVyYXIgZXMgbGEgw6l0aWNhIGVuIGxhIHRvbWEgZGUgZGVjaXNpb25lcyBiYXNhZGFzIGVuIGRhdG9zLiBFcyBmdW5kYW1lbnRhbCBxdWUgbGFzIGRlY2lzaW9uZXMgZW1wcmVzYXJpYWxlcyBzZSB0b21lbiBjb25zaWRlcmFuZG8gbm8gc29sbyBsYSBpbmZvcm1hY2nDs24gZGlzcG9uaWJsZSwgc2lubyB0YW1iacOpbiBsb3MgdmFsb3JlcyDDqXRpY29zIHF1ZSBndcOtYW4gZWwgY29tcG9ydGFtaWVudG8gZGUgcXVpZW5lcyBnZXN0aW9uYW4gZGljaG9zIGRhdG9zLiAgCkFzaW1pc21vLCBzZSBwdWVkZSBkZXN0YWNhciBsYSBpbXBvcnRhbmNpYSBkZSBsYSBjb25maWFuemEgY29tbyByZXN1bHRhZG8gZGUgbGEgY29tYmluYWNpw7NuIGRlIGVzdG9zIHZhbG9yZXMgw6l0aWNvcy4gTGEgY29uZmlhbnphIHRhbnRvIGludGVybmEgY29tbyBleHRlcm5hIHNlIGNvbnN0cnV5ZSBhIHBhcnRpciBkZSBsYSBjb2hlcmVuY2lhIGVudHJlIGxvIHF1ZSBzZSBkaWNlIHkgbG8gcXVlIHNlIGhhY2UgZW4gcmVsYWNpw7NuIGNvbiBsb3MgZGF0b3MgZW1wcmVzYXJpYWxlcy4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+UmVmbGV4acOzbiBQZXJzb25hbDogQWRyacOhbiBNb3JhbGVzPC9zcGFuPiAKLSBSZWZsZXhpw7NuIHBlcnNvbmFsOiBEZXNkZSBtaSBwdW50byBkZSB2aXN0YSwgY29uc2lkZXJvIHF1ZSBsYSBpbnRlZ3JpZGFkIGVzIGZ1bmRhbWVudGFsIHBhcmEgbGEgaG9uZXN0aWRhZCB5IGxhIGNvaGVyZW5jaWEgZW4gdG9kb3MgbG9zIGFzcGVjdG9zIGRlIGxhIHZpZGEuIEVuIGVsIGNhbXBvIGRlIGxhIGludGVsaWdlbmNpYSBkZSBuZWdvY2lvcywgZG9uZGUgbWUgZGVzZW1wZcOxbyBjb21vIGVzdHVkaWFudGUsIGVsIGPDs2RpZ28gw6l0aWNvIGRlIG51ZXN0cmEgZGlzY2lwbGluYSBhY3TDumEgY29tbyBlbCBndcOtYSBxdWUgb3JpZW50YSBtaSBjb21wb3J0YW1pZW50byBwcm9mZXNpb25hbC4gRXN0ZSBjw7NkaWdvIG5vIHNvbGFtZW50ZSBlc3RhYmxlY2UgbGEgb2JsaWdhY2nDs24gZGUgbWFuZWphciBsYSBpbmZvcm1hY2nDs24gZGUgZm9ybWEgcHJlY2lzYSB5IGNvbmZpZGVuY2lhbCwgc2lubyBxdWUgdGFtYmnDqW4gcmVzYWx0YSBsYSBpbXBvcnRhbmNpYSBkZSB1dGlsaXphciBlbCBjb25vY2ltaWVudG8gYWRxdWlyaWRvIGRlIG1hbmVyYSBlcXVpdGF0aXZhIHkgY2xhcmEuIFRlbmVyIGFjY2VzbyBhIGxhIGluZm9ybWFjacOzbiBkZSB1bmEgZW1wcmVzYSBjb25sbGV2YSB1bmEgZ3JhbiByZXNwb25zYWJpbGlkYWQgZGUgbWFuZWphcmxhIGNvbiBjdWlkYWRvLCBnYXJhbnRpemFuZG8gbGEgY29uZmlkZW5jaWFsaWRhZCB5IGV2aXRhbmRvIGNvbmZsaWN0b3MgZGUgaW50ZXLDqXMsIGFwbGljYW5kbyBhbsOhbGlzaXMgw6l0aWNvcyBxdWUgYmVuZWZpY2llIGEgbGEgb3JnYW5pemFjacOzbiB5IGEgbGEgc29jaWVkYWQgZW4gZ2VuZXJhbC4gQWwgZmluYWwgZGVsIGTDrWEsIG1hbnRlbmVyIGxhIGludGVncmlkYWQgZW4gbGEgZ2VzdGnDs24gZGUgZGF0b3MgZGUgbGEgZW1wcmVzYSBubyBzb2xvIG11ZXN0cmEgbWkgZGVkaWNhY2nDs24gYSBsYSDDqXRpY2EgbGFib3JhbCwgc2lubyBxdWUgdGFtYmnDqW4gYXVtZW50YSBsYSBjb25maWFuemEgeSBjcmVkaWJpbGlkYWQgZW4gZWwgY2FtcG8gZGUgbGEgaW50ZWxpZ2VuY2lhIGVtcHJlc2FyaWFsCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPlJlZmxleGnDs24gUGVyc29uYWw6IEthcmxhIEzDs3Blejwvc3Bhbj4gCi0gUmVmbGV4acOzbiBwZXJzb25hbDogTGEgaW50ZWdyaWRhZCBzZSBwdWVkZSBkZWZpbmlyIGNvbW8gbGEgY2FsaWRhZCBkZSBzZXIgaG9uZXN0bywgw6l0aWNvIHkgbW9yYWwgZW4gdG9kYXMgbGFzIGFjY2lvbmVzIHkgZGVjaXNpb25lcy4gRW4gZWwgY29udGV4dG8gZGUgbWkgZGlzY2lwbGluYSBhY2Fkw6ltaWNhLCBsYSBpbnRlZ3JpZGFkIGVzIGZ1bmRhbWVudGFsIHBhcmEgbWlzIHRyYWJham9zIGluZGl2aWR1YWxlcyB5IGdydXBhbGVzLCB5YSBxdWUgcmVwcmVzZW50YSBsYSByZWxhY2nDs24gZGUgbWlzIGFjY2lvbmVzLCB2YWxvcmVzLCBwcmluY2lwaW9zIHkgcmVzdWx0YWRvcy4gQXNpbWlzbW8sIGVuIG1pIGRpc2NpcGxpbmEgcGVyc29uYWwsIG1lIGltcHVsc2EgYSBzZXIgaG9uZXN0YSwgdHJhbnNwYXJlbnRlIHkgcmVzcG9uc2FibGUgZW4gbWlzIGFjdGl2aWRhZGVzLCBhc2VndXJhbmRvIHF1ZSBtaXMgYWNjaW9uZXMgc2llbXByZSByZWZsZWplbiBtaXMgdmFsb3JlcyBtb3JhbGVzIHkgw6l0aWNvcy4gUG9yIG90cm8gbGFkbywgZW4gZWwgw6FtYml0byBwcm9mZXNpb25hbCwgZW4gdW5hIGVtcHJlc2Egbm8gc29sbyBzZSBidXNjYSBjb250YXIgY29uIHVuIGNvbXByb21pc28gY29uIGxhIGluZm9ybWFjacOzbiBwcm9wb3JjaW9uYWRhIHNpbm8gdGFtYmnDqW4gY29uIGVsIGVxdWlwbyB5IGxhcyBoZXJyYW1pZW50YXMsIHlhIHF1ZSBlcyBmdW5kYW1lbnRhbCBtYW50ZW5lciB1bmEgY29uZHVjdGEgw6l0aWNhIHRhbnRvIGVuIGxhcyByZWxhY2lvbmVzIGNvbiBsb3MgY29tcGHDsWVyb3MgY29tbyBlbiBlbCB1c28gZGUgbG9zIHJlY3Vyc29zIGRpc3BvbmlibGVzIHBhcmEgZWwgZGVzYXJyb2xsbyB5IGVsIMOpeGl0byBkZSBsYSBlbXByZXNhLgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5Db25jbHVzacOzbiBHZW5lcmFsPC9zcGFuPiAKVHJhcyBleGFtaW5hciBlbCBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwsIHNlIHB1ZG8gb2JzZXJ2YXIgcXVlIGVsIDg4LjY4JSBkZSBsYSB2YXJpYWJpbGlkYWQgZW4gbGEgdmFyaWFibGUgZGVwZW5kaWVudGUgKHJldHJhc28gZW4gbG9zIHZ1ZWxvcykgc2UgcHVlZGUgZXhwbGljYXIgdXRpbGl6YW5kbyBsYXMgdmFyaWFibGVzIGluZGVwZW5kaWVudGVzLiBMYXMgY3VhbGVzIHNlIGlkZW50aWZpY2Fyb24gY2llcnRhcyB2YXJpYWJsZXMgcXVlIG11ZXN0cmFuIHVuYSBzaWduaWZpY2FuY2lhIGVzdGFkw61zdGljYSwgY29uIHZhbG9yZXMgZGUgcCBtZW5vcmVzIGEgMC4wMDEsIGxvIHF1ZSBkZW11ZXN0cmEgcXVlIHRpZW5lbiB1biBpbXBhY3RvIHNpZ25pZmljYXRpdm8sIGxvIHF1ZSBzaWduaWZpY2EgcXVlIHRpZW5lbiB1bmEgcmVsYWNpw7NuIGRpcmVjdGEgeSBsw7NnaWNhIGNvbiBlbCByZXRyYXNvIGRlIGxvcyB2dWVsb3MsIGxhcyBjdWFsZXMgZnVlcm9uOgoKCmRlcF90aW1lOiBSYXpvbmVzIHBvciBsYXMgY3VhbGVzIGVsIHRpZW1wbyBkZSBzYWxpZGEgcHVlZGUgYWZlY3RhciBhIGxvcyB2dWVsb3MgcHVlZGVuIHNlciBwcm9ibGVtYXMgZGUgZ2VzdGnDs24gcG9yIHBhcnRlIGRlIGxhcyBhZXJvbMOtbmVhcywgY29tbyBkaWZpY3VsdGFkZXMgb3BlcmF0aXZhcyByZWxhY2lvbmFkYXMgY29uIGVsIGVxdWlwbyBvIGVsIHBlcnNvbmFsLCBvIHByb2JsZW1hcyBlbiBlbCBhZXJvcHVlcnRvLigqKiopCgphcnJfZGVsYXk6IFJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVuIGxhIGNvbmV4acOzbiBkZSBsYXMgbGxlZ2FkYXMgdGFyZMOtYXMgY29uIGxhcyBzYWxpZGFzLiAoKioqKQoKYWlyX3RpbWU6IEFsIGVzdGFyIG3DoXMgZXhwdWVzdG9zIGVuIGVsIGFpcmUsIGxvcyB2dWVsb3MgcHVlZGVuIHN1ZnJpciBwcm9ibGVtYXMgY2xpbcOhdGljb3MsIGVzY2FsYXMsIHByb2Nlc29zIGRlIHNlZ3VyaWRhZCwgZW50cmUgb3Ryb3MuICgqKiopCgpkZXN0OiBMb3MgdnVlbG9zIHB1ZWRlbiB2ZXJzZSBhZmVjdGFkb3MgcG9yIGFsZ3Vub3MgZGVzdGlub3MgZG9uZGUgaGF5IHRyw6FmaWNvIGHDqXJlbywgY29uZGljaW9uZXMgbWV0ZW9yb2zDs2dpY2FzIGxvY2FsZXMgbyBjb25nZXN0acOzbiBkZWwgYWVyb3B1ZXJ0byBkZSBkZXN0aW5vLCBxdWUgc3VjZWRlIGZyZWN1ZW50ZW1lbnRlIGVuIGNpdWRhZGVzIGdyYW5kZXMuKCoqKikKCndpbmRfc3BlZWQ6IFJlbGFjacOzbiBlbnRyZSBsYSB2ZWxvY2lkYWQgZGVsIHZpZW50byB5IGxvcyByZXRyYXNvcyBlbiBsYSBzYWxpZGEgZGUgbG9zIHZ1ZWxvcy4gUHVlZGUgc2VyIG9jYXNpb25hZG8gcG9yIG9wZXJhY2nDs24gZW4gZWwgdnVlbG8gbyBkZSBzZWd1cmlkYWQsIHByb2NlZGltaWVudG9zIGRlIHNlZ3VyaWRhZCwgZW50cmUgb3Ryb3MuICgqKikKCndpbmRfZGlyOiBSZWxhY2nDs24gZW50cmUgbGEgZGlyZWNjacOzbiBkZWwgdmllbnRvIHkgbG9zIHJldHJhc29zLCBxdWUgcHVlZGVuIHNlciBkZWJpZG9zIHBvciBsYXMgY29uZGljaW9uZXMgZGUgdnVlbG8sIHByb2NlZGltaWVudG9zIGRlIGRlc3BlZ3VlLCBlbnRyZSBvdHJvcy4gKCoqKQoKClBvciBsbyBjdWFsLCBzdWdpZXJlIHF1ZSB1bmEgdmFyaWVkYWQgZGUgdmFyaWFibGVzLCB0YW50byByZWxhY2lvbmFkYXMgY29uIGxhIG9wZXJhY2nDs24gZGUgbGFzIGFlcm9sw61uZWFzIGNvbW8gY29uIGxhcyBjb25kaWNpb25lcyBtZXRlb3JvbMOzZ2ljYXMsIHB1ZWRlbiBjb250cmlidWlyIGEgbG9zIHJldHJhc29zIGVuIGxhIHNhbGlkYSBkZSBsb3MgdnVlbG9zLiAKCgoKCgoKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+QmlibGlvZ3JhZsOtYXM8L3NwYW4+IAoqQmVycmVuZGVybywgSi4gUi4gKG4uZC4pLiBVbmEgYnJldmUgaW50cm9kdWNjacOzbiBhIGdncGxvdDIuIGh0dHA6Ly92ZXJzby5tYXQudWFtLmVzL35qb3Nlci5iZXJyZW5kZXJvL1IvaW50cm9nZ3Bsb3QyLmh0bWwKCiogRWwgdmFsb3IgZGUgdmFsb3JlczogTGEgaW50ZWdyaWRhZCB8IExpbmtlZEluLiAobi5kLikuIGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9wdWxzZS9lbC12YWxvci1kZS12YWxvcmVzLWxhLWludGVncmlkYWQtbWFybGV0aC1tb3JhbGVzLz9vcmlnaW5hbFN1YmRvbWFpbj1lcwoKKiDigJxMYSBDaWVuY2lhIGRlIExhIEludGVncmlkYWQu4oCdIE5hY2lvbmVzIFVuaWRhcyA6IE9maWNpbmEgZGUgTGFzIE5hY2lvbmVzIFVuaWRhcyBDb250cmEgTGEgRHJvZ2EgWSBFbCBEZWxpdG8sIHd3dy51bm9kYy5vcmcvdW5vZGMvZXMvbGlzdGVuLWZpcnN0L3N1cGVyLXNraWxscy9pbnRlZ3JpdHkuaHRtbC4KCiogTG9kZXdpamNreCwgSWxvbmEuIOKAnMK/Q3XDoWwgRXMgTGEgRGlmZXJlbmNpYSBFbnRyZSBFbCBDb21wcm9taXNvIENpdWRhZGFubyBZIExhIFBhcnRpY2lwYWNpw7NuP+KAnSBDaXRpemVuTGFi4oCZcyBCbG9nLCAyOSBKdW5lIDIwMjAsIHd3dy5jaXRpemVubGFiLmNvL2Jsb2cvcGFydGljaXBhY2lvbi1jaXVkYWRhbmEvY3VhbC1lcy1sYS1kaWZlcmVuY2lhLWVudHJlLWVsLWNvbXByb21pc28tY2l1ZGFkYW5vLXktbGEtcGFydGljaXBhY2lvbi8/bGFuZz1lcy4gQWNjZXNzZWQgMTIgTWFyLiAyMDI0LgoKKiBNYXVyaS3DgWx2YXJleiwgTWFyZ2FyaXRhLCBldCBhbC4g4oCcQ29tcHJvbWlzbyDDiXRpY28gWSBSZXNwb25zYWJpbGlkYWQgRW4gRWwgQ29udGV4dG8gVW5pdmVyc2l0YXJpby7igJ0gUkVJUkUgUmV2aXN0YSBk4oCZSW5ub3ZhY2nDsyBJIFJlY2VyY2EgRW4gRWR1Y2FjacOzLCB2b2wuIDE1LCBuby4gMSwgMiBEZWMuIDIwMjEsIGRpcG9zaXQudWIuZWR1L2RzcGFjZS9iaXRzdHJlYW0vMjQ0NS8xOTQzNDEvMS83MjE1MTcucGRmLCBodHRwczovL2RvaS5vcmcvMTAuMTM0NC9yZWlyZS4zNjk3MC4gQWNjZXNzZWQgMjkgQXVnLiAyMDIzCgoqIFJQdWJzIC0gRnVuY2nDs24gZ2dwbG90KCkgZGUgZ2dwbG90Mi4gKG4uZC4pLiBodHRwczovL3JwdWJzLmNvbS9kYW5pYmFsbGFyaS9nZ3Bsb3QKCiogUmx0LiAobi5kLikuR3LDoWZpY29zIGRlIGJhcnJhcyBjb24gZ2VvbV9iYXIuIGh0dHBzOi8vcmF5bW9uZGx0cmVtYmxheS5naXRodWIuaW8vQU5BTElUSUNBL0c3X2dlb21fYmFyLmh0bWwK