The main benefit of studying community assembly, and factors that
impact it, is to further understand the connection of community
diversity to ecosystem functionality, which is crucial in upkeeping
ecosystems. With spatial distance shown to be a significant factor in
community assembly processes, it is sensible to explore the waterbodies
of the Lunz study site, which consists of various environments with
different conditions, and includes three springs, seven creeks, four
groundwater wells, a pond, a hyporheic spring, and three lakes. The
connectivity is presumed to be hindered at the middle point of the
catchment area, the Middle Lake.
Package loading
library(FEAST) # for source tracking
## Warning: replacing previous import 'dplyr::combine' by 'gridExtra::combine'
## when loading 'FEAST'
library(tidyverse)
library(vegan)
library(FSA) # for dunn post-hoc test
library(caret)
library(broom)
library(patchwork) # for combining plots into 1
library(ggfortify)
library(pairwiseAdonis) # for permanova post-hoc
From every sample, DNA was extracted and used for 16S rRNA gene
amplicon sequencing. Amplicon sequencing and bioinformatic processing of
the raw sequence data for the inference of amplicon sequence variants
(ASV) using DADA2 was done, as well as other processing of organelles
and mitochondria.
Load data
# load metadata
metadata <- read.csv("~/faks/Ecology and Ecosystems/MEC-8 (Specific research project)/data/metadata_Lunz_revised.csv",
row.names = 1)
# load asv table
asv_table <- read.csv("~/faks/Ecology and Ecosystems/MEC-8 (Specific research project)/data/asv_table.csv", row.names=1)
# identifier need to be identical between asv_table and metadata
identical(rownames(metadata), colnames(asv_table))
# if there is some that are different use setdiff(rownames(metadata), colnames(asv_table)) to see which
# data on sources/sinks
feast_metadata <- read.csv("~/faks/Ecology and Ecosystems/MEC-8 (Specific research project)/data/feast_metadata.csv", row.names=1)
# identifiers for sources have to be unique - source 1 needs to be Source1_1, Source1_2, ... )
# SampleID column need to be rownames
FEAST
FEAST - the fast expectation-maximization was used, as a more
computational efficient and shorter alternative to SourceTracker.
Prepare the data for FEAST.
# classes of datasets
# feast_metadata should be a data.frame
class(feast_metadata)
#asv should be matrix and each column an ineger in order to perform feast
feast_asv <- as.matrix(asv_table) # matrix as a whole
for(i in 1:ncol(feast_asv)){ # each column as integer
feast_asv[, i] <- as.integer(feast_asv[, i])
}
# whole table should be a matrix
class(feast_asv)
# individual column should be integer
class(feast_asv[, 1])
# final step - form needs to be as with vegan (sites rows, species columns)
feast_asv <- t(feast_asv)
feast_asv[1:10, 1:5]
#to remove from environment
rm(i)
Perform FEAST. It exports the results and later on needs to be
imported again.
The metadata table has three columns (i.e., ‘Env’, ‘SourceSink’,
‘id’). The first column is a description of the sampled environment
(e.g., sample names), the second column indicates if this sample is a
source or a sink (can take the value ‘Source’ or ‘Sink’). The third
column is the Sink-Source id.
When using multiple sinks, only the rows with ‘SourceSink’ = Sink
need an id (between 1 - number of sinks in the data), the sources’ ids
are blank.
feast_output <- FEAST(C = feast_asv, # transposed asv_table
metadata = feast_metadata, # sink or source information
different_sources_flag = 0, # 0 if sources are not assigned to different sinks
EM_iterations = 1000, # number of iterations
dir_path = "C:/Users/Angela Cukusic/Documents/faks/Ecology and Ecosystems/MEC-8 (Specific research project)/Results",
outfile = "feast_results") # prefix for saving output file
# COVERAGE should be included in the command if we want to indicate the rarefaction depth
#we got an output, import it now
feast_table <- read.table("C:/Users/Angela Cukusic/Documents/faks/Ecology and Ecosystems/MEC-8 (Specific research project)/Results/feast_results_source_contributions_matrix.txt",
sep = "\t", row.names = 1)
Raw contribution to
plottable data
To get an overview of the total contribution of each source
(i.e. groups of samples) to the different sink we have to clean it.
# feast_output is of class "list"
# we want to make it a matrix
# 1. make a new vector with source types (and it is "character")
sources <- paste("source", c(1:8), sep = "")
# 2. make empty matrix with nrow = number of SINKS (5),
# and ncol = number of possible sources (20+ samples are designated to 1-8 sources)
source_contributions <- matrix(NA, # empty
nrow = nrow(feast_table), # 5 sinks
ncol = length(sources)) # n sources
# 3. fill matrix
for(i in 1:length(sources)){ # for each source add contribution
source_contributions[, i] <- rowSums(feast_table[, # sum up contributions for all 5 rows
grepl(sources[i], colnames(feast_table))])
# of only the columns which have sourceX in name
}
# 4. we added contributions assigned to each of 8 sources, now add from unknown sources
source_contributions <- cbind(source_contributions, feast_table$Unknown)
# 5. check if all contributuons for individual sink amount to 1
rowSums(source_contributions)
# 6. convert to data frame and bring back rownames and colnames
source_contributions <- as.data.frame(source_contributions)
colnames(source_contributions) <- c(sources, "unknown") # col
source_contributions <- source_contributions %>% # row
mutate(sample_id = rownames(feast_table), .before = 1)
# final clean up of environment
rm( sources, i)
Plot source
contribution
source_contributions %>%
pivot_longer(cols = -sample_id, names_to = "sources", values_to = "contributions") %>%
mutate(sources = as.factor(sources)) %>%
# find relative abundances for each date in each water kind (well/pump/surf)
group_by(sample_id) %>%
mutate(rel_cont = contributions / sum(contributions) * 100) %>%
ungroup() %>%
# plotting
ggplot(aes(x = sample_id, y = rel_cont, fill = sources)) +
geom_bar(stat = "identity") +
# labelling
geom_text(aes(label =
# label if % is big enough
ifelse(rel_cont > 2,
# if yes then paste, if no then empty ""
paste0(round(rel_cont, 4) , "%"), "" ) ),
# how to position it
position = position_stack(vjust = 0.5), size = 4) +
# theme
theme(legend.position = "none",
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.title.y = element_blank()) +
theme_classic() +
scale_fill_brewer(palette = "Set1") +
labs(x= "Sinks", y="Relative contributions %", fill = "Sources") +
scale_x_discrete(labels = c("Untersee \n(31m)",
"Untersee \n(5m)",
"Untersee - \nnear OSB inflow",
"Untersee - \nat OSB \ninflow",
"Sediment: \nUntersee - \nat OSB \ninflow"))

From five sink samples identified in this study, four were water
samples, and one a sediment sample. Each sink had a substantial portion
of microbes of unknown origin.
Additional to that, another visible trend is water samples being
traced back to Source 1 (surface waters), with non-existent or minimal
portion of Source 2 related microbes (surface waters’ sediment and
biofilm samples, see Fig.2.).
The sediment sink, on the other hand, showed no influence of Source 1
on its composition, but had a high Source 2 origin. Water sinks
contained more ASVs not found in any of the sources than the sediment
sink.
feast_table %>%
rownames_to_column("sample_id") %>%
# find the two sinks in question
filter(sample_id %in% c("OSB_in_LUS_inflow_LUS_at_OSB_inflow",
"OSB_in_LUS_sed_LUS_sediment")) %>%
# find the individual samples from source 6
select( "sample_id", contains("source6")) %>%
# remove the last part of names, which says "source6"
rename_all(~str_remove(., ".{10}$")) %>%
pivot_longer(cols = -sample_id, names_to = "sources", values_to = "contributions") %>%
mutate(sources = as.factor(sources)) %>%
# find relative abundances for each date in each water kind (well/pump/surf)
group_by(sample_id) %>%
mutate(rel_cont = contributions / sum(contributions) * 100) %>%
ungroup() %>%
# plotting
ggplot(aes(x = sample_id, y = rel_cont, fill = sources)) +
geom_bar(stat = "identity", color = "black") +
# labelling
geom_text(aes(label =
# label if % is big enough
ifelse(rel_cont > 2,
# if yes then paste, if no then empty ""
paste0(round(rel_cont, 4) , "%"), "" ) ),
# how to position it
position = position_stack(vjust = 0.5), size = 4) +
# theme
theme(legend.position = "none",
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.title.y = element_blank()) +
theme_classic() +
labs(x= "Sinks", y="Relative contributions %", fill = "Sources") +
scale_x_discrete(labels = c("Untersee - \nat OSB \ninflow",
"Sediment: \nUntersee - \nat OSB \ninflow")) +
scale_fill_manual(values = c( "#006400", "#FFD700", "lightblue", "#FFD700",
"lightblue", "#006400", "lightblue" ))

Even though the two sinks at the inflow both had ~10% of Source 6
microbes (which was two locations - both sediment and water), it seems
that more detailed look gives more insight that sample type is a better
predictor of contribution than location is.
Result: water sink was more influenced by water samples communities,
while sediment sink contained almost exclusively microbes from spring
sediments and spring biofilms.
Sample type
distribution
metadata_type <- metadata %>%
rownames_to_column("sources") %>%
select("sources", "type_III") %>%
mutate(type_III = case_when(
# assign categories
type_III %in% c("Creek", "Hyporheic",
"Pond", "Lake", "Inflow") ~ "Surface",
TRUE ~ type_III))
feast_table %>%
rownames_to_column("sink_id") %>%
# rename the columns so that they can be connected to the metadata (type info)
rename_all(~str_remove(., ".{10}$")) %>%
pivot_longer(cols = - sink_id, names_to = "sources", values_to = "contributions") %>%
# filter out contributions from unknow sources
filter(sources != "Unknown") %>%
# join with metadata
left_join(., metadata_type, by = "sources") %>%
filter(type_III != "NA") %>%
filter( contributions < 0.05) %>%
# plot
ggplot(aes(x= type_III, y= contributions)) +
geom_boxplot(aes(fill = sink_id) ) +
theme_linedraw() +
scale_fill_manual(labels=c("Untersee (31m)",
"Untersee (5m)",
"Untersee (near inflow)",
"Untersee (at inflow)",
"Sediment (at inflow)"),
values=c("#acc7d9", "#8bb0ca","#5180a2","#3e647d","#d8b365")) +
theme(legend.position=c(0.3,0.8),
legend.title = element_blank(),
legend.text = element_text(size = 14),
legend.background = element_rect(),
legend.box.background = element_rect(color = "gray")) +
labs(y = "Contributions", x= "Sample type") +
scale_x_discrete(labels = c("Biofilm", "Ground water", "Sediment",
"Soil", "Spring water", "Surface water") )

Surface waters contributed to all water sinks, but their effect on
the sediment of the sink was minimal. Samples that did contribute to
sediment sink are biofilm, sediment and soil source samples. Additional
to contributing to the sediment sink, biofilm samples also had an impact
on the community at the inflow of the Lower Lake. Springwater samples
were the biggest contributor to the inflow, and had an impact on the
microbial assembly of the Lower Lake at its 31-meter depth.
Spatial
distribution
metadata_rank <- metadata %>%
rownames_to_column("sources") %>%
select("sources", "rank") %>%
filter(rank != "sink")
feast_table %>%
rownames_to_column("sink_id") %>%
# rename the columns so that they can be connected to the metadata (rank info)
rename_all(~str_remove(., ".{10}$")) %>%
pivot_longer(cols = - sink_id, names_to = "sources", values_to = "contributions") %>%
# filter out contributions from unknow sources
filter(sources != "Unknown") %>%
# join with metadata
left_join(., metadata_rank, by = "sources") %>%
filter(rank != "NA") %>%
# plot
ggplot(aes(x= rank, y= contributions)) +
geom_boxplot( fill = "violet") +
facet_wrap(~sink_id, scales = "free_y", labeller =
as_labeller( c("LUS_dp_31m_LUS_31m" = "Untersee (31m)",
"LUS_dp_5m_LUS_5m" = "Untersee (5m)",
"LUS_in_OSB_LUS_near_OSB_inflow" = "Untersee (near inflow)",
"OSB_in_LUS_inflow_LUS_at_OSB_inflow" = "Untersee (at inflow)",
"OSB_in_LUS_sed_LUS_sediment" = "Sediment (at inflow)" ))) +
theme_linedraw() +
labs(y = "Contributions", x= "Ranked by spatial distance ")

We hypothesized that a substantial effect of passive dispersal of
microorganisms on the composition of microbial communities in the lake
sinks should result in significantly declining contributions of sources
with increasing spatial distance to the main lake (i.e. distance ranks
since data on exact spatial distances were not available).
Tackling this hypothesis, we did not find a significant correlation
between spatial distance and sink contribution. None of the sinks
followed the presumed trend of rank 1 having the highest sink
contribution and rank 8 the lowest, nor was there a difference between
the ranks before the connectivity barrier and after the barrier. The
rank 6 is upstream of the Middle lake, which is the presumed
barrier.
Alpha diversity
shannondiv <- vegan::diversity(t(asv_table))
# recalculating it as the effective number of species to be more comparable across studies.
ens <- exp(shannondiv) %>% as.data.frame() %>% rownames_to_column("sample_id") %>%
rename("diversity" = ".")
diversity_data <- specnumber(t(asv_table)) %>% as.data.frame() %>% rownames_to_column("sample_id") %>%
rename("richness" = ".") %>% inner_join(., ens, by ="sample_id" )
# we will plot diversity by source so make clean categorization here
feast_metadata %>%
# remove last two strings
mutate(Env = str_remove(Env, ".{2}$")) %>%
# where SourceSink column is a source keep the value from the Env column
mutate(Source_category = case_when(SourceSink == "Source" ~ Env,
# otherwise keep the value from SourceSink column
TRUE ~ SourceSink) ) %>%
# some trouble with source 3
mutate(Source_category = case_when(Source_category %in% c("source3", "source3_") ~ "source3",
TRUE ~Source_category)) %>%
rownames_to_column("sample_id") %>%
select("sample_id", "Source_category") %>%
mutate(Source_category = as.factor(Source_category)) %>%
# we now have clean category and can connect it to the diversity data
inner_join(., diversity_data, by = "sample_id") %>%
select(-sample_id) %>%
#pivot longer so we can facet
pivot_longer(cols = -Source_category, names_to = "measure", values_to = "values") %>%
# plot
ggplot( aes(x = Source_category, y = values)) +
#stat_boxplot(geom ='errorbar') +
geom_boxplot(fill = "violet") +
theme_linedraw()+
coord_flip() +
facet_wrap(~measure, scales = "free", labeller =
as_labeller( c("diversity" = "Shannon's diversity index",
"richness" = "Richness") ) )+
theme(legend.position = "none",
axis.title=element_text(size=14,face="bold"),
axis.text.y = element_text(size=10,face="bold"),
strip.text = element_text(size = 14)) +
labs( x = "Source category",
y = NULL) +
scale_x_discrete(labels = c("Sink", "Source 1", "Source 2", "Source 3", "Source 4",
"Source 5", "Source 6", "Source 7", "Source 8"))

Richness of the sinks was the lowest compared to source richness.
Sources 7, and 8, which have a direct inflow to the sinks, had the
highest richness. Source 1, which makes a big contribution to sink
communities had higher richness than the sinks it contributed to.
Sink evenness was lower than evenness of sources. Species
distribution of the sink leans towards a few very dominant ASVs and many
rare ones, indicating possible harder environmental conditions or bigger
competitiveness in sink. Source 3, with its soil samples, had high
evenness. Source 4 (groundwater) had slightly lower evenness and
richness in comparison to other sources.
Test it:
# 1. the same data manipulation as above
feast_metadata %>%
mutate(Env = str_remove(Env, ".{2}$")) %>%
mutate(Source_category = case_when(SourceSink == "Source" ~ Env,
TRUE ~ SourceSink) ) %>%
mutate(Source_category = case_when(Source_category %in% c("source3", "source3_") ~ "source3",
TRUE ~Source_category)) %>%
rownames_to_column("sample_id") %>%
select("sample_id", "Source_category") %>%
mutate(Source_category = as.factor(Source_category)) %>%
inner_join(., diversity_data, by = "sample_id") %>%
select(-sample_id) -> data_for_alpha
# 2. perform ANOVA/ kruskal-wallis
# 1. assumption of ANOVA: Normal distribution:
# Each population to be compared should be normally distributed
# (NOT THE ENTIRE DATASET).
shapiro.test ( data_for_alpha[which(data_for_alpha$Source_category == "source1"), "diversity"] ) # NOT ND
shapiro.test ( data_for_alpha[which(data_for_alpha$Source_category == "source2"), "diversity"] ) # ND
shapiro.test ( data_for_alpha[which(data_for_alpha$Source_category == "source3"), "diversity"] ) # ND
shapiro.test ( data_for_alpha[which(data_for_alpha$Source_category == "source4"), "diversity"] ) # NOT ND
shapiro.test ( data_for_alpha[which(data_for_alpha$Source_category == "source5"), "diversity"] ) # NOT ND
shapiro.test ( data_for_alpha[which(data_for_alpha$Source_category == "source6"), "diversity"] ) # ND
# source 7 is too small sample size to perform the test
shapiro.test ( data_for_alpha[which(data_for_alpha$Source_category == "source8"), "diversity"] ) # ND
shapiro.test ( data_for_alpha[which(data_for_alpha$Source_category == "Sink"), "diversity"] ) # ND
# A: would be better to do a non-parametric test
## 2. assumption of ANOVA: Homogeneity of variance:
## Variance in the populations compared should be the same/similar.
bartlett.test ( diversity ~ Source_category, data= data_for_alpha )
# assumption met
# 3. test
kruskal.test (diversity ~ Source_category, data= data_for_alpha)
# 4. post-hoc
FSA::dunnTest(diversity ~ Source_category, data= data_for_alpha)
## Dunn (1964) Kruskal-Wallis multiple comparison
## p-values adjusted with the Holm method.
Even though one assumption is met (hom.var.) we should not use ANOVA
- the assumption of homogeneity of variance is an extension of the
assumption of normality. It would not be feasible to compare a skewed
distribution in one group to a normal distribution in another group,
even if they have comparable variances!
Kruskal-Wallis test confirms differences in shannon’s index. We do
post-hoc diagnosing to see which groups are different with a Dunn test.
The difference which is statistically sound is the diversity levels
between the source 3 samples and the Sink, after adjusting the
p-value.
Since source 3 consists of soil samples, it is not unexpected that it
would have higher diversity.
Beta diversity
bc_diss <- vegdist(t(asv_table), method = "bray")
nmds <- metaMDS(bc_diss)
# make palette for plotting
pal = c("green4", "navy", "orange", "brown", "blue", "lightblue")
# lets plot an nmds where the color is sample type, shape is source sink
as.data.frame(nmds$points) %>%
cbind(data_for_alpha$Source_category, metadata_type$type_III) %>%
rename("source_cat" = "data_for_alpha$Source_category",
"type" = "metadata_type$type_III") %>%
mutate(source_cat = case_when(source_cat == "Sink" ~ "sink",
TRUE ~ "source")) -> data_for_nmds
# plot
data_for_nmds %>%
ggplot(aes(x = MDS1, y = MDS2)) +
geom_point(aes(fill = type, color = type,
shape= source_cat),
size = 5, stroke=1, alpha = 0.6) +
# customizing the plot
scale_fill_manual(values = pal) +
scale_color_manual(values = pal) +
scale_shape_manual(values = c(21,23)) +
theme_linedraw() +
annotate(geom="text",x=-1.4, y=1.5, label="stress =", color="black") +
annotate(geom="text", x=-1.1, y=1.5, label=round(nmds$stress,4),
color="black") +
#stat_ellipse(aes(colour = type), linewidth = 0.3) +
#stat_ellipse(aes(fill = type), geom="polygon",level=0.95,alpha=0.04) +
theme(legend.background = element_blank(),
legend.box.background = element_rect(colour = "gray")) +
labs(color = "Water \ntype", shape = "Source") +
guides(fill = FALSE) +
geom_vline(xintercept = c(0), color = "grey70", linetype = 2) +
geom_hline(yintercept = c(0), color = "grey70", linetype = 2) -> plot_nmds
There was clear grouping of soil and sediment communities. Surface
water, spring water and biofilm communities were more spread out, and
more dissimilar to soil than to sediment communities.
Out of five sinks, four water and one sediment sink, the most similar
to sediment source samples, in terms of community assembly, was the
sediment sink. It is also closer to the soil sources, whereas water
sinks communities showed little similarity to soil sources.

Environmental data
pca (environmenta
variables of water communities)
df_pca <- metadata %>%
# we only have measurements for water, not for soil nor sediment
filter(type_I == "Water") %>%
select(where(is.numeric)) %>%
select(-c("filter", # dont need it
"N_NO2", "P_PO4")) # NAs
# remove the highly correlated ones, like internalATP and totalATP
cor_matrix <- cor(df_pca)
highly_correlated <- caret::findCorrelation(cor_matrix, cutoff = 0.9)
df_pca <- df_pca[, -highly_correlated]
# now there is 22 observations and 10 environmental variables
# lets see if any env vars can be packed neatly in PCs
pca_env <- prcomp(df_pca, scale = TRUE)
biplot(pca_env)

# i believe it is beneficial to remove the sample PX_gw since it is a single outlier in almost every variable, and stresses the ordination
pca_env <- prcomp(df_pca[rownames(df_pca) != "PX_gw",], scale = TRUE)
# we need the column for coloring by type, get it from the original metadata
metadata[rownames(df_pca) != "PX_gw", c(colnames(df_pca), "type_III", "type_I")] %>%
# remove the outlier sample, the columns that are highly correlated and soil/sed samples
filter(type_I == "Water") -> data_for_pca
autoplot(pca_env, data =data_for_pca ,
colour = 'type_III',
size=5, loadings=TRUE,
loadings.colour="black",
loadings.label=TRUE, loadings.label.size=5,
loadings.label.colour="black" )+
geom_vline(xintercept = c(0), color = "grey70", linetype = 2) +
geom_hline(yintercept = c(0), color = "grey70", linetype = 2) +
geom_point(shape= 21, color = "black", size = 5) +
theme_linedraw() +
geom_vline(xintercept = c(0), color = "grey70", linetype = 2) +
geom_hline(yintercept = c(0), color = "grey70", linetype = 2) +
scale_color_brewer(palette = "Accent")+
theme(legend.background = element_blank(),
legend.box.background = element_rect(colour = "gray")) -> pca_plot
pca_plot

The first three components have 1+ variance explanation. See more
detailed what PC1, PC2 and PC3 (as combinations of environmental
variables) consist of.
normal data: variance = (st.dev)^2 pca data: eigenvalue = (st.dev)^2
“eigenvalues represent the variance explained by each principal
component” -> eigen ~ variance
# Extract the loadings from the PCA result and convert to tidy format
loadings_df <- tidy(pca_env, matrix = "rotation")
# PC1
# Create the ggplot2 object for plotting the loadings
loadings_df %>% filter(PC == "1") %>%
#x=reorder(class,-amount,sum)
ggplot( aes(x = reorder(column, -value), y = value, group = factor(column))) +
geom_bar(stat = "identity", position = "dodge",
fill= "gray90", color = "gray20") +
geom_text(aes(label = column), position = position_dodge(width = 0.9),
#vjust = "inward",
angle = 90 , hjust = "inward") +
labs(x = "Variables of PC1", y = "Loadings") +
theme_minimal() +
theme(axis.text.x = element_blank(),
legend.position = "none") -> plot_pca1
# PC2
loadings_df %>% filter(PC == "2") %>%
#x=reorder(class,-amount,sum)
ggplot( aes(x = reorder(column, -value), y = value, group = factor(column))) +
geom_bar(stat = "identity", position = "dodge",
fill= "gray90", color = "gray20") +
geom_text(aes(label = column), position = position_dodge(width = 0.9),
#vjust = "inward",
angle = 90 , hjust = "inward") +
labs(x = "Variables of PC2", y = "Loadings") +
theme_minimal() +
theme(axis.text.x = element_blank(),
legend.position = "none") -> plot_pca2
# PC3
loadings_df %>% filter(PC == "3") %>%
#x=reorder(class,-amount,sum)
ggplot( aes(x = reorder(column, -value), y = value, group = factor(column))) +
geom_bar(stat = "identity", position = "dodge",
fill= "gray90", color = "gray20") +
geom_text(aes(label = column), position = position_dodge(width = 0.9),
#vjust = "inward",
angle = 90 , hjust = "inward") +
labs(x = "Variables of PC3", y = "Loadings") +
theme_minimal() +
theme(axis.text.x = element_blank(),
legend.position = "none") -> plot_pca3
plot_pca1 + plot_pca2 + plot_pca3

Test pca dispersions.
# we can check the significance in difference between groups in both pca and nmds
euclidean_dist <- data_for_pca %>% select(-c("type_I" , "type_III")) %>%
scale() %>% as.data.frame() %>%
dist(., method = "euclidean")
disp_pca <- betadisper( euclidean_dist, data_for_pca$type_III )
anova(disp_pca) #no sign. differences
## Analysis of Variance Table
##
## Response: Distances
## Df Sum Sq Mean Sq F value Pr(>F)
## Groups 6 22.11 3.685 1.7759 0.1762
## Residuals 14 29.05 2.075
disp_pca$distances %>% as.data.frame() %>%
rename("Distance" = ".") %>%
rownames_to_column("sample_id") %>%
cbind(data_for_pca) %>%
# plot
ggplot( aes(x = type_III, y = Distance)) +
geom_boxplot( fill = "violet") +
labs(x = NULL, y = "Environmental differences \nstandardized Euclidean distance") +
theme_linedraw() +
theme(axis.text.x = element_text(size = 10),
axis.title.y = element_text(size = 10)) -> pca_disp
nmds (water
communities)
asv_water <- asv_table [,rownames(df_pca)] %>% select(!"PX_gw")
bc_diss_water <- vegdist(t(asv_water), method = "bray")
nmds_water <- metaMDS(bc_diss_water)
as.data.frame(nmds_water$points) %>%
cbind(data_for_pca$type_III) %>%
rename("type" = "data_for_pca$type_III") %>%
# plot
ggplot(aes(x = MDS1, y = MDS2)) +
geom_point(aes(fill = type), shape = 21,
size = 5, color= "black" ) +
# customizing the plot
scale_fill_brewer(palette = "Accent") +
theme_linedraw() +
annotate(geom="text",x=-1.4, y=1.5, label="stress =", color="black") +
annotate(geom="text", x=-1.1, y=1.5, label=round(nmds_water$stress,4),
color="black") +
theme(legend.background = element_blank(),
legend.box.background = element_rect(colour = "gray")) +
labs(color = "Water \ntype", shape = "Source") +
guides(fill = FALSE) +
geom_vline(xintercept = c(0), color = "grey70", linetype = 2) +
geom_hline(yintercept = c(0), color = "grey70", linetype = 2) -> nmds_plot_water
euclidean_dist <- data_for_pca %>% select(-c("type_I" , "type_III")) %>%
scale() %>% as.data.frame() %>%
dist(., method = "euclidean")
disp_nmds <- betadisper( bc_diss_water, data_for_pca$type_III )
anova(disp_nmds) # sign. differences
disp_nmds$distances %>% as.data.frame() %>%
rename("Distance" = ".") %>%
rownames_to_column("sample_id") %>%
cbind(data_for_pca) %>%
# plot
ggplot( aes(x = type_III, y = Distance)) +
geom_boxplot( fill = "violet") +
labs(x = NULL, y = "Bray-curtis distance") +
theme_linedraw() +
theme(axis.text.x = element_text(size = 10),
axis.title.y = element_text(size = 10)) -> nmds_water_disp
nmds_plot_water + pca_plot +
nmds_water_disp + pca_disp

## Analysis of Variance Table
##
## Response: Distances
## Df Sum Sq Mean Sq F value Pr(>F)
## Groups 6 0.48932 0.081554 3.0834 0.03869 *
## Residuals 14 0.37029 0.026449
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Lake communities and groundwater communties seem to have relatively
distinct microbial composition. The hyporheic, pond and inflow water
consist only of one sample point, when we remove the soil and sediment
samples for this analysis, so it is not possible to draw conclusions.
But the rest of the samples have a similar relation for both the
environmental variaton and the community variation - environmental
homogeneity of the groundwater samples in visible in the low dispersion
of the groundwater microbial communities. (check significance and put on
plot later)
Constrained
ordiantion
CAP ordination as an distance-based alternative to the RDA (which
uses bray, as opposed to RDA’s euclidean). Hellinger transformation
(square root of relative abundances) is used to account for
compositionality of data.
data_for_pca %>% select(where(is.numeric)) %>%
scale() %>% as.data.frame() -> env.data
decostand(t(asv_water), method = "hellinger") -> sp.dat
# check
identical(rownames(env.data), colnames(asv_water)) #TRUE
# perform model
simpleRDA <- capscale(sp.dat ~ ., data=env.data ,
distance = "bray")
vif.cca(simpleRDA) # all variables lower than 10
# test
# test env paameters
anova.model3 <- anova(simpleRDA, step=1000, by = "term")
anova.model3
# sign: bix* , fi***, TCC***, Cond, O2**, Temp*
# new model
simpleRDA <- capscale(sp.dat ~ bix + fi + TCC + Cond + O2 + Temp, data=env.data ,
distance = "bray")
# test env paameters
anova.model3 <- anova(simpleRDA, step=1000, by = "term")
# test of all canonical axes
anova.model <- anova.cca(simpleRDA, by='axis', step=1000) # CAP1,CAP2,CAP3 significant
# test the whole model
anova.model2 <- anova.cca(simpleRDA, step=1000) # sign
RsquareAdj(simpleRDA)$adj.r.squared # explains 30%
## [1] TRUE
## bix fi TCC Cond O2 Temp pH tot.N
## 5.638966 3.408220 2.283686 2.525874 1.294785 1.745977 1.627837 4.961876
## N_NO3 tot.P
## 6.261860 5.577410
## Permutation test for capscale under reduced model
## Terms added sequentially (first to last)
## Permutation: free
## Number of permutations: 999
##
## Model: capscale(formula = sp.dat ~ bix + fi + TCC + Cond + O2 + Temp + pH + tot.N + N_NO3 + tot.P, data = env.data, distance = "bray")
## Df SumOfSqs F Pr(>F)
## bix 1 0.31946 1.7225 0.001 ***
## fi 1 0.84028 4.5307 0.001 ***
## TCC 1 0.66653 3.5939 0.001 ***
## Cond 1 0.31856 1.7177 0.039 *
## O2 1 0.50456 2.7205 0.001 ***
## Temp 1 0.43066 2.3221 0.013 *
## pH 1 0.30100 1.6230 0.075 .
## tot.N 1 0.29959 1.6154 0.064 .
## N_NO3 1 0.30315 1.6345 0.053 .
## tot.P 1 0.24783 1.3363 0.133
## Residual 10 1.85462
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## [1] 0.2943814
We can say that bix and fix, as well as the temeprature, oxygen and
conductivity have an impact on the microbial communities of Luny water
bodies. Additionally, the number of TCC (microbial load) in the water
body is also a significant indicator of the water community
composition.
Plot the constrained ordination if we want to but it could be a bit
redundadnt considering the individual ordinations of environmental
variables and communitiies. On the other hand, the visual depiction
implies need for more sample points, considering how sparse the
ordination is.
# vectors
ccavectors <- as.matrix(scores(simpleRDA, display = "bp", scaling = "sites")*3.32) %>%
t() %>% as.data.frame() %>%
rename("bix*" = "bix",
"Temp*" = "Temp",
"O2**" = "O2",
"fi***" = "fi",
"TCC***" = "TCC") %>%
t() %>% as.data.frame()
#bix* , fi***, TCC***, Cond, O2**, Temp*
# site coordinates
site_data <- scores(simpleRDA, display = "sites") %>%
as.data.frame() %>%
cbind(., data_for_pca$type_III) %>%
rename("type" = "data_for_pca$type_III")
# plotting
plot_cca <-
site_data %>%
ggplot( aes(x = CAP1, y = CAP2)) +
geom_point(aes(fill = type), shape = 21,
size = 5, color= "black" )+
geom_segment(data = ccavectors, aes(x = 0, y = 0, xend = CAP1, yend = CAP2),
size = 1.2, arrow = arrow(length = unit(0.5, "cm"))) +
geom_vline(xintercept = c(0), color = "grey70", linetype = 2) +
geom_hline(yintercept = c(0), color = "grey70", linetype = 2) +
geom_text(data = ccavectors, aes(x = CAP1*1.2, y = CAP2*1.1,
label = rownames(ccavectors)),
size=6 ) +
theme_linedraw() +
scale_fill_brewer(palette = "Accent") +
theme(legend.background = element_blank(),
legend.box.background = element_rect(colour = "gray"))
plot_cca

There is certain indication that microbial community assembly of Lunz
lakes water samples and near water bodies is not impacted by the
environmental variables which were measured in this study. However, the
sample type provided a clearer impact on community assembly. Samples of
type sediment, soil and surface water showed community similarity within
the type category. To determine whether sample type is merely a proxy
for ecological conditions, environmental variables for samples other
than water samples need to be measured, which was not the case in this
study.
Contribution of sources to sinks was not impacted by spatial
distance, and the artificial lake provided no physical barrier.
Contribution by sample type provided more accurate insight than
contribution by “Source” category, which was an arbitrary category
determined as a mix of sample type and distance from the sink.
This was shown with Source 6 contribution, consisting of spring
sediment and water. Sample type analysis showed that spring sediment of
Source 6 contributed to sink sediments, and Source 6 water samples
contributed to water sinks.
In summary, this study provides a starting point in community
assembly research of microbial fauna of Lunz lakes catchment, and gives
indication that future studies should be focused on environmental
conditions of each microenvironment, and their ties to microbial
assembly, since categorising samples by distance or similarity does not
give clear results.
LS0tDQp0aXRsZTogIk1pY3JvYmlhbCBjb21tdW5pdHkgYXNzZW1ibHkgYW5hbHlzaXMgb2YgTHVueiBsYWtlcyBhbmQgdGhlIHN1cnJvdW5kaW5nIHdhdGVyYm9kaWVzIiANCmF1dGhvcjogICJBbmdlbGEgQ3VrdXNpYyINCmRhdGU6IEp1bHkgMjksIDIwMjMNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUgICAgICAgICAgICAgICAjIFRhYmxlIG9mIGNvbnRlbnRzDQogICAgdG9jX2Zsb2F0OiB0cnVlICAgICAgICAgIyBLZWVwIHRoZSB0YWJsZSBvZiBjb250ZW50cyBmbG9hdGluZyBvbiB0aGUgcGFnZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgICAgICMgRW5hYmxlIGNvZGUgZG93bmxvYWQgYnV0dG9uDQogICAgY29kZV9jb3B5OiB0cnVlICAgICAgICAgIyBFbmFibGUgY29kZSBjb3B5IGJ1dHRvbg0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZSAgICMgTnVtYmVyaW5nIHRoZSBzZWN0aW9ucw0KICAgIHRoZW1lOiBjZXJ1bGVhbiAgICAgICAgICAgIyBDaG9vc2UgYSBCb290c3RyYXAgdGhlbWUgKGNoZWNrIGF2YWlsYWJsZSB0aGVtZXMpDQogICAgaGlnaGxpZ2h0OiB0YW5nbyAgICAgICAgIyBTeW50YXggaGlnaGxpZ2h0aW5nIHN0eWxlIChwaWNrIGEgc3R5bGUgZnJvbSBhdmFpbGFibGUgdGhlbWVzKQ0KDQotLS0NCg0KVGhlIG1haW4gYmVuZWZpdCBvZiBzdHVkeWluZyBjb21tdW5pdHkgYXNzZW1ibHksIGFuZCBmYWN0b3JzIHRoYXQgaW1wYWN0IGl0LCBpcyB0byBmdXJ0aGVyIHVuZGVyc3RhbmQgdGhlIGNvbm5lY3Rpb24gb2YgY29tbXVuaXR5IGRpdmVyc2l0eSB0byBlY29zeXN0ZW0gZnVuY3Rpb25hbGl0eSwgd2hpY2ggaXMgY3J1Y2lhbCBpbiB1cGtlZXBpbmcgZWNvc3lzdGVtcy4gV2l0aCBzcGF0aWFsIGRpc3RhbmNlIHNob3duIHRvIGJlIGEgc2lnbmlmaWNhbnQgZmFjdG9yIGluIGNvbW11bml0eSBhc3NlbWJseSBwcm9jZXNzZXMsIGl0IGlzIHNlbnNpYmxlIHRvIGV4cGxvcmUgdGhlIHdhdGVyYm9kaWVzIG9mIHRoZSBMdW56IHN0dWR5IHNpdGUsIHdoaWNoIGNvbnNpc3RzIG9mIHZhcmlvdXMNCmVudmlyb25tZW50cyB3aXRoIGRpZmZlcmVudCBjb25kaXRpb25zLCBhbmQgaW5jbHVkZXMgdGhyZWUgc3ByaW5ncywgc2V2ZW4gY3JlZWtzLCBmb3VyIGdyb3VuZHdhdGVyIHdlbGxzLCBhIHBvbmQsIGEgaHlwb3JoZWljIHNwcmluZywgYW5kIHRocmVlIGxha2VzLiBUaGUgY29ubmVjdGl2aXR5IGlzIHByZXN1bWVkIHRvIGJlIGhpbmRlcmVkIGF0IHRoZSBtaWRkbGUgcG9pbnQgb2YgdGhlIGNhdGNobWVudCBhcmVhLCB0aGUgTWlkZGxlIExha2UuDQoNCiMgUGFja2FnZSBsb2FkaW5nDQpgYGB7ciwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KEZFQVNUKSAjIGZvciBzb3VyY2UgdHJhY2tpbmcNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeSh2ZWdhbikNCmxpYnJhcnkoRlNBKSAjIGZvciBkdW5uIHBvc3QtaG9jIHRlc3QNCmxpYnJhcnkoY2FyZXQpIA0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkocGF0Y2h3b3JrKSAjIGZvciBjb21iaW5pbmcgcGxvdHMgaW50byAxDQpsaWJyYXJ5KGdnZm9ydGlmeSkNCmxpYnJhcnkocGFpcndpc2VBZG9uaXMpICMgZm9yIHBlcm1hbm92YSBwb3N0LWhvYw0KYGBgDQoNCkZyb20gZXZlcnkgc2FtcGxlLCBETkEgd2FzIGV4dHJhY3RlZCBhbmQgdXNlZCBmb3IgMTZTIHJSTkEgZ2VuZSBhbXBsaWNvbiBzZXF1ZW5jaW5nLiBBbXBsaWNvbiBzZXF1ZW5jaW5nIGFuZCBiaW9pbmZvcm1hdGljIHByb2Nlc3Npbmcgb2YgdGhlIHJhdyBzZXF1ZW5jZSBkYXRhIGZvciB0aGUgaW5mZXJlbmNlIG9mIGFtcGxpY29uIHNlcXVlbmNlIHZhcmlhbnRzIChBU1YpIHVzaW5nIERBREEyIHdhcyBkb25lLCBhcyB3ZWxsIGFzIG90aGVyIHByb2Nlc3Npbmcgb2Ygb3JnYW5lbGxlcyBhbmQgbWl0b2Nob25kcmlhLg0KDQojIExvYWQgZGF0YQ0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQ0KDQoNCiMgbG9hZCBtZXRhZGF0YQ0KbWV0YWRhdGEgPC0gcmVhZC5jc3YoIn4vZmFrcy9FY29sb2d5IGFuZCBFY29zeXN0ZW1zL01FQy04IChTcGVjaWZpYyByZXNlYXJjaCBwcm9qZWN0KS9kYXRhL21ldGFkYXRhX0x1bnpfcmV2aXNlZC5jc3YiLCANCiAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9IDEpDQoNCiMgbG9hZCBhc3YgdGFibGUNCmFzdl90YWJsZSA8LSByZWFkLmNzdigifi9mYWtzL0Vjb2xvZ3kgYW5kIEVjb3N5c3RlbXMvTUVDLTggKFNwZWNpZmljIHJlc2VhcmNoIHByb2plY3QpL2RhdGEvYXN2X3RhYmxlLmNzdiIsIHJvdy5uYW1lcz0xKQ0KDQojIGlkZW50aWZpZXIgbmVlZCB0byBiZSBpZGVudGljYWwgYmV0d2VlbiBhc3ZfdGFibGUgYW5kIG1ldGFkYXRhDQppZGVudGljYWwocm93bmFtZXMobWV0YWRhdGEpLCBjb2xuYW1lcyhhc3ZfdGFibGUpKQ0KIyBpZiB0aGVyZSBpcyBzb21lIHRoYXQgYXJlIGRpZmZlcmVudCB1c2Ugc2V0ZGlmZihyb3duYW1lcyhtZXRhZGF0YSksIGNvbG5hbWVzKGFzdl90YWJsZSkpIHRvIHNlZSB3aGljaA0KDQojIGRhdGEgb24gc291cmNlcy9zaW5rcw0KZmVhc3RfbWV0YWRhdGEgPC0gcmVhZC5jc3YoIn4vZmFrcy9FY29sb2d5IGFuZCBFY29zeXN0ZW1zL01FQy04IChTcGVjaWZpYyByZXNlYXJjaCBwcm9qZWN0KS9kYXRhL2ZlYXN0X21ldGFkYXRhLmNzdiIsIHJvdy5uYW1lcz0xKQ0KIyBpZGVudGlmaWVycyBmb3Igc291cmNlcyBoYXZlIHRvIGJlIHVuaXF1ZSAtIHNvdXJjZSAxIG5lZWRzIHRvIGJlIFNvdXJjZTFfMSwgU291cmNlMV8yLCAuLi4gKQ0KIyBTYW1wbGVJRCBjb2x1bW4gbmVlZCB0byBiZSAgcm93bmFtZXMNCg0KYGBgDQoNCiMgRkVBU1QNCg0KRkVBU1QgLSB0aGUgZmFzdCBleHBlY3RhdGlvbi1tYXhpbWl6YXRpb24gd2FzIHVzZWQsIGFzIGEgbW9yZSBjb21wdXRhdGlvbmFsIGVmZmljaWVudCBhbmQgc2hvcnRlciBhbHRlcm5hdGl2ZSB0byBTb3VyY2VUcmFja2VyLg0KDQoNClByZXBhcmUgdGhlIGRhdGEgZm9yIEZFQVNULg0KYGBge3IsIGV2YWw9RkFMU0V9DQojIGNsYXNzZXMgb2YgZGF0YXNldHMNCg0KIyBmZWFzdF9tZXRhZGF0YSBzaG91bGQgYmUgYSBkYXRhLmZyYW1lDQpjbGFzcyhmZWFzdF9tZXRhZGF0YSkNCg0KI2FzdiBzaG91bGQgYmUgbWF0cml4IGFuZCBlYWNoIGNvbHVtbiBhbiBpbmVnZXIgaW4gb3JkZXIgdG8gcGVyZm9ybSBmZWFzdA0KZmVhc3RfYXN2IDwtIGFzLm1hdHJpeChhc3ZfdGFibGUpICAgICAgICAgICAgICAgICMgbWF0cml4IGFzIGEgd2hvbGUNCiAgICBmb3IoaSBpbiAxOm5jb2woZmVhc3RfYXN2KSl7ICAgICAgICAgICAgICAgICAjIGVhY2ggY29sdW1uIGFzIGludGVnZXINCiAgICAgICAgICAgICAgICAgICAgZmVhc3RfYXN2WywgaV0gPC0gYXMuaW50ZWdlcihmZWFzdF9hc3ZbLCBpXSkNCn0NCg0KDQojIHdob2xlICB0YWJsZSBzaG91bGQgYmUgYSBtYXRyaXgNCmNsYXNzKGZlYXN0X2FzdikNCg0KIyBpbmRpdmlkdWFsIGNvbHVtbiBzaG91bGQgYmUgaW50ZWdlcg0KY2xhc3MoZmVhc3RfYXN2WywgMV0pDQoNCg0KDQojIGZpbmFsIHN0ZXAgLSBmb3JtIG5lZWRzIHRvIGJlIGFzIHdpdGggdmVnYW4gKHNpdGVzIHJvd3MsIHNwZWNpZXMgY29sdW1ucykNCmZlYXN0X2FzdiA8LSB0KGZlYXN0X2FzdikNCmZlYXN0X2FzdlsxOjEwLCAxOjVdDQoNCg0KI3RvIHJlbW92ZSBmcm9tIGVudmlyb25tZW50DQpybShpKSANCg0KDQpgYGANCg0KDQpQZXJmb3JtIEZFQVNULiBJdCBleHBvcnRzIHRoZSByZXN1bHRzIGFuZCBsYXRlciBvbiBuZWVkcyB0byBiZSBpbXBvcnRlZCBhZ2Fpbi4NCg0KVGhlIG1ldGFkYXRhIHRhYmxlIGhhcyB0aHJlZSBjb2x1bW5zIChpLmUuLCAnRW52JywgJ1NvdXJjZVNpbmsnLCAnaWQnKS4gDQpUaGUgZmlyc3QgY29sdW1uIGlzIGEgZGVzY3JpcHRpb24gb2YgdGhlIHNhbXBsZWQgZW52aXJvbm1lbnQgKGUuZy4sIHNhbXBsZSBuYW1lcyksIA0KdGhlIHNlY29uZCBjb2x1bW4gaW5kaWNhdGVzIGlmIHRoaXMgc2FtcGxlIGlzIGEgc291cmNlIG9yIGEgc2luayAoY2FuIHRha2UgdGhlIHZhbHVlICdTb3VyY2UnIG9yICdTaW5rJykuIA0KVGhlIHRoaXJkIGNvbHVtbiBpcyB0aGUgU2luay1Tb3VyY2UgaWQuIA0KDQpXaGVuIHVzaW5nIG11bHRpcGxlIHNpbmtzLCBvbmx5IHRoZSByb3dzIHdpdGggJ1NvdXJjZVNpbmsnID0gU2luayBuZWVkIGFuIGlkIA0KKGJldHdlZW4gMSAtIG51bWJlciBvZiBzaW5rcyBpbiB0aGUgZGF0YSksIHRoZSBzb3VyY2Vz4oCZIGlkcyBhcmUgYmxhbmsuIA0KDQoNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpmZWFzdF9vdXRwdXQgPC0gRkVBU1QoQyA9IGZlYXN0X2FzdiwgICAgICAgICAgICAgICMgdHJhbnNwb3NlZCBhc3ZfdGFibGUNCiAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YSA9IGZlYXN0X21ldGFkYXRhLCAgIyBzaW5rIG9yIHNvdXJjZSBpbmZvcm1hdGlvbg0KICAgICAgICAgICAgICAgICAgICAgIGRpZmZlcmVudF9zb3VyY2VzX2ZsYWcgPSAwLCAjIDAgaWYgc291cmNlcyBhcmUgbm90IGFzc2lnbmVkIHRvIGRpZmZlcmVudCBzaW5rcw0KICAgICAgICAgICAgICAgICAgICAgIEVNX2l0ZXJhdGlvbnMgPSAxMDAwLCAgICAgICAjIG51bWJlciBvZiBpdGVyYXRpb25zDQogICAgICAgICAgICAgICAgICAgICAgZGlyX3BhdGggPSAiQzovVXNlcnMvQW5nZWxhIEN1a3VzaWMvRG9jdW1lbnRzL2Zha3MvRWNvbG9neSBhbmQgRWNvc3lzdGVtcy9NRUMtOCAoU3BlY2lmaWMgcmVzZWFyY2ggcHJvamVjdCkvUmVzdWx0cyIsIA0KICAgICAgICAgICAgICAgICAgICAgIG91dGZpbGUgPSAiZmVhc3RfcmVzdWx0cyIpICAjIHByZWZpeCBmb3Igc2F2aW5nIG91dHB1dCBmaWxlDQoNCiMgQ09WRVJBR0Ugc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZSBjb21tYW5kIGlmIHdlIHdhbnQgdG8gaW5kaWNhdGUgdGhlIHJhcmVmYWN0aW9uIGRlcHRoDQoNCg0KYGBgDQoNCmBgYHtyfQ0KI3dlIGdvdCBhbiBvdXRwdXQsIGltcG9ydCBpdCBub3cNCmZlYXN0X3RhYmxlIDwtIHJlYWQudGFibGUoIkM6L1VzZXJzL0FuZ2VsYSBDdWt1c2ljL0RvY3VtZW50cy9mYWtzL0Vjb2xvZ3kgYW5kIEVjb3N5c3RlbXMvTUVDLTggKFNwZWNpZmljIHJlc2VhcmNoIHByb2plY3QpL1Jlc3VsdHMvZmVhc3RfcmVzdWx0c19zb3VyY2VfY29udHJpYnV0aW9uc19tYXRyaXgudHh0IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJcdCIsIHJvdy5uYW1lcyA9IDEpDQoNCmBgYA0KDQoNCg0KIyMgUmF3IGNvbnRyaWJ1dGlvbiB0byBwbG90dGFibGUgZGF0YQ0KVG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIHRoZSB0b3RhbCBjb250cmlidXRpb24gb2YgZWFjaCBzb3VyY2UgKGkuZS4gZ3JvdXBzIG9mIHNhbXBsZXMpIHRvIHRoZSBkaWZmZXJlbnQgc2luayB3ZSBoYXZlIHRvIGNsZWFuIGl0Lg0KDQpgYGB7ciwgcmVzdWx0cz0naGlkZSd9DQojIGZlYXN0X291dHB1dCBpcyBvZiBjbGFzcyAibGlzdCINCiMgd2Ugd2FudCB0byBtYWtlIGl0IGEgbWF0cml4DQoNCiMgMS4gbWFrZSBhIG5ldyB2ZWN0b3Igd2l0aCBzb3VyY2UgdHlwZXMgKGFuZCBpdCBpcyAiY2hhcmFjdGVyIikNCnNvdXJjZXMgPC0gcGFzdGUoInNvdXJjZSIsIGMoMTo4KSwgc2VwID0gIiIpDQoNCg0KIyAyLiBtYWtlIGVtcHR5IG1hdHJpeCB3aXRoIG5yb3cgPSBudW1iZXIgb2YgU0lOS1MgKDUpLCANCiMgYW5kIG5jb2wgPSBudW1iZXIgb2YgcG9zc2libGUgc291cmNlcyAoMjArIHNhbXBsZXMgYXJlIGRlc2lnbmF0ZWQgdG8gMS04IHNvdXJjZXMpDQpzb3VyY2VfY29udHJpYnV0aW9ucyA8LSBtYXRyaXgoTkEsICAgICAgICAgICAgICAgICAgICAgICAgIyBlbXB0eQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSBucm93KGZlYXN0X3RhYmxlKSwgICMgNSBzaW5rcw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSBsZW5ndGgoc291cmNlcykpICAgICMgbiBzb3VyY2VzDQoNCiMgMy4gZmlsbCBtYXRyaXggDQpmb3IoaSBpbiAxOmxlbmd0aChzb3VyY2VzKSl7ICAgICMgZm9yIGVhY2ggc291cmNlIGFkZCBjb250cmlidXRpb24gDQogIHNvdXJjZV9jb250cmlidXRpb25zWywgaV0gPC0gcm93U3VtcyhmZWFzdF90YWJsZVssICAgICAgIyBzdW0gdXAgY29udHJpYnV0aW9ucyBmb3IgYWxsIDUgcm93cw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbChzb3VyY2VzW2ldLCBjb2xuYW1lcyhmZWFzdF90YWJsZSkpXSkgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBvZiBvbmx5IHRoZSBjb2x1bW5zIHdoaWNoIGhhdmUgc291cmNlWCBpbiBuYW1lDQp9DQoNCiMgNC4gd2UgYWRkZWQgY29udHJpYnV0aW9ucyBhc3NpZ25lZCB0byBlYWNoIG9mIDggc291cmNlcywgbm93IGFkZCBmcm9tIHVua25vd24gc291cmNlcw0Kc291cmNlX2NvbnRyaWJ1dGlvbnMgPC0gY2JpbmQoc291cmNlX2NvbnRyaWJ1dGlvbnMsIGZlYXN0X3RhYmxlJFVua25vd24pDQoNCg0KIyA1LiBjaGVjayBpZiBhbGwgY29udHJpYnV0dW9ucyBmb3IgaW5kaXZpZHVhbCBzaW5rIGFtb3VudCB0byAxDQpyb3dTdW1zKHNvdXJjZV9jb250cmlidXRpb25zKSANCg0KDQojIDYuIGNvbnZlcnQgdG8gZGF0YSBmcmFtZSBhbmQgYnJpbmcgYmFjayByb3duYW1lcyBhbmQgY29sbmFtZXMNCnNvdXJjZV9jb250cmlidXRpb25zIDwtIGFzLmRhdGEuZnJhbWUoc291cmNlX2NvbnRyaWJ1dGlvbnMpDQpjb2xuYW1lcyhzb3VyY2VfY29udHJpYnV0aW9ucykgPC0gYyhzb3VyY2VzLCAidW5rbm93biIpICMgY29sDQpzb3VyY2VfY29udHJpYnV0aW9ucyA8LSBzb3VyY2VfY29udHJpYnV0aW9ucyAlPiUgICAgICAgICMgcm93DQogIG11dGF0ZShzYW1wbGVfaWQgPSByb3duYW1lcyhmZWFzdF90YWJsZSksIC5iZWZvcmUgPSAxKSANCg0KDQojICBmaW5hbCBjbGVhbiB1cCBvZiBlbnZpcm9ubWVudA0Kcm0oIHNvdXJjZXMsIGkpDQoNCmBgYA0KDQojIyBQbG90IHNvdXJjZSBjb250cmlidXRpb24NCg0KYGBge3J9DQpzb3VyY2VfY29udHJpYnV0aW9ucyAlPiUgDQoNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtc2FtcGxlX2lkLCBuYW1lc190byA9ICJzb3VyY2VzIiwgdmFsdWVzX3RvID0gImNvbnRyaWJ1dGlvbnMiKSAlPiUgDQogIG11dGF0ZShzb3VyY2VzID0gYXMuZmFjdG9yKHNvdXJjZXMpKSAgICAgJT4lIA0KICANCiAgDQojIGZpbmQgIHJlbGF0aXZlIGFidW5kYW5jZXMgZm9yIGVhY2ggZGF0ZSBpbiBlYWNoIHdhdGVyIGtpbmQgKHdlbGwvcHVtcC9zdXJmKQ0KICBncm91cF9ieShzYW1wbGVfaWQpICU+JQ0KICBtdXRhdGUocmVsX2NvbnQgPSBjb250cmlidXRpb25zIC8gc3VtKGNvbnRyaWJ1dGlvbnMpICogMTAwKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICANCiMgcGxvdHRpbmcNCiAgZ2dwbG90KGFlcyh4ID0gc2FtcGxlX2lkLCB5ID0gcmVsX2NvbnQsIGZpbGwgPSBzb3VyY2VzKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICANCiMgbGFiZWxsaW5nICAgDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSAgDQogICAgICAgICAgICAgICAgICAjIGxhYmVsIGlmICUgaXMgYmlnIGVub3VnaA0KICAgICAgICAgICAgICAgICAgaWZlbHNlKHJlbF9jb250ID4gMiwgDQogICAgICAgICAgICAgICAgICAjIGlmIHllcyB0aGVuICBwYXN0ZSwgaWYgbm8gdGhlbiBlbXB0eSAiIg0KICAgICAgICAgICAgICAgICAgcGFzdGUwKHJvdW5kKHJlbF9jb250LCA0KSAsICIlIiksICIiICkgICksDQogICAgICAgICAgICAjIGhvdyB0byBwb3NpdGlvbiBpdA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA0KSArDQoNCiMgdGhlbWUgIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKw0KICBsYWJzKHg9ICJTaW5rcyIsIHk9IlJlbGF0aXZlIGNvbnRyaWJ1dGlvbnMgJSIsIGZpbGwgPSAiU291cmNlcyIpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJVbnRlcnNlZSBcbigzMW0pIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVW50ZXJzZWUgXG4oNW0pIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVW50ZXJzZWUgLSBcbm5lYXIgT1NCIGluZmxvdyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVudGVyc2VlIC0gXG5hdCBPU0IgXG5pbmZsb3ciLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTZWRpbWVudDogXG5VbnRlcnNlZSAtIFxuYXQgT1NCIFxuaW5mbG93IikpIA0KDQoNCmBgYA0KDQpGcm9tIGZpdmUgc2luayBzYW1wbGVzIGlkZW50aWZpZWQgaW4gdGhpcyBzdHVkeSwgZm91ciB3ZXJlIHdhdGVyIHNhbXBsZXMsIGFuZCBvbmUgYSBzZWRpbWVudCBzYW1wbGUuIEVhY2ggc2luayBoYWQgYSBzdWJzdGFudGlhbCBwb3J0aW9uIG9mIG1pY3JvYmVzIG9mIHVua25vd24gb3JpZ2luLg0KDQpBZGRpdGlvbmFsIHRvIHRoYXQsIGFub3RoZXIgdmlzaWJsZSB0cmVuZCBpcyB3YXRlciBzYW1wbGVzIGJlaW5nIHRyYWNlZCBiYWNrIHRvIFNvdXJjZSAxIChzdXJmYWNlIHdhdGVycyksIHdpdGggbm9uLWV4aXN0ZW50IG9yIG1pbmltYWwgcG9ydGlvbiBvZiBTb3VyY2UgMiByZWxhdGVkIG1pY3JvYmVzIChzdXJmYWNlIHdhdGVycycgc2VkaW1lbnQgYW5kIGJpb2ZpbG0gc2FtcGxlcywgc2VlIEZpZy4yLikuIA0KDQpUaGUgc2VkaW1lbnQgc2luaywgb24gdGhlIG90aGVyIGhhbmQsIHNob3dlZCBubyBpbmZsdWVuY2Ugb2YgU291cmNlIDEgb24gaXRzIGNvbXBvc2l0aW9uLCBidXQgaGFkIGEgaGlnaCBTb3VyY2UgMiBvcmlnaW4uDQpXYXRlciBzaW5rcyBjb250YWluZWQgbW9yZSBBU1ZzIG5vdCBmb3VuZCBpbiBhbnkgb2YgdGhlIHNvdXJjZXMgdGhhbiB0aGUgc2VkaW1lbnQgc2luay4gDQoNCg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCmZlYXN0X3RhYmxlICU+JSANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGVfaWQiKSAlPiUgDQojIGZpbmQgdGhlIHR3byBzaW5rcyBpbiBxdWVzdGlvbiAgDQogIGZpbHRlcihzYW1wbGVfaWQgJWluJSBjKCJPU0JfaW5fTFVTX2luZmxvd19MVVNfYXRfT1NCX2luZmxvdyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJPU0JfaW5fTFVTX3NlZF9MVVNfc2VkaW1lbnQiKSkgJT4lIA0KICANCiMgZmluZCB0aGUgaW5kaXZpZHVhbCBzYW1wbGVzIGZyb20gc291cmNlIDYNCiAgc2VsZWN0KCAic2FtcGxlX2lkIiwgIGNvbnRhaW5zKCJzb3VyY2U2IikpICU+JSANCiMgcmVtb3ZlIHRoZSBsYXN0IHBhcnQgb2YgbmFtZXMsIHdoaWNoIHNheXMgInNvdXJjZTYiICANCiAgcmVuYW1lX2FsbCh+c3RyX3JlbW92ZSguLCAiLnsxMH0kIikpICU+JSANCiAgDQogIHBpdm90X2xvbmdlcihjb2xzID0gLXNhbXBsZV9pZCwgbmFtZXNfdG8gPSAic291cmNlcyIsIHZhbHVlc190byA9ICJjb250cmlidXRpb25zIikgJT4lIA0KICBtdXRhdGUoc291cmNlcyA9IGFzLmZhY3Rvcihzb3VyY2VzKSkgICAgICU+JSANCiAgDQogIA0KIyBmaW5kICByZWxhdGl2ZSBhYnVuZGFuY2VzIGZvciBlYWNoIGRhdGUgaW4gZWFjaCB3YXRlciBraW5kICh3ZWxsL3B1bXAvc3VyZikNCiAgZ3JvdXBfYnkoc2FtcGxlX2lkKSAlPiUNCiAgbXV0YXRlKHJlbF9jb250ID0gY29udHJpYnV0aW9ucyAvIHN1bShjb250cmlidXRpb25zKSAqIDEwMCkgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgDQojIHBsb3R0aW5nDQogIA0KICBnZ3Bsb3QoYWVzKHggPSBzYW1wbGVfaWQsIHkgPSByZWxfY29udCwgZmlsbCA9IHNvdXJjZXMpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIpICsNCiAgDQojIGxhYmVsbGluZyAgIA0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gIA0KICAgICAgICAgICAgICAgICAgIyBsYWJlbCBpZiAlIGlzIGJpZyBlbm91Z2gNCiAgICAgICAgICAgICAgICAgIGlmZWxzZShyZWxfY29udCA+IDIsIA0KICAgICAgICAgICAgICAgICAgIyBpZiB5ZXMgdGhlbiAgcGFzdGUsIGlmIG5vIHRoZW4gZW1wdHkgIiINCiAgICAgICAgICAgICAgICAgIHBhc3RlMChyb3VuZChyZWxfY29udCwgNCkgLCAiJSIpLCAiIiApICApLA0KICAgICAgICAgICAgIyBob3cgdG8gcG9zaXRpb24gaXQNCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCBzaXplID0gNCkgKw0KDQojIHRoZW1lICANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIGxhYnMoeD0gIlNpbmtzIiwgeT0iUmVsYXRpdmUgY29udHJpYnV0aW9ucyAlIiwgZmlsbCA9ICJTb3VyY2VzIikgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIlVudGVyc2VlIC0gXG5hdCBPU0IgXG5pbmZsb3ciLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTZWRpbWVudDogXG5VbnRlcnNlZSAtIFxuYXQgT1NCIFxuaW5mbG93IikpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyggIiMwMDY0MDAiLCAiI0ZGRDcwMCIsICJsaWdodGJsdWUiLCAiI0ZGRDcwMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJsaWdodGJsdWUiLCAiIzAwNjQwMCIsICJsaWdodGJsdWUiICkpDQpgYGANCg0KDQpFdmVuIHRob3VnaCB0aGUgdHdvIHNpbmtzIGF0IHRoZSBpbmZsb3cgYm90aCBoYWQgfjEwJSBvZiBTb3VyY2UgNiBtaWNyb2JlcyAod2hpY2ggd2FzIHR3byBsb2NhdGlvbnMgLSBib3RoIHNlZGltZW50IGFuZCB3YXRlciksIGl0IHNlZW1zIHRoYXQgbW9yZSBkZXRhaWxlZCBsb29rIGdpdmVzIG1vcmUgaW5zaWdodCB0aGF0IHNhbXBsZSB0eXBlIGlzIGEgYmV0dGVyIHByZWRpY3RvciBvZiBjb250cmlidXRpb24gdGhhbiBsb2NhdGlvbiBpcy4NCg0KUmVzdWx0OiB3YXRlciBzaW5rIHdhcyBtb3JlIGluZmx1ZW5jZWQgYnkgd2F0ZXIgc2FtcGxlcyBjb21tdW5pdGllcywgd2hpbGUgc2VkaW1lbnQgc2luayBjb250YWluZWQgYWxtb3N0IGV4Y2x1c2l2ZWx5IG1pY3JvYmVzIGZyb20gc3ByaW5nIHNlZGltZW50cyBhbmQgc3ByaW5nIGJpb2ZpbG1zLg0KDQoNCg0KIyBTYW1wbGUgdHlwZSBkaXN0cmlidXRpb24NCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdob2xkJ30NCg0KbWV0YWRhdGFfdHlwZSA8LSBtZXRhZGF0YSAlPiUgDQogICAgICAgICAgICAgICAgIHJvd25hbWVzX3RvX2NvbHVtbigic291cmNlcyIpICU+JSANCiAgICAgICAgICAgICAgICAgc2VsZWN0KCJzb3VyY2VzIiwgInR5cGVfSUlJIikgJT4lIA0KICAgICAgICAgICAgICAgICBtdXRhdGUodHlwZV9JSUkgPSBjYXNlX3doZW4oDQogICAgICAgICAgICAgICAgICMgYXNzaWduIGNhdGVnb3JpZXMgIA0KICAgICAgICAgICAgICAgICAgIHR5cGVfSUlJICVpbiUgYygiQ3JlZWsiLCAiSHlwb3JoZWljIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBvbmQiLCAiTGFrZSIsICJJbmZsb3ciKSB+ICJTdXJmYWNlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IHR5cGVfSUlJKSkgDQoNCg0KDQoNCmZlYXN0X3RhYmxlICU+JSANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzaW5rX2lkIikgJT4lIA0KIyByZW5hbWUgdGhlIGNvbHVtbnMgc28gdGhhdCB0aGV5IGNhbiBiZSBjb25uZWN0ZWQgdG8gdGhlIG1ldGFkYXRhICh0eXBlIGluZm8pICANCiAgcmVuYW1lX2FsbCh+c3RyX3JlbW92ZSguLCAiLnsxMH0kIikpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtIHNpbmtfaWQsIG5hbWVzX3RvID0gInNvdXJjZXMiLCB2YWx1ZXNfdG8gPSAiY29udHJpYnV0aW9ucyIpICU+JSANCiMgZmlsdGVyIG91dCBjb250cmlidXRpb25zIGZyb20gdW5rbm93IHNvdXJjZXMNCiAgZmlsdGVyKHNvdXJjZXMgIT0gIlVua25vd24iKSAlPiUgDQojIGpvaW4gd2l0aCBtZXRhZGF0YQ0KICBsZWZ0X2pvaW4oLiwgbWV0YWRhdGFfdHlwZSwgYnkgPSAic291cmNlcyIpICU+JSANCiAgZmlsdGVyKHR5cGVfSUlJICE9ICJOQSIpICU+JSANCiAgZmlsdGVyKCBjb250cmlidXRpb25zIDwgMC4wNSkgJT4lIA0KIyBwbG90DQogIGdncGxvdChhZXMoeD0gdHlwZV9JSUksIHk9IGNvbnRyaWJ1dGlvbnMpKSArIA0KICBnZW9tX2JveHBsb3QoYWVzKGZpbGwgPSBzaW5rX2lkKSApICsNCiAgdGhlbWVfbGluZWRyYXcoKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKGxhYmVscz1jKCJVbnRlcnNlZSAoMzFtKSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVW50ZXJzZWUgKDVtKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbnRlcnNlZSAobmVhciBpbmZsb3cpIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVbnRlcnNlZSAoYXQgaW5mbG93KSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2VkaW1lbnQgKGF0IGluZmxvdykiKSwgDQogICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKCIjYWNjN2Q5IiwgIiM4YmIwY2EiLCIjNTE4MGEyIiwiIzNlNjQ3ZCIsIiNkOGIzNjUiKSkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249YygwLjMsMC44KSwgDQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksIA0KICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgpLCANCiAgICAgICAgbGVnZW5kLmJveC5iYWNrZ3JvdW5kICA9ICAgZWxlbWVudF9yZWN0KGNvbG9yID0gImdyYXkiKSkgKw0KICBsYWJzKHkgPSAiQ29udHJpYnV0aW9ucyIsIHg9ICJTYW1wbGUgdHlwZSIpICsgDQogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiQmlvZmlsbSIsICJHcm91bmQgd2F0ZXIiLCAiU2VkaW1lbnQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTb2lsIiwgIlNwcmluZyB3YXRlciIsICJTdXJmYWNlIHdhdGVyIikgKQ0KICANCiAgDQoNCmBgYA0KDQoNClN1cmZhY2Ugd2F0ZXJzIGNvbnRyaWJ1dGVkIHRvIGFsbCB3YXRlciBzaW5rcywgYnV0IHRoZWlyIGVmZmVjdCBvbiB0aGUgc2VkaW1lbnQgb2YgdGhlIHNpbmsgd2FzIG1pbmltYWwuIA0KU2FtcGxlcyB0aGF0IGRpZCBjb250cmlidXRlIHRvIHNlZGltZW50IHNpbmsgYXJlICBiaW9maWxtLCBzZWRpbWVudCBhbmQgc29pbCBzb3VyY2Ugc2FtcGxlcy4gDQpBZGRpdGlvbmFsIHRvIGNvbnRyaWJ1dGluZyB0byB0aGUgc2VkaW1lbnQgc2luaywgYmlvZmlsbSBzYW1wbGVzIGFsc28gaGFkIGFuIGltcGFjdCBvbiB0aGUgY29tbXVuaXR5IGF0IHRoZSBpbmZsb3cgb2YgdGhlIExvd2VyIExha2UuDQpTcHJpbmd3YXRlciBzYW1wbGVzIHdlcmUgdGhlIGJpZ2dlc3QgY29udHJpYnV0b3IgdG8gdGhlIGluZmxvdywgYW5kIGhhZCBhbiBpbXBhY3Qgb24gdGhlDQptaWNyb2JpYWwgYXNzZW1ibHkgb2YgdGhlIExvd2VyIExha2UgYXQgaXRzIDMxLW1ldGVyIGRlcHRoLg0KDQoNCg0KIyBTcGF0aWFsIGRpc3RyaWJ1dGlvbg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naG9sZCd9DQptZXRhZGF0YV9yYW5rIDwtIG1ldGFkYXRhICU+JSANCiAgICAgICAgICAgICAgICAgcm93bmFtZXNfdG9fY29sdW1uKCJzb3VyY2VzIikgJT4lIA0KICAgICAgICAgICAgICAgICBzZWxlY3QoInNvdXJjZXMiLCAicmFuayIpICU+JSANCiAgICAgICAgICAgICAgICAgZmlsdGVyKHJhbmsgIT0gInNpbmsiKQ0KDQpmZWFzdF90YWJsZSAlPiUgDQogIHJvd25hbWVzX3RvX2NvbHVtbigic2lua19pZCIpICU+JSANCiMgcmVuYW1lIHRoZSBjb2x1bW5zIHNvIHRoYXQgdGhleSBjYW4gYmUgY29ubmVjdGVkIHRvIHRoZSBtZXRhZGF0YSAocmFuayBpbmZvKSAgDQogIHJlbmFtZV9hbGwofnN0cl9yZW1vdmUoLiwgIi57MTB9JCIpKSAlPiUgDQogIHBpdm90X2xvbmdlcihjb2xzID0gLSBzaW5rX2lkLCBuYW1lc190byA9ICJzb3VyY2VzIiwgdmFsdWVzX3RvID0gImNvbnRyaWJ1dGlvbnMiKSAlPiUgDQojIGZpbHRlciBvdXQgY29udHJpYnV0aW9ucyBmcm9tIHVua25vdyBzb3VyY2VzDQogIGZpbHRlcihzb3VyY2VzICE9ICJVbmtub3duIikgJT4lIA0KIyBqb2luIHdpdGggbWV0YWRhdGENCiAgbGVmdF9qb2luKC4sIG1ldGFkYXRhX3JhbmssIGJ5ID0gInNvdXJjZXMiKSAlPiUgDQogIGZpbHRlcihyYW5rICE9ICJOQSIpICU+JSANCiMgcGxvdA0KICBnZ3Bsb3QoYWVzKHg9IHJhbmssIHk9IGNvbnRyaWJ1dGlvbnMpKSArIA0KICBnZW9tX2JveHBsb3QoIGZpbGwgPSAidmlvbGV0IikgKw0KICBmYWNldF93cmFwKH5zaW5rX2lkLCBzY2FsZXMgPSAiZnJlZV95IiwgIGxhYmVsbGVyID0gDQogICAgICAgICAgICAgICBhc19sYWJlbGxlciggYygiTFVTX2RwXzMxbV9MVVNfMzFtIiA9ICJVbnRlcnNlZSAoMzFtKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTFVTX2RwXzVtX0xVU181bSIgPSAiVW50ZXJzZWUgKDVtKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTFVTX2luX09TQl9MVVNfbmVhcl9PU0JfaW5mbG93IiA9ICJVbnRlcnNlZSAobmVhciBpbmZsb3cpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPU0JfaW5fTFVTX2luZmxvd19MVVNfYXRfT1NCX2luZmxvdyIgPSAiVW50ZXJzZWUgKGF0IGluZmxvdykiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9TQl9pbl9MVVNfc2VkX0xVU19zZWRpbWVudCIgPSAiU2VkaW1lbnQgKGF0IGluZmxvdykiICkpKSArDQogIHRoZW1lX2xpbmVkcmF3KCkgKyANCiAgbGFicyh5ID0gIkNvbnRyaWJ1dGlvbnMiLCB4PSAiUmFua2VkIGJ5IHNwYXRpYWwgZGlzdGFuY2UgIikNCg0KICANCmBgYA0KDQpXZSBoeXBvdGhlc2l6ZWQgdGhhdCBhIHN1YnN0YW50aWFsIGVmZmVjdCBvZiBwYXNzaXZlIGRpc3BlcnNhbCBvZiBtaWNyb29yZ2FuaXNtcyBvbiB0aGUgY29tcG9zaXRpb24gb2YgbWljcm9iaWFsIGNvbW11bml0aWVzIGluIHRoZSBsYWtlIHNpbmtzIHNob3VsZCByZXN1bHQgaW4gc2lnbmlmaWNhbnRseSBkZWNsaW5pbmcgY29udHJpYnV0aW9ucyBvZiBzb3VyY2VzIHdpdGggaW5jcmVhc2luZyBzcGF0aWFsIGRpc3RhbmNlIHRvIHRoZSBtYWluIGxha2UgKGkuZS4gZGlzdGFuY2UgcmFua3Mgc2luY2UgZGF0YSBvbiBleGFjdCBzcGF0aWFsIGRpc3RhbmNlcyB3ZXJlIG5vdCBhdmFpbGFibGUpLiANCg0KVGFja2xpbmcgdGhpcyBoeXBvdGhlc2lzLCB3ZSBkaWQgbm90IGZpbmQgYSBzaWduaWZpY2FudCBjb3JyZWxhdGlvbiBiZXR3ZWVuIHNwYXRpYWwgZGlzdGFuY2UgYW5kIHNpbmsgY29udHJpYnV0aW9uLiBOb25lIG9mIHRoZSBzaW5rcyBmb2xsb3dlZCB0aGUgcHJlc3VtZWQgdHJlbmQgb2YgcmFuayAxIGhhdmluZyB0aGUgaGlnaGVzdCBzaW5rIGNvbnRyaWJ1dGlvbiBhbmQgcmFuayA4IHRoZSBsb3dlc3QsIG5vciB3YXMgdGhlcmUgYSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHJhbmtzIGJlZm9yZSB0aGUgY29ubmVjdGl2aXR5IGJhcnJpZXIgYW5kIGFmdGVyIHRoZSBiYXJyaWVyLiANClRoZSByYW5rIDYgaXMgdXBzdHJlYW0gb2YgdGhlIE1pZGRsZSBsYWtlLCB3aGljaCBpcyB0aGUgcHJlc3VtZWQgYmFycmllci4gDQoNCg0KDQojIFByZS1wcm9jZXNzaW5nIGZvciBjb21tdW5pdHkgYW5hbHlzaXMNCg0KV2UgbmVlZCB0byBhY2NvdW50IGZvciB0aGUgdW5ldmVuIHNlcXVlbmNpbmcgZGVwdGguDQpgYGB7cn0NCiMgbnVtYmVyIG9mIHJlYWRzIHBlciBzYW1wbGUNCmFzdl90YWJsZSAlPiUgY29sU3VtcygpICU+JSBzdW1tYXJ5KCkgDQoNCmBgYA0KDQpDb25zaWRlcmluZyBhbGwgc2FtcGxlcyBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiByZWFkcyB0aGUgZGF0YXNldCBoYXMgY2xlYXJseSBhbHJlYWR5IGJlZW4gcmFyZWZpZWQgYnkgTHVjYXMgYmVmb3JlIGdpdmluZyBpdCB0byBtZS4NCg0KDQoNCg0KIyBBbHBoYSBkaXZlcnNpdHkNCmBgYHtyfQ0KDQpzaGFubm9uZGl2IDwtIHZlZ2FuOjpkaXZlcnNpdHkodChhc3ZfdGFibGUpKQ0KIyByZWNhbGN1bGF0aW5nIGl0IGFzIHRoZSBlZmZlY3RpdmUgbnVtYmVyIG9mIHNwZWNpZXMgdG8gYmUgbW9yZSBjb21wYXJhYmxlIGFjcm9zcyBzdHVkaWVzLg0KZW5zIDwtIGV4cChzaGFubm9uZGl2KSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSByb3duYW1lc190b19jb2x1bW4oInNhbXBsZV9pZCIpICU+JSANCiAgcmVuYW1lKCJkaXZlcnNpdHkiID0gIi4iKQ0KDQpkaXZlcnNpdHlfZGF0YSA8LSBzcGVjbnVtYmVyKHQoYXN2X3RhYmxlKSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGVfaWQiKSAlPiUgDQogIHJlbmFtZSgicmljaG5lc3MiID0gIi4iKSAlPiUgaW5uZXJfam9pbiguLCBlbnMsIGJ5ID0ic2FtcGxlX2lkIiApDQoNCiMgd2Ugd2lsbCBwbG90IGRpdmVyc2l0eSBieSBzb3VyY2Ugc28gbWFrZSBjbGVhbiBjYXRlZ29yaXphdGlvbiBoZXJlDQpmZWFzdF9tZXRhZGF0YSAlPiUgDQogICMgcmVtb3ZlIGxhc3QgdHdvIHN0cmluZ3MNCiAgbXV0YXRlKEVudiA9IHN0cl9yZW1vdmUoRW52LCAiLnsyfSQiKSkgJT4lIA0KICAjIHdoZXJlIFNvdXJjZVNpbmsgY29sdW1uIGlzIGEgc291cmNlIGtlZXAgdGhlIHZhbHVlIGZyb20gdGhlIEVudiBjb2x1bW4NCiAgbXV0YXRlKFNvdXJjZV9jYXRlZ29yeSA9IGNhc2Vfd2hlbihTb3VyY2VTaW5rID09ICJTb3VyY2UiIH4gRW52LA0KICAjIG90aGVyd2lzZSBrZWVwIHRoZSB2YWx1ZSBmcm9tIFNvdXJjZVNpbmsgY29sdW1uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gU291cmNlU2luaykgKSAlPiUgDQogICMgc29tZSB0cm91YmxlIHdpdGggc291cmNlIDMNCiAgbXV0YXRlKFNvdXJjZV9jYXRlZ29yeSA9IGNhc2Vfd2hlbihTb3VyY2VfY2F0ZWdvcnkgJWluJSBjKCJzb3VyY2UzIiwgInNvdXJjZTNfIikgfiAic291cmNlMyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+U291cmNlX2NhdGVnb3J5KSkgJT4lIA0KICANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGVfaWQiKSAgJT4lIA0KICBzZWxlY3QoInNhbXBsZV9pZCIsICJTb3VyY2VfY2F0ZWdvcnkiKSAlPiUgDQogIG11dGF0ZShTb3VyY2VfY2F0ZWdvcnkgPSBhcy5mYWN0b3IoU291cmNlX2NhdGVnb3J5KSkgJT4lIA0KICAjIHdlIG5vdyBoYXZlIGNsZWFuIGNhdGVnb3J5IGFuZCBjYW4gY29ubmVjdCBpdCB0byB0aGUgZGl2ZXJzaXR5IGRhdGENCiAgaW5uZXJfam9pbiguLCBkaXZlcnNpdHlfZGF0YSwgICBieSA9ICJzYW1wbGVfaWQiKSAlPiUgDQogIHNlbGVjdCgtc2FtcGxlX2lkKSAlPiUgDQogIA0KICAjcGl2b3QgbG9uZ2VyIHNvIHdlIGNhbiBmYWNldA0KICBwaXZvdF9sb25nZXIoY29scyA9IC1Tb3VyY2VfY2F0ZWdvcnksIG5hbWVzX3RvID0gIm1lYXN1cmUiLCB2YWx1ZXNfdG8gPSAidmFsdWVzIikgJT4lIA0KICANCiAgIyBwbG90DQogIGdncGxvdCggYWVzKHggPSBTb3VyY2VfY2F0ZWdvcnksIHkgPSB2YWx1ZXMpKSArDQogICNzdGF0X2JveHBsb3QoZ2VvbSA9J2Vycm9yYmFyJykgKyANCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAidmlvbGV0IikgKw0KICB0aGVtZV9saW5lZHJhdygpKw0KICBjb29yZF9mbGlwKCkgKyANCiAgZmFjZXRfd3JhcCh+bWVhc3VyZSwgc2NhbGVzID0gImZyZWUiLCAgbGFiZWxsZXIgPSANCiAgICAgICAgICAgICAgIGFzX2xhYmVsbGVyKCBjKCJkaXZlcnNpdHkiID0gIlNoYW5ub24ncyBkaXZlcnNpdHkgaW5kZXgiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJyaWNobmVzcyIgPSAiUmljaG5lc3MiKSApICkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNCxmYWNlPSJib2xkIiksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTAsZmFjZT0iYm9sZCIpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICsNCiAgbGFicyggeCA9ICJTb3VyY2UgY2F0ZWdvcnkiLA0KICAgICAgIHkgPSBOVUxMKSArDQogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiU2luayIsICAiU291cmNlIDEiLCAiU291cmNlIDIiLCAiU291cmNlIDMiLCAiU291cmNlIDQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU291cmNlIDUiLCAiU291cmNlIDYiLCAgIlNvdXJjZSA3IiwgICJTb3VyY2UgOCIpKSAgDQoNCg0KDQpgYGANCg0KUmljaG5lc3Mgb2YgdGhlIHNpbmtzIHdhcyB0aGUgbG93ZXN0IGNvbXBhcmVkIHRvIHNvdXJjZSByaWNobmVzcy4gU291cmNlcyA3LCBhbmQgOCwNCndoaWNoIGhhdmUgYSBkaXJlY3QgaW5mbG93IHRvIHRoZSBzaW5rcywgaGFkIHRoZSBoaWdoZXN0IHJpY2huZXNzLiBTb3VyY2UgMSwgd2hpY2ggbWFrZXMgYSBiaWcNCmNvbnRyaWJ1dGlvbiB0byBzaW5rIGNvbW11bml0aWVzIGhhZCBoaWdoZXIgcmljaG5lc3MgdGhhbiB0aGUgc2lua3MgaXQNCmNvbnRyaWJ1dGVkIHRvLg0KDQpTaW5rIGV2ZW5uZXNzIHdhcyBsb3dlciB0aGFuIGV2ZW5uZXNzIG9mIHNvdXJjZXMuIFNwZWNpZXMgZGlzdHJpYnV0aW9uIG9mIHRoZSBzaW5rIGxlYW5zIHRvd2FyZHMgYQ0KZmV3IHZlcnkgZG9taW5hbnQgQVNWcyBhbmQgbWFueSByYXJlIG9uZXMsIGluZGljYXRpbmcgcG9zc2libGUgaGFyZGVyIGVudmlyb25tZW50YWwgY29uZGl0aW9ucyBvciBiaWdnZXINCmNvbXBldGl0aXZlbmVzcyBpbiBzaW5rLiBTb3VyY2UgMywgd2l0aCBpdHMgc29pbCBzYW1wbGVzLCBoYWQgaGlnaCBldmVubmVzcy4gU291cmNlIDQgKGdyb3VuZHdhdGVyKSBoYWQgc2xpZ2h0bHkgbG93ZXINCmV2ZW5uZXNzIGFuZCByaWNobmVzcyBpbiBjb21wYXJpc29uIHRvIG90aGVyIHNvdXJjZXMuDQoNClRlc3QgaXQ6DQpgYGB7ciwgcmVzdWx0cz0naGlkZSd9DQojIDEuIHRoZSBzYW1lIGRhdGEgbWFuaXB1bGF0aW9uIGFzIGFib3ZlDQpmZWFzdF9tZXRhZGF0YSAlPiUgDQogIG11dGF0ZShFbnYgPSBzdHJfcmVtb3ZlKEVudiwgIi57Mn0kIikpICU+JSANCiAgbXV0YXRlKFNvdXJjZV9jYXRlZ29yeSA9IGNhc2Vfd2hlbihTb3VyY2VTaW5rID09ICJTb3VyY2UiIH4gRW52LCAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBTb3VyY2VTaW5rKSApICU+JSANCiAgbXV0YXRlKFNvdXJjZV9jYXRlZ29yeSA9IGNhc2Vfd2hlbihTb3VyY2VfY2F0ZWdvcnkgJWluJSBjKCJzb3VyY2UzIiwgInNvdXJjZTNfIikgfiAic291cmNlMyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+U291cmNlX2NhdGVnb3J5KSkgJT4lIA0KICANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGVfaWQiKSAgJT4lIA0KICBzZWxlY3QoInNhbXBsZV9pZCIsICJTb3VyY2VfY2F0ZWdvcnkiKSAlPiUgDQogIG11dGF0ZShTb3VyY2VfY2F0ZWdvcnkgPSBhcy5mYWN0b3IoU291cmNlX2NhdGVnb3J5KSkgJT4lIA0KICBpbm5lcl9qb2luKC4sIGRpdmVyc2l0eV9kYXRhLCAgIGJ5ID0gInNhbXBsZV9pZCIpICU+JSANCiAgc2VsZWN0KC1zYW1wbGVfaWQpIC0+IGRhdGFfZm9yX2FscGhhDQoNCg0KIyAyLiBwZXJmb3JtIEFOT1ZBLyBrcnVza2FsLXdhbGxpcw0KDQojIDEuIGFzc3VtcHRpb24gb2YgQU5PVkE6IE5vcm1hbCBkaXN0cmlidXRpb246IA0KIyBFYWNoIHBvcHVsYXRpb24gdG8gYmUgY29tcGFyZWQgc2hvdWxkIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIA0KIyAoTk9UIFRIRSBFTlRJUkUgREFUQVNFVCkuDQpzaGFwaXJvLnRlc3QgKCAgZGF0YV9mb3JfYWxwaGFbd2hpY2goZGF0YV9mb3JfYWxwaGEkU291cmNlX2NhdGVnb3J5ID09ICJzb3VyY2UxIiksICJkaXZlcnNpdHkiXSApICMgTk9UIE5EDQpzaGFwaXJvLnRlc3QgKCAgZGF0YV9mb3JfYWxwaGFbd2hpY2goZGF0YV9mb3JfYWxwaGEkU291cmNlX2NhdGVnb3J5ID09ICJzb3VyY2UyIiksICJkaXZlcnNpdHkiXSApICMgTkQNCnNoYXBpcm8udGVzdCAoICBkYXRhX2Zvcl9hbHBoYVt3aGljaChkYXRhX2Zvcl9hbHBoYSRTb3VyY2VfY2F0ZWdvcnkgPT0gInNvdXJjZTMiKSwgImRpdmVyc2l0eSJdICkgIyBORA0Kc2hhcGlyby50ZXN0ICggIGRhdGFfZm9yX2FscGhhW3doaWNoKGRhdGFfZm9yX2FscGhhJFNvdXJjZV9jYXRlZ29yeSA9PSAic291cmNlNCIpLCAiZGl2ZXJzaXR5Il0gKSAjIE5PVCBORA0Kc2hhcGlyby50ZXN0ICggIGRhdGFfZm9yX2FscGhhW3doaWNoKGRhdGFfZm9yX2FscGhhJFNvdXJjZV9jYXRlZ29yeSA9PSAic291cmNlNSIpLCAiZGl2ZXJzaXR5Il0gKSAjIE5PVCBORA0Kc2hhcGlyby50ZXN0ICggIGRhdGFfZm9yX2FscGhhW3doaWNoKGRhdGFfZm9yX2FscGhhJFNvdXJjZV9jYXRlZ29yeSA9PSAic291cmNlNiIpLCAiZGl2ZXJzaXR5Il0gKSAjIE5EDQojIHNvdXJjZSA3IGlzIHRvbyBzbWFsbCBzYW1wbGUgc2l6ZSB0byBwZXJmb3JtIHRoZSB0ZXN0ICANCnNoYXBpcm8udGVzdCAoICBkYXRhX2Zvcl9hbHBoYVt3aGljaChkYXRhX2Zvcl9hbHBoYSRTb3VyY2VfY2F0ZWdvcnkgPT0gInNvdXJjZTgiKSwgImRpdmVyc2l0eSJdICkgIyBORA0Kc2hhcGlyby50ZXN0ICggIGRhdGFfZm9yX2FscGhhW3doaWNoKGRhdGFfZm9yX2FscGhhJFNvdXJjZV9jYXRlZ29yeSA9PSAiU2luayIpLCAiZGl2ZXJzaXR5Il0gKSAjIE5EDQoNCiMgQTogd291bGQgYmUgYmV0dGVyIHRvIGRvIGEgbm9uLXBhcmFtZXRyaWMgdGVzdA0KDQoNCiMjIDIuIGFzc3VtcHRpb24gb2YgQU5PVkE6IEhvbW9nZW5laXR5IG9mIHZhcmlhbmNlOiANCiMjIFZhcmlhbmNlIGluIHRoZSBwb3B1bGF0aW9ucyBjb21wYXJlZCBzaG91bGQgYmUgdGhlIHNhbWUvc2ltaWxhci4gDQpiYXJ0bGV0dC50ZXN0ICggZGl2ZXJzaXR5IH4gU291cmNlX2NhdGVnb3J5LCBkYXRhPSBkYXRhX2Zvcl9hbHBoYSApDQojIGFzc3VtcHRpb24gbWV0DQoNCg0KIyAzLiB0ZXN0DQprcnVza2FsLnRlc3QgKGRpdmVyc2l0eSB+IFNvdXJjZV9jYXRlZ29yeSwgZGF0YT0gZGF0YV9mb3JfYWxwaGEpIA0KIyA0LiBwb3N0LWhvYw0KRlNBOjpkdW5uVGVzdChkaXZlcnNpdHkgfiBTb3VyY2VfY2F0ZWdvcnksIGRhdGE9IGRhdGFfZm9yX2FscGhhKQ0KYGBgDQoNCkV2ZW4gdGhvdWdoIG9uZSBhc3N1bXB0aW9uIGlzIG1ldCAoaG9tLnZhci4pIHdlIHNob3VsZCBub3QgdXNlIEFOT1ZBIC0gdGhlIGFzc3VtcHRpb24gb2YgaG9tb2dlbmVpdHkgb2YgdmFyaWFuY2UgaXMgYW4gZXh0ZW5zaW9uIG9mIHRoZSBhc3N1bXB0aW9uIG9mIG5vcm1hbGl0eS4gSXQgd291bGQgbm90IGJlIGZlYXNpYmxlIHRvIGNvbXBhcmUgYSBza2V3ZWQgZGlzdHJpYnV0aW9uIGluIG9uZSBncm91cCB0byBhIG5vcm1hbCBkaXN0cmlidXRpb24gaW4gYW5vdGhlciBncm91cCwgZXZlbiBpZiB0aGV5IGhhdmUgY29tcGFyYWJsZSB2YXJpYW5jZXMhDQoNCktydXNrYWwtV2FsbGlzIHRlc3QgY29uZmlybXMgZGlmZmVyZW5jZXMgaW4gc2hhbm5vbidzIGluZGV4LiBXZSBkbyBwb3N0LWhvYyBkaWFnbm9zaW5nIHRvIHNlZSB3aGljaCBncm91cHMgYXJlIGRpZmZlcmVudCB3aXRoIGEgRHVubiB0ZXN0LiBUaGUgZGlmZmVyZW5jZSB3aGljaCBpcyBzdGF0aXN0aWNhbGx5IHNvdW5kIGlzIHRoZSBkaXZlcnNpdHkgbGV2ZWxzIGJldHdlZW4gdGhlIHNvdXJjZSAzIHNhbXBsZXMgYW5kIHRoZSBTaW5rLCBhZnRlciBhZGp1c3RpbmcgdGhlIHAtdmFsdWUuDQoNClNpbmNlIHNvdXJjZSAzIGNvbnNpc3RzIG9mIHNvaWwgc2FtcGxlcywgaXQgaXMgbm90IHVuZXhwZWN0ZWQgdGhhdCBpdCB3b3VsZCBoYXZlIGhpZ2hlciBkaXZlcnNpdHkuDQoNCg0KIyBCZXRhIGRpdmVyc2l0eQ0KYGBge3IsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFfQ0KYmNfZGlzcyA8LSB2ZWdkaXN0KHQoYXN2X3RhYmxlKSwgbWV0aG9kID0gImJyYXkiKQ0Kbm1kcyA8LSBtZXRhTURTKGJjX2Rpc3MpDQoNCg0KIyBtYWtlIHBhbGV0dGUgZm9yIHBsb3R0aW5nDQpwYWwgPSBjKCJncmVlbjQiLCAibmF2eSIsICJvcmFuZ2UiLCAiYnJvd24iLCAiYmx1ZSIsICJsaWdodGJsdWUiKQ0KDQoNCiMgbGV0cyBwbG90IGFuIG5tZHMgd2hlcmUgdGhlIGNvbG9yIGlzIHNhbXBsZSB0eXBlLCBzaGFwZSBpcyBzb3VyY2Ugc2luaw0KYXMuZGF0YS5mcmFtZShubWRzJHBvaW50cykgJT4lIA0KICBjYmluZChkYXRhX2Zvcl9hbHBoYSRTb3VyY2VfY2F0ZWdvcnksIG1ldGFkYXRhX3R5cGUkdHlwZV9JSUkpICU+JSANCiAgcmVuYW1lKCJzb3VyY2VfY2F0IiA9ICJkYXRhX2Zvcl9hbHBoYSRTb3VyY2VfY2F0ZWdvcnkiLA0KICAgICAgICAgInR5cGUiID0gIm1ldGFkYXRhX3R5cGUkdHlwZV9JSUkiKSAlPiUgDQogIG11dGF0ZShzb3VyY2VfY2F0ID0gY2FzZV93aGVuKHNvdXJjZV9jYXQgPT0gIlNpbmsiIH4gInNpbmsiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gInNvdXJjZSIpKSAtPiAgZGF0YV9mb3Jfbm1kcw0KICANCiMgcGxvdCANCmRhdGFfZm9yX25tZHMgJT4lICAgDQogIGdncGxvdChhZXMoeCA9IE1EUzEsIHkgPSBNRFMyKSkgKw0KICBnZW9tX3BvaW50KGFlcyhmaWxsID0gdHlwZSwgY29sb3IgPSB0eXBlLCANCiAgICAgICAgICAgICAgICAgc2hhcGU9IHNvdXJjZV9jYXQpLCANCiAgICAgICAgICAgICBzaXplID0gNSwgc3Ryb2tlPTEsIGFscGhhID0gMC42KSArDQojIGN1c3RvbWl6aW5nIHRoZSBwbG90ICANCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gIHBhbCkgKyANCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbCkgKw0KICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygyMSwyMykpICsNCiAgDQogIHRoZW1lX2xpbmVkcmF3KCkgKw0KICBhbm5vdGF0ZShnZW9tPSJ0ZXh0Iix4PS0xLjQsIHk9MS41LCBsYWJlbD0ic3RyZXNzID0iLCBjb2xvcj0iYmxhY2siKSArICAgDQogIGFubm90YXRlKGdlb209InRleHQiLCB4PS0xLjEsIHk9MS41LCBsYWJlbD1yb3VuZChubWRzJHN0cmVzcyw0KSwNCiAgICAgICAgICAgY29sb3I9ImJsYWNrIikgKw0KICANCiAgI3N0YXRfZWxsaXBzZShhZXMoY29sb3VyID0gdHlwZSksIGxpbmV3aWR0aCA9IDAuMykgKyANCiAgI3N0YXRfZWxsaXBzZShhZXMoZmlsbCA9IHR5cGUpLCBnZW9tPSJwb2x5Z29uIixsZXZlbD0wLjk1LGFscGhhPTAuMDQpICsNCiAgDQogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBsZWdlbmQuYm94LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyYXkiKSkgKw0KICBsYWJzKGNvbG9yID0gIldhdGVyIFxudHlwZSIsIHNoYXBlID0gIlNvdXJjZSIpICsNCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDApLCBjb2xvciA9ICJncmV5NzAiLCBsaW5ldHlwZSA9IDIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYygwKSwgY29sb3IgPSAiZ3JleTcwIiwgbGluZXR5cGUgPSAyKSAtPiBwbG90X25tZHMNCiAgDQoNCg0KDQpgYGANCg0KVGhlcmUgd2FzIGNsZWFyIGdyb3VwaW5nIG9mIHNvaWwgYW5kIHNlZGltZW50IGNvbW11bml0aWVzLiANClN1cmZhY2Ugd2F0ZXIsIHNwcmluZyB3YXRlciBhbmQgYmlvZmlsbSBjb21tdW5pdGllcyB3ZXJlIG1vcmUgc3ByZWFkIG91dCwgYW5kIG1vcmUgZGlzc2ltaWxhciB0byBzb2lsIHRoYW4gdG8gc2VkaW1lbnQNCmNvbW11bml0aWVzLg0KDQpPdXQgb2YgZml2ZSBzaW5rcywgZm91ciB3YXRlciBhbmQgb25lIHNlZGltZW50IHNpbmssIHRoZSBtb3N0IHNpbWlsYXIgdG8gc2VkaW1lbnQgc291cmNlIHNhbXBsZXMsIGluIHRlcm1zIG9mIGNvbW11bml0eSBhc3NlbWJseSwgd2FzIHRoZSBzZWRpbWVudCBzaW5rLiBJdCBpcyBhbHNvIGNsb3NlciB0byB0aGUgc29pbCBzb3VyY2VzLCB3aGVyZWFzIHdhdGVyIHNpbmtzIGNvbW11bml0aWVzIHNob3dlZCBsaXR0bGUgc2ltaWxhcml0eSB0byBzb2lsIHNvdXJjZXMuDQoNCmBgYHtyfQ0KcGxvdF9ubWRzDQpgYGANCg0KIyMgVGVzdCBjb21tdW5pdHkgZGlmZmVyZW5jZXMNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgbWVzc2FnZT1GQUxTRX0NCiMgdGVzdCBkaWZmZXJlbmNlcyBpbiBncm91cCBjZW50cm9pZCB3aXRoIGFkb25pcyAoYW5vdmEgdmVyc2lvbiBmb3IgbXVsdGl2YXJpYXRlIHN0YXRpc3RpY3MpDQpwZXJtYW5vdmEgPC0gYWRvbmlzMih0KGFzdl90YWJsZSkgfiBkYXRhX2Zvcl9ubWRzJHR5cGUsIA0KICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiYnJheSIgLCBwZXJtdXRhdGlvbnMgPSA5OTkpDQpwZXJtYW5vdmEgIyAwLjAwMQ0KcGFpcl9yZXMgPC0gcGFpcndpc2VBZG9uaXM6OnBhaXJ3aXNlLmFkb25pczIodChhc3ZfdGFibGUpIH4gdHlwZSwgZGF0YSA9IGRhdGFfZm9yX25tZHMpDQojIFNwcmluZ192c19TdXJmYWNlLCBHV192c19TcHJpbmcgYXJlIG9ubHkgb25lIG5vdCBzaWduaWZpY2FudGx5IGRpc3RpbmN0ISENCg0KDQojIHRlc3QgZGlzcGVyc2lvbiBhcyBhbiBhc3N1bXB0aW9uICh2YXJpYW5jZSB0ZXN0IGZvciBtdWx0aXZhcmlhdGUgc3RhdGl0aWNzKQ0KZGlzcCA8LSBiZXRhZGlzcGVyKCB2ZWdkaXN0KCAgdChhc3ZfdGFibGUpLCBtZXRob2QgPSAiYnJheSIgKSwgZGF0YV9mb3Jfbm1kcyR0eXBlKSANCmFub3ZhKGRpc3ApDQpUdWtleUhTRChkaXNwKSANCiMgU3VyZmFjZS1HVyBoYXZlIGRpZmYgZGlzcGVyc2lvbnMsIGRvZXMgbm90IGludGVyZmVyZSB3aXRoIGNlbnRyb2lkIGRpZmZlcmVuY2VzDQoNCiANCmBgYA0KDQoNClRoZXJlIGlzIHNpZ25pZmlpY2FudCBkaWZmZXJlbmNlIGluIGNvbW11bml0aWVzIG9mIGRpZmZlcmVudCBzYW1wbGUgdHlwZSAoKioqKS4NCkJpb2ZpbG0sIHNlZGltZW50IGFuZCBzb2lsIGFyZSBkaXN0aW5jdGx5IGRpZmZlcmVudCBmcm9tIGVhY2ggb3RoZXIgYW5kIGZyb20gc3VyZmFjZSB3YXRlciwgZ3JvdW5kd2F0ZXIgYW5kIHNwcmluZy4NClN1cmZhY2Ugd2F0ZXIsIGdyb3VuZHdhdGVyIGFuZCBzcHJpbmcgYXJlIG5vdCBlYXNpbHkgaWRlbnRpZmlhYmxlIGJldHdlZW4gdGhlbXNlbHZlcy4NCg0KDQojIEVudmlyb25tZW50YWwgZGF0YQ0KDQojIyBwY2EgKGVudmlyb25tZW50YSB2YXJpYWJsZXMgb2Ygd2F0ZXIgY29tbXVuaXRpZXMpDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCmRmX3BjYSA8LSBtZXRhZGF0YSAlPiUgDQogICMgd2Ugb25seSBoYXZlIG1lYXN1cmVtZW50cyBmb3Igd2F0ZXIsIG5vdCBmb3Igc29pbCBub3Igc2VkaW1lbnQgDQogIGZpbHRlcih0eXBlX0kgPT0gIldhdGVyIikgJT4lIA0KICBzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpICU+JSANCiAgc2VsZWN0KC1jKCJmaWx0ZXIiLCAjIGRvbnQgbmVlZCBpdA0KICAgICAgICAgICAgIk5fTk8yIiwgIlBfUE80IikpICMgTkFzDQogDQoNCiMgcmVtb3ZlIHRoZSBoaWdobHkgY29ycmVsYXRlZCBvbmVzLCBsaWtlIGludGVybmFsQVRQIGFuZCB0b3RhbEFUUA0KY29yX21hdHJpeCA8LSBjb3IoZGZfcGNhKQ0KaGlnaGx5X2NvcnJlbGF0ZWQgPC0gY2FyZXQ6OmZpbmRDb3JyZWxhdGlvbihjb3JfbWF0cml4LCBjdXRvZmYgPSAwLjkpDQpkZl9wY2EgPC0gZGZfcGNhWywgLWhpZ2hseV9jb3JyZWxhdGVkXQ0KDQojIG5vdyB0aGVyZSBpcyAyMiBvYnNlcnZhdGlvbnMgYW5kIDEwIGVudmlyb25tZW50YWwgdmFyaWFibGVzDQojIGxldHMgc2VlIGlmIGFueSBlbnYgdmFycyBjYW4gYmUgcGFja2VkIG5lYXRseSBpbiBQQ3MNCnBjYV9lbnYgPC0gcHJjb21wKGRmX3BjYSwgc2NhbGUgPSBUUlVFKQ0KYmlwbG90KHBjYV9lbnYpDQoNCiMgaSBiZWxpZXZlIGl0IGlzIGJlbmVmaWNpYWwgdG8gcmVtb3ZlIHRoZSBzYW1wbGUgUFhfZ3cgc2luY2UgaXQgaXMgYSBzaW5nbGUgb3V0bGllciBpbiBhbG1vc3QgZXZlcnkgdmFyaWFibGUsIGFuZCBzdHJlc3NlcyB0aGUgb3JkaW5hdGlvbg0KcGNhX2VudiA8LSBwcmNvbXAoZGZfcGNhW3Jvd25hbWVzKGRmX3BjYSkgIT0gIlBYX2d3IixdLCBzY2FsZSA9IFRSVUUpDQoNCg0KIyB3ZSBuZWVkIHRoZSBjb2x1bW4gZm9yIGNvbG9yaW5nIGJ5IHR5cGUsIGdldCBpdCBmcm9tIHRoZSBvcmlnaW5hbCBtZXRhZGF0YQ0KIG1ldGFkYXRhW3Jvd25hbWVzKGRmX3BjYSkgIT0gIlBYX2d3IiwgYyhjb2xuYW1lcyhkZl9wY2EpLCAidHlwZV9JSUkiLCAidHlwZV9JIildICU+JSANCiAgICMgcmVtb3ZlIHRoZSBvdXRsaWVyIHNhbXBsZSwgdGhlIGNvbHVtbnMgdGhhdCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgYW5kIHNvaWwvc2VkIHNhbXBsZXMNCiAgZmlsdGVyKHR5cGVfSSA9PSAiV2F0ZXIiKSAtPiBkYXRhX2Zvcl9wY2ENCg0KYXV0b3Bsb3QocGNhX2VudiwgZGF0YSA9ZGF0YV9mb3JfcGNhICwgDQogICAgICAgICBjb2xvdXIgPSAndHlwZV9JSUknLA0KICAgICAgICAgc2l6ZT01LCBsb2FkaW5ncz1UUlVFLCANCiAgICAgICAgIGxvYWRpbmdzLmNvbG91cj0iYmxhY2siLCANCiAgICAgICAgIGxvYWRpbmdzLmxhYmVsPVRSVUUsIGxvYWRpbmdzLmxhYmVsLnNpemU9NSwgDQogICAgICAgICBsb2FkaW5ncy5sYWJlbC5jb2xvdXI9ImJsYWNrIiApKyANCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygwKSwgY29sb3IgPSAiZ3JleTcwIiwgbGluZXR5cGUgPSAyKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGMoMCksIGNvbG9yID0gImdyZXk3MCIsIGxpbmV0eXBlID0gMikgKw0KICBnZW9tX3BvaW50KHNoYXBlPSAyMSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNSkgKyANCiAgdGhlbWVfbGluZWRyYXcoKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoMCksIGNvbG9yID0gImdyZXk3MCIsIGxpbmV0eXBlID0gMikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKDApLCBjb2xvciA9ICJncmV5NzAiLCBsaW5ldHlwZSA9IDIpICsNCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiQWNjZW50IikrDQogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBsZWdlbmQuYm94LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyYXkiKSkgIC0+IHBjYV9wbG90DQoNCnBjYV9wbG90DQpgYGANCg0KDQoNCg0KDQpUaGUgZmlyc3QgdGhyZWUgY29tcG9uZW50cyBoYXZlIDErIHZhcmlhbmNlIGV4cGxhbmF0aW9uLiBTZWUgbW9yZSBkZXRhaWxlZCB3aGF0IFBDMSwgUEMyIGFuZCBQQzMgKGFzIGNvbWJpbmF0aW9ucyBvZiBlbnZpcm9ubWVudGFsIHZhcmlhYmxlcykgY29uc2lzdCBvZi4NCg0KDQpub3JtYWwgZGF0YTogdmFyaWFuY2UgPSAoc3QuZGV2KV4yIHBjYSBkYXRhOiBlaWdlbnZhbHVlID0gKHN0LmRldileMg0K4oCcZWlnZW52YWx1ZXMgcmVwcmVzZW50IHRoZSB2YXJpYW5jZSBleHBsYWluZWQgYnkgZWFjaCBwcmluY2lwYWwgY29tcG9uZW504oCdIC0+IGVpZ2VuIH4gdmFyaWFuY2UNCg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naG9sZCd9DQoNCiMgRXh0cmFjdCB0aGUgbG9hZGluZ3MgZnJvbSB0aGUgUENBIHJlc3VsdCBhbmQgY29udmVydCB0byB0aWR5IGZvcm1hdCANCmxvYWRpbmdzX2RmIDwtICAgdGlkeShwY2FfZW52LCBtYXRyaXggPSAicm90YXRpb24iKQ0KDQoNCiMgUEMxDQojIENyZWF0ZSB0aGUgZ2dwbG90MiBvYmplY3QgZm9yIHBsb3R0aW5nIHRoZSBsb2FkaW5ncw0KbG9hZGluZ3NfZGYgJT4lIGZpbHRlcihQQyA9PSAiMSIpICU+JSANCiAgI3g9cmVvcmRlcihjbGFzcywtYW1vdW50LHN1bSkNCmdncGxvdCggYWVzKHggPSByZW9yZGVyKGNvbHVtbiwgLXZhbHVlKSwgeSA9IHZhbHVlLCBncm91cCA9IGZhY3Rvcihjb2x1bW4pKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCANCiAgICAgICAgICAgZmlsbD0gImdyYXk5MCIsIGNvbG9yID0gImdyYXkyMCIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNvbHVtbiksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCANCiAgICAgICAgICAgICN2anVzdCA9ICJpbndhcmQiLCAgDQogICAgICAgICAgICBhbmdsZSA9IDkwICwgaGp1c3QgPSAiaW53YXJkIikgKw0KICBsYWJzKHggPSAiVmFyaWFibGVzIG9mIFBDMSIsIHkgPSAiTG9hZGluZ3MiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICAtPiBwbG90X3BjYTENCg0KIyBQQzIgDQpsb2FkaW5nc19kZiAlPiUgZmlsdGVyKFBDID09ICIyIikgJT4lIA0KICAjeD1yZW9yZGVyKGNsYXNzLC1hbW91bnQsc3VtKQ0KZ2dwbG90KCBhZXMoeCA9IHJlb3JkZXIoY29sdW1uLCAtdmFsdWUpLCB5ID0gdmFsdWUsIGdyb3VwID0gZmFjdG9yKGNvbHVtbikpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIA0KICAgICAgICAgICBmaWxsPSAiZ3JheTkwIiwgY29sb3IgPSAiZ3JheTIwIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY29sdW1uKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIA0KICAgICAgICAgICAgI3ZqdXN0ID0gImlud2FyZCIsICANCiAgICAgICAgICAgIGFuZ2xlID0gOTAgLCBoanVzdCA9ICJpbndhcmQiKSArDQogIGxhYnMoeCA9ICJWYXJpYWJsZXMgb2YgUEMyIiwgeSA9ICJMb2FkaW5ncyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgLT4gcGxvdF9wY2EyDQoNCiMgUEMzDQpsb2FkaW5nc19kZiAlPiUgZmlsdGVyKFBDID09ICIzIikgJT4lIA0KICAjeD1yZW9yZGVyKGNsYXNzLC1hbW91bnQsc3VtKQ0KZ2dwbG90KCBhZXMoeCA9IHJlb3JkZXIoY29sdW1uLCAtdmFsdWUpLCB5ID0gdmFsdWUsIGdyb3VwID0gZmFjdG9yKGNvbHVtbikpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIA0KICAgICAgICAgICBmaWxsPSAiZ3JheTkwIiwgY29sb3IgPSAiZ3JheTIwIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY29sdW1uKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIA0KICAgICAgICAgICAgI3ZqdXN0ID0gImlud2FyZCIsICANCiAgICAgICAgICAgIGFuZ2xlID0gOTAgLCBoanVzdCA9ICJpbndhcmQiKSArDQogIGxhYnMoeCA9ICJWYXJpYWJsZXMgb2YgUEMzIiwgeSA9ICJMb2FkaW5ncyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgLT4gcGxvdF9wY2EzDQoNCnBsb3RfcGNhMSArIHBsb3RfcGNhMiArIHBsb3RfcGNhMw0KYGBgDQoNCg0KVGVzdCBwY2EgZGlzcGVyc2lvbnMuDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCiMgd2UgY2FuIGNoZWNrIHRoZSBzaWduaWZpY2FuY2UgaW4gZGlmZmVyZW5jZSBiZXR3ZWVuIGdyb3VwcyBpbiBib3RoIHBjYSBhbmQgbm1kcw0KDQpldWNsaWRlYW5fZGlzdCA8LSBkYXRhX2Zvcl9wY2EgJT4lIHNlbGVjdCgtYygidHlwZV9JIiAsICJ0eXBlX0lJSSIpKSAlPiUgDQogICAgICAgICAgICAgICAgICBzY2FsZSgpICU+JSBhcy5kYXRhLmZyYW1lKCkgICU+JSANCiAgICAgICAgICAgICAgICAgIGRpc3QoLiwgbWV0aG9kID0gImV1Y2xpZGVhbiIpIA0KDQpkaXNwX3BjYSA8LSBiZXRhZGlzcGVyKCBldWNsaWRlYW5fZGlzdCwgZGF0YV9mb3JfcGNhJHR5cGVfSUlJICkNCmFub3ZhKGRpc3BfcGNhKSAjbm8gc2lnbi4gZGlmZmVyZW5jZXMgDQoNCg0KZGlzcF9wY2EkZGlzdGFuY2VzICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICByZW5hbWUoIkRpc3RhbmNlIiA9ICIuIikgJT4lIA0KICByb3duYW1lc190b19jb2x1bW4oInNhbXBsZV9pZCIpICU+JSANCiAgY2JpbmQoZGF0YV9mb3JfcGNhKSAlPiUgDQojIHBsb3QNCiAgZ2dwbG90KCBhZXMoeCA9IHR5cGVfSUlJLCB5ID0gRGlzdGFuY2UpKSArDQogIGdlb21fYm94cGxvdCggZmlsbCA9ICJ2aW9sZXQiKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiRW52aXJvbm1lbnRhbCBkaWZmZXJlbmNlcyBcbnN0YW5kYXJkaXplZCBFdWNsaWRlYW4gZGlzdGFuY2UiKSArDQogIHRoZW1lX2xpbmVkcmF3KCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgLT4gcGNhX2Rpc3ANCg0KYGBgDQoNCiMjIG5tZHMgKHdhdGVyIGNvbW11bml0aWVzKQ0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQ0KDQphc3Zfd2F0ZXIgPC0gYXN2X3RhYmxlIFsscm93bmFtZXMoZGZfcGNhKV0gJT4lIHNlbGVjdCghIlBYX2d3IikNCmJjX2Rpc3Nfd2F0ZXIgPC0gdmVnZGlzdCh0KGFzdl93YXRlciksIG1ldGhvZCA9ICJicmF5IikNCm5tZHNfd2F0ZXIgPC0gbWV0YU1EUyhiY19kaXNzX3dhdGVyKQ0KDQoNCmBgYA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naG9sZCd9DQoNCmFzLmRhdGEuZnJhbWUobm1kc193YXRlciRwb2ludHMpICU+JSANCiAgY2JpbmQoZGF0YV9mb3JfcGNhJHR5cGVfSUlJKSAlPiUgDQogIHJlbmFtZSgidHlwZSIgPSAiZGF0YV9mb3JfcGNhJHR5cGVfSUlJIikgJT4lIA0KICANCiMgcGxvdCANCiAgZ2dwbG90KGFlcyh4ID0gTURTMSwgeSA9IE1EUzIpKSArDQogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSB0eXBlKSwgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgc2l6ZSA9IDUsIGNvbG9yPSAiYmxhY2siICkgKw0KIyBjdXN0b21pemluZyB0aGUgcGxvdCAgDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiQWNjZW50IikgKw0KICB0aGVtZV9saW5lZHJhdygpICsNCiAgYW5ub3RhdGUoZ2VvbT0idGV4dCIseD0tMS40LCB5PTEuNSwgbGFiZWw9InN0cmVzcyA9IiwgY29sb3I9ImJsYWNrIikgKyAgIA0KICBhbm5vdGF0ZShnZW9tPSJ0ZXh0IiwgeD0tMS4xLCB5PTEuNSwgbGFiZWw9cm91bmQobm1kc193YXRlciRzdHJlc3MsNCksDQogICAgICAgICAgIGNvbG9yPSJibGFjayIpICsNCiAgDQogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBsZWdlbmQuYm94LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyYXkiKSkgKw0KICBsYWJzKGNvbG9yID0gIldhdGVyIFxudHlwZSIsIHNoYXBlID0gIlNvdXJjZSIpICsNCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDApLCBjb2xvciA9ICJncmV5NzAiLCBsaW5ldHlwZSA9IDIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYygwKSwgY29sb3IgPSAiZ3JleTcwIiwgbGluZXR5cGUgPSAyKSAtPiBubWRzX3Bsb3Rfd2F0ZXINCiAgDQoNCg0KZXVjbGlkZWFuX2Rpc3QgPC0gZGF0YV9mb3JfcGNhICU+JSBzZWxlY3QoLWMoInR5cGVfSSIgLCAidHlwZV9JSUkiKSkgJT4lIA0KICAgICAgICAgICAgICAgICAgc2NhbGUoKSAlPiUgYXMuZGF0YS5mcmFtZSgpICAlPiUgDQogICAgICAgICAgICAgICAgICBkaXN0KC4sIG1ldGhvZCA9ICJldWNsaWRlYW4iKSANCg0KZGlzcF9ubWRzIDwtIGJldGFkaXNwZXIoIGJjX2Rpc3Nfd2F0ZXIsIGRhdGFfZm9yX3BjYSR0eXBlX0lJSSApDQphbm92YShkaXNwX25tZHMpICMgc2lnbi4gZGlmZmVyZW5jZXMgDQoNCg0KZGlzcF9ubWRzJGRpc3RhbmNlcyAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgcmVuYW1lKCJEaXN0YW5jZSIgPSAiLiIpICU+JSANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGVfaWQiKSAlPiUgDQogIGNiaW5kKGRhdGFfZm9yX3BjYSkgJT4lIA0KIyBwbG90DQogIGdncGxvdCggYWVzKHggPSB0eXBlX0lJSSwgeSA9IERpc3RhbmNlKSkgKw0KICBnZW9tX2JveHBsb3QoIGZpbGwgPSAidmlvbGV0IikgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gIkJyYXktY3VydGlzIGRpc3RhbmNlIikgKw0KICB0aGVtZV9saW5lZHJhdygpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpIC0+IG5tZHNfd2F0ZXJfZGlzcA0KDQoNCiBubWRzX3Bsb3Rfd2F0ZXIgICsgcGNhX3Bsb3QgKw0KICBubWRzX3dhdGVyX2Rpc3AgKyBwY2FfZGlzcCANCmBgYA0KDQoNCkxha2UgY29tbXVuaXRpZXMgYW5kIGdyb3VuZHdhdGVyIGNvbW11bnRpZXMgc2VlbSB0byBoYXZlIHJlbGF0aXZlbHkgZGlzdGluY3QgbWljcm9iaWFsIGNvbXBvc2l0aW9uLg0KVGhlIGh5cG9yaGVpYywgcG9uZCBhbmQgaW5mbG93IHdhdGVyIGNvbnNpc3Qgb25seSBvZiBvbmUgc2FtcGxlIHBvaW50LCB3aGVuIHdlIHJlbW92ZSB0aGUgc29pbCBhbmQgc2VkaW1lbnQgc2FtcGxlcyBmb3IgdGhpcyBhbmFseXNpcywgc28gaXQgaXMgbm90IHBvc3NpYmxlIHRvIGRyYXcgY29uY2x1c2lvbnMuIEJ1dCB0aGUgcmVzdCBvZiB0aGUgc2FtcGxlcyBoYXZlIGEgc2ltaWxhciByZWxhdGlvbiBmb3IgYm90aCB0aGUgZW52aXJvbm1lbnRhbCB2YXJpYXRvbiBhbmQgdGhlIGNvbW11bml0eSB2YXJpYXRpb24gLSBlbnZpcm9ubWVudGFsIGhvbW9nZW5laXR5IG9mIHRoZSBncm91bmR3YXRlciBzYW1wbGVzIGluIHZpc2libGUgaW4gdGhlIGxvdyBkaXNwZXJzaW9uIG9mIHRoZSBncm91bmR3YXRlciBtaWNyb2JpYWwgY29tbXVuaXRpZXMuIChjaGVjayBzaWduaWZpY2FuY2UgYW5kIHB1dCBvbiBwbG90IGxhdGVyKSANCg0KIyMgQ29uc3RyYWluZWQgb3JkaWFudGlvbg0KDQpDQVAgb3JkaW5hdGlvbiBhcyBhbiBkaXN0YW5jZS1iYXNlZCBhbHRlcm5hdGl2ZSB0byB0aGUgUkRBICh3aGljaCB1c2VzIGJyYXksIGFzIG9wcG9zZWQgdG8gUkRBJ3MgZXVjbGlkZWFuKS4NCkhlbGxpbmdlciB0cmFuc2Zvcm1hdGlvbiAoc3F1YXJlIHJvb3Qgb2YgcmVsYXRpdmUgYWJ1bmRhbmNlcykgaXMgdXNlZCB0byBhY2NvdW50IGZvciBjb21wb3NpdGlvbmFsaXR5IG9mIGRhdGEuIA0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hvbGQnfQ0KDQpkYXRhX2Zvcl9wY2EgJT4lIHNlbGVjdCh3aGVyZShpcy5udW1lcmljKSkgJT4lIA0KICBzY2FsZSgpICU+JSBhcy5kYXRhLmZyYW1lKCkgLT4gZW52LmRhdGENCg0KZGVjb3N0YW5kKHQoYXN2X3dhdGVyKSwgbWV0aG9kID0gImhlbGxpbmdlciIpIC0+IHNwLmRhdA0KDQojIGNoZWNrDQppZGVudGljYWwocm93bmFtZXMoZW52LmRhdGEpLCBjb2xuYW1lcyhhc3Zfd2F0ZXIpKSAjVFJVRQ0KDQojIHBlcmZvcm0gbW9kZWwNCnNpbXBsZVJEQSA8LSBjYXBzY2FsZShzcC5kYXQgfiAgLiwgZGF0YT1lbnYuZGF0YSAsDQogICAgICAgICAgICAgICAgIGRpc3RhbmNlID0gImJyYXkiKQ0KDQp2aWYuY2NhKHNpbXBsZVJEQSkgIyBhbGwgdmFyaWFibGVzIGxvd2VyIHRoYW4gMTANCg0KDQojIHRlc3QNCg0KIyB0ZXN0IGVudiBwYWFtZXRlcnMNCmFub3ZhLm1vZGVsMyA8LSBhbm92YShzaW1wbGVSREEsIHN0ZXA9MTAwMCwgYnkgPSAidGVybSIpDQphbm92YS5tb2RlbDMNCiMgc2lnbjogYml4KiAsIGZpKioqLCBUQ0MqKiosIENvbmQsIE8yKiosICBUZW1wKg0KDQojIG5ldyBtb2RlbCANCnNpbXBsZVJEQSA8LSBjYXBzY2FsZShzcC5kYXQgfiAgYml4ICsgZmkgKyBUQ0MgKyBDb25kICsgTzIgKyBUZW1wLCBkYXRhPWVudi5kYXRhICwNCiAgICAgICAgICAgICAgICAgZGlzdGFuY2UgPSAiYnJheSIpDQojIHRlc3QgZW52IHBhYW1ldGVycw0KYW5vdmEubW9kZWwzIDwtIGFub3ZhKHNpbXBsZVJEQSwgc3RlcD0xMDAwLCBieSA9ICJ0ZXJtIikNCg0KIyB0ZXN0IG9mIGFsbCBjYW5vbmljYWwgYXhlcw0KYW5vdmEubW9kZWwgPC0gYW5vdmEuY2NhKHNpbXBsZVJEQSwgYnk9J2F4aXMnLCBzdGVwPTEwMDApICAjIENBUDEsQ0FQMixDQVAzIHNpZ25pZmljYW50IA0KDQojIHRlc3QgdGhlIHdob2xlIG1vZGVsDQphbm92YS5tb2RlbDIgPC0gYW5vdmEuY2NhKHNpbXBsZVJEQSwgc3RlcD0xMDAwKSAjIHNpZ24NClJzcXVhcmVBZGooc2ltcGxlUkRBKSRhZGouci5zcXVhcmVkICMgZXhwbGFpbnMgMzAlDQoNCmBgYA0KDQpXZSBjYW4gc2F5IHRoYXQgYml4IGFuZCBmaXgsIGFzIHdlbGwgYXMgdGhlIHRlbWVwcmF0dXJlLCBveHlnZW4gYW5kIGNvbmR1Y3Rpdml0eSBoYXZlIGFuIGltcGFjdCBvbiB0aGUgbWljcm9iaWFsIGNvbW11bml0aWVzIG9mIEx1bnkgd2F0ZXIgYm9kaWVzLiBBZGRpdGlvbmFsbHksIHRoZSBudW1iZXIgb2YgVENDIChtaWNyb2JpYWwgbG9hZCkgaW4gdGhlIHdhdGVyIGJvZHkgaXMgYWxzbyBhIHNpZ25pZmljYW50IGluZGljYXRvciBvZiB0aGUgd2F0ZXIgY29tbXVuaXR5IGNvbXBvc2l0aW9uLg0KDQoNCg0KUGxvdCB0aGUgY29uc3RyYWluZWQgb3JkaW5hdGlvbiBpZiB3ZSB3YW50IHRvIGJ1dCBpdCBjb3VsZCBiZSBhIGJpdCByZWR1bmRhZG50IGNvbnNpZGVyaW5nIHRoZSBpbmRpdmlkdWFsIG9yZGluYXRpb25zIG9mIGVudmlyb25tZW50YWwgdmFyaWFibGVzIGFuZCBjb21tdW5pdGlpZXMuIE9uIHRoZSBvdGhlciBoYW5kLCB0aGUgdmlzdWFsIGRlcGljdGlvbiBpbXBsaWVzIG5lZWQgZm9yIG1vcmUgc2FtcGxlIHBvaW50cywgY29uc2lkZXJpbmcgaG93IHNwYXJzZSB0aGUgb3JkaW5hdGlvbiBpcy4NCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdob2xkJ30NCiMgdmVjdG9ycw0KY2NhdmVjdG9ycyA8LSBhcy5tYXRyaXgoc2NvcmVzKHNpbXBsZVJEQSwgZGlzcGxheSA9ICJicCIsIHNjYWxpbmcgPSAic2l0ZXMiKSozLjMyKSAlPiUgDQogIHQoKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgcmVuYW1lKCJiaXgqIiA9ICJiaXgiLA0KICAgICAgICAgIlRlbXAqIiA9ICJUZW1wIiwNCiAgICAgICAgICJPMioqIiA9ICJPMiIsDQogICAgICAgICAiZmkqKioiID0gImZpIiwNCiAgICAgICAgICJUQ0MqKioiID0gIlRDQyIpICU+JQ0KICB0KCkgJT4lIGFzLmRhdGEuZnJhbWUoKQ0KDQojYml4KiAsIGZpKioqLCBUQ0MqKiosIENvbmQsIE8yKiosICBUZW1wKg0KDQoNCiMgc2l0ZSBjb29yZGluYXRlcw0Kc2l0ZV9kYXRhIDwtIHNjb3JlcyhzaW1wbGVSREEsIGRpc3BsYXkgPSAic2l0ZXMiKSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIGNiaW5kKC4sIGRhdGFfZm9yX3BjYSR0eXBlX0lJSSkgJT4lIA0KICByZW5hbWUoInR5cGUiID0gImRhdGFfZm9yX3BjYSR0eXBlX0lJSSIpDQoNCiMgcGxvdHRpbmcNCnBsb3RfY2NhIDwtIA0KICBzaXRlX2RhdGEgJT4lIA0KICBnZ3Bsb3QoIGFlcyh4ID0gQ0FQMSwgeSA9IENBUDIpKSArDQogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSB0eXBlKSwgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgc2l6ZSA9IDUsIGNvbG9yPSAiYmxhY2siICkrICANCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBjY2F2ZWN0b3JzLCBhZXMoeCA9IDAsIHkgPSAwLCB4ZW5kID0gQ0FQMSwgeWVuZCA9IENBUDIpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjIsIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgwLjUsICJjbSIpKSkgKw0KICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygwKSwgY29sb3IgPSAiZ3JleTcwIiwgbGluZXR5cGUgPSAyKSArDQogICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKDApLCBjb2xvciA9ICJncmV5NzAiLCBsaW5ldHlwZSA9IDIpICsNCiAgZ2VvbV90ZXh0KGRhdGEgPSBjY2F2ZWN0b3JzLCBhZXMoeCA9IENBUDEqMS4yLCB5ID0gQ0FQMioxLjEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHJvd25hbWVzKGNjYXZlY3RvcnMpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT02ICkgKw0KICB0aGVtZV9saW5lZHJhdygpICsNCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJBY2NlbnQiKSArDQogICAgIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICBsZWdlbmQuYm94LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyYXkiKSkgDQoNCnBsb3RfY2NhDQpgYGANCg0KVGhlcmUgaXMgY2VydGFpbiBpbmRpY2F0aW9uIHRoYXQgbWljcm9iaWFsIGNvbW11bml0eSBhc3NlbWJseSBvZiBMdW56IGxha2VzIHdhdGVyIHNhbXBsZXMgYW5kIG5lYXIgd2F0ZXIgYm9kaWVzIGlzIG5vdCBpbXBhY3RlZCBieSB0aGUgZW52aXJvbm1lbnRhbCB2YXJpYWJsZXMgd2hpY2ggd2VyZSBtZWFzdXJlZCBpbiB0aGlzIHN0dWR5LiBIb3dldmVyLCB0aGUgc2FtcGxlIHR5cGUgcHJvdmlkZWQgYSBjbGVhcmVyIGltcGFjdCBvbiBjb21tdW5pdHkNCmFzc2VtYmx5LiBTYW1wbGVzIG9mIHR5cGUgc2VkaW1lbnQsIHNvaWwgYW5kIHN1cmZhY2Ugd2F0ZXIgc2hvd2VkIGNvbW11bml0eSBzaW1pbGFyaXR5IHdpdGhpbiB0aGUgdHlwZSBjYXRlZ29yeS4gVG8gZGV0ZXJtaW5lIHdoZXRoZXIgc2FtcGxlIHR5cGUgaXMgbWVyZWx5IGEgcHJveHkgZm9yIGVjb2xvZ2ljYWwgY29uZGl0aW9ucywgZW52aXJvbm1lbnRhbCB2YXJpYWJsZXMgZm9yIHNhbXBsZXMgb3RoZXIgdGhhbiB3YXRlciBzYW1wbGVzIG5lZWQgdG8gYmUgbWVhc3VyZWQsIHdoaWNoIHdhcyBub3QgdGhlIGNhc2UgaW4gdGhpcyBzdHVkeS4gDQoNCkNvbnRyaWJ1dGlvbiBvZiBzb3VyY2VzIHRvIHNpbmtzIHdhcyBub3QgaW1wYWN0ZWQgYnkgc3BhdGlhbCBkaXN0YW5jZSwgYW5kIHRoZSBhcnRpZmljaWFsIGxha2UgcHJvdmlkZWQgbm8gcGh5c2ljYWwgYmFycmllci4gDQpDb250cmlidXRpb24gYnkgc2FtcGxlIHR5cGUgcHJvdmlkZWQgbW9yZSBhY2N1cmF0ZSBpbnNpZ2h0IHRoYW4gY29udHJpYnV0aW9uIGJ5IOKAnFNvdXJjZeKAnSBjYXRlZ29yeSwgd2hpY2ggd2FzIGFuIGFyYml0cmFyeSBjYXRlZ29yeSBkZXRlcm1pbmVkIGFzIGEgbWl4IG9mIHNhbXBsZSB0eXBlIGFuZCBkaXN0YW5jZSBmcm9tIHRoZSBzaW5rLiANCg0KVGhpcyB3YXMgc2hvd24gd2l0aCBTb3VyY2UgNiBjb250cmlidXRpb24sIGNvbnNpc3Rpbmcgb2Ygc3ByaW5nIHNlZGltZW50IGFuZCB3YXRlci4gU2FtcGxlIHR5cGUgYW5hbHlzaXMgc2hvd2VkIHRoYXQgc3ByaW5nIHNlZGltZW50IG9mIFNvdXJjZSA2IGNvbnRyaWJ1dGVkIHRvIHNpbmsgc2VkaW1lbnRzLCBhbmQgU291cmNlIDYgd2F0ZXIgc2FtcGxlcyBjb250cmlidXRlZCB0byB3YXRlciBzaW5rcy4NCg0KSW4gc3VtbWFyeSwgdGhpcyBzdHVkeSBwcm92aWRlcyBhIHN0YXJ0aW5nIHBvaW50IGluIGNvbW11bml0eSBhc3NlbWJseSByZXNlYXJjaCBvZiBtaWNyb2JpYWwgZmF1bmEgb2YgTHVueiBsYWtlcyBjYXRjaG1lbnQsIGFuZCBnaXZlcyBpbmRpY2F0aW9uIHRoYXQgZnV0dXJlIHN0dWRpZXMgc2hvdWxkIGJlIGZvY3VzZWQgb24gZW52aXJvbm1lbnRhbCBjb25kaXRpb25zIG9mIGVhY2ggbWljcm9lbnZpcm9ubWVudCwgYW5kIHRoZWlyIHRpZXMgdG8gbWljcm9iaWFsDQphc3NlbWJseSwgc2luY2UgY2F0ZWdvcmlzaW5nIHNhbXBsZXMgYnkgZGlzdGFuY2Ugb3Igc2ltaWxhcml0eSBkb2VzIG5vdCBnaXZlIGNsZWFyIHJlc3VsdHMuDQo=