Contexto

El paquete nycflights13 contiene información sore todos los vueles 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 ocnjuntos 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

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)
#install.packages("broom")
library(broom)

Guardar base de datos

flights <- flights
weather <- weather
planes <- planes
airports <- airports
airlines <- airlines
bdgrande <-merge(flights,airlines, by="carrier")
bdgrande2 <-left_join(bdgrande,planes, by="tailnum")
bdgrande3 <- left_join(bdgrande2,weather,by=c("origin","time_hour"))
bdgrande4 <- left_join(bdgrande3, airports, by = c("origin" = "faa"))
bdgrande5 <- left_join(bdgrande4, airports, by = c("dest" = "faa"))

dim(bdgrande5)
## [1] 336776     55

Relación entre las bases de datos

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

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

Ejercicios

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

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

# La carga a a memoria se hizo en el paso anterior
flights
## # A tibble: 336,776 × 19
##     year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
##  1  2013     1     1      517            515         2      830            819
##  2  2013     1     1      533            529         4      850            830
##  3  2013     1     1      542            540         2      923            850
##  4  2013     1     1      544            545        -1     1004           1022
##  5  2013     1     1      554            600        -6      812            837
##  6  2013     1     1      554            558        -4      740            728
##  7  2013     1     1      555            600        -5      913            854
##  8  2013     1     1      557            600        -3      709            723
##  9  2013     1     1      557            600        -3      838            846
## 10  2013     1     1      558            600        -2      753            745
## # ℹ 336,766 more rows
## # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## #   hour <dbl>, minute <dbl>, time_hour <dttm>

2. Consulta la estructura de “flights”

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

3. ¿Cuál es la clase “flights” y qué significa?

class(flights)
## [1] "tbl_df"     "tbl"        "data.frame"
# Las 5 clases de objetos
# 1. numeric: Número real o décimal
# 2. integer: Números enteros
# 3. Complex: Números complejos
# 4. Character: Caractéres 
# 5. Logical: TRUE o FALSE

# Las 4 clases de objetos compuestos son:
# 1. list: lista
# 2. Matrix: Matriz
# 3. Array: colección de objetos
# 4. data.frame: base de datos

4. ¿Cuántas columnas y renglones tiene “flights”?

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

5. Muestra los primeros 6 renglones de “flights”. Tambien los ultimos 6

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

6. Muestra los estadisticos descriptivos de “flights”

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  
## 

Conclusión

En este trabajo pudimos utlizar las funciones más comunes del análisis exploratorio, el cual es el primer paso para cualquier trabajo de manipulación de datos.

Evidencia 1 Analítica descriptiva

Exploración

Flights

# Consulta la estructura de cada data frame
# Para el data frame flights
data(flights) 
str(flights)
## tibble [336,776 × 19] (S3: tbl_df/tbl/data.frame)
##  $ year          : int [1:336776] 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month         : int [1:336776] 1 1 1 1 1 1 1 1 1 1 ...
##  $ day           : int [1:336776] 1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_time      : int [1:336776] 517 533 542 544 554 554 555 557 557 558 ...
##  $ sched_dep_time: int [1:336776] 515 529 540 545 600 558 600 600 600 600 ...
##  $ dep_delay     : num [1:336776] 2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_time      : int [1:336776] 830 850 923 1004 812 740 913 709 838 753 ...
##  $ sched_arr_time: int [1:336776] 819 830 850 1022 837 728 854 723 846 745 ...
##  $ arr_delay     : num [1:336776] 11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ carrier       : chr [1:336776] "UA" "UA" "AA" "B6" ...
##  $ flight        : int [1:336776] 1545 1714 1141 725 461 1696 507 5708 79 301 ...
##  $ tailnum       : chr [1:336776] "N14228" "N24211" "N619AA" "N804JB" ...
##  $ origin        : chr [1:336776] "EWR" "LGA" "JFK" "JFK" ...
##  $ dest          : chr [1:336776] "IAH" "IAH" "MIA" "BQN" ...
##  $ air_time      : num [1:336776] 227 227 160 183 116 150 158 53 140 138 ...
##  $ distance      : num [1:336776] 1400 1416 1089 1576 762 ...
##  $ hour          : num [1:336776] 5 5 5 5 6 5 6 6 6 6 ...
##  $ minute        : num [1:336776] 15 29 40 45 0 58 0 0 0 0 ...
##  $ time_hour     : POSIXct[1:336776], format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...
ncol(flights)
## [1] 19
nrow(flights)
## [1] 336776
dim(flights)
## [1] 336776     19
head(flights)
## # A tibble: 6 × 19
##    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
## 1  2013     1     1      517            515         2      830            819
## 2  2013     1     1      533            529         4      850            830
## 3  2013     1     1      542            540         2      923            850
## 4  2013     1     1      544            545        -1     1004           1022
## 5  2013     1     1      554            600        -6      812            837
## 6  2013     1     1      554            558        -4      740            728
## # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## #   hour <dbl>, minute <dbl>, time_hour <dttm>
tail(flights)
## # A tibble: 6 × 19
##    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
## 1  2013     9    30       NA           1842        NA       NA           2019
## 2  2013     9    30       NA           1455        NA       NA           1634
## 3  2013     9    30       NA           2200        NA       NA           2312
## 4  2013     9    30       NA           1210        NA       NA           1330
## 5  2013     9    30       NA           1159        NA       NA           1344
## 6  2013     9    30       NA            840        NA       NA           1020
## # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## #   hour <dbl>, minute <dbl>, time_hour <dttm>
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  
## 

¿Cuáles son los campos y sus tipos de datos? Los campos del conjunto de datos flights y sus tipos de datos son:

  • year: int (entero) - Año del vuelo.
  • month: int (entero) - Mes del vuelo.
  • day: int (entero) - Día del vuelo.
  • dep_time: int (entero) - Hora de salida real del vuelo.
  • sched_dep_time: int (entero) - Hora de salida programada del vuelo.
  • dep_delay: num (número) - Retraso de salida en minutos.
  • arr_time: int (entero) - Hora de llegada real.
  • sched_arr_time: int (entero) - Hora de llegada programada.
  • arr_delay: num (número) - Retraso de llegada en minutos.
  • carrier: chr (carácter) - Código de la aerolínea.
  • flight: int (entero) - Número del vuelo.
  • tailnum: chr (carácter) - Número de cola del avión.
  • origin: chr (carácter) - Aeropuerto de origen.
  • dest: chr (carácter) - Aeropuerto de destino.
  • air_time: num (número) - Tiempo en el aire en minutos.
  • distance: num (número) - Distancia del vuelo en millas.
  • hour: num (número) - Hora programada de salida (hora).
  • minute: num (número) - Hora programada de salida (minutos).
  • time_hour: POSIXct (dttm) - Fecha y hora del vuelo.

weather

# Para el data frame weather
data(weather) 
str(weather)
## tibble [26,115 × 15] (S3: tbl_df/tbl/data.frame)
##  $ origin    : chr [1:26115] "EWR" "EWR" "EWR" "EWR" ...
##  $ year      : int [1:26115] 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month     : int [1:26115] 1 1 1 1 1 1 1 1 1 1 ...
##  $ day       : int [1:26115] 1 1 1 1 1 1 1 1 1 1 ...
##  $ hour      : int [1:26115] 1 2 3 4 5 6 7 8 9 10 ...
##  $ temp      : num [1:26115] 39 39 39 39.9 39 ...
##  $ dewp      : num [1:26115] 26.1 27 28 28 28 ...
##  $ humid     : num [1:26115] 59.4 61.6 64.4 62.2 64.4 ...
##  $ wind_dir  : num [1:26115] 270 250 240 250 260 240 240 250 260 260 ...
##  $ wind_speed: num [1:26115] 10.36 8.06 11.51 12.66 12.66 ...
##  $ wind_gust : num [1:26115] NA NA NA NA NA NA NA NA NA NA ...
##  $ precip    : num [1:26115] 0 0 0 0 0 0 0 0 0 0 ...
##  $ pressure  : num [1:26115] 1012 1012 1012 1012 1012 ...
##  $ visib     : num [1:26115] 10 10 10 10 10 10 10 10 10 10 ...
##  $ time_hour : POSIXct[1:26115], format: "2013-01-01 01:00:00" "2013-01-01 02:00:00" ...
ncol(weather)
## [1] 15
nrow(weather)
## [1] 26115
dim(weather)
## [1] 26115    15
head(weather)
## # A tibble: 6 × 15
##   origin  year month   day  hour  temp  dewp humid wind_dir wind_speed wind_gust
##   <chr>  <int> <int> <int> <int> <dbl> <dbl> <dbl>    <dbl>      <dbl>     <dbl>
## 1 EWR     2013     1     1     1  39.0  26.1  59.4      270      10.4         NA
## 2 EWR     2013     1     1     2  39.0  27.0  61.6      250       8.06        NA
## 3 EWR     2013     1     1     3  39.0  28.0  64.4      240      11.5         NA
## 4 EWR     2013     1     1     4  39.9  28.0  62.2      250      12.7         NA
## 5 EWR     2013     1     1     5  39.0  28.0  64.4      260      12.7         NA
## 6 EWR     2013     1     1     6  37.9  28.0  67.2      240      11.5         NA
## # ℹ 4 more variables: precip <dbl>, pressure <dbl>, visib <dbl>,
## #   time_hour <dttm>
tail(weather)
## # A tibble: 6 × 15
##   origin  year month   day  hour  temp  dewp humid wind_dir wind_speed wind_gust
##   <chr>  <int> <int> <int> <int> <dbl> <dbl> <dbl>    <dbl>      <dbl>     <dbl>
## 1 LGA     2013    12    30    13  37.0  21.9  54.0      340       17.3      20.7
## 2 LGA     2013    12    30    14  36.0  19.9  51.8      340       13.8      21.9
## 3 LGA     2013    12    30    15  34.0  17.1  49.5      330       17.3      21.9
## 4 LGA     2013    12    30    16  32    15.1  49.2      340       15.0      23.0
## 5 LGA     2013    12    30    17  30.9  12.9  46.7      320       17.3      NA  
## 6 LGA     2013    12    30    18  28.9  10.9  46.4      330       18.4      NA  
## # ℹ 4 more variables: precip <dbl>, pressure <dbl>, visib <dbl>,
## #   time_hour <dttm>
summary(weather)
##     origin               year          month             day       
##  Length:26115       Min.   :2013   Min.   : 1.000   Min.   : 1.00  
##  Class :character   1st Qu.:2013   1st Qu.: 4.000   1st Qu.: 8.00  
##  Mode  :character   Median :2013   Median : 7.000   Median :16.00  
##                     Mean   :2013   Mean   : 6.504   Mean   :15.68  
##                     3rd Qu.:2013   3rd Qu.: 9.000   3rd Qu.:23.00  
##                     Max.   :2013   Max.   :12.000   Max.   :31.00  
##                                                                    
##       hour            temp             dewp           humid       
##  Min.   : 0.00   Min.   : 10.94   Min.   :-9.94   Min.   : 12.74  
##  1st Qu.: 6.00   1st Qu.: 39.92   1st Qu.:26.06   1st Qu.: 47.05  
##  Median :11.00   Median : 55.40   Median :42.08   Median : 61.79  
##  Mean   :11.49   Mean   : 55.26   Mean   :41.44   Mean   : 62.53  
##  3rd Qu.:17.00   3rd Qu.: 69.98   3rd Qu.:57.92   3rd Qu.: 78.79  
##  Max.   :23.00   Max.   :100.04   Max.   :78.08   Max.   :100.00  
##                  NA's   :1        NA's   :1       NA's   :1       
##     wind_dir       wind_speed         wind_gust         precip        
##  Min.   :  0.0   Min.   :   0.000   Min.   :16.11   Min.   :0.000000  
##  1st Qu.:120.0   1st Qu.:   6.905   1st Qu.:20.71   1st Qu.:0.000000  
##  Median :220.0   Median :  10.357   Median :24.17   Median :0.000000  
##  Mean   :199.8   Mean   :  10.518   Mean   :25.49   Mean   :0.004469  
##  3rd Qu.:290.0   3rd Qu.:  13.809   3rd Qu.:28.77   3rd Qu.:0.000000  
##  Max.   :360.0   Max.   :1048.361   Max.   :66.75   Max.   :1.210000  
##  NA's   :460     NA's   :4          NA's   :20778                     
##     pressure          visib          time_hour                    
##  Min.   : 983.8   Min.   : 0.000   Min.   :2013-01-01 01:00:00.0  
##  1st Qu.:1012.9   1st Qu.:10.000   1st Qu.:2013-04-01 21:30:00.0  
##  Median :1017.6   Median :10.000   Median :2013-07-01 14:00:00.0  
##  Mean   :1017.9   Mean   : 9.255   Mean   :2013-07-01 18:26:37.7  
##  3rd Qu.:1023.0   3rd Qu.:10.000   3rd Qu.:2013-09-30 13:00:00.0  
##  Max.   :1042.1   Max.   :10.000   Max.   :2013-12-30 18:00:00.0  
##  NA's   :2729

¿Cuáles son los campos y sus tipos de datos? Los campos del conjunto de datos weather y sus tipos de datos son:

  • origin: chr (carácter) - Código del aeropuerto de origen.
  • year: int (entero) - Año de la observación meteorológica.
  • month: int (entero) - Mes de la observación meteorológica.
  • day: int (entero) - Día de la observación meteorológica.
  • hour: int (entero) - Hora de la observación meteorológica.
  • temp: num (número) - Temperatura en grados Fahrenheit.
  • dewp: num (número) - Punto de rocío en grados Fahrenheit.
  • humid: num (número) - Humedad relativa en porcentaje.
  • wind_dir: num (número) - Dirección del viento en grados.
  • wind_speed: num (número) - Velocidad del viento en millas por hora.
  • wind_gust: num (número) - Ráfaga de viento en millas por hora.
  • precip: num (número) - Precipitación en pulgadas.
  • pressure: num (número) - Presión atmosférica en milibares.
  • visib: num (número) - Visibilidad en millas.
  • time_hour: POSIXct (dttm) - Fecha y hora de la observación meteorológica.

planes

# Para el data frame planes
data(planes) 
str(planes)
## tibble [3,322 × 9] (S3: tbl_df/tbl/data.frame)
##  $ tailnum     : chr [1:3322] "N10156" "N102UW" "N103US" "N104UW" ...
##  $ year        : int [1:3322] 2004 1998 1999 1999 2002 1999 1999 1999 1999 1999 ...
##  $ type        : chr [1:3322] "Fixed wing multi engine" "Fixed wing multi engine" "Fixed wing multi engine" "Fixed wing multi engine" ...
##  $ manufacturer: chr [1:3322] "EMBRAER" "AIRBUS INDUSTRIE" "AIRBUS INDUSTRIE" "AIRBUS INDUSTRIE" ...
##  $ model       : chr [1:3322] "EMB-145XR" "A320-214" "A320-214" "A320-214" ...
##  $ engines     : int [1:3322] 2 2 2 2 2 2 2 2 2 2 ...
##  $ seats       : int [1:3322] 55 182 182 182 55 182 182 182 182 182 ...
##  $ speed       : int [1:3322] NA NA NA NA NA NA NA NA NA NA ...
##  $ engine      : chr [1:3322] "Turbo-fan" "Turbo-fan" "Turbo-fan" "Turbo-fan" ...
ncol(planes)
## [1] 9
nrow(planes)
## [1] 3322
dim(planes)
## [1] 3322    9
head(planes)
## # A tibble: 6 × 9
##   tailnum  year type               manufacturer model engines seats speed engine
##   <chr>   <int> <chr>              <chr>        <chr>   <int> <int> <int> <chr> 
## 1 N10156   2004 Fixed wing multi … EMBRAER      EMB-…       2    55    NA Turbo…
## 2 N102UW   1998 Fixed wing multi … AIRBUS INDU… A320…       2   182    NA Turbo…
## 3 N103US   1999 Fixed wing multi … AIRBUS INDU… A320…       2   182    NA Turbo…
## 4 N104UW   1999 Fixed wing multi … AIRBUS INDU… A320…       2   182    NA Turbo…
## 5 N10575   2002 Fixed wing multi … EMBRAER      EMB-…       2    55    NA Turbo…
## 6 N105UW   1999 Fixed wing multi … AIRBUS INDU… A320…       2   182    NA Turbo…
tail(planes)
## # A tibble: 6 × 9
##   tailnum  year type               manufacturer model engines seats speed engine
##   <chr>   <int> <chr>              <chr>        <chr>   <int> <int> <int> <chr> 
## 1 N996DL   1991 Fixed wing multi … MCDONNELL D… MD-88       2   142    NA Turbo…
## 2 N997AT   2002 Fixed wing multi … BOEING       717-…       2   100    NA Turbo…
## 3 N997DL   1992 Fixed wing multi … MCDONNELL D… MD-88       2   142    NA Turbo…
## 4 N998AT   2002 Fixed wing multi … BOEING       717-…       2   100    NA Turbo…
## 5 N998DL   1992 Fixed wing multi … MCDONNELL D… MD-88       2   142    NA Turbo…
## 6 N999DN   1992 Fixed wing multi … MCDONNELL D… MD-88       2   142    NA Turbo…
summary(planes)
##    tailnum               year          type           manufacturer      
##  Length:3322        Min.   :1956   Length:3322        Length:3322       
##  Class :character   1st Qu.:1997   Class :character   Class :character  
##  Mode  :character   Median :2001   Mode  :character   Mode  :character  
##                     Mean   :2000                                        
##                     3rd Qu.:2005                                        
##                     Max.   :2013                                        
##                     NA's   :70                                          
##     model              engines          seats           speed      
##  Length:3322        Min.   :1.000   Min.   :  2.0   Min.   : 90.0  
##  Class :character   1st Qu.:2.000   1st Qu.:140.0   1st Qu.:107.5  
##  Mode  :character   Median :2.000   Median :149.0   Median :162.0  
##                     Mean   :1.995   Mean   :154.3   Mean   :236.8  
##                     3rd Qu.:2.000   3rd Qu.:182.0   3rd Qu.:432.0  
##                     Max.   :4.000   Max.   :450.0   Max.   :432.0  
##                                                     NA's   :3299   
##     engine         
##  Length:3322       
##  Class :character  
##  Mode  :character  
##                    
##                    
##                    
## 

¿Cuáles son los campos y sus tipos de datos? Los campos del conjunto de datos planes y sus tipos de datos son:

  • tailnum: chr (carácter) - Número de cola del avión.
  • year: int (entero) - Año de fabricación del avión.
  • type: chr (carácter) - Tipo de avión, en este caso todos son de ala fija con múltiples motores.
  • manufacturer: chr (carácter) - Fabricante del avión.
  • model: chr (carácter) - Modelo del avión.
  • engines: int (entero) - Número de motores del avión.
  • seats: int (entero) - Número de asientos del avión.
  • speed: int (entero) - Velocidad del avión, aunque la mayoría de los registros parecen no tener esta información (NA).
  • engine: chr (carácter) - Tipo de motor del avión, la mayoría son turbofán.

airports

# Para el data frame airports
data(airports) 
str(airports)
## tibble [1,458 × 8] (S3: tbl_df/tbl/data.frame)
##  $ faa  : chr [1:1458] "04G" "06A" "06C" "06N" ...
##  $ name : chr [1:1458] "Lansdowne Airport" "Moton Field Municipal Airport" "Schaumburg Regional" "Randall Airport" ...
##  $ lat  : num [1:1458] 41.1 32.5 42 41.4 31.1 ...
##  $ lon  : num [1:1458] -80.6 -85.7 -88.1 -74.4 -81.4 ...
##  $ alt  : num [1:1458] 1044 264 801 523 11 ...
##  $ tz   : num [1:1458] -5 -6 -6 -5 -5 -5 -5 -5 -5 -8 ...
##  $ dst  : chr [1:1458] "A" "A" "A" "A" ...
##  $ tzone: chr [1:1458] "America/New_York" "America/Chicago" "America/Chicago" "America/New_York" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   id = col_double(),
##   ..   name = col_character(),
##   ..   city = col_character(),
##   ..   country = col_character(),
##   ..   faa = col_character(),
##   ..   icao = col_character(),
##   ..   lat = col_double(),
##   ..   lon = col_double(),
##   ..   alt = col_double(),
##   ..   tz = col_double(),
##   ..   dst = col_character(),
##   ..   tzone = col_character()
##   .. )
ncol(airports)
## [1] 8
nrow(airports)
## [1] 1458
dim(airports)
## [1] 1458    8
head(airports)
## # A tibble: 6 × 8
##   faa   name                             lat   lon   alt    tz dst   tzone      
##   <chr> <chr>                          <dbl> <dbl> <dbl> <dbl> <chr> <chr>      
## 1 04G   Lansdowne Airport               41.1 -80.6  1044    -5 A     America/Ne…
## 2 06A   Moton Field Municipal Airport   32.5 -85.7   264    -6 A     America/Ch…
## 3 06C   Schaumburg Regional             42.0 -88.1   801    -6 A     America/Ch…
## 4 06N   Randall Airport                 41.4 -74.4   523    -5 A     America/Ne…
## 5 09J   Jekyll Island Airport           31.1 -81.4    11    -5 A     America/Ne…
## 6 0A9   Elizabethton Municipal Airport  36.4 -82.2  1593    -5 A     America/Ne…
tail(airports)
## # A tibble: 6 × 8
##   faa   name                        lat    lon   alt    tz dst   tzone          
##   <chr> <chr>                     <dbl>  <dbl> <dbl> <dbl> <chr> <chr>          
## 1 ZTY   Boston Back Bay Station    42.3  -71.1    20    -5 A     America/New_Yo…
## 2 ZUN   Black Rock                 35.1 -109.   6454    -7 A     America/Denver 
## 3 ZVE   New Haven Rail Station     41.3  -72.9     7    -5 A     America/New_Yo…
## 4 ZWI   Wilmington Amtrak Station  39.7  -75.6     0    -5 A     America/New_Yo…
## 5 ZWU   Washington Union Station   38.9  -77.0    76    -5 A     America/New_Yo…
## 6 ZYP   Penn Station               40.8  -74.0    35    -5 A     America/New_Yo…
summary(airports)
##      faa                name                lat             lon         
##  Length:1458        Length:1458        Min.   :19.72   Min.   :-176.65  
##  Class :character   Class :character   1st Qu.:34.26   1st Qu.:-119.19  
##  Mode  :character   Mode  :character   Median :40.09   Median : -94.66  
##                                        Mean   :41.65   Mean   :-103.39  
##                                        3rd Qu.:45.07   3rd Qu.: -82.52  
##                                        Max.   :72.27   Max.   : 174.11  
##       alt                tz              dst               tzone          
##  Min.   : -54.00   Min.   :-10.000   Length:1458        Length:1458       
##  1st Qu.:  70.25   1st Qu.: -8.000   Class :character   Class :character  
##  Median : 473.00   Median : -6.000   Mode  :character   Mode  :character  
##  Mean   :1001.42   Mean   : -6.519                                        
##  3rd Qu.:1062.50   3rd Qu.: -5.000                                        
##  Max.   :9078.00   Max.   :  8.000

¿Cuáles son los campos y sus tipos de datos? Los campos del conjunto de datos airports y sus tipos de datos son:

  • origin: chr (carácter) - Código del aeropuerto.
  • name: chr (carácter) - Nombre del aeropuerto.
  • lat: num (número) - Latitud del aeropuerto.
  • lon: num (número) - Longitud del aeropuerto.
  • alt: num (número) - Altitud del aeropuerto en pies.
  • tz: num (número) - Zona horaria del aeropuerto, basada en el desplazamiento del UTC.
  • dst: chr (carácter) - Indicador de horario de verano (p. ej., “A” para horario de verano, “N” para no observarlo).
  • tzone: chr (carácter) - Zona horaria del aeropuerto en texto, por ejemplo, “America/New_York”.

airlines

# Para el data frame airlines
data(airlines) 
str(airlines)
## tibble [16 × 2] (S3: tbl_df/tbl/data.frame)
##  $ carrier: chr [1:16] "9E" "AA" "AS" "B6" ...
##  $ name   : chr [1:16] "Endeavor Air Inc." "American Airlines Inc." "Alaska Airlines Inc." "JetBlue Airways" ...
ncol(airlines)
## [1] 2
nrow(airlines)
## [1] 16
dim(airlines)
## [1] 16  2
head(airlines)
## # A tibble: 6 × 2
##   carrier name                    
##   <chr>   <chr>                   
## 1 9E      Endeavor Air Inc.       
## 2 AA      American Airlines Inc.  
## 3 AS      Alaska Airlines Inc.    
## 4 B6      JetBlue Airways         
## 5 DL      Delta Air Lines Inc.    
## 6 EV      ExpressJet Airlines Inc.
tail(airlines)
## # A tibble: 6 × 2
##   carrier name                  
##   <chr>   <chr>                 
## 1 OO      SkyWest Airlines Inc. 
## 2 UA      United Air Lines Inc. 
## 3 US      US Airways Inc.       
## 4 VX      Virgin America        
## 5 WN      Southwest Airlines Co.
## 6 YV      Mesa Airlines Inc.
summary(airlines)
##    carrier              name          
##  Length:16          Length:16         
##  Class :character   Class :character  
##  Mode  :character   Mode  :character

¿Cuáles son los campos y sus tipos de datos?

Los campos del conjunto de datos airlines y sus tipos de datos son:

  • carrier: chr (carácter) - Código de dos letras de la aerolínea.
  • name: chr (carácter) - Nombre completo de la aerolínea.

Manipulación de datos

1 Consultar dataframe

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

2 Encuentra los datos descriptivos del data frame flights. Identifica la media de las distancias recorridas en millas.

#la media (Mean) de la distancia es de 1040 millas, lo que indica que, en promedio, los vuelos en este conjunto de datos recorren una distancia de 1040 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

df <- flights %>% 
  select(carrier, distance, origin, dest) %>%
  filter(distance > mean(distance, na.rm= TRUE)) %>% 
  arrange(desc(distance))

print(df)
## # A tibble: 127,665 × 4
##    carrier distance origin dest 
##    <chr>      <dbl> <chr>  <chr>
##  1 HA          4983 JFK    HNL  
##  2 HA          4983 JFK    HNL  
##  3 HA          4983 JFK    HNL  
##  4 HA          4983 JFK    HNL  
##  5 HA          4983 JFK    HNL  
##  6 HA          4983 JFK    HNL  
##  7 HA          4983 JFK    HNL  
##  8 HA          4983 JFK    HNL  
##  9 HA          4983 JFK    HNL  
## 10 HA          4983 JFK    HNL  
## # ℹ 127,655 more rows

4. Suma y Media de las distancias recorridas por carrier

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


dfDR <- df %>% 
  group_by(carrier, origin, dest) %>% 
  summarise(suma_distancia= sum(distance, na.rm= TRUE), 
            media_distancia= mean(distance, na.rm= TRUE)) %>% 
# Ordena en forma descendente por distancia recorrida
    arrange(desc(carrier), desc(suma_distancia))
## `summarise()` has grouped output by 'carrier', 'origin'. You can override using
## the `.groups` argument.
dfDR
## # A tibble: 150 × 5
## # Groups:   carrier, origin [26]
##    carrier origin dest  suma_distancia media_distancia
##    <chr>   <chr>  <chr>          <dbl>           <dbl>
##  1 WN      EWR    HOU          1377136            1411
##  2 WN      LGA    DEN          1158300            1620
##  3 WN      EWR    DEN          1105845            1605
##  4 WN      EWR    PHX           919323            2133
##  5 WN      LGA    HOU           606900            1428
##  6 WN      EWR    AUS           448192            1504
##  7 WN      EWR    MSY           347766            1167
##  8 VX      JFK    LAX          4447575            2475
##  9 VX      JFK    SFO          3656604            2586
## 10 VX      EWR    SFO          2008395            2565
## # ℹ 140 more rows

5.Observa tus resultados de la última tabla y agrega tus interpretaciones.

  • Las aerolíneas operan estratégicamente en rutas largas desde aeropuertos específicos para maximizar la eficiencia y satisfacer la demanda del mercado. Este comportamiento se evidencia en la concentración de vuelos de larga distancia operados por aerolíneas específicas desde aeropuertos particulares, como se muestra en los datos recopilados. Por ejemplo, Virgin America (VX) destaca por operar rutas transcontinentales principalmente desde JFK hacia destinos como Los Ángeles (LAX) y San Francisco (SFO), lo cual es indicativo de una estrategia orientada a servir mercados de alto volumen y larga distancia desde un hub estratégico. La evidencia directa de esta afirmación se encuentra en las sumas y medias de distancias recorridas presentadas en la tabla, donde VX opera la ruta JFK-LAX con una suma de distancia de 4447575 millas y una media de 2475 millas, y la ruta JFK-SFO con 3656604 millas en total y una media de 2586 millas. Además, Southwest Airlines (WN) muestra un patrón de operación concentrado en vuelos desde EWR y LGA hacia destinos nacionales clave como Houston (HOU) y Denver (DEN), con sumas de distancia significativas como 1377136 millas para EWR-HOU y 1158300 millas para LGA-DEN, lo que refleja una estrategia orientada a cubrir rutas nacionales de gran demanda desde Nueva York.

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

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

df_JFK <- dfDR %>% 
  filter(origin == "JFK") %>% arrange(carrier, desc(suma_distancia))

df_JFK
## # A tibble: 69 × 5
## # Groups:   carrier, origin [8]
##    carrier origin dest  suma_distancia media_distancia
##    <chr>   <chr>  <chr>          <dbl>           <dbl>
##  1 9E      JFK    MSY           515352            1182
##  2 9E      JFK    DFW           507715            1391
##  3 9E      JFK    MCI           307188            1113
##  4 9E      JFK    SAT            84111            1587
##  5 9E      JFK    AUS             3042            1521
##  6 AA      JFK    LAX          7962075            2475
##  7 AA      JFK    SFO          3677292            2586
##  8 AA      JFK    MIA          2418669            1089
##  9 AA      JFK    SJU          1756202            1598
## 10 AA      JFK    LAS          1436472            2248
## # ℹ 59 more rows
df_LGA <- dfDR %>% 
  filter(origin == "LGA") %>% arrange(carrier, desc(suma_distancia))

df_LGA
## # A tibble: 31 × 5
## # Groups:   carrier, origin [9]
##    carrier origin dest  suma_distancia media_distancia
##    <chr>   <chr>  <chr>          <dbl>           <dbl>
##  1 9E      LGA    MCI            94095            1107
##  2 9E      LGA    SRQ            81666            1047
##  3 9E      LGA    RSW            72360            1080
##  4 9E      LGA    DFW            19446            1389
##  5 9E      LGA    MSY             1183            1183
##  6 AA      LGA    DFW          6717204            1389
##  7 AA      LGA    MIA          4323720            1096
##  8 B6      LGA    FLL          2354288            1076
##  9 B6      LGA    RSW           394200            1080
## 10 B6      LGA    SRQ           382155            1047
## # ℹ 21 more rows
df_EWR <- dfDR %>% 
  filter(origin == "EWR") %>% arrange(carrier, desc(suma_distancia))

df_EWR
## # A tibble: 50 × 5
## # Groups:   carrier, origin [9]
##    carrier origin dest  suma_distancia media_distancia
##    <chr>   <chr>  <chr>          <dbl>           <dbl>
##  1 AA      EWR    DFW          2818088            1372
##  2 AA      EWR    MIA          1158780            1085
##  3 AA      EWR    LAX           895710            2454
##  4 AS      EWR    SEA          1715028            2402
##  5 B6      EWR    FLL          1476090            1065
##  6 B6      EWR    SJU           609432            1608
##  7 B6      EWR    RSW           389820            1068
##  8 DL      EWR    SLC           697026            1969
##  9 EV      EWR    MCI          1480752            1092
## 10 EV      EWR    OMA           852768            1134
## # ℹ 40 more rows

7. Conclusión: Evidencia 1

United Airlines (UA) y American Airlines (AA) emergen como las principales aerolíneas en términos de distancia total de vuelo, principalmente debido a sus operaciones concentradas en los aeropuertos de Newark Liberty International (EWR) y John F. Kennedy International (JFK). Estos aeropuertos, dada su ubicación más alejada del centro de la ciudad y su amplia gama de destinos, facilitan vuelos de mayor duración. Las estadísticas muestran que UA lidera con una distancia media de vuelo de 2565 millas desde EWR y 2586 millas desde JFK, representando las cifras más elevadas comparadas con otras aerolíneas y aeropuertos. Por su parte, AA registra una media de 2475 millas desde EWR y 1703 millas desde JFK, posicionándose como la segunda en este ránking.

Aunque UA y AA dominan en JFK y LaGuardia (LGA) por el volumen de tráfico y la diversidad de rutas, en EWR, United Airlines tiene una presencia predominante en comparación con American Airlines, reflejando una diferencia en la distancia media de vuelo y en el tiempo de viaje. En resumen, United Airlines destaca como la aerolínea con la mayor distancia media de vuelo desde EWR, mientras que American Airlines lidera desde JFK, demostrando su liderazgo en términos de millas aéreas recorridas en comparación con otras compañías. Esta distinción subraya la competitividad y la estrategia de rutas de ambas aerolíneas en los principales aeropuertos de Nueva York.

Evidencia 2 - Analítica descriptiva (Integración de datos a través de modelo entidad-relación) y el compromiso ético y ciudadano

Modelo Entidad-Relación

Información para cada vuelo

#Se necesita saber de cada vuelo, la aerolínea, el aeropuerto de origen y el aeropuerto destino.

dfaerolinea <- df1 %>% 
  left_join(airlines, by= "carrier")

dfaerolinea
## # A tibble: 336,776 × 3
##    carrier flight name                    
##    <chr>    <int> <chr>                   
##  1 UA        1545 United Air Lines Inc.   
##  2 UA        1714 United Air Lines Inc.   
##  3 AA        1141 American Airlines Inc.  
##  4 B6         725 JetBlue Airways         
##  5 DL         461 Delta Air Lines Inc.    
##  6 UA        1696 United Air Lines Inc.   
##  7 B6         507 JetBlue Airways         
##  8 EV        5708 ExpressJet Airlines Inc.
##  9 B6          79 JetBlue Airways         
## 10 AA         301 American Airlines Inc.  
## # ℹ 336,766 more rows
dfaeropuerto_oyd <- flights %>% 
  select(carrier, origin, dest)

dfaeropuerto_oyd
## # A tibble: 336,776 × 3
##    carrier origin dest 
##    <chr>   <chr>  <chr>
##  1 UA      EWR    IAH  
##  2 UA      LGA    IAH  
##  3 AA      JFK    MIA  
##  4 B6      JFK    BQN  
##  5 DL      LGA    ATL  
##  6 UA      EWR    ORD  
##  7 B6      EWR    FLL  
##  8 EV      LGA    IAD  
##  9 B6      JFK    MCO  
## 10 AA      LGA    ORD  
## # ℹ 336,766 more rows

Cantidad de vuelos por destino

# cantidad de vuelos por cada destino
dfcantidad <- flights %>% 
  group_by(carrier) %>% 
  summarise(num_flights= n()) %>% 
  arrange(desc(num_flights))

dfcantidad
## # A tibble: 16 × 2
##    carrier num_flights
##    <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
## 11 FL             3260
## 12 AS              714
## 13 F9              685
## 14 YV              601
## 15 HA              342
## 16 OO               32
#Posteriormente Agregar el nombre de la aerolínea al data frame anterior.

dfnombre <- dfcantidad %>% 
  left_join(airlines, by= "carrier")


dfnombre
## # A tibble: 16 × 3
##    carrier num_flights name                       
##    <chr>         <int> <chr>                      
##  1 UA            58665 United Air Lines Inc.      
##  2 B6            54635 JetBlue Airways            
##  3 EV            54173 ExpressJet Airlines Inc.   
##  4 DL            48110 Delta Air Lines Inc.       
##  5 AA            32729 American Airlines Inc.     
##  6 MQ            26397 Envoy Air                  
##  7 US            20536 US Airways Inc.            
##  8 9E            18460 Endeavor Air Inc.          
##  9 WN            12275 Southwest Airlines Co.     
## 10 VX             5162 Virgin America             
## 11 FL             3260 AirTran Airways Corporation
## 12 AS              714 Alaska Airlines Inc.       
## 13 F9              685 Frontier Airlines Inc.     
## 14 YV              601 Mesa Airlines Inc.         
## 15 HA              342 Hawaiian Airlines Inc.     
## 16 OO               32 SkyWest Airlines Inc.

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

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

hora <- dfAYD %>% 
  mutate(clas_horario = case_when(
                      between(sched_dep_time, 600, 1159) ~ "Mañana",
                      between(sched_dep_time, 1200, 1859) ~ "Tarde",
                      between(sched_dep_time, 1900, 2400) ~ "Noche",
                      TRUE ~ "Madrugada"
                    ))
hora
## # A tibble: 336,776 × 5
##    carrier dest  sched_dep_time name                     clas_horario
##    <chr>   <chr>          <int> <chr>                    <chr>       
##  1 UA      IAH              515 United Air Lines Inc.    Madrugada   
##  2 UA      IAH              529 United Air Lines Inc.    Madrugada   
##  3 AA      MIA              540 American Airlines Inc.   Madrugada   
##  4 B6      BQN              545 JetBlue Airways          Madrugada   
##  5 DL      ATL              600 Delta Air Lines Inc.     Mañana      
##  6 UA      ORD              558 United Air Lines Inc.    Madrugada   
##  7 B6      FLL              600 JetBlue Airways          Mañana      
##  8 EV      IAD              600 ExpressJet Airlines Inc. Mañana      
##  9 B6      MCO              600 JetBlue Airways          Mañana      
## 10 AA      ORD              600 American Airlines Inc.   Mañana      
## # ℹ 336,766 more rows

Cantidad de vuelos por aerolínea y destino que hay por la Mañana, Tarde, Noche y Madrugada

dfCDV <- hora %>%
  group_by(carrier, dest, clas_horario) %>%
  summarise(num_flights = n()) %>%
  arrange(carrier, dest, clas_horario)
## `summarise()` has grouped output by 'carrier', 'dest'. You can override using
## the `.groups` argument.
dfCDV
## # A tibble: 741 × 4
## # Groups:   carrier, dest [314]
##    carrier dest  clas_horario num_flights
##    <chr>   <chr> <chr>              <int>
##  1 9E      ATL   Mañana                59
##  2 9E      AUS   Tarde                  2
##  3 9E      AVL   Mañana                10
##  4 9E      BGR   Noche                  1
##  5 9E      BNA   Mañana                 6
##  6 9E      BNA   Noche                  1
##  7 9E      BNA   Tarde                467
##  8 9E      BOS   Mañana               271
##  9 9E      BOS   Noche                 94
## 10 9E      BOS   Tarde                549
## # ℹ 731 more rows

Destinos a los que vuela American Airlines en Madrugada

# Destinos a los que vuela "American Airlines Inc." durante la Madrugada

dfDaa <- hora %>%
  select(carrier,name, dest,clas_horario) %>% 
  filter(carrier == "AA", clas_horario == "Madrugada") %>% 
  group_by(carrier,name, dest,clas_horario)

dfDaa
## # A tibble: 365 × 4
## # Groups:   carrier, name, dest, clas_horario [1]
##    carrier name                   dest  clas_horario
##    <chr>   <chr>                  <chr> <chr>       
##  1 AA      American Airlines Inc. MIA   Madrugada   
##  2 AA      American Airlines Inc. MIA   Madrugada   
##  3 AA      American Airlines Inc. MIA   Madrugada   
##  4 AA      American Airlines Inc. MIA   Madrugada   
##  5 AA      American Airlines Inc. MIA   Madrugada   
##  6 AA      American Airlines Inc. MIA   Madrugada   
##  7 AA      American Airlines Inc. MIA   Madrugada   
##  8 AA      American Airlines Inc. MIA   Madrugada   
##  9 AA      American Airlines Inc. MIA   Madrugada   
## 10 AA      American Airlines Inc. MIA   Madrugada   
## # ℹ 355 more rows

¿Qué aviones utiliza la aerolínea AA?, y ¿Cuántos vuelos se han realizado con cada uno?

# Conocer los aviones que usa "American Airlines Inc."

dfAAI <- flights %>%
  left_join(planes, by = "tailnum") %>%
  filter(carrier == "AA" & !is.na(type)) %>%
  group_by(carrier, type, engine, seats) %>%
  summarise(num_flights = n()) %>%
  arrange(desc(num_flights))
## `summarise()` has grouped output by 'carrier', 'type', 'engine'. You can
## override using the `.groups` argument.
dfAAI
## # A tibble: 22 × 5
## # Groups:   carrier, type, engine [6]
##    carrier type                     engine        seats num_flights
##    <chr>   <chr>                    <chr>         <int>       <int>
##  1 AA      Fixed wing multi engine  Turbo-fan       255        4257
##  2 AA      Fixed wing multi engine  Turbo-fan       172        3857
##  3 AA      Fixed wing multi engine  Turbo-fan       178         501
##  4 AA      Fixed wing single engine Reciprocating     2         463
##  5 AA      Fixed wing multi engine  Turbo-fan       330         450
##  6 AA      Fixed wing multi engine  Reciprocating     8          92
##  7 AA      Fixed wing single engine Reciprocating     7          63
##  8 AA      Fixed wing single engine Reciprocating    16          63
##  9 AA      Fixed wing single engine Reciprocating     4          56
## 10 AA      Fixed wing single engine 4 Cycle           4          45
## # ℹ 12 more rows

Visualización de Datos

Vuelos con retraso en ida y regreso

#Se solicita analizar para la aerolínea American Airlines si los vuelos que tienen retraso en la partida también tienen retraso en la hora de llegada.Realiza una visualización con una gráfica Scatterplot.

plot(flights$dep_delay, flights$arr_delay,
     main = "Retrasos en la partida y llegada para la aerolínea American Airlines",
     xlab = "Retrasos en la partida",
     ylab = "Retrasos en la llegada",
     col = "blue",
     pch = 1
     )

Tendencia de la temperatura

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

flight_weather <-flights %>% inner_join(weather, by = c("origin" = "origin", "year" = "year", "month" = "month", "day" = "day", "hour" = "hour"))
flight_weather<- mutate(flight_weather, celcius= ((temp-32)*(5/9)))
flight_weather<- mutate(flight_weather, dw_celcius= ((dewp-32)*(5/9)))
flight_weather<- mutate(flight_weather, khm= (wind_speed*1.60934))
flight_weather<- mutate(flight_weather, mm= (precip*25.4))
flight_weather<- mutate(flight_weather, km= (visib*1.60934))


temp_promedio <- flight_weather %>%
  filter(origin == "EWR") %>%
  mutate(date = as.Date(paste(year, month, day, sep = "-"))) %>%
  select(date, celcius) %>%
  group_by(date) %>%
  summarise(temp_promedio = mean(celcius, na.rm = TRUE))

temp_promedio_enero <- temp_promedio %>%
  filter(between(date, as.Date("2013-01-01"), as.Date("2013-01-15")))

plot(temp_promedio_enero$date, temp_promedio_enero$temp_promedio, 
     type = "l",
     main = "Temperatura durante los primeros 15 días de enero en (Newark)",
     xlab = "Fecha",
     ylab = "Temperatura Promedio (C°)")

Temperatura más frecuente

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

weather_enero$date <- as.Date(paste(weather_enero$year, weather_enero$month, weather_enero$day, sep = "-"))

temp_promedio <- weather_enero %>%
  group_by(date) %>%
  summarize(temp_promedio = mean(celcius, na.rm = TRUE))

ggplot(data = temp_promedio, aes(x = temp_promedio)) +
  geom_histogram(binwidth = 5, fill = "purple", color = "black") +
  labs(title = "Histograma de Promedio de Temperaturas del 1 al 15 de Enero",
       x = "Promedio de Temperatura (C°)",
       y = "Frecuencia")

Facets

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

ggplot(data = flight_weather, aes(x = celcius)) +
  geom_histogram(binwidth = 5, color = "red") +
  facet_wrap(~ month, nrow = 4)
## Warning: Removed 17 rows containing non-finite outside the scale range
## (`stat_bin()`).

Vuelos que salieron de Nueva York en el 2013

#Número de vuelos que salieron de Nueva York en 2013 por aerolínea (mostrar solamente las 10 aerolíneas con más vuelos), utilizar gráfica de barras.

flights_table <- flights %>% 
  group_by(carrier) %>% 
  summarize(number = n())
         
ggplot(data = flights_table, mapping = aes(x = carrier, y = number)) +
  geom_col()

Grafica de pie

#Visualiza el punto anterior en una gráfica de pie.
pie(flights_table$number,
    labels = flights_table$carrier,
    main = "Proporción de vuelos por aerolínea",
    col = rainbow(length(flights_table$carrier)),
    cex = 0.5)

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 relación?

flights_airports <- flights %>%
  left_join(airports, by = c("dest" = "faa"))

Data frame

top_carriers <- flights %>%
  inner_join(airports, by = c("origin" = "faa"))
ggplot(data = top_carriers, mapping = aes(x = carrier, fill = name)) +
  geom_bar()

ggplot(data = top_carriers, mapping = aes(x = carrier, fill = name)) +
  geom_bar(position = "dodge")

ggplot(data = top_carriers, mapping = aes(x = carrier, fill = name)) +
  geom_bar() +
  facet_grid(name ~ .)

Conclusiónes

Los vuelos de American Airlines que tienen retraso en la partida entre 0-100 minutos, no tienen retraso en la llegada. Al cruzar de los 100 minutos de retraso en la partida se empieza a notar más el retraso en la llegada. La mayoría de los vuelos que salen tarde reajustan la velocidad en el aire para que la demora de la llegada no sea igual, sino mucho menor. Son minoría los casos que no tienen retraso en la partida y si tienen retraso en la llegada. American Airlines tiene una clara ventaja competitiva porque al analizar los datos de los vuelos, mantienen la gran parte de sus vuelos entre 0-100 minutos de retraso en la partida, los vuelos que se retrasan de más aún así no tienen una gran demora en la llegada. American Airlines se encuentra en un punto alto en relación a su competencia, la aerolínea representa el 9.72% de la cantidad de vuelos por destino, tiene principalmente a 4 competidores superiores (United, JetBlue, ExpressJet y Delta) y 11 inferiores.

Compromiso ético y ciudadano

Describe el valor de la integridad.

  • La integridad implica entereza moral, rectitud, y honradez en la conducta y el comportamiento. Deriva del latín “integrĭtas”, significando totalidad, pureza, e inocencia. En un sentido más amplio, la integridad se relaciona con ser completo, estar intacto, y no estar afectado por el mal o daño, ya sea físico o moral. Además, la integridad personal se asocia con ser educado, honesto, respetuoso consigo mismo y con los demás, y mantener firmeza en las acciones.(Enciclopedia Significados, 2023)

Enciclopedia Significados, E. (2023, 5 mayo). Qué es Integridad (y su significado). Enciclopedia Significados. https://www.significados.com/integridad/

Reflexión Personal:

¿ cómo puedes actuar con respeto y honestidad en los negocios y en el uso de datos cuando realices análisis de datos y estés en contacto con los datos de una empresa?

Alma:Actuar con respeto y honestidad en los negocios y al manejar datos es crucial para mantener la confianza y la integridad. La honestidad promueve prácticas sanas y organizaciones sólidas (Argandoña, 2022), mientras que adherirse a principios éticos asegura transparencia y evita prácticas corruptas, contribuyendo al desarrollo sostenible (abriendomercados.com, 2023). Además, la cortesía y el respeto fortalecen relaciones duraderas, fundamentales para el éxito empresarial (eslabonesdenegocio.com). En resumen, estos valores no solo benefician a las empresas éticamente, sino que también impulsan el crecimiento y la imagen positiva en el mercado.

Diego:Considero que trabajar con datos, es un trabajo que tiene que llevarse a cabo con mucha inteligencia y delicadeza, ya que las empresas te están confiando lo más importante que tienen y eso es su información. Para asegurar la confidencialidad, para mi, el primer paso es trabajar bajo contrato donde se especifique de forma clara, ¿quién tiene acceso a esta información?, ¿a quién se puede acudir en caso de dudas?, ¿para quién va dirigida la información una vez procesada? etc. Es decir, tener bien delimitado el proceso de manipulación que se llevará a cabo. Posteriormente, trabajar de la mano con la empresa, es decir, tenerlos informados en todo momento del proceso y ser transparentes al respecto. Por último, respetar los lineamientos de las empresas y su filosofía empresarial, cada organización tiene una manera de operar y es esencial adaptarse al estilo de trabajo de estas.

Osvaldo:Para mí, la honestidad y respeto provienen de una ética que se comparte en casa o por parte de los maestros, que inculcan dentro de los estudiantes el conocimiento de lo que es correcto y no. En mi caso creo que consiste en proteger la privacidad de los datos, a su vez de obtener el consentimiento para el uso de los datos, y siendo íntegro y guardando la confidencialidad de la información. Para mí es importante evitar cualquier forma de manipulación o uso engañoso e incorrecto de la información. Cumpliendo con las regulaciones de protección de datos, comunicando claramente las políticas de privacidad y seguridad, y llevando a cabo la transparencia en el manejo de datos, así puedo llegar a construir una reputación sólida y ganarme la confianza de posibles clientes, de mis compañeros y profesores. Cualquier duda que tenga con relación al uso de datos que no me pertenecen debo consultarlo con los autores de dichos datos y no dar nada por hecho de mi parte.

Referencias: + Argandoña, A. (2022). La honestidad en la empresa. IESE Business School Blog. https://blog.iese.edu/antonioargandona/2022/06/21/la-honestidad-en-la-empresa/ + Ética empresarial en negocios internacionales: códigos y principios éticos. (2023). Abriendo Mercados. https://abriendomercados.com/etica-empresarial-en-negocios-internacionales-codigos-y-principios-eticos/ + Cortesía y respeto como pilares de las relaciones de negocio. Eslabones de Negocio. https://eslabonesdenegocio.com/cortesia-y-respeto-como-pilares-de-las-relaciones-de-negocio/

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

BASE DE DATOS

flights <- flights
weather <- weather
planes <- planes
airports <- airports
airlines <- airlines
bdgrande <-merge(flights,airlines, by="carrier")
bdgrande2 <-left_join(bdgrande,planes, by="tailnum")
bdgrande3 <- left_join(bdgrande2,weather,by=c("origin","time_hour"))
bdgrande4 <- left_join(bdgrande3, airports, by = c("origin" = "faa"))
bdgrande5 <- left_join(bdgrande4, airports, by = c("dest" = "faa"))

dim(bdgrande5)
## [1] 336776     55

Porcentaje de retrasos por aeropuerto

summary_delay <- bdgrande5 %>%
  group_by(origin) %>%
  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)

summary_delay
## # A tibble: 3 × 5
##   origin avg_delay total_flights total_delayed_flights perc_delayed_flights
##   <chr>      <dbl>         <int>                 <int>                <dbl>
## 1 EWR         15.1        120835                 52711                 43.6
## 2 JFK         12.1        111279                 42031                 37.8
## 3 LGA         10.3        104662                 33690                 32.2

Gráfica 1. Numero de vuelos por aeropuerto con y sin retraso

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

  • Observaciones:
  • El aeropuerto con mayor porcentaje de retrasos es el “EWR” con 43.6%, seguido por el aeropueto “JFK” con 37.7% y por ultimo, el aeropuerto LGA con 32.2%.
  • El aeropuero EWR, es el aeropuerto con el mayor numero de vuelos con 120,835, seguido por el aeropuerto “JFK” con 111,279 y por ultimo, el aeropuerto LGA con 104,662.
  • En la grafica, se puede apreciar esto con los colores verdes y rojo, siendo el verde el numero de vuelos a tiempo y el rojo siendo el numero de vuelos retrasados.
  • Esto indica, que un factor que afecta la puntualidad de los vuelos, es la cantidad de vuelos como tal. Con las observaciones anteriores podemos concluir que el porcentaje de retrasos es directamente proporcional al numero de vuelos por aeropuerto. Un ejemplo es que el aeropuerto “EWR”, que cuenta con el mayor numero de vuelos (120,835), tambien cuenta con el mayor porcentaje de retrasos (43.6%).

Porcentaje de retrasos por destino

summary_delay <- bdgrande5 %>%
  group_by(dest) %>%
  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)

summary_delay
## # A tibble: 105 × 5
##    dest  avg_delay total_flights total_delayed_flights perc_delayed_flights
##    <chr>     <dbl>         <int>                 <int>                <dbl>
##  1 ABQ       13.7            254                   115                 45.3
##  2 ACK        6.46           265                    82                 30.9
##  3 ALB       23.6            439                   210                 47.8
##  4 ANC       12.9              8                     6                 75  
##  5 ATL       12.5          17215                  6081                 35.3
##  6 AUS       13.0           2439                  1037                 42.5
##  7 AVL        8.19           275                    86                 31.3
##  8 BDL       17.7            443                   186                 42.0
##  9 BGR       19.5            375                   153                 40.8
## 10 BHM       29.7            297                   138                 46.5
## # ℹ 95 more rows

Gráfica 2. Numero de vuelos por destino con y sin retraso

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

  • Observaciones:
  • Se puede observar que “ORD”, fue el destino con mas vuelos, seguido por “ATL”. “ORD”, tuvo 17,283 vuelos y “AT”L, tuvo 17,215 vuelos.
  • Se puede observar que existe una diferencia abismal en el numero de vuelos de los aeropuertos. El destino “LEX” Y “LGA”, tienen 1 solo vuelo.
  • Con lo mencionado anteriormente, no podemos seguir con esta linea de investigacion, debido a que los procentajes de vuelos retrasados, no serian significativos debido a la gran diferencia de vuelos por destino. Un ejemplo es el destino “ANC”, tiene un porcentaje de retraso del 75% pero solo tiene 8 vuelos.

Porcentaje de retrasos por mes

summary_delay <- bdgrande5 %>%
  group_by(month.x) %>%
  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)

summary_delay
## # A tibble: 12 × 5
##    month.x avg_delay total_flights total_delayed_flights perc_delayed_flights
##      <int>     <dbl>         <int>                 <int>                <dbl>
##  1       1     10.0          27004                  9662                 35.8
##  2       2     10.8          24951                  9124                 36.6
##  3       3     13.2          28834                 11209                 38.9
##  4       4     13.9          28330                 10543                 37.2
##  5       5     13.0          28796                 11291                 39.2
##  6       6     20.8          28243                 12655                 44.8
##  7       7     21.7          29425                 13909                 47.3
##  8       8     12.6          29327                 11713                 39.9
##  9       9      6.72         27574                  7815                 28.3
## 10      10      6.24         28889                  8722                 30.2
## 11      11      5.44         27268                  8239                 30.2
## 12      12     16.6          28135                 13550                 48.2

Gráfica 3. Numero de vuelos por mes con y sin retraso

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

  • Observaciones:
  • Se puede observar que los meses de “Julio” y “Diciembre”, son los meses con mas porcentaje de retraso. “Julio” cuenta con 47.3% de retraso y “Diciembre” con 48.2% de retraso.
  • Se puede obervar Julio y Agosto, tienen la mayor demanda, ya que son los meses con mas numero de vuelos. Julio tiene 29.424 vuelos y Agosto tiene 29,327 vuelos.
  • Diembre cuenta con 28,135 vuelos, lo cual no es nada fuera de la media.
  • Con lo anterior, se puede concluir que la demanda y mas especificamente las vacaciones, son un factor clave que afecta la puntualidad de los vuelos, ya las vacaciones de verano empiezan en Julio y las vacaciones de navidad empiezan en Diciembre. Estas dos fechas, son las fechas con mayor porcentaje de retrasos, de acuerdo a la información proporcionada.

Porcentaje de retrasos por hora

bdgrande5 <- bdgrande5 %>%
  mutate(hour_of_day = sched_dep_time %/% 100)  # Extrae la hora del tiempo de salida programado

summary_delay <- bdgrande5 %>%
  group_by(hour_of_day) %>%
  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)

summary_delay
## # A tibble: 20 × 5
##    hour_of_day avg_delay total_flights total_delayed_flights
##          <dbl>     <dbl>         <int>                 <int>
##  1           1   NaN                 1                     0
##  2           5     0.688          1953                   489
##  3           6     1.64          25951                  5430
##  4           7     1.91          22821                  4963
##  5           8     4.13          27242                  6790
##  6           9     4.58          20312                  5392
##  7          10     6.50          16708                  4942
##  8          11     7.19          16033                  5034
##  9          12     8.61          18181                  6408
## 10          13    11.4           19956                  8183
## 11          14    13.8           21706                  9257
## 12          15    16.9           23888                 11364
## 13          16    18.8           23002                 10699
## 14          17    21.1           24426                 12132
## 15          18    21.1           21783                 10636
## 16          19    24.8           21441                 10839
## 17          20    24.3           16739                  8633
## 18          21    24.2           10933                  5596
## 19          22    18.8            2639                  1184
## 20          23    14.0            1061                   461
## # ℹ 1 more variable: perc_delayed_flights <dbl>

Gráfica 4. Numero de vuelos por hora con y sin retraso

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

  • Observaciones:
  • Se puede observar, que la hora pico de vuelos es a las 8:00 con 27,242 vuelos, seguido por las 6:00 con 25,951 vuelos.
  • Se puede observar que en la tarde los vuelos tienen un mayor porcentaje de retrasos. Especialmente de 17:00 a 21:00, el porcentaje es realmente alto. A las 17:00, se tiene un porcentaje de 49.7%, a las 18:00, se tiene un porcentaje de 48.8%, a las 19:00 un porcentaje de 50.6%, a las 20:00, un procentaje de 51.6% y a las 21:00, un procentaje de 51.2%.
  • A las 20:00 se tiene el mayor porcentaje de retrasos.
  • Se observa, que el retraso promedio, de igual manera, aumenta considerablemente de 17:00 a 21:00. A las 17:00 se tiene un promedio de 21.1 minutos, a las 18:00, se tiene un promedio de de 21.1 minutos, a las 19:00, se tiene un promedio de 24.8 minutos, a las 20:00, se tiene un promedio de 24.3 minutos y a las 21.00 se tiene un promedio de 24.2 minutos.
  • Se observa, que no solo el porcentaje de vuelos, sino tambien la cantidad de retraso aumento durante esas horas.
  • Con esto, se puede concluir que los retrasos surgen en un efecto cadena, debido a que conforme va pasando el día, el porcentaje de vuelos retrasados aumento, especialemnte en la tarde de 17.00 a 21:00, al momento de retrasarse un vuelo, se ven afectados los demas vuelos que vienen despues de el, debido a que un avión, no hace un solo recorrdio al día, sino que se le intenta sacar el maximo provecho posible a cada uno, ese retraso se va acumulando conforme va pasando el día, esto se explica, con la tendencia y el aumento tanto de porcentaje como de promedio de retraso.

Conclusiones

La probabilidad de retrasos en los vuelos varía significativamente según el aeropuerto de origen, el mes del año y la hora del día, con los aeropuertos más concurridos y las horas pico presentando mayores desafíos para la puntualidad de los vuelos.

Los aeropuertos con un alto volumen de tráfico aéreo, como EWR, tienden a experimentar mayores retrasos, probablemente debido a la congestión y la complejidad de manejar un mayor número de operaciones simultáneas. Según los datos analizados, EWR, con un mayor volumen total de vuelos (120,835) y un mayor porcentaje de vuelos retrasados (43.6%), experimenta más retrasos en comparación con JFK y LGA. Los cuales cuentan con un total de vuelos de 111,279 y 104,662 y un porcentaje de retrasos de 37.7% y 32.2% respectivamente.

Adicionalmente, ciertos periodos del año, especialmente “Julio” y “Diciembre”, muestran un aumento en el porcentaje de retrasos, los cuales destacaron por tener los porcentajes mas altos de retrasos, con 47.3% y 48.2% respectivamente, lo que refleja el impacto de las vacaciones y la demanda estacional en la puntualidad de los vuelos. Las fechas coinciden con el inicio de vacaciones de verano en “Julio” y el inicio de vacaciones de invierno en “Diciembre”. Adicionalmente “Julio” y ”Agosto”, cuentan con la mayor demanda de vuelos, Julio con 29,424 vuelos y Agosto con 29,327 vuelos.

Finalmente, las horas de la tarde (de 17:00 a 21:00), experimentan un incremento en los retrasos en comparación con las horas matutinas, indicando que los retrasos acumulativos a lo largo del día y la mayor demanda de vuelos durante estas horas contribuyen a complicaciones adicionales en las operaciones aéreas. Esto se demuestra debido a que no solo el porcentaje de retrasos es mayor durante estas horas del día, sino tambien el retraso promedio es mayor. Un ejemplo, es que a pesar de que a las 8:00 es la hora pico de vuelos (27,742 vuelos), el porcentaje de retraso es del 24.9 % y el retraso promedio es de tan solo 4.1 minutos, mientras que a las 20:00, hay un total de 16,739 vuelos, pero el porcentaje de retraso es del 51.6% y el retraso promedio es de 24.3 minutos.

LS0tCnRpdGxlOiAiRXZpZGVuY2lhIEZpbmFsIgphdXRob3I6ICJBbG1hIFNhbnRpYWdvIC0gQTAwODM2NjM2LCBEaWVnbyBTZXJuYSAtIEEwMTI4NTQ5MCwgT3N2YWxkbyBUZWxsbyAtIEEwMTI4NTY0MiIKZGF0ZTogIjIwMjQtMDMtMDQiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFCiAgICB0aGVtZTogY29zbW8KLS0tCgohW10oL1VzZXJzL2RpZWdvc2VybmEvRGVza3RvcC9UZWMgU21lc3RyZXMgLzR0byBTZW1lc3RyZS9NYW5pcHVsYWNpb8yBbiBkZSBEYXRvcy9Gb3RvcyBSIHN0dWRpby9OZXdfeW9ya190aW1lc19zcXVhcmUtdGVyYWJhc3MucG5nKQoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPkNvbnRleHRvPC9zcGFuPiAKRWwgcGFxdWV0ZSAqKm55Y2ZsaWdodHMxMyoqIGNvbnRpZW5lIGluZm9ybWFjacOzbiBzb3JlIHRvZG9zIGxvcyB2dWVsZXMgcXVlIHBhcnRpZXJvbiBkZXNkZSBOdWV2YSBZb3JrKEVXUiwgSkZMLCBMR0EpIGVuIGRlc3Rpbm9zIGEgbG9zIEVzdGFkb3MgVW5pZG9zIGVuIDIwMTMuIEZ1ZXJvbiAzMzYsNzc2IHZ1ZWxvcyBlbiB0b3RhbC4gUGFyYSBheXVkYXIgYSBjb21wcmVuZGVyIGxhcyBjYXVzYXMgZGUgbG9zIHJldHJhc29zLCB0YW1iacOpbiBpbmNsdXllIG90cm9zIG9jbmp1bnRvcyBkZSBkYXRvcyDDunRpbGVzLiAgCgpFc3RlIHBhcXVldGUgaW5jbHV5ZSBsYXMgc2lndWllbnRlcyB0YWJsYXM6CgorIGZsaWdodHMgPSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSBzYWxpZXJvbiBkZSBOVWV2YSBZb3JrIGVuIGVsIDIwMTMgIAorIHdlYXRoZXIgPSBkYXRvcyBtZXRlcmVvbMOzZ2ljb3MgcG9yIGhvcmEgZGUgY2FkYSBhZXJvcHVlcnRvICAKKyBwbGFuZXMgPSBpbmZvcm1hY2nDs24gZGUgY29uc3RydWNjacOzbiBkZSBjYWRhIGF2acOzbiAgCisgYWlycG9ydHMgPSBub21icmVzIHkgdWJsaWNhY2lvbmVzIGRlIGFlcm9wdWVydG9zICAKKyBhaXJsaW5lcyA9IHJlbGFjacOzbiBlbnRyZSBub21icmVzIHkgY8OzZGlnb3MgZGUgbGFzIGFlcm9sw61uZWFzICAKCkZ1ZW50ZToKW09yaWdlbiBkZSBsb3MgZGF0b3NdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ueWNmbGlnaHRzMTMvbnljZmxpZ2h0czEzLnBkZikKCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogcmVkOyI+SW5zdGFsYXIgcGFxdWV0ZXMgeSBsbGFtYXIgbGlicmVyw61hczwvc3Bhbj4KYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJueWNmbGlnaHQxMyIpCmxpYnJhcnkobnljZmxpZ2h0czEzKQojaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKbGlicmFyeSh0aWR5dmVyc2UpCiNpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCmxpYnJhcnkoZHBseXIpCiNpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKbGlicmFyeShnZ3Bsb3QyKQojaW5zdGFsbC5wYWNrYWdlcygiYnJvb20iKQpsaWJyYXJ5KGJyb29tKQoKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogcmVkOyI+R3VhcmRhciBiYXNlIGRlIGRhdG9zPC9zcGFuPiAKYGBge3J9CmZsaWdodHMgPC0gZmxpZ2h0cwp3ZWF0aGVyIDwtIHdlYXRoZXIKcGxhbmVzIDwtIHBsYW5lcwphaXJwb3J0cyA8LSBhaXJwb3J0cwphaXJsaW5lcyA8LSBhaXJsaW5lcwpiZGdyYW5kZSA8LW1lcmdlKGZsaWdodHMsYWlybGluZXMsIGJ5PSJjYXJyaWVyIikKYmRncmFuZGUyIDwtbGVmdF9qb2luKGJkZ3JhbmRlLHBsYW5lcywgYnk9InRhaWxudW0iKQpiZGdyYW5kZTMgPC0gbGVmdF9qb2luKGJkZ3JhbmRlMix3ZWF0aGVyLGJ5PWMoIm9yaWdpbiIsInRpbWVfaG91ciIpKQpiZGdyYW5kZTQgPC0gbGVmdF9qb2luKGJkZ3JhbmRlMywgYWlycG9ydHMsIGJ5ID0gYygib3JpZ2luIiA9ICJmYWEiKSkKYmRncmFuZGU1IDwtIGxlZnRfam9pbihiZGdyYW5kZTQsIGFpcnBvcnRzLCBieSA9IGMoImRlc3QiID0gImZhYSIpKQoKZGltKGJkZ3JhbmRlNSkKCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPlJlbGFjacOzbiBlbnRyZSBsYXMgYmFzZXMgZGUgZGF0b3M8L3NwYW4+IAoKIVtdKC9Vc2Vycy9kaWVnb3Nlcm5hL0Rlc2t0b3AvVGVjIFNtZXN0cmVzIC80dG8gU2VtZXN0cmUvTWFuaXB1bGFjaW/MgW4gZGUgRGF0b3MvRm90b3MgUiBzdHVkaW8vcmVsYXRpb25hbC1ueWNmbGlnaHRzLnBuZykKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5EYXRhIFdyYW5nbGluZzwvc3Bhbj4gCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPjEuIEZ1bmNpb25lcyBiw6FzaWNhcyBkZSBtYW5lam8gZGUgZGF0b3M8L3NwYW4+IAojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPlNlbGVjdDwvc3Bhbj4gCkxhIGZ1bmNpw7NuICpzZWxlY3QqIHNpcnZlIHBhcmEgc2VsZWNjaW9uYXIgY29sdW1ub3MgZGUgdW4gdGFibGUgKCpkYXRhIGZyYW1lKikuCmBgYHtyfQpkZjEgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KGNhcnJpZXIsIGZsaWdodCkgIyBTZWxlY2Npw7NuIGRlIGNvbHVtbmFzIGVzcGVjw61maWNhcwpkZjIgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KGNhcnJpZXI6ZGlzdGFuY2UpICMgU2VsZWNjacOzbiBkZSByYW5nbyBkZSBjb2x1bW5hcwpkZjMgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KC1jYXJyaWVyLCAtZmxpZ2h0KSAjIEVsaW1pbmFyIGNvbHVtbmFzIGVzcGVjw61maWNhcwpkZjQgPC0gZmxpZ2h0cyAlPiUgc2VsZWN0KC1jYXJyaWVyOiAtZmxpZ2h0KSAjIEVsaW1pbmFyIHJhbmdvIGRlIGNvbHVtbmFzCmRmNSA8LSBmbGlnaHRzICU+JSBzZWxlY3QoYWVyb2xpbmVhID0gY2FycmllcikgIyBTZWxlY2Npb25hIHVuYSBjb2x1bW5hIHkgbGUgY2FtYmlhIGVsIG5vbWJyZQpkZjYgPC0gZmxpZ2h0cyAlPiUgcmVuYW1lKGFlcm9saW5lYSA9IGNhcnJpZXIpICMgQ2FtYmlhIGVsIG5vbWJyZSBkZSB1bmEgY29sdW1uYQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+RmlsdGVyPC9zcGFuPiAKTGEgZnVuY2nDs24gKkZpbHRlciogc2lydmUgcGFyYSBzZWxlY2Npb25hciByZW5nbG9uZXMgZGUgdW4gdGFibGEoKmRhdGEgZnJhbWUqKS4KYGBge3J9CmRmNyA8LSBmbGlnaHRzICU+JSBmaWx0ZXIoZGVwX2RlbGF5ID49NTAwKSAjIEV4dHJhZSByZW5nbG9uZXMgcXVlIGN1bXBsYW4gY29uZGljacOzbgojIENvbmRpY2lvbmFsZXM6IElndWFsID09LCBEZXNpZ3VhbCA9IT0sIE1heW9yIHF1ZSA+LCBNYXlvciBvIGlndWFsIHF1ZSA+PSwgTWVub3IgbyBpZ3VhbCBxdWUgPD0KIyBPcGVyYWRvcmVzIGzDs2dpY29zOiBBTkQgJiwgT1IgfCwgTk9UICEKZGY4IDwtIGZsaWdodHMgJT4lIGZpbHRlcihkZXBfZGVsYXkgPj01MDAsIGRlcF9kZWxheSA8PTYwMCkgIyBFeHRyYWUgcmVuZ2xvbmVzIHF1ZSBjdW1wbGFuIGNvbiBkb3MgY29uZGljaW9uZXMKZGY5IDwtIGZsaWdodHMgJT4lIHNsaWNlKDEwMDA6IDEwOTkpICMgRXh0cmFlIGxvcyBuw7ptZXJvcyBkZSBsb3MgcmVuZ2xvbmVzIGluZGljYWRvcywgc2luIGltcG9ydGFyIHN1cyB2YWxvcmVzCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5EaXN0aW5jdDwvc3Bhbj4gCkxhIGZ1bmNpw7NuICpkaXN0aW5jdCogc2lydmUgcGFyYSBlbGltaW5hciByZW5nbG9uZXMgZHVwbGljYWRvcy4KYGBge3J9CmRmMTAgPC0gZGlzdGluY3QoZmxpZ2h0cykgIyBEZWphciBzb2xvIGxvcyByZW5nbG9uZXMgZGlmZXJlbnRlcywgYm9ycmEgdG9kb3MgbG9zIHJlcGV0aWRvcy4KYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPk1lcmdlPC9zcGFuPiAKTGEgZnVuY2nDs24gKm1lcmdlKiBzaXJ2ZSBwYXJhIGp1bnRhciBiYXNlcyBkZSBkYXRvcy4KYGBge3J9CmJkZ3JhbmRlIDwtIG1lcmdlKGZsaWdodHMsIGFpcmxpbmVzLCBieT0iY2FycmllciIpCmJkZ3JhbmRlMiA8LSBtZXJnZShiZGdyYW5kZSxwbGFuZXMsIGJ5PSJ0YWlsbnVtIikKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPk11dGF0ZTwvc3Bhbj4gCmBgYHtyfQpiZGdyYW5kZV9jb25fZGlzdF9tdHMgPC0gbXV0YXRlKGJkZ3JhbmRlMiwgZGlzdF9tdHMgPSBkaXN0YW5jZSoxLjYwOSkKI0FncmVnYSB2YXJpYWJsZXMgbnVldmFzIGNhbHVsYWRhcyBhIHBhcnRpciBkZSB2YXJpYWJsZXMgZXhpc3RlbnRlcyBlbiBsYSBiYXNlIGRlIGRhdG9zLgpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+RWplcmNpY2lvczwvc3Bhbj4gCjEuIEVuY3VlbnRyYSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSB0dXZpZXJvbiB1biBhdHJhc28gZW4gbGxlZ2FkYSBkZSAyIGhvcmFzIG8gbcOhcy4KYGBge3J9CmVqZXJjaWNpbzEgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIoYXJyX2RlbGF5Pj0xMjApCmBgYAoKMi4gRW5jdWVudHJhIHRvZG9zIGxvcyB2dWVsb3MgcXVlIGxsZWdhcm9uIGEgSG91c3RvbiAoSUFOIE8gSE9VKQpgYGB7cn0KZWplcmNpY2lvMiA8LSBiZGdyYW5kZTIgJT4lIGZpbHRlcihkZXN0PT0gIklBSCIgfCBkZXN0ID09ICJIT1UiKQpgYGAKCjMuIEVuY3VlbnRyYSB0b2RvcyBsb3MgdnVlbG9zIG9wZXJhZG9zIHBvciBVbml0ZWQsIEFtZXJpY2FuIG8gRGVsdGEuCmBgYHtyfQplamVyY2ljaW8zIDwtIGJkZ3JhbmRlMiAlPiUgZmlsdGVyKGNhcnJpZXIgJWluJSBjKCJVQSIsICJBQSIsICJETCIpKQpgYGAKCjQuIEVuY3VlbnRyYSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSBkZXNwZWdhcm9uIGVuIEp1bGlvLCBBZ29zdG8gbyBTZXB0aWVtYnJlCmBgYHtyfQplamVyY2ljaW80IDwtIGJkZ3JhbmRlMiAlPiUgZmlsdGVyKG1vbnRoICVpbiUgYyg3LCA4LCA5KSkKZWplcmNpY2lvNGEgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIobW9udGggPT0gNyB8IG1vbnRoID09IDggfCBtb250aCA9PSA5KSAKYGBgCgo1LiBFbmN1ZW50cmEgdG9kb3MgbG9zIHZ1ZWxvcyBxdWUgYXJyaXZhcm9uIG3DoXMgZGUgMiBob3JhcyB0YXJkZSwgcGVybyBubyBkZXNwZWdhcm9uIHRhcmRlLgpgYGB7cn0KZWplcmNpY2lvNSA8LSBiZGdyYW5kZTIgJT4lIGZpbHRlcihhcnJfZGVsYXk+MTIwICYgZGVwX3RpbWUgPT0gc2NoZWRfZGVwX3RpbWUpCmVqZXJjaWNpbzVhIDwtIGJkZ3JhbmRlMiAlPiUgZmlsdGVyKGFycl9kZWxheT4xMjAgJiBkZXBfZGVsYXk8PTApCmBgYAoKNi4gRW5jdWVudHJhIHRvZG9zIGxvcyB2dWVsb3MgcXVlIHNlIHJldHJhc2Fyb24gYWwgbWVub3MgMSBob3JhLCBwZXJvIHF1ZSBsbGVnYXJvbiBhbnRlcyAzMCBtaW51dG9zIG8gbcOhcy4KYGBge3J9CmVqZXJjaWNpbzYgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIoZGVwX2RlbGF5Pj02MCAmIGFycl9kZWxheTw9LTMwKQpgYGAKCjcuIEVuY3VlbnRyYSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSBzYWxpZXJvbiBlbnRyZSBsYSBtZWRpYW5vY2hlIHkgbGFzIDYgYS5tLgpgYGB7cn0KZWplcmNpY2lvNyA8LSBiZGdyYW5kZTIgJT4lIGZpbHRlcihkZXBfdGltZSAlaW4lIGMoIjI0MDAiLCAiMTAwIiwgIjIwMCIsICIzMDAiLCAiNDAwIiwgIjUwMCIsICI2MDAiKSkKZWplcmNpY2lvN2EgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIoZGVwX3RpbWU9PTI0MDAgfCBkZXBfdGltZTw9NjAwKSAKZWplcmNpY2lvN2IgPC0gYmRncmFuZGUyICU+JSBmaWx0ZXIoaG91ciAlaW4lIGMoIjAiLCAiMSIsICIyIiwgIjMiLCAiNCIsICI1IiwgIjYiKSkKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPkFycmFuZ2U8L3NwYW4+IApTaW1pbGFyIGEgZmlsdGVyICgpIHBlcm8gZW4gbHVnYXIgZGUgc2VsZWNjaW9uYXIgcmVuZ2xvbmVzLCBsb3Mgb3JkZW5hIGRlIG1lbm9yIGEgbWF5b3IuCmBgYHtyfQpkZjExIDwtIGFycmFuZ2UoYmRncmFuZGUyLCB5ZWFyLngsIG1vbnRoLCBkYXkpCmBgYAoKUGFyYSBhY29tb2RhciBkZSBtYXlvciBhIG1lbm9yLgpgYGB7cn0KZGYxMiA8LSBhcnJhbmdlKGJkZ3JhbmRlMiwgeWVhci54LCBkZXNjKG1vbnRoKSwgZGF5KQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+U3VtbWFyaXplPC9zcGFuPiAKQ29sYXBzYSB1bmEgdGFibGEgYSB1biBzw7NsbyByZW5nbMOzbgpgYGB7cn0KIyBPYnTDqW4gZWwgcmV0cmFzbyBwcm9tZWRpbyBkZSBzYWxpZGEgZGUgZGVzcGVndWUgZGUgdG9kb3MgbG9zIHZ1ZWxvcwpzdW1tYXJpemUoYmRncmFuZGUyLCBtZWFuKGRlcF9kZWxheSwgbmEucm09VFJVRSkpCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5Hcm91cCBieTwvc3Bhbj4gCkFncnVwYSB0YWJsYSBiYXNhZG8gZW4gYWxndW5hcyBjb2x1bW5hcy4KYGBge3J9CiMgT2J0ZW5lciBlbCByZXRyYXNvIHByb21lZGlvIGRlIGRlc3BlZ3VlIHBvciBkw61hCnBvcl9kaWEgPC0gZ3JvdXBfYnkoYmRncmFuZGUyLCB5ZWFyLngsIG1vbnRoLCBkYXkpCnN1bW1hcml6ZShwb3JfZGlhLCBtZWFuKGRlcF9kZWxheSwgbmEucm09VFJVRSkpCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPkV2aWRlbmNpYSAxIE5ldyBZb3JrIChIZWNoYSBlbiBjbGFzZSk8L3NwYW4+CiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+MS4gQ2FyZ2FyIGVuIG1lbW9yaWEgbGEgdGFibGEgImZsaWdodHMiIHkgbW9zdHJhciBzdSBjb250ZW5pZG88L3NwYW4+CmBgYHtyfQojIExhIGNhcmdhIGEgYSBtZW1vcmlhIHNlIGhpem8gZW4gZWwgcGFzbyBhbnRlcmlvcgpmbGlnaHRzCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij4yLiBDb25zdWx0YSBsYSBlc3RydWN0dXJhIGRlICJmbGlnaHRzIiA8L3NwYW4+CmBgYHtyfQpzdHIoZmxpZ2h0cykKIyBpbnQ6ZW50ZXJvIChzaW4gZGVjaW1hbGVzKQojIG51bTpudW3DqXJpY28gKGNvbiBkZWNpbWFsZXMpCiMgY2hyOiBjYXJhY3TDqXIgKGxldHJhcykKIyBkYXRlOiBmZWNoYSAoZW4gUiB2YSBhw7FvLW1lcy1kaWEpCiMgUE9TSVhjdDpmb3JtYXRvIGZlY2hhIHkgaG9yYQoKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPjMuIMK/Q3XDoWwgZXMgbGEgY2xhc2UgImZsaWdodHMiIHkgcXXDqSBzaWduaWZpY2E/PC9zcGFuPgpgYGB7cn0KY2xhc3MoZmxpZ2h0cykKCiMgTGFzIDUgY2xhc2VzIGRlIG9iamV0b3MKIyAxLiBudW1lcmljOiBOw7ptZXJvIHJlYWwgbyBkw6ljaW1hbAojIDIuIGludGVnZXI6IE7Dum1lcm9zIGVudGVyb3MKIyAzLiBDb21wbGV4OiBOw7ptZXJvcyBjb21wbGVqb3MKIyA0LiBDaGFyYWN0ZXI6IENhcmFjdMOpcmVzIAojIDUuIExvZ2ljYWw6IFRSVUUgbyBGQUxTRQoKIyBMYXMgNCBjbGFzZXMgZGUgb2JqZXRvcyBjb21wdWVzdG9zIHNvbjoKIyAxLiBsaXN0OiBsaXN0YQojIDIuIE1hdHJpeDogTWF0cml6CiMgMy4gQXJyYXk6IGNvbGVjY2nDs24gZGUgb2JqZXRvcwojIDQuIGRhdGEuZnJhbWU6IGJhc2UgZGUgZGF0b3MKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPjQuIMK/Q3XDoW50YXMgY29sdW1uYXMgeSByZW5nbG9uZXMgdGllbmUgImZsaWdodHMiPzwvc3Bhbj4KYGBge3J9CiMgTsO6bWVybyBkZSBjb2x1bW5hcwpuY29sKGZsaWdodHMpCiMgTnVtZXJvIGRlIHJlbmdsb25lcwpucm93KGZsaWdodHMpCiMgRGltZW5zacOzbgpkaW0oZmxpZ2h0cykKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPjUuIE11ZXN0cmEgbG9zIHByaW1lcm9zIDYgcmVuZ2xvbmVzIGRlICJmbGlnaHRzIi4gVGFtYmllbiBsb3MgdWx0aW1vcyA2IDwvc3Bhbj4KYGBge3J9CmhlYWQoZmxpZ2h0cykKdGFpbChmbGlnaHRzKQojIFNpIHF1aXNpZXJhbW9zIDcgcmVuZ2xvbmVzOiBoZWFkKGZsaWdodHMsNykKCmBgYAoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij42LiBNdWVzdHJhIGxvcyBlc3RhZGlzdGljb3MgZGVzY3JpcHRpdm9zIGRlICJmbGlnaHRzIjwvc3Bhbj4KYGBge3J9CnN1bW1hcnkoZmxpZ2h0cykKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPkNvbmNsdXNpw7NuPC9zcGFuPgpFbiBlc3RlIHRyYWJham8gcHVkaW1vcyB1dGxpemFyIGxhcyBmdW5jaW9uZXMgbcOhcyBjb211bmVzIGRlbCBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvLCBlbCBjdWFsIGVzIGVsIHByaW1lciBwYXNvIHBhcmEgY3VhbHF1aWVyIHRyYWJham8gZGUgbWFuaXB1bGFjacOzbiBkZSBkYXRvcy4KCgojIDxzcGFuIHN0eWxlPSJjb2xvcjpyZWQ7Ij5FdmlkZW5jaWEgMSBBbmFsw610aWNhIGRlc2NyaXB0aXZhPC9zcGFuPiAKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+RXhwbG9yYWNpw7NuPC9zcGFuPiAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+RmxpZ2h0czwvc3Bhbj4gCgpgYGB7cn0KIyBDb25zdWx0YSBsYSBlc3RydWN0dXJhIGRlIGNhZGEgZGF0YSBmcmFtZQojIFBhcmEgZWwgZGF0YSBmcmFtZSBmbGlnaHRzCmRhdGEoZmxpZ2h0cykgCnN0cihmbGlnaHRzKQpuY29sKGZsaWdodHMpCm5yb3coZmxpZ2h0cykKZGltKGZsaWdodHMpCmhlYWQoZmxpZ2h0cykKdGFpbChmbGlnaHRzKQpzdW1tYXJ5KGZsaWdodHMpCmBgYAoKwr9DdcOhbGVzIHNvbiBsb3MgY2FtcG9zIHkgc3VzIHRpcG9zIGRlIGRhdG9zPyAKTG9zIGNhbXBvcyBkZWwgY29uanVudG8gZGUgZGF0b3MgZmxpZ2h0cyB5IHN1cyB0aXBvcyBkZSBkYXRvcyBzb246CgorIHllYXI6IGludCAoZW50ZXJvKSAtIEHDsW8gZGVsIHZ1ZWxvLgorIG1vbnRoOiBpbnQgKGVudGVybykgLSBNZXMgZGVsIHZ1ZWxvLgorIGRheTogaW50IChlbnRlcm8pIC0gRMOtYSBkZWwgdnVlbG8uCisgZGVwX3RpbWU6IGludCAoZW50ZXJvKSAtIEhvcmEgZGUgc2FsaWRhIHJlYWwgZGVsIHZ1ZWxvLgorIHNjaGVkX2RlcF90aW1lOiBpbnQgKGVudGVybykgLSBIb3JhIGRlIHNhbGlkYSBwcm9ncmFtYWRhIGRlbCB2dWVsby4KKyBkZXBfZGVsYXk6IG51bSAobsO6bWVybykgLSBSZXRyYXNvIGRlIHNhbGlkYSBlbiBtaW51dG9zLgorIGFycl90aW1lOiBpbnQgKGVudGVybykgLSBIb3JhIGRlIGxsZWdhZGEgcmVhbC4KKyBzY2hlZF9hcnJfdGltZTogaW50IChlbnRlcm8pIC0gSG9yYSBkZSBsbGVnYWRhIHByb2dyYW1hZGEuCisgYXJyX2RlbGF5OiBudW0gKG7Dum1lcm8pIC0gUmV0cmFzbyBkZSBsbGVnYWRhIGVuIG1pbnV0b3MuCisgY2FycmllcjogY2hyIChjYXLDoWN0ZXIpIC0gQ8OzZGlnbyBkZSBsYSBhZXJvbMOtbmVhLgorIGZsaWdodDogaW50IChlbnRlcm8pIC0gTsO6bWVybyBkZWwgdnVlbG8uCisgdGFpbG51bTogY2hyIChjYXLDoWN0ZXIpIC0gTsO6bWVybyBkZSBjb2xhIGRlbCBhdmnDs24uCisgb3JpZ2luOiBjaHIgKGNhcsOhY3RlcikgLSBBZXJvcHVlcnRvIGRlIG9yaWdlbi4KKyBkZXN0OiBjaHIgKGNhcsOhY3RlcikgLSBBZXJvcHVlcnRvIGRlIGRlc3Rpbm8uCisgYWlyX3RpbWU6IG51bSAobsO6bWVybykgLSBUaWVtcG8gZW4gZWwgYWlyZSBlbiBtaW51dG9zLgorIGRpc3RhbmNlOiBudW0gKG7Dum1lcm8pIC0gRGlzdGFuY2lhIGRlbCB2dWVsbyBlbiBtaWxsYXMuCisgaG91cjogbnVtIChuw7ptZXJvKSAtIEhvcmEgcHJvZ3JhbWFkYSBkZSBzYWxpZGEgKGhvcmEpLgorIG1pbnV0ZTogbnVtIChuw7ptZXJvKSAtIEhvcmEgcHJvZ3JhbWFkYSBkZSBzYWxpZGEgKG1pbnV0b3MpLgorIHRpbWVfaG91cjogUE9TSVhjdCAoZHR0bSkgLSBGZWNoYSB5IGhvcmEgZGVsIHZ1ZWxvLgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij53ZWF0aGVyPC9zcGFuPiAKYGBge3J9CiMgUGFyYSBlbCBkYXRhIGZyYW1lIHdlYXRoZXIKZGF0YSh3ZWF0aGVyKSAKc3RyKHdlYXRoZXIpCm5jb2wod2VhdGhlcikKbnJvdyh3ZWF0aGVyKQpkaW0od2VhdGhlcikKaGVhZCh3ZWF0aGVyKQp0YWlsKHdlYXRoZXIpCnN1bW1hcnkod2VhdGhlcikKYGBgCgrCv0N1w6FsZXMgc29uIGxvcyBjYW1wb3MgeSBzdXMgdGlwb3MgZGUgZGF0b3M/IApMb3MgY2FtcG9zIGRlbCBjb25qdW50byBkZSBkYXRvcyB3ZWF0aGVyIHkgc3VzIHRpcG9zIGRlIGRhdG9zIHNvbjoKCisgb3JpZ2luOiBjaHIgKGNhcsOhY3RlcikgLSBDw7NkaWdvIGRlbCBhZXJvcHVlcnRvIGRlIG9yaWdlbi4KKyB5ZWFyOiBpbnQgKGVudGVybykgLSBBw7FvIGRlIGxhIG9ic2VydmFjacOzbiBtZXRlb3JvbMOzZ2ljYS4KKyBtb250aDogaW50IChlbnRlcm8pIC0gTWVzIGRlIGxhIG9ic2VydmFjacOzbiBtZXRlb3JvbMOzZ2ljYS4KKyBkYXk6IGludCAoZW50ZXJvKSAtIETDrWEgZGUgbGEgb2JzZXJ2YWNpw7NuIG1ldGVvcm9sw7NnaWNhLgorIGhvdXI6IGludCAoZW50ZXJvKSAtIEhvcmEgZGUgbGEgb2JzZXJ2YWNpw7NuIG1ldGVvcm9sw7NnaWNhLgorIHRlbXA6IG51bSAobsO6bWVybykgLSBUZW1wZXJhdHVyYSBlbiBncmFkb3MgRmFocmVuaGVpdC4KKyBkZXdwOiBudW0gKG7Dum1lcm8pIC0gUHVudG8gZGUgcm9jw61vIGVuIGdyYWRvcyBGYWhyZW5oZWl0LgorIGh1bWlkOiBudW0gKG7Dum1lcm8pIC0gSHVtZWRhZCByZWxhdGl2YSBlbiBwb3JjZW50YWplLgorIHdpbmRfZGlyOiBudW0gKG7Dum1lcm8pIC0gRGlyZWNjacOzbiBkZWwgdmllbnRvIGVuIGdyYWRvcy4KKyB3aW5kX3NwZWVkOiBudW0gKG7Dum1lcm8pIC0gVmVsb2NpZGFkIGRlbCB2aWVudG8gZW4gbWlsbGFzIHBvciBob3JhLgorIHdpbmRfZ3VzdDogbnVtIChuw7ptZXJvKSAtIFLDoWZhZ2EgZGUgdmllbnRvIGVuIG1pbGxhcyBwb3IgaG9yYS4KKyBwcmVjaXA6IG51bSAobsO6bWVybykgLSBQcmVjaXBpdGFjacOzbiBlbiBwdWxnYWRhcy4KKyBwcmVzc3VyZTogbnVtIChuw7ptZXJvKSAtIFByZXNpw7NuIGF0bW9zZsOpcmljYSBlbiBtaWxpYmFyZXMuCisgdmlzaWI6IG51bSAobsO6bWVybykgLSBWaXNpYmlsaWRhZCBlbiBtaWxsYXMuCisgdGltZV9ob3VyOiBQT1NJWGN0IChkdHRtKSAtIEZlY2hhIHkgaG9yYSBkZSBsYSBvYnNlcnZhY2nDs24gbWV0ZW9yb2zDs2dpY2EuCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5wbGFuZXM8L3NwYW4+IApgYGB7cn0KIyBQYXJhIGVsIGRhdGEgZnJhbWUgcGxhbmVzCmRhdGEocGxhbmVzKSAKc3RyKHBsYW5lcykKbmNvbChwbGFuZXMpCm5yb3cocGxhbmVzKQpkaW0ocGxhbmVzKQpoZWFkKHBsYW5lcykKdGFpbChwbGFuZXMpCnN1bW1hcnkocGxhbmVzKQpgYGAKCsK/Q3XDoWxlcyBzb24gbG9zIGNhbXBvcyB5IHN1cyB0aXBvcyBkZSBkYXRvcz8gCkxvcyBjYW1wb3MgZGVsIGNvbmp1bnRvIGRlIGRhdG9zIHBsYW5lcyB5IHN1cyB0aXBvcyBkZSBkYXRvcyBzb246CgorIHRhaWxudW06IGNociAoY2Fyw6FjdGVyKSAtIE7Dum1lcm8gZGUgY29sYSBkZWwgYXZpw7NuLgorIHllYXI6IGludCAoZW50ZXJvKSAtIEHDsW8gZGUgZmFicmljYWNpw7NuIGRlbCBhdmnDs24uCisgdHlwZTogY2hyIChjYXLDoWN0ZXIpIC0gVGlwbyBkZSBhdmnDs24sIGVuIGVzdGUgY2FzbyB0b2RvcyBzb24gZGUgYWxhIGZpamEgY29uIG3Dumx0aXBsZXMgbW90b3Jlcy4KKyBtYW51ZmFjdHVyZXI6IGNociAoY2Fyw6FjdGVyKSAtIEZhYnJpY2FudGUgZGVsIGF2acOzbi4KKyBtb2RlbDogY2hyIChjYXLDoWN0ZXIpIC0gTW9kZWxvIGRlbCBhdmnDs24uCisgZW5naW5lczogaW50IChlbnRlcm8pIC0gTsO6bWVybyBkZSBtb3RvcmVzIGRlbCBhdmnDs24uCisgc2VhdHM6IGludCAoZW50ZXJvKSAtIE7Dum1lcm8gZGUgYXNpZW50b3MgZGVsIGF2acOzbi4KKyBzcGVlZDogaW50IChlbnRlcm8pIC0gVmVsb2NpZGFkIGRlbCBhdmnDs24sIGF1bnF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgcmVnaXN0cm9zIHBhcmVjZW4gbm8gdGVuZXIgZXN0YSBpbmZvcm1hY2nDs24gKE5BKS4KKyBlbmdpbmU6IGNociAoY2Fyw6FjdGVyKSAtIFRpcG8gZGUgbW90b3IgZGVsIGF2acOzbiwgbGEgbWF5b3LDrWEgc29uIHR1cmJvZsOhbi4KCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPmFpcnBvcnRzPC9zcGFuPiAKYGBge3J9CiMgUGFyYSBlbCBkYXRhIGZyYW1lIGFpcnBvcnRzCmRhdGEoYWlycG9ydHMpIApzdHIoYWlycG9ydHMpCm5jb2woYWlycG9ydHMpCm5yb3coYWlycG9ydHMpCmRpbShhaXJwb3J0cykKaGVhZChhaXJwb3J0cykKdGFpbChhaXJwb3J0cykKc3VtbWFyeShhaXJwb3J0cykKYGBgCgrCv0N1w6FsZXMgc29uIGxvcyBjYW1wb3MgeSBzdXMgdGlwb3MgZGUgZGF0b3M/IApMb3MgY2FtcG9zIGRlbCBjb25qdW50byBkZSBkYXRvcyBhaXJwb3J0cyB5IHN1cyB0aXBvcyBkZSBkYXRvcyBzb246CgorIG9yaWdpbjogY2hyIChjYXLDoWN0ZXIpIC0gQ8OzZGlnbyBkZWwgYWVyb3B1ZXJ0by4KKyBuYW1lOiBjaHIgKGNhcsOhY3RlcikgLSBOb21icmUgZGVsIGFlcm9wdWVydG8uCisgbGF0OiBudW0gKG7Dum1lcm8pIC0gTGF0aXR1ZCBkZWwgYWVyb3B1ZXJ0by4KKyBsb246IG51bSAobsO6bWVybykgLSBMb25naXR1ZCBkZWwgYWVyb3B1ZXJ0by4KKyBhbHQ6IG51bSAobsO6bWVybykgLSBBbHRpdHVkIGRlbCBhZXJvcHVlcnRvIGVuIHBpZXMuCisgdHo6IG51bSAobsO6bWVybykgLSBab25hIGhvcmFyaWEgZGVsIGFlcm9wdWVydG8sIGJhc2FkYSBlbiBlbCBkZXNwbGF6YW1pZW50byBkZWwgVVRDLgorIGRzdDogY2hyIChjYXLDoWN0ZXIpIC0gSW5kaWNhZG9yIGRlIGhvcmFyaW8gZGUgdmVyYW5vIChwLiBlai4sICJBIiBwYXJhIGhvcmFyaW8gZGUgdmVyYW5vLCAiTiIgcGFyYSBubyBvYnNlcnZhcmxvKS4KKyB0em9uZTogY2hyIChjYXLDoWN0ZXIpIC0gWm9uYSBob3JhcmlhIGRlbCBhZXJvcHVlcnRvIGVuIHRleHRvLCBwb3IgZWplbXBsbywgIkFtZXJpY2EvTmV3X1lvcmsiLgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5haXJsaW5lczwvc3Bhbj4gCmBgYHtyfQojIFBhcmEgZWwgZGF0YSBmcmFtZSBhaXJsaW5lcwpkYXRhKGFpcmxpbmVzKSAKc3RyKGFpcmxpbmVzKQpuY29sKGFpcmxpbmVzKQpucm93KGFpcmxpbmVzKQpkaW0oYWlybGluZXMpCmhlYWQoYWlybGluZXMpCnRhaWwoYWlybGluZXMpCnN1bW1hcnkoYWlybGluZXMpCmBgYAoKwr9DdcOhbGVzIHNvbiBsb3MgY2FtcG9zIHkgc3VzIHRpcG9zIGRlIGRhdG9zPyAKCkxvcyBjYW1wb3MgZGVsIGNvbmp1bnRvIGRlIGRhdG9zIGFpcmxpbmVzIHkgc3VzIHRpcG9zIGRlIGRhdG9zIHNvbjoKCisgY2FycmllcjogY2hyIChjYXLDoWN0ZXIpIC0gQ8OzZGlnbyBkZSBkb3MgbGV0cmFzIGRlIGxhIGFlcm9sw61uZWEuCisgbmFtZTogY2hyIChjYXLDoWN0ZXIpIC0gTm9tYnJlIGNvbXBsZXRvIGRlIGxhIGFlcm9sw61uZWEuCgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+TWFuaXB1bGFjacOzbiBkZSBkYXRvczwvc3Bhbj4gCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+MSBDb25zdWx0YXIgZGF0YWZyYW1lPC9zcGFuPgoKYGBge3J9CiNBbCBjb25zdWx0YXIgbCBEYXRhRnJhbWUgbm9zIHBlcm1pdGUgdmlzdWFsaXphciBsYSBiYXNlIGRlIGRhdG9zICpmbGlnaHRzKi4KdmlldyhmbGlnaHRzKQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+MiBFbmN1ZW50cmEgbG9zIGRhdG9zIGRlc2NyaXB0aXZvcyBkZWwgZGF0YSBmcmFtZSBmbGlnaHRzLiBJZGVudGlmaWNhIGxhIG1lZGlhIGRlIGxhcyBkaXN0YW5jaWFzIHJlY29ycmlkYXMgZW4gbWlsbGFzLjwvc3Bhbj4KYGBge3J9CiNsYSBtZWRpYSAoTWVhbikgZGUgbGEgZGlzdGFuY2lhIGVzIGRlIDEwNDAgbWlsbGFzLCBsbyBxdWUgaW5kaWNhIHF1ZSwgZW4gcHJvbWVkaW8sIGxvcyB2dWVsb3MgZW4gZXN0ZSBjb25qdW50byBkZSBkYXRvcyByZWNvcnJlbiB1bmEgZGlzdGFuY2lhIGRlIDEwNDAgbWlsbGFzLgpzdW1tYXJ5KGZsaWdodHMpCgpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+My4gQ3JpdGVyaW9zIHBhcmEgZW5jb250cmFyIGFlcm9sw61uZWFzPC9zcGFuPiAKCmBgYHtyfQpkZiA8LSBmbGlnaHRzICU+JSAKICBzZWxlY3QoY2FycmllciwgZGlzdGFuY2UsIG9yaWdpbiwgZGVzdCkgJT4lCiAgZmlsdGVyKGRpc3RhbmNlID4gbWVhbihkaXN0YW5jZSwgbmEucm09IFRSVUUpKSAlPiUgCiAgYXJyYW5nZShkZXNjKGRpc3RhbmNlKSkKCnByaW50KGRmKQpgYGAKCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPjQuIFN1bWEgeSBNZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzIHBvciBjYXJyaWVyPC9zcGFuPiAKYGBge3J9CiMgRW5jdWVudHJhIGxhIHN1bWEgeSBsYSBtZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzIHBvciBjYXJyaWVyLCBlbGltaW5hIGxvcyBOQeKAmVMgZSBpbnRlcnByZXRhIHF1ZSBzaWduaWZpY2EgbGEgc3VtYSB5IGxhIG1lZGlhIGRlIGxhcyBkaXN0YW5jaWFzIHJlY29ycmlkYXMuCgoKZGZEUiA8LSBkZiAlPiUgCiAgZ3JvdXBfYnkoY2Fycmllciwgb3JpZ2luLCBkZXN0KSAlPiUgCiAgc3VtbWFyaXNlKHN1bWFfZGlzdGFuY2lhPSBzdW0oZGlzdGFuY2UsIG5hLnJtPSBUUlVFKSwgCiAgICAgICAgICAgIG1lZGlhX2Rpc3RhbmNpYT0gbWVhbihkaXN0YW5jZSwgbmEucm09IFRSVUUpKSAlPiUgCiMgT3JkZW5hIGVuIGZvcm1hIGRlc2NlbmRlbnRlIHBvciBkaXN0YW5jaWEgcmVjb3JyaWRhCiAgICBhcnJhbmdlKGRlc2MoY2FycmllciksIGRlc2Moc3VtYV9kaXN0YW5jaWEpKQpkZkRSCgpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+NS5PYnNlcnZhIHR1cyByZXN1bHRhZG9zIGRlIGxhIMO6bHRpbWEgdGFibGEgeSBhZ3JlZ2EgdHVzIGludGVycHJldGFjaW9uZXMuPC9zcGFuPgoKKyBMYXMgYWVyb2zDrW5lYXMgb3BlcmFuIGVzdHJhdMOpZ2ljYW1lbnRlIGVuIHJ1dGFzIGxhcmdhcyBkZXNkZSBhZXJvcHVlcnRvcyBlc3BlY8OtZmljb3MgcGFyYSBtYXhpbWl6YXIgbGEgZWZpY2llbmNpYSB5IHNhdGlzZmFjZXIgbGEgZGVtYW5kYSBkZWwgbWVyY2Fkby4gRXN0ZSBjb21wb3J0YW1pZW50byBzZSBldmlkZW5jaWEgZW4gbGEgY29uY2VudHJhY2nDs24gZGUgdnVlbG9zIGRlIGxhcmdhIGRpc3RhbmNpYSBvcGVyYWRvcyBwb3IgYWVyb2zDrW5lYXMgZXNwZWPDrWZpY2FzIGRlc2RlIGFlcm9wdWVydG9zIHBhcnRpY3VsYXJlcywgY29tbyBzZSBtdWVzdHJhIGVuIGxvcyBkYXRvcyByZWNvcGlsYWRvcy4gUG9yIGVqZW1wbG8sIFZpcmdpbiBBbWVyaWNhIChWWCkgZGVzdGFjYSBwb3Igb3BlcmFyIHJ1dGFzIHRyYW5zY29udGluZW50YWxlcyBwcmluY2lwYWxtZW50ZSBkZXNkZSBKRksgaGFjaWEgZGVzdGlub3MgY29tbyBMb3Mgw4FuZ2VsZXMgKExBWCkgeSBTYW4gRnJhbmNpc2NvIChTRk8pLCBsbyBjdWFsIGVzIGluZGljYXRpdm8gZGUgdW5hIGVzdHJhdGVnaWEgb3JpZW50YWRhIGEgc2VydmlyIG1lcmNhZG9zIGRlIGFsdG8gdm9sdW1lbiB5IGxhcmdhIGRpc3RhbmNpYSBkZXNkZSB1biBodWIgZXN0cmF0w6lnaWNvLiBMYSBldmlkZW5jaWEgZGlyZWN0YSBkZSBlc3RhIGFmaXJtYWNpw7NuIHNlIGVuY3VlbnRyYSBlbiBsYXMgc3VtYXMgeSBtZWRpYXMgZGUgZGlzdGFuY2lhcyByZWNvcnJpZGFzIHByZXNlbnRhZGFzIGVuIGxhIHRhYmxhLCBkb25kZSBWWCBvcGVyYSBsYSBydXRhIEpGSy1MQVggY29uIHVuYSBzdW1hIGRlIGRpc3RhbmNpYSBkZSA0NDQ3NTc1IG1pbGxhcyB5IHVuYSBtZWRpYSBkZSAyNDc1IG1pbGxhcywgeSBsYSBydXRhIEpGSy1TRk8gY29uIDM2NTY2MDQgbWlsbGFzIGVuIHRvdGFsIHkgdW5hIG1lZGlhIGRlIDI1ODYgbWlsbGFzLiBBZGVtw6FzLCBTb3V0aHdlc3QgQWlybGluZXMgKFdOKSBtdWVzdHJhIHVuIHBhdHLDs24gZGUgb3BlcmFjacOzbiBjb25jZW50cmFkbyBlbiB2dWVsb3MgZGVzZGUgRVdSIHkgTEdBIGhhY2lhIGRlc3Rpbm9zIG5hY2lvbmFsZXMgY2xhdmUgY29tbyBIb3VzdG9uIChIT1UpIHkgRGVudmVyIChERU4pLCBjb24gc3VtYXMgZGUgZGlzdGFuY2lhIHNpZ25pZmljYXRpdmFzIGNvbW8gMTM3NzEzNiBtaWxsYXMgcGFyYSBFV1ItSE9VIHkgMTE1ODMwMCBtaWxsYXMgcGFyYSBMR0EtREVOLCBsbyBxdWUgcmVmbGVqYSB1bmEgZXN0cmF0ZWdpYSBvcmllbnRhZGEgYSBjdWJyaXIgcnV0YXMgbmFjaW9uYWxlcyBkZSBncmFuIGRlbWFuZGEgZGVzZGUgTnVldmEgWW9yay4KCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+Ni5JZGVudGlmaWNhciBhZXJvbMOtbmVhcyBsw61kZXJlcyBlbiBsb3MgYWVyb3B1ZXJ0b3M8L3NwYW4+CmBgYHtyfQojU2UgaWRlbnRpZmljYSBzaSBsYXMgYWVyb2zDrW5lYXMgbMOtZGVyZXMgc29uIGxhcyBtaXNtYXMgZW4gbG9zIHRyZXMgYWVyb3B1ZXJ0b3MgY3V5byBvcmlnZW4gZXMgTnVldmEgWW9yayB5YSBzZWEgZWwgSm9obiBGLiBLZW5uZWR5IChKRkspLCBlbCBkZSBMYUd1YXJkaWEgKExHQSkgbyBlbCBkZSBOZXdhcmsgTGliZXJ0eSAoRVdSKQoKZGZfSkZLIDwtIGRmRFIgJT4lIAogIGZpbHRlcihvcmlnaW4gPT0gIkpGSyIpICU+JSBhcnJhbmdlKGNhcnJpZXIsIGRlc2Moc3VtYV9kaXN0YW5jaWEpKQoKZGZfSkZLCgpkZl9MR0EgPC0gZGZEUiAlPiUgCiAgZmlsdGVyKG9yaWdpbiA9PSAiTEdBIikgJT4lIGFycmFuZ2UoY2FycmllciwgZGVzYyhzdW1hX2Rpc3RhbmNpYSkpCgpkZl9MR0EKCmRmX0VXUiA8LSBkZkRSICU+JSAKICBmaWx0ZXIob3JpZ2luID09ICJFV1IiKSAlPiUgYXJyYW5nZShjYXJyaWVyLCBkZXNjKHN1bWFfZGlzdGFuY2lhKSkKCmRmX0VXUgoKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPjcuIENvbmNsdXNpw7NuOiBFdmlkZW5jaWEgMTwvc3Bhbj4KClVuaXRlZCBBaXJsaW5lcyAoVUEpIHkgQW1lcmljYW4gQWlybGluZXMgKEFBKSBlbWVyZ2VuIGNvbW8gbGFzIHByaW5jaXBhbGVzIGFlcm9sw61uZWFzIGVuIHTDqXJtaW5vcyBkZSBkaXN0YW5jaWEgdG90YWwgZGUgdnVlbG8sIHByaW5jaXBhbG1lbnRlIGRlYmlkbyBhIHN1cyBvcGVyYWNpb25lcyBjb25jZW50cmFkYXMgZW4gbG9zIGFlcm9wdWVydG9zIGRlIE5ld2FyayBMaWJlcnR5IEludGVybmF0aW9uYWwgKEVXUikgeSBKb2huIEYuIEtlbm5lZHkgSW50ZXJuYXRpb25hbCAoSkZLKS4gRXN0b3MgYWVyb3B1ZXJ0b3MsIGRhZGEgc3UgdWJpY2FjacOzbiBtw6FzIGFsZWphZGEgZGVsIGNlbnRybyBkZSBsYSBjaXVkYWQgeSBzdSBhbXBsaWEgZ2FtYSBkZSBkZXN0aW5vcywgZmFjaWxpdGFuIHZ1ZWxvcyBkZSBtYXlvciBkdXJhY2nDs24uIExhcyBlc3RhZMOtc3RpY2FzIG11ZXN0cmFuIHF1ZSBVQSBsaWRlcmEgY29uIHVuYSBkaXN0YW5jaWEgbWVkaWEgZGUgdnVlbG8gZGUgMjU2NSBtaWxsYXMgZGVzZGUgRVdSIHkgMjU4NiBtaWxsYXMgZGVzZGUgSkZLLCByZXByZXNlbnRhbmRvIGxhcyBjaWZyYXMgbcOhcyBlbGV2YWRhcyBjb21wYXJhZGFzIGNvbiBvdHJhcyBhZXJvbMOtbmVhcyB5IGFlcm9wdWVydG9zLiBQb3Igc3UgcGFydGUsIEFBIHJlZ2lzdHJhIHVuYSBtZWRpYSBkZSAyNDc1IG1pbGxhcyBkZXNkZSBFV1IgeSAxNzAzIG1pbGxhcyBkZXNkZSBKRkssIHBvc2ljaW9uw6FuZG9zZSBjb21vIGxhIHNlZ3VuZGEgZW4gZXN0ZSByw6Fua2luZy4KCkF1bnF1ZSBVQSB5IEFBIGRvbWluYW4gZW4gSkZLIHkgTGFHdWFyZGlhIChMR0EpIHBvciBlbCB2b2x1bWVuIGRlIHRyw6FmaWNvIHkgbGEgZGl2ZXJzaWRhZCBkZSBydXRhcywgZW4gRVdSLCBVbml0ZWQgQWlybGluZXMgdGllbmUgdW5hIHByZXNlbmNpYSBwcmVkb21pbmFudGUgZW4gY29tcGFyYWNpw7NuIGNvbiBBbWVyaWNhbiBBaXJsaW5lcywgcmVmbGVqYW5kbyB1bmEgZGlmZXJlbmNpYSBlbiBsYSBkaXN0YW5jaWEgbWVkaWEgZGUgdnVlbG8geSBlbiBlbCB0aWVtcG8gZGUgdmlhamUuIEVuIHJlc3VtZW4sIFVuaXRlZCBBaXJsaW5lcyBkZXN0YWNhIGNvbW8gbGEgYWVyb2zDrW5lYSBjb24gbGEgbWF5b3IgZGlzdGFuY2lhIG1lZGlhIGRlIHZ1ZWxvIGRlc2RlIEVXUiwgbWllbnRyYXMgcXVlIEFtZXJpY2FuIEFpcmxpbmVzIGxpZGVyYSBkZXNkZSBKRkssIGRlbW9zdHJhbmRvIHN1IGxpZGVyYXpnbyBlbiB0w6lybWlub3MgZGUgbWlsbGFzIGHDqXJlYXMgcmVjb3JyaWRhcyBlbiBjb21wYXJhY2nDs24gY29uIG90cmFzIGNvbXBhw7HDrWFzLiBFc3RhIGRpc3RpbmNpw7NuIHN1YnJheWEgbGEgY29tcGV0aXRpdmlkYWQgeSBsYSBlc3RyYXRlZ2lhIGRlIHJ1dGFzIGRlIGFtYmFzIGFlcm9sw61uZWFzIGVuIGxvcyBwcmluY2lwYWxlcyBhZXJvcHVlcnRvcyBkZSBOdWV2YSBZb3JrLgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPiBFdmlkZW5jaWEgMiAtIEFuYWzDrXRpY2EgZGVzY3JpcHRpdmEgKEludGVncmFjacOzbiBkZSBkYXRvcyBhIHRyYXbDqXMgZGUgbW9kZWxvIGVudGlkYWQtcmVsYWNpw7NuKSAgeSBlbCBjb21wcm9taXNvIMOpdGljbyB5IGNpdWRhZGFubzwvc3Bhbj4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPk1vZGVsbyBFbnRpZGFkLVJlbGFjacOzbjwvc3Bhbj4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5JbmZvcm1hY2nDs24gcGFyYSBjYWRhIHZ1ZWxvPC9zcGFuPgoKYGBge3J9CiNTZSBuZWNlc2l0YSBzYWJlciBkZSBjYWRhIHZ1ZWxvLCBsYSBhZXJvbMOtbmVhLCBlbCBhZXJvcHVlcnRvIGRlIG9yaWdlbiB5IGVsIGFlcm9wdWVydG8gZGVzdGluby4KCmRmYWVyb2xpbmVhIDwtIGRmMSAlPiUgCiAgbGVmdF9qb2luKGFpcmxpbmVzLCBieT0gImNhcnJpZXIiKQoKZGZhZXJvbGluZWEKCmRmYWVyb3B1ZXJ0b19veWQgPC0gZmxpZ2h0cyAlPiUgCiAgc2VsZWN0KGNhcnJpZXIsIG9yaWdpbiwgZGVzdCkKCmRmYWVyb3B1ZXJ0b19veWQKCgpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5DYW50aWRhZCBkZSB2dWVsb3MgcG9yIGRlc3Rpbm88L3NwYW4+CmBgYHtyfSAKIyBjYW50aWRhZCBkZSB2dWVsb3MgcG9yIGNhZGEgZGVzdGlubwpkZmNhbnRpZGFkIDwtIGZsaWdodHMgJT4lIAogIGdyb3VwX2J5KGNhcnJpZXIpICU+JSAKICBzdW1tYXJpc2UobnVtX2ZsaWdodHM9IG4oKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhudW1fZmxpZ2h0cykpCgpkZmNhbnRpZGFkCgoKI1Bvc3Rlcmlvcm1lbnRlIEFncmVnYXIgZWwgbm9tYnJlIGRlIGxhIGFlcm9sw61uZWEgYWwgZGF0YSBmcmFtZSBhbnRlcmlvci4KCmRmbm9tYnJlIDwtIGRmY2FudGlkYWQgJT4lIAogIGxlZnRfam9pbihhaXJsaW5lcywgYnk9ICJjYXJyaWVyIikKCgpkZm5vbWJyZQpgYGAKCgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPkFlcm9sw61uZWFzIHkgRGVzdGlub3M6IE1hw7FhbmEsIFRhcmRlLCBOb2NoZSB5IE1hZHJ1Z2FkYTwvc3Bhbj4KYGBge3J9CmRmQVlEIDwtIGZsaWdodHMgJT4lCiAgc2VsZWN0KGNhcnJpZXIsIGRlc3QsIHNjaGVkX2RlcF90aW1lKSAlPiUgCiAgbGVmdF9qb2luKGFpcmxpbmVzLCBieT0gImNhcnJpZXIiKQoKaG9yYSA8LSBkZkFZRCAlPiUgCiAgbXV0YXRlKGNsYXNfaG9yYXJpbyA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgICAgIGJldHdlZW4oc2NoZWRfZGVwX3RpbWUsIDYwMCwgMTE1OSkgfiAiTWHDsWFuYSIsCiAgICAgICAgICAgICAgICAgICAgICBiZXR3ZWVuKHNjaGVkX2RlcF90aW1lLCAxMjAwLCAxODU5KSB+ICJUYXJkZSIsCiAgICAgICAgICAgICAgICAgICAgICBiZXR3ZWVuKHNjaGVkX2RlcF90aW1lLCAxOTAwLCAyNDAwKSB+ICJOb2NoZSIsCiAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1hZHJ1Z2FkYSIKICAgICAgICAgICAgICAgICAgICApKQpob3JhCgpgYGAKCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+IENhbnRpZGFkIGRlIHZ1ZWxvcyBwb3IgYWVyb2zDrW5lYSB5IGRlc3Rpbm8gcXVlIGhheSBwb3IgbGEgTWHDsWFuYSwgVGFyZGUsIE5vY2hlIHkgTWFkcnVnYWRhPC9zcGFuPgpgYGB7cn0KZGZDRFYgPC0gaG9yYSAlPiUKICBncm91cF9ieShjYXJyaWVyLCBkZXN0LCBjbGFzX2hvcmFyaW8pICU+JQogIHN1bW1hcmlzZShudW1fZmxpZ2h0cyA9IG4oKSkgJT4lCiAgYXJyYW5nZShjYXJyaWVyLCBkZXN0LCBjbGFzX2hvcmFyaW8pCmRmQ0RWCgoKYGBgCgoKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij4gRGVzdGlub3MgYSBsb3MgcXVlIHZ1ZWxhIEFtZXJpY2FuIEFpcmxpbmVzIGVuIE1hZHJ1Z2FkYTwvc3Bhbj4KYGBge3J9CiMgRGVzdGlub3MgYSBsb3MgcXVlIHZ1ZWxhICJBbWVyaWNhbiBBaXJsaW5lcyBJbmMuIiBkdXJhbnRlIGxhIE1hZHJ1Z2FkYQoKZGZEYWEgPC0gaG9yYSAlPiUKICBzZWxlY3QoY2FycmllcixuYW1lLCBkZXN0LGNsYXNfaG9yYXJpbykgJT4lIAogIGZpbHRlcihjYXJyaWVyID09ICJBQSIsIGNsYXNfaG9yYXJpbyA9PSAiTWFkcnVnYWRhIikgJT4lIAogIGdyb3VwX2J5KGNhcnJpZXIsbmFtZSwgZGVzdCxjbGFzX2hvcmFyaW8pCgpkZkRhYQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij4gwr9RdcOpIGF2aW9uZXMgdXRpbGl6YSBsYSBhZXJvbMOtbmVhIEFBPywgeSDCv0N1w6FudG9zIHZ1ZWxvcyBzZSBoYW4gcmVhbGl6YWRvIGNvbiBjYWRhIHVubz88L3NwYW4+CgpgYGB7cn0KIyBDb25vY2VyIGxvcyBhdmlvbmVzIHF1ZSB1c2EgIkFtZXJpY2FuIEFpcmxpbmVzIEluYy4iCgpkZkFBSSA8LSBmbGlnaHRzICU+JQogIGxlZnRfam9pbihwbGFuZXMsIGJ5ID0gInRhaWxudW0iKSAlPiUKICBmaWx0ZXIoY2FycmllciA9PSAiQUEiICYgIWlzLm5hKHR5cGUpKSAlPiUKICBncm91cF9ieShjYXJyaWVyLCB0eXBlLCBlbmdpbmUsIHNlYXRzKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZsaWdodHMgPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhudW1fZmxpZ2h0cykpCmRmQUFJCgpgYGAKCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij4gVmlzdWFsaXphY2nDs24gZGUgRGF0b3M8L3NwYW4+CiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+VnVlbG9zIGNvbiByZXRyYXNvIGVuIGlkYSB5IHJlZ3Jlc288L3NwYW4+CgpgYGB7cn0KI1NlIHNvbGljaXRhIGFuYWxpemFyIHBhcmEgbGEgYWVyb2zDrW5lYSBBbWVyaWNhbiBBaXJsaW5lcyBzaSBsb3MgdnVlbG9zIHF1ZSB0aWVuZW4gcmV0cmFzbyBlbiBsYSBwYXJ0aWRhIHRhbWJpw6luIHRpZW5lbiByZXRyYXNvIGVuIGxhIGhvcmEgZGUgbGxlZ2FkYS5SZWFsaXphIHVuYSB2aXN1YWxpemFjacOzbiBjb24gdW5hIGdyw6FmaWNhIFNjYXR0ZXJwbG90LgoKcGxvdChmbGlnaHRzJGRlcF9kZWxheSwgZmxpZ2h0cyRhcnJfZGVsYXksCiAgICAgbWFpbiA9ICJSZXRyYXNvcyBlbiBsYSBwYXJ0aWRhIHkgbGxlZ2FkYSBwYXJhIGxhIGFlcm9sw61uZWEgQW1lcmljYW4gQWlybGluZXMiLAogICAgIHhsYWIgPSAiUmV0cmFzb3MgZW4gbGEgcGFydGlkYSIsCiAgICAgeWxhYiA9ICJSZXRyYXNvcyBlbiBsYSBsbGVnYWRhIiwKICAgICBjb2wgPSAiYmx1ZSIsCiAgICAgcGNoID0gMQogICAgICkKCgpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+VGVuZGVuY2lhIGRlIGxhIHRlbXBlcmF0dXJhPC9zcGFuPgoKYGBge3J9CiMjVmlzdWFsaXphIGxhIHRlbmRlbmNpYSBkZSBsYSB0ZW1wZXJhdHVyYSBkdXJhbnRlIGxvcyBwcmltZXJvcyAxNSBkw61hcyBkZWwgbWVzIGRlIEVuZXJvIGVuIGxvcyB2dWVsb3MgcXVlIHBhcnRlbiBkZWwgYWVyb3B1ZXJ0byDigJxOZXdhcmssICBFV1LigJ0sIHV0aWxpemFyIHVuYSBncsOhZmljYSBkZSBsw61uZWEuCgpmbGlnaHRfd2VhdGhlciA8LWZsaWdodHMgJT4lIGlubmVyX2pvaW4od2VhdGhlciwgYnkgPSBjKCJvcmlnaW4iID0gIm9yaWdpbiIsICJ5ZWFyIiA9ICJ5ZWFyIiwgIm1vbnRoIiA9ICJtb250aCIsICJkYXkiID0gImRheSIsICJob3VyIiA9ICJob3VyIikpCmZsaWdodF93ZWF0aGVyPC0gbXV0YXRlKGZsaWdodF93ZWF0aGVyLCBjZWxjaXVzPSAoKHRlbXAtMzIpKig1LzkpKSkKZmxpZ2h0X3dlYXRoZXI8LSBtdXRhdGUoZmxpZ2h0X3dlYXRoZXIsIGR3X2NlbGNpdXM9ICgoZGV3cC0zMikqKDUvOSkpKQpmbGlnaHRfd2VhdGhlcjwtIG11dGF0ZShmbGlnaHRfd2VhdGhlciwga2htPSAod2luZF9zcGVlZCoxLjYwOTM0KSkKZmxpZ2h0X3dlYXRoZXI8LSBtdXRhdGUoZmxpZ2h0X3dlYXRoZXIsIG1tPSAocHJlY2lwKjI1LjQpKQpmbGlnaHRfd2VhdGhlcjwtIG11dGF0ZShmbGlnaHRfd2VhdGhlciwga209ICh2aXNpYioxLjYwOTM0KSkKCgp0ZW1wX3Byb21lZGlvIDwtIGZsaWdodF93ZWF0aGVyICU+JQogIGZpbHRlcihvcmlnaW4gPT0gIkVXUiIpICU+JQogIG11dGF0ZShkYXRlID0gYXMuRGF0ZShwYXN0ZSh5ZWFyLCBtb250aCwgZGF5LCBzZXAgPSAiLSIpKSkgJT4lCiAgc2VsZWN0KGRhdGUsIGNlbGNpdXMpICU+JQogIGdyb3VwX2J5KGRhdGUpICU+JQogIHN1bW1hcmlzZSh0ZW1wX3Byb21lZGlvID0gbWVhbihjZWxjaXVzLCBuYS5ybSA9IFRSVUUpKQoKdGVtcF9wcm9tZWRpb19lbmVybyA8LSB0ZW1wX3Byb21lZGlvICU+JQogIGZpbHRlcihiZXR3ZWVuKGRhdGUsIGFzLkRhdGUoIjIwMTMtMDEtMDEiKSwgYXMuRGF0ZSgiMjAxMy0wMS0xNSIpKSkKCnBsb3QodGVtcF9wcm9tZWRpb19lbmVybyRkYXRlLCB0ZW1wX3Byb21lZGlvX2VuZXJvJHRlbXBfcHJvbWVkaW8sIAogICAgIHR5cGUgPSAibCIsCiAgICAgbWFpbiA9ICJUZW1wZXJhdHVyYSBkdXJhbnRlIGxvcyBwcmltZXJvcyAxNSBkw61hcyBkZSBlbmVybyBlbiAoTmV3YXJrKSIsCiAgICAgeGxhYiA9ICJGZWNoYSIsCiAgICAgeWxhYiA9ICJUZW1wZXJhdHVyYSBQcm9tZWRpbyAoQ8KwKSIpCmBgYAoKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+VGVtcGVyYXR1cmEgbcOhcyBmcmVjdWVudGU8L3NwYW4+CmBgYHtyfQojVmlzdWFsaXphIGxhIHRlbXBlcmF0dXJhIG3DoXMgZnJlY3VlbnRlIGVuIGxvcyBwcmltZXJvcyAxNSBkw61hcyBkZWwgbWVzIGRlIEVuZXJvLCB1dGlsaXphciB1biBoaXN0cm9ncmFtYQp3ZWF0aGVyX2VuZXJvIDwtIGZsaWdodF93ZWF0aGVyICU+JQogIGZpbHRlcihtb250aCA9PSAxLCBkYXkgPj0gMSwgZGF5IDw9IDE1KQoKd2VhdGhlcl9lbmVybyRkYXRlIDwtIGFzLkRhdGUocGFzdGUod2VhdGhlcl9lbmVybyR5ZWFyLCB3ZWF0aGVyX2VuZXJvJG1vbnRoLCB3ZWF0aGVyX2VuZXJvJGRheSwgc2VwID0gIi0iKSkKCnRlbXBfcHJvbWVkaW8gPC0gd2VhdGhlcl9lbmVybyAlPiUKICBncm91cF9ieShkYXRlKSAlPiUKICBzdW1tYXJpemUodGVtcF9wcm9tZWRpbyA9IG1lYW4oY2VsY2l1cywgbmEucm0gPSBUUlVFKSkKCmdncGxvdChkYXRhID0gdGVtcF9wcm9tZWRpbywgYWVzKHggPSB0ZW1wX3Byb21lZGlvKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgZmlsbCA9ICJwdXJwbGUiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbWEgZGUgUHJvbWVkaW8gZGUgVGVtcGVyYXR1cmFzIGRlbCAxIGFsIDE1IGRlIEVuZXJvIiwKICAgICAgIHggPSAiUHJvbWVkaW8gZGUgVGVtcGVyYXR1cmEgKEPCsCkiLAogICAgICAgeSA9ICJGcmVjdWVuY2lhIikKYGBgCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5GYWNldHM8L3NwYW4+CmBgYHtyfQojVXRpbGl6YSBGYWNldHMgcGFyYSBvYnNlcnZhciBjw7NtbyB2YXLDrWEgbGEgdGVtcGVyYXR1cmEgZW4gY2FkYSBtZXMgZW4gw6lsIGhpc3RvZ3JhbWEgZGVsIHB1bnRvIGFudGVyaW9yCgpnZ3Bsb3QoZGF0YSA9IGZsaWdodF93ZWF0aGVyLCBhZXMoeCA9IGNlbGNpdXMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBjb2xvciA9ICJyZWQiKSArCiAgZmFjZXRfd3JhcCh+IG1vbnRoLCBucm93ID0gNCkKYGBgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPlZ1ZWxvcyBxdWUgc2FsaWVyb24gZGUgTnVldmEgWW9yayBlbiBlbCAyMDEzPC9zcGFuPgpgYGB7cn0KI07Dum1lcm8gZGUgdnVlbG9zIHF1ZSBzYWxpZXJvbiBkZSBOdWV2YSBZb3JrIGVuIDIwMTMgcG9yIGFlcm9sw61uZWEgKG1vc3RyYXIgc29sYW1lbnRlIGxhcyAxMCBhZXJvbMOtbmVhcyBjb24gbcOhcyB2dWVsb3MpLCB1dGlsaXphciBncsOhZmljYSBkZSBiYXJyYXMuCgpmbGlnaHRzX3RhYmxlIDwtIGZsaWdodHMgJT4lIAogIGdyb3VwX2J5KGNhcnJpZXIpICU+JSAKICBzdW1tYXJpemUobnVtYmVyID0gbigpKQogICAgICAgICAKZ2dwbG90KGRhdGEgPSBmbGlnaHRzX3RhYmxlLCBtYXBwaW5nID0gYWVzKHggPSBjYXJyaWVyLCB5ID0gbnVtYmVyKSkgKwogIGdlb21fY29sKCkKCgpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+R3JhZmljYSBkZSBwaWU8L3NwYW4+CmBgYHtyfQojVmlzdWFsaXphIGVsIHB1bnRvIGFudGVyaW9yIGVuIHVuYSBncsOhZmljYSBkZSBwaWUuCnBpZShmbGlnaHRzX3RhYmxlJG51bWJlciwKICAgIGxhYmVscyA9IGZsaWdodHNfdGFibGUkY2FycmllciwKICAgIG1haW4gPSAiUHJvcG9yY2nDs24gZGUgdnVlbG9zIHBvciBhZXJvbMOtbmVhIiwKICAgIGNvbCA9IHJhaW5ib3cobGVuZ3RoKGZsaWdodHNfdGFibGUkY2FycmllcikpLAogICAgY2V4ID0gMC41KQpgYGAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrOyI+UmVsYWNpw7NuIEZsaWdodHMgYW5kIEFpcnBvcnRzPC9zcGFuPgpgYGB7cn0KI1JlbGFjaW9uYSBlbCBkYXRhIGZyYW1lIGZsaWdodHMgY29uIGVsIGRhdGEgZnJhbWUgYWlycG9ydHMgYSB0cmF2w6lzIGRlbCBjYW1wbyBkZXN0aW5vIMK/Y8OzbW8gbG9ncmFyIGVzdGFzIHJlbGFjacOzbj8KCmZsaWdodHNfYWlycG9ydHMgPC0gZmxpZ2h0cyAlPiUKICBsZWZ0X2pvaW4oYWlycG9ydHMsIGJ5ID0gYygiZGVzdCIgPSAiZmFhIikpCgoKYGBgCgoKIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5EYXRhIGZyYW1lPC9zcGFuPgpgYGB7cn0KdG9wX2NhcnJpZXJzIDwtIGZsaWdodHMgJT4lCiAgaW5uZXJfam9pbihhaXJwb3J0cywgYnkgPSBjKCJvcmlnaW4iID0gImZhYSIpKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IHRvcF9jYXJyaWVycywgbWFwcGluZyA9IGFlcyh4ID0gY2FycmllciwgZmlsbCA9IG5hbWUpKSArCiAgZ2VvbV9iYXIoKQoKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSB0b3BfY2FycmllcnMsIG1hcHBpbmcgPSBhZXMoeCA9IGNhcnJpZXIsIGZpbGwgPSBuYW1lKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSB0b3BfY2FycmllcnMsIG1hcHBpbmcgPSBhZXMoeCA9IGNhcnJpZXIsIGZpbGwgPSBuYW1lKSkgKwogIGdlb21fYmFyKCkgKwogIGZhY2V0X2dyaWQobmFtZSB+IC4pCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibGFjazsiPkNvbmNsdXNpw7NuZXM8L3NwYW4+CgpMb3MgdnVlbG9zIGRlICoqQW1lcmljYW4gQWlybGluZXMqKiBxdWUgdGllbmVuIHJldHJhc28gZW4gbGEgcGFydGlkYSBlbnRyZSAwLTEwMCBtaW51dG9zLCBubyB0aWVuZW4gcmV0cmFzbyBlbiBsYSBsbGVnYWRhLiBBbCBjcnV6YXIgZGUgbG9zIDEwMCBtaW51dG9zIGRlIHJldHJhc28gZW4gbGEgcGFydGlkYSBzZSBlbXBpZXphIGEgbm90YXIgbcOhcyBlbCByZXRyYXNvIGVuIGxhIGxsZWdhZGEuIExhIG1heW9yw61hIGRlIGxvcyB2dWVsb3MgcXVlIHNhbGVuIHRhcmRlIHJlYWp1c3RhbiBsYSB2ZWxvY2lkYWQgZW4gZWwgYWlyZSBwYXJhIHF1ZSBsYSBkZW1vcmEgZGUgbGEgbGxlZ2FkYSBubyBzZWEgaWd1YWwsIHNpbm8gbXVjaG8gbWVub3IuIFNvbiBtaW5vcsOtYSBsb3MgY2Fzb3MgcXVlIG5vIHRpZW5lbiByZXRyYXNvIGVuIGxhIHBhcnRpZGEgeSBzaSB0aWVuZW4gcmV0cmFzbyBlbiBsYSBsbGVnYWRhLiAqKkFtZXJpY2FuIEFpcmxpbmVzKiogdGllbmUgdW5hIGNsYXJhIHZlbnRhamEgY29tcGV0aXRpdmEgcG9ycXVlIGFsIGFuYWxpemFyIGxvcyBkYXRvcyBkZSBsb3MgdnVlbG9zLCBtYW50aWVuZW4gbGEgZ3JhbiBwYXJ0ZSBkZSBzdXMgdnVlbG9zIGVudHJlIDAtMTAwIG1pbnV0b3MgZGUgcmV0cmFzbyBlbiBsYSBwYXJ0aWRhLCBsb3MgdnVlbG9zIHF1ZSBzZSByZXRyYXNhbiBkZSBtw6FzIGHDum4gYXPDrSBubyB0aWVuZW4gdW5hIGdyYW4gZGVtb3JhIGVuIGxhIGxsZWdhZGEuICoqQW1lcmljYW4gQWlybGluZXMqKiBzZSBlbmN1ZW50cmEgZW4gdW4gcHVudG8gYWx0byBlbiByZWxhY2nDs24gYSBzdSBjb21wZXRlbmNpYSwgbGEgYWVyb2zDrW5lYSByZXByZXNlbnRhIGVsIDkuNzIlIGRlIGxhIGNhbnRpZGFkIGRlIHZ1ZWxvcyBwb3IgZGVzdGlubywgdGllbmUgcHJpbmNpcGFsbWVudGUgYSA0IGNvbXBldGlkb3JlcyBzdXBlcmlvcmVzICgqKlVuaXRlZCoqLCAqKkpldEJsdWUqKiwgKipFeHByZXNzSmV0KiogeSAqKkRlbHRhKiopIHkgMTEgaW5mZXJpb3Jlcy4KCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5Db21wcm9taXNvIMOpdGljbyB5IGNpdWRhZGFubzwvc3Bhbj4gCkRlc2NyaWJlIGVsIHZhbG9yIGRlIGxhIGludGVncmlkYWQuCgorIExhIGludGVncmlkYWQgaW1wbGljYSBlbnRlcmV6YSBtb3JhbCwgcmVjdGl0dWQsIHkgaG9ucmFkZXogZW4gbGEgY29uZHVjdGEgeSBlbCBjb21wb3J0YW1pZW50by4gRGVyaXZhIGRlbCBsYXTDrW4gImludGVncsStdGFzIiwgc2lnbmlmaWNhbmRvIHRvdGFsaWRhZCwgcHVyZXphLCBlIGlub2NlbmNpYS4gRW4gdW4gc2VudGlkbyBtw6FzIGFtcGxpbywgbGEgaW50ZWdyaWRhZCBzZSByZWxhY2lvbmEgY29uIHNlciBjb21wbGV0bywgZXN0YXIgaW50YWN0bywgeSBubyBlc3RhciBhZmVjdGFkbyBwb3IgZWwgbWFsIG8gZGHDsW8sIHlhIHNlYSBmw61zaWNvIG8gbW9yYWwuIEFkZW3DoXMsIGxhIGludGVncmlkYWQgcGVyc29uYWwgc2UgYXNvY2lhIGNvbiBzZXIgZWR1Y2FkbywgaG9uZXN0bywgcmVzcGV0dW9zbyBjb25zaWdvIG1pc21vIHkgY29uIGxvcyBkZW3DoXMsIHkgbWFudGVuZXIgZmlybWV6YSBlbiBsYXMgYWNjaW9uZXMuKEVuY2ljbG9wZWRpYSBTaWduaWZpY2Fkb3MsIDIwMjMpCgpFbmNpY2xvcGVkaWEgU2lnbmlmaWNhZG9zLCBFLiAoMjAyMywgNSBtYXlvKS4gUXXDqSBlcyBJbnRlZ3JpZGFkICh5IHN1IHNpZ25pZmljYWRvKS4gRW5jaWNsb3BlZGlhIFNpZ25pZmljYWRvcy4gaHR0cHM6Ly93d3cuc2lnbmlmaWNhZG9zLmNvbS9pbnRlZ3JpZGFkLwoKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmxhY2s7Ij5SZWZsZXhpw7NuIFBlcnNvbmFsOgoKIMK/IGPDs21vIHB1ZWRlcyBhY3R1YXIgY29uIHJlc3BldG8geSBob25lc3RpZGFkIGVuIGxvcyBuZWdvY2lvcyB5IGVuIGVsIHVzbyBkZSBkYXRvcyBjdWFuZG8gcmVhbGljZXMgYW7DoWxpc2lzIGRlIGRhdG9zIHkgZXN0w6lzIGVuIGNvbnRhY3RvIGNvbiBsb3MgZGF0b3MgZGUgdW5hIGVtcHJlc2E/CgoqKkFsbWEqKjpBY3R1YXIgY29uIHJlc3BldG8geSBob25lc3RpZGFkIGVuIGxvcyBuZWdvY2lvcyB5IGFsIG1hbmVqYXIgZGF0b3MgZXMgY3J1Y2lhbCBwYXJhIG1hbnRlbmVyIGxhIGNvbmZpYW56YSB5IGxhIGludGVncmlkYWQuIExhIGhvbmVzdGlkYWQgcHJvbXVldmUgcHLDoWN0aWNhcyBzYW5hcyB5IG9yZ2FuaXphY2lvbmVzIHPDs2xpZGFzIChBcmdhbmRvw7FhLCAyMDIyKSwgbWllbnRyYXMgcXVlIGFkaGVyaXJzZSBhIHByaW5jaXBpb3Mgw6l0aWNvcyBhc2VndXJhIHRyYW5zcGFyZW5jaWEgeSBldml0YSBwcsOhY3RpY2FzIGNvcnJ1cHRhcywgY29udHJpYnV5ZW5kbyBhbCBkZXNhcnJvbGxvIHNvc3RlbmlibGUgKGFicmllbmRvbWVyY2Fkb3MuY29tLCAyMDIzKS4gQWRlbcOhcywgbGEgY29ydGVzw61hIHkgZWwgcmVzcGV0byBmb3J0YWxlY2VuIHJlbGFjaW9uZXMgZHVyYWRlcmFzLCBmdW5kYW1lbnRhbGVzIHBhcmEgZWwgw6l4aXRvIGVtcHJlc2FyaWFsIChlc2xhYm9uZXNkZW5lZ29jaW8uY29tKS4gRW4gcmVzdW1lbiwgZXN0b3MgdmFsb3JlcyBubyBzb2xvIGJlbmVmaWNpYW4gYSBsYXMgZW1wcmVzYXMgw6l0aWNhbWVudGUsIHNpbm8gcXVlIHRhbWJpw6luIGltcHVsc2FuIGVsIGNyZWNpbWllbnRvIHkgbGEgaW1hZ2VuIHBvc2l0aXZhIGVuIGVsIG1lcmNhZG8uCgoqKkRpZWdvKio6Q29uc2lkZXJvIHF1ZSB0cmFiYWphciBjb24gZGF0b3MsIGVzIHVuIHRyYWJham8gcXVlIHRpZW5lIHF1ZSBsbGV2YXJzZSBhIGNhYm8gY29uIG11Y2hhIGludGVsaWdlbmNpYSB5IGRlbGljYWRlemEsIHlhIHF1ZSBsYXMgZW1wcmVzYXMgdGUgZXN0w6FuIGNvbmZpYW5kbyBsbyBtw6FzIGltcG9ydGFudGUgcXVlIHRpZW5lbiB5IGVzbyBlcyBzdSBpbmZvcm1hY2nDs24uIFBhcmEgYXNlZ3VyYXIgbGEgY29uZmlkZW5jaWFsaWRhZCwgcGFyYSBtaSwgZWwgcHJpbWVyIHBhc28gZXMgdHJhYmFqYXIgYmFqbyBjb250cmF0byBkb25kZSBzZSBlc3BlY2lmaXF1ZSBkZSBmb3JtYSBjbGFyYSwgwr9xdWnDqW4gdGllbmUgYWNjZXNvIGEgZXN0YSBpbmZvcm1hY2nDs24/LCDCv2EgcXVpw6luIHNlIHB1ZWRlIGFjdWRpciBlbiBjYXNvIGRlIGR1ZGFzPywgwr9wYXJhIHF1acOpbiB2YSBkaXJpZ2lkYSBsYSBpbmZvcm1hY2nDs24gdW5hIHZleiBwcm9jZXNhZGE/IGV0Yy4gRXMgZGVjaXIsIHRlbmVyIGJpZW4gZGVsaW1pdGFkbyBlbCBwcm9jZXNvIGRlIG1hbmlwdWxhY2nDs24gcXVlIHNlIGxsZXZhcsOhIGEgY2Fiby4gUG9zdGVyaW9ybWVudGUsIHRyYWJhamFyIGRlIGxhIG1hbm8gY29uIGxhIGVtcHJlc2EsIGVzIGRlY2lyLCB0ZW5lcmxvcyBpbmZvcm1hZG9zIGVuIHRvZG8gbW9tZW50byBkZWwgcHJvY2VzbyB5IHNlciB0cmFuc3BhcmVudGVzIGFsIHJlc3BlY3RvLiBQb3Igw7psdGltbywgcmVzcGV0YXIgbG9zIGxpbmVhbWllbnRvcyBkZSBsYXMgZW1wcmVzYXMgeSBzdSBmaWxvc29mw61hIGVtcHJlc2FyaWFsLCBjYWRhIG9yZ2FuaXphY2nDs24gdGllbmUgdW5hIG1hbmVyYSBkZSBvcGVyYXIgeSBlcyBlc2VuY2lhbCBhZGFwdGFyc2UgYWwgZXN0aWxvIGRlIHRyYWJham8gZGUgZXN0YXMuCgoqKk9zdmFsZG8qKjpQYXJhIG3DrSwgbGEgaG9uZXN0aWRhZCB5IHJlc3BldG8gcHJvdmllbmVuIGRlIHVuYSDDqXRpY2EgcXVlIHNlIGNvbXBhcnRlIGVuIGNhc2EgbyBwb3IgcGFydGUgZGUgbG9zIG1hZXN0cm9zLCBxdWUgaW5jdWxjYW4gZGVudHJvIGRlIGxvcyBlc3R1ZGlhbnRlcyBlbCBjb25vY2ltaWVudG8gZGUgbG8gcXVlIGVzIGNvcnJlY3RvIHkgbm8uIEVuIG1pIGNhc28gY3JlbyBxdWUgY29uc2lzdGUgZW4gcHJvdGVnZXIgbGEgcHJpdmFjaWRhZCBkZSBsb3MgZGF0b3MsIGEgc3UgdmV6IGRlIG9idGVuZXIgZWwgY29uc2VudGltaWVudG8gcGFyYSBlbCB1c28gZGUgbG9zIGRhdG9zLCB5IHNpZW5kbyDDrW50ZWdybyB5IGd1YXJkYW5kbyBsYSBjb25maWRlbmNpYWxpZGFkIGRlIGxhIGluZm9ybWFjacOzbi4gUGFyYSBtw60gZXMgaW1wb3J0YW50ZSBldml0YXIgY3VhbHF1aWVyIGZvcm1hIGRlIG1hbmlwdWxhY2nDs24gbyB1c28gZW5nYcOxb3NvIGUgaW5jb3JyZWN0byBkZSBsYSBpbmZvcm1hY2nDs24uIEN1bXBsaWVuZG8gY29uIGxhcyByZWd1bGFjaW9uZXMgZGUgcHJvdGVjY2nDs24gZGUgZGF0b3MsIGNvbXVuaWNhbmRvIGNsYXJhbWVudGUgbGFzIHBvbMOtdGljYXMgZGUgcHJpdmFjaWRhZCB5IHNlZ3VyaWRhZCwgeSBsbGV2YW5kbyBhIGNhYm8gbGEgdHJhbnNwYXJlbmNpYSBlbiBlbCBtYW5lam8gZGUgZGF0b3MsIGFzw60gcHVlZG8gbGxlZ2FyIGEgY29uc3RydWlyIHVuYSByZXB1dGFjacOzbiBzw7NsaWRhIHkgZ2FuYXJtZSBsYSBjb25maWFuemEgZGUgcG9zaWJsZXMgY2xpZW50ZXMsIGRlIG1pcyBjb21wYcOxZXJvcyB5IHByb2Zlc29yZXMuIEN1YWxxdWllciBkdWRhIHF1ZSB0ZW5nYSBjb24gcmVsYWNpw7NuIGFsIHVzbyBkZSBkYXRvcyBxdWUgbm8gbWUgcGVydGVuZWNlbiBkZWJvIGNvbnN1bHRhcmxvIGNvbiBsb3MgYXV0b3JlcyBkZSBkaWNob3MgZGF0b3MgeSBubyBkYXIgbmFkYSBwb3IgaGVjaG8gZGUgbWkgcGFydGUuCgoqKlJlZmVyZW5jaWFzOioqCisgQXJnYW5kb8OxYSwgQS4gKDIwMjIpLiBMYSBob25lc3RpZGFkIGVuIGxhIGVtcHJlc2EuIElFU0UgQnVzaW5lc3MgU2Nob29sIEJsb2cuIGh0dHBzOi8vYmxvZy5pZXNlLmVkdS9hbnRvbmlvYXJnYW5kb25hLzIwMjIvMDYvMjEvbGEtaG9uZXN0aWRhZC1lbi1sYS1lbXByZXNhLworIMOJdGljYSBlbXByZXNhcmlhbCBlbiBuZWdvY2lvcyBpbnRlcm5hY2lvbmFsZXM6IGPDs2RpZ29zIHkgcHJpbmNpcGlvcyDDqXRpY29zLiAoMjAyMykuIEFicmllbmRvIE1lcmNhZG9zLiBodHRwczovL2FicmllbmRvbWVyY2Fkb3MuY29tL2V0aWNhLWVtcHJlc2FyaWFsLWVuLW5lZ29jaW9zLWludGVybmFjaW9uYWxlcy1jb2RpZ29zLXktcHJpbmNpcGlvcy1ldGljb3MvCisgQ29ydGVzw61hIHkgcmVzcGV0byBjb21vIHBpbGFyZXMgZGUgbGFzIHJlbGFjaW9uZXMgZGUgbmVnb2Npby4gRXNsYWJvbmVzIGRlIE5lZ29jaW8uIGh0dHBzOi8vZXNsYWJvbmVzZGVuZWdvY2lvLmNvbS9jb3J0ZXNpYS15LXJlc3BldG8tY29tby1waWxhcmVzLWRlLWxhcy1yZWxhY2lvbmVzLWRlLW5lZ29jaW8vCgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiID5DQVNPOiDCv1BvciBxdcOpIHNlIHJldHJhc2FuIGxvcyB2dWVsb3MgZW4gTnVldmEgWW9yaz88L3NwYW4+PC9zcGFuPgoKIyMgW0JBU0UgREUgREFUT1Nde3N0eWxlPSJibGFjazogYmx1ZTsifQpgYGB7cn0KZmxpZ2h0cyA8LSBmbGlnaHRzCndlYXRoZXIgPC0gd2VhdGhlcgpwbGFuZXMgPC0gcGxhbmVzCmFpcnBvcnRzIDwtIGFpcnBvcnRzCmFpcmxpbmVzIDwtIGFpcmxpbmVzCmJkZ3JhbmRlIDwtbWVyZ2UoZmxpZ2h0cyxhaXJsaW5lcywgYnk9ImNhcnJpZXIiKQpiZGdyYW5kZTIgPC1sZWZ0X2pvaW4oYmRncmFuZGUscGxhbmVzLCBieT0idGFpbG51bSIpCmJkZ3JhbmRlMyA8LSBsZWZ0X2pvaW4oYmRncmFuZGUyLHdlYXRoZXIsYnk9Yygib3JpZ2luIiwidGltZV9ob3VyIikpCmJkZ3JhbmRlNCA8LSBsZWZ0X2pvaW4oYmRncmFuZGUzLCBhaXJwb3J0cywgYnkgPSBjKCJvcmlnaW4iID0gImZhYSIpKQpiZGdyYW5kZTUgPC0gbGVmdF9qb2luKGJkZ3JhbmRlNCwgYWlycG9ydHMsIGJ5ID0gYygiZGVzdCIgPSAiZmFhIikpCgpkaW0oYmRncmFuZGU1KQpgYGAKCiMjIFtQb3JjZW50YWplIGRlIHJldHJhc29zIHBvciBhZXJvcHVlcnRvXXtzdHlsZT0iYmxhY2s6IGJsdWU7In0KYGBge3J9CgpzdW1tYXJ5X2RlbGF5IDwtIGJkZ3JhbmRlNSAlPiUKICBncm91cF9ieShvcmlnaW4pICU+JQogIHN1bW1hcmlzZShhdmdfZGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgdG90YWxfZmxpZ2h0cyA9IG4oKSwKICAgICAgICAgICAgdG90YWxfZGVsYXllZF9mbGlnaHRzID0gc3VtKGRlcF9kZWxheSA+IDAsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHBlcmNfZGVsYXllZF9mbGlnaHRzID0gdG90YWxfZGVsYXllZF9mbGlnaHRzIC8gdG90YWxfZmxpZ2h0cyAqIDEwMCkKCnN1bW1hcnlfZGVsYXkKYGBgCiMjIyBbR3LDoWZpY2EgMS4gTnVtZXJvIGRlIHZ1ZWxvcyBwb3IgYWVyb3B1ZXJ0byBjb24geSBzaW4gcmV0cmFzb117c3R5bGU9ImJsYWNrOiBibHVlOyJ9CgpgYGB7cn0KZmxpZ2h0c19maWx0ZXJlZCA8LSBiZGdyYW5kZTUgJT4lCiAgbXV0YXRlKGRlbGF5ZWQgPSBpZmVsc2UoZGVwX2RlbGF5ID4gMCwgIkRlbGF5ZWQiLCAiTm90IERlbGF5ZWQiKSkgJT4lCiAgZ3JvdXBfYnkob3JpZ2luLCBkZWxheWVkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIG11dGF0ZShwZXJjZW50ID0gY291bnQgLyBzdW0oY291bnQpICogMTAwKQoKZ2dwbG90KGZsaWdodHNfZmlsdGVyZWQsIGFlcyh4ID0gZmFjdG9yKG9yaWdpbiksIHkgPSBjb3VudCwgZmlsbCA9IGRlbGF5ZWQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJncmVlbiIpKSArCiAgbGFicyh0aXRsZSA9ICJOw7ptZXJvIGRlIHZ1ZWxvcyBwb3IgYWVyb3B1ZXJ0byBjb24geSBzaW4gcmV0cmFzbyIsCiAgICAgICB4ID0gIkFlcm9wdWVydG8iLAogICAgICAgeSA9ICJOw7ptZXJvIGRlIHZ1ZWxvcyIsCiAgICAgICBmaWxsID0gIlJldHJhc28iKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKKiAqT2JzZXJ2YWNpb25lcyo6IAorIEVsIGFlcm9wdWVydG8gY29uIG1heW9yIHBvcmNlbnRhamUgZGUgcmV0cmFzb3MgZXMgZWwgIkVXUiIgY29uIDQzLjYlLCBzZWd1aWRvIHBvciBlbCBhZXJvcHVldG8gIkpGSyIgY29uIDM3LjclIHkgcG9yIHVsdGltbywgZWwgYWVyb3B1ZXJ0byBMR0EgY29uIDMyLjIlLgorIEVsIGFlcm9wdWVybyBFV1IsIGVzIGVsIGFlcm9wdWVydG8gY29uIGVsIG1heW9yIG51bWVybyBkZSB2dWVsb3MgY29uIDEyMCw4MzUsIHNlZ3VpZG8gcG9yIGVsIGFlcm9wdWVydG8gIkpGSyIgY29uIDExMSwyNzkgeSBwb3IgdWx0aW1vLCBlbCBhZXJvcHVlcnRvIExHQSBjb24gMTA0LDY2Mi4gCisgRW4gbGEgZ3JhZmljYSwgc2UgcHVlZGUgYXByZWNpYXIgZXN0byBjb24gbG9zIGNvbG9yZXMgdmVyZGVzIHkgcm9qbywgc2llbmRvIGVsIHZlcmRlIGVsIG51bWVybyBkZSB2dWVsb3MgYSB0aWVtcG8geSBlbCByb2pvIHNpZW5kbyBlbCBudW1lcm8gZGUgdnVlbG9zIHJldHJhc2Fkb3MuIAorIEVzdG8gaW5kaWNhLCBxdWUgdW4gZmFjdG9yIHF1ZSBhZmVjdGEgbGEgcHVudHVhbGlkYWQgZGUgbG9zIHZ1ZWxvcywgZXMgbGEgY2FudGlkYWQgZGUgdnVlbG9zIGNvbW8gdGFsLiBDb24gbGFzIG9ic2VydmFjaW9uZXMgYW50ZXJpb3JlcyBwb2RlbW9zIGNvbmNsdWlyIHF1ZSBlbCBwb3JjZW50YWplIGRlIHJldHJhc29zIGVzIGRpcmVjdGFtZW50ZSBwcm9wb3JjaW9uYWwgYWwgbnVtZXJvIGRlIHZ1ZWxvcyBwb3IgYWVyb3B1ZXJ0by4gVW4gZWplbXBsbyBlcyBxdWUgZWwgYWVyb3B1ZXJ0byAiRVdSIiwgcXVlIGN1ZW50YSBjb24gZWwgbWF5b3IgbnVtZXJvIGRlIHZ1ZWxvcyAoMTIwLDgzNSksIHRhbWJpZW4gY3VlbnRhIGNvbiBlbCBtYXlvciBwb3JjZW50YWplIGRlIHJldHJhc29zICg0My42JSkuIAoKIyMgW1BvcmNlbnRhamUgZGUgcmV0cmFzb3MgcG9yIGRlc3Rpbm9de3N0eWxlPSJibGFjazogYmx1ZTsifQpgYGB7cn0Kc3VtbWFyeV9kZWxheSA8LSBiZGdyYW5kZTUgJT4lCiAgZ3JvdXBfYnkoZGVzdCkgJT4lCiAgc3VtbWFyaXNlKGF2Z19kZWxheSA9IG1lYW4oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICB0b3RhbF9mbGlnaHRzID0gbigpLAogICAgICAgICAgICB0b3RhbF9kZWxheWVkX2ZsaWdodHMgPSBzdW0oZGVwX2RlbGF5ID4gMCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcGVyY19kZWxheWVkX2ZsaWdodHMgPSB0b3RhbF9kZWxheWVkX2ZsaWdodHMgLyB0b3RhbF9mbGlnaHRzICogMTAwKQoKc3VtbWFyeV9kZWxheQpgYGAKIyMjIFtHcsOhZmljYSAyLiBOdW1lcm8gZGUgdnVlbG9zIHBvciBkZXN0aW5vIGNvbiB5IHNpbiByZXRyYXNvXXtzdHlsZT0iYmxhY2s6IGJsdWU7In0KCmBgYHtyfQpmbGlnaHRzX2ZpbHRlcmVkIDwtIGJkZ3JhbmRlNSAlPiUKICBtdXRhdGUoZGVsYXllZCA9IGlmZWxzZShkZXBfZGVsYXkgPiAwLCAiRGVsYXllZCIsICJOb3QgRGVsYXllZCIpKSAlPiUKICBncm91cF9ieShkZXN0LCBkZWxheWVkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIG11dGF0ZShwZXJjZW50ID0gY291bnQgLyBzdW0oY291bnQpICogMTAwKQoKCmdncGxvdChmbGlnaHRzX2ZpbHRlcmVkLCBhZXMoeCA9IGZhY3RvcihkZXN0KSwgeSA9IGNvdW50LCBmaWxsID0gZGVsYXllZCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAic3RhY2siKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygicmVkIiwgImdyZWVuIikpICsKICBsYWJzKHRpdGxlID0gIk7Dum1lcm8gZGUgdnVlbG9zIHBvciBkZXN0aW5vIGNvbiB5IHNpbiByZXRyYXNvIiwKICAgICAgIHggPSAiRGVzdGlubyIsCiAgICAgICB5ID0gIk7Dum1lcm8gZGUgdnVlbG9zIiwKICAgICAgIGZpbGwgPSAiUmV0cmFzbyIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgoqICpPYnNlcnZhY2lvbmVzKjogCisgU2UgcHVlZGUgb2JzZXJ2YXIgcXVlICJPUkQiLCBmdWUgZWwgZGVzdGlubyBjb24gbWFzIHZ1ZWxvcywgc2VndWlkbyBwb3IgIkFUTCIuICJPUkQiLCB0dXZvIDE3LDI4MyB2dWVsb3MgeSAiQVQiTCwgdHV2byAxNywyMTUgdnVlbG9zLgorIFNlIHB1ZWRlIG9ic2VydmFyIHF1ZSBleGlzdGUgdW5hIGRpZmVyZW5jaWEgYWJpc21hbCBlbiBlbCBudW1lcm8gZGUgdnVlbG9zIGRlIGxvcyBhZXJvcHVlcnRvcy4gRWwgZGVzdGlubyAiTEVYIiBZICJMR0EiLCB0aWVuZW4gMSBzb2xvIHZ1ZWxvLiAKKyBDb24gbG8gbWVuY2lvbmFkbyBhbnRlcmlvcm1lbnRlLCBubyBwb2RlbW9zIHNlZ3VpciBjb24gZXN0YSBsaW5lYSBkZSBpbnZlc3RpZ2FjaW9uLCBkZWJpZG8gYSBxdWUgbG9zIHByb2NlbnRhamVzIGRlIHZ1ZWxvcyByZXRyYXNhZG9zLCBubyBzZXJpYW4gc2lnbmlmaWNhdGl2b3MgZGViaWRvIGEgbGEgZ3JhbiBkaWZlcmVuY2lhIGRlIHZ1ZWxvcyBwb3IgZGVzdGluby4gVW4gZWplbXBsbyBlcyBlbCBkZXN0aW5vICJBTkMiLCB0aWVuZSB1biBwb3JjZW50YWplIGRlIHJldHJhc28gZGVsIDc1JSBwZXJvIHNvbG8gdGllbmUgOCB2dWVsb3MuIAoKIyMgW1BvcmNlbnRhamUgZGUgcmV0cmFzb3MgcG9yIG1lc117c3R5bGU9ImJsYWNrOiBibHVlOyJ9CgpgYGB7cn0KCnN1bW1hcnlfZGVsYXkgPC0gYmRncmFuZGU1ICU+JQogIGdyb3VwX2J5KG1vbnRoLngpICU+JQogIHN1bW1hcmlzZShhdmdfZGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgdG90YWxfZmxpZ2h0cyA9IG4oKSwKICAgICAgICAgICAgdG90YWxfZGVsYXllZF9mbGlnaHRzID0gc3VtKGRlcF9kZWxheSA+IDAsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHBlcmNfZGVsYXllZF9mbGlnaHRzID0gdG90YWxfZGVsYXllZF9mbGlnaHRzIC8gdG90YWxfZmxpZ2h0cyAqIDEwMCkKCnN1bW1hcnlfZGVsYXkKYGBgCgojIyMgW0dyw6FmaWNhIDMuIE51bWVybyBkZSB2dWVsb3MgcG9yIG1lcyBjb24geSBzaW4gcmV0cmFzb117c3R5bGU9ImJsYWNrOiBibHVlOyJ9CmBgYHtyfQpmbGlnaHRzX2ZpbHRlcmVkIDwtIGJkZ3JhbmRlNSAlPiUKICBtdXRhdGUoZGVsYXllZCA9IGlmZWxzZShkZXBfZGVsYXkgPiAwLCAiRGVsYXllZCIsICJOb3QgRGVsYXllZCIpKSAlPiUKICBncm91cF9ieShtb250aC54LCBkZWxheWVkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIG11dGF0ZShwZXJjZW50ID0gY291bnQgLyBzdW0oY291bnQpICogMTAwKQoKCmdncGxvdChmbGlnaHRzX2ZpbHRlcmVkLCBhZXMoeCA9IGZhY3Rvcihtb250aC54KSwgeSA9IGNvdW50LCBmaWxsID0gZGVsYXllZCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAic3RhY2siKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygicmVkIiwgImdyZWVuIikpICsKICBsYWJzKHRpdGxlID0gIk7Dum1lcm8gZGUgdnVlbG9zIHBvciBtZXMgY29uIHkgc2luIHJldHJhc28iLAogICAgICAgeCA9ICJNZXMiLAogICAgICAgeSA9ICJOw7ptZXJvIGRlIHZ1ZWxvcyIsCiAgICAgICBmaWxsID0gIlJldHJhc28iKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKKiAqT2JzZXJ2YWNpb25lcyo6IAorIFNlIHB1ZWRlIG9ic2VydmFyIHF1ZSBsb3MgbWVzZXMgZGUgIkp1bGlvIiB5ICJEaWNpZW1icmUiLCBzb24gbG9zIG1lc2VzIGNvbiBtYXMgcG9yY2VudGFqZSBkZSByZXRyYXNvLiAiSnVsaW8iIGN1ZW50YSBjb24gNDcuMyUgZGUgcmV0cmFzbyB5ICJEaWNpZW1icmUiIGNvbiA0OC4yJSBkZSByZXRyYXNvLiAKKyBTZSBwdWVkZSBvYmVydmFyIEp1bGlvIHkgQWdvc3RvLCB0aWVuZW4gbGEgbWF5b3IgZGVtYW5kYSwgeWEgcXVlIHNvbiBsb3MgbWVzZXMgY29uIG1hcyBudW1lcm8gZGUgdnVlbG9zLiBKdWxpbyB0aWVuZSAyOS40MjQgdnVlbG9zIHkgQWdvc3RvIHRpZW5lIDI5LDMyNyB2dWVsb3MuCisgRGllbWJyZSBjdWVudGEgY29uIDI4LDEzNSB2dWVsb3MsIGxvIGN1YWwgbm8gZXMgbmFkYSBmdWVyYSBkZSBsYSBtZWRpYS4gCisgQ29uIGxvIGFudGVyaW9yLCBzZSBwdWVkZSBjb25jbHVpciBxdWUgbGEgZGVtYW5kYSB5IG1hcyBlc3BlY2lmaWNhbWVudGUgbGFzIHZhY2FjaW9uZXMsIHNvbiB1biBmYWN0b3IgY2xhdmUgcXVlIGFmZWN0YSBsYSBwdW50dWFsaWRhZCBkZSBsb3MgdnVlbG9zLCB5YSBsYXMgdmFjYWNpb25lcyBkZSB2ZXJhbm8gZW1waWV6YW4gZW4gSnVsaW8geSBsYXMgdmFjYWNpb25lcyBkZSBuYXZpZGFkIGVtcGllemFuIGVuIERpY2llbWJyZS4gRXN0YXMgZG9zIGZlY2hhcywgc29uIGxhcyBmZWNoYXMgY29uIG1heW9yIHBvcmNlbnRhamUgZGUgcmV0cmFzb3MsIGRlIGFjdWVyZG8gYSBsYSBpbmZvcm1hY2nDs24gcHJvcG9yY2lvbmFkYS4gCgojIyBbUG9yY2VudGFqZSBkZSByZXRyYXNvcyBwb3IgaG9yYV17c3R5bGU9ImJsYWNrOiBibHVlOyJ9CgpgYGB7cn0KCmJkZ3JhbmRlNSA8LSBiZGdyYW5kZTUgJT4lCiAgbXV0YXRlKGhvdXJfb2ZfZGF5ID0gc2NoZWRfZGVwX3RpbWUgJS8lIDEwMCkgICMgRXh0cmFlIGxhIGhvcmEgZGVsIHRpZW1wbyBkZSBzYWxpZGEgcHJvZ3JhbWFkbwoKc3VtbWFyeV9kZWxheSA8LSBiZGdyYW5kZTUgJT4lCiAgZ3JvdXBfYnkoaG91cl9vZl9kYXkpICU+JQogIHN1bW1hcmlzZShhdmdfZGVsYXkgPSBtZWFuKGRlcF9kZWxheSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgdG90YWxfZmxpZ2h0cyA9IG4oKSwKICAgICAgICAgICAgdG90YWxfZGVsYXllZF9mbGlnaHRzID0gc3VtKGRlcF9kZWxheSA+IDAsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHBlcmNfZGVsYXllZF9mbGlnaHRzID0gdG90YWxfZGVsYXllZF9mbGlnaHRzIC8gdG90YWxfZmxpZ2h0cyAqIDEwMCkKCnN1bW1hcnlfZGVsYXkKYGBgCgojIyMgW0dyw6FmaWNhIDQuIE51bWVybyBkZSB2dWVsb3MgcG9yIGhvcmEgY29uIHkgc2luIHJldHJhc29de3N0eWxlPSJibGFjazogYmx1ZTsifQoKYGBge3J9CgpmbGlnaHRzX2ZpbHRlcmVkIDwtIGJkZ3JhbmRlNSAlPiUKICBtdXRhdGUoZGVsYXllZCA9IGlmZWxzZShkZXBfZGVsYXkgPiAwLCAiRGVsYXllZCIsICJOb3QgRGVsYXllZCIpKSAlPiUKICBncm91cF9ieShob3VyX29mX2RheSwgZGVsYXllZCkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUKICBtdXRhdGUocGVyY2VudCA9IGNvdW50IC8gc3VtKGNvdW50KSAqIDEwMCkKCgpnZ3Bsb3QoZmxpZ2h0c19maWx0ZXJlZCwgYWVzKHggPSBmYWN0b3IoaG91cl9vZl9kYXkpLCB5ID0gY291bnQsIGZpbGwgPSBkZWxheWVkKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJzdGFjayIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJyZWQiLCAiZ3JlZW4iKSkgKwogIGxhYnModGl0bGUgPSAiTsO6bWVybyBkZSB2dWVsb3MgcG9yIGhvcmEgY29uIHkgc2luIHJldHJhc28iLAogICAgICAgeCA9ICJIb3JhIiwKICAgICAgIHkgPSAiTsO6bWVybyBkZSB2dWVsb3MiLAogICAgICAgZmlsbCA9ICJSZXRyYXNvIikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCiogKk9ic2VydmFjaW9uZXMqOiAKKyBTZSBwdWVkZSBvYnNlcnZhciwgcXVlIGxhIGhvcmEgcGljbyBkZSB2dWVsb3MgZXMgYSBsYXMgODowMCBjb24gMjcsMjQyIHZ1ZWxvcywgc2VndWlkbyBwb3IgbGFzIDY6MDAgY29uIDI1LDk1MSB2dWVsb3MuCisgU2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGVuIGxhIHRhcmRlIGxvcyB2dWVsb3MgdGllbmVuIHVuIG1heW9yIHBvcmNlbnRhamUgZGUgcmV0cmFzb3MuIEVzcGVjaWFsbWVudGUgZGUgMTc6MDAgYSAyMTowMCwgZWwgcG9yY2VudGFqZSBlcyByZWFsbWVudGUgYWx0by4gQSBsYXMgMTc6MDAsIHNlIHRpZW5lIHVuIHBvcmNlbnRhamUgZGUgNDkuNyUsIGEgbGFzIDE4OjAwLCBzZSB0aWVuZSB1biBwb3JjZW50YWplIGRlIDQ4LjglLCBhIGxhcyAxOTowMCB1biBwb3JjZW50YWplIGRlIDUwLjYlLCBhIGxhcyAyMDowMCwgdW4gcHJvY2VudGFqZSBkZSA1MS42JSB5IGEgbGFzIDIxOjAwLCB1biBwcm9jZW50YWplIGRlIDUxLjIlLgorIEEgbGFzIDIwOjAwIHNlIHRpZW5lIGVsIG1heW9yIHBvcmNlbnRhamUgZGUgcmV0cmFzb3MuCisgU2Ugb2JzZXJ2YSwgcXVlIGVsIHJldHJhc28gcHJvbWVkaW8sIGRlIGlndWFsIG1hbmVyYSwgYXVtZW50YSBjb25zaWRlcmFibGVtZW50ZSBkZSAxNzowMCBhIDIxOjAwLiBBIGxhcyAxNzowMCBzZSB0aWVuZSB1biBwcm9tZWRpbyBkZSAyMS4xIG1pbnV0b3MsIGEgbGFzIDE4OjAwLCBzZSB0aWVuZSB1biBwcm9tZWRpbyBkZSBkZSAyMS4xIG1pbnV0b3MsIGEgbGFzIDE5OjAwLCBzZSB0aWVuZSB1biBwcm9tZWRpbyBkZSAyNC44IG1pbnV0b3MsIGEgbGFzIDIwOjAwLCBzZSB0aWVuZSB1biBwcm9tZWRpbyBkZSAyNC4zIG1pbnV0b3MgeSBhIGxhcyAyMS4wMCBzZSB0aWVuZSB1biBwcm9tZWRpbyBkZSAyNC4yIG1pbnV0b3MuCisgU2Ugb2JzZXJ2YSwgcXVlIG5vIHNvbG8gZWwgcG9yY2VudGFqZSBkZSB2dWVsb3MsIHNpbm8gdGFtYmllbiBsYSBjYW50aWRhZCBkZSByZXRyYXNvIGF1bWVudG8gZHVyYW50ZSBlc2FzIGhvcmFzLiAKKyBDb24gZXN0bywgc2UgcHVlZGUgY29uY2x1aXIgcXVlIGxvcyByZXRyYXNvcyBzdXJnZW4gZW4gdW4gZWZlY3RvIGNhZGVuYSwgZGViaWRvIGEgcXVlIGNvbmZvcm1lIHZhIHBhc2FuZG8gZWwgZMOtYSwgZWwgcG9yY2VudGFqZSBkZSB2dWVsb3MgcmV0cmFzYWRvcyBhdW1lbnRvLCBlc3BlY2lhbGVtbnRlIGVuIGxhIHRhcmRlIGRlIDE3LjAwIGEgMjE6MDAsIGFsIG1vbWVudG8gZGUgcmV0cmFzYXJzZSB1biB2dWVsbywgc2UgdmVuIGFmZWN0YWRvcyBsb3MgZGVtYXMgdnVlbG9zIHF1ZSB2aWVuZW4gZGVzcHVlcyBkZSBlbCwgZGViaWRvIGEgcXVlIHVuIGF2acOzbiwgbm8gaGFjZSB1biBzb2xvIHJlY29ycmRpbyBhbCBkw61hLCBzaW5vIHF1ZSBzZSBsZSBpbnRlbnRhIHNhY2FyIGVsIG1heGltbyBwcm92ZWNobyBwb3NpYmxlIGEgY2FkYSB1bm8sIGVzZSByZXRyYXNvIHNlIHZhIGFjdW11bGFuZG8gY29uZm9ybWUgdmEgcGFzYW5kbyBlbCBkw61hLCBlc3RvIHNlIGV4cGxpY2EsIGNvbiBsYSB0ZW5kZW5jaWEgeSBlbCBhdW1lbnRvIHRhbnRvIGRlIHBvcmNlbnRhamUgY29tbyBkZSBwcm9tZWRpbyBkZSByZXRyYXNvLiAKCiMjIFtDb25jbHVzaW9uZXNde3N0eWxlPSJibGFjazogYmx1ZTsifQoKTGEgcHJvYmFiaWxpZGFkIGRlIHJldHJhc29zIGVuIGxvcyB2dWVsb3MgdmFyw61hIHNpZ25pZmljYXRpdmFtZW50ZSBzZWfDum4gZWwgYWVyb3B1ZXJ0byBkZSBvcmlnZW4sIGVsIG1lcyBkZWwgYcOxbyB5IGxhIGhvcmEgZGVsIGTDrWEsIGNvbiBsb3MgYWVyb3B1ZXJ0b3MgbcOhcyBjb25jdXJyaWRvcyB5IGxhcyBob3JhcyBwaWNvIHByZXNlbnRhbmRvIG1heW9yZXMgZGVzYWbDrW9zIHBhcmEgbGEgcHVudHVhbGlkYWQgZGUgbG9zIHZ1ZWxvcy4gCgpMb3MgYWVyb3B1ZXJ0b3MgY29uIHVuIGFsdG8gdm9sdW1lbiBkZSB0csOhZmljbyBhw6lyZW8sIGNvbW8gRVdSLCB0aWVuZGVuIGEgZXhwZXJpbWVudGFyIG1heW9yZXMgcmV0cmFzb3MsIHByb2JhYmxlbWVudGUgZGViaWRvIGEgbGEgY29uZ2VzdGnDs24geSBsYSBjb21wbGVqaWRhZCBkZSBtYW5lamFyIHVuIG1heW9yIG7Dum1lcm8gZGUgb3BlcmFjaW9uZXMgc2ltdWx0w6FuZWFzLiBTZWfDum4gbG9zIGRhdG9zIGFuYWxpemFkb3MsIEVXUiwgY29uIHVuIG1heW9yIHZvbHVtZW4gdG90YWwgZGUgdnVlbG9zICgxMjAsODM1KSB5IHVuIG1heW9yIHBvcmNlbnRhamUgZGUgdnVlbG9zIHJldHJhc2Fkb3MgKDQzLjYlKSwgZXhwZXJpbWVudGEgbcOhcyByZXRyYXNvcyBlbiBjb21wYXJhY2nDs24gY29uIEpGSyB5IExHQS4gIExvcyBjdWFsZXMgY3VlbnRhbiBjb24gdW4gdG90YWwgZGUgdnVlbG9zIGRlIDExMSwyNzkgeSAxMDQsNjYyIHkgdW4gcG9yY2VudGFqZSBkZSByZXRyYXNvcyBkZSAzNy43JSB5IDMyLjIlIHJlc3BlY3RpdmFtZW50ZS4gCgpBZGljaW9uYWxtZW50ZSwgY2llcnRvcyBwZXJpb2RvcyBkZWwgYcOxbywgZXNwZWNpYWxtZW50ZSDigJxKdWxpb+KAnSB5IOKAnERpY2llbWJyZeKAnSwgbXVlc3RyYW4gdW4gYXVtZW50byBlbiBlbCBwb3JjZW50YWplIGRlIHJldHJhc29zLCBsb3MgY3VhbGVzIGRlc3RhY2Fyb24gcG9yIHRlbmVyIGxvcyBwb3JjZW50YWplcyBtYXMgYWx0b3MgZGUgcmV0cmFzb3MsIGNvbiA0Ny4zJSB5IDQ4LjIlIHJlc3BlY3RpdmFtZW50ZSwgbG8gcXVlIHJlZmxlamEgZWwgaW1wYWN0byBkZSBsYXMgdmFjYWNpb25lcyB5IGxhIGRlbWFuZGEgZXN0YWNpb25hbCBlbiBsYSBwdW50dWFsaWRhZCBkZSBsb3MgdnVlbG9zLiBMYXMgZmVjaGFzIGNvaW5jaWRlbiBjb24gZWwgaW5pY2lvIGRlIHZhY2FjaW9uZXMgZGUgdmVyYW5vIGVuIOKAnEp1bGlv4oCdIHkgZWwgaW5pY2lvIGRlIHZhY2FjaW9uZXMgZGUgaW52aWVybm8gZW4g4oCcRGljaWVtYnJl4oCdLiBBZGljaW9uYWxtZW50ZSDigJxKdWxpb+KAnSB5IOKAnUFnb3N0b+KAnSwgY3VlbnRhbiBjb24gbGEgbWF5b3IgZGVtYW5kYSBkZSB2dWVsb3MsICBKdWxpbyBjb24gMjksNDI0IHZ1ZWxvcyB5IEFnb3N0byBjb24gMjksMzI3IHZ1ZWxvcy4gCgpGaW5hbG1lbnRlLCBsYXMgaG9yYXMgZGUgbGEgdGFyZGUgKGRlIDE3OjAwIGEgMjE6MDApLCBleHBlcmltZW50YW4gdW4gaW5jcmVtZW50byBlbiBsb3MgcmV0cmFzb3MgZW4gY29tcGFyYWNpw7NuIGNvbiBsYXMgaG9yYXMgbWF0dXRpbmFzLCBpbmRpY2FuZG8gcXVlIGxvcyByZXRyYXNvcyBhY3VtdWxhdGl2b3MgYSBsbyBsYXJnbyBkZWwgZMOtYSB5IGxhIG1heW9yIGRlbWFuZGEgZGUgdnVlbG9zIGR1cmFudGUgZXN0YXMgaG9yYXMgY29udHJpYnV5ZW4gYSBjb21wbGljYWNpb25lcyBhZGljaW9uYWxlcyBlbiBsYXMgb3BlcmFjaW9uZXMgYcOpcmVhcy4gRXN0byBzZSBkZW11ZXN0cmEgZGViaWRvIGEgcXVlIG5vIHNvbG8gZWwgcG9yY2VudGFqZSBkZSByZXRyYXNvcyBlcyBtYXlvciBkdXJhbnRlIGVzdGFzIGhvcmFzIGRlbCBkw61hLCBzaW5vIHRhbWJpZW4gZWwgcmV0cmFzbyBwcm9tZWRpbyBlcyBtYXlvci4gVW4gZWplbXBsbywgZXMgcXVlIGEgcGVzYXIgZGUgcXVlIGEgbGFzIDg6MDAgZXMgbGEgaG9yYSBwaWNvIGRlIHZ1ZWxvcyAoMjcsNzQyIHZ1ZWxvcyksIGVsIHBvcmNlbnRhamUgZGUgcmV0cmFzbyBlcyBkZWwgMjQuOSAlIHkgZWwgcmV0cmFzbyBwcm9tZWRpbyBlcyBkZSB0YW4gc29sbyA0LjEgbWludXRvcywgbWllbnRyYXMgcXVlIGEgbGFzIDIwOjAwLCBoYXkgdW4gdG90YWwgZGUgMTYsNzM5IHZ1ZWxvcywgcGVybyBlbCBwb3JjZW50YWplIGRlIHJldHJhc28gZXMgZGVsIDUxLjYlIHkgZWwgcmV0cmFzbyBwcm9tZWRpbyBlcyBkZSAyNC4zIG1pbnV0b3MuIAoKCg==