Required Packages


library(readr)
library(outliers)
library(lubridate)
library(tidyr)
library(dplyr)

Executive Summary

Data Wrangling refers to the preprocessing of Data and converting it into an analyzable state. The two datasets used for the assignment are The Covid-19 India Dataset and the Statewise Testing Details dataset.
Both the datasets are available on: https://www.kaggle.com/sudalairajkumar/covid19-in-india
The datasets are merged together for the assignment purpose. Various tasks like data understanding, tidying of data, manipulation, filtering, scanning, transforming have been performed on the dataset. Skewness is checked for the Confirmed cases variable and the neccessary transformation is done to reduce the skewness.

Data

The Dataset used are the covid_19_india[1] which contains the details of the increase in coronavirus cases per day in different states of India and the StatewiseTestingdetails[1] which contains the date wise details of the Total tests carried out each day in different states of India.
The variables in covid_19_india dataset are Date and time of recording, the State/Union Territory for which the information is recorded, ConfirmedIndianNationals refers to the cases reported from Indian citizens, ConfirmedForeignNationals are the cases reported from people who are not Indian Citizens, Cured refers to cases cured till that date, Deaths are the number of deaths due to Covid-19 till that date, and Confirmed refers to the total confirmed cases in India till that date.
The variables in StatewiseTestingdetails dataset are Date which refers to the date of the information recorded, States refers to the State of India for which the information is recorded, TotalSamples refers to the Tests being done till that date, and Positive Refers to the total number of people infected by coronavirus till the date in that State.

covid_19_india <- read_csv("Downloads/covid_19_india.csv")

── Column specification ────────────────────────────────────────────────────────────────────
cols(
  Date = col_character(),
  Time = col_time(format = ""),
  `State/UnionTerritory` = col_character(),
  ConfirmedIndianNational = col_character(),
  ConfirmedForeignNational = col_character(),
  Cured = col_double(),
  Deaths = col_double(),
  Confirmed = col_double()
)
StatewiseTestingDetails <- read_csv("Downloads/StatewiseTestingDetails.csv")

── Column specification ────────────────────────────────────────────────────────────────────
cols(
  Date = col_character(),
  State = col_character(),
  TotalSamples = col_double(),
  Positive = col_double()
)
covid_19_india<- covid_19_india%>%unite(DateTime, Date, Time, sep=" ")
head(covid_19_india)
head(StatewiseTestingDetails)

The two datasets have been merged together as per the assignment specification. The type of the variable date for StatewiseTestingdetails has been converted to character for proper merging of the dataset as the covid_19_india has date stored as a character variable.

StatewiseTestingDetails$Date<-as.character(StatewiseTestingDetails$Date, format="%d/%m/%y")
covid_19_india<-covid_19_india %>%separate(DateTime, into = c("Date", "Time"), sep = " ")
df_join <-full_join(covid_19_india,StatewiseTestingDetails, by = c("Date" = "Date", "State/UnionTerritory"="State"))

head(df_join)

Tidy & Data Manipulate I

It is observed in the dataset covid_19_india, the date and time have been merged into a single colum. Its breaks the Wickham and Grolemund principles as each variable must have its own column. Date and Time can be separated as follows:

covid_19_india<-covid_19_india %>%separate(DateTime, into = c("Date", "Time"), sep = " ")
head(df_join)

The above code has been used before merging the 2 datasets above in the Data section.

Understand

The structure and dimensions of the dataset can be checked using the str() and dim() functions respectively. We can observe that the dataset contains character, time, numeric variables. There are a total of 7266 observations and a total of 10 variables.

dim(df_join)
[1] 7266   10
str(df_join)
tibble [7,266 × 10] (S3: tbl_df/tbl/data.frame)
 $ Date                    : chr [1:7266] "30/1/20" "31/1/20" "1/2/20" "2/2/20" ...
 $ Time                    : chr [1:7266] "18:00:00" "18:00:00" "18:00:00" "18:00:00" ...
 $ State/UnionTerritory    : chr [1:7266] "Kerala" "Kerala" "Kerala" "Kerala" ...
 $ ConfirmedIndianNational : chr [1:7266] "1" "1" "2" "3" ...
 $ ConfirmedForeignNational: chr [1:7266] "0" "0" "0" "0" ...
 $ Cured                   : num [1:7266] 0 0 0 0 0 0 0 0 0 0 ...
 $ Deaths                  : num [1:7266] 0 0 0 0 0 0 0 0 0 0 ...
 $ Confirmed               : num [1:7266] 1 1 2 3 3 3 3 3 3 3 ...
 $ TotalSamples            : num [1:7266] NA NA NA NA NA NA NA NA NA NA ...
 $ Positive                : num [1:7266] NA NA NA NA NA NA NA NA NA NA ...

Earlier on the type of the variable date for StatewiseTestingdetails has been converted to character for proper merging of the dataset as the covid_19_india has date stored as a character variable. In the merged dataset, we can observe that the date is stored as a character variable and should be converted to type Date.

df_join$Date<-as.Date(df_join$Date,format = "%d/%m/%y")
str(df_join)
tibble [7,266 × 10] (S3: tbl_df/tbl/data.frame)
 $ Date                    : Date[1:7266], format: "2020-01-30" "2020-01-31" "2020-02-01" ...
 $ Time                    : chr [1:7266] "18:00:00" "18:00:00" "18:00:00" "18:00:00" ...
 $ State/UnionTerritory    : chr [1:7266] "Kerala" "Kerala" "Kerala" "Kerala" ...
 $ ConfirmedIndianNational : chr [1:7266] "1" "1" "2" "3" ...
 $ ConfirmedForeignNational: chr [1:7266] "0" "0" "0" "0" ...
 $ Cured                   : num [1:7266] 0 0 0 0 0 0 0 0 0 0 ...
 $ Deaths                  : num [1:7266] 0 0 0 0 0 0 0 0 0 0 ...
 $ Confirmed               : num [1:7266] 1 1 2 3 3 3 3 3 3 3 ...
 $ TotalSamples            : num [1:7266] NA NA NA NA NA NA NA NA NA NA ...
 $ Positive                : num [1:7266] NA NA NA NA NA NA NA NA NA NA ...

The State/UnionTerritory variable has been converted to a factor variable. But there is no need to for ordering/labelling. Instead the data has been arranged in increasing Alphabetical order for the variable State/UnionTerritory. Earlier it was arranged based on date which had all the data for states mixed up. The data is more clear now as it is arranged for the States and all the data for a particular state could be found continously.

df_join$`State/UnionTerritory`<-as.factor(df_join$`State/UnionTerritory`)
df_join<-df_join%>% arrange(`State/UnionTerritory`)

head(df_join)
str(df_join)
tibble [7,266 × 10] (S3: tbl_df/tbl/data.frame)
 $ Date                    : Date[1:7266], format: "2020-03-26" "2020-03-27" "2020-03-28" ...
 $ Time                    : chr [1:7266] "18:00:00" "10:00:00" "18:00:00" "19:30:00" ...
 $ State/UnionTerritory    : Factor w/ 42 levels "Andaman and Nicobar Islands",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ ConfirmedIndianNational : chr [1:7266] "1" "1" "6" "-" ...
 $ ConfirmedForeignNational: chr [1:7266] "0" "0" "0" "-" ...
 $ Cured                   : num [1:7266] 0 0 0 0 0 0 0 0 0 0 ...
 $ Deaths                  : num [1:7266] 0 0 0 0 0 0 0 0 0 0 ...
 $ Confirmed               : num [1:7266] 1 1 6 9 9 10 10 10 10 10 ...
 $ TotalSamples            : num [1:7266] NA NA NA NA NA NA NA NA NA NA ...
 $ Positive                : num [1:7266] NA NA NA NA NA NA NA NA NA NA ...

Tidy and Manipulate II

A variable Negative has been created using the mutate() function to calculated to the total number of people who were Covid-19 negative based on the TotalSamples and Positive variables.

df_join<-mutate(df_join, NegativeCases = TotalSamples - Positive)
head(df_join)

Scan I

The missing values can be calculated using the colSums() function nested with is.na(). The follwing missing values are observed.

colSums(is.na(df_join))
                    Date                     Time     State/UnionTerritory 
                       0                      179                        0 
 ConfirmedIndianNational ConfirmedForeignNational                    Cured 
                     179                      179                      179 
                  Deaths                Confirmed             TotalSamples 
                     179                      179                     1300 
                Positive            NegativeCases 
                    2772                     2772 

The missing values can be omitted as it would not affect the dataset. Even though about 20% of values are omitted, still it won’t affect the dataset as the future dates contain the cases and samples recorded for all the previous dates. This is because ever date also has the records of the cases recorded till previous date also included in that and not only new cases of that day. Even if we omit values for a particular date, the observations for the next nearest date contains the sum of cases or new cases recorded for all the previous dates and hence it would not affect the case and Sample count of the country Statewise. na.omit() function is used to omit the missing values.

df_join<-na.omit(df_join)
colSums(is.na(df_join))
                    Date                     Time     State/UnionTerritory 
                       0                        0                        0 
 ConfirmedIndianNational ConfirmedForeignNational                    Cured 
                       0                        0                        0 
                  Deaths                Confirmed             TotalSamples 
                       0                        0                        0 
                Positive            NegativeCases 
                       0                        0 
str(df_join)
tibble [4,357 × 11] (S3: tbl_df/tbl/data.frame)
 $ Date                    : Date[1:4357], format: "2020-04-17" "2020-04-24" "2020-04-27" ...
 $ Time                    : chr [1:4357] "17:00:00" "17:00:00" "17:00:00" "17:00:00" ...
 $ State/UnionTerritory    : Factor w/ 42 levels "Andaman and Nicobar Islands",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ ConfirmedIndianNational : chr [1:4357] "-" "-" "-" "-" ...
 $ ConfirmedForeignNational: chr [1:4357] "-" "-" "-" "-" ...
 $ Cured                   : num [1:4357] 10 11 11 16 33 33 33 33 33 33 ...
 $ Deaths                  : num [1:4357] 0 0 0 0 0 0 0 0 0 0 ...
 $ Confirmed               : num [1:4357] 11 22 33 33 33 33 33 33 33 33 ...
 $ TotalSamples            : num [1:4357] 1403 2679 2848 3754 6677 ...
 $ Positive                : num [1:4357] 12 27 33 33 33 33 33 33 33 33 ...
 $ NegativeCases           : num [1:4357] 1391 2652 2815 3721 6644 ...
 - attr(*, "na.action")= 'omit' Named int [1:2909] 1 2 3 4 5 6 7 8 9 10 ...
  ..- attr(*, "names")= chr [1:2909] "1" "2" "3" "4" ...
head(df_join)

Scan II

Now the outliers in the dataset are observed. The variables Cured, Deaths, Confirmed, TotalSamples, Positive, NegativeCases are observed for possible outliers using the boxplot for each variables.

df_join$Confirmed %>%  boxplot(main="Box Plot of Confirmed", ylab="Confirmed", col = "grey")

df_join$Cured %>%  boxplot(main="Box Plot of Cured", ylab="Cured", col = "grey")

df_join$Deaths %>%  boxplot(main="Box Plot of Deaths", ylab="Deaths", col = "grey")

df_join$TotalSamples %>%  boxplot(main="Box Plot of TotalSamples", ylab="TotalSamples", col = "grey")

df_join$Positive %>%  boxplot(main="Box Plot of Positive", ylab="Positive", col = "grey")

df_join$NegativeCases %>%  boxplot(main="Box Plot of NegativeCases", ylab="NegativeCases", col = "grey")

NA
NA

It is observed that all the variables contain outliers. This is because ever date also has the records of the cases recorded till previous date also included in that and not only new cases of that day. So the observation count for that particular day is the observation recorded for that day minus for the previous day which gives us the count of that particular day. Hence, outliers are kept intact.

Transform

By creating a histogram of the variable confimed, it is observed that the variable is right skewed.

hist(df_join$Confirmed)

So mathematical operations have been used to reduce skewness and convert distribution to normal distribution. Using the natural logarithm transformation

hist(log(df_join$Confirmed))

LS0tCnRpdGxlOiAiRGF0YSBXcmFuZ2xpbmcgTUFUSDIzNDkgQXNzaWdubWVudCAyIgphdXRob3I6ICdUYW5tYXkgVmFzaGlzdGgsICBTdHVkZW50IElkOiBzMzgyMzE3NicKZGF0ZTogIjI1LzEwLzIwMjAiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAotLS0KIyMgUmVxdWlyZWQgUGFja2FnZXMKPGJyPgpgYGB7cn0KbGlicmFyeShyZWFkcikKbGlicmFyeShvdXRsaWVycykKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmBgYAoKCiMjIEV4ZWN1dGl2ZSBTdW1tYXJ5CkRhdGEgV3JhbmdsaW5nIHJlZmVycyB0byB0aGUgcHJlcHJvY2Vzc2luZyBvZiBEYXRhIGFuZCBjb252ZXJ0aW5nIGl0IGludG8gYW4gYW5hbHl6YWJsZSBzdGF0ZS4gVGhlIHR3byBkYXRhc2V0cyB1c2VkIGZvciB0aGUgYXNzaWdubWVudCBhcmUgVGhlIENvdmlkLTE5IEluZGlhIERhdGFzZXQgYW5kIHRoZSBTdGF0ZXdpc2UgVGVzdGluZyBEZXRhaWxzIGRhdGFzZXQuIDxicj4KQm90aCB0aGUgZGF0YXNldHMgYXJlIGF2YWlsYWJsZSBvbjogaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9zdWRhbGFpcmFqa3VtYXIvY292aWQxOS1pbi1pbmRpYQo8YnI+ClRoZSBkYXRhc2V0cyBhcmUgbWVyZ2VkIHRvZ2V0aGVyIGZvciB0aGUgYXNzaWdubWVudCBwdXJwb3NlLiBWYXJpb3VzIHRhc2tzIGxpa2UgZGF0YSB1bmRlcnN0YW5kaW5nLCB0aWR5aW5nIG9mIGRhdGEsIG1hbmlwdWxhdGlvbiwgZmlsdGVyaW5nLCBzY2FubmluZywgdHJhbnNmb3JtaW5nIGhhdmUgYmVlbiBwZXJmb3JtZWQgb24gdGhlIGRhdGFzZXQuIFNrZXduZXNzIGlzIGNoZWNrZWQgZm9yIHRoZSBDb25maXJtZWQgY2FzZXMgdmFyaWFibGUgYW5kIHRoZSBuZWNjZXNzYXJ5IHRyYW5zZm9ybWF0aW9uIGlzIGRvbmUgdG8gcmVkdWNlIHRoZSBza2V3bmVzcy4KPGJyPiA8YnI+CgoKIyMgRGF0YQpUaGUgRGF0YXNldCB1c2VkIGFyZSB0aGUgY292aWRfMTlfaW5kaWFbMV0gd2hpY2ggY29udGFpbnMgdGhlIGRldGFpbHMgb2YgdGhlIGluY3JlYXNlIGluIGNvcm9uYXZpcnVzIGNhc2VzIHBlciBkYXkgaW4gZGlmZmVyZW50IHN0YXRlcyBvZiBJbmRpYSBhbmQgdGhlIFN0YXRld2lzZVRlc3RpbmdkZXRhaWxzWzFdIHdoaWNoIGNvbnRhaW5zIHRoZSBkYXRlIHdpc2UgZGV0YWlscyBvZiB0aGUgVG90YWwgdGVzdHMgY2FycmllZCBvdXQgZWFjaCBkYXkgaW4gZGlmZmVyZW50IHN0YXRlcyBvZiBJbmRpYS48YnI+ClRoZSB2YXJpYWJsZXMgaW4gY292aWRfMTlfaW5kaWEgZGF0YXNldCBhcmUgRGF0ZSBhbmQgdGltZSBvZiByZWNvcmRpbmcsIHRoZSBTdGF0ZS9VbmlvbiBUZXJyaXRvcnkgZm9yIHdoaWNoIHRoZSBpbmZvcm1hdGlvbiBpcyByZWNvcmRlZCwgQ29uZmlybWVkSW5kaWFuTmF0aW9uYWxzIHJlZmVycyB0byB0aGUgY2FzZXMgcmVwb3J0ZWQgZnJvbSBJbmRpYW4gY2l0aXplbnMsIENvbmZpcm1lZEZvcmVpZ25OYXRpb25hbHMgYXJlIHRoZSBjYXNlcyByZXBvcnRlZCBmcm9tIHBlb3BsZSB3aG8gYXJlIG5vdCBJbmRpYW4gQ2l0aXplbnMsIEN1cmVkIHJlZmVycyB0byBjYXNlcyBjdXJlZCB0aWxsIHRoYXQgZGF0ZSwgRGVhdGhzIGFyZSB0aGUgbnVtYmVyIG9mIGRlYXRocyBkdWUgdG8gQ292aWQtMTkgdGlsbCB0aGF0IGRhdGUsIGFuZCBDb25maXJtZWQgcmVmZXJzIHRvIHRoZSB0b3RhbCBjb25maXJtZWQgY2FzZXMgaW4gSW5kaWEgdGlsbCB0aGF0IGRhdGUuPGJyPgpUaGUgdmFyaWFibGVzIGluIFN0YXRld2lzZVRlc3RpbmdkZXRhaWxzIGRhdGFzZXQgYXJlIERhdGUgd2hpY2ggcmVmZXJzIHRvIHRoZSBkYXRlIG9mIHRoZSBpbmZvcm1hdGlvbiByZWNvcmRlZCwgU3RhdGVzIHJlZmVycyB0byB0aGUgU3RhdGUgb2YgSW5kaWEgZm9yIHdoaWNoIHRoZSBpbmZvcm1hdGlvbiBpcyByZWNvcmRlZCwgVG90YWxTYW1wbGVzIHJlZmVycyB0byB0aGUgVGVzdHMgYmVpbmcgZG9uZSB0aWxsIHRoYXQgZGF0ZSwgYW5kIFBvc2l0aXZlIFJlZmVycyB0byB0aGUgdG90YWwgbnVtYmVyIG9mIHBlb3BsZSBpbmZlY3RlZCBieSBjb3JvbmF2aXJ1cyB0aWxsIHRoZSBkYXRlIGluIHRoYXQgU3RhdGUuCmBgYHtyfQpjb3ZpZF8xOV9pbmRpYSA8LSByZWFkX2NzdigiRG93bmxvYWRzL2NvdmlkXzE5X2luZGlhLmNzdiIpCmBgYAoKYGBge3J9ClN0YXRld2lzZVRlc3RpbmdEZXRhaWxzIDwtIHJlYWRfY3N2KCJEb3dubG9hZHMvU3RhdGV3aXNlVGVzdGluZ0RldGFpbHMuY3N2IikKY292aWRfMTlfaW5kaWE8LSBjb3ZpZF8xOV9pbmRpYSU+JXVuaXRlKERhdGVUaW1lLCBEYXRlLCBUaW1lLCBzZXA9IiAiKQoKYGBgCgpgYGB7cn0KaGVhZChjb3ZpZF8xOV9pbmRpYSkKaGVhZChTdGF0ZXdpc2VUZXN0aW5nRGV0YWlscykKYGBgCgpUaGUgdHdvIGRhdGFzZXRzIGhhdmUgYmVlbiBtZXJnZWQgdG9nZXRoZXIgYXMgcGVyIHRoZSBhc3NpZ25tZW50IHNwZWNpZmljYXRpb24uIFRoZSB0eXBlIG9mIHRoZSB2YXJpYWJsZSBkYXRlIGZvciBTdGF0ZXdpc2VUZXN0aW5nZGV0YWlscyBoYXMgYmVlbiBjb252ZXJ0ZWQgdG8gY2hhcmFjdGVyIGZvciBwcm9wZXIgbWVyZ2luZyBvZiB0aGUgZGF0YXNldCBhcyB0aGUgY292aWRfMTlfaW5kaWEgaGFzIGRhdGUgc3RvcmVkIGFzIGEgY2hhcmFjdGVyIHZhcmlhYmxlLgpgYGB7cn0KU3RhdGV3aXNlVGVzdGluZ0RldGFpbHMkRGF0ZTwtYXMuY2hhcmFjdGVyKFN0YXRld2lzZVRlc3RpbmdEZXRhaWxzJERhdGUsIGZvcm1hdD0iJWQvJW0vJXkiKQpjb3ZpZF8xOV9pbmRpYTwtY292aWRfMTlfaW5kaWEgJT4lc2VwYXJhdGUoRGF0ZVRpbWUsIGludG8gPSBjKCJEYXRlIiwgIlRpbWUiKSwgc2VwID0gIiAiKQpkZl9qb2luIDwtZnVsbF9qb2luKGNvdmlkXzE5X2luZGlhLFN0YXRld2lzZVRlc3RpbmdEZXRhaWxzLCBieSA9IGMoIkRhdGUiID0gIkRhdGUiLCAiU3RhdGUvVW5pb25UZXJyaXRvcnkiPSJTdGF0ZSIpKQoKaGVhZChkZl9qb2luKQpgYGAKIyMgVGlkeSAmIERhdGEgTWFuaXB1bGF0ZSBJCkl0IGlzIG9ic2VydmVkIGluIHRoZSBkYXRhc2V0IGNvdmlkXzE5X2luZGlhLCB0aGUgZGF0ZSBhbmQgdGltZSBoYXZlIGJlZW4gbWVyZ2VkIGludG8gYSBzaW5nbGUgY29sdW0uIEl0cyBicmVha3MgdGhlIFdpY2toYW0gYW5kIEdyb2xlbXVuZCBwcmluY2lwbGVzIGFzIGVhY2ggdmFyaWFibGUgbXVzdCBoYXZlIGl0cyBvd24gY29sdW1uLgpEYXRlIGFuZCBUaW1lIGNhbiBiZSBzZXBhcmF0ZWQgYXMgZm9sbG93czoKYGBge3J9CmNvdmlkXzE5X2luZGlhPC1jb3ZpZF8xOV9pbmRpYSAlPiVzZXBhcmF0ZShEYXRlVGltZSwgaW50byA9IGMoIkRhdGUiLCAiVGltZSIpLCBzZXAgPSAiICIpCgpgYGAKCmBgYHtyfQpoZWFkKGRmX2pvaW4pCmBgYAoKVGhlIGFib3ZlIGNvZGUgaGFzIGJlZW4gdXNlZCBiZWZvcmUgbWVyZ2luZyB0aGUgMiBkYXRhc2V0cyBhYm92ZSBpbiB0aGUgRGF0YSBzZWN0aW9uLgoKIyMgVW5kZXJzdGFuZApUaGUgc3RydWN0dXJlIGFuZCBkaW1lbnNpb25zIG9mIHRoZSBkYXRhc2V0IGNhbiBiZSBjaGVja2VkIHVzaW5nIHRoZSBzdHIoKSBhbmQgZGltKCkgZnVuY3Rpb25zIHJlc3BlY3RpdmVseS4gV2UgY2FuIG9ic2VydmUgdGhhdCB0aGUgZGF0YXNldCBjb250YWlucyBjaGFyYWN0ZXIsIHRpbWUsIG51bWVyaWMgdmFyaWFibGVzLiBUaGVyZSBhcmUgYSB0b3RhbCBvZiA3MjY2IG9ic2VydmF0aW9ucyBhbmQgYSB0b3RhbCBvZiAxMCB2YXJpYWJsZXMuCgpgYGB7cn0KZGltKGRmX2pvaW4pCnN0cihkZl9qb2luKQpgYGAKRWFybGllciBvbiB0aGUgdHlwZSBvZiB0aGUgdmFyaWFibGUgZGF0ZSBmb3IgU3RhdGV3aXNlVGVzdGluZ2RldGFpbHMgaGFzIGJlZW4gY29udmVydGVkIHRvIGNoYXJhY3RlciBmb3IgcHJvcGVyIG1lcmdpbmcgb2YgdGhlIGRhdGFzZXQgYXMgdGhlIGNvdmlkXzE5X2luZGlhIGhhcyBkYXRlIHN0b3JlZCBhcyBhIGNoYXJhY3RlciB2YXJpYWJsZS4KSW4gdGhlIG1lcmdlZCBkYXRhc2V0LCB3ZSBjYW4gb2JzZXJ2ZSB0aGF0IHRoZSBkYXRlIGlzIHN0b3JlZCBhcyBhIGNoYXJhY3RlciB2YXJpYWJsZSBhbmQgc2hvdWxkIGJlIGNvbnZlcnRlZCB0byB0eXBlIERhdGUuCmBgYHtyfQpkZl9qb2luJERhdGU8LWFzLkRhdGUoZGZfam9pbiREYXRlLGZvcm1hdCA9ICIlZC8lbS8leSIpCnN0cihkZl9qb2luKQoKYGBgCgpUaGUgU3RhdGUvVW5pb25UZXJyaXRvcnkgdmFyaWFibGUgaGFzIGJlZW4gY29udmVydGVkIHRvIGEgZmFjdG9yIHZhcmlhYmxlLiBCdXQgdGhlcmUgaXMgbm8gbmVlZCB0byBmb3Igb3JkZXJpbmcvbGFiZWxsaW5nLiBJbnN0ZWFkIHRoZSBkYXRhIGhhcyBiZWVuIGFycmFuZ2VkIGluIGluY3JlYXNpbmcgQWxwaGFiZXRpY2FsIG9yZGVyIGZvciB0aGUgdmFyaWFibGUgU3RhdGUvVW5pb25UZXJyaXRvcnkuIEVhcmxpZXIgaXQgd2FzIGFycmFuZ2VkIGJhc2VkIG9uIGRhdGUgd2hpY2ggaGFkIGFsbCB0aGUgZGF0YSBmb3Igc3RhdGVzIG1peGVkIHVwLiBUaGUgZGF0YSBpcyBtb3JlIGNsZWFyIG5vdyBhcyBpdCBpcyBhcnJhbmdlZCBmb3IgdGhlIFN0YXRlcyBhbmQgYWxsIHRoZSBkYXRhIGZvciBhIHBhcnRpY3VsYXIgc3RhdGUgY291bGQgYmUgZm91bmQgY29udGlub3VzbHkuCmBgYHtyfQpkZl9qb2luJGBTdGF0ZS9VbmlvblRlcnJpdG9yeWA8LWFzLmZhY3RvcihkZl9qb2luJGBTdGF0ZS9VbmlvblRlcnJpdG9yeWApCmRmX2pvaW48LWRmX2pvaW4lPiUgYXJyYW5nZShgU3RhdGUvVW5pb25UZXJyaXRvcnlgKQoKaGVhZChkZl9qb2luKQpzdHIoZGZfam9pbikKYGBgCgoKCiMjIFRpZHkgYW5kIE1hbmlwdWxhdGUgSUkKQSB2YXJpYWJsZSBOZWdhdGl2ZSBoYXMgYmVlbiBjcmVhdGVkIHVzaW5nIHRoZSBtdXRhdGUoKSBmdW5jdGlvbiB0byBjYWxjdWxhdGVkIHRvIHRoZSB0b3RhbCBudW1iZXIgb2YgcGVvcGxlIHdobyB3ZXJlIENvdmlkLTE5IG5lZ2F0aXZlIGJhc2VkIG9uIHRoZSBUb3RhbFNhbXBsZXMgYW5kIFBvc2l0aXZlIHZhcmlhYmxlcy4KYGBge3J9CmRmX2pvaW48LW11dGF0ZShkZl9qb2luLCBOZWdhdGl2ZUNhc2VzID0gVG90YWxTYW1wbGVzIC0gUG9zaXRpdmUpCmhlYWQoZGZfam9pbikKYGBgCgojIyBTY2FuIEkKVGhlIG1pc3NpbmcgdmFsdWVzIGNhbiBiZSBjYWxjdWxhdGVkIHVzaW5nIHRoZSBjb2xTdW1zKCkgZnVuY3Rpb24gbmVzdGVkIHdpdGggaXMubmEoKS4KVGhlIGZvbGx3aW5nIG1pc3NpbmcgdmFsdWVzIGFyZSBvYnNlcnZlZC4KYGBge3J9CmNvbFN1bXMoaXMubmEoZGZfam9pbikpCgpgYGAKClRoZSBtaXNzaW5nIHZhbHVlcyBjYW4gYmUgb21pdHRlZCBhcyBpdCB3b3VsZCBub3QgYWZmZWN0IHRoZSBkYXRhc2V0LiBFdmVuIHRob3VnaCBhYm91dCAyMCUgb2YgdmFsdWVzIGFyZSBvbWl0dGVkLCBzdGlsbCBpdCB3b24ndCBhZmZlY3QgdGhlIGRhdGFzZXQgYXMgdGhlIGZ1dHVyZSBkYXRlcyBjb250YWluIHRoZSBjYXNlcyBhbmQgc2FtcGxlcyByZWNvcmRlZCBmb3IgYWxsIHRoZSBwcmV2aW91cyBkYXRlcy4gVGhpcyBpcyBiZWNhdXNlIGV2ZXIgZGF0ZSBhbHNvIGhhcyB0aGUgcmVjb3JkcyBvZiB0aGUgY2FzZXMgcmVjb3JkZWQgdGlsbCBwcmV2aW91cyBkYXRlIGFsc28gaW5jbHVkZWQgaW4gdGhhdCBhbmQgbm90IG9ubHkgbmV3IGNhc2VzIG9mIHRoYXQgZGF5LiBFdmVuIGlmIHdlIG9taXQgdmFsdWVzIGZvciBhIHBhcnRpY3VsYXIgZGF0ZSwgdGhlIG9ic2VydmF0aW9ucyBmb3IgdGhlIG5leHQgbmVhcmVzdCBkYXRlIGNvbnRhaW5zIHRoZSBzdW0gb2YgY2FzZXMgb3IgbmV3IGNhc2VzIHJlY29yZGVkIGZvciBhbGwgdGhlIHByZXZpb3VzIGRhdGVzIGFuZCBoZW5jZSBpdCB3b3VsZCBub3QgYWZmZWN0IHRoZSBjYXNlIGFuZCBTYW1wbGUgY291bnQgb2YgdGhlIGNvdW50cnkgU3RhdGV3aXNlLgpuYS5vbWl0KCkgZnVuY3Rpb24gaXMgdXNlZCB0byBvbWl0IHRoZSBtaXNzaW5nIHZhbHVlcy4KCgpgYGB7cn0KZGZfam9pbjwtbmEub21pdChkZl9qb2luKQpjb2xTdW1zKGlzLm5hKGRmX2pvaW4pKQpzdHIoZGZfam9pbikKaGVhZChkZl9qb2luKQpgYGAKCgojIyBTY2FuIElJCgpOb3cgdGhlIG91dGxpZXJzIGluIHRoZSBkYXRhc2V0IGFyZSBvYnNlcnZlZC4gVGhlIHZhcmlhYmxlcyBDdXJlZCwgRGVhdGhzLCBDb25maXJtZWQsIFRvdGFsU2FtcGxlcywgUG9zaXRpdmUsIE5lZ2F0aXZlQ2FzZXMgYXJlIG9ic2VydmVkIGZvciBwb3NzaWJsZSBvdXRsaWVycyB1c2luZyB0aGUgYm94cGxvdCBmb3IgZWFjaCB2YXJpYWJsZXMuCmBgYHtyfQpkZl9qb2luJENvbmZpcm1lZCAlPiUgIGJveHBsb3QobWFpbj0iQm94IFBsb3Qgb2YgQ29uZmlybWVkIiwgeWxhYj0iQ29uZmlybWVkIiwgY29sID0gImdyZXkiKQpkZl9qb2luJEN1cmVkICU+JSAgYm94cGxvdChtYWluPSJCb3ggUGxvdCBvZiBDdXJlZCIsIHlsYWI9IkN1cmVkIiwgY29sID0gImdyZXkiKQpkZl9qb2luJERlYXRocyAlPiUgIGJveHBsb3QobWFpbj0iQm94IFBsb3Qgb2YgRGVhdGhzIiwgeWxhYj0iRGVhdGhzIiwgY29sID0gImdyZXkiKQpkZl9qb2luJFRvdGFsU2FtcGxlcyAlPiUgIGJveHBsb3QobWFpbj0iQm94IFBsb3Qgb2YgVG90YWxTYW1wbGVzIiwgeWxhYj0iVG90YWxTYW1wbGVzIiwgY29sID0gImdyZXkiKQpkZl9qb2luJFBvc2l0aXZlICU+JSAgYm94cGxvdChtYWluPSJCb3ggUGxvdCBvZiBQb3NpdGl2ZSIsIHlsYWI9IlBvc2l0aXZlIiwgY29sID0gImdyZXkiKQpkZl9qb2luJE5lZ2F0aXZlQ2FzZXMgJT4lICBib3hwbG90KG1haW49IkJveCBQbG90IG9mIE5lZ2F0aXZlQ2FzZXMiLCB5bGFiPSJOZWdhdGl2ZUNhc2VzIiwgY29sID0gImdyZXkiKQoKCmBgYApJdCBpcyBvYnNlcnZlZCB0aGF0IGFsbCB0aGUgdmFyaWFibGVzIGNvbnRhaW4gb3V0bGllcnMuIFRoaXMgaXMgYmVjYXVzZSBldmVyIGRhdGUgYWxzbyBoYXMgdGhlIHJlY29yZHMgb2YgdGhlIGNhc2VzIHJlY29yZGVkIHRpbGwgcHJldmlvdXMgZGF0ZSBhbHNvIGluY2x1ZGVkIGluIHRoYXQgYW5kIG5vdCBvbmx5IG5ldyBjYXNlcyBvZiB0aGF0IGRheS4gU28gdGhlIG9ic2VydmF0aW9uIGNvdW50IGZvciB0aGF0IHBhcnRpY3VsYXIgZGF5IGlzIHRoZSBvYnNlcnZhdGlvbiByZWNvcmRlZCBmb3IgdGhhdCBkYXkgbWludXMgZm9yIHRoZSBwcmV2aW91cyBkYXkgd2hpY2ggZ2l2ZXMgdXMgdGhlIGNvdW50IG9mIHRoYXQgcGFydGljdWxhciBkYXkuIEhlbmNlLCBvdXRsaWVycyBhcmUga2VwdCBpbnRhY3QuCgojIyBUcmFuc2Zvcm0KQnkgY3JlYXRpbmcgYSBoaXN0b2dyYW0gb2YgdGhlIHZhcmlhYmxlIGNvbmZpbWVkLCBpdCBpcyBvYnNlcnZlZCB0aGF0IHRoZSB2YXJpYWJsZSBpcyByaWdodCBza2V3ZWQuCmBgYHtyfQpoaXN0KGRmX2pvaW4kQ29uZmlybWVkKQoKYGBgCgpTbyBtYXRoZW1hdGljYWwgb3BlcmF0aW9ucyBoYXZlIGJlZW4gdXNlZCB0byByZWR1Y2Ugc2tld25lc3MgYW5kIGNvbnZlcnQgZGlzdHJpYnV0aW9uIHRvIG5vcm1hbCBkaXN0cmlidXRpb24uIFVzaW5nIHRoZSBuYXR1cmFsIGxvZ2FyaXRobSB0cmFuc2Zvcm1hdGlvbgpgYGB7cn0KaGlzdChsb2coZGZfam9pbiRDb25maXJtZWQpKQoKYGBgCgo=