Contexto

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

Este paquete incluye las siguientes tablas:

  • flights = todos los vuelos que salieron de Nueva York en 2013
  • weather = datos meteorológicos por hora de cada aeropuerto
  • planes = informacion de construcción de cada avión
  • airports = nombres y ubicaciones de aeropuertos
  • airlines = relacion entre nombres y códigos de las aerolinea

Fuente:
Origen de los Datos

Situación Problema 1. Actividad 1.

Tema: base de datos, sus campos, registros,tipos de datos y los resultados descriptivos de la base de datos.

Situación problema: ¿Cómo mejorar la posición competitiva de una de las aerolíneas líderes en los aeropuertos de Nueva York?

Instrucciones:

• Paquetes requeridos para la práctica: tidyverse, nyflights13 El paquete tidyverse incluye varias librerías entre ellas ggplot2, dplyr, tidyverse El paquete nyflights13 incluye varias bases de datos entre ellas flights • Librerías que deben estar instaladas: dplyr

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

data(flights)
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. Cargar en memoria la tabla flights y mostrar su contenido. Consulta la estructura de flights, ¿Cuáles son los campos y sus tipos de datos? Identifica los diferentes tipos de datos y explica en qué consiste cada uno de ellos y cuál es la diferencia entre uno y otro, incluyendo los siguientes tipos de datos: int, dbl, chr, dttm

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

###3. ¿Cuál es la clase de flights? y ¿Qué significa?

class(flights)
## [1] "tbl_df"     "tbl"        "data.frame"

###4. ¿Cuántas columnas tiene flights?

ncol(flights)
## [1] 19

###5. ¿Cuántos renglones tiene flights?

nrow(flights)
## [1] 336776

###6. ¿Cuál es la dimensión de flights?

dim(flights)
## [1] 336776     19

###7. Consulta la tabla flights

View(flights)

###8. Genera un output de la tabla flights. Utiliza las funciones head y tail, ¿Cuántos renglones muestran por defecto cada función?

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>

###9. Ahora muestra los primeros 50 registros y los últimos 20, ¿Cómo lo harías?

head(flights,50)
## # A tibble: 50 × 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
## # ℹ 40 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>
tail(flights,20)
## # A tibble: 20 × 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     2150           2159        -9     2250           2306
##  2  2013     9    30     2159           1845       194     2344           2030
##  3  2013     9    30     2203           2205        -2     2339           2331
##  4  2013     9    30     2207           2140        27     2257           2250
##  5  2013     9    30     2211           2059        72     2339           2242
##  6  2013     9    30     2231           2245       -14     2335           2356
##  7  2013     9    30     2233           2113        80      112             30
##  8  2013     9    30     2235           2001       154       59           2249
##  9  2013     9    30     2237           2245        -8     2345           2353
## 10  2013     9    30     2240           2245        -5     2334           2351
## 11  2013     9    30     2240           2250       -10     2347              7
## 12  2013     9    30     2241           2246        -5     2345              1
## 13  2013     9    30     2307           2255        12     2359           2358
## 14  2013     9    30     2349           2359       -10      325            350
## 15  2013     9    30       NA           1842        NA       NA           2019
## 16  2013     9    30       NA           1455        NA       NA           1634
## 17  2013     9    30       NA           2200        NA       NA           2312
## 18  2013     9    30       NA           1210        NA       NA           1330
## 19  2013     9    30       NA           1159        NA       NA           1344
## 20  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>

###10. Encuentra los resultados descriptivos de las variables en la base de datos. Ejemplo: promedio, moda, mínimo, máximo, etc.Función: summary.

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

Situación Problema 1. Actividad 2.

Funciones básicas para la manipulación de datos. Temas: Dplyr (filter, arrange, select, rename, mutate, summarize, group_by) if/else, subset, for (loops) Situación problema: ¿Cómo mejorar la posición competitiva de una de las aerolíneas líderes en los aeropuertos de Nueva York? Instrucciones: Librerías requeridas: • Paquetes requeridos para la práctica: tidyverse, nyflights13 El paquete tidyverse incluye varias librerías entre ellas ggplot2, dplyr, tidyverse El paquete nyflights13 incluye varias bases de datos entre ellas flights • Librerías que deben estar instaladas: ggplot2, dplyr, tidyverse

library(nycflights13)
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.3.3
## Warning: package 'ggplot2' was built under R version 4.3.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.0     ✔ readr     2.1.4
## ✔ ggplot2   3.5.0     ✔ stringr   1.5.1
## ✔ lubridate 1.9.3     ✔ tibble    3.2.1
## ✔ purrr     1.0.2     ✔ tidyr     1.3.0
## ── 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
library(dplyr)
data("flights")

###1. Mostrar la base de datos flights para que conozcas su contenido

View(flights)

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

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

###3. Define un criterio para encontrar las aerolíneas que han recorrido más distancia (en millas) y crea un nuevo data frame que filtre solamente a las aeorlíneas que han recorridao una distancia superior a la media, se desea ver los campos carrier, distance, origin, dest en forma descendente por distance. Ejemplo: aerolíneas con millas recorridas superiores a la media, ordenadas en forma descendente.

#selecciona las variables carrier, distance, origin, dest de la tabla
res01 <- select(flights, carrier, distance, origin, dest)

#se filtra las aerolíneas con millas recorridas superiores a la media - 1040 
res02 <- filter(res01, distance >1040) 

#ordena en forma descendente por distancia recorrida 
res03 <- arrange(res02, desc(distance))

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

#Agrupar los datos por carrier,origin, dest y obtener la suma acumulada y la media de las distancias recorridas por carrier eliminando los NA's
res04 <- res03 %>% 
  group_by(carrier,origin,dest)
sumdistance <- sum(res03$distance, n= TRUE)

###5. Ordena en forma descendente por distancia recorrida

res05 <- arrange(res04,carrier,sumdistance)

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

###7.Identifica si las aerolíneas líderes son las mismas en los tres aeropuertos cuyo origen es Nueva York ( John F. Kennedy (JFK), LaGuardia (LGA) and Newark Liberty (EWR) ).
Genera un data frame para cada aeropuerto. Funciones: filter(), arrange()

JFK = res05 %>%  
  filter(origin == "JFK")  %>%
  arrange(carrier, desc(sumdistance))
LGA = res05 %>%  
  filter(origin == "LGA")  %>%
  arrange(carrier, desc(sumdistance))
EWR = res05 %>%  
  filter(origin == "EWR")  %>%
  arrange(carrier, desc(sumdistance))

Situación Problema 1. Actividad 3.

knitr::opts_chunk$set(echo = TRUE)

R Markdown

###1. Consulta las tablas planes y weather para que conozcas su contenido.

view(planes)
view(weather)

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

aerolineas <- flights %>% 
  select(carrier,origin,dest)

###3. En la consulta anterior se necesita conocer el nombre de la aerolínea.

aerolineas_nombre <- aerolineas %>%
  left_join(airlines, by = "carrier")

###4 Se necesita saber la cantidad de vuelos por cada destino para identificar cuáles son los destinos más buscados.

cant_vuelos <- flights %>% 
  select(carrier, dest) %>% 
  count(carrier)

###5 Agregar el nombre de la aerolínea a la tabla anterior.

cant_vuelos_nombre <- cant_vuelos %>%
  left_join(airlines, by = "carrier")

###6. Se necesita conocer las aerolíneas (clave y nombre) y destinos que vuelan por la Mañana: de 6 a 12, Tarde: de 12 a 19 , Noche: de 19 a 24 y Madrugada de 24 a 6. # Agrega un nuevo campo a la tabla con el nombre de clas_horario y agrega, mañana, tarde, noche y madrugada según sea el caso.

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

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

###7.Se necesita saber la cantidad de vuelos por aerolínea y destino que hay por la Mañana, Tarde, Noche y Madrugada.

cant_clasxhora <- clasxhora %>% 
             group_by(carrier, dest,clas_horario) %>% count()

###8 Se necesita saber a qué destinos vuela la aerolínea American Airlines Inc.-AA durante la madrugada.

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

###9. ¿Qué aviones utiliza la aerolínea AA? aerolínea, tipo, motor y número de asientos y ¿Cuántos vuelos se han realizado con cada uno? elimina los NA’s

avion_aa <- flights %>%
  left_join(planes, by = "tailnum") %>%
  select(carrier, type, engine, seats) %>%
  filter(carrier == "AA", !is.na(type)) %>%
  group_by(carrier,type,engine,seats) %>% 
  count()

Evidencia 1.

Te acabas de incorporar a una empresa consultora en Inteligencia de Negocios, actualmente están brindando servicios de análisis para la industria de la aviación y les interesa tener a la aerolínea American Airlines como cliente ya que es una de las aerolíneas líderes en los aeropuertos de Nueva York, motivo por el cuál te han contratado.

Instalar paquetes y llamar librerías

# install.packages("nycflights13")
library(nycflights13)
# install.packages("tidyverse")
library(tidyverse)

Guardar bases de datos

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

Relación entre las bases de datos

1. Data Frames e Identificación de tipo de datos

## Datos de Weather
weather
## # A tibble: 26,115 × 15
##    origin  year month   day  hour  temp  dewp humid wind_dir wind_speed
##    <chr>  <int> <int> <int> <int> <dbl> <dbl> <dbl>    <dbl>      <dbl>
##  1 EWR     2013     1     1     1  39.0  26.1  59.4      270      10.4 
##  2 EWR     2013     1     1     2  39.0  27.0  61.6      250       8.06
##  3 EWR     2013     1     1     3  39.0  28.0  64.4      240      11.5 
##  4 EWR     2013     1     1     4  39.9  28.0  62.2      250      12.7 
##  5 EWR     2013     1     1     5  39.0  28.0  64.4      260      12.7 
##  6 EWR     2013     1     1     6  37.9  28.0  67.2      240      11.5 
##  7 EWR     2013     1     1     7  39.0  28.0  64.4      240      15.0 
##  8 EWR     2013     1     1     8  39.9  28.0  62.2      250      10.4 
##  9 EWR     2013     1     1     9  39.9  28.0  62.2      260      15.0 
## 10 EWR     2013     1     1    10  41    28.0  59.6      260      13.8 
## # ℹ 26,105 more rows
## # ℹ 5 more variables: wind_gust <dbl>, precip <dbl>, pressure <dbl>,
## #   visib <dbl>, time_hour <dttm>
## Datos de Planes
planes
## # A tibble: 3,322 × 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…
##  7 N107US   1999 Fixed wing multi… AIRBUS INDU… A320…       2   182    NA Turbo…
##  8 N108UW   1999 Fixed wing multi… AIRBUS INDU… A320…       2   182    NA Turbo…
##  9 N109UW   1999 Fixed wing multi… AIRBUS INDU… A320…       2   182    NA Turbo…
## 10 N110UW   1999 Fixed wing multi… AIRBUS INDU… A320…       2   182    NA Turbo…
## # ℹ 3,312 more rows
## Datos de Airports
airports
## # A tibble: 1,458 × 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/…
##  2 06A   Moton Field Municipal Airport   32.5  -85.7   264    -6 A     America/…
##  3 06C   Schaumburg Regional             42.0  -88.1   801    -6 A     America/…
##  4 06N   Randall Airport                 41.4  -74.4   523    -5 A     America/…
##  5 09J   Jekyll Island Airport           31.1  -81.4    11    -5 A     America/…
##  6 0A9   Elizabethton Municipal Airport  36.4  -82.2  1593    -5 A     America/…
##  7 0G6   Williams County Airport         41.5  -84.5   730    -5 A     America/…
##  8 0G7   Finger Lakes Regional Airport   42.9  -76.8   492    -5 A     America/…
##  9 0P2   Shoestring Aviation Airfield    39.8  -76.6  1000    -5 U     America/…
## 10 0S9   Jefferson County Intl           48.1 -123.    108    -8 A     America/…
## # ℹ 1,448 more rows
## Datos de airlines
airlines
## # A tibble: 16 × 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.   
##  7 F9      Frontier Airlines Inc.     
##  8 FL      AirTran Airways Corporation
##  9 HA      Hawaiian Airlines Inc.     
## 10 MQ      Envoy Air                  
## 11 OO      SkyWest Airlines Inc.      
## 12 UA      United Air Lines Inc.      
## 13 US      US Airways Inc.            
## 14 VX      Virgin America             
## 15 WN      Southwest Airlines Co.     
## 16 YV      Mesa Airlines Inc.

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

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

3. 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 (no tiene decimales). Se utiliza para almacenar valores numéricos sin decimales, como la cantidad de pasajeros o el número de vuelos.
# dbl: Se usa para almacenar números con decimales, como distancias o precios.
# num: numérico (tiene decimales) peso
# chr: caracter (letras). Se usa para almacenar texto, como nombres o palabras.  
# Date: fecha (en R va año-mes-día)
# POSIXct: formato fecha y hora. Es un tipo de dato que representa una fecha y hora específica. Se utiliza para almacenar información temporal, como la fecha de un vuelo o la hora de salida.

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

class(flights)
## [1] "tbl_df"     "tbl"        "data.frame"
class
## function (x)  .Primitive("class")
# Las 5 clases de objetos son:
# 1. numeric: número real o decimales
# 2. integer: números enteros
# 3. complex: números complejos
# 4. character: caracteres, letras o palabras
# 5. logical: TRUE o FALSE

# Las 4 clases de objetos compuestos son: 

# 1. list: lista
# 2. matrix: matriz (es todo lo mismo)
# 3. array: colección de objetos
# 4. data.frame: base de datos (es mezclado)

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

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

6. Muestra los primeros 6 renglones de “flights”, también los últimos 6.

head(flights)
## # A tibble: 6 × 19
##    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
## 1  2013     1     1      517            515         2      830            819
## 2  2013     1     1      533            529         4      850            830
## 3  2013     1     1      542            540         2      923            850
## 4  2013     1     1      544            545        -1     1004           1022
## 5  2013     1     1      554            600        -6      812            837
## 6  2013     1     1      554            558        -4      740            728
## # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## #   hour <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. Muestra los estadísticos 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  
## 

7.1. Distancia media recorrida en millas.

summary(flights$distance)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      17     502     872    1040    1389    4983

Podemos ver que la distancia media en millas es de 1040

7.2. Aerolíneas con millas recorridas superiores a la media, ordenadas en forma descendente.

media_distancia <- mean(flights$distance, na.rm = TRUE)
aerolineas_top <- flights %>%
  filter(distance > media_distancia) %>%
  select(carrier, distance, origin, dest) %>%
  arrange(desc(distance))
print(aerolineas_top)
## # 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

7.3. Encuentra la suma y la media de las distancias recorridas por carrier

distancia_aerolinea <- flights %>%
  filter(!is.na(distance)) %>%
  group_by(carrier) %>%
  summarise(
    suma_distancia = sum(distance),
    media_distancia = mean(distance, na.rm = TRUE)
  ) %>%
  arrange(desc(suma_distancia))
print(distancia_aerolinea)
## # A tibble: 16 × 3
##    carrier suma_distancia media_distancia
##    <chr>            <dbl>           <dbl>
##  1 UA            89705524           1529.
##  2 DL            59507317           1237.
##  3 B6            58384137           1069.
##  4 AA            43864584           1340.
##  5 EV            30498951            563.
##  6 MQ            15033955            570.
##  7 VX            12902327           2499.
##  8 WN            12229203            996.
##  9 US            11365778            553.
## 10 9E             9788152            530.
## 11 FL             2167344            665.
## 12 AS             1715028           2402 
## 13 HA             1704186           4983 
## 14 F9             1109700           1620 
## 15 YV              225395            375.
## 16 OO               16026            501.

8. Identifica si las aerolíneas líderes son las mismas en los tres aeropuertos

# Función para crear un data frame para un aeropuerto
aeropuerto_df <- function(aeropuerto) {
  flights %>%
    filter(origin == aeropuerto) %>%
    filter(!is.na(distance)) %>%
    group_by(carrier) %>%
    summarise(
      suma_distancia = sum(distance),
      media_distancia = mean(distance, na.rm = TRUE)
    ) %>%
    arrange(desc(suma_distancia))
}

# Data frames para cada aeropuerto
jfk_df <- aeropuerto_df("JFK")
lga_df <- aeropuerto_df("LGA")
ewr_df <- aeropuerto_df("EWR")

# Mostrar los data frames
print(jfk_df)
## # A tibble: 10 × 3
##    carrier suma_distancia media_distancia
##    <chr>            <dbl>           <dbl>
##  1 B6            46858933           1114.
##  2 DL            34970353           1689.
##  3 AA            22891534           1661.
##  4 UA            11496375           2536.
##  5 VX             8972450           2495.
##  6 9E             7426450            507.
##  7 US             3376685           1127.
##  8 MQ             2887772            401.
##  9 HA             1704186           4983 
## 10 EV              322193            229.
print(lga_df)
## # A tibble: 13 × 3
##    carrier suma_distancia media_distancia
##    <chr>            <dbl>           <dbl>
##  1 DL            20861920            904.
##  2 AA            16100472           1041.
##  3 MQ            10509739            621.
##  4 UA             9258277           1151.
##  5 B6             6181593           1030.
##  6 WN             5517587            906.
##  7 EV             4316573            489.
##  8 US             3779472            288.
##  9 FL             2167344            665.
## 10 9E             1580071            622.
## 11 F9             1109700           1620 
## 12 YV              225395            375.
## 13 OO               11018            424.
print(ewr_df)
## # A tibble: 12 × 3
##    carrier suma_distancia media_distancia
##    <chr>            <dbl>           <dbl>
##  1 UA            68950872           1496.
##  2 EV            25860185            589.
##  3 WN             6711616           1085.
##  4 B6             5343611            815.
##  5 AA             4872578           1397.
##  6 US             4209621            956.
##  7 VX             3929877           2510.
##  8 DL             3675044            846.
##  9 AS             1715028           2402 
## 10 MQ             1636444            719 
## 11 9E              781631            616.
## 12 OO                5008            835.

Interpretación

American Airlines tiene una alta suma de distancia recorrida, lo que indica que es una aerolínea con una amplia red de rutas y un gran volumen de pasajeros. La media de la distancia recorrida por AA es superior a la media de otras aerolíneas, lo que indica que sus vuelos son generalmente más largos. Estos datos podrían ser relevantes para los inversores que buscan una aerolínea con una fuerte presencia en el mercado y un historial de rentabilidad.

Conclusión

En este trabajo pudimos utilizar las funciones más comunes del análisis explotarotio, el cual es el primer paso para cualquier trabajo de manipulación de datos, hicimos uso de distintas herramientas para analizar medias, distancias mayores y menores y así finalmente analizar los beneficios de tener a American Airlines como nuevo cliente, descubriendo su gran potencial en múltiples aeropuertos como aerolinea líder.

Situación Problema 2.

Evidencia 2 - Analítica descriptiva (Integración de datos a través de modelo entidad-relación)
Compromiso ético y ciudadano. Se te ha solicitado hacer un estudio sobre la situación actual de la aerolínea American Airlines ya que se necesita revisar sus destinos, horarios y aviones con los que cuenta para hacer propuestas de aumento o reducción de vuelos por destino y horarios, así como la cantidad de aviones.

1. Datos Generales.

1.1 Consulta y exploración del data frame planes y weather.”

view(weather)
view(planes)

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

aerolineas <- flights %>% 
  select(carrier,origin,dest)
aerolineas
## # 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

1.3. En la consulta anterior se necesita conocer el nombre de la aerolínea.”

aerolineas_nombre <- aerolineas %>%
  left_join(airlines, by = "carrier")
aerolineas_nombre
## # A tibble: 336,776 × 4
##    carrier origin dest  name                    
##    <chr>   <chr>  <chr> <chr>                   
##  1 UA      EWR    IAH   United Air Lines Inc.   
##  2 UA      LGA    IAH   United Air Lines Inc.   
##  3 AA      JFK    MIA   American Airlines Inc.  
##  4 B6      JFK    BQN   JetBlue Airways         
##  5 DL      LGA    ATL   Delta Air Lines Inc.    
##  6 UA      EWR    ORD   United Air Lines Inc.   
##  7 B6      EWR    FLL   JetBlue Airways         
##  8 EV      LGA    IAD   ExpressJet Airlines Inc.
##  9 B6      JFK    MCO   JetBlue Airways         
## 10 AA      LGA    ORD   American Airlines Inc.  
## # ℹ 336,766 more rows

1.4. Se necesita saber la cantidad de vuelos por cada destino para identificar cuáles son los destinos más buscados.”

cant_vuelos <- flights %>% 
  select(carrier, dest) %>% 
  count(dest)
cant_vuelos <- cant_vuelos %>%
  arrange(desc(n))
cant_vuelos
## # A tibble: 105 × 2
##    dest      n
##    <chr> <int>
##  1 ORD   17283
##  2 ATL   17215
##  3 LAX   16174
##  4 BOS   15508
##  5 MCO   14082
##  6 CLT   14064
##  7 SFO   13331
##  8 FLL   12055
##  9 MIA   11728
## 10 DCA    9705
## # ℹ 95 more rows

Los destinos más buscados son ORD (Aeropuerto Internacional O’Hare) con 17,283 vuelos, ATL (Atlanta) con 17,215 vuelos y LAX (Los Angeles) con 16,174 vuelos.

1.5. Agregar el nombre de la aerolínea a la tabla anterior.”

cant_vuelos1 <- flights %>%
  select(carrier, dest) %>%
  group_by(carrier, dest) %>%
  summarise(n = n()) %>%
  ungroup() %>%
  arrange(desc(n))
## `summarise()` has grouped output by 'carrier'. You can override using the
## `.groups` argument.
cant_vuelos1
## # A tibble: 314 × 3
##    carrier dest      n
##    <chr>   <chr> <int>
##  1 DL      ATL   10571
##  2 US      CLT    8632
##  3 AA      DFW    7257
##  4 AA      MIA    7234
##  5 UA      ORD    6984
##  6 UA      IAH    6924
##  7 UA      SFO    6819
##  8 B6      FLL    6563
##  9 B6      MCO    6472
## 10 AA      ORD    6059
## # ℹ 304 more rows

La aerolínea con mayor cantidad de vuelos es DL (DELTA AIRLINES): Delta Air Lines es una aerolínea comercial estadounidense cuya base está situada en Atlanta, Georgia. Es miembro fundador, junto con Aeroméxico, Air France y Korean Air, de SkyTeam, una alianza de aerolíneas globales que ofrece a los clientes un gran número de destinos alrededor del mundo, vuelos y otros servicios

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

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

clas_hora<- mutate(vuelo_porhora, clas_horario = ifelse(sched_dep_time %in% 600:1159,"Morning",
                                               ifelse(sched_dep_time %in% 1200:1859,"Afertnoon",
                                               ifelse(sched_dep_time %in% 1900:2400,"Night", "Madrugada"))))
clas_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.     Morning     
##  6 UA      ORD              558 United Air Lines Inc.    Madrugada   
##  7 B6      FLL              600 JetBlue Airways          Morning     
##  8 EV      IAD              600 ExpressJet Airlines Inc. Morning     
##  9 B6      MCO              600 JetBlue Airways          Morning     
## 10 AA      ORD              600 American Airlines Inc.   Morning     
## # ℹ 336,766 more rows

1.7.Se necesita saber la cantidad de vuelos por aerolínea y destino que hay por la Mañana, Tarde, Noche y Madrugada.”

# Agrupar por aerolínea, destino y franja horaria y contar la cantidad de vuelos
vuelos_conteo <- clas_hora %>%  
  group_by(carrier, dest, clas_horario) %>% count()

# Mostrar los resultados
vuelos_conteo
## # A tibble: 741 × 4
## # Groups:   carrier, dest, clas_horario [741]
##    carrier dest  clas_horario     n
##    <chr>   <chr> <chr>        <int>
##  1 9E      ATL   Morning         59
##  2 9E      AUS   Afertnoon        2
##  3 9E      AVL   Morning         10
##  4 9E      BGR   Night            1
##  5 9E      BNA   Afertnoon      467
##  6 9E      BNA   Morning          6
##  7 9E      BNA   Night            1
##  8 9E      BOS   Afertnoon      549
##  9 9E      BOS   Morning        271
## 10 9E      BOS   Night           94
## # ℹ 731 more rows

1.8.Se necesita saber a qué destinos vuela la aerolínea American Airlines Inc.-AA durante la madrugada.”

destinos_american <- clas_hora %>% 
  select(carrier,name, dest,clas_horario) %>% 
  filter(carrier == "AA" & clas_horario == "Madrugada") %>% 
  group_by(carrier,name, dest,clas_horario)
destinos_american
## # 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

American Airlines realiza vuelos de madrugada a únicamente el destino de Miami. #### 1.9.Qué aviones utiliza la aerolínea AA? aerolínea, tipo, motor y número de asientos y ¿Cuántos vuelos se han realizado con cada uno? (elimina los NA’s)“

avion_american <- flights %>%
  left_join(planes, by = "tailnum") %>%
  select(carrier, type, engine, seats) %>%
  filter(carrier == "AA", !is.na(type)) %>%
  group_by(carrier,type,engine,seats) %>% 
  count()
avion_american
## # A tibble: 22 × 5
## # Groups:   carrier, type, engine, seats [22]
##    carrier type                    engine        seats     n
##    <chr>   <chr>                   <chr>         <int> <int>
##  1 AA      Fixed wing multi engine Reciprocating     6    22
##  2 AA      Fixed wing multi engine Reciprocating     8    92
##  3 AA      Fixed wing multi engine Reciprocating   102    22
##  4 AA      Fixed wing multi engine Turbo-fan         8    38
##  5 AA      Fixed wing multi engine Turbo-fan        11    19
##  6 AA      Fixed wing multi engine Turbo-fan        22    13
##  7 AA      Fixed wing multi engine Turbo-fan       172  3857
##  8 AA      Fixed wing multi engine Turbo-fan       178   501
##  9 AA      Fixed wing multi engine Turbo-fan       255  4257
## 10 AA      Fixed wing multi engine Turbo-fan       330   450
## # ℹ 12 more rows

Reporte

Hallazgos:
-Retrasos:
Aerolíneas con mayor retraso: Varían según el destino (F9, EV, OO)
Destinos con mayor retraso: LGA, EWR, JFK (debido a las condiciones climáticas adversas o congestión aérea)
-Modelos de aviones:
Más utilizados:
Fixed wing multi engine: Los aviones de ala fija multimotor son una opción versátil y confiable para una variedad de aplicaciones. Si bien son más costosos que los aviones monomotores, ofrecen mayor seguridad, rendimiento y alcance.

Visualización de datos

En los avances anteriores se han realizado diferentes análisis y ahora nos solicitan hacer visualizaciones de la aerolínea American Airlines para los ejecutivos con las siguientes características. Dentro de las aerolíneas el retraso tanto en la hora de partida como en la hora de llegada a su destino van generando indicadores negativos. ### 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.

# Filtrar los vuelos de American Airlines (AA)
american_flights <- flights %>% filter(carrier == "AA")

# Mostrar la relación entre el retraso en la partida y el retraso en la llegada
cor(american_flights$dep_delay, american_flights$arr_delay, use = "complete.obs")
## [1] 0.8917433
# Filtrar los vuelos de American Airlines (AA)
american_flights <- flights %>% filter(carrier == "AA")

# Crear un gráfico de dispersión
ggplot(american_flights, aes(x = dep_delay, y = arr_delay)) +
  geom_point(alpha = 0.5, color = "blue") +
  labs(main = "Relación entre Retraso en Salida y Llegada para American Airlines", x = "Retraso en la Partida (minutos)", y = "Retraso en la Llegada (minutos)") +
  theme_minimal()
## Warning: Removed 782 rows containing missing values or values outside the scale range
## (`geom_point()`).

El resultado de la correlación entre el retraso en la partida y el retraso en la llegada para los vuelos de American Airlines (AA) es aproximadamente 0.8917. Este valor cercano a 1 indica una fuerte correlación positiva entre ambas variables. En otras palabras, hay una tendencia a que los vuelos que experimentan retraso en la salida también tengan retraso en la llegada.

Temperatura y sus variaciones

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.

library(ggplot2)

# Filtrar los datos para los primeros 15 días de enero en el aeropuerto Newark
weather_january <- weather %>%
  filter(month == 1 & day <= 15 & origin == "EWR")

# Gráfico de línea para la tendencia de temperatura
ggplot(weather_january, aes(x = day, y = temp)) +
  geom_line(color = "black", size = 1) +
  labs(main="Tendencia de la Temperatura en los Primeros 15 Días de Enero (Aeropuerto Newark)",
       x=weather_january$day,
       y=weather_january$temp)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

#### Visualiza la temperatura más frecuente en los primeros 15 días del mes de Enero, utilizar un histrograma.

# Filtrar los datos para los primeros 15 días de enero en el aeropuerto Newark
weather_january <- weather %>%
  filter(month == 1 & day <= 15 & origin == "EWR")

# Gráfico de línea para la tendencia de temperatura
ggplot(weather_january, aes(x = temp)) +
  geom_histogram(binwidth = 1, fill = "skyblue", color = "black") +
  labs(main="Tendencia de la Temperatura en los Primeros 15 Días de Enero (Aeropuerto Newark)",
       x=weather_january$day,
       y=weather_january$temp)

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

weather %>%
  ggplot(aes(x = temp)) +
  geom_histogram(binwidth = 2, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Temperaturas por Mes",
       x = "Temperatura (Fahrenheit)",
       y = "Frecuencia") +
  facet_wrap(~month)
## Warning: Removed 1 row containing non-finite outside the scale range
## (`stat_bin()`).

#### 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 %>%
  group_by(carrier) %>%
  summarise(num_flights = n()) %>%
  arrange(desc(num_flights)) %>%
  slice(1:10) %>%
  ggplot(aes(x = reorder(carrier, -num_flights), y = num_flights)) +
  geom_bar(stat = "identity", fill = "skyblue") +
  labs(title = "Numero de vuelos por aerolinea",
       x = "Aerolinea",
       y = "Numero de Vuelos") +
  theme_minimal()

Según el gráfico “Número de vuelos por aerolínea en 2013”, se observa que las aerolíneas con mayor cantidad de vuelos desde Nueva York durante ese año fueron “United Airlines” y “JetBlue Airways”. Estas dos aerolíneas lideran significativamente en términos de la cantidad de vuelos, superando a otras compañías. El gráfico proporciona una rápida visualización de la distribución de vuelos entre las aerolíneas principales, siendo útil para comprender la participación relativa de cada una en el tráfico aéreo desde Nueva York en 2013. #### Visualiza el punto anterior en una gráfica de pie.

Sys.setlocale("LC_CTYPE", "en_US.UTF-8")
## [1] "en_US.UTF-8"
# Filtramos los datos para obtener la cantidad de vuelos por aerolínea
top_airlines <- flights %>%
  group_by(carrier) %>%
  summarise(num_flights = n()) %>%
  arrange(desc(num_flights)) %>%
  slice(1:10)  # Seleccionamos las 10 aerolíneas con más vuelos
ggplot(top_airlines, aes(x = "", y = num_flights, fill = factor(carrier))) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Distribución del Número de Vuelos por Aerolínea desde Nueva York en 2013",
       fill = "Aerolínea",
       x = NULL,
       y = NULL) +
  theme_minimal() +
  theme(legend.position = "bottom")

#### Relaciona el data frame fligths con el data frame airports a través del campo destino.

# Realiza la unión de los data frames flights y airports por el campo destino
union_fya <- left_join(flights, airports, by = c("dest" = "faa"))

Crea un nuevo data frame con el punto anterior únicamente con los 5 carriers con más vuelos por destino

# Crea un nuevo data frame con los 5 carriers con más vuelos
top_carriers <- union_fya %>%
  group_by(carrier) %>%
  summarise(num_flights = n()) %>%
  arrange(desc(num_flights)) %>%
  slice(1:5) %>%
  ungroup()

# Muestra el nuevo data frame
print(top_carriers)
## # A tibble: 5 × 2
##   carrier num_flights
##   <chr>         <int>
## 1 UA            58665
## 2 B6            54635
## 3 EV            54173
## 4 DL            48110
## 5 AA            32729
flights_top_carriers <- union_fya %>%
  filter(carrier %in% top_carriers$carrier)

####Realiza una visualización del punto anterior de las siguientes tres formas.

# DataFrame con los resultados
top_carriers <- union_fya %>%
  group_by(carrier, origin) %>%
  summarise(num_flights = n()) %>%
  arrange(desc(num_flights)) %>%
  slice(1:5) %>%
  ungroup()
## `summarise()` has grouped output by 'carrier'. You can override using the
## `.groups` argument.
ggplot(top_carriers, aes(x = carrier, y = num_flights, fill = as.factor(carrier))) +
  geom_bar(stat = "identity", position = "stack") +
  labs(x = "Carrier", y = "Number of Flights", title = "Top 5 Carriers con más vuelos por aeropuerto") +
  facet_wrap(~origin, scales = "free_x") +
  theme_minimal()

ggplot(flights_top_carriers, aes(x = carrier, fill = carrier)) +
  geom_bar() +
  labs(title = "Cantidad de vuelos por aerolínea", x = "Aerolínea", y = "Cantidad de vuelos") +
  theme_minimal() +
  geom_text(stat = "count", aes(label = ..count.., group = carrier), vjust = -0.5)
## Warning: The dot-dot notation (`..count..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(count)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

ggplot(flights_top_carriers, aes(x = dest, fill = carrier)) +
  geom_bar() +
  labs(title = "Cantidad de vuelos por destino", x = "Destino", y = "Cantidad de vuelos") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

Compromiso Ético y Ciudadano

Valor de la integridad:

La integridad es un valor fundamental que implica actuar con honestidad y coherencia en todas las acciones. En el contexto del análisis de datos, la integridad se traduce en manejar la información de manera precisa, respetar la privacidad de los datos y presentar resultados de manera fiel y objetiva. Este valor implica la responsabilidad de tomar decisiones éticas y transparentes en todas las fases del análisis de datos, desde la recopilación hasta la interpretación y comunicación de los resultados.

Reflexión personal:

En nuestro debe como analistas de datos nos comprometemos a ser justos con los datos de una empresa. Esto implica garantizar la confidencialidad de la información sensible, utilizar métodos y técnicas éticas en el análisis, y presentar los resultados de manera transparente y comprensible. Además, nos comprometemos a cuestionar cualquier práctica que pueda comprometer la integridad de los datos o el análisis, abogando siempre por la toma de decisiones éticas y responsables.

Bibliografía:

Johnson, R. (2018). “Ethics in Data Science: An Introduction.” O’Reilly Media.

Davenport, T., & Harris, J. (2017). “Competing on Analytics: Updated, with a New Introduction.” Harvard Business Review Press.

Diakopoulos, N. (2016). “Data Ethics and the Role of Data Science in the Fourth Industrial Revolution.” Journal of Data Science, 14(4), 553-562.

Conclusiones:

Algunos puntos destacados y conclusiones importantes incluyen:

Identificación de las principales aerolíneas y destinos:

El código permite identificar las principales aerolíneas y destinos basándose en la cantidad de vuelos. Esto proporciona información clave sobre las asociaciones más frecuentes y puede ser esencial para la toma de decisiones estratégicas. Visualización efectiva:

La implementación de gráficos de barras con colores distintivos facilita la interpretación de la información. La visualización efectiva es crucial para comunicar hallazgos de manera comprensible a los stakeholders de la empresa. Filtrado de datos relevante:

La capacidad de filtrar y trabajar solo con los datos más relevantes, como las cinco principales aerolíneas por destino, ayuda a concentrarse en la información más significativa, reduciendo el ruido y mejorando la eficiencia del análisis.

El código puede ser una herramienta valiosa para la empresa en términos de toma de decisiones estratégicas. Proporciona insights sobre las relaciones clave entre aerolíneas y destinos, lo que puede influir en la planificación de rutas, asociaciones estratégicas y estrategias de marketing. Además, la atención a la ética y la integridad en el manejo de datos refuerza la confianza del cliente y la reputación de la empresa.

LS0tDQp0aXRsZTogIkV2aWRlbmNpYSAyIC0gTWFuaXB1bGFjacOzbiBkZSBEYXRvcyAtIEVxdWlwbyA1Ig0KYXV0aG9yOiAiRXF1aXBvIDU6DQpGYWJpYW5hIE1lZGluYWNlbGxpIC0gQTAwODM1ODk2LiANCg0KDQpTYWx2YWRvciBOYXJ2w6FleiBBbmRyYWRlIC0gQTAwNTcxODQ4DQoNCg0KUGF1bGV0dGUgTXR6IC0gQTAxNzQ3NTM1LiANCg0KDQpKZXN1cyBBbGJlcnRvIE1vcmVubyBNYXJyb3F1aW4gLSBBMDExNzgwMzIiIA0KZGF0ZTogIjIwMjQtMDMtMTIiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiAiY29zbW8iDQogICAgaGlnaGxpZ2h0OiAiZXNwcmVzc28iICAgIA0KLS0tDQohW10oQzpcXFVzZXJzXFxIUFxcRGVza3RvcFxcdmlzaW9uIGJvYXJkXFxiYmY1MTQ0YjFlNDMyMmI1YTQ3MjczYmExOGE1ZjVlZi5qcGcpDQoNCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+Q29udGV4dG88L3NwYW4+DQoNCkVsIHBhcXVldGUgKipueWNmbGlnaHRzMTMqKiBjb250aW5lIGluZm9ybWFjacOzbiBzb2JyZSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSBwYXJ0aWVyb24gZGVzZGUgTnVldmEgWW9yayAoRVdSLCBKRksgWSBMR0EpIGEgZGVzdGlub3MgZW4gbG9zIEVzdGFkb3MgVW5pZG9zIGVuIDIwMTMuIEZ1ZXJvbiAzMzY3NzYgdnVlbG9zIGVuIHRvdGFsLiBQYXJhIGF5dWRhciBhIGNvbXByZW5kZXIgbGFzIGNhdXNhcyBkZSBsb3MgcmV0cmFzb3MsIHRhbWJpw6luIGluY2x1eWUgb3Ryb3MgY29uanVudG9zIGRlIGRhdG9zIMO6dGlsZXMuICANCg0KRXN0ZSBwYXF1ZXRlIGluY2x1eWUgbGFzIHNpZ3VpZW50ZXMgdGFibGFzOg0KDQorIGZsaWdodHMgPSB0b2RvcyBsb3MgdnVlbG9zIHF1ZSBzYWxpZXJvbiBkZSBOdWV2YSBZb3JrIGVuIDIwMTMgICANCisgd2VhdGhlciA9IGRhdG9zIG1ldGVvcm9sw7NnaWNvcyBwb3IgaG9yYSBkZSBjYWRhIGFlcm9wdWVydG8gICAgDQorIHBsYW5lcyA9IGluZm9ybWFjaW9uIGRlIGNvbnN0cnVjY2nDs24gZGUgY2FkYSBhdmnDs24gIA0KKyBhaXJwb3J0cyA9IG5vbWJyZXMgeSB1YmljYWNpb25lcyBkZSBhZXJvcHVlcnRvcyAgDQorIGFpcmxpbmVzID0gcmVsYWNpb24gZW50cmUgbm9tYnJlcyB5IGPDs2RpZ29zIGRlIGxhcyBhZXJvbGluZWEgIA0KDQpGdWVudGU6ICANCltPcmlnZW4gZGUgbG9zIERhdG9zXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbnljZmxpZ2h0czEzL255Y2ZsaWdodHMxMy5wZGYpICANCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5TaXR1YWNpw7NuIFByb2JsZW1hIDEuIEFjdGl2aWRhZCAxLiA8L3NwYW4+DQpUZW1hOiBiYXNlIGRlIGRhdG9zLCBzdXMgY2FtcG9zLCByZWdpc3Ryb3MsdGlwb3MgZGUgZGF0b3MgeSBsb3MgcmVzdWx0YWRvcyBkZXNjcmlwdGl2b3MgZGUgbGEgYmFzZSBkZSBkYXRvcy4NCg0KU2l0dWFjacOzbiBwcm9ibGVtYTogDQrCv0PDs21vIG1lam9yYXIgbGEgcG9zaWNpw7NuIGNvbXBldGl0aXZhIGRlIHVuYSBkZSBsYXMgYWVyb2zDrW5lYXMgbMOtZGVyZXMgZW4gbG9zIGFlcm9wdWVydG9zIGRlIE51ZXZhIFlvcms/DQoNCkluc3RydWNjaW9uZXM6DQoNCuKAoglQYXF1ZXRlcyAgcmVxdWVyaWRvcyBwYXJhIGxhIHByw6FjdGljYTogIHRpZHl2ZXJzZSwgbnlmbGlnaHRzMTMgDQogIEVsIHBhcXVldGUgdGlkeXZlcnNlIGluY2x1eWUgdmFyaWFzIGxpYnJlcsOtYXMgZW50cmUgZWxsYXMgZ2dwbG90MiwgZHBseXIsIHRpZHl2ZXJzZQ0KICBFbCBwYXF1ZXRlIG55ZmxpZ2h0czEzIGluY2x1eWUgdmFyaWFzIGJhc2VzIGRlIGRhdG9zIGVudHJlIGVsbGFzIGZsaWdodHMgDQrigKIgTGlicmVyw61hcyBxdWUgZGViZW4gZXN0YXIgaW5zdGFsYWRhczogZHBseXINCg0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KI0xsYW1hciBhIGxhcyBsaWJyZXLDrWFzIHJlcXVlcmlkYXMNCmxpYnJhcnkoZHBseXIpDQojTGxhbWFyIGEgbGEgbGlicmVyw61hIHF1ZSB0aWVuZSBlbCBhcmNoaXZvIHJlcXVlcmlkbyBwYXJhIGxhIHByw6FjdGljYS4NCmxpYnJhcnkobnljZmxpZ2h0czEzKQ0KI0VsIGFyY2hpdm8gdGllbmUgNCBiYXNlcyBkZSBkYXRvcywgc29sbyBsbGFtYXIgYSBsb3MgZGF0b3MgZmxpZ2h0cy4NCmBgYA0KDQojIyMxLiBDYXJnYXIgZW4gbWVtb3JpYSBsYSB0YWJsYSBmbGlnaHRzIHkgbW9zdHJhciBzdSBjb250ZW5pZG8NCmBgYHtyfQ0KZGF0YShmbGlnaHRzKQ0KZmxpZ2h0cw0KYGBgDQoNCiMjIzIuCUNhcmdhciBlbiBtZW1vcmlhIGxhIHRhYmxhIGZsaWdodHMgeSBtb3N0cmFyIHN1IGNvbnRlbmlkby4gQ29uc3VsdGEgbGEgZXN0cnVjdHVyYSBkZSBmbGlnaHRzLCDCv0N1w6FsZXMgc29uIGxvcyBjYW1wb3MgeSBzdXMgdGlwb3MgZGUgZGF0b3M/ICBJZGVudGlmaWNhIGxvcyBkaWZlcmVudGVzIHRpcG9zIGRlIGRhdG9zIHkgZXhwbGljYSBlbiBxdcOpIGNvbnNpc3RlIGNhZGEgdW5vIGRlIGVsbG9zICB5IGN1w6FsIGVzIGxhIGRpZmVyZW5jaWEgZW50cmUgdW5vIHkgb3RybywgaW5jbHV5ZW5kbyBsb3Mgc2lndWllbnRlcyB0aXBvcyBkZSBkYXRvczogaW50LCBkYmwsIGNociwgZHR0bQ0KDQpgYGB7cn0NCnN0cihmbGlnaHRzKQ0KYGBgDQoNCiMjIzMuIMK/Q3XDoWwgZXMgbGEgY2xhc2UgZGUgZmxpZ2h0cz8geSDCv1F1w6kgc2lnbmlmaWNhPw0KYGBge3J9DQpjbGFzcyhmbGlnaHRzKQ0KYGBgDQojIyM0LiDCv0N1w6FudGFzIGNvbHVtbmFzIHRpZW5lIGZsaWdodHM/DQpgYGB7cn0NCm5jb2woZmxpZ2h0cykNCmBgYA0KIyMjNS4gwr9DdcOhbnRvcyByZW5nbG9uZXMgdGllbmUgZmxpZ2h0cz8NCg0KYGBge3J9DQpucm93KGZsaWdodHMpDQpgYGANCiMjIzYuIMK/Q3XDoWwgZXMgbGEgZGltZW5zacOzbiBkZSBmbGlnaHRzPw0KDQpgYGB7cn0NCmRpbShmbGlnaHRzKQ0KYGBgDQojIyM3LiBDb25zdWx0YSBsYSB0YWJsYSBmbGlnaHRzDQpgYGB7cn0NClZpZXcoZmxpZ2h0cykNCg0KYGBgDQojIyM4LiBHZW5lcmEgdW4gb3V0cHV0IGRlIGxhIHRhYmxhIGZsaWdodHMuIFV0aWxpemEgbGFzIGZ1bmNpb25lcyBoZWFkIHkgdGFpbCwgwr9DdcOhbnRvcyByZW5nbG9uZXMgbXVlc3RyYW4gcG9yIGRlZmVjdG8gY2FkYSBmdW5jacOzbj8NCmBgYHtyfQ0KaGVhZChmbGlnaHRzKQ0KdGFpbChmbGlnaHRzKQ0KYGBgDQoNCiMjIzkuIEFob3JhIG11ZXN0cmEgbG9zIHByaW1lcm9zIDUwIHJlZ2lzdHJvcyB5IGxvcyDDumx0aW1vcyAyMCwgwr9Dw7NtbyBsbyBoYXLDrWFzPyANCg0KYGBge3J9DQpoZWFkKGZsaWdodHMsNTApDQp0YWlsKGZsaWdodHMsMjApDQpgYGANCg0KIyMjMTAuIEVuY3VlbnRyYSBsb3MgcmVzdWx0YWRvcyBkZXNjcmlwdGl2b3MgZGUgbGFzIHZhcmlhYmxlcyBlbiBsYSBiYXNlIGRlIGRhdG9zLiBFamVtcGxvOiBwcm9tZWRpbywgbW9kYSwgbcOtbmltbywgbcOheGltbywgZXRjLkZ1bmNpw7NuOiBzdW1tYXJ5LiANCg0KYGBge3J9DQpzdW1tYXJ5KGZsaWdodHMpDQpgYGANCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+U2l0dWFjacOzbiBQcm9ibGVtYSAxLiBBY3RpdmlkYWQgMi4gPC9zcGFuPg0KDQpGdW5jaW9uZXMgYsOhc2ljYXMgcGFyYSBsYSBtYW5pcHVsYWNpw7NuIGRlIGRhdG9zLg0KVGVtYXM6ICBEcGx5ciAoZmlsdGVyLCBhcnJhbmdlLCBzZWxlY3QsIHJlbmFtZSwgIG11dGF0ZSwgc3VtbWFyaXplLCBncm91cF9ieSkgaWYvZWxzZSwgc3Vic2V0LCBmb3IgKGxvb3BzKQ0KU2l0dWFjacOzbiBwcm9ibGVtYTogwr9Dw7NtbyBtZWpvcmFyIGxhIHBvc2ljacOzbiBjb21wZXRpdGl2YSBkZSB1bmEgZGUgbGFzIGFlcm9sw61uZWFzIGzDrWRlcmVzIGVuIGxvcyBhZXJvcHVlcnRvcyBkZSBOdWV2YSBZb3JrPw0KSW5zdHJ1Y2Npb25lczoNCkxpYnJlcsOtYXMgcmVxdWVyaWRhczogDQrigKIJUGFxdWV0ZXMgIHJlcXVlcmlkb3MgcGFyYSBsYSBwcsOhY3RpY2E6ICB0aWR5dmVyc2UsIG55ZmxpZ2h0czEzIA0KICBFbCBwYXF1ZXRlIHRpZHl2ZXJzZSBpbmNsdXllIHZhcmlhcyBsaWJyZXLDrWFzIGVudHJlIGVsbGFzIGdncGxvdDIsIGRwbHlyLCB0aWR5dmVyc2UNCiAgRWwgcGFxdWV0ZSBueWZsaWdodHMxMyBpbmNsdXllIHZhcmlhcyBiYXNlcyBkZSBkYXRvcyBlbnRyZSBlbGxhcyBmbGlnaHRzIA0K4oCiIExpYnJlcsOtYXMgcXVlIGRlYmVuIGVzdGFyIGluc3RhbGFkYXM6ICBnZ3Bsb3QyLCAgZHBseXIsIHRpZHl2ZXJzZQ0KDQpgYGB7cn0NCmxpYnJhcnkobnljZmxpZ2h0czEzKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KZGF0YSgiZmxpZ2h0cyIpDQpgYGANCg0KIyMjMS4gTW9zdHJhciBsYSBiYXNlIGRlIGRhdG9zIGZsaWdodHMgcGFyYSBxdWUgY29ub3pjYXMgc3UgY29udGVuaWRvDQoNCmBgYHtyfQ0KVmlldyhmbGlnaHRzKQ0KYGBgDQoNCg0KIyMjMi4JRW5jdWVudHJhIGxvcyBkYXRvcyBkZXNjcmlwdGl2b3MgZGVsIGRhdGEgZnJhbWUgZmxpZ2h0cy4gSWRlbnRpZmljYSBsYSBtZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzIGVuIG1pbGxhcy4NCmBgYHtyfQ0Kc3VtbWFyeShmbGlnaHRzKQ0KYGBgDQoNCg0KIyMjMy4JRGVmaW5lIHVuIGNyaXRlcmlvIHBhcmEgZW5jb250cmFyIGxhcyBhZXJvbMOtbmVhcyBxdWUgaGFuIHJlY29ycmlkbyBtw6FzIGRpc3RhbmNpYSAoZW4gbWlsbGFzKSB5IGNyZWEgdW4gbnVldm8gZGF0YSBmcmFtZSBxdWUgZmlsdHJlIHNvbGFtZW50ZSBhIGxhcyBhZW9ybMOtbmVhcyBxdWUgaGFuIHJlY29ycmlkYW8gdW5hIGRpc3RhbmNpYSBzdXBlcmlvciBhIGxhIG1lZGlhLCBzZSBkZXNlYSB2ZXIgbG9zIGNhbXBvcyBjYXJyaWVyLCBkaXN0YW5jZSwgb3JpZ2luLCBkZXN0IGVuIGZvcm1hIGRlc2NlbmRlbnRlIHBvciBkaXN0YW5jZS4NCkVqZW1wbG86ICBhZXJvbMOtbmVhcyBjb24gbWlsbGFzIHJlY29ycmlkYXMgc3VwZXJpb3JlcyBhIGxhIG1lZGlhLCBvcmRlbmFkYXMgZW4gZm9ybWEgZGVzY2VuZGVudGUuDQoNCg0KYGBge3J9DQojc2VsZWNjaW9uYSBsYXMgdmFyaWFibGVzIGNhcnJpZXIsIGRpc3RhbmNlLCBvcmlnaW4sIGRlc3QgZGUgbGEgdGFibGENCnJlczAxIDwtIHNlbGVjdChmbGlnaHRzLCBjYXJyaWVyLCBkaXN0YW5jZSwgb3JpZ2luLCBkZXN0KQ0KDQojc2UgZmlsdHJhIGxhcyBhZXJvbMOtbmVhcyBjb24gbWlsbGFzIHJlY29ycmlkYXMgc3VwZXJpb3JlcyBhIGxhIG1lZGlhIC0gMTA0MCANCnJlczAyIDwtIGZpbHRlcihyZXMwMSwgZGlzdGFuY2UgPjEwNDApIA0KDQojb3JkZW5hIGVuIGZvcm1hIGRlc2NlbmRlbnRlIHBvciBkaXN0YW5jaWEgcmVjb3JyaWRhIA0KcmVzMDMgPC0gYXJyYW5nZShyZXMwMiwgZGVzYyhkaXN0YW5jZSkpDQpgYGANCg0KIyMjNC4gRW5jdWVudHJhIGxhIHN1bWEgeSBsYSBtZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzIHBvciBjYXJyaWVyLCBlbGltaW5hIGxvcyBOQeKAmVMgIGUgaW50ZXJwcmV0YSBxdWUgc2lnbmlmaWNhIGxhIHN1bWEgeSBsYSBtZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzLg0KDQpgYGB7cn0NCiNBZ3J1cGFyIGxvcyBkYXRvcyBwb3IgY2FycmllcixvcmlnaW4sIGRlc3QgeSBvYnRlbmVyIGxhIHN1bWEgYWN1bXVsYWRhIHkgbGEgbWVkaWEgZGUgbGFzIGRpc3RhbmNpYXMgcmVjb3JyaWRhcyBwb3IgY2FycmllciBlbGltaW5hbmRvIGxvcyBOQSdzDQpyZXMwNCA8LSByZXMwMyAlPiUgDQogIGdyb3VwX2J5KGNhcnJpZXIsb3JpZ2luLGRlc3QpDQpzdW1kaXN0YW5jZSA8LSBzdW0ocmVzMDMkZGlzdGFuY2UsIG49IFRSVUUpDQpgYGANCiMjIzUuIE9yZGVuYSBlbiBmb3JtYSBkZXNjZW5kZW50ZSBwb3IgZGlzdGFuY2lhIHJlY29ycmlkYQ0KYGBge3J9DQpyZXMwNSA8LSBhcnJhbmdlKHJlczA0LGNhcnJpZXIsc3VtZGlzdGFuY2UpDQpgYGANCg0KDQojIyM2Lk9ic2VydmEgdHVzIHJlc3VsdGFkb3MgZGUgbGEgw7psdGltYSB0YWJsYSB5IGFncmVnYSB0dXMgaW50ZXJwcmV0YWNpb25lcyANCg0KIyMjNy5JZGVudGlmaWNhIHNpIGxhcyBhZXJvbMOtbmVhcyBsw61kZXJlcyBzb24gbGFzIG1pc21hcyBlbiBsb3MgdHJlcyBhZXJvcHVlcnRvcyBjdXlvIG9yaWdlbiBlcyBOdWV2YSBZb3JrICggSm9obiBGLiBLZW5uZWR5IChKRkspLCBMYUd1YXJkaWEgKExHQSkgYW5kIE5ld2FyayBMaWJlcnR5ICAoRVdSKSApLiAgDQpHZW5lcmEgdW4gZGF0YSBmcmFtZSAgcGFyYSBjYWRhIGFlcm9wdWVydG8uIA0KRnVuY2lvbmVzOiBmaWx0ZXIoKSwgYXJyYW5nZSgpIA0KDQpgYGB7cn0NCkpGSyA9IHJlczA1ICU+JSAgDQogIGZpbHRlcihvcmlnaW4gPT0gIkpGSyIpICAlPiUNCiAgYXJyYW5nZShjYXJyaWVyLCBkZXNjKHN1bWRpc3RhbmNlKSkNCkxHQSA9IHJlczA1ICU+JSAgDQogIGZpbHRlcihvcmlnaW4gPT0gIkxHQSIpICAlPiUNCiAgYXJyYW5nZShjYXJyaWVyLCBkZXNjKHN1bWRpc3RhbmNlKSkNCkVXUiA9IHJlczA1ICU+JSAgDQogIGZpbHRlcihvcmlnaW4gPT0gIkVXUiIpICAlPiUNCiAgYXJyYW5nZShjYXJyaWVyLCBkZXNjKHN1bWRpc3RhbmNlKSkNCmBgYA0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5TaXR1YWNpw7NuIFByb2JsZW1hIDEuIEFjdGl2aWRhZCAzLiA8L3NwYW4+DQoNCmBgYHtyfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMjIyBSIE1hcmtkb3duDQoNCiMjIzEuCUNvbnN1bHRhIGxhcyB0YWJsYXMgcGxhbmVzIHkgd2VhdGhlciBwYXJhIHF1ZSBjb25vemNhcyBzdSBjb250ZW5pZG8uDQpgYGB7cn0NCnZpZXcocGxhbmVzKQ0Kdmlldyh3ZWF0aGVyKQ0KYGBgDQoNCiMjIzIuCVNlIG5lY2VzaXRhIHNhYmVyIGRlIGNhZGEgdnVlbG8sIGxhIGFlcm9sw61uZWEsIGVsIGFlcm9wdWVydG8gZGUgb3JpZ2VuIHkgZWwgYWVyb3B1ZXJ0byBkZXN0aW5vLg0KYGBge3J9DQphZXJvbGluZWFzIDwtIGZsaWdodHMgJT4lIA0KICBzZWxlY3QoY2FycmllcixvcmlnaW4sZGVzdCkNCmBgYA0KDQojIyMzLglFbiBsYSBjb25zdWx0YSBhbnRlcmlvciBzZSBuZWNlc2l0YSBjb25vY2VyIGVsIG5vbWJyZSBkZSBsYSBhZXJvbMOtbmVhLg0KYGBge3J9DQphZXJvbGluZWFzX25vbWJyZSA8LSBhZXJvbGluZWFzICU+JQ0KICBsZWZ0X2pvaW4oYWlybGluZXMsIGJ5ID0gImNhcnJpZXIiKQ0KYGBgDQoNCiMjIzQgU2UgbmVjZXNpdGEgc2FiZXIgbGEgY2FudGlkYWQgZGUgdnVlbG9zIHBvciBjYWRhIGRlc3Rpbm8gcGFyYSBpZGVudGlmaWNhciBjdcOhbGVzIHNvbiBsb3MgZGVzdGlub3MgbcOhcyBidXNjYWRvcy4NCmBgYHtyfQ0KY2FudF92dWVsb3MgPC0gZmxpZ2h0cyAlPiUgDQogIHNlbGVjdChjYXJyaWVyLCBkZXN0KSAlPiUgDQogIGNvdW50KGNhcnJpZXIpDQogIA0KYGBgDQoNCiMjIzUgQWdyZWdhciBlbCBub21icmUgZGUgbGEgYWVyb2zDrW5lYSBhIGxhIHRhYmxhIGFudGVyaW9yLg0KYGBge3J9DQpjYW50X3Z1ZWxvc19ub21icmUgPC0gY2FudF92dWVsb3MgJT4lDQogIGxlZnRfam9pbihhaXJsaW5lcywgYnkgPSAiY2FycmllciIpDQpgYGANCg0KIyMjNi4gU2UgbmVjZXNpdGEgY29ub2NlciBsYXMgYWVyb2zDrW5lYXMgKGNsYXZlIHkgbm9tYnJlKSB5IGRlc3Rpbm9zIHF1ZSB2dWVsYW4gcG9yIGxhIE1hw7FhbmE6IGRlIDYgYSAxMiwgVGFyZGU6IGRlIDEyIGEgMTkgLCBOb2NoZTogZGUgMTkgYSAyNCB5IE1hZHJ1Z2FkYSBkZSAyNCBhIDYuDQojIEFncmVnYSB1biBudWV2byBjYW1wbyBhIGxhIHRhYmxhIGNvbiBlbCBub21icmUgZGUgY2xhc19ob3JhcmlvIHkgYWdyZWdhLCBtYcOxYW5hLCB0YXJkZSwgbm9jaGUgeSBtYWRydWdhZGEgc2Vnw7puIHNlYSBlbCBjYXNvLg0KYGBge3J9DQpjYXJyaWVyX2hvcmFyaW8gPC0gZmxpZ2h0cyAlPiUNCnNlbGVjdChjYXJyaWVyLCBkZXN0LCBzY2hlZF9kZXBfdGltZSkgJT4lDQogIGxlZnRfam9pbihhaXJsaW5lcywgYnkgPSAiY2FycmllciIpDQoNCmNsYXN4aG9yYTwtIG11dGF0ZShjYXJyaWVyX2hvcmFyaW8sIGNsYXNfaG9yYXJpbyA9IGlmZWxzZShzY2hlZF9kZXBfdGltZSAlaW4lIDYwMDoxMTU5LCJNYcOxYW5hIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHNjaGVkX2RlcF90aW1lICVpbiUgMTIwMDoxODU5LCJUYXJkZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShzY2hlZF9kZXBfdGltZSAlaW4lIDE5MDA6MjQwMCwiTm9jaGUiLCAiTWFkcnVnYWRhIikpKSkNCmBgYA0KDQojIyM3LlNlIG5lY2VzaXRhIHNhYmVyIGxhIGNhbnRpZGFkIGRlIHZ1ZWxvcyBwb3IgYWVyb2zDrW5lYSB5IGRlc3Rpbm8gcXVlIGhheSBwb3IgbGEgTWHDsWFuYSwgVGFyZGUsIE5vY2hlIHkgTWFkcnVnYWRhLg0KYGBge3J9DQpjYW50X2NsYXN4aG9yYSA8LSBjbGFzeGhvcmEgJT4lIA0KICAgICAgICAgICAgIGdyb3VwX2J5KGNhcnJpZXIsIGRlc3QsY2xhc19ob3JhcmlvKSAlPiUgY291bnQoKQ0KDQpgYGAgICAgICAgICAgICAgICAgICAgICAgIA0KIA0KIyMjOCBTZSBuZWNlc2l0YSBzYWJlciBhIHF1w6kgZGVzdGlub3MgdnVlbGEgbGEgYWVyb2zDrW5lYSBBbWVyaWNhbiBBaXJsaW5lcyBJbmMuLUFBICBkdXJhbnRlIGxhIG1hZHJ1Z2FkYS4gIA0KYGBge3J9DQpkZXN0aW5vc19hYSA8LSBjbGFzeGhvcmEgJT4lIA0KICBzZWxlY3QoY2FycmllcixuYW1lLCBkZXN0LGNsYXNfaG9yYXJpbykgJT4lIA0KICBmaWx0ZXIoY2FycmllciA9PSAiQUEiICYgY2xhc19ob3JhcmlvID09ICJNYWRydWdhZGEiKSAlPiUgDQogIGdyb3VwX2J5KGNhcnJpZXIsbmFtZSwgZGVzdCxjbGFzX2hvcmFyaW8pDQpgYGANCg0KIyMjOS4gwr9RdcOpIGF2aW9uZXMgdXRpbGl6YSBsYSBhZXJvbMOtbmVhIEFBPyBhZXJvbMOtbmVhLCB0aXBvLCBtb3RvciB5IG7Dum1lcm8gZGUgYXNpZW50b3MgeSDCv0N1w6FudG9zIHZ1ZWxvcyBzZSBoYW4gcmVhbGl6YWRvIGNvbiBjYWRhIHVubz8gZWxpbWluYSBsb3MgTkEncw0KYGBge3J9DQphdmlvbl9hYSA8LSBmbGlnaHRzICU+JQ0KICBsZWZ0X2pvaW4ocGxhbmVzLCBieSA9ICJ0YWlsbnVtIikgJT4lDQogIHNlbGVjdChjYXJyaWVyLCB0eXBlLCBlbmdpbmUsIHNlYXRzKSAlPiUNCiAgZmlsdGVyKGNhcnJpZXIgPT0gIkFBIiwgIWlzLm5hKHR5cGUpKSAlPiUNCiAgZ3JvdXBfYnkoY2Fycmllcix0eXBlLGVuZ2luZSxzZWF0cykgJT4lIA0KICBjb3VudCgpDQpgYGANCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5FdmlkZW5jaWEgMS4gPC9zcGFuPg0KVGUgYWNhYmFzIGRlIGluY29ycG9yYXIgYSB1bmEgZW1wcmVzYSBjb25zdWx0b3JhIGVuIEludGVsaWdlbmNpYSBkZSBOZWdvY2lvcywNCmFjdHVhbG1lbnRlIGVzdMOhbiBicmluZGFuZG8gc2VydmljaW9zIGRlIGFuw6FsaXNpcyBwYXJhIGxhIGluZHVzdHJpYSBkZSBsYSBhdmlhY2nDs24geSBsZXMNCmludGVyZXNhIHRlbmVyIGEgbGEgYWVyb2zDrW5lYSBBbWVyaWNhbiBBaXJsaW5lcyBjb21vIGNsaWVudGUgeWEgcXVlIGVzIHVuYSBkZSBsYXMNCmFlcm9sw61uZWFzIGzDrWRlcmVzIGVuIGxvcyBhZXJvcHVlcnRvcyBkZSBOdWV2YSBZb3JrLCBtb3Rpdm8gcG9yIGVsIGN1w6FsIHRlIGhhbg0KY29udHJhdGFkby4gIA0KDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPkluc3RhbGFyIHBhcXVldGVzIHkgbGxhbWFyIGxpYnJlcsOtYXM8L3NwYW4+DQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygibnljZmxpZ2h0czEzIikNCmxpYnJhcnkobnljZmxpZ2h0czEzKQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IHNreSBibHVlOyI+R3VhcmRhciBiYXNlcyBkZSBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0KZmxpZ2h0cyA8LSBmbGlnaHRzDQp3ZWF0aGVyIDwtIHdlYXRoZXINCnBsYW5lcyA8LSBwbGFuZXMNCmFpcnBvcnRzIDwtIGFpcnBvcnRzDQphaXJsaW5lcyA8LSBhaXJsaW5lcw0KYGBgDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPlJlbGFjacOzbiBlbnRyZSBsYXMgYmFzZXMgZGUgZGF0b3M8L3NwYW4+DQohW10oQzpcXFVzZXJzXFxIUFxcRG93bmxvYWRzXFxyZWxhdGlvbmFsLW55Y2ZsaWdodHMucG5nKSAgDQoNCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IHNreSBibHVlOyI+MS4gRGF0YSBGcmFtZXMgZSBJZGVudGlmaWNhY2nDs24gZGUgdGlwbyBkZSBkYXRvczwvc3Bhbj4NCmBgYHtyfQ0KIyMgRGF0b3MgZGUgV2VhdGhlcg0Kd2VhdGhlcg0KIyMgRGF0b3MgZGUgUGxhbmVzDQpwbGFuZXMNCiMjIERhdG9zIGRlIEFpcnBvcnRzDQphaXJwb3J0cw0KIyMgRGF0b3MgZGUgYWlybGluZXMNCmFpcmxpbmVzDQpgYGANCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IHNreSBibHVlOyI+Mi4gQ2FyZ2FyIGVuIG1lbW9yaWEgbGEgdGFibGEgImZsaWdodHMiIHkgbW9zdHJhciBzdSBjb250ZW5pZG88L3NwYW4+DQpgYGB7cn0NCiMjIExhIGNhcmdhIGEgbWVtb3JpYSBzZSBoaXpvIGVuIGVsIHBhc28gYW50ZXJpb3INCmZsaWdodHMNCmBgYA0KDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPjMuIENvbnN1bHRhIGxhIGVzdHJ1Y3R1cmEgZGUgImZsaWdodHMiPC9zcGFuPg0KYGBge3J9DQpzdHIoZmxpZ2h0cykNCiMgaW50OiBlbnRlcm8gKG5vIHRpZW5lIGRlY2ltYWxlcykuIFNlIHV0aWxpemEgcGFyYSBhbG1hY2VuYXIgdmFsb3JlcyBudW3DqXJpY29zIHNpbiBkZWNpbWFsZXMsIGNvbW8gbGEgY2FudGlkYWQgZGUgcGFzYWplcm9zIG8gZWwgbsO6bWVybyBkZSB2dWVsb3MuDQojIGRibDogU2UgdXNhIHBhcmEgYWxtYWNlbmFyIG7Dum1lcm9zIGNvbiBkZWNpbWFsZXMsIGNvbW8gZGlzdGFuY2lhcyBvIHByZWNpb3MuDQojIG51bTogbnVtw6lyaWNvICh0aWVuZSBkZWNpbWFsZXMpIHBlc28NCiMgY2hyOiBjYXJhY3RlciAobGV0cmFzKS4gU2UgdXNhIHBhcmEgYWxtYWNlbmFyIHRleHRvLCBjb21vIG5vbWJyZXMgbyBwYWxhYnJhcy4gIA0KIyBEYXRlOiBmZWNoYSAoZW4gUiB2YSBhw7FvLW1lcy1kw61hKQ0KIyBQT1NJWGN0OiBmb3JtYXRvIGZlY2hhIHkgaG9yYS4gRXMgdW4gdGlwbyBkZSBkYXRvIHF1ZSByZXByZXNlbnRhIHVuYSBmZWNoYSB5IGhvcmEgZXNwZWPDrWZpY2EuIFNlIHV0aWxpemEgcGFyYSBhbG1hY2VuYXIgaW5mb3JtYWNpw7NuIHRlbXBvcmFsLCBjb21vIGxhIGZlY2hhIGRlIHVuIHZ1ZWxvIG8gbGEgaG9yYSBkZSBzYWxpZGEuDQpgYGANCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IHNreSBibHVlOyI+NC4gwr9DdcOhbCBlcyBsYSBjbGFzZSBkZSAiZmxpZ2h0cyIgeSBxdcOpIHNpZ25pZmljYT88L3NwYW4+DQpgYGB7cn0NCmNsYXNzKGZsaWdodHMpDQpjbGFzcw0KDQojIExhcyA1IGNsYXNlcyBkZSBvYmpldG9zIHNvbjoNCiMgMS4gbnVtZXJpYzogbsO6bWVybyByZWFsIG8gZGVjaW1hbGVzDQojIDIuIGludGVnZXI6IG7Dum1lcm9zIGVudGVyb3MNCiMgMy4gY29tcGxleDogbsO6bWVyb3MgY29tcGxlam9zDQojIDQuIGNoYXJhY3RlcjogY2FyYWN0ZXJlcywgbGV0cmFzIG8gcGFsYWJyYXMNCiMgNS4gbG9naWNhbDogVFJVRSBvIEZBTFNFDQoNCiMgTGFzIDQgY2xhc2VzIGRlIG9iamV0b3MgY29tcHVlc3RvcyBzb246IA0KDQojIDEuIGxpc3Q6IGxpc3RhDQojIDIuIG1hdHJpeDogbWF0cml6IChlcyB0b2RvIGxvIG1pc21vKQ0KIyAzLiBhcnJheTogY29sZWNjacOzbiBkZSBvYmpldG9zDQojIDQuIGRhdGEuZnJhbWU6IGJhc2UgZGUgZGF0b3MgKGVzIG1lemNsYWRvKQ0KYGBgDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPjUuIMK/Q3XDoW50YXMgY29sdW1uYXMgeSByZW5nbG9uZXMgdGllbmUgImZsaWdodHMiIMK/IEN1w6FsIGVzIHN1IGRpbWVuc2nDs24/IDwvc3Bhbj4NCmBgYHtyfQ0KIyBOw7ptZXJvIGRlIGNvbHVtbmFzDQpuY29sKGZsaWdodHMpDQojIE7Dum1lcm8gZGUgcmVuZ2xvbmVzDQpucm93KGZsaWdodHMpDQojIERpbWVuc2nDs24NCmRpbShmbGlnaHRzKQ0KYGBgDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPjYuIE11ZXN0cmEgbG9zIHByaW1lcm9zIDYgcmVuZ2xvbmVzIGRlICJmbGlnaHRzIiwgdGFtYmnDqW4gbG9zIMO6bHRpbW9zIDYuIDwvc3Bhbj4NCmBgYHtyfQ0KaGVhZChmbGlnaHRzKQ0KdGFpbChmbGlnaHRzKQ0KIyBTaSBxdWlzaWVyYW1vcyA3IHJlbmdsb25lczogaGVhZChmbGlnaHRzKQ0KYGBgDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPjcuIE11ZXN0cmEgbG9zIGVzdGFkw61zdGljb3MgZGVzY3JpcHRpdm9zIGRlICJmbGlnaHRzIjwvc3Bhbj4NCmBgYHtyfQ0Kc3VtbWFyeShmbGlnaHRzKQ0KYGBgICANCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IHNreSBibHVlOyI+Ny4xLiBEaXN0YW5jaWEgbWVkaWEgcmVjb3JyaWRhIGVuIG1pbGxhcy48L3NwYW4+ICANCmBgYHtyfQ0Kc3VtbWFyeShmbGlnaHRzJGRpc3RhbmNlKQ0KYGBgICANClBvZGVtb3MgdmVyIHF1ZSBsYSBkaXN0YW5jaWEgbWVkaWEgZW4gbWlsbGFzIGVzIGRlIDEwNDAgIA0KDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPjcuMi4gQWVyb2zDrW5lYXMgY29uIG1pbGxhcyByZWNvcnJpZGFzIHN1cGVyaW9yZXMgYSBsYSBtZWRpYSwgb3JkZW5hZGFzIGVuIGZvcm1hIGRlc2NlbmRlbnRlLjwvc3Bhbj4gIA0KDQpgYGB7cn0NCm1lZGlhX2Rpc3RhbmNpYSA8LSBtZWFuKGZsaWdodHMkZGlzdGFuY2UsIG5hLnJtID0gVFJVRSkNCmFlcm9saW5lYXNfdG9wIDwtIGZsaWdodHMgJT4lDQogIGZpbHRlcihkaXN0YW5jZSA+IG1lZGlhX2Rpc3RhbmNpYSkgJT4lDQogIHNlbGVjdChjYXJyaWVyLCBkaXN0YW5jZSwgb3JpZ2luLCBkZXN0KSAlPiUNCiAgYXJyYW5nZShkZXNjKGRpc3RhbmNlKSkNCnByaW50KGFlcm9saW5lYXNfdG9wKQ0KYGBgDQojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPjcuMy4gRW5jdWVudHJhIGxhIHN1bWEgeSBsYSBtZWRpYSBkZSBsYXMgZGlzdGFuY2lhcyByZWNvcnJpZGFzIHBvciBjYXJyaWVyPC9zcGFuPiAgDQpgYGB7cn0NCmRpc3RhbmNpYV9hZXJvbGluZWEgPC0gZmxpZ2h0cyAlPiUNCiAgZmlsdGVyKCFpcy5uYShkaXN0YW5jZSkpICU+JQ0KICBncm91cF9ieShjYXJyaWVyKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIHN1bWFfZGlzdGFuY2lhID0gc3VtKGRpc3RhbmNlKSwNCiAgICBtZWRpYV9kaXN0YW5jaWEgPSBtZWFuKGRpc3RhbmNlLCBuYS5ybSA9IFRSVUUpDQogICkgJT4lDQogIGFycmFuZ2UoZGVzYyhzdW1hX2Rpc3RhbmNpYSkpDQpwcmludChkaXN0YW5jaWFfYWVyb2xpbmVhKQ0KYGBgDQoNCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IHNreSBibHVlOyI+OC4gSWRlbnRpZmljYSBzaSBsYXMgYWVyb2zDrW5lYXMgbMOtZGVyZXMgc29uIGxhcyBtaXNtYXMgZW4gbG9zIHRyZXMgYWVyb3B1ZXJ0b3M8L3NwYW4+DQpgYGB7cn0NCiMgRnVuY2nDs24gcGFyYSBjcmVhciB1biBkYXRhIGZyYW1lIHBhcmEgdW4gYWVyb3B1ZXJ0bw0KYWVyb3B1ZXJ0b19kZiA8LSBmdW5jdGlvbihhZXJvcHVlcnRvKSB7DQogIGZsaWdodHMgJT4lDQogICAgZmlsdGVyKG9yaWdpbiA9PSBhZXJvcHVlcnRvKSAlPiUNCiAgICBmaWx0ZXIoIWlzLm5hKGRpc3RhbmNlKSkgJT4lDQogICAgZ3JvdXBfYnkoY2FycmllcikgJT4lDQogICAgc3VtbWFyaXNlKA0KICAgICAgc3VtYV9kaXN0YW5jaWEgPSBzdW0oZGlzdGFuY2UpLA0KICAgICAgbWVkaWFfZGlzdGFuY2lhID0gbWVhbihkaXN0YW5jZSwgbmEucm0gPSBUUlVFKQ0KICAgICkgJT4lDQogICAgYXJyYW5nZShkZXNjKHN1bWFfZGlzdGFuY2lhKSkNCn0NCg0KIyBEYXRhIGZyYW1lcyBwYXJhIGNhZGEgYWVyb3B1ZXJ0bw0KamZrX2RmIDwtIGFlcm9wdWVydG9fZGYoIkpGSyIpDQpsZ2FfZGYgPC0gYWVyb3B1ZXJ0b19kZigiTEdBIikNCmV3cl9kZiA8LSBhZXJvcHVlcnRvX2RmKCJFV1IiKQ0KDQojIE1vc3RyYXIgbG9zIGRhdGEgZnJhbWVzDQpwcmludChqZmtfZGYpDQpwcmludChsZ2FfZGYpDQpwcmludChld3JfZGYpDQpgYGANCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPkludGVycHJldGFjacOzbjwvc3Bhbj4gDQpBbWVyaWNhbiBBaXJsaW5lcyB0aWVuZSB1bmEgYWx0YSBzdW1hIGRlIGRpc3RhbmNpYSByZWNvcnJpZGEsIGxvIHF1ZSBpbmRpY2EgcXVlIGVzIHVuYSBhZXJvbMOtbmVhIGNvbiB1bmEgYW1wbGlhIHJlZCBkZSBydXRhcyB5IHVuIGdyYW4gdm9sdW1lbiBkZSBwYXNhamVyb3MuDQpMYSBtZWRpYSBkZSBsYSBkaXN0YW5jaWEgcmVjb3JyaWRhIHBvciBBQSBlcyBzdXBlcmlvciBhIGxhIG1lZGlhIGRlIG90cmFzIGFlcm9sw61uZWFzLCBsbyBxdWUgaW5kaWNhIHF1ZSBzdXMgdnVlbG9zIHNvbiBnZW5lcmFsbWVudGUgbcOhcyBsYXJnb3MuDQpFc3RvcyBkYXRvcyBwb2Ryw61hbiBzZXIgcmVsZXZhbnRlcyBwYXJhIGxvcyBpbnZlcnNvcmVzIHF1ZSBidXNjYW4gdW5hIGFlcm9sw61uZWEgY29uIHVuYSBmdWVydGUgcHJlc2VuY2lhIGVuIGVsIG1lcmNhZG8geSB1biBoaXN0b3JpYWwgZGUgcmVudGFiaWxpZGFkLiAgICANCiFbXShDOlxcVXNlcnNcXEhQXFxEZXNrdG9wXFxCTE9RVUVcXEFpcnBsYW5lLTEucG5nKSAgDQoNCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBza3kgYmx1ZTsiPkNvbmNsdXNpw7NuPC9zcGFuPg0KRW4gZXN0ZSB0cmFiYWpvIHB1ZGltb3MgdXRpbGl6YXIgbGFzIGZ1bmNpb25lcyBtw6FzIGNvbXVuZXMgZGVsIGFuw6FsaXNpcyBleHBsb3Rhcm90aW8sIGVsIGN1YWwgZXMgZWwgcHJpbWVyIHBhc28gcGFyYSBjdWFscXVpZXIgdHJhYmFqbyBkZSBtYW5pcHVsYWNpw7NuIGRlIGRhdG9zLCBoaWNpbW9zIHVzbyBkZSBkaXN0aW50YXMgaGVycmFtaWVudGFzIHBhcmEgYW5hbGl6YXIgbWVkaWFzLCBkaXN0YW5jaWFzIG1heW9yZXMgeSBtZW5vcmVzIHkgYXPDrSBmaW5hbG1lbnRlIGFuYWxpemFyIGxvcyBiZW5lZmljaW9zIGRlIHRlbmVyIGEgQW1lcmljYW4gQWlybGluZXMgY29tbyBudWV2byBjbGllbnRlLCBkZXNjdWJyaWVuZG8gc3UgZ3JhbiBwb3RlbmNpYWwgZW4gbcO6bHRpcGxlcyBhZXJvcHVlcnRvcyBjb21vIGFlcm9saW5lYSBsw61kZXIuICANCg0KDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPlNpdHVhY2nDs24gUHJvYmxlbWEgMi48L3NwYW4+DQpFdmlkZW5jaWEgMiAtIEFuYWzDrXRpY2EgZGVzY3JpcHRpdmEgKEludGVncmFjacOzbiBkZSBkYXRvcyBhIHRyYXbDqXMgZGUgbW9kZWxvIGVudGlkYWQtcmVsYWNpw7NuKSAgDQpDb21wcm9taXNvIMOpdGljbyB5IGNpdWRhZGFuby4gU2UgdGUgaGEgc29saWNpdGFkbyBoYWNlciB1biBlc3R1ZGlvIHNvYnJlIGxhIHNpdHVhY2nDs24gYWN0dWFsIGRlIGxhIGFlcm9sw61uZWEgQW1lcmljYW4gQWlybGluZXMgeWENCnF1ZSBzZSBuZWNlc2l0YSByZXZpc2FyIHN1cyBkZXN0aW5vcywgaG9yYXJpb3MgeSBhdmlvbmVzIGNvbiBsb3MgcXVlIGN1ZW50YSBwYXJhIGhhY2VyIHByb3B1ZXN0YXMNCmRlIGF1bWVudG8gbyByZWR1Y2Npw7NuIGRlIHZ1ZWxvcyBwb3IgZGVzdGlubyB5IGhvcmFyaW9zLCBhc8OtIGNvbW8gbGEgY2FudGlkYWQgZGUgYXZpb25lcy4gIA0KIVtdKEM6XFxVc2Vyc1xcSFBcXERlc2t0b3BcXERhdGlzXFx0QkJPMFIuZ2lmKSAgDQoNCg0KIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPjEuIERhdG9zIEdlbmVyYWxlcy48L3NwYW4+ICANCg0KIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij4xLjEgQ29uc3VsdGEgeSBleHBsb3JhY2nDs24gZGVsIGRhdGEgZnJhbWUgcGxhbmVzIHkgd2VhdGhlci4iPC9zcGFuPg0KYGBge3J9DQp2aWV3KHdlYXRoZXIpDQp2aWV3KHBsYW5lcykNCmBgYCAgDQoNCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+MS4yLglTZSBuZWNlc2l0YSBzYWJlciBkZSBjYWRhIHZ1ZWxvLCBsYSBhZXJvbMOtbmVhLCBlbCBhZXJvcHVlcnRvIGRlIG9yaWdlbiB5IGVsIGFlcm9wdWVydG8gZGVzdGluby4iPC9zcGFuPg0KYGBge3J9DQphZXJvbGluZWFzIDwtIGZsaWdodHMgJT4lIA0KICBzZWxlY3QoY2FycmllcixvcmlnaW4sZGVzdCkNCmFlcm9saW5lYXMNCmBgYA0KIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij4xLjMuCUVuIGxhIGNvbnN1bHRhIGFudGVyaW9yIHNlIG5lY2VzaXRhIGNvbm9jZXIgZWwgbm9tYnJlIGRlIGxhIGFlcm9sw61uZWEuIjwvc3Bhbj4NCmBgYHtyfQ0KYWVyb2xpbmVhc19ub21icmUgPC0gYWVyb2xpbmVhcyAlPiUNCiAgbGVmdF9qb2luKGFpcmxpbmVzLCBieSA9ICJjYXJyaWVyIikNCmFlcm9saW5lYXNfbm9tYnJlDQpgYGANCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+MS40LglTZSBuZWNlc2l0YSBzYWJlciBsYSBjYW50aWRhZCBkZSB2dWVsb3MgcG9yIGNhZGEgZGVzdGlubyBwYXJhIGlkZW50aWZpY2FyIGN1w6FsZXMgc29uIGxvcyBkZXN0aW5vcyBtw6FzIGJ1c2NhZG9zLiI8L3NwYW4+DQpgYGB7cn0NCmNhbnRfdnVlbG9zIDwtIGZsaWdodHMgJT4lIA0KICBzZWxlY3QoY2FycmllciwgZGVzdCkgJT4lIA0KICBjb3VudChkZXN0KQ0KY2FudF92dWVsb3MgPC0gY2FudF92dWVsb3MgJT4lDQogIGFycmFuZ2UoZGVzYyhuKSkNCmNhbnRfdnVlbG9zDQpgYGANCkxvcyBkZXN0aW5vcyBtw6FzIGJ1c2NhZG9zIHNvbiBPUkQgKEFlcm9wdWVydG8gSW50ZXJuYWNpb25hbCBPJ0hhcmUpIGNvbiAxNywyODMgdnVlbG9zLCBBVEwgKEF0bGFudGEpIGNvbiAxNywyMTUgdnVlbG9zIHkgTEFYIChMb3MgQW5nZWxlcykgY29uIDE2LDE3NCB2dWVsb3MuICANCg0KIVtdKEM6XFxVc2Vyc1xcSFBcXERlc2t0b3BcXERhdGlzXFxjaGljYWdvLWNocmlzdG9waGVyLWFsdmFyZW5nYS11bnNwbGFzaC5qcGcpICANCg0KDQojIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPjEuNS4gQWdyZWdhciBlbCBub21icmUgZGUgbGEgYWVyb2zDrW5lYSBhIGxhIHRhYmxhIGFudGVyaW9yLiI8L3NwYW4+DQpgYGB7cn0NCmNhbnRfdnVlbG9zMSA8LSBmbGlnaHRzICU+JQ0KICBzZWxlY3QoY2FycmllciwgZGVzdCkgJT4lDQogIGdyb3VwX2J5KGNhcnJpZXIsIGRlc3QpICU+JQ0KICBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgYXJyYW5nZShkZXNjKG4pKQ0KY2FudF92dWVsb3MxDQpgYGAgIA0KDQpMYSBhZXJvbMOtbmVhIGNvbiBtYXlvciBjYW50aWRhZCBkZSB2dWVsb3MgZXMgREwgKERFTFRBIEFJUkxJTkVTKTogRGVsdGEgQWlyIExpbmVzIGVzIHVuYSBhZXJvbMOtbmVhIGNvbWVyY2lhbCBlc3RhZG91bmlkZW5zZSBjdXlhIGJhc2UgZXN0w6Egc2l0dWFkYSBlbiBBdGxhbnRhLCBHZW9yZ2lhLiBFcyBtaWVtYnJvIGZ1bmRhZG9yLCBqdW50byBjb24gQWVyb23DqXhpY28sIEFpciBGcmFuY2UgeSBLb3JlYW4gQWlyLCBkZSBTa3lUZWFtLCB1bmEgYWxpYW56YSBkZSBhZXJvbMOtbmVhcyBnbG9iYWxlcyBxdWUgb2ZyZWNlIGEgbG9zIGNsaWVudGVzIHVuIGdyYW4gbsO6bWVybyBkZSBkZXN0aW5vcyBhbHJlZGVkb3IgZGVsIG11bmRvLCB2dWVsb3MgeSBvdHJvcyBzZXJ2aWNpb3MgIA0KDQojIyMjIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPjEuNi4gU2UgbmVjZXNpdGEgY29ub2NlciBsYXMgYWVyb2zDrW5lYXMgKGNsYXZlIHkgbm9tYnJlKSB5IGRlc3Rpbm9zIHF1ZSB2dWVsYW4gcG9yIGxhIE1hw7FhbmE6IGRlIDYgYSAxMiwgVGFyZGU6IGRlIDEyIGEgMTkgLCBOb2NoZTogZGUgMTkgYSAyNCB5IE1hZHJ1Z2FkYSBkZSAyNCBhIDYuIjwvc3Bhbj4NCmBgYHtyfQ0KdnVlbG9fcG9yaG9yYSA8LSBmbGlnaHRzICU+JQ0Kc2VsZWN0KGNhcnJpZXIsIGRlc3QsIHNjaGVkX2RlcF90aW1lKSAlPiUNCiAgbGVmdF9qb2luKGFpcmxpbmVzLCBieSA9ICJjYXJyaWVyIikNCg0KY2xhc19ob3JhPC0gbXV0YXRlKHZ1ZWxvX3BvcmhvcmEsIGNsYXNfaG9yYXJpbyA9IGlmZWxzZShzY2hlZF9kZXBfdGltZSAlaW4lIDYwMDoxMTU5LCJNb3JuaW5nIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHNjaGVkX2RlcF90aW1lICVpbiUgMTIwMDoxODU5LCJBZmVydG5vb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uoc2NoZWRfZGVwX3RpbWUgJWluJSAxOTAwOjI0MDAsIk5pZ2h0IiwgIk1hZHJ1Z2FkYSIpKSkpDQpjbGFzX2hvcmENCmBgYCAgDQoNCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+MS43LlNlIG5lY2VzaXRhIHNhYmVyIGxhIGNhbnRpZGFkIGRlIHZ1ZWxvcyBwb3IgYWVyb2zDrW5lYSB5IGRlc3Rpbm8gcXVlIGhheSBwb3IgbGEgTWHDsWFuYSwgVGFyZGUsIE5vY2hlIHkgTWFkcnVnYWRhLiI8L3NwYW4+DQpgYGB7cn0NCiMgQWdydXBhciBwb3IgYWVyb2zDrW5lYSwgZGVzdGlubyB5IGZyYW5qYSBob3JhcmlhIHkgY29udGFyIGxhIGNhbnRpZGFkIGRlIHZ1ZWxvcw0KdnVlbG9zX2NvbnRlbyA8LSBjbGFzX2hvcmEgJT4lICANCiAgZ3JvdXBfYnkoY2FycmllciwgZGVzdCwgY2xhc19ob3JhcmlvKSAlPiUgY291bnQoKQ0KDQojIE1vc3RyYXIgbG9zIHJlc3VsdGFkb3MNCnZ1ZWxvc19jb250ZW8NCmBgYCAgDQoNCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+MS44LlNlIG5lY2VzaXRhIHNhYmVyIGEgcXXDqSBkZXN0aW5vcyB2dWVsYSBsYSBhZXJvbMOtbmVhIEFtZXJpY2FuIEFpcmxpbmVzIEluYy4tQUEgZHVyYW50ZSBsYSBtYWRydWdhZGEuIjwvc3Bhbj4NCmBgYHtyfQ0KZGVzdGlub3NfYW1lcmljYW4gPC0gY2xhc19ob3JhICU+JSANCiAgc2VsZWN0KGNhcnJpZXIsbmFtZSwgZGVzdCxjbGFzX2hvcmFyaW8pICU+JSANCiAgZmlsdGVyKGNhcnJpZXIgPT0gIkFBIiAmIGNsYXNfaG9yYXJpbyA9PSAiTWFkcnVnYWRhIikgJT4lIA0KICBncm91cF9ieShjYXJyaWVyLG5hbWUsIGRlc3QsY2xhc19ob3JhcmlvKQ0KZGVzdGlub3NfYW1lcmljYW4NCmBgYA0KQW1lcmljYW4gQWlybGluZXMgcmVhbGl6YSB2dWVsb3MgZGUgbWFkcnVnYWRhIGEgw7puaWNhbWVudGUgZWwgZGVzdGlubyBkZSBNaWFtaS4NCiFbXShDOlxcVXNlcnNcXEhQXFxEZXNrdG9wXFxEYXRpc1xcMzM5NjU2LURvd250b3duLU1pYW1pLmpwZykNCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+MS45LlF1w6kgYXZpb25lcyB1dGlsaXphIGxhIGFlcm9sw61uZWEgQUE/IGFlcm9sw61uZWEsIHRpcG8sIG1vdG9yIHkgbsO6bWVybyBkZSBhc2llbnRvcyB5IMK/Q3XDoW50b3MgdnVlbG9zIHNlIGhhbiByZWFsaXphZG8gY29uIGNhZGEgdW5vPyAoZWxpbWluYSBsb3MgTkEncykiPC9zcGFuPg0KYGBge3J9DQphdmlvbl9hbWVyaWNhbiA8LSBmbGlnaHRzICU+JQ0KICBsZWZ0X2pvaW4ocGxhbmVzLCBieSA9ICJ0YWlsbnVtIikgJT4lDQogIHNlbGVjdChjYXJyaWVyLCB0eXBlLCBlbmdpbmUsIHNlYXRzKSAlPiUNCiAgZmlsdGVyKGNhcnJpZXIgPT0gIkFBIiwgIWlzLm5hKHR5cGUpKSAlPiUNCiAgZ3JvdXBfYnkoY2Fycmllcix0eXBlLGVuZ2luZSxzZWF0cykgJT4lIA0KICBjb3VudCgpDQphdmlvbl9hbWVyaWNhbg0KYGBgDQojIDxzcGFuIHN0eWxlPSJjb2xvcjogc2t5IGJsdWU7Ij5SZXBvcnRlPC9zcGFuPg0KSGFsbGF6Z29zOiAgIA0KLVJldHJhc29zOiAgICANCkFlcm9sw61uZWFzIGNvbiBtYXlvciByZXRyYXNvOiBWYXLDrWFuIHNlZ8O6biBlbCBkZXN0aW5vIChGOSwgRVYsIE9PKSAgDQpEZXN0aW5vcyBjb24gbWF5b3IgcmV0cmFzbzogTEdBLCBFV1IsIEpGSyAoZGViaWRvIGEgbGFzIGNvbmRpY2lvbmVzIGNsaW3DoXRpY2FzIGFkdmVyc2FzIG8gY29uZ2VzdGnDs24gYcOpcmVhKSAgDQotTW9kZWxvcyBkZSBhdmlvbmVzOiAgDQpNw6FzIHV0aWxpemFkb3M6ICAgIA0KRml4ZWQgd2luZyBtdWx0aSBlbmdpbmU6IExvcyBhdmlvbmVzIGRlIGFsYSBmaWphIG11bHRpbW90b3Igc29uIHVuYSBvcGNpw7NuIHZlcnPDoXRpbCB5IGNvbmZpYWJsZSBwYXJhIHVuYSB2YXJpZWRhZCBkZSBhcGxpY2FjaW9uZXMuIFNpIGJpZW4gc29uIG3DoXMgY29zdG9zb3MgcXVlIGxvcyBhdmlvbmVzIG1vbm9tb3RvcmVzLCBvZnJlY2VuIG1heW9yIHNlZ3VyaWRhZCwgcmVuZGltaWVudG8geSBhbGNhbmNlLiAgDQoNCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IHNreSBibHVlOyI+VmlzdWFsaXphY2nDs24gZGUgZGF0b3M8L3NwYW4+DQpFbiBsb3MgYXZhbmNlcyBhbnRlcmlvcmVzIHNlIGhhbiByZWFsaXphZG8gZGlmZXJlbnRlcyBhbsOhbGlzaXMgeSBhaG9yYSBub3Mgc29saWNpdGFuIGhhY2VyIHZpc3VhbGl6YWNpb25lcyBkZSBsYQ0KYWVyb2zDrW5lYSBBbWVyaWNhbiBBaXJsaW5lcyBwYXJhIGxvcyBlamVjdXRpdm9zIGNvbiBsYXMgc2lndWllbnRlcyBjYXJhY3RlcsOtc3RpY2FzLg0KRGVudHJvIGRlIGxhcyBhZXJvbMOtbmVhcyBlbCByZXRyYXNvIHRhbnRvIGVuIGxhIGhvcmEgZGUgcGFydGlkYSBjb21vIGVuIGxhIGhvcmEgZGUgbGxlZ2FkYSBhIHN1IGRlc3Rpbm8gdmFuDQpnZW5lcmFuZG8gaW5kaWNhZG9yZXMgbmVnYXRpdm9zLg0KIyMjIFNlIHNvbGljaXRhIGFuYWxpemFyIHBhcmEgbGEgYWVyb2zDrW5lYSBBbWVyaWNhbiBBaXJsaW5lcyBzaSBsb3MgdnVlbG9zIHF1ZSB0aWVuZW4gcmV0cmFzbyBlbiBsYSBwYXJ0aWRhIHRhbWJpw6luIHRpZW5lbiByZXRyYXNvIGVuIGxhIGhvcmEgZGUgbGxlZ2FkYS4gIA0KYGBge3J9DQojIEZpbHRyYXIgbG9zIHZ1ZWxvcyBkZSBBbWVyaWNhbiBBaXJsaW5lcyAoQUEpDQphbWVyaWNhbl9mbGlnaHRzIDwtIGZsaWdodHMgJT4lIGZpbHRlcihjYXJyaWVyID09ICJBQSIpDQoNCiMgTW9zdHJhciBsYSByZWxhY2nDs24gZW50cmUgZWwgcmV0cmFzbyBlbiBsYSBwYXJ0aWRhIHkgZWwgcmV0cmFzbyBlbiBsYSBsbGVnYWRhDQpjb3IoYW1lcmljYW5fZmxpZ2h0cyRkZXBfZGVsYXksIGFtZXJpY2FuX2ZsaWdodHMkYXJyX2RlbGF5LCB1c2UgPSAiY29tcGxldGUub2JzIikNCmBgYA0KYGBge3J9DQojIEZpbHRyYXIgbG9zIHZ1ZWxvcyBkZSBBbWVyaWNhbiBBaXJsaW5lcyAoQUEpDQphbWVyaWNhbl9mbGlnaHRzIDwtIGZsaWdodHMgJT4lIGZpbHRlcihjYXJyaWVyID09ICJBQSIpDQoNCiMgQ3JlYXIgdW4gZ3LDoWZpY28gZGUgZGlzcGVyc2nDs24NCmdncGxvdChhbWVyaWNhbl9mbGlnaHRzLCBhZXMoeCA9IGRlcF9kZWxheSwgeSA9IGFycl9kZWxheSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSwgY29sb3IgPSAiYmx1ZSIpICsNCiAgbGFicyhtYWluID0gIlJlbGFjacOzbiBlbnRyZSBSZXRyYXNvIGVuIFNhbGlkYSB5IExsZWdhZGEgcGFyYSBBbWVyaWNhbiBBaXJsaW5lcyIsIHggPSAiUmV0cmFzbyBlbiBsYSBQYXJ0aWRhIChtaW51dG9zKSIsIHkgPSAiUmV0cmFzbyBlbiBsYSBMbGVnYWRhIChtaW51dG9zKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCkVsIHJlc3VsdGFkbyBkZSBsYSBjb3JyZWxhY2nDs24gZW50cmUgZWwgcmV0cmFzbyBlbiBsYSBwYXJ0aWRhIHkgZWwgcmV0cmFzbyBlbiBsYSBsbGVnYWRhIHBhcmEgbG9zIHZ1ZWxvcyBkZSBBbWVyaWNhbiBBaXJsaW5lcyAoQUEpIGVzIGFwcm94aW1hZGFtZW50ZSAwLjg5MTcuIEVzdGUgdmFsb3IgY2VyY2FubyBhIDEgaW5kaWNhIHVuYSBmdWVydGUgY29ycmVsYWNpw7NuIHBvc2l0aXZhIGVudHJlIGFtYmFzIHZhcmlhYmxlcy4gRW4gb3RyYXMgcGFsYWJyYXMsIGhheSB1bmEgdGVuZGVuY2lhIGEgcXVlIGxvcyB2dWVsb3MgcXVlIGV4cGVyaW1lbnRhbiByZXRyYXNvIGVuIGxhIHNhbGlkYSB0YW1iacOpbiB0ZW5nYW4gcmV0cmFzbyBlbiBsYSBsbGVnYWRhLiAgDQoNCiMjIyBUZW1wZXJhdHVyYSB5IHN1cyB2YXJpYWNpb25lcw0KIyMjIyBWaXN1YWxpemEgbGEgdGVuZGVuY2lhIGRlIGxhIHRlbXBlcmF0dXJhIGR1cmFudGUgbG9zIHByaW1lcm9zIDE1IGTDrWFzIGRlbCBtZXMgZGUgRW5lcm8gZW4gbG9zIHZ1ZWxvcyBxdWUgcGFydGVuIGRlbCBhZXJvcHVlcnRvIOKAnE5ld2FyaywgRVdS4oCdLCB1dGlsaXphciB1bmEgZ3LDoWZpY2EgZGUgbMOtbmVhLg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgRmlsdHJhciBsb3MgZGF0b3MgcGFyYSBsb3MgcHJpbWVyb3MgMTUgZMOtYXMgZGUgZW5lcm8gZW4gZWwgYWVyb3B1ZXJ0byBOZXdhcmsNCndlYXRoZXJfamFudWFyeSA8LSB3ZWF0aGVyICU+JQ0KICBmaWx0ZXIobW9udGggPT0gMSAmIGRheSA8PSAxNSAmIG9yaWdpbiA9PSAiRVdSIikNCg0KIyBHcsOhZmljbyBkZSBsw61uZWEgcGFyYSBsYSB0ZW5kZW5jaWEgZGUgdGVtcGVyYXR1cmENCmdncGxvdCh3ZWF0aGVyX2phbnVhcnksIGFlcyh4ID0gZGF5LCB5ID0gdGVtcCkpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEpICsNCiAgbGFicyhtYWluPSJUZW5kZW5jaWEgZGUgbGEgVGVtcGVyYXR1cmEgZW4gbG9zIFByaW1lcm9zIDE1IETDrWFzIGRlIEVuZXJvIChBZXJvcHVlcnRvIE5ld2FyaykiLA0KICAgICAgIHg9d2VhdGhlcl9qYW51YXJ5JGRheSwNCiAgICAgICB5PXdlYXRoZXJfamFudWFyeSR0ZW1wKQ0KYGBgDQojIyMjIFZpc3VhbGl6YSBsYSB0ZW1wZXJhdHVyYSBtw6FzIGZyZWN1ZW50ZSBlbiBsb3MgcHJpbWVyb3MgMTUgZMOtYXMgZGVsIG1lcyBkZSBFbmVybywgdXRpbGl6YXIgdW4gaGlzdHJvZ3JhbWEuDQpgYGB7cn0NCiMgRmlsdHJhciBsb3MgZGF0b3MgcGFyYSBsb3MgcHJpbWVyb3MgMTUgZMOtYXMgZGUgZW5lcm8gZW4gZWwgYWVyb3B1ZXJ0byBOZXdhcmsNCndlYXRoZXJfamFudWFyeSA8LSB3ZWF0aGVyICU+JQ0KICBmaWx0ZXIobW9udGggPT0gMSAmIGRheSA8PSAxNSAmIG9yaWdpbiA9PSAiRVdSIikNCg0KIyBHcsOhZmljbyBkZSBsw61uZWEgcGFyYSBsYSB0ZW5kZW5jaWEgZGUgdGVtcGVyYXR1cmENCmdncGxvdCh3ZWF0aGVyX2phbnVhcnksIGFlcyh4ID0gdGVtcCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyhtYWluPSJUZW5kZW5jaWEgZGUgbGEgVGVtcGVyYXR1cmEgZW4gbG9zIFByaW1lcm9zIDE1IETDrWFzIGRlIEVuZXJvIChBZXJvcHVlcnRvIE5ld2FyaykiLA0KICAgICAgIHg9d2VhdGhlcl9qYW51YXJ5JGRheSwNCiAgICAgICB5PXdlYXRoZXJfamFudWFyeSR0ZW1wKQ0KYGBgDQojIyMjIFV0aWxpemEgRmFjZXRzIHBhcmEgb2JzZXJ2YXIgY8OzbW8gdmFyw61hIGxhIHRlbXBlcmF0dXJhIGVuIGNhZGEgbWVzIGVuIGVsIGhpc3RvZ3JhbWEgZGVsIHB1bnRvIGFudGVyaW9yIC4NCmBgYHtyfQ0Kd2VhdGhlciAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gdGVtcCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAyLCBmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW1hIGRlIFRlbXBlcmF0dXJhcyBwb3IgTWVzIiwNCiAgICAgICB4ID0gIlRlbXBlcmF0dXJhIChGYWhyZW5oZWl0KSIsDQogICAgICAgeSA9ICJGcmVjdWVuY2lhIikgKw0KICBmYWNldF93cmFwKH5tb250aCkNCmBgYA0KIyMjIyBOw7ptZXJvIGRlIHZ1ZWxvcyBxdWUgc2FsaWVyb24gZGUgTnVldmEgWW9yayBlbiAyMDEzIHBvciBhZXJvbMOtbmVhIChtb3N0cmFyIHNvbGFtZW50ZSBsYXMgMTAgYWVyb2zDrW5lYXMgY29uIG3DoXMgdnVlbG9zKSwgdXRpbGl6YXIgZ3LDoWZpY2EgZGUgYmFycmFzLg0KYGBge3J9DQpmbGlnaHRzICU+JQ0KICBncm91cF9ieShjYXJyaWVyKSAlPiUNCiAgc3VtbWFyaXNlKG51bV9mbGlnaHRzID0gbigpKSAlPiUNCiAgYXJyYW5nZShkZXNjKG51bV9mbGlnaHRzKSkgJT4lDQogIHNsaWNlKDE6MTApICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGNhcnJpZXIsIC1udW1fZmxpZ2h0cyksIHkgPSBudW1fZmxpZ2h0cykpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIpICsNCiAgbGFicyh0aXRsZSA9ICJOdW1lcm8gZGUgdnVlbG9zIHBvciBhZXJvbGluZWEiLA0KICAgICAgIHggPSAiQWVyb2xpbmVhIiwNCiAgICAgICB5ID0gIk51bWVybyBkZSBWdWVsb3MiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpTZWfDum4gZWwgZ3LDoWZpY28gIk7Dum1lcm8gZGUgdnVlbG9zIHBvciBhZXJvbMOtbmVhIGVuIDIwMTMiLCBzZSBvYnNlcnZhIHF1ZSBsYXMgYWVyb2zDrW5lYXMgY29uIG1heW9yIGNhbnRpZGFkIGRlIHZ1ZWxvcyBkZXNkZSBOdWV2YSBZb3JrIGR1cmFudGUgZXNlIGHDsW8gZnVlcm9uICJVbml0ZWQgQWlybGluZXMiIHkgIkpldEJsdWUgQWlyd2F5cyIuIEVzdGFzIGRvcyBhZXJvbMOtbmVhcyBsaWRlcmFuIHNpZ25pZmljYXRpdmFtZW50ZSBlbiB0w6lybWlub3MgZGUgbGEgY2FudGlkYWQgZGUgdnVlbG9zLCBzdXBlcmFuZG8gYSBvdHJhcyBjb21wYcOxw61hcy4gRWwgZ3LDoWZpY28gcHJvcG9yY2lvbmEgdW5hIHLDoXBpZGEgdmlzdWFsaXphY2nDs24gZGUgbGEgZGlzdHJpYnVjacOzbiBkZSB2dWVsb3MgZW50cmUgbGFzIGFlcm9sw61uZWFzIHByaW5jaXBhbGVzLCBzaWVuZG8gw7p0aWwgcGFyYSBjb21wcmVuZGVyIGxhIHBhcnRpY2lwYWNpw7NuIHJlbGF0aXZhIGRlIGNhZGEgdW5hIGVuIGVsIHRyw6FmaWNvIGHDqXJlbyBkZXNkZSBOdWV2YSBZb3JrIGVuIDIwMTMuDQojIyMjIFZpc3VhbGl6YSBlbCBwdW50byBhbnRlcmlvciBlbiB1bmEgZ3LDoWZpY2EgZGUgcGllLg0KYGBge3J9DQpTeXMuc2V0bG9jYWxlKCJMQ19DVFlQRSIsICJlbl9VUy5VVEYtOCIpDQojIEZpbHRyYW1vcyBsb3MgZGF0b3MgcGFyYSBvYnRlbmVyIGxhIGNhbnRpZGFkIGRlIHZ1ZWxvcyBwb3IgYWVyb2zDrW5lYQ0KdG9wX2FpcmxpbmVzIDwtIGZsaWdodHMgJT4lDQogIGdyb3VwX2J5KGNhcnJpZXIpICU+JQ0KICBzdW1tYXJpc2UobnVtX2ZsaWdodHMgPSBuKCkpICU+JQ0KICBhcnJhbmdlKGRlc2MobnVtX2ZsaWdodHMpKSAlPiUNCiAgc2xpY2UoMToxMCkgICMgU2VsZWNjaW9uYW1vcyBsYXMgMTAgYWVyb2zDrW5lYXMgY29uIG3DoXMgdnVlbG9zDQpnZ3Bsb3QodG9wX2FpcmxpbmVzLCBhZXMoeCA9ICIiLCB5ID0gbnVtX2ZsaWdodHMsIGZpbGwgPSBmYWN0b3IoY2FycmllcikpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlbCBOw7ptZXJvIGRlIFZ1ZWxvcyBwb3IgQWVyb2zDrW5lYSBkZXNkZSBOdWV2YSBZb3JrIGVuIDIwMTMiLA0KICAgICAgIGZpbGwgPSAiQWVyb2zDrW5lYSIsDQogICAgICAgeCA9IE5VTEwsDQogICAgICAgeSA9IE5VTEwpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQpgYGANCiMjIyMgUmVsYWNpb25hIGVsIGRhdGEgZnJhbWUgZmxpZ3RocyBjb24gZWwgZGF0YSBmcmFtZSBhaXJwb3J0cyBhIHRyYXbDqXMgZGVsIGNhbXBvIGRlc3Rpbm8uDQpgYGB7cn0NCiMgUmVhbGl6YSBsYSB1bmnDs24gZGUgbG9zIGRhdGEgZnJhbWVzIGZsaWdodHMgeSBhaXJwb3J0cyBwb3IgZWwgY2FtcG8gZGVzdGlubw0KdW5pb25fZnlhIDwtIGxlZnRfam9pbihmbGlnaHRzLCBhaXJwb3J0cywgYnkgPSBjKCJkZXN0IiA9ICJmYWEiKSkNCmBgYA0KDQojIyMjIENyZWEgdW4gbnVldm8gZGF0YSBmcmFtZSBjb24gZWwgcHVudG8gYW50ZXJpb3Igw7puaWNhbWVudGUgY29uIGxvcyA1IGNhcnJpZXJzIGNvbiBtw6FzIHZ1ZWxvcyBwb3IgZGVzdGlubw0KYGBge3J9DQojIENyZWEgdW4gbnVldm8gZGF0YSBmcmFtZSBjb24gbG9zIDUgY2FycmllcnMgY29uIG3DoXMgdnVlbG9zDQp0b3BfY2FycmllcnMgPC0gdW5pb25fZnlhICU+JQ0KICBncm91cF9ieShjYXJyaWVyKSAlPiUNCiAgc3VtbWFyaXNlKG51bV9mbGlnaHRzID0gbigpKSAlPiUNCiAgYXJyYW5nZShkZXNjKG51bV9mbGlnaHRzKSkgJT4lDQogIHNsaWNlKDE6NSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIE11ZXN0cmEgZWwgbnVldm8gZGF0YSBmcmFtZQ0KcHJpbnQodG9wX2NhcnJpZXJzKQ0KDQpmbGlnaHRzX3RvcF9jYXJyaWVycyA8LSB1bmlvbl9meWEgJT4lDQogIGZpbHRlcihjYXJyaWVyICVpbiUgdG9wX2NhcnJpZXJzJGNhcnJpZXIpDQpgYGANCiMjIyNSZWFsaXphIHVuYSB2aXN1YWxpemFjacOzbiBkZWwgcHVudG8gYW50ZXJpb3IgZGUgbGFzIHNpZ3VpZW50ZXMgdHJlcyBmb3JtYXMuDQpgYGB7cn0NCiMgRGF0YUZyYW1lIGNvbiBsb3MgcmVzdWx0YWRvcw0KdG9wX2NhcnJpZXJzIDwtIHVuaW9uX2Z5YSAlPiUNCiAgZ3JvdXBfYnkoY2Fycmllciwgb3JpZ2luKSAlPiUNCiAgc3VtbWFyaXNlKG51bV9mbGlnaHRzID0gbigpKSAlPiUNCiAgYXJyYW5nZShkZXNjKG51bV9mbGlnaHRzKSkgJT4lDQogIHNsaWNlKDE6NSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQpnZ3Bsb3QodG9wX2NhcnJpZXJzLCBhZXMoeCA9IGNhcnJpZXIsIHkgPSBudW1fZmxpZ2h0cywgZmlsbCA9IGFzLmZhY3RvcihjYXJyaWVyKSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIikgKw0KICBsYWJzKHggPSAiQ2FycmllciIsIHkgPSAiTnVtYmVyIG9mIEZsaWdodHMiLCB0aXRsZSA9ICJUb3AgNSBDYXJyaWVycyBjb24gbcOhcyB2dWVsb3MgcG9yIGFlcm9wdWVydG8iKSArDQogIGZhY2V0X3dyYXAofm9yaWdpbiwgc2NhbGVzID0gImZyZWVfeCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGZsaWdodHNfdG9wX2NhcnJpZXJzLCBhZXMoeCA9IGNhcnJpZXIsIGZpbGwgPSBjYXJyaWVyKSkgKw0KICBnZW9tX2JhcigpICsNCiAgbGFicyh0aXRsZSA9ICJDYW50aWRhZCBkZSB2dWVsb3MgcG9yIGFlcm9sw61uZWEiLCB4ID0gIkFlcm9sw61uZWEiLCB5ID0gIkNhbnRpZGFkIGRlIHZ1ZWxvcyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgZ2VvbV90ZXh0KHN0YXQgPSAiY291bnQiLCBhZXMobGFiZWwgPSAuLmNvdW50Li4sIGdyb3VwID0gY2FycmllciksIHZqdXN0ID0gLTAuNSkNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZmxpZ2h0c190b3BfY2FycmllcnMsIGFlcyh4ID0gZGVzdCwgZmlsbCA9IGNhcnJpZXIpKSArDQogIGdlb21fYmFyKCkgKw0KICBsYWJzKHRpdGxlID0gIkNhbnRpZGFkIGRlIHZ1ZWxvcyBwb3IgZGVzdGlubyIsIHggPSAiRGVzdGlubyIsIHkgPSAiQ2FudGlkYWQgZGUgdnVlbG9zIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKQ0KYGBgDQoNCiMgQ29tcHJvbWlzbyDDiXRpY28geSBDaXVkYWRhbm8gIA0KDQpWYWxvciBkZSBsYSBpbnRlZ3JpZGFkOiAgDQoNCkxhIGludGVncmlkYWQgZXMgdW4gdmFsb3IgZnVuZGFtZW50YWwgcXVlIGltcGxpY2EgYWN0dWFyIGNvbiBob25lc3RpZGFkIHkgY29oZXJlbmNpYSBlbiB0b2RhcyBsYXMgYWNjaW9uZXMuIEVuIGVsIGNvbnRleHRvIGRlbCBhbsOhbGlzaXMgZGUgZGF0b3MsIGxhIGludGVncmlkYWQgc2UgdHJhZHVjZSBlbiBtYW5lamFyIGxhIGluZm9ybWFjacOzbiBkZSBtYW5lcmEgcHJlY2lzYSwgcmVzcGV0YXIgbGEgcHJpdmFjaWRhZCBkZSBsb3MgZGF0b3MgeSBwcmVzZW50YXIgcmVzdWx0YWRvcyBkZSBtYW5lcmEgZmllbCB5IG9iamV0aXZhLiBFc3RlIHZhbG9yIGltcGxpY2EgbGEgcmVzcG9uc2FiaWxpZGFkIGRlIHRvbWFyIGRlY2lzaW9uZXMgw6l0aWNhcyB5IHRyYW5zcGFyZW50ZXMgZW4gdG9kYXMgbGFzIGZhc2VzIGRlbCBhbsOhbGlzaXMgZGUgZGF0b3MsIGRlc2RlIGxhIHJlY29waWxhY2nDs24gaGFzdGEgbGEgaW50ZXJwcmV0YWNpw7NuIHkgY29tdW5pY2FjacOzbiBkZSBsb3MgcmVzdWx0YWRvcy4gIA0KDQoNClJlZmxleGnDs24gcGVyc29uYWw6ICANCg0KRW4gbnVlc3RybyBkZWJlIGNvbW8gYW5hbGlzdGFzIGRlIGRhdG9zIG5vcyBjb21wcm9tZXRlbW9zIGEgc2VyIGp1c3RvcyBjb24gbG9zIGRhdG9zIGRlIHVuYSBlbXByZXNhLiBFc3RvIGltcGxpY2EgZ2FyYW50aXphciBsYSBjb25maWRlbmNpYWxpZGFkIGRlIGxhIGluZm9ybWFjacOzbiBzZW5zaWJsZSwgdXRpbGl6YXIgbcOpdG9kb3MgeSB0w6ljbmljYXMgw6l0aWNhcyBlbiBlbCBhbsOhbGlzaXMsIHkgcHJlc2VudGFyIGxvcyByZXN1bHRhZG9zIGRlIG1hbmVyYSB0cmFuc3BhcmVudGUgeSBjb21wcmVuc2libGUuIEFkZW3DoXMsIG5vcyBjb21wcm9tZXRlbW9zIGEgY3Vlc3Rpb25hciBjdWFscXVpZXIgcHLDoWN0aWNhIHF1ZSBwdWVkYSBjb21wcm9tZXRlciBsYSBpbnRlZ3JpZGFkIGRlIGxvcyBkYXRvcyBvIGVsIGFuw6FsaXNpcywgYWJvZ2FuZG8gc2llbXByZSBwb3IgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIMOpdGljYXMgeSByZXNwb25zYWJsZXMuICANCg0KDQpCaWJsaW9ncmFmw61hOiAgDQoNCg0KSm9obnNvbiwgUi4gKDIwMTgpLiAiRXRoaWNzIGluIERhdGEgU2NpZW5jZTogQW4gSW50cm9kdWN0aW9uLiIgTydSZWlsbHkgTWVkaWEuICANCg0KRGF2ZW5wb3J0LCBULiwgJiBIYXJyaXMsIEouICgyMDE3KS4gIkNvbXBldGluZyBvbiBBbmFseXRpY3M6IFVwZGF0ZWQsIHdpdGggYSBOZXcgSW50cm9kdWN0aW9uLiIgSGFydmFyZCBCdXNpbmVzcyBSZXZpZXcgUHJlc3MuICANCg0KRGlha29wb3Vsb3MsIE4uICgyMDE2KS4gIkRhdGEgRXRoaWNzIGFuZCB0aGUgUm9sZSBvZiBEYXRhIFNjaWVuY2UgaW4gdGhlIEZvdXJ0aCBJbmR1c3RyaWFsIFJldm9sdXRpb24uIiBKb3VybmFsIG9mIERhdGEgU2NpZW5jZSwgMTQoNCksIDU1My01NjIuICANCg0KIyBDb25jbHVzaW9uZXM6ICANCkFsZ3Vub3MgcHVudG9zIGRlc3RhY2Fkb3MgeSBjb25jbHVzaW9uZXMgaW1wb3J0YW50ZXMgaW5jbHV5ZW46DQoNCklkZW50aWZpY2FjacOzbiBkZSBsYXMgcHJpbmNpcGFsZXMgYWVyb2zDrW5lYXMgeSBkZXN0aW5vczoNCg0KRWwgY8OzZGlnbyBwZXJtaXRlIGlkZW50aWZpY2FyIGxhcyBwcmluY2lwYWxlcyBhZXJvbMOtbmVhcyB5IGRlc3Rpbm9zIGJhc8OhbmRvc2UgZW4gbGEgY2FudGlkYWQgZGUgdnVlbG9zLiBFc3RvIHByb3BvcmNpb25hIGluZm9ybWFjacOzbiBjbGF2ZSBzb2JyZSBsYXMgYXNvY2lhY2lvbmVzIG3DoXMgZnJlY3VlbnRlcyB5IHB1ZWRlIHNlciBlc2VuY2lhbCBwYXJhIGxhIHRvbWEgZGUgZGVjaXNpb25lcyBlc3RyYXTDqWdpY2FzLg0KVmlzdWFsaXphY2nDs24gZWZlY3RpdmE6DQoNCkxhIGltcGxlbWVudGFjacOzbiBkZSBncsOhZmljb3MgZGUgYmFycmFzIGNvbiBjb2xvcmVzIGRpc3RpbnRpdm9zIGZhY2lsaXRhIGxhIGludGVycHJldGFjacOzbiBkZSBsYSBpbmZvcm1hY2nDs24uIExhIHZpc3VhbGl6YWNpw7NuIGVmZWN0aXZhIGVzIGNydWNpYWwgcGFyYSBjb211bmljYXIgaGFsbGF6Z29zIGRlIG1hbmVyYSBjb21wcmVuc2libGUgYSBsb3Mgc3Rha2Vob2xkZXJzIGRlIGxhIGVtcHJlc2EuDQpGaWx0cmFkbyBkZSBkYXRvcyByZWxldmFudGU6DQoNCkxhIGNhcGFjaWRhZCBkZSBmaWx0cmFyIHkgdHJhYmFqYXIgc29sbyBjb24gbG9zIGRhdG9zIG3DoXMgcmVsZXZhbnRlcywgY29tbyBsYXMgY2luY28gcHJpbmNpcGFsZXMgYWVyb2zDrW5lYXMgcG9yIGRlc3Rpbm8sIGF5dWRhIGEgY29uY2VudHJhcnNlIGVuIGxhIGluZm9ybWFjacOzbiBtw6FzIHNpZ25pZmljYXRpdmEsIHJlZHVjaWVuZG8gZWwgcnVpZG8geSBtZWpvcmFuZG8gbGEgZWZpY2llbmNpYSBkZWwgYW7DoWxpc2lzLg0KDQpFbCBjw7NkaWdvIHB1ZWRlIHNlciB1bmEgaGVycmFtaWVudGEgdmFsaW9zYSBwYXJhIGxhIGVtcHJlc2EgZW4gdMOpcm1pbm9zIGRlIHRvbWEgZGUgZGVjaXNpb25lcyBlc3RyYXTDqWdpY2FzLiBQcm9wb3JjaW9uYSBpbnNpZ2h0cyBzb2JyZSBsYXMgcmVsYWNpb25lcyBjbGF2ZSBlbnRyZSBhZXJvbMOtbmVhcyB5IGRlc3Rpbm9zLCBsbyBxdWUgcHVlZGUgaW5mbHVpciBlbiBsYSBwbGFuaWZpY2FjacOzbiBkZSBydXRhcywgYXNvY2lhY2lvbmVzIGVzdHJhdMOpZ2ljYXMgeSBlc3RyYXRlZ2lhcyBkZSBtYXJrZXRpbmcuIEFkZW3DoXMsIGxhIGF0ZW5jacOzbiBhIGxhIMOpdGljYSB5IGxhIGludGVncmlkYWQgZW4gZWwgbWFuZWpvIGRlIGRhdG9zIHJlZnVlcnphIGxhIGNvbmZpYW56YSBkZWwgY2xpZW50ZSB5IGxhIHJlcHV0YWNpw7NuIGRlIGxhIGVtcHJlc2EuDQoNCg0KDQoNCg0KDQoNCg0K