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:
- The data are not normally distrbuted
- Users collected data on activities more often than other health categories
- Users collected data on weight least often
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)
| 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)
| Minutes Asleep |
-0.6127408 |
4.582448 |
| Minutes in Bed |
-0.2178411 |
6.441879 |
kable(sk_ku_wei_df)
| 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)
| 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)
| Minutes Asleep |
413 |
| Minutes in Bed |
413 |
kable(o_wei_df)
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.
- Most observations were logged manually
- 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).
| 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:
- Conduct a brief survey of current customers to:
- Verify the results of the results of the analysis
- Gauge customer interest about adding a feature to automatically log weight data
If the results of the survey correspond with the analysis and there is sufficient customer interest:
Examine the cost associated with adding automated weight collection to future products.
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==