1 Executive Summary

1.1 Problem Statement

In recent years, the reported rates of lyme disease in Maine have been increasing, especially in the midcoast region. As lyme disease can be difficult to diagnose, being able to determine contributing societal factors related to this outbreak is of acute concern to healthcare and epidemiological professionals. Although we can track the dynamics of reported cases, there are a number of reasons why those reported rates may be changing that are not related to the true incidence of disease in the area. From individuals spending more time in their backyards to providers not correctly diagnosing the disease, lurking variables impact our ability to track lyme through the state. Understanding which towns have a greater disease incidence and risk, because of these factors, provides a valuable tool to show lyme researchers where lyme disease diagnosis training could provide the greatest impact.

1.2 Proposed Solution

In order to parse out the relationship between various sociological behaviors and lyme risk, we created an interactive map of the state with a number of toggle-able layers so that researchers can see those associations. The base layer is a choropleth map that visualizes the number of cases per 100,000 people by town. Individuals can then toggle on three more layers to compare income, age, and locations of conserved lands within the state. Further, pinpointed locations of hospitals and primary care centers can be toggled on and selected in order to get information about healthcare access and provider frequency. This compiled data provides a route to assess the correlation between various regional factors and lyme prevalence.

1.3 Final Thoughts and Next Steps

While lyme is a difficult disease to track epidemiologically because of difficulties in diagnosing, having an understanding of the other factors at play in infection can be very beneficial in order to better understand the circumstances of individuals contracting it in different areas. We hope that this feature can be built upon to include a number of other toggle-able factors depending on data availability, including but not limited to health insurance prevalence, habitats that suit ticks, and more. Additionally, developing a system to define doctors as “lyme literate” would be beneficial to more specifically categorize the array of hospitals that individuals have access to in different areas. Finally, more up-to-date data about recognized health centers can be added in place of our current set in order to specify regional access more accurately.

2 Introduction

Maine has high rates of tick borne diseases including anaplasmosis, lyme, and babesiosis as it is prime habitat for Ixodes Scapularis, the vector responsible for carrying these bacteria. For this project, we focused on lyme disease because of its increasing prevalence, and because it involves the most reliable data. 70-80% of the time, lyme disease is accompanied by an identifiable bull’s eye rash around the site of the tick bite. The real struggle in diagnosing lyme is the 20-30% of cases that do not have this identifier as other initial symptoms can be difficult to distinguish. Further, providers that are not familiar with lyme disease or see few cases per year are less likely to provide a correct, early diagnosis. If caught early, patients can make a full recovery without lingering symptoms, however, some patients develop Post-Treatment Lyme Disease Syndrome, also known as chronic lyme disease. Symptoms include pain, fatigue, trouble thinking, and increased suicidal thoughts lasting 6 months and more after treatment.

Our partner, Maine Medical Center’s Vector-Borne Disease Lab, is interested in finding solutions to lower tick borne disease rates in Maine. This involves tracking and identifying areas in the state where individuals are at higher risk of disease. They relayed to us that many primary care providers could benefit from further educational training on diagnosing lyme. Further, that the strength and trust in primary care providers as well as resources to access health care can affect case rates because of how likely symptomatic individuals are to seek treatment. With these realities in mind, they are working to understand the significance of lyme disease case rates across the state, and how other variables affect this data. Our goal is to create maps to display trends that can guide researchers and the general public about where the risk of lyme is higher, and what healthcare resources exist in those areas. Much of this analysis involves determining reasons for higher case rates in the midcoast region.

Our research aim is to create a tool to identify where primary care providers are not meeting the demand, and investigate reasons for demand. There are a number of elements that can affect your likelihood of getting lyme, including proximity to tall grass, time spent outside, if you are checking yourself for ticks, and age. Once contracted, there are many different outcomes in the diagnosis and treatment process based on a range of factors. Those who live in a region with strong primary care providers and who are insured are more likely to be treated and correctly diagnosed. Having trust in the healthcare system is also important because it may take more than one doctor’s visit to be diagnosed. If you are of a population that is less likely to seek healthcare, you will be less likely to be correctly diagnosed and treated for the disease.

The tool that we created is an RShiny app that has two tabs. One tab is a map that displays case rates per town, median income per county, percentage of county over 65, and health care centers. These layers are toggle-able so that you can visually see intersections of high rates of lyme and other characteristics. The other tab is a table that shows case rates per town as well as the health centers available in that area.

3 Methodological Approach

Because the independent variable we’re interested in modeling is geography, we decided that a map with filters would be most useful for our community partner to visualize spatial correlations. After much deliberation about factors that could relate to the transmission of lyme disease in certain areas, we determined that we could most reliably track data related to human and provider behavior as opposed to tick locations and behavior. Although it is important to see where ticks are more likely to be carrying lyme, the passive tick submission archives were not extensive enough to be reliable in our mapping software. As such, we used the cases per 100,000 persons data as the base layer of the map.

As we experimented with different mapping strategies, we found that using data by town was more effective than using data by county because it allows for higher resolution of disease prevalence on the map. The greater specificity of town as opposed to county location on the map shows more specifically where the case rates are higher.

3.1 Preparing Spatial Data

This project relied largely on the leaflet and RShiny packages, along with assorted helper packages for dealing with spatial data. The spatial data files were available on the Maine State Geolibrary Catalog. These came in the form of .shp and .kml files, which could be read with the help of the sf package. These data had to be converted to the WGS84 datum to be used with leaflet, which was accomplished with the st_transform function from the sf package. Additionally, the rmapshaper::ms_simplify function was used to simplify the geometries for both town and county data, in order to decrease the rendering time of our Shiny application.

The following example shows the process by which we cleaned the polygon data to be used for creating leaflet map layers with town polygons.

town_latlon <- read_sf("data/spatial_data/towns/towns.shp")
town_latlon <- town_latlon %>% 
  st_transform(crs = "WGS84") %>% 
  rmapshaper::ms_simplify(explode = TRUE, weighting = 0.5)

A similar process was used for the county and conserved lands data, which were also available on the the Maine State Geolibrary Catalog.

3.2 Utilizing Spatial Data in Leaflet

Our partners requested that our final map dashboard have toggle-able layers for different potential indicators of Lyme risk. We decided that the most useful base map for this dashboard would be a choropleth map, in which each town is shaded by its relative case rate, controlled for population. In practice, this was a single layer within a leaflet map, which used the addPolygons function and mapped fillColor and color to the lyme rate data for each town. The code for this layer is as follows:

addPolygons(
        data = rates_town_latlon,
        group = "Lyme Rates",
        fillColor = ~lyme_rates_fill_palette(color_values),
        color = ~lyme_rates_fill_palette(color_values),
        weight = 1,
        fillOpacity = 0.5,
        popup = ~lyme_popup,
        options = leafletOptions(pane = "rates")
)

The function lyme_rates_fill_palette was defined using colorNumeric, and a logarithmic scale of the lyme rates. The logarithmic color scale was necessary due to one extreme outlier, the town of Islesboro. If left as a standard colorNumeric gradient, Islesboro would throw the color scale off, and cause all towns with less than 500 cases per 100,000 residents to appear the same color. The palette functions income_palette and age_palette were also created using colorNumeric, but did not require logarithmic scaling, as there were no clear outliers. This is the definition of the lyme_rates_fill_palette:

rates <- rates %>% 
    mutate(color_values = case_when(lyme != 0 ~ log(lyme, base = 1.1),
                                    lyme == 0 ~ 0) ) %>% 
    arrange(desc(lyme))

lyme_rates_fill_palette <- colorNumeric(
    palette = "Blues", 
    domain = rates$color_values)

Other layers on the leaflet map include conservation lands, the median income by county, percent of the county population over age 65, and markers for Federal Health Care Centers. The conservation land and county-level census data also utilize the addPolygons feature, while the Health Centers are done using addMarkers. Additionally, county boundaries are added via addPolylines.

3.3 Layer Controls and Map Panes

In order to create a map that is both aesthetically pleasing and functional for researchers, we had to think carefully about how to control the visibility of different layers. Ultimately, the county-level census data, which displays potential indicators of Lyme risk, needed to be toggle-able, and should be layered on top of the base Lyme cases map. To execute this vision, we used both addLayersControl and addMapPane functions.

The addMapPane function allowed us to control which layers would appear on top of other layers. The bottom-most layer would be the conservation land polygons, as that layer would not be turned on and off. The next layer is the base Lyme case rates map, which also is not able to be turned off. County boundaries can be seen on top of the town data. Next, the census data are in the same map pane, and can both be turned off independent of each other. This allows a researcher to view the county-level data and identify an area of interest, then turn off those layers to see the case rate data in detail. Lastly, the Health Center markers are on top as another toggle-able layer. In the leaflet definition, this layering is accomplished through manually setting the zIndex of each mapPane. A higher zIndex will make that mapPane be displayed on top of those with a lower zIndex.

addMapPane("indicators", zIndex = 440) %>% # county-level data
addMapPane("borders", zIndex = 450) %>% # county borders
addMapPane("rates", zIndex = 430) %>% # case rates
addMapPane("conservation", zIndex = 410) # conservation lands

In order to have layers turn on and off, we used the addLayersControl function. Each layer is assigned to a group, which is then designated as either a baseGroup or overlayGroup in the addLayersControl function. In our case, we wanted all layers that would be turned off to operate independently, so all three were designated as overlayGroups.

addLayersControl(
  overlayGroups = c("Median Income",
                    "Percent 65+",
                    "Federally Recognized Healthcare Centers")
    )

3.4 Creating an Interactive Platform

The final step in creating our interactive dashboard was to place this leaflet map within an RShiny application. The purpose of the Shiny app was to allow a researcher to select a town of concern, which would then be highlighted on the map. The second tab would allow the researcher to see all towns in the same county as the selected town, arranged by highest Lyme rate, and the third tab would display all Health Centers within that town. This multi-tab, interactive format was achieved through the sidebarLayout and tabsetPanel UI functions. The UI for this Shiny app is as follows:

ui <- fluidPage(
    titlePanel("Lyme Rates per 100,000 Population"
               ),
    sidebarLayout(
        sidebarPanel(
            h3("Maine Tracking Network Incidence Rate Data, 2016-2020."),
            selectInput("town", label = h3("Select a Town"), 
                        choices = rates$Location, 
                        selected = "Portland")
        ),
        mainPanel(
            tabsetPanel(
                tabPanel("Map", 
                         leafletOutput("mymap")),
                tabPanel("Cases",
                         h3("Towns in the same county with the highest lyme rates."),
                         tableOutput("table")),
                tabPanel("Health Centers",
                         h3("Federally-Recognized Healthcare Centers in this town."),
                         tableOutput("health"))
            )
            
        )
    )
)   

For interactivity, the server functions all depended on the town input. The first of these was to add an additional addPolylines function to the leaflet map, which would highlight the desired town in yellow.

output$mymap <- renderLeaflet({
        town_leaflet %>% 
            addMapPane("highlight", zIndex = 500) %>% 
            addPolylines(
                options = leafletOptions(pane = "highlight"),
                data = rates_town_latlon %>% filter(TOWN == input$town),
                color = "yellow",
                weight = 2,
                opacity = 1
            )

The next two server chunks each created a table, which changes depending on the value of input$town. One determines the county that this town is in, and shows all of the towns within that county. The other behaves similarly, but filters the Federal Health Centers data to only include Health Centers within the desired town. Below, find the code for filtering by the county that input$town belongs to:

output$table <- renderTable(
      rates %>% 
        filter(COUNTY == rates$COUNTY[which(rates$Location == input$town)]) %>% 
        mutate(Town = Location) %>% 
        mutate(County = COUNTY) %>% 
        select(Town, lyme, anaplasmosis, babesiosis, County) %>% 
        arrange(desc(lyme)) 
      )

3.5 Future Code Improvements to Consider

The most attractive potential code improvement to consider for the future of this project would be to convert the existing tables in the Shiny app to utilize the kableExtra package for interactive HTML formatting. This could allow the user to arrange the data by different variables. For example, they could change from arranging the set by Lyme rates to arranging by Anaplasmosis rates, or view the set from lowest to highest Lyme rate rather than highest to lowest. There was not time to explore this package during the extremely compact 3 week schedule of the course, but it would be a relatively simple add-on that could vastly improve the usability of the dashboard.

4 Results and Discussion

Our final product is a map and accompanying table that is to be used as a tool to guide our community partner in their process of drawing conclusions about disease prevention of tick-borne disease. We start with a base map of tick-borne disease case incidence as well as toggle-able layers for case rates per town, median income per county, percentage of county over age 65, conserved land, and federally recognized health care centers.

Our map is mainly to be used as a research tool for scientists hoping to learn more about hotspots of tick-borne diseases, and not as a source to draw definitive, statistical outcomes. With that in mind, we start with a base layer map of tick-borne disease incidence rates. With this base layer, we are able to see basic information about where certain tick-borne diseases are strongest. From there, we can add our layers onto the map to see how they interact and reveal more information about tick prevalence as it interacts with different factors across Maine.

The first toggleable layer allows users to filter by case rates per town. This filter allows users to compare the indicators (other filters) to the variable we are trying to lower (tick-borne disease cases). Therefore, users are able to get a better picture of the number of cases in each town, not necessarily the proportion. This allows users to draw conclusions about which towns are recording and reporting the most tick cases by number. This plays into how easily and readily people are able to report tick cases in their area, and how well doctors are able to identify them. As a particular standout example, case rates are noteably high in Isleboro because there is a doctor who is up to date on sending in paperwork confirming cases. This sort of training for primary health providers has a huge impact on the reporting of tick cases. In terms of visualization creation, we used a logarithmic scale for the coloration of towns, so the Isleboro data was not the only town that had a visible difference in color, given that its concentration was so high in comparison to other towns.

Our next filter was median income per county, collected via census data. Median income per county, while not a direct cause of tick-borne diseases, is a great indicator of patient behavior in the event of a tick bite and the town response. It is useful to predict where primary care providers are strongest, citizens are insured, and those who could have lyme will pursue multiple opinions on sickness. High income areas tend to have better access to health care and more resources, and in areas with lower median income, people might be less inclined to seek out help from primary health providers in the same way. High income people are more likely to spend more on health care and are more likely to access specialists. Median income data also can also explain where citizens have more leisure time to contract lyme. While our users should not make any firm decisions from these data, it is highly useful to examine in tandem with our other indicators to see overlapping points of interest, and to give more context to areas that may need more attention on the primary healthcare center side.

Our next layer filters by the percentage of the people in a county who are over 65 years of age. Here, our goal is to draw attention to the role that age may play in contracting lyme and other tick-borne diseases. Senior citizens may be susceptible to weaker immune systems (becoming more likely to be affected more heavily by bites) and are more likely to be retired, thus having more leisure time outdoors to contract lyme. Symptoms for tick borne diseases are more serious for seniors and may present differently, so it is important that they have access to health care to treat the disease as soon as possible. The results here are particularly useful in tandem with the conservation lands data.

In consideration of lyme disease, it is intuitive to think about tick location as the primary indicator for lyme, as we did before further conversations with our community partner. The conservation land filter allows for more context about where tick habitats exist since conserved lands tend to be more wooded with tall grass. As we are aware, people are most likely to contract bites on their property, in their backyards. However, in many places in Maine, conserved lands back up onto people’s backyards or really serve as them. Additionally, areas with less conserved land could designate urban spaces where incidence of individuals contracting lyme in their backyards is presumed to be much lower. As such, we determined that it would still be beneficial to include the map layer. This filter sheds light on the prevalence of ticks in certain towns, and how that may play into tick-borne disease analysis. Especially if this is an area with few reported ticks but high proportions of conserved land.

Our final toggleable layer to our map is a layer of federally recognized health care centers in Maine. This layer was added both as a resource to citizens in Maine and researchers/scientists at Maine Medical Center. This feature allows users to see healthcare providers in close proximity to them. For citizens, it may help them to figure out where they should immediately go if they were bitten by a tick, and for researchers it may help to be able to isolate blank spots in healthcare coverage, or areas where healthcare coverage doesn’t match up with the reported number of cases in a certain region. This final layer helps to bridge the gap between case incidence and primary healthcare education, essentially allowing researchers to draw connections between tick incidence and the actions that Maine Medical should take when considering tick-borne disease training implementation locations and to identify health centers in areas of distress.

Given the nature of our resulting work, a lot of the decision of what to include in our layers of the base tick-incidence map came from discussion with project partners, drawing on their knowledge base and our own personal experience with ticks in Maine to determine the best path forwards in terms of what data to collect. Our final list of what to include in the map was based on mutual discussion and collaboration. Our sources come from widely recognizable and available sources, including US census data (income, age) and google scrapes/federal records (health centers). This is also why our results are not to be taken as statistically-sound facts to make decisions off of, but rather as generalizable trends to take into account when attempting to make decisions of tick-borne disease education.

5 Recomendations and Next Steps

Because we were limited in time, there are a number of future directions that could improve the efficacy of this tool. The first limiting issue for us was accuracy and relevancy of our healthcare center data. In making the decision to work with data discovered from a google maps scrape of healthcare providers versus federally recognized centers we had to weigh the importance of data completeness (finding every location that could work with lyme, even if not federally recognized) and data reliability (whether the healthcare centers found were actually adequate for providing treatment). We know that a more reliable arrangement of centers is being developed for use, this data can easily be added to our script in place of the federally recognized centers that we chose to plot. Once that data is cleaned and added to the code, it will replace that map layer.

In that same vein, a consideration of ours while mapping the centers involved the relevancy of a number of the sites in terms of whether or not they were well equipped to diagnose and treat lyme disease. In our research and conversations with community partners we determined that some sites are more “lyme literate” than others, meaning that those doctors may more frequently see and treat lyme, or have been more recently educated about diagnosis and treatment. While urgent care sites and emergency rooms can list on their websites that they are equipped to treat lyme, we don’t have an understanding of whether that information is reliable based upon their true experience with it. Further, we didn’t believe that we were well equipped to make those determinations because of our lack of data and understanding about lyme educational campaigns across the state. If the Vector-Borne Disease Lab were able to survey doctors about how frequently they diagnose and are educated about lyme, or use other sources of similar data to evaluate healthcare sites based upon lyme literacy, those characteristics could be added to the map. Being more specific about how competently healthcare sites could identify and treat the disease would make the map more effective because it would control for lyme hotspots due to provider reliability and emphasize areas where the disease may be going underdiagnosed because of a deficiency on the provider side. Further, sites where individuals are unlikely to go for lyme disease symptoms because of a lack of training or testing capability could be eliminated from the set.

The area with the greatest opportunity for development as we conclude the project is the map layers. The beauty of using interactive software to show trends is that there are infinite possibilities about what data can be added. Now that the baseline code process has been set up, it will be simple to clean new information using the format that we’ve identified and create fresh layers. A roadblock for us was the availability of relevant data. Although we had a number of ideas about various important factors related to contracting lyme disease, there simply was not existing data divided by Maine county or town. We thought that some interesting layers of information could involve health insurance access, outdoor recreational activity participation, and locations of lyme disease educational campaigns.

Because our leaflet is meant to act as a tool for researchers, next steps involve using the information gathered from it to determine which hospitals require further lyme disease training. Evaluating the factors listed in contrast to the baseline lyme case rates allows us to inform our currently-listed health centers that they are possibly underdiagnosing.

6 References

Artiga, S., Orgera, K., & Pham, O. (2020). Disparities in health and health care: Five key questions and answers. Kaiser Family Foundation.

Bisanzio, D., Fernández, M. P., Martello, E., Reithinger, R., & Diuk-Wasser, M. A. (2020). Current and future spatiotemporal patterns of Lyme disease reporting in the Northeastern United States. JAMA network open, 3(3), e200319-e200319.

Dickman, S. L., Woolhandler, S., Bor, J., McCormick, D., Bor, D. H., & Himmelstein, D. U. (2016). Health spending for low-, middle-, and high-income Americans, 1963–2012. Health Affairs, 35(7), 1189-1196.

Eisen, R. J., Piesman, J., Zielinski-Gutierrez, E., & Eisen, L. (2012). What do we need to know about disease ecology to prevent Lyme disease in the northeastern United States?. Journal of medical entomology, 49(1), 11-22.

Elias, S. P., Maasch, K. A., Anderson, N. T., Rand, P. W., Lacombe, E. H., Robich, R. M., … & Smith Jr, R. P. (2020). Decoupling of blacklegged tick abundance and Lyme disease incidence in Southern Maine, USA. Journal of medical entomology, 57(3), 755-765.

Herrington Jr, J. E., Campbell, G. L., Bailey, R. E., Cartter, M. L., Adams, M., Frazier, E. L., … & Gensheimer, K. F. (1997). Predisposing factors for individuals’ Lyme disease prevention practices: Connecticut, Maine, and Montana. American journal of public health, 87(12), 2035-2038.

Lacout, A., El Hajjam, M., Marcy, P. Y., & Perronne, C. (2018). The persistent Lyme disease:“True chronic Lyme disease” rather than “post-treatment Lyme disease syndrome”. Journal of Global Infectious Diseases, 10(3), 170.

Maine Center for Disease Control and Prevention, Maine Tracking Network. Tick-Related: Near real-time data. Retrieved from https://data.mainepublichealth.gov/tracking/.

Smith Jr, R. P., Rand, P. W., & Lacombe, E. H. (1990). Potential for Lyme disease in Maine: deer survey of distribution of Ixodes dammini, the tick vector. American journal of public health, 80(3), 333-335

State of Maine, Geolibrary Data Catalog. Maine Town and Townships Boundary Polygons (2022) [Data file]. Retrieved from https://www.maine.gov/geolib/catalog.html#boundaries.

Van Doorslaer, E., Masseria, C., & Koolman, X. (2006). Inequalities in access to medical care by income in developed countries. Cmaj, 174(2), 177-183.

U.S. Census Bureau 2022. SELECTED CHARACTERISTICS OF THE NATIVE AND FOREIGN BORN POPULATIONS. Retrieved from https://data.census.gov/cedsci/.

LS0tCnRpdGxlOiAiTWFwcGluZyBQcmltYXJ5IENhcmUgUHJvdmlkZXJzIGZvciBMeW1lIERpc2Vhc2UgRWR1Y2F0aW9uIE91dHJlYWNoIgphdXRob3I6ICJHcmFjZSBBY3RvbiwgTWFyY28gV2lsbGVuLCBTaGVsYnkgQXJtb3IsIEVtaWx5IFRhbWtpbiIKZGF0ZTogIlNob3J0IFRlcm0gMjAyMiIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IHNhbmRzdG9uZQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICBudW1iZXJfc2VjdGlvbnM6IFRSVUUKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCiAgICB0b2NfZGVwdGg6IDEKICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUKLS0tCiAgICAKYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UpICMgU3RlcCAyIENoYW5naW5nIHRoZSBjb2RlIGNodW5rIHNldHRpbmdzCmBgYCAgICAKCmBgYHtyIExpYnJhcmllcywgZWNobyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KCiMgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKbGlicmFyeSh0aWR5dmVyc2UpCgojIGluc3RhbGwucGFja2FnZXMoImthYmxlRXh0cmEiKQpsaWJyYXJ5KGthYmxlRXh0cmEpCgojIGluc3RhbGwucGFja2FnZXMoImdhcG1pbmRlciIpCmxpYnJhcnkoZ2FwbWluZGVyKQoKIyBpbnN0YWxsLnBhY2thZ2VzKCJsZWFmbGV0IikKbGlicmFyeShsZWFmbGV0KQoKbGlicmFyeShzaGlueSkKbGlicmFyeShzZikKbGlicmFyeShybWFwc2hhcGVyKQpgYGAKCiMgRXhlY3V0aXZlIFN1bW1hcnkKIyMgUHJvYmxlbSBTdGF0ZW1lbnQgIApJbiByZWNlbnQgeWVhcnMsIHRoZSByZXBvcnRlZCByYXRlcyBvZiBseW1lIGRpc2Vhc2UgaW4gTWFpbmUgaGF2ZSBiZWVuIGluY3JlYXNpbmcsIGVzcGVjaWFsbHkgaW4gdGhlIG1pZGNvYXN0IHJlZ2lvbi4gQXMgbHltZSBkaXNlYXNlIGNhbiBiZSBkaWZmaWN1bHQgdG8gZGlhZ25vc2UsIGJlaW5nIGFibGUgdG8gZGV0ZXJtaW5lIGNvbnRyaWJ1dGluZyBzb2NpZXRhbCBmYWN0b3JzIHJlbGF0ZWQgdG8gdGhpcyBvdXRicmVhayBpcyBvZiBhY3V0ZSBjb25jZXJuIHRvIGhlYWx0aGNhcmUgYW5kIGVwaWRlbWlvbG9naWNhbCBwcm9mZXNzaW9uYWxzLiBBbHRob3VnaCB3ZSBjYW4gdHJhY2sgdGhlIGR5bmFtaWNzIG9mIHJlcG9ydGVkIGNhc2VzLCB0aGVyZSBhcmUgYSBudW1iZXIgb2YgcmVhc29ucyB3aHkgdGhvc2UgcmVwb3J0ZWQgcmF0ZXMgbWF5IGJlIGNoYW5naW5nIHRoYXQgYXJlIG5vdCByZWxhdGVkIHRvIHRoZSB0cnVlIGluY2lkZW5jZSBvZiBkaXNlYXNlIGluIHRoZSBhcmVhLiBGcm9tIGluZGl2aWR1YWxzIHNwZW5kaW5nIG1vcmUgdGltZSBpbiB0aGVpciBiYWNreWFyZHMgdG8gcHJvdmlkZXJzIG5vdCBjb3JyZWN0bHkgZGlhZ25vc2luZyB0aGUgZGlzZWFzZSwgbHVya2luZyB2YXJpYWJsZXMgaW1wYWN0IG91ciBhYmlsaXR5IHRvIHRyYWNrIGx5bWUgdGhyb3VnaCB0aGUgc3RhdGUuIFVuZGVyc3RhbmRpbmcgd2hpY2ggdG93bnMgaGF2ZSBhIGdyZWF0ZXIgZGlzZWFzZSBpbmNpZGVuY2UgYW5kIHJpc2ssIGJlY2F1c2Ugb2YgdGhlc2UgZmFjdG9ycywgcHJvdmlkZXMgYSB2YWx1YWJsZSB0b29sIHRvIHNob3cgbHltZSByZXNlYXJjaGVycyB3aGVyZSBseW1lIGRpc2Vhc2UgZGlhZ25vc2lzIHRyYWluaW5nIGNvdWxkIHByb3ZpZGUgdGhlIGdyZWF0ZXN0IGltcGFjdC4gIAoKCiMjIFByb3Bvc2VkIFNvbHV0aW9uICAKSW4gb3JkZXIgdG8gcGFyc2Ugb3V0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB2YXJpb3VzIHNvY2lvbG9naWNhbCBiZWhhdmlvcnMgYW5kIGx5bWUgcmlzaywgd2UgY3JlYXRlZCBhbiBpbnRlcmFjdGl2ZSBtYXAgb2YgdGhlIHN0YXRlIHdpdGggYSBudW1iZXIgb2YgdG9nZ2xlLWFibGUgbGF5ZXJzIHNvIHRoYXQgcmVzZWFyY2hlcnMgY2FuIHNlZSB0aG9zZSBhc3NvY2lhdGlvbnMuIFRoZSBiYXNlIGxheWVyIGlzIGEgY2hvcm9wbGV0aCBtYXAgdGhhdCB2aXN1YWxpemVzIHRoZSBudW1iZXIgb2YgY2FzZXMgcGVyIDEwMCwwMDAgcGVvcGxlIGJ5IHRvd24uIEluZGl2aWR1YWxzIGNhbiB0aGVuIHRvZ2dsZSBvbiB0aHJlZSBtb3JlIGxheWVycyB0byBjb21wYXJlIGluY29tZSwgYWdlLCBhbmQgbG9jYXRpb25zIG9mIGNvbnNlcnZlZCBsYW5kcyB3aXRoaW4gdGhlIHN0YXRlLiBGdXJ0aGVyLCBwaW5wb2ludGVkIGxvY2F0aW9ucyBvZiBob3NwaXRhbHMgYW5kIHByaW1hcnkgY2FyZSBjZW50ZXJzIGNhbiBiZSB0b2dnbGVkIG9uIGFuZCBzZWxlY3RlZCBpbiBvcmRlciB0byBnZXQgaW5mb3JtYXRpb24gYWJvdXQgaGVhbHRoY2FyZSBhY2Nlc3MgYW5kIHByb3ZpZGVyIGZyZXF1ZW5jeS4gVGhpcyBjb21waWxlZCBkYXRhIHByb3ZpZGVzIGEgcm91dGUgdG8gYXNzZXNzIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHZhcmlvdXMgcmVnaW9uYWwgZmFjdG9ycyBhbmQgbHltZSBwcmV2YWxlbmNlLiAgCgoKIyMgRmluYWwgVGhvdWdodHMgYW5kIE5leHQgU3RlcHMgIApXaGlsZSBseW1lIGlzIGEgZGlmZmljdWx0IGRpc2Vhc2UgdG8gdHJhY2sgZXBpZGVtaW9sb2dpY2FsbHkgYmVjYXVzZSBvZiBkaWZmaWN1bHRpZXMgaW4gZGlhZ25vc2luZywgaGF2aW5nIGFuIHVuZGVyc3RhbmRpbmcgb2YgdGhlIG90aGVyIGZhY3RvcnMgYXQgcGxheSBpbiBpbmZlY3Rpb24gY2FuIGJlIHZlcnkgYmVuZWZpY2lhbCBpbiBvcmRlciB0byBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgY2lyY3Vtc3RhbmNlcyBvZiBpbmRpdmlkdWFscyBjb250cmFjdGluZyBpdCBpbiBkaWZmZXJlbnQgYXJlYXMuIFdlIGhvcGUgdGhhdCB0aGlzIGZlYXR1cmUgY2FuIGJlIGJ1aWx0IHVwb24gdG8gaW5jbHVkZSBhIG51bWJlciBvZiBvdGhlciB0b2dnbGUtYWJsZSBmYWN0b3JzIGRlcGVuZGluZyBvbiBkYXRhIGF2YWlsYWJpbGl0eSwgaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZCB0byBoZWFsdGggaW5zdXJhbmNlIHByZXZhbGVuY2UsIGhhYml0YXRzIHRoYXQgc3VpdCB0aWNrcywgYW5kIG1vcmUuIEFkZGl0aW9uYWxseSwgZGV2ZWxvcGluZyBhIHN5c3RlbSB0byBkZWZpbmUgZG9jdG9ycyBhcyDigJxseW1lIGxpdGVyYXRl4oCdIHdvdWxkIGJlIGJlbmVmaWNpYWwgdG8gbW9yZSBzcGVjaWZpY2FsbHkgY2F0ZWdvcml6ZSB0aGUgYXJyYXkgb2YgaG9zcGl0YWxzIHRoYXQgaW5kaXZpZHVhbHMgaGF2ZSBhY2Nlc3MgdG8gaW4gZGlmZmVyZW50IGFyZWFzLiBGaW5hbGx5LCBtb3JlIHVwLXRvLWRhdGUgZGF0YSBhYm91dCByZWNvZ25pemVkIGhlYWx0aCBjZW50ZXJzIGNhbiBiZSBhZGRlZCBpbiBwbGFjZSBvZiBvdXIgY3VycmVudCBzZXQgaW4gb3JkZXIgdG8gc3BlY2lmeSByZWdpb25hbCBhY2Nlc3MgbW9yZSBhY2N1cmF0ZWx5LgoKIyBJbnRyb2R1Y3Rpb24KICBNYWluZSBoYXMgaGlnaCByYXRlcyBvZiB0aWNrIGJvcm5lIGRpc2Vhc2VzIGluY2x1ZGluZyBhbmFwbGFzbW9zaXMsIGx5bWUsIGFuZCBiYWJlc2lvc2lzIGFzIGl0IGlzIHByaW1lIGhhYml0YXQgZm9yIEl4b2RlcyBTY2FwdWxhcmlzLCB0aGUgdmVjdG9yIHJlc3BvbnNpYmxlIGZvciBjYXJyeWluZyB0aGVzZSBiYWN0ZXJpYS4gRm9yIHRoaXMgcHJvamVjdCwgd2UgZm9jdXNlZCBvbiBseW1lIGRpc2Vhc2UgYmVjYXVzZSBvZiBpdHMgaW5jcmVhc2luZyBwcmV2YWxlbmNlLCBhbmQgYmVjYXVzZSBpdCBpbnZvbHZlcyB0aGUgbW9zdCByZWxpYWJsZSBkYXRhLiA3MC04MCUgb2YgdGhlIHRpbWUsIGx5bWUgZGlzZWFzZSBpcyBhY2NvbXBhbmllZCBieSBhbiBpZGVudGlmaWFibGUgYnVsbOKAmXMgZXllIHJhc2ggYXJvdW5kIHRoZSBzaXRlIG9mIHRoZSB0aWNrIGJpdGUuIFRoZSByZWFsIHN0cnVnZ2xlIGluIGRpYWdub3NpbmcgbHltZSBpcyB0aGUgMjAtMzAlIG9mIGNhc2VzIHRoYXQgZG8gbm90IGhhdmUgdGhpcyBpZGVudGlmaWVyIGFzIG90aGVyIGluaXRpYWwgc3ltcHRvbXMgY2FuIGJlIGRpZmZpY3VsdCB0byBkaXN0aW5ndWlzaC4gRnVydGhlciwgcHJvdmlkZXJzIHRoYXQgYXJlIG5vdCBmYW1pbGlhciB3aXRoIGx5bWUgZGlzZWFzZSBvciBzZWUgZmV3IGNhc2VzIHBlciB5ZWFyIGFyZSBsZXNzIGxpa2VseSB0byBwcm92aWRlIGEgY29ycmVjdCwgZWFybHkgZGlhZ25vc2lzLiBJZiBjYXVnaHQgZWFybHksIHBhdGllbnRzIGNhbiBtYWtlIGEgZnVsbCByZWNvdmVyeSB3aXRob3V0IGxpbmdlcmluZyBzeW1wdG9tcywgaG93ZXZlciwgc29tZSBwYXRpZW50cyBkZXZlbG9wIFBvc3QtVHJlYXRtZW50IEx5bWUgRGlzZWFzZSBTeW5kcm9tZSwgYWxzbyBrbm93biBhcyBjaHJvbmljIGx5bWUgZGlzZWFzZS4gU3ltcHRvbXMgaW5jbHVkZSBwYWluLCBmYXRpZ3VlLCB0cm91YmxlIHRoaW5raW5nLCBhbmQgaW5jcmVhc2VkIHN1aWNpZGFsIHRob3VnaHRzIGxhc3RpbmcgNiBtb250aHMgYW5kIG1vcmUgYWZ0ZXIgdHJlYXRtZW50LiAgCgogIE91ciBwYXJ0bmVyLCBNYWluZSBNZWRpY2FsIENlbnRlcuKAmXMgVmVjdG9yLUJvcm5lIERpc2Vhc2UgTGFiLCBpcyBpbnRlcmVzdGVkIGluIGZpbmRpbmcgc29sdXRpb25zIHRvIGxvd2VyIHRpY2sgYm9ybmUgZGlzZWFzZSByYXRlcyBpbiBNYWluZS4gVGhpcyBpbnZvbHZlcyB0cmFja2luZyBhbmQgaWRlbnRpZnlpbmcgYXJlYXMgaW4gdGhlIHN0YXRlIHdoZXJlIGluZGl2aWR1YWxzIGFyZSBhdCBoaWdoZXIgcmlzayBvZiBkaXNlYXNlLiBUaGV5IHJlbGF5ZWQgdG8gdXMgdGhhdCBtYW55IHByaW1hcnkgY2FyZSBwcm92aWRlcnMgY291bGQgYmVuZWZpdCBmcm9tIGZ1cnRoZXIgZWR1Y2F0aW9uYWwgdHJhaW5pbmcgb24gZGlhZ25vc2luZyBseW1lLiBGdXJ0aGVyLCB0aGF0IHRoZSBzdHJlbmd0aCBhbmQgdHJ1c3QgaW4gcHJpbWFyeSBjYXJlIHByb3ZpZGVycyBhcyB3ZWxsIGFzIHJlc291cmNlcyB0byBhY2Nlc3MgaGVhbHRoIGNhcmUgY2FuIGFmZmVjdCBjYXNlIHJhdGVzIGJlY2F1c2Ugb2YgaG93IGxpa2VseSBzeW1wdG9tYXRpYyBpbmRpdmlkdWFscyBhcmUgdG8gc2VlayB0cmVhdG1lbnQuIFdpdGggdGhlc2UgcmVhbGl0aWVzIGluIG1pbmQsIHRoZXkgYXJlIHdvcmtpbmcgdG8gdW5kZXJzdGFuZCB0aGUgc2lnbmlmaWNhbmNlIG9mIGx5bWUgZGlzZWFzZSBjYXNlIHJhdGVzIGFjcm9zcyB0aGUgc3RhdGUsIGFuZCBob3cgb3RoZXIgdmFyaWFibGVzIGFmZmVjdCB0aGlzIGRhdGEuIE91ciBnb2FsIGlzIHRvIGNyZWF0ZSBtYXBzIHRvIGRpc3BsYXkgdHJlbmRzIHRoYXQgY2FuIGd1aWRlIHJlc2VhcmNoZXJzIGFuZCB0aGUgZ2VuZXJhbCBwdWJsaWMgYWJvdXQgd2hlcmUgdGhlIHJpc2sgb2YgbHltZSBpcyBoaWdoZXIsIGFuZCB3aGF0IGhlYWx0aGNhcmUgcmVzb3VyY2VzIGV4aXN0IGluIHRob3NlIGFyZWFzLiBNdWNoIG9mIHRoaXMgYW5hbHlzaXMgaW52b2x2ZXMgZGV0ZXJtaW5pbmcgcmVhc29ucyBmb3IgaGlnaGVyIGNhc2UgcmF0ZXMgaW4gdGhlIG1pZGNvYXN0IHJlZ2lvbi4gIAoKICBPdXIgcmVzZWFyY2ggYWltIGlzIHRvIGNyZWF0ZSBhIHRvb2wgdG8gaWRlbnRpZnkgd2hlcmUgcHJpbWFyeSBjYXJlIHByb3ZpZGVycyBhcmUgbm90IG1lZXRpbmcgdGhlIGRlbWFuZCwgYW5kIGludmVzdGlnYXRlIHJlYXNvbnMgZm9yIGRlbWFuZC4gVGhlcmUgYXJlIGEgbnVtYmVyIG9mIGVsZW1lbnRzIHRoYXQgY2FuIGFmZmVjdCB5b3VyIGxpa2VsaWhvb2Qgb2YgZ2V0dGluZyBseW1lLCBpbmNsdWRpbmcgcHJveGltaXR5IHRvIHRhbGwgZ3Jhc3MsIHRpbWUgc3BlbnQgb3V0c2lkZSwgaWYgeW91IGFyZSBjaGVja2luZyB5b3Vyc2VsZiBmb3IgdGlja3MsIGFuZCBhZ2UuIE9uY2UgY29udHJhY3RlZCwgdGhlcmUgYXJlIG1hbnkgZGlmZmVyZW50IG91dGNvbWVzIGluIHRoZSBkaWFnbm9zaXMgYW5kIHRyZWF0bWVudCBwcm9jZXNzIGJhc2VkIG9uIGEgcmFuZ2Ugb2YgZmFjdG9ycy4gVGhvc2Ugd2hvIGxpdmUgaW4gYSByZWdpb24gd2l0aCBzdHJvbmcgcHJpbWFyeSBjYXJlIHByb3ZpZGVycyBhbmQgd2hvIGFyZSBpbnN1cmVkIGFyZSBtb3JlIGxpa2VseSB0byBiZSB0cmVhdGVkIGFuZCBjb3JyZWN0bHkgZGlhZ25vc2VkLiBIYXZpbmcgdHJ1c3QgaW4gdGhlIGhlYWx0aGNhcmUgc3lzdGVtIGlzIGFsc28gaW1wb3J0YW50IGJlY2F1c2UgaXQgbWF5IHRha2UgbW9yZSB0aGFuIG9uZSBkb2N0b3LigJlzIHZpc2l0IHRvIGJlIGRpYWdub3NlZC4gSWYgeW91IGFyZSBvZiBhIHBvcHVsYXRpb24gdGhhdCBpcyBsZXNzIGxpa2VseSB0byBzZWVrIGhlYWx0aGNhcmUsIHlvdSB3aWxsIGJlIGxlc3MgbGlrZWx5IHRvIGJlIGNvcnJlY3RseSBkaWFnbm9zZWQgYW5kIHRyZWF0ZWQgZm9yIHRoZSBkaXNlYXNlLiAgCiAKICBUaGUgdG9vbCB0aGF0IHdlIGNyZWF0ZWQgaXMgYW4gUlNoaW55IGFwcCB0aGF0IGhhcyB0d28gdGFicy4gT25lIHRhYiBpcyBhIG1hcCB0aGF0IGRpc3BsYXlzIGNhc2UgcmF0ZXMgcGVyIHRvd24sIG1lZGlhbiBpbmNvbWUgcGVyIGNvdW50eSwgcGVyY2VudGFnZSBvZiBjb3VudHkgb3ZlciA2NSwgYW5kIGhlYWx0aCBjYXJlIGNlbnRlcnMuIFRoZXNlIGxheWVycyBhcmUgdG9nZ2xlLWFibGUgc28gdGhhdCB5b3UgY2FuIHZpc3VhbGx5IHNlZSBpbnRlcnNlY3Rpb25zIG9mIGhpZ2ggcmF0ZXMgb2YgbHltZSBhbmQgb3RoZXIgY2hhcmFjdGVyaXN0aWNzLiBUaGUgb3RoZXIgdGFiIGlzIGEgdGFibGUgdGhhdCBzaG93cyBjYXNlIHJhdGVzIHBlciB0b3duIGFzIHdlbGwgYXMgdGhlIGhlYWx0aCBjZW50ZXJzIGF2YWlsYWJsZSBpbiB0aGF0IGFyZWEuCgoKIyBNZXRob2RvbG9naWNhbCBBcHByb2FjaAogIEJlY2F1c2UgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlIHdl4oCZcmUgaW50ZXJlc3RlZCBpbiBtb2RlbGluZyBpcyBnZW9ncmFwaHksIHdlIGRlY2lkZWQgdGhhdCBhIG1hcCB3aXRoIGZpbHRlcnMgd291bGQgYmUgbW9zdCB1c2VmdWwgZm9yIG91ciBjb21tdW5pdHkgcGFydG5lciB0byB2aXN1YWxpemUgc3BhdGlhbCBjb3JyZWxhdGlvbnMuIEFmdGVyIG11Y2ggZGVsaWJlcmF0aW9uIGFib3V0IGZhY3RvcnMgdGhhdCBjb3VsZCByZWxhdGUgdG8gdGhlIHRyYW5zbWlzc2lvbiBvZiBseW1lIGRpc2Vhc2UgaW4gY2VydGFpbiBhcmVhcywgd2UgZGV0ZXJtaW5lZCB0aGF0IHdlIGNvdWxkIG1vc3QgcmVsaWFibHkgdHJhY2sgZGF0YSByZWxhdGVkIHRvIGh1bWFuIGFuZCBwcm92aWRlciBiZWhhdmlvciBhcyBvcHBvc2VkIHRvIHRpY2sgbG9jYXRpb25zIGFuZCBiZWhhdmlvci4gQWx0aG91Z2ggaXQgaXMgaW1wb3J0YW50IHRvIHNlZSB3aGVyZSB0aWNrcyBhcmUgbW9yZSBsaWtlbHkgdG8gYmUgY2FycnlpbmcgbHltZSwgdGhlIHBhc3NpdmUgdGljayBzdWJtaXNzaW9uIGFyY2hpdmVzIHdlcmUgbm90IGV4dGVuc2l2ZSBlbm91Z2ggdG8gYmUgcmVsaWFibGUgaW4gb3VyIG1hcHBpbmcgc29mdHdhcmUuIEFzIHN1Y2gsIHdlIHVzZWQgdGhlIGNhc2VzIHBlciAxMDAsMDAwIHBlcnNvbnMgZGF0YSBhcyB0aGUgYmFzZSBsYXllciBvZiB0aGUgbWFwLiAgCgogIEFzIHdlIGV4cGVyaW1lbnRlZCB3aXRoIGRpZmZlcmVudCBtYXBwaW5nIHN0cmF0ZWdpZXMsIHdlIGZvdW5kIHRoYXQgdXNpbmcgZGF0YSBieSB0b3duIHdhcyBtb3JlIGVmZmVjdGl2ZSB0aGFuIHVzaW5nIGRhdGEgYnkgY291bnR5IGJlY2F1c2UgaXQgYWxsb3dzIGZvciBoaWdoZXIgcmVzb2x1dGlvbiBvZiBkaXNlYXNlIHByZXZhbGVuY2Ugb24gdGhlIG1hcC4gVGhlIGdyZWF0ZXIgc3BlY2lmaWNpdHkgb2YgdG93biBhcyBvcHBvc2VkIHRvIGNvdW50eSBsb2NhdGlvbiBvbiB0aGUgbWFwIHNob3dzIG1vcmUgc3BlY2lmaWNhbGx5IHdoZXJlIHRoZSBjYXNlIHJhdGVzIGFyZSBoaWdoZXIuICAKCiMjIFByZXBhcmluZyBTcGF0aWFsIERhdGEKClRoaXMgcHJvamVjdCByZWxpZWQgbGFyZ2VseSBvbiB0aGUgYGxlYWZsZXRgIGFuZCBgUlNoaW55YCBwYWNrYWdlcywgYWxvbmcgd2l0aCBhc3NvcnRlZCBoZWxwZXIgcGFja2FnZXMgZm9yIGRlYWxpbmcgd2l0aCBzcGF0aWFsIGRhdGEuIFRoZSBzcGF0aWFsIGRhdGEgZmlsZXMgd2VyZSBhdmFpbGFibGUgb24gdGhlIE1haW5lIFN0YXRlIEdlb2xpYnJhcnkgQ2F0YWxvZy4gVGhlc2UgY2FtZSBpbiB0aGUgZm9ybSBvZiBgLnNocGAgYW5kIGAua21sYCBmaWxlcywgd2hpY2ggY291bGQgYmUgcmVhZCB3aXRoIHRoZSBoZWxwIG9mIHRoZSBgc2ZgIHBhY2thZ2UuIFRoZXNlIGRhdGEgaGFkIHRvIGJlIGNvbnZlcnRlZCB0byB0aGUgV0dTODQgZGF0dW0gdG8gYmUgdXNlZCB3aXRoIGBsZWFmbGV0YCwgd2hpY2ggd2FzIGFjY29tcGxpc2hlZCB3aXRoIHRoZSBgc3RfdHJhbnNmb3JtYCBmdW5jdGlvbiBmcm9tIHRoZSBgc2ZgIHBhY2thZ2UuIEFkZGl0aW9uYWxseSwgdGhlIGBybWFwc2hhcGVyOjptc19zaW1wbGlmeWAgZnVuY3Rpb24gd2FzIHVzZWQgdG8gc2ltcGxpZnkgdGhlIGdlb21ldHJpZXMgZm9yIGJvdGggdG93biBhbmQgY291bnR5IGRhdGEsIGluIG9yZGVyIHRvIGRlY3JlYXNlIHRoZSByZW5kZXJpbmcgdGltZSBvZiBvdXIgYFNoaW55YCBhcHBsaWNhdGlvbi4gCgpUaGUgZm9sbG93aW5nIGV4YW1wbGUgc2hvd3MgdGhlIHByb2Nlc3MgYnkgd2hpY2ggd2UgY2xlYW5lZCB0aGUgcG9seWdvbiBkYXRhIHRvIGJlIHVzZWQgZm9yIGNyZWF0aW5nIGBsZWFmbGV0YCBtYXAgbGF5ZXJzIHdpdGggdG93biBwb2x5Z29ucy4KCmBgYHtyIHBvbHlnb24tY2xlYW5pbmcsIGVjaG89VFJVRSwgZXZhbD1GQUxTRX0KdG93bl9sYXRsb24gPC0gcmVhZF9zZigiZGF0YS9zcGF0aWFsX2RhdGEvdG93bnMvdG93bnMuc2hwIikKdG93bl9sYXRsb24gPC0gdG93bl9sYXRsb24gJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSAiV0dTODQiKSAlPiUgCiAgcm1hcHNoYXBlcjo6bXNfc2ltcGxpZnkoZXhwbG9kZSA9IFRSVUUsIHdlaWdodGluZyA9IDAuNSkKYGBgCgpBIHNpbWlsYXIgcHJvY2VzcyB3YXMgdXNlZCBmb3IgdGhlIGNvdW50eSBhbmQgY29uc2VydmVkIGxhbmRzIGRhdGEsIHdoaWNoIHdlcmUgYWxzbyBhdmFpbGFibGUgb24gdGhlIHRoZSBNYWluZSBTdGF0ZSBHZW9saWJyYXJ5IENhdGFsb2cuIAoKIyMgVXRpbGl6aW5nIFNwYXRpYWwgRGF0YSBpbiBgTGVhZmxldGAKCk91ciBwYXJ0bmVycyByZXF1ZXN0ZWQgdGhhdCBvdXIgZmluYWwgbWFwIGRhc2hib2FyZCBoYXZlIHRvZ2dsZS1hYmxlIGxheWVycyBmb3IgZGlmZmVyZW50IHBvdGVudGlhbCBpbmRpY2F0b3JzIG9mIEx5bWUgcmlzay4gV2UgZGVjaWRlZCB0aGF0IHRoZSBtb3N0IHVzZWZ1bCBiYXNlIG1hcCBmb3IgdGhpcyBkYXNoYm9hcmQgd291bGQgYmUgYSBjaG9yb3BsZXRoIG1hcCwgaW4gd2hpY2ggZWFjaCB0b3duIGlzIHNoYWRlZCBieSBpdHMgcmVsYXRpdmUgY2FzZSByYXRlLCBjb250cm9sbGVkIGZvciBwb3B1bGF0aW9uLiBJbiBwcmFjdGljZSwgdGhpcyB3YXMgYSBzaW5nbGUgbGF5ZXIgd2l0aGluIGEgYGxlYWZsZXRgIG1hcCwgd2hpY2ggdXNlZCB0aGUgYGFkZFBvbHlnb25zYCBmdW5jdGlvbiBhbmQgbWFwcGVkIGBmaWxsQ29sb3JgIGFuZCBgY29sb3JgIHRvIHRoZSBseW1lIHJhdGUgZGF0YSBmb3IgZWFjaCB0b3duLiBUaGUgY29kZSBmb3IgdGhpcyBsYXllciBpcyBhcyBmb2xsb3dzOiAKCmBgYHtyIHRvd24tbGF5ZXIsIGVjaG89VFJVRSwgZXZhbD1GQUxTRX0KYWRkUG9seWdvbnMoCiAgICAgICAgZGF0YSA9IHJhdGVzX3Rvd25fbGF0bG9uLAogICAgICAgIGdyb3VwID0gIkx5bWUgUmF0ZXMiLAogICAgICAgIGZpbGxDb2xvciA9IH5seW1lX3JhdGVzX2ZpbGxfcGFsZXR0ZShjb2xvcl92YWx1ZXMpLAogICAgICAgIGNvbG9yID0gfmx5bWVfcmF0ZXNfZmlsbF9wYWxldHRlKGNvbG9yX3ZhbHVlcyksCiAgICAgICAgd2VpZ2h0ID0gMSwKICAgICAgICBmaWxsT3BhY2l0eSA9IDAuNSwKICAgICAgICBwb3B1cCA9IH5seW1lX3BvcHVwLAogICAgICAgIG9wdGlvbnMgPSBsZWFmbGV0T3B0aW9ucyhwYW5lID0gInJhdGVzIikKKQpgYGAKClRoZSBmdW5jdGlvbiBgbHltZV9yYXRlc19maWxsX3BhbGV0dGVgIHdhcyBkZWZpbmVkIHVzaW5nIGBjb2xvck51bWVyaWNgLCBhbmQgYSBsb2dhcml0aG1pYyBzY2FsZSBvZiB0aGUgbHltZSByYXRlcy4gVGhlIGxvZ2FyaXRobWljIGNvbG9yIHNjYWxlIHdhcyBuZWNlc3NhcnkgZHVlIHRvIG9uZSBleHRyZW1lIG91dGxpZXIsIHRoZSB0b3duIG9mIElzbGVzYm9yby4gSWYgbGVmdCBhcyBhIHN0YW5kYXJkIGBjb2xvck51bWVyaWNgIGdyYWRpZW50LCBJc2xlc2Jvcm8gd291bGQgdGhyb3cgdGhlIGNvbG9yIHNjYWxlIG9mZiwgYW5kIGNhdXNlIGFsbCB0b3ducyB3aXRoIGxlc3MgdGhhbiA1MDAgY2FzZXMgcGVyIDEwMCwwMDAgcmVzaWRlbnRzIHRvIGFwcGVhciB0aGUgc2FtZSBjb2xvci4gVGhlIHBhbGV0dGUgZnVuY3Rpb25zIGBpbmNvbWVfcGFsZXR0ZWAgYW5kIGBhZ2VfcGFsZXR0ZWAgd2VyZSBhbHNvIGNyZWF0ZWQgdXNpbmcgYGNvbG9yTnVtZXJpY2AsIGJ1dCBkaWQgbm90IHJlcXVpcmUgbG9nYXJpdGhtaWMgc2NhbGluZywgYXMgdGhlcmUgd2VyZSBubyBjbGVhciBvdXRsaWVycy4gVGhpcyBpcyB0aGUgZGVmaW5pdGlvbiBvZiB0aGUgYGx5bWVfcmF0ZXNfZmlsbF9wYWxldHRlYDoKCmBgYHtyIGZpbGwtcGFsZXR0ZSwgZWNobz1UUlVFLCBldmFsPUZBTFNFfQpyYXRlcyA8LSByYXRlcyAlPiUgCiAgICBtdXRhdGUoY29sb3JfdmFsdWVzID0gY2FzZV93aGVuKGx5bWUgIT0gMCB+IGxvZyhseW1lLCBiYXNlID0gMS4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHltZSA9PSAwIH4gMCkgKSAlPiUgCiAgICBhcnJhbmdlKGRlc2MobHltZSkpCgpseW1lX3JhdGVzX2ZpbGxfcGFsZXR0ZSA8LSBjb2xvck51bWVyaWMoCiAgICBwYWxldHRlID0gIkJsdWVzIiwgCiAgICBkb21haW4gPSByYXRlcyRjb2xvcl92YWx1ZXMpCmBgYAoKT3RoZXIgbGF5ZXJzIG9uIHRoZSBgbGVhZmxldGAgbWFwIGluY2x1ZGUgY29uc2VydmF0aW9uIGxhbmRzLCB0aGUgbWVkaWFuIGluY29tZSBieSBjb3VudHksIHBlcmNlbnQgb2YgdGhlIGNvdW50eSBwb3B1bGF0aW9uIG92ZXIgYWdlIDY1LCBhbmQgbWFya2VycyBmb3IgRmVkZXJhbCBIZWFsdGggQ2FyZSBDZW50ZXJzLiBUaGUgY29uc2VydmF0aW9uIGxhbmQgYW5kIGNvdW50eS1sZXZlbCBjZW5zdXMgZGF0YSBhbHNvIHV0aWxpemUgdGhlIGBhZGRQb2x5Z29uc2AgZmVhdHVyZSwgd2hpbGUgdGhlIEhlYWx0aCBDZW50ZXJzIGFyZSBkb25lIHVzaW5nIGBhZGRNYXJrZXJzYC4gQWRkaXRpb25hbGx5LCBjb3VudHkgYm91bmRhcmllcyBhcmUgYWRkZWQgdmlhIGBhZGRQb2x5bGluZXNgLiAKCiMjIExheWVyIENvbnRyb2xzIGFuZCBNYXAgUGFuZXMKCkluIG9yZGVyIHRvIGNyZWF0ZSBhIG1hcCB0aGF0IGlzIGJvdGggYWVzdGhldGljYWxseSBwbGVhc2luZyBhbmQgZnVuY3Rpb25hbCBmb3IgcmVzZWFyY2hlcnMsIHdlIGhhZCB0byB0aGluayBjYXJlZnVsbHkgYWJvdXQgaG93IHRvIGNvbnRyb2wgdGhlIHZpc2liaWxpdHkgb2YgZGlmZmVyZW50IGxheWVycy4gVWx0aW1hdGVseSwgdGhlIGNvdW50eS1sZXZlbCBjZW5zdXMgZGF0YSwgd2hpY2ggZGlzcGxheXMgcG90ZW50aWFsIGluZGljYXRvcnMgb2YgTHltZSByaXNrLCBuZWVkZWQgdG8gYmUgdG9nZ2xlLWFibGUsIGFuZCBzaG91bGQgYmUgbGF5ZXJlZCBvbiB0b3Agb2YgdGhlIGJhc2UgTHltZSBjYXNlcyBtYXAuIFRvIGV4ZWN1dGUgdGhpcyB2aXNpb24sIHdlIHVzZWQgYm90aCBgYWRkTGF5ZXJzQ29udHJvbGAgYW5kIGBhZGRNYXBQYW5lYCBmdW5jdGlvbnMuIAoKVGhlIGBhZGRNYXBQYW5lYCBmdW5jdGlvbiBhbGxvd2VkIHVzIHRvIGNvbnRyb2wgd2hpY2ggbGF5ZXJzIHdvdWxkIGFwcGVhciBvbiB0b3Agb2Ygb3RoZXIgbGF5ZXJzLiBUaGUgYm90dG9tLW1vc3QgbGF5ZXIgd291bGQgYmUgdGhlIGNvbnNlcnZhdGlvbiBsYW5kIHBvbHlnb25zLCBhcyB0aGF0IGxheWVyIHdvdWxkIG5vdCBiZSB0dXJuZWQgb24gYW5kIG9mZi4gVGhlIG5leHQgbGF5ZXIgaXMgdGhlIGJhc2UgTHltZSBjYXNlIHJhdGVzIG1hcCwgd2hpY2ggYWxzbyBpcyBub3QgYWJsZSB0byBiZSB0dXJuZWQgb2ZmLiBDb3VudHkgYm91bmRhcmllcyBjYW4gYmUgc2VlbiBvbiB0b3Agb2YgdGhlIHRvd24gZGF0YS4gTmV4dCwgdGhlIGNlbnN1cyBkYXRhIGFyZSBpbiB0aGUgc2FtZSBtYXAgcGFuZSwgYW5kIGNhbiBib3RoIGJlIHR1cm5lZCBvZmYgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlci4gVGhpcyBhbGxvd3MgYSByZXNlYXJjaGVyIHRvIHZpZXcgdGhlIGNvdW50eS1sZXZlbCBkYXRhIGFuZCBpZGVudGlmeSBhbiBhcmVhIG9mIGludGVyZXN0LCB0aGVuIHR1cm4gb2ZmIHRob3NlIGxheWVycyB0byBzZWUgdGhlIGNhc2UgcmF0ZSBkYXRhIGluIGRldGFpbC4gTGFzdGx5LCB0aGUgSGVhbHRoIENlbnRlciBtYXJrZXJzIGFyZSBvbiB0b3AgYXMgYW5vdGhlciB0b2dnbGUtYWJsZSBsYXllci4gSW4gdGhlIGBsZWFmbGV0YCBkZWZpbml0aW9uLCB0aGlzIGxheWVyaW5nIGlzIGFjY29tcGxpc2hlZCB0aHJvdWdoIG1hbnVhbGx5IHNldHRpbmcgdGhlIGB6SW5kZXhgIG9mIGVhY2ggYG1hcFBhbmVgLiBBIGhpZ2hlciBgekluZGV4YCB3aWxsIG1ha2UgdGhhdCBgbWFwUGFuZWAgYmUgZGlzcGxheWVkIG9uIHRvcCBvZiB0aG9zZSB3aXRoIGEgbG93ZXIgYHpJbmRleGAuIAoKYGBge3IgbWFwLXBhbmVzLCBlY2hvPVRSVUUsIGV2YWw9RkFMU0V9CmFkZE1hcFBhbmUoImluZGljYXRvcnMiLCB6SW5kZXggPSA0NDApICU+JSAjIGNvdW50eS1sZXZlbCBkYXRhCmFkZE1hcFBhbmUoImJvcmRlcnMiLCB6SW5kZXggPSA0NTApICU+JSAjIGNvdW50eSBib3JkZXJzCmFkZE1hcFBhbmUoInJhdGVzIiwgekluZGV4ID0gNDMwKSAlPiUgIyBjYXNlIHJhdGVzCmFkZE1hcFBhbmUoImNvbnNlcnZhdGlvbiIsIHpJbmRleCA9IDQxMCkgIyBjb25zZXJ2YXRpb24gbGFuZHMKYGBgCgpJbiBvcmRlciB0byBoYXZlIGxheWVycyB0dXJuIG9uIGFuZCBvZmYsIHdlIHVzZWQgdGhlIGBhZGRMYXllcnNDb250cm9sYCBmdW5jdGlvbi4gRWFjaCBsYXllciBpcyBhc3NpZ25lZCB0byBhIGdyb3VwLCB3aGljaCBpcyB0aGVuIGRlc2lnbmF0ZWQgYXMgZWl0aGVyIGEgYGJhc2VHcm91cGAgb3IgYG92ZXJsYXlHcm91cGAgaW4gdGhlIGBhZGRMYXllcnNDb250cm9sYCBmdW5jdGlvbi4gSW4gb3VyIGNhc2UsIHdlIHdhbnRlZCBhbGwgbGF5ZXJzIHRoYXQgd291bGQgYmUgdHVybmVkIG9mZiB0byBvcGVyYXRlIGluZGVwZW5kZW50bHksIHNvIGFsbCB0aHJlZSB3ZXJlIGRlc2lnbmF0ZWQgYXMgYG92ZXJsYXlHcm91cHNgLiAKCmBgYHtyIGxheWVycywgZWNobz1UUlVFLCBldmFsPUZBTFNFfQphZGRMYXllcnNDb250cm9sKAogIG92ZXJsYXlHcm91cHMgPSBjKCJNZWRpYW4gSW5jb21lIiwKICAgICAgICAgICAgICAgICAgICAiUGVyY2VudCA2NSsiLAogICAgICAgICAgICAgICAgICAgICJGZWRlcmFsbHkgUmVjb2duaXplZCBIZWFsdGhjYXJlIENlbnRlcnMiKQogICAgKQpgYGAKCiMjIENyZWF0aW5nIGFuIEludGVyYWN0aXZlIFBsYXRmb3JtCgpUaGUgZmluYWwgc3RlcCBpbiBjcmVhdGluZyBvdXIgaW50ZXJhY3RpdmUgZGFzaGJvYXJkIHdhcyB0byBwbGFjZSB0aGlzIGBsZWFmbGV0YCBtYXAgd2l0aGluIGFuIGBSU2hpbnlgIGFwcGxpY2F0aW9uLiBUaGUgcHVycG9zZSBvZiB0aGUgYFNoaW55YCBhcHAgd2FzIHRvIGFsbG93IGEgcmVzZWFyY2hlciB0byBzZWxlY3QgYSB0b3duIG9mIGNvbmNlcm4sIHdoaWNoIHdvdWxkIHRoZW4gYmUgaGlnaGxpZ2h0ZWQgb24gdGhlIG1hcC4gVGhlIHNlY29uZCB0YWIgd291bGQgYWxsb3cgdGhlIHJlc2VhcmNoZXIgdG8gc2VlIGFsbCB0b3ducyBpbiB0aGUgc2FtZSBjb3VudHkgYXMgdGhlIHNlbGVjdGVkIHRvd24sIGFycmFuZ2VkIGJ5IGhpZ2hlc3QgTHltZSByYXRlLCBhbmQgdGhlIHRoaXJkIHRhYiB3b3VsZCBkaXNwbGF5IGFsbCBIZWFsdGggQ2VudGVycyB3aXRoaW4gdGhhdCB0b3duLiBUaGlzIG11bHRpLXRhYiwgaW50ZXJhY3RpdmUgZm9ybWF0IHdhcyBhY2hpZXZlZCB0aHJvdWdoIHRoZSBgc2lkZWJhckxheW91dGAgYW5kIGB0YWJzZXRQYW5lbGAgVUkgZnVuY3Rpb25zLiBUaGUgVUkgZm9yIHRoaXMgYFNoaW55YCBhcHAgaXMgYXMgZm9sbG93czoKCmBgYHtyIHNoaW55LXVpLCBlY2hvPVRSVUUsIGV2YWw9RkFMU0V9CnVpIDwtIGZsdWlkUGFnZSgKICAgIHRpdGxlUGFuZWwoIkx5bWUgUmF0ZXMgcGVyIDEwMCwwMDAgUG9wdWxhdGlvbiIKICAgICAgICAgICAgICAgKSwKICAgIHNpZGViYXJMYXlvdXQoCiAgICAgICAgc2lkZWJhclBhbmVsKAogICAgICAgICAgICBoMygiTWFpbmUgVHJhY2tpbmcgTmV0d29yayBJbmNpZGVuY2UgUmF0ZSBEYXRhLCAyMDE2LTIwMjAuIiksCiAgICAgICAgICAgIHNlbGVjdElucHV0KCJ0b3duIiwgbGFiZWwgPSBoMygiU2VsZWN0IGEgVG93biIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgY2hvaWNlcyA9IHJhdGVzJExvY2F0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQgPSAiUG9ydGxhbmQiKQogICAgICAgICksCiAgICAgICAgbWFpblBhbmVsKAogICAgICAgICAgICB0YWJzZXRQYW5lbCgKICAgICAgICAgICAgICAgIHRhYlBhbmVsKCJNYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGxlYWZsZXRPdXRwdXQoIm15bWFwIikpLAogICAgICAgICAgICAgICAgdGFiUGFuZWwoIkNhc2VzIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGgzKCJUb3ducyBpbiB0aGUgc2FtZSBjb3VudHkgd2l0aCB0aGUgaGlnaGVzdCBseW1lIHJhdGVzLiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgdGFibGVPdXRwdXQoInRhYmxlIikpLAogICAgICAgICAgICAgICAgdGFiUGFuZWwoIkhlYWx0aCBDZW50ZXJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGgzKCJGZWRlcmFsbHktUmVjb2duaXplZCBIZWFsdGhjYXJlIENlbnRlcnMgaW4gdGhpcyB0b3duLiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgdGFibGVPdXRwdXQoImhlYWx0aCIpKQogICAgICAgICAgICApCiAgICAgICAgICAgIAogICAgICAgICkKICAgICkKKSAgIApgYGAKCkZvciBpbnRlcmFjdGl2aXR5LCB0aGUgc2VydmVyIGZ1bmN0aW9ucyBhbGwgZGVwZW5kZWQgb24gdGhlIHRvd24gaW5wdXQuIFRoZSBmaXJzdCBvZiB0aGVzZSB3YXMgdG8gYWRkIGFuIGFkZGl0aW9uYWwgYGFkZFBvbHlsaW5lc2AgZnVuY3Rpb24gdG8gdGhlIGBsZWFmbGV0YCBtYXAsIHdoaWNoIHdvdWxkIGhpZ2hsaWdodCB0aGUgZGVzaXJlZCB0b3duIGluIHllbGxvdy4gCgpgYGB7ciBzaGlueS1oaWdobGlnaHQsIGVjaG89VFJVRSwgZXZhbD1GQUxTRX0Kb3V0cHV0JG15bWFwIDwtIHJlbmRlckxlYWZsZXQoewogICAgICAgIHRvd25fbGVhZmxldCAlPiUgCiAgICAgICAgICAgIGFkZE1hcFBhbmUoImhpZ2hsaWdodCIsIHpJbmRleCA9IDUwMCkgJT4lIAogICAgICAgICAgICBhZGRQb2x5bGluZXMoCiAgICAgICAgICAgICAgICBvcHRpb25zID0gbGVhZmxldE9wdGlvbnMocGFuZSA9ICJoaWdobGlnaHQiKSwKICAgICAgICAgICAgICAgIGRhdGEgPSByYXRlc190b3duX2xhdGxvbiAlPiUgZmlsdGVyKFRPV04gPT0gaW5wdXQkdG93biksCiAgICAgICAgICAgICAgICBjb2xvciA9ICJ5ZWxsb3ciLAogICAgICAgICAgICAgICAgd2VpZ2h0ID0gMiwKICAgICAgICAgICAgICAgIG9wYWNpdHkgPSAxCiAgICAgICAgICAgICkKYGBgCgoKVGhlIG5leHQgdHdvIHNlcnZlciBjaHVua3MgZWFjaCBjcmVhdGVkIGEgdGFibGUsIHdoaWNoIGNoYW5nZXMgZGVwZW5kaW5nIG9uIHRoZSB2YWx1ZSBvZiBgaW5wdXQkdG93bmAuIE9uZSBkZXRlcm1pbmVzIHRoZSBjb3VudHkgdGhhdCB0aGlzIHRvd24gaXMgaW4sIGFuZCBzaG93cyBhbGwgb2YgdGhlIHRvd25zIHdpdGhpbiB0aGF0IGNvdW50eS4gVGhlIG90aGVyIGJlaGF2ZXMgc2ltaWxhcmx5LCBidXQgZmlsdGVycyB0aGUgRmVkZXJhbCBIZWFsdGggQ2VudGVycyBkYXRhIHRvIG9ubHkgaW5jbHVkZSBIZWFsdGggQ2VudGVycyB3aXRoaW4gdGhlIGRlc2lyZWQgdG93bi4gQmVsb3csIGZpbmQgdGhlIGNvZGUgZm9yIGZpbHRlcmluZyBieSB0aGUgY291bnR5IHRoYXQgYGlucHV0JHRvd25gIGJlbG9uZ3MgdG86CgpgYGB7ciBzaGlueS10YWJsZSwgZWNobz1UUlVFLCBldmFsPUZBTFNFfQpvdXRwdXQkdGFibGUgPC0gcmVuZGVyVGFibGUoCiAgICAgIHJhdGVzICU+JSAKICAgICAgICBmaWx0ZXIoQ09VTlRZID09IHJhdGVzJENPVU5UWVt3aGljaChyYXRlcyRMb2NhdGlvbiA9PSBpbnB1dCR0b3duKV0pICU+JSAKICAgICAgICBtdXRhdGUoVG93biA9IExvY2F0aW9uKSAlPiUgCiAgICAgICAgbXV0YXRlKENvdW50eSA9IENPVU5UWSkgJT4lIAogICAgICAgIHNlbGVjdChUb3duLCBseW1lLCBhbmFwbGFzbW9zaXMsIGJhYmVzaW9zaXMsIENvdW50eSkgJT4lIAogICAgICAgIGFycmFuZ2UoZGVzYyhseW1lKSkgCiAgICAgICkKYGBgCgojIyBGdXR1cmUgQ29kZSBJbXByb3ZlbWVudHMgdG8gQ29uc2lkZXIKClRoZSBtb3N0IGF0dHJhY3RpdmUgcG90ZW50aWFsIGNvZGUgaW1wcm92ZW1lbnQgdG8gY29uc2lkZXIgZm9yIHRoZSBmdXR1cmUgb2YgdGhpcyBwcm9qZWN0IHdvdWxkIGJlIHRvIGNvbnZlcnQgdGhlIGV4aXN0aW5nIHRhYmxlcyBpbiB0aGUgYFNoaW55YCBhcHAgdG8gdXRpbGl6ZSB0aGUgYGthYmxlRXh0cmFgIHBhY2thZ2UgZm9yIGludGVyYWN0aXZlIEhUTUwgZm9ybWF0dGluZy4gVGhpcyBjb3VsZCBhbGxvdyB0aGUgdXNlciB0byBhcnJhbmdlIHRoZSBkYXRhIGJ5IGRpZmZlcmVudCB2YXJpYWJsZXMuIEZvciBleGFtcGxlLCB0aGV5IGNvdWxkIGNoYW5nZSBmcm9tIGFycmFuZ2luZyB0aGUgc2V0IGJ5IEx5bWUgcmF0ZXMgdG8gYXJyYW5naW5nIGJ5IEFuYXBsYXNtb3NpcyByYXRlcywgb3IgdmlldyB0aGUgc2V0IGZyb20gbG93ZXN0IHRvIGhpZ2hlc3QgTHltZSByYXRlIHJhdGhlciB0aGFuIGhpZ2hlc3QgdG8gbG93ZXN0LiBUaGVyZSB3YXMgbm90IHRpbWUgdG8gZXhwbG9yZSB0aGlzIHBhY2thZ2UgZHVyaW5nIHRoZSBleHRyZW1lbHkgY29tcGFjdCAzIHdlZWsgc2NoZWR1bGUgb2YgdGhlIGNvdXJzZSwgYnV0IGl0IHdvdWxkIGJlIGEgcmVsYXRpdmVseSBzaW1wbGUgYWRkLW9uIHRoYXQgY291bGQgdmFzdGx5IGltcHJvdmUgdGhlIHVzYWJpbGl0eSBvZiB0aGUgZGFzaGJvYXJkLiAKCiMgUmVzdWx0cyBhbmQgRGlzY3Vzc2lvbgpPdXIgZmluYWwgcHJvZHVjdCBpcyBhIG1hcCBhbmQgYWNjb21wYW55aW5nIHRhYmxlIHRoYXQgaXMgdG8gYmUgdXNlZCBhcyBhIHRvb2wgdG8gZ3VpZGUgb3VyIGNvbW11bml0eSBwYXJ0bmVyIGluIHRoZWlyIHByb2Nlc3Mgb2YgZHJhd2luZyBjb25jbHVzaW9ucyBhYm91dCBkaXNlYXNlIHByZXZlbnRpb24gb2YgdGljay1ib3JuZSBkaXNlYXNlLiBXZSBzdGFydCB3aXRoIGEgYmFzZSBtYXAgb2YgdGljay1ib3JuZSBkaXNlYXNlIGNhc2UgaW5jaWRlbmNlIGFzIHdlbGwgYXMgdG9nZ2xlLWFibGUgbGF5ZXJzIGZvciBjYXNlIHJhdGVzIHBlciB0b3duLCBtZWRpYW4gaW5jb21lIHBlciBjb3VudHksIHBlcmNlbnRhZ2Ugb2YgY291bnR5IG92ZXIgYWdlIDY1LCBjb25zZXJ2ZWQgbGFuZCwgYW5kIGZlZGVyYWxseSByZWNvZ25pemVkIGhlYWx0aCBjYXJlIGNlbnRlcnMuICAKCk91ciBtYXAgaXMgbWFpbmx5IHRvIGJlIHVzZWQgYXMgYSByZXNlYXJjaCB0b29sIGZvciBzY2llbnRpc3RzIGhvcGluZyB0byBsZWFybiBtb3JlIGFib3V0IGhvdHNwb3RzIG9mIHRpY2stYm9ybmUgZGlzZWFzZXMsIGFuZCBub3QgYXMgYSBzb3VyY2UgdG8gZHJhdyBkZWZpbml0aXZlLCBzdGF0aXN0aWNhbCBvdXRjb21lcy4gV2l0aCB0aGF0IGluIG1pbmQsIHdlIHN0YXJ0IHdpdGggYSBiYXNlIGxheWVyIG1hcCBvZiB0aWNrLWJvcm5lIGRpc2Vhc2UgaW5jaWRlbmNlIHJhdGVzLiBXaXRoIHRoaXMgYmFzZSBsYXllciwgd2UgYXJlIGFibGUgdG8gc2VlIGJhc2ljIGluZm9ybWF0aW9uIGFib3V0IHdoZXJlIGNlcnRhaW4gdGljay1ib3JuZSBkaXNlYXNlcyBhcmUgc3Ryb25nZXN0LiBGcm9tIHRoZXJlLCB3ZSBjYW4gYWRkIG91ciBsYXllcnMgb250byB0aGUgbWFwIHRvIHNlZSBob3cgdGhleSBpbnRlcmFjdCBhbmQgcmV2ZWFsIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGljayBwcmV2YWxlbmNlIGFzIGl0IGludGVyYWN0cyB3aXRoIGRpZmZlcmVudCBmYWN0b3JzIGFjcm9zcyBNYWluZS4gIAoKVGhlIGZpcnN0IHRvZ2dsZWFibGUgbGF5ZXIgYWxsb3dzIHVzZXJzIHRvIGZpbHRlciBieSBjYXNlIHJhdGVzIHBlciB0b3duLiBUaGlzIGZpbHRlciBhbGxvd3MgdXNlcnMgdG8gY29tcGFyZSB0aGUgaW5kaWNhdG9ycyAob3RoZXIgZmlsdGVycykgdG8gdGhlIHZhcmlhYmxlIHdlIGFyZSB0cnlpbmcgdG8gbG93ZXIgKHRpY2stYm9ybmUgZGlzZWFzZSBjYXNlcykuIFRoZXJlZm9yZSwgdXNlcnMgYXJlIGFibGUgdG8gZ2V0IGEgYmV0dGVyIHBpY3R1cmUgb2YgdGhlIG51bWJlciBvZiBjYXNlcyBpbiBlYWNoIHRvd24sIG5vdCBuZWNlc3NhcmlseSB0aGUgcHJvcG9ydGlvbi4gVGhpcyBhbGxvd3MgdXNlcnMgdG8gZHJhdyBjb25jbHVzaW9ucyBhYm91dCB3aGljaCB0b3ducyBhcmUgcmVjb3JkaW5nIGFuZCByZXBvcnRpbmcgdGhlIG1vc3QgdGljayBjYXNlcyBieSBudW1iZXIuIFRoaXMgcGxheXMgaW50byBob3cgZWFzaWx5IGFuZCByZWFkaWx5IHBlb3BsZSBhcmUgYWJsZSB0byByZXBvcnQgdGljayBjYXNlcyBpbiB0aGVpciBhcmVhLCBhbmQgaG93IHdlbGwgZG9jdG9ycyBhcmUgYWJsZSB0byBpZGVudGlmeSB0aGVtLiBBcyBhIHBhcnRpY3VsYXIgc3RhbmRvdXQgZXhhbXBsZSwgY2FzZSByYXRlcyBhcmUgbm90ZWFibHkgaGlnaCBpbiBJc2xlYm9ybyBiZWNhdXNlIHRoZXJlIGlzIGEgZG9jdG9yIHdobyBpcyB1cCB0byBkYXRlIG9uIHNlbmRpbmcgaW4gcGFwZXJ3b3JrIGNvbmZpcm1pbmcgY2FzZXMuIFRoaXMgc29ydCBvZiB0cmFpbmluZyBmb3IgcHJpbWFyeSBoZWFsdGggcHJvdmlkZXJzIGhhcyBhIGh1Z2UgaW1wYWN0IG9uIHRoZSByZXBvcnRpbmcgb2YgdGljayBjYXNlcy4gSW4gdGVybXMgb2YgdmlzdWFsaXphdGlvbiBjcmVhdGlvbiwgd2UgdXNlZCBhIGxvZ2FyaXRobWljIHNjYWxlIGZvciB0aGUgY29sb3JhdGlvbiBvZiB0b3ducywgc28gdGhlIElzbGVib3JvIGRhdGEgd2FzIG5vdCB0aGUgb25seSB0b3duIHRoYXQgaGFkIGEgdmlzaWJsZSBkaWZmZXJlbmNlIGluIGNvbG9yLCBnaXZlbiB0aGF0IGl0cyBjb25jZW50cmF0aW9uIHdhcyBzbyBoaWdoIGluIGNvbXBhcmlzb24gdG8gb3RoZXIgdG93bnMuIAoKT3VyIG5leHQgZmlsdGVyIHdhcyBtZWRpYW4gaW5jb21lIHBlciBjb3VudHksIGNvbGxlY3RlZCB2aWEgY2Vuc3VzIGRhdGEuIE1lZGlhbiBpbmNvbWUgcGVyIGNvdW50eSwgd2hpbGUgbm90IGEgZGlyZWN0IGNhdXNlIG9mIHRpY2stYm9ybmUgZGlzZWFzZXMsIGlzIGEgZ3JlYXQgaW5kaWNhdG9yIG9mIHBhdGllbnQgYmVoYXZpb3IgaW4gdGhlIGV2ZW50IG9mIGEgdGljayBiaXRlIGFuZCB0aGUgdG93biByZXNwb25zZS4gSXQgaXMgdXNlZnVsIHRvIHByZWRpY3Qgd2hlcmUgcHJpbWFyeSBjYXJlIHByb3ZpZGVycyBhcmUgc3Ryb25nZXN0LCBjaXRpemVucyBhcmUgaW5zdXJlZCwgYW5kIHRob3NlIHdobyBjb3VsZCBoYXZlIGx5bWUgd2lsbCBwdXJzdWUgbXVsdGlwbGUgb3BpbmlvbnMgb24gc2lja25lc3MuIEhpZ2ggaW5jb21lIGFyZWFzIHRlbmQgdG8gaGF2ZSBiZXR0ZXIgYWNjZXNzIHRvIGhlYWx0aCBjYXJlIGFuZCBtb3JlIHJlc291cmNlcywgYW5kIGluIGFyZWFzIHdpdGggbG93ZXIgbWVkaWFuIGluY29tZSwgcGVvcGxlIG1pZ2h0IGJlIGxlc3MgaW5jbGluZWQgdG8gc2VlayBvdXQgaGVscCBmcm9tIHByaW1hcnkgaGVhbHRoIHByb3ZpZGVycyBpbiB0aGUgc2FtZSB3YXkuIEhpZ2ggaW5jb21lIHBlb3BsZSBhcmUgbW9yZSBsaWtlbHkgdG8gc3BlbmQgbW9yZSBvbiBoZWFsdGggY2FyZSBhbmQgYXJlIG1vcmUgbGlrZWx5IHRvIGFjY2VzcyBzcGVjaWFsaXN0cy4gTWVkaWFuIGluY29tZSBkYXRhIGFsc28gY2FuIGFsc28gZXhwbGFpbiB3aGVyZSBjaXRpemVucyBoYXZlIG1vcmUgbGVpc3VyZSB0aW1lIHRvIGNvbnRyYWN0IGx5bWUuIFdoaWxlIG91ciB1c2VycyBzaG91bGQgbm90IG1ha2UgYW55IGZpcm0gZGVjaXNpb25zIGZyb20gdGhlc2UgZGF0YSwgaXQgaXMgaGlnaGx5IHVzZWZ1bCB0byBleGFtaW5lIGluIHRhbmRlbSB3aXRoIG91ciBvdGhlciBpbmRpY2F0b3JzIHRvIHNlZSBvdmVybGFwcGluZyBwb2ludHMgb2YgaW50ZXJlc3QsIGFuZCB0byBnaXZlIG1vcmUgY29udGV4dCB0byBhcmVhcyB0aGF0IG1heSBuZWVkIG1vcmUgYXR0ZW50aW9uIG9uIHRoZSBwcmltYXJ5IGhlYWx0aGNhcmUgY2VudGVyIHNpZGUuICAKCk91ciBuZXh0IGxheWVyIGZpbHRlcnMgYnkgdGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIHBlb3BsZSBpbiBhIGNvdW50eSB3aG8gYXJlIG92ZXIgNjUgeWVhcnMgb2YgYWdlLiBIZXJlLCBvdXIgZ29hbCBpcyB0byBkcmF3IGF0dGVudGlvbiB0byB0aGUgcm9sZSB0aGF0IGFnZSBtYXkgcGxheSBpbiBjb250cmFjdGluZyBseW1lIGFuZCBvdGhlciB0aWNrLWJvcm5lIGRpc2Vhc2VzLiBTZW5pb3IgY2l0aXplbnMgbWF5IGJlIHN1c2NlcHRpYmxlIHRvIHdlYWtlciBpbW11bmUgc3lzdGVtcyAoYmVjb21pbmcgbW9yZSBsaWtlbHkgdG8gYmUgYWZmZWN0ZWQgbW9yZSBoZWF2aWx5IGJ5IGJpdGVzKSBhbmQgYXJlIG1vcmUgbGlrZWx5IHRvIGJlIHJldGlyZWQsIHRodXMgaGF2aW5nIG1vcmUgbGVpc3VyZSB0aW1lIG91dGRvb3JzIHRvIGNvbnRyYWN0IGx5bWUuIFN5bXB0b21zIGZvciB0aWNrIGJvcm5lIGRpc2Vhc2VzIGFyZSBtb3JlIHNlcmlvdXMgZm9yIHNlbmlvcnMgYW5kIG1heSBwcmVzZW50IGRpZmZlcmVudGx5LCBzbyBpdCBpcyBpbXBvcnRhbnQgdGhhdCB0aGV5IGhhdmUgYWNjZXNzIHRvIGhlYWx0aCBjYXJlIHRvIHRyZWF0IHRoZSBkaXNlYXNlIGFzIHNvb24gYXMgcG9zc2libGUuIFRoZSByZXN1bHRzIGhlcmUgYXJlIHBhcnRpY3VsYXJseSB1c2VmdWwgaW4gdGFuZGVtIHdpdGggdGhlIGNvbnNlcnZhdGlvbiBsYW5kcyBkYXRhLiAgCgpJbiBjb25zaWRlcmF0aW9uIG9mIGx5bWUgZGlzZWFzZSwgaXQgaXMgaW50dWl0aXZlIHRvIHRoaW5rIGFib3V0IHRpY2sgbG9jYXRpb24gYXMgdGhlIHByaW1hcnkgaW5kaWNhdG9yIGZvciBseW1lLCBhcyB3ZSBkaWQgYmVmb3JlIGZ1cnRoZXIgY29udmVyc2F0aW9ucyB3aXRoIG91ciBjb21tdW5pdHkgcGFydG5lci4gVGhlIGNvbnNlcnZhdGlvbiBsYW5kIGZpbHRlciBhbGxvd3MgZm9yIG1vcmUgY29udGV4dCBhYm91dCB3aGVyZSB0aWNrIGhhYml0YXRzIGV4aXN0IHNpbmNlIGNvbnNlcnZlZCBsYW5kcyB0ZW5kIHRvIGJlIG1vcmUgd29vZGVkIHdpdGggdGFsbCBncmFzcy4gQXMgd2UgYXJlIGF3YXJlLCBwZW9wbGUgYXJlIG1vc3QgbGlrZWx5IHRvIGNvbnRyYWN0IGJpdGVzIG9uIHRoZWlyIHByb3BlcnR5LCBpbiB0aGVpciBiYWNreWFyZHMuIEhvd2V2ZXIsIGluIG1hbnkgcGxhY2VzIGluIE1haW5lLCBjb25zZXJ2ZWQgbGFuZHMgYmFjayB1cCBvbnRvIHBlb3BsZeKAmXMgYmFja3lhcmRzIG9yIHJlYWxseSBzZXJ2ZSBhcyB0aGVtLiBBZGRpdGlvbmFsbHksIGFyZWFzIHdpdGggbGVzcyBjb25zZXJ2ZWQgbGFuZCBjb3VsZCBkZXNpZ25hdGUgdXJiYW4gc3BhY2VzIHdoZXJlIGluY2lkZW5jZSBvZiBpbmRpdmlkdWFscyBjb250cmFjdGluZyBseW1lIGluIHRoZWlyIGJhY2t5YXJkcyBpcyBwcmVzdW1lZCB0byBiZSBtdWNoIGxvd2VyLiBBcyBzdWNoLCB3ZSBkZXRlcm1pbmVkIHRoYXQgaXQgd291bGQgc3RpbGwgYmUgYmVuZWZpY2lhbCB0byBpbmNsdWRlIHRoZSBtYXAgbGF5ZXIuIFRoaXMgZmlsdGVyIHNoZWRzIGxpZ2h0IG9uIHRoZSBwcmV2YWxlbmNlIG9mIHRpY2tzIGluIGNlcnRhaW4gdG93bnMsIGFuZCBob3cgdGhhdCBtYXkgcGxheSBpbnRvIHRpY2stYm9ybmUgZGlzZWFzZSBhbmFseXNpcy4gRXNwZWNpYWxseSBpZiB0aGlzIGlzIGFuIGFyZWEgd2l0aCBmZXcgcmVwb3J0ZWQgdGlja3MgYnV0IGhpZ2ggcHJvcG9ydGlvbnMgb2YgY29uc2VydmVkIGxhbmQuICAKCk91ciBmaW5hbCB0b2dnbGVhYmxlIGxheWVyIHRvIG91ciBtYXAgaXMgYSBsYXllciBvZiBmZWRlcmFsbHkgcmVjb2duaXplZCBoZWFsdGggY2FyZSBjZW50ZXJzIGluIE1haW5lLiBUaGlzIGxheWVyIHdhcyBhZGRlZCBib3RoIGFzIGEgcmVzb3VyY2UgdG8gY2l0aXplbnMgaW4gTWFpbmUgYW5kIHJlc2VhcmNoZXJzL3NjaWVudGlzdHMgYXQgTWFpbmUgTWVkaWNhbCBDZW50ZXIuIFRoaXMgZmVhdHVyZSBhbGxvd3MgdXNlcnMgdG8gc2VlIGhlYWx0aGNhcmUgcHJvdmlkZXJzIGluIGNsb3NlIHByb3hpbWl0eSB0byB0aGVtLiBGb3IgY2l0aXplbnMsIGl0IG1heSBoZWxwIHRoZW0gdG8gZmlndXJlIG91dCB3aGVyZSB0aGV5IHNob3VsZCBpbW1lZGlhdGVseSBnbyBpZiB0aGV5IHdlcmUgYml0dGVuIGJ5IGEgdGljaywgYW5kIGZvciByZXNlYXJjaGVycyBpdCBtYXkgaGVscCB0byBiZSBhYmxlIHRvIGlzb2xhdGUgYmxhbmsgc3BvdHMgaW4gaGVhbHRoY2FyZSBjb3ZlcmFnZSwgb3IgYXJlYXMgd2hlcmUgaGVhbHRoY2FyZSBjb3ZlcmFnZSBkb2VzbuKAmXQgbWF0Y2ggdXAgd2l0aCB0aGUgcmVwb3J0ZWQgbnVtYmVyIG9mIGNhc2VzIGluIGEgY2VydGFpbiByZWdpb24uIFRoaXMgZmluYWwgbGF5ZXIgaGVscHMgdG8gYnJpZGdlIHRoZSBnYXAgYmV0d2VlbiBjYXNlIGluY2lkZW5jZSBhbmQgcHJpbWFyeSBoZWFsdGhjYXJlIGVkdWNhdGlvbiwgZXNzZW50aWFsbHkgYWxsb3dpbmcgcmVzZWFyY2hlcnMgdG8gZHJhdyBjb25uZWN0aW9ucyBiZXR3ZWVuIHRpY2sgaW5jaWRlbmNlIGFuZCB0aGUgYWN0aW9ucyB0aGF0IE1haW5lIE1lZGljYWwgc2hvdWxkIHRha2Ugd2hlbiBjb25zaWRlcmluZyB0aWNrLWJvcm5lIGRpc2Vhc2UgdHJhaW5pbmcgaW1wbGVtZW50YXRpb24gbG9jYXRpb25zIGFuZCB0byBpZGVudGlmeSBoZWFsdGggY2VudGVycyBpbiBhcmVhcyBvZiBkaXN0cmVzcy4gIAoKR2l2ZW4gdGhlIG5hdHVyZSBvZiBvdXIgcmVzdWx0aW5nIHdvcmssIGEgbG90IG9mIHRoZSBkZWNpc2lvbiBvZiB3aGF0IHRvIGluY2x1ZGUgaW4gb3VyIGxheWVycyBvZiB0aGUgYmFzZSB0aWNrLWluY2lkZW5jZSBtYXAgY2FtZSBmcm9tIGRpc2N1c3Npb24gd2l0aCBwcm9qZWN0IHBhcnRuZXJzLCBkcmF3aW5nIG9uIHRoZWlyIGtub3dsZWRnZSBiYXNlIGFuZCBvdXIgb3duIHBlcnNvbmFsIGV4cGVyaWVuY2Ugd2l0aCB0aWNrcyBpbiBNYWluZSB0byBkZXRlcm1pbmUgdGhlIGJlc3QgcGF0aCBmb3J3YXJkcyBpbiB0ZXJtcyBvZiB3aGF0IGRhdGEgdG8gY29sbGVjdC4gT3VyIGZpbmFsIGxpc3Qgb2Ygd2hhdCB0byBpbmNsdWRlIGluIHRoZSBtYXAgd2FzIGJhc2VkIG9uIG11dHVhbCBkaXNjdXNzaW9uIGFuZCBjb2xsYWJvcmF0aW9uLiBPdXIgc291cmNlcyBjb21lIGZyb20gd2lkZWx5IHJlY29nbml6YWJsZSBhbmQgYXZhaWxhYmxlIHNvdXJjZXMsIGluY2x1ZGluZyBVUyBjZW5zdXMgZGF0YSAoaW5jb21lLCBhZ2UpIGFuZCBnb29nbGUgc2NyYXBlcy9mZWRlcmFsIHJlY29yZHMgKGhlYWx0aCBjZW50ZXJzKS4gVGhpcyBpcyBhbHNvIHdoeSBvdXIgcmVzdWx0cyBhcmUgbm90IHRvIGJlIHRha2VuIGFzIHN0YXRpc3RpY2FsbHktc291bmQgZmFjdHMgdG8gbWFrZSBkZWNpc2lvbnMgb2ZmIG9mLCBidXQgcmF0aGVyIGFzIGdlbmVyYWxpemFibGUgdHJlbmRzIHRvIHRha2UgaW50byBhY2NvdW50IHdoZW4gYXR0ZW1wdGluZyB0byBtYWtlIGRlY2lzaW9ucyBvZiB0aWNrLWJvcm5lIGRpc2Vhc2UgZWR1Y2F0aW9uLiAgCgojIFJlY29tZW5kYXRpb25zIGFuZCBOZXh0IFN0ZXBzCiAgQmVjYXVzZSB3ZSB3ZXJlIGxpbWl0ZWQgaW4gdGltZSwgdGhlcmUgYXJlIGEgbnVtYmVyIG9mIGZ1dHVyZSBkaXJlY3Rpb25zIHRoYXQgY291bGQgaW1wcm92ZSB0aGUgZWZmaWNhY3kgb2YgdGhpcyB0b29sLiBUaGUgZmlyc3QgbGltaXRpbmcgaXNzdWUgZm9yIHVzIHdhcyBhY2N1cmFjeSBhbmQgcmVsZXZhbmN5IG9mIG91ciBoZWFsdGhjYXJlIGNlbnRlciBkYXRhLiBJbiBtYWtpbmcgdGhlIGRlY2lzaW9uIHRvIHdvcmsgd2l0aCBkYXRhIGRpc2NvdmVyZWQgZnJvbSBhIGdvb2dsZSBtYXBzIHNjcmFwZSBvZiBoZWFsdGhjYXJlIHByb3ZpZGVycyB2ZXJzdXMgZmVkZXJhbGx5IHJlY29nbml6ZWQgY2VudGVycyB3ZSBoYWQgdG8gd2VpZ2ggdGhlIGltcG9ydGFuY2Ugb2YgZGF0YSBjb21wbGV0ZW5lc3MgKGZpbmRpbmcgZXZlcnkgbG9jYXRpb24gdGhhdCBjb3VsZCB3b3JrIHdpdGggbHltZSwgZXZlbiBpZiBub3QgZmVkZXJhbGx5IHJlY29nbml6ZWQpIGFuZCBkYXRhIHJlbGlhYmlsaXR5ICh3aGV0aGVyIHRoZSBoZWFsdGhjYXJlIGNlbnRlcnMgZm91bmQgd2VyZSBhY3R1YWxseSBhZGVxdWF0ZSBmb3IgcHJvdmlkaW5nIHRyZWF0bWVudCkuIFdlIGtub3cgdGhhdCBhIG1vcmUgcmVsaWFibGUgYXJyYW5nZW1lbnQgb2YgY2VudGVycyBpcyBiZWluZyBkZXZlbG9wZWQgZm9yIHVzZSwgdGhpcyBkYXRhIGNhbiBlYXNpbHkgYmUgYWRkZWQgdG8gb3VyIHNjcmlwdCBpbiBwbGFjZSBvZiB0aGUgZmVkZXJhbGx5IHJlY29nbml6ZWQgY2VudGVycyB0aGF0IHdlIGNob3NlIHRvIHBsb3QuIE9uY2UgdGhhdCBkYXRhIGlzIGNsZWFuZWQgYW5kIGFkZGVkIHRvIHRoZSBjb2RlLCBpdCB3aWxsIHJlcGxhY2UgdGhhdCBtYXAgbGF5ZXIuICAKICAKICBJbiB0aGF0IHNhbWUgdmVpbiwgYSBjb25zaWRlcmF0aW9uIG9mIG91cnMgd2hpbGUgbWFwcGluZyB0aGUgY2VudGVycyBpbnZvbHZlZCB0aGUgcmVsZXZhbmN5IG9mIGEgbnVtYmVyIG9mIHRoZSBzaXRlcyBpbiB0ZXJtcyBvZiB3aGV0aGVyIG9yIG5vdCB0aGV5IHdlcmUgd2VsbCBlcXVpcHBlZCB0byBkaWFnbm9zZSBhbmQgdHJlYXQgbHltZSBkaXNlYXNlLiBJbiBvdXIgcmVzZWFyY2ggYW5kIGNvbnZlcnNhdGlvbnMgd2l0aCBjb21tdW5pdHkgcGFydG5lcnMgd2UgZGV0ZXJtaW5lZCB0aGF0IHNvbWUgc2l0ZXMgYXJlIG1vcmUg4oCcbHltZSBsaXRlcmF0ZeKAnSB0aGFuIG90aGVycywgbWVhbmluZyB0aGF0IHRob3NlIGRvY3RvcnMgbWF5IG1vcmUgZnJlcXVlbnRseSBzZWUgYW5kIHRyZWF0IGx5bWUsIG9yIGhhdmUgYmVlbiBtb3JlIHJlY2VudGx5IGVkdWNhdGVkIGFib3V0IGRpYWdub3NpcyBhbmQgdHJlYXRtZW50LiBXaGlsZSB1cmdlbnQgY2FyZSBzaXRlcyBhbmQgZW1lcmdlbmN5IHJvb21zIGNhbiBsaXN0IG9uIHRoZWlyIHdlYnNpdGVzIHRoYXQgdGhleSBhcmUgZXF1aXBwZWQgdG8gdHJlYXQgbHltZSwgd2UgZG9u4oCZdCBoYXZlIGFuIHVuZGVyc3RhbmRpbmcgb2Ygd2hldGhlciB0aGF0IGluZm9ybWF0aW9uIGlzIHJlbGlhYmxlIGJhc2VkIHVwb24gdGhlaXIgdHJ1ZSBleHBlcmllbmNlIHdpdGggaXQuIEZ1cnRoZXIsIHdlIGRpZG7igJl0IGJlbGlldmUgdGhhdCB3ZSB3ZXJlIHdlbGwgZXF1aXBwZWQgdG8gbWFrZSB0aG9zZSBkZXRlcm1pbmF0aW9ucyBiZWNhdXNlIG9mIG91ciBsYWNrIG9mIGRhdGEgYW5kIHVuZGVyc3RhbmRpbmcgYWJvdXQgbHltZSBlZHVjYXRpb25hbCBjYW1wYWlnbnMgYWNyb3NzIHRoZSBzdGF0ZS4gSWYgdGhlIFZlY3Rvci1Cb3JuZSBEaXNlYXNlIExhYiB3ZXJlIGFibGUgdG8gc3VydmV5IGRvY3RvcnMgYWJvdXQgaG93IGZyZXF1ZW50bHkgdGhleSBkaWFnbm9zZSBhbmQgYXJlIGVkdWNhdGVkIGFib3V0IGx5bWUsIG9yIHVzZSBvdGhlciBzb3VyY2VzIG9mIHNpbWlsYXIgZGF0YSB0byBldmFsdWF0ZSBoZWFsdGhjYXJlIHNpdGVzIGJhc2VkIHVwb24gbHltZSBsaXRlcmFjeSwgdGhvc2UgY2hhcmFjdGVyaXN0aWNzIGNvdWxkIGJlIGFkZGVkIHRvIHRoZSBtYXAuIEJlaW5nIG1vcmUgc3BlY2lmaWMgYWJvdXQgaG93IGNvbXBldGVudGx5IGhlYWx0aGNhcmUgc2l0ZXMgY291bGQgaWRlbnRpZnkgYW5kIHRyZWF0IHRoZSBkaXNlYXNlIHdvdWxkIG1ha2UgdGhlIG1hcCBtb3JlIGVmZmVjdGl2ZSBiZWNhdXNlIGl0IHdvdWxkIGNvbnRyb2wgZm9yIGx5bWUgaG90c3BvdHMgZHVlIHRvIHByb3ZpZGVyIHJlbGlhYmlsaXR5IGFuZCBlbXBoYXNpemUgYXJlYXMgd2hlcmUgdGhlIGRpc2Vhc2UgbWF5IGJlIGdvaW5nIHVuZGVyZGlhZ25vc2VkIGJlY2F1c2Ugb2YgYSBkZWZpY2llbmN5IG9uIHRoZSBwcm92aWRlciBzaWRlLiBGdXJ0aGVyLCBzaXRlcyB3aGVyZSBpbmRpdmlkdWFscyBhcmUgdW5saWtlbHkgdG8gZ28gZm9yIGx5bWUgZGlzZWFzZSBzeW1wdG9tcyBiZWNhdXNlIG9mIGEgbGFjayBvZiB0cmFpbmluZyBvciB0ZXN0aW5nIGNhcGFiaWxpdHkgY291bGQgYmUgZWxpbWluYXRlZCBmcm9tIHRoZSBzZXQuICAKICAKICBUaGUgYXJlYSB3aXRoIHRoZSBncmVhdGVzdCBvcHBvcnR1bml0eSBmb3IgZGV2ZWxvcG1lbnQgYXMgd2UgY29uY2x1ZGUgdGhlIHByb2plY3QgaXMgdGhlIG1hcCBsYXllcnMuIFRoZSBiZWF1dHkgb2YgdXNpbmcgaW50ZXJhY3RpdmUgc29mdHdhcmUgdG8gc2hvdyB0cmVuZHMgaXMgdGhhdCB0aGVyZSBhcmUgaW5maW5pdGUgcG9zc2liaWxpdGllcyBhYm91dCB3aGF0IGRhdGEgY2FuIGJlIGFkZGVkLiBOb3cgdGhhdCB0aGUgYmFzZWxpbmUgY29kZSBwcm9jZXNzIGhhcyBiZWVuIHNldCB1cCwgaXQgd2lsbCBiZSBzaW1wbGUgdG8gY2xlYW4gbmV3IGluZm9ybWF0aW9uIHVzaW5nIHRoZSBmb3JtYXQgdGhhdCB3ZeKAmXZlIGlkZW50aWZpZWQgYW5kIGNyZWF0ZSBmcmVzaCBsYXllcnMuIEEgcm9hZGJsb2NrIGZvciB1cyB3YXMgdGhlIGF2YWlsYWJpbGl0eSBvZiByZWxldmFudCBkYXRhLiBBbHRob3VnaCB3ZSBoYWQgYSBudW1iZXIgb2YgaWRlYXMgYWJvdXQgdmFyaW91cyBpbXBvcnRhbnQgZmFjdG9ycyByZWxhdGVkIHRvIGNvbnRyYWN0aW5nIGx5bWUgZGlzZWFzZSwgdGhlcmUgc2ltcGx5IHdhcyBub3QgZXhpc3RpbmcgZGF0YSBkaXZpZGVkIGJ5IE1haW5lIGNvdW50eSBvciB0b3duLiBXZSB0aG91Z2h0IHRoYXQgc29tZSBpbnRlcmVzdGluZyBsYXllcnMgb2YgaW5mb3JtYXRpb24gY291bGQgaW52b2x2ZSBoZWFsdGggaW5zdXJhbmNlIGFjY2Vzcywgb3V0ZG9vciByZWNyZWF0aW9uYWwgYWN0aXZpdHkgcGFydGljaXBhdGlvbiwgYW5kIGxvY2F0aW9ucyBvZiBseW1lIGRpc2Vhc2UgZWR1Y2F0aW9uYWwgY2FtcGFpZ25zLiAgCiAgCiAgQmVjYXVzZSBvdXIgbGVhZmxldCBpcyBtZWFudCB0byBhY3QgYXMgYSB0b29sIGZvciByZXNlYXJjaGVycywgbmV4dCBzdGVwcyBpbnZvbHZlIHVzaW5nIHRoZSBpbmZvcm1hdGlvbiBnYXRoZXJlZCBmcm9tIGl0IHRvIGRldGVybWluZSB3aGljaCBob3NwaXRhbHMgcmVxdWlyZSBmdXJ0aGVyIGx5bWUgZGlzZWFzZSB0cmFpbmluZy4gRXZhbHVhdGluZyB0aGUgZmFjdG9ycyBsaXN0ZWQgaW4gY29udHJhc3QgdG8gdGhlIGJhc2VsaW5lIGx5bWUgY2FzZSByYXRlcyBhbGxvd3MgdXMgdG8gaW5mb3JtIG91ciBjdXJyZW50bHktbGlzdGVkIGhlYWx0aCBjZW50ZXJzIHRoYXQgdGhleSBhcmUgcG9zc2libHkgdW5kZXJkaWFnbm9zaW5nLiAKCgojIFJlZmVyZW5jZXMKQXJ0aWdhLCBTLiwgT3JnZXJhLCBLLiwgJiBQaGFtLCBPLiAoMjAyMCkuIERpc3Bhcml0aWVzIGluIGhlYWx0aCBhbmQgaGVhbHRoIGNhcmU6IEZpdmUga2V5IHF1ZXN0aW9ucyBhbmQgYW5zd2Vycy4gS2Fpc2VyIEZhbWlseSBGb3VuZGF0aW9uLgoKQmlzYW56aW8sIEQuLCBGZXJuw6FuZGV6LCBNLiBQLiwgTWFydGVsbG8sIEUuLCBSZWl0aGluZ2VyLCBSLiwgJiBEaXVrLVdhc3NlciwgTS4gQS4gKDIwMjApLiBDdXJyZW50IGFuZCBmdXR1cmUgc3BhdGlvdGVtcG9yYWwgcGF0dGVybnMgb2YgTHltZSBkaXNlYXNlIHJlcG9ydGluZyBpbiB0aGUgTm9ydGhlYXN0ZXJuIFVuaXRlZCBTdGF0ZXMuIEpBTUEgbmV0d29yayBvcGVuLCAzKDMpLCBlMjAwMzE5LWUyMDAzMTkuCgpEaWNrbWFuLCBTLiBMLiwgV29vbGhhbmRsZXIsIFMuLCBCb3IsIEouLCBNY0Nvcm1pY2ssIEQuLCBCb3IsIEQuIEguLCAmIEhpbW1lbHN0ZWluLCBELiBVLiAoMjAxNikuIEhlYWx0aCBzcGVuZGluZyBmb3IgbG93LSwgbWlkZGxlLSwgYW5kIGhpZ2gtaW5jb21lIEFtZXJpY2FucywgMTk2M+KAkzIwMTIuIEhlYWx0aCBBZmZhaXJzLCAzNSg3KSwgMTE4OS0xMTk2LgoKRWlzZW4sIFIuIEouLCBQaWVzbWFuLCBKLiwgWmllbGluc2tpLUd1dGllcnJleiwgRS4sICYgRWlzZW4sIEwuICgyMDEyKS4gV2hhdCBkbyB3ZSBuZWVkIHRvIGtub3cgYWJvdXQgZGlzZWFzZSBlY29sb2d5IHRvIHByZXZlbnQgTHltZSBkaXNlYXNlIGluIHRoZSBub3J0aGVhc3Rlcm4gVW5pdGVkIFN0YXRlcz8uIEpvdXJuYWwgb2YgbWVkaWNhbCBlbnRvbW9sb2d5LCA0OSgxKSwgMTEtMjIuCgpFbGlhcywgUy4gUC4sIE1hYXNjaCwgSy4gQS4sIEFuZGVyc29uLCBOLiBULiwgUmFuZCwgUC4gVy4sIExhY29tYmUsIEUuIEguLCBSb2JpY2gsIFIuIE0uLCAuLi4gJiBTbWl0aCBKciwgUi4gUC4gKDIwMjApLiBEZWNvdXBsaW5nIG9mIGJsYWNrbGVnZ2VkIHRpY2sgYWJ1bmRhbmNlIGFuZCBMeW1lIGRpc2Vhc2UgaW5jaWRlbmNlIGluIFNvdXRoZXJuIE1haW5lLCBVU0EuIEpvdXJuYWwgb2YgbWVkaWNhbCBlbnRvbW9sb2d5LCA1NygzKSwgNzU1LTc2NS4KCkhlcnJpbmd0b24gSnIsIEouIEUuLCBDYW1wYmVsbCwgRy4gTC4sIEJhaWxleSwgUi4gRS4sIENhcnR0ZXIsIE0uIEwuLCBBZGFtcywgTS4sIEZyYXppZXIsIEUuIEwuLCAuLi4gJiBHZW5zaGVpbWVyLCBLLiBGLiAoMTk5NykuIFByZWRpc3Bvc2luZyBmYWN0b3JzIGZvciBpbmRpdmlkdWFscycgTHltZSBkaXNlYXNlIHByZXZlbnRpb24gcHJhY3RpY2VzOiBDb25uZWN0aWN1dCwgTWFpbmUsIGFuZCBNb250YW5hLiBBbWVyaWNhbiBqb3VybmFsIG9mIHB1YmxpYyBoZWFsdGgsIDg3KDEyKSwgMjAzNS0yMDM4LgoKTGFjb3V0LCBBLiwgRWwgSGFqamFtLCBNLiwgTWFyY3ksIFAuIFkuLCAmIFBlcnJvbm5lLCBDLiAoMjAxOCkuIFRoZSBwZXJzaXN0ZW50IEx5bWUgZGlzZWFzZTrigJxUcnVlIGNocm9uaWMgTHltZSBkaXNlYXNl4oCdIHJhdGhlciB0aGFuIOKAnHBvc3QtdHJlYXRtZW50IEx5bWUgZGlzZWFzZSBzeW5kcm9tZeKAnS4gSm91cm5hbCBvZiBHbG9iYWwgSW5mZWN0aW91cyBEaXNlYXNlcywgMTAoMyksIDE3MC4KCk1haW5lIENlbnRlciBmb3IgRGlzZWFzZSBDb250cm9sIGFuZCBQcmV2ZW50aW9uLCBNYWluZSBUcmFja2luZyBOZXR3b3JrLiBUaWNrLVJlbGF0ZWQ6IE5lYXIgcmVhbC10aW1lIGRhdGEuIFJldHJpZXZlZCBmcm9tIGh0dHBzOi8vZGF0YS5tYWluZXB1YmxpY2hlYWx0aC5nb3YvdHJhY2tpbmcvLgoKU21pdGggSnIsIFIuIFAuLCBSYW5kLCBQLiBXLiwgJiBMYWNvbWJlLCBFLiBILiAoMTk5MCkuIFBvdGVudGlhbCBmb3IgTHltZSBkaXNlYXNlIGluIE1haW5lOiBkZWVyIHN1cnZleSBvZiBkaXN0cmlidXRpb24gb2YgSXhvZGVzIGRhbW1pbmksIHRoZSB0aWNrIHZlY3Rvci4gQW1lcmljYW4gam91cm5hbCBvZiBwdWJsaWMgaGVhbHRoLCA4MCgzKSwgMzMzLTMzNQoKU3RhdGUgb2YgTWFpbmUsIEdlb2xpYnJhcnkgRGF0YSBDYXRhbG9nLiBNYWluZSBUb3duIGFuZCBUb3duc2hpcHMgQm91bmRhcnkgUG9seWdvbnMgKDIwMjIpIFtEYXRhIGZpbGVdLiBSZXRyaWV2ZWQgZnJvbSBodHRwczovL3d3dy5tYWluZS5nb3YvZ2VvbGliL2NhdGFsb2cuaHRtbCNib3VuZGFyaWVzLiAKClZhbiBEb29yc2xhZXIsIEUuLCBNYXNzZXJpYSwgQy4sICYgS29vbG1hbiwgWC4gKDIwMDYpLiBJbmVxdWFsaXRpZXMgaW4gYWNjZXNzIHRvIG1lZGljYWwgY2FyZSBieSBpbmNvbWUgaW4gZGV2ZWxvcGVkIGNvdW50cmllcy4gQ21haiwgMTc0KDIpLCAxNzctMTgzLgoKVS5TLiBDZW5zdXMgQnVyZWF1IDIwMjIuIFNFTEVDVEVEIENIQVJBQ1RFUklTVElDUyBPRiBUSEUgTkFUSVZFIEFORCBGT1JFSUdOIEJPUk4gUE9QVUxBVElPTlMuIFJldHJpZXZlZCBmcm9tIGh0dHBzOi8vZGF0YS5jZW5zdXMuZ292L2NlZHNjaS8uIAoK