This dataset is too large to view in a spreadsheet, so this notebook
is a changelog for using SQL to clean the health_fitness_dataset on
google’s BigQuery.
2. Summarizing Data
The following queries were run to summarize the data. This
summary table was created in Google Sheets to compile these
results.
Summarizing Gender
SELECT
gender,
COUNT(DISTINCT participant_id) AS user_count
FROM `complete-will-468115-p2.fitlife360_synthetic_health_data.fitlife`
GROUP BY gender;
Summarizing Activity Types
First, this query was run to summarize the activity types, split up
by intensity:
SELECT
activity_type, intensity,
COUNT(DISTINCT participant_id) AS activity_type_count,
COUNT(participant_id) AS activity_session_count,
SUM(duration_minutes) AS activity_duration_count,
ROUND(AVG(duration_minutes), 2) AS activity_duration_average_in_minutes,
ROUND(MIN(duration_minutes), 2) AS activity_duration_min_in_minutes,
ROUND(MAX(duration_minutes), 2) AS activity_duration_max_in_minutes,
FROM `complete-will-468115-p2.fitlife360_synthetic_health_data.fitlife`
GROUP BY activity_type, intensity
ORDER BY activity_type,
CASE intensity
WHEN 'Low' THEN 1
WHEN 'Medium' THEN 2
WHEN 'High' THEN 3
ELSE NULL
END
Intensity minutes breakdown
SELECT
intensity,
COUNT(intensity) AS intensity_session_total_count
FROM `complete-will-468115-p2.fitlife360_synthetic_health_data.fitlife`
GROUP BY
intensity
ORDER BY
CASE intensity
WHEN 'Low' THEN 1
WHEN 'Medium' THEN 2
WHEN 'High' THEN 3
ELSE NULL
END
Min, Max, Avg Summaries by User
SELECT
intensity,
DISTINCT participant_id,
ROUND(AVG(stress_level), 2) AS stress_average,
ROUND(MIN(stress_level), 2) AS stress_min,
ROUND(MAX(stress_level), 2) AS stress_max,
ROUND(AVG(hours_sleep), 2) AS hours_sleep_average,
ROUND(MIN(hours_sleep), 2) AS hours_sleep_min,
ROUND(MAX(hours_sleep), 2) AS hours_sleep_max,
ROUND(AVG(weight_kg), 2) AS weight_kg_average,
ROUND(MIN(weight_kg), 2) AS weight_kg_min,
ROUND(MAX(weight_kg), 2) AS weight_kg_max,
ROUND(AVG(hydration_level), 2) AS hydration_level_average,
ROUND(MIN(hydration_level), 2) AS hydration_level_min,
ROUND(MAX(hydration_level), 2) AS hydration_level_max,
ROUND(AVG(daily_steps)) AS daily_steps_average,
ROUND(MIN(daily_steps)) AS daily_steps_min,
ROUND(MAX(daily_steps)) AS daily_steps_max,
ROUND(AVG(age), 2) AS average_age,
ROUND(AVG(duration_minutes)) AS duration_average_in_minutes,
ROUND(MIN(duration_minutes)) AS duration_min_in_minutes,
ROUND(MAX(duration_minutes)) AS duration_max_in_minutes,
ROUND(AVG(bmi)) AS bmi_average,
ROUND(MIN(bmi)) AS bmi_min,
ROUND(MAX(bmi)) AS bmi_max,
ROUND(AVG(resting_heart_rate)) AS resting_heart_rate_average,
ROUND(MIN(resting_heart_rate)) AS resting_heart_rate_min,
ROUND(MAX(resting_heart_rate)) AS resting_heart_rate_max,
ROUND(AVG(blood_pressure_diastolic)) AS blood_pressure_diastolic_average,
ROUND(MIN(blood_pressure_diastolic)) AS blood_pressure_diastolic_min,
ROUND(MAX(blood_pressure_diastolic)) AS blood_pressure_diastolic_max,
ROUND(AVG(blood_pressure_systolic)) AS blood_pressure_systolic_average,
ROUND(MIN(blood_pressure_systolic)) AS blood_pressure_systolic_min,
ROUND(MAX(blood_pressure_systolic)) AS blood_pressure_systolic_max,
ROUND(AVG(calories_burned)) AS calories_burned_average,
ROUND(MIN(calories_burned)) AS calories_burned_min,
ROUND(MAX(calories_burned)) AS calories_burned_max,
FROM `complete-will-468115-p2.fitlife360_synthetic_health_data.fitlife`
GROUP BY activity_type, intensity
ORDER BY activity_type,
CASE intensity
WHEN 'Low' THEN 1
WHEN 'Medium' THEN 2
WHEN 'High' THEN 3
ELSE NULL
END
Min, Max, Avg Summaries by Date
SELECT
DISTINCT date,
ROUND(AVG(stress_level), 2) AS stress_average,
ROUND(MIN(stress_level), 2) AS stress_min,
ROUND(MAX(stress_level), 2) AS stress_max,
ROUND(AVG(hours_sleep), 2) AS hours_sleep_average,
ROUND(MIN(hours_sleep), 2) AS hours_sleep_min,
ROUND(MAX(hours_sleep), 2) AS hours_sleep_max,
ROUND(AVG(weight_kg), 2) AS weight_kg_average,
ROUND(MIN(weight_kg), 2) AS weight_kg_min,
ROUND(MAX(weight_kg), 2) AS weight_kg_max,
ROUND(AVG(hydration_level), 2) AS hydration_level_average,
ROUND(MIN(hydration_level), 2) AS hydration_level_min,
ROUND(MAX(hydration_level), 2) AS hydration_level_max,
ROUND(AVG(daily_steps)) AS daily_steps_average,
ROUND(MIN(daily_steps)) AS daily_steps_min,
ROUND(MAX(daily_steps)) AS daily_steps_max,
ROUND(AVG(age), 2) AS average_age,
ROUND(AVG(duration_minutes)) AS duration_average_in_minutes,
ROUND(MIN(duration_minutes)) AS duration_min_in_minutes,
ROUND(MAX(duration_minutes)) AS duration_max_in_minutes,
ROUND(AVG(bmi)) AS bmi_average,
ROUND(MIN(bmi)) AS bmi_min,
ROUND(MAX(bmi)) AS bmi_max,
ROUND(AVG(resting_heart_rate)) AS resting_heart_rate_average,
ROUND(MIN(resting_heart_rate)) AS resting_heart_rate_min,
ROUND(MAX(resting_heart_rate)) AS resting_heart_rate_max,
ROUND(AVG(blood_pressure_diastolic)) AS blood_pressure_diastolic_average,
ROUND(MIN(blood_pressure_diastolic)) AS blood_pressure_diastolic_min,
ROUND(MAX(blood_pressure_diastolic)) AS blood_pressure_diastolic_max,
ROUND(AVG(blood_pressure_systolic)) AS blood_pressure_systolic_average,
ROUND(MIN(blood_pressure_systolic)) AS blood_pressure_systolic_min,
ROUND(MAX(blood_pressure_systolic)) AS blood_pressure_systolic_max,
ROUND(AVG(calories_burned)) AS calories_burned_average,
ROUND(MIN(calories_burned)) AS calories_burned_min,
ROUND(MAX(calories_burned)) AS calories_burned_max,
ROUND(AVG(duration_minutes)) AS duration_minutes_average,
ROUND(MIN(duration_minutes)) AS duration_minutes_min,
ROUND(MAX(duration_minutes)) AS duration_minutes_max,
FROM `complete-will-468115-p2.fitlife360_synthetic_health_data.fitlife`
GROUP BY date;
3. Summarizing While Filtering for Gender
Bellabeat has positioned itself as a health & wellness company
for women, so the data has been filtered to exclude men by adding the
following to each summary query written in the previous section to
filter the men out of the dataset without altering the dataset
itself.
WHERE gender <> "M"
Summing activities by user and date without dividing by
intensity
Breaking the sums up yesterday created a potential for confusing data
as each user could be counted in each intensity category, meaning just
summing those values would not be accurate in counting unique users for
each activity.
SELECT
activity_type,
COUNT(DISTINCT participant_id) AS unique_users
FROM `complete-will-468115-p2.fitlife360_synthetic_health_data.fitlife`
GROUP BY
activity_type
ORDER BY
activity_type;
Activity Session Counts
SELECT
activity_type,
COUNT(activity_type) AS activity_session_count
FROM `complete-will-468115-p2.fitlife360_synthetic_health_data.fitlife`
GROUP BY
activity_type
ORDER BY
activity_type;
Activity Duration Summary
SELECT
activity_type,
SUM(duration_minutes) AS activity_duration_in_minutes
FROM `complete-will-468115-p2.fitlife360_synthetic_health_data.fitlife`
GROUP BY
activity_type
ORDER BY
activity_type;
LS0tCnRpdGxlOiAiRml0TGlmZSBEYXRhc2V0IENoYW5nZWxvZyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBkYXRhc2V0IGlzIHRvbyBsYXJnZSB0byB2aWV3IGluIGEgc3ByZWFkc2hlZXQsIHNvIHRoaXMgbm90ZWJvb2sgaXMgYSBjaGFuZ2Vsb2cgZm9yIHVzaW5nIFNRTCB0byBjbGVhbiB0aGUgaGVhbHRoX2ZpdG5lc3NfZGF0YXNldCBvbiBnb29nbGUncyBCaWdRdWVyeS4KCiMjIDEuIEludmVzdGlnYXRpbmcgTlVMTCBWYWx1ZXMKClZhcmlhdGlvbnMgb2YgdGhlIGZvbGxvd2luZyBzY3JpcHQgd2VyZSBydW4gZm9yIGV2ZXJ5IGNvbHVtbiB0byBkaXNjb3ZlciBpZiB0aGVyZSB3ZXJlIGFueSBOVUxMIHZhbHVlcy4KCmBgYHtzcWwgY29ubmVjdGlvbj19ClNFTEVDVCAgKCopCkZST00gYGNvbXBsZXRlLXdpbGwtNDY4MTE1LXAyLmZpdGxpZmUzNjBfc3ludGhldGljX2hlYWx0aF9kYXRhLmZpdGxpZmVgCldIRVJFIAogIHBhcnRpY3BhbnRfaWQgSVMgTlVMTDsKCmBgYAoKQXMgZXhwZWN0ZWQgZnJvbSBhIHN5bnRoZXRpYyBkYXRhc2V0LCB0aGVyZSB3ZXJlIG5vIHJvd3MgY29udGFpbmluZyBOVUxMIHZhbHVlcyB0aGF0IG5lZWRlZCB0byBiZSBleGNsdWRlZCBmcm9tIHRoZSBkYXRhc2V0LgoKCiMjIDIuIFN1bW1hcml6aW5nIERhdGEKVGhlIGZvbGxvd2luZyBxdWVyaWVzIHdlcmUgcnVuIHRvIHN1bW1hcml6ZSB0aGUgZGF0YS4gW1RoaXMgc3VtbWFyeSB0YWJsZV0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMXlVWi05bTNWamM4RHQyV0JScWhFNTlnYm5ST0x2bkd0czNmcHBrT1dhZlEvZWRpdD91c3A9c2hhcmluZykgd2FzIGNyZWF0ZWQgaW4gR29vZ2xlIFNoZWV0cyB0byBjb21waWxlIHRoZXNlIHJlc3VsdHMuCgojIyMgU3VtbWFyaXppbmcgR2VuZGVyCmBgYHtzcWwgY29ubmVjdGlvbj1zdW1tYXJpemluZ19nZW5kZXJ9ClNFTEVDVCAgCiAgZ2VuZGVyLAogIENPVU5UKERJU1RJTkNUIHBhcnRpY2lwYW50X2lkKSBBUyB1c2VyX2NvdW50CkZST00gYGNvbXBsZXRlLXdpbGwtNDY4MTE1LXAyLmZpdGxpZmUzNjBfc3ludGhldGljX2hlYWx0aF9kYXRhLmZpdGxpZmVgCkdST1VQIEJZIGdlbmRlcjsKCmBgYAoKIyMjIFN1bW1hcml6aW5nIEFjdGl2aXR5IFR5cGVzCgpGaXJzdCwgdGhpcyBxdWVyeSB3YXMgcnVuIHRvIHN1bW1hcml6ZSB0aGUgYWN0aXZpdHkgdHlwZXMsIHNwbGl0IHVwIGJ5IGludGVuc2l0eToKCmBgYHtzcWwgY29ubmVjdGlvbj1hY3Rpdml0eV9kdXJhdGlvbl9ieV9pbnRlbnNpdHlfaW5fbWludXRlc30KU0VMRUNUCiAgYWN0aXZpdHlfdHlwZSwgaW50ZW5zaXR5LAogIENPVU5UKERJU1RJTkNUIHBhcnRpY2lwYW50X2lkKSBBUyBhY3Rpdml0eV90eXBlX2NvdW50LAogIENPVU5UKHBhcnRpY2lwYW50X2lkKSBBUyBhY3Rpdml0eV9zZXNzaW9uX2NvdW50LAogIFNVTShkdXJhdGlvbl9taW51dGVzKSBBUyBhY3Rpdml0eV9kdXJhdGlvbl9jb3VudCwKICBST1VORChBVkcoZHVyYXRpb25fbWludXRlcyksIDIpIEFTIGFjdGl2aXR5X2R1cmF0aW9uX2F2ZXJhZ2VfaW5fbWludXRlcywKICBST1VORChNSU4oZHVyYXRpb25fbWludXRlcyksIDIpIEFTIGFjdGl2aXR5X2R1cmF0aW9uX21pbl9pbl9taW51dGVzLAogIFJPVU5EKE1BWChkdXJhdGlvbl9taW51dGVzKSwgMikgQVMgYWN0aXZpdHlfZHVyYXRpb25fbWF4X2luX21pbnV0ZXMsCkZST00gYGNvbXBsZXRlLXdpbGwtNDY4MTE1LXAyLmZpdGxpZmUzNjBfc3ludGhldGljX2hlYWx0aF9kYXRhLmZpdGxpZmVgIApHUk9VUCBCWSBhY3Rpdml0eV90eXBlLCBpbnRlbnNpdHkKT1JERVIgQlkgYWN0aXZpdHlfdHlwZSwKICBDQVNFIGludGVuc2l0eQogICAgICAgIFdIRU4gJ0xvdycgVEhFTiAxCiAgICAgICAgV0hFTiAnTWVkaXVtJyBUSEVOIDIKICAgICAgICBXSEVOICdIaWdoJyBUSEVOIDMKICAgICAgICBFTFNFIE5VTEwKICAgICAgICBFTkQKYGBgCiMjIyBJbnRlbnNpdHkgbWludXRlcyBicmVha2Rvd24KYGBge3NxbCBjb25uZWN0aW9uPWludGVuc2l0eV9taW51dGVzfQpTRUxFQ1QKICBpbnRlbnNpdHksCiAgQ09VTlQoaW50ZW5zaXR5KSBBUyBpbnRlbnNpdHlfc2Vzc2lvbl90b3RhbF9jb3VudApGUk9NIGBjb21wbGV0ZS13aWxsLTQ2ODExNS1wMi5maXRsaWZlMzYwX3N5bnRoZXRpY19oZWFsdGhfZGF0YS5maXRsaWZlYApHUk9VUCBCWSAgCiAgaW50ZW5zaXR5Ck9SREVSIEJZICAKICBDQVNFIGludGVuc2l0eQogICAgICAgIFdIRU4gJ0xvdycgVEhFTiAxCiAgICAgICAgV0hFTiAnTWVkaXVtJyBUSEVOIDIKICAgICAgICBXSEVOICdIaWdoJyBUSEVOIDMKICAgICAgICBFTFNFIE5VTEwKICAgICAgICBFTkQKYGBgCiMjIyBNaW4sIE1heCwgQXZnIFN1bW1hcmllcyBieSBVc2VyCmBgYHtzcWwgY29ubmVjdGlvbj1zdHJlc3NfYW5kX3NsZWVwX3N1bW1hcnl9ClNFTEVDVAogIGludGVuc2l0eSwKICBESVNUSU5DVCBwYXJ0aWNpcGFudF9pZCwKICBST1VORChBVkcoc3RyZXNzX2xldmVsKSwgMikgQVMgc3RyZXNzX2F2ZXJhZ2UsCiAgUk9VTkQoTUlOKHN0cmVzc19sZXZlbCksIDIpIEFTIHN0cmVzc19taW4sCiAgUk9VTkQoTUFYKHN0cmVzc19sZXZlbCksIDIpIEFTIHN0cmVzc19tYXgsCiAgUk9VTkQoQVZHKGhvdXJzX3NsZWVwKSwgMikgQVMgaG91cnNfc2xlZXBfYXZlcmFnZSwKICBST1VORChNSU4oaG91cnNfc2xlZXApLCAyKSBBUyBob3Vyc19zbGVlcF9taW4sCiAgUk9VTkQoTUFYKGhvdXJzX3NsZWVwKSwgMikgQVMgaG91cnNfc2xlZXBfbWF4LAogIFJPVU5EKEFWRyh3ZWlnaHRfa2cpLCAyKSBBUyB3ZWlnaHRfa2dfYXZlcmFnZSwKICBST1VORChNSU4od2VpZ2h0X2tnKSwgMikgQVMgd2VpZ2h0X2tnX21pbiwKICBST1VORChNQVgod2VpZ2h0X2tnKSwgMikgQVMgd2VpZ2h0X2tnX21heCwKICBST1VORChBVkcoaHlkcmF0aW9uX2xldmVsKSwgMikgQVMgaHlkcmF0aW9uX2xldmVsX2F2ZXJhZ2UsCiAgUk9VTkQoTUlOKGh5ZHJhdGlvbl9sZXZlbCksIDIpIEFTIGh5ZHJhdGlvbl9sZXZlbF9taW4sCiAgUk9VTkQoTUFYKGh5ZHJhdGlvbl9sZXZlbCksIDIpIEFTIGh5ZHJhdGlvbl9sZXZlbF9tYXgsCiAgUk9VTkQoQVZHKGRhaWx5X3N0ZXBzKSkgQVMgZGFpbHlfc3RlcHNfYXZlcmFnZSwKICBST1VORChNSU4oZGFpbHlfc3RlcHMpKSBBUyBkYWlseV9zdGVwc19taW4sCiAgUk9VTkQoTUFYKGRhaWx5X3N0ZXBzKSkgQVMgZGFpbHlfc3RlcHNfbWF4LAogIFJPVU5EKEFWRyhhZ2UpLCAyKSBBUyBhdmVyYWdlX2FnZSwKICBST1VORChBVkcoZHVyYXRpb25fbWludXRlcykpIEFTIGR1cmF0aW9uX2F2ZXJhZ2VfaW5fbWludXRlcywKICBST1VORChNSU4oZHVyYXRpb25fbWludXRlcykpIEFTIGR1cmF0aW9uX21pbl9pbl9taW51dGVzLAogIFJPVU5EKE1BWChkdXJhdGlvbl9taW51dGVzKSkgQVMgZHVyYXRpb25fbWF4X2luX21pbnV0ZXMsCiAgUk9VTkQoQVZHKGJtaSkpIEFTIGJtaV9hdmVyYWdlLAogIFJPVU5EKE1JTihibWkpKSBBUyBibWlfbWluLAogIFJPVU5EKE1BWChibWkpKSBBUyBibWlfbWF4LAogIFJPVU5EKEFWRyhyZXN0aW5nX2hlYXJ0X3JhdGUpKSBBUyByZXN0aW5nX2hlYXJ0X3JhdGVfYXZlcmFnZSwKICBST1VORChNSU4ocmVzdGluZ19oZWFydF9yYXRlKSkgQVMgcmVzdGluZ19oZWFydF9yYXRlX21pbiwKICBST1VORChNQVgocmVzdGluZ19oZWFydF9yYXRlKSkgQVMgcmVzdGluZ19oZWFydF9yYXRlX21heCwKICBST1VORChBVkcoYmxvb2RfcHJlc3N1cmVfZGlhc3RvbGljKSkgQVMgYmxvb2RfcHJlc3N1cmVfZGlhc3RvbGljX2F2ZXJhZ2UsCiAgUk9VTkQoTUlOKGJsb29kX3ByZXNzdXJlX2RpYXN0b2xpYykpIEFTIGJsb29kX3ByZXNzdXJlX2RpYXN0b2xpY19taW4sCiAgUk9VTkQoTUFYKGJsb29kX3ByZXNzdXJlX2RpYXN0b2xpYykpIEFTIGJsb29kX3ByZXNzdXJlX2RpYXN0b2xpY19tYXgsCiAgUk9VTkQoQVZHKGJsb29kX3ByZXNzdXJlX3N5c3RvbGljKSkgQVMgYmxvb2RfcHJlc3N1cmVfc3lzdG9saWNfYXZlcmFnZSwKICBST1VORChNSU4oYmxvb2RfcHJlc3N1cmVfc3lzdG9saWMpKSBBUyBibG9vZF9wcmVzc3VyZV9zeXN0b2xpY19taW4sCiAgUk9VTkQoTUFYKGJsb29kX3ByZXNzdXJlX3N5c3RvbGljKSkgQVMgYmxvb2RfcHJlc3N1cmVfc3lzdG9saWNfbWF4LAogIFJPVU5EKEFWRyhjYWxvcmllc19idXJuZWQpKSBBUyBjYWxvcmllc19idXJuZWRfYXZlcmFnZSwKICBST1VORChNSU4oY2Fsb3JpZXNfYnVybmVkKSkgQVMgY2Fsb3JpZXNfYnVybmVkX21pbiwKICBST1VORChNQVgoY2Fsb3JpZXNfYnVybmVkKSkgQVMgY2Fsb3JpZXNfYnVybmVkX21heCwKRlJPTSBgY29tcGxldGUtd2lsbC00NjgxMTUtcDIuZml0bGlmZTM2MF9zeW50aGV0aWNfaGVhbHRoX2RhdGEuZml0bGlmZWAgCkdST1VQIEJZIGFjdGl2aXR5X3R5cGUsIGludGVuc2l0eQpPUkRFUiBCWSBhY3Rpdml0eV90eXBlLAogIENBU0UgaW50ZW5zaXR5CiAgICAgICAgV0hFTiAnTG93JyBUSEVOIDEKICAgICAgICBXSEVOICdNZWRpdW0nIFRIRU4gMgogICAgICAgIFdIRU4gJ0hpZ2gnIFRIRU4gMwogICAgICAgIEVMU0UgTlVMTAogICAgICAgIEVORApgYGAKIyMjIE1pbiwgTWF4LCBBdmcgU3VtbWFyaWVzIGJ5IERhdGUKYGBge3NxbCBjb25uZWN0aW9uPWJ5X2RhdGVfc3VtbWFyaWVzfQpTRUxFQ1QKICBESVNUSU5DVCBkYXRlLAogIFJPVU5EKEFWRyhzdHJlc3NfbGV2ZWwpLCAyKSBBUyBzdHJlc3NfYXZlcmFnZSwKICBST1VORChNSU4oc3RyZXNzX2xldmVsKSwgMikgQVMgc3RyZXNzX21pbiwKICBST1VORChNQVgoc3RyZXNzX2xldmVsKSwgMikgQVMgc3RyZXNzX21heCwKICBST1VORChBVkcoaG91cnNfc2xlZXApLCAyKSBBUyBob3Vyc19zbGVlcF9hdmVyYWdlLAogIFJPVU5EKE1JTihob3Vyc19zbGVlcCksIDIpIEFTIGhvdXJzX3NsZWVwX21pbiwKICBST1VORChNQVgoaG91cnNfc2xlZXApLCAyKSBBUyBob3Vyc19zbGVlcF9tYXgsCiAgUk9VTkQoQVZHKHdlaWdodF9rZyksIDIpIEFTIHdlaWdodF9rZ19hdmVyYWdlLAogIFJPVU5EKE1JTih3ZWlnaHRfa2cpLCAyKSBBUyB3ZWlnaHRfa2dfbWluLAogIFJPVU5EKE1BWCh3ZWlnaHRfa2cpLCAyKSBBUyB3ZWlnaHRfa2dfbWF4LAogIFJPVU5EKEFWRyhoeWRyYXRpb25fbGV2ZWwpLCAyKSBBUyBoeWRyYXRpb25fbGV2ZWxfYXZlcmFnZSwKICBST1VORChNSU4oaHlkcmF0aW9uX2xldmVsKSwgMikgQVMgaHlkcmF0aW9uX2xldmVsX21pbiwKICBST1VORChNQVgoaHlkcmF0aW9uX2xldmVsKSwgMikgQVMgaHlkcmF0aW9uX2xldmVsX21heCwKICBST1VORChBVkcoZGFpbHlfc3RlcHMpKSBBUyBkYWlseV9zdGVwc19hdmVyYWdlLAogIFJPVU5EKE1JTihkYWlseV9zdGVwcykpIEFTIGRhaWx5X3N0ZXBzX21pbiwKICBST1VORChNQVgoZGFpbHlfc3RlcHMpKSBBUyBkYWlseV9zdGVwc19tYXgsCiAgUk9VTkQoQVZHKGFnZSksIDIpIEFTIGF2ZXJhZ2VfYWdlLAogIFJPVU5EKEFWRyhkdXJhdGlvbl9taW51dGVzKSkgQVMgZHVyYXRpb25fYXZlcmFnZV9pbl9taW51dGVzLAogIFJPVU5EKE1JTihkdXJhdGlvbl9taW51dGVzKSkgQVMgZHVyYXRpb25fbWluX2luX21pbnV0ZXMsCiAgUk9VTkQoTUFYKGR1cmF0aW9uX21pbnV0ZXMpKSBBUyBkdXJhdGlvbl9tYXhfaW5fbWludXRlcywKICBST1VORChBVkcoYm1pKSkgQVMgYm1pX2F2ZXJhZ2UsCiAgUk9VTkQoTUlOKGJtaSkpIEFTIGJtaV9taW4sCiAgUk9VTkQoTUFYKGJtaSkpIEFTIGJtaV9tYXgsCiAgUk9VTkQoQVZHKHJlc3RpbmdfaGVhcnRfcmF0ZSkpIEFTIHJlc3RpbmdfaGVhcnRfcmF0ZV9hdmVyYWdlLAogIFJPVU5EKE1JTihyZXN0aW5nX2hlYXJ0X3JhdGUpKSBBUyByZXN0aW5nX2hlYXJ0X3JhdGVfbWluLAogIFJPVU5EKE1BWChyZXN0aW5nX2hlYXJ0X3JhdGUpKSBBUyByZXN0aW5nX2hlYXJ0X3JhdGVfbWF4LAogIFJPVU5EKEFWRyhibG9vZF9wcmVzc3VyZV9kaWFzdG9saWMpKSBBUyBibG9vZF9wcmVzc3VyZV9kaWFzdG9saWNfYXZlcmFnZSwKICBST1VORChNSU4oYmxvb2RfcHJlc3N1cmVfZGlhc3RvbGljKSkgQVMgYmxvb2RfcHJlc3N1cmVfZGlhc3RvbGljX21pbiwKICBST1VORChNQVgoYmxvb2RfcHJlc3N1cmVfZGlhc3RvbGljKSkgQVMgYmxvb2RfcHJlc3N1cmVfZGlhc3RvbGljX21heCwKICBST1VORChBVkcoYmxvb2RfcHJlc3N1cmVfc3lzdG9saWMpKSBBUyBibG9vZF9wcmVzc3VyZV9zeXN0b2xpY19hdmVyYWdlLAogIFJPVU5EKE1JTihibG9vZF9wcmVzc3VyZV9zeXN0b2xpYykpIEFTIGJsb29kX3ByZXNzdXJlX3N5c3RvbGljX21pbiwKICBST1VORChNQVgoYmxvb2RfcHJlc3N1cmVfc3lzdG9saWMpKSBBUyBibG9vZF9wcmVzc3VyZV9zeXN0b2xpY19tYXgsCiAgUk9VTkQoQVZHKGNhbG9yaWVzX2J1cm5lZCkpIEFTIGNhbG9yaWVzX2J1cm5lZF9hdmVyYWdlLAogIFJPVU5EKE1JTihjYWxvcmllc19idXJuZWQpKSBBUyBjYWxvcmllc19idXJuZWRfbWluLAogIFJPVU5EKE1BWChjYWxvcmllc19idXJuZWQpKSBBUyBjYWxvcmllc19idXJuZWRfbWF4LAogIFJPVU5EKEFWRyhkdXJhdGlvbl9taW51dGVzKSkgQVMgZHVyYXRpb25fbWludXRlc19hdmVyYWdlLAogIFJPVU5EKE1JTihkdXJhdGlvbl9taW51dGVzKSkgQVMgZHVyYXRpb25fbWludXRlc19taW4sCiAgUk9VTkQoTUFYKGR1cmF0aW9uX21pbnV0ZXMpKSBBUyBkdXJhdGlvbl9taW51dGVzX21heCwKRlJPTSBgY29tcGxldGUtd2lsbC00NjgxMTUtcDIuZml0bGlmZTM2MF9zeW50aGV0aWNfaGVhbHRoX2RhdGEuZml0bGlmZWAgCkdST1VQIEJZIGRhdGU7CmBgYAoKCiMjIyAzLiBTdW1tYXJpemluZyBXaGlsZSBGaWx0ZXJpbmcgZm9yIEdlbmRlcgpCZWxsYWJlYXQgaGFzIHBvc2l0aW9uZWQgaXRzZWxmIGFzIGEgaGVhbHRoICYgd2VsbG5lc3MgY29tcGFueSBmb3Igd29tZW4sIHNvIHRoZSBkYXRhIGhhcyBiZWVuIGZpbHRlcmVkIHRvIGV4Y2x1ZGUgbWVuIGJ5IGFkZGluZyB0aGUgZm9sbG93aW5nIHRvIGVhY2ggc3VtbWFyeSBxdWVyeSB3cml0dGVuIGluIHRoZSBwcmV2aW91cyBzZWN0aW9uIHRvIGZpbHRlciB0aGUgbWVuIG91dCBvZiB0aGUgZGF0YXNldCB3aXRob3V0IGFsdGVyaW5nIHRoZSBkYXRhc2V0IGl0c2VsZi4KCmBgYHtzcWwgY29ubmVjdGlvbj1leGNsdWRpbmdfbWVufQpXSEVSRSBnZW5kZXIgPD4gIk0iIApgYGAKCiMjIFN1bW1pbmcgYWN0aXZpdGllcyBieSB1c2VyIGFuZCBkYXRlIHdpdGhvdXQgZGl2aWRpbmcgYnkgaW50ZW5zaXR5CkJyZWFraW5nIHRoZSBzdW1zIHVwIHllc3RlcmRheSBjcmVhdGVkIGEgcG90ZW50aWFsIGZvciBjb25mdXNpbmcgZGF0YSBhcyBlYWNoIHVzZXIgY291bGQgYmUgY291bnRlZCBpbiBlYWNoIGludGVuc2l0eSBjYXRlZ29yeSwgbWVhbmluZyBqdXN0IHN1bW1pbmcgdGhvc2UgdmFsdWVzIHdvdWxkIG5vdCBiZSBhY2N1cmF0ZSBpbiBjb3VudGluZyB1bmlxdWUgdXNlcnMgZm9yIGVhY2ggYWN0aXZpdHkuCgpgYGB7c3FsIGNvbm5lY3Rpb249c3VtbWluZ19ieV9hY3Rpdml0eX0KU0VMRUNUCiAgYWN0aXZpdHlfdHlwZSwKICBDT1VOVChESVNUSU5DVCBwYXJ0aWNpcGFudF9pZCkgQVMgdW5pcXVlX3VzZXJzCgpGUk9NIGBjb21wbGV0ZS13aWxsLTQ2ODExNS1wMi5maXRsaWZlMzYwX3N5bnRoZXRpY19oZWFsdGhfZGF0YS5maXRsaWZlYApHUk9VUCBCWQogIGFjdGl2aXR5X3R5cGUKT1JERVIgQlkKICBhY3Rpdml0eV90eXBlOwpgYGAKCiMjIyBBY3Rpdml0eSBTZXNzaW9uIENvdW50cwpgYGB7c3FsIGNvbm5lY3Rpb249YWN0aXZpdHlfc2Vzc2lvbl9jb3VudH0KU0VMRUNUCiAgYWN0aXZpdHlfdHlwZSwKICBDT1VOVChhY3Rpdml0eV90eXBlKSBBUyBhY3Rpdml0eV9zZXNzaW9uX2NvdW50CkZST00gYGNvbXBsZXRlLXdpbGwtNDY4MTE1LXAyLmZpdGxpZmUzNjBfc3ludGhldGljX2hlYWx0aF9kYXRhLmZpdGxpZmVgCkdST1VQIEJZCiAgYWN0aXZpdHlfdHlwZQpPUkRFUiBCWQogIGFjdGl2aXR5X3R5cGU7CgpgYGAKIyMjIEFjdGl2aXR5IER1cmF0aW9uIFN1bW1hcnkKYGBge3NxbCBjb25uZWN0aW9uPWFjdGl2aXR5X2R1cmF0aW9uX2luX21pbnV0ZXN9ClNFTEVDVAogIGFjdGl2aXR5X3R5cGUsCiAgU1VNKGR1cmF0aW9uX21pbnV0ZXMpIEFTIGFjdGl2aXR5X2R1cmF0aW9uX2luX21pbnV0ZXMKRlJPTSBgY29tcGxldGUtd2lsbC00NjgxMTUtcDIuZml0bGlmZTM2MF9zeW50aGV0aWNfaGVhbHRoX2RhdGEuZml0bGlmZWAKR1JPVVAgQlkKICBhY3Rpdml0eV90eXBlCk9SREVSIEJZCiAgYWN0aXZpdHlfdHlwZTsKYGBgCgojIyBEYXRhIFZpc3VhbGl6YXRpb24KVGhlIGRhdGEgd2FzIHZpc3VhbGl6ZWQgdXNpbmcgdmFyaW91cyB0YWJsZXMgaW4gVGFibGVhdSBQdWJsaWMuIFRoaXMgZGF0YXNldCB3YXMgZm91bmQgdG8gb25seSBkaXNwbGF5IHRyZW5kcyB0aGF0IHdlcmUgc3RlYWR5IGFuZCBzaG93IG5vIGdyb3d0aCBvciBkZWNyZWFzZS4gVGhpcyBtYWtlcyBzZW5zZSBhcyB0aGUgZGF0YSBpcyBzeW50aGV0aWMsIGFuZCB0aHVzIHdvdWxkbid0IGhhdmUgYW55IHN1cnByaXNpbmcgdHJlbmRzIHRvIGJlIGRpc2NvdmVyZWQuIFRoZXNlIHZpc3VhbGl6dGlvbnMgd2VyZSBub3QgdXNlZCBpbiB0aGUgZmluYWwgcmVwb3J0LgoKIyMgQ29uY2x1c2lvbgpUaGlzIGRhdGFzZXQgaXMgbm90IHVzZWZ1bCBmb3IgdGhpcyBjYXNlIHN0dWR5IGJ1dCB3YXMgYSBnb29kIGNoYW5jZSB0byBwcmFjdGljZSBjbGVhbmluZyBhbmQgYW5hbHl6aW5nIGRhdGEgdXNpbmcgdmFyaW91cyB0b29scyBzdWNoIGFzIEJpZ1F1ZXJ5LCBzcHJlYWRzaGVldHMsIGFuZCBUYWJsZWF1IFB1YmxpYy4KCgoK