Download and
Installation
Both R and RStudio are free and
open-source. R is a programming language widely used in
statistics and data science, including machine learning, while
RStudio is a data science platform that simplifies
working with R. In other words, we need to install both
R and RStudio and then use
R through RStudio.
The following YouTube video by Tony Carlsen demonstrates the steps
for downloading and installing both programs.
Please follow the steps to install these two programs on your
machine. You can also use R Studio on WCU’s Ramcloud.
Getting Started with R
and RStudio
The next video shows how to use R through RStudio with some basic
arithmetic operations and basic commands that will be used to compose
some formulas in this course.
You can also change the appearance of the RStudio user interface (UI)
to get a more comfortable and better UI by following the next few
steps:
- From the menu bar, go to Tools > Global
Options
- Click on Appearance
- Change the Editor font size if you want to
- Try out a few themes in the Editor theme box. (The
default is Textmate. I prefer Pastel on
Dark).
- Once you find something you like (or just stick with
Textmate if you are happy with the default appearance),
click on OK, and continue with this tutorial.

My own RStudio UI (user interface) is shown below (File >
New File > R Script)

After clearing the Console (bottom-left window) and
minimizing the right side windows (top-right and bottom-right windows),
we have the following UI with Script window and
Console window.

It is convenient for you to save a single file that includes all of
your code to be drafted during the semester. We will discuss how to
effectively organize your code for different modules later.
Using R As A
Calculator
R can be used as a powerful calculator by entering equations directly
at the prompt in the command console. Simply type your arithmetic
expression and press ENTER. R will evaluate the expressions and respond
with the result. While this is a simple interaction interface, there
could be problems if you are not careful. R will normally execute your
arithmetic expression by evaluating each item from left to right, but
some operators have precedence in the order of evaluation. Let’s start
with some simple expressions as examples.
Simple
Arithmetic Expressions
The operators R uses for basic arithmetic are:
+, -, *, /, ^
. The following table presents some
examples.
+ |
Addition |
4 + 8 |
12 |
- |
Subtraction |
5 - 8 |
-3 |
* |
Multiplication |
4 * 8-2 |
30 |
/ |
Division |
4 / 8 |
0.5 |
^ |
Exponentiation |
4^3 |
64 |
Here is how I performed the above operations in RStudio:
Open RStudio (click the RStudio icon, it will
automatically open the script window, Console, and other windows on the
right-hand side). Minimize the windows on the right-hand side to keep
only Script and Console windows.
Type the expressions in the Script
window.
Highlight the expression you want to
run,
You will view both code and results in the
R Console
The following is the screenshot of my RStudio UI (with some
annotations)

From the above screenshot, you see that using hashtags can make your
code more organized.
Input Data in
R
In statistics, a data set consists of values of multiple measurements
from multiple characteristics. For example, a data set contains
height, weight, and
gender taken from a group of \(n\) students.
1 |
\(x_1\) |
\(y_1\) |
F |
2 |
\(x_2\) |
\(y_2\) |
M |
\(\vdots\) |
\(\vdots\) |
\(\vdots\) |
\(\vdots\) |
\(n-1\) |
\(x_{n-1}\) |
\(y_{n-1}\) |
M |
\(n\) |
\(x_n\) |
\(y_n\) |
F |
The above data set has \(n\) rows,
each row records a student’s height,
weight, and gender. Different columns
represent different characteristics, which are commonly called
variables. A dataset is usually saved in a different format. The most
common formats of a flat data file are a text file .txt
(plain text file). If Excel is used to store data,
comma-separated values .csv
, and
Microsoft Excel spreadsheets (.xls
) or
Excel Open XML Spreadsheet (.xlsx
). A data
set with a different format required a different R
function to read data into R.
As an example, I save the following data set in
C:\cpeng\STA200
in plain text format with extension
.txt
and comma-separated values with extension
.csv
.
```{} ID height weight gender 1 60 120 F 2 64 119 M 3 68 145 M 4 71 132 F
When reading the data set into R, you need to provide the path to the
data file. The following screenshot shows how to use appropriate
R functions to read the dataset.

We can also define individual variables and then make a data frame
using the R function data.frame()
as shown
in the following code chunk.
# define individual variables first
ID <- c(1,2,3,4) # ID = observation id, lower case c() is an R function used to define a vector.
height <- c(60, 64, 68, 71)
weight <- c(120, 119, 145, 132)
gender <- c("F", "M", "M", "F") # Categorical values must be enclosed in double quotes and separated by commas.
# put the above variables in a dataframe
height.weight.data <- data.frame(ID = ID, height = height, weight = weight, gender = gender) # data.frame() is an R function
You can also define the data frame directly using the following
code.
height.weight.data.02 <- data.frame(
ID = c(1,2,3,4), # CAUTION: "=" CANNOT be replaced by "<-"!!!!
height = c(60, 64, 68, 71),
weight = c(120, 119, 145, 132),
gender = c("F", "M", "M", "F")
)
height.weight.data.02
## ID height weight gender
## 1 1 60 120 F
## 2 2 64 119 M
## 3 3 68 145 M
## 4 4 71 132 F
Working With Data
Frame
Quite often, we only work with one or two variables in a data frame
instead of the entire data set. For example, we want to calculate the
mean and standard deviation of the variable height
in the
above data set. We can extract height
from the data frame
we defined using the following code.
height <- height.weight.data.02$height # datasetname + $ + variablename
# Calculate mean and variance
xbar <- mean(height) # compute the mean and store it in a variable under the name of xbar
xbar # print out the result
## [1] 65.75
var.height <- var(height)
var.height
## [1] 22.91667
Some Basic
Statistics and Mathematics Functions
Most of you have experience using graphing calculators and relevant
functions. R has similar built-in functions for basic mathematical and
statistical calculations. We use height
and
weight
in examples in the following table.
mean |
mean() |
mean(height) |
65.75 |
variance |
var() |
var(height) |
22.92 |
standard deviation |
sd() |
sd(height) |
4.79 |
correlation coefficient |
cor() |
cor(height, weight) |
0.691 |
summation of data values |
sum() |
sum(height) |
263 |
Critical Values and
Left-tail Probabilities
In testing hypotheses, we can use either the critical value or
p-value methods to make a statistical decision. The next table lists the
R functions for critical and p-values from normal and t tables.
\(95\%\) normal
critical value |
NA |
qnorm(0.975) |
1.96 |
\(95\%\) normal
critical value |
25 |
qt(0.975, 25) |
2.059539 |
\(P(TS < 1.45)\)
normal table |
NA |
pnorm(1.45) |
0.9264707 |
\(P(TS < 1.45)\) t
table |
15 |
pt(1.45, 15) |
0.9161772 |
R Built-in Statistics
Function
R has a rich built-in functions for various statistical analyses.
Next, we list some of the functions that can perform all the analyses in
introductory statistics like MAT121 at WCU. These functions are called
when you have raw data stored in variables. Remember, each
column in a data frame is a variable.
For convenience, we use the following raw data set collected from a
diabetes study, which can be found at https://pengdsci.github.io/STA200/dataset/diabetes-dataset.csv
We first read the above data using the command given previously and
extract variables to perform one-sample, two-sample tests, correlation
coefficient, and least squares regression.
Data loading and variable extraction
correlation coefficient |
cor() |
cor(BMI, SkinThickness) |
five-number-summary |
summary() |
summary(BMI) |
histogram |
hist() |
hist(SkinThickness) |
scatter plot |
plot() |
plot(BMI, SkinThickness) |
frequency table (categorical data) |
table() |
table(Outcome) |
linear regression |
lm() |
lm(BMI ~ diabets.status) |
R Packages
An R package is a collection of functions, data, and documentation
that extends the capabilities of base R. Different R functions in
different packages allow users to perform different statistical tasks.
In this course, we will use a few functions and some packages. To use an
R function in a specific package, you need to load the package using the
following command.
if (!require("packageName")) {
install.packages("packageName")
library(packageName)
}
For example, if you want to perform a z-test (i.e., normal test), we
can use the R function z.test()
in the package. The
following is the code for testing BMI Ho: mu <= 30 vs Ha: mu >
30.
## install and load package
if (!require("BSDA")) {
install.packages("BSDA")
library(BSDA)
}
## Call the function to perform a normal test
# Ho: mu = 30 vs Ha: mu != 30, the alternative is !=, this is a two-sided test
# IF the test is right-tailed, the alternative MUST be specified as "greater",
# Similarly, if the test is left-tailed, the alternative MUST be specified as "less".
z.test(x = BMI, sigma.x = sd(BMI), mu = 30, alternative = "two.sided")
##
## One-sample z-Test
##
## data: BMI
## z = 7.0039, p-value = 2.489e-12
## alternative hypothesis: true mean is not equal to 30
## 95 percent confidence interval:
## 31.43498 32.55018
## sample estimates:
## mean of x
## 31.99258
You can see that the output also provides a 95% confidence interval
of the mean BMI.
Some commonly used packages come with the R base
package - this means that you don’t need to install and load
these packages when you use any R functions. These packages will be
automatically loaded when you start an R session. For example, the
following R function prop.test()
for testing population
proportion is in package {stats}:
prop.test(75, 137, p =0.57, alternative = "greater")
##
## 1-sample proportions test with continuity correction
##
## data: 75 out of 137, null probability 0.57
## X-squared = 0.19977, df = 1, p-value = 0.6725
## alternative hypothesis: true p is greater than 0.57
## 95 percent confidence interval:
## 0.4736288 1.0000000
## sample estimates:
## p
## 0.5474453
There are more than 20,000 (twenty
thousand!) R packages are available for various applications.
We will use about five packages
that require installation and explicit loading to access specific R
functions for analysis. You don’t need to memorize the names of these
packages—I encourage you to use AI tools like ChatGPT or related Copilot
assistants to find the R functions you need for your analysis. I will
also provide this information in my example code within the lecture
notes.
LS0tDQp0aXRsZTogIkdldHRpbmcgU3RhcnRlZCB3aXRoIFIgYW5kIFJTdHVkaW8iDQphdXRob3I6ICJDaGVuZyBQZW5nIg0KZGF0ZTogIiAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIHRoZW1lOiBsdW1lbg0KICBwZGZfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiA1DQogICAgZmlnX2hlaWdodDogNA0KLS0tDQoNCmBgYHtjc3MgZWNobyA9IEZBTFNFfQ0KDQpkaXYjVE9DIGxpIHsNCiAgICBsaXN0LXN0eWxlOm5vbmU7DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDI0cHg7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgxIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIwcHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDIgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQpgYGANCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSkNCmBgYA0KDQpcDQoNCiMgSW50cm9kdWN0aW9uDQoNClRoaXMgbW9kdWxlIG91dGxpbmVzIHRoZSBvcGVuLXNvdXJjZSBjb21wdXRlciBzb2Z0d2FyZSBwcm9ncmFtIFIgKDxodHRwczovL3d3dy5yLXByb2plY3Qub3JnLz4pIGFuZCB0aGUgcGxhdGZvcm0gUlN0dWRpbyAoPGh0dHBzOi8vcG9zaXQuY28vZG93bmxvYWRzLz4pIHRvIGJlIHVzZWQgaW4gdGhpcyBhbmQgc3Vic2VxdWVudCBzdGF0aXN0aWNzIGNvdXJzZXMuDQoNCg0KIyBEb3dubG9hZCBhbmQgSW5zdGFsbGF0aW9uDQoNCkJvdGggKipSKiogYW5kICoqUlN0dWRpbyoqIGFyZSBmcmVlIGFuZCBvcGVuLXNvdXJjZS4gKipSKiogaXMgYSBwcm9ncmFtbWluZyBsYW5ndWFnZSB3aWRlbHkgdXNlZCBpbiBzdGF0aXN0aWNzIGFuZCBkYXRhIHNjaWVuY2UsIGluY2x1ZGluZyBtYWNoaW5lIGxlYXJuaW5nLCB3aGlsZSAqKlJTdHVkaW8qKiBpcyBhIGRhdGEgc2NpZW5jZSBwbGF0Zm9ybSB0aGF0IHNpbXBsaWZpZXMgd29ya2luZyB3aXRoICoqUioqLiBJbiBvdGhlciB3b3Jkcywgd2UgbmVlZCB0byBpbnN0YWxsIGJvdGggKipSKiogYW5kICoqUlN0dWRpbyoqIGFuZCB0aGVuIHVzZSAqKlIqKiB0aHJvdWdoICoqUlN0dWRpbyoqLg0KDQpUaGUgZm9sbG93aW5nIFlvdVR1YmUgdmlkZW8gYnkgVG9ueSBDYXJsc2VuIGRlbW9uc3RyYXRlcyB0aGUgc3RlcHMgZm9yIGRvd25sb2FkaW5nIGFuZCBpbnN0YWxsaW5nIGJvdGggcHJvZ3JhbXMuDQoNClwNCjxjZW50ZXI+PGEgaHJlZj0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj00QWpGYkpzTk5iOCIgdGFyZ2V0PSJwb3B1cCIgDQogICAgICAgICAgICAgICAgICAgb25jbGljaz0id2luZG93Lm9wZW4oJ2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9NEFqRmJKc05OYjgnLA0KICAgICAgICAgICAgICAgICAgICAgICduYW1lJywnd2lkdGg9ODUwLGhlaWdodD01MDAnKSI+PGltZyBzcmMgPSAiaHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vTUFUMTIxVzUvaW1nL1ZpZGVvSWNvbi5wbmciIHdpZHRoPSIyMDAiIGhlaWdodD0iMTIwIj48L2E+DQo8L2NlbnRlcj4NClwNCg0KUGxlYXNlIGZvbGxvdyB0aGUgc3RlcHMgdG8gaW5zdGFsbCB0aGVzZSB0d28gcHJvZ3JhbXMgb24geW91ciBtYWNoaW5lLiBZb3UgY2FuIGFsc28gdXNlIFIgU3R1ZGlvIG9uIFdDVSdzIFJhbWNsb3VkLiANCg0KDQojIEdldHRpbmcgU3RhcnRlZCB3aXRoIFIgYW5kIFJTdHVkaW8NCg0KVGhlIG5leHQgdmlkZW8gc2hvd3MgaG93IHRvIHVzZSBSIHRocm91Z2ggUlN0dWRpbyB3aXRoIHNvbWUgYmFzaWMgYXJpdGhtZXRpYyBvcGVyYXRpb25zIGFuZCBiYXNpYyBjb21tYW5kcyB0aGF0IHdpbGwgYmUgdXNlZCB0byBjb21wb3NlIHNvbWUgZm9ybXVsYXMgaW4gdGhpcyBjb3Vyc2UuDQoNClwNCg0KPGNlbnRlcj48YSBocmVmPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUs5LXpEbXE3MzdJIiB0YXJnZXQ9InBvcHVwIiANCiAgICAgICAgICAgICAgICAgICBvbmNsaWNrPSJ3aW5kb3cub3BlbignaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1LOS16RG1xNzM3SScsDQogICAgICAgICAgICAgICAgICAgICAgJ25hbWUnLCd3aWR0aD04NTAsaGVpZ2h0PTUwMCcpIj48aW1nIHNyYyA9ICJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9NQVQxMjFXNS9pbWcvVmlkZW9JY29uLnBuZyIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxMjAiPjwvYT4NCjwvY2VudGVyPg0KDQpcDQoNCllvdSBjYW4gYWxzbyBjaGFuZ2UgdGhlIGFwcGVhcmFuY2Ugb2YgdGhlIFJTdHVkaW8gdXNlciBpbnRlcmZhY2UgKFVJKSB0byBnZXQgYSBtb3JlIGNvbWZvcnRhYmxlIGFuZCBiZXR0ZXIgVUkgYnkgZm9sbG93aW5nIHRoZSBuZXh0IGZldyBzdGVwczogDQoNCiogRnJvbSB0aGUgbWVudSBiYXIsIGdvIHRvICoqVG9vbHMqKiA+ICoqR2xvYmFsIE9wdGlvbnMqKg0KKiBDbGljayBvbiAqKkFwcGVhcmFuY2UqKg0KKiBDaGFuZ2UgdGhlICoqRWRpdG9yIGZvbnQgc2l6ZSoqIGlmIHlvdSB3YW50IHRvDQoqIFRyeSBvdXQgYSBmZXcgdGhlbWVzIGluIHRoZSAqKkVkaXRvciB0aGVtZSBib3gqKi4gKFRoZSBkZWZhdWx0IGlzICoqVGV4dG1hdGUqKi4gSSBwcmVmZXIgKipQYXN0ZWwgb24gRGFyayoqKS4NCiogT25jZSB5b3UgZmluZCBzb21ldGhpbmcgeW91IGxpa2UgKG9yIGp1c3Qgc3RpY2sgd2l0aCAqKlRleHRtYXRlKiogaWYgeW91IGFyZSBoYXBweSB3aXRoIHRoZSBkZWZhdWx0IGFwcGVhcmFuY2UpLCBjbGljayBvbiAqKk9LKiosIGFuZCBjb250aW51ZSB3aXRoIHRoaXMgdHV0b3JpYWwuDQoNCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCAgb3V0LndpZHRoID0gJzg1JSd9DQppZiAoa25pdHI6Ojppc19sYXRleF9vdXRwdXQoKSkgew0KICBrbml0cjo6YXNpc19vdXRwdXQoJ1xcdXJse2h0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL1NUQTIwMC9naWYvUnNldHVwLmdpZn0nKQ0KfSBlbHNlIHsNCiAga25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIlIvUnNldHVwLmdpZiIpDQp9DQpgYGANCg0KDQpNeSBvd24gUlN0dWRpbyBVSSAodXNlciBpbnRlcmZhY2UpIGlzIHNob3duIGJlbG93ICgqKkZpbGUgPiBOZXcgRmlsZSA+IFIgU2NyaXB0KiopDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjEwMCUifQ0KaW5jbHVkZV9ncmFwaGljcygiTW9kdWxlMDAvUlN0dWRpby1XaW5kb3dzLnBuZyIpDQpgYGANCg0KQWZ0ZXIgY2xlYXJpbmcgdGhlICoqQ29uc29sZSoqIChib3R0b20tbGVmdCB3aW5kb3cpIGFuZCBtaW5pbWl6aW5nIHRoZSByaWdodCBzaWRlIHdpbmRvd3MgKHRvcC1yaWdodCBhbmQgYm90dG9tLXJpZ2h0IHdpbmRvd3MpLCB3ZSBoYXZlIHRoZSBmb2xsb3dpbmcgVUkgd2l0aCAqKlNjcmlwdCoqIHdpbmRvdyBhbmQgKipDb25zb2xlKiogd2luZG93Lg0KDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjEwMCUifQ0KaW5jbHVkZV9ncmFwaGljcygiTW9kdWxlMDAvUlN0dWRpby1Xb3JraW5nLVdpbmRvdy5wbmciKQ0KYGBgDQoNCkl0IGlzIGNvbnZlbmllbnQgZm9yIHlvdSB0byBzYXZlIGEgc2luZ2xlIGZpbGUgdGhhdCBpbmNsdWRlcyBhbGwgb2YgeW91ciBjb2RlIHRvIGJlIGRyYWZ0ZWQgZHVyaW5nIHRoZSBzZW1lc3Rlci4gV2Ugd2lsbCBkaXNjdXNzIGhvdyB0byBlZmZlY3RpdmVseSBvcmdhbml6ZSB5b3VyIGNvZGUgZm9yIGRpZmZlcmVudCBtb2R1bGVzIGxhdGVyLiANCg0KDQoNCiMgVXNpbmcgUiBBcyBBIENhbGN1bGF0b3INCg0KUiBjYW4gYmUgdXNlZCBhcyBhIHBvd2VyZnVsIGNhbGN1bGF0b3IgYnkgZW50ZXJpbmcgZXF1YXRpb25zIGRpcmVjdGx5IGF0IHRoZSBwcm9tcHQgaW4gdGhlIGNvbW1hbmQgY29uc29sZS4gU2ltcGx5IHR5cGUgeW91ciBhcml0aG1ldGljIGV4cHJlc3Npb24gYW5kIHByZXNzIEVOVEVSLiBSIHdpbGwgZXZhbHVhdGUgdGhlIGV4cHJlc3Npb25zIGFuZCByZXNwb25kIHdpdGggdGhlIHJlc3VsdC4gV2hpbGUgdGhpcyBpcyBhIHNpbXBsZSBpbnRlcmFjdGlvbiBpbnRlcmZhY2UsIHRoZXJlIGNvdWxkIGJlIHByb2JsZW1zIGlmIHlvdSBhcmUgbm90IGNhcmVmdWwuIFIgd2lsbCBub3JtYWxseSBleGVjdXRlIHlvdXIgYXJpdGhtZXRpYyBleHByZXNzaW9uIGJ5IGV2YWx1YXRpbmcgZWFjaCBpdGVtIGZyb20gbGVmdCB0byByaWdodCwgYnV0IHNvbWUgb3BlcmF0b3JzIGhhdmUgcHJlY2VkZW5jZSBpbiB0aGUgb3JkZXIgb2YgZXZhbHVhdGlvbi4gTGV0J3Mgc3RhcnQgd2l0aCBzb21lIHNpbXBsZSBleHByZXNzaW9ucyBhcyBleGFtcGxlcy4NCg0KDQojIyAqKlNpbXBsZSBBcml0aG1ldGljIEV4cHJlc3Npb25zKioNCg0KVGhlIG9wZXJhdG9ycyBSIHVzZXMgZm9yIGJhc2ljIGFyaXRobWV0aWMgYXJlOiAgYCssIC0sICosIC8sIF5gLiBUaGUgZm9sbG93aW5nIHRhYmxlIHByZXNlbnRzIHNvbWUgZXhhbXBsZXMuDQoNCg0KfCAgT3BlcmF0b3IgfCAgTWVhbmluZyB8IEV4YW1wbGUgRXhwcmVzc2lvbiAgfCAgUmVzdWx0IHwNCnw6LS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS18DQp8YCtgICAgIHxBZGRpdGlvbiAgICAgICAgICAgIHwgYDQgKyA4YCB8IDEyIHwNCnxgLWAgICAgfFN1YnRyYWN0aW9uICAgICAgICAgfCBgNSAtIDhgIHwgLTMgfA0KfGAqYCAgICB8TXVsdGlwbGljYXRpb24gICAgICB8IGA0ICogOC0yYCB8IDMwIHwNCnxgL2AgICAgfERpdmlzaW9uICAgICAgICAgICAgfCBgNCAvIDhgIHwgMC41IHwNCnxgXmAgICAgfEV4cG9uZW50aWF0aW9uICAgICAgfCBgNF4zYCAgIHwgNjQgfA0KDQpIZXJlIGlzIGhvdyBJIHBlcmZvcm1lZCB0aGUgYWJvdmUgb3BlcmF0aW9ucyBpbiBSU3R1ZGlvOg0KDQoxLiAqKk9wZW4gUlN0dWRpbyoqIChjbGljayB0aGUgUlN0dWRpbyBpY29uLCBpdCB3aWxsIGF1dG9tYXRpY2FsbHkgb3BlbiB0aGUgc2NyaXB0IHdpbmRvdywgQ29uc29sZSwgYW5kIG90aGVyIHdpbmRvd3Mgb24gdGhlIHJpZ2h0LWhhbmQgc2lkZSkuIE1pbmltaXplIHRoZSB3aW5kb3dzIG9uIHRoZSByaWdodC1oYW5kIHNpZGUgdG8ga2VlcCBvbmx5IFNjcmlwdCBhbmQgQ29uc29sZSB3aW5kb3dzLg0KDQoyLiAqKlR5cGUgdGhlIGV4cHJlc3Npb25zKiogaW4gdGhlICoqU2NyaXB0IHdpbmRvdyoqLiANCg0KMy4gKipIaWdobGlnaHQgdGhlIGV4cHJlc3Npb24qKiB5b3Ugd2FudCB0byBydW4sDQoNCjQuIFlvdSB3aWxsIHZpZXcgKipib3RoIGNvZGUgYW5kIHJlc3VsdHMqKiBpbiB0aGUgKipSIENvbnNvbGUqKg0KDQpUaGUgZm9sbG93aW5nIGlzIHRoZSBzY3JlZW5zaG90IG9mIG15IFJTdHVkaW8gVUkgKHdpdGggc29tZSBhbm5vdGF0aW9ucykNCg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSIxMDAlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoIk1vZHVsZTAwL2FyaXRobWV0aWMtb3BlcmF0aW9ucy5wbmciKQ0KYGBgDQoNCg0KRnJvbSB0aGUgYWJvdmUgc2NyZWVuc2hvdCwgeW91IHNlZSB0aGF0IHVzaW5nIGhhc2h0YWdzIGNhbiBtYWtlIHlvdXIgY29kZSBtb3JlIG9yZ2FuaXplZC4NCg0KXA0KDQoNCiMjICoqSW5wdXQgRGF0YSBpbiBSKioNCg0KSW4gc3RhdGlzdGljcywgYSBkYXRhIHNldCBjb25zaXN0cyBvZiB2YWx1ZXMgb2YgbXVsdGlwbGUgbWVhc3VyZW1lbnRzIGZyb20gbXVsdGlwbGUgY2hhcmFjdGVyaXN0aWNzLiBGb3IgZXhhbXBsZSwgYSBkYXRhIHNldCBjb250YWlucyAqKmhlaWdodCoqLCAqKndlaWdodCoqLCBhbmQgKipnZW5kZXIqKiB0YWtlbiBmcm9tIGEgZ3JvdXAgb2YgJG4kIHN0dWRlbnRzLiANCg0KfCBvYnNlcnZhdGlvbiBJRCAgfCAgIGhlaWdodCAoJFgkKSB8ICAgd2VpZ2h0ICgkWSQpIHwgIEdlbmRlciAoJFokKQ0KfDotLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLXwNCnwgMSAgICAgICAgICAgIHwgICR4XzEkICAgICAgICAgfCAgICR5XzEkICAgICAgICB8ICAgRiAgICAgfA0KfCAyICAgICAgICAgICAgfCAgJHhfMiQgICAgICAgICB8ICAgJHlfMiQgICAgICAgIHwgICBNICAgICB8DQp8ICRcdmRvdHMkICAgICB8ICAkXHZkb3RzJCAgICAgIHwgICAkXHZkb3RzJCAgICAgfCRcdmRvdHMkIHwgICANCnwgJG4tMSQgICAgICAgIHwgICR4X3tuLTF9JCAgICAgfCAgICR5X3tuLTF9JCAgICB8ICAgTSAgICAgfA0KfCAkbiQgICAgICAgICAgfCAgJHhfbiQgICAgICAgICB8ICAgJHlfbiQgICAgICAgIHwgICBGICAgICB8DQoNClRoZSBhYm92ZSBkYXRhIHNldCBoYXMgJG4kIHJvd3MsIGVhY2ggcm93IHJlY29yZHMgYSBzdHVkZW50J3MgKipoZWlnaHQqKiwgKip3ZWlnaHQqKiwgYW5kICoqZ2VuZGVyKiouIERpZmZlcmVudCBjb2x1bW5zIHJlcHJlc2VudCBkaWZmZXJlbnQgY2hhcmFjdGVyaXN0aWNzLCB3aGljaCBhcmUgY29tbW9ubHkgY2FsbGVkIHZhcmlhYmxlcy4gQSBkYXRhc2V0IGlzIHVzdWFsbHkgc2F2ZWQgaW4gYSBkaWZmZXJlbnQgZm9ybWF0LiBUaGUgbW9zdCBjb21tb24gZm9ybWF0cyBvZiBhIGZsYXQgZGF0YSBmaWxlIGFyZSBhIHRleHQgZmlsZSBgLnR4dGAgKHBsYWluIHRleHQgZmlsZSkuIElmIEV4Y2VsIGlzIHVzZWQgdG8gc3RvcmUgZGF0YSwgKipjb21tYS1zZXBhcmF0ZWQgdmFsdWVzKiogYC5jc3ZgLCBhbmQgICoqTWljcm9zb2Z0IEV4Y2VsIHNwcmVhZHNoZWV0cyoqIChgLnhsc2ApIG9yICoqRXhjZWwgT3BlbiBYTUwgU3ByZWFkc2hlZXQqKiAoYC54bHN4YCkuIEEgZGF0YSBzZXQgd2l0aCBhIGRpZmZlcmVudCBmb3JtYXQgcmVxdWlyZWQgYSBkaWZmZXJlbnQgKipSIGZ1bmN0aW9uKiogdG8gcmVhZCBkYXRhIGludG8gUi4gIA0KDQpBcyBhbiBleGFtcGxlLCBJIHNhdmUgdGhlIGZvbGxvd2luZyBkYXRhIHNldCBpbiBgQzpcY3BlbmdcU1RBMjAwYCBpbiBwbGFpbiB0ZXh0IGZvcm1hdCB3aXRoIGV4dGVuc2lvbiBgLnR4dGAgYW5kIGNvbW1hLXNlcGFyYXRlZCB2YWx1ZXMgd2l0aCBleHRlbnNpb24gYC5jc3ZgLiANCg0KYGBgYGBge30NCklEICAgaGVpZ2h0ICAgIHdlaWdodCAgIGdlbmRlcg0KMSAgICAgNjAgICAgICAgICAxMjAgICAgICBGDQoyICAgICA2NCAgICAgICAgIDExOSAgICAgIE0NCjMgICAgIDY4ICAgICAgICAgMTQ1ICAgICAgTQ0KNCAgICAgNzEgICAgICAgICAxMzIgICAgICBGDQpgYGANCg0KV2hlbiByZWFkaW5nIHRoZSBkYXRhIHNldCBpbnRvIFIsIHlvdSBuZWVkIHRvIHByb3ZpZGUgdGhlIHBhdGggdG8gdGhlIGRhdGEgZmlsZS4gVGhlIGZvbGxvd2luZyBzY3JlZW5zaG90IHNob3dzIGhvdyB0byB1c2UgYXBwcm9wcmlhdGUgKipSIGZ1bmN0aW9ucyoqIHRvIHJlYWQgdGhlIGRhdGFzZXQuDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjEwMCUifQ0KaW5jbHVkZV9ncmFwaGljcygiTW9kdWxlMDAvUmVhZERhdGEyUi5wbmciKQ0KYGBgDQoNCldlIGNhbiBhbHNvIGRlZmluZSBpbmRpdmlkdWFsIHZhcmlhYmxlcyBhbmQgdGhlbiBtYWtlIGEgZGF0YSBmcmFtZSB1c2luZyB0aGUgKipSIGZ1bmN0aW9uKiogYGRhdGEuZnJhbWUoKWAgYXMgc2hvd24gaW4gdGhlIGZvbGxvd2luZyAqKmNvZGUgY2h1bmsqKi4NCg0KYGBge3IgZWNobyA9IFRSVUV9DQojIGRlZmluZSBpbmRpdmlkdWFsIHZhcmlhYmxlcyBmaXJzdA0KSUQgPC0gYygxLDIsMyw0KSAgICAjIElEID0gb2JzZXJ2YXRpb24gaWQsIGxvd2VyIGNhc2UgYygpIGlzIGFuIFIgZnVuY3Rpb24gdXNlZCB0byBkZWZpbmUgYSB2ZWN0b3IuDQpoZWlnaHQgPC0gYyg2MCwgNjQsIDY4LCA3MSkNCndlaWdodCA8LSBjKDEyMCwgMTE5LCAxNDUsIDEzMikNCmdlbmRlciA8LSBjKCJGIiwgIk0iLCAiTSIsICJGIikgICAjIENhdGVnb3JpY2FsIHZhbHVlcyBtdXN0IGJlIGVuY2xvc2VkIGluIGRvdWJsZSBxdW90ZXMgYW5kIHNlcGFyYXRlZCBieSBjb21tYXMuDQojIHB1dCB0aGUgYWJvdmUgdmFyaWFibGVzIGluIGEgZGF0YWZyYW1lDQpoZWlnaHQud2VpZ2h0LmRhdGEgPC0gZGF0YS5mcmFtZShJRCA9IElELCBoZWlnaHQgPSBoZWlnaHQsIHdlaWdodCA9IHdlaWdodCwgZ2VuZGVyID0gZ2VuZGVyKSAgIyBkYXRhLmZyYW1lKCkgaXMgYW4gIFIgZnVuY3Rpb24NCmBgYA0KDQpZb3UgY2FuIGFsc28gZGVmaW5lIHRoZSBkYXRhIGZyYW1lIGRpcmVjdGx5IHVzaW5nIHRoZSBmb2xsb3dpbmcgY29kZS4NCg0KYGBge3IgZWNobyA9IFRSVUV9DQpoZWlnaHQud2VpZ2h0LmRhdGEuMDIgPC0gZGF0YS5mcmFtZSgNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSUQgPSBjKDEsMiwzLDQpLCAgICAgICAjIENBVVRJT046ICI9IiBDQU5OT1QgYmUgcmVwbGFjZWQgYnkgIjwtIiEhISENCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gYyg2MCwgNjQsIDY4LCA3MSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodCA9IGMoMTIwLCAxMTksIDE0NSwgMTMyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZGVyID0gYygiRiIsICJNIiwgIk0iLCAiRiIpDQopDQpoZWlnaHQud2VpZ2h0LmRhdGEuMDINCmBgYA0KDQojIyBXb3JraW5nIFdpdGggRGF0YSBGcmFtZSANCg0KUXVpdGUgb2Z0ZW4sIHdlIG9ubHkgd29yayB3aXRoIG9uZSBvciB0d28gdmFyaWFibGVzIGluIGEgZGF0YSBmcmFtZSBpbnN0ZWFkIG9mIHRoZSBlbnRpcmUgZGF0YSBzZXQuIEZvciBleGFtcGxlLCB3ZSB3YW50IHRvIGNhbGN1bGF0ZSB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSB2YXJpYWJsZSBgaGVpZ2h0YCBpbiB0aGUgYWJvdmUgZGF0YSBzZXQuIFdlIGNhbiBleHRyYWN0IGBoZWlnaHRgIGZyb20gdGhlIGRhdGEgZnJhbWUgd2UgZGVmaW5lZCB1c2luZyB0aGUgZm9sbG93aW5nIGNvZGUuDQoNCmBgYHtyIGVjaG8gPSBUUlVFfQ0KaGVpZ2h0IDwtIGhlaWdodC53ZWlnaHQuZGF0YS4wMiRoZWlnaHQgICAjIGRhdGFzZXRuYW1lICsgJCArIHZhcmlhYmxlbmFtZQ0KIyBDYWxjdWxhdGUgbWVhbiBhbmQgdmFyaWFuY2UNCnhiYXIgPC0gbWVhbihoZWlnaHQpICAjIGNvbXB1dGUgdGhlIG1lYW4gYW5kIHN0b3JlIGl0IGluIGEgdmFyaWFibGUgdW5kZXIgdGhlIG5hbWUgb2YgeGJhcg0KeGJhciAgICAgICAgICAgICAgICAgICMgcHJpbnQgb3V0IHRoZSByZXN1bHQNCnZhci5oZWlnaHQgPC0gdmFyKGhlaWdodCkNCnZhci5oZWlnaHQNCmBgYA0KDQoNCg0KIyMgKipTb21lIEJhc2ljIFN0YXRpc3RpY3MgYW5kIE1hdGhlbWF0aWNzIEZ1bmN0aW9ucyoqDQoNCk1vc3Qgb2YgeW91IGhhdmUgZXhwZXJpZW5jZSB1c2luZyBncmFwaGluZyBjYWxjdWxhdG9ycyBhbmQgcmVsZXZhbnQgZnVuY3Rpb25zLiBSIGhhcyBzaW1pbGFyIGJ1aWx0LWluIGZ1bmN0aW9ucyBmb3IgYmFzaWMgbWF0aGVtYXRpY2FsIGFuZCBzdGF0aXN0aWNhbCBjYWxjdWxhdGlvbnMuIFdlIHVzZSBgaGVpZ2h0YCBhbmQgYHdlaWdodGAgaW4gZXhhbXBsZXMgaW4gdGhlIGZvbGxvd2luZyB0YWJsZS4NCg0KDQp8IE1hdGggJiBTdGF0cyBmdW5jdGlvbiAgfCBSIGZ1bmN0aW9uICB8ICAgIEV4YW1wbGUgIENvZGUgICAgICAgIHwgICBSZXN1bHQgICB8DQp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS18DQp8IG1lYW4gICAgICAgICAgICAgICAgICAgfCBgbWVhbigpYCAgICB8ICBgbWVhbihoZWlnaHQpYCAgICAgICAgIHwgICAgNjUuNzUgICB8ICAgICAgDQp8IHZhcmlhbmNlICAgICAgICAgICAgICAgfCBgdmFyKClgICAgICB8ICBgdmFyKGhlaWdodClgICAgICAgICAgIHwgICAgMjIuOTIgICB8ICANCnwgc3RhbmRhcmQgZGV2aWF0aW9uICAgICB8IGBzZCgpYCAgICAgIHwgIGBzZChoZWlnaHQpYCAgICAgICAgICAgfCAgICAgNC43OSAgIHwNCnwgY29ycmVsYXRpb24gY29lZmZpY2llbnQgfCBgY29yKClgICAgIHwgIGBjb3IoaGVpZ2h0LCB3ZWlnaHQpYCAgfCAgICAwLjY5MSAgIHwNCnwgc3VtbWF0aW9uIG9mIGRhdGEgdmFsdWVzfCBgc3VtKClgICAgIHwgIGBzdW0oaGVpZ2h0KWAgICAgICAgICAgfCAgICAyNjMgICAgIHwNCg0KDQojIyBDcml0aWNhbCBWYWx1ZXMgYW5kIExlZnQtdGFpbCBQcm9iYWJpbGl0aWVzDQoNCkluIHRlc3RpbmcgaHlwb3RoZXNlcywgd2UgY2FuIHVzZSBlaXRoZXIgdGhlIGNyaXRpY2FsIHZhbHVlIG9yIHAtdmFsdWUgbWV0aG9kcyB0byBtYWtlIGEgc3RhdGlzdGljYWwgZGVjaXNpb24uIFRoZSBuZXh0IHRhYmxlIGxpc3RzIHRoZSBSIGZ1bmN0aW9ucyBmb3IgY3JpdGljYWwgYW5kIHAtdmFsdWVzIGZyb20gbm9ybWFsIGFuZCB0IHRhYmxlcy4NCg0KDQp8IENyaXRpY2FsIFZhbHVlICAgICAgICAgICAgICAgIHwgZGVncmVlcyBvZiBmcmVlZG9tICB8ICAgIEV4YW1wbGUgIENvZGUgICAgICAgIHwgICBSZXN1bHQgICAgICB8DQp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS18DQp8ICQ5NVwlJCBub3JtYWwgY3JpdGljYWwgdmFsdWUgIHwgIE5BICAgICAgICAgICAgICAgICB8ICBgcW5vcm0oMC45NzUpYCAgICAgICAgIHwgICAgMS45NiAgICAgICB8ICAgICAgDQp8JDk1XCUkIG5vcm1hbCBjcml0aWNhbCB2YWx1ZSAgIHwgMjUgICAgICAgICAgICAgICAgICB8ICBgcXQoMC45NzUsIDI1KWAgICAgICAgIHwgICAgMi4wNTk1MzkgICB8ICANCg0KDQoNCg0KfCBsZWZ0LXRhaWwgIFByb2JhYmlsaXR5ICAgICAgICB8IGRlZ3JlZXMgb2YgZnJlZWRvbSAgfCAgICBFeGFtcGxlICBDb2RlICAgICAgICB8ICAgUmVzdWx0ICAgICAgfA0KfDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tfA0KfCAkUChUUyA8IDEuNDUpJCBub3JtYWwgdGFibGUgICB8ICBOQSAgICAgICAgICAgICAgICAgfCAgYHBub3JtKDEuNDUpYCAgICAgICAgICB8ICAgIDAuOTI2NDcwNyAgfCAgICAgIA0KfCAkUChUUyA8IDEuNDUpJCB0IHRhYmxlICAgICAgICB8ICAxNSAgICAgICAgICAgICAgICAgfCAgYHB0KDEuNDUsIDE1KWAgICAgICAgICB8ICAgIDAuOTE2MTc3MiAgfCANCg0KDQoNCg0KDQoNCiMjIEV2YWx1YXRlIEZvcm11bGFzDQoNCkp1c3QgbGlrZSB1c2luZyBhIGdyYXBoaW5nIGNhbGN1bGF0b3IsIHdlIHNvbWV0aW1lcyBuZWVkIHRvIGV2YWx1YXRlIGEgZm9ybXVsYS4gRm9yIGV4YW1wbGUsIHdoZW4gY29uc3RydWN0aW5nIGEgOTUlIG5vcm1hbCBjb25maWRlbmNlIGludGVydmFsIGJhc2VkIG9uIGdpdmVuIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgKHJhdGhlciB0aGFuIHJhdyBkYXRhKSwgd2UgdXNlIHRoZSBmb2xsb3dpbmcgZm9ybXVsYS4NCg0KDQoNCiQkDQpcYmFye1h9IFxwbSBaX3tcYWxwaGEvMn1cZnJhY3tzfXtcc3FydHtufX0uDQokJA0KDQpXZSB1c2UgYW4gZXhhbXBsZSB0byBpbGx1c3RyYXRlIGhvdyB0byB3cml0ZSB0aGUgYWJvdmUgZm9ybXVsYSBpbiBSIHRvIGNhbGN1bGF0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbC4NCg0KKipFeGFtcGxlKio6IFRoZSBEZWFuIHdhbnRzIHRvIGVzdGltYXRlIHRoZSBtZWFuIG51bWJlciBvZiBob3VycyB0aGF0IHN0dWRlbnRzIHdvcmtlZCBwZXIgd2Vlay4gIEEgc2FtcGxlIG9mIDQ5IHN0dWRlbnRzIHNob3dlZCBhIG1lYW4gb2YgMjQgaG91cnMgd2l0aCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiA0IGhvdXJzLiBUaGUgcG9pbnQgZXN0aW1hdGUgaXMgMjQgaG91cnMgKHNhbXBsZSBtZWFuKS4gV2hhdCBpcyB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoZSBhdmVyYWdlIG51bWJlciBvZiBob3VycyB3b3JrZWQgcGVyIHdlZWsgYnkgdGhlIHN0dWRlbnRzPw0KDQoqcmVhc29uaW5nIHByb2Nlc3MqOiBzaW5jZSAkbj0zOSA+IDMwJCwgd2UgY2FuIHVzZSB0aGUgY2VudHJhbCBsaW1pdCB0aGVvcmVtIChDTFQpIHRvIGNsYWltIHRoYXQgJFxiYXJ7WH0kIGlzIGFwcHJveGltYXRlZCBieSBhIG5vcm1hbCBkaXN0cmlidXRpb24uIFRoZXJlZm9yZSwgJFpfe1xhbHBoYS8yfSQgY2FuIGJlIGZvdW5kIHVzaW5nIGBxbm9ybSgxLWFscGhhLzIpYC4gDQoNCmBgYHtyIGVjaG8gPSBUUlVFfQ0KIyMgQXNzaWduIHZhbHVlcyB0byB2YXJpYWJsZXMgaW4gdGhlIGZvcm11bGEgDQphbHBoYSA9IDEtMC45NSAgICMgYWxwaGENCnhiYXIgPSAyNCAgICMgc2FtcGxlIG1lYW4NCnN0ZGV2ID0gNCAgICMgc3RhbmRhcmQgZGV2aWF0aW9uDQpuID0gNDkNCiMjIGNyaXRpY2FsIHZhbHVlDQpaLjAuOTc1ID0gcW5vcm0oMC45NzUpICAgICMgYWxwaGEgPSAxIC0gOTUlIC0gMSAtIDAuOTUgPSAwLjA1LCAxIC0gYWxwaGEvMiA9IDEgLTAuMDI1ID0gMC45NzUNCiMjIGxvd2VyIGFuZCB1cHBlciBjb25maWRlbmNlIGxpbWl0cw0KTENMID0geGJhciAtIFouMC45NzUqKHN0ZGV2L3NxcnQobikpICAgIyBubyBzcXVhcmUgYW5kIGN1cmx5IGJyYWNrZXQgc2hvdWxkIGJlIHVzZWQgaW4gUg0KVUNMID0geGJhciArIFouMC45NzUqKHN0ZGV2L3NxcnQobikpIA0KIyMgV3JpdGUgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwNCmNiaW5kKExDTCA9IExDTCwgVUNMID0gVUNMKSAgICAjIGNvbWJpbmVkIHRoZSB0d28gbGltaXRzIGluIGEgdHdvLWNvbHVtbiB0YWJsZSB3aXRoIG9uZSByb3cNCmBgYA0KDQojIFIgQnVpbHQtaW4gU3RhdGlzdGljcyBGdW5jdGlvbg0KDQpSIGhhcyBhIHJpY2ggYnVpbHQtaW4gZnVuY3Rpb25zIGZvciB2YXJpb3VzIHN0YXRpc3RpY2FsIGFuYWx5c2VzLiBOZXh0LCB3ZSBsaXN0IHNvbWUgb2YgdGhlIGZ1bmN0aW9ucyB0aGF0IGNhbiBwZXJmb3JtIGFsbCB0aGUgYW5hbHlzZXMgaW4gaW50cm9kdWN0b3J5IHN0YXRpc3RpY3MgbGlrZSBNQVQxMjEgYXQgV0NVLiBUaGVzZSBmdW5jdGlvbnMgYXJlIGNhbGxlZCB3aGVuIHlvdSBoYXZlIHJhdyBkYXRhIHN0b3JlZCBpbiB2YXJpYWJsZXMuICoqUmVtZW1iZXIsIGVhY2ggY29sdW1uIGluIGEgZGF0YSBmcmFtZSBpcyBhIHZhcmlhYmxlLioqDQoNCkZvciBjb252ZW5pZW5jZSwgd2UgdXNlIHRoZSBmb2xsb3dpbmcgcmF3IGRhdGEgc2V0IGNvbGxlY3RlZCBmcm9tIGEgZGlhYmV0ZXMgc3R1ZHksIHdoaWNoIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9wZW5nZHNjaS5naXRodWIuaW8vU1RBMjAwL2RhdGFzZXQvZGlhYmV0ZXMtZGF0YXNldC5jc3Y+DQoNCldlIGZpcnN0IHJlYWQgdGhlIGFib3ZlIGRhdGEgdXNpbmcgdGhlIGNvbW1hbmQgZ2l2ZW4gcHJldmlvdXNseSBhbmQgZXh0cmFjdCB2YXJpYWJsZXMgdG8gcGVyZm9ybSBvbmUtc2FtcGxlLCB0d28tc2FtcGxlIHRlc3RzLCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCwgYW5kIGxlYXN0IHNxdWFyZXMgcmVncmVzc2lvbi4NCg0KKipEYXRhIGxvYWRpbmcgYW5kIHZhcmlhYmxlIGV4dHJhY3Rpb24qKg0KDQpgYGB7cn0NCiMjIGxvYWRpbmcgZGF0YQ0KZGlhYmV0ZXMgPC0gcmVhZC5jc3YoImh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL1NUQTIwMC9kYXRhc2V0L2RpYWJldGVzLWRhdGFzZXQuY3N2IikNCmRpYWJldHMuc3RhdHVzIDwtIGRpYWJldGVzJE91dGNvbWUgICAgICAjIGRhdHNldE5hbWUkdmFyaWFibGVOYW1lIGV4dHJhY3QgdmFyaWFibGUgZnJvbSBhIGRhdGEgc2V0DQpTa2luVGhpY2tuZXNzIDwtIGRpYWJldGVzJFNraW5UaGlja25lc3MgIyBleHRyYWN0IHNraW4gdGhpY2tuZXNzDQpCTUkgPC0gZGlhYmV0ZXMkQk1JICAgICAgICAgICAgICAgICAgICAgIyBleHRyYWN0IEJNSSAoYm9keSBtYXNzIGluZGV4KQ0KYGBgIA0KYGBge3IgdGFibGUyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5ncz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9DQp0YWJsIDwtICINCnwgU3RhdGlzdGljYWwgVGFzayB8ICBCdWlsdC1pbiBSIEZ1bmN0aW9uICB8ICBFeGFtcGxlIHdpdGggRGF0YSB8IA0KfDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tfA0KfCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCAgICAgICB8IGBjb3IoKWAgIHwgYGNvcihCTUksIFNraW5UaGlja25lc3MpYCB8DQp8IGZpdmUtbnVtYmVyLXN1bW1hcnkgICAgICAgICAgIHwgYHN1bW1hcnkoKWB8IGBzdW1tYXJ5KEJNSSlgIHwNCnwgaGlzdG9ncmFtICAgICAgICAgICAgICAgICAgICAgfCBgaGlzdCgpYCAgICB8IGBoaXN0KFNraW5UaGlja25lc3MpYHwNCnwgc2NhdHRlciBwbG90ICAgICAgICAgICAgICAgICAgfCBgcGxvdCgpYCAgICB8IGBwbG90KEJNSSwgU2tpblRoaWNrbmVzcylgIHwNCnwgZnJlcXVlbmN5IHRhYmxlIChjYXRlZ29yaWNhbCBkYXRhKXwgYHRhYmxlKClgIHwgYHRhYmxlKE91dGNvbWUpYCB8DQp8IGxpbmVhciByZWdyZXNzaW9uICAgICAgICAgICAgIHwgYGxtKClgICB8IGBsbShCTUkgfiBkaWFiZXRzLnN0YXR1cylgIHwNCiINCmNhdCh0YWJsKSAjIG91dHB1dCB0aGUgdGFibGUgaW4gYSBmb3JtYXQgZ29vZCBmb3IgSFRNTC9QREYvZG9jeCBjb252ZXJzaW9uDQpgYGANCg0KDQojIFIgUGFja2FnZXMNCg0KQW4gUiBwYWNrYWdlIGlzIGEgY29sbGVjdGlvbiBvZiBmdW5jdGlvbnMsIGRhdGEsIGFuZCBkb2N1bWVudGF0aW9uIHRoYXQgZXh0ZW5kcyB0aGUgY2FwYWJpbGl0aWVzIG9mIGJhc2UgUi4gRGlmZmVyZW50IFIgZnVuY3Rpb25zIGluIGRpZmZlcmVudCBwYWNrYWdlcyBhbGxvdyB1c2VycyB0byBwZXJmb3JtIGRpZmZlcmVudCBzdGF0aXN0aWNhbCB0YXNrcy4gSW4gdGhpcyBjb3Vyc2UsIHdlIHdpbGwgdXNlIGEgZmV3IGZ1bmN0aW9ucyBhbmQgc29tZSBwYWNrYWdlcy4gVG8gdXNlIGFuIFIgZnVuY3Rpb24gaW4gYSBzcGVjaWZpYyBwYWNrYWdlLCB5b3UgbmVlZCB0byBsb2FkIHRoZSBwYWNrYWdlIHVzaW5nIHRoZSBmb2xsb3dpbmcgY29tbWFuZC4NCg0KYGBge30NCmlmICghcmVxdWlyZSgicGFja2FnZU5hbWUiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGFja2FnZU5hbWUiKQ0KICAgbGlicmFyeShwYWNrYWdlTmFtZSkNCn0NCmBgYA0KDQpGb3IgZXhhbXBsZSwgaWYgeW91IHdhbnQgdG8gcGVyZm9ybSBhIHotdGVzdCAoaS5lLiwgbm9ybWFsIHRlc3QpLCB3ZSBjYW4gdXNlIHRoZSBSIGZ1bmN0aW9uIGB6LnRlc3QoKWAgaW4gdGhlIHBhY2thZ2UuIFRoZSBmb2xsb3dpbmcgaXMgdGhlIGNvZGUgZm9yIHRlc3RpbmcgQk1JIEhvOiBtdSA8PSAzMCB2cyBIYTogbXUgPiAzMC4NCg0KYGBge3IgZWNobyA9IFRSVUV9DQojIyBpbnN0YWxsIGFuZCBsb2FkIHBhY2thZ2UNCmlmICghcmVxdWlyZSgiQlNEQSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJCU0RBIikNCiAgIGxpYnJhcnkoQlNEQSkNCn0NCiMjIENhbGwgdGhlIGZ1bmN0aW9uIHRvIHBlcmZvcm0gYSBub3JtYWwgdGVzdA0KIyBIbzogbXUgPSAzMCB2cyBIYTogbXUgIT0gMzAsIHRoZSBhbHRlcm5hdGl2ZSBpcyAhPSwgdGhpcyBpcyBhIHR3by1zaWRlZCB0ZXN0DQojIElGIHRoZSB0ZXN0IGlzIHJpZ2h0LXRhaWxlZCwgdGhlIGFsdGVybmF0aXZlIE1VU1QgYmUgc3BlY2lmaWVkIGFzICJncmVhdGVyIiwNCiMgU2ltaWxhcmx5LCBpZiB0aGUgdGVzdCBpcyBsZWZ0LXRhaWxlZCwgdGhlIGFsdGVybmF0aXZlIE1VU1QgYmUgc3BlY2lmaWVkIGFzICJsZXNzIi4NCnoudGVzdCh4ID0gQk1JLCBzaWdtYS54ID0gc2QoQk1JKSwgbXUgPSAzMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCmBgYA0KDQpZb3UgY2FuIHNlZSB0aGF0IHRoZSBvdXRwdXQgYWxzbyBwcm92aWRlcyBhIDk1JSBjb25maWRlbmNlIGludGVydmFsIG9mIHRoZSBtZWFuIEJNSS4NCg0KKipTb21lIGNvbW1vbmx5IHVzZWQgcGFja2FnZXMgY29tZSB3aXRoIHRoZSBSIGJhc2UgcGFja2FnZSoqIC0gdGhpcyBtZWFucyB0aGF0IHlvdSBkb24ndCBuZWVkIHRvIGluc3RhbGwgYW5kIGxvYWQgdGhlc2UgcGFja2FnZXMgd2hlbiB5b3UgdXNlIGFueSBSIGZ1bmN0aW9ucy4gVGhlc2UgcGFja2FnZXMgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGxvYWRlZCB3aGVuIHlvdSBzdGFydCBhbiBSIHNlc3Npb24uIEZvciBleGFtcGxlLCB0aGUgZm9sbG93aW5nIFIgZnVuY3Rpb24gYHByb3AudGVzdCgpYCBmb3IgdGVzdGluZyBwb3B1bGF0aW9uIHByb3BvcnRpb24gaXMgaW4gcGFja2FnZSB7c3RhdHN9Og0KDQpgYGB7ciBlY2hvID0gVFJVRX0NCnByb3AudGVzdCg3NSwgMTM3LCBwID0wLjU3LCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikNCmBgYA0KDQoNCjxmb250IGNvbG9yID0gInJlZCI+KipcY29sb3J7cmVkfVRoZXJlIGFyZSBtb3JlIHRoYW4gMjAsMDAwICh0d2VudHkgdGhvdXNhbmQhKSBSIHBhY2thZ2VzIGFyZSBhdmFpbGFibGUgZm9yIHZhcmlvdXMgYXBwbGljYXRpb25zLioqIDwvZm9udD4gPGZvbnQgY29sb3IgPSAgImJsdWUiPioqXGNvbG9ye2JsdWV9IFdlIHdpbGwgdXNlIGFib3V0IGZpdmUgcGFja2FnZXMgdGhhdCByZXF1aXJlIGluc3RhbGxhdGlvbiBhbmQgZXhwbGljaXQgbG9hZGluZyB0byBhY2Nlc3Mgc3BlY2lmaWMgUiBmdW5jdGlvbnMgZm9yIGFuYWx5c2lzLiBZb3UgZG9u4oCZdCBuZWVkIHRvIG1lbW9yaXplIHRoZSBuYW1lcyBvZiB0aGVzZSBwYWNrYWdlc+KAlEkgZW5jb3VyYWdlIHlvdSB0byB1c2UgQUkgdG9vbHMgbGlrZSBDaGF0R1BUIG9yIHJlbGF0ZWQgQ29waWxvdCBhc3Npc3RhbnRzIHRvIGZpbmQgdGhlIFIgZnVuY3Rpb25zIHlvdSBuZWVkIGZvciB5b3VyIGFuYWx5c2lzLiBJIHdpbGwgYWxzbyBwcm92aWRlIHRoaXMgaW5mb3JtYXRpb24gaW4gbXkgZXhhbXBsZSBjb2RlIHdpdGhpbiB0aGUgbGVjdHVyZSBub3Rlcy4qKjwvZm9udD4NCg0KDQoNCg0KDQoNCg==