1 . Purpose of the Quiz

This Quiz 4 focuses on logistic regression: building a model, interpreting results, and giving managerial recommendations.

We will follow these steps:

  • Step 1 — Model construction: Define a binary outcome (Subscribe: Yes=1) and choose two predictors (Age, Gender).
  • Step 2 — Interpretation: Interpret coefficients using odds ratios and predicted probabilities.
  • Step 3 — Managerial recommendations: Translate results into clear business actions.
  • Step 4 — Value add: A simple predicted probability plot and example profiles.

Important note: The goal is not advanced coding.
The goal is correct interpretation and manager-friendly insights.

2 . Load Libraries & Read Data

# ==========================================================
# 2.1 Libraries
# - readxl: to read Excel
# - dplyr: data manipulation
# - ggplot2: visualization
# - broom: tidy model output into clean tables
# - tidyr: reshape data for plotting
# ==========================================================

library(readxl)
library(dplyr)
library(ggplot2)
library(broom)
library(tidyr)

# ==========================================================
# 2.2 Read Excel Data
# - We read the sheet named "data"
# ==========================================================

df_raw <- read_excel("Logitsubscribedata.xlsx", sheet = "data")

# Quick look at structure and first rows
str(df_raw)
## tibble [1,345 × 3] (S3: tbl_df/tbl/data.frame)
##  $ Age               : num [1:1345] 33 45 57 32 56 60 40 55 27 48 ...
##  $ Gender (W=1)      : num [1:1345] 0 1 0 1 0 1 0 0 0 1 ...
##  $ Subscribe? (Yes=1): num [1:1345] 0 0 0 0 0 1 0 0 0 0 ...
head(df_raw)
## # A tibble: 6 × 3
##     Age `Gender (W=1)` `Subscribe? (Yes=1)`
##   <dbl>          <dbl>                <dbl>
## 1    33              0                    0
## 2    45              1                    0
## 3    57              0                    0
## 4    32              1                    0
## 5    56              0                    0
## 6    60              1                    1

Interpretation (Data check):
We confirm we have 3 columns: Age, Gender (W=1), and Subscribe (Yes=1).
This is a binary classification problem because Subscribe is 0/1.

3 . Data Preparation (Clean names + types)

# ==========================================================
# 3.1 Rename columns to simpler names
# - gender_w: 1 if Woman, 0 if Man (based on the column name)
# - subscribe: 1 if Yes, 0 if No
# ==========================================================

df <- df_raw %>%
  rename(
    gender_w  = `Gender (W=1)`,
    subscribe = `Subscribe? (Yes=1)`
  )

# ==========================================================
# 3.2 Ensure correct data types
# - Logistic regression expects the outcome as 0/1 numeric
# ==========================================================

df <- df %>%
  mutate(
    gender_w  = as.integer(gender_w),
    subscribe = as.integer(subscribe),
    Age       = as.numeric(Age)
  )

# Confirm again
str(df)
## tibble [1,345 × 3] (S3: tbl_df/tbl/data.frame)
##  $ Age      : num [1:1345] 33 45 57 32 56 60 40 55 27 48 ...
##  $ gender_w : int [1:1345] 0 1 0 1 0 1 0 0 0 1 ...
##  $ subscribe: int [1:1345] 0 0 0 0 0 1 0 0 0 0 ...
summary(df)
##       Age           gender_w        subscribe     
##  Min.   :20.00   Min.   :0.0000   Min.   :0.0000  
##  1st Qu.:29.00   1st Qu.:0.0000   1st Qu.:0.0000  
##  Median :40.00   Median :1.0000   Median :0.0000  
##  Mean   :39.65   Mean   :0.5078   Mean   :0.2379  
##  3rd Qu.:50.00   3rd Qu.:1.0000   3rd Qu.:0.0000  
##  Max.   :60.00   Max.   :1.0000   Max.   :1.0000

Interpretation (Cleaning):
We renamed columns for easier coding and ensured Age is numeric and the binary variables are integers (0/1).
This helps avoid common R issues (e.g., numbers read as text).

4 . Quick Descriptive Statistics

# ==========================================================
# 4.1 Outcome distribution: how many subscribed vs not
# ==========================================================
table(df$subscribe)
## 
##    0    1 
## 1025  320
# ==========================================================
# 4.2 Age summary
# ==========================================================
summary(df$Age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   20.00   29.00   40.00   39.65   50.00   60.00
# ==========================================================
# 4.3 Gender distribution
# ==========================================================
table(df$gender_w)
## 
##   0   1 
## 662 683
# Subscription rate (mean of 0/1)
mean(df$subscribe)
## [1] 0.2379182

Interpretation (Descriptives):
- The dataset has 1,345 observations.
- The subscription rate is about 24% (mean of 0/1).
- Age ranges from 20 to 60 (median around 40).
- Gender is balanced (similar counts for men vs women).

These statistics provide context before modeling.

5 . Step 1 — Logistic Regression Model

We model subscription likelihood using two predictors:

  • Age (continuous)
  • Gender (Woman=1)

Logistic regression is appropriate because the outcome is binary (0/1).

# ==========================================================
# 5.1 Logistic regression model
# glm(..., family = binomial) fits a logistic regression
#
# Model form:
# log(odds(subscribe)) = b0 + b1*Age + b2*gender_w
# ==========================================================

m1 <- glm(subscribe ~ Age + gender_w, data = df, family = binomial)

# Main model output
summary(m1)
## 
## Call:
## glm(formula = subscribe ~ Age + gender_w, family = binomial, 
##     data = df)
## 
## Coefficients:
##              Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  0.597628   0.230870   2.589  0.00964 ** 
## Age         -0.052399   0.005895  -8.888  < 2e-16 ***
## gender_w     0.407014   0.133725   3.044  0.00234 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 1475.9  on 1344  degrees of freedom
## Residual deviance: 1381.1  on 1342  degrees of freedom
## AIC: 1387.1
## 
## Number of Fisher Scoring iterations: 4

Interpretation (Model output – high level):
- Check the sign of coefficients (positive/negative).
- Check p-values to see which predictors are statistically significant.

From the output:
- Age coefficient is negative and highly significant → older customers are less likely to subscribe.
- Gender (Woman=1) coefficient is positive and significant → women are more likely to subscribe.

6 . Step 2 — Odds Ratios

Logistic coefficients are in log-odds. To interpret in a simpler way, we convert them to odds ratios (OR):

  • OR > 1 → increases odds of subscribing
  • OR < 1 → decreases odds of subscribing
# ==========================================================
# 6.1 Odds Ratios + Confidence Intervals
# exponentiate = TRUE means exp(coef) -> odds ratio
# ==========================================================

or_table <- tidy(m1, conf.int = TRUE, exponentiate = TRUE)
or_table
## # A tibble: 3 × 7
##   term        estimate std.error statistic  p.value conf.low conf.high
##   <chr>          <dbl>     <dbl>     <dbl>    <dbl>    <dbl>     <dbl>
## 1 (Intercept)    1.82    0.231        2.59 9.64e- 3    1.16      2.86 
## 2 Age            0.949   0.00590     -8.89 6.22e-19    0.938     0.960
## 3 gender_w       1.50    0.134        3.04 2.34e- 3    1.16      1.95

Interpretation (Odds ratios):
- Age OR ≈ 0.95: each additional year decreases the odds of subscribing by about 5% (1 - 0.95).
- Gender (Woman) OR ≈ 1.50: women have about 50% higher odds of subscribing than men.

Both predictors are statistically significant (small p-values).

7 . Predicted Probabilities

Managers understand probabilities better than odds. We compute predicted probabilities for example profiles:

  • Ages: 25, 45, 65
  • Gender: Man (0) vs Woman (1)
# ==========================================================
# 7.1 Example profiles
# predict(..., type="response") returns predicted probability (0-1)
# ==========================================================

profiles <- data.frame(
  Age = c(25, 25, 45, 45, 65, 65),
  gender_w = c(0, 1, 0, 1, 0, 1)
)

profiles$pred_prob <- predict(m1, newdata = profiles, type = "response")
profiles
##   Age gender_w  pred_prob
## 1  25        0 0.32908212
## 2  25        1 0.42425609
## 3  45        0 0.14675107
## 4  45        1 0.20533140
## 5  65        0 0.05687796
## 6  65        1 0.08307560

Interpretation (Predicted probabilities):
- Younger customers have much higher predicted subscription probability.
- At every age, women have higher probability than men.

Example (from our output):
- Age 25: ~0.33 (men) vs ~0.42 (women)
- Age 45: ~0.15 (men) vs ~0.21 (women)
- Age 65: ~0.06 (men) vs ~0.08 (women)

8 . Visualization

We create a smooth probability curve by age for men vs women.

# ==========================================================
# 8.1 Create an age grid for predictions
# ==========================================================

age_grid_m <- data.frame(
  Age = seq(min(df$Age), max(df$Age), by = 1),
  gender_w = 0
)
age_grid_m$pred_prob <- predict(m1, newdata = age_grid_m, type = "response")
age_grid_m$Group <- "Men"

age_grid_w <- data.frame(
  Age = seq(min(df$Age), max(df$Age), by = 1),
  gender_w = 1
)
age_grid_w$pred_prob <- predict(m1, newdata = age_grid_w, type = "response")
age_grid_w$Group <- "Women"

plot_df <- bind_rows(age_grid_m, age_grid_w)

# ==========================================================
# 8.2 Plot
# ==========================================================

ggplot(plot_df, aes(x = Age, y = pred_prob, linetype = Group)) +
  geom_line(linewidth = 1) +
  labs(
    title = "Predicted Subscription Probability by Age and Gender",
    x = "Age",
    y = "Predicted probability of subscribing",
    linetype = "Group"
  ) +
  theme_minimal()

Interpretation (Plot):
- The curve decreases with age → subscription probability decreases as customers get older.
- The women curve is above the men curve → women are more likely to subscribe at each age.

9 . Step 3 — Managerial Recommendations

Based on the model:

  1. Focus acquisition campaigns on younger customers
  • Age is the strongest driver. Younger customers have the highest conversion potential.
  1. Women are a higher-likelihood segment
  • Women have ~50% higher odds of subscribing than men (OR ≈ 1.50).
  • Use channels and messaging that perform well for this segment.
  1. Improve conversion for older customers with targeted actions
  • For older customers, test clearer value communication, simpler onboarding, and tailored offers.

Manager-friendly conclusion:
Age significantly reduces subscription likelihood, while being female increases it. Therefore, marketing should prioritize younger segments (especially women) for acquisition, and develop specific strategies to improve conversion among older customers.

10 . Limitations

  • We used only two predictors (as required by the quiz). Real-world models may need more variables.
  • This model shows association, not guaranteed causation.
  • We did not test interactions (e.g., Age × Gender). This can be explored if required.
LS0tCnRpdGxlOiAiTWlNODExIFRIIFF1aXogNCDigJMgTG9naXN0aWMgUmVncmVzc2lvbiIKYXV0aG9yOiAiR8O8bMWfYWggw4dhbMSxxZ9rYW4iCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogZmxhdGx5CiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEdsb2JhbCBvcHRpb25zIGZvciBjbGVhbiBIVE1MCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UKKQpgYGAKCiMgLiBQdXJwb3NlIG9mIHRoZSBRdWl6CgpUaGlzIFF1aXogNCBmb2N1c2VzIG9uICoqbG9naXN0aWMgcmVncmVzc2lvbioqOiBidWlsZGluZyBhIG1vZGVsLCBpbnRlcnByZXRpbmcgcmVzdWx0cywgYW5kIGdpdmluZyAqKm1hbmFnZXJpYWwgcmVjb21tZW5kYXRpb25zKiouCgpXZSB3aWxsIGZvbGxvdyB0aGVzZSBzdGVwczoKCi0gKipTdGVwIDEg4oCUIE1vZGVsIGNvbnN0cnVjdGlvbjoqKiBEZWZpbmUgYSBiaW5hcnkgb3V0Y29tZSAoU3Vic2NyaWJlOiBZZXM9MSkgYW5kIGNob29zZSAqKnR3byBwcmVkaWN0b3JzKiogKEFnZSwgR2VuZGVyKS4KLSAqKlN0ZXAgMiDigJQgSW50ZXJwcmV0YXRpb246KiogSW50ZXJwcmV0IGNvZWZmaWNpZW50cyB1c2luZyAqKm9kZHMgcmF0aW9zKiogYW5kICoqcHJlZGljdGVkIHByb2JhYmlsaXRpZXMqKi4KLSAqKlN0ZXAgMyDigJQgTWFuYWdlcmlhbCByZWNvbW1lbmRhdGlvbnM6KiogVHJhbnNsYXRlIHJlc3VsdHMgaW50byBjbGVhciBidXNpbmVzcyBhY3Rpb25zLgotICoqU3RlcCA0IOKAlCBWYWx1ZSBhZGQ6KiogQSBzaW1wbGUgcHJlZGljdGVkIHByb2JhYmlsaXR5IHBsb3QgYW5kIGV4YW1wbGUgcHJvZmlsZXMuCgo+IEltcG9ydGFudCBub3RlOiBUaGUgZ29hbCBpcyBub3QgYWR2YW5jZWQgY29kaW5nLiAgCj4gVGhlIGdvYWwgaXMgY29ycmVjdCBpbnRlcnByZXRhdGlvbiBhbmQgbWFuYWdlci1mcmllbmRseSBpbnNpZ2h0cy4KCiMgLiBMb2FkIExpYnJhcmllcyAmIFJlYWQgRGF0YQoKYGBge3Igc3RlcDEtcmVhZC1kYXRhfQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyAyLjEgTGlicmFyaWVzCiMgLSByZWFkeGw6IHRvIHJlYWQgRXhjZWwKIyAtIGRwbHlyOiBkYXRhIG1hbmlwdWxhdGlvbgojIC0gZ2dwbG90MjogdmlzdWFsaXphdGlvbgojIC0gYnJvb206IHRpZHkgbW9kZWwgb3V0cHV0IGludG8gY2xlYW4gdGFibGVzCiMgLSB0aWR5cjogcmVzaGFwZSBkYXRhIGZvciBwbG90dGluZwojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkodGlkeXIpCgojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyAyLjIgUmVhZCBFeGNlbCBEYXRhCiMgLSBXZSByZWFkIHRoZSBzaGVldCBuYW1lZCAiZGF0YSIKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgpkZl9yYXcgPC0gcmVhZF9leGNlbCgiTG9naXRzdWJzY3JpYmVkYXRhLnhsc3giLCBzaGVldCA9ICJkYXRhIikKCiMgUXVpY2sgbG9vayBhdCBzdHJ1Y3R1cmUgYW5kIGZpcnN0IHJvd3MKc3RyKGRmX3JhdykKaGVhZChkZl9yYXcpCmBgYAoKKipJbnRlcnByZXRhdGlvbiAoRGF0YSBjaGVjayk6KiogIApXZSBjb25maXJtIHdlIGhhdmUgMyBjb2x1bW5zOiAqKkFnZSoqLCAqKkdlbmRlciAoVz0xKSoqLCBhbmQgKipTdWJzY3JpYmUgKFllcz0xKSoqLiAgClRoaXMgaXMgYSBiaW5hcnkgY2xhc3NpZmljYXRpb24gcHJvYmxlbSBiZWNhdXNlICoqU3Vic2NyaWJlKiogaXMgMC8xLgoKIyAuIERhdGEgUHJlcGFyYXRpb24gKENsZWFuIG5hbWVzICsgdHlwZXMpCgpgYGB7ciBzdGVwMS1jbGVhbn0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgMy4xIFJlbmFtZSBjb2x1bW5zIHRvIHNpbXBsZXIgbmFtZXMKIyAtIGdlbmRlcl93OiAxIGlmIFdvbWFuLCAwIGlmIE1hbiAoYmFzZWQgb24gdGhlIGNvbHVtbiBuYW1lKQojIC0gc3Vic2NyaWJlOiAxIGlmIFllcywgMCBpZiBObwojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmRmIDwtIGRmX3JhdyAlPiUKICByZW5hbWUoCiAgICBnZW5kZXJfdyAgPSBgR2VuZGVyIChXPTEpYCwKICAgIHN1YnNjcmliZSA9IGBTdWJzY3JpYmU/IChZZXM9MSlgCiAgKQoKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgMy4yIEVuc3VyZSBjb3JyZWN0IGRhdGEgdHlwZXMKIyAtIExvZ2lzdGljIHJlZ3Jlc3Npb24gZXhwZWN0cyB0aGUgb3V0Y29tZSBhcyAwLzEgbnVtZXJpYwojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmRmIDwtIGRmICU+JQogIG11dGF0ZSgKICAgIGdlbmRlcl93ICA9IGFzLmludGVnZXIoZ2VuZGVyX3cpLAogICAgc3Vic2NyaWJlID0gYXMuaW50ZWdlcihzdWJzY3JpYmUpLAogICAgQWdlICAgICAgID0gYXMubnVtZXJpYyhBZ2UpCiAgKQoKIyBDb25maXJtIGFnYWluCnN0cihkZikKc3VtbWFyeShkZikKYGBgCgoqKkludGVycHJldGF0aW9uIChDbGVhbmluZyk6KiogIApXZSByZW5hbWVkIGNvbHVtbnMgZm9yIGVhc2llciBjb2RpbmcgYW5kIGVuc3VyZWQgQWdlIGlzIG51bWVyaWMgYW5kIHRoZSBiaW5hcnkgdmFyaWFibGVzIGFyZSBpbnRlZ2VycyAoMC8xKS4gIApUaGlzIGhlbHBzIGF2b2lkIGNvbW1vbiBSIGlzc3VlcyAoZS5nLiwgbnVtYmVycyByZWFkIGFzIHRleHQpLgoKIyAuIFF1aWNrIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MKCmBgYHtyIHN0ZXAxLWRlc2NyaXB0aXZlc30KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgNC4xIE91dGNvbWUgZGlzdHJpYnV0aW9uOiBob3cgbWFueSBzdWJzY3JpYmVkIHZzIG5vdAojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KdGFibGUoZGYkc3Vic2NyaWJlKQoKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgNC4yIEFnZSBzdW1tYXJ5CiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpzdW1tYXJ5KGRmJEFnZSkKCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIDQuMyBHZW5kZXIgZGlzdHJpYnV0aW9uCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQp0YWJsZShkZiRnZW5kZXJfdykKCiMgU3Vic2NyaXB0aW9uIHJhdGUgKG1lYW4gb2YgMC8xKQptZWFuKGRmJHN1YnNjcmliZSkKYGBgCgoqKkludGVycHJldGF0aW9uIChEZXNjcmlwdGl2ZXMpOioqICAKLSBUaGUgZGF0YXNldCBoYXMgKioxLDM0NSoqIG9ic2VydmF0aW9ucy4gIAotIFRoZSBzdWJzY3JpcHRpb24gcmF0ZSBpcyBhYm91dCAqKjI0JSoqIChtZWFuIG9mIDAvMSkuICAKLSBBZ2UgcmFuZ2VzIGZyb20gKioyMCB0byA2MCoqIChtZWRpYW4gYXJvdW5kICoqNDAqKikuICAKLSBHZW5kZXIgaXMgYmFsYW5jZWQgKHNpbWlsYXIgY291bnRzIGZvciBtZW4gdnMgd29tZW4pLiAgCgpUaGVzZSBzdGF0aXN0aWNzIHByb3ZpZGUgY29udGV4dCBiZWZvcmUgbW9kZWxpbmcuCgojIC4gU3RlcCAxIOKAlCBMb2dpc3RpYyBSZWdyZXNzaW9uIE1vZGVsCgpXZSBtb2RlbCBzdWJzY3JpcHRpb24gbGlrZWxpaG9vZCB1c2luZyB0d28gcHJlZGljdG9yczoKCi0gKipBZ2UqKiAoY29udGludW91cykKLSAqKkdlbmRlcioqIChXb21hbj0xKQoKTG9naXN0aWMgcmVncmVzc2lvbiBpcyBhcHByb3ByaWF0ZSBiZWNhdXNlIHRoZSBvdXRjb21lIGlzIGJpbmFyeSAoMC8xKS4KCmBgYHtyIHN0ZXAxLWxvZ2l0LW1vZGVsfQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyA1LjEgTG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbAojIGdsbSguLi4sIGZhbWlseSA9IGJpbm9taWFsKSBmaXRzIGEgbG9naXN0aWMgcmVncmVzc2lvbgojCiMgTW9kZWwgZm9ybToKIyBsb2cob2RkcyhzdWJzY3JpYmUpKSA9IGIwICsgYjEqQWdlICsgYjIqZ2VuZGVyX3cKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgptMSA8LSBnbG0oc3Vic2NyaWJlIH4gQWdlICsgZ2VuZGVyX3csIGRhdGEgPSBkZiwgZmFtaWx5ID0gYmlub21pYWwpCgojIE1haW4gbW9kZWwgb3V0cHV0CnN1bW1hcnkobTEpCmBgYAoKKipJbnRlcnByZXRhdGlvbiAoTW9kZWwgb3V0cHV0IOKAkyBoaWdoIGxldmVsKToqKiAgCi0gQ2hlY2sgdGhlICoqc2lnbioqIG9mIGNvZWZmaWNpZW50cyAocG9zaXRpdmUvbmVnYXRpdmUpLiAgCi0gQ2hlY2sgKipwLXZhbHVlcyoqIHRvIHNlZSB3aGljaCBwcmVkaWN0b3JzIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKRnJvbSB0aGUgb3V0cHV0OiAgCi0gKipBZ2UqKiBjb2VmZmljaWVudCBpcyAqKm5lZ2F0aXZlIGFuZCBoaWdobHkgc2lnbmlmaWNhbnQqKiDihpIgb2xkZXIgY3VzdG9tZXJzIGFyZSBsZXNzIGxpa2VseSB0byBzdWJzY3JpYmUuICAKLSAqKkdlbmRlciAoV29tYW49MSkqKiBjb2VmZmljaWVudCBpcyAqKnBvc2l0aXZlIGFuZCBzaWduaWZpY2FudCoqIOKGkiB3b21lbiBhcmUgbW9yZSBsaWtlbHkgdG8gc3Vic2NyaWJlLgoKIyAuIFN0ZXAgMiDigJQgT2RkcyBSYXRpb3MgCgpMb2dpc3RpYyBjb2VmZmljaWVudHMgYXJlIGluICoqbG9nLW9kZHMqKi4gVG8gaW50ZXJwcmV0IGluIGEgc2ltcGxlciB3YXksIHdlIGNvbnZlcnQgdGhlbSB0byAqKm9kZHMgcmF0aW9zIChPUikqKjoKCi0gT1IgPiAxIOKGkiBpbmNyZWFzZXMgb2RkcyBvZiBzdWJzY3JpYmluZyAgCi0gT1IgPCAxIOKGkiBkZWNyZWFzZXMgb2RkcyBvZiBzdWJzY3JpYmluZwoKYGBge3Igc3RlcDItb2Rkcy1yYXRpb3N9CiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIDYuMSBPZGRzIFJhdGlvcyArIENvbmZpZGVuY2UgSW50ZXJ2YWxzCiMgZXhwb25lbnRpYXRlID0gVFJVRSBtZWFucyBleHAoY29lZikgLT4gb2RkcyByYXRpbwojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCm9yX3RhYmxlIDwtIHRpZHkobTEsIGNvbmYuaW50ID0gVFJVRSwgZXhwb25lbnRpYXRlID0gVFJVRSkKb3JfdGFibGUKYGBgCgoqKkludGVycHJldGF0aW9uIChPZGRzIHJhdGlvcyk6KiogIAotICoqQWdlIE9SIOKJiCAwLjk1OioqIGVhY2ggYWRkaXRpb25hbCB5ZWFyIGRlY3JlYXNlcyB0aGUgb2RkcyBvZiBzdWJzY3JpYmluZyBieSBhYm91dCAqKjUlKiogKDEgLSAwLjk1KS4gIAotICoqR2VuZGVyIChXb21hbikgT1Ig4omIIDEuNTA6Kiogd29tZW4gaGF2ZSBhYm91dCAqKjUwJSBoaWdoZXIgb2RkcyoqIG9mIHN1YnNjcmliaW5nIHRoYW4gbWVuLiAgCgpCb3RoIHByZWRpY3RvcnMgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKHNtYWxsIHAtdmFsdWVzKS4KCiMgLiBQcmVkaWN0ZWQgUHJvYmFiaWxpdGllcyAKCk1hbmFnZXJzIHVuZGVyc3RhbmQgcHJvYmFiaWxpdGllcyBiZXR0ZXIgdGhhbiBvZGRzLiBXZSBjb21wdXRlIHByZWRpY3RlZCBwcm9iYWJpbGl0aWVzIGZvciBleGFtcGxlIHByb2ZpbGVzOgoKLSBBZ2VzOiAyNSwgNDUsIDY1ICAKLSBHZW5kZXI6IE1hbiAoMCkgdnMgV29tYW4gKDEpCgpgYGB7ciBzdGVwMi1wcmVkaWN0ZWQtcHJvZmlsZXN9CiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIDcuMSBFeGFtcGxlIHByb2ZpbGVzCiMgcHJlZGljdCguLi4sIHR5cGU9InJlc3BvbnNlIikgcmV0dXJucyBwcmVkaWN0ZWQgcHJvYmFiaWxpdHkgKDAtMSkKIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Cgpwcm9maWxlcyA8LSBkYXRhLmZyYW1lKAogIEFnZSA9IGMoMjUsIDI1LCA0NSwgNDUsIDY1LCA2NSksCiAgZ2VuZGVyX3cgPSBjKDAsIDEsIDAsIDEsIDAsIDEpCikKCnByb2ZpbGVzJHByZWRfcHJvYiA8LSBwcmVkaWN0KG0xLCBuZXdkYXRhID0gcHJvZmlsZXMsIHR5cGUgPSAicmVzcG9uc2UiKQpwcm9maWxlcwpgYGAKCioqSW50ZXJwcmV0YXRpb24gKFByZWRpY3RlZCBwcm9iYWJpbGl0aWVzKToqKiAgCi0gWW91bmdlciBjdXN0b21lcnMgaGF2ZSBtdWNoIGhpZ2hlciBwcmVkaWN0ZWQgc3Vic2NyaXB0aW9uIHByb2JhYmlsaXR5LiAgCi0gQXQgZXZlcnkgYWdlLCB3b21lbiBoYXZlIGhpZ2hlciBwcm9iYWJpbGl0eSB0aGFuIG1lbi4gIAoKRXhhbXBsZSAoZnJvbSBvdXIgb3V0cHV0KTogIAotIEFnZSAyNTogfjAuMzMgKG1lbikgdnMgfjAuNDIgKHdvbWVuKSAgCi0gQWdlIDQ1OiB+MC4xNSAobWVuKSB2cyB+MC4yMSAod29tZW4pICAKLSBBZ2UgNjU6IH4wLjA2IChtZW4pIHZzIH4wLjA4ICh3b21lbikgIAoKIyAuIFZpc3VhbGl6YXRpb24KCldlIGNyZWF0ZSBhIHNtb290aCBwcm9iYWJpbGl0eSBjdXJ2ZSBieSBhZ2UgZm9yIG1lbiB2cyB3b21lbi4KCmBgYHtyIHN0ZXA0LXBsb3R9CiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIDguMSBDcmVhdGUgYW4gYWdlIGdyaWQgZm9yIHByZWRpY3Rpb25zCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKYWdlX2dyaWRfbSA8LSBkYXRhLmZyYW1lKAogIEFnZSA9IHNlcShtaW4oZGYkQWdlKSwgbWF4KGRmJEFnZSksIGJ5ID0gMSksCiAgZ2VuZGVyX3cgPSAwCikKYWdlX2dyaWRfbSRwcmVkX3Byb2IgPC0gcHJlZGljdChtMSwgbmV3ZGF0YSA9IGFnZV9ncmlkX20sIHR5cGUgPSAicmVzcG9uc2UiKQphZ2VfZ3JpZF9tJEdyb3VwIDwtICJNZW4iCgphZ2VfZ3JpZF93IDwtIGRhdGEuZnJhbWUoCiAgQWdlID0gc2VxKG1pbihkZiRBZ2UpLCBtYXgoZGYkQWdlKSwgYnkgPSAxKSwKICBnZW5kZXJfdyA9IDEKKQphZ2VfZ3JpZF93JHByZWRfcHJvYiA8LSBwcmVkaWN0KG0xLCBuZXdkYXRhID0gYWdlX2dyaWRfdywgdHlwZSA9ICJyZXNwb25zZSIpCmFnZV9ncmlkX3ckR3JvdXAgPC0gIldvbWVuIgoKcGxvdF9kZiA8LSBiaW5kX3Jvd3MoYWdlX2dyaWRfbSwgYWdlX2dyaWRfdykKCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIDguMiBQbG90CiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKZ2dwbG90KHBsb3RfZGYsIGFlcyh4ID0gQWdlLCB5ID0gcHJlZF9wcm9iLCBsaW5ldHlwZSA9IEdyb3VwKSkgKwogIGdlb21fbGluZShsaW5ld2lkdGggPSAxKSArCiAgbGFicygKICAgIHRpdGxlID0gIlByZWRpY3RlZCBTdWJzY3JpcHRpb24gUHJvYmFiaWxpdHkgYnkgQWdlIGFuZCBHZW5kZXIiLAogICAgeCA9ICJBZ2UiLAogICAgeSA9ICJQcmVkaWN0ZWQgcHJvYmFiaWxpdHkgb2Ygc3Vic2NyaWJpbmciLAogICAgbGluZXR5cGUgPSAiR3JvdXAiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKKipJbnRlcnByZXRhdGlvbiAoUGxvdCk6KiogIAotIFRoZSBjdXJ2ZSBkZWNyZWFzZXMgd2l0aCBhZ2Ug4oaSIHN1YnNjcmlwdGlvbiBwcm9iYWJpbGl0eSBkZWNyZWFzZXMgYXMgY3VzdG9tZXJzIGdldCBvbGRlci4gIAotIFRoZSB3b21lbiBjdXJ2ZSBpcyBhYm92ZSB0aGUgbWVuIGN1cnZlIOKGkiB3b21lbiBhcmUgbW9yZSBsaWtlbHkgdG8gc3Vic2NyaWJlIGF0IGVhY2ggYWdlLgoKIyAuIFN0ZXAgMyDigJQgTWFuYWdlcmlhbCBSZWNvbW1lbmRhdGlvbnMKCkJhc2VkIG9uIHRoZSBtb2RlbDoKCjEpICoqRm9jdXMgYWNxdWlzaXRpb24gY2FtcGFpZ25zIG9uIHlvdW5nZXIgY3VzdG9tZXJzKiogIAotIEFnZSBpcyB0aGUgc3Ryb25nZXN0IGRyaXZlci4gWW91bmdlciBjdXN0b21lcnMgaGF2ZSB0aGUgaGlnaGVzdCBjb252ZXJzaW9uIHBvdGVudGlhbC4KCjIpICoqV29tZW4gYXJlIGEgaGlnaGVyLWxpa2VsaWhvb2Qgc2VnbWVudCoqICAKLSBXb21lbiBoYXZlIH41MCUgaGlnaGVyIG9kZHMgb2Ygc3Vic2NyaWJpbmcgdGhhbiBtZW4gKE9SIOKJiCAxLjUwKS4gIAotIFVzZSBjaGFubmVscyBhbmQgbWVzc2FnaW5nIHRoYXQgcGVyZm9ybSB3ZWxsIGZvciB0aGlzIHNlZ21lbnQuCgozKSAqKkltcHJvdmUgY29udmVyc2lvbiBmb3Igb2xkZXIgY3VzdG9tZXJzIHdpdGggdGFyZ2V0ZWQgYWN0aW9ucyoqICAKLSBGb3Igb2xkZXIgY3VzdG9tZXJzLCB0ZXN0IGNsZWFyZXIgdmFsdWUgY29tbXVuaWNhdGlvbiwgc2ltcGxlciBvbmJvYXJkaW5nLCBhbmQgdGFpbG9yZWQgb2ZmZXJzLgoKKipNYW5hZ2VyLWZyaWVuZGx5IGNvbmNsdXNpb246KiogIApBZ2Ugc2lnbmlmaWNhbnRseSByZWR1Y2VzIHN1YnNjcmlwdGlvbiBsaWtlbGlob29kLCB3aGlsZSBiZWluZyBmZW1hbGUgaW5jcmVhc2VzIGl0LiBUaGVyZWZvcmUsIG1hcmtldGluZyBzaG91bGQgcHJpb3JpdGl6ZSB5b3VuZ2VyIHNlZ21lbnRzIChlc3BlY2lhbGx5IHdvbWVuKSBmb3IgYWNxdWlzaXRpb24sIGFuZCBkZXZlbG9wIHNwZWNpZmljIHN0cmF0ZWdpZXMgdG8gaW1wcm92ZSBjb252ZXJzaW9uIGFtb25nIG9sZGVyIGN1c3RvbWVycy4KCiMgLiBMaW1pdGF0aW9ucyAKCi0gV2UgdXNlZCBvbmx5ICoqdHdvIHByZWRpY3RvcnMqKiAoYXMgcmVxdWlyZWQgYnkgdGhlIHF1aXopLiBSZWFsLXdvcmxkIG1vZGVscyBtYXkgbmVlZCBtb3JlIHZhcmlhYmxlcy4gIAotIFRoaXMgbW9kZWwgc2hvd3MgKiphc3NvY2lhdGlvbioqLCBub3QgZ3VhcmFudGVlZCBjYXVzYXRpb24uICAKLSBXZSBkaWQgbm90IHRlc3QgaW50ZXJhY3Rpb25zIChlLmcuLCBBZ2Ugw5cgR2VuZGVyKS4gVGhpcyBjYW4gYmUgZXhwbG9yZWQgaWYgcmVxdWlyZWQuCgo=