Librairies

library(tidyverse)
## -- Attaching packages -------------------------------------------------------------------------------------- tidyverse 1.3.0 --
## v ggplot2 3.3.2     v purrr   0.3.4
## v tibble  3.0.3     v dplyr   1.0.2
## v tidyr   1.1.2     v stringr 1.4.0
## v readr   1.3.1     v forcats 0.5.0
## -- Conflicts ----------------------------------------------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(kableExtra)
## 
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows

Load data

airlines <- read.csv("https://raw.githubusercontent.com/jnataky/DATA-607/master/A5_Data_transformation/airlines_dest.csv")

Data Transformation

Clean the data frame

# Get rid of the empty row & reset the index

airlines <- na.omit(airlines)
row.names(airlines) <- NULL
# Replcae row 2 and 4 by airlines names

airlines[2, "X"] <- "ALASKA"
airlines[4, "X"] <- "AM WEST"
# Rename the columns names

airlines <- airlines %>%
  rename(carrier = X, status = X.1, los_angeles = Los.Angeles, phoenix = Phoenix, san_diego = San.Diego,
         san_francisco = San.Francisco, seattle = Seattle)

Tidying the data frame

# create new variable for destination and number of flights 

airlines <- airlines %>%
  gather("dest", "n_flights", 3:7)
# Wider the data frame by adding variables "on time" and "delayed"

airlines <- airlines %>%
  pivot_wider(names_from = "status", values_from = "n_flights")
# Table for tidy data


airlines %>%
  kbl(caption = "Airlines info", align = 'c') %>%
  kable_material(c("striped", "hover")) %>%
  row_spec(0, color = "indigo")
Airlines info
carrier dest on time delayed
ALASKA los_angeles 497 62
AM WEST los_angeles 694 117
ALASKA phoenix 221 12
AM WEST phoenix 4840 415
ALASKA san_diego 212 20
AM WEST san_diego 383 65
ALASKA san_francisco 503 102
AM WEST san_francisco 320 129
ALASKA seattle 1841 305
AM WEST seattle 201 61

Data Analysis

Airlines performance

# Create news variables

n_total <- airlines$delayed + airlines$`on time`
ontime_percent <- round((airlines$`on time` / n_total), 3)
delayed_percent <- round((airlines$delayed / n_total), 3)

airlines_df <- airlines %>%
  mutate(n_total, ontime_percent, delayed_percent)


airlines_df %>%
  kbl(caption = "Airlines more info", align = 'c') %>%
  kable_material(c("striped", "hover")) %>%
  row_spec(0, color = "indigo")
Airlines more info
carrier dest on time delayed n_total ontime_percent delayed_percent
ALASKA los_angeles 497 62 559 0.889 0.111
AM WEST los_angeles 694 117 811 0.856 0.144
ALASKA phoenix 221 12 233 0.948 0.052
AM WEST phoenix 4840 415 5255 0.921 0.079
ALASKA san_diego 212 20 232 0.914 0.086
AM WEST san_diego 383 65 448 0.855 0.145
ALASKA san_francisco 503 102 605 0.831 0.169
AM WEST san_francisco 320 129 449 0.713 0.287
ALASKA seattle 1841 305 2146 0.858 0.142
AM WEST seattle 201 61 262 0.767 0.233

Plotting the airlines performance

Airlines on time comparison per city

on_time1 <- airlines_df%>%
  group_by(dest, carrier) %>%
  summarise(ontime_percent)
## `summarise()` regrouping output by 'dest' (override with `.groups` argument)
on_time1 %>%
  kbl(caption = "On time performance per city", align = 'c') %>%
  kable_material(c("striped", "hover")) %>%
  row_spec(0, color = "indigo")
On time performance per city
dest carrier ontime_percent
los_angeles ALASKA 0.889
los_angeles AM WEST 0.856
phoenix ALASKA 0.948
phoenix AM WEST 0.921
san_diego ALASKA 0.914
san_diego AM WEST 0.855
san_francisco ALASKA 0.831
san_francisco AM WEST 0.713
seattle ALASKA 0.858
seattle AM WEST 0.767
# Plotting on time performance

ggplot(data = on_time1, aes(x = dest, y = ontime_percent, fill = carrier)) +
  geom_bar(stat = "identity", position = "dodge") +
  xlab("City") + ylab("On time % ") + ggtitle("Carriers on time performance per city")

Note on airlines on-time performance per city

Alaska performs better than AM West in every single of the five cities.

Overall on-time performance for both airlines

on_time2 <- airlines_df%>%
  group_by(carrier) %>%
  summarise(ontime_mean = mean(ontime_percent))
## `summarise()` ungrouping output (override with `.groups` argument)
on_time2 %>%
  kbl(caption = "Overall on-time performance", align = 'c') %>%
  kable_material(c("striped", "hover")) %>%
  row_spec(0, color = "indigo")
Overall on-time performance
carrier ontime_mean
ALASKA 0.8880
AM WEST 0.8224
# Plotting overall on-time performance

ggplot(data = on_time2, aes(x = carrier, y = ontime_mean)) +
  geom_bar(stat = "identity", width = 0.5, fill = "#b629a0") +
  xlab("Carrier") + ylab("On-time mean % ") + ggtitle("Overall on-time performance per carrier")

Note on overall on-time performance per carrier

Overall Alaska has more on-time flights than AM West.

A note on discrepancy

The overall on-time performance per carrier difference between two carriers is about 6%, and when looking the per city one the difference goes up to about 12% with a lowest of 2%. This creates a lack of similarities on that. The difference is varying.

Take Away

The analyze has shown that Alaska performs better on-time than AM West… Maybe it is because AM West have more flights in major cities than Alaska which cause the delay. Should it be expected ?

Before digging into the conclusion, let have a look on delays and analyze the overall number of flights per city, and see how it goes!

Graphs and insights

on_time3 <- airlines_df%>%
  group_by(dest, carrier) %>%
  summarise(ontime_percent)
## `summarise()` regrouping output by 'dest' (override with `.groups` argument)
# Plotting on time performance

ggplot(data = on_time3, aes(x = dest, y = delayed_percent, fill = carrier)) +
  geom_bar(stat = "identity", position = "dodge") +
  xlab("City") + ylab("Delayed  % ") + ggtitle("Carriers delay per city")

on_time4 <- airlines_df%>%
  group_by(dest, carrier) %>%
  summarise(n_total)
## `summarise()` regrouping output by 'dest' (override with `.groups` argument)
# Plotting on time performance

ggplot(data = on_time4, aes(x = dest, y = n_total, fill = carrier)) +
  geom_bar(stat = "identity", position = "dodge") +
  xlab("City") + ylab("Number of flights ") + ggtitle("Number of flights per city")

Conclusion

The two graphs above hve shown something different… That’s not what could be expected!

Here’s: Looking at the graphs above, we can see that Alaska operates more flights in Seattle and San Francisco, but even in Seattle where Alaska has largely more flights than AM West, AM West still have more delay than Alaska. And the on-time performance per city graph can also proove it, Alaska flights are more on-time than AM West. It is also the case in the cities where AM West operates more flights (Los Angeles, Phoenix, and San Diego), those cities have more delays flights with AM West compared to Alaska… Alaska still better performing than AM West in any condition, that’s not number of flights operated in major cities causing delays to AM West. Thus, I will recommend to AM West to work on their reservation system and in their hand when it comes to make a choose between traveling to one the five cities with one of those two airlines , I will suggest Alaska airline to avoid a high potential delay with AM West.

LS0tDQp0aXRsZTogIkRBVEEgNjA3IEFTU0lHTk1FTlQgNSINCmF1dGhvcjogIkplcmVkIEF0YWt5Ig0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiANCiAgb3BlbmludHJvOjpsYWJfcmVwb3J0OiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIyBMaWJyYWlyaWVzDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpgYGANCg0KIyMgTG9hZCBkYXRhDQoNCg0KYGBge3J9DQoNCmFpcmxpbmVzIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vam5hdGFreS9EQVRBLTYwNy9tYXN0ZXIvQTVfRGF0YV90cmFuc2Zvcm1hdGlvbi9haXJsaW5lc19kZXN0LmNzdiIpDQpgYGANCg0KDQojIyBEYXRhIFRyYW5zZm9ybWF0aW9uDQoNCiMjIyBDbGVhbiB0aGUgZGF0YSBmcmFtZQ0KDQoNCmBgYHtyfQ0KDQojIEdldCByaWQgb2YgdGhlIGVtcHR5IHJvdyAmIHJlc2V0IHRoZSBpbmRleA0KDQphaXJsaW5lcyA8LSBuYS5vbWl0KGFpcmxpbmVzKQ0Kcm93Lm5hbWVzKGFpcmxpbmVzKSA8LSBOVUxMDQpgYGANCg0KYGBge3J9DQojIFJlcGxjYWUgcm93IDIgYW5kIDQgYnkgYWlybGluZXMgbmFtZXMNCg0KYWlybGluZXNbMiwgIlgiXSA8LSAiQUxBU0tBIg0KYWlybGluZXNbNCwgIlgiXSA8LSAiQU0gV0VTVCINCmBgYA0KDQpgYGB7cn0NCiMgUmVuYW1lIHRoZSBjb2x1bW5zIG5hbWVzDQoNCmFpcmxpbmVzIDwtIGFpcmxpbmVzICU+JQ0KICByZW5hbWUoY2FycmllciA9IFgsIHN0YXR1cyA9IFguMSwgbG9zX2FuZ2VsZXMgPSBMb3MuQW5nZWxlcywgcGhvZW5peCA9IFBob2VuaXgsIHNhbl9kaWVnbyA9IFNhbi5EaWVnbywNCiAgICAgICAgIHNhbl9mcmFuY2lzY28gPSBTYW4uRnJhbmNpc2NvLCBzZWF0dGxlID0gU2VhdHRsZSkNCg0KYGBgDQoNCg0KIyMjIFRpZHlpbmcgdGhlIGRhdGEgZnJhbWUNCg0KDQpgYGB7cn0NCg0KIyBjcmVhdGUgbmV3IHZhcmlhYmxlIGZvciBkZXN0aW5hdGlvbiBhbmQgbnVtYmVyIG9mIGZsaWdodHMgDQoNCmFpcmxpbmVzIDwtIGFpcmxpbmVzICU+JQ0KICBnYXRoZXIoImRlc3QiLCAibl9mbGlnaHRzIiwgMzo3KQ0KDQoNCmBgYA0KDQpgYGB7cn0NCg0KIyBXaWRlciB0aGUgZGF0YSBmcmFtZSBieSBhZGRpbmcgdmFyaWFibGVzICJvbiB0aW1lIiBhbmQgImRlbGF5ZWQiDQoNCmFpcmxpbmVzIDwtIGFpcmxpbmVzICU+JQ0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gInN0YXR1cyIsIHZhbHVlc19mcm9tID0gIm5fZmxpZ2h0cyIpDQoNCmBgYA0KDQpgYGB7cn0NCg0KIyBUYWJsZSBmb3IgdGlkeSBkYXRhDQoNCg0KYWlybGluZXMgJT4lDQogIGtibChjYXB0aW9uID0gIkFpcmxpbmVzIGluZm8iLCBhbGlnbiA9ICdjJykgJT4lDQogIGthYmxlX21hdGVyaWFsKGMoInN0cmlwZWQiLCAiaG92ZXIiKSkgJT4lDQogIHJvd19zcGVjKDAsIGNvbG9yID0gImluZGlnbyIpDQpgYGANCg0KIyMgRGF0YSBBbmFseXNpcw0KDQojIyMgQWlybGluZXMgcGVyZm9ybWFuY2UNCmBgYHtyfQ0KDQojIENyZWF0ZSBuZXdzIHZhcmlhYmxlcw0KDQpuX3RvdGFsIDwtIGFpcmxpbmVzJGRlbGF5ZWQgKyBhaXJsaW5lcyRgb24gdGltZWANCm9udGltZV9wZXJjZW50IDwtIHJvdW5kKChhaXJsaW5lcyRgb24gdGltZWAgLyBuX3RvdGFsKSwgMykNCmRlbGF5ZWRfcGVyY2VudCA8LSByb3VuZCgoYWlybGluZXMkZGVsYXllZCAvIG5fdG90YWwpLCAzKQ0KDQphaXJsaW5lc19kZiA8LSBhaXJsaW5lcyAlPiUNCiAgbXV0YXRlKG5fdG90YWwsIG9udGltZV9wZXJjZW50LCBkZWxheWVkX3BlcmNlbnQpDQoNCg0KYWlybGluZXNfZGYgJT4lDQogIGtibChjYXB0aW9uID0gIkFpcmxpbmVzIG1vcmUgaW5mbyIsIGFsaWduID0gJ2MnKSAlPiUNCiAga2FibGVfbWF0ZXJpYWwoYygic3RyaXBlZCIsICJob3ZlciIpKSAlPiUNCiAgcm93X3NwZWMoMCwgY29sb3IgPSAiaW5kaWdvIikNCmBgYA0KDQoNCiMjIyBQbG90dGluZyB0aGUgYWlybGluZXMgcGVyZm9ybWFuY2UNCg0KIyMjIEFpcmxpbmVzIG9uIHRpbWUgY29tcGFyaXNvbiBwZXIgY2l0eQ0KDQpgYGB7cn0NCg0Kb25fdGltZTEgPC0gYWlybGluZXNfZGYlPiUNCiAgZ3JvdXBfYnkoZGVzdCwgY2FycmllcikgJT4lDQogIHN1bW1hcmlzZShvbnRpbWVfcGVyY2VudCkNCg0Kb25fdGltZTEgJT4lDQogIGtibChjYXB0aW9uID0gIk9uIHRpbWUgcGVyZm9ybWFuY2UgcGVyIGNpdHkiLCBhbGlnbiA9ICdjJykgJT4lDQogIGthYmxlX21hdGVyaWFsKGMoInN0cmlwZWQiLCAiaG92ZXIiKSkgJT4lDQogIHJvd19zcGVjKDAsIGNvbG9yID0gImluZGlnbyIpDQoNCg0KYGBgDQoNCmBgYHtyfQ0KIyBQbG90dGluZyBvbiB0aW1lIHBlcmZvcm1hbmNlDQoNCmdncGxvdChkYXRhID0gb25fdGltZTEsIGFlcyh4ID0gZGVzdCwgeSA9IG9udGltZV9wZXJjZW50LCBmaWxsID0gY2FycmllcikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICB4bGFiKCJDaXR5IikgKyB5bGFiKCJPbiB0aW1lICUgIikgKyBnZ3RpdGxlKCJDYXJyaWVycyBvbiB0aW1lIHBlcmZvcm1hbmNlIHBlciBjaXR5IikNCg0KDQpgYGANCg0KIyMjIE5vdGUgb24gYWlybGluZXMgb24tdGltZSBwZXJmb3JtYW5jZSBwZXIgY2l0eQ0KDQpBbGFza2EgcGVyZm9ybXMgYmV0dGVyIHRoYW4gQU0gV2VzdCBpbiBldmVyeSBzaW5nbGUgb2YgdGhlIGZpdmUgY2l0aWVzLg0KDQoNCiMjIyBPdmVyYWxsIG9uLXRpbWUgcGVyZm9ybWFuY2UgZm9yIGJvdGggYWlybGluZXMNCg0KDQpgYGB7cn0NCg0Kb25fdGltZTIgPC0gYWlybGluZXNfZGYlPiUNCiAgZ3JvdXBfYnkoY2FycmllcikgJT4lDQogIHN1bW1hcmlzZShvbnRpbWVfbWVhbiA9IG1lYW4ob250aW1lX3BlcmNlbnQpKQ0KDQpvbl90aW1lMiAlPiUNCiAga2JsKGNhcHRpb24gPSAiT3ZlcmFsbCBvbi10aW1lIHBlcmZvcm1hbmNlIiwgYWxpZ24gPSAnYycpICU+JQ0KICBrYWJsZV9tYXRlcmlhbChjKCJzdHJpcGVkIiwgImhvdmVyIikpICU+JQ0KICByb3dfc3BlYygwLCBjb2xvciA9ICJpbmRpZ28iKQ0KDQoNCmBgYA0KDQoNCg0KYGBge3J9DQojIFBsb3R0aW5nIG92ZXJhbGwgb24tdGltZSBwZXJmb3JtYW5jZQ0KDQpnZ3Bsb3QoZGF0YSA9IG9uX3RpbWUyLCBhZXMoeCA9IGNhcnJpZXIsIHkgPSBvbnRpbWVfbWVhbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41LCBmaWxsID0gIiNiNjI5YTAiKSArDQogIHhsYWIoIkNhcnJpZXIiKSArIHlsYWIoIk9uLXRpbWUgbWVhbiAlICIpICsgZ2d0aXRsZSgiT3ZlcmFsbCBvbi10aW1lIHBlcmZvcm1hbmNlIHBlciBjYXJyaWVyIikNCmBgYA0KDQoNCiMjIyBOb3RlIG9uIG92ZXJhbGwgb24tdGltZSBwZXJmb3JtYW5jZSBwZXIgY2Fycmllcg0KDQpPdmVyYWxsIEFsYXNrYSBoYXMgbW9yZSBvbi10aW1lIGZsaWdodHMgdGhhbiBBTSBXZXN0Lg0KDQoNCiMjIyBBIG5vdGUgb24gZGlzY3JlcGFuY3kNCg0KDQo8c3R5bGU+DQpkaXYuYXF1YW1hcmluZSB7IGJhY2tncm91bmQtY29sb3I6IzdmZmZkNDsgYm9yZGVyLXJhZGl1czogMTBweDsgcGFkZGluZzogNXB4O30NCjwvc3R5bGU+DQo8ZGl2IGNsYXNzID0gImFxdWFtYXJpbmUiPg0KDQpUaGUgb3ZlcmFsbCBvbi10aW1lIHBlcmZvcm1hbmNlIHBlciBjYXJyaWVyIGRpZmZlcmVuY2UgYmV0d2VlbiB0d28gY2FycmllcnMgaXMgYWJvdXQgNiUsIA0KYW5kIHdoZW4gbG9va2luZyB0aGUgcGVyIGNpdHkgb25lIHRoZSBkaWZmZXJlbmNlIGdvZXMgdXAgdG8gYWJvdXQgMTIlIHdpdGggYSBsb3dlc3Qgb2YgMiUuDQpUaGlzIGNyZWF0ZXMgYSBsYWNrIG9mIHNpbWlsYXJpdGllcyBvbiB0aGF0LiBUaGUgZGlmZmVyZW5jZSBpcyB2YXJ5aW5nLg0KDQoNCjwvZGl2PiBcaGZpbGxcYnJlYWsNCg0KDQojIyBUYWtlIEF3YXkNCg0KPHN0eWxlPg0KZGl2LmFxdWFtYXJpbmUgeyBiYWNrZ3JvdW5kLWNvbG9yOiM3ZmZmZDQ7IGJvcmRlci1yYWRpdXM6IDEwcHg7IHBhZGRpbmc6IDVweDt9DQo8L3N0eWxlPg0KPGRpdiBjbGFzcyA9ICJhcXVhbWFyaW5lIj4NCg0KDQpUaGUgYW5hbHl6ZSBoYXMgc2hvd24gdGhhdCBBbGFza2EgcGVyZm9ybXMgYmV0dGVyIG9uLXRpbWUgdGhhbiBBTSBXZXN0Li4uIA0KTWF5YmUgaXQgaXMgYmVjYXVzZSBBTSBXZXN0IGhhdmUgbW9yZSBmbGlnaHRzIGluIG1ham9yIGNpdGllcyB0aGFuIEFsYXNrYSB3aGljaCBjYXVzZSB0aGUgZGVsYXkuIA0KU2hvdWxkIGl0IGJlIGV4cGVjdGVkID8NCg0KQmVmb3JlIGRpZ2dpbmcgaW50byB0aGUgY29uY2x1c2lvbiwgbGV0IGhhdmUgYSBsb29rIG9uIGRlbGF5cyANCmFuZCBhbmFseXplIHRoZSBvdmVyYWxsIG51bWJlciBvZiBmbGlnaHRzIHBlciBjaXR5LCBhbmQgc2VlIGhvdyBpdCBnb2VzIQ0KDQoNCg0KPC9kaXY+IFxoZmlsbFxicmVhaw0KDQoNCg0KDQojIyMgR3JhcGhzIGFuZCBpbnNpZ2h0cw0KDQoNCmBgYHtyfQ0KDQpvbl90aW1lMyA8LSBhaXJsaW5lc19kZiU+JQ0KICBncm91cF9ieShkZXN0LCBjYXJyaWVyKSAlPiUNCiAgc3VtbWFyaXNlKG9udGltZV9wZXJjZW50KQ0KDQojIFBsb3R0aW5nIG9uIHRpbWUgcGVyZm9ybWFuY2UNCg0KZ2dwbG90KGRhdGEgPSBvbl90aW1lMywgYWVzKHggPSBkZXN0LCB5ID0gZGVsYXllZF9wZXJjZW50LCBmaWxsID0gY2FycmllcikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICB4bGFiKCJDaXR5IikgKyB5bGFiKCJEZWxheWVkICAlICIpICsgZ2d0aXRsZSgiQ2FycmllcnMgZGVsYXkgcGVyIGNpdHkiKQ0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpvbl90aW1lNCA8LSBhaXJsaW5lc19kZiU+JQ0KICBncm91cF9ieShkZXN0LCBjYXJyaWVyKSAlPiUNCiAgc3VtbWFyaXNlKG5fdG90YWwpDQoNCiMgUGxvdHRpbmcgb24gdGltZSBwZXJmb3JtYW5jZQ0KDQpnZ3Bsb3QoZGF0YSA9IG9uX3RpbWU0LCBhZXMoeCA9IGRlc3QsIHkgPSBuX3RvdGFsLCBmaWxsID0gY2FycmllcikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICB4bGFiKCJDaXR5IikgKyB5bGFiKCJOdW1iZXIgb2YgZmxpZ2h0cyAiKSArIGdndGl0bGUoIk51bWJlciBvZiBmbGlnaHRzIHBlciBjaXR5IikNCg0KDQpgYGANCg0KIyMjIENvbmNsdXNpb24NCg0KDQo8c3R5bGU+DQpkaXYuYXF1YW1hcmluZSB7IGJhY2tncm91bmQtY29sb3I6IzdmZmZkNDsgYm9yZGVyLXJhZGl1czogMTBweDsgcGFkZGluZzogNXB4O30NCjwvc3R5bGU+DQo8ZGl2IGNsYXNzID0gImFxdWFtYXJpbmUiPg0KDQoNClRoZSB0d28gZ3JhcGhzIGFib3ZlIGh2ZSBzaG93biBzb21ldGhpbmcgZGlmZmVyZW50Li4uIFRoYXQncyBub3Qgd2hhdCBjb3VsZCBiZSBleHBlY3RlZCENCg0KSGVyZSdzOiBMb29raW5nIGF0IHRoZSBncmFwaHMgYWJvdmUsIHdlIGNhbiBzZWUgdGhhdCBBbGFza2Egb3BlcmF0ZXMgbW9yZSBmbGlnaHRzIGluIFNlYXR0bGUgYW5kIFNhbiBGcmFuY2lzY28sDQpidXQgZXZlbiBpbiBTZWF0dGxlIHdoZXJlIEFsYXNrYSBoYXMgbGFyZ2VseSBtb3JlIGZsaWdodHMgdGhhbiBBTSBXZXN0LCBBTSBXZXN0IHN0aWxsIGhhdmUgbW9yZSBkZWxheSB0aGFuIEFsYXNrYS4NCkFuZCB0aGUgb24tdGltZSBwZXJmb3JtYW5jZSBwZXIgY2l0eSBncmFwaCBjYW4gYWxzbyBwcm9vdmUgaXQsIEFsYXNrYSBmbGlnaHRzIGFyZSBtb3JlIG9uLXRpbWUgdGhhbiBBTSBXZXN0Lg0KSXQgaXMgYWxzbyB0aGUgY2FzZSBpbiB0aGUgY2l0aWVzIHdoZXJlIEFNIFdlc3Qgb3BlcmF0ZXMgbW9yZSBmbGlnaHRzIChMb3MgQW5nZWxlcywgUGhvZW5peCwgYW5kIFNhbiBEaWVnbyksIA0KdGhvc2UgY2l0aWVzIGhhdmUgbW9yZSBkZWxheXMgZmxpZ2h0cyB3aXRoIEFNIFdlc3QgY29tcGFyZWQgdG8gQWxhc2thLi4uIEFsYXNrYSBzdGlsbCBiZXR0ZXIgcGVyZm9ybWluZyB0aGFuIEFNIFdlc3QgaW4gYW55IGNvbmRpdGlvbiwgdGhhdCdzIG5vdCBudW1iZXIgb2YgZmxpZ2h0cyBvcGVyYXRlZCBpbiBtYWpvciBjaXRpZXMgY2F1c2luZyBkZWxheXMgdG8gQU0gV2VzdC4gVGh1cywgSSB3aWxsIHJlY29tbWVuZCB0byBBTSBXZXN0IHRvIHdvcmsgb24gdGhlaXIgcmVzZXJ2YXRpb24gc3lzdGVtIGFuZCBpbiB0aGVpciBoYW5kIHdoZW4gaXQgY29tZXMgdG8gbWFrZSBhIGNob29zZSBiZXR3ZWVuIHRyYXZlbGluZyB0byBvbmUgdGhlIGZpdmUgY2l0aWVzIHdpdGggb25lIG9mIHRob3NlIHR3byBhaXJsaW5lcyAsIEkgd2lsbCBzdWdnZXN0IEFsYXNrYSBhaXJsaW5lIHRvIGF2b2lkIGEgaGlnaCBwb3RlbnRpYWwgZGVsYXkgd2l0aCBBTSBXZXN0Lg0KDQoNCg0KDQo8L2Rpdj4gXGhmaWxsXGJyZWFrDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K