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/"

1. referenceExtract

The referenceExtract package from govscienceuseR is designed to take unstructured PDF documents, feed them through the anystyle.io citation extraction software, and return tagged citation data in a tabular format. This is accomplished using three functions, outlined in the following sections.

reference_extract()

The first step of extracting references is to input PDF documents into the reference_extract() function. This function reads in every PDF in the document directory (doc_dir), and runs them through anystyle.io. Anystyle extracts probable citations and exports them to the reference directory (ref_dir) as JSON files. Depending on the number and size of files, this can take some time. For example, these 114 documents took over an hour to extract.

# Extract probable citations from PDF documents and convert them to .json files
ref_directory <- "gsp_vignette_files/data/ref_dir"
reference_extract(doc_dir = doc_directory, 
                 ref_dir = ref_directory, 
                 layout = "none")

reference_compile()

Next, the reference_compile() function transforms the JSON files into tabular data and compiles them all in one data table, adding the file name as an identifier.

# Compile json files into a singular tabular data table
dt <- reference_compile(ref_directory)
## [1] "compiling 114 files, this will not be instantaneous"

After these first two steps we can take a look at our probable citations according to the Anystyle software. Initially, there are 26528 probable citations across these 114 documents.

It is noticeable above that the data provided by Anystyle has its challenges for further analysis. The first is a related to data structure: authors are nested into matrices, some rows (such as the date) have multiple listed values, etc., all of which make the data hard to analyze. For example, here is what seems to be two probable citations combined into one observation:

unnest(dt[204, c(2,3)])
## # A tibble: 3 × 2
##   date  title                                                                   
##   <chr> <chr>                                                                   
## 1 2017  Long‐Term Socio‐Economic Forecasts by County: Kings County              
## 2 2015  Progress Report: Subsidence in the Central Valley, California. For Depa…
## 3 2009  Ground‐water availability in California’s Central Valley

The second challenge is related to quality: many of the probable citations are not sensible. The Anystyle software seems sensitive to multiple formats like numbers and short-form sentences, such as addresses, resulting in false positive identification of references. For example, here is an address listed as a probable citation from our data:

unlist(dt[148, c(1,3,5)])
##                                                                                      author.family 
##                                                                                             "When" 
##                                                                                       author.given 
##                                                                                        "Firebaugh" 
##                                                                                              title 
## "5:00 - 7:00 PM Firebaugh Middle School MPR 1600 16th Street, Firebaugh, CA Los Banos – Wednesday" 
##                                                                                   container-title1 
##                                                    "PM College Greens Building 1815 Scripps Drive" 
##                                                                                   container-title2 
##                                                "PM Hammon Senior Center 1033 W. Las Palmas Avenue" 
##                                                                                   container-title3 
##                                                                                           "Monday"

reference_clean()

To try to address the challenges in these probable citations, the reference_clean() function goes through a series of steps. For each column the function unlists the data and filters out unlikely candidates for that column. For instance, if a number listed in the date column does not match any reasonable date format or expectation, it is removed. If a string in the URL column actually resembles a DOI, it is moved to that column. And so on. Furthermore, if there seem to be multiple citations listed in one row that can be broken apart in parallel across all of the columns, we unnest these rows. (Note: depending on the size of the files this function may take some time. Cleaning these 26528 citations takes about 18 minutes).

# Unnests list structures into tabular data and filters out low probability refs
dt <- reference_clean(dt)

This cleaning process has the changed probable citations now a bit. Some of the probable citations have been unnested (and therefore expanded) while others have been removed, leaving us with 14423 probable citations. Examples of these probable citations are below:

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:

extractWorks()

Using the concept page ID from the previous function, the extractWorks() function extracts the associated works from the openAlex API and saves them as compressed .json.gz files. The .json.gz files are stored in the dest_file specified.

for(j in 2000:2010){
sapply(indexdf$id, FUN = function(x){
  extractWorks(mailto = "belwood@ucdavis.edu",
             concept_page = x,
             dest_file = paste0("openalex_index_gsp/", 
                              stringr::str_extract(x,'[A-Za-z0-9]+$'),
                              "_2000_2020", ".json.gz"),
             per_page = 200, # must be between 1 and 200
             to_date = j,
             from_date = j,
             sleep_time = 0.5)

})
}

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==