Required packages

Provide the packages required to reproduce the report. Make sure you fulfilled the minimum requirement #10.

library(readr)
library(readxl)
library(magrittr)
library(dplyr)
library(tidyr)
library(Hmisc)
library(plyr)
library(foreign)
library(lubridate)
library(forecast)

Executive Summary

1.Two datasets consisting of information about a body weight lifting competition was uploaded in R to perform detailed data preprocessing functions.

2.Dataset_1 consisting of information of weight lifting competition and Dataset_2 consisting of event information of the weightlifting competition was joined to form a final detailed dataset with all the information in one table and was named Final_Dataset.

3.As our data didn’t conform to the tidy data principles, manipulation and changes were made to tidy the dataset.

4.A new variable Totalliftkg was formed by mutating 3 variables namely BestSquatKg, BestBenchKg and BestDeadliftkg from the Final_Dataset.

5.The data was then scanned for missing values, inconsistances and obvious errors.

6.It was found that the data consisted of large number of missing values in the dataset.So,in order to overcome such a problem and we were missing values only in numeric variables, we decided to impute the mean of the variables in the cells that contained no values.

7.To visually represent the numeric variables in our dataset, we then plotted a boxplot for all the variables.

8.Outliers were seen the visual representation and hence to overcome such values we filtered out the outliers.

9.Data transformation on Best Bench (kg) was done using the log and the boxcox transformation.

10.However we felt that the boxcox transformation provided better visual represenation in reducing skewness and in converting the distribution into normal distribution.

Data

1.Datasets were acquired from the following website“https://www.kaggle.com/open-powerlifting/powerlifting-database” in xlsx format.

2.Dataset 1 stored as powerlifting.xlsx in the working directory consisted information of different powerlifting results.At total it consisted of 1117 observations and 11 variables. The eleven variables listed were MeetId,Name,Sex,Equipment,Age,Bodyweight(kg),Weightclass(kg),Best Squat(kg), BestBench(kg) and Wilks.

3.Dataset 2 on the other-hand was stored as meets.xlsx, consisting of information about the meets of the different powerlifting competitions. At total it consisted of 21 observations and 8 variables. The variables included MeetID, Federation,MeetCountry,MeetState,MeetTown,MeetName and date.

4.Both dataset were imported into R using the read_excel function from the library(readxl).

DataSet1<-read_excel("powerlifting.xlsx") 
head(DataSet1)
DataSet2<-read_excel("meets.xlsx")
head(DataSet2)

Understand

  1. The two dataset was then joined into a single dataset using the full join function on the variable MeetId and was assigned as Final_Dataset.
  2. Str function was implemented on the dataset to get a listed representation of all the datatypes and the sturucture, put together for convinence.
Final_Dataset<-DataSet1 %>% full_join(DataSet2)
Joining, by = "MeetID"
str(Final_Dataset)
Classes 'tbl_df', 'tbl' and 'data.frame':   1117 obs. of  18 variables:
 $ MeetID        : num  0 0 0 0 0 0 0 0 0 0 ...
 $ Name          : chr  "Angie Belk Terry" "Dawn Bogart" "Dawn Bogart" "Dawn Bogart" ...
 $ Sex           : chr  "F" "F" "F" "F" ...
 $ Equipment     : chr  "Wraps" "Single-ply" "Single-ply" "Raw" ...
 $ Age           : num  47 42 42 42 18 28 60 60 52 52 ...
 $ BodyweightKg  : num  59.6 58.5 58.5 58.5 63.7 ...
 $ WeightClassKg : chr  "60" "60" "60" "60" ...
 $ BestSquatKg   : num  47.6 142.9 142.9 NA NA ...
 $ BestBenchKg   : num  20.4 95.2 95.2 95.2 31.8 ...
 $ BestDeadliftKg: num  70.3 163.3 163.3 NA 90.7 ...
 $ Wilks         : num  155 456 456 108 130 ...
 $ MeetPath      : chr  "365strong/1601" "365strong/1601" "365strong/1601" "365strong/1601" ...
 $ Federation    : chr  "365Strong" "365Strong" "365Strong" "365Strong" ...
 $ MeetCountry   : chr  "USA" "USA" "USA" "USA" ...
 $ MeetState     : chr  "NC" "NC" "NC" "NC" ...
 $ MeetTown      : chr  "Charlotte" "Charlotte" "Charlotte" "Charlotte" ...
 $ MeetName      : chr  "2016 Junior & Senior National Powerlifting Championships" "2016 Junior & Senior National Powerlifting Championships" "2016 Junior & Senior National Powerlifting Championships" "2016 Junior & Senior National Powerlifting Championships" ...
 $ Date          : POSIXct, format: "2016-10-29" "2016-10-29" "2016-10-29" "2016-10-29" ...
head(Final_Dataset)

Tidy & Manipulate Data I

  1. Unfortunately our data was not tidy, so certain tidying and manipulation was done.
  2. We firstly seperated the values in MeetPath into two different columns i.e, federation and path.
  3. Then factorized sex and gave a better labelling.
  4. Equipment column and meet ID was also factorized so that analyzing can be easier in the next step of data analysis.
  5. Weight Class category was factorized from character datatype into categorical ordinal data. A better labelling was also done for WeightClassKg.
  6. Finally the as.Date function was used to convert date to date format.
Final_Dataset <- Final_Dataset %>% separate(MeetPath, into=c("Federation", "Path"), sep="/")
Final_Dataset$Sex<- Final_Dataset$Sex %>% factor(levels = c("M","F"),labels = c("Male","Female"))
Final_Dataset$Equipment<-Final_Dataset$Equipment %>% factor(levels =c("Raw","Wraps","Multi-ply","Single-ply"))
Final_Dataset$WeightClassKg<-Final_Dataset$WeightClassKg %>% factor(levels =c("140+","140","125","110","100","90","82.5","75","67.5","60","56","52","48","44","42","40"), ordered = TRUE)
Final_Dataset$MeetID<-as.factor(Final_Dataset$MeetID) 
Final_Dataset<-rename(Final_Dataset,c("WeightClassKg"="Weight Category (Kg)"))
#date formating
Final_Dataset$Date <- as.Date(Final_Dataset$Date, "%d/%m/%Y")
unknown timezone '%d/%m/%Y'
head(Final_Dataset)

Tidy & Manipulate Data II

  1. A new variable was created called TotalLiftKg which included the addition of the BestSquat, BestBenchKg and BestDeadLiftKg, however before mutating the variable from existing variable, we replaced all the Na variables in the three columns to zero so that Na values are neglected in the new variable.
Final_Dataset %>% replace_na(list(BestSquatKg=0, BestBenchKg=0, BestDeadliftKg = 0)) %>% mutate (Final_Dataset, TotalLiftKg = BestSquatKg + BestBenchKg + BestDeadliftKg)

Scan I

  1. Missing values, incosistences and obvious errors was checked in this section.
  2. Missing values were found in various variables such as age, BodyweightKg, BestSquatKg,BestBenchKg, and Wilks.
  3. The method of mean imputation were used to handle the missing values in all the variables as all the variables were numeric.
  4. The colSum (is.na(Final_Dataset)) function were used for refrence of the missing values.
colSums(is.na(Final_Dataset)) 
              MeetID                 Name                  Sex            Equipment                  Age         BodyweightKg Weight Category (Kg) 
                   0                    0                    0                    0                   11                    1                    0 
         BestSquatKg          BestBenchKg       BestDeadliftKg                Wilks           Federation                 Path          MeetCountry 
                 412                  125                  224                   39                    0                    0                    0 
           MeetState             MeetTown             MeetName                 Date 
                   0                    0                    0                    0 
Final_Dataset$BodyweightKg<-impute(Final_Dataset$BodyweightKg,fun = mean)
Final_Dataset$Age <-impute(Final_Dataset$Age, fun = mean)
Final_Dataset$BestSquatKg<-impute(Final_Dataset$BestSquatKg, fun = mean)
Final_Dataset$BestBenchKg<-impute(Final_Dataset$BestBenchKg, fun = mean)
Final_Dataset$BestDeadliftKg<-impute(Final_Dataset$BestDeadliftKg, fun = mean)
Final_Dataset$Wilks<-impute(Final_Dataset$Wilks, fun = mean)
colSums(is.na(Final_Dataset))
              MeetID                 Name                  Sex            Equipment                  Age         BodyweightKg Weight Category (Kg) 
                   0                    0                    0                    0                    0                    0                    0 
         BestSquatKg          BestBenchKg       BestDeadliftKg                Wilks           Federation                 Path          MeetCountry 
                   0                    0                    0                    0                    0                    0                    0 
           MeetState             MeetTown             MeetName                 Date 
                   0                    0                    0                    0 
head(Final_Dataset)

Scan II

  1. A sumaary of the Dataset was first presented for refrence.
  2. As after imputation the datatype remained as impute, we converted the variables to numeric datatype using the function as.numeric, so as to plot the boxplot.
  3. Boxplot were drawn for all the numeric variables and the existing outliers were handled.
  4. If present above the upper fence, the outliers were handled by filtering data using the formula filter(1.5*IQR+Q3) and if present below the lower fence, the formula filter(Q1-1.5IQR).
  5. Box plot after removing the outliers were also presented.
  6. In the boxplot presented below, the wilks boxplot had no outliers present.
  7. In the case of bodyweightkg, best dead lift and best bench press : outliers were presented and removed.
  8. However in the case of Best Squat(kg), outliers were present even after filtering the outliers present, above and below the upper and lower fence.
summary(Final_Dataset)

 11 values imputed to 36.7387 


 1 values imputed to 90.80884 


 412 values imputed to 185.5859 


 125 values imputed to 129.5909 


 224 values imputed to 197.929 


 39 values imputed to 278.6083 

     MeetID        Name               Sex           Equipment        Age         BodyweightKg    Weight Category (Kg)  BestSquatKg     BestBenchKg   
 15     :211   Length:1117        Male  :819   Raw       :775   Min.   : 5.00   Min.   : 26.13   90     :200          Min.   : 20.0   Min.   : 15.5  
 5      :129   Class :character   Female:298   Wraps     :235   1st Qu.:25.00   1st Qu.: 74.16   100    :144          1st Qu.:155.0   1st Qu.: 92.5  
 12     :128   Mode  :character                Multi-ply : 56   Median :33.00   Median : 88.36   75     :130          Median :185.6   Median :129.6  
 2      : 92                                   Single-ply: 51   Mean   :36.74   Mean   : 90.81   110    :126          Mean   :185.6   Mean   :129.6  
 0      : 79                                                    3rd Qu.:47.00   3rd Qu.:106.87   82.5   :126          3rd Qu.:205.0   3rd Qu.:160.0  
 7      : 64                                                    Max.   :95.00   Max.   :179.99   125    :110          Max.   :457.5   Max.   :350.0  
 (Other):414                                                                                     (Other):281                                         
 BestDeadliftKg      Wilks         Federation            Path           MeetCountry         MeetState           MeetTown           MeetName        
 Min.   : 25.0   Min.   : 45.56   Length:1117        Length:1117        Length:1117        Length:1117        Length:1117        Length:1117       
 1st Qu.:150.0   1st Qu.:158.77   Class :character   Class :character   Class :character   Class :character   Class :character   Class :character  
 Median :197.9   Median :286.81   Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character  
 Mean   :197.9   Mean   :278.61                                                                                                                    
 3rd Qu.:238.1   3rd Qu.:375.19                                                                                                                    
 Max.   :374.2   Max.   :666.62                                                                                                                    
                                                                                                                                                   
      Date           
 Min.   :2016-04-10  
 1st Qu.:2016-09-23  
 Median :2017-01-21  
 Mean   :2017-02-03  
 3rd Qu.:2017-06-10  
 Max.   :2017-12-09  
                     
str(Final_Dataset)
Classes 'tbl_df', 'tbl' and 'data.frame':   1117 obs. of  18 variables:
 $ MeetID              : Factor w/ 21 levels "0","1","2","3",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Name                : chr  "Angie Belk Terry" "Dawn Bogart" "Dawn Bogart" "Dawn Bogart" ...
 $ Sex                 : Factor w/ 2 levels "Male","Female": 2 2 2 2 2 2 2 2 2 2 ...
 $ Equipment           : Factor w/ 4 levels "Raw","Wraps",..: 2 4 4 1 1 2 1 1 2 1 ...
 $ Age                 : 'impute' num  47 42 42 42 18 28 60 60 52 52 ...
  ..- attr(*, "imputed")= int  731 854 862 863 864 865 872 873 874 875 ...
 $ BodyweightKg        : 'impute' num  59.6 58.5 58.5 58.5 63.7 ...
  ..- attr(*, "imputed")= int 1103
 $ Weight Category (Kg): Ord.factor w/ 16 levels "140+"<"140"<"125"<..: 10 10 10 10 9 9 9 9 9 9 ...
 $ BestSquatKg         : 'impute' num  47.6 142.9 142.9 185.6 185.6 ...
  ..- attr(*, "imputed")= int  4 5 10 18 19 34 38 39 43 44 ...
 $ BestBenchKg         : 'impute' num  20.4 95.2 95.2 95.2 31.8 ...
  ..- attr(*, "imputed")= int  10 18 38 41 60 69 73 106 107 108 ...
 $ BestDeadliftKg      : 'impute' num  70.3 163.3 163.3 197.9 90.7 ...
  ..- attr(*, "imputed")= int  4 18 34 38 41 43 44 53 55 56 ...
 $ Wilks               : 'impute' num  155 456 456 108 130 ...
  ..- attr(*, "imputed")= int  18 38 41 43 73 107 116 133 135 154 ...
 $ Federation          : chr  "365strong" "365strong" "365strong" "365strong" ...
 $ Path                : chr  "1601" "1601" "1601" "1601" ...
 $ MeetCountry         : chr  "USA" "USA" "USA" "USA" ...
 $ MeetState           : chr  "NC" "NC" "NC" "NC" ...
 $ MeetTown            : chr  "Charlotte" "Charlotte" "Charlotte" "Charlotte" ...
 $ MeetName            : chr  "2016 Junior & Senior National Powerlifting Championships" "2016 Junior & Senior National Powerlifting Championships" "2016 Junior & Senior National Powerlifting Championships" "2016 Junior & Senior National Powerlifting Championships" ...
 $ Date                : Date, format: "2016-10-29" "2016-10-29" "2016-10-29" "2016-10-29" ...
Final_Dataset$Wilks = as.numeric(Final_Dataset$Wilks)
boxplot(Final_Dataset$Wilks, main="Strength of Power Lifters", ylab = "Wilks", col = "grey")

Final_Dataset$BodyweightKg = as.numeric(Final_Dataset$BodyweightKg)
boxplot(Final_Dataset$BodyweightKg, main="Body Weight in kg", ylab = "Weight(kg)",col = "red")

x<-IQR(Final_Dataset$BodyweightKg,na.rm = TRUE)
summary(Final_Dataset$BodyweightKg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  26.13   74.16   88.36   90.81  106.87  179.99 
c<-1.5*x+106.87
z<-Final_Dataset%>% filter(BodyweightKg<156.895) 
boxplot(z$BodyweightKg, main="Body Weight in kg After Removing Outliers", ylab="weight(kg)", col = "red")

Final_Dataset$BestSquatKg= as.numeric(Final_Dataset$BestSquatKg)
boxplot(Final_Dataset$BestSquatKg, main = " Box Plot of Best Squat ", col="blue", ylab="weight(kg)")

Y<-IQR(Final_Dataset$BestSquatKg)
summary(Final_Dataset$BestSquatKg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   20.0   155.0   185.6   185.6   205.0   457.5 
D<-1.5*Y+205.0
R<-155-1.5*Y
R3<-Final_Dataset %>% filter((80.0<BestSquatKg) & (BestSquatKg<280))
boxplot(R3$BestSquatKg, main = " Box Plot of Best Squat  After Removing Outlier ", col="blue",ylab="weight(kg)")

Final_Dataset$BestBenchKg= as.numeric(Final_Dataset$BestBenchKg)
boxplot(Final_Dataset$BestBenchKg, main = " Box Plot of Best Bench ", col="green",ylab="weight(kg)",ylab="weight(kg)")

summary(Final_Dataset$BestBenchKg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   15.5    92.5   129.6   129.6   160.0   350.0 
Q<-IQR(Final_Dataset$BestBenchKg)
H<-1.5*Q+160
T<- Final_Dataset %>% filter(BestBenchKg<261.25)
boxplot(T$BestBenchKg, main = " Box Plot of Best Bench After Removing Outlier ", col="green",ylab="weight(kg)")

Final_Dataset$BestDeadliftKg<-as.numeric(Final_Dataset$BestDeadliftKg)
boxplot(Final_Dataset$BestDeadliftKg, main = " Box Plot of Best Dead Lift ", col="orange",ylab="weight(kg)")

summary(Final_Dataset$BestDeadliftKg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   25.0   150.0   197.9   197.9   238.1   374.2 
W<-IQR(Final_Dataset$BestDeadliftKg)
K<-1.5*W+238.1
R<-Final_Dataset %>% filter(BestDeadliftKg<370.31)
boxplot(R$BestDeadliftKg, main = "Box Plot of Best Dead Lift After Removing Outlier", col="orange",ylab="weight(kg)")

Transform

1.Data transformation on Best Bench (kg) was done using the log and the boxcox transformation.
2.However it was found that the transformation with boxcox transformation provided better visual represenation in reducing skewness and converting the distribution into normal distribution.

hist(Final_Dataset$BestBenchKg,col = "grey")

hist(log(Final_Dataset$BestBenchKg), main = "Log Transformation to BestBenchKg",col = "grey")

boxcox<-BoxCox(Final_Dataset$BestBenchKg, lambda = "auto")
hist(boxcox, main = "Boxcox Transformation to BestBenchkg",col = "grey")



LS0tCnRpdGxlOiAiTUFUSDIzNDkgU2VtZXN0ZXIgMiwgMjAxOCIKYXV0aG9yOiAiIFRlbnppbmcgU2FuZ2F5IEJodXRpYSAoczM2ODA0NDYpLCBRaWFud2VpIFlhbmcoczM3MTYyOTYpIgpzdWJ0aXRsZTogQXNzaWdubWVudCAzCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKCgojIyBSZXF1aXJlZCBwYWNrYWdlcyAKUHJvdmlkZSB0aGUgcGFja2FnZXMgcmVxdWlyZWQgdG8gcmVwcm9kdWNlIHRoZSByZXBvcnQuIE1ha2Ugc3VyZSB5b3UgZnVsZmlsbGVkIHRoZSBtaW5pbXVtIHJlcXVpcmVtZW50ICMxMC4KCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShIbWlzYykKbGlicmFyeShwbHlyKQpsaWJyYXJ5KGZvcmVpZ24pCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGZvcmVjYXN0KQpgYGAKCgojIyBFeGVjdXRpdmUgU3VtbWFyeSAKCjEuVHdvIGRhdGFzZXRzIGNvbnNpc3Rpbmcgb2YgaW5mb3JtYXRpb24gYWJvdXQgYSBib2R5IHdlaWdodCBsaWZ0aW5nIGNvbXBldGl0aW9uIHdhcyB1cGxvYWRlZCBpbiBSIHRvIHBlcmZvcm0gZGV0YWlsZWQgZGF0YSBwcmVwcm9jZXNzaW5nIGZ1bmN0aW9ucy4KCjIuRGF0YXNldF8xIGNvbnNpc3Rpbmcgb2YgaW5mb3JtYXRpb24gb2Ygd2VpZ2h0IGxpZnRpbmcgY29tcGV0aXRpb24gYW5kIERhdGFzZXRfMiBjb25zaXN0aW5nIG9mIGV2ZW50IGluZm9ybWF0aW9uIG9mIHRoZSB3ZWlnaHRsaWZ0aW5nIGNvbXBldGl0aW9uIHdhcyBqb2luZWQgdG8gZm9ybSBhIGZpbmFsIGRldGFpbGVkIGRhdGFzZXQgd2l0aCBhbGwgdGhlIGluZm9ybWF0aW9uIGluIG9uZSB0YWJsZSBhbmQgd2FzIG5hbWVkIEZpbmFsX0RhdGFzZXQuCgozLkFzIG91ciBkYXRhIGRpZG4ndCBjb25mb3JtIHRvIHRoZSB0aWR5IGRhdGEgcHJpbmNpcGxlcywgbWFuaXB1bGF0aW9uIGFuZCBjaGFuZ2VzIHdlcmUgbWFkZSB0byB0aWR5IHRoZSBkYXRhc2V0LgoKNC5BIG5ldyB2YXJpYWJsZSBUb3RhbGxpZnRrZyB3YXMgZm9ybWVkIGJ5IG11dGF0aW5nIDMgdmFyaWFibGVzIG5hbWVseSBCZXN0U3F1YXRLZywgQmVzdEJlbmNoS2cgYW5kIEJlc3REZWFkbGlmdGtnIGZyb20gdGhlIEZpbmFsX0RhdGFzZXQuCgo1LlRoZSBkYXRhIHdhcyB0aGVuIHNjYW5uZWQgZm9yIG1pc3NpbmcgdmFsdWVzLCBpbmNvbnNpc3RhbmNlcyBhbmQgb2J2aW91cyBlcnJvcnMuIAoKNi5JdCB3YXMgZm91bmQgdGhhdCB0aGUgZGF0YSBjb25zaXN0ZWQgb2YgbGFyZ2UgbnVtYmVyIG9mIG1pc3NpbmcgdmFsdWVzIGluIHRoZSBkYXRhc2V0LlNvLGluIG9yZGVyIHRvIG92ZXJjb21lIHN1Y2ggYSBwcm9ibGVtIGFuZCB3ZSB3ZXJlIG1pc3NpbmcgdmFsdWVzIG9ubHkgICBpbiBudW1lcmljIHZhcmlhYmxlcywgd2UgZGVjaWRlZCB0byBpbXB1dGUgdGhlIG1lYW4gb2YgdGhlIHZhcmlhYmxlcyBpbiB0aGUgY2VsbHMgdGhhdCBjb250YWluZWQgbm8gdmFsdWVzLgoKNy5UbyB2aXN1YWxseSByZXByZXNlbnQgdGhlIG51bWVyaWMgdmFyaWFibGVzIGluIG91ciBkYXRhc2V0LCB3ZSB0aGVuIHBsb3R0ZWQgYSBib3hwbG90IGZvciBhbGwgdGhlIHZhcmlhYmxlcy4gCgo4Lk91dGxpZXJzIHdlcmUgc2VlbiB0aGUgdmlzdWFsIHJlcHJlc2VudGF0aW9uIGFuZCBoZW5jZSB0byBvdmVyY29tZSBzdWNoIHZhbHVlcyB3ZSBmaWx0ZXJlZCBvdXQgdGhlIG91dGxpZXJzLgoKOS5EYXRhIHRyYW5zZm9ybWF0aW9uIG9uIEJlc3QgQmVuY2ggKGtnKSB3YXMgZG9uZSB1c2luZyB0aGUgbG9nIGFuZCB0aGUgYm94Y294IHRyYW5zZm9ybWF0aW9uLiAgCgoxMC5Ib3dldmVyIHdlIGZlbHQgdGhhdCB0aGUgYm94Y294IHRyYW5zZm9ybWF0aW9uIHByb3ZpZGVkIGJldHRlciB2aXN1YWwgcmVwcmVzZW5hdGlvbiBpbiByZWR1Y2luZyBza2V3bmVzcyBhbmQgaW4gY29udmVydGluZyB0aGUgZGlzdHJpYnV0aW9uIGludG8gbm9ybWFsICAgIGRpc3RyaWJ1dGlvbi4KCgojIyBEYXRhIAoKMS5EYXRhc2V0cyB3ZXJlIGFjcXVpcmVkIGZyb20gdGhlIGZvbGxvd2luZyB3ZWJzaXRlImh0dHBzOi8vd3d3LmthZ2dsZS5jb20vb3Blbi1wb3dlcmxpZnRpbmcvcG93ZXJsaWZ0aW5nLWRhdGFiYXNlIiBpbiB4bHN4IGZvcm1hdC4KCjIuRGF0YXNldCAxIHN0b3JlZCBhcyBwb3dlcmxpZnRpbmcueGxzeCBpbiB0aGUgd29ya2luZyBkaXJlY3RvcnkgY29uc2lzdGVkIGluZm9ybWF0aW9uIG9mIGRpZmZlcmVudCBwb3dlcmxpZnRpbmcgcmVzdWx0cy5BdCB0b3RhbCBpdCBjb25zaXN0ZWQgb2YgMTExNyBvYnNlcnZhdGlvbnMgYW5kIDExIHZhcmlhYmxlcy4gVGhlIGVsZXZlbiB2YXJpYWJsZXMgbGlzdGVkIHdlcmUgTWVldElkLE5hbWUsU2V4LEVxdWlwbWVudCxBZ2UsQm9keXdlaWdodChrZyksV2VpZ2h0Y2xhc3Moa2cpLEJlc3QgU3F1YXQoa2cpLCBCZXN0QmVuY2goa2cpIGFuZCBXaWxrcy4KCjMuRGF0YXNldCAyIG9uIHRoZSBvdGhlci1oYW5kIHdhcyBzdG9yZWQgYXMgbWVldHMueGxzeCwgY29uc2lzdGluZyBvZiBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVldHMgb2YgdGhlIGRpZmZlcmVudCBwb3dlcmxpZnRpbmcgY29tcGV0aXRpb25zLiBBdCB0b3RhbCBpdCBjb25zaXN0ZWQgb2YgMjEgb2JzZXJ2YXRpb25zIGFuZCAgOCB2YXJpYWJsZXMuIFRoZSB2YXJpYWJsZXMgaW5jbHVkZWQgTWVldElELCBGZWRlcmF0aW9uLE1lZXRDb3VudHJ5LE1lZXRTdGF0ZSxNZWV0VG93bixNZWV0TmFtZSBhbmQgZGF0ZS4KCjQuQm90aCBkYXRhc2V0IHdlcmUgaW1wb3J0ZWQgaW50byBSIHVzaW5nIHRoZSByZWFkX2V4Y2VsIGZ1bmN0aW9uIGZyb20gdGhlIGxpYnJhcnkocmVhZHhsKS4KCgpgYGB7cn0KRGF0YVNldDE8LXJlYWRfZXhjZWwoInBvd2VybGlmdGluZy54bHN4IikgCmhlYWQoRGF0YVNldDEpCkRhdGFTZXQyPC1yZWFkX2V4Y2VsKCJtZWV0cy54bHN4IikKaGVhZChEYXRhU2V0MikKCgoKYGBgCgojIyBVbmRlcnN0YW5kIAoKMS4gVGhlIHR3byBkYXRhc2V0IHdhcyB0aGVuIGpvaW5lZCBpbnRvIGEgc2luZ2xlIGRhdGFzZXQgdXNpbmcgdGhlIGZ1bGwgam9pbiBmdW5jdGlvbiBvbiB0aGUgdmFyaWFibGUgTWVldElkIGFuZCB3YXMgYXNzaWduZWQgYXMgRmluYWxfRGF0YXNldC4KMi4gU3RyIGZ1bmN0aW9uIHdhcyBpbXBsZW1lbnRlZCBvbiB0aGUgZGF0YXNldCB0byBnZXQgYSBsaXN0ZWQgcmVwcmVzZW50YXRpb24gb2YgYWxsIHRoZSBkYXRhdHlwZXMgYW5kIHRoZSBzdHVydWN0dXJlLCBwdXQgdG9nZXRoZXIgZm9yIGNvbnZpbmVuY2UuCgoKYGBge3J9CkZpbmFsX0RhdGFzZXQ8LURhdGFTZXQxICU+JSBmdWxsX2pvaW4oRGF0YVNldDIpCnN0cihGaW5hbF9EYXRhc2V0KQpoZWFkKEZpbmFsX0RhdGFzZXQpCgoKYGBgCgoKIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJIAoKMS4gVW5mb3J0dW5hdGVseSBvdXIgZGF0YSB3YXMgbm90IHRpZHksIHNvIGNlcnRhaW4gdGlkeWluZyAgYW5kIG1hbmlwdWxhdGlvbiB3YXMgZG9uZS4KMi4gV2UgZmlyc3RseSBzZXBlcmF0ZWQgdGhlIHZhbHVlcyBpbiBNZWV0UGF0aCBpbnRvIHR3byBkaWZmZXJlbnQgY29sdW1ucyBpLmUsIGZlZGVyYXRpb24gYW5kIHBhdGguCjMuIFRoZW4gZmFjdG9yaXplZCBzZXggYW5kICBnYXZlIGEgYmV0dGVyIGxhYmVsbGluZy4KNC4gRXF1aXBtZW50IGNvbHVtbiAgYW5kIG1lZXQgSUQgd2FzIGFsc28gZmFjdG9yaXplZCBzbyB0aGF0IGFuYWx5emluZyBjYW4gYmUgZWFzaWVyIGluIHRoZSBuZXh0IHN0ZXAgb2YgZGF0YSBhbmFseXNpcy4KNS4gV2VpZ2h0IENsYXNzIGNhdGVnb3J5IHdhcyBmYWN0b3JpemVkIGZyb20gY2hhcmFjdGVyIGRhdGF0eXBlICBpbnRvICBjYXRlZ29yaWNhbCBvcmRpbmFsIGRhdGEuIEEgYmV0dGVyIGxhYmVsbGluZyB3YXMgYWxzbyBkb25lIGZvciBXZWlnaHRDbGFzc0tnLgo2LiBGaW5hbGx5IHRoZSBhcy5EYXRlIGZ1bmN0aW9uIHdhcyB1c2VkIHRvIGNvbnZlcnQgZGF0ZSB0byBkYXRlIGZvcm1hdC4KCgpgYGB7cn0KRmluYWxfRGF0YXNldCA8LSBGaW5hbF9EYXRhc2V0ICU+JSBzZXBhcmF0ZShNZWV0UGF0aCwgaW50bz1jKCJGZWRlcmF0aW9uIiwgIlBhdGgiKSwgc2VwPSIvIikKRmluYWxfRGF0YXNldCRTZXg8LSBGaW5hbF9EYXRhc2V0JFNleCAlPiUgZmFjdG9yKGxldmVscyA9IGMoIk0iLCJGIiksbGFiZWxzID0gYygiTWFsZSIsIkZlbWFsZSIpKQpGaW5hbF9EYXRhc2V0JEVxdWlwbWVudDwtRmluYWxfRGF0YXNldCRFcXVpcG1lbnQgJT4lIGZhY3RvcihsZXZlbHMgPWMoIlJhdyIsIldyYXBzIiwiTXVsdGktcGx5IiwiU2luZ2xlLXBseSIpKQpGaW5hbF9EYXRhc2V0JFdlaWdodENsYXNzS2c8LUZpbmFsX0RhdGFzZXQkV2VpZ2h0Q2xhc3NLZyAlPiUgZmFjdG9yKGxldmVscyA9YygiMTQwKyIsIjE0MCIsIjEyNSIsIjExMCIsIjEwMCIsIjkwIiwiODIuNSIsIjc1IiwiNjcuNSIsIjYwIiwiNTYiLCI1MiIsIjQ4IiwiNDQiLCI0MiIsIjQwIiksIG9yZGVyZWQgPSBUUlVFKQpGaW5hbF9EYXRhc2V0JE1lZXRJRDwtYXMuZmFjdG9yKEZpbmFsX0RhdGFzZXQkTWVldElEKSAKRmluYWxfRGF0YXNldDwtcmVuYW1lKEZpbmFsX0RhdGFzZXQsYygiV2VpZ2h0Q2xhc3NLZyI9IldlaWdodCBDYXRlZ29yeSAoS2cpIikpCiNkYXRlIGZvcm1hdGluZwpGaW5hbF9EYXRhc2V0JERhdGUgPC0gYXMuRGF0ZShGaW5hbF9EYXRhc2V0JERhdGUsICIlZC8lbS8lWSIpCmhlYWQoRmluYWxfRGF0YXNldCkKCmBgYAoKIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJSSAKCjEuIEEgbmV3IHZhcmlhYmxlIHdhcyBjcmVhdGVkIGNhbGxlZCBUb3RhbExpZnRLZyB3aGljaCBpbmNsdWRlZCB0aGUgYWRkaXRpb24gb2YgdGhlIEJlc3RTcXVhdCwgQmVzdEJlbmNoS2cgYW5kIEJlc3REZWFkTGlmdEtnLCBob3dldmVyIGJlZm9yZSBtdXRhdGluZyB0aGUgdmFyaWFibGUgZnJvbSBleGlzdGluZyB2YXJpYWJsZSwgd2UgcmVwbGFjZWQgYWxsIHRoZSBOYSB2YXJpYWJsZXMgaW4gdGhlIHRocmVlIGNvbHVtbnMgdG8gemVybyBzbyB0aGF0IE5hIHZhbHVlcyBhcmUgbmVnbGVjdGVkIGluIHRoZSBuZXcgdmFyaWFibGUuCgpgYGB7cn0KRmluYWxfRGF0YXNldCAlPiUgcmVwbGFjZV9uYShsaXN0KEJlc3RTcXVhdEtnPTAsIEJlc3RCZW5jaEtnPTAsIEJlc3REZWFkbGlmdEtnID0gMCkpICU+JSBtdXRhdGUgKEZpbmFsX0RhdGFzZXQsIFRvdGFsTGlmdEtnID0gQmVzdFNxdWF0S2cgKyBCZXN0QmVuY2hLZyArIEJlc3REZWFkbGlmdEtnKQoKCmBgYAoKCiMjCVNjYW4gSSAKCjEuIE1pc3NpbmcgdmFsdWVzLCBpbmNvc2lzdGVuY2VzIGFuZCBvYnZpb3VzIGVycm9ycyB3YXMgY2hlY2tlZCBpbiB0aGlzIHNlY3Rpb24uCjIuIE1pc3NpbmcgdmFsdWVzIHdlcmUgZm91bmQgaW4gdmFyaW91cyB2YXJpYWJsZXMgc3VjaCBhcyBhZ2UsIEJvZHl3ZWlnaHRLZywgQmVzdFNxdWF0S2csQmVzdEJlbmNoS2csIGFuZCBXaWxrcy4KMy4gVGhlIG1ldGhvZCBvZiBtZWFuIGltcHV0YXRpb24gd2VyZSB1c2VkIHRvIGhhbmRsZSB0aGUgbWlzc2luZyB2YWx1ZXMgaW4gYWxsIHRoZSB2YXJpYWJsZXMgYXMgYWxsIHRoZSB2YXJpYWJsZXMgd2VyZSBudW1lcmljLgo0LiBUaGUgY29sU3VtIChpcy5uYShGaW5hbF9EYXRhc2V0KSkgZnVuY3Rpb24gd2VyZSB1c2VkIGZvciByZWZyZW5jZSBvZiB0aGUgbWlzc2luZyB2YWx1ZXMuCgoKYGBge3J9Cgpjb2xTdW1zKGlzLm5hKEZpbmFsX0RhdGFzZXQpKSAKRmluYWxfRGF0YXNldCRCb2R5d2VpZ2h0S2c8LWltcHV0ZShGaW5hbF9EYXRhc2V0JEJvZHl3ZWlnaHRLZyxmdW4gPSBtZWFuKQpGaW5hbF9EYXRhc2V0JEFnZSA8LWltcHV0ZShGaW5hbF9EYXRhc2V0JEFnZSwgZnVuID0gbWVhbikKRmluYWxfRGF0YXNldCRCZXN0U3F1YXRLZzwtaW1wdXRlKEZpbmFsX0RhdGFzZXQkQmVzdFNxdWF0S2csIGZ1biA9IG1lYW4pCkZpbmFsX0RhdGFzZXQkQmVzdEJlbmNoS2c8LWltcHV0ZShGaW5hbF9EYXRhc2V0JEJlc3RCZW5jaEtnLCBmdW4gPSBtZWFuKQpGaW5hbF9EYXRhc2V0JEJlc3REZWFkbGlmdEtnPC1pbXB1dGUoRmluYWxfRGF0YXNldCRCZXN0RGVhZGxpZnRLZywgZnVuID0gbWVhbikKRmluYWxfRGF0YXNldCRXaWxrczwtaW1wdXRlKEZpbmFsX0RhdGFzZXQkV2lsa3MsIGZ1biA9IG1lYW4pCmNvbFN1bXMoaXMubmEoRmluYWxfRGF0YXNldCkpCmhlYWQoRmluYWxfRGF0YXNldCkKCmBgYAoKCiMjCVNjYW4gSUkKMS4gQSBzdW1hYXJ5IG9mIHRoZSBEYXRhc2V0IHdhcyBmaXJzdCBwcmVzZW50ZWQgZm9yIHJlZnJlbmNlLgoyLiBBcyBhZnRlciBpbXB1dGF0aW9uIHRoZSBkYXRhdHlwZSByZW1haW5lZCBhcyBpbXB1dGUsIHdlIGNvbnZlcnRlZCB0aGUgdmFyaWFibGVzIHRvIG51bWVyaWMgZGF0YXR5cGUgdXNpbmcgdGhlIGZ1bmN0aW9uIGFzLm51bWVyaWMsIHNvIGFzIHRvIHBsb3QgdGhlIGJveHBsb3QuCjMuIEJveHBsb3Qgd2VyZSBkcmF3biBmb3IgYWxsIHRoZSBudW1lcmljIHZhcmlhYmxlcyBhbmQgdGhlIGV4aXN0aW5nIG91dGxpZXJzIHdlcmUgaGFuZGxlZC4KNC4gSWYgIHByZXNlbnQgYWJvdmUgdGhlIHVwcGVyIGZlbmNlLCB0aGUgb3V0bGllcnMgd2VyZSBoYW5kbGVkIGJ5IGZpbHRlcmluZyBkYXRhIHVzaW5nIHRoZSBmb3JtdWxhIGZpbHRlcigxLjUqSVFSK1EzKSBhbmQgaWYgcHJlc2VudCBiZWxvdyB0aGUgbG93ZXIgZmVuY2UsIHRoZSBmb3JtdWxhIGZpbHRlcihRMS0xLjVJUVIpLgo1LiBCb3ggcGxvdCBhZnRlciByZW1vdmluZyB0aGUgb3V0bGllcnMgd2VyZSBhbHNvIHByZXNlbnRlZC4gCjYuIEluIHRoZSBib3hwbG90IHByZXNlbnRlZCBiZWxvdywgdGhlIHdpbGtzIGJveHBsb3QgaGFkIG5vIG91dGxpZXJzIHByZXNlbnQuCjcuIEluIHRoZSBjYXNlIG9mIGJvZHl3ZWlnaHRrZywgYmVzdCBkZWFkIGxpZnQgYW5kIGJlc3QgYmVuY2ggcHJlc3MgOiBvdXRsaWVycyB3ZXJlIHByZXNlbnRlZCBhbmQgcmVtb3ZlZC4KOC4gSG93ZXZlciBpbiB0aGUgY2FzZSBvZiBCZXN0IFNxdWF0KGtnKSwgb3V0bGllcnMgd2VyZSBwcmVzZW50IGV2ZW4gYWZ0ZXIgZmlsdGVyaW5nIHRoZSBvdXRsaWVycyBwcmVzZW50LCBhYm92ZSBhbmQgYmVsb3cgdGhlIHVwcGVyIGFuZCBsb3dlciBmZW5jZS4KCmBgYHtyfQpzdW1tYXJ5KEZpbmFsX0RhdGFzZXQpCnN0cihGaW5hbF9EYXRhc2V0KQpGaW5hbF9EYXRhc2V0JFdpbGtzID0gYXMubnVtZXJpYyhGaW5hbF9EYXRhc2V0JFdpbGtzKQpib3hwbG90KEZpbmFsX0RhdGFzZXQkV2lsa3MsIG1haW49IlN0cmVuZ3RoIG9mIFBvd2VyIExpZnRlcnMiLCB5bGFiID0gIldpbGtzIiwgY29sID0gImdyZXkiKQpGaW5hbF9EYXRhc2V0JEJvZHl3ZWlnaHRLZyA9IGFzLm51bWVyaWMoRmluYWxfRGF0YXNldCRCb2R5d2VpZ2h0S2cpCmJveHBsb3QoRmluYWxfRGF0YXNldCRCb2R5d2VpZ2h0S2csIG1haW49IkJvZHkgV2VpZ2h0IGluIGtnIiwgeWxhYiA9ICJXZWlnaHQoa2cpIixjb2wgPSAicmVkIikKeDwtSVFSKEZpbmFsX0RhdGFzZXQkQm9keXdlaWdodEtnLG5hLnJtID0gVFJVRSkKc3VtbWFyeShGaW5hbF9EYXRhc2V0JEJvZHl3ZWlnaHRLZykKYzwtMS41KngrMTA2Ljg3Cno8LUZpbmFsX0RhdGFzZXQlPiUgZmlsdGVyKEJvZHl3ZWlnaHRLZzwxNTYuODk1KSAKYm94cGxvdCh6JEJvZHl3ZWlnaHRLZywgbWFpbj0iQm9keSBXZWlnaHQgaW4ga2cgQWZ0ZXIgUmVtb3ZpbmcgT3V0bGllcnMiLCB5bGFiPSJ3ZWlnaHQoa2cpIiwgY29sID0gInJlZCIpCkZpbmFsX0RhdGFzZXQkQmVzdFNxdWF0S2c9IGFzLm51bWVyaWMoRmluYWxfRGF0YXNldCRCZXN0U3F1YXRLZykKYm94cGxvdChGaW5hbF9EYXRhc2V0JEJlc3RTcXVhdEtnLCBtYWluID0gIiBCb3ggUGxvdCBvZiBCZXN0IFNxdWF0ICIsIGNvbD0iYmx1ZSIsIHlsYWI9IndlaWdodChrZykiKQpZPC1JUVIoRmluYWxfRGF0YXNldCRCZXN0U3F1YXRLZykKc3VtbWFyeShGaW5hbF9EYXRhc2V0JEJlc3RTcXVhdEtnKQpEPC0xLjUqWSsyMDUuMApSPC0xNTUtMS41KlkKUjM8LUZpbmFsX0RhdGFzZXQgJT4lIGZpbHRlcigoODAuMDxCZXN0U3F1YXRLZykgJiAoQmVzdFNxdWF0S2c8MjgwKSkKYm94cGxvdChSMyRCZXN0U3F1YXRLZywgbWFpbiA9ICIgQm94IFBsb3Qgb2YgQmVzdCBTcXVhdCAgQWZ0ZXIgUmVtb3ZpbmcgT3V0bGllciAiLCBjb2w9ImJsdWUiLHlsYWI9IndlaWdodChrZykiKQpGaW5hbF9EYXRhc2V0JEJlc3RCZW5jaEtnPSBhcy5udW1lcmljKEZpbmFsX0RhdGFzZXQkQmVzdEJlbmNoS2cpCmJveHBsb3QoRmluYWxfRGF0YXNldCRCZXN0QmVuY2hLZywgbWFpbiA9ICIgQm94IFBsb3Qgb2YgQmVzdCBCZW5jaCAiLCBjb2w9ImdyZWVuIix5bGFiPSJ3ZWlnaHQoa2cpIix5bGFiPSJ3ZWlnaHQoa2cpIikKc3VtbWFyeShGaW5hbF9EYXRhc2V0JEJlc3RCZW5jaEtnKQpRPC1JUVIoRmluYWxfRGF0YXNldCRCZXN0QmVuY2hLZykKSDwtMS41KlErMTYwClQ8LSBGaW5hbF9EYXRhc2V0ICU+JSBmaWx0ZXIoQmVzdEJlbmNoS2c8MjYxLjI1KQpib3hwbG90KFQkQmVzdEJlbmNoS2csIG1haW4gPSAiIEJveCBQbG90IG9mIEJlc3QgQmVuY2ggQWZ0ZXIgUmVtb3ZpbmcgT3V0bGllciAiLCBjb2w9ImdyZWVuIix5bGFiPSJ3ZWlnaHQoa2cpIikKRmluYWxfRGF0YXNldCRCZXN0RGVhZGxpZnRLZzwtYXMubnVtZXJpYyhGaW5hbF9EYXRhc2V0JEJlc3REZWFkbGlmdEtnKQpib3hwbG90KEZpbmFsX0RhdGFzZXQkQmVzdERlYWRsaWZ0S2csIG1haW4gPSAiIEJveCBQbG90IG9mIEJlc3QgRGVhZCBMaWZ0ICIsIGNvbD0ib3JhbmdlIix5bGFiPSJ3ZWlnaHQoa2cpIikKc3VtbWFyeShGaW5hbF9EYXRhc2V0JEJlc3REZWFkbGlmdEtnKQpXPC1JUVIoRmluYWxfRGF0YXNldCRCZXN0RGVhZGxpZnRLZykKSzwtMS41KlcrMjM4LjEKUjwtRmluYWxfRGF0YXNldCAlPiUgZmlsdGVyKEJlc3REZWFkbGlmdEtnPDM3MC4zMSkKYm94cGxvdChSJEJlc3REZWFkbGlmdEtnLCBtYWluID0gIkJveCBQbG90IG9mIEJlc3QgRGVhZCBMaWZ0IEFmdGVyIFJlbW92aW5nIE91dGxpZXIiLCBjb2w9Im9yYW5nZSIseWxhYj0id2VpZ2h0KGtnKSIpCmBgYAoKCiMjCVRyYW5zZm9ybSAKMS5EYXRhIHRyYW5zZm9ybWF0aW9uIG9uIEJlc3QgQmVuY2ggKGtnKSB3YXMgZG9uZSB1c2luZyB0aGUgbG9nIGFuZCB0aGUgYm94Y294IHRyYW5zZm9ybWF0aW9uLiAgCjIuSG93ZXZlciAgaXQgd2FzIGZvdW5kIHRoYXQgdGhlIHRyYW5zZm9ybWF0aW9uIHdpdGggYm94Y294IHRyYW5zZm9ybWF0aW9uIHByb3ZpZGVkIGJldHRlciB2aXN1YWwgcmVwcmVzZW5hdGlvbiBpbiByZWR1Y2luZyBza2V3bmVzcyBhbmQgY29udmVydGluZyAgdGhlIGRpc3RyaWJ1dGlvbiBpbnRvIG5vcm1hbCBkaXN0cmlidXRpb24uCgpgYGB7cn0KaGlzdChGaW5hbF9EYXRhc2V0JEJlc3RCZW5jaEtnLGNvbCA9ICJncmV5IikKaGlzdChsb2coRmluYWxfRGF0YXNldCRCZXN0QmVuY2hLZyksIG1haW4gPSAiTG9nIFRyYW5zZm9ybWF0aW9uIHRvIEJlc3RCZW5jaEtnIixjb2wgPSAiZ3JleSIpCmJveGNveDwtQm94Q294KEZpbmFsX0RhdGFzZXQkQmVzdEJlbmNoS2csIGxhbWJkYSA9ICJhdXRvIikKaGlzdChib3hjb3gsIG1haW4gPSAiQm94Y294IFRyYW5zZm9ybWF0aW9uIHRvIEJlc3RCZW5jaGtnIixjb2wgPSAiZ3JleSIpCgoKYGBgCgoKCgoKPGJyPgo8YnI+Cg==