
knitr::opts_chunk$set(warning=FALSE, message=FALSE, fig.align = 'center')
options(tidyverse.quiet = TRUE)
library(readxl)
library(janitor)
library(glmmTMB)
library(lubridate)
library(broom.mixed)
library(knitr)
library(ggpubr)
library(sjPlot)
library(sf)
library(leaflet)
library(raster)
library(DHARMa)
library(ggspatial)
library(cowplot)
library(ggpubr)
library(mapview)
theme_set(theme_minimal())
Survey design
The objective of the study was to quantify spatio-temporal changes in fish density after a massive seabream escape event in July 2014.
Surveys were conducted in 14 July 2014, five days after the escape event, and then in August 2014 and September 2014.
Density was determined by snorkel-based dive surveys at eight different locations.
At each location two sites were surveyed, with six replicates per site, except Gorguel in July (12 replicates) and Escombreras in August and September when no surveys were conducted.
Sampling units consisted of 500 m2 transects sampled visually by snorkelers swimming 50 m in a straight line and observing the area within 2.5 m on either side (5 x 100 m2).
Snorkelers estimated the density and the size of each fish in the transect.
# get map of Murcia---
murcia <-
read_sf('C:/Users/javiera/OneDrive - Cawthron/UA/Consumo/data/CCAA/Comunidades_Autonomas_ETRS89_30N.shp') %>%
filter(Texto_Alt == "Murcia")
locations <- st_read("data/coords_gorguel.kml", quiet = T)
esc_d <-
read_csv('data/gorguel_density_data_clean.csv', show_col_types = FALSE) %>%
mutate(month = fct_relevel(month, c("July","August")))
esc_d %>%
tabyl(month, localidad) %>%
kable(caption = 'Transectos por Localidad y mes')
Transectos por Localidad y mes
July |
12 |
12 |
12 |
12 |
12 |
24 |
12 |
12 |
August |
12 |
12 |
12 |
12 |
0 |
12 |
12 |
12 |
September |
12 |
12 |
12 |
12 |
0 |
12 |
12 |
12 |
Study locations
leaflet(locations) %>%
setView(lng = -1,
lat = 37.6,
zoom = 11) %>%
addTiles() %>%
addProviderTiles("Esri.WorldImagery") %>%
addCircleMarkers()
Bathymetry
murcia_bathy_cropped <- raster('data/murcia_bathy_cropped.grd')
mapview(murcia_bathy_cropped)@map
Map version 2
sf_use_s2(FALSE)
Spherical geometry (s2) switched off
murcia <-
read_sf('C:/Users/javiera/OneDrive - Cawthron/UA/Consumo/data/CCAA/Comunidades_Autonomas_ETRS89_30N.shp') %>%
filter(Texto_Alt == "Murcia") %>%
st_transform (4326) %>%
st_crop(
xmin = -1.2,
xmax = 0.7,
ymin = 37.5,
ymax = 37.65
)
although coordinates are longitude/latitude, st_intersection assumes that they are planar
Data exploration
Distance
Locations were at increasing distance, in both direction (E and W), from the farm where the escape was originated.
esc_d %>%
distinct(localidad, distance, orientation) %>%
arrange(orientation, distance) %>%
kable(caption = "Distancia y direccion de cada sitio")
Distancia y direccion de cada sitio
Gorguel |
0.7 |
E |
Portman |
4.4 |
E |
Atamaría |
10.1 |
E |
Cabo Palos |
23.7 |
E |
Escombreras |
6.4 |
W |
Calacortina |
12.6 |
W |
Portus |
26.4 |
W |
Azohía |
45.3 |
W |
Density distribution
Fish density data was standardized to number of fish per 100 m2, resulting in continuous variable containing a disproportionately high number of zero values (73.6% of the 276 transects) and the non-zero data was highly overdispersed.
ggarrange(
ggplot(esc_d, aes(density)) +
geom_histogram() + labs(subtitle = 'Untrasnformed'),
ggplot(esc_d, aes(density)) +
geom_histogram() +
scale_x_continuous(trans = 'log1p') + labs(subtitle = 'log1p transformed')
)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Density by Month
ggplot(esc_d, aes(month, density, fill = month)) +
scale_y_continuous(trans = "log1p", breaks = c(0,10, 50, 250, 1000) ) +
geom_boxplot(alpha = .4) +
labs(x = 'Distance (m)' , y = Individuals~per~100~m^2, parse = T) +
scale_fill_discrete(name = NULL)

Density by location, month and site
ggplot(esc_d, aes(month, density)) +
geom_point(alpha = .5, size = 3, aes(color = factor(sitio)), position = position_jitter(width = .1)) +
scale_y_continuous(trans = "log1p", expand = c(0, Inf), ) +
# scale_x_date(date_labels = "%b %d") +
facet_wrap(~localidad)

Density vs distance, month and direccion (E -W)
ggplot(esc_d, aes(distance, density, color = month, group = month)) +
scale_y_continuous(trans = "log1p") +
stat_summary(fun.data = mean_se) +
stat_summary(fun.data = mean_se, geom = 'line') +
facet_wrap(~orientation, scales = 'free_x') +
theme(legend.position = 'bottom') +
labs(x = 'Distance from escape (km)' , y = Number~of~fish~per~100~m^2, parse = T) +
scale_color_discrete(name = NULL)

Distance no direction
ggplot(esc_d, aes(distance, density, color = month, group = month)) +
scale_y_continuous(trans = "log1p", breaks = c(0,10, 50, 250, 1000) ) +
geom_point(alpha = .4, position = position_jitter(width = .5)) +
geom_smooth(stat = 'summary', fun.data = mean_se, alpha = .2) +
theme(legend.position = 'bottom') +
labs(x = 'Distance from escape (km)' , y = Individuals~per~100~m^2, parse = T) +
scale_color_discrete(name = NULL)

Density by Orientation
ggplot(esc_d, aes(month, density, fill = orientation)) +
scale_y_continuous(trans = "log1p", breaks = c(0,10, 50, 250, 1000) ) +
geom_boxplot(alpha = .4) +
labs(x = NULL , y = Individuals~per~100~m^2, parse = T) +
scale_fill_discrete(name = NULL)

Fish density modelling
Fish count data was standardised to number of fish per 100 m2, resulting in continuous variable that was overdispered and contained a large number of zero values. As such, density data was analysed using generalised linear models fitted with Tweedie error distribution which is more robust to overdispersed and zero-rich data than other distribution families (e.g. negative binomial, gamma). Zero-inflation was tested with the testZeroInflation function of the package DHARMa that compares the observed number of zeros with the zeros expected from simulations.
Models were fitted with distance a continuous covariate, month as categorical with three levels (July, August and September), and their interaction (Distance x Month). The main effect of Orientation (W and E) was also included as a categorical fixed effect. Site nested in location was included a random factor to quatify the variability in density at a small spatial scale (100s m). Models were selected based on the AIC values and validated using simulated residulas using the simulateResiduals function in the package DHARMa.
The contribution of fixed and random effects to the performance of the model was calculated using marginal R2 (accounting for fixed effects only) and conditional pseudo-R2 (accounting for fixed and random effects, Nakagawa and Schielzeth, 2013).
Test for zero-inflation
zi_model <-
glmmTMB(
density ~ distance * month + orientation + (1|localidad:sitio),
zi = ~ distance + month,
family = tweedie(link = "log"),
data = esc_d
)
testZeroInflation(zi_model)
DHARMa zero-inflation test via comparison to expected zeros with
simulation under H0 = fitted model
data: simulationOutput
ratioObsSim = 0.98653, p-value = 0.816
alternative hypothesis: two.sided

glance(zi_model)
The test showed that the expected distribution of zeros is not larger than the observed values, thus there is no need to incorporate zero-inflation in the model.
GLMM without zero-inflation
m1 <-
glmmTMB(
density ~ distance * month + orientation + (1|localidad:sitio),
family = tweedie(link = "log"),
data = esc_d
)
drop1(m1)
Single term deletions
Model:
density ~ distance * month + orientation + (1 | localidad:sitio)
Df AIC
<none> 718.69
orientation 1 716.97
distance:month 2 721.76
The lowest AIC value (716.97) was for the model with the distance and month interaction and no effect of orientation (density ~ distance * month).
All AIC values were lower than that for the zero-inflated model.
Model validation
final_model <-
glmmTMB(
density ~ distance * month + (1|localidad:sitio),
family = tweedie(link = "log"),
data = esc_d
)
simulationOutput <- simulateResiduals(fittedModel = final_model, plot = F)
plot(simulationOutput)

# testResiduals(final_model)
There are no residual patterns or over-dispersion. The residuals test identified one outlier that could be potentially removed and some mild deviation that is not of concern.
Model inference
fixed |
cond |
NA |
(Intercept) |
3.77 |
0.72 |
5.21 |
0.00 |
fixed |
cond |
NA |
distance |
-0.19 |
0.03 |
-7.13 |
0.00 |
fixed |
cond |
NA |
monthAugust |
-4.16 |
0.82 |
-5.07 |
0.00 |
fixed |
cond |
NA |
monthSeptember |
-5.23 |
1.06 |
-4.95 |
0.00 |
fixed |
cond |
NA |
distance:monthAugust |
0.10 |
0.04 |
2.51 |
0.01 |
fixed |
cond |
NA |
distance:monthSeptember |
0.11 |
0.06 |
1.72 |
0.09 |
ran_pars |
cond |
localidad:sitio |
sd__(Intercept) |
0.78 |
NA |
NA |
NA |
The model predicted an average fish density (intercept of the model) of 43 individuals per 100 m2 (10.49 – 178.96 95% CI) at the location of the escape. The density reduction rate varied significantly with sampling month (Distance x month, P<0.05).
Fish density significantly decreased with distance, more specifically by 17% for every km away from the escape location. Fish density was predicted to decrease to 2% and 1% after one and two month of the escape event, respectively
Additionally, there was relatively site-to-site variability in fish density, evidenced by the small standard deviation for the effect of site nested in location, and the small difference between the conditional the R2 value marginal value (0.38 and 0.41, respectively).
Fish size distribution
In addition to fish density, divers estimated total fish length of all fish in the transects.
size <- read_csv('data/size_data.csv')
size_raw <- read_csv('data/size_data_raw.csv')
Histograms of total fish length by month and location
ggplot(size_raw, aes(size, fill = localidad)) +
geom_histogram(bins = 15) +
facet_wrap(~month, scales = 'free_y')

NA
Mean (±SD) total length by month and locality
ggplot(size_raw, aes(fct_relevel(month,"July","August"), size, color = fct_reorder(loc_dist, distance) , group = fct_reorder(loc_dist, distance) )) +
stat_summary(fun.data = mean_sdl, position = position_dodge(width = .7)) +
scale_color_discrete(name = NULL) +
labs(x = NULL, y = "Total fish length (cm)" )

Test for size between month
Length frequencies between months were compared using a randomization Kolmogorov & Smirnov test using the function clus.lf in the fishmethods package.
From package help file:
Length frequency distributions of fishes are commonly tested for differences among groups (e.g., regions, sexes, etc.) using a two-sample Kolmogov-Smirnov test (K-S). Like most statistical tests, the K-S test requires that observations are collected at random and are independent of each other to satisfy assumptions. These basic assumptions are violated when gears (e.g., trawls, haul seines, gillnets, etc.) are used to sample fish because individuals are collected in clusters . In this case, the “haul”, not the individual fish, is the primary sampling unit and statistical comparisons must take this into account.
library(fishmethods)
clus_res <-
clus.lf(group=size$month,haul=paste(size$transecto,size$toponimia),
len=size$size, number=size$number,
binsize=5,resamples=100)
clus_res$results %>% kable
There were significant differences in fish size frequency distribution between months, except between August and September.
LS0tDQp0aXRsZTogIkVzY2FwZXMgR29yZ3VlbCINCmF1dGhvcjogIkphdmllciBBdGFsYWgiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgbnVtYmVyX3NlY3Rpb246IHllcw0KICAgIHRoZW1lOiBkZWZhdWx0DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDINCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IG5vDQogICAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCi0tLQ0KDQohW10oZmlndXJlcy9sb2dvLXVhLmpwZyl7d2lkdGg9IjMwNyJ9DQoNCmBgYHtyIHNldHVwLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5hbGlnbiA9ICdjZW50ZXInKQ0Kb3B0aW9ucyh0aWR5dmVyc2UucXVpZXQgPSBUUlVFKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KGdsbW1UTUIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoYnJvb20ubWl4ZWQpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShnZ3B1YnIpDQpsaWJyYXJ5KHNqUGxvdCkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KHJhc3RlcikNCmxpYnJhcnkoREhBUk1hKQ0KbGlicmFyeShnZ3NwYXRpYWwpDQpsaWJyYXJ5KGNvd3Bsb3QpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkobWFwdmlldykNCnRoZW1lX3NldCh0aGVtZV9taW5pbWFsKCkpDQpgYGANCg0KIyBTdXJ2ZXkgZGVzaWduDQoNCi0gICBUaGUgb2JqZWN0aXZlIG9mIHRoZSBzdHVkeSB3YXMgdG8gcXVhbnRpZnkgc3BhdGlvLXRlbXBvcmFsIGNoYW5nZXMgaW4gZmlzaCBkZW5zaXR5IGFmdGVyIGEgbWFzc2l2ZSBzZWFicmVhbSBlc2NhcGUgZXZlbnQgaW4gSnVseSAyMDE0Lg0KDQotICAgU3VydmV5cyB3ZXJlIGNvbmR1Y3RlZCBpbiAxNCBKdWx5IDIwMTQsIGZpdmUgZGF5cyBhZnRlciB0aGUgZXNjYXBlIGV2ZW50LCBhbmQgdGhlbiBpbiBBdWd1c3QgMjAxNCBhbmQgU2VwdGVtYmVyIDIwMTQuDQoNCi0gICBEZW5zaXR5IHdhcyBkZXRlcm1pbmVkIGJ5IHNub3JrZWwtYmFzZWQgZGl2ZSBzdXJ2ZXlzIGF0IGVpZ2h0IGRpZmZlcmVudCBsb2NhdGlvbnMuDQoNCi0gICBBdCBlYWNoIGxvY2F0aW9uIHR3byBzaXRlcyB3ZXJlIHN1cnZleWVkLCB3aXRoIHNpeCByZXBsaWNhdGVzIHBlciBzaXRlLCBleGNlcHQgR29yZ3VlbCBpbiBKdWx5ICgxMiByZXBsaWNhdGVzKSBhbmQgRXNjb21icmVyYXMgaW4gQXVndXN0IGFuZCBTZXB0ZW1iZXIgd2hlbiBubyBzdXJ2ZXlzIHdlcmUgY29uZHVjdGVkLg0KDQotICAgU2FtcGxpbmcgdW5pdHMgY29uc2lzdGVkIG9mIDUwMCBtXjJeIHRyYW5zZWN0cyBzYW1wbGVkIHZpc3VhbGx5IGJ5IHNub3JrZWxlcnMgc3dpbW1pbmcgNTAgbSBpbiBhIHN0cmFpZ2h0IGxpbmUgYW5kIG9ic2VydmluZyB0aGUgYXJlYSB3aXRoaW4gMi41IG0gb24gZWl0aGVyIHNpZGUgKDUgeCAxMDAgbV4yXikuDQoNCi0gICBTbm9ya2VsZXJzIGVzdGltYXRlZCB0aGUgZGVuc2l0eSBhbmQgdGhlIHNpemUgb2YgZWFjaCBmaXNoIGluIHRoZSB0cmFuc2VjdC4NCg0KYGBge3J9DQojIGdldCBtYXAgb2YgTXVyY2lhLS0tDQptdXJjaWEgPC0gDQogIHJlYWRfc2YoJ0M6L1VzZXJzL2phdmllcmEvT25lRHJpdmUgLSBDYXd0aHJvbi9VQS9Db25zdW1vL2RhdGEvQ0NBQS9Db211bmlkYWRlc19BdXRvbm9tYXNfRVRSUzg5XzMwTi5zaHAnKSAlPiUgDQogIGZpbHRlcihUZXh0b19BbHQgPT0gIk11cmNpYSIpDQoNCmxvY2F0aW9ucyA8LSBzdF9yZWFkKCJkYXRhL2Nvb3Jkc19nb3JndWVsLmttbCIsIHF1aWV0ID0gVCkNCg0KZXNjX2QgPC0gDQogIHJlYWRfY3N2KCdkYXRhL2dvcmd1ZWxfZGVuc2l0eV9kYXRhX2NsZWFuLmNzdicsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JSANCiAgbXV0YXRlKG1vbnRoID0gZmN0X3JlbGV2ZWwobW9udGgsIGMoIkp1bHkiLCJBdWd1c3QiKSkpIA0KDQpgYGANCg0KYGBge3J9DQplc2NfZCAlPiUgDQogIHRhYnlsKG1vbnRoLCBsb2NhbGlkYWQpICU+JSANCiAga2FibGUoY2FwdGlvbiA9ICdUcmFuc2VjdG9zIHBvciBMb2NhbGlkYWQgeSBtZXMnKSANCmBgYA0KDQojIFN0dWR5IGxvY2F0aW9ucw0KDQpgYGB7cn0NCmxlYWZsZXQobG9jYXRpb25zKSAlPiUNCiAgc2V0VmlldyhsbmcgPSAtMSwNCiAgICAgICAgICBsYXQgPSAzNy42LA0KICAgICAgICAgIHpvb20gPSAxMSkgJT4lDQogIGFkZFRpbGVzKCkgJT4lDQogIGFkZFByb3ZpZGVyVGlsZXMoIkVzcmkuV29ybGRJbWFnZXJ5IikgJT4lDQogIGFkZENpcmNsZU1hcmtlcnMoKQ0KYGBgDQoNCiMjIEJhdGh5bWV0cnkNCg0KYGBge3J9DQptdXJjaWFfYmF0aHlfY3JvcHBlZCA8LSByYXN0ZXIoJ2RhdGEvbXVyY2lhX2JhdGh5X2Nyb3BwZWQuZ3JkJykNCm1hcHZpZXcobXVyY2lhX2JhdGh5X2Nyb3BwZWQpQG1hcA0KYGBgDQoNCiMjIE1hcCB2ZXJzaW9uIDINCg0KYGBge3J9DQpjb29yZHMgPC0gcmVhZF9jc3YoJ2RhdGEvY29vcmRzLmNzdicpDQpzcGFpbiA8LSANCiAgcmVhZF9zZignQzovVXNlcnMvamF2aWVyYS9PbmVEcml2ZSAtIENhd3Rocm9uL1VBL0NvbnN1bW8vZGF0YS9DQ0FBL0NvbXVuaWRhZGVzX0F1dG9ub21hc19FVFJTODlfMzBOLnNocCcpICU+JSANCiAgZmlsdGVyKCFUZXh0byVpbiUgYygiQ2FuYXJpYXMiLCJDZXV0YSIsIk1lbGlsbGEiKSkgJT4lIA0KICBzdF90cmFuc2Zvcm0gKDQzMjYpIA0KDQpzZl91c2VfczIoRkFMU0UpDQptdXJjaWEgPC0gDQogIHJlYWRfc2YoJ0M6L1VzZXJzL2phdmllcmEvT25lRHJpdmUgLSBDYXd0aHJvbi9VQS9Db25zdW1vL2RhdGEvQ0NBQS9Db211bmlkYWRlc19BdXRvbm9tYXNfRVRSUzg5XzMwTi5zaHAnKSAlPiUgDQogIGZpbHRlcihUZXh0b19BbHQgPT0gIk11cmNpYSIpICU+JSANCiAgc3RfdHJhbnNmb3JtICg0MzI2KSAlPiUgDQogIHN0X2Nyb3AoDQogICAgeG1pbiA9IC0xLjIsDQogICAgeG1heCA9IDAuNywNCiAgICB5bWluID0gMzcuNSwNCiAgICB5bWF4ID0gMzcuNjUNCiAgKSANCg0Kc2l0ZXNfbWFwIDwtIA0KZ2dwbG90KCkgKyANCiAgZ2VvbV9zZihkYXRhID0gbXVyY2lhLCBmaWxsID0gJ2dyYXk5MCcpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gY29vcmRzLCBhZXMoWCxZKSkgKw0KICBnZ3JlcGVsOjpnZW9tX2xhYmVsX3JlcGVsKGRhdGEgPSBjb29yZHMsIGFlcyhYLFksIGxhYmVsID0gbG9jYWxpZGFkKSwgY29sb3IgPTEgLCBzaXplID0gMi41KSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMKSArDQogIGFubm90YXRpb25fbm9ydGhfYXJyb3coDQogICAgbG9jYXRpb24gPSAiYnIiLA0KICAgIHdoaWNoX25vcnRoID0gInRydWUiLA0KICAgIHBhZF94ID0gdW5pdCgwLjA1LCAiaW4iKSwNCiAgICBwYWRfeSA9IHVuaXQoMC4yLCAiaW4iKSwNCiAgICBzdHlsZSA9IG5vcnRoX2Fycm93X2ZhbmN5X29yaWVudGVlcmluZw0KICApICsNCiAgYW5ub3RhdGlvbl9zY2FsZShsb2NhdGlvbiA9ICJiciIsIHdpZHRoX2hpbnQgPSAwLjE1KSANCg0KDQpzcGFpbl9tYXAgPC0gDQogIGdncGxvdCgpICsgDQogIGdlb21fc2YoZGF0YSA9IHNwYWluLCBmaWxsID0gJ2dyYXk5MCcpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwpICsNCiAgIyBjb29yZF9tYXAoeGxpbSA9IGMoMTY2LCAxNzkpLCB5bGltID0gYygtNDcuNSwgLTM0KSkgKw0KICBhbm5vdGF0ZSgNCiAgICAicmVjdCIsDQogICAgeG1pbiA9IC0xLjIsDQogICAgeG1heCA9IC0wLjcsDQogICAgeW1pbiA9IDM3LjUsDQogICAgeW1heCA9IDM3LjcsDQogICAgY29sb3IgPSAyLA0KICAgIGZpbGwgPSAndHJhbnNwYXJlbnQnLA0KICAgIHNpemUgPSAxDQogICkgKw0KICB0aGVtZV92b2lkKCkgKw0KICB0aGVtZSgNCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAnZ3JheTMwJywgZmlsbD0gTkEpDQogICkgDQoNCmZpZ19tYXAgPC0gDQogIGNvd3Bsb3Q6OmdnZHJhdygpICsNCiAgZHJhd19wbG90KHNpdGVzX21hcCkgKw0KICBkcmF3X3Bsb3QoDQogICAgc3BhaW5fbWFwLA0KICAgIHggPSAwLjgsDQogICAgeSA9IC43NSwNCiAgICB3aWR0aCA9IC4yLA0KICAgIGhlaWdodCA9IC4yDQogICkNCmZpZ19tYXANCmBgYA0KDQojIERhdGEgZXhwbG9yYXRpb24NCg0KIyMgRGlzdGFuY2UNCg0KTG9jYXRpb25zIHdlcmUgYXQgaW5jcmVhc2luZyBkaXN0YW5jZSwgaW4gYm90aCBkaXJlY3Rpb24gKEUgYW5kIFcpLCBmcm9tIHRoZSBmYXJtIHdoZXJlIHRoZSBlc2NhcGUgd2FzIG9yaWdpbmF0ZWQuDQoNCmBgYHtyfQ0KZXNjX2QgJT4lIA0KICBkaXN0aW5jdChsb2NhbGlkYWQsIGRpc3RhbmNlLCBvcmllbnRhdGlvbikgJT4lIA0KICBhcnJhbmdlKG9yaWVudGF0aW9uLCBkaXN0YW5jZSkgJT4lIA0KICBrYWJsZShjYXB0aW9uID0gIkRpc3RhbmNpYSB5IGRpcmVjY2lvbiBkZSBjYWRhIHNpdGlvIg0KYGBgDQoNCiMjIERlbnNpdHkgZGlzdHJpYnV0aW9uDQoNCkZpc2ggZGVuc2l0eSBkYXRhIHdhcyBzdGFuZGFyZGl6ZWQgdG8gbnVtYmVyIG9mIGZpc2ggcGVyIDEwMCBtMiwgcmVzdWx0aW5nIGluIGNvbnRpbnVvdXMgdmFyaWFibGUgY29udGFpbmluZyBhIGRpc3Byb3BvcnRpb25hdGVseSBoaWdoIG51bWJlciBvZiB6ZXJvIHZhbHVlcyAoNzMuNiUgb2YgdGhlIDI3NiB0cmFuc2VjdHMpIGFuZCB0aGUgbm9uLXplcm8gZGF0YSB3YXMgaGlnaGx5IG92ZXJkaXNwZXJzZWQuDQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0xMH0NCmdnYXJyYW5nZSgNCiAgZ2dwbG90KGVzY19kLCBhZXMoZGVuc2l0eSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oKSArIGxhYnMoc3VidGl0bGUgPSAnVW50cmFzbmZvcm1lZCcpLA0KICBnZ3Bsb3QoZXNjX2QsIGFlcyhkZW5zaXR5KSkgKw0KICBnZW9tX2hpc3RvZ3JhbSgpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gJ2xvZzFwJykgKyBsYWJzKHN1YnRpdGxlID0gJ2xvZzFwIHRyYW5zZm9ybWVkJykNCiAgKQ0KYGBgDQoNCiMjIERlbnNpdHkgYnkgTW9udGgNCg0KYGBge3J9DQpnZ3Bsb3QoZXNjX2QsIGFlcyhtb250aCwgZGVuc2l0eSwgZmlsbCA9IG1vbnRoKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMXAiLCBicmVha3MgPSBjKDAsMTAsIDUwLCAyNTAsIDEwMDApICkgKw0KICBnZW9tX2JveHBsb3QoYWxwaGEgPSAuNCkgKw0KICBsYWJzKHggPSAnRGlzdGFuY2UgKG0pJyAsIHkgPSBJbmRpdmlkdWFsc35wZXJ+MTAwfm1eMiwgcGFyc2UgPSBUKSArDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9IE5VTEwpDQpgYGANCg0KIyMgRGVuc2l0eSBieSBsb2NhdGlvbiwgbW9udGggYW5kIHNpdGUNCg0KYGBge3J9DQpnZ3Bsb3QoZXNjX2QsIGFlcyhtb250aCwgZGVuc2l0eSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IC41LCBzaXplID0gMywgYWVzKGNvbG9yID0gZmFjdG9yKHNpdGlvKSksIHBvc2l0aW9uID0gICAgIHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IC4xKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMXAiLCBleHBhbmQgPSBjKDAsIEluZiksICkgKw0KICAjIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlYiAlZCIpICsNCiAgZmFjZXRfd3JhcCh+bG9jYWxpZGFkKSANCmBgYA0KDQojIyBEZW5zaXR5IHZzIGRpc3RhbmNlLCBtb250aCBhbmQgZGlyZWNjaW9uIChFIC1XKQ0KDQpgYGB7cn0NCmdncGxvdChlc2NfZCwgYWVzKGRpc3RhbmNlLCBkZW5zaXR5LCBjb2xvciA9IG1vbnRoLCBncm91cCA9IG1vbnRoKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMXAiKSArDQogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwgZ2VvbSA9ICdsaW5lJykgKw0KICBmYWNldF93cmFwKH5vcmllbnRhdGlvbiwgc2NhbGVzID0gJ2ZyZWVfeCcpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsNCiAgbGFicyh4ID0gJ0Rpc3RhbmNlIGZyb20gZXNjYXBlIChrbSknICwgeSA9IE51bWJlcn5vZn5maXNofnBlcn4xMDB+bV4yLCBwYXJzZSA9IFQpICsNCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZSA9IE5VTEwpDQoNCmBgYA0KDQojIyBEaXN0YW5jZSBubyBkaXJlY3Rpb24NCg0KYGBge3J9DQpnZ3Bsb3QoZXNjX2QsIGFlcyhkaXN0YW5jZSwgZGVuc2l0eSwgY29sb3IgPSBtb250aCwgZ3JvdXAgPSBtb250aCkpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzFwIiwgYnJlYWtzID0gYygwLDEwLCA1MCwgMjUwLCAxMDAwKSApICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IC40LCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IC41KSkgKw0KICBnZW9tX3Ntb290aChzdGF0ID0gJ3N1bW1hcnknLCBmdW4uZGF0YSA9IG1lYW5fc2UsIGFscGhhID0gLjIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsNCiAgbGFicyh4ID0gJ0Rpc3RhbmNlIGZyb20gZXNjYXBlIChrbSknICwgeSA9IEluZGl2aWR1YWxzfnBlcn4xMDB+bV4yLCBwYXJzZSA9IFQpICsNCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZSA9IE5VTEwpDQoNCmBgYA0KDQojIyBEZW5zaXR5IGJ5IE9yaWVudGF0aW9uDQoNCmBgYHtyfQ0KZ2dwbG90KGVzY19kLCBhZXMobW9udGgsIGRlbnNpdHksIGZpbGwgPSBvcmllbnRhdGlvbikpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzFwIiwgYnJlYWtzID0gYygwLDEwLCA1MCwgMjUwLCAxMDAwKSApICsNCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gLjQpICsNCiAgbGFicyh4ID0gTlVMTCAsIHkgPSBJbmRpdmlkdWFsc35wZXJ+MTAwfm1eMiwgcGFyc2UgPSBUKSArDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9IE5VTEwpDQpgYGANCg0KIyBGaXNoIGRlbnNpdHkgbW9kZWxsaW5nDQoNCkZpc2ggY291bnQgZGF0YSB3YXMgc3RhbmRhcmRpc2VkIHRvIG51bWJlciBvZiBmaXNoIHBlciAxMDAgbTIsIHJlc3VsdGluZyBpbiBjb250aW51b3VzIHZhcmlhYmxlIHRoYXQgd2FzIG92ZXJkaXNwZXJlZCBhbmQgY29udGFpbmVkIGEgbGFyZ2UgbnVtYmVyIG9mIHplcm8gdmFsdWVzLiBBcyBzdWNoLCBkZW5zaXR5IGRhdGEgd2FzIGFuYWx5c2VkIHVzaW5nIGdlbmVyYWxpc2VkIGxpbmVhciBtb2RlbHMgZml0dGVkIHdpdGggVHdlZWRpZSBlcnJvciBkaXN0cmlidXRpb24gd2hpY2ggaXMgbW9yZSByb2J1c3QgdG8gb3ZlcmRpc3BlcnNlZCBhbmQgemVyby1yaWNoIGRhdGEgdGhhbiBvdGhlciBkaXN0cmlidXRpb24gZmFtaWxpZXMgKGUuZy4gbmVnYXRpdmUgYmlub21pYWwsIGdhbW1hKS4gWmVyby1pbmZsYXRpb24gd2FzIHRlc3RlZCB3aXRoIHRoZSB0ZXN0WmVyb0luZmxhdGlvbiBmdW5jdGlvbiBvZiB0aGUgcGFja2FnZSBESEFSTWEgdGhhdCBjb21wYXJlcyB0aGUgb2JzZXJ2ZWQgbnVtYmVyIG9mIHplcm9zIHdpdGggdGhlIHplcm9zIGV4cGVjdGVkIGZyb20gc2ltdWxhdGlvbnMuDQoNCk1vZGVscyB3ZXJlIGZpdHRlZCB3aXRoIGRpc3RhbmNlIGEgY29udGludW91cyBjb3ZhcmlhdGUsIG1vbnRoIGFzIGNhdGVnb3JpY2FsIHdpdGggdGhyZWUgbGV2ZWxzIChKdWx5LCBBdWd1c3QgYW5kIFNlcHRlbWJlciksIGFuZCB0aGVpciBpbnRlcmFjdGlvbiAoRGlzdGFuY2UgeCBNb250aCkuIFRoZSBtYWluIGVmZmVjdCBvZiBPcmllbnRhdGlvbiAoVyBhbmQgRSkgd2FzIGFsc28gaW5jbHVkZWQgYXMgYSBjYXRlZ29yaWNhbCBmaXhlZCBlZmZlY3QuIFNpdGUgbmVzdGVkIGluIGxvY2F0aW9uIHdhcyBpbmNsdWRlZCBhIHJhbmRvbSBmYWN0b3IgdG8gcXVhdGlmeSB0aGUgdmFyaWFiaWxpdHkgaW4gZGVuc2l0eSBhdCBhIHNtYWxsIHNwYXRpYWwgc2NhbGUgKDEwMHMgbSkuIE1vZGVscyB3ZXJlIHNlbGVjdGVkIGJhc2VkIG9uIHRoZSBBSUMgdmFsdWVzIGFuZCB2YWxpZGF0ZWQgdXNpbmcgc2ltdWxhdGVkIHJlc2lkdWxhcyB1c2luZyB0aGUgc2ltdWxhdGVSZXNpZHVhbHMgZnVuY3Rpb24gaW4gdGhlIHBhY2thZ2UgREhBUk1hLg0KDQpUaGUgY29udHJpYnV0aW9uIG9mIGZpeGVkIGFuZCByYW5kb20gZWZmZWN0cyB0byB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIG1vZGVsIHdhcyBjYWxjdWxhdGVkIHVzaW5nIG1hcmdpbmFsIFIyIChhY2NvdW50aW5nIGZvciBmaXhlZCBlZmZlY3RzIG9ubHkpIGFuZCBjb25kaXRpb25hbCBwc2V1ZG8tUjIgKGFjY291bnRpbmcgZm9yIGZpeGVkIGFuZCByYW5kb20gZWZmZWN0cywgTmFrYWdhd2EgYW5kIFNjaGllbHpldGgsIDIwMTMpLg0KDQojIyBUZXN0IGZvciB6ZXJvLWluZmxhdGlvbg0KDQpgYGB7cn0NCnppX21vZGVsIDwtDQogIGdsbW1UTUIoDQogICAgZGVuc2l0eSB+IGRpc3RhbmNlICogbW9udGggKyBvcmllbnRhdGlvbiArICgxfGxvY2FsaWRhZDpzaXRpbyksDQogICAgemkgPSAgfiBkaXN0YW5jZSArIG1vbnRoLA0KICAgIGZhbWlseSA9IHR3ZWVkaWUobGluayA9ICJsb2ciKSwNCiAgICBkYXRhID0gZXNjX2QNCiAgKQ0KDQp0ZXN0WmVyb0luZmxhdGlvbih6aV9tb2RlbCkNCg0KZ2xhbmNlKHppX21vZGVsKQ0KYGBgDQoNClRoZSB0ZXN0IHNob3dlZCB0aGF0IHRoZSBleHBlY3RlZCBkaXN0cmlidXRpb24gb2YgemVyb3MgaXMgbm90IGxhcmdlciB0aGFuIHRoZSBvYnNlcnZlZCB2YWx1ZXMsIHRodXMgdGhlcmUgaXMgbm8gbmVlZCB0byBpbmNvcnBvcmF0ZSB6ZXJvLWluZmxhdGlvbiBpbiB0aGUgbW9kZWwuDQoNCiMjIEdMTU0gd2l0aG91dCB6ZXJvLWluZmxhdGlvbg0KDQpgYGB7cn0NCm0xIDwtDQogIGdsbW1UTUIoDQogICAgZGVuc2l0eSB+IGRpc3RhbmNlICogbW9udGggKyBvcmllbnRhdGlvbiArICgxfGxvY2FsaWRhZDpzaXRpbyksDQogICAgZmFtaWx5ID0gdHdlZWRpZShsaW5rID0gImxvZyIpLA0KICAgIGRhdGEgPSBlc2NfZA0KICApDQoNCg0KZHJvcDEobTEpDQoNCmBgYA0KDQpUaGUgbG93ZXN0IEFJQyB2YWx1ZSAoNzE2Ljk3KSB3YXMgZm9yIHRoZSBtb2RlbCB3aXRoIHRoZSBkaXN0YW5jZSBhbmQgbW9udGggaW50ZXJhY3Rpb24gYW5kIG5vIGVmZmVjdCBvZiBvcmllbnRhdGlvbiAoZGVuc2l0eSBcfiBkaXN0YW5jZSBcKiBtb250aCkuDQoNCkFsbCBBSUMgdmFsdWVzIHdlcmUgbG93ZXIgdGhhbiB0aGF0IGZvciB0aGUgemVyby1pbmZsYXRlZCBtb2RlbC4NCg0KIyMgTW9kZWwgdmFsaWRhdGlvbg0KDQpgYGB7cn0NCmZpbmFsX21vZGVsIDwtDQogIGdsbW1UTUIoDQogICAgZGVuc2l0eSB+IGRpc3RhbmNlICogbW9udGggICsgKDF8bG9jYWxpZGFkOnNpdGlvKSwNCiAgICBmYW1pbHkgPSB0d2VlZGllKGxpbmsgPSAibG9nIiksDQogICAgZGF0YSA9IGVzY19kDQogICkNCg0Kc2ltdWxhdGlvbk91dHB1dCA8LSBzaW11bGF0ZVJlc2lkdWFscyhmaXR0ZWRNb2RlbCA9IGZpbmFsX21vZGVsLCBwbG90ID0gRikNCnBsb3Qoc2ltdWxhdGlvbk91dHB1dCkNCiMgdGVzdFJlc2lkdWFscyhmaW5hbF9tb2RlbCkNCmBgYA0KDQpUaGVyZSBhcmUgbm8gcmVzaWR1YWwgcGF0dGVybnMgb3Igb3Zlci1kaXNwZXJzaW9uLiBUaGUgcmVzaWR1YWxzIHRlc3QgaWRlbnRpZmllZCBvbmUgb3V0bGllciB0aGF0IGNvdWxkIGJlIHBvdGVudGlhbGx5IHJlbW92ZWQgYW5kIHNvbWUgbWlsZCBkZXZpYXRpb24gdGhhdCBpcyBub3Qgb2YgY29uY2Vybi4NCg0KIyMgTW9kZWwgaW5mZXJlbmNlDQoNCmBgYHtyfQ0KdGlkeShmaW5hbF9tb2RlbCkgJT4lIGthYmxlKGRpZ2l0cyA9IDIpDQpgYGANCg0KVGhlIG1vZGVsIHByZWRpY3RlZCBhbiBhdmVyYWdlIGZpc2ggZGVuc2l0eSAoaW50ZXJjZXB0IG9mIHRoZSBtb2RlbCkgb2YgNDMgaW5kaXZpZHVhbHMgcGVyIDEwMCBtXjJeICgxMC40OSAtLSAxNzguOTYgOTUlIENJKSBhdCB0aGUgbG9jYXRpb24gb2YgdGhlIGVzY2FwZS4gVGhlIGRlbnNpdHkgcmVkdWN0aW9uIHJhdGUgdmFyaWVkIHNpZ25pZmljYW50bHkgd2l0aCBzYW1wbGluZyBtb250aCAoRGlzdGFuY2UgeCBtb250aCwgUFw8MC4wNSkuDQoNCkZpc2ggZGVuc2l0eSBzaWduaWZpY2FudGx5IGRlY3JlYXNlZCB3aXRoIGRpc3RhbmNlLCBtb3JlIHNwZWNpZmljYWxseSBieSAxNyUgZm9yIGV2ZXJ5IGttIGF3YXkgZnJvbSB0aGUgZXNjYXBlIGxvY2F0aW9uLiBGaXNoIGRlbnNpdHkgd2FzIHByZWRpY3RlZCB0byBkZWNyZWFzZSB0byAyJSBhbmQgMSUgYWZ0ZXIgb25lIGFuZCB0d28gbW9udGggb2YgdGhlIGVzY2FwZSBldmVudCwgcmVzcGVjdGl2ZWx5DQoNCkFkZGl0aW9uYWxseSwgdGhlcmUgd2FzIHJlbGF0aXZlbHkgc2l0ZS10by1zaXRlIHZhcmlhYmlsaXR5IGluIGZpc2ggZGVuc2l0eSwgZXZpZGVuY2VkIGJ5IHRoZSBzbWFsbCBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIHRoZSBlZmZlY3Qgb2Ygc2l0ZSBuZXN0ZWQgaW4gbG9jYXRpb24sIGFuZCB0aGUgc21hbGwgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBjb25kaXRpb25hbCB0aGUgUl4yXiB2YWx1ZSBtYXJnaW5hbCB2YWx1ZSAoMC4zOCBhbmQgMC40MSwgcmVzcGVjdGl2ZWx5KS4NCg0KIyBGaXNoIHNpemUgZGlzdHJpYnV0aW9uDQoNCkluIGFkZGl0aW9uIHRvIGZpc2ggZGVuc2l0eSwgZGl2ZXJzIGVzdGltYXRlZCB0b3RhbCBmaXNoIGxlbmd0aCBvZiBhbGwgZmlzaCBpbiB0aGUgdHJhbnNlY3RzLg0KDQpgYGB7cn0NCnNpemUgPC0gcmVhZF9jc3YoJ2RhdGEvc2l6ZV9kYXRhLmNzdicpDQpzaXplX3JhdyA8LSByZWFkX2NzdignZGF0YS9zaXplX2RhdGFfcmF3LmNzdicpDQpgYGANCg0KIyMgSGlzdG9ncmFtcyBvZiB0b3RhbCBmaXNoIGxlbmd0aCBieSBtb250aCBhbmQgbG9jYXRpb24NCg0KYGBge3IsIGZpZy53aWR0aD0xMn0NCg0KZ2dwbG90KHNpemVfcmF3LCBhZXMoc2l6ZSwgZmlsbCA9IGxvY2FsaWRhZCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDE1KSArDQogIGZhY2V0X3dyYXAofm1vbnRoLCBzY2FsZXMgPSAnZnJlZV95JykgDQogIA0KYGBgDQoNCiMjIE1lYW4gKMKxU0QpIHRvdGFsIGxlbmd0aCBieSBtb250aCBhbmQgbG9jYWxpdHkNCg0KYGBge3J9DQpnZ3Bsb3Qoc2l6ZV9yYXcsIGFlcyhmY3RfcmVsZXZlbChtb250aCwiSnVseSIsIkF1Z3VzdCIpLCBzaXplLCBjb2xvciA9IGZjdF9yZW9yZGVyKGxvY19kaXN0LCBkaXN0YW5jZSkgLCBncm91cCA9IGZjdF9yZW9yZGVyKGxvY19kaXN0LCBkaXN0YW5jZSkgKSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NkbCwgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjcpKSArDQogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSBOVUxMKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiVG90YWwgZmlzaCBsZW5ndGggKGNtKSIgKQ0KDQpgYGANCg0KIyMgVGVzdCBmb3Igc2l6ZSBiZXR3ZWVuIG1vbnRoDQoNCkxlbmd0aCBmcmVxdWVuY2llcyBiZXR3ZWVuIG1vbnRocyB3ZXJlIGNvbXBhcmVkIHVzaW5nIGEgcmFuZG9taXphdGlvbiBLb2xtb2dvcm92ICYgU21pcm5vdiB0ZXN0IHVzaW5nIHRoZSBmdW5jdGlvbiAqY2x1cy5sZiogaW4gdGhlIGZpc2htZXRob2RzIHBhY2thZ2UuDQoNCkZyb20gcGFja2FnZSBoZWxwIGZpbGU6DQoNCipMZW5ndGggZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbnMgb2YgZmlzaGVzIGFyZSBjb21tb25seSB0ZXN0ZWQgZm9yIGRpZmZlcmVuY2VzIGFtb25nIGdyb3VwcyAoZS5nLiwgcmVnaW9ucywgc2V4ZXMsIGV0Yy4pIHVzaW5nIGEgdHdvLXNhbXBsZSBLb2xtb2dvdi1TbWlybm92IHRlc3QgKEstUykuIExpa2UgbW9zdCBzdGF0aXN0aWNhbCB0ZXN0cywgdGhlIEstUyB0ZXN0IHJlcXVpcmVzIHRoYXQgb2JzZXJ2YXRpb25zIGFyZSBjb2xsZWN0ZWQgYXQgcmFuZG9tIGFuZCBhcmUgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlciB0byBzYXRpc2Z5IGFzc3VtcHRpb25zLiBUaGVzZSBiYXNpYyBhc3N1bXB0aW9ucyBhcmUgdmlvbGF0ZWQgd2hlbiBnZWFycyAoZS5nLiwgdHJhd2xzLCBoYXVsIHNlaW5lcywgZ2lsbG5ldHMsIGV0Yy4pIGFyZSB1c2VkIHRvIHNhbXBsZSBmaXNoIGJlY2F1c2UgaW5kaXZpZHVhbHMgYXJlIGNvbGxlY3RlZCBpbiBjbHVzdGVycyAuIEluIHRoaXMgY2FzZSwgdGhlICJoYXVsIiwgbm90IHRoZSBpbmRpdmlkdWFsIGZpc2gsIGlzIHRoZSBwcmltYXJ5IHNhbXBsaW5nIHVuaXQgYW5kIHN0YXRpc3RpY2FsIGNvbXBhcmlzb25zIG11c3QgdGFrZSB0aGlzIGludG8gYWNjb3VudC4qDQoNCmBgYHtyfQ0KbGlicmFyeShmaXNobWV0aG9kcykNCg0KY2x1c19yZXMgPC0gDQpjbHVzLmxmKGdyb3VwPXNpemUkbW9udGgsaGF1bD1wYXN0ZShzaXplJHRyYW5zZWN0byxzaXplJHRvcG9uaW1pYSksDQogICAgICAgIGxlbj1zaXplJHNpemUsIG51bWJlcj1zaXplJG51bWJlciwgDQogICAgICAgIGJpbnNpemU9NSxyZXNhbXBsZXM9MTAwKQ0KDQpjbHVzX3JlcyRyZXN1bHRzICU+JSBrYWJsZQ0KYGBgDQoNClRoZXJlIHdlcmUgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgaW4gZmlzaCBzaXplIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gYmV0d2VlbiBtb250aHMsIGV4Y2VwdCBiZXR3ZWVuIEF1Z3VzdCBhbmQgU2VwdGVtYmVyLg0K