Working Data and Data
Loading
The Hawks data set was collected by students from Cornell College. It
is built in the R library {Stat2Data}. I also made a copy and posted it
at https://raw.githubusercontent.com/pengdsci/sta553/main/Tableau/hawks.csv.
You can download it and save it to a folder on your machine.
data("Hawks")
write.csv(Hawks[which(Hawks$Tail > 175),], file="C:/Users/75CPENG/OneDrive - West Chester University of PA/Desktop/cpeng/WCU-Teaching/2024Spring/STA553/w09/tableau/hawks.csv")
Tableau uses a menu-driven approach to load data in certain formats.
The following figure shows the types of external data that are connected
to Tableau. There are some built-in data sets available in Tableau for
practice purposes.
We open the program and see the following UI.
The Hawks data is in CSV format, we choose text file
to
connect to the data set. After the data is connected, we will see the
following Data Source page with brief information about the data
set.
We can explore the variables in the data set on the data source page.
We can connect to multiple data sets and merge them on this page.
Opening Work
Sheet
Click the Sheet tab in the bottom left of the data source data, we
will the list of the variables and the panels of visualization tools for
making charts.
Statistical charts are created on different sheets. We can add more
sheets as needed and change the default sheet’s name to a meaningful
name.
Next, we create commonly used statistical charts in separate
sheets.
Basic Statistical
Charts with Existing Variables
Bar Chart
Bar charts are one of the most common data visualizations. We can use
them to quickly compare data across categories, highlight differences,
show trends and outliers, and reveal historical highs and lows at a
glance. Bar charts are especially effective when you have data that can
be split into multiple categories.
We consider the distribution of hawk species. Change
Sheet 1
to barChart
.
Step 1: Drag Species
to the Column
field
Step 2: Drag Species
to the Row field
and change it to counts (frequencies).
Pie Chart
Pie charts are powerful for adding detail to other visualizations.
Alone, a pie chart doesn’t give the viewer a way to quickly and
accurately compare the information. Since the viewer has to create
context on their own, key points from your data are missed. Instead of
making a pie chart the focus of your dashboard, try using it to drill
down on other visualizations.
Step 1: repeat the two steps in the bar chart.
Step 2: Click Show Me
on the top-right
of the UI and select piechart icon
.
Step 3: Select the Entire View
from the
top panel drop-down menu.
Step 4: drag Species
to
Label
in Marks panel.
Histogram
A histogram is a chart that displays the shape of a distribution. A
histogram looks like a bar chart but groups values for a continuous
measure into ranges or bins.
Step 1: drag weight
to the column
field.
Step 2: click show me
, in the drop-down
menu and select histogram
icon.
Step 3: Click color
icon in the Marks
panel to adjust the color and border of the histogram.
Box-plot
We can use box plots, also known as box-and-whisker plots, to show
the distribution of values along an axis. Boxes indicate the middle 50
percent of the data (that is, the middle two quartiles of the data’s
distribution).
The following steps are used to create a simple box plot.
Step 1: add a numerical variable to the sheet (we
use weight
in this example).
Step 2: change weight
to dimension. It
will automatically create a default box plot with data points plotted on
the numerical axis.
Step 3: Change the appearance of the box-plot by
selecting Entire View (see the screenshot)
Step 4: choose Gantt Bar
to show the
density of the values and edit the boxplot to get a better chart.
Line Chart
The line chart, or line graph, connects several distinct data points,
presenting them as one continuous evolution. Use line charts to view
trends in data, usually over time (like stock price changes over five
years or website page views for the month). The result is a simple,
straightforward way to visualize changes in one value relative to
another.
Step 1: Drap year
to the column field
and Species
to the row field and convert them into
frequencies.
Step 2: Click Show Me
on the top-right
of the UI and select the line plot
icon.
Step 3: right-click Species
and
Sex
and send them to the Filter panel.
Step 4: Choose an appropriate display form of the
filter (see the right panel of the following screenshot)
Scatter Plot
Scatter plots are an effective way to investigate the relationship
between different variables, showing if one variable is a good predictor
of another, or if they tend to change independently. A scatter plot
presents lots of distinct data points on a single chart. The chart can
then be enhanced with analytics like cluster analysis or trend
lines.
Let’s explore the association between the lengths of wings and tails
of hawks across the species. The following steps create a simple scatter
plot in Tableau.
Step 1: drag the two numerical variables to column
and row fields.
Step 2: Change the two aggregated variables (by
default) to dimension
(see the left-hand side
screenshot).
Step 3: Color code the species (drag
species
to the color mark).
Step 4: Choose the categorical variables to define
filters to explore the association of a subset of the data (partial
association) using the drop-down menu, radio button, slider, etc.
Bubble Chart
Although bubbles aren’t technically their own type of visualization,
using them as a technique adds detail to scatter plots or maps to show
the relationship between three or more measures. Varying the size and
color of circles creates visually compelling charts that present large
volumes of data at once.
A bubble chart is modified from a regular scatter plot. We next use
the above scatter plot as a base plot and make the point size
proportional to the value of the variable wing
.
Step 1: create a basic scatter plot (following steps
1-4 in the previous section of the scatter plot).
Step 2: drag variable wing
to
size icon (Marks panel).
Step 3: right color icon in Marks
panel to adjust transparency and modify the point border to make
partially overlapped points distinguishable.
Step 4: convert year
to a string
variable and add sex
and year
to the
filter.
Step 5: Change the default display of year from
select menu
to drop-down menu and
sex
to radio button
Treemap
Treemaps relate different segments of your data to the whole. As the
name of the chart suggests, each rectangle in a treemap is subdivided
into smaller rectangles, or sub-branches, based on its proportion to the
whole. They make efficient use of space to show the percent total for
each category.
Maps
Maps are a no-brainer for visualizing any kind of location
information, whether it’s postal codes, state abbreviations, country
names, or your own custom geocoding. If you have geographic information
associated with your data, maps are a simple and compelling way to show
how location correlates with trends in your data. Let’s look at a small
data set with geo-information. The data set can be found at https://raw.githubusercontent.com/pengdsci/datasets/main/Realestate.csv.
We first download this data and save it to a local folder so we can
connect the data to Tableau.
The following steps will create a map to view the spatial
distribution of properties in the bay area.
Step 1. Drag longitude
and
latitude
to row and column fields respectively.
Step 2. Click Show me
and select the
World Map in the list of the template plots.
Step 3. Go to the top menu bar, and click
Map
to select a background map.
Step 4. Click the Color
shelf in the
Marks field, and change the default color to an appropriate color.
Step 5. Choose an appropriate color.
Step 6. select an appropriate variable to determine
the point size.
Step 7. drag the variable you want to display in the
hover text.
The following screenshot was created based on the above steps.
The actual map is available on the Tableau Public Server at https://public.tableau.com/app/profile/cpeng/viz/Book1_16487389941160/Sheet4?publish=yes
Density Maps
Density maps reveal patterns or relative concentrations that might
otherwise be hidden due to an overlapping mark on a map—helping you
identify locations with greater or fewer numbers of data points. Density
maps are most effective when working with a data set containing many
data points in a small geographic area.
Let’s use the POC (US gas station data) as an example of how to
handle the data with two data points. The data can be found at: https://github.com/pengdsci/datasets/raw/main/POC.csv.
We first download this data file save it into a local folder and then
connect Tableau to this data.
The following suggested steps will create a density map for the US
gas stations.
Step 1. Convert xcoord
and
ycoord
to longitude and latitude (see the left screenshot
below).
Step 2. Drag xcoord
and
ycoord
to row and column fields respectively.
Step 3. In the drop-down menu of the Marks field,
select density
.
Step 4. Go to the top menu bar, and click
Map
to select a background map.
Step 5. Click the Color
shelf in the
Marks field, and change the default color to an appropriate color.
The actual interactive map is on the Tableau Public Server at https://public.tableau.com/app/profile/cpeng/viz/POC-map/Sheet1?publish=yes
Calculated Derived
Features and Parameters
We have introduced some of the basic statistical graphics that only
require point-and-click, Next we introduce graphics that require derived
variables using Tableau’s capability of creating calculated fields and
parameters.
Although Tableau is not a software program for statistical
modeling, some of the built-in Tableau functions can be used for some
basic modeling tasks. The detailed list of available Tableau functions
can be found at https://help.tableau.com/current/pro/desktop/en-us/functions.htm.
This note only focuses on descriptive visual analysis using simple
builtin graphical functions.
In practice, many statistical procedures are based on the assumption
of normal distribution. As an example, we will create a histogram of a
numerical variable to visualize its distribution and then add a normal
density curve on the top of the histogram to compare the empirical
distribution with the actual theoretic normal distribution.
Recall that the general form of the normal density function of random
variable \(X\) has the following
form
\[
f(x) = \frac{1}{\sqrt{2\pi} \sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}}
\] where \(\mu\) is the mean of
\(X\) and \(\sigma\) the density function of \(X\). To make a normal density curve that
has the same mean and standard deviation as that of \(X\), we need to add two fields,
xbar
and sdx
, to the
worksheet and then define the variable fx
to draw
the density curve. To
Next, we define a parameter to specify the bin width when drawing
histograms (density curves) and three new variables to draw the density
curve.
Create
Parameters
When creating a histogram, we need to define the bin width
(bandwidth, interval width, class width, …) so that each data point will
fall into one and only one bin (interval, class). Many statistical
software programs run an algorithm and provide a default (optimal width
from theory). In Tableau, we can define a bin size (i.e., width)
manually so that the resulting histogram or density curve can be
adjusted by changing the bin width to choose an appropriate width to
better display the distribution from the visual perspective. The Tableau
parameter
allows users to change its value. We will define
bin width as a parameter. The following figure illustrates the steps for
defining the parameter.
Create Calculated
Variables
We next define the mean and standard deviation of variable
Tail
stored in two fields of the workbook. The following
figure shows the steps for defining the mean. We can similarly define
the standard deviation.
Comments
We used TOTAL
function in the above definition of
the mean of the variable Tail
(i.e., all values of variable
Tail
in the data table).
Tableau also provides a function FIXED
that allows
the calculation of grouped sum, mean, etc. For example, we can count the
observations in each year
using the following functions.
Note that F1
is the observation ID of the data.
- Create
bin value
so that the histograms of
Tail
and normalCurve
will use the same bin
width.
ATTR()
is a special Tableau function that effectively
returns a record-level result as an aggregation. If
there are multiple values of the record-level field in the current
context then ATTR()
will return the number of values
instead of a single value.
Next, we use the formula of the density to calculate normal density
scores and save them in the field normalCurve
. The Tableau
formula is given by
Steps for creating a histogram with a density curve being placed on
the top of it.
- Create two histograms:
Tail
and
normalCurve
.
- Change the histogram of
normalCurve
to a density curve
by changing the mark type from Bar
to Line
in
the Marks panel
- Right-click the left-hand side and select
Dual Axis
to
place the density curve on the histogram
- Right-click the right-hand side axis of the resulting overlay graph
and uncheck
Show Header
to get the following.
- Wrap-up After finishing the above steps, go to
file
and select Save to Tableau Public...
or
Save to Tableau Public As
and fill in the text box, click
Save
button to publish the graph on the Tableau Public
server.
- To embed the Tableau graph in the RMD and then render it in an HTML
format, click the bottom-right share button.
We copy the embed code and paste it to the cell of the single-cell
HTML table in the RMD document and edit it with the correct
indention.
<table border = 0 bordercolor="darkgreen" bgcolor='#f6f6f6' width=100% align = center>
<tr>
<td>
embedding JS code from Tableau...
</td>
</tr>
</table>
The following is the embedded interactive Tableau from the Tableau
Public server.
Practice - Reproduce
The Following
LS0tDQp0aXRsZTogIkJhc2ljIENoYXJ0cyB3aXRoIFRhYmxlYXUiDQphdXRob3I6ICJDaGVuZyBQZW5nIg0KZGF0ZTogIldlc3QgQ2hlc3RlciBVbml2ZXJzaXR5ICINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IHJlYWRhYmxlDQotLS0NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoNCmRpdiNUT0MgbGkgew0KICAgIGxpc3Qtc3R5bGU6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjRweDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgxIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIycHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDIgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNXB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCmltZyB7DQogIGJvcmRlcjogMXB4IHNvbGlkICM1NTU7DQp9DQo8L3N0eWxlPg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJTdGF0MkRhdGEiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiU3RhdDJEYXRhIikNCiAgIGxpYnJhcnkoU3RhdDJEYXRhKQ0KfQ0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEpDQpgYGANCg0KXA0KDQpcDQoNCg0KIyBJbnRyb2R1Y3Rpb24NCg0KQW1vbmcgYWxsIHNwZWNpYWxpemVkIHZpc3VhbGl6YXRpb24gc29mdHdhcmUgcHJvZ3JhbXMsIFRhYmxlYXUgaXMgcHJvYmFibHkgdGhlIG1vc3Qgd2lkZWx5IHVzZWQgYW5kIHBvcHVsYXIgaW4gdGhlIGluZHVzdHJ5IGJlY2F1c2UgaXQgZG9lcyBub3QgcmVxdWlyZSBtdWNoIGNvZGluZyBlZmZvcnQuIEl0IGFsc28gcHJvdmlkZXMgdXNlcnMgZW5vdWdoIGZsZXhpYmlsaXR5IHRvIGRlc2lnbiBhZHZhbmNlZCB2aXN1YWxpemF0aW9ucyBieSBkZWZpbmluZyBuZXcgdmFyaWFibGVzIGJhc2VkIG9uIGV4aXN0aW5nIHZhcmlhYmxlcy4gDQoNClRhYmxlYXUgdmlzdWFsIG9iamVjdHMgYXJlIGNyZWF0ZWQgd2l0aCB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgdGFibGUuIExpa2Ugb3RoZXIgcG9pbnQtYW5kLWNsaWNrIHN0YXRpc3RpY2FsIHNvZnR3YXJlIHByb2dyYW1zIHN1Y2ggYXMgTUlOSVRBQiwgaXQgb2ZmZXJzIHNvbWUgYmFzaWMgZnVuY3Rpb25zIG9uZSBjYW4gdXNlIHRvIGRlZmluZSBuZXcgZmllbGRzIGluIHRoZSBkYXRhIHNldCB0byBwZXJmb3JtIHJlbGF0ZWQgdmlzdWFsaXphdGlvbi4gIA0KDQpUYWJsZWF1IGlzIHByaW1hcmlseSBkZXNpZ25lZCBhcyBhIHZpc3VhbGl6YXRpb24gdG9vbC4gSXQgYWxzbyBoYXMgbGltaXRlZCBjYXBhY2l0eSBmb3IgZGF0YSBpbnRlZ3JhdGlvbi4gVGhpcyBhbmQgdGhlIG5leHQgbm90ZXMgZm9jdXMgb25seSBvbiB2aXN1YWxpemF0aW9uLiBUaGVyZWZvcmUsIHdlIGFzc3VtZSB0aGF0IHdlIGhhdmUgYSBzaW5nbGUgY2xlYW4gZGF0YSByZWFkeSANCg0KDQojIFdvcmtpbmcgRGF0YSBhbmQgRGF0YSBMb2FkaW5nDQoNClRoZSBIYXdrcyBkYXRhIHNldCB3YXMgY29sbGVjdGVkIGJ5IHN0dWRlbnRzIGZyb20gQ29ybmVsbCBDb2xsZWdlLiBJdCBpcyBidWlsdCBpbiB0aGUgUiBsaWJyYXJ5IHtTdGF0MkRhdGF9LiBJIGFsc28gbWFkZSBhIGNvcHkgYW5kIHBvc3RlZCBpdCBhdCA8aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Blbmdkc2NpL3N0YTU1My9tYWluL1RhYmxlYXUvaGF3a3MuY3N2Pi4gWW91IGNhbiBkb3dubG9hZCBpdCBhbmQgc2F2ZSBpdCB0byBhIGZvbGRlciBvbiB5b3VyIG1hY2hpbmUuDQoNCmBgYHtyfQ0KZGF0YSgiSGF3a3MiKQ0Kd3JpdGUuY3N2KEhhd2tzW3doaWNoKEhhd2tzJFRhaWwgPiAxNzUpLF0sIGZpbGU9IkM6L1VzZXJzLzc1Q1BFTkcvT25lRHJpdmUgLSBXZXN0IENoZXN0ZXIgVW5pdmVyc2l0eSBvZiBQQS9EZXNrdG9wL2NwZW5nL1dDVS1UZWFjaGluZy8yMDI0U3ByaW5nL1NUQTU1My93MDkvdGFibGVhdS9oYXdrcy5jc3YiKQ0KYGBgDQoNCg0KVGFibGVhdSB1c2VzIGEgbWVudS1kcml2ZW4gYXBwcm9hY2ggdG8gbG9hZCBkYXRhIGluIGNlcnRhaW4gZm9ybWF0cy4gVGhlIGZvbGxvd2luZyBmaWd1cmUgc2hvd3MgdGhlIHR5cGVzIG9mIGV4dGVybmFsIGRhdGEgdGhhdCBhcmUgY29ubmVjdGVkIHRvIFRhYmxlYXUuIFRoZXJlIGFyZSBzb21lIGJ1aWx0LWluIGRhdGEgc2V0cyBhdmFpbGFibGUgaW4gVGFibGVhdSBmb3IgcHJhY3RpY2UgcHVycG9zZXMuDQoNCg0KV2Ugb3BlbiB0aGUgcHJvZ3JhbSBhbmQgc2VlIHRoZSBmb2xsb3dpbmcgVUkuDQoNCjxicj4NCjxjZW50ZXI+DQo8aW1nIHNyYyA9Imh0dHBzOi8vZ2l0aHViLmNvbS9wZW5nZHNjaS9zdGE1NTMvYmxvYi9tYWluL1RhYmxlYXUvVEJMRnJvbnRQYWdlLnBuZz9yYXc9dHJ1ZSIgd2lkdGggPSA2MDAgaGVpZ2h0ID0gNTAwPg0KPC9jZW50ZXI+DQo8YnI+DQoNClRoZSBIYXdrcyBkYXRhIGlzIGluIENTViBmb3JtYXQsIHdlIGNob29zZSBgdGV4dCBmaWxlYCB0byBjb25uZWN0IHRvIHRoZSBkYXRhIHNldC4gQWZ0ZXIgdGhlIGRhdGEgaXMgY29ubmVjdGVkLCB3ZSB3aWxsIHNlZSB0aGUgZm9sbG93aW5nIERhdGEgU291cmNlIHBhZ2Ugd2l0aCBicmllZiBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGF0YSBzZXQuDQoNCjxicj4NCjxjZW50ZXI+DQo8aW1nIHNyYyA9Imh0dHBzOi8vZ2l0aHViLmNvbS9wZW5nZHNjaS9zdGE1NTMvYmxvYi9tYWluL1RhYmxlYXUvVEJMRGF0YVNvdXJjZVBhZ2UucG5nP3Jhdz10cnVlIiB3aWR0aCA9IDUwMCBoZWlnaHQgPSAzNTA+DQo8L2NlbnRlcj4NCjxicj4NCg0KV2UgY2FuIGV4cGxvcmUgdGhlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBzZXQgb24gdGhlIGRhdGEgc291cmNlIHBhZ2UuIFdlIGNhbiBjb25uZWN0IHRvIG11bHRpcGxlIGRhdGEgc2V0cyBhbmQgbWVyZ2UgdGhlbSBvbiB0aGlzIHBhZ2UuDQoNCg0KIyMgT3BlbmluZyBXb3JrIFNoZWV0DQoNCkNsaWNrIHRoZSBTaGVldCB0YWIgaW4gdGhlIGJvdHRvbSBsZWZ0IG9mIHRoZSBkYXRhIHNvdXJjZSBkYXRhLCB3ZSB3aWxsIHRoZSBsaXN0IG9mIHRoZSB2YXJpYWJsZXMgYW5kIHRoZSBwYW5lbHMgb2YgdmlzdWFsaXphdGlvbiB0b29scyBmb3IgbWFraW5nIGNoYXJ0cy4NCg0KPGJyPg0KPGNlbnRlcj4NCjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxTaGVldC5wbmc/cmF3PXRydWUiIHdpZHRoID0gNTAwIGhlaWdodCA9IDM1MD4NCjwvY2VudGVyPg0KPGJyPg0KDQpTdGF0aXN0aWNhbCBjaGFydHMgYXJlIGNyZWF0ZWQgb24gZGlmZmVyZW50IHNoZWV0cy4gV2UgY2FuIGFkZCBtb3JlIHNoZWV0cyBhcyBuZWVkZWQgYW5kIGNoYW5nZSB0aGUgZGVmYXVsdCBzaGVldOKAmXMgbmFtZSB0byBhIG1lYW5pbmdmdWwgbmFtZS4NCg0KTmV4dCwgd2UgY3JlYXRlIGNvbW1vbmx5IHVzZWQgc3RhdGlzdGljYWwgY2hhcnRzIGluIHNlcGFyYXRlIHNoZWV0cy4NCg0KDQojIEJhc2ljIFN0YXRpc3RpY2FsIENoYXJ0cyB3aXRoIEV4aXN0aW5nIFZhcmlhYmxlcw0KDQojIyBCYXIgQ2hhcnQNCg0KQmFyIGNoYXJ0cyBhcmUgb25lIG9mIHRoZSBtb3N0IGNvbW1vbiBkYXRhIHZpc3VhbGl6YXRpb25zLiBXZSBjYW4gdXNlIHRoZW0gdG8gcXVpY2tseSBjb21wYXJlIGRhdGEgYWNyb3NzIGNhdGVnb3JpZXMsIGhpZ2hsaWdodCBkaWZmZXJlbmNlcywgc2hvdyB0cmVuZHMgYW5kIG91dGxpZXJzLCBhbmQgcmV2ZWFsIGhpc3RvcmljYWwgaGlnaHMgYW5kIGxvd3MgYXQgYSBnbGFuY2UuIEJhciBjaGFydHMgYXJlIGVzcGVjaWFsbHkgZWZmZWN0aXZlIHdoZW4geW91IGhhdmUgZGF0YSB0aGF0IGNhbiBiZSBzcGxpdCBpbnRvIG11bHRpcGxlIGNhdGVnb3JpZXMuDQoNCldlIGNvbnNpZGVyIHRoZSBkaXN0cmlidXRpb24gb2YgaGF3ayBzcGVjaWVzLiBDaGFuZ2UgYFNoZWV0IDFgIHRvIGBiYXJDaGFydGAuDQoNCioqU3RlcCAxKio6IERyYWcgYFNwZWNpZXNgIHRvIHRoZSBDb2x1bW4gZmllbGQNCg0KKipTdGVwIDIqKjogRHJhZyBgU3BlY2llc2AgdG8gdGhlIFJvdyBmaWVsZCBhbmQgY2hhbmdlIGl0IHRvIGNvdW50cyAoZnJlcXVlbmNpZXMpLg0KDQo8Y2VudGVyPg0KICA8dGFibGUgYm9yZGVyPSIwIj4NCgk8Y29sIHN0eWxlPSJ3aWR0aDo0NyUiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjYlIj4NCgk8Y29sIHN0eWxlPSJ3aWR0aDo0NyUiPg0KICAgPHRyPg0KICAgIDx0ZD48aW1nIHNyYyA9Imh0dHBzOi8vZ2l0aHViLmNvbS9wZW5nZHNjaS9zdGE1NTMvYmxvYi9tYWluL1RhYmxlYXUvVEJMYmFyQ2hhcnQwMS5wbmc/cmF3PXRydWUiIHdpZHRoID0gMzAwIGhlaWdodCA9IDI1MD48L3RkPg0KICAgIDx0ZD4NCiAgICA8L3RkPg0KICAgIDx0ZD48aW1nIHNyYyA9Imh0dHBzOi8vZ2l0aHViLmNvbS9wZW5nZHNjaS9zdGE1NTMvYmxvYi9tYWluL1RhYmxlYXUvVEJMYmFyQ2hhcnQwMi5wbmc/cmF3PXRydWUiIHdpZHRoID0gMzAwIGhlaWdodCA9IDI1MD48L3RkPg0KICAgPC90cj4NCiAgPC90YWJsZT4NCjwvY2VudGVyPg0KDQoNCiMjIFBpZSBDaGFydA0KDQpQaWUgY2hhcnRzIGFyZSBwb3dlcmZ1bCBmb3IgYWRkaW5nIGRldGFpbCB0byBvdGhlciB2aXN1YWxpemF0aW9ucy4gQWxvbmUsIGEgcGllIGNoYXJ0IGRvZXNu4oCZdCBnaXZlIHRoZSB2aWV3ZXIgYSB3YXkgdG8gcXVpY2tseSBhbmQgYWNjdXJhdGVseSBjb21wYXJlIHRoZSBpbmZvcm1hdGlvbi4gU2luY2UgdGhlIHZpZXdlciBoYXMgdG8gY3JlYXRlIGNvbnRleHQgb24gdGhlaXIgb3duLCBrZXkgcG9pbnRzIGZyb20geW91ciBkYXRhIGFyZSBtaXNzZWQuIEluc3RlYWQgb2YgbWFraW5nIGEgcGllIGNoYXJ0IHRoZSBmb2N1cyBvZiB5b3VyIGRhc2hib2FyZCwgdHJ5IHVzaW5nIGl0IHRvIGRyaWxsIGRvd24gb24gb3RoZXIgdmlzdWFsaXphdGlvbnMuDQoNCioqU3RlcCAxKio6IHJlcGVhdCB0aGUgdHdvIHN0ZXBzIGluIHRoZSBiYXIgY2hhcnQuDQoNCioqU3RlcCAyKio6IENsaWNrIGBTaG93IE1lYCBvbiB0aGUgdG9wLXJpZ2h0IG9mIHRoZSBVSSBhbmQgc2VsZWN0IGBwaWVjaGFydCBpY29uYC4NCg0KKipTdGVwIDMqKjogU2VsZWN0IHRoZSBgRW50aXJlIFZpZXdgIGZyb20gdGhlIHRvcCBwYW5lbCBkcm9wLWRvd24gbWVudS4NCg0KKipTdGVwIDQqKjogZHJhZyBgU3BlY2llc2AgdG8gYExhYmVsYCBpbiAqKk1hcmtzKiogcGFuZWwuDQoNCjxjZW50ZXI+DQogIDx0YWJsZSBib3JkZXI9IjAiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQoJPGNvbCBzdHlsZT0id2lkdGg6NiUiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQogICA8dHI+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxwaWVDaGFydDAxLnBuZz9yYXc9dHJ1ZSIgd2lkdGggPSAzMDAgaGVpZ2h0ID0gMjUwPjwvdGQ+DQogICAgPHRkPg0KICAgIDwvdGQ+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxwaWVDaGFydDAyLnBuZz9yYXc9dHJ1ZSIgd2lkdGggPSAzMDAgaGVpZ2h0ID0gMjUwPjwvdGQ+DQogICA8L3RyPg0KICA8L3RhYmxlPg0KPC9jZW50ZXI+DQoNCg0KIyMgSGlzdG9ncmFtDQoNCkEgaGlzdG9ncmFtIGlzIGEgY2hhcnQgdGhhdCBkaXNwbGF5cyB0aGUgc2hhcGUgb2YgYSBkaXN0cmlidXRpb24uIEEgaGlzdG9ncmFtIGxvb2tzIGxpa2UgYSBiYXIgY2hhcnQgYnV0IGdyb3VwcyB2YWx1ZXMgZm9yIGEgY29udGludW91cyBtZWFzdXJlIGludG8gcmFuZ2VzIG9yIGJpbnMuDQoNCioqU3RlcCAxKio6IGRyYWcgYHdlaWdodGAgdG8gdGhlIGNvbHVtbiBmaWVsZC4NCg0KKipTdGVwIDIqKjogY2xpY2sgYHNob3cgbWVgLCBpbiB0aGUgZHJvcC1kb3duIG1lbnUgYW5kIHNlbGVjdCBgaGlzdG9ncmFtYCBpY29uLg0KDQoqKlN0ZXAgMyoqOiBDbGljayBgY29sb3JgIGljb24gaW4gdGhlIE1hcmtzIHBhbmVsIHRvIGFkanVzdCB0aGUgY29sb3IgYW5kIGJvcmRlciBvZiB0aGUgaGlzdG9ncmFtLg0KDQoNCjxjZW50ZXI+DQogIDx0YWJsZSBib3JkZXI9IjAiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQoJPGNvbCBzdHlsZT0id2lkdGg6NiUiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQogICA8dHI+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxoaXN0b2dyYW0wMi5wbmc/cmF3PXRydWUiIHdpZHRoID0gMzAwIGhlaWdodCA9IDI1MD48L3RkPg0KICAgIDx0ZD4NCiAgICA8L3RkPg0KICAgIDx0ZD48aW1nIHNyYyA9Imh0dHBzOi8vZ2l0aHViLmNvbS9wZW5nZHNjaS9zdGE1NTMvYmxvYi9tYWluL1RhYmxlYXUvVEJMaGlzdG9ncmFtMDEucG5nP3Jhdz10cnVlIiB3aWR0aCA9IDMwMCBoZWlnaHQgPSAyNTA+PC90ZD4NCiAgIDwvdHI+DQogIDwvdGFibGU+DQo8L2NlbnRlcj4NCg0KDQojIyBCb3gtcGxvdA0KDQpXZSBjYW4gdXNlIGJveCBwbG90cywgYWxzbyBrbm93biBhcyBib3gtYW5kLXdoaXNrZXIgcGxvdHMsIHRvIHNob3cgdGhlIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgYWxvbmcgYW4gYXhpcy4gQm94ZXMgaW5kaWNhdGUgdGhlIG1pZGRsZSA1MCBwZXJjZW50IG9mIHRoZSBkYXRhICh0aGF0IGlzLCB0aGUgbWlkZGxlIHR3byBxdWFydGlsZXMgb2YgdGhlIGRhdGEncyBkaXN0cmlidXRpb24pLg0KDQpUaGUgZm9sbG93aW5nIHN0ZXBzIGFyZSB1c2VkIHRvIGNyZWF0ZSBhIHNpbXBsZSBib3ggcGxvdC4NCg0KKipTdGVwIDEqKjogYWRkIGEgbnVtZXJpY2FsIHZhcmlhYmxlIHRvIHRoZSBzaGVldCAod2UgdXNlIGB3ZWlnaHRgIGluIHRoaXMgZXhhbXBsZSkuDQoNCioqU3RlcCAyKio6IGNoYW5nZSBgd2VpZ2h0YCB0byBkaW1lbnNpb24uIEl0IHdpbGwgYXV0b21hdGljYWxseSBjcmVhdGUgYSBkZWZhdWx0IGJveCBwbG90IHdpdGggZGF0YSBwb2ludHMgcGxvdHRlZCBvbiB0aGUgbnVtZXJpY2FsIGF4aXMuDQoNCioqU3RlcCAzKio6IENoYW5nZSB0aGUgYXBwZWFyYW5jZSBvZiB0aGUgYm94LXBsb3QgYnkgc2VsZWN0aW5nICoqRW50aXJlIFZpZXcqKiAoc2VlIHRoZSAgc2NyZWVuc2hvdCkgDQoNCioqU3RlcCA0Kio6IGNob29zZSBgR2FudHQgQmFyYCB0byBzaG93IHRoZSBkZW5zaXR5IG9mIHRoZSB2YWx1ZXMgYW5kIGVkaXQgdGhlIGJveHBsb3QgdG8gZ2V0IGEgYmV0dGVyIGNoYXJ0Lg0KDQo8Y2VudGVyPg0KICA8dGFibGUgYm9yZGVyPSIwIj4NCgk8Y29sIHN0eWxlPSJ3aWR0aDo0NyUiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjYlIj4NCgk8Y29sIHN0eWxlPSJ3aWR0aDo0NyUiPg0KICAgPHRyPg0KICAgIDx0ZD48aW1nIHNyYyA9Imh0dHBzOi8vZ2l0aHViLmNvbS9wZW5nZHNjaS9zdGE1NTMvYmxvYi9tYWluL1RhYmxlYXUvVEJMYm94UGxvdDAxLnBuZz9yYXc9dHJ1ZSIgd2lkdGggPSAzMDAgaGVpZ2h0ID0gMjUwPjwvdGQ+DQogICAgPHRkPg0KICAgIDwvdGQ+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxib3hQbG90MDIucG5nP3Jhdz10cnVlIiB3aWR0aCA9IDMwMCBoZWlnaHQgPSAyNTA+PC90ZD4NCiAgIDwvdHI+DQogIDwvdGFibGU+DQo8L2NlbnRlcj4NCg0KDQojIyBMaW5lIENoYXJ0DQoNClRoZSBsaW5lIGNoYXJ0LCBvciBsaW5lIGdyYXBoLCBjb25uZWN0cyBzZXZlcmFsIGRpc3RpbmN0IGRhdGEgcG9pbnRzLCBwcmVzZW50aW5nIHRoZW0gYXMgb25lIGNvbnRpbnVvdXMgZXZvbHV0aW9uLiBVc2UgbGluZSBjaGFydHMgdG8gdmlldyB0cmVuZHMgaW4gZGF0YSwgdXN1YWxseSBvdmVyIHRpbWUgKGxpa2Ugc3RvY2sgcHJpY2UgY2hhbmdlcyBvdmVyIGZpdmUgeWVhcnMgb3Igd2Vic2l0ZSBwYWdlIHZpZXdzIGZvciB0aGUgbW9udGgpLiBUaGUgcmVzdWx0IGlzIGEgc2ltcGxlLCBzdHJhaWdodGZvcndhcmQgd2F5IHRvIHZpc3VhbGl6ZSBjaGFuZ2VzIGluIG9uZSB2YWx1ZSByZWxhdGl2ZSB0byBhbm90aGVyLg0KDQoqKlN0ZXAgMSoqOiBEcmFwIGB5ZWFyYCB0byB0aGUgY29sdW1uIGZpZWxkIGFuZCBgU3BlY2llc2AgdG8gdGhlIHJvdyBmaWVsZCBhbmQgY29udmVydCB0aGVtIGludG8gZnJlcXVlbmNpZXMuDQoNCioqU3RlcCAyKio6IENsaWNrIGBTaG93IE1lYCBvbiB0aGUgdG9wLXJpZ2h0IG9mIHRoZSBVSSBhbmQgc2VsZWN0IHRoZSBgbGluZSBwbG90YCBpY29uLg0KDQoqKlN0ZXAgMyoqOiByaWdodC1jbGljayBgU3BlY2llc2AgYW5kIGBTZXhgIGFuZCBzZW5kIHRoZW0gdG8gdGhlICoqRmlsdGVyKiogcGFuZWwuDQoNCioqU3RlcCA0Kio6IENob29zZSBhbiBhcHByb3ByaWF0ZSBkaXNwbGF5IGZvcm0gb2YgdGhlIGZpbHRlciAoc2VlIHRoZSByaWdodCBwYW5lbCBvZiB0aGUgZm9sbG93aW5nIHNjcmVlbnNob3QpDQoNCjxjZW50ZXI+DQogIDx0YWJsZSBib3JkZXI9IjAiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQoJPGNvbCBzdHlsZT0id2lkdGg6NiUiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQogICA8dHI+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxsaW5lUGxvdDAxLnBuZz9yYXc9dHJ1ZSIgd2lkdGggPSAzMDAgaGVpZ2h0ID0gMjUwPjwvdGQ+DQogICAgPHRkPg0KICAgIDwvdGQ+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxsaW5lUGxvdDAyLnBuZz9yYXc9dHJ1ZSIgd2lkdGggPSAzMDAgaGVpZ2h0ID0gMjUwPjwvdGQ+DQogICA8L3RyPg0KICA8L3RhYmxlPg0KPC9jZW50ZXI+DQoNCg0KIyMgU2NhdHRlciBQbG90DQoNClNjYXR0ZXIgcGxvdHMgYXJlIGFuIGVmZmVjdGl2ZSB3YXkgdG8gaW52ZXN0aWdhdGUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGRpZmZlcmVudCB2YXJpYWJsZXMsIHNob3dpbmcgaWYgb25lIHZhcmlhYmxlIGlzIGEgZ29vZCBwcmVkaWN0b3Igb2YgYW5vdGhlciwgb3IgaWYgdGhleSB0ZW5kIHRvIGNoYW5nZSBpbmRlcGVuZGVudGx5LiBBIHNjYXR0ZXIgcGxvdCBwcmVzZW50cyBsb3RzIG9mIGRpc3RpbmN0IGRhdGEgcG9pbnRzIG9uIGEgc2luZ2xlIGNoYXJ0LiBUaGUgY2hhcnQgY2FuIHRoZW4gYmUgZW5oYW5jZWQgd2l0aCBhbmFseXRpY3MgbGlrZSBjbHVzdGVyIGFuYWx5c2lzIG9yIHRyZW5kIGxpbmVzLg0KDQpMZXQncyBleHBsb3JlIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBsZW5ndGhzIG9mIHdpbmdzIGFuZCB0YWlscyBvZiBoYXdrcyBhY3Jvc3MgdGhlIHNwZWNpZXMuIFRoZSBmb2xsb3dpbmcgc3RlcHMgY3JlYXRlIGEgc2ltcGxlIHNjYXR0ZXIgcGxvdCBpbiBUYWJsZWF1LiANCg0KKipTdGVwIDEqKjogZHJhZyB0aGUgdHdvIG51bWVyaWNhbCB2YXJpYWJsZXMgdG8gY29sdW1uIGFuZCByb3cgZmllbGRzLg0KDQoqKlN0ZXAgMioqOiBDaGFuZ2UgdGhlIHR3byBhZ2dyZWdhdGVkIHZhcmlhYmxlcyAoYnkgZGVmYXVsdCkgdG8gYGRpbWVuc2lvbmAgKHNlZSB0aGUgbGVmdC1oYW5kIHNpZGUgc2NyZWVuc2hvdCkuDQoNCioqU3RlcCAzKio6IENvbG9yIGNvZGUgdGhlIHNwZWNpZXMgKGRyYWcgYHNwZWNpZXNgIHRvIHRoZSAqKmNvbG9yKiogbWFyaykuDQoNCioqU3RlcCA0Kio6IENob29zZSB0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIHRvIGRlZmluZSBmaWx0ZXJzIHRvIGV4cGxvcmUgdGhlIGFzc29jaWF0aW9uIG9mIGEgc3Vic2V0IG9mIHRoZSBkYXRhIChwYXJ0aWFsIGFzc29jaWF0aW9uKSB1c2luZyB0aGUgZHJvcC1kb3duIG1lbnUsIHJhZGlvIGJ1dHRvbiwgc2xpZGVyLCBldGMuDQoNCjxjZW50ZXI+DQogIDx0YWJsZSBib3JkZXI9IjAiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQoJPGNvbCBzdHlsZT0id2lkdGg6NiUiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQogICA8dHI+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxzY2F0dGVyUGxvdDAxLnBuZz9yYXc9dHJ1ZSIgd2lkdGggPSAzMDAgaGVpZ2h0ID0gMjUwPjwvdGQ+DQogICAgPHRkPg0KICAgIDwvdGQ+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxzY2F0dGVyUGxvdDAyLnBuZz9yYXc9dHJ1ZSIgd2lkdGggPSAzMDAgaGVpZ2h0ID0gMjUwPjwvdGQ+DQogICA8L3RyPg0KICA8L3RhYmxlPg0KPC9jZW50ZXI+DQoNCg0KIyMgQnViYmxlIENoYXJ0DQoNCkFsdGhvdWdoIGJ1YmJsZXMgYXJlbuKAmXQgdGVjaG5pY2FsbHkgdGhlaXIgb3duIHR5cGUgb2YgdmlzdWFsaXphdGlvbiwgdXNpbmcgdGhlbSBhcyBhIHRlY2huaXF1ZSBhZGRzIGRldGFpbCB0byBzY2F0dGVyIHBsb3RzIG9yIG1hcHMgdG8gc2hvdyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhyZWUgb3IgbW9yZSBtZWFzdXJlcy4gVmFyeWluZyB0aGUgc2l6ZSBhbmQgY29sb3Igb2YgY2lyY2xlcyBjcmVhdGVzIHZpc3VhbGx5IGNvbXBlbGxpbmcgY2hhcnRzIHRoYXQgcHJlc2VudCBsYXJnZSB2b2x1bWVzIG9mIGRhdGEgYXQgb25jZS4NCg0KQSBidWJibGUgY2hhcnQgaXMgbW9kaWZpZWQgZnJvbSBhIHJlZ3VsYXIgc2NhdHRlciBwbG90LiBXZSBuZXh0IHVzZSB0aGUgYWJvdmUgc2NhdHRlciBwbG90IGFzIGEgYmFzZSBwbG90IGFuZCBtYWtlIHRoZSBwb2ludCBzaXplIHByb3BvcnRpb25hbCB0byB0aGUgdmFsdWUgb2YgdGhlIHZhcmlhYmxlIGB3aW5nYC4NCg0KKipTdGVwIDEqKjogY3JlYXRlIGEgYmFzaWMgc2NhdHRlciBwbG90IChmb2xsb3dpbmcgc3RlcHMgMS00IGluIHRoZSBwcmV2aW91cyBzZWN0aW9uIG9mIHRoZSBzY2F0dGVyIHBsb3QpLg0KDQoqKlN0ZXAgMioqOiBkcmFnIHZhcmlhYmxlIGB3aW5nYCB0byAqKnNpemUqKiBpY29uIChNYXJrcyBwYW5lbCkuDQoNCioqU3RlcCAzKio6IHJpZ2h0ICoqY29sb3IqKiBpY29uIGluIE1hcmtzIHBhbmVsIHRvIGFkanVzdCB0cmFuc3BhcmVuY3kgYW5kIG1vZGlmeSB0aGUgcG9pbnQgYm9yZGVyIHRvIG1ha2UgcGFydGlhbGx5IG92ZXJsYXBwZWQgcG9pbnRzIGRpc3Rpbmd1aXNoYWJsZS4NCg0KKipTdGVwIDQqKjogY29udmVydCBgeWVhcmAgdG8gYSBzdHJpbmcgdmFyaWFibGUgYW5kIGFkZCBgc2V4YCBhbmQgYHllYXJgIHRvIHRoZSBmaWx0ZXIuDQoNCioqU3RlcCA1Kio6IENoYW5nZSB0aGUgZGVmYXVsdCBkaXNwbGF5IG9mIHllYXIgZnJvbSBgc2VsZWN0IG1lbnVgIHRvICoqZHJvcC1kb3duIG1lbnUqKiBhbmQgYHNleGAgdG8gKipyYWRpbyBidXR0b24qKg0KDQoNCjxjZW50ZXI+DQogIDx0YWJsZSBib3JkZXI9IjAiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQoJPGNvbCBzdHlsZT0id2lkdGg6NiUiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjQ3JSI+DQogICA8dHI+DQogICAgPHRkPjxpbWcgc3JjID0iaHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL3N0YTU1My9ibG9iL21haW4vVGFibGVhdS9UQkxidWJibGVQbG90MDEucG5nP3Jhdz10cnVlIiB3aWR0aCA9IDMwMCBoZWlnaHQgPSAyNTA+PC90ZD4NCiAgICA8dGQ+DQogICAgPC90ZD4NCiAgICA8dGQ+PGltZyBzcmMgPSJodHRwczovL2dpdGh1Yi5jb20vcGVuZ2RzY2kvc3RhNTUzL2Jsb2IvbWFpbi9UYWJsZWF1L1RCTGJ1YmJsZVBsb3QwMi5wbmc/cmF3PXRydWUiIHdpZHRoID0gMzAwIGhlaWdodCA9IDI1MD48L3RkPg0KICAgPC90cj4NCiAgPC90YWJsZT4NCjwvY2VudGVyPg0KDQoNCiMjIFRyZWVtYXANCg0KVHJlZW1hcHMgcmVsYXRlIGRpZmZlcmVudCBzZWdtZW50cyBvZiB5b3VyIGRhdGEgdG8gdGhlIHdob2xlLiBBcyB0aGUgbmFtZSBvZiB0aGUgY2hhcnQgc3VnZ2VzdHMsIGVhY2ggcmVjdGFuZ2xlIGluIGEgdHJlZW1hcCBpcyBzdWJkaXZpZGVkIGludG8gc21hbGxlciByZWN0YW5nbGVzLCBvciBzdWItYnJhbmNoZXMsIGJhc2VkIG9uIGl0cyBwcm9wb3J0aW9uIHRvIHRoZSB3aG9sZS4gVGhleSBtYWtlIGVmZmljaWVudCB1c2Ugb2Ygc3BhY2UgdG8gc2hvdyB0aGUgcGVyY2VudCB0b3RhbCBmb3IgZWFjaCBjYXRlZ29yeS4NCg0KDQojIyBNYXBzDQoNCk1hcHMgYXJlIGEgbm8tYnJhaW5lciBmb3IgdmlzdWFsaXppbmcgYW55IGtpbmQgb2YgbG9jYXRpb24gaW5mb3JtYXRpb24sIHdoZXRoZXIgaXTigJlzIHBvc3RhbCBjb2Rlcywgc3RhdGUgYWJicmV2aWF0aW9ucywgY291bnRyeSBuYW1lcywgb3IgeW91ciBvd24gY3VzdG9tIGdlb2NvZGluZy4gSWYgeW91IGhhdmUgZ2VvZ3JhcGhpYyBpbmZvcm1hdGlvbiBhc3NvY2lhdGVkIHdpdGggeW91ciBkYXRhLCBtYXBzIGFyZSBhIHNpbXBsZSBhbmQgY29tcGVsbGluZyB3YXkgdG8gc2hvdyBob3cgbG9jYXRpb24gY29ycmVsYXRlcyB3aXRoIHRyZW5kcyBpbiB5b3VyIGRhdGEuIExldCdzIGxvb2sgYXQgYSBzbWFsbCBkYXRhIHNldCB3aXRoIGdlby1pbmZvcm1hdGlvbi4gVGhlIGRhdGEgc2V0IGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Blbmdkc2NpL2RhdGFzZXRzL21haW4vUmVhbGVzdGF0ZS5jc3Y+LiBXZSBmaXJzdCBkb3dubG9hZCB0aGlzIGRhdGEgYW5kIHNhdmUgaXQgdG8gYSBsb2NhbCBmb2xkZXIgc28gd2UgY2FuIGNvbm5lY3QgdGhlIGRhdGEgdG8gVGFibGVhdS4NCg0KVGhlIGZvbGxvd2luZyBzdGVwcyB3aWxsIGNyZWF0ZSBhIG1hcCB0byB2aWV3IHRoZSBzcGF0aWFsIGRpc3RyaWJ1dGlvbiBvZiBwcm9wZXJ0aWVzIGluIHRoZSBiYXkgYXJlYS4NCg0KDQoqKlN0ZXAgMSoqLiBEcmFnIGBsb25naXR1ZGVgIGFuZCBgbGF0aXR1ZGVgIHRvIHJvdyBhbmQgY29sdW1uIGZpZWxkcyByZXNwZWN0aXZlbHkuDQoNCioqU3RlcCAyKiouIENsaWNrIGBTaG93IG1lYCBhbmQgc2VsZWN0IHRoZSBXb3JsZCBNYXAgaW4gdGhlIGxpc3Qgb2YgdGhlIHRlbXBsYXRlIHBsb3RzLg0KDQoqKlN0ZXAgMyoqLiBHbyB0byB0aGUgdG9wIG1lbnUgYmFyLCBhbmQgY2xpY2sgYE1hcGAgdG8gc2VsZWN0IGEgYmFja2dyb3VuZCBtYXAuDQoNCioqU3RlcCA0KiouIENsaWNrIHRoZSBgQ29sb3JgIHNoZWxmIGluIHRoZSBNYXJrcyBmaWVsZCwgYW5kIGNoYW5nZSB0aGUgZGVmYXVsdCBjb2xvciB0byBhbiBhcHByb3ByaWF0ZSBjb2xvci4NCg0KKipTdGVwIDUqKi4gQ2hvb3NlIGFuIGFwcHJvcHJpYXRlIGNvbG9yLg0KDQoqKlN0ZXAgNioqLiBzZWxlY3QgYW4gYXBwcm9wcmlhdGUgdmFyaWFibGUgdG8gZGV0ZXJtaW5lIHRoZSBwb2ludCBzaXplLg0KDQoqKlN0ZXAgNyoqLiBkcmFnIHRoZSB2YXJpYWJsZSB5b3Ugd2FudCB0byBkaXNwbGF5IGluIHRoZSBob3ZlciB0ZXh0Lg0KDQpUaGUgZm9sbG93aW5nIHNjcmVlbnNob3Qgd2FzIGNyZWF0ZWQgYmFzZWQgb24gdGhlIGFib3ZlIHN0ZXBzLg0KDQoNCjxjZW50ZXI+PGltZyBzcmMgPSJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcGVuZ2RzY2kvc3RhNTUzL21haW4vVGFibGVhdS9UQkxSZWFsRXN0TWFwLnBuZyIgd2lkdGggPSA3NTAgaGVpZ2h0ID0gNTAwPiA8L2NlbnRlcj4NCg0KXA0KDQpUaGUgYWN0dWFsIG1hcCBpcyBhdmFpbGFibGUgb24gdGhlIFRhYmxlYXUgUHVibGljIFNlcnZlciBhdCA8aHR0cHM6Ly9wdWJsaWMudGFibGVhdS5jb20vYXBwL3Byb2ZpbGUvY3Blbmcvdml6L0Jvb2sxXzE2NDg3Mzg5OTQxMTYwL1NoZWV0ND9wdWJsaXNoPXllcz4NCg0KDQoNCiMjIERlbnNpdHkgTWFwcw0KDQpEZW5zaXR5IG1hcHMgcmV2ZWFsIHBhdHRlcm5zIG9yIHJlbGF0aXZlIGNvbmNlbnRyYXRpb25zIHRoYXQgbWlnaHQgb3RoZXJ3aXNlIGJlIGhpZGRlbiBkdWUgdG8gYW4gb3ZlcmxhcHBpbmcgbWFyayBvbiBhIG1hcOKAlGhlbHBpbmcgeW91IGlkZW50aWZ5IGxvY2F0aW9ucyB3aXRoIGdyZWF0ZXIgb3IgZmV3ZXIgbnVtYmVycyBvZiBkYXRhIHBvaW50cy4gRGVuc2l0eSBtYXBzIGFyZSBtb3N0IGVmZmVjdGl2ZSB3aGVuIHdvcmtpbmcgd2l0aCBhIGRhdGEgc2V0IGNvbnRhaW5pbmcgbWFueSBkYXRhIHBvaW50cyBpbiBhIHNtYWxsIGdlb2dyYXBoaWMgYXJlYS4NCg0KTGV0J3MgdXNlIHRoZSBQT0MgKFVTIGdhcyBzdGF0aW9uIGRhdGEpIGFzIGFuIGV4YW1wbGUgb2YgaG93IHRvIGhhbmRsZSB0aGUgZGF0YSB3aXRoIHR3byBkYXRhIHBvaW50cy4gVGhlIGRhdGEgY2FuIGJlIGZvdW5kIGF0OiA8aHR0cHM6Ly9naXRodWIuY29tL3Blbmdkc2NpL2RhdGFzZXRzL3Jhdy9tYWluL1BPQy5jc3Y+LiBXZSBmaXJzdCBkb3dubG9hZCB0aGlzIGRhdGEgZmlsZSBzYXZlIGl0IGludG8gYSBsb2NhbCBmb2xkZXIgYW5kIHRoZW4gY29ubmVjdCBUYWJsZWF1IHRvIHRoaXMgZGF0YS4NCg0KVGhlIGZvbGxvd2luZyBzdWdnZXN0ZWQgc3RlcHMgd2lsbCBjcmVhdGUgYSBkZW5zaXR5IG1hcCBmb3IgdGhlIFVTIGdhcyBzdGF0aW9ucy4NCg0KKipTdGVwIDEqKi4gQ29udmVydCBgeGNvb3JkYCBhbmQgYHljb29yZGAgdG8gbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSAoc2VlIHRoZSBsZWZ0IHNjcmVlbnNob3QgYmVsb3cpLg0KDQoqKlN0ZXAgMioqLiBEcmFnIGB4Y29vcmRgIGFuZCBgeWNvb3JkYCB0byByb3cgYW5kIGNvbHVtbiBmaWVsZHMgcmVzcGVjdGl2ZWx5Lg0KDQoqKlN0ZXAgMyoqLiBJbiB0aGUgZHJvcC1kb3duIG1lbnUgb2YgdGhlIE1hcmtzIGZpZWxkLCBzZWxlY3QgYGRlbnNpdHlgLg0KDQoqKlN0ZXAgNCoqLiBHbyB0byB0aGUgdG9wIG1lbnUgYmFyLCBhbmQgY2xpY2sgYE1hcGAgdG8gc2VsZWN0IGEgYmFja2dyb3VuZCBtYXAuDQoNCioqU3RlcCA1KiouIENsaWNrIHRoZSBgQ29sb3JgIHNoZWxmIGluIHRoZSBNYXJrcyBmaWVsZCwgYW5kIGNoYW5nZSB0aGUgZGVmYXVsdCBjb2xvciB0byBhbiBhcHByb3ByaWF0ZSBjb2xvci4NCg0KDQo8Y2VudGVyPg0KICA8dGFibGUgYm9yZGVyPSIwIj4NCgk8Y29sIHN0eWxlPSJ3aWR0aDo0NyUiPg0KCTxjb2wgc3R5bGU9IndpZHRoOjYlIj4NCgk8Y29sIHN0eWxlPSJ3aWR0aDo0NyUiPg0KICAgPHRyPg0KICAgIDx0ZD48aW1nIHNyYyA9Imh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9wZW5nZHNjaS9zdGE1NTMvbWFpbi9UYWJsZWF1L1RCTHBvY0xvbmcucG5nIiB3aWR0aCA9IDMwMCBoZWlnaHQgPSAyNTA+PC90ZD4NCiAgICA8dGQ+DQogICAgPC90ZD4NCiAgICA8dGQ+PGltZyBzcmMgPSJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcGVuZ2RzY2kvc3RhNTUzL21haW4vVGFibGVhdS9UQkxwb2MtZGVuc2l0eS5wbmciIHdpZHRoID0gMzAwIGhlaWdodCA9IDI1MD48L3RkPg0KICAgPC90cj4NCiAgPC90YWJsZT4NCjwvY2VudGVyPg0KDQoNClRoZSBhY3R1YWwgaW50ZXJhY3RpdmUgbWFwIGlzIG9uIHRoZSBUYWJsZWF1IFB1YmxpYyBTZXJ2ZXIgYXQgPGh0dHBzOi8vcHVibGljLnRhYmxlYXUuY29tL2FwcC9wcm9maWxlL2NwZW5nL3Zpei9QT0MtbWFwL1NoZWV0MT9wdWJsaXNoPXllcz4NCg0KXA0KDQojIENhbGN1bGF0ZWQgRGVyaXZlZCBGZWF0dXJlcyBhbmQgUGFyYW1ldGVycw0KDQpXZSBoYXZlIGludHJvZHVjZWQgc29tZSBvZiB0aGUgYmFzaWMgc3RhdGlzdGljYWwgZ3JhcGhpY3MgdGhhdCBvbmx5IHJlcXVpcmUgcG9pbnQtYW5kLWNsaWNrLCBOZXh0IHdlIGludHJvZHVjZSBncmFwaGljcyB0aGF0IHJlcXVpcmUgZGVyaXZlZCB2YXJpYWJsZXMgdXNpbmcgVGFibGVhdSdzIGNhcGFiaWxpdHkgb2YgY3JlYXRpbmcgY2FsY3VsYXRlZCBmaWVsZHMgYW5kIHBhcmFtZXRlcnMuIA0KDQpBbHRob3VnaCBUYWJsZWF1IGlzICpub3QqIGEgc29mdHdhcmUgcHJvZ3JhbSBmb3Igc3RhdGlzdGljYWwgbW9kZWxpbmcsIHNvbWUgb2YgdGhlIGJ1aWx0LWluIFRhYmxlYXUgZnVuY3Rpb25zIGNhbiBiZSB1c2VkIGZvciBzb21lIGJhc2ljIG1vZGVsaW5nIHRhc2tzLiBUaGUgZGV0YWlsZWQgbGlzdCBvZiBhdmFpbGFibGUgVGFibGVhdSBmdW5jdGlvbnMgY2FuIGJlIGZvdW5kIGF0IFtodHRwczovL2hlbHAudGFibGVhdS5jb20vY3VycmVudC9wcm8vZGVza3RvcC9lbi11cy9mdW5jdGlvbnMuaHRtXShodHRwczovL2hlbHAudGFibGVhdS5jb20vY3VycmVudC9wcm8vZGVza3RvcC9lbi11cy9mdW5jdGlvbnMuaHRtKS4gVGhpcyBub3RlIG9ubHkgZm9jdXNlcyBvbiBkZXNjcmlwdGl2ZSB2aXN1YWwgYW5hbHlzaXMgdXNpbmcgc2ltcGxlIGJ1aWx0aW4gZ3JhcGhpY2FsIGZ1bmN0aW9ucy4NCg0KSW4gcHJhY3RpY2UsIG1hbnkgc3RhdGlzdGljYWwgcHJvY2VkdXJlcyBhcmUgYmFzZWQgb24gdGhlIGFzc3VtcHRpb24gb2Ygbm9ybWFsIGRpc3RyaWJ1dGlvbi4gQXMgYW4gZXhhbXBsZSwgd2Ugd2lsbCBjcmVhdGUgYSBoaXN0b2dyYW0gb2YgYSBudW1lcmljYWwgdmFyaWFibGUgdG8gdmlzdWFsaXplIGl0cyBkaXN0cmlidXRpb24gYW5kIHRoZW4gYWRkIGEgbm9ybWFsIGRlbnNpdHkgY3VydmUgb24gdGhlIHRvcCBvZiB0aGUgaGlzdG9ncmFtIHRvIGNvbXBhcmUgdGhlIGVtcGlyaWNhbCBkaXN0cmlidXRpb24gd2l0aCB0aGUgYWN0dWFsIHRoZW9yZXRpYyBub3JtYWwgZGlzdHJpYnV0aW9uLg0KDQpSZWNhbGwgdGhhdCB0aGUgZ2VuZXJhbCBmb3JtIG9mIHRoZSBub3JtYWwgZGVuc2l0eSBmdW5jdGlvbiBvZiByYW5kb20gdmFyaWFibGUgJFgkIGhhcyB0aGUgZm9sbG93aW5nIGZvcm0NCg0KJCQNCmYoeCkgPSBcZnJhY3sxfXtcc3FydHsyXHBpfSBcc2lnbWF9ZV57LVxmcmFjeyh4LVxtdSleMn17MlxzaWdtYV4yfX0NCiQkDQp3aGVyZSAkXG11JCBpcyB0aGUgbWVhbiBvZiAkWCQgYW5kICRcc2lnbWEkIHRoZSBkZW5zaXR5IGZ1bmN0aW9uIG9mICRYJC4gVG8gbWFrZSBhIG5vcm1hbCBkZW5zaXR5IGN1cnZlIHRoYXQgaGFzIHRoZSBzYW1lIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBhcyB0aGF0IG9mICRYJCwgd2UgbmVlZCB0byBhZGQgdHdvIGZpZWxkcywgYHhiYXJgIGFuZCBgc2R4YCwgdG8gKip0aGUgd29ya3NoZWV0KiogYW5kIHRoZW4gZGVmaW5lIHRoZSB2YXJpYWJsZSBgZnhgIHRvIGRyYXcgdGhlIGRlbnNpdHkgY3VydmUuIFRvIA0KDQpOZXh0LCB3ZSBkZWZpbmUgYSBwYXJhbWV0ZXIgdG8gc3BlY2lmeSB0aGUgYmluIHdpZHRoIHdoZW4gZHJhd2luZyBoaXN0b2dyYW1zIChkZW5zaXR5IGN1cnZlcykgYW5kIHRocmVlIG5ldyB2YXJpYWJsZXMgdG8gZHJhdyB0aGUgZGVuc2l0eSBjdXJ2ZS4NCg0KDQojIyBDcmVhdGUgUGFyYW1ldGVycw0KDQpXaGVuIGNyZWF0aW5nIGEgaGlzdG9ncmFtLCB3ZSBuZWVkIHRvIGRlZmluZSB0aGUgYmluIHdpZHRoIChiYW5kd2lkdGgsIGludGVydmFsIHdpZHRoLCBjbGFzcyB3aWR0aCwgLi4uKSBzbyB0aGF0IGVhY2ggZGF0YSBwb2ludCB3aWxsIGZhbGwgaW50byBvbmUgYW5kIG9ubHkgb25lIGJpbiAoaW50ZXJ2YWwsIGNsYXNzKS4gTWFueSBzdGF0aXN0aWNhbCBzb2Z0d2FyZSBwcm9ncmFtcyBydW4gYW4gYWxnb3JpdGhtIGFuZCBwcm92aWRlIGEgZGVmYXVsdCAob3B0aW1hbCB3aWR0aCBmcm9tIHRoZW9yeSkuIEluIFRhYmxlYXUsIHdlIGNhbiBkZWZpbmUgYSBiaW4gc2l6ZSAoaS5lLiwgd2lkdGgpIG1hbnVhbGx5IHNvIHRoYXQgdGhlIHJlc3VsdGluZyBoaXN0b2dyYW0gb3IgZGVuc2l0eSBjdXJ2ZSBjYW4gYmUgYWRqdXN0ZWQgYnkgY2hhbmdpbmcgdGhlIGJpbiB3aWR0aCB0byBjaG9vc2UgYW4gYXBwcm9wcmlhdGUgd2lkdGggdG8gYmV0dGVyIGRpc3BsYXkgdGhlIGRpc3RyaWJ1dGlvbiBmcm9tIHRoZSB2aXN1YWwgcGVyc3BlY3RpdmUuIFRoZSBUYWJsZWF1IGBwYXJhbWV0ZXJgIGFsbG93cyB1c2VycyB0byBjaGFuZ2UgaXRzIHZhbHVlLiBXZSB3aWxsIGRlZmluZSBiaW4gd2lkdGggYXMgYSBwYXJhbWV0ZXIuIFRoZSBmb2xsb3dpbmcgZmlndXJlIGlsbHVzdHJhdGVzIHRoZSBzdGVwcyBmb3IgZGVmaW5pbmcgdGhlIHBhcmFtZXRlci4gDQoNCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjgwJSIsIGVjaG8gPSBGQUxTRX0NCmluY2x1ZGVfZ3JhcGhpY3MoInRhYmxlYXUvUGFyYW1ldGVyRGVmaW5pdGlvbi5wbmciKQ0KYGBgDQoNCg0KIyMgQ3JlYXRlIENhbGN1bGF0ZWQgVmFyaWFibGVzDQoNCldlIG5leHQgZGVmaW5lIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdmFyaWFibGUgYFRhaWxgIHN0b3JlZCBpbiB0d28gZmllbGRzIG9mIHRoZSB3b3JrYm9vay4gVGhlIGZvbGxvd2luZyBmaWd1cmUgc2hvd3MgdGhlIHN0ZXBzIGZvciBkZWZpbmluZyB0aGUgbWVhbi4gV2UgY2FuIHNpbWlsYXJseSBkZWZpbmUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbi4NCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjgwJSIsIGVjaG8gPSBGQUxTRX0NCmluY2x1ZGVfZ3JhcGhpY3MoInRhYmxlYXUvQ2FsY3VsYXRlZE1lYW4ucG5nIikNCmBgYA0KDQoqKkNvbW1lbnRzKioNCg0KMS4gV2UgdXNlZCBgVE9UQUxgIGZ1bmN0aW9uIGluIHRoZSBhYm92ZSBkZWZpbml0aW9uIG9mIHRoZSBtZWFuIG9mIHRoZSB2YXJpYWJsZSBgVGFpbGAgKGkuZS4sIGFsbCB2YWx1ZXMgb2YgdmFyaWFibGUgYFRhaWxgIGluIHRoZSBkYXRhIHRhYmxlKS4NCg0KMi4gVGFibGVhdSBhbHNvIHByb3ZpZGVzIGEgZnVuY3Rpb24gYEZJWEVEYCB0aGF0IGFsbG93cyB0aGUgY2FsY3VsYXRpb24gb2YgZ3JvdXBlZCBzdW0sIG1lYW4sIGV0Yy4gRm9yIGV4YW1wbGUsIHdlIGNhbiBjb3VudCB0aGUgb2JzZXJ2YXRpb25zIGluIGVhY2ggYHllYXJgIHVzaW5nIHRoZSBmb2xsb3dpbmcgZnVuY3Rpb25zLiBOb3RlIHRoYXQgYEYxYCBpcyB0aGUgb2JzZXJ2YXRpb24gSUQgb2YgdGhlIGRhdGEuDQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI0MCUiLCBlY2hvID0gRkFMU0V9DQppbmNsdWRlX2dyYXBoaWNzKCJ0YWJsZWF1L2dyb3VwZWRNZWFzdXJlcy5wbmciKQ0KYGBgDQoNCjMuIENyZWF0ZSBgYmluIHZhbHVlYCBzbyB0aGF0IHRoZSBoaXN0b2dyYW1zIG9mIGBUYWlsYCBhbmQgYG5vcm1hbEN1cnZlYCB3aWxsIHVzZSB0aGUgc2FtZSBiaW4gd2lkdGguDQoNCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI0MCUiLCBlY2hvID0gRkFMU0V9DQppbmNsdWRlX2dyYXBoaWNzKCJ0YWJsZWF1L0JpblZhbHVlLnBuZyIpDQpgYGANCg0KDQoNCjQuIGBBVFRSKClgIGlzIGEgc3BlY2lhbCBUYWJsZWF1IGZ1bmN0aW9uIHRoYXQgZWZmZWN0aXZlbHkgKipyZXR1cm5zIGEgcmVjb3JkLWxldmVsIHJlc3VsdCBhcyBhbiBhZ2dyZWdhdGlvbioqLiBJZiB0aGVyZSBhcmUgbXVsdGlwbGUgdmFsdWVzIG9mIHRoZSByZWNvcmQtbGV2ZWwgZmllbGQgaW4gdGhlIGN1cnJlbnQgY29udGV4dCB0aGVuIGBBVFRSKClgIHdpbGwgcmV0dXJuIHRoZSBudW1iZXIgb2YgdmFsdWVzIGluc3RlYWQgb2YgYSBzaW5nbGUgdmFsdWUuDQoNCg0KTmV4dCwgd2UgdXNlIHRoZSBmb3JtdWxhIG9mIHRoZSBkZW5zaXR5IHRvIGNhbGN1bGF0ZSBub3JtYWwgZGVuc2l0eSBzY29yZXMgYW5kIHNhdmUgdGhlbSBpbiB0aGUgZmllbGQgYG5vcm1hbEN1cnZlYC4gVGhlIFRhYmxlYXUgZm9ybXVsYSBpcyBnaXZlbiBieQ0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNzAlIiwgZWNobyA9IEZBTFNFfQ0KaW5jbHVkZV9ncmFwaGljcygidGFibGVhdS9Ob3JtYWxDdXJ2ZVNjb3JlLnBuZyIpDQpgYGANCg0KDQpTdGVwcyBmb3IgY3JlYXRpbmcgYSBoaXN0b2dyYW0gd2l0aCBhIGRlbnNpdHkgY3VydmUgYmVpbmcgcGxhY2VkIG9uIHRoZSB0b3Agb2YgaXQuDQoNCjEuIENyZWF0ZSB0d28gaGlzdG9ncmFtczogYFRhaWxgIGFuZCBgbm9ybWFsQ3VydmVgLg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iOTAlIiwgZWNobyA9IEZBTFNFfQ0KaW5jbHVkZV9ncmFwaGljcygidGFibGVhdS90d29IaXN0b2dyYW0ucG5nIikNCmBgYA0KDQoyLiBDaGFuZ2UgdGhlIGhpc3RvZ3JhbSBvZiBgbm9ybWFsQ3VydmVgIHRvIGEgZGVuc2l0eSBjdXJ2ZSBieSBjaGFuZ2luZyB0aGUgbWFyayB0eXBlIGZyb20gYEJhcmAgdG8gYExpbmVgIGluIHRoZSBNYXJrcyBwYW5lbA0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iOTAlIiwgZWNobyA9IEZBTFNFfQ0KaW5jbHVkZV9ncmFwaGljcygidGFibGVhdS9kZW5zaXR5Q3VydmUucG5nIikNCmBgYA0KDQozLiBSaWdodC1jbGljayB0aGUgbGVmdC1oYW5kIHNpZGUgYW5kIHNlbGVjdCBgRHVhbCBBeGlzYCB0byBwbGFjZSB0aGUgZGVuc2l0eSBjdXJ2ZSBvbiB0aGUgaGlzdG9ncmFtDQoNCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjkwJSIsIGVjaG8gPSBGQUxTRX0NCmluY2x1ZGVfZ3JhcGhpY3MoInRhYmxlYXUvQ2hvb3NpbmdEdWFsQXhpcy5wbmciKQ0KYGBgDQoNCjQuIFJpZ2h0LWNsaWNrIHRoZSByaWdodC1oYW5kIHNpZGUgYXhpcyBvZiB0aGUgcmVzdWx0aW5nIG92ZXJsYXkgZ3JhcGggYW5kIHVuY2hlY2sgYFNob3cgSGVhZGVyYCB0byBnZXQgdGhlIGZvbGxvd2luZy4NCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjkwJSIsIGVjaG8gPSBGQUxTRX0NCmluY2x1ZGVfZ3JhcGhpY3MoInRhYmxlYXUvRmluYWxEZW5zaXR5Q3VydmUucG5nIikNCmBgYA0KDQo1LiAqKldyYXAtdXAqKiBBZnRlciBmaW5pc2hpbmcgdGhlIGFib3ZlIHN0ZXBzLCBnbyB0byBgZmlsZWAgYW5kIHNlbGVjdCBgU2F2ZSB0byBUYWJsZWF1IFB1YmxpYy4uLmAgb3IgYFNhdmUgdG8gVGFibGVhdSBQdWJsaWMgQXNgIGFuZCBmaWxsIGluIHRoZSB0ZXh0IGJveCwgY2xpY2sgYFNhdmVgIGJ1dHRvbiB0byBwdWJsaXNoIHRoZSBncmFwaCBvbiB0aGUgVGFibGVhdSBQdWJsaWMgc2VydmVyLiANCg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iOTAlIiwgZWNobyA9IEZBTFNFfQ0KaW5jbHVkZV9ncmFwaGljcygidGFibGVhdS9GaW5hbERlbnNpdHlDdXJ2ZS5wbmciKQ0KYGBgDQoNCg0KNi4gVG8gZW1iZWQgdGhlIFRhYmxlYXUgZ3JhcGggaW4gdGhlIFJNRCBhbmQgdGhlbiByZW5kZXIgaXQgaW4gYW4gSFRNTCBmb3JtYXQsIGNsaWNrIHRoZSBib3R0b20tcmlnaHQgKipzaGFyZSoqIGJ1dHRvbi4NCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjQwJSIsIGVjaG8gPSBGQUxTRX0NCmluY2x1ZGVfZ3JhcGhpY3MoInRhYmxlYXUvVGFibGVhdVNoYXJlLnBuZyIpDQpgYGANCg0KV2UgY29weSB0aGUgZW1iZWQgY29kZSBhbmQgcGFzdGUgaXQgdG8gdGhlIGNlbGwgb2YgdGhlIHNpbmdsZS1jZWxsIEhUTUwgdGFibGUgaW4gdGhlIFJNRCBkb2N1bWVudCBhbmQgZWRpdCBpdCB3aXRoIHRoZSBjb3JyZWN0IGluZGVudGlvbi4gIA0KDQoNCmBgYGB7dmVyYmF0aW19DQo8dGFibGUgYm9yZGVyID0gMCBib3JkZXJjb2xvcj0iZGFya2dyZWVuIiBiZ2NvbG9yPScjZjZmNmY2JyAgd2lkdGg9MTAwJSAgYWxpZ24gPSBjZW50ZXI+DQo8dHI+DQo8dGQ+DQplbWJlZGRpbmcgSlMgY29kZSBmcm9tIFRhYmxlYXUuLi4NCjwvdGQ+DQo8L3RyPg0KPC90YWJsZT4NCmBgYGANCg0KVGhlIGZvbGxvd2luZyBpcyB0aGUgZW1iZWRkZWQgaW50ZXJhY3RpdmUgVGFibGVhdSBmcm9tIHRoZSBUYWJsZWF1IFB1YmxpYyBzZXJ2ZXIuDQoNCjx0YWJsZSBib3JkZXIgPSAwIGJvcmRlcmNvbG9yPSJkYXJrZ3JlZW4iIGJnY29sb3I9JyNmNmY2ZjYnICB3aWR0aD0xMDAlICBhbGlnbiA9IGNlbnRlcj4NCjx0cj4NCjx0ZD4NCg0KPGRpdiBjbGFzcz0ndGFibGVhdVBsYWNlaG9sZGVyJyBpZD0ndml6MTcxMTI5NzQyNjAyOScgc3R5bGU9J3Bvc2l0aW9uOiByZWxhdGl2ZSc+DQoNCjxub3NjcmlwdD48YSBocmVmPScjJz48aW1nIGFsdD0nSGlzdG9ncmFtIFdpdGggQSBOb3JtYWwgRGVuc2l0eSBDdXJ2ZSAnIHNyYz0naHR0cHM6JiM0NzsmIzQ3O3B1YmxpYy50YWJsZWF1LmNvbSYjNDc7c3RhdGljJiM0NztpbWFnZXMmIzQ3O0hhJiM0NztIYXdrc18xNzExMjk0Nzg1MjI5MCYjNDc7SGlzdERlbnNpdHkmIzQ3OzFfcnNzLnBuZycgc3R5bGU9J2JvcmRlcjogbm9uZScgLz48L2E+DQo8L25vc2NyaXB0Pg0KDQo8b2JqZWN0IGNsYXNzPSd0YWJsZWF1Vml6JyAgc3R5bGU9J2Rpc3BsYXk6bm9uZTsnPg0KPHBhcmFtIG5hbWU9J2hvc3RfdXJsJyB2YWx1ZT0naHR0cHMlM0ElMkYlMkZwdWJsaWMudGFibGVhdS5jb20lMkYnIC8+IA0KPHBhcmFtIG5hbWU9J2VtYmVkX2NvZGVfdmVyc2lvbicgdmFsdWU9JzMnIC8+IA0KPHBhcmFtIG5hbWU9J3NpdGVfcm9vdCcgdmFsdWU9JycgLz4NCjxwYXJhbSBuYW1lPSduYW1lJyB2YWx1ZT0nSGF3a3NfMTcxMTI5NDc4NTIyOTAmIzQ3O0hpc3REZW5zaXR5JyAvPg0KPHBhcmFtIG5hbWU9J3RhYnMnIHZhbHVlPSdubycgLz4NCjxwYXJhbSBuYW1lPSd0b29sYmFyJyB2YWx1ZT0neWVzJyAvPg0KPHBhcmFtIG5hbWU9J3N0YXRpY19pbWFnZScgdmFsdWU9J2h0dHBzOiYjNDc7JiM0NztwdWJsaWMudGFibGVhdS5jb20mIzQ3O3N0YXRpYyYjNDc7aW1hZ2VzJiM0NztIYSYjNDc7SGF3a3NfMTcxMTI5NDc4NTIyOTAmIzQ3O0hpc3REZW5zaXR5JiM0NzsxLnBuZycgLz4gDQo8cGFyYW0gbmFtZT0nYW5pbWF0ZV90cmFuc2l0aW9uJyB2YWx1ZT0neWVzJyAvPg0KPHBhcmFtIG5hbWU9J2Rpc3BsYXlfc3RhdGljX2ltYWdlJyB2YWx1ZT0neWVzJyAvPg0KPHBhcmFtIG5hbWU9J2Rpc3BsYXlfc3Bpbm5lcicgdmFsdWU9J3llcycgLz4NCjxwYXJhbSBuYW1lPSdkaXNwbGF5X292ZXJsYXknIHZhbHVlPSd5ZXMnIC8+DQo8cGFyYW0gbmFtZT0nZGlzcGxheV9jb3VudCcgdmFsdWU9J3llcycgLz4NCjxwYXJhbSBuYW1lPSdsYW5ndWFnZScgdmFsdWU9J2VuLVVTJyAvPg0KPC9vYmplY3Q+PC9kaXY+ICAgICAgICAgICAgICAgIA0KDQo8c2NyaXB0IHR5cGU9J3RleHQvamF2YXNjcmlwdCc+ICAgICAgICAgICAgICAgICAgICANCnZhciBkaXZFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3ZpejE3MTEyOTc0MjYwMjknKTsgICAgICAgICAgICAgICAgICAgIA0KdmFyIHZpekVsZW1lbnQgPSBkaXZFbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdvYmplY3QnKVswXTsgICAgICAgICAgICAgICAgICAgIHZpekVsZW1lbnQuc3R5bGUud2lkdGg9JzEwMCUnO3ZpekVsZW1lbnQuc3R5bGUuaGVpZ2h0PShkaXZFbGVtZW50Lm9mZnNldFdpZHRoKjAuNzUpKydweCc7ICAgIA0KdmFyIHNjcmlwdEVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsgc2NyaXB0RWxlbWVudC5zcmMgPSAnaHR0cHM6Ly9wdWJsaWMudGFibGVhdS5jb20vamF2YXNjcmlwdHMvYXBpL3Zpel92MS5qcyc7ICAgICAgICAgICAgICAgICAgICB2aXpFbGVtZW50LnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHNjcmlwdEVsZW1lbnQsIHZpekVsZW1lbnQpOyAgICAgICAgICAgICAgICANCjwvc2NyaXB0Pg0KDQo8L3RkPg0KPC90cj4NCjwvdGFibGU+DQoNCg0KIyMgUHJhY3RpY2UgLSBSZXByb2R1Y2UgVGhlIEZvbGxvd2luZw0KDQo8dGFibGUgYm9yZGVyID0gMCBib3JkZXJjb2xvcj0iZGFya2dyZWVuIiBiZ2NvbG9yPScjZjZmNmY2JyAgd2lkdGg9MTAwJSAgYWxpZ24gPSBjZW50ZXI+DQo8dHI+DQo8dGQ+DQo8ZGl2IGNsYXNzPSd0YWJsZWF1UGxhY2Vob2xkZXInIGlkPSd2aXoxNzExMjU4NzM4NjEyJyBzdHlsZT0ncG9zaXRpb246IHJlbGF0aXZlJz4NCjxub3NjcmlwdD48YSBocmVmPScjJz48aW1nIGFsdD0nSGlzdG9ncmFtUHJpY2UgJyBzcmM9J2h0dHBzOiYjNDc7JiM0NztwdWJsaWMudGFibGVhdS5jb20mIzQ3O3N0YXRpYyYjNDc7aW1hZ2VzJiM0Nzt3MCYjNDc7dzA5SG9uZXlQcm9kRGFzaEltYWdlJiM0NztIaXN0b2dyYW1QcmljZSYjNDc7MV9yc3MucG5nJyBzdHlsZT0nYm9yZGVyOiBub25lJyAvPjwvYT4NCjwvbm9zY3JpcHQ+DQoNCjxvYmplY3QgY2xhc3M9J3RhYmxlYXVWaXonICBzdHlsZT0nZGlzcGxheTpub25lOyc+DQo8cGFyYW0gbmFtZT0naG9zdF91cmwnIHZhbHVlPSdodHRwcyUzQSUyRiUyRnB1YmxpYy50YWJsZWF1LmNvbSUyRicgLz4gDQo8cGFyYW0gbmFtZT0nZW1iZWRfY29kZV92ZXJzaW9uJyB2YWx1ZT0nMycgLz4gDQo8cGFyYW0gbmFtZT0nc2l0ZV9yb290JyB2YWx1ZT0nJyAvPg0KPHBhcmFtIG5hbWU9J25hbWUnIHZhbHVlPSd3MDlIb25leVByb2REYXNoSW1hZ2UmIzQ3O0hpc3RvZ3JhbVByaWNlJyAvPg0KPHBhcmFtIG5hbWU9J3RhYnMnIHZhbHVlPSdubycgLz48cGFyYW0gbmFtZT0ndG9vbGJhcicgdmFsdWU9J3llcycgLz4NCjxwYXJhbSBuYW1lPSdzdGF0aWNfaW1hZ2UnIHZhbHVlPSdodHRwczomIzQ3OyYjNDc7cHVibGljLnRhYmxlYXUuY29tJiM0NztzdGF0aWMmIzQ3O2ltYWdlcyYjNDc7dzAmIzQ3O3cwOUhvbmV5UHJvZERhc2hJbWFnZSYjNDc7SGlzdG9ncmFtUHJpY2UmIzQ3OzEucG5nJyAvPiANCjxwYXJhbSBuYW1lPSdhbmltYXRlX3RyYW5zaXRpb24nIHZhbHVlPSd5ZXMnIC8+DQo8cGFyYW0gbmFtZT0nZGlzcGxheV9zdGF0aWNfaW1hZ2UnIHZhbHVlPSd5ZXMnIC8+DQo8cGFyYW0gbmFtZT0nZGlzcGxheV9zcGlubmVyJyB2YWx1ZT0neWVzJyAvPg0KPHBhcmFtIG5hbWU9J2Rpc3BsYXlfb3ZlcmxheScgdmFsdWU9J3llcycgLz4NCjxwYXJhbSBuYW1lPSdkaXNwbGF5X2NvdW50JyB2YWx1ZT0neWVzJyAvPg0KPHBhcmFtIG5hbWU9J2xhbmd1YWdlJyB2YWx1ZT0nZW4tVVMnIC8+DQo8L29iamVjdD4NCjwvZGl2PiAgICAgICAgICAgICAgICANCg0KPHNjcmlwdCB0eXBlPSd0ZXh0L2phdmFzY3JpcHQnPiAgICAgICAgICAgICAgICAgICAgDQp2YXIgZGl2RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2aXoxNzExMjU4NzM4NjEyJyk7ICAgICAgICAgICAgICAgICAgIA0KdmFyIHZpekVsZW1lbnQgPSBkaXZFbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdvYmplY3QnKVswXTsgICAgICAgICAgICAgICAgICAgIHZpekVsZW1lbnQuc3R5bGUud2lkdGg9JzEwMCUnO3ZpekVsZW1lbnQuc3R5bGUuaGVpZ2h0PShkaXZFbGVtZW50Lm9mZnNldFdpZHRoKjAuNzUpKydweCc7ICAgICAgICAgICAgICAgICAgIA0KdmFyIHNjcmlwdEVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsgICBzY3JpcHRFbGVtZW50LnNyYyA9ICdodHRwczovL3B1YmxpYy50YWJsZWF1LmNvbS9qYXZhc2NyaXB0cy9hcGkvdml6X3YxLmpzJzsgDQp2aXpFbGVtZW50LnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHNjcmlwdEVsZW1lbnQsIHZpekVsZW1lbnQpOyAgICAgICAgICAgICAgICANCjwvc2NyaXB0Pg0KPC90ZD4NCjwvdHI+DQo8L3RhYmxlPg0KDQojIEltYWdlcywgQW5ub3RhdGlvbnMgYW5kIFRvb2x0aXAgVmlzdWFscw0KDQpBcyB3ZSBkaWQgaW4gdmlzdWFsaXphdGlvbiB3aXRoIFIsIHdlIGNhbiBhbHNvIGFuaW1hdGUgVGFibGVhdSBncmFwaGljcywgaW5zZXJ0IGFubm90YXRpb25zLCBpbWFnZXMgdG9vbHRpcCBwb3B1cHMsIGV0Yy4gaW4gVGFibGVhdSBncmFwaGljcy4gU29tZSBvZiB0aGVzZSBncmFwaGljYWwgdGFza3MgYXJlIG9ubHkgb25lIGNsaWNrIGF3YXksIGFuZCBzb21lIG9mIHRoZW0gcmVxdWlyZSBtdWx0aS1zdGVwIHByb2NlZHVyZXMuIA0KDQpXZSBjYW4gY3JlYXRlIHN0YXRpYyBpbWFnZXMgYXMgbmV3IHNoYXBlcywgYWRkaXRpb25hbCB3b3Jrc2hlZXRzIHRvIHBsYWNlIGluIHRoZSB0b29sdGlwLCBldGMuIHRvIG1ha2UgbW9yZSBpbnRlcmFjdGl2ZSBUYWJsZWF1IGdyYXBoaWNzLiAgDQoNClRoZSBmb2xsb3dpbmcgVGFibGVhdSBncmFwaCBjb250YWlucyBzZXZlcmFsIGZlYXR1cmVzLiBXZSBjYW4gZG93bmxvYWQgdGhlIHdvcmtib29rIHRocm91Z2ggdGhlIGJvdHRvbS1yaWdodCBgZG93bmxvYWRgIGljb24uDQoNCg0KDQojIyBJbnNlcnRpbmcgRXh0ZXJuYWwgSW1hZ2VzDQoNCkluc2VydGluZyBleHRlcm5hbCBpbWFnZXMgKG5vdCBnZW5lcmF0ZWQgYnkgVGFibGVhdSBpbiB0aGUgY3VycmVudCBzZXNzaW9uKSBpbnRvIFRhYmxlYXUgd29ya3NoZWV0cyBpcyBub3Qgc3RyYWlnaHRmb3J3YXJkLiBPbmUgY2FuIGNyZWF0ZSBhIHNlcGFyYXRlIGltYWdlIGZpbGUgdG8gZ2V0IHRoaXMgYXJvdW5kLiBEZXBlbmRpbmcgb24gdGhlIHB1cnBvc2Ugb2YgdXNpbmcgdGhlIGltYWdlcywgb25lIGNhbiBhbHNvIGRlZmluZSBuZXcgc2hhcGVzIHdpdGggZXh0ZXJuYWwgaW1hZ2VzIGFuZCBwbG90IHRoZW0gb24gVGFibGVhdSBncmFwaGljcy4gSW4gdGhpcyBzZWN0aW9uLCB3ZSBjcmVhdGUgYSBzaW5nbGUtY2VsbCBkYXNoYm9hcmQgYW5kIHRoZW4gaW5zZXJ0IGltYWdlcyB0aHJvdWdoIHRoZSBkYXNoYm9hcmQgZm9sbG93aW5nIGEgZmV3IHN0ZXBzDQoNCjEuIENyZWF0ZSBhIHRhYmxlYXUgZ3JhcGhpYyBpbiBhIHN0YW5kYWxvbmUgd29ya3NoZWV0IGd1aWRlZCBieSB0aGUgcHJpbmNpcGxlcyBvZiB2aXN1YWwgZGVzaWduLg0KDQoyLiBDbGljayB0aGUgYERhc2hib2FyZGAgdGFiICh0b3AgcGFuZWwgdGFicykgdG8gb3BlbiBhIGBOZXcgZGFzaGJvYXJkYCBhbmQgcmVuYW1lIHRoZSBkZWZhdWx0IGBEYXNoYm9hcmQgMWAgKGJvdHRvbSBzaGVldCB0YWJzKS4gDQoNCjMuIFVuZGVyIHRoZSBsaXN0IG9mIGBTaGVldHNgIChsZWZ0IHBhbmVsIG9mIHRoZSBVSSksIGRyYWcgdGhlIGdyYXBoaWMgdG8gdGhlIHJpZ2h0LWhhbmQgZGFzaGJvYXJkIGJveC4NCg0KNC4gQWRqdXN0IHRoZSBzaXplIHVzaW5nIHRoZSBkcm9wLWRvd24gbWVudSB1bmRlciBgU2l6ZWAgKGxlZnQgcGFuZWwpDQoNCjUuIENsaWNrIGBMYXlvdXRgIChuZXh0IHRvIGBEYXNoYm9hcmRgIG9uIHRoZSBsZWZ0IHBhbmVsIC0gbm90IHRoZSB0b3AgdGFiIG1lbnUpIGFuZCBjaGVjayBgRmxvYXRpbmdgLg0KDQo2LiBSZXNpemUgdGhlIGdyYXBoaWMgdG8gZml0IHRvIHRoZSBkYXNoYm9hcmQuDQoNCjcuIENsaWNrIGBEYXNoYm9hcmRgIChuZXh0IHRvIGBMYXlvdXRgKSwgZ28gdG8gYE9iamVjdHNgLCBhbmQgZG91YmxlLWNsaWNrIGBJbWFnZWAgb24gdGhlIGxpc3QsIGZvbGxvd2luZyB0aGUgZGlyZWN0aW9ucyB0byB1cGxvYWQgYW4gaW1hZ2Ugb3IgcHJvdmlkZSBhIFVSTCBvZiBhbiBpbWFnZS4NCg0KOC4gRmluZCBhIHNwb3QgdG8gcGxhY2UgdGhlIGltYWdlIGFuZCByZXNpemUgaXQuDQoNCg0KVGhlIGZvbGxvd2luZyBpcyBhbiBleGFtcGxlLiBZb3UgY2FuIGRvd25sb2FkIHRoZSB3b3JrYm9vayB0byBwcmFjdGljZSBhbmQgcmVwcm9kdWNlIGl0IHVzaW5nIHlvdXIgb3duIGltYWdlLg0KDQoNClwNCg0KPHRhYmxlIGJvcmRlciA9IDAgYm9yZGVyY29sb3I9ImRhcmtncmVlbiIgYmdjb2xvcj0nI2Y2ZjZmNicgIHdpZHRoPTEwMCUgIGFsaWduID0gY2VudGVyPg0KPHRyPg0KPHRkPg0KPGRpdiBjbGFzcz0ndGFibGVhdVBsYWNlaG9sZGVyJyBpZD0ndml6MTcxMTE3ODQ1ODY5NCcgc3R5bGU9J3Bvc2l0aW9uOiByZWxhdGl2ZSc+DQogIDxub3NjcmlwdD48YSBocmVmPScjJz48aW1nIGFsdD0nRGFzaEltYWdlICcgc3JjPSdodHRwczomIzQ3OyYjNDc7cHVibGljLnRhYmxlYXUuY29tJiM0NztzdGF0aWMmIzQ3O2ltYWdlcyYjNDc7dzAmIzQ3O3cwOUhvbmV5UHJvZERhc2hJbWFnZSYjNDc7RGFzaEltYWdlJiM0NzsxX3Jzcy5wbmcnIHN0eWxlPSdib3JkZXI6IG5vbmUnIC8+PC9hPjwvbm9zY3JpcHQ+DQogIDxvYmplY3QgY2xhc3M9J3RhYmxlYXVWaXonICBzdHlsZT0nZGlzcGxheTpub25lOyc+DQogIDxwYXJhbSBuYW1lPSdob3N0X3VybCcgdmFsdWU9J2h0dHBzJTNBJTJGJTJGcHVibGljLnRhYmxlYXUuY29tJTJGJyAvPiANCiAgPHBhcmFtIG5hbWU9J2VtYmVkX2NvZGVfdmVyc2lvbicgdmFsdWU9JzMnIC8+IA0KICA8cGFyYW0gbmFtZT0nc2l0ZV9yb290JyB2YWx1ZT0nJyAvPg0KICA8cGFyYW0gbmFtZT0nbmFtZScgdmFsdWU9J3cwOUhvbmV5UHJvZERhc2hJbWFnZSYjNDc7RGFzaEltYWdlJyAvPg0KICBwYXJhbSBuYW1lPSd0YWJzJyB2YWx1ZT0nbm8nIC8+PHBhcmFtIG5hbWU9J3Rvb2xiYXInIHZhbHVlPSd5ZXMnIC8+DQogIDxwYXJhbSBuYW1lPSdzdGF0aWNfaW1hZ2UnIHZhbHVlPSdodHRwczomIzQ3OyYjNDc7cHVibGljLnRhYmxlYXUuY29tJiM0NztzdGF0aWMmIzQ3O2ltYWdlcyYjNDc7dzAmIzQ3O3cwOUhvbmV5UHJvZERhc2hJbWFnZSYjNDc7RGFzaEltYWdlJiM0NzsxLnBuZycgLz4gDQogIDxwYXJhbSBuYW1lPSdhbmltYXRlX3RyYW5zaXRpb24nIHZhbHVlPSd5ZXMnIC8+DQogIDxwYXJhbSBuYW1lPSdkaXNwbGF5X3N0YXRpY19pbWFnZScgdmFsdWU9J3llcycgLz4NCiAgPHBhcmFtIG5hbWU9J2Rpc3BsYXlfc3Bpbm5lcicgdmFsdWU9J3llcycgLz4NCiAgPHBhcmFtIG5hbWU9J2Rpc3BsYXlfb3ZlcmxheScgdmFsdWU9J3llcycgLz4NCiAgPHBhcmFtIG5hbWU9J2Rpc3BsYXlfY291bnQnIHZhbHVlPSd5ZXMnIC8+DQogIDxwYXJhbSBuYW1lPSdsYW5ndWFnZScgdmFsdWU9J2VuLVVTJyAvPg0KICA8L29iamVjdD48L2Rpdj4gICAgICAgICAgICAgICAgDQogIA0KICA8c2NyaXB0IHR5cGU9J3RleHQvamF2YXNjcmlwdCc+ICAgICAgICAgICAgICAgICAgICANCiAgdmFyIGRpdkVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndml6MTcxMTE3ODQ1ODY5NCcpOyAgICAgICAgICAgICAgICAgICAgDQogIHZhciB2aXpFbGVtZW50ID0gZGl2RWxlbWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnb2JqZWN0JylbMF07ICAgICAgICAgICAgICAgICAgICB2aXpFbGVtZW50LnN0eWxlLm1pbldpZHRoPSc0MjBweCc7dml6RWxlbWVudC5zdHlsZS5tYXhXaWR0aD0nMTI1MHB4Jzt2aXpFbGVtZW50LnN0eWxlLndpZHRoPScxMDAlJzt2aXpFbGVtZW50LnN0eWxlLm1pbkhlaWdodD0nNTg3cHgnO3ZpekVsZW1lbnQuc3R5bGUubWF4SGVpZ2h0PScxMTg3cHgnO3ZpekVsZW1lbnQuc3R5bGUuaGVpZ2h0PShkaXZFbGVtZW50Lm9mZnNldFdpZHRoKjAuNzUpKydweCc7ICAgICAgICAgICAgICAgICAgICANCiAgdmFyIHNjcmlwdEVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsgICAgICAgICAgICAgICAgICAgIA0KICBzY3JpcHRFbGVtZW50LnNyYyA9ICdodHRwczovL3B1YmxpYy50YWJsZWF1LmNvbS9qYXZhc2NyaXB0cy9hcGkvdml6X3YxLmpzJzsgICAgICAgICAgICAgICAgICAgIHZpekVsZW1lbnQucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoc2NyaXB0RWxlbWVudCwgdml6RWxlbWVudCk7ICAgICAgICAgICAgICAgIA0KICA8L3NjcmlwdD4NCjwvdGQ+DQo8L3RyPg0KPC90YWJsZT4NCg0KXA0KDQojIyBBbm5vdGF0aW9ucyBhbmQgSW50ZXJuYWwgSW1hZ2VzDQoNCkFkZGluZyB0ZXh0IGFubm90YXRpb25zIHRvIGEgdGFibGVhdSBncmFwaGljIGlzIHN0cmFpZ2h0Zm9yd2FyZC4gDQoNCjEuIE1vdmUgeW91ciBjdXJzb3IgdG8gYW55IHNwb3Qgb2YgdGhlIFRhYmxlYXUgZ3JhcGhpYyAobm90IERhc2hib2FyZCkgYW5kIHJpZ2h0LWNsaWNrIHRvIHNlZSB0aGUgcG9wdXAgbWVudS4NCg0KMi4gU2VsZWN0IGBBbm5vdGF0aW9uYCBhbmQgdGhlbiBzZWxlY3QgZWl0aGVyIGBQb2ludGAgb3IgYEFyZWFgLg0KDQo0LiBXcml0ZSB0aGUgYW5ub3RhdGlvbiBpbiB0aGUgcG9wdXAgdGV4dCBlZGl0b3IgKHlvdSBhZGQgZGVjb3JhdGl2ZSBmZWF0dXJlcyB0byB0aGUgYW5ub3RhdGlvbikuDQoNCjUuIENsaWNrIGBPS2AgYW5kIHBsYWNlIGl0IG9uIGFuIGFwcHJvcHJpYXRlIHNwb3Qgb24gdGhlIGdyYXBoaWMuDQoNCg0KVG8gYWRkIGFuIGV4aXN0aW5nIFRhYmxlYXUgZ3JhcGhpYyB0byBUb29sdGlwLCB3ZSBjYW4gZm9sbG93IHRoZSBuZXh0IGZldyBzdGVwcy4NCg0KDQoxLiBDcmVhdGUgYSBzdGFuZGFsb25lIFRhYmxlYXUgZ3JhcGhpYyBndWlkZWQgYnkgdGhlIGJhc2ljIHByaW5jaXBsZXMgb2YgdmlzdWFsIGRlc2lnbi4NCg0KMi4gR28gdG8gdGhlIG1haW4gVGFibGVhdSBncmFwaGljLCBDbGljayB0aGUgYFRvb2x0aXBgIGljb24gaW4gdGhlIGBNYXJrc2AgcGFuZWwuDQoNCjMuIEluIHRoZSBwb3B1cCB3aW5kb3csIGNsaWNrIGBJbnNlcnRgLCBvbiB0aGUgdG9wIG9mIHRoZSBwb3B1cCBtZW51LCBwb2ludCB0byBgU2hlZXRzYCwgYW5kIHNlbGVjdCBhIHNoZWV0Lg0KDQo0LiBDbGljayBgT0tgIG9uIHRoZSBwb3AtdXAgd2luZG93LiAqKkRvbmUqKg0KDQoNClRoZSBmb2xsb3dpbmcgc2NhdHRlciBwbG90IGNvbnRhaW5zIGJvdGggYW5ub3RhdGlvbiBhbmQgdG9vbHRpcCBpbWFnZXMuIFlvdSBkb3duIHRoZSB3b3JrIGFuZCByZXByb2R1Y2UgdGhlIGdyYXBoaWMuDQoNClwNCg0KPHRhYmxlIGJvcmRlciA9IDAgYm9yZGVyY29sb3I9ImRhcmtncmVlbiIgYmdjb2xvcj0nI2Y2ZjZmNicgIHdpZHRoPTEwMCUgIGFsaWduID0gY2VudGVyPg0KPHRyPg0KPHRkPg0KDQo8ZGl2IGNsYXNzPSd0YWJsZWF1UGxhY2Vob2xkZXInIGlkPSd2aXoxNzExNzIzNzY3MDQyJyBzdHlsZT0ncG9zaXRpb246IHJlbGF0aXZlJz4NCjxub3NjcmlwdD48YSBocmVmPScjJz48aW1nIGFsdD0nUHJpY2UgcGVyIFBvdW5kIHYucy4gWWllbGQgcGVyIENvbG9ueSAnIHNyYz0naHR0cHM6JiM0NzsmIzQ3O3B1YmxpYy50YWJsZWF1LmNvbSYjNDc7c3RhdGljJiM0NztpbWFnZXMmIzQ3O3cwJiM0Nzt3MDlTY2F0dGVyVW5pdFByaWNlWWllbGQmIzQ3O1NjYXR0ZXJQbG90JiM0NzsxX3Jzcy5wbmcnIHN0eWxlPSdib3JkZXI6IG5vbmUnIC8+PC9hPg0KPC9ub3NjcmlwdD4NCg0KPG9iamVjdCBjbGFzcz0ndGFibGVhdVZpeicgIHN0eWxlPSdkaXNwbGF5Om5vbmU7Jz4NCjxwYXJhbSBuYW1lPSdob3N0X3VybCcgdmFsdWU9J2h0dHBzJTNBJTJGJTJGcHVibGljLnRhYmxlYXUuY29tJTJGJyAvPiANCjxwYXJhbSBuYW1lPSdlbWJlZF9jb2RlX3ZlcnNpb24nIHZhbHVlPSczJyAvPiA8cGFyYW0gbmFtZT0nc2l0ZV9yb290JyB2YWx1ZT0nJyAvPg0KPHBhcmFtIG5hbWU9J25hbWUnIHZhbHVlPSd3MDlTY2F0dGVyVW5pdFByaWNlWWllbGQmIzQ3O1NjYXR0ZXJQbG90JyAvPg0KPHBhcmFtIG5hbWU9J3RhYnMnIHZhbHVlPSdubycgLz48cGFyYW0gbmFtZT0ndG9vbGJhcicgdmFsdWU9J3llcycgLz4NCjxwYXJhbSBuYW1lPSdzdGF0aWNfaW1hZ2UnIHZhbHVlPSdodHRwczomIzQ3OyYjNDc7cHVibGljLnRhYmxlYXUuY29tJiM0NztzdGF0aWMmIzQ3O2ltYWdlcyYjNDc7dzAmIzQ3O3cwOVNjYXR0ZXJVbml0UHJpY2VZaWVsZCYjNDc7U2NhdHRlclBsb3QmIzQ3OzEucG5nJyAvPiANCjxwYXJhbSBuYW1lPSdhbmltYXRlX3RyYW5zaXRpb24nIHZhbHVlPSd5ZXMnIC8+DQo8cGFyYW0gbmFtZT0nZGlzcGxheV9zdGF0aWNfaW1hZ2UnIHZhbHVlPSd5ZXMnIC8+DQo8cGFyYW0gbmFtZT0nZGlzcGxheV9zcGlubmVyJyB2YWx1ZT0neWVzJyAvPg0KPHBhcmFtIG5hbWU9J2Rpc3BsYXlfb3ZlcmxheScgdmFsdWU9J3llcycgLz4NCjxwYXJhbSBuYW1lPSdkaXNwbGF5X2NvdW50JyB2YWx1ZT0neWVzJyAvPg0KPHBhcmFtIG5hbWU9J2xhbmd1YWdlJyB2YWx1ZT0nZW4tVVMnIC8+DQo8cGFyYW0gbmFtZT0nZmlsdGVyJyB2YWx1ZT0ncHVibGlzaD15ZXMnIC8+DQo8L29iamVjdD48L2Rpdj4gICAgICAgICAgICAgICAgDQoNCjxzY3JpcHQgdHlwZT0ndGV4dC9qYXZhc2NyaXB0Jz4gICAgICAgICAgICAgICAgICAgIA0KdmFyIGRpdkVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndml6MTcxMTcyMzc2NzA0MicpOyAgICAgICAgICAgICAgICAgICAgDQp2YXIgdml6RWxlbWVudCA9IGRpdkVsZW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ29iamVjdCcpWzBdOyAgICAgICAgICAgICAgICAgICAgdml6RWxlbWVudC5zdHlsZS53aWR0aD0nMTAwJSc7dml6RWxlbWVudC5zdHlsZS5oZWlnaHQ9KGRpdkVsZW1lbnQub2Zmc2V0V2lkdGgqMC43NSkrJ3B4JzsgICAgICAgICAgICAgICAgICAgIA0KdmFyIHNjcmlwdEVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsgICAgICAgICAgICAgICAgICAgIA0Kc2NyaXB0RWxlbWVudC5zcmMgPSAnaHR0cHM6Ly9wdWJsaWMudGFibGVhdS5jb20vamF2YXNjcmlwdHMvYXBpL3Zpel92MS5qcyc7ICAgICAgICAgICAgICAgICAgICB2aXpFbGVtZW50LnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHNjcmlwdEVsZW1lbnQsIHZpekVsZW1lbnQpOyAgICAgICAgICAgICAgICANCjwvc2NyaXB0Pg0KDQo8L3RkPg0KPC90cj4NCjwvdGFibGU+DQoNClwNCg0KDQoNCg0KDQoNClwNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K