- Which variables in the person table have missing values? What number
and proportion of those variables are missing?
#Check for values with NA
person_1000 %>%
summarise_all(~sum(is.na(.))) %>%
gather(parameters, missing_values) %>% #create new columns to store the missing values for each parameter
filter(missing_values > 0) %>% #only show parameters with missing values
mutate(proportion_missing = missing_values/nrow(person_1000)) #proportion calc.
NA
- Which variables in the person table have suspicious-looking values?
(Choose 3 suspicious values to list, and explain why they are not what
you expect).
#check +/- suspicious values in year_of_birth variable by identifying if there are any values that are not within the expected range of ~1900-2024
range(person_1000$year_of_birth)
#1909 - 1983
range(person_1000$month_of_birth)
#1 1
range(person_1000$day_of_birth)
#1 1
#identify if patients recruited for study were from diverse racial backgrounds
unique(person_1000$race_concept_id)
#8527; signifes White
unique(person_1000$ethnicity_concept_id)
#38003564; signifies non-Hispanic
- What is the concept ID for Congestive Heart Failure?
- What clinical concept is represented by the concept ID of 8507?
chf_observations <- concept_1000 %>%
filter(grepl("congestive.*heart failure|heart failure.*congestive", concept_name, ignore.case = TRUE))
print(chf_observations)
NA
- How many patients are there for each year included in the
dataset?
#Construct a table from person_1000 outlining the count of patients for each value under "year_of_birth"
q3a<-person_1000 %>%
count(year_of_birth)
knitr::kable(q3a, format = "markdown") #display the table in markdown format
- What are the distributions of patients by race, ethnicity, and
gender?
r_person_1000 <- person_1000 %>%
group_by(race_concept_id) %>%
summarise(count=n()) %>% #creates a new column, 'count', to store the number of patients that corresponds to each unique value of race_concept_id
mutate(proportion=count/sum(count))
print(r_person_1000)
e_person_1000 <- person_1000 %>%
group_by(ethnicity_concept_id) %>%
summarise(count=n()) %>%
mutate(proportion=count/sum(count))
print(e_person_1000)
g_person_1000 <- person_1000 %>%
group_by(gender_concept_id) %>%
summarise(count=n()) %>%
mutate(proportion=count/sum(count))
print(g_person_1000)
person_1000 %>%
count(ethnicity_concept_id) %>%
ggplot(aes(x=ethnicity_concept_id,y=n)) +
geom_bar(stat="identity")+
labs(title = "Distribution of Patients by Ethnicity",
x = "Ethnicity",
y = "Number of Patients") +
theme_bw()
- What is the distribution of patients by year of birth and month of
birth?
yob_person_1000 <- person_1000 %>%
group_by(year_of_birth) %>%
summarise(count=n()) %>%
mutate(percent=((count/sum(count)*100)))
print(yob_person_1000)
#Verify wrangle was correct by ensuring the sum of the percentages is 100
yob_check <-c(yob_person_1000$percent)
sum(yob_check)
knitr::kable(yob_person_1000, format = "markdown")
#Plot the distribution of patients by year of birth
ggplot(yob_person_1000, aes(x = factor(year_of_birth), y = count)) +
geom_bar(stat = "identity") +
coord_flip() + #allows for horizontal bar graph
geom_text(aes(label = count), hjust = -0.1,size=2.5) +
labs(title = "Distribution of Patients by Year of Birth",
x = "Year of Birth",
y = "Number of Patients") +
theme_minimal() +
scale_y_continuous(breaks = seq(0,70,by=10))
mob_person_1000 <- person_1000 %>%
group_by(month_of_birth) %>%
summarise(count=n()) %>%
mutate(percent=((count/sum(count)*100)))
print(mob_person_1000)
mob_check <-c(mob_person_1000$percent)
sum(mob_check)
- What is the distribution of patients in different states? Which
states have the most patients? And the least?
state_location_1000 <- location_1000 %>%
group_by(state) %>%
summarise(count=n()) %>%
mutate(percent=((count/sum(count)*100))) %>%
arrange(desc(count))
print(state_location_1000)
#Plot the distribution of patients by state
ggplot(state_location_1000, aes(x = reorder(state, count), y = count)) +
geom_bar(stat = "identity") +
coord_flip() +
geom_text(aes(label = count), hjust = -0.1,size=2.5) +
labs(title = "Distribution of Patients by State",
x = "State",
y = "Number of Patients") +
theme_minimal() +
theme(axis.text.y = element_text(size = 6))
e.How many of these patients have death data? Which state had the
most deaths? Are there any states that saw no deaths?
#Only a select number of patients have death data, so we will filter for those patients from the person_1000 dataset, since the person_1000 dataset contains location_id, corresponding to states.
death_states <- person_1000 %>%
filter(person_id %in% death_1000$person_id) %>%
group_by(location_id) %>%
summarise(count=n())
print(death_states)
#Join the death_states dataset with the location_1000 dataset to obtain the state names
death_states_0 <- death_states %>%
left_join(location_1000, by = c("location_id" = "location_id")) %>%
select(state, count)
print(death_states_0)
#Determine states that did not contain any deaths
dead_states <- c(death_states_0$state) #vector of states that had deaths
all_states <- c(state_location_1000$state) #vector of all states
no_death_states <- setdiff(all_states, dead_states) #states that did not have any deaths
print(no_death_states)
#Determine the year with the most deaths per death_1000
death_1000 %>%
group_by(death_DATE) %>%
summarise(count=n()) %>%
arrange(desc(count))
- What are the 5 most prevalent conditions in this dataset?
indication_df <- condition_occurrence_1000 %>%
group_by(condition_concept_id) %>% #x-digit code for the condition
summarise(count=n()) %>%
arrange(desc(count))
print(indication_df)
#Join the indication_df with concept_1000 to obtain the condition names
indication_df0 <- indication_df %>%
left_join(concept_1000, by = c("condition_concept_id" = "concept_id")) %>%
select(concept_name,count)
print(indication_df0)
- Which condition was most prevalent in 2010?
#Filter for obs. in 2010 only
condition_2010 <- condition_occurrence_1000 %>%
filter(condition_start_DATE >= "2010-01-01" & condition_start_DATE <= "2010-12-31") %>%
group_by(condition_concept_id) %>%
summarise(count=n()) %>%
arrange(desc(count))
#Join the condition_2010 with concept_1000 to obtain the condition names
condition_2010x <- condition_2010 %>%
left_join(concept_1000, by = c("condition_concept_id" = "concept_id")) %>%
select(concept_name,count)
print(condition_2010x)
- What was the most prevalent condition in CA (looking across all
years)?
#Filter for patients from location_1000 to obtain location_id's specific for California
dfca1 <- location_1000 %>%
filter(state == "CA") %>%
select(location_id,state) %>%
distinct()
ca_id <- dfca1$location_id #Out of >3k location_id's, sixty represent california
#Identify California-only pt. by searching for location_id's present from ca_id in person_1000
dfca2 <- person_1000 %>%
filter(location_id %in% ca_id) %>% #California-only pt. info
distinct()
ca_ptinfo <- dfca2$person_id #person-id's for patients in California;86
#Filter for the patient_ID's from condition_occurrence_1000
dfca3 <- condition_occurrence_1000 %>%
inner_join(dfca2, by = "person_id") %>%
select(condition_concept_id,person_id)
dfca4 <- dfca3 %>%
group_by(condition_concept_id) %>%
summarise(count=n()) %>%
arrange(desc(count))
#Join the dfca4 with concept_1000 to obtain the condition names
dfca5 <- dfca4 %>%
left_join(concept_1000, by = c("condition_concept_id" = "concept_id")) %>%
select(concept_name,count)
- Which state had the highest incidence of Congestive Heart Failure
across all years?
#Concept ID for CHF is 319835
#Merge the location_1000 dataset with the person_1000 dataset to obtain the State for each person_id
person_location <- person_1000 %>%
left_join(location_1000, by = c("location_id" = "location_id")) %>%
select(person_id,state)
#Merge person_location with condition_occurrence_1000 dataset but filtering when condition_concept_id == 319835
chf_states <- condition_occurrence_1000 %>%
filter(condition_concept_id == 319835) %>%
inner_join(person_location, by = "person_id") %>%
group_by(state) %>%
summarise(count=n()) %>%
arrange(desc(count))
- What are the 5 most commonly used drugs?
drug_exposure_1000 %>%
group_by(drug_concept_id) %>%
summarise(count=n()) %>%
arrange(desc(count)) %>%
left_join(concept_1000, by = c("drug_concept_id" = "concept_id")) %>%
select(concept_name,count) %>%
head(5)
- What is the average number of drugs per person?
#Group the drug_exposure_1000 dataset by person_id and count the number of drugs each person has taken
drug_per_person <- drug_exposure_1000 %>%
group_by(person_id) %>%
summarise(count=n())
#Calculate the average number of drugs per person
avg_drugs_per_person <- mean(drug_per_person$count)
- What is the average duration that the Simvastatin 40 mg oral tablet
is taken for?
#Filter the drug_exposure_1000 dataset for the drug_concept_id for Simvastatin 40 mg oral tablet, where drug_concept_ID == 1539407 | 1539406
simvastatin <- drug_exposure_1000 %>%
filter(drug_concept_id == 1539407 | drug_concept_id == 1539406) %>%
select(drug_exposure_id, person_id, drug_concept_id, drug_exposure_start_DATE, drug_exposure_end_DATE) %>%
mutate(duration = as.numeric(difftime(drug_exposure_end_DATE, drug_exposure_start_DATE, units = "days")))
mean(simvastatin$duration, na.rm = TRUE)
LS0tCnRpdGxlOiAiUTEuUTIiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQojSW1wb3J0IHBhY2thZ2VzCmxpYnJhcnkodGlkeXZlcnNlKQojSW1wb3J0IGRhdGFzZXQgZnJvbSB3ZApwZXJzb25fMTAwMCA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvU3RhbmZvcmRfQmlvaW5mb3JtYXRpY3MvQ29kaW5nX2NoYWxsZW5nZV9kYXRhc2V0L3BlcnNvbl8xMDAwLmNzdiIpCgpgYGAKCmEuIFdoaWNoIHZhcmlhYmxlcyBpbiB0aGUgcGVyc29uIHRhYmxlIGhhdmUgbWlzc2luZyB2YWx1ZXM/IFdoYXQgbnVtYmVyIGFuZCBwcm9wb3J0aW9uIG9mIHRob3NlIHZhcmlhYmxlcyBhcmUgbWlzc2luZz8KYGBge3IgcGVyc29uXzEwMDAgd3JhbmdsZX0KI0NoZWNrIGZvciB2YWx1ZXMgd2l0aCBOQQpwZXJzb25fMTAwMCAlPiUKICBzdW1tYXJpc2VfYWxsKH5zdW0oaXMubmEoLikpKSAlPiUKICAgICAgICBnYXRoZXIocGFyYW1ldGVycywgbWlzc2luZ192YWx1ZXMpICU+JSAjY3JlYXRlIG5ldyBjb2x1bW5zIHRvIHN0b3JlIHRoZSBtaXNzaW5nIHZhbHVlcyBmb3IgZWFjaCBwYXJhbWV0ZXIKICAgICAgICBmaWx0ZXIobWlzc2luZ192YWx1ZXMgPiAwKSAlPiUgI29ubHkgc2hvdyBwYXJhbWV0ZXJzIHdpdGggbWlzc2luZyB2YWx1ZXMKICAgICAgICBtdXRhdGUocHJvcG9ydGlvbl9taXNzaW5nID0gbWlzc2luZ192YWx1ZXMvbnJvdyhwZXJzb25fMTAwMCkpICNwcm9wb3J0aW9uIGNhbGMuIAoKYGBgCmIuIFdoaWNoIHZhcmlhYmxlcyBpbiB0aGUgcGVyc29uIHRhYmxlIGhhdmUgc3VzcGljaW91cy1sb29raW5nIHZhbHVlcz8gKENob29zZSAzIHN1c3BpY2lvdXMgdmFsdWVzIHRvIGxpc3QsIGFuZCBleHBsYWluIHdoeSB0aGV5IGFyZSBub3Qgd2hhdCB5b3UgZXhwZWN0KS4KYGBge3IgdW5pcXVlX3ZhbHVlc30KI2NoZWNrICsvLSBzdXNwaWNpb3VzIHZhbHVlcyBpbiB5ZWFyX29mX2JpcnRoIHZhcmlhYmxlIGJ5IGlkZW50aWZ5aW5nIGlmIHRoZXJlIGFyZSBhbnkgdmFsdWVzIHRoYXQgYXJlIG5vdCB3aXRoaW4gdGhlIGV4cGVjdGVkIHJhbmdlIG9mIH4xOTAwLTIwMjQKcmFuZ2UocGVyc29uXzEwMDAkeWVhcl9vZl9iaXJ0aCkgCiMxOTA5IC0gMTk4MwpyYW5nZShwZXJzb25fMTAwMCRtb250aF9vZl9iaXJ0aCkKIzEgMSAKcmFuZ2UocGVyc29uXzEwMDAkZGF5X29mX2JpcnRoKQojMSAxCiNpZGVudGlmeSBpZiBwYXRpZW50cyByZWNydWl0ZWQgZm9yIHN0dWR5IHdlcmUgZnJvbSBkaXZlcnNlIHJhY2lhbCBiYWNrZ3JvdW5kcwp1bmlxdWUocGVyc29uXzEwMDAkcmFjZV9jb25jZXB0X2lkKQojODUyNzsgc2lnbmlmZXMgV2hpdGUKdW5pcXVlKHBlcnNvbl8xMDAwJGV0aG5pY2l0eV9jb25jZXB0X2lkKQojMzgwMDM1NjQ7IHNpZ25pZmllcyBub24tSGlzcGFuaWMKYGBgCgphLiBXaGF0IGlzIHRoZSBjb25jZXB0IElEIGZvciBDb25nZXN0aXZlIEhlYXJ0IEZhaWx1cmU/CmIuIFdoYXQgY2xpbmljYWwgY29uY2VwdCBpcyByZXByZXNlbnRlZCBieSB0aGUgY29uY2VwdCBJRCBvZiA4NTA3PwpgYGB7ciBDSEZ9CmNoZl9vYnNlcnZhdGlvbnMgPC0gY29uY2VwdF8xMDAwICU+JQogIGZpbHRlcihncmVwbCgiY29uZ2VzdGl2ZS4qaGVhcnQgZmFpbHVyZXxoZWFydCBmYWlsdXJlLipjb25nZXN0aXZlIiwgY29uY2VwdF9uYW1lLCBpZ25vcmUuY2FzZSA9IFRSVUUpKQpwcmludChjaGZfb2JzZXJ2YXRpb25zKQoKYGBgCgphLiBIb3cgbWFueSBwYXRpZW50cyBhcmUgdGhlcmUgZm9yIGVhY2ggeWVhciBpbmNsdWRlZCBpbiB0aGUgZGF0YXNldD8KYGBge3J9CiNDb25zdHJ1Y3QgYSB0YWJsZSBmcm9tIHBlcnNvbl8xMDAwIG91dGxpbmluZyB0aGUgY291bnQgb2YgcGF0aWVudHMgZm9yIGVhY2ggdmFsdWUgdW5kZXIgInllYXJfb2ZfYmlydGgiCnEzYTwtcGVyc29uXzEwMDAgJT4lCiAgY291bnQoeWVhcl9vZl9iaXJ0aCkKa25pdHI6OmthYmxlKHEzYSwgZm9ybWF0ID0gIm1hcmtkb3duIikgI2Rpc3BsYXkgdGhlIHRhYmxlIGluIG1hcmtkb3duIGZvcm1hdAoKYGBgCgpiLiBXaGF0IGFyZSB0aGUgZGlzdHJpYnV0aW9ucyBvZiBwYXRpZW50cyBieSByYWNlLCBldGhuaWNpdHksIGFuZCBnZW5kZXI/CmBgYHtyfQpyX3BlcnNvbl8xMDAwIDwtIHBlcnNvbl8xMDAwICU+JSAKICAgICAgICBncm91cF9ieShyYWNlX2NvbmNlcHRfaWQpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JSAjY3JlYXRlcyBhIG5ldyBjb2x1bW4sICdjb3VudCcsIHRvIHN0b3JlIHRoZSBudW1iZXIgb2YgcGF0aWVudHMgdGhhdCBjb3JyZXNwb25kcyB0byBlYWNoIHVuaXF1ZSB2YWx1ZSBvZiByYWNlX2NvbmNlcHRfaWQKICAgICAgICBtdXRhdGUocHJvcG9ydGlvbj1jb3VudC9zdW0oY291bnQpKQpwcmludChyX3BlcnNvbl8xMDAwKQoKZV9wZXJzb25fMTAwMCA8LSBwZXJzb25fMTAwMCAlPiUKICAgICAgICBncm91cF9ieShldGhuaWNpdHlfY29uY2VwdF9pZCkgJT4lCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkgJT4lCiAgICAgICAgbXV0YXRlKHByb3BvcnRpb249Y291bnQvc3VtKGNvdW50KSkKcHJpbnQoZV9wZXJzb25fMTAwMCkKCmdfcGVyc29uXzEwMDAgPC0gcGVyc29uXzEwMDAgJT4lCiAgICAgICAgZ3JvdXBfYnkoZ2VuZGVyX2NvbmNlcHRfaWQpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIG11dGF0ZShwcm9wb3J0aW9uPWNvdW50L3N1bShjb3VudCkpCnByaW50KGdfcGVyc29uXzEwMDApCgpwZXJzb25fMTAwMCAlPiUgCiAgICAgICAgY291bnQoZXRobmljaXR5X2NvbmNlcHRfaWQpICU+JQogICAgICAgIGdncGxvdChhZXMoeD1ldGhuaWNpdHlfY29uY2VwdF9pZCx5PW4pKSArCiAgICAgICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsKICAgICAgICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBQYXRpZW50cyBieSBFdGhuaWNpdHkiLAogICAgICAgICAgICAgeCA9ICJFdGhuaWNpdHkiLAogICAgICAgICAgICAgeSA9ICJOdW1iZXIgb2YgUGF0aWVudHMiKSArCiAgICAgICAgdGhlbWVfYncoKQpgYGAKCmMuIFdoYXQgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwYXRpZW50cyBieSB5ZWFyIG9mIGJpcnRoIGFuZCBtb250aCBvZiBiaXJ0aD8KYGBge3J9CnlvYl9wZXJzb25fMTAwMCA8LSBwZXJzb25fMTAwMCAlPiUgCiAgICAgICAgZ3JvdXBfYnkoeWVhcl9vZl9iaXJ0aCkgJT4lCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkgJT4lCiAgICAgICAgbXV0YXRlKHBlcmNlbnQ9KChjb3VudC9zdW0oY291bnQpKjEwMCkpKQpwcmludCh5b2JfcGVyc29uXzEwMDApCiNWZXJpZnkgd3JhbmdsZSB3YXMgY29ycmVjdCBieSBlbnN1cmluZyB0aGUgc3VtIG9mIHRoZSBwZXJjZW50YWdlcyBpcyAxMDAKeW9iX2NoZWNrIDwtYyh5b2JfcGVyc29uXzEwMDAkcGVyY2VudCkKc3VtKHlvYl9jaGVjaykKCmtuaXRyOjprYWJsZSh5b2JfcGVyc29uXzEwMDAsIGZvcm1hdCA9ICJtYXJrZG93biIpCgojUGxvdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHBhdGllbnRzIGJ5IHllYXIgb2YgYmlydGgKZ2dwbG90KHlvYl9wZXJzb25fMTAwMCwgYWVzKHggPSBmYWN0b3IoeWVhcl9vZl9iaXJ0aCksIHkgPSBjb3VudCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGNvb3JkX2ZsaXAoKSArICNhbGxvd3MgZm9yIGhvcml6b250YWwgYmFyIGdyYXBoCiAgICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNvdW50KSwgaGp1c3QgPSAtMC4xLHNpemU9Mi41KSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUGF0aWVudHMgYnkgWWVhciBvZiBCaXJ0aCIsCiAgICAgICB4ID0gIlllYXIgb2YgQmlydGgiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgUGF0aWVudHMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsNzAsYnk9MTApKQoKbW9iX3BlcnNvbl8xMDAwIDwtIHBlcnNvbl8xMDAwICU+JQogICAgICAgIGdyb3VwX2J5KG1vbnRoX29mX2JpcnRoKSAlPiUKICAgICAgICBzdW1tYXJpc2UoY291bnQ9bigpKSAlPiUKICAgICAgICBtdXRhdGUocGVyY2VudD0oKGNvdW50L3N1bShjb3VudCkqMTAwKSkpCnByaW50KG1vYl9wZXJzb25fMTAwMCkKCm1vYl9jaGVjayA8LWMobW9iX3BlcnNvbl8xMDAwJHBlcmNlbnQpCnN1bShtb2JfY2hlY2spCgpgYGAKCmQuIFdoYXQgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwYXRpZW50cyBpbiBkaWZmZXJlbnQgc3RhdGVzPyBXaGljaCBzdGF0ZXMgaGF2ZSB0aGUgbW9zdCBwYXRpZW50cz8gQW5kIHRoZSBsZWFzdD8KYGBge3IgbG9jYXRpb25fMTAwMCB3cmFuZ2xlfQpzdGF0ZV9sb2NhdGlvbl8xMDAwIDwtIGxvY2F0aW9uXzEwMDAgJT4lIAogICAgICAgIGdyb3VwX2J5KHN0YXRlKSAlPiUKICAgICAgICBzdW1tYXJpc2UoY291bnQ9bigpKSAlPiUKICAgICAgICBtdXRhdGUocGVyY2VudD0oKGNvdW50L3N1bShjb3VudCkqMTAwKSkpICU+JSAKICAgICAgICBhcnJhbmdlKGRlc2MoY291bnQpKQpwcmludChzdGF0ZV9sb2NhdGlvbl8xMDAwKQoKI1Bsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwYXRpZW50cyBieSBzdGF0ZQpnZ3Bsb3Qoc3RhdGVfbG9jYXRpb25fMTAwMCwgYWVzKHggPSByZW9yZGVyKHN0YXRlLCBjb3VudCksIHkgPSBjb3VudCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGNvb3JkX2ZsaXAoKSArCiAgICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNvdW50KSwgaGp1c3QgPSAtMC4xLHNpemU9Mi41KSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUGF0aWVudHMgYnkgU3RhdGUiLAogICAgICAgeCA9ICJTdGF0ZSIsCiAgICAgICB5ID0gIk51bWJlciBvZiBQYXRpZW50cyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSkKCgpgYGAKCmUuSG93IG1hbnkgb2YgdGhlc2UgcGF0aWVudHMgaGF2ZSBkZWF0aCBkYXRhPyBXaGljaCBzdGF0ZSBoYWQgdGhlIG1vc3QgZGVhdGhzPyBBcmUgdGhlcmUgYW55IHN0YXRlcyB0aGF0IHNhdyBubyBkZWF0aHM/CmBgYHtyfQojT25seSBhIHNlbGVjdCBudW1iZXIgb2YgcGF0aWVudHMgaGF2ZSBkZWF0aCBkYXRhLCBzbyB3ZSB3aWxsIGZpbHRlciBmb3IgdGhvc2UgcGF0aWVudHMgZnJvbSB0aGUgcGVyc29uXzEwMDAgZGF0YXNldCwgc2luY2UgdGhlIHBlcnNvbl8xMDAwIGRhdGFzZXQgY29udGFpbnMgbG9jYXRpb25faWQsIGNvcnJlc3BvbmRpbmcgdG8gc3RhdGVzLiAKZGVhdGhfc3RhdGVzIDwtIHBlcnNvbl8xMDAwICU+JQogICAgICAgIGZpbHRlcihwZXJzb25faWQgJWluJSBkZWF0aF8xMDAwJHBlcnNvbl9pZCkgJT4lCiAgICAgICAgZ3JvdXBfYnkobG9jYXRpb25faWQpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpCnByaW50KGRlYXRoX3N0YXRlcykKCiNKb2luIHRoZSBkZWF0aF9zdGF0ZXMgZGF0YXNldCB3aXRoIHRoZSBsb2NhdGlvbl8xMDAwIGRhdGFzZXQgdG8gb2J0YWluIHRoZSBzdGF0ZSBuYW1lcwpkZWF0aF9zdGF0ZXNfMCA8LSBkZWF0aF9zdGF0ZXMgJT4lCiAgICAgICAgbGVmdF9qb2luKGxvY2F0aW9uXzEwMDAsIGJ5ID0gYygibG9jYXRpb25faWQiID0gImxvY2F0aW9uX2lkIikpICU+JQogICAgICAgIHNlbGVjdChzdGF0ZSwgY291bnQpCnByaW50KGRlYXRoX3N0YXRlc18wKQoKI0RldGVybWluZSBzdGF0ZXMgdGhhdCBkaWQgbm90IGNvbnRhaW4gYW55IGRlYXRocwpkZWFkX3N0YXRlcyA8LSBjKGRlYXRoX3N0YXRlc18wJHN0YXRlKSAjdmVjdG9yIG9mIHN0YXRlcyB0aGF0IGhhZCBkZWF0aHMKYWxsX3N0YXRlcyA8LSBjKHN0YXRlX2xvY2F0aW9uXzEwMDAkc3RhdGUpICN2ZWN0b3Igb2YgYWxsIHN0YXRlcwpub19kZWF0aF9zdGF0ZXMgPC0gc2V0ZGlmZihhbGxfc3RhdGVzLCBkZWFkX3N0YXRlcykgI3N0YXRlcyB0aGF0IGRpZCBub3QgaGF2ZSBhbnkgZGVhdGhzCnByaW50KG5vX2RlYXRoX3N0YXRlcykKCiNEZXRlcm1pbmUgdGhlIHllYXIgd2l0aCB0aGUgbW9zdCBkZWF0aHMgcGVyIGRlYXRoXzEwMDAKZGVhdGhfMTAwMCAlPiUKICAgICAgICBncm91cF9ieShkZWF0aF9EQVRFKSAlPiUKICAgICAgICBzdW1tYXJpc2UoY291bnQ9bigpKSAlPiUKICAgICAgICBhcnJhbmdlKGRlc2MoY291bnQpKQoKYGBgCgphLiBXaGF0IGFyZSB0aGUgNSBtb3N0IHByZXZhbGVudCBjb25kaXRpb25zIGluIHRoaXMgZGF0YXNldD8KYGBge3IgY29uZGl0aW9uX29jY3VycmVuY2VfMTAwMCB3cmFuZ2xlfQppbmRpY2F0aW9uX2RmIDwtIGNvbmRpdGlvbl9vY2N1cnJlbmNlXzEwMDAgJT4lCiAgICAgICAgZ3JvdXBfYnkoY29uZGl0aW9uX2NvbmNlcHRfaWQpICU+JSAjeC1kaWdpdCBjb2RlIGZvciB0aGUgY29uZGl0aW9uCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkgJT4lCiAgICAgICAgYXJyYW5nZShkZXNjKGNvdW50KSkKCnByaW50KGluZGljYXRpb25fZGYpCiNKb2luIHRoZSBpbmRpY2F0aW9uX2RmIHdpdGggY29uY2VwdF8xMDAwIHRvIG9idGFpbiB0aGUgY29uZGl0aW9uIG5hbWVzCmluZGljYXRpb25fZGYwIDwtIGluZGljYXRpb25fZGYgJT4lCiAgICAgICAgbGVmdF9qb2luKGNvbmNlcHRfMTAwMCwgYnkgPSBjKCJjb25kaXRpb25fY29uY2VwdF9pZCIgPSAiY29uY2VwdF9pZCIpKSAlPiUgCiAgICAgICAgc2VsZWN0KGNvbmNlcHRfbmFtZSxjb3VudCkKcHJpbnQoaW5kaWNhdGlvbl9kZjApCgpgYGAKYi4gV2hpY2ggY29uZGl0aW9uIHdhcyBtb3N0IHByZXZhbGVudCBpbiAyMDEwPwpgYGB7cn0KI0ZpbHRlciBmb3Igb2JzLiBpbiAyMDEwIG9ubHkgCmNvbmRpdGlvbl8yMDEwIDwtIGNvbmRpdGlvbl9vY2N1cnJlbmNlXzEwMDAgJT4lCiAgICAgICAgZmlsdGVyKGNvbmRpdGlvbl9zdGFydF9EQVRFID49ICIyMDEwLTAxLTAxIiAmIGNvbmRpdGlvbl9zdGFydF9EQVRFIDw9ICIyMDEwLTEyLTMxIikgJT4lCiAgICAgICAgZ3JvdXBfYnkoY29uZGl0aW9uX2NvbmNlcHRfaWQpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIGFycmFuZ2UoZGVzYyhjb3VudCkpCiNKb2luIHRoZSBjb25kaXRpb25fMjAxMCB3aXRoIGNvbmNlcHRfMTAwMCB0byBvYnRhaW4gdGhlIGNvbmRpdGlvbiBuYW1lcwpjb25kaXRpb25fMjAxMHggPC0gY29uZGl0aW9uXzIwMTAgJT4lCiAgICAgICAgbGVmdF9qb2luKGNvbmNlcHRfMTAwMCwgYnkgPSBjKCJjb25kaXRpb25fY29uY2VwdF9pZCIgPSAiY29uY2VwdF9pZCIpKSAlPiUgCiAgICAgICAgc2VsZWN0KGNvbmNlcHRfbmFtZSxjb3VudCkKcHJpbnQoY29uZGl0aW9uXzIwMTB4KQpgYGAKYy4gV2hhdCB3YXMgdGhlIG1vc3QgcHJldmFsZW50IGNvbmRpdGlvbiBpbiBDQSAobG9va2luZyBhY3Jvc3MgYWxsIHllYXJzKT8KYGBge3J9CiNGaWx0ZXIgZm9yIHBhdGllbnRzIGZyb20gbG9jYXRpb25fMTAwMCB0byBvYnRhaW4gbG9jYXRpb25faWQncyBzcGVjaWZpYyBmb3IgQ2FsaWZvcm5pYQpkZmNhMSA8LSBsb2NhdGlvbl8xMDAwICU+JQogICAgICAgIGZpbHRlcihzdGF0ZSA9PSAiQ0EiKSAlPiUKICAgICAgICBzZWxlY3QobG9jYXRpb25faWQsc3RhdGUpICU+JSAKICAgICAgICBkaXN0aW5jdCgpCmNhX2lkIDwtIGRmY2ExJGxvY2F0aW9uX2lkICNPdXQgb2YgPjNrIGxvY2F0aW9uX2lkJ3MsIHNpeHR5IHJlcHJlc2VudCBjYWxpZm9ybmlhIAojSWRlbnRpZnkgQ2FsaWZvcm5pYS1vbmx5IHB0LiBieSBzZWFyY2hpbmcgZm9yIGxvY2F0aW9uX2lkJ3MgcHJlc2VudCBmcm9tIGNhX2lkIGluIHBlcnNvbl8xMDAwCmRmY2EyIDwtIHBlcnNvbl8xMDAwICU+JSAKICAgICAgICBmaWx0ZXIobG9jYXRpb25faWQgJWluJSBjYV9pZCkgJT4lICNDYWxpZm9ybmlhLW9ubHkgcHQuIGluZm8KICAgICAgICBkaXN0aW5jdCgpCgpjYV9wdGluZm8gPC0gZGZjYTIkcGVyc29uX2lkICNwZXJzb24taWQncyBmb3IgcGF0aWVudHMgaW4gQ2FsaWZvcm5pYTs4NgoKI0ZpbHRlciBmb3IgdGhlIHBhdGllbnRfSUQncyBmcm9tIGNvbmRpdGlvbl9vY2N1cnJlbmNlXzEwMDAKZGZjYTMgPC0gY29uZGl0aW9uX29jY3VycmVuY2VfMTAwMCAlPiUKICAgICAgICBpbm5lcl9qb2luKGRmY2EyLCBieSA9ICJwZXJzb25faWQiKSAlPiUgCiAgICAgICAgc2VsZWN0KGNvbmRpdGlvbl9jb25jZXB0X2lkLHBlcnNvbl9pZCkKZGZjYTQgPC0gZGZjYTMgJT4lCiAgICAgICAgZ3JvdXBfYnkoY29uZGl0aW9uX2NvbmNlcHRfaWQpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIGFycmFuZ2UoZGVzYyhjb3VudCkpCiNKb2luIHRoZSBkZmNhNCB3aXRoIGNvbmNlcHRfMTAwMCB0byBvYnRhaW4gdGhlIGNvbmRpdGlvbiBuYW1lcwpkZmNhNSA8LSBkZmNhNCAlPiUKICAgICAgICBsZWZ0X2pvaW4oY29uY2VwdF8xMDAwLCBieSA9IGMoImNvbmRpdGlvbl9jb25jZXB0X2lkIiA9ICJjb25jZXB0X2lkIikpICU+JSAKICAgICAgICBzZWxlY3QoY29uY2VwdF9uYW1lLGNvdW50KQoKYGBgCgoKZC4gV2hpY2ggc3RhdGUgaGFkIHRoZSBoaWdoZXN0IGluY2lkZW5jZSBvZiBDb25nZXN0aXZlIEhlYXJ0IEZhaWx1cmUgYWNyb3NzIGFsbCB5ZWFycz8KYGBge3J9IAojQ29uY2VwdCBJRCBmb3IgQ0hGIGlzIDMxOTgzNSAKI01lcmdlIHRoZSBsb2NhdGlvbl8xMDAwIGRhdGFzZXQgd2l0aCB0aGUgcGVyc29uXzEwMDAgZGF0YXNldCB0byBvYnRhaW4gdGhlIFN0YXRlIGZvciBlYWNoIHBlcnNvbl9pZApwZXJzb25fbG9jYXRpb24gPC0gcGVyc29uXzEwMDAgJT4lCiAgICAgICAgbGVmdF9qb2luKGxvY2F0aW9uXzEwMDAsIGJ5ID0gYygibG9jYXRpb25faWQiID0gImxvY2F0aW9uX2lkIikpICU+JQogICAgICAgIHNlbGVjdChwZXJzb25faWQsc3RhdGUpCiNNZXJnZSBwZXJzb25fbG9jYXRpb24gd2l0aCBjb25kaXRpb25fb2NjdXJyZW5jZV8xMDAwIGRhdGFzZXQgYnV0IGZpbHRlcmluZyB3aGVuIGNvbmRpdGlvbl9jb25jZXB0X2lkID09IDMxOTgzNQpjaGZfc3RhdGVzIDwtIGNvbmRpdGlvbl9vY2N1cnJlbmNlXzEwMDAgJT4lCiAgICAgICAgZmlsdGVyKGNvbmRpdGlvbl9jb25jZXB0X2lkID09IDMxOTgzNSkgJT4lCiAgICAgICAgaW5uZXJfam9pbihwZXJzb25fbG9jYXRpb24sIGJ5ID0gInBlcnNvbl9pZCIpICU+JQogICAgICAgIGdyb3VwX2J5KHN0YXRlKSAlPiUKICAgICAgICBzdW1tYXJpc2UoY291bnQ9bigpKSAlPiUKICAgICAgICBhcnJhbmdlKGRlc2MoY291bnQpKQoKYGBgCgphLiBXaGF0IGFyZSB0aGUgNSBtb3N0IGNvbW1vbmx5IHVzZWQgZHJ1Z3M/CmBgYHtyfQpkcnVnX2V4cG9zdXJlXzEwMDAgJT4lCiAgICAgICAgZ3JvdXBfYnkoZHJ1Z19jb25jZXB0X2lkKSAlPiUKICAgICAgICBzdW1tYXJpc2UoY291bnQ9bigpKSAlPiUKICAgICAgICBhcnJhbmdlKGRlc2MoY291bnQpKSAlPiUKICAgICAgICBsZWZ0X2pvaW4oY29uY2VwdF8xMDAwLCBieSA9IGMoImRydWdfY29uY2VwdF9pZCIgPSAiY29uY2VwdF9pZCIpKSAlPiUKICAgICAgICBzZWxlY3QoY29uY2VwdF9uYW1lLGNvdW50KSAlPiUKICAgICAgICBoZWFkKDUpCgpgYGAKCmIuIFdoYXQgaXMgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGRydWdzIHBlciBwZXJzb24/CmBgYHtyfQojR3JvdXAgdGhlIGRydWdfZXhwb3N1cmVfMTAwMCBkYXRhc2V0IGJ5IHBlcnNvbl9pZCBhbmQgY291bnQgdGhlIG51bWJlciBvZiBkcnVncyBlYWNoIHBlcnNvbiBoYXMgdGFrZW4KZHJ1Z19wZXJfcGVyc29uIDwtIGRydWdfZXhwb3N1cmVfMTAwMCAlPiUKICAgICAgICBncm91cF9ieShwZXJzb25faWQpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpCiNDYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGRydWdzIHBlciBwZXJzb24KYXZnX2RydWdzX3Blcl9wZXJzb24gPC0gbWVhbihkcnVnX3Blcl9wZXJzb24kY291bnQpCmBgYAoKYy4gV2hhdCBpcyB0aGUgYXZlcmFnZSBkdXJhdGlvbiB0aGF0IHRoZSBTaW12YXN0YXRpbiA0MCBtZyBvcmFsIHRhYmxldCBpcyB0YWtlbiBmb3I/CmBgYHtyfQojRmlsdGVyIHRoZSBkcnVnX2V4cG9zdXJlXzEwMDAgZGF0YXNldCBmb3IgdGhlIGRydWdfY29uY2VwdF9pZCBmb3IgU2ltdmFzdGF0aW4gNDAgbWcgb3JhbCB0YWJsZXQsIHdoZXJlIGRydWdfY29uY2VwdF9JRCA9PSAxNTM5NDA3IHwgMTUzOTQwNgpzaW12YXN0YXRpbiA8LSBkcnVnX2V4cG9zdXJlXzEwMDAgJT4lCiAgICAgICAgZmlsdGVyKGRydWdfY29uY2VwdF9pZCA9PSAxNTM5NDA3IHwgZHJ1Z19jb25jZXB0X2lkID09IDE1Mzk0MDYpICU+JSAKICAgICAgICBzZWxlY3QoZHJ1Z19leHBvc3VyZV9pZCwgcGVyc29uX2lkLCBkcnVnX2NvbmNlcHRfaWQsIGRydWdfZXhwb3N1cmVfc3RhcnRfREFURSwgZHJ1Z19leHBvc3VyZV9lbmRfREFURSkgJT4lCiAgICAgICAgbXV0YXRlKGR1cmF0aW9uID0gYXMubnVtZXJpYyhkaWZmdGltZShkcnVnX2V4cG9zdXJlX2VuZF9EQVRFLCBkcnVnX2V4cG9zdXJlX3N0YXJ0X0RBVEUsIHVuaXRzID0gImRheXMiKSkpCm1lYW4oc2ltdmFzdGF0aW4kZHVyYXRpb24sIG5hLnJtID0gVFJVRSkKCmBgYAoK