Instructions


Review criteria

  • The submitted data set is tidy.
  • The Github repo contains the required scripts.
  • GitHub contains a code book that modifies and updates the available codebooks with the data to indicate all the variables and summaries calculated, along with units, and any other relevant information.
  • The README that explains the analysis files is clear and understandable.
  • The work submitted for this project is the work of the student who submitted it.


Getting and Cleaning Data Course Project

The purpose of this project is to demonstrate your ability to collect, work with, and clean a data set. The goal is to prepare tidy data that can be used for later analysis. You will be graded by your peers on a series of yes/no questions related to the project.

You will be required to submit:

  1. A tidy data set as described below,
  2. A link to a Github repository with your script for performing the analysis,
  3. A code book that describes the variables, the data, and any transformations or work that you performed to clean up the data called CodeBook.md. You should also include a README.md in the repo with your scripts. This repo explains how all of the scripts work and how they are connected.


Dataset

One of the most exciting areas in all of data science right now is wearable computing - see for example this article . Companies like Fitbit, Nike, and Jawbone Up are racing to develop the most advanced algorithms to attract new users. The data linked to from the course website represent data collected from the accelerometers from the Samsung Galaxy S smartphone. A full description is available at the site where the data was obtained:

http://archive.ics.uci.edu/ml/datasets/Human+Activity+Recognition+Using+Smartphones

Here are the data for the project:

https://d396qusza40orc.cloudfront.net/getdata%2Fprojectfiles%2FUCI%20HAR%20Dataset.zip

You should create one R script called run_analysis.R that does the following.

  1. Merges the training and the test sets to create one data set.
  2. Extracts only the measurements on the mean and standard deviation for each measurement.
  3. Uses descriptive activity names to name the activities in the data set
  4. Appropriately labels the data set with descriptive variable names.
  5. From the data set in step 4, creates a second, independent tidy data set with the average of each variable for each activity and each subject.

Good luck!




Here we go!


Preparation Stage


Loading required packages

library(dplyr)


Download the dataset

filename <- "Coursera_DS3_Final.zip"

# Checking if archieve already exists.
if (!file.exists(filename)){
  fileURL <- "https://d396qusza40orc.cloudfront.net/getdata%2Fprojectfiles%2FUCI%20HAR%20Dataset.zip"
  download.file(fileURL, filename, method="curl")
}  

# Checking if folder exists
if (!file.exists("UCI HAR Dataset")) { 
  unzip(filename) 
}


Assigning all data frames

features <- read.table("UCI HAR Dataset/features.txt", col.names = c("n","functions"))
activities <- read.table("UCI HAR Dataset/activity_labels.txt", col.names = c("code", "activity"))
subject_test <- read.table("UCI HAR Dataset/test/subject_test.txt", col.names = "subject")
x_test <- read.table("UCI HAR Dataset/test/X_test.txt", col.names = features$functions)
y_test <- read.table("UCI HAR Dataset/test/y_test.txt", col.names = "code")
subject_train <- read.table("UCI HAR Dataset/train/subject_train.txt", col.names = "subject")
x_train <- read.table("UCI HAR Dataset/train/X_train.txt", col.names = features$functions)
y_train <- read.table("UCI HAR Dataset/train/y_train.txt", col.names = "code")


The “Go for it!” Stage

“You should create one R script called run_analysis.R that does the following:”


Step 1: Merges the training and the test sets to create one data set.

X <- rbind(x_train, x_test)
Y <- rbind(y_train, y_test)
Subject <- rbind(subject_train, subject_test)
Merged_Data <- cbind(Subject, Y, X)


Step 2: Extracts only the measurements on the mean and standard deviation for each measurement.

TidyData <- Merged_Data %>% select(subject, code, contains("mean"), contains("std"))


Step 3: Uses descriptive activity names to name the activities in the data set.

TidyData$code <- activities[TidyData$code, 2]


Step 4: Appropriately labels the data set with descriptive variable names.

names(TidyData)[2] = "activity"
names(TidyData)<-gsub("Acc", "Accelerometer", names(TidyData))
names(TidyData)<-gsub("Gyro", "Gyroscope", names(TidyData))
names(TidyData)<-gsub("BodyBody", "Body", names(TidyData))
names(TidyData)<-gsub("Mag", "Magnitude", names(TidyData))
names(TidyData)<-gsub("^t", "Time", names(TidyData))
names(TidyData)<-gsub("^f", "Frequency", names(TidyData))
names(TidyData)<-gsub("tBody", "TimeBody", names(TidyData))
names(TidyData)<-gsub("-mean()", "Mean", names(TidyData), ignore.case = TRUE)
names(TidyData)<-gsub("-std()", "STD", names(TidyData), ignore.case = TRUE)
names(TidyData)<-gsub("-freq()", "Frequency", names(TidyData), ignore.case = TRUE)
names(TidyData)<-gsub("angle", "Angle", names(TidyData))
names(TidyData)<-gsub("gravity", "Gravity", names(TidyData))


Step 5: From the data set in step 4, creates a second, independent tidy data set with the average of each variable for each activity and each subject.

FinalData <- TidyData %>%
    group_by(subject, activity) %>%
    summarise_all(funs(mean))
write.table(FinalData, "FinalData.txt", row.name=FALSE)


Final Check Stage


Checking variable names

str(FinalData)
Classes ‘grouped_df’, ‘tbl_df’, ‘tbl’ and 'data.frame': 180 obs. of  88 variables:
 $ subject                                           : int  1 1 1 1 1 1 2 2 2 2 ...
 $ activity                                          : Factor w/ 6 levels "LAYING","SITTING",..: 1 2 3 4 5 6 1 2 3 4 ...
 $ TimeBodyAccelerometer.mean...X                    : num  0.222 0.261 0.279 0.277 0.289 ...
 $ TimeBodyAccelerometer.mean...Y                    : num  -0.04051 -0.00131 -0.01614 -0.01738 -0.00992 ...
 $ TimeBodyAccelerometer.mean...Z                    : num  -0.113 -0.105 -0.111 -0.111 -0.108 ...
 $ TimeGravityAccelerometer.mean...X                 : num  -0.249 0.832 0.943 0.935 0.932 ...
 $ TimeGravityAccelerometer.mean...Y                 : num  0.706 0.204 -0.273 -0.282 -0.267 ...
 $ TimeGravityAccelerometer.mean...Z                 : num  0.4458 0.332 0.0135 -0.0681 -0.0621 ...
 $ TimeBodyAccelerometerJerk.mean...X                : num  0.0811 0.0775 0.0754 0.074 0.0542 ...
 $ TimeBodyAccelerometerJerk.mean...Y                : num  0.003838 -0.000619 0.007976 0.028272 0.02965 ...
 $ TimeBodyAccelerometerJerk.mean...Z                : num  0.01083 -0.00337 -0.00369 -0.00417 -0.01097 ...
 $ TimeBodyGyroscope.mean...X                        : num  -0.0166 -0.0454 -0.024 -0.0418 -0.0351 ...
 $ TimeBodyGyroscope.mean...Y                        : num  -0.0645 -0.0919 -0.0594 -0.0695 -0.0909 ...
 $ TimeBodyGyroscope.mean...Z                        : num  0.1487 0.0629 0.0748 0.0849 0.0901 ...
 $ TimeBodyGyroscopeJerk.mean...X                    : num  -0.1073 -0.0937 -0.0996 -0.09 -0.074 ...
 $ TimeBodyGyroscopeJerk.mean...Y                    : num  -0.0415 -0.0402 -0.0441 -0.0398 -0.044 ...
 $ TimeBodyGyroscopeJerk.mean...Z                    : num  -0.0741 -0.0467 -0.049 -0.0461 -0.027 ...
 $ TimeBodyAccelerometerMagnitude.mean..             : num  -0.8419 -0.9485 -0.9843 -0.137 0.0272 ...
 $ TimeGravityAccelerometerMagnitude.mean..          : num  -0.8419 -0.9485 -0.9843 -0.137 0.0272 ...
 $ TimeBodyAccelerometerJerkMagnitude.mean..         : num  -0.9544 -0.9874 -0.9924 -0.1414 -0.0894 ...
 $ TimeBodyGyroscopeMagnitude.mean..                 : num  -0.8748 -0.9309 -0.9765 -0.161 -0.0757 ...
 $ TimeBodyGyroscopeJerkMagnitude.mean..             : num  -0.963 -0.992 -0.995 -0.299 -0.295 ...
 $ FrequencyBodyAccelerometer.mean...X               : num  -0.9391 -0.9796 -0.9952 -0.2028 0.0382 ...
 $ FrequencyBodyAccelerometer.mean...Y               : num  -0.86707 -0.94408 -0.97707 0.08971 0.00155 ...
 $ FrequencyBodyAccelerometer.mean...Z               : num  -0.883 -0.959 -0.985 -0.332 -0.226 ...
 $ FrequencyBodyAccelerometer.meanFreq...X           : num  -0.1588 -0.0495 0.0865 -0.2075 -0.3074 ...
 $ FrequencyBodyAccelerometer.meanFreq...Y           : num  0.0975 0.0759 0.1175 0.1131 0.0632 ...
 $ FrequencyBodyAccelerometer.meanFreq...Z           : num  0.0894 0.2388 0.2449 0.0497 0.2943 ...
 $ FrequencyBodyAccelerometerJerk.mean...X           : num  -0.9571 -0.9866 -0.9946 -0.1705 -0.0277 ...
 $ FrequencyBodyAccelerometerJerk.mean...Y           : num  -0.9225 -0.9816 -0.9854 -0.0352 -0.1287 ...
 $ FrequencyBodyAccelerometerJerk.mean...Z           : num  -0.948 -0.986 -0.991 -0.469 -0.288 ...
 $ FrequencyBodyAccelerometerJerk.meanFreq...X       : num  0.132 0.257 0.314 -0.209 -0.253 ...
 $ FrequencyBodyAccelerometerJerk.meanFreq...Y       : num  0.0245 0.0475 0.0392 -0.3862 -0.3376 ...
 $ FrequencyBodyAccelerometerJerk.meanFreq...Z       : num  0.02439 0.09239 0.13858 -0.18553 0.00937 ...
 $ FrequencyBodyGyroscope.mean...X                   : num  -0.85 -0.976 -0.986 -0.339 -0.352 ...
 $ FrequencyBodyGyroscope.mean...Y                   : num  -0.9522 -0.9758 -0.989 -0.1031 -0.0557 ...
 $ FrequencyBodyGyroscope.mean...Z                   : num  -0.9093 -0.9513 -0.9808 -0.2559 -0.0319 ...
 $ FrequencyBodyGyroscope.meanFreq...X               : num  -0.00355 0.18915 -0.12029 0.01478 -0.10045 ...
 $ FrequencyBodyGyroscope.meanFreq...Y               : num  -0.0915 0.0631 -0.0447 -0.0658 0.0826 ...
 $ FrequencyBodyGyroscope.meanFreq...Z               : num  0.010458 -0.029784 0.100608 0.000773 -0.075676 ...
 $ FrequencyBodyAccelerometerMagnitude.mean..        : num  -0.8618 -0.9478 -0.9854 -0.1286 0.0966 ...
 $ FrequencyBodyAccelerometerMagnitude.meanFreq..    : num  0.0864 0.2367 0.2846 0.1906 0.1192 ...
 $ FrequencyBodyAccelerometerJerkMagnitude.mean..    : num  -0.9333 -0.9853 -0.9925 -0.0571 0.0262 ...
 $ FrequencyBodyAccelerometerJerkMagnitude.meanFreq..: num  0.2664 0.3519 0.4222 0.0938 0.0765 ...
 $ FrequencyBodyGyroscopeMagnitude.mean..            : num  -0.862 -0.958 -0.985 -0.199 -0.186 ...
 $ FrequencyBodyGyroscopeMagnitude.meanFreq..        : num  -0.139775 -0.000262 -0.028606 0.268844 0.349614 ...
 $ FrequencyBodyGyroscopeJerkMagnitude.mean..        : num  -0.942 -0.99 -0.995 -0.319 -0.282 ...
 $ FrequencyBodyGyroscopeJerkMagnitude.meanFreq..    : num  0.176 0.185 0.334 0.191 0.19 ...
 $ Angle.TimeBodyAccelerometerMean.Gravity.          : num  0.021366 0.027442 -0.000222 0.060454 -0.002695 ...
 $ Angle.TimeBodyAccelerometerJerkMean..GravityMean. : num  0.00306 0.02971 0.02196 -0.00793 0.08993 ...
 $ Angle.TimeBodyGyroscopeMean.GravityMean.          : num  -0.00167 0.0677 -0.03379 0.01306 0.06334 ...
 $ Angle.TimeBodyGyroscopeJerkMean.GravityMean.      : num  0.0844 -0.0649 -0.0279 -0.0187 -0.04 ...
 $ Angle.X.GravityMean.                              : num  0.427 -0.591 -0.743 -0.729 -0.744 ...
 $ Angle.Y.GravityMean.                              : num  -0.5203 -0.0605 0.2702 0.277 0.2672 ...
 $ Angle.Z.GravityMean.                              : num  -0.3524 -0.218 0.0123 0.0689 0.065 ...
 $ TimeBodyAccelerometer.std...X                     : num  -0.928 -0.977 -0.996 -0.284 0.03 ...
 $ TimeBodyAccelerometer.std...Y                     : num  -0.8368 -0.9226 -0.9732 0.1145 -0.0319 ...
 $ TimeBodyAccelerometer.std...Z                     : num  -0.826 -0.94 -0.98 -0.26 -0.23 ...
 $ TimeGravityAccelerometer.std...X                  : num  -0.897 -0.968 -0.994 -0.977 -0.951 ...
 $ TimeGravityAccelerometer.std...Y                  : num  -0.908 -0.936 -0.981 -0.971 -0.937 ...
 $ TimeGravityAccelerometer.std...Z                  : num  -0.852 -0.949 -0.976 -0.948 -0.896 ...
 $ TimeBodyAccelerometerJerk.std...X                 : num  -0.9585 -0.9864 -0.9946 -0.1136 -0.0123 ...
 $ TimeBodyAccelerometerJerk.std...Y                 : num  -0.924 -0.981 -0.986 0.067 -0.102 ...
 $ TimeBodyAccelerometerJerk.std...Z                 : num  -0.955 -0.988 -0.992 -0.503 -0.346 ...
 $ TimeBodyGyroscope.std...X                         : num  -0.874 -0.977 -0.987 -0.474 -0.458 ...
 $ TimeBodyGyroscope.std...Y                         : num  -0.9511 -0.9665 -0.9877 -0.0546 -0.1263 ...
 $ TimeBodyGyroscope.std...Z                         : num  -0.908 -0.941 -0.981 -0.344 -0.125 ...
 $ TimeBodyGyroscopeJerk.std...X                     : num  -0.919 -0.992 -0.993 -0.207 -0.487 ...
 $ TimeBodyGyroscopeJerk.std...Y                     : num  -0.968 -0.99 -0.995 -0.304 -0.239 ...
 $ TimeBodyGyroscopeJerk.std...Z                     : num  -0.958 -0.988 -0.992 -0.404 -0.269 ...
 $ TimeBodyAccelerometerMagnitude.std..              : num  -0.7951 -0.9271 -0.9819 -0.2197 0.0199 ...
 $ TimeGravityAccelerometerMagnitude.std..           : num  -0.7951 -0.9271 -0.9819 -0.2197 0.0199 ...
 $ TimeBodyAccelerometerJerkMagnitude.std..          : num  -0.9282 -0.9841 -0.9931 -0.0745 -0.0258 ...
 $ TimeBodyGyroscopeMagnitude.std..                  : num  -0.819 -0.935 -0.979 -0.187 -0.226 ...
 $ TimeBodyGyroscopeJerkMagnitude.std..              : num  -0.936 -0.988 -0.995 -0.325 -0.307 ...
 $ FrequencyBodyAccelerometer.std...X                : num  -0.9244 -0.9764 -0.996 -0.3191 0.0243 ...
 $ FrequencyBodyAccelerometer.std...Y                : num  -0.834 -0.917 -0.972 0.056 -0.113 ...
 $ FrequencyBodyAccelerometer.std...Z                : num  -0.813 -0.934 -0.978 -0.28 -0.298 ...
 $ FrequencyBodyAccelerometerJerk.std...X            : num  -0.9642 -0.9875 -0.9951 -0.1336 -0.0863 ...
 $ FrequencyBodyAccelerometerJerk.std...Y            : num  -0.932 -0.983 -0.987 0.107 -0.135 ...
 $ FrequencyBodyAccelerometerJerk.std...Z            : num  -0.961 -0.988 -0.992 -0.535 -0.402 ...
 $ FrequencyBodyGyroscope.std...X                    : num  -0.882 -0.978 -0.987 -0.517 -0.495 ...
 $ FrequencyBodyGyroscope.std...Y                    : num  -0.9512 -0.9623 -0.9871 -0.0335 -0.1814 ...
 $ FrequencyBodyGyroscope.std...Z                    : num  -0.917 -0.944 -0.982 -0.437 -0.238 ...
 $ FrequencyBodyAccelerometerMagnitude.std..         : num  -0.798 -0.928 -0.982 -0.398 -0.187 ...
 $ FrequencyBodyAccelerometerJerkMagnitude.std..     : num  -0.922 -0.982 -0.993 -0.103 -0.104 ...
 $ FrequencyBodyGyroscopeMagnitude.std..             : num  -0.824 -0.932 -0.978 -0.321 -0.398 ...
 $ FrequencyBodyGyroscopeJerkMagnitude.std..         : num  -0.933 -0.987 -0.995 -0.382 -0.392 ...
 - attr(*, "vars")= chr "subject"
 - attr(*, "drop")= logi TRUE


Take a look at final data

FinalData




Submission


Code Book

The run_analysis.R script performs the data preparation and then followed by the 5 steps required as described in the course project’s definition.

  1. Download the dataset
    • Dataset downloaded and extracted under the folder called UCI HAR Dataset

  2. Assign each data to variables
    • features <- features.txt : 561 rows, 2 columns
      The features selected for this database come from the accelerometer and gyroscope 3-axial raw signals tAcc-XYZ and tGyro-XYZ.
    • activities <- activity_labels.txt : 6 rows, 2 columns
      List of activities performed when the corresponding measurements were taken and its codes (labels)
    • subject_test <- test/subject_test.txt : 2947 rows, 1 column
      contains test data of 9/30 volunteer test subjects being observed
    • x_test <- test/X_test.txt : 2947 rows, 561 columns
      contains recorded features test data
    • y_test <- test/y_test.txt : 2947 rows, 1 columns
      contains test data of activities’code labels
    • subject_train <- test/subject_train.txt : 7352 rows, 1 column
      contains train data of 21/30 volunteer subjects being observed
    • x_train <- test/X_train.txt : 7352 rows, 561 columns
      contains recorded features train data
    • y_train <- test/y_train.txt : 7352 rows, 1 columns
      contains train data of activities’code labels

  3. Merges the training and the test sets to create one data set
    • X (10299 rows, 561 columns) is created by merging x_train and x_test using rbind() function
    • Y (10299 rows, 1 column) is created by merging y_train and y_test using rbind() function
    • Subject (10299 rows, 1 column) is created by merging subject_train and subject_test using rbind() function
    • Merged_Data (10299 rows, 563 column) is created by merging Subject, Y and X using cbind() function

  4. Extracts only the measurements on the mean and standard deviation for each measurement
    • TidyData (10299 rows, 88 columns) is created by subsetting Merged_Data, selecting only columns: subject, code and the measurements on the mean and standard deviation (std) for each measurement

  5. Uses descriptive activity names to name the activities in the data set
    • Entire numbers in code column of the TidyData replaced with corresponding activity taken from second column of the activities variable

  6. Appropriately labels the data set with descriptive variable names
    • code column in TidyData renamed into activities
    • All Acc in column’s name replaced by Accelerometer
    • All Gyro in column’s name replaced by Gyroscope
    • All BodyBody in column’s name replaced by Body
    • All Mag in column’s name replaced by Magnitude
    • All start with character f in column’s name replaced by Frequency
    • All start with character t in column’s name replaced by Time

  7. From the data set in step 4, creates a second, independent tidy data set with the average of each variable for each activity and each subject
    • FinalData (180 rows, 88 columns) is created by sumarizing TidyData taking the means of each variable for each activity and each subject, after groupped by subject and activity.
    • Export FinalData into FinalData.txt file.


README

Peer-graded Assignment: Getting and Cleaning Data Course Project

This repository is a Nunno Nugroho submission for Getting and Cleaning Data course project. It has the instructions on how to run analysis on Human Activity recognition dataset.

Dataset

Human Activity Recognition Using Smartphones

Files

  • CodeBook.md a code book that describes the variables, the data, and any transformations or work that I performed to clean up the data

  • run_analysis.R performs the data preparation and then followed by the 5 steps required as described in the course project’s definition:
    • Merges the training and the test sets to create one data set.
    • Extracts only the measurements on the mean and standard deviation for each measurement.
    • Uses descriptive activity names to name the activities in the data set
    • Appropriately labels the data set with descriptive variable names.
    • From the data set in step 4, creates a second, independent tidy data set with the average of each variable for each activity and each subject.
  • FinalData.txt is the exported final data after going through all the sequences described above.


Review criteria

  • The submitted data set is tidy. check

  • The Github repo contains the required scripts. check

  • GitHub contains a code book that modifies and updates the available codebooks with the data to indicate all the variables and summaries calculated, along with units, and any other relevant information. check

  • The README that explains the analysis files is clear and understandable. check

  • The work submitted for this project is the work of the student who submitted it. check



END

LS0tDQp0aXRsZTogIlBlZXItZ3JhZGVkIEFzc2lnbm1lbnQ6IEdldHRpbmcgYW5kIENsZWFuaW5nIERhdGEgQ291cnNlIFByb2plY3QiDQphdXRob3I6IE51bm5vIE51Z3JvaG8NCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCi0tLQ0KDQo8YnIvPg0KDQojIEluc3RydWN0aW9ucw0KDQo8YnIvPg0KDQojIyMgUmV2aWV3IGNyaXRlcmlhDQoNCiogVGhlIHN1Ym1pdHRlZCBkYXRhIHNldCBpcyB0aWR5Lg0KKiBUaGUgR2l0aHViIHJlcG8gY29udGFpbnMgdGhlIHJlcXVpcmVkIHNjcmlwdHMuDQoqIEdpdEh1YiBjb250YWlucyBhIGNvZGUgYm9vayB0aGF0IG1vZGlmaWVzIGFuZCB1cGRhdGVzIHRoZSBhdmFpbGFibGUgY29kZWJvb2tzIHdpdGggdGhlIGRhdGEgdG8gaW5kaWNhdGUgYWxsIHRoZSB2YXJpYWJsZXMgYW5kIHN1bW1hcmllcyBjYWxjdWxhdGVkLCBhbG9uZyB3aXRoIHVuaXRzLCBhbmQgYW55IG90aGVyIHJlbGV2YW50IGluZm9ybWF0aW9uLg0KKiBUaGUgUkVBRE1FIHRoYXQgZXhwbGFpbnMgdGhlIGFuYWx5c2lzIGZpbGVzIGlzIGNsZWFyIGFuZCB1bmRlcnN0YW5kYWJsZS4NCiogVGhlIHdvcmsgc3VibWl0dGVkIGZvciB0aGlzIHByb2plY3QgaXMgdGhlIHdvcmsgb2YgdGhlIHN0dWRlbnQgd2hvIHN1Ym1pdHRlZCBpdC4NCg0KPGJyLz4NCg0KIyMjIEdldHRpbmcgYW5kIENsZWFuaW5nIERhdGEgQ291cnNlIFByb2plY3QNCg0KVGhlIHB1cnBvc2Ugb2YgdGhpcyBwcm9qZWN0IGlzIHRvIGRlbW9uc3RyYXRlIHlvdXIgYWJpbGl0eSB0byBjb2xsZWN0LCB3b3JrIHdpdGgsIGFuZCBjbGVhbiBhIGRhdGEgc2V0LiBUaGUgZ29hbCBpcyB0byBwcmVwYXJlIHRpZHkgZGF0YSB0aGF0IGNhbiBiZSB1c2VkIGZvciBsYXRlciBhbmFseXNpcy4gWW91IHdpbGwgYmUgZ3JhZGVkIGJ5IHlvdXIgcGVlcnMgb24gYSBzZXJpZXMgb2YgeWVzL25vIHF1ZXN0aW9ucyByZWxhdGVkIHRvIHRoZSBwcm9qZWN0Lg0KDQpZb3Ugd2lsbCBiZSByZXF1aXJlZCB0byBzdWJtaXQ6DQoNCjEuIEEgdGlkeSBkYXRhIHNldCBhcyBkZXNjcmliZWQgYmVsb3csDQoyLiBBIGxpbmsgdG8gYSBHaXRodWIgcmVwb3NpdG9yeSB3aXRoIHlvdXIgc2NyaXB0IGZvciBwZXJmb3JtaW5nIHRoZSBhbmFseXNpcywNCjMuIEEgY29kZSBib29rIHRoYXQgZGVzY3JpYmVzIHRoZSB2YXJpYWJsZXMsIHRoZSBkYXRhLCBhbmQgYW55IHRyYW5zZm9ybWF0aW9ucyBvciB3b3JrIHRoYXQgeW91IHBlcmZvcm1lZCB0byBjbGVhbiB1cCB0aGUgZGF0YSBjYWxsZWQgQ29kZUJvb2subWQuIFlvdSBzaG91bGQgYWxzbyBpbmNsdWRlIGEgUkVBRE1FLm1kIGluIHRoZSByZXBvIHdpdGggeW91ciBzY3JpcHRzLiBUaGlzIHJlcG8gZXhwbGFpbnMgaG93IGFsbCBvZiB0aGUgc2NyaXB0cyB3b3JrIGFuZCBob3cgdGhleSBhcmUgY29ubmVjdGVkLg0KDQo8YnIvPg0KDQojIyMgRGF0YXNldA0KT25lIG9mIHRoZSBtb3N0IGV4Y2l0aW5nIGFyZWFzIGluIGFsbCBvZiBkYXRhIHNjaWVuY2UgcmlnaHQgbm93IGlzIHdlYXJhYmxlIGNvbXB1dGluZyAtIHNlZSBmb3IgZXhhbXBsZSB0aGlzIGFydGljbGUgLiBDb21wYW5pZXMgbGlrZSBGaXRiaXQsIE5pa2UsIGFuZCBKYXdib25lIFVwIGFyZSByYWNpbmcgdG8gZGV2ZWxvcCB0aGUgbW9zdCBhZHZhbmNlZCBhbGdvcml0aG1zIHRvIGF0dHJhY3QgbmV3IHVzZXJzLiBUaGUgZGF0YSBsaW5rZWQgdG8gZnJvbSB0aGUgY291cnNlIHdlYnNpdGUgcmVwcmVzZW50IGRhdGEgY29sbGVjdGVkIGZyb20gdGhlIGFjY2VsZXJvbWV0ZXJzIGZyb20gdGhlIFNhbXN1bmcgR2FsYXh5IFMgc21hcnRwaG9uZS4gQSBmdWxsIGRlc2NyaXB0aW9uIGlzIGF2YWlsYWJsZSBhdCB0aGUgc2l0ZSB3aGVyZSB0aGUgZGF0YSB3YXMgb2J0YWluZWQ6DQoNCmh0dHA6Ly9hcmNoaXZlLmljcy51Y2kuZWR1L21sL2RhdGFzZXRzL0h1bWFuK0FjdGl2aXR5K1JlY29nbml0aW9uK1VzaW5nK1NtYXJ0cGhvbmVzDQoNCkhlcmUgYXJlIHRoZSBkYXRhIGZvciB0aGUgcHJvamVjdDoNCg0KaHR0cHM6Ly9kMzk2cXVzemE0MG9yYy5jbG91ZGZyb250Lm5ldC9nZXRkYXRhJTJGcHJvamVjdGZpbGVzJTJGVUNJJTIwSEFSJTIwRGF0YXNldC56aXANCg0KWW91IHNob3VsZCBjcmVhdGUgb25lIFIgc2NyaXB0IGNhbGxlZCAqcnVuX2FuYWx5c2lzLlIqIHRoYXQgZG9lcyB0aGUgZm9sbG93aW5nLg0KDQoxLiBNZXJnZXMgdGhlIHRyYWluaW5nIGFuZCB0aGUgdGVzdCBzZXRzIHRvIGNyZWF0ZSBvbmUgZGF0YSBzZXQuDQoyLiBFeHRyYWN0cyBvbmx5IHRoZSBtZWFzdXJlbWVudHMgb24gdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBmb3IgZWFjaCBtZWFzdXJlbWVudC4NCjMuIFVzZXMgZGVzY3JpcHRpdmUgYWN0aXZpdHkgbmFtZXMgdG8gbmFtZSB0aGUgYWN0aXZpdGllcyBpbiB0aGUgZGF0YSBzZXQNCjQuIEFwcHJvcHJpYXRlbHkgbGFiZWxzIHRoZSBkYXRhIHNldCB3aXRoIGRlc2NyaXB0aXZlIHZhcmlhYmxlIG5hbWVzLg0KNS4gRnJvbSB0aGUgZGF0YSBzZXQgaW4gc3RlcCA0LCBjcmVhdGVzIGEgc2Vjb25kLCBpbmRlcGVuZGVudCB0aWR5IGRhdGEgc2V0IHdpdGggdGhlIGF2ZXJhZ2Ugb2YgZWFjaCB2YXJpYWJsZSBmb3IgZWFjaCBhY3Rpdml0eSBhbmQgZWFjaCBzdWJqZWN0Lg0KDQpHb29kIGx1Y2shDQoNCjxici8+DQoNCi0tLQ0KDQo8YnIvPg0KDQojIEhlcmUgd2UgZ28hDQoNCjxici8+DQoNCiMjIyBQcmVwYXJhdGlvbiBTdGFnZQ0KDQo8YnIvPg0KTG9hZGluZyByZXF1aXJlZCBwYWNrYWdlcw0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KYGBgDQo8YnIvPg0KRG93bmxvYWQgdGhlIGRhdGFzZXQNCmBgYHtyfQ0KZmlsZW5hbWUgPC0gIkNvdXJzZXJhX0RTM19GaW5hbC56aXAiDQoNCiMgQ2hlY2tpbmcgaWYgYXJjaGlldmUgYWxyZWFkeSBleGlzdHMuDQppZiAoIWZpbGUuZXhpc3RzKGZpbGVuYW1lKSl7DQogIGZpbGVVUkwgPC0gImh0dHBzOi8vZDM5NnF1c3phNDBvcmMuY2xvdWRmcm9udC5uZXQvZ2V0ZGF0YSUyRnByb2plY3RmaWxlcyUyRlVDSSUyMEhBUiUyMERhdGFzZXQuemlwIg0KICBkb3dubG9hZC5maWxlKGZpbGVVUkwsIGZpbGVuYW1lLCBtZXRob2Q9ImN1cmwiKQ0KfSAgDQoNCiMgQ2hlY2tpbmcgaWYgZm9sZGVyIGV4aXN0cw0KaWYgKCFmaWxlLmV4aXN0cygiVUNJIEhBUiBEYXRhc2V0IikpIHsgDQogIHVuemlwKGZpbGVuYW1lKSANCn0NCmBgYA0KPGJyLz4NCkFzc2lnbmluZyBhbGwgZGF0YSBmcmFtZXMNCmBgYHtyfQ0KZmVhdHVyZXMgPC0gcmVhZC50YWJsZSgiVUNJIEhBUiBEYXRhc2V0L2ZlYXR1cmVzLnR4dCIsIGNvbC5uYW1lcyA9IGMoIm4iLCJmdW5jdGlvbnMiKSkNCmFjdGl2aXRpZXMgPC0gcmVhZC50YWJsZSgiVUNJIEhBUiBEYXRhc2V0L2FjdGl2aXR5X2xhYmVscy50eHQiLCBjb2wubmFtZXMgPSBjKCJjb2RlIiwgImFjdGl2aXR5IikpDQoNCnN1YmplY3RfdGVzdCA8LSByZWFkLnRhYmxlKCJVQ0kgSEFSIERhdGFzZXQvdGVzdC9zdWJqZWN0X3Rlc3QudHh0IiwgY29sLm5hbWVzID0gInN1YmplY3QiKQ0KeF90ZXN0IDwtIHJlYWQudGFibGUoIlVDSSBIQVIgRGF0YXNldC90ZXN0L1hfdGVzdC50eHQiLCBjb2wubmFtZXMgPSBmZWF0dXJlcyRmdW5jdGlvbnMpDQp5X3Rlc3QgPC0gcmVhZC50YWJsZSgiVUNJIEhBUiBEYXRhc2V0L3Rlc3QveV90ZXN0LnR4dCIsIGNvbC5uYW1lcyA9ICJjb2RlIikNCg0Kc3ViamVjdF90cmFpbiA8LSByZWFkLnRhYmxlKCJVQ0kgSEFSIERhdGFzZXQvdHJhaW4vc3ViamVjdF90cmFpbi50eHQiLCBjb2wubmFtZXMgPSAic3ViamVjdCIpDQp4X3RyYWluIDwtIHJlYWQudGFibGUoIlVDSSBIQVIgRGF0YXNldC90cmFpbi9YX3RyYWluLnR4dCIsIGNvbC5uYW1lcyA9IGZlYXR1cmVzJGZ1bmN0aW9ucykNCnlfdHJhaW4gPC0gcmVhZC50YWJsZSgiVUNJIEhBUiBEYXRhc2V0L3RyYWluL3lfdHJhaW4udHh0IiwgY29sLm5hbWVzID0gImNvZGUiKQ0KYGBgDQoNCjxici8+DQoNCiMjIyBUaGUgIkdvIGZvciBpdCEiIFN0YWdlDQoNCj4gIllvdSBzaG91bGQgY3JlYXRlIG9uZSBSIHNjcmlwdCBjYWxsZWQgKnJ1bl9hbmFseXNpcy5SKiB0aGF0IGRvZXMgdGhlIGZvbGxvd2luZzoiDQoNCjxici8+DQoNCioqU3RlcCAxOiBNZXJnZXMgdGhlIHRyYWluaW5nIGFuZCB0aGUgdGVzdCBzZXRzIHRvIGNyZWF0ZSBvbmUgZGF0YSBzZXQuKioNCg0KYGBge3J9DQpYIDwtIHJiaW5kKHhfdHJhaW4sIHhfdGVzdCkNClkgPC0gcmJpbmQoeV90cmFpbiwgeV90ZXN0KQ0KU3ViamVjdCA8LSByYmluZChzdWJqZWN0X3RyYWluLCBzdWJqZWN0X3Rlc3QpDQoNCk1lcmdlZF9EYXRhIDwtIGNiaW5kKFN1YmplY3QsIFksIFgpDQpgYGANCg0KPGJyLz4NCg0KKipTdGVwIDI6IEV4dHJhY3RzIG9ubHkgdGhlIG1lYXN1cmVtZW50cyBvbiB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGZvciBlYWNoIG1lYXN1cmVtZW50LioqDQoNCmBgYHtyfQ0KVGlkeURhdGEgPC0gTWVyZ2VkX0RhdGEgJT4lIHNlbGVjdChzdWJqZWN0LCBjb2RlLCBjb250YWlucygibWVhbiIpLCBjb250YWlucygic3RkIikpDQpgYGANCg0KPGJyLz4NCg0KKipTdGVwIDM6IFVzZXMgZGVzY3JpcHRpdmUgYWN0aXZpdHkgbmFtZXMgdG8gbmFtZSB0aGUgYWN0aXZpdGllcyBpbiB0aGUgZGF0YSBzZXQuKioNCg0KYGBge3J9DQpUaWR5RGF0YSRjb2RlIDwtIGFjdGl2aXRpZXNbVGlkeURhdGEkY29kZSwgMl0NCmBgYA0KDQo8YnIvPg0KDQoqKlN0ZXAgNDogQXBwcm9wcmlhdGVseSBsYWJlbHMgdGhlIGRhdGEgc2V0IHdpdGggZGVzY3JpcHRpdmUgdmFyaWFibGUgbmFtZXMuKioNCg0KYGBge3J9DQpuYW1lcyhUaWR5RGF0YSlbMl0gPSAiYWN0aXZpdHkiDQpuYW1lcyhUaWR5RGF0YSk8LWdzdWIoIkFjYyIsICJBY2NlbGVyb21ldGVyIiwgbmFtZXMoVGlkeURhdGEpKQ0KbmFtZXMoVGlkeURhdGEpPC1nc3ViKCJHeXJvIiwgIkd5cm9zY29wZSIsIG5hbWVzKFRpZHlEYXRhKSkNCm5hbWVzKFRpZHlEYXRhKTwtZ3N1YigiQm9keUJvZHkiLCAiQm9keSIsIG5hbWVzKFRpZHlEYXRhKSkNCm5hbWVzKFRpZHlEYXRhKTwtZ3N1YigiTWFnIiwgIk1hZ25pdHVkZSIsIG5hbWVzKFRpZHlEYXRhKSkNCm5hbWVzKFRpZHlEYXRhKTwtZ3N1YigiXnQiLCAiVGltZSIsIG5hbWVzKFRpZHlEYXRhKSkNCm5hbWVzKFRpZHlEYXRhKTwtZ3N1YigiXmYiLCAiRnJlcXVlbmN5IiwgbmFtZXMoVGlkeURhdGEpKQ0KbmFtZXMoVGlkeURhdGEpPC1nc3ViKCJ0Qm9keSIsICJUaW1lQm9keSIsIG5hbWVzKFRpZHlEYXRhKSkNCm5hbWVzKFRpZHlEYXRhKTwtZ3N1YigiLW1lYW4oKSIsICJNZWFuIiwgbmFtZXMoVGlkeURhdGEpLCBpZ25vcmUuY2FzZSA9IFRSVUUpDQpuYW1lcyhUaWR5RGF0YSk8LWdzdWIoIi1zdGQoKSIsICJTVEQiLCBuYW1lcyhUaWR5RGF0YSksIGlnbm9yZS5jYXNlID0gVFJVRSkNCm5hbWVzKFRpZHlEYXRhKTwtZ3N1YigiLWZyZXEoKSIsICJGcmVxdWVuY3kiLCBuYW1lcyhUaWR5RGF0YSksIGlnbm9yZS5jYXNlID0gVFJVRSkNCm5hbWVzKFRpZHlEYXRhKTwtZ3N1YigiYW5nbGUiLCAiQW5nbGUiLCBuYW1lcyhUaWR5RGF0YSkpDQpuYW1lcyhUaWR5RGF0YSk8LWdzdWIoImdyYXZpdHkiLCAiR3Jhdml0eSIsIG5hbWVzKFRpZHlEYXRhKSkNCmBgYA0KDQo8YnIvPg0KDQoqKlN0ZXAgNTogRnJvbSB0aGUgZGF0YSBzZXQgaW4gc3RlcCA0LCBjcmVhdGVzIGEgc2Vjb25kLCBpbmRlcGVuZGVudCB0aWR5IGRhdGEgc2V0IHdpdGggdGhlIGF2ZXJhZ2Ugb2YgZWFjaCB2YXJpYWJsZSBmb3IgZWFjaCBhY3Rpdml0eSBhbmQgZWFjaCBzdWJqZWN0LioqDQoNCmBgYHtyfQ0KRmluYWxEYXRhIDwtIFRpZHlEYXRhICU+JQ0KICAgIGdyb3VwX2J5KHN1YmplY3QsIGFjdGl2aXR5KSAlPiUNCiAgICBzdW1tYXJpc2VfYWxsKGZ1bnMobWVhbikpDQoNCndyaXRlLnRhYmxlKEZpbmFsRGF0YSwgIkZpbmFsRGF0YS50eHQiLCByb3cubmFtZT1GQUxTRSkNCmBgYA0KDQo8YnIvPg0KDQojIyMgRmluYWwgQ2hlY2sgU3RhZ2UNCg0KPGJyLz4NCkNoZWNraW5nIHZhcmlhYmxlIG5hbWVzDQpgYGB7cn0NCnN0cihGaW5hbERhdGEpDQpgYGANCg0KPGJyLz4NCg0KVGFrZSBhIGxvb2sgYXQgZmluYWwgZGF0YQ0KYGBge3J9DQpGaW5hbERhdGENCmBgYA0KDQo8YnIvPg0KDQotLS0NCg0KPGJyLz4NCg0KIyBTdWJtaXNzaW9uDQoNCjxici8+DQoNCiMjIyBDb2RlIEJvb2sNCg0KPGRpdiBzdHlsZT0gImJvcmRlcjogNXB4IGRvdHRlZCBncmF5OyBwYWRkaW5nOiAxMHB4IDIwcHg7IGJhY2tncm91bmQtY29sb3I6I2VkZWRlZDsgYm94LXNoYWRvdzogMCAxcHggNXB4IHJnYmEoMCwgMCwgMCwgMC4yNSk7Ij4NCg0KVGhlIGBydW5fYW5hbHlzaXMuUmAgc2NyaXB0IHBlcmZvcm1zIHRoZSBkYXRhIHByZXBhcmF0aW9uIGFuZCB0aGVuIGZvbGxvd2VkIGJ5IHRoZSA1IHN0ZXBzIHJlcXVpcmVkIGFzIGRlc2NyaWJlZCBpbiB0aGUgY291cnNlIHByb2plY3QncyBkZWZpbml0aW9uLg0KDQoxLiAqKkRvd25sb2FkIHRoZSBkYXRhc2V0KioNCiAgICArIERhdGFzZXQgZG93bmxvYWRlZCBhbmQgZXh0cmFjdGVkIHVuZGVyIHRoZSBmb2xkZXIgY2FsbGVkIGBVQ0kgSEFSIERhdGFzZXRgDQogICAgDQogICAgPGJyLz4NCjIuICoqQXNzaWduIGVhY2ggZGF0YSB0byB2YXJpYWJsZXMqKg0KICAgICsgYGZlYXR1cmVzYCA8LSBgZmVhdHVyZXMudHh0YCA6IDU2MSByb3dzLCAyIGNvbHVtbnMgPGJyLz4NCiAgICAgICAgKlRoZSBmZWF0dXJlcyBzZWxlY3RlZCBmb3IgdGhpcyBkYXRhYmFzZSBjb21lIGZyb20gdGhlIGFjY2VsZXJvbWV0ZXIgYW5kIGd5cm9zY29wZSAzLWF4aWFsIHJhdyBzaWduYWxzIHRBY2MtWFlaIGFuZCB0R3lyby1YWVouKg0KICAgICsgYGFjdGl2aXRpZXNgIDwtIGBhY3Rpdml0eV9sYWJlbHMudHh0YCA6IDYgcm93cywgMiBjb2x1bW5zIDxici8+DQogICAgICAgICpMaXN0IG9mIGFjdGl2aXRpZXMgcGVyZm9ybWVkIHdoZW4gdGhlIGNvcnJlc3BvbmRpbmcgbWVhc3VyZW1lbnRzIHdlcmUgdGFrZW4gYW5kIGl0cyBjb2RlcyAobGFiZWxzKSoNCiAgICArIGBzdWJqZWN0X3Rlc3RgIDwtIGB0ZXN0L3N1YmplY3RfdGVzdC50eHRgIDogMjk0NyByb3dzLCAxIGNvbHVtbiA8YnIvPg0KICAgICAgICAqY29udGFpbnMgdGVzdCBkYXRhIG9mIDkvMzAgdm9sdW50ZWVyIHRlc3Qgc3ViamVjdHMgYmVpbmcgb2JzZXJ2ZWQqDQogICAgKyBgeF90ZXN0YCA8LSBgdGVzdC9YX3Rlc3QudHh0YCA6IDI5NDcgcm93cywgNTYxIGNvbHVtbnMgPGJyLz4NCiAgICAgICAgKmNvbnRhaW5zIHJlY29yZGVkIGZlYXR1cmVzIHRlc3QgZGF0YSoNCiAgICArIGB5X3Rlc3RgIDwtIGB0ZXN0L3lfdGVzdC50eHRgIDogMjk0NyByb3dzLCAxIGNvbHVtbnMgPGJyLz4NCiAgICAgICAgKmNvbnRhaW5zIHRlc3QgZGF0YSBvZiBhY3Rpdml0aWVzJ2NvZGUgbGFiZWxzKg0KICAgICsgYHN1YmplY3RfdHJhaW5gIDwtIGB0ZXN0L3N1YmplY3RfdHJhaW4udHh0YCA6IDczNTIgcm93cywgMSBjb2x1bW4gPGJyLz4NCiAgICAgICAgKmNvbnRhaW5zIHRyYWluIGRhdGEgb2YgMjEvMzAgdm9sdW50ZWVyIHN1YmplY3RzIGJlaW5nIG9ic2VydmVkKg0KICAgICsgYHhfdHJhaW5gIDwtIGB0ZXN0L1hfdHJhaW4udHh0YCA6IDczNTIgcm93cywgNTYxIGNvbHVtbnMgPGJyLz4NCiAgICAgICAgKmNvbnRhaW5zIHJlY29yZGVkIGZlYXR1cmVzIHRyYWluIGRhdGEqDQogICAgKyBgeV90cmFpbmAgPC0gYHRlc3QveV90cmFpbi50eHRgIDogNzM1MiByb3dzLCAxIGNvbHVtbnMgPGJyLz4NCiAgICAgICAgKmNvbnRhaW5zIHRyYWluIGRhdGEgb2YgYWN0aXZpdGllcydjb2RlIGxhYmVscyoNCiAgIA0KICAgIDxici8+DQozLiAqKk1lcmdlcyB0aGUgdHJhaW5pbmcgYW5kIHRoZSB0ZXN0IHNldHMgdG8gY3JlYXRlIG9uZSBkYXRhIHNldCoqDQogICAgKyBgWGAgKDEwMjk5IHJvd3MsIDU2MSBjb2x1bW5zKSBpcyBjcmVhdGVkIGJ5IG1lcmdpbmcgYHhfdHJhaW5gIGFuZCBgeF90ZXN0YCB1c2luZyAqKnJiaW5kKCkqKiBmdW5jdGlvbg0KICAgICsgYFlgICgxMDI5OSByb3dzLCAxIGNvbHVtbikgaXMgY3JlYXRlZCBieSBtZXJnaW5nIGB5X3RyYWluYCBhbmQgYHlfdGVzdGAgdXNpbmcgKipyYmluZCgpKiogZnVuY3Rpb24NCiAgICArIGBTdWJqZWN0YCAoMTAyOTkgcm93cywgMSBjb2x1bW4pIGlzIGNyZWF0ZWQgYnkgbWVyZ2luZyBgc3ViamVjdF90cmFpbmAgYW5kIGBzdWJqZWN0X3Rlc3RgIHVzaW5nICoqcmJpbmQoKSoqIGZ1bmN0aW9uDQogICAgKyBgTWVyZ2VkX0RhdGFgICgxMDI5OSByb3dzLCA1NjMgY29sdW1uKSBpcyBjcmVhdGVkIGJ5IG1lcmdpbmcgYFN1YmplY3RgLCBgWWAgYW5kIGBYYCB1c2luZyAqKmNiaW5kKCkqKiBmdW5jdGlvbg0KICAgDQogICAgPGJyLz4NCjQuICoqRXh0cmFjdHMgb25seSB0aGUgbWVhc3VyZW1lbnRzIG9uIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIGVhY2ggbWVhc3VyZW1lbnQqKg0KICAgICsgYFRpZHlEYXRhYCAoMTAyOTkgcm93cywgODggY29sdW1ucykgaXMgY3JlYXRlZCBieSBzdWJzZXR0aW5nIGBNZXJnZWRfRGF0YWAsIHNlbGVjdGluZyBvbmx5IGNvbHVtbnM6IGBzdWJqZWN0YCwgYGNvZGVgIGFuZCB0aGUgbWVhc3VyZW1lbnRzIG9uIHRoZSBgbWVhbmAgYW5kICpzdGFuZGFyZCBkZXZpYXRpb24qIChgc3RkYCkgZm9yIGVhY2ggbWVhc3VyZW1lbnQNCg0KICAgIDxici8+DQo1LiAqKlVzZXMgZGVzY3JpcHRpdmUgYWN0aXZpdHkgbmFtZXMgdG8gbmFtZSB0aGUgYWN0aXZpdGllcyBpbiB0aGUgZGF0YSBzZXQqKg0KICAgICsgRW50aXJlIG51bWJlcnMgaW4gYGNvZGVgIGNvbHVtbiBvZiB0aGUgYFRpZHlEYXRhYCByZXBsYWNlZCB3aXRoIGNvcnJlc3BvbmRpbmcgYWN0aXZpdHkgdGFrZW4gZnJvbSBzZWNvbmQgY29sdW1uIG9mIHRoZSBgYWN0aXZpdGllc2AgdmFyaWFibGUNCg0KICAgIDxici8+DQo2LiAqKkFwcHJvcHJpYXRlbHkgbGFiZWxzIHRoZSBkYXRhIHNldCB3aXRoIGRlc2NyaXB0aXZlIHZhcmlhYmxlIG5hbWVzKioNCiAgICArIGBjb2RlYCBjb2x1bW4gaW4gYFRpZHlEYXRhYCByZW5hbWVkIGludG8gYGFjdGl2aXRpZXNgDQogICAgKyAgQWxsIGBBY2NgIGluIGNvbHVtbidzIG5hbWUgcmVwbGFjZWQgYnkgYEFjY2VsZXJvbWV0ZXJgDQogICAgKyAgQWxsIGBHeXJvYCBpbiBjb2x1bW4ncyBuYW1lIHJlcGxhY2VkIGJ5IGBHeXJvc2NvcGVgDQogICAgKyAgQWxsIGBCb2R5Qm9keWAgaW4gY29sdW1uJ3MgbmFtZSByZXBsYWNlZCBieSBgQm9keWANCiAgICArICBBbGwgYE1hZ2AgaW4gY29sdW1uJ3MgbmFtZSByZXBsYWNlZCBieSBgTWFnbml0dWRlYA0KICAgICsgIEFsbCBzdGFydCB3aXRoIGNoYXJhY3RlciBgZmAgaW4gY29sdW1uJ3MgbmFtZSByZXBsYWNlZCBieSBgRnJlcXVlbmN5YA0KICAgICsgIEFsbCBzdGFydCB3aXRoIGNoYXJhY3RlciBgdGAgaW4gY29sdW1uJ3MgbmFtZSByZXBsYWNlZCBieSBgVGltZWANCg0KICAgIDxici8+DQo3LiAqKkZyb20gdGhlIGRhdGEgc2V0IGluIHN0ZXAgNCwgY3JlYXRlcyBhIHNlY29uZCwgaW5kZXBlbmRlbnQgdGlkeSBkYXRhIHNldCB3aXRoIHRoZSBhdmVyYWdlIG9mIGVhY2ggdmFyaWFibGUgZm9yIGVhY2ggYWN0aXZpdHkgYW5kIGVhY2ggc3ViamVjdCoqDQogICAgKyBgRmluYWxEYXRhYCAoMTgwIHJvd3MsIDg4IGNvbHVtbnMpIGlzIGNyZWF0ZWQgYnkgc3VtYXJpemluZyBgVGlkeURhdGFgIHRha2luZyB0aGUgbWVhbnMgb2YgZWFjaCB2YXJpYWJsZSBmb3IgZWFjaCBhY3Rpdml0eSBhbmQgZWFjaCBzdWJqZWN0LCBhZnRlciBncm91cHBlZCBieSBzdWJqZWN0IGFuZCBhY3Rpdml0eS4NCiAgICArIEV4cG9ydCBgRmluYWxEYXRhYCBpbnRvIGBGaW5hbERhdGEudHh0YCBmaWxlLg0KDQo8L2Rpdj4NCg0KPGJyLz4NCg0KIyMjIFJFQURNRQ0KDQo8ZGl2IHN0eWxlPSAiYm9yZGVyOiA1cHggZG90dGVkIGdyYXk7IHBhZGRpbmc6IDEwcHggMjBweDsgYmFja2dyb3VuZC1jb2xvcjojZWRlZGVkOyBib3gtc2hhZG93OiAwIDFweCA1cHggcmdiYSgwLCAwLCAwLCAwLjI1KTsiPg0KDQojIyMjIFBlZXItZ3JhZGVkIEFzc2lnbm1lbnQ6IEdldHRpbmcgYW5kIENsZWFuaW5nIERhdGEgQ291cnNlIFByb2plY3QNCg0KVGhpcyByZXBvc2l0b3J5IGlzIGEgKipOdW5ubyBOdWdyb2hvKiogc3VibWlzc2lvbiBmb3IgR2V0dGluZyBhbmQgQ2xlYW5pbmcgRGF0YSBjb3Vyc2UgcHJvamVjdC4gSXQgaGFzIHRoZSBpbnN0cnVjdGlvbnMgb24gaG93IHRvIHJ1biBhbmFseXNpcyBvbiBIdW1hbiBBY3Rpdml0eSByZWNvZ25pdGlvbiBkYXRhc2V0Lg0KDQojIyMjIERhdGFzZXQNCg0KW0h1bWFuIEFjdGl2aXR5IFJlY29nbml0aW9uIFVzaW5nIFNtYXJ0cGhvbmVzXShodHRwOi8vYXJjaGl2ZS5pY3MudWNpLmVkdS9tbC9kYXRhc2V0cy9IdW1hbitBY3Rpdml0eStSZWNvZ25pdGlvbitVc2luZytTbWFydHBob25lcykNCg0KIyMjIyBGaWxlcw0KDQoqIGBDb2RlQm9vay5tZGAgYSBjb2RlIGJvb2sgdGhhdCBkZXNjcmliZXMgdGhlIHZhcmlhYmxlcywgdGhlIGRhdGEsIGFuZCBhbnkgdHJhbnNmb3JtYXRpb25zIG9yIHdvcmsgdGhhdCBJIHBlcmZvcm1lZCB0byBjbGVhbiB1cCB0aGUgZGF0YQ0KDQoqIGBydW5fYW5hbHlzaXMuUmAgcGVyZm9ybXMgdGhlIGRhdGEgcHJlcGFyYXRpb24gYW5kIHRoZW4gZm9sbG93ZWQgYnkgdGhlIDUgc3RlcHMgcmVxdWlyZWQgYXMgZGVzY3JpYmVkIGluIHRoZSBjb3Vyc2UgcHJvamVjdCdzIGRlZmluaXRpb246DQogICAgKyBNZXJnZXMgdGhlIHRyYWluaW5nIGFuZCB0aGUgdGVzdCBzZXRzIHRvIGNyZWF0ZSBvbmUgZGF0YSBzZXQuDQogICAgKyBFeHRyYWN0cyBvbmx5IHRoZSBtZWFzdXJlbWVudHMgb24gdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBmb3IgZWFjaCBtZWFzdXJlbWVudC4NCiAgICArIFVzZXMgZGVzY3JpcHRpdmUgYWN0aXZpdHkgbmFtZXMgdG8gbmFtZSB0aGUgYWN0aXZpdGllcyBpbiB0aGUgZGF0YSBzZXQNCiAgICArIEFwcHJvcHJpYXRlbHkgbGFiZWxzIHRoZSBkYXRhIHNldCB3aXRoIGRlc2NyaXB0aXZlIHZhcmlhYmxlIG5hbWVzLg0KICAgICsgRnJvbSB0aGUgZGF0YSBzZXQgaW4gc3RlcCA0LCBjcmVhdGVzIGEgc2Vjb25kLCBpbmRlcGVuZGVudCB0aWR5IGRhdGEgc2V0IHdpdGggdGhlIGF2ZXJhZ2Ugb2YgZWFjaCB2YXJpYWJsZSBmb3IgZWFjaCBhY3Rpdml0eSBhbmQgZWFjaCBzdWJqZWN0Lg0KICAgIA0KKiBgRmluYWxEYXRhLnR4dGAgaXMgdGhlIGV4cG9ydGVkIGZpbmFsIGRhdGEgYWZ0ZXIgZ29pbmcgdGhyb3VnaCBhbGwgdGhlIHNlcXVlbmNlcyBkZXNjcmliZWQgYWJvdmUuDQoNCg0KPC9kaXY+DQoNCjxici8+DQoNCiMjIyBSZXZpZXcgY3JpdGVyaWENCg0KKiBUaGUgc3VibWl0dGVkIGRhdGEgc2V0IGlzIHRpZHkuDQo8aW1nIHNyYz0iaHR0cHM6Ly9jZG4xLmljb25maW5kZXIuY29tL2RhdGEvaWNvbnMvaW50ZXJmYWNlLWVsZW1lbnRzLzMyL2FjY2VwdC1jaXJjbGUtNTEyLnBuZyIgYWx0PSJjaGVjayIgd2lkdGg9IjE1cHgiIGhlaWd0aD0iMTVweCIvPg0KDQoqIFRoZSBHaXRodWIgcmVwbyBjb250YWlucyB0aGUgcmVxdWlyZWQgc2NyaXB0cy4NCjxpbWcgc3JjPSJodHRwczovL2NkbjEuaWNvbmZpbmRlci5jb20vZGF0YS9pY29ucy9pbnRlcmZhY2UtZWxlbWVudHMvMzIvYWNjZXB0LWNpcmNsZS01MTIucG5nIiBhbHQ9ImNoZWNrIiB3aWR0aD0iMTVweCIgaGVpZ3RoPSIxNXB4Ii8+DQoNCiogR2l0SHViIGNvbnRhaW5zIGEgY29kZSBib29rIHRoYXQgbW9kaWZpZXMgYW5kIHVwZGF0ZXMgdGhlIGF2YWlsYWJsZSBjb2RlYm9va3Mgd2l0aCB0aGUgZGF0YSB0byBpbmRpY2F0ZSBhbGwgdGhlIHZhcmlhYmxlcyBhbmQgc3VtbWFyaWVzIGNhbGN1bGF0ZWQsIGFsb25nIHdpdGggdW5pdHMsIGFuZCBhbnkgb3RoZXIgcmVsZXZhbnQgaW5mb3JtYXRpb24uDQo8aW1nIHNyYz0iaHR0cHM6Ly9jZG4xLmljb25maW5kZXIuY29tL2RhdGEvaWNvbnMvaW50ZXJmYWNlLWVsZW1lbnRzLzMyL2FjY2VwdC1jaXJjbGUtNTEyLnBuZyIgYWx0PSJjaGVjayIgd2lkdGg9IjE1cHgiIGhlaWd0aD0iMTVweCIvPg0KDQoqIFRoZSBSRUFETUUgdGhhdCBleHBsYWlucyB0aGUgYW5hbHlzaXMgZmlsZXMgaXMgY2xlYXIgYW5kIHVuZGVyc3RhbmRhYmxlLg0KPGltZyBzcmM9Imh0dHBzOi8vY2RuMS5pY29uZmluZGVyLmNvbS9kYXRhL2ljb25zL2ludGVyZmFjZS1lbGVtZW50cy8zMi9hY2NlcHQtY2lyY2xlLTUxMi5wbmciIGFsdD0iY2hlY2siIHdpZHRoPSIxNXB4IiBoZWlndGg9IjE1cHgiLz4NCg0KKiBUaGUgd29yayBzdWJtaXR0ZWQgZm9yIHRoaXMgcHJvamVjdCBpcyB0aGUgd29yayBvZiB0aGUgc3R1ZGVudCB3aG8gc3VibWl0dGVkIGl0Lg0KPGltZyBzcmM9Imh0dHBzOi8vY2RuMS5pY29uZmluZGVyLmNvbS9kYXRhL2ljb25zL2ludGVyZmFjZS1lbGVtZW50cy8zMi9hY2NlcHQtY2lyY2xlLTUxMi5wbmciIGFsdD0iY2hlY2siIHdpZHRoPSIxNXB4IiBoZWlndGg9IjE1cHgiLz4NCg0KPGJyLz4NCg0KLS0tDQoNCjxjZW50ZXI+KipFTkQqKjwvY2VudGVyPg0KDQotLS0=