library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.0.4     ── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(ggplot2)
df <- read_csv("social_media_vs_productivity.csv")
Rows: 30000 Columns: 19── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (3): gender, job_type, social_platform_preference
dbl (14): age, daily_social_media_time, number_of_notifications, work_hours_per_day, perceived_productivity_score, actual_productivity...
lgl  (2): uses_focus_apps, has_digital_wellbeing_enabled
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(df)
summary(df)
      age           gender            job_type         daily_social_media_time social_platform_preference number_of_notifications
 Min.   :18.00   Length:30000       Length:30000       Min.   : 0.000          Length:30000               Min.   :30.00          
 1st Qu.:30.00   Class :character   Class :character   1st Qu.: 1.640          Class :character           1st Qu.:55.00          
 Median :41.00   Mode  :character   Mode  :character   Median : 3.026          Mode  :character           Median :60.00          
 Mean   :41.49                                         Mean   : 3.113                                     Mean   :59.96          
 3rd Qu.:53.00                                         3rd Qu.: 4.369                                     3rd Qu.:65.00          
 Max.   :65.00                                         Max.   :17.973                                     Max.   :90.00          
                                                       NA's   :2765                                                              
 work_hours_per_day perceived_productivity_score actual_productivity_score  stress_level     sleep_hours     screen_time_before_sleep
 Min.   : 0.000     Min.   :2.000                Min.   :0.2968            Min.   : 1.000   Min.   : 3.000   Min.   :0.0000          
 1st Qu.: 5.644     1st Qu.:3.758                1st Qu.:3.3733            1st Qu.: 3.000   1st Qu.: 5.494   1st Qu.:0.5285          
 Median : 6.991     Median :5.525                Median :4.9517            Median : 6.000   Median : 6.498   Median :1.0062          
 Mean   : 6.991     Mean   :5.511                Mean   :4.9518            Mean   : 5.514   Mean   : 6.500   Mean   :1.0256          
 3rd Qu.: 8.355     3rd Qu.:7.266                3rd Qu.:6.5263            3rd Qu.: 8.000   3rd Qu.: 7.504   3rd Qu.:1.4772          
 Max.   :12.000     Max.   :8.999                Max.   :9.8463            Max.   :10.000   Max.   :10.000   Max.   :3.0000          
                    NA's   :1614                 NA's   :2365              NA's   :1904     NA's   :2598     NA's   :2211            
 breaks_during_work uses_focus_apps has_digital_wellbeing_enabled coffee_consumption_per_day days_feeling_burnout_per_month
 Min.   : 0.000     Mode :logical   Mode :logical                 Min.   : 0.000             Min.   : 0.00                 
 1st Qu.: 2.000     FALSE:20979     FALSE:22602                   1st Qu.: 1.000             1st Qu.: 8.00                 
 Median : 5.000     TRUE :9021      TRUE :7398                    Median : 2.000             Median :16.00                 
 Mean   : 4.992                                                   Mean   : 1.999             Mean   :15.56                 
 3rd Qu.: 8.000                                                   3rd Qu.: 3.000             3rd Qu.:24.00                 
 Max.   :10.000                                                   Max.   :10.000             Max.   :31.00                 
                                                                                                                           
 weekly_offline_hours job_satisfaction_score
 Min.   : 0.000       Min.   : 0.000        
 1st Qu.: 4.542       1st Qu.: 3.364        
 Median :10.014       Median : 4.951        
 Mean   :10.361       Mean   : 4.965        
 3rd Qu.:15.301       3rd Qu.: 6.581        
 Max.   :40.965       Max.   :10.000        
                      NA's   :2730          
str(df)
spc_tbl_ [30,000 × 19] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ age                           : num [1:30000] 56 46 32 60 25 38 56 36 40 28 ...
 $ gender                        : chr [1:30000] "Male" "Male" "Male" "Female" ...
 $ job_type                      : chr [1:30000] "Unemployed" "Health" "Finance" "Unemployed" ...
 $ daily_social_media_time       : num [1:30000] 4.18 3.25 NA NA NA ...
 $ social_platform_preference    : chr [1:30000] "Facebook" "Twitter" "Twitter" "Facebook" ...
 $ number_of_notifications       : num [1:30000] 61 59 57 59 66 50 60 49 57 64 ...
 $ work_hours_per_day            : num [1:30000] 6.75 9.17 7.91 6.36 6.21 ...
 $ perceived_productivity_score  : num [1:30000] 8.04 5.06 3.86 2.92 8.87 ...
 $ actual_productivity_score     : num [1:30000] 7.29 5.17 3.47 1.77 NA ...
 $ stress_level                  : num [1:30000] 4 7 4 6 7 5 7 4 4 3 ...
 $ sleep_hours                   : num [1:30000] 5.12 5.1 8.58 6.05 5.41 ...
 $ screen_time_before_sleep      : num [1:30000] 0.419 0.672 0.624 1.205 1.876 ...
 $ breaks_during_work            : num [1:30000] 8 7 0 1 1 5 4 2 10 10 ...
 $ uses_focus_apps               : logi [1:30000] FALSE TRUE TRUE FALSE FALSE FALSE ...
 $ has_digital_wellbeing_enabled : logi [1:30000] FALSE TRUE FALSE FALSE TRUE TRUE ...
 $ coffee_consumption_per_day    : num [1:30000] 4 2 3 0 1 5 4 4 2 1 ...
 $ days_feeling_burnout_per_month: num [1:30000] 11 25 17 4 30 2 20 29 10 18 ...
 $ weekly_offline_hours          : num [1:30000] 21.9 0 10.3 23.9 10.7 ...
 $ job_satisfaction_score        : num [1:30000] 6.34 3.41 2.47 1.73 9.69 ...
 - attr(*, "spec")=
  .. cols(
  ..   age = col_double(),
  ..   gender = col_character(),
  ..   job_type = col_character(),
  ..   daily_social_media_time = col_double(),
  ..   social_platform_preference = col_character(),
  ..   number_of_notifications = col_double(),
  ..   work_hours_per_day = col_double(),
  ..   perceived_productivity_score = col_double(),
  ..   actual_productivity_score = col_double(),
  ..   stress_level = col_double(),
  ..   sleep_hours = col_double(),
  ..   screen_time_before_sleep = col_double(),
  ..   breaks_during_work = col_double(),
  ..   uses_focus_apps = col_logical(),
  ..   has_digital_wellbeing_enabled = col_logical(),
  ..   coffee_consumption_per_day = col_double(),
  ..   days_feeling_burnout_per_month = col_double(),
  ..   weekly_offline_hours = col_double(),
  ..   job_satisfaction_score = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
colSums(is.na(df))
                           age                         gender                       job_type        daily_social_media_time 
                             0                              0                              0                           2765 
    social_platform_preference        number_of_notifications             work_hours_per_day   perceived_productivity_score 
                             0                              0                              0                           1614 
     actual_productivity_score                   stress_level                    sleep_hours       screen_time_before_sleep 
                          2365                           1904                           2598                           2211 
            breaks_during_work                uses_focus_apps  has_digital_wellbeing_enabled     coffee_consumption_per_day 
                             0                              0                              0                              0 
days_feeling_burnout_per_month           weekly_offline_hours         job_satisfaction_score 
                             0                              0                           2730 
df <- df %>% rename(
  "job" = "job_type",
  "online_hours" = "daily_social_media_time",
  "app" = "social_platform_preference" ,
  "notifications" = "number_of_notifications",
  "work_hours" = "work_hours_per_day",
  "self_prod_score" = "perceived_productivity_score",
  "actual_prod_score" = "actual_productivity_score",
  "stress" = "stress_level",
  "focus_app" = "uses_focus_apps",
  "digital_wellbeing" = "has_digital_wellbeing_enabled",
  "coffee" = "coffee_consumption_per_day",
  "burnout_days" = "days_feeling_burnout_per_month",
  "job_score" = "job_satisfaction_score"
)
cols_to_fill <- c("online_hours", "self_prod_score", "actual_prod_score", "stress", "sleep_hours", "screen_time_before_sleep", "job_score")  # Replace with your column names
for (col in cols_to_fill) {
  df[[col]][is.na(df[[col]])] <- mean(df[[col]], na.rm = TRUE)
}
colSums(is.na(df))
                     age                   gender                      job             online_hours                      app 
                       0                        0                        0                        0                        0 
           notifications               work_hours          self_prod_score        actual_prod_score                   stress 
                       0                        0                        0                        0                        0 
             sleep_hours screen_time_before_sleep       breaks_during_work                focus_app        digital_wellbeing 
                       0                        0                        0                        0                        0 
                  coffee             burnout_days     weekly_offline_hours                job_score 
                       0                        0                        0                        0 
cols_to_round <- c("self_prod_score", "actual_prod_score", "job_score")
for (col in cols_to_round) {
  df[[col]] <- round(df[[col]])
}
head(df)
df <- df[df$gender != "Other", ]
ggplot(df, aes(x = `gender`)) +
  geom_bar(fill = "cyan", color = "black", alpha = 0.5 , stat = "count") +
  labs(title = "Gender Distribution", x = "Gender", y = "Frequency")

ggplot(df, aes(x = `job`)) +
  geom_bar(fill = "green", color = "black", alpha = 0.5) +
  labs(title = "Job Distribution", x = "Job", y = "Frequency")

ggplot(df, aes(x = `focus_app`)) +
  geom_bar(fill = "brown", color = "black", alpha = 0.5) +
  labs(title = "Focus App Users", x = "Yes or No", y = "Frequency")

ggplot(df, aes(x = `digital_wellbeing`)) +
  geom_bar(fill = "red", color = "black", alpha = 0.5) +
  labs(title = "Digital Wellbeing Enabled", x = "Yes or No", y = "Frequency")

ggplot(df, aes(x = `app`)) +
  geom_bar(fill = "purple", color = "black", alpha = 0.5 , stat = "count") +
  labs(title = "Social Media Platform Distribution", x = "App", y = "Frequency")

ggplot(df, aes(x = `age`)) +
  geom_density(fill = "yellow", color = "black", alpha = 0.5) +
  labs(title = "Age", x = "Age", y = "Frequency")

df <- df %>%
  mutate(age_group = cut(
    age,
    breaks = c(17, 30, 47, 65),
    labels = c("Young Adult", "Middle-Aged Adults", "Old Adults"),
    right = TRUE,
    include.lowest = TRUE
  ))
age_counts <- table(df$age_group)
pct <- round(100 * age_counts / sum(age_counts), 1)
labels <- paste(names(age_counts), "\n", pct, "%")
pie(age_counts, labels = labels, main = "Age Group Distribution")

ggplot(df, aes(x = `self_prod_score`)) +
  geom_histogram(binwidth = 1, fill = "cyan", color = "black", alpha = 0.5) +
  scale_x_continuous(breaks = 1:10) +
  labs(title = "Self Productivity Score", x = "Self Productivity Score", y = "Frequency")
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'rmarkdown':
  method         from
  print.paged_df     

ggplot(df, aes(x = `actual_prod_score`)) +
  geom_histogram(binwidth = 1, fill = "green", color = "black", alpha = 0.5) +
  scale_x_continuous(breaks = 1:10) +
  labs(title = "Actual Prodcutivity Score", x = "Actual Productivity Score", y = "Frequency")

ggplot(df, aes(x = `sleep_hours`)) +
  geom_density(fill = "red", color = "black", alpha = 0.5) +
  labs(title = "Sleep Hours Distirbution", x = "Sleep Hours", y = "Frequency")

ggplot(df, aes(y = `work_hours`)) +
  geom_boxplot(outlier.colour = "red", fill = "red", outlier.shape = 16) +
  labs(title = "Boxplot of Sleep Hours", y = "Hours")

ggplot(df, aes(x = `work_hours`)) +
  geom_density(fill = "cyan", color = "black", alpha = 0.5) +
  labs(title = "Work Hours Distirbution", x = "Work Hours", y = "Frequency")

ggplot(df, aes(y = `work_hours`)) +
  geom_boxplot(outlier.colour = "red", fill = "cyan", outlier.shape = 16) +
  labs(title = "Boxplot of Work Hours", y = "Hours")

ggplot(df, aes(x = `online_hours`)) +
  geom_density(fill = "pink", color = "black", alpha = 0.5) +
  labs(title = "Online Hours Distirbution", x = "Online Hours", y = "Frequency")

ggplot(df, aes(y = `online_hours`)) +
  geom_boxplot(outlier.colour = "red", fill = "pink", outlier.shape = 16) +
  labs(title = "Boxplot of Online Hours", y = "Hours")

replace_outliers_with_mean <- function(data, columns) {
  for (col in columns) {
      Q1 <- quantile(data[[col]], 0.25, na.rm = TRUE)
      Q3 <- quantile(data[[col]], 0.75, na.rm = TRUE)
      IQR_val <- Q3 - Q1

      lower_bound <- Q1 - 1.5 * IQR_val
      upper_bound <- Q3 + 1.5 * IQR_val

      mean_val <- mean(data[[col]], na.rm = TRUE)

      data[[col]] <- ifelse(data[[col]] < lower_bound | data[[col]] > upper_bound,
                            mean_val,
                            data[[col]])
  }
  return(data)
}
df <- replace_outliers_with_mean(df, c("online_hours", "work_hours", "sleep_hours"))
ggplot(df, aes(y = `online_hours`)) +
  geom_boxplot(outlier.colour = "red", fill = "pink", outlier.shape = 16) +
  labs(title = "Boxplot of Online Hours", y = "Hours")

ggplot(df, aes(y = `work_hours`)) +
  geom_boxplot(outlier.colour = "red", fill = "cyan", outlier.shape = 16) +
  labs(title = "Boxplot of Work Hours", y = "Hours")

ggplot(df, aes(y = `work_hours`)) +
  geom_boxplot(outlier.colour = "red", fill = "red", outlier.shape = 16) +
  labs(title = "Boxplot of Sleep Hours", y = "Hours")

ggplot(df, aes(x = `stress`)) +
  geom_histogram(binwidth = 1, fill = "green", color = "black", alpha = 0.5) +
  scale_x_continuous(breaks = 1:10) +
  labs(title = "Stress Level", x = "Stress Level", y = "Frequency")

ggplot(df, aes(x = `job_score`)) +
  geom_histogram(binwidth = 1,fill = "purple", color = "black", alpha = 0.5) +
  labs(title = "Job Satisfaction Score", x = "Job Satisfaction Score", y = "Frequency")

library(ggcorrplot)
corr_mat = round(cor(df[sapply(df, is.numeric)]),1)
ggcorrplot(corr_mat, lab = TRUE)

No strong correlation between features in dataset so predictive analysis won’t be feasible. so leaning towards hypothesis testing. We will be using t-test, anova to test some basic hypothesis.

H0: Average productivity score is equal to 6 Ha: Average productivity score is not equal to 6

t_test_productivity <- t.test(df$actual_prod_score, mu = 6)
print("T-Test Result of Actual Productivity Score")
[1] "T-Test Result of Actual Productivity Score"
print(t_test_productivity)

    One Sample t-test

data:  df$actual_prod_score
t = -96.371, df = 28821, p-value < 2.2e-16
alternative hypothesis: true mean is not equal to 6
95 percent confidence interval:
 4.938242 4.980570
sample estimates:
mean of x 
 4.959406 

H0: Use of focus apps have no effect on productivity Ha: Use of focus apps have effect on productivity

t_test_focus_app <- t.test(actual_prod_score ~ focus_app, data = df)
print("T-Test Result of Effect of Focus Apps")
[1] "T-Test Result of Effect of Focus Apps"
print(t_test_focus_app)

    Welch Two Sample t-test

data:  actual_prod_score by focus_app
t = 0.3019, df = 16341, p-value = 0.7627
alternative hypothesis: true difference in means between group FALSE and group TRUE is not equal to 0
95 percent confidence interval:
 -0.03912522  0.05337156
sample estimates:
mean in group FALSE  mean in group TRUE 
           4.961548            4.954425 

H0:Screen Time is equal across various Social Media platforms Ha:Screen Time is not equal across various Social Media platforms

anova_model <- aov(online_hours ~ app, data = df)
summary(anova_model)
               Df Sum Sq Mean Sq F value Pr(>F)  
app             4     29   7.241   2.405 0.0473 *
Residuals   28817  86750   3.010                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
tukey <- TukeyHSD(anova_model)
par(mar = c(5, 9, 4, 2))
plot(tukey,las = 1)

H0 : Screen Time is equal across various Age group Ha : Screen Time is not equal across various Age group

anova_model <- aov(online_hours ~ age_group, data = df)
summary(anova_model)
               Df Sum Sq Mean Sq F value Pr(>F)
age_group       2      2   1.209   0.402  0.669
Residuals   28819  86776   3.011               

There is no significant affect of age group in screen time.

H0: There is no difference in mean Screen Time between groups that have digital well being enabled Ha: There is difference in mean Screen Time between groups that have digital well being enabled

t_test_digital_wellbeing <- t.test(online_hours ~ digital_wellbeing, data = df)
print("T Test Result of Digital Wellbeing")
[1] "T Test Result of Digital Wellbeing"
print(t_test_digital_wellbeing)

    Welch Two Sample t-test

data:  online_hours by digital_wellbeing
t = -0.53469, df = 12275, p-value = 0.5929
alternative hypothesis: true difference in means between group FALSE and group TRUE is not equal to 0
95 percent confidence interval:
 -0.05878130  0.03358548
sample estimates:
mean in group FALSE  mean in group TRUE 
           3.017930            3.030528 
LS0tDQp0aXRsZTogIlNvY2lhbE1lZGlhIHZzIFByb2R1Y3Rpdml0eSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZGYgPC0gcmVhZF9jc3YoInNvY2lhbF9tZWRpYV92c19wcm9kdWN0aXZpdHkuY3N2IikNCmhlYWQoZGYpDQpgYGANCmBgYHtyfQ0Kc3VtbWFyeShkZikNCmBgYA0KYGBge3J9DQpzdHIoZGYpDQpgYGANCmBgYHtyfQ0KY29sU3Vtcyhpcy5uYShkZikpDQpgYGANCmBgYHtyfQ0KZGYgPC0gZGYgJT4lIHJlbmFtZSgNCiAgImpvYiIgPSAiam9iX3R5cGUiLA0KICAib25saW5lX2hvdXJzIiA9ICJkYWlseV9zb2NpYWxfbWVkaWFfdGltZSIsDQogICJhcHAiID0gInNvY2lhbF9wbGF0Zm9ybV9wcmVmZXJlbmNlIiAsDQogICJub3RpZmljYXRpb25zIiA9ICJudW1iZXJfb2Zfbm90aWZpY2F0aW9ucyIsDQogICJ3b3JrX2hvdXJzIiA9ICJ3b3JrX2hvdXJzX3Blcl9kYXkiLA0KICAic2VsZl9wcm9kX3Njb3JlIiA9ICJwZXJjZWl2ZWRfcHJvZHVjdGl2aXR5X3Njb3JlIiwNCiAgImFjdHVhbF9wcm9kX3Njb3JlIiA9ICJhY3R1YWxfcHJvZHVjdGl2aXR5X3Njb3JlIiwNCiAgInN0cmVzcyIgPSAic3RyZXNzX2xldmVsIiwNCiAgImZvY3VzX2FwcCIgPSAidXNlc19mb2N1c19hcHBzIiwNCiAgImRpZ2l0YWxfd2VsbGJlaW5nIiA9ICJoYXNfZGlnaXRhbF93ZWxsYmVpbmdfZW5hYmxlZCIsDQogICJjb2ZmZWUiID0gImNvZmZlZV9jb25zdW1wdGlvbl9wZXJfZGF5IiwNCiAgImJ1cm5vdXRfZGF5cyIgPSAiZGF5c19mZWVsaW5nX2J1cm5vdXRfcGVyX21vbnRoIiwNCiAgImpvYl9zY29yZSIgPSAiam9iX3NhdGlzZmFjdGlvbl9zY29yZSINCikNCmBgYA0KYGBge3J9DQpjb2xzX3RvX2ZpbGwgPC0gYygib25saW5lX2hvdXJzIiwgInNlbGZfcHJvZF9zY29yZSIsICJhY3R1YWxfcHJvZF9zY29yZSIsICJzdHJlc3MiLCAic2xlZXBfaG91cnMiLCAic2NyZWVuX3RpbWVfYmVmb3JlX3NsZWVwIiwgImpvYl9zY29yZSIpICAjIFJlcGxhY2Ugd2l0aCB5b3VyIGNvbHVtbiBuYW1lcw0KZm9yIChjb2wgaW4gY29sc190b19maWxsKSB7DQogIGRmW1tjb2xdXVtpcy5uYShkZltbY29sXV0pXSA8LSBtZWFuKGRmW1tjb2xdXSwgbmEucm0gPSBUUlVFKQ0KfQ0KY29sU3Vtcyhpcy5uYShkZikpDQpgYGANCmBgYHtyfQ0KY29sc190b19yb3VuZCA8LSBjKCJzZWxmX3Byb2Rfc2NvcmUiLCAiYWN0dWFsX3Byb2Rfc2NvcmUiLCAiam9iX3Njb3JlIikNCmZvciAoY29sIGluIGNvbHNfdG9fcm91bmQpIHsNCiAgZGZbW2NvbF1dIDwtIHJvdW5kKGRmW1tjb2xdXSkNCn0NCmhlYWQoZGYpDQpgYGANCg0KDQpgYGB7cn0NCmRmIDwtIGRmW2RmJGdlbmRlciAhPSAiT3RoZXIiLCBdDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gYGdlbmRlcmApKSArDQogIGdlb21fYmFyKGZpbGwgPSAiY3lhbiIsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjUgLCBzdGF0ID0gImNvdW50IikgKw0KICBsYWJzKHRpdGxlID0gIkdlbmRlciBEaXN0cmlidXRpb24iLCB4ID0gIkdlbmRlciIsIHkgPSAiRnJlcXVlbmN5IikNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGYsIGFlcyh4ID0gYGpvYmApKSArDQogIGdlb21fYmFyKGZpbGwgPSAiZ3JlZW4iLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiSm9iIERpc3RyaWJ1dGlvbiIsIHggPSAiSm9iIiwgeSA9ICJGcmVxdWVuY3kiKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHggPSBgZm9jdXNfYXBwYCkpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICJicm93biIsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJGb2N1cyBBcHAgVXNlcnMiLCB4ID0gIlllcyBvciBObyIsIHkgPSAiRnJlcXVlbmN5IikNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGYsIGFlcyh4ID0gYGRpZ2l0YWxfd2VsbGJlaW5nYCkpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICJyZWQiLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiRGlnaXRhbCBXZWxsYmVpbmcgRW5hYmxlZCIsIHggPSAiWWVzIG9yIE5vIiwgeSA9ICJGcmVxdWVuY3kiKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHggPSBgYXBwYCkpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICJwdXJwbGUiLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41ICwgc3RhdCA9ICJjb3VudCIpICsNCiAgbGFicyh0aXRsZSA9ICJTb2NpYWwgTWVkaWEgUGxhdGZvcm0gRGlzdHJpYnV0aW9uIiwgeCA9ICJBcHAiLCB5ID0gIkZyZXF1ZW5jeSIpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeCA9IGBhZ2VgKSkgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJ5ZWxsb3ciLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiQWdlIiwgeCA9ICJBZ2UiLCB5ID0gIkZyZXF1ZW5jeSIpDQpgYGANCmBgYHtyfQ0KZGYgPC0gZGYgJT4lDQogIG11dGF0ZShhZ2VfZ3JvdXAgPSBjdXQoDQogICAgYWdlLA0KICAgIGJyZWFrcyA9IGMoMTcsIDMwLCA0NywgNjUpLA0KICAgIGxhYmVscyA9IGMoIllvdW5nIEFkdWx0IiwgIk1pZGRsZS1BZ2VkIEFkdWx0cyIsICJPbGQgQWR1bHRzIiksDQogICAgcmlnaHQgPSBUUlVFLA0KICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRQ0KICApKQ0KYWdlX2NvdW50cyA8LSB0YWJsZShkZiRhZ2VfZ3JvdXApDQpwY3QgPC0gcm91bmQoMTAwICogYWdlX2NvdW50cyAvIHN1bShhZ2VfY291bnRzKSwgMSkNCmxhYmVscyA8LSBwYXN0ZShuYW1lcyhhZ2VfY291bnRzKSwgIlxuIiwgcGN0LCAiJSIpDQpwaWUoYWdlX2NvdW50cywgbGFiZWxzID0gbGFiZWxzLCBtYWluID0gIkFnZSBHcm91cCBEaXN0cmlidXRpb24iKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHggPSBgc2VsZl9wcm9kX3Njb3JlYCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gImN5YW4iLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjEwKSArDQogIGxhYnModGl0bGUgPSAiU2VsZiBQcm9kdWN0aXZpdHkgU2NvcmUiLCB4ID0gIlNlbGYgUHJvZHVjdGl2aXR5IFNjb3JlIiwgeSA9ICJGcmVxdWVuY3kiKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHggPSBgYWN0dWFsX3Byb2Rfc2NvcmVgKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAiZ3JlZW4iLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjEwKSArDQogIGxhYnModGl0bGUgPSAiQWN0dWFsIFByb2RjdXRpdml0eSBTY29yZSIsIHggPSAiQWN0dWFsIFByb2R1Y3Rpdml0eSBTY29yZSIsIHkgPSAiRnJlcXVlbmN5IikNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGYsIGFlcyh4ID0gYHNsZWVwX2hvdXJzYCkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAicmVkIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKw0KICBsYWJzKHRpdGxlID0gIlNsZWVwIEhvdXJzIERpc3RpcmJ1dGlvbiIsIHggPSAiU2xlZXAgSG91cnMiLCB5ID0gIkZyZXF1ZW5jeSIpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeSA9IGB3b3JrX2hvdXJzYCkpICsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gInJlZCIsIGZpbGwgPSAicmVkIiwgb3V0bGllci5zaGFwZSA9IDE2KSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBTbGVlcCBIb3VycyIsIHkgPSAiSG91cnMiKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHggPSBgd29ya19ob3Vyc2ApKSArDQogIGdlb21fZGVuc2l0eShmaWxsID0gImN5YW4iLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiV29yayBIb3VycyBEaXN0aXJidXRpb24iLCB4ID0gIldvcmsgSG91cnMiLCB5ID0gIkZyZXF1ZW5jeSIpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeSA9IGB3b3JrX2hvdXJzYCkpICsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gInJlZCIsIGZpbGwgPSAiY3lhbiIsIG91dGxpZXIuc2hhcGUgPSAxNikgKw0KICBsYWJzKHRpdGxlID0gIkJveHBsb3Qgb2YgV29yayBIb3VycyIsIHkgPSAiSG91cnMiKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHggPSBgb25saW5lX2hvdXJzYCkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAicGluayIsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJPbmxpbmUgSG91cnMgRGlzdGlyYnV0aW9uIiwgeCA9ICJPbmxpbmUgSG91cnMiLCB5ID0gIkZyZXF1ZW5jeSIpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeSA9IGBvbmxpbmVfaG91cnNgKSkgKw0KICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAicmVkIiwgZmlsbCA9ICJwaW5rIiwgb3V0bGllci5zaGFwZSA9IDE2KSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBPbmxpbmUgSG91cnMiLCB5ID0gIkhvdXJzIikNCmBgYA0KYGBge3J9DQpyZXBsYWNlX291dGxpZXJzX3dpdGhfbWVhbiA8LSBmdW5jdGlvbihkYXRhLCBjb2x1bW5zKSB7DQogIGZvciAoY29sIGluIGNvbHVtbnMpIHsNCiAgICAgIFExIDwtIHF1YW50aWxlKGRhdGFbW2NvbF1dLCAwLjI1LCBuYS5ybSA9IFRSVUUpDQogICAgICBRMyA8LSBxdWFudGlsZShkYXRhW1tjb2xdXSwgMC43NSwgbmEucm0gPSBUUlVFKQ0KICAgICAgSVFSX3ZhbCA8LSBRMyAtIFExDQoNCiAgICAgIGxvd2VyX2JvdW5kIDwtIFExIC0gMS41ICogSVFSX3ZhbA0KICAgICAgdXBwZXJfYm91bmQgPC0gUTMgKyAxLjUgKiBJUVJfdmFsDQoNCiAgICAgIG1lYW5fdmFsIDwtIG1lYW4oZGF0YVtbY29sXV0sIG5hLnJtID0gVFJVRSkNCg0KICAgICAgZGF0YVtbY29sXV0gPC0gaWZlbHNlKGRhdGFbW2NvbF1dIDwgbG93ZXJfYm91bmQgfCBkYXRhW1tjb2xdXSA+IHVwcGVyX2JvdW5kLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW5fdmFsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbW2NvbF1dKQ0KICB9DQogIHJldHVybihkYXRhKQ0KfQ0KZGYgPC0gcmVwbGFjZV9vdXRsaWVyc193aXRoX21lYW4oZGYsIGMoIm9ubGluZV9ob3VycyIsICJ3b3JrX2hvdXJzIiwgInNsZWVwX2hvdXJzIikpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeSA9IGBvbmxpbmVfaG91cnNgKSkgKw0KICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAicmVkIiwgZmlsbCA9ICJwaW5rIiwgb3V0bGllci5zaGFwZSA9IDE2KSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBPbmxpbmUgSG91cnMiLCB5ID0gIkhvdXJzIikNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGYsIGFlcyh5ID0gYHdvcmtfaG91cnNgKSkgKw0KICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAicmVkIiwgZmlsbCA9ICJjeWFuIiwgb3V0bGllci5zaGFwZSA9IDE2KSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBXb3JrIEhvdXJzIiwgeSA9ICJIb3VycyIpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeSA9IGB3b3JrX2hvdXJzYCkpICsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gInJlZCIsIGZpbGwgPSAicmVkIiwgb3V0bGllci5zaGFwZSA9IDE2KSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBTbGVlcCBIb3VycyIsIHkgPSAiSG91cnMiKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHggPSBgc3RyZXNzYCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gImdyZWVuIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMToxMCkgKw0KICBsYWJzKHRpdGxlID0gIlN0cmVzcyBMZXZlbCIsIHggPSAiU3RyZXNzIExldmVsIiwgeSA9ICJGcmVxdWVuY3kiKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHggPSBgam9iX3Njb3JlYCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLGZpbGwgPSAicHVycGxlIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKw0KICBsYWJzKHRpdGxlID0gIkpvYiBTYXRpc2ZhY3Rpb24gU2NvcmUiLCB4ID0gIkpvYiBTYXRpc2ZhY3Rpb24gU2NvcmUiLCB5ID0gIkZyZXF1ZW5jeSIpDQpgYGANCmBgYHtyfQ0KbGlicmFyeShnZ2NvcnJwbG90KQ0KY29ycl9tYXQgPSByb3VuZChjb3IoZGZbc2FwcGx5KGRmLCBpcy5udW1lcmljKV0pLDEpDQpnZ2NvcnJwbG90KGNvcnJfbWF0LCBsYWIgPSBUUlVFKQ0KYGBgDQpObyBzdHJvbmcgY29ycmVsYXRpb24gYmV0d2VlbiBmZWF0dXJlcyBpbiBkYXRhc2V0IHNvIHByZWRpY3RpdmUgYW5hbHlzaXMgd29uJ3QgYmUgZmVhc2libGUuIA0Kc28gbGVhbmluZyB0b3dhcmRzIGh5cG90aGVzaXMgdGVzdGluZy4NCldlIHdpbGwgYmUgdXNpbmcgdC10ZXN0LCBhbm92YSB0byB0ZXN0IHNvbWUgYmFzaWMgaHlwb3RoZXNpcy4NCg0KSDA6IEF2ZXJhZ2UgcHJvZHVjdGl2aXR5IHNjb3JlIGlzIGVxdWFsIHRvIDYNCkhhOiBBdmVyYWdlIHByb2R1Y3Rpdml0eSBzY29yZSBpcyBub3QgZXF1YWwgdG8gNg0KYGBge3J9DQp0X3Rlc3RfcHJvZHVjdGl2aXR5IDwtIHQudGVzdChkZiRhY3R1YWxfcHJvZF9zY29yZSwgbXUgPSA2KQ0KcHJpbnQoIlQtVGVzdCBSZXN1bHQgb2YgQWN0dWFsIFByb2R1Y3Rpdml0eSBTY29yZSIpDQpwcmludCh0X3Rlc3RfcHJvZHVjdGl2aXR5KQ0KYGBgDQpIMDogVXNlIG9mIGZvY3VzIGFwcHMgaGF2ZSBubyBlZmZlY3Qgb24gcHJvZHVjdGl2aXR5DQpIYTogVXNlIG9mIGZvY3VzIGFwcHMgaGF2ZSBlZmZlY3Qgb24gcHJvZHVjdGl2aXR5DQpgYGB7cn0NCnRfdGVzdF9mb2N1c19hcHAgPC0gdC50ZXN0KGFjdHVhbF9wcm9kX3Njb3JlIH4gZm9jdXNfYXBwLCBkYXRhID0gZGYpDQpwcmludCgiVC1UZXN0IFJlc3VsdCBvZiBFZmZlY3Qgb2YgRm9jdXMgQXBwcyIpDQpwcmludCh0X3Rlc3RfZm9jdXNfYXBwKQ0KYGBgDQpIMDpTY3JlZW4gVGltZSBpcyBlcXVhbCBhY3Jvc3MgdmFyaW91cyBTb2NpYWwgTWVkaWEgcGxhdGZvcm1zDQpIYTpTY3JlZW4gVGltZSBpcyBub3QgZXF1YWwgYWNyb3NzIHZhcmlvdXMgU29jaWFsIE1lZGlhIHBsYXRmb3Jtcw0KYGBge3J9DQphbm92YV9tb2RlbCA8LSBhb3Yob25saW5lX2hvdXJzIH4gYXBwLCBkYXRhID0gZGYpDQpzdW1tYXJ5KGFub3ZhX21vZGVsKQ0KYGBgDQpgYGB7cn0NCnR1a2V5IDwtIFR1a2V5SFNEKGFub3ZhX21vZGVsKQ0KcGFyKG1hciA9IGMoNSwgOSwgNCwgMikpDQpwbG90KHR1a2V5LGxhcyA9IDEpDQpgYGANCkgwIDogU2NyZWVuIFRpbWUgaXMgZXF1YWwgYWNyb3NzIHZhcmlvdXMgQWdlIGdyb3VwDQpIYSA6IFNjcmVlbiBUaW1lIGlzIG5vdCBlcXVhbCBhY3Jvc3MgdmFyaW91cyBBZ2UgZ3JvdXANCmBgYHtyfQ0KYW5vdmFfbW9kZWwgPC0gYW92KG9ubGluZV9ob3VycyB+IGFnZV9ncm91cCwgZGF0YSA9IGRmKQ0Kc3VtbWFyeShhbm92YV9tb2RlbCkNCmBgYA0KVGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgYWZmZWN0IG9mIGFnZSBncm91cCBpbiBzY3JlZW4gdGltZS4NCg0KSDA6IFRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgaW4gbWVhbiBTY3JlZW4gVGltZSBiZXR3ZWVuIGdyb3VwcyB0aGF0IGhhdmUgZGlnaXRhbCB3ZWxsIGJlaW5nIGVuYWJsZWQNCkhhOiBUaGVyZSBpcyBkaWZmZXJlbmNlIGluIG1lYW4gU2NyZWVuIFRpbWUgYmV0d2VlbiBncm91cHMgdGhhdCBoYXZlIGRpZ2l0YWwgd2VsbCBiZWluZyBlbmFibGVkDQpgYGB7cn0NCnRfdGVzdF9kaWdpdGFsX3dlbGxiZWluZyA8LSB0LnRlc3Qob25saW5lX2hvdXJzIH4gZGlnaXRhbF93ZWxsYmVpbmcsIGRhdGEgPSBkZikNCnByaW50KCJUIFRlc3QgUmVzdWx0IG9mIERpZ2l0YWwgV2VsbGJlaW5nIikNCnByaW50KHRfdGVzdF9kaWdpdGFsX3dlbGxiZWluZykNCmBgYA==