1 Introduction

Among all specialized visualization software programs, Tableau is probably the most widely used and popular in the industry because it does not require much coding effort. It also provides users enough flexibility to design advanced visualizations by defining new variables based on existing variables.

Tableau visual objects are created with variables in the data table. Like other point-and-click statistical software programs such as MINITAB, it offers some basic functions one can use to define new fields in the data set to perform related visualization.

Tableau is primarily designed as a visualization tool. It also has limited capacity for data integration. This and the next notes focus only on visualization. Therefore, we assume that we have a single clean data ready

2 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.

2.1 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.

3 Basic Statistical Charts with Existing Variables

3.1 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).

3.2 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.

3.3 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.

3.4 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.

3.5 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)

3.6 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.

3.7 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

3.8 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.

3.9 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

3.10 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


4 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.

4.1 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.

4.2 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

  1. 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).

  2. 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.

  1. Create bin value so that the histograms of Tail and normalCurve will use the same bin width.

  1. 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.

  1. Create two histograms: Tail and normalCurve.

  1. Change the histogram of normalCurve to a density curve by changing the mark type from Bar to Line in the Marks panel

  1. Right-click the left-hand side and select Dual Axis to place the density curve on the histogram

  1. Right-click the right-hand side axis of the resulting overlay graph and uncheck Show Header to get the following.

  1. 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.

  1. 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.

4.3 Practice - Reproduce The Following

5 Images, Annotations and Tooltip Visuals

As we did in visualization with R, we can also animate Tableau graphics, insert annotations, images tooltip popups, etc. in Tableau graphics. Some of these graphical tasks are only one click away, and some of them require multi-step procedures.

We can create static images as new shapes, additional worksheets to place in the tooltip, etc. to make more interactive Tableau graphics.

The following Tableau graph contains several features. We can download the workbook through the bottom-right download icon.

5.1 Inserting External Images

Inserting external images (not generated by Tableau in the current session) into Tableau worksheets is not straightforward. One can create a separate image file to get this around. Depending on the purpose of using the images, one can also define new shapes with external images and plot them on Tableau graphics. In this section, we create a single-cell dashboard and then insert images through the dashboard following a few steps

  1. Create a tableau graphic in a standalone worksheet guided by the principles of visual design.

  2. Click the Dashboard tab (top panel tabs) to open a New dashboard and rename the default Dashboard 1 (bottom sheet tabs).

  3. Under the list of Sheets (left panel of the UI), drag the graphic to the right-hand dashboard box.

  4. Adjust the size using the drop-down menu under Size (left panel)

  5. Click Layout (next to Dashboard on the left panel - not the top tab menu) and check Floating.

  6. Resize the graphic to fit to the dashboard.

  7. Click Dashboard (next to Layout), go to Objects, and double-click Image on the list, following the directions to upload an image or provide a URL of an image.

  8. Find a spot to place the image and resize it.

The following is an example. You can download the workbook to practice and reproduce it using your own image.



5.2 Annotations and Internal Images

Adding text annotations to a tableau graphic is straightforward.

  1. Move your cursor to any spot of the Tableau graphic (not Dashboard) and right-click to see the popup menu.

  2. Select Annotation and then select either Point or Area.

  3. Write the annotation in the popup text editor (you add decorative features to the annotation).

  4. Click OK and place it on an appropriate spot on the graphic.

To add an existing Tableau graphic to Tooltip, we can follow the next few steps.

  1. Create a standalone Tableau graphic guided by the basic principles of visual design.

  2. Go to the main Tableau graphic, Click the Tooltip icon in the Marks panel.

  3. In the popup window, click Insert, on the top of the popup menu, point to Sheets, and select a sheet.

  4. Click OK on the pop-up window. Done

The following scatter plot contains both annotation and tooltip images. You down the work and reproduce the graphic.




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