Synopsis:

This report utilizes the U.S. National Oceanic and Atmospheric Administration’s (NOAA) storm database to answer two basic questions:

The data contains information on a wide variety of severe storms occurring between 1950 and 2011. Everything from heavy rain, sleet or high surf to tornadoes and volcaninc ash are included.

Data Processing:

The data is read in from the working directory using the read.csv function. Data processing and visualization packages are also loaded.

library(dplyr)
library(ggplot2)
storm_data <- read.csv("repdata%2Fdata%2FStormData.csv.bz2", as.is = TRUE)

Using the names function, the available database variables are viewed:

names(storm_data)
 [1] "STATE__"    "BGN_DATE"   "BGN_TIME"   "TIME_ZONE"  "COUNTY"     "COUNTYNAME" "STATE"     
 [8] "EVTYPE"     "BGN_RANGE"  "BGN_AZI"    "BGN_LOCATI" "END_DATE"   "END_TIME"   "COUNTY_END"
[15] "COUNTYENDN" "END_RANGE"  "END_AZI"    "END_LOCATI" "LENGTH"     "WIDTH"      "F"         
[22] "MAG"        "FATALITIES" "INJURIES"   "PROPDMG"    "PROPDMGEXP" "CROPDMG"    "CROPDMGEXP"
[29] "WFO"        "STATEOFFIC" "ZONENAMES"  "LATITUDE"   "LONGITUDE"  "LATITUDE_E" "LONGITUDE_"
[36] "REMARKS"    "REFNUM"    

The NOAA storm database documentation can be found here: ( http://www.nws.noaa.gov/directives/). After reviewing this documentation, the variables FATALITIES and INJURIES appear to be the only variables pertinent to the question of harm caused to individual health.

The variables PROPDMG, PROPDMEGXP, CROPDMG and CROPDMGEXP each relate to the economic consequences caused by storm events. PROPDMG and PROPDMGEXP give property damage totals with PROPDMGEXP providing a multiplier for the damage amount (code “H” for hundreds of dollars, “K” for thousands, “M” for millions, etc.). CROPDMG and CROPDMGEXP give similar damage estimates for agricultural losses.

Assessment of harm to population health

For ease of visualization, subsets of the data are created containing only event type and fatalities/injuries. We then take a cursory look at the data using the summary function.

death <- storm_data[,c(8,23)]
injury <- storm_data[,c(8,24)]
summary(death$FATALITIES)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
  0.0000   0.0000   0.0000   0.0168   0.0000 583.0000 
summary(injury$INJURIES)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
   0.0000    0.0000    0.0000    0.1557    0.0000 1700.0000 

Both the fatality and injury variables contain a large number of zero values. Those are removed here, and the resulting five most fatal/injurious event types are retained for plotting.

death <- death[death$FATALITIES > 0,]
injury <- injury[injury$INJURIES > 0,]
total_deaths <- aggregate(death$FATALITIES, by = list(death$EVTYPE), FUN = "sum")
total_deaths <- total_deaths[order(-total_deaths[,2]),]
total_deaths <- total_deaths[1:5,]
names(total_deaths) <- c("Event", "Total_Deaths")
rownames(total_deaths) <- NULL
total_injuries <- aggregate(injury$INJURIES, by = list(injury$EVTYPE), FUN = "sum")
total_injuries <- total_injuries[order(-total_injuries[,2]),]
total_injuries <- total_injuries[1:5,]
names(total_injuries) <- c("Event", "Total_Injuries")
rownames(total_injuries) <- NULL

ggplot2 is used to plot the data:

ggplot(total_deaths, aes(x=reorder(Event, -Total_Deaths), y=Total_Deaths, fill=Event)) +
  labs(title = "The Five Deadliest Weather Event Types", x = "Weather Event", y = "Total Deaths") +
  geom_bar(stat="identity") + ylim(0, 6500) + theme(legend.position = "none") 

ggplot(total_injuries, aes(x=reorder(Event, -Total_Injuries), y=Total_Injuries, fill=Event)) +
  labs(title = "Weather Event Types That Cause the Most Injuries") +
  labs(x = "Weather Event", y = "Total Injuries") +
  geom_bar(stat="identity") + ylim(0, 101000) + theme(legend.position = "none")

Assessment of Economic Consequnces

As noted above, the economic consequence data utilizes multipliers found in variables PROPDMGEXP and CROPDMGEXP to describe the total financial loss caused by a given event. Respectively, the two multiplier variables contain the following codes:

levels(as.factor(storm_data$PROPDMGEXP))
 [1] ""  "-" "?" "+" "0" "1" "2" "3" "4" "5" "6" "7" "8" "B" "h" "H" "K" "m" "M"
levels(as.factor(storm_data$CROPDMGEXP))
[1] ""  "?" "0" "2" "B" "k" "K" "m" "M"

To ease assessment of the financial loss data, subsets of the data are again created containing only event type and property or econimic harm data. Zero values for damage are excluded since they are not pertinent to the question posed.

prop_damage <- storm_data[,c(8,25:26)]
prop_damage <- prop_damage[prop_damage$PROPDMG > 0,]
crop_damage <- storm_data[,c(8, 27:28)]
crop_damage <- crop_damage[crop_damage$CROPDMG > 0,]

The summary function shows how many times each multiplier is used in the remaining data. (The first entry in each list is a count of the number of times no multiplier was indicated.)

summary(as.factor(prop_damage$PROPDMGEXP))
            -      +      0      2      3      4      5      6      7      B      h      H      K 
    76      1      5    209      1      1      4     18      3      2     40      1      6 227481 
     m      M 
     7  11319 
summary(as.factor(crop_damage$CROPDMGEXP))
          0     B     k     K     m     M 
    3    12     7    21 20137     1  1918 

A small number of the remaining multipliers have unknown meanings (i.e. they are not discussed in the dataset documentation). These values are: -, ?, +, 0 through 8, and blank spaces. Because these entries are present in only 0.0013% of the property damage data and 0.00068% of the crop damage data, those rows are excluded as possible data entry errors.

prop_damage <- prop_damage[(prop_damage$PROPDMGEXP == "B") | (prop_damage$PROPDMGEXP == "h") |
                           (prop_damage$PROPDMGEXP == "H") | (prop_damage$PROPDMGEXP == "K") |
                           (prop_damage$PROPDMGEXP == "m") | (prop_damage$PROPDMGEXP == "M"),]
crop_damage <- crop_damage[(crop_damage$CROPDMGEXP == "B") | (crop_damage$CROPDMGEXP == "k") |
                           (crop_damage$CROPDMGEXP == "K") | (crop_damage$CROPDMGEXP == "m") |
                           (crop_damage$CROPDMGEXP == "M"),]

The multipliers are now used to adjust the property and crop damage values.

prop_damage$PROPDMGEXP[prop_damage$PROPDMGEXP == "B"] <- 1000000000
prop_damage$PROPDMGEXP[prop_damage$PROPDMGEXP == "M"] <- 1000000
prop_damage$PROPDMGEXP[prop_damage$PROPDMGEXP == "m"] <- 1000000
prop_damage$PROPDMGEXP[prop_damage$PROPDMGEXP == "K"] <- 1000
prop_damage$PROPDMGEXP[prop_damage$PROPDMGEXP == "H"] <- 100
prop_damage$PROPDMGEXP[prop_damage$PROPDMGEXP == "h"] <- 100
crop_damage$CROPDMGEXP[crop_damage$CROPDMGEXP == "B"] <- 1000000000
crop_damage$CROPDMGEXP[crop_damage$CROPDMGEXP == "M"] <- 1000000
crop_damage$CROPDMGEXP[crop_damage$CROPDMGEXP == "m"] <- 1000000
crop_damage$CROPDMGEXP[crop_damage$CROPDMGEXP == "K"] <- 1000
crop_damage$CROPDMGEXP[crop_damage$CROPDMGEXP == "K"] <- 1000
prop_damage$ADJPROPDMG <- prop_damage$PROPDMG * as.numeric(prop_damage$PROPDMGEXP)
crop_damage$ADJCROPDMG <- crop_damage$CROPDMG * as.numeric(crop_damage$CROPDMGEXP)
NAs introduced by coercion

Finally, the most damaging storm events are identified:

prop_damage <- aggregate(prop_damage$ADJPROPDMG, by = list(prop_damage$EVTYPE), FUN = "sum")
prop_damage <- prop_damage[order(-prop_damage[,2]),]
names(prop_damage) <- c("Event", "Prop_Damage")
crop_damage <- aggregate(crop_damage$ADJCROPDMG, by = list(crop_damage$EVTYPE), FUN = "sum")
crop_damage <- crop_damage[order(-crop_damage[,2]),]
names(crop_damage) <- c("Event", "Crop_Damage")
total <- merge(prop_damage, crop_damage, by="Event")
total[is.na(total)] <- 0
total$Losses <- total$Prop_Damage + total$Crop_Damage
total <- total[order(-total[,4]),]
row.names(total) = NULL
total <- total[1:10,]
total$Losses <- total$Losses/1e+09
total

The economic loss information is also summarized visually here:

ggplot(data = total, aes(x=reorder(Event, -Losses), y=Losses)) + geom_bar(stat = "identity") +
  geom_text(aes(label=round(Losses,2)), color="white", vjust= 1, size=3) +
  labs(title = "Economic Losses Attributable to Weather Events") +
  labs(x = "Event", y = "Losses in Billions of Dollars") + 
  theme(axis.text.x = element_text(angle = 90, size = 8))

Results:

Clearly, tornadoes pose the greatest risk of injury or death of any weather event in the United States. Tornadoes have caused nearly three times as many deaths and tens of thousands more injuries. On the other hand, while tornadoes have had a significant economic impact over the years, they do not cause the most financial damage. Rather, flooding has been the most economically significant weather event in the U.S. by a large margin.

LS0tDQp0aXRsZTogIlN0b3JtIFNldmVyaXR5IEFuYWx5c2lzIFVzaW5nIHRoZSBOT0FBIFN0b3JtIERhdGFiYXNlIg0KYXV0aG9yOiBieSBKb3NoIENob2F0ZQ0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCiMjIFN5bm9wc2lzOg0KDQpUaGlzIHJlcG9ydCB1dGlsaXplcyB0aGUgVS5TLiBOYXRpb25hbCBPY2VhbmljIGFuZCBBdG1vc3BoZXJpYyBBZG1pbmlzdHJhdGlvbidzIChOT0FBKSBzdG9ybSBkYXRhYmFzZSB0byBhbnN3ZXIgdHdvIGJhc2ljIHF1ZXN0aW9uczoNCg0KKiBXaGF0IGtpbmRzIG9mIHN0b3JtIGV2ZW50cyBoYXZlIGJlZW4gdGhlIG1vc3QgaGFybWZ1bCB0byBwb3B1bGF0aW9uIGhlYWx0aD8NCiogV2hhdCBraW5kcyBvZiBzdG9ybSBldmVudHMgaGF2ZSBoYWQgdGhlIGdyZWF0ZXN0IGVjb25vbWljIGNvbnNlcXVlbmNlcz8NCg0KVGhlIGRhdGEgY29udGFpbnMgaW5mb3JtYXRpb24gb24gYSB3aWRlIHZhcmlldHkgb2Ygc2V2ZXJlIHN0b3JtcyBvY2N1cnJpbmcgYmV0d2VlbiAxOTUwIGFuZCAyMDExLiBFdmVyeXRoaW5nIGZyb20gaGVhdnkgcmFpbiwgc2xlZXQgb3IgaGlnaCBzdXJmIHRvIHRvcm5hZG9lcyBhbmQgdm9sY2FuaW5jIGFzaCBhcmUgaW5jbHVkZWQuIA0KDQojIyBEYXRhIFByb2Nlc3Npbmc6DQoNClRoZSBkYXRhIGlzIHJlYWQgaW4gZnJvbSB0aGUgd29ya2luZyBkaXJlY3RvcnkgdXNpbmcgdGhlIHJlYWQuY3N2IGZ1bmN0aW9uLiBEYXRhIHByb2Nlc3NpbmcgYW5kIHZpc3VhbGl6YXRpb24gcGFja2FnZXMgYXJlIGFsc28gbG9hZGVkLg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0Kc3Rvcm1fZGF0YSA8LSByZWFkLmNzdigicmVwZGF0YSUyRmRhdGElMkZTdG9ybURhdGEuY3N2LmJ6MiIsIGFzLmlzID0gVFJVRSkNCmBgYA0KDQpVc2luZyB0aGUgbmFtZXMgZnVuY3Rpb24sIHRoZSBhdmFpbGFibGUgZGF0YWJhc2UgdmFyaWFibGVzIGFyZSB2aWV3ZWQ6DQpgYGB7cn0NCm5hbWVzKHN0b3JtX2RhdGEpDQpgYGANCg0KVGhlIE5PQUEgc3Rvcm0gZGF0YWJhc2UgZG9jdW1lbnRhdGlvbiBjYW4gYmUgZm91bmQgaGVyZTogKCBodHRwOi8vd3d3Lm53cy5ub2FhLmdvdi9kaXJlY3RpdmVzLykuIEFmdGVyIHJldmlld2luZyB0aGlzIGRvY3VtZW50YXRpb24sIHRoZSB2YXJpYWJsZXMgRkFUQUxJVElFUyBhbmQgSU5KVVJJRVMgYXBwZWFyIHRvIGJlIHRoZSBvbmx5IHZhcmlhYmxlcyBwZXJ0aW5lbnQgdG8gdGhlIHF1ZXN0aW9uIG9mIGhhcm0gY2F1c2VkIHRvIGluZGl2aWR1YWwgaGVhbHRoLiANCg0KVGhlIHZhcmlhYmxlcyBQUk9QRE1HLCBQUk9QRE1FR1hQLCBDUk9QRE1HIGFuZCBDUk9QRE1HRVhQIGVhY2ggcmVsYXRlIHRvIHRoZSBlY29ub21pYyBjb25zZXF1ZW5jZXMgY2F1c2VkIGJ5IHN0b3JtIGV2ZW50cy4gUFJPUERNRyBhbmQgUFJPUERNR0VYUCBnaXZlIHByb3BlcnR5IGRhbWFnZSB0b3RhbHMgd2l0aCBQUk9QRE1HRVhQIHByb3ZpZGluZyBhIG11bHRpcGxpZXIgZm9yIHRoZSBkYW1hZ2UgYW1vdW50IChjb2RlICJIIiBmb3IgaHVuZHJlZHMgb2YgZG9sbGFycywgIksiIGZvciB0aG91c2FuZHMsICJNIiBmb3IgbWlsbGlvbnMsIGV0Yy4pLiBDUk9QRE1HIGFuZCBDUk9QRE1HRVhQIGdpdmUgc2ltaWxhciBkYW1hZ2UgZXN0aW1hdGVzIGZvciBhZ3JpY3VsdHVyYWwgbG9zc2VzLg0KDQojIyMgQXNzZXNzbWVudCBvZiBoYXJtIHRvIHBvcHVsYXRpb24gaGVhbHRoDQoNCkZvciBlYXNlIG9mIHZpc3VhbGl6YXRpb24sIHN1YnNldHMgb2YgdGhlIGRhdGEgYXJlIGNyZWF0ZWQgY29udGFpbmluZyBvbmx5IGV2ZW50IHR5cGUgYW5kIGZhdGFsaXRpZXMvaW5qdXJpZXMuIFdlIHRoZW4gdGFrZSBhIGN1cnNvcnkgbG9vayBhdCB0aGUgZGF0YSB1c2luZyB0aGUgc3VtbWFyeSBmdW5jdGlvbi4NCmBgYHtyfQ0KZGVhdGggPC0gc3Rvcm1fZGF0YVssYyg4LDIzKV0NCmluanVyeSA8LSBzdG9ybV9kYXRhWyxjKDgsMjQpXQ0Kc3VtbWFyeShkZWF0aCRGQVRBTElUSUVTKQ0Kc3VtbWFyeShpbmp1cnkkSU5KVVJJRVMpDQpgYGANCg0KQm90aCB0aGUgZmF0YWxpdHkgYW5kIGluanVyeSB2YXJpYWJsZXMgY29udGFpbiBhIGxhcmdlIG51bWJlciBvZiB6ZXJvIHZhbHVlcy4gVGhvc2UgYXJlIHJlbW92ZWQgaGVyZSwgYW5kIHRoZSByZXN1bHRpbmcgZml2ZSBtb3N0IGZhdGFsL2luanVyaW91cyBldmVudCB0eXBlcyBhcmUgcmV0YWluZWQgZm9yIHBsb3R0aW5nLg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpkZWF0aCA8LSBkZWF0aFtkZWF0aCRGQVRBTElUSUVTID4gMCxdDQppbmp1cnkgPC0gaW5qdXJ5W2luanVyeSRJTkpVUklFUyA+IDAsXQ0KDQp0b3RhbF9kZWF0aHMgPC0gYWdncmVnYXRlKGRlYXRoJEZBVEFMSVRJRVMsIGJ5ID0gbGlzdChkZWF0aCRFVlRZUEUpLCBGVU4gPSAic3VtIikNCnRvdGFsX2RlYXRocyA8LSB0b3RhbF9kZWF0aHNbb3JkZXIoLXRvdGFsX2RlYXRoc1ssMl0pLF0NCnRvdGFsX2RlYXRocyA8LSB0b3RhbF9kZWF0aHNbMTo1LF0NCm5hbWVzKHRvdGFsX2RlYXRocykgPC0gYygiRXZlbnQiLCAiVG90YWxfRGVhdGhzIikNCnJvd25hbWVzKHRvdGFsX2RlYXRocykgPC0gTlVMTA0KDQp0b3RhbF9pbmp1cmllcyA8LSBhZ2dyZWdhdGUoaW5qdXJ5JElOSlVSSUVTLCBieSA9IGxpc3QoaW5qdXJ5JEVWVFlQRSksIEZVTiA9ICJzdW0iKQ0KdG90YWxfaW5qdXJpZXMgPC0gdG90YWxfaW5qdXJpZXNbb3JkZXIoLXRvdGFsX2luanVyaWVzWywyXSksXQ0KdG90YWxfaW5qdXJpZXMgPC0gdG90YWxfaW5qdXJpZXNbMTo1LF0NCm5hbWVzKHRvdGFsX2luanVyaWVzKSA8LSBjKCJFdmVudCIsICJUb3RhbF9Jbmp1cmllcyIpDQpyb3duYW1lcyh0b3RhbF9pbmp1cmllcykgPC0gTlVMTA0KYGBgDQoNCmdncGxvdDIgaXMgdXNlZCB0byBwbG90IHRoZSBkYXRhOg0KYGBge3J9DQpnZ3Bsb3QodG90YWxfZGVhdGhzLCBhZXMoeD1yZW9yZGVyKEV2ZW50LCAtVG90YWxfRGVhdGhzKSwgeT1Ub3RhbF9EZWF0aHMsIGZpbGw9RXZlbnQpKSArDQogIGxhYnModGl0bGUgPSAiVGhlIEZpdmUgRGVhZGxpZXN0IFdlYXRoZXIgRXZlbnQgVHlwZXMiLCB4ID0gIldlYXRoZXIgRXZlbnQiLCB5ID0gIlRvdGFsIERlYXRocyIpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArIHlsaW0oMCwgNjUwMCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIA0KDQpnZ3Bsb3QodG90YWxfaW5qdXJpZXMsIGFlcyh4PXJlb3JkZXIoRXZlbnQsIC1Ub3RhbF9Jbmp1cmllcyksIHk9VG90YWxfSW5qdXJpZXMsIGZpbGw9RXZlbnQpKSArDQogIGxhYnModGl0bGUgPSAiV2VhdGhlciBFdmVudCBUeXBlcyBUaGF0IENhdXNlIHRoZSBNb3N0IEluanVyaWVzIikgKw0KICBsYWJzKHggPSAiV2VhdGhlciBFdmVudCIsIHkgPSAiVG90YWwgSW5qdXJpZXMiKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyB5bGltKDAsIDEwMTAwMCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KIyMjIEFzc2Vzc21lbnQgb2YgRWNvbm9taWMgQ29uc2VxdW5jZXMNCg0KQXMgbm90ZWQgYWJvdmUsIHRoZSBlY29ub21pYyBjb25zZXF1ZW5jZSBkYXRhIHV0aWxpemVzIG11bHRpcGxpZXJzIGZvdW5kIGluIHZhcmlhYmxlcyBQUk9QRE1HRVhQIGFuZCBDUk9QRE1HRVhQIHRvIGRlc2NyaWJlIHRoZSB0b3RhbCBmaW5hbmNpYWwgbG9zcyBjYXVzZWQgYnkgYSBnaXZlbiBldmVudC4gUmVzcGVjdGl2ZWx5LCB0aGUgdHdvIG11bHRpcGxpZXIgdmFyaWFibGVzIGNvbnRhaW4gdGhlIGZvbGxvd2luZyBjb2RlczoNCmBgYHtyfQ0KbGV2ZWxzKGFzLmZhY3RvcihzdG9ybV9kYXRhJFBST1BETUdFWFApKQ0KbGV2ZWxzKGFzLmZhY3RvcihzdG9ybV9kYXRhJENST1BETUdFWFApKQ0KYGBgDQoNClRvIGVhc2UgYXNzZXNzbWVudCBvZiB0aGUgZmluYW5jaWFsIGxvc3MgZGF0YSwgc3Vic2V0cyBvZiB0aGUgZGF0YSBhcmUgYWdhaW4gY3JlYXRlZCBjb250YWluaW5nIG9ubHkgZXZlbnQgdHlwZSBhbmQgcHJvcGVydHkgb3IgZWNvbmltaWMgaGFybSBkYXRhLiBaZXJvIHZhbHVlcyBmb3IgZGFtYWdlIGFyZSBleGNsdWRlZCBzaW5jZSB0aGV5IGFyZSBub3QgcGVydGluZW50IHRvIHRoZSBxdWVzdGlvbiBwb3NlZC4NCmBgYHtyfQ0KcHJvcF9kYW1hZ2UgPC0gc3Rvcm1fZGF0YVssYyg4LDI1OjI2KV0NCnByb3BfZGFtYWdlIDwtIHByb3BfZGFtYWdlW3Byb3BfZGFtYWdlJFBST1BETUcgPiAwLF0NCg0KY3JvcF9kYW1hZ2UgPC0gc3Rvcm1fZGF0YVssYyg4LCAyNzoyOCldDQpjcm9wX2RhbWFnZSA8LSBjcm9wX2RhbWFnZVtjcm9wX2RhbWFnZSRDUk9QRE1HID4gMCxdDQpgYGANCg0KVGhlIHN1bW1hcnkgZnVuY3Rpb24gc2hvd3MgaG93IG1hbnkgdGltZXMgZWFjaCBtdWx0aXBsaWVyIGlzIHVzZWQgaW4gdGhlIHJlbWFpbmluZyBkYXRhLiAoVGhlIGZpcnN0IGVudHJ5IGluIGVhY2ggbGlzdCBpcyBhIGNvdW50IG9mIHRoZSBudW1iZXIgb2YgdGltZXMgbm8gbXVsdGlwbGllciB3YXMgaW5kaWNhdGVkLikNCmBgYHtyfQ0Kc3VtbWFyeShhcy5mYWN0b3IocHJvcF9kYW1hZ2UkUFJPUERNR0VYUCkpDQpzdW1tYXJ5KGFzLmZhY3Rvcihjcm9wX2RhbWFnZSRDUk9QRE1HRVhQKSkNCmBgYA0KDQpBIHNtYWxsIG51bWJlciBvZiB0aGUgcmVtYWluaW5nIG11bHRpcGxpZXJzIGhhdmUgdW5rbm93biBtZWFuaW5ncyAoaS5lLiB0aGV5IGFyZSBub3QgZGlzY3Vzc2VkIGluIHRoZSBkYXRhc2V0IGRvY3VtZW50YXRpb24pLiBUaGVzZSB2YWx1ZXMgYXJlOiAtLCA/LCArLCAwIHRocm91Z2ggOCwgYW5kIGJsYW5rIHNwYWNlcy4gQmVjYXVzZSB0aGVzZSBlbnRyaWVzIGFyZSBwcmVzZW50IGluIG9ubHkgMC4wMDEzJSBvZiB0aGUgcHJvcGVydHkgZGFtYWdlIGRhdGEgYW5kIDAuMDAwNjglIG9mIHRoZSBjcm9wIGRhbWFnZSBkYXRhLCB0aG9zZSByb3dzIGFyZSBleGNsdWRlZCBhcyBwb3NzaWJsZSBkYXRhIGVudHJ5IGVycm9ycy4NCmBgYHtyfQ0KcHJvcF9kYW1hZ2UgPC0gcHJvcF9kYW1hZ2VbKHByb3BfZGFtYWdlJFBST1BETUdFWFAgPT0gIkIiKSB8IChwcm9wX2RhbWFnZSRQUk9QRE1HRVhQID09ICJoIikgfA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgKHByb3BfZGFtYWdlJFBST1BETUdFWFAgPT0gIkgiKSB8IChwcm9wX2RhbWFnZSRQUk9QRE1HRVhQID09ICJLIikgfA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgKHByb3BfZGFtYWdlJFBST1BETUdFWFAgPT0gIm0iKSB8IChwcm9wX2RhbWFnZSRQUk9QRE1HRVhQID09ICJNIiksXQ0KDQpjcm9wX2RhbWFnZSA8LSBjcm9wX2RhbWFnZVsoY3JvcF9kYW1hZ2UkQ1JPUERNR0VYUCA9PSAiQiIpIHwgKGNyb3BfZGFtYWdlJENST1BETUdFWFAgPT0gImsiKSB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAoY3JvcF9kYW1hZ2UkQ1JPUERNR0VYUCA9PSAiSyIpIHwgKGNyb3BfZGFtYWdlJENST1BETUdFWFAgPT0gIm0iKSB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAoY3JvcF9kYW1hZ2UkQ1JPUERNR0VYUCA9PSAiTSIpLF0NCmBgYA0KDQpUaGUgbXVsdGlwbGllcnMgYXJlIG5vdyB1c2VkIHRvIGFkanVzdCB0aGUgcHJvcGVydHkgYW5kIGNyb3AgZGFtYWdlIHZhbHVlcy4NCmBgYHtyfQ0KcHJvcF9kYW1hZ2UkUFJPUERNR0VYUFtwcm9wX2RhbWFnZSRQUk9QRE1HRVhQID09ICJCIl0gPC0gMTAwMDAwMDAwMA0KcHJvcF9kYW1hZ2UkUFJPUERNR0VYUFtwcm9wX2RhbWFnZSRQUk9QRE1HRVhQID09ICJNIl0gPC0gMTAwMDAwMA0KcHJvcF9kYW1hZ2UkUFJPUERNR0VYUFtwcm9wX2RhbWFnZSRQUk9QRE1HRVhQID09ICJtIl0gPC0gMTAwMDAwMA0KcHJvcF9kYW1hZ2UkUFJPUERNR0VYUFtwcm9wX2RhbWFnZSRQUk9QRE1HRVhQID09ICJLIl0gPC0gMTAwMA0KcHJvcF9kYW1hZ2UkUFJPUERNR0VYUFtwcm9wX2RhbWFnZSRQUk9QRE1HRVhQID09ICJIIl0gPC0gMTAwDQpwcm9wX2RhbWFnZSRQUk9QRE1HRVhQW3Byb3BfZGFtYWdlJFBST1BETUdFWFAgPT0gImgiXSA8LSAxMDANCg0KY3JvcF9kYW1hZ2UkQ1JPUERNR0VYUFtjcm9wX2RhbWFnZSRDUk9QRE1HRVhQID09ICJCIl0gPC0gMTAwMDAwMDAwMA0KY3JvcF9kYW1hZ2UkQ1JPUERNR0VYUFtjcm9wX2RhbWFnZSRDUk9QRE1HRVhQID09ICJNIl0gPC0gMTAwMDAwMA0KY3JvcF9kYW1hZ2UkQ1JPUERNR0VYUFtjcm9wX2RhbWFnZSRDUk9QRE1HRVhQID09ICJtIl0gPC0gMTAwMDAwMA0KY3JvcF9kYW1hZ2UkQ1JPUERNR0VYUFtjcm9wX2RhbWFnZSRDUk9QRE1HRVhQID09ICJLIl0gPC0gMTAwMA0KY3JvcF9kYW1hZ2UkQ1JPUERNR0VYUFtjcm9wX2RhbWFnZSRDUk9QRE1HRVhQID09ICJLIl0gPC0gMTAwMA0KDQpwcm9wX2RhbWFnZSRBREpQUk9QRE1HIDwtIHByb3BfZGFtYWdlJFBST1BETUcgKiBhcy5udW1lcmljKHByb3BfZGFtYWdlJFBST1BETUdFWFApDQpjcm9wX2RhbWFnZSRBREpDUk9QRE1HIDwtIGNyb3BfZGFtYWdlJENST1BETUcgKiBhcy5udW1lcmljKGNyb3BfZGFtYWdlJENST1BETUdFWFApDQpgYGANCg0KRmluYWxseSwgdGhlIG1vc3QgZGFtYWdpbmcgc3Rvcm0gZXZlbnRzIGFyZSBpZGVudGlmaWVkOg0KYGBge3J9DQpwcm9wX2RhbWFnZSA8LSBhZ2dyZWdhdGUocHJvcF9kYW1hZ2UkQURKUFJPUERNRywgYnkgPSBsaXN0KHByb3BfZGFtYWdlJEVWVFlQRSksIEZVTiA9ICJzdW0iKQ0KcHJvcF9kYW1hZ2UgPC0gcHJvcF9kYW1hZ2Vbb3JkZXIoLXByb3BfZGFtYWdlWywyXSksXQ0KbmFtZXMocHJvcF9kYW1hZ2UpIDwtIGMoIkV2ZW50IiwgIlByb3BfRGFtYWdlIikNCg0KY3JvcF9kYW1hZ2UgPC0gYWdncmVnYXRlKGNyb3BfZGFtYWdlJEFESkNST1BETUcsIGJ5ID0gbGlzdChjcm9wX2RhbWFnZSRFVlRZUEUpLCBGVU4gPSAic3VtIikNCmNyb3BfZGFtYWdlIDwtIGNyb3BfZGFtYWdlW29yZGVyKC1jcm9wX2RhbWFnZVssMl0pLF0NCm5hbWVzKGNyb3BfZGFtYWdlKSA8LSBjKCJFdmVudCIsICJDcm9wX0RhbWFnZSIpDQoNCnRvdGFsIDwtIG1lcmdlKHByb3BfZGFtYWdlLCBjcm9wX2RhbWFnZSwgYnk9IkV2ZW50IikNCnRvdGFsW2lzLm5hKHRvdGFsKV0gPC0gMA0KdG90YWwkTG9zc2VzIDwtIHRvdGFsJFByb3BfRGFtYWdlICsgdG90YWwkQ3JvcF9EYW1hZ2UNCnRvdGFsIDwtIHRvdGFsW29yZGVyKC10b3RhbFssNF0pLF0NCnJvdy5uYW1lcyh0b3RhbCkgPSBOVUxMDQp0b3RhbCA8LSB0b3RhbFsxOjEwLF0NCnRvdGFsJExvc3NlcyA8LSB0b3RhbCRMb3NzZXMvMWUrMDkNCnRvdGFsDQpgYGANCg0KVGhlIGVjb25vbWljIGxvc3MgaW5mb3JtYXRpb24gaXMgYWxzbyBzdW1tYXJpemVkIHZpc3VhbGx5IGhlcmU6DQpgYGB7cn0NCmdncGxvdChkYXRhID0gdG90YWwsIGFlcyh4PXJlb3JkZXIoRXZlbnQsIC1Mb3NzZXMpLCB5PUxvc3NlcykpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChMb3NzZXMsMikpLCBjb2xvcj0id2hpdGUiLCB2anVzdD0gMSwgc2l6ZT0zKSArDQogIGxhYnModGl0bGUgPSAiRWNvbm9taWMgTG9zc2VzIEF0dHJpYnV0YWJsZSB0byBXZWF0aGVyIEV2ZW50cyIpICsNCiAgbGFicyh4ID0gIkV2ZW50IiwgeSA9ICJMb3NzZXMgaW4gQmlsbGlvbnMgb2YgRG9sbGFycyIpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSA4KSkNCmBgYA0KDQojIyBSZXN1bHRzOg0KDQpDbGVhcmx5LCB0b3JuYWRvZXMgcG9zZSB0aGUgZ3JlYXRlc3QgcmlzayBvZiBpbmp1cnkgb3IgZGVhdGggb2YgYW55IHdlYXRoZXIgZXZlbnQgaW4gdGhlIFVuaXRlZCBTdGF0ZXMuIFRvcm5hZG9lcyBoYXZlIGNhdXNlZCBuZWFybHkgdGhyZWUgdGltZXMgYXMgbWFueSBkZWF0aHMgYW5kIHRlbnMgb2YgdGhvdXNhbmRzIG1vcmUgaW5qdXJpZXMuIE9uIHRoZSBvdGhlciBoYW5kLCB3aGlsZSB0b3JuYWRvZXMgaGF2ZSBoYWQgYSBzaWduaWZpY2FudCBlY29ub21pYyBpbXBhY3Qgb3ZlciB0aGUgeWVhcnMsIHRoZXkgZG8gbm90IGNhdXNlIHRoZSBtb3N0IGZpbmFuY2lhbCBkYW1hZ2UuIFJhdGhlciwgZmxvb2RpbmcgaGFzIGJlZW4gdGhlIG1vc3QgZWNvbm9taWNhbGx5IHNpZ25pZmljYW50IHdlYXRoZXIgZXZlbnQgaW4gdGhlIFUuUy4gYnkgYSBsYXJnZSBtYXJnaW4uDQoNCg==