Bayesian Election Modeling
library("dplyr")
library("ggplot2")
library("bayestestR")
library("usmap")
#Triangle Prior
get_prior_distr <- function(vals) {
  vals_pmin <- pmin(vals, 1 - vals)
  # Normalize the prior so that they sum to 1.
  tibble::tibble(theta = vals, prior = vals_pmin / sum(vals_pmin)
  )
  }

plot_prior_distr <- function(prior_distr_df, plot_x_labels = TRUE) {
  theta_prior_p <- 
    prior_distr_df %>%
    ggplot(aes(x = theta, y = prior)) +
    geom_point() +
    geom_segment(aes(x = theta, xend = theta, y = prior, yend = 0)) +
    xlab(expression(theta)) +
    ylab(expression(paste("P(", theta, ")"))) +
    ggtitle("Prior Distribution") 

  if (plot_x_labels) {
    theta_vals <- prior_distr_df[["theta"]]
    theta_prior_p <- theta_prior_p + scale_x_continuous(breaks = c(theta_vals), labels = theta_vals)
  }

  return(theta_prior_p)
}

get_likelihood_df <- function(theta_vals, num_succss, num_fails) {
  likelihood.vals <- c()
  for (cur.theta.val in theta_vals) {
    likelihood.vals <- 
      c(likelihood.vals, 
        (cur.theta.val^num_succss) * (1 - cur.theta.val)^(num_fails))
  }

  likelihood.vals <- dbinom(num_succss, num_succss + num_fails, theta_vals)
  likelihood_df <- 
    tibble::tibble(
      theta = theta_vals,
      likelihood = likelihood.vals
    )

  return(likelihood_df)
}

get_posterior_df <- function(likelihood_df, prior_distr_df) {

  likelihood_prior_df <- dplyr::left_join(likelihood_df, prior_distr_df, by = "theta")

  marg_likelihood <- likelihood_prior_df %>%dplyr::mutate(likelihood_theta = .data[["likelihood"]] * .data[["prior"]]) %>% dplyr::pull("likelihood_theta") %>%sum()

  posterior_df <- dplyr::mutate(likelihood_prior_df, post_prob = (likelihood * prior) / marg_likelihood)

  return(posterior_df)
}


plot_likelihood_prob_distr <- function(likelihood_df) {
  likelihood_df %>%
  ggplot(aes(x = theta, y = likelihood)) +
  geom_point() +
  geom_segment(aes(x = theta, xend = theta, y = likelihood, yend = 0)) +
  xlab(expression(theta)) +
  ylab(expression(paste("P(D|", theta, ")"))) +
  ggtitle("Likelihood Distribution")
}

plot_posterior_prob_distr <- function(posterior_df, theta_vals) {
  posterior_df %>%
  ggplot(aes(x = theta, y = post_prob)) +
  geom_point() +
  geom_segment(aes(x = theta, xend = theta, y = post_prob, yend = 0)) +
  xlab(expression(theta)) +
  ylab(expression(paste("P(", theta, "|D)"))) +
  ggtitle("Posterior Distribution")
}

ci <- function(x, px){  # Function created using https://stats.stackexchange.com/questions/240749/how-to-find-95-credible-interval

  xx <- seq(min(x), max(x), by = 0.05)

  # interpolate function from the sample
  fx <- splinefun(x, px) # interpolating function
  pxx <- pmax(0, fx(xx)) # normalize so prob >0

  # sample from the "empirical" distribution
  samp <- sample(xx, 1e5, replace = TRUE, prob = pxx)

  # and take sample quantiles
  quantile(samp, c(0.025, 0.975)) 

  cpxx <- cumsum(pxx) / sum(pxx)
  xx[which(cpxx >= 0.025)[1]]   # lower boundary
  xx[which(cpxx >= 0.975)[1]-1] # upper boundary

  return(c(xx[which(cpxx >= 0.025)[1]],xx[which(cpxx >= 0.975)[1]-1]))   # lower boundary, upper

}
#Read more about these! http://tinyheero.github.io/2017/03/08/how-to-bayesian-infer-101.html
theta_vals <- seq(0, 1, 0.05) # Sets the resolution of the distrobution for theta .001 for the prettiest picture, but way more computational power
theta_prior_distr_df <- get_prior_distr(theta_vals) #Setup the dataframe for prior
likelihood_df <- get_likelihood_df(theta_vals, 0, 10) ## 0 successes, 10 failures
posterior_df <- get_posterior_df(likelihood_df, theta_prior_distr_df)
plot_prior_distr(theta_prior_distr_df)

plot_likelihood_prob_distr(likelihood_df)

plot_posterior_prob_distr(posterior_df, theta_vals)

testsample <- sample(posterior_df$theta, 1, prob = posterior_df$post_prob, replace=TRUE)
testsample * 13 
[1] 3.9
posterior_df

ci(posterior_df$theta, posterior_df$post_prob)
[1] 0.05 0.35
all = `1976.2016.president` 
prez1 = subset(all, party == 'democrat' & writein==FALSE & year>=2000 | party == 'republican' & writein==FALSE & year>=2000 | party == 'democratic-farmer-labor' & writein==FALSE & year>=2000)
prezd = subset(prez1, party == 'democrat' & writein==FALSE | party == 'democratic-farmer-labor' & writein==FALSE)
prezr = subset(prez1, party == 'republican' & writein==FALSE)

win2000 <- list()
for (i in 1:255){
  if (prezr[i,11] < prezd[i,11]) {
  win2000 <- c(win2000, 1)
  } else {
  win2000 <-c(win2000, 0)
  }
}
df <- data.frame(matrix(unlist(win2000), nrow=5, ncol=51, byrow=T))
dftotal <- colSums(df, na.rm = T)
dftotal
 X1  X2  X3  X4  X5  X6  X7  X8  X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 X32 X33 X34 X35 X36 X37 X38 X39 
  0   0   0   0   5   3   5   5   5   2   0   5   0   5   1   3   0   0   0   5   5   5   4   5   0   0   0   0   3   4   5   4   5   1   0   2   0   5   4 
X40 X41 X42 X43 X44 X45 X46 X47 X48 X49 X50 X51 
  5   0   0   0   0   0   5   3   5   0   4   0 
poll_df = `polldata.11.26`

postmaster = list()
postrange = list()

for (i in 1:nrow(poll_df)){ #Repeat this loop the number of items in my list. Note that it should always be 51 since I have 51 "states"
 dwin = poll_df[i,2] + dftotal[i] 
 dloss = poll_df[i,3] + 6 -poll_df[i,2] - dftotal[i]
 
 likelihood_df <- get_likelihood_df(theta_vals, dwin , dloss)
 posterior_df <- get_posterior_df(likelihood_df, theta_prior_distr_df)
 
 postmastertemp <- data.frame(i, t(sapply(posterior_df[which.max(posterior_df$post_prob),]$theta,c)))
 postmaster <-rbind(postmaster, postmastertemp)

 #Collecting CIs and rearranging them into a data frame
 ci_eti<-ci(posterior_df$theta, posterior_df$post_prob)
 postrangetemp <- data.frame(t(sapply(ci_eti,c)))
 postrange <-rbind(postrange, postrangetemp)
}
colnames(postmaster) <- c("state", "mostlikelytheta")
colnames(postrange) <- c("low", "high")
postmaster$state <- statepop$full # giving state numbers their name. Needed only for mapping with usmap
postrange
NA
postmaster%>%ggplot(aes(1:51, mostlikelytheta))+
  geom_point()+
  geom_errorbar(aes(ymin=postrange$low, ymax=postrange$high), width=.2, position=position_dodge(0.05))+
  labs(title = "Biden vs. Trump", y = "Biden Chance of Victory", x = "State")

plot_usmap(data = postmaster, values = "mostlikelytheta", color = "black") + 
  scale_fill_gradient(name = "Chance of Biden Win", low = "white", high = "blue")+
  theme(legend.position = "right")

statevote = `statevote`
colnames(statevote) <- c("state","vote")

postmaster = list()
postrange = list()
samplemaster = list()
for (i in 1:1000){
  sampletemp2 = list()
  for (i in 1:nrow(poll_df)){ #Repeat this loop the number of items in my list. Note that it should always be 51 since I have 51 "states"
    dwin = poll_df[i,2] + dftotal[i] 
    dloss = poll_df[i,3] + 6 -poll_df[i,2] - dftotal[i]
 
    likelihood_df <- get_likelihood_df(theta_vals, dwin , dloss)
    posterior_df <- get_posterior_df(likelihood_df, theta_prior_distr_df)
    sampletemp1 <- statevote$vote[i]*sample(posterior_df$theta, 1, prob = posterior_df$post_prob, replace=TRUE)
    sampletemp2 <-rbind(sampletemp2, sampletemp1)
    
  }
    
  samplemaster <- rbind(samplemaster,sum(as.numeric(sampletemp2)))
}
d <- density(as.numeric(samplemaster))
plot(d, main = "Probability of Biden Success")


mean(as.numeric(samplemaster) > 270)
[1] 0.703
LS0tDQp0aXRsZTogIkJJIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3IgTGlicmFyaWVzfQ0KbGlicmFyeSgiZHBseXIiKQ0KbGlicmFyeSgiZ2dwbG90MiIpDQpsaWJyYXJ5KCJiYXllc3Rlc3RSIikNCmxpYnJhcnkoInVzbWFwIikNCmBgYA0KDQpgYGB7cn0NCiNUcmlhbmdsZSBQcmlvcg0KZ2V0X3ByaW9yX2Rpc3RyIDwtIGZ1bmN0aW9uKHZhbHMpIHsNCiAgdmFsc19wbWluIDwtIHBtaW4odmFscywgMSAtIHZhbHMpDQogICMgTm9ybWFsaXplIHRoZSBwcmlvciBzbyB0aGF0IHRoZXkgc3VtIHRvIDEuDQogIHRpYmJsZTo6dGliYmxlKHRoZXRhID0gdmFscywgcHJpb3IgPSB2YWxzX3BtaW4gLyBzdW0odmFsc19wbWluKQ0KICApDQogIH0NCg0KcGxvdF9wcmlvcl9kaXN0ciA8LSBmdW5jdGlvbihwcmlvcl9kaXN0cl9kZiwgcGxvdF94X2xhYmVscyA9IFRSVUUpIHsNCiAgdGhldGFfcHJpb3JfcCA8LSANCiAgICBwcmlvcl9kaXN0cl9kZiAlPiUNCiAgICBnZ3Bsb3QoYWVzKHggPSB0aGV0YSwgeSA9IHByaW9yKSkgKw0KICAgIGdlb21fcG9pbnQoKSArDQogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gdGhldGEsIHhlbmQgPSB0aGV0YSwgeSA9IHByaW9yLCB5ZW5kID0gMCkpICsNCiAgICB4bGFiKGV4cHJlc3Npb24odGhldGEpKSArDQogICAgeWxhYihleHByZXNzaW9uKHBhc3RlKCJQKCIsIHRoZXRhLCAiKSIpKSkgKw0KICAgIGdndGl0bGUoIlByaW9yIERpc3RyaWJ1dGlvbiIpIA0KDQogIGlmIChwbG90X3hfbGFiZWxzKSB7DQogICAgdGhldGFfdmFscyA8LSBwcmlvcl9kaXN0cl9kZltbInRoZXRhIl1dDQogICAgdGhldGFfcHJpb3JfcCA8LSB0aGV0YV9wcmlvcl9wICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGModGhldGFfdmFscyksIGxhYmVscyA9IHRoZXRhX3ZhbHMpDQogIH0NCg0KICByZXR1cm4odGhldGFfcHJpb3JfcCkNCn0NCg0KZ2V0X2xpa2VsaWhvb2RfZGYgPC0gZnVuY3Rpb24odGhldGFfdmFscywgbnVtX3N1Y2NzcywgbnVtX2ZhaWxzKSB7DQogIGxpa2VsaWhvb2QudmFscyA8LSBjKCkNCiAgZm9yIChjdXIudGhldGEudmFsIGluIHRoZXRhX3ZhbHMpIHsNCiAgICBsaWtlbGlob29kLnZhbHMgPC0gDQogICAgICBjKGxpa2VsaWhvb2QudmFscywgDQogICAgICAgIChjdXIudGhldGEudmFsXm51bV9zdWNjc3MpICogKDEgLSBjdXIudGhldGEudmFsKV4obnVtX2ZhaWxzKSkNCiAgfQ0KDQogIGxpa2VsaWhvb2QudmFscyA8LSBkYmlub20obnVtX3N1Y2NzcywgbnVtX3N1Y2NzcyArIG51bV9mYWlscywgdGhldGFfdmFscykNCiAgbGlrZWxpaG9vZF9kZiA8LSANCiAgICB0aWJibGU6OnRpYmJsZSgNCiAgICAgIHRoZXRhID0gdGhldGFfdmFscywNCiAgICAgIGxpa2VsaWhvb2QgPSBsaWtlbGlob29kLnZhbHMNCiAgICApDQoNCiAgcmV0dXJuKGxpa2VsaWhvb2RfZGYpDQp9DQoNCmdldF9wb3N0ZXJpb3JfZGYgPC0gZnVuY3Rpb24obGlrZWxpaG9vZF9kZiwgcHJpb3JfZGlzdHJfZGYpIHsNCg0KICBsaWtlbGlob29kX3ByaW9yX2RmIDwtIGRwbHlyOjpsZWZ0X2pvaW4obGlrZWxpaG9vZF9kZiwgcHJpb3JfZGlzdHJfZGYsIGJ5ID0gInRoZXRhIikNCg0KICBtYXJnX2xpa2VsaWhvb2QgPC0gbGlrZWxpaG9vZF9wcmlvcl9kZiAlPiVkcGx5cjo6bXV0YXRlKGxpa2VsaWhvb2RfdGhldGEgPSAuZGF0YVtbImxpa2VsaWhvb2QiXV0gKiAuZGF0YVtbInByaW9yIl1dKSAlPiUgZHBseXI6OnB1bGwoImxpa2VsaWhvb2RfdGhldGEiKSAlPiVzdW0oKQ0KDQogIHBvc3Rlcmlvcl9kZiA8LSBkcGx5cjo6bXV0YXRlKGxpa2VsaWhvb2RfcHJpb3JfZGYsIHBvc3RfcHJvYiA9IChsaWtlbGlob29kICogcHJpb3IpIC8gbWFyZ19saWtlbGlob29kKQ0KDQogIHJldHVybihwb3N0ZXJpb3JfZGYpDQp9DQoNCg0KcGxvdF9saWtlbGlob29kX3Byb2JfZGlzdHIgPC0gZnVuY3Rpb24obGlrZWxpaG9vZF9kZikgew0KICBsaWtlbGlob29kX2RmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB0aGV0YSwgeSA9IGxpa2VsaWhvb2QpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc2VnbWVudChhZXMoeCA9IHRoZXRhLCB4ZW5kID0gdGhldGEsIHkgPSBsaWtlbGlob29kLCB5ZW5kID0gMCkpICsNCiAgeGxhYihleHByZXNzaW9uKHRoZXRhKSkgKw0KICB5bGFiKGV4cHJlc3Npb24ocGFzdGUoIlAoRHwiLCB0aGV0YSwgIikiKSkpICsNCiAgZ2d0aXRsZSgiTGlrZWxpaG9vZCBEaXN0cmlidXRpb24iKQ0KfQ0KDQpwbG90X3Bvc3Rlcmlvcl9wcm9iX2Rpc3RyIDwtIGZ1bmN0aW9uKHBvc3Rlcmlvcl9kZiwgdGhldGFfdmFscykgew0KICBwb3N0ZXJpb3JfZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHRoZXRhLCB5ID0gcG9zdF9wcm9iKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3NlZ21lbnQoYWVzKHggPSB0aGV0YSwgeGVuZCA9IHRoZXRhLCB5ID0gcG9zdF9wcm9iLCB5ZW5kID0gMCkpICsNCiAgeGxhYihleHByZXNzaW9uKHRoZXRhKSkgKw0KICB5bGFiKGV4cHJlc3Npb24ocGFzdGUoIlAoIiwgdGhldGEsICJ8RCkiKSkpICsNCiAgZ2d0aXRsZSgiUG9zdGVyaW9yIERpc3RyaWJ1dGlvbiIpDQp9DQoNCmNpIDwtIGZ1bmN0aW9uKHgsIHB4KXsgICMgRnVuY3Rpb24gY3JlYXRlZCB1c2luZyBodHRwczovL3N0YXRzLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy8yNDA3NDkvaG93LXRvLWZpbmQtOTUtY3JlZGlibGUtaW50ZXJ2YWwNCg0KICB4eCA8LSBzZXEobWluKHgpLCBtYXgoeCksIGJ5ID0gMC4wNSkNCg0KICAjIGludGVycG9sYXRlIGZ1bmN0aW9uIGZyb20gdGhlIHNhbXBsZQ0KICBmeCA8LSBzcGxpbmVmdW4oeCwgcHgpICMgaW50ZXJwb2xhdGluZyBmdW5jdGlvbg0KICBweHggPC0gcG1heCgwLCBmeCh4eCkpICMgbm9ybWFsaXplIHNvIHByb2IgPjANCg0KICAjIHNhbXBsZSBmcm9tIHRoZSAiZW1waXJpY2FsIiBkaXN0cmlidXRpb24NCiAgc2FtcCA8LSBzYW1wbGUoeHgsIDFlNSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBweHgpDQoNCiAgIyBhbmQgdGFrZSBzYW1wbGUgcXVhbnRpbGVzDQogIHF1YW50aWxlKHNhbXAsIGMoMC4wMjUsIDAuOTc1KSkgDQoNCiAgY3B4eCA8LSBjdW1zdW0ocHh4KSAvIHN1bShweHgpDQogIHh4W3doaWNoKGNweHggPj0gMC4wMjUpWzFdXSAgICMgbG93ZXIgYm91bmRhcnkNCiAgeHhbd2hpY2goY3B4eCA+PSAwLjk3NSlbMV0tMV0gIyB1cHBlciBib3VuZGFyeQ0KDQogIHJldHVybihjKHh4W3doaWNoKGNweHggPj0gMC4wMjUpWzFdXSx4eFt3aGljaChjcHh4ID49IDAuOTc1KVsxXS0xXSkpICAgIyBsb3dlciBib3VuZGFyeSwgdXBwZXINCg0KfQ0KI1JlYWQgbW9yZSBhYm91dCB0aGVzZSEgaHR0cDovL3RpbnloZWVyby5naXRodWIuaW8vMjAxNy8wMy8wOC9ob3ctdG8tYmF5ZXNpYW4taW5mZXItMTAxLmh0bWwNCmBgYA0KDQpgYGB7ciAtIFByaW9yc30NCnRoZXRhX3ZhbHMgPC0gc2VxKDAsIDEsIDAuMDUpICMgU2V0cyB0aGUgcmVzb2x1dGlvbiBvZiB0aGUgZGlzdHJvYnV0aW9uIGZvciB0aGV0YSAuMDAxIGZvciB0aGUgcHJldHRpZXN0IHBpY3R1cmUsIGJ1dCB3YXkgbW9yZSBjb21wdXRhdGlvbmFsIHBvd2VyDQp0aGV0YV9wcmlvcl9kaXN0cl9kZiA8LSBnZXRfcHJpb3JfZGlzdHIodGhldGFfdmFscykgI1NldHVwIHRoZSBkYXRhZnJhbWUgZm9yIHByaW9yDQpgYGANCg0KYGBge3J9DQpsaWtlbGlob29kX2RmIDwtIGdldF9saWtlbGlob29kX2RmKHRoZXRhX3ZhbHMsIDAsIDEwKSAjIyAwIHN1Y2Nlc3NlcywgMTAgZmFpbHVyZXMNCnBvc3Rlcmlvcl9kZiA8LSBnZXRfcG9zdGVyaW9yX2RmKGxpa2VsaWhvb2RfZGYsIHRoZXRhX3ByaW9yX2Rpc3RyX2RmKQ0KcGxvdF9wcmlvcl9kaXN0cih0aGV0YV9wcmlvcl9kaXN0cl9kZikNCnBsb3RfbGlrZWxpaG9vZF9wcm9iX2Rpc3RyKGxpa2VsaWhvb2RfZGYpDQpwbG90X3Bvc3Rlcmlvcl9wcm9iX2Rpc3RyKHBvc3Rlcmlvcl9kZiwgdGhldGFfdmFscykNCmBgYA0KDQpgYGB7cn0NCnRlc3RzYW1wbGUgPC0gc2FtcGxlKHBvc3Rlcmlvcl9kZiR0aGV0YSwgMSwgcHJvYiA9IHBvc3Rlcmlvcl9kZiRwb3N0X3Byb2IsIHJlcGxhY2U9VFJVRSkNCnRlc3RzYW1wbGUgKiAxMyANCmBgYA0KDQoNCmBgYHtyfQ0KcG9zdGVyaW9yX2RmDQoNCmNpKHBvc3Rlcmlvcl9kZiR0aGV0YSwgcG9zdGVyaW9yX2RmJHBvc3RfcHJvYikNCg0KYGBgDQoNCmBgYHtyIC0gTG9hZGluZyBpbiBwcmlvciBlbGVjdGlvbiBpbmZvfQ0KYWxsID0gYDE5NzYuMjAxNi5wcmVzaWRlbnRgIA0KcHJlejEgPSBzdWJzZXQoYWxsLCBwYXJ0eSA9PSAnZGVtb2NyYXQnICYgd3JpdGVpbj09RkFMU0UgJiB5ZWFyPj0yMDAwIHwgcGFydHkgPT0gJ3JlcHVibGljYW4nICYgd3JpdGVpbj09RkFMU0UgJiB5ZWFyPj0yMDAwIHwgcGFydHkgPT0gJ2RlbW9jcmF0aWMtZmFybWVyLWxhYm9yJyAmIHdyaXRlaW49PUZBTFNFICYgeWVhcj49MjAwMCkNCnByZXpkID0gc3Vic2V0KHByZXoxLCBwYXJ0eSA9PSAnZGVtb2NyYXQnICYgd3JpdGVpbj09RkFMU0UgfCBwYXJ0eSA9PSAnZGVtb2NyYXRpYy1mYXJtZXItbGFib3InICYgd3JpdGVpbj09RkFMU0UpDQpwcmV6ciA9IHN1YnNldChwcmV6MSwgcGFydHkgPT0gJ3JlcHVibGljYW4nICYgd3JpdGVpbj09RkFMU0UpDQoNCndpbjIwMDAgPC0gbGlzdCgpDQpmb3IgKGkgaW4gMToyNTUpew0KICBpZiAocHJlenJbaSwxMV0gPCBwcmV6ZFtpLDExXSkgew0KICB3aW4yMDAwIDwtIGMod2luMjAwMCwgMSkNCiAgfSBlbHNlIHsNCiAgd2luMjAwMCA8LWMod2luMjAwMCwgMCkNCiAgfQ0KfQ0KZGYgPC0gZGF0YS5mcmFtZShtYXRyaXgodW5saXN0KHdpbjIwMDApLCBucm93PTUsIG5jb2w9NTEsIGJ5cm93PVQpKQ0KZGZ0b3RhbCA8LSBjb2xTdW1zKGRmLCBuYS5ybSA9IFQpDQpkZnRvdGFsDQpgYGANCg0KDQpgYGB7ciAtIEFjdHVhbGx5IFdvcmtpbmcgd2l0aCBhIGxpc3R9DQpwb2xsX2RmID0gYHBvbGxkYXRhLjExLjI2YA0KDQpwb3N0bWFzdGVyID0gbGlzdCgpDQpwb3N0cmFuZ2UgPSBsaXN0KCkNCg0KZm9yIChpIGluIDE6bnJvdyhwb2xsX2RmKSl7ICNSZXBlYXQgdGhpcyBsb29wIHRoZSBudW1iZXIgb2YgaXRlbXMgaW4gbXkgbGlzdC4gTm90ZSB0aGF0IGl0IHNob3VsZCBhbHdheXMgYmUgNTEgc2luY2UgSSBoYXZlIDUxICJzdGF0ZXMiDQogZHdpbiA9IHBvbGxfZGZbaSwyXSArIGRmdG90YWxbaV0gDQogZGxvc3MgPSBwb2xsX2RmW2ksM10gKyA2IC1wb2xsX2RmW2ksMl0gLSBkZnRvdGFsW2ldDQogDQogbGlrZWxpaG9vZF9kZiA8LSBnZXRfbGlrZWxpaG9vZF9kZih0aGV0YV92YWxzLCBkd2luICwgZGxvc3MpDQogcG9zdGVyaW9yX2RmIDwtIGdldF9wb3N0ZXJpb3JfZGYobGlrZWxpaG9vZF9kZiwgdGhldGFfcHJpb3JfZGlzdHJfZGYpDQogDQogcG9zdG1hc3RlcnRlbXAgPC0gZGF0YS5mcmFtZShpLCB0KHNhcHBseShwb3N0ZXJpb3JfZGZbd2hpY2gubWF4KHBvc3Rlcmlvcl9kZiRwb3N0X3Byb2IpLF0kdGhldGEsYykpKQ0KIHBvc3RtYXN0ZXIgPC1yYmluZChwb3N0bWFzdGVyLCBwb3N0bWFzdGVydGVtcCkNCg0KICNDb2xsZWN0aW5nIENJcyBhbmQgcmVhcnJhbmdpbmcgdGhlbSBpbnRvIGEgZGF0YSBmcmFtZQ0KIGNpX2V0aTwtY2kocG9zdGVyaW9yX2RmJHRoZXRhLCBwb3N0ZXJpb3JfZGYkcG9zdF9wcm9iKQ0KIHBvc3RyYW5nZXRlbXAgPC0gZGF0YS5mcmFtZSh0KHNhcHBseShjaV9ldGksYykpKQ0KIHBvc3RyYW5nZSA8LXJiaW5kKHBvc3RyYW5nZSwgcG9zdHJhbmdldGVtcCkNCn0NCmNvbG5hbWVzKHBvc3RtYXN0ZXIpIDwtIGMoInN0YXRlIiwgIm1vc3RsaWtlbHl0aGV0YSIpDQpjb2xuYW1lcyhwb3N0cmFuZ2UpIDwtIGMoImxvdyIsICJoaWdoIikNCnBvc3RtYXN0ZXIkc3RhdGUgPC0gc3RhdGVwb3AkZnVsbCAjIGdpdmluZyBzdGF0ZSBudW1iZXJzIHRoZWlyIG5hbWUuIE5lZWRlZCBvbmx5IGZvciBtYXBwaW5nIHdpdGggdXNtYXANCnBvc3RyYW5nZQ0KDQpgYGANCg0KYGBge3IgcGxvdHRpbmcgb3VyIGRhdGEgd2l0aCBDSX0NCnBvc3RtYXN0ZXIlPiVnZ3Bsb3QoYWVzKDE6NTEsIG1vc3RsaWtlbHl0aGV0YSkpKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49cG9zdHJhbmdlJGxvdywgeW1heD1wb3N0cmFuZ2UkaGlnaCksIHdpZHRoPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSgwLjA1KSkrDQogIGxhYnModGl0bGUgPSAiQmlkZW4gdnMuIFRydW1wIiwgeSA9ICJCaWRlbiBDaGFuY2Ugb2YgVmljdG9yeSIsIHggPSAiU3RhdGUiKQ0KDQpgYGANCg0KDQpgYGB7ciAtIFRha2VuIGxhcmdlbHkgZnJvbSBodHRwczovL3NvY3Zpei5jby9tYXBzLmh0bWx9DQpwbG90X3VzbWFwKGRhdGEgPSBwb3N0bWFzdGVyLCB2YWx1ZXMgPSAibW9zdGxpa2VseXRoZXRhIiwgY29sb3IgPSAiYmxhY2siKSArIA0KICBzY2FsZV9maWxsX2dyYWRpZW50KG5hbWUgPSAiQ2hhbmNlIG9mIEJpZGVuIFdpbiIsIGxvdyA9ICJ3aGl0ZSIsIGhpZ2ggPSAiYmx1ZSIpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQ0KYGBgDQoNCg0KYGBge3J9DQpzdGF0ZXZvdGUgPSBgc3RhdGV2b3RlYA0KY29sbmFtZXMoc3RhdGV2b3RlKSA8LSBjKCJzdGF0ZSIsInZvdGUiKQ0KDQpwb3N0bWFzdGVyID0gbGlzdCgpDQpwb3N0cmFuZ2UgPSBsaXN0KCkNCnNhbXBsZW1hc3RlciA9IGxpc3QoKQ0KZm9yIChpIGluIDE6MTAwMCl7DQogIHNhbXBsZXRlbXAyID0gbGlzdCgpDQogIGZvciAoaSBpbiAxOm5yb3cocG9sbF9kZikpeyAjUmVwZWF0IHRoaXMgbG9vcCB0aGUgbnVtYmVyIG9mIGl0ZW1zIGluIG15IGxpc3QuIE5vdGUgdGhhdCBpdCBzaG91bGQgYWx3YXlzIGJlIDUxIHNpbmNlIEkgaGF2ZSA1MSAic3RhdGVzIg0KICAgIGR3aW4gPSBwb2xsX2RmW2ksMl0gKyBkZnRvdGFsW2ldIA0KICAgIGRsb3NzID0gcG9sbF9kZltpLDNdICsgNiAtcG9sbF9kZltpLDJdIC0gZGZ0b3RhbFtpXQ0KIA0KICAgIGxpa2VsaWhvb2RfZGYgPC0gZ2V0X2xpa2VsaWhvb2RfZGYodGhldGFfdmFscywgZHdpbiAsIGRsb3NzKQ0KICAgIHBvc3Rlcmlvcl9kZiA8LSBnZXRfcG9zdGVyaW9yX2RmKGxpa2VsaWhvb2RfZGYsIHRoZXRhX3ByaW9yX2Rpc3RyX2RmKQ0KICAgIHNhbXBsZXRlbXAxIDwtIHN0YXRldm90ZSR2b3RlW2ldKnNhbXBsZShwb3N0ZXJpb3JfZGYkdGhldGEsIDEsIHByb2IgPSBwb3N0ZXJpb3JfZGYkcG9zdF9wcm9iLCByZXBsYWNlPVRSVUUpDQogICAgc2FtcGxldGVtcDIgPC1yYmluZChzYW1wbGV0ZW1wMiwgc2FtcGxldGVtcDEpDQogICAgDQogIH0NCiAgICANCiAgc2FtcGxlbWFzdGVyIDwtIHJiaW5kKHNhbXBsZW1hc3RlcixzdW0oYXMubnVtZXJpYyhzYW1wbGV0ZW1wMikpKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KZCA8LSBkZW5zaXR5KGFzLm51bWVyaWMoc2FtcGxlbWFzdGVyKSkNCnBsb3QoZCwgbWFpbiA9ICJQcm9iYWJpbGl0eSBvZiBCaWRlbiBTdWNjZXNzIikNCmBgYA0KDQpgYGB7cn0NCg0KbWVhbihhcy5udW1lcmljKHNhbXBsZW1hc3RlcikgPiAyNzApDQoNCmBgYA0KDQoNCg0KDQoNCg==