
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
- Encuentra todos los vuelos que tuvieron un atraso en llegada de 2
horas o más.
ejercicio1 <- bdgrande2 %>% filter(arr_delay>=120)
- Encuentra todos los vuelos que llegaron a Houston (IAN O HOU)
ejercicio2 <- bdgrande2 %>% filter(dest== "IAH" | dest == "HOU")
- Encuentra todos los vuelos operados por United, American o
Delta.
ejercicio3 <- bdgrande2 %>% filter(carrier %in% c("UA", "AA", "DL"))
- 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)
- 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)
- 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)
- 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))
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)
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
# Calcular la cantidad total de vuelos por mes
total_flights_per_month <- flights %>%
group_by(month) %>%
summarize(total_flights = n())
# Calcular la cantidad de vuelos con y sin retraso por mes
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.
# Unir los datos para incluir el total de vuelos por mes
flights_filtered <- left_join(flights_filtered, total_flights_per_month, by = "month")
# Calcular el porcentaje de vuelos para cada categoría por mes
flights_filtered <- flights_filtered %>%
mutate(percent_of_total = count / total_flights * 100)
# Gráfico de barras para el porcentaje de vuelos con y sin retraso por mes
ggplot(flights_filtered, aes(x = factor(month), y = percent_of_total, fill = flights)) +
geom_bar(stat = "identity", position = "stack") +
scale_fill_manual(values = c("seashell2", "rosybrown2")) +
labs(title = "Porcentaje de vuelos por mes con y sin retraso",
x = "Mes",
y = "Porcentaje de vuelos",
fill = "Retraso") +
theme_minimal()

Visualizaciones Flights 4: Gráfico de
Barras
Retrasos en la partida
# Calcular la cantidad total de vuelos
total_flights <- nrow(flights)
# Calcular la cantidad de vuelos con diferentes niveles de retraso en la partida
delayed_flights <- flights %>%
filter(dep_delay > 0) %>%
group_by(dep_delay) %>%
summarize(count = n())
# Calcular el porcentaje de vuelos para cada nivel de retraso
delayed_flights <- delayed_flights %>%
mutate(percentage = (count / total_flights) * 100)
# Gráfico de barras para el porcentaje de vuelos con diferentes niveles de retraso en la partida
ggplot(delayed_flights, aes(x = as.factor(dep_delay), y = percentage)) +
geom_bar(stat = "identity") +
labs(title = "Porcentaje de Vuelos con Retrasos en la Partida",
x = "Retraso en la Partida (minutos)",
y = "Porcentaje de Vuelos") +
scale_x_discrete(labels = function(x) ifelse(as.numeric(x) %% 100 == 0, x, ""))
#### 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
# Calcular el número total de vuelos por origen
total_flights_per_origin <- flights %>%
group_by(origin) %>%
summarize(total_flights = n())
# Calcular el número de vuelos retrasados por origen
delayed_flights_per_origin <- flights %>%
filter(dep_delay > 0) %>%
group_by(origin) %>%
summarize(delayed_flights = n())
# Unir los datos y calcular el porcentaje de vuelos retrasados
delay_percentage_per_origin <- total_flights_per_origin %>%
left_join(delayed_flights_per_origin, by = "origin") %>%
mutate(delay_percentage = (delayed_flights / total_flights) * 100)
# Gráfico de barras para el porcentaje de vuelos retrasados por origen
ggplot(delay_percentage_per_origin, aes(x = origin, y = delay_percentage)) +
geom_bar(stat = "identity", fill = "lightblue1") +
theme_minimal() +
labs(title = "Porcentaje de Vuelos Retrasados por Origen",
x = "Origen",
y = "Porcentaje de Vuelos Retrasados")

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")

# Calcular el número total de vuelos por transportista
total_flights_per_carrier <- flights %>%
group_by(carrier) %>%
summarize(total_flights = n())
# Calcular el número de vuelos retrasados por transportista
delayed_flights_per_carrier <- flights %>%
filter(dep_delay > 0) %>%
group_by(carrier) %>%
summarize(delayed_flights = n())
# Unir los datos y calcular el porcentaje de vuelos retrasados
delay_percentage_per_carrier <- total_flights_per_carrier %>%
left_join(delayed_flights_per_carrier, by = "carrier") %>%
mutate(delay_percentage = (delayed_flights / total_flights) * 100)
# Gráfico de barras para el porcentaje de vuelos retrasados por transportista
ggplot(delay_percentage_per_carrier, aes(x = carrier, y = delay_percentage)) +
geom_bar(stat = "identity", fill = "cadetblue3") +
theme_minimal() +
labs(title = "Porcentaje de Vuelos Retrasados por Carrier",
x = "Carrier",
y = "Porcentaje de Vuelos Retrasados")

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")

# Calcular el número total de vuelos por mes
total_flights_per_month <- flights %>%
group_by(month) %>%
summarize(total_flights = n())
# Calcular el número de vuelos retrasados por mes
delayed_flights_per_month <- flights %>%
filter(dep_delay > 0) %>%
group_by(month) %>%
summarize(delayed_flights = n())
# Unir los datos y calcular el porcentaje de vuelos retrasados
delay_percentage_per_month <- total_flights_per_month %>%
left_join(delayed_flights_per_month, by = "month") %>%
mutate(delay_percentage = (delayed_flights / total_flights) * 100)
# Gráfico de línea para el porcentaje de vuelos retrasados por mes
ggplot(delay_percentage_per_month, aes(x = month, y = delay_percentage)) +
geom_line(colour = "darkslategray3") +
theme_minimal() +
labs(title = "Porcentaje de Vuelos Retrasados por Mes",
x = "Mes",
y = "Porcentaje de Vuelos Retrasados")

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()

# Calcular el número total de vuelos por tipo de avión
total_flights_per_type <- flights %>%
left_join(planes, by = "tailnum") %>%
group_by(type) %>%
summarize(total_flights = n())
# Calcular el número de vuelos retrasados por tipo de avión
delayed_flights_per_type <- flights %>%
filter(dep_delay > 0) %>%
left_join(planes, by = "tailnum") %>%
group_by(type) %>%
summarize(delayed_flights = n())
# Unir los datos y calcular el porcentaje de vuelos retrasados
retraso_por_avion <- total_flights_per_type %>%
left_join(delayed_flights_per_type, by = "type") %>%
mutate(delay_percentage = (delayed_flights / total_flights) * 100)
# Gráfico de barras para retraso por tipo de avión
ggplot(retraso_por_avion, aes(x = type, y = delay_percentage)) +
geom_bar(stat = "identity", fill = "skyblue") +
labs(title = "Porcentaje de Vuelos Retrasados por Tipo de Avión",
x = "Tipo de Avión",
y = "Porcentaje de Vuelos Retrasados") +
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 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
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
El valor de valores: La integridad | LinkedIn. (n.d.). https://www.linkedin.com/pulse/el-valor-de-valores-la-integridad-marleth-morales/?originalSubdomain=es
“La Ciencia de La Integridad.” Naciones Unidas : Oficina de Las
Naciones Unidas Contra La Droga Y El Delito,
www.unodc.org/unodc/es/listen-first/super-skills/integrity.html.
Lodewijckx, Ilona. “¿Cuál Es La Diferencia Entre El Compromiso
Ciudadano Y La Participación?” CitizenLab’s Blog, 29 June 2020,
www.citizenlab.co/blog/participacion-ciudadana/cual-es-la-diferencia-entre-el-compromiso-ciudadano-y-la-participacion/?lang=es.
Accessed 12 Mar. 2024.
Mauri-Álvarez, Margarita, et al. “Compromiso Ético Y
Responsabilidad En El Contexto Universitario.” REIRE Revista d’Innovació
I Recerca En Educació, vol. 15, no. 1, 2 Dec. 2021,
diposit.ub.edu/dspace/bitstream/2445/194341/1/721517.pdf, https://doi.org/10.1344/reire.36970. Accessed 29
Aug. 2023
RPubs - Función ggplot() de ggplot2. (n.d.). https://rpubs.com/daniballari/ggplot
Rlt. (n.d.).Gráficos de barras con geom_bar. https://raymondltremblay.github.io/ANALITICA/G7_geom_bar.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+Ck7Dum1lcm8gZGUgdnVlbG9zIHBvciBtZXMgY29uIHkgc2luIHJldHJhc28KYGBge3J9CiMgQ2FsY3VsYXIgbGEgY2FudGlkYWQgdG90YWwgZGUgdnVlbG9zIHBvciBtZXMKdG90YWxfZmxpZ2h0c19wZXJfbW9udGggPC0gZmxpZ2h0cyAlPiUKICBncm91cF9ieShtb250aCkgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2ZsaWdodHMgPSBuKCkpCgojIENhbGN1bGFyIGxhIGNhbnRpZGFkIGRlIHZ1ZWxvcyBjb24geSBzaW4gcmV0cmFzbyBwb3IgbWVzCmZsaWdodHNfZmlsdGVyZWQgPC0gZmxpZ2h0cyAlPiUKICBtdXRhdGUoZmxpZ2h0cyA9IGlmZWxzZShkZXBfZGVsYXkgPiAwLCAiRGVsYXllZCIsICJOb3QgRGVsYXllZCIpKSAlPiUgCiAgZ3JvdXBfYnkobW9udGgsIGZsaWdodHMpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnQgPSBjb3VudCAvIHN1bShjb3VudCkgKiAxMDApCgojIFVuaXIgbG9zIGRhdG9zIHBhcmEgaW5jbHVpciBlbCB0b3RhbCBkZSB2dWVsb3MgcG9yIG1lcwpmbGlnaHRzX2ZpbHRlcmVkIDwtIGxlZnRfam9pbihmbGlnaHRzX2ZpbHRlcmVkLCB0b3RhbF9mbGlnaHRzX3Blcl9tb250aCwgYnkgPSAibW9udGgiKQoKIyBDYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIHZ1ZWxvcyBwYXJhIGNhZGEgY2F0ZWdvcsOtYSBwb3IgbWVzCmZsaWdodHNfZmlsdGVyZWQgPC0gZmxpZ2h0c19maWx0ZXJlZCAlPiUKICBtdXRhdGUocGVyY2VudF9vZl90b3RhbCA9IGNvdW50IC8gdG90YWxfZmxpZ2h0cyAqIDEwMCkKCiMgR3LDoWZpY28gZGUgYmFycmFzIHBhcmEgZWwgcG9yY2VudGFqZSBkZSB2dWVsb3MgY29uIHkgc2luIHJldHJhc28gcG9yIG1lcwpnZ3Bsb3QoZmxpZ2h0c19maWx0ZXJlZCwgYWVzKHggPSBmYWN0b3IobW9udGgpLCB5ID0gcGVyY2VudF9vZl90b3RhbCwgZmlsbCA9IGZsaWdodHMpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIikgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJzZWFzaGVsbDIiLCAicm9zeWJyb3duMiIpKSArCiAgbGFicyh0aXRsZSA9ICJQb3JjZW50YWplIGRlIHZ1ZWxvcyBwb3IgbWVzIGNvbiB5IHNpbiByZXRyYXNvIiwKICAgICAgIHggPSAiTWVzIiwKICAgICAgIHkgPSAiUG9yY2VudGFqZSBkZSB2dWVsb3MiLAogICAgICAgZmlsbCA9ICJSZXRyYXNvIikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBvcmFuZ2U7Ij5WaXN1YWxpemFjaW9uZXMgRmxpZ2h0cyA0OiBHcsOhZmljbyBkZSBCYXJyYXM8L3NwYW4+ClJldHJhc29zIGVuIGxhIHBhcnRpZGEKYGBge3J9CiMgQ2FsY3VsYXIgbGEgY2FudGlkYWQgdG90YWwgZGUgdnVlbG9zCnRvdGFsX2ZsaWdodHMgPC0gbnJvdyhmbGlnaHRzKQoKIyBDYWxjdWxhciBsYSBjYW50aWRhZCBkZSB2dWVsb3MgY29uIGRpZmVyZW50ZXMgbml2ZWxlcyBkZSByZXRyYXNvIGVuIGxhIHBhcnRpZGEKZGVsYXllZF9mbGlnaHRzIDwtIGZsaWdodHMgJT4lCiAgZmlsdGVyKGRlcF9kZWxheSA+IDApICU+JQogIGdyb3VwX2J5KGRlcF9kZWxheSkgJT4lCiAgc3VtbWFyaXplKGNvdW50ID0gbigpKQoKIyBDYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIHZ1ZWxvcyBwYXJhIGNhZGEgbml2ZWwgZGUgcmV0cmFzbwpkZWxheWVkX2ZsaWdodHMgPC0gZGVsYXllZF9mbGlnaHRzICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gKGNvdW50IC8gdG90YWxfZmxpZ2h0cykgKiAxMDApCgojIEdyw6FmaWNvIGRlIGJhcnJhcyBwYXJhIGVsIHBvcmNlbnRhamUgZGUgdnVlbG9zIGNvbiBkaWZlcmVudGVzIG5pdmVsZXMgZGUgcmV0cmFzbyBlbiBsYSBwYXJ0aWRhCmdncGxvdChkZWxheWVkX2ZsaWdodHMsIGFlcyh4ID0gYXMuZmFjdG9yKGRlcF9kZWxheSksIHkgPSBwZXJjZW50YWdlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgbGFicyh0aXRsZSA9ICJQb3JjZW50YWplIGRlIFZ1ZWxvcyBjb24gUmV0cmFzb3MgZW4gbGEgUGFydGlkYSIsCiAgICAgICB4ID0gIlJldHJhc28gZW4gbGEgUGFydGlkYSAobWludXRvcykiLAogICAgICAgeSA9ICJQb3JjZW50YWplIGRlIFZ1ZWxvcyIpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIGlmZWxzZShhcy5udW1lcmljKHgpICUlIDEwMCA9PSAwLCB4LCAiIikpCmBgYAojIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5JbnRlcnByZXRhY2lvbmVzOiBWaXN1YWxpemFjaW9uZXMgRmxpZ2h0czwvc3Bhbj4KRW4gZXN0YSBwYXJ0ZSBzZSByZWFsaXphIHVuIG1heW9yIGVuZm9xdWUgZW4gbGFzIHZpc3VhbGl6YWNpb25lcyBkZSBsYSBiYXNlIGRlIGRhdG9zICpmbGlnaHRzKiwgcGFyYSBlc3RvIG9wdGFtb3MgcG9yIGdyw6FmaWNvcyBkZSBiYXJyYXMgeSBkZSBwYXN0ZWwuIExhIHByaW1lcmEgdmlzdWFsaXphY2nDs24gcXVlIHNlIHByZXNlbnRhIGVzIGxhIGNhbnRpZGFkIGRlIHZ1ZWxvcyBwb3IgQWVyb2zDrW5lYSwgbXV5IHNpbWlsYXIgYSBsYSBkZWwgVG9wIDEwIGRlIGFlcm9sw61uZWFzIGNvbiBtw6FzIHZ1ZWxvcywgc2luIGVtYmFyZ28gZW4gZXN0YSBncsOhZmljYSBkZSBiYXJyYXMgc2kgc2UgcHJlc2VudGFuIGxhcyAxNiBhZXJvbMOtbmVhcyBwYXJ0aWNpcGFudGVzIGVuIGxvcyBhZXJvcHVlcnRvcyBkZSBOdWV2YSBZb3JrLgoKQ29udGludWFtb3MgY29uIHVuIGdyw6FmaWNvIGRlIHBhc3RlbCwgZWwgY3XDoWwgZW4gdW4gZm9ybWF0byBhdHJhY3Rpdm8gbXVlc3RyYSBsYSBwcm9wb3JjacOzbiBkZSB2dWVsb3MgcG9yIGFlcm9sw61uZWEsIHF1ZSBhIHNpbXBsZSB2aXN0YSBzZSBkZXN0YWNhbiA1IHByaW5jaXBhbGVzOiAqQW1lcmljYW4gQWlybGluZXMgSW5jLiogKEFBKSwgKlVuaXRlZCBBaXIgTGluZXMgSW5jLiogKFVBKSwgKkRlbHRhIEFpciBMaW5lcyBJbmMuKiAoREwpLCAqRXhwcmVzc0pldCBBaXJsaW5lcyBJbmMqIChFVikgeSAqSmV0Qmx1ZSBBaXJ3YXlzKiAoQjYpLgoKRW4gZWwgdGVyY2VyIGdyw6FmaWNvIHNlIHByZXNlbnRhIGVsIG7Dum1lcm8gZGUgdnVlbG9zIHBvciBtZXMgY29uIHkgc2luIHJldHJhc28sIGVzdG8gcG9yIG1lZGlvIGRlIHVuYSBncsOhZmljYSBkZSBiYXJyYXMsIHNlIGRlc3RhY2EgcXVlIGxhIG1heW9yw61hIGRlIGxvcyB2dWVsb3MsIGVuIHRvZG9zIGxvcyBtZXNlcywgbm8gc2UgcmV0cmFzYW4uIFBlcm8gcG9yIGVqZW1wbG8sIGVuIGVsIG1lcyBuw7ptZXJvIDcsIG8gc2VhIEp1bGlvLCBlcyBkZSBsb3MgbcOhcyBiYWpvcyBjb24gdnVlbG9zIG5vIHJldHJhc2Fkb3MgeSBkZSBsb3MgbcOhcyBhbHRvcyBjb24gdnVlbG9zIGNvbiByZXRyYXNvLCBlc3RvIHNpbiBkdWRhIG5vcyBheXVkYSBhIGNvbmZpcm1hciB1bmEgZGUgbnVlc3RyYXMgY29uY2x1c2lvbmVzIGRlIHBvciBxdcOpIGxvcyB2dWVsb3Mgc2UgcmV0cmFzYW4sIGFxdcOtIGhheSB1biBjbGFybyBlamVtcGxvLCBxdWUgbGEgdGVtcG9yYWRhIGFsdGEgZGUgdmFjYWNpb25lcyBkZSB2ZXJhbm8sIGVzIHVuIGZhY3RvciBwYXJhIGxvcyByZXRyYXNvcyBlbiBsb3MgdnVlbG9zLiBQb3Igw7psdGltbyBhZ3JlZ2Ftb3MgdW5hIGN1YXJ0YSB2aXN1YWxpemFjacOzbiwgZW4gZWxsYSBzZSBwcmVzZW50YSBsb3MgcmV0cmFzb3MgZW4gbGEgcGFydGlkYS4KCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBvcmFuZ2U7Ij5WaXN1YWxpemFjaW9uZXMgQWlycG9ydHMgMTogR3LDoWZpY28gZGUgRGlzcGVyc2nDs248L3NwYW4+ClJlbGFjacOzbiBlbnRyZSBjb29yZGVuYWRhcyBkZSBhZXJvcHVlcnRvcwpgYGB7cn0KZ2dwbG90KGFpcnBvcnRzLCBhZXMoeCA9IGxvbiwgeSA9IGxhdCkpICsgZ2VvbV9wb2ludCgpICsgbGFicyh0aXRsZSA9ICJSZWxhY2lvbiBlbnRyZSBDb29yZGVuYWRhcyBkZSBBZXJvcHVlcnRvcyIpCmBgYAojIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogb3JhbmdlOyI+VmlzdWFsaXphY2lvbmVzIEFpcnBvcnRzIDI6IEdyw6FmaWNvIGRlIEJhcnJhczwvc3Bhbj4KQXF1w60gZmFsdGEgZWwgdGVyY2VyIHZpc3VhbGl6YWNpw7NuCmBgYHtyfQp0b3BfMTBfYWlycG9ydHMgPC0gaGVhZChhaXJwb3J0c1tvcmRlcigtYWlycG9ydHMkYWx0KSwgXSwgMTApCgpnZ3Bsb3QodG9wXzEwX2FpcnBvcnRzLCBhZXMoeCA9IHJlb3JkZXIobmFtZSwgLWFsdCksIHkgPSBhbHQsIGZpbGwgPSBuYW1lKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBzaXplID0gMikgKwogIGxhYnModGl0bGUgPSAiVG9wIDEwIEFlcm9wdWVydG9zIE3DoXMgQWx0b3MiLAogICAgICAgeCA9ICJBZXJvcHVlcnRvIiwKICAgICAgIHkgPSAiQWx0dXJhIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDMpKQpgYGAKCgojIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5JbnRlcnByZXRhY2lvbmVzOiBWaXN1YWxpemFjaW9uZXMgQWlycG9ydHM8L3NwYW4+CkVuIGxhcyB2aXN1YWxpemFjaW9uZXMgZGUgKkFpcnBvcnRzKiBzZSB1dGlsaXphcm9uIHVuIGdyw6FmaWNvIGRlIGRpc3BlcnNpw7NuIHkgdW4gZ3LDoWZpY28gZGUgYmFycmFzLiBFbiBlbCBwcmltZXJvIHNlIHByZXNlbnRhIGxhIHJlbGFjacOzbiBleGlzdGVudGUgZW50cmUgbGFzIGNvb3JkZW5hZGFzIGRlIGxvcyBhZXJvcHVlcnRvcywgc2kgc2UgbWFudGVtb3MgdW4gYXRhZW5jacOzbiwgc2UgcHVlZGUgZGVzdGFjYXIgcXVlIGVuIGxhcyBjb29yZGVuYWRhcyBzZSBwcmVzZW50YSB1bmEgcGFydGUgZGUgRXN0YWRvcyBVbmlkb3MgeSBsYSBvdHJhIHBhcnRlIHNlcsOtYSBkZSBBbGFza2EuIEVuIGxhIHNlZ3VuZGEgdmlzdWFsaXphY2nDs24sIGNvbiB1bmEgZ3LDoWZpY2EgZGUgYmFycmFzLCBzZSBvYnRpZW5lIGVsIFRvcCAxMCBkZSBhZXJvcHVlcnRvcyBtw6FzIGFsdG9zLCBlbiBlbCBwcmltZXIgcHVlc3RvIHNlIGVuY3VlbnRyYSAqVGVsbHVyaWRlKiwgZW4gZWwgdG9wIDUgc2UgZW5jdWVudHJhIGVsICpCcnljZSBDYW55b24qIHkgZW4gZWwgdG9wIDEwICpNYW1tb3RoIFlvc2VtaXQgQWlycG9ydCouCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPjEwLiBDb25jbHVzacOzbjogUGFydGUgMjwvc3Bhbj4KRW4gZXN0YSBzZWd1bmRhIHBhcnRlIHNlIHB1ZGllcm9uIHBvbmVyIGVuIHByw6FjdGljYSBkaWZlcmVudGVzIGhhYmlsaWRhZGVzIGRlIHByb2dyYW1hY2nDs24sIHByaW5jaXBhbG1lbnRlIGFsIG1vbWVudG8gZGUgcmVhbGl6YXIgZ3LDoWZpY29zIHkgYW5hbGl6YXJsb3MuIFNlIGxvZ3LDsyBvYnRlbmVyIGxhIGluZm9ybWFjacOzbiBkZSBjYWRhIHZ1ZWxvLCBkZSBsb3MgZGVzdGlub3MgbcOhcyBjb25jdXJyaWRvcyB5IGhhc3RhIGxhIGRpdmlzw7NuIGRlIHZ1ZWxvcyBlbiBsb3MgZGlmZXJlbnRlcyB0dXJub3MgZGUgb2ZlcnRhIGRlIHZ1ZWxvcy4gU2UgZ2VuZXLDsyB1biBlbmZvcXVlIGVuICpBbWVyaWNhbiBBaXJsaW5lcyogeSBjb24gbGFzIHZpc3VhbGl6YWNpb25lcyBkZSBsYSDDumx0aW1hIHBhcnRlIGRlIGxhIGV2aWRlbmNpYSwgc2UgbG9ncsOzIHJlYWxpemFyIHVuIGFuw6FsaXNpcyBtw6FzIHByb2Z1bmRvIGVuIGxvcyByZXRyYXNvcywgZW5jb250cmFyIGxhcyByZWxhY2lvbmVzIGVudHJlIGxhIGJhc2UgZGUgZGF0b3MgKmZsaWdodHMqIHkgbGEgZGUgKmFpcnBvcnRzKiB5IGPDs21vIGVzIHF1ZSBjYWRhIHVuYSBkZSBlbGxhcyBub3Mgc2lydmUgcGFyYSBlbmNvbnRyYXIgZGlmZXJlbnRlcyB2YXJpYWJsZXMgcGFyYSBlbCBkZXNhcnJvbGxvIGRlIGFuw6FsaXNpcyBkZSByZXRyYXNvcy4gRW4gbGFzIGludGVycHJldGFjaW9uZXMgYW50ZXJpb3Jlcywgc2UgZXhwbGljYSBkZSBtYW5lcmEgbcOhcyBkZXRhbGxhZGEsIGxvcyByZXN1bHRhZG9zIG9idGVuaWRvcywgcGVybyBzaW4gZHVkYSwgZWwgdXNvIGRlIHZpc3VhbGl6YWNpb25lcyBmdWUgY2xhdmUgcGFyYSBwb2RlciBlbnRlbmRlciBtZWpvciBjb21vIGZ1bmNpb25hbiBlbCB0ZW1hIGRlIGxvcyB2dWVsb3MsIGFlcm9sw61uZWFzLCBkZXN0aW5vcywgZW50cmUgb3Ryb3MuCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPsK/UG9yIHF1w6kgc2UgcmV0cmFzYW4gbG9zIHZ1ZWxvcyBlbiBOdWV2YSBZb3JrPzwvc3Bhbj4KYGBge3J9CiNBdHJhc29zIGRlIG9yaWdlbiwgY2FycmllciB5IG1lcy4KYXRyYXNvX3Bvcl9vcmlnZW4gPC0gZmxpZ2h0cyAlPiUgZ3JvdXBfYnkob3JpZ2luKSAlPiUgc3VtbWFyaXNlKHRpZW1wb19hdHJhc29fcHJvbWVkaW8gPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkKCmF0cmFzb19wb3JfY2FycmllciA8LSBmbGlnaHRzICU+JSBncm91cF9ieShjYXJyaWVyKSAlPiUgc3VtbWFyaXNlKHRpZW1wb19hdHJhc29fcHJvbWVkaW8gPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkKCmF0cmFzb19wb3JfbWVzIDwtIGZsaWdodHMgJT4lIGdyb3VwX2J5KG1vbnRoKSAlPiUgc3VtbWFyaXNlKHRpZW1wb19hdHJhc29fcHJvbWVkaW8gPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkKCiMgUmVzdW1lbiBwb3Igb3JpZ2VuCnN1bW1hcnlfYnlfb3JpZ2luIDwtIGZsaWdodHMgJT4lIGdyb3VwX2J5KG9yaWdpbikgJT4lIHN1bW1hcml6ZShNZWRpYV9EZXBfRGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSwKTWVkaWFuYV9EZXBfRGVsYXkgPSBtZWRpYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpLCBNaW5fRGVwX0RlbGF5ID0gbWluKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSwgTWF4X0RlcF9EZWxheSA9IG1heChkZXBfZGVsYXksIG5hLnJtID0gVFJVRSkpCgojIFJlc3VtZW4gcG9yIGFlcm9sw61uZWEKc3VtbWFyeV9ieV9jYXJyaWVyIDwtIGZsaWdodHMgJT4lIGdyb3VwX2J5KGNhcnJpZXIpICU+JSBzdW1tYXJpemUoTWVkaWFfRGVwX0RlbGF5ID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksCiAgICBNZWRpYW5hX0RlcF9EZWxheSA9IG1lZGlhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksCiAgICBNaW5fRGVwX0RlbGF5ID0gbWluKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSwKICAgIE1heF9EZXBfRGVsYXkgPSBtYXgoZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKQoKIyBDYWxjdWxhciByZXN1bWVuIGVzdGFkw61zdGljbyBwb3IgZGVzdGlubwpzdW1tYXJ5X2J5X2Rlc3QgPC0gZmxpZ2h0cyAlPiUKICBncm91cF9ieShkZXN0KSAlPiUKICBzdW1tYXJpemUoTWVkaWFfRGVwX0RlbGF5ID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksCiAgICBNZWRpYW5hX0RlcF9EZWxheSA9IG1lZGlhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSksCiAgICBNaW5fRGVwX0RlbGF5ID0gbWluKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSwKICAgIE1heF9EZXBfRGVsYXkgPSBtYXgoZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKQoKIyBDcmVhciB1biBjb25qdW50byBkZSBkYXRvcyBjb21iaW5hbmRvIGxhcyB2YXJpYWJsZXMgZGUgaW50ZXLDqXMKbW9kZWxvX2RhdGEgPC0gZmxpZ2h0cyAlPiUKICBzZWxlY3QoZGVwX2RlbGF5LCBjYXJyaWVyLCBvcmlnaW4sIG1vbnRoKQoKIyBBanVzdGFyIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbAptb2RlbG8gPC0gbG0oZGVwX2RlbGF5IH4gY2FycmllciArIG9yaWdpbiArIG1vbnRoLCBkYXRhID0gbW9kZWxvX2RhdGEpCgojIFJlc3VtZW4gZGVsIG1vZGVsbwpzdW1tYXJ5KG1vZGVsbykKCmdncGxvdChtb2RlbG9fZGF0YSwgYWVzKHggPSBhcy5mYWN0b3IobW9udGgpLCB5ID0gZGVwX2RlbGF5LCBncm91cCA9IDEpKSArCiAgZ2VvbV9saW5lKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIiwgbGluZXR5cGUgPSAic29saWQiLCBzaXplID0gMSkgKwogIGxhYnModGl0bGUgPSAiUHJvbWVkaW8gZGVsIFJldHJhc28gZGUgU2FsaWRhIGVuIGZ1bmNpw7NuIGRlbCBNZXMiLAogICAgICAgeCA9ICJNZXMiLAogICAgICAgeSA9ICJQcm9tZWRpbyBkZSBSZXRyYXNvIGRlIFNhbGlkYSIpCmBgYAoKYGBge3J9CmRmX2NvbWJpbmFkbyA8LSBiZGdyYW5kZTIgJT4lCiAgbWVyZ2Uod2VhdGhlcikgCgpkZl9jb21iaW5hZG8gPC0gYXMuZGF0YS5mcmFtZShkZl9jb21iaW5hZG8pCnJlZ3Jlc2lvbiA8LSBsbShkZXBfZGVsYXkgfiB0YWlsbnVtICsgY2FycmllciArIHllYXIueCArIG1vbnRoICsgZGF5ICsgZGVwX3RpbWUgKyBhcnJfZGVsYXkgKyBmbGlnaHQgKyBvcmlnaW4gKyBkZXN0ICsgYWlyX3RpbWUgKyBkaXN0YW5jZSAgKyBtaW51dGUgICsgbmFtZSArIHllYXIueSArIHR5cGUgKyBtb2RlbCArIHNwZWVkICsgZW5naW5lICAgKyB0ZW1wICsgZGV3cCArIGh1bWlkICsgd2luZF9kaXIgKyB3aW5kX3NwZWVkICsgcHJlY2lwICsgcHJlc3N1cmUgKyB2aXNpYiwgZGF0YT1kZl9jb21iaW5hZG8pCnN1bW1hcnkocmVncmVzaW9uKQpgYGAKCgpgYGB7cn0KCmBgYAoKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+QW7DoWxpc2lzIFJldHJhc29zPC9zcGFuPgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5HcsOhZmljbyAtIEF0cmFzbyBwcm9tZWRpbyBwb3Igb3JpZ2VuPC9zcGFuPgpHcsOhZmljbyAtIEF0cmFzbyBwcm9tZWRpbyBwb3Igb3JpZ2VuCmBgYHtyfQojIENhbGN1bGFyIGVsIG7Dum1lcm8gdG90YWwgZGUgdnVlbG9zIHBvciBvcmlnZW4KdG90YWxfZmxpZ2h0c19wZXJfb3JpZ2luIDwtIGZsaWdodHMgJT4lCiAgZ3JvdXBfYnkob3JpZ2luKSAlPiUKICBzdW1tYXJpemUodG90YWxfZmxpZ2h0cyA9IG4oKSkKCiMgQ2FsY3VsYXIgZWwgbsO6bWVybyBkZSB2dWVsb3MgcmV0cmFzYWRvcyBwb3Igb3JpZ2VuCmRlbGF5ZWRfZmxpZ2h0c19wZXJfb3JpZ2luIDwtIGZsaWdodHMgJT4lCiAgZmlsdGVyKGRlcF9kZWxheSA+IDApICU+JQogIGdyb3VwX2J5KG9yaWdpbikgJT4lCiAgc3VtbWFyaXplKGRlbGF5ZWRfZmxpZ2h0cyA9IG4oKSkKCiMgVW5pciBsb3MgZGF0b3MgeSBjYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIHZ1ZWxvcyByZXRyYXNhZG9zCmRlbGF5X3BlcmNlbnRhZ2VfcGVyX29yaWdpbiA8LSB0b3RhbF9mbGlnaHRzX3Blcl9vcmlnaW4gJT4lCiAgbGVmdF9qb2luKGRlbGF5ZWRfZmxpZ2h0c19wZXJfb3JpZ2luLCBieSA9ICJvcmlnaW4iKSAlPiUKICBtdXRhdGUoZGVsYXlfcGVyY2VudGFnZSA9IChkZWxheWVkX2ZsaWdodHMgLyB0b3RhbF9mbGlnaHRzKSAqIDEwMCkKCiMgR3LDoWZpY28gZGUgYmFycmFzIHBhcmEgZWwgcG9yY2VudGFqZSBkZSB2dWVsb3MgcmV0cmFzYWRvcyBwb3Igb3JpZ2VuCmdncGxvdChkZWxheV9wZXJjZW50YWdlX3Blcl9vcmlnaW4sIGFlcyh4ID0gb3JpZ2luLCB5ID0gZGVsYXlfcGVyY2VudGFnZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJsaWdodGJsdWUxIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJQb3JjZW50YWplIGRlIFZ1ZWxvcyBSZXRyYXNhZG9zIHBvciBPcmlnZW4iLAogICAgICAgeCA9ICJPcmlnZW4iLAogICAgICAgeSA9ICJQb3JjZW50YWplIGRlIFZ1ZWxvcyBSZXRyYXNhZG9zIikKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPkdyw6FmaWNvIC0gQXRyYXNvIHByb21lZGlvIHBvciBjYXJyaWVyPC9zcGFuPgpHcsOhZmljbyAtIEF0cmFzbyBwcm9tZWRpbyBwb3IgY2FycmllcgpgYGB7cn0KZ2dwbG90KGF0cmFzb19wb3JfY2FycmllciwgYWVzKHg9Y2FycmllciwgeT10aWVtcG9fYXRyYXNvX3Byb21lZGlvKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0iY2FkZXRibHVlMyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGU9IkF0cmFzbyBwcm9tZWRpbyBwb3IgY2FycmllciIsIHg9IkNhcnJpZXIiLCB5PSJUaWVtcG8gZGUgYXRyYXNvIHByb21lZGlvIikKYGBgCmBgYHtyfQojIENhbGN1bGFyIGVsIG7Dum1lcm8gdG90YWwgZGUgdnVlbG9zIHBvciB0cmFuc3BvcnRpc3RhCnRvdGFsX2ZsaWdodHNfcGVyX2NhcnJpZXIgPC0gZmxpZ2h0cyAlPiUKICBncm91cF9ieShjYXJyaWVyKSAlPiUKICBzdW1tYXJpemUodG90YWxfZmxpZ2h0cyA9IG4oKSkKCiMgQ2FsY3VsYXIgZWwgbsO6bWVybyBkZSB2dWVsb3MgcmV0cmFzYWRvcyBwb3IgdHJhbnNwb3J0aXN0YQpkZWxheWVkX2ZsaWdodHNfcGVyX2NhcnJpZXIgPC0gZmxpZ2h0cyAlPiUKICBmaWx0ZXIoZGVwX2RlbGF5ID4gMCkgJT4lCiAgZ3JvdXBfYnkoY2FycmllcikgJT4lCiAgc3VtbWFyaXplKGRlbGF5ZWRfZmxpZ2h0cyA9IG4oKSkKCiMgVW5pciBsb3MgZGF0b3MgeSBjYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIHZ1ZWxvcyByZXRyYXNhZG9zCmRlbGF5X3BlcmNlbnRhZ2VfcGVyX2NhcnJpZXIgPC0gdG90YWxfZmxpZ2h0c19wZXJfY2FycmllciAlPiUKICBsZWZ0X2pvaW4oZGVsYXllZF9mbGlnaHRzX3Blcl9jYXJyaWVyLCBieSA9ICJjYXJyaWVyIikgJT4lCiAgbXV0YXRlKGRlbGF5X3BlcmNlbnRhZ2UgPSAoZGVsYXllZF9mbGlnaHRzIC8gdG90YWxfZmxpZ2h0cykgKiAxMDApCgojIEdyw6FmaWNvIGRlIGJhcnJhcyBwYXJhIGVsIHBvcmNlbnRhamUgZGUgdnVlbG9zIHJldHJhc2Fkb3MgcG9yIHRyYW5zcG9ydGlzdGEKZ2dwbG90KGRlbGF5X3BlcmNlbnRhZ2VfcGVyX2NhcnJpZXIsIGFlcyh4ID0gY2FycmllciwgeSA9IGRlbGF5X3BlcmNlbnRhZ2UpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiY2FkZXRibHVlMyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiUG9yY2VudGFqZSBkZSBWdWVsb3MgUmV0cmFzYWRvcyBwb3IgQ2FycmllciIsCiAgICAgICB4ID0gIkNhcnJpZXIiLAogICAgICAgeSA9ICJQb3JjZW50YWplIGRlIFZ1ZWxvcyBSZXRyYXNhZG9zIikKYGBgCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5HcsOhZmljbyAtIEF0cmFzbyBwcm9tZWRpbyBwb3IgbWVzPC9zcGFuPgpHcsOhZmljbyAtIEF0cmFzbyBwcm9tZWRpbyBwb3IgbWVzCmBgYHtyfQpnZ3Bsb3QoYXRyYXNvX3Bvcl9tZXMsIGFlcyh4PW1vbnRoLCB5PXRpZW1wb19hdHJhc29fcHJvbWVkaW8pKSArCiAgZ2VvbV9saW5lKGdyb3VwPTEsIGNvbG91cj0iZGFya3NsYXRlZ3JheTMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlPSJBdHJhc28gcHJvbWVkaW8gcG9yIG1lcyIsIHg9Ik1lcyIsIHk9IlRpZW1wbyBkZSBhdHJhc28gcHJvbWVkaW8iKQoKIyBDYWxjdWxhciBlbCBuw7ptZXJvIHRvdGFsIGRlIHZ1ZWxvcyBwb3IgbWVzCnRvdGFsX2ZsaWdodHNfcGVyX21vbnRoIDwtIGZsaWdodHMgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9mbGlnaHRzID0gbigpKQoKIyBDYWxjdWxhciBlbCBuw7ptZXJvIGRlIHZ1ZWxvcyByZXRyYXNhZG9zIHBvciBtZXMKZGVsYXllZF9mbGlnaHRzX3Blcl9tb250aCA8LSBmbGlnaHRzICU+JQogIGZpbHRlcihkZXBfZGVsYXkgPiAwKSAlPiUKICBncm91cF9ieShtb250aCkgJT4lCiAgc3VtbWFyaXplKGRlbGF5ZWRfZmxpZ2h0cyA9IG4oKSkKCiMgVW5pciBsb3MgZGF0b3MgeSBjYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIHZ1ZWxvcyByZXRyYXNhZG9zCmRlbGF5X3BlcmNlbnRhZ2VfcGVyX21vbnRoIDwtIHRvdGFsX2ZsaWdodHNfcGVyX21vbnRoICU+JQogIGxlZnRfam9pbihkZWxheWVkX2ZsaWdodHNfcGVyX21vbnRoLCBieSA9ICJtb250aCIpICU+JQogIG11dGF0ZShkZWxheV9wZXJjZW50YWdlID0gKGRlbGF5ZWRfZmxpZ2h0cyAvIHRvdGFsX2ZsaWdodHMpICogMTAwKQoKIyBHcsOhZmljbyBkZSBsw61uZWEgcGFyYSBlbCBwb3JjZW50YWplIGRlIHZ1ZWxvcyByZXRyYXNhZG9zIHBvciBtZXMKZ2dwbG90KGRlbGF5X3BlcmNlbnRhZ2VfcGVyX21vbnRoLCBhZXMoeCA9IG1vbnRoLCB5ID0gZGVsYXlfcGVyY2VudGFnZSkpICsKICBnZW9tX2xpbmUoY29sb3VyID0gImRhcmtzbGF0ZWdyYXkzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJQb3JjZW50YWplIGRlIFZ1ZWxvcyBSZXRyYXNhZG9zIHBvciBNZXMiLAogICAgICAgeCA9ICJNZXMiLAogICAgICAgeSA9ICJQb3JjZW50YWplIGRlIFZ1ZWxvcyBSZXRyYXNhZG9zIikKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPkludGVycHJldGFjaW9uZXM6IFJldHJhc29zPC9zcGFuPgpBY2VyY8OhbmRvbm9zIG3DoXMgaGFjaWEgZWwgYW7DoWxpc2lzIGZpbmFsIGRlbCBwb3IgcXXDqSBsb3MgdnVlbG9zIHNlIHJldHJhc2FuIGVuIGxvcyBhZXJvcHVlcnRvcyBkZSBOdWV2YSBZb3JrLCBzZSBvYnR1dm8gZWwgYXRyYXNvIGVuIHRpZXBvIHByb21lZGlvIHBvciBhZXJvbMOtbmVhLCBvcmlnZW4geSBtZXMuCkVuIGxhIGdyw6FmaWNhIGRlIGJhcnJhcyBzZSBtdWVzdHJhIGVsIHByaW1lciBhbsOhbGlzaXMgZGUgYXRyYXNvIHByb21lZGlvIHBvciBvcmlnZW4sIGRhbmRvIGNvbW8gcmVzdWx0YWRvIHF1ZSBlbCBhZXJvcHVlcnRvICoqRVdSKiogZXMgZWwgcXVlIGN1ZW50YSBjb24gdW4gbWF5b3IgYXRyYXNvIHByb21lZGlvLCBjb24gdW4gdG90YWwgZGVsIDE1LjExIG1pbnV0b3MgZGUgYXRyYXNvLCBhIGVzdGUgbGUgc2lndWUgKipKSyoqIGNvbiB1biB0b3RhbCBkZSAxMi4xMSBtaW51dG9zIGRlIGF0cmFzbywgeSBjb24gZWwgbWVub3IgcHJvbWVkaW8gc2UgZW5jdWVudHJhICoqTEdBKiogY29uIHVuIHRvdGFsIGRlIDEwLjM1IG1pbnRvcyBkZSBhdHJhc28uIAoKRW4gbGEgc2VndW5kYSBncsOhZmljYSBkZSBiYXJyYXMgc2UgcHJlc2VudGEgZWwgYXRyYXNvIHByb21lZGlvIHBvciBjYXJyaWVyLCBkYW5kbyBjb21vIHJlc3VsdGFkb3MgcHJpbmNpcGFsZXMgcXVlICpGcm9udGllciBBaXJsaW5lcyBJbmMuKiAoRjkpIGVzIGxhIGFlcm9sw61uZWEgcXVlIGN1ZW50YSBjb24gdW4gbWF5b3IgYXRyYXNvIHByb21lZGlvIGRlIGRlIDIwLjIyIG1pbnV0b3MsIGVuIGNhbWJpbyBsYSBhZXJvbMOtbmVhIGNvbiBlbCBtZW5vciBhdHJhc28gcHJvbWVkaW8gZXMgKlVTIEFpcndheXMgSW5jLiogY29uIHVuIHRvdGFsIGRlIDMuNzggbWludXRvcyBkZSBhdHJhc28uCgpQYXJhIGxhIHRlcmNlcmEgZ3LDoWZpY2EgZGUgbMOtbmVhLCBzZSBwcmVzZW50YSBlbCBhdHJhc28gcHJvbWVkaW8gcG9yIG1lcywgZW4gZG9uZGUgc2UgZGVzdGFjYSBxdWUgZWwgbWVzIGRlIEp1bGlvIGVzIGVsIHF1ZSBjdWVudGEgY29uIHVuIG1heW9yIHRpZW1wbyBkZSBhdHJhc28gZW4gcHJvbWVkaW8sIGNvbiB1biB0b3RhbCBkZSAyMS43MyBtaW51dG9zLiBFbiBzZWd1bmRvIGx1Z2FyIHNlIGVuY3VlbnRyYSBKdW5pbywgY29uIHVuIHRpZW1wbyBkZSBhdHJhc28gZW4gcHJvbWVkaW8gZGUgMjAuODUgbWludXRvcywgeSBlbiB0ZXJjZXIgbHVnYXIgc2UgZW5jdWVudHJhIGRpY2llbWJyZSwgY29uIHVuIHRvdGFsIGRlIGF0cmFzbyBwcm9tZWRpbyBkZSAxNi41NyBtaW51dG9zLiBFbCBhdHJhc28gcHJvbWVkaW8gZW4gZWwgbWVzLCBzZSBwdWVkZSBkZWJlciBhbCBwcmluY2lwYWwgZmFjdG9yIGRlIHRlbXBvcmFkYXMgYWx0YXMgdmFjYWNpb25hbGVzLgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5SZXRyYXNvIHBvciB0aXBvIGRlIGF2acOzbjwvc3Bhbj4KUmV0cmFzbyBwb3IgdGlwbyBkZSBhdmnDs24KYGBge3J9CiMgUmV0cmFzbyBwb3IgdGlwbyBkZSBhdmnDs24KcmV0cmFzb19wb3JfYXZpb24gPC0gZmxpZ2h0cyAlPiUKICBsZWZ0X2pvaW4ocGxhbmVzLCBieSA9ICJ0YWlsbnVtIikgJT4lCiAgZ3JvdXBfYnkodHlwZSkgJT4lCiAgc3VtbWFyaXplKGF2Z19kZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKQoKIyBHcsOhZmljbyBkZSBiYXJyYXMgcGFyYSByZXRyYXNvIHBvciB0aXBvIGRlIGF2acOzbgpnZ3Bsb3QocmV0cmFzb19wb3JfYXZpb24sIGFlcyh4ID0gdHlwZSwgeSA9IGF2Z19kZWxheSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJza3libHVlIikgKwogIGxhYnModGl0bGUgPSAiUmV0cmFzbyBQcm9tZWRpbyBwb3IgVGlwbyBkZSBBdmnDs24iLAogICAgICAgeCA9ICJUaXBvIGRlIEF2acOzbiIsCiAgICAgICB5ID0gIlJldHJhc28gUHJvbWVkaW8iKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIENhbGN1bGFyIGVsIG7Dum1lcm8gdG90YWwgZGUgdnVlbG9zIHBvciB0aXBvIGRlIGF2acOzbgp0b3RhbF9mbGlnaHRzX3Blcl90eXBlIDwtIGZsaWdodHMgJT4lCiAgbGVmdF9qb2luKHBsYW5lcywgYnkgPSAidGFpbG51bSIpICU+JQogIGdyb3VwX2J5KHR5cGUpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9mbGlnaHRzID0gbigpKQoKIyBDYWxjdWxhciBlbCBuw7ptZXJvIGRlIHZ1ZWxvcyByZXRyYXNhZG9zIHBvciB0aXBvIGRlIGF2acOzbgpkZWxheWVkX2ZsaWdodHNfcGVyX3R5cGUgPC0gZmxpZ2h0cyAlPiUKICBmaWx0ZXIoZGVwX2RlbGF5ID4gMCkgJT4lCiAgbGVmdF9qb2luKHBsYW5lcywgYnkgPSAidGFpbG51bSIpICU+JQogIGdyb3VwX2J5KHR5cGUpICU+JQogIHN1bW1hcml6ZShkZWxheWVkX2ZsaWdodHMgPSBuKCkpCgojIFVuaXIgbG9zIGRhdG9zIHkgY2FsY3VsYXIgZWwgcG9yY2VudGFqZSBkZSB2dWVsb3MgcmV0cmFzYWRvcwpyZXRyYXNvX3Bvcl9hdmlvbiA8LSB0b3RhbF9mbGlnaHRzX3Blcl90eXBlICU+JQogIGxlZnRfam9pbihkZWxheWVkX2ZsaWdodHNfcGVyX3R5cGUsIGJ5ID0gInR5cGUiKSAlPiUKICBtdXRhdGUoZGVsYXlfcGVyY2VudGFnZSA9IChkZWxheWVkX2ZsaWdodHMgLyB0b3RhbF9mbGlnaHRzKSAqIDEwMCkKCiMgR3LDoWZpY28gZGUgYmFycmFzIHBhcmEgcmV0cmFzbyBwb3IgdGlwbyBkZSBhdmnDs24KZ2dwbG90KHJldHJhc29fcG9yX2F2aW9uLCBhZXMoeCA9IHR5cGUsIHkgPSBkZWxheV9wZXJjZW50YWdlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInNreWJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJQb3JjZW50YWplIGRlIFZ1ZWxvcyBSZXRyYXNhZG9zIHBvciBUaXBvIGRlIEF2acOzbiIsCiAgICAgICB4ID0gIlRpcG8gZGUgQXZpw7NuIiwKICAgICAgIHkgPSAiUG9yY2VudGFqZSBkZSBWdWVsb3MgUmV0cmFzYWRvcyIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5SZXRyYXNvIHBvciBkw61hIGRlIGxhIHNlbWFuYTwvc3Bhbj4KUmV0cmFzbyBwb3IgZMOtYSBkZSBsYSBzZW1hbmEKYGBge3J9CiMgUmV0cmFzbyBwb3IgZMOtYSBkZSBsYSBzZW1hbmEKcmV0cmFzb19wb3JfZGlhX3NlbWFuYSA8LSBmbGlnaHRzICU+JQogIG11dGF0ZSh3ZWVrZGF5ID0gd2Vla2RheXMoYXMuRGF0ZShwYXN0ZSh5ZWFyLCBtb250aCwgZGF5LCBzZXAgPSAiLSIpKSkpICU+JQogIGdyb3VwX2J5KHdlZWtkYXkpICU+JQogIHN1bW1hcml6ZShhdmdfZGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkKCiMgT3JkZW5hciBkw61hcyBkZSBsYSBzZW1hbmEKcmV0cmFzb19wb3JfZGlhX3NlbWFuYSR3ZWVrZGF5IDwtIGZhY3RvcihyZXRyYXNvX3Bvcl9kaWFfc2VtYW5hJHdlZWtkYXksIGxldmVscyA9IGMoIk1vbmRheSIsICJUdWVzZGF5IiwgIldlZG5lc2RheSIsICJUaHVyc2RheSIsICJGcmlkYXkiLCAiU2F0dXJkYXkiLCAiU3VuZGF5IikpCgojIEdyw6FmaWNvIGRlIGJhcnJhcyBwYXJhIHJldHJhc28gcG9yIGTDrWEgZGUgbGEgc2VtYW5hCmdncGxvdChyZXRyYXNvX3Bvcl9kaWFfc2VtYW5hLCBhZXMoeCA9IHdlZWtkYXksIHkgPSBhdmdfZGVsYXkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiYmx1ZSIpICsKICBsYWJzKHRpdGxlID0gIlJldHJhc28gUHJvbWVkaW8gcG9yIERpYSBkZSBsYSBTZW1hbmEiLAogICAgICAgeCA9ICJEaWEgZGUgbGEgU2VtYW5hIiwKICAgICAgIHkgPSAiUmV0cmFzbyBQcm9tZWRpbyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCgpgYGAKCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlJldHJhc28gcG9yIGhvcmEgZGVsIGTDrWE8L3NwYW4+ClJldHJhc28gcG9yIGhvcmEgZGVsIGTDrWEKYGBge3J9CiMgUmV0cmFzbyBwb3IgaG9yYSBkZWwgZMOtYQpmbGlnaHRzJGhvdXIgPC0gYXMuaW50ZWdlcihmbGlnaHRzJGhvdXIpIAptZWFuX2RlbGF5X3Blcl9ob3VyIDwtIGFnZ3JlZ2F0ZShkZXBfZGVsYXkgfiBob3VyLCBmbGlnaHRzLCBtZWFuKQpnZ3Bsb3QoZGF0YSA9IG1lYW5fZGVsYXlfcGVyX2hvdXIsIGFlcyh4ID0gaG91ciwgeSA9IGRlcF9kZWxheSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJza3libHVlIikgKwogIGxhYnMoeCA9ICJIb3JhIGRlbCBkw61hIiwgeSA9ICJSZXRyYXNvIHByb21lZGlvIChtaW51dG9zKSIsIAogICAgICAgdGl0bGUgPSAiUmV0cmFzbyBwcm9tZWRpbyBwb3IgaG9yYSBkZWwgZMOtYSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+SW50ZXJwcmV0YWNpb25lczogUmV0cmFzb3M8L3NwYW4+CkVuIGVsIGFuw6FsaXNpcyBhbnRlcmlvciwgYWhvcmEgc2UgdG9tYSBlbiBjdWVudGEgZWwgcmV0cmFzbyBwcm9tZWRpbyBwb3IgdGlwbyBkZSBhdmnDs24sIGVsIHJldHJhc28gcG9yIGTDrWEgZGUgbGEgc2VtYW5hLCB5IHJldHJhc28gcG9yIGhvcmEgZGVsIGTDrWEuIAoKRWwgcHJpbWVyIHJldHJhc28gYW5hbGl6YWRvIGZ1ZSBwb3IgZWwgdGlwbyBkZSBhdmnDs24sIGVsIGN1YWwgbm9zIHByZXNlbnRhIHF1ZSBsb3MgdGlwb3MgZGUgYXZpb25lcyAqUm90b3JjcmFmdCogc29uIGxvcyBxdWUgY3VlbnRhbiBjb24gdW4gbWF5b3IgYXRyYXNvIHByb21lZGlvLCBkYW5kbyBjb21vIHJlc3VsdGFkbyB1biB0b3RhbCBkZSAxNC4xNyBtaW51dG9zIGRlIHJldHJhc28uIEEgZXN0ZSBsZSBzaWd1ZSBsb3MgdGlwb3MgZGUgYXZpb25lcyBkZSAqRml4ZWQgd2luZyBtdWx0aSBlbmdpbmUqIGNvbiB1biB0b3RhbCBkZSAxMy4xOSBtaW51dG9zIGRlIHJldHJhc28uIFBvciDDumx0aW1vIGVsIHRpcG8gZGUgYXZpw7NuIGNvbiBtZW5vciBjYW50aWRhZCBkZSByZXRyYXNvIHByb21lZGlvIGVzIGVsICpGaXhlZCB3aW5nIHNpbmdsZSBlbmdpbmUqIGNvbiB1biB0b3RhbCBkZSAxMC41MCBtaW51dG9zLiBBIHBlc2FyIGRlIHF1ZSBleGlzdGVuIGVzb3MgdHJlcyB0aXBvcyBkZSBhdmlvbmVzLCBsYSBncsOhZmljYSB0YW1iacOpbiBub3MgbXVlc3RyYSBsb3MgTkEgY29uIHVuIHRvdGFsIGRlIDkuNSBtaW51dG9zIGRlIGF0cmFzbyBwcm9tZWRpby4KCkVuIGxhIHNlZ3VuZGEgZ3LDoWZpY2Egc2UgcHJlc2VudGEgZWwgYXRyYXNvIHByb21lZGlvIHBvciBkw61hIGRlIGxhIHNlbWFuYSwgZG9uZGUgc2UgZGVzdGFjYSBxdWUgbG9zIGp1ZXZlcyBzb24gbG9zIGTDrWFzIGNvbiBtYXlvciBhdHJhc28gcHJvbWVkaW8sIGNvbiB1biB0b3RhbCBkZSAxNi4xNSBtaW51dG9zLiBQb3Igb3RyYSBwYXJ0ZSwgZWwgZMOtYSBjb24gbWVub3IgYXRyYXNvIHByb21lZGlvIHNvbiBsb3Mgc8OhYmFkb3MsIGNvbiB1biB0b3RhbCBkZSA3LjY1IG1pbnV0b3MuCgpFbiBsYSB0ZXJjZXIgZ3LDoWZpY2Egc2UgbXVlc3RyYSBlbCBhdHJhc28gcHJvbWVkaW8gcG9yIGhvcmEgZGVsIGTDrWEsIGVuIGxhIGN1w6FsIGVzIHZpc2libGUgdW4gY3JlY2ltaWVudG8gZW4gcmV0cmFzb3MgZW50cmUgbG9zIGhvcmFyaW9zIGRlIGxhcyAxNTowMCB5IDIwOjAwIGhvcmFzLCBkZXNwdcOpcyBkZSBlc3RvIGRpc21pbnV5ZSBwYXJhIGxvcyB2dWVsb3MgZGUgbGFzIDU6MDAgYSAxMDowMCBob3Jhcy4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+QW7DoWxpc2lzIGRlbCBDbGltYTwvc3Bhbj4KIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5SZXRyYXNvIHByb21lZGlvIHBvciBodW1lZGFkIHJlbGF0aXZhPC9zcGFuPgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpmbGlnaHRzX3dlYXRoZXI8LSBtZXJnZSh3ZWF0aGVyLCBmbGlnaHRzKQpmbGlnaHRzX3dlYXRoZXIgJT4lCiAgZ3JvdXBfYnkoaHVtaWQpICU+JQogIHN1bW1hcmlzZShkZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBodW1pZCwgeSA9IGRlbGF5KSkgKwogIGxhYnMoeCA9ICJIdW1lZGFkIHJlbGF0aXZhIiwgeSA9ICJSZXRyYXNvIHByb21lZGlvIChtaW51dG9zKSIsIGZpbGwgPSAiQWVvcm9wdWVydG8iKSArCiAgZ2d0aXRsZSgiUmV0cmFzbyBwcm9tZWRpbyBwb3IgaHVtZWRhZCByZWxhdGl2YSIpICsKICBnZW9tX2xpbmUoKSArIGdlb21fcG9pbnQoKSsgdGhlbWUocGxvdC50aXRsZT0gZWxlbWVudF90ZXh0KGhqdXN0PTAuNSkpCmBgYAojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlJldHJhc28gcHJvbWVkaW8gcG9yIHRlbXBlcmF0dXJhPC9zcGFuPgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpmbGlnaHRzX3dlYXRoZXIgJT4lCiAgZ3JvdXBfYnkodGVtcCkgJT4lCiAgc3VtbWFyaXNlKGRlbGF5ID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVFJVRSkpICU+JQogIGdncGxvdChhZXMoeCA9IHRlbXAsIHkgPSBkZWxheSkpICsKICBsYWJzKHggPSAiVGVtcGVyYXR1cmEiLCB5ID0gIlJldHJhc28gcHJvbWVkaW8gKG1pbnV0b3MpIiwgZmlsbCA9ICJBZW9yb3B1ZXJ0byIpICsKICBnZ3RpdGxlKCJSZXRyYXNvIHByb21lZGlvIHBvciBUZW1wZXJhdHVyYSIpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKCkrIHRoZW1lKHBsb3QudGl0bGU9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUpKQpgYGAKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5SZXRyYXNvIHByb21lZGlvIHBvciB2ZWxvY2lkYWQgZGVsIHZpZW50bzwvc3Bhbj4KYGBge3Igd2FybmluZz1GQUxTRX0KZmxpZ2h0c193ZWF0aGVyICU+JQogIGdyb3VwX2J5KHdpbmRfc3BlZWQpICU+JQogIHN1bW1hcmlzZShkZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB3aW5kX3NwZWVkLCB5ID0gZGVsYXkpKSArCiAgbGFicyh4ID0gIlZlbG9jaWRhZCBkZWwgVmllbnRvIiwgeSA9ICJSZXRyYXNvIHByb21lZGlvIChtaW51dG9zKSIpICsKICBnZ3RpdGxlKCJSZXRyYXNvIHByb21lZGlvIHBvciBWZWxvY2lkYWQgZGVsIFZpZW50byIpICsKICBnZW9tX3Ntb290aCgpKyB0aGVtZShwbG90LnRpdGxlPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41KSkKYGBgCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+UmV0cmFzbyBwcm9tZWRpbyBwb3IgZGlyZWNjacOzbiBkZWwgdmllbnRvPC9zcGFuPgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpmbGlnaHRzX3dlYXRoZXIgJT4lCiAgZ3JvdXBfYnkod2luZF9kaXIpICU+JQogIHN1bW1hcmlzZShkZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB3aW5kX2RpciwgeSA9IGRlbGF5KSkgKwogIGxhYnMoeCA9ICJEaXJlY2Npw7NuIGRlbCBWaWVudG8iLCB5ID0gIlJldHJhc28gcHJvbWVkaW8gKG1pbnV0b3MpIikgKwogIGdndGl0bGUoIlJldHJhc28gcHJvbWVkaW8gcG9yIERpcmVjY2nDs24gZGVsIFZpZW50byIpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyAKICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChoanVzdD0wLjUpKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+UmV0cmFzbyBwcm9tZWRpbyBwb3IgdmlzaWJpbGlkYWQgZW4gZWwgYWlyZTwvc3Bhbj4KYGBge3Igd2FybmluZz1GQUxTRX0KZmxpZ2h0c193ZWF0aGVyICU+JQogIGdyb3VwX2J5KHZpc2liKSAlPiUKICBzdW1tYXJpc2UoZGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdmlzaWIsIHkgPSBkZWxheSkpICsKICBsYWJzKHggPSAiVmlzaWJpbGlkYWQiLCB5ID0gIlJldHJhc28gcHJvbWVkaW8gKG1pbnV0b3MpIikgKwogIGdndGl0bGUoIlJldHJhc28gcHJvbWVkaW8gcG9yIFZpc2liaWxpZGFkIGVuIGVsIGFpcmUiKSArCiAgZ2VvbV9saW5lKCkgKyAKICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChoanVzdD0wLjUpKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+SW50ZXJwcmV0YWNpb25lczogQW7DoWxpc2lzIGRlbCBDbGltYTwvc3Bhbj4KRW4gZWwgYW7DoWxpc2lzIGRlbCBjbGltYSwgcHJpbWVybyBzZSBvYnR1dm8gZWwgcmV0cmFzbyBwcm9tZWRpbyBwb3IgaHVtZWRhZCByZWxhdGl2YSwgZW4gZG9uZGUgbXVlc3RyYSBxdWUgaGF5ICBhdHJhc29zIGRlIHVuYSBtYXlvciBjYW50aWRhZCBkZSB0aWVtcG8gZW50cmUgZWwgNzUlIHkgMTAwJSBkZSBsYSBodW1lZGFkIHJlbGF0aXZhLiBEZXNwdcOpcywgc2Ugb2J0dXZvIGVsIGF0cmFzbyBwcm9tZWRpbyBwb3IgbGEgdGVtcGVyYXR1cmEsIGVuIGVzdGUgZ3LDoWZpY28gc2UgZGVzdGFjYSBxdWUgcHVlZGUgdmFyaWFyIG11Y2hvIGxhIHRlbXBlcmF0dXJhIHkgZWwgdGllbXBvIHF1ZSBzZSByZXRyYXNhIGxvcyB2dWVsb3MuIAoKRWwgdGVyY2VyIGFuw6FsaXNpcyB1dGlsaXphIGVsIHJldHJhc28gcHJvbWVkaW8gcG9yIHZlbG9jaWRhZCBkZWwgdmllbnRvLCBlbiBkb25kZSBzaSBsYSB2ZWxvY2lkYWQgc2UgZW5jdWVudHJhIGVudHJlIGVsIDMwIHkgNDAsIGV4aXN0ZSBsYSBwcm9iYWJpbGlkYWQgZGUgcXVlIGxvcyBhdHJhc29zIHNlYW4gbWF5b3JlcyBhIGxvcyAyMCBtaW51dG9zLiBEZXNwdcOpcyBzZSBvYnR1dm8gZWwgYXRyYXNvIHByb21lZGlvIHBvciBkaXJlY2Npw7NuIGRlbCB2aWVudG8sIHF1ZSBncmFjaWFzIGEgbGEgdmlzdWFsaXphY2nDs24gZGUgbGEgZ3LDoWZpY2EgZGUgYmFycmFzLCBzaSBsYSBkaXJlY2Npw7NuIGRlbCB2aWVudG8gc2UgZW5jdWVudHJhIGVuIHVuIGVzdGltYWRvIGVudHJlIDgwIHkgMTUwLCBleGlzdGUgdW4gYXRyYXNvIHByb21lZGlvIG1heW9yLiBQb3Igw7psdGltbyBzZSBvYnR1dm8gZWwgYXRyYXNvIHByb21lZGlvIHBvciBsYSB2aXNpYmlsaWRhZCBlbiBlbCBhaXJlLCBlbiBlbCBxdWUgaGFjaWVuZG8gdW4gZXN0aW1hZG8sIHNpIGxhIHZpc2liaWxpZGFkIHNlIGVuY3VuZXRyYSBlbnRyZSAwLjAgeSAyLjUsIGxvcyB2dWVsb3MgdGllbmRlbiBhIHRlbmVyIHVuIG1heW9yIGF0cmFzbyBwcm9tZWRpbywgZGUgYWxyZWRlZG9yIGRlIDMwIGEgNTAgbWludXRvcy4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+Q29uY2x1c2lvbmVzIGRlIHJldHJhc29zPC9zcGFuPgpFbiBlc3RhIGFjdGl2aWRhZCBkZSBtYW5lcmEgZ3J1cGFsLCBkZXRlcm1pbmFtb3MgZWwgcG9yIHF1w6kgc2UgcmV0cmFzYW4gbG9zIHZ1ZWxvcyBlbiBsb3MgYWVyb3B1ZXJ0b3MgZGUgTnVldmEgWW9yay4gU2Ugb2J0dXZvIGluZm9ybWFjacOzbiBtdXkgaW50ZXJlc2FudGUgYSB0cmF2w6lzIGRlIGxvcyBkaWZlcmVudGVzIGFuw6FsaXNpcyBkZSBsYXMgYmFzZXMgZGUgZGF0b3MuICAKCkVuIHByaW1lcmEgaW5zdGFuY2lhIHNlIG9idHV2byBlbCBhdHJhc28gcG9yIG9yaWdlbiwgZW4gZG9uZGUgbm9zIG1vc3Ryw7MgZWwgdGllbXBvIGRlIGF0cmFzbyBwcm9tZWRpbyBlbiBjYWRhIHVubyBkZSBsb3MgdHJlcyBhZXJvcHVlcnRvcyBkaXNwb25pYmxlcywgZGFuZG8gY29tbyByZXN1bHRhZG8gcXVlIGVsIGFlcm9wdWVydG8gY29uIG1heW9yIGF0cmFzbyBlbiBwcm9tZWRpbyBlcyBlbCAqKkVXUioqLiBFbCBzaWd1aWVudGUgYW7DoWxpc2lzIGZ1ZSBlbCBhdHJhc28gcG9yIENhcnJpZXIsIGVuIGRvbmRlIHNlIG9idHV2byBlbCBhdHJhc28gcHJvbWVkaW8gcG9yIGFlcm9sw61uZWE7IDlFICgqRW5kZXZvaXIgQWlyKikgb2J0dXZvIGVsIG1heW9yIHJlc3VsdGFkbyBlbiBhdHJhc28gcHJvbWVkaW8uICAKCkRlc3DDumVzIG5vcyBlbmZvY2Ftb3MgbcOhcyBlbiBlbCBtZXMgZW4gZWwgcXVlIGhhYsOtYSBtYXlvcmVzIHJldHJhc29zLCBkYW5kbyBjb21vIHJlc3VsdGFkbyB0ZW1wb3JhZGFzIGFsdGFzIHBhcmEgdmlhamFyLCBwb3IgZWplbXBsbyBlbiBwcmltZXIgbHVnYXIgZGVsIG1lcyBjb24gbWF5b3IgcmV0cmFzbyBzZSBlbmNvbnRyYWJhIEp1bGlvLCBhcHJveGltYWRhbWVudGUgc29sbyBwb3IgdW4gbWludXRvIG1heW9yIGEgSnVuaW8sIHkgYSBlc3RlIGxlIHNlZ3XDrWEgZGljaWVtYnJlIGVuIGVsIHRlcmNlciBwdWVzdG8uIFNpIHRvbWFtb3MgZW4gY3VlbnRhIHF1ZSBtdWNoYXMgcGVyc29uYXMgdmlhamFuIGVuIGRpY2hhcyB0ZW1wb3JhZG9zIHBvciBlbCB2ZXJhbm8geSBsYXMgZmllc3RhcyBkZWNlbWJyaW5hcywgbG8gcXVlIG9jYXNpb25hIHF1ZSBoYXlhIG1heW9yIGNhbnRpZGFkIGRlIHBlcnNvbmFzIGVuIG1vdmlsaWRhZCBlbiBhZXJvcHVlcnRvcywgcG9kcsOtYSBzZXIgdW4gaW1wb3J0YW50ZSBmYWN0b3IgZGVsIHBvciBxdcOpIGxvcyB2dWVsb3Mgc2UgcmV0cmFzYW4gbcOhcyBlbiBkaWNoYXMgdGVtcG9yYWRhcy4gIAoKUmVhbGl6YW1vcyB1biBtb2RlbG8gZGVsIHByb21lZGlvIGRlbCByZXRyYXNvIGRlIHNhbGlkYSBlbiBmdW5jacOzbiBkZWwgbWVzLCBsbyBxdWUgbm9zIG11ZXN0cmEgY29uIG1heW9yIGNsYXJpZGFkLCBxdWUgbGFzIHRlbXBvcmFkYXMgYWx0YXMgZGUgdmlhamVzIHNvbiB1biBmYWN0b3IgcXVlIGluZmx1eWUgZW4gbG9zIHJldHJhc29zIGdlbmVyYWRvcyBlbiBsb3MgYWVyb3B1ZXJ0b3MgZGUgTnVldmEgWW9yay4KClBvciDDumx0aW1vIHNlIHJlYWxpemFyb24gbG9zIGFuw6FsaXNpcyBkZWwgY2xpbWEsIGNvbnNpZGVyYW5kbyBkaWZlcmVudGVzIHZhcmlhYmxlcywgeWEgc2VhIGxhIGRpcmVjY2nDs24gZGUgdmllbnRvLCBzdSB2aXNpYmlsaWRhZCwgbGEgaHVtZWRhZCByZWxhdGl2YSB5IGxhIHRlbXBlcmF0dXJhLCBlbiBsb3MgY3XDoWxlcyBzZSBub3MgbXVlc3RyYSBxdWUgc2luIGR1ZGEgc29uIHVuIGZhY3RvciBpbXBvcnRhbnRlIGEgY29uc2lkZXJhciBkZW50cm8gZGVsIHBvciBxdcOpIGxvcyB2dWVsb3Mgc2UgcmV0cmFzYW4sIGVzdGUgcHVudG8gZXMgZXhwbGljYWRvIGNvbiBtYXlvciBkZXRlbmltaWVudG8gZW4gbGFzIGludGVycHJldGFjaW9uZXMgYW50ZXJpb3Jlcy4KCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPkVqZXJjaWNpb3MgZGUgZXZpZGVuY2lhIGVuIGNsYXNlPC9zcGFuPiAKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5FeHRyYSAxLiBDb25zdWx0YSBsYSBlc3RydWN0dXJhIGRlICJmbGlnaHRzIjwvc3Bhbj4gCmBgYHtyfQpzdHIoZmxpZ2h0cykKIyBpbnQ6IGVudGVybyAoc2luIGRlY2ltYWxlcykKIyBudW06IG51bcOpcmljbyAoY29uIGRlY2ltYWxlcykKIyBjaHI6IGNhcmFjdMOpciAobGV0cmFzKQojIERhdGU6IGZlY2hhIChlbiBSIHZhIGHDsW8tbWVzLWTDrWEpCiMgUE9TSVhjdDogZm9ybWF0byBmZWNoYSB5IGhvcmEKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPkV4dHJhIDIuIMK/Q3XDoWwgZXMgbGEgY2xhc2UgZGUgImZsaWdodHMiIHkgcXVlIHNpZ25pZmljYT88L3NwYW4+IApgYGB7cn0KY2xhc3MoZmxpZ2h0cykKCiMgTGFzIDUgY2xhc2VzIGRlIG9iamV0b3Mgc29uOgojIDEuIG51bWVyaWM6IE7Dum1lcm8gcmVhbCBvIGRlY2ltYWxlcy4KIyAyLiBpbnRlZ2VyOiBOw7ptd2VvcyBlbnRlcm9zCiMgMy4gY29tcGxleDogTsO6bWVyb3MgY29tcGxlam9zCiMgNC4gY2hhcmFjdGVyOiBjYXLDoWN0ZXJlcwojIDUuIGxvZ2ljYWw6IFRSVUUgTyBGQUxTRQoKIyBMYXMgNCBjbGFzZXMgZGUgb2JqZXRvcyBjb21wdWVzdG9zIHNvbjoKIyAxLiBsaXN0OiBsaXN0YQojIDIuIG1hdHJpeDogbWF0cml6CiMgMy4gYXJyYXk6IGNvbGVjY2nDs24gZGUgb2JqZXRvcwojIDQuIGRhdGEuZnJhbWU6IGJhc2UgZGUgZGF0b3MKCmBgYAojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPkV4dHJhIDMuIMK/Q3XDoW50YXMgY29sdW1uYXMgeSByZW5nbG9uZXMgdGllbmUgImZsaWdodHMiPyDCv0N1w6FsIGVzIHN1IGRpbWVuc2nDs24/PC9zcGFuPiAKYGBge3J9CiMgTsO6bWVybyBkZSBjb2x1bW5hcwpuY29sKGZsaWdodHMpCiMgTsO6bWVybyBkZSByZW5nbG9uZXMKbnJvdyhmbGlnaHRzKQojIERpbWVuc2nDs24KZGltKGZsaWdodHMpCmBgYAojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPkV4dHJhIDQuIE11ZXN0cmEgbG9zIHByaW1lcm9zIDYgcmVuZ2xvbmVzIGRlICJmbGlnaHRzIi4gVGFtYmnDqW4gbG9zIMO6bHRpbW9zIDYuPC9zcGFuPiAKYGBge3J9CmhlYWQoZmxpZ2h0cykKdGFpbChmbGlnaHRzKQojIFNpIHF1aXNpZXJhbW9zIDcgcmVuZ2xvbmVzOiBoZWFkKGZsaWdodHMsNykKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPkNvbXByb21pc28gw6l0aWNvIHkgY2l1ZGFkYW5vPC9zcGFuPiAKRWwgdmFsb3IgZGUgbGEgaW50ZWdyaWRhZCwgc2Vnw7puIGxhcyBOYWNpb25lcyBVbmlkYXMsIHZpZW5lIGRlIGxhIHByw6FjdGljYSBkZSBzZXIgdW5hIHBlcnNvbmEgaG9uZXN0YSwgcXVlIHNlIGFkaGllcmUgYSBzdXMgdmFsb3JlcyB5IHF1ZSBsYSB0b21hIGRlIGRlY2lzaW9uZXMgZXMgc2lzdGVtw6F0aWNhbWVudGUgcG9zaXRpdmEuIExhIGludGVncmlkYWQgZXMgbGEgZm9ybWEgZGUgYWN0dWFyIGRlIGFjdWVyZG8gYSBsb3MgcHJpbmNpcGlvcywgYSBkaWZlcmVuY2lhIGRlIGxhIGhvbmVzdGlkYWQgcXVlIGVzIGVsIGFjdG8gZGUgc2VyIHZlcmF6LiAoTmFjaW9uZXMgVW5pZGFzKSAgClBvciBsYSBwYXJ0ZSBkZWwgY29tcHJvbWlzbyDDqXRpY28sIHNlZ8O6biBtaWVtYnJvcyBkZSBsYSBVbml2ZXJzaXRhdCBkZSBCYXJjZWxvbmEsIGVzIGxhIGNhcGFjaWRhZCBkZSBhY3R1YXIgY29uIGxhcyB2aXJ0dWRlcyBwZXJzb25hbGVzIHkgcHJvZmVzaW9uYWxlcyBxdWUgcmVxdWllcmUgZWwgY29ycmVjdG8gZWplcmNjaW8gZGUgdW5hIHByb2Zlc2nDs24sIGVsIGRlc2Fycm9sbG8gcGVyc29uYWwgeSBsYSBjaXVkYWRhbsOtYSBkZW1vY3LDoXRpY2EsIHRvZG8gZXN0byBkZW50cm8gZGUgdW4gY29udGV4dG8gdW5pdmVyc2l0YXJpby4gKE1hdXJpLcOBbHZhcmV6LCBNYXJnYXJpdGEsIGV0IGFsKQoKUG9yIMO6bHRpbW8sIGVsIGNvbXByb21pc28gY2l1ZGFkYW5vIGxvIHBvZGVtb3MgZGlmZXJlbmNpYXIgZGUgbGEgcGFydGljaXBhY2nDs24gY2l1ZGFkYW5hLiBFbCBjb21wcm9taXNvIGJ1c2NhIHVuIGRpw6Fsb2dvIGFjdGl2byBlbnRyZSBsYSB0b21hIGRlIGRlY2lzaW9uZXMgeSBsb3MgY2l1ZGFkYW5vcy4oTG9kZXdpamNreCwgSWxvbmEpIApUZW5lciB1biBjb21wcm9taXNvIMOpdGljbyB5IGNpdWRhZGFubyBmdWUgdW4gcHVudG8gY2xhdmUgcGFyYSBsYSBlbGFib3JhY2nDs24gZGUgZXN0YSBldmlkZW5jaWEuCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHB1cnBsZTsiPlJlZmxleGnDs24gUGVyc29uYWw6IE5hbmN5IE1hcnJvcXXDrW48L3NwYW4+IAotIFJlZmxleGnDs24gcGVyc29uYWw6IEVsIHJlc3BldG8geSBsYSBob25lc3RpZGFkIGZvcm1hbiBwYXJ0ZSBkZSBsb3MgdmFsb3JlcyBxdWUgdHJhdG8gZGUgcmVwcmVzZW50YXIgZW4gbWkgZMOtYSBhIGTDrWEuIEVuIGN1YWxxdWllIHRpcG8gZGUgcHJveWVjdG8gZW4gZWwgcXVlIHBhcnRpY2lwbywgYnVzY28gcXVlIGVzdGUgc2UgbGxldmUgYSBjYWJvIGRlIG1hbmVyYSBtw6FzIHRyYW5wYXJlbnRlLCBmb21lbnRhbmRvIGxhIGNvbXVuaWNhY2nDs24geSBsYSBlc2N1Y2hhIGFjdGl2YS4gRW4gZWwgbXVuZG8gZGUgbG9zIG5lZ29jaW9zIGZvbWVudGFyIGVzdG9zIHZhbG9yZXMgdGFuIGltcG9ydGFudGVzLCBzb24gY2xhdmUgcGFyYSBlbCDDqXhpdG8gZGUgbGFzIGVtcHJlc2FzLiBFbCBhY3R1YSBkZSBtYW5lcmEgaG9uZXN0YSB5IGNvbiByZXNwZXRvIGhhY2lhIGxvcyBkZW3DoXMsIHRlIHBlcm1pdGUgdGVuZXIgdW4gbWVqb3IgZGVzYXJyb2xsbyBwZXJzb25hbCB5IHByb2Zlc2lvbmFsLiBTaSBub3MgZW5mb2NhbW9zIG3DoXMsIGhhY2lhIGxhIHBhcnRlIGRlIGFuw6FsaXNpcyBkZSBkYXRvcyB5IGVsIHVzbyBkZSBkYXRvcyBkZSBsYXMgZW1wcmVzYXMsIGVsIHJlcGV0byB5IGxhIGhvbmVzdGlkYWQsIG5vIHNvbiBsb3Mgw7puaWNvcyB2YWxvcmVzIHF1ZSBzZSBwcm9tdWV2ZW4sIHNpbm8gcXVlIHRhbWJpw6luIGxhIGNvbmZpYW56YSwgZWwgY29tcHJvbWlzbyB5IGxhIGludGVncmlkYWQuIEFsIHRyYWJhamFyIGNvbiBpbmZvcm1hY2nDs24gZGUgbGEgZW1wcmVzYXMgZXMgbmVjZXNhcmlvIHRlbmVyIG11Y2hvIGN1aWRhZG8gY8OzbW8gZXMgcXVlIHNlIHV0aWxpemEgeSBjdcOhbCBlcyBzdSBwcm9ww7NzaXRvLiBEZSBlc3RhIG1hbmVyYSBlcyBwb3NpYmxlIGdlbmVyYXIgdW5hIG1lam9yIHRvbWEgZGUgZGVjaXNpb25lcyByZXBlY3RvIGFsIHVzbyB5IGRlc2Fycm9sbG8gZGUgZGljaG9zIGRhdG9zLgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5SZWZsZXhpw7NuIFBlcnNvbmFsOiBLZXZpbiBNZXphPC9zcGFuPiAKLSBSZWZsZXhpw7NuIHBlcnNvbmFsOiBMYSByZXNwb25zYWJpbGlkYWQsIGVzIHVuIHZhbG9yIGVsIGN1YWwgdmEgZGUgbGEgbWFubyBjb24gdHJhbnNwYXJlbmNpYSBlIGludGVncmlkYWQuIEVsIHNlcmxvIGFsIGxsZXZhciBhIGNhYm8gZW4gZWwgdXNvIGRlIGRhdG9zLCBlcyBhc3VtaXIgbGFzIGNvbnNlY3VlbmNpYXMgZGUgbGFzIGFjY2lvbmVzIHRvbWFkYXMgeSBnYXJhbnRpemFyIHF1ZSBzZSBjdW1wbGFuIGxvcyBwcmluY2lwaW8gw6l0aWNvcyB5IGxlZ2FsZXMgZGVsIG1vbWVudG8uIE90cm8gcHVudG8gcmVsZXZhbnRlIGEgY29uc2lkZXJhciBlcyBsYSDDqXRpY2EgZW4gbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGJhc2FkYXMgZW4gZGF0b3MuIEVzIGZ1bmRhbWVudGFsIHF1ZSBsYXMgZGVjaXNpb25lcyBlbXByZXNhcmlhbGVzIHNlIHRvbWVuIGNvbnNpZGVyYW5kbyBubyBzb2xvIGxhIGluZm9ybWFjacOzbiBkaXNwb25pYmxlLCBzaW5vIHRhbWJpw6luIGxvcyB2YWxvcmVzIMOpdGljb3MgcXVlIGd1w61hbiBlbCBjb21wb3J0YW1pZW50byBkZSBxdWllbmVzIGdlc3Rpb25hbiBkaWNob3MgZGF0b3MuICAKQXNpbWlzbW8sIHNlIHB1ZWRlIGRlc3RhY2FyIGxhIGltcG9ydGFuY2lhIGRlIGxhIGNvbmZpYW56YSBjb21vIHJlc3VsdGFkbyBkZSBsYSBjb21iaW5hY2nDs24gZGUgZXN0b3MgdmFsb3JlcyDDqXRpY29zLiBMYSBjb25maWFuemEgdGFudG8gaW50ZXJuYSBjb21vIGV4dGVybmEgc2UgY29uc3RydXllIGEgcGFydGlyIGRlIGxhIGNvaGVyZW5jaWEgZW50cmUgbG8gcXVlIHNlIGRpY2UgeSBsbyBxdWUgc2UgaGFjZSBlbiByZWxhY2nDs24gY29uIGxvcyBkYXRvcyBlbXByZXNhcmlhbGVzLgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBwdXJwbGU7Ij5SZWZsZXhpw7NuIFBlcnNvbmFsOiBBZHJpw6FuIE1vcmFsZXM8L3NwYW4+IAotIFJlZmxleGnDs24gcGVyc29uYWw6IERlc2RlIG1pIHB1bnRvIGRlIHZpc3RhLCBjb25zaWRlcm8gcXVlIGxhIGludGVncmlkYWQgZXMgZnVuZGFtZW50YWwgcGFyYSBsYSBob25lc3RpZGFkIHkgbGEgY29oZXJlbmNpYSBlbiB0b2RvcyBsb3MgYXNwZWN0b3MgZGUgbGEgdmlkYS4gRW4gZWwgY2FtcG8gZGUgbGEgaW50ZWxpZ2VuY2lhIGRlIG5lZ29jaW9zLCBkb25kZSBtZSBkZXNlbXBlw7FvIGNvbW8gZXN0dWRpYW50ZSwgZWwgY8OzZGlnbyDDqXRpY28gZGUgbnVlc3RyYSBkaXNjaXBsaW5hIGFjdMO6YSBjb21vIGVsIGd1w61hIHF1ZSBvcmllbnRhIG1pIGNvbXBvcnRhbWllbnRvIHByb2Zlc2lvbmFsLiBFc3RlIGPDs2RpZ28gbm8gc29sYW1lbnRlIGVzdGFibGVjZSBsYSBvYmxpZ2FjacOzbiBkZSBtYW5lamFyIGxhIGluZm9ybWFjacOzbiBkZSBmb3JtYSBwcmVjaXNhIHkgY29uZmlkZW5jaWFsLCBzaW5vIHF1ZSB0YW1iacOpbiByZXNhbHRhIGxhIGltcG9ydGFuY2lhIGRlIHV0aWxpemFyIGVsIGNvbm9jaW1pZW50byBhZHF1aXJpZG8gZGUgbWFuZXJhIGVxdWl0YXRpdmEgeSBjbGFyYS4gVGVuZXIgYWNjZXNvIGEgbGEgaW5mb3JtYWNpw7NuIGRlIHVuYSBlbXByZXNhIGNvbmxsZXZhIHVuYSBncmFuIHJlc3BvbnNhYmlsaWRhZCBkZSBtYW5lamFybGEgY29uIGN1aWRhZG8sIGdhcmFudGl6YW5kbyBsYSBjb25maWRlbmNpYWxpZGFkIHkgZXZpdGFuZG8gY29uZmxpY3RvcyBkZSBpbnRlcsOpcywgYXBsaWNhbmRvIGFuw6FsaXNpcyDDqXRpY29zIHF1ZSBiZW5lZmljaWUgYSBsYSBvcmdhbml6YWNpw7NuIHkgYSBsYSBzb2NpZWRhZCBlbiBnZW5lcmFsLiBBbCBmaW5hbCBkZWwgZMOtYSwgbWFudGVuZXIgbGEgaW50ZWdyaWRhZCBlbiBsYSBnZXN0acOzbiBkZSBkYXRvcyBkZSBsYSBlbXByZXNhIG5vIHNvbG8gbXVlc3RyYSBtaSBkZWRpY2FjacOzbiBhIGxhIMOpdGljYSBsYWJvcmFsLCBzaW5vIHF1ZSB0YW1iacOpbiBhdW1lbnRhIGxhIGNvbmZpYW56YSB5IGNyZWRpYmlsaWRhZCBlbiBlbCBjYW1wbyBkZSBsYSBpbnRlbGlnZW5jaWEgZW1wcmVzYXJpYWwKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcHVycGxlOyI+UmVmbGV4acOzbiBQZXJzb25hbDogS2FybGEgTMOzcGV6PC9zcGFuPiAKLSBSZWZsZXhpw7NuIHBlcnNvbmFsOiBMYSBpbnRlZ3JpZGFkIHNlIHB1ZWRlIGRlZmluaXIgY29tbyBsYSBjYWxpZGFkIGRlIHNlciBob25lc3RvLCDDqXRpY28geSBtb3JhbCBlbiB0b2RhcyBsYXMgYWNjaW9uZXMgeSBkZWNpc2lvbmVzLiBFbiBlbCBjb250ZXh0byBkZSBtaSBkaXNjaXBsaW5hIGFjYWTDqW1pY2EsIGxhIGludGVncmlkYWQgZXMgZnVuZGFtZW50YWwgcGFyYSBtaXMgdHJhYmFqb3MgaW5kaXZpZHVhbGVzIHkgZ3J1cGFsZXMsIHlhIHF1ZSByZXByZXNlbnRhIGxhIHJlbGFjacOzbiBkZSBtaXMgYWNjaW9uZXMsIHZhbG9yZXMsIHByaW5jaXBpb3MgeSByZXN1bHRhZG9zLiBBc2ltaXNtbywgZW4gbWkgZGlzY2lwbGluYSBwZXJzb25hbCwgbWUgaW1wdWxzYSBhIHNlciBob25lc3RhLCB0cmFuc3BhcmVudGUgeSByZXNwb25zYWJsZSBlbiBtaXMgYWN0aXZpZGFkZXMsIGFzZWd1cmFuZG8gcXVlIG1pcyBhY2Npb25lcyBzaWVtcHJlIHJlZmxlamVuIG1pcyB2YWxvcmVzIG1vcmFsZXMgeSDDqXRpY29zLiBQb3Igb3RybyBsYWRvLCBlbiBlbCDDoW1iaXRvIHByb2Zlc2lvbmFsLCBlbiB1bmEgZW1wcmVzYSBubyBzb2xvIHNlIGJ1c2NhIGNvbnRhciBjb24gdW4gY29tcHJvbWlzbyBjb24gbGEgaW5mb3JtYWNpw7NuIHByb3BvcmNpb25hZGEgc2lubyB0YW1iacOpbiBjb24gZWwgZXF1aXBvIHkgbGFzIGhlcnJhbWllbnRhcywgeWEgcXVlIGVzIGZ1bmRhbWVudGFsIG1hbnRlbmVyIHVuYSBjb25kdWN0YSDDqXRpY2EgdGFudG8gZW4gbGFzIHJlbGFjaW9uZXMgY29uIGxvcyBjb21wYcOxZXJvcyBjb21vIGVuIGVsIHVzbyBkZSBsb3MgcmVjdXJzb3MgZGlzcG9uaWJsZXMgcGFyYSBlbCBkZXNhcnJvbGxvIHkgZWwgw6l4aXRvIGRlIGxhIGVtcHJlc2EuCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPkNvbmNsdXNpw7NuIEdlbmVyYWw8L3NwYW4+IApUcmFzIGV4YW1pbmFyIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbCwgc2UgcHVkbyBvYnNlcnZhciBxdWUgZWwgODguNjglIGRlIGxhIHZhcmlhYmlsaWRhZCBlbiBsYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSAocmV0cmFzbyBlbiBsb3MgdnVlbG9zKSBzZSBwdWVkZSBleHBsaWNhciB1dGlsaXphbmRvIGxhcyB2YXJpYWJsZXMgaW5kZXBlbmRpZW50ZXMuIExhcyBjdWFsZXMgc2UgaWRlbnRpZmljYXJvbiBjaWVydGFzIHZhcmlhYmxlcyBxdWUgbXVlc3RyYW4gdW5hIHNpZ25pZmljYW5jaWEgZXN0YWTDrXN0aWNhLCBjb24gdmFsb3JlcyBkZSBwIG1lbm9yZXMgYSAwLjAwMSwgbG8gcXVlIGRlbXVlc3RyYSBxdWUgdGllbmVuIHVuIGltcGFjdG8gc2lnbmlmaWNhdGl2bywgbG8gcXVlIHNpZ25pZmljYSBxdWUgdGllbmVuIHVuYSByZWxhY2nDs24gZGlyZWN0YSB5IGzDs2dpY2EgY29uIGVsIHJldHJhc28gZGUgbG9zIHZ1ZWxvcywgbGFzIGN1YWxlcyBmdWVyb246CgpkZXBfdGltZTogUmF6b25lcyBwb3IgbGFzIGN1YWxlcyBlbCB0aWVtcG8gZGUgc2FsaWRhIHB1ZWRlIGFmZWN0YXIgYSBsb3MgdnVlbG9zIHB1ZWRlbiBzZXIgcHJvYmxlbWFzIGRlIGdlc3Rpw7NuIHBvciBwYXJ0ZSBkZSBsYXMgYWVyb2zDrW5lYXMsIGNvbW8gZGlmaWN1bHRhZGVzIG9wZXJhdGl2YXMgcmVsYWNpb25hZGFzIGNvbiBlbCBlcXVpcG8gbyBlbCBwZXJzb25hbCwgbyBwcm9ibGVtYXMgZW4gZWwgYWVyb3B1ZXJ0by4oKioqKQoKYXJyX2RlbGF5OiBSZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbiBsYSBjb25leGnDs24gZGUgbGFzIGxsZWdhZGFzIHRhcmTDrWFzIGNvbiBsYXMgc2FsaWRhcy4gKCoqKikKCmFpcl90aW1lOiBBbCBlc3RhciBtw6FzIGV4cHVlc3RvcyBlbiBlbCBhaXJlLCBsb3MgdnVlbG9zIHB1ZWRlbiBzdWZyaXIgcHJvYmxlbWFzIGNsaW3DoXRpY29zLCBlc2NhbGFzLCBwcm9jZXNvcyBkZSBzZWd1cmlkYWQsIGVudHJlIG90cm9zLiAoKioqKQoKZGVzdDogTG9zIHZ1ZWxvcyBwdWVkZW4gdmVyc2UgYWZlY3RhZG9zIHBvciBhbGd1bm9zIGRlc3Rpbm9zIGRvbmRlIGhheSB0csOhZmljbyBhw6lyZW8sIGNvbmRpY2lvbmVzIG1ldGVvcm9sw7NnaWNhcyBsb2NhbGVzIG8gY29uZ2VzdGnDs24gZGVsIGFlcm9wdWVydG8gZGUgZGVzdGlubywgcXVlIHN1Y2VkZSBmcmVjdWVudGVtZW50ZSBlbiBjaXVkYWRlcyBncmFuZGVzLigqKiopCgp3aW5kX3NwZWVkOiBSZWxhY2nDs24gZW50cmUgbGEgdmVsb2NpZGFkIGRlbCB2aWVudG8geSBsb3MgcmV0cmFzb3MgZW4gbGEgc2FsaWRhIGRlIGxvcyB2dWVsb3MuIFB1ZWRlIHNlciBvY2FzaW9uYWRvIHBvciBvcGVyYWNpw7NuIGVuIGVsIHZ1ZWxvIG8gZGUgc2VndXJpZGFkLCBwcm9jZWRpbWllbnRvcyBkZSBzZWd1cmlkYWQsIGVudHJlIG90cm9zLiAoKiopCgp3aW5kX2RpcjogUmVsYWNpw7NuIGVudHJlIGxhIGRpcmVjY2nDs24gZGVsIHZpZW50byB5IGxvcyByZXRyYXNvcywgcXVlIHB1ZWRlbiBzZXIgZGViaWRvcyBwb3IgbGFzIGNvbmRpY2lvbmVzIGRlIHZ1ZWxvLCBwcm9jZWRpbWllbnRvcyBkZSBkZXNwZWd1ZSwgZW50cmUgb3Ryb3MuICgqKikKClBvciBsbyBjdWFsLCBzdWdpZXJlIHF1ZSB1bmEgdmFyaWVkYWQgZGUgdmFyaWFibGVzLCB0YW50byByZWxhY2lvbmFkYXMgY29uIGxhIG9wZXJhY2nDs24gZGUgbGFzIGFlcm9sw61uZWFzIGNvbW8gY29uIGxhcyBjb25kaWNpb25lcyBtZXRlb3JvbMOzZ2ljYXMsIHB1ZWRlbiBjb250cmlidWlyIGEgbG9zIHJldHJhc29zIGVuIGxhIHNhbGlkYSBkZSBsb3MgdnVlbG9zLgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5CaWJsaW9ncmFmw61hczwvc3Bhbj4gCipCZXJyZW5kZXJvLCBKLiBSLiAobi5kLikuIFVuYSBicmV2ZSBpbnRyb2R1Y2Npw7NuIGEgZ2dwbG90Mi4gaHR0cDovL3ZlcnNvLm1hdC51YW0uZXMvfmpvc2VyLmJlcnJlbmRlcm8vUi9pbnRyb2dncGxvdDIuaHRtbAoKKiBFbCB2YWxvciBkZSB2YWxvcmVzOiBMYSBpbnRlZ3JpZGFkIHwgTGlua2VkSW4uIChuLmQuKS4gaHR0cHM6Ly93d3cubGlua2VkaW4uY29tL3B1bHNlL2VsLXZhbG9yLWRlLXZhbG9yZXMtbGEtaW50ZWdyaWRhZC1tYXJsZXRoLW1vcmFsZXMvP29yaWdpbmFsU3ViZG9tYWluPWVzCgoqIOKAnExhIENpZW5jaWEgZGUgTGEgSW50ZWdyaWRhZC7igJ0gTmFjaW9uZXMgVW5pZGFzIDogT2ZpY2luYSBkZSBMYXMgTmFjaW9uZXMgVW5pZGFzIENvbnRyYSBMYSBEcm9nYSBZIEVsIERlbGl0bywgd3d3LnVub2RjLm9yZy91bm9kYy9lcy9saXN0ZW4tZmlyc3Qvc3VwZXItc2tpbGxzL2ludGVncml0eS5odG1sLgoKKiBMb2Rld2lqY2t4LCBJbG9uYS4g4oCcwr9DdcOhbCBFcyBMYSBEaWZlcmVuY2lhIEVudHJlIEVsIENvbXByb21pc28gQ2l1ZGFkYW5vIFkgTGEgUGFydGljaXBhY2nDs24/4oCdIENpdGl6ZW5MYWLigJlzIEJsb2csIDI5IEp1bmUgMjAyMCwgd3d3LmNpdGl6ZW5sYWIuY28vYmxvZy9wYXJ0aWNpcGFjaW9uLWNpdWRhZGFuYS9jdWFsLWVzLWxhLWRpZmVyZW5jaWEtZW50cmUtZWwtY29tcHJvbWlzby1jaXVkYWRhbm8teS1sYS1wYXJ0aWNpcGFjaW9uLz9sYW5nPWVzLiBBY2Nlc3NlZCAxMiBNYXIuIDIwMjQuCgoqIE1hdXJpLcOBbHZhcmV6LCBNYXJnYXJpdGEsIGV0IGFsLiDigJxDb21wcm9taXNvIMOJdGljbyBZIFJlc3BvbnNhYmlsaWRhZCBFbiBFbCBDb250ZXh0byBVbml2ZXJzaXRhcmlvLuKAnSBSRUlSRSBSZXZpc3RhIGTigJlJbm5vdmFjacOzIEkgUmVjZXJjYSBFbiBFZHVjYWNpw7MsIHZvbC4gMTUsIG5vLiAxLCAyIERlYy4gMjAyMSwgZGlwb3NpdC51Yi5lZHUvZHNwYWNlL2JpdHN0cmVhbS8yNDQ1LzE5NDM0MS8xLzcyMTUxNy5wZGYsIGh0dHBzOi8vZG9pLm9yZy8xMC4xMzQ0L3JlaXJlLjM2OTcwLiBBY2Nlc3NlZCAyOSBBdWcuIDIwMjMKCiogUlB1YnMgLSBGdW5jacOzbiBnZ3Bsb3QoKSBkZSBnZ3Bsb3QyLiAobi5kLikuIGh0dHBzOi8vcnB1YnMuY29tL2RhbmliYWxsYXJpL2dncGxvdAoKKiBSbHQuIChuLmQuKS5HcsOhZmljb3MgZGUgYmFycmFzIGNvbiBnZW9tX2Jhci4gaHR0cHM6Ly9yYXltb25kbHRyZW1ibGF5LmdpdGh1Yi5pby9BTkFMSVRJQ0EvRzdfZ2VvbV9iYXIuaHRtbAo=