This document was created to fulfill some of the requirements for the Google Data Analytics Professional Certificate.


Overview

To inform marketing strategies and product developement for Bellabeat, a fitness company geared towards women, an analysis of publically available data from smart devices was conducted. The dataset aggregated information from FitBit products in 2016 and was obtained through Kaggle.

The data were cleaned, reviewed, and analyzed with RStudio. Tests of normality and an analysis of unique users was conducted for all data. To gain additional information about the under-utilization of data related to weight, a second analysis was conducted.

Summary of Data

The results of the analysis should be interpreted cautiously due to the age of the dataset, number of unique users, and tests of normality; however, Step 1 in the Recommendations section will mitigate some of these limitations.

A review of all measures indicated:

Tests of Normality

### Tests of Normality

#Tests of Skewness
SkSt <- skewness(merged$TotalSteps)
SkDi <- skewness(merged$TotalDistance)
SkVeMi <- skewness(merged$VeryActiveMinutes)
SkFaMi <- skewness(merged$FairlyActiveMinutes)
SkLiMi <- skewness(merged$LightlyActiveMinutes)
SkSeMi <- skewness(merged$SedentaryMinutes)
SkCa <- skewness(merged$Calories)
SkSl <- skewness(sleep$minutes_asleep)
SkBd <- skewness(sleep$minutes_in_bed)
SkWe <- skewness(weight$weight_pounds)
SkBmi <- skewness(weight$bmi)

#Test of Kurtosis 
KuSt <- kurtosis(merged$TotalSteps)
KuDi <- kurtosis(merged$TotalDistance)
KuVeMi <- kurtosis(merged$VeryActiveMinutes)
KuFaMi <- kurtosis(merged$FairlyActiveMinutes)
KuLiMi <- kurtosis(merged$LightlyActiveMinutes)
KuSeMi <- kurtosis(merged$SedentaryMinutes)
KuCa <- kurtosis(merged$Calories)
KuSl <- kurtosis(sleep$minutes_asleep)
KuBd <- kurtosis(sleep$minutes_in_bed)
KuWe <- kurtosis(weight$weight_pounds)
KuBmi <- kurtosis(weight$bmi)

#List of Variables Tested
sk_ku_act_names <- c("Total Steps", "Total Distance", "Very Active Minutes", "Fairly Active Minutes", "Lightly Active Minutes", "Sedentary Minutes", "Calories")
sk_ku_sle_names <- c("Minutes Asleep", "Minutes in Bed")
sk_ku_wei_names <- c("Weight (lbs)", "BMI")

#Vector of Skewness Results
sk_act_values <- c(SkSt, SkDi, SkVeMi, SkFaMi, SkLiMi, SkSeMi, SkCa)
sk_sle_values <- c(SkSl, SkBd)
sk_wei_values <- c(SkWe, SkBmi)

#Vector of Kurtosis Results
ku_act_values <- c(KuSt, KuDi, KuVeMi, KuFaMi, KuLiMi, KuSeMi, KuCa)
ku_sle_values <- c(KuSl, KuBd)
ku_wei_values <- c(KuWe, KuBmi)

#Data frames
sk_ku_act_df <- data.frame(sk_ku_act_names, sk_act_values, ku_act_values)
sk_ku_sle_df <- data.frame(sk_ku_sle_names, sk_sle_values, ku_sle_values)
sk_ku_wei_df <- data.frame(sk_ku_wei_names, sk_wei_values, ku_wei_values)

#Renaming Columns
colnames(sk_ku_act_df) <- c("Activity Measures", "Skewness", "Kurtosis")
colnames(sk_ku_sle_df) <- c("Sleep Measures", "Skewness", "Kurtosis")
colnames(sk_ku_wei_df) <- c("Weight Measures", "Skewness", "Kurtosis")

#Data frames to tables
kable(sk_ku_act_df)
Activity Measures Skewness Kurtosis
Total Steps 0.6518526 4.156526
Total Distance 1.1244756 6.090108
Very Active Minutes 2.1726691 8.741005
Fairly Active Minutes 2.4755336 10.946888
Lightly Active Minutes -0.0378688 2.635419
Sedentary Minutes -0.2940279 2.331211
Calories 0.4217761 3.615331
kable(sk_ku_sle_df)
Sleep Measures Skewness Kurtosis
Minutes Asleep -0.6127408 4.582448
Minutes in Bed -0.2178411 6.441879
kable(sk_ku_wei_df)
Weight Measures Skewness Kurtosis
Weight (lbs) 1.338812 6.49147
BMI 5.865064 43.53380

Observations


#Calculating number of observations across health measures
OSt <- length(merged$TotalSteps)
ODi <- length(merged$TotalDistance)
OVeMi <- length(merged$VeryActiveMinutes)
OFaMi <- length(merged$FairlyActiveMinutes)
OLiMi <- length(merged$LightlyActiveMinutes)
OSeMi <- length(merged$SedentaryMinutes)
OCa <- length(merged$Calories)
OSl <- length(sleep$minutes_asleep)
OBd <- length(sleep$minutes_in_bed)
OWe <- length(weight$weight_pounds)
OBmi <- length(weight$bmi)

#Organizing information about activity into data frame
o_act_measures <- c("Total Steps", "Total Distance", "Very Active Minutes", "Fairly Active Minutes", "Lightly Active Minutes", "Sedentary Minutes", "Calories")
o_act_observations <- c(OSt, ODi, OVeMi, OFaMi, OLiMi, OSeMi, OCa)
o_act_df <- data.frame(o_act_measures, o_act_observations)

#Organizing information about sleep into data frame
o_sle_measures <- c("Minutes Asleep", "Minutes in Bed")
o_sle_observations <- c(OSl, OBd)
o_sle_df <- data.frame(o_sle_measures, o_sle_observations)

#Organizing information on weight into data frame
o_wei_measures <- c("Weight (lbs)", "BMI")
o_wei_observations <- c(OWe, OBmi)
o_wei_df <- data.frame(o_wei_measures, o_wei_observations)

#Renaming Columns
colnames(o_wei_df) <- c("Weight Measures", "Observations")
colnames(o_sle_df) <- c("Sleep Measures", "Observations")
colnames(o_act_df) <- c("Activity Measures", "Observations")

#Converting data frames to tables
kable(o_act_df)
Activity Measures Observations
Total Steps 940
Total Distance 940
Very Active Minutes 940
Fairly Active Minutes 940
Lightly Active Minutes 940
Sedentary Minutes 940
Calories 940
kable(o_sle_df)
Sleep Measures Observations
Minutes Asleep 413
Minutes in Bed 413
kable(o_wei_df)
Weight Measures Observations
Weight (lbs) 67
BMI 67

Visual Representation of Data


#Calculating number of unique users
users_activity <- length(unique(merged$Id))
users_sleep <- length(unique(sleep$id))
users_weight <- length(unique(weight$id))

#Creating data frame
user_values <- c(users_activity, users_sleep, users_weight)
user_labels <- c("Activity", "Sleep", "Weight")
unique_user_df <- data.frame(user_labels, user_values)

#Graph of unique users
ggplot(unique_user_df) + geom_col(mapping = aes(x=user_labels, y=user_values), fill = "#000066") + theme_bw() + labs(x = "Health Categories", y = "Total", title = "Unique Users") + theme(axis.text = element_text(size = 13), text = element_text(size = 13))

#Color palette

cbPalette <- c("#999999", "#009E73")

#Graph of weight-specific data
ggplot(weight) + geom_bar(mapping = aes(x=id, fill = manual_report)) + coord_flip() + theme_bw() + labs(x = "User ID", y="Total", title = "Type of Weight Log") + theme(legend.title = element_blank()) + scale_fill_manual(values=cbPalette) + theme(axis.text = element_text(size = 12.5), text = element_text(size = 13))

Potential Growth Area

Two important themes were found in the weight-specific analysis.

  1. Most observations were logged manually
  2. Of the limited users, most logged their weight fewer than 5 times

Based on the available information, it appears measures without automated data collection are less likely to be monitored and used.

Patterns in user behavior may be attributed to the effort required to manually log data, forgetting to complete the task due to competing obligations (e.g., work, family), or a combination of factors.

Bellabeat does not currently offer a product with automated data colleciton for weight (see table below).

Product Description Activity Sleep Stress Hydration Weight
Leaf Worn as bracelet, clip, or necklace Yes Yes Yes No No
Time Worn as watch Yes Yes Yes No No
Spring Used as water bottle No No No Yes No

If users must enter data manually or use another product to collect weight data automatically, it may decrease the use of the Bellabeat app and the online coaching program, which would decrease user engagement.

Recommendations

Immediate Next Steps:

If the results of the survey correspond with the analysis and there is sufficient customer interest:

  1. Examine the cost associated with adding automated weight collection to future products.

  2. Consider releasing a limited amount of updated devices and monitor the use of the Bellabeat app and online coaching program for a concurrent increase in user engagement.


LS0tCnRpdGxlOiAnUGF0dGVybnMgaW4gRml0bmVzcyBEYXRhIGZyb20gU21hcnQgRGV2aWNlcyAnCmF1dGhvcjogIkNocmlzdG9waGVyIFRheWxvciIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IG51bGwKICAndG1sX25vdGVib29rOic6IGRlZmF1bHQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKI1BhY2thZ2VzIHVzZWQKbGlicmFyeShyZWFkcikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkobW9tZW50cykKCiNBY3Rpdml0eSBEYXRhCm1lcmdlZCA8LSBtZXJnZWQgPC0gcmVhZF9leGNlbCgifi9GaXRCaXQgQW5hbHlzaXMvbWVyZ2VkLnhsc3giLCBjb2xfdHlwZXMgPSBjKCJ0ZXh0IiwgImRhdGUiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIpKQoKI1NsZWVwIERhdGEKc2xlZXAgPC0gcmVhZF9leGNlbCgifi9GaXRCaXQgQW5hbHlzaXMvc2xlZXAueGxzeCIsIGNvbF90eXBlcyA9IGMoInRleHQiLCAiZGF0ZSIsIm51bWVyaWMiLCAibnVtZXJpYyIsIm51bWVyaWMiKSkKCiNXZWlnaHQgRGF0YQp3ZWlnaHQgPC0gcmVhZF9leGNlbCgifi9GaXRCaXQgQW5hbHlzaXMvd2VpZ2h0Lnhsc3giLCBjb2xfdHlwZXMgPSBjKCJ0ZXh0IiwgImRhdGUiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgInRleHQiLCAibnVtZXJpYyIpKQoKYGBgCgpUaGlzIGRvY3VtZW50IHdhcyBjcmVhdGVkIHRvIGZ1bGZpbGwgc29tZSBvZiB0aGUgcmVxdWlyZW1lbnRzIGZvciB0aGUgR29vZ2xlIERhdGEgQW5hbHl0aWNzIFByb2Zlc3Npb25hbCBDZXJ0aWZpY2F0ZS4KCi0tLQoKIyMgT3ZlcnZpZXcKVG8gaW5mb3JtIG1hcmtldGluZyBzdHJhdGVnaWVzIGFuZCBwcm9kdWN0IGRldmVsb3BlbWVudCBmb3IgQmVsbGFiZWF0LCBhIGZpdG5lc3MgY29tcGFueSBnZWFyZWQgdG93YXJkcyB3b21lbiwgYW4gYW5hbHlzaXMgb2YgcHVibGljYWxseSBhdmFpbGFibGUgZGF0YSBmcm9tIHNtYXJ0IGRldmljZXMgd2FzIGNvbmR1Y3RlZC4gVGhlIFtkYXRhc2V0XShodHRwczovL3d3dy5rYWdnbGUuY29tL2FyYXNobmljL2ZpdGJpdCkgYWdncmVnYXRlZCBpbmZvcm1hdGlvbiBmcm9tIEZpdEJpdCBwcm9kdWN0cyBpbiAyMDE2IGFuZCB3YXMgb2J0YWluZWQgdGhyb3VnaCBLYWdnbGUuCgpUaGUgZGF0YSB3ZXJlIGNsZWFuZWQsIHJldmlld2VkLCBhbmQgYW5hbHl6ZWQgd2l0aCBSU3R1ZGlvLiBUZXN0cyBvZiBub3JtYWxpdHkgYW5kIGFuIGFuYWx5c2lzIG9mIHVuaXF1ZSB1c2VycyB3YXMgY29uZHVjdGVkIGZvciBhbGwgZGF0YS4gVG8gZ2FpbiBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IHRoZSB1bmRlci11dGlsaXphdGlvbiBvZiBkYXRhIHJlbGF0ZWQgdG8gd2VpZ2h0LCBhIHNlY29uZCBhbmFseXNpcyB3YXMgY29uZHVjdGVkLiAKCiMjIFN1bW1hcnkgb2YgRGF0YQoKVGhlIHJlc3VsdHMgb2YgdGhlIGFuYWx5c2lzIHNob3VsZCBiZSBpbnRlcnByZXRlZCBjYXV0aW91c2x5IGR1ZSB0byB0aGUgYWdlIG9mIHRoZSBkYXRhc2V0LCBudW1iZXIgb2YgdW5pcXVlIHVzZXJzLCBhbmQgdGVzdHMgb2Ygbm9ybWFsaXR5OyBob3dldmVyLCBTdGVwIDEgaW4gdGhlIFJlY29tbWVuZGF0aW9ucyBzZWN0aW9uIHdpbGwgbWl0aWdhdGUgc29tZSBvZiB0aGVzZSBsaW1pdGF0aW9ucy4KCkEgcmV2aWV3IG9mIGFsbCBtZWFzdXJlcyBpbmRpY2F0ZWQ6CgotIFRoZSBkYXRhIGFyZSBub3Qgbm9ybWFsbHkgZGlzdHJidXRlZAotIFVzZXJzIGNvbGxlY3RlZCBkYXRhIG9uIGFjdGl2aXRpZXMgbW9yZSBvZnRlbiB0aGFuIG90aGVyIGhlYWx0aCBjYXRlZ29yaWVzIAotIFVzZXJzIGNvbGxlY3RlZCBkYXRhIG9uIHdlaWdodCBsZWFzdCBvZnRlbgoKIyMjIFRlc3RzIG9mIE5vcm1hbGl0eQpgYGB7cn0KIyMjIFRlc3RzIG9mIE5vcm1hbGl0eQoKI1Rlc3RzIG9mIFNrZXduZXNzClNrU3QgPC0gc2tld25lc3MobWVyZ2VkJFRvdGFsU3RlcHMpClNrRGkgPC0gc2tld25lc3MobWVyZ2VkJFRvdGFsRGlzdGFuY2UpClNrVmVNaSA8LSBza2V3bmVzcyhtZXJnZWQkVmVyeUFjdGl2ZU1pbnV0ZXMpClNrRmFNaSA8LSBza2V3bmVzcyhtZXJnZWQkRmFpcmx5QWN0aXZlTWludXRlcykKU2tMaU1pIDwtIHNrZXduZXNzKG1lcmdlZCRMaWdodGx5QWN0aXZlTWludXRlcykKU2tTZU1pIDwtIHNrZXduZXNzKG1lcmdlZCRTZWRlbnRhcnlNaW51dGVzKQpTa0NhIDwtIHNrZXduZXNzKG1lcmdlZCRDYWxvcmllcykKU2tTbCA8LSBza2V3bmVzcyhzbGVlcCRtaW51dGVzX2FzbGVlcCkKU2tCZCA8LSBza2V3bmVzcyhzbGVlcCRtaW51dGVzX2luX2JlZCkKU2tXZSA8LSBza2V3bmVzcyh3ZWlnaHQkd2VpZ2h0X3BvdW5kcykKU2tCbWkgPC0gc2tld25lc3Mod2VpZ2h0JGJtaSkKCiNUZXN0IG9mIEt1cnRvc2lzIApLdVN0IDwtIGt1cnRvc2lzKG1lcmdlZCRUb3RhbFN0ZXBzKQpLdURpIDwtIGt1cnRvc2lzKG1lcmdlZCRUb3RhbERpc3RhbmNlKQpLdVZlTWkgPC0ga3VydG9zaXMobWVyZ2VkJFZlcnlBY3RpdmVNaW51dGVzKQpLdUZhTWkgPC0ga3VydG9zaXMobWVyZ2VkJEZhaXJseUFjdGl2ZU1pbnV0ZXMpCkt1TGlNaSA8LSBrdXJ0b3NpcyhtZXJnZWQkTGlnaHRseUFjdGl2ZU1pbnV0ZXMpCkt1U2VNaSA8LSBrdXJ0b3NpcyhtZXJnZWQkU2VkZW50YXJ5TWludXRlcykKS3VDYSA8LSBrdXJ0b3NpcyhtZXJnZWQkQ2Fsb3JpZXMpCkt1U2wgPC0ga3VydG9zaXMoc2xlZXAkbWludXRlc19hc2xlZXApCkt1QmQgPC0ga3VydG9zaXMoc2xlZXAkbWludXRlc19pbl9iZWQpCkt1V2UgPC0ga3VydG9zaXMod2VpZ2h0JHdlaWdodF9wb3VuZHMpCkt1Qm1pIDwtIGt1cnRvc2lzKHdlaWdodCRibWkpCgojTGlzdCBvZiBWYXJpYWJsZXMgVGVzdGVkCnNrX2t1X2FjdF9uYW1lcyA8LSBjKCJUb3RhbCBTdGVwcyIsICJUb3RhbCBEaXN0YW5jZSIsICJWZXJ5IEFjdGl2ZSBNaW51dGVzIiwgIkZhaXJseSBBY3RpdmUgTWludXRlcyIsICJMaWdodGx5IEFjdGl2ZSBNaW51dGVzIiwgIlNlZGVudGFyeSBNaW51dGVzIiwgIkNhbG9yaWVzIikKc2tfa3Vfc2xlX25hbWVzIDwtIGMoIk1pbnV0ZXMgQXNsZWVwIiwgIk1pbnV0ZXMgaW4gQmVkIikKc2tfa3Vfd2VpX25hbWVzIDwtIGMoIldlaWdodCAobGJzKSIsICJCTUkiKQoKI1ZlY3RvciBvZiBTa2V3bmVzcyBSZXN1bHRzCnNrX2FjdF92YWx1ZXMgPC0gYyhTa1N0LCBTa0RpLCBTa1ZlTWksIFNrRmFNaSwgU2tMaU1pLCBTa1NlTWksIFNrQ2EpCnNrX3NsZV92YWx1ZXMgPC0gYyhTa1NsLCBTa0JkKQpza193ZWlfdmFsdWVzIDwtIGMoU2tXZSwgU2tCbWkpCgojVmVjdG9yIG9mIEt1cnRvc2lzIFJlc3VsdHMKa3VfYWN0X3ZhbHVlcyA8LSBjKEt1U3QsIEt1RGksIEt1VmVNaSwgS3VGYU1pLCBLdUxpTWksIEt1U2VNaSwgS3VDYSkKa3Vfc2xlX3ZhbHVlcyA8LSBjKEt1U2wsIEt1QmQpCmt1X3dlaV92YWx1ZXMgPC0gYyhLdVdlLCBLdUJtaSkKCiNEYXRhIGZyYW1lcwpza19rdV9hY3RfZGYgPC0gZGF0YS5mcmFtZShza19rdV9hY3RfbmFtZXMsIHNrX2FjdF92YWx1ZXMsIGt1X2FjdF92YWx1ZXMpCnNrX2t1X3NsZV9kZiA8LSBkYXRhLmZyYW1lKHNrX2t1X3NsZV9uYW1lcywgc2tfc2xlX3ZhbHVlcywga3Vfc2xlX3ZhbHVlcykKc2tfa3Vfd2VpX2RmIDwtIGRhdGEuZnJhbWUoc2tfa3Vfd2VpX25hbWVzLCBza193ZWlfdmFsdWVzLCBrdV93ZWlfdmFsdWVzKQoKI1JlbmFtaW5nIENvbHVtbnMKY29sbmFtZXMoc2tfa3VfYWN0X2RmKSA8LSBjKCJBY3Rpdml0eSBNZWFzdXJlcyIsICJTa2V3bmVzcyIsICJLdXJ0b3NpcyIpCmNvbG5hbWVzKHNrX2t1X3NsZV9kZikgPC0gYygiU2xlZXAgTWVhc3VyZXMiLCAiU2tld25lc3MiLCAiS3VydG9zaXMiKQpjb2xuYW1lcyhza19rdV93ZWlfZGYpIDwtIGMoIldlaWdodCBNZWFzdXJlcyIsICJTa2V3bmVzcyIsICJLdXJ0b3NpcyIpCgojRGF0YSBmcmFtZXMgdG8gdGFibGVzCmthYmxlKHNrX2t1X2FjdF9kZikKa2FibGUoc2tfa3Vfc2xlX2RmKQprYWJsZShza19rdV93ZWlfZGYpCmBgYAoKIyMjIE9ic2VydmF0aW9ucwpgYGB7cn0KCiNDYWxjdWxhdGluZyBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGFjcm9zcyBoZWFsdGggbWVhc3VyZXMKT1N0IDwtIGxlbmd0aChtZXJnZWQkVG90YWxTdGVwcykKT0RpIDwtIGxlbmd0aChtZXJnZWQkVG90YWxEaXN0YW5jZSkKT1ZlTWkgPC0gbGVuZ3RoKG1lcmdlZCRWZXJ5QWN0aXZlTWludXRlcykKT0ZhTWkgPC0gbGVuZ3RoKG1lcmdlZCRGYWlybHlBY3RpdmVNaW51dGVzKQpPTGlNaSA8LSBsZW5ndGgobWVyZ2VkJExpZ2h0bHlBY3RpdmVNaW51dGVzKQpPU2VNaSA8LSBsZW5ndGgobWVyZ2VkJFNlZGVudGFyeU1pbnV0ZXMpCk9DYSA8LSBsZW5ndGgobWVyZ2VkJENhbG9yaWVzKQpPU2wgPC0gbGVuZ3RoKHNsZWVwJG1pbnV0ZXNfYXNsZWVwKQpPQmQgPC0gbGVuZ3RoKHNsZWVwJG1pbnV0ZXNfaW5fYmVkKQpPV2UgPC0gbGVuZ3RoKHdlaWdodCR3ZWlnaHRfcG91bmRzKQpPQm1pIDwtIGxlbmd0aCh3ZWlnaHQkYm1pKQoKI09yZ2FuaXppbmcgaW5mb3JtYXRpb24gYWJvdXQgYWN0aXZpdHkgaW50byBkYXRhIGZyYW1lCm9fYWN0X21lYXN1cmVzIDwtIGMoIlRvdGFsIFN0ZXBzIiwgIlRvdGFsIERpc3RhbmNlIiwgIlZlcnkgQWN0aXZlIE1pbnV0ZXMiLCAiRmFpcmx5IEFjdGl2ZSBNaW51dGVzIiwgIkxpZ2h0bHkgQWN0aXZlIE1pbnV0ZXMiLCAiU2VkZW50YXJ5IE1pbnV0ZXMiLCAiQ2Fsb3JpZXMiKQpvX2FjdF9vYnNlcnZhdGlvbnMgPC0gYyhPU3QsIE9EaSwgT1ZlTWksIE9GYU1pLCBPTGlNaSwgT1NlTWksIE9DYSkKb19hY3RfZGYgPC0gZGF0YS5mcmFtZShvX2FjdF9tZWFzdXJlcywgb19hY3Rfb2JzZXJ2YXRpb25zKQoKI09yZ2FuaXppbmcgaW5mb3JtYXRpb24gYWJvdXQgc2xlZXAgaW50byBkYXRhIGZyYW1lCm9fc2xlX21lYXN1cmVzIDwtIGMoIk1pbnV0ZXMgQXNsZWVwIiwgIk1pbnV0ZXMgaW4gQmVkIikKb19zbGVfb2JzZXJ2YXRpb25zIDwtIGMoT1NsLCBPQmQpCm9fc2xlX2RmIDwtIGRhdGEuZnJhbWUob19zbGVfbWVhc3VyZXMsIG9fc2xlX29ic2VydmF0aW9ucykKCiNPcmdhbml6aW5nIGluZm9ybWF0aW9uIG9uIHdlaWdodCBpbnRvIGRhdGEgZnJhbWUKb193ZWlfbWVhc3VyZXMgPC0gYygiV2VpZ2h0IChsYnMpIiwgIkJNSSIpCm9fd2VpX29ic2VydmF0aW9ucyA8LSBjKE9XZSwgT0JtaSkKb193ZWlfZGYgPC0gZGF0YS5mcmFtZShvX3dlaV9tZWFzdXJlcywgb193ZWlfb2JzZXJ2YXRpb25zKQoKI1JlbmFtaW5nIENvbHVtbnMKY29sbmFtZXMob193ZWlfZGYpIDwtIGMoIldlaWdodCBNZWFzdXJlcyIsICJPYnNlcnZhdGlvbnMiKQpjb2xuYW1lcyhvX3NsZV9kZikgPC0gYygiU2xlZXAgTWVhc3VyZXMiLCAiT2JzZXJ2YXRpb25zIikKY29sbmFtZXMob19hY3RfZGYpIDwtIGMoIkFjdGl2aXR5IE1lYXN1cmVzIiwgIk9ic2VydmF0aW9ucyIpCgojQ29udmVydGluZyBkYXRhIGZyYW1lcyB0byB0YWJsZXMKa2FibGUob19hY3RfZGYpCmthYmxlKG9fc2xlX2RmKQprYWJsZShvX3dlaV9kZikKYGBgCgojIyBWaXN1YWwgUmVwcmVzZW50YXRpb24gb2YgRGF0YQoKYGBge3J9CgojQ2FsY3VsYXRpbmcgbnVtYmVyIG9mIHVuaXF1ZSB1c2Vycwp1c2Vyc19hY3Rpdml0eSA8LSBsZW5ndGgodW5pcXVlKG1lcmdlZCRJZCkpCnVzZXJzX3NsZWVwIDwtIGxlbmd0aCh1bmlxdWUoc2xlZXAkaWQpKQp1c2Vyc193ZWlnaHQgPC0gbGVuZ3RoKHVuaXF1ZSh3ZWlnaHQkaWQpKQoKI0NyZWF0aW5nIGRhdGEgZnJhbWUKdXNlcl92YWx1ZXMgPC0gYyh1c2Vyc19hY3Rpdml0eSwgdXNlcnNfc2xlZXAsIHVzZXJzX3dlaWdodCkKdXNlcl9sYWJlbHMgPC0gYygiQWN0aXZpdHkiLCAiU2xlZXAiLCAiV2VpZ2h0IikKdW5pcXVlX3VzZXJfZGYgPC0gZGF0YS5mcmFtZSh1c2VyX2xhYmVscywgdXNlcl92YWx1ZXMpCgojR3JhcGggb2YgdW5pcXVlIHVzZXJzCmdncGxvdCh1bmlxdWVfdXNlcl9kZikgKyBnZW9tX2NvbChtYXBwaW5nID0gYWVzKHg9dXNlcl9sYWJlbHMsIHk9dXNlcl92YWx1ZXMpLCBmaWxsID0gIiMwMDAwNjYiKSArIHRoZW1lX2J3KCkgKyBsYWJzKHggPSAiSGVhbHRoIENhdGVnb3JpZXMiLCB5ID0gIlRvdGFsIiwgdGl0bGUgPSAiVW5pcXVlIFVzZXJzIikgKyB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpKQpgYGAKCmBgYHtyfQojQ29sb3IgcGFsZXR0ZQoKY2JQYWxldHRlIDwtIGMoIiM5OTk5OTkiLCAiIzAwOUU3MyIpCgojR3JhcGggb2Ygd2VpZ2h0LXNwZWNpZmljIGRhdGEKZ2dwbG90KHdlaWdodCkgKyBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHg9aWQsIGZpbGwgPSBtYW51YWxfcmVwb3J0KSkgKyBjb29yZF9mbGlwKCkgKyB0aGVtZV9idygpICsgbGFicyh4ID0gIlVzZXIgSUQiLCB5PSJUb3RhbCIsIHRpdGxlID0gIlR5cGUgb2YgV2VpZ2h0IExvZyIpICsgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jYlBhbGV0dGUpICsgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMi41KSwgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpKQoKYGBgCgojIyBQb3RlbnRpYWwgR3Jvd3RoIEFyZWEKClR3byBpbXBvcnRhbnQgdGhlbWVzIHdlcmUgZm91bmQgaW4gdGhlIHdlaWdodC1zcGVjaWZpYyBhbmFseXNpcy4gCgoxLiBNb3N0IG9ic2VydmF0aW9ucyB3ZXJlIGxvZ2dlZCBtYW51YWxseQoyLiBPZiB0aGUgbGltaXRlZCB1c2VycywgbW9zdCBsb2dnZWQgdGhlaXIgd2VpZ2h0IGZld2VyIHRoYW4gNSB0aW1lc1wKCkJhc2VkIG9uIHRoZSBhdmFpbGFibGUgaW5mb3JtYXRpb24sIGl0IGFwcGVhcnMgKiptZWFzdXJlcyB3aXRob3V0IGF1dG9tYXRlZCBkYXRhIGNvbGxlY3Rpb24gYXJlIGxlc3MgbGlrZWx5IHRvIGJlIG1vbml0b3JlZCBhbmQgdXNlZC4qKiBcCgpQYXR0ZXJucyBpbiB1c2VyIGJlaGF2aW9yIG1heSBiZSBhdHRyaWJ1dGVkIHRvIHRoZSBlZmZvcnQgcmVxdWlyZWQgdG8gbWFudWFsbHkgbG9nIGRhdGEsIGZvcmdldHRpbmcgdG8gY29tcGxldGUgdGhlIHRhc2sgZHVlIHRvIGNvbXBldGluZyBvYmxpZ2F0aW9ucyAoZS5nLiwgd29yaywgZmFtaWx5KSwgb3IgYSBjb21iaW5hdGlvbiBvZiBmYWN0b3JzLlwKCkJlbGxhYmVhdCBkb2VzIG5vdCBjdXJyZW50bHkgb2ZmZXIgYSBwcm9kdWN0IHdpdGggYXV0b21hdGVkIGRhdGEgY29sbGVjaXRvbiBmb3Igd2VpZ2h0IChzZWUgdGFibGUgYmVsb3cpLlwKCmBgYHtyIGVjaG89RkFMU0V9CgojRGF0YSBmb3IgZGF0YSBmcmFtZQpQcm9kdWN0IDwtIGMoIkxlYWYiLCAiVGltZSIsICJTcHJpbmciKQpEZXNjcmlwdGlvbiA8LSBjKCJXb3JuIGFzIGJyYWNlbGV0LCBjbGlwLCBvciBuZWNrbGFjZSIsICJXb3JuIGFzIHdhdGNoIiwgIlVzZWQgYXMgd2F0ZXIgYm90dGxlIikgCkFjdGl2aXR5IDwtIGMoIlllcyIsICJZZXMiLCAiTm8iKQpTbGVlcCA8LSBjKCJZZXMiLCAiWWVzIiwgIk5vIikKU3RyZXNzIDwtIGMoIlllcyIsICJZZXMiLCAiTm8iKQpIeWRyYXRpb24gPC0gYygiTm8iLCAiTm8iLCAiWWVzIikKV2VpZ2h0IDwtIGMoIk5vIiwgIk5vIiwgIk5vIikKCiNEYXRhIGZyYW1lIGFib3V0IEJlbGxhYmVhdCBwcm9kdWN0cwpwcm9kdWN0X2RmIDwtIGRhdGEuZnJhbWUoUHJvZHVjdCwgRGVzY3JpcHRpb24sIEFjdGl2aXR5LCBTbGVlcCwgU3RyZXNzLCBIeWRyYXRpb24sIFdlaWdodCkKCiNEYXRhIGZyYW1lIHRvIHRhYmxlCmthYmxlKHByb2R1Y3RfZGYpCmBgYAoKSWYgdXNlcnMgbXVzdCBlbnRlciBkYXRhIG1hbnVhbGx5IG9yIHVzZSBhbm90aGVyIHByb2R1Y3QgdG8gY29sbGVjdCB3ZWlnaHQgZGF0YSBhdXRvbWF0aWNhbGx5LCBpdCBtYXkgZGVjcmVhc2UgdGhlIHVzZSBvZiB0aGUgQmVsbGFiZWF0IGFwcCBhbmQgdGhlIG9ubGluZSBjb2FjaGluZyBwcm9ncmFtLCB3aGljaCB3b3VsZCBkZWNyZWFzZSB1c2VyIGVuZ2FnZW1lbnQuCgojIyBSZWNvbW1lbmRhdGlvbnMgCkltbWVkaWF0ZSBOZXh0IFN0ZXBzOgoKLSBDb25kdWN0IGEgYnJpZWYgc3VydmV5IG9mIGN1cnJlbnQgY3VzdG9tZXJzIHRvOgogIC0gVmVyaWZ5IHRoZSByZXN1bHRzIG9mIHRoZSByZXN1bHRzIG9mIHRoZSBhbmFseXNpcwogIC0gR2F1Z2UgY3VzdG9tZXIgaW50ZXJlc3QgYWJvdXQgYWRkaW5nIGEgZmVhdHVyZSB0byBhdXRvbWF0aWNhbGx5IGxvZyB3ZWlnaHQgZGF0YQoKSWYgdGhlIHJlc3VsdHMgb2YgdGhlIHN1cnZleSBjb3JyZXNwb25kIHdpdGggdGhlIGFuYWx5c2lzIGFuZCB0aGVyZSBpcyBzdWZmaWNpZW50IGN1c3RvbWVyIGludGVyZXN0OiAKCjEuIEV4YW1pbmUgdGhlIGNvc3QgYXNzb2NpYXRlZCB3aXRoIGFkZGluZyBhdXRvbWF0ZWQgd2VpZ2h0IGNvbGxlY3Rpb24gdG8gZnV0dXJlIHByb2R1Y3RzLgoKMi4gQ29uc2lkZXIgcmVsZWFzaW5nIGEgbGltaXRlZCBhbW91bnQgb2YgdXBkYXRlZCBkZXZpY2VzIGFuZCBtb25pdG9yIHRoZSB1c2Ugb2YgdGhlIEJlbGxhYmVhdCBhcHAgYW5kIG9ubGluZSBjb2FjaGluZyBwcm9ncmFtIGZvciBhIGNvbmN1cnJlbnQgaW5jcmVhc2UgaW4gdXNlciBlbmdhZ2VtZW50LgoKLS0tCg==