Some River Flow Data
river <- scan("https://www.stat.uiowa.edu/~luke/data/river.dat")
plot(river)
A Simple Model of Visual Perception
The eyes acquire an image, which is processed through three stages of memory:
Iconic Memory
The first processing stage of an image happens in iconic memory.
Images remain in iconic memory for less than a second.
Processing in iconic memory is massively parallel and automatic.
This is called preattentive processing .
Preattentive processing is a fast recognition process.
Working Memory
Meaningful visual chunks are moved from iconic memory to short term memory.
These chunks are used by conscious, or attentive, processing.
Attentive processing often involves conscious comparisons or search.
Short term memory is limited:
Chunks can be of varying size; a coherent pattern can form a single chunk even if it is quite large.
If more chunks are needed or chunks are needed longer they need to be reacquired or retrieved from long term memory.
Long Term Memory
Long term visual memory is built up over a lifetime, though infrequently used visual chunks may become lost.
Chunks processed repeatedly in working memory may be transferred to long term memory.
Common patterns and contextual information can be retrieved from long term memory for attentive processing in working memory.
Visual Design Implications
Try to make as much use of preattentive features as possible.
Recognize when preattentive features might mislead.
For features that require attentive processing keep in mind that working memory is limited.
Some Examples of Challenges
Context Matters
Which of the inner circles is larger, or are they the same size?
Which of the lines is longer, or are they the same length?
The sine Illusion: which of the bars are longer, or are they the same length?
x <- seq(0, 5 * pi, length.out = 100)
w <- 0.5
plot(x, sin(x), ylim = c(-1, 1 + w), type = "n")
segments(x0 = x, y0 = sin(x), y1 = sin(x) + w, lwd = 3)
Which of the squares A and B is darker, or are they the same shade?
Some Optical Illusions
R implementations of some optical illusions by Kohske Takahashi:
Are these lines parallel?
Again, are these lines parallel?
Scintillating grid illusion : Black dots at the intersections appear and disappear; are they real?
Hermann grid illusion : “Ghost-like” grey blobs at the intersections of white lines.
Grid illusion in a cartogram:
A case where there are more dots than we can see at once:
Red from black and white:
Some illusions in pictures:
A large collection of optical illusions is available at https://michaelbach.de/ot/index.html .
Motion
n <- 50
x <- 2 * (1 : n)
y <- rep(2, n)
lim <- c(min(x) + 0.1 * (max(x) - min(x)), max(x) - 0.1 * (max(x) - min(x)))
v <- TRUE
for (i in 1 : 2) {
plot(x + v, y, xlim = lim)
v <- ! v
Sys.sleep(0.1)
}
Images contain no information about the direction of the rotation.
Your mind picks a direction.
library(rgl)
d <- data.frame(x = rnorm(1000), y = rnorm(1000), z = rnorm(1000))
points3d(d)
par3d(FOV = 1) ## removes perspective distortion
if (interactive())
play3d(spin3d(axis = c(0, 0, 1), rpm = 30), duration = 20)
Interactive rotation can help.
Depth cueing and perspective can also help.
Popout and Distractors
Where is the red dot:
Shape only:
Shapes and colors:
Items, Attributes, Marks, and Channels
To evaluate or design a visualization it is useful to have some terms for the components.
Several schools have developed different but similar sets of terms.
Some References:
Bertin, J. (1967), The Semiology of Graphics .
Cleveland, W. S. (1988), The Elements of Graphing Data .
Cleveland, W. S. (1993), Visualizing Data .
Few, S. (2012), Show Me the Numbers: Designing Tables and Graphs to Enlighten , 2nd ed.
Munzner, T. (2014), Visualization Analysis and Design
Ware, C. (2012), Information Visualization: Perception for Design , 3rd ed.
Wilkinson, L. (2005), The Grammar of Graphics , 2nd ed.
Munzner uses the terminology of items , attributes , links , marks , and channels :
Items are the basic units on which data is collected: the entities represented by the rows in a tidy data frame.
Attributes are the numerical or categorical features of the data items we want to represent; the variables in a tidy data frame.
Links are relations among items: e.g. months within a year, or countries within a continent.
Marks are the geometric entities used to represent items: points, lines, areas. These correspond to the simple geom
objects in ggplot
.
Visual channels are features of marks that can be used to reflect values of attributes.
Channels correspond approximately to aesthetics in ggplot
but are more focused on the visual aspect:
An x
aesthetic that is transformed to polar coordinates is a different channel than an x
aesthetic representing a position on a standard linear scale.
Channels are used to encode attributes (aesthetic mappings ).
A single attribute can be encoded in several channels.
Some channels are well suited to encode quantitative or ordered values; they are quantitatively perceived .
Others are only suited for nominal values.
A useful classification, adapted from Few(2012):
Form
Length
Yes
Width
Yes, but limited
Orientation
No
Size
Yes, but limited
Shape
No
Color
Hue
No
Intensity
Yes, but limited
Position
2D position
Yes
Munzner uses the terms magnitude channels and identity channels .
Ideally,
A useful principle: The most important attributes should be mapped to the most effective channels.
Channel Effectiveness
Some questions about channels:
What kind and how much information can a channel encode?
Are some channels better than others?
Can channels be used independently, or do they interfere?
Some criteria for evaluating channels:
Accuracy: How well can a viewer decode the information in the channel?
Discriminability: How easily can differences between attribute levels be perceived?
Separability: Can channels be used independently or is there interference?
Popout: can a channel provide popout where a difference is perceived preattentively?
Grouping: can a channel show perceptual grouping of items?
Channel Accuracy
Stevens (1957) argues that accuracy of magnitude channels can be described by a power law:
\[ \text{perceived sensation} = (\text{physical intensity})^\gamma \]
Experiments by Stevens suggest these values for some visual channels:
Others have raised concerns about the validity of these findings.
Another approach has used controlled experiments to assess accuracy of various channels used in visualizations:
William S. Cleveland and Robert McGill (1984), “Graphical Perception: Theory, Experimentation, and Application to the Development of Graphical Methods,” Journal of the American Statistical Association 79, 531–554.
William S. Cleveland and Robert McGill (1987), “Graphical Perception: The Visual Decoding of Quantitative Information on Graphical Displays of Data” Journal of the Royal Statistical Society. Series A , 192-229.
Jeffrey Heer and Michael Bostock (2010) “Crowdsourcing Graphical Perception: Using Mechanical Turk to Assess Visualization Design,” Proceedings of the SIGCHI , 203-212.
Munzner’s ordering by accuracy:
This ordering is sometimes referred to as a perceptual ladder .
Line width is another channel; not sure there is agreement on its accuracy, but it is not high.
Discriminability
Many channels, in particular identity channels, can only support a limited number of discriminable levels.
Line width is one of the most limited with perhaps 3 levels.
Using more than 5 or 6 color hues is not recommended.
Similarly, using more than 5 or 6 symbol shapes can create difficulties.
If the number of levels that can be represented by a channel is smaller than the number of attribute levels then some form of meaningful aggregation is needed.
Separability
Some encodings can be used independently of each other; others interfere with each other to some degree.
Vertical an horizontal position can be used independently.
Color (hue) and position can be used independently
Size and hue interfere somewhat; hue is harder to perceive on smaller objects.
Width and height do not function well independently; the result is perceived primarily as shape.
Encoding two different values in the red and green channels as a hue does not work at all.
Popout
Many channels support visual popout : having one item or a few items immediately stand out from the others.
Annotation can also be used to create popout.
Grouping
Perceptual grouping can be achieved in several ways:
Experimental Evidence
Cleveland-McGill
The 1984 paper is available from JSTOR .
The paper formulates a theory for ranking Elementary Perceptual Tasks ; these correspond to channel mappings.
Some orderings were addressed by informal experiments (obvious to the authors at least).
Others were assessed by formal experiments with about 50 subjects.
Experiments focused on accuracy of decoding, though this is not viewed as the primary purpose of a graph:
One must be careful not to fall into a conceptual trap of adopting accuracy as a criterion. … The power of a graph is its ability to enable one to take in the quantitative information, organize it, and see patterns and structure not readily revealed by other means of studying the data.
Their premise:
A graphical form that involves elementary perceptual tasks that lead to more accurate judgments than another graphical form (with the same quantitative information) will result in better organization and increase the chances of a correct perception of patterns and behavior."
The tasks: For each setting
Results:
Percent large errors:
Absolute error:
Heer and Bostock
Heer and Bostock (2010) set out to replicate the Cleveland McGill experiment using crowd sourcing via Amazon Mechanical Turk
They used the five position stimuli from Cleveland and McGill and some new ones:
50 subjects were recruited for each task.
Results were consistent with Cleveland-McGill results:
Use of Mechanical Turk was deemed a success.
Pie Chart Experiments
Pie charts are popular but somewhat controversial.
Pie charts are inferior for comparisons to bar charts.
Pie charts are quite good at representing part-whole relationships.
Cleveland and McGill suggested pie charts are read by angle.
Kosara and Skau report experiments that suggest this is not the case.
If it were, donut charts would be even less effective, but they seem to be very comparable.
Kosara’s blog provides a review of other pie chart studies.
Improving Some Common Charts
Cleveland and McGill set out to suggest improvements to some common charts. This is a selection of their examples.
Dot Charts
Cleveland and McGill use their perceptual ladder to argue strongly for using dot charts in place of bar charts and pie charts.
Playfair’s Balance of Trade plots
Playfair presented a number of plots showing imports and exports between England and other nations.
A primary goal was to show the balance of trade, the difference between exports and imports:
Assessing the differences from a plot showing exports and imports as separate curves requires length judgments, which are less accurate than comparisons to a common stale.
Plotting the difference makes the balance of trade much easier to assess:
An ensemble plot showing both views may also help.
Framed Unaligned Bars
It is difficult to compare lengths of unaligned rectangles when the lengths are close.
Adding a frame moves the task up the perceptual ladder to an unaligned comparison against a common scale.
Comparing to a common scale is still the most effective approach:
But this does suggest that using unaligned framed rectangles to encode a third variable, with position encoding the two primary variables may be effective.
Framed Rectangle Maps
A choropleth map is a common way to depict a quantitative variable in a geographic context.
Shading is quite low on the perceptual ladder.
Cleveland and McGill suggest the use of framed rectangles positioned on the map as an alternative.
This does not seem to have caught on so far, though you do sometimes see the use of other glyphs, such as pie charts.
Analyzing a Design
Graph layout involves several levels:
A useful structure for describing the primary features:
What are the data items?
What are the attributes?
What marks are used?
What channels are used?
Which attribute is matched to channel 1
Which attribute is matched to channel 2
…
Useful questions:
Are the most important attributes mapped to the strongest channels?
Do the mappings do a good job of conveying the primary message?
If not, can the graph be improved by adjusting the mappings?
A Gapminder Plot
One of the frames of a plot from the GapMinder site :
The basic plot can be created with ggplot
and aesthetic mappings:
library(gapminder)
gm2007 <- filter(gapminder, year == 2007)
ggplot(gm2007) +
geom_point(aes(x = gdpPercap,
y = lifeExp,
size = pop,
color = continent)) +
scale_x_log10() +
ylim(c(20, 85))
The data in the gapminder
package differ somewhat from the data used by the Gapminder site, but overall the plot designs are very close.
With some adjustments the basic plot can be brought close to the Gapminder version in appearance:
gm2007 <- filter(gapminder, year == 2007) |>
arrange(desc(pop)) ## sort to avoid over-plotting
ggplot(gm2007) +
geom_point(aes(x = gdpPercap,
y = lifeExp,
size = pop,
fill = continent),
shape = 21) + ## to allow the using `fill` aesthetic
scale_x_log10(labels = comma) +
ylim(c(20, 85)) +
scale_size_area(max_size = 20,
labels = comma,
breaks = c(0.25 * 10 ^ 9, 0.5 * 10 ^ 9, 10 ^ 9)) +
scale_fill_manual(values = c(Africa = "deepskyblue",
Asia = "red",
Americas = "green",
Europe = "gold",
Oceania = "brown")) +
labs(x = "Income", y = "Life expectancy") +
theme(text = element_text(size = 16)) +
guides(fill = guide_legend(title = "Continent",
override.aes = list(size = 5),
order = 1),
size = guide_legend(title = "Population",
label.hjust = 1,
order = 2)) +
theme_minimal() +
theme(panel.border = element_rect(fill = NA, color = "grey20"))
Some notes:
Using larger bubbles makes the plot more engaging.
Using larger bubbles makes differences in population easier to assess, but makes the strength of the relationship between life expectancy and income harder to assess.
Using larger bubbles also increases the risk of over-plotting. Sorting the rows so larger bubble are drawn first helps reduce the risk somewhat.
These plots show a fairly strong marginal association between life expectancy and income.
There does not seem to be a strong association of population with the other two variables, but these plots are not ideal for that assessment.
To judge the marginal association between life expectancy and population size we can change the channel mapping:
map the horizontal axis to population;
map area to income.
ggplot(filter(gapminder, year == 2007)) +
geom_point(aes(x = pop,
y = lifeExp,
size = gdpPercap)) +
scale_x_log10() +
ylim(c(20, 85)) +
theme_minimal() +
theme(panel.border =
element_rect(fill = NA,
color = "grey20"))
This confirms that there is very little association between life expectancy and population.
The association between life expectancy and income is still visible, but is easier to assess when these two variables are mapped to 2D position.
Michelin Stars
This image, from a blog post , shows the total number of stars for different countries:
Observations:
None of the channels are very strong.
The strongest channels, 2D position, are not used.
The number of colors used is too high.
A simple dot plot would convey the distribution better.
A dot plot using 2017 data from an article in The Telegraph:
michelin <- read.table(WLNK("michelin.dat"),
head = TRUE)
michelin <- mutate(michelin,
stars = one + 2 * two + 3 * three,
country = reorder(country, stars))
ggplot(michelin, aes(x = stars, y = country)) +
geom_point() +
labs(x = "Stars", y = NULL) +
theme_minimal() +
theme(text = element_text(size = 16)) +
theme(panel.border =
element_rect(fill = NA,
color = "grey20"))
Even if a bubble plot is desired for aesthetic reasons, position could be used to
group countries by continent;
show countries on a map.
A plot like the original can be constructed by
computing locations for a set of packed spheres with specified radii;
using geom_point
and geom_text
.
## create randomly located packed spheres with specified areas
library(packcircles)
set.seed(54321)
packing <- circleProgressiveLayout(michelin$stars)
## merge circle locations with starts data
mcirc <- bind_cols(packing, michelin) |>
mutate(country = factor(country)) ## clean out stray attributes
## compute some colors to use
nr <- nrow(mcirc)
pal <- colorRampPalette(RColorBrewer::brewer.pal(9, "Set1"))
cols <- sample(pal(nr), nr)
## these need tuning for the screen or R markdown
csize <- 45
tsize <- 2.5
## the basic plot
## uses shape = 19 and `color` aesthetic
p <- ggplot(mcirc, aes(x = x, y = y)) +
geom_point(aes(size = radius ^ 2, color = country), shape = 19) +
scale_size_area(max_size = csize) +
geom_text(aes(label = paste(country, stars, sep = "\n")),
data = filter(mcirc, stars >= 120),
size = tsize) +
coord_fixed()
## adjustments
p + guides(size = "none") +
scale_color_manual(values = cols) +
xlim(with(mcirc, range(x) + c(-1, 1) * max(radius))) +
ylim(with(mcirc, range(y) + c(-1, 1) * max(radius))) +
theme_void()
A somewhat more robust approach
creates vertex data for polygon approximations to the circles;
merges the stars data with the polygon data;
uses geom_polygon
and geom_text
.
This is very similar to the way simple choropleth maps are created.
## compute polygon approximations to spheres
mcircpoly <- circleLayoutVertices(mcirc, idcol = "country", npoints = 100) |>
rename(country = id)
## merge the stars data into the polygon data
sttab <- select(michelin, country, stars)
mcircpoly <- left_join(mcircpoly, sttab, "country")
## create the plot
ggplot(mcircpoly, aes(x = x, y = y)) +
geom_polygon(aes(fill = country)) +
geom_text(aes(label = paste(country, stars, sep = "\n")),
data = filter(mcirc, stars >= 120),
size = tsize) +
coord_fixed() +
scale_fill_manual(values = cols) +
theme_void()
Aspect Ratio and Perception
The river flow data shows how important aspect ratio can be to our ability to detect patterns:
Using a line plot the basic periodicity becomes apparent even in the first aspect ratio.
p2 <- p0 + geom_line()
p2 + coord_fixed(ratio = 35)
But the steeper increase/shallower decrease of most periods is easier to see in the second aspect ratio:
p2 + coord_fixed(ratio = 4)
The aspect ratio also influences interpretation of results.
Some alternative views of (suspect) data on the number of people on government assistance over a time period:
library(readr)
w <- read_csv(WLNK("hw2-welfare.csv"))
w <- mutate(w, onAssistance = onAssistance / 10 ^ 6)
w <- mutate(w,
date = seq(as.Date("2009-01-01"), by = "quarter", length.out = 10))
p0 <- ggplot(w, aes(x = date, y = onAssistance)) +
theme_minimal() +
theme(panel.border = element_rect(fill = NA, color = "grey20"))
p1 <- p0 + geom_line(aes(group = 1))
grid.arrange(p1, p1 + coord_fixed(ratio = 8),
p1 + ylim(0, max(w$onAssistance)),
p0 + geom_col(width = 40), ncol = 2)
Some notes:
Automated choices of axis scaling can affect the aspect ratio of the content of a plot.
A zero base line supports ratio comparisons.
The preattentive response to bar charts is always to compare ratios, so using a zero base line is important.
Using a non-zero base line for line plots and scatter plots encourages interval, or difference, comparisons.
Research on the effect of aspact ratio on perception has focused on accuracy of slope comparisons.
The general message is that keeping away from slopes that are too steep or too shallow is best.
Banking to 45 degrees , or choosing an aspect ratio so the slope magnitudes are distributed around 45 degrees is often recommended.
This also tends to be a useful “neutral ground” when political implications are involved.
Some references:
A blog post by Robert Kosara.
William S. Cleveland, Marylyn E. McGill and Robert McGill (1988), “The Shape Parameter of a Two-Variable Graph”, Journal of the American Statistical Association (JSTOR )
Justin Talbot, John Gerth, Pat Hanrahan (2012), “An Empirical Model of Slope Ratio Comparisons”, IEEE Trans. Visualization & Comp. Graphics (Proc. InfoVis) (PDF )
Ensemble Plots and Faceting
Using multiple channels allows a single plot to show a lot of information.
But over-plotting and interference can become problems.
One alternative is to use several related views in a useful arrangement.
Such arrangements are sometimes called ensemble plots .
There are a number of variations; a few are introduced below.
Similar Plots with Different Variables and Shared Encodings
One way to show three continuous variables is with two plots that share an axis:
library(patchwork)
pe_thm <- theme_minimal() +
theme(panel.background = element_rect(color = "black",
linewidth = 0.5,
fill = NA))
p1 <- ggplot(gm2007, aes(x = gdpPercap, y = lifeExp, color = continent)) +
geom_point() +
scale_x_log10() +
guides(color = "none") +
pe_thm
p2 <- ggplot(gm2007, aes(x = pop / 10 ^ 6, y = lifeExp, color = continent)) +
geom_point() +
scale_x_log10() +
pe_thm +
theme(axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank())
p1 + p2
Life expectancy is mapped to the vertical position in both plots.
Continent is mapped to color in both plots.
Guides can be shared when encodings are shared.
Different Plots with Shared Encodings
Multiple views of the data are often helpful.
Sharing encodings makes the relations between views easier to perceive.
p3 <- ggplot(gm2007,
aes(x = pop / 10 ^ 6,
y = reorder(continent, pop, FUN = sum),
fill = continent)) +
geom_col() +
ylab(NULL) +
pe_thm
p1 + p3
Small Multiples
Small multiples refers to a collection of plots with identical structure showing different subsets of the data and organized in a useful way.
These plot collections are also called trellis plots , lattice plots , or faceted plots .
A plot of life expectancy against income per capita in 2007 faceted by continent:
gd <- filter(gapminder, year %in% c(1977, 1987, 1997, 2007))
gd2007 <- filter(gapminder, year == 2007)
fct_thm <- theme_minimal() +
theme(panel.background = element_rect(color = "black",
linewidth = 0.5,
fill = NA))
ggplot(gd2007, aes(x = gdpPercap, y = lifeExp, color = continent)) +
geom_point(size = 2.5) +
scale_x_log10() +
facet_wrap(~ continent) +
fct_thm
A useful variation is to show a muted view of the full data in the background:
ggplot(gd2007, aes(x = gdpPercap, y = lifeExp, color = continent)) +
geom_point(data = mutate(gd2007, continent = NULL), color = "grey80") +
geom_point(size = 2.5) +
scale_x_log10() +
facet_wrap(~ continent) +
fct_thm
Data can be facetet on two variables.
This plot shows the full data faceted by both continent and a set of years:
ggplot(gd, aes(x = gdpPercap, y = lifeExp, color = continent)) +
geom_point(size = 2.5) +
scale_x_log10() +
facet_grid(continent ~ year) +
fct_thm
Adding muted data for each year helps regonizing where each continent group fits within a year
ggplot(gd, aes(x = gdpPercap, y = lifeExp, color = continent)) +
geom_point(data = mutate(gd, continent = NULL), color = "grey80") +
geom_point(size = 2.5) +
scale_x_log10() +
facet_grid(continent ~ year) +
fct_thm
A recent example from the Financial Times:
Exercises
Which of the following channels are magnitude channels and which are identity channels?
Position on a common scale
Length
Color hue (red, green, etc.)
Symbol shape (dot, cross, etc.)
Consider the following visualizations of the 2017 Michelin star data:
Which plot makes it easier to compare the numbers of stars for different countries? Explain your conclusion by identifying the channels used and their relative strengths.
Identify the items, attributes, marks, channels, and mappings use in the following plot:
LS0tCnRpdGxlOiAiUGVyY2VwdGlvbiBhbmQgVmlzdWFsaXphdGlvbiIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJzdGF0NDU4MC5jc3MiIHR5cGU9InRleHQvY3NzIiAvPgoKYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0Kc291cmNlKGhlcmU6OmhlcmUoInNldHVwLlIiKSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGNvbGxhcHNlID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDYsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQoKbGlicmFyeShsYXR0aWNlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoc2NhbGVzKQpzZXQuc2VlZCgxMjM0NSkKYGBgCgoKIyMgU29tZSBSaXZlciBGbG93IERhdGEKCmBgYHtyLCBlY2hvID0gVFJVRX0Kcml2ZXIgPC0gc2NhbigiaHR0cHM6Ly93d3cuc3RhdC51aW93YS5lZHUvfmx1a2UvZGF0YS9yaXZlci5kYXQiKQpwbG90KHJpdmVyKQpgYGAKCgojIyBBIFNpbXBsZSBNb2RlbCBvZiBWaXN1YWwgUGVyY2VwdGlvbgoKVGhlIGV5ZXMgYWNxdWlyZSBhbiBpbWFnZSwgd2hpY2ggaXMgcHJvY2Vzc2VkIHRocm91Z2ggdGhyZWUgc3RhZ2VzIG9mCm1lbW9yeToKCiogSWNvbmljIG1lbW9yeTsKCiogV29ya2luZyBtZW1vcnksIG9yIHNob3J0LXRlcm0gbWVtb3J5OwoKKiBMb25nLXRlcm0gbWVtb3J5LgoKCiMjIyBJY29uaWMgTWVtb3J5CgpUaGUgZmlyc3QgcHJvY2Vzc2luZyBzdGFnZSBvZiBhbiBpbWFnZSBoYXBwZW5zIGluIGljb25pYyBtZW1vcnkuCgoqIEltYWdlcyByZW1haW4gaW4gaWNvbmljIG1lbW9yeSBmb3IgbGVzcyB0aGFuIGEgc2Vjb25kLgoKKiBQcm9jZXNzaW5nIGluIGljb25pYyBtZW1vcnkgaXMgbWFzc2l2ZWx5IHBhcmFsbGVsIGFuZCBhdXRvbWF0aWMuCgoqIFRoaXMgaXMgY2FsbGVkIF9wcmVhdHRlbnRpdmUgcHJvY2Vzc2luZ18uCgpQcmVhdHRlbnRpdmUgcHJvY2Vzc2luZyBpcyBhIGZhc3QgcmVjb2duaXRpb24gcHJvY2Vzcy4KCgojIyMgV29ya2luZyBNZW1vcnkKCk1lYW5pbmdmdWwgdmlzdWFsIGNodW5rcyBhcmUgbW92ZWQgZnJvbSBpY29uaWMgbWVtb3J5IHRvIHNob3J0IHRlcm0gbWVtb3J5LgoKVGhlc2UgY2h1bmtzIGFyZSB1c2VkIGJ5IGNvbnNjaW91cywgb3IgYXR0ZW50aXZlLCBwcm9jZXNzaW5nLgoKQXR0ZW50aXZlIHByb2Nlc3Npbmcgb2Z0ZW4gaW52b2x2ZXMgY29uc2Npb3VzIGNvbXBhcmlzb25zIG9yIHNlYXJjaC4KClNob3J0IHRlcm0gbWVtb3J5IGlzIGxpbWl0ZWQ6CgoqIGluZm9ybWF0aW9uIGlzIHJldGFpbmVkIGZvciBvbmx5IGEgZmV3IHNlY29uZHM7CgoqIG9ubHkgdGhyZWUgb3IgZm91cnMgY2h1bmtzIGNhbiBiZSBoZWxkIGF0IGEgdGltZS4KCkNodW5rcyBjYW4gYmUgb2YgdmFyeWluZyBzaXplOyBhIGNvaGVyZW50IHBhdHRlcm4gY2FuIGZvcm0gYSBzaW5nbGUKY2h1bmsgZXZlbiBpZiBpdCBpcyBxdWl0ZSBsYXJnZS4KCklmIG1vcmUgY2h1bmtzIGFyZSBuZWVkZWQgb3IgY2h1bmtzIGFyZSBuZWVkZWQgbG9uZ2VyIHRoZXkgbmVlZCB0bwpiZSByZWFjcXVpcmVkIG9yIHJldHJpZXZlZCBmcm9tIGxvbmcgdGVybSBtZW1vcnkuCgoKIyMjIExvbmcgVGVybSBNZW1vcnkKCkxvbmcgdGVybSB2aXN1YWwgbWVtb3J5IGlzIGJ1aWx0IHVwIG92ZXIgYSBsaWZldGltZSwgdGhvdWdoCmluZnJlcXVlbnRseSB1c2VkIHZpc3VhbCBjaHVua3MgbWF5IGJlY29tZSBsb3N0LgoKQ2h1bmtzIHByb2Nlc3NlZCByZXBlYXRlZGx5IGluIHdvcmtpbmcgbWVtb3J5IG1heSBiZSB0cmFuc2ZlcnJlZCB0bwpsb25nIHRlcm0gbWVtb3J5LgoKQ29tbW9uIHBhdHRlcm5zIGFuZCBjb250ZXh0dWFsIGluZm9ybWF0aW9uIGNhbiBiZSByZXRyaWV2ZWQgZnJvbQpsb25nIHRlcm0gbWVtb3J5IGZvciBhdHRlbnRpdmUgcHJvY2Vzc2luZyBpbiB3b3JraW5nIG1lbW9yeS4KCgojIyMgVmlzdWFsIERlc2lnbiBJbXBsaWNhdGlvbnMKClRyeSB0byBtYWtlIGFzIG11Y2ggdXNlIG9mIHByZWF0dGVudGl2ZSBmZWF0dXJlcyBhcyBwb3NzaWJsZS4KClJlY29nbml6ZSB3aGVuIHByZWF0dGVudGl2ZSBmZWF0dXJlcyBtaWdodCBtaXNsZWFkLgoKRm9yIGZlYXR1cmVzIHRoYXQgcmVxdWlyZSBhdHRlbnRpdmUgcHJvY2Vzc2luZyBrZWVwIGluIG1pbmQgdGhhdAp3b3JraW5nIG1lbW9yeSBpcyBsaW1pdGVkLgoKCiMjIFNvbWUgRXhhbXBsZXMgb2YgQ2hhbGxlbmdlcwoKCiMjIyBDb250ZXh0IE1hdHRlcnMKCldoaWNoIG9mIHRoZSBpbm5lciBjaXJjbGVzIGlzIGxhcmdlciwgb3IgYXJlIHRoZXkgdGhlIHNhbWUgc2l6ZT8KCjwhLS0KaHR0cDovL2p1bmtjaGFydHMudHlwZXBhZC5jb20vanVua19jaGFydHMvMjAxMi8wOS9pbnN1ZmZpY2llbmN5LWFuZC1pbGx1c2lvbnMuaHRtbAotLT4KCmBgYHtyLCBlY2hvID0gRkFMU0V9CmNpcmNsZSA8LSBsb2NhbCh7CiAgICBwaGkgPC0gc2VxKDAsIDIgKiBwaSwgbGVuZ3RoLm91dCA9IDEwMCkKICAgIHggPC0gY29zKHBoaSkKICAgIHkgPC0gc2luKHBoaSkKICAgIGZ1bmN0aW9uKGN4ID0gMCwgY3kgPSAwLCByID0gMSkgbGlzdCh4ID0gciAqIHggKyBjeCwgeSA9IHIgKiB5ICsgY3kpCn0pCnNldHVwIDwtIGZ1bmN0aW9uKHcgPSA1KQogICAgcGxvdCgwLCB0eXBlID0gIm4iLCBhc3AgPSAxLAogICAgICAgICB4bGltID0gYygtdywgdyksIHlsaW0gPSBjKC13LCB3KSwKICAgICAgICAgYXhlcyA9IEZBTFNFLCB4bGFiID0gIiIsIHlsYWIgPSAiIiwKICAgICAgICAgbWFyID0gYygwLCAwLCAwLCAwKSkKc2V0dXAoKQpwb2x5Z29uKGNpcmNsZSgtMiwgMCwgMykpCnBvbHlnb24oY2lyY2xlKC0yLCAwKSwgY29sID0gImJsYWNrIikKcG9seWdvbihjaXJjbGUoMywgMCwgMS4zKSkKcG9seWdvbihjaXJjbGUoMywgMCksIGNvbCA9ICJibGFjayIpCmBgYApgYGB7ciwgZWNobyA9IEZBTFNFfQpzZXR1cCgxMCkKeDEgPC0gLTQKeDIgPC0gNgpwb2x5Z29uKGNpcmNsZSh4MSwgMCkpCmZvciAoYSBpbiAoMiAqIHBpICogKDEgOiA2KSAvIDYpKQogICAgcG9seWdvbihjaXJjbGUoNCAqIGNvcyhhKSArIHgxLCA0ICogc2luKGEpLCAyKSkKcG9seWdvbihjaXJjbGUoeDIsIDApKQpmb3IgKGEgaW4gKDIgKiBwaSAqICgxIDogMTApIC8gMTApKQogICAgcG9seWdvbihjaXJjbGUoMS41ICogY29zKGEpICsgeDIsIDEuNSAqIHNpbihhKSwgMC41KSkKYGBgCgpXaGljaCBvZiB0aGUgbGluZXMgaXMgbG9uZ2VyLCBvciBhcmUgdGhleSB0aGUgc2FtZSBsZW5ndGg/CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpzZXR1cCgpCnBvbHlnb24oY2lyY2xlKC00LCAtMikpCnBvbHlnb24oY2lyY2xlKDQsIC0yKSkKcG9seWdvbihjaXJjbGUoLTIsIDIpKQpwb2x5Z29uKGNpcmNsZSgyLCAyKSkKc2VnbWVudHMoLTMsIC0yLCAzLCAtMiwgbHdkID0gMykKc2VnbWVudHMoLTMsICsyLCAzLCArMiwgbHdkID0gMykKCndpZHRoIDwtIDMKYWggPC0gZnVuY3Rpb24oeCwgeSwgc2l6ZSA9IDEsIGRpciA9IDEpIHsKICAgIGF4IDwtIGMoLXNpemUgKiBkaXIsIDAsIC1zaXplICogZGlyKQogICAgYXkgPC0gYygtc2l6ZSwgMCwgc2l6ZSkKICAgIGxpbmVzKHggKyBheCwgeSArIGF5LCBsd2QgPSB3aWR0aCkKfQpgYGAKYGBge3IsIGVjaG8gPSBGQUxTRX0Kc2V0dXAoKQpzZWdtZW50cygtMywgLTIsIDMsIC0yLCBsd2QgPSB3aWR0aCkKYWgoMywgLTIpCmFoKC0zLCAtMiwgZGlyID0gLTEpCnNlZ21lbnRzKC0zLCArMiwgMywgKzIsIGx3ZCA9IHdpZHRoKQphaCgzLCAyLCBkaXIgPSAtMSkKYWgoLTMsIDIpCmBgYAoKVGhlIHNpbmUgSWxsdXNpb246IHdoaWNoIG9mIHRoZSBiYXJzIGFyZSBsb25nZXIsIG9yIGFyZSB0aGV5IHRoZSBzYW1lCmxlbmd0aD8KCmBgYHtyLCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0KeCA8LSBzZXEoMCwgNSAqIHBpLCBsZW5ndGgub3V0ID0gMTAwKQp3IDwtIDAuNQpwbG90KHgsIHNpbih4KSwgeWxpbSA9IGMoLTEsIDEgKyB3KSwgdHlwZSA9ICJuIikKc2VnbWVudHMoeDAgPSB4LCB5MCA9IHNpbih4KSwgeTEgPSBzaW4oeCkgKyB3LCBsd2QgPSAzKQpgYGAKCjwhLS0gaHR0cDovL3ZhbnNlb2Rlc2lnbi5jb20vd2ViLWRlc2lnbi9jb2xvci1sdW1pbmFuY2UvLS0+CgpXaGljaCBvZiB0aGUgc3F1YXJlcyBBIGFuZCBCIGlzIGRhcmtlciwgb3IgYXJlIHRoZXkgdGhlIHNhbWUgc2hhZGU/CgpgYGB7ciBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKElNRygiY2hlc3MxLnBuZyIpKQpgYGAKYGBge3IgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhJTUcoImNoZXNzMi5wbmciKSkKYGBgCgoKIyMjIFNvbWUgT3B0aWNhbCBJbGx1c2lvbnMKCltSIGltcGxlbWVudGF0aW9uc10oaHR0cDovL3JwdWJzLmNvbS9rb2hza2UvUi1kZS1pbGx1c2lvbikgb2Ygc29tZQpvcHRpY2FsIGlsbHVzaW9ucyBieSBLb2hza2UgVGFrYWhhc2hpOgoKPCEtLQpTb21lIGFsc28gdXNlZCBpbgpodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMva25pdHJCb290c3RyYXAvdmlnbmV0dGVzL2lsbHVzaW9ucy5odG1sCgpGaXJzdCBzYXcgdGhlc2UgaW4KaHR0cDovL2Jsb2cucmV2b2x1dGlvbmFuYWx5dGljcy5jb20vMjAxMi8xMi9jcmVhdGUtb3B0aWNhbC1pbGx1c2lvbnMtd2l0aC1yLmh0bWwKLS0+CgpBcmUgdGhlc2UgbGluZXMgcGFyYWxsZWw/CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpsaWJyYXJ5KGdyaWQpCnJzIDwtIGV4cGFuZC5ncmlkKHggPSBzZXEoMCwgMSwgMSAvIDEwKSwgeSA9IHNlcSgwLCAxLCAxIC8gMTApKQpncmlkLnJlY3QocnMkeCwgcnMkeSwgMSAvIDEwIC8gMiwgMSAvIDEwIC8gMiwKICAgICAgICAgIGdwID0gZ3BhcihmaWxsID0gImJsYWNrIiwgY29sID0gTkEpKQpncmlkLnJlY3QocnMkeCArIDEgLyAxMCAvIDQsIHJzJHkgKyAxIC8gMTAgLyAyLCAxIC8gMTAgLyAyLCAxIC8gMTAgLyAyLAogICAgICAgICAgZ3AgPSBncGFyKGZpbGwgPSAiYmxhY2siLCBjb2wgPSBOQSkpCmxzIDwtIGV4cGFuZC5ncmlkKHggPSAwIDogMSwgeSA9IHNlcSgwLCAxLCAxIC8gMjApIC0gMSAvIDIwIC8gMikKZ3JpZC5wb2x5bGluZShscyR4LCBscyR5LCBpZCA9IGdsKG5yb3cobHMpIC8gMiwgMiksCiAgICAgICAgICAgICAgZ3AgPSBncGFyKGNvbCA9ICJncmV5NTAiLCBsd2QgPSAxKSkKYGBgCgpBZ2FpbiwgYXJlIHRoZXNlIGxpbmVzIHBhcmFsbGVsPwoKYGBge3IsIGVjaG8gPSBGQUxTRX0KZ3JpZC5uZXdwYWdlKCkKbiA8LSAxMDsgbnkgPC0gODsgTCA8LSAwLjAxCmMgPC0gc2VxKDAsIDEsIGxlbmd0aCA9IG4pOyBkIDwtIDEuMiAqIGRpZmYoYylbMV0gLyAyCmNvbCA8LSBjKCJibGFjayIsICJ3aGl0ZSIpCnggPC0gYyhjIC0gZCwgYywgYyArIGQsIGMpCnkgPC0gcmVwKGMoMCwgLWQsIDAsIGQpLCBlYWNoID0gbikKdyA8LSBjKGMgLSBkLCBjIC0gZCArIEwsIGMgKyBkLCBjICsgZCAtIEwpCnogPC0gYygwLCBMLCAwLCAtTCkKeXMgPC0gc2VxKDAsIDEsIGxlbmd0aCA9IG55KQpncmlkLnJlY3QoZ3AgPSBncGFyKGZpbGwgPSBncmF5KDAuNSksIGNvbCA9IE5BKSkKcGx5cjo6bF9wbHkoMSA6IG55LCBmdW5jdGlvbihpKSB7CiAgICBpZiAoaSAlJSAyID09IDApIHsKICAgICAgICBjbyA8LSByZXYoY29sKQogICAgICAgIHogPC0gLXoKICAgIH0gZWxzZQogICAgICAgIGNvIDwtIGNvbAogICAgZ3JpZC5wb2x5Z29uKHgsIHkgKyB5c1tpXSwgaWQgPSByZXAoMSA6IG4sIDQpLAogICAgICAgICAgICAgICAgIGdwID0gZ3BhcihmaWxsID0gY28sIGNvbCA9IE5BKSkKICAgIGdyaWQucG9seWdvbih3LCByZXAoeiwgZWFjaCA9IG4pICsgeXNbaV0sIGlkID0gcmVwKDEgOiBuLCA0KSwKICAgICAgICAgICAgICAgICBncCA9IGdwYXIoZmlsbCA9IHJldihjbyksIGNvbCA9IE5BKSkKfSkKYGBgCgpbU2NpbnRpbGxhdGluZyBncmlkCmlsbHVzaW9uXShodHRwczovL3BzeWNob2xvZ3kuZmFuZG9tLmNvbS93aWtpL0dyaWRfaWxsdXNpb24jU2NpbnRpbGxhdGluZ19ncmlkX2lsbHVzaW9uKToKQmxhY2sgZG90cyBhdCB0aGUgaW50ZXJzZWN0aW9ucyBhcHBlYXIgYW5kIGRpc2FwcGVhcjsgYXJlIHRoZXkgcmVhbD8KCjwhLS0gdGhlIGNpcmNsZXMgbmVlZCB0byBiZSBhIGxpdHRsZSBiaWdnZXIgdGhhbiB0aGUgbGluZXMgLS0+CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpueCA8LSA2OyBueSA8LSA2OyBsd2QgPC0gMTA7IGNyIDwtIDEuMiAvIDEwMApncmlkLm5ld3BhZ2UoKQojIyBub2xpbnQgc3RhcnQKIyMgeGxpbSA8LSB5bGltIDwtIGMoMC4wNSwgMC45NSkKIyMgcHVzaFZpZXdwb3J0KHZpZXdwb3J0KCAjIGxpa2UgcGxvdC53aW5kb3coKQojIyAgICAgICAgIHg9MC41LCB5PTAuNSwgIyBhIGNlbnRlcmVkIHZpZXdwb3J0CiMjICAgICAgICAgd2lkdGg9dW5pdChtaW4oMSxkaWZmKHhsaW0pL2RpZmYoeWxpbSkpLCAic25wYyIpLCAjIGFzcGVjdCByYXRpbyBwcmVzZXJ2ZWQKIyMgICAgICAgIGhlaWdodD11bml0KG1pbigxLGRpZmYoeWxpbSkvZGlmZih4bGltKSksICJzbnBjIiksCiMjICAgICAgICB4c2NhbGU9eGxpbSwgIyBjZi4geGxpbQojIyAgICAgICAgeXNjYWxlPXlsaW0gICMgY2YuIHlsaW0KIyMpKQojIyBub2xpbnQgZW5kCmdyaWQucmVjdCgwLjUsIDAuNSwgMSwgMSwgZ3AgPSBncGFyKGZpbGwgPSAiYmxhY2siKSkKbHMgPC0gZXhwYW5kLmdyaWQoeCA9IDA6MSwgeSA9IHNlcSgwLCAxLCAxIC8gbnggLyAyKSAtIDEgLyBueCAvIDIgLyAyKQpncmlkLnBvbHlsaW5lKGxzJHgsIGxzJHksIGlkID0gZ2wobnJvdyhscykgLyAyLCAyKSwKICAgICAgICAgICAgICBncCA9IGdwYXIoY29sID0gImdyZXkiLCBsd2QgPSBsd2QpKQpscyA8LSBleHBhbmQuZ3JpZCh5ID0gMCA6IDEsIHggPSBzZXEoMCwgMSwgMSAvIG55IC8gMikgLSAxIC8gbnkgLyAyIC8gMikKZ3JpZC5wb2x5bGluZShscyR4LCBscyR5LCBpZCA9IGdsKG5yb3cobHMpIC8gMiwgMiksCiAgICAgICAgICAgICAgZ3AgPSBncGFyKGNvbCA9ICJncmV5IiwgbHdkID0gbHdkKSkKbHMgPC0gZXhwYW5kLmdyaWQoeCA9IHNlcSgwLCAxLCAxIC8gbnggLyAyKSAtIDEgLyBueCAvIDIgLyAyLAogICAgICAgICAgICAgICAgICB5ID0gc2VxKDAsIDEsIDEgLyBueSAvIDIpIC0gMSAvIG55IC8gMiAvIDIpCmdyaWQuY2lyY2xlKGxzJHgsIGxzJHksIHIgPSBjciwgZ3AgPSBncGFyKGNvbCA9IE5BLCBmaWxsID0gIndoaXRlIikpCmBgYAoKW0hlcm1hbm4gZ3JpZAppbGx1c2lvbl0oaHR0cHM6Ly9wc3ljaG9sb2d5LmZhbmRvbS5jb20vd2lraS9HcmlkX2lsbHVzaW9uI0hlcm1hbm5fZ3JpZF9pbGx1c2lvbik6CiJHaG9zdC1saWtlIiBncmV5IGJsb2JzIGF0IHRoZSBpbnRlcnNlY3Rpb25zIG9mIHdoaXRlIGxpbmVzLgoKYGBge3IsIGVjaG8gPSBGQUxTRX0KZ3JpZC5uZXdwYWdlKCkKZ3JpZC5yZWN0KDAuNSwgMC41LCAxLCAxLCBncCA9IGdwYXIoZmlsbCA9ICJibGFjayIpKQpncCA8LSBncGFyKGNvbCA9ICJ3aGl0ZSIsIGx3ZCA9IDIwKQpscyA8LSBleHBhbmQuZ3JpZCh4ID0gMCA6IDEsIHkgPSBzZXEoMCwgMSwgbGVuID0gbngpKQpncmlkLnBvbHlsaW5lKGxzJHgsIGxzJHksIGlkID0gZ2wobnJvdyhscykgLyAyLCAyKSwgZ3AgPSBncCkKZ3JpZC5wb2x5bGluZShscyR5LCBscyR4LCBpZCA9IGdsKG5yb3cobHMpIC8gMiwgMiksIGdwID0gZ3ApCmBgYAoKR3JpZCBpbGx1c2lvbiBpbiBhIGNhcnRvZ3JhbToKCjwhLS0gIyMgbm9saW50IHN0YXJ0OiBsaW5lX2xlbmd0aCAtLT4KPCEtLSBodHRwczovL3R3aXR0ZXIuY29tL2hyYnJtc3RyL3N0YXR1cy8xMjgxNjgxNDY5NDc2NDEzNDQ3IC0tPgpgYGB7ciwgZWNobyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgb3V0LndpZHRoID0gIjYwJSJ9CmxpYnJhcnkoZ2d0ZXh0KQpsaWJyYXJ5KHN0YXRlYmlucykKbGlicmFyeShocmJydGhlbWVzKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKCiMjIGpzb25saXRlOjpmcm9tSlNPTigKIyMgICAiaHR0cHM6Ly9zdGF0aWMwMS5ueXQuY29tL25ld3NncmFwaGljcy8yMDIwLzA2LzAyL3Rlc3RpbmctZGFzaGJvYXJkLzM2YTdmOWY3MWZiNjI3MTA3OGRmMzAxYjgwMTIxODUwMTZjODUxY2Yvc3RhdGVzLmpzb24iCiMjICkgLT4gY3ZkZgpjdmRmIDwtIGpzb25saXRlOjpmcm9tSlNPTihXTE5LKCJueXQtc3RhdGVzLTIwMjAtMDYtMDIuanNvbiIpKQoKY3ZkZiB8PgogIHVubmVzdChkYXRhKSB8PgogIG11dGF0ZShkYXRlID0gYXMuRGF0ZShkYXRlKSkgfD4KICBmaWx0ZXIoZGF0ZSA9PSBtYXgoZGF0ZSkpIHw+CiAgbXV0YXRlKHRlc3RfcGN0ID0gdGVzdHNfbmV3IC8gZXN0X3Rlc3RzX25lZWRlZCkgfD4KICBzZWxlY3QocG9zdGFsLCB0ZXN0X3BjdCkgfD4KICBtdXRhdGUoCiAgICBzdGF0dXMgPSBjYXNlX3doZW4oCiAgICAgIHRlc3RfcGN0ID4gMS4yIH4gImFib3ZlIiwKICAgICAgdGVzdF9wY3QgPCAwLjggfiAiYmVsb3ciLAogICAgICBUUlVFIH4gIm5lYXIiCiAgICApCiAgKSB8PgogIGdncGxvdCgpICsKICBnZW9tX3N0YXRlYmlucygKICAgIGFlcyhzdGF0ZSA9IHBvc3RhbCwgZmlsbCA9IHN0YXR1cykKICApICsKICBjb29yZF9maXhlZCgpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgIG5hbWUgPSBOVUxMLAogICAgdmFsdWVzID0gYygKICAgICAgIm5lYXIiID0gIiNmZWJmODIiLAogICAgICAiYmVsb3ciID0gIiNjNzYxNWIiLAogICAgICAiYWJvdmUiID0gIiNiYWNmYTIiCiAgICApCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIklzIFlvdXIgU3RhdGUgRG9pbmcgRW5vdWdoIENvcm9uYXZpcnVzIFRlc3Rpbmc/IiwKICAgIHN1YnRpdGxlID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojYmFjZmEyO2ZvbnQtc2l6ZToxNXB0Oyc+KioxMioqPC9zcGFuPiBzdGF0ZXMgbWVldCB0aGUgdGVzdGluZyB0YXJnZXQ7PGJyPiA8c3BhbiBzdHlsZT0nY29sb3I6I2ZlYmY4Mjtmb250LXNpemU6MTVwdDsnPioqNSoqPC9zcGFuPiBhcmUgbmVhciB0aGUgdGFyZ2V0OyA8c3BhbiBzdHlsZT0nY29sb3I6I2M3NjE1Yjtmb250LXNpemU6MTVwdDsnPioqMzQqKjwvc3Bhbj4gYXJlIGJlbG93IHRoZSB0YXJnZXQ7IiwKICAgIGNhcHRpb24gPSAiRGF0YSBzb3VyY2U6IE5ZVGltZXMgPHd3dy5ueXRpbWVzLmNvbS9pbnRlcmFjdGl2ZS8yMDIwL3VzL2Nvcm9uYXZpcnVzLXRlc3RpbmcuaHRtbD4iCiAgKSArCiAgdGhlbWVfaXBzdW1fZXMoZ3JpZCA9ICIiLCBwbG90X3RpdGxlX3NpemUgPSAxNSwgY2FwdGlvbl9zaXplID0gNykgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF9tYXJrZG93bihmYW1pbHkgPSBmb250X2VzLCBmYWNlID0gInBsYWluIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMC41LCBzaXplID0gMTApCiAgKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLCAxLCAxLCAxLjUpLCAiY20iKSkKYGBgCjwhLS0gIyMgbm9saW50IGVuZCAtLT4KCkEgY2FzZSB3aGVyZSB0aGVyZSBhcmUgbW9yZSBkb3RzIHRoYW4gd2UgY2FuIHNlZSBhdCBvbmNlOgo8IS0taHR0cHM6Ly90d2l0dGVyLmNvbS90ZXNsYXBoeC9zdGF0dXMvMTM3MzQzNjcyNjcyNzc0NTUzNz9zPTExIC0tPgoKYGBge3IgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiNDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoSU1HKCJkaXNhcHBlYXJpbmctZG90cy5qcGVnIikpCmBgYAoKUmVkIGZyb20gYmxhY2sgYW5kIHdoaXRlOgoKPCEtLSBodHRwczovL3R3aXR0ZXIuY29tL0FraXlvc2hpS2l0YW9rYS9zdGF0dXMvMTU5MTc4NDg5NzI4MjQ3ODA4MCAtLT4KCmBgYHtyIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKElNRygicmVkX2Zyb21fYmxhY2tfYW5kX3doaXRlLmpwZWciKSkKYGBgCgpTb21lIGlsbHVzaW9ucyBpbiBwaWN0dXJlczoKCjwhLS0gaHR0cHM6Ly90d2l0dGVyLmNvbS9ueHRob21wc29uL3N0YXR1cy8xMzU3MTQ3OTY4MzI4MTE4MjcyP3M9MTEgLS0+CmBgYHtyIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjUwJSIsIGZpZy5jYXAgPSAiQSBtYW4gcnVubmluZyBpbnRvIHRoZSBzbm93In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoSU1HKCJtYW5faW5fc25vdy5qcGVnIikpCmBgYAo8IS0tIGh0dHBzOi8vdHdpdHRlci5jb20vbWFya3lzdW1tL3N0YXR1cy8xMzM3NzI1ODUxNzk5MDU2Mzg2P3M9MTEgLS0+CmBgYHtyIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjUwJSIsIGZpZy5jYXAgPSAiT25jZSB5b3Ugc2VlIENvb2tpZSBNb25zdGVyLCB5b3UgY2Fu4oCZdCB1bnNlZSBpdCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKElNRygiY29va2llLW1vbnN0ZXIuanBlZyIpKQpgYGAKCkEgbGFyZ2UgY29sbGVjdGlvbiBvZiBvcHRpY2FsIGlsbHVzaW9ucyBpcyBhdmFpbGFibGUgYXQKPGh0dHBzOi8vbWljaGFlbGJhY2guZGUvb3QvaW5kZXguaHRtbD4uCgo8IS0tCk90aGVyIGxpbmtzIHRvIG9wdGljYWwgaWxsdXNpb25zIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly9vbmxpbmVtYXN0ZXJzLm9oaW8uZWR1L21hc3RlcnMtaGVhbHRoLWFkbWluaXN0cmF0aW9uL2hlYWx0aC1icmFpbi1nYW1lcy1vcHRpY2FsLWlsbHVzaW9ucy8pLgotLT4KCgojIyMgTW90aW9uCgpgYGB7ciBjaHVuay1sYWJlbCwgZmlnLndpZHRoID0gMTAsIGZpZy5zaG93PSdhbmltYXRlJywgZmZtcGVnLmZvcm1hdD0nZ2lmJywgZGV2PSdqcGVnJywgaW50ZXJ2YWwgPSAwLjEsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLWhpZGUifQpuIDwtIDUwCnggPC0gMiAqICgxIDogbikKeSA8LSByZXAoMiwgbikKbGltIDwtIGMobWluKHgpICsgMC4xICogKG1heCh4KSAtIG1pbih4KSksIG1heCh4KSAtIDAuMSAqIChtYXgoeCkgLSBtaW4oeCkpKQp2IDwtIFRSVUUKZm9yIChpIGluIDEgOiAyKSB7CiAgICBwbG90KHggKyB2LCB5LCB4bGltID0gbGltKQogICAgdiA8LSAhIHYKICAgIFN5cy5zbGVlcCgwLjEpCn0KYGBgCgo8IS0tIE1vcmUgbW90aW9uIGlsbHVzaW9uczoKICBodHRwczovL3R3aXR0ZXIuY29tL0FubmVMYXVyZV9EYXZpZC9zdGF0dXMvMTUxMzU5Nzk5MDY2OTI3MTA0NQogIGh0dHBzOi8vdHdpdHRlci5jb20vamFnYXJpa2luL3N0YXR1cy8xNTMxMTE1NzMxMjIzMzM5MDA4Ci0tPgoKYGBge3IsIGluY2x1ZGUgPSBGQUxTRX0KZ2lmX2ZpbGUgPC0gIjNkc2NhdHRlcl9wZXJjZXAuZ2lmIgppZiAoISBmaWxlLmV4aXN0cyhJTUcoZ2lmX2ZpbGUpKSkgewogICAgbGlicmFyeShyZ2wpCiAgICBkIDwtIGRhdGEuZnJhbWUoeCA9IHJub3JtKDEwMDApLCB5ID0gcm5vcm0oMTAwMCksIHogPSBybm9ybSgxMDAwKSkKICAgIHBvaW50czNkKGQpCiAgICBwYXIzZChGT1YgPSAxKSAgIyMgcmVtb3ZlcyBwZXJzcGVjdGl2ZSBkaXN0b3J0aW9uCiAgICBtb3ZpZTNkKAogICAgICAgIG1vdmllID0gc3ViKCJcXC4uKiIsICIiLCBnaWZfZmlsZSksCiAgICAgICAgc3BpbjNkKGF4aXMgPSBjKDAsIDAsIDEpLCBycG0gPSAyMCksCiAgICAgICAgZHVyYXRpb24gPSAzLAogICAgICAgIHR5cGUgPSAiZ2lmIiwKICAgICAgICBkaXIgPSBJTUcoIiIpLAogICAgICAgIGNsZWFuID0gVFJVRQogICAgKQogICAgIyMgcmUtc2F2ZSBzbyBpdCBsb29wcyBpbmRlZmluaXRlbHkKICAgIGltZyA8LSBtYWdpY2s6OmltYWdlX3JlYWQoSU1HKGdpZl9maWxlKSkKICAgIG1hZ2ljazo6aW1hZ2Vfd3JpdGUoaW1nLCBwYXRoID0gSU1HKGdpZl9maWxlKSkKfQpgYGAKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjc1JSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKElNRygiM2RzY2F0dGVyX3BlcmNlcC5naWYiKSkKYGBgCgpJbWFnZXMgY29udGFpbiBubyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGlyZWN0aW9uIG9mIHRoZSByb3RhdGlvbi4KCllvdXIgbWluZCBwaWNrcyBhIGRpcmVjdGlvbi4KCmBgYHtyLCBpbmNsdWRlID0gRkFMU0V9CmtuaXRyOjprbml0X2hvb2tzJHNldCh3ZWJnbCA9IHJnbDo6aG9va193ZWJnbCkKb3B0aW9ucyhyZ2wudXNlTlVMTCA9IFRSVUUpCmBgYApgYGB7ciwgd2ViZ2wgPSBUUlVFLCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0KbGlicmFyeShyZ2wpCmQgPC0gZGF0YS5mcmFtZSh4ID0gcm5vcm0oMTAwMCksIHkgPSBybm9ybSgxMDAwKSwgeiA9IHJub3JtKDEwMDApKQpwb2ludHMzZChkKQpwYXIzZChGT1YgPSAxKSAgIyMgcmVtb3ZlcyBwZXJzcGVjdGl2ZSBkaXN0b3J0aW9uCmlmIChpbnRlcmFjdGl2ZSgpKQogICAgcGxheTNkKHNwaW4zZChheGlzID0gYygwLCAwLCAxKSwgcnBtID0gMzApLCBkdXJhdGlvbiA9IDIwKQpgYGAKCkludGVyYWN0aXZlIHJvdGF0aW9uIGNhbiBoZWxwLgoKRGVwdGggY3VlaW5nIGFuZCBwZXJzcGVjdGl2ZSBjYW4gYWxzbyBoZWxwLgoKCiMjIyBQb3BvdXQgYW5kIERpc3RyYWN0b3JzCgpXaGVyZSBpcyB0aGUgcmVkIGRvdDoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CnRobSA8LSB0aGVtZV9jbGFzc2ljKCkKdGhtIDwtIGxpc3QodGhlbWVfdm9pZCgpLAogICAgICAgICAgICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BLCBjb2xvciA9ICJncmV5MjAiKSksCiAgICAgICAgICAgIGd1aWRlcyhjb2xvciA9ICJub25lIiwgc2hhcGUgPSAibm9uZSIpLAogICAgICAgICAgICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYyhBID0gMTYsIEIgPSAxNSkpLAogICAgICAgICAgICBjb29yZF9lcXVhbCgpLCB4bGltKGMoMCwgMSkpLCB5bGltKGMoMCwgMSkpKQoKcHRzIDwtIGZ1bmN0aW9uKG4sIHZlcnNpb24sIHN6ID0gMykgewogICAgaWR4IDwtIHNlcV9sZW4obikKICAgIGlmICh2ZXJzaW9uID09IDEpIHsKICAgICAgICB2MSA8LSBpZmVsc2UoaWR4ID09IDEsICJBIiwgIkIiKQogICAgICAgIHYyIDwtICJBIgogICAgfQogICAgZWxzZSBpZiAodmVyc2lvbiA9PSAyKSB7CiAgICAgICAgdjEgPC0gIkEiCiAgICAgICAgdjIgPC0gaWZlbHNlKGlkeCA9PSAxLCAiQSIsICJCIikKICAgIH0KICAgIGVsc2UgaWYgKHZlcnNpb24gPT0gMykgewogICAgICAgIHYxIDwtIGlmZWxzZShpZHggPT0gMSB8IGlkeCA+IChuIC8gMiksICJBIiwgIkIiKQogICAgICAgIHYyIDwtIGlmZWxzZShpZHggPD0gKG4gLyAyKSwgIkEiLCAiQiIpCiAgICB9CiAgICBkIDwtIGRhdGEuZnJhbWUoeCA9IHJ1bmlmKG4pLCB5ID0gcnVuaWYobiksIHYxID0gdjEsIHYyID0gdjIpCiAgICBnZ3Bsb3QoZCwgYWVzKHgsIHksIGNvbG9yID0gdjEsIHNoYXBlID0gdjIpKSArIGdlb21fcG9pbnQoc2l6ZSA9IHN6KSArIHRobQp9CgpwMSA8LSBwdHMoMTAsIDEpCnAyIDwtIHB0cygxMDAsIDEpCnAzIDwtIHB0cygxMCwgMikKcDQgPC0gcHRzKDEwMCwgMikKcDUgPC0gcHRzKDEwLCAzKQpwNiA8LSBwdHMoMTAwLCAzKQpgYGAKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGRwaSA9IDMwMCwgb3V0LndpZHRoID0gIjYwJSJ9CmdyaWQuYXJyYW5nZShwMSwgcDIsIG5yb3cgPSAxKQpgYGAKClNoYXBlIG9ubHk6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBkcGkgPSAzMDAsIG91dC53aWR0aCA9ICI2MCUifQpncmlkLmFycmFuZ2UocDMsIHA0LCBucm93ID0gMSkKYGBgCgpTaGFwZXMgYW5kIGNvbG9yczoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGRwaSA9IDMwMCwgb3V0LndpZHRoID0gIjYwJSJ9CmdyaWQuYXJyYW5nZShwNSwgcDYsIG5yb3cgPSAxKQpgYGAKCgojIyBJdGVtcywgQXR0cmlidXRlcywgTWFya3MsIGFuZCBDaGFubmVscwoKVG8gZXZhbHVhdGUgb3IgZGVzaWduIGEgdmlzdWFsaXphdGlvbiBpdCBpcyB1c2VmdWwgdG8gaGF2ZSBzb21lIHRlcm1zCmZvciB0aGUgY29tcG9uZW50cy4KClNldmVyYWwgc2Nob29scyBoYXZlIGRldmVsb3BlZCBkaWZmZXJlbnQgYnV0IHNpbWlsYXIgc2V0cyBvZiB0ZXJtcy4KClNvbWUgUmVmZXJlbmNlczoKCiogQmVydGluLCBKLiAoMTk2NyksIF9UaGUgU2VtaW9sb2d5IG9mIEdyYXBoaWNzXy4KKiBDbGV2ZWxhbmQsIFcuIFMuICgxOTg4KSwgX1RoZSBFbGVtZW50cyBvZiBHcmFwaGluZyBEYXRhXy4KKiBDbGV2ZWxhbmQsIFcuIFMuICgxOTkzKSwgX1Zpc3VhbGl6aW5nIERhdGFfLgoqIEZldywgUy4gKDIwMTIpLCBfU2hvdyBNZSB0aGUgTnVtYmVyczogRGVzaWduaW5nIFRhYmxlcyBhbmQgR3JhcGhzIHRvCiAgRW5saWdodGVuXywgMm5kIGVkLgoqIE11bnpuZXIsIFQuICgyMDE0KSwgX1Zpc3VhbGl6YXRpb24gQW5hbHlzaXMgYW5kIERlc2lnbl8KKiBXYXJlLCBDLiAoMjAxMiksIF9JbmZvcm1hdGlvbiBWaXN1YWxpemF0aW9uOiBQZXJjZXB0aW9uIGZvciBEZXNpZ25fLCAzcmQgZWQuCiogV2lsa2luc29uLCBMLiAoMjAwNSksIF9UaGUgR3JhbW1hciBvZiBHcmFwaGljc18sIDJuZCBlZC4KCk11bnpuZXIgdXNlcyB0aGUgdGVybWlub2xvZ3kgb2YgX2l0ZW1zXywgX2F0dHJpYnV0ZXNfLCBfbGlua3NfLApfbWFya3NfLCBhbmQgX2NoYW5uZWxzXzoKCiogX0l0ZW1zXyBhcmUgdGhlIGJhc2ljIHVuaXRzIG9uIHdoaWNoIGRhdGEgaXMgY29sbGVjdGVkOiB0aGUgZW50aXRpZXMKICByZXByZXNlbnRlZCBieSB0aGUgcm93cyBpbiBhIF90aWR5XyBkYXRhIGZyYW1lLgoKKiBfQXR0cmlidXRlc18gYXJlIHRoZSBudW1lcmljYWwgb3IgY2F0ZWdvcmljYWwgZmVhdHVyZXMgb2YgdGhlIGRhdGEKICBpdGVtcyB3ZSB3YW50IHRvIHJlcHJlc2VudDsgdGhlIHZhcmlhYmxlcyBpbiBhIHRpZHkgZGF0YSBmcmFtZS4KCiogX0xpbmtzXyBhcmUgcmVsYXRpb25zIGFtb25nIGl0ZW1zOiBlLmcuIG1vbnRocyB3aXRoaW4gYSB5ZWFyLCBvcgogIGNvdW50cmllcyB3aXRoaW4gYSBjb250aW5lbnQuCgoqIF9NYXJrc18gYXJlIHRoZSBnZW9tZXRyaWMgZW50aXRpZXMgdXNlZCB0byByZXByZXNlbnQgaXRlbXM6IHBvaW50cywKICBsaW5lcywgYXJlYXMuIFRoZXNlIGNvcnJlc3BvbmQgdG8gdGhlIHNpbXBsZSBgZ2VvbWAgb2JqZWN0cyBpbgogIGBnZ3Bsb3RgLgoKKiBfVmlzdWFsIGNoYW5uZWxzXyBhcmUgZmVhdHVyZXMgb2YgbWFya3MgdGhhdCBjYW4gYmUgdXNlZCB0byByZWZsZWN0CiAgdmFsdWVzIG9mIGF0dHJpYnV0ZXMuCgpDaGFubmVscyBjb3JyZXNwb25kIGFwcHJveGltYXRlbHkgdG8gYWVzdGhldGljcyBpbiBgZ2dwbG90YCBidXQgYXJlCm1vcmUgZm9jdXNlZCBvbiB0aGUgdmlzdWFsIGFzcGVjdDoKCiogQW4gYHhgIGFlc3RoZXRpYyB0aGF0IGlzIHRyYW5zZm9ybWVkIHRvIHBvbGFyIGNvb3JkaW5hdGVzIGlzIGEKICBkaWZmZXJlbnQgY2hhbm5lbCB0aGFuIGFuIGB4YCBhZXN0aGV0aWMgcmVwcmVzZW50aW5nIGEgcG9zaXRpb24gb24gYQogIHN0YW5kYXJkIGxpbmVhciBzY2FsZS4KCkNoYW5uZWxzIGFyZSB1c2VkIHRvIF9lbmNvZGVfIGF0dHJpYnV0ZXMgKF9hZXN0aGV0aWMgbWFwcGluZ3NfKS4KCkEgc2luZ2xlIGF0dHJpYnV0ZSBjYW4gYmUgZW5jb2RlZCBpbiBzZXZlcmFsIGNoYW5uZWxzLgoKKiBUaGlzIG1ha2VzIHRoZSBhdHRyaWJ1dGUgZWFzaWVyIHRvIHBlcmNlaXZlLgoKKiBCdXQgaXQgYWxzbyB1c2VzIHVwIGF2YWlsYWJsZSBjaGFubmVscy4KClNvbWUgY2hhbm5lbHMgYXJlIHdlbGwgc3VpdGVkIHRvIGVuY29kZSBxdWFudGl0YXRpdmUgb3Igb3JkZXJlZAp2YWx1ZXM7IHRoZXkgYXJlIF9xdWFudGl0YXRpdmVseSBwZXJjZWl2ZWRfLgoKT3RoZXJzIGFyZSBvbmx5IHN1aXRlZCBmb3Igbm9taW5hbCB2YWx1ZXMuCgpBIHVzZWZ1bCBjbGFzc2lmaWNhdGlvbiwgYWRhcHRlZCBmcm9tIEZldygyMDEyKToKCnwgVHlwZSAgICAgfCAgQ2hhbm5lbCAgICB8ICBRdWFudGl0YXRpdmVseSBQZXJjZWl2ZWQ/ICB8Cnw6LS0tLS0tLS0tfDotLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8CnwgRm9ybSAgICAgfCBMZW5ndGggICAgICB8IFllcyAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgfCBXaWR0aCAgICAgICB8IFllcywgYnV0IGxpbWl0ZWQgICAgICAgICAgICB8CnwgICAgICAgICAgfCBPcmllbnRhdGlvbiB8IE5vICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgfCBTaXplICAgICAgICB8IFllcywgYnV0IGxpbWl0ZWQgICAgICAgICAgICB8CnwgICAgICAgICAgfCBTaGFwZSAgICAgICB8IE5vICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgQ29sb3IgICAgfCBIdWUgICAgICAgICB8IE5vICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgfCBJbnRlbnNpdHkgICB8IFllcywgYnV0IGxpbWl0ZWQgICAgICAgICAgICB8CnwgUG9zaXRpb24gfCAyRCBwb3NpdGlvbiB8IFllcyAgICAgICAgICAgICAgICAgICAgICAgICB8CgpNdW56bmVyIHVzZXMgdGhlIHRlcm1zIF9tYWduaXR1ZGUgY2hhbm5lbHNfIGFuZCBfaWRlbnRpdHkgY2hhbm5lbHNfLgoKSWRlYWxseSwKCiogbnVtZXJpYyBhbmQgb3JkZXJlZCBhdHRyaWJ1dGVzIHNob3VsZCBiZSByZXByZXNlbnRlZCBieSBxdWFudGl0YXRpdmVseQogIHBlcmNlaXZlZCBjaGFubmVsczsKCiogdW5vcmRlcmVkIGNhdGVnb3JpY2FsIGF0dHJpYnV0ZXMgc2hvdWxkIGJlIHJlcHJlc2VudGVkIGJ5CiAgbm9uLXF1YW50aXRhdGl2ZSBjaGFubmVscy4KCkEgdXNlZnVsIHByaW5jaXBsZTogVGhlIG1vc3QgaW1wb3J0YW50IGF0dHJpYnV0ZXMgc2hvdWxkIGJlIG1hcHBlZCB0bwp0aGUgbW9zdCBlZmZlY3RpdmUgY2hhbm5lbHMuCgoKIyMgQ2hhbm5lbCBFZmZlY3RpdmVuZXNzCgpTb21lIHF1ZXN0aW9ucyBhYm91dCBjaGFubmVsczoKCiogV2hhdCBraW5kIGFuZCBob3cgbXVjaCBpbmZvcm1hdGlvbiBjYW4gYSBjaGFubmVsIGVuY29kZT8KCiogQXJlIHNvbWUgY2hhbm5lbHMgYmV0dGVyIHRoYW4gb3RoZXJzPwoKKiBDYW4gY2hhbm5lbHMgYmUgdXNlZCBpbmRlcGVuZGVudGx5LCBvciBkbyB0aGV5IGludGVyZmVyZT8KClNvbWUgY3JpdGVyaWEgZm9yIGV2YWx1YXRpbmcgY2hhbm5lbHM6CgoqIEFjY3VyYWN5OiBIb3cgd2VsbCBjYW4gYSB2aWV3ZXIgZGVjb2RlIHRoZSBpbmZvcm1hdGlvbiBpbiB0aGUgY2hhbm5lbD8KCiogRGlzY3JpbWluYWJpbGl0eTogSG93IGVhc2lseSBjYW4gZGlmZmVyZW5jZXMgYmV0d2VlbiBhdHRyaWJ1dGUKICBsZXZlbHMgYmUgcGVyY2VpdmVkPwoKKiBTZXBhcmFiaWxpdHk6IENhbiBjaGFubmVscyBiZSB1c2VkIGluZGVwZW5kZW50bHkgb3IgaXMgdGhlcmUKICBpbnRlcmZlcmVuY2U/CgoqIFBvcG91dDogY2FuIGEgY2hhbm5lbCBwcm92aWRlIF9wb3BvdXRfIHdoZXJlIGEgZGlmZmVyZW5jZSBpcyBwZXJjZWl2ZWQKICBwcmVhdHRlbnRpdmVseT8KCiogR3JvdXBpbmc6IGNhbiBhIGNoYW5uZWwgc2hvdyBwZXJjZXB0dWFsIGdyb3VwaW5nIG9mIGl0ZW1zPwoKCiMjIyBDaGFubmVsIEFjY3VyYWN5CgpTdGV2ZW5zICgxOTU3KSBhcmd1ZXMgdGhhdCBhY2N1cmFjeSBvZiBtYWduaXR1ZGUgY2hhbm5lbHMgY2FuIGJlCmRlc2NyaWJlZCBieSBhIHBvd2VyIGxhdzoKCiQkIFx0ZXh0e3BlcmNlaXZlZCBzZW5zYXRpb259ID0gKFx0ZXh0e3BoeXNpY2FsIGludGVuc2l0eX0pXlxnYW1tYSAkJAoKRXhwZXJpbWVudHMgYnkgU3RldmVucyBzdWdnZXN0IHRoZXNlIHZhbHVlcyBmb3Igc29tZSB2aXN1YWwgY2hhbm5lbHM6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuaGVpZ2h0ID0gNH0KbiA8LSAxMDAKeCA8LSBzZXEoMCwgNSwgbGVuID0gbikKZ2FtbWEgPC0gYygwLjUsIDAuNjcsIDAuNywgMSwgMS43KQpjaGFuIDwtIGMoIkJyaWdodG5lc3MiLCAiRGVwdGgiLCAiQXJlYSIsICJMZW5ndGgiLCAiU3RhdHVyYXRpb24iKQpsYWJlbCA8LSBzcHJpbnRmKCIlcyAoJS4yZikiLCBjaGFuLCBnYW1tYSkKbmMgPC0gbGVuZ3RoKGdhbW1hKQpkIDwtIGRhdGEuZnJhbWUoSW50ZW5zaXR5ID0gcmVwKHgsIG5jKSwKICAgICAgICAgICAgICAgIGdhbW1hID0gcmVwKGdhbW1hLCBlYWNoID0gbiksCiAgICAgICAgICAgICAgICBsYWJlbCA9IHJlcChsYWJlbCwgZWFjaCA9IG4pKQpwIDwtIGdncGxvdChkLCBhZXMoeCA9IEludGVuc2l0eSwgeSA9IEludGVuc2l0eSBeIGdhbW1hKSkgKwogICAgZ2VvbV9saW5lKGFlcyhncm91cCA9IGdhbW1hLCBjb2xvciA9IGxhYmVsKSwKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLjUpICsgeWxpbShjKDAsIDUpKSArCiAgICBsYWJzKHggPSAiUGhpc2ljYWwgSW50ZW5zaXR5IiwgeSA9ICJQZXJjZWl2ZWQgU2Vuc2F0aW9uIikgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGNvbG9yID0gImdyZXkyMCIpKQpzdXBwcmVzc1dhcm5pbmdzKHByaW50KHApKQpgYGAKCltPdGhlcnMgaGF2ZSByYWlzZWQgY29uY2VybnNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1N0ZXZlbnMlMjdzX3Bvd2VyX2xhdykKYWJvdXQgdGhlIHZhbGlkaXR5IG9mIHRoZXNlIGZpbmRpbmdzLgoKPCEtLQoKIyMjIEFzcGVjdCBSYXRpbwpgYGB7ciwgZXZhbCA9IEZBTFNFfQpyaXZlciA8LSBzY2FuKCJodHRwczovL3d3dy5zdGF0LnVpb3dhLmVkdS9+bHVrZS9kYXRhL3JpdmVyLmRhdCIpCnBsb3Qocml2ZXIpCmBgYAoKKioqKiBtaXNsZWFkaW5nIGV4YW1wbGUgZnJvbSBIVzIgYXMgc2xvcGVzCi0tPgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IEZBTFNFfQojIyBDb2xvciB3aGVlbCBmb3IgaHVlOgpuIDwtIDcyCnBpZShyZXAoMSwgbiksIGNvbCA9IGhzdigoMSA6IG4pIC8gbiwgMSwgMSksIGJvcmRlciA9IE5BLCBsYWJlbHMgPSBOQSkKYGBgCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gRkFMU0V9CiMjIFZhbHVlIGFuZCBzYXR1cmF0aW9uCnBsb3QoMCwgdHlwZSA9ICJuIiwgYXNwID0gMSwKICAgICB4bGltID0gYygwLCAxKSwgeWxpbSA9IGMoMCwgMSksCiAgICAgYXhlcyA9IEZBTFNFLCB4bGFiID0gInZhbHVlL2xpZ2h0bmVzcyIsIHlsYWIgPSAic2F0dXJhdGlvbiIsCiAgICAgbWFyID0gYygwLCAwLCAwLCAwKSkKCm4gPC0gMzIKeCA8LSBzZXEoMCwgMSwgbGVuZ3RoLm91dCA9IG4pWy1uXQpodWUgPC0gcmdiMmhzdihjb2wycmdiKCJibHVlIikpW1siaCIsIDFdXQoKZGVseCA8LSBtZWFuKGRpZmYoeCkpCmRlbHkgPC0gMSAvIG4KZm9yIChpIGluIDEgOiBuKQogICAgcmVjdCh4LCBkZWx5ICogKGkgLSAxKSwgeCArIGRlbHgsIGRlbHkgKiBpLAogICAgICAgICBjb2wgPSBoc3YoaHVlLCBkZWx5ICogaSwgeCArIGRlbHgpLCBib3JkZXIgPSBOQSkKYGBgCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gRkFMU0V9CiMjIEFub3RoZXIgYXBwcm9hY2gKb3BhciA8LSBwYXIobWZyb3cgPSBjKDIsIDEpKQpuIDwtIDY0CnggPC0gc2VxKDAsIDEsIGxlbmd0aC5vdXQgPSBuKVstbl0KaHVlIDwtIHJnYjJoc3YoY29sMnJnYigiYmx1ZSIpKVtbImgiLCAxXV0KZGVseCA8LSBtZWFuKGRpZmYoeCkpCgpwbG90KDAsIHR5cGUgPSAibiIsIHhsaW0gPSBjKDAsIDEpLCB5bGltID0gYygwLCAxKSwKICAgICBheGVzID0gRkFMU0UsIHhsYWIgPSAiIiwgeWxhYiA9ICIiLCBtYXIgPSBjKDAsIDAsIDAsIDApKQpyZWN0KHgsIDAuMiwgeCArIGRlbHgsIDAuNywgY29sID0gaHN2KGh1ZSwgeCwgMSksIGJvcmRlciA9IE5BKQp0aXRsZSgiU2F0dXJhdGlvbiIpCgpwbG90KDAsIHR5cGUgPSAibiIsIHhsaW0gPSBjKDAsIDEpLCB5bGltID0gYygwLCAxKSwKICAgICBheGVzID0gRkFMU0UsIHhsYWIgPSAiIiwgeWxhYiA9ICIiLCBtYXIgPSBjKDAsIDAsIDAsIDApKQpyZWN0KHgsIDAuMiwgeCArIGRlbHgsIDAuNywgY29sID0gaHN2KGh1ZSwgMSwgeCksIGJvcmRlciA9IE5BKQp0aXRsZSgiVmFsdWUiKQoKcGFyKG9wYXIpCmBgYAoKQW5vdGhlciBhcHByb2FjaCBoYXMgdXNlZCBjb250cm9sbGVkIGV4cGVyaW1lbnRzIHRvIGFzc2VzcyBhY2N1cmFjeSBvZgp2YXJpb3VzIGNoYW5uZWxzIHVzZWQgaW4gdmlzdWFsaXphdGlvbnM6CgoqIFdpbGxpYW0gUy4gQ2xldmVsYW5kIGFuZCBSb2JlcnQgTWNHaWxsICgxOTg0KSwgIkdyYXBoaWNhbAogIFBlcmNlcHRpb246IFRoZW9yeSwgRXhwZXJpbWVudGF0aW9uLCBhbmQgQXBwbGljYXRpb24gdG8gdGhlCiAgRGV2ZWxvcG1lbnQgb2YgR3JhcGhpY2FsIE1ldGhvZHMsIiBfSm91cm5hbCBvZiB0aGUgQW1lcmljYW4KICBTdGF0aXN0aWNhbCBBc3NvY2lhdGlvbl8gNzksIDUzMeKAkzU1NC4KCiogV2lsbGlhbSBTLiBDbGV2ZWxhbmQgYW5kIFJvYmVydCBNY0dpbGwgKDE5ODcpLCAiR3JhcGhpY2FsCiAgUGVyY2VwdGlvbjogVGhlIFZpc3VhbCBEZWNvZGluZyBvZiBRdWFudGl0YXRpdmUgSW5mb3JtYXRpb24gb24KICBHcmFwaGljYWwgRGlzcGxheXMgb2YgRGF0YSIgX0pvdXJuYWwgb2YgdGhlIFJveWFsIFN0YXRpc3RpY2FsCiAgU29jaWV0eS4gU2VyaWVzIEFfLCAxOTItMjI5LgoKKiBKZWZmcmV5IEhlZXIgYW5kIE1pY2hhZWwgQm9zdG9jayAoMjAxMCkgIkNyb3dkc291cmNpbmcgR3JhcGhpY2FsCiAgUGVyY2VwdGlvbjogVXNpbmcgTWVjaGFuaWNhbCBUdXJrIHRvIEFzc2VzcyBWaXN1YWxpemF0aW9uIERlc2lnbiwiCiAgX1Byb2NlZWRpbmdzIG9mIHRoZSBTSUdDSElfLCAyMDMtMjEyLgoKTXVuem5lcidzIG9yZGVyaW5nIGJ5IGFjY3VyYWN5OgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoSU1HKCJ0bW1jaGFubmVscy5qcGVnIikpCmBgYApUaGlzIG9yZGVyaW5nIGlzIHNvbWV0aW1lcyByZWZlcnJlZCB0byBhcyBhIF9wZXJjZXB0dWFsIGxhZGRlcl8uCgo8IS0tCk1hZ25pdHVkZSBDaGFubmVscyAoT3JkZXJlZCwgTnVtZXJpY2FsKSAgICBJZGVudGl0eSBDaGFubmVscyAoQ2F0ZWdvcmljYWwpCi0tLS0tLS0tLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLS0tLQpQb3NpdGlvbiBvbiBjb21tb24gc2NhbGUgICAgICAgICAgICAgICAgICAgU3BhdGlhbCBncm91cGluZwpQb3NpdGlvbiBvbiB1bmFsaWduZWQgc2NhbGUgICAgICAgICAgICAgICAgQ29sb3IgaHVlCkxlbmd0aCAoMUQgc2l6ZSkgICAgICAgICAgICAgICAgICAgICAgICAgICBTaGFwZQpUaWx0LCBhbmdsZQpBcmVhICgyRCBzaXplKQpEZXB0aCAoM0QgcG9zaXRpb24pCkNvbG9yIGx1bWluYW5jZSwgc2F0dXJhdGlvbgpDdXJ2YXR1cmUsIHZvbHVtZSAoM0Qgc2l6ZSkKLS0+CgpMaW5lIHdpZHRoIGlzIGFub3RoZXIgY2hhbm5lbDsgbm90IHN1cmUgdGhlcmUgaXMgYWdyZWVtZW50IG9uIGl0cwphY2N1cmFjeSwgYnV0IGl0IGlzIG5vdCBoaWdoLgoKCiMjIyBEaXNjcmltaW5hYmlsaXR5CgpNYW55IGNoYW5uZWxzLCBpbiBwYXJ0aWN1bGFyIGlkZW50aXR5IGNoYW5uZWxzLCBjYW4gb25seSBzdXBwb3J0IGEKbGltaXRlZCBudW1iZXIgb2YgZGlzY3JpbWluYWJsZSBsZXZlbHMuCgoqIExpbmUgd2lkdGggaXMgb25lIG9mIHRoZSBtb3N0IGxpbWl0ZWQgd2l0aCBwZXJoYXBzIDMgbGV2ZWxzLgoKKiBVc2luZyBtb3JlIHRoYW4gNSBvciA2IGNvbG9yIGh1ZXMgaXMgbm90IHJlY29tbWVuZGVkLgoKKiBTaW1pbGFybHksIHVzaW5nIG1vcmUgdGhhbiA1IG9yIDYgc3ltYm9sIHNoYXBlcyBjYW4gY3JlYXRlIGRpZmZpY3VsdGllcy4KCklmIHRoZSBudW1iZXIgb2YgbGV2ZWxzIHRoYXQgY2FuIGJlIHJlcHJlc2VudGVkIGJ5IGEgY2hhbm5lbCBpcwpzbWFsbGVyIHRoYW4gdGhlIG51bWJlciBvZiBhdHRyaWJ1dGUgbGV2ZWxzIHRoZW4gc29tZSBmb3JtIG9mCm1lYW5pbmdmdWwgYWdncmVnYXRpb24gaXMgbmVlZGVkLgoKCiMjIyBTZXBhcmFiaWxpdHkKClNvbWUgZW5jb2RpbmdzIGNhbiBiZSB1c2VkIGluZGVwZW5kZW50bHkgb2YgZWFjaCBvdGhlcjsgb3RoZXJzCmludGVyZmVyZSB3aXRoIGVhY2ggb3RoZXIgdG8gc29tZSBkZWdyZWUuCgo8IS0tICoqKiogc29tZXRoaW5nIGxpa2UgTXVuem5lciBGaWcgNS4xMCAtLT4KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjU1JSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKElNRygiVE1maWc1LjEwLmpwZyIpKQpgYGAKCiogVmVydGljYWwgYW4gaG9yaXpvbnRhbCBwb3NpdGlvbiBjYW4gYmUgdXNlZCBpbmRlcGVuZGVudGx5LgoKKiBDb2xvciAoaHVlKSBhbmQgcG9zaXRpb24gY2FuIGJlIHVzZWQgaW5kZXBlbmRlbnRseQoKKiBTaXplIGFuZCBodWUgaW50ZXJmZXJlIHNvbWV3aGF0OyBodWUgaXMgaGFyZGVyIHRvIHBlcmNlaXZlIG9uCiAgc21hbGxlciBvYmplY3RzLgoKKiBXaWR0aCBhbmQgaGVpZ2h0IGRvIG5vdCBmdW5jdGlvbiB3ZWxsIGluZGVwZW5kZW50bHk7IHRoZSByZXN1bHQgaXMKICBwZXJjZWl2ZWQgcHJpbWFyaWx5IGFzIHNoYXBlLgoKKiBFbmNvZGluZyB0d28gZGlmZmVyZW50IHZhbHVlcyBpbiB0aGUgcmVkIGFuZCBncmVlbiBjaGFubmVscyBhcyBhIGh1ZQogIGRvZXMgbm90IHdvcmsgYXQgYWxsLgoKCiMjIyBQb3BvdXQKCk1hbnkgY2hhbm5lbHMgc3VwcG9ydCBfdmlzdWFsIHBvcG91dF86IGhhdmluZyBvbmUgaXRlbSBvciBhIGZldyBpdGVtcwppbW1lZGlhdGVseSBzdGFuZCBvdXQgZnJvbSB0aGUgb3RoZXJzLgoKKiBDb2xvciAoaHVlIGFuZCBpbnRlbnNpdHkpIGRvIHRoaXMgd2VsbC4KCiogU2hhcGUgYW5kIHNpemUgY2FuIGFsc28gYmUgdXNlZCBlZmZlY3RpdmVseSB0byBjcmVhdGUgcG9wb3V0LgoKQW5ub3RhdGlvbiBjYW4gYWxzbyBiZSB1c2VkIHRvIGNyZWF0ZSBwb3BvdXQuCgoKIyMjIEdyb3VwaW5nCgpQZXJjZXB0dWFsIGdyb3VwaW5nIGNhbiBiZSBhY2hpZXZlZCBpbiBzZXZlcmFsIHdheXM6CgoqIFVzaW5nIGFuIGlkZW50aXR5IGNoYW5uZWwgdG8gdG8gcmVwcmVzZW50IGl0ZW1zIGFzIGEgZ3JvdXAuCgoqIFVzaW5nIF9saW5rIG1hcmtzXy4KCiogQnkgX2VuY2xvc3VyZV8uCgoqIEJ5IHNwYXRpYWwgcHJveGltaXR5LgoKYGBge3IsIGVjaG8gPSBGQUxTRX0KZDEgPC0gZGF0YS5mcmFtZSh4ID0gYygxLCAyLCAzLCA0LCAxLCAyLCAzLCA0KSwKICAgICAgICAgICAgICAgICB5ID0gYygxLCAyLCAxLCAxLjUsIDYsIDUuNSwgNiwgNSksCiAgICAgICAgICAgICAgICAgdiA9IHJlcChjKCJBIiwgIkIiKSwgZWFjaCA9IDQpKQpwMSA8LSBnZ3Bsb3QoZDEsIGFlcyh4LCB5LCBjb2xvciA9IHYpKSArIGdlb21fcG9pbnQoc2l6ZSA9IDQpICsKICAgIHRoZW1lX3ZvaWQoKSArIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogICAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3IgPSAiZ3JleTIwIikpCmBgYAoKYGBge3IsIGVjaG8gPSBGQUxTRX0KZDEgPC0gZGF0YS5mcmFtZSh4ID0gYygxLCAyLCAzLCA0LCAxLCAyLCAzLCA0KSwKICAgICAgICAgICAgICAgICB5ID0gYygxLCAyLCAxLCAxLjUsIDYsIDUuNSwgNiwgNSksCiAgICAgICAgICAgICAgICAgdiA9IHJlcChjKCJBIiwgIkIiKSwgZWFjaCA9IDQpKQpwMiA8LSBnZ3Bsb3QoZDEsIGFlcyh4LCB5LCBjb2xvciA9IHYpKSArCiAgICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gdiksIGNvbG9yID0gImJsYWNrIikgKwogICAgZ2VvbV9wb2ludChzaXplID0gNCkgKyB0aGVtZV92b2lkKCkgKyBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICAgIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGNvbG9yID0gImdyZXkyMCIpKQpgYGAKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmQzIDwtIGRhdGEuZnJhbWUoeCA9IGMoMSwgMSwgMywgMyksCiAgICAgICAgICAgICAgICAgeSA9IGMoMSwgLTEsIDEsIC0xKSwKICAgICAgICAgICAgICAgICBzID0gYyg1LCAxMCwgMTAsIDUpKQpkMyRpIDwtIGZhY3RvcihzZXFfYWxvbmcoZDMkeCkgJSUgMikKcDMgPC0gZ2dwbG90KGQzKSArCiAgICBnZW9tX3JlY3QoYWVzKHhtaW4gPSAwLjYsIHltaW4gPSAtMS41LCB4bWF4ID0gMS41LCB5bWF4ID0gMS41KSwKICAgICAgICAgICAgICBmaWxsID0gImdyYXkiKSArCiAgICBnZW9tX3BvaW50KGFlcyh4ID0geCwgeSA9IHksIHNpemUgPSBzLCBjb2xvciA9IGkpKSArCiAgICBzY2FsZV9zaXplX2FyZWEobWF4X3NpemUgPSAxMCkgKwogICAgZ3VpZGVzKHNpemUgPSAibm9uZSIsIGNvbG9yID0gIm5vbmUiKSArIHRoZW1lX3ZvaWQoKSArCiAgICB4bGltKGMoMCwgNCkpICsgeWxpbShjKC0yLCAyKSkgKwogICAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3IgPSAiZ3JleTIwIikpCmBgYAoKYGBge3IsIGVjaG8gPSBGQUxTRX0KZDQgPC0gZGF0YS5mcmFtZSh4ID0gYygxLCAyLCAzLCAxMCwgMTAsIDEyKSwKICAgICAgICAgICAgICAgICB5ID0gYygxLCAtMSwgMSwgNiwgOCwgNiksCiAgICAgICAgICAgICAgICAgcyA9IGMoNSwgMTAsIDEwLCA1LCA1LCAxMCkpCmQ0JGkgPC0gZmFjdG9yKHNlcV9hbG9uZyhkNCR4KSAlJSAyKQpwNCA8LSBnZ3Bsb3QoZDQpICsgZ2VvbV9wb2ludChhZXMoeCA9IHgsIHkgPSB5LCBzaXplID0gcywgY29sb3IgPSBpKSkgKwogICAgc2NhbGVfc2l6ZV9hcmVhKG1heF9zaXplID0gMTUpICsKICAgIGd1aWRlcyhzaXplID0gIm5vbmUiLCBjb2xvciA9ICJub25lIikgKyB0aGVtZV92b2lkKCkgKwogICAgeWxpbShjKC0yLCA5KSkgKyB4bGltKGMoMCwgMTMpKSArCiAgICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BLCBjb2xvciA9ICJncmV5MjAiKSkKYGBgCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpncmlkLmFycmFuZ2UocDEsIHAyLCBwMywgcDQsIG5yb3cgPSAyKQpgYGAKCgojIyBFeHBlcmltZW50YWwgRXZpZGVuY2UKCgojIyMgQ2xldmVsYW5kLU1jR2lsbAoKVGhlIDE5ODQgcGFwZXIgaXMgYXZhaWxhYmxlIGZyb20KW0pTVE9SXShodHRwczovL3d3dy5qc3Rvci5vcmcvc3RhYmxlLzIyODg0MDApLgoKVGhlIHBhcGVyIGZvcm11bGF0ZXMgYSB0aGVvcnkgZm9yIHJhbmtpbmcgX0VsZW1lbnRhcnkgUGVyY2VwdHVhbApUYXNrc187IHRoZXNlIGNvcnJlc3BvbmQgdG8gY2hhbm5lbCBtYXBwaW5ncy4KClNvbWUgb3JkZXJpbmdzIHdlcmUgYWRkcmVzc2VkIGJ5IGluZm9ybWFsIGV4cGVyaW1lbnRzIChvYnZpb3VzIHRvIHRoZQphdXRob3JzIGF0IGxlYXN0KS4KCk90aGVycyB3ZXJlIGFzc2Vzc2VkIGJ5IGZvcm1hbCBleHBlcmltZW50cyB3aXRoIGFib3V0IDUwIHN1YmplY3RzLgoKRXhwZXJpbWVudHMgZm9jdXNlZCBvbiBhY2N1cmFjeSBvZiBkZWNvZGluZywgdGhvdWdoIHRoaXMgaXMgbm90IHZpZXdlZAphcyB0aGUgcHJpbWFyeSBwdXJwb3NlIG9mIGEgZ3JhcGg6Cgo+IE9uZSBtdXN0IGJlIGNhcmVmdWwgbm90IHRvIGZhbGwgaW50byBhIGNvbmNlcHR1YWwgdHJhcCBvZiBhZG9wdGluZwo+IGFjY3VyYWN5IGFzIGEgY3JpdGVyaW9uLiAuLi4gVGhlIHBvd2VyIG9mIGEgZ3JhcGggaXMgaXRzIGFiaWxpdHkgdG8KPiBlbmFibGUgb25lIHRvIHRha2UgaW4gdGhlIHF1YW50aXRhdGl2ZSBpbmZvcm1hdGlvbiwgb3JnYW5pemUgaXQsIGFuZAo+IHNlZSBwYXR0ZXJucyBhbmQgc3RydWN0dXJlIG5vdCByZWFkaWx5IHJldmVhbGVkIGJ5IG90aGVyIG1lYW5zIG9mCj4gc3R1ZHlpbmcgdGhlIGRhdGEuCgpUaGVpciBwcmVtaXNlOgoKPiBBIGdyYXBoaWNhbCBmb3JtIHRoYXQgaW52b2x2ZXMgZWxlbWVudGFyeSBwZXJjZXB0dWFsIHRhc2tzIHRoYXQgbGVhZAo+IHRvIG1vcmUgYWNjdXJhdGUganVkZ21lbnRzIHRoYW4gYW5vdGhlciBncmFwaGljYWwgZm9ybSAod2l0aCB0aGUKPiBzYW1lIHF1YW50aXRhdGl2ZSBpbmZvcm1hdGlvbikgd2lsbCByZXN1bHQgaW4gYmV0dGVyIG9yZ2FuaXphdGlvbgo+IGFuZCBpbmNyZWFzZSB0aGUgY2hhbmNlcyBvZiBhIGNvcnJlY3QgcGVyY2VwdGlvbiBvZiBwYXR0ZXJucyBhbmQKPiBiZWhhdmlvci4iCgpUaGUgdGFza3M6IEZvciBlYWNoIHNldHRpbmcKCiogSWRlbnRpZnkgd2hpY2ggb2YgdHdvIG1hcmtlZCBpdGVtcyBpcyBzbWFsbGVyLgoKKiBFc3RpbWF0ZSB0aGUgcGVyY2VudGFnZSB0aGUgc21hbGxlciBpcyBvZiB0aGUgbGFyZ2VyLgoKIVtdKGByIElNRygiQ00xLmpwZyIpYCkKCiFbXShgciBJTUcoIkNNMi5wbmciKWApCgpSZXN1bHRzOgoKUGVyY2VudCBsYXJnZSBlcnJvcnM6CgohW10oYHIgSU1HKCJDTUxFLmpwZyIpYCkKCkFic29sdXRlIGVycm9yOgoKIVtdKGByIElNRygiY2xldmVsYW5kLXJlc3VsdHMucG5nIilgKQoKCiMjIyBIZWVyIGFuZCBCb3N0b2NrCgpbSGVlciBhbmQgQm9zdG9jawogICgyMDEwKV0oaHR0cDovL2lkbC5jcy53YXNoaW5ndG9uLmVkdS9wYXBlcnMvY3Jvd2Rzb3VyY2luZy1ncmFwaGljYWwtcGVyY2VwdGlvbi8pCnNldCBvdXQgdG8gcmVwbGljYXRlIHRoZSBDbGV2ZWxhbmQgTWNHaWxsIGV4cGVyaW1lbnQgdXNpbmcgY3Jvd2QKc291cmNpbmcgdmlhIFtBbWF6b24gTWVjaGFuaWNhbCBUdXJrXShodHRwczovL3d3dy5tdHVyay5jb20vKQoKVGhleSB1c2VkIHRoZSBmaXZlIHBvc2l0aW9uIHN0aW11bGkgZnJvbSBDbGV2ZWxhbmQgYW5kIE1jR2lsbCBhbmQKc29tZSBuZXcgb25lczoKCiFbXShgciBJTUcoImhlZXItYm9zdG9jay10YXNrcy5wbmciKWApCgo1MCBzdWJqZWN0cyB3ZXJlIHJlY3J1aXRlZCBmb3IgZWFjaCB0YXNrLgoKUmVzdWx0cyB3ZXJlIGNvbnNpc3RlbnQgd2l0aCBDbGV2ZWxhbmQtTWNHaWxsIHJlc3VsdHM6CgohW10oYHIgSU1HKCJIQjEuanBlZyIpYCkKClVzZSBvZiBNZWNoYW5pY2FsIFR1cmsgd2FzIGRlZW1lZCBhIHN1Y2Nlc3MuCgoKIyMjIFBpZSBDaGFydCBFeHBlcmltZW50cwoKW1BpZSBjaGFydHNdKGh0dHBzOi8vZWFnZXJleWVzLm9yZy9waWUtY2hhcnRzKSBhcmUgcG9wdWxhciBidXQKc29tZXdoYXQgY29udHJvdmVyc2lhbC4KCiogUGllIGNoYXJ0cyBhcmUgaW5mZXJpb3IgZm9yIGNvbXBhcmlzb25zIHRvIGJhciBjaGFydHMuCgoqIFBpZSBjaGFydHMgYXJlIHF1aXRlIGdvb2QgYXQgcmVwcmVzZW50aW5nIHBhcnQtd2hvbGUgcmVsYXRpb25zaGlwcy4KCiogQ2xldmVsYW5kIGFuZCBNY0dpbGwgc3VnZ2VzdGVkIHBpZSBjaGFydHMgYXJlIHJlYWQgYnkgYW5nbGUuCgoqIFtLb3NhcmEgYW5kIFNrYXVdKGh0dHBzOi8vZWFnZXJleWVzLm9yZy9wYXBlcnMvYS1wYWlyLW9mLXBpZS1jaGFydC1wYXBlcnMpCiAgcmVwb3J0IGV4cGVyaW1lbnRzIHRoYXQgc3VnZ2VzdCB0aGlzIGlzIG5vdCB0aGUgY2FzZS4KCiogSWYgaXQgd2VyZSwKICBbX2RvbnV0IGNoYXJ0c19dKGh0dHBzOi8vZGF0YXZpemNhdGFsb2d1ZS5jb20vbWV0aG9kcy9kb251dF9jaGFydC5odG1sKQogIHdvdWxkIGJlIGV2ZW4gbGVzcyBlZmZlY3RpdmUsIGJ1dCB0aGV5IHNlZW0gdG8gYmUgdmVyeSBjb21wYXJhYmxlLgoKKiBbS29zYXJhJ3MgYmxvZ10oaHR0cHM6Ly9lYWdlcmV5ZXMub3JnKSBwcm92aWRlcyBhCiAgW3Jldmlld10oaHR0cHM6Ly9lYWdlcmV5ZXMub3JnL2Jsb2cvMjAxNi9hbi1pbGx1c3RyYXRlZC10b3VyLW9mLXRoZS1waWUtY2hhcnQtc3R1ZHktcmVzdWx0cykKICAgICAgb2Ygb3RoZXIgcGllIGNoYXJ0IHN0dWRpZXMuCgoKIyMgSW1wcm92aW5nIFNvbWUgQ29tbW9uIENoYXJ0cwoKQ2xldmVsYW5kIGFuZCBNY0dpbGwgc2V0IG91dCB0byBzdWdnZXN0IGltcHJvdmVtZW50cyB0byBzb21lIGNvbW1vbiBjaGFydHMuClRoaXMgaXMgYSBzZWxlY3Rpb24gb2YgdGhlaXIgZXhhbXBsZXMuCgoKIyMjIERvdCBDaGFydHMKCkNsZXZlbGFuZCBhbmQgTWNHaWxsIHVzZSB0aGVpciBwZXJjZXB0dWFsIGxhZGRlciB0byBhcmd1ZSBzdHJvbmdseSBmb3IKdXNpbmcgZG90IGNoYXJ0cyBpbiBwbGFjZSBvZiBiYXIgY2hhcnRzIGFuZCBwaWUgY2hhcnRzLgoKCiMjIyBQbGF5ZmFpcidzIEJhbGFuY2Ugb2YgVHJhZGUgcGxvdHMKClBsYXlmYWlyIHByZXNlbnRlZCBhIG51bWJlciBvZiBwbG90cyBzaG93aW5nIGltcG9ydHMgYW5kIGV4cG9ydHMKYmV0d2VlbiBFbmdsYW5kIGFuZCBvdGhlciBuYXRpb25zLgoKQSBwcmltYXJ5IGdvYWwgd2FzIHRvIHNob3cgdGhlIGJhbGFuY2Ugb2YgdHJhZGUsIHRoZSBkaWZmZXJlbmNlCmJldHdlZW4gZXhwb3J0cyBhbmQgaW1wb3J0czoKCiFbXShgciBJTUcoIlBsYXlmYWlyX0V4cG9ydHNfSW1wb3J0cy5qcGciKWApCgpBc3Nlc3NpbmcgdGhlIGRpZmZlcmVuY2VzIGZyb20gYSBwbG90IHNob3dpbmcgZXhwb3J0cyBhbmQgaW1wb3J0cyBhcwpzZXBhcmF0ZSBjdXJ2ZXMgcmVxdWlyZXMgbGVuZ3RoIGp1ZGdtZW50cywgd2hpY2ggYXJlIGxlc3MgYWNjdXJhdGUKdGhhbiBjb21wYXJpc29ucyB0byBhIGNvbW1vbiBzdGFsZS4KCjwhLS0KZGF0YToKaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2plbm55YmMvci1ncmFwaC1jYXRhbG9nL21hc3Rlci9maWd1cmVzL2ZpZzAyLTE0X3BsYXlmYWlyLXMtYmFsYW5jZS1vZi10cmFkZS1kYXRhL2ZpZzAyLTE0X3BsYXlmYWlyLXMtYmFsYW5jZS1vZi10cmFkZS1kYXRhLnRzdgotLT4KCmBgYHtyLCBpbmNsdWRlID0gRkFMU0V9CiMgbm9saW50IHN0YXJ0CmlmICghIGZpbGUuZXhpc3RzKCJwbGF5ZmFpci1iYWxhbmNlLW9mLXRyYWRlLWRhdGEudHN2IikpCiAgICBkb3dubG9hZC5maWxlKCJodHRwOi8vd3d3LnN0YXQudWlvd2EuZWR1L35sdWtlL2RhdGEvcGxheWZhaXItYmFsYW5jZS1vZi10cmFkZS1kYXRhLnRzdiIsCiAgICAgICAgICAgICAgICAgICJwbGF5ZmFpci1iYWxhbmNlLW9mLXRyYWRlLWRhdGEudHN2IikKIyBub2xpbnQgZW5kCmBgYAoKYGBge3IsIGVjaG8gPSBGQUxTRX0KcGltZXggPC0gcmVhZC5kZWxpbSgicGxheWZhaXItYmFsYW5jZS1vZi10cmFkZS1kYXRhLnRzdiIpCnBwMSA8LSBtdXRhdGUocGltZXgsIGRpZmZlcmVuY2UgPSBOVUxMKSB8PgogICAgcGl2b3RfbG9uZ2VyKC15ZWFyLCBuYW1lc190byA9ICJ3aGljaCIsIHZhbHVlc190byA9ICJ0cmFkZSIpIHw+CiAgICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdHJhZGUsIGdyb3VwID0gd2hpY2gsIGNvbG9yID0gd2hpY2gpKSArCiAgICBnZW9tX2xpbmUoKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3IgPSAiZ3JleTIwIikpCnBwMQpgYGAKClBsb3R0aW5nIHRoZSBkaWZmZXJlbmNlIG1ha2VzIHRoZSBiYWxhbmNlIG9mIHRyYWRlIG11Y2ggZWFzaWVyIHRvIGFzc2VzczoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CnBwMiA8LSBnZ3Bsb3QocGltZXgpICsgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IGltcG9ydHMgLSBleHBvcnRzKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGNvbG9yID0gImdyZXkyMCIpKQpwcDIKYGBgCgpBbiBfZW5zZW1ibGUgcGxvdF8gc2hvd2luZyBib3RoIHZpZXdzIG1heSBhbHNvIGhlbHAuCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuaGVpZ2h0ID0gNn0KbGlicmFyeShwYXRjaHdvcmspCnBwMSAvIHBwMgpgYGAKCgojIyMgRnJhbWVkIFVuYWxpZ25lZCBCYXJzCgpJdCBpcyBkaWZmaWN1bHQgdG8gY29tcGFyZSBsZW5ndGhzIG9mIHVuYWxpZ25lZCByZWN0YW5nbGVzIHdoZW4gdGhlCmxlbmd0aHMgYXJlIGNsb3NlLgoKYGBge3IsIGVjaG8gPSBGQUxTRX0KaDEgPC0gNy40CmgyIDwtIDYuNwpoYiA8LSAxMApvZmYgPC0gMwpwMSA8LSBnZ3Bsb3QoKSArCiAgICBnZW9tX3JlY3QoYWVzKHhtaW4gPSAwLCB5bWluID0gMCwgeG1heCA9IDEsIHltYXggPSBoMSksCiAgICAgICAgICAgICAgZmlsbCA9IG11dGVkKCJibHVlIikpICsKICAgIGdlb21fcmVjdChhZXMoeG1pbiA9IDIsIHltaW4gPSBvZmYsIHhtYXggPSAzLCB5bWF4ID0gb2ZmICsgaDIpLAogICAgICAgICAgICAgIGZpbGwgPSBtdXRlZCgiYmx1ZSIpKSArCiAgICB0aGVtZV92b2lkKCkgKwogICAgeWxpbShjKC0xLCBvZmYgKyBoYiArIDEpKSArIHhsaW0oYygtMiwgNSkpCnAxCmBgYAoKQWRkaW5nIGEgZnJhbWUgbW92ZXMgdGhlIHRhc2sgdXAgdGhlIHBlcmNlcHR1YWwgbGFkZGVyIHRvIGFuIHVuYWxpZ25lZApjb21wYXJpc29uIGFnYWluc3QgYSBjb21tb24gc2NhbGUuCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpwMSArIGdlb21fcmVjdChhZXMoeG1pbiA9IDAsIHltaW4gPSAwLCB4bWF4ID0gMSwgeW1heCA9IGhiKSwKICAgICAgICAgICAgICAgZmlsbCA9IE5BLCBjb2xvciA9ICJibGFjayIpICsKICAgIGdlb21fcmVjdChhZXMoeG1pbiA9IDIsIHltaW4gPSBvZmYsIHhtYXggPSAzLCB5bWF4ID0gb2ZmICsgaGIpLAogICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9IE5BKQpgYGAKCkNvbXBhcmluZyB0byBhIGNvbW1vbiBzY2FsZSBpcyBzdGlsbCB0aGUgbW9zdCBlZmZlY3RpdmUgYXBwcm9hY2g6CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpnZ3Bsb3QoKSArCiAgICBnZW9tX3JlY3QoYWVzKHhtaW4gPSAwLCB5bWluID0gMCwgeG1heCA9IDEsIHltYXggPSBoMSksCiAgICAgICAgICAgICAgZmlsbCA9IG11dGVkKCJibHVlIikpICsKICAgIGdlb21fcmVjdChhZXMoeG1pbiA9IDIsIHltaW4gPSAwLCB4bWF4ID0gMywgeW1heCA9IGgyKSwKICAgICAgICAgICAgICBmaWxsID0gbXV0ZWQoImJsdWUiKSkgKyB0aGVtZV92b2lkKCkgKwogICAgeWxpbShjKC0xLCBvZmYgKyBoYiArIDEpKSArIHhsaW0oYygtMiwgNSkpCmBgYAoKQnV0IHRoaXMgZG9lcyBzdWdnZXN0IHRoYXQgdXNpbmcgdW5hbGlnbmVkIGZyYW1lZCByZWN0YW5nbGVzIHRvIGVuY29kZQphIF90aGlyZF8gdmFyaWFibGUsIHdpdGggcG9zaXRpb24gZW5jb2RpbmcgdGhlIHR3byBwcmltYXJ5IHZhcmlhYmxlcwptYXkgYmUgZWZmZWN0aXZlLgoKCiMjIyBGcmFtZWQgUmVjdGFuZ2xlIE1hcHMKCkEgX2Nob3JvcGxldGggbWFwXyBpcyBhIGNvbW1vbiB3YXkgdG8gZGVwaWN0IGEgcXVhbnRpdGF0aXZlIHZhcmlhYmxlIGluCmEgZ2VvZ3JhcGhpYyBjb250ZXh0LgoKU2hhZGluZyBpcyBxdWl0ZSBsb3cgb24gdGhlIHBlcmNlcHR1YWwgbGFkZGVyLgoKQ2xldmVsYW5kIGFuZCBNY0dpbGwgc3VnZ2VzdCB0aGUgdXNlIG9mIGZyYW1lZCByZWN0YW5nbGVzIHBvc2l0aW9uZWQKb24gdGhlIG1hcCBhcyBhbiBhbHRlcm5hdGl2ZS4KClRoaXMgZG9lcyBub3Qgc2VlbSB0byBoYXZlIGNhdWdodCBvbiBzbyBmYXIsIHRob3VnaCB5b3UgZG8gc29tZXRpbWVzCnNlZSB0aGUgdXNlIG9mIG90aGVyIGdseXBocywgc3VjaCBhcyBwaWUgY2hhcnRzLgoKPCEtLSAhW10oaHR0cDovL2xoNC5nZ3BodC5jb20vX0xlbkNabHl6YTIwL1RSOHlhSG1zeXpJL0FBQUFBQUFBSlI4L3lUdmw3YXdka3lzL3RtcDE0ODE2X3RodW1iMV90aHVtYjEuanBnP2ltZ21heD04MDApIC0tPgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiOTAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoSU1HKCJDTW1hcC5qcGciKSkKYGBgCgoKIyMgQW5hbHl6aW5nIGEgRGVzaWduCgpHcmFwaCBsYXlvdXQgaW52b2x2ZXMgc2V2ZXJhbCBsZXZlbHM6CgoqIFByaW1hcnkgZGF0YSByZXByZXNlbnRhdGlvbgoKICAqIGl0ZW1zLCBhdHRyaWJ1dGVzCiAgKiBtYXJrcywgY2hhbm5lbHMKCiogU3VwcG9ydGluZyBmZWF0dXJlcwoKICAqIHRyZW5kIGxpbmVzLCByZWZlcmVuY2UgbGluZXMsIGFubm90YXRpb25zCiAgKiBheGVzLCBsZWdlbmRzCgpBIHVzZWZ1bCBzdHJ1Y3R1cmUgZm9yIGRlc2NyaWJpbmcgdGhlIHByaW1hcnkgZmVhdHVyZXM6CgoqIFdoYXQgYXJlIHRoZSBkYXRhIGl0ZW1zPwoqIFdoYXQgYXJlIHRoZSBhdHRyaWJ1dGVzPwoqIFdoYXQgbWFya3MgYXJlIHVzZWQ/CiogV2hhdCBjaGFubmVscyBhcmUgdXNlZD8KKiBXaGljaCBhdHRyaWJ1dGUgaXMgbWF0Y2hlZCB0byBjaGFubmVsIDEKKiBXaGljaCBhdHRyaWJ1dGUgaXMgbWF0Y2hlZCB0byBjaGFubmVsIDIKKiAuLi4KClVzZWZ1bCBxdWVzdGlvbnM6CgoqIEFyZSB0aGUgbW9zdCBpbXBvcnRhbnQgYXR0cmlidXRlcyBtYXBwZWQgdG8gdGhlIHN0cm9uZ2VzdCBjaGFubmVscz8KKiBEbyB0aGUgbWFwcGluZ3MgZG8gYSBnb29kIGpvYiBvZiBjb252ZXlpbmcgdGhlIHByaW1hcnkgbWVzc2FnZT8KKiBJZiBub3QsIGNhbiB0aGUgZ3JhcGggYmUgaW1wcm92ZWQgYnkgYWRqdXN0aW5nIHRoZSBtYXBwaW5ncz8KCgojIyMgQSBHYXBtaW5kZXIgUGxvdAoKT25lIG9mIHRoZSBmcmFtZXMgb2YgYSBwbG90IGZyb20gdGhlIFtHYXBNaW5kZXIKc2l0ZV0oaHR0cHM6Ly93d3cuZ2FwbWluZGVyLm9yZyk6CgohW10oYHIgSU1HKCJnYXBtaW5kZXIyLnBuZyIpYCkKCiogSXRlbXMgYXJlIGNvdW50cmllcyAoaW4gYSBwYXJ0aWN1bGFyIHllYXIpCgoqIEF0dHJpYnV0ZXMgaW4gdGhlIHBsb3Q6CiAgICAqIGxpZmUgZXhwZWN0YW5jeQogICAgKiBpbmNvbWUgcGVyIHBlcnNvbgogICAgKiBwb3B1bGF0aW9uCiAgICAqIGNvbnRpbmVudAogICAgKiBjb3VudHJ5IG5hbWUKICAgICogeWVhcgoKKiBNYXJrczogcG9pbnRzIChvciBidWJibGVzKS4KCiogQ2hhbm5lbHMgYW5kIG1hcHBpbmdzOgogICAgKiBob3Jpem9udGFsIHBvc2l0aW9uLCBtYXBwZWQgdG8gbG9nIGluY29tZQogICAgKiB2ZXJ0aWNhbCBwb3NpdGlvbiwgbWFwcGVkIHRvIGxpZmUgZXhwZWN0YW5jeQogICAgKiBhcmVhLCBtYXBwZWQgdG8gcG9wdWxhdGlvbgogICAgKiBjb2xvciAoaHVlKSwgbWFwcGVkIHRvIGNvbnRpbmVudAogICAgKiBpbnRlcmFjdGl2ZTogbW91c2Utb3ZlciwgbWFwcGVkIHRvIGNvdW50cnkgbmFtZQogICAgKiBpbnRlcmFjdGl2ZTogdGltZSAob3IgZnJhbWUpLCBtYXBwZWQgdG8geWVhcgoKVGhlIGJhc2ljIHBsb3QgY2FuIGJlIGNyZWF0ZWQgd2l0aCBgZ2dwbG90YCBhbmQgYWVzdGhldGljIG1hcHBpbmdzOgoKYGBge3IgZ2FwbWluZGVyLWJhc2ljLCBldmFsID0gRkFMU0V9CmxpYnJhcnkoZ2FwbWluZGVyKQpnbTIwMDcgPC0gZmlsdGVyKGdhcG1pbmRlciwgeWVhciA9PSAyMDA3KQpnZ3Bsb3QoZ20yMDA3KSArCiAgICBnZW9tX3BvaW50KGFlcyh4ID0gZ2RwUGVyY2FwLAogICAgICAgICAgICAgICAgICAgeSA9IGxpZmVFeHAsCiAgICAgICAgICAgICAgICAgICBzaXplID0gcG9wLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSBjb250aW5lbnQpKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgeWxpbShjKDIwLCA4NSkpCmBgYApgYGB7ciBnYXBtaW5kZXItYmFzaWMsIGVjaG8gPSBGQUxTRX0KYGBgCgpUaGUgZGF0YSBpbiB0aGUgYGdhcG1pbmRlcmAgcGFja2FnZSBkaWZmZXIgc29tZXdoYXQgZnJvbSB0aGUgZGF0YSB1c2VkCmJ5IHRoZSBHYXBtaW5kZXIgc2l0ZSwgYnV0IG92ZXJhbGwgdGhlIHBsb3QgZGVzaWducyBhcmUgdmVyeSBjbG9zZS4KCldpdGggc29tZSBhZGp1c3RtZW50cyB0aGUgYmFzaWMgcGxvdCBjYW4gYmUgYnJvdWdodCBjbG9zZSB0byB0aGUKR2FwbWluZGVyIHZlcnNpb24gaW4gYXBwZWFyYW5jZToKCmBgYHtyIGdhcG1pbmRlci1mdWxsLCBldmFsID0gRkFMU0V9CmdtMjAwNyA8LSBmaWx0ZXIoZ2FwbWluZGVyLCB5ZWFyID09IDIwMDcpIHw+CiAgICBhcnJhbmdlKGRlc2MocG9wKSkgIyMgc29ydCB0byBhdm9pZCBvdmVyLXBsb3R0aW5nCmdncGxvdChnbTIwMDcpICsKICAgIGdlb21fcG9pbnQoYWVzKHggPSBnZHBQZXJjYXAsCiAgICAgICAgICAgICAgICAgICB5ID0gbGlmZUV4cCwKICAgICAgICAgICAgICAgICAgIHNpemUgPSBwb3AsCiAgICAgICAgICAgICAgICAgICBmaWxsID0gY29udGluZW50KSwKICAgICAgICAgICAgICAgc2hhcGUgPSAyMSkgKyAjIyB0byBhbGxvdyB0aGUgdXNpbmcgYGZpbGxgIGFlc3RoZXRpYwogICAgc2NhbGVfeF9sb2cxMChsYWJlbHMgPSBjb21tYSkgKwogICAgeWxpbShjKDIwLCA4NSkpICsKICAgIHNjYWxlX3NpemVfYXJlYShtYXhfc2l6ZSA9IDIwLAogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGNvbW1hLAogICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoMC4yNSAqIDEwIF4gOSwgMC41ICogMTAgXiA5LCAxMCBeIDkpKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKEFmcmljYSA9ICJkZWVwc2t5Ymx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzaWEgPSAicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQW1lcmljYXMgPSAiZ3JlZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdXJvcGUgPSAiZ29sZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9jZWFuaWEgPSAiYnJvd24iKSkgKwogICAgbGFicyh4ID0gIkluY29tZSIsIHkgPSAiTGlmZSBleHBlY3RhbmN5IikgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSArCiAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJDb250aW5lbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gNSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IDEpLAogICAgICAgICAgIHNpemUgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiUG9wdWxhdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbC5oanVzdCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IDIpKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3IgPSAiZ3JleTIwIikpCmBgYApgYGB7ciBnYXBtaW5kZXItZnVsbCwgZWNobyA9IEZBTFNFLCBmaWcuaGVpZ2h0ID0gNiwgZmlnLndpZHRoID0gOH0KYGBgCgpTb21lIG5vdGVzOgoKKiBVc2luZyBsYXJnZXIgYnViYmxlcyBtYWtlcyB0aGUgcGxvdCBtb3JlIGVuZ2FnaW5nLgoKKiBVc2luZyBsYXJnZXIgYnViYmxlcyBtYWtlcyBkaWZmZXJlbmNlcyBpbiBwb3B1bGF0aW9uIGVhc2llciB0bwogIGFzc2VzcywgYnV0IG1ha2VzIHRoZSBzdHJlbmd0aCBvZiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbGlmZQogIGV4cGVjdGFuY3kgYW5kIGluY29tZSBoYXJkZXIgdG8gYXNzZXNzLgoKKiBVc2luZyBsYXJnZXIgYnViYmxlcyBhbHNvIGluY3JlYXNlcyB0aGUgcmlzayBvZgogIG92ZXItcGxvdHRpbmcuIFNvcnRpbmcgdGhlIHJvd3Mgc28gbGFyZ2VyIGJ1YmJsZSBhcmUgZHJhd24gZmlyc3QKICBoZWxwcyByZWR1Y2UgdGhlIHJpc2sgc29tZXdoYXQuCgpUaGVzZSBwbG90cyBzaG93IGEgZmFpcmx5IHN0cm9uZyBtYXJnaW5hbCBhc3NvY2lhdGlvbiBiZXR3ZWVuIGxpZmUKZXhwZWN0YW5jeSBhbmQgaW5jb21lLgoKVGhlcmUgZG9lcyBub3Qgc2VlbSB0byBiZSBhIHN0cm9uZyBhc3NvY2lhdGlvbiBvZiBwb3B1bGF0aW9uIHdpdGggdGhlCm90aGVyIHR3byB2YXJpYWJsZXMsIGJ1dCB0aGVzZSBwbG90cyBhcmUgbm90IGlkZWFsIGZvciB0aGF0IGFzc2Vzc21lbnQuCgpUbyBqdWRnZSB0aGUgbWFyZ2luYWwgYXNzb2NpYXRpb24gYmV0d2VlbiBsaWZlIGV4cGVjdGFuY3kgYW5kCnBvcHVsYXRpb24gc2l6ZSB3ZSBjYW4gY2hhbmdlIHRoZSBjaGFubmVsIG1hcHBpbmc6CgoqIG1hcCB0aGUgaG9yaXpvbnRhbCBheGlzIHRvIHBvcHVsYXRpb247CiogbWFwIGFyZWEgdG8gaW5jb21lLgoKYGBge3IgZ2FwbWluZGVyLWxpZmVwb3AsIGV2YWwgPSBGQUxTRX0KZ2dwbG90KGZpbHRlcihnYXBtaW5kZXIsIHllYXIgPT0gMjAwNykpICsKICAgIGdlb21fcG9pbnQoYWVzKHggPSBwb3AsCiAgICAgICAgICAgICAgICAgICB5ID0gbGlmZUV4cCwKICAgICAgICAgICAgICAgICAgIHNpemUgPSBnZHBQZXJjYXApKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgeWxpbShjKDIwLCA4NSkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShwYW5lbC5ib3JkZXIgPQogICAgICAgICAgICAgIGVsZW1lbnRfcmVjdChmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImdyZXkyMCIpKQpgYGAKYGBge3IgZ2FwbWluZGVyLWxpZmVwb3AsIGVjaG8gPSBGQUxTRX0KYGBgCgpUaGlzIGNvbmZpcm1zIHRoYXQgdGhlcmUgaXMgdmVyeSBsaXR0bGUgYXNzb2NpYXRpb24gYmV0d2VlbiBsaWZlCmV4cGVjdGFuY3kgYW5kIHBvcHVsYXRpb24uCgpUaGUgYXNzb2NpYXRpb24gYmV0d2VlbiBsaWZlIGV4cGVjdGFuY3kgYW5kIGluY29tZSBpcyBzdGlsbCB2aXNpYmxlLApidXQgaXMgZWFzaWVyIHRvIGFzc2VzcyB3aGVuIHRoZXNlIHR3byB2YXJpYWJsZXMgYXJlIG1hcHBlZCB0byAyRApwb3NpdGlvbi4KCgojIyMgTWljaGVsaW4gU3RhcnMKClRoaXMgaW1hZ2UsIGZyb20gYQpbYmxvZyBwb3N0XShodHRwOi8vY3JlYXRlaHRtbDVtYXAuY29tL2ludGVyYWN0aXZlLW1hcC1ibG9nL2ludGVyYWN0aXZlLWJ1YmJsZS1jaGFydC1jb3VudHJpZXMtcmVjZWl2ZS10aGUtbW9zdC1taWNoZWxpbi1zdGFycy1lYWNoLXllYXIvKSwKc2hvd3MgdGhlIHRvdGFsIG51bWJlciBvZiBzdGFycyBmb3IgZGlmZmVyZW50IGNvdW50cmllczoKCiFbXShgciBJTUcoIm1pY2hlbGluLXN0YXJzLnBuZyIpYCkKCiogSXRlbXM6IENvdW50cmllcyAoaW4gYSBwYXJ0aWN1bGFyIHllYXIpCgoqIEF0dHJpYnV0ZXM6CiAgICAqIGNvdW50cnkgbmFtZQogICAgKiBudW1iZXIgb2Ygc3RhcnMKCiogTWFya3M6IGJ1YmJsZXMsIHRleHQKCiogQ2hhbm5lbHMgYW5kIG1hcHBpbmdzOgogICAgKiBidWJibGUgY29sb3IsIG1hcHBlZCB0byBjb3VudHJ5CiAgICAqIGJ1YmJsZSBhcmVhLCBtYXBwZWQgdG8gbnVtYmVyIG9mIHN0YXJzCiAgICAqIHRleHQsIG1hcHBlZCB0byBjb3VudHJ5IG5hbWUgKHdoZXJlIHBvc3NpYmxlKQogICAgKiB0ZXh0LCBtYXBwZWQgdG8gbnVtYmVyIG9mIHN0YXJzICh3aGVyZSBwb3NzaWJsZSkKCjwhLS0gc2VwYXJhdGUgbmV4dCBsaW5lIC0tPgoKT2JzZXJ2YXRpb25zOgoKKiBOb25lIG9mIHRoZSBjaGFubmVscyBhcmUgdmVyeSBzdHJvbmcuCgoqIFRoZSBzdHJvbmdlc3QgY2hhbm5lbHMsIDJEIHBvc2l0aW9uLCBhcmUgbm90IHVzZWQuCgoqIFRoZSBudW1iZXIgb2YgY29sb3JzIHVzZWQgaXMgdG9vIGhpZ2guCgpBIHNpbXBsZSBfZG90IHBsb3RfIHdvdWxkIGNvbnZleSB0aGUgZGlzdHJpYnV0aW9uIGJldHRlci4KCkEgZG90IHBsb3QgdXNpbmcgWzIwMTcgZGF0YV0obWljaGVsaW4uZGF0KSBmcm9tIGFuClthcnRpY2xlXShodHRwczovL3d3dy50ZWxlZ3JhcGguY28udWsvdHJhdmVsL21hcHMtYW5kLWdyYXBoaWNzL21hcC1taWNoZWxpbi1zdGFyLXJlc3RhdXJhbnRzLWNvdW50cmllcy13aXRoLXRoZS1tb3N0LykKaW4gVGhlIFRlbGVncmFwaDoKCmBgYHtyfQptaWNoZWxpbiA8LSByZWFkLnRhYmxlKFdMTksoIm1pY2hlbGluLmRhdCIpLAogICAgICAgICAgICAgICAgICAgICAgIGhlYWQgPSBUUlVFKQptaWNoZWxpbiA8LSBtdXRhdGUobWljaGVsaW4sCiAgICAgICAgICAgICAgICAgICBzdGFycyA9IG9uZSArIDIgKiB0d28gKyAzICogdGhyZWUsCiAgICAgICAgICAgICAgICAgICBjb3VudHJ5ID0gcmVvcmRlcihjb3VudHJ5LCBzdGFycykpCmdncGxvdChtaWNoZWxpbiwgYWVzKHggPSBzdGFycywgeSA9IGNvdW50cnkpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh4ID0gIlN0YXJzIiwgeSA9IE5VTEwpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikpICsKICAgIHRoZW1lKHBhbmVsLmJvcmRlciA9CiAgICAgICAgICAgICAgZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZ3JleTIwIikpCmBgYAoKRXZlbiBpZiBhIGJ1YmJsZSBwbG90IGlzIGRlc2lyZWQgZm9yIGFlc3RoZXRpYyByZWFzb25zLCBwb3NpdGlvbgpjb3VsZCBiZSB1c2VkIHRvCgoqIGdyb3VwIGNvdW50cmllcyBieSBjb250aW5lbnQ7Ciogc2hvdyBjb3VudHJpZXMgb24gYSBtYXAuCgpBIHBsb3QgbGlrZSB0aGUgb3JpZ2luYWwgY2FuIGJlIGNvbnN0cnVjdGVkIGJ5CgoqIGNvbXB1dGluZyBsb2NhdGlvbnMgZm9yIGEgc2V0IG9mIHBhY2tlZCBzcGhlcmVzIHdpdGggc3BlY2lmaWVkIHJhZGlpOwoqIHVzaW5nIGBnZW9tX3BvaW50YCBhbmQgYGdlb21fdGV4dGAuCgpgYGB7ciwgZmlnLndpZHRoID0gOCwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSJ9CiMjIGNyZWF0ZSByYW5kb21seSBsb2NhdGVkICBwYWNrZWQgc3BoZXJlcyB3aXRoIHNwZWNpZmllZCBhcmVhcwpsaWJyYXJ5KHBhY2tjaXJjbGVzKQpzZXQuc2VlZCg1NDMyMSkKcGFja2luZyA8LSBjaXJjbGVQcm9ncmVzc2l2ZUxheW91dChtaWNoZWxpbiRzdGFycykKCiMjIG1lcmdlIGNpcmNsZSBsb2NhdGlvbnMgd2l0aCBzdGFydHMgZGF0YQptY2lyYyA8LSBiaW5kX2NvbHMocGFja2luZywgbWljaGVsaW4pIHw+CiAgICBtdXRhdGUoY291bnRyeSA9IGZhY3Rvcihjb3VudHJ5KSkgIyMgY2xlYW4gb3V0IHN0cmF5IGF0dHJpYnV0ZXMKCiMjIGNvbXB1dGUgc29tZSBjb2xvcnMgdG8gdXNlCm5yIDwtIG5yb3cobWNpcmMpCnBhbCA8LSBjb2xvclJhbXBQYWxldHRlKFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg5LCAiU2V0MSIpKQpjb2xzIDwtIHNhbXBsZShwYWwobnIpLCBucikKCiMjIHRoZXNlIG5lZWQgdHVuaW5nIGZvciB0aGUgc2NyZWVuIG9yIFIgbWFya2Rvd24KY3NpemUgPC0gNDUKdHNpemUgPC0gMi41CgojIyB0aGUgYmFzaWMgcGxvdAojIyB1c2VzIHNoYXBlID0gMTkgYW5kIGBjb2xvcmAgYWVzdGhldGljCnAgPC0gZ2dwbG90KG1jaXJjLCBhZXMoeCA9IHgsIHkgPSB5KSkgKwogICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IHJhZGl1cyBeIDIsIGNvbG9yID0gY291bnRyeSksIHNoYXBlID0gMTkpICsKICAgIHNjYWxlX3NpemVfYXJlYShtYXhfc2l6ZSA9IGNzaXplKSArCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUoY291bnRyeSwgc3RhcnMsIHNlcCA9ICJcbiIpKSwKICAgICAgICAgICAgICBkYXRhID0gZmlsdGVyKG1jaXJjLCBzdGFycyA+PSAxMjApLAogICAgICAgICAgICAgIHNpemUgPSB0c2l6ZSkgKwogICAgY29vcmRfZml4ZWQoKQoKIyMgYWRqdXN0bWVudHMKcCArIGd1aWRlcyhzaXplID0gIm5vbmUiKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29scykgKwogICAgeGxpbSh3aXRoKG1jaXJjLCByYW5nZSh4KSArIGMoLTEsIDEpICogbWF4KHJhZGl1cykpKSArCiAgICB5bGltKHdpdGgobWNpcmMsIHJhbmdlKHkpICsgYygtMSwgMSkgKiBtYXgocmFkaXVzKSkpICsKICAgIHRoZW1lX3ZvaWQoKQpgYGAKCkEgc29tZXdoYXQgbW9yZSByb2J1c3QgYXBwcm9hY2gKCiAgKiBjcmVhdGVzIHZlcnRleCBkYXRhIGZvciBwb2x5Z29uIGFwcHJveGltYXRpb25zIHRvIHRoZSBjaXJjbGVzOwogICogbWVyZ2VzIHRoZSBzdGFycyBkYXRhIHdpdGggdGhlIHBvbHlnb24gZGF0YTsKICAqIHVzZXMgYGdlb21fcG9seWdvbmAgYW5kIGBnZW9tX3RleHRgLgoKVGhpcyBpcyB2ZXJ5IHNpbWlsYXIgdG8gdGhlIHdheSBzaW1wbGUgX2Nob3JvcGxldGggbWFwc18gYXJlIGNyZWF0ZWQuCgpgYGB7ciwgZmlnLndpZHRoID0gOCwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSJ9CiMjIGNvbXB1dGUgcG9seWdvbiBhcHByb3hpbWF0aW9ucyB0byBzcGhlcmVzCm1jaXJjcG9seSA8LSBjaXJjbGVMYXlvdXRWZXJ0aWNlcyhtY2lyYywgaWRjb2wgPSAiY291bnRyeSIsIG5wb2ludHMgPSAxMDApIHw+CiAgICByZW5hbWUoY291bnRyeSA9IGlkKQoKIyMgbWVyZ2UgdGhlIHN0YXJzIGRhdGEgaW50byB0aGUgcG9seWdvbiBkYXRhCnN0dGFiIDwtIHNlbGVjdChtaWNoZWxpbiwgY291bnRyeSwgc3RhcnMpCm1jaXJjcG9seSA8LSBsZWZ0X2pvaW4obWNpcmNwb2x5LCBzdHRhYiwgImNvdW50cnkiKQoKIyMgY3JlYXRlIHRoZSBwbG90CmdncGxvdChtY2lyY3BvbHksIGFlcyh4ID0geCwgeSA9IHkpKSArCiAgICBnZW9tX3BvbHlnb24oYWVzKGZpbGwgPSBjb3VudHJ5KSkgKwogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlKGNvdW50cnksIHN0YXJzLCBzZXAgPSAiXG4iKSksCiAgICAgICAgICAgICAgZGF0YSA9IGZpbHRlcihtY2lyYywgc3RhcnMgPj0gMTIwKSwKICAgICAgICAgICAgICBzaXplID0gdHNpemUpICsKICAgIGNvb3JkX2ZpeGVkKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29scykgKwogICAgdGhlbWVfdm9pZCgpCmBgYAoKCiMjIEFzcGVjdCBSYXRpbyBhbmQgUGVyY2VwdGlvbgoKVGhlIHJpdmVyIGZsb3cgZGF0YSBzaG93cyBob3cgaW1wb3J0YW50IGFzcGVjdCByYXRpbyBjYW4gYmUgdG8gb3VyCmFiaWxpdHkgdG8gZGV0ZWN0IHBhdHRlcm5zOgoKYGBge3IsIGVjaG8gPSBGQUxTRX0KbGlicmFyeShncmlkRXh0cmEpCnJpdmVyIDwtIHNjYW4oImh0dHBzOi8vd3d3LnN0YXQudWlvd2EuZWR1L35sdWtlL2RhdGEvcml2ZXIuZGF0IikKciA8LSBkYXRhLmZyYW1lKGZsb3cgPSByaXZlciwgbW9udGggPSBzZXFfYWxvbmcocml2ZXIpKQoKcDAgPC0gZ2dwbG90KHIsIGFlcyh4ID0gbW9udGgsIHkgPSBmbG93KSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGNvbG9yID0gImdyZXkyMCIpKQpwMSA8LSBwMCArIGdlb21fcG9pbnQoKQoKZ3JpZC5hcnJhbmdlKHAxICsgY29vcmRfZml4ZWQocmF0aW8gPSAzNSksCiAgICAgICAgICAgICBwMSArIGNvb3JkX2ZpeGVkKHJhdGlvID0gNCksIGhlaWdodHMgPSBjKDMsIDEpKQpgYGAKClVzaW5nIGEgbGluZSBwbG90IHRoZSBiYXNpYyBwZXJpb2RpY2l0eSBiZWNvbWVzIGFwcGFyZW50IGV2ZW4gaW4gdGhlCmZpcnN0IGFzcGVjdCByYXRpby4KCmBgYHtyLCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0KcDIgPC0gcDAgKyBnZW9tX2xpbmUoKQpwMiArIGNvb3JkX2ZpeGVkKHJhdGlvID0gMzUpCmBgYAoKQnV0IHRoZSBzdGVlcGVyIGluY3JlYXNlL3NoYWxsb3dlciBkZWNyZWFzZSBvZiBtb3N0IHBlcmlvZHMgaXMgZWFzaWVyCnRvIHNlZSBpbiB0aGUgc2Vjb25kIGFzcGVjdCByYXRpbzoKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMiwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSJ9CnAyICsgY29vcmRfZml4ZWQocmF0aW8gPSA0KQpgYGAKClRoZSBhc3BlY3QgcmF0aW8gYWxzbyBpbmZsdWVuY2VzIGludGVycHJldGF0aW9uIG9mIHJlc3VsdHMuCgpTb21lIGFsdGVybmF0aXZlIHZpZXdzIG9mIChzdXNwZWN0KSBkYXRhIG9uIHRoZSBudW1iZXIgb2YgcGVvcGxlIG9uCmdvdmVybm1lbnQgYXNzaXN0YW5jZSBvdmVyIGEgdGltZSBwZXJpb2Q6CgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCBmaWcud2lkdGggPSA4LCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0KbGlicmFyeShyZWFkcikKdyA8LSByZWFkX2NzdihXTE5LKCJodzItd2VsZmFyZS5jc3YiKSkKdyA8LSBtdXRhdGUodywgb25Bc3Npc3RhbmNlID0gb25Bc3Npc3RhbmNlIC8gMTAgXiA2KQp3IDwtIG11dGF0ZSh3LAogICAgICAgICAgICBkYXRlID0gc2VxKGFzLkRhdGUoIjIwMDktMDEtMDEiKSwgYnkgPSAicXVhcnRlciIsIGxlbmd0aC5vdXQgPSAxMCkpCgpwMCA8LSBnZ3Bsb3QodywgYWVzKHggPSBkYXRlLCB5ID0gb25Bc3Npc3RhbmNlKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGNvbG9yID0gImdyZXkyMCIpKQoKcDEgPC0gcDAgKyBnZW9tX2xpbmUoYWVzKGdyb3VwID0gMSkpCgpncmlkLmFycmFuZ2UocDEsIHAxICsgY29vcmRfZml4ZWQocmF0aW8gPSA4KSwKICAgICAgICAgICAgIHAxICsgeWxpbSgwLCBtYXgodyRvbkFzc2lzdGFuY2UpKSwKICAgICAgICAgICAgIHAwICsgZ2VvbV9jb2wod2lkdGggPSA0MCksIG5jb2wgPSAyKQpgYGAKClNvbWUgbm90ZXM6CgoqIEF1dG9tYXRlZCBjaG9pY2VzIG9mIGF4aXMgc2NhbGluZyBjYW4gYWZmZWN0IHRoZSBhc3BlY3QgcmF0aW8gb2YKICB0aGUgY29udGVudCBvZiBhIHBsb3QuCgoqIEEgemVybyBiYXNlIGxpbmUgc3VwcG9ydHMgcmF0aW8gY29tcGFyaXNvbnMuCgoqIFRoZSBwcmVhdHRlbnRpdmUgcmVzcG9uc2UgdG8gYmFyIGNoYXJ0cyBpcyBhbHdheXMgdG8gY29tcGFyZQogIHJhdGlvcywgc28gdXNpbmcgYSB6ZXJvIGJhc2UgbGluZSBpcyBpbXBvcnRhbnQuCgoqIFVzaW5nIGEgbm9uLXplcm8gYmFzZSBsaW5lIGZvciBsaW5lIHBsb3RzIGFuZCBzY2F0dGVyIHBsb3RzCiAgZW5jb3VyYWdlcyBpbnRlcnZhbCwgb3IgZGlmZmVyZW5jZSwgY29tcGFyaXNvbnMuCgoqIFJlc2VhcmNoIG9uIHRoZSBlZmZlY3Qgb2YgYXNwYWN0IHJhdGlvIG9uIHBlcmNlcHRpb24gaGFzIGZvY3VzZWQKICBvbiBhY2N1cmFjeSBvZiBzbG9wZSBjb21wYXJpc29ucy4KCiogVGhlIGdlbmVyYWwgbWVzc2FnZSBpcyB0aGF0IGtlZXBpbmcgYXdheSBmcm9tIHNsb3BlcyB0aGF0IGFyZSB0b28KICBzdGVlcCBvciB0b28gc2hhbGxvdyBpcyBiZXN0LgoKKiBfQmFua2luZyB0byA0NSBkZWdyZWVzXywgb3IgY2hvb3NpbmcgYW4gYXNwZWN0IHJhdGlvIHNvIHRoZSBzbG9wZQogIG1hZ25pdHVkZXMgYXJlIGRpc3RyaWJ1dGVkIGFyb3VuZCA0NSBkZWdyZWVzIGlzIG9mdGVuIHJlY29tbWVuZGVkLgoKKiBUaGlzIGFsc28gdGVuZHMgdG8gYmUgYSB1c2VmdWwgIm5ldXRyYWwgZ3JvdW5kIiB3aGVuIHBvbGl0aWNhbAogIGltcGxpY2F0aW9ucyBhcmUgaW52b2x2ZWQuCgpTb21lIHJlZmVyZW5jZXM6CgoqIEEgW2Jsb2cgcG9zdF0oaHR0cHM6Ly9lYWdlcmV5ZXMub3JnL2Jhc2ljcy9iYW5raW5nLTQ1LWRlZ3JlZXMpIGJ5CiAgUm9iZXJ0IEtvc2FyYS4KCiogV2lsbGlhbSBTLiBDbGV2ZWxhbmQsIE1hcnlseW4gRS4gTWNHaWxsIGFuZCBSb2JlcnQgTWNHaWxsICgxOTg4KSwKICAiVGhlIFNoYXBlIFBhcmFtZXRlciBvZiBhIFR3by1WYXJpYWJsZSBHcmFwaCIsIF9Kb3VybmFsIG9mIHRoZQogIEFtZXJpY2FuIFN0YXRpc3RpY2FsIEFzc29jaWF0aW9uXwogIChbSlNUT1JdKGh0dHA6Ly93d3cuanN0b3Iub3JnL3N0YWJsZS8yMjg4ODQzP3NlcT0xI3BhZ2Vfc2Nhbl90YWJfY29udGVudHMpKQoKKiBKdXN0aW4gVGFsYm90LCBKb2huIEdlcnRoLCBQYXQgSGFucmFoYW4gKDIwMTIpLCAiQW4gRW1waXJpY2FsIE1vZGVsCiAgb2YgU2xvcGUgUmF0aW8gQ29tcGFyaXNvbnMiLCBfSUVFRSBUcmFucy4gVmlzdWFsaXphdGlvbiAmCiAgQ29tcC4gR3JhcGhpY3MgKFByb2MuIEluZm9WaXMpXwogIChbUERGXShodHRwOi8vdmlzLnN0YW5mb3JkLmVkdS9maWxlcy8yMDEyLVNsb3BlQ29tcGFyaXNvbi1JbmZvVmlzLnBkZikpCgo8IS0tCkNoZWNrIHRoaXMgb3V0OgpodHRwOi8vdGltZWx5cG9ydGZvbGlvLmdpdGh1Yi5pby9idWlsZGluZ3dpZGdldHMvd2VlazExL2V4YW1wbGVfMDcuaHRtbAotLT4KCjwhLS0KTW9yZSBmcm9tIGhlcmU6Cmh0dHA6Ly9lbnJpY28uYmVydGluaS5pby90ZWFjaGluZy8KLS0+CgoKIyMgRW5zZW1ibGUgUGxvdHMgYW5kIEZhY2V0aW5nCgpVc2luZyBtdWx0aXBsZSBjaGFubmVscyBhbGxvd3MgYSBzaW5nbGUgcGxvdCB0byBzaG93IGEgbG90IG9mIGluZm9ybWF0aW9uLgoKQnV0IG92ZXItcGxvdHRpbmcgYW5kIGludGVyZmVyZW5jZSBjYW4gYmVjb21lIHByb2JsZW1zLgoKT25lIGFsdGVybmF0aXZlIGlzIHRvIHVzZSBzZXZlcmFsIHJlbGF0ZWQgdmlld3MgaW4gYSB1c2VmdWwgYXJyYW5nZW1lbnQuCgpTdWNoIGFycmFuZ2VtZW50cyBhcmUgc29tZXRpbWVzIGNhbGxlZCBfZW5zZW1ibGUgcGxvdHNfLgoKVGhlcmUgYXJlIGEgbnVtYmVyIG9mIHZhcmlhdGlvbnM7IGEgZmV3IGFyZSBpbnRyb2R1Y2VkIGJlbG93LgoKCiMjIyBTaW1pbGFyIFBsb3RzIHdpdGggRGlmZmVyZW50IFZhcmlhYmxlcyBhbmQgU2hhcmVkIEVuY29kaW5ncwoKT25lIHdheSB0byBzaG93IHRocmVlIGNvbnRpbnVvdXMgdmFyaWFibGVzIGlzIHdpdGggdHdvIHBsb3RzIHRoYXQKc2hhcmUgYW4gYXhpczoKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMywgZmlnLndpZHRoID0gOCwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSJ9CmxpYnJhcnkocGF0Y2h3b3JrKQpwZV90aG0gPC0gdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSkpCgpwMSA8LSBnZ3Bsb3QoZ20yMDA3LCBhZXMoeCA9IGdkcFBlcmNhcCwgeSA9IGxpZmVFeHAsIGNvbG9yID0gY29udGluZW50KSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICAgIHBlX3RobQpwMiA8LSBnZ3Bsb3QoZ20yMDA3LCBhZXMoeCA9IHBvcCAvIDEwIF4gNiwgeSA9IGxpZmVFeHAsIGNvbG9yID0gY29udGluZW50KSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBwZV90aG0gKwogICAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCkpCnAxICsgcDIKYGBgCgpMaWZlIGV4cGVjdGFuY3kgaXMgbWFwcGVkIHRvIHRoZSB2ZXJ0aWNhbCBwb3NpdGlvbiBpbiBib3RoIHBsb3RzLgoKQ29udGluZW50IGlzIG1hcHBlZCB0byBjb2xvciBpbiBib3RoIHBsb3RzLgoKR3VpZGVzIGNhbiBiZSBzaGFyZWQgd2hlbiBlbmNvZGluZ3MgYXJlIHNoYXJlZC4KCgojIyMgRGlmZmVyZW50IFBsb3RzIHdpdGggU2hhcmVkIEVuY29kaW5ncwoKTXVsdGlwbGUgdmlld3Mgb2YgdGhlIGRhdGEgYXJlIG9mdGVuIGhlbHBmdWwuCgpTaGFyaW5nIGVuY29kaW5ncyBtYWtlcyB0aGUgcmVsYXRpb25zIGJldHdlZW4gdmlld3MgZWFzaWVyIHRvIHBlcmNlaXZlLgoKYGBge3IsIGZpZy5oZWlnaHQgPSAzLCBmaWcud2lkdGggPSA4LCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0KcDMgPC0gZ2dwbG90KGdtMjAwNywKICAgICAgICAgICAgIGFlcyh4ID0gcG9wIC8gMTAgXiA2LAogICAgICAgICAgICAgICAgIHkgPSByZW9yZGVyKGNvbnRpbmVudCwgcG9wLCBGVU4gPSBzdW0pLAogICAgICAgICAgICAgICAgIGZpbGwgPSBjb250aW5lbnQpKSArCiAgICBnZW9tX2NvbCgpICsKICAgIHlsYWIoTlVMTCkgKwogICAgcGVfdGhtCnAxICsgcDMKYGBgCgoKIyMjIFNtYWxsIE11bHRpcGxlcwoKX1NtYWxsIG11bHRpcGxlc18gcmVmZXJzIHRvIGEgY29sbGVjdGlvbiBvZiBwbG90cyB3aXRoIGlkZW50aWNhbApzdHJ1Y3R1cmUgc2hvd2luZyBkaWZmZXJlbnQgc3Vic2V0cyBvZiB0aGUgZGF0YSBhbmQgb3JnYW5pemVkIGluIGEKdXNlZnVsIHdheS4KClRoZXNlIHBsb3QgY29sbGVjdGlvbnMgYXJlIGFsc28gY2FsbGVkIF90cmVsbGlzIHBsb3RzXywgX2xhdHRpY2UKcGxvdHNfLCBvciBfZmFjZXRlZCBwbG90c18uCgpBIHBsb3Qgb2YgbGlmZSBleHBlY3RhbmN5IGFnYWluc3QgaW5jb21lIHBlciBjYXBpdGEgaW4gMjAwNyBmYWNldGVkIGJ5CmNvbnRpbmVudDoKCmBgYHtyLCBmaWcud2lkdGggPSA4LCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0KZ2QgPC0gZmlsdGVyKGdhcG1pbmRlciwgeWVhciAlaW4lIGMoMTk3NywgMTk4NywgMTk5NywgMjAwNykpCmdkMjAwNyA8LSBmaWx0ZXIoZ2FwbWluZGVyLCB5ZWFyID09IDIwMDcpCmZjdF90aG0gPC0gdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSkpCmdncGxvdChnZDIwMDcsIGFlcyh4ID0gZ2RwUGVyY2FwLCB5ID0gbGlmZUV4cCwgY29sb3IgPSBjb250aW5lbnQpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAyLjUpICsKICAgIHNjYWxlX3hfbG9nMTAoKSArCiAgICBmYWNldF93cmFwKH4gY29udGluZW50KSArCiAgICBmY3RfdGhtCmBgYAoKQSB1c2VmdWwgdmFyaWF0aW9uIGlzIHRvIHNob3cgYSBtdXRlZCB2aWV3IG9mIHRoZSBmdWxsIGRhdGEgaW4gdGhlCmJhY2tncm91bmQ6CgpgYGB7ciwgZmlnLndpZHRoID0gOCwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSJ9CmdncGxvdChnZDIwMDcsIGFlcyh4ID0gZ2RwUGVyY2FwLCB5ID0gbGlmZUV4cCwgY29sb3IgPSBjb250aW5lbnQpKSArCiAgICBnZW9tX3BvaW50KGRhdGEgPSBtdXRhdGUoZ2QyMDA3LCBjb250aW5lbnQgPSBOVUxMKSwgY29sb3IgPSAiZ3JleTgwIikgKwogICAgZ2VvbV9wb2ludChzaXplID0gMi41KSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgZmFjZXRfd3JhcCh+IGNvbnRpbmVudCkgKwogICAgZmN0X3RobQpgYGAKCkRhdGEgY2FuIGJlIGZhY2V0ZXQgb24gdHdvIHZhcmlhYmxlcy4KClRoaXMgcGxvdCBzaG93cyB0aGUgZnVsbCBkYXRhCmZhY2V0ZWQgYnkgYm90aCBjb250aW5lbnQgYW5kIGEgc2V0IG9mIHllYXJzOgoKYGBge3IsIGZpZy53aWR0aCA9IDcsIGZpZy5oZWlnaHQgPSA3LCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0KZ2dwbG90KGdkLCBhZXMoeCA9IGdkcFBlcmNhcCwgeSA9IGxpZmVFeHAsIGNvbG9yID0gY29udGluZW50KSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMi41KSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgZmFjZXRfZ3JpZChjb250aW5lbnQgfiB5ZWFyKSArCiAgICBmY3RfdGhtCmBgYAoKQWRkaW5nIG11dGVkIGRhdGEgZm9yIGVhY2ggeWVhciBoZWxwcyByZWdvbml6aW5nIHdoZXJlIGVhY2gKY29udGluZW50IGdyb3VwIGZpdHMgd2l0aGluIGEgeWVhcgoKYGBge3IsIGZpZy53aWR0aCA9IDcsIGZpZy5oZWlnaHQgPSA3LCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0KZ2dwbG90KGdkLCBhZXMoeCA9IGdkcFBlcmNhcCwgeSA9IGxpZmVFeHAsIGNvbG9yID0gY29udGluZW50KSkgKwogICAgZ2VvbV9wb2ludChkYXRhID0gbXV0YXRlKGdkLCBjb250aW5lbnQgPSBOVUxMKSwgY29sb3IgPSAiZ3JleTgwIikgKwogICAgZ2VvbV9wb2ludChzaXplID0gMi41KSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgZmFjZXRfZ3JpZChjb250aW5lbnQgfiB5ZWFyKSArCiAgICBmY3RfdGhtCmBgYAoKQSBbcmVjZW50IGV4YW1wbGVdKApodHRwczovL3d3dy5mdC5jb20vY29udGVudC8yOWZkOWI1Yy0yZjM1LTQxYmYtOWQ0Yy05OTRkYjRlMTI5OTgpIGZyb20KdGhlIEZpbmFuY2lhbCBUaW1lczoKCmBgYHtyIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjcwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKElNRygiRlQtZ2VuZGVyLXBvbGl0aWNzLmpwZWciKSkKYGBgCgoKIyMgUmVhZGluZwoKU2VjdGlvbiBbX1BlcmNlcHRpb24gYW5kIERhdGEKVmlzdWFsaXphdGlvbl9dKGh0dHBzOi8vc29jdml6LmNvL2xvb2thdGRhdGEuaHRtbCNwZXJjZXB0aW9uLWFuZC1kYXRhLXZpc3VhbGl6YXRpb24pCmluIFtfRGF0YSBWaXN1YWxpemF0aW9uX10oaHR0cHM6Ly9zb2N2aXouY28vKS4KCkNoYXB0ZXIgW19EYXRhIHZpc3VhbGl6YXRpb24KcHJpbmNpcGxlc19dKGh0dHBzOi8vcmFmYWxhYi5kZmNpLmhhcnZhcmQuZWR1L2RzYm9vay1wYXJ0LTEvZGF0YXZpei9kYXRhdml6LXByaW5jaXBsZXMuaHRtbCkKaW4gW19JbnRyb2R1Y3Rpb24gdG8gRGF0YSBTY2llbmNlOiBEYXRhIEFuYWx5c2lzIGFuZCBQcmVkaWN0aW9uCkFsZ29yaXRobXMgd2l0aCBSX10oaHR0cHM6Ly9yYWZhbGFiLmRmY2kuaGFydmFyZC5lZHUvZHNib29rLXBhcnQtMS8pLgoKCiMjIEV4ZXJjaXNlcwoKMS4gV2hpY2ggb2YgdGhlIGZvbGxvd2luZyBjaGFubmVscyBhcmUgbWFnbml0dWRlIGNoYW5uZWxzIGFuZCB3aGljaAogICBhcmUgaWRlbnRpdHkgY2hhbm5lbHM/CgogICAgYS4gUG9zaXRpb24gb24gYSBjb21tb24gc2NhbGUKICAgIGIuIExlbmd0aAogICAgYy4gQ29sb3IgaHVlIChyZWQsIGdyZWVuLCBldGMuKQogICAgZC4gU3ltYm9sIHNoYXBlIChkb3QsIGNyb3NzLCBldGMuKQoKMi4gQ29uc2lkZXIgdGhlIGZvbGxvd2luZyB2aXN1YWxpemF0aW9ucyBvZiB0aGUgMjAxNyBNaWNoZWxpbiBzdGFyCiAgIGRhdGE6CgpgYGB7ciwgaW5jbHVkZSA9IEZBTFNFfQpwbG90Lm5ldygpCm1pY2hlbGluIDwtIHJlYWQudGFibGUoV0xOSygibWljaGVsaW4uZGF0IiksCiAgICAgICAgICAgICAgICAgICAgICAgaGVhZCA9IFRSVUUpCm1pY2hlbGluIDwtIG11dGF0ZShtaWNoZWxpbiwKICAgICAgICAgICAgICAgICAgIHN0YXJzID0gb25lICsgMiAqIHR3byArIDMgKiB0aHJlZSwKICAgICAgICAgICAgICAgICAgICMjIEdldCBzdHJ3aWR0aCBmcm9tIGJhc2UgZ3JhcGhpY3MuCiAgICAgICAgICAgICAgICAgICAjIyBOb3QgcmlnaHQgYnV0IG1heSBiZSBPSyBmb3Igd3VpY2sgdXNlLgogICAgICAgICAgICAgICAgICAgc3Ryd2lkdGggPSA1MDAgKiBzdHJ3aWR0aChjb3VudHJ5LCAiaW5jaGVzIiksCiAgICAgICAgICAgICAgICAgICBjb3VudHJ5ID0gcmVvcmRlcihjb3VudHJ5LCBzdGFycykpCmBgYApgYGB7ciwgZWNobyA9IEZBTFNFfQpsaWJyYXJ5KGRwbHlyLCB3YXJuLmNvbmZsaWN0cyA9IEZBTFNFKQpsaWJyYXJ5KGdncGxvdDIpCgpwMSA8LSBnZ3Bsb3QobWljaGVsaW4sIGFlcyh4ID0gMCwgeSA9IGNvdW50cnksIGxhYmVsID0gY291bnRyeSkpICsKICAgIGdlb21fdGV4dChoanVzdCA9IDAsIHNpemUgPSA0KSArCiAgICBnZW9tX3RpbGUoYWVzKHggPSBzdHJ3aWR0aCArIHN0YXJzIC8gMiwKICAgICAgICAgICAgICAgICAgd2lkdGggPSBzdGFycyksCiAgICAgICAgICAgICAgaGVpZ2h0ID0gMC41LAogICAgICAgICAgICAgIGZpbGwgPSAiZGVlcHNreWJsdWUiKSArCiAgICB4bGltKGMoMCwgMTAwMCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgeWxhYihOVUxMKSArCiAgICB4bGFiKE5VTEwpICsKICAgIGdndGl0bGUoIlBsb3QgQSIpCgpwMiA8LSBnZ3Bsb3QobWljaGVsaW4sIGFlcyh4ID0gc3RhcnMsIHkgPSBjb3VudHJ5LCBsYWJlbCA9IGNvdW50cnkpKSArCiAgICBnZW9tX3RpbGUoYWVzKHggPSBzdGFycyAvIDIsCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gc3RhcnMpLAogICAgICAgICAgICAgIGhlaWdodCA9IDAuNSwKICAgICAgICAgICAgICBmaWxsID0gImRlZXBza3libHVlIikgKwogICAgZ2VvbV90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDQsIG51ZGdlX3ggPSAzMCkgKwogICAgeGxpbShjKDAsIDEwMDApKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIHlsYWIoTlVMTCkgKwogICAgeGxhYihOVUxMKSArCiAgICBnZ3RpdGxlKCJQbG90IEIiKQoKcDEgKyBwMgpgYGAKCldoaWNoIHBsb3QgbWFrZXMgaXQgZWFzaWVyIHRvIGNvbXBhcmUgdGhlIG51bWJlcnMgb2Ygc3RhcnMgZm9yCmRpZmZlcmVudCBjb3VudHJpZXM/IEV4cGxhaW4geW91ciBjb25jbHVzaW9uIGJ5IGlkZW50aWZ5aW5nIHRoZQpjaGFubmVscyB1c2VkIGFuZCB0aGVpciByZWxhdGl2ZSBzdHJlbmd0aHMuCgozLiBJZGVudGlmeSB0aGUgaXRlbXMsIGF0dHJpYnV0ZXMsIG1hcmtzLCBjaGFubmVscywgYW5kIG1hcHBpbmdzIHVzZQogICBpbiB0aGUgZm9sbG93aW5nIHBsb3Q6CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpsaWJyYXJ5KGRwbHlyLCB3YXJuLmNvbmZsaWN0cyA9IEZBTFNFKQpsaWJyYXJ5KGdncGxvdDIpCgptdXRhdGUobXBnLCBjeWwgPSBmYWN0b3IoY3lsKSkgfD4KICAgIGdyb3VwX2J5KGN5bCwgeWVhcikgfD4KICAgIHN1bW1hcml6ZShod3kgPSBtZWFuKGh3eSksIGN0eSA9IG1lYW4oY3R5KSwgQ291bnQgPSBuKCkpIHw+CiAgICB1bmdyb3VwKCkgfD4KICAgIG11dGF0ZShjeWwgPSBmYWN0b3IoY3lsKSwgeWVhciA9IGZhY3Rvcih5ZWFyKSkgfD4KICAgIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBod3ksIHNpemUgPSBDb3VudCwgY29sb3IgPSBjeWwpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgc2NhbGVfc2l6ZV9hcmVhKG1heF9zaXplID0gMTUpICsKICAgIHRoZW1lX21pbmltYWwoKSArIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpCmBgYAo=