This analysis was created as a self-selected case study for the Google Data Analytics Certificate. The data from this case study was found on Kaggle, was posted by Akul Bahl, and is originally from the US Department of Transportation https://www.kaggle.com/akulbahl/covid19-airline-flight-delays-and-cancellations/metadata. The purpose of this script is to reduce the data size (to make it compatible with the free version of rstudio), clean the data, and then answer the question: “Which airline has the most reliable flights to and from Austin?”

Step 1: Load required packages

library(tidyverse)
library(readr)
library(lubridate)
library(dplyr)
library(ggplot2)
library(viridis)
library(ggridges)

Step 2: Select potentially useful columns from original dataset

The following was completed in a Kaggle notebook.

This code creates a subset of the original dataset from https://www.kaggle.com/akulbahl/covid19-airline-flight-delays-and-cancellations/metadata of the columns I might likely use for my data analysis.

  1. library(tidyverse)

// metapackage of all tidyverse packages

  1. flight_data <- read_csv(“../input/covid19-airline-flight-delays-and-cancellations/jantojun2020.csv”)

  2. library(readr)

  3. colnames(flight_data)

  4. flight_data_v2 <- select(flight_data, FL_DATE, MKT_UNIQUE_CARRIER, ORIGIN_CITY_NAME, DEST_STATE_ABR, DEST_CITY_NAME, DEP_DELAY, CANCELLED)

  5. head(flight_data_v2)

//Checked to ensure correct columns with corresponding values were selected

  1. colnames(flight_data_v2)

// The columns selected to export and double-checked with colnames() were FL_DATE, MKT_UNIQUE_CARRIER, ORIGIN_CITY_NAME, DEST_STATE_ABR, DEST_CITY_NAME, DEP_DELAY, CANCELLED

  1. flight_data_v2 <- filter(flight_data_v2, ORIGIN_CITY_NAME == “Austin, TX” | DEST_CITY_NAME == “Austin, TX”)

//I was only interested in flights leaving Austin or returning to Austin for this case study.

  1. write.csv(flight_data_v2, “flight_data_v2.csv”, row.names = F)

// This creates the new csv file that I downloaded to my computer and uploaded to RStudio.

Step 3: Import Data to RStudio

flight_data_v2 <- read_csv("Flight_Data_Kaggle/flight_data_v2.csv")
Rows: 45280 Columns: 7
── Column specification ─────────────────────────────────────
Delimiter: ","
chr (5): FL_DATE, MKT_UNIQUE_CARRIER, ORIGIN_CITY_NAME, D...
dbl (2): DEP_DELAY, CANCELLED

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(flight_data_v2)

Step 4: Clean Data and Prepare for Analysis

#Looks for total number of null values (NA)
sum(is.na(flight_data_v2))
[1] 5196
#Displays rows with nulls. Looks like most are in column DEP_DELAY when a flight was also marked as cancelled.
flight_data_v2[rowSums(is.na(flight_data_v2)) > 0, ]

#This shows that there are no null values outside of DEP_DELAY.
flight_data_v2[rowSums(is.na(flight_data_v2)) > 0 & !is.na(flight_data_v2$DEP_DELAY), ]

#This shows that the only null values in DEP_DELAY occur when the flight was cancelled.
flight_data_v2[sum(is.na(flight_data_v2$DEP_DELAY)) > 0 & isTRUE(flight_data_v2$CANCELLED == 1), ]

#Change FL_DATE from chr (character) to date in format: YYYY-MM-DD
flight_data_v2$FL_DATE = as.Date(flight_data_v2$FL_DATE, "%m/%d/%Y")
head(flight_data_v2)

#Check that all dates are within expected bounds (January, 1st to October 7th, 2020)
if (flight_data_v2$FL_DATE < "2020-01-01" | flight_data_v2$FL_DATE > "2020-10-07") {
  print("There is at least one date out of range.")
  } else {print("No dates are out of range.")}
[1] "No dates are out of range."

Step 5: Descriptive Analysis


grouped_data_by_airline <- flight_data_v2 %>%
  group_by(MKT_UNIQUE_CARRIER) %>%
  summarise(mean_dep_delay = mean(DEP_DELAY, na.rm = TRUE),
            median_dep_delay = median(DEP_DELAY, na.rm = TRUE),
            total_flights_cancelled = sum(CANCELLED),
            total_flights_from_austin = sum(ORIGIN_CITY_NAME == "Austin, TX"),
            total_cancelled_from_austin = sum(CANCELLED & ORIGIN_CITY_NAME == "Austin, TX"),
            total_flights_to_austin = sum(DEST_CITY_NAME == "Austin, TX"),
            total_cancelled_to_austin = sum(CANCELLED & DEST_CITY_NAME == "Austin, TX"),
            total_flights = sum(total_flights_from_austin, total_flights_to_austin),
            extreme_delay_n = sum(DEP_DELAY > 60 & !is.na(DEP_DELAY)),
            moderate_delay_n = sum(DEP_DELAY > 15 & DEP_DELAY <= 60 & !is.na(DEP_DELAY)),
            mild_delay_n = sum(DEP_DELAY > 0 & DEP_DELAY <= 15 & !is.na(DEP_DELAY)))

grouped_data_by_airline <- mutate(grouped_data_by_airline, cancelled = (total_flights_cancelled / total_flights)*100)

grouped_data_by_airline <- mutate(grouped_data_by_airline, extreme_delay =  (extreme_delay_n / total_flights)*100)
  
grouped_data_by_airline <- mutate(grouped_data_by_airline, moderate_delay =  (moderate_delay_n / total_flights)*100)

grouped_data_by_airline <- mutate(grouped_data_by_airline, mild_delay =  (mild_delay_n / total_flights)*100)

grouped_data_by_airline <- mutate(grouped_data_by_airline, on_time =  (100 - (mild_delay_n + moderate_delay_n + extreme_delay_n + total_flights_cancelled) / total_flights*100))

view(grouped_data_by_airline)

Step 6: Graphical Representation

    AA: American Airlines
            AS: Alaska Airlines
            B6: JetBlue
            DL: Delta Air Lines
            F9: Frontier Airlines
            G4: Allegiant Air
            HA: Hawaiian Airlines
            NK: Spirit Airlines
            UA: United Airlines
            WN: Southwest Airlines
            

To determine which airlines were the least reliable, I first looked at the breakdown of flight delays for each airline. For the purposes of analysis, I categorized delays based on their impact to connecting flights/chance of missing planned meetings.

On Time: Flight arrived early or exactly at scheduled time
Mild Delay: Flight is less than 15 minutes late
Moderate Delay: Flight is between 15 and 60 minutes late (inclusive)
Extreme Delay: Flight is more than 60 minutes late
Cancelled: Flight is cancelled

# graph of percent cancelled flights
grouped_data_by_airline$MKT_UNIQUE_CARRIER <- as.factor(grouped_data_by_airline$MKT_UNIQUE_CARRIER)
library(RColorBrewer)

chart_data <- pivot_longer(select(grouped_data_by_airline, c('MKT_UNIQUE_CARRIER', 'cancelled', 'extreme_delay', 'mild_delay', 'moderate_delay', 'on_time', 'total_flights')), cols = c(cancelled, extreme_delay, moderate_delay, mild_delay, on_time), names_to = "Flight_Status", values_to = "Percent")

chart_data$Flight_Status <- as.factor(chart_data$Flight_Status)
chart_data$Flight_Status <- factor(chart_data$Flight_Status, levels = c("cancelled", "extreme_delay", "moderate_delay", "mild_delay", "on_time"))
chart_data$MKT_UNIQUE_CARRIER <- as.factor(chart_data$MKT_UNIQUE_CARRIER)

head(chart_data)

ggplot(chart_data, aes(fill = Flight_Status, y = Percent, x = MKT_UNIQUE_CARRIER)) +
  geom_bar(position = "dodge", stat = "identity") + 
  theme(plot.title = element_text(size = 10)) + 
  ggtitle("Percent of Cancelled, Delayed, On-Time Flights By Airline in Austin") + 
  xlab("Airline")

# This graph shows the breakdown of flights to/from Austin by flight delay status for each airline. 

grouped_data_by_airline %>% 
  ggplot( aes(x = MKT_UNIQUE_CARRIER, y = cancelled, fill = MKT_UNIQUE_CARRIER)) + 
  geom_bar(stat = "identity") +
  ggtitle("Percent of Flights Cancelled Per Airline") +
  xlab("Airline") +
  ylab("Percent of Flights Cancelled") +
  geom_text(aes(label = round(cancelled, digits = 1)), position = position_dodge(width = 0.9), vjust = -0.25) +
  theme(legend.position = "none")


grouped_data_by_airline %>% 
  ggplot( aes(x = MKT_UNIQUE_CARRIER, y = extreme_delay, fill = MKT_UNIQUE_CARRIER)) + 
  geom_bar(stat = "identity") +
  ggtitle("Percent of Flights Extremely Delayed Per Airline") +
  xlab("Airline") +
  ylab("Percent of Flights Extremely Delayed") +
  geom_text(aes(label = round(extreme_delay, digits = 1)), position = position_dodge(width = 0.9), vjust = -0.25) +
  theme(legend.position = "none")


# This graph shows that the airline G4, which is Alliegent Air, is the least reliable.
grouped_data_by_airline %>% 
  ggplot( aes(x = MKT_UNIQUE_CARRIER, y = extreme_delay + cancelled, fill = MKT_UNIQUE_CARRIER)) + 
  geom_bar(stat = "identity") +
  ggtitle("Percent of Flights Cancelled or Extremely Delayed Per Airline") +
  xlab("Airline") +
  ylab("Percent of Flights Cancelled or Extremely Delayed") +
  geom_text(aes(label = round(extreme_delay + cancelled, digits = 1)), position = position_dodge(width = 0.9), vjust = -0.25) +
  theme(legend.position = "none")


grouped_data_by_airline %>% 
  ggplot( aes(x = MKT_UNIQUE_CARRIER, y = moderate_delay, fill = MKT_UNIQUE_CARRIER)) + 
  geom_bar(stat = "identity") +
  ggtitle("Percent of Flights Moderately Delayed Per Airline") +
  xlab("Airline") +
  ylab("Percent of Flights Moderately Delayed (between 15 min. and 1 hour") +
  geom_text(aes(label = round(moderate_delay, digits = 1)), position = position_dodge(width = 0.9), vjust = -0.25) +
  theme(legend.position = "none")


grouped_data_by_airline %>% 
  ggplot( aes(x = MKT_UNIQUE_CARRIER, y = mild_delay, fill = MKT_UNIQUE_CARRIER)) + 
  geom_bar(stat = "identity") +
  ggtitle("Percent of Flights Mildly Delayed (15 min or less) Per Airline") +
  xlab("Airline") +
  ylab("Percent of Flights Mildly Delayed") +
  geom_text(aes(label = round(mild_delay, digits = 1)), position = position_dodge(width = 0.9), vjust = -0.25) +
  theme(legend.position = "none")


grouped_data_by_airline %>% 
  ggplot( aes(x = MKT_UNIQUE_CARRIER, y = on_time, fill = MKT_UNIQUE_CARRIER)) + 
  geom_bar(stat = "identity") +
  ggtitle("Percent of Flights On Time Per Airline") +
  xlab("Airline") +
  ylab("Percent of Flights On Time") +
  geom_text(aes(label = round(on_time, digits = 1)), position = position_dodge(width = 0.9), vjust = -0.25) +
  theme(legend.position = "none")


# This boxplot of delay times per airline shows that airlines typically had about 75% of flights on time. I excluded this graph from my actual analysis because I had to exclude extreme delays for the graph to be readable. 
flight_data_v2 %>% 
  ggplot( aes(x = MKT_UNIQUE_CARRIER, y = DEP_DELAY, fill = MKT_UNIQUE_CARRIER)) +
  geom_boxplot(outlier.shape = NA) + 
  ylim(-20, 15) +
  scale_fill_viridis(discrete = TRUE, alpha = 0.6) + 
  ggtitle("Airline Delay Times") +
  xlab("Airline") + 
  ylab("Delay Time")


# This graph looks at the distribution of delays less than or equal to 1 hour.
delayed_mild_mod <- flight_data_v2[flight_data_v2$DEP_DELAY > 0 & flight_data_v2$DEP_DELAY <= 60, ]
delayed_mild_mod %>% 
  ggplot( aes(x = DEP_DELAY, group = MKT_UNIQUE_CARRIER, fill = MKT_UNIQUE_CARRIER)) +
  geom_density(adjust = 1.5) + 
  facet_wrap(~MKT_UNIQUE_CARRIER) +
  ggtitle("Airline Delay Times") +
  xlab("Airline") + 
  ylab("Delay Time")


# This graph shows the distribution of delays and has quartile lines to better show the distribution of flight delays. Based on this graph, of the mild-moderate delays, WN, which is Southwest Airlines, has the shortest mild-moderate delays.
delayed_mild_mod %>% 
  ggplot( aes(x = DEP_DELAY, y = MKT_UNIQUE_CARRIER, fill = factor(stat(quantile)))) + 
  stat_density_ridges(geom = "density_ridges_gradient", calc_ecdf = TRUE, quantiles = 4, quantile_lines = TRUE) + 
  scale_fill_viridis_d(name = "Quartiles") +
  theme_ridges() + 
  theme(legend.position = "none")
Picking joint bandwidth of 3.78

# Overall, the most reliable airline is NK, which is Spirit Airlines.
grouped_data_by_airline %>% 
  ggplot( aes(x = MKT_UNIQUE_CARRIER, y = on_time + mild_delay, fill = MKT_UNIQUE_CARRIER)) + 
  geom_bar(stat = "identity") +
  ggtitle("Percent of Flights On Time or Delayed Less Than 15 Min") +
  xlab("Airline") +
  ylab("Percent of Flights On Time or Mildly Delayed") +
  geom_text(aes(label = round(on_time + mild_delay, digits = 1)), position = position_dodge(width = 0.9), vjust = -0.25) +
  theme(legend.position = "none")

LS0tCnRpdGxlOiBGbGlnaHRzX0Zyb21fQXVzdGluCm91dHB1dDogaHRtbF9ub3RlYm9vawpkYXRlOiAyLzcvMjAyMgphdXRob3I6IE1hbG9yeSBXb2RrYQotLS0KClRoaXMgYW5hbHlzaXMgd2FzIGNyZWF0ZWQgYXMgYSBzZWxmLXNlbGVjdGVkIGNhc2Ugc3R1ZHkgZm9yIHRoZSBHb29nbGUgRGF0YSBBbmFseXRpY3MgQ2VydGlmaWNhdGUuIFRoZSBkYXRhIGZyb20gdGhpcyBjYXNlIHN0dWR5IHdhcyBmb3VuZCBvbiBLYWdnbGUsIHdhcyBwb3N0ZWQgYnkgQWt1bCBCYWhsLCBhbmQgaXMgb3JpZ2luYWxseSBmcm9tIHRoZSBVUyBEZXBhcnRtZW50IG9mIFRyYW5zcG9ydGF0aW9uIDxodHRwczovL3d3dy5rYWdnbGUuY29tL2FrdWxiYWhsL2NvdmlkMTktYWlybGluZS1mbGlnaHQtZGVsYXlzLWFuZC1jYW5jZWxsYXRpb25zL21ldGFkYXRhPi4gVGhlIHB1cnBvc2Ugb2YgdGhpcyBzY3JpcHQgaXMgdG8gcmVkdWNlIHRoZSBkYXRhIHNpemUgKHRvIG1ha2UgaXQgY29tcGF0aWJsZSB3aXRoIHRoZSBmcmVlIHZlcnNpb24gb2YgcnN0dWRpbyksIGNsZWFuIHRoZSBkYXRhLCBhbmQgdGhlbiBhbnN3ZXIgdGhlIHF1ZXN0aW9uOiAiV2hpY2ggYWlybGluZSBoYXMgdGhlIG1vc3QgcmVsaWFibGUgZmxpZ2h0cyB0byBhbmQgZnJvbSBBdXN0aW4/IiAKCiMgU3RlcCAxOiBMb2FkIHJlcXVpcmVkIHBhY2thZ2VzCiogdGlkeXZlcnNlIGZvciBkYXRhIHdyYW5nbGluZwoqIHJlYWRyIGZvciBsb2FkaW5nIGNzdiBmaWxlCiogbHVicmlkYXRlIGZvciB0aW1lIGZ1bmN0aW9ucwoqIGRwbHlyIGZvciBkYXRhIHRyYW5zZm9ybWF0aW9uCiogZ2dwbG90MiwgdmlyaWRpcywgYW5kIGdncmlkZ2VzIGZvciBncmFwaGluZwoKYGBge3IgU3RlcCAxLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkcikKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh2aXJpZGlzKQpsaWJyYXJ5KGdncmlkZ2VzKQpgYGAKCiMgU3RlcCAyOiBTZWxlY3QgcG90ZW50aWFsbHkgdXNlZnVsIGNvbHVtbnMgZnJvbSBvcmlnaW5hbCBkYXRhc2V0CiogVGhlIG9yaWdpbmFsIGRhdGFzZXQgd2FzIHRvbyBsYXJnZSBmb3IgdGhlIGZyZWUgdmVyc2lvbiBvZiByc3R1ZGlvIHRvIGhhbmRsZSB3aXRob3V0IGNyYXNoaW5nLCBzbyBJIHNlbGVjdGVkIHRoZSBjb2x1bW5zICh1c2luZyBLYWdnbGUpIHRvIGV4cG9ydCB0aGUgc21hbGxlciBkYXRhc2V0ICdmbGlnaHRfZGF0YV92MicuCgpUaGUgZm9sbG93aW5nIHdhcyBjb21wbGV0ZWQgaW4gYSBLYWdnbGUgbm90ZWJvb2suCi0tLS0tClRoaXMgY29kZSBjcmVhdGVzIGEgc3Vic2V0IG9mIHRoZSBvcmlnaW5hbCBkYXRhc2V0IGZyb20gPGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vYWt1bGJhaGwvY292aWQxOS1haXJsaW5lLWZsaWdodC1kZWxheXMtYW5kLWNhbmNlbGxhdGlvbnMvbWV0YWRhdGE+IG9mIHRoZSBjb2x1bW5zIEkgbWlnaHQgbGlrZWx5IHVzZSBmb3IgbXkgZGF0YSBhbmFseXNpcy4KCjEuIGxpYnJhcnkodGlkeXZlcnNlKSAKCiAvLyBtZXRhcGFja2FnZSBvZiBhbGwgdGlkeXZlcnNlIHBhY2thZ2VzCgoyLiBmbGlnaHRfZGF0YSA8LSByZWFkX2NzdigiLi4vaW5wdXQvY292aWQxOS1haXJsaW5lLWZsaWdodC1kZWxheXMtYW5kLWNhbmNlbGxhdGlvbnMvamFudG9qdW4yMDIwLmNzdiIpCgozLiBsaWJyYXJ5KHJlYWRyKQoKNC4gY29sbmFtZXMoZmxpZ2h0X2RhdGEpCgo1LiBmbGlnaHRfZGF0YV92MiA8LSBzZWxlY3QoZmxpZ2h0X2RhdGEsIEZMX0RBVEUsIE1LVF9VTklRVUVfQ0FSUklFUiwgIE9SSUdJTl9DSVRZX05BTUUsIERFU1RfU1RBVEVfQUJSLCBERVNUX0NJVFlfTkFNRSwgREVQX0RFTEFZLCBDQU5DRUxMRUQpCgo2LiBoZWFkKGZsaWdodF9kYXRhX3YyKQoKLy9DaGVja2VkIHRvIGVuc3VyZSBjb3JyZWN0IGNvbHVtbnMgd2l0aCBjb3JyZXNwb25kaW5nIHZhbHVlcyB3ZXJlIHNlbGVjdGVkCgo3LiBjb2xuYW1lcyhmbGlnaHRfZGF0YV92MikKCi8vIFRoZSBjb2x1bW5zIHNlbGVjdGVkIHRvIGV4cG9ydCBhbmQgZG91YmxlLWNoZWNrZWQgd2l0aCBjb2xuYW1lcygpIHdlcmUgRkxfREFURSwgTUtUX1VOSVFVRV9DQVJSSUVSLCBPUklHSU5fQ0lUWV9OQU1FLCBERVNUX1NUQVRFX0FCUiwgREVTVF9DSVRZX05BTUUsIERFUF9ERUxBWSwgQ0FOQ0VMTEVECgo4LiBmbGlnaHRfZGF0YV92MiA8LSBmaWx0ZXIoZmxpZ2h0X2RhdGFfdjIsIE9SSUdJTl9DSVRZX05BTUUgPT0gIkF1c3RpbiwgVFgiIHwgREVTVF9DSVRZX05BTUUgPT0gIkF1c3RpbiwgVFgiKQoKLy9JIHdhcyBvbmx5IGludGVyZXN0ZWQgaW4gZmxpZ2h0cyBsZWF2aW5nIEF1c3RpbiBvciByZXR1cm5pbmcgdG8gQXVzdGluIGZvciB0aGlzIGNhc2Ugc3R1ZHkuCgo5LiB3cml0ZS5jc3YoZmxpZ2h0X2RhdGFfdjIsICJmbGlnaHRfZGF0YV92Mi5jc3YiLCByb3cubmFtZXMgPSBGKQoKLy8gVGhpcyBjcmVhdGVzIHRoZSBuZXcgY3N2IGZpbGUgdGhhdCBJIGRvd25sb2FkZWQgdG8gbXkgY29tcHV0ZXIgYW5kIHVwbG9hZGVkIHRvIFJTdHVkaW8uCgojIFN0ZXAgMzogSW1wb3J0IERhdGEgdG8gUlN0dWRpbwoKYGBge3IgU3RlcCAzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpmbGlnaHRfZGF0YV92MiA8LSByZWFkX2NzdigiRmxpZ2h0X0RhdGFfS2FnZ2xlL2ZsaWdodF9kYXRhX3YyLmNzdiIpCmhlYWQoZmxpZ2h0X2RhdGFfdjIpCmBgYAoKIyBTdGVwIDQ6IENsZWFuIERhdGEgYW5kIFByZXBhcmUgZm9yIEFuYWx5c2lzCgpgYGB7ciBTdGVwIDQ6IERhdGEgQ2xlYW5pbmcsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiNMb29rcyBmb3IgdG90YWwgbnVtYmVyIG9mIG51bGwgdmFsdWVzIChOQSkKc3VtKGlzLm5hKGZsaWdodF9kYXRhX3YyKSkKCiNEaXNwbGF5cyByb3dzIHdpdGggbnVsbHMuIExvb2tzIGxpa2UgbW9zdCBhcmUgaW4gY29sdW1uIERFUF9ERUxBWSB3aGVuIGEgZmxpZ2h0IHdhcyBhbHNvIG1hcmtlZCBhcyBjYW5jZWxsZWQuCmZsaWdodF9kYXRhX3YyW3Jvd1N1bXMoaXMubmEoZmxpZ2h0X2RhdGFfdjIpKSA+IDAsIF0KCiNUaGlzIHNob3dzIHRoYXQgdGhlcmUgYXJlIG5vIG51bGwgdmFsdWVzIG91dHNpZGUgb2YgREVQX0RFTEFZLgpmbGlnaHRfZGF0YV92Mltyb3dTdW1zKGlzLm5hKGZsaWdodF9kYXRhX3YyKSkgPiAwICYgIWlzLm5hKGZsaWdodF9kYXRhX3YyJERFUF9ERUxBWSksIF0KCiNUaGlzIHNob3dzIHRoYXQgdGhlIG9ubHkgbnVsbCB2YWx1ZXMgaW4gREVQX0RFTEFZIG9jY3VyIHdoZW4gdGhlIGZsaWdodCB3YXMgY2FuY2VsbGVkLgpmbGlnaHRfZGF0YV92MltzdW0oaXMubmEoZmxpZ2h0X2RhdGFfdjIkREVQX0RFTEFZKSkgPiAwICYgaXNUUlVFKGZsaWdodF9kYXRhX3YyJENBTkNFTExFRCA9PSAxKSwgXQoKI0NoYW5nZSBGTF9EQVRFIGZyb20gY2hyIChjaGFyYWN0ZXIpIHRvIGRhdGUgaW4gZm9ybWF0OiBZWVlZLU1NLURECmZsaWdodF9kYXRhX3YyJEZMX0RBVEUgPSBhcy5EYXRlKGZsaWdodF9kYXRhX3YyJEZMX0RBVEUsICIlbS8lZC8lWSIpCmhlYWQoZmxpZ2h0X2RhdGFfdjIpCgojQ2hlY2sgdGhhdCBhbGwgZGF0ZXMgYXJlIHdpdGhpbiBleHBlY3RlZCBib3VuZHMgKEphbnVhcnksIDFzdCB0byBPY3RvYmVyIDd0aCwgMjAyMCkKaWYgKGZsaWdodF9kYXRhX3YyJEZMX0RBVEUgPCAiMjAyMC0wMS0wMSIgfCBmbGlnaHRfZGF0YV92MiRGTF9EQVRFID4gIjIwMjAtMTAtMDciKSB7CiAgcHJpbnQoIlRoZXJlIGlzIGF0IGxlYXN0IG9uZSBkYXRlIG91dCBvZiByYW5nZS4iKQogIH0gZWxzZSB7cHJpbnQoIk5vIGRhdGVzIGFyZSBvdXQgb2YgcmFuZ2UuIil9CgpgYGAKIyBTdGVwIDU6IERlc2NyaXB0aXZlIEFuYWx5c2lzCgpgYGB7ciBTdGVwIDU6IERlc2NyaXB0aXZlIEFuYWx5c2lzLCBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9Cgpncm91cGVkX2RhdGFfYnlfYWlybGluZSA8LSBmbGlnaHRfZGF0YV92MiAlPiUKICBncm91cF9ieShNS1RfVU5JUVVFX0NBUlJJRVIpICU+JQogIHN1bW1hcmlzZShtZWFuX2RlcF9kZWxheSA9IG1lYW4oREVQX0RFTEFZLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBtZWRpYW5fZGVwX2RlbGF5ID0gbWVkaWFuKERFUF9ERUxBWSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgdG90YWxfZmxpZ2h0c19jYW5jZWxsZWQgPSBzdW0oQ0FOQ0VMTEVEKSwKICAgICAgICAgICAgdG90YWxfZmxpZ2h0c19mcm9tX2F1c3RpbiA9IHN1bShPUklHSU5fQ0lUWV9OQU1FID09ICJBdXN0aW4sIFRYIiksCiAgICAgICAgICAgIHRvdGFsX2NhbmNlbGxlZF9mcm9tX2F1c3RpbiA9IHN1bShDQU5DRUxMRUQgJiBPUklHSU5fQ0lUWV9OQU1FID09ICJBdXN0aW4sIFRYIiksCiAgICAgICAgICAgIHRvdGFsX2ZsaWdodHNfdG9fYXVzdGluID0gc3VtKERFU1RfQ0lUWV9OQU1FID09ICJBdXN0aW4sIFRYIiksCiAgICAgICAgICAgIHRvdGFsX2NhbmNlbGxlZF90b19hdXN0aW4gPSBzdW0oQ0FOQ0VMTEVEICYgREVTVF9DSVRZX05BTUUgPT0gIkF1c3RpbiwgVFgiKSwKICAgICAgICAgICAgdG90YWxfZmxpZ2h0cyA9IHN1bSh0b3RhbF9mbGlnaHRzX2Zyb21fYXVzdGluLCB0b3RhbF9mbGlnaHRzX3RvX2F1c3RpbiksCiAgICAgICAgICAgIGV4dHJlbWVfZGVsYXlfbiA9IHN1bShERVBfREVMQVkgPiA2MCAmICFpcy5uYShERVBfREVMQVkpKSwKICAgICAgICAgICAgbW9kZXJhdGVfZGVsYXlfbiA9IHN1bShERVBfREVMQVkgPiAxNSAmIERFUF9ERUxBWSA8PSA2MCAmICFpcy5uYShERVBfREVMQVkpKSwKICAgICAgICAgICAgbWlsZF9kZWxheV9uID0gc3VtKERFUF9ERUxBWSA+IDAgJiBERVBfREVMQVkgPD0gMTUgJiAhaXMubmEoREVQX0RFTEFZKSkpCgpncm91cGVkX2RhdGFfYnlfYWlybGluZSA8LSBtdXRhdGUoZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUsIGNhbmNlbGxlZCA9ICh0b3RhbF9mbGlnaHRzX2NhbmNlbGxlZCAvIHRvdGFsX2ZsaWdodHMpKjEwMCkKCmdyb3VwZWRfZGF0YV9ieV9haXJsaW5lIDwtIG11dGF0ZShncm91cGVkX2RhdGFfYnlfYWlybGluZSwgZXh0cmVtZV9kZWxheSA9ICAoZXh0cmVtZV9kZWxheV9uIC8gdG90YWxfZmxpZ2h0cykqMTAwKQogIApncm91cGVkX2RhdGFfYnlfYWlybGluZSA8LSBtdXRhdGUoZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUsIG1vZGVyYXRlX2RlbGF5ID0gIChtb2RlcmF0ZV9kZWxheV9uIC8gdG90YWxfZmxpZ2h0cykqMTAwKQoKZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUgPC0gbXV0YXRlKGdyb3VwZWRfZGF0YV9ieV9haXJsaW5lLCBtaWxkX2RlbGF5ID0gIChtaWxkX2RlbGF5X24gLyB0b3RhbF9mbGlnaHRzKSoxMDApCgpncm91cGVkX2RhdGFfYnlfYWlybGluZSA8LSBtdXRhdGUoZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUsIG9uX3RpbWUgPSAgKDEwMCAtIChtaWxkX2RlbGF5X24gKyBtb2RlcmF0ZV9kZWxheV9uICsgZXh0cmVtZV9kZWxheV9uICsgdG90YWxfZmxpZ2h0c19jYW5jZWxsZWQpIC8gdG90YWxfZmxpZ2h0cyoxMDApKQoKdmlldyhncm91cGVkX2RhdGFfYnlfYWlybGluZSkKCmBgYAoKIyBTdGVwIDY6IEdyYXBoaWNhbCBSZXByZXNlbnRhdGlvbgoKICAgICAgICBBQTogQW1lcmljYW4gQWlybGluZXMKCQkJCUFTOiBBbGFza2EgQWlybGluZXMKCQkJCUI2OiBKZXRCbHVlCgkJCQlETDogRGVsdGEgQWlyIExpbmVzCgkJCQlGOTogRnJvbnRpZXIgQWlybGluZXMKCQkJCUc0OiBBbGxlZ2lhbnQgQWlyCgkJCQlIQTogSGF3YWlpYW4gQWlybGluZXMKCQkJCU5LOiBTcGlyaXQgQWlybGluZXMKCQkJCVVBOiBVbml0ZWQgQWlybGluZXMKCQkJCVdOOiBTb3V0aHdlc3QgQWlybGluZXMKCQkJCQpUbyBkZXRlcm1pbmUgd2hpY2ggYWlybGluZXMgd2VyZSB0aGUgbGVhc3QgcmVsaWFibGUsIEkgZmlyc3QgbG9va2VkIGF0IHRoZSBicmVha2Rvd24gb2YgZmxpZ2h0IGRlbGF5cyBmb3IgZWFjaCBhaXJsaW5lLiBGb3IgdGhlIHB1cnBvc2VzIG9mIGFuYWx5c2lzLCBJIGNhdGVnb3JpemVkIGRlbGF5cyBiYXNlZCBvbiB0aGVpciBpbXBhY3QgdG8gY29ubmVjdGluZyBmbGlnaHRzL2NoYW5jZSBvZiBtaXNzaW5nIHBsYW5uZWQgbWVldGluZ3MuIAoKICAgIE9uIFRpbWU6IEZsaWdodCBhcnJpdmVkIGVhcmx5IG9yIGV4YWN0bHkgYXQgc2NoZWR1bGVkIHRpbWUKICAgIE1pbGQgRGVsYXk6IEZsaWdodCBpcyBsZXNzIHRoYW4gMTUgbWludXRlcyBsYXRlCiAgICBNb2RlcmF0ZSBEZWxheTogRmxpZ2h0IGlzIGJldHdlZW4gMTUgYW5kIDYwIG1pbnV0ZXMgbGF0ZSAoaW5jbHVzaXZlKQogICAgRXh0cmVtZSBEZWxheTogRmxpZ2h0IGlzIG1vcmUgdGhhbiA2MCBtaW51dGVzIGxhdGUKICAgIENhbmNlbGxlZDogRmxpZ2h0IGlzIGNhbmNlbGxlZApgYGB7ciBTdGVwIDY6IEdyYXBoaWNhbCBSZXByZXNlbnRhdGlvbiwgZWNobz1UUlVFLCBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9CgojIGdyYXBoIG9mIHBlcmNlbnQgY2FuY2VsbGVkIGZsaWdodHMKZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUkTUtUX1VOSVFVRV9DQVJSSUVSIDwtIGFzLmZhY3Rvcihncm91cGVkX2RhdGFfYnlfYWlybGluZSRNS1RfVU5JUVVFX0NBUlJJRVIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQoKY2hhcnRfZGF0YSA8LSBwaXZvdF9sb25nZXIoc2VsZWN0KGdyb3VwZWRfZGF0YV9ieV9haXJsaW5lLCBjKCdNS1RfVU5JUVVFX0NBUlJJRVInLCAnY2FuY2VsbGVkJywgJ2V4dHJlbWVfZGVsYXknLCAnbWlsZF9kZWxheScsICdtb2RlcmF0ZV9kZWxheScsICdvbl90aW1lJywgJ3RvdGFsX2ZsaWdodHMnKSksIGNvbHMgPSBjKGNhbmNlbGxlZCwgZXh0cmVtZV9kZWxheSwgbW9kZXJhdGVfZGVsYXksIG1pbGRfZGVsYXksIG9uX3RpbWUpLCBuYW1lc190byA9ICJGbGlnaHRfU3RhdHVzIiwgdmFsdWVzX3RvID0gIlBlcmNlbnQiKQoKY2hhcnRfZGF0YSRGbGlnaHRfU3RhdHVzIDwtIGFzLmZhY3RvcihjaGFydF9kYXRhJEZsaWdodF9TdGF0dXMpCmNoYXJ0X2RhdGEkRmxpZ2h0X1N0YXR1cyA8LSBmYWN0b3IoY2hhcnRfZGF0YSRGbGlnaHRfU3RhdHVzLCBsZXZlbHMgPSBjKCJjYW5jZWxsZWQiLCAiZXh0cmVtZV9kZWxheSIsICJtb2RlcmF0ZV9kZWxheSIsICJtaWxkX2RlbGF5IiwgIm9uX3RpbWUiKSkKY2hhcnRfZGF0YSRNS1RfVU5JUVVFX0NBUlJJRVIgPC0gYXMuZmFjdG9yKGNoYXJ0X2RhdGEkTUtUX1VOSVFVRV9DQVJSSUVSKQoKaGVhZChjaGFydF9kYXRhKQoKZ2dwbG90KGNoYXJ0X2RhdGEsIGFlcyhmaWxsID0gRmxpZ2h0X1N0YXR1cywgeSA9IFBlcmNlbnQsIHggPSBNS1RfVU5JUVVFX0NBUlJJRVIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsgCiAgZ2d0aXRsZSgiUGVyY2VudCBvZiBDYW5jZWxsZWQsIERlbGF5ZWQsIE9uLVRpbWUgRmxpZ2h0cyBCeSBBaXJsaW5lIGluIEF1c3RpbiIpICsgCiAgeGxhYigiQWlybGluZSIpCiMgVGhpcyBncmFwaCBzaG93cyB0aGUgYnJlYWtkb3duIG9mIGZsaWdodHMgdG8vZnJvbSBBdXN0aW4gYnkgZmxpZ2h0IGRlbGF5IHN0YXR1cyBmb3IgZWFjaCBhaXJsaW5lLiAKCmdyb3VwZWRfZGF0YV9ieV9haXJsaW5lICU+JSAKICBnZ3Bsb3QoIGFlcyh4ID0gTUtUX1VOSVFVRV9DQVJSSUVSLCB5ID0gY2FuY2VsbGVkLCBmaWxsID0gTUtUX1VOSVFVRV9DQVJSSUVSKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBlcmNlbnQgb2YgRmxpZ2h0cyBDYW5jZWxsZWQgUGVyIEFpcmxpbmUiKSArCiAgeGxhYigiQWlybGluZSIpICsKICB5bGFiKCJQZXJjZW50IG9mIEZsaWdodHMgQ2FuY2VsbGVkIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChjYW5jZWxsZWQsIGRpZ2l0cyA9IDEpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIHZqdXN0ID0gLTAuMjUpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpncm91cGVkX2RhdGFfYnlfYWlybGluZSAlPiUgCiAgZ2dwbG90KCBhZXMoeCA9IE1LVF9VTklRVUVfQ0FSUklFUiwgeSA9IGV4dHJlbWVfZGVsYXksIGZpbGwgPSBNS1RfVU5JUVVFX0NBUlJJRVIpKSArIAogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2d0aXRsZSgiUGVyY2VudCBvZiBGbGlnaHRzIEV4dHJlbWVseSBEZWxheWVkIFBlciBBaXJsaW5lIikgKwogIHhsYWIoIkFpcmxpbmUiKSArCiAgeWxhYigiUGVyY2VudCBvZiBGbGlnaHRzIEV4dHJlbWVseSBEZWxheWVkIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChleHRyZW1lX2RlbGF5LCBkaWdpdHMgPSAxKSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCB2anVzdCA9IC0wLjI1KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKIyBUaGlzIGdyYXBoIHNob3dzIHRoYXQgdGhlIGFpcmxpbmUgRzQsIHdoaWNoIGlzIEFsbGllZ2VudCBBaXIsIGlzIHRoZSBsZWFzdCByZWxpYWJsZS4KZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUgJT4lIAogIGdncGxvdCggYWVzKHggPSBNS1RfVU5JUVVFX0NBUlJJRVIsIHkgPSBleHRyZW1lX2RlbGF5ICsgY2FuY2VsbGVkLCBmaWxsID0gTUtUX1VOSVFVRV9DQVJSSUVSKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBlcmNlbnQgb2YgRmxpZ2h0cyBDYW5jZWxsZWQgb3IgRXh0cmVtZWx5IERlbGF5ZWQgUGVyIEFpcmxpbmUiKSArCiAgeGxhYigiQWlybGluZSIpICsKICB5bGFiKCJQZXJjZW50IG9mIEZsaWdodHMgQ2FuY2VsbGVkIG9yIEV4dHJlbWVseSBEZWxheWVkIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChleHRyZW1lX2RlbGF5ICsgY2FuY2VsbGVkLCBkaWdpdHMgPSAxKSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCB2anVzdCA9IC0wLjI1KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUgJT4lIAogIGdncGxvdCggYWVzKHggPSBNS1RfVU5JUVVFX0NBUlJJRVIsIHkgPSBtb2RlcmF0ZV9kZWxheSwgZmlsbCA9IE1LVF9VTklRVUVfQ0FSUklFUikpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZ3RpdGxlKCJQZXJjZW50IG9mIEZsaWdodHMgTW9kZXJhdGVseSBEZWxheWVkIFBlciBBaXJsaW5lIikgKwogIHhsYWIoIkFpcmxpbmUiKSArCiAgeWxhYigiUGVyY2VudCBvZiBGbGlnaHRzIE1vZGVyYXRlbHkgRGVsYXllZCAoYmV0d2VlbiAxNSBtaW4uIGFuZCAxIGhvdXIiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG1vZGVyYXRlX2RlbGF5LCBkaWdpdHMgPSAxKSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCB2anVzdCA9IC0wLjI1KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUgJT4lIAogIGdncGxvdCggYWVzKHggPSBNS1RfVU5JUVVFX0NBUlJJRVIsIHkgPSBtaWxkX2RlbGF5LCBmaWxsID0gTUtUX1VOSVFVRV9DQVJSSUVSKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBlcmNlbnQgb2YgRmxpZ2h0cyBNaWxkbHkgRGVsYXllZCAoMTUgbWluIG9yIGxlc3MpIFBlciBBaXJsaW5lIikgKwogIHhsYWIoIkFpcmxpbmUiKSArCiAgeWxhYigiUGVyY2VudCBvZiBGbGlnaHRzIE1pbGRseSBEZWxheWVkIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtaWxkX2RlbGF5LCBkaWdpdHMgPSAxKSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCB2anVzdCA9IC0wLjI1KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZ3JvdXBlZF9kYXRhX2J5X2FpcmxpbmUgJT4lIAogIGdncGxvdCggYWVzKHggPSBNS1RfVU5JUVVFX0NBUlJJRVIsIHkgPSBvbl90aW1lLCBmaWxsID0gTUtUX1VOSVFVRV9DQVJSSUVSKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBlcmNlbnQgb2YgRmxpZ2h0cyBPbiBUaW1lIFBlciBBaXJsaW5lIikgKwogIHhsYWIoIkFpcmxpbmUiKSArCiAgeWxhYigiUGVyY2VudCBvZiBGbGlnaHRzIE9uIFRpbWUiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG9uX3RpbWUsIGRpZ2l0cyA9IDEpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIHZqdXN0ID0gLTAuMjUpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgojIFRoaXMgYm94cGxvdCBvZiBkZWxheSB0aW1lcyBwZXIgYWlybGluZSBzaG93cyB0aGF0IGFpcmxpbmVzIHR5cGljYWxseSBoYWQgYWJvdXQgNzUlIG9mIGZsaWdodHMgb24gdGltZS4gSSBleGNsdWRlZCB0aGlzIGdyYXBoIGZyb20gbXkgYWN0dWFsIGFuYWx5c2lzIGJlY2F1c2UgSSBoYWQgdG8gZXhjbHVkZSBleHRyZW1lIGRlbGF5cyBmb3IgdGhlIGdyYXBoIHRvIGJlIHJlYWRhYmxlLiAKZmxpZ2h0X2RhdGFfdjIgJT4lIAogIGdncGxvdCggYWVzKHggPSBNS1RfVU5JUVVFX0NBUlJJRVIsIHkgPSBERVBfREVMQVksIGZpbGwgPSBNS1RfVU5JUVVFX0NBUlJJRVIpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKyAKICB5bGltKC0yMCwgMTUpICsKICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBUUlVFLCBhbHBoYSA9IDAuNikgKyAKICBnZ3RpdGxlKCJBaXJsaW5lIERlbGF5IFRpbWVzIikgKwogIHhsYWIoIkFpcmxpbmUiKSArIAogIHlsYWIoIkRlbGF5IFRpbWUiKQoKIyBUaGlzIGdyYXBoIGxvb2tzIGF0IHRoZSBkaXN0cmlidXRpb24gb2YgZGVsYXlzIGxlc3MgdGhhbiBvciBlcXVhbCB0byAxIGhvdXIuCmRlbGF5ZWRfbWlsZF9tb2QgPC0gZmxpZ2h0X2RhdGFfdjJbZmxpZ2h0X2RhdGFfdjIkREVQX0RFTEFZID4gMCAmIGZsaWdodF9kYXRhX3YyJERFUF9ERUxBWSA8PSA2MCwgXQpkZWxheWVkX21pbGRfbW9kICU+JSAKICBnZ3Bsb3QoIGFlcyh4ID0gREVQX0RFTEFZLCBncm91cCA9IE1LVF9VTklRVUVfQ0FSUklFUiwgZmlsbCA9IE1LVF9VTklRVUVfQ0FSUklFUikpICsKICBnZW9tX2RlbnNpdHkoYWRqdXN0ID0gMS41KSArIAogIGZhY2V0X3dyYXAofk1LVF9VTklRVUVfQ0FSUklFUikgKwogIGdndGl0bGUoIkFpcmxpbmUgRGVsYXkgVGltZXMiKSArCiAgeGxhYigiQWlybGluZSIpICsgCiAgeWxhYigiRGVsYXkgVGltZSIpCgojIFRoaXMgZ3JhcGggc2hvd3MgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkZWxheXMgYW5kIGhhcyBxdWFydGlsZSBsaW5lcyB0byBiZXR0ZXIgc2hvdyB0aGUgZGlzdHJpYnV0aW9uIG9mIGZsaWdodCBkZWxheXMuIEJhc2VkIG9uIHRoaXMgZ3JhcGgsIG9mIHRoZSBtaWxkLW1vZGVyYXRlIGRlbGF5cywgV04sIHdoaWNoIGlzIFNvdXRod2VzdCBBaXJsaW5lcywgaGFzIHRoZSBzaG9ydGVzdCBtaWxkLW1vZGVyYXRlIGRlbGF5cy4KZGVsYXllZF9taWxkX21vZCAlPiUgCiAgZ2dwbG90KCBhZXMoeCA9IERFUF9ERUxBWSwgeSA9IE1LVF9VTklRVUVfQ0FSUklFUiwgZmlsbCA9IGZhY3RvcihzdGF0KHF1YW50aWxlKSkpKSArIAogIHN0YXRfZGVuc2l0eV9yaWRnZXMoZ2VvbSA9ICJkZW5zaXR5X3JpZGdlc19ncmFkaWVudCIsIGNhbGNfZWNkZiA9IFRSVUUsIHF1YW50aWxlcyA9IDQsIHF1YW50aWxlX2xpbmVzID0gVFJVRSkgKyAKICBzY2FsZV9maWxsX3ZpcmlkaXNfZChuYW1lID0gIlF1YXJ0aWxlcyIpICsKICB0aGVtZV9yaWRnZXMoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiMgT3ZlcmFsbCwgdGhlIG1vc3QgcmVsaWFibGUgYWlybGluZSBpcyBOSywgd2hpY2ggaXMgU3Bpcml0IEFpcmxpbmVzLgpncm91cGVkX2RhdGFfYnlfYWlybGluZSAlPiUgCiAgZ2dwbG90KCBhZXMoeCA9IE1LVF9VTklRVUVfQ0FSUklFUiwgeSA9IG9uX3RpbWUgKyBtaWxkX2RlbGF5LCBmaWxsID0gTUtUX1VOSVFVRV9DQVJSSUVSKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBlcmNlbnQgb2YgRmxpZ2h0cyBPbiBUaW1lIG9yIERlbGF5ZWQgTGVzcyBUaGFuIDE1IE1pbiIpICsKICB4bGFiKCJBaXJsaW5lIikgKwogIHlsYWIoIlBlcmNlbnQgb2YgRmxpZ2h0cyBPbiBUaW1lIG9yIE1pbGRseSBEZWxheWVkIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChvbl90aW1lICsgbWlsZF9kZWxheSwgZGlnaXRzID0gMSkpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwgdmp1c3QgPSAtMC4yNSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmBgYAoK