Background 
R is a language, or an environment, for data analysis and data visualization.
R is derived form the [S  language](https://en.wikipedia.org/wiki/S_(programming_language)  developed at ATT Bell Laboratories.
R was originally developed for teaching at the University of Auckland, New Zealand, by Ross Ihaka and Robert Gentleman.
R is now maintained by an international group of about 20 statisticians and computer scientists.
A great strength of R is the large number of extension packages that have been developed.
The number available on CRAN  is now over 19,000.
 
Basic Usage 
Interactive R uses a command line interface  (CLI).
The interface runs a read-evaluate-print loop  (REPL).
A simple interaction with the R interpreter:
> 1 + 2
[1] 3Values can be assigned to variables using a left arrow <- combination:
> x <- c(1, 3, 5)
> x
[1] 1 3 5
The = sign can also be used for assignment, but <- is recommended.
 
Basic arithmetic operations work element-wise on vectors:
> x + x
[1]  2  6 10Scalars are recycled  to the length of the longer operand:
> x + 1
[1] 2 4 6> 2 * x
[1]  2  6 10Some ways to create new vectors:
> c(1, 2, 3)
[1] 1 2 3> c("a", "b", "c")
[1] "a" "b" "c"> 1 : 3
[1] 1 2 3These examples show a prompt  as you would see in the interpreter.
Usually Rmarkdown documents show code and results like this:
2 * x
## [1]  2  6 10This makes it easier to copy code for pasting it into another document or the R console.
 
Data Frames 
Data sets in R are often organized in named lists  of variables called data frames .
The value of the variable faithful is a data frame with two variables recorded for eruptions of the Old Faithful  geyser in Yellowstone National Park:
eruptions: Eruption duration (minutes)waiting: Waiting time to next eruption (minutes) 
head() shows the first 6 rows:
head(faithful)
##   eruptions waiting
## 1     3.600      79
## 2     1.800      54
## 3     3.333      74
## 4     2.283      62
## 5     4.533      85
## 6     2.883      55 
A Simple Scatter Plot 
with(faithful,
     plot(eruptions, waiting,
          xlab = "Eruption time (min)",
          ylab = "Waiting time to next eruption (min)"))
Several graphics systems are available for R.
plot() is part of base graphics .
 
Fitting a Linear Regression 
fit <- with(faithful, lm(waiting ~ eruptions))
fit
## 
## Call:
## lm(formula = waiting ~ eruptions)
## 
## Coefficients:
## (Intercept)    eruptions  
##       33.47        10.73You can also use the data argument to lm():
fit <- lm(waiting ~ eruptions, data = faithful)coef() extracts the coefficients:
coef(fit)
## (Intercept)   eruptions 
##    33.47440    10.72964summary(fit) provides more details:
summary(fit)
## 
## Call:
## lm(formula = waiting ~ eruptions, data = faithful)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -12.0796  -4.4831   0.2122   3.9246  15.9719 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  33.4744     1.1549   28.98   <2e-16 ***
## eruptions    10.7296     0.3148   34.09   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.914 on 270 degrees of freedom
## Multiple R-squared:  0.8115, Adjusted R-squared:  0.8108 
## F-statistic:  1162 on 1 and 270 DF,  p-value: < 2.2e-16 
Adding the Regression Line to the Plot 
Original plot:
with(faithful,
     plot(eruptions, waiting,
          xlab = "Eruption time (min)",
          ylab = "Waiting time to next eruption (min)"))
With a regression line:
with(faithful,
     plot(eruptions, waiting,
          xlab = "Eruption time (min)",
          ylab = "Waiting time to next eruption (min)"))
abline(coef(fit), col = "red", lwd = 3)
 
Packages and Package Libraries 
Extension code and data sets are often made available in packages .
Packages are stored in folders or directories as collections called libraries .
.libPaths() will show you the libraries your R process will search.
search() shows what packages are attached to the global search path.
The library() function is used to find packages in the libraries and attach them to the search path.
The expression pkg::var gets the value of variable var from package pkg without attaching pkg.
You can install packages using the install.packages function or the Install Packages  item in the RStudio Tools  menu.
By default packages are installed from CRAN .
It is also possible to use functions in the remotes package to install packages hosted on GitHub  or GitLab .
 
A Useful Package: ggplot2 
The ggplot2 package provides a powerful alternative to the base graphics system.
The geyser example can be done in ggplot2 like this:
library(ggplot2)
ggplot(data = faithful) +
    geom_point(mapping = aes(x = eruptions, y = waiting)) +
    geom_smooth(mapping = aes(x = eruptions, y = waiting),
                method = "lm", se = FALSE)
ggplot2 is part of a useful collection of packages called the tidyverse 
ggplot is based on the Grammar of Graphics .
A basic template for creating a plot with ggplot:
ggplot(data = <DATA>) + <GEOM>(mapping = aes(<MAPPINGS>)) 
 
Subsetting and Extracting Components 
The subset operator  [ can be used to extract element by index:
month.abb
##  [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
month.abb[1 : 3]
## [1] "Jan" "Feb" "Mar"Subsetting can also be based on a logical expression that returns TRUE or FALSE for each element:
(starts_with_J <- substr(month.abb, 1, 1) == "J")
##  [1]  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE
month.abb[starts_with_J]
## [1] "Jan" "Jun" "Jul"
The value of an assignment operation is the right hand side value.
Ordinarily this value is not printed. 
Placing the assignment expression in parentheses causes it to be printed. 
 
 
Individual elements can be extracted using the element operator  [[:
month.abb[[3]]
## [1] "Mar"Components of named lists, like data frames , can be extracted with the $ operator:
names(faithful)
## [1] "eruptions" "waiting"
head(faithful, 4)
##   eruptions waiting
## 1     3.600      79
## 2     1.800      54
## 3     3.333      74
## 4     2.283      62
head(faithful$eruptions, 4)
## [1] 3.600 1.800 3.333 2.283The element operator can be used as well:
head(faithful[["eruptions"]], 4)
## [1] 3.600 1.800 3.333 2.283 
Functions 
Simple Functions 
All computations in R are carried out by functions.
Defining a function allows you to avoid cutting and pasting code.
A simple function:
ms <- function(x) list(mean = mean(x), sd = sd(x))
ms(faithful$eruptions)
## $mean
## [1] 3.487783
## 
## $sd
## [1] 1.141371 
Generic Functions and Object-Oriented Programming 
R supports several mechanisms for object-oriented programming based on generic functions .
The most commonly used mechanism, called S3, allows a function to dispatch  to a method  based on the class  of its first argument.
plot is a very simple generic function.
plot
## function (x, y, ...) 
## UseMethod("plot")
## <bytecode: 0x562822b00028>
## <environment: namespace:base>For example, the plot method for linear model fit objects produces a set of 4 plots commonly used to assess regression fits.
plot(fit)
 
Lazy and Non-Standard Evaluation 
An unusual but useful feature of R is that function arguments are not evaluated until their value is needed, so they may not be evaluated at all.
This is called lazy evaluation .
log("A")
## Error in log("A"): non-numeric argument to mathematical function
f <- function(x) NULL
f(log("A"))
## NULLFunctions can also capture the expression of the arguments they were called with:
f <- function(x) deparse(substitute(x))
f(a + b)
## [1] "a + b"Together these features allow functions to evaluate their arguments in non-standard  ways.
This is most commonly used to allow values for variables in arguments to be found in a provided data frame.
The with() function is a simple example:
mean(eruptions)
## Error in eval(expr, envir, enclos): object 'eruptions' not foundwith(faithful, mean(eruptions))
## [1] 3.487783Non-standard evaluation of this type is used extensively in the tidyverse .
 
 
The Tidyverse 
Tidyverse 
The dplyr package provides a grammar for data manipulation .
A simple example: computing means and standard deviations for the waiting times after the short (less than 3 minutes) and the long (3 minutes or more) eruptions:
library(dplyr)
tmp <- mutate(faithful,
              type = ifelse(eruptions < 3,
                            "short",
                            "long"))
head(tmp)
##   eruptions waiting  type
## 1     3.600      79  long
## 2     1.800      54 short
## 3     3.333      74  long
## 4     2.283      62 short
## 5     4.533      85  long
## 6     2.883      55 shortsummarize(group_by(tmp, type),
          mean = mean(waiting),
          sd = sd(waiting))
## # A tibble: 2 × 3
##   type   mean    sd
##   <chr> <dbl> <dbl>
## 1 long   80.0  5.99
## 2 short  54.5  5.84
Tidyverse functions like to work with an enhanced form of data frame called a tibble .
 
A computation like this can be viewed as a transformation pipeline  consisting of three stages:
mutation (adding a new variable) 
grouping (splitting by type) 
summarizing within groups. 
 
Tidyverse code often uses the forward pipe operator  %>% provided by the magrittr package to express such a pipeline.
R 4.1.0 and later also provides a native pipe operator  |>.
The pipe operator allows a call f(x) to be written as
x |> f()The left hand value is passed implicitly as the first argument to the function called on the right.
Using the pipe operator, the code for computing means and standard deviations can be written as
faithful |>
    mutate(type = ifelse(eruptions < 3, "short", "long")) |>
    group_by(type) |>
    summarize(mean = mean(waiting),
              sd = sd(waiting))
## # A tibble: 2 × 3
##   type   mean    sd
##   <chr> <dbl> <dbl>
## 1 long   80.0  5.99
## 2 short  54.5  5.84There are trade-offs:
Manipulation pipelines expressed this way are often more compact than ones using intermediate variables and/or nested calls.
With pipe notation there is no need to come up with intermediate variable names.
Pipe notation obscures the function calls that are actually happening and this can make debugging harder.
 
 
Contrast to Point-and-Click Interfaces 
Even simple tasks require learning some of the R language.
Once you can do simple tasks, you have learned some of the R language.
More complicated tasks become easier.
Even very complicated tasks become possible.
 
 
R and Reproducibility 
Analyses in R are carried out by running code describing the tasks to perform.
This code can be
audited to make sure the analysis is right;
replayed to make sure the results are repoducible;
reused after changes in the data or on new data.
 
Literate data analysis  tools like Rmarkdown provide support for this.
 
Finding Out More 
Getting Help on Functions 
help(mean) will show help for the function mean.This can be abbreviated as ?mean 
 
 
Some R Introductions and Tutorials 
 
Introductions to the Tidiverse 
 
 
Interactive Tutorial 
An interactive learnravailable .
You can run the tutorial with
STAT4580::runTutorial("Rintro")You can install the current version of the STAT4580 package with
remotes::install_gitlab("luke-tierney/STAT4580")You may need to install the remotes package from CRAN first.
 
Exercises 
Compute the mean of the numbers 1, 3, 5, 8. 
 
What is the mean of the eruptions variable in the faithful data frame? 
 
Find the average of the first 50 eruption durations in the faithful data frame. 
 
Use the median function to modify the pipe example in the tidyverse section  to include medians. 
 
 
LS0tCnRpdGxlOiAiQSBCcmllZiBPdmVydmlldyBvZiBSIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQpzb3VyY2UoaGVyZTo6aGVyZSgic2V0dXAuUiIpKQprbml0cjo6b3B0c19jaHVuayRzZXQoY29sbGFwc2UgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDYsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQpgYGAKPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJzdGF0NDU4MC5jc3MiIHR5cGU9InRleHQvY3NzIiAvPgoKCiMjIEJhY2tncm91bmQKClIgaXMgYSBsYW5ndWFnZSwgb3IgYW4gZW52aXJvbm1lbnQsIGZvciBkYXRhIGFuYWx5c2lzIGFuZCBkYXRhIHZpc3VhbGl6YXRpb24uCgpSIGlzIGRlcml2ZWQgZm9ybSB0aGUgW19TXwpsYW5ndWFnZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU18ocHJvZ3JhbW1pbmdfbGFuZ3VhZ2UpCmRldmVsb3BlZCBhdCBBVFQgQmVsbCBMYWJvcmF0b3JpZXMuCgpSIHdhcyBvcmlnaW5hbGx5IGRldmVsb3BlZCBmb3IgdGVhY2hpbmcgYXQgdGhlIFVuaXZlcnNpdHkgb2YgQXVja2xhbmQsCk5ldyBaZWFsYW5kLCBieSBSb3NzIEloYWthIGFuZCBSb2JlcnQgR2VudGxlbWFuLgoKUiBpcyBub3cgbWFpbnRhaW5lZCBieSBhbiBpbnRlcm5hdGlvbmFsIGdyb3VwIG9mIGFib3V0IDIwCnN0YXRpc3RpY2lhbnMgYW5kIGNvbXB1dGVyIHNjaWVudGlzdHMuCgpBIGdyZWF0IHN0cmVuZ3RoIG9mIFIgaXMgdGhlIGxhcmdlIG51bWJlciBvZiBleHRlbnNpb24gcGFja2FnZXMgdGhhdApoYXZlIGJlZW4gZGV2ZWxvcGVkLgoKVGhlIG51bWJlciBhdmFpbGFibGUgb24gW0NSQU5dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnKSBpcyBub3cgb3ZlcgoxOSwwMDAuCgoKIyMgQmFzaWMgVXNhZ2UKCkludGVyYWN0aXZlIFIgdXNlcyBhIF9jb21tYW5kIGxpbmUgaW50ZXJmYWNlXyAoQ0xJKS4KClRoZSBpbnRlcmZhY2UgcnVucyBhIF9yZWFkLWV2YWx1YXRlLXByaW50IGxvb3BfIChSRVBMKS4KCkEgc2ltcGxlIGludGVyYWN0aW9uIHdpdGggdGhlIFIgaW50ZXJwcmV0ZXI6CgpgYGB7ciwgcHJvbXB0ID0gVFJVRSwgY29tbWVudCA9ICIifQoxICsgMgpgYGAKClZhbHVlcyBjYW4gYmUgYXNzaWduZWQgdG8gdmFyaWFibGVzIHVzaW5nIGEgbGVmdCBhcnJvdyBgPC1gIGNvbWJpbmF0aW9uOgoKYGBge3IsIHByb21wdCA9IFRSVUUsIGNvbW1lbnQgPSAiIn0KeCA8LSBjKDEsIDMsIDUpCngKYGBgCgo8ZGl2IGNsYXNzID0gImFsZXJ0Ij4KVGhlIGA9YCBzaWduIGNhbiBhbHNvIGJlIHVzZWQgZm9yIGFzc2lnbm1lbnQsIGJ1dCBgPC1gIGlzIHJlY29tbWVuZGVkLgo8L2Rpdj4KCkJhc2ljIGFyaXRobWV0aWMgb3BlcmF0aW9ucyB3b3JrIGVsZW1lbnQtd2lzZSBvbiB2ZWN0b3JzOgoKYGBge3IsIHByb21wdCA9IFRSVUUsIGNvbW1lbnQgPSAiIn0KeCArIHgKYGBgCgpTY2FsYXJzIGFyZSBfcmVjeWNsZWRfIHRvIHRoZSBsZW5ndGggb2YgdGhlIGxvbmdlciBvcGVyYW5kOgoKYGBge3IsIHByb21wdCA9IFRSVUUsIGNvbW1lbnQgPSAiIn0KeCArIDEKYGBgCgpgYGB7ciwgcHJvbXB0ID0gVFJVRSwgY29tbWVudCA9ICIifQoyICogeApgYGAKClNvbWUgd2F5cyB0byBjcmVhdGUgbmV3IHZlY3RvcnM6CgpgYGB7ciwgcHJvbXB0ID0gVFJVRSwgY29tbWVudCA9ICIifQpjKDEsIDIsIDMpCmBgYAoKYGBge3IsIHByb21wdCA9IFRSVUUsIGNvbW1lbnQgPSAiIn0KYygiYSIsICJiIiwgImMiKQpgYGAKCmBgYHtyLCBwcm9tcHQgPSBUUlVFLCBjb21tZW50ID0gIiJ9CjEgOiAzCmBgYAoKVGhlc2UgZXhhbXBsZXMgc2hvdyBhIF9wcm9tcHRfIGFzIHlvdSB3b3VsZCBzZWUgaW4gdGhlIGludGVycHJldGVyLgoKVXN1YWxseSBSbWFya2Rvd24gZG9jdW1lbnRzIHNob3cgY29kZSBhbmQgcmVzdWx0cyBsaWtlIHRoaXM6CgpgYGB7cn0KMiAqIHgKYGBgCgpUaGlzIG1ha2VzIGl0IGVhc2llciB0byBjb3B5IGNvZGUgZm9yIHBhc3RpbmcgaXQgaW50byBhbm90aGVyIGRvY3VtZW50Cm9yIHRoZSBSIGNvbnNvbGUuCgoKIyMgRGF0YSBGcmFtZXMKCkRhdGEgc2V0cyBpbiBSIGFyZSBvZnRlbiBvcmdhbml6ZWQgaW4gX25hbWVkIGxpc3RzXyBvZiB2YXJpYWJsZXMKY2FsbGVkIF9kYXRhIGZyYW1lc18uCgpUaGUgdmFsdWUgb2YgdGhlIHZhcmlhYmxlIGBmYWl0aGZ1bGAgaXMgYSBkYXRhIGZyYW1lIHdpdGggdHdvCnZhcmlhYmxlcyByZWNvcmRlZCBmb3IgZXJ1cHRpb25zIG9mIHRoZSBfT2xkIEZhaXRoZnVsXyBnZXlzZXIgaW4gWWVsbG93c3RvbmUKTmF0aW9uYWwgUGFyazoKCiogYGVydXB0aW9uc2A6ICBFcnVwdGlvbiBkdXJhdGlvbiAobWludXRlcykKKiBgd2FpdGluZ2A6ICBXYWl0aW5nIHRpbWUgdG8gbmV4dCBlcnVwdGlvbiAobWludXRlcykKCmBoZWFkKClgIHNob3dzIHRoZSBmaXJzdCA2IHJvd3M6CgpgYGB7cn0KaGVhZChmYWl0aGZ1bCkKYGBgCgoKIyMgQSBTaW1wbGUgU2NhdHRlciBQbG90CgpgYGB7ciBnZXlzZXIsIGV2YWwgPSBGQUxTRX0Kd2l0aChmYWl0aGZ1bCwKICAgICBwbG90KGVydXB0aW9ucywgd2FpdGluZywKICAgICAgICAgIHhsYWIgPSAiRXJ1cHRpb24gdGltZSAobWluKSIsCiAgICAgICAgICB5bGFiID0gIldhaXRpbmcgdGltZSB0byBuZXh0IGVydXB0aW9uIChtaW4pIikpCmBgYAoKPCEtLSAjIyBub2xpbnQgc3RhcnQgLS0+CmBgYHtyIGV2YWwgPSBUUlVFLCBlY2hvID0gRkFMU0UsIGZpZy5oZWlnaHQgPSA0fQpvcCA8LSBwYXIobWFyID0gYyg0LCA0LCAwLjEsIDAuMSkpCjw8Z2V5c2VyPj4KcGFyKG9wKQpgYGAKPCEtLSAjIyBub2xpbnQgZW5kIC0tPgoKU2V2ZXJhbCBncmFwaGljcyBzeXN0ZW1zIGFyZSBhdmFpbGFibGUgZm9yIFIuCgpgcGxvdCgpYCBpcyBwYXJ0IG9mIF9iYXNlIGdyYXBoaWNzXy4KCgojIyBGaXR0aW5nIGEgTGluZWFyIFJlZ3Jlc3Npb24KYGBge3J9CmZpdCA8LSB3aXRoKGZhaXRoZnVsLCBsbSh3YWl0aW5nIH4gZXJ1cHRpb25zKSkKZml0CmBgYAoKWW91IGNhbiBhbHNvIHVzZSB0aGUgYGRhdGFgIGFyZ3VtZW50IHRvIGBsbSgpYDoKCmBgYHtyfQpmaXQgPC0gbG0od2FpdGluZyB+IGVydXB0aW9ucywgZGF0YSA9IGZhaXRoZnVsKQpgYGAKCmBjb2VmKClgIGV4dHJhY3RzIHRoZSBjb2VmZmljaWVudHM6CgpgYGB7cn0KY29lZihmaXQpCmBgYAoKYHN1bW1hcnkoZml0KWAgcHJvdmlkZXMgbW9yZSBkZXRhaWxzOgoKYGBge3J9CnN1bW1hcnkoZml0KQpgYGAKCgojIyBBZGRpbmcgdGhlIFJlZ3Jlc3Npb24gTGluZSB0byB0aGUgUGxvdAoKT3JpZ2luYWwgcGxvdDoKCjwhLS0gIyMgbm9saW50IHN0YXJ0IC0tPgpgYGB7ciwgZXZhbCA9IEZBTFNFfQo8PGdleXNlcj4+CmBgYAo8IS0tICMjIG5vbGludCBlbmQgLS0+CjwhLS0gIyMgbm9saW50IHN0YXJ0IC0tPgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBGQUxTRX0KPDxnZXlzZXI+PgpgYGAKPCEtLSAjIyBub2xpbnQgZW5kIC0tPgoKV2l0aCBhIHJlZ3Jlc3Npb24gbGluZToKCjwhLS0gIyMgbm9saW50IHN0YXJ0IC0tPgpgYGB7ciBnZXlzZXItd2l0aC1saW5lLCBldmFsID0gRkFMU0V9Cjw8Z2V5c2VyPj4KYWJsaW5lKGNvZWYoZml0KSwgY29sID0gInJlZCIsIGx3ZCA9IDMpCmBgYAo8IS0tICMjIG5vbGludCBlbmQgLS0+CgpgYGB7ciBnZXlzZXItd2l0aC1saW5lLCBldmFsID0gVFJVRSwgZWNobyA9IEZBTFNFfQpgYGAKCgojIyBQYWNrYWdlcyBhbmQgUGFja2FnZSBMaWJyYXJpZXMKCkV4dGVuc2lvbiBjb2RlIGFuZCBkYXRhIHNldHMgYXJlIG9mdGVuIG1hZGUgYXZhaWxhYmxlIGluIF9wYWNrYWdlc18uCgpQYWNrYWdlcyBhcmUgc3RvcmVkIGluIGZvbGRlcnMgb3IgZGlyZWN0b3JpZXMgYXMgY29sbGVjdGlvbnMgY2FsbGVkIF9saWJyYXJpZXNfLgoKYC5saWJQYXRocygpYCB3aWxsIHNob3cgeW91IHRoZSBsaWJyYXJpZXMgeW91ciBSIHByb2Nlc3Mgd2lsbCBzZWFyY2guCgpgc2VhcmNoKClgIHNob3dzIHdoYXQgcGFja2FnZXMgYXJlIGF0dGFjaGVkIHRvIHRoZSBnbG9iYWwgc2VhcmNoIHBhdGguCgpUaGUgYGxpYnJhcnkoKWAgZnVuY3Rpb24gaXMgdXNlZCB0byBmaW5kIHBhY2thZ2VzIGluIHRoZSBsaWJyYXJpZXMgYW5kCmF0dGFjaCB0aGVtIHRvIHRoZSBzZWFyY2ggcGF0aC4KClRoZSBleHByZXNzaW9uIGBwa2c6OnZhcmAgZ2V0cyB0aGUgdmFsdWUgb2YgdmFyaWFibGUgYHZhcmAgZnJvbQpwYWNrYWdlIGBwa2dgIHdpdGhvdXQgYXR0YWNoaW5nIGBwa2dgLgoKWW91IGNhbiBpbnN0YWxsIHBhY2thZ2VzIHVzaW5nIHRoZSBgaW5zdGFsbC5wYWNrYWdlc2AgZnVuY3Rpb24gb3IKdGhlICoqSW5zdGFsbCBQYWNrYWdlcyoqIGl0ZW0gaW4gdGhlIFJTdHVkaW8gKipUb29scyoqIG1lbnUuCgpCeSBkZWZhdWx0IHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQgZnJvbSBbQ1JBTl0oY3Jhbi5yLXByb2plY3Qub3JnKS4KCkl0IGlzIGFsc28gcG9zc2libGUgdG8gdXNlIGZ1bmN0aW9ucyBpbiB0aGUgYHJlbW90ZXNgIHBhY2thZ2UgdG8KaW5zdGFsbCBwYWNrYWdlcyBob3N0ZWQgb24gW0dpdEh1Yl0oaHR0cHM6Ly9naXRodWIuY29tLykgb3IKW0dpdExhYl0oaHR0cHM6Ly9hYm91dC5naXRsYWIuY29tLykuCgoKIyMgQSBVc2VmdWwgUGFja2FnZTogYGdncGxvdDJgCgpUaGUgYGdncGxvdDJgIHBhY2thZ2UgcHJvdmlkZXMgYSBwb3dlcmZ1bCBhbHRlcm5hdGl2ZSB0byB0aGUgYmFzZQpncmFwaGljcyBzeXN0ZW0uCgpUaGUgZ2V5c2VyIGV4YW1wbGUgY2FuIGJlIGRvbmUgaW4gYGdncGxvdDJgIGxpa2UgdGhpczoKCmBgYHtyIGdleXNlci1nZ3Bsb3QsIGV2YWwgPSBGQUxTRSwgZWNobyA9IFRSVUV9CmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KGRhdGEgPSBmYWl0aGZ1bCkgKwogICAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBlcnVwdGlvbnMsIHkgPSB3YWl0aW5nKSkgKwogICAgZ2VvbV9zbW9vdGgobWFwcGluZyA9IGFlcyh4ID0gZXJ1cHRpb25zLCB5ID0gd2FpdGluZyksCiAgICAgICAgICAgICAgICBtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKQpgYGAKYGBge3IgZ2V5c2VyLWdncGxvdCwgZXZhbCA9IFRSVUUsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpgYGAKCmBnZ3Bsb3QyYCBpcyBwYXJ0IG9mIGEgdXNlZnVsIGNvbGxlY3Rpb24gb2YgcGFja2FnZXMgY2FsbGVkIHRoZQpbX3RpZHl2ZXJzZV9dKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKS4KCjxkaXYgY2xhc3M9ImFsZXJ0Ij4KYGdncGxvdGAgaXMgYmFzZWQgb24gdGhlIF9HcmFtbWFyIG9mIEdyYXBoaWNzXy4KCiogUGxvdHMgYXJlIGNvbXBvc2VkIG9mIF9nZW9tZXRyaWMgb2JqZWN0c18gKGBnZW9tc2ApLgoKKiBWYXJpYWJsZXMgYXJlIF9tYXBwZWRfIHRvIF9hZXN0aGV0aWMgZmVhdHVyZXNfIG9mIGdlb21ldHJpYyBvYmplY3RzLgoKQSBiYXNpYyB0ZW1wbGF0ZSBmb3IgY3JlYXRpbmcgYSBwbG90IHdpdGggYGdncGxvdGA6Cgo8IS0tICMgbm9saW50IHN0YXJ0IC0tPgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QoZGF0YSA9IDxEQVRBPikgKyA8R0VPTT4obWFwcGluZyA9IGFlcyg8TUFQUElOR1M+KSkKYGBgCjwhLS0gIyBub2xpbnQgZW5kIC0tPgo8L2Rpdj4KCgojIyBTdWJzZXR0aW5nIGFuZCBFeHRyYWN0aW5nIENvbXBvbmVudHMKClRoZSBfc3Vic2V0IG9wZXJhdG9yXyBgW2AgY2FuIGJlIHVzZWQgdG8gZXh0cmFjdCBlbGVtZW50IGJ5IGluZGV4OgoKYGBge3J9Cm1vbnRoLmFiYgptb250aC5hYmJbMSA6IDNdCmBgYAoKU3Vic2V0dGluZyBjYW4gYWxzbyBiZSBiYXNlZCBvbiBhIGxvZ2ljYWwgZXhwcmVzc2lvbiB0aGF0IHJldHVybnMKYFRSVUVgIG9yIGBGQUxTRWAgZm9yIGVhY2ggZWxlbWVudDoKCmBgYHtyfQooc3RhcnRzX3dpdGhfSiA8LSBzdWJzdHIobW9udGguYWJiLCAxLCAxKSA9PSAiSiIpCm1vbnRoLmFiYltzdGFydHNfd2l0aF9KXQpgYGAKCjxkaXYgY2xhc3MgPSAiYWxlcnQiPgpUaGUgdmFsdWUgb2YgYW4gYXNzaWdubWVudCBvcGVyYXRpb24gaXMgdGhlIHJpZ2h0IGhhbmQgc2lkZSB2YWx1ZS4KCiogT3JkaW5hcmlseSB0aGlzIHZhbHVlIGlzIG5vdCBwcmludGVkLgoqIFBsYWNpbmcgdGhlIGFzc2lnbm1lbnQgZXhwcmVzc2lvbiBpbiBwYXJlbnRoZXNlcyBjYXVzZXMgaXQgdG8gYmUKICBwcmludGVkLgo8L2Rpdj4KCkluZGl2aWR1YWwgZWxlbWVudHMgY2FuIGJlIGV4dHJhY3RlZCB1c2luZyB0aGUgX2VsZW1lbnQgb3BlcmF0b3JfIGBbW2A6CgpgYGB7cn0KbW9udGguYWJiW1szXV0KYGBgCgpDb21wb25lbnRzIG9mIG5hbWVkIGxpc3RzLCBsaWtlIF9kYXRhIGZyYW1lc18sIGNhbiBiZSBleHRyYWN0ZWQgd2l0aAp0aGUgYCRgIG9wZXJhdG9yOgoKYGBge3J9Cm5hbWVzKGZhaXRoZnVsKQpoZWFkKGZhaXRoZnVsLCA0KQpoZWFkKGZhaXRoZnVsJGVydXB0aW9ucywgNCkKYGBgCgpUaGUgZWxlbWVudCBvcGVyYXRvciBjYW4gYmUgdXNlZCBhcyB3ZWxsOgoKYGBge3J9CmhlYWQoZmFpdGhmdWxbWyJlcnVwdGlvbnMiXV0sIDQpCmBgYAoKCiMjIEZ1bmN0aW9ucwoKCiMjIyBTaW1wbGUgRnVuY3Rpb25zCgpBbGwgY29tcHV0YXRpb25zIGluIFIgYXJlIGNhcnJpZWQgb3V0IGJ5IGZ1bmN0aW9ucy4KCkRlZmluaW5nIGEgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byBhdm9pZCBjdXR0aW5nIGFuZCBwYXN0aW5nIGNvZGUuCgpBIHNpbXBsZSBmdW5jdGlvbjoKCmBgYHtyfQptcyA8LSBmdW5jdGlvbih4KSBsaXN0KG1lYW4gPSBtZWFuKHgpLCBzZCA9IHNkKHgpKQptcyhmYWl0aGZ1bCRlcnVwdGlvbnMpCmBgYAoKCiMjIyBHZW5lcmljIEZ1bmN0aW9ucyBhbmQgT2JqZWN0LU9yaWVudGVkIFByb2dyYW1taW5nCgpSIHN1cHBvcnRzIHNldmVyYWwgbWVjaGFuaXNtcyBmb3Igb2JqZWN0LW9yaWVudGVkIHByb2dyYW1taW5nIGJhc2VkIG9uCl9nZW5lcmljIGZ1bmN0aW9uc18uCgpUaGUgbW9zdCBjb21tb25seSB1c2VkIG1lY2hhbmlzbSwgY2FsbGVkIFMzLCBhbGxvd3MgYSBmdW5jdGlvbiB0bwpfZGlzcGF0Y2hfIHRvIGEgX21ldGhvZF8gYmFzZWQgb24gdGhlIF9jbGFzc18gb2YgaXRzIGZpcnN0IGFyZ3VtZW50LgoKYHBsb3RgIGlzIGEgdmVyeSBzaW1wbGUgZ2VuZXJpYyBmdW5jdGlvbi4KCmBgYHtyfQpwbG90CmBgYAoKRm9yIGV4YW1wbGUsIHRoZSBgcGxvdGAgbWV0aG9kIGZvciBsaW5lYXIgbW9kZWwgZml0IG9iamVjdHMgcHJvZHVjZXMgYQpzZXQgb2YgNCBwbG90cyBjb21tb25seSB1c2VkIHRvIGFzc2VzcyByZWdyZXNzaW9uIGZpdHMuCgpgYGB7ciBnZXlzZXJfbG1fZml0LCBldmFsID0gRkFMU0V9CnBsb3QoZml0KQpgYGAKYGBge3IsIGVjaG8gPSBGQUxTRSwgZmlnLmhlaWdodCA9IDYuNSwgZmlnLndpZHRoID0gN30Kb3AgPC0gcGFyKG1mcm93ID0gYygyLCAyKSkKPDxnZXlzZXJfbG1fZml0Pj4KcGFyKG9wKQpgYGAKCgojIyMgTGF6eSBhbmQgTm9uLVN0YW5kYXJkIEV2YWx1YXRpb24KCkFuIHVudXN1YWwgYnV0IHVzZWZ1bCBmZWF0dXJlIG9mIFIgaXMgdGhhdCBmdW5jdGlvbiBhcmd1bWVudHMgYXJlIG5vdApldmFsdWF0ZWQgdW50aWwgdGhlaXIgdmFsdWUgaXMgbmVlZGVkLCBzbyB0aGV5IG1heSBub3QgYmUgZXZhbHVhdGVkIGF0CmFsbC4KClRoaXMgaXMgY2FsbGVkIF9sYXp5IGV2YWx1YXRpb25fLgoKYGBge3IsIGVycm9yID0gVFJVRX0KbG9nKCJBIikKZiA8LSBmdW5jdGlvbih4KSBOVUxMCmYobG9nKCJBIikpCmBgYAoKRnVuY3Rpb25zIGNhbiBhbHNvIGNhcHR1cmUgdGhlIGV4cHJlc3Npb24gb2YgdGhlIGFyZ3VtZW50cyB0aGV5IHdlcmUKY2FsbGVkIHdpdGg6CgpgYGB7cn0KZiA8LSBmdW5jdGlvbih4KSBkZXBhcnNlKHN1YnN0aXR1dGUoeCkpCmYoYSArIGIpCmBgYAoKVG9nZXRoZXIgdGhlc2UgZmVhdHVyZXMgYWxsb3cgZnVuY3Rpb25zIHRvIGV2YWx1YXRlIHRoZWlyIGFyZ3VtZW50cyBpbgpfbm9uLXN0YW5kYXJkXyB3YXlzLgoKVGhpcyBpcyBtb3N0IGNvbW1vbmx5IHVzZWQgdG8gYWxsb3cgdmFsdWVzIGZvciB2YXJpYWJsZXMgaW4gYXJndW1lbnRzCnRvIGJlIGZvdW5kIGluIGEgcHJvdmlkZWQgZGF0YSBmcmFtZS4KClRoZSBgd2l0aCgpYCBmdW5jdGlvbiBpcyBhIHNpbXBsZSBleGFtcGxlOgoKYGBge3IsIGVycm9yID0gVFJVRX0KbWVhbihlcnVwdGlvbnMpCmBgYAoKYGBge3J9CndpdGgoZmFpdGhmdWwsIG1lYW4oZXJ1cHRpb25zKSkKYGBgCgpOb24tc3RhbmRhcmQgZXZhbHVhdGlvbiBvZiB0aGlzIHR5cGUgaXMgdXNlZCBleHRlbnNpdmVseSBpbiB0aGUgX3RpZHl2ZXJzZV8uCgoKIyMgVGhlIFRpZHl2ZXJzZQoKW19UaWR5dmVyc2VfXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLykgZnVuY3Rpb25zIGFyZSBkZXNpZ25lZCB0bwpwZXJmb3JtIG9wZXJhdGlvbnMgb24gZGF0YSBmcmFtZXMuCgpUaGUgYGRwbHlyYCBwYWNrYWdlIHByb3ZpZGVzIGEgX2dyYW1tYXIgZm9yIGRhdGEgbWFuaXB1bGF0aW9uXy4KCkEgc2ltcGxlIGV4YW1wbGU6IGNvbXB1dGluZyBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBmb3IgdGhlCndhaXRpbmcgdGltZXMgYWZ0ZXIgdGhlIHNob3J0IChsZXNzIHRoYW4gMyBtaW51dGVzKSBhbmQgdGhlIGxvbmcgKDMKbWludXRlcyBvciBtb3JlKSBlcnVwdGlvbnM6CgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFfQpsaWJyYXJ5KGRwbHlyKQp0bXAgPC0gbXV0YXRlKGZhaXRoZnVsLAogICAgICAgICAgICAgIHR5cGUgPSBpZmVsc2UoZXJ1cHRpb25zIDwgMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzaG9ydCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAibG9uZyIpKQpoZWFkKHRtcCkKYGBgCmBgYHtyfQpzdW1tYXJpemUoZ3JvdXBfYnkodG1wLCB0eXBlKSwKICAgICAgICAgIG1lYW4gPSBtZWFuKHdhaXRpbmcpLAogICAgICAgICAgc2QgPSBzZCh3YWl0aW5nKSkKYGBgCjxkaXYgY2xhc3MgPSAiYWxlcnQiPgpUaWR5dmVyc2UgZnVuY3Rpb25zIGxpa2UgdG8gd29yayB3aXRoIGFuIGVuaGFuY2VkIGZvcm0gb2YgZGF0YSBmcmFtZQpjYWxsZWQgYSBfdGliYmxlXy4KPC9kaXY+CgpBIGNvbXB1dGF0aW9uIGxpa2UgdGhpcyBjYW4gYmUgdmlld2VkIGFzIGEgX3RyYW5zZm9ybWF0aW9uIHBpcGVsaW5lXwpjb25zaXN0aW5nIG9mIHRocmVlIHN0YWdlczoKCiogbXV0YXRpb24gKGFkZGluZyBhIG5ldyB2YXJpYWJsZSkKKiBncm91cGluZyAoc3BsaXR0aW5nIGJ5IGB0eXBlYCkKKiBzdW1tYXJpemluZyB3aXRoaW4gZ3JvdXBzLgogIAoKVGlkeXZlcnNlIGNvZGUgb2Z0ZW4gdXNlcyB0aGUgX2ZvcndhcmQgcGlwZSBvcGVyYXRvcl8gYCU+JWAgcHJvdmlkZWQgYnkKdGhlIGBtYWdyaXR0cmAgcGFja2FnZSB0byBleHByZXNzIHN1Y2ggYSBwaXBlbGluZS4KClIgNC4xLjAgYW5kIGxhdGVyIGFsc28gcHJvdmlkZXMgYSBfbmF0aXZlIHBpcGUgb3BlcmF0b3JfIGB8PmAuCgpUaGUgcGlwZSBvcGVyYXRvciBhbGxvd3MgYSBjYWxsIGBmKHgpYCB0byBiZSB3cml0dGVuIGFzCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQp4IHw+IGYoKQpgYGAKClRoZSBsZWZ0IGhhbmQgdmFsdWUgaXMgcGFzc2VkIGltcGxpY2l0bHkgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHRvIHRoZQpmdW5jdGlvbiBjYWxsZWQgb24gdGhlIHJpZ2h0LgoKVXNpbmcgdGhlIHBpcGUgb3BlcmF0b3IsIHRoZSBjb2RlIGZvciBjb21wdXRpbmcgbWVhbnMgYW5kIHN0YW5kYXJkCmRldmlhdGlvbnMgY2FuIGJlIHdyaXR0ZW4gYXMKCmBgYHtyfQpmYWl0aGZ1bCB8PgogICAgbXV0YXRlKHR5cGUgPSBpZmVsc2UoZXJ1cHRpb25zIDwgMywgInNob3J0IiwgImxvbmciKSkgfD4KICAgIGdyb3VwX2J5KHR5cGUpIHw+CiAgICBzdW1tYXJpemUobWVhbiA9IG1lYW4od2FpdGluZyksCiAgICAgICAgICAgICAgc2QgPSBzZCh3YWl0aW5nKSkKYGBgCgpUaGVyZSBhcmUgdHJhZGUtb2ZmczoKCiogTWFuaXB1bGF0aW9uIHBpcGVsaW5lcyBleHByZXNzZWQgdGhpcyB3YXkgYXJlIG9mdGVuIG1vcmUgY29tcGFjdAogIHRoYW4gb25lcyB1c2luZyBpbnRlcm1lZGlhdGUgdmFyaWFibGVzIGFuZC9vciBuZXN0ZWQgY2FsbHMuCgoqIFdpdGggcGlwZSBub3RhdGlvbiB0aGVyZSBpcyBubyBuZWVkIHRvIGNvbWUgdXAgd2l0aCBpbnRlcm1lZGlhdGUKICB2YXJpYWJsZSBuYW1lcy4KCiogUGlwZSBub3RhdGlvbiBvYnNjdXJlcyB0aGUgZnVuY3Rpb24gY2FsbHMgdGhhdCBhcmUgYWN0dWFsbHkKICBoYXBwZW5pbmcgYW5kIHRoaXMgY2FuIG1ha2UgZGVidWdnaW5nIGhhcmRlci4KCgojIyBDb250cmFzdCB0byBQb2ludC1hbmQtQ2xpY2sgSW50ZXJmYWNlcwoKKiBFdmVuIHNpbXBsZSB0YXNrcyByZXF1aXJlIGxlYXJuaW5nIHNvbWUgb2YgdGhlIFIgbGFuZ3VhZ2UuCgoqIE9uY2UgeW91IGNhbiBkbyBzaW1wbGUgdGFza3MsIHlvdSBoYXZlIGxlYXJuZWQgc29tZSBvZiB0aGUgUiBsYW5ndWFnZS4KCiogTW9yZSBjb21wbGljYXRlZCB0YXNrcyBiZWNvbWUgZWFzaWVyLgoKKiBFdmVuIHZlcnkgY29tcGxpY2F0ZWQgdGFza3MgYmVjb21lIHBvc3NpYmxlLgoKCiMjIFIgYW5kIFJlcHJvZHVjaWJpbGl0eQoKQW5hbHlzZXMgaW4gUiBhcmUgY2FycmllZCBvdXQgYnkgcnVubmluZyBjb2RlIGRlc2NyaWJpbmcgdGhlIHRhc2tzIHRvCnBlcmZvcm0uCgpUaGlzIGNvZGUgY2FuIGJlCgoqIGF1ZGl0ZWQgdG8gbWFrZSBzdXJlIHRoZSBhbmFseXNpcyBpcyByaWdodDsKCiogcmVwbGF5ZWQgdG8gbWFrZSBzdXJlIHRoZSByZXN1bHRzIGFyZSByZXBvZHVjaWJsZTsKCiogcmV1c2VkIGFmdGVyIGNoYW5nZXMgaW4gdGhlIGRhdGEgb3Igb24gbmV3IGRhdGEuCgpfTGl0ZXJhdGUgZGF0YSBhbmFseXNpc18gdG9vbHMgbGlrZSBSbWFya2Rvd24gcHJvdmlkZSBzdXBwb3J0IGZvcgp0aGlzLgoKCiMjIEZpbmRpbmcgT3V0IE1vcmUKCgojIyMgR2V0dGluZyBIZWxwIG9uIEZ1bmN0aW9ucwoKKiBgaGVscChtZWFuKWAgd2lsbCBzaG93IGhlbHAgZm9yIHRoZSBmdW5jdGlvbiBgbWVhbmAuCiogVGhpcyBjYW4gYmUgYWJicmV2aWF0ZWQgYXMgYD9tZWFuYAoKCiMjIyBTb21lIFIgSW50cm9kdWN0aW9ucyBhbmQgVHV0b3JpYWxzCgoqIFtBbiBJbnRyb2R1Y3Rpb24gdG8gUl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvZG9jL21hbnVhbHMvUi1pbnRyby5odG1sKQogIGludHJvZHVjZXMgdGhlIGxhbmd1YWdlIGFuZCBzaG93cyBob3cgdG8gdXNlIFIgZm9yCiAgc3RhdGlzdGljYWwgYW5hbHlzaXMgYW5kIGdyYXBoaWNzLgoqIEFub3RoZXIKICBbaW50cm9kdWN0aW9uIHRvIFJdKGh0dHA6Ly96b29uZWsyLmZyZWUuZnIvVU5JWC80OF9SL2FsbC5odG1sKSBieQogIFZpbmNlbnQgWm9vbmVreW5kLgoqIFtRdWljay1SXShodHRwczovL3d3dy5zdGF0bWV0aG9kcy5uZXQvKSB3ZWIgc2l0ZSByZWxhdGVkIHRvICpSCiAgaW4gQWN0aW9uKiBib29rLgoqIFtSIEZvcgogIEJlZ2lubmVyc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvZG9jL2NvbnRyaWIvUGFyYWRpcy1yZGVidXRzX2VuLnBkZikuCiogW1RyeVJdKGh0dHBzOi8vd3d3LnBsdXJhbHNpZ2h0LmNvbS9zZWFyY2g/cT1SKSBhdCBDb2Rlc2Nob29sLgoqIFtzd2lybDogTGVhcm4gUiBpbiBSXShodHRwczovL3N3aXJsc3RhdHMuY29tLykuCiogW19IYW5kcy1PbiBQcm9ncmFtbWluZyB3aXRoIFJfXShodHRwczovL3JzdHVkaW8tZWR1Y2F0aW9uLmdpdGh1Yi5pby9ob3ByLykuCiogW19SIGZvciBEYXRhIFNjaWVuY2VfXShodHRwczovL3I0ZHMuaGFkbGV5Lm56LykuCiogW0RhdGEgU2NpZW5jZSBEb2pvIFlvdVR1YmUKICB0dXRvcmlhbHNdKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL2MvRGF0YXNjaWVuY2Vkb2pvL3BsYXlsaXN0cz92aWV3PTUwJnNvcnQ9ZGQmc2hlbGZfaWQ9MikuCiogW1R1dG9yaWFscyBhZCBSU3R1ZGlvXShodHRwczovL2VkdWNhdGlvbi5yc3R1ZGlvLmNvbS9sZWFybi8pLgoqIFtSIGZvciB0aGUgUmVzdCBvZiBVc10oaHR0cHM6Ly9yZm9ydGhlcmVzdG9mdXMuY29tLykuCiogVGhlcmUgYXJlIF9tYW55XyBvdGhlcnMuCgoKIyMjIEludHJvZHVjdGlvbnMgdG8gdGhlIFRpZGl2ZXJzZQoKICAqIEhhZGxleSBXaWNraGFtLCBNaW5lIMOHZXRpbmtheWEtUnVuZGVsLCBhbmQgR2FycmV0dCBHcm9sZW11bmQKICAgICgyMDIzKSwgW19SIGZvciBEYXRhIFNjaWVuY2UgKDJuZAogICAgRWRpdGlvbilfXShodHRwczovL3I0ZHMuaGFkbGV5Lm56LyksIE8nUmVpbGx5LiAoW0Jvb2sgc291cmNlIG9uCiAgICBHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9oYWRsZXkvcjRkcykpCgogICogW1IgQmFzaWNzCiAgICBjaGFwdGVyXShodHRwczovL3JhZmFsYWIuZGZjaS5oYXJ2YXJkLmVkdS9kc2Jvb2stcGFydC0xL1IvUi1iYXNpY3MuaHRtbCkKICAgIGluIFJhZmFlbCBBLiBJcml6YXJyeSAoMjAxOSksIFtJbnRyb2R1Y3Rpb24gdG8gRGF0YSBTY2llbmNlOiBfRGF0YQogICAgQW5hbHlzaXMgYW5kIFByZWRpY3Rpb24gQWxnb3JpdGhtcyB3aXRoCiAgICBSX10oaHR0cHM6Ly9yYWZhbGFiLmRmY2kuaGFydmFyZC5lZHUvZHNib29rLXBhcnQtMS8pLCBDaGFwbWFuICYKICAgIEhhbGwvQ1JDLiAoW0Jvb2sgc291cmNlIG9uCiAgICBHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9yYWZhbGFiL2RzYm9vay1wYXJ0LTEpKQoKCiMjIyBSIE1hcmtkb3duIFR1dG9yaWFscwoKKiBbUiBNYXJrZG93bjogVGhlIERlZmluaXRpdmUgR3VpZGVdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi8pCiAgYnkgWWlodWkgWGllIGlzIGEgYm9vay1sZW5ndGggcHJlc2VudGF0aW9uLgoqIFRoZSBbUiBNYXJrZG93biBIb21lIFBhZ2VdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBoYXMgYSBsaW5rCiAgdG8gYSBbdHV0b3JpYWxdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2xlc3Nvbi0xLmh0bWwpLgoKCiMjIEludGVyYWN0aXZlIFR1dG9yaWFsCgpBbiBpbnRlcmFjdGl2ZSBbYGxlYXJucmBdKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vbGVhcm5yLykgdHV0b3JpYWwKZm9yIHRoZXNlIG5vdGVzIGlzIFthdmFpbGFibGVdKGByIFdMTksoInR1dG9yaWFscy9SaW50cm8uUm1kIilgKS4KCllvdSBjYW4gcnVuIHRoZSB0dXRvcmlhbCB3aXRoCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpTVEFUNDU4MDo6cnVuVHV0b3JpYWwoIlJpbnRybyIpCmBgYAoKWW91IGNhbiBpbnN0YWxsIHRoZSBjdXJyZW50IHZlcnNpb24gb2YgdGhlIGBTVEFUNDU4MGAgcGFja2FnZSB3aXRoCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpyZW1vdGVzOjppbnN0YWxsX2dpdGxhYigibHVrZS10aWVybmV5L1NUQVQ0NTgwIikKYGBgCgpZb3UgbWF5IG5lZWQgdG8gaW5zdGFsbCB0aGUgYHJlbW90ZXNgIHBhY2thZ2UgZnJvbSBDUkFOIGZpcnN0LgoKCiMjIEV4ZXJjaXNlcwoKMS4gQ29tcHV0ZSB0aGUgbWVhbiBvZiB0aGUgbnVtYmVycyAxLCAzLCA1LCA4LgoKPCEtLQpUaGUgYW5zd2VyIHRvIEV4ZXJjaXNlIDEgaXMgY2xvc2VzdCB0bwoqIDQuMjUKICA1Ljc1CiAgMy43NQogIDUuMjUKLS0+CgoyLiBXaGF0IGlzIHRoZSBtZWFuIG9mIHRoZSBgZXJ1cHRpb25zYCB2YXJpYWJsZSBpbiB0aGUgYGZhaXRoZnVsYCBkYXRhCiAgIGZyYW1lPwoKPCEtLQpUaGUgYW5zd2VyIHRvIEV4ZXJjaXNlIDIgaXMgY2xvc2VzdCB0bwoqIDMuNDkKICAzLjM1CiAgMy44NwogIDMuMTYKLS0+CgozLiBGaW5kIHRoZSBhdmVyYWdlIG9mIHRoZSBmaXJzdCA1MCBlcnVwdGlvbiBkdXJhdGlvbnMgaW4gdGhlIGBmYWl0aGZ1bGAKICAgZGF0YSBmcmFtZS4KCjwhLS0KVGhlIGFuc3dlciB0byBFeGVyY2lzZSAzIGlzIGNsb3Nlc3QgdG8KKiAzLjMwCiAgMi41MAogIDMuMTMKICA0LjMzCi0tPgoKNC4gVXNlIHRoZSBgbWVkaWFuYCBmdW5jdGlvbiB0byBtb2RpZnkgdGhlIHBpcGUgZXhhbXBsZSBpbiB0aGUKICAgW3RpZHl2ZXJzZSBzZWN0aW9uXSgjdGhlLXRpZHl2ZXJzZSkgdG8gaW5jbHVkZSBtZWRpYW5zLgo=