1 The Introduction

The Colorado Plateau in Southern Utah is an annual destination for millions of tourists seeking a variety of backpacking, hiking, mountain biking, and caynoneering opportunities. To capitalize on these tourism dollars, the cities of Antimony, Koosharem, and Burrville plan to develop the “Grass Valley Trail”. This proposed ~65mi backpacking trail will connect the Otter Creek and Koosharem Resevoirs. They will use existing trails in the nearby Fish Lake National Forest and newly developed paths to create a trail that traverses Forshea Mountain, Langdon Mountain, Monroe Peak, Marysvale Peak, and Monument Peak. This area also has a small population of Puma concolor (mountain lion) that inhabit the nearby Sevier Plateau.

The Grass Valley Trail Committee has contracted with you to determine the likely impact of increased tourism on the mountain lion habitat and potential risk to visitors. So they have asked you to analyze the home range of two individual mountain lions that were fitted with GPS collars to track their movements. This information will be used to assess the viability of their proposal.

In this exercise you will:

  • Use a comma delimited file to create a new dataset
  • Create a minimum convex polygon for home range based on point data
  • Create a kernel density estimate of home range based on point data
  • Examine the difference in area between the two home range estimates
  • Determine the impact of the Grass Valley Trail on Puma concolor on the Sevier Plateau

Software specific directions can be found for each step below. Please submit the answer to the questions and your final map by the due date.

1.1 Step One: The Data

To begin this work you have obtained GPS collar data for local mountain lions from a wildlife biologist at the Utah Division of Wildlife Resources. The dataset contains relocation information (i.e. where the cougars have been located through collar transmission) for each tracked cougar. However, this data was provided as a CSV file. So you will need to import that data to create a new dataset.

View Directions in ArcGIS Pro

First you will need to download the following datasets from GitHub by clicking on the link and using right-click Save as… on the page to save the *.csv file to your project folder:

In order to calculate home range you need to have your data in a projected coordinate system. Since the data is in UTM format, you will need to change your project coordinate system to WGS 1984 UTM Zone 12N by right-clicking on your Map > Properties then going to the Coordinate Systems and changing the coordinate system to Projected Coordinate System > UTM > WGS 1984 > Northern Hemisphere > WGS 1984 UTM Zone 12N. The move over to the General options and change the Display Units to UTM. This will ensure that your map and data are all in the appropriate coordinate system.

Changing Coordinate System

Similar to previous exercises you can now import the dataset with the cougar relocations by going to Map Tab > Add Data -> XY Point Data. Make sure you set the coordinate system to the one list above or current map which you previously set.

Adding Cougar Dataset

You should now have the cougar dataset added to your Table of Contents. If you right-click on the dataset and click “Zoom to Layer” it will zoom into the full extent of that dataset. Because of the type of analysis in the next step you can keep the default basemap.

Question No. 1
How many individuals are being tracked in this dataset?

View directions in QGIS

First you will need to download the following datasets from GitHub by clicking on the link and using right-click Save as… or Crtl+click Save as.. on the page to save the *.csv file to your project folder:

In order to calculate home range you need to have your data in a projected coordinate system. So you will need to change your project CRS to EPSG: 32612 WGS 84/UTM zone 12N. Now add the comma delimited (or csv) file to your project by clicking on the Add Delimited Text Layer button in the left vertical menu or selecting it on the menu bar through Layer > Add Layer > Add Delimited Text Layer. In the resulting window, remember to click the button Browse File Path to browse to the location of the data. The layer name will automatically populate or you can change this by typing a new name in the Layer name field. Next, select CSV (comma separated values) in the File Format options. You should use the project CRS for the Geometry Definition and make sure the X Field and Y Field are set to the proper UTM columns. Finally at the bottom of the window click Add.

Data Source Manager|Delimited Text

Alternatively, you could follow the directions from Exercise 6, Step 1 using the MMQGIS plugin to load the file directly from the URL. Just be sure to set the latitude and longitude value fields for the UTM information.

Now you can close the Delimited Text window. The resulting dataset is added to your layers as a temporary file. It can still be used for analysis and display purposes, but if you close the project the layer may be removed. To make it a permanent dataset, select the temporary dataset in the layers area, and on the menu bar choose Layers > Save As… Alternatively you can right-click or Crtl+click on a Mac and choose Export > Save features as…

View of new dataset

Question No. 1
How many individuals are being tracked in this dataset?

View directions in R

Before you begin, you will need to open the Ex9 Colab Notebook and insert tocolab after github in the URL to open in the Colab Environment. As you have seen before, R requires various packages to complete certain analyses. In this exercise you will be using tidyverse, OpenStreetMaps, ggfortify, maptools, and rgeos. To install and load the packages we will use the following script:

Now that you have the packages required for the exercise you can read in the csv file and view the resulting dataset. Using the read.csv command and a URL to the data on GitHub you will import and examine the data.

cougars <- read.csv("https://raw.githubusercontent.com/chrismgentry/GIS1-Exercise-9/main/Data/cougars.csv")
head(cougars)

You can also plot the simple XY data to examine the spread of the dataset.

ggplot(cougars) + geom_point(aes(utm_east, utm_north)) + 
                  labs(x="Easting", y="Northing") +
                  guides(color=guide_legend("Identification")) +
                  theme_bw() + theme(legend.position = "top") +
                  theme(axis.text.y = element_text(angle=90, hjust=0.5)) +
                  theme(panel.grid.major = element_blank(),
                        panel.grid.minor = element_blank()) +
                  xlim(405000,425000)
Question No. 1
How many individuals are being tracked in this dataset?

1.2 Step Two: The Analyses

Now that you have the data you can calculate the two home range estimates: minimum convex polygon and kernel density estimation. The minimum convex polygon (MCP) draws the smallest polygon encompassing all the points, while the kernel density estimation (KDE) calculates a magnitude-per-unit area from the point features using a function to fit a smoothly tapered surface. For this exercise you will run both analyses and compare the results.

View Directions in ArcGIS Pro

In the previous step you loaded the relocations and added the layer to your view. Now you will use several tools from the Toolbox Toolbox to complete the analyses including:

  • Minimum Bounding Geometry (minimum convex polygon)
  • Kernel Density Estimation
  • Calculate Geometry
  • Reclassify
  • Raster to Polygon

To create the minimum convex polygon you will use the Minimum Bounding Geometry tool that can be found by using the name as a search term in Toolbox from the Analysis Tab. You will use the cougar dataset for the Input Features, navigate to your project folder and give the *.shp file a name in the Output Feature Class options, and select convex hull for the Geometry Type. For Group Option select All. Leave the box for geometry characteristics unchecked.

Creating the Minimum Bounding Geometry

You should now have a bounding geometry polygon in your layers you can style as necessary to display the information. Notice how the polygon is drawn and encompasses the data points. To create the kernel density estimation search for it in the toolbox or alternatively it can be found in the quickly link for tools on the Analysis Tab. Use the following setting for the Kernel Density analysis:

  • Input point of polyline features = cougars dataset
  • Population field = NONE
  • Output raster = navigate to your project folder and give the file a name followed by .tif
  • Output cell size = 100
  • Search radius = 2000
  • Area units = Square meters
  • Output cell values = Densities
  • Method = Planar
  • Input barrier featues = Leave this blank

Creating the Kernel Density Estimation

Before moving on with any additional analysis, you will reclassify the KDE output to four (4) classes. To do this search for Reclassify in the geoprocessing tools. In parentheses behind the tools name you will see the name of the package it is being selected from. You want to choose the Reclassify tool from the Spatial Analyst Tools package. In the Reclassify pane select the kernel density file you just created as the Input Raster and click Classify. In the Window select 4 classes and click OK. Finally, in the Output raster option navigate to your project folder and be sure to save the file as a .tif then click Run.

Classifying the KDE to 4 classes

Next, in order to calculate the area of the new classified KDE you will need to conver it to a polygon feature class. In Tools you can search for “Raster to Polygon” and add the new reclassifed KDE as the Input Raster, select “Value” for the Field parameter, and use the browse button to navigate to your project folder and give the new file a .shp file name in the Output Polygon Features parameter. Be sure to click the Simply polygons and Create multipart features boxes and click Run.

Creating Polygons from Raster

This will create a series of overlapping polygons representing each of the four classes.

  • Class 1 = Low levels of relocations
  • Class 2 = Moderate levels of relocations
  • Class 3 = High levels of relocations
  • Class 4 = Very high level of relocations

However, because they are overlapping polygons, Class 1 makes up the entire surface area including those in the higher categories that are overlapping the data (e.g. Class 4 locations will overlap Class 1, so the “area” of Class 1 makes up the entire surface area). Since the development of the KDE ranges from the extent of the point values, some areas without relocations were calculated in the development of the polygons. So before continuing use the Clip geoprocessing tool to clip the KDE based on the MCP.

With the new clipped KDE polygons created you need to add a new field to calculate the area. Open the attribute table and click the Add Field button Toolbox and provide a Field Name of Area to the new variable. Click Float as the Data Type and Numeric as the Number Format. You can now close the fields tab and save the edits. On the new variable in the attribute table right-click on Area and click Calculate Geometry. On the new pane select the clipped KDE-polygon layer as the Input Features, choose Area as the Target Field and Area as the Property. For Area Units select square meters and be sure that the Coordinate system matches the CRS of your project and click OK. Re peat this process for the MCP polygon you created earlier.

Calculate Geometry Field

Question No. 2
What is the area of the Minimum Convex Polygon?
What is the area of the Kernel Density Estimation?

View Directions in QGIS

In the previous step you loaded the relocations and added the layer to your view. Now you will use several tools from the Processing Toolbox  Processing Toolbox to complete the analyses including:

  • Minimum bounding geometry
  • Add geometry attributes
  • Heat map (Kernel Density Estimation)
  • Raster calculator
  • Polygonize (raster to vector)

To create the minimum convex polygon you will use the Minimum bounding geometry tool that can be found in the Processing Toolbox under Vector geometry. Alternatively you can search for it in the toolbox search bar. You will use the cougar dataset for the Input layer, and Convex hull for the Geometry type. All other options you can leave as the default. Remember this will create a temporary layer which you can choose to make permanent or rename in your layers for clarity.

Minimum bounding geometry options

You should now have a Bounding geometry polygon in your layers you can style as necessary to display the information. By viewing the attribute table you can see the area (in square meters) of the polygon.

Creating the KDE estimate will take a few more steps before you can obtain the statistical information for comparison. Because the kernel density estimation creates a raster dataset, you will classify the data using the raster calculator and convert the classified values to a vector with polygonize before examining the statistics.

To begin this analysis you need to open the Heatmap (Kernel Density Estimation) tool from Interpolation in the Processing Toolbox. In the input layer you will use the cougar dataset, set a Radius of 2000, a pixel size of 100, and set the Kernel shape to Epanechnikov.

Heatmap (KDE) options

Now click Run. This will create a KDE and add it to your layers. You can style the heatmap using symbology under the properties menu for the data. IN order to get more information out of this analysis you need to reclassify the raster into the following categories:

  • Level 1 = 0 to 60, low levels of relocations
  • Level 2 = 61 to 120, moderate levels of relocations
  • Level 3 = 121 to 180, high levels of relocations
  • Level 4 = Greater than 180, very high level of relocations

To do this you will use the Raster Calculator located under Raster on the Menu Bar or under Raster analysis in the Processing Toolbox. In the Layers section you should see the available raster layers in your current project. In the Expression box you will paste the following SQL expression:

("Heatmap@1" <= 60) * 1 + 
(("Heatmap@1" > 60)  AND  ("Heatmap@1" <= 120)) * 2 + 
(("Heatmap@1" > 120)  AND  ("Heatmap@1" <= 180)) * 3 + 
("Heatmap@1" > 180) * 4

Where “Heatmap@1” is the name of the KDE output from the previous step. This will convert all of the values to a range of 1-4 indicating the level of relocations. In the section for Reference layer(s) (used for automated extent, cellsize, and CRS)[optional] you should click the browse file path button Browse File Path to add the Heatmap (or the name of your KDE file). Make the Cell size to 100, using the dropdown menu next to the Output extent [optional] select Calculate from Layer and choose your Heatmap. For the Output CRS [optional] select the project CRS and then click Run.

Raster calculator options

This will add the reclassified heatmap to you layers. Now you can use Polygonize (raster to vector) found under Raster > Conversion on the menur bar or GDAL > Raster conversion in the Processing Toolbox. In the Polygonize (Raster to Vector) window choose your reclassified KDE created in the previous step as the Input layer and click Run. This will add another layer (usually called “Vectorized” if set as a temporary file) that turned the raster data to vector polygons. Finally, we need to use the Add geometry attributes found under Vector > Geometry Tools on the menu bar or Vector geometry in the Processing Toolbox. This will add columns for Area and Perimeter to the attribute table for the vectorized dataset. You will need to add the vectorized layer as the Input layer, Layer CRS for the Calculate using field and click Run.

Add geometry attributes

Finally, if you click the Show Statistical Summary button Show statistical summary on the primary horizontal menu, a new Statistics panel will be added to your layout. By selecting the Added geometry info layer (or the name of the file from the previous step) and choosing area you can see a summary of the statistical information. The total area in the KDE Estimation will be found in the Sum statistic.

Question No. 2
What is the area of the Minimum Convex Polygon?
What is the area of the Kernel Density Estimation?

View Directions in R

For this exercise you will use the adehabitat package to calculate both the MCP and KDE polygons. Because this package uses specialized functions you need to convert your XY data to a class of data called SpatialPoints. Once the spatial data is created you can run both the MCP and KDE analyses for the dataset you obtained above.

Because the analyses need to be calculated using metric values, you will use the utm-east and utm-north columns in the dataset to create a set of coordinates with a SpatialPoints class that will be used in the calculation of the polygons.

With this new XY dataset you can now create the MCP and KDE estimates for the cougar relocations. You will start with the MCP polygon. Using the mcp function in the adehabitat package, you will create the estimated MCP home range. Then you will need to convert the resulting SpatialPolygonsDataFrame to a format that can be plotted using ggpolt2. Currently you will use the fortify function, however as functions are deprecated over time, tidy as part of the broom package can also be used for this process.

In the script above you can see the area of the minimum convex polygon is being measured in hectares. To determine the area of the MCP you can type mcp.out$area to print the measurement.

While the MCP creates a single bounding polygon, kernel density estimates often are used to create multiple polygons that can be used similar to a hotpsot analysis. This requires a few additional steps as compared to the MCP example above. Before converting the SpatialPolygonsDataframe you will need to create multiple estimates from the dataset by varying the percentage level for the home range estimation. Essentially, higher percentage levels will encompass areas with very few relocations and lower percentage levels will encompass areas with a dense number of relocations. For this analysis you will create estimates based on:

  • 100% level = includes low to very high levels of relocations
  • 75% level = includes moderate to very high levels of relocations
  • 50% level = includes high to very high levels of relocations
  • 25% level = includes only very high level of relocations

Once these estimates are created you will need to fortify each of the polygons so they can be displayed with ggplot2.

In these KDE scripts you can print the area (hectares) of any polygon by typing kde##$area, where ## is the kde value from the scripts above. Viewing the area of kde100 will allow you to view the entire area estimated by the analysis since it includes all levels of relocation.

Question No. 2
What is the area of the Minimum Convex Polygon?
What is the area of the Kernel Density Estimation?

1.3 Step Three: The Visualization

In order to view our data in situ we need to add a basemap to our view. Think about all of the possible basemaps you can add such as topo or terrain maps, or even satellite imagery.

View directions in ArcGIS Pro

It will be important to select an appropriate basemap for your visualization. Look through the options available in the Basemap drop-down menu on the Map Tab and determine which will provide the best visualization of the data you are interested in displaying.

Basemap Options

Question No. 3
What steps would you take to add and differentiate between the individual cougars in a visualization?

View directions in QGIS

In a previous exercise you added XYZ tiles to your QGIS Browser. Remember to add new tiles such as ESRI Satellite Imagery to your broswer you need to Right-Click (CRTL+click on Mac) on XYZ Tiles and click “New Connection” and add the following URL:

https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}

In Exercise 6, Step 1 you were provided with directions to create connections for satellite imagery, street maps, and topographic maps. Remember to arrange your layers so that you can visualize all of the data you are interested in examining.

QGIS Output

Question No. 3
What steps would you take to add and differentiate between the individual cougars in a visualization?

View directions in R

To obtain imagery for this project you are again going to use OpenStreetMap to connect to Bing Aerial Imagery. Although you used the UTM values for the analysis, OpenStreetMap only uses geographic coordinates for their imagery. So you will obtain the image first and then reproject it to the appropriate UTM zone.

In the following script you will be using the minimum and maximum values from cougars longitude and latitude columns to set the bounding coordinates. To avoid any point being located on the edge of the image we are going to add a 0.05 degree buffer to each value.

Now you will convert the imagery projection from geographic coordinates to UTM Zone 12.

With this imagery now you can plot the MCP and KDE polygons as well as the data points if necessary.

autoplot.OpenStreetMap(imagery_utm, expand = TRUE) + 
theme_bw() + theme(legend.position = "bottom") +
geom_polygon(data = kde.poly100, aes(x=long, y=lat, group=group), color = NA, fill = 'lightyellow') +
geom_polygon(data = kde.poly75, aes(x=long, y=lat, group=group), color = NA, fill = 'gold') +
geom_polygon(data = kde.poly50, aes(x=long, y=lat, group=group), color = NA, fill = 'darkorange') +
geom_polygon(data = kde.poly25, aes(x=long, y=lat, group=group), color = NA, fill = 'darkred') +
geom_polygon(data = mcp.poly, aes(x=long, y=lat), color = "red", fill = NA, alpha = 0.8, size = 1) +
geom_point(data = cougars, aes(x=utm_east, y=utm_north), alpha = 0.1) +
labs(x="Easting", y="Northing") + guides(color=guide_legend("Identifier")) +
theme(legend.position="bottom") +
theme(axis.text.y = element_text(angle=90, hjust=0.5))
Question No. 3
What steps would you take to differentiate between the individual cougars in this visualization?

1.4 Step Four: The Trail

Now that you have all of the data necessary to determine the feasibility of the “Grass Valley Trail”, you need to add the proposed trail to assess the impact it may have on the cougar population.

View directions in ArcGIS Pro

In the first step you should have downloaded the hiking_trails dataset from GitHub. If you skipped that step you will need to download the dataset now. Similar to Step 1 on the Map Tab go to Add Data -> XY Point Data. Be sure the coordinate system is set appropriate for the data. In Tools search for Points to Line and select the downloaded CSV file as the Input Features, navigate to your project folder and save the .shp file in the Output Feature Class. Leave the Line Field blank and set the Sort Field to node and click Run.

Points to Line

Now you should have a line representing the proposed Grass Valley Trail that you can style appropriately to help examine all of the data.

Question No. 4
Does the trail cross any areas calculated as high or very high use based on the KDE analysis?

View directions in QGIS

In the first step you should have downloaded the hiking_trails dataset from GitHub. If you skipped that step you will need to download the dataset now. Similarly to step one, the data is formatted as a .csv file so you will need to use Add Delimited Text Layer Add Delimited Text Layer to import the dataset. Once added to your layers you can use the points to path tool located in Vector creation in the Processing Toolbox. In the Input point layer parameter choose the hiking_trail dataset and in Order field choose node. You can leave the remainder of the options as default and click Run.

QGIS Output

Now you should have a line representing the proposed Grass Valley Trail that you can style appropriately to help examine all of the data.

Question No. 4
Does the trail cross any areas calculated as high or very high use based on the KDE analysis?

View directions in R

Similarly to step one, you are going to use read.csv and a URL from GitHub to import the data for the proposed “Grass Valley Trail”.

In the previous step you created a visualization that allowed you to overlay the MCP and KDE polygons on aerial imagery as well as the relocations. To convert the “Grass Valley Trail” import from above, which is point data, to a line, you need to add the following script to visualization from above:

geom_path(data = trail, aes(x = x ,y = y), size = 1, linetype = 1)

Remember, ggplot2 draws each layer over the previous. So if you want the proposed trail to be the top layer, it should be the last one drawn.

Question No. 4
Does the trail cross any areas calculated as high or very high use based on the KDE analysis?

2 The Decision

Recall that Grass Valley Trail Committee has asked you to assess the impact of the proposed hiking trail on the mountain lion habitat and potential risk to visitors. Based on the analyses above, complete a lab write-up that addresses the following questions:

  • Explain to the committee the process you used to determine the risks of the proposed trail.
  • Describe the difference between the two types of home range analyses. How would this potentially impact the decisions made by the committee?
  • What portion of the proposed trail has the highest likelihood to traverse areas of the Sevier Plateau that are frequently (high to very high categories) used by the tracked cougars?

Finally, provide a recommendation for the committee on how the proposed trail can be completed with as little interaction as possible with the cougar habitat. Include your map that helps provide additional details for your recommendation.

LS0tDQp0aXRsZTogIkV4ZXJjaXNlIDk6IEludGVycG9sYXRlZCBTdXJmYWNlcyBhbmQ8YnI+IEhvbWUgUmFuZ2UgQW5hbHlzaXMgPGJyPjxzbWFsbD5HZW9ncmFwaGljIEluZm9ybWF0aW9uIFN5c3RlbXMgMSBMYWI8L3NtYWxsPjwvYnI+Ig0KYXV0aG9yOiAiR0VPRyAzMTUwIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHJvd3MucHJpbnQ6IDEwDQogICAgdGhlbWU6IGNvc21vDQogICAgaGlnaGxpZ2h0OiBicmVlemVkYXJrDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCiAgICAgIHNtb290aF9zY3JvbGw6IHllcw0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCiAgbW9kZTogZ2ZtDQotLS0NCg0KYGBgez1odG1sfQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDQwcHg7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAyMHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmJvZHkgew0KICBmb250LWZhbWlseTogSGVsdmV0aWNhOw0KICBmb250LXNpemU6IDEycHQ7DQp9DQoNCi56b29tIHsNCiAgdHJhbnNmb3JtLW9yaWdpbjogNDAlIDUwJSAwOw0KICB0cmFuc2l0aW9uOiB0cmFuc2Zvcm0gLjJzOw0KICBtYXJnaW46IDAgYXV0bzsNCn0NCi56b29tIGltZ3sNCgl3aWR0aDphdXRvOw0KCWhlaWdodDphdXRvOwkNCn0NCi56b29tOmhvdmVyIHsNCiAgdHJhbnNmb3JtOiBzY2FsZSgyKTsNCn0NCg0KdGgsIHRkIHtwYWRkaW5nOiA1cHg7fQ0KDQo8L3N0eWxlPg0KYGBgDQo8aHI+PC9ocj4NCg0KIyBUaGUgSW50cm9kdWN0aW9uDQoNClRoZSBDb2xvcmFkbyBQbGF0ZWF1IGluIFNvdXRoZXJuIFV0YWggaXMgYW4gYW5udWFsIGRlc3RpbmF0aW9uIGZvciBtaWxsaW9ucyBvZiB0b3VyaXN0cyBzZWVraW5nIGEgdmFyaWV0eSBvZiBiYWNrcGFja2luZywgaGlraW5nLCBtb3VudGFpbiBiaWtpbmcsIGFuZCBjYXlub25lZXJpbmcgb3Bwb3J0dW5pdGllcy4gVG8gY2FwaXRhbGl6ZSBvbiB0aGVzZSB0b3VyaXNtIGRvbGxhcnMsIHRoZSBjaXRpZXMgb2YgQW50aW1vbnksIEtvb3NoYXJlbSwgYW5kIEJ1cnJ2aWxsZSBwbGFuIHRvIGRldmVsb3AgdGhlICoqIkdyYXNzIFZhbGxleSBUcmFpbCIqKi4gVGhpcyBwcm9wb3NlZCB+NjVtaSBiYWNrcGFja2luZyB0cmFpbCB3aWxsIGNvbm5lY3QgdGhlIE90dGVyIENyZWVrIGFuZCBLb29zaGFyZW0gUmVzZXZvaXJzLiBUaGV5IHdpbGwgdXNlIGV4aXN0aW5nIHRyYWlscyBpbiB0aGUgbmVhcmJ5IEZpc2ggTGFrZSBOYXRpb25hbCBGb3Jlc3QgYW5kIG5ld2x5IGRldmVsb3BlZCBwYXRocyB0byBjcmVhdGUgYSB0cmFpbCB0aGF0IHRyYXZlcnNlcyBGb3JzaGVhIE1vdW50YWluLCBMYW5nZG9uIE1vdW50YWluLCBNb25yb2UgUGVhaywgTWFyeXN2YWxlIFBlYWssIGFuZCBNb251bWVudCBQZWFrLiBUaGlzIGFyZWEgYWxzbyBoYXMgYSBzbWFsbCBwb3B1bGF0aW9uIG9mIF9QdW1hIGNvbmNvbG9yXyAobW91bnRhaW4gbGlvbikgdGhhdCBpbmhhYml0IHRoZSBuZWFyYnkgU2V2aWVyIFBsYXRlYXUuDQoNClRoZSBfR3Jhc3MgVmFsbGV5IFRyYWlsIENvbW1pdHRlZV8gaGFzIGNvbnRyYWN0ZWQgd2l0aCB5b3UgdG8gZGV0ZXJtaW5lIHRoZSBsaWtlbHkgaW1wYWN0IG9mIGluY3JlYXNlZCB0b3VyaXNtIG9uIHRoZSBtb3VudGFpbiBsaW9uIGhhYml0YXQgYW5kIHBvdGVudGlhbCByaXNrIHRvIHZpc2l0b3JzLiBTbyB0aGV5IGhhdmUgYXNrZWQgeW91IHRvIGFuYWx5emUgdGhlIGhvbWUgcmFuZ2Ugb2YgdHdvIGluZGl2aWR1YWwgbW91bnRhaW4gbGlvbnMgdGhhdCB3ZXJlIGZpdHRlZCB3aXRoIEdQUyBjb2xsYXJzIHRvIHRyYWNrIHRoZWlyIG1vdmVtZW50cy4gVGhpcyBpbmZvcm1hdGlvbiB3aWxsIGJlIHVzZWQgdG8gYXNzZXNzIHRoZSB2aWFiaWxpdHkgb2YgdGhlaXIgcHJvcG9zYWwuDQoNCkluIHRoaXMgZXhlcmNpc2UgeW91IHdpbGw6DQoNCi0gICBVc2UgYSBjb21tYSBkZWxpbWl0ZWQgZmlsZSB0byBjcmVhdGUgYSBuZXcgZGF0YXNldA0KLSAgIENyZWF0ZSBhIG1pbmltdW0gY29udmV4IHBvbHlnb24gZm9yIGhvbWUgcmFuZ2UgYmFzZWQgb24gcG9pbnQgZGF0YQ0KLSAgIENyZWF0ZSBhIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlIG9mIGhvbWUgcmFuZ2UgYmFzZWQgb24gcG9pbnQgZGF0YQ0KLSAgIEV4YW1pbmUgdGhlIGRpZmZlcmVuY2UgaW4gYXJlYSBiZXR3ZWVuIHRoZSB0d28gaG9tZSByYW5nZSBlc3RpbWF0ZXMNCi0gICBEZXRlcm1pbmUgdGhlIGltcGFjdCBvZiB0aGUgKipHcmFzcyBWYWxsZXkgVHJhaWwqKiBvbiBfUHVtYSBjb25jb2xvcl8gb24gdGhlIFNldmllciBQbGF0ZWF1DQoNClNvZnR3YXJlIHNwZWNpZmljIGRpcmVjdGlvbnMgY2FuIGJlIGZvdW5kIGZvciBlYWNoIHN0ZXAgYmVsb3cuIFBsZWFzZSBzdWJtaXQgdGhlIGFuc3dlciB0byB0aGUgcXVlc3Rpb25zIGFuZCB5b3VyIGZpbmFsIG1hcCBieSB0aGUgZHVlIGRhdGUuDQoNCiMjIFN0ZXAgT25lOiBUaGUgRGF0YQ0KDQpUbyBiZWdpbiB0aGlzIHdvcmsgeW91IGhhdmUgb2J0YWluZWQgR1BTIGNvbGxhciBkYXRhIGZvciBsb2NhbCBtb3VudGFpbiBsaW9ucyBmcm9tIGEgd2lsZGxpZmUgYmlvbG9naXN0IGF0IHRoZSBVdGFoIERpdmlzaW9uIG9mIFdpbGRsaWZlIFJlc291cmNlcy4gVGhlIGRhdGFzZXQgY29udGFpbnMgcmVsb2NhdGlvbiBpbmZvcm1hdGlvbiAoaS5lLiB3aGVyZSB0aGUgY291Z2FycyBoYXZlIGJlZW4gbG9jYXRlZCB0aHJvdWdoIGNvbGxhciB0cmFuc21pc3Npb24pIGZvciBlYWNoIHRyYWNrZWQgY291Z2FyLiBIb3dldmVyLCB0aGlzIGRhdGEgd2FzIHByb3ZpZGVkIGFzIGEgQ1NWIGZpbGUuIFNvIHlvdSB3aWxsIG5lZWQgdG8gaW1wb3J0IHRoYXQgZGF0YSB0byBjcmVhdGUgYSBuZXcgZGF0YXNldC4NCg0KPGRldGFpbHM+DQo8c3VtbWFyeT48YmlnPlZpZXcgRGlyZWN0aW9ucyBpbiA8Yj4gW0FyY0dJUyBQcm9de3N0eWxlPSJjb2xvcjojZmY0NTAwIn0gPC9iPjwvYmlnPjwvc3VtbWFyeT4NCg0KRmlyc3QgeW91IHdpbGwgbmVlZCB0byBkb3dubG9hZCB0aGUgZm9sbG93aW5nIGRhdGFzZXRzIGZyb20gR2l0SHViIGJ5IGNsaWNraW5nIG9uIHRoZSBsaW5rIGFuZCAgdXNpbmcgcmlnaHQtY2xpY2sgX1NhdmUgYXMuLi5fIG9uIHRoZSBwYWdlIHRvIHNhdmUgdGhlIFwqLmNzdiBmaWxlIHRvIHlvdXIgcHJvamVjdCBmb2xkZXI6IA0KDQotIDxhIGhyZWY9Imh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9jaHJpc21nZW50cnkvR0lTMS1FeGVyY2lzZS05L21haW4vRGF0YS9jb3VnYXJzLmNzdiIgdGFyZ2V0PSJfYmxhbmsiPkNvdWdhciBSZWxvY2F0aW9uczwvYT4NCi0gPGEgaHJlZj0iaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2NocmlzbWdlbnRyeS9HSVMxLUV4ZXJjaXNlLTkvbWFpbi9EYXRhL2hpa2luZ190cmFpbC5jc3YiIHRhcmdldD0iX2JsYW5rIj5IaWtpbmcgVHJhaWwgTm9kZXM8L2E+DQoNCkluIG9yZGVyIHRvIGNhbGN1bGF0ZSBob21lIHJhbmdlIHlvdSBuZWVkIHRvIGhhdmUgeW91ciBkYXRhIGluIGEgcHJvamVjdGVkIGNvb3JkaW5hdGUgc3lzdGVtLiBTaW5jZSB0aGUgZGF0YSBpcyBpbiBVVE0gZm9ybWF0LCB5b3Ugd2lsbCBuZWVkIHRvIGNoYW5nZSB5b3VyIHByb2plY3QgY29vcmRpbmF0ZSBzeXN0ZW0gdG8gKipXR1MgMTk4NCBVVE0gWm9uZSAxMk4qKiBieSByaWdodC1jbGlja2luZyBvbiB5b3VyIF9NYXAgPiBQcm9wZXJ0aWVzXyB0aGVuIGdvaW5nIHRvIHRoZSBfQ29vcmRpbmF0ZSBTeXN0ZW1zXyBhbmQgY2hhbmdpbmcgdGhlIGNvb3JkaW5hdGUgc3lzdGVtIHRvIFByb2plY3RlZCBDb29yZGluYXRlIFN5c3RlbSA+IFVUTSA+IFdHUyAxOTg0ID4gTm9ydGhlcm4gSGVtaXNwaGVyZSA+IFdHUyAxOTg0IFVUTSBab25lIDEyTi4gVGhlIG1vdmUgb3ZlciB0byB0aGUgR2VuZXJhbCBvcHRpb25zIGFuZCBjaGFuZ2UgdGhlIF9EaXNwbGF5IFVuaXRzXyB0byBVVE0uIFRoaXMgd2lsbCBlbnN1cmUgdGhhdCB5b3VyIG1hcCBhbmQgZGF0YSBhcmUgYWxsIGluIHRoZSBhcHByb3ByaWF0ZSBjb29yZGluYXRlIHN5c3RlbS4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLW1hcC1wcm9wZXJ0aWVzLnBuZyIgYWx0PSJDaGFuZ2luZyBDb29yZGluYXRlIFN5c3RlbSIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KU2ltaWxhciB0byBbcHJldmlvdXMgZXhlcmNpc2VzXShodHRwczovL2NocmlzbWdlbnRyeS5naXRodWIuaW8vR0lTMS1FeGVyY2lzZS02LyMxMV9TdGVwX09uZTpfVGhlX0RhdGEpIHlvdSBjYW4gbm93IGltcG9ydCB0aGUgZGF0YXNldCB3aXRoIHRoZSBjb3VnYXIgcmVsb2NhdGlvbnMgYnkgZ29pbmcgdG8gX01hcCBUYWIgPiBBZGQgRGF0YSAtPiBYWSBQb2ludCBEYXRhXy4gTWFrZSBzdXJlIHlvdSBzZXQgdGhlIGNvb3JkaW5hdGUgc3lzdGVtIHRvIHRoZSBvbmUgbGlzdCBhYm92ZSBvciBfY3VycmVudCBtYXBfIHdoaWNoIHlvdSBwcmV2aW91c2x5IHNldC4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLXh5LWRhdGEucG5nIiBhbHQ9IkFkZGluZyBDb3VnYXIgRGF0YXNldCIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KWW91IHNob3VsZCBub3cgaGF2ZSB0aGUgY291Z2FyIGRhdGFzZXQgYWRkZWQgdG8geW91ciBUYWJsZSBvZiBDb250ZW50cy4gSWYgeW91IHJpZ2h0LWNsaWNrIG9uIHRoZSBkYXRhc2V0IGFuZCBjbGljayAiWm9vbSB0byBMYXllciIgaXQgd2lsbCB6b29tIGludG8gdGhlIGZ1bGwgZXh0ZW50IG9mIHRoYXQgZGF0YXNldC4gQmVjYXVzZSBvZiB0aGUgdHlwZSBvZiBhbmFseXNpcyBpbiB0aGUgbmV4dCBzdGVwIHlvdSBjYW4ga2VlcCB0aGUgZGVmYXVsdCBiYXNlbWFwLg0KDQoqKlF1ZXN0aW9uIE5vLiAxKioNCjxibG9ja3F1b3RlPg0KSG93IG1hbnkgaW5kaXZpZHVhbHMgYXJlIGJlaW5nIHRyYWNrZWQgaW4gdGhpcyBkYXRhc2V0Pw0KPC9ibG9ja3F1b3RlPg0KDQo8L2RldGFpbHM+DQoNCjxocj48L2hyPg0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxiaWc+VmlldyBkaXJlY3Rpb25zIGluIDxiPiBbUUdJU117c3R5bGU9ImNvbG9yOiAjMDA2NDAwIn0gPC9iPjwvYmlnPjwvc3VtbWFyeT4NCg0KRmlyc3QgeW91IHdpbGwgbmVlZCB0byBkb3dubG9hZCB0aGUgZm9sbG93aW5nIGRhdGFzZXRzIGZyb20gR2l0SHViIGJ5IGNsaWNraW5nIG9uIHRoZSBsaW5rIGFuZCB1c2luZyByaWdodC1jbGljayBfU2F2ZSBhcy4uLl8gb3IgQ3J0bCtjbGljayBfU2F2ZSBhcy4uXyBvbiB0aGUgcGFnZSB0byBzYXZlIHRoZSBcKi5jc3YgZmlsZSB0byB5b3VyIHByb2plY3QgZm9sZGVyOiANCg0KLSA8YSBocmVmPSJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vY2hyaXNtZ2VudHJ5L0dJUzEtRXhlcmNpc2UtOS9tYWluL0RhdGEvY291Z2Fycy5jc3YiIHRhcmdldD0iX2JsYW5rIj5Db3VnYXIgUmVsb2NhdGlvbnM8L2E+DQotIDxhIGhyZWY9Imh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9jaHJpc21nZW50cnkvR0lTMS1FeGVyY2lzZS05L21haW4vRGF0YS9oaWtpbmdfdHJhaWwuY3N2IiB0YXJnZXQ9Il9ibGFuayI+SGlraW5nIFRyYWlsIE5vZGVzPC9hPg0KDQpJbiBvcmRlciB0byBjYWxjdWxhdGUgaG9tZSByYW5nZSB5b3UgbmVlZCB0byBoYXZlIHlvdXIgZGF0YSBpbiBhIHByb2plY3RlZCBjb29yZGluYXRlIHN5c3RlbS4gU28geW91IHdpbGwgbmVlZCB0byBjaGFuZ2UgeW91ciBwcm9qZWN0IENSUyB0byBgYGBFUFNHOiAzMjYxMiBXR1MgODQvVVRNIHpvbmUgMTJOYGBgLiBOb3cgYWRkIHRoZSBfY29tbWEgZGVsaW1pdGVkXyAob3IgY3N2KSBmaWxlIHRvICB5b3VyIHByb2plY3QgYnkgY2xpY2tpbmcgb24gdGhlIDxpbWcgc3JjPSAiSW1hZ2VzL2Nzdl9pbWFnZS5wbmciIGFsdD0iQWRkIERlbGltaXRlZCBUZXh0IExheWVyIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiPiBidXR0b24gaW4gdGhlIGxlZnQgdmVydGljYWwgbWVudSBvciBzZWxlY3RpbmcgaXQgb24gdGhlIG1lbnUgYmFyIHRocm91Z2ggX0xheWVyID4gQWRkIExheWVyID4gQWRkIERlbGltaXRlZCBUZXh0IExheWVyXy4gSW4gdGhlIHJlc3VsdGluZyB3aW5kb3csIHJlbWVtYmVyIHRvIGNsaWNrIHRoZSBidXR0b24gPGltZyBzcmM9ICJJbWFnZXMvZmlsZV9wYXRoLnBuZyIgYWx0PSJCcm93c2UgRmlsZSBQYXRoIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiPiB0byBicm93c2UgdG8gdGhlIGxvY2F0aW9uIG9mIHRoZSBkYXRhLiBUaGUgX2xheWVyIG5hbWVfIHdpbGwgYXV0b21hdGljYWxseSBwb3B1bGF0ZSBvciB5b3UgY2FuIGNoYW5nZSB0aGlzIGJ5IHR5cGluZyBhIG5ldyBuYW1lIGluIHRoZSBfTGF5ZXIgbmFtZV8gZmllbGQuIE5leHQsIHNlbGVjdCAqKkNTViAoY29tbWEgc2VwYXJhdGVkIHZhbHVlcykqKiBpbiB0aGUgX0ZpbGUgRm9ybWF0XyBvcHRpb25zLiBZb3Ugc2hvdWxkIHVzZSB0aGUgcHJvamVjdCBDUlMgZm9yIHRoZSBfR2VvbWV0cnkgRGVmaW5pdGlvbl8gYW5kIG1ha2Ugc3VyZSB0aGUgX1ggRmllbGRfIGFuZCBfWSBGaWVsZF8gYXJlIHNldCB0byB0aGUgPHU+cHJvcGVyIFVUTSBjb2x1bW5zPC91Pi4gRmluYWxseSBhdCB0aGUgYm90dG9tIG9mIHRoZSB3aW5kb3cgY2xpY2sgKipBZGQqKi4gDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxpbWcgc3JjPSAiSW1hZ2VzL2RlbGltaXRlZF90ZXh0LnBuZyIgYWx0PSJEYXRhIFNvdXJjZSBNYW5hZ2VyfERlbGltaXRlZCBUZXh0IiB3aWR0aD0iNDQwIiBoZWlnaHQ9IjUyMCI+PC9wPg0KDQpBbHRlcm5hdGl2ZWx5LCB5b3UgY291bGQgZm9sbG93IHRoZSBkaXJlY3Rpb25zIGZyb20gW0V4ZXJjaXNlIDYsIFN0ZXAgMV0oaHR0cHM6Ly9jaHJpc21nZW50cnkuZ2l0aHViLmlvL0dJUzEtRXhlcmNpc2UtNi8jMTFfU3RlcF9PbmU6X1RoZV9EYXRhKSB1c2luZyB0aGUgTU1RR0lTIHBsdWdpbiB0byBsb2FkIHRoZSBmaWxlIGRpcmVjdGx5IGZyb20gdGhlIFVSTC4gSnVzdCBiZSBzdXJlIHRvIHNldCB0aGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSB2YWx1ZSBmaWVsZHMgZm9yIHRoZSBVVE0gaW5mb3JtYXRpb24uDQoNCk5vdyB5b3UgY2FuIGNsb3NlIHRoZSBfRGVsaW1pdGVkIFRleHRfIHdpbmRvdy4gVGhlIHJlc3VsdGluZyBkYXRhc2V0IGlzIGFkZGVkIHRvIHlvdXIgbGF5ZXJzIGFzIGEgdGVtcG9yYXJ5IGZpbGUuIEl0IGNhbiBzdGlsbCBiZSB1c2VkIGZvciBhbmFseXNpcyBhbmQgZGlzcGxheSBwdXJwb3NlcywgYnV0IGlmIHlvdSBjbG9zZSB0aGUgcHJvamVjdCB0aGUgbGF5ZXIgbWF5IGJlIHJlbW92ZWQuIFRvIG1ha2UgaXQgYSBwZXJtYW5lbnQgZGF0YXNldCwgc2VsZWN0IHRoZSB0ZW1wb3JhcnkgZGF0YXNldCBpbiB0aGUgbGF5ZXJzIGFyZWEsIGFuZCBvbiB0aGUgbWVudSBiYXIgY2hvb3NlIF9MYXllcnMgPiBTYXZlIEFz4oCmXyBBbHRlcm5hdGl2ZWx5IHlvdSBjYW4gcmlnaHQtY2xpY2sgb3IgQ3J0bCtjbGljayBvbiBhIE1hYyBhbmQgY2hvb3NlIF9FeHBvcnQgPiBTYXZlIGZlYXR1cmVzIGFzLi4uXw0KDQo8cCBhbGlnbj0iY2VudGVyIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzX2RhdGFzZXQucG5nIiBhbHQ9IlZpZXcgb2YgbmV3IGRhdGFzZXQiIHdpZHRoPSI2NDAiIGhlaWdodD0iNTA2Ij48L3A+DQoNCioqUXVlc3Rpb24gTm8uIDEqKg0KPGJsb2NrcXVvdGU+DQpIb3cgbWFueSBpbmRpdmlkdWFscyBhcmUgYmVpbmcgdHJhY2tlZCBpbiB0aGlzIGRhdGFzZXQ/DQo8L2Jsb2NrcXVvdGU+DQo8L2RldGFpbHM+DQoNCjxocj48L2hyPg0KDQo8ZGV0YWlscz48c3VtbWFyeT48YmlnPlZpZXcgZGlyZWN0aW9ucyBpbiA8Yj4gW1Jde3N0eWxlPSJjb2xvcjogIzY0OTVFRCJ9IDwvYj48L3NwYW4+PC9iaWc+PC9zdW1tYXJ5Pg0KQmVmb3JlIHlvdSBiZWdpbiwgeW91IHdpbGwgbmVlZCB0byBvcGVuIHRoZSBbRXg5IENvbGFiIE5vdGVib29rXShodHRwczovL2dpdGh1Yi5jb20vY2hyaXNtZ2VudHJ5L0dJUzEtRXhlcmNpc2UtOS9ibG9iL21haW4vR0lTMV9FWDkuaXB5bmIpIGFuZCBpbnNlcnQgKip0b2NvbGFiKiogYWZ0ZXIgX2dpdGh1Yl8gaW4gdGhlIFVSTCB0byBvcGVuIGluIHRoZSBfQ29sYWIgRW52aXJvbm1lbnRfLiBBcyB5b3UgaGF2ZSBzZWVuIGJlZm9yZSwgUiByZXF1aXJlcyB2YXJpb3VzIHBhY2thZ2VzIHRvIGNvbXBsZXRlIGNlcnRhaW4gYW5hbHlzZXMuIEluIHRoaXMgZXhlcmNpc2UgeW91IHdpbGwgYmUgdXNpbmcgKip0aWR5dmVyc2UsIE9wZW5TdHJlZXRNYXBzLCBnZ2ZvcnRpZnksIG1hcHRvb2xzLCBhbmQgcmdlb3MqKi4gVG8gaW5zdGFsbCBhbmQgbG9hZCB0aGUgcGFja2FnZXMgd2Ugd2lsbCB1c2UgdGhlIGZvbGxvd2luZyBzY3JpcHQ6DQoNCmBgYCB7ciBpbnN0YWxsIHBhY2thZ2VzLCBlY2hvPVRSVUUsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KcGFja2FnZXMgPC0gYygiYWRlaGFiaXRhdEhSIiwiZ2dmb3J0aWZ5IiwiT3BlblN0cmVldE1hcCIsInRpZHl2ZXJzZSIsIm1hcHRvb2xzIiwicmdlb3MiKQ0Kc2FwcGx5KHBhY2thZ2VzLCBpbnN0YWxsLnBhY2thZ2VzLCBjaGFyYWN0ZXIub25seT1UUlVFKQ0Kc2FwcGx5KHBhY2thZ2VzLCByZXF1aXJlLCBjaGFyYWN0ZXIub25seT1UUlVFKQ0KYGBgDQoNCk5vdyB0aGF0IHlvdSBoYXZlIHRoZSBwYWNrYWdlcyByZXF1aXJlZCBmb3IgdGhlIGV4ZXJjaXNlIHlvdSBjYW4gcmVhZCBpbiB0aGUgX2Nzdl8gZmlsZSBhbmQgdmlldyB0aGUgcmVzdWx0aW5nIGRhdGFzZXQuIFVzaW5nIHRoZSBgYGByZWFkLmNzdmBgYCBjb21tYW5kIGFuZCBhIFVSTCB0byB0aGUgZGF0YSBvbiBHaXRIdWIgeW91IHdpbGwgaW1wb3J0IGFuZCBleGFtaW5lIHRoZSBkYXRhLg0KDQpgYGB7ciBsb2FkIGNzdiwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KY291Z2FycyA8LSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2NocmlzbWdlbnRyeS9HSVMxLUV4ZXJjaXNlLTkvbWFpbi9EYXRhL2NvdWdhcnMuY3N2IikNCmhlYWQoY291Z2FycykNCmBgYA0KDQpZb3UgY2FuIGFsc28gcGxvdCB0aGUgc2ltcGxlIFhZIGRhdGEgdG8gZXhhbWluZSB0aGUgc3ByZWFkIG9mIHRoZSBkYXRhc2V0Lg0KYGBge3IgcGxvdCBjb3VnYXIgeHkgZGF0YSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9NCwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KZ2dwbG90KGNvdWdhcnMpICsgZ2VvbV9wb2ludChhZXModXRtX2Vhc3QsIHV0bV9ub3J0aCkpICsgDQogICAgICAgICAgICAgICAgICBsYWJzKHg9IkVhc3RpbmciLCB5PSJOb3J0aGluZyIpICsNCiAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQoIklkZW50aWZpY2F0aW9uIikpICsNCiAgICAgICAgICAgICAgICAgIHRoZW1lX2J3KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKw0KICAgICAgICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTAuNSkpICsNCiAgICAgICAgICAgICAgICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKSArDQogICAgICAgICAgICAgICAgICB4bGltKDQwNTAwMCw0MjUwMDApDQpgYGANCg0KKipRdWVzdGlvbiBOby4gMSoqDQo8YmxvY2txdW90ZT4NCkhvdyBtYW55IGluZGl2aWR1YWxzIGFyZSBiZWluZyB0cmFja2VkIGluIHRoaXMgZGF0YXNldD8NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KDQojIyBTdGVwIFR3bzogVGhlIEFuYWx5c2VzDQoNCk5vdyB0aGF0IHlvdSBoYXZlIHRoZSBkYXRhIHlvdSBjYW4gY2FsY3VsYXRlIHRoZSB0d28gaG9tZSByYW5nZSBlc3RpbWF0ZXM6IF9taW5pbXVtIGNvbnZleCBwb2x5Z29uXyBhbmQgX2tlcm5lbCBkZW5zaXR5IGVzdGltYXRpb25fLiBUaGUgbWluaW11bSBjb252ZXggcG9seWdvbiAoKipNQ1AqKikgZHJhd3MgdGhlIHNtYWxsZXN0IHBvbHlnb24gZW5jb21wYXNzaW5nIGFsbCB0aGUgcG9pbnRzLCB3aGlsZSB0aGUga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiAoKipLREUqKikgY2FsY3VsYXRlcyBhIG1hZ25pdHVkZS1wZXItdW5pdCBhcmVhIGZyb20gdGhlIHBvaW50IGZlYXR1cmVzIHVzaW5nIGEgZnVuY3Rpb24gdG8gZml0IGEgc21vb3RobHkgdGFwZXJlZCBzdXJmYWNlLiBGb3IgdGhpcyBleGVyY2lzZSB5b3Ugd2lsbCBydW4gYm90aCBhbmFseXNlcyBhbmQgY29tcGFyZSB0aGUgcmVzdWx0cy4NCg0KPGRldGFpbHM+DQo8c3VtbWFyeT48YmlnPlZpZXcgRGlyZWN0aW9ucyBpbiA8Yj4gW0FyY0dJUyBQcm9de3N0eWxlPSJjb2xvcjojZmY0NTAwIn0gPC9iPjwvYmlnPjwvc3VtbWFyeT4NCg0KSW4gdGhlIHByZXZpb3VzIHN0ZXAgeW91IGxvYWRlZCB0aGUgcmVsb2NhdGlvbnMgYW5kIGFkZGVkIHRoZSBsYXllciB0byB5b3VyIHZpZXcuIE5vdyB5b3Ugd2lsbCB1c2Ugc2V2ZXJhbCB0b29scyBmcm9tIHRoZSBfVG9vbGJveF8gPGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLXRvb2xib3gtYnV0dG9uLmpwZyIgYWx0PSJUb29sYm94IiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiPiB0byBjb21wbGV0ZSB0aGUgYW5hbHlzZXMgaW5jbHVkaW5nOg0KDQotIE1pbmltdW0gQm91bmRpbmcgR2VvbWV0cnkgKG1pbmltdW0gY29udmV4IHBvbHlnb24pDQotIEtlcm5lbCBEZW5zaXR5IEVzdGltYXRpb24NCi0gQ2FsY3VsYXRlIEdlb21ldHJ5DQotIFJlY2xhc3NpZnkNCi0gUmFzdGVyIHRvIFBvbHlnb24NCg0KVG8gY3JlYXRlIHRoZSBtaW5pbXVtIGNvbnZleCBwb2x5Z29uIHlvdSB3aWxsIHVzZSB0aGUgYE1pbmltdW0gQm91bmRpbmcgR2VvbWV0cnlgIHRvb2wgdGhhdCBjYW4gYmUgZm91bmQgYnkgdXNpbmcgdGhlIG5hbWUgYXMgYSBzZWFyY2ggdGVybSBpbiBfVG9vbGJveF8gZnJvbSB0aGUgQW5hbHlzaXMgVGFiLiBZb3Ugd2lsbCB1c2UgdGhlICoqY291Z2FyKiogZGF0YXNldCBmb3IgdGhlIF9JbnB1dCBGZWF0dXJlc18sIG5hdmlnYXRlIHRvIHlvdXIgcHJvamVjdCBmb2xkZXIgYW5kIGdpdmUgdGhlIFwqLnNocCBmaWxlIGEgbmFtZSBpbiB0aGUgX091dHB1dCBGZWF0dXJlIENsYXNzXyBvcHRpb25zLCBhbmQgc2VsZWN0ICoqY29udmV4IGh1bGwqKiBmb3IgdGhlIF9HZW9tZXRyeSBUeXBlXy4gRm9yIF9Hcm91cCBPcHRpb25fIHNlbGVjdCBBbGwuIExlYXZlIHRoZSBib3ggZm9yIGdlb21ldHJ5IGNoYXJhY3RlcmlzdGljcyB1bmNoZWNrZWQuDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1tY3AtZGlhbG9nLnBuZyIgYWx0PSJDcmVhdGluZyB0aGUgTWluaW11bSBCb3VuZGluZyBHZW9tZXRyeSIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KWW91IHNob3VsZCBub3cgaGF2ZSBhIGJvdW5kaW5nIGdlb21ldHJ5IHBvbHlnb24gaW4geW91ciBsYXllcnMgeW91IGNhbiBzdHlsZSBhcyBuZWNlc3NhcnkgdG8gZGlzcGxheSB0aGUgaW5mb3JtYXRpb24uIE5vdGljZSBob3cgdGhlIHBvbHlnb24gaXMgZHJhd24gYW5kIGVuY29tcGFzc2VzIHRoZSBkYXRhIHBvaW50cy4gVG8gY3JlYXRlIHRoZSBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHNlYXJjaCBmb3IgaXQgaW4gdGhlIHRvb2xib3ggb3IgYWx0ZXJuYXRpdmVseSBpdCBjYW4gYmUgZm91bmQgaW4gdGhlIHF1aWNrbHkgbGluayBmb3IgdG9vbHMgb24gdGhlIEFuYWx5c2lzIFRhYi4gVXNlIHRoZSBmb2xsb3dpbmcgc2V0dGluZyBmb3IgdGhlIEtlcm5lbCBEZW5zaXR5IGFuYWx5c2lzOg0KDQotIElucHV0IHBvaW50IG9mIHBvbHlsaW5lIGZlYXR1cmVzID0gY291Z2FycyBkYXRhc2V0DQotIFBvcHVsYXRpb24gZmllbGQgPSBOT05FDQotIE91dHB1dCByYXN0ZXIgPSBuYXZpZ2F0ZSB0byB5b3VyIHByb2plY3QgZm9sZGVyIGFuZCBnaXZlIHRoZSBmaWxlIGEgbmFtZSBmb2xsb3dlZCBieSAudGlmDQotIE91dHB1dCBjZWxsIHNpemUgPSAxMDANCi0gU2VhcmNoIHJhZGl1cyA9IDIwMDANCi0gQXJlYSB1bml0cyA9IFNxdWFyZSBtZXRlcnMNCi0gT3V0cHV0IGNlbGwgdmFsdWVzID0gRGVuc2l0aWVzDQotIE1ldGhvZCA9IFBsYW5hcg0KLSBJbnB1dCBiYXJyaWVyIGZlYXR1ZXMgPSBMZWF2ZSB0aGlzIGJsYW5rDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1rZGUtZGlhbG9nLnBuZyIgYWx0PSJDcmVhdGluZyB0aGUgS2VybmVsIERlbnNpdHkgRXN0aW1hdGlvbiIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KQmVmb3JlIG1vdmluZyBvbiB3aXRoIGFueSBhZGRpdGlvbmFsIGFuYWx5c2lzLCB5b3Ugd2lsbCByZWNsYXNzaWZ5IHRoZSBLREUgb3V0cHV0IHRvIGZvdXIgKDQpIGNsYXNzZXMuIFRvIGRvIHRoaXMgc2VhcmNoIGZvciAqKlJlY2xhc3NpZnkqKiBpbiB0aGUgZ2VvcHJvY2Vzc2luZyB0b29scy4gSW4gcGFyZW50aGVzZXMgYmVoaW5kIHRoZSB0b29scyBuYW1lIHlvdSB3aWxsIHNlZSB0aGUgbmFtZSBvZiB0aGUgcGFja2FnZSBpdCBpcyBiZWluZyBzZWxlY3RlZCBmcm9tLiBZb3Ugd2FudCB0byBjaG9vc2UgdGhlIGBSZWNsYXNzaWZ5YCB0b29sIGZyb20gdGhlIF9TcGF0aWFsIEFuYWx5c3QgVG9vbHNfIHBhY2thZ2UuIEluIHRoZSBSZWNsYXNzaWZ5IHBhbmUgc2VsZWN0IHRoZSBrZXJuZWwgZGVuc2l0eSBmaWxlIHlvdSBqdXN0IGNyZWF0ZWQgYXMgdGhlIF9JbnB1dCBSYXN0ZXJfIGFuZCBjbGljayAqKkNsYXNzaWZ5KiouIEluIHRoZSBXaW5kb3cgc2VsZWN0IDQgY2xhc3NlcyBhbmQgY2xpY2sgT0suIEZpbmFsbHksIGluIHRoZSBfT3V0cHV0IHJhc3Rlcl8gb3B0aW9uIG5hdmlnYXRlIHRvIHlvdXIgcHJvamVjdCBmb2xkZXIgYW5kIGJlIHN1cmUgdG8gc2F2ZSB0aGUgZmlsZSBhcyBhIC50aWYgdGhlbiBjbGljayBSdW4uDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1yZWNsYXNzaWZ5LnBuZyIgYWx0PSJDbGFzc2lmeWluZyB0aGUgS0RFIHRvIDQgY2xhc3NlcyIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KTmV4dCwgaW4gb3JkZXIgdG8gY2FsY3VsYXRlIHRoZSBhcmVhIG9mIHRoZSBuZXcgY2xhc3NpZmllZCBLREUgeW91IHdpbGwgbmVlZCB0byBjb252ZXIgaXQgdG8gYSBwb2x5Z29uIGZlYXR1cmUgY2xhc3MuIEluIF9Ub29sc18geW91IGNhbiBzZWFyY2ggZm9yICJSYXN0ZXIgdG8gUG9seWdvbiIgYW5kIGFkZCB0aGUgbmV3IHJlY2xhc3NpZmVkIEtERSBhcyB0aGUgX0lucHV0IFJhc3Rlcl8sIHNlbGVjdCAiVmFsdWUiIGZvciB0aGUgX0ZpZWxkXyBwYXJhbWV0ZXIsIGFuZCB1c2UgdGhlIGJyb3dzZSBidXR0b24gdG8gbmF2aWdhdGUgdG8geW91ciBwcm9qZWN0IGZvbGRlciBhbmQgZ2l2ZSB0aGUgbmV3IGZpbGUgYSAuc2hwIGZpbGUgbmFtZSBpbiB0aGUgX091dHB1dCBQb2x5Z29uIEZlYXR1cmVzXyBwYXJhbWV0ZXIuIEJlIHN1cmUgdG8gY2xpY2sgdGhlIF9TaW1wbHkgcG9seWdvbnNfIGFuZCBfQ3JlYXRlIG11bHRpcGFydCBmZWF0dXJlc18gYm94ZXMgYW5kIGNsaWNrIFJ1bi4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLXJhc3Rlci10by1wb2x5Z29uLnBuZyIgYWx0PSJDcmVhdGluZyBQb2x5Z29ucyBmcm9tIFJhc3RlciIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KVGhpcyB3aWxsIGNyZWF0ZSBhIHNlcmllcyBvZiBvdmVybGFwcGluZyBwb2x5Z29ucyByZXByZXNlbnRpbmcgZWFjaCBvZiB0aGUgZm91ciBjbGFzc2VzLiAgDQoNCi0gQ2xhc3MgMSA9IExvdyBsZXZlbHMgb2YgcmVsb2NhdGlvbnMNCi0gQ2xhc3MgMiA9IE1vZGVyYXRlIGxldmVscyBvZiByZWxvY2F0aW9ucw0KLSBDbGFzcyAzID0gSGlnaCBsZXZlbHMgb2YgcmVsb2NhdGlvbnMNCi0gQ2xhc3MgNCA9IFZlcnkgaGlnaCBsZXZlbCBvZiByZWxvY2F0aW9ucw0KDQpIb3dldmVyLCBiZWNhdXNlIHRoZXkgYXJlIG92ZXJsYXBwaW5nIHBvbHlnb25zLCBDbGFzcyAxIG1ha2VzIHVwIHRoZSBlbnRpcmUgc3VyZmFjZSBhcmVhIGluY2x1ZGluZyB0aG9zZSBpbiB0aGUgaGlnaGVyIGNhdGVnb3JpZXMgdGhhdCBhcmUgb3ZlcmxhcHBpbmcgdGhlIGRhdGEgKGUuZy4gQ2xhc3MgNCBsb2NhdGlvbnMgd2lsbCBvdmVybGFwIENsYXNzIDEsIHNvIHRoZSAiYXJlYSIgb2YgQ2xhc3MgMSBtYWtlcyB1cCB0aGUgZW50aXJlIHN1cmZhY2UgYXJlYSkuIFNpbmNlIHRoZSBkZXZlbG9wbWVudCBvZiB0aGUgS0RFIHJhbmdlcyBmcm9tIHRoZSBleHRlbnQgb2YgdGhlIHBvaW50IHZhbHVlcywgc29tZSBhcmVhcyB3aXRob3V0IHJlbG9jYXRpb25zIHdlcmUgY2FsY3VsYXRlZCBpbiB0aGUgZGV2ZWxvcG1lbnQgb2YgdGhlIHBvbHlnb25zLiBTbyBiZWZvcmUgY29udGludWluZyB1c2UgdGhlICoqQ2xpcCoqIGdlb3Byb2Nlc3NpbmcgdG9vbCB0byBjbGlwIHRoZSBLREUgYmFzZWQgb24gdGhlIE1DUC4NCg0KV2l0aCB0aGUgbmV3IGNsaXBwZWQgS0RFIHBvbHlnb25zIGNyZWF0ZWQgeW91IG5lZWQgdG8gYWRkIGEgbmV3IGZpZWxkIHRvIGNhbGN1bGF0ZSB0aGUgYXJlYS4gT3BlbiB0aGUgYXR0cmlidXRlIHRhYmxlIGFuZCBjbGljayB0aGUgX0FkZCBGaWVsZF8gYnV0dG9uIDxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1hZGQtZmllbGQtYnV0dG9uLmpwZyIgYWx0PSJUb29sYm94IiB3aWR0aD0iNDAiIGhlaWdodD0iMjAiPiBhbmQgcHJvdmlkZSBhIF9GaWVsZCBOYW1lXyBvZiBBcmVhIHRvIHRoZSBuZXcgdmFyaWFibGUuIENsaWNrIEZsb2F0IGFzIHRoZSBfRGF0YSBUeXBlXyBhbmQgTnVtZXJpYyBhcyB0aGUgX051bWJlciBGb3JtYXRfLiBZb3UgY2FuIG5vdyBjbG9zZSB0aGUgZmllbGRzIHRhYiBhbmQgc2F2ZSB0aGUgZWRpdHMuIE9uIHRoZSBuZXcgdmFyaWFibGUgaW4gdGhlIGF0dHJpYnV0ZSB0YWJsZSByaWdodC1jbGljayBvbiBBcmVhIGFuZCBjbGljayBfQ2FsY3VsYXRlIEdlb21ldHJ5Xy4gT24gdGhlIG5ldyBwYW5lIHNlbGVjdCB0aGUgY2xpcHBlZCBLREUtcG9seWdvbiBsYXllciBhcyB0aGUgX0lucHV0IEZlYXR1cmVzXywgY2hvb3NlIEFyZWEgYXMgdGhlIF9UYXJnZXQgRmllbGRfIGFuZCBBcmVhIGFzIHRoZSBfUHJvcGVydHlfLiBGb3IgX0FyZWEgVW5pdHNfIHNlbGVjdCBzcXVhcmUgbWV0ZXJzIGFuZCBiZSBzdXJlIHRoYXQgdGhlIF9Db29yZGluYXRlIHN5c3RlbV8gbWF0Y2hlcyB0aGUgQ1JTIG9mIHlvdXIgcHJvamVjdCBhbmQgY2xpY2sgT0suIFJlIHBlYXQgdGhpcyBwcm9jZXNzIGZvciB0aGUgTUNQIHBvbHlnb24geW91IGNyZWF0ZWQgZWFybGllci4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLWNhbGN1bGF0ZS1nZW9tZXRyeS5wbmciIGFsdD0iQ2FsY3VsYXRlIEdlb21ldHJ5IEZpZWxkIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PC9wPg0KDQoqKlF1ZXN0aW9uIE5vLiAyKioNCjxibG9ja3F1b3RlPg0KV2hhdCBpcyB0aGUgYXJlYSBvZiB0aGUgTWluaW11bSBDb252ZXggUG9seWdvbj88YnI+DQpXaGF0IGlzIHRoZSBhcmVhIG9mIHRoZSBLZXJuZWwgRGVuc2l0eSBFc3RpbWF0aW9uPw0KPC9ibG9ja3F1b3RlPg0KDQo8L2RldGFpbHM+DQoNCjxocj48L2hyPg0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxiaWc+VmlldyBEaXJlY3Rpb25zIGluIDxiPiBbUUdJU117c3R5bGU9ImNvbG9yOiMwMDY0MDAifSA8L2I+PC9iaWc+PC9zdW1tYXJ5Pg0KDQpJbiB0aGUgcHJldmlvdXMgc3RlcCB5b3UgbG9hZGVkIHRoZSByZWxvY2F0aW9ucyBhbmQgYWRkZWQgdGhlIGxheWVyIHRvIHlvdXIgdmlldy4gTm93IHlvdSB3aWxsIHVzZSBzZXZlcmFsIHRvb2xzIGZyb20gdGhlIF9Qcm9jZXNzaW5nIFRvb2xib3hfICZuYnNwOzxpbWcgc3JjPSAiSW1hZ2VzL3FnaXNfdG9vbGJveC5wbmciIGFsdD0iUHJvY2Vzc2luZyBUb29sYm94IiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiPiB0byBjb21wbGV0ZSB0aGUgYW5hbHlzZXMgaW5jbHVkaW5nOg0KDQotIE1pbmltdW0gYm91bmRpbmcgZ2VvbWV0cnkNCi0gQWRkIGdlb21ldHJ5IGF0dHJpYnV0ZXMNCi0gSGVhdCBtYXAgKEtlcm5lbCBEZW5zaXR5IEVzdGltYXRpb24pDQotIFJhc3RlciBjYWxjdWxhdG9yDQotIFBvbHlnb25pemUgKHJhc3RlciB0byB2ZWN0b3IpDQoNClRvIGNyZWF0ZSB0aGUgX21pbmltdW0gY29udmV4IHBvbHlnb25fIHlvdSB3aWxsIHVzZSB0aGUgYGBgTWluaW11bSBib3VuZGluZyBnZW9tZXRyeWBgYCB0b29sIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBfUHJvY2Vzc2luZyBUb29sYm94XyB1bmRlciAqKlZlY3RvciBnZW9tZXRyeSoqLiBBbHRlcm5hdGl2ZWx5IHlvdSBjYW4gc2VhcmNoIGZvciBpdCBpbiB0aGUgdG9vbGJveCBzZWFyY2ggYmFyLiBZb3Ugd2lsbCB1c2UgdGhlICoqY291Z2FyKiogZGF0YXNldCBmb3IgdGhlIF9JbnB1dCBsYXllcl8sIGFuZCAqKkNvbnZleCBodWxsKiogZm9yIHRoZSBfR2VvbWV0cnkgdHlwZV8uIEFsbCBvdGhlciBvcHRpb25zIHlvdSBjYW4gbGVhdmUgYXMgdGhlIGRlZmF1bHQuIFJlbWVtYmVyIHRoaXMgd2lsbCBjcmVhdGUgYSB0ZW1wb3JhcnkgbGF5ZXIgd2hpY2ggeW91IGNhbiBjaG9vc2UgdG8gbWFrZSBwZXJtYW5lbnQgb3IgcmVuYW1lIGluIHlvdXIgbGF5ZXJzIGZvciBjbGFyaXR5LiANCg0KPHAgYWxpZ249ImNlbnRlciI+PGltZyBzcmM9ICJJbWFnZXMvcWdpc19tYmcucG5nIiBhbHQ9Ik1pbmltdW0gYm91bmRpbmcgZ2VvbWV0cnkgb3B0aW9ucyIgd2lkdGg9IjQ4MiIgaGVpZ2h0PSIzODciPjwvcD4NCg0KWW91IHNob3VsZCBub3cgaGF2ZSBhIF9Cb3VuZGluZyBnZW9tZXRyeV8gcG9seWdvbiBpbiB5b3VyIGxheWVycyB5b3UgY2FuIHN0eWxlIGFzIG5lY2Vzc2FyeSB0byBkaXNwbGF5IHRoZSBpbmZvcm1hdGlvbi4gQnkgdmlld2luZyB0aGUgX2F0dHJpYnV0ZSB0YWJsZV8geW91IGNhbiBzZWUgdGhlIGFyZWEgKGluIHNxdWFyZSBtZXRlcnMpIG9mIHRoZSBwb2x5Z29uLiANCg0KQ3JlYXRpbmcgdGhlICoqS0RFKiogZXN0aW1hdGUgd2lsbCB0YWtlIGEgZmV3IG1vcmUgc3RlcHMgYmVmb3JlIHlvdSBjYW4gb2J0YWluIHRoZSBzdGF0aXN0aWNhbCBpbmZvcm1hdGlvbiBmb3IgY29tcGFyaXNvbi4gQmVjYXVzZSB0aGUgX2tlcm5lbCBkZW5zaXR5IGVzdGltYXRpb25fIGNyZWF0ZXMgYSByYXN0ZXIgZGF0YXNldCwgeW91IHdpbGwgY2xhc3NpZnkgdGhlIGRhdGEgdXNpbmcgdGhlIGBgYHJhc3RlciBjYWxjdWxhdG9yYGBgIGFuZCBjb252ZXJ0IHRoZSBjbGFzc2lmaWVkIHZhbHVlcyB0byBhIHZlY3RvciB3aXRoIGBgYHBvbHlnb25pemVgYGAgYmVmb3JlIGV4YW1pbmluZyB0aGUgc3RhdGlzdGljcy4gDQoNClRvIGJlZ2luIHRoaXMgYW5hbHlzaXMgeW91IG5lZWQgdG8gb3BlbiB0aGUgYGBgSGVhdG1hcCAoS2VybmVsIERlbnNpdHkgRXN0aW1hdGlvbilgYGAgdG9vbCBmcm9tICoqSW50ZXJwb2xhdGlvbioqIGluIHRoZSBfUHJvY2Vzc2luZyBUb29sYm94Xy4gSW4gdGhlIF9pbnB1dCBsYXllcl8geW91IHdpbGwgdXNlIHRoZSAqKmNvdWdhcioqIGRhdGFzZXQsIHNldCBhIF9SYWRpdXNfIG9mIDIwMDAsIGEgX3BpeGVsIHNpemVfIG9mIDEwMCwgYW5kIHNldCB0aGUgX0tlcm5lbCBzaGFwZV8gdG8gX0VwYW5lY2huaWtvdl8uIA0KDQo8cCBhbGlnbj0iY2VudGVyIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzX2hlYXRtYXAucG5nIiBhbHQ9IkhlYXRtYXAgKEtERSkgb3B0aW9ucyIgd2lkdGg9IjQ4MCIgaGVpZ2h0PSIzODYiPjwvcD4NCg0KTm93IGNsaWNrICoqUnVuKiouIFRoaXMgd2lsbCBjcmVhdGUgYSAqKktERSoqIGFuZCBhZGQgaXQgdG8geW91ciBsYXllcnMuIFlvdSBjYW4gc3R5bGUgdGhlIF9oZWF0bWFwXyB1c2luZyBfc3ltYm9sb2d5XyB1bmRlciB0aGUgX3Byb3BlcnRpZXNfIG1lbnUgZm9yIHRoZSBkYXRhLiBJTiBvcmRlciB0byBnZXQgbW9yZSBpbmZvcm1hdGlvbiBvdXQgb2YgdGhpcyBhbmFseXNpcyB5b3UgbmVlZCB0byAqKnJlY2xhc3NpZnkqKiB0aGUgcmFzdGVyIGludG8gdGhlIGZvbGxvd2luZyBjYXRlZ29yaWVzOg0KDQotIExldmVsIDEgPSAwIHRvIDYwLCBsb3cgbGV2ZWxzIG9mIHJlbG9jYXRpb25zDQotIExldmVsIDIgPSA2MSB0byAxMjAsIG1vZGVyYXRlIGxldmVscyBvZiByZWxvY2F0aW9ucw0KLSBMZXZlbCAzID0gMTIxIHRvIDE4MCwgaGlnaCBsZXZlbHMgb2YgcmVsb2NhdGlvbnMNCi0gTGV2ZWwgNCA9IEdyZWF0ZXIgdGhhbiAxODAsIHZlcnkgaGlnaCBsZXZlbCBvZiByZWxvY2F0aW9ucyANCg0KVG8gZG8gdGhpcyB5b3Ugd2lsbCB1c2UgdGhlIGBgYFJhc3RlciBDYWxjdWxhdG9yYGBgIGxvY2F0ZWQgdW5kZXIgX1Jhc3Rlcl8gb24gdGhlIF9NZW51IEJhcl8gb3IgdW5kZXIgX1Jhc3RlciBhbmFseXNpc18gaW4gdGhlIF9Qcm9jZXNzaW5nIFRvb2xib3hfLiBJbiB0aGUgX0xheWVyc18gc2VjdGlvbiB5b3Ugc2hvdWxkIHNlZSB0aGUgYXZhaWxhYmxlIHJhc3RlciBsYXllcnMgaW4geW91ciBjdXJyZW50IHByb2plY3QuIEluIHRoZSBfRXhwcmVzc2lvbl8gYm94IHlvdSB3aWxsIHBhc3RlIHRoZSBmb2xsb3dpbmcgU1FMIGV4cHJlc3Npb246DQoNCmBgYA0KKCJIZWF0bWFwQDEiIDw9IDYwKSAqIDEgKyANCigoIkhlYXRtYXBAMSIgPiA2MCkgIEFORCAgKCJIZWF0bWFwQDEiIDw9IDEyMCkpICogMiArIA0KKCgiSGVhdG1hcEAxIiA+IDEyMCkgIEFORCAgKCJIZWF0bWFwQDEiIDw9IDE4MCkpICogMyArIA0KKCJIZWF0bWFwQDEiID4gMTgwKSAqIDQNCmBgYA0KDQpXaGVyZSAqKiJIZWF0bWFwXEAxIioqIGlzIHRoZSBuYW1lIG9mIHRoZSBfS0RFXyBvdXRwdXQgZnJvbSB0aGUgcHJldmlvdXMgc3RlcC4gVGhpcyB3aWxsIGNvbnZlcnQgYWxsIG9mIHRoZSB2YWx1ZXMgdG8gYSByYW5nZSBvZiAxLTQgaW5kaWNhdGluZyB0aGUgbGV2ZWwgb2YgcmVsb2NhdGlvbnMuIEluIHRoZSBzZWN0aW9uIGZvciBfUmVmZXJlbmNlIGxheWVyKHMpICh1c2VkIGZvciBhdXRvbWF0ZWQgZXh0ZW50LCBjZWxsc2l6ZSwgYW5kIENSUylbb3B0aW9uYWxdXyB5b3Ugc2hvdWxkIGNsaWNrIHRoZSBfYnJvd3NlIGZpbGUgcGF0aF8gYnV0dG9uIDxpbWcgc3JjPSAiSW1hZ2VzL2ZpbGVfcGF0aC5wbmciIGFsdD0iQnJvd3NlIEZpbGUgUGF0aCIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIj4gdG8gYWRkIHRoZSAqKkhlYXRtYXAqKiAob3IgdGhlIG5hbWUgb2YgeW91ciBfS0RFXyBmaWxlKS4gTWFrZSB0aGUgX0NlbGwgc2l6ZV8gdG8gMTAwLCB1c2luZyB0aGUgZHJvcGRvd24gbWVudSBuZXh0IHRvIHRoZSBfT3V0cHV0IGV4dGVudCBbb3B0aW9uYWxdXyBzZWxlY3QgKipDYWxjdWxhdGUgZnJvbSBMYXllcioqIGFuZCBjaG9vc2UgeW91ciBfSGVhdG1hcF8uIEZvciB0aGUgX091dHB1dCBDUlMgW29wdGlvbmFsXV8gc2VsZWN0IHRoZSBwcm9qZWN0IENSUyBhbmQgdGhlbiBjbGljayAqKlJ1bioqLg0KDQo8cCBhbGlnbj0iY2VudGVyIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzX3JjLnBuZyIgYWx0PSJSYXN0ZXIgY2FsY3VsYXRvciBvcHRpb25zIiB3aWR0aD0iNDMwIiBoZWlnaHQ9IjUwMiI+PC9wPg0KDQpUaGlzIHdpbGwgYWRkIHRoZSByZWNsYXNzaWZpZWQgaGVhdG1hcCB0byB5b3UgbGF5ZXJzLiBOb3cgeW91IGNhbiB1c2UgYGBgUG9seWdvbml6ZSAocmFzdGVyIHRvIHZlY3RvcilgYGAgZm91bmQgdW5kZXIgX1Jhc3RlciA+IENvbnZlcnNpb25fIG9uIHRoZSBtZW51ciBiYXIgb3IgX0dEQUwgPiBSYXN0ZXIgY29udmVyc2lvbl8gaW4gdGhlIF9Qcm9jZXNzaW5nIFRvb2xib3hfLiBJbiB0aGUgX1BvbHlnb25pemUgKFJhc3RlciB0byBWZWN0b3IpXyB3aW5kb3cgY2hvb3NlIHlvdXIgcmVjbGFzc2lmaWVkIEtERSBjcmVhdGVkIGluIHRoZSBwcmV2aW91cyBzdGVwIGFzIHRoZSBfSW5wdXQgbGF5ZXJfIGFuZCBjbGljayAqKlJ1bioqLiBUaGlzIHdpbGwgYWRkIGFub3RoZXIgbGF5ZXIgKHVzdWFsbHkgY2FsbGVkICJWZWN0b3JpemVkIiBpZiBzZXQgYXMgYSB0ZW1wb3JhcnkgZmlsZSkgdGhhdCB0dXJuZWQgdGhlIHJhc3RlciBkYXRhIHRvIHZlY3RvciBwb2x5Z29ucy4gRmluYWxseSwgd2UgbmVlZCB0byB1c2UgdGhlICoqQWRkIGdlb21ldHJ5IGF0dHJpYnV0ZXMqKiBmb3VuZCB1bmRlciBfVmVjdG9yID4gR2VvbWV0cnkgVG9vbHNfIG9uIHRoZSBtZW51IGJhciBvciBfVmVjdG9yIGdlb21ldHJ5XyBpbiB0aGUgX1Byb2Nlc3NpbmcgVG9vbGJveF8uIFRoaXMgd2lsbCBhZGQgY29sdW1ucyBmb3IgKipBcmVhKiogYW5kICoqUGVyaW1ldGVyKiogdG8gdGhlIGF0dHJpYnV0ZSB0YWJsZSBmb3IgdGhlIHZlY3Rvcml6ZWQgZGF0YXNldC4gWW91IHdpbGwgbmVlZCB0byBhZGQgdGhlIF92ZWN0b3JpemVkXyBsYXllciBhcyB0aGUgKipJbnB1dCBsYXllcioqLCBfTGF5ZXIgQ1JTXyBmb3IgdGhlICoqQ2FsY3VsYXRlIHVzaW5nKiogZmllbGQgYW5kIGNsaWNrICoqUnVuKiouDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxpbWcgc3JjPSAiSW1hZ2VzL3FnaXNfZ2VvbWV0cmllcy5wbmciIGFsdD0iQWRkIGdlb21ldHJ5IGF0dHJpYnV0ZXMiIHdpZHRoPSI0MjYiIGhlaWdodD0iMjIyIj48L3A+DQoNCkZpbmFsbHksIGlmIHlvdSBjbGljayB0aGUgKipTaG93IFN0YXRpc3RpY2FsIFN1bW1hcnkqKiBidXR0b24gPGltZyBzcmM9ICJJbWFnZXMvcWdpc19zdGF0aXN0aWNzLnBuZyIgYWx0PSJTaG93IHN0YXRpc3RpY2FsIHN1bW1hcnkiIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+IG9uIHRoZSBwcmltYXJ5IGhvcml6b250YWwgbWVudSwgYSBuZXcgX1N0YXRpc3RpY3NfIHBhbmVsIHdpbGwgYmUgYWRkZWQgdG8geW91ciBsYXlvdXQuIEJ5IHNlbGVjdGluZyB0aGUgX0FkZGVkIGdlb21ldHJ5IGluZm9fIGxheWVyIChvciB0aGUgbmFtZSBvZiB0aGUgZmlsZSBmcm9tIHRoZSBwcmV2aW91cyBzdGVwKSBhbmQgY2hvb3NpbmcgX2FyZWFfIHlvdSBjYW4gc2VlIGEgc3VtbWFyeSBvZiB0aGUgc3RhdGlzdGljYWwgaW5mb3JtYXRpb24uIFRoZSB0b3RhbCBhcmVhIGluIHRoZSBfS0RFIEVzdGltYXRpb25fIHdpbGwgYmUgZm91bmQgaW4gdGhlICoqU3VtKiogc3RhdGlzdGljLg0KDQoqKlF1ZXN0aW9uIE5vLiAyKioNCjxibG9ja3F1b3RlPg0KV2hhdCBpcyB0aGUgYXJlYSBvZiB0aGUgTWluaW11bSBDb252ZXggUG9seWdvbj88YnI+DQpXaGF0IGlzIHRoZSBhcmVhIG9mIHRoZSBLZXJuZWwgRGVuc2l0eSBFc3RpbWF0aW9uPw0KPC9ibG9ja3F1b3RlPg0KPC9kZXRhaWxzPg0KDQo8aHI+PC9ocj4NCg0KPGRldGFpbHM+DQo8c3VtbWFyeT48YmlnPlZpZXcgRGlyZWN0aW9ucyBpbiA8Yj4gW1Jde3N0eWxlPSJjb2xvcjojNjQ5NUVEIn0gPC9iPjwvYmlnPjwvc3VtbWFyeT4NCg0KRm9yIHRoaXMgZXhlcmNpc2UgeW91IHdpbGwgdXNlIHRoZSBgYGBhZGVoYWJpdGF0YGBgIHBhY2thZ2UgdG8gY2FsY3VsYXRlIGJvdGggdGhlIF9NQ1BfIGFuZCBfS0RFXyBwb2x5Z29ucy4gQmVjYXVzZSB0aGlzIHBhY2thZ2UgdXNlcyBzcGVjaWFsaXplZCBmdW5jdGlvbnMgeW91IG5lZWQgdG8gY29udmVydCB5b3VyIFhZIGRhdGEgdG8gYSBjbGFzcyBvZiBkYXRhIGNhbGxlZCBfU3BhdGlhbFBvaW50c18uIE9uY2UgdGhlIHNwYXRpYWwgZGF0YSBpcyBjcmVhdGVkIHlvdSBjYW4gcnVuIGJvdGggdGhlIE1DUCBhbmQgS0RFIGFuYWx5c2VzIGZvciB0aGUgZGF0YXNldCB5b3Ugb2J0YWluZWQgYWJvdmUuDQoNCkJlY2F1c2UgdGhlIGFuYWx5c2VzIG5lZWQgdG8gYmUgY2FsY3VsYXRlZCB1c2luZyBtZXRyaWMgdmFsdWVzLCB5b3Ugd2lsbCB1c2UgdGhlICoqdXRtLWVhc3QqKiBhbmQgKip1dG0tbm9ydGgqKiBjb2x1bW5zIGluIHRoZSBkYXRhc2V0IHRvIGNyZWF0ZSBhIHNldCBvZiBjb29yZGluYXRlcyB3aXRoIGEgX1NwYXRpYWxQb2ludHNfIGNsYXNzIHRoYXQgd2lsbCBiZSB1c2VkIGluIHRoZSBjYWxjdWxhdGlvbiBvZiB0aGUgcG9seWdvbnMuDQoNCmBgYHtyIGNyZWF0ZSBjb29yZGluYXRlcywgZWNobz1UUlVFLCByZXN1bHRzPSdoaWRlJywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCnggPC0gY291Z2FycyR1dG1fZWFzdA0KeSA8LSBjb3VnYXJzJHV0bV9ub3J0aA0KeHkgPC0gYXMuZGF0YS5mcmFtZShjYmluZCh4LHkpKQ0KY29vcmRpbmF0ZXMoeHkpIDwtIH54K3kNCmBgYA0KDQpXaXRoIHRoaXMgbmV3IF9YWV8gZGF0YXNldCB5b3UgY2FuIG5vdyBjcmVhdGUgdGhlICoqTUNQKiogYW5kICoqS0RFKiogZXN0aW1hdGVzIGZvciB0aGUgY291Z2FyIHJlbG9jYXRpb25zLiBZb3Ugd2lsbCBzdGFydCB3aXRoIHRoZSAqKk1DUCoqIHBvbHlnb24uIFVzaW5nIHRoZSBgYGBtY3BgYGAgZnVuY3Rpb24gaW4gdGhlIGBgYGFkZWhhYml0YXRgYGAgcGFja2FnZSwgeW91IHdpbGwgY3JlYXRlIHRoZSBlc3RpbWF0ZWQgX01DUCBob21lIHJhbmdlXy4gVGhlbiB5b3Ugd2lsbCBuZWVkIHRvIGNvbnZlcnQgdGhlIHJlc3VsdGluZyBfU3BhdGlhbFBvbHlnb25zRGF0YUZyYW1lXyB0byBhIGZvcm1hdCB0aGF0IGNhbiBiZSBwbG90dGVkIHVzaW5nIGBgYGdncG9sdDJgYGAuIEN1cnJlbnRseSB5b3Ugd2lsbCB1c2UgdGhlIGBgYGZvcnRpZnlgYGAgZnVuY3Rpb24sIGhvd2V2ZXIgYXMgZnVuY3Rpb25zIGFyZSBkZXByZWNhdGVkIG92ZXIgdGltZSwgYGBgdGlkeWBgYCBhcyBwYXJ0IG9mIHRoZSBgYGBicm9vbWBgYCBwYWNrYWdlIGNhbiBhbHNvIGJlIHVzZWQgZm9yIHRoaXMgcHJvY2Vzcy4NCg0KYGBge3IgY3JlYXRlIG1jcCwgZWNobz1UUlVFLCByZXN1bHRzPSdoaWRlJywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCm1jcC5vdXQgPC0gbWNwKHh5LCBwZXJjZW50PTEwMCwgdW5vdXQ9ImhhIikNCm1jcC5wb2x5IDwtIGZvcnRpZnkobWNwLm91dCkNCmBgYA0KDQpJbiB0aGUgc2NyaXB0IGFib3ZlIHlvdSBjYW4gc2VlIHRoZSBhcmVhIG9mIHRoZSBfbWluaW11bSBjb252ZXggcG9seWdvbl8gaXMgYmVpbmcgbWVhc3VyZWQgaW4gaGVjdGFyZXMuIFRvIGRldGVybWluZSB0aGUgYXJlYSBvZiB0aGUgX01DUF8geW91IGNhbiB0eXBlIGBgYG1jcC5vdXQkYXJlYWBgYCB0byBwcmludCB0aGUgbWVhc3VyZW1lbnQuDQoNCldoaWxlIHRoZSBfTUNQXyBjcmVhdGVzIGEgc2luZ2xlIGJvdW5kaW5nIHBvbHlnb24sIF9rZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZXNfIG9mdGVuIGFyZSB1c2VkIHRvIGNyZWF0ZSBtdWx0aXBsZSBwb2x5Z29ucyB0aGF0IGNhbiBiZSB1c2VkIHNpbWlsYXIgdG8gYSBfaG90cHNvdCBhbmFseXNpc18uIFRoaXMgcmVxdWlyZXMgYSBmZXcgYWRkaXRpb25hbCBzdGVwcyBhcyBjb21wYXJlZCB0byB0aGUgX01DUF8gZXhhbXBsZSBhYm92ZS4gQmVmb3JlIGNvbnZlcnRpbmcgdGhlIF9TcGF0aWFsUG9seWdvbnNEYXRhZnJhbWVfIHlvdSB3aWxsIG5lZWQgdG8gY3JlYXRlIG11bHRpcGxlIGVzdGltYXRlcyBmcm9tIHRoZSBkYXRhc2V0IGJ5IHZhcnlpbmcgdGhlIHBlcmNlbnRhZ2UgbGV2ZWwgZm9yIHRoZSBob21lIHJhbmdlIGVzdGltYXRpb24uIEVzc2VudGlhbGx5LCBoaWdoZXIgcGVyY2VudGFnZSBsZXZlbHMgd2lsbCBlbmNvbXBhc3MgYXJlYXMgd2l0aCB2ZXJ5IGZldyByZWxvY2F0aW9ucyBhbmQgbG93ZXIgcGVyY2VudGFnZSBsZXZlbHMgd2lsbCBlbmNvbXBhc3MgYXJlYXMgd2l0aCBhIGRlbnNlIG51bWJlciBvZiByZWxvY2F0aW9ucy4gRm9yIHRoaXMgYW5hbHlzaXMgeW91IHdpbGwgY3JlYXRlIGVzdGltYXRlcyBiYXNlZCBvbjoNCg0KLSAxMDAlIGxldmVsID0gaW5jbHVkZXMgbG93IHRvIHZlcnkgaGlnaCBsZXZlbHMgb2YgcmVsb2NhdGlvbnMNCi0gNzUlIGxldmVsID0gaW5jbHVkZXMgbW9kZXJhdGUgdG8gdmVyeSBoaWdoIGxldmVscyBvZiByZWxvY2F0aW9ucw0KLSA1MCUgbGV2ZWwgPSBpbmNsdWRlcyBoaWdoIHRvIHZlcnkgaGlnaCBsZXZlbHMgb2YgcmVsb2NhdGlvbnMNCi0gMjUlIGxldmVsID0gaW5jbHVkZXMgb25seSB2ZXJ5IGhpZ2ggbGV2ZWwgb2YgcmVsb2NhdGlvbnMNCg0KT25jZSB0aGVzZSBlc3RpbWF0ZXMgYXJlIGNyZWF0ZWQgeW91IHdpbGwgbmVlZCB0byBgYGBmb3J0aWZ5YGBgIGVhY2ggb2YgdGhlIHBvbHlnb25zIHNvIHRoZXkgY2FuIGJlIGRpc3BsYXllZCB3aXRoIGBgYGdncGxvdDJgYGAuDQoNCmBgYHtyIGNyZWF0ZSBrZGVzLCBlY2hvPVRSVUUsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0Ka2RlIDwtIGtlcm5lbFVEKHh5LCBoPTIwMDAsIGtlcm49ImVwYSIsIGdyaWQ9MTAwKQ0Ka2RlMTAwIDwtIGdldHZlcnRpY2VzaHIoa2RlLCAxMDAsIHVub3V0PSJoYSIpDQprZGU3NSA8LSBnZXR2ZXJ0aWNlc2hyKGtkZSwgNzUsIHVub3V0PSJoYSIpDQprZGU1MCA8LSBnZXR2ZXJ0aWNlc2hyKGtkZSwgNTAsIHVub3V0PSJoYSIpDQprZGUyNSA8LSBnZXR2ZXJ0aWNlc2hyKGtkZSwgMjUsIHVub3V0PSJoYSIpDQprZGUucG9seTEwMCA8LSBmb3J0aWZ5KGtkZTEwMCkNCmtkZS5wb2x5NzUgPC0gZm9ydGlmeShrZGU3NSkNCmtkZS5wb2x5NTAgPC0gZm9ydGlmeShrZGU1MCkNCmtkZS5wb2x5MjUgPC0gZm9ydGlmeShrZGUyNSkNCmBgYA0KDQpJbiB0aGVzZSBLREUgc2NyaXB0cyB5b3UgY2FuIHByaW50IHRoZSBhcmVhIChoZWN0YXJlcykgb2YgYW55IHBvbHlnb24gYnkgdHlwaW5nIGBgYGtkZSMjJGFyZWFgYGAsIHdoZXJlICMjIGlzIHRoZSBfa2RlXyB2YWx1ZSBmcm9tIHRoZSBzY3JpcHRzIGFib3ZlLiBWaWV3aW5nIHRoZSBhcmVhIG9mICoqa2RlMTAwKiogd2lsbCBhbGxvdyB5b3UgdG8gdmlldyB0aGUgZW50aXJlIGFyZWEgZXN0aW1hdGVkIGJ5IHRoZSBhbmFseXNpcyBzaW5jZSBpdCBpbmNsdWRlcyBhbGwgbGV2ZWxzIG9mIHJlbG9jYXRpb24uDQoNCioqUXVlc3Rpb24gTm8uIDIqKg0KPGJsb2NrcXVvdGU+DQpXaGF0IGlzIHRoZSBhcmVhIG9mIHRoZSBNaW5pbXVtIENvbnZleCBQb2x5Z29uPzxicj4NCldoYXQgaXMgdGhlIGFyZWEgb2YgdGhlIEtlcm5lbCBEZW5zaXR5IEVzdGltYXRpb24/DQo8L2Jsb2NrcXVvdGU+DQo8L2RldGFpbHM+DQoNCiMjIFN0ZXAgVGhyZWU6IFRoZSBWaXN1YWxpemF0aW9uDQoNCkluIG9yZGVyIHRvIHZpZXcgb3VyIGRhdGEgX2luIHNpdHVfIHdlIG5lZWQgdG8gYWRkIGEgYmFzZW1hcCB0byBvdXIgdmlldy4gVGhpbmsgYWJvdXQgYWxsIG9mIHRoZSBwb3NzaWJsZSBiYXNlbWFwcyB5b3UgY2FuIGFkZCBzdWNoIGFzIHRvcG8gb3IgdGVycmFpbiBtYXBzLCBvciBldmVuIHNhdGVsbGl0ZSBpbWFnZXJ5Lg0KDQo8ZGV0YWlscz48c3VtbWFyeT48YmlnPlZpZXcgZGlyZWN0aW9ucyBpbiA8Yj4gW0FyY0dJUyBQcm9de3N0eWxlPSJjb2xvcjojZmY0NTAwIn0gPC9iPjwvc3Bhbj48L2JpZz48L3N1bW1hcnk+DQoNCkl0IHdpbGwgYmUgaW1wb3J0YW50IHRvIHNlbGVjdCBhbiBhcHByb3ByaWF0ZSBiYXNlbWFwIGZvciB5b3VyIHZpc3VhbGl6YXRpb24uIExvb2sgdGhyb3VnaCB0aGUgb3B0aW9ucyBhdmFpbGFibGUgaW4gdGhlIF9CYXNlbWFwXyBkcm9wLWRvd24gbWVudSBvbiB0aGUgTWFwIFRhYiBhbmQgZGV0ZXJtaW5lIHdoaWNoIHdpbGwgcHJvdmlkZSB0aGUgYmVzdCB2aXN1YWxpemF0aW9uIG9mIHRoZSBkYXRhIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiBkaXNwbGF5aW5nLiANCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLWJhc2VtYXBzLnBuZyIgYWx0PSJCYXNlbWFwIE9wdGlvbnMiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCioqUXVlc3Rpb24gTm8uIDMqKg0KPGJsb2NrcXVvdGU+DQpXaGF0IHN0ZXBzIHdvdWxkIHlvdSB0YWtlIHRvIGFkZCBhbmQgZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIHRoZSBpbmRpdmlkdWFsIGNvdWdhcnMgaW4gYSB2aXN1YWxpemF0aW9uPw0KPC9ibG9ja3F1b3RlPg0KDQo8L2RldGFpbHM+DQoNCjxocj48L2hyPg0KDQo8ZGV0YWlscz48c3VtbWFyeT48YmlnPlZpZXcgZGlyZWN0aW9ucyBpbiA8Yj4gW1FHSVNde3N0eWxlPSJjb2xvcjojMDA2NDAwIn0gPC9iPjwvc3Bhbj48L2JpZz48L3N1bW1hcnk+DQpJbiBhIHByZXZpb3VzIGV4ZXJjaXNlIHlvdSBhZGRlZCBYWVogdGlsZXMgdG8geW91ciBRR0lTIEJyb3dzZXIuIFJlbWVtYmVyIHRvIGFkZCBuZXcgdGlsZXMgc3VjaCBhcyAqKkVTUkkgU2F0ZWxsaXRlIEltYWdlcnkqKiB0byB5b3VyIGJyb3N3ZXIgeW91IG5lZWQgdG8gUmlnaHQtQ2xpY2sgKENSVEwrY2xpY2sgb24gTWFjKSBvbiBfWFlaIFRpbGVzXyBhbmQgY2xpY2sgKioiTmV3IENvbm5lY3Rpb24iKiogYW5kIGFkZCB0aGUgZm9sbG93aW5nIFVSTDoNCg0KYGBgDQpodHRwczovL3NlcnZlci5hcmNnaXNvbmxpbmUuY29tL0FyY0dJUy9yZXN0L3NlcnZpY2VzL1dvcmxkX0ltYWdlcnkvTWFwU2VydmVyL3RpbGUve3p9L3t5fS97eH0NCmBgYA0KDQpJbiBbRXhlcmNpc2UgNiwgU3RlcCAxXShodHRwczovL2NocmlzbWdlbnRyeS5naXRodWIuaW8vR0lTMS1FeGVyY2lzZS02LyMxMV9TdGVwX09uZTpfVGhlX0RhdGEpIHlvdSB3ZXJlIHByb3ZpZGVkIHdpdGggZGlyZWN0aW9ucyB0byBjcmVhdGUgY29ubmVjdGlvbnMgZm9yIHNhdGVsbGl0ZSBpbWFnZXJ5LCBzdHJlZXQgbWFwcywgYW5kIHRvcG9ncmFwaGljIG1hcHMuIFJlbWVtYmVyIHRvIGFycmFuZ2UgeW91ciBsYXllcnMgc28gdGhhdCB5b3UgY2FuIHZpc3VhbGl6ZSBhbGwgb2YgdGhlIGRhdGEgeW91IGFyZSBpbnRlcmVzdGVkIGluIGV4YW1pbmluZy4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGltZyBzcmM9ICJJbWFnZXMvcWdpc19vdXRwdXQucG5nIiBhbHQ9IlFHSVMgT3V0cHV0IiB3aWR0aD0iNjgwIiBoZWlnaHQ9IjM1MCI+PC9wPg0KDQoqKlF1ZXN0aW9uIE5vLiAzKioNCjxibG9ja3F1b3RlPg0KV2hhdCBzdGVwcyB3b3VsZCB5b3UgdGFrZSB0byBhZGQgYW5kIGRpZmZlcmVudGlhdGUgYmV0d2VlbiB0aGUgaW5kaXZpZHVhbCBjb3VnYXJzIGluIGEgdmlzdWFsaXphdGlvbj8NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KDQo8aHI+PC9ocj4NCg0KPGRldGFpbHM+PHN1bW1hcnk+PGJpZz5WaWV3IGRpcmVjdGlvbnMgaW4gPGI+IFtSXXtzdHlsZT0iY29sb3I6IzY0OTVFRCJ9IDwvYj48L3NwYW4+PC9iaWc+PC9zdW1tYXJ5Pg0KVG8gb2J0YWluIGltYWdlcnkgZm9yIHRoaXMgcHJvamVjdCB5b3UgYXJlIGFnYWluIGdvaW5nIHRvIHVzZSBgYGBPcGVuU3RyZWV0TWFwYGBgIHRvIGNvbm5lY3QgdG8gKipCaW5nIEFlcmlhbCBJbWFnZXJ5KiouIEFsdGhvdWdoIHlvdSB1c2VkIHRoZSBVVE0gdmFsdWVzIGZvciB0aGUgYW5hbHlzaXMsIF9PcGVuU3RyZWV0TWFwXyBvbmx5IHVzZXMgZ2VvZ3JhcGhpYyBjb29yZGluYXRlcyBmb3IgdGhlaXIgaW1hZ2VyeS4gU28geW91IHdpbGwgb2J0YWluIHRoZSBpbWFnZSBmaXJzdCBhbmQgdGhlbiByZXByb2plY3QgaXQgdG8gdGhlIGFwcHJvcHJpYXRlIFVUTSB6b25lLg0KDQpJbiB0aGUgZm9sbG93aW5nIHNjcmlwdCB5b3Ugd2lsbCBiZSB1c2luZyB0aGUgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZXMgZnJvbSBfY291Z2Fyc18gbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSBjb2x1bW5zIHRvIHNldCB0aGUgYm91bmRpbmcgY29vcmRpbmF0ZXMuIFRvIGF2b2lkIGFueSBwb2ludCBiZWluZyBsb2NhdGVkIG9uIHRoZSBlZGdlIG9mIHRoZSBpbWFnZSB3ZSBhcmUgZ29pbmcgdG8gYWRkIGEgMC4wNSBkZWdyZWUgYnVmZmVyIHRvIGVhY2ggdmFsdWUuIA0KDQpgYGB7ciBPU00gaW1hZ2VyeSwgZWNobz1UUlVFLCByZXN1bHRzPSdoaWRlJywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmltYWdlcnkgPC0gb3Blbm1hcChjKG1heChjb3VnYXJzJGxhdCswLjA1KSxtaW4oY291Z2FycyRsb25nLTAuMDUpKSwNCiAgICAgICAgICAgICAgICAgICBjKG1pbihjb3VnYXJzJGxhdC0wLjA3KSxtYXgoY291Z2FycyRsb25nKzAuMDUpKSwNCiAgICAgICAgICAgICAgICAgICB0eXBlID0gImJpbmciKQ0KYGBgDQoNCk5vdyB5b3Ugd2lsbCBjb252ZXJ0IHRoZSBpbWFnZXJ5IHByb2plY3Rpb24gZnJvbSBnZW9ncmFwaGljIGNvb3JkaW5hdGVzIHRvIFVUTSBab25lIDEyLg0KDQpgYGB7ciBSZXByb2plY3QgT1NNLCBlY2hvPVRSVUUsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KaW1hZ2VyeV91dG0gPC0gb3BlbnByb2ooaW1hZ2VyeSwgDQogICAgICAgICAgICAgICAgICAgICAgICBwcm9qZWN0aW9uID0gIitwcm9qPXV0bSArem9uZT0xMiArZGF0dW09V0dTODQgK3VuaXRzPW0gK25vX2RlZnMiKQ0KYGBgDQogICAgICAgICAgICAgICAgICAgICAgICANCldpdGggdGhpcyBpbWFnZXJ5IG5vdyB5b3UgY2FuIHBsb3QgdGhlIF9NQ1BfIGFuZCBfS0RFXyBwb2x5Z29ucyBhcyB3ZWxsIGFzIHRoZSBkYXRhIHBvaW50cyBpZiBuZWNlc3NhcnkuDQoNCmBgYHtyIG1hcCwgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KYXV0b3Bsb3QuT3BlblN0cmVldE1hcChpbWFnZXJ5X3V0bSwgZXhwYW5kID0gVFJVRSkgKyANCnRoZW1lX2J3KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KZ2VvbV9wb2x5Z29uKGRhdGEgPSBrZGUucG9seTEwMCwgYWVzKHg9bG9uZywgeT1sYXQsIGdyb3VwPWdyb3VwKSwgY29sb3IgPSBOQSwgZmlsbCA9ICdsaWdodHllbGxvdycpICsNCmdlb21fcG9seWdvbihkYXRhID0ga2RlLnBvbHk3NSwgYWVzKHg9bG9uZywgeT1sYXQsIGdyb3VwPWdyb3VwKSwgY29sb3IgPSBOQSwgZmlsbCA9ICdnb2xkJykgKw0KZ2VvbV9wb2x5Z29uKGRhdGEgPSBrZGUucG9seTUwLCBhZXMoeD1sb25nLCB5PWxhdCwgZ3JvdXA9Z3JvdXApLCBjb2xvciA9IE5BLCBmaWxsID0gJ2RhcmtvcmFuZ2UnKSArDQpnZW9tX3BvbHlnb24oZGF0YSA9IGtkZS5wb2x5MjUsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGNvbG9yID0gTkEsIGZpbGwgPSAnZGFya3JlZCcpICsNCmdlb21fcG9seWdvbihkYXRhID0gbWNwLnBvbHksIGFlcyh4PWxvbmcsIHk9bGF0KSwgY29sb3IgPSAicmVkIiwgZmlsbCA9IE5BLCBhbHBoYSA9IDAuOCwgc2l6ZSA9IDEpICsNCmdlb21fcG9pbnQoZGF0YSA9IGNvdWdhcnMsIGFlcyh4PXV0bV9lYXN0LCB5PXV0bV9ub3J0aCksIGFscGhhID0gMC4xKSArDQpsYWJzKHg9IkVhc3RpbmciLCB5PSJOb3J0aGluZyIpICsgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCgiSWRlbnRpZmllciIpKSArDQp0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsNCnRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwLCBoanVzdD0wLjUpKQ0KYGBgDQoNCioqUXVlc3Rpb24gTm8uIDMqKg0KPGJsb2NrcXVvdGU+DQpXaGF0IHN0ZXBzIHdvdWxkIHlvdSB0YWtlIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiB0aGUgaW5kaXZpZHVhbCBjb3VnYXJzIGluIHRoaXMgdmlzdWFsaXphdGlvbj8NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KDQojIyBTdGVwIEZvdXI6IFRoZSBUcmFpbA0KDQpOb3cgdGhhdCB5b3UgaGF2ZSBhbGwgb2YgdGhlIGRhdGEgbmVjZXNzYXJ5IHRvIGRldGVybWluZSB0aGUgZmVhc2liaWxpdHkgb2YgdGhlICoqIkdyYXNzIFZhbGxleSBUcmFpbCIqKiwgeW91IG5lZWQgdG8gYWRkIHRoZSBwcm9wb3NlZCB0cmFpbCB0byBhc3Nlc3MgdGhlIGltcGFjdCBpdCBtYXkgaGF2ZSBvbiB0aGUgY291Z2FyIHBvcHVsYXRpb24uDQoNCjxkZXRhaWxzPjxzdW1tYXJ5PjxiaWc+VmlldyBkaXJlY3Rpb25zIGluIDxiPiBbQXJjR0lTIFByb117c3R5bGU9ImNvbG9yOiNmZjQ1MDAifSA8L2I+PC9zcGFuPjwvYmlnPjwvc3VtbWFyeT4NCkluIHRoZSBmaXJzdCBzdGVwIHlvdSBzaG91bGQgaGF2ZSBkb3dubG9hZGVkIHRoZSAqKmhpa2luZ190cmFpbHMqKiBkYXRhc2V0IGZyb20gR2l0SHViLiBJZiB5b3Ugc2tpcHBlZCB0aGF0IHN0ZXAgeW91IHdpbGwgbmVlZCB0byBkb3dubG9hZCB0aGUgPGEgaHJlZj0iaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2NocmlzbWdlbnRyeS9HSVMxLUV4ZXJjaXNlLTkvbWFpbi9EYXRhL2hpa2luZ190cmFpbC5jc3YiIHRhcmdldD0iX2JsYW5rIj5kYXRhc2V0PC9hPiBub3cuIFNpbWlsYXIgdG8gW1N0ZXAgMV0oaHR0cHM6Ly9jaHJpc21nZW50cnkuZ2l0aHViLmlvL0dJUzEtRXhlcmNpc2UtOS8jMTFfU3RlcF9PbmU6X1RoZV9EYXRhKSBvbiB0aGUgTWFwIFRhYiBnbyB0byBfQWRkIERhdGEgLT4gWFkgUG9pbnQgRGF0YV8uIEJlIHN1cmUgdGhlIGNvb3JkaW5hdGUgc3lzdGVtIGlzIHNldCBhcHByb3ByaWF0ZSBmb3IgdGhlIGRhdGEuIEluIF9Ub29sc18gc2VhcmNoIGZvciAqKlBvaW50cyB0byBMaW5lKiogYW5kIHNlbGVjdCB0aGUgZG93bmxvYWRlZCBDU1YgZmlsZSBhcyB0aGUgX0lucHV0IEZlYXR1cmVzXywgbmF2aWdhdGUgdG8geW91ciBwcm9qZWN0IGZvbGRlciBhbmQgc2F2ZSB0aGUgLnNocCBmaWxlIGluIHRoZSBfT3V0cHV0IEZlYXR1cmUgQ2xhc3NfLiBMZWF2ZSB0aGUgX0xpbmUgRmllbGRfIGJsYW5rIGFuZCBzZXQgdGhlIF9Tb3J0IEZpZWxkXyB0byBub2RlIGFuZCBjbGljayBSdW4uDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1wb2ludC10by1saW5lLnBuZyIgYWx0PSJQb2ludHMgdG8gTGluZSIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KTm93IHlvdSBzaG91bGQgaGF2ZSBhIGxpbmUgcmVwcmVzZW50aW5nIHRoZSBwcm9wb3NlZCAqKkdyYXNzIFZhbGxleSBUcmFpbCoqIHRoYXQgeW91IGNhbiBzdHlsZSBhcHByb3ByaWF0ZWx5IHRvIGhlbHAgZXhhbWluZSBhbGwgb2YgdGhlIGRhdGEuDQoNCioqUXVlc3Rpb24gTm8uIDQqKg0KPGJsb2NrcXVvdGU+DQpEb2VzIHRoZSB0cmFpbCBjcm9zcyBhbnkgYXJlYXMgY2FsY3VsYXRlZCBhcyBfaGlnaF8gb3IgX3ZlcnkgaGlnaF8gdXNlIGJhc2VkIG9uIHRoZSBfS0RFXyBhbmFseXNpcz8NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KDQo8aHI+PC9ocj4NCg0KPGRldGFpbHM+PHN1bW1hcnk+PGJpZz5WaWV3IGRpcmVjdGlvbnMgaW4gPGI+IFtRR0lTXXtzdHlsZT0iY29sb3I6IzAwNjQwMCJ9IDwvYj48L3NwYW4+PC9iaWc+PC9zdW1tYXJ5Pg0KSW4gdGhlIGZpcnN0IHN0ZXAgeW91IHNob3VsZCBoYXZlIGRvd25sb2FkZWQgdGhlICoqaGlraW5nX3RyYWlscyoqIGRhdGFzZXQgZnJvbSBfR2l0SHViXy4gSWYgeW91IHNraXBwZWQgdGhhdCBzdGVwIHlvdSB3aWxsIG5lZWQgdG8gZG93bmxvYWQgdGhlIFtkYXRhc2V0XShodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vY2hyaXNtZ2VudHJ5L0dJUzEtRXhlcmNpc2UtOS9tYWluL0RhdGEvaGlraW5nX3RyYWlsLmNzdikgbm93LiBTaW1pbGFybHkgdG8gc3RlcCBvbmUsIHRoZSBkYXRhIGlzIGZvcm1hdHRlZCBhcyBhIF9cLmNzdl8gZmlsZSBzbyB5b3Ugd2lsbCBuZWVkIHRvIHVzZSBfQWRkIERlbGltaXRlZCBUZXh0IExheWVyXyA8aW1nIHNyYz0gIkltYWdlcy9jc3ZfaW1hZ2UucG5nIiBhbHQ9IkFkZCBEZWxpbWl0ZWQgVGV4dCBMYXllciIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIj4gdG8gaW1wb3J0IHRoZSBkYXRhc2V0LiBPbmNlIGFkZGVkIHRvIHlvdXIgbGF5ZXJzIHlvdSBjYW4gdXNlIHRoZSAqKnBvaW50cyB0byBwYXRoKiogdG9vbCBsb2NhdGVkIGluIF9WZWN0b3IgY3JlYXRpb25fIGluIHRoZSBfUHJvY2Vzc2luZyBUb29sYm94Xy4gSW4gdGhlIF9JbnB1dCBwb2ludCBsYXllcl8gcGFyYW1ldGVyIGNob29zZSB0aGUgKipoaWtpbmdfdHJhaWwqKiBkYXRhc2V0IGFuZCBpbiBfT3JkZXIgZmllbGRfIGNob29zZSAqKm5vZGUqKi4gWW91IGNhbiBsZWF2ZSB0aGUgcmVtYWluZGVyIG9mIHRoZSBvcHRpb25zIGFzIGRlZmF1bHQgYW5kIGNsaWNrICoqUnVuKiouDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxpbWcgc3JjPSAiSW1hZ2VzL3FnaXNfcDJwLnBuZyIgYWx0PSJRR0lTIE91dHB1dCIgd2lkdGg9IjQ4MiIgaGVpZ2h0PSIzODciPjwvcD4NCg0KTm93IHlvdSBzaG91bGQgaGF2ZSBhIGxpbmUgcmVwcmVzZW50aW5nIHRoZSBwcm9wb3NlZCAqKkdyYXNzIFZhbGxleSBUcmFpbCoqIHRoYXQgeW91IGNhbiBzdHlsZSBhcHByb3ByaWF0ZWx5IHRvIGhlbHAgZXhhbWluZSBhbGwgb2YgdGhlIGRhdGEuDQoNCioqUXVlc3Rpb24gTm8uIDQqKg0KPGJsb2NrcXVvdGU+DQpEb2VzIHRoZSB0cmFpbCBjcm9zcyBhbnkgYXJlYXMgY2FsY3VsYXRlZCBhcyBfaGlnaF8gb3IgX3ZlcnkgaGlnaF8gdXNlIGJhc2VkIG9uIHRoZSBfS0RFXyBhbmFseXNpcz8NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KDQo8aHI+PC9ocj4NCg0KPGRldGFpbHM+PHN1bW1hcnk+PGJpZz5WaWV3IGRpcmVjdGlvbnMgaW4gPGI+IFtSXXtzdHlsZT0iY29sb3I6IzY0OTVFRCJ9IDwvYj48L3NwYW4+PC9iaWc+PC9zdW1tYXJ5Pg0KU2ltaWxhcmx5IHRvIHN0ZXAgb25lLCB5b3UgYXJlIGdvaW5nIHRvIHVzZSBgYGByZWFkLmNzdmBgYCBhbmQgYSBVUkwgZnJvbSBHaXRIdWIgdG8gaW1wb3J0IHRoZSBkYXRhIGZvciB0aGUgcHJvcG9zZWQgKioiR3Jhc3MgVmFsbGV5IFRyYWlsIioqLg0KDQpgYGB7ciBoaWtpbmcgdHJhaWwsIGVjaG89VFJVRSwgcmVzdWx0cz0iaGlkZSIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQp0cmFpbCA8LSByZWFkLmNzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2NocmlzbWdlbnRyeS9HSVMxLUV4ZXJjaXNlLTkvbWFpbi9EYXRhL2hpa2luZ190cmFpbC5jc3YnKQ0KYGBgDQoNCkluIHRoZSBwcmV2aW91cyBzdGVwIHlvdSBjcmVhdGVkIGEgdmlzdWFsaXphdGlvbiB0aGF0IGFsbG93ZWQgeW91IHRvIG92ZXJsYXkgdGhlIF9NQ1BfIGFuZCBfS0RFXyBwb2x5Z29ucyBvbiBhZXJpYWwgaW1hZ2VyeSBhcyB3ZWxsIGFzIHRoZSByZWxvY2F0aW9ucy4gVG8gY29udmVydCB0aGUgKioiR3Jhc3MgVmFsbGV5IFRyYWlsIioqIGltcG9ydCBmcm9tIGFib3ZlLCB3aGljaCBpcyBwb2ludCBkYXRhLCB0byBhIGxpbmUsIHlvdSBuZWVkIHRvIGFkZCB0aGUgZm9sbG93aW5nIHNjcmlwdCB0byB2aXN1YWxpemF0aW9uIGZyb20gYWJvdmU6DQoNCmBgYA0KZ2VvbV9wYXRoKGRhdGEgPSB0cmFpbCwgYWVzKHggPSB4ICx5ID0geSksIHNpemUgPSAxLCBsaW5ldHlwZSA9IDEpDQpgYGANClJlbWVtYmVyLCBgYGBnZ3Bsb3QyYGBgIGRyYXdzIGVhY2ggbGF5ZXIgb3ZlciB0aGUgcHJldmlvdXMuIFNvIGlmIHlvdSB3YW50IHRoZSBwcm9wb3NlZCB0cmFpbCB0byBiZSB0aGUgdG9wIGxheWVyLCBpdCBzaG91bGQgYmUgdGhlIGxhc3Qgb25lIGRyYXduLg0KDQpgYGB7ciBtYXAgd2l0aCB0cmFpbCwgZXZhbD1GQUxTRSwgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCmF1dG9wbG90Lk9wZW5TdHJlZXRNYXAoaW1hZ2VyeV91dG0sIGV4cGFuZCA9IFRSVUUpICsgDQp0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCmdlb21fcG9seWdvbihkYXRhID0ga2RlLnBvbHkxMDAsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGNvbG9yID0gTkEsIGZpbGwgPSAnbGlnaHR5ZWxsb3cnKSArDQpnZW9tX3BvbHlnb24oZGF0YSA9IGtkZS5wb2x5NzUsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGNvbG9yID0gTkEsIGZpbGwgPSAnZ29sZCcpICsNCmdlb21fcG9seWdvbihkYXRhID0ga2RlLnBvbHk1MCwgYWVzKHg9bG9uZywgeT1sYXQsIGdyb3VwPWdyb3VwKSwgY29sb3IgPSBOQSwgZmlsbCA9ICdkYXJrb3JhbmdlJykgKw0KZ2VvbV9wb2x5Z29uKGRhdGEgPSBrZGUucG9seTI1LCBhZXMoeD1sb25nLCB5PWxhdCwgZ3JvdXA9Z3JvdXApLCBjb2xvciA9IE5BLCBmaWxsID0gJ2RhcmtyZWQnKSArDQpnZW9tX3BvbHlnb24oZGF0YSA9IG1jcC5wb2x5LCBhZXMoeD1sb25nLCB5PWxhdCksIGNvbG9yID0gInJlZCIsIGZpbGwgPSBOQSwgYWxwaGEgPSAwLjgsIHNpemUgPSAxKSArDQpnZW9tX3BhdGgoZGF0YSA9IHRyYWlsLCBhZXMoeCA9IHggLHkgPSB5KSwgc2l6ZSA9IDEsIGxpbmV0eXBlID0gMSkgKw0KbGFicyh4PSJFYXN0aW5nIiwgeT0iTm9ydGhpbmciKSArIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQoIklkZW50aWZpZXIiKSkgKw0KdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArDQp0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCwgaGp1c3Q9MC41KSkNCmBgYA0KDQoqKlF1ZXN0aW9uIE5vLiA0KioNCjxibG9ja3F1b3RlPg0KRG9lcyB0aGUgdHJhaWwgY3Jvc3MgYW55IGFyZWFzIGNhbGN1bGF0ZWQgYXMgX2hpZ2hfIG9yIF92ZXJ5IGhpZ2hfIHVzZSBiYXNlZCBvbiB0aGUgX0tERV8gYW5hbHlzaXM/DQo8L2Jsb2NrcXVvdGU+DQoNCjwvZGV0YWlscz4NCg0KIyBUaGUgRGVjaXNpb24NClJlY2FsbCB0aGF0IF9HcmFzcyBWYWxsZXkgVHJhaWwgQ29tbWl0dGVlXyBoYXMgYXNrZWQgeW91IHRvIGFzc2VzcyB0aGUgaW1wYWN0IG9mIHRoZSBwcm9wb3NlZCBoaWtpbmcgdHJhaWwgb24gdGhlIG1vdW50YWluIGxpb24gaGFiaXRhdCBhbmQgcG90ZW50aWFsIHJpc2sgdG8gdmlzaXRvcnMuIEJhc2VkIG9uIHRoZSBhbmFseXNlcyBhYm92ZSwgY29tcGxldGUgYSBsYWIgd3JpdGUtdXAgdGhhdCBhZGRyZXNzZXMgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6DQoNCi0gRXhwbGFpbiB0byB0aGUgY29tbWl0dGVlIHRoZSBwcm9jZXNzIHlvdSB1c2VkIHRvIGRldGVybWluZSB0aGUgcmlza3Mgb2YgdGhlIHByb3Bvc2VkIHRyYWlsLg0KLSBEZXNjcmliZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gdHlwZXMgb2YgaG9tZSByYW5nZSBhbmFseXNlcy4gSG93IHdvdWxkIHRoaXMgcG90ZW50aWFsbHkgaW1wYWN0IHRoZSBkZWNpc2lvbnMgbWFkZSBieSB0aGUgY29tbWl0dGVlPyANCi0gV2hhdCBwb3J0aW9uIG9mIHRoZSBwcm9wb3NlZCB0cmFpbCBoYXMgdGhlIGhpZ2hlc3QgbGlrZWxpaG9vZCB0byB0cmF2ZXJzZSBhcmVhcyBvZiB0aGUgX1NldmllciBQbGF0ZWF1XyB0aGF0IGFyZSBmcmVxdWVudGx5IChoaWdoIHRvIHZlcnkgaGlnaCBjYXRlZ29yaWVzKSB1c2VkIGJ5IHRoZSB0cmFja2VkIGNvdWdhcnM/DQoNCkZpbmFsbHksIHByb3ZpZGUgYSByZWNvbW1lbmRhdGlvbiBmb3IgdGhlIGNvbW1pdHRlZSBvbiBob3cgdGhlIHByb3Bvc2VkIHRyYWlsIGNhbiBiZSBjb21wbGV0ZWQgd2l0aCBhcyBsaXR0bGUgaW50ZXJhY3Rpb24gYXMgcG9zc2libGUgd2l0aCB0aGUgY291Z2FyIGhhYml0YXQuIEluY2x1ZGUgeW91ciBtYXAgdGhhdCBoZWxwcyBwcm92aWRlIGFkZGl0aW9uYWwgZGV0YWlscyBmb3IgeW91ciByZWNvbW1lbmRhdGlvbi4=