The purpose of this exercise is to help familiarize you with some of the Geoprocessing Tools available in the various programs. These tools will help you to simplify, organize, and reduce the amount of information and allow you to create additional base maps from existing data.

1 The Introduction

The Federal Emergency Management Agency  (FEMA) is in the process of planning for the federal distribution of resources related to natural disasters in the US. As hurricane season approaches predictions are suggesting a very active season in the Atlantic Basin. As a FEMA analyst, you have been tasked with examining hurricane paths over the last five years that have impacted the Southeastern US. This information will be used to develop a plan for the establishment of temporary relief shelters, supply storage facilities, and mobile medical services that will be necessary in the hardest hit areas.

In this exercise you will:

  • Use various methods of geoprocessing
  • Create derived datasets
  • Adjust the coordinate systems
  • Create inset maps
  • Use the attribute table for labeling

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

The data you will be using for this exercise comes from the National Oceanic and Atmospheric Administration - Office for Coastal Management, Historical Hurricane Tracks interactive map. Information on the site is derived from the NOAA National Hurricane Center HURDAT2 and NOAA National Centers for Environmental Information IBTrACS data sets.

View Directions in ArcGIS Pro

As you have done with each of the previous exercises, Exercise 2 and Exercise 3, you will begin by launching ArcGIS Pro from the start menu or dekstop shortcut. Select Map from New > Blank Templates and on the resulting screen provide a name and location for your project. Remember it would be beneficial to keep all of these exercises in a single folder on your computer.

With your screen now displaying the World Topographic Map  and World Hillshade  in the table of contents, navigate to GitHub and download all datasets for this exercise here to your project folder and extract the data. If you have any questions on how to retrieve and extract the data refer to Exercise 2, Step 1 for detailed instructions.

Add the states, counties, and all hurricanes  datasets to the map view. Remember that the layers in your Table of Contents  are drawn in the order they appear. So the first item on the list will be the first show, followed, by the second and so on. Therefore, if you want certain datasets to be visible above all others it should be located at the top by clicking and dragging the data up or down in the list. For polygons, you can edit the fill and transparency (found under the appearance tab in effects) to allow for items underneath to be scene. For example, in the image below, the hurricane tracks are ordered by year and are situated on top of the county and state polygons. If the polygons were drawn first, the hurricane tracks would not be shown once they make landfall. In this example, the states polygons are displayed with a hollow fill and white border to allow for the counties to show through with their black borders.

Ex4 Datasets

Refer back to previous exercises to review how to change the symbology for a given dataset. You should experiment with different order, fill, and transparencies to customize your view of the data.

Because FEMA is only interested in counties impacted by hurricanes, you need to select only the states that are intersected by the tracks. There are several ways to subset data in ArcGIS Pro. For this example we can select counties by name through a structured query language (SQL), we can use graphical tools to select data, and we can use geoprocessing tools to subset the data. Because this is a learning module, you will be learning several different techniques. While this might not necessarily be the quickest method, the purpose of this exercise is to introduce you to several tools you can use as appropriate in future projects.

To continue gathering data for this exercise you are first going to isolate the data you want to select. In the Table of Contents click the List by Selection button List by Selection to show a list of the selectable datasets in the project. Because you should have a number of datasets in the project, to isolate only the states file, right-click on the USA_States_Continental  and chose “Make this the only selectable layer”.

Make data selectable

To begin, click the drop-down menu for Select  on the Map Tab  and choose Lasso from the drop-down menu and and use the cursor to draw a circle encompassing Alabama, Arkansas, Delaware, Florida, Georgia, Illinois, Indiana, Kentucky, Louisiana, Maryland, Mississippi, Missouri, New Jersey, North Carolina, Ohio, Pennsylvania, South Carolina, Tennessee, Virginia, and West Virginia. Your circle does not need to include all of the state, just a small portion. See the example below:

Lasso Select Tool

With the states selected, return the Table of Contents to the “List by Drawing Order” button List by Drawing Order and right-click on the USA_States_Continental  dataset and choose Data > Export Features from the menu. In the resulting menu include the following options and click OK:

  • Input Features = USA_States_Continental
  • Output Location = Select a folder for the export. It it important that you do not click into the folder, simply click once to select and click OK (see example).
  • Output Name = choose a name for your file and add .shp behind it to create a shapefile.

Export Data

When finished you should have the file added to your project. Another technique to isolate data is by using the Clip analysis tool. This tool can be used to cut out a piece of one dataset using one or more of the features in another dataset as a “cookie cutter”. This is useful for creating a new dataset that contains a geographic subset of the features in another larger dataset.

ArcGIS Pro Clip Illustration

Illustration from https://pro.arcgis.com/en/pro-app/latest/tool-reference/analysis/clip.htm

Under the Analysis Tab, click the Tools button Geoprocessing Tools Button to open a geoprocessing search menu. In the search box at the top of the menu type in the word Clip and click enter. The first option will show “Clip (Analysis Tools)”. Click on the tool to open the associated menu. In the new menu choose the following options from the drop-down menus and click Run :

  • Input Features = USA_Counties
  • Clip Features = ex4_States (or the name of the file for the selected states in the previous step)
  • Output Feature Class = choose a name for your file and add .shp behind it to create a shapefile.

Clip Analysis Tool

This will create a dataset containing only the counties that are included within the states used as the selection. While the colors were altered to highlight the changes and additions to the project, you should now see a new dataset in your Table of Contents that only contains those counties.

Clipped Counties
Colors altered from previous images to highlight geoprocessing results.

Finally, while having the individual hurricane tracks can be important, for the purposes of this exercise you are going to use the Merge tool to combined all of the individual hurricane tracks into a single dataset. Similar to the previous step, click on the Tools  button on the Analysis Tab and search for Merge. Click on “Merge (Data Management Tool)” and in the new window choose the following options from the drop-down menu and click run:

  • Input Datasets = Either from the drop-down menu or the add many button  Add Many select all of the individual hurricane tracks. If using the “add many” button you will need to click the “add” link in the bottom right-hand corner of the input. If you use the drop-down menu the data will add automatically
  • Output Dataset = choose a name for your file and add .shp behind it to create a shapefile.

Merged Hurricanes

Now you can remove the USA_Counties  and all the individual hurricane track files to reduce the clutter in your Table of Contents. To do this you simply right-click on the dataset in the Table of Contents and click Remove.

Question No. 1
How many individual track segments are contained in the merged hurricane dataset?

View directions in QGIS

As you have done with each of the previous exercises, Exercise 2 and Exercise 3, you will begin by launching QGIS from the start menu, launchpad, or dekstop shortcut. Start with a New Empty Project  and save it to your project folder.

With your your empty project created, navigate to GitHub and download all datasets for this exercise here to your project folder and extract the data. If you have any questions on how to retrieve and extract the data refer to Exercise 2, Step 1 for detailed instructions.

Add the states, counties, and all hurricanes  datasets to the map view. Remember that the datasets in your Layers menu are drawn in the order they appear. So the first item on the list will be the first show, followed, by the second and so on. Therefore, if you want certain datasets to be visible above all others it should be located at the top by clicking and dragging the data up or down in the list. For polygons, you can edit the fill and transparency (found under the appearance tab in effects) to allow for items underneath to be scene. For example, in the image below, the hurricane tracks are ordered by year and are situated on top of the county and state polygons. If the polygons were drawn first, the hurricane tracks would not be shown once they make landfall. In this example, the states polygons are displayed with a hollow fill and white border to allow for the counties to show through with their black borders.

Exercise 4 Datasets

Refer back to previous exercises to review how to change the symbology for a given dataset. You should experiment with different order, fill, and transparencies to customize your view of the data.

Because FEMA is only interested in counties impacted by hurricanes, you need to select only the states that are intersected by the tracks. There are several ways to subset data in QGIS. For this example we can select counties by name through a structured query language (SQL), we can use graphical tools to select data, and we can use geoprocessing tools to subset the data. Because this is a learning module, you will be learning several different techniques. While this might not necessarily be the quickest method, the purpose of this exercise is to introduce you to several tools you can use as appropriate in future projects.

To continue gathering data for this exercise you are first going to isolate the data you want to select. Begin by clicking on the USA_States_Continental  dataset to make it the only selectable layer. Next, using the Select Features tool Select Features Tool use the drop-down menu to choose Select Features by Freehand.

Freehand Select

Single click on the map somewhere in the Gulf of Mexico and use the cursor to draw a circle encompassing Alabama, Arkansas, Delaware, Florida, Georgia, Illinois, Indiana, Kentucky, Louisiana, Maryland, Mississippi, Missouri, New Jersey, North Carolina, Ohio, Pennsylvania, South Carolina, Tennessee, Virginia, and West Virginia. Your circle does not need to include all of the state, just a small portion. After circling the selected states, single click again to finish the selection. See the example below:

Data Selection

If you make a mistake you can use the Deselect Features button Clear Select Features Tool to clear your selection and try again. With the states selected, return the Layers menu right/CRTL click on the USA_States_Continental dataset and choose Export > Save Selected Features As… from the menu. In the resulting menu include the following options and click OK:

  • Format = ESRI Shapefile
  • File name = choose a name and location for your file by clicking on the Select Folder and File Name button
  • Leave all other options as the default

Export Data Selection

When finished you should have the file added to your project. Another technique to isolate data is by using the Clip analysis tool. This tool can be used to cut out a piece of one dataset using one or more of the features in another dataset as a “cookie cutter”. This is useful for creating a new dataset that contains a geographic subset of the features in another larger dataset.

ArcGIS Pro Clip Illustration

Illustration from https://pro.arcgis.com/en/pro-app/latest/tool-reference/analysis/clip.htm

On the menu bar, select Vector > Geoprocessing Tools > Clip to open the clipping dialog box. Choose the following options and click Run at the bottom of the screen when finished:

  • Input layer = USA_Counties
  • Overlay layer = The file of selected states you created above
  • Clipped = When creating new datasets you can choose to leave this section a Create temporoary layer or use the Select Folder and File Name button to choose Save to File…. Temporary layers are great when you need to create an intermediate layer you do not plan to retain for analysis. In this case, because we want to keep the file, it is best to save it as a new shapefile. Any temporary file created will be lost once you close the project.

Clip

This will create a dataset containing only the counties that are included within the states used as the selection. While the colors were altered to highlight the changes and additions to the project, you should now see the new dataset in your Layers menu that only contains those counties.

Clipped Data
Colors altered from previous images to highlight geoprocessing results.

Finally, while having the individual hurricane tracks can be important, for the purposes of this exercise you are going to use the Merge vector layers tool to combined all of the individual hurricane tracks into a single dataset. To locate this tool you will need to click the Toolbox  button Processing Toolbox Button on the toolbar. This will open the Processing Toolbox side menu and allow you to search for merge.

Double click on the Merge vector layers tool and in the new window click the Select Folder and File Name button for the Input layers. The window will shift to allow you to select all of the individual hurricane track layers. When complete click the return arrow Select Folder and File Name to go back to the Merge Vector Layers dialog box. The Input layers  should now say “5 inputs selected.” Next, click the Select Folder and File Name button for the section that says Merged. While you could make this a temporary layer, it would be best to save the file similar to in the previous steps to retain access to the new dataset.

Merged Vector Layers Dialog

Now you can remove the USA_Counties  and all the individual hurricane track files to reduce the clutter in your Layers menu. To do this you simply right/CRTL-click on the dataset in the Layers menu and click Remove Layer or hiding the layer by unchecking the hide layer  button Hide Layer Button.

Merged Data Example

Question No. 1
How many individual track segments are contained in the merged hurricane dataset?

View directions in R

Before you begin, you will need to open the Ex4 Colab Notebook and insert tocolab after github in the URL to open in the Colab Environment. If you have any questions regarding Colab Notebooks refer to Exercise 2, Introduction for R. Remember to make a copy of the notebook. As you have seen before, R requires various packages to complete certain analyses. In this exercise you will be using tidyverse, ggsn, cowplot, maps, mapproj, plyr, raster, rgeos, rgdal, sp). This is a large number of packages and will take a while to load. To install and load the packages we will use the following script:

#install.packages('tidyverse')
#install.packages('ggsn')
#install.packages('cowplot')
#install.packages('maps')
#install.packages('mapproj')
#install.packages('plyr')
#install.packages('raster')
#install.packages('rgeos')
#install.packages('rgdal')
#install.packages('sp')
library('tidyverse')
library('ggsn')
library('cowplot')
library('maps')
library('mapproj')
library('plyr')
library('raster')
library('rgeos')
library('rgdal')
library('sp')
library('utils')

In future exercises you will learn how to reduce the script above to load and install packages in fewer lines. Additionally, there are certain functions that are duplicated between different packages. Therefore, in this exercise you will learn to use :: (double colons) to indicate which package you want to execute a specific function.

For this exercise you will use a combination of built in data from various packages and downloaded data from the above sources in the form of a shapefile. A shapefile is a “simple, non-topological format for storing the geometric location and attribute information of geographic features. Features can be represented by points, lines, or polygons. The workspace containing shapefiles may also contain a database manage table, which can store additional attributes that can be joined to a shapefiles features.”

In previous exercises you created relatively simplistic maps and design layouts. More fully developed maps contain additional geographic data, or base maps, that can be used to provide reference or location information. In this exercise you will also create an inset map or reference map that provides an overview.

To begin, you will use the information from the maps package to create an object containing the states of Alabama, Arkansas, Delaware, Florida, Georgia, Illinois, Indiana, Kentucky, Louisiana, Maryland, Mississippi, Missouri, New Jersey, North Carolina, Ohio, Pennsylvania, South Carolina, Tennessee, Virginia, and West Virginia. The process is similar to the directions for Exercise 2, Step 1 and Exercise 3, Step 1.

states <- map_data(map = "state", region =  c("alabama","arkansas","delaware","florida","georgia",
                                              "illinois","indiana","kentucky","louisiana","maryland",
                                              "mississippi","missouri","new jersey","north carolina","ohio",
                                              "pennsylvania","south carolina","tennessee","virginia","west virginia"))

ggplot(states) + 
  geom_polygon(aes(x=long, y=lat, group=group), color = "white") +
  coord_fixed()

To add contextual data and avoid the appearance of “floating data” you will next create an object to fill in the surrounding states.

us <- map_data('state')

ggplot() + 
  geom_polygon(data = us, aes(x=long, y=lat, group=group), color = "white", fill = "gray") + 
  geom_polygon(data = states, aes(x=long, y=lat, group=group), color = "white") + 
  coord_fixed()

To add the hurricane information from NOAA you need to download the shapefiles, extract the dataset, and read in the files. To do this you will use the readOGR function from the rgdal package. You will use the download.file function and github link to obtain the zip file and the unzip function to extract the data. The readOGR function requires listing the path to the file to import that data. In the path below you will see a . (period) in front of the /Hurricanes folder. The period is a shortcut version to say “in the project folder” instead of typing out the entire folder path.

download.file('https://github.com/chrismgentry/GIS1-Exercise-4/raw/main/Data/Hurricanes.zip', 'hurricanes.zip')
trying URL 'https://github.com/chrismgentry/GIS1-Exercise-4/raw/main/Data/Hurricanes.zip'
Content type 'application/zip' length 23885 bytes (23 KB)
downloaded 23 KB
unzip('hurricanes.zip')

dorian <- readOGR("./Hurricanes","Dorian_2019_line")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\gentryc\Google Drive\APSU\Courses\GEOG 3150 GIS 1\Exercises\New Exercises\Ex4\GIS1-Exercise-4\Hurricanes", layer: "Dorian_2019_line"
with 4 features
It has 4 fields
irma <- readOGR("./Hurricanes","Irma_2017_line")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\gentryc\Google Drive\APSU\Courses\GEOG 3150 GIS 1\Exercises\New Exercises\Ex4\GIS1-Exercise-4\Hurricanes", layer: "Irma_2017_line"
with 20 features
It has 4 fields
Integer64 fields read as strings:  STORMNUM 
laura <-readOGR("./Hurricanes","Laura_2020_line") 
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\gentryc\Google Drive\APSU\Courses\GEOG 3150 GIS 1\Exercises\New Exercises\Ex4\GIS1-Exercise-4\Hurricanes", layer: "Laura_2020_line"
with 10 features
It has 4 fields
matthew <-readOGR("./Hurricanes","Matthew_2016_line") 
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\gentryc\Google Drive\APSU\Courses\GEOG 3150 GIS 1\Exercises\New Exercises\Ex4\GIS1-Exercise-4\Hurricanes", layer: "Matthew_2016_line"
with 13 features
It has 4 fields
Integer64 fields read as strings:  STORMNUM 
michael <-readOGR("./Hurricanes","Michael_2018_line")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\gentryc\Google Drive\APSU\Courses\GEOG 3150 GIS 1\Exercises\New Exercises\Ex4\GIS1-Exercise-4\Hurricanes", layer: "Michael_2018_line"
with 6 features
It has 4 fields

Next you will use the rbind function, which is a base R function, to combine all of the individual tracks into one. However, because of the structure of the data there are some additional steps that need to be taken before the data can be used in ggplot2. The first is to create a column of row ids for each row to use in a future step to connect the data. Then the fortify function from ggplot2 can be used to convert the data to an object that can be imported into the map. Finally, the join function from the plyr package can be used to attach the data lost in the conversion from the original dataset to the new ggplot2 ready dataset.

hurricanes <- rbind(dorian,irma,laura,matthew,michael)
hurricanes@data$id <- rownames(hurricanes@data)
sp_hurricanes <- fortify(hurricanes)
hurricane_tracks <- plyr::join(sp_hurricanes,hurricanes@data, by = "id")

Next you will take similar steps to download and extract a counties shapefile, subset the counties to include those in the selected states above, and finally, prepare the dataset for use with ggplot2.

download.file('https://github.com/chrismgentry/GIS1-Exercise-4/raw/main/Data/US_Counties.zip', 'counties.zip')
unzip('counties.zip')

counties <- readOGR(".","USA_Counties")
subset_counties <- counties[counties$STATE_NAME == "Alabama" | counties$STATE_NAME == "Arkansas"|
                                counties$STATE_NAME == "Delaware" | counties$STATE_NAME == "Florida"|
                                counties$STATE_NAME == "Georgia" | counties$STATE_NAME == "Illinois"|
                                counties$STATE_NAME == "Indiana" | counties$STATE_NAME == "Kentucky"|
                                counties$STATE_NAME == "Louisiana" | counties$STATE_NAME == "Maryland"|
                                counties$STATE_NAME == "Mississippi" | counties$STATE_NAME == "Missouri"|
                                counties$STATE_NAME == "New Jersey" | counties$STATE_NAME == "North Carolina"|
                                counties$STATE_NAME == "Ohio" | counties$STATE_NAME == "Pennsylvania"|
                                counties$STATE_NAME == "South Carolina" | counties$STATE_NAME == "Tennessee"|
                                counties$STATE_NAME == "Virginia" | counties$STATE_NAME == "West Virginia",]

subset_counties@data$id <- rownames(subset_counties@data)
counties_data <- fortify(subset_counties)
se_counties <- plyr::join(counties_data,subset_counties@data, by = "id")

Now you can use ggplot2 to visualize the data. The steps to display the data are similar to those from Exercise 2, Step 3 or Exercise 3, Step 3.

ggplot() + 
  geom_polygon(data = us, aes(x=long, y=lat, group=group), color = "white", fill = "gray") +
  geom_polygon(data = states, aes(x=long, y=lat, group=group), color = "white") +
    geom_polygon(data = se_counties, aes(x=long, y=lat, group=group), color = "darkgray", fill = "NA") +
  geom_path(data = hurricane_tracks, aes(x=long, y=lat, group=group), color = "red", size = 2) +
  coord_fixed(xlim = c(-125,-65), ylim = c(25,50))

Notice in the code above coord_fixed() is used to limit the range of the map. This will be important in future visualizations.

Question No. 1
What variables are present in the hurricane track dataset? Which of these could be used to categorize the data in a new visualization? Answer in the code cell below.

1.2 Step Two: The Analyses

In this step you will organize and display the data in order to prepare it for the final visualization.

View Directions in ArcGIS Pro

Now that you have the necessary data, you need determine which counties are most significantly impacted by the hurricanes. Because hurricane winds can impact areas far away from the eye or the storm, you will begin by creating a buffer around the hurricane tracks. You can either use the Tools button Geoprocessing Tools Button on the Analysis Tab  or search for Buffer in the list of tools next to the button. In the Buffer window select the following options and click run:

  • Input Features = The merged hurricane dataset
  • Output Feature Class = choose a name for your file and add .shp behind it to create a shapefile
  • Distance = 50 miles (linear unit)
  • Side Type = Full
  • End Type = Round
  • Method = Planar
  • Dissolve Type = Dissolve all output features into a single feature

Buffer Tool

If in this step or the next you encounter a warning stating there is a “datum conflict between the input and output”, just proceed with the exercise. We will discuss datums, a set of reference points on the earth’s surface against which position measurements are made, in future exercises. While they are important to understand, for the purposes of this exercise you can ignore the warning.

In this next step you need to isolate only the counties that are located within this buffer. To do this, click the Select By Location button Select By Location Button on the Map Tab  in the Selection Section. In the new menu choose the following and click OK.

  • Input Features = Your clipped counties
  • Relationship = Choose Intersect
  • Selecting Features = Your buffered hurricanes
  • Selection Type = New Selection

Select By Location

With this selection made, you can take the same steps as before to create a new dataset by right-clicking on the clipped counties dataset in the Table of Contents, going to Data > Export Features  and creating a new shapefile of the selected counties. You can now remove the clipped counties you created in step one or change the symbology to make this new selection stand out.

To answer the following question, open the attribute table for the new dataset you created highlighting the impacted counties. Right-click on the column header for the Population variable, and select statistics.

Question No. 2
What is the total population (POP2000; sum information) of the counties impacted by these hurricanes?

View Directions in QGIS

Now that you have the necessary data, you need determine which counties are most significantly impacted by the hurricanes. Because hurricane winds can impact areas far away from the eye or the storm, you will begin by creating a buffer around the hurricane tracks. You can either go to Vector > Geoprocessing Tools > Buffer on the menu bar or search for Buffer in the Processing Toolbox  (similar to searching for Merge). Double-click on the Buffer tool, select the following options and click Run:

Buffer Tool Dialog

  • Input layer = The merged hurricane file you created
  • Distance = 0.8
  • Segments = 4
  • End cap style = Round
  • Join style = Round
  • Miter limit = 2.0
  • Check the box for Dissolve result
  • Buffered save the file in your project folder

You may receive a warning about using degrees to calculate the buffer. If so you can dismiss it for now. In future exercises you will project your dataset, however for the purposes of this exercise you can ignore the warning. Your screen should now look similar to this (colors have been altered to highlight the results):

Buffered hurricane dataset

For this exercise, you are going to add satellite imagery from a remote connection. In the browser, scroll down to XYZ Tiles and right/CRTL-click to add a “New Connection”. In the resulting window name the connection “Google Satellite” and type the following into the URL:

https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}

You can now click and drag Google Satellite into the layer to view the satellite imagery. Remember to arrange your layer so that either the fill for counties is transparent or the satellite layer is above the counties so you can see the imagery.

Adding satellite data basemap

In this next step you need to isolate only the counties that are located within the hurricane buffer. To do this, click Vector > Research Tools > Select By Location from the menu bar. In the new menu choose the following and click Run

Select by location tool

  • Select features from = The clipped counties dataset. This is the file that contains only the counties in the selected states.
  • Where the features (geometric predicate) = Check the box for intersect
  • By comparing to the features from = The hurricane buffer dataset
  • Modify current selection by = Creating new selection

With this selection made, you can take the same steps as before to create a new dataset by right/CRTL-clicking on the clipped counties dataset in the Layers menu, going to Export > Save Selected Features As… and creating a new shapefile of the selected counties.

Exporting the current selection

You can now remove the clipped counties you created in step one or change the symbology to make this new selection stand out.

All Analyzed Datasets

To answer the following question, click the Show Statistical Summary  button Show Statistical Summary Button on the menu bar. A new menu will open in the left-hand column of the screen. In this menu select the dataset you created for the hurricane impacted counties in the first box and population in the second.

Statistics Information

Question No. 2
What is the total population (sum information) of the counties impacted by these hurricanes?

View Directions in R

Now that you have the necessary data, you need determine which counties are most significantly impacted by the hurricanes. Because hurricane winds can impact areas far away from the eye or the storm, you will begin by creating a buffer around the hurricane tracks. For this step you will use the buffer function from the raster package. The function requires:

buffer(x,width=0,dissolve=TRUE)

where x = the dataset, width = distance in map units, and dissolve = if TRUE, overalpping polygons are dissolved.

hurricanes_buffer <- buffer(hurricanes, width = 1, dissolve = TRUE)

With the buffer created you can now use intersect from the raster package to select the overlapping counties. More information on Intersect can be found on the ESRI website. Similar to before, you will need to fortify the data and connect to the original dataset.

intersection <- raster::intersect(hurricanes_buffer,subset_counties)
intersection@data$id <- rownames(intersection@data)
hurricanes_counties <- fortify(intersection)
impacted_counties <- plyr::join(hurricanes_counties,intersection@data, by = "id")

With the intersection complete, the counties that are most impacted by the hurricane (e.g. those within the buffer zone of the tracks) are contained within the impacted_counties object.

Question No. 2 To answer this question you will need to create a dataset that won’t be used in the map. Due to the dissected nature of the data, you need to examine the distinct ids of the impacted counties. This can be done using the following script:

county_populations <- distinct(impacted_counties, FIPS, .keep_all = TRUE)
Where you are using the impacted_counties dataset and keeping only the distinct federal FIPS code that is unique to each county.
With the dataset above, write a script using sum() to determine the total population impacted by the hurricanes?
HINT: Similar to Exercise 3, Question 2 place the object followed by a $ and the variable name between the () in the sum function. You can use str() to view the variables available in the dataset.

1.3 Step Three: The Visualization

You will now create a graphical display of your data that includes cartographic elements such as legend, scale bar, north arrow, etc. In this visualization you will also learn to add a different basemap, add an inset or overview map, and alter the projected coordinate system.

View directions in ArcGIS Pro

On the Map Tab  click the Basemap button Basemaps and select the option for Oceans. Remember that the order of the datasets in the Table of Contets determines what order they are displayed.

Basemaps

In future exercises you may choose any of these basemap options that are apprropriate for your analyses. Next, on the Insert Tab  click the button for New Map Insert New Map and select New Map. A new map tab (probably called Map2) will appear in your map frame. Add (or copy/paste from the original map) the hurricane impacted counties and the continental US States shapefiles as well as the Oceans basemap to this new map. Be sure to zoom in a appropriate to see the data.

Inset Map

To return to the original map simply click on the appropriate tab. This will allow you to switch back and forth between the two in order to make the necessary customizations. It may be beneficial to rename each one to keep track of the purpose for each map.

Next you can change the projection of the coordinate system for the inset map (Map2). In the Table of Contents, right-click on Map2 and select Properties. In the resulting window click Coordinate Systems from the left-side menu. Under “XY Coordinate Systems Available” scroll down until you see Projected Coordinate System. Using the series of drop-down menus go to Projected Coordinate System > Continental > North America and select the option for “North America Albers Equal Area Conic” and click OK. You should notice that the awkward “flat top” border of the United States should now me curved and the overall shape of the states has a more pleasing appearance.

Altering Coordinate systems

In lecture we will discuss the importance of projections and coordinate systems. In future exercises you should take some time to select different options to see which Coordinate System  has the most pleasing shape to your eyes.

It is now time for you to make your map. Similar to previous exercises, you need to add all of the necessary elements discussed in Exercise 2 and 3. In this exercise you will also need to add your inset map (Map2). To do this, you first need to add the primary map with using the Map Frame button like before. Next you can click the Map Frame button again to add the second map.

Add Inset Map

However, for the inset you want it to be smaller and not cover your map data.

Map with Inset Map

Finalize your map by adding all of the necessary map elements (title, legend, north arrow, scale bar, name and date) and altering the symbology of the hurricane dataset to provide additional important data. Remember to renaming items in the Table of Contents will rename them in the legend.

Final Map

Question No. 3
How many total impacted counties are included in the new dataset?

View directions in QGIS

To create this visualization you are going to also create what is called an inset or indicator map. These are smaller maps that are used to provide additional detail about a specific location. These maps are often small scale versions or the primary map, but sometimes can be larger scale to enhance detail in congested areas. In this case it will be a small scale version of the continental US.

To begin this process you are going to create some organizations in the Layer Menu by using the Add Group button Add Groups. Name the first group “Main Map” and create a second group called “Inset Map”.

Layers Groups

In the Layers Menu you can click and drag the datasets into the different groups as well as right/CRTL-click to copy and paste. For this exercise you should order your datasets as follows:

  • Main Map
    • Hurricanes Dataset
    • Hurricane Impacted Counties
    • Selected States
    • Clipped Counties
    • Continental US
    • Google Satellite Imagery
  • Inset Map
    • Hurricane Buffer
    • Selected States
    • Continental US
    • Google Satellite Imagery

Layers Groups

Similar to previous exercises, your visualization should include all of the necessary map elements discussed in Exercise 2 and 3. However, you will also need to add the inset map for this exercise. To do this, you first need to create a New Print Layout, and with the “Main Map” selected and the “Inset Map” hidden in the Layers Menu, and add the map with the Add map  tool like before.

Layout with Main Map

In the item properties for the map, set your level of zoom and align the map in your desired location. Then under Layers  section, click “Lock Layers” to keep the map frame from being altered. You can always return to this layer and unlock it if you need to make changes.

Next return to the project and turn off the Main Map, then turn on the Inset Map and return to the layout and add another map. Because you have the inset group selected and the main map group hidden, the additional map frame will contain the inset information. Remember to think about where you want the inset to be located before you draw it on the layout. While you can change this at anytime, you should always have a planned map design.

Layout with Inset Map

Finalize your map by adding all of the necessary map elements (title, legend, north arrow, scale bar, name and date) and altering the symbology of the hurricane dataset to provide additional important data. Remember to renaming items in the Table of Contents will rename them in the legend but you will need to update in the item properties. Alternatively, in the item properties for the legend you can select any object and click the Edit button Add Groups to rename them.

Question No. 3
How many total impacted counties are included in the new dataset?

View directions in R

To create this visualization you are going to also create what is called an inset or indicator map. These are smaller maps that are used to provide additional detail about a specific location. These maps are often small scale versions or the primary map, but sometimes can be larger scale to enhance detail in congested areas. In this case it will be a small scale version of the continental US.

To begin this process you are going to create an additional object for countries of the world.

world <- map_data(map = "world")

You can now create the primary map data. Within the script below you will see some of the common functions used throughout this and previous exercises. There are two changes made from the typical ggplot2 script to mention:

  • geom_path() is a function to add a line based on a series of data points such as hurricane tracks.
  • Within the aes() for geom_path() the color variable was converted to a character (letters) from numeric (numbers). This was done to create discrete variables rather than continuous variables to make a more appropriate legend.
main_map <- ggplot() + 
  geom_polygon(data = world, aes(x=long, y=lat, group=group), color = NA, fill = "gray") +
  geom_polygon(data = us, aes(x=long, y=lat, group=group), color = "white", fill = "DimGray") +
  geom_polygon(data = se_counties, aes(x=long, y=lat, group=group), fill = "LightGray", color = "DarkGray") +
  geom_polygon(data = states, aes(x=long, y=lat, group=group), color = "black", fill = NA) +
  geom_polygon(data = impacted_counties, aes(x=long, y=lat, group=group), color = "DarkGray", fill = "LightSkyBlue") +
  geom_path(data = hurricane_tracks, aes(x=long, y=lat, group=group, color = as.character(SS)), size = 2, lineend = "round") +
  scale_color_viridis_d(option = "A", "Saffir\nSimpson\nScale") +
  coord_fixed(xlim = c(-97,-74), ylim = c(25,44)) + 
  theme(axis.title.x=element_blank(), axis.title.y=element_blank(), panel.background = element_rect(fill = "lightblue"), 
        panel.grid.major = element_blank(), panel.grid.minor = element_blank())
main_map

To create the inset map you will use the world data you created above along with the US and impacted counties datasets.

inset <- ggplot() + 
  geom_polygon(data = world, aes(x=long, y=lat, group=group), color = "white", fill = "gray") +
  geom_polygon(data = us, aes(x=long, y=lat, group=group), color = "black", fill = "DarkGray") +
  geom_polygon(data = impacted_counties, aes(x=long, y=lat, group=group), color = NA, fill = "LightSkyBlue") +
  coord_map(xlim = c(-125,-65), ylim = c(25,50), "conic", lat0 = 30) +
  theme(panel.background = element_rect(fill = "lightblue"), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), 
        axis.line=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(),axis.ticks=element_blank(), 
        axis.title.x=element_blank(), axis.title.y=element_blank())
inset

Notice in each of these scripts created an object out of the ggplot(). This is used to facilitate the creation of the final map when overlaying the inset on the main map. To do this you will use ggdraw from the ggplot2 package. In this function to add the maps using the draw_plot function and locate the inset using x, y, width, and height arguments. These values can be altered to move the inset map to any location on the main map. Feel free to experiment with location in Step 4.

ggdraw() +
draw_plot(main_map) + 
draw_plot(inset, x = 0.039, y = 0.62, width = 0.3, height = 0.3)

ggdraw() +
draw_plot(main_map) + 
draw_plot(inset, x = 0.105, y = 0.72, width = 0.275, height = 0.275)

There may be a discrepancy between the x, y, width, and height information for the inset in the script above and the Colab Notebook due to the differences in resolution and space limitations of creating the webpage.

Question No. 3
Provide the full script you would use to add the north arrow, title, scalebar, and name/date information to the map.

1.4 Step Four: Your Turn

After providing the initial map to FEMA, the Deputy Associate Administrator for the Office of Response and Recovery has asked if you could add some additional data. Specifically, they are interested in cities with a population of greater than 300,000 so they are able to situate response teams in proximity to the most people.

View directions in ArcGIS Pro

If you did not previously download the cities data from the GitHub Exercise Page please download the data and unzip it in your project folder. With that data available, add the US_Cities_100k.shp to your primary map (not the inset map). Repeating the steps to clip from Step 1 select the cities as your Input Feature, the hurricane buffer as the Clip Feature, and be sure to save the new dataset to your project folder with .shp to create a shapefile. You can now remove the US Cities from the project but keep your clipped cities.

While you will leave all of the clipped cities on the map, you will now create a Label Class to only create labels for cities with a population greater than 300,000. To begin, right-click on your new clipped cities dataset and select “Labeling Properties…” Labeling Properties from the options.

Under the “Class” option in the Label Class window select SQL from the three options. Next select New expression  Labeling SQL and select the following options:

Where POPULATIONis greater than300,000

SQL Options for Labeling

When complete, click Apply at the bottom of the window. Use the options on the Labeling Tab for the dataset to adjust the label field to NAME, change the font or size of the text, and click the Label button on the left of the tab.

Labeling Options

Question No. 4
What labeled cities are the furthest North, South, East, and West?

View directions in QGIS

If you did not previously download the cities data from the GitHub Exercise Page please download the data and unzip it in your project folder. With that data available, add the US_Cities_100k.shp to your primary map (not the inset map). Repeating the steps to clip from Step 1 select the cities as your Input Layer, the hurricane buffer as the Overlay Layer, and be sure to save the new dataset to your project folder in the Clipped  option. You can now remove the US Cities from the project but keep your clipped cities.

While you will leave all of the clipped cities on the map, you will now create a Label Class to only create labels for cities with a population greater than 300,000. To begin, right/CRTL-click on your new clipped cities dataset and select “Properties”. Under the Labels tab on the left side of the new window, select Rule-based Labeling  from the drop-down menu at the top of the window. Next, click the Green + at the bottom to add a new rule. Provide the following inputs and click OK

  • Description = Give your rule a name
  • Filter = Type the following: "POPULATION" > 300000
  • Labels = Check this box
  • Value = NAME
  • Text, Formatting, Buffer, Mask, etc. = Customize as necessary for your preferred style

Rule-based Options for Labeling

Finally, click OK on the layer properties window. You will need to return to your main map in the layout and uncheck the box for locked to update the map with this new information.

Question No. 4
What labeled cities are the furthest North, South, East, and West?

View directions in R

Just like the steps above you will use the download.file, unzip, and readOGR functions to download the cities shapefile and extract the information. Also like above, you will need to subset the cities to include only those in the selected states.

download.file('https://github.com/chrismgentry/GIS1-Exercise-4/raw/main/Data/US_Cities_100k.zip', 'cities.zip')
trying URL 'https://github.com/chrismgentry/GIS1-Exercise-4/raw/main/Data/US_Cities_100k.zip'
Content type 'application/zip' length 62708 bytes (61 KB)
downloaded 61 KB
unzip('cities.zip')

cities <- readOGR(".","US_Cities_100k")
OGR data source with driver: ESRI Shapefile 
Source: "C:\Users\gentryc\Google Drive\APSU\Courses\GEOG 3150 GIS 1\Exercises\New Exercises\Ex4\GIS1-Exercise-4", layer: "US_Cities_100k"
with 318 features
It has 49 fields
subset_cities <- cities[cities$ST == "AL" | cities$ST == "AR"|
                              cities$ST == "DE" | cities$ST == "FL"|
                              cities$ST == "GA" | cities$ST == "IL"|
                              cities$ST == "IN" | cities$ST == "KY"|
                              cities$ST == "LA" | cities$ST == "MD"|
                              cities$ST == "MS" | cities$ST == "MO"|
                              cities$ST == "NJ" | cities$ST == "NC"|
                              cities$ST == "OH" | cities$ST == "PA"|
                              cities$ST == "SC" | cities$ST == "TN"|
                              cities$ST == "VA" | cities$ST == "WV",]

With the cities information available you will again use the intersect function to limit the cities data to only those within the hurricane buffer.

cities_intersect <- raster::intersect(subset_cities,hurricanes_buffer)
cities_intersect@data$id <- rownames(cities_intersect@data)
se_cities <- data.frame(cities_intersect)
names(se_cities)[names(se_cities) =="coords.x1"] <- "long"
names(se_cities)[names(se_cities) =="coords.x2"] <- "lat"

Notice in the script above there is additional code to rename two variables: coords.x1 and coords.x2. Due to the conversion from a shapefile and the intersect, the resulting object needed to be set as a data frame. In the process the coordinate information columns were renamed coords.x1 and coords.x2. Therefore you needed to rename those individual columns to lat and long to remain consistent with the rest of your scripts.

And finally you will create a query that selects just those cities that have a population greater than 300,000 individuals.

large_cities <- se_cities[se_cities$POPULATION > 300000,]

Now you have a number of datasets that can be used to create your final map including:

  • World
  • US States
  • Southeast States
  • Southeast Counties
  • Hurricane Impacted Counties
  • Hurricane Tracks
  • Southeast Cities
  • Large Southeast Cities

For your final map, you need to use these datasets to create the visualization requested by FEMA above that includes the geographic information, hurricane tracks, cities, and large cities with populations greater than 300,000. In the Colab Notebok and below is an incomplete ggplot2 script.

cities_map <- ggplot() + 
  geom_polygon(data = World...
  geom_polygon(data = US States...
  geom_polygon(data = SE Counties...
  geom_polygon(data = SE States...
  geom_polygon(data = Impacted Counties...
  geom_path(data = Hurricane Tracks...
  scale_color_viridis_d(option = "A", "Saffir\nSimpson\nScale") +
  geom_point(data = se_cities, aes(x=long, y=lat), color = "yellow") +
  geom_point(data = large_cities, aes(x=long, y=lat), color = "yellow") +
  geom_text(data = large_cities, aes(x=long, y=lat, label = NAME, fontface = "bold"), size = 3, 
            nudge_y = 0.60, nudge_x = 0.25, check_overlap = TRUE, color = "white") +
  annotate("text", x = -86.85, y = 38.5, label = "Louisville", fontface = "bold", size = 3, color = "white") +
  coord_sf(Limiting coordinates to focus on the SE US...
  theme(axis.title.x=element_blank(), axis.title.y=element_blank(),
        panel.background = element_rect(fill = "lightblue"), 
        panel.grid.major = element_blank(), panel.grid.minor = element_blank())
cities_map

Complete this script in the Colab Notebook, including lines for scale bar, north arrow, title, name and date.

Question No. 4
What labeled cities are the furthest North, South, East, and West?

2 The Write-Up

In the report you provide to FEMA please provide the following information:

  • Total population of the impacted counties
  • Total number of large cities (all in the clipped dataset)
  • Which cities above 300,000 people would need response teams
    • Based on the distribution of these, would it be possible for one response team to cover multiple large cities?

When complete, send a link to your Colab Notebook or word document with answers to Questions 1-4 and your completed map via email.

LS0tDQp0aXRsZTogIkV4ZXJjaXNlIDQ6IEJhc2ljIEdlb3Byb2Nlc3NpbmcgVG9vbHMgPGJyPjxzbWFsbD5HZW9ncmFwaGljIEluZm9ybWF0aW9uIFN5c3RlbXMgMSBMYWI8L3NtYWxsPjwvYnI+Ig0KYXV0aG9yOiAiR0VPRyAzMTUwIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHJvd3MucHJpbnQ6IDEwDQogICAgdGhlbWU6IGNvc21vDQogICAgaGlnaGxpZ2h0OiBicmVlemVkYXJrDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCiAgICAgIHNtb290aF9zY3JvbGw6IHllcw0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCiAgbW9kZTogZ2ZtDQotLS0NCg0KYGBgez1odG1sfQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDQwcHg7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMjBweDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQouem9vbSB7DQogIHRyYW5zZm9ybS1vcmlnaW46IDQwJSA1MCUgMDsNCiAgdHJhbnNpdGlvbjogdHJhbnNmb3JtIC4yczsNCiAgbWFyZ2luOiAwIGF1dG87DQp9DQouem9vbSBpbWd7DQoJd2lkdGg6YXV0bzsNCgloZWlnaHQ6YXV0bzsJDQp9DQouem9vbTpob3ZlciB7DQogIHRyYW5zZm9ybTogc2NhbGUoMik7DQp9DQoNCnRoLCB0ZCB7cGFkZGluZzogNXB4O30NCg0KPC9zdHlsZT4NCmBgYA0KPGhyPjwvaHI+DQoNClRoZSBwdXJwb3NlIG9mIHRoaXMgZXhlcmNpc2UgaXMgdG8gaGVscCBmYW1pbGlhcml6ZSB5b3Ugd2l0aCBzb21lIG9mIHRoZSBHZW9wcm9jZXNzaW5nIFRvb2xzIGF2YWlsYWJsZSBpbiB0aGUgdmFyaW91cyBwcm9ncmFtcy4gVGhlc2UgdG9vbHMgd2lsbCBoZWxwIHlvdSB0byBzaW1wbGlmeSwgb3JnYW5pemUsIGFuZCByZWR1Y2UgdGhlIGFtb3VudCBvZiBpbmZvcm1hdGlvbiBhbmQgYWxsb3cgeW91IHRvIGNyZWF0ZSBhZGRpdGlvbmFsIGJhc2UgbWFwcyBmcm9tIGV4aXN0aW5nIGRhdGEuDQoNCiMgVGhlIEludHJvZHVjdGlvbg0KDQpUaGUgX0ZlZGVyYWwgRW1lcmdlbmN5IE1hbmFnZW1lbnQgQWdlbmN5XyZuYnNwOyAoRkVNQSkgaXMgaW4gdGhlIHByb2Nlc3Mgb2YgcGxhbm5pbmcgZm9yIHRoZSBmZWRlcmFsIGRpc3RyaWJ1dGlvbiBvZiByZXNvdXJjZXMgcmVsYXRlZCB0byBuYXR1cmFsIGRpc2FzdGVycyBpbiB0aGUgVVMuIEFzIFtodXJyaWNhbmVdKGh0dHBzOi8vd3d3Lm5vYWEuZ292L25ld3MtcmVsZWFzZS9ub2FhLXByZWRpY3RzLWFub3RoZXItYWN0aXZlLWF0bGFudGljLWh1cnJpY2FuZS1zZWFzb24pIHNlYXNvbiBhcHByb2FjaGVzIHByZWRpY3Rpb25zIGFyZSBzdWdnZXN0aW5nIGEgdmVyeSBhY3RpdmUgc2Vhc29uIGluIHRoZSBBdGxhbnRpYyBCYXNpbi4gQXMgYSBGRU1BIGFuYWx5c3QsIHlvdSBoYXZlIGJlZW4gdGFza2VkIHdpdGggZXhhbWluaW5nIGh1cnJpY2FuZSBwYXRocyBvdmVyIHRoZSBsYXN0IGZpdmUgeWVhcnMgdGhhdCBoYXZlIGltcGFjdGVkIHRoZSBTb3V0aGVhc3Rlcm4gVVMuIFRoaXMgaW5mb3JtYXRpb24gd2lsbCBiZSB1c2VkIHRvIGRldmVsb3AgYSBwbGFuIGZvciB0aGUgZXN0YWJsaXNobWVudCBvZiB0ZW1wb3JhcnkgcmVsaWVmIHNoZWx0ZXJzLCBzdXBwbHkgc3RvcmFnZSBmYWNpbGl0aWVzLCBhbmQgbW9iaWxlIG1lZGljYWwgc2VydmljZXMgdGhhdCB3aWxsIGJlIG5lY2Vzc2FyeSBpbiB0aGUgaGFyZGVzdCBoaXQgYXJlYXMuDQoNCkluIHRoaXMgZXhlcmNpc2UgeW91IHdpbGw6DQoNCi0gICBVc2UgdmFyaW91cyBtZXRob2RzIG9mIGdlb3Byb2Nlc3NpbmcNCi0gICBDcmVhdGUgZGVyaXZlZCBkYXRhc2V0cw0KLSAgIEFkanVzdCB0aGUgY29vcmRpbmF0ZSBzeXN0ZW1zDQotICAgQ3JlYXRlIGluc2V0IG1hcHMNCi0gICBVc2UgdGhlIGF0dHJpYnV0ZSB0YWJsZSBmb3IgbGFiZWxpbmcNCg0KU29mdHdhcmUgc3BlY2lmaWMgZGlyZWN0aW9ucyBjYW4gYmUgZm91bmQgZm9yIGVhY2ggc3RlcCBiZWxvdy4gUGxlYXNlIHN1Ym1pdCB0aGUgYW5zd2VyIHRvIHRoZSBxdWVzdGlvbnMgYW5kIHlvdXIgZmluYWwgbWFwIGJ5IHRoZSBkdWUgZGF0ZS4NCg0KIyMgU3RlcCBPbmU6IFRoZSBEYXRhDQoNClRoZSBkYXRhIHlvdSB3aWxsIGJlIHVzaW5nIGZvciB0aGlzIGV4ZXJjaXNlIGNvbWVzIGZyb20gdGhlIE5hdGlvbmFsIE9jZWFuaWMgYW5kIEF0bW9zcGhlcmljIEFkbWluaXN0cmF0aW9uIC0gW09mZmljZSBmb3IgQ29hc3RhbCBNYW5hZ2VtZW50XShodHRwczovL2NvYXN0Lm5vYWEuZ292LyksIFtIaXN0b3JpY2FsIEh1cnJpY2FuZSBUcmFja3MgaW50ZXJhY3RpdmUgbWFwXShodHRwczovL2NvYXN0Lm5vYWEuZ292L2h1cnJpY2FuZXMvKS4gSW5mb3JtYXRpb24gb24gdGhlIHNpdGUgaXMgZGVyaXZlZCBmcm9tIHRoZSBOT0FBIE5hdGlvbmFsIEh1cnJpY2FuZSBDZW50ZXIgW0hVUkRBVDJdKGh0dHBzOi8vd3d3Lm5oYy5ub2FhLmdvdi9kYXRhLyNodXJkYXQpIGFuZCBOT0FBIE5hdGlvbmFsIENlbnRlcnMgZm9yIEVudmlyb25tZW50YWwgSW5mb3JtYXRpb24gW0lCVHJBQ1NdKGh0dHBzOi8vd3d3Lm5jZGMubm9hYS5nb3YvaWJ0cmFjcy8pIGRhdGEgc2V0cy4NCg0KPGRldGFpbHM+DQo8c3VtbWFyeT48YmlnPlZpZXcgRGlyZWN0aW9ucyBpbiA8Yj4gW0FyY0dJUyBQcm9de3N0eWxlPSJjb2xvcjojZmY0NTAwIn0gPC9iPjwvYmlnPjwvc3VtbWFyeT4NCg0KQXMgeW91IGhhdmUgZG9uZSB3aXRoIGVhY2ggb2YgdGhlIHByZXZpb3VzIGV4ZXJjaXNlcywgW0V4ZXJjaXNlIDJdKGh0dHBzOi8vY2hyaXNtZ2VudHJ5LmdpdGh1Yi5pby9HSVMxLUV4ZXJjaXNlLTIvKSBhbmQgW0V4ZXJjaXNlIDNdKGh0dHBzOi8vY2hyaXNtZ2VudHJ5LmdpdGh1Yi5pby9HSVMxLUV4ZXJjaXNlLTMvKSwgeW91IHdpbGwgYmVnaW4gYnkgbGF1bmNoaW5nICoqW0FyY0dJUyBQcm9de3N0eWxlPSJjb2xvcjojZmY0NTAwIn0qKiBmcm9tIHRoZSBzdGFydCBtZW51IG9yIGRla3N0b3Agc2hvcnRjdXQuIFNlbGVjdCAqKk1hcCoqIGZyb20gX05ldyA+IEJsYW5rIFRlbXBsYXRlc18gYW5kIG9uIHRoZSByZXN1bHRpbmcgc2NyZWVuIHByb3ZpZGUgYSBuYW1lIGFuZCBsb2NhdGlvbiBmb3IgeW91ciBwcm9qZWN0LiBSZW1lbWJlciBpdCB3b3VsZCBiZSBiZW5lZmljaWFsIHRvIGtlZXAgYWxsIG9mIHRoZXNlIGV4ZXJjaXNlcyBpbiBhIHNpbmdsZSBmb2xkZXIgb24geW91ciBjb21wdXRlci4gDQoNCldpdGggeW91ciBzY3JlZW4gbm93IGRpc3BsYXlpbmcgdGhlIF9Xb3JsZCBUb3BvZ3JhcGhpYyBNYXBfJm5ic3A7IGFuZCBfV29ybGQgSGlsbHNoYWRlXyZuYnNwOyBpbiB0aGUgdGFibGUgb2YgY29udGVudHMsIG5hdmlnYXRlIHRvIEdpdEh1YiBhbmQgZG93bmxvYWQgKipbYWxsIGRhdGFzZXRzIGZvciB0aGlzIGV4ZXJjaXNlIGhlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9jaHJpc21nZW50cnkvR0lTMS1FeGVyY2lzZS00L3RyZWUvbWFpbi9EYXRhKSoqIHRvIHlvdXIgcHJvamVjdCBmb2xkZXIgYW5kIGV4dHJhY3QgdGhlIGRhdGEuIElmIHlvdSBoYXZlIGFueSBxdWVzdGlvbnMgb24gaG93IHRvIHJldHJpZXZlIGFuZCBleHRyYWN0IHRoZSBkYXRhIHJlZmVyIHRvIFtFeGVyY2lzZSAyLCBTdGVwIDFdKGh0dHBzOi8vY2hyaXNtZ2VudHJ5LmdpdGh1Yi5pby9HSVMxLUV4ZXJjaXNlLTIvIzExX1N0ZXBfT25lOl9UaGVfRGF0YSkgZm9yIGRldGFpbGVkIGluc3RydWN0aW9ucy4NCg0KQWRkIHRoZSBfc3RhdGVzXywgX2NvdW50aWVzXywgYW5kIGFsbCBfaHVycmljYW5lc18mbmJzcDsgZGF0YXNldHMgdG8gdGhlIG1hcCB2aWV3LiBSZW1lbWJlciB0aGF0IHRoZSBsYXllcnMgaW4geW91ciBfVGFibGUgb2YgQ29udGVudHNfJm5ic3A7IGFyZSBkcmF3biBpbiB0aGUgb3JkZXIgdGhleSBhcHBlYXIuIFNvIHRoZSBmaXJzdCBpdGVtIG9uIHRoZSBsaXN0IHdpbGwgYmUgdGhlIGZpcnN0IHNob3csIGZvbGxvd2VkLCBieSB0aGUgc2Vjb25kIGFuZCBzbyBvbi4gVGhlcmVmb3JlLCBpZiB5b3Ugd2FudCBjZXJ0YWluIGRhdGFzZXRzIHRvIGJlIHZpc2libGUgYWJvdmUgYWxsIG90aGVycyBpdCBzaG91bGQgYmUgbG9jYXRlZCBhdCB0aGUgdG9wIGJ5IGNsaWNraW5nIGFuZCBkcmFnZ2luZyB0aGUgZGF0YSB1cCBvciBkb3duIGluIHRoZSBsaXN0LiBGb3IgcG9seWdvbnMsIHlvdSBjYW4gZWRpdCB0aGUgZmlsbCBhbmQgdHJhbnNwYXJlbmN5IChmb3VuZCB1bmRlciB0aGUgYXBwZWFyYW5jZSB0YWIgaW4gZWZmZWN0cykgdG8gYWxsb3cgZm9yIGl0ZW1zIHVuZGVybmVhdGggdG8gYmUgc2NlbmUuIEZvciBleGFtcGxlLCBpbiB0aGUgaW1hZ2UgYmVsb3csIHRoZSBodXJyaWNhbmUgdHJhY2tzIGFyZSBvcmRlcmVkIGJ5IHllYXIgYW5kIGFyZSBzaXR1YXRlZCBvbiB0b3Agb2YgdGhlIGNvdW50eSBhbmQgc3RhdGUgcG9seWdvbnMuIElmIHRoZSBwb2x5Z29ucyB3ZXJlIGRyYXduIGZpcnN0LCB0aGUgaHVycmljYW5lIHRyYWNrcyB3b3VsZCBub3QgYmUgc2hvd24gb25jZSB0aGV5IG1ha2UgbGFuZGZhbGwuIEluIHRoaXMgZXhhbXBsZSwgdGhlIHN0YXRlcyBwb2x5Z29ucyBhcmUgZGlzcGxheWVkIHdpdGggYSBob2xsb3cgZmlsbCBhbmQgd2hpdGUgYm9yZGVyIHRvIGFsbG93IGZvciB0aGUgY291bnRpZXMgdG8gc2hvdyB0aHJvdWdoIHdpdGggdGhlaXIgYmxhY2sgYm9yZGVycy4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLWV4NC1kYXRhLmpwZyIgYWx0PSJFeDQgRGF0YXNldHMiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNClJlZmVyIGJhY2sgdG8gcHJldmlvdXMgZXhlcmNpc2VzIHRvIHJldmlldyBob3cgdG8gY2hhbmdlIHRoZSBzeW1ib2xvZ3kgZm9yIGEgZ2l2ZW4gZGF0YXNldC4gWW91IHNob3VsZCBleHBlcmltZW50IHdpdGggZGlmZmVyZW50IG9yZGVyLCBmaWxsLCBhbmQgdHJhbnNwYXJlbmNpZXMgdG8gY3VzdG9taXplIHlvdXIgdmlldyBvZiB0aGUgZGF0YS4NCg0KQmVjYXVzZSBGRU1BIGlzIG9ubHkgaW50ZXJlc3RlZCBpbiBjb3VudGllcyBpbXBhY3RlZCBieSBodXJyaWNhbmVzLCB5b3UgbmVlZCB0byBzZWxlY3Qgb25seSB0aGUgc3RhdGVzIHRoYXQgYXJlIGludGVyc2VjdGVkIGJ5IHRoZSB0cmFja3MuIFRoZXJlIGFyZSBzZXZlcmFsIHdheXMgdG8gc3Vic2V0IGRhdGEgaW4gW0FyY0dJUyBQcm9de3N0eWxlPSJjb2xvcjojZmY0NTAwIn0uIEZvciB0aGlzIGV4YW1wbGUgd2UgY2FuIHNlbGVjdCBjb3VudGllcyBieSBuYW1lIHRocm91Z2ggYSBzdHJ1Y3R1cmVkIHF1ZXJ5IGxhbmd1YWdlIChTUUwpLCB3ZSBjYW4gdXNlIGdyYXBoaWNhbCB0b29scyB0byBzZWxlY3QgZGF0YSwgYW5kIHdlIGNhbiB1c2UgZ2VvcHJvY2Vzc2luZyB0b29scyB0byBzdWJzZXQgdGhlIGRhdGEuIEJlY2F1c2UgdGhpcyBpcyBhIGxlYXJuaW5nIG1vZHVsZSwgeW91IHdpbGwgYmUgbGVhcm5pbmcgc2V2ZXJhbCBkaWZmZXJlbnQgdGVjaG5pcXVlcy4gV2hpbGUgdGhpcyBtaWdodCBub3QgbmVjZXNzYXJpbHkgYmUgdGhlIHF1aWNrZXN0IG1ldGhvZCwgdGhlIHB1cnBvc2Ugb2YgdGhpcyBleGVyY2lzZSBpcyB0byBpbnRyb2R1Y2UgeW91IHRvIHNldmVyYWwgdG9vbHMgeW91IGNhbiB1c2UgYXMgYXBwcm9wcmlhdGUgaW4gZnV0dXJlIHByb2plY3RzLiANCg0KVG8gY29udGludWUgZ2F0aGVyaW5nIGRhdGEgZm9yIHRoaXMgZXhlcmNpc2UgeW91IGFyZSBmaXJzdCBnb2luZyB0byBpc29sYXRlIHRoZSBkYXRhIHlvdSB3YW50IHRvIHNlbGVjdC4gSW4gdGhlIF9UYWJsZSBvZiBDb250ZW50c18gY2xpY2sgdGhlICoqTGlzdCBieSBTZWxlY3Rpb24qKiBidXR0b24gPGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLWxpc3Qtc2VsZWN0aW9uLWJ1dHRvbi5qcGciIGFsdD0iTGlzdCBieSBTZWxlY3Rpb24iIHdpZHRoID0gIjIwIiBoZWlnaHQgPSAiMjAiPiB0byBzaG93IGEgbGlzdCBvZiB0aGUgc2VsZWN0YWJsZSBkYXRhc2V0cyBpbiB0aGUgcHJvamVjdC4gQmVjYXVzZSB5b3Ugc2hvdWxkIGhhdmUgYSBudW1iZXIgb2YgZGF0YXNldHMgaW4gdGhlIHByb2plY3QsIHRvIGlzb2xhdGUgb25seSB0aGUgc3RhdGVzIGZpbGUsIHJpZ2h0LWNsaWNrIG9uIHRoZSBfVVNBX1N0YXRlc19Db250aW5lbnRhbF8mbmJzcDsgYW5kIGNob3NlICJNYWtlIHRoaXMgdGhlIG9ubHkgc2VsZWN0YWJsZSBsYXllciIuIA0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtbWFrZS1zZWxlY3RhYmxlLnBuZyIgYWx0PSJNYWtlIGRhdGEgc2VsZWN0YWJsZSIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KVG8gYmVnaW4sIGNsaWNrIHRoZSBkcm9wLWRvd24gbWVudSBmb3IgX1NlbGVjdF8mbmJzcDsgb24gdGhlIF9NYXAgVGFiXyZuYnNwOyBhbmQgY2hvb3NlICoqTGFzc28qKiBmcm9tIHRoZSBkcm9wLWRvd24gbWVudSBhbmQgYW5kIHVzZSB0aGUgY3Vyc29yIHRvIGRyYXcgYSBjaXJjbGUgZW5jb21wYXNzaW5nIEFsYWJhbWEsIEFya2Fuc2FzLCBEZWxhd2FyZSwgRmxvcmlkYSwgR2VvcmdpYSwgSWxsaW5vaXMsIEluZGlhbmEsIEtlbnR1Y2t5LCBMb3Vpc2lhbmEsIE1hcnlsYW5kLCBNaXNzaXNzaXBwaSwgTWlzc291cmksIE5ldyBKZXJzZXksIE5vcnRoIENhcm9saW5hLCBPaGlvLCBQZW5uc3lsdmFuaWEsIFNvdXRoIENhcm9saW5hLCBUZW5uZXNzZWUsIFZpcmdpbmlhLCBhbmQgV2VzdCBWaXJnaW5pYS4gWW91ciBjaXJjbGUgZG9lcyBub3QgbmVlZCB0byBpbmNsdWRlIGFsbCBvZiB0aGUgc3RhdGUsIGp1c3QgYSBzbWFsbCBwb3J0aW9uLiBTZWUgdGhlIGV4YW1wbGUgYmVsb3c6DQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1sYXNzby1zZWxlY3QucG5nIiBhbHQ9Ikxhc3NvIFNlbGVjdCBUb29sIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PC9wPg0KDQpXaXRoIHRoZSBzdGF0ZXMgc2VsZWN0ZWQsIHJldHVybiB0aGUgVGFibGUgb2YgQ29udGVudHMgdG8gdGhlICJMaXN0IGJ5IERyYXdpbmcgT3JkZXIiIGJ1dHRvbiA8aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtbGlzdC1kcmF3LWJ1dHRvbi5qcGciIGFsdD0iTGlzdCBieSBEcmF3aW5nIE9yZGVyIiB3aWR0aCA9ICIyMCIgaGVpZ2h0ID0gIjIwIj4gYW5kIHJpZ2h0LWNsaWNrIG9uIHRoZSBfVVNBX1N0YXRlc19Db250aW5lbnRhbF8mbmJzcDsgZGF0YXNldCBhbmQgY2hvb3NlICoqRGF0YSA+IEV4cG9ydCBGZWF0dXJlcyoqIGZyb20gdGhlIG1lbnUuIEluIHRoZSByZXN1bHRpbmcgbWVudSBpbmNsdWRlIHRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhbmQgY2xpY2sgT0s6DQoNCi0gX0lucHV0IEZlYXR1cmVzXyA9IFVTQV9TdGF0ZXNfQ29udGluZW50YWwNCi0gX091dHB1dCBMb2NhdGlvbl8gPSBTZWxlY3QgYSBmb2xkZXIgZm9yIHRoZSBleHBvcnQuIEl0IGl0IGltcG9ydGFudCB0aGF0IHlvdSBkbyBub3QgY2xpY2sgaW50byB0aGUgZm9sZGVyLCBzaW1wbHkgY2xpY2sgb25jZSB0byBzZWxlY3QgYW5kIGNsaWNrIE9LIChzZWUgZXhhbXBsZSkuDQotIF9PdXRwdXQgTmFtZV8gPSBjaG9vc2UgYSBuYW1lIGZvciB5b3VyIGZpbGUgYW5kICoqYWRkIC5zaHAqKiBiZWhpbmQgaXQgdG8gY3JlYXRlIGEgc2hhcGVmaWxlLg0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtZXhwb3J0LWRhdGEucG5nIiBhbHQ9IkV4cG9ydCBEYXRhIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PC9wPg0KDQpXaGVuIGZpbmlzaGVkIHlvdSBzaG91bGQgaGF2ZSB0aGUgZmlsZSBhZGRlZCB0byB5b3VyIHByb2plY3QuIEFub3RoZXIgdGVjaG5pcXVlIHRvIGlzb2xhdGUgZGF0YSBpcyBieSB1c2luZyB0aGUgKipDbGlwKiogYW5hbHlzaXMgdG9vbC4gVGhpcyB0b29sIGNhbiBiZSB1c2VkIHRvIGN1dCBvdXQgYSBwaWVjZSBvZiBvbmUgZGF0YXNldCB1c2luZyBvbmUgb3IgbW9yZSBvZiB0aGUgZmVhdHVyZXMgaW4gYW5vdGhlciBkYXRhc2V0IGFzIGEgImNvb2tpZSBjdXR0ZXIiLiBUaGlzIGlzIHVzZWZ1bCBmb3IgY3JlYXRpbmcgYSBuZXcgZGF0YXNldCB0aGF0IGNvbnRhaW5zIGEgZ2VvZ3JhcGhpYyBzdWJzZXQgb2YgdGhlIGZlYXR1cmVzIGluIGFub3RoZXIgbGFyZ2VyIGRhdGFzZXQuDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1jbGlwLWlsbHVzdHJhdGlvbi5wbmciIGFsdD0iQXJjR0lTIFBybyBDbGlwIElsbHVzdHJhdGlvbiIgd2lkdGg9IjUxNSIgaGVpZ2h0PSIyMDIiPjxmaWdjYXB0aW9uPjxzbWFsbD48Yj5JbGx1c3RyYXRpb24gZnJvbSBodHRwczovL3Byby5hcmNnaXMuY29tL2VuL3Byby1hcHAvbGF0ZXN0L3Rvb2wtcmVmZXJlbmNlL2FuYWx5c2lzL2NsaXAuaHRtPC9iPjwvc21hbGw+PC9maWdjYXB0aW9uPjwvcD4NCg0KVW5kZXIgdGhlIF9BbmFseXNpcyBUYWJfLCBjbGljayB0aGUgKipUb29scyoqIGJ1dHRvbiA8aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtdG9vbGJveC1idXR0b24uanBnIiBhbHQ9Ikdlb3Byb2Nlc3NpbmcgVG9vbHMgQnV0dG9uIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiPiB0byBvcGVuIGEgZ2VvcHJvY2Vzc2luZyBzZWFyY2ggbWVudS4gSW4gdGhlIHNlYXJjaCBib3ggYXQgdGhlIHRvcCBvZiB0aGUgbWVudSB0eXBlIGluIHRoZSB3b3JkICoqQ2xpcCoqIGFuZCBjbGljayBlbnRlci4gVGhlIGZpcnN0IG9wdGlvbiB3aWxsIHNob3cgIioqQ2xpcCoqIChBbmFseXNpcyBUb29scykiLiBDbGljayBvbiB0aGUgdG9vbCB0byBvcGVuIHRoZSBhc3NvY2lhdGVkIG1lbnUuIEluIHRoZSBuZXcgbWVudSBjaG9vc2UgdGhlIGZvbGxvd2luZyBvcHRpb25zIGZyb20gdGhlIGRyb3AtZG93biBtZW51cyBhbmQgY2xpY2sgUnVuIDoNCg0KLSBfSW5wdXQgRmVhdHVyZXNfID0gVVNBX0NvdW50aWVzDQotIF9DbGlwIEZlYXR1cmVzXyA9IGV4NF9TdGF0ZXMgKG9yIHRoZSBuYW1lIG9mIHRoZSBmaWxlIGZvciB0aGUgc2VsZWN0ZWQgc3RhdGVzIGluIHRoZSBwcmV2aW91cyBzdGVwKQ0KLSBfT3V0cHV0IEZlYXR1cmUgQ2xhc3NfID0gY2hvb3NlIGEgbmFtZSBmb3IgeW91ciBmaWxlIGFuZCBhZGQgLnNocCBiZWhpbmQgaXQgdG8gY3JlYXRlIGEgc2hhcGVmaWxlLg0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtY2xpcC10b29sLnBuZyIgYWx0PSJDbGlwIEFuYWx5c2lzIFRvb2wiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNClRoaXMgd2lsbCBjcmVhdGUgYSBkYXRhc2V0IGNvbnRhaW5pbmcgb25seSB0aGUgY291bnRpZXMgdGhhdCBhcmUgaW5jbHVkZWQgd2l0aGluIHRoZSBzdGF0ZXMgdXNlZCBhcyB0aGUgc2VsZWN0aW9uLiBXaGlsZSB0aGUgY29sb3JzIHdlcmUgYWx0ZXJlZCB0byBoaWdobGlnaHQgdGhlIGNoYW5nZXMgYW5kIGFkZGl0aW9ucyB0byB0aGUgcHJvamVjdCwgeW91IHNob3VsZCBub3cgc2VlIGEgbmV3IGRhdGFzZXQgaW4geW91ciBUYWJsZSBvZiBDb250ZW50cyB0aGF0IG9ubHkgY29udGFpbnMgdGhvc2UgY291bnRpZXMuIA0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtY2xpcHBlZC1kYXRhLnBuZyIgYWx0PSJDbGlwcGVkIENvdW50aWVzIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PGZpZ2NhcHRpb24+PHNtYWxsPjxiPkNvbG9ycyBhbHRlcmVkIGZyb20gcHJldmlvdXMgaW1hZ2VzIHRvIGhpZ2hsaWdodCBnZW9wcm9jZXNzaW5nIHJlc3VsdHMuPC9iPjwvc21hbGw+PC9maWdjYXB0aW9uPjwvcD4NCg0KRmluYWxseSwgd2hpbGUgaGF2aW5nIHRoZSBpbmRpdmlkdWFsIGh1cnJpY2FuZSB0cmFja3MgY2FuIGJlIGltcG9ydGFudCwgZm9yIHRoZSBwdXJwb3NlcyBvZiB0aGlzIGV4ZXJjaXNlIHlvdSBhcmUgZ29pbmcgdG8gdXNlIHRoZSAqKk1lcmdlKiogdG9vbCB0byBjb21iaW5lZCBhbGwgb2YgdGhlIGluZGl2aWR1YWwgaHVycmljYW5lIHRyYWNrcyBpbnRvIGEgc2luZ2xlIGRhdGFzZXQuIFNpbWlsYXIgdG8gdGhlIHByZXZpb3VzIHN0ZXAsIGNsaWNrIG9uIHRoZSBfVG9vbHNfJm5ic3A7IGJ1dHRvbiBvbiB0aGUgQW5hbHlzaXMgVGFiIGFuZCBzZWFyY2ggZm9yICoqTWVyZ2UqKi4gQ2xpY2sgb24gIioqTWVyZ2UqKiAoRGF0YSBNYW5hZ2VtZW50IFRvb2wpIiBhbmQgaW4gdGhlIG5ldyB3aW5kb3cgY2hvb3NlIHRoZSBmb2xsb3dpbmcgb3B0aW9ucyBmcm9tIHRoZSBkcm9wLWRvd24gbWVudSBhbmQgY2xpY2sgcnVuOg0KDQotIF9JbnB1dCBEYXRhc2V0c18gPSBFaXRoZXIgZnJvbSB0aGUgZHJvcC1kb3duIG1lbnUgb3IgdGhlIF9hZGQgbWFueSBidXR0b25fJm5ic3A7IDxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1hZGQtbWFueS1idXR0b24uanBnIiBhbHQ9IkFkZCBNYW55IiB3aWR0aCA9ICIxMCIgaGVpZ2h0ID0gIjEwIj4gc2VsZWN0IGFsbCBvZiB0aGUgaW5kaXZpZHVhbCBodXJyaWNhbmUgdHJhY2tzLiBJZiB1c2luZyB0aGUgImFkZCBtYW55IiBidXR0b24geW91IHdpbGwgbmVlZCB0byBjbGljayB0aGUgImFkZCIgbGluayBpbiB0aGUgYm90dG9tIHJpZ2h0LWhhbmQgY29ybmVyIG9mIHRoZSBpbnB1dC4gSWYgeW91IHVzZSB0aGUgZHJvcC1kb3duIG1lbnUgdGhlIGRhdGEgd2lsbCBhZGQgYXV0b21hdGljYWxseQ0KLSBfT3V0cHV0IERhdGFzZXRfID0gY2hvb3NlIGEgbmFtZSBmb3IgeW91ciBmaWxlIGFuZCBhZGQgLnNocCBiZWhpbmQgaXQgdG8gY3JlYXRlIGEgc2hhcGVmaWxlLg0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtbWVyZ2VkLWRhdGEucG5nIiBhbHQ9Ik1lcmdlZCBIdXJyaWNhbmVzIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PC9wPg0KDQpOb3cgeW91IGNhbiByZW1vdmUgdGhlIF9VU0FfQ291bnRpZXNfJm5ic3A7IGFuZCBhbGwgdGhlIGluZGl2aWR1YWwgaHVycmljYW5lIHRyYWNrIGZpbGVzIHRvIHJlZHVjZSB0aGUgY2x1dHRlciBpbiB5b3VyIFRhYmxlIG9mIENvbnRlbnRzLiBUbyBkbyB0aGlzIHlvdSBzaW1wbHkgcmlnaHQtY2xpY2sgb24gdGhlIGRhdGFzZXQgaW4gdGhlIFRhYmxlIG9mIENvbnRlbnRzIGFuZCBjbGljayBfUmVtb3ZlXy4NCg0KPGJpZz48Yj5RdWVzdGlvbiBOby4gMTwvYj48L2JpZz4NCjxibG9ja3F1b3RlPg0KSG93IG1hbnkgaW5kaXZpZHVhbCB0cmFjayBzZWdtZW50cyBhcmUgY29udGFpbmVkIGluIHRoZSBtZXJnZWQgaHVycmljYW5lIGRhdGFzZXQ/DQo8L2Jsb2NrcXVvdGU+DQoNCjwvZGV0YWlscz4NCjxocj48L2hyPg0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxiaWc+VmlldyBkaXJlY3Rpb25zIGluIDxiPiBbUUdJU117c3R5bGU9ImNvbG9yOiAjMDA2NDAwIn0gPC9iPjwvYmlnPjwvc3VtbWFyeT4NCg0KQXMgeW91IGhhdmUgZG9uZSB3aXRoIGVhY2ggb2YgdGhlIHByZXZpb3VzIGV4ZXJjaXNlcywgW0V4ZXJjaXNlIDJdKGh0dHBzOi8vY2hyaXNtZ2VudHJ5LmdpdGh1Yi5pby9HSVMxLUV4ZXJjaXNlLTIvKSBhbmQgW0V4ZXJjaXNlIDNdKGh0dHBzOi8vY2hyaXNtZ2VudHJ5LmdpdGh1Yi5pby9HSVMxLUV4ZXJjaXNlLTMvKSwgeW91IHdpbGwgYmVnaW4gYnkgbGF1bmNoaW5nIDxiPltRR0lTXXtzdHlsZT0iY29sb3I6ICMwMDY0MDAifTwvYj4gZnJvbSB0aGUgc3RhcnQgbWVudSwgbGF1bmNocGFkLCBvciBkZWtzdG9wIHNob3J0Y3V0LiBTdGFydCB3aXRoIGEgX05ldyBFbXB0eSBQcm9qZWN0XyZuYnNwOyBhbmQgc2F2ZSBpdCB0byB5b3VyIHByb2plY3QgZm9sZGVyLiANCg0KV2l0aCB5b3VyIHlvdXIgZW1wdHkgcHJvamVjdCBjcmVhdGVkLCBuYXZpZ2F0ZSB0byBHaXRIdWIgYW5kIGRvd25sb2FkICoqW2FsbCBkYXRhc2V0cyBmb3IgdGhpcyBleGVyY2lzZSBoZXJlXShodHRwczovL2dpdGh1Yi5jb20vY2hyaXNtZ2VudHJ5L0dJUzEtRXhlcmNpc2UtNC90cmVlL21haW4vRGF0YSkqKiB0byB5b3VyIHByb2plY3QgZm9sZGVyIGFuZCBleHRyYWN0IHRoZSBkYXRhLiBJZiB5b3UgaGF2ZSBhbnkgcXVlc3Rpb25zIG9uIGhvdyB0byByZXRyaWV2ZSBhbmQgZXh0cmFjdCB0aGUgZGF0YSByZWZlciB0byBbRXhlcmNpc2UgMiwgU3RlcCAxXShodHRwczovL2NocmlzbWdlbnRyeS5naXRodWIuaW8vR0lTMS1FeGVyY2lzZS0yLyMxMV9TdGVwX09uZTpfVGhlX0RhdGEpIGZvciBkZXRhaWxlZCBpbnN0cnVjdGlvbnMuDQoNCkFkZCB0aGUgX3N0YXRlc18sIF9jb3VudGllc18sIGFuZCBhbGwgX2h1cnJpY2FuZXNfJm5ic3A7IGRhdGFzZXRzIHRvIHRoZSBtYXAgdmlldy4gUmVtZW1iZXIgdGhhdCB0aGUgZGF0YXNldHMgaW4geW91ciBfTGF5ZXJzXyZuYnNwO21lbnUgYXJlIGRyYXduIGluIHRoZSBvcmRlciB0aGV5IGFwcGVhci4gU28gdGhlIGZpcnN0IGl0ZW0gb24gdGhlIGxpc3Qgd2lsbCBiZSB0aGUgZmlyc3Qgc2hvdywgZm9sbG93ZWQsIGJ5IHRoZSBzZWNvbmQgYW5kIHNvIG9uLiBUaGVyZWZvcmUsIGlmIHlvdSB3YW50IGNlcnRhaW4gZGF0YXNldHMgdG8gYmUgdmlzaWJsZSBhYm92ZSBhbGwgb3RoZXJzIGl0IHNob3VsZCBiZSBsb2NhdGVkIGF0IHRoZSB0b3AgYnkgY2xpY2tpbmcgYW5kIGRyYWdnaW5nIHRoZSBkYXRhIHVwIG9yIGRvd24gaW4gdGhlIGxpc3QuIEZvciBwb2x5Z29ucywgeW91IGNhbiBlZGl0IHRoZSBmaWxsIGFuZCB0cmFuc3BhcmVuY3kgKGZvdW5kIHVuZGVyIHRoZSBhcHBlYXJhbmNlIHRhYiBpbiBlZmZlY3RzKSB0byBhbGxvdyBmb3IgaXRlbXMgdW5kZXJuZWF0aCB0byBiZSBzY2VuZS4gRm9yIGV4YW1wbGUsIGluIHRoZSBpbWFnZSBiZWxvdywgdGhlIGh1cnJpY2FuZSB0cmFja3MgYXJlIG9yZGVyZWQgYnkgeWVhciBhbmQgYXJlIHNpdHVhdGVkIG9uIHRvcCBvZiB0aGUgY291bnR5IGFuZCBzdGF0ZSBwb2x5Z29ucy4gSWYgdGhlIHBvbHlnb25zIHdlcmUgZHJhd24gZmlyc3QsIHRoZSBodXJyaWNhbmUgdHJhY2tzIHdvdWxkIG5vdCBiZSBzaG93biBvbmNlIHRoZXkgbWFrZSBsYW5kZmFsbC4gSW4gdGhpcyBleGFtcGxlLCB0aGUgc3RhdGVzIHBvbHlnb25zIGFyZSBkaXNwbGF5ZWQgd2l0aCBhIGhvbGxvdyBmaWxsIGFuZCB3aGl0ZSBib3JkZXIgdG8gYWxsb3cgZm9yIHRoZSBjb3VudGllcyB0byBzaG93IHRocm91Z2ggd2l0aCB0aGVpciBibGFjayBib3JkZXJzLg0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzLWV4NC1kYXRhLnBuZyIgYWx0PSJFeGVyY2lzZSA0IERhdGFzZXRzIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PC9wPg0KDQpSZWZlciBiYWNrIHRvIHByZXZpb3VzIGV4ZXJjaXNlcyB0byByZXZpZXcgaG93IHRvIGNoYW5nZSB0aGUgc3ltYm9sb2d5IGZvciBhIGdpdmVuIGRhdGFzZXQuIFlvdSBzaG91bGQgZXhwZXJpbWVudCB3aXRoIGRpZmZlcmVudCBvcmRlciwgZmlsbCwgYW5kIHRyYW5zcGFyZW5jaWVzIHRvIGN1c3RvbWl6ZSB5b3VyIHZpZXcgb2YgdGhlIGRhdGEuDQoNCkJlY2F1c2UgRkVNQSBpcyBvbmx5IGludGVyZXN0ZWQgaW4gY291bnRpZXMgaW1wYWN0ZWQgYnkgaHVycmljYW5lcywgeW91IG5lZWQgdG8gc2VsZWN0IG9ubHkgdGhlIHN0YXRlcyB0aGF0IGFyZSBpbnRlcnNlY3RlZCBieSB0aGUgdHJhY2tzLiBUaGVyZSBhcmUgc2V2ZXJhbCB3YXlzIHRvIHN1YnNldCBkYXRhIGluIFtRR0lTXXtzdHlsZT0iY29sb3I6ICMwMDY0MDAifS4gRm9yIHRoaXMgZXhhbXBsZSB3ZSBjYW4gc2VsZWN0IGNvdW50aWVzIGJ5IG5hbWUgdGhyb3VnaCBhIHN0cnVjdHVyZWQgcXVlcnkgbGFuZ3VhZ2UgKFNRTCksIHdlIGNhbiB1c2UgZ3JhcGhpY2FsIHRvb2xzIHRvIHNlbGVjdCBkYXRhLCBhbmQgd2UgY2FuIHVzZSBnZW9wcm9jZXNzaW5nIHRvb2xzIHRvIHN1YnNldCB0aGUgZGF0YS4gQmVjYXVzZSB0aGlzIGlzIGEgbGVhcm5pbmcgbW9kdWxlLCB5b3Ugd2lsbCBiZSBsZWFybmluZyBzZXZlcmFsIGRpZmZlcmVudCB0ZWNobmlxdWVzLiBXaGlsZSB0aGlzIG1pZ2h0IG5vdCBuZWNlc3NhcmlseSBiZSB0aGUgcXVpY2tlc3QgbWV0aG9kLCB0aGUgcHVycG9zZSBvZiB0aGlzIGV4ZXJjaXNlIGlzIHRvIGludHJvZHVjZSB5b3UgdG8gc2V2ZXJhbCB0b29scyB5b3UgY2FuIHVzZSBhcyBhcHByb3ByaWF0ZSBpbiBmdXR1cmUgcHJvamVjdHMuDQoNClRvIGNvbnRpbnVlIGdhdGhlcmluZyBkYXRhIGZvciB0aGlzIGV4ZXJjaXNlIHlvdSBhcmUgZmlyc3QgZ29pbmcgdG8gaXNvbGF0ZSB0aGUgZGF0YSB5b3Ugd2FudCB0byBzZWxlY3QuIEJlZ2luIGJ5IGNsaWNraW5nIG9uIHRoZSBfVVNBX1N0YXRlc19Db250aW5lbnRhbF8mbmJzcDsgZGF0YXNldCB0byBtYWtlIGl0IHRoZSBvbmx5IHNlbGVjdGFibGUgbGF5ZXIuIE5leHQsIHVzaW5nIHRoZSAqKlNlbGVjdCBGZWF0dXJlcyAqKiB0b29sIDxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtc2VsZWN0LWZlYXR1cmVzLXRvb2wuanBnIiBhbHQ9IlNlbGVjdCBGZWF0dXJlcyBUb29sIiB3aWR0aCA9ICIyMCIgaGVpZ2h0ID0gIjIwIj4gdXNlIHRoZSBkcm9wLWRvd24gbWVudSB0byBjaG9vc2UgKipTZWxlY3QgRmVhdHVyZXMgYnkgRnJlZWhhbmQqKi4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGltZyBzcmM9ICJJbWFnZXMvcWdpcy1mcmVlaGFuZC1zZWxlY3QtdG9vbC5qcGciIGFsdD0iRnJlZWhhbmQgU2VsZWN0IiBzdHlsZT0id2lkdGg6NTAlIj48L3A+DQoNClNpbmdsZSBjbGljayBvbiB0aGUgbWFwIHNvbWV3aGVyZSBpbiB0aGUgR3VsZiBvZiBNZXhpY28gYW5kIHVzZSB0aGUgY3Vyc29yIHRvIGRyYXcgYSBjaXJjbGUgZW5jb21wYXNzaW5nIEFsYWJhbWEsIEFya2Fuc2FzLCBEZWxhd2FyZSwgRmxvcmlkYSwgR2VvcmdpYSwgSWxsaW5vaXMsIEluZGlhbmEsIEtlbnR1Y2t5LCBMb3Vpc2lhbmEsIE1hcnlsYW5kLCBNaXNzaXNzaXBwaSwgTWlzc291cmksIE5ldyBKZXJzZXksIE5vcnRoIENhcm9saW5hLCBPaGlvLCBQZW5uc3lsdmFuaWEsIFNvdXRoIENhcm9saW5hLCBUZW5uZXNzZWUsIFZpcmdpbmlhLCBhbmQgV2VzdCBWaXJnaW5pYS4gWW91ciBjaXJjbGUgZG9lcyBub3QgbmVlZCB0byBpbmNsdWRlIGFsbCBvZiB0aGUgc3RhdGUsIGp1c3QgYSBzbWFsbCBwb3J0aW9uLiBBZnRlciBjaXJjbGluZyB0aGUgc2VsZWN0ZWQgc3RhdGVzLCBzaW5nbGUgY2xpY2sgYWdhaW4gdG8gZmluaXNoIHRoZSBzZWxlY3Rpb24uIFNlZSB0aGUgZXhhbXBsZSBiZWxvdzoNCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvcWdpcy1kYXRhLXNlbGVjdGlvbi10b29sLnBuZyIgYWx0PSJEYXRhIFNlbGVjdGlvbiIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KSWYgeW91IG1ha2UgYSBtaXN0YWtlIHlvdSBjYW4gdXNlIHRoZSBfRGVzZWxlY3QgRmVhdHVyZXNfIGJ1dHRvbiA8aW1nIHNyYz0gIkltYWdlcy9xZ2lzLWNsZWFyLXNlbGVjdGlvbi1idXR0b24ucG5nIiBhbHQ9IkNsZWFyIFNlbGVjdCBGZWF0dXJlcyBUb29sIiB3aWR0aCA9ICIyMCIgaGVpZ2h0ID0gIjIwIj4gdG8gY2xlYXIgeW91ciBzZWxlY3Rpb24gYW5kIHRyeSBhZ2Fpbi4gV2l0aCB0aGUgc3RhdGVzIHNlbGVjdGVkLCByZXR1cm4gdGhlIExheWVycyBtZW51IHJpZ2h0L0NSVEwgY2xpY2sgb24gdGhlIFVTQV9TdGF0ZXNfQ29udGluZW50YWwgZGF0YXNldCBhbmQgY2hvb3NlICoqRXhwb3J0ID4gU2F2ZSBTZWxlY3RlZCBGZWF0dXJlcyBBcy4uLioqIGZyb20gdGhlIG1lbnUuIEluIHRoZSByZXN1bHRpbmcgbWVudSBpbmNsdWRlIHRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhbmQgY2xpY2sgT0s6DQoNCi0gX0Zvcm1hdF8gPSBFU1JJIFNoYXBlZmlsZQ0KLSBfRmlsZSBuYW1lXyA9IGNob29zZSBhIG5hbWUgYW5kIGxvY2F0aW9uIGZvciB5b3VyIGZpbGUgYnkgY2xpY2tpbmcgb24gdGhlIDxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtZm9sZGVyLXNlbGVjdC1idXR0b24uanBnIiBhbHQ9IlNlbGVjdCBGb2xkZXIgYW5kIEZpbGUgTmFtZSIgd2lkdGggPSAiMjAiIGhlaWdodCA9ICIyMCI+IGJ1dHRvbg0KLSBMZWF2ZSBhbGwgb3RoZXIgb3B0aW9ucyBhcyB0aGUgZGVmYXVsdA0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzLWV4cG9ydC1zZWxlY3Rpb24ucG5nIiBhbHQ9IkV4cG9ydCBEYXRhIFNlbGVjdGlvbiIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KV2hlbiBmaW5pc2hlZCB5b3Ugc2hvdWxkIGhhdmUgdGhlIGZpbGUgYWRkZWQgdG8geW91ciBwcm9qZWN0LiBBbm90aGVyIHRlY2huaXF1ZSB0byBpc29sYXRlIGRhdGEgaXMgYnkgdXNpbmcgdGhlICoqQ2xpcCoqIGFuYWx5c2lzIHRvb2wuIFRoaXMgdG9vbCBjYW4gYmUgdXNlZCB0byBjdXQgb3V0IGEgcGllY2Ugb2Ygb25lIGRhdGFzZXQgdXNpbmcgb25lIG9yIG1vcmUgb2YgdGhlIGZlYXR1cmVzIGluIGFub3RoZXIgZGF0YXNldCBhcyBhICJjb29raWUgY3V0dGVyIi4gVGhpcyBpcyB1c2VmdWwgZm9yIGNyZWF0aW5nIGEgbmV3IGRhdGFzZXQgdGhhdCBjb250YWlucyBhIGdlb2dyYXBoaWMgc3Vic2V0IG9mIHRoZSBmZWF0dXJlcyBpbiBhbm90aGVyIGxhcmdlciBkYXRhc2V0Lg0KDQo8cCBhbGlnbj0iY2VudGVyIj48aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtY2xpcC1pbGx1c3RyYXRpb24ucG5nIiBhbHQ9IkFyY0dJUyBQcm8gQ2xpcCBJbGx1c3RyYXRpb24iIHdpZHRoPSI1MTUiIGhlaWdodD0iMjAyIj48ZmlnY2FwdGlvbj48c21hbGw+PGI+SWxsdXN0cmF0aW9uIGZyb20gaHR0cHM6Ly9wcm8uYXJjZ2lzLmNvbS9lbi9wcm8tYXBwL2xhdGVzdC90b29sLXJlZmVyZW5jZS9hbmFseXNpcy9jbGlwLmh0bTwvYj48L3NtYWxsPjwvZmlnY2FwdGlvbj48L3A+DQoNCk9uIHRoZSBtZW51IGJhciwgc2VsZWN0ICoqVmVjdG9yID4gR2VvcHJvY2Vzc2luZyBUb29scyA+IENsaXAqKiB0byBvcGVuIHRoZSBjbGlwcGluZyBkaWFsb2cgYm94LiBDaG9vc2UgdGhlIGZvbGxvd2luZyBvcHRpb25zIGFuZCBjbGljayBSdW4gYXQgdGhlIGJvdHRvbSBvZiB0aGUgc2NyZWVuIHdoZW4gZmluaXNoZWQ6DQoNCi0gX0lucHV0IGxheWVyXyA9IFVTQV9Db3VudGllcw0KLSBfT3ZlcmxheSBsYXllcl8gPSBUaGUgZmlsZSBvZiBzZWxlY3RlZCBzdGF0ZXMgeW91IGNyZWF0ZWQgYWJvdmUNCi0gX0NsaXBwZWRfID0gV2hlbiBjcmVhdGluZyBuZXcgZGF0YXNldHMgeW91IGNhbiBjaG9vc2UgdG8gbGVhdmUgdGhpcyBzZWN0aW9uIGEgX0NyZWF0ZSB0ZW1wb3JvYXJ5IGxheWVyXyBvciB1c2UgdGhlIDxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtZm9sZGVyLXNlbGVjdC1idXR0b24uanBnIiBhbHQ9IlNlbGVjdCBGb2xkZXIgYW5kIEZpbGUgTmFtZSIgd2lkdGggPSAiMjAiIGhlaWdodCA9ICIyMCI+IGJ1dHRvbiB0byBjaG9vc2UgX1NhdmUgdG8gRmlsZS4uLl8uIFRlbXBvcmFyeSBsYXllcnMgYXJlIGdyZWF0IHdoZW4geW91IG5lZWQgdG8gY3JlYXRlIGFuIGludGVybWVkaWF0ZSBsYXllciB5b3UgZG8gbm90IHBsYW4gdG8gcmV0YWluIGZvciBhbmFseXNpcy4gSW4gdGhpcyBjYXNlLCBiZWNhdXNlIHdlIHdhbnQgdG8ga2VlcCB0aGUgZmlsZSwgaXQgaXMgYmVzdCB0byBzYXZlIGl0IGFzIGEgbmV3IHNoYXBlZmlsZS4gQW55IHRlbXBvcmFyeSBmaWxlIGNyZWF0ZWQgd2lsbCBiZSBsb3N0IG9uY2UgeW91IGNsb3NlIHRoZSBwcm9qZWN0Lg0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzLWNsaXAtdG9vbC5wbmciIGFsdD0iQ2xpcCIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KVGhpcyB3aWxsIGNyZWF0ZSBhIGRhdGFzZXQgY29udGFpbmluZyBvbmx5IHRoZSBjb3VudGllcyB0aGF0IGFyZSBpbmNsdWRlZCB3aXRoaW4gdGhlIHN0YXRlcyB1c2VkIGFzIHRoZSBzZWxlY3Rpb24uIFdoaWxlIHRoZSBjb2xvcnMgd2VyZSBhbHRlcmVkIHRvIGhpZ2hsaWdodCB0aGUgY2hhbmdlcyBhbmQgYWRkaXRpb25zIHRvIHRoZSBwcm9qZWN0LCB5b3Ugc2hvdWxkIG5vdyBzZWUgdGhlIG5ldyBkYXRhc2V0IGluIHlvdXIgTGF5ZXJzIG1lbnUgdGhhdCBvbmx5IGNvbnRhaW5zIHRob3NlIGNvdW50aWVzLg0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzLWNsaXBwZWQtZGF0YS5wbmciIGFsdD0iQ2xpcHBlZCBEYXRhIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PGZpZ2NhcHRpb24+PHNtYWxsPjxiPkNvbG9ycyBhbHRlcmVkIGZyb20gcHJldmlvdXMgaW1hZ2VzIHRvIGhpZ2hsaWdodCBnZW9wcm9jZXNzaW5nIHJlc3VsdHMuPC9iPjwvc21hbGw+PC9maWdjYXB0aW9uPjwvcD4NCg0KRmluYWxseSwgd2hpbGUgaGF2aW5nIHRoZSBpbmRpdmlkdWFsIGh1cnJpY2FuZSB0cmFja3MgY2FuIGJlIGltcG9ydGFudCwgZm9yIHRoZSBwdXJwb3NlcyBvZiB0aGlzIGV4ZXJjaXNlIHlvdSBhcmUgZ29pbmcgdG8gdXNlIHRoZSAqKk1lcmdlIHZlY3RvciBsYXllcnMqKiB0b29sIHRvIGNvbWJpbmVkIGFsbCBvZiB0aGUgaW5kaXZpZHVhbCBodXJyaWNhbmUgdHJhY2tzIGludG8gYSBzaW5nbGUgZGF0YXNldC4gVG8gbG9jYXRlIHRoaXMgdG9vbCB5b3Ugd2lsbCBuZWVkIHRvIGNsaWNrIHRoZSBfVG9vbGJveF8mbmJzcDsgYnV0dG9uIDxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtdG9vbGJveC1idXR0b24uanBnIiBhbHQ9IlByb2Nlc3NpbmcgVG9vbGJveCBCdXR0b24iIHdpZHRoID0gIjIwIiBoZWlnaHQgPSAiMjAiPiBvbiB0aGUgdG9vbGJhci4gVGhpcyB3aWxsIG9wZW4gdGhlICoqUHJvY2Vzc2luZyBUb29sYm94Kiogc2lkZSBtZW51IGFuZCBhbGxvdyB5b3UgdG8gc2VhcmNoIGZvciBtZXJnZS4NCg0KRG91YmxlIGNsaWNrIG9uIHRoZSAqKk1lcmdlIHZlY3RvciBsYXllcnMqKiB0b29sIGFuZCBpbiB0aGUgbmV3IHdpbmRvdyBjbGljayB0aGUgPGltZyBzcmM9ICJJbWFnZXMvcWdpcy1mb2xkZXItc2VsZWN0LWJ1dHRvbi5qcGciIGFsdD0iU2VsZWN0IEZvbGRlciBhbmQgRmlsZSBOYW1lIiB3aWR0aCA9ICIyMCIgaGVpZ2h0ID0gIjIwIj4gYnV0dG9uIGZvciB0aGUgX0lucHV0IGxheWVyc18uIFRoZSB3aW5kb3cgd2lsbCBzaGlmdCB0byBhbGxvdyB5b3UgdG8gc2VsZWN0IGFsbCBvZiB0aGUgaW5kaXZpZHVhbCBodXJyaWNhbmUgdHJhY2sgbGF5ZXJzLiBXaGVuIGNvbXBsZXRlIGNsaWNrIHRoZSByZXR1cm4gYXJyb3cgPGltZyBzcmM9ICJJbWFnZXMvcWdpcy1pbnB1dC1sYXllcnMtcmV0dXJuLWJ1dHRvbi5qcGciIGFsdD0iU2VsZWN0IEZvbGRlciBhbmQgRmlsZSBOYW1lIiB3aWR0aCA9ICIyMCIgaGVpZ2h0ID0gIjIwIj4gdG8gZ28gYmFjayB0byB0aGUgTWVyZ2UgVmVjdG9yIExheWVycyBkaWFsb2cgYm94LiBUaGUgX0lucHV0IGxheWVyc18mbmJzcDsgc2hvdWxkIG5vdyBzYXkgIjUgaW5wdXRzIHNlbGVjdGVkLiIgTmV4dCwgY2xpY2sgdGhlIDxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtZm9sZGVyLXNlbGVjdC1idXR0b24uanBnIiBhbHQ9IlNlbGVjdCBGb2xkZXIgYW5kIEZpbGUgTmFtZSIgd2lkdGggPSAiMjAiIGhlaWdodCA9ICIyMCI+IGJ1dHRvbiBmb3IgdGhlIHNlY3Rpb24gdGhhdCBzYXlzIF9NZXJnZWRfLiBXaGlsZSB5b3UgY291bGQgbWFrZSB0aGlzIGEgdGVtcG9yYXJ5IGxheWVyLCBpdCB3b3VsZCBiZSBiZXN0IHRvIHNhdmUgdGhlIGZpbGUgc2ltaWxhciB0byBpbiB0aGUgcHJldmlvdXMgc3RlcHMgdG8gcmV0YWluIGFjY2VzcyB0byB0aGUgbmV3IGRhdGFzZXQuDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtbWVyZ2UtZGlhbG9nMi5wbmciIGFsdD0iTWVyZ2VkIFZlY3RvciBMYXllcnMgRGlhbG9nIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PC9wPg0KDQpOb3cgeW91IGNhbiByZW1vdmUgdGhlIF9VU0FfQ291bnRpZXNfJm5ic3A7IGFuZCBhbGwgdGhlIGluZGl2aWR1YWwgaHVycmljYW5lIHRyYWNrIGZpbGVzIHRvIHJlZHVjZSB0aGUgY2x1dHRlciBpbiB5b3VyIExheWVycyBtZW51LiBUbyBkbyB0aGlzIHlvdSBzaW1wbHkgcmlnaHQvQ1JUTC1jbGljayBvbiB0aGUgZGF0YXNldCBpbiB0aGUgTGF5ZXJzIG1lbnUgYW5kIGNsaWNrIF9SZW1vdmUgTGF5ZXJfIG9yIGhpZGluZyB0aGUgbGF5ZXIgYnkgdW5jaGVja2luZyB0aGUgX2hpZGUgbGF5ZXJfJm5ic3A7IGJ1dHRvbiA8aW1nIHNyYz0gIkltYWdlcy9xZ2lzLWhpZGUtbGF5ZXItYnV0dG9uLmpwZyIgYWx0PSJIaWRlIExheWVyIEJ1dHRvbiIgd2lkdGggPSAiMjAiIGhlaWdodCA9ICIyMCI+LiANCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvcWdpcy1tZXJnZWQtZGF0YS5wbmciIGFsdD0iTWVyZ2VkIERhdGEgRXhhbXBsZSIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KPGJpZz48Yj5RdWVzdGlvbiBOby4gMTwvYj48L2JpZz4NCjxibG9ja3F1b3RlPg0KSG93IG1hbnkgaW5kaXZpZHVhbCB0cmFjayBzZWdtZW50cyBhcmUgY29udGFpbmVkIGluIHRoZSBtZXJnZWQgaHVycmljYW5lIGRhdGFzZXQ/DQo8L2Jsb2NrcXVvdGU+DQoNCjwvZGV0YWlscz4NCjxocj48L2hyPg0KDQo8ZGV0YWlscz48c3VtbWFyeT48YmlnPlZpZXcgZGlyZWN0aW9ucyBpbiA8Yj4gW1Jde3N0eWxlPSJjb2xvcjogIzY0OTVFRCJ9IDwvYj48L3NwYW4+PC9iaWc+PC9zdW1tYXJ5Pg0KQmVmb3JlIHlvdSBiZWdpbiwgeW91IHdpbGwgbmVlZCB0byBvcGVuIHRoZSBbRXg0IENvbGFiIE5vdGVib29rXShodHRwczovL2dpdGh1Yi5jb20vY2hyaXNtZ2VudHJ5L0dJUzEtRXhlcmNpc2UtNC9ibG9iL21haW4vR0lTMV9FWDQuaXB5bmIpIGFuZCBpbnNlcnQgKip0b2NvbGFiKiogYWZ0ZXIgX2dpdGh1Yl8gaW4gdGhlIFVSTCB0byBvcGVuIGluIHRoZSBfQ29sYWIgRW52aXJvbm1lbnRfLiBJZiB5b3UgaGF2ZSBhbnkgcXVlc3Rpb25zIHJlZ2FyZGluZyBDb2xhYiBOb3RlYm9va3MgcmVmZXIgdG8gW0V4ZXJjaXNlIDIsIEludHJvZHVjdGlvbl0oaHR0cHM6Ly9jaHJpc21nZW50cnkuZ2l0aHViLmlvL0dJUzEtRXhlcmNpc2UtMi8pIGZvciA8Yj5bUl17c3R5bGU9ImNvbG9yOiAjNjQ5NUVEIn08L2I+LiBSZW1lbWJlciB0byBtYWtlIGEgY29weSBvZiB0aGUgbm90ZWJvb2suIEFzIHlvdSBoYXZlIHNlZW4gYmVmb3JlLCBSIHJlcXVpcmVzIHZhcmlvdXMgcGFja2FnZXMgdG8gY29tcGxldGUgY2VydGFpbiBhbmFseXNlcy4gSW4gdGhpcyBleGVyY2lzZSB5b3Ugd2lsbCBiZSB1c2luZyAqKnRpZHl2ZXJzZSwgZ2dzbiwgY293cGxvdCwgbWFwcywgbWFwcHJvaiwgcGx5ciwgcmFzdGVyLCByZ2VvcywgcmdkYWwsIHNwKSoqLiBUaGlzIGlzIGEgbGFyZ2UgbnVtYmVyIG9mIHBhY2thZ2VzIGFuZCB3aWxsIHRha2UgYSB3aGlsZSB0byBsb2FkLiBUbyBpbnN0YWxsIGFuZCBsb2FkIHRoZSBwYWNrYWdlcyB3ZSB3aWxsIHVzZSB0aGUgZm9sbG93aW5nIHNjcmlwdDoNCg0KYGBge3IgaW5zdGFsbCBwYWNrYWdlcywgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI2luc3RhbGwucGFja2FnZXMoJ3RpZHl2ZXJzZScpDQojaW5zdGFsbC5wYWNrYWdlcygnZ2dzbicpDQojaW5zdGFsbC5wYWNrYWdlcygnY293cGxvdCcpDQojaW5zdGFsbC5wYWNrYWdlcygnbWFwcycpDQojaW5zdGFsbC5wYWNrYWdlcygnbWFwcHJvaicpDQojaW5zdGFsbC5wYWNrYWdlcygncGx5cicpDQojaW5zdGFsbC5wYWNrYWdlcygncmFzdGVyJykNCiNpbnN0YWxsLnBhY2thZ2VzKCdyZ2VvcycpDQojaW5zdGFsbC5wYWNrYWdlcygncmdkYWwnKQ0KI2luc3RhbGwucGFja2FnZXMoJ3NwJykNCmxpYnJhcnkoJ3RpZHl2ZXJzZScpDQpsaWJyYXJ5KCdnZ3NuJykNCmxpYnJhcnkoJ2Nvd3Bsb3QnKQ0KbGlicmFyeSgnbWFwcycpDQpsaWJyYXJ5KCdtYXBwcm9qJykNCmxpYnJhcnkoJ3BseXInKQ0KbGlicmFyeSgncmFzdGVyJykNCmxpYnJhcnkoJ3JnZW9zJykNCmxpYnJhcnkoJ3JnZGFsJykNCmxpYnJhcnkoJ3NwJykNCmxpYnJhcnkoJ3V0aWxzJykNCmBgYA0KDQpJbiBmdXR1cmUgZXhlcmNpc2VzIHlvdSB3aWxsIGxlYXJuIGhvdyB0byByZWR1Y2UgdGhlIHNjcmlwdCBhYm92ZSB0byBsb2FkIGFuZCBpbnN0YWxsIHBhY2thZ2VzIGluIGZld2VyIGxpbmVzLiBBZGRpdGlvbmFsbHksIHRoZXJlIGFyZSBjZXJ0YWluIGZ1bmN0aW9ucyB0aGF0IGFyZSBkdXBsaWNhdGVkIGJldHdlZW4gZGlmZmVyZW50IHBhY2thZ2VzLiBUaGVyZWZvcmUsIGluIHRoaXMgZXhlcmNpc2UgeW91IHdpbGwgbGVhcm4gdG8gdXNlICoqOjoqKiAoZG91YmxlIGNvbG9ucykgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB5b3Ugd2FudCB0byBleGVjdXRlIGEgc3BlY2lmaWMgZnVuY3Rpb24uDQoNCkZvciB0aGlzIGV4ZXJjaXNlIHlvdSB3aWxsIHVzZSBhIGNvbWJpbmF0aW9uIG9mIGJ1aWx0IGluIGRhdGEgZnJvbSB2YXJpb3VzIHBhY2thZ2VzIGFuZCBkb3dubG9hZGVkIGRhdGEgZnJvbSB0aGUgYWJvdmUgc291cmNlcyBpbiB0aGUgZm9ybSBvZiBhIHNoYXBlZmlsZS4gQSBbc2hhcGVmaWxlXShodHRwczovL2Rlc2t0b3AuYXJjZ2lzLmNvbS9lbi9hcmNtYXAvbGF0ZXN0L21hbmFnZS1kYXRhL3NoYXBlZmlsZXMvd2hhdC1pcy1hLXNoYXBlZmlsZS5odG0pIGlzIGEgInNpbXBsZSwgbm9uLXRvcG9sb2dpY2FsIGZvcm1hdCBmb3Igc3RvcmluZyB0aGUgZ2VvbWV0cmljIGxvY2F0aW9uIGFuZCBhdHRyaWJ1dGUgaW5mb3JtYXRpb24gb2YgZ2VvZ3JhcGhpYyBmZWF0dXJlcy4gRmVhdHVyZXMgY2FuIGJlIHJlcHJlc2VudGVkIGJ5IHBvaW50cywgbGluZXMsIG9yIHBvbHlnb25zLiBUaGUgd29ya3NwYWNlIGNvbnRhaW5pbmcgc2hhcGVmaWxlcyBtYXkgYWxzbyBjb250YWluIGEgZGF0YWJhc2UgbWFuYWdlIHRhYmxlLCB3aGljaCBjYW4gc3RvcmUgYWRkaXRpb25hbCBhdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIGpvaW5lZCB0byBhIHNoYXBlZmlsZXMgZmVhdHVyZXMuIg0KDQpJbiBwcmV2aW91cyBleGVyY2lzZXMgeW91IGNyZWF0ZWQgcmVsYXRpdmVseSBzaW1wbGlzdGljIG1hcHMgYW5kIGRlc2lnbiBsYXlvdXRzLiBNb3JlIGZ1bGx5IGRldmVsb3BlZCBtYXBzIGNvbnRhaW4gYWRkaXRpb25hbCBnZW9ncmFwaGljIGRhdGEsIG9yIGJhc2UgbWFwcywgdGhhdCBjYW4gYmUgdXNlZCB0byBwcm92aWRlIHJlZmVyZW5jZSBvciBsb2NhdGlvbiBpbmZvcm1hdGlvbi4gSW4gdGhpcyBleGVyY2lzZSB5b3Ugd2lsbCBhbHNvIGNyZWF0ZSBhbiBpbnNldCBtYXAgb3IgcmVmZXJlbmNlIG1hcCB0aGF0IHByb3ZpZGVzIGFuIG92ZXJ2aWV3Lg0KDQpUbyBiZWdpbiwgeW91IHdpbGwgdXNlIHRoZSBpbmZvcm1hdGlvbiBmcm9tIHRoZSBfbWFwcyBwYWNrYWdlXyB0byBjcmVhdGUgYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHN0YXRlcyBvZiBBbGFiYW1hLCBBcmthbnNhcywgRGVsYXdhcmUsIEZsb3JpZGEsIEdlb3JnaWEsIElsbGlub2lzLCBJbmRpYW5hLCBLZW50dWNreSwgTG91aXNpYW5hLCBNYXJ5bGFuZCwgTWlzc2lzc2lwcGksIE1pc3NvdXJpLCBOZXcgSmVyc2V5LCBOb3J0aCBDYXJvbGluYSwgT2hpbywgUGVubnN5bHZhbmlhLCBTb3V0aCBDYXJvbGluYSwgVGVubmVzc2VlLCBWaXJnaW5pYSwgYW5kIFdlc3QgVmlyZ2luaWEuIFRoZSBwcm9jZXNzIGlzIHNpbWlsYXIgdG8gdGhlIGRpcmVjdGlvbnMgZm9yIFtFeGVyY2lzZSAyLCBTdGVwIDFdKGh0dHBzOi8vY2hyaXNtZ2VudHJ5LmdpdGh1Yi5pby9HSVMxLUV4ZXJjaXNlLTIvIzExX1N0ZXBfT25lOl9UaGVfRGF0YSkgYW5kIFtFeGVyY2lzZSAzLCBTdGVwIDFdKGh0dHBzOi8vY2hyaXNtZ2VudHJ5LmdpdGh1Yi5pby9HSVMxLUV4ZXJjaXNlLTMvIzExX1N0ZXBfT25lOl9UaGVfRGF0YSkuDQoNCmBgYHtyIHNlIHN0YXRlcywgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc3RhdGVzIDwtIG1hcF9kYXRhKG1hcCA9ICJzdGF0ZSIsIHJlZ2lvbiA9ICBjKCJhbGFiYW1hIiwiYXJrYW5zYXMiLCJkZWxhd2FyZSIsImZsb3JpZGEiLCJnZW9yZ2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiaWxsaW5vaXMiLCJpbmRpYW5hIiwia2VudHVja3kiLCJsb3Vpc2lhbmEiLCJtYXJ5bGFuZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1pc3Npc3NpcHBpIiwibWlzc291cmkiLCJuZXcgamVyc2V5Iiwibm9ydGggY2Fyb2xpbmEiLCJvaGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGVubnN5bHZhbmlhIiwic291dGggY2Fyb2xpbmEiLCJ0ZW5uZXNzZWUiLCJ2aXJnaW5pYSIsIndlc3QgdmlyZ2luaWEiKSkNCg0KZ2dwbG90KHN0YXRlcykgKyANCiAgZ2VvbV9wb2x5Z29uKGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGNvbG9yID0gIndoaXRlIikgKw0KICBjb29yZF9maXhlZCgpDQpgYGANClRvIGFkZCBjb250ZXh0dWFsIGRhdGEgYW5kIGF2b2lkIHRoZSBhcHBlYXJhbmNlIG9mICJmbG9hdGluZyBkYXRhIiB5b3Ugd2lsbCBuZXh0IGNyZWF0ZSBhbiBvYmplY3QgdG8gZmlsbCBpbiB0aGUgc3Vycm91bmRpbmcgc3RhdGVzLg0KDQpgYGB7ciB1cyBzdGF0ZXMsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnVzIDwtIG1hcF9kYXRhKCdzdGF0ZScpDQoNCmdncGxvdCgpICsgDQogIGdlb21fcG9seWdvbihkYXRhID0gdXMsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJncmF5IikgKyANCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBzdGF0ZXMsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGNvbG9yID0gIndoaXRlIikgKyANCiAgY29vcmRfZml4ZWQoKQ0KYGBgDQpUbyBhZGQgdGhlIGh1cnJpY2FuZSBpbmZvcm1hdGlvbiBmcm9tIE5PQUEgeW91IG5lZWQgdG8gZG93bmxvYWQgdGhlIHNoYXBlZmlsZXMsIGV4dHJhY3QgdGhlIGRhdGFzZXQsIGFuZCByZWFkIGluIHRoZSBmaWxlcy4gVG8gZG8gdGhpcyB5b3Ugd2lsbCB1c2UgdGhlIGBgYHJlYWRPR1JgYGAgZnVuY3Rpb24gZnJvbSB0aGUgKipbcmdkYWxdKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9yZ2RhbC92ZXJzaW9ucy8xLjUtMjMvdG9waWNzL3JlYWRPR1IpKiogcGFja2FnZS4gWW91IHdpbGwgdXNlIHRoZSBgZG93bmxvYWQuZmlsZWAgZnVuY3Rpb24gYW5kIGdpdGh1YiBsaW5rIHRvIG9idGFpbiB0aGUgemlwIGZpbGUgYW5kIHRoZSBgdW56aXBgIGZ1bmN0aW9uIHRvIGV4dHJhY3QgdGhlIGRhdGEuIFRoZSBgcmVhZE9HUmAgZnVuY3Rpb24gcmVxdWlyZXMgbGlzdGluZyB0aGUgcGF0aCB0byB0aGUgZmlsZSB0byBpbXBvcnQgdGhhdCBkYXRhLiBJbiB0aGUgcGF0aCBiZWxvdyB5b3Ugd2lsbCBzZWUgYSAqKi4qKiAocGVyaW9kKSBpbiBmcm9udCBvZiB0aGUgL0h1cnJpY2FuZXMgZm9sZGVyLiBUaGUgcGVyaW9kIGlzIGEgc2hvcnRjdXQgdmVyc2lvbiB0byBzYXkgImluIHRoZSBwcm9qZWN0IGZvbGRlciIgaW5zdGVhZCBvZiB0eXBpbmcgb3V0IHRoZSBlbnRpcmUgZm9sZGVyIHBhdGguDQoNCmBgYHtyIE5PQUEgZGF0YSwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZG93bmxvYWQuZmlsZSgnaHR0cHM6Ly9naXRodWIuY29tL2NocmlzbWdlbnRyeS9HSVMxLUV4ZXJjaXNlLTQvcmF3L21haW4vRGF0YS9IdXJyaWNhbmVzLnppcCcsICdodXJyaWNhbmVzLnppcCcpDQp1bnppcCgnaHVycmljYW5lcy56aXAnKQ0KDQpkb3JpYW4gPC0gcmVhZE9HUigiLi9IdXJyaWNhbmVzIiwiRG9yaWFuXzIwMTlfbGluZSIpDQppcm1hIDwtIHJlYWRPR1IoIi4vSHVycmljYW5lcyIsIklybWFfMjAxN19saW5lIikNCmxhdXJhIDwtcmVhZE9HUigiLi9IdXJyaWNhbmVzIiwiTGF1cmFfMjAyMF9saW5lIikgDQptYXR0aGV3IDwtcmVhZE9HUigiLi9IdXJyaWNhbmVzIiwiTWF0dGhld18yMDE2X2xpbmUiKSANCm1pY2hhZWwgPC1yZWFkT0dSKCIuL0h1cnJpY2FuZXMiLCJNaWNoYWVsXzIwMThfbGluZSIpDQpgYGANCg0KTmV4dCB5b3Ugd2lsbCB1c2UgdGhlIGByYmluZGAgZnVuY3Rpb24sIHdoaWNoIGlzIGEgYmFzZSBSIGZ1bmN0aW9uLCB0byBjb21iaW5lIGFsbCBvZiB0aGUgaW5kaXZpZHVhbCB0cmFja3MgaW50byBvbmUuIEhvd2V2ZXIsIGJlY2F1c2Ugb2YgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YSB0aGVyZSBhcmUgc29tZSBhZGRpdGlvbmFsIHN0ZXBzIHRoYXQgbmVlZCB0byBiZSB0YWtlbiBiZWZvcmUgdGhlIGRhdGEgY2FuIGJlIHVzZWQgaW4gYGdncGxvdDJgLiBUaGUgZmlyc3QgaXMgdG8gY3JlYXRlIGEgY29sdW1uIG9mIHJvdyBpZHMgZm9yIGVhY2ggcm93IHRvIHVzZSBpbiBhIGZ1dHVyZSBzdGVwIHRvIGNvbm5lY3QgdGhlIGRhdGEuIFRoZW4gdGhlIGBmb3J0aWZ5YCBmdW5jdGlvbiBmcm9tICoqZ2dwbG90MioqIGNhbiBiZSB1c2VkIHRvIGNvbnZlcnQgdGhlIGRhdGEgdG8gYW4gb2JqZWN0IHRoYXQgY2FuIGJlIGltcG9ydGVkIGludG8gdGhlIG1hcC4gRmluYWxseSwgdGhlIGBqb2luYCBmdW5jdGlvbiBmcm9tIHRoZSAqKnBseXIqKiBwYWNrYWdlIGNhbiBiZSB1c2VkIHRvIGF0dGFjaCB0aGUgZGF0YSBsb3N0IGluIHRoZSBjb252ZXJzaW9uIGZyb20gdGhlIG9yaWdpbmFsIGRhdGFzZXQgdG8gdGhlIG5ldyBnZ3Bsb3QyIHJlYWR5IGRhdGFzZXQuDQoNCmBgYHtyIGNvbWJpbmUgaHVycmljYW5lcywgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KaHVycmljYW5lcyA8LSByYmluZChkb3JpYW4saXJtYSxsYXVyYSxtYXR0aGV3LG1pY2hhZWwpDQpodXJyaWNhbmVzQGRhdGEkaWQgPC0gcm93bmFtZXMoaHVycmljYW5lc0BkYXRhKQ0Kc3BfaHVycmljYW5lcyA8LSBmb3J0aWZ5KGh1cnJpY2FuZXMpDQpodXJyaWNhbmVfdHJhY2tzIDwtIHBseXI6OmpvaW4oc3BfaHVycmljYW5lcyxodXJyaWNhbmVzQGRhdGEsIGJ5ID0gImlkIikNCmBgYA0KDQpOZXh0IHlvdSB3aWxsIHRha2Ugc2ltaWxhciBzdGVwcyB0byBkb3dubG9hZCBhbmQgZXh0cmFjdCBhIGNvdW50aWVzIHNoYXBlZmlsZSwgc3Vic2V0IHRoZSBjb3VudGllcyB0byBpbmNsdWRlIHRob3NlIGluIHRoZSBzZWxlY3RlZCBzdGF0ZXMgYWJvdmUsIGFuZCBmaW5hbGx5LCBwcmVwYXJlIHRoZSBkYXRhc2V0IGZvciB1c2Ugd2l0aCBgZ2dwbG90MmAuDQoNCmBgYHtyIGNvdW50aWVzIGRhdGEsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vZ2l0aHViLmNvbS9jaHJpc21nZW50cnkvR0lTMS1FeGVyY2lzZS00L3Jhdy9tYWluL0RhdGEvVVNfQ291bnRpZXMuemlwJywgJ2NvdW50aWVzLnppcCcpDQp1bnppcCgnY291bnRpZXMuemlwJykNCg0KY291bnRpZXMgPC0gcmVhZE9HUigiLiIsIlVTQV9Db3VudGllcyIpDQpzdWJzZXRfY291bnRpZXMgPC0gY291bnRpZXNbY291bnRpZXMkU1RBVEVfTkFNRSA9PSAiQWxhYmFtYSIgfCBjb3VudGllcyRTVEFURV9OQU1FID09ICJBcmthbnNhcyJ8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50aWVzJFNUQVRFX05BTUUgPT0gIkRlbGF3YXJlIiB8IGNvdW50aWVzJFNUQVRFX05BTUUgPT0gIkZsb3JpZGEifA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudGllcyRTVEFURV9OQU1FID09ICJHZW9yZ2lhIiB8IGNvdW50aWVzJFNUQVRFX05BTUUgPT0gIklsbGlub2lzInwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRpZXMkU1RBVEVfTkFNRSA9PSAiSW5kaWFuYSIgfCBjb3VudGllcyRTVEFURV9OQU1FID09ICJLZW50dWNreSJ8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50aWVzJFNUQVRFX05BTUUgPT0gIkxvdWlzaWFuYSIgfCBjb3VudGllcyRTVEFURV9OQU1FID09ICJNYXJ5bGFuZCJ8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50aWVzJFNUQVRFX05BTUUgPT0gIk1pc3Npc3NpcHBpIiB8IGNvdW50aWVzJFNUQVRFX05BTUUgPT0gIk1pc3NvdXJpInwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRpZXMkU1RBVEVfTkFNRSA9PSAiTmV3IEplcnNleSIgfCBjb3VudGllcyRTVEFURV9OQU1FID09ICJOb3J0aCBDYXJvbGluYSJ8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50aWVzJFNUQVRFX05BTUUgPT0gIk9oaW8iIHwgY291bnRpZXMkU1RBVEVfTkFNRSA9PSAiUGVubnN5bHZhbmlhInwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRpZXMkU1RBVEVfTkFNRSA9PSAiU291dGggQ2Fyb2xpbmEiIHwgY291bnRpZXMkU1RBVEVfTkFNRSA9PSAiVGVubmVzc2VlInwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRpZXMkU1RBVEVfTkFNRSA9PSAiVmlyZ2luaWEiIHwgY291bnRpZXMkU1RBVEVfTkFNRSA9PSAiV2VzdCBWaXJnaW5pYSIsXQ0KDQpzdWJzZXRfY291bnRpZXNAZGF0YSRpZCA8LSByb3duYW1lcyhzdWJzZXRfY291bnRpZXNAZGF0YSkNCmNvdW50aWVzX2RhdGEgPC0gZm9ydGlmeShzdWJzZXRfY291bnRpZXMpDQpzZV9jb3VudGllcyA8LSBwbHlyOjpqb2luKGNvdW50aWVzX2RhdGEsc3Vic2V0X2NvdW50aWVzQGRhdGEsIGJ5ID0gImlkIikNCmBgYA0KDQpOb3cgeW91IGNhbiB1c2UgYGdncGxvdDJgIHRvIHZpc3VhbGl6ZSB0aGUgZGF0YS4gVGhlIHN0ZXBzIHRvIGRpc3BsYXkgdGhlIGRhdGEgYXJlIHNpbWlsYXIgdG8gdGhvc2UgZnJvbSBbRXhlcmNpc2UgMiwgU3RlcCAzXShodHRwczovL2NocmlzbWdlbnRyeS5naXRodWIuaW8vR0lTMS1FeGVyY2lzZS0yLyMxM19TdGVwX1RocmVlOl9UaGVfVmlzdWFsaXphdGlvbikgb3IgW0V4ZXJjaXNlIDMsIFN0ZXAgM10oaHR0cHM6Ly9jaHJpc21nZW50cnkuZ2l0aHViLmlvL0dJUzEtRXhlcmNpc2UtMy8jMTNfU3RlcF9UaHJlZTpfVGhlX1Zpc3VhbGl6YXRpb24pLiANCg0KYGBge3IgZmlyc3QgdmlzdWFsaXphdGlvbiwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZ2dwbG90KCkgKyANCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB1cywgYWVzKHg9bG9uZywgeT1sYXQsIGdyb3VwPWdyb3VwKSwgY29sb3IgPSAid2hpdGUiLCBmaWxsID0gImdyYXkiKSArDQogIGdlb21fcG9seWdvbihkYXRhID0gc3RhdGVzLCBhZXMoeD1sb25nLCB5PWxhdCwgZ3JvdXA9Z3JvdXApLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgICBnZW9tX3BvbHlnb24oZGF0YSA9IHNlX2NvdW50aWVzLCBhZXMoeD1sb25nLCB5PWxhdCwgZ3JvdXA9Z3JvdXApLCBjb2xvciA9ICJkYXJrZ3JheSIsIGZpbGwgPSAiTkEiKSArDQogIGdlb21fcGF0aChkYXRhID0gaHVycmljYW5lX3RyYWNrcywgYWVzKHg9bG9uZywgeT1sYXQsIGdyb3VwPWdyb3VwKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDIpICsNCiAgY29vcmRfZml4ZWQoeGxpbSA9IGMoLTEyNSwtNjUpLCB5bGltID0gYygyNSw1MCkpDQpgYGANCk5vdGljZSBpbiB0aGUgY29kZSBhYm92ZSBgY29vcmRfZml4ZWQoKWAgaXMgdXNlZCB0byBsaW1pdCB0aGUgcmFuZ2Ugb2YgdGhlIG1hcC4gVGhpcyB3aWxsIGJlIGltcG9ydGFudCBpbiBmdXR1cmUgdmlzdWFsaXphdGlvbnMuDQoNCjxiaWc+PGI+UXVlc3Rpb24gTm8uIDE8L2I+PC9iaWc+DQo8YmxvY2txdW90ZT4NCldoYXQgdmFyaWFibGVzIGFyZSBwcmVzZW50IGluIHRoZSBodXJyaWNhbmUgdHJhY2sgZGF0YXNldD8gV2hpY2ggb2YgdGhlc2UgY291bGQgYmUgdXNlZCB0byBjYXRlZ29yaXplIHRoZSBkYXRhIGluIGEgbmV3IHZpc3VhbGl6YXRpb24/IEFuc3dlciBpbiB0aGUgY29kZSBjZWxsIGJlbG93Lg0KPC9ibG9ja3F1b3RlPg0KDQo8L2RldGFpbHM+DQoNCiMjIFN0ZXAgVHdvOiBUaGUgQW5hbHlzZXMNCg0KSW4gdGhpcyBzdGVwIHlvdSB3aWxsIG9yZ2FuaXplIGFuZCBkaXNwbGF5IHRoZSBkYXRhIGluIG9yZGVyIHRvIHByZXBhcmUgaXQgZm9yIHRoZSBmaW5hbCB2aXN1YWxpemF0aW9uLg0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxiaWc+VmlldyBEaXJlY3Rpb25zIGluIDxiPiBbQXJjR0lTIFByb117c3R5bGU9ImNvbG9yOiNmZjQ1MDAifSA8L2I+PC9iaWc+PC9zdW1tYXJ5Pg0KDQpOb3cgdGhhdCB5b3UgaGF2ZSB0aGUgbmVjZXNzYXJ5IGRhdGEsIHlvdSBuZWVkIGRldGVybWluZSB3aGljaCBjb3VudGllcyBhcmUgbW9zdCBzaWduaWZpY2FudGx5IGltcGFjdGVkIGJ5IHRoZSBodXJyaWNhbmVzLiBCZWNhdXNlIGh1cnJpY2FuZSB3aW5kcyBjYW4gaW1wYWN0IGFyZWFzIGZhciBhd2F5IGZyb20gdGhlIGV5ZSBvciB0aGUgc3Rvcm0sIHlvdSB3aWxsIGJlZ2luIGJ5IGNyZWF0aW5nIGEgYnVmZmVyIGFyb3VuZCB0aGUgaHVycmljYW5lIHRyYWNrcy4gWW91IGNhbiBlaXRoZXIgdXNlIHRoZSAqKlRvb2xzKiogYnV0dG9uIDxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy10b29sYm94LWJ1dHRvbi5qcGciIGFsdD0iR2VvcHJvY2Vzc2luZyBUb29scyBCdXR0b24iIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+IG9uIHRoZSBfQW5hbHlzaXMgVGFiXyZuYnNwOyBvciBzZWFyY2ggZm9yICoqQnVmZmVyKiogaW4gdGhlIGxpc3Qgb2YgdG9vbHMgbmV4dCB0byB0aGUgYnV0dG9uLiBJbiB0aGUgQnVmZmVyIHdpbmRvdyBzZWxlY3QgdGhlIGZvbGxvd2luZyBvcHRpb25zIGFuZCBjbGljayBydW46DQoNCi0gX0lucHV0IEZlYXR1cmVzXyA9IFRoZSBtZXJnZWQgaHVycmljYW5lIGRhdGFzZXQNCi0gX091dHB1dCBGZWF0dXJlIENsYXNzXyA9IGNob29zZSBhIG5hbWUgZm9yIHlvdXIgZmlsZSBhbmQgYWRkIC5zaHAgYmVoaW5kIGl0IHRvIGNyZWF0ZSBhIHNoYXBlZmlsZQ0KLSBfRGlzdGFuY2VfID0gNTAgbWlsZXMgKGxpbmVhciB1bml0KQ0KLSBfU2lkZSBUeXBlXyA9IEZ1bGwNCi0gX0VuZCBUeXBlXyA9IFJvdW5kDQotIF9NZXRob2RfID0gUGxhbmFyDQotIF9EaXNzb2x2ZSBUeXBlXyA9IERpc3NvbHZlIGFsbCBvdXRwdXQgZmVhdHVyZXMgaW50byBhIHNpbmdsZSBmZWF0dXJlDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1idWZmZXItZGF0YS5wbmciIGFsdD0iQnVmZmVyIFRvb2wiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCklmIGluIHRoaXMgc3RlcCBvciB0aGUgbmV4dCB5b3UgZW5jb3VudGVyIGEgd2FybmluZyBzdGF0aW5nIHRoZXJlIGlzIGEgImRhdHVtIGNvbmZsaWN0IGJldHdlZW4gdGhlIGlucHV0IGFuZCBvdXRwdXQiLCBqdXN0IHByb2NlZWQgd2l0aCB0aGUgZXhlcmNpc2UuIFdlIHdpbGwgZGlzY3VzcyBfZGF0dW1zXywgYSBzZXQgb2YgcmVmZXJlbmNlIHBvaW50cyBvbiB0aGUgZWFydGgncyBzdXJmYWNlIGFnYWluc3Qgd2hpY2ggcG9zaXRpb24gbWVhc3VyZW1lbnRzIGFyZSBtYWRlLCBpbiBmdXR1cmUgZXhlcmNpc2VzLiBXaGlsZSB0aGV5IGFyZSBpbXBvcnRhbnQgdG8gdW5kZXJzdGFuZCwgZm9yIHRoZSBwdXJwb3NlcyBvZiB0aGlzIGV4ZXJjaXNlIHlvdSBjYW4gaWdub3JlIHRoZSB3YXJuaW5nLg0KDQpJbiB0aGlzIG5leHQgc3RlcCB5b3UgbmVlZCB0byBpc29sYXRlIG9ubHkgdGhlIGNvdW50aWVzIHRoYXQgYXJlIGxvY2F0ZWQgd2l0aGluIHRoaXMgYnVmZmVyLiBUbyBkbyB0aGlzLCBjbGljayB0aGUgKipTZWxlY3QgQnkgTG9jYXRpb24qKiBidXR0b24gPGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLXNlbGVjdC1sb2NhdGlvbi1idXR0b24uanBnIiBhbHQ9IlNlbGVjdCBCeSBMb2NhdGlvbiBCdXR0b24iIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+IG9uIHRoZSBfTWFwIFRhYl8mbmJzcDsgaW4gdGhlIFNlbGVjdGlvbiBTZWN0aW9uLiBJbiB0aGUgbmV3IG1lbnUgY2hvb3NlIHRoZSBmb2xsb3dpbmcgYW5kIGNsaWNrIE9LLg0KDQotIF9JbnB1dCBGZWF0dXJlc18gPSBZb3VyIGNsaXBwZWQgY291bnRpZXMNCi0gX1JlbGF0aW9uc2hpcF8gPSBDaG9vc2UgSW50ZXJzZWN0DQotIF9TZWxlY3RpbmcgRmVhdHVyZXNfID0gWW91ciBidWZmZXJlZCBodXJyaWNhbmVzDQotIF9TZWxlY3Rpb24gVHlwZV8gPSBOZXcgU2VsZWN0aW9uDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1zZWxlY3QtYnktbG9jYXRpb24ucG5nIiBhbHQ9IlNlbGVjdCBCeSBMb2NhdGlvbiIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KV2l0aCB0aGlzIHNlbGVjdGlvbiBtYWRlLCB5b3UgY2FuIHRha2UgdGhlIHNhbWUgc3RlcHMgYXMgYmVmb3JlIHRvIGNyZWF0ZSBhIG5ldyBkYXRhc2V0IGJ5IHJpZ2h0LWNsaWNraW5nIG9uIHRoZSBjbGlwcGVkIGNvdW50aWVzIGRhdGFzZXQgaW4gdGhlIFRhYmxlIG9mIENvbnRlbnRzLCBnb2luZyB0byBfRGF0YSA+IEV4cG9ydCBGZWF0dXJlc18mbmJzcDsgYW5kIGNyZWF0aW5nIGEgbmV3IHNoYXBlZmlsZSBvZiB0aGUgc2VsZWN0ZWQgY291bnRpZXMuIFlvdSBjYW4gbm93IHJlbW92ZSB0aGUgY2xpcHBlZCBjb3VudGllcyB5b3UgY3JlYXRlZCBpbiBzdGVwIG9uZSBvciBjaGFuZ2UgdGhlIHN5bWJvbG9neSB0byBtYWtlIHRoaXMgbmV3IHNlbGVjdGlvbiBzdGFuZCBvdXQuDQoNClRvIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uLCBvcGVuIHRoZSBhdHRyaWJ1dGUgdGFibGUgZm9yIHRoZSBuZXcgZGF0YXNldCB5b3UgY3JlYXRlZCBoaWdobGlnaHRpbmcgdGhlIGltcGFjdGVkIGNvdW50aWVzLiBSaWdodC1jbGljayBvbiB0aGUgY29sdW1uIGhlYWRlciBmb3IgdGhlICoqUG9wdWxhdGlvbioqIHZhcmlhYmxlLCBhbmQgc2VsZWN0IHN0YXRpc3RpY3MuDQoNCjxiaWc+PGI+UXVlc3Rpb24gTm8uIDI8L2I+PC9iaWc+DQo8YmxvY2txdW90ZT4NCldoYXQgaXMgdGhlIHRvdGFsIHBvcHVsYXRpb24gKFBPUDIwMDA7IHN1bSBpbmZvcm1hdGlvbikgb2YgdGhlIGNvdW50aWVzIGltcGFjdGVkIGJ5IHRoZXNlIGh1cnJpY2FuZXM/DQo8L2Jsb2NrcXVvdGU+DQoNCjwvZGV0YWlscz4NCjxocj48L2hyPg0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxiaWc+VmlldyBEaXJlY3Rpb25zIGluIDxiPiBbUUdJU117c3R5bGU9ImNvbG9yOiMwMDY0MDAifSA8L2I+PC9iaWc+PC9zdW1tYXJ5Pg0KDQpOb3cgdGhhdCB5b3UgaGF2ZSB0aGUgbmVjZXNzYXJ5IGRhdGEsIHlvdSBuZWVkIGRldGVybWluZSB3aGljaCBjb3VudGllcyBhcmUgbW9zdCBzaWduaWZpY2FudGx5IGltcGFjdGVkIGJ5IHRoZSBodXJyaWNhbmVzLiBCZWNhdXNlIGh1cnJpY2FuZSB3aW5kcyBjYW4gaW1wYWN0IGFyZWFzIGZhciBhd2F5IGZyb20gdGhlIGV5ZSBvciB0aGUgc3Rvcm0sIHlvdSB3aWxsIGJlZ2luIGJ5IGNyZWF0aW5nIGEgYnVmZmVyIGFyb3VuZCB0aGUgaHVycmljYW5lIHRyYWNrcy4gWW91IGNhbiBlaXRoZXIgZ28gdG8gKipWZWN0b3IgPiBHZW9wcm9jZXNzaW5nIFRvb2xzID4gQnVmZmVyKiogb24gdGhlIG1lbnUgYmFyIG9yIHNlYXJjaCBmb3IgKipCdWZmZXIqKiBpbiB0aGUgX1Byb2Nlc3NpbmcgVG9vbGJveF8mbmJzcDsgKHNpbWlsYXIgdG8gc2VhcmNoaW5nIGZvciBNZXJnZSkuIERvdWJsZS1jbGljayBvbiB0aGUgQnVmZmVyIHRvb2wsIHNlbGVjdCB0aGUgZm9sbG93aW5nIG9wdGlvbnMgYW5kIGNsaWNrIFJ1bjoNCg0KPHAgYWxpZ249ImNlbnRlciI+PGltZyBzcmM9ICJJbWFnZXMvcWdpcy1idWZmZXItYW5hbHlzaXMucG5nIiBhbHQ9IkJ1ZmZlciBUb29sIERpYWxvZyIgc3R5bGU9IndpZHRoOjc1JSI+PC9wPg0KDQotIF9JbnB1dCBsYXllcl8gPSBUaGUgbWVyZ2VkIGh1cnJpY2FuZSBmaWxlIHlvdSBjcmVhdGVkDQotIF9EaXN0YW5jZV8gPSAwLjgNCi0gX1NlZ21lbnRzXyA9IDQNCi0gX0VuZCBjYXAgc3R5bGVfID0gUm91bmQNCi0gX0pvaW4gc3R5bGVfID0gUm91bmQNCi0gX01pdGVyIGxpbWl0XyA9IDIuMA0KLSBDaGVjayB0aGUgYm94IGZvciBfRGlzc29sdmUgcmVzdWx0Xw0KLSBfQnVmZmVyZWRfIHNhdmUgdGhlIGZpbGUgaW4geW91ciBwcm9qZWN0IGZvbGRlcg0KDQpZb3UgbWF5IHJlY2VpdmUgYSB3YXJuaW5nIGFib3V0IHVzaW5nIGRlZ3JlZXMgdG8gY2FsY3VsYXRlIHRoZSBidWZmZXIuIElmIHNvIHlvdSBjYW4gZGlzbWlzcyBpdCBmb3Igbm93LiBJbiBmdXR1cmUgZXhlcmNpc2VzIHlvdSB3aWxsIHByb2plY3QgeW91ciBkYXRhc2V0LCBob3dldmVyIGZvciB0aGUgcHVycG9zZXMgb2YgdGhpcyBleGVyY2lzZSB5b3UgY2FuIGlnbm9yZSB0aGUgd2FybmluZy4gWW91ciBzY3JlZW4gc2hvdWxkIG5vdyBsb29rIHNpbWlsYXIgdG8gdGhpcyAoY29sb3JzIGhhdmUgYmVlbiBhbHRlcmVkIHRvIGhpZ2hsaWdodCB0aGUgcmVzdWx0cyk6DQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtYnVmZmVyZWQtZGF0YS5wbmciIGFsdD0iQnVmZmVyZWQgaHVycmljYW5lIGRhdGFzZXQiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCkZvciB0aGlzIGV4ZXJjaXNlLCB5b3UgYXJlIGdvaW5nIHRvIGFkZCBzYXRlbGxpdGUgaW1hZ2VyeSBmcm9tIGEgcmVtb3RlIGNvbm5lY3Rpb24uIEluIHRoZSBicm93c2VyLCBzY3JvbGwgZG93biB0byAqKlhZWiBUaWxlcyoqIGFuZCByaWdodC9DUlRMLWNsaWNrIHRvIGFkZCBhIOKAnE5ldyBDb25uZWN0aW9u4oCdLiBJbiB0aGUgcmVzdWx0aW5nIHdpbmRvdyBuYW1lIHRoZSBjb25uZWN0aW9uIOKAnEdvb2dsZSBTYXRlbGxpdGXigJ0gYW5kIHR5cGUgdGhlIGZvbGxvd2luZyBpbnRvIHRoZSBVUkw6DQoNCmBgYA0KaHR0cHM6Ly9tdDEuZ29vZ2xlLmNvbS92dC9seXJzPXMmeD17eH0meT17eX0mej17en0NCmBgYA0KDQpZb3UgY2FuIG5vdyBjbGljayBhbmQgZHJhZyAqKkdvb2dsZSBTYXRlbGxpdGUqKiBpbnRvIHRoZSBsYXllciB0byB2aWV3IHRoZSBzYXRlbGxpdGUgaW1hZ2VyeS4gUmVtZW1iZXIgdG8gYXJyYW5nZSB5b3VyIGxheWVyIHNvIHRoYXQgZWl0aGVyIHRoZSBmaWxsIGZvciBjb3VudGllcyBpcyB0cmFuc3BhcmVudCBvciB0aGUgc2F0ZWxsaXRlIGxheWVyIGlzIGFib3ZlIHRoZSBjb3VudGllcyBzbyB5b3UgY2FuIHNlZSB0aGUgaW1hZ2VyeS4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvcWdpcy1kYXRhLXdpdGgtc2F0ZWxsaXRlLnBuZyIgYWx0PSJBZGRpbmcgc2F0ZWxsaXRlIGRhdGEgYmFzZW1hcCIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KSW4gdGhpcyBuZXh0IHN0ZXAgeW91IG5lZWQgdG8gaXNvbGF0ZSBvbmx5IHRoZSBjb3VudGllcyB0aGF0IGFyZSBsb2NhdGVkIHdpdGhpbiB0aGUgaHVycmljYW5lIGJ1ZmZlci4gVG8gZG8gdGhpcywgY2xpY2sgKipWZWN0b3IgPiBSZXNlYXJjaCBUb29scyA+IFNlbGVjdCBCeSBMb2NhdGlvbioqIGZyb20gdGhlIG1lbnUgYmFyLiBJbiB0aGUgbmV3IG1lbnUgY2hvb3NlIHRoZSBmb2xsb3dpbmcgYW5kIGNsaWNrIFJ1bg0KDQo8cCBhbGlnbj0iY2VudGVyIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzLXNlbGVjdC1ieS1sb2NhdGlvbi5qcGciIGFsdD0iU2VsZWN0IGJ5IGxvY2F0aW9uIHRvb2wiIHN0eWxlPSJ3aWR0aDo3NSUiPjwvcD4NCg0KLSBfU2VsZWN0IGZlYXR1cmVzIGZyb21fID0gVGhlIGNsaXBwZWQgY291bnRpZXMgZGF0YXNldC4gVGhpcyBpcyB0aGUgZmlsZSB0aGF0IGNvbnRhaW5zIG9ubHkgdGhlIGNvdW50aWVzIGluIHRoZSBzZWxlY3RlZCBzdGF0ZXMuDQotIF9XaGVyZSB0aGUgZmVhdHVyZXMgKGdlb21ldHJpYyBwcmVkaWNhdGUpXyA9IENoZWNrIHRoZSBib3ggZm9yICoqaW50ZXJzZWN0KioNCi0gX0J5IGNvbXBhcmluZyB0byB0aGUgZmVhdHVyZXMgZnJvbV8gPSBUaGUgaHVycmljYW5lIGJ1ZmZlciBkYXRhc2V0DQotIF9Nb2RpZnkgY3VycmVudCBzZWxlY3Rpb24gYnlfID0gQ3JlYXRpbmcgbmV3IHNlbGVjdGlvbg0KDQpXaXRoIHRoaXMgc2VsZWN0aW9uIG1hZGUsIHlvdSBjYW4gdGFrZSB0aGUgc2FtZSBzdGVwcyBhcyBiZWZvcmUgdG8gY3JlYXRlIGEgbmV3IGRhdGFzZXQgYnkgcmlnaHQvQ1JUTC1jbGlja2luZyBvbiB0aGUgY2xpcHBlZCBjb3VudGllcyBkYXRhc2V0IGluIHRoZSBMYXllcnMgbWVudSwgZ29pbmcgdG8gKipFeHBvcnQgPiBTYXZlIFNlbGVjdGVkIEZlYXR1cmVzIEFzLi4uKiogYW5kIGNyZWF0aW5nIGEgbmV3IHNoYXBlZmlsZSBvZiB0aGUgc2VsZWN0ZWQgY291bnRpZXMuIA0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzLXNlbGVjdGVkLXNhdmUucG5nIiBhbHQ9IkV4cG9ydGluZyB0aGUgY3VycmVudCBzZWxlY3Rpb24iIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCllvdSBjYW4gbm93IHJlbW92ZSB0aGUgY2xpcHBlZCBjb3VudGllcyB5b3UgY3JlYXRlZCBpbiBzdGVwIG9uZSBvciBjaGFuZ2UgdGhlIHN5bWJvbG9neSB0byBtYWtlIHRoaXMgbmV3IHNlbGVjdGlvbiBzdGFuZCBvdXQuDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtc2VsZWN0LWJ5LWxvY2F0aW9uLWRhdGEucG5nIiBhbHQ9IkFsbCBBbmFseXplZCBEYXRhc2V0cyIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KVG8gYW5zd2VyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb24sIGNsaWNrIHRoZSBfU2hvdyBTdGF0aXN0aWNhbCBTdW1tYXJ5XyZuYnNwOyBidXR0b24gPGltZyBzcmM9ICJJbWFnZXMvcWdpcy1zdGF0aXN0aWNhbC1zdW1tYXJ5LWJ1dHRvbi5qcGciIGFsdD0iU2hvdyBTdGF0aXN0aWNhbCBTdW1tYXJ5IEJ1dHRvbiIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIj4gb24gdGhlIG1lbnUgYmFyLiBBIG5ldyBtZW51IHdpbGwgb3BlbiBpbiB0aGUgbGVmdC1oYW5kIGNvbHVtbiBvZiB0aGUgc2NyZWVuLiBJbiB0aGlzIG1lbnUgc2VsZWN0IHRoZSBkYXRhc2V0IHlvdSBjcmVhdGVkIGZvciB0aGUgaHVycmljYW5lIGltcGFjdGVkIGNvdW50aWVzIGluIHRoZSBmaXJzdCBib3ggYW5kIHBvcHVsYXRpb24gaW4gdGhlIHNlY29uZC4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGltZyBzcmM9ICJJbWFnZXMvcWdpcy1zdGF0aXN0aWNzLW1lbnUucG5nIiBhbHQ9IlN0YXRpc3RpY3MgSW5mb3JtYXRpb24iIHN0eWxlPSJ3aWR0aDo2MCUiPjwvcD4NCg0KPGJpZz48Yj5RdWVzdGlvbiBOby4gMjwvYj48L2JpZz4NCjxibG9ja3F1b3RlPg0KV2hhdCBpcyB0aGUgdG90YWwgcG9wdWxhdGlvbiAoc3VtIGluZm9ybWF0aW9uKSBvZiB0aGUgY291bnRpZXMgaW1wYWN0ZWQgYnkgdGhlc2UgaHVycmljYW5lcz8NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KPGhyPjwvaHI+DQoNCjxkZXRhaWxzPg0KPHN1bW1hcnk+PGJpZz5WaWV3IERpcmVjdGlvbnMgaW4gPGI+IFtSXXtzdHlsZT0iY29sb3I6IzY0OTVFRCJ9IDwvYj48L2JpZz48L3N1bW1hcnk+DQoNCk5vdyB0aGF0IHlvdSBoYXZlIHRoZSBuZWNlc3NhcnkgZGF0YSwgeW91IG5lZWQgZGV0ZXJtaW5lIHdoaWNoIGNvdW50aWVzIGFyZSBtb3N0IHNpZ25pZmljYW50bHkgaW1wYWN0ZWQgYnkgdGhlIGh1cnJpY2FuZXMuIEJlY2F1c2UgaHVycmljYW5lIHdpbmRzIGNhbiBpbXBhY3QgYXJlYXMgZmFyIGF3YXkgZnJvbSB0aGUgZXllIG9yIHRoZSBzdG9ybSwgeW91IHdpbGwgYmVnaW4gYnkgY3JlYXRpbmcgYSBidWZmZXIgYXJvdW5kIHRoZSBodXJyaWNhbmUgdHJhY2tzLiBGb3IgdGhpcyBzdGVwIHlvdSB3aWxsIHVzZSB0aGUgYGJ1ZmZlcmAgZnVuY3Rpb24gZnJvbSB0aGUgKipyYXN0ZXIqKiBwYWNrYWdlLiBUaGUgZnVuY3Rpb24gcmVxdWlyZXM6DQoNCmBgYA0KYnVmZmVyKHgsd2lkdGg9MCxkaXNzb2x2ZT1UUlVFKQ0KYGBgDQp3aGVyZSBfeF8gPSB0aGUgZGF0YXNldCwgX3dpZHRoXyA9IGRpc3RhbmNlIGluIG1hcCB1bml0cywgYW5kIF9kaXNzb2x2ZV8gPSBpZiBUUlVFLCBvdmVyYWxwcGluZyBwb2x5Z29ucyBhcmUgZGlzc29sdmVkLg0KDQpgYGB7ciBidWZmZXIsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmh1cnJpY2FuZXNfYnVmZmVyIDwtIGJ1ZmZlcihodXJyaWNhbmVzLCB3aWR0aCA9IDEsIGRpc3NvbHZlID0gVFJVRSkNCmBgYA0KDQpXaXRoIHRoZSBidWZmZXIgY3JlYXRlZCB5b3UgY2FuIG5vdyB1c2UgW2BpbnRlcnNlY3RgXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvcmFzdGVyL3ZlcnNpb25zLzMuNC0xMy90b3BpY3MvaW50ZXJzZWN0KSBmcm9tIHRoZSAqKnJhc3RlcioqIHBhY2thZ2UgdG8gc2VsZWN0IHRoZSBvdmVybGFwcGluZyBjb3VudGllcy4gTW9yZSBpbmZvcm1hdGlvbiBvbiBbSW50ZXJzZWN0XShodHRwczovL3Byby5hcmNnaXMuY29tL2VuL3Byby1hcHAvbGF0ZXN0L3Rvb2wtcmVmZXJlbmNlL2FuYWx5c2lzL2ludGVyc2VjdC5odG0pIGNhbiBiZSBmb3VuZCBvbiB0aGUgW0VTUkldKGh0dHBzOi8vcHJvLmFyY2dpcy5jb20vZW4vcHJvLWFwcC9sYXRlc3QvdG9vbC1yZWZlcmVuY2UvYW5hbHlzaXMvaW50ZXJzZWN0Lmh0bSkgd2Vic2l0ZS4gU2ltaWxhciB0byBiZWZvcmUsIHlvdSB3aWxsIG5lZWQgdG8gYGZvcnRpZnlgIHRoZSBkYXRhIGFuZCBjb25uZWN0IHRvIHRoZSBvcmlnaW5hbCBkYXRhc2V0Lg0KDQpgYGB7ciBpbXBhY3RlZCBjb3VudGllcywgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KaW50ZXJzZWN0aW9uIDwtIHJhc3Rlcjo6aW50ZXJzZWN0KGh1cnJpY2FuZXNfYnVmZmVyLHN1YnNldF9jb3VudGllcykNCmludGVyc2VjdGlvbkBkYXRhJGlkIDwtIHJvd25hbWVzKGludGVyc2VjdGlvbkBkYXRhKQ0KaHVycmljYW5lc19jb3VudGllcyA8LSBmb3J0aWZ5KGludGVyc2VjdGlvbikNCmltcGFjdGVkX2NvdW50aWVzIDwtIHBseXI6OmpvaW4oaHVycmljYW5lc19jb3VudGllcyxpbnRlcnNlY3Rpb25AZGF0YSwgYnkgPSAiaWQiKQ0KYGBgDQoNCldpdGggdGhlIGludGVyc2VjdGlvbiBjb21wbGV0ZSwgdGhlIGNvdW50aWVzIHRoYXQgYXJlIG1vc3QgaW1wYWN0ZWQgYnkgdGhlIGh1cnJpY2FuZSAoZS5nLiB0aG9zZSB3aXRoaW4gdGhlIGJ1ZmZlciB6b25lIG9mIHRoZSB0cmFja3MpIGFyZSBjb250YWluZWQgd2l0aGluIHRoZSBfaW1wYWN0ZWRfY291bnRpZXNfIG9iamVjdC4NCg0KPGJpZz48Yj5RdWVzdGlvbiBOby4gMjwvYj48L2JpZz4NClRvIGFuc3dlciB0aGlzIHF1ZXN0aW9uIHlvdSB3aWxsIG5lZWQgdG8gY3JlYXRlIGEgZGF0YXNldCB0aGF0IHdvbid0IGJlIHVzZWQgaW4gdGhlIG1hcC4gRHVlIHRvIHRoZSBkaXNzZWN0ZWQgbmF0dXJlIG9mIHRoZSBkYXRhLCB5b3UgbmVlZCB0byBleGFtaW5lIHRoZSBkaXN0aW5jdCBfaWRzXyBvZiB0aGUgaW1wYWN0ZWQgY291bnRpZXMuIFRoaXMgY2FuIGJlIGRvbmUgdXNpbmcgdGhlIGZvbGxvd2luZyBzY3JpcHQ6DQoNCmBgYA0KY291bnR5X3BvcHVsYXRpb25zIDwtIGRpc3RpbmN0KGltcGFjdGVkX2NvdW50aWVzLCBGSVBTLCAua2VlcF9hbGwgPSBUUlVFKQ0KYGBgDQoNCldoZXJlIHlvdSBhcmUgdXNpbmcgdGhlIF9pbXBhY3RlZF9jb3VudGllc18gZGF0YXNldCBhbmQga2VlcGluZyBvbmx5IHRoZSBfZGlzdGluY3RfIGZlZGVyYWwgRklQUyBjb2RlIHRoYXQgaXMgdW5pcXVlIHRvIGVhY2ggY291bnR5Lg0KPGJsb2NrcXVvdGU+DQpXaXRoIHRoZSBkYXRhc2V0IGFib3ZlLCB3cml0ZSBhIHNjcmlwdCB1c2luZyA8Yj5zdW0oKTwvYj4gdG8gZGV0ZXJtaW5lIHRoZSB0b3RhbCBwb3B1bGF0aW9uIGltcGFjdGVkIGJ5IHRoZSBodXJyaWNhbmVzPw0KPC9ibG9ja3F1b3RlPg0KPGk+PHNtYWxsPkhJTlQ6IFNpbWlsYXIgdG8gRXhlcmNpc2UgMywgUXVlc3Rpb24gMiBwbGFjZSB0aGUgb2JqZWN0IGZvbGxvd2VkIGJ5IGEgJCBhbmQgdGhlIHZhcmlhYmxlIG5hbWUgYmV0d2VlbiB0aGUgKCkgaW4gdGhlIHN1bSBmdW5jdGlvbi4gWW91IGNhbiB1c2UgPGI+c3RyKCk8L2I+IHRvIHZpZXcgdGhlIHZhcmlhYmxlcyBhdmFpbGFibGUgaW4gdGhlIGRhdGFzZXQuPC9zbWFsbD48L2k+DQo8L2RldGFpbHM+DQoNCiMjIFN0ZXAgVGhyZWU6IFRoZSBWaXN1YWxpemF0aW9uDQoNCllvdSB3aWxsIG5vdyBjcmVhdGUgYSBncmFwaGljYWwgZGlzcGxheSBvZiB5b3VyIGRhdGEgdGhhdCBpbmNsdWRlcyBjYXJ0b2dyYXBoaWMgZWxlbWVudHMgc3VjaCBhcyBsZWdlbmQsIHNjYWxlIGJhciwgbm9ydGggYXJyb3csIGV0Yy4gSW4gdGhpcyB2aXN1YWxpemF0aW9uIHlvdSB3aWxsIGFsc28gbGVhcm4gdG8gYWRkIGEgZGlmZmVyZW50IGJhc2VtYXAsIGFkZCBhbiBpbnNldCBvciBvdmVydmlldyBtYXAsIGFuZCBhbHRlciB0aGUgcHJvamVjdGVkIGNvb3JkaW5hdGUgc3lzdGVtLiANCg0KPGRldGFpbHM+PHN1bW1hcnk+PGJpZz5WaWV3IGRpcmVjdGlvbnMgaW4gPGI+IFtBcmNHSVMgUHJvXXtzdHlsZT0iY29sb3I6I2ZmNDUwMCJ9IDwvYj48L3NwYW4+PC9iaWc+PC9zdW1tYXJ5Pg0KDQpPbiB0aGUgX01hcCBUYWJfJm5ic3A7IGNsaWNrIHRoZSAqKkJhc2VtYXAqKiBidXR0b24gPGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLWJhc2VtYXAtYnV0dG9uLmpwZyIgYWx0PSJCYXNlbWFwcyIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIj4gYW5kIHNlbGVjdCB0aGUgb3B0aW9uIGZvciBfT2NlYW5zXy4gUmVtZW1iZXIgdGhhdCB0aGUgb3JkZXIgb2YgdGhlIGRhdGFzZXRzIGluIHRoZSBUYWJsZSBvZiBDb250ZXRzIGRldGVybWluZXMgd2hhdCBvcmRlciB0aGV5IGFyZSBkaXNwbGF5ZWQuDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1iYXNlbWFwcy5wbmciIGFsdD0iQmFzZW1hcHMiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCkluIGZ1dHVyZSBleGVyY2lzZXMgeW91IG1heSBjaG9vc2UgYW55IG9mIHRoZXNlIGJhc2VtYXAgb3B0aW9ucyB0aGF0IGFyZSBhcHBycm9wcmlhdGUgZm9yIHlvdXIgYW5hbHlzZXMuIE5leHQsIG9uIHRoZSBfSW5zZXJ0IFRhYl8mbmJzcDsgY2xpY2sgdGhlIGJ1dHRvbiBmb3IgKipOZXcgTWFwKiogPGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLW5ldy1tYXAtYnV0dG9uLmpwZyIgYWx0PSJJbnNlcnQgTmV3IE1hcCIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIj4gYW5kIHNlbGVjdCBOZXcgTWFwLiBBIG5ldyBtYXAgdGFiIChwcm9iYWJseSBjYWxsZWQgTWFwMikgd2lsbCBhcHBlYXIgaW4geW91ciBtYXAgZnJhbWUuIEFkZCAob3IgY29weS9wYXN0ZSBmcm9tIHRoZSBvcmlnaW5hbCBtYXApIHRoZSBodXJyaWNhbmUgaW1wYWN0ZWQgY291bnRpZXMgYW5kIHRoZSBjb250aW5lbnRhbCBVUyBTdGF0ZXMgc2hhcGVmaWxlcyBhcyB3ZWxsIGFzIHRoZSBPY2VhbnMgYmFzZW1hcCB0byB0aGlzIG5ldyBtYXAuIEJlIHN1cmUgdG8gem9vbSBpbiBhIGFwcHJvcHJpYXRlIHRvIHNlZSB0aGUgZGF0YS4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLW1hcDIucG5nIiBhbHQ9Ikluc2V0IE1hcCIgc3R5bGU9IndpZHRoOjEwMCUiPjwvcD4NCg0KVG8gcmV0dXJuIHRvIHRoZSBvcmlnaW5hbCBtYXAgc2ltcGx5IGNsaWNrIG9uIHRoZSBhcHByb3ByaWF0ZSB0YWIuIFRoaXMgd2lsbCBhbGxvdyB5b3UgdG8gc3dpdGNoIGJhY2sgYW5kIGZvcnRoIGJldHdlZW4gdGhlIHR3byBpbiBvcmRlciB0byBtYWtlIHRoZSBuZWNlc3NhcnkgY3VzdG9taXphdGlvbnMuIEl0IG1heSBiZSBiZW5lZmljaWFsIHRvIHJlbmFtZSBlYWNoIG9uZSB0byBrZWVwIHRyYWNrIG9mIHRoZSBwdXJwb3NlIGZvciBlYWNoIG1hcC4NCg0KTmV4dCB5b3UgY2FuIGNoYW5nZSB0aGUgcHJvamVjdGlvbiBvZiB0aGUgY29vcmRpbmF0ZSBzeXN0ZW0gZm9yIHRoZSBpbnNldCBtYXAgKE1hcDIpLiBJbiB0aGUgVGFibGUgb2YgQ29udGVudHMsIHJpZ2h0LWNsaWNrIG9uICoqTWFwMioqIGFuZCBzZWxlY3QgX1Byb3BlcnRpZXNfLiBJbiB0aGUgcmVzdWx0aW5nIHdpbmRvdyBjbGljayAqKkNvb3JkaW5hdGUgU3lzdGVtcyoqIGZyb20gdGhlIGxlZnQtc2lkZSBtZW51LiBVbmRlciAiWFkgQ29vcmRpbmF0ZSBTeXN0ZW1zIEF2YWlsYWJsZSIgc2Nyb2xsIGRvd24gdW50aWwgeW91IHNlZSBfUHJvamVjdGVkIENvb3JkaW5hdGUgU3lzdGVtXy4gVXNpbmcgdGhlIHNlcmllcyBvZiBkcm9wLWRvd24gbWVudXMgZ28gdG8gKipQcm9qZWN0ZWQgQ29vcmRpbmF0ZSBTeXN0ZW0gPiBDb250aW5lbnRhbCA+IE5vcnRoIEFtZXJpY2EqKiBhbmQgc2VsZWN0IHRoZSBvcHRpb24gZm9yICJOb3J0aCBBbWVyaWNhIEFsYmVycyBFcXVhbCBBcmVhIENvbmljIiBhbmQgY2xpY2sgT0suIFlvdSBzaG91bGQgbm90aWNlIHRoYXQgdGhlIGF3a3dhcmQgImZsYXQgdG9wIiBib3JkZXIgb2YgdGhlIFVuaXRlZCBTdGF0ZXMgc2hvdWxkIG5vdyBtZSBjdXJ2ZWQgYW5kIHRoZSBvdmVyYWxsIHNoYXBlIG9mIHRoZSBzdGF0ZXMgaGFzIGEgbW9yZSBwbGVhc2luZyBhcHBlYXJhbmNlLg0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtY29vcmRpbmF0ZS1zeXN0ZW1zLnBuZyIgYWx0PSJBbHRlcmluZyBDb29yZGluYXRlIHN5c3RlbXMiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCkluIGxlY3R1cmUgd2Ugd2lsbCBkaXNjdXNzIHRoZSBpbXBvcnRhbmNlIG9mIHByb2plY3Rpb25zIGFuZCBjb29yZGluYXRlIHN5c3RlbXMuIEluIGZ1dHVyZSBleGVyY2lzZXMgeW91IHNob3VsZCB0YWtlIHNvbWUgdGltZSB0byBzZWxlY3QgZGlmZmVyZW50IG9wdGlvbnMgdG8gc2VlIHdoaWNoIF9Db29yZGluYXRlIFN5c3RlbV8mbmJzcDsgaGFzIHRoZSBtb3N0IHBsZWFzaW5nIHNoYXBlIHRvIHlvdXIgZXllcy4NCg0KSXQgaXMgbm93IHRpbWUgZm9yIHlvdSB0byBtYWtlIHlvdXIgbWFwLiBTaW1pbGFyIHRvICoqW3ByZXZpb3VzIGV4ZXJjaXNlc10oaHR0cHM6Ly9jaHJpc21nZW50cnkuZ2l0aHViLmlvL0dJUzEtRXhlcmNpc2UtMi8jMTNfU3RlcF9UaHJlZTpfVGhlX1Zpc3VhbGl6YXRpb24pKiosIHlvdSBuZWVkIHRvIGFkZCBhbGwgb2YgdGhlIG5lY2Vzc2FyeSBlbGVtZW50cyBkaXNjdXNzZWQgaW4gRXhlcmNpc2UgMiBhbmQgMy4gSW4gdGhpcyBleGVyY2lzZSB5b3Ugd2lsbCBhbHNvIG5lZWQgdG8gYWRkIHlvdXIgaW5zZXQgbWFwIChNYXAyKS4gVG8gZG8gdGhpcywgeW91IGZpcnN0IG5lZWQgdG8gYWRkIHRoZSBwcmltYXJ5IG1hcCB3aXRoIHVzaW5nIHRoZSBNYXAgRnJhbWUgYnV0dG9uIGxpa2UgYmVmb3JlLiBOZXh0IHlvdSBjYW4gY2xpY2sgdGhlIE1hcCBGcmFtZSBidXR0b24gYWdhaW4gdG8gYWRkIHRoZSBzZWNvbmQgbWFwLg0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtYWRkLW1hcDIucG5nIiBhbHQ9IkFkZCBJbnNldCBNYXAiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCkhvd2V2ZXIsIGZvciB0aGUgaW5zZXQgeW91IHdhbnQgaXQgdG8gYmUgc21hbGxlciBhbmQgbm90IGNvdmVyIHlvdXIgbWFwIGRhdGEuDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1tYXAtYW5kLWluc2V0LnBuZyIgYWx0PSJNYXAgd2l0aCBJbnNldCBNYXAiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCkZpbmFsaXplIHlvdXIgbWFwIGJ5IGFkZGluZyBhbGwgb2YgdGhlIG5lY2Vzc2FyeSBtYXAgZWxlbWVudHMgKHRpdGxlLCBsZWdlbmQsIG5vcnRoIGFycm93LCBzY2FsZSBiYXIsIG5hbWUgYW5kIGRhdGUpIGFuZCBhbHRlcmluZyB0aGUgc3ltYm9sb2d5IG9mIHRoZSBodXJyaWNhbmUgZGF0YXNldCB0byBwcm92aWRlIGFkZGl0aW9uYWwgaW1wb3J0YW50IGRhdGEuIFJlbWVtYmVyIHRvIHJlbmFtaW5nIGl0ZW1zIGluIHRoZSBUYWJsZSBvZiBDb250ZW50cyB3aWxsIHJlbmFtZSB0aGVtIGluIHRoZSBsZWdlbmQuDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1maW5hbC1tYXAucG5nIiBhbHQ9IkZpbmFsIE1hcCIgc3R5bGU9IndpZHRoOjEwMCUiPjwvcD4NCg0KPGJpZz48Yj5RdWVzdGlvbiBOby4gMzwvYj48L2JpZz4NCjxibG9ja3F1b3RlPg0KSG93IG1hbnkgdG90YWwgaW1wYWN0ZWQgY291bnRpZXMgYXJlIGluY2x1ZGVkIGluIHRoZSBuZXcgZGF0YXNldD8NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KPGhyPjwvaHI+DQoNCjxkZXRhaWxzPjxzdW1tYXJ5PjxiaWc+VmlldyBkaXJlY3Rpb25zIGluIDxiPiBbUUdJU117c3R5bGU9ImNvbG9yOiMwMDY0MDAifSA8L2I+PC9zcGFuPjwvYmlnPjwvc3VtbWFyeT4NCg0KVG8gY3JlYXRlIHRoaXMgdmlzdWFsaXphdGlvbiB5b3UgYXJlIGdvaW5nIHRvIGFsc28gY3JlYXRlIHdoYXQgaXMgY2FsbGVkIGFuIGluc2V0IG9yIGluZGljYXRvciBtYXAuIFRoZXNlIGFyZSBzbWFsbGVyIG1hcHMgdGhhdCBhcmUgdXNlZCB0byBwcm92aWRlIGFkZGl0aW9uYWwgZGV0YWlsIGFib3V0IGEgc3BlY2lmaWMgbG9jYXRpb24uIFRoZXNlIG1hcHMgYXJlIG9mdGVuIHNtYWxsIHNjYWxlIHZlcnNpb25zIG9yIHRoZSBwcmltYXJ5IG1hcCwgYnV0IHNvbWV0aW1lcyBjYW4gYmUgbGFyZ2VyIHNjYWxlIHRvIGVuaGFuY2UgZGV0YWlsIGluIGNvbmdlc3RlZCBhcmVhcy4gSW4gdGhpcyBjYXNlIGl0IHdpbGwgYmUgYSBzbWFsbCBzY2FsZSB2ZXJzaW9uIG9mIHRoZSBjb250aW5lbnRhbCBVUy4NCg0KVG8gYmVnaW4gdGhpcyBwcm9jZXNzIHlvdSBhcmUgZ29pbmcgdG8gY3JlYXRlIHNvbWUgb3JnYW5pemF0aW9ucyBpbiB0aGUgTGF5ZXIgTWVudSBieSB1c2luZyB0aGUgKipBZGQgR3JvdXAqKiBidXR0b24gPGltZyBzcmM9ICJJbWFnZXMvcWdpcy1sYXllcnMtYWRkLWdyb3VwLmpwZyIgYWx0PSJBZGQgR3JvdXBzIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiPi4gTmFtZSB0aGUgZmlyc3QgZ3JvdXAgIk1haW4gTWFwIiBhbmQgY3JlYXRlIGEgc2Vjb25kIGdyb3VwIGNhbGxlZCAiSW5zZXQgTWFwIi4gDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtbGF5ZXJzLW1lbnUtZ3JvdXBzLmpwZyIgYWx0PSJMYXllcnMgR3JvdXBzIiBzdHlsZT0id2lkdGg6NjAlIj48L3A+DQoNCkluIHRoZSBMYXllcnMgTWVudSB5b3UgY2FuIGNsaWNrIGFuZCBkcmFnIHRoZSBkYXRhc2V0cyBpbnRvIHRoZSBkaWZmZXJlbnQgZ3JvdXBzIGFzIHdlbGwgYXMgcmlnaHQvQ1JUTC1jbGljayB0byBjb3B5IGFuZCBwYXN0ZS4gRm9yIHRoaXMgZXhlcmNpc2UgeW91IHNob3VsZCBvcmRlciB5b3VyIGRhdGFzZXRzIGFzIGZvbGxvd3M6DQoNCi0gKipNYWluIE1hcCoqDQogIC0gSHVycmljYW5lcyBEYXRhc2V0DQogIC0gSHVycmljYW5lIEltcGFjdGVkIENvdW50aWVzDQogIC0gU2VsZWN0ZWQgU3RhdGVzDQogIC0gQ2xpcHBlZCBDb3VudGllcw0KICAtIENvbnRpbmVudGFsIFVTDQogIC0gR29vZ2xlIFNhdGVsbGl0ZSBJbWFnZXJ5DQotICoqSW5zZXQgTWFwKioNCiAgLSBIdXJyaWNhbmUgQnVmZmVyDQogIC0gU2VsZWN0ZWQgU3RhdGVzDQogIC0gQ29udGluZW50YWwgVVMNCiAgLSBHb29nbGUgU2F0ZWxsaXRlIEltYWdlcnkNCg0KPHAgYWxpZ249ImNlbnRlciI+PGltZyBzcmM9ICJJbWFnZXMvcWdpcy1sYXllcnMtd2l0aC1ncm91cHMuanBnIiBhbHQ9IkxheWVycyBHcm91cHMiIHN0eWxlPSJ3aWR0aDo2MCUiPjwvcD4NCg0KU2ltaWxhciB0byAqKltwcmV2aW91cyBleGVyY2lzZXNdKGh0dHBzOi8vY2hyaXNtZ2VudHJ5LmdpdGh1Yi5pby9HSVMxLUV4ZXJjaXNlLTIvIzEzX1N0ZXBfVGhyZWU6X1RoZV9WaXN1YWxpemF0aW9uKSoqLCB5b3VyIHZpc3VhbGl6YXRpb24gc2hvdWxkIGluY2x1ZGUgYWxsIG9mIHRoZSBuZWNlc3NhcnkgbWFwIGVsZW1lbnRzIGRpc2N1c3NlZCBpbiBFeGVyY2lzZSAyIGFuZCAzLiBIb3dldmVyLCB5b3Ugd2lsbCBhbHNvIG5lZWQgdG8gYWRkIHRoZSBpbnNldCBtYXAgZm9yIHRoaXMgZXhlcmNpc2UuIFRvIGRvIHRoaXMsIHlvdSBmaXJzdCBuZWVkIHRvIGNyZWF0ZSBhIF9OZXcgUHJpbnQgTGF5b3V0XywgYW5kIHdpdGggdGhlICJNYWluIE1hcCIgc2VsZWN0ZWQgYW5kIHRoZSAiSW5zZXQgTWFwIiBoaWRkZW4gaW4gdGhlIExheWVycyBNZW51LCBhbmQgYWRkIHRoZSBtYXAgd2l0aCB0aGUgX0FkZCBtYXBfJm5ic3A7IHRvb2wgbGlrZSBiZWZvcmUuIA0KDQo8cCBhbGlnbj0iY2VudGVyIj48ZGl2IGNsYXNzPSJ6b29tIj48aW1nIHNyYz0gIkltYWdlcy9xZ2lzLWxheW91dC1tYWluLW1hcC5wbmciIGFsdD0iTGF5b3V0IHdpdGggTWFpbiBNYXAiIHN0eWxlPSJ3aWR0aDoxMDAlIj48L2Rpdj48L3A+DQoNCkluIHRoZSBpdGVtIHByb3BlcnRpZXMgZm9yIHRoZSBtYXAsIHNldCB5b3VyIGxldmVsIG9mIHpvb20gYW5kIGFsaWduIHRoZSBtYXAgaW4geW91ciBkZXNpcmVkIGxvY2F0aW9uLiBUaGVuIHVuZGVyIF9MYXllcnNfJm5ic3A7IHNlY3Rpb24sIGNsaWNrICJMb2NrIExheWVycyIgdG8ga2VlcCB0aGUgbWFwIGZyYW1lIGZyb20gYmVpbmcgYWx0ZXJlZC4gWW91IGNhbiBhbHdheXMgcmV0dXJuIHRvIHRoaXMgbGF5ZXIgYW5kIHVubG9jayBpdCBpZiB5b3UgbmVlZCB0byBtYWtlIGNoYW5nZXMuDQoNCk5leHQgcmV0dXJuIHRvIHRoZSBwcm9qZWN0IGFuZCB0dXJuIG9mZiB0aGUgTWFpbiBNYXAsIHRoZW4gdHVybiBvbiB0aGUgSW5zZXQgTWFwIGFuZCByZXR1cm4gdG8gdGhlIGxheW91dCBhbmQgYWRkIGFub3RoZXIgbWFwLiBCZWNhdXNlIHlvdSBoYXZlIHRoZSBpbnNldCBncm91cCBzZWxlY3RlZCBhbmQgdGhlIG1haW4gbWFwIGdyb3VwIGhpZGRlbiwgdGhlIGFkZGl0aW9uYWwgbWFwIGZyYW1lIHdpbGwgY29udGFpbiB0aGUgaW5zZXQgaW5mb3JtYXRpb24uIFJlbWVtYmVyIHRvIHRoaW5rIGFib3V0IHdoZXJlIHlvdSB3YW50IHRoZSBpbnNldCB0byBiZSBsb2NhdGVkIGJlZm9yZSB5b3UgZHJhdyBpdCBvbiB0aGUgbGF5b3V0LiBXaGlsZSB5b3UgY2FuIGNoYW5nZSB0aGlzIGF0IGFueXRpbWUsIHlvdSBzaG91bGQgYWx3YXlzIGhhdmUgYSBwbGFubmVkIG1hcCBkZXNpZ24uDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxkaXYgY2xhc3M9Inpvb20iPjxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtbGF5b3V0LWluc2V0LW1hcC5wbmciIGFsdD0iTGF5b3V0IHdpdGggSW5zZXQgTWFwIiBzdHlsZT0id2lkdGg6MTAwJSI+PC9kaXY+PC9wPg0KDQpGaW5hbGl6ZSB5b3VyIG1hcCBieSBhZGRpbmcgYWxsIG9mIHRoZSBuZWNlc3NhcnkgbWFwIGVsZW1lbnRzICh0aXRsZSwgbGVnZW5kLCBub3J0aCBhcnJvdywgc2NhbGUgYmFyLCBuYW1lIGFuZCBkYXRlKSBhbmQgYWx0ZXJpbmcgdGhlIHN5bWJvbG9neSBvZiB0aGUgaHVycmljYW5lIGRhdGFzZXQgdG8gcHJvdmlkZSBhZGRpdGlvbmFsIGltcG9ydGFudCBkYXRhLiBSZW1lbWJlciB0byByZW5hbWluZyBpdGVtcyBpbiB0aGUgVGFibGUgb2YgQ29udGVudHMgd2lsbCByZW5hbWUgdGhlbSBpbiB0aGUgbGVnZW5kIGJ1dCB5b3Ugd2lsbCBuZWVkIHRvIHVwZGF0ZSBpbiB0aGUgaXRlbSBwcm9wZXJ0aWVzLiBBbHRlcm5hdGl2ZWx5LCBpbiB0aGUgaXRlbSBwcm9wZXJ0aWVzIGZvciB0aGUgbGVnZW5kIHlvdSBjYW4gc2VsZWN0IGFueSBvYmplY3QgYW5kIGNsaWNrIHRoZSBFZGl0IGJ1dHRvbiA8aW1nIHNyYz0gIkltYWdlcy9xZ2lzLWVkaXQtaXRlbS1wcm9wZXJ0aWVzLWJ1dHRvbi5qcGciIGFsdD0iQWRkIEdyb3VwcyIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIj4gdG8gcmVuYW1lIHRoZW0uDQoNCjxiaWc+PGI+UXVlc3Rpb24gTm8uIDM8L2I+PC9iaWc+DQo8YmxvY2txdW90ZT4NCkhvdyBtYW55IHRvdGFsIGltcGFjdGVkIGNvdW50aWVzIGFyZSBpbmNsdWRlZCBpbiB0aGUgbmV3IGRhdGFzZXQ/DQo8L2Jsb2NrcXVvdGU+DQoNCjwvZGV0YWlscz4NCjxocj48L2hyPg0KDQo8ZGV0YWlscz48c3VtbWFyeT48YmlnPlZpZXcgZGlyZWN0aW9ucyBpbiA8Yj4gW1Jde3N0eWxlPSJjb2xvcjojNjQ5NUVEIn0gPC9iPjwvc3Bhbj48L2JpZz48L3N1bW1hcnk+DQoNClRvIGNyZWF0ZSB0aGlzIHZpc3VhbGl6YXRpb24geW91IGFyZSBnb2luZyB0byBhbHNvIGNyZWF0ZSB3aGF0IGlzIGNhbGxlZCBhbiBpbnNldCBvciBpbmRpY2F0b3IgbWFwLiBUaGVzZSBhcmUgc21hbGxlciBtYXBzIHRoYXQgYXJlIHVzZWQgdG8gcHJvdmlkZSBhZGRpdGlvbmFsIGRldGFpbCBhYm91dCBhIHNwZWNpZmljIGxvY2F0aW9uLiBUaGVzZSBtYXBzIGFyZSBvZnRlbiBzbWFsbCBzY2FsZSB2ZXJzaW9ucyBvciB0aGUgcHJpbWFyeSBtYXAsIGJ1dCBzb21ldGltZXMgY2FuIGJlIGxhcmdlciBzY2FsZSB0byBlbmhhbmNlIGRldGFpbCBpbiBjb25nZXN0ZWQgYXJlYXMuIEluIHRoaXMgY2FzZSBpdCB3aWxsIGJlIGEgc21hbGwgc2NhbGUgdmVyc2lvbiBvZiB0aGUgY29udGluZW50YWwgVVMuDQoNClRvIGJlZ2luIHRoaXMgcHJvY2VzcyB5b3UgYXJlIGdvaW5nIHRvIGNyZWF0ZSBhbiBhZGRpdGlvbmFsIG9iamVjdCBmb3IgY291bnRyaWVzIG9mIHRoZSB3b3JsZC4NCg0KYGBge3Igd29ybGQsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCndvcmxkIDwtIG1hcF9kYXRhKG1hcCA9ICJ3b3JsZCIpDQpgYGANCg0KWW91IGNhbiBub3cgY3JlYXRlIHRoZSBwcmltYXJ5IG1hcCBkYXRhLiBXaXRoaW4gdGhlIHNjcmlwdCBiZWxvdyB5b3Ugd2lsbCBzZWUgc29tZSBvZiB0aGUgY29tbW9uIGZ1bmN0aW9ucyB1c2VkIHRocm91Z2hvdXQgdGhpcyBhbmQgcHJldmlvdXMgZXhlcmNpc2VzLiBUaGVyZSBhcmUgdHdvIGNoYW5nZXMgbWFkZSBmcm9tIHRoZSB0eXBpY2FsIGBnZ3Bsb3QyYCBzY3JpcHQgdG8gbWVudGlvbjoNCg0KLSBnZW9tX3BhdGgoKSBpcyBhIGZ1bmN0aW9uIHRvIGFkZCBhIGxpbmUgYmFzZWQgb24gYSBzZXJpZXMgb2YgZGF0YSBwb2ludHMgc3VjaCBhcyBodXJyaWNhbmUgdHJhY2tzLg0KLSBXaXRoaW4gdGhlIGFlcygpIGZvciBnZW9tX3BhdGgoKSB0aGUgY29sb3IgdmFyaWFibGUgd2FzIGNvbnZlcnRlZCB0byBhIGNoYXJhY3RlciAobGV0dGVycykgZnJvbSBudW1lcmljIChudW1iZXJzKS4gVGhpcyB3YXMgZG9uZSB0byBjcmVhdGUgZGlzY3JldGUgdmFyaWFibGVzIHJhdGhlciB0aGFuIGNvbnRpbnVvdXMgdmFyaWFibGVzIHRvIG1ha2UgYSBtb3JlIGFwcHJvcHJpYXRlIGxlZ2VuZC4NCg0KYGBge3IgbWFpbiBtYXAsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCm1haW5fbWFwIDwtIGdncGxvdCgpICsgDQogIGdlb21fcG9seWdvbihkYXRhID0gd29ybGQsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGNvbG9yID0gTkEsIGZpbGwgPSAiZ3JheSIpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB1cywgYWVzKHg9bG9uZywgeT1sYXQsIGdyb3VwPWdyb3VwKSwgY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIkRpbUdyYXkiKSArDQogIGdlb21fcG9seWdvbihkYXRhID0gc2VfY291bnRpZXMsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGZpbGwgPSAiTGlnaHRHcmF5IiwgY29sb3IgPSAiRGFya0dyYXkiKSArDQogIGdlb21fcG9seWdvbihkYXRhID0gc3RhdGVzLCBhZXMoeD1sb25nLCB5PWxhdCwgZ3JvdXA9Z3JvdXApLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSkgKw0KICBnZW9tX3BvbHlnb24oZGF0YSA9IGltcGFjdGVkX2NvdW50aWVzLCBhZXMoeD1sb25nLCB5PWxhdCwgZ3JvdXA9Z3JvdXApLCBjb2xvciA9ICJEYXJrR3JheSIsIGZpbGwgPSAiTGlnaHRTa3lCbHVlIikgKw0KICBnZW9tX3BhdGgoZGF0YSA9IGh1cnJpY2FuZV90cmFja3MsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCwgY29sb3IgPSBhcy5jaGFyYWN0ZXIoU1MpKSwgc2l6ZSA9IDIsIGxpbmVlbmQgPSAicm91bmQiKSArDQogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZChvcHRpb24gPSAiQSIsICJTYWZmaXJcblNpbXBzb25cblNjYWxlIikgKw0KICBjb29yZF9maXhlZCh4bGltID0gYygtOTcsLTc0KSwgeWxpbSA9IGMoMjUsNDQpKSArIA0KICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAibGlnaHRibHVlIiksIA0KICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQ0KbWFpbl9tYXANCmBgYA0KDQpUbyBjcmVhdGUgdGhlIGluc2V0IG1hcCB5b3Ugd2lsbCB1c2UgdGhlIF93b3JsZF8gZGF0YSB5b3UgY3JlYXRlZCBhYm92ZSBhbG9uZyB3aXRoIHRoZSBVUyBhbmQgaW1wYWN0ZWQgY291bnRpZXMgZGF0YXNldHMuDQoNCmBgYHtyIGluc2V0IG1hcCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KaW5zZXQgPC0gZ2dwbG90KCkgKyANCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSB3b3JsZCwgYWVzKHg9bG9uZywgeT1sYXQsIGdyb3VwPWdyb3VwKSwgY29sb3IgPSAid2hpdGUiLCBmaWxsID0gImdyYXkiKSArDQogIGdlb21fcG9seWdvbihkYXRhID0gdXMsIGFlcyh4PWxvbmcsIHk9bGF0LCBncm91cD1ncm91cCksIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJEYXJrR3JheSIpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBpbXBhY3RlZF9jb3VudGllcywgYWVzKHg9bG9uZywgeT1sYXQsIGdyb3VwPWdyb3VwKSwgY29sb3IgPSBOQSwgZmlsbCA9ICJMaWdodFNreUJsdWUiKSArDQogIGNvb3JkX21hcCh4bGltID0gYygtMTI1LC02NSksIHlsaW0gPSBjKDI1LDUwKSwgImNvbmljIiwgbGF0MCA9IDMwKSArDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJsaWdodGJsdWUiKSwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgDQogICAgICAgIGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLGF4aXMudGlja3M9ZWxlbWVudF9ibGFuaygpLCANCiAgICAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSkNCmluc2V0DQpgYGANCg0KTm90aWNlIGluIGVhY2ggb2YgdGhlc2Ugc2NyaXB0cyBjcmVhdGVkIGFuIG9iamVjdCBvdXQgb2YgdGhlIGdncGxvdCgpLiBUaGlzIGlzIHVzZWQgdG8gZmFjaWxpdGF0ZSB0aGUgY3JlYXRpb24gb2YgdGhlIGZpbmFsIG1hcCB3aGVuIG92ZXJsYXlpbmcgdGhlIGluc2V0IG9uIHRoZSBtYWluIG1hcC4gVG8gZG8gdGhpcyB5b3Ugd2lsbCB1c2UgYGdnZHJhd2AgZnJvbSB0aGUgKipnZ3Bsb3QyKiogcGFja2FnZS4gSW4gdGhpcyBmdW5jdGlvbiB0byBhZGQgdGhlIG1hcHMgdXNpbmcgdGhlIGBkcmF3X3Bsb3RgIGZ1bmN0aW9uIGFuZCBsb2NhdGUgdGhlIGluc2V0IHVzaW5nIF94XywgX3lfLCBfd2lkdGhfLCBhbmQgX2hlaWdodF8gYXJndW1lbnRzLiBUaGVzZSB2YWx1ZXMgY2FuIGJlIGFsdGVyZWQgdG8gbW92ZSB0aGUgaW5zZXQgbWFwIHRvIGFueSBsb2NhdGlvbiBvbiB0aGUgbWFpbiBtYXAuIEZlZWwgZnJlZSB0byBleHBlcmltZW50IHdpdGggbG9jYXRpb24gaW4gU3RlcCA0Lg0KDQpgYGB7ciBzdGVwIDMgbWFwLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpnZ2RyYXcoKSArDQpkcmF3X3Bsb3QobWFpbl9tYXApICsgDQpkcmF3X3Bsb3QoaW5zZXQsIHggPSAwLjEwNSwgeSA9IDAuNzIsIHdpZHRoID0gMC4yNzUsIGhlaWdodCA9IDAuMjc1KQ0KYGBgDQpUaGVyZSBtYXkgYmUgYSBkaXNjcmVwYW5jeSBiZXR3ZWVuIHRoZSB4LCB5LCB3aWR0aCwgYW5kIGhlaWdodCBpbmZvcm1hdGlvbiBmb3IgdGhlIGluc2V0IGluIHRoZSBzY3JpcHQgYWJvdmUgYW5kIHRoZSBDb2xhYiBOb3RlYm9vayBkdWUgdG8gdGhlIGRpZmZlcmVuY2VzIGluIHJlc29sdXRpb24gYW5kIHNwYWNlIGxpbWl0YXRpb25zIG9mIGNyZWF0aW5nIHRoZSB3ZWJwYWdlLiANCg0KPGJpZz48Yj5RdWVzdGlvbiBOby4gMzwvYj48L2JpZz4NCjxibG9ja3F1b3RlPg0KUHJvdmlkZSB0aGUgZnVsbCBzY3JpcHQgeW91IHdvdWxkIHVzZSB0byBhZGQgdGhlIG5vcnRoIGFycm93LCB0aXRsZSwgc2NhbGViYXIsIGFuZCBuYW1lL2RhdGUgaW5mb3JtYXRpb24gdG8gdGhlIG1hcC4NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KDQojIyBTdGVwIEZvdXI6IFlvdXIgVHVybg0KDQpBZnRlciBwcm92aWRpbmcgdGhlIGluaXRpYWwgbWFwIHRvIEZFTUEsIHRoZSBEZXB1dHkgQXNzb2NpYXRlIEFkbWluaXN0cmF0b3IgZm9yIHRoZSBPZmZpY2Ugb2YgUmVzcG9uc2UgYW5kIFJlY292ZXJ5IGhhcyBhc2tlZCBpZiB5b3UgY291bGQgYWRkIHNvbWUgYWRkaXRpb25hbCBkYXRhLiBTcGVjaWZpY2FsbHksIHRoZXkgYXJlIGludGVyZXN0ZWQgaW4gY2l0aWVzIHdpdGggYSBwb3B1bGF0aW9uIG9mIGdyZWF0ZXIgdGhhbiAzMDAsMDAwIHNvIHRoZXkgYXJlIGFibGUgdG8gc2l0dWF0ZSByZXNwb25zZSB0ZWFtcyBpbiBwcm94aW1pdHkgdG8gdGhlIG1vc3QgcGVvcGxlLg0KDQo8ZGV0YWlscz48c3VtbWFyeT48YmlnPlZpZXcgZGlyZWN0aW9ucyBpbiA8Yj4gW0FyY0dJUyBQcm9de3N0eWxlPSJjb2xvcjojZmY0NTAwIn0gPC9iPjwvc3Bhbj48L2JpZz48L3N1bW1hcnk+DQoNCklmIHlvdSBkaWQgbm90IHByZXZpb3VzbHkgZG93bmxvYWQgdGhlIFtjaXRpZXMgZGF0YV0oaHR0cHM6Ly9naXRodWIuY29tL2NocmlzbWdlbnRyeS9HSVMxLUV4ZXJjaXNlLTQvcmF3L21haW4vRGF0YS9VU19DaXRpZXNfMTAway56aXApIGZyb20gdGhlIEdpdEh1YiBFeGVyY2lzZSBQYWdlIHBsZWFzZSBkb3dubG9hZCB0aGUgZGF0YSBhbmQgdW56aXAgaXQgaW4geW91ciBwcm9qZWN0IGZvbGRlci4gV2l0aCB0aGF0IGRhdGEgYXZhaWxhYmxlLCBhZGQgdGhlIFVTX0NpdGllc18xMDBrLnNocCB0byB5b3VyIHByaW1hcnkgbWFwIChub3QgdGhlIGluc2V0IG1hcCkuIFJlcGVhdGluZyB0aGUgc3RlcHMgdG8gKipjbGlwKiogZnJvbSBbU3RlcCAxXShodHRwczovL2NocmlzbWdlbnRyeS5naXRodWIuaW8vR0lTMS1FeGVyY2lzZS00LyMxMV9TdGVwX09uZTpfVGhlX0RhdGEpIHNlbGVjdCB0aGUgY2l0aWVzIGFzIHlvdXIgX0lucHV0IEZlYXR1cmVfLCB0aGUgaHVycmljYW5lIGJ1ZmZlciBhcyB0aGUgX0NsaXAgRmVhdHVyZV8sIGFuZCBiZSBzdXJlIHRvIHNhdmUgdGhlIG5ldyBkYXRhc2V0IHRvIHlvdXIgcHJvamVjdCBmb2xkZXIgd2l0aCAuc2hwIHRvIGNyZWF0ZSBhIHNoYXBlZmlsZS4gWW91IGNhbiBub3cgcmVtb3ZlIHRoZSBVUyBDaXRpZXMgZnJvbSB0aGUgcHJvamVjdCBidXQga2VlcCB5b3VyIGNsaXBwZWQgY2l0aWVzLg0KDQpXaGlsZSB5b3Ugd2lsbCBsZWF2ZSBhbGwgb2YgdGhlIGNsaXBwZWQgY2l0aWVzIG9uIHRoZSBtYXAsIHlvdSB3aWxsIG5vdyBjcmVhdGUgYSBfTGFiZWwgQ2xhc3NfIHRvIG9ubHkgY3JlYXRlIGxhYmVscyBmb3IgY2l0aWVzIHdpdGggYSBwb3B1bGF0aW9uIGdyZWF0ZXIgdGhhbiAzMDAsMDAwLiBUbyBiZWdpbiwgcmlnaHQtY2xpY2sgb24geW91ciBuZXcgY2xpcHBlZCBjaXRpZXMgZGF0YXNldCBhbmQgc2VsZWN0ICJMYWJlbGluZyBQcm9wZXJ0aWVzLi4uIiA8aW1nIHNyYz0gIkltYWdlcy9hcmNnaXMtbGFiZWxpbmctcHJvcGVydGllcy5qcGciIGFsdD0iTGFiZWxpbmcgUHJvcGVydGllcyIgd2lkdGg9IjE1MCIgaGVpZ2h0PSIyMCI+IGZyb20gdGhlIG9wdGlvbnMuDQoNClVuZGVyIHRoZSAiQ2xhc3MiIG9wdGlvbiBpbiB0aGUgTGFiZWwgQ2xhc3Mgd2luZG93IHNlbGVjdCAqKlNRTCoqIGZyb20gdGhlIHRocmVlIG9wdGlvbnMuIE5leHQgc2VsZWN0IF9OZXcgZXhwcmVzc2lvbl8mbmJzcDsgPGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLW5ldy1leHByZXNzaW9uLWxhYmVscy5qcGciIGFsdD0iTGFiZWxpbmcgU1FMIiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjIwIj4gYW5kIHNlbGVjdCB0aGUgZm9sbG93aW5nIG9wdGlvbnM6DQoNCjxwIGFsaWduPSJjZW50ZXIiPldoZXJlJmVtc3A7KipQT1BVTEFUSU9OKiomZW1zcDsqKmlzIGdyZWF0ZXIgdGhhbioqJmVtc3A7KiozMDAsMDAwKio8L3A+DQoNCjxwIGFsaWduPSJjZW50ZXIiPjxpbWcgc3JjPSAiSW1hZ2VzL2FyY2dpcy1sYWJlbGluZy1zcWwucG5nIiBhbHQ9IlNRTCBPcHRpb25zIGZvciBMYWJlbGluZyIgc3R5bGU9IndpZHRoOjUwJSI+PC9wPg0KDQpXaGVuIGNvbXBsZXRlLCBjbGljayAqKkFwcGx5KiogYXQgdGhlIGJvdHRvbSBvZiB0aGUgd2luZG93LiBVc2UgdGhlIG9wdGlvbnMgb24gdGhlIF9MYWJlbGluZyBUYWJfIGZvciB0aGUgZGF0YXNldCB0byBhZGp1c3QgdGhlIGxhYmVsIGZpZWxkIHRvIE5BTUUsIGNoYW5nZSB0aGUgZm9udCBvciBzaXplIG9mIHRoZSB0ZXh0LCBhbmQgY2xpY2sgdGhlICoqTGFiZWwqKiBidXR0b24gb24gdGhlIGxlZnQgb2YgdGhlIHRhYi4NCg0KPHAgYWxpZ249ImNlbnRlciI+PGRpdiBjbGFzcz0iem9vbSI+PGltZyBzcmM9ICJJbWFnZXMvYXJjZ2lzLWxhYmVsaW5nLXRhYi5qcGciIGFsdD0iTGFiZWxpbmcgT3B0aW9ucyIgc3R5bGU9IndpZHRoOjEwMCUiPjwvZGl2PjwvcD4NCg0KPGJpZz48Yj5RdWVzdGlvbiBOby4gNDwvYj48L2JpZz4NCjxibG9ja3F1b3RlPg0KV2hhdCBsYWJlbGVkIGNpdGllcyBhcmUgdGhlIGZ1cnRoZXN0IE5vcnRoLCBTb3V0aCwgRWFzdCwgYW5kIFdlc3Q/DQo8L2Jsb2NrcXVvdGU+DQoNCjwvZGV0YWlscz4NCjxocj48L2hyPg0KDQo8ZGV0YWlscz48c3VtbWFyeT48YmlnPlZpZXcgZGlyZWN0aW9ucyBpbiA8Yj4gW1FHSVNde3N0eWxlPSJjb2xvcjojMDA2NDAwIn0gPC9iPjwvc3Bhbj48L2JpZz48L3N1bW1hcnk+DQoNCklmIHlvdSBkaWQgbm90IHByZXZpb3VzbHkgZG93bmxvYWQgdGhlIFtjaXRpZXMgZGF0YV0oaHR0cHM6Ly9naXRodWIuY29tL2NocmlzbWdlbnRyeS9HSVMxLUV4ZXJjaXNlLTQvcmF3L21haW4vRGF0YS9VU19DaXRpZXNfMTAway56aXApIGZyb20gdGhlIEdpdEh1YiBFeGVyY2lzZSBQYWdlIHBsZWFzZSBkb3dubG9hZCB0aGUgZGF0YSBhbmQgdW56aXAgaXQgaW4geW91ciBwcm9qZWN0IGZvbGRlci4gV2l0aCB0aGF0IGRhdGEgYXZhaWxhYmxlLCBhZGQgdGhlIFVTX0NpdGllc18xMDBrLnNocCB0byB5b3VyIHByaW1hcnkgbWFwIChub3QgdGhlIGluc2V0IG1hcCkuIFJlcGVhdGluZyB0aGUgc3RlcHMgdG8gKipjbGlwKiogZnJvbSBbU3RlcCAxXShodHRwczovL2NocmlzbWdlbnRyeS5naXRodWIuaW8vR0lTMS1FeGVyY2lzZS00LyMxMV9TdGVwX09uZTpfVGhlX0RhdGEpIHNlbGVjdCB0aGUgY2l0aWVzIGFzIHlvdXIgX0lucHV0IExheWVyXywgdGhlIGh1cnJpY2FuZSBidWZmZXIgYXMgdGhlIF9PdmVybGF5IExheWVyXywgYW5kIGJlIHN1cmUgdG8gc2F2ZSB0aGUgbmV3IGRhdGFzZXQgdG8geW91ciBwcm9qZWN0IGZvbGRlciBpbiB0aGUgX0NsaXBwZWRfJm5ic3A7IG9wdGlvbi4gWW91IGNhbiBub3cgcmVtb3ZlIHRoZSBVUyBDaXRpZXMgZnJvbSB0aGUgcHJvamVjdCBidXQga2VlcCB5b3VyIGNsaXBwZWQgY2l0aWVzLg0KDQpXaGlsZSB5b3Ugd2lsbCBsZWF2ZSBhbGwgb2YgdGhlIGNsaXBwZWQgY2l0aWVzIG9uIHRoZSBtYXAsIHlvdSB3aWxsIG5vdyBjcmVhdGUgYSBMYWJlbCBDbGFzcyB0byBvbmx5IGNyZWF0ZSBsYWJlbHMgZm9yIGNpdGllcyB3aXRoIGEgcG9wdWxhdGlvbiBncmVhdGVyIHRoYW4gMzAwLDAwMC4gVG8gYmVnaW4sIHJpZ2h0L0NSVEwtY2xpY2sgb24geW91ciBuZXcgY2xpcHBlZCBjaXRpZXMgZGF0YXNldCBhbmQgc2VsZWN0IOKAnFByb3BlcnRpZXPigJ0uIFVuZGVyIHRoZSAqKkxhYmVscyoqIHRhYiBvbiB0aGUgbGVmdCBzaWRlIG9mIHRoZSBuZXcgd2luZG93LCBzZWxlY3QgX1J1bGUtYmFzZWQgTGFiZWxpbmdfJm5ic3A7IGZyb20gdGhlIGRyb3AtZG93biBtZW51IGF0IHRoZSB0b3Agb2YgdGhlIHdpbmRvdy4gTmV4dCwgY2xpY2sgdGhlIDxiPltHcmVlbiArXXtzdHlsZT0iY29sb3I6IzAwNjQwMCJ9PC9iPiBhdCB0aGUgYm90dG9tIHRvIGFkZCBhIG5ldyBydWxlLiBQcm92aWRlIHRoZSBmb2xsb3dpbmcgaW5wdXRzIGFuZCBjbGljayBPSw0KDQotIF9EZXNjcmlwdGlvbl8gPSBHaXZlIHlvdXIgcnVsZSBhIG5hbWUNCi0gX0ZpbHRlcl8gPSBUeXBlIHRoZSBmb2xsb3dpbmc6IGBgYCAiUE9QVUxBVElPTiIgPiAzMDAwMDBgYGANCi0gX0xhYmVsc18gPSBDaGVjayB0aGlzIGJveA0KLSBfVmFsdWVfID0gTkFNRQ0KLSBfVGV4dCwgRm9ybWF0dGluZywgQnVmZmVyLCBNYXNrLCBldGMuXyA9IEN1c3RvbWl6ZSBhcyBuZWNlc3NhcnkgZm9yIHlvdXIgcHJlZmVycmVkIHN0eWxlDQoNCjxwIGFsaWduPSJjZW50ZXIiPjxpbWcgc3JjPSAiSW1hZ2VzL3FnaXMtcnVsZS1iYXNlZC1sYWJlbHMucG5nIiBhbHQ9IlJ1bGUtYmFzZWQgT3B0aW9ucyBmb3IgTGFiZWxpbmciIHN0eWxlPSJ3aWR0aDoxMDAlIj48L3A+DQoNCkZpbmFsbHksIGNsaWNrIE9LIG9uIHRoZSBsYXllciBwcm9wZXJ0aWVzIHdpbmRvdy4gWW91IHdpbGwgbmVlZCB0byByZXR1cm4gdG8geW91ciBtYWluIG1hcCBpbiB0aGUgbGF5b3V0IGFuZCB1bmNoZWNrIHRoZSBib3ggZm9yIGxvY2tlZCB0byB1cGRhdGUgdGhlIG1hcCB3aXRoIHRoaXMgbmV3IGluZm9ybWF0aW9uLg0KDQo8YmlnPjxiPlF1ZXN0aW9uIE5vLiA0PC9iPjwvYmlnPg0KPGJsb2NrcXVvdGU+DQpXaGF0IGxhYmVsZWQgY2l0aWVzIGFyZSB0aGUgZnVydGhlc3QgTm9ydGgsIFNvdXRoLCBFYXN0LCBhbmQgV2VzdD8NCjwvYmxvY2txdW90ZT4NCg0KPC9kZXRhaWxzPg0KPGhyPjwvaHI+DQoNCjxkZXRhaWxzPjxzdW1tYXJ5PjxiaWc+VmlldyBkaXJlY3Rpb25zIGluIDxiPiBbUl17c3R5bGU9ImNvbG9yOiM2NDk1RUQifSA8L2I+PC9zcGFuPjwvYmlnPjwvc3VtbWFyeT4NCg0KSnVzdCBsaWtlIHRoZSBzdGVwcyBhYm92ZSB5b3Ugd2lsbCB1c2UgdGhlIGBkb3dubG9hZC5maWxlYCwgYHVuemlwYCwgYW5kIGByZWFkT0dSYCBmdW5jdGlvbnMgdG8gZG93bmxvYWQgdGhlIGNpdGllcyBzaGFwZWZpbGUgYW5kIGV4dHJhY3QgdGhlIGluZm9ybWF0aW9uLiBBbHNvIGxpa2UgYWJvdmUsIHlvdSB3aWxsIG5lZWQgdG8gc3Vic2V0IHRoZSBjaXRpZXMgdG8gaW5jbHVkZSBvbmx5IHRob3NlIGluIHRoZSBzZWxlY3RlZCBzdGF0ZXMuDQoNCmBgYHtyIGNpdGllcywgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFIH0NCmRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vZ2l0aHViLmNvbS9jaHJpc21nZW50cnkvR0lTMS1FeGVyY2lzZS00L3Jhdy9tYWluL0RhdGEvVVNfQ2l0aWVzXzEwMGsuemlwJywgJ2NpdGllcy56aXAnKQ0KdW56aXAoJ2NpdGllcy56aXAnKQ0KDQpjaXRpZXMgPC0gcmVhZE9HUigiLiIsIlVTX0NpdGllc18xMDBrIikNCg0Kc3Vic2V0X2NpdGllcyA8LSBjaXRpZXNbY2l0aWVzJFNUID09ICJBTCIgfCBjaXRpZXMkU1QgPT0gIkFSInwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpdGllcyRTVCA9PSAiREUiIHwgY2l0aWVzJFNUID09ICJGTCJ8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaXRpZXMkU1QgPT0gIkdBIiB8IGNpdGllcyRTVCA9PSAiSUwifA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2l0aWVzJFNUID09ICJJTiIgfCBjaXRpZXMkU1QgPT0gIktZInwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpdGllcyRTVCA9PSAiTEEiIHwgY2l0aWVzJFNUID09ICJNRCJ8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaXRpZXMkU1QgPT0gIk1TIiB8IGNpdGllcyRTVCA9PSAiTU8ifA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2l0aWVzJFNUID09ICJOSiIgfCBjaXRpZXMkU1QgPT0gIk5DInwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpdGllcyRTVCA9PSAiT0giIHwgY2l0aWVzJFNUID09ICJQQSJ8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaXRpZXMkU1QgPT0gIlNDIiB8IGNpdGllcyRTVCA9PSAiVE4ifA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2l0aWVzJFNUID09ICJWQSIgfCBjaXRpZXMkU1QgPT0gIldWIixdDQpgYGANCg0KV2l0aCB0aGUgY2l0aWVzIGluZm9ybWF0aW9uIGF2YWlsYWJsZSB5b3Ugd2lsbCBhZ2FpbiB1c2UgdGhlIGBpbnRlcnNlY3RgIGZ1bmN0aW9uIHRvIGxpbWl0IHRoZSBjaXRpZXMgZGF0YSB0byBvbmx5IHRob3NlIHdpdGhpbiB0aGUgaHVycmljYW5lIGJ1ZmZlci4NCg0KYGBge3IgYnVmZmVyZWQgY2l0aWVzLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UgfQ0KY2l0aWVzX2ludGVyc2VjdCA8LSByYXN0ZXI6OmludGVyc2VjdChzdWJzZXRfY2l0aWVzLGh1cnJpY2FuZXNfYnVmZmVyKQ0KY2l0aWVzX2ludGVyc2VjdEBkYXRhJGlkIDwtIHJvd25hbWVzKGNpdGllc19pbnRlcnNlY3RAZGF0YSkNCnNlX2NpdGllcyA8LSBkYXRhLmZyYW1lKGNpdGllc19pbnRlcnNlY3QpDQpuYW1lcyhzZV9jaXRpZXMpW25hbWVzKHNlX2NpdGllcykgPT0iY29vcmRzLngxIl0gPC0gImxvbmciDQpuYW1lcyhzZV9jaXRpZXMpW25hbWVzKHNlX2NpdGllcykgPT0iY29vcmRzLngyIl0gPC0gImxhdCINCmBgYA0KDQpOb3RpY2UgaW4gdGhlIHNjcmlwdCBhYm92ZSB0aGVyZSBpcyBhZGRpdGlvbmFsIGNvZGUgdG8gcmVuYW1lIHR3byB2YXJpYWJsZXM6IGNvb3Jkcy54MSBhbmQgY29vcmRzLngyLiBEdWUgdG8gdGhlIGNvbnZlcnNpb24gZnJvbSBhIHNoYXBlZmlsZSBhbmQgdGhlIGludGVyc2VjdCwgdGhlIHJlc3VsdGluZyBvYmplY3QgbmVlZGVkIHRvIGJlIHNldCBhcyBhIGRhdGEgZnJhbWUuIEluIHRoZSBwcm9jZXNzIHRoZSBjb29yZGluYXRlIGluZm9ybWF0aW9uIGNvbHVtbnMgd2VyZSByZW5hbWVkIGNvb3Jkcy54MSBhbmQgY29vcmRzLngyLiBUaGVyZWZvcmUgeW91IG5lZWRlZCB0byByZW5hbWUgdGhvc2UgaW5kaXZpZHVhbCBjb2x1bW5zIHRvIGxhdCBhbmQgbG9uZyB0byByZW1haW4gY29uc2lzdGVudCB3aXRoIHRoZSByZXN0IG9mIHlvdXIgc2NyaXB0cy4gDQoNCkFuZCBmaW5hbGx5IHlvdSB3aWxsIGNyZWF0ZSBhIHF1ZXJ5IHRoYXQgc2VsZWN0cyBqdXN0IHRob3NlIGNpdGllcyB0aGF0IGhhdmUgYSBwb3B1bGF0aW9uIGdyZWF0ZXIgdGhhbiAzMDAsMDAwIGluZGl2aWR1YWxzLg0KDQpgYGB7ciBsYXJnZSBjaXRpZXMsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSB9DQpsYXJnZV9jaXRpZXMgPC0gc2VfY2l0aWVzW3NlX2NpdGllcyRQT1BVTEFUSU9OID4gMzAwMDAwLF0NCmBgYA0KDQpOb3cgeW91IGhhdmUgYSBudW1iZXIgb2YgZGF0YXNldHMgdGhhdCBjYW4gYmUgdXNlZCB0byBjcmVhdGUgeW91ciBmaW5hbCBtYXAgaW5jbHVkaW5nOg0KDQotIFdvcmxkDQotIFVTIFN0YXRlcw0KLSBTb3V0aGVhc3QgU3RhdGVzDQotIFNvdXRoZWFzdCBDb3VudGllcw0KLSBIdXJyaWNhbmUgSW1wYWN0ZWQgQ291bnRpZXMNCi0gSHVycmljYW5lIFRyYWNrcw0KLSBTb3V0aGVhc3QgQ2l0aWVzDQotIExhcmdlIFNvdXRoZWFzdCBDaXRpZXMNCg0KRm9yIHlvdXIgZmluYWwgbWFwLCB5b3UgbmVlZCB0byB1c2UgdGhlc2UgZGF0YXNldHMgdG8gY3JlYXRlIHRoZSB2aXN1YWxpemF0aW9uIHJlcXVlc3RlZCBieSBGRU1BIGFib3ZlIHRoYXQgaW5jbHVkZXMgdGhlIGdlb2dyYXBoaWMgaW5mb3JtYXRpb24sIGh1cnJpY2FuZSB0cmFja3MsIGNpdGllcywgYW5kIGxhcmdlIGNpdGllcyB3aXRoIHBvcHVsYXRpb25zIGdyZWF0ZXIgdGhhbiAzMDAsMDAwLiBJbiB0aGUgQ29sYWIgTm90ZWJvayBhbmQgYmVsb3cgaXMgYW4gaW5jb21wbGV0ZSBgZ2dwbG90MmAgc2NyaXB0Lg0KDQpgYGANCmNpdGllc19tYXAgPC0gZ2dwbG90KCkgKyANCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBXb3JsZC4uLg0KICBnZW9tX3BvbHlnb24oZGF0YSA9IFVTIFN0YXRlcy4uLg0KICBnZW9tX3BvbHlnb24oZGF0YSA9IFNFIENvdW50aWVzLi4uDQogIGdlb21fcG9seWdvbihkYXRhID0gU0UgU3RhdGVzLi4uDQogIGdlb21fcG9seWdvbihkYXRhID0gSW1wYWN0ZWQgQ291bnRpZXMuLi4NCiAgZ2VvbV9wYXRoKGRhdGEgPSBIdXJyaWNhbmUgVHJhY2tzLi4uDQogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZChvcHRpb24gPSAiQSIsICJTYWZmaXJcblNpbXBzb25cblNjYWxlIikgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBzZV9jaXRpZXMsIGFlcyh4PWxvbmcsIHk9bGF0KSwgY29sb3IgPSAieWVsbG93IikgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBsYXJnZV9jaXRpZXMsIGFlcyh4PWxvbmcsIHk9bGF0KSwgY29sb3IgPSAieWVsbG93IikgKw0KICBnZW9tX3RleHQoZGF0YSA9IGxhcmdlX2NpdGllcywgYWVzKHg9bG9uZywgeT1sYXQsIGxhYmVsID0gTkFNRSwgZm9udGZhY2UgPSAiYm9sZCIpLCBzaXplID0gMywgDQogICAgICAgICAgICBudWRnZV95ID0gMC42MCwgbnVkZ2VfeCA9IDAuMjUsIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gLTg2Ljg1LCB5ID0gMzguNSwgbGFiZWwgPSAiTG91aXN2aWxsZSIsIGZvbnRmYWNlID0gImJvbGQiLCBzaXplID0gMywgY29sb3IgPSAid2hpdGUiKSArDQogIGNvb3JkX3NmKExpbWl0aW5nIGNvb3JkaW5hdGVzIHRvIGZvY3VzIG9uIHRoZSBTRSBVUy4uLg0KICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAibGlnaHRibHVlIiksIA0KICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQ0KY2l0aWVzX21hcA0KYGBgDQoNCkNvbXBsZXRlIHRoaXMgc2NyaXB0IGluIHRoZSBDb2xhYiBOb3RlYm9vaywgaW5jbHVkaW5nIGxpbmVzIGZvciBzY2FsZSBiYXIsIG5vcnRoIGFycm93LCB0aXRsZSwgbmFtZSBhbmQgZGF0ZS4gDQoNCjxiaWc+PGI+UXVlc3Rpb24gTm8uIDQ8L2I+PC9iaWc+DQo8YmxvY2txdW90ZT4NCldoYXQgbGFiZWxlZCBjaXRpZXMgYXJlIHRoZSBmdXJ0aGVzdCBOb3J0aCwgU291dGgsIEVhc3QsIGFuZCBXZXN0Pw0KPC9ibG9ja3F1b3RlPg0KDQo8L2RldGFpbHM+DQoNCiMgVGhlIFdyaXRlLVVwDQoNCkluIHRoZSByZXBvcnQgeW91IHByb3ZpZGUgdG8gRkVNQSBwbGVhc2UgcHJvdmlkZSB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uOg0KDQotIFRvdGFsIHBvcHVsYXRpb24gb2YgdGhlIGltcGFjdGVkIGNvdW50aWVzDQotIFRvdGFsIG51bWJlciBvZiBsYXJnZSBjaXRpZXMgKGFsbCBpbiB0aGUgY2xpcHBlZCBkYXRhc2V0KQ0KLSBXaGljaCBjaXRpZXMgYWJvdmUgMzAwLDAwMCBwZW9wbGUgd291bGQgbmVlZCByZXNwb25zZSB0ZWFtcw0KICAtIEJhc2VkIG9uIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlc2UsIHdvdWxkIGl0IGJlIHBvc3NpYmxlIGZvciBvbmUgcmVzcG9uc2UgdGVhbSB0byBjb3ZlciBtdWx0aXBsZSBsYXJnZSBjaXRpZXM/DQoNCldoZW4gY29tcGxldGUsIHNlbmQgYSBsaW5rIHRvIHlvdXIgX0NvbGFiIE5vdGVib29rXyBvciB3b3JkIGRvY3VtZW50IHdpdGggYW5zd2VycyB0byBRdWVzdGlvbnMgMS00IGFuZCB5b3VyIGNvbXBsZXRlZCBtYXAgdmlhIGVtYWlsLg==