#Import packages
library(tidyverse)

#Import dataset from wd
person_1000 <- read.csv("~/Documents/Stanford_Bioinformatics/Coding_challenge_dataset/person_1000.csv")
concept_1000 <- read.csv("~/Documents/Stanford_Bioinformatics/Coding_challenge_dataset/concept_1000.csv")
death_1000 <- read.csv("~/Documents/Stanford_Bioinformatics/Coding_challenge_dataset/death_1000.csv")
location_1000 <- read.csv("~/Documents/Stanford_Bioinformatics/Coding_challenge_dataset/location_1000.csv")
condition_occurrence_1000 <- read.csv("~/Documents/Stanford_Bioinformatics/Coding_challenge_dataset/condition_occurrence_1000.csv")
drug_exposure_1000 <- read.csv("~/Documents/Stanford_Bioinformatics/Coding_challenge_dataset/drug_exposure_1000.csv")
  1. 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
  1. 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) 
[1] 1909 1983
#1909 - 1983
range(person_1000$month_of_birth)
[1] 1 1
#1 1 
range(person_1000$day_of_birth)
[1] 1 1
#1 1
#identify if patients recruited for study were from diverse racial backgrounds
unique(person_1000$race_concept_id)
[1] 8527
#8527; signifes White
unique(person_1000$ethnicity_concept_id)
[1] 38003564
#38003564; signifies non-Hispanic
  1. What is the concept ID for Congestive Heart Failure?
  1. 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
  1. 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)
q3a
NA
  1. 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)
NA
  1. 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)

#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))

#Month of Birth
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)
  1. 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))

NA
NA
  1. 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, use person_id to join; want location_id for state name
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)
 [1] "GA" "KS" "NC" "TN" "54" "NE" "MI" "MS" "OK" "WI" "AL" "SD" "CO" "MT" "WV" "ID" "NM" "UT" "AK" "MD" "WY" "NH" "ME"
[24] "NV" "MA" "VT" "HI" "DE" "DC"
  1. Which year saw the most deaths?
df_2009death <- death_1000 %>%
        group_by(death_DATE) %>%
        summarise(count=n()) %>%
        arrange(desc(count))
print(df_2009death)
  1. 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)
indication_df0
NA
  1. 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)
condition_2010x
  1. 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)
print(dfca5)
NA
  1. 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))
print(chf_states)
  1. What are the 5 most commonly used drugs?
df_de <- 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(df_de)
NA
  1. 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())
summary(drug_per_person)
   person_id          count       
 Min.   :    35   Min.   :  1.00  
 1st Qu.: 42550   1st Qu.: 13.00  
 Median : 89129   Median : 58.00  
 Mean   : 90666   Mean   : 68.77  
 3rd Qu.:131773   3rd Qu.:105.00  
 Max.   :217190   Max.   :530.00  
#Calculate the average number of drugs per person
  1. 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)
[1] 40.91563
LS0tCnRpdGxlOiAic3RhbmZvcmQtYXNzaWdubWVudCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IgaW1wb3J0IHBhY2thZ2VzIGFuZCBkYXRhc2V0c30KI0ltcG9ydCBwYWNrYWdlcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKCiNJbXBvcnQgZGF0YXNldCBmcm9tIHdkCnBlcnNvbl8xMDAwIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9TdGFuZm9yZF9CaW9pbmZvcm1hdGljcy9Db2RpbmdfY2hhbGxlbmdlX2RhdGFzZXQvcGVyc29uXzEwMDAuY3N2IikKY29uY2VwdF8xMDAwIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9TdGFuZm9yZF9CaW9pbmZvcm1hdGljcy9Db2RpbmdfY2hhbGxlbmdlX2RhdGFzZXQvY29uY2VwdF8xMDAwLmNzdiIpCmRlYXRoXzEwMDAgPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1N0YW5mb3JkX0Jpb2luZm9ybWF0aWNzL0NvZGluZ19jaGFsbGVuZ2VfZGF0YXNldC9kZWF0aF8xMDAwLmNzdiIpCmxvY2F0aW9uXzEwMDAgPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1N0YW5mb3JkX0Jpb2luZm9ybWF0aWNzL0NvZGluZ19jaGFsbGVuZ2VfZGF0YXNldC9sb2NhdGlvbl8xMDAwLmNzdiIpCmNvbmRpdGlvbl9vY2N1cnJlbmNlXzEwMDAgPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1N0YW5mb3JkX0Jpb2luZm9ybWF0aWNzL0NvZGluZ19jaGFsbGVuZ2VfZGF0YXNldC9jb25kaXRpb25fb2NjdXJyZW5jZV8xMDAwLmNzdiIpCmRydWdfZXhwb3N1cmVfMTAwMCA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvU3RhbmZvcmRfQmlvaW5mb3JtYXRpY3MvQ29kaW5nX2NoYWxsZW5nZV9kYXRhc2V0L2RydWdfZXhwb3N1cmVfMTAwMC5jc3YiKQpgYGAKCmEuIFdoaWNoIHZhcmlhYmxlcyBpbiB0aGUgcGVyc29uIHRhYmxlIGhhdmUgbWlzc2luZyB2YWx1ZXM/IFdoYXQgbnVtYmVyIGFuZCBwcm9wb3J0aW9uIG9mIHRob3NlIHZhcmlhYmxlcyBhcmUgbWlzc2luZz8KYGBge3IgcGVyc29uXzEwMDAgd3JhbmdsZX0KI0NoZWNrIGZvciB2YWx1ZXMgd2l0aCBOQQpwZXJzb25fMTAwMCAlPiUKICBzdW1tYXJpc2VfYWxsKH5zdW0oaXMubmEoLikpKSAlPiUKICAgICAgICBnYXRoZXIocGFyYW1ldGVycywgbWlzc2luZ192YWx1ZXMpICU+JSAjY3JlYXRlIG5ldyBjb2x1bW5zIHRvIHN0b3JlIHRoZSBtaXNzaW5nIHZhbHVlcyBmb3IgZWFjaCBwYXJhbWV0ZXIKICAgICAgICBmaWx0ZXIobWlzc2luZ192YWx1ZXMgPiAwKSAlPiUgI29ubHkgc2hvdyBwYXJhbWV0ZXJzIHdpdGggbWlzc2luZyB2YWx1ZXMKICAgICAgICBtdXRhdGUocHJvcG9ydGlvbl9taXNzaW5nID0gbWlzc2luZ192YWx1ZXMvbnJvdyhwZXJzb25fMTAwMCkpICNwcm9wb3J0aW9uIGNhbGMuIAoKYGBgCmIuIFdoaWNoIHZhcmlhYmxlcyBpbiB0aGUgcGVyc29uIHRhYmxlIGhhdmUgc3VzcGljaW91cy1sb29raW5nIHZhbHVlcz8gKENob29zZSAzIHN1c3BpY2lvdXMgdmFsdWVzIHRvIGxpc3QsIGFuZCBleHBsYWluIHdoeSB0aGV5IGFyZSBub3Qgd2hhdCB5b3UgZXhwZWN0KS4KLSBUaGUgZm9sbG93aW5nIHZhcmlhYmxlcyBzaGFyZSBhIHZhbHVlIG9mIG9uZSBmb3IgYWxsIHBhdGllbnRzIHdpdGhpbiB0aGUgcGVyc29uIHRhYmxlOiDigJhtb250aF9vZl9iaXJ0aOKAmSwg4oCYZGF5X29mX2JpcnRo4oCZLiBUaGlzIGltcGxpZXMgYWxsIHBhdGllbnRzIHdlcmUgYm9ybiB0b2dldGhlciBvbiB0aGUgc2FtZSBkYXRlIC0tICB0aGUgZmlyc3Qgb2YgSmFudWFyeS4gVGhpcyBzdGF0aXN0aWNhbGx5IGltcHJvYmFibGUgZmluZGluZyBzdWdnZXN0cyBmdXJ0aGVyIHJldmlldyBvZiBkYXRhIHNvdXJjaW5nLiAKLSBUaGUgb25seSB2YWx1ZSBmb3Ig4oCYcmFjZV9jb25jZXB0X2lk4oCZIHdhcyA4NTI3LCBkZW5vdGluZyDigJhXaGl0ZeKAmSByYWNlIGZvciBwYXRpZW50cy4gQWx0aG91Z2ggdW5pZm9ybWl0eSBpbiBwYXRpZW50IGRlbW9ncmFwaGljIHN1Y2ggYXMgaGVhbHRoeSwgd2hpdGUgdm9sdW50ZWVycyBhcmUgcHJlc2VudCBpbiBwcmFjdGljZSwgdGhpcyBpcyB0eXBpY2FsbHkgb2JzZXJ2ZWQgaW4gUGhhc2UgSSB0cmlhbHMgd2l0aCBhIHNtYWxsIHNhbXBsZSBzaXplLCBuID0gMTAgLSAzMC4gV2l0aCBhIGRhdGFiYXNlIGFtYXNzaW5nIG9uZS10aG91c2FuZCBpbmRpdmlkdWFsIHBhdGllbnQgcmVjb3Jkcywgd2UgdXN1YWxseSBleHBlY3QgYSBtb3JlIGRpdmVyc2UgcG9vbC4gCmBgYHtyIHVuaXF1ZV92YWx1ZXN9CiNjaGVjayArLy0gc3VzcGljaW91cyB2YWx1ZXMgaW4geWVhcl9vZl9iaXJ0aCB2YXJpYWJsZSBieSBpZGVudGlmeWluZyBpZiB0aGVyZSBhcmUgYW55IHZhbHVlcyB0aGF0IGFyZSBub3Qgd2l0aGluIHRoZSBleHBlY3RlZCByYW5nZSBvZiB+MTkwMC0yMDI0CnJhbmdlKHBlcnNvbl8xMDAwJHllYXJfb2ZfYmlydGgpIAojMTkwOSAtIDE5ODMKcmFuZ2UocGVyc29uXzEwMDAkbW9udGhfb2ZfYmlydGgpCiMxIDEgCnJhbmdlKHBlcnNvbl8xMDAwJGRheV9vZl9iaXJ0aCkKIzEgMQojaWRlbnRpZnkgaWYgcGF0aWVudHMgcmVjcnVpdGVkIGZvciBzdHVkeSB3ZXJlIGZyb20gZGl2ZXJzZSByYWNpYWwgYmFja2dyb3VuZHMKdW5pcXVlKHBlcnNvbl8xMDAwJHJhY2VfY29uY2VwdF9pZCkKIzg1Mjc7IHNpZ25pZmVzIFdoaXRlCnVuaXF1ZShwZXJzb25fMTAwMCRldGhuaWNpdHlfY29uY2VwdF9pZCkKIzM4MDAzNTY0OyBzaWduaWZpZXMgbm9uLUhpc3BhbmljCmBgYAoKYS4gV2hhdCBpcyB0aGUgY29uY2VwdCBJRCBmb3IgQ29uZ2VzdGl2ZSBIZWFydCBGYWlsdXJlPwotIDMxOTgzNQpiLiBXaGF0IGNsaW5pY2FsIGNvbmNlcHQgaXMgcmVwcmVzZW50ZWQgYnkgdGhlIGNvbmNlcHQgSUQgb2YgODUwNz8KLSBTZXggb2YgdGhlIHBhdGllbnQgLSBtYWxlLiAKYGBge3IgQ0hGfQpjaGZfb2JzZXJ2YXRpb25zIDwtIGNvbmNlcHRfMTAwMCAlPiUKICBmaWx0ZXIoZ3JlcGwoImNvbmdlc3RpdmUuKmhlYXJ0IGZhaWx1cmV8aGVhcnQgZmFpbHVyZS4qY29uZ2VzdGl2ZSIsIGNvbmNlcHRfbmFtZSwgaWdub3JlLmNhc2UgPSBUUlVFKSkKcHJpbnQoY2hmX29ic2VydmF0aW9ucykKCmBgYAoKYS4gSG93IG1hbnkgcGF0aWVudHMgYXJlIHRoZXJlIGZvciBlYWNoIHllYXIgaW5jbHVkZWQgaW4gdGhlIGRhdGFzZXQ/CmBgYHtyfQojQ29uc3RydWN0IGEgdGFibGUgZnJvbSBwZXJzb25fMTAwMCBvdXRsaW5pbmcgdGhlIGNvdW50IG9mIHBhdGllbnRzIGZvciBlYWNoIHZhbHVlIHVuZGVyICJ5ZWFyX29mX2JpcnRoIgpxM2E8LXBlcnNvbl8xMDAwICU+JQogIGNvdW50KHllYXJfb2ZfYmlydGgpCnEzYQoKYGBgCgpiLiBXaGF0IGFyZSB0aGUgZGlzdHJpYnV0aW9ucyBvZiBwYXRpZW50cyBieSByYWNlLCBldGhuaWNpdHksIGFuZCBnZW5kZXI/CmBgYHtyfQpyX3BlcnNvbl8xMDAwIDwtIHBlcnNvbl8xMDAwICU+JSAKICAgICAgICBncm91cF9ieShyYWNlX2NvbmNlcHRfaWQpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JSAjY3JlYXRlcyBhIG5ldyBjb2x1bW4sICdjb3VudCcsIHRvIHN0b3JlIHRoZSBudW1iZXIgb2YgcGF0aWVudHMgdGhhdCBjb3JyZXNwb25kcyB0byBlYWNoIHVuaXF1ZSB2YWx1ZSBvZiByYWNlX2NvbmNlcHRfaWQKICAgICAgICBtdXRhdGUocHJvcG9ydGlvbj1jb3VudC9zdW0oY291bnQpKQpwcmludChyX3BlcnNvbl8xMDAwKQoKZV9wZXJzb25fMTAwMCA8LSBwZXJzb25fMTAwMCAlPiUKICAgICAgICBncm91cF9ieShldGhuaWNpdHlfY29uY2VwdF9pZCkgJT4lCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkgJT4lCiAgICAgICAgbXV0YXRlKHByb3BvcnRpb249Y291bnQvc3VtKGNvdW50KSkKcHJpbnQoZV9wZXJzb25fMTAwMCkKCmdfcGVyc29uXzEwMDAgPC0gcGVyc29uXzEwMDAgJT4lCiAgICAgICAgZ3JvdXBfYnkoZ2VuZGVyX2NvbmNlcHRfaWQpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIG11dGF0ZShwcm9wb3J0aW9uPWNvdW50L3N1bShjb3VudCkpCnByaW50KGdfcGVyc29uXzEwMDApCgpgYGAKCmMuIFdoYXQgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwYXRpZW50cyBieSB5ZWFyIG9mIGJpcnRoIGFuZCBtb250aCBvZiBiaXJ0aD8KYGBge3J9CnlvYl9wZXJzb25fMTAwMCA8LSBwZXJzb25fMTAwMCAlPiUgCiAgICAgICAgZ3JvdXBfYnkoeWVhcl9vZl9iaXJ0aCkgJT4lCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkgJT4lCiAgICAgICAgbXV0YXRlKHBlcmNlbnQ9KChjb3VudC9zdW0oY291bnQpKjEwMCkpKQojcHJpbnQoeW9iX3BlcnNvbl8xMDAwKQojVmVyaWZ5IHdyYW5nbGUgd2FzIGNvcnJlY3QgYnkgZW5zdXJpbmcgdGhlIHN1bSBvZiB0aGUgcGVyY2VudGFnZXMgaXMgMTAwCiN5b2JfY2hlY2sgPC1jKHlvYl9wZXJzb25fMTAwMCRwZXJjZW50KQojc3VtKHlvYl9jaGVjaykKCiNQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgcGF0aWVudHMgYnkgeWVhciBvZiBiaXJ0aApnZ3Bsb3QoeW9iX3BlcnNvbl8xMDAwLCBhZXMoeCA9IGZhY3Rvcih5ZWFyX29mX2JpcnRoKSwgeSA9IGNvdW50KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgY29vcmRfZmxpcCgpICsgI2FsbG93cyBmb3IgaG9yaXpvbnRhbCBiYXIgZ3JhcGgKICAgICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY291bnQpLCBoanVzdCA9IC0wLjEsc2l6ZT0yLjUpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBQYXRpZW50cyBieSBZZWFyIG9mIEJpcnRoIiwKICAgICAgIHggPSAiWWVhciBvZiBCaXJ0aCIsCiAgICAgICB5ID0gIk51bWJlciBvZiBQYXRpZW50cyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw3MCxieT0xMCkpCiNNb250aCBvZiBCaXJ0aAptb2JfcGVyc29uXzEwMDAgPC0gcGVyc29uXzEwMDAgJT4lCiAgICAgICAgZ3JvdXBfYnkobW9udGhfb2ZfYmlydGgpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIG11dGF0ZShwZXJjZW50PSgoY291bnQvc3VtKGNvdW50KSoxMDApKSkKcHJpbnQobW9iX3BlcnNvbl8xMDAwKQoKI21vYl9jaGVjayA8LWMobW9iX3BlcnNvbl8xMDAwJHBlcmNlbnQpCiNzdW0obW9iX2NoZWNrKQoKYGBgCgpkLiBXaGF0IGlzIHRoZSBkaXN0cmlidXRpb24gb2YgcGF0aWVudHMgaW4gZGlmZmVyZW50IHN0YXRlcz8gV2hpY2ggc3RhdGVzIGhhdmUgdGhlIG1vc3QgcGF0aWVudHM/IEFuZCB0aGUgbGVhc3Q/Ci0gVGV4YXMgaGFzIHRoZSBoaWdoZXN0IG51bWJlciBvZiBwdC4gKG49MjQzKSBhbmQgV2FzaGluZ3RvbiBELkMgaGFzIHRoZSBsb3dlc3QgbnVtYmVyIG9mIHB0LiAobj0xKQpgYGB7ciBsb2NhdGlvbl8xMDAwIHdyYW5nbGV9CnN0YXRlX2xvY2F0aW9uXzEwMDAgPC0gbG9jYXRpb25fMTAwMCAlPiUgCiAgICAgICAgZ3JvdXBfYnkoc3RhdGUpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIG11dGF0ZShwZXJjZW50PSgoY291bnQvc3VtKGNvdW50KSoxMDApKSkgJT4lIAogICAgICAgIGFycmFuZ2UoZGVzYyhjb3VudCkpCnByaW50KHN0YXRlX2xvY2F0aW9uXzEwMDApCgojUGxvdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHBhdGllbnRzIGJ5IHN0YXRlCmdncGxvdChzdGF0ZV9sb2NhdGlvbl8xMDAwLCBhZXMoeCA9IHJlb3JkZXIoc3RhdGUsIGNvdW50KSwgeSA9IGNvdW50KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgY29vcmRfZmxpcCgpICsKICAgICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY291bnQpLCBoanVzdCA9IC0wLjEsc2l6ZT0yLjUpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBQYXRpZW50cyBieSBTdGF0ZSIsCiAgICAgICB4ID0gIlN0YXRlIiwKICAgICAgIHkgPSAiTnVtYmVyIG9mIFBhdGllbnRzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpKQoKCmBgYAoKZS4gSG93IG1hbnkgb2YgdGhlc2UgcGF0aWVudHMgaGF2ZSBkZWF0aCBkYXRhPyBXaGljaCBzdGF0ZSBoYWQgdGhlIG1vc3QgZGVhdGhzPyBBcmUgdGhlcmUgYW55IHN0YXRlcyB0aGF0IHNhdyBubyBkZWF0aHM/Ci0gVGhlcmUgYXJlIHRoaXJ0eS1maXZlIHBhdGllbnRzIGZvciB3aGljaCBkZWF0aCBkYXRhIGlzIGF2YWlsYWJsZSwgcGVyIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgaW4gZGVhdGhfMTAwMC5jc3YgCi0gV2l0aGluIHRoaXMgc3Vic2V0LCBlYWNoIHBhdGllbnQgcGFzc2VkIGF3YXkgaW4gYSBkaWZmZXJlbnQgbG9jYXRpb247IGFsbCBzdGF0ZXMgcHJvdmlkZWQgYmVsb3cgY29udGFpbiBvbmx5IG9uZSByZWNvcmQgb2YgcGF0aWVudCBkZWF0aDogIk5ZIiAiUkkiICJOWSIgIlRYIiAiQ0EiICJBWiIgIk9SIiAiSUEiICJDVCIgIkNUIiAiRkwiICJWQSIgIk5KIiAiQ0EiICJBUiIgIkZMIiAiTU8iICJPSCIgIk5EIiAiTkoiICJGTCIgIkZMIiAiVkEiICJMQSIgIklBIiAiUEEiICJTQyIgIlBBIiAiVkEiICJJTCIgIktZIiAiTlkiICJJTiIgIldBIiAiTU4iCi0gVGhlIGZvbGxvd2luZyBzdGF0ZXMgZGlkIG5vdCBjb250YWluIGFueSBkZWF0aHM6ICJHQSIgIktTIiAiTkMiICJUTiIgIjU0IiAiTkUiICJNSSIgIk1TIiAiT0siICJXSSIgIkFMIiAiU0QiICJDTyIgIk1UIiAiV1YiICJJRCIgIk5NIiAiVVQiICJBSyIgIk1EIiAiV1kiICJOSCIgIk1FIiAiTlYiICJNQSIgIlZUIiAiSEkiICJERSIgIkRDIgpgYGB7cn0KI09ubHkgYSBzZWxlY3QgbnVtYmVyIG9mIHBhdGllbnRzIGhhdmUgZGVhdGggZGF0YSwgdXNlIHBlcnNvbl9pZCB0byBqb2luOyB3YW50IGxvY2F0aW9uX2lkIGZvciBzdGF0ZSBuYW1lCmRlYXRoX3N0YXRlcyA8LSBwZXJzb25fMTAwMCAlPiUKICAgICAgICBmaWx0ZXIocGVyc29uX2lkICVpbiUgZGVhdGhfMTAwMCRwZXJzb25faWQpICU+JQogICAgICAgIGdyb3VwX2J5KGxvY2F0aW9uX2lkKSAlPiUKICAgICAgICBzdW1tYXJpc2UoY291bnQ9bigpKQojcHJpbnQoZGVhdGhfc3RhdGVzKQoKI0pvaW4gdGhlIGRlYXRoX3N0YXRlcyBkYXRhc2V0IHdpdGggdGhlIGxvY2F0aW9uXzEwMDAgZGF0YXNldCB0byBvYnRhaW4gdGhlIHN0YXRlIG5hbWVzCmRlYXRoX3N0YXRlc18wIDwtIGRlYXRoX3N0YXRlcyAlPiUKICAgICAgICBsZWZ0X2pvaW4obG9jYXRpb25fMTAwMCwgYnkgPSBjKCJsb2NhdGlvbl9pZCIgPSAibG9jYXRpb25faWQiKSkgJT4lCiAgICAgICAgc2VsZWN0KHN0YXRlLCBjb3VudCkKcHJpbnQoZGVhdGhfc3RhdGVzXzApCgojRGV0ZXJtaW5lIHN0YXRlcyB0aGF0IGRpZCBub3QgY29udGFpbiBhbnkgZGVhdGhzCmRlYWRfc3RhdGVzIDwtIGMoZGVhdGhfc3RhdGVzXzAkc3RhdGUpICN2ZWN0b3Igb2Ygc3RhdGVzIHRoYXQgaGFkIGRlYXRocwphbGxfc3RhdGVzIDwtIGMoc3RhdGVfbG9jYXRpb25fMTAwMCRzdGF0ZSkgI3ZlY3RvciBvZiBhbGwgc3RhdGVzCm5vX2RlYXRoX3N0YXRlcyA8LSBzZXRkaWZmKGFsbF9zdGF0ZXMsIGRlYWRfc3RhdGVzKSAjc3RhdGVzIHRoYXQgZGlkIG5vdCBoYXZlIGFueSBkZWF0aHMKcHJpbnQobm9fZGVhdGhfc3RhdGVzKQoKYGBgCmYuIFdoaWNoIHllYXIgc2F3IHRoZSBtb3N0IGRlYXRocz8gCi0gMjAwOSBvYnNlcnZlZCB0aGUgbW9zdCBkZWF0aHMKYGBge3J9CmRmXzIwMDlkZWF0aCA8LSBkZWF0aF8xMDAwICU+JQogICAgICAgIGdyb3VwX2J5KGRlYXRoX0RBVEUpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIGFycmFuZ2UoZGVzYyhjb3VudCkpCnByaW50KGRmXzIwMDlkZWF0aCkKYGBgCgoKYS4gV2hhdCBhcmUgdGhlIDUgbW9zdCBwcmV2YWxlbnQgY29uZGl0aW9ucyBpbiB0aGlzIGRhdGFzZXQ/Ci0gVDJETSwgYWZpYiwgY2hlc3QgcGFpbiwgYW5lbWlhLCBwdXJlIGh5cGVyY2hvbGVzdGVyb2xlbWlhCmBgYHtyIGNvbmRpdGlvbl9vY2N1cnJlbmNlXzEwMDAgd3JhbmdsZX0KaW5kaWNhdGlvbl9kZiA8LSBjb25kaXRpb25fb2NjdXJyZW5jZV8xMDAwICU+JQogICAgICAgIGdyb3VwX2J5KGNvbmRpdGlvbl9jb25jZXB0X2lkKSAlPiUgI3gtZGlnaXQgY29kZSBmb3IgdGhlIGNvbmRpdGlvbgogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIGFycmFuZ2UoZGVzYyhjb3VudCkpCiNwcmludChpbmRpY2F0aW9uX2RmKQoKI0pvaW4gdGhlIGluZGljYXRpb25fZGYgd2l0aCBjb25jZXB0XzEwMDAgdG8gb2J0YWluIHRoZSBjb25kaXRpb24gbmFtZXMKaW5kaWNhdGlvbl9kZjAgPC0gaW5kaWNhdGlvbl9kZiAlPiUKICAgICAgICBsZWZ0X2pvaW4oY29uY2VwdF8xMDAwLCBieSA9IGMoImNvbmRpdGlvbl9jb25jZXB0X2lkIiA9ICJjb25jZXB0X2lkIikpICU+JSAKICAgICAgICBzZWxlY3QoY29uY2VwdF9uYW1lLGNvdW50KQppbmRpY2F0aW9uX2RmMAoKYGBgCmIuIFdoaWNoIGNvbmRpdGlvbiB3YXMgbW9zdCBwcmV2YWxlbnQgaW4gMjAxMD8KLSBUMkRNCmBgYHtyfQojRmlsdGVyIGZvciBvYnMuIGluIDIwMTAgb25seSAKY29uZGl0aW9uXzIwMTAgPC0gY29uZGl0aW9uX29jY3VycmVuY2VfMTAwMCAlPiUKICAgICAgICBmaWx0ZXIoY29uZGl0aW9uX3N0YXJ0X0RBVEUgPj0gIjIwMTAtMDEtMDEiICYgY29uZGl0aW9uX3N0YXJ0X0RBVEUgPD0gIjIwMTAtMTItMzEiKSAlPiUKICAgICAgICBncm91cF9ieShjb25kaXRpb25fY29uY2VwdF9pZCkgJT4lCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkgJT4lCiAgICAgICAgYXJyYW5nZShkZXNjKGNvdW50KSkKI0pvaW4gdGhlIGNvbmRpdGlvbl8yMDEwIHdpdGggY29uY2VwdF8xMDAwIHRvIG9idGFpbiB0aGUgY29uZGl0aW9uIG5hbWVzCmNvbmRpdGlvbl8yMDEweCA8LSBjb25kaXRpb25fMjAxMCAlPiUKICAgICAgICBsZWZ0X2pvaW4oY29uY2VwdF8xMDAwLCBieSA9IGMoImNvbmRpdGlvbl9jb25jZXB0X2lkIiA9ICJjb25jZXB0X2lkIikpICU+JSAKICAgICAgICBzZWxlY3QoY29uY2VwdF9uYW1lLGNvdW50KQpjb25kaXRpb25fMjAxMHgKYGBgCmMuIFdoYXQgd2FzIHRoZSBtb3N0IHByZXZhbGVudCBjb25kaXRpb24gaW4gQ0EgKGxvb2tpbmcgYWNyb3NzIGFsbCB5ZWFycyk/Ci0gVDJETQpgYGB7cn0KI0ZpbHRlciBmb3IgcGF0aWVudHMgZnJvbSBsb2NhdGlvbl8xMDAwIHRvIG9idGFpbiBsb2NhdGlvbl9pZCdzIHNwZWNpZmljIGZvciBDYWxpZm9ybmlhCmRmY2ExIDwtIGxvY2F0aW9uXzEwMDAgJT4lCiAgICAgICAgZmlsdGVyKHN0YXRlID09ICJDQSIpICU+JQogICAgICAgIHNlbGVjdChsb2NhdGlvbl9pZCxzdGF0ZSkgJT4lIAogICAgICAgIGRpc3RpbmN0KCkKY2FfaWQgPC0gZGZjYTEkbG9jYXRpb25faWQgI091dCBvZiA+M2sgbG9jYXRpb25faWQncywgc2l4dHkgcmVwcmVzZW50IGNhbGlmb3JuaWEgCiNJZGVudGlmeSBDYWxpZm9ybmlhLW9ubHkgcHQuIGJ5IHNlYXJjaGluZyBmb3IgbG9jYXRpb25faWQncyBwcmVzZW50IGZyb20gY2FfaWQgaW4gcGVyc29uXzEwMDAKZGZjYTIgPC0gcGVyc29uXzEwMDAgJT4lIAogICAgICAgIGZpbHRlcihsb2NhdGlvbl9pZCAlaW4lIGNhX2lkKSAlPiUgI0NhbGlmb3JuaWEtb25seSBwdC4gaW5mbwogICAgICAgIGRpc3RpbmN0KCkKCmNhX3B0aW5mbyA8LSBkZmNhMiRwZXJzb25faWQgI3BlcnNvbi1pZCdzIGZvciBwYXRpZW50cyBpbiBDYWxpZm9ybmlhOzg2CgojRmlsdGVyIGZvciB0aGUgcGF0aWVudF9JRCdzIGZyb20gY29uZGl0aW9uX29jY3VycmVuY2VfMTAwMApkZmNhMyA8LSBjb25kaXRpb25fb2NjdXJyZW5jZV8xMDAwICU+JQogICAgICAgIGlubmVyX2pvaW4oZGZjYTIsIGJ5ID0gInBlcnNvbl9pZCIpICU+JSAKICAgICAgICBzZWxlY3QoY29uZGl0aW9uX2NvbmNlcHRfaWQscGVyc29uX2lkKQpkZmNhNCA8LSBkZmNhMyAlPiUKICAgICAgICBncm91cF9ieShjb25kaXRpb25fY29uY2VwdF9pZCkgJT4lCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkgJT4lCiAgICAgICAgYXJyYW5nZShkZXNjKGNvdW50KSkKI0pvaW4gdGhlIGRmY2E0IHdpdGggY29uY2VwdF8xMDAwIHRvIG9idGFpbiB0aGUgY29uZGl0aW9uIG5hbWVzCmRmY2E1IDwtIGRmY2E0ICU+JQogICAgICAgIGxlZnRfam9pbihjb25jZXB0XzEwMDAsIGJ5ID0gYygiY29uZGl0aW9uX2NvbmNlcHRfaWQiID0gImNvbmNlcHRfaWQiKSkgJT4lIAogICAgICAgIHNlbGVjdChjb25jZXB0X25hbWUsY291bnQpCnByaW50KGRmY2E1KQoKYGBgCmQuIFdoaWNoIHN0YXRlIGhhZCB0aGUgaGlnaGVzdCBpbmNpZGVuY2Ugb2YgQ29uZ2VzdGl2ZSBIZWFydCBGYWlsdXJlIGFjcm9zcyBhbGwgeWVhcnM/Ci0gRmxvcmlkYQpgYGB7cn0gCiNDb25jZXB0IElEIGZvciBDSEYgaXMgMzE5ODM1IAojTWVyZ2UgdGhlIGxvY2F0aW9uXzEwMDAgZGF0YXNldCB3aXRoIHRoZSBwZXJzb25fMTAwMCBkYXRhc2V0IHRvIG9idGFpbiB0aGUgU3RhdGUgZm9yIGVhY2ggcGVyc29uX2lkCnBlcnNvbl9sb2NhdGlvbiA8LSBwZXJzb25fMTAwMCAlPiUKICAgICAgICBsZWZ0X2pvaW4obG9jYXRpb25fMTAwMCwgYnkgPSBjKCJsb2NhdGlvbl9pZCIgPSAibG9jYXRpb25faWQiKSkgJT4lCiAgICAgICAgc2VsZWN0KHBlcnNvbl9pZCxzdGF0ZSkKI01lcmdlIHBlcnNvbl9sb2NhdGlvbiB3aXRoIGNvbmRpdGlvbl9vY2N1cnJlbmNlXzEwMDAgZGF0YXNldCBidXQgZmlsdGVyaW5nIHdoZW4gY29uZGl0aW9uX2NvbmNlcHRfaWQgPT0gMzE5ODM1CmNoZl9zdGF0ZXMgPC0gY29uZGl0aW9uX29jY3VycmVuY2VfMTAwMCAlPiUKICAgICAgICBmaWx0ZXIoY29uZGl0aW9uX2NvbmNlcHRfaWQgPT0gMzE5ODM1KSAlPiUKICAgICAgICBpbm5lcl9qb2luKHBlcnNvbl9sb2NhdGlvbiwgYnkgPSAicGVyc29uX2lkIikgJT4lCiAgICAgICAgZ3JvdXBfYnkoc3RhdGUpICU+JQogICAgICAgIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JQogICAgICAgIGFycmFuZ2UoZGVzYyhjb3VudCkpCnByaW50KGNoZl9zdGF0ZXMpCmBgYAoKYS4gV2hhdCBhcmUgdGhlIDUgbW9zdCBjb21tb25seSB1c2VkIGRydWdzPwotIEVwb2V0aW4gQWxmYSxJbmZsdWVuemEgdmlydXMgdmFjY2luZSwgcGFyaWNhbGNpdHJvbCwgb3h5Z2VuIDk5JSBnYXMsIG9tZXByYXpvbGUgMjBtZwotIE9mIG5vdGUsIHRoZSBudW1iZXIgb25lIHJlc3VsdCByZXR1cm5lZCBhIGRydWdfY29uY2VwdF9pZCBvZiAwLCB3aXRoIGEgY291bnQgb2YgMTQ2Ny4gCgpgYGB7cn0KZGZfZGUgPC0gZHJ1Z19leHBvc3VyZV8xMDAwICU+JQogICAgICAgIGdyb3VwX2J5KGRydWdfY29uY2VwdF9pZCkgJT4lCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkgJT4lCiAgICAgICAgYXJyYW5nZShkZXNjKGNvdW50KSkgJT4lCiAgICAgICAgbGVmdF9qb2luKGNvbmNlcHRfMTAwMCwgYnkgPSBjKCJkcnVnX2NvbmNlcHRfaWQiID0gImNvbmNlcHRfaWQiKSkgJT4lCiAgICAgICAgc2VsZWN0KGNvbmNlcHRfbmFtZSxjb3VudCkKaGVhZChkZl9kZSkKCmBgYApiLiBXaGF0IGlzIHRoZSBhdmVyYWdlIG51bWJlciBvZiBkcnVncyBwZXIgcGVyc29uPwotIDY4IGRydWdzIHBlciBwZXJzb24KYGBge3J9CiNHcm91cCB0aGUgZHJ1Z19leHBvc3VyZV8xMDAwIGRhdGFzZXQgYnkgcGVyc29uX2lkIGFuZCBjb3VudCB0aGUgbnVtYmVyIG9mIGRydWdzIGVhY2ggcGVyc29uIGhhcyB0YWtlbgpkcnVnX3Blcl9wZXJzb24gPC0gZHJ1Z19leHBvc3VyZV8xMDAwICU+JQogICAgICAgIGdyb3VwX2J5KHBlcnNvbl9pZCkgJT4lCiAgICAgICAgc3VtbWFyaXNlKGNvdW50PW4oKSkKc3VtbWFyeShkcnVnX3Blcl9wZXJzb24pCiNDYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGRydWdzIHBlciBwZXJzb24KYGBgCgpjLiBXaGF0IGlzIHRoZSBhdmVyYWdlIGR1cmF0aW9uIHRoYXQgdGhlIFNpbXZhc3RhdGluIDQwIG1nIG9yYWwgdGFibGV0IGlzIHRha2VuIGZvcj8KLSA0MSBkYXlzCmBgYHtyfQojRmlsdGVyIHRoZSBkcnVnX2V4cG9zdXJlXzEwMDAgZGF0YXNldCBmb3IgdGhlIGRydWdfY29uY2VwdF9pZCBmb3IgU2ltdmFzdGF0aW4gNDAgbWcgb3JhbCB0YWJsZXQsIHdoZXJlIGRydWdfY29uY2VwdF9JRCA9PSAxNTM5NDA3IHwgMTUzOTQwNgpzaW12YXN0YXRpbiA8LSBkcnVnX2V4cG9zdXJlXzEwMDAgJT4lCiAgICAgICAgZmlsdGVyKGRydWdfY29uY2VwdF9pZCA9PSAxNTM5NDA3IHwgZHJ1Z19jb25jZXB0X2lkID09IDE1Mzk0MDYpICU+JSAKICAgICAgICBzZWxlY3QoZHJ1Z19leHBvc3VyZV9pZCwgcGVyc29uX2lkLCBkcnVnX2NvbmNlcHRfaWQsIGRydWdfZXhwb3N1cmVfc3RhcnRfREFURSwgZHJ1Z19leHBvc3VyZV9lbmRfREFURSkgJT4lCiAgICAgICAgbXV0YXRlKGR1cmF0aW9uID0gYXMubnVtZXJpYyhkaWZmdGltZShkcnVnX2V4cG9zdXJlX2VuZF9EQVRFLCBkcnVnX2V4cG9zdXJlX3N0YXJ0X0RBVEUsIHVuaXRzID0gImRheXMiKSkpCm1lYW4oc2ltdmFzdGF0aW4kZHVyYXRpb24sIG5hLnJtID0gVFJVRSkKCmBgYAoK