Introduction
Aligning scientific supply with policy demand in order to develop
evidence-based policy is considered a gold standard by many accounts.
The Biden Administration recently reaffirmed that ‘It is the policy of
[the Biden] Administration to make evidence-based decisions guided by
the best available science and data… Scientific findings should never be
distorted or influenced by political considerations’ (Biden, 2021). This
sentiment has been echoed by the calls for use-inspired basic research
to deliver innovative solutions in service of social and environmental
goals (Stokes 2011; Fuglie & Toole 2014).
However, there is broad recognition that promoting evidence-based
policymaking at face value overlooks challenges related to knowledge
politics and the selective use of science. Namely, policymakers’
emphasis on science as a neutral arbiter masks the politics of
generating and communicating scientific knowledge (Sarewitz 2000).
Science is not value-free, but rather, supply and demand of science are
politically linked (Sarewitz & Pielke 2007). As such, research to
support evidence-based policymaking requires intentional engagement by
scientists to not only reduce uncertainty through high-quality research,
but also reduce ambiguity through strategic communication and problem
framing (Cairney 2016). Emphasis on communication is echoed by
literature on boundary spanners that can broker between the scientific
and policy communities (Guston 2001).
Recognizing the complex interplay of science and policymaking, what
methods can we use to better understand these dynamics? Through surveys
and interviews of public servants, studies find wide variation in how
policymakers interact with scientific information (Newman et al. 2016),
and highlight that internal governmental reports and personal networks
are among the most popular sources of information (Piczak et al. 2022).
These findings have been supported and detailed through a handful of
bibliometric analyses of policy documents. Desmaris and Herd (2014)
evaluated 102 Regulatory Impact Assessments, confirming that the
majority of citations are to governmental agencies. They also describe
the prevalence of disciplines like economics, environmental science, and
public health from high-impact journals across 1,378 scholarly
citations. Koontz (2022) finds similar trends when analyzing 12 salmon
recovery plans, categorizing 1,104 references from various sources
(academic, governmental, organizational, etc.) and expanding on how
science is used to support causal arguments.
The insights from bibliometric analyses of policy documents lay an
important foundation for systematically quantifying the evidence used to
support policy. However, manually extracting and indexing references can
be a tedious task. Unlike ‘science of science’ research, where
bibliometric methods are made easier through publishing norms of
citations and indexing (e.g. DOIs, ORCIDs, etc.), science of policy
research is less systematic. Policy documents do not always follow
consistent formatting or citation norms, and references outside of
non-scholarly articles (which are the majority of references) are not
systematically indexed. However, developments in computational tools for
reading and analyzing large texts create an opportunity for automating
some of the more tedious phases of bibliometry on policy documents. This
paper presents a set of tools for aiding bibliometric analysis of policy
documents, govscienceuseR, which we hope will support
policy process researchers in quantifying and unpacking the complex
interplay of science and policymaking.
Method
The govscienceuseR tools provide a computational
approach for indexing and summarizing references from policy documents.
This is a vignette walking through the steps of the R packages in the
govscienceuseR tool set: referenceExtract,
referenceClassify, indexBuild, and
referenceSearch. Together, these four packages allow
researchers to go from PDF documents to a data frame of indexed
citations in only a handful of steps in the R coding language (steps
mapped below). The goal of these tools is to allow researchers working
with various types of policy documents to analyze citations using a
systematic and reproducible approach.

Case: Groundwater Sustainability Plans
California’s Sustainable Groundwater Management Act (SGMA) of 2014
sets out a framework for local Groundwater Sustainability Agencies
(‘Agencies’) to work towards sustainable management of their groundwater
basins. Agencies are required to outline their strategies in Groundwater
Sustainability Plans (GSPs) – documents reviewed by the Department of
Water Resources (DWR) to ensure that Agency strategies comply with SGMA,
the GSP regulations, and achieve groundwater sustainability for the
basin (DWR no date). Among the criteria for plan evaluation, the
California Code specifies: “When evaluating whether a Plan is likely to
achieve the sustainability goal for the basin, the Department shall
consider… Whether the assumptions, criteria, findings, and objectives,
including the sustainability goal… are reasonable and supported by the
best available information and best available science” (23 CCR §
355.4).
There is a clear mandate that GSP documents use scientific evidence
to support their strategies for groundwater sustainability, but defining
and measuring sustainability is no simple feat (Kuhlman & Farrington
2010). DWR sets out six sustainability indicators, whereby the
occurrence of any indicator would be an undesirable result: lowering
groundwater levels, reduction of storage, seawater intrusion, degraded
quality, land subsidence, and surface water depletion. However, each
local Agency is responsible for setting measurable objectives and
minimum thresholds for these indicators by considering all ‘beneficial
users and uses’ for their basin (Austin, 2019). Beneficial uses include
‘domestic, municipal, agricultural, and industrial supply; power
generation; recreation; aesthetic enjoyment; navigation; and
preservation and enhancement of fish, wildlife, and other aquatic
resources or preserves’ (California Water Plan glossary 2018).
Facing the challenge of managing groundwater resources across a wide
array of users and interests, we ask: How is science used to
inform the multiple dimensions of groundwater sustainability?
Analyses of the SGMA collaborative process and GSP drafts have already
shown that achieving groundwater sustainability while supporting
all beneficial uses is unlikely. Minimum thresholds analyzed in
draft plans found that some beneficial uses are preferenced over others,
with stakeholders like domestic well users potentially going without
water (Bostic et al. 2020). To build on this existing research, we turn
to the scientific evidence used in GSPs to tell us about how agencies
are defining sustainability. We trial the govscienceuseR
tool kit on 114 GSPs, described more in the data section below.
Getting started
Installations
To begin, download all four packages from the govscienceuseR GitHub
page:
devtools::install_github("govscienceuseR/referenceExtract")
devtools::install_github("govscienceuseR/referenceClassify")
devtools::install_github("govscienceuseR/indexBuild")
devtools::install_github("govscienceuseR/referenceSearch")
Then load these and dependent packages into library. You may be
prompted to install some of the dependent packages if you do not already
have them, such as keras.
library(referenceExtract)
library(referenceClassify)
library(indexBuild)
library(referenceSearch)
packs <- c('data.table', 'dplyr', 'stringr', 'keras', 'tensorflow',
'tidyr', 'purrr', 'sjrdata')
if(!'sjrdata' %in% installed.packages()[,'Package']){
pak::pak('ikashnitsky/sjrdata')
}
sapply(packs, require, character.only = T)
Outside of R, the referenceSearch package also requires
installation and running of Solr.
This software should be downloaded to a known location on your
computer.
Data
The documents of interest for this paper are California’s Groundwater
Sustainability Plans. These documents are available publicly to download
from a Box
folder we host. To follow along with this tutorial, download the files
to a file that will be considered your document directory. Our document
directory is specified below. Here we are working with 114 plans which
total over 160,000 pages, published between 2019-2022.
doc_directory <- "~/Box/reference_classifier/reference_classifier/documents_gsp/"
2. referenceClassify
The referenceClassify package is designed to take a data
frame of tabular, tagged citation data (author, year, container,
publisher, doi, etc), look for exact matches between those tags and
various high-level indices (mainly journal and agency names), and begin
to classify probable citations into these high-level categories. These
indices are 1) an index of academic journals from the sjr
package relying on the Scimago
database, 2) an index of academic conference papers/proceedings also
from the Scimago database, 3) and an index of US state and federal
agencies, curated by the package authors. All three of these indices are
built into this package and can be accessed with
data('scimago.j') for journals,
data('scimago.c') for conferences, and
data('agencies') for agencies.
prepared_by() and journal_disambig()
Before classifying our probable references, we can further clean and
refine these potential citations with the prepared_by()
function, which removes commonly-seen lead-ins to references (‘prepared
for/by’, etc.) to improve exact matching.
dt <- prepared_by(dt, x = 'container', y = 'author', z = 'publisher')
Additionally, we disambiguate the journals with the
journal_disambig() function, which references indices of
common journal abbreviations and through manual cleaning of journals
referenced in transportation documents.
dt$container <- journal_disambig(dt$container)
regex_classify()
Now with probable references as ‘clean’ as possible, we use regular
expressions to classify our data based on exact matches using the
regex_classify() function. This function does two things.
First it looks across all of the columns for exact matches to our
indices, and if there is an exact match, it pulls out that value into a
‘input’ column. If there is no exact match, the value in the input
column will be selected in the following order of preference: doi,
container, publisher, title, author. Second, based on the matches the
function will assign the potential citation into one of four classes:
journal, agency, conference, or none. If none of the potential
citations’ data is an exact match to any of the indices, the
classification is NA.
# Extract most descriptive 'input' and look for exact match to index
dt <- regex_classify(dt, 'container')
Based on these classifications, we can see the counts of exact
matches, and which ones have not been classified.
|
Agency
|
Conference
|
Journal
|
Not a citation
|
Unclassified
|
|
1867
|
3
|
997
|
146
|
10899
|
keras_classify()
Next we want to classify the probable references that are not exact
matches to any of our indices. To do this, we use
keras_classify(), in which we input our probable references
into a neural network trained to predict the reference class. To train
this model, we used data from Environmental Impact Statements,
classified through both manual classification and the semi-automated
regex classification explained above.
# Use the descriptive 'input' to probabilistically identify the reference class
setwd("~/Documents/Davis/R-Projects/referenceClassify/")
predictions <- keras_classify(dt, probability = .85,
'container', auto_input = F,
'training_input')
dt <- cbind(dt, select(predictions, predict_class))
Because we ran this model on the whole data frame, we can compare our
regex classification with the Keras classifications to get a sense of
the model performance.
|
Incorrect
|
Match
|
Classified as unsure
|
|
30
|
2801
|
182
|
These results, altogether, suggest that the Keras model is 93%
accurate in its prediction of the citations we are able to do exact
matching for. Now, let’s unify the classification columns and have a
look at the total for each estimated grouping.
|
Agency
|
Conference
|
Not a citation
|
Journal
|
Unsure
|
|
3675
|
5
|
3163
|
1856
|
5213
|
And we’ll tidy up these data by filtering out the citations
classified into ‘delete’ (the false positives) in preparation for our
indexing in the next step.
dt <- dt %>%
select(-c(predict_class, method_comparison)) %>%
filter(class != "delete")
Interim check in: Journals and agencies from exact matching
So far, we’ve identified exact matches to our high-level indices
(journal, agency, conference) and then used machine learning to classify
citations that are not exact matches so that we can begin to figure out
their source. At this interim stage, we can take a look at the
high-level classifications across citations, and the journals and
agencies for which we’ve found exact matches.
First, let’s take a look at the high-level matches. A reference list
was required by DWR for GSPs, and indeed we see that all 114 of the
documents have references that we can identify as either a scholarly
journal or agency. Based on our tool’s probabilistic tags, it looks like
the number of references ranges from 1 to 128, with 24 being the average
number of classified references. That average differs between references
classes, whereby the average number of journal references is 16 and the
average number of agency references is twice that, at 32. In total,
there are 1,865 journal references and 3,675 agency references.
Of these references, we display the top 15 references to journals and
agencies identified by our exact matching strategies. At a glance, we
see a strong representation of geological, hydrological, and
agricultural science in both the journals and agency representation.
Among agencies, references to USGS are exceptionally large, more than
three times that of the second most-referenced agency.

Regarding the impact factor of academic references, we see very
little evidence for high-impact journals accounting for more citations.
While Science, one of the higher impact journals (12.6 SJR
score), is among the top 15 journals, the remaining 14 average an SJR
score of 2.

3. indexBuild
Now that we have a general sense of the kinds of reference types that
are represented within the probable references, the next step is to try
to index these reference exactly. The indexBuild package is
designed to query the openAlex
API, an open access catalog of research, in order to build a
personalized catalog relevant to the field of research. This step is
optional for the govscienceuseR workflow, as the tool kit
provides a default index with [define default index once it is created].
However, building an index for a given research project will likely
increase the matching abilities of the tool.
Identify index concepts
To build an index, we first need to define the scope. openAlex allows
indices to be built based on five different types of entities: authors,
institutions, venues, concepts, and works. We choose to build our index
based on concepts, as this casts the widest and most inclusive net. To
identify concepts, we use the journals already identified in our data.
We take these journals’ disciplinary category metadata from the Scimago
database as use these to query the categories in the openAlex data base.
Across the journals identified in our references there are 94
disciplinary categories and the top categories are displayed below.
queryConcepts()
We use these themes to inform our index creation through querying
openAlex concepts. The queryConcepts() function allows us
to enter words, based on ours themes, into openAlex API and find a
number of associated research concepts. I input the 192 Scimago themes
and keywords into the concept_string argument to query the
API.
key_themes <- unique(c(themes$cat, keywords$word))
# I am building in a sleep argument to this query function to avoid errors
query_slowly <- function(x){
index <- queryConcepts(concept_string = x,
per_page = 50)
return(index)
Sys.sleep(1)
}
index <- lapply(key_themes, query_slowly)
# For some reason there was a bit of missing data for particular concepts
index[[66]]$description <- ''
indexdf <- do.call('rbind', index) %>% unique()
From the 192 themes, openAlex identifies 3982 associated concepts,
representing 898507778 works. To focus our index, we select only the
concepts that are associated with the themes at ‘level 0’ – that is, the
highest match of relevance. This reduces our concepts down to 15,
high-level concepts, representing 898507778 works.
A summary of these concepts is below:
works2dt()
Now that we have .json.gz files containing the works we want in our
index, we can convert them into a data table using the
works2dt() function. This function takes the filepath of
the .json.gz compile to convert.
jsons <- list.files("openalex_index_gsp/", full.names = T)
# Anything that is 23 is empty
jsons <- jsons[file.size(jsons) > 23]
records <- lapply(jsons, works2dt)
recordsdf <- do.call("rbind", records)
We’ll also want to make sure our record data frame has the column
names that are compatible with the next stage, so let’s go ahead and
rename them appropriately.
colnames(recordsdf)[c(1,2,3,5,7,8,10,12)] <- c("source", "title", "doi",
"year", "miscid",
"journal_title",
"publisher", "authors")
Forthcoming: 4. referenceSearch()
LS0tCnRpdGxlOiAiVGhlIHNjaWVuY2UgaW5mb3JtaW5nIENhbGlmb3JuaWEncyBHcm91bmR3YXRlciBTdXN0YWluYWJpbGl0eSBQbGFucyIKc3VidGl0bGU6ICJBIHRlc3QgY2FzZSB1c2luZyBgZ292c2NpZW5jZXVzZVJgIHRvb2xzIgphdXRob3I6IAogIC0gTGl6YSBXb29kCiAgLSBUeWxlciBBLiBTY290dCAKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KCgpgYGB7ciBjaHVuayBzZXR1cCwgaW5jbHVkZSA9IEZ9CmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEYpCmBgYAoKYGBge3IgZnVuY3Rpb25zLCBlY2hvPSBGLG1lc3NhZ2UgPSBGfQpsaWJyYXJ5KHNob3d0ZXh0KQojZm9udF9hZGRfZ29vZ2xlKCJSb2JvdG8gbW9ubyIpCnRoZW1lX2dvdnVzZXIgPC0gZnVuY3Rpb24oYmFzZV9zaXplID0gMTIsIGZvbnQgPSAibW9ubyIpIHsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IGJhc2Vfc2l6ZSkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBmb250KSwKICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIiNkOWQ5ZDkiKQogICAgICApCn0KYGBgCgojIyMgSW50cm9kdWN0aW9uICAKCkFsaWduaW5nIHNjaWVudGlmaWMgc3VwcGx5IHdpdGggcG9saWN5IGRlbWFuZCBpbiBvcmRlciB0byBkZXZlbG9wIGV2aWRlbmNlLWJhc2VkIHBvbGljeSBpcyBjb25zaWRlcmVkIGEgZ29sZCBzdGFuZGFyZCBieSBtYW55IGFjY291bnRzLiBUaGUgQmlkZW4gQWRtaW5pc3RyYXRpb24gcmVjZW50bHkgcmVhZmZpcm1lZCB0aGF0ICdJdCBpcyB0aGUgcG9saWN5IG9mIFt0aGUgQmlkZW5dIEFkbWluaXN0cmF0aW9uIHRvIG1ha2UgZXZpZGVuY2UtYmFzZWQgZGVjaXNpb25zIGd1aWRlZCBieSB0aGUgYmVzdCBhdmFpbGFibGUgc2NpZW5jZSBhbmQgZGF0YS4uLiBTY2llbnRpZmljIGZpbmRpbmdzIHNob3VsZCBuZXZlciBiZSBkaXN0b3J0ZWQgb3IgaW5mbHVlbmNlZCBieSBwb2xpdGljYWwgY29uc2lkZXJhdGlvbnMnIChCaWRlbiwgMjAyMSkuIFRoaXMgc2VudGltZW50IGhhcyBiZWVuIGVjaG9lZCBieSB0aGUgY2FsbHMgZm9yIHVzZS1pbnNwaXJlZCBiYXNpYyByZXNlYXJjaCB0byBkZWxpdmVyIGlubm92YXRpdmUgc29sdXRpb25zIGluIHNlcnZpY2Ugb2Ygc29jaWFsIGFuZCBlbnZpcm9ubWVudGFsIGdvYWxzIChTdG9rZXMgMjAxMTsgRnVnbGllICYgVG9vbGUgMjAxNCkuIAoKSG93ZXZlciwgdGhlcmUgaXMgYnJvYWQgcmVjb2duaXRpb24gdGhhdCBwcm9tb3RpbmcgZXZpZGVuY2UtYmFzZWQgcG9saWN5bWFraW5nIGF0IGZhY2UgdmFsdWUgb3Zlcmxvb2tzIGNoYWxsZW5nZXMgcmVsYXRlZCB0byBrbm93bGVkZ2UgcG9saXRpY3MgYW5kIHRoZSBzZWxlY3RpdmUgdXNlIG9mIHNjaWVuY2UuIE5hbWVseSwgcG9saWN5bWFrZXJzJyBlbXBoYXNpcyBvbiBzY2llbmNlIGFzIGEgbmV1dHJhbCBhcmJpdGVyIG1hc2tzIHRoZSBwb2xpdGljcyBvZiBnZW5lcmF0aW5nIGFuZCBjb21tdW5pY2F0aW5nIHNjaWVudGlmaWMga25vd2xlZGdlIChTYXJld2l0eiAyMDAwKS4gU2NpZW5jZSBpcyBub3QgdmFsdWUtZnJlZSwgYnV0IHJhdGhlciwgc3VwcGx5IGFuZCBkZW1hbmQgb2Ygc2NpZW5jZSBhcmUgcG9saXRpY2FsbHkgbGlua2VkIChTYXJld2l0eiAmIFBpZWxrZSAyMDA3KS4gQXMgc3VjaCwgcmVzZWFyY2ggdG8gc3VwcG9ydCBldmlkZW5jZS1iYXNlZCBwb2xpY3ltYWtpbmcgcmVxdWlyZXMgaW50ZW50aW9uYWwgZW5nYWdlbWVudCBieSBzY2llbnRpc3RzIHRvIG5vdCBvbmx5IHJlZHVjZSB1bmNlcnRhaW50eSB0aHJvdWdoIGhpZ2gtcXVhbGl0eSByZXNlYXJjaCwgYnV0IGFsc28gcmVkdWNlIGFtYmlndWl0eSB0aHJvdWdoIHN0cmF0ZWdpYyBjb21tdW5pY2F0aW9uIGFuZCBwcm9ibGVtIGZyYW1pbmcgKENhaXJuZXkgMjAxNikuIEVtcGhhc2lzIG9uIGNvbW11bmljYXRpb24gaXMgZWNob2VkIGJ5IGxpdGVyYXR1cmUgb24gYm91bmRhcnkgc3Bhbm5lcnMgdGhhdCBjYW4gYnJva2VyIGJldHdlZW4gdGhlIHNjaWVudGlmaWMgYW5kIHBvbGljeSBjb21tdW5pdGllcyAoR3VzdG9uIDIwMDEpLiAgIAoKPCEtLS0gUXVhbGl0YXRpdmUgY2FzZSBkZXNjcmlwdGlvbnMgaGF2ZSBkZXNjcmliZWQgdGhlIHJlY3Vyc2l2ZSBzY2llbmNlLXBvbGljeSByZWxhdGlvbnNoaXAgZm9yIGVudmlyb25tZW50YWwgaXNzdWVzIHN1Y2ggYXMgYWNpZCByYWluLCBvem9uZSByZXBsZXRpb24sIGFuZCBjbGltYXRlIGNoYW5nZSAoUGllbGtlICYgQmV0c2lsbCAxOTk3OyBTYXJld2l0eiAyMDAwKS0tLT4KClJlY29nbml6aW5nIHRoZSBjb21wbGV4IGludGVycGxheSBvZiBzY2llbmNlIGFuZCBwb2xpY3ltYWtpbmcsIHdoYXQgbWV0aG9kcyBjYW4gd2UgdXNlIHRvIGJldHRlciB1bmRlcnN0YW5kIHRoZXNlIGR5bmFtaWNzPyBUaHJvdWdoIHN1cnZleXMgYW5kIGludGVydmlld3Mgb2YgcHVibGljIHNlcnZhbnRzLCBzdHVkaWVzIGZpbmQgd2lkZSB2YXJpYXRpb24gaW4gaG93IHBvbGljeW1ha2VycyBpbnRlcmFjdCB3aXRoIHNjaWVudGlmaWMgaW5mb3JtYXRpb24gKE5ld21hbiBldCBhbC4gMjAxNiksIGFuZCBoaWdobGlnaHQgdGhhdCBpbnRlcm5hbCBnb3Zlcm5tZW50YWwgcmVwb3J0cyBhbmQgcGVyc29uYWwgbmV0d29ya3MgYXJlIGFtb25nIHRoZSBtb3N0IHBvcHVsYXIgc291cmNlcyBvZiBpbmZvcm1hdGlvbiAoUGljemFrIGV0IGFsLiAyMDIyKS4gVGhlc2UgZmluZGluZ3MgaGF2ZSBiZWVuIHN1cHBvcnRlZCBhbmQgZGV0YWlsZWQgdGhyb3VnaCBhIGhhbmRmdWwgb2YgYmlibGlvbWV0cmljIGFuYWx5c2VzIG9mIHBvbGljeSBkb2N1bWVudHMuIERlc21hcmlzIGFuZCBIZXJkICgyMDE0KSBldmFsdWF0ZWQgMTAyIFJlZ3VsYXRvcnkgSW1wYWN0IEFzc2Vzc21lbnRzLCBjb25maXJtaW5nIHRoYXQgdGhlIG1ham9yaXR5IG9mIGNpdGF0aW9ucyBhcmUgdG8gZ292ZXJubWVudGFsIGFnZW5jaWVzLiBUaGV5IGFsc28gZGVzY3JpYmUgdGhlIHByZXZhbGVuY2Ugb2YgZGlzY2lwbGluZXMgbGlrZSBlY29ub21pY3MsIGVudmlyb25tZW50YWwgc2NpZW5jZSwgYW5kIHB1YmxpYyBoZWFsdGggZnJvbSBoaWdoLWltcGFjdCBqb3VybmFscyBhY3Jvc3MgMSwzNzggc2Nob2xhcmx5IGNpdGF0aW9ucy4gS29vbnR6ICgyMDIyKSBmaW5kcyBzaW1pbGFyIHRyZW5kcyB3aGVuIGFuYWx5emluZyAxMiBzYWxtb24gcmVjb3ZlcnkgcGxhbnMsIGNhdGVnb3JpemluZyAxLDEwNCByZWZlcmVuY2VzIGZyb20gdmFyaW91cyBzb3VyY2VzIChhY2FkZW1pYywgZ292ZXJubWVudGFsLCBvcmdhbml6YXRpb25hbCwgZXRjLikgYW5kIGV4cGFuZGluZyBvbiBob3cgc2NpZW5jZSBpcyB1c2VkIHRvIHN1cHBvcnQgY2F1c2FsIGFyZ3VtZW50cy4gIAoKVGhlIGluc2lnaHRzIGZyb20gYmlibGlvbWV0cmljIGFuYWx5c2VzIG9mIHBvbGljeSBkb2N1bWVudHMgbGF5IGFuIGltcG9ydGFudCBmb3VuZGF0aW9uIGZvciBzeXN0ZW1hdGljYWxseSBxdWFudGlmeWluZyB0aGUgZXZpZGVuY2UgdXNlZCB0byBzdXBwb3J0IHBvbGljeS4gSG93ZXZlciwgbWFudWFsbHkgZXh0cmFjdGluZyBhbmQgaW5kZXhpbmcgcmVmZXJlbmNlcyBjYW4gYmUgYSB0ZWRpb3VzIHRhc2suIFVubGlrZSAnc2NpZW5jZSBvZiBzY2llbmNlJyByZXNlYXJjaCwgd2hlcmUgYmlibGlvbWV0cmljIG1ldGhvZHMgYXJlIG1hZGUgZWFzaWVyIHRocm91Z2ggcHVibGlzaGluZyBub3JtcyBvZiBjaXRhdGlvbnMgYW5kIGluZGV4aW5nIChlLmcuIERPSXMsIE9SQ0lEcywgZXRjLiksIHNjaWVuY2Ugb2YgcG9saWN5IHJlc2VhcmNoIGlzIGxlc3Mgc3lzdGVtYXRpYy4gUG9saWN5IGRvY3VtZW50cyBkbyBub3QgYWx3YXlzIGZvbGxvdyBjb25zaXN0ZW50IGZvcm1hdHRpbmcgb3IgY2l0YXRpb24gbm9ybXMsIGFuZCByZWZlcmVuY2VzIG91dHNpZGUgb2Ygbm9uLXNjaG9sYXJseSBhcnRpY2xlcyAod2hpY2ggYXJlIHRoZSBtYWpvcml0eSBvZiByZWZlcmVuY2VzKSBhcmUgbm90IHN5c3RlbWF0aWNhbGx5IGluZGV4ZWQuIEhvd2V2ZXIsIGRldmVsb3BtZW50cyBpbiBjb21wdXRhdGlvbmFsIHRvb2xzIGZvciByZWFkaW5nIGFuZCBhbmFseXppbmcgbGFyZ2UgdGV4dHMgY3JlYXRlIGFuIG9wcG9ydHVuaXR5IGZvciBhdXRvbWF0aW5nIHNvbWUgb2YgdGhlIG1vcmUgdGVkaW91cyBwaGFzZXMgb2YgYmlibGlvbWV0cnkgb24gcG9saWN5IGRvY3VtZW50cy4gVGhpcyBwYXBlciBwcmVzZW50cyBhIHNldCBvZiB0b29scyBmb3IgYWlkaW5nIGJpYmxpb21ldHJpYyBhbmFseXNpcyBvZiBwb2xpY3kgZG9jdW1lbnRzLCBgZ292c2NpZW5jZXVzZVJgLCB3aGljaCB3ZSBob3BlIHdpbGwgc3VwcG9ydCBwb2xpY3kgcHJvY2VzcyByZXNlYXJjaGVycyBpbiBxdWFudGlmeWluZyBhbmQgdW5wYWNraW5nIHRoZSBjb21wbGV4IGludGVycGxheSBvZiBzY2llbmNlIGFuZCBwb2xpY3ltYWtpbmcuICAKCiMjIyBNZXRob2QgIAoKVGhlIGBnb3ZzY2llbmNldXNlUmAgdG9vbHMgcHJvdmlkZSBhIGNvbXB1dGF0aW9uYWwgYXBwcm9hY2ggZm9yIGluZGV4aW5nIGFuZCBzdW1tYXJpemluZyByZWZlcmVuY2VzIGZyb20gcG9saWN5IGRvY3VtZW50cy4gVGhpcyBpcyBhIHZpZ25ldHRlIHdhbGtpbmcgdGhyb3VnaCB0aGUgc3RlcHMgb2YgdGhlIFIgcGFja2FnZXMgaW4gdGhlIGBnb3ZzY2llbmNldXNlUmAgdG9vbCBzZXQ6IGByZWZlcmVuY2VFeHRyYWN0YCwgYHJlZmVyZW5jZUNsYXNzaWZ5YCwgYGluZGV4QnVpbGRgLCBhbmQgYHJlZmVyZW5jZVNlYXJjaGAuIFRvZ2V0aGVyLCB0aGVzZSBmb3VyIHBhY2thZ2VzIGFsbG93IHJlc2VhcmNoZXJzIHRvIGdvIGZyb20gUERGIGRvY3VtZW50cyB0byBhIGRhdGEgZnJhbWUgb2YgaW5kZXhlZCBjaXRhdGlvbnMgaW4gb25seSBhIGhhbmRmdWwgb2Ygc3RlcHMgaW4gdGhlIFIgY29kaW5nIGxhbmd1YWdlIChzdGVwcyBtYXBwZWQgYmVsb3cpLiBUaGUgZ29hbCBvZiB0aGVzZSB0b29scyBpcyB0byBhbGxvdyByZXNlYXJjaGVycyB3b3JraW5nIHdpdGggdmFyaW91cyB0eXBlcyBvZiBwb2xpY3kgZG9jdW1lbnRzIHRvIGFuYWx5emUgY2l0YXRpb25zIHVzaW5nIGEgc3lzdGVtYXRpYyBhbmQgcmVwcm9kdWNpYmxlIGFwcHJvYWNoLiAgCgohW10oaW1nL3dvcmtmbG93LnBuZykKYGBge3Igd29ya2Zsb3cgaW1hZ2UsIGVjaG89RkFMU0UsIG91dC53aWR0aD0nNzUlJywgZmlnLmFsaWduID0gImNlbnRlciIsIGV2YWwgPSBGfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnaW1nL3dvcmtmbG93LnBuZycpCmBgYAoKIyMjIENhc2U6IEdyb3VuZHdhdGVyIFN1c3RhaW5hYmlsaXR5IFBsYW5zICAgIAoKQ2FsaWZvcm5pYSdzIFN1c3RhaW5hYmxlIEdyb3VuZHdhdGVyIE1hbmFnZW1lbnQgQWN0IChTR01BKSBvZiAyMDE0IHNldHMgb3V0IGEgZnJhbWV3b3JrIGZvciBsb2NhbCBHcm91bmR3YXRlciBTdXN0YWluYWJpbGl0eSBBZ2VuY2llcyAoJ0FnZW5jaWVzJykgdG8gd29yayB0b3dhcmRzIHN1c3RhaW5hYmxlIG1hbmFnZW1lbnQgb2YgdGhlaXIgZ3JvdW5kd2F0ZXIgYmFzaW5zLiBBZ2VuY2llcyBhcmUgcmVxdWlyZWQgdG8gb3V0bGluZSB0aGVpciBzdHJhdGVnaWVzIGluIEdyb3VuZHdhdGVyIFN1c3RhaW5hYmlsaXR5IFBsYW5zIChHU1BzKSAtLSBkb2N1bWVudHMgcmV2aWV3ZWQgYnkgdGhlIERlcGFydG1lbnQgb2YgV2F0ZXIgUmVzb3VyY2VzIChEV1IpIHRvIGVuc3VyZSB0aGF0IEFnZW5jeSBzdHJhdGVnaWVzIGNvbXBseSB3aXRoIFNHTUEsIHRoZSBHU1AgcmVndWxhdGlvbnMsIGFuZCBhY2hpZXZlIGdyb3VuZHdhdGVyIHN1c3RhaW5hYmlsaXR5IGZvciB0aGUgYmFzaW4gKERXUiBubyBkYXRlKS4gQW1vbmcgdGhlIGNyaXRlcmlhIGZvciBwbGFuIGV2YWx1YXRpb24sIHRoZSBDYWxpZm9ybmlhIENvZGUgc3BlY2lmaWVzOiAiV2hlbiBldmFsdWF0aW5nIHdoZXRoZXIgYSBQbGFuIGlzIGxpa2VseSB0byBhY2hpZXZlIHRoZSBzdXN0YWluYWJpbGl0eSBnb2FsIGZvciB0aGUgYmFzaW4sIHRoZSBEZXBhcnRtZW50IHNoYWxsIGNvbnNpZGVy4oCmIFdoZXRoZXIgdGhlIGFzc3VtcHRpb25zLCBjcml0ZXJpYSwgZmluZGluZ3MsIGFuZCBvYmplY3RpdmVzLCBpbmNsdWRpbmcgdGhlIHN1c3RhaW5hYmlsaXR5IGdvYWzigKYgYXJlIHJlYXNvbmFibGUgYW5kIHN1cHBvcnRlZCBieSB0aGUgYmVzdCBhdmFpbGFibGUgaW5mb3JtYXRpb24gYW5kIGJlc3QgYXZhaWxhYmxlIHNjaWVuY2UiICgyMyBDQ1IgwqcgMzU1LjQpLiAgCgpUaGVyZSBpcyBhIGNsZWFyIG1hbmRhdGUgdGhhdCBHU1AgZG9jdW1lbnRzIHVzZSBzY2llbnRpZmljIGV2aWRlbmNlIHRvIHN1cHBvcnQgdGhlaXIgc3RyYXRlZ2llcyBmb3IgZ3JvdW5kd2F0ZXIgc3VzdGFpbmFiaWxpdHksIGJ1dCBkZWZpbmluZyBhbmQgbWVhc3VyaW5nIHN1c3RhaW5hYmlsaXR5IGlzIG5vIHNpbXBsZSBmZWF0IChLdWhsbWFuICYgRmFycmluZ3RvbiAyMDEwKS4gRFdSIHNldHMgb3V0IHNpeCBzdXN0YWluYWJpbGl0eSBpbmRpY2F0b3JzLCB3aGVyZWJ5IHRoZSBvY2N1cnJlbmNlIG9mIGFueSBpbmRpY2F0b3Igd291bGQgYmUgYW4gdW5kZXNpcmFibGUgcmVzdWx0OiBsb3dlcmluZyBncm91bmR3YXRlciBsZXZlbHMsIHJlZHVjdGlvbiBvZiBzdG9yYWdlLCBzZWF3YXRlciBpbnRydXNpb24sIGRlZ3JhZGVkIHF1YWxpdHksIGxhbmQgc3Vic2lkZW5jZSwgYW5kIHN1cmZhY2Ugd2F0ZXIgZGVwbGV0aW9uLiBIb3dldmVyLCBlYWNoIGxvY2FsIEFnZW5jeSBpcyByZXNwb25zaWJsZSBmb3Igc2V0dGluZyBtZWFzdXJhYmxlIG9iamVjdGl2ZXMgYW5kIG1pbmltdW0gdGhyZXNob2xkcyBmb3IgdGhlc2UgaW5kaWNhdG9ycyBieSBjb25zaWRlcmluZyBhbGwgJ2JlbmVmaWNpYWwgdXNlcnMgYW5kIHVzZXMnIGZvciB0aGVpciBiYXNpbiAoQXVzdGluLCAyMDE5KS4gQmVuZWZpY2lhbCB1c2VzIGluY2x1ZGUgJ2RvbWVzdGljLCBtdW5pY2lwYWwsIGFncmljdWx0dXJhbCwgYW5kIGluZHVzdHJpYWwgc3VwcGx5OyBwb3dlciBnZW5lcmF0aW9uOyByZWNyZWF0aW9uOyBhZXN0aGV0aWMgZW5qb3ltZW50OyBuYXZpZ2F0aW9uOyBhbmQgcHJlc2VydmF0aW9uIGFuZCBlbmhhbmNlbWVudCBvZiBmaXNoLCB3aWxkbGlmZSwgYW5kIG90aGVyIGFxdWF0aWMgcmVzb3VyY2VzIG9yIHByZXNlcnZlcycgKENhbGlmb3JuaWEgV2F0ZXIgUGxhbiBnbG9zc2FyeSAyMDE4KS4gCgpGYWNpbmcgdGhlIGNoYWxsZW5nZSBvZiBtYW5hZ2luZyBncm91bmR3YXRlciByZXNvdXJjZXMgYWNyb3NzIGEgd2lkZSBhcnJheSBvZiB1c2VycyBhbmQgaW50ZXJlc3RzLCB3ZSBhc2s6ICoqSG93IGlzIHNjaWVuY2UgdXNlZCB0byBpbmZvcm0gdGhlIG11bHRpcGxlIGRpbWVuc2lvbnMgb2YgZ3JvdW5kd2F0ZXIgc3VzdGFpbmFiaWxpdHk/KiogQW5hbHlzZXMgb2YgdGhlIFNHTUEgY29sbGFib3JhdGl2ZSBwcm9jZXNzIGFuZCBHU1AgZHJhZnRzIGhhdmUgYWxyZWFkeSBzaG93biB0aGF0IGFjaGlldmluZyBncm91bmR3YXRlciBzdXN0YWluYWJpbGl0eSB3aGlsZSBzdXBwb3J0aW5nIF9hbGxfIGJlbmVmaWNpYWwgdXNlcyBpcyB1bmxpa2VseS4gTWluaW11bSB0aHJlc2hvbGRzIGFuYWx5emVkIGluIGRyYWZ0IHBsYW5zIGZvdW5kIHRoYXQgc29tZSBiZW5lZmljaWFsIHVzZXMgYXJlIHByZWZlcmVuY2VkIG92ZXIgb3RoZXJzLCB3aXRoIHN0YWtlaG9sZGVycyBsaWtlIGRvbWVzdGljIHdlbGwgdXNlcnMgcG90ZW50aWFsbHkgZ29pbmcgd2l0aG91dCB3YXRlciAoQm9zdGljIGV0IGFsLiAyMDIwKS4gVG8gYnVpbGQgb24gdGhpcyBleGlzdGluZyByZXNlYXJjaCwgd2UgdHVybiB0byB0aGUgc2NpZW50aWZpYyBldmlkZW5jZSB1c2VkIGluIEdTUHMgdG8gdGVsbCB1cyBhYm91dCBob3cgYWdlbmNpZXMgYXJlIGRlZmluaW5nIHN1c3RhaW5hYmlsaXR5LiBXZSB0cmlhbCB0aGUgYGdvdnNjaWVuY2V1c2VSYCB0b29sIGtpdCBvbiAxMTQgR1NQcywgZGVzY3JpYmVkIG1vcmUgaW4gdGhlIGRhdGEgc2VjdGlvbiBiZWxvdy4gIAoKPCEtLS0gUmVwcmVzZW50YXRpb24gY2hhbGxlbmdlcyAoRG9iYmluKSAtLS0+CgojIyMgR2V0dGluZyBzdGFydGVkICAgCgojIyMjIEluc3RhbGxhdGlvbnMgIAoKVG8gYmVnaW4sIGRvd25sb2FkIGFsbCBmb3VyIHBhY2thZ2VzIGZyb20gdGhlIFtnb3ZzY2llbmNldXNlUiBHaXRIdWIgcGFnZV0oaHR0cHM6Ly9naXRodWIuY29tL2dvdnNjaWVuY2V1c2VSKTogIAoKYGBge3IgcGFja2FnZSBkb3dubG9hZCwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGLCByZXN1bHRzID0gRiwgZXZhbCA9IEZ9CmRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZ292c2NpZW5jZXVzZVIvcmVmZXJlbmNlRXh0cmFjdCIpCmRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZ292c2NpZW5jZXVzZVIvcmVmZXJlbmNlQ2xhc3NpZnkiKQpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImdvdnNjaWVuY2V1c2VSL2luZGV4QnVpbGQiKQpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImdvdnNjaWVuY2V1c2VSL3JlZmVyZW5jZVNlYXJjaCIpCmBgYAoKYGBge3IgZWNobyA9IEZ9CnNlbmRfbWFpbHRvIDwtICd0YXNjb3R0QHVjZGF2aXMuZWR1JwpgYGAKVGhlbiBsb2FkIHRoZXNlIGFuZCBkZXBlbmRlbnQgcGFja2FnZXMgaW50byBsaWJyYXJ5LiBZb3UgbWF5IGJlIHByb21wdGVkIHRvIGluc3RhbGwgc29tZSBvZiB0aGUgZGVwZW5kZW50IHBhY2thZ2VzIGlmIHlvdSBkbyBub3QgYWxyZWFkeSBoYXZlIHRoZW0sIHN1Y2ggYXMgYGtlcmFzYC4gIAoKPCEtLS1bKipOb3RlOiBBbGwgb2YgdGhlIGRlcGVuZGVudCBwYWNrYWdlcyByZXF1aXJlZCBzaG91bGQgYmUgaW1wb3J0ZWQgd2hlbiB3ZSBsb2FkIGluIHRoZXNlIHBhY2thZ2VzLCBidXQgdGhleSBjdXJyZW50bHkgYXJlbid0IC0tIHN0aWxsIHN0cnVnZ2xpbmcgd2l0aCBwYWNrYWdlIGltcG9ydHMgd2hlbiBmdW5jdGlvbi1idWlsZGluZyoqXS4gLS0tPgoKYGBge3IgcGFja2FnZSBzZXR1cCwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGLCByZXN1bHRzID0gRn0KbGlicmFyeShyZWZlcmVuY2VFeHRyYWN0KQpsaWJyYXJ5KHJlZmVyZW5jZUNsYXNzaWZ5KQpsaWJyYXJ5KGluZGV4QnVpbGQpCmxpYnJhcnkocmVmZXJlbmNlU2VhcmNoKQpwYWNrcyA8LSBjKCdkYXRhLnRhYmxlJywgJ2RwbHlyJywgJ3N0cmluZ3InLCAna2VyYXMnLCAndGVuc29yZmxvdycsCiAgICAgICAgICAndGlkeXInLCAncHVycnInLCAnc2pyZGF0YScpCmlmKCEnc2pyZGF0YScgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKVssJ1BhY2thZ2UnXSl7CiAgcGFrOjpwYWsoJ2lrYXNobml0c2t5L3NqcmRhdGEnKQp9CnNhcHBseShwYWNrcywgcmVxdWlyZSwgY2hhcmFjdGVyLm9ubHkgPSBUKQpgYGAKCk91dHNpZGUgb2YgUiwgdGhlIGByZWZlcmVuY2VTZWFyY2hgIHBhY2thZ2UgYWxzbyByZXF1aXJlcyBpbnN0YWxsYXRpb24gYW5kIHJ1bm5pbmcgb2YgIFtTb2xyXShodHRwczovL3NvbHIuYXBhY2hlLm9yZykuIFRoaXMgc29mdHdhcmUgc2hvdWxkIGJlIGRvd25sb2FkZWQgdG8gYSBrbm93biBsb2NhdGlvbiBvbiB5b3VyIGNvbXB1dGVyLiAgICAKCiMjIyMgRGF0YSAgICAKClRoZSBkb2N1bWVudHMgb2YgaW50ZXJlc3QgZm9yIHRoaXMgcGFwZXIgYXJlIENhbGlmb3JuaWEncyBHcm91bmR3YXRlciBTdXN0YWluYWJpbGl0eSBQbGFucy4gVGhlc2UgZG9jdW1lbnRzIGFyZSBhdmFpbGFibGUgcHVibGljbHkgdG8gZG93bmxvYWQgZnJvbSBhIFtCb3hdKGh0dHBzOi8vdWNkYXZpcy5ib3guY29tL3MvOW0zZG9nYmlia3J3eTAxcGc0c2R3b3Voemw4aTZzZWYpIGZvbGRlciB3ZSBob3N0LiBUbyBmb2xsb3cgYWxvbmcgd2l0aCB0aGlzIHR1dG9yaWFsLCBkb3dubG9hZCB0aGUgZmlsZXMgdG8gYSBmaWxlIHRoYXQgd2lsbCBiZSBjb25zaWRlcmVkIHlvdXIgZG9jdW1lbnQgZGlyZWN0b3J5LiBPdXIgZG9jdW1lbnQgZGlyZWN0b3J5IGlzIHNwZWNpZmllZCBiZWxvdy4gSGVyZSB3ZSBhcmUgd29ya2luZyB3aXRoIGByIGxlbmd0aChsaXN0LmZpbGVzKCJ+L0JveC9yZWZlcmVuY2VfY2xhc3NpZmllci9kb2N1bWVudHNfZ3NwLyIpKWAgcGxhbnMgd2hpY2ggdG90YWwgb3ZlciAxNjAsMDAwIHBhZ2VzLCBwdWJsaXNoZWQgYmV0d2VlbiAyMDE5LTIwMjIuICAKCmBgYHtyIHNldCBkb2MgZGlyfQpkb2NfZGlyZWN0b3J5IDwtICJ+L0JveC9yZWZlcmVuY2VfY2xhc3NpZmllci9yZWZlcmVuY2VfY2xhc3NpZmllci9kb2N1bWVudHNfZ3NwLyIKYGBgCgpgYGB7ciBjb3VudCBwYWdlcywgZXZhbCA9IEYsIGVjaG8gPSBGfQpwZGZpbmZvIDwtIGxhcHBseShsaXN0LmZpbGVzKGRvY19kaXJlY3RvcnksIGZ1bGwubmFtZXMgPSBUKSwKICAgICAgICAgICAgICAgcGRmdG9vbHM6OnBkZl9pbmZvKQp5ZWFyZGYgPC0gZGF0YS5mcmFtZSgpCmZvcihpIGluIDE6bGVuZ3RoKHBkZmluZm8pKXsKICB5ZWFycyA8LSB5ZWFyKHBkZmluZm9bW2ldXSRjcmVhdGVkKQogIHllYXJkZiA8LSByYmluZCh5ZWFycywgeWVhcmRmKQp9CnN1bW1hcnkoeWVhcmRmJFgyMDIwTFt5ZWFyZGYkWDIwMjBMICE9IDIxMDZdKQpwZGZzIDwtIGRhdGEuZnJhbWUoZG8uY2FsbCgncmJpbmQnLCBwZGZpbmZvKSkKcGFnZXMgPC0gc3VtKGFzLm51bWVyaWMocGRmcyRwYWdlcykpCnBhZ2VzL25yb3cocGRmcykKYGBgCgojIyMgMS4gYHJlZmVyZW5jZUV4dHJhY3RgICAKClRoZSBgcmVmZXJlbmNlRXh0cmFjdGAgcGFja2FnZSBmcm9tIGdvdnNjaWVuY2V1c2VSIGlzIGRlc2lnbmVkIHRvIHRha2UgdW5zdHJ1Y3R1cmVkIFBERiBkb2N1bWVudHMsIGZlZWQgdGhlbSB0aHJvdWdoIHRoZSBbYW55c3R5bGUuaW9dKGh0dHBzOi8vYW55c3R5bGUuaW8vKSBjaXRhdGlvbiBleHRyYWN0aW9uIHNvZnR3YXJlLCBhbmQgcmV0dXJuIHRhZ2dlZCBjaXRhdGlvbiBkYXRhIGluIGEgdGFidWxhciBmb3JtYXQuIFRoaXMgaXMgYWNjb21wbGlzaGVkIHVzaW5nIHRocmVlIGZ1bmN0aW9ucywgb3V0bGluZWQgaW4gdGhlIGZvbGxvd2luZyBzZWN0aW9ucy4gICAgIAoKIyMjIyBgcmVmZXJlbmNlX2V4dHJhY3QoKWAgICAKClRoZSBmaXJzdCBzdGVwIG9mIGV4dHJhY3RpbmcgcmVmZXJlbmNlcyBpcyB0byBpbnB1dCBQREYgZG9jdW1lbnRzIGludG8gdGhlIGByZWZlcmVuY2VfZXh0cmFjdCgpYCBmdW5jdGlvbi4gVGhpcyBmdW5jdGlvbiByZWFkcyBpbiBldmVyeSBQREYgaW4gdGhlIGRvY3VtZW50IGRpcmVjdG9yeSAoZG9jX2RpciksIGFuZCBydW5zIHRoZW0gdGhyb3VnaCBhbnlzdHlsZS5pby4gQW55c3R5bGUgZXh0cmFjdHMgcHJvYmFibGUgY2l0YXRpb25zIGFuZCBleHBvcnRzIHRoZW0gdG8gdGhlIHJlZmVyZW5jZSBkaXJlY3RvcnkgKHJlZl9kaXIpIGFzIEpTT04gZmlsZXMuIERlcGVuZGluZyBvbiB0aGUgbnVtYmVyIGFuZCBzaXplIG9mIGZpbGVzLCB0aGlzIGNhbiB0YWtlIHNvbWUgdGltZS4gRm9yIGV4YW1wbGUsIHRoZXNlIDExNCBkb2N1bWVudHMgdG9vayBvdmVyIGFuIGhvdXIgdG8gZXh0cmFjdC4gIAoKYGBge3Igc2V0IHJlZiBkaXIgY292ZXJ0LCBlY2hvID0gRn0KcmVmX2RpcmVjdG9yeSA8LSAicG9zdHMvZ3NwX3ZpZ25ldHRlX2ZpbGVzL2RhdGEvcmVmX2RpciIKYGBgCgpgYGB7ciByZWZlcmVuY2UgZXh0cmFjdCwgZXZhbCA9IEZ9CiMgRXh0cmFjdCBwcm9iYWJsZSBjaXRhdGlvbnMgZnJvbSBQREYgZG9jdW1lbnRzIGFuZCBjb252ZXJ0IHRoZW0gdG8gLmpzb24gZmlsZXMKcmVmX2RpcmVjdG9yeSA8LSAiZ3NwX3ZpZ25ldHRlX2ZpbGVzL2RhdGEvcmVmX2RpciIKcmVmZXJlbmNlX2V4dHJhY3QoZG9jX2RpciA9IGRvY19kaXJlY3RvcnksIAogICAgICAgICAgICAgICAgIHJlZl9kaXIgPSByZWZfZGlyZWN0b3J5LCAKICAgICAgICAgICAgICAgICBsYXlvdXQgPSAibm9uZSIpCmBgYAoKIyMjIyBgcmVmZXJlbmNlX2NvbXBpbGUoKWAgICAKCk5leHQsIHRoZSBgcmVmZXJlbmNlX2NvbXBpbGUoKWAgZnVuY3Rpb24gdHJhbnNmb3JtcyB0aGUgSlNPTiBmaWxlcyBpbnRvIHRhYnVsYXIgZGF0YSBhbmQgY29tcGlsZXMgdGhlbSBhbGwgaW4gb25lIGRhdGEgdGFibGUsIGFkZGluZyB0aGUgZmlsZSBuYW1lIGFzIGFuIGlkZW50aWZpZXIuICAKCmBgYHtyIHJlZmVyZW5jZSBjb21waWxlfQojIENvbXBpbGUganNvbiBmaWxlcyBpbnRvIGEgc2luZ3VsYXIgdGFidWxhciBkYXRhIHRhYmxlCmR0IDwtIHJlZmVyZW5jZV9jb21waWxlKHJlZl9kaXJlY3RvcnkpCmBgYAoKQWZ0ZXIgdGhlc2UgZmlyc3QgdHdvIHN0ZXBzIHdlIGNhbiB0YWtlIGEgbG9vayBhdCBvdXIgcHJvYmFibGUgY2l0YXRpb25zIGFjY29yZGluZyB0byB0aGUgQW55c3R5bGUgc29mdHdhcmUuIEluaXRpYWxseSwgdGhlcmUgYXJlIGByIG5yb3coZHQpYCBwcm9iYWJsZSBjaXRhdGlvbnMgYWNyb3NzIHRoZXNlIGByIGxlbmd0aChsaXN0LmZpbGVzKHJlZl9kaXJlY3RvcnkpKWAgZG9jdW1lbnRzLiAgCgpgYGB7ciBzaG93IGNvbXBpbGVkIGRhdGEsIGVjaG8gPSBGfQpEVDo6ZGF0YXRhYmxlKGhlYWQoc2VsZWN0KGR0LCBhdXRob3IsIGRhdGUsIHRpdGxlLCBgY29udGFpbmVyLXRpdGxlYCksCiAgICAgICAgICAgICAgICAgICBuID0gMTAwKSwgcm93bmFtZXMgPSBGKQpgYGAKCkl0IGlzIG5vdGljZWFibGUgYWJvdmUgdGhhdCB0aGUgZGF0YSBwcm92aWRlZCBieSBBbnlzdHlsZSBoYXMgaXRzIGNoYWxsZW5nZXMgZm9yIGZ1cnRoZXIgYW5hbHlzaXMuIFRoZSBmaXJzdCBpcyBhIHJlbGF0ZWQgdG8gZGF0YSBzdHJ1Y3R1cmU6IGF1dGhvcnMgYXJlIG5lc3RlZCBpbnRvIG1hdHJpY2VzLCBzb21lIHJvd3MgKHN1Y2ggYXMgdGhlIGRhdGUpIGhhdmUgbXVsdGlwbGUgbGlzdGVkIHZhbHVlcywgZXRjLiwgYWxsIG9mIHdoaWNoIG1ha2UgdGhlIGRhdGEgaGFyZCB0byBhbmFseXplLiBGb3IgZXhhbXBsZSwgaGVyZSBpcyB3aGF0IHNlZW1zIHRvIGJlIHR3byBwcm9iYWJsZSBjaXRhdGlvbnMgY29tYmluZWQgaW50byBvbmUgb2JzZXJ2YXRpb246ICAKCjwhLS0tIEFyZSB0aGVzZSBleGFtcGxlcyBuZWNlc3Nhcnk/IC0tLT4KCmBgYHtyIGNoYWxsZW5nZSBleGFtcGxlIDF9CnVubmVzdChkdFsyMDQsIGMoMiwzKV0pCmBgYAoKVGhlIHNlY29uZCBjaGFsbGVuZ2UgaXMgcmVsYXRlZCB0byBxdWFsaXR5OiBtYW55IG9mIHRoZSBwcm9iYWJsZSBjaXRhdGlvbnMgYXJlIG5vdCBzZW5zaWJsZS4gVGhlIEFueXN0eWxlIHNvZnR3YXJlIHNlZW1zIHNlbnNpdGl2ZSB0byBtdWx0aXBsZSBmb3JtYXRzIGxpa2UgbnVtYmVycyBhbmQgc2hvcnQtZm9ybSBzZW50ZW5jZXMsIHN1Y2ggYXMgYWRkcmVzc2VzLCByZXN1bHRpbmcgaW4gZmFsc2UgcG9zaXRpdmUgaWRlbnRpZmljYXRpb24gb2YgcmVmZXJlbmNlcy4gRm9yIGV4YW1wbGUsIGhlcmUgaXMgYW4gYWRkcmVzcyBsaXN0ZWQgYXMgYSBwcm9iYWJsZSBjaXRhdGlvbiBmcm9tIG91ciBkYXRhOiAgCmBgYHtyIGNoYWxsZW5nZSBleGFtcGxlIDJ9CnVubGlzdChkdFsxNDgsIGMoMSwzLDUpXSkKYGBgCgojIyMjIGByZWZlcmVuY2VfY2xlYW4oKWAgIAoKVG8gdHJ5IHRvIGFkZHJlc3MgdGhlIGNoYWxsZW5nZXMgaW4gdGhlc2UgcHJvYmFibGUgY2l0YXRpb25zLCB0aGUgYHJlZmVyZW5jZV9jbGVhbigpYCBmdW5jdGlvbiBnb2VzIHRocm91Z2ggYSBzZXJpZXMgb2Ygc3RlcHMuIEZvciBlYWNoIGNvbHVtbiB0aGUgZnVuY3Rpb24gdW5saXN0cyB0aGUgZGF0YSBhbmQgZmlsdGVycyBvdXQgdW5saWtlbHkgY2FuZGlkYXRlcyBmb3IgdGhhdCBjb2x1bW4uIEZvciBpbnN0YW5jZSwgaWYgYSBudW1iZXIgbGlzdGVkIGluIHRoZSBkYXRlIGNvbHVtbiBkb2VzIG5vdCBtYXRjaCBhbnkgcmVhc29uYWJsZSBkYXRlIGZvcm1hdCBvciBleHBlY3RhdGlvbiwgaXQgaXMgcmVtb3ZlZC4gSWYgYSBzdHJpbmcgaW4gdGhlIFVSTCBjb2x1bW4gYWN0dWFsbHkgcmVzZW1ibGVzIGEgRE9JLCBpdCBpcyBtb3ZlZCB0byB0aGF0IGNvbHVtbi4gQW5kIHNvIG9uLiBGdXJ0aGVybW9yZSwgaWYgdGhlcmUgc2VlbSB0byBiZSBtdWx0aXBsZSBjaXRhdGlvbnMgbGlzdGVkIGluIG9uZSByb3cgdGhhdCBjYW4gYmUgYnJva2VuIGFwYXJ0IGluIHBhcmFsbGVsIGFjcm9zcyBhbGwgb2YgdGhlIGNvbHVtbnMsIHdlIHVubmVzdCB0aGVzZSByb3dzLiAoTm90ZTogZGVwZW5kaW5nIG9uIHRoZSBzaXplIG9mIHRoZSBmaWxlcyB0aGlzIGZ1bmN0aW9uIG1heSB0YWtlIHNvbWUgdGltZS4gQ2xlYW5pbmcgdGhlc2UgYHIgbnJvdyhkdClgIGNpdGF0aW9ucyB0YWtlcyBhYm91dCAxOCBtaW51dGVzKS4gIAoKYGBge3IgcmVmZXJlbmNlIGNsZWFuLCBldmFsID0gRn0KIyBVbm5lc3RzIGxpc3Qgc3RydWN0dXJlcyBpbnRvIHRhYnVsYXIgZGF0YSBhbmQgZmlsdGVycyBvdXQgbG93IHByb2JhYmlsaXR5IHJlZnMKZHQgPC0gcmVmZXJlbmNlX2NsZWFuKGR0KQpgYGAKCmBgYHtyIGxvYWQgcmVmIGNsZWFuIGR0IGNvdmVydCwgZWNobyA9IEZ9CiNzYXZlUkRTKGNsZWFuZWRfZHQsICJ2aWduZXR0ZXMvZ3NwX3ZpZ25ldHRlX2ZpbGVzL2RhdGEvZHRfcG9zdF9yZWZjbGVhbi5SRFMiKQpkdCA8LSByZWFkUkRTKCJwb3N0cy9nc3BfdmlnbmV0dGVfZmlsZXMvZGF0YS9kdF9wb3N0X3JlZmNsZWFuLlJEUyIpCmBgYAoKVGhpcyBjbGVhbmluZyBwcm9jZXNzIGhhcyB0aGUgY2hhbmdlZCBwcm9iYWJsZSBjaXRhdGlvbnMgbm93IGEgYml0LiBTb21lIG9mIHRoZSBwcm9iYWJsZSBjaXRhdGlvbnMgaGF2ZSBiZWVuIHVubmVzdGVkIChhbmQgdGhlcmVmb3JlIGV4cGFuZGVkKSB3aGlsZSBvdGhlcnMgaGF2ZSBiZWVuIHJlbW92ZWQsIGxlYXZpbmcgdXMgd2l0aCBgciBucm93KGR0KWAgcHJvYmFibGUgY2l0YXRpb25zLiBFeGFtcGxlcyBvZiB0aGVzZSBwcm9iYWJsZSBjaXRhdGlvbnMgYXJlIGJlbG93OiAgIAoKYGBge3IgZXhhbXBsZSBvZiBjbGVhbmVkLCBlY2hvID0gRn0KRFQ6OmRhdGF0YWJsZShoZWFkKHNlbGVjdChkdCwgYXV0aG9yLCB5ZWFyLCB0aXRsZSwgY29udGFpbmVyLCBwdWJsaXNoZXIpLCBuID0gMTAwKSwgcm93bmFtZXMgPSBGKQpgYGAKCgojIyMgMi4gYHJlZmVyZW5jZUNsYXNzaWZ5YCAgCgpUaGUgYHJlZmVyZW5jZUNsYXNzaWZ5YCBwYWNrYWdlIGlzIGRlc2lnbmVkIHRvIHRha2UgYSBkYXRhIGZyYW1lIG9mIHRhYnVsYXIsIHRhZ2dlZCBjaXRhdGlvbiBkYXRhIChhdXRob3IsIHllYXIsIGNvbnRhaW5lciwgcHVibGlzaGVyLCBkb2ksIGV0YyksIGxvb2sgZm9yIGV4YWN0IG1hdGNoZXMgYmV0d2VlbiB0aG9zZSB0YWdzIGFuZCB2YXJpb3VzIGhpZ2gtbGV2ZWwgaW5kaWNlcyAobWFpbmx5IGpvdXJuYWwgYW5kIGFnZW5jeSBuYW1lcyksIGFuZCBiZWdpbiB0byBjbGFzc2lmeSBwcm9iYWJsZSBjaXRhdGlvbnMgaW50byB0aGVzZSBoaWdoLWxldmVsIGNhdGVnb3JpZXMuIFRoZXNlIGluZGljZXMgYXJlIDEpIGFuIGluZGV4IG9mIGFjYWRlbWljIGpvdXJuYWxzIGZyb20gdGhlIFtgc2pyYCBwYWNrYWdlXShodHRwczovL3JkcnIuaW8vZ2l0aHViL2lrYXNobml0c2t5L3NqcmRhdGEvbWFuL3Nqcl9qb3VybmFscy5odG1sKSByZWx5aW5nIG9uIHRoZSBbU2NpbWFnbyBkYXRhYmFzZV0oaHR0cHM6Ly93d3cuc2NpbWFnb2pyLmNvbS8pLCAyKSBhbiBpbmRleCBvZiBhY2FkZW1pYyBjb25mZXJlbmNlIHBhcGVycy9wcm9jZWVkaW5ncyBhbHNvIGZyb20gdGhlIFNjaW1hZ28gZGF0YWJhc2UsIDMpIGFuZCBhbiBpbmRleCBvZiBVUyBzdGF0ZSBhbmQgZmVkZXJhbCBhZ2VuY2llcywgY3VyYXRlZCBieSB0aGUgcGFja2FnZSBhdXRob3JzLiBBbGwgdGhyZWUgb2YgdGhlc2UgaW5kaWNlcyBhcmUgYnVpbHQgaW50byB0aGlzIHBhY2thZ2UgYW5kIGNhbiBiZSBhY2Nlc3NlZCB3aXRoIGBkYXRhKCdzY2ltYWdvLmonKWAgZm9yIGpvdXJuYWxzLCBgZGF0YSgnc2NpbWFnby5jJylgIGZvciBjb25mZXJlbmNlcywgYW5kIGBkYXRhKCdhZ2VuY2llcycpYCBmb3IgYWdlbmNpZXMuICAKCjwhLS0tCiMjIyMgYF9tYXRjaCgpYCBmdW5jdGlvbnMgIAoKQmFzZWQgb24gb3VyIGluaXRpYWwgY2xlYW5pbmcgb2YgdGhlIEdTUCBkYXRhIGluIHRoZSBwcmV2aW91cyBzZWN0aW9uLCB3ZSBjYW4gc2VlIHdoaWNoIG9mIHRoZXNlIHByb2JhYmxlIGNpdGF0aW9ucyBhcmUgZXhhY3QgbWF0Y2hlcyB0byB0aHJlZSBkaWZmZXJlbnQgaW5kaWNlczogYW4gaW5kZXggb2YgYWNhZGVtaWMgam91cm5hbHMgZnJvbSB0aGUgU2NpbWFnbyBkYXRhYmFzZSwgYW4gaW5kZXggb2YgYWNhZGVtaWMgY29uZmVyZW5jZSBwYXBlcnMvcHJvY2VlZGluZ3MgYWxzbyBmcm9tIHRoZSBTY2ltYWdvIGRhdGFiYXNlLCBhbmQgYW4gaW5kZXggb2YgVVMgc3RhdGUgYW5kIGZlZGVyYWwgYWdlbmNpZXMsIGN1cmF0ZWQgYnkgdGhlIHBhY2thZ2UgYXV0aG9ycy4gV2UgY2FuIGxvb2sgZm9yIG1hdGNoZXMgdXNpbmcgdGhlIGBqb3VybmFsX21hdGNoKClgLCBgY29uZmVyZW5jZV9tYXRjaCgpYCBhbmQgYGFnZW5jeV9tYXRjaCgpYCBmdW5jdGlvbnMuCgpgYGB7cn0KdGFibGUoam91cm5hbF9tYXRjaChkdCRjb250YWluZXIpKQpgYGAKCmBgYHtyfQp0YWJsZShjb25mZXJlbmNlX21hdGNoKGR0JGNvbnRhaW5lcikpCmBgYAoKYGBge3J9CnRhYmxlKGFnZW5jeV9tYXRjaChkdCRjb250YWluZXIsIGR0JGF1dGhvcikpCmBgYAotLS0+CgojIyMjIGBwcmVwYXJlZF9ieSgpYCBhbmQgYGpvdXJuYWxfZGlzYW1iaWcoKWAgIAoKPCEtLU5vdGU6IFNob3VsZCB0aGVzZSBiZSBtb3ZlZCB0byB0aGUgY2xlYW5pbmcgZnVuY3Rpb24sIG9yIHRvIHRoZSBvdGhlciBwYWNrYWdlPyAtLS0+CgpCZWZvcmUgY2xhc3NpZnlpbmcgb3VyIHByb2JhYmxlIHJlZmVyZW5jZXMsIHdlIGNhbiBmdXJ0aGVyIGNsZWFuIGFuZCByZWZpbmUgdGhlc2UgcG90ZW50aWFsIGNpdGF0aW9ucyB3aXRoIHRoZSBgcHJlcGFyZWRfYnkoKWAgZnVuY3Rpb24sIHdoaWNoIHJlbW92ZXMgY29tbW9ubHktc2VlbiBsZWFkLWlucyB0byByZWZlcmVuY2VzICgncHJlcGFyZWQgZm9yL2J5JywgZXRjLikgdG8gaW1wcm92ZSBleGFjdCBtYXRjaGluZy4gIAoKYGBge3IgcHJlcGFyZWQgYnl9CmR0IDwtIHByZXBhcmVkX2J5KGR0LCB4ID0gJ2NvbnRhaW5lcicsIHkgPSAnYXV0aG9yJywgeiA9ICdwdWJsaXNoZXInKQpgYGAKCkFkZGl0aW9uYWxseSwgd2UgZGlzYW1iaWd1YXRlIHRoZSBqb3VybmFscyB3aXRoIHRoZSBgam91cm5hbF9kaXNhbWJpZygpYCBmdW5jdGlvbiwgd2hpY2ggcmVmZXJlbmNlcyBpbmRpY2VzIG9mIGNvbW1vbiBqb3VybmFsIGFiYnJldmlhdGlvbnMgYW5kIHRocm91Z2ggbWFudWFsIGNsZWFuaW5nIG9mIGpvdXJuYWxzIHJlZmVyZW5jZWQgaW4gdHJhbnNwb3J0YXRpb24gZG9jdW1lbnRzLiAgCgpgYGB7ciBqb3VybmFsIGRpc2FtfQpkdCRjb250YWluZXIgPC0gam91cm5hbF9kaXNhbWJpZyhkdCRjb250YWluZXIpCmBgYAoKIyMjIyBgcmVnZXhfY2xhc3NpZnkoKWAgIAoKTm93IHdpdGggcHJvYmFibGUgcmVmZXJlbmNlcyBhcyAnY2xlYW4nIGFzIHBvc3NpYmxlLCB3ZSB1c2UgcmVndWxhciBleHByZXNzaW9ucyB0byBjbGFzc2lmeSBvdXIgZGF0YSBiYXNlZCBvbiBleGFjdCBtYXRjaGVzIHVzaW5nIHRoZSBgcmVnZXhfY2xhc3NpZnkoKWAgZnVuY3Rpb24uIFRoaXMgZnVuY3Rpb24gZG9lcyB0d28gdGhpbmdzLiBGaXJzdCBpdCBsb29rcyBhY3Jvc3MgYWxsIG9mIHRoZSBjb2x1bW5zIGZvciBleGFjdCBtYXRjaGVzIHRvIG91ciBpbmRpY2VzLCBhbmQgaWYgdGhlcmUgaXMgYW4gZXhhY3QgbWF0Y2gsIGl0IHB1bGxzIG91dCB0aGF0IHZhbHVlIGludG8gYSAnaW5wdXQnIGNvbHVtbi4gSWYgdGhlcmUgaXMgbm8gZXhhY3QgbWF0Y2gsIHRoZSB2YWx1ZSBpbiB0aGUgaW5wdXQgY29sdW1uIHdpbGwgYmUgc2VsZWN0ZWQgaW4gdGhlIGZvbGxvd2luZyBvcmRlciBvZiBwcmVmZXJlbmNlOiBkb2ksIGNvbnRhaW5lciwgcHVibGlzaGVyLCB0aXRsZSwgYXV0aG9yLiBTZWNvbmQsIGJhc2VkIG9uIHRoZSBtYXRjaGVzIHRoZSBmdW5jdGlvbiB3aWxsIGFzc2lnbiB0aGUgcG90ZW50aWFsIGNpdGF0aW9uIGludG8gb25lIG9mIGZvdXIgY2xhc3Nlczogam91cm5hbCwgYWdlbmN5LCBjb25mZXJlbmNlLCBvciBub25lLiBJZiBub25lIG9mIHRoZSBwb3RlbnRpYWwgY2l0YXRpb25zJyBkYXRhIGlzIGFuIGV4YWN0IG1hdGNoIHRvIGFueSBvZiB0aGUgaW5kaWNlcywgdGhlIGNsYXNzaWZpY2F0aW9uIGlzIE5BLiAKCmBgYHtyIHJlZ2V4IGNsYXNzaWZ5fQojIEV4dHJhY3QgbW9zdCBkZXNjcmlwdGl2ZSAnaW5wdXQnIGFuZCBsb29rIGZvciBleGFjdCBtYXRjaCB0byBpbmRleCAKZHQgPC0gcmVnZXhfY2xhc3NpZnkoZHQsICdjb250YWluZXInKQpgYGAKCjwhLS0tIFNvIGJlbG93IEkgYW0gcHVsbGluZyBvdXQgdGhlIGV4YWN0IG1hdGNoZXMgZm9yIGFnZW5jaWVzIGludG8gdGhlaXIgb3duIGNvbHVtbi4gUmlnaHQgbm93IHRoZSBmdW5jdGlvbiBkb2VzIG5vdCBwdWxsIG91dCB0aGUgYWdlbmN5IHBlciBzZSwgaXQganVzdCB0YWdzIHdoZXRoZXIgb3Igbm90IGl0IHNlZXMgYSBtYXRjaCBpbnNpZGUgdGhlIGNvbHVtbnMgc3BlY2lmaWVkIGluIHRoZSBmdW5jdGlvbi4gU28gYmVsb3cgSSBhbSBkb2luZyBpdCBtYW51YWxseSwgYnV0IHRoaXMgc2hvdWxkIGJlIGJ1aWx0IGluIC0tLT4KCmBgYHtyIGV4YWN0IG1hdGNoIGFnZW5jaWVzLCBlY2hvID0gRiwgZXZhbCA9IEZ9CmRhdGEoImFnZW5jaWVzIikKeCA9IGR0JHRyYWluaW5nX2lucHV0W2R0JGNsYXNzID09ICJhZ2VuY3kiICYgIWlzLm5hKGR0JGNsYXNzKV0KYWJiciA8LSBhZ2VuY2llcyRBYmJyW2FnZW5jaWVzJEFiYnIgIT0gIiJdCnkgPSBjKGFnZW5jaWVzJEFnZW5jeSwgYWJicikKCmR0X2FnZW5jaWVzIDwtIGZpbHRlcihkdCwgY2xhc3MgPT0gImFnZW5jeSIgJiAhaXMubmEoY2xhc3MpKSAlPiUgCiAgc2VsZWN0KElELCB0cmFpbmluZ19pbnB1dCkKZHRfYWdlbmNpZXMkYWdlbmN5ID0gTkEKdDEgPC0gU3lzLnRpbWUoKQpmb3IoaSBpbiAxOmxlbmd0aCh4KSl7CiAgZm9yKGogaW4gMTpsZW5ndGgoeSkpewogICAgbWF0Y2ggPC0gc3RyX2V4dHJhY3QoeFtpXSwgeVtqXSkKICBpZighaXMubmEobWF0Y2gpKXsKICBkdF9hZ2VuY2llcyRhZ2VuY3lbaV0gPC0gbWF0Y2gKICB9CiAgfQogICAgaWYoIWlzLm5hKG1hdGNoKSl7CiAgICAgIG5leHQKICB9Cn0KdDIgPC0gU3lzLnRpbWUoKQp0Mi10MSAKCmR0IDwtIGxlZnRfam9pbihkdCwgZHRfYWdlbmNpZXMpCmR0JGFnZW5jeSA8LSBpZmVsc2UoZHQkYWdlbmN5ID09ICJHZW9sb2dpY2FsIFN1cnZleSIsIAogICAgICAgICAgICAgICAgICAgICJVUyBHZW9sb2dpY2FsIFN1cnZleSIsIGR0JGFnZW5jeSkKZHQkYWdlbmN5IDwtIGlmZWxzZShkdCRhZ2VuY3kgPT0gIkFybXkiLCAKICAgICAgICAgICAgICAgICAgICAiVVMgQXJteSIsIGR0JGFnZW5jeSkKZHQkYWdlbmN5IDwtIGlmZWxzZShkdCRhZ2VuY3kgPT0gIkFybXkgQ29ycHMgb2YgRW5naW5lZXJzIiwgCiAgICAgICAgICAgICAgICAgICAgIlVTIEFybXkgQ29ycHMgb2YgRW5naW5lZXJzIiwgZHQkYWdlbmN5KQpkdCRhZ2VuY3kgPC0gaWZlbHNlKGR0JGFnZW5jeSA9PSAiQnVyZWF1IG9mIFJlY2xhbWF0aW9uIiwgCiAgICAgICAgICAgICAgICAgICAgIlVTIEJ1cmVhdSBvZiBSZWNsYW1hdGlvbiIsIGR0JGFnZW5jeSkKZHQkYWdlbmN5IDwtIGlmZWxzZShkdCRhZ2VuY3kgPT0gIkNlbnN1cyBCdXJlYXUiLCAKICAgICAgICAgICAgICAgICAgICAiVVMgQ2Vuc3VzIEJ1cmVhdSIsIGR0JGFnZW5jeSkKZHQkYWdlbmN5IDwtIGlmZWxzZShkdCRhZ2VuY3kgPT0gIkRlcGFydG1lbnQgb2YgQWdyaWN1bHR1cmUiLCAKICAgICAgICAgICAgICAgICAgICAiVVMgRGVwYXJ0bWVudCBvZiBBZ3JpY3VsdHVyZSIsIGR0JGFnZW5jeSkKZHQkYWdlbmN5IDwtIGlmZWxzZShkdCRhZ2VuY3kgPT0gIkRlcGFydG1lbnQgb2YgSGVhbHRoIGFuZCBIdW1hbiBTZXJ2aWNlcyIsIAogICAgICAgICAgICAgICAgICAgICJVUyBEZXBhcnRtZW50IG9mIEhlYWx0aCBhbmQgSHVtYW4gU2VydmljZXMiLCBkdCRhZ2VuY3kpCmR0JGFnZW5jeSA8LSBpZmVsc2UoZHQkYWdlbmN5ID09ICJEZXBhcnRtZW50IG9mIHRoZSBJbnRlcmlvciIsIAogICAgICAgICAgICAgICAgICAgICJVUyBEZXBhcnRtZW50IG9mIHRoZSBJbnRlcmlvciIsIGR0JGFnZW5jeSkKZHQkYWdlbmN5IDwtIGlmZWxzZShkdCRhZ2VuY3kgPT0gIkVudmlyb25tZW50YWwgUHJvdGVjdGlvbiBBZ2VuY3kiLCAKICAgICAgICAgICAgICAgICAgICAiVVMgRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSIsIGR0JGFnZW5jeSkKZHQkYWdlbmN5IDwtIGlmZWxzZShkdCRhZ2VuY3kgPT0gIkZpc2ggYW5kIFdpbGRsaWZlIFNlcnZpY2UiLCAKICAgICAgICAgICAgICAgICAgICAiVVMgRmlzaCBhbmQgV2lsZGxpZmUgU2VydmljZSIsIGR0JGFnZW5jeSkKZHQkYWdlbmN5IDwtIGlmZWxzZShkdCRhZ2VuY3kgPT0gIkZvcmVzdCBTZXJ2aWNlIiwgCiAgICAgICAgICAgICAgICAgICAgIlVTIEZvcmVzdCBTZXJ2aWNlIiwgZHQkYWdlbmN5KQpzYXZlUkRTKGR0LCAndmlnbmV0dGVzL2dzcF92aWduZXR0ZV9maWxlcy9kYXRhL2R0X3dpdGhhZ2VuY2llcy5yZHMnKQpgYGAKCmBgYHtyLCBlY2hvID0gRn0KZHQgPC0gcmVhZFJEUygncG9zdHMvZ3NwX3ZpZ25ldHRlX2ZpbGVzL2RhdGEvZHRfd2l0aGFnZW5jaWVzLnJkcycpCmBgYAoKQmFzZWQgb24gdGhlc2UgY2xhc3NpZmljYXRpb25zLCB3ZSBjYW4gc2VlIHRoZSBjb3VudHMgb2YgZXhhY3QgbWF0Y2hlcywgYW5kIHdoaWNoIG9uZXMgaGF2ZSBub3QgYmVlbiBjbGFzc2lmaWVkLiAgIAoKYGBge3IsIGVjaG8gPSBGLCBmaWcuYWxpZ24gPSAnY2VudGVyJywgcmVzdWx0cyA9ICdhc2lzJ30KdGFibGUgPC0gZGF0YS5mcmFtZSgibiIgPSBjKHRhYmxlKGR0JGNsYXNzKSwgdGFibGUoaXMubmEoZHQkY2xhc3MpKVsyXSkpCnRhYmxlJGNsYXNzIDwtIGMoIkFnZW5jeSIsICJDb25mZXJlbmNlIiwgIkpvdXJuYWwiLCAiTm90IGEgY2l0YXRpb24iLCAiVW5jbGFzc2lmaWVkIikKbGlicmFyeShrYWJsZUV4dHJhKQprYWJsZShwaXZvdF93aWRlcih0YWJsZSwgbmFtZXNfZnJvbSA9IGNsYXNzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBuKSwgYm9va3RhYnMgPSBULCBhbGlnbiA9ICdjJykgJT4lIAogIGthYmxlX3N0eWxpbmcoKQpgYGAKCiMjIyMgYGtlcmFzX2NsYXNzaWZ5KClgICAKCk5leHQgd2Ugd2FudCB0byBjbGFzc2lmeSB0aGUgcHJvYmFibGUgcmVmZXJlbmNlcyB0aGF0IGFyZSBub3QgZXhhY3QgbWF0Y2hlcyB0byBhbnkgb2Ygb3VyIGluZGljZXMuIFRvIGRvIHRoaXMsIHdlIHVzZSBga2VyYXNfY2xhc3NpZnkoKWAsIGluIHdoaWNoIHdlIGlucHV0IG91ciBwcm9iYWJsZSByZWZlcmVuY2VzIGludG8gYSBuZXVyYWwgbmV0d29yayB0cmFpbmVkIHRvIHByZWRpY3QgdGhlIHJlZmVyZW5jZSBjbGFzcy4gVG8gdHJhaW4gdGhpcyBtb2RlbCwgd2UgdXNlZCBkYXRhIGZyb20gRW52aXJvbm1lbnRhbCBJbXBhY3QgU3RhdGVtZW50cywgY2xhc3NpZmllZCB0aHJvdWdoIGJvdGggbWFudWFsIGNsYXNzaWZpY2F0aW9uIGFuZCB0aGUgc2VtaS1hdXRvbWF0ZWQgcmVnZXggY2xhc3NpZmljYXRpb24gZXhwbGFpbmVkIGFib3ZlLiAgCgpgYGB7ciBrZXJhcywgZXZhbCA9IEZ9CiMgVXNlIHRoZSBkZXNjcmlwdGl2ZSAnaW5wdXQnIHRvIHByb2JhYmlsaXN0aWNhbGx5IGlkZW50aWZ5IHRoZSByZWZlcmVuY2UgY2xhc3MKc2V0d2QoIn4vRG9jdW1lbnRzL0RhdmlzL1ItUHJvamVjdHMvcmVmZXJlbmNlQ2xhc3NpZnkvIikKcHJlZGljdGlvbnMgPC0ga2VyYXNfY2xhc3NpZnkoZHQsIHByb2JhYmlsaXR5ID0gLjg1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbnRhaW5lcicsIGF1dG9faW5wdXQgPSBGLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHJhaW5pbmdfaW5wdXQnKSAKZHQgPC0gY2JpbmQoZHQsIHNlbGVjdChwcmVkaWN0aW9ucywgcHJlZGljdF9jbGFzcykpCmBgYAoKYGBge3IgbG9hZCBwb3N0IGtlcmFzIGR0IGNvdmVydCwgZWNobyA9IEZ9CiNzYXZlUkRTKGR0LCAidmlnbmV0dGVzL2dzcF92aWduZXR0ZV9maWxlcy9kYXRhL2R0X3Bvc3Rfa2VyYXMuUkRTIikKZHQgPC0gcmVhZFJEUygicG9zdHMvZ3NwX3ZpZ25ldHRlX2ZpbGVzL2RhdGEvZHRfcG9zdF9rZXJhcy5SRFMiKQpgYGAKCkJlY2F1c2Ugd2UgcmFuIHRoaXMgbW9kZWwgb24gdGhlIHdob2xlIGRhdGEgZnJhbWUsIHdlIGNhbiBjb21wYXJlIG91ciByZWdleCBjbGFzc2lmaWNhdGlvbiB3aXRoIHRoZSBLZXJhcyBjbGFzc2lmaWNhdGlvbnMgdG8gZ2V0IGEgc2Vuc2Ugb2YgdGhlIG1vZGVsIHBlcmZvcm1hbmNlLiAgCgpgYGB7ciwgZWNobyA9IEYsIGZpZy5hbGlnbj0nY2VudGVyJ30KZHQgPC0gZHQgJT4lIAogIG11dGF0ZShjbGFzcyA9IGNhc2Vfd2hlbigKICAgICAgICAgICBjbGFzcyA9PSAicmVtb3ZlX3JvdyIgfiAiZGVsZXRlIiwKICAgICAgICAgICBUIH4gY2xhc3MpLAogICAgICAgICBtZXRob2QgPSBjYXNlX3doZW4oCiAgICAgICAgICAgaXMubmEoY2xhc3MpIH4gImtlcmFzIiwKICAgICAgICAgICBUIH4gInJlZ2V4IiksCiAgICAgICAgIG1ldGhvZF9jb21wYXJpc29uID0gY2FzZV93aGVuKAogICAgICAgICAgIG1ldGhvZCA9PSAicmVnZXgiICYgY2xhc3MgPT0gcHJlZGljdF9jbGFzcyB+ICJtYXRjaCIsCiAgICAgICAgICAgbWV0aG9kID09ICJyZWdleCIgJiBwcmVkaWN0X2NsYXNzID09ICJ1bnN1cmUiIH4gInVuc3VyZSIsCiAgICAgICAgICAgbWV0aG9kID09ICJyZWdleCIgJiBjbGFzcyAhPSBwcmVkaWN0X2NsYXNzIH4gImluY29ycmVjdCIsCiAgICAgICAgICAgVCB+IE5BX2NoYXJhY3Rlcl8pKQoKdGFibGUgPC0gZGF0YS5mcmFtZSh0YWJsZShkdCRtZXRob2RfY29tcGFyaXNvbikpICU+JSBzZWxlY3QoLVZhcjEpCnRhYmxlJGNsYXNzIDwtIGMoIkluY29ycmVjdCIsICJNYXRjaCIsICJDbGFzc2lmaWVkIGFzIHVuc3VyZSIpCmthYmxlKHBpdm90X3dpZGVyKHRhYmxlLCBuYW1lc19mcm9tID0gY2xhc3MsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IEZyZXEpLCBib29rdGFicyA9IFQsIGFsaWduID0gJ2MnKSAlPiUgCiAga2FibGVfc3R5bGluZygpCmBgYAoKVGhlc2UgcmVzdWx0cywgYWx0b2dldGhlciwgc3VnZ2VzdCB0aGF0IHRoZSBLZXJhcyBtb2RlbCBpcyBgciAxMDAqcm91bmQodGFibGUoZHQkbWV0aG9kX2NvbXBhcmlzb24pW1syXV0vc3VtKHRhYmxlKGR0JG1ldGhvZF9jb21wYXJpc29uKSksMilgJSBhY2N1cmF0ZSBpbiBpdHMgcHJlZGljdGlvbiBvZiB0aGUgY2l0YXRpb25zIHdlIGFyZSBhYmxlIHRvIGRvIGV4YWN0IG1hdGNoaW5nIGZvci4gTm93LCBsZXQncyB1bmlmeSB0aGUgY2xhc3NpZmljYXRpb24gY29sdW1ucyBhbmQgaGF2ZSBhIGxvb2sgYXQgdGhlIHRvdGFsIGZvciBlYWNoIGVzdGltYXRlZCBncm91cGluZy4gICAKCmBgYHtyLCBlY2hvID0gRiwgZmlnLmFsaWduPSdjZW50ZXInfQpkdCRjbGFzcyA8LSBpZmVsc2UoaXMubmEoZHQkY2xhc3MpLCBkdCRwcmVkaWN0X2NsYXNzLCBkdCRjbGFzcykKdGFibGUgPC0gZGF0YS5mcmFtZSh0YWJsZShkdCRjbGFzcykpICU+JSBzZWxlY3QoLVZhcjEpCnRhYmxlJGNsYXNzIDwtIGMoIkFnZW5jeSIsICJDb25mZXJlbmNlIiwgIk5vdCBhIGNpdGF0aW9uIiwKICAgICAgICAgICAgICAgICAiSm91cm5hbCIsICJVbnN1cmUiKQprYWJsZShwaXZvdF93aWRlcih0YWJsZSwgbmFtZXNfZnJvbSA9IGNsYXNzLCB2YWx1ZXNfZnJvbSA9IEZyZXEpLCAKICAgICAgICAgICAgICAgICAgYm9va3RhYnMgPSBULCBhbGlnbiA9ICdjJykgICU+JSAKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpBbmQgd2UnbGwgdGlkeSB1cCB0aGVzZSBkYXRhIGJ5IGZpbHRlcmluZyBvdXQgdGhlIGNpdGF0aW9ucyBjbGFzc2lmaWVkIGludG8gJ2RlbGV0ZScgKHRoZSBmYWxzZSBwb3NpdGl2ZXMpIGluIHByZXBhcmF0aW9uIGZvciBvdXIgaW5kZXhpbmcgaW4gdGhlIG5leHQgc3RlcC4gICAKYGBge3J9CmR0IDwtIGR0ICU+JSAKICBzZWxlY3QoLWMocHJlZGljdF9jbGFzcywgbWV0aG9kX2NvbXBhcmlzb24pKSAlPiUgCiAgZmlsdGVyKGNsYXNzICE9ICJkZWxldGUiKQpgYGAKCiMjIyMgSW50ZXJpbSBjaGVjayBpbjogSm91cm5hbHMgYW5kIGFnZW5jaWVzIGZyb20gZXhhY3QgbWF0Y2hpbmcgICAKClNvIGZhciwgd2UndmUgaWRlbnRpZmllZCBleGFjdCBtYXRjaGVzIHRvIG91ciBoaWdoLWxldmVsIGluZGljZXMgKGpvdXJuYWwsIGFnZW5jeSwgY29uZmVyZW5jZSkgYW5kIHRoZW4gdXNlZCBtYWNoaW5lIGxlYXJuaW5nIHRvIGNsYXNzaWZ5IGNpdGF0aW9ucyB0aGF0IGFyZSBub3QgZXhhY3QgbWF0Y2hlcyBzbyB0aGF0IHdlIGNhbiBiZWdpbiB0byBmaWd1cmUgb3V0IHRoZWlyIHNvdXJjZS4gQXQgdGhpcyBpbnRlcmltIHN0YWdlLCB3ZSBjYW4gdGFrZSBhIGxvb2sgYXQgdGhlIGhpZ2gtbGV2ZWwgY2xhc3NpZmljYXRpb25zIGFjcm9zcyBjaXRhdGlvbnMsIGFuZCB0aGUgam91cm5hbHMgYW5kIGFnZW5jaWVzIGZvciB3aGljaCB3ZSd2ZSBmb3VuZCBleGFjdCBtYXRjaGVzLiAgCgpGaXJzdCwgbGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIGhpZ2gtbGV2ZWwgbWF0Y2hlcy4gQSByZWZlcmVuY2UgbGlzdCB3YXMgcmVxdWlyZWQgYnkgRFdSIGZvciBHU1BzLCBhbmQgaW5kZWVkIHdlIHNlZSB0aGF0IGFsbCBgciBsZW5ndGgodW5pcXVlKGR0JEZpbGVbZHQkY2xhc3MgJWluJSBjKCJqb3VybmFsIiwgImFnZW5jeSIpXSkpYCBvZiB0aGUgZG9jdW1lbnRzIGhhdmUgcmVmZXJlbmNlcyB0aGF0IHdlIGNhbiBpZGVudGlmeSBhcyBlaXRoZXIgYSBzY2hvbGFybHkgam91cm5hbCBvciBhZ2VuY3kuIEJhc2VkIG9uIG91ciB0b29sJ3MgcHJvYmFiaWxpc3RpYyB0YWdzLCBpdCBsb29rcyBsaWtlIHRoZSBudW1iZXIgb2YgcmVmZXJlbmNlcyByYW5nZXMgZnJvbSAxIHRvIDEyOCwgd2l0aCAyNCBiZWluZyB0aGUgYXZlcmFnZSBudW1iZXIgb2YgY2xhc3NpZmllZCByZWZlcmVuY2VzLiBUaGF0IGF2ZXJhZ2UgZGlmZmVycyBiZXR3ZWVuIHJlZmVyZW5jZXMgY2xhc3Nlcywgd2hlcmVieSB0aGUgYXZlcmFnZSBudW1iZXIgb2Ygam91cm5hbCByZWZlcmVuY2VzIGlzIDE2IGFuZCB0aGUgYXZlcmFnZSBudW1iZXIgb2YgYWdlbmN5IHJlZmVyZW5jZXMgaXMgdHdpY2UgdGhhdCwgYXQgMzIuIEluIHRvdGFsLCB0aGVyZSBhcmUgMSw4NjUgam91cm5hbCByZWZlcmVuY2VzIGFuZCAzLDY3NSBhZ2VuY3kgcmVmZXJlbmNlcy4gIAoKYGBge3Igc3VtbWFyaWVzIG9mIHJlZmVyZW5jZXMsIGVjaG8gPSBGLCByZXN1bHRzID0gRn0KYnlfZG9jIDwtIGR0ICU+JSAKICBmaWx0ZXIoY2xhc3MgJWluJSBjKCJqb3VybmFsIiwgImFnZW5jeSIpKSAlPiUgCiAgZ3JvdXBfYnkoRmlsZSwgY2xhc3MpICU+JSAKICBjb3VudCgpICU+JSAKICB1bmdyb3VwKCkgCgpzdW1tYXJ5KGJ5X2RvYyRuKQoKYnlfZG9jICU+JSAKICBncm91cF9ieShjbGFzcykgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihuKSwKICAgICAgICAgICAgbWluID0gbWluKG4pLAogICAgICAgICAgICBtYXggPSBtYXgobikpCgpkdCAlPiUgCiAgZmlsdGVyKGNsYXNzICVpbiUgYygiam91cm5hbCIsICJhZ2VuY3kiKSkgJT4lIAogIGdyb3VwX2J5KGNsYXNzKSAlPiUgCiAgY291bnQoKQpgYGAKCk9mIHRoZXNlIHJlZmVyZW5jZXMsIHdlIGRpc3BsYXkgdGhlIHRvcCAxNSByZWZlcmVuY2VzIHRvIGpvdXJuYWxzIGFuZCBhZ2VuY2llcyBpZGVudGlmaWVkIGJ5IG91ciBleGFjdCBtYXRjaGluZyBzdHJhdGVnaWVzLiBBdCBhIGdsYW5jZSwgd2Ugc2VlIGEgc3Ryb25nIHJlcHJlc2VudGF0aW9uIG9mIGdlb2xvZ2ljYWwsIGh5ZHJvbG9naWNhbCwgYW5kIGFncmljdWx0dXJhbCBzY2llbmNlIGluIGJvdGggdGhlIGpvdXJuYWxzIGFuZCBhZ2VuY3kgcmVwcmVzZW50YXRpb24uIEFtb25nIGFnZW5jaWVzLCByZWZlcmVuY2VzIHRvIFVTR1MgYXJlIGV4Y2VwdGlvbmFsbHkgbGFyZ2UsIG1vcmUgdGhhbiB0aHJlZSB0aW1lcyB0aGF0IG9mIHRoZSBzZWNvbmQgbW9zdC1yZWZlcmVuY2VkIGFnZW5jeS4gIAoKYGBge3Igd3JhbmdsZSBkYXRhIGZvciBwbG90cywgZWNobyA9IEZ9CmRhdGEoInNjaW1hZ28uaiIpCiMgR2V0IG1ldGFkYXRhIHRvIGJlIGEgc3VtbWFyaXplIG9mIApqb3VybmFsX21ldGFkYXRhIDwtIGRhdGEuZnJhbWUoc2pyZGF0YTo6c2pyX2pvdXJuYWxzKSAlPiUgCiAgZ3JvdXBfYnkoc291cmNlaWQsIHRpdGxlKSAlPiUgCiAgc3VtbWFyaXplKHNqcl9hdmcgPSBtZWFuKHNqciwgbmEucm0gPSBUKSkgJT4lIAogIHJpZ2h0X2pvaW4oc2VsZWN0KGRhdGEuZnJhbWUoc2pyZGF0YTo6c2pyX2pvdXJuYWxzKSwgc291cmNlaWQsIHRpdGxlLCBjYXRlZ29yaWVzKSkgJT4lIAogIHNlcGFyYXRlKGNhdGVnb3JpZXMsIGludG8gPSBwYXN0ZTAoImNhdCIsIDE6MTUpLCBzZXAgPSAiOyIpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGNhdDE6Y2F0MTUsIAogICAgICAgICAgICAgICBuYW1lc190byA9ICJudW1iZXIiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiY2F0IikgJT4lIAogIGZpbHRlcighaXMubmEoY2F0KSkgJT4lIAogIG11dGF0ZShjYXQgPSB0cmltd3Moc3RyX3JlbW92ZV9hbGwoY2F0LCAnXFwoUVxcZFxcKScpKSkgJT4lIAogIG11dGF0ZShjYXQgPSB0cmltd3Moc3RyX3JlbW92ZV9hbGwodG9sb3dlcihjYXQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1xcKG1pc2NlbGxhbmVvdXNcXCl8LHwtJykpKSAlPiUgCiAgc2VsZWN0KC1udW1iZXIpICU+JSAKICB1bmlxdWUoKSAlPiUgCiAgcmVuYW1lKCJqb3VybmFsX3RpdGxlIiA9ICJ0aXRsZSIpICU+JSAKICBncm91cF9ieShzb3VyY2VpZCwgam91cm5hbF90aXRsZSwgc2pyX2F2ZykgJT4lIAogIG11dGF0ZShudW1iZXIgPSBwYXN0ZTAoJ2NhdCcsIDE6bigpKSkgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKHNvdXJjZWlkLCBqb3VybmFsX3RpdGxlLCBzanJfYXZnKSwKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gIm51bWJlciIsIHZhbHVlc19mcm9tID0gImNhdCIpICU+JSAKICB1bmlxdWUoKQoKZHRfYWdlbmNpZXMgPC0gZHQgJT4lIAogIGZpbHRlcihjbGFzcyA9PSAiYWdlbmN5IikgCgpkdF9qb3VybmFscyA8LSBkdCAlPiUgCiAgZmlsdGVyKGNsYXNzID09ICJqb3VybmFsIiAmICFpcy5uYShjb250YWluZXIpKSAlPiUgCiAgbGVmdF9qb2luKHNjaW1hZ28uaiwgYnkgPSBjKCJjb250YWluZXIiID0gInRpdGxlIikpICU+JSAKICBsZWZ0X2pvaW4oam91cm5hbF9tZXRhZGF0YSwgYnkgPSAic291cmNlaWQiKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShzb3VyY2VpZCkpCgpkdF9qb3VybmFscyRjb250YWluZXJbZHRfam91cm5hbHMkY29udGFpbmVyID09ICJQcm9jZWVkaW5ncyBvZiB0aGUgTmF0aW9uYWwgQWNhZGVteSBvZiBTY2llbmNlcyBvZiB0aGUgVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIl0gPC0gIlBOQVMiCgpgYGAKCmBgYHtyLCBlY2hvID0gRn0KbGlicmFyeShnZ3Bsb3QyKQpwX2pvdXIgPC0gZHRfam91cm5hbHMgJT4lIAogIGdyb3VwX2J5KGNvbnRhaW5lcikgJT4lIAogIGNvdW50KCkgJT4lIAogIGFycmFuZ2UobikgJT4lIAogIGZpbHRlcihuID4gMTMpICU+JSAKICBtdXRhdGUoY29udGFpbmVyID0gZmFjdG9yKGNvbnRhaW5lciwgbGV2ZWxzID0gLiRjb250YWluZXIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29udGFpbmVyLCB5ID0gbikpICsKICBnZW9tX2NvbChmaWxsID0gIiMwMzk4OWUiKSArCiAgbGFicyh5ID0gIkNvdW50IiwgeCA9ICIiLCB0aXRsZSA9ICJUb3AgcmVmZXJlbmNlZCBqb3VybmFscyIpICsKICBjb29yZF9mbGlwKCkgKwogIHRoZW1lX2dvdnVzZXIoYmFzZV9zaXplID0gMTApCgpwX2FnZW5jeSA8LSBkdF9hZ2VuY2llcyAlPiUgCiAgZ3JvdXBfYnkoYWdlbmN5KSAlPiUgCiAgZmlsdGVyKCFpcy5uYShhZ2VuY3kpKSAlPiUgCiAgY291bnQoKSAlPiUgCiAgYXJyYW5nZShuKSAlPiUgCiAgZmlsdGVyKG4gPiAxNSkgJT4lIAogIG11dGF0ZShhZ2VuY3kgPSBmYWN0b3IoYWdlbmN5LCBsZXZlbHMgPSAuJGFnZW5jeSkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhZ2VuY3ksIHkgPSBuKSkgKwogIGdlb21fY29sKGZpbGwgPSAiIzAzOTg5ZSIpICsKICBsYWJzKHkgPSAiQ291bnQiLCB4ID0gIiIsIHRpdGxlID0gIlRvcCByZWZlcmVuY2VkIGFnZW5jaWVzIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfZ292dXNlcihiYXNlX3NpemUgPSAxMCkKYGBgCgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTMsIGVjaG8gPSBGfQpjb3dwbG90OjpwbG90X2dyaWQocF9qb3VyLCBwX2FnZW5jeSwgcmVsX3dpZHRocyA9IGMoMSwgMS4wNSkpCmBgYAoKUmVnYXJkaW5nIHRoZSBpbXBhY3QgZmFjdG9yIG9mIGFjYWRlbWljIHJlZmVyZW5jZXMsIHdlIHNlZSB2ZXJ5IGxpdHRsZSBldmlkZW5jZSBmb3IgaGlnaC1pbXBhY3Qgam91cm5hbHMgYWNjb3VudGluZyBmb3IgbW9yZSBjaXRhdGlvbnMuIFdoaWxlIF9TY2llbmNlXywgb25lIG9mIHRoZSBoaWdoZXIgaW1wYWN0IGpvdXJuYWxzICgxMi42IFNKUiBzY29yZSksIGlzIGFtb25nIHRoZSB0b3AgMTUgam91cm5hbHMsIHRoZSByZW1haW5pbmcgMTQgYXZlcmFnZSBhbiBTSlIgc2NvcmUgb2YgMi4gIAoKYGBge3IsIGVjaG8gPSBGLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTMsIG91dC53aWR0aD0gJzUwJSd9CmR0X2pvdXJuYWxzICU+JSAKICBncm91cF9ieShqb3VybmFsX3RpdGxlLCBzanJfYXZnKSAlPiUgCiAgY291bnQoKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzanJfYXZnLCB5ID0gbikpICsKICBnZW9tX3BvaW50KGFscGhhID0gLjUpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nLCBjb2xvciA9ICIjMDM5ODllIikgKwogIGxhYnMoeCA9ICdKb3VybmFsIGltcGFjdCBmYWN0b3InLCB5ID0gJ051bWJlciBvZiBjaXRhdGlvbnMnKSArCiAgdGhlbWVfZ292dXNlcihiYXNlX3NpemUgPSAxMCkKYGBgCgoKIyMjIDMuIGBpbmRleEJ1aWxkYCAgCgpOb3cgdGhhdCB3ZSBoYXZlIGEgZ2VuZXJhbCBzZW5zZSBvZiB0aGUga2luZHMgb2YgcmVmZXJlbmNlIHR5cGVzIHRoYXQgYXJlIHJlcHJlc2VudGVkIHdpdGhpbiB0aGUgcHJvYmFibGUgcmVmZXJlbmNlcywgdGhlIG5leHQgc3RlcCBpcyB0byB0cnkgdG8gaW5kZXggdGhlc2UgcmVmZXJlbmNlIGV4YWN0bHkuIFRoZSBgaW5kZXhCdWlsZGAgcGFja2FnZSBpcyBkZXNpZ25lZCB0byBxdWVyeSB0aGUgW29wZW5BbGV4IEFQSV0oaHR0cHM6Ly9kb2NzLm9wZW5hbGV4Lm9yZy8pLCBhbiBvcGVuIGFjY2VzcyBjYXRhbG9nIG9mIHJlc2VhcmNoLCBpbiBvcmRlciB0byBidWlsZCBhIHBlcnNvbmFsaXplZCBjYXRhbG9nIHJlbGV2YW50IHRvIHRoZSBmaWVsZCBvZiByZXNlYXJjaC4gVGhpcyBzdGVwIGlzIG9wdGlvbmFsIGZvciB0aGUgYGdvdnNjaWVuY2V1c2VSYCB3b3JrZmxvdywgYXMgdGhlIHRvb2wga2l0IHByb3ZpZGVzIGEgZGVmYXVsdCBpbmRleCB3aXRoIFtkZWZpbmUgZGVmYXVsdCBpbmRleCBvbmNlIGl0IGlzIGNyZWF0ZWRdLiBIb3dldmVyLCBidWlsZGluZyBhbiBpbmRleCBmb3IgYSBnaXZlbiByZXNlYXJjaCBwcm9qZWN0IHdpbGwgbGlrZWx5IGluY3JlYXNlIHRoZSBtYXRjaGluZyBhYmlsaXRpZXMgb2YgdGhlIHRvb2wuICAKCiMjIyMgSWRlbnRpZnkgaW5kZXggY29uY2VwdHMgIAoKYGBge3IsIGVjaG8gPSBGfQp0aGVtZXMgPC0gZHRfam91cm5hbHMgJT4lIAogIHNlbGVjdChzb3VyY2VpZCwgam91cm5hbF90aXRsZSwgY2F0MTpjYXQxMykgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gY2F0MTpjYXQxMywgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIm51bWJlciIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJjYXQiKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShjYXQpKSAlPiUgCiAgZ3JvdXBfYnkoY2F0KSAlPiUgCiAgY291bnQoKSAlPiUgCiAgYXJyYW5nZShuKQpgYGAKClRvIGJ1aWxkIGFuIGluZGV4LCB3ZSBmaXJzdCBuZWVkIHRvIGRlZmluZSB0aGUgc2NvcGUuIG9wZW5BbGV4IGFsbG93cyBpbmRpY2VzIHRvIGJlIGJ1aWx0IGJhc2VkIG9uIGZpdmUgZGlmZmVyZW50IHR5cGVzIG9mIGVudGl0aWVzOiBhdXRob3JzLCBpbnN0aXR1dGlvbnMsIHZlbnVlcywgY29uY2VwdHMsIGFuZCB3b3Jrcy4gV2UgY2hvb3NlIHRvIGJ1aWxkIG91ciBpbmRleCBiYXNlZCBvbiBjb25jZXB0cywgYXMgdGhpcyBjYXN0cyB0aGUgd2lkZXN0IGFuZCBtb3N0IGluY2x1c2l2ZSBuZXQuIFRvIGlkZW50aWZ5IGNvbmNlcHRzLCB3ZSB1c2UgdGhlIGpvdXJuYWxzIGFscmVhZHkgaWRlbnRpZmllZCBpbiBvdXIgZGF0YS4gV2UgdGFrZSB0aGVzZSBqb3VybmFscycgZGlzY2lwbGluYXJ5IGNhdGVnb3J5IG1ldGFkYXRhIGZyb20gdGhlIFNjaW1hZ28gZGF0YWJhc2UgYXMgdXNlIHRoZXNlIHRvIHF1ZXJ5IHRoZSBjYXRlZ29yaWVzIGluIHRoZSBvcGVuQWxleCBkYXRhIGJhc2UuICAgQWNyb3NzIHRoZSBqb3VybmFscyBpZGVudGlmaWVkIGluIG91ciByZWZlcmVuY2VzIHRoZXJlIGFyZSBgciBucm93KHRoZW1lcylgIGRpc2NpcGxpbmFyeSBjYXRlZ29yaWVzIGFuZCB0aGUgdG9wIGNhdGVnb3JpZXMgYXJlIGRpc3BsYXllZCBiZWxvdy4gIAoKYGBge3IsIGVjaG8gPSBGfQpwX3RoZW1lIDwtIHRoZW1lcyAlPiUKICBtdXRhdGUoY2F0ID0gZmFjdG9yKGNhdCwgbGV2ZWxzID0gLiRjYXQpKSAlPiUgCiAgZmlsdGVyKG4gPiA0OCkgJT4lIAogIGdncGxvdChhZXMoeCA9IGNhdCwgeSA9IG4pKSArCiAgZ2VvbV9jb2woZmlsbCA9ICIjMDM5ODllIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh5ID0gIkNvdW50IiwgeCA9ICIiLCB0aXRsZSA9ICJUb3AgdGhlbWVzIGZyb20gam91cm5hbHMiKSArCiAgdGhlbWVfZ292dXNlcihiYXNlX3NpemUgPSAxMCkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodCA9IDMsIGZpZy53aWR0aCA9IDYsIGZpZy5hbGlnbj0nY2VudGVyJywgZWNobyA9IEYsb3V0LndpZHRoPSAnNTAlJ30KcF90aGVtZQpgYGAKPCEtLS1bQWxzbyBjb25zaWRlciB0YWtpbmcga2V5d29yZHM/IFRoaXMgaXMgbWFpbmx5IGJlY2F1c2UgZXZlbiB0aG91Z2ggJ3dhdGVyIHNjaWVuY2UgYW5kIHRlY2hub2xvZ3knIGlzIHRoZSBtYWluIHRoZW1lLCB0aGlzIGRvZXNuJ3QgbWF0Y2ggdG8gYW4gb3BlbkFsZXggY29uY2VwdCwgYW5kIHNvIEkgZGlkbid0IHdhbnQgdG8gbG9zZSBvdXQgb24gY29uY2VwdHMgbGlrZSAnd2F0ZXInLiBCdXQgdGhlbiBvcGVucyB1cCBhIHdob2xlIGxvbmcgbGlzdCBvZiB0aGluZ3MgSSdtIG5vdCBpbnRlcmVzdGVkIGluLCBhbmQgYmVjYXVzZSB0aGlzIGlzIGEgbWFzc2l2ZSBsaXN0IG9mIGNvbmNlcHRzIHRvIGJ1aWxkIGZyb20gSSdkIGxpa2UgdG8gZmlndXJlIG91dCBhIHdheSB0byBzY2FsZSBpdCBiYWNrXS4gIC0tLT4KYGBge3IsIGVjaG8gPSBGfQpwZXJzb25hbF9zdG9wIDwtIGMoInNjaWVuY2UiLCAidGhlb3J5IiwgImFwcGx5IiwgInRoZW9yZXRpY2FsIiwgImluZm9ybWF0aW9uIiwKICAgICAgICAgICAgICAgICAgICJ1bmNlcnRhaW50eSIsICJzeXN0ZW0iLCAicGxhbiIsICJtb2RlbCIsICJjaGFuZ2UiKQprZXl3b3JkcyA8LSB0aGVtZXMgJT4lIAogIHRpZHl0ZXh0Ojp1bm5lc3RfdG9rZW5zKHdvcmQsIGNhdCkgJT4lIAogIGRwbHlyOjpmaWx0ZXIoIXdvcmQgJWluJSB0aWR5dGV4dDo6c3RvcF93b3JkcyR3b3JkICYgCiAgICAgICAgICAgICAgICAgICF3b3JkICVpbiUgcGVyc29uYWxfc3RvcCkgJT4lIAogIG11dGF0ZSh3b3JkID0gdGV4dHN0ZW06OmxlbW1hdGl6ZV93b3Jkcyh3b3JkKSkgJT4lIAogIHVuaXF1ZSgpCmBgYAoKIyMjIyBgcXVlcnlDb25jZXB0cygpYCAgCgpXZSB1c2UgdGhlc2UgdGhlbWVzIHRvIGluZm9ybSBvdXIgaW5kZXggY3JlYXRpb24gdGhyb3VnaCBxdWVyeWluZyBvcGVuQWxleCBjb25jZXB0cy4gVGhlIGBxdWVyeUNvbmNlcHRzKClgIGZ1bmN0aW9uIGFsbG93cyB1cyB0byBlbnRlciB3b3JkcywgYmFzZWQgb24gb3VycyB0aGVtZXMsIGludG8gb3BlbkFsZXggQVBJIGFuZCBmaW5kIGEgbnVtYmVyIG9mIGFzc29jaWF0ZWQgcmVzZWFyY2ggY29uY2VwdHMuIEkgaW5wdXQgdGhlIDE5MiBTY2ltYWdvIHRoZW1lcyBhbmQga2V5d29yZHMgaW50byB0aGUgYGNvbmNlcHRfc3RyaW5nYCBhcmd1bWVudCB0byBxdWVyeSB0aGUgQVBJLiAKCjwhLS0tKipOb3RlOiBJIHRoaW5rIHdlIHNob3VsZCBidWlsZCBpbiBzbGVlcCB0aW1lIHRvIHRoaXMgZnVuY3Rpb24gYmVjYXVzZSBpZiB5b3UgdHJ5IHRvIGlucHV0IG11bHRpcGxlIGNvbmNlcHRzIGl0IGlzIHJlamVjdGVkKipdLS0tPgoKYGBge3IsIGV2YWwgPSBGfQprZXlfdGhlbWVzIDwtIHVuaXF1ZShjKHRoZW1lcyRjYXQsIGtleXdvcmRzJHdvcmQpKQoKIyBJIGFtIGJ1aWxkaW5nIGluIGEgc2xlZXAgYXJndW1lbnQgdG8gdGhpcyBxdWVyeSBmdW5jdGlvbiB0byBhdm9pZCBlcnJvcnMKcXVlcnlfc2xvd2x5IDwtIGZ1bmN0aW9uKHgpewogIGluZGV4IDwtIHF1ZXJ5Q29uY2VwdHMoY29uY2VwdF9zdHJpbmcgPSB4LCAKICAgICAgICAgICAgICAgICAgICAgICAgIHBlcl9wYWdlID0gNTApCiAgcmV0dXJuKGluZGV4KQogIFN5cy5zbGVlcCgxKQp9CmluZGV4IDwtIGxhcHBseShrZXlfdGhlbWVzLCBxdWVyeV9zbG93bHkpCgojIEZvciBzb21lIHJlYXNvbiB0aGVyZSB3YXMgYSBiaXQgb2YgbWlzc2luZyBkYXRhIGZvciBwYXJ0aWN1bGFyIGNvbmNlcHRzCmluZGV4W1s2Nl1dJGRlc2NyaXB0aW9uIDwtICcnCmluZGV4ZGYgPC0gZG8uY2FsbCgncmJpbmQnLCBpbmRleCkgJT4lIHVuaXF1ZSgpCmBgYAoKYGBge3IsIGVjaG8gPSBGfQojc2F2ZVJEUyhpbmRleGRmLCAidmlnbmV0dGVzL2dzcF92aWduZXR0ZV9maWxlcy9kYXRhL2luZGV4ZGYucmRzIikKaW5kZXhkZiA8LSByZWFkUkRTKCJwb3N0cy9nc3BfdmlnbmV0dGVfZmlsZXMvZGF0YS9pbmRleGRmLnJkcyIpCmBgYAoKRnJvbSB0aGUgMTkyIHRoZW1lcywgb3BlbkFsZXggaWRlbnRpZmllcyBgciBucm93KGluZGV4ZGYpYCBhc3NvY2lhdGVkIGNvbmNlcHRzLCByZXByZXNlbnRpbmcgYHIgc3VtKGluZGV4ZGYkd29ya3NfY291bnQpYCB3b3Jrcy4gVG8gZm9jdXMgb3VyIGluZGV4LCB3ZSBzZWxlY3Qgb25seSB0aGUgY29uY2VwdHMgdGhhdCBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoZSB0aGVtZXMgYXQgJ2xldmVsIDAnIC0tIHRoYXQgaXMsIHRoZSBoaWdoZXN0IG1hdGNoIG9mIHJlbGV2YW5jZS4gVGhpcyByZWR1Y2VzIG91ciBjb25jZXB0cyBkb3duIHRvIDE1LCBoaWdoLWxldmVsIGNvbmNlcHRzLCByZXByZXNlbnRpbmcgYHIgc3VtKGluZGV4ZGYkd29ya3NfY291bnQpYCB3b3Jrcy4gCgo8IS0tLSoqTm90ZTogVGhpcyBpcyBub3QgYSBzdXN0YWluYWJsZSBudW1iZXIgb2Ygd29ya3MgdG8gaW5kZXgsIHNvLi4uIG5lZWQgdG8gZGl0Y2ggdGhpcyBvciBsaW1pdCBpdCBzZXZlcmVseSoqXS0tLT4KCmBgYHtyLCBlY2hvID0gRn0KaW5kZXhkZiA8LSBpbmRleGRmICU+JSAKICAgZmlsdGVyKGxldmVsID09IDApCmBgYAoKQSBzdW1tYXJ5IG9mIHRoZXNlIGNvbmNlcHRzIGlzIGJlbG93OgoKYGBge3IsIGVjaG8gPSBGfQpEVDo6ZGF0YXRhYmxlKGluZGV4ZGZbLC1jKDMsNSldLCByb3duYW1lcyA9IEYpCmBgYAoKIyMjIyBgZXh0cmFjdFdvcmtzKClgICAKClVzaW5nIHRoZSBjb25jZXB0IHBhZ2UgSUQgZnJvbSB0aGUgcHJldmlvdXMgZnVuY3Rpb24sIHRoZSBgZXh0cmFjdFdvcmtzKClgIGZ1bmN0aW9uIGV4dHJhY3RzIHRoZSBhc3NvY2lhdGVkIHdvcmtzIGZyb20gdGhlIG9wZW5BbGV4IEFQSSBhbmQgc2F2ZXMgdGhlbSBhcyBjb21wcmVzc2VkIC5qc29uLmd6IGZpbGVzLiBUaGUgLmpzb24uZ3ogZmlsZXMgYXJlIHN0b3JlZCBpbiB0aGUgYGRlc3RfZmlsZWAgc3BlY2lmaWVkLiAgCgpgYGB7ciwgZXZhbCA9IEZ9CmZvcihqIGluIDIwMDA6MjAxMCl7CnNhcHBseShpbmRleGRmJGlkLCBGVU4gPSBmdW5jdGlvbih4KXsKICBleHRyYWN0V29ya3MobWFpbHRvID0gImJlbHdvb2RAdWNkYXZpcy5lZHUiLAogICAgICAgICAgICAgY29uY2VwdF9wYWdlID0geCwKICAgICAgICAgICAgIGRlc3RfZmlsZSA9IHBhc3RlMCgib3BlbmFsZXhfaW5kZXhfZ3NwLyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfZXh0cmFjdCh4LCdbQS1aYS16MC05XSskJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfMjAwMF8yMDIwIiwgIi5qc29uLmd6IiksCiAgICAgICAgICAgICBwZXJfcGFnZSA9IDIwMCwgIyBtdXN0IGJlIGJldHdlZW4gMSBhbmQgMjAwCiAgICAgICAgICAgICB0b19kYXRlID0gaiwKICAgICAgICAgICAgIGZyb21fZGF0ZSA9IGosCiAgICAgICAgICAgICBzbGVlcF90aW1lID0gMC41KQoKfSkKfQpgYGAKCmBgYHtyLCBldmFsID0gRiwgZWNobyA9IEZ9CnNtYWxsd29ya3MgPC0gZmlsdGVyKGluZGV4ZGYsIHdvcmtzX2NvdW50IDwgMTAwMDAwMCkKCiMgSSBkaWQgaXQgdGhpcyB3YXkgc28gdGhhdCBpZiBpdCBicmVha3MgZHVlIHRvIGludGVybmV0IGNvbm5lY3Rpb24gZmFpbHVyZSBJIGNhbiBzZWUgd2hlcmUgaXQgbGVhdmVzIG9mZgpmb3IoaSBpbiAxMjU6bnJvdyhzbWFsbHdvcmtzKSl7CnNhcHBseShzbWFsbHdvcmtzJGlkW2ldLCBGVU4gPSBmdW5jdGlvbih4KXsKICBleHRyYWN0V29ya3MobWFpbHRvID0gc2VuZF9tYWlsdG8sCiAgICAgICAgICAgICBjb25jZXB0X3BhZ2UgPSB4LAogICAgICAgICAgICAgZGVzdF9maWxlID0gcGFzdGUwKCJvcGVuYWxleF9pbmRleF9nc3AvIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9leHRyYWN0KHgsJ1tBLVphLXowLTldKyQnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl8yMDAwXzIwMjAiLCAiLmpzb24uZ3oiKSwKICAgICAgICAgICAgIHBlcl9wYWdlID0gMjAwLCAjIG11c3QgYmUgYmV0d2VlbiAxIGFuZCAyMDAKICAgICAgICAgICAgIHRvX2RhdGUgPSAyMDIyLAogICAgICAgICAgICAgZnJvbV9kYXRlID0gMjAwMCwKICAgICAgICAgICAgIHNsZWVwX3RpbWUgPSAwLjUpCgp9KQp9CmBgYAoKIyMjIyBgd29ya3MyZHQoKWAgIAoKTm93IHRoYXQgd2UgaGF2ZSAuanNvbi5neiBmaWxlcyBjb250YWluaW5nIHRoZSB3b3JrcyB3ZSB3YW50IGluIG91ciBpbmRleCwgd2UgY2FuIGNvbnZlcnQgdGhlbSBpbnRvIGEgZGF0YSB0YWJsZSB1c2luZyB0aGUgYHdvcmtzMmR0KClgIGZ1bmN0aW9uLiBUaGlzIGZ1bmN0aW9uIHRha2VzIHRoZSBmaWxlcGF0aCBvZiB0aGUgLmpzb24uZ3ogY29tcGlsZSB0byBjb252ZXJ0LiAgCgo8IS0tLVtOb3RlOiBGcm9tIGhlcmUgb24gd2UgYXJlIHVzaW5nIG9ubHkgYSBzYW1wbGUgb2YgdGhlIGluZGV4LCBzaW5jZSBpdCB0YWtlcyB0aW1lIHRvIGV4dHJhY3RdLiBJbnRlcm1pbiBpbmRleCBoYXMgb3ZlciAzIG1pbGxpb24gd29ya3MuIFRoaXMgY29udmVyc2lvbiBmcm9tIGpzb24gY29uY2VwdHMgdG8gd29ya3MgdG9vayAxMi41IGhvdXJzLiAtLS0+CgpgYGB7ciBjb21waWxlIHJlY29yZHMsIGV2YWwgPSBGfQpqc29ucyA8LSBsaXN0LmZpbGVzKCJvcGVuYWxleF9pbmRleF9nc3AvIiwgZnVsbC5uYW1lcyA9IFQpCiMgQW55dGhpbmcgdGhhdCBpcyAyMyBpcyBlbXB0eQpqc29ucyA8LSBqc29uc1tmaWxlLnNpemUoanNvbnMpID4gMjNdCnJlY29yZHMgPC0gbGFwcGx5KGpzb25zLCB3b3JrczJkdCkKcmVjb3Jkc2RmIDwtIGRvLmNhbGwoInJiaW5kIiwgcmVjb3JkcykKYGBgCgpXZSdsbCBhbHNvIHdhbnQgdG8gbWFrZSBzdXJlIG91ciByZWNvcmQgZGF0YSBmcmFtZSBoYXMgdGhlIGNvbHVtbiBuYW1lcyB0aGF0IGFyZSBjb21wYXRpYmxlIHdpdGggdGhlIG5leHQgc3RhZ2UsIHNvIGxldCdzIGdvIGFoZWFkIGFuZCByZW5hbWUgdGhlbSBhcHByb3ByaWF0ZWx5LiAgCmBgYHtyIHNldCB1cCByZWNvcmRzLCBldmFsID0gRn0gCmNvbG5hbWVzKHJlY29yZHNkZilbYygxLDIsMyw1LDcsOCwxMCwxMildIDwtIGMoInNvdXJjZSIsICJ0aXRsZSIsICJkb2kiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAieWVhciIsICJtaXNjaWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJqb3VybmFsX3RpdGxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicHVibGlzaGVyIiwgImF1dGhvcnMiKQpgYGAKCmBgYHtyIGxvYWRzIHJlY29yZHMgZGYgY292ZXJ0LCBlY2hvID0gRiwgZXZhbCA9IEZ9CiMgc2hvdWxkIGJlIEVWQUwgVFJVRQojc2F2ZVJEUyhyZWNvcmRzZGYsICJ+L0JveC9nb3ZzY2llbmNldXNlUi9yZWNvcmRzLnJkcyIpCnJlY29yZHNkZiA8LSByZWFkUkRTKCJ+L0JveC9nb3ZzY2llbmNldXNlUi9yZWNvcmRzLnJkcyIpCmBgYAoKRm9ydGhjb21pbmc6IDQuIGByZWZlcmVuY2VTZWFyY2goKWAKCg==