In this post, I will explain how I performed a small analysis on the
characteristics of songs from albums in the Rolling Stone top 100
greatest metal albums of all times. I was inspired to do this after I
followed this
tutorial.
Loading libraries
As always with R, the needed libraries need to be loaded before
functions of those libraries can be used:
# Load the necessary libraries
library(dplyr)
library(tidyverse)
library(ggplot2)
library(reshape2)
library(broom)
library(stringr)
library(ggrepel)
library(ggtext)
library(glue)
library(showtext)
library(patchwork)
Another thing to load in advance are the fonts needed to create the
PCA plot:
# Load fonts
font_add_google("Acme", "acme")
font_add_google("Raleway", "raleway")
font_add_google("Cabin Condensed","cabin")
font_add_google("Barlow Condensed","barlow")
font_add_google("Stint Ultra Condensed","stint")
font_add_google("Poppins","poppins")
font_add_google("Pacifico","pacifico")
font_add_google("Oswald","oswald")
# Automatically use {showtext} for plots
showtext_auto()
Importing data
First, I imported the data from TSV files obtained from a dataset
on data.world. These datasets contain data about the Rolling Stone
top 100 best metal albums of all time. For each album, metadata such as
the artist, name, release year, duration, genre, rating and more is
included. For each of the songs on the album, information about the
individual characteristics is included, such as BPM, popularity and
various metrics about how the song sounds (energy, dance, loud, valence
etc.).
# Read in album dataset
raw_albums <- read.delim("RS_metal_albums.txt")
# View results
head(raw_albums)
# Read in song dataset
raw_songs <- read.delim("RS_metal_songs.txt")
# View results
head(raw_songs)
Some of the headers in both datasets contained spaces, which are
automatically replaced by a “.” by R. I replaced these with an
underscore (“_“):
# Change column names of raw_albums
colnames(raw_albums)[4] <- "Release_Year"
colnames(raw_albums)[11] <- "Total_Seconds"
colnames(raw_albums)[13] <- "Sub_Metal_Genre"
colnames(raw_albums)[15] <- "Rolling_Stone_Rating"
# Change column names of raw_songs
colnames(raw_songs)[1] <- "Song_Index"
colnames(raw_songs)[4] <- "Track_No"
The dataset with the songs does not contain any data on the release
year of the album, but the album dataset does. I needed to add a column
to the songs dataset that shows the release year of the album on which
each of the songs is. I did this by using the “AlbumID_Rank” column
which corresponds between the 2 datasets. The method I used for this
operation is from the dplyr
package, and is called
left_join
. I first selected the relevant columns from
raw_albums (AlbumID_Rank
and Release_Year
) and
then joined it to raw_songs
using the
AlbumID_Rank
column.
# Left join on AlbumID_Rank to add the Release_Year to raw_songs
songs_with_year <- raw_songs %>%
left_join(raw_albums %>% select(AlbumID_Rank, Release_Year), by = "AlbumID_Rank")
# View result
head(songs_with_year)
This resulted in a new dataset (songs_with_year
) with a
column appended to the raw_songs
dataset. This column
contains the release year of the album on which the song is.
Another column that might come in useful is the
Sub_Metal_Genre
column of the raw_albums
dataset; I also performed a left_join
on this data:
# Left join on AlbumID_Rank to add the Sub_Metal_Genre to raw_songs
songs_with_year_genre <- songs_with_year %>%
left_join(raw_albums %>% select(AlbumID_Rank, Sub_Metal_Genre), by = "AlbumID_Rank")
# View result
head(songs_with_year_genre)
To choose which variables are going to be included in the PCA, I
wanted to check which variables correlate the most with each other. For
this, I created a correlation matrix with the cor
function
for all numeric columns of the songs_with_year_genre
dataset with the code below:
# Select only numeric columns
numeric_data <- songs_with_year_genre %>%
select_if(is.numeric)
# Calculate correlation matrix
cor_matrix <- cor(numeric_data, use = "complete.obs")
To get a visual insight into the correlation, I created a simple
heatmap of the correlation values with ggplot2
:
# Convert correlation matrix to a long format for ggplot2
cor_data <- melt(cor_matrix)
# Plot heatmap
ggplot(cor_data, aes(Var1, Var2, fill = value)) +
geom_tile(color = "white") + # White space between tiles
scale_fill_gradient2(low = "blue", high = "red", mid = "white", # Heatmap color range
midpoint = 0, limit = c(-1, 1), space = "Lab", # Midpoint 0 and fill between -1 and 1
name = "Correlation") # Legend name

This heatmap does not look the best… There are no labels in the plot
and the x-axis labels overlap. Let’s improve it:
# Plot heatmap, but pretty
ggplot(cor_data, aes(Var1, Var2, fill = value)) +
geom_tile(color = "white") + # White space between tiles
geom_text(aes(label = round(value, 2)), size = 2, color = "black") + # Add labels on tiles
scale_fill_gradient2(low = "blue", high = "red", mid = "white",
midpoint = 0, limit = c(-1, 1), space = "Lab",
name = "Correlation") +
theme_minimal() + # Set theme
theme(text = element_text(size = 9),axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + # Adjust axis labels
labs(title = "Metalsongs Correlation Matrix Heatmap", # Plot title
x = "Variables", # Axis title
y = "Variables") # Axis title

Now, we can see that Song_index
and
AlbumID_Rank
are highly correlated, which makes sense
because the song index values were assigned based on the songs sorted
based on the album ranking. In addition, Loud
and
Energy
are highly correlated, which was also to be expected
because loud songs are also very energetic most of the times. To reduce
redundancy, I will only use one of these two categories:
Energy
for the PCA. 2 combinations that are highly
negatively correlated are Acoustic
and Loud
and Acoustic
and Energy
. Again, this makes
sense because within the metal genre, most acoustic songs are not loud
and do not contain a lot of energy.
A bit more unexpected is the correlation between
Release_Year
and AlbumID_Rank
(and
Song_Index
). This indicates that the year an album was
released influences the position on the Rolling Stone top 100. Let’s see
if I can further analyze this correlation during the PCA.
Selecting PCA data
To perform a PCA, I had to select the variables with numerical values
of interest from the data. These included the ranking place of the
album, but also information about the characteristics of each song and
the year they were released. I also added Song
and
Artist
because this will be usefull when labeling the
different datapoints. To select the variables that are interesting for
our PCA from the data, I used the code below:
# New data for PCA
PCA1_data<-songs_with_year_genre%>%
select(
# Interesting variables for PCA
c(AlbumID_Rank,BPM,Dance,
Loud,Valence,Acoustic,Popularity,
Release_Year,Song,Artist)
)%>%
# Remove NA entries
drop_na()
Plotting variables
To see what variables account for the variability in the plot, I
extracted the coordinates of the variables from the “rotation” matrix of
the PCA1_var
data:
# New dataframe for variables
PCA1_var<-PCA1_rank %>%
# Extract variable coords
tidy(matrix = "rotation") %>%
# Format table long to wide
pivot_wider(names_from = "PC", names_prefix = "PC", values_from = "value") %>%
# Rename column with variable names
rename(Variable=column)
# Check tibble
head(PCA1_var)
To actually plot the variables, I used the ggrepel
library because this prevents errors when variable names overlap. I
chose a different color for the AlbumID_Rank
variable,
because it is interesting to see how this variable is influenced by the
others.
ggplot(data = PCA1_var, aes(PC1, PC2)) +
# Add variable arrows with conditional color
geom_segment(
aes(color = ifelse(Variable == "AlbumID_Rank", "black", "red")),
xend = 0, yend = 0,
arrow = arrow(
length = unit(0.03, "npc"),
type = "closed",
ends = "first"
)
) +
# Add variable names with conditional color
geom_text_repel(
aes(label = Variable, color = ifelse(Variable == "AlbumID_Rank", "black", "red")),
hjust = 1, size = 3,
min.segment.length = Inf,
nudge_x = 0.01, nudge_y = 0.08
) +
coord_fixed() +
labs(
# Add titles
title = 'Plot of PCA Variables Top 100 Metal Albums',
x = 'PC1',
y = 'PC2',
color = 'Variable'
) +
scale_color_identity() +
theme_minimal()

This plot of variables again shows that the AlbumID_Rank
is mostly influenced by Release_Year
, but also that
Acoustic
and Loud
separate a lot of songs.
With a larger plot in mind, I wanted to remove the information about the
PC numbers, and make the plot look more visually appealing so it can be
shown together with the PCA plot:
pretty_var_plot <- ggplot(data = PCA1_var, aes(PC1, PC2)) +
# Add variable arrows with conditional color
geom_segment(
aes(color = ifelse(Variable == "AlbumID_Rank", "black", "#c93434")), # Black and red arrows
xend = 0, yend = 0,
arrow = arrow(
length = unit(0.05, "npc"),
type = "closed",
ends = "first"
),
linewidth = 0.9, # Wide lines
) +
# Add variable names
geom_text_repel(
aes(label = Variable, color = ifelse(Variable == "AlbumID_Rank", "black", "#c93434")), # Black and red names
hjust = 1, size = 3.5,
min.segment.length = Inf,
nudge_x = 0.01, nudge_y = 0.08
) +
# Add dashed line for y axis
annotate(
geom = "segment", x = 0, xend = 0, y = -Inf, yend = Inf, col = "grey60", lty = "dashed",
linewidth = 0.5
) +
# Add dashed line for x axis
annotate(
geom = "segment", x = Inf, xend = -Inf, y = 0, yend = 0, col = "grey60", lty = "dashed",
linewidth = 0.5
) +
# Keep fixed aspect ratio
coord_fixed() +
# Maintain color identity and remove legend
scale_color_identity() +
guides(color = "none") +
theme_minimal() +
theme(
panel.grid = element_blank(),
# No axis labels
axis.text.x = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank()
)
pretty_var_plot

Plotting songs
To actually create a plot of all songs included in the first PCA, I
used ggplot
again. Of course I used red and black in the
color palette, this is a metal data analysis after all :).
# Add rank data back to PCA calculated data
PCA1_indiv_rank<-PCA1_rank%>%
augment(PCA1_data)
# Plot individuals
ggplot(
# Based on calculated PCA data
data=PCA1_indiv_rank,
# Use PCA values and color based on release year
aes(.fittedPC1, .fittedPC2,color=Release_Year))+
geom_point()+
# Add labels and color based on year
labs(
title = 'Plot of individual songs',
subtitle = 'Color shows year of album release of songs',
x='PC1 (26%)',
y='PC2 (22%)',
color='Release_Year'
)+
# Gradient with reds
scale_color_gradient(low = "black", high = "red") +
# Light theme
theme_light()

The plot shows that PC1 is the principal component that is able to
distinguish the songs the best based on the album release year.
Now, I wanted to try and make the plot contain more information and
also look a bit prettier…
Optimizing the plot
The first bit of information I thought about adding to the plot was
the song names. I started with trying to add all labels to the plot with
the code below, but as was to be expected, it became a big mess:
# Check if song names are valid and handle special characters
PCA1_indiv_rank <- PCA1_indiv_rank %>%
# Check that song is a character vector
mutate(Song = as.character(Song)) %>%
# Remove not accepted characters
mutate(Song = iconv(Song, "UTF-8", "ASCII", sub = "")) %>%
mutate(Song = gsub("[^[:alnum:] ]", "", Song))
# Plot the PCA with all song name labels, allowing overlaps
ggplot(PCA1_indiv_rank, aes(.fittedPC1, .fittedPC2, label = Song)) +
geom_point(aes(color = Release_Year)) + # Add points colored by release year
geom_text(aes(label = Song), size = 3, vjust = -0.5, hjust = 0.5) + # Add song labels directly (no overlap avoidance)
# Add labels and color based on year
labs(
title = 'PCA of Songs',
subtitle = 'Color shows year of album release',
x = 'PC1',
y = 'PC2',
color = 'Release Year'
) +
# Color gradient
scale_color_gradient(low = "black", high = "red") +
theme_minimal()

Based on this plot, I noticed two major problems. The first one being
that labeling every single data point leads to overlaps and clutter. The
second one being that some song names are unnecessary long due to them
being remastered versions. I started with trying to fix the first
problem.
Selecting most popular song from each album
To reduce the amount of songs with a label, I decided to make a new
dataset that contains only the most popular song of each album in the
dataset:
# New dataset
highest_popularity_per_album <- PCA1_indiv_rank %>%
# Group based on rank
group_by(AlbumID_Rank) %>%
# Filter rows with max Popularity
filter(Popularity == max(Popularity)) %>%
# Handle ties by selecting the first row
slice(1) %>%
ungroup()
Removing remaster info from popular song names
After making a subset of only the most popular songs, I wanted to
shorten some of the song names. A lot of the songs are remastered after
the initial album release, which means that some information is added to
the song title. I created a regex
pattern to filter out all
songs that have some version of “Remaster”, “Remastered” and a year in
the song title. All text that matches this pattern is removed in the
code below:
# Clean the song names column
popular_no_remaster <- highest_popularity_per_album %>%
mutate(Song = str_remove_all(Song, "(?i)\\s*\\b(remaster(ed)?( \\d{4})?|\\d{4} remaster(ed)?)\\b.*$"))
# Add a flag for popular songs in the original PCA dataset
PCA1_indiv_rank <- PCA1_indiv_rank %>%
mutate(Popular = ifelse(Song %in% popular_no_remaster$Song, TRUE, FALSE))
To make the downstream plotting of this data easier, I added a flag
to the original PCA data to indicate if the song is the most popular of
an album.
Plotting again
Let’s see if reducing the amount of labels to only one for each album
and shortening remastered song names made a difference in making the
plot look better:
# Plot the PCA with non-overlapping labels for popular songs
ggplot(PCA1_indiv_rank, aes(.fittedPC1, .fittedPC2)) +
geom_point(aes(color = Release_Year)) + # Add points colored by release year
geom_text_repel(
data = subset(PCA1_indiv_rank, Popular == TRUE), # Only label popular songs
aes(label = Song),
size = 3, # Text size
box.padding = 0.35, # Padding around the text box
point.padding = 0.5, # Space between the label and the point
max.overlaps = Inf, # Allow all labels to attempt to display
segment.color = 'grey50', # Line color
segment.size = 0.5 # Line thickness
) +
# Add labels and color based on year
labs(
title = 'PCA of Songs',
subtitle = 'Color shows year of album release; labels for popular songs',
x = 'PC1',
y = 'PC2',
color = 'Release Year'
) +
# Colors and theme
scale_color_gradient(low = "black", high = "red") +
theme_minimal()

Well, this still looks very chaotic… Maybe it’s better to manually
select songs that have to be labelled in the graph. For this, I selected
my personal favorites from the most popular metal songs.
# Manually specify the song names to be labeled
selected_songs <- c("Chop Suey","Breaking the Law","Master Of Puppets","Would","Nothing Else Matters","Blind","People Shit","Transilvanian Hunger","Walk","Bat Country","Raining Blood","Killing In The Name")
# New dataset to include only the selected songs
popular_favorites <- popular_no_remaster %>%
filter(Song %in% selected_songs)
# Add a flag for favorite songs in the original PCA dataset
PCA1_indiv_rank <- PCA1_indiv_rank %>%
mutate(Favorite = ifelse(Song %in% popular_favorites$Song, TRUE, FALSE))
# Plot the PCA with repelled labels for popular songs
neat_pca <- ggplot(PCA1_indiv_rank, aes(.fittedPC1, .fittedPC2)) +
geom_point(aes(color = Release_Year)) + # Add points colored by release year
geom_text_repel(
data = subset(PCA1_indiv_rank, Favorite == TRUE), # Only label favorite songs
aes(label = Song),
size = 3,
nudge_x = -0.01,
nudge_y = -0.01,
box.padding = 0.4, # Padding around the text box
point.padding = 0, # Space between the label and the point
max.overlaps = Inf, # Allow all labels to attempt to display
segment.color = 'black', # Line color
segment.size = 0.6 # Line thickness
) +
labs(
title = 'PCA of Songs',
subtitle = 'Color shows year of album release; labels for favorite songs',
x = 'PC1',
y = 'PC2',
color = 'Release Year'
) +
scale_color_gradient(low = "black", high = "red") +
theme_minimal()
neat_pca

Creating the ideal plot
I already really liked this version of the plot, but I wanted to make
it look more styled. In the code below, I played around with different
looks for the datapoints, labelling mechanisms and fonts.
pretty_pca_plot1 <- ggplot(PCA1_indiv_rank, aes(.fittedPC1, .fittedPC2, color = Release_Year)) + # Map color to a variable
geom_point(alpha=0.2,size = 2) +
scale_color_gradient(low = "black", high = "red") +
scale_x_continuous(limits = c(-5, 7)) + # Plot size x
scale_y_continuous(limits = c(-7.8, 10))+ # Plot size y
# Labels that can not overlap and are not on the datapoint
geom_text_repel(
data = subset(PCA1_indiv_rank, Favorite == TRUE), # Only label favorite songs
aes(label = paste(Song, "\n", Artist, sep = ""), fontface = "bold.italic"), # Song and artist label
size = 2.8, # Text size
box.padding = 0.6, # Increase padding around text boxes
point.padding = 0.1, # Padding between points and labels
force = 20, # Increase repulsion between labels
force_pull = 0.1, # Slight pull to the data points, ensuring alignment
min.segment.length = 0.5, # Avoid overly short segment lines
max.overlaps = Inf, # Ensure all labels are shown
segment.color = 'black', # Line color
segment.size = 0.3 # Thinner segment lines
)
# View
pretty_pca_plot1

I liked the styling of the points and labels here, but I wanted the
axes to run through the middle of the data instead of being on the
sides. I did this by creating some arrow styles and adding them
manually:
arrow_style <- arrow(
angle = 20, ends = "first", type = "closed", length = grid::unit(4, "pt")
)
arrow_style_ind <- arrow(
angle = 45,
length = grid::unit(8, "pt")
)
pretty_pca_plot2 <- pretty_pca_plot1 +
# x-axis line
annotate(
geom = "segment", x = -5, xend = 6, y = 0, yend = 0,
lty = "dashed",
col = "grey60",
size = 0.5
) +
# x-axis arrow
annotate(
geom = "segment", x = 5.9, xend = 6, y = 0, yend = 0,
col = "grey60",
size = 0.5, arrow = arrow_style_ind, lineend = 'round', linejoin = 'round'
) +
# x-axis label
annotate(
geom = "text", x = 4.7, y = 0.25, label = "Principal Component 1 (26%)",
col = "dimgrey", size = 3, family = "sans", fontface = "italic"
) +
# y-axis label
annotate(
geom = "text", x = -0.1, y = -7.7, label = "Principal Component 2 (22%)",
col = "dimgrey", size = 3, family = "sans", angle = 90, vjust = 0, hjust = 0, fontface = "italic"
) +
# y-axis
annotate(
geom = "segment", x = 0, xend = 0, y = -7.8, yend = 5, col = "grey60", lty = "dashed",
size = 0.5
) +
# y-axis arrow
annotate(
geom = "segment", x = 0, xend = 0, y = 4.9, yend = 5, col = "grey60",
size = 0.5, arrow = arrow_style_ind, lineend = 'round', linejoin = 'round'
)
pretty_pca_plot2

Now, there are too many axes and the background does not fit the
style anymore. I fixed it like this:
pretty_pca_plot3 <- pretty_pca_plot2 +
# Set minimal theme
theme_minimal() +
theme(
panel.grid = element_blank(), # No grid
# No axis labels
axis.text.x = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
)
pretty_pca_plot3

This plot now really misses some additional information, such as what
type of data we are looking at, what kind of analysis was performed and
the data source. I also incorporated the legend into the subtitle.
# Create title object
maintitle<-cbind.data.frame(
# Position on left top
x = -5, y = 9.5,
# Glue for HTML styling
label = glue("<span style='color:darkred'>PCA Rolling Stone top 100 metal albums of all time</span>")
)
# Subtitle object
subtitle <- cbind.data.frame(
# Position below title
x = -5, y = 8.5,
# Glue for HTML styling, include legend colors
label = glue("<span style='color:#2b2a30'>Principal component analysis of metal songs' features from the<br>Rolling Stone top 100 Metal Albums from </span><b style='color:black'> 1970 </b><span style='color:#2b2a30'>to</span><b style='color:red'> 2013 </b><span style='color:#2b2a30'>.<br>Each dot stands for a song, with title and artist for some favorite tracks.</span> ")
)
pretty_pca_plot4 <- pretty_pca_plot3 +
annotate(
geom = "text", x = 6, y = -7.5, hjust = 1, color = "dimgrey",
label = "Data: data.world",
size = 2, family = "cabin", lineheight = 0.4
) +
geom_richtext(
data = maintitle,
aes(x = x, y = y, label = label),
inherit.aes = FALSE, lineheight = 0.5,
alpha = 1, size = 7, family = 'cabin', hjust = 0, vjust = 1,
fill = NA, label.color = NA,
label.padding = grid::unit(rep(0, 4), "pt")
) +
geom_richtext(
data = subtitle,
aes(x = x, y = y, label = label),
inherit.aes = FALSE, lineheight = 0.5,
alpha = 1, size = 5, family = 'cabin', hjust = 0, vjust = 1,
fill = NA, label.color = NA,
label.padding = grid::unit(rep(0, 4), "pt")
) +
# Remove original legend
theme(
legend.position = "none"
)
pretty_pca_plot4

This looks good! But, I have also created a plot of variables that I
want to include in this figure. I used patchwork
to combine
these two plots into one.
# Make plot with patchwork
layout = c(
area(t = 0, l = 0, b = 10, r = 15), # Large area
area(t = 0, l = 6, b = 5, r = 17) # Smaller area in right corner
)
pretty_pca_plot4+pretty_var_plot+plot_layout(design=layout)

Okay, one final touch! I want to help the viewer understand the plot
of variables better, so I want to add a description of the variable plot
to the figure:
pretty_pca_plot5 <- pretty_pca_plot4 +
annotate(
geom = "text", x = 3.2, y = 3.3, hjust = 0.5, label = "Album ranking is\n heavily influenced\n by release year",
size = 3.8, family = "cabin", lineheight = 1
)
# Make plot with patchwork
layout2 = c(
area(t = 0, l = 0, b = 10, r = 15), # Large area
area(t = 0, l = 6, b = 5, r = 17) # Smaller area in right corner
)
pretty_pca_plot5+pretty_var_plot+plot_layout(design=layout)

Unfortunately, some of the label positions keep changing due to the
use of patchwork
, but this is the best I could achieve with
my skills.
This plot shows that the release year of the album of the songs
correlates the most with the rank of the albums, which shows that
Rolling Stone ranked older metal albums higher than the newer metal
albums. It also shows that my personal taste differs leans towards the
left and darker side of the main cloud of songs, which means that I
prefer older songs too new ones.
This document will be improved in the future!
LS0tDQp0aXRsZTogIk1ldGFsbXVzaWMgUENBIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCkluIHRoaXMgcG9zdCwgSSB3aWxsIGV4cGxhaW4gaG93IEkgcGVyZm9ybWVkIGEgc21hbGwgYW5hbHlzaXMgb24gdGhlIGNoYXJhY3RlcmlzdGljcyBvZiBzb25ncyBmcm9tIGFsYnVtcyBpbiB0aGUgUm9sbGluZyBTdG9uZSB0b3AgMTAwIGdyZWF0ZXN0IG1ldGFsIGFsYnVtcyBvZiBhbGwgdGltZXMuIEkgd2FzIGluc3BpcmVkIHRvIGRvIHRoaXMgYWZ0ZXIgSSBmb2xsb3dlZCBbdGhpcyB0dXRvcmlhbF0oaHR0cHM6Ly9iam5ub3dhay5uZXRsaWZ5LmFwcC8yMDIxLzA5LzE1L3ItcGNhLXdpdGgtdGlkeXZlcnNlLykuDQoNCiMgTG9hZGluZyBsaWJyYXJpZXMNCkFzIGFsd2F5cyB3aXRoIFIsIHRoZSBuZWVkZWQgbGlicmFyaWVzIG5lZWQgdG8gYmUgbG9hZGVkIGJlZm9yZSBmdW5jdGlvbnMgb2YgdGhvc2UgbGlicmFyaWVzIGNhbiBiZSB1c2VkOg0KYGBge3IgbGlicmFyaWVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBMb2FkIHRoZSBuZWNlc3NhcnkgbGlicmFyaWVzDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkoZ2dyZXBlbCkNCmxpYnJhcnkoZ2d0ZXh0KQ0KbGlicmFyeShnbHVlKQ0KbGlicmFyeShzaG93dGV4dCkNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KYGBgDQoNCkFub3RoZXIgdGhpbmcgdG8gbG9hZCBpbiBhZHZhbmNlIGFyZSB0aGUgZm9udHMgbmVlZGVkIHRvIGNyZWF0ZSB0aGUgUENBIHBsb3Q6DQpgYGB7ciBmb250cywgbWVzc2FnZT1GQUxTRX0NCiMgTG9hZCBmb250cw0KZm9udF9hZGRfZ29vZ2xlKCJBY21lIiwgImFjbWUiKQ0KZm9udF9hZGRfZ29vZ2xlKCJSYWxld2F5IiwgInJhbGV3YXkiKQ0KZm9udF9hZGRfZ29vZ2xlKCJDYWJpbiBDb25kZW5zZWQiLCJjYWJpbiIpDQpmb250X2FkZF9nb29nbGUoIkJhcmxvdyBDb25kZW5zZWQiLCJiYXJsb3ciKQ0KZm9udF9hZGRfZ29vZ2xlKCJTdGludCBVbHRyYSBDb25kZW5zZWQiLCJzdGludCIpDQpmb250X2FkZF9nb29nbGUoIlBvcHBpbnMiLCJwb3BwaW5zIikNCmZvbnRfYWRkX2dvb2dsZSgiUGFjaWZpY28iLCJwYWNpZmljbyIpDQpmb250X2FkZF9nb29nbGUoIk9zd2FsZCIsIm9zd2FsZCIpDQoNCiMgQXV0b21hdGljYWxseSB1c2Uge3Nob3d0ZXh0fSBmb3IgcGxvdHMNCnNob3d0ZXh0X2F1dG8oKQ0KYGBgDQojIEltcG9ydGluZyBkYXRhDQpGaXJzdCwgSSBpbXBvcnRlZCB0aGUgZGF0YSBmcm9tIFRTViBmaWxlcyBvYnRhaW5lZCBmcm9tIGEgW2RhdGFzZXQgb24gZGF0YS53b3JsZF0oaHR0cHM6Ly9kYXRhLndvcmxkL2tjbWlsbGVyc2Vhbi9ycy0xMDAtZ3JlYXRlc3QtbWV0YWwtYWxidW1zLW9mLWFsbC10aW1lKS4gVGhlc2UgZGF0YXNldHMgY29udGFpbiBkYXRhIGFib3V0IHRoZSBSb2xsaW5nIFN0b25lIHRvcCAxMDAgYmVzdCBtZXRhbCBhbGJ1bXMgb2YgYWxsIHRpbWUuIEZvciBlYWNoIGFsYnVtLCBtZXRhZGF0YSBzdWNoIGFzIHRoZSBhcnRpc3QsIG5hbWUsIHJlbGVhc2UgeWVhciwgZHVyYXRpb24sIGdlbnJlLCByYXRpbmcgYW5kIG1vcmUgaXMgaW5jbHVkZWQuIEZvciBlYWNoIG9mIHRoZSBzb25ncyBvbiB0aGUgYWxidW0sIGluZm9ybWF0aW9uIGFib3V0IHRoZSBpbmRpdmlkdWFsIGNoYXJhY3RlcmlzdGljcyBpcyBpbmNsdWRlZCwgc3VjaCBhcyBCUE0sIHBvcHVsYXJpdHkgYW5kIHZhcmlvdXMgbWV0cmljcyBhYm91dCBob3cgdGhlIHNvbmcgc291bmRzIChlbmVyZ3ksIGRhbmNlLCBsb3VkLCB2YWxlbmNlIGV0Yy4pLg0KYGBge3IgbG9hZF9hbGJ1bV9kYXRhfQ0KIyBSZWFkIGluIGFsYnVtIGRhdGFzZXQNCnJhd19hbGJ1bXMgPC0gcmVhZC5kZWxpbSgiUlNfbWV0YWxfYWxidW1zLnR4dCIpDQoNCiMgVmlldyByZXN1bHRzDQpoZWFkKHJhd19hbGJ1bXMpDQpgYGANCmBgYHtyIGxvYWRfc29uZ19kYXRhfQ0KIyBSZWFkIGluIHNvbmcgZGF0YXNldA0KcmF3X3NvbmdzIDwtIHJlYWQuZGVsaW0oIlJTX21ldGFsX3NvbmdzLnR4dCIpDQoNCiMgVmlldyByZXN1bHRzDQpoZWFkKHJhd19zb25ncykNCmBgYA0KU29tZSBvZiB0aGUgaGVhZGVycyBpbiBib3RoIGRhdGFzZXRzIGNvbnRhaW5lZCBzcGFjZXMsIHdoaWNoIGFyZSBhdXRvbWF0aWNhbGx5IHJlcGxhY2VkIGJ5IGEgIi4iIGJ5IFIuIEkgcmVwbGFjZWQgdGhlc2Ugd2l0aCBhbiB1bmRlcnNjb3JlICgiXyIpOg0KYGBge3IgcmVtb3ZlX3VuZGVyc2NvcmVzfQ0KIyBDaGFuZ2UgY29sdW1uIG5hbWVzIG9mIHJhd19hbGJ1bXMNCmNvbG5hbWVzKHJhd19hbGJ1bXMpWzRdIDwtICJSZWxlYXNlX1llYXIiDQpjb2xuYW1lcyhyYXdfYWxidW1zKVsxMV0gPC0gIlRvdGFsX1NlY29uZHMiDQpjb2xuYW1lcyhyYXdfYWxidW1zKVsxM10gPC0gIlN1Yl9NZXRhbF9HZW5yZSINCmNvbG5hbWVzKHJhd19hbGJ1bXMpWzE1XSA8LSAiUm9sbGluZ19TdG9uZV9SYXRpbmciDQoNCiMgQ2hhbmdlIGNvbHVtbiBuYW1lcyBvZiByYXdfc29uZ3MNCmNvbG5hbWVzKHJhd19zb25ncylbMV0gPC0gIlNvbmdfSW5kZXgiDQpjb2xuYW1lcyhyYXdfc29uZ3MpWzRdIDwtICJUcmFja19ObyINCmBgYA0KVGhlIGRhdGFzZXQgd2l0aCB0aGUgc29uZ3MgZG9lcyBub3QgY29udGFpbiBhbnkgZGF0YSBvbiB0aGUgcmVsZWFzZSB5ZWFyIG9mIHRoZSBhbGJ1bSwgYnV0IHRoZSBhbGJ1bSBkYXRhc2V0IGRvZXMuIEkgbmVlZGVkIHRvIGFkZCBhIGNvbHVtbiB0byB0aGUgc29uZ3MgZGF0YXNldCB0aGF0IHNob3dzIHRoZSByZWxlYXNlIHllYXIgb2YgdGhlIGFsYnVtIG9uIHdoaWNoIGVhY2ggb2YgdGhlIHNvbmdzIGlzLiBJIGRpZCB0aGlzIGJ5IHVzaW5nIHRoZSAiQWxidW1JRF9SYW5rIiBjb2x1bW4gd2hpY2ggY29ycmVzcG9uZHMgYmV0d2VlbiB0aGUgMiBkYXRhc2V0cy4gVGhlIG1ldGhvZCBJIHVzZWQgZm9yIHRoaXMgb3BlcmF0aW9uIGlzIGZyb20gdGhlIGBkcGx5cmAgcGFja2FnZSwgYW5kIGlzIGNhbGxlZCBgbGVmdF9qb2luYC4gSSBmaXJzdCBzZWxlY3RlZCB0aGUgcmVsZXZhbnQgY29sdW1ucyBmcm9tIHJhd19hbGJ1bXMgKGBBbGJ1bUlEX1JhbmtgIGFuZCBgUmVsZWFzZV9ZZWFyYCkgYW5kIHRoZW4gam9pbmVkIGl0IHRvIGByYXdfc29uZ3NgIHVzaW5nIHRoZSBgQWxidW1JRF9SYW5rYCBjb2x1bW4uIA0KYGBge3IgbGpvaW5feWVhcnN9DQojIExlZnQgam9pbiBvbiBBbGJ1bUlEX1JhbmsgdG8gYWRkIHRoZSBSZWxlYXNlX1llYXIgdG8gcmF3X3NvbmdzDQpzb25nc193aXRoX3llYXIgPC0gcmF3X3NvbmdzICU+JQ0KICBsZWZ0X2pvaW4ocmF3X2FsYnVtcyAlPiUgc2VsZWN0KEFsYnVtSURfUmFuaywgUmVsZWFzZV9ZZWFyKSwgYnkgPSAiQWxidW1JRF9SYW5rIikNCg0KIyBWaWV3IHJlc3VsdA0KaGVhZChzb25nc193aXRoX3llYXIpDQpgYGANClRoaXMgcmVzdWx0ZWQgaW4gYSBuZXcgZGF0YXNldCAoYHNvbmdzX3dpdGhfeWVhcmApIHdpdGggYSBjb2x1bW4gYXBwZW5kZWQgdG8gdGhlIGByYXdfc29uZ3NgIGRhdGFzZXQuIFRoaXMgY29sdW1uIGNvbnRhaW5zIHRoZSByZWxlYXNlIHllYXIgb2YgdGhlIGFsYnVtIG9uIHdoaWNoIHRoZSBzb25nIGlzLiANCg0KQW5vdGhlciBjb2x1bW4gdGhhdCBtaWdodCBjb21lIGluIHVzZWZ1bCBpcyB0aGUgYFN1Yl9NZXRhbF9HZW5yZWAgY29sdW1uIG9mIHRoZSBgcmF3X2FsYnVtc2AgZGF0YXNldDsgSSBhbHNvIHBlcmZvcm1lZCBhIGBsZWZ0X2pvaW5gIG9uIHRoaXMgZGF0YTogDQpgYGB7ciBsam9pbl9nZW5yZX0NCiMgTGVmdCBqb2luIG9uIEFsYnVtSURfUmFuayB0byBhZGQgdGhlIFN1Yl9NZXRhbF9HZW5yZSB0byByYXdfc29uZ3MNCnNvbmdzX3dpdGhfeWVhcl9nZW5yZSA8LSBzb25nc193aXRoX3llYXIgJT4lDQogIGxlZnRfam9pbihyYXdfYWxidW1zICU+JSBzZWxlY3QoQWxidW1JRF9SYW5rLCBTdWJfTWV0YWxfR2VucmUpLCBieSA9ICJBbGJ1bUlEX1JhbmsiKQ0KDQojIFZpZXcgcmVzdWx0DQpoZWFkKHNvbmdzX3dpdGhfeWVhcl9nZW5yZSkNCmBgYA0KVG8gY2hvb3NlIHdoaWNoIHZhcmlhYmxlcyBhcmUgZ29pbmcgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIFBDQSwgSSB3YW50ZWQgdG8gY2hlY2sgd2hpY2ggdmFyaWFibGVzIGNvcnJlbGF0ZSB0aGUgbW9zdCB3aXRoIGVhY2ggb3RoZXIuIEZvciB0aGlzLCBJIGNyZWF0ZWQgYSBjb3JyZWxhdGlvbiBtYXRyaXggd2l0aCB0aGUgYGNvcmAgZnVuY3Rpb24gZm9yIGFsbCBudW1lcmljIGNvbHVtbnMgb2YgdGhlIGBzb25nc193aXRoX3llYXJfZ2VucmVgIGRhdGFzZXQgd2l0aCB0aGUgY29kZSBiZWxvdzoNCg0KYGBge3IgY2FsY3VsYXRlX2Nvcm1hdHJpeH0NCiMgU2VsZWN0IG9ubHkgbnVtZXJpYyBjb2x1bW5zDQpudW1lcmljX2RhdGEgPC0gc29uZ3Nfd2l0aF95ZWFyX2dlbnJlICU+JQ0KICBzZWxlY3RfaWYoaXMubnVtZXJpYykNCg0KIyBDYWxjdWxhdGUgY29ycmVsYXRpb24gbWF0cml4DQpjb3JfbWF0cml4IDwtIGNvcihudW1lcmljX2RhdGEsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQ0KYGBgDQpUbyBnZXQgYSB2aXN1YWwgaW5zaWdodCBpbnRvIHRoZSBjb3JyZWxhdGlvbiwgSSBjcmVhdGVkIGEgc2ltcGxlIGhlYXRtYXAgb2YgdGhlIGNvcnJlbGF0aW9uIHZhbHVlcyB3aXRoIGBnZ3Bsb3QyYDoNCmBgYHtyIHBsb3RfY29ybWF0cml4fQ0KIyBDb252ZXJ0IGNvcnJlbGF0aW9uIG1hdHJpeCB0byBhIGxvbmcgZm9ybWF0IGZvciBnZ3Bsb3QyDQpjb3JfZGF0YSA8LSBtZWx0KGNvcl9tYXRyaXgpDQoNCiMgUGxvdCBoZWF0bWFwDQpnZ3Bsb3QoY29yX2RhdGEsIGFlcyhWYXIxLCBWYXIyLCBmaWxsID0gdmFsdWUpKSArDQogIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpICsgIyBXaGl0ZSBzcGFjZSBiZXR3ZWVuIHRpbGVzDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKGxvdyA9ICJibHVlIiwgaGlnaCA9ICJyZWQiLCBtaWQgPSAid2hpdGUiLCAjIEhlYXRtYXAgY29sb3IgcmFuZ2UNCiAgICAgICAgICAgICAgICAgICAgICAgbWlkcG9pbnQgPSAwLCBsaW1pdCA9IGMoLTEsIDEpLCBzcGFjZSA9ICJMYWIiLCAjIE1pZHBvaW50IDAgYW5kIGZpbGwgYmV0d2VlbiAtMSBhbmQgMQ0KICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkNvcnJlbGF0aW9uIikgIyBMZWdlbmQgbmFtZQ0KYGBgDQpUaGlzIGhlYXRtYXAgZG9lcyBub3QgbG9vayB0aGUgYmVzdC4uLiBUaGVyZSBhcmUgbm8gbGFiZWxzIGluIHRoZSBwbG90IGFuZCB0aGUgeC1heGlzIGxhYmVscyBvdmVybGFwLiBMZXQncyBpbXByb3ZlIGl0Og0KYGBge3IgcGxvdF9jb3JtYXRyaXhfcHJldHR5fQ0KIyBQbG90IGhlYXRtYXAsIGJ1dCBwcmV0dHkNCmdncGxvdChjb3JfZGF0YSwgYWVzKFZhcjEsIFZhcjIsIGZpbGwgPSB2YWx1ZSkpICsNCiAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKyAjIFdoaXRlIHNwYWNlIGJldHdlZW4gdGlsZXMNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKHZhbHVlLCAyKSksIHNpemUgPSAyLCBjb2xvciA9ICJibGFjayIpICsgIyBBZGQgbGFiZWxzIG9uIHRpbGVzDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKGxvdyA9ICJibHVlIiwgaGlnaCA9ICJyZWQiLCBtaWQgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgICAgICAgICBtaWRwb2ludCA9IDAsIGxpbWl0ID0gYygtMSwgMSksIHNwYWNlID0gIkxhYiIsDQogICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiQ29ycmVsYXRpb24iKSArDQogIHRoZW1lX21pbmltYWwoKSArICMgU2V0IHRoZW1lDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgaGp1c3QgPSAxKSkgKyAjIEFkanVzdCBheGlzIGxhYmVscw0KICBsYWJzKHRpdGxlID0gIk1ldGFsc29uZ3MgQ29ycmVsYXRpb24gTWF0cml4IEhlYXRtYXAiLCAjIFBsb3QgdGl0bGUNCiAgICAgICB4ID0gIlZhcmlhYmxlcyIsICMgQXhpcyB0aXRsZQ0KICAgICAgIHkgPSAiVmFyaWFibGVzIikgIyBBeGlzIHRpdGxlDQpgYGANCk5vdywgd2UgY2FuIHNlZSB0aGF0IGBTb25nX2luZGV4YCBhbmQgYEFsYnVtSURfUmFua2AgYXJlIGhpZ2hseSBjb3JyZWxhdGVkLCB3aGljaCBtYWtlcyBzZW5zZSBiZWNhdXNlIHRoZSBzb25nIGluZGV4IHZhbHVlcyB3ZXJlIGFzc2lnbmVkIGJhc2VkIG9uIHRoZSBzb25ncyBzb3J0ZWQgYmFzZWQgb24gdGhlIGFsYnVtIHJhbmtpbmcuIEluIGFkZGl0aW9uLCBgTG91ZGAgYW5kIGBFbmVyZ3lgIGFyZSBoaWdobHkgY29ycmVsYXRlZCwgd2hpY2ggd2FzIGFsc28gdG8gYmUgZXhwZWN0ZWQgYmVjYXVzZSBsb3VkIHNvbmdzIGFyZSBhbHNvIHZlcnkgZW5lcmdldGljIG1vc3Qgb2YgdGhlIHRpbWVzLiBUbyByZWR1Y2UgcmVkdW5kYW5jeSwgSSB3aWxsIG9ubHkgdXNlIG9uZSBvZiB0aGVzZSB0d28gY2F0ZWdvcmllczogYEVuZXJneWAgZm9yIHRoZSBQQ0EuIDIgY29tYmluYXRpb25zIHRoYXQgYXJlIGhpZ2hseSBuZWdhdGl2ZWx5IGNvcnJlbGF0ZWQgYXJlIGBBY291c3RpY2AgYW5kIGBMb3VkYCBhbmQgYEFjb3VzdGljYCBhbmQgYEVuZXJneWAuIEFnYWluLCB0aGlzIG1ha2VzIHNlbnNlIGJlY2F1c2Ugd2l0aGluIHRoZSBtZXRhbCBnZW5yZSwgbW9zdCBhY291c3RpYyBzb25ncyBhcmUgbm90IGxvdWQgYW5kIGRvIG5vdCBjb250YWluIGEgbG90IG9mIGVuZXJneS4gDQoNCkEgYml0IG1vcmUgdW5leHBlY3RlZCBpcyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBgUmVsZWFzZV9ZZWFyYCBhbmQgYEFsYnVtSURfUmFua2AgKGFuZCBgU29uZ19JbmRleGApLiBUaGlzIGluZGljYXRlcyB0aGF0IHRoZSB5ZWFyIGFuIGFsYnVtIHdhcyByZWxlYXNlZCBpbmZsdWVuY2VzIHRoZSBwb3NpdGlvbiBvbiB0aGUgUm9sbGluZyBTdG9uZSB0b3AgMTAwLiBMZXQncyBzZWUgaWYgSSBjYW4gZnVydGhlciBhbmFseXplIHRoaXMgY29ycmVsYXRpb24gZHVyaW5nIHRoZSBQQ0EuDQoNCiMgU2VsZWN0aW5nIFBDQSBkYXRhDQpUbyBwZXJmb3JtIGEgUENBLCBJIGhhZCB0byBzZWxlY3QgdGhlIHZhcmlhYmxlcyB3aXRoIG51bWVyaWNhbCB2YWx1ZXMgb2YgaW50ZXJlc3QgZnJvbSB0aGUgZGF0YS4gVGhlc2UgaW5jbHVkZWQgdGhlIHJhbmtpbmcgcGxhY2Ugb2YgdGhlIGFsYnVtLCBidXQgYWxzbyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIGVhY2ggc29uZyBhbmQgdGhlIHllYXIgdGhleSB3ZXJlIHJlbGVhc2VkLiBJIGFsc28gYWRkZWQgYFNvbmdgIGFuZCBgQXJ0aXN0YCBiZWNhdXNlIHRoaXMgd2lsbCBiZSB1c2VmdWxsIHdoZW4gbGFiZWxpbmcgdGhlIGRpZmZlcmVudCBkYXRhcG9pbnRzLg0KVG8gc2VsZWN0IHRoZSB2YXJpYWJsZXMgdGhhdCBhcmUgaW50ZXJlc3RpbmcgZm9yIG91ciBQQ0EgZnJvbSB0aGUgZGF0YSwgSSB1c2VkIHRoZSBjb2RlIGJlbG93Og0KYGBge3Igc2VsZWN0aW5nfQ0KIyBOZXcgZGF0YSBmb3IgUENBDQpQQ0ExX2RhdGE8LXNvbmdzX3dpdGhfeWVhcl9nZW5yZSU+JQ0KICBzZWxlY3QoDQogICAgIyBJbnRlcmVzdGluZyB2YXJpYWJsZXMgZm9yIFBDQQ0KICAgIGMoQWxidW1JRF9SYW5rLEJQTSxEYW5jZSwNCiAgICAgIExvdWQsVmFsZW5jZSxBY291c3RpYyxQb3B1bGFyaXR5LA0KICAgICAgUmVsZWFzZV9ZZWFyLFNvbmcsQXJ0aXN0KQ0KICApJT4lDQogICMgUmVtb3ZlIE5BIGVudHJpZXMNCiAgZHJvcF9uYSgpDQpgYGANCiMgUGVyZm9ybWluZyB0aGUgUENBDQpBZnRlciB0aGVzZSBzdGVwcyBJIHdhcyByZWFkeSB0byBwZXJmb3JtIHRoZSBQQ0EsIHdoaWNoIEkgZGlkIHVzaW5nIHRoZSBgcHJjb21wYCBmdW5jdGlvbjoNCg0KYGBge3IgUENBMV9yYW5rfQ0KIyBSZW1vdmUgdGhlIG5vbi1udW1lcmljYWwgYXJ0aXN0IGFuZCBzb25nIG5hbWUgZGF0YSBmb3IgdGhlIFBDQQ0KUENBMV9yYW5rIDwtIFBDQTFfZGF0YSU+JQ0KICBzZWxlY3QoLUFydGlzdCwtU29uZyklPiUNCiAgIyBQZXJmb3JtIFBDQSANCiAgcHJjb21wKHNjYWxlPVRSVUUpDQpgYGANCg0KSSB1c2VkIGFub3RoZXIgcGFja2FnZSAoYGJyb29tYCkgdG8gdmlldyB0aGUgcmVzdWx0cyBpbiB0aGUgYHRpZHl2ZXJzZWAgc3ludGF4Og0KDQpgYGB7ciBhY2Nlc3NfUENBMV9yYW5rfQ0KIyBWaWV3IHJlc3VsdHMgaW4gZWlnZW52YWx1ZXMgbWF0cml4DQpQQ0ExX3JhbmslPiUNCiAgdGlkeShtYXRyaXggPSAiZWlnZW52YWx1ZXMiKQ0KYGBgDQpBcyB0aGUgdGliYmxlIHNob3dzLCBQQ0ExIGFjY291bnRzIGZvciAyNiUgb2YgdGhlIG92ZXJhbGwgdmFyaWFiaWxpdHksIGFuZCBQQ0EyIGZvciAyMiUuIEkgd2FudGVkIHRvIHZpc3VhbGl6ZSBob3cgdGhlIGRpZmZlcmVudCBjYXRlZ29yaWVzIHNlcGFyYXRlIHRoZSBkYXRhLCBiZWZvcmUgcGxvdHRpbmcgdGhlIGFjdHVhbCBkYXRhcG9pbnRzIG9mIGVhY2ggc29uZy4NCg0KIyBQbG90dGluZyB2YXJpYWJsZXMNClRvIHNlZSB3aGF0IHZhcmlhYmxlcyBhY2NvdW50IGZvciB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIHBsb3QsIEkgZXh0cmFjdGVkIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgdmFyaWFibGVzIGZyb20gdGhlICJyb3RhdGlvbiIgbWF0cml4IG9mIHRoZSBgUENBMV92YXJgIGRhdGE6DQpgYGB7ciBQQ0ExX3ZhcmlhYmxlc30NCiMgTmV3IGRhdGFmcmFtZSBmb3IgdmFyaWFibGVzDQpQQ0ExX3ZhcjwtUENBMV9yYW5rICU+JQ0KICAjIEV4dHJhY3QgdmFyaWFibGUgY29vcmRzDQogIHRpZHkobWF0cml4ID0gInJvdGF0aW9uIikgJT4lDQogICMgRm9ybWF0IHRhYmxlIGxvbmcgdG8gd2lkZQ0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gIlBDIiwgbmFtZXNfcHJlZml4ID0gIlBDIiwgdmFsdWVzX2Zyb20gPSAidmFsdWUiKSAlPiUNCiAgIyBSZW5hbWUgY29sdW1uIHdpdGggdmFyaWFibGUgbmFtZXMNCiAgcmVuYW1lKFZhcmlhYmxlPWNvbHVtbikNCiAgIyBDaGVjayB0aWJibGUNCiAgaGVhZChQQ0ExX3ZhcikNCmBgYA0KVG8gYWN0dWFsbHkgcGxvdCB0aGUgdmFyaWFibGVzLCBJIHVzZWQgdGhlIGBnZ3JlcGVsYCBsaWJyYXJ5IGJlY2F1c2UgdGhpcyBwcmV2ZW50cyBlcnJvcnMgd2hlbiB2YXJpYWJsZSBuYW1lcyBvdmVybGFwLiAgSSBjaG9zZSBhIGRpZmZlcmVudCBjb2xvciBmb3IgdGhlIGBBbGJ1bUlEX1JhbmtgIHZhcmlhYmxlLCBiZWNhdXNlIGl0IGlzIGludGVyZXN0aW5nIHRvIHNlZSBob3cgdGhpcyB2YXJpYWJsZSBpcyBpbmZsdWVuY2VkIGJ5IHRoZSBvdGhlcnMuDQpgYGB7ciBwbG90X3ZhcmlhYmxlc30NCmdncGxvdChkYXRhID0gUENBMV92YXIsIGFlcyhQQzEsIFBDMikpICsNCiAgIyBBZGQgdmFyaWFibGUgYXJyb3dzIHdpdGggY29uZGl0aW9uYWwgY29sb3INCiAgZ2VvbV9zZWdtZW50KA0KICAgIGFlcyhjb2xvciA9IGlmZWxzZShWYXJpYWJsZSA9PSAiQWxidW1JRF9SYW5rIiwgImJsYWNrIiwgInJlZCIpKSwNCiAgICB4ZW5kID0gMCwgeWVuZCA9IDAsDQogICAgYXJyb3cgPSBhcnJvdygNCiAgICAgIGxlbmd0aCA9IHVuaXQoMC4wMywgIm5wYyIpLA0KICAgICAgdHlwZSA9ICJjbG9zZWQiLA0KICAgICAgZW5kcyA9ICJmaXJzdCINCiAgICApDQogICkgKw0KICAjIEFkZCB2YXJpYWJsZSBuYW1lcyB3aXRoIGNvbmRpdGlvbmFsIGNvbG9yDQogIGdlb21fdGV4dF9yZXBlbCgNCiAgICBhZXMobGFiZWwgPSBWYXJpYWJsZSwgY29sb3IgPSBpZmVsc2UoVmFyaWFibGUgPT0gIkFsYnVtSURfUmFuayIsICJibGFjayIsICJyZWQiKSksDQogICAgaGp1c3QgPSAxLCBzaXplID0gMywNCiAgICBtaW4uc2VnbWVudC5sZW5ndGggPSBJbmYsDQogICAgbnVkZ2VfeCA9IDAuMDEsIG51ZGdlX3kgPSAwLjA4DQogICkgKw0KICBjb29yZF9maXhlZCgpICsNCiAgbGFicygNCiAgICAjIEFkZCB0aXRsZXMNCiAgICB0aXRsZSA9ICdQbG90IG9mIFBDQSBWYXJpYWJsZXMgVG9wIDEwMCBNZXRhbCBBbGJ1bXMnLA0KICAgIHggPSAnUEMxJywNCiAgICB5ID0gJ1BDMicsDQogICAgY29sb3IgPSAnVmFyaWFibGUnDQogICkgKw0KICBzY2FsZV9jb2xvcl9pZGVudGl0eSgpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANClRoaXMgcGxvdCBvZiB2YXJpYWJsZXMgYWdhaW4gc2hvd3MgdGhhdCB0aGUgYEFsYnVtSURfUmFua2AgaXMgbW9zdGx5IGluZmx1ZW5jZWQgYnkgYFJlbGVhc2VfWWVhcmAsIGJ1dCBhbHNvIHRoYXQgYEFjb3VzdGljYCBhbmQgYExvdWRgIHNlcGFyYXRlIGEgbG90IG9mIHNvbmdzLiBXaXRoIGEgbGFyZ2VyIHBsb3QgaW4gbWluZCwgSSB3YW50ZWQgdG8gcmVtb3ZlIHRoZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgUEMgbnVtYmVycywgYW5kIG1ha2UgdGhlIHBsb3QgbG9vayBtb3JlIHZpc3VhbGx5IGFwcGVhbGluZyBzbyBpdCBjYW4gYmUgc2hvd24gdG9nZXRoZXIgd2l0aCB0aGUgUENBIHBsb3Q6DQpgYGB7ciBwbG90X3ZhcmlhYmxlc19wcmV0dHl9DQpwcmV0dHlfdmFyX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBQQ0ExX3ZhciwgYWVzKFBDMSwgUEMyKSkgKw0KICAjIEFkZCB2YXJpYWJsZSBhcnJvd3Mgd2l0aCBjb25kaXRpb25hbCBjb2xvcg0KICBnZW9tX3NlZ21lbnQoDQogICAgYWVzKGNvbG9yID0gaWZlbHNlKFZhcmlhYmxlID09ICJBbGJ1bUlEX1JhbmsiLCAiYmxhY2siLCAiI2M5MzQzNCIpKSwgIyBCbGFjayBhbmQgcmVkIGFycm93cw0KICAgIHhlbmQgPSAwLCB5ZW5kID0gMCwNCiAgICBhcnJvdyA9IGFycm93KA0KICAgICAgbGVuZ3RoID0gdW5pdCgwLjA1LCAibnBjIiksDQogICAgICB0eXBlID0gImNsb3NlZCIsDQogICAgICBlbmRzID0gImZpcnN0Ig0KICAgICksDQogICAgbGluZXdpZHRoID0gMC45LCAjIFdpZGUgbGluZXMNCiAgKSArDQogICMgQWRkIHZhcmlhYmxlIG5hbWVzDQogIGdlb21fdGV4dF9yZXBlbCgNCiAgICBhZXMobGFiZWwgPSBWYXJpYWJsZSwgY29sb3IgPSBpZmVsc2UoVmFyaWFibGUgPT0gIkFsYnVtSURfUmFuayIsICJibGFjayIsICIjYzkzNDM0IikpLCAjIEJsYWNrIGFuZCByZWQgbmFtZXMNCiAgICBoanVzdCA9IDEsIHNpemUgPSAzLjUsDQogICAgbWluLnNlZ21lbnQubGVuZ3RoID0gSW5mLA0KICAgIG51ZGdlX3ggPSAwLjAxLCBudWRnZV95ID0gMC4wOA0KICApICsNCiAgIyBBZGQgZGFzaGVkIGxpbmUgZm9yIHkgYXhpcw0KICBhbm5vdGF0ZSgNCiAgICBnZW9tID0gInNlZ21lbnQiLCB4ID0gMCwgeGVuZCA9IDAsIHkgPSAtSW5mLCB5ZW5kID0gSW5mLCBjb2wgPSAiZ3JleTYwIiwgbHR5ID0gImRhc2hlZCIsDQogICAgbGluZXdpZHRoID0gMC41DQogICkgKw0KICAjIEFkZCBkYXNoZWQgbGluZSBmb3IgeCBheGlzDQogIGFubm90YXRlKA0KICAgIGdlb20gPSAic2VnbWVudCIsIHggPSBJbmYsIHhlbmQgPSAtSW5mLCB5ID0gMCwgeWVuZCA9IDAsIGNvbCA9ICJncmV5NjAiLCBsdHkgPSAiZGFzaGVkIiwNCiAgICBsaW5ld2lkdGggPSAwLjUNCiAgKSArDQogICMgS2VlcCBmaXhlZCBhc3BlY3QgcmF0aW8NCiAgY29vcmRfZml4ZWQoKSArDQogICMgTWFpbnRhaW4gY29sb3IgaWRlbnRpdHkgYW5kIHJlbW92ZSBsZWdlbmQNCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkoKSArDQogIGd1aWRlcyhjb2xvciA9ICJub25lIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgICMgTm8gYXhpcyBsYWJlbHMNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpDQogICkNCnByZXR0eV92YXJfcGxvdA0KYGBgDQojIFBsb3R0aW5nIHNvbmdzDQpUbyBhY3R1YWxseSBjcmVhdGUgYSBwbG90IG9mIGFsbCBzb25ncyBpbmNsdWRlZCBpbiB0aGUgZmlyc3QgUENBLCBJIHVzZWQgYGdncGxvdGAgYWdhaW4uIE9mIGNvdXJzZSBJIHVzZWQgcmVkIGFuZCBibGFjayBpbiB0aGUgY29sb3IgcGFsZXR0ZSwgdGhpcyBpcyBhIG1ldGFsIGRhdGEgYW5hbHlzaXMgYWZ0ZXIgYWxsIDopLg0KYGBge3IgUENBMV9wbG90fQ0KIyBBZGQgcmFuayBkYXRhIGJhY2sgdG8gUENBIGNhbGN1bGF0ZWQgZGF0YQ0KUENBMV9pbmRpdl9yYW5rPC1QQ0ExX3JhbmslPiUNCiAgYXVnbWVudChQQ0ExX2RhdGEpDQoNCiMgUGxvdCBpbmRpdmlkdWFscw0KZ2dwbG90KA0KICAjIEJhc2VkIG9uIGNhbGN1bGF0ZWQgUENBIGRhdGENCiAgZGF0YT1QQ0ExX2luZGl2X3JhbmssDQogICMgVXNlIFBDQSB2YWx1ZXMgYW5kIGNvbG9yIGJhc2VkIG9uIHJlbGVhc2UgeWVhcg0KICBhZXMoLmZpdHRlZFBDMSwgLmZpdHRlZFBDMixjb2xvcj1SZWxlYXNlX1llYXIpKSsNCiAgZ2VvbV9wb2ludCgpKw0KICAjIEFkZCBsYWJlbHMgYW5kIGNvbG9yIGJhc2VkIG9uIHllYXINCiAgbGFicygNCiAgICB0aXRsZSA9ICdQbG90IG9mIGluZGl2aWR1YWwgc29uZ3MnLA0KICAgIHN1YnRpdGxlID0gJ0NvbG9yIHNob3dzIHllYXIgb2YgYWxidW0gcmVsZWFzZSBvZiBzb25ncycsDQogICAgeD0nUEMxICgyNiUpJywNCiAgICB5PSdQQzIgKDIyJSknLA0KICAgIGNvbG9yPSdSZWxlYXNlX1llYXInDQogICkrDQogICMgR3JhZGllbnQgd2l0aCByZWRzDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAicmVkIikgKw0KICAjIExpZ2h0IHRoZW1lDQogIHRoZW1lX2xpZ2h0KCkNCmBgYA0KVGhlIHBsb3Qgc2hvd3MgdGhhdCBQQzEgaXMgdGhlIHByaW5jaXBhbCBjb21wb25lbnQgdGhhdCBpcyBhYmxlIHRvIGRpc3Rpbmd1aXNoIHRoZSBzb25ncyB0aGUgYmVzdCBiYXNlZCBvbiB0aGUgYWxidW0gcmVsZWFzZSB5ZWFyLg0KDQpOb3csIEkgd2FudGVkIHRvIHRyeSBhbmQgbWFrZSB0aGUgcGxvdCBjb250YWluIG1vcmUgaW5mb3JtYXRpb24gYW5kIGFsc28gbG9vayBhIGJpdCBwcmV0dGllci4uLg0KDQojIE9wdGltaXppbmcgdGhlIHBsb3QNClRoZSBmaXJzdCBiaXQgb2YgaW5mb3JtYXRpb24gSSB0aG91Z2h0IGFib3V0IGFkZGluZyB0byB0aGUgcGxvdCB3YXMgdGhlIHNvbmcgbmFtZXMuIEkgc3RhcnRlZCB3aXRoIHRyeWluZyB0byBhZGQgYWxsIGxhYmVscyB0byB0aGUgcGxvdCB3aXRoIHRoZSBjb2RlIGJlbG93LCBidXQgYXMgd2FzIHRvIGJlIGV4cGVjdGVkLCBpdCBiZWNhbWUgYSBiaWcgbWVzczoNCmBgYHtyIFBDQTFfYWxsbmFtZXN9DQojIENoZWNrIGlmIHNvbmcgbmFtZXMgYXJlIHZhbGlkIGFuZCBoYW5kbGUgc3BlY2lhbCBjaGFyYWN0ZXJzDQpQQ0ExX2luZGl2X3JhbmsgPC0gUENBMV9pbmRpdl9yYW5rICU+JQ0KICAjIENoZWNrIHRoYXQgc29uZyBpcyBhIGNoYXJhY3RlciB2ZWN0b3INCiAgbXV0YXRlKFNvbmcgPSBhcy5jaGFyYWN0ZXIoU29uZykpICU+JQ0KICAjIFJlbW92ZSBub3QgYWNjZXB0ZWQgY2hhcmFjdGVycw0KICBtdXRhdGUoU29uZyA9IGljb252KFNvbmcsICJVVEYtOCIsICJBU0NJSSIsIHN1YiA9ICIiKSkgJT4lDQogIG11dGF0ZShTb25nID0gZ3N1YigiW15bOmFsbnVtOl0gXSIsICIiLCBTb25nKSkNCg0KIyBQbG90IHRoZSBQQ0Egd2l0aCBhbGwgc29uZyBuYW1lIGxhYmVscywgYWxsb3dpbmcgb3ZlcmxhcHMNCmdncGxvdChQQ0ExX2luZGl2X3JhbmssIGFlcyguZml0dGVkUEMxLCAuZml0dGVkUEMyLCBsYWJlbCA9IFNvbmcpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUmVsZWFzZV9ZZWFyKSkgKyAgIyBBZGQgcG9pbnRzIGNvbG9yZWQgYnkgcmVsZWFzZSB5ZWFyDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBTb25nKSwgc2l6ZSA9IDMsIHZqdXN0ID0gLTAuNSwgaGp1c3QgPSAwLjUpICsgICMgQWRkIHNvbmcgbGFiZWxzIGRpcmVjdGx5IChubyBvdmVybGFwIGF2b2lkYW5jZSkNCiAgIyBBZGQgbGFiZWxzIGFuZCBjb2xvciBiYXNlZCBvbiB5ZWFyDQogIGxhYnMoDQogICAgdGl0bGUgPSAnUENBIG9mIFNvbmdzJywNCiAgICBzdWJ0aXRsZSA9ICdDb2xvciBzaG93cyB5ZWFyIG9mIGFsYnVtIHJlbGVhc2UnLA0KICAgIHggPSAnUEMxJywNCiAgICB5ID0gJ1BDMicsDQogICAgY29sb3IgPSAnUmVsZWFzZSBZZWFyJw0KICApICsNCiAgIyBDb2xvciBncmFkaWVudA0KICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gInJlZCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KQmFzZWQgb24gdGhpcyBwbG90LCBJIG5vdGljZWQgdHdvIG1ham9yIHByb2JsZW1zLiBUaGUgZmlyc3Qgb25lIGJlaW5nIHRoYXQgbGFiZWxpbmcgZXZlcnkgc2luZ2xlIGRhdGEgcG9pbnQgbGVhZHMgdG8gb3ZlcmxhcHMgYW5kIGNsdXR0ZXIuIFRoZSBzZWNvbmQgb25lIGJlaW5nIHRoYXQgc29tZSBzb25nIG5hbWVzIGFyZSB1bm5lY2Vzc2FyeSBsb25nIGR1ZSB0byB0aGVtIGJlaW5nIHJlbWFzdGVyZWQgdmVyc2lvbnMuIEkgc3RhcnRlZCB3aXRoIHRyeWluZyB0byBmaXggdGhlIGZpcnN0IHByb2JsZW0uDQoNCiMjIFNlbGVjdGluZyBtb3N0IHBvcHVsYXIgc29uZyBmcm9tIGVhY2ggYWxidW0NClRvIHJlZHVjZSB0aGUgYW1vdW50IG9mIHNvbmdzIHdpdGggYSBsYWJlbCwgSSBkZWNpZGVkIHRvIG1ha2UgYSBuZXcgZGF0YXNldCB0aGF0IGNvbnRhaW5zIG9ubHkgdGhlIG1vc3QgcG9wdWxhciBzb25nIG9mIGVhY2ggYWxidW0gaW4gdGhlIGRhdGFzZXQ6DQpgYGB7ciBwb3B1bGFyX3NvbmdzX29ubHl9DQojIE5ldyBkYXRhc2V0DQpoaWdoZXN0X3BvcHVsYXJpdHlfcGVyX2FsYnVtIDwtIFBDQTFfaW5kaXZfcmFuayAlPiUNCiAgIyBHcm91cCBiYXNlZCBvbiByYW5rDQogIGdyb3VwX2J5KEFsYnVtSURfUmFuaykgJT4lDQogICMgRmlsdGVyIHJvd3Mgd2l0aCBtYXggUG9wdWxhcml0eQ0KICBmaWx0ZXIoUG9wdWxhcml0eSA9PSBtYXgoUG9wdWxhcml0eSkpICU+JQ0KICAjIEhhbmRsZSB0aWVzIGJ5IHNlbGVjdGluZyB0aGUgZmlyc3Qgcm93DQogIHNsaWNlKDEpICU+JSAgDQogIHVuZ3JvdXAoKQ0KYGBgDQojIyBSZW1vdmluZyByZW1hc3RlciBpbmZvIGZyb20gcG9wdWxhciBzb25nIG5hbWVzDQpBZnRlciBtYWtpbmcgYSBzdWJzZXQgb2Ygb25seSB0aGUgbW9zdCBwb3B1bGFyIHNvbmdzLCBJIHdhbnRlZCB0byBzaG9ydGVuIHNvbWUgb2YgdGhlIHNvbmcgbmFtZXMuIEEgbG90IG9mIHRoZSBzb25ncyBhcmUgcmVtYXN0ZXJlZCBhZnRlciB0aGUgaW5pdGlhbCBhbGJ1bSByZWxlYXNlLCB3aGljaCBtZWFucyB0aGF0IHNvbWUgaW5mb3JtYXRpb24gaXMgYWRkZWQgdG8gdGhlIHNvbmcgdGl0bGUuDQpJIGNyZWF0ZWQgYSBgcmVnZXhgIHBhdHRlcm4gdG8gZmlsdGVyIG91dCBhbGwgc29uZ3MgdGhhdCBoYXZlIHNvbWUgdmVyc2lvbiBvZiAiUmVtYXN0ZXIiLCAiUmVtYXN0ZXJlZCIgYW5kIGEgeWVhciBpbiB0aGUgc29uZyB0aXRsZS4NCkFsbCB0ZXh0IHRoYXQgbWF0Y2hlcyB0aGlzIHBhdHRlcm4gaXMgcmVtb3ZlZCBpbiB0aGUgY29kZSBiZWxvdzoNCmBgYHtyIG5vX3JlbWFzdGVyX2NsZWFuaW5nfQ0KIyBDbGVhbiB0aGUgc29uZyBuYW1lcyBjb2x1bW4NCnBvcHVsYXJfbm9fcmVtYXN0ZXIgPC0gaGlnaGVzdF9wb3B1bGFyaXR5X3Blcl9hbGJ1bSAlPiUNCiAgbXV0YXRlKFNvbmcgPSBzdHJfcmVtb3ZlX2FsbChTb25nLCAiKD9pKVxccypcXGIocmVtYXN0ZXIoZWQpPyggXFxkezR9KT98XFxkezR9IHJlbWFzdGVyKGVkKT8pXFxiLiokIikpDQoNCiMgQWRkIGEgZmxhZyBmb3IgcG9wdWxhciBzb25ncyBpbiB0aGUgb3JpZ2luYWwgUENBIGRhdGFzZXQNClBDQTFfaW5kaXZfcmFuayA8LSBQQ0ExX2luZGl2X3JhbmsgJT4lDQogIG11dGF0ZShQb3B1bGFyID0gaWZlbHNlKFNvbmcgJWluJSBwb3B1bGFyX25vX3JlbWFzdGVyJFNvbmcsIFRSVUUsIEZBTFNFKSkNCmBgYA0KVG8gbWFrZSB0aGUgZG93bnN0cmVhbSBwbG90dGluZyBvZiB0aGlzIGRhdGEgZWFzaWVyLCBJIGFkZGVkIGEgZmxhZyB0byB0aGUgb3JpZ2luYWwgUENBIGRhdGEgdG8gaW5kaWNhdGUgaWYgdGhlIHNvbmcgaXMgdGhlIG1vc3QgcG9wdWxhciBvZiBhbiBhbGJ1bS4NCg0KIyMgUGxvdHRpbmcgYWdhaW4NCkxldCdzIHNlZSBpZiByZWR1Y2luZyB0aGUgYW1vdW50IG9mIGxhYmVscyB0byBvbmx5IG9uZSBmb3IgZWFjaCBhbGJ1bSBhbmQgc2hvcnRlbmluZyByZW1hc3RlcmVkIHNvbmcgbmFtZXMgbWFkZSBhIGRpZmZlcmVuY2UgaW4gbWFraW5nIHRoZSBwbG90IGxvb2sgYmV0dGVyOg0KYGBge3IgUENBMV9wb3B1bGFyX25vX3JlbWFzdGVyfQ0KIyBQbG90IHRoZSBQQ0Egd2l0aCBub24tb3ZlcmxhcHBpbmcgbGFiZWxzIGZvciBwb3B1bGFyIHNvbmdzDQpnZ3Bsb3QoUENBMV9pbmRpdl9yYW5rLCBhZXMoLmZpdHRlZFBDMSwgLmZpdHRlZFBDMikpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSZWxlYXNlX1llYXIpKSArICAjIEFkZCBwb2ludHMgY29sb3JlZCBieSByZWxlYXNlIHllYXINCiAgZ2VvbV90ZXh0X3JlcGVsKA0KICAgIGRhdGEgPSBzdWJzZXQoUENBMV9pbmRpdl9yYW5rLCBQb3B1bGFyID09IFRSVUUpLCAgIyBPbmx5IGxhYmVsIHBvcHVsYXIgc29uZ3MNCiAgICBhZXMobGFiZWwgPSBTb25nKSwNCiAgICBzaXplID0gMywgIyBUZXh0IHNpemUNCiAgICBib3gucGFkZGluZyA9IDAuMzUsICAjIFBhZGRpbmcgYXJvdW5kIHRoZSB0ZXh0IGJveA0KICAgIHBvaW50LnBhZGRpbmcgPSAwLjUsICAjIFNwYWNlIGJldHdlZW4gdGhlIGxhYmVsIGFuZCB0aGUgcG9pbnQNCiAgICBtYXgub3ZlcmxhcHMgPSBJbmYsICAjIEFsbG93IGFsbCBsYWJlbHMgdG8gYXR0ZW1wdCB0byBkaXNwbGF5DQogICAgc2VnbWVudC5jb2xvciA9ICdncmV5NTAnLCAgIyBMaW5lIGNvbG9yDQogICAgc2VnbWVudC5zaXplID0gMC41ICAjIExpbmUgdGhpY2tuZXNzDQogICkgKw0KICAjIEFkZCBsYWJlbHMgYW5kIGNvbG9yIGJhc2VkIG9uIHllYXINCiAgbGFicygNCiAgICB0aXRsZSA9ICdQQ0Egb2YgU29uZ3MnLA0KICAgIHN1YnRpdGxlID0gJ0NvbG9yIHNob3dzIHllYXIgb2YgYWxidW0gcmVsZWFzZTsgbGFiZWxzIGZvciBwb3B1bGFyIHNvbmdzJywNCiAgICB4ID0gJ1BDMScsDQogICAgeSA9ICdQQzInLA0KICAgIGNvbG9yID0gJ1JlbGVhc2UgWWVhcicNCiAgKSArDQogICMgQ29sb3JzIGFuZCB0aGVtZSANCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJyZWQiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpXZWxsLCB0aGlzIHN0aWxsIGxvb2tzIHZlcnkgY2hhb3RpYy4uLiBNYXliZSBpdCdzIGJldHRlciB0byBtYW51YWxseSBzZWxlY3Qgc29uZ3MgdGhhdCBoYXZlIHRvIGJlIGxhYmVsbGVkIGluIHRoZSBncmFwaC4gRm9yIHRoaXMsIEkgc2VsZWN0ZWQgbXkgcGVyc29uYWwgZmF2b3JpdGVzIGZyb20gdGhlIG1vc3QgcG9wdWxhciBtZXRhbCBzb25ncy4gDQpgYGB7ciBQQ0FfZmF2b3JpdGVzfQ0KIyBNYW51YWxseSBzcGVjaWZ5IHRoZSBzb25nIG5hbWVzIHRvIGJlIGxhYmVsZWQNCnNlbGVjdGVkX3NvbmdzIDwtIGMoIkNob3AgU3VleSIsIkJyZWFraW5nIHRoZSBMYXciLCJNYXN0ZXIgT2YgUHVwcGV0cyIsIldvdWxkIiwiTm90aGluZyBFbHNlIE1hdHRlcnMiLCJCbGluZCIsIlBlb3BsZSAgU2hpdCIsIlRyYW5zaWx2YW5pYW4gSHVuZ2VyIiwiV2FsayIsIkJhdCBDb3VudHJ5IiwiUmFpbmluZyBCbG9vZCIsIktpbGxpbmcgSW4gVGhlIE5hbWUiKQ0KDQojIE5ldyBkYXRhc2V0IHRvIGluY2x1ZGUgb25seSB0aGUgc2VsZWN0ZWQgc29uZ3MNCnBvcHVsYXJfZmF2b3JpdGVzIDwtIHBvcHVsYXJfbm9fcmVtYXN0ZXIgJT4lDQogIGZpbHRlcihTb25nICVpbiUgc2VsZWN0ZWRfc29uZ3MpDQoNCiMgQWRkIGEgZmxhZyBmb3IgZmF2b3JpdGUgc29uZ3MgaW4gdGhlIG9yaWdpbmFsIFBDQSBkYXRhc2V0DQpQQ0ExX2luZGl2X3JhbmsgPC0gUENBMV9pbmRpdl9yYW5rICU+JQ0KICBtdXRhdGUoRmF2b3JpdGUgPSBpZmVsc2UoU29uZyAlaW4lIHBvcHVsYXJfZmF2b3JpdGVzJFNvbmcsIFRSVUUsIEZBTFNFKSkNCg0KIyBQbG90IHRoZSBQQ0Egd2l0aCByZXBlbGxlZCBsYWJlbHMgZm9yIHBvcHVsYXIgc29uZ3MNCm5lYXRfcGNhIDwtIGdncGxvdChQQ0ExX2luZGl2X3JhbmssIGFlcyguZml0dGVkUEMxLCAuZml0dGVkUEMyKSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJlbGVhc2VfWWVhcikpICsgICMgQWRkIHBvaW50cyBjb2xvcmVkIGJ5IHJlbGVhc2UgeWVhcg0KICBnZW9tX3RleHRfcmVwZWwoDQogICAgZGF0YSA9IHN1YnNldChQQ0ExX2luZGl2X3JhbmssIEZhdm9yaXRlID09IFRSVUUpLCAgIyBPbmx5IGxhYmVsIGZhdm9yaXRlIHNvbmdzDQogICAgYWVzKGxhYmVsID0gU29uZyksDQogICAgc2l6ZSA9IDMsDQogICAgbnVkZ2VfeCA9IC0wLjAxLA0KICAgIG51ZGdlX3kgPSAtMC4wMSwNCiAgICBib3gucGFkZGluZyA9IDAuNCwgICMgUGFkZGluZyBhcm91bmQgdGhlIHRleHQgYm94DQogICAgcG9pbnQucGFkZGluZyA9IDAsICAjIFNwYWNlIGJldHdlZW4gdGhlIGxhYmVsIGFuZCB0aGUgcG9pbnQNCiAgICBtYXgub3ZlcmxhcHMgPSBJbmYsICAjIEFsbG93IGFsbCBsYWJlbHMgdG8gYXR0ZW1wdCB0byBkaXNwbGF5DQogICAgc2VnbWVudC5jb2xvciA9ICdibGFjaycsICAjIExpbmUgY29sb3INCiAgICBzZWdtZW50LnNpemUgPSAwLjYgICMgTGluZSB0aGlja25lc3MNCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAnUENBIG9mIFNvbmdzJywNCiAgICBzdWJ0aXRsZSA9ICdDb2xvciBzaG93cyB5ZWFyIG9mIGFsYnVtIHJlbGVhc2U7IGxhYmVscyBmb3IgZmF2b3JpdGUgc29uZ3MnLA0KICAgIHggPSAnUEMxJywNCiAgICB5ID0gJ1BDMicsDQogICAgY29sb3IgPSAnUmVsZWFzZSBZZWFyJw0KICApICsNCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJyZWQiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KbmVhdF9wY2ENCmBgYA0KIyBDcmVhdGluZyB0aGUgaWRlYWwgcGxvdA0KSSBhbHJlYWR5IHJlYWxseSBsaWtlZCB0aGlzIHZlcnNpb24gb2YgdGhlIHBsb3QsIGJ1dCBJIHdhbnRlZCB0byBtYWtlIGl0IGxvb2sgbW9yZSBzdHlsZWQuIEluIHRoZSBjb2RlIGJlbG93LCBJIHBsYXllZCBhcm91bmQgd2l0aCBkaWZmZXJlbnQgbG9va3MgZm9yIHRoZSBkYXRhcG9pbnRzLCBsYWJlbGxpbmcgbWVjaGFuaXNtcyBhbmQgZm9udHMuIA0KYGBge3IgcHJldHR5X3BjYV9wbG90X3BhcnQxfQ0KcHJldHR5X3BjYV9wbG90MSA8LSBnZ3Bsb3QoUENBMV9pbmRpdl9yYW5rLCBhZXMoLmZpdHRlZFBDMSwgLmZpdHRlZFBDMiwgY29sb3IgPSBSZWxlYXNlX1llYXIpKSArICMgTWFwIGNvbG9yIHRvIGEgdmFyaWFibGUNCiAgZ2VvbV9wb2ludChhbHBoYT0wLjIsc2l6ZSA9IDIpICsNCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJyZWQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LCA3KSkgKyAjIFBsb3Qgc2l6ZSB4DQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC03LjgsIDEwKSkrICMgUGxvdCBzaXplIHkNCiAgIyBMYWJlbHMgdGhhdCBjYW4gbm90IG92ZXJsYXAgYW5kIGFyZSBub3Qgb24gdGhlIGRhdGFwb2ludA0KICBnZW9tX3RleHRfcmVwZWwoIA0KICAgIGRhdGEgPSBzdWJzZXQoUENBMV9pbmRpdl9yYW5rLCBGYXZvcml0ZSA9PSBUUlVFKSwgIyBPbmx5IGxhYmVsIGZhdm9yaXRlIHNvbmdzDQogICAgYWVzKGxhYmVsID0gcGFzdGUoU29uZywgIlxuIiwgQXJ0aXN0LCBzZXAgPSAiIiksIGZvbnRmYWNlID0gImJvbGQuaXRhbGljIiksICMgU29uZyBhbmQgYXJ0aXN0IGxhYmVsDQogICAgc2l6ZSA9IDIuOCwgICMgVGV4dCBzaXplDQogICAgYm94LnBhZGRpbmcgPSAwLjYsICAjIEluY3JlYXNlIHBhZGRpbmcgYXJvdW5kIHRleHQgYm94ZXMNCiAgICBwb2ludC5wYWRkaW5nID0gMC4xLCAgIyBQYWRkaW5nIGJldHdlZW4gcG9pbnRzIGFuZCBsYWJlbHMNCiAgICBmb3JjZSA9IDIwLCAgIyBJbmNyZWFzZSByZXB1bHNpb24gYmV0d2VlbiBsYWJlbHMNCiAgICBmb3JjZV9wdWxsID0gMC4xLCAgIyBTbGlnaHQgcHVsbCB0byB0aGUgZGF0YSBwb2ludHMsIGVuc3VyaW5nIGFsaWdubWVudA0KICAgIG1pbi5zZWdtZW50Lmxlbmd0aCA9IDAuNSwgICMgQXZvaWQgb3Zlcmx5IHNob3J0IHNlZ21lbnQgbGluZXMNCiAgICBtYXgub3ZlcmxhcHMgPSBJbmYsICAjIEVuc3VyZSBhbGwgbGFiZWxzIGFyZSBzaG93bg0KICAgIHNlZ21lbnQuY29sb3IgPSAnYmxhY2snLCAgIyBMaW5lIGNvbG9yDQogICAgc2VnbWVudC5zaXplID0gMC4zICAjIFRoaW5uZXIgc2VnbWVudCBsaW5lcw0KICApDQojIFZpZXcNCnByZXR0eV9wY2FfcGxvdDENCmBgYA0KSSBsaWtlZCB0aGUgc3R5bGluZyBvZiB0aGUgcG9pbnRzIGFuZCBsYWJlbHMgaGVyZSwgYnV0IEkgd2FudGVkIHRoZSBheGVzIHRvIHJ1biB0aHJvdWdoIHRoZSBtaWRkbGUgb2YgdGhlIGRhdGEgaW5zdGVhZCBvZiBiZWluZyBvbiB0aGUgc2lkZXMuIEkgZGlkIHRoaXMgYnkgY3JlYXRpbmcgc29tZSBhcnJvdyBzdHlsZXMgYW5kIGFkZGluZyB0aGVtIG1hbnVhbGx5Og0KYGBge3IgcHJldHR5X3BjYV9wbG90X3BhcnQyfQ0KYXJyb3dfc3R5bGUgPC0gYXJyb3coDQogIGFuZ2xlID0gMjAsIGVuZHMgPSAiZmlyc3QiLCB0eXBlID0gImNsb3NlZCIsIGxlbmd0aCA9IGdyaWQ6OnVuaXQoNCwgInB0IikNCikNCg0KYXJyb3dfc3R5bGVfaW5kIDwtIGFycm93KA0KICBhbmdsZSA9IDQ1LCANCiAgbGVuZ3RoID0gZ3JpZDo6dW5pdCg4LCAicHQiKQ0KKQ0KDQpwcmV0dHlfcGNhX3Bsb3QyIDwtIHByZXR0eV9wY2FfcGxvdDEgKw0KICAjIHgtYXhpcyBsaW5lDQogIGFubm90YXRlKA0KICAgIGdlb20gPSAic2VnbWVudCIsIHggPSAtNSwgeGVuZCA9IDYsIHkgPSAwLCB5ZW5kID0gMCwNCiAgICBsdHkgPSAiZGFzaGVkIiwNCiAgICBjb2wgPSAiZ3JleTYwIiwNCiAgICBzaXplID0gMC41DQogICkgKw0KICAjIHgtYXhpcyBhcnJvdw0KICBhbm5vdGF0ZSgNCiAgICBnZW9tID0gInNlZ21lbnQiLCB4ID0gNS45LCB4ZW5kID0gNiwgeSA9IDAsIHllbmQgPSAwLA0KICAgIGNvbCA9ICJncmV5NjAiLA0KICAgIHNpemUgPSAwLjUsIGFycm93ID0gYXJyb3dfc3R5bGVfaW5kLCBsaW5lZW5kID0gJ3JvdW5kJywgbGluZWpvaW4gPSAncm91bmQnDQogICkgKw0KICAjIHgtYXhpcyBsYWJlbA0KICBhbm5vdGF0ZSgNCiAgICBnZW9tID0gInRleHQiLCB4ID0gNC43LCB5ID0gMC4yNSwgbGFiZWwgPSAiUHJpbmNpcGFsIENvbXBvbmVudCAxICgyNiUpIiwNCiAgICBjb2wgPSAiZGltZ3JleSIsIHNpemUgPSAzLCBmYW1pbHkgPSAic2FucyIsIGZvbnRmYWNlID0gIml0YWxpYyINCiAgKSArDQogICMgeS1heGlzIGxhYmVsDQogIGFubm90YXRlKA0KICAgIGdlb20gPSAidGV4dCIsIHggPSAtMC4xLCB5ID0gLTcuNywgbGFiZWwgPSAiUHJpbmNpcGFsIENvbXBvbmVudCAyICgyMiUpIiwNCiAgICBjb2wgPSAiZGltZ3JleSIsIHNpemUgPSAzLCBmYW1pbHkgPSAic2FucyIsIGFuZ2xlID0gOTAsIHZqdXN0ID0gMCwgaGp1c3QgPSAwLCBmb250ZmFjZSA9ICJpdGFsaWMiDQogICkgKw0KICAjIHktYXhpcw0KICBhbm5vdGF0ZSgNCiAgICBnZW9tID0gInNlZ21lbnQiLCB4ID0gMCwgeGVuZCA9IDAsIHkgPSAtNy44LCB5ZW5kID0gNSwgY29sID0gImdyZXk2MCIsIGx0eSA9ICJkYXNoZWQiLA0KICAgIHNpemUgPSAwLjUNCiAgKSArDQogICMgeS1heGlzIGFycm93DQogIGFubm90YXRlKA0KICAgIGdlb20gPSAic2VnbWVudCIsIHggPSAwLCB4ZW5kID0gMCwgeSA9IDQuOSwgeWVuZCA9IDUsIGNvbCA9ICJncmV5NjAiLA0KICAgIHNpemUgPSAwLjUsIGFycm93ID0gYXJyb3dfc3R5bGVfaW5kLCBsaW5lZW5kID0gJ3JvdW5kJywgbGluZWpvaW4gPSAncm91bmQnDQogICkNCnByZXR0eV9wY2FfcGxvdDINCg0KYGBgDQpOb3csIHRoZXJlIGFyZSB0b28gbWFueSBheGVzIGFuZCB0aGUgYmFja2dyb3VuZCBkb2VzIG5vdCBmaXQgdGhlIHN0eWxlIGFueW1vcmUuIEkgZml4ZWQgaXQgbGlrZSB0aGlzOiANCmBgYHtyIHByZXR0eV9wY2FfcGxvdF9wYXJ0M30NCnByZXR0eV9wY2FfcGxvdDMgPC0gcHJldHR5X3BjYV9wbG90MiArDQogICMgU2V0IG1pbmltYWwgdGhlbWUNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwgIyBObyBncmlkDQogICAgIyBObyBheGlzIGxhYmVscw0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksDQogICkNCnByZXR0eV9wY2FfcGxvdDMNCmBgYA0KVGhpcyBwbG90IG5vdyByZWFsbHkgbWlzc2VzIHNvbWUgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiwgc3VjaCBhcyB3aGF0IHR5cGUgb2YgZGF0YSB3ZSBhcmUgbG9va2luZyBhdCwgd2hhdCBraW5kIG9mIGFuYWx5c2lzIHdhcyBwZXJmb3JtZWQgYW5kIHRoZSBkYXRhIHNvdXJjZS4gSSBhbHNvIGluY29ycG9yYXRlZCB0aGUgbGVnZW5kIGludG8gdGhlIHN1YnRpdGxlLg0KYGBge3IgcHJldHR5X3BjYV9wbG90X3BhcnQ0fQ0KIyBDcmVhdGUgdGl0bGUgb2JqZWN0DQptYWludGl0bGU8LWNiaW5kLmRhdGEuZnJhbWUoDQogICMgUG9zaXRpb24gb24gbGVmdCB0b3ANCiAgeCA9IC01LCB5ID0gOS41LA0KICAjIEdsdWUgZm9yIEhUTUwgc3R5bGluZw0KICBsYWJlbCA9IGdsdWUoIjxzcGFuIHN0eWxlPSdjb2xvcjpkYXJrcmVkJz5QQ0EgUm9sbGluZyBTdG9uZSB0b3AgMTAwIG1ldGFsIGFsYnVtcyBvZiBhbGwgdGltZTwvc3Bhbj4iKQ0KKQ0KDQojIFN1YnRpdGxlIG9iamVjdA0Kc3VidGl0bGUgPC0gY2JpbmQuZGF0YS5mcmFtZSgNCiAgIyBQb3NpdGlvbiBiZWxvdyB0aXRsZQ0KICB4ID0gLTUsIHkgPSA4LjUsDQogICMgR2x1ZSBmb3IgSFRNTCBzdHlsaW5nLCBpbmNsdWRlIGxlZ2VuZCBjb2xvcnMNCiAgbGFiZWwgPSBnbHVlKCI8c3BhbiBzdHlsZT0nY29sb3I6IzJiMmEzMCc+UHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcyBvZiBtZXRhbCBzb25ncycgZmVhdHVyZXMgZnJvbSB0aGU8YnI+Um9sbGluZyBTdG9uZSB0b3AgMTAwIE1ldGFsIEFsYnVtcyBmcm9tIDwvc3Bhbj48YiBzdHlsZT0nY29sb3I6YmxhY2snPiAxOTcwIDwvYj48c3BhbiBzdHlsZT0nY29sb3I6IzJiMmEzMCc+dG88L3NwYW4+PGIgc3R5bGU9J2NvbG9yOnJlZCc+IDIwMTMgPC9iPjxzcGFuIHN0eWxlPSdjb2xvcjojMmIyYTMwJz4uPGJyPkVhY2ggZG90IHN0YW5kcyBmb3IgYSBzb25nLCB3aXRoIHRpdGxlIGFuZCBhcnRpc3QgZm9yIHNvbWUgZmF2b3JpdGUgdHJhY2tzLjwvc3Bhbj4gIikNCikNCg0KcHJldHR5X3BjYV9wbG90NCA8LSBwcmV0dHlfcGNhX3Bsb3QzICsNCiAgYW5ub3RhdGUoDQogICAgZ2VvbSA9ICJ0ZXh0IiwgeCA9IDYsIHkgPSAtNy41LCBoanVzdCA9IDEsIGNvbG9yID0gImRpbWdyZXkiLA0KICAgIGxhYmVsID0gIkRhdGE6IGRhdGEud29ybGQiLA0KICAgIHNpemUgPSAyLCBmYW1pbHkgPSAiY2FiaW4iLCBsaW5laGVpZ2h0ID0gMC40DQogICkgKw0KICBnZW9tX3JpY2h0ZXh0KA0KICAgIGRhdGEgPSBtYWludGl0bGUsDQogICAgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSBsYWJlbCksDQogICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwgbGluZWhlaWdodCA9IDAuNSwNCiAgICBhbHBoYSA9IDEsIHNpemUgPSA3LCBmYW1pbHkgPSAnY2FiaW4nLCBoanVzdCA9IDAsIHZqdXN0ID0gMSwNCiAgICBmaWxsID0gTkEsIGxhYmVsLmNvbG9yID0gTkEsIA0KICAgIGxhYmVsLnBhZGRpbmcgPSBncmlkOjp1bml0KHJlcCgwLCA0KSwgInB0IikNCiAgKSArDQogIGdlb21fcmljaHRleHQoDQogICAgZGF0YSA9IHN1YnRpdGxlLA0KICAgIGFlcyh4ID0geCwgeSA9IHksIGxhYmVsID0gbGFiZWwpLA0KICAgIGluaGVyaXQuYWVzID0gRkFMU0UsIGxpbmVoZWlnaHQgPSAwLjUsDQogICAgYWxwaGEgPSAxLCBzaXplID0gNSwgZmFtaWx5ID0gJ2NhYmluJywgaGp1c3QgPSAwLCB2anVzdCA9IDEsDQogICAgZmlsbCA9IE5BLCBsYWJlbC5jb2xvciA9IE5BLCANCiAgICBsYWJlbC5wYWRkaW5nID0gZ3JpZDo6dW5pdChyZXAoMCwgNCksICJwdCIpDQogICkgKw0KICAjIFJlbW92ZSBvcmlnaW5hbCBsZWdlbmQNCiAgdGhlbWUoDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiDQogICkNCnByZXR0eV9wY2FfcGxvdDQNCmBgYA0KVGhpcyBsb29rcyBnb29kISBCdXQsIEkgaGF2ZSBhbHNvIGNyZWF0ZWQgYSBwbG90IG9mIHZhcmlhYmxlcyB0aGF0IEkgd2FudCB0byBpbmNsdWRlIGluIHRoaXMgZmlndXJlLiBJIHVzZWQgYHBhdGNod29ya2AgdG8gY29tYmluZSB0aGVzZSB0d28gcGxvdHMgaW50byBvbmUuDQpgYGB7ciBjb21iaW5lZF9wbG90c19wYXJ0MX0NCiMgTWFrZSBwbG90IHdpdGggcGF0Y2h3b3JrDQpsYXlvdXQgPSBjKA0KICBhcmVhKHQgPSAwLCBsID0gMCwgYiA9IDEwLCByID0gMTUpLCAjIExhcmdlIGFyZWENCiAgYXJlYSh0ID0gMCwgbCA9IDYsIGIgPSA1LCByID0gMTcpICMgU21hbGxlciBhcmVhIGluIHJpZ2h0IGNvcm5lcg0KKSAgDQpwcmV0dHlfcGNhX3Bsb3Q0K3ByZXR0eV92YXJfcGxvdCtwbG90X2xheW91dChkZXNpZ249bGF5b3V0KQ0KYGBgDQpPa2F5LCBvbmUgZmluYWwgdG91Y2ghIEkgd2FudCB0byBoZWxwIHRoZSB2aWV3ZXIgdW5kZXJzdGFuZCB0aGUgcGxvdCBvZiB2YXJpYWJsZXMgYmV0dGVyLCBzbyBJIHdhbnQgdG8gYWRkIGEgZGVzY3JpcHRpb24gb2YgdGhlIHZhcmlhYmxlIHBsb3QgdG8gdGhlIGZpZ3VyZToNCmBgYHtyIGNvbWJpbmVkX3Bsb3RzX3BhcnQyfQ0KcHJldHR5X3BjYV9wbG90NSA8LSBwcmV0dHlfcGNhX3Bsb3Q0ICsNCiAgIyBBZGQgbm90ZSBmb3IgdmFyaWFibGUgcGxvdA0KICBhbm5vdGF0ZSgNCiAgZ2VvbSA9ICJ0ZXh0IiwgeCA9IDMuMiwgeSA9IDMuMywgaGp1c3QgPSAwLjUsIGxhYmVsID0gIkFsYnVtIHJhbmtpbmcgaXNcbiBoZWF2aWx5IGluZmx1ZW5jZWRcbiBieSByZWxlYXNlIHllYXIiLA0KICBzaXplID0gMy44LCBmYW1pbHkgPSAiY2FiaW4iLCBsaW5laGVpZ2h0ID0gMQ0KICApDQpwcmV0dHlfcGNhX3Bsb3Q1K3ByZXR0eV92YXJfcGxvdCtwbG90X2xheW91dChkZXNpZ249bGF5b3V0KQ0KYGBgDQpVbmZvcnR1bmF0ZWx5LCBzb21lIG9mIHRoZSBsYWJlbCBwb3NpdGlvbnMga2VlcCBjaGFuZ2luZyBkdWUgdG8gdGhlIHVzZSBvZiBgcGF0Y2h3b3JrYCwgYnV0IHRoaXMgaXMgdGhlIGJlc3QgSSBjb3VsZCBhY2hpZXZlIHdpdGggbXkgc2tpbGxzLiANCg0KVGhpcyBwbG90IHNob3dzIHRoYXQgdGhlIHJlbGVhc2UgeWVhciBvZiB0aGUgYWxidW0gb2YgdGhlIHNvbmdzIGNvcnJlbGF0ZXMgdGhlIG1vc3Qgd2l0aCB0aGUgcmFuayBvZiB0aGUgYWxidW1zLCB3aGljaCBzaG93cyB0aGF0IFJvbGxpbmcgU3RvbmUgcmFua2VkIG9sZGVyIG1ldGFsIGFsYnVtcyBoaWdoZXIgdGhhbiB0aGUgbmV3ZXIgbWV0YWwgYWxidW1zLiBJdCBhbHNvIHNob3dzIHRoYXQgbXkgcGVyc29uYWwgdGFzdGUgZGlmZmVycyBsZWFucyB0b3dhcmRzIHRoZSBsZWZ0IGFuZCBkYXJrZXIgc2lkZSBvZiB0aGUgbWFpbiBjbG91ZCBvZiBzb25ncywgd2hpY2ggbWVhbnMgdGhhdCBJIHByZWZlciBvbGRlciBzb25ncyB0b28gbmV3IG9uZXMuIA0KDQpUaGlzIGRvY3VtZW50IHdpbGwgYmUgaW1wcm92ZWQgaW4gdGhlIGZ1dHVyZSENCg==