1 Introduction

The book “Applied Analytics Through Case Studies Using SAS and R: Implementing Predictive Models and Machine Learning Techniques” is a guide book for statisticians, data analysts, and others who are interested in trying to learn/transition into data science. The book, authored by Deepti Gupta, use case studies to explore how to answer various business questions using statistical and machine learning methods using programming platforms SAS and R.

One of those case studies involves predicting flight delays based on several factors. In the book, Gupta uses statistical learning methods to analyze the data and determine which factors influence how long a flight a will be delayed for. For this project, the goal is to use data visualization and regression methods to determine which factors are influential to flight delays.

The data set that will be used for this analysis will be the same one used in the case study. The data set was downloaded from a data set repository and uploaded to Github. Analysis for this report will be done via R.

flights <- read.csv("https://raw.githubusercontent.com/IV246/R_DataSets/refs/heads/main/Flight_delay-data.csv")

2 Data Preparation

This portion of the report will focus on preparing the data set for visual exploratory data analysis and regression analysis. Here, data exploration, preparation and visualization will be done to the data set to prepare for analysis.

2.1 Structure of the Data Set

The data used in the case study was synthetically generated. It contains 3593 observations and 11 variables. The variables are as follows:

# Create an interactive data dictionary
data_dictionary <- tribble(
  ~Variable_Name,    ~Description,                                                        ~Variable_Type,
  "[",          "[Brief description of variable 1 — what it measures, units]",       "[Numeric/Categorical/Date/Text]",
  "[var2]",          "[Brief description of variable 2 — what it measures, categories]",  "[Numeric/Categorical/Date/Text]",
  "[var3]",          "[Brief description of variable 3 — what it measures]",              "[Numeric/Categorical/Date/Text]",
  "[var4]",          "[Brief description of variable 4 — what it measures, categories]",  "[Numeric/Categorical/Date/Text]"
  # Add more rows as needed
)

datatable(
  data_dictionary,
  caption = "Table 1: Variable definitions and types for the analysis dataset",
  rownames = FALSE,
  options = list(pageLength = 10, dom = 'tip')
)

Next, we can check a summary of the data set:

summary(flights)
   Carrier          Airport_Distance Number_of_flights    Weather     
 Length:3593        Min.   :376.0    Min.   :29475     Min.   :5.000  
 Class :character   1st Qu.:431.0    1st Qu.:41634     1st Qu.:5.000  
 Mode  :character   Median :443.0    Median :43424     Median :5.000  
                    Mean   :442.4    Mean   :43311     Mean   :5.353  
                    3rd Qu.:454.0    3rd Qu.:45140     3rd Qu.:6.000  
                    Max.   :499.0    Max.   :53461     Max.   :6.000  
 Support_Crew_Available Baggage_loading_time Late_Arrival_o    Cleaning_o   
 Min.   :  0            Min.   :14.00        Min.   :15.00   Min.   :-4.00  
 1st Qu.: 56            1st Qu.:17.00        1st Qu.:18.00   1st Qu.: 8.00  
 Median : 83            Median :17.00        Median :19.00   Median :10.00  
 Mean   : 85            Mean   :16.98        Mean   :18.74   Mean   :10.02  
 3rd Qu.:112            3rd Qu.:17.00        3rd Qu.:19.00   3rd Qu.:12.00  
 Max.   :222            Max.   :19.00        Max.   :22.00   Max.   :23.00  
   Fueling_o       Security_o      Arr_Delay    
 Min.   :13.00   Min.   :13.00   Min.   :  0.0  
 1st Qu.:23.00   1st Qu.:32.00   1st Qu.: 49.0  
 Median :25.00   Median :37.00   Median : 70.0  
 Mean   :25.01   Mean   :37.09   Mean   : 69.8  
 3rd Qu.:27.00   3rd Qu.:42.00   3rd Qu.: 90.0  
 Max.   :36.00   Max.   :63.00   Max.   :180.0  

If we pay close attention to the summary, a red flag immediately jumps out: The min of Cleaning_o is below 0, and since it’s a time variable, it can’t have values below 0. We can verify if it’s a mistake by either sorting the values of Cleaning_o or by summing up the values of the variable that are less than 0. To keep output simplistic, we can find out which specific observations have values of Cleaning_o of less than 0, as well as their respective values.

which(flights$Cleaning_o < 0)
[1]  624 1243 2357 2684 2786
flights$Cleaning_o[c(624, 1243, 2357, 2684, 2786)]
[1] -1 -4 -1 -1 -1

It appears that we only have 5 observations that have values less than 0. For this report, i will assume that they probably were just entry mistakes and will multiply them by -1 to make them positive so that no observations have to be dropped.

flights$Cleaning_o <- ifelse(flights$Cleaning_o < 0, flights$Cleaning_o*-1, flights$Cleaning_o)

To verify that the change worked, we can use the sort() function:

head(sort(flights$Cleaning_o))
[1] 0 0 0 0 0 0

The change worked. We will continue with data preparation.

2.2 Missing Values

Next we will check for missing values. Missing values, especially large amounts of them, can complicate analysis and lead to incorrect results and conclusions.

The summary of the data set that was ran earlier shows that there are no missing values. To verify, we can generate a lollipop plot of missing values to and run the sum() and is.na() functions to check how many missing values are in the data set.

# Add Up Total Missing Values 

# Check for Missing Values
sum(is.na(flights))
[1] 0

The sum of missing values is 0, which means there are no missing values in the data set. Next, let’s generate the lollipop plot using the gg_miss_var() function from the naniar package:

# Generate Lollipop Plot 

# library(naniar)
miss <- gg_miss_var(flights) + 
  labs(title = "Missing Values Per Variable") +
  theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 10, b = 25, l = 30))
ggplotly(miss)

All of the dots on are on 0, and there does not appear to be any stems. So it’s safe to say that we have a clean data set.

In the event that missing values were present, they could either just be dropped from the data set or imputed in some way.

2.3 Variable Screening

According to Gupta, the reasons airlines report for delays fall into 5 broad categories:

Extreme Weather: When extreme weather conditions like hurricanes or tornadoes occur, or when conditions are not ideal like in a snow storm, flights often have to change schedules, which results in delays or cancellations.

Late Arrival: This is the problem airlines report most often. When an airplane makes multiple flights and just even one time arrives late, it can make other flights using the same plane late, which will inevitably cause delays.

Air Carrier: Reasons such as aircraft maintenance issues, cleaning, baggage loading, fueling, and others contribute to the delays or cancellations that occur.

Security: Reasons such as inoperative screening equpiment, long queues in screening areas, reboarding of aircraft, and more contribute to flight delays.

National Aviation System (NAS): Airport operations, heavy volume/traffic, air traffic control and more can contribute to flight delays and cancellations.

It seems that all of our bases are covered with the variables generated for the data set. So for now, we won’t add or drop any variables. However, since weather is a rating variable, and seems to only have values of either 5 or 6 (despite being on a rating scale of 0-10), I will convert that variable into a factor:

flights$Weather <- factor(flights$Weather, ordered = TRUE)

The data is now prepared for analysis. Analysis will be done via visualization and regression. To do so, we will turn our attention to a shinyapp dashboard built specifically built for the analysis of this data set.

3 Visual Exploratory Data Analysis

This section of the report will focus on exploratory data analysis. In this section, we will plot variable distributions and explore relationships between variables. This portion and the regression portion will rely entirely on the shinyapp dashboard built for this data set.

LS0tDQp0aXRsZTogIkEgU3R1ZHkgb2YgQWlybGluZSBGbGlnaHQgRGVsYXlzIFVzaW5nIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIg0KYXV0aG9yOiAiSWFuIFZhbldyaWdodCINCmRhdGU6ICIwNi8yOS8yMDI2Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiB5ZXRpDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICAgIGNzczogc3R5bGVzLmNzcw0KLS0tDQoNCg0KYGBge2NzcyBlY2hvID0gRkFMU0V9DQovKiA9PT09PT09PT09PT0gQ1NTIFN0eWxpbmcgZm9yIExlY3R1cmUgTm90ZXMgPT09PT09PT09PT09ICovDQoNCmJvZHkgew0KICBmb250LWZhbWlseTogJ1NlZ29lIFVJJywgJ0ludGVyJywgc3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBzYW5zLXNlcmlmOw0KICBsaW5lLWhlaWdodDogMS43Ow0KICBjb2xvcjogIzJkMWIyOTsNCiAgYmFja2dyb3VuZC1jb2xvcjogI2ZkZmFmZDsNCn0NCg0KI1RPQzo6YmVmb3JlIHsNCiAgY29udGVudDogIlRhYmxlIG9mIENvbnRlbnRzIjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtc2l6ZTogMS4yZW07DQogIGRpc3BsYXk6IGJsb2NrOw0KICBjb2xvcjogbmF2eTsNCiAgbWFyZ2luLWJvdHRvbTogMTBweDsNCn0NCg0KDQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovDQogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQogICAgLypmb250LXdlaWdodDogYm9sZDsgKi8NCiAgICBmb250LXNpemU6IDEuMWVtOw0KICAgIGZvbnQtd2VpZ2h0OiA1MDA7DQogICAgY29sb3I6ICM2RTMwNjE7DQp9DQoNCg0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDI2cHg7DQogIGNvbG9yOiAjNkUzMDYxOw0KICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIC8qZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7Ki8NCiAgY29sb3I6ICM2RTMwNjE7DQogIHRleHQtYWxpZ246IGxlZnQ7DQp9DQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICAvKmZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOyovDQogIGNvbG9yOiAjNkUzMDYxOw0KICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQoNCmgxIHsNCiAgY29sb3I6ICM2RTMwNjE7DQogIGJvcmRlci1ib3R0b206IDNweCBzb2xpZCAjNkUzMDYxOw0KICBwYWRkaW5nLWJvdHRvbTogOHB4Ow0KICBtYXJnaW4tdG9wOiA0MHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAyLjJyZW07DQp9DQoNCmgyIHsNCiAgY29sb3I6ICM2RTMwNjE7DQogIGJvcmRlci1sZWZ0OiA1cHggc29saWQgIzZFMzA2MTsNCiAgcGFkZGluZy1sZWZ0OiAxMnB4Ow0KICBtYXJnaW4tdG9wOiAzMHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAxLjhyZW07DQp9DQoNCmgzIHsNCiAgY29sb3I6ICM4YjRhN2Q7DQogIG1hcmdpbi10b3A6IDI0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuOG07DQp9DQoNCmg0IHsNCiAgY29sb3I6ICNhMDVmOTI7DQogIG1hcmdpbi10b3A6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuNHJlbTsNCn0NCg0KY29kZSB7DQogIGJhY2tncm91bmQtY29sb3I6ICNmNGVkZjM7DQogIGNvbG9yOiAjNGEyMDQwOw0KICBwYWRkaW5nOiAycHggNnB4Ow0KICBib3JkZXItcmFkaXVzOiA0cHg7DQogIGZvbnQtZmFtaWx5OiAnRmlyYSBDb2RlJywgJ0pldEJyYWlucyBNb25vJywgJ0NvbnNvbGFzJywgbW9ub3NwYWNlOw0KICBmb250LXNpemU6IDAuOWVtOw0KICBib3JkZXI6IDFweCBzb2xpZCAjZDRjMGQxOw0KfQ0KDQpwcmUgew0KICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjlmNWY5Ow0KICBib3JkZXI6IDFweCBzb2xpZCAjZDRjMGQxOw0KICBib3JkZXItbGVmdDogNHB4IHNvbGlkICM2RTMwNjE7DQogIGJvcmRlci1yYWRpdXM6IDZweDsNCiAgcGFkZGluZzogMTRweDsNCn0NCg0KcHJlIGNvZGUgew0KICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsNCiAgYm9yZGVyOiBub25lOw0KICBwYWRkaW5nOiAwOw0KfQ0KDQpibG9ja3F1b3RlIHsNCiAgYmFja2dyb3VuZC1jb2xvcjogI2Y0ZWRmMzsNCiAgYm9yZGVyLWxlZnQ6IDRweCBzb2xpZCAjNkUzMDYxOw0KICBwYWRkaW5nOiAxMnB4IDE4cHg7DQogIG1hcmdpbjogMTZweCAwOw0KICBib3JkZXItcmFkaXVzOiAwIDZweCA2cHggMDsNCiAgY29sb3I6ICM0YTIwNDA7DQp9DQoNCi5ub3RlLWJveCB7DQogIGJhY2tncm91bmQtY29sb3I6ICNmMGU2ZWU7DQogIGJvcmRlcjogMXB4IHNvbGlkICNjNDliYjg7DQogIGJvcmRlci1yYWRpdXM6IDhweDsNCiAgcGFkZGluZzogMTZweCAyMHB4Ow0KICBtYXJnaW46IDE4cHggMDsNCn0NCg0KLm5vdGUtYm94IHN0cm9uZyB7DQogIGNvbG9yOiAjNkUzMDYxOw0KfQ0KDQoudGlwLWJveCB7DQogIGJhY2tncm91bmQtY29sb3I6ICNlOGY1ZTk7DQogIGJvcmRlcjogMXB4IHNvbGlkICM4MWM3ODQ7DQogIGJvcmRlci1yYWRpdXM6IDhweDsNCiAgcGFkZGluZzogMTZweCAyMHB4Ow0KICBtYXJnaW46IDE4cHggMDsNCn0NCg0KLnRpcC1ib3ggc3Ryb25nIHsNCiAgY29sb3I6ICMyZTdkMzI7DQp9DQoNCi53YXJuaW5nLWJveCB7DQogIGJhY2tncm91bmQtY29sb3I6ICNmZmYzZTA7DQogIGJvcmRlcjogMXB4IHNvbGlkICNmZmI3NGQ7DQogIGJvcmRlci1yYWRpdXM6IDhweDsNCiAgcGFkZGluZzogMTZweCAyMHB4Ow0KICBtYXJnaW46IDE4cHggMDsNCn0NCg0KLndhcm5pbmctYm94IHN0cm9uZyB7DQogIGNvbG9yOiAjZTY1MTAwOw0KfQ0KDQp0YWJsZSB7DQogIHdpZHRoOiAxMDAlOw0KICBib3JkZXItY29sbGFwc2U6IGNvbGxhcHNlOw0KICBtYXJnaW46IDE2cHggMDsNCn0NCg0KdGFibGUgdGggew0KICBiYWNrZ3JvdW5kLWNvbG9yOiAjNkUzMDYxOw0KICBjb2xvcjogd2hpdGU7DQogIHBhZGRpbmc6IDEwcHggMTJweDsNCiAgdGV4dC1hbGlnbjogbGVmdDsNCiAgZm9udC13ZWlnaHQ6IDYwMDsNCn0NCg0KdGFibGUgdGQgew0KICBwYWRkaW5nOiA4cHggMTJweDsNCiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNkNGMwZDE7DQp9DQoNCnRhYmxlIHRyOm50aC1jaGlsZChldmVuKSB0ZCB7DQogIGJhY2tncm91bmQtY29sb3I6ICNmYWY1Zjk7DQp9DQoNCnRhYmxlIHRyOmhvdmVyIHRkIHsNCiAgYmFja2dyb3VuZC1jb2xvcjogI2YwZTZlZTsNCn0NCg0KLnRvYyB7DQogIGJhY2tncm91bmQtY29sb3I6ICNmYWY1Zjk7DQogIGJvcmRlcjogMXB4IHNvbGlkICNkNGMwZDE7DQogIGJvcmRlci1yYWRpdXM6IDhweDsNCiAgcGFkZGluZzogMTZweCAyMHB4Ow0KICBtYXJnaW4tYm90dG9tOiAyNHB4Ow0KfQ0KDQouZmlndXJlIHsNCiAgYm9yZGVyOiAxcHggc29saWQgI2UwZDFkYjsNCiAgYm9yZGVyLXJhZGl1czogOHB4Ow0KICBwYWRkaW5nOiA4cHg7DQogIG1hcmdpbjogMTZweCAwOw0KICBib3gtc2hhZG93OiAwIDJweCA4cHggcmdiYSgxMTAsIDQ4LCA5NywgMC4wOCk7DQp9DQpgYGANCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09DQojICBSRVFVSVJFRCBQQUNLQUdFUw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT0NCiMgUXVpY2sgaW5zdGFsbCBhbmQgbG9hZCBmb3IgUiBNYXJrZG93bg0KcGFja2FnZXMgPC0gYygia25pdHIiLCAicmVhZHIiLCAidGlkeXZlcnNlIiwgInBsb3RseSIsICJsZWFmbGV0IiwgIkRUIiwgImNvcnJwbG90IiwgIkdHYWxseSIsICJjYXIiLCAiTUFTUyIsICJwYXRjaHdvcmsiLCAic2NhbGVzIiwgInZpcmlkaXMiLCAiUkNvbG9yQnJld2VyIiwgImdncmlkZ2VzIiwgImdnaGlnaGxpZ2h0IiwgImNvd3Bsb3QiLCAic2YiLCAiZ2dzcGF0aWFsIiwgImtuaXRyIiwgImthYmxlRXh0cmEiLCAiZ3JpZEV4dHJhIiwgImxlYXBzIiwgImdnZm9ydGlmeSIsICJwYW5kZXIiLCAic2NhbGVzIiwgImdhcG1pbmRlciIsICJodG1sd2lkZ2V0cyIsICJ2aXNkYXQiLCAibmFuaWFyIikNCg0KIyBJbnN0YWxsIG1pc3NpbmcgcGFja2FnZXMNCmlmKGFueSghKHBhY2thZ2VzICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKHBhY2thZ2VzWyEocGFja2FnZXMgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSldKQ0KfQ0KDQojIExvYWQgYWxsIHBhY2thZ2VzDQppbnZpc2libGUobGFwcGx5KHBhY2thZ2VzLCBsaWJyYXJ5LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKQ0KDQojIw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoPTgsIA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQ9NSwNCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIiwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEpDQpgYGANCg0KIyBJbnRyb2R1Y3Rpb24NClRoZSBib29rICJBcHBsaWVkIEFuYWx5dGljcyBUaHJvdWdoIENhc2UgU3R1ZGllcyBVc2luZyBTQVMgYW5kIFI6IEltcGxlbWVudGluZyBQcmVkaWN0aXZlIE1vZGVscyBhbmQgTWFjaGluZSBMZWFybmluZyBUZWNobmlxdWVzIiBpcyBhIGd1aWRlIGJvb2sgZm9yIHN0YXRpc3RpY2lhbnMsIGRhdGEgYW5hbHlzdHMsIGFuZCBvdGhlcnMgd2hvIGFyZSBpbnRlcmVzdGVkIGluIHRyeWluZyB0byBsZWFybi90cmFuc2l0aW9uIGludG8gZGF0YSBzY2llbmNlLiBUaGUgYm9vaywgYXV0aG9yZWQgYnkgRGVlcHRpIEd1cHRhLCB1c2UgY2FzZSBzdHVkaWVzIHRvIGV4cGxvcmUgaG93IHRvIGFuc3dlciB2YXJpb3VzIGJ1c2luZXNzIHF1ZXN0aW9ucyB1c2luZyBzdGF0aXN0aWNhbCBhbmQgbWFjaGluZSBsZWFybmluZyBtZXRob2RzIHVzaW5nIHByb2dyYW1taW5nIHBsYXRmb3JtcyBTQVMgYW5kIFIuIA0KDQpPbmUgb2YgdGhvc2UgY2FzZSBzdHVkaWVzIGludm9sdmVzIHByZWRpY3RpbmcgZmxpZ2h0IGRlbGF5cyBiYXNlZCBvbiBzZXZlcmFsIGZhY3RvcnMuIEluIHRoZSBib29rLCBHdXB0YSB1c2VzIHN0YXRpc3RpY2FsIGxlYXJuaW5nIG1ldGhvZHMgdG8gYW5hbHl6ZSB0aGUgZGF0YSBhbmQgZGV0ZXJtaW5lIHdoaWNoIGZhY3RvcnMgaW5mbHVlbmNlIGhvdyBsb25nIGEgZmxpZ2h0IGEgd2lsbCBiZSBkZWxheWVkIGZvci4gRm9yIHRoaXMgcHJvamVjdCwgdGhlIGdvYWwgaXMgdG8gdXNlIGRhdGEgdmlzdWFsaXphdGlvbiBhbmQgcmVncmVzc2lvbiBtZXRob2RzIHRvIGRldGVybWluZSB3aGljaCBmYWN0b3JzIGFyZSBpbmZsdWVudGlhbCB0byBmbGlnaHQgZGVsYXlzLg0KDQpUaGUgZGF0YSBzZXQgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIHRoaXMgYW5hbHlzaXMgd2lsbCBiZSB0aGUgc2FtZSBvbmUgdXNlZCBpbiB0aGUgY2FzZSBzdHVkeS4gVGhlIGRhdGEgc2V0IHdhcyBkb3dubG9hZGVkIGZyb20gYSBkYXRhIHNldCByZXBvc2l0b3J5IGFuZCB1cGxvYWRlZCB0byBHaXRodWIuIEFuYWx5c2lzIGZvciB0aGlzIHJlcG9ydCB3aWxsIGJlIGRvbmUgdmlhIFIuDQpgYGB7cn0NCmZsaWdodHMgPC0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9JVjI0Ni9SX0RhdGFTZXRzL3JlZnMvaGVhZHMvbWFpbi9GbGlnaHRfZGVsYXktZGF0YS5jc3YiKQ0KYGBgDQoNCiMgRGF0YSBQcmVwYXJhdGlvbg0KVGhpcyBwb3J0aW9uIG9mIHRoZSByZXBvcnQgd2lsbCBmb2N1cyBvbiBwcmVwYXJpbmcgdGhlIGRhdGEgc2V0IGZvciB2aXN1YWwgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyBhbmQgcmVncmVzc2lvbiBhbmFseXNpcy4gSGVyZSwgZGF0YSBleHBsb3JhdGlvbiwgcHJlcGFyYXRpb24gYW5kIHZpc3VhbGl6YXRpb24gd2lsbCBiZSBkb25lIHRvIHRoZSBkYXRhIHNldCB0byBwcmVwYXJlIGZvciBhbmFseXNpcy4NCg0KIyMgU3RydWN0dXJlIG9mIHRoZSBEYXRhIFNldA0KVGhlIGRhdGEgdXNlZCBpbiB0aGUgY2FzZSBzdHVkeSB3YXMgc3ludGhldGljYWxseSBnZW5lcmF0ZWQuIEl0IGNvbnRhaW5zIDM1OTMgb2JzZXJ2YXRpb25zIGFuZCAxMSB2YXJpYWJsZXMuIFRoZSB2YXJpYWJsZXMgYXJlIGFzIGZvbGxvd3M6DQoNCmBgYHtyfQ0KIyBDcmVhdGUgYW4gaW50ZXJhY3RpdmUgZGF0YSBkaWN0aW9uYXJ5DQpkYXRhX2RpY3Rpb25hcnkgPC0gdHJpYmJsZSgNCiAgflZhcmlhYmxlX05hbWUsICAgIH5EZXNjcmlwdGlvbiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH5WYXJpYWJsZV9UeXBlLA0KICAiWyIsICAgICAgICAgICJbQnJpZWYgZGVzY3JpcHRpb24gb2YgdmFyaWFibGUgMSDigJQgd2hhdCBpdCBtZWFzdXJlcywgdW5pdHNdIiwgICAgICAgIltOdW1lcmljL0NhdGVnb3JpY2FsL0RhdGUvVGV4dF0iLA0KICAiW3ZhcjJdIiwgICAgICAgICAgIltCcmllZiBkZXNjcmlwdGlvbiBvZiB2YXJpYWJsZSAyIOKAlCB3aGF0IGl0IG1lYXN1cmVzLCBjYXRlZ29yaWVzXSIsICAiW051bWVyaWMvQ2F0ZWdvcmljYWwvRGF0ZS9UZXh0XSIsDQogICJbdmFyM10iLCAgICAgICAgICAiW0JyaWVmIGRlc2NyaXB0aW9uIG9mIHZhcmlhYmxlIDMg4oCUIHdoYXQgaXQgbWVhc3VyZXNdIiwgICAgICAgICAgICAgICJbTnVtZXJpYy9DYXRlZ29yaWNhbC9EYXRlL1RleHRdIiwNCiAgIlt2YXI0XSIsICAgICAgICAgICJbQnJpZWYgZGVzY3JpcHRpb24gb2YgdmFyaWFibGUgNCDigJQgd2hhdCBpdCBtZWFzdXJlcywgY2F0ZWdvcmllc10iLCAgIltOdW1lcmljL0NhdGVnb3JpY2FsL0RhdGUvVGV4dF0iDQogICMgQWRkIG1vcmUgcm93cyBhcyBuZWVkZWQNCikNCg0KZGF0YXRhYmxlKA0KICBkYXRhX2RpY3Rpb25hcnksDQogIGNhcHRpb24gPSAiVGFibGUgMTogVmFyaWFibGUgZGVmaW5pdGlvbnMgYW5kIHR5cGVzIGZvciB0aGUgYW5hbHlzaXMgZGF0YXNldCIsDQogIHJvd25hbWVzID0gRkFMU0UsDQogIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwgZG9tID0gJ3RpcCcpDQopDQpgYGANCg0KTmV4dCwgd2UgY2FuIGNoZWNrIGEgc3VtbWFyeSBvZiB0aGUgZGF0YSBzZXQ6DQpgYGB7cn0NCnN1bW1hcnkoZmxpZ2h0cykNCmBgYA0KSWYgd2UgcGF5IGNsb3NlIGF0dGVudGlvbiB0byB0aGUgc3VtbWFyeSwgYSByZWQgZmxhZyBpbW1lZGlhdGVseSBqdW1wcyBvdXQ6IFRoZSBtaW4gb2YgQ2xlYW5pbmdfbyBpcyBiZWxvdyAwLCBhbmQgc2luY2UgaXQncyBhIHRpbWUgdmFyaWFibGUsIGl0IGNhbid0IGhhdmUgdmFsdWVzIGJlbG93IDAuIFdlIGNhbiB2ZXJpZnkgaWYgaXQncyBhIG1pc3Rha2UgYnkgZWl0aGVyIHNvcnRpbmcgdGhlIHZhbHVlcyBvZiBDbGVhbmluZ19vIG9yIGJ5IHN1bW1pbmcgdXAgdGhlIHZhbHVlcyBvZiB0aGUgdmFyaWFibGUgdGhhdCBhcmUgbGVzcyB0aGFuIDAuIFRvIGtlZXAgb3V0cHV0IHNpbXBsaXN0aWMsIHdlIGNhbiBmaW5kIG91dCB3aGljaCBzcGVjaWZpYyBvYnNlcnZhdGlvbnMgaGF2ZSB2YWx1ZXMgb2YgQ2xlYW5pbmdfbyBvZiBsZXNzIHRoYW4gMCwgYXMgd2VsbCBhcyB0aGVpciByZXNwZWN0aXZlIHZhbHVlcy4NCg0KYGBge3J9DQp3aGljaChmbGlnaHRzJENsZWFuaW5nX28gPCAwKQ0KZmxpZ2h0cyRDbGVhbmluZ19vW2MoNjI0LCAxMjQzLCAyMzU3LCAyNjg0LCAyNzg2KV0NCmBgYA0KSXQgYXBwZWFycyB0aGF0IHdlIG9ubHkgaGF2ZSA1IG9ic2VydmF0aW9ucyB0aGF0IGhhdmUgdmFsdWVzIGxlc3MgdGhhbiAwLiBGb3IgdGhpcyByZXBvcnQsIGkgd2lsbCBhc3N1bWUgdGhhdCB0aGV5IHByb2JhYmx5IHdlcmUganVzdCBlbnRyeSBtaXN0YWtlcyBhbmQgd2lsbCBtdWx0aXBseSB0aGVtIGJ5IC0xIHRvIG1ha2UgdGhlbSBwb3NpdGl2ZSBzbyB0aGF0IG5vIG9ic2VydmF0aW9ucyBoYXZlIHRvIGJlIGRyb3BwZWQuDQoNCmBgYHtyfQ0KZmxpZ2h0cyRDbGVhbmluZ19vIDwtIGlmZWxzZShmbGlnaHRzJENsZWFuaW5nX28gPCAwLCBmbGlnaHRzJENsZWFuaW5nX28qLTEsIGZsaWdodHMkQ2xlYW5pbmdfbykNCmBgYA0KDQpUbyB2ZXJpZnkgdGhhdCB0aGUgY2hhbmdlIHdvcmtlZCwgd2UgY2FuIHVzZSB0aGUgc29ydCgpIGZ1bmN0aW9uOg0KYGBge3J9DQpoZWFkKHNvcnQoZmxpZ2h0cyRDbGVhbmluZ19vKSkNCmBgYA0KVGhlIGNoYW5nZSB3b3JrZWQuIFdlIHdpbGwgY29udGludWUgd2l0aCBkYXRhIHByZXBhcmF0aW9uLiANCg0KIyMgTWlzc2luZyBWYWx1ZXMNCk5leHQgd2Ugd2lsbCBjaGVjayBmb3IgbWlzc2luZyB2YWx1ZXMuIE1pc3NpbmcgdmFsdWVzLCBlc3BlY2lhbGx5IGxhcmdlIGFtb3VudHMgb2YgdGhlbSwgY2FuIGNvbXBsaWNhdGUgYW5hbHlzaXMgYW5kIGxlYWQgdG8gaW5jb3JyZWN0IHJlc3VsdHMgYW5kIGNvbmNsdXNpb25zLg0KDQpUaGUgc3VtbWFyeSBvZiB0aGUgZGF0YSBzZXQgdGhhdCB3YXMgcmFuIGVhcmxpZXIgc2hvd3MgdGhhdCB0aGVyZSBhcmUgbm8gbWlzc2luZyB2YWx1ZXMuIFRvIHZlcmlmeSwgd2UgY2FuIGdlbmVyYXRlIGEgbG9sbGlwb3AgcGxvdCBvZiBtaXNzaW5nIHZhbHVlcyB0byBhbmQgcnVuIHRoZSBzdW0oKSBhbmQgaXMubmEoKSBmdW5jdGlvbnMgdG8gY2hlY2sgaG93IG1hbnkgbWlzc2luZyB2YWx1ZXMgYXJlIGluIHRoZSBkYXRhIHNldC4NCg0KYGBge3J9DQojIEFkZCBVcCBUb3RhbCBNaXNzaW5nIFZhbHVlcyANCg0KIyBDaGVjayBmb3IgTWlzc2luZyBWYWx1ZXMNCnN1bShpcy5uYShmbGlnaHRzKSkNCmBgYA0KDQpUaGUgc3VtIG9mIG1pc3NpbmcgdmFsdWVzIGlzIDAsIHdoaWNoIG1lYW5zIHRoZXJlIGFyZSBubyBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgZGF0YSBzZXQuIE5leHQsIGxldCdzIGdlbmVyYXRlIHRoZSBsb2xsaXBvcCBwbG90IHVzaW5nIHRoZSBnZ19taXNzX3ZhcigpIGZ1bmN0aW9uIGZyb20gdGhlIGBuYW5pYXJgIHBhY2thZ2U6DQpgYGB7cn0NCiMgR2VuZXJhdGUgTG9sbGlwb3AgUGxvdCANCg0KIyBsaWJyYXJ5KG5hbmlhcikNCm1pc3MgPC0gZ2dfbWlzc192YXIoZmxpZ2h0cykgKyANCiAgbGFicyh0aXRsZSA9ICJNaXNzaW5nIFZhbHVlcyBQZXIgVmFyaWFibGUiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMzUsIHIgPSAxMCwgYiA9IDI1LCBsID0gMzApKQ0KZ2dwbG90bHkobWlzcykNCmBgYA0KQWxsIG9mIHRoZSBkb3RzIG9uIGFyZSBvbiAwLCBhbmQgdGhlcmUgZG9lcyBub3QgYXBwZWFyIHRvIGJlIGFueSBzdGVtcy4gU28gaXQncyBzYWZlIHRvIHNheSB0aGF0IHdlIGhhdmUgYSBjbGVhbiBkYXRhIHNldC4NCg0KSW4gdGhlIGV2ZW50IHRoYXQgbWlzc2luZyB2YWx1ZXMgd2VyZSBwcmVzZW50LCB0aGV5IGNvdWxkIGVpdGhlciBqdXN0IGJlIGRyb3BwZWQgZnJvbSB0aGUgZGF0YSBzZXQgb3IgaW1wdXRlZCBpbiBzb21lIHdheS4NCg0KIyMgVmFyaWFibGUgU2NyZWVuaW5nDQpBY2NvcmRpbmcgdG8gR3VwdGEsIHRoZSByZWFzb25zIGFpcmxpbmVzIHJlcG9ydCBmb3IgZGVsYXlzIGZhbGwgaW50byA1IGJyb2FkIGNhdGVnb3JpZXM6DQoNCioqKkV4dHJlbWUgV2VhdGhlcjoqKiogV2hlbiBleHRyZW1lIHdlYXRoZXIgY29uZGl0aW9ucyBsaWtlIGh1cnJpY2FuZXMgb3IgdG9ybmFkb2VzIG9jY3VyLCBvciB3aGVuIGNvbmRpdGlvbnMgYXJlIG5vdCBpZGVhbCBsaWtlIGluIGEgc25vdyBzdG9ybSwgZmxpZ2h0cyBvZnRlbiBoYXZlIHRvIGNoYW5nZSBzY2hlZHVsZXMsIHdoaWNoIHJlc3VsdHMgaW4gZGVsYXlzIG9yIGNhbmNlbGxhdGlvbnMuDQoNCioqKkxhdGUgQXJyaXZhbDoqKiogVGhpcyBpcyB0aGUgcHJvYmxlbSBhaXJsaW5lcyByZXBvcnQgbW9zdCBvZnRlbi4gV2hlbiBhbiBhaXJwbGFuZSBtYWtlcyBtdWx0aXBsZSBmbGlnaHRzIGFuZCBqdXN0IGV2ZW4gb25lIHRpbWUgYXJyaXZlcyBsYXRlLCBpdCBjYW4gbWFrZSBvdGhlciBmbGlnaHRzIHVzaW5nIHRoZSBzYW1lIHBsYW5lIGxhdGUsIHdoaWNoIHdpbGwgaW5ldml0YWJseSBjYXVzZSBkZWxheXMuDQoNCioqKkFpciBDYXJyaWVyOioqKiBSZWFzb25zIHN1Y2ggYXMgYWlyY3JhZnQgbWFpbnRlbmFuY2UgaXNzdWVzLCBjbGVhbmluZywgYmFnZ2FnZSBsb2FkaW5nLCBmdWVsaW5nLCBhbmQgb3RoZXJzIGNvbnRyaWJ1dGUgdG8gdGhlIGRlbGF5cyBvciBjYW5jZWxsYXRpb25zIHRoYXQgb2NjdXIuDQoNCioqKlNlY3VyaXR5OioqKiBSZWFzb25zIHN1Y2ggYXMgaW5vcGVyYXRpdmUgc2NyZWVuaW5nIGVxdXBpbWVudCwgbG9uZyBxdWV1ZXMgaW4gc2NyZWVuaW5nIGFyZWFzLCByZWJvYXJkaW5nIG9mIGFpcmNyYWZ0LCBhbmQgbW9yZSBjb250cmlidXRlIHRvIGZsaWdodCBkZWxheXMuDQoNCioqKk5hdGlvbmFsIEF2aWF0aW9uIFN5c3RlbSAoTkFTKToqKiogQWlycG9ydCBvcGVyYXRpb25zLCBoZWF2eSB2b2x1bWUvdHJhZmZpYywgYWlyIHRyYWZmaWMgY29udHJvbCBhbmQgbW9yZSBjYW4gY29udHJpYnV0ZSB0byBmbGlnaHQgZGVsYXlzIGFuZCBjYW5jZWxsYXRpb25zLg0KDQpJdCBzZWVtcyB0aGF0IGFsbCBvZiBvdXIgYmFzZXMgYXJlIGNvdmVyZWQgd2l0aCB0aGUgdmFyaWFibGVzIGdlbmVyYXRlZCBmb3IgdGhlIGRhdGEgc2V0LiBTbyBmb3Igbm93LCB3ZSB3b24ndCBhZGQgb3IgZHJvcCBhbnkgdmFyaWFibGVzLiBIb3dldmVyLCBzaW5jZSB3ZWF0aGVyIGlzIGEgcmF0aW5nIHZhcmlhYmxlLCBhbmQgc2VlbXMgdG8gb25seSBoYXZlIHZhbHVlcyBvZiBlaXRoZXIgNSBvciA2IChkZXNwaXRlIGJlaW5nIG9uIGEgcmF0aW5nIHNjYWxlIG9mIDAtMTApLCBJIHdpbGwgY29udmVydCB0aGF0IHZhcmlhYmxlIGludG8gYSBmYWN0b3I6DQpgYGB7cn0NCmZsaWdodHMkV2VhdGhlciA8LSBmYWN0b3IoZmxpZ2h0cyRXZWF0aGVyLCBvcmRlcmVkID0gVFJVRSkNCmBgYA0KDQpUaGUgZGF0YSBpcyBub3cgcHJlcGFyZWQgZm9yIGFuYWx5c2lzLiBBbmFseXNpcyB3aWxsIGJlIGRvbmUgdmlhIHZpc3VhbGl6YXRpb24gYW5kIHJlZ3Jlc3Npb24uIFRvIGRvIHNvLCB3ZSB3aWxsIHR1cm4gb3VyIGF0dGVudGlvbiB0byBhIHNoaW55YXBwIGRhc2hib2FyZCBidWlsdCBzcGVjaWZpY2FsbHkgYnVpbHQgZm9yIHRoZSBhbmFseXNpcyBvZiB0aGlzIGRhdGEgc2V0Lg0KDQojIFZpc3VhbCBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzDQpUaGlzIHNlY3Rpb24gb2YgdGhlIHJlcG9ydCB3aWxsIGZvY3VzIG9uIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMuIEluIHRoaXMgc2VjdGlvbiwgd2Ugd2lsbCBwbG90IHZhcmlhYmxlIGRpc3RyaWJ1dGlvbnMgYW5kIGV4cGxvcmUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHZhcmlhYmxlcy4gVGhpcyBwb3J0aW9uIGFuZCB0aGUgcmVncmVzc2lvbiBwb3J0aW9uIHdpbGwgcmVseSBlbnRpcmVseSBvbiB0aGUgc2hpbnlhcHAgZGFzaGJvYXJkIGJ1aWx0IGZvciB0aGlzIGRhdGEgc2V0LiA=