Miscellaneous analyses using raw Pew data. See Chapter 2 in Regression and Other Stories.


Load packages

library("rprojroot")
root<-has_file(".ROS-Examples-root")$make_fix_file()
library("foreign")

Load data

pew_pre <- read.dta(root("Pew/data","pew_research_center_june_elect_wknd_data.dta"))
n <- nrow(pew_pre)

Glance data

table(pew_pre[,"date"])

 61808  61908  62008  62108  62208  62308  62408  62508  62608  62708  62808 
   228    422    340    412    376    442    420    280    370    258    334 
 62908  72308  72408  72508  72608  72708  73108  80108  80208  80308  80408 
   126    484    942    502    654    424    360    584    508    478    524 
 80508  80608  80708  80808  80908  81008  81108  90908  91008  91108  91208 
   742    410    532    560    540    540     32    614   1420   1184    976 
 91308  91408  92708  92808  92908 100908 101008 101108 101208 101308 101608 
   970    800   1498   1246    266    376    384    433    285      7    874 
101708 101808 101908 102308 102408 102508 102608 102908 103008 103108 110108 
   922    843    377    535    527    400     38    873    867    864    798 
which_question <- ifelse(!is.na(pew_pre$heat2), 2, ifelse (!is.na(pew_pre$heat4), 4, 0))
table(pew_pre$date, which_question)
        which_question
            0    2    4
  61808    26  202    0
  61908    96  326    0
  62008    66  274    0
  62108    94  318    0
  62208    82  294    0
  62308    96  346    0
  62408    82  338    0
  62508    68  212    0
  62608    90  280    0
  62708    64  194    0
  62808    60  274    0
  62908    36   90    0
  72308    84  400    0
  72408   140  802    0
  72508    86  416    0
  72608   112  542    0
  72708   102  322    0
  73108    42  318    0
  80108    86  498    0
  80208    92  416    0
  80308    70  408    0
  80408    82  442    0
  80508   134  608    0
  80608    92  318    0
  80708    90  442    0
  80808   120  440    0
  80908    90  450    0
  81008    74  466    0
  81108    10   22    0
  90908    80  534    0
  91008   182 1238    0
  91108   202  982    0
  91208   172  804    0
  91308   148  822    0
  91408   162  638    0
  92708   250 1248    0
  92808   210 1036    0
  92908    34  232    0
  100908   46  330    0
  101008   55  329    0
  101108   47  386    0
  101208   58  227    0
  101308    1    6    0
  101608  114  760    0
  101708  124  798    0
  101808  114  729    0
  101908   65  312    0
  102308   66    0  469
  102408   55    0  472
  102508   47    0  353
  102608    7    0   31
  102908    0    0  873
  103008    0    0  867
  103108    0    0  864
  110108    0    0  798

Create vote intention variable "rvote" using variables heat2 and heat4 from Pew

numeric_heat2 <- as.numeric(pew_pre$heat2)
numeric_heat4 <- as.numeric(pew_pre$heat4)
rvote <- rep (NA, n)
for (i in 1:n){
  if (which_question[i]==2){
    rvote[i] <- ifelse(numeric_heat2[i]==1, 1,
                 ifelse(numeric_heat2[i]==2, 0, NA))
  }
  else if (which_question[i]==4){
    rvote[i] <- ifelse(numeric_heat4[i]==1, 1,
                 ifelse(numeric_heat4[i]==2, 0, NA))
  }
}

Certain to have registered to vote?

registered <- ifelse(pew_pre$regicert=="absolutely certain", 1, 0)
registered[is.na(registered)] <- 0

Date

early <- pew_pre$date < 90008
late <- pew_pre$date > 90008
month <- floor(pew_pre$date/10000)
day <- floor(pew_pre$date/100) - 100*month
day.numeric <- month*31 + day
poll.id <- ifelse (month==6, 1,
             ifelse (month==7 & day<28, 2,
               ifelse ((month==7 & day>=28) | month==8, 3,
                 ifelse (month==9 & day<16, 4,
                   ifelse (month==9 & day>=16, 5,
                     ifelse (month==10 & day<14, 6,
                       ifelse (month==10 & day>=14 & day<20, 7,
                         ifelse (month==10 & day>=20 & day<27, 8, 9))))))))
n.poll.id <- max(poll.id)

State (1-51, in alfa order, including DC)

stnum <- as.numeric(pew_pre$state)

Identify out DC

state.abb.long <- c(state.abb[1:8], "DC", state.abb[9:50])
dc <- state.abb.long[stnum]=="DC"

Votes

votes08 <- c(60,39, 62,36, 54,45, 58,39, 40,59, 46,53, 39,60, 37,62, 7,93, 49,51, 53,46, 25,74, 61,36, 38,61, 49,50, 45,54, 57,42, 58,41, 59,40, 40,58, 39,60, 36,62, 42,56, 44,54, 57,43, 49,49, 50,47, 57,41, 41,57, 44,55, 42,57, 42,57, 37,62, 49,50, 53,45, 47,51, 66,34, 42,56, 44,55, 35,63, 54,45, 54,44, 57,42, 55,44, 62,35, 32,67, 48,52, 43,56, 56,43, 43,56, 65,33)
obama08 <- votes08[seq(2,102,2)]
mccain08 <- votes08[seq(1,101,2)]
ovote.actual <- obama08/(obama08+mccain08)
stnum <- as.numeric(pew_pre$state)

Weight

pop.weight0 <- pew_pre$weight
voter.weight0 <- ifelse(is.na(rvote) | registered==0, NA, pop.weight0)
pop.weight <- rep(NA, length(pop.weight0))
voter.weight <- rep(NA, length(voter.weight0))
for (i in 1:n.poll.id){
  ok <- poll.id==i
  pop.weight[ok] <- pop.weight0[ok]/mean(pop.weight0[ok])
  voter.weight[ok] <- voter.weight0[ok]/mean(voter.weight0[ok],na.rm=TRUE)
}
voter.weight1 <- rep(1, length(voter.weight0))
for (i in 1:51){
  ok <- stnum==i
  if (sum(ok)>10){
    sum.d <- sum(voter.weight[ok & rvote==0], na.rm=TRUE)
    sum.r <- sum(voter.weight[ok & rvote==1], na.rm=TRUE)
    ovote.sample <- sum.d/(sum.d+sum.r)
    voter.weight1[ok & rvote==0] <- ovote.actual[i]/ovote.sample
    voter.weight1[ok & rvote==1] <- (1-ovote.actual[i])/(1-ovote.sample)
  }
}
voter.weight2 <- voter.weight*voter.weight1

Income (1-9 scale)

inc <- as.numeric(pew_pre$income)
inc[inc==10] <- NA
value.inc <- c(5,15,25,35,45,62.5,87.5,125,200)
n.inc <- max(inc, na.rm=TRUE)

Party id

pid0 <- as.numeric(pew_pre[,"party"])
lean0 <- as.numeric(pew_pre[,"partyln"])
pid <- ifelse(pid0==2, 5,  # Republican
         ifelse(pid0==3, 1,  # Democrat
         ifelse(lean0==2, 4, # Lean Republican
         ifelse(lean0==4, 2, # Lean Democrat
         3)))) # Independent
#1=Dem, 2=Lean Dem, 2=Ind, 4=Lean Rep, 5=Repub
pid.label <- c("Democrat", "Lean Dem.", "Independent", "Lean Rep.", "Republican")
n.pid <- max(pid, na.rm=TRUE)

Ideology

ideology0 <- as.numeric(pew_pre[,"ideo"])
ideology <- ifelse(ideology0==2, 5, # Very conservative
              ifelse(ideology0==3, 4, # Conservative
              ifelse(ideology0==6, 1, # Very liberal
              ifelse(ideology0==5, 2, # Liberal
              3)))) # Moderate
ideology.label <- c("Very liberal", "Liberal", "Moderate", "Conservative", "Very conservative")
n.ideology <- max(ideology, na.rm=TRUE)
par(mar=c(3,2,2.5,1), mgp=c(1.5,.7,0), tck=-.01)
plot(c(1,n.inc), c(0,1), xaxs="i", yaxs="i", type="n", xlab="", ylab="", xaxt="n", yaxt="n")
axis(1, 1:n.inc, rep("",n.inc))
axis(1, seq(1.5,n.inc-.5,length=3), c("Low income", "Middle income", "High income"), tck=0)
axis(2, c(0,.5,1), c(0,"50%","100%"))
center <- floor((1+n.inc)/2)
incprop <- array(NA, c(n.pid+1,n.inc))
incprop[n.pid+1,] <- 1
for (i in 1:n.pid){
  for (j in 1:n.inc){
    incprop[i,j] <- weighted.mean((pid<i)[inc==j], pop.weight0[inc==j], na.rm=TRUE)
  }
}
for (i in 1:n.pid){
  polygon(c(1:n.inc, n.inc:1), c(incprop[i,], rev(incprop[i+1,])), col=paste("gray", 40+10*i, sep=""))
  lines(1:n.inc, incprop[i,])
  text(center, mean(incprop[c(i,i+1),center]), pid.label[i])
}
mtext("Self-declared party identification, by income", side=3, line=1, cex=1.2)

par(mar=c(3,2,2.5,1), mgp=c(1.5,.7,0), tck=-.01)
plot(c(1,n.inc), c(0,1), xaxs="i", yaxs="i", type="n", xlab="", ylab="", xaxt="n", yaxt="n")
axis(1, 1:n.inc, rep("",n.inc))
axis(1, seq(1.5,n.inc-.5,length=3), c("Low income", "Middle income", "High income"), tck=0)
axis(2, c(0,.5,1), c(0,"50%","100%"))
center <- floor((1+n.inc)/2)
incprop <- array(NA, c(n.ideology+1,n.inc))
incprop[n.ideology+1,] <- 1
for (i in 1:n.ideology){
  for (j in 1:n.inc){
    incprop[i,j] <- weighted.mean((ideology<i)[inc==j], pop.weight0[inc==j], na.rm=TRUE)
  }
}
for (i in 1:n.ideology){
  polygon(c(1:n.inc, n.inc:1), c(incprop[i,], rev(incprop[i+1,])), col=paste("gray", 40+10*i, sep=""))
  lines(1:n.inc, incprop[i,])
  text(center, mean(incprop[c(i,i+1),center]), ideology.label[i])
}
mtext("Self-declared political ideology, by income", side=3, line=1, cex=1.2)

Recoded religious attendance (relatt) to 1-5 scale

relatt <- 7 - as.numeric(pew_pre$attend)
relatt[relatt==0] <- NA
relatt <- ifelse(relatt==1|relatt==2, 1,
            ifelse(relatt==3, 2,
              ifelse(relatt==4, 3,
                ifelse(relatt==5, 4,
                  ifelse(relatt==6, 5, NA)))))
n.relatt <- max(relatt, na.rm=TRUE)
relatt.label <- c("Nonattenders","Rare attenders","Occasional\nattenders","Frequent attenders","Very frequent\nchurch attenders")

Categories

pid2 <- ifelse(pid==1, 1, ifelse(pid==5, 3, 2))
ideology2 <- ifelse(ideology==1|ideology==2, 1, ifelse(ideology==3, 2, 3))
pid2.label <- c("Democrats", "Independents", "Republicans")
ideology2.label <- c("Liberal", "Moderate", "Conservative")
prop <- array(NA, c(3,3,n.inc))
for (i in 1:3){
  for (j in 1:3){
     for (k in 1:n.inc){
       prop[i,j,k] <- weighted.mean(pid2==i & ideology2==j & inc==k, pop.weight, na.rm=TRUE)
     }
   }
}
par(mfrow=c(3,3), oma=c(0,0,2.5,0))
par(mar=c(2,2,4,0), mgp=c(1.5,.7,0), tck=-.01)
for (i in 1:3){
  for (j in 1:3){
      plot(1:n.inc, prop[i,j,], type="l", bty="l", xaxs="i", yaxs="i", ylim=c(0,max(prop)),
           xaxt="n", yaxt="n", xlab="", ylab="")
    axis(1, 1:n.inc, rep("",n.inc))
    axis(1, seq(2.7,n.inc-1.7,length=2), c("Low income", "High income"), tck=0, cex.axis=1.2)
    axis(2, c(0,.01,.02), c("0","1%","2%"), cex.axis=1.2)
    mtext(paste(ideology2.label[j], pid2.label[i]), side=3, line=1, cex=.9)
  }
}
mtext("Income distributions within self-reported political categories in 2008",
      outer=TRUE, side=3, line=.5, cex=1.2)

LS0tCnRpdGxlOiAiUmVncmVzc2lvbiBhbmQgT3RoZXIgU3RvcmllczogUGV3IgphdXRob3I6ICJBbmRyZXcgR2VsbWFuLCBKZW5uaWZlciBIaWxsLCBBa2kgVmVodGFyaSIKZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IHJlYWRhYmxlCiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQpNaXNjZWxsYW5lb3VzIGFuYWx5c2VzIHVzaW5nIHJhdyBQZXcgZGF0YS4gU2VlIENoYXB0ZXIgMiBpbgpSZWdyZXNzaW9uIGFuZCBPdGhlciBTdG9yaWVzLgoKLS0tLS0tLS0tLS0tLQoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNvbW1lbnQ9TkEpCiMgc3dpdGNoIHRoaXMgdG8gVFJVRSB0byBzYXZlIGZpZ3VyZXMgaW4gc2VwYXJhdGUgZmlsZXMKc2F2ZWZpZ3MgPC0gRkFMU0UKYGBgCgojIyMjIExvYWQgcGFja2FnZXMKCmBgYHtyIH0KbGlicmFyeSgicnByb2pyb290IikKcm9vdDwtaGFzX2ZpbGUoIi5ST1MtRXhhbXBsZXMtcm9vdCIpJG1ha2VfZml4X2ZpbGUoKQpsaWJyYXJ5KCJmb3JlaWduIikKYGBgCgojIyMjIExvYWQgZGF0YQoKYGBge3IgfQpwZXdfcHJlIDwtIHJlYWQuZHRhKHJvb3QoIlBldy9kYXRhIiwicGV3X3Jlc2VhcmNoX2NlbnRlcl9qdW5lX2VsZWN0X3drbmRfZGF0YS5kdGEiKSkKbiA8LSBucm93KHBld19wcmUpCmBgYAoKIyMjIyBHbGFuY2UgZGF0YQoKYGBge3IgfQp0YWJsZShwZXdfcHJlWywiZGF0ZSJdKQp3aGljaF9xdWVzdGlvbiA8LSBpZmVsc2UoIWlzLm5hKHBld19wcmUkaGVhdDIpLCAyLCBpZmVsc2UgKCFpcy5uYShwZXdfcHJlJGhlYXQ0KSwgNCwgMCkpCnRhYmxlKHBld19wcmUkZGF0ZSwgd2hpY2hfcXVlc3Rpb24pCmBgYAoKIyMjIyBDcmVhdGUgdm90ZSBpbnRlbnRpb24gdmFyaWFibGUgInJ2b3RlIiB1c2luZyB2YXJpYWJsZXMgaGVhdDIgYW5kIGhlYXQ0IGZyb20gUGV3CgpgYGB7ciB9Cm51bWVyaWNfaGVhdDIgPC0gYXMubnVtZXJpYyhwZXdfcHJlJGhlYXQyKQpudW1lcmljX2hlYXQ0IDwtIGFzLm51bWVyaWMocGV3X3ByZSRoZWF0NCkKcnZvdGUgPC0gcmVwIChOQSwgbikKZm9yIChpIGluIDE6bil7CiAgaWYgKHdoaWNoX3F1ZXN0aW9uW2ldPT0yKXsKICAgIHJ2b3RlW2ldIDwtIGlmZWxzZShudW1lcmljX2hlYXQyW2ldPT0xLCAxLAogICAgICAgICAgICAgICAgIGlmZWxzZShudW1lcmljX2hlYXQyW2ldPT0yLCAwLCBOQSkpCiAgfQogIGVsc2UgaWYgKHdoaWNoX3F1ZXN0aW9uW2ldPT00KXsKICAgIHJ2b3RlW2ldIDwtIGlmZWxzZShudW1lcmljX2hlYXQ0W2ldPT0xLCAxLAogICAgICAgICAgICAgICAgIGlmZWxzZShudW1lcmljX2hlYXQ0W2ldPT0yLCAwLCBOQSkpCiAgfQp9CmBgYAoKIyMjIyBDZXJ0YWluIHRvIGhhdmUgcmVnaXN0ZXJlZCB0byB2b3RlPwoKYGBge3IgfQpyZWdpc3RlcmVkIDwtIGlmZWxzZShwZXdfcHJlJHJlZ2ljZXJ0PT0iYWJzb2x1dGVseSBjZXJ0YWluIiwgMSwgMCkKcmVnaXN0ZXJlZFtpcy5uYShyZWdpc3RlcmVkKV0gPC0gMApgYGAKCkRhdGUKCmBgYHtyIH0KZWFybHkgPC0gcGV3X3ByZSRkYXRlIDwgOTAwMDgKbGF0ZSA8LSBwZXdfcHJlJGRhdGUgPiA5MDAwOAptb250aCA8LSBmbG9vcihwZXdfcHJlJGRhdGUvMTAwMDApCmRheSA8LSBmbG9vcihwZXdfcHJlJGRhdGUvMTAwKSAtIDEwMCptb250aApkYXkubnVtZXJpYyA8LSBtb250aCozMSArIGRheQpwb2xsLmlkIDwtIGlmZWxzZSAobW9udGg9PTYsIDEsCiAgICAgICAgICAgICBpZmVsc2UgKG1vbnRoPT03ICYgZGF5PDI4LCAyLAogICAgICAgICAgICAgICBpZmVsc2UgKChtb250aD09NyAmIGRheT49MjgpIHwgbW9udGg9PTgsIDMsCiAgICAgICAgICAgICAgICAgaWZlbHNlIChtb250aD09OSAmIGRheTwxNiwgNCwKICAgICAgICAgICAgICAgICAgIGlmZWxzZSAobW9udGg9PTkgJiBkYXk+PTE2LCA1LAogICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKG1vbnRoPT0xMCAmIGRheTwxNCwgNiwKICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKG1vbnRoPT0xMCAmIGRheT49MTQgJiBkYXk8MjAsIDcsCiAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKG1vbnRoPT0xMCAmIGRheT49MjAgJiBkYXk8MjcsIDgsIDkpKSkpKSkpKQpuLnBvbGwuaWQgPC0gbWF4KHBvbGwuaWQpCmBgYAoKU3RhdGUgKDEtNTEsIGluIGFsZmEgb3JkZXIsIGluY2x1ZGluZyBEQykKCmBgYHtyIH0Kc3RudW0gPC0gYXMubnVtZXJpYyhwZXdfcHJlJHN0YXRlKQpgYGAKCklkZW50aWZ5IG91dCBEQwoKYGBge3IgfQpzdGF0ZS5hYmIubG9uZyA8LSBjKHN0YXRlLmFiYlsxOjhdLCAiREMiLCBzdGF0ZS5hYmJbOTo1MF0pCmRjIDwtIHN0YXRlLmFiYi5sb25nW3N0bnVtXT09IkRDIgpgYGAKClZvdGVzCgpgYGB7ciB9CnZvdGVzMDggPC0gYyg2MCwzOSwgNjIsMzYsIDU0LDQ1LCA1OCwzOSwgNDAsNTksIDQ2LDUzLCAzOSw2MCwgMzcsNjIsIDcsOTMsIDQ5LDUxLCA1Myw0NiwgMjUsNzQsIDYxLDM2LCAzOCw2MSwgNDksNTAsIDQ1LDU0LCA1Nyw0MiwgNTgsNDEsIDU5LDQwLCA0MCw1OCwgMzksNjAsIDM2LDYyLCA0Miw1NiwgNDQsNTQsIDU3LDQzLCA0OSw0OSwgNTAsNDcsIDU3LDQxLCA0MSw1NywgNDQsNTUsIDQyLDU3LCA0Miw1NywgMzcsNjIsIDQ5LDUwLCA1Myw0NSwgNDcsNTEsIDY2LDM0LCA0Miw1NiwgNDQsNTUsIDM1LDYzLCA1NCw0NSwgNTQsNDQsIDU3LDQyLCA1NSw0NCwgNjIsMzUsIDMyLDY3LCA0OCw1MiwgNDMsNTYsIDU2LDQzLCA0Myw1NiwgNjUsMzMpCm9iYW1hMDggPC0gdm90ZXMwOFtzZXEoMiwxMDIsMildCm1jY2FpbjA4IDwtIHZvdGVzMDhbc2VxKDEsMTAxLDIpXQpvdm90ZS5hY3R1YWwgPC0gb2JhbWEwOC8ob2JhbWEwOCttY2NhaW4wOCkKc3RudW0gPC0gYXMubnVtZXJpYyhwZXdfcHJlJHN0YXRlKQpgYGAKCldlaWdodAoKYGBge3IgfQpwb3Aud2VpZ2h0MCA8LSBwZXdfcHJlJHdlaWdodAp2b3Rlci53ZWlnaHQwIDwtIGlmZWxzZShpcy5uYShydm90ZSkgfCByZWdpc3RlcmVkPT0wLCBOQSwgcG9wLndlaWdodDApCnBvcC53ZWlnaHQgPC0gcmVwKE5BLCBsZW5ndGgocG9wLndlaWdodDApKQp2b3Rlci53ZWlnaHQgPC0gcmVwKE5BLCBsZW5ndGgodm90ZXIud2VpZ2h0MCkpCmZvciAoaSBpbiAxOm4ucG9sbC5pZCl7CiAgb2sgPC0gcG9sbC5pZD09aQogIHBvcC53ZWlnaHRbb2tdIDwtIHBvcC53ZWlnaHQwW29rXS9tZWFuKHBvcC53ZWlnaHQwW29rXSkKICB2b3Rlci53ZWlnaHRbb2tdIDwtIHZvdGVyLndlaWdodDBbb2tdL21lYW4odm90ZXIud2VpZ2h0MFtva10sbmEucm09VFJVRSkKfQp2b3Rlci53ZWlnaHQxIDwtIHJlcCgxLCBsZW5ndGgodm90ZXIud2VpZ2h0MCkpCmZvciAoaSBpbiAxOjUxKXsKICBvayA8LSBzdG51bT09aQogIGlmIChzdW0ob2spPjEwKXsKICAgIHN1bS5kIDwtIHN1bSh2b3Rlci53ZWlnaHRbb2sgJiBydm90ZT09MF0sIG5hLnJtPVRSVUUpCiAgICBzdW0uciA8LSBzdW0odm90ZXIud2VpZ2h0W29rICYgcnZvdGU9PTFdLCBuYS5ybT1UUlVFKQogICAgb3ZvdGUuc2FtcGxlIDwtIHN1bS5kLyhzdW0uZCtzdW0ucikKICAgIHZvdGVyLndlaWdodDFbb2sgJiBydm90ZT09MF0gPC0gb3ZvdGUuYWN0dWFsW2ldL292b3RlLnNhbXBsZQogICAgdm90ZXIud2VpZ2h0MVtvayAmIHJ2b3RlPT0xXSA8LSAoMS1vdm90ZS5hY3R1YWxbaV0pLygxLW92b3RlLnNhbXBsZSkKICB9Cn0Kdm90ZXIud2VpZ2h0MiA8LSB2b3Rlci53ZWlnaHQqdm90ZXIud2VpZ2h0MQpgYGAKCkluY29tZSAoMS05IHNjYWxlKQoKYGBge3IgfQppbmMgPC0gYXMubnVtZXJpYyhwZXdfcHJlJGluY29tZSkKaW5jW2luYz09MTBdIDwtIE5BCnZhbHVlLmluYyA8LSBjKDUsMTUsMjUsMzUsNDUsNjIuNSw4Ny41LDEyNSwyMDApCm4uaW5jIDwtIG1heChpbmMsIG5hLnJtPVRSVUUpCmBgYAoKUGFydHkgaWQKCmBgYHtyIH0KcGlkMCA8LSBhcy5udW1lcmljKHBld19wcmVbLCJwYXJ0eSJdKQpsZWFuMCA8LSBhcy5udW1lcmljKHBld19wcmVbLCJwYXJ0eWxuIl0pCnBpZCA8LSBpZmVsc2UocGlkMD09MiwgNSwgICMgUmVwdWJsaWNhbgogICAgICAgICBpZmVsc2UocGlkMD09MywgMSwgICMgRGVtb2NyYXQKICAgICAgICAgaWZlbHNlKGxlYW4wPT0yLCA0LCAjIExlYW4gUmVwdWJsaWNhbgogICAgICAgICBpZmVsc2UobGVhbjA9PTQsIDIsICMgTGVhbiBEZW1vY3JhdAogICAgICAgICAzKSkpKSAjIEluZGVwZW5kZW50CiMxPURlbSwgMj1MZWFuIERlbSwgMj1JbmQsIDQ9TGVhbiBSZXAsIDU9UmVwdWIKcGlkLmxhYmVsIDwtIGMoIkRlbW9jcmF0IiwgIkxlYW4gRGVtLiIsICJJbmRlcGVuZGVudCIsICJMZWFuIFJlcC4iLCAiUmVwdWJsaWNhbiIpCm4ucGlkIDwtIG1heChwaWQsIG5hLnJtPVRSVUUpCmBgYAoKSWRlb2xvZ3kKCmBgYHtyIH0KaWRlb2xvZ3kwIDwtIGFzLm51bWVyaWMocGV3X3ByZVssImlkZW8iXSkKaWRlb2xvZ3kgPC0gaWZlbHNlKGlkZW9sb2d5MD09MiwgNSwgIyBWZXJ5IGNvbnNlcnZhdGl2ZQogICAgICAgICAgICAgIGlmZWxzZShpZGVvbG9neTA9PTMsIDQsICMgQ29uc2VydmF0aXZlCiAgICAgICAgICAgICAgaWZlbHNlKGlkZW9sb2d5MD09NiwgMSwgIyBWZXJ5IGxpYmVyYWwKICAgICAgICAgICAgICBpZmVsc2UoaWRlb2xvZ3kwPT01LCAyLCAjIExpYmVyYWwKICAgICAgICAgICAgICAzKSkpKSAjIE1vZGVyYXRlCmlkZW9sb2d5LmxhYmVsIDwtIGMoIlZlcnkgbGliZXJhbCIsICJMaWJlcmFsIiwgIk1vZGVyYXRlIiwgIkNvbnNlcnZhdGl2ZSIsICJWZXJ5IGNvbnNlcnZhdGl2ZSIpCm4uaWRlb2xvZ3kgPC0gbWF4KGlkZW9sb2d5LCBuYS5ybT1UUlVFKQoKYGBgCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmlmIChzYXZlZmlncykgcGRmKHJvb3QoIlBldy9maWdzIiwicGlkLnBkZiIpLCBoZWlnaHQ9NC41LCB3aWR0aD01LjUsIGNvbG9ybW9kZWw9ImdyYXkiKQpgYGAKYGBge3IgfQpwYXIobWFyPWMoMywyLDIuNSwxKSwgbWdwPWMoMS41LC43LDApLCB0Y2s9LS4wMSkKcGxvdChjKDEsbi5pbmMpLCBjKDAsMSksIHhheHM9ImkiLCB5YXhzPSJpIiwgdHlwZT0ibiIsIHhsYWI9IiIsIHlsYWI9IiIsIHhheHQ9Im4iLCB5YXh0PSJuIikKYXhpcygxLCAxOm4uaW5jLCByZXAoIiIsbi5pbmMpKQpheGlzKDEsIHNlcSgxLjUsbi5pbmMtLjUsbGVuZ3RoPTMpLCBjKCJMb3cgaW5jb21lIiwgIk1pZGRsZSBpbmNvbWUiLCAiSGlnaCBpbmNvbWUiKSwgdGNrPTApCmF4aXMoMiwgYygwLC41LDEpLCBjKDAsIjUwJSIsIjEwMCUiKSkKY2VudGVyIDwtIGZsb29yKCgxK24uaW5jKS8yKQppbmNwcm9wIDwtIGFycmF5KE5BLCBjKG4ucGlkKzEsbi5pbmMpKQppbmNwcm9wW24ucGlkKzEsXSA8LSAxCmZvciAoaSBpbiAxOm4ucGlkKXsKICBmb3IgKGogaW4gMTpuLmluYyl7CiAgICBpbmNwcm9wW2ksal0gPC0gd2VpZ2h0ZWQubWVhbigocGlkPGkpW2luYz09al0sIHBvcC53ZWlnaHQwW2luYz09al0sIG5hLnJtPVRSVUUpCiAgfQp9CmZvciAoaSBpbiAxOm4ucGlkKXsKICBwb2x5Z29uKGMoMTpuLmluYywgbi5pbmM6MSksIGMoaW5jcHJvcFtpLF0sIHJldihpbmNwcm9wW2krMSxdKSksIGNvbD1wYXN0ZSgiZ3JheSIsIDQwKzEwKmksIHNlcD0iIikpCiAgbGluZXMoMTpuLmluYywgaW5jcHJvcFtpLF0pCiAgdGV4dChjZW50ZXIsIG1lYW4oaW5jcHJvcFtjKGksaSsxKSxjZW50ZXJdKSwgcGlkLmxhYmVsW2ldKQp9Cm10ZXh0KCJTZWxmLWRlY2xhcmVkIHBhcnR5IGlkZW50aWZpY2F0aW9uLCBieSBpbmNvbWUiLCBzaWRlPTMsIGxpbmU9MSwgY2V4PTEuMikKYGBgCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmlmIChzYXZlZmlncykgZGV2Lm9mZigpCgpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBwZGYocm9vdCgiUGV3L2ZpZ3MiLCJpZGVvbG9neS5wZGYiKSwgaGVpZ2h0PTQuNSwgd2lkdGg9NS41LCBjb2xvcm1vZGVsPSJncmF5IikKYGBgCmBgYHtyIH0KcGFyKG1hcj1jKDMsMiwyLjUsMSksIG1ncD1jKDEuNSwuNywwKSwgdGNrPS0uMDEpCnBsb3QoYygxLG4uaW5jKSwgYygwLDEpLCB4YXhzPSJpIiwgeWF4cz0iaSIsIHR5cGU9Im4iLCB4bGFiPSIiLCB5bGFiPSIiLCB4YXh0PSJuIiwgeWF4dD0ibiIpCmF4aXMoMSwgMTpuLmluYywgcmVwKCIiLG4uaW5jKSkKYXhpcygxLCBzZXEoMS41LG4uaW5jLS41LGxlbmd0aD0zKSwgYygiTG93IGluY29tZSIsICJNaWRkbGUgaW5jb21lIiwgIkhpZ2ggaW5jb21lIiksIHRjaz0wKQpheGlzKDIsIGMoMCwuNSwxKSwgYygwLCI1MCUiLCIxMDAlIikpCmNlbnRlciA8LSBmbG9vcigoMStuLmluYykvMikKaW5jcHJvcCA8LSBhcnJheShOQSwgYyhuLmlkZW9sb2d5KzEsbi5pbmMpKQppbmNwcm9wW24uaWRlb2xvZ3krMSxdIDwtIDEKZm9yIChpIGluIDE6bi5pZGVvbG9neSl7CiAgZm9yIChqIGluIDE6bi5pbmMpewogICAgaW5jcHJvcFtpLGpdIDwtIHdlaWdodGVkLm1lYW4oKGlkZW9sb2d5PGkpW2luYz09al0sIHBvcC53ZWlnaHQwW2luYz09al0sIG5hLnJtPVRSVUUpCiAgfQp9CmZvciAoaSBpbiAxOm4uaWRlb2xvZ3kpewogIHBvbHlnb24oYygxOm4uaW5jLCBuLmluYzoxKSwgYyhpbmNwcm9wW2ksXSwgcmV2KGluY3Byb3BbaSsxLF0pKSwgY29sPXBhc3RlKCJncmF5IiwgNDArMTAqaSwgc2VwPSIiKSkKICBsaW5lcygxOm4uaW5jLCBpbmNwcm9wW2ksXSkKICB0ZXh0KGNlbnRlciwgbWVhbihpbmNwcm9wW2MoaSxpKzEpLGNlbnRlcl0pLCBpZGVvbG9neS5sYWJlbFtpXSkKfQptdGV4dCgiU2VsZi1kZWNsYXJlZCBwb2xpdGljYWwgaWRlb2xvZ3ksIGJ5IGluY29tZSIsIHNpZGU9MywgbGluZT0xLCBjZXg9MS4yKQpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBkZXYub2ZmKCkKYGBgCgpSZWNvZGVkIHJlbGlnaW91cyBhdHRlbmRhbmNlIChyZWxhdHQpIHRvIDEtNSBzY2FsZQoKYGBge3IgfQpyZWxhdHQgPC0gNyAtIGFzLm51bWVyaWMocGV3X3ByZSRhdHRlbmQpCnJlbGF0dFtyZWxhdHQ9PTBdIDwtIE5BCnJlbGF0dCA8LSBpZmVsc2UocmVsYXR0PT0xfHJlbGF0dD09MiwgMSwKICAgICAgICAgICAgaWZlbHNlKHJlbGF0dD09MywgMiwKICAgICAgICAgICAgICBpZmVsc2UocmVsYXR0PT00LCAzLAogICAgICAgICAgICAgICAgaWZlbHNlKHJlbGF0dD09NSwgNCwKICAgICAgICAgICAgICAgICAgaWZlbHNlKHJlbGF0dD09NiwgNSwgTkEpKSkpKQpuLnJlbGF0dCA8LSBtYXgocmVsYXR0LCBuYS5ybT1UUlVFKQpyZWxhdHQubGFiZWwgPC0gYygiTm9uYXR0ZW5kZXJzIiwiUmFyZSBhdHRlbmRlcnMiLCJPY2Nhc2lvbmFsXG5hdHRlbmRlcnMiLCJGcmVxdWVudCBhdHRlbmRlcnMiLCJWZXJ5IGZyZXF1ZW50XG5jaHVyY2ggYXR0ZW5kZXJzIikKYGBgCgpDYXRlZ29yaWVzCgpgYGB7ciB9CnBpZDIgPC0gaWZlbHNlKHBpZD09MSwgMSwgaWZlbHNlKHBpZD09NSwgMywgMikpCmlkZW9sb2d5MiA8LSBpZmVsc2UoaWRlb2xvZ3k9PTF8aWRlb2xvZ3k9PTIsIDEsIGlmZWxzZShpZGVvbG9neT09MywgMiwgMykpCnBpZDIubGFiZWwgPC0gYygiRGVtb2NyYXRzIiwgIkluZGVwZW5kZW50cyIsICJSZXB1YmxpY2FucyIpCmlkZW9sb2d5Mi5sYWJlbCA8LSBjKCJMaWJlcmFsIiwgIk1vZGVyYXRlIiwgIkNvbnNlcnZhdGl2ZSIpCnByb3AgPC0gYXJyYXkoTkEsIGMoMywzLG4uaW5jKSkKZm9yIChpIGluIDE6Myl7CiAgZm9yIChqIGluIDE6Myl7CiAgICAgZm9yIChrIGluIDE6bi5pbmMpewogICAgICAgcHJvcFtpLGosa10gPC0gd2VpZ2h0ZWQubWVhbihwaWQyPT1pICYgaWRlb2xvZ3kyPT1qICYgaW5jPT1rLCBwb3Aud2VpZ2h0LCBuYS5ybT1UUlVFKQogICAgIH0KICAgfQp9CgpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KcG5nKCJwaWRpZGVvbG9neS5wbmciLCBoZWlnaHQ9NTAwLCB3aWR0aD00NTApCmBgYApgYGB7ciB9CnBhcihtZnJvdz1jKDMsMyksIG9tYT1jKDAsMCwyLjUsMCkpCnBhcihtYXI9YygyLDIsNCwwKSwgbWdwPWMoMS41LC43LDApLCB0Y2s9LS4wMSkKZm9yIChpIGluIDE6Myl7CiAgZm9yIChqIGluIDE6Myl7CiAgICAgIHBsb3QoMTpuLmluYywgcHJvcFtpLGosXSwgdHlwZT0ibCIsIGJ0eT0ibCIsIHhheHM9ImkiLCB5YXhzPSJpIiwgeWxpbT1jKDAsbWF4KHByb3ApKSwKICAgICAgICAgICB4YXh0PSJuIiwgeWF4dD0ibiIsIHhsYWI9IiIsIHlsYWI9IiIpCiAgICBheGlzKDEsIDE6bi5pbmMsIHJlcCgiIixuLmluYykpCiAgICBheGlzKDEsIHNlcSgyLjcsbi5pbmMtMS43LGxlbmd0aD0yKSwgYygiTG93IGluY29tZSIsICJIaWdoIGluY29tZSIpLCB0Y2s9MCwgY2V4LmF4aXM9MS4yKQogICAgYXhpcygyLCBjKDAsLjAxLC4wMiksIGMoIjAiLCIxJSIsIjIlIiksIGNleC5heGlzPTEuMikKICAgIG10ZXh0KHBhc3RlKGlkZW9sb2d5Mi5sYWJlbFtqXSwgcGlkMi5sYWJlbFtpXSksIHNpZGU9MywgbGluZT0xLCBjZXg9LjkpCiAgfQp9Cm10ZXh0KCJJbmNvbWUgZGlzdHJpYnV0aW9ucyB3aXRoaW4gc2VsZi1yZXBvcnRlZCBwb2xpdGljYWwgY2F0ZWdvcmllcyBpbiAyMDA4IiwKICAgICAgb3V0ZXI9VFJVRSwgc2lkZT0zLCBsaW5lPS41LCBjZXg9MS4yKQpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KaWYgKHNhdmVmaWdzKSBkZXYub2ZmKCkKYGBgCgo=