This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

library(readr)
df = read_csv("~/Desktop/nycHospitalReviews.csv")
Parsed with column specification:
cols(
  hospital = col_character(),
  address = col_character(),
  numRev = col_character(),
  reviews = col_character(),
  Latitude = col_double(),
  Longitude = col_double(),
  `Accuracy Score` = col_double(),
  `Accuracy Type` = col_character(),
  Number = col_character(),
  Street = col_character(),
  City = col_character(),
  State = col_character(),
  County = col_character(),
  Zip = col_character(),
  Country = col_character(),
  Source = col_character()
)
library(dplyr)
df = mutate(df, count= (is.null(reviews)))
df$count = as.integer(df$count) + 1 #chnage to 1 because was 0 as they are not null 
totComp = aggregate(count ~ hospital, data = df, FUN = sum)
tot_sort =  totComp[order(-totComp$count ),]
library(stringr)
library(syuzhet)
#df$reviewText = as.character(df$reviewText)
#find the sentiment for each hospital
df$sentiment = get_sentiment(df$reviews)
totSent = aggregate(sentiment ~ hospital, data = df, FUN = mean) 
totSent = totSent[order(-totSent$sent ),]
#find the word count over sentiment for each of 6 words
df$word_count = str_count(df$reviews, "rude")
totRude = aggregate(word_count ~ hospital, data = df, FUN = sum) 
totRude1 = totRude
totRude1$word = "Rude"
totRude1 = merge(totRude1,totSent, by = 'hospital', sort = TRUE)
totRude1 = totRude1[order(totRude1$sent ),]
df$word_count = str_count(df$reviews, "unprofessional")
totUnprofes = aggregate(word_count ~ hospital, data = df, FUN = sum) 
totUnprofes1 = totUnprofes
totUnprofes1$word = "Unprofessional"
totUnprofes1 = merge(totUnprofes1,totSent, by = 'hospital', sort = TRUE)
totUnprofes1 = totUnprofes1[order(totUnprofes1$sent ),]
df$word_count = str_count(df$reviews, "pain")
totPain = aggregate(word_count ~ hospital, data = df, FUN = sum)
totPain1 = totPain
totPain1$word = "Pain"
totPain1 = merge(totPain1,totSent, by = 'hospital', sort = TRUE)
totPain1 = totPain1[order(totPain1$sent ),]
df$word_count = str_count(df$reviews, "friendly")
totFriend = aggregate(word_count ~ hospital, data = df, FUN = sum) 
totFriend1 = totFriend
totFriend1$word = "Friendly"
totFriend1 = merge(totFriend1,totSent, by = 'hospital', sort = TRUE)
totFriend1 = totFriend1[order(totFriend1$sent ),]
df$word_count = str_count(df$reviews, "kind")
totKind = aggregate(word_count ~ hospital, data = df, FUN = sum) 
totKind1 = totKind
totKind1$word = "Kind"
totKind1 = merge(totKind1,totSent, by = 'hospital', sort = TRUE)
totKind1 = totKind1[order(totKind1$sent ),]
df$word_count = str_count(df$reviews, "baby")
totBaby = aggregate(word_count ~ hospital, data = df, FUN = sum )
totBaby1 = totBaby
totBaby1$word = "Baby"
totBaby1 = merge(totBaby1,totSent, by = 'hospital', sort = TRUE)
totBaby1 = totBaby1[order(totBaby1$sent ),]
wordword = rbind(totRude1, totPain1,totUnprofes1, totFriend1, totBaby1, totKind1)
#plot the data 
library(ggplot2)
ggplot(wordword, aes(x=sentiment, y=word_count, color = word)) + 
    geom_point() +
    facet_wrap(~ word)

#Northwell Health-GoHealth Urgent Care
word_northwell = wordword[(wordword$hospital == 'Northwell Health-GoHealth Urgent Care'),]
word_northwell$hospital = NULL
word_northwell$sentiment = NULL
names(word_northwell)[2]<-"Words in NorthwellHealth-GoHealth Urgent Care"
word_northwell =  word_northwell[order(-word_northwell$word_count),]
library(huxtable)
word_northwell = as_hux(word_northwell)
# Select columns by name:
word_northwell= word_northwell[, c("Words in NorthwellHealth-GoHealth Urgent Care", "word_count")] 
word_northwell<- huxtable::add_colnames(word_northwell)
theme_basic(word_northwell)
  Words in NorthwellHealth-GoHealth Urgent Care │ word_count     
────────────────────────────────────────────────┼────────────────
                                       Friendly │ 19             
                                           Kind │ 17             
                                           Pain │ 15             
                                           Rude │ 6              
                                 Unprofessional │ 2              
                                           Baby │ 0              

Column names: Words in NorthwellHealth-GoHealth Urgent Care, word_count
#urgent care!
df$urgent = str_detect(df$hospital, "urgent")
df$Urgent = str_detect(df$hospital, "Urgent")
urgent = df[which(df$Urgent == TRUE | df$urgent == TRUE) ,]
nonUrgent = df[which(df$Urgent == FALSE | df$urgent == FALSE) ,]
urgent$pain_sent = get_sentiment(urgent$reviews)
nonUrgent$pain_sent = get_sentiment(nonUrgent$reviews)
urgent$word_count = str_count(urgent$reviews, "pain")
totPain = aggregate(word_count ~ hospital, data = urgent, FUN = sum)
totPain$word = "Urgent- Pain"
totPain = merge(totPain,totSent, by = 'hospital', sort = TRUE)
totPain = totPain[order(totPain$sent ),]
nonUrgent$word_count = str_count(nonUrgent$reviews, "pain")
totPain1 = aggregate(word_count ~ hospital, data = nonUrgent, FUN = sum)
totPain1$word = "Non Urgent - Pain"
totPain1 = merge(totPain1,totSent, by = 'hospital', sort = TRUE)
totPain1 = totPain1[order(totPain1$sent ),]
pain_urgent =rbind(totPain, totPain1)
ggplot(pain_urgent, aes(x=sentiment, y=word_count, color = word)) + 
    geom_point() +
    facet_wrap(~ word)

#prepare data for extraction to be used in Tableau
df2 = df[,c("hospital", "Longitude", "Latitude", "numRev")]
to_export = merge(totSent, df2,by = "hospital")
to_export = to_export[!duplicated(to_export$hospital), ]
to_export$sent = to_export$sentiment
to_export = mutate(to_export, isNeg = (sentiment < 0))
to_export$sentiment = abs(to_export$sentiment)
setwd("~/Desktop/")
The working directory was changed to /Users/ariellaschneider/Desktop inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the the working directory for notebook chunks.
write.csv(to_export, "long_lat_rev1.csv") 
library(tm)
library(wordcloud)
#make the corpus
corp <- VCorpus(VectorSource(df$reviews))
#clean the corpus 
corp = tm_map(corp, removePunctuation) 
corp = tm_map(corp, content_transformer(tolower) ,lazy=TRUE) 
corp = tm_map(corp, content_transformer(removeWords), stopwords("english") ,lazy=TRUE)
corp = tm_map(corp, stripWhitespace)
corp = tm_map(corp, removeNumbers)
corp = tm_map(corp, removeWords, c("hello","is","it","me","you're","looking","for?", "said", "the", "will", "read", "one", "also", "doctor", "doctors", "hospital", "get", "just", "like", "told"))
#make a document term matrix 
dtm = DocumentTermMatrix(corp)
#remove sparese terms to get less than 300 words
dtms = removeSparseTerms(dtm, .99)
dim(dtms)
[1] 1940 1034
m = as.matrix(dtms)
corr = cor(df$sentiment, m)
sentRev = data.frame(colnames(m))
sentRev$corr = corr[1,1:nrow(sentRev)]
sentRev$corr = sentRev$corr *100
sentRev =  sentRev[order(-sentRev$corr),]
# Keep only those in the top 100
pos100 = order(corr, decreasing=T)[1:100]
pos100words = colnames(corr)[pos100]
posCorr = corr[pos100]
#make a word clous with the size based on the correlation
wordcloud(pos100words, freq = posCorr, scale = c(2.3, 0.005), max.words = 110)

# Keep only those in the bottom 100
neg100 = order(corr, decreasing= FALSE)[1:100]
neg100words = colnames(corr)[neg100]
negCorr = corr[neg100]
#make a word clous with the size based on the correlation
wordcloud(neg30words, scale = c(2.5, 0.005), freq = abs(negCorr))

library(readr)
infe = read_csv("~/Desktop/infection.csv")
Parsed with column specification:
cols(
  `Facility ID` = col_double(),
  `Hospital Name` = col_character(),
  `Indicator Name` = col_character(),
  Year = col_double(),
  `Infections Observed` = col_double(),
  `Infections Predicted` = col_double(),
  Denominator = col_double(),
  `Indicator Value` = col_double(),
  `Indicator Lower Confidence Limit` = col_double(),
  `Indicator Upper Confidence Limit` = col_double(),
  `Indicator Units` = col_character(),
  `Comparison Results` = col_character(),
  Latitude = col_double(),
  Longitude = col_double()
)
#get the relevant data 
infections = infe[which(infe$`Hospital Name` %in% totSent$hospital),]
#find the total infections
totInf = aggregate(`Infections Observed` ~ `Hospital Name`, data = infections, FUN = sum) 
totInf = totInf[order(-totInf$`Infections Observed` ),]
#find all of the hospital codes
totCodes = aggregate(`Facility ID` ~ `Hospital Name`, data = infections, FUN = mean) 
#merge the data sets
tots = merge(totSent,totInf, by.x = 'hospital', by.y = 'Hospital Name', sort = TRUE)
tots = merge(tots,totCodes, by.x = 'hospital', by.y = 'Hospital Name', sort = TRUE)
#get rid of the outlier
tots = tots[!(tots$sentiment >7.1),]
#make a linear regression model
fit = lm(tots$`Infections Observed` ~ tots$sentiment)
summary(fit)

Call:
lm(formula = tots$`Infections Observed` ~ tots$sentiment)

Residuals:
    Min      1Q  Median      3Q     Max 
-1752.1 -1035.5  -552.1   747.0  4845.3 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)      2054.0      309.6   6.634 1.31e-07 ***
tots$sentiment   -109.1      211.0  -0.517    0.609    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1596 on 34 degrees of freedom
Multiple R-squared:  0.007795,  Adjusted R-squared:  -0.02139 
F-statistic: 0.2671 on 1 and 34 DF,  p-value: 0.6086
library(ggplot2)
ggplot(tots, aes(x=sentiment , y=`Infections Observed`)) + geom_point(color="darkred", size=4, alpha=.5) + 
    geom_smooth(method="lm", se=TRUE) + xlab("Sentiment") +
    ylab("Infections Observed")

library(readr)
death = read_csv("~/Desktop/deaths.csv")
Parsed with column specification:
cols(
  `Hospital Name` = col_character(),
  `Facility ID` = col_double(),
  `APR Medical Surgical Description` = col_character(),
  `Type of Insurance` = col_character(),
  `Patient Gender` = col_character(),
  live_status = col_character(),
  `Patient Age Group` = col_character(),
  `Discharge Year` = col_double(),
  `Number of Discharges` = col_double(),
  `Average Length of Stay` = col_double(),
  `Yearly Rank by Volume` = col_double()
)
#get relevant deaths based on facility id 
deaths = death[which(death$`Facility ID` %in% tots$`Facility ID`),]
#count the dead vs. alive patients
deaths = mutate(deaths, dead = (live_status == "Dea"))
deaths$dead = as.integer(deaths$dead)
deaths$dead = deaths$dead * deaths$`Number of Discharges`
totDead= aggregate(dead ~ `Hospital Name`, data = deaths, FUN = sum) 
totPatients= aggregate(`Number of Discharges` ~ `Hospital Name`, data = deaths, FUN = sum) 
totID= aggregate(`Facility ID` ~ `Hospital Name`, data = deaths, FUN = mean) 
totsID = merge(totID,totDead, by.x = 'Hospital Name', by.y = 'Hospital Name', sort = TRUE)
totsID = merge(totsID,totPatients, by.x = 'Hospital Name', by.y = 'Hospital Name', sort = TRUE)
totsID$`Hospital Name` <- NULL 
tots = merge(tots,totsID, by = 'Facility ID', sort = TRUE)
#find the percentage of deaths
tots$percent_death = as.double(tots$dead)/as.double(tots$`Number of Discharges`)
tots = tots[!(tots$sentiment >7.1),]
#linear regression model
ggplot(tots, aes(x=sentiment , y=percent_death)) + geom_point(color="darkred", size=4, alpha=.5) + 
    geom_smooth(method="lm", se=FALSE) + xlab("Sentiment") +
    ylab("Percent of Discharges that Result in Death")

fit = lm(tots$percent_death ~ tots$sentiment)
summary(fit)

Call:
lm(formula = tots$percent_death ~ tots$sentiment)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.11530 -0.03042 -0.01316 -0.00254  0.74786 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)
(Intercept)     0.02205    0.02626   0.840    0.407
tots$sentiment  0.02671    0.01789   1.493    0.145

Residual standard error: 0.1353 on 34 degrees of freedom
Multiple R-squared:  0.06151,   Adjusted R-squared:  0.03391 
F-statistic: 2.228 on 1 and 34 DF,  p-value: 0.1447
#remove another outlier!!
tots = tots[!(tots$percent_death >0.8),]
tots = tots[!(tots$sentiment >7.1),]
#linear regression
ggplot(tots, aes(x=sentiment , y=percent_death)) + geom_point(color="darkred", size=4, alpha=.5) + 
    geom_smooth(method="lm", se=TRUE) + xlab("Sentiment") +
    ylab("Percent of Discharges that Result in Death")

fit = lm(tots$percent_death ~ tots$sentiment)
summary(fit)

Call:
lm(formula = tots$percent_death ~ tots$sentiment)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.012048 -0.005454 -0.001620  0.003623  0.020663 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)     0.020980   0.001513  13.863 2.57e-15 ***
tots$sentiment -0.002552   0.001071  -2.382   0.0231 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.0078 on 33 degrees of freedom
Multiple R-squared:  0.1467,    Adjusted R-squared:  0.1209 
F-statistic: 5.675 on 1 and 33 DF,  p-value: 0.02312
#find length of stay 
totLength= aggregate(`Average Length of Stay` ~ `Facility ID`, data = deaths, FUN = mean) 
tots = merge(tots,totLength, by = 'Facility ID', sort = TRUE)
tots = tots[!(tots$sentiment >6.0),]
#linear regression
ggplot(tots, aes(x=sentiment , y=`Average Length of Stay`)) + geom_point(color="darkred", size=4, alpha=.5) + 
    geom_smooth(method="lm", se=TRUE) + xlab("Sentiment") +
    ylab("Average Length of Stay")

fit = lm(tots$`Average Length of Stay` ~ tots$sentiment)
summary(fit)

Call:
lm(formula = tots$`Average Length of Stay` ~ tots$sentiment)

Residuals:
    Min      1Q  Median      3Q     Max 
-4.4412 -1.3363 -0.1588  1.0601  4.6385 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)     10.2303     0.4233  24.169   <2e-16 ***
tots$sentiment  -0.4180     0.2996  -1.395    0.172    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.182 on 33 degrees of freedom
Multiple R-squared:  0.05568,   Adjusted R-squared:  0.02706 
F-statistic: 1.946 on 1 and 33 DF,  p-value: 0.1724
#read in readmission rates
library(readr)
readmis = read_csv("~/Desktop/readmission.csv")
Parsed with column specification:
cols(
  `Discharge Year` = col_double(),
  `Software Version` = col_double(),
  `Facility ID` = col_double(),
  `Facility Name` = col_character(),
  `Hospital County` = col_character(),
  `At Risk Admissions` = col_double(),
  `Observed PPR Chains` = col_double(),
  `Observed PPR Rate` = col_double(),
  `Expected PPR Rate` = col_double(),
  `Risk Adjusted PPR Rate` = col_double()
)
#count up the readmission rates 
readmish = readmis[which(readmis$`Facility ID` %in% tots$`Facility ID`),]
totReadmis= aggregate(`Observed PPR Rate` ~ `Facility ID`, data = readmish, FUN = mean) 
tots = merge(tots,totReadmis, by = 'Facility ID', sort = TRUE)
tots = tots[!(tots$sentiment >6.0),]
#linear regression model
ggplot(tots, aes(x=sentiment , y=`Observed PPR Rate`)) + geom_point(color="darkred", size=4, alpha=.5) + 
    geom_smooth(method="lm", se=TRUE) + xlab("Sentiment") +
    ylab("Observed PPR Rate")

fit = lm(tots[,9] ~ tots$sentiment)
summary(fit)

Call:
lm(formula = tots[, 9] ~ tots$sentiment)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.0586 -1.0208 -0.2028  0.8365  3.6944 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)      7.7797     0.3048  25.520   <2e-16 ***
tots$sentiment  -0.7718     0.2158  -3.576   0.0011 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.571 on 33 degrees of freedom
Multiple R-squared:  0.2793,    Adjusted R-squared:  0.2575 
F-statistic: 12.79 on 1 and 33 DF,  p-value: 0.001099

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ21kK1NoaWZ0K0VudGVyKi4gCgpgYGB7cn0KbGlicmFyeShyZWFkcikKZGYgPSByZWFkX2Nzdigifi9EZXNrdG9wL255Y0hvc3BpdGFsUmV2aWV3cy5jc3YiKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpkZiA9IG11dGF0ZShkZiwgY291bnQ9IChpcy5udWxsKHJldmlld3MpKSkKZGYkY291bnQgPSBhcy5pbnRlZ2VyKGRmJGNvdW50KSArIDEgI2NobmFnZSB0byAxIGJlY2F1c2Ugd2FzIDAgYXMgdGhleSBhcmUgbm90IG51bGwgCnRvdENvbXAgPSBhZ2dyZWdhdGUoY291bnQgfiBob3NwaXRhbCwgZGF0YSA9IGRmLCBGVU4gPSBzdW0pCnRvdF9zb3J0ID0gIHRvdENvbXBbb3JkZXIoLXRvdENvbXAkY291bnQgKSxdCgpgYGAKCmBgYHtyfQoKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHN5dXpoZXQpCiNkZiRyZXZpZXdUZXh0ID0gYXMuY2hhcmFjdGVyKGRmJHJldmlld1RleHQpCgojZmluZCB0aGUgc2VudGltZW50IGZvciBlYWNoIGhvc3BpdGFsCmRmJHNlbnRpbWVudCA9IGdldF9zZW50aW1lbnQoZGYkcmV2aWV3cykKdG90U2VudCA9IGFnZ3JlZ2F0ZShzZW50aW1lbnQgfiBob3NwaXRhbCwgZGF0YSA9IGRmLCBGVU4gPSBtZWFuKSAKdG90U2VudCA9IHRvdFNlbnRbb3JkZXIoLXRvdFNlbnQkc2VudCApLF0KCiNmaW5kIHRoZSB3b3JkIGNvdW50IG92ZXIgc2VudGltZW50IGZvciBlYWNoIG9mIDYgd29yZHMKZGYkd29yZF9jb3VudCA9IHN0cl9jb3VudChkZiRyZXZpZXdzLCAicnVkZSIpCnRvdFJ1ZGUgPSBhZ2dyZWdhdGUod29yZF9jb3VudCB+IGhvc3BpdGFsLCBkYXRhID0gZGYsIEZVTiA9IHN1bSkgCnRvdFJ1ZGUxID0gdG90UnVkZQp0b3RSdWRlMSR3b3JkID0gIlJ1ZGUiCnRvdFJ1ZGUxID0gbWVyZ2UodG90UnVkZTEsdG90U2VudCwgYnkgPSAnaG9zcGl0YWwnLCBzb3J0ID0gVFJVRSkKdG90UnVkZTEgPSB0b3RSdWRlMVtvcmRlcih0b3RSdWRlMSRzZW50ICksXQoKCmRmJHdvcmRfY291bnQgPSBzdHJfY291bnQoZGYkcmV2aWV3cywgInVucHJvZmVzc2lvbmFsIikKdG90VW5wcm9mZXMgPSBhZ2dyZWdhdGUod29yZF9jb3VudCB+IGhvc3BpdGFsLCBkYXRhID0gZGYsIEZVTiA9IHN1bSkgCnRvdFVucHJvZmVzMSA9IHRvdFVucHJvZmVzCnRvdFVucHJvZmVzMSR3b3JkID0gIlVucHJvZmVzc2lvbmFsIgp0b3RVbnByb2ZlczEgPSBtZXJnZSh0b3RVbnByb2ZlczEsdG90U2VudCwgYnkgPSAnaG9zcGl0YWwnLCBzb3J0ID0gVFJVRSkKdG90VW5wcm9mZXMxID0gdG90VW5wcm9mZXMxW29yZGVyKHRvdFVucHJvZmVzMSRzZW50ICksXQoKZGYkd29yZF9jb3VudCA9IHN0cl9jb3VudChkZiRyZXZpZXdzLCAicGFpbiIpCnRvdFBhaW4gPSBhZ2dyZWdhdGUod29yZF9jb3VudCB+IGhvc3BpdGFsLCBkYXRhID0gZGYsIEZVTiA9IHN1bSkKdG90UGFpbjEgPSB0b3RQYWluCnRvdFBhaW4xJHdvcmQgPSAiUGFpbiIKdG90UGFpbjEgPSBtZXJnZSh0b3RQYWluMSx0b3RTZW50LCBieSA9ICdob3NwaXRhbCcsIHNvcnQgPSBUUlVFKQp0b3RQYWluMSA9IHRvdFBhaW4xW29yZGVyKHRvdFBhaW4xJHNlbnQgKSxdCgpkZiR3b3JkX2NvdW50ID0gc3RyX2NvdW50KGRmJHJldmlld3MsICJmcmllbmRseSIpCnRvdEZyaWVuZCA9IGFnZ3JlZ2F0ZSh3b3JkX2NvdW50IH4gaG9zcGl0YWwsIGRhdGEgPSBkZiwgRlVOID0gc3VtKSAKdG90RnJpZW5kMSA9IHRvdEZyaWVuZAp0b3RGcmllbmQxJHdvcmQgPSAiRnJpZW5kbHkiCnRvdEZyaWVuZDEgPSBtZXJnZSh0b3RGcmllbmQxLHRvdFNlbnQsIGJ5ID0gJ2hvc3BpdGFsJywgc29ydCA9IFRSVUUpCnRvdEZyaWVuZDEgPSB0b3RGcmllbmQxW29yZGVyKHRvdEZyaWVuZDEkc2VudCApLF0KCmRmJHdvcmRfY291bnQgPSBzdHJfY291bnQoZGYkcmV2aWV3cywgImtpbmQiKQp0b3RLaW5kID0gYWdncmVnYXRlKHdvcmRfY291bnQgfiBob3NwaXRhbCwgZGF0YSA9IGRmLCBGVU4gPSBzdW0pIAp0b3RLaW5kMSA9IHRvdEtpbmQKdG90S2luZDEkd29yZCA9ICJLaW5kIgp0b3RLaW5kMSA9IG1lcmdlKHRvdEtpbmQxLHRvdFNlbnQsIGJ5ID0gJ2hvc3BpdGFsJywgc29ydCA9IFRSVUUpCnRvdEtpbmQxID0gdG90S2luZDFbb3JkZXIodG90S2luZDEkc2VudCApLF0KCmRmJHdvcmRfY291bnQgPSBzdHJfY291bnQoZGYkcmV2aWV3cywgImJhYnkiKQp0b3RCYWJ5ID0gYWdncmVnYXRlKHdvcmRfY291bnQgfiBob3NwaXRhbCwgZGF0YSA9IGRmLCBGVU4gPSBzdW0gKQp0b3RCYWJ5MSA9IHRvdEJhYnkKdG90QmFieTEkd29yZCA9ICJCYWJ5Igp0b3RCYWJ5MSA9IG1lcmdlKHRvdEJhYnkxLHRvdFNlbnQsIGJ5ID0gJ2hvc3BpdGFsJywgc29ydCA9IFRSVUUpCnRvdEJhYnkxID0gdG90QmFieTFbb3JkZXIodG90QmFieTEkc2VudCApLF0KCgoKd29yZHdvcmQgPSByYmluZCh0b3RSdWRlMSwgdG90UGFpbjEsdG90VW5wcm9mZXMxLCB0b3RGcmllbmQxLCB0b3RCYWJ5MSwgdG90S2luZDEpCgoKI3Bsb3QgdGhlIGRhdGEgCmxpYnJhcnkoZ2dwbG90MikKCgpnZ3Bsb3Qod29yZHdvcmQsIGFlcyh4PXNlbnRpbWVudCwgeT13b3JkX2NvdW50LCBjb2xvciA9IHdvcmQpKSArIAogICAgZ2VvbV9wb2ludCgpICsKICAgIGZhY2V0X3dyYXAofiB3b3JkKQoKI05vcnRod2VsbCBIZWFsdGgtR29IZWFsdGggVXJnZW50IENhcmUKd29yZF9ub3J0aHdlbGwgPSB3b3Jkd29yZFsod29yZHdvcmQkaG9zcGl0YWwgPT0gJ05vcnRod2VsbCBIZWFsdGgtR29IZWFsdGggVXJnZW50IENhcmUnKSxdCndvcmRfbm9ydGh3ZWxsJGhvc3BpdGFsID0gTlVMTAp3b3JkX25vcnRod2VsbCRzZW50aW1lbnQgPSBOVUxMCm5hbWVzKHdvcmRfbm9ydGh3ZWxsKVsyXTwtIldvcmRzIGluIE5vcnRod2VsbEhlYWx0aC1Hb0hlYWx0aCBVcmdlbnQgQ2FyZSIKd29yZF9ub3J0aHdlbGwgPSAgd29yZF9ub3J0aHdlbGxbb3JkZXIoLXdvcmRfbm9ydGh3ZWxsJHdvcmRfY291bnQpLF0KCmxpYnJhcnkoaHV4dGFibGUpCndvcmRfbm9ydGh3ZWxsID0gYXNfaHV4KHdvcmRfbm9ydGh3ZWxsKQoKIyBTZWxlY3QgY29sdW1ucyBieSBuYW1lOgp3b3JkX25vcnRod2VsbD0gd29yZF9ub3J0aHdlbGxbLCBjKCJXb3JkcyBpbiBOb3J0aHdlbGxIZWFsdGgtR29IZWFsdGggVXJnZW50IENhcmUiLCAid29yZF9jb3VudCIpXSAKd29yZF9ub3J0aHdlbGw8LSBodXh0YWJsZTo6YWRkX2NvbG5hbWVzKHdvcmRfbm9ydGh3ZWxsKQoKCnRoZW1lX2Jhc2ljKHdvcmRfbm9ydGh3ZWxsKQoKYGBgCgpgYGB7cn0KCiNkZWNpZGVkIG5vdCB0byB1c2UgdGhpcyBwYXJ0ISAKCgojdXJnZW50IGNhcmUhCmRmJHVyZ2VudCA9IHN0cl9kZXRlY3QoZGYkaG9zcGl0YWwsICJ1cmdlbnQiKQpkZiRVcmdlbnQgPSBzdHJfZGV0ZWN0KGRmJGhvc3BpdGFsLCAiVXJnZW50IikKCnVyZ2VudCA9IGRmW3doaWNoKGRmJFVyZ2VudCA9PSBUUlVFIHwgZGYkdXJnZW50ID09IFRSVUUpICxdCm5vblVyZ2VudCA9IGRmW3doaWNoKGRmJFVyZ2VudCA9PSBGQUxTRSB8IGRmJHVyZ2VudCA9PSBGQUxTRSkgLF0KCnVyZ2VudCRwYWluX3NlbnQgPSBnZXRfc2VudGltZW50KHVyZ2VudCRyZXZpZXdzKQpub25VcmdlbnQkcGFpbl9zZW50ID0gZ2V0X3NlbnRpbWVudChub25VcmdlbnQkcmV2aWV3cykKCgoKCnVyZ2VudCR3b3JkX2NvdW50ID0gc3RyX2NvdW50KHVyZ2VudCRyZXZpZXdzLCAicGFpbiIpCnRvdFBhaW4gPSBhZ2dyZWdhdGUod29yZF9jb3VudCB+IGhvc3BpdGFsLCBkYXRhID0gdXJnZW50LCBGVU4gPSBzdW0pCnRvdFBhaW4kd29yZCA9ICJVcmdlbnQtIFBhaW4iCnRvdFBhaW4gPSBtZXJnZSh0b3RQYWluLHRvdFNlbnQsIGJ5ID0gJ2hvc3BpdGFsJywgc29ydCA9IFRSVUUpCnRvdFBhaW4gPSB0b3RQYWluW29yZGVyKHRvdFBhaW4kc2VudCApLF0KCm5vblVyZ2VudCR3b3JkX2NvdW50ID0gc3RyX2NvdW50KG5vblVyZ2VudCRyZXZpZXdzLCAicGFpbiIpCnRvdFBhaW4xID0gYWdncmVnYXRlKHdvcmRfY291bnQgfiBob3NwaXRhbCwgZGF0YSA9IG5vblVyZ2VudCwgRlVOID0gc3VtKQp0b3RQYWluMSR3b3JkID0gIk5vbiBVcmdlbnQgLSBQYWluIgp0b3RQYWluMSA9IG1lcmdlKHRvdFBhaW4xLHRvdFNlbnQsIGJ5ID0gJ2hvc3BpdGFsJywgc29ydCA9IFRSVUUpCnRvdFBhaW4xID0gdG90UGFpbjFbb3JkZXIodG90UGFpbjEkc2VudCApLF0KCgpwYWluX3VyZ2VudCA9cmJpbmQodG90UGFpbiwgdG90UGFpbjEpCgpnZ3Bsb3QocGFpbl91cmdlbnQsIGFlcyh4PXNlbnRpbWVudCwgeT13b3JkX2NvdW50LCBjb2xvciA9IHdvcmQpKSArIAogICAgZ2VvbV9wb2ludCgpICsKICAgIGZhY2V0X3dyYXAofiB3b3JkKQoKYGBgCgpgYGB7cn0KI3ByZXBhcmUgZGF0YSBmb3IgZXh0cmFjdGlvbiB0byBiZSB1c2VkIGluIFRhYmxlYXUKZGYyID0gZGZbLGMoImhvc3BpdGFsIiwgIkxvbmdpdHVkZSIsICJMYXRpdHVkZSIsICJudW1SZXYiKV0KdG9fZXhwb3J0ID0gbWVyZ2UodG90U2VudCwgZGYyLGJ5ID0gImhvc3BpdGFsIikKdG9fZXhwb3J0ID0gdG9fZXhwb3J0WyFkdXBsaWNhdGVkKHRvX2V4cG9ydCRob3NwaXRhbCksIF0KdG9fZXhwb3J0JHNlbnQgPSB0b19leHBvcnQkc2VudGltZW50CnRvX2V4cG9ydCA9IG11dGF0ZSh0b19leHBvcnQsIGlzTmVnID0gKHNlbnRpbWVudCA8IDApKQp0b19leHBvcnQkc2VudGltZW50ID0gYWJzKHRvX2V4cG9ydCRzZW50aW1lbnQpCgpzZXR3ZCgifi9EZXNrdG9wLyIpCndyaXRlLmNzdih0b19leHBvcnQsICJsb25nX2xhdF9yZXYxLmNzdiIpIAoKCmBgYAoKYGBge3J9CgpsaWJyYXJ5KHRtKQpsaWJyYXJ5KHdvcmRjbG91ZCkKCgojbWFrZSB0aGUgY29ycHVzCmNvcnAgPC0gVkNvcnB1cyhWZWN0b3JTb3VyY2UoZGYkcmV2aWV3cykpCgojY2xlYW4gdGhlIGNvcnB1cyAKY29ycCA9IHRtX21hcChjb3JwLCByZW1vdmVQdW5jdHVhdGlvbikgCmNvcnAgPSB0bV9tYXAoY29ycCwgY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSAsbGF6eT1UUlVFKSAKY29ycCA9IHRtX21hcChjb3JwLCBjb250ZW50X3RyYW5zZm9ybWVyKHJlbW92ZVdvcmRzKSwgc3RvcHdvcmRzKCJlbmdsaXNoIikgLGxhenk9VFJVRSkKY29ycCA9IHRtX21hcChjb3JwLCBzdHJpcFdoaXRlc3BhY2UpCmNvcnAgPSB0bV9tYXAoY29ycCwgcmVtb3ZlTnVtYmVycykKY29ycCA9IHRtX21hcChjb3JwLCByZW1vdmVXb3JkcywgYygiaGVsbG8iLCJpcyIsIml0IiwibWUiLCJ5b3UncmUiLCJsb29raW5nIiwiZm9yPyIsICJzYWlkIiwgInRoZSIsICJ3aWxsIiwgInJlYWQiLCAib25lIiwgImFsc28iLCAiZG9jdG9yIiwgImRvY3RvcnMiLCAiaG9zcGl0YWwiLCAiZ2V0IiwgImp1c3QiLCAibGlrZSIsICJ0b2xkIikpCgoKI21ha2UgYSBkb2N1bWVudCB0ZXJtIG1hdHJpeCAKZHRtID0gRG9jdW1lbnRUZXJtTWF0cml4KGNvcnApCgojcmVtb3ZlIHNwYXJlc2UgdGVybXMgdG8gZ2V0IGxlc3MgdGhhbiAzMDAgd29yZHMKZHRtcyA9IHJlbW92ZVNwYXJzZVRlcm1zKGR0bSwgLjk5KQpkaW0oZHRtcykKbSA9IGFzLm1hdHJpeChkdG1zKQoKY29yciA9IGNvcihkZiRzZW50aW1lbnQsIG0pCgpzZW50UmV2ID0gZGF0YS5mcmFtZShjb2xuYW1lcyhtKSkKc2VudFJldiRjb3JyID0gY29yclsxLDE6bnJvdyhzZW50UmV2KV0Kc2VudFJldiRjb3JyID0gc2VudFJldiRjb3JyICoxMDAKc2VudFJldiA9ICBzZW50UmV2W29yZGVyKC1zZW50UmV2JGNvcnIpLF0KCgojIEtlZXAgb25seSB0aG9zZSBpbiB0aGUgdG9wIDEwMApwb3MxMDAgPSBvcmRlcihjb3JyLCBkZWNyZWFzaW5nPVQpWzE6MTAwXQpwb3MxMDB3b3JkcyA9IGNvbG5hbWVzKGNvcnIpW3BvczEwMF0KCnBvc0NvcnIgPSBjb3JyW3BvczEwMF0KI21ha2UgYSB3b3JkIGNsb3VzIHdpdGggdGhlIHNpemUgYmFzZWQgb24gdGhlIGNvcnJlbGF0aW9uCndvcmRjbG91ZChwb3MxMDB3b3JkcywgZnJlcSA9IHBvc0NvcnIsIHNjYWxlID0gYygyLjMsIDAuMDA1KSwgbWF4LndvcmRzID0gMTEwKQoKCiMgS2VlcCBvbmx5IHRob3NlIGluIHRoZSBib3R0b20gMTAwCm5lZzEwMCA9IG9yZGVyKGNvcnIsIGRlY3JlYXNpbmc9IEZBTFNFKVsxOjEwMF0KbmVnMTAwd29yZHMgPSBjb2xuYW1lcyhjb3JyKVtuZWcxMDBdCm5lZ0NvcnIgPSBjb3JyW25lZzEwMF0KI21ha2UgYSB3b3JkIGNsb3VzIHdpdGggdGhlIHNpemUgYmFzZWQgb24gdGhlIGNvcnJlbGF0aW9uCndvcmRjbG91ZChuZWczMHdvcmRzLCBzY2FsZSA9IGMoMi41LCAwLjAwNSksIGZyZXEgPSBhYnMobmVnQ29ycikpCgpgYGAKCgpgYGB7cn0KbGlicmFyeShyZWFkcikKaW5mZSA9IHJlYWRfY3N2KCJ+L0Rlc2t0b3AvaW5mZWN0aW9uLmNzdiIpCmBgYAoKCmBgYHtyfQoKI2dldCB0aGUgcmVsZXZhbnQgZGF0YSAKaW5mZWN0aW9ucyA9IGluZmVbd2hpY2goaW5mZSRgSG9zcGl0YWwgTmFtZWAgJWluJSB0b3RTZW50JGhvc3BpdGFsKSxdCgojZmluZCB0aGUgdG90YWwgaW5mZWN0aW9ucwp0b3RJbmYgPSBhZ2dyZWdhdGUoYEluZmVjdGlvbnMgT2JzZXJ2ZWRgIH4gYEhvc3BpdGFsIE5hbWVgLCBkYXRhID0gaW5mZWN0aW9ucywgRlVOID0gc3VtKSAKdG90SW5mID0gdG90SW5mW29yZGVyKC10b3RJbmYkYEluZmVjdGlvbnMgT2JzZXJ2ZWRgICksXQoKI2ZpbmQgYWxsIG9mIHRoZSBob3NwaXRhbCBjb2Rlcwp0b3RDb2RlcyA9IGFnZ3JlZ2F0ZShgRmFjaWxpdHkgSURgIH4gYEhvc3BpdGFsIE5hbWVgLCBkYXRhID0gaW5mZWN0aW9ucywgRlVOID0gbWVhbikgCgojbWVyZ2UgdGhlIGRhdGEgc2V0cwp0b3RzID0gbWVyZ2UodG90U2VudCx0b3RJbmYsIGJ5LnggPSAnaG9zcGl0YWwnLCBieS55ID0gJ0hvc3BpdGFsIE5hbWUnLCBzb3J0ID0gVFJVRSkKdG90cyA9IG1lcmdlKHRvdHMsdG90Q29kZXMsIGJ5LnggPSAnaG9zcGl0YWwnLCBieS55ID0gJ0hvc3BpdGFsIE5hbWUnLCBzb3J0ID0gVFJVRSkKCiNnZXQgcmlkIG9mIHRoZSBvdXRsaWVyCnRvdHMgPSB0b3RzWyEodG90cyRzZW50aW1lbnQgPjcuMSksXQoKI21ha2UgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbApmaXQgPSBsbSh0b3RzJGBJbmZlY3Rpb25zIE9ic2VydmVkYCB+IHRvdHMkc2VudGltZW50KQpzdW1tYXJ5KGZpdCkKCmxpYnJhcnkoZ2dwbG90MikKCmdncGxvdCh0b3RzLCBhZXMoeD1zZW50aW1lbnQgLCB5PWBJbmZlY3Rpb25zIE9ic2VydmVkYCkpICsgZ2VvbV9wb2ludChjb2xvcj0iZGFya3JlZCIsIHNpemU9NCwgYWxwaGE9LjUpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2U9VFJVRSkgKyB4bGFiKCJTZW50aW1lbnQiKSArCiAgICB5bGFiKCJJbmZlY3Rpb25zIE9ic2VydmVkIikKYGBgCgoKCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpkZWF0aCA9IHJlYWRfY3N2KCJ+L0Rlc2t0b3AvZGVhdGhzLmNzdiIpCgoKI2dldCByZWxldmFudCBkZWF0aHMgYmFzZWQgb24gZmFjaWxpdHkgaWQgCmRlYXRocyA9IGRlYXRoW3doaWNoKGRlYXRoJGBGYWNpbGl0eSBJRGAgJWluJSB0b3RzJGBGYWNpbGl0eSBJRGApLF0KCiNjb3VudCB0aGUgZGVhZCB2cy4gYWxpdmUgcGF0aWVudHMKZGVhdGhzID0gbXV0YXRlKGRlYXRocywgZGVhZCA9IChsaXZlX3N0YXR1cyA9PSAiRGVhIikpCmRlYXRocyRkZWFkID0gYXMuaW50ZWdlcihkZWF0aHMkZGVhZCkKZGVhdGhzJGRlYWQgPSBkZWF0aHMkZGVhZCAqIGRlYXRocyRgTnVtYmVyIG9mIERpc2NoYXJnZXNgCnRvdERlYWQ9IGFnZ3JlZ2F0ZShkZWFkIH4gYEhvc3BpdGFsIE5hbWVgLCBkYXRhID0gZGVhdGhzLCBGVU4gPSBzdW0pIAp0b3RQYXRpZW50cz0gYWdncmVnYXRlKGBOdW1iZXIgb2YgRGlzY2hhcmdlc2AgfiBgSG9zcGl0YWwgTmFtZWAsIGRhdGEgPSBkZWF0aHMsIEZVTiA9IHN1bSkgCnRvdElEPSBhZ2dyZWdhdGUoYEZhY2lsaXR5IElEYCB+IGBIb3NwaXRhbCBOYW1lYCwgZGF0YSA9IGRlYXRocywgRlVOID0gbWVhbikgCgoKdG90c0lEID0gbWVyZ2UodG90SUQsdG90RGVhZCwgYnkueCA9ICdIb3NwaXRhbCBOYW1lJywgYnkueSA9ICdIb3NwaXRhbCBOYW1lJywgc29ydCA9IFRSVUUpCnRvdHNJRCA9IG1lcmdlKHRvdHNJRCx0b3RQYXRpZW50cywgYnkueCA9ICdIb3NwaXRhbCBOYW1lJywgYnkueSA9ICdIb3NwaXRhbCBOYW1lJywgc29ydCA9IFRSVUUpCnRvdHNJRCRgSG9zcGl0YWwgTmFtZWAgPC0gTlVMTCAKdG90cyA9IG1lcmdlKHRvdHMsdG90c0lELCBieSA9ICdGYWNpbGl0eSBJRCcsIHNvcnQgPSBUUlVFKQoKI2ZpbmQgdGhlIHBlcmNlbnRhZ2Ugb2YgZGVhdGhzCnRvdHMkcGVyY2VudF9kZWF0aCA9IGFzLmRvdWJsZSh0b3RzJGRlYWQpL2FzLmRvdWJsZSh0b3RzJGBOdW1iZXIgb2YgRGlzY2hhcmdlc2ApCnRvdHMgPSB0b3RzWyEodG90cyRzZW50aW1lbnQgPjcuMSksXQoKI2xpbmVhciByZWdyZXNzaW9uIG1vZGVsCmdncGxvdCh0b3RzLCBhZXMoeD1zZW50aW1lbnQgLCB5PXBlcmNlbnRfZGVhdGgpKSArIGdlb21fcG9pbnQoY29sb3I9ImRhcmtyZWQiLCBzaXplPTQsIGFscGhhPS41KSArIAogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIHNlPUZBTFNFKSArIHhsYWIoIlNlbnRpbWVudCIpICsKICAgIHlsYWIoIlBlcmNlbnQgb2YgRGlzY2hhcmdlcyB0aGF0IFJlc3VsdCBpbiBEZWF0aCIpCgpmaXQgPSBsbSh0b3RzJHBlcmNlbnRfZGVhdGggfiB0b3RzJHNlbnRpbWVudCkKc3VtbWFyeShmaXQpCgpgYGAKCmBgYHtyfQojcmVtb3ZlIGFub3RoZXIgb3V0bGllciEhCnRvdHMgPSB0b3RzWyEodG90cyRwZXJjZW50X2RlYXRoID4wLjgpLF0KdG90cyA9IHRvdHNbISh0b3RzJHNlbnRpbWVudCA+Ny4xKSxdCgojbGluZWFyIHJlZ3Jlc3Npb24KZ2dwbG90KHRvdHMsIGFlcyh4PXNlbnRpbWVudCAsIHk9cGVyY2VudF9kZWF0aCkpICsgZ2VvbV9wb2ludChjb2xvcj0iZGFya3JlZCIsIHNpemU9NCwgYWxwaGE9LjUpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2U9VFJVRSkgKyB4bGFiKCJTZW50aW1lbnQiKSArCiAgICB5bGFiKCJQZXJjZW50IG9mIERpc2NoYXJnZXMgdGhhdCBSZXN1bHQgaW4gRGVhdGgiKQoKZml0ID0gbG0odG90cyRwZXJjZW50X2RlYXRoIH4gdG90cyRzZW50aW1lbnQpCnN1bW1hcnkoZml0KQpgYGAKCmBgYHtyfQoKI2ZpbmQgbGVuZ3RoIG9mIHN0YXkgCnRvdExlbmd0aD0gYWdncmVnYXRlKGBBdmVyYWdlIExlbmd0aCBvZiBTdGF5YCB+IGBGYWNpbGl0eSBJRGAsIGRhdGEgPSBkZWF0aHMsIEZVTiA9IG1lYW4pIAp0b3RzID0gbWVyZ2UodG90cyx0b3RMZW5ndGgsIGJ5ID0gJ0ZhY2lsaXR5IElEJywgc29ydCA9IFRSVUUpCnRvdHMgPSB0b3RzWyEodG90cyRzZW50aW1lbnQgPjYuMCksXQoKI2xpbmVhciByZWdyZXNzaW9uCmdncGxvdCh0b3RzLCBhZXMoeD1zZW50aW1lbnQgLCB5PWBBdmVyYWdlIExlbmd0aCBvZiBTdGF5YCkpICsgZ2VvbV9wb2ludChjb2xvcj0iZGFya3JlZCIsIHNpemU9NCwgYWxwaGE9LjUpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2U9VFJVRSkgKyB4bGFiKCJTZW50aW1lbnQiKSArCiAgICB5bGFiKCJBdmVyYWdlIExlbmd0aCBvZiBTdGF5IikKCmZpdCA9IGxtKHRvdHMkYEF2ZXJhZ2UgTGVuZ3RoIG9mIFN0YXlgIH4gdG90cyRzZW50aW1lbnQpCnN1bW1hcnkoZml0KQoKYGBgCgpgYGB7cn0KCiNyZWFkIGluIHJlYWRtaXNzaW9uIHJhdGVzCmxpYnJhcnkocmVhZHIpCnJlYWRtaXMgPSByZWFkX2Nzdigifi9EZXNrdG9wL3JlYWRtaXNzaW9uLmNzdiIpCgojY291bnQgdXAgdGhlIHJlYWRtaXNzaW9uIHJhdGVzIApyZWFkbWlzaCA9IHJlYWRtaXNbd2hpY2gocmVhZG1pcyRgRmFjaWxpdHkgSURgICVpbiUgdG90cyRgRmFjaWxpdHkgSURgKSxdCnRvdFJlYWRtaXM9IGFnZ3JlZ2F0ZShgT2JzZXJ2ZWQgUFBSIFJhdGVgIH4gYEZhY2lsaXR5IElEYCwgZGF0YSA9IHJlYWRtaXNoLCBGVU4gPSBtZWFuKSAKdG90cyA9IG1lcmdlKHRvdHMsdG90UmVhZG1pcywgYnkgPSAnRmFjaWxpdHkgSUQnLCBzb3J0ID0gVFJVRSkKdG90cyA9IHRvdHNbISh0b3RzJHNlbnRpbWVudCA+Ni4wKSxdCgojbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwKZ2dwbG90KHRvdHMsIGFlcyh4PXNlbnRpbWVudCAsIHk9YE9ic2VydmVkIFBQUiBSYXRlYCkpICsgZ2VvbV9wb2ludChjb2xvcj0iZGFya3JlZCIsIHNpemU9NCwgYWxwaGE9LjUpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2U9VFJVRSkgKyB4bGFiKCJTZW50aW1lbnQiKSArCiAgICB5bGFiKCJPYnNlcnZlZCBQUFIgUmF0ZSIpCgpmaXQgPSBsbSh0b3RzWyw5XSB+IHRvdHMkc2VudGltZW50KQpzdW1tYXJ5KGZpdCkKYGBgCgpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ21kK09wdGlvbitJKi4KCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ21kK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuCg==