GAM
In this exercise we will explore the concept of GAM
- Generalized Additive Models - these are models that take dynamic
approach to modelling behavior. Most, behavioral questions are never
straight forward, do not follow a linear model or pattern of behavior,
it requires a flexible approach to understanding complex relationships
within a data set - in this case, the use of splines (we will
get to that) as a smoothing factor, along a multi-modal use in an
additive manner to really understand what influences patterns - in this
case, dolphin behavior.
Dolphins
The problem is described as reviewing the impact on these
contributing factors on $behav - we expect to see some
variance in the contributing factors, some linear and others not
quite.
Rows: 167
Columns: 11
$ speed <dbl> 0.9206887, 1.1729019, 1.1749055, 0.6720431,…
$ rr <dbl> 42.28394, 61.78797, 66.73499, 18.15142, 59.…
$ lin <dbl> 0.633153893, 0.665410017, 0.428164531, 0.62…
$ distance <dbl> 138.29062, 182.16778, 200.23402, 268.98642,…
$ timeper <dbl> 0.5, 0.5, 0.6, 0.2, 0.3, 0.3, 0.3, 0.5, 0.4…
$ cat <chr> "Mid", "Mid", "Tour", "None", "Small", "Sma…
$ grpsize <int> 3, 3, 2, 2, 2, 5, 6, 3, 4, 3, 1, 1, 1, 2, 1…
$ calf <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ behav <chr> "Forage", "Rest", "Rest", "Forage", "Rest",…
$ count <int> 1, 2, 1, 1, 2, 1, 1, 2, 1, 3, 2, 1, 4, 1, 5…
$ id <int> 414334, 414334, 414336, 414341, 414341, 414…
How to Decide Which Variables to Apply Smooth Splines (s()):
Think of splines as bendable rulers that adjust to the shape
of the data. They are built using knots, which are points where the
curve can change direction smoothly. The most common types include
B-splines and thin plate regression splines, which help capture patterns
without overfitting.
In GAMs, splines are used to model nonlinear effects while
maintaining interpretability. They help reveal hidden trends in data
that a simple linear model might miss and are best applied to numeric
predictors where relationships with the target variable are expected to
be non-linear. Here’s a step-by-step guide in deciding where to use
them:
- Look at Variable Types:
- Smooth terms (s()) are suited for continuous numeric predictors
(e.g.,
$speed
, $rr
, $distance
,
$lin
).
- Avoid applying s() to categorical or integer variables like
$cat
or $grpsize
.
- Consider the Nature of the Relationship: If you believe the
relationship between a predictor and the target variable isn’t strictly
linear, splines are ideal. For example:
$speed
: Dolphin behavior may vary non-linearly with
swimming speed.
$distance
: Behavioral states could be influenced by a
non-linear relationship with the distance traveled.
One way of understanding the relationship is by plotting for the
relationships, each predictor against the target variable to observe the
relationship. If we see curves or irregular trends, use a
spline.
Exploratory Data Analysis (EDA):
To achieve this we will be review the underlying relationships
through an EDA, i.e, stats., tables, plots, etc.
1. Basic summary statistics
Basic behaviour stats.
FSB |
54 |
0.3233533 |
3.476940 |
21.93659 |
0.7276897 |
172.0757 |
Social |
52 |
0.3113772 |
1.698714 |
49.99276 |
0.5195180 |
160.1517 |
Forage |
42 |
0.2514970 |
1.686381 |
55.56664 |
0.3921278 |
113.6056 |
Rest |
14 |
0.0838323 |
1.828723 |
40.17311 |
0.5661032 |
175.6061 |
Travel |
5 |
0.0299401 |
2.897316 |
31.00841 |
0.5649046 |
147.2829 |
2. Distribution of behaviors (count and proportion)

3. Numeric variables by behavior
Error in glue("Distribution of **{var}** by Behavior") :
could not find function "glue"
4. Categorical variables by behavior
-> Group size

-> Calf presence

-> Category

5. Timeper (time period) analysis

6. Pairwise relationships colored by behavior
Smaller sample for better visualization if dataset is large

Dissecting the plots
Pairwise Relationships
- Speed vs. Respiration Rate (rr)
There’s a noticeable distinction between behavior types based on
speed and rr.
Foraging behavior occurs at lower speeds but higher rr, possibly
indicating exertion from hunting.
Resting shows moderate speed but lower rr, which aligns with reduced
movement.
- Distance vs. Speed
Non-linear trends emerge: dolphins covering greater distances tend to
maintain a consistent speed instead of fluctuating frequently.
Travel behavior seems distributed across mid-range distances and
speed levels.
- Group Size vs. Behavior
Larger groups show more frequent social interactions, with foraging
behaviors often happening in smaller groups.
Resting appears to occur at variable group sizes, suggesting it might
not be group-dependent.
- Presence of a Calf vs. Behavior
The presence of a calf does not strongly influence behavior, based on
model output significance levels.
Calf presence might be an independent factor rather than a primary
behavioral determinant.
7. Individual patterns (if IDs represent individuals)
if(length(unique(df$id)) < 20) { # Only plot if not too many individuals
ggplot(df, aes(x = id, fill = behav)) +
geom_bar() +
labs(title = "Behavior Distribution by Individual ID",
x = "Individual ID", y = "Count") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
}
8. Count vs behavior
ggplot(df, aes(x = behav, y = count, fill = behav)) +
geom_boxplot() +
labs(title = "Count Distribution by Behavior",
x = "Behavior", y = "Count") +
theme_minimal()

ID’s and count From the distributions above - we’ve
now got the following understanding of what the relationships are:
- Numeric Variables & Behavior
The boxplots suggest that behaviors vary based on numerical
predictors like speed, distance, and rr (possibly respiration rate).
Foraging behavior is associated with higher rr and lower speed
compared to other behaviors.
Resting tends to occur at moderate rr and speed levels.
- Categorical Variables & Behavior
Group size and calf presence seem to have some impact on behaviors,
with larger groups showing different behavioral distributions.
Key Takeaways Behavioral states are influenced by
both linear and non-linear relationships.
Speed and respiration rate interact in a way that differentiates
active behaviors from passive ones.
We can begin to sense how the predictive model would reinforce these
group dynamics matter, like how calf presence does not show strong
predictive influence on how the dolphins will largely behave. Distance
traveled also suggests a patterned movement strategy rather than
randomness.
GAM Analysis
set.seed(234)
data_split <- initial_split(df, prop = 0.8)
train_data <- training(data_split) %>%
mutate(
behav = as.factor(behav)#,
# grpsize = as.integer(grpsize),
# calf = as.integer(calf)
)
test_data <- testing(data_split)
For the Generalized Additive Model (GAM), we will use the
mgcv package - it integrates well with Tidymodels.
Apply directly to the mgcv library
gam_formula <- behav ~ s(speed) + s(rr) + s(distance) + s(lin) + grpsize + calf
gam_model <- gam(
gam_formula,
data = train_data,
family = binomial(),
method = "REML"
)
summary(gam_model)
Family: binomial
Link function: logit
Formula:
behav ~ s(speed) + s(rr) + s(distance) + s(lin) + grpsize + calf
Parametric coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -2.1684 0.8176 -2.652 0.008 **
grpsize 1.1058 0.2580 4.286 1.82e-05 ***
calf -0.7351 0.8319 -0.884 0.377
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Approximate significance of smooth terms:
edf Ref.df Chi.sq p-value
s(speed) 1.000 1.000 0.047 0.8288
s(rr) 1.000 1.000 3.099 0.0783 .
s(distance) 5.268 6.400 13.398 0.0576 .
s(lin) 1.819 2.266 2.053 0.4391
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
R-sq.(adj) = 0.493 Deviance explained = 52%
-REML = 44.42 Scale est. = 1 n = 133
Smooth Terms (Splines) in GAM Analysis
The Generalized Additive Model (GAM) suggests that some relationships
are non-linear, especially for distance (significant smooth term) and
possibly rr.
Speed does not show a strong non-linear effect, suggesting
its influence might be more linear.
Overall Model Performance
The explained deviance of 52% indicates a reasonable ability to
capture behavior variability with these predictors.
The significance levels suggest that group size has a strong effect,
while calf presence does not.
Based on this, behaviors appear influenced by both linear
and non-linear relationships, with distance and
respiration rate showing non-linear patterns.
Now we have built a baseline model that accomodates for the basics
and an understanding or BAU guide to using the Generalized Additive
Model, for linear and non-linear relationships..
Other Thoughts & Interpretation Looking deeper
into calf presence and its influence on behavior, the analysis suggests
that calves do not significantly impact dolphin behavior within this
dataset. Here’s why:
Statistical Insights: The p-value for calf presence in the model is
0.377, indicating a non-significant effect on behavior.
Compare this to group size, which has a highly significant effect
(p-value = 1.82e-05)—showing that larger groups strongly influence
behavior, but the presence of a calf does not.
Observed Patterns: While the GAM model did account for calf presence,
the lack of significance means it doesn’t differentiate behaviors
clearly based on whether a calf is present or not.
The boxplots and pairwise relationships further confirm no strong
behavioral shifts when calves are in the group.
Unlike group size, which influences social interactions and movement
dynamics, calves seem to be more passive participants in behavioral
shifts.
Dolphins might prioritize protective behavior over distinct
behavioral changes when calves are around, but this isn’t strongly
reflected in movement metrics like speed, respiration rate, or distance
traveled.
LS0tDQp0aXRsZTogIlVuZGVyc3RhbmRpbmcgR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWxzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMgR0FNDQpJbiB0aGlzIGV4ZXJjaXNlIHdlIHdpbGwgZXhwbG9yZSB0aGUgY29uY2VwdCBvZiAqKkdBTSoqIC0gR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWxzIC0gdGhlc2UgYXJlIG1vZGVscyB0aGF0IHRha2UgZHluYW1pYyBhcHByb2FjaCB0byBtb2RlbGxpbmcgYmVoYXZpb3IuIE1vc3QsIGJlaGF2aW9yYWwgcXVlc3Rpb25zIGFyZSBuZXZlciBzdHJhaWdodCBmb3J3YXJkLCBkbyBub3QgZm9sbG93IGEgbGluZWFyIG1vZGVsIG9yIHBhdHRlcm4gb2YgYmVoYXZpb3IsIGl0IHJlcXVpcmVzIGEgZmxleGlibGUgYXBwcm9hY2ggdG8gdW5kZXJzdGFuZGluZyBjb21wbGV4IHJlbGF0aW9uc2hpcHMgd2l0aGluIGEgZGF0YSBzZXQgLSBpbiB0aGlzIGNhc2UsIHRoZSB1c2Ugb2YgX3NwbGluZXNfICh3ZSB3aWxsIGdldCB0byB0aGF0KSBhcyBhIHNtb290aGluZyBmYWN0b3IsIGFsb25nIGEgbXVsdGktbW9kYWwgdXNlIGluIGFuIGFkZGl0aXZlIG1hbm5lciB0byByZWFsbHkgdW5kZXJzdGFuZCB3aGF0IGluZmx1ZW5jZXMgcGF0dGVybnMgLSBpbiB0aGlzIGNhc2UsIGRvbHBoaW4gYmVoYXZpb3IuDQoNCg0KYGBge3IgTG9hZCBEZXBlbmRlbmNpZXMsIGVjaG8gPSBGLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0NCiMgY2hlY2sgYW5kIGluc3RhbGwgcmVxdWlyZWQgcGFja2FnZXMNCnJlcXVpcmVkX3BhY2thZ2VzIDwtIGMoImdhbSIsICJJU1RSIiwgIm1nY3YiLCAiR0dhbGx5IiwgImthYmxlRXh0cmEiKQ0KbWlzc2luZ19wYWNrYWdlcyA8LSByZXF1aXJlZF9wYWNrYWdlc1shcmVxdWlyZWRfcGFja2FnZXMgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKVssICJQYWNrYWdlIl1dDQppZihsZW5ndGgobWlzc2luZ19wYWNrYWdlcykpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcyhtaXNzaW5nX3BhY2thZ2VzKQ0KfQ0KDQpsaWJyYXJ5KHRpZHltb2RlbHMpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoYnJvb20pDQpsaWJyYXJ5KHNjYWxlcykjIEZvciBiZXR0ZXIgYXhpcyBmb3JtYXR0aW5nDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KGdhbSkNCiMgbGlicmFyeShJU1RSKQ0KbGlicmFyeShtZ2N2KQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoR0dhbGx5KSAgIyBGb3IgcGFpcnMgcGxvdA0KYGBgDQojIyBEb2xwaGlucw0KVGhlIHByb2JsZW0gaXMgZGVzY3JpYmVkIGFzIHJldmlld2luZyB0aGUgaW1wYWN0IG9uIHRoZXNlIGNvbnRyaWJ1dGluZyBmYWN0b3JzIG9uICoqJGJlaGF2KiogLSB3ZSBleHBlY3QgdG8gc2VlIHNvbWUgdmFyaWFuY2UgaW4gdGhlIGNvbnRyaWJ1dGluZyBmYWN0b3JzLCBzb21lIGxpbmVhciBhbmQgb3RoZXJzIG5vdCBxdWl0ZS4NCg0KYGBge3IsIGVjaG8gPSBGfQ0KZGF0YV9wdGggPSAiQzovVXNlcnMvQWZyb2xvZ2ljSW5zZWN0Ly5jYWNoZS9rYWdnbGVodWIvZGF0YXNldHMvZXJlbmFrYnVsdXQvY29tbW9uLWJvdHRsZW5vc2UtZG9scGhpbi1iZWhhdmlvci92ZXJzaW9ucy8xL0RhdGEuY3N2Ig0KDQpkZiA8LSByZWFkLmNzdihkYXRhX3B0aCkgJT4lIA0KICBjbGVhbl9uYW1lcygpDQoNCmRmICU+JSANCiAgZ2xpbXBzZSgpDQpgYGANCg0KDQojIyMjIEhvdyB0byBEZWNpZGUgV2hpY2ggVmFyaWFibGVzIHRvIEFwcGx5IFNtb290aCBTcGxpbmVzIChzKCkpOg0KVGhpbmsgb2YgX3NwbGluZXNfIGFzIGJlbmRhYmxlIHJ1bGVycyB0aGF0IGFkanVzdCB0byB0aGUgc2hhcGUgb2YgdGhlIGRhdGEuIFRoZXkgYXJlIGJ1aWx0IHVzaW5nIGtub3RzLCB3aGljaCBhcmUgcG9pbnRzIHdoZXJlIHRoZSBjdXJ2ZSBjYW4gY2hhbmdlIGRpcmVjdGlvbiBzbW9vdGhseS4gVGhlIG1vc3QgY29tbW9uIHR5cGVzIGluY2x1ZGUgQi1zcGxpbmVzIGFuZCB0aGluIHBsYXRlIHJlZ3Jlc3Npb24gc3BsaW5lcywgd2hpY2ggaGVscCBjYXB0dXJlIHBhdHRlcm5zIHdpdGhvdXQgb3ZlcmZpdHRpbmcuDQoNCkluIEdBTXMsIHNwbGluZXMgYXJlIHVzZWQgdG8gbW9kZWwgbm9ubGluZWFyIGVmZmVjdHMgd2hpbGUgbWFpbnRhaW5pbmcgaW50ZXJwcmV0YWJpbGl0eS4gVGhleSBoZWxwIHJldmVhbCBoaWRkZW4gdHJlbmRzIGluIGRhdGEgdGhhdCBhIHNpbXBsZSBsaW5lYXIgbW9kZWwgbWlnaHQgbWlzcyBhbmQgYXJlIGJlc3QgYXBwbGllZCB0byBudW1lcmljIHByZWRpY3RvcnMgd2hlcmUgcmVsYXRpb25zaGlwcyB3aXRoIHRoZSB0YXJnZXQgdmFyaWFibGUgYXJlIGV4cGVjdGVkIHRvIGJlIG5vbi1saW5lYXIuIEhlcmUncyBhIHN0ZXAtYnktc3RlcCBndWlkZSBpbiBkZWNpZGluZyB3aGVyZSB0byB1c2UgdGhlbToNCg0KMS4gTG9vayBhdCBWYXJpYWJsZSBUeXBlczoNCi0gU21vb3RoIHRlcm1zIChzKCkpIGFyZSBzdWl0ZWQgZm9yIGNvbnRpbnVvdXMgbnVtZXJpYyBwcmVkaWN0b3JzIChlLmcuLCBgJHNwZWVkYCwgYCRycmAsIGAkZGlzdGFuY2VgLCBgJGxpbmApLg0KLSBBdm9pZCBhcHBseWluZyBzKCkgdG8gY2F0ZWdvcmljYWwgb3IgaW50ZWdlciB2YXJpYWJsZXMgbGlrZSBgJGNhdGAgb3IgYCRncnBzaXplYC4NCg0KMi4gQ29uc2lkZXIgdGhlIE5hdHVyZSBvZiB0aGUgUmVsYXRpb25zaGlwOg0KSWYgeW91IGJlbGlldmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGEgcHJlZGljdG9yIGFuZCB0aGUgdGFyZ2V0IHZhcmlhYmxlIGlzbid0IHN0cmljdGx5IGxpbmVhciwgc3BsaW5lcyBhcmUgaWRlYWwuIEZvciBleGFtcGxlOg0KDQotIGAkc3BlZWRgOiBEb2xwaGluIGJlaGF2aW9yIG1heSB2YXJ5IG5vbi1saW5lYXJseSB3aXRoIHN3aW1taW5nIHNwZWVkLg0KLSBgJGRpc3RhbmNlYDogQmVoYXZpb3JhbCBzdGF0ZXMgY291bGQgYmUgaW5mbHVlbmNlZCBieSBhIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwIHdpdGggdGhlIGRpc3RhbmNlIHRyYXZlbGVkLg0KDQpPbmUgd2F5IG9mIHVuZGVyc3RhbmRpbmcgdGhlIHJlbGF0aW9uc2hpcCBpcyBieSBwbG90dGluZyBmb3IgdGhlIHJlbGF0aW9uc2hpcHMsIGVhY2ggcHJlZGljdG9yIGFnYWluc3QgdGhlIHRhcmdldCB2YXJpYWJsZSB0byBvYnNlcnZlIHRoZSByZWxhdGlvbnNoaXAuIElmIHdlIHNlZSBjdXJ2ZXMgb3IgaXJyZWd1bGFyIHRyZW5kcywgKnVzZSBhIHNwbGluZSouDQoNCiMjIyMgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyAoRURBKToNClRvIGFjaGlldmUgdGhpcyB3ZSB3aWxsIGJlIHJldmlldyB0aGUgdW5kZXJseWluZyByZWxhdGlvbnNoaXBzIHRocm91Z2ggYW4gRURBLCBpLmUsIHN0YXRzLiwgdGFibGVzLCBwbG90cywgZXRjLg0KDQoNCiMjIyMjIDEuIEJhc2ljIHN1bW1hcnkgc3RhdGlzdGljcw0KYGBge3IgRGlzdHJvLiBvZiBUYXJnZXQgVmFyaWFibGUsIGVjaG8gPSBGfQ0KYmVoYXZpb3Jfc3VtbWFyeSA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkoYmVoYXYpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgY291bnQgPSBuKCksDQogICAgcHJvcG9ydGlvbiA9IG4oKS9ucm93KC4pLA0KICAgIGF2Z19zcGVlZCA9IG1lYW4oc3BlZWQsIG5hLnJtID0gVFJVRSksDQogICAgYXZnX3JyID0gbWVhbihyciwgbmEucm0gPSBUUlVFKSwNCiAgICBhdmdfbGluID0gbWVhbihsaW4sIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2Rpc3RhbmNlID0gbWVhbihkaXN0YW5jZSwgbmEucm0gPSBUUlVFKQ0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoY291bnQpKQ0KDQprYWJsZShiZWhhdmlvcl9zdW1tYXJ5LCBjYXB0aW9uID0gIkJhc2ljIGJlaGF2aW91ciBzdGF0cy4iKQ0KYGBgDQoNCiMjIyMjIDIuIERpc3RyaWJ1dGlvbiBvZiBiZWhhdmlvcnMgKGNvdW50IGFuZCBwcm9wb3J0aW9uKQ0KYGBge3IgRGlzdHJvLiBvZiBUYXJnZXQgVmFyaWFibGUgSUksIGVjaG8gPSBGLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zfQ0KZ2dwbG90KGRmLCBhZXMoeCA9IGJlaGF2LCBmaWxsID0gYmVoYXYpKSArDQogIGdlb21fYmFyKCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gYWZ0ZXJfc3RhdChjb3VudCkpLCBzdGF0ID0gImNvdW50Iiwgdmp1c3QgPSAtMC41KSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEJlaGF2aW9yIENhdGVnb3JpZXMiLCANCiAgICAgICB4ID0gIkJlaGF2aW9yIiwgeSA9ICJDb3VudCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQojIyMjIyAzLiBOdW1lcmljIHZhcmlhYmxlcyBieSBiZWhhdmlvcg0KDQpgYGB7ciBCb3hwbG90IERpc3RybywgZWNobyA9IEYsIHdhcm5pbmcgPSBGLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zfQ0KbnVtZXJpY192YXJzIDwtIGMoInNwZWVkIiwgInJyIiwgImxpbiIsICJkaXN0YW5jZSIsICJ0aW1lcGVyIikNCg0KbGFwcGx5KG51bWVyaWNfdmFycywgZnVuY3Rpb24odmFyKSB7DQogIGdncGxvdChkZiwgYWVzX3N0cmluZyh4ID0gImJlaGF2IiwgeSA9IHZhciwgZmlsbCA9ICJiZWhhdiIpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIGxhYnModGl0bGUgPSBnbHVlKCJEaXN0cmlidXRpb24gb2YgKip7dmFyfSoqIGJ5IEJlaGF2aW9yIiksIHggPSAiQmVoYXZpb3IiLCB5ID0gdmFyKSArDQogICAgdGhlbWVfbWluaW1hbCgpDQp9KQ0KYGBgDQoNCiMjIyMjIDQuIENhdGVnb3JpY2FsIHZhcmlhYmxlcyBieSBiZWhhdmlvcg0KLT4gR3JvdXAgc2l6ZQ0KYGBge3IgQ2F0ZWdvcmljYWwgRGlzdHJvLCBlY2hvID0gRiwgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9M30NCmdncGxvdChkZiwgYWVzKHggPSBmYWN0b3IoZ3Jwc2l6ZSksIGZpbGwgPSBiZWhhdikpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgbGFicyh0aXRsZSA9ICJCZWhhdmlvciBEaXN0cmlidXRpb24gYnkgR3JvdXAgU2l6ZSIsDQogICAgICAgeCA9ICJHcm91cCBTaXplIiwgeSA9ICJQcm9wb3J0aW9uIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQotPiBDYWxmIHByZXNlbmNlDQpgYGB7ciBQcmVzZW5jZSBvZiBDYWxmLCBlY2hvID0gRiwgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9M30NCmdncGxvdChkZiwgYWVzKHggPSBmYWN0b3IoY2FsZiksIGZpbGwgPSBiZWhhdikpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgbGFicyh0aXRsZSA9ICJCZWhhdmlvciBEaXN0cmlidXRpb24gYnkgQ2FsZiBQcmVzZW5jZSIsDQogICAgICAgeCA9ICJDYWxmIFByZXNlbnQgKDE9WWVzKSIsIHkgPSAiUHJvcG9ydGlvbiIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KLT4gQ2F0ZWdvcnkNCmBgYHtyLCBlY2hvID0gRiwgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9M30NCmdncGxvdChkZiwgYWVzKHggPSBjYXQsIGZpbGwgPSBiZWhhdikpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgbGFicyh0aXRsZSA9ICJCZWhhdmlvciBEaXN0cmlidXRpb24gYnkgQ2F0ZWdvcnkiLA0KICAgICAgIHggPSAiQ2F0ZWdvcnkiLCB5ID0gIlByb3BvcnRpb24iKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMjIyMjIDUuIFRpbWVwZXIgKHRpbWUgcGVyaW9kKSBhbmFseXNpcw0KYGBge3IgVGltZSBwZXJpb2QgZGVuc2l0eSwgZWNobyA9IEYsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTN9DQpnZ3Bsb3QoZGYsIGFlcyh4ID0gdGltZXBlciwgZmlsbCA9IGJlaGF2KSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjYpICsNCiAgbGFicyh0aXRsZSA9ICJCZWhhdmlvciBEaXN0cmlidXRpb24gQWNyb3NzIFRpbWUgUGVyaW9kcyIsDQogICAgICAgeCA9ICJUaW1lIFBlcmlvZCIsIHkgPSAiRGVuc2l0eSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KIyMjIyMgNi4gUGFpcndpc2UgcmVsYXRpb25zaGlwcyBjb2xvcmVkIGJ5IGJlaGF2aW9yDQpTbWFsbGVyIHNhbXBsZSBmb3IgYmV0dGVyIHZpc3VhbGl6YXRpb24gaWYgZGF0YXNldCBpcyBsYXJnZQ0KYGBge3IgUGFpcndpc2UgZGVuc2l0eSwgZWNobyA9IEYsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTN9DQojIHNldC5zZWVkKDEyMykNCiMgc2FtcGxlX2RmIDwtIGRmICU+JSANCiMgICBzZWxlY3QoYWxsX29mKG51bWVyaWNfdmFycyksIGJlaGF2KSAlPiUNCiMgICBzYW1wbGVfbihtaW4oMTAwLCBucm93KC4pKSkNCg0KIyBVc2UgZ2dwYWlycyB3aXRob3V0IGNvcnJlbGF0aW9uIHRlc3RzDQpnZ3BhaXJzKGRmLCANCiAgICAgICAgY29sdW1ucyA9IG51bWVyaWNfdmFycywNCiAgICAgICAgbWFwcGluZyA9IGFlcyhjb2xvciA9IGJlaGF2KSwNCiAgICAgICAgdXBwZXIgPSBsaXN0KGNvbnRpbnVvdXMgPSAiYmxhbmsiKSwgICMgU2tpcCBjb3JyZWxhdGlvbg0KICAgICAgICBsb3dlciA9IGxpc3QoDQogICAgICAgICAgY29udGludW91cyA9IHdyYXAoInBvaW50cyIsIGFscGhhID0gMC4zLCBzaXplID0gMC41KSwNCiAgICAgICAgICBjb21ibyA9IHdyYXAoImZhY2V0aGlzdCIsIGJpbnMgPSAyMCkNCiAgICAgICAgKSkgKw0KICBsYWJzKHRpdGxlID0gIlBhaXJ3aXNlIFJlbGF0aW9uc2hpcHMgYnkgQmVoYXZpb3IiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMjIyMjIERpc3NlY3RpbmcgdGhlIHBsb3RzDQoqKlBhaXJ3aXNlIFJlbGF0aW9uc2hpcHMqKg0KDQoxLiBTcGVlZCB2cy4gUmVzcGlyYXRpb24gUmF0ZSAocnIpDQoNClRoZXJlJ3MgYSBub3RpY2VhYmxlIGRpc3RpbmN0aW9uIGJldHdlZW4gYmVoYXZpb3IgdHlwZXMgYmFzZWQgb24gc3BlZWQgYW5kIHJyLg0KDQpGb3JhZ2luZyBiZWhhdmlvciBvY2N1cnMgYXQgbG93ZXIgc3BlZWRzIGJ1dCBoaWdoZXIgcnIsIHBvc3NpYmx5IGluZGljYXRpbmcgZXhlcnRpb24gZnJvbSBodW50aW5nLg0KDQpSZXN0aW5nIHNob3dzIG1vZGVyYXRlIHNwZWVkIGJ1dCBsb3dlciByciwgd2hpY2ggYWxpZ25zIHdpdGggcmVkdWNlZCBtb3ZlbWVudC4NCg0KMi4gRGlzdGFuY2UgdnMuIFNwZWVkDQoNCk5vbi1saW5lYXIgdHJlbmRzIGVtZXJnZTogZG9scGhpbnMgY292ZXJpbmcgZ3JlYXRlciBkaXN0YW5jZXMgdGVuZCB0byBtYWludGFpbiBhIGNvbnNpc3RlbnQgc3BlZWQgaW5zdGVhZCBvZiBmbHVjdHVhdGluZyBmcmVxdWVudGx5Lg0KDQpUcmF2ZWwgYmVoYXZpb3Igc2VlbXMgZGlzdHJpYnV0ZWQgYWNyb3NzIG1pZC1yYW5nZSBkaXN0YW5jZXMgYW5kIHNwZWVkIGxldmVscy4NCg0KMy4gR3JvdXAgU2l6ZSB2cy4gQmVoYXZpb3INCg0KTGFyZ2VyIGdyb3VwcyBzaG93IG1vcmUgZnJlcXVlbnQgc29jaWFsIGludGVyYWN0aW9ucywgd2l0aCBmb3JhZ2luZyBiZWhhdmlvcnMgb2Z0ZW4gaGFwcGVuaW5nIGluIHNtYWxsZXIgZ3JvdXBzLg0KDQpSZXN0aW5nIGFwcGVhcnMgdG8gb2NjdXIgYXQgdmFyaWFibGUgZ3JvdXAgc2l6ZXMsIHN1Z2dlc3RpbmcgaXQgbWlnaHQgbm90IGJlIGdyb3VwLWRlcGVuZGVudC4NCg0KNC4gUHJlc2VuY2Ugb2YgYSBDYWxmIHZzLiBCZWhhdmlvcg0KDQpUaGUgcHJlc2VuY2Ugb2YgYSBjYWxmIGRvZXMgbm90IHN0cm9uZ2x5IGluZmx1ZW5jZSBiZWhhdmlvciwgYmFzZWQgb24gbW9kZWwgb3V0cHV0IHNpZ25pZmljYW5jZSBsZXZlbHMuDQoNCkNhbGYgcHJlc2VuY2UgbWlnaHQgYmUgYW4gaW5kZXBlbmRlbnQgZmFjdG9yIHJhdGhlciB0aGFuIGEgcHJpbWFyeSBiZWhhdmlvcmFsIGRldGVybWluYW50Lg0KDQojIyMjIyA3LiBJbmRpdmlkdWFsIHBhdHRlcm5zIChpZiBJRHMgcmVwcmVzZW50IGluZGl2aWR1YWxzKQ0KYGBge3J9DQppZihsZW5ndGgodW5pcXVlKGRmJGlkKSkgPCAyMCkgeyAgIyBPbmx5IHBsb3QgaWYgbm90IHRvbyBtYW55IGluZGl2aWR1YWxzDQogIGdncGxvdChkZiwgYWVzKHggPSBpZCwgZmlsbCA9IGJlaGF2KSkgKw0KICAgIGdlb21fYmFyKCkgKw0KICAgIGxhYnModGl0bGUgPSAiQmVoYXZpb3IgRGlzdHJpYnV0aW9uIGJ5IEluZGl2aWR1YWwgSUQiLA0KICAgICAgICAgeCA9ICJJbmRpdmlkdWFsIElEIiwgeSA9ICJDb3VudCIpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQp9DQpgYGANCg0KIyMjIyMgIDguIENvdW50IHZzIGJlaGF2aW9yDQpgYGB7ciwgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9M30NCmdncGxvdChkZiwgYWVzKHggPSBiZWhhdiwgeSA9IGNvdW50LCBmaWxsID0gYmVoYXYpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgbGFicyh0aXRsZSA9ICJDb3VudCBEaXN0cmlidXRpb24gYnkgQmVoYXZpb3IiLA0KICAgICAgIHggPSAiQmVoYXZpb3IiLCB5ID0gIkNvdW50IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoqKklEJ3MgYW5kIGNvdW50KioNCkZyb20gdGhlIGRpc3RyaWJ1dGlvbnMgYWJvdmUgLSB3ZSd2ZSBub3cgZ290IHRoZSBmb2xsb3dpbmcgdW5kZXJzdGFuZGluZyBvZiB3aGF0IHRoZSByZWxhdGlvbnNoaXBzIGFyZToNCg0KMS4gTnVtZXJpYyBWYXJpYWJsZXMgJiBCZWhhdmlvcg0KDQpUaGUgYm94cGxvdHMgc3VnZ2VzdCB0aGF0IGJlaGF2aW9ycyB2YXJ5IGJhc2VkIG9uIG51bWVyaWNhbCBwcmVkaWN0b3JzIGxpa2Ugc3BlZWQsIGRpc3RhbmNlLCBhbmQgcnIgKHBvc3NpYmx5IHJlc3BpcmF0aW9uIHJhdGUpLg0KDQpGb3JhZ2luZyBiZWhhdmlvciBpcyBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIHJyIGFuZCBsb3dlciBzcGVlZCBjb21wYXJlZCB0byBvdGhlciBiZWhhdmlvcnMuDQoNClJlc3RpbmcgdGVuZHMgdG8gb2NjdXIgYXQgbW9kZXJhdGUgcnIgYW5kIHNwZWVkIGxldmVscy4NCg0KMi4gQ2F0ZWdvcmljYWwgVmFyaWFibGVzICYgQmVoYXZpb3INCg0KR3JvdXAgc2l6ZSBhbmQgY2FsZiBwcmVzZW5jZSBzZWVtIHRvIGhhdmUgc29tZSBpbXBhY3Qgb24gYmVoYXZpb3JzLCB3aXRoIGxhcmdlciBncm91cHMgc2hvd2luZyBkaWZmZXJlbnQgYmVoYXZpb3JhbCBkaXN0cmlidXRpb25zLg0KDQoNCioqS2V5IFRha2Vhd2F5cyoqDQpCZWhhdmlvcmFsIHN0YXRlcyBhcmUgaW5mbHVlbmNlZCBieSBib3RoIGxpbmVhciBhbmQgbm9uLWxpbmVhciByZWxhdGlvbnNoaXBzLg0KDQpTcGVlZCBhbmQgcmVzcGlyYXRpb24gcmF0ZSBpbnRlcmFjdCBpbiBhIHdheSB0aGF0IGRpZmZlcmVudGlhdGVzIGFjdGl2ZSBiZWhhdmlvcnMgZnJvbSBwYXNzaXZlIG9uZXMuDQoNCldlIGNhbiBiZWdpbiB0byBzZW5zZSBob3cgdGhlIHByZWRpY3RpdmUgbW9kZWwgd291bGQgcmVpbmZvcmNlIHRoZXNlIGdyb3VwIGR5bmFtaWNzIG1hdHRlciwgbGlrZSBob3cgY2FsZiBwcmVzZW5jZSBkb2VzIG5vdCBzaG93IHN0cm9uZyBwcmVkaWN0aXZlIGluZmx1ZW5jZSBvbiBob3cgdGhlIGRvbHBoaW5zIHdpbGwgbGFyZ2VseSBiZWhhdmUuIERpc3RhbmNlIHRyYXZlbGVkIGFsc28gc3VnZ2VzdHMgYSBwYXR0ZXJuZWQgbW92ZW1lbnQgc3RyYXRlZ3kgcmF0aGVyIHRoYW4gcmFuZG9tbmVzcy4NCg0KIyMgR0FNIEFuYWx5c2lzDQoNCmBgYHtyIFNwbGl0cywgZWNobyA9IFR9DQpzZXQuc2VlZCgyMzQpDQpkYXRhX3NwbGl0IDwtIGluaXRpYWxfc3BsaXQoZGYsIHByb3AgPSAwLjgpDQp0cmFpbl9kYXRhIDwtIHRyYWluaW5nKGRhdGFfc3BsaXQpICU+JSANCiAgbXV0YXRlKA0KICAgIGJlaGF2ID0gYXMuZmFjdG9yKGJlaGF2KSMsDQogICAgIyBncnBzaXplID0gYXMuaW50ZWdlcihncnBzaXplKSwNCiAgICAjIGNhbGYgPSBhcy5pbnRlZ2VyKGNhbGYpDQogICkNCnRlc3RfZGF0YSA8LSB0ZXN0aW5nKGRhdGFfc3BsaXQpDQpgYGANCg0KRm9yIHRoZSAqR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWwgKEdBTSkqLCB3ZSB3aWxsIHVzZSB0aGUgX21nY3ZfIHBhY2thZ2UgLSBpdCBpbnRlZ3JhdGVzIHdlbGwgd2l0aCBUaWR5bW9kZWxzLg0KDQpgYGB7ciBHQU0sIGVjaG8gPSBGLCBldmFsID0gRn0NCiMjIFNwZWNpZmljYXRpb25zIC0gc2V0IHRvIHJlZ3Jlc3Npb24gbW9kZQ0KIyBnYW1fc3BlYyA8LSBnZW5fYWRkaXRpdmVfbW9kKCkgJT4lIA0KIyAgIHNldF9lbmdpbmUoIm1nY3YiKSAlPiUgDQojICAgc2V0X21vZGUoImNsYXNzaWZpY2F0aW9uIikNCiMgDQojICMjIEZvcm11bGE6IERlZmluZSByZWxhdGlvbnNoaXANCiMgIyBnYW1fZm9ybXVsYSA8LSBiZWhhdiB+IHMoc3BlZWQpICsgcyhycikgKyBzKGRpc3RhbmNlKSArIHMobGluKSArIGdycHNpemUgKyBjYWxmDQojIA0KIyAjIyBSZWNpcGUNCiMgZ2FtX3JlY2lwZSA8LSByZWNpcGUoYmVoYXYgfiBzcGVlZCArIHJyICsgZGlzdGFuY2UgKyBsaW4gKyBncnBzaXplICsgY2FsZiwgZGF0YSA9IHRyYWluX2RhdGEpICU+JQ0KIyAgIHN0ZXBfbm9ybWFsaXplKGFsbF9udW1lcmljX3ByZWRpY3RvcnMoKSkgJT4lDQojICAgc3RlcF9ucyhzcGVlZCwgcnIsIGRpc3RhbmNlLCBsaW4sIGRlZ19mcmVlID0gMykgDQojIA0KIyAjIyBDcmVhdGUgV29ya2Zsb3cNCiMgd29ya2Zsb3cgPC0gd29ya2Zsb3coKSAlPiUgDQojICAgYWRkX21vZGVsKGdhbV9zcGVjKSAlPiUNCiMgICAjIGFkZF9mb3JtdWxhKGdhbV9mb3JtdWxhKQ0KIyAgIGFkZF9yZWNpcGUoZ2FtX3JlY2lwZSkNCiMgDQojICMjIFRyYWluIE1vZGVsIG9uIHRoZSBUcmFpbmluZyBkYXRhDQojIGdhbV9maXQgPC0gd29ya2Zsb3cgJT4lIA0KIyAgIGZpdChkYXRhID0gdHJhaW5fZGF0YSkNCmBgYA0KDQoNCkFwcGx5IGRpcmVjdGx5IHRvIHRoZSBfbWdjdl8gbGlicmFyeQ0KYGBge3IgbWdjdiwgZWNobyA9IFR9DQpnYW1fZm9ybXVsYSA8LSBiZWhhdiB+IHMoc3BlZWQpICsgcyhycikgKyBzKGRpc3RhbmNlKSArIHMobGluKSArIGdycHNpemUgKyBjYWxmICMgKyB0ZShncnBzaXplLCBjYWxmKSwgcyhzcGVlZCwgaz0xMCkNCg0KZ2FtX21vZGVsIDwtIGdhbSgNCiAgZ2FtX2Zvcm11bGEsDQogIGRhdGEgPSB0cmFpbl9kYXRhLA0KICBmYW1pbHkgPSBiaW5vbWlhbCgpLA0KICBtZXRob2QgPSAiUkVNTCINCikNCg0Kc3VtbWFyeShnYW1fbW9kZWwpDQpgYGANCg0KDQoNCioqU21vb3RoIFRlcm1zIChTcGxpbmVzKSBpbiBHQU0gQW5hbHlzaXMqKg0KDQpUaGUgR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWwgKEdBTSkgc3VnZ2VzdHMgdGhhdCBzb21lIHJlbGF0aW9uc2hpcHMgYXJlIG5vbi1saW5lYXIsIGVzcGVjaWFsbHkgZm9yIGRpc3RhbmNlIChzaWduaWZpY2FudCBzbW9vdGggdGVybSkgYW5kIHBvc3NpYmx5IHJyLg0KDQpfU3BlZWRfIGRvZXMgbm90IHNob3cgYSBzdHJvbmcgbm9uLWxpbmVhciBlZmZlY3QsIHN1Z2dlc3RpbmcgaXRzIGluZmx1ZW5jZSBtaWdodCBiZSBtb3JlIGxpbmVhci4NCg0KKipPdmVyYWxsIE1vZGVsIFBlcmZvcm1hbmNlKioNCg0KVGhlIGV4cGxhaW5lZCBkZXZpYW5jZSBvZiA1MiUgaW5kaWNhdGVzIGEgcmVhc29uYWJsZSBhYmlsaXR5IHRvIGNhcHR1cmUgYmVoYXZpb3IgdmFyaWFiaWxpdHkgd2l0aCB0aGVzZSBwcmVkaWN0b3JzLg0KDQpUaGUgc2lnbmlmaWNhbmNlIGxldmVscyBzdWdnZXN0IHRoYXQgZ3JvdXAgc2l6ZSBoYXMgYSBzdHJvbmcgZWZmZWN0LCB3aGlsZSBjYWxmIHByZXNlbmNlIGRvZXMgbm90Lg0KDQpCYXNlZCBvbiB0aGlzLCBiZWhhdmlvcnMgYXBwZWFyIGluZmx1ZW5jZWQgYnkgYm90aCAqbGluZWFyKiBhbmQgKm5vbi1saW5lYXIqIHJlbGF0aW9uc2hpcHMsIHdpdGggX2Rpc3RhbmNlXyBhbmQgX3Jlc3BpcmF0aW9uIHJhdGVfIHNob3dpbmcgbm9uLWxpbmVhciBwYXR0ZXJucy4NCg0KTm93IHdlIGhhdmUgYnVpbHQgYSBiYXNlbGluZSBtb2RlbCB0aGF0IGFjY29tb2RhdGVzIGZvciB0aGUgYmFzaWNzIGFuZCBhbiB1bmRlcnN0YW5kaW5nIG9yIEJBVSBndWlkZSB0byB1c2luZyB0aGUgR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWwsIGZvciBsaW5lYXIgYW5kIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwcy4uDQoNCg0KYGBge3IgRXZhbHVhdGUgTW9kZWwsIGVjaG8gPSBUfQ0KcHJlZGljdGlvbnMgPC0gcHJlZGljdChnYW1fZml0LCBuZXdfZGF0YSA9IHRlc3RfZGF0YSkgJT4lIA0KICBiaW5kX2NvbHModGVzdF9kYXRhKQ0KDQptZXRyaWNzIDwtIHByZWRpY3Rpb25zICU+JSANCiAgbWV0cmljcyh0cnV0aCA9IGJlaGF2LCBlc3RpbWF0ZSA9IC5wcmVkKQ0KDQpwcmludChtZXRyaWNzKQ0KYGBgDQoNCg0KYGBge3IgVml6IFJlc3VsdHMsIGVjaG8gPSBUfQ0KZ2dwbG90KHByZWRpY3Rpb25zLCBhZXMoeCA9IGJlaGF2LCB5ID0gLnByZWQpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fYWJsaW5lKHNsb3BlID0gMSwgaW50ZXJjZXB0ID0gMCwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIkdBTSBQcmVkaWN0aW9ucyB2cyBBY3R1YWwiLA0KICAgICAgIHggPSAiQWN0dWFsIFZhbHVlcyIsDQogICAgICAgeSA9ICJQcmVkaWN0ZWQgVmFsdWVzIikNCmBgYA0KDQoNCioqT3RoZXIgVGhvdWdodHMgJiBJbnRlcnByZXRhdGlvbioqDQpMb29raW5nIGRlZXBlciBpbnRvIGNhbGYgcHJlc2VuY2UgYW5kIGl0cyBpbmZsdWVuY2Ugb24gYmVoYXZpb3IsIHRoZSBhbmFseXNpcyBzdWdnZXN0cyB0aGF0IGNhbHZlcyBkbyBub3Qgc2lnbmlmaWNhbnRseSBpbXBhY3QgZG9scGhpbiBiZWhhdmlvciB3aXRoaW4gdGhpcyBkYXRhc2V0LiBIZXJlJ3Mgd2h5Og0KDQpTdGF0aXN0aWNhbCBJbnNpZ2h0czogDQpUaGUgcC12YWx1ZSBmb3IgY2FsZiBwcmVzZW5jZSBpbiB0aGUgbW9kZWwgaXMgMC4zNzcsIGluZGljYXRpbmcgYSBub24tc2lnbmlmaWNhbnQgZWZmZWN0IG9uIGJlaGF2aW9yLg0KDQpDb21wYXJlIHRoaXMgdG8gZ3JvdXAgc2l6ZSwgd2hpY2ggaGFzIGEgaGlnaGx5IHNpZ25pZmljYW50IGVmZmVjdCAocC12YWx1ZSA9IDEuODJlLTA1KeKAlHNob3dpbmcgdGhhdCBsYXJnZXIgZ3JvdXBzIHN0cm9uZ2x5IGluZmx1ZW5jZSBiZWhhdmlvciwgYnV0IHRoZSBwcmVzZW5jZSBvZiBhIGNhbGYgZG9lcyBub3QuDQoNCk9ic2VydmVkIFBhdHRlcm5zOiANCldoaWxlIHRoZSBHQU0gbW9kZWwgZGlkIGFjY291bnQgZm9yIGNhbGYgcHJlc2VuY2UsIHRoZSBsYWNrIG9mIHNpZ25pZmljYW5jZSBtZWFucyBpdCBkb2Vzbid0IGRpZmZlcmVudGlhdGUgYmVoYXZpb3JzIGNsZWFybHkgYmFzZWQgb24gd2hldGhlciBhIGNhbGYgaXMgcHJlc2VudCBvciBub3QuDQoNClRoZSBib3hwbG90cyBhbmQgcGFpcndpc2UgcmVsYXRpb25zaGlwcyBmdXJ0aGVyIGNvbmZpcm0gbm8gc3Ryb25nIGJlaGF2aW9yYWwgc2hpZnRzIHdoZW4gY2FsdmVzIGFyZSBpbiB0aGUgZ3JvdXAuDQoNClVubGlrZSBncm91cCBzaXplLCB3aGljaCBpbmZsdWVuY2VzIHNvY2lhbCBpbnRlcmFjdGlvbnMgYW5kIG1vdmVtZW50IGR5bmFtaWNzLCBjYWx2ZXMgc2VlbSB0byBiZSBtb3JlIHBhc3NpdmUgcGFydGljaXBhbnRzIGluIGJlaGF2aW9yYWwgc2hpZnRzLg0KDQpEb2xwaGlucyBtaWdodCBwcmlvcml0aXplIHByb3RlY3RpdmUgYmVoYXZpb3Igb3ZlciBkaXN0aW5jdCBiZWhhdmlvcmFsIGNoYW5nZXMgd2hlbiBjYWx2ZXMgYXJlIGFyb3VuZCwgYnV0IHRoaXMgaXNu4oCZdCBzdHJvbmdseSByZWZsZWN0ZWQgaW4gbW92ZW1lbnQgbWV0cmljcyBsaWtlIHNwZWVkLCByZXNwaXJhdGlvbiByYXRlLCBvciBkaXN0YW5jZSB0cmF2ZWxlZC4NCg0KDQoNCg0KDQo=