Executive Summary
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.
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.
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.
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.
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.
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.
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.
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")
)
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.
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.
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.
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