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:

  1. 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.
  1. 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.
behav count proportion avg_speed avg_rr avg_lin avg_distance
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

  1. 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.

  1. 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.

  1. 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.

  1. 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:

  1. 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.

  1. 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=