### About

This worksheet includes three main tasks on data outliers, data preparation, and data modeling. The lab requires the use of Microsoft Excel, R, and ERDplus.

Setup

Remember to always set your working directory to the source file location. Go to ‘Session’, scroll down to ‘Set Working Directory’, and click ‘To Source File Location’. Read carefully the below and follow the instructions to complete the tasks and answer any questions. Submit your work in Sakai as detailed in previous notes.

Note

For your assignment you may be using different data sets than what is included here. Always read carefully the instructions provided, before executing any included code chunks and/or adding your own code. For clarity, tasks/questions to be completed/answered are highlighted in red color and numbered according to their particular placement in the task section. The red color is only apparent when in Preview mode. Quite often you will need to add your own code chunk.

Execute all code chunks (already included and own added), preview, check integrity, and submit final work (\(html\) file) in Sakai.


Task 1: Data Outliers

First, we must calculate the mean, standard deviation, maximum, and minimum for the Age column using R.

In R, we must read in the file again, extract the column and find the values that are asked for.

#Read File
mydata = read.csv(file="creditrisk.csv") 

#Name the extracted variable
age = mydata$Age 

##### 1A) Fill in the code chunk below to calculate and display each result. Refer to previous worksheets and on-line help for some commands (2pts)


#Calculate the average age 
mean(age)
[1] 34.39765
#Calculate the standard deviation of age 
sd(age)
[1] 11.04513
#Calculate the maxima of age.  Search in Help to find the right command for maxima
max(age)
[1] 73
#Calculate the minima of age.  Search in Help to find the right command for minima
min(age)
[1] 18

Next, we will use the formula from class to detect any outliers. An outlier is a value that “lies outside” most of the other values in a set of data. A common way to estimate the upper and lower limits is to take the mean (+ or -) 3 * standard deviation.

##### 1B) Insert and execute the code chunk corresponding to the above formula to calculate the upper and lower limits for age. Show your results. Based on the limits do you think there are outliers? Explain your logic (2pts)

Yes, in this case, an outlier is described as a value + or - 3 standard deviations from the mean. This means the upper limit is 67.5 years old, and the lower limit is 1.3 years old.There are outliers because there are people aged more thean 67.5 years old, which is greater than the upper limit. There is someone aged 73, and this is more than 3 standard deviations away from the mean, and this defines an outlier.

#Upper limit
mean(age)+sd(age)*3
[1] 67.53302
#Lower Limit
mean(age)-sd(age)*3
[1] 1.262269

Another method to find the upper and lower thresholds, discussed in many introductory statistics courses, requires calculating the interquartile range. Follow along below to see how we first calculate the interquartile range..

quantile(age) 
  0%  25%  50%  75% 100% 
  18   26   32   41   73 
lowerq = quantile(age)[2]
upperq = quantile(age)[4]
iqr = upperq - lowerq

Next we calculate the limiting thresholds. A threshold here is the boundary that determines if a value is an outlier. If the value falls above the upper threshold or below the lower threshold, it is an outlier.

To calculate the upper threshold:

upperthreshold = (iqr * 1.5) + upperq 
upperthreshold
 75% 
63.5 

Below is the lower threshold:

lowerthreshold = lowerq - (iqr * 1.5)
lowerthreshold
25% 
3.5 

A good way to undertsand the above calculations is to visualize the results using a box and whisker plot. The top and lower ends of the box correspond to the upper and lower quartiles. The median is marked by a bolded line. The whiskers are the lines connecting the upper and lower quartiles to upper and lower thresholds. Any points beyond the thresholds is a potential outlier.

boxplot(age) 

##### 1C) From the box plot representation are there any outliers? How many can you count? How does your answer reconcile with the result from Task 1B? (2pts)

The Box plot shows 5 different ages Outliers. Looking at the excel sheet, there are 9 outliers total (73,67,67, 66, 65, 65, 65, 64, 64). In all, there are 5 differnt ages as outliers, (73, 67, 66, 65, and 64). This reconciles the ages that are considered outliers in excel and in the Box Plot.

The following is an optional challenge question. To answer, you will need to consider the difference between a normal distribution and a corresponding histogram. It will count as 2 extra points instead of the second pop quiz.

##### 1C’) Looking at the two methods of calculations to identify outliers in 1A) and 1B) , explain how they differ and also how they reconcile (2pts extra)

We used two different methods to calculate outliers.The first, was using a normal distribution curve. Outliers are defined as anything outside of the upper and lower limits found (mean + 3 standard deviations or mean - 3 standard deviations). In this calculation, about 99.7% of the data is within 3 standard deviations, and about .3% is outside of this range, meaning it is an outlier. The second method is using histogram. This method uses the interquartile range (IQR) to calculate outliers. The IQR accounts for the middle 50% of the data, and it takes the difference between the top 75th percentile data (Q3) and the 25th percentile (Q1) data. This is then multiplied by 1.5, and either added or subtracted from the IQR to find the upper or lower limits for outliers.

Reconcile of histogram and normal distribution outliers: a z-score of -.67 is the 25th percentile of data (Q1) and a z-score of .67 is the 75th percentile of data (Q3)

#Read File
mydata = read.csv(file="creditrisk.csv") 

#Name the extracted variable
age = mydata$Age
mean(age)
[1] 34.39765
sd(age)
[1] 11.04513
#Q1
# z =  (x - xbar )/ spread
# change equation to easily solve z*s + xbar = x
# if z= -.67, this is Q1
z = -.67
y = mean(age)
s = sd(age)
z*s + y
[1] 26.99741

In the histogram, Q1 is 26. This reconciles to the Q1 found using z-scores. Obviously there is a rounding error.

#Q3
# z =  (x - xbar )/ spread
# change equation to easily solve z*s + xbar = x
# if z= -.67, this is Q1
z = .67
y = mean(age)
s = sd(age)
z*s + y
[1] 41.79788

In the histogram, Q3 is 41, which is very close to the Q3 found using z-scores. This is a rounding error away.

#Solve for IQR
41.797888-26.99741
[1] 14.80048
#solve for lower limit
26.99741-(14.80048*1.5)
[1] 4.79669
#solve for upper limit
41.797888+(14.80048*1.5)
[1] 63.99861

Under these calculations, anything over 63.99861 is an outlier, compared to the 63.5 outlier upper range calculated from the histogram. These are very close, but they vary from rounding errors. Anything under 4.79669 is an outlier, compared to the 3.5 from the histogram. Again, this number varies slightly from the rounding errors. This is the reconciling of the histogram and standard deviation calculations of the outliers. —————

Task 2: Data Preparation

Next, we will read the file creditriskorg.csv into R as provided in its original form. Unlike the cleaned file creditrisk.csv, the original dataset will require some data preparation.

newdata = read.csv(file="creditriskorg1.csv")
head(newdata)

We observe a new line is inserted with the header labels X, X.1, ... and that the true column headers are shifted down. This is because of the empty line in the original dataset. To account for this detail we must skip one line when reading the file.

newdata = read.csv(file="creditriskorg1.csv",skip=1) 
head(newdata)

Next we want to extract the Checking column and then find the average of checking, smilar to what we did in the previous lab. When we try to execute the code chunk below notice that we get an error.

checking = newdata$Checking # command to extract the Checking column from the data file newdata
mean(checking)
argument is not numeric or logical: returning NA
[1] NA

To resolve the error, we must understand first where it’s source. There are missing values in the csv file represented by the symbol $-. Missing data is quite common as most datasets are not perfect. Additionally, there are commas within the excel spreadsheet, and R does not recognize that ‘1,234’ is equivalent to ‘1234’. Lastly, there are ‘$’ symbols throughout the file which is not a numerical symbol either.

To correct for the error we need to do some data cleanup. For this we will use the sub function sub() in R to replace unwanted symbols with something else. For example, in order to remove the comma in the number “1,234”, we can substitute it with blank. Below is a sequence of commands to help with the cleanup of the data in the Checking column and eventual calculation of the mean.

#substitute comma with blank in all of checking  
checking= sub(",","",checking)

#substitute dollar sign with blank in all of checking 
# Example new = sub("\\$","",new)
checking = sub("\\$","",checking)

#Convert values to numeric. Any value that cannot be converted to numeric will be designated as NA (Not Applicable)
checking = as.numeric(checking)

#Calculate mean of checking with all NAs removed 
mean(checking,na.rm=TRUE)
[1] 2559.805

##### 2A) Repeat the above commands to calculate the mean of the Savings column instead. Use a different variable naming (2pts)





Savings = newdata$Savings
#substitute comma with blank in all of Savings  
Savings = sub(",","",Savings)

#substitute dollar sign with blank in all of Savings 
# Example new = sub("\\$","",new)
Savings = sub("\\$","",Savings)

#Convert values to numeric. Any value that cannot be converted to numeric will be designated as NA (Not Applicable)
Savings = as.numeric(Savings)
NAs introduced by coercion
#Calculate mean of Savings with all NAs removed 
mean(Savings,na.rm = TRUE)
[1] 2122.146
mean(Savings,na.rm = TRUE)
[1] 2122.146

##### 2B) Calculate now the mean of the Checking column in Excel using the Excel function Average. Compare the two results, from Excel and R and share your observation (2pts)

The mean of the Excel file is $2559.805. The R mean of checking and the excel mean are the same number. R was unfamiliar with the formatting of the data, with commas and dollar signs. This may be because the data was imported, and R may not be familiar with the formatting styles. Therefore, we had to clean the data to be used. However, excel can manipulate the numbers to be easily analyzed. This may be because it is designed to do this, and can work around the formatting.

##### 2C) Based on your observation how did Excel treat the missing values represented by the symbol $-? Are they included in the calculation of the mean or excluded? Explain your answer (2pts)

Excel excluded the missing values. This conclusion can be drawn because R and excel calculated the same mean. Since R excluded the missing data, excel must have too. I am concluding this because they must have calculated the same mean by using the same procedures. Also, if excel included the missing values, there would be an error, or a lower mean if excel deemed them to have a value of zero.


Task 3: Data Modeling

```

Here, we will look at Chicago Divvy bike data. The historical data sets with description of fields can be found at:

Chicago Divvy Data: https://www.divvybikes.com/data

First you need to download the archived (zipped) ‘Divvy_Trips_2019_Q3.zip' file. Once downlaoded you should unarchive (unzip) the file to extract its content. You will then obtain the corresponding file `Divvy_Trips_2019_Q3.csv’ file. The file is relatively big in size, and you will quickly come to appreciate some of the challenges working with big data files using Excel.

###### 3A) Open in RStudio or Excel the file Divvy_Trips_2019_Q3.csv. What is the size of the file (measured in bytes), the number of columns and of rows?. Identify the column field(s) in the data that is/are unique identifier(s) (cannot have duplicate/repeated values) (2pts) The size of the file is 215MB (215,000,000 bytes). The number of columns is 12 The number of rows is 1,048,576 Unique Identifiers: trip_id

###### 3B) Looking at the Divvy bike data define two business rules: one for field integrity, and one for relationship integrity. (2pts)

field integrity: gender cannot be numerical relationship integrity: end_time cannot be before start time

###### 3C) Using https://erdplus.com/#/standalone draw a star like schema using the below three tables. Include an image capture of your schema here (4pts) #####

  • A Fact table for Trips
  • A Dimension table for Stations
  • A Dimension table for Users SEE THE TOP OF THE LAB
LS0tDQp0aXRsZTogIkRhdGEgUHJlcGFyYXRpb24gJiBGbG93IChsYWIwNCkiDQphdXRob3I6ICJMYXVyZW4gS3JvbGwiDQpkYXRlOiAiMi8xMy8yMDIwIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCnN1YnRpdGxlOiBCU0FEIDM0M0gsIEJ1c2luZXNzIEFuYWx5dGljcywgU3ByaW5nIDIwMjANCi0tLQ0KIVtdKGRpdnZ5LnBuZykNCiMjIyBBYm91dA0KDQpUaGlzIHdvcmtzaGVldCBpbmNsdWRlcyB0aHJlZSBtYWluIHRhc2tzIG9uIGRhdGEgb3V0bGllcnMsIGRhdGEgcHJlcGFyYXRpb24sIGFuZCBkYXRhIG1vZGVsaW5nLiBUaGUgbGFiIHJlcXVpcmVzIHRoZSB1c2Ugb2YgTWljcm9zb2Z0IEV4Y2VsLCBSLCBhbmQgRVJEcGx1cy4NCg0KIyMjIFNldHVwDQoNClJlbWVtYmVyIHRvIGFsd2F5cyBzZXQgeW91ciB3b3JraW5nIGRpcmVjdG9yeSB0byB0aGUgc291cmNlIGZpbGUgbG9jYXRpb24uIEdvIHRvICdTZXNzaW9uJywgc2Nyb2xsIGRvd24gdG8gJ1NldCBXb3JraW5nIERpcmVjdG9yeScsIGFuZCBjbGljayAnVG8gU291cmNlIEZpbGUgTG9jYXRpb24nLiBSZWFkIGNhcmVmdWxseSB0aGUgYmVsb3cgYW5kIGZvbGxvdyB0aGUgaW5zdHJ1Y3Rpb25zIHRvIGNvbXBsZXRlIHRoZSB0YXNrcyBhbmQgYW5zd2VyIGFueSBxdWVzdGlvbnMuICBTdWJtaXQgeW91ciB3b3JrIGluIFNha2FpIGFzIGRldGFpbGVkIGluIHByZXZpb3VzIG5vdGVzLiANCg0KIyMjIE5vdGUNCg0KRm9yIHlvdXIgYXNzaWdubWVudCB5b3UgbWF5IGJlIHVzaW5nIGRpZmZlcmVudCBkYXRhIHNldHMgdGhhbiB3aGF0IGlzIGluY2x1ZGVkIGhlcmUuIEFsd2F5cyByZWFkIGNhcmVmdWxseSB0aGUgaW5zdHJ1Y3Rpb25zIHByb3ZpZGVkLCBiZWZvcmUgZXhlY3V0aW5nIGFueSBpbmNsdWRlZCBjb2RlIGNodW5rcyBhbmQvb3IgYWRkaW5nIHlvdXIgb3duIGNvZGUuICBGb3IgY2xhcml0eSwgdGFza3MvcXVlc3Rpb25zIHRvIGJlIGNvbXBsZXRlZC9hbnN3ZXJlZCBhcmUgaGlnaGxpZ2h0ZWQgaW4gcmVkIGNvbG9yIGFuZCBudW1iZXJlZCBhY2NvcmRpbmcgdG8gdGhlaXIgcGFydGljdWxhciBwbGFjZW1lbnQgaW4gdGhlIHRhc2sgc2VjdGlvbi4gIFRoZSByZWQgY29sb3IgaXMgb25seSBhcHBhcmVudCB3aGVuIGluIFByZXZpZXcgbW9kZS4gUXVpdGUgb2Z0ZW4geW91IHdpbGwgbmVlZCB0byBhZGQgeW91ciBvd24gY29kZSBjaHVuay4NCg0KRXhlY3V0ZSBhbGwgY29kZSBjaHVua3MgKGFscmVhZHkgaW5jbHVkZWQgYW5kIG93biBhZGRlZCksIHByZXZpZXcsIGNoZWNrIGludGVncml0eSwgYW5kIHN1Ym1pdCBmaW5hbCB3b3JrICgkaHRtbCQgZmlsZSkgaW4gU2FrYWkuDQoNCi0tLS0tLS0tLS0tLS0tDQoNCiMjIyBUYXNrIDE6IERhdGEgT3V0bGllcnMNCg0KRmlyc3QsIHdlIG11c3QgY2FsY3VsYXRlIHRoZSBtZWFuLCBzdGFuZGFyZCBkZXZpYXRpb24sIG1heGltdW0sIGFuZCBtaW5pbXVtIGZvciB0aGUgQWdlIGNvbHVtbiB1c2luZyBSLg0KDQpJbiBSLCB3ZSBtdXN0IHJlYWQgaW4gdGhlIGZpbGUgYWdhaW4sIGV4dHJhY3QgdGhlIGNvbHVtbiBhbmQgZmluZCB0aGUgdmFsdWVzIHRoYXQgYXJlIGFza2VkIGZvci4NCg0KYGBge3IgfQ0KI1JlYWQgRmlsZQ0KbXlkYXRhID0gcmVhZC5jc3YoZmlsZT0iY3JlZGl0cmlzay5jc3YiKSANCg0KI05hbWUgdGhlIGV4dHJhY3RlZCB2YXJpYWJsZQ0KYWdlID0gbXlkYXRhJEFnZSANCmBgYA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFBKSBGaWxsIGluIHRoZSBjb2RlIGNodW5rIGJlbG93IHRvIGNhbGN1bGF0ZSBhbmQgZGlzcGxheSBlYWNoIHJlc3VsdC4gIFJlZmVyIHRvIHByZXZpb3VzIHdvcmtzaGVldHMgYW5kIG9uLWxpbmUgaGVscCBmb3Igc29tZSBjb21tYW5kcyAoMnB0cykNCjwvc3Bhbj4NCg0KYGBge3J9DQoNCiNDYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgYWdlIA0KbWVhbihhZ2UpDQoNCiNDYWxjdWxhdGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBhZ2UgDQpzZChhZ2UpDQoNCg0KI0NhbGN1bGF0ZSB0aGUgbWF4aW1hIG9mIGFnZS4gIFNlYXJjaCBpbiBIZWxwIHRvIGZpbmQgdGhlIHJpZ2h0IGNvbW1hbmQgZm9yIG1heGltYQ0KbWF4KGFnZSkNCg0KI0NhbGN1bGF0ZSB0aGUgbWluaW1hIG9mIGFnZS4gIFNlYXJjaCBpbiBIZWxwIHRvIGZpbmQgdGhlIHJpZ2h0IGNvbW1hbmQgZm9yIG1pbmltYQ0KbWluKGFnZSkNCg0KYGBgDQoNCk5leHQsIHdlIHdpbGwgdXNlIHRoZSBmb3JtdWxhIGZyb20gY2xhc3MgdG8gZGV0ZWN0IGFueSBvdXRsaWVycy4gQW4gb3V0bGllciBpcyBhIHZhbHVlIHRoYXQgImxpZXMgb3V0c2lkZSIgbW9zdCBvZiB0aGUgb3RoZXIgdmFsdWVzIGluIGEgc2V0IG9mIGRhdGEuIEEgY29tbW9uIHdheSB0byBlc3RpbWF0ZSB0aGUgdXBwZXIgYW5kIGxvd2VyIGxpbWl0cyBpcyB0byB0YWtlIHRoZSBgYGBtZWFuICgrIG9yIC0pIDMgKiBzdGFuZGFyZCBkZXZpYXRpb25gYGAuICANCg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFCKSBJbnNlcnQgYW5kIGV4ZWN1dGUgdGhlIGNvZGUgY2h1bmsgY29ycmVzcG9uZGluZyB0byB0aGUgYWJvdmUgZm9ybXVsYSB0byBjYWxjdWxhdGUgdGhlIHVwcGVyIGFuZCBsb3dlciBsaW1pdHMgZm9yIGFnZS4gU2hvdyB5b3VyIHJlc3VsdHMuIEJhc2VkIG9uIHRoZSBsaW1pdHMgZG8geW91IHRoaW5rIHRoZXJlIGFyZSBvdXRsaWVycz8gRXhwbGFpbiB5b3VyIGxvZ2ljICgycHRzKQ0KDQpZZXMsIGluIHRoaXMgY2FzZSwgYW4gb3V0bGllciBpcyBkZXNjcmliZWQgYXMgYSB2YWx1ZSArIG9yIC0gMyBzdGFuZGFyZCBkZXZpYXRpb25zIGZyb20gdGhlIG1lYW4uIFRoaXMgbWVhbnMgdGhlIHVwcGVyIGxpbWl0IGlzIDY3LjUgeWVhcnMgb2xkLCBhbmQgdGhlIGxvd2VyIGxpbWl0IGlzIDEuMyB5ZWFycyBvbGQuVGhlcmUgYXJlIG91dGxpZXJzIGJlY2F1c2UgdGhlcmUgYXJlIHBlb3BsZSBhZ2VkIG1vcmUgdGhlYW4gNjcuNSB5ZWFycyBvbGQsIHdoaWNoIGlzIGdyZWF0ZXIgdGhhbiB0aGUgdXBwZXIgbGltaXQuICBUaGVyZSBpcyBzb21lb25lIGFnZWQgNzMsIGFuZCB0aGlzIGlzIG1vcmUgdGhhbiAzIHN0YW5kYXJkIGRldmlhdGlvbnMgYXdheSBmcm9tIHRoZSBtZWFuLCBhbmQgdGhpcyBkZWZpbmVzIGFuIG91dGxpZXIuDQoNCmBgYHtyfQ0KI1VwcGVyIGxpbWl0DQptZWFuKGFnZSkrc2QoYWdlKSozDQoNCiNMb3dlciBMaW1pdA0KbWVhbihhZ2UpLXNkKGFnZSkqMw0KDQpgYGANCg0KPC9zcGFuPg0KDQpBbm90aGVyIG1ldGhvZCB0byBmaW5kIHRoZSB1cHBlciBhbmQgbG93ZXIgdGhyZXNob2xkcywgZGlzY3Vzc2VkIGluIG1hbnkgaW50cm9kdWN0b3J5IHN0YXRpc3RpY3MgY291cnNlcywgcmVxdWlyZXMgY2FsY3VsYXRpbmcgdGhlIGludGVycXVhcnRpbGUgcmFuZ2UuIEZvbGxvdyBhbG9uZyBiZWxvdyB0byBzZWUgaG93IHdlIGZpcnN0IGNhbGN1bGF0ZSB0aGUgaW50ZXJxdWFydGlsZSByYW5nZS4uIA0KDQpgYGB7cn0gDQpxdWFudGlsZShhZ2UpIA0KbG93ZXJxID0gcXVhbnRpbGUoYWdlKVsyXQ0KdXBwZXJxID0gcXVhbnRpbGUoYWdlKVs0XQ0KaXFyID0gdXBwZXJxIC0gbG93ZXJxDQpgYGANCg0KTmV4dCB3ZSBjYWxjdWxhdGUgdGhlIGxpbWl0aW5nIHRocmVzaG9sZHMuIEEgdGhyZXNob2xkIGhlcmUgaXMgdGhlIGJvdW5kYXJ5IHRoYXQgZGV0ZXJtaW5lcyBpZiBhIHZhbHVlIGlzIGFuIG91dGxpZXIuIElmIHRoZSB2YWx1ZSBmYWxscyBhYm92ZSB0aGUgdXBwZXIgdGhyZXNob2xkIG9yIGJlbG93IHRoZSBsb3dlciB0aHJlc2hvbGQsIGl0IGlzIGFuIG91dGxpZXIuIA0KDQpUbyBjYWxjdWxhdGUgdGhlIHVwcGVyIHRocmVzaG9sZDoNCmBgYHtyfSANCnVwcGVydGhyZXNob2xkID0gKGlxciAqIDEuNSkgKyB1cHBlcnEgDQp1cHBlcnRocmVzaG9sZA0KYGBgDQoNCkJlbG93IGlzIHRoZSBsb3dlciB0aHJlc2hvbGQ6DQpgYGB7cn0NCmxvd2VydGhyZXNob2xkID0gbG93ZXJxIC0gKGlxciAqIDEuNSkNCmxvd2VydGhyZXNob2xkDQpgYGANCg0KQSBnb29kIHdheSB0byB1bmRlcnRzYW5kIHRoZSBhYm92ZSBjYWxjdWxhdGlvbnMgaXMgdG8gdmlzdWFsaXplIHRoZSByZXN1bHRzIHVzaW5nIGEgYm94IGFuZCB3aGlza2VyIHBsb3QuIFRoZSB0b3AgYW5kIGxvd2VyIGVuZHMgb2YgdGhlIGJveCBjb3JyZXNwb25kIHRvIHRoZSB1cHBlciBhbmQgbG93ZXIgcXVhcnRpbGVzLiBUaGUgbWVkaWFuIGlzIG1hcmtlZCBieSBhIGJvbGRlZCBsaW5lLiBUaGUgd2hpc2tlcnMgYXJlIHRoZSBsaW5lcyBjb25uZWN0aW5nIHRoZSB1cHBlciBhbmQgbG93ZXIgcXVhcnRpbGVzIHRvIHVwcGVyIGFuZCBsb3dlciB0aHJlc2hvbGRzLiBBbnkgcG9pbnRzIGJleW9uZCB0aGUgdGhyZXNob2xkcyBpcyBhIHBvdGVudGlhbCBvdXRsaWVyLg0KDQpgYGB7cn0gDQpib3hwbG90KGFnZSkgDQpgYGANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAxQykgRnJvbSB0aGUgYm94IHBsb3QgcmVwcmVzZW50YXRpb24gYXJlIHRoZXJlIGFueSBvdXRsaWVycz8gSG93IG1hbnkgY2FuIHlvdSBjb3VudD8gSG93IGRvZXMgeW91ciBhbnN3ZXIgcmVjb25jaWxlIHdpdGggdGhlIHJlc3VsdCBmcm9tIFRhc2sgMUI/DQooMnB0cykNCg0KVGhlIEJveCBwbG90IHNob3dzIDUgZGlmZmVyZW50IGFnZXMgT3V0bGllcnMuDQpMb29raW5nIGF0IHRoZSBleGNlbCBzaGVldCwgdGhlcmUgYXJlIDkgb3V0bGllcnMgdG90YWwgKDczLDY3LDY3LCA2NiwgNjUsIDY1LCA2NSwgNjQsIDY0KS4gSW4gYWxsLCB0aGVyZSBhcmUgNSBkaWZmZXJudCBhZ2VzIGFzIG91dGxpZXJzLCAoNzMsIDY3LCA2NiwgNjUsIGFuZCA2NCkuIFRoaXMgcmVjb25jaWxlcyB0aGUgYWdlcyB0aGF0IGFyZSBjb25zaWRlcmVkIG91dGxpZXJzIGluIGV4Y2VsIGFuZCBpbiB0aGUgQm94IFBsb3QuDQo8L3NwYW4+DQoNCg0KIyMjIyMgVGhlIGZvbGxvd2luZyBpcyBhbiBvcHRpb25hbCBjaGFsbGVuZ2UgcXVlc3Rpb24uIFRvIGFuc3dlciwgeW91IHdpbGwgbmVlZCB0byBjb25zaWRlciB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhbmQgYSBjb3JyZXNwb25kaW5nIGhpc3RvZ3JhbS4gSXQgd2lsbCBjb3VudCBhcyAyIGV4dHJhIHBvaW50cyBpbnN0ZWFkIG9mIHRoZSBzZWNvbmQgcG9wIHF1aXouICANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAxQycpIExvb2tpbmcgYXQgdGhlIHR3byBtZXRob2RzIG9mIGNhbGN1bGF0aW9ucyB0byBpZGVudGlmeSBvdXRsaWVycyBpbiAxQSkgYW5kIDFCKSAsIGV4cGxhaW4gaG93IHRoZXkgZGlmZmVyIGFuZCBhbHNvIGhvdyB0aGV5IHJlY29uY2lsZSAoMnB0cyBleHRyYSkNCg0KDQpXZSB1c2VkIHR3byBkaWZmZXJlbnQgbWV0aG9kcyB0byBjYWxjdWxhdGUgb3V0bGllcnMuVGhlIGZpcnN0LCB3YXMgdXNpbmcgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGN1cnZlLiAgT3V0bGllcnMgYXJlIGRlZmluZWQgYXMgYW55dGhpbmcgb3V0c2lkZSBvZiB0aGUgdXBwZXIgYW5kIGxvd2VyIGxpbWl0cyBmb3VuZCAobWVhbiArIDMgc3RhbmRhcmQgZGV2aWF0aW9ucyBvciBtZWFuIC0gMyBzdGFuZGFyZCBkZXZpYXRpb25zKS4gSW4gdGhpcyBjYWxjdWxhdGlvbiwgYWJvdXQgOTkuNyUgb2YgdGhlIGRhdGEgaXMgd2l0aGluIDMgc3RhbmRhcmQgZGV2aWF0aW9ucywgYW5kIGFib3V0IC4zJSBpcyBvdXRzaWRlIG9mIHRoaXMgcmFuZ2UsIG1lYW5pbmcgaXQgaXMgYW4gb3V0bGllci4gDQpUaGUgc2Vjb25kIG1ldGhvZCBpcyB1c2luZyBoaXN0b2dyYW0uIFRoaXMgbWV0aG9kIHVzZXMgdGhlIGludGVycXVhcnRpbGUgcmFuZ2UgKElRUikgdG8gY2FsY3VsYXRlIG91dGxpZXJzLiBUaGUgSVFSIGFjY291bnRzIGZvciB0aGUgbWlkZGxlIDUwJSBvZiB0aGUgZGF0YSwgYW5kIGl0IHRha2VzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHRvcCA3NXRoIHBlcmNlbnRpbGUgZGF0YSAoUTMpIGFuZCB0aGUgMjV0aCBwZXJjZW50aWxlIChRMSkgZGF0YS4gIFRoaXMgaXMgdGhlbiBtdWx0aXBsaWVkIGJ5IDEuNSwgYW5kIGVpdGhlciBhZGRlZCBvciBzdWJ0cmFjdGVkIGZyb20gdGhlIElRUiB0byBmaW5kIHRoZSB1cHBlciBvciBsb3dlciBsaW1pdHMgZm9yIG91dGxpZXJzLg0KDQpSZWNvbmNpbGUgb2YgaGlzdG9ncmFtIGFuZCBub3JtYWwgZGlzdHJpYnV0aW9uIG91dGxpZXJzOg0KYSB6LXNjb3JlIG9mIC0uNjcgaXMgdGhlIDI1dGggcGVyY2VudGlsZSBvZiBkYXRhIChRMSkgYW5kIGEgei1zY29yZSBvZiAuNjcgaXMgdGhlIDc1dGggcGVyY2VudGlsZSBvZiBkYXRhIChRMykNCmBgYHtyfQ0KI1JlYWQgRmlsZQ0KbXlkYXRhID0gcmVhZC5jc3YoZmlsZT0iY3JlZGl0cmlzay5jc3YiKSANCg0KI05hbWUgdGhlIGV4dHJhY3RlZCB2YXJpYWJsZQ0KYWdlID0gbXlkYXRhJEFnZQ0KYGBgDQoNCmBgYHtyfQ0KbWVhbihhZ2UpDQpzZChhZ2UpDQpgYGANCmBgYHtyfQ0KI1ExICh6PS0uNjcpDQojIHogPSAgKHggLSB4YmFyICkvIHNwcmVhZA0KIyBjaGFuZ2UgZXF1YXRpb24gdG8gZWFzaWx5IHNvbHZlIHoqcyArIHhiYXIgPSB4DQojIGlmIHo9IC0uNjcsIHRoaXMgaXMgUTENCnogPSAtLjY3DQp5ID0gbWVhbihhZ2UpDQpzID0gc2QoYWdlKQ0KeipzICsgeQ0KDQpgYGANCkluIHRoZSBoaXN0b2dyYW0sIFExIGlzIDI2LiBUaGlzIHJlY29uY2lsZXMgdG8gdGhlIFExIGZvdW5kIHVzaW5nIHotc2NvcmVzLiBPYnZpb3VzbHkgdGhlcmUgaXMgYSByb3VuZGluZyBlcnJvci4NCjwvc3Bhbj4NCg0KYGBge3J9DQojUTMgKHo9LjY3KQ0KIyB6ID0gICh4IC0geGJhciApLyBzcHJlYWQNCiMgY2hhbmdlIGVxdWF0aW9uIHRvIGVhc2lseSBzb2x2ZSB6KnMgKyB4YmFyID0geA0KIyBpZiB6PSAtLjY3LCB0aGlzIGlzIFExDQp6ID0gLjY3DQp5ID0gbWVhbihhZ2UpDQpzID0gc2QoYWdlKQ0KeipzICsgeQ0KYGBgDQpJbiB0aGUgaGlzdG9ncmFtLCBRMyBpcyA0MSwgd2hpY2ggaXMgdmVyeSBjbG9zZSB0byB0aGUgUTMgZm91bmQgdXNpbmcgei1zY29yZXMuICBUaGlzIGlzIGEgcm91bmRpbmcgZXJyb3IgYXdheS4NCg0KYGBge3J9DQojU29sdmUgZm9yIElRUg0KNDEuNzk3ODg4LTI2Ljk5NzQxDQoNCg0KYGBgDQpgYGB7cn0NCiNzb2x2ZSBmb3IgbG93ZXIgbGltaXQNCjI2Ljk5NzQxLSgxNC44MDA0OCoxLjUpDQpgYGANCmBgYHtyfQ0KI3NvbHZlIGZvciB1cHBlciBsaW1pdA0KNDEuNzk3ODg4KygxNC44MDA0OCoxLjUpDQpgYGANClVuZGVyIHRoZXNlIGNhbGN1bGF0aW9ucywgYW55dGhpbmcgb3ZlciA2My45OTg2MSBpcyBhbiBvdXRsaWVyLCBjb21wYXJlZCB0byB0aGUgNjMuNSBvdXRsaWVyIHVwcGVyIHJhbmdlIGNhbGN1bGF0ZWQgZnJvbSB0aGUgaGlzdG9ncmFtLiBUaGVzZSBhcmUgdmVyeSBjbG9zZSwgYnV0IHRoZXkgdmFyeSBmcm9tIHJvdW5kaW5nIGVycm9ycy4NCkFueXRoaW5nIHVuZGVyIDQuNzk2NjkgaXMgYW4gb3V0bGllciwgY29tcGFyZWQgdG8gdGhlIDMuNSBmcm9tIHRoZSBoaXN0b2dyYW0uIEFnYWluLCB0aGlzIG51bWJlciB2YXJpZXMgc2xpZ2h0bHkgZnJvbSB0aGUgcm91bmRpbmcgZXJyb3JzLiANClRoaXMgaXMgdGhlIHJlY29uY2lsaW5nIG9mIHRoZSBoaXN0b2dyYW0gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBjYWxjdWxhdGlvbnMgb2YgdGhlIG91dGxpZXJzLg0KLS0tLS0tLS0tLS0tLS0tDQoNCiMjIyBUYXNrIDI6IERhdGEgUHJlcGFyYXRpb24NCg0KTmV4dCwgd2Ugd2lsbCByZWFkIHRoZSBmaWxlIGBjcmVkaXRyaXNrb3JnLmNzdmAgaW50byBSIGFzIHByb3ZpZGVkIGluIGl0cyBvcmlnaW5hbCBmb3JtLiBVbmxpa2UgdGhlIGNsZWFuZWQgZmlsZSBgY3JlZGl0cmlzay5jc3ZgLCB0aGUgb3JpZ2luYWwgZGF0YXNldCB3aWxsIHJlcXVpcmUgc29tZSBkYXRhIHByZXBhcmF0aW9uLiAgDQoNCmBgYHtyfQ0KbmV3ZGF0YSA9IHJlYWQuY3N2KGZpbGU9ImNyZWRpdHJpc2tvcmcxLmNzdiIpDQpoZWFkKG5ld2RhdGEpDQpgYGANCg0KV2Ugb2JzZXJ2ZSBhIG5ldyBsaW5lIGlzIGluc2VydGVkIHdpdGggdGhlIGhlYWRlciBsYWJlbHMgYFgsIFguMSwgLi4uYCBhbmQgdGhhdCB0aGUgdHJ1ZSBjb2x1bW4gaGVhZGVycyBhcmUgc2hpZnRlZCBkb3duLiAgVGhpcyBpcyBiZWNhdXNlIG9mIHRoZSBlbXB0eSBsaW5lIGluIHRoZSBvcmlnaW5hbCBkYXRhc2V0LiBUbyBhY2NvdW50IGZvciB0aGlzIGRldGFpbCB3ZSBtdXN0IHNraXAgb25lIGxpbmUgd2hlbiByZWFkaW5nIHRoZSBmaWxlLg0KDQpgYGB7cn0gDQpuZXdkYXRhID0gcmVhZC5jc3YoZmlsZT0iY3JlZGl0cmlza29yZzEuY3N2Iixza2lwPTEpIA0KaGVhZChuZXdkYXRhKQ0KYGBgDQoNCk5leHQgd2Ugd2FudCB0byBleHRyYWN0IHRoZSBDaGVja2luZyBjb2x1bW4gYW5kIHRoZW4gZmluZCB0aGUgYXZlcmFnZSBvZiBjaGVja2luZywgc21pbGFyIHRvIHdoYXQgd2UgZGlkIGluIHRoZSBwcmV2aW91cyBsYWIuICBXaGVuIHdlIHRyeSB0byBleGVjdXRlIHRoZSBjb2RlIGNodW5rIGJlbG93IG5vdGljZSB0aGF0IHdlIGdldCBhbiBlcnJvci4NCg0KYGBge3J9IA0KY2hlY2tpbmcgPSBuZXdkYXRhJENoZWNraW5nICMgY29tbWFuZCB0byBleHRyYWN0IHRoZSBDaGVja2luZyBjb2x1bW4gZnJvbSB0aGUgZGF0YSBmaWxlIG5ld2RhdGENCm1lYW4oY2hlY2tpbmcpDQpgYGANCg0KVG8gcmVzb2x2ZSB0aGUgZXJyb3IsIHdlIG11c3QgdW5kZXJzdGFuZCBmaXJzdCB3aGVyZSBpdCdzIHNvdXJjZS4gVGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzIGluIHRoZSBjc3YgZmlsZSByZXByZXNlbnRlZCBieSB0aGUgc3ltYm9sIGAkLWAuIE1pc3NpbmcgZGF0YSBpcyBxdWl0ZSBjb21tb24gYXMgbW9zdCBkYXRhc2V0cyBhcmUgbm90IHBlcmZlY3QuIEFkZGl0aW9uYWxseSwgdGhlcmUgYXJlIGNvbW1hcyB3aXRoaW4gdGhlIGV4Y2VsIHNwcmVhZHNoZWV0LCBhbmQgUiBkb2VzIG5vdCByZWNvZ25pemUgdGhhdCAnMSwyMzQnIGlzIGVxdWl2YWxlbnQgdG8gJzEyMzQnLiBMYXN0bHksIHRoZXJlIGFyZSAnJCcgc3ltYm9scyB0aHJvdWdob3V0IHRoZSBmaWxlIHdoaWNoIGlzIG5vdCBhIG51bWVyaWNhbCBzeW1ib2wgZWl0aGVyLg0KDQpUbyBjb3JyZWN0IGZvciB0aGUgZXJyb3Igd2UgbmVlZCB0byBkbyBzb21lIGRhdGEgY2xlYW51cC4gRm9yIHRoaXMgd2Ugd2lsbCB1c2UgdGhlIHN1YiBmdW5jdGlvbiBgc3ViKClgIGluIFIgdG8gcmVwbGFjZSB1bndhbnRlZCBzeW1ib2xzIHdpdGggc29tZXRoaW5nIGVsc2UuIEZvciBleGFtcGxlLCBpbiBvcmRlciB0byByZW1vdmUgdGhlIGNvbW1hIGluIHRoZSBudW1iZXIgIjEsMjM0Iiwgd2UgY2FuIHN1YnN0aXR1dGUgaXQgd2l0aCBibGFuay4gQmVsb3cgaXMgYSBzZXF1ZW5jZSBvZiBjb21tYW5kcyB0byBoZWxwIHdpdGggdGhlIGNsZWFudXAgb2YgdGhlIGRhdGEgaW4gdGhlIENoZWNraW5nIGNvbHVtbiBhbmQgZXZlbnR1YWwgY2FsY3VsYXRpb24gb2YgdGhlIG1lYW4uDQoNCmBgYHtyfSANCiNzdWJzdGl0dXRlIGNvbW1hIHdpdGggYmxhbmsgaW4gYWxsIG9mIGNoZWNraW5nICANCmNoZWNraW5nPSBzdWIoIiwiLCIiLGNoZWNraW5nKQ0KDQojc3Vic3RpdHV0ZSBkb2xsYXIgc2lnbiB3aXRoIGJsYW5rIGluIGFsbCBvZiBjaGVja2luZyANCiMgRXhhbXBsZSBuZXcgPSBzdWIoIlxcJCIsIiIsbmV3KQ0KY2hlY2tpbmcgPSBzdWIoIlxcJCIsIiIsY2hlY2tpbmcpDQoNCiNDb252ZXJ0IHZhbHVlcyB0byBudW1lcmljLiBBbnkgdmFsdWUgdGhhdCBjYW5ub3QgYmUgY29udmVydGVkIHRvIG51bWVyaWMgd2lsbCBiZSBkZXNpZ25hdGVkIGFzIE5BIChOb3QgQXBwbGljYWJsZSkNCmNoZWNraW5nID0gYXMubnVtZXJpYyhjaGVja2luZykNCg0KI0NhbGN1bGF0ZSBtZWFuIG9mIGNoZWNraW5nIHdpdGggYWxsIE5BcyByZW1vdmVkIA0KbWVhbihjaGVja2luZyxuYS5ybT1UUlVFKQ0KYGBgDQoNCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPg0KIyMjIyMgMkEpIFJlcGVhdCB0aGUgYWJvdmUgY29tbWFuZHMgdG8gY2FsY3VsYXRlIHRoZSBtZWFuIG9mIHRoZSBTYXZpbmdzIGNvbHVtbiBpbnN0ZWFkLiBVc2UgYSBkaWZmZXJlbnQgdmFyaWFibGUgbmFtaW5nICgycHRzKQ0KDQpgYGB7cn0NCg0KDQoNCg0KU2F2aW5ncyA9IG5ld2RhdGEkU2F2aW5ncw0KI3N1YnN0aXR1dGUgY29tbWEgd2l0aCBibGFuayBpbiBhbGwgb2YgU2F2aW5ncyAgDQpTYXZpbmdzID0gc3ViKCIsIiwiIixTYXZpbmdzKQ0KDQojc3Vic3RpdHV0ZSBkb2xsYXIgc2lnbiB3aXRoIGJsYW5rIGluIGFsbCBvZiBTYXZpbmdzIA0KIyBFeGFtcGxlIG5ldyA9IHN1YigiXFwkIiwiIixuZXcpDQpTYXZpbmdzID0gc3ViKCJcXCQiLCIiLFNhdmluZ3MpDQoNCiNDb252ZXJ0IHZhbHVlcyB0byBudW1lcmljLiBBbnkgdmFsdWUgdGhhdCBjYW5ub3QgYmUgY29udmVydGVkIHRvIG51bWVyaWMgd2lsbCBiZSBkZXNpZ25hdGVkIGFzIE5BIChOb3QgQXBwbGljYWJsZSkNClNhdmluZ3MgPSBhcy5udW1lcmljKFNhdmluZ3MpDQoNCiNDYWxjdWxhdGUgbWVhbiBvZiBTYXZpbmdzIHdpdGggYWxsIE5BcyByZW1vdmVkIA0KbWVhbihTYXZpbmdzLG5hLnJtID0gVFJVRSkNCmBgYA0KYGBge3J9DQptZWFuKFNhdmluZ3MsbmEucm0gPSBUUlVFKQ0KYGBgDQoNCg0KPC9zcGFuPg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDJCKSBDYWxjdWxhdGUgbm93IHRoZSBtZWFuIG9mIHRoZSBDaGVja2luZyBjb2x1bW4gaW4gRXhjZWwgdXNpbmcgdGhlIEV4Y2VsIGZ1bmN0aW9uIGBBdmVyYWdlYC4gQ29tcGFyZSB0aGUgdHdvIHJlc3VsdHMsIGZyb20gRXhjZWwgYW5kIFIgYW5kIHNoYXJlIHlvdXIgb2JzZXJ2YXRpb24gKDJwdHMpDQoNCg0KVGhlIG1lYW4gb2YgdGhlIEV4Y2VsIGZpbGUgaXMgJDI1NTkuODA1LiAgVGhlIFIgbWVhbiBvZiBjaGVja2luZyBhbmQgdGhlIGV4Y2VsIG1lYW4gYXJlIHRoZSBzYW1lIG51bWJlci4gIFIgd2FzIHVuZmFtaWxpYXIgd2l0aCB0aGUgZm9ybWF0dGluZyBvZiB0aGUgZGF0YSwgd2l0aCBjb21tYXMgYW5kIGRvbGxhciBzaWducy4gVGhpcyBtYXkgYmUgYmVjYXVzZSB0aGUgZGF0YSB3YXMgaW1wb3J0ZWQsIGFuZCBSIG1heSBub3QgYmUgZmFtaWxpYXIgd2l0aCB0aGUgZm9ybWF0dGluZyBzdHlsZXMuICBUaGVyZWZvcmUsIHdlIGhhZCB0byBjbGVhbiB0aGUgZGF0YSB0byBiZSB1c2VkLiBIb3dldmVyLCBleGNlbCBjYW4gbWFuaXB1bGF0ZSB0aGUgbnVtYmVycyB0byBiZSBlYXNpbHkgYW5hbHl6ZWQuIFRoaXMgbWF5IGJlIGJlY2F1c2UgaXQgaXMgZGVzaWduZWQgdG8gZG8gdGhpcywgYW5kIGNhbiB3b3JrIGFyb3VuZCB0aGUgZm9ybWF0dGluZy4NCjwvc3Bhbj4NCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAyQykgQmFzZWQgb24geW91ciBvYnNlcnZhdGlvbiBob3cgZGlkIEV4Y2VsIHRyZWF0IHRoZSBtaXNzaW5nIHZhbHVlcyByZXByZXNlbnRlZCBieSB0aGUgc3ltYm9sIGAkLWA/IEFyZSB0aGV5IGluY2x1ZGVkIGluIHRoZSBjYWxjdWxhdGlvbiBvZiB0aGUgbWVhbiBvciBleGNsdWRlZD8gIEV4cGxhaW4geW91ciBhbnN3ZXIgKDJwdHMpDQoNCg0KRXhjZWwgZXhjbHVkZWQgdGhlIG1pc3NpbmcgdmFsdWVzLiBUaGlzIGNvbmNsdXNpb24gY2FuIGJlIGRyYXduIGJlY2F1c2UgUiBhbmQgZXhjZWwgY2FsY3VsYXRlZCB0aGUgc2FtZSBtZWFuLiBTaW5jZSBSIGV4Y2x1ZGVkIHRoZSBtaXNzaW5nIGRhdGEsIGV4Y2VsIG11c3QgIGhhdmUgdG9vLiAgSSBhbSAgY29uY2x1ZGluZyB0aGlzIGJlY2F1c2UgdGhleSBtdXN0IGhhdmUgY2FsY3VsYXRlZCB0aGUgc2FtZSBtZWFuIGJ5IHVzaW5nIHRoZSBzYW1lIHByb2NlZHVyZXMuIEFsc28sIGlmIGV4Y2VsIGluY2x1ZGVkIHRoZSBtaXNzaW5nIHZhbHVlcywgdGhlcmUgd291bGQgYmUgYW4gZXJyb3IsIG9yIGEgbG93ZXIgbWVhbiBpZiBleGNlbCBkZWVtZWQgdGhlbSB0byBoYXZlIGEgdmFsdWUgb2YgemVyby4NCg0KLS0tLS0tLS0tLS0tLQ0KDQojIyMgVGFzayAzOiBEYXRhIE1vZGVsaW5nDQoNCg0KYGBgDQoNCg0KSGVyZSwgd2Ugd2lsbCBsb29rIGF0IENoaWNhZ28gRGl2dnkgYmlrZSBkYXRhLiBUaGUgaGlzdG9yaWNhbCBkYXRhIHNldHMgd2l0aCBkZXNjcmlwdGlvbiBvZiBmaWVsZHMgY2FuIGJlIGZvdW5kIGF0OiAgDQoNCkNoaWNhZ28gRGl2dnkgRGF0YTogW2h0dHBzOi8vd3d3LmRpdnZ5YmlrZXMuY29tL2RhdGFdKGh0dHBzOi8vd3d3LmRpdnZ5YmlrZXMuY29tL3N5c3RlbS1kYXRhKQ0KDQpGaXJzdCB5b3UgbmVlZCB0byBkb3dubG9hZCB0aGUgYXJjaGl2ZWQgKHppcHBlZCkgJ2BEaXZ2eV9Ucmlwc18yMDE5X1EzLnppcCcgZmlsZWAuICBPbmNlIGRvd25sYW9kZWQgeW91IHNob3VsZCB1bmFyY2hpdmUgKHVuemlwKSB0aGUgZmlsZSB0byBleHRyYWN0IGl0cyBjb250ZW50LiAgWW91IHdpbGwgdGhlbiBvYnRhaW4gdGhlIGNvcnJlc3BvbmRpbmcgZmlsZSBgRGl2dnlfVHJpcHNfMjAxOV9RMy5jc3YnIGZpbGUuIFRoZSBmaWxlIGlzIHJlbGF0aXZlbHkgYmlnIGluIHNpemUsIGFuZCB5b3Ugd2lsbCBxdWlja2x5IGNvbWUgdG8gYXBwcmVjaWF0ZSBzb21lIG9mIHRoZSBjaGFsbGVuZ2VzIHdvcmtpbmcgd2l0aCBiaWcgZGF0YSBmaWxlcyB1c2luZyBFeGNlbC4NCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyMgM0EpIE9wZW4gaW4gUlN0dWRpbyBvciBFeGNlbCB0aGUgZmlsZSBgRGl2dnlfVHJpcHNfMjAxOV9RMy5jc3ZgLiBXaGF0IGlzIHRoZSBzaXplIG9mIHRoZSBmaWxlIChtZWFzdXJlZCBpbiBieXRlcyksIHRoZSBudW1iZXIgb2YgY29sdW1ucyBhbmQgb2Ygcm93cz8uIElkZW50aWZ5IHRoZSBjb2x1bW4gZmllbGQocykgaW4gdGhlIGRhdGEgdGhhdCBpcy9hcmUgdW5pcXVlIGlkZW50aWZpZXIocykgKGNhbm5vdCBoYXZlIGR1cGxpY2F0ZS9yZXBlYXRlZCB2YWx1ZXMpICgycHRzKQ0KPC9zcGFuPiANClRoZSBzaXplIG9mIHRoZSBmaWxlIGlzIDIxNU1CICgyMTUsMDAwLDAwMCBieXRlcykuDQpUaGUgbnVtYmVyIG9mIGNvbHVtbnMgaXMgMTINClRoZSBudW1iZXIgb2Ygcm93cyBpcyAxLDA0OCw1NzYNClVuaXF1ZSBJZGVudGlmaWVyczogdHJpcF9pZA0KDQoNCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyMgM0IpIExvb2tpbmcgYXQgdGhlIERpdnZ5IGJpa2UgZGF0YSBkZWZpbmUgdHdvIGJ1c2luZXNzIHJ1bGVzOiBvbmUgZm9yIGZpZWxkIGludGVncml0eSwgYW5kIG9uZSBmb3IgcmVsYXRpb25zaGlwIGludGVncml0eS4gKDJwdHMpDQoNCg0KDQpmaWVsZCBpbnRlZ3JpdHk6IGdlbmRlciBjYW5ub3QgYmUgbnVtZXJpY2FsDQpyZWxhdGlvbnNoaXAgaW50ZWdyaXR5OiBlbmRfdGltZSBjYW5ub3QgYmUgYmVmb3JlIHN0YXJ0IHRpbWUNCjwvc3Bhbj4NCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyMgM0MpIFVzaW5nIFtodHRwczovL2VyZHBsdXMuY29tLyMvc3RhbmRhbG9uZV0oaHR0cHM6Ly9lcmRwbHVzLmNvbS8jL3N0YW5kYWxvbmUpIGRyYXcgYSBzdGFyIGxpa2Ugc2NoZW1hIHVzaW5nIHRoZSBiZWxvdyB0aHJlZSB0YWJsZXMuIEluY2x1ZGUgYW4gaW1hZ2UgY2FwdHVyZSBvZiB5b3VyIHNjaGVtYSBoZXJlICg0cHRzKQ0KIyMjIyMNCg0KPC9zcGFuPg0KDQojIyMjIyMNCiANCg0KDQoNCi0gQSBGYWN0IHRhYmxlIGZvciBUcmlwcw0KLSBBIERpbWVuc2lvbiB0YWJsZSBmb3IgU3RhdGlvbnMNCi0gQSBEaW1lbnNpb24gdGFibGUgZm9yIFVzZXJzDQpTRUUgVEhFIFRPUCBPRiBUSEUgTEFCDQoNCg0K