Required packages

The packages used in this project.

library(dplyr)
library(readr)
library(ggplot2)
library(stringr)
library(tidyr)
library(lubridate)
library(magrittr)
library(outliers)

Executive Summary

Data preprocessing is an imperative step in the data preparation stage of the Data Science process. For learning purposes, the decision was made to merge and preprocess two datasets. To keep with the times, a Covid-19 dataset and a SARS dataset was taken from Kaggle in order to investigate the idea of which pandemic is more fatal. The two selected datasets required much preprocessing. While both datasets required some common preprocessing such as the renaming of columns and selected row values, one dataset was relatively untidy. In the Covid dataset, one of the columns had both date and time combined inconsistently, while also having different date formats. This column needed to be split up and formatted appropriately in preparation for merging the two selected datasets for this project. Before merging the two datasets, the Covid dataset had to be further manipulated in order to be able to be properly merged with the SARS dataset. Once the datasets have been merged, one final data cleaning needed to be done to the newly merged dataset. With the merged dataset, a new variable was mutated in order to compare the deadliness of the two pandemics. The dataset also needed to be scanned for missing values, special values and outliers. However, at that point the dataset had been appropriately cleaned so no missing values or special values were found. The outliers were found but was justifiably left alone as they were important values. While data normalisation was attempted on the variables of the dataset, the results of the transformation did not yield any interesting results. Overall, the main goal of the project was successfully reached – with results supporting the notion that SARS is the more fatal pandemic compared to Covid-19.

Data description & Data importing

The Covid dataset was collected for research purposes by SRK from the John Hopkins University and posted on Kaggle. The dataset can be found on Kaggle(https://www.kaggle.com/sudalairajkumar/novel-corona-virus-2019-dataset?select=covid_19_data.csv). This repository contains many different csv files. But for this project, only the Covid-19 dataset will be the point of focus from this repository. The aforementioned Covid-19 dataset in the “covid_19_data.csv” file contains the following variables:

The SARS dataset was collected for research purposes by Devakumar kp from the World Health Organization website and posted on Kaggle. The dataset can be found on Kaggle(https://www.kaggle.com/imdevskp/sars-outbreak-2003-complete-dataset). This repository contains two different csv files. But for this project, only the cleaned summary dataset will be the point of focus from this repository. The aforementioned Sars dataset in the “summary_data_clean.csv” file contains the following variables:

———————————————————————————————————–

The goal of this project is to clean the Covid-19 dataset and merge it with a cleaned SARS dataset. Then, mutate a Covid fatality ratio variable so it can be compared to the Sars fatality ratio in order to find out which pandemic is deadlier based on countries.

———————————————————————————————————–

To achieve this, the datasets will firstly be imported and subsetted. The datasets need to be subsetted as both datasets contain columns that are not relevant to the goal of this project. The datasets were subsetted as follows:

# Import the data
covidRaw <- read_csv("covid_19_data.csv")
Parsed with column specification:
cols(
  SNo = col_double(),
  ObservationDate = col_character(),
  `Province/State` = col_character(),
  `Country/Region` = col_character(),
  `Last Update` = col_character(),
  Confirmed = col_double(),
  Deaths = col_double(),
  Recovered = col_double()
)
sarsRaw <- read_csv("summary_data_clean.csv")
Parsed with column specification:
cols(
  `Country/Region` = col_character(),
  `Cumulative male cases` = col_double(),
  `Cumulative female cases` = col_double(),
  `Cumulative total cases` = col_double(),
  `No. of deaths` = col_double(),
  `Case fatalities ratio (%)` = col_double(),
  `Date onset first probable case` = col_date(format = ""),
  `Date onset last probable case` = col_date(format = ""),
  `Median age` = col_double(),
  `Age range` = col_character(),
  `Number of Imported cases` = col_double(),
  `Percentage of Imported cases` = col_double(),
  `Number of HCW affected` = col_double(),
  `Percentage of HCW affected` = col_double()
)
# Subset data
covid <- covidRaw[, c(2,4:7)]
sars <- sarsRaw[, c(1,4:8)]
# Print the data
head(covid)
head(sars)

Data cleaning I

After importing the datasets, the data needs to be briefly cleaned before tidying begins. The first thing that was done was to rename the columns for both datasets for consistency purposes. Then, selected rows of both datasets are also renamed for consistency and correctness purposes (Eg. in the Sars dataset, Vietnam was written as Viet Nam which is incorrect). Then, the structure of the datasets were inspected, and various data types were identified for both datasets. While the data type conversions will occur later in the process (Data cleaning II), the dates for both datasets were formatted for consistency.

# Inspecting and renaming columns for consistency purposes
colnames(covid)
[1] "ObservationDate" "Country/Region"  "Last Update"     "Confirmed"       "Deaths"         
covid %<>% rename(`CovidConfirmedCases` = "Confirmed", `CovidDeaths` = "Deaths",
                 `Covid First Observations` = "ObservationDate", `Covid Last Update` = "Last Update")
colnames(sars)
[1] "Country/Region"                 "Cumulative total cases"         "No. of deaths"                 
[4] "Case fatalities ratio (%)"      "Date onset first probable case" "Date onset last probable case" 
sars %<>% rename(`Sars Total Cases` = "Cumulative total cases",
                 `Sars Deaths` = "No. of deaths",
                 `Sars Fatality Ratio (%)` = "Case fatalities ratio (%)",
                 `Sars First Probable Case Date` = "Date onset first probable case",
                 `Sars Last Probable Case Date` = "Date onset last probable case")
# Inspecting and renaming rows for consistency purposes
unique(covid$`Country/Region`)
  [1] "Mainland China"                   "Hong Kong"                       
  [3] "Macau"                            "Taiwan"                          
  [5] "US"                               "Japan"                           
  [7] "Thailand"                         "South Korea"                     
  [9] "Singapore"                        "Philippines"                     
 [11] "Malaysia"                         "Vietnam"                         
 [13] "Australia"                        "Mexico"                          
 [15] "Brazil"                           "Colombia"                        
 [17] "France"                           "Nepal"                           
 [19] "Canada"                           "Cambodia"                        
 [21] "Sri Lanka"                        "Ivory Coast"                     
 [23] "Germany"                          "Finland"                         
 [25] "United Arab Emirates"             "India"                           
 [27] "Italy"                            "UK"                              
 [29] "Russia"                           "Sweden"                          
 [31] "Spain"                            "Belgium"                         
 [33] "Others"                           "Egypt"                           
 [35] "Iran"                             "Israel"                          
 [37] "Lebanon"                          "Iraq"                            
 [39] "Oman"                             "Afghanistan"                     
 [41] "Bahrain"                          "Kuwait"                          
 [43] "Austria"                          "Algeria"                         
 [45] "Croatia"                          "Switzerland"                     
 [47] "Pakistan"                         "Georgia"                         
 [49] "Greece"                           "North Macedonia"                 
 [51] "Norway"                           "Romania"                         
 [53] "Denmark"                          "Estonia"                         
 [55] "Netherlands"                      "San Marino"                      
 [57] "Azerbaijan"                       "Belarus"                         
 [59] "Iceland"                          "Lithuania"                       
 [61] "New Zealand"                      "Nigeria"                         
 [63] "North Ireland"                    "Ireland"                         
 [65] "Luxembourg"                       "Monaco"                          
 [67] "Qatar"                            "Ecuador"                         
 [69] "Czech Republic"                   "Armenia"                         
 [71] "Dominican Republic"               "Indonesia"                       
 [73] "Portugal"                         "Andorra"                         
 [75] "Latvia"                           "Morocco"                         
 [77] "Saudi Arabia"                     "Senegal"                         
 [79] "Argentina"                        "Chile"                           
 [81] "Jordan"                           "Ukraine"                         
 [83] "Saint Barthelemy"                 "Hungary"                         
 [85] "Faroe Islands"                    "Gibraltar"                       
 [87] "Liechtenstein"                    "Poland"                          
 [89] "Tunisia"                          "Palestine"                       
 [91] "Bosnia and Herzegovina"           "Slovenia"                        
 [93] "South Africa"                     "Bhutan"                          
 [95] "Cameroon"                         "Costa Rica"                      
 [97] "Peru"                             "Serbia"                          
 [99] "Slovakia"                         "Togo"                            
[101] "Vatican City"                     "French Guiana"                   
[103] "Malta"                            "Martinique"                      
[105] "Republic of Ireland"              "Bulgaria"                        
[107] "Maldives"                         "Bangladesh"                      
[109] "Moldova"                          "Paraguay"                        
[111] "Albania"                          "Cyprus"                          
[113] "St. Martin"                       "Brunei"                          
[115] "occupied Palestinian territory"   "('St. Martin',)"                 
[117] "Burkina Faso"                     "Channel Islands"                 
[119] "Holy See"                         "Mongolia"                        
[121] "Panama"                           "Bolivia"                         
[123] "Honduras"                         "Congo (Kinshasa)"                
[125] "Jamaica"                          "Reunion"                         
[127] "Turkey"                           "Cuba"                            
[129] "Guyana"                           "Kazakhstan"                      
[131] "Cayman Islands"                   "Guadeloupe"                      
[133] "Ethiopia"                         "Sudan"                           
[135] "Guinea"                           "Antigua and Barbuda"             
[137] "Aruba"                            "Kenya"                           
[139] "Uruguay"                          "Ghana"                           
[141] "Jersey"                           "Namibia"                         
[143] "Seychelles"                       "Trinidad and Tobago"             
[145] "Venezuela"                        "Curacao"                         
[147] "Eswatini"                         "Gabon"                           
[149] "Guatemala"                        "Guernsey"                        
[151] "Mauritania"                       "Rwanda"                          
[153] "Saint Lucia"                      "Saint Vincent and the Grenadines"
[155] "Suriname"                         "Kosovo"                          
[157] "Central African Republic"         "Congo (Brazzaville)"             
[159] "Equatorial Guinea"                "Uzbekistan"                      
[161] "Guam"                             "Puerto Rico"                     
[163] "Benin"                            "Greenland"                       
[165] "Liberia"                          "Mayotte"                         
[167] "Republic of the Congo"            "Somalia"                         
[169] "Tanzania"                         "The Bahamas"                     
[171] "Barbados"                         "Montenegro"                      
[173] "The Gambia"                       "Kyrgyzstan"                      
[175] "Mauritius"                        "Zambia"                          
[177] "Djibouti"                         "Gambia, The"                     
[179] "Bahamas, The"                     "Chad"                            
[181] "El Salvador"                      "Fiji"                            
[183] "Nicaragua"                        "Madagascar"                      
[185] "Haiti"                            "Angola"                          
[187] "Cabo Verde"                       "Niger"                           
[189] "Papua New Guinea"                 "Zimbabwe"                        
[191] "Cape Verde"                       "East Timor"                      
[193] "Eritrea"                          "Uganda"                          
[195] "Bahamas"                          "Dominica"                        
[197] "Gambia"                           "Grenada"                         
[199] "Mozambique"                       "Syria"                           
[201] "Timor-Leste"                      "Belize"                          
[203] "Laos"                             "Libya"                           
[205] "Diamond Princess"                 "Guinea-Bissau"                   
[207] "Mali"                             "Saint Kitts and Nevis"           
[209] "West Bank and Gaza"               "Burma"                           
[211] "MS Zaandam"                       "Botswana"                        
[213] "Burundi"                          "Sierra Leone"                    
[215] "Malawi"                           "South Sudan"                     
[217] "Western Sahara"                   "Sao Tome and Principe"           
[219] "Yemen"                            "Comoros"                         
[221] "Tajikistan"                       "Lesotho"                         
covid$`Country/Region`[covid$`Country/Region` == "UK"] <- "United Kingdom"
covid$`Country/Region`[covid$`Country/Region` == "US"] <- "United States"
unique(sars$`Country/Region`)
 [1] "Australia"            "Canada"               "China"                "Hong Kong SAR, China"
 [5] "Macao SAR, China"     "Taiwan"               "France"               "Germany"             
 [9] "India"                "Indonesia"            "Italy"                "Kuwait"              
[13] "Malaysia"             "Mongolia"             "New Zealand"          "Philippines"         
[17] "Republic of Ireland"  "Republic of Korea"    "Romania"              "Russian Federation"  
[21] "Singapore"            "South Africa"         "Spain"                "Sweden"              
[25] "Switzerland"          "Thailand"             "United Kingdom"       "United States"       
[29] "Viet Nam"            
sars[3, 1] <- "Mainland China"
sars[4, 1] <- "Hong Kong"
sars[5, 1] <- "Macau"
sars[18, 1] <- "South Korea"
sars[20, 1] <- "Russia"
sars[29, 1] <- "Vietnam"# Renaming mispelled `Viet Nam` to `Vietnam`
# Inspecting the structure of the datasets and making the date format consistent for the Covid dataset
str(covid)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   27618 obs. of  5 variables:
 $ Covid First Observations: chr  "01/22/2020" "01/22/2020" "01/22/2020" "01/22/2020" ...
 $ Country/Region          : chr  "Mainland China" "Mainland China" "Mainland China" "Mainland China" ...
 $ Covid Last Update       : chr  "1/22/2020 17:00" "1/22/2020 17:00" "1/22/2020 17:00" "1/22/2020 17:00" ...
 $ CovidConfirmedCases     : num  1 14 6 1 0 26 2 1 4 1 ...
 $ CovidDeaths             : num  0 0 0 0 0 0 0 0 0 0 ...
covid$`Covid First Observations` <- as.Date(covid$`Covid First Observations`, "%m/%d/%Y")
covid$`Covid First Observations` <- format(as.Date(covid$`Covid First Observations`, format = "%Y-%m-%d"), "%d/%m/%Y")
head(covid)
# Inspecting the structure of the datasets and making the date format consistent for the Sars dataset
str(sars)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   29 obs. of  6 variables:
 $ Country/Region               : chr  "Australia" "Canada" "Mainland China" "Hong Kong" ...
 $ Sars Total Cases             : num  6 251 5327 1755 1 ...
 $ Sars Deaths                  : num  0 43 349 299 0 37 1 0 0 0 ...
 $ Sars Fatality Ratio (%)      : num  0 17 7 17 0 11 14 0 0 0 ...
 $ Sars First Probable Case Date: Date, format: "2003-02-26" "2003-02-23" "2002-11-16" ...
 $ Sars Last Probable Case Date : Date, format: "2003-04-01" "2003-06-12" "2003-06-03" ...
sars$`Sars First Probable Case Date` <- strftime(sars$`Sars First Probable Case Date`, "%d/%m/%Y")
sars$`Sars Last Probable Case Date` <- strftime(sars$`Sars Last Probable Case Date`, "%d/%m/%Y")
head(sars)

Tidy & Manipulate Data I

Once the data has been briefly cleaned, it is time to tidy up the dataset. The Covid dataset is untidy as it contains multiple coulmns that are not necessary for the projects goal; which has been removed in the first section. The Covid dataset also possesses a column that contains both date and time (and some of them have letters instead of whitespaces as seperators). This is not tidy according to Hadley Wickham’s tidy principles which states that each value must have its own cell. To remedy this problem, the column was split into two using a tidyr function with a regex seperator. The date column was then restructured using the parse_date_time() function as the column had multiple different date formats. The Covid dataset was now much tidier than before once the unnecessary columns were removed and the untidy column was separated and formatted appropriately.

# Splitting the covidLastUpdate column
splitCovid <- separate(covid, `Covid Last Update`, c("Covid Last Update", "Last Update Time"), sep = "T|[:space:]")
# Tidying up the new column
unique(splitCovid$`Covid Last Update`)
  [1] "1/22/2020"  "1/23/20"    "1/24/20"    "1/25/20"    "1/26/20"    "1/27/20"    "1/28/20"   
  [8] "1/29/20"    "1/30/20"    "1/31/2020"  "2/1/2020"   "2020-02-02" "2020-02-01" "2020-01-31"
 [15] "2020-02-03" "2020-02-04" "2020-02-05" "2020-02-06" "2020-02-07" "2020-02-08" "2020-02-09"
 [22] "2020-02-10" "2020-02-11" "2020-02-12" "2020-02-13" "2020-02-14" "2020-02-15" "2020-02-16"
 [29] "2020-02-17" "2020-02-18" "2020-02-19" "2020-02-20" "2020-02-21" "2020-02-22" "2020-02-23"
 [36] "2020-02-24" "2020-02-25" "2020-02-26" "2020-02-27" "2020-02-28" "2020-02-29" "2020-03-01"
 [43] "2020-03-02" "2020-03-03" "2020-03-04" "2020-03-05" "2020-03-06" "2020-03-07" "2020-03-08"
 [50] "2020-03-09" "2020-03-10" "2020-03-11" "2020-03-12" "2020-03-13" "2020-03-14" "2020-03-15"
 [57] "2020-03-16" "2020-03-17" "2020-03-18" "2020-03-19" "2020-03-20" "2020-03-21" "3/8/20"    
 [64] "2020-03-23" "2020-03-24" "2020-03-25" "2020-03-26" "2020-03-27" "2020-03-31" "2020-04-01"
 [71] "4/2/20"     "2020-04-03" "4/4/20"     "2020-04-05" "4/6/20"     "2020-04-07" "2020-04-08"
 [78] "2020-04-09" "2020-04-10" "2020-04-11" "2020-04-12" "2020-04-13" "2020-04-14" "2020-04-15"
 [85] "2020-04-16" "2020-04-17" "2020-04-18" "2020-04-19" "2020-04-20" "2020-04-21" "2020-04-22"
 [92] "2020-04-24" "2020-04-25" "2020-04-26" "2020-04-27" "2020-04-28" "2020-04-29" "2020-04-30"
 [99] "2020-05-01" "2020-05-02" "2020-05-03" "2020-05-04" "2020-05-05" "2020-05-06" "2020-05-07"
[106] "2020-05-08" "2020-05-09" "2020-05-10" "2020-05-11" "2020-05-12" "2020-05-13" "2020-05-14"
[113] "2020-05-15" "2020-05-16" "2020-05-17" "2020-05-18" "2020-05-19" "2020-05-20" "2020-05-21"
[120] "2020-05-22"
splitCovid$`Covid Last Update` <- parse_date_time(x = splitCovid$`Covid Last Update`, orders = c("m d y", "y m d"))
head(splitCovid)
str(splitCovid)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   27618 obs. of  6 variables:
 $ Covid First Observations: chr  "22/01/2020" "22/01/2020" "22/01/2020" "22/01/2020" ...
 $ Country/Region          : chr  "Mainland China" "Mainland China" "Mainland China" "Mainland China" ...
 $ Covid Last Update       : POSIXct, format: "2020-01-22" "2020-01-22" "2020-01-22" ...
 $ Last Update Time        : chr  "17:00" "17:00" "17:00" "17:00" ...
 $ CovidConfirmedCases     : num  1 14 6 1 0 26 2 1 4 1 ...
 $ CovidDeaths             : num  0 0 0 0 0 0 0 0 0 0 ...

Merging the Data

Once the Covid dataset has been made tidy, the Sars dataset and Covid dataset can be merged together. The first step is to remove more unnecessary columns. The first was to drop the time column in the splitCovid dataset, that was attained from the section above as it serves no purpose for the goal of this project. The next step was to subset the splitCovid to a dataset that contained the countries and the concatenation of the total covid cases and total covid deaths by country. This dataset was called covidCases.

After that step, it was time to focus on the dates. The splitCovid was subset to two datasets, one for the latest updated Covid date by country and one by the earliest Covid date by country. Once these two datasets were complete, they were then merged together along with the covidCases set in order to attain the final covid dataset called covidSet. A right_join was used to combine covidFirstDate and covidCases as we want to prioritize the covidCases dataset. A left_join was used to merge the covidLastDate in as we want to prioritize the prior combined covidFirstDate and covidCases dataset.

Once the covidSet was completed, it was then finally merged with the Sars dataset using a left_join as we only want the countries that are in the Sars dataset (as the covid dataset has more countries than the Sars dataset)

# Dropping the time column
splitCovid <- select(splitCovid, -c(`Last Update Time`))
# Summarise all the total covid cases and total covid deaths by country
covidCases <- splitCovid %>% 
  group_by(`Country/Region`) %>% 
  summarise(sum(CovidConfirmedCases), sum(CovidDeaths))
# Get the latest updated Covid date by country
covidLastDate <- splitCovid %>% 
  group_by(`Country/Region`) %>% 
  filter(`Covid Last Update` == max(`Covid Last Update`)) %>% 
  select(-c(`Covid First Observations`, `CovidConfirmedCases`, `CovidDeaths`))
# Get the earliest Covid date by country
covidFirstDate <- splitCovid %>% 
  group_by(`Country/Region`) %>% 
  filter(`Covid First Observations` == min(`Covid First Observations`)) %>% 
  select(-c(`Covid Last Update`, `CovidConfirmedCases`, `CovidDeaths`))
# Combine both dates with the covidCases while removing all duplicate rows
covidSet <- covidFirstDate %>% 
  group_by(`Country/Region`, `Covid First Observations`) %>% 
  right_join(covidCases, by="Country/Region") %>% 
  left_join(covidLastDate, by="Country/Region") %>% 
  distinct()
# Combine the covidSet with the Sars dataset
combinedSet <- left_join(sars, covidSet)
Joining, by = "Country/Region"
str(combinedSet)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   29 obs. of  10 variables:
 $ Country/Region               : chr  "Australia" "Canada" "Mainland China" "Hong Kong" ...
 $ Sars Total Cases             : num  6 251 5327 1755 1 ...
 $ Sars Deaths                  : num  0 43 349 299 0 37 1 0 0 0 ...
 $ Sars Fatality Ratio (%)      : num  0 17 7 17 0 11 14 0 0 0 ...
 $ Sars First Probable Case Date: chr  "26/02/2003" "23/02/2003" "16/11/2002" "15/02/2003" ...
 $ Sars Last Probable Case Date : chr  "01/04/2003" "12/06/2003" "03/06/2003" "31/05/2003" ...
 $ Covid First Observations     : chr  "01/02/2020" "01/02/2020" "01/02/2020" "01/02/2020" ...
 $ sum(CovidConfirmedCases)     : num  370129 2464766 8386881 61059 3165 ...
 $ sum(CovidDeaths)             : num  4055 146966 361112 346 0 ...
 $ Covid Last Update            : POSIXct, format: "2020-05-22" "2020-05-22" "2020-05-22" ...
head(combinedSet)

Data cleaning II

Once the datasets have been successfully merged, it is time to clean up the new dataset. This step entails the renaming and reordering of columns for consistency in the structure of the dataset. Appropriate data type conversions will also be performed, converting the “Country/Region” column to a factor data type, and also converting the date columns appropriately using lubridate functions.

# Factor data type conversion
combinedSet$`Country/Region` <- factor(combinedSet$`Country/Region`, levels = c("Australia", "Canada", "France", "Germany", "Hong Kong", "India", "Indonesia", "Italy", "Kuwait", "Macau", "Mainland China", "Malaysia", "Mongolia", "New Zealand", "Philippines", "Republic of Ireland", "Romania", "Russia", "Singapore", "South Africa", "South Korea", "Spain", "Sweden", "Switzerland", "Taiwan", "Thailand", "United Kingdom", "United States", "Vietnam"), labels = c("Australia", "Canada", "France", "Germany", "Hong Kong", "India", "Indonesia", "Italy", "Kuwait", "Macau", "Mainland China", "Malaysia", "Mongolia", "New Zealand", "Philippines", "Republic of Ireland", "Romania", "Russia", "Singapore", "South Africa", "South Korea", "Spain", "Sweden", "Switzerland", "Taiwan", "Thailand", "United Kingdom", "United States", "Vietnam"), ordered = FALSE)
# Name and structure cleaning
names(combinedSet)[7] <- "Covid First Probable Case Date"
names(combinedSet)[8] <- "Covid Total Cases"
names(combinedSet)[9] <- "Covid Deaths"
names(combinedSet)[10] <- "Covid Last Updated Case Date"
combinedSet$`Covid Last Updated Case Date` <- strftime(combinedSet$`Covid Last Updated Case Date`, "%d/%m/%Y")
col_order <- c("Country/Region", "Sars First Probable Case Date", "Sars Last Probable Case Date", "Sars Total Cases", "Sars Deaths", "Sars Fatality Ratio (%)", "Covid First Probable Case Date", "Covid Last Updated Case Date", "Covid Total Cases", "Covid Deaths")
cleanSet <- combinedSet[, col_order]
# Date data type conversion
cleanSet$`Sars First Probable Case Date` <- dmy(cleanSet$`Sars First Probable Case Date`)
cleanSet$`Sars Last Probable Case Date` <- dmy(cleanSet$`Sars Last Probable Case Date`)
cleanSet$`Covid First Probable Case Date` <- dmy(cleanSet$`Covid First Probable Case Date`)
cleanSet$`Covid Last Updated Case Date` <- dmy(cleanSet$`Covid Last Updated Case Date`)
str(cleanSet)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   29 obs. of  10 variables:
 $ Country/Region                : Factor w/ 29 levels "Australia","Canada",..: 1 2 11 5 10 25 3 4 6 7 ...
 $ Sars First Probable Case Date : Date, format: "2003-02-26" "2003-02-23" "2002-11-16" ...
 $ Sars Last Probable Case Date  : Date, format: "2003-04-01" "2003-06-12" "2003-06-03" ...
 $ Sars Total Cases              : num  6 251 5327 1755 1 ...
 $ Sars Deaths                   : num  0 43 349 299 0 37 1 0 0 0 ...
 $ Sars Fatality Ratio (%)       : num  0 17 7 17 0 11 14 0 0 0 ...
 $ Covid First Probable Case Date: Date, format: "2020-02-01" "2020-02-01" "2020-02-01" ...
 $ Covid Last Updated Case Date  : Date, format: "2020-05-22" "2020-05-22" "2020-05-22" ...
 $ Covid Total Cases             : num  370129 2464766 8386881 61059 3165 ...
 $ Covid Deaths                  : num  4055 146966 361112 346 0 ...
head(cleanSet)

Tidy & Manipulate Data II

Once we have a cleaned set that has both Sars and Covid cases; referring to the original goals of the project, one of which was to find the deadlier pandemic. This requires a mutation of a Covid Fatality Ratio variable so it can be compared to the Sars Fatality Ratio (%) variable (which is already in the dataset). To achieve this, a mutation where the Covid Deaths are divided by Covid Total Cases and multiplied by 100 in order to attain the ratio value in percentage - exactly like the Sars Fatality Ratio (%) variable.

# Mutating the Covid Fatality Ratio (%) variable by using the following formula and rounding the answer
cleanSet %<>% mutate(`Covid Fatality Ratio (%)` = round((`Covid Deaths`/`Covid Total Cases`*100)))
head(cleanSet)

Scan I

Once the dataset is clean and tidy, we can then move on to scanning for missing or special values. To scan for missing values, using the print(colSums(is.na())) function is very helpful. For scanning special values, a function was made that checks every numerical column if they possess infinite or NaN values called valueChecker. This was then applied to the cleaned dataset. The results showed that the dataset contains no missing values or special values.

# Scanning for missing values
print(colSums(is.na(cleanSet)))
                Country/Region  Sars First Probable Case Date   Sars Last Probable Case Date 
                             0                              0                              0 
              Sars Total Cases                    Sars Deaths        Sars Fatality Ratio (%) 
                             0                              0                              0 
Covid First Probable Case Date   Covid Last Updated Case Date              Covid Total Cases 
                             0                              0                              0 
                  Covid Deaths       Covid Fatality Ratio (%) 
                             0                              0 
# Scanning for special values
specialValueChecker <- function(x) {
  if(is.numeric(x)) (is.infinite(x) | is.nan(x))
}
sapply(cleanSet, specialValueChecker)
$`Country/Region`
NULL

$`Sars First Probable Case Date`
NULL

$`Sars Last Probable Case Date`
NULL

$`Sars Total Cases`
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[18] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$`Sars Deaths`
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[18] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$`Sars Fatality Ratio (%)`
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[18] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$`Covid First Probable Case Date`
NULL

$`Covid Last Updated Case Date`
NULL

$`Covid Total Cases`
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[18] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$`Covid Deaths`
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[18] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

$`Covid Fatality Ratio (%)`
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[18] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

Scan II

Once the dataset has been scanned for missing and special values, the next step would be to scan the numeric data for outliers. To achieve this, Tukey’s method of outlier detection was used. This was performed by plotting boxplots for all numeric variables in the dataset, while printing the value of the outliers found in the boxplots. From the boxplots, it can be seen that there are a number of suggested outliers for each variable. While these anomalies may be problematic for statistical analysis - however, none will be performed for this project. Additionally, these anomalies represent important values that are needed in reaching the goal of this project.

# Boxplots to identify outliers
sarsCase_outliers <- cleanSet$`Sars Total Cases` %>% boxplot(main = "Box Plot of Sars Cases", ylab = "Total Cases")

covidCase_outliers <- cleanSet$`Covid Total Cases` %>% boxplot(main = "Box Plot of Covid Cases", ylab = "Total Cases")

sarsDeaths_outliers <- cleanSet$`Sars Deaths` %>% boxplot(main = "Box Plot of Sars Deaths", ylab = "Total Cases")

covidDeaths_outliers <- cleanSet$`Covid Deaths` %>% boxplot(main = "Box Plot of Covid Deaths", ylab = "Total Cases")

sarsFatality_outliers <- cleanSet$`Sars Fatality Ratio (%)` %>% boxplot(main = "Box plot of Sars Fatality Ratio", ylab = "Total Cases")

covidFatality_outliers <- cleanSet$`Covid Fatality Ratio (%)` %>% boxplot(main = "Box plot of Covid Fatality Ratio", ylab = "Total Cases")

# Outlier values
sarsCase_outliers$out
[1]  251 5327 1755  346  238   63
covidCase_outliers$out
[1] 48882141
sarsDeaths_outliers$out
[1]  43 349 299  37  33
covidDeaths_outliers$out
[1] 1067943 1404119 1161985 1083065 2671622
sarsFatality_outliers$out
[1]  40 100
covidFatality_outliers$out
[1] 14

Transform

From the section above, we can see that the Box plot of the Covid Fatality Ratio variable is the most suitable variable compared to the rest for an attempt at a data transformation. This will be performed by firstly plotting a histogram of the variable to get a visualization on what the distribution looks like. Then, we attempt to normalise the variable by using the z score standardisation. The resulting histogram does not reflect that of a normal distribution, instead it produced a cleaner U-shaped distribution.

# Histogram of the Covid Fatality Ratio variable
cleanSet$`Covid Fatality Ratio (%)` %>% hist(main = "Histogram of the Covid Fatality Ratio", xlab = "Fatality Ratio")

# Attempt to normalize the Covid Fatality Ratio variable using z score standardisation
zScoreStd_Test <- scale(cleanSet$`Covid Fatality Ratio (%)`, center = TRUE, scale = TRUE)
hist(zScoreStd_Test)

Final results

This final table represents the results of this project’s goal. From this table, while there are far more Covid cases and Covid deaths than SARS, the latter is still the more fatal pandemic. It seems that Covid-19 has a higher infection rate compared to SARS, however - the ratio of patients dying once infected is higher for SARS. This project could be further extended by adding the datasets of other pandemics in order to create an informational pandemic dataset.

head(cleanSet, n = 29)



LS0tDQp0aXRsZTogIk1BVEgyMzQ5IFNlbWVzdGVyIDEsIDIwMjAiDQphdXRob3I6ICJIb24gTWVuZyBMZWUgW3MzNzE2NDcxXSINCnN1YnRpdGxlOiBBc3NpZ25tZW50IDINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KLS0tDQoNCiMjIFJlcXVpcmVkIHBhY2thZ2VzIA0KDQpUaGUgcGFja2FnZXMgdXNlZCBpbiB0aGlzIHByb2plY3QuDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkobWFncml0dHIpDQpsaWJyYXJ5KG91dGxpZXJzKQ0KYGBgDQoNCg0KIyMgRXhlY3V0aXZlIFN1bW1hcnkgDQoNCkRhdGEgcHJlcHJvY2Vzc2luZyBpcyBhbiBpbXBlcmF0aXZlIHN0ZXAgaW4gdGhlIGRhdGEgcHJlcGFyYXRpb24gc3RhZ2Ugb2YgdGhlIERhdGEgU2NpZW5jZSBwcm9jZXNzLiBGb3IgbGVhcm5pbmcgcHVycG9zZXMsIHRoZSBkZWNpc2lvbiB3YXMgbWFkZSB0byBtZXJnZSBhbmQgcHJlcHJvY2VzcyB0d28gZGF0YXNldHMuIFRvIGtlZXAgd2l0aCB0aGUgdGltZXMsIGEgQ292aWQtMTkgZGF0YXNldCBhbmQgYSBTQVJTIGRhdGFzZXQgd2FzIHRha2VuIGZyb20gS2FnZ2xlIGluIG9yZGVyIHRvIGludmVzdGlnYXRlIHRoZSBpZGVhIG9mIHdoaWNoIHBhbmRlbWljIGlzIG1vcmUgZmF0YWwuIFRoZSB0d28gc2VsZWN0ZWQgZGF0YXNldHMgcmVxdWlyZWQgbXVjaCBwcmVwcm9jZXNzaW5nLiBXaGlsZSBib3RoIGRhdGFzZXRzIHJlcXVpcmVkIHNvbWUgY29tbW9uIHByZXByb2Nlc3Npbmcgc3VjaCBhcyB0aGUgcmVuYW1pbmcgb2YgY29sdW1ucyBhbmQgc2VsZWN0ZWQgcm93IHZhbHVlcywgb25lIGRhdGFzZXQgd2FzIHJlbGF0aXZlbHkgdW50aWR5LiBJbiB0aGUgQ292aWQgZGF0YXNldCwgb25lIG9mIHRoZSBjb2x1bW5zIGhhZCBib3RoIGRhdGUgYW5kIHRpbWUgY29tYmluZWQgaW5jb25zaXN0ZW50bHksIHdoaWxlIGFsc28gaGF2aW5nIGRpZmZlcmVudCBkYXRlIGZvcm1hdHMuIFRoaXMgY29sdW1uIG5lZWRlZCB0byBiZSBzcGxpdCB1cCBhbmQgZm9ybWF0dGVkIGFwcHJvcHJpYXRlbHkgaW4gcHJlcGFyYXRpb24gZm9yIG1lcmdpbmcgdGhlIHR3byBzZWxlY3RlZCBkYXRhc2V0cyBmb3IgdGhpcyBwcm9qZWN0LiBCZWZvcmUgbWVyZ2luZyB0aGUgdHdvIGRhdGFzZXRzLCB0aGUgQ292aWQgZGF0YXNldCBoYWQgdG8gYmUgZnVydGhlciBtYW5pcHVsYXRlZCBpbiBvcmRlciB0byBiZSBhYmxlIHRvIGJlIHByb3Blcmx5IG1lcmdlZCB3aXRoIHRoZSBTQVJTIGRhdGFzZXQuIE9uY2UgdGhlIGRhdGFzZXRzIGhhdmUgYmVlbiBtZXJnZWQsIG9uZSBmaW5hbCBkYXRhIGNsZWFuaW5nIG5lZWRlZCB0byBiZSBkb25lIHRvIHRoZSBuZXdseSBtZXJnZWQgZGF0YXNldC4gV2l0aCB0aGUgbWVyZ2VkIGRhdGFzZXQsIGEgbmV3IHZhcmlhYmxlIHdhcyBtdXRhdGVkIGluIG9yZGVyIHRvIGNvbXBhcmUgdGhlIGRlYWRsaW5lc3Mgb2YgdGhlIHR3byBwYW5kZW1pY3MuIFRoZSBkYXRhc2V0IGFsc28gbmVlZGVkIHRvIGJlIHNjYW5uZWQgZm9yIG1pc3NpbmcgdmFsdWVzLCBzcGVjaWFsIHZhbHVlcyBhbmQgb3V0bGllcnMuIEhvd2V2ZXIsIGF0IHRoYXQgcG9pbnQgdGhlIGRhdGFzZXQgaGFkIGJlZW4gYXBwcm9wcmlhdGVseSBjbGVhbmVkIHNvIG5vIG1pc3NpbmcgdmFsdWVzIG9yIHNwZWNpYWwgdmFsdWVzIHdlcmUgZm91bmQuIFRoZSBvdXRsaWVycyB3ZXJlIGZvdW5kIGJ1dCB3YXMganVzdGlmaWFibHkgbGVmdCBhbG9uZSBhcyB0aGV5IHdlcmUgaW1wb3J0YW50IHZhbHVlcy4gV2hpbGUgZGF0YSBub3JtYWxpc2F0aW9uIHdhcyBhdHRlbXB0ZWQgb24gdGhlIHZhcmlhYmxlcyBvZiB0aGUgZGF0YXNldCwgdGhlIHJlc3VsdHMgb2YgdGhlIHRyYW5zZm9ybWF0aW9uIGRpZCBub3QgeWllbGQgYW55IGludGVyZXN0aW5nIHJlc3VsdHMuIE92ZXJhbGwsIHRoZSBtYWluIGdvYWwgb2YgdGhlIHByb2plY3Qgd2FzIHN1Y2Nlc3NmdWxseSByZWFjaGVkIOKAkyB3aXRoIHJlc3VsdHMgc3VwcG9ydGluZyB0aGUgbm90aW9uIHRoYXQgU0FSUyBpcyB0aGUgbW9yZSBmYXRhbCBwYW5kZW1pYyBjb21wYXJlZCB0byBDb3ZpZC0xOS4NCg0KDQojIyBEYXRhIGRlc2NyaXB0aW9uICYgRGF0YSBpbXBvcnRpbmcgDQoNClRoZSBDb3ZpZCBkYXRhc2V0IHdhcyBjb2xsZWN0ZWQgZm9yIHJlc2VhcmNoIHB1cnBvc2VzIGJ5IFNSSyBmcm9tIHRoZSBKb2huIEhvcGtpbnMgVW5pdmVyc2l0eSBhbmQgcG9zdGVkIG9uIEthZ2dsZS4gVGhlIGRhdGFzZXQgY2FuIGJlIGZvdW5kIG9uIEthZ2dsZShodHRwczovL3d3dy5rYWdnbGUuY29tL3N1ZGFsYWlyYWprdW1hci9ub3ZlbC1jb3JvbmEtdmlydXMtMjAxOS1kYXRhc2V0P3NlbGVjdD1jb3ZpZF8xOV9kYXRhLmNzdikuIFRoaXMgcmVwb3NpdG9yeSBjb250YWlucyBtYW55IGRpZmZlcmVudCBjc3YgZmlsZXMuIEJ1dCBmb3IgdGhpcyBwcm9qZWN0LCBvbmx5IHRoZSBDb3ZpZC0xOSBkYXRhc2V0IHdpbGwgYmUgdGhlIHBvaW50IG9mIGZvY3VzIGZyb20gdGhpcyByZXBvc2l0b3J5LiBUaGUgYWZvcmVtZW50aW9uZWQgQ292aWQtMTkgZGF0YXNldCBpbiB0aGUgImNvdmlkXzE5X2RhdGEuY3N2IiBmaWxlIGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzOg0KDQoqIFNubzogU2VyaWFsIG51bWJlcg0KKiBPYnNlcnZhdGlvbkRhdGU6IERhdGUgb2YgdGhlIG9ic2VydmF0aW9uDQoqIFByb3ZpbmNlL1N0YXRlOiBQcm92aW5jZSBvciBzdGF0ZSBvZiB0aGUgb2JzZXJ2YXRpb24NCiogQ291bnRyeS9SZWdpb246IENvdW50cnkgb2Ygb2JzZXJ2YXRpb24NCiogTGFzdCBVcGRhdGU6IERhdGUgYW5kIHRpbWUgYXQgd2hpY2ggdGhlIHJvdyBpcyB1cGRhdGVkDQoqIENvbmZpcm1lZDogQ3VtdWxhdGl2ZSBudW1iZXIgb2YgY29uZmlybWVkIGNhc2VzIHVwIHRvIHRoYXQgZGF0ZQ0KKiBEZWF0aHM6IEN1bXVsYXRpdmUgbnVtYmVyIG9mIGRlYXRocyB1cCB0byB0aGF0IGRhdGUNCiogUmVjb3ZlcmVkOiBDdW11bGF0aXZlIG51bWJlciBvZiByZWNvdmVyZWQgY2FzZXMgdXAgdG8gdGhhdCBkYXRlDQoNClRoZSBTQVJTIGRhdGFzZXQgd2FzIGNvbGxlY3RlZCBmb3IgcmVzZWFyY2ggcHVycG9zZXMgYnkgRGV2YWt1bWFyIGtwIGZyb20gdGhlIFdvcmxkIEhlYWx0aCBPcmdhbml6YXRpb24gd2Vic2l0ZSBhbmQgcG9zdGVkIG9uIEthZ2dsZS4gVGhlIGRhdGFzZXQgY2FuIGJlIGZvdW5kIG9uIEthZ2dsZShodHRwczovL3d3dy5rYWdnbGUuY29tL2ltZGV2c2twL3NhcnMtb3V0YnJlYWstMjAwMy1jb21wbGV0ZS1kYXRhc2V0KS4gVGhpcyByZXBvc2l0b3J5IGNvbnRhaW5zIHR3byBkaWZmZXJlbnQgY3N2IGZpbGVzLiBCdXQgZm9yIHRoaXMgcHJvamVjdCwgb25seSB0aGUgY2xlYW5lZCBzdW1tYXJ5IGRhdGFzZXQgd2lsbCBiZSB0aGUgcG9pbnQgb2YgZm9jdXMgZnJvbSB0aGlzIHJlcG9zaXRvcnkuIFRoZSBhZm9yZW1lbnRpb25lZCBTYXJzIGRhdGFzZXQgaW4gdGhlICJzdW1tYXJ5X2RhdGFfY2xlYW4uY3N2IiBmaWxlIGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzOg0KDQoqIENvdW50cnkvUmVnaW9uOiBDb3VudHJ5IG9mIG9ic2VydmF0aW9uDQoqIEN1bXVsYXRpdmUgbWFsZSBjYXNlczogVG90YWwgbWFsZSBjYXNlcw0KKiBDdW11bGF0aXZlIGZlbWFsZSBjYXNlczogVG90YWwgZmVtYWxlIGNhc2VzDQoqIEN1bXVsYXRpdmUgdG90YWwgY2FzZXM6IFRvdGFsIGNhc2VzDQoqIE5vLiBvZiBkZWF0aHM6IE51bWJlciBvZiBkZWF0aHMNCiogQ2FzZSBmYXRhbGl0aWVzIHJhdGlvICglKTogQ2FzZSBmYXRhbGl0aWVzIGluIHBlcmNlbnRhZ2UNCiogRGF0ZSBvbnNldCBmaXJzdCBwcm9iYWJsZSBjYXNlOiBUaGUgZGF0ZSBvZiB0aGUgZmlyc3QgcHJvYmFibGUgU2FycyBjYXNlDQoqIERhdGUgb25zZXQgbGFzdCBwcm9iYWJsZSBjYXNlOiBUaGUgZGF0ZSBvZiB0aGUgbGFzdCBwcm9iYWJsZSBTYXJzIGNhc2UNCiogTWVkaWFuIGFnZTogVGhlIG1lZGlhbiBhZ2UNCiogQWdlIHJhbmdlOiBUaGUgYWdlIHJhbmdlIG9mIHRoZSBkYXRhDQoqIFBlcmNlbnRhZ2Ugb2YgSW1wb3J0ZWQgY2FzZXM6IFRoZSBwZXJjZW50YWdlIG9mIGNhc2VzIGR1ZSB0byBpbW1pZ3JhdGlvbg0KKiBOdW1iZXIgb2YgSENXIGFmZmVjdGVkOiBUaGUgbnVtYmVyIG9mIGhlYWx0aCBjYXJlIHdvcmtlcidzIGFmZmVjdGVkDQoqIFBlcmNlbnRhZ2Ugb2YgSENXIGFmZmVjdGVkOiBUaGUgcGVyY2VudGFnZSBvZiBoZWFsdGggY2FyZSB3b3JrZXIncyBhZmZlY3RlZA0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMNCg0KVGhlIGdvYWwgb2YgdGhpcyBwcm9qZWN0IGlzIHRvIGNsZWFuIHRoZSBDb3ZpZC0xOSBkYXRhc2V0IGFuZCBtZXJnZSBpdCB3aXRoIGEgY2xlYW5lZCBTQVJTIGRhdGFzZXQuIFRoZW4sIG11dGF0ZSBhIENvdmlkIGZhdGFsaXR5IHJhdGlvIHZhcmlhYmxlIHNvIGl0IGNhbiBiZSBjb21wYXJlZCB0byB0aGUgU2FycyBmYXRhbGl0eSByYXRpbyBpbiBvcmRlciB0byBmaW5kIG91dCB3aGljaCBwYW5kZW1pYyBpcyBkZWFkbGllciBiYXNlZCBvbiBjb3VudHJpZXMuDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIw0KDQpUbyBhY2hpZXZlIHRoaXMsIHRoZSBkYXRhc2V0cyB3aWxsIGZpcnN0bHkgYmUgaW1wb3J0ZWQgYW5kIHN1YnNldHRlZC4gVGhlIGRhdGFzZXRzIG5lZWQgdG8gYmUgc3Vic2V0dGVkIGFzIGJvdGggZGF0YXNldHMgY29udGFpbiBjb2x1bW5zIHRoYXQgYXJlIG5vdCByZWxldmFudCB0byB0aGUgZ29hbCBvZiB0aGlzIHByb2plY3QuIFRoZSBkYXRhc2V0cyB3ZXJlIHN1YnNldHRlZCBhcyBmb2xsb3dzOg0KDQoqIENvdmlkOiAiU05vIiBhbmQgIlByb3ZpbmNlL1N0YXRlIiBjb2x1bW5zIHdlcmUgcmVtb3ZlZCBhcyB0aGlzIHByb2plY3QgZm9jdXNlcyBtb3JlIG9uIENvdW50cmllcy4gVGhlIFNObyBjb2x1bW4gd2FzIHJlbW92ZWQgYXMgdGhlIHNlcmlhbCBudW1iZXIgb2YgdGhlIGNhc2VzIGlzIG5vdCBuZWNlc3NhcnkgZm9yIHRoZSBnb2FsIG9mIHRoaXMgcHJvamVjdC4NCg0KKiBTYXJzOiAiQ3VtdWxhdGl2ZSBtYWxlIGNhc2VzIiwgIkN1bXVsYXRpdmUgZmVtYWxlIGNhc2VzIiwgIkFnZSByYW5nZSIsICJQZXJjZW50YWdlIG9mIEltcG9ydGVkIGNhc2VzIiwgIk51bWJlciBvZiBIQ1cgYWZmZWN0ZWQiIGFuZCAiUGVyY2VudGFnZSBvZiBIQ1cgYWZmZWN0ZWQiIGNvbHVtbnMgd2VyZSByZW1vdmVkIGFzIHRoZXNlIGNvbHVtbnMgYXJlIG5vdCBuZWNlc3NhcnkgZm9yIHRoZSBnb2FsIG9mIHRoaXMgcHJvamVjdC4NCg0KDQpgYGB7cn0NCiMgSW1wb3J0IHRoZSBkYXRhDQpjb3ZpZFJhdyA8LSByZWFkX2NzdigiY292aWRfMTlfZGF0YS5jc3YiKQ0Kc2Fyc1JhdyA8LSByZWFkX2Nzdigic3VtbWFyeV9kYXRhX2NsZWFuLmNzdiIpDQojIFN1YnNldCBkYXRhDQpjb3ZpZCA8LSBjb3ZpZFJhd1ssIGMoMiw0OjcpXQ0Kc2FycyA8LSBzYXJzUmF3WywgYygxLDQ6OCldDQojIFByaW50IHRoZSBkYXRhDQpoZWFkKGNvdmlkKQ0KaGVhZChzYXJzKQ0KYGBgDQoNCg0KIyMgRGF0YSBjbGVhbmluZyBJIA0KDQpBZnRlciBpbXBvcnRpbmcgdGhlIGRhdGFzZXRzLCB0aGUgZGF0YSBuZWVkcyB0byBiZSBicmllZmx5IGNsZWFuZWQgYmVmb3JlIHRpZHlpbmcgYmVnaW5zLiBUaGUgZmlyc3QgdGhpbmcgdGhhdCB3YXMgZG9uZSB3YXMgdG8gcmVuYW1lIHRoZSBjb2x1bW5zIGZvciBib3RoIGRhdGFzZXRzIGZvciBjb25zaXN0ZW5jeSBwdXJwb3Nlcy4gVGhlbiwgc2VsZWN0ZWQgcm93cyBvZiBib3RoIGRhdGFzZXRzIGFyZSBhbHNvIHJlbmFtZWQgZm9yIGNvbnNpc3RlbmN5IGFuZCBjb3JyZWN0bmVzcyBwdXJwb3NlcyAoRWcuIGluIHRoZSBTYXJzIGRhdGFzZXQsIFZpZXRuYW0gd2FzIHdyaXR0ZW4gYXMgVmlldCBOYW0gd2hpY2ggaXMgaW5jb3JyZWN0KS4gVGhlbiwgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldHMgd2VyZSBpbnNwZWN0ZWQsIGFuZCB2YXJpb3VzIGRhdGEgdHlwZXMgd2VyZSBpZGVudGlmaWVkIGZvciBib3RoIGRhdGFzZXRzLiBXaGlsZSB0aGUgZGF0YSB0eXBlIGNvbnZlcnNpb25zIHdpbGwgb2NjdXIgbGF0ZXIgaW4gdGhlIHByb2Nlc3MgKERhdGEgY2xlYW5pbmcgSUkpLCB0aGUgZGF0ZXMgZm9yIGJvdGggZGF0YXNldHMgd2VyZSBmb3JtYXR0ZWQgZm9yIGNvbnNpc3RlbmN5Lg0KDQoNCmBgYHtyfQ0KIyBJbnNwZWN0aW5nIGFuZCByZW5hbWluZyBjb2x1bW5zIGZvciBjb25zaXN0ZW5jeSBwdXJwb3Nlcw0KY29sbmFtZXMoY292aWQpDQpjb3ZpZCAlPD4lIHJlbmFtZShgQ292aWRDb25maXJtZWRDYXNlc2AgPSAiQ29uZmlybWVkIiwgYENvdmlkRGVhdGhzYCA9ICJEZWF0aHMiLA0KICAgICAgICAgICAgICAgICBgQ292aWQgRmlyc3QgT2JzZXJ2YXRpb25zYCA9ICJPYnNlcnZhdGlvbkRhdGUiLCBgQ292aWQgTGFzdCBVcGRhdGVgID0gIkxhc3QgVXBkYXRlIikNCmNvbG5hbWVzKHNhcnMpDQpzYXJzICU8PiUgcmVuYW1lKGBTYXJzIFRvdGFsIENhc2VzYCA9ICJDdW11bGF0aXZlIHRvdGFsIGNhc2VzIiwNCiAgICAgICAgICAgICAgICAgYFNhcnMgRGVhdGhzYCA9ICJOby4gb2YgZGVhdGhzIiwNCiAgICAgICAgICAgICAgICAgYFNhcnMgRmF0YWxpdHkgUmF0aW8gKCUpYCA9ICJDYXNlIGZhdGFsaXRpZXMgcmF0aW8gKCUpIiwNCiAgICAgICAgICAgICAgICAgYFNhcnMgRmlyc3QgUHJvYmFibGUgQ2FzZSBEYXRlYCA9ICJEYXRlIG9uc2V0IGZpcnN0IHByb2JhYmxlIGNhc2UiLA0KICAgICAgICAgICAgICAgICBgU2FycyBMYXN0IFByb2JhYmxlIENhc2UgRGF0ZWAgPSAiRGF0ZSBvbnNldCBsYXN0IHByb2JhYmxlIGNhc2UiKQ0KIyBJbnNwZWN0aW5nIGFuZCByZW5hbWluZyByb3dzIGZvciBjb25zaXN0ZW5jeSBwdXJwb3Nlcw0KdW5pcXVlKGNvdmlkJGBDb3VudHJ5L1JlZ2lvbmApDQpjb3ZpZCRgQ291bnRyeS9SZWdpb25gW2NvdmlkJGBDb3VudHJ5L1JlZ2lvbmAgPT0gIlVLIl0gPC0gIlVuaXRlZCBLaW5nZG9tIg0KY292aWQkYENvdW50cnkvUmVnaW9uYFtjb3ZpZCRgQ291bnRyeS9SZWdpb25gID09ICJVUyJdIDwtICJVbml0ZWQgU3RhdGVzIg0KdW5pcXVlKHNhcnMkYENvdW50cnkvUmVnaW9uYCkNCnNhcnNbMywgMV0gPC0gIk1haW5sYW5kIENoaW5hIg0Kc2Fyc1s0LCAxXSA8LSAiSG9uZyBLb25nIg0Kc2Fyc1s1LCAxXSA8LSAiTWFjYXUiDQpzYXJzWzE4LCAxXSA8LSAiU291dGggS29yZWEiDQpzYXJzWzIwLCAxXSA8LSAiUnVzc2lhIg0Kc2Fyc1syOSwgMV0gPC0gIlZpZXRuYW0iIyBSZW5hbWluZyBtaXNwZWxsZWQgYFZpZXQgTmFtYCB0byBgVmlldG5hbWANCiMgSW5zcGVjdGluZyB0aGUgc3RydWN0dXJlIG9mIHRoZSBkYXRhc2V0cyBhbmQgbWFraW5nIHRoZSBkYXRlIGZvcm1hdCBjb25zaXN0ZW50IGZvciB0aGUgQ292aWQgZGF0YXNldA0Kc3RyKGNvdmlkKQ0KY292aWQkYENvdmlkIEZpcnN0IE9ic2VydmF0aW9uc2AgPC0gYXMuRGF0ZShjb3ZpZCRgQ292aWQgRmlyc3QgT2JzZXJ2YXRpb25zYCwgIiVtLyVkLyVZIikNCmNvdmlkJGBDb3ZpZCBGaXJzdCBPYnNlcnZhdGlvbnNgIDwtIGZvcm1hdChhcy5EYXRlKGNvdmlkJGBDb3ZpZCBGaXJzdCBPYnNlcnZhdGlvbnNgLCBmb3JtYXQgPSAiJVktJW0tJWQiKSwgIiVkLyVtLyVZIikNCmhlYWQoY292aWQpDQojIEluc3BlY3RpbmcgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldHMgYW5kIG1ha2luZyB0aGUgZGF0ZSBmb3JtYXQgY29uc2lzdGVudCBmb3IgdGhlIFNhcnMgZGF0YXNldA0Kc3RyKHNhcnMpDQpzYXJzJGBTYXJzIEZpcnN0IFByb2JhYmxlIENhc2UgRGF0ZWAgPC0gc3RyZnRpbWUoc2FycyRgU2FycyBGaXJzdCBQcm9iYWJsZSBDYXNlIERhdGVgLCAiJWQvJW0vJVkiKQ0Kc2FycyRgU2FycyBMYXN0IFByb2JhYmxlIENhc2UgRGF0ZWAgPC0gc3RyZnRpbWUoc2FycyRgU2FycyBMYXN0IFByb2JhYmxlIENhc2UgRGF0ZWAsICIlZC8lbS8lWSIpDQpoZWFkKHNhcnMpDQpgYGANCg0KDQojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgDQoNCk9uY2UgdGhlIGRhdGEgaGFzIGJlZW4gYnJpZWZseSBjbGVhbmVkLCBpdCBpcyB0aW1lIHRvIHRpZHkgdXAgdGhlIGRhdGFzZXQuIFRoZSBDb3ZpZCBkYXRhc2V0IGlzIHVudGlkeSBhcyBpdCBjb250YWlucyBtdWx0aXBsZSBjb3VsbW5zIHRoYXQgYXJlIG5vdCBuZWNlc3NhcnkgZm9yIHRoZSBwcm9qZWN0cyBnb2FsOyB3aGljaCBoYXMgYmVlbiByZW1vdmVkIGluIHRoZSBmaXJzdCBzZWN0aW9uLiBUaGUgQ292aWQgZGF0YXNldCBhbHNvIHBvc3Nlc3NlcyBhIGNvbHVtbiB0aGF0IGNvbnRhaW5zIGJvdGggZGF0ZSBhbmQgdGltZSAoYW5kIHNvbWUgb2YgdGhlbSBoYXZlIGxldHRlcnMgaW5zdGVhZCBvZiB3aGl0ZXNwYWNlcyBhcyBzZXBlcmF0b3JzKS4gVGhpcyBpcyBub3QgdGlkeSBhY2NvcmRpbmcgdG8gSGFkbGV5IFdpY2toYW0ncyB0aWR5IHByaW5jaXBsZXMgd2hpY2ggc3RhdGVzIHRoYXQgZWFjaCB2YWx1ZSBtdXN0IGhhdmUgaXRzIG93biBjZWxsLiBUbyByZW1lZHkgdGhpcyBwcm9ibGVtLCB0aGUgY29sdW1uIHdhcyBzcGxpdCBpbnRvIHR3byB1c2luZyBhIHRpZHlyIGZ1bmN0aW9uIHdpdGggYSByZWdleCBzZXBlcmF0b3IuIFRoZSBkYXRlIGNvbHVtbiB3YXMgdGhlbiByZXN0cnVjdHVyZWQgdXNpbmcgdGhlIHBhcnNlX2RhdGVfdGltZSgpIGZ1bmN0aW9uIGFzIHRoZSBjb2x1bW4gaGFkIG11bHRpcGxlIGRpZmZlcmVudCBkYXRlIGZvcm1hdHMuIFRoZSBDb3ZpZCBkYXRhc2V0IHdhcyBub3cgbXVjaCB0aWRpZXIgdGhhbiBiZWZvcmUgb25jZSB0aGUgdW5uZWNlc3NhcnkgY29sdW1ucyB3ZXJlIHJlbW92ZWQgYW5kIHRoZSB1bnRpZHkgY29sdW1uIHdhcyBzZXBhcmF0ZWQgYW5kIGZvcm1hdHRlZCBhcHByb3ByaWF0ZWx5Lg0KDQoNCmBgYHtyfQ0KIyBTcGxpdHRpbmcgdGhlIGNvdmlkTGFzdFVwZGF0ZSBjb2x1bW4NCnNwbGl0Q292aWQgPC0gc2VwYXJhdGUoY292aWQsIGBDb3ZpZCBMYXN0IFVwZGF0ZWAsIGMoIkNvdmlkIExhc3QgVXBkYXRlIiwgIkxhc3QgVXBkYXRlIFRpbWUiKSwgc2VwID0gIlR8WzpzcGFjZTpdIikNCiMgVGlkeWluZyB1cCB0aGUgbmV3IGNvbHVtbg0KdW5pcXVlKHNwbGl0Q292aWQkYENvdmlkIExhc3QgVXBkYXRlYCkNCnNwbGl0Q292aWQkYENvdmlkIExhc3QgVXBkYXRlYCA8LSBwYXJzZV9kYXRlX3RpbWUoeCA9IHNwbGl0Q292aWQkYENvdmlkIExhc3QgVXBkYXRlYCwgb3JkZXJzID0gYygibSBkIHkiLCAieSBtIGQiKSkNCmhlYWQoc3BsaXRDb3ZpZCkNCnN0cihzcGxpdENvdmlkKQ0KYGBgDQoNCg0KIyMJTWVyZ2luZyB0aGUgRGF0YQ0KDQpPbmNlIHRoZSBDb3ZpZCBkYXRhc2V0IGhhcyBiZWVuIG1hZGUgdGlkeSwgdGhlIFNhcnMgZGF0YXNldCBhbmQgQ292aWQgZGF0YXNldCBjYW4gYmUgbWVyZ2VkIHRvZ2V0aGVyLiBUaGUgZmlyc3Qgc3RlcCBpcyB0byByZW1vdmUgbW9yZSB1bm5lY2Vzc2FyeSBjb2x1bW5zLiBUaGUgZmlyc3Qgd2FzIHRvIGRyb3AgdGhlIHRpbWUgY29sdW1uIGluIHRoZSBzcGxpdENvdmlkIGRhdGFzZXQsIHRoYXQgd2FzIGF0dGFpbmVkIGZyb20gdGhlIHNlY3Rpb24gYWJvdmUgYXMgaXQgc2VydmVzIG5vIHB1cnBvc2UgZm9yIHRoZSBnb2FsIG9mIHRoaXMgcHJvamVjdC4gVGhlIG5leHQgc3RlcCB3YXMgdG8gc3Vic2V0IHRoZSBzcGxpdENvdmlkIHRvIGEgZGF0YXNldCB0aGF0IGNvbnRhaW5lZCB0aGUgY291bnRyaWVzIGFuZCB0aGUgY29uY2F0ZW5hdGlvbiBvZiB0aGUgdG90YWwgY292aWQgY2FzZXMgYW5kIHRvdGFsIGNvdmlkIGRlYXRocyBieSBjb3VudHJ5LiBUaGlzIGRhdGFzZXQgd2FzIGNhbGxlZCBjb3ZpZENhc2VzLiANCg0KQWZ0ZXIgdGhhdCBzdGVwLCBpdCB3YXMgdGltZSB0byBmb2N1cyBvbiB0aGUgZGF0ZXMuIFRoZSBzcGxpdENvdmlkIHdhcyBzdWJzZXQgdG8gdHdvIGRhdGFzZXRzLCBvbmUgZm9yIHRoZSBsYXRlc3QgdXBkYXRlZCBDb3ZpZCBkYXRlIGJ5IGNvdW50cnkgYW5kIG9uZSBieSB0aGUgZWFybGllc3QgQ292aWQgZGF0ZSBieSBjb3VudHJ5LiBPbmNlIHRoZXNlIHR3byBkYXRhc2V0cyB3ZXJlIGNvbXBsZXRlLCB0aGV5IHdlcmUgdGhlbiBtZXJnZWQgdG9nZXRoZXIgYWxvbmcgd2l0aCB0aGUgY292aWRDYXNlcyBzZXQgaW4gb3JkZXIgdG8gYXR0YWluIHRoZSBmaW5hbCBjb3ZpZCBkYXRhc2V0IGNhbGxlZCBjb3ZpZFNldC4gQSByaWdodF9qb2luIHdhcyB1c2VkIHRvIGNvbWJpbmUgY292aWRGaXJzdERhdGUgYW5kIGNvdmlkQ2FzZXMgYXMgd2Ugd2FudCB0byBwcmlvcml0aXplIHRoZSBjb3ZpZENhc2VzIGRhdGFzZXQuIEEgbGVmdF9qb2luIHdhcyB1c2VkIHRvIG1lcmdlIHRoZSBjb3ZpZExhc3REYXRlIGluIGFzIHdlIHdhbnQgdG8gcHJpb3JpdGl6ZSB0aGUgcHJpb3IgY29tYmluZWQgY292aWRGaXJzdERhdGUgYW5kIGNvdmlkQ2FzZXMgZGF0YXNldC4NCg0KT25jZSB0aGUgY292aWRTZXQgd2FzIGNvbXBsZXRlZCwgaXQgd2FzIHRoZW4gZmluYWxseSBtZXJnZWQgd2l0aCB0aGUgU2FycyBkYXRhc2V0IHVzaW5nIGEgbGVmdF9qb2luIGFzIHdlIG9ubHkgd2FudCB0aGUgY291bnRyaWVzIHRoYXQgYXJlIGluIHRoZSBTYXJzIGRhdGFzZXQgKGFzIHRoZSBjb3ZpZCBkYXRhc2V0IGhhcyBtb3JlIGNvdW50cmllcyB0aGFuIHRoZSBTYXJzIGRhdGFzZXQpDQoNCg0KYGBge3J9DQojIERyb3BwaW5nIHRoZSB0aW1lIGNvbHVtbg0Kc3BsaXRDb3ZpZCA8LSBzZWxlY3Qoc3BsaXRDb3ZpZCwgLWMoYExhc3QgVXBkYXRlIFRpbWVgKSkNCiMgU3VtbWFyaXNlIGFsbCB0aGUgdG90YWwgY292aWQgY2FzZXMgYW5kIHRvdGFsIGNvdmlkIGRlYXRocyBieSBjb3VudHJ5DQpjb3ZpZENhc2VzIDwtIHNwbGl0Q292aWQgJT4lIA0KICBncm91cF9ieShgQ291bnRyeS9SZWdpb25gKSAlPiUgDQogIHN1bW1hcmlzZShzdW0oQ292aWRDb25maXJtZWRDYXNlcyksIHN1bShDb3ZpZERlYXRocykpDQojIEdldCB0aGUgbGF0ZXN0IHVwZGF0ZWQgQ292aWQgZGF0ZSBieSBjb3VudHJ5DQpjb3ZpZExhc3REYXRlIDwtIHNwbGl0Q292aWQgJT4lIA0KICBncm91cF9ieShgQ291bnRyeS9SZWdpb25gKSAlPiUgDQogIGZpbHRlcihgQ292aWQgTGFzdCBVcGRhdGVgID09IG1heChgQ292aWQgTGFzdCBVcGRhdGVgKSkgJT4lIA0KICBzZWxlY3QoLWMoYENvdmlkIEZpcnN0IE9ic2VydmF0aW9uc2AsIGBDb3ZpZENvbmZpcm1lZENhc2VzYCwgYENvdmlkRGVhdGhzYCkpDQojIEdldCB0aGUgZWFybGllc3QgQ292aWQgZGF0ZSBieSBjb3VudHJ5DQpjb3ZpZEZpcnN0RGF0ZSA8LSBzcGxpdENvdmlkICU+JSANCiAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCkgJT4lIA0KICBmaWx0ZXIoYENvdmlkIEZpcnN0IE9ic2VydmF0aW9uc2AgPT0gbWluKGBDb3ZpZCBGaXJzdCBPYnNlcnZhdGlvbnNgKSkgJT4lIA0KICBzZWxlY3QoLWMoYENvdmlkIExhc3QgVXBkYXRlYCwgYENvdmlkQ29uZmlybWVkQ2FzZXNgLCBgQ292aWREZWF0aHNgKSkNCiMgQ29tYmluZSBib3RoIGRhdGVzIHdpdGggdGhlIGNvdmlkQ2FzZXMgd2hpbGUgcmVtb3ZpbmcgYWxsIGR1cGxpY2F0ZSByb3dzDQpjb3ZpZFNldCA8LSBjb3ZpZEZpcnN0RGF0ZSAlPiUgDQogIGdyb3VwX2J5KGBDb3VudHJ5L1JlZ2lvbmAsIGBDb3ZpZCBGaXJzdCBPYnNlcnZhdGlvbnNgKSAlPiUgDQogIHJpZ2h0X2pvaW4oY292aWRDYXNlcywgYnk9IkNvdW50cnkvUmVnaW9uIikgJT4lIA0KICBsZWZ0X2pvaW4oY292aWRMYXN0RGF0ZSwgYnk9IkNvdW50cnkvUmVnaW9uIikgJT4lIA0KICBkaXN0aW5jdCgpDQojIENvbWJpbmUgdGhlIGNvdmlkU2V0IHdpdGggdGhlIFNhcnMgZGF0YXNldA0KY29tYmluZWRTZXQgPC0gbGVmdF9qb2luKHNhcnMsIGNvdmlkU2V0KQ0Kc3RyKGNvbWJpbmVkU2V0KQ0KaGVhZChjb21iaW5lZFNldCkNCmBgYA0KDQoNCiMjCURhdGEgY2xlYW5pbmcgSUkNCg0KT25jZSB0aGUgZGF0YXNldHMgaGF2ZSBiZWVuIHN1Y2Nlc3NmdWxseSBtZXJnZWQsIGl0IGlzIHRpbWUgdG8gY2xlYW4gdXAgdGhlIG5ldyBkYXRhc2V0LiBUaGlzIHN0ZXAgZW50YWlscyB0aGUgcmVuYW1pbmcgYW5kIHJlb3JkZXJpbmcgb2YgY29sdW1ucyBmb3IgY29uc2lzdGVuY3kgaW4gdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gQXBwcm9wcmlhdGUgZGF0YSB0eXBlIGNvbnZlcnNpb25zIHdpbGwgYWxzbyBiZSBwZXJmb3JtZWQsIGNvbnZlcnRpbmcgdGhlICJDb3VudHJ5L1JlZ2lvbiIgY29sdW1uIHRvIGEgZmFjdG9yIGRhdGEgdHlwZSwgYW5kIGFsc28gY29udmVydGluZyB0aGUgZGF0ZSBjb2x1bW5zIGFwcHJvcHJpYXRlbHkgdXNpbmcgbHVicmlkYXRlIGZ1bmN0aW9ucy4NCg0KDQpgYGB7cn0NCiMgRmFjdG9yIGRhdGEgdHlwZSBjb252ZXJzaW9uDQpjb21iaW5lZFNldCRgQ291bnRyeS9SZWdpb25gIDwtIGZhY3Rvcihjb21iaW5lZFNldCRgQ291bnRyeS9SZWdpb25gLCBsZXZlbHMgPSBjKCJBdXN0cmFsaWEiLCAiQ2FuYWRhIiwgIkZyYW5jZSIsICJHZXJtYW55IiwgIkhvbmcgS29uZyIsICJJbmRpYSIsICJJbmRvbmVzaWEiLCAiSXRhbHkiLCAiS3V3YWl0IiwgIk1hY2F1IiwgIk1haW5sYW5kIENoaW5hIiwgIk1hbGF5c2lhIiwgIk1vbmdvbGlhIiwgIk5ldyBaZWFsYW5kIiwgIlBoaWxpcHBpbmVzIiwgIlJlcHVibGljIG9mIElyZWxhbmQiLCAiUm9tYW5pYSIsICJSdXNzaWEiLCAiU2luZ2Fwb3JlIiwgIlNvdXRoIEFmcmljYSIsICJTb3V0aCBLb3JlYSIsICJTcGFpbiIsICJTd2VkZW4iLCAiU3dpdHplcmxhbmQiLCAiVGFpd2FuIiwgIlRoYWlsYW5kIiwgIlVuaXRlZCBLaW5nZG9tIiwgIlVuaXRlZCBTdGF0ZXMiLCAiVmlldG5hbSIpLCBsYWJlbHMgPSBjKCJBdXN0cmFsaWEiLCAiQ2FuYWRhIiwgIkZyYW5jZSIsICJHZXJtYW55IiwgIkhvbmcgS29uZyIsICJJbmRpYSIsICJJbmRvbmVzaWEiLCAiSXRhbHkiLCAiS3V3YWl0IiwgIk1hY2F1IiwgIk1haW5sYW5kIENoaW5hIiwgIk1hbGF5c2lhIiwgIk1vbmdvbGlhIiwgIk5ldyBaZWFsYW5kIiwgIlBoaWxpcHBpbmVzIiwgIlJlcHVibGljIG9mIElyZWxhbmQiLCAiUm9tYW5pYSIsICJSdXNzaWEiLCAiU2luZ2Fwb3JlIiwgIlNvdXRoIEFmcmljYSIsICJTb3V0aCBLb3JlYSIsICJTcGFpbiIsICJTd2VkZW4iLCAiU3dpdHplcmxhbmQiLCAiVGFpd2FuIiwgIlRoYWlsYW5kIiwgIlVuaXRlZCBLaW5nZG9tIiwgIlVuaXRlZCBTdGF0ZXMiLCAiVmlldG5hbSIpLCBvcmRlcmVkID0gRkFMU0UpDQojIE5hbWUgYW5kIHN0cnVjdHVyZSBjbGVhbmluZw0KbmFtZXMoY29tYmluZWRTZXQpWzddIDwtICJDb3ZpZCBGaXJzdCBQcm9iYWJsZSBDYXNlIERhdGUiDQpuYW1lcyhjb21iaW5lZFNldClbOF0gPC0gIkNvdmlkIFRvdGFsIENhc2VzIg0KbmFtZXMoY29tYmluZWRTZXQpWzldIDwtICJDb3ZpZCBEZWF0aHMiDQpuYW1lcyhjb21iaW5lZFNldClbMTBdIDwtICJDb3ZpZCBMYXN0IFVwZGF0ZWQgQ2FzZSBEYXRlIg0KY29tYmluZWRTZXQkYENvdmlkIExhc3QgVXBkYXRlZCBDYXNlIERhdGVgIDwtIHN0cmZ0aW1lKGNvbWJpbmVkU2V0JGBDb3ZpZCBMYXN0IFVwZGF0ZWQgQ2FzZSBEYXRlYCwgIiVkLyVtLyVZIikNCmNvbF9vcmRlciA8LSBjKCJDb3VudHJ5L1JlZ2lvbiIsICJTYXJzIEZpcnN0IFByb2JhYmxlIENhc2UgRGF0ZSIsICJTYXJzIExhc3QgUHJvYmFibGUgQ2FzZSBEYXRlIiwgIlNhcnMgVG90YWwgQ2FzZXMiLCAiU2FycyBEZWF0aHMiLCAiU2FycyBGYXRhbGl0eSBSYXRpbyAoJSkiLCAiQ292aWQgRmlyc3QgUHJvYmFibGUgQ2FzZSBEYXRlIiwgIkNvdmlkIExhc3QgVXBkYXRlZCBDYXNlIERhdGUiLCAiQ292aWQgVG90YWwgQ2FzZXMiLCAiQ292aWQgRGVhdGhzIikNCmNsZWFuU2V0IDwtIGNvbWJpbmVkU2V0WywgY29sX29yZGVyXQ0KIyBEYXRlIGRhdGEgdHlwZSBjb252ZXJzaW9uDQpjbGVhblNldCRgU2FycyBGaXJzdCBQcm9iYWJsZSBDYXNlIERhdGVgIDwtIGRteShjbGVhblNldCRgU2FycyBGaXJzdCBQcm9iYWJsZSBDYXNlIERhdGVgKQ0KY2xlYW5TZXQkYFNhcnMgTGFzdCBQcm9iYWJsZSBDYXNlIERhdGVgIDwtIGRteShjbGVhblNldCRgU2FycyBMYXN0IFByb2JhYmxlIENhc2UgRGF0ZWApDQpjbGVhblNldCRgQ292aWQgRmlyc3QgUHJvYmFibGUgQ2FzZSBEYXRlYCA8LSBkbXkoY2xlYW5TZXQkYENvdmlkIEZpcnN0IFByb2JhYmxlIENhc2UgRGF0ZWApDQpjbGVhblNldCRgQ292aWQgTGFzdCBVcGRhdGVkIENhc2UgRGF0ZWAgPC0gZG15KGNsZWFuU2V0JGBDb3ZpZCBMYXN0IFVwZGF0ZWQgQ2FzZSBEYXRlYCkNCnN0cihjbGVhblNldCkNCmhlYWQoY2xlYW5TZXQpDQpgYGANCg0KDQojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJIA0KDQpPbmNlIHdlIGhhdmUgYSBjbGVhbmVkIHNldCB0aGF0IGhhcyBib3RoIFNhcnMgYW5kIENvdmlkIGNhc2VzOyByZWZlcnJpbmcgdG8gdGhlIG9yaWdpbmFsIGdvYWxzIG9mIHRoZSBwcm9qZWN0LCBvbmUgb2Ygd2hpY2ggd2FzIHRvIGZpbmQgdGhlIGRlYWRsaWVyIHBhbmRlbWljLiBUaGlzIHJlcXVpcmVzIGEgbXV0YXRpb24gb2YgYSBDb3ZpZCBGYXRhbGl0eSBSYXRpbyB2YXJpYWJsZSBzbyBpdCBjYW4gYmUgY29tcGFyZWQgdG8gdGhlIFNhcnMgRmF0YWxpdHkgUmF0aW8gKCUpIHZhcmlhYmxlICh3aGljaCBpcyBhbHJlYWR5IGluIHRoZSBkYXRhc2V0KS4gVG8gYWNoaWV2ZSB0aGlzLCBhIG11dGF0aW9uIHdoZXJlIHRoZSBDb3ZpZCBEZWF0aHMgYXJlIGRpdmlkZWQgYnkgQ292aWQgVG90YWwgQ2FzZXMgYW5kIG11bHRpcGxpZWQgYnkgMTAwIGluIG9yZGVyIHRvIGF0dGFpbiB0aGUgcmF0aW8gdmFsdWUgaW4gcGVyY2VudGFnZSAtIGV4YWN0bHkgbGlrZSB0aGUgU2FycyBGYXRhbGl0eSBSYXRpbyAoJSkgdmFyaWFibGUuDQoNCg0KYGBge3J9DQojIE11dGF0aW5nIHRoZSBDb3ZpZCBGYXRhbGl0eSBSYXRpbyAoJSkgdmFyaWFibGUgYnkgdXNpbmcgdGhlIGZvbGxvd2luZyBmb3JtdWxhIGFuZCByb3VuZGluZyB0aGUgYW5zd2VyDQpjbGVhblNldCAlPD4lIG11dGF0ZShgQ292aWQgRmF0YWxpdHkgUmF0aW8gKCUpYCA9IHJvdW5kKChgQ292aWQgRGVhdGhzYC9gQ292aWQgVG90YWwgQ2FzZXNgKjEwMCkpKQ0KaGVhZChjbGVhblNldCkNCmBgYA0KDQoNCiMjCVNjYW4gSQ0KDQpPbmNlIHRoZSBkYXRhc2V0IGlzIGNsZWFuIGFuZCB0aWR5LCB3ZSBjYW4gdGhlbiBtb3ZlIG9uIHRvIHNjYW5uaW5nIGZvciBtaXNzaW5nIG9yIHNwZWNpYWwgdmFsdWVzLiBUbyBzY2FuIGZvciBtaXNzaW5nIHZhbHVlcywgdXNpbmcgdGhlIHByaW50KGNvbFN1bXMoaXMubmEoKSkpIGZ1bmN0aW9uIGlzIHZlcnkgaGVscGZ1bC4gRm9yIHNjYW5uaW5nIHNwZWNpYWwgdmFsdWVzLCBhIGZ1bmN0aW9uIHdhcyBtYWRlIHRoYXQgY2hlY2tzIGV2ZXJ5IG51bWVyaWNhbCBjb2x1bW4gaWYgdGhleSBwb3NzZXNzIGluZmluaXRlIG9yIE5hTiB2YWx1ZXMgY2FsbGVkIHZhbHVlQ2hlY2tlci4gVGhpcyB3YXMgdGhlbiBhcHBsaWVkIHRvIHRoZSBjbGVhbmVkIGRhdGFzZXQuIFRoZSByZXN1bHRzIHNob3dlZCB0aGF0IHRoZSBkYXRhc2V0IGNvbnRhaW5zIG5vIG1pc3NpbmcgdmFsdWVzIG9yIHNwZWNpYWwgdmFsdWVzLg0KDQoNCmBgYHtyfQ0KIyBTY2FubmluZyBmb3IgbWlzc2luZyB2YWx1ZXMNCnByaW50KGNvbFN1bXMoaXMubmEoY2xlYW5TZXQpKSkNCiMgU2Nhbm5pbmcgZm9yIHNwZWNpYWwgdmFsdWVzDQpzcGVjaWFsVmFsdWVDaGVja2VyIDwtIGZ1bmN0aW9uKHgpIHsNCiAgaWYoaXMubnVtZXJpYyh4KSkgKGlzLmluZmluaXRlKHgpIHwgaXMubmFuKHgpKQ0KfQ0Kc2FwcGx5KGNsZWFuU2V0LCBzcGVjaWFsVmFsdWVDaGVja2VyKQ0KYGBgDQoNCg0KIyMJU2NhbiBJSQ0KDQpPbmNlIHRoZSBkYXRhc2V0IGhhcyBiZWVuIHNjYW5uZWQgZm9yIG1pc3NpbmcgYW5kIHNwZWNpYWwgdmFsdWVzLCB0aGUgbmV4dCBzdGVwIHdvdWxkIGJlIHRvIHNjYW4gdGhlIG51bWVyaWMgZGF0YSBmb3Igb3V0bGllcnMuIFRvIGFjaGlldmUgdGhpcywgVHVrZXkncyBtZXRob2Qgb2Ygb3V0bGllciBkZXRlY3Rpb24gd2FzIHVzZWQuIFRoaXMgd2FzIHBlcmZvcm1lZCBieSBwbG90dGluZyBib3hwbG90cyBmb3IgYWxsIG51bWVyaWMgdmFyaWFibGVzIGluIHRoZSBkYXRhc2V0LCB3aGlsZSBwcmludGluZyB0aGUgdmFsdWUgb2YgdGhlIG91dGxpZXJzIGZvdW5kIGluIHRoZSBib3hwbG90cy4gRnJvbSB0aGUgYm94cGxvdHMsIGl0IGNhbiBiZSBzZWVuIHRoYXQgdGhlcmUgYXJlIGEgbnVtYmVyIG9mIHN1Z2dlc3RlZCBvdXRsaWVycyBmb3IgZWFjaCB2YXJpYWJsZS4gV2hpbGUgdGhlc2UgYW5vbWFsaWVzIG1heSBiZSBwcm9ibGVtYXRpYyBmb3Igc3RhdGlzdGljYWwgYW5hbHlzaXMgLSBob3dldmVyLCBub25lIHdpbGwgYmUgcGVyZm9ybWVkIGZvciB0aGlzIHByb2plY3QuIEFkZGl0aW9uYWxseSwgdGhlc2UgYW5vbWFsaWVzIHJlcHJlc2VudCBpbXBvcnRhbnQgdmFsdWVzIHRoYXQgYXJlIG5lZWRlZCBpbiByZWFjaGluZyB0aGUgZ29hbCBvZiB0aGlzIHByb2plY3QuDQoNCg0KYGBge3J9DQojIEJveHBsb3RzIHRvIGlkZW50aWZ5IG91dGxpZXJzDQpzYXJzQ2FzZV9vdXRsaWVycyA8LSBjbGVhblNldCRgU2FycyBUb3RhbCBDYXNlc2AgJT4lIGJveHBsb3QobWFpbiA9ICJCb3ggUGxvdCBvZiBTYXJzIENhc2VzIiwgeWxhYiA9ICJUb3RhbCBDYXNlcyIpDQpjb3ZpZENhc2Vfb3V0bGllcnMgPC0gY2xlYW5TZXQkYENvdmlkIFRvdGFsIENhc2VzYCAlPiUgYm94cGxvdChtYWluID0gIkJveCBQbG90IG9mIENvdmlkIENhc2VzIiwgeWxhYiA9ICJUb3RhbCBDYXNlcyIpDQpzYXJzRGVhdGhzX291dGxpZXJzIDwtIGNsZWFuU2V0JGBTYXJzIERlYXRoc2AgJT4lIGJveHBsb3QobWFpbiA9ICJCb3ggUGxvdCBvZiBTYXJzIERlYXRocyIsIHlsYWIgPSAiVG90YWwgQ2FzZXMiKQ0KY292aWREZWF0aHNfb3V0bGllcnMgPC0gY2xlYW5TZXQkYENvdmlkIERlYXRoc2AgJT4lIGJveHBsb3QobWFpbiA9ICJCb3ggUGxvdCBvZiBDb3ZpZCBEZWF0aHMiLCB5bGFiID0gIlRvdGFsIENhc2VzIikNCnNhcnNGYXRhbGl0eV9vdXRsaWVycyA8LSBjbGVhblNldCRgU2FycyBGYXRhbGl0eSBSYXRpbyAoJSlgICU+JSBib3hwbG90KG1haW4gPSAiQm94IHBsb3Qgb2YgU2FycyBGYXRhbGl0eSBSYXRpbyIsIHlsYWIgPSAiVG90YWwgQ2FzZXMiKQ0KY292aWRGYXRhbGl0eV9vdXRsaWVycyA8LSBjbGVhblNldCRgQ292aWQgRmF0YWxpdHkgUmF0aW8gKCUpYCAlPiUgYm94cGxvdChtYWluID0gIkJveCBwbG90IG9mIENvdmlkIEZhdGFsaXR5IFJhdGlvIiwgeWxhYiA9ICJUb3RhbCBDYXNlcyIpDQojIE91dGxpZXIgdmFsdWVzDQpzYXJzQ2FzZV9vdXRsaWVycyRvdXQNCmNvdmlkQ2FzZV9vdXRsaWVycyRvdXQNCnNhcnNEZWF0aHNfb3V0bGllcnMkb3V0DQpjb3ZpZERlYXRoc19vdXRsaWVycyRvdXQNCnNhcnNGYXRhbGl0eV9vdXRsaWVycyRvdXQNCmNvdmlkRmF0YWxpdHlfb3V0bGllcnMkb3V0DQpgYGANCg0KDQojIwlUcmFuc2Zvcm0gDQoNCkZyb20gdGhlIHNlY3Rpb24gYWJvdmUsIHdlIGNhbiBzZWUgdGhhdCB0aGUgQm94IHBsb3Qgb2YgdGhlIENvdmlkIEZhdGFsaXR5IFJhdGlvIHZhcmlhYmxlIGlzIHRoZSBtb3N0IHN1aXRhYmxlIHZhcmlhYmxlIGNvbXBhcmVkIHRvIHRoZSByZXN0IGZvciBhbiBhdHRlbXB0IGF0IGEgZGF0YSB0cmFuc2Zvcm1hdGlvbi4gVGhpcyB3aWxsIGJlIHBlcmZvcm1lZCBieSBmaXJzdGx5IHBsb3R0aW5nIGEgaGlzdG9ncmFtIG9mIHRoZSB2YXJpYWJsZSB0byBnZXQgYSB2aXN1YWxpemF0aW9uIG9uIHdoYXQgdGhlIGRpc3RyaWJ1dGlvbiBsb29rcyBsaWtlLiBUaGVuLCB3ZSBhdHRlbXB0IHRvIG5vcm1hbGlzZSB0aGUgdmFyaWFibGUgYnkgdXNpbmcgdGhlIHogc2NvcmUgc3RhbmRhcmRpc2F0aW9uLiBUaGUgcmVzdWx0aW5nIGhpc3RvZ3JhbSBkb2VzIG5vdCByZWZsZWN0IHRoYXQgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCBpbnN0ZWFkIGl0IHByb2R1Y2VkIGEgY2xlYW5lciBVLXNoYXBlZCBkaXN0cmlidXRpb24uDQoNCg0KYGBge3J9DQojIEhpc3RvZ3JhbSBvZiB0aGUgQ292aWQgRmF0YWxpdHkgUmF0aW8gdmFyaWFibGUNCmNsZWFuU2V0JGBDb3ZpZCBGYXRhbGl0eSBSYXRpbyAoJSlgICU+JSBoaXN0KG1haW4gPSAiSGlzdG9ncmFtIG9mIHRoZSBDb3ZpZCBGYXRhbGl0eSBSYXRpbyIsIHhsYWIgPSAiRmF0YWxpdHkgUmF0aW8iKQ0KIyBBdHRlbXB0IHRvIG5vcm1hbGl6ZSB0aGUgQ292aWQgRmF0YWxpdHkgUmF0aW8gdmFyaWFibGUgdXNpbmcgeiBzY29yZSBzdGFuZGFyZGlzYXRpb24NCnpTY29yZVN0ZF9UZXN0IDwtIHNjYWxlKGNsZWFuU2V0JGBDb3ZpZCBGYXRhbGl0eSBSYXRpbyAoJSlgLCBjZW50ZXIgPSBUUlVFLCBzY2FsZSA9IFRSVUUpDQpoaXN0KHpTY29yZVN0ZF9UZXN0KQ0KYGBgDQoNCg0KIyMJRmluYWwgcmVzdWx0cw0KDQpUaGlzIGZpbmFsIHRhYmxlIHJlcHJlc2VudHMgdGhlIHJlc3VsdHMgb2YgdGhpcyBwcm9qZWN0J3MgZ29hbC4gRnJvbSB0aGlzIHRhYmxlLCB3aGlsZSB0aGVyZSBhcmUgZmFyIG1vcmUgQ292aWQgY2FzZXMgYW5kIENvdmlkIGRlYXRocyB0aGFuIFNBUlMsIHRoZSBsYXR0ZXIgaXMgc3RpbGwgdGhlIG1vcmUgZmF0YWwgcGFuZGVtaWMuIEl0IHNlZW1zIHRoYXQgQ292aWQtMTkgaGFzIGEgaGlnaGVyIGluZmVjdGlvbiByYXRlIGNvbXBhcmVkIHRvIFNBUlMsIGhvd2V2ZXIgLSB0aGUgcmF0aW8gb2YgcGF0aWVudHMgZHlpbmcgb25jZSBpbmZlY3RlZCBpcyBoaWdoZXIgZm9yIFNBUlMuIFRoaXMgcHJvamVjdCBjb3VsZCBiZSBmdXJ0aGVyIGV4dGVuZGVkIGJ5IGFkZGluZyB0aGUgZGF0YXNldHMgb2Ygb3RoZXIgcGFuZGVtaWNzIGluIG9yZGVyIHRvIGNyZWF0ZSBhbiBpbmZvcm1hdGlvbmFsIHBhbmRlbWljIGRhdGFzZXQuDQoNCg0KYGBge3J9DQpoZWFkKGNsZWFuU2V0LCBuID0gMjkpDQpgYGANCg0KPGJyPg0KPGJyPg0K