Mean in R
1.Introduction
Finding the center of a dataset is one of the most common ways to
summarize statistical findings. Often, people communicate the center of
data using words like, on average, usually, or often.
In this lesson, you will learn how to calculate the mean of a
dataset, a common measure of a dataset’s center. We will use the mean to
help us answer the question,
When are adults their most creative and productive?
You could define “creative” and “productive” in a lot of ways, making
this question impossible to fully answer by the end of this lesson.
However, you will form an informed opinion on the question using data of
the one hundred greatest novels of all time.
We collected the dataset from a survey administered by the French
literary magazine, Le Monde. From the dataset, you will calculate the
average age of the authors when their books were published.
Instructions
The histogram to the right displays the ages of 100 authors from the
Le Monde survey. Where do you think the data is centered?
# load libraries
library(readr)
library(dplyr)
library(ggplot2)
# load data frame
greatest_books <- read_csv('top-hundred-books.csv')
#plot data
hist <- qplot(greatest_books$Ages,
geom='histogram',
binwidth = 3,
main = 'Age of Top 100 Novel Authors at Publication',
xlab = 'Publication Age',
ylab = 'Count',
fill=I("blue"),
col=I("red"),
alpha=I(.2))
hist

2.Calculating Mean
The mean, often referred to as the average, is a way to measure the
center of a dataset.
The average of a set is calculated using a two-step process:
1.Add all of the observations in your dataset.
2.Divide the total sum from step one by the number of points in your
dataset.
knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Mean1.png")

Example
Imagine that we wanted to calculate average of a dataset with the
following four observations:
data <- c(4, 6, 2, 8)
Step One: Calculate the total
4+6+2+8=20
Step Two: Divide by the number of observations
The total is equal to 20, and the number of observations is equal to
4.
20 / 4 = 5
The average of this dataset is equal to 5.
Instructions
1.In this exercise, you will use R to find the average age of the
first four authors in Le Monde’s top 100 books.
29,49,42,43
Add the values together, and set total equal to the answer. Print
total.
total <- sum(29, 49, 42, 43)
print(total)
[1] 163
2.Divide total by the number of values in the dataset, and set
mean_value to the answer.
Print mean_value. Keep that number in your head as you progress
through the lesson.
mean_value <- total / 4
print(mean_value)
[1] 40.75
3.Mean in R
While you’ve shown that you can calculate the average yourself, it
becomes time-consuming as the size of your dataset increases — imagine
adding all of the numbers in a dataset with 10,000 observations.
The R mean() function can do the work of adding and dividing for you.
In the example below, we use mean() to calculate the average of a
dataset with ten values:
example_data <- c(24, 16, 30, 10, 12, 28, 38, 2, 4, 36)
example_average <- mean(example_data)
print(example_average)
[1] 20
The code above calculates the average of example_data and saves the
value to example_average. The resulting average of this array is 20.
Instructions
1.Use R to calculate the average value of the author_ages array. Save
the result to average_age and print it.
Does the average age of the authors surprise you? If so, how? Is it
older, or younger than you expected?
# Set author ages to a vector
author_ages <- greatest_books$Ages
# Use R to calculate mean
average_age <- mean(author_ages)
average_age
[1] 41.83
4.Review and Discussion
In this lesson, you learned how to calculate the average of a dataset
using the formula:
knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Mean1.png")

and the R function:
mean(my_data)
Circling back to the original question, do you feel like the average
of our dataset, 42.12, provides us enough information to claim when
someone is their most creative and productive?
Take a look at the histogram and mean (in red) to the right as you
consider this question.
We would say, No. Though we could argue against its use for a few
reasons, below, we’ve highlighted two:
1.The date of publication is not necessarily an author’s most
creative year. When did they start authoring the book? What factors
impacted their writing during those years?
2.The average age of the publishing dates for 100 authors may not
accurately measure peak creativity in other professions. The average age
of painters or sculptors may be very different.
So, what kind of information does the average provide us, and why
would we use the average to describe something when we could display a
histogram?
The most important outcome is that we’re able to use a single number
as a measure of centrality. Although histograms provide more
information, they are not a concise or precise measure of centrality —
the reader must interpret it for themselves.
Instructions
Take a look at the histogram. Are you older or younger than the
average age at publication?
This doesn’t tell you much about when someone will have their most
creative year. However, this type of data could be used as an example in
a broader study on aging.
#plot data
hist <- qplot(greatest_books$Ages,
geom='histogram',
binwidth = 3,
main = 'Age of Top 100 Novel Authors at Publication',
xlab = 'Publication Age',
ylab = 'Count',
fill=I("blue"),
col=I("black"),
alpha=I(.2)) +
geom_vline(aes(xintercept=mean(greatest_books$Ages),
color="mean"), linetype="solid",
size=1) +
scale_color_manual(name = "statistics", values = c(mean = "red"))
hist

Median in R
1.Introduction
In this lesson, you will learn how to find the median of a dataset —
a common measure of a dataset’s center. Each of the next three exercises
will cover the following topics:
1.Manually finding the median of a dataset
2.Using R’s median function to find the median of a dataset
3.Interpreting what it means for a dataset to have similar and
different median and mean values
In the lesson, we will use a dataset of the 100 greatest novels,
determined by a French literary magazine, Le Monde. From the dataset,
you will use the median to answer the question:
When are great authors most likely to publish their best work?
If you are not familiar with mean, also known as average, we
recommend that you learn about it in our lesson on average.
Instructions
The histogram to the right displays the age of authors, at
publication, for the top 100 novels. The red line represents the average
value of this dataset.
You can think of the median as being the observation in your dataset
that falls right in the middle.
Using this informal definition of the median and the graph to the
right, see if you can determine whether the median of this dataset falls
to the right or the left of the mean. We will show you the correct
answer in the last exercise.
#plot data
hist <- qplot(greatest_books$Ages,
geom='histogram',
binwidth = 3,
main = 'Age of Top 100 Novel Authors at Publication',
xlab = 'Publication Age',
ylab = 'Count',
fill=I("blue"),
col=I("black"),
alpha=I(.2)) +
geom_vline( aes(xintercept=mean(greatest_books$Ages),color="mean"), linetype="solid",size=1) +
scale_color_manual(name = "statistics", values = c(mean = "red"))
hist

2.Median
The formal definition for the median of a dataset is:
The value that, assuming the dataset is ordered from smallest to
largest, falls in the middle. If there are an even number of values in a
dataset, you either report both of the middle two values or their
average.
There are always two steps to finding the median of a dataset:
1.Order the values in the dataset from smallest to largest
2.Identify the number(s) that fall(s) in the middle
Example One: Even Number of Values
Say we have a dataset with the following ten numbers:
24, 16, 30, 10, 12, 28, 38, 2, 4, 36
The first step is to order these numbers from smallest to
largest:
2, 4, 10, 12, [16, 24], 28, 30, 36, 38
Because this dataset has an even number of values, there are two
medians: 16 and 24 — 16 has four datapoints to the left, and 24 has four
datapoints to the right.
Although you can report both values as the median, people often
average them. If you averaged 16 and 24, you could report the median as
20.
Example Two: Odd Number of Values
If we added another value (say, 24) to the dataset and sorted it, we
would have:
2, 4, 10, 12, 16, [24], 24, 28, 30, 36, 38
The new median is equal to 24, because there are 5 values to the left
of it, and 5 values to the right of it.
Instructions
1.In the next two steps, you will manually sort an array, and then
determine which value in the array is the median.
In notebook.Rmd, we have a vector with the ages of the first five
authors from Le Monde’s survey:
29,49,42,43,32
Under five_author_ages there is a variable called sorted_author_ages.
Change the 0s in sorted_author_ages to the values in ascending order
from five_author_ages.
# Array of the first five author ages
five_author_ages <- c(29, 49, 42, 43, 32)
# Fill in the empty array with the values sorted
sorted_author_ages <- sort(five_author_ages)
sorted_author_ages
[1] 29 32 42 43 49
2.Set median_value equal to the median of the array.
# Save the median value to median_value
median_value <- 42
# Print the sorted array and median value
cat("The sorted array is:", sorted_author_ages, '\n')
The sorted array is: 29 32 42 43 49
cat(paste("The median of the array is: ", median_value))
The median of the array is: 42
*關於 cat():
cat() 是 “concatenate and print”
的意思,用來將字串和變數輸出成一行文字;
它不像 print() 會自動換行,所以建議你手動加入 ;
如果你用 cat(paste(…)),那麼 paste() 會先組合成一整句,再輸出;
cat() 不會回傳值,也無法直接複製回 RStudio 物件,僅用於輸出文字。
*在 R 中,paste()
是一個用來將多個字串合併成一個字串的函數。它常用於產生動態文字、報告輸出等情境。
name <- "Annabel"
age <- 18
paste("My name is", name, "and I am", age, "years old.")
[1] "My name is Annabel and I am 18 years old."
# 輸出: "My name is Annabel and I am 18 years old."
4.Review and Discussion
In this lesson, you learned how to find the median of a dataset in
two steps:
1.Sort the dataset
2.Identify the one or two numbers that fall in the middle of the
sorted dataset
You also learned how to calculate the median using R:
median(my_data)
Discussion
Take a look at the histogram. It displays the author age distribution
with vertical lines for the mean (red) and median (blue).
Do you feel like the median of our dataset, 40.5, provides us enough
information to claim when authors publish their greatest work?
We argue it does not.
Although the median is a good measure of the dataset’s center, we
cannot make a definitive claim about when authors publish their greatest
work — the youngest author published at 18 and the oldest at 76. It
would be irresponsible to say anything but, “it seems to be possible at
almost any age.”
Notice that the mean and the median are nearly equal. This is not a
surprising result, as both statistics are a measure of the dataset’s
center. However, it’s worth noting that these results will not always be
so close.
In the instructions below, we’ve written a brief explanation that
puts median in the context of our problem.
#plot data
hist <- qplot(greatest_books$Ages,
geom='histogram',
binwidth = 3,
main = 'Age of Top 100 Novel Authors at Publication',
xlab = 'Publication Age',
ylab = 'Count',
fill=I("blue"),
col=I("black"),
alpha=I(.2)) +
geom_vline(aes(xintercept=median(greatest_books$Ages),
color="median"), linetype="dashed",
size=1) +
geom_vline(aes(xintercept=mean(greatest_books$Ages),
color="mean"), linetype="solid",
size=1) +
scale_color_manual(name = "statistics", values = c(median = "blue", mean = "green"))
hist

Instructions
The median age of authors, when they publish their best work, from Le
Monde’s 100 greatest books is 41.
While this does not tell us much about which year is an author’s
greatest year, it does indicate that half of the authors from the survey
find their greatest success before the age of 41 and half find their
greatest success after the age of 41.
Mode in R (眾數)
1.Introduction
In this lesson, you will learn how to find the mode of a dataset.
Each of the next three exercises will cover the following:
1.Manually finding the mode of a dataset
2.Using R’s functions to find the mode
3.Comparing mode to mean and median values
In the lesson, we will use a dataset of the 100 greatest novels,
determined by a French literary magazine, Le Monde. From the dataset,
you will use the mode to answer the question:
What is the most common age for a great author to publish their best
work?
If you are not familiar with mean, also known as average, or median,
we recommend that you learn about it in our lessons on average and
median.
Instructions
The histogram to the right displays the age of authors, at
publication, for the top 100 novels from Le Monde’s survey. The red line
is the mean age, and the blue line is the median age.
Use the definition of mode below and the histogram to the right to
guess where the mode falls. You will calculate the correct answer in the
last exercise.
The mode is the most common observation in a dataset.
You will not be able to find the exact mode, because the histogram
displays bins with a range of values. However, you can guess a range of
values where you are most likely to see the mode.
#plot data
hist <- qplot(greatest_books$Ages,
geom='histogram',
binwidth = 3,
main = 'Age of Top 100 Novel Authors at Publication',
xlab = 'Publication Age',
ylab = 'Count',
fill=I("blue"),
col=I("black"),
alpha=I(.2)) +
geom_vline(aes(xintercept=median(greatest_books$Ages),
color="median"), linetype="dashed",
size=1) +
geom_vline(aes(xintercept=mean(greatest_books$Ages),
color="mean"), linetype="solid",
size=1) +
scale_color_manual(name = "statistics", values = c(median = "blue", mean = "red"))
hist

2.Mode
The formal definition for the mode of a dataset is:
The most frequently occurring observation in the dataset. A dataset
can have multiple modes if there is more than one value with the same
maximum frequency.
While you may be able to find the mode of a small dataset by simply
looking through it, if you have trouble, we recommend you follow these
two steps:
1.Find the frequency of every unique number in the dataset
2.Determine which number has the highest frequency
Example
Say we have a dataset with the following ten numbers:
24, 16, 12, 10, 12, 28, 38, 12, 28, 24
Let’s find the frequency of each number:
24 16 12 10 28 38
2 1 3 1 2 1
From the table, we can see that our mode is 12, the most frequent
number in our dataset.
Instructions
1.Determine the mode of the ages for the first ten authors in the Le
Monde survey:
29,49,42,43,32,38,37,41,27,27
Save the value to mode_age.
mode_age <- 27
mode_age
[1] 27
2.Determine the number of authors who were the age of the mode. Save
the number to mode_count.
mode_count <- 2
mode_count
[1] 2
3.Mode with DescTools
Finding the mode of a dataset becomes increasingly time-consuming as
the size of your dataset increases — imagine finding the mode of a
dataset with 10,000 observations.
The R package DescTools includes a handy Mode() function which can do
the work of finding the mode for us. In the example below, we use Mode()
to calculate the mode of a dataset with ten values:
Example: One Mode
library(DescTools)
example_data <- c(24, 16, 12, 10, 12, 28, 38, 12, 28, 24)
example_mode <- Mode(example_data)
The code above calculates the mode of the values in example_data and
saves it to example_mode.
The result of Mode() is a vector with the mode value:
example_mode
[1] 12
attr(,"freq")
[1] 3
Example: Two Modes
If there are multiple modes, the Mode() function will return them as
a vector.
Let’s look at a vector with two modes, 12 and 24:
example_data = c(24, 16, 12, 10, 12, 24, 38, 12, 28, 24)
example_mode = Mode(example_data)
The result is:
example_mode
[1] 12 24
attr(,"freq")
[1] 3
Instructions
1.We have already imported the DescTools library for you.
Delete the current value set to mode_age.
Find the mode of the observations in the author_ages array. Save the
result to mode_age.
# Set author ages to
author_ages <- greatest_books$Ages
mode_age <- Mode(author_ages)
print(paste("The mode age of authors from Le Monde's 100 greatest books is: ", mode_age[1]))
[1] "The mode age of authors from Le Monde's 100 greatest books is: 38"
4.Review and Discussion
In this lesson, you learned how to find the mode of a dataset in two
steps:
1.Find the frequency of every unique number in the dataset
2.Determine which number has the highest frequency
You also learned how to calculate the mode using DescTools:
Mode(my_array)
Discussion
In this lesson, you found that 38 was the most common age, at
publication, for an author from the Le Monde survey. How does this
number compare to your guess from the beginning of the lesson?
The mode is close to the median and mean of the dataset, but it is
not in the tallest bucket. This should not be surprising, as the
histogram indicates the data is centered between the ages of 30 and 50 —
there is a higher chance of a mode in that range than outside of it.
The mode is not always this close to the median and mean, and often
will not be in the tallest bucket.
Look at the 25-30 year-old bin. There are nine observations in it. If
all the values in that bin happened to be 27, then the dataset’s mode
would be 27. Although unlikely, it is possible. Below, we show what this
would look like:
knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Mean2.png")

Based on this graph, it is fair to say the mode may not always be a
great measure of where the data is centered. Simply put, mode is a
measure of the most frequent observation in the dataset, and is not an
indication of the tallest bin in a histogram.
In the instructions below, we’ve written a brief explanation that
puts mode in the context of our problem.
Instructions
#plot data
hist <- qplot(greatest_books$Ages,
geom='histogram',
binwidth = 3,
main = 'Age of Top 100 Novel Authors at Publication',
xlab = 'Publication Age',
ylab = 'Count',
fill=I("blue"),
col=I("black"),
alpha=I(.2)) +
geom_vline(aes(xintercept=median(greatest_books$Ages),
color="median"), linetype="dashed",
size=1) +
geom_vline(aes(xintercept=mean(greatest_books$Ages),
color="mean"), linetype="solid",
size=1) +
geom_vline(aes(xintercept=38,
color="mode"), linetype="solid",
size=1) +
scale_color_manual(name = "statistics", values = c(median = "blue", mean = "red", mode="green"))
hist

LS0tDQp0aXRsZTogIkxlYXJuIFI6IE1lYW4sIE1lZGlhbiwgYW5kIE1vZGUiDQphdXRob3I6ICJBbm5hYmVsIEt1byINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVZLSVtLSVkICVIOiVNJylgIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyBNZWFuIGluIFINCiMgMS5JbnRyb2R1Y3Rpb24NCg0KRmluZGluZyB0aGUgY2VudGVyIG9mIGEgZGF0YXNldCBpcyBvbmUgb2YgdGhlIG1vc3QgY29tbW9uIHdheXMgdG8gc3VtbWFyaXplIHN0YXRpc3RpY2FsIGZpbmRpbmdzLiBPZnRlbiwgcGVvcGxlIGNvbW11bmljYXRlIHRoZSBjZW50ZXIgb2YgZGF0YSB1c2luZyB3b3JkcyBsaWtlLCBvbiBhdmVyYWdlLCB1c3VhbGx5LCBvciBvZnRlbi4NCg0KSW4gdGhpcyBsZXNzb24sIHlvdSB3aWxsIGxlYXJuIGhvdyB0byBjYWxjdWxhdGUgdGhlIG1lYW4gb2YgYSBkYXRhc2V0LCBhIGNvbW1vbiBtZWFzdXJlIG9mIGEgZGF0YXNldOKAmXMgY2VudGVyLiBXZSB3aWxsIHVzZSB0aGUgbWVhbiB0byBoZWxwIHVzIGFuc3dlciB0aGUgcXVlc3Rpb24sDQoNCldoZW4gYXJlIGFkdWx0cyB0aGVpciBtb3N0IGNyZWF0aXZlIGFuZCBwcm9kdWN0aXZlPw0KDQpZb3UgY291bGQgZGVmaW5lIOKAnGNyZWF0aXZl4oCdIGFuZCDigJxwcm9kdWN0aXZl4oCdIGluIGEgbG90IG9mIHdheXMsIG1ha2luZyB0aGlzIHF1ZXN0aW9uIGltcG9zc2libGUgdG8gZnVsbHkgYW5zd2VyIGJ5IHRoZSBlbmQgb2YgdGhpcyBsZXNzb24uIEhvd2V2ZXIsIHlvdSB3aWxsIGZvcm0gYW4gaW5mb3JtZWQgb3BpbmlvbiBvbiB0aGUgcXVlc3Rpb24gdXNpbmcgZGF0YSBvZiB0aGUgb25lIGh1bmRyZWQgZ3JlYXRlc3Qgbm92ZWxzIG9mIGFsbCB0aW1lLg0KDQpXZSBjb2xsZWN0ZWQgdGhlIGRhdGFzZXQgZnJvbSBhIHN1cnZleSBhZG1pbmlzdGVyZWQgYnkgdGhlIEZyZW5jaCBsaXRlcmFyeSBtYWdhemluZSwgTGUgTW9uZGUuIEZyb20gdGhlIGRhdGFzZXQsIHlvdSB3aWxsIGNhbGN1bGF0ZSB0aGUgYXZlcmFnZSBhZ2Ugb2YgdGhlIGF1dGhvcnMgd2hlbiB0aGVpciBib29rcyB3ZXJlIHB1Ymxpc2hlZC4NCg0KIyMgSW5zdHJ1Y3Rpb25zDQoNClRoZSBoaXN0b2dyYW0gdG8gdGhlIHJpZ2h0IGRpc3BsYXlzIHRoZSBhZ2VzIG9mIDEwMCBhdXRob3JzIGZyb20gdGhlIExlIE1vbmRlIHN1cnZleS4gV2hlcmUgZG8geW91IHRoaW5rIHRoZSBkYXRhIGlzIGNlbnRlcmVkPw0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBsb2FkIGxpYnJhcmllcw0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgbG9hZCBkYXRhIGZyYW1lDQpncmVhdGVzdF9ib29rcyA8LSByZWFkX2NzdigndG9wLWh1bmRyZWQtYm9va3MuY3N2JykNCg0KDQoNCiNwbG90IGRhdGENCmhpc3QgPC0gcXBsb3QoZ3JlYXRlc3RfYm9va3MkQWdlcywNCiAgICAgIGdlb209J2hpc3RvZ3JhbScsDQogICAgICBiaW53aWR0aCA9IDMsICANCiAgICAgIG1haW4gPSAnQWdlIG9mIFRvcCAxMDAgTm92ZWwgQXV0aG9ycyBhdCBQdWJsaWNhdGlvbicsIA0KICAgICAgeGxhYiA9ICdQdWJsaWNhdGlvbiBBZ2UnLA0KICAgICAgeWxhYiA9ICdDb3VudCcsDQogICAgICBmaWxsPUkoImJsdWUiKSwgDQogICAgICBjb2w9SSgicmVkIiksIA0KICAgICAgYWxwaGE9SSguMikpIA0KDQpoaXN0DQpgYGANCg0KIyAyLkNhbGN1bGF0aW5nIE1lYW4NCg0KVGhlIG1lYW4sIG9mdGVuIHJlZmVycmVkIHRvIGFzIHRoZSBhdmVyYWdlLCBpcyBhIHdheSB0byBtZWFzdXJlIHRoZSBjZW50ZXIgb2YgYSBkYXRhc2V0Lg0KDQpUaGUgYXZlcmFnZSBvZiBhIHNldCBpcyBjYWxjdWxhdGVkIHVzaW5nIGEgdHdvLXN0ZXAgcHJvY2VzczoNCg0KMS5BZGQgYWxsIG9mIHRoZSBvYnNlcnZhdGlvbnMgaW4geW91ciBkYXRhc2V0Lg0KDQoyLkRpdmlkZSB0aGUgdG90YWwgc3VtIGZyb20gc3RlcCBvbmUgYnkgdGhlIG51bWJlciBvZiBwb2ludHMgaW4geW91ciBkYXRhc2V0Lg0KDQpgYGB7ciBNZWFuMSwgb3V0LndpZHRoPSI2MCUifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzL2t1b2FuL0Rlc2t0b3AvUiBDb2RlL01lYW4xLnBuZyIpDQpgYGANCiMjIEV4YW1wbGUNCg0KSW1hZ2luZSB0aGF0IHdlIHdhbnRlZCB0byBjYWxjdWxhdGUgYXZlcmFnZSBvZiBhIGRhdGFzZXQgd2l0aCB0aGUgZm9sbG93aW5nIGZvdXIgb2JzZXJ2YXRpb25zOg0KYGBge3J9DQpkYXRhIDwtIGMoNCwgNiwgMiwgOCkNCmBgYA0KDQojIyMgU3RlcCBPbmU6IENhbGN1bGF0ZSB0aGUgdG90YWwNCg0KNCs2KzIrOD0yMA0KDQojIyMgU3RlcCBUd286IERpdmlkZSBieSB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucw0KDQpUaGUgdG90YWwgaXMgZXF1YWwgdG8gMjAsIGFuZCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBpcyBlcXVhbCB0byA0Lg0KDQoyMCAvIDQgPSA1DQoNClRoZSBhdmVyYWdlIG9mIHRoaXMgZGF0YXNldCBpcyBlcXVhbCB0byA1Lg0KDQojIyBJbnN0cnVjdGlvbnMNCg0KMS5JbiB0aGlzIGV4ZXJjaXNlLCB5b3Ugd2lsbCB1c2UgUiB0byBmaW5kIHRoZSBhdmVyYWdlIGFnZSBvZiB0aGUgZmlyc3QgZm91ciBhdXRob3JzIGluIExlIE1vbmRl4oCZcyB0b3AgMTAwIGJvb2tzLg0KDQoyOSw0OSw0Miw0Mw0KDQpBZGQgdGhlIHZhbHVlcyB0b2dldGhlciwgYW5kIHNldCB0b3RhbCBlcXVhbCB0byB0aGUgYW5zd2VyLiBQcmludCB0b3RhbC4NCg0KYGBge3J9DQp0b3RhbCA8LSBzdW0oMjksIDQ5LCA0MiwgNDMpDQpwcmludCh0b3RhbCkNCmBgYA0KDQoyLkRpdmlkZSB0b3RhbCBieSB0aGUgbnVtYmVyIG9mIHZhbHVlcyBpbiB0aGUgZGF0YXNldCwgYW5kIHNldCBtZWFuX3ZhbHVlIHRvIHRoZSBhbnN3ZXIuDQoNClByaW50IG1lYW5fdmFsdWUuIEtlZXAgdGhhdCBudW1iZXIgaW4geW91ciBoZWFkIGFzIHlvdSBwcm9ncmVzcyB0aHJvdWdoIHRoZSBsZXNzb24uDQoNCmBgYHtyfQ0KbWVhbl92YWx1ZSA8LSB0b3RhbCAvIDQNCnByaW50KG1lYW5fdmFsdWUpDQpgYGANCg0KIyAzLk1lYW4gaW4gUg0KDQpXaGlsZSB5b3XigJl2ZSBzaG93biB0aGF0IHlvdSBjYW4gY2FsY3VsYXRlIHRoZSBhdmVyYWdlIHlvdXJzZWxmLCBpdCBiZWNvbWVzIHRpbWUtY29uc3VtaW5nIGFzIHRoZSBzaXplIG9mIHlvdXIgZGF0YXNldCBpbmNyZWFzZXMg4oCUIGltYWdpbmUgYWRkaW5nIGFsbCBvZiB0aGUgbnVtYmVycyBpbiBhIGRhdGFzZXQgd2l0aCAxMCwwMDAgb2JzZXJ2YXRpb25zLg0KDQpUaGUgUiBtZWFuKCkgZnVuY3Rpb24gY2FuIGRvIHRoZSB3b3JrIG9mIGFkZGluZyBhbmQgZGl2aWRpbmcgZm9yIHlvdS4gSW4gdGhlIGV4YW1wbGUgYmVsb3csIHdlIHVzZSBtZWFuKCkgdG8gY2FsY3VsYXRlIHRoZSBhdmVyYWdlIG9mIGEgZGF0YXNldCB3aXRoIHRlbiB2YWx1ZXM6DQoNCmBgYHtyfQ0KZXhhbXBsZV9kYXRhIDwtIGMoMjQsIDE2LCAzMCwgMTAsIDEyLCAyOCwgMzgsIDIsIDQsIDM2KQ0KDQpleGFtcGxlX2F2ZXJhZ2UgPC0gbWVhbihleGFtcGxlX2RhdGEpDQoNCnByaW50KGV4YW1wbGVfYXZlcmFnZSkNCg0KYGBgDQoNClRoZSBjb2RlIGFib3ZlIGNhbGN1bGF0ZXMgdGhlIGF2ZXJhZ2Ugb2YgZXhhbXBsZV9kYXRhIGFuZCBzYXZlcyB0aGUgdmFsdWUgdG8gZXhhbXBsZV9hdmVyYWdlLiBUaGUgcmVzdWx0aW5nIGF2ZXJhZ2Ugb2YgdGhpcyBhcnJheSBpcyAyMC4NCg0KIyMgSW5zdHJ1Y3Rpb25zDQoNCg0KMS5Vc2UgUiB0byBjYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgdmFsdWUgb2YgdGhlIGF1dGhvcl9hZ2VzIGFycmF5LiBTYXZlIHRoZSByZXN1bHQgdG8gYXZlcmFnZV9hZ2UgYW5kIHByaW50IGl0Lg0KDQpEb2VzIHRoZSBhdmVyYWdlIGFnZSBvZiB0aGUgYXV0aG9ycyBzdXJwcmlzZSB5b3U/IElmIHNvLCBob3c/IElzIGl0IG9sZGVyLCBvciB5b3VuZ2VyIHRoYW4geW91IGV4cGVjdGVkPw0KDQpgYGB7cn0NCiMgU2V0IGF1dGhvciBhZ2VzIHRvIGEgdmVjdG9yDQphdXRob3JfYWdlcyA8LSBncmVhdGVzdF9ib29rcyRBZ2VzDQoNCiMgVXNlIFIgdG8gY2FsY3VsYXRlIG1lYW4NCmF2ZXJhZ2VfYWdlIDwtIG1lYW4oYXV0aG9yX2FnZXMpDQphdmVyYWdlX2FnZQ0KYGBgDQoNCiMgNC5SZXZpZXcgYW5kIERpc2N1c3Npb24NCg0KSW4gdGhpcyBsZXNzb24sIHlvdSBsZWFybmVkIGhvdyB0byBjYWxjdWxhdGUgdGhlIGF2ZXJhZ2Ugb2YgYSBkYXRhc2V0IHVzaW5nIHRoZSBmb3JtdWxhOg0KDQpgYGB7ciAsIG91dC53aWR0aD0iNjAlIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9rdW9hbi9EZXNrdG9wL1IgQ29kZS9NZWFuMS5wbmciKQ0KYGBgDQoNCmFuZCB0aGUgUiBmdW5jdGlvbjoNCg0KbWVhbihteV9kYXRhKQ0KDQpDaXJjbGluZyBiYWNrIHRvIHRoZSBvcmlnaW5hbCBxdWVzdGlvbiwgZG8geW91IGZlZWwgbGlrZSB0aGUgYXZlcmFnZSBvZiBvdXIgZGF0YXNldCwgNDIuMTIsIHByb3ZpZGVzIHVzIGVub3VnaCBpbmZvcm1hdGlvbiB0byBjbGFpbSB3aGVuIHNvbWVvbmUgaXMgdGhlaXIgbW9zdCBjcmVhdGl2ZSBhbmQgcHJvZHVjdGl2ZT8NCg0KVGFrZSBhIGxvb2sgYXQgdGhlIGhpc3RvZ3JhbSBhbmQgbWVhbiAoaW4gcmVkKSB0byB0aGUgcmlnaHQgYXMgeW91IGNvbnNpZGVyIHRoaXMgcXVlc3Rpb24uDQoNCldlIHdvdWxkIHNheSwgTm8uIFRob3VnaCB3ZSBjb3VsZCBhcmd1ZSBhZ2FpbnN0IGl0cyB1c2UgZm9yIGEgZmV3IHJlYXNvbnMsIGJlbG93LCB3ZeKAmXZlIGhpZ2hsaWdodGVkIHR3bzoNCg0KMS5UaGUgZGF0ZSBvZiBwdWJsaWNhdGlvbiBpcyBub3QgbmVjZXNzYXJpbHkgYW4gYXV0aG9y4oCZcyBtb3N0IGNyZWF0aXZlIHllYXIuIFdoZW4gZGlkIHRoZXkgc3RhcnQgYXV0aG9yaW5nIHRoZSBib29rPyBXaGF0IGZhY3RvcnMgaW1wYWN0ZWQgdGhlaXIgd3JpdGluZyBkdXJpbmcgdGhvc2UgeWVhcnM/DQoNCjIuVGhlIGF2ZXJhZ2UgYWdlIG9mIHRoZSBwdWJsaXNoaW5nIGRhdGVzIGZvciAxMDAgYXV0aG9ycyBtYXkgbm90IGFjY3VyYXRlbHkgbWVhc3VyZSBwZWFrIGNyZWF0aXZpdHkgaW4gb3RoZXIgcHJvZmVzc2lvbnMuIFRoZSBhdmVyYWdlIGFnZSBvZiBwYWludGVycyBvciBzY3VscHRvcnMgbWF5IGJlIHZlcnkgZGlmZmVyZW50Lg0KDQpTbywgd2hhdCBraW5kIG9mIGluZm9ybWF0aW9uIGRvZXMgdGhlIGF2ZXJhZ2UgcHJvdmlkZSB1cywgYW5kIHdoeSB3b3VsZCB3ZSB1c2UgdGhlIGF2ZXJhZ2UgdG8gZGVzY3JpYmUgc29tZXRoaW5nIHdoZW4gd2UgY291bGQgZGlzcGxheSBhIGhpc3RvZ3JhbT8NCg0KVGhlIG1vc3QgaW1wb3J0YW50IG91dGNvbWUgaXMgdGhhdCB3ZeKAmXJlIGFibGUgdG8gdXNlIGEgc2luZ2xlIG51bWJlciBhcyBhIG1lYXN1cmUgb2YgY2VudHJhbGl0eS4gQWx0aG91Z2ggaGlzdG9ncmFtcyBwcm92aWRlIG1vcmUgaW5mb3JtYXRpb24sIHRoZXkgYXJlIG5vdCBhIGNvbmNpc2Ugb3IgcHJlY2lzZSBtZWFzdXJlIG9mIGNlbnRyYWxpdHkg4oCUIHRoZSByZWFkZXIgbXVzdCBpbnRlcnByZXQgaXQgZm9yIHRoZW1zZWx2ZXMuDQoNCiMjIEluc3RydWN0aW9ucw0KDQpUYWtlIGEgbG9vayBhdCB0aGUgaGlzdG9ncmFtLiBBcmUgeW91IG9sZGVyIG9yIHlvdW5nZXIgdGhhbiB0aGUgYXZlcmFnZSBhZ2UgYXQgcHVibGljYXRpb24/DQoNClRoaXMgZG9lc27igJl0IHRlbGwgeW91IG11Y2ggYWJvdXQgd2hlbiBzb21lb25lIHdpbGwgaGF2ZSB0aGVpciBtb3N0IGNyZWF0aXZlIHllYXIuIEhvd2V2ZXIsIHRoaXMgdHlwZSBvZiBkYXRhIGNvdWxkIGJlIHVzZWQgYXMgYW4gZXhhbXBsZSBpbiBhIGJyb2FkZXIgc3R1ZHkgb24gYWdpbmcuDQoNCmBgYHtyfQ0KI3Bsb3QgZGF0YQ0KaGlzdCA8LSBxcGxvdChncmVhdGVzdF9ib29rcyRBZ2VzLA0KICAgICAgZ2VvbT0naGlzdG9ncmFtJywNCiAgICAgIGJpbndpZHRoID0gMywgIA0KICAgICAgbWFpbiA9ICdBZ2Ugb2YgVG9wIDEwMCBOb3ZlbCBBdXRob3JzIGF0IFB1YmxpY2F0aW9uJywgDQogICAgICB4bGFiID0gJ1B1YmxpY2F0aW9uIEFnZScsDQogICAgICB5bGFiID0gJ0NvdW50JywNCiAgICAgIGZpbGw9SSgiYmx1ZSIpLCANCiAgICAgIGNvbD1JKCJibGFjayIpLCANCiAgICAgIGFscGhhPUkoLjIpKSArDQogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVhbihncmVhdGVzdF9ib29rcyRBZ2VzKSwNCiAgICAgICAgICAgICAgICAgY29sb3I9Im1lYW4iKSwgbGluZXR5cGU9InNvbGlkIiwNCiAgICAgICAgICAgICBzaXplPTEpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWUgPSAic3RhdGlzdGljcyIsIHZhbHVlcyA9IGMobWVhbiA9ICJyZWQiKSkNCg0KaGlzdA0KYGBgDQoNCiMgTWVkaWFuIGluIFINCiMgMS5JbnRyb2R1Y3Rpb24NCg0KSW4gdGhpcyBsZXNzb24sIHlvdSB3aWxsIGxlYXJuIGhvdyB0byBmaW5kIHRoZSBtZWRpYW4gb2YgYSBkYXRhc2V0IOKAlCBhIGNvbW1vbiBtZWFzdXJlIG9mIGEgZGF0YXNldOKAmXMgY2VudGVyLiBFYWNoIG9mIHRoZSBuZXh0IHRocmVlIGV4ZXJjaXNlcyB3aWxsIGNvdmVyIHRoZSBmb2xsb3dpbmcgdG9waWNzOg0KDQoxLk1hbnVhbGx5IGZpbmRpbmcgdGhlIG1lZGlhbiBvZiBhIGRhdGFzZXQNCg0KMi5Vc2luZyBS4oCZcyBtZWRpYW4gZnVuY3Rpb24gdG8gZmluZCB0aGUgbWVkaWFuIG9mIGEgZGF0YXNldA0KDQozLkludGVycHJldGluZyB3aGF0IGl0IG1lYW5zIGZvciBhIGRhdGFzZXQgdG8gaGF2ZSBzaW1pbGFyIGFuZCBkaWZmZXJlbnQgbWVkaWFuIGFuZCBtZWFuIHZhbHVlcw0KDQpJbiB0aGUgbGVzc29uLCB3ZSB3aWxsIHVzZSBhIGRhdGFzZXQgb2YgdGhlIDEwMCBncmVhdGVzdCBub3ZlbHMsIGRldGVybWluZWQgYnkgYSBGcmVuY2ggbGl0ZXJhcnkgbWFnYXppbmUsIExlIE1vbmRlLiBGcm9tIHRoZSBkYXRhc2V0LCB5b3Ugd2lsbCB1c2UgdGhlIG1lZGlhbiB0byBhbnN3ZXIgdGhlIHF1ZXN0aW9uOg0KDQpXaGVuIGFyZSBncmVhdCBhdXRob3JzIG1vc3QgbGlrZWx5IHRvIHB1Ymxpc2ggdGhlaXIgYmVzdCB3b3JrPw0KDQpJZiB5b3UgYXJlIG5vdCBmYW1pbGlhciB3aXRoIG1lYW4sIGFsc28ga25vd24gYXMgYXZlcmFnZSwgd2UgcmVjb21tZW5kIHRoYXQgeW91IGxlYXJuIGFib3V0IGl0IGluIG91ciBsZXNzb24gb24gYXZlcmFnZS4NCg0KIyMgSW5zdHJ1Y3Rpb25zDQoNClRoZSBoaXN0b2dyYW0gdG8gdGhlIHJpZ2h0IGRpc3BsYXlzIHRoZSBhZ2Ugb2YgYXV0aG9ycywgYXQgcHVibGljYXRpb24sIGZvciB0aGUgdG9wIDEwMCBub3ZlbHMuIFRoZSByZWQgbGluZSByZXByZXNlbnRzIHRoZSBhdmVyYWdlIHZhbHVlIG9mIHRoaXMgZGF0YXNldC4NCg0KWW91IGNhbiB0aGluayBvZiB0aGUgbWVkaWFuIGFzIGJlaW5nIHRoZSBvYnNlcnZhdGlvbiBpbiB5b3VyIGRhdGFzZXQgdGhhdCBmYWxscyByaWdodCBpbiB0aGUgbWlkZGxlLg0KDQpVc2luZyB0aGlzIGluZm9ybWFsIGRlZmluaXRpb24gb2YgdGhlIG1lZGlhbiBhbmQgdGhlIGdyYXBoIHRvIHRoZSByaWdodCwgc2VlIGlmIHlvdSBjYW4gZGV0ZXJtaW5lIHdoZXRoZXIgdGhlIG1lZGlhbiBvZiB0aGlzIGRhdGFzZXQgZmFsbHMgdG8gdGhlIHJpZ2h0IG9yIHRoZSBsZWZ0IG9mIHRoZSBtZWFuLiBXZSB3aWxsIHNob3cgeW91IHRoZSBjb3JyZWN0IGFuc3dlciBpbiB0aGUgbGFzdCBleGVyY2lzZS4NCg0KYGBge3J9DQojcGxvdCBkYXRhDQpoaXN0IDwtIHFwbG90KGdyZWF0ZXN0X2Jvb2tzJEFnZXMsDQogICAgICBnZW9tPSdoaXN0b2dyYW0nLA0KICAgICAgYmlud2lkdGggPSAzLCAgDQogICAgICBtYWluID0gJ0FnZSBvZiBUb3AgMTAwIE5vdmVsIEF1dGhvcnMgYXQgUHVibGljYXRpb24nLCANCiAgICAgIHhsYWIgPSAnUHVibGljYXRpb24gQWdlJywNCiAgICAgIHlsYWIgPSAnQ291bnQnLA0KICAgICAgZmlsbD1JKCJibHVlIiksIA0KICAgICAgY29sPUkoImJsYWNrIiksIA0KICAgICAgYWxwaGE9SSguMikpICsNCiAgZ2VvbV92bGluZSggYWVzKHhpbnRlcmNlcHQ9bWVhbihncmVhdGVzdF9ib29rcyRBZ2VzKSxjb2xvcj0ibWVhbiIpLCBsaW5ldHlwZT0ic29saWQiLHNpemU9MSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZSA9ICJzdGF0aXN0aWNzIiwgdmFsdWVzID0gYyhtZWFuID0gInJlZCIpKQ0KDQpoaXN0DQpgYGANCg0KIyAyLk1lZGlhbg0KDQpUaGUgZm9ybWFsIGRlZmluaXRpb24gZm9yIHRoZSBtZWRpYW4gb2YgYSBkYXRhc2V0IGlzOg0KDQpUaGUgdmFsdWUgdGhhdCwgYXNzdW1pbmcgdGhlIGRhdGFzZXQgaXMgb3JkZXJlZCBmcm9tIHNtYWxsZXN0IHRvIGxhcmdlc3QsIGZhbGxzIGluIHRoZSBtaWRkbGUuIElmIHRoZXJlIGFyZSBhbiBldmVuIG51bWJlciBvZiB2YWx1ZXMgaW4gYSBkYXRhc2V0LCB5b3UgZWl0aGVyIHJlcG9ydCBib3RoIG9mIHRoZSBtaWRkbGUgdHdvIHZhbHVlcyBvciB0aGVpciBhdmVyYWdlLg0KDQpUaGVyZSBhcmUgYWx3YXlzIHR3byBzdGVwcyB0byBmaW5kaW5nIHRoZSBtZWRpYW4gb2YgYSBkYXRhc2V0Og0KDQoxLk9yZGVyIHRoZSB2YWx1ZXMgaW4gdGhlIGRhdGFzZXQgZnJvbSBzbWFsbGVzdCB0byBsYXJnZXN0DQoNCjIuSWRlbnRpZnkgdGhlIG51bWJlcihzKSB0aGF0IGZhbGwocykgaW4gdGhlIG1pZGRsZQ0KDQojIyMgRXhhbXBsZSBPbmU6IEV2ZW4gTnVtYmVyIG9mIFZhbHVlcw0KDQpTYXkgd2UgaGF2ZSBhIGRhdGFzZXQgd2l0aCB0aGUgZm9sbG93aW5nIHRlbiBudW1iZXJzOg0KDQoyNCwgMTYsIDMwLCAxMCwgMTIsIDI4LCAzOCwgMiwgNCwgMzYNCg0KVGhlIGZpcnN0IHN0ZXAgaXMgdG8gb3JkZXIgdGhlc2UgbnVtYmVycyBmcm9tIHNtYWxsZXN0IHRvIGxhcmdlc3Q6DQoNCjIsIDQsIDEwLCAxMiwgWzE2LCAyNF0sIDI4LCAzMCwgMzYsIDM4DQoNCkJlY2F1c2UgdGhpcyBkYXRhc2V0IGhhcyBhbiBldmVuIG51bWJlciBvZiB2YWx1ZXMsIHRoZXJlIGFyZSB0d28gbWVkaWFuczogMTYgYW5kIDI0IOKAlCAxNiBoYXMgZm91ciBkYXRhcG9pbnRzIHRvIHRoZSBsZWZ0LCBhbmQgMjQgaGFzIGZvdXIgZGF0YXBvaW50cyB0byB0aGUgcmlnaHQuDQoNCkFsdGhvdWdoIHlvdSBjYW4gcmVwb3J0IGJvdGggdmFsdWVzIGFzIHRoZSBtZWRpYW4sIHBlb3BsZSBvZnRlbiBhdmVyYWdlIHRoZW0uIElmIHlvdSBhdmVyYWdlZCAxNiBhbmQgMjQsIHlvdSBjb3VsZCByZXBvcnQgdGhlIG1lZGlhbiBhcyAyMC4NCg0KIyMjIEV4YW1wbGUgVHdvOiBPZGQgTnVtYmVyIG9mIFZhbHVlcw0KDQpJZiB3ZSBhZGRlZCBhbm90aGVyIHZhbHVlIChzYXksIDI0KSB0byB0aGUgZGF0YXNldCBhbmQgc29ydGVkIGl0LCB3ZSB3b3VsZCBoYXZlOg0KDQoyLCA0LCAxMCwgMTIsIDE2LCBbMjRdLCAyNCwgMjgsIDMwLCAzNiwgMzgNCg0KVGhlIG5ldyBtZWRpYW4gaXMgZXF1YWwgdG8gMjQsIGJlY2F1c2UgdGhlcmUgYXJlIDUgdmFsdWVzIHRvIHRoZSBsZWZ0IG9mIGl0LCBhbmQgNSB2YWx1ZXMgdG8gdGhlIHJpZ2h0IG9mIGl0Lg0KDQojIyBJbnN0cnVjdGlvbnMNCg0KMS5JbiB0aGUgbmV4dCB0d28gc3RlcHMsIHlvdSB3aWxsIG1hbnVhbGx5IHNvcnQgYW4gYXJyYXksIGFuZCB0aGVuIGRldGVybWluZSB3aGljaCB2YWx1ZSBpbiB0aGUgYXJyYXkgaXMgdGhlIG1lZGlhbi4NCg0KSW4gbm90ZWJvb2suUm1kLCB3ZSBoYXZlIGEgdmVjdG9yIHdpdGggdGhlIGFnZXMgb2YgdGhlIGZpcnN0IGZpdmUgYXV0aG9ycyBmcm9tIExlIE1vbmRl4oCZcyBzdXJ2ZXk6DQoNCjI5LDQ5LDQyLDQzLDMyDQoNClVuZGVyIGZpdmVfYXV0aG9yX2FnZXMgdGhlcmUgaXMgYSB2YXJpYWJsZSBjYWxsZWQgc29ydGVkX2F1dGhvcl9hZ2VzLiBDaGFuZ2UgdGhlIDBzIGluIHNvcnRlZF9hdXRob3JfYWdlcyB0byB0aGUgdmFsdWVzIGluIGFzY2VuZGluZyBvcmRlciBmcm9tIGZpdmVfYXV0aG9yX2FnZXMuDQoNCmBgYHtyfQ0KIyBBcnJheSBvZiB0aGUgZmlyc3QgZml2ZSBhdXRob3IgYWdlcw0KZml2ZV9hdXRob3JfYWdlcyA8LSBjKDI5LCA0OSwgNDIsIDQzLCAzMikNCg0KIyBGaWxsIGluIHRoZSBlbXB0eSBhcnJheSB3aXRoIHRoZSB2YWx1ZXMgc29ydGVkDQpzb3J0ZWRfYXV0aG9yX2FnZXMgPC0gc29ydChmaXZlX2F1dGhvcl9hZ2VzKQ0KDQpzb3J0ZWRfYXV0aG9yX2FnZXMNCmBgYA0KDQoyLlNldCBtZWRpYW5fdmFsdWUgZXF1YWwgdG8gdGhlIG1lZGlhbiBvZiB0aGUgYXJyYXkuDQoNCmBgYHtyfQ0KIyBTYXZlIHRoZSBtZWRpYW4gdmFsdWUgdG8gbWVkaWFuX3ZhbHVlDQptZWRpYW5fdmFsdWUgPC0gNDINCg0KIyBQcmludCB0aGUgc29ydGVkIGFycmF5IGFuZCBtZWRpYW4gdmFsdWUNCmNhdCgiVGhlIHNvcnRlZCBhcnJheSBpczoiLCBzb3J0ZWRfYXV0aG9yX2FnZXMsICdcbicpDQoNCmNhdChwYXN0ZSgiVGhlIG1lZGlhbiBvZiB0aGUgYXJyYXkgaXM6ICIsIG1lZGlhbl92YWx1ZSkpDQpgYGANCirpl5zmlrwgY2F0KCnvvJoNCg0KY2F0KCkg5pivICJjb25jYXRlbmF0ZSBhbmQgcHJpbnQiIOeahOaEj+aAne+8jOeUqOS+huWwh+Wtl+S4suWSjOiuiuaVuOi8uOWHuuaIkOS4gOihjOaWh+Wtl++8mw0KDQrlroPkuI3lg48gcHJpbnQoKSDmnIPoh6rli5Xmj5vooYzvvIzmiYDku6Xlu7rorbDkvaDmiYvli5XliqDlhaUgXG7vvJsNCg0K5aaC5p6c5L2g55SoIGNhdChwYXN0ZSguLi4pKe+8jOmCo+m6vCBwYXN0ZSgpIOacg+WFiOe1hOWQiOaIkOS4gOaVtOWPpe+8jOWGjei8uOWHuu+8mw0KDQpjYXQoKSDkuI3mnIPlm57lgrPlgLzvvIzkuZ/nhKHms5Xnm7TmjqXopIfoo73lm54gUlN0dWRpbyDnianku7bvvIzlg4XnlKjmlrzovLjlh7rmloflrZfjgIINCg0KKuWcqCBSIOS4re+8jHBhc3RlKCkg5piv5LiA5YCL55So5L6G5bCH5aSa5YCL5a2X5Liy5ZCI5L215oiQ5LiA5YCL5a2X5Liy55qE5Ye95pW444CC5a6D5bi455So5pa855Si55Sf5YuV5oWL5paH5a2X44CB5aCx5ZGK6Ly45Ye6562J5oOF5aKD44CCDQpgYGB7cn0NCm5hbWUgPC0gIkFubmFiZWwiDQphZ2UgPC0gMTgNCg0KcGFzdGUoIk15IG5hbWUgaXMiLCBuYW1lLCAiYW5kIEkgYW0iLCBhZ2UsICJ5ZWFycyBvbGQuIikNCiMg6Ly45Ye6OiAiTXkgbmFtZSBpcyBBbm5hYmVsIGFuZCBJIGFtIDE4IHllYXJzIG9sZC4iDQpgYGANCg0KIyAzLk1lZGlhbiBpbiBSDQoNCkZpbmRpbmcgdGhlIG1lZGlhbiBvZiBhIGRhdGFzZXQgYmVjb21lcyBpbmNyZWFzaW5nbHkgdGltZS1jb25zdW1pbmcgYXMgdGhlIHNpemUgb2YgeW91ciBkYXRhc2V0IGluY3JlYXNlcyDigJQgaW1hZ2luZSBmaW5kaW5nIHRoZSBtZWRpYW4gb2YgYW4gdW5zb3J0ZWQgZGF0YXNldCB3aXRoIDEwLDAwMCBvYnNlcnZhdGlvbnMuDQoNClRoZSBSIG1lZGlhbigpIGZ1bmN0aW9uIGNhbiBkbyB0aGUgd29yayBvZiBzb3J0aW5nLCB0aGVuIGZpbmRpbmcgdGhlIG1lZGlhbiBmb3IgeW91LiBJbiB0aGUgZXhhbXBsZSBiZWxvdywgd2UgdXNlIG1lZGlhbigpIHRvIGNhbGN1bGF0ZSB0aGUgbWVkaWFuIG9mIGEgZGF0YXNldCB3aXRoIHRlbiB2YWx1ZXM6DQpgYGB7cn0NCmV4YW1wbGVfZGF0YSA9IGMoMjQsIDE2LCAzMCwgMTAsIDEyLCAyOCwgMzgsIDIsIDQsIDM2LCA0MikNCg0KZXhhbXBsZV9tZWRpYW4gPSBtZWRpYW4oZXhhbXBsZV9kYXRhKQ0KDQpwcmludChleGFtcGxlX21lZGlhbikNCg0KYGBgDQoNClRoZSBjb2RlIGFib3ZlIHByaW50cyB0aGUgbWVkaWFuIG9mIHRoZSBkYXRhc2V0LCAyNC4gVGhlIG1lYW4gb2YgdGhpcyBkYXRhc2V0IGlzIDIyLiBJdOKAmXMgd29ydGggbm90aW5nIHRoZXNlIHR3byB2YWx1ZXMgYXJlIGNsb3NlIHRvIG9uZSBhbm90aGVyLCBidXQgbm90IGVxdWFsLg0KDQojIyBJbnN0cnVjdGlvbnMNCg0KMS5Vc2UgUiB0byBmaW5kIHRoZSBtZWRpYW4gb2YgdGhlIGF1dGhvcl9hZ2VzIGFycmF5LiBTYXZlIHRoZSByZXN1bHQgdG8gbWVkaWFuX2FnZS4NCg0KRG9lcyB0aGUgbWVkaWFuIGFnZSBvZiB0aGUgYXV0aG9ycyBzdXJwcmlzZSB5b3U/IElmIHNvLCBob3c/IElzIGl0IG9sZGVyLCBvciB5b3VuZ2VyIHRoYW4geW91IGV4cGVjdGVkPw0KDQpgYGB7cn0NCiMgU2F2ZSBhdXRob3IgYWdlcyB0byBhdXRob3JfYWdlcw0KYXV0aG9yX2FnZXMgPC0gZ3JlYXRlc3RfYm9va3MkQWdlcw0KDQojIFVzZSBSIHRvIGNhbGN1bGF0ZSB0aGUgbWVkaWFuIGFnZSBvZiB0aGUgdG9wIDEwMCBhdXRob3JzDQptZWRpYW5fYWdlIDwtIG1lZGlhbihhdXRob3JfYWdlcykNCg0KcHJpbnQocGFzdGUoIlRoZSBtZWRpYW4gYWdlIG9mIHRoZSAxMDAgZ3JlYXRlc3QgYXV0aG9ycywgYWNjb3JkaW5nIHRvIGEgc3VydmV5IGJ5IExlIE1vbmRlIGlzOiAiICwgbWVkaWFuX2FnZSkpDQpgYGANCg0KIyA0LlJldmlldyBhbmQgRGlzY3Vzc2lvbg0KDQpJbiB0aGlzIGxlc3NvbiwgeW91IGxlYXJuZWQgaG93IHRvIGZpbmQgdGhlIG1lZGlhbiBvZiBhIGRhdGFzZXQgaW4gdHdvIHN0ZXBzOg0KDQoxLlNvcnQgdGhlIGRhdGFzZXQNCg0KMi5JZGVudGlmeSB0aGUgb25lIG9yIHR3byBudW1iZXJzIHRoYXQgZmFsbCBpbiB0aGUgbWlkZGxlIG9mIHRoZSBzb3J0ZWQgZGF0YXNldA0KDQpZb3UgYWxzbyBsZWFybmVkIGhvdyB0byBjYWxjdWxhdGUgdGhlIG1lZGlhbiB1c2luZyBSOg0KDQptZWRpYW4obXlfZGF0YSkNCg0KIyMgRGlzY3Vzc2lvbg0KDQpUYWtlIGEgbG9vayBhdCB0aGUgaGlzdG9ncmFtLiBJdCBkaXNwbGF5cyB0aGUgYXV0aG9yIGFnZSBkaXN0cmlidXRpb24gd2l0aCB2ZXJ0aWNhbCBsaW5lcyBmb3IgdGhlIG1lYW4gKHJlZCkgYW5kIG1lZGlhbiAoYmx1ZSkuDQoNCkRvIHlvdSBmZWVsIGxpa2UgdGhlIG1lZGlhbiBvZiBvdXIgZGF0YXNldCwgNDAuNSwgcHJvdmlkZXMgdXMgZW5vdWdoIGluZm9ybWF0aW9uIHRvIGNsYWltIHdoZW4gYXV0aG9ycyBwdWJsaXNoIHRoZWlyIGdyZWF0ZXN0IHdvcms/DQoNCldlIGFyZ3VlIGl0IGRvZXMgbm90Lg0KDQpBbHRob3VnaCB0aGUgbWVkaWFuIGlzIGEgZ29vZCBtZWFzdXJlIG9mIHRoZSBkYXRhc2V04oCZcyBjZW50ZXIsIHdlIGNhbm5vdCBtYWtlIGEgZGVmaW5pdGl2ZSBjbGFpbSBhYm91dCB3aGVuIGF1dGhvcnMgcHVibGlzaCB0aGVpciBncmVhdGVzdCB3b3JrIOKAlCB0aGUgeW91bmdlc3QgYXV0aG9yIHB1Ymxpc2hlZCBhdCAxOCBhbmQgdGhlIG9sZGVzdCBhdCA3Ni4gSXQgd291bGQgYmUgaXJyZXNwb25zaWJsZSB0byBzYXkgYW55dGhpbmcgYnV0LCDigJxpdCBzZWVtcyB0byBiZSBwb3NzaWJsZSBhdCBhbG1vc3QgYW55IGFnZS7igJ0NCg0KTm90aWNlIHRoYXQgdGhlIG1lYW4gYW5kIHRoZSBtZWRpYW4gYXJlIG5lYXJseSBlcXVhbC4gVGhpcyBpcyBub3QgYSBzdXJwcmlzaW5nIHJlc3VsdCwgYXMgYm90aCBzdGF0aXN0aWNzIGFyZSBhIG1lYXN1cmUgb2YgdGhlIGRhdGFzZXTigJlzIGNlbnRlci4gSG93ZXZlciwgaXTigJlzIHdvcnRoIG5vdGluZyB0aGF0IHRoZXNlIHJlc3VsdHMgd2lsbCBub3QgYWx3YXlzIGJlIHNvIGNsb3NlLg0KDQpJbiB0aGUgaW5zdHJ1Y3Rpb25zIGJlbG93LCB3ZeKAmXZlIHdyaXR0ZW4gYSBicmllZiBleHBsYW5hdGlvbiB0aGF0IHB1dHMgbWVkaWFuIGluIHRoZSBjb250ZXh0IG9mIG91ciBwcm9ibGVtLg0KDQpgYGB7cn0NCiNwbG90IGRhdGENCmhpc3QgPC0gcXBsb3QoZ3JlYXRlc3RfYm9va3MkQWdlcywNCiAgICAgIGdlb209J2hpc3RvZ3JhbScsDQogICAgICBiaW53aWR0aCA9IDMsICANCiAgICAgIG1haW4gPSAnQWdlIG9mIFRvcCAxMDAgTm92ZWwgQXV0aG9ycyBhdCBQdWJsaWNhdGlvbicsIA0KICAgICAgeGxhYiA9ICdQdWJsaWNhdGlvbiBBZ2UnLA0KICAgICAgeWxhYiA9ICdDb3VudCcsDQogICAgICBmaWxsPUkoImJsdWUiKSwgDQogICAgICBjb2w9SSgiYmxhY2siKSwgDQogICAgICBhbHBoYT1JKC4yKSkgKw0KICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lZGlhbihncmVhdGVzdF9ib29rcyRBZ2VzKSwNCiAgICAgICAgICAgICAgICAgY29sb3I9Im1lZGlhbiIpLCBsaW5ldHlwZT0iZGFzaGVkIiwNCiAgICAgICAgICAgICBzaXplPTEpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWFuKGdyZWF0ZXN0X2Jvb2tzJEFnZXMpLA0KICAgICAgICAgICAgICAgICBjb2xvcj0ibWVhbiIpLCBsaW5ldHlwZT0ic29saWQiLA0KICAgICAgICAgICAgIHNpemU9MSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZSA9ICJzdGF0aXN0aWNzIiwgdmFsdWVzID0gYyhtZWRpYW4gPSAiYmx1ZSIsIG1lYW4gPSAiZ3JlZW4iKSkNCg0KaGlzdA0KYGBgDQoNCiMjIEluc3RydWN0aW9ucw0KDQpUaGUgbWVkaWFuIGFnZSBvZiBhdXRob3JzLCB3aGVuIHRoZXkgcHVibGlzaCB0aGVpciBiZXN0IHdvcmssIGZyb20gTGUgTW9uZGXigJlzIDEwMCBncmVhdGVzdCBib29rcyBpcyA0MS4NCg0KV2hpbGUgdGhpcyBkb2VzIG5vdCB0ZWxsIHVzIG11Y2ggYWJvdXQgd2hpY2ggeWVhciBpcyBhbiBhdXRob3LigJlzIGdyZWF0ZXN0IHllYXIsIGl0IGRvZXMgaW5kaWNhdGUgdGhhdCBoYWxmIG9mIHRoZSBhdXRob3JzIGZyb20gdGhlIHN1cnZleSBmaW5kIHRoZWlyIGdyZWF0ZXN0IHN1Y2Nlc3MgYmVmb3JlIHRoZSBhZ2Ugb2YgNDEgYW5kIGhhbGYgZmluZCB0aGVpciBncmVhdGVzdCBzdWNjZXNzIGFmdGVyIHRoZSBhZ2Ugb2YgNDEuDQoNCg0KIyBNb2RlIGluIFIgKOecvuaVuCkNCiMgMS5JbnRyb2R1Y3Rpb24NCg0KSW4gdGhpcyBsZXNzb24sIHlvdSB3aWxsIGxlYXJuIGhvdyB0byBmaW5kIHRoZSBtb2RlIG9mIGEgZGF0YXNldC4gRWFjaCBvZiB0aGUgbmV4dCB0aHJlZSBleGVyY2lzZXMgd2lsbCBjb3ZlciB0aGUgZm9sbG93aW5nOg0KDQoxLk1hbnVhbGx5IGZpbmRpbmcgdGhlIG1vZGUgb2YgYSBkYXRhc2V0DQoNCjIuVXNpbmcgUuKAmXMgZnVuY3Rpb25zIHRvIGZpbmQgdGhlIG1vZGUNCg0KMy5Db21wYXJpbmcgbW9kZSB0byBtZWFuIGFuZCBtZWRpYW4gdmFsdWVzDQoNCkluIHRoZSBsZXNzb24sIHdlIHdpbGwgdXNlIGEgZGF0YXNldCBvZiB0aGUgMTAwIGdyZWF0ZXN0IG5vdmVscywgZGV0ZXJtaW5lZCBieSBhIEZyZW5jaCBsaXRlcmFyeSBtYWdhemluZSwgTGUgTW9uZGUuIEZyb20gdGhlIGRhdGFzZXQsIHlvdSB3aWxsIHVzZSB0aGUgbW9kZSB0byBhbnN3ZXIgdGhlIHF1ZXN0aW9uOg0KDQpXaGF0IGlzIHRoZSBtb3N0IGNvbW1vbiBhZ2UgZm9yIGEgZ3JlYXQgYXV0aG9yIHRvIHB1Ymxpc2ggdGhlaXIgYmVzdCB3b3JrPw0KDQpJZiB5b3UgYXJlIG5vdCBmYW1pbGlhciB3aXRoIG1lYW4sIGFsc28ga25vd24gYXMgYXZlcmFnZSwgb3IgbWVkaWFuLCB3ZSByZWNvbW1lbmQgdGhhdCB5b3UgbGVhcm4gYWJvdXQgaXQgaW4gb3VyIGxlc3NvbnMgb24gYXZlcmFnZSBhbmQgbWVkaWFuLg0KDQojIyBJbnN0cnVjdGlvbnMNCg0KVGhlIGhpc3RvZ3JhbSB0byB0aGUgcmlnaHQgZGlzcGxheXMgdGhlIGFnZSBvZiBhdXRob3JzLCBhdCBwdWJsaWNhdGlvbiwgZm9yIHRoZSB0b3AgMTAwIG5vdmVscyBmcm9tIExlIE1vbmRl4oCZcyBzdXJ2ZXkuIFRoZSByZWQgbGluZSBpcyB0aGUgbWVhbiBhZ2UsIGFuZCB0aGUgYmx1ZSBsaW5lIGlzIHRoZSBtZWRpYW4gYWdlLg0KDQpVc2UgdGhlIGRlZmluaXRpb24gb2YgbW9kZSBiZWxvdyBhbmQgdGhlIGhpc3RvZ3JhbSB0byB0aGUgcmlnaHQgdG8gZ3Vlc3Mgd2hlcmUgdGhlIG1vZGUgZmFsbHMuIFlvdSB3aWxsIGNhbGN1bGF0ZSB0aGUgY29ycmVjdCBhbnN3ZXIgaW4gdGhlIGxhc3QgZXhlcmNpc2UuDQoNClRoZSBtb2RlIGlzIHRoZSBtb3N0IGNvbW1vbiBvYnNlcnZhdGlvbiBpbiBhIGRhdGFzZXQuDQoNCllvdSB3aWxsIG5vdCBiZSBhYmxlIHRvIGZpbmQgdGhlIGV4YWN0IG1vZGUsIGJlY2F1c2UgdGhlIGhpc3RvZ3JhbSBkaXNwbGF5cyBiaW5zIHdpdGggYSByYW5nZSBvZiB2YWx1ZXMuIEhvd2V2ZXIsIHlvdSBjYW4gZ3Vlc3MgYSByYW5nZSBvZiB2YWx1ZXMgd2hlcmUgeW91IGFyZSBtb3N0IGxpa2VseSB0byBzZWUgdGhlIG1vZGUuDQoNCmBgYHtyfQ0KI3Bsb3QgZGF0YQ0KaGlzdCA8LSBxcGxvdChncmVhdGVzdF9ib29rcyRBZ2VzLA0KICAgICAgZ2VvbT0naGlzdG9ncmFtJywNCiAgICAgIGJpbndpZHRoID0gMywgIA0KICAgICAgbWFpbiA9ICdBZ2Ugb2YgVG9wIDEwMCBOb3ZlbCBBdXRob3JzIGF0IFB1YmxpY2F0aW9uJywgDQogICAgICB4bGFiID0gJ1B1YmxpY2F0aW9uIEFnZScsDQogICAgICB5bGFiID0gJ0NvdW50JywNCiAgICAgIGZpbGw9SSgiYmx1ZSIpLCANCiAgICAgIGNvbD1JKCJibGFjayIpLCANCiAgICAgIGFscGhhPUkoLjIpKSArDQogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVkaWFuKGdyZWF0ZXN0X2Jvb2tzJEFnZXMpLA0KICAgICAgICAgICAgICAgICBjb2xvcj0ibWVkaWFuIiksIGxpbmV0eXBlPSJkYXNoZWQiLA0KICAgICAgICAgICAgIHNpemU9MSkgKw0KICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lYW4oZ3JlYXRlc3RfYm9va3MkQWdlcyksDQogICAgICAgICAgICAgICAgIGNvbG9yPSJtZWFuIiksIGxpbmV0eXBlPSJzb2xpZCIsDQogICAgICAgICAgICAgc2l6ZT0xKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lID0gInN0YXRpc3RpY3MiLCB2YWx1ZXMgPSBjKG1lZGlhbiA9ICJibHVlIiwgbWVhbiA9ICJyZWQiKSkNCg0KaGlzdA0KYGBgDQoNCiMgMi5Nb2RlDQoNClRoZSBmb3JtYWwgZGVmaW5pdGlvbiBmb3IgdGhlIG1vZGUgb2YgYSBkYXRhc2V0IGlzOg0KDQpUaGUgbW9zdCBmcmVxdWVudGx5IG9jY3VycmluZyBvYnNlcnZhdGlvbiBpbiB0aGUgZGF0YXNldC4gQSBkYXRhc2V0IGNhbiBoYXZlIG11bHRpcGxlIG1vZGVzIGlmIHRoZXJlIGlzIG1vcmUgdGhhbiBvbmUgdmFsdWUgd2l0aCB0aGUgc2FtZSBtYXhpbXVtIGZyZXF1ZW5jeS4NCg0KV2hpbGUgeW91IG1heSBiZSBhYmxlIHRvIGZpbmQgdGhlIG1vZGUgb2YgYSBzbWFsbCBkYXRhc2V0IGJ5IHNpbXBseSBsb29raW5nIHRocm91Z2ggaXQsIGlmIHlvdSBoYXZlIHRyb3VibGUsIHdlIHJlY29tbWVuZCB5b3UgZm9sbG93IHRoZXNlIHR3byBzdGVwczoNCg0KMS5GaW5kIHRoZSBmcmVxdWVuY3kgb2YgZXZlcnkgdW5pcXVlIG51bWJlciBpbiB0aGUgZGF0YXNldA0KDQoyLkRldGVybWluZSB3aGljaCBudW1iZXIgaGFzIHRoZSBoaWdoZXN0IGZyZXF1ZW5jeQ0KDQpFeGFtcGxlDQoNClNheSB3ZSBoYXZlIGEgZGF0YXNldCB3aXRoIHRoZSBmb2xsb3dpbmcgdGVuIG51bWJlcnM6DQoNCjI0LCAxNiwgMTIsIDEwLCAxMiwgMjgsIDM4LCAxMiwgMjgsIDI0DQoNCkxldOKAmXMgZmluZCB0aGUgZnJlcXVlbmN5IG9mIGVhY2ggbnVtYmVyOg0KDQoyNAkxNgkxMgkxMAkyOAkzOA0KDQoyCSAgMQkgIDMJICAxCSAgMgkgIDENCg0KRnJvbSB0aGUgdGFibGUsIHdlIGNhbiBzZWUgdGhhdCBvdXIgbW9kZSBpcyAxMiwgdGhlIG1vc3QgZnJlcXVlbnQgbnVtYmVyIGluIG91ciBkYXRhc2V0Lg0KDQojIyBJbnN0cnVjdGlvbnMNCg0KMS5EZXRlcm1pbmUgdGhlIG1vZGUgb2YgdGhlIGFnZXMgZm9yIHRoZSBmaXJzdCB0ZW4gYXV0aG9ycyBpbiB0aGUgTGUgTW9uZGUgc3VydmV5Og0KDQoyOSw0OSw0Miw0MywzMiwzOCwzNyw0MSwyNywyNw0KDQpTYXZlIHRoZSB2YWx1ZSB0byBtb2RlX2FnZS4NCmBgYHtyfQ0KbW9kZV9hZ2UgPC0gMjcNCm1vZGVfYWdlDQpgYGANCg0KMi5EZXRlcm1pbmUgdGhlIG51bWJlciBvZiBhdXRob3JzIHdobyB3ZXJlIHRoZSBhZ2Ugb2YgdGhlIG1vZGUuIFNhdmUgdGhlIG51bWJlciB0byBtb2RlX2NvdW50Lg0KDQpgYGB7cn0NCm1vZGVfY291bnQgPC0gMg0KbW9kZV9jb3VudA0KYGBgDQoNCiMgMy5Nb2RlIHdpdGggRGVzY1Rvb2xzDQoNCkZpbmRpbmcgdGhlIG1vZGUgb2YgYSBkYXRhc2V0IGJlY29tZXMgaW5jcmVhc2luZ2x5IHRpbWUtY29uc3VtaW5nIGFzIHRoZSBzaXplIG9mIHlvdXIgZGF0YXNldCBpbmNyZWFzZXMg4oCUIGltYWdpbmUgZmluZGluZyB0aGUgbW9kZSBvZiBhIGRhdGFzZXQgd2l0aCAxMCwwMDAgb2JzZXJ2YXRpb25zLg0KDQpUaGUgUiBwYWNrYWdlIERlc2NUb29scyBpbmNsdWRlcyBhIGhhbmR5IE1vZGUoKSBmdW5jdGlvbiB3aGljaCBjYW4gZG8gdGhlIHdvcmsgb2YgZmluZGluZyB0aGUgbW9kZSBmb3IgdXMuIEluIHRoZSBleGFtcGxlIGJlbG93LCB3ZSB1c2UgTW9kZSgpIHRvIGNhbGN1bGF0ZSB0aGUgbW9kZSBvZiBhIGRhdGFzZXQgd2l0aCB0ZW4gdmFsdWVzOg0KDQpFeGFtcGxlOiBPbmUgTW9kZQ0KDQpgYGB7cn0NCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KDQpleGFtcGxlX2RhdGEgPC0gYygyNCwgMTYsIDEyLCAxMCwgMTIsIDI4LCAzOCwgMTIsIDI4LCAyNCkNCg0KZXhhbXBsZV9tb2RlIDwtIE1vZGUoZXhhbXBsZV9kYXRhKQ0KDQpgYGANCg0KVGhlIGNvZGUgYWJvdmUgY2FsY3VsYXRlcyB0aGUgbW9kZSBvZiB0aGUgdmFsdWVzIGluIGV4YW1wbGVfZGF0YSBhbmQgc2F2ZXMgaXQgdG8gZXhhbXBsZV9tb2RlLg0KDQpUaGUgcmVzdWx0IG9mIE1vZGUoKSBpcyBhIHZlY3RvciB3aXRoIHRoZSBtb2RlIHZhbHVlOg0KDQpgYGB7cn0NCmV4YW1wbGVfbW9kZQ0KYGBgDQoNCkV4YW1wbGU6IFR3byBNb2Rlcw0KDQpJZiB0aGVyZSBhcmUgbXVsdGlwbGUgbW9kZXMsIHRoZSBNb2RlKCkgZnVuY3Rpb24gd2lsbCByZXR1cm4gdGhlbSBhcyBhIHZlY3Rvci4NCg0KTGV04oCZcyBsb29rIGF0IGEgdmVjdG9yIHdpdGggdHdvIG1vZGVzLCAxMiBhbmQgMjQ6DQpgYGB7cn0NCmV4YW1wbGVfZGF0YSA9IGMoMjQsIDE2LCAxMiwgMTAsIDEyLCAyNCwgMzgsIDEyLCAyOCwgMjQpDQoNCmV4YW1wbGVfbW9kZSA9IE1vZGUoZXhhbXBsZV9kYXRhKQ0KYGBgDQoNClRoZSByZXN1bHQgaXM6DQpgYGB7cn0NCmV4YW1wbGVfbW9kZQ0KYGBgDQoNCiMjIEluc3RydWN0aW9ucw0KDQoxLldlIGhhdmUgYWxyZWFkeSBpbXBvcnRlZCB0aGUgRGVzY1Rvb2xzIGxpYnJhcnkgZm9yIHlvdS4NCg0KRGVsZXRlIHRoZSBjdXJyZW50IHZhbHVlIHNldCB0byBtb2RlX2FnZS4NCg0KRmluZCB0aGUgbW9kZSBvZiB0aGUgb2JzZXJ2YXRpb25zIGluIHRoZSBhdXRob3JfYWdlcyBhcnJheS4gU2F2ZSB0aGUgcmVzdWx0IHRvIG1vZGVfYWdlLg0KDQpgYGB7cn0NCiMgU2V0IGF1dGhvciBhZ2VzIHRvIA0KYXV0aG9yX2FnZXMgPC0gZ3JlYXRlc3RfYm9va3MkQWdlcw0KDQptb2RlX2FnZSA8LSBNb2RlKGF1dGhvcl9hZ2VzKQ0KDQpwcmludChwYXN0ZSgiVGhlIG1vZGUgYWdlIG9mIGF1dGhvcnMgZnJvbSBMZSBNb25kZSdzIDEwMCBncmVhdGVzdCBib29rcyBpczogIiwgbW9kZV9hZ2VbMV0pKQ0KYGBgDQoNCiMgNC5SZXZpZXcgYW5kIERpc2N1c3Npb24NCg0KSW4gdGhpcyBsZXNzb24sIHlvdSBsZWFybmVkIGhvdyB0byBmaW5kIHRoZSBtb2RlIG9mIGEgZGF0YXNldCBpbiB0d28gc3RlcHM6DQoNCjEuRmluZCB0aGUgZnJlcXVlbmN5IG9mIGV2ZXJ5IHVuaXF1ZSBudW1iZXIgaW4gdGhlIGRhdGFzZXQNCg0KMi5EZXRlcm1pbmUgd2hpY2ggbnVtYmVyIGhhcyB0aGUgaGlnaGVzdCBmcmVxdWVuY3kNCg0KWW91IGFsc28gbGVhcm5lZCBob3cgdG8gY2FsY3VsYXRlIHRoZSBtb2RlIHVzaW5nIERlc2NUb29sczoNCg0KTW9kZShteV9hcnJheSkNCg0KIyMjIERpc2N1c3Npb24NCg0KSW4gdGhpcyBsZXNzb24sIHlvdSBmb3VuZCB0aGF0IDM4IHdhcyB0aGUgbW9zdCBjb21tb24gYWdlLCBhdCBwdWJsaWNhdGlvbiwgZm9yIGFuIGF1dGhvciBmcm9tIHRoZSBMZSBNb25kZSBzdXJ2ZXkuIEhvdyBkb2VzIHRoaXMgbnVtYmVyIGNvbXBhcmUgdG8geW91ciBndWVzcyBmcm9tIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxlc3Nvbj8NCg0KVGhlIG1vZGUgaXMgY2xvc2UgdG8gdGhlIG1lZGlhbiBhbmQgbWVhbiBvZiB0aGUgZGF0YXNldCwgYnV0IGl0IGlzIG5vdCBpbiB0aGUgdGFsbGVzdCBidWNrZXQuIFRoaXMgc2hvdWxkIG5vdCBiZSBzdXJwcmlzaW5nLCBhcyB0aGUgaGlzdG9ncmFtIGluZGljYXRlcyB0aGUgZGF0YSBpcyBjZW50ZXJlZCBiZXR3ZWVuIHRoZSBhZ2VzIG9mIDMwIGFuZCA1MCDigJQgdGhlcmUgaXMgYSBoaWdoZXIgY2hhbmNlIG9mIGEgbW9kZSBpbiB0aGF0IHJhbmdlIHRoYW4gb3V0c2lkZSBvZiBpdC4NCg0KVGhlIG1vZGUgaXMgbm90IGFsd2F5cyB0aGlzIGNsb3NlIHRvIHRoZSBtZWRpYW4gYW5kIG1lYW4sIGFuZCBvZnRlbiB3aWxsIG5vdCBiZSBpbiB0aGUgdGFsbGVzdCBidWNrZXQuDQoNCkxvb2sgYXQgdGhlIDI1LTMwIHllYXItb2xkIGJpbi4gVGhlcmUgYXJlIG5pbmUgb2JzZXJ2YXRpb25zIGluIGl0LiBJZiBhbGwgdGhlIHZhbHVlcyBpbiB0aGF0IGJpbiBoYXBwZW5lZCB0byBiZSAyNywgdGhlbiB0aGUgZGF0YXNldOKAmXMgbW9kZSB3b3VsZCBiZSAyNy4gQWx0aG91Z2ggdW5saWtlbHksIGl0IGlzIHBvc3NpYmxlLiBCZWxvdywgd2Ugc2hvdyB3aGF0IHRoaXMgd291bGQgbG9vayBsaWtlOg0KDQpgYGB7ciBNZWFuMiwgb3V0LndpZHRoPSI2MCUifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzL2t1b2FuL0Rlc2t0b3AvUiBDb2RlL01lYW4yLnBuZyIpDQpgYGANCg0KQmFzZWQgb24gdGhpcyBncmFwaCwgaXQgaXMgZmFpciB0byBzYXkgdGhlIG1vZGUgbWF5IG5vdCBhbHdheXMgYmUgYSBncmVhdCBtZWFzdXJlIG9mIHdoZXJlIHRoZSBkYXRhIGlzIGNlbnRlcmVkLiBTaW1wbHkgcHV0LCBtb2RlIGlzIGEgbWVhc3VyZSBvZiB0aGUgbW9zdCBmcmVxdWVudCBvYnNlcnZhdGlvbiBpbiB0aGUgZGF0YXNldCwgYW5kIGlzIG5vdCBhbiBpbmRpY2F0aW9uIG9mIHRoZSB0YWxsZXN0IGJpbiBpbiBhIGhpc3RvZ3JhbS4NCg0KSW4gdGhlIGluc3RydWN0aW9ucyBiZWxvdywgd2XigJl2ZSB3cml0dGVuIGEgYnJpZWYgZXhwbGFuYXRpb24gdGhhdCBwdXRzIG1vZGUgaW4gdGhlIGNvbnRleHQgb2Ygb3VyIHByb2JsZW0uDQoNCiMjIEluc3RydWN0aW9ucw0KDQpgYGB7cn0NCiNwbG90IGRhdGENCmhpc3QgPC0gcXBsb3QoZ3JlYXRlc3RfYm9va3MkQWdlcywNCiAgICAgIGdlb209J2hpc3RvZ3JhbScsDQogICAgICBiaW53aWR0aCA9IDMsICANCiAgICAgIG1haW4gPSAnQWdlIG9mIFRvcCAxMDAgTm92ZWwgQXV0aG9ycyBhdCBQdWJsaWNhdGlvbicsIA0KICAgICAgeGxhYiA9ICdQdWJsaWNhdGlvbiBBZ2UnLA0KICAgICAgeWxhYiA9ICdDb3VudCcsDQogICAgICBmaWxsPUkoImJsdWUiKSwgDQogICAgICBjb2w9SSgiYmxhY2siKSwgDQogICAgICBhbHBoYT1JKC4yKSkgKw0KICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lZGlhbihncmVhdGVzdF9ib29rcyRBZ2VzKSwNCiAgICAgICAgICAgICAgICAgY29sb3I9Im1lZGlhbiIpLCBsaW5ldHlwZT0iZGFzaGVkIiwNCiAgICAgICAgICAgICBzaXplPTEpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWFuKGdyZWF0ZXN0X2Jvb2tzJEFnZXMpLA0KICAgICAgICAgICAgICAgICBjb2xvcj0ibWVhbiIpLCBsaW5ldHlwZT0ic29saWQiLA0KICAgICAgICAgICAgIHNpemU9MSkgKw0KICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PTM4LA0KICAgICAgICAgICAgICAgICBjb2xvcj0ibW9kZSIpLCBsaW5ldHlwZT0ic29saWQiLA0KICAgICAgICAgICAgIHNpemU9MSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZSA9ICJzdGF0aXN0aWNzIiwgdmFsdWVzID0gYyhtZWRpYW4gPSAiYmx1ZSIsIG1lYW4gPSAicmVkIiwgbW9kZT0iZ3JlZW4iKSkNCg0KaGlzdA0KYGBgDQoNCg==