This is an R Notebook which reproduces the analysis, tables and figures of the working paper "MetaMetaZipf. What do analyses of city size distributions have in common?", as of August 2020. The data is stored on the MetaZipf GitHub repository.

Importing Data from the metaZipf project:

refs <- read.csv2("data/zipf_refs.csv", sep=';')
cites <- read.csv2("data/zipf_cites.csv", sep=',')
data <- read.csv2("data/zipf_meta.csv", sep=",", dec=".")
cname <- "data/FullText/"
docs <- Corpus(DirSource(cname))   
J2D <- read.csv2("data/journals2Disciplines.csv", sep=';')

Cleaning citation data

cites_out <- cites[67:1221,]
cites_out$YEAR <- as.numeric(gsub("\\D+", "", cites_out$REFID))
cites_out$JOURNAL <- gsub(".*\\d.", "", cites_out$REFID)
cites_out$AUTHOR <- gsub("\\d.*", "", cites_out$REFID)
cites_out$JOURNAL <- gsub("[[:punct:]]", " ", cites_out$JOURNAL)
cites_out$AUTHOR <- gsub("[[:punct:]]", " ", cites_out$AUTHOR)
cites_out <- data.frame(cites_out,J2D[match(cites_out$JOURNAL, J2D$JOURNAL),])
cites_out$DISCIPLINE <- cites_out$DISCPLINE
cites_out$DISCPLINE <- NULL
cites_out$JOURNAL.1 <- NULL
cites <- rbind(cites[1:66,],cites_out)
cites[is.na(cites)] <- 0
cites_within <- cites[1:66,c(1,6:71)]
head(cites)

Corpus analysis

j <- cites[1:66,1:5]
j$n <- 1
journals <- aggregate(j[,"n"], by=list(j[,"JOURNAL"]), FUN = sum)
disciplines <- aggregate(j[,"n"], by=list(j[,"DISCIPLINE"]), FUN = sum)
q <- ggplot(journals, aes(x= Group.1, y = x))
 q + geom_lollipop(aes(reorder( Group.1, -x)),color = "orangered", cex=1) +
  coord_flip() +
  labs(x="Journal", y="Number of articles in the corpus")

rownames(cites_within) <- cites_within$REFID
cites_within$REFID <- NULL
cmat <- t(as.matrix(cites_within))
c <- colSums(cmat)
co <- c[order(-c)]
ref <- names(co)
cope <- data.frame(ref, co)
cope_full_names <- data.frame(cope, cites[match(cope$ref, cites$REFID),c("AUTHOR", "YEAR", "JOURNAL")])
cope_full_names$ref <- paste(cope_full_names$AUTHOR, cope_full_names$YEAR, sep=" ")

par(mar = c(2,2,2,2))
q <- ggplot(cope_full_names, aes(x=ref, y = co))
q + geom_lollipop(aes(reorder(ref, -co)),color = "seagreen3", cex=1) +
  coord_flip() +
  labs(x="Reference", y="Number of in-citations from the corpus")

age_journals <- data.frame(aggregate(j[,"YEAR"], by=list(j[,"JOURNAL"]), FUN = mean), journals$x)
age_disciplines <- data.frame(aggregate(j[,"YEAR"], by=list(j[,"DISCIPLINE"]), FUN = mean), disciplines$x)
rownames(age_disciplines) = age_disciplines$Group.1
rownames(age_journals) = age_journals$Group.1
age_disciplines$Group.1 <- NULL
age_journals$Group.1 <- NULL
colnames(age_disciplines) <- c("mean age", "n articles")
colnames(age_journals) <- c("mean age", "n articles")
round(mean(j$YEAR), digit=0)
[1] 2004
round(age_disciplines, digit=0)
corpussummary <- data.frame(j, cope[match(j$REFID, cope$ref),])
colnames(corpussummary)[8] <- "in_citations"
mean(corpussummary[corpussummary$in_citations > 10, "YEAR"])
[1] 1998.3

External citation analysis

cites_out <- cites[67:1221,]
cites_out$n_cites <- rowSums(cites_out[,6:71])
single_outcites <- cites_out[order(-cites_out$n_cites),c(1:5,72)] 
s_outcites <- single_outcites[,c("REFID", "n_cites")]
colnames(s_outcites) <- c("ref", "n")
s_outcites <- subset(s_outcites[-100,], n>=5)
q <- ggplot(s_outcites, aes(x=ref, y = n))
q + geom_lollipop(aes(reorder(ref, -n)),color = "coral3", cex=1) +
  coord_flip() +
  labs(x="Reference", y="Number of citations from the corpus (>=5)")

Who cited Nitsch (2005)?

who <- cites_out[cites_out$REFID == "Nitsch_2005_Journal_Urban_Economics",6:71]
who[1,]

Who did not cite G. K. Zipf himself?

nozipf<- as.data.frame(colSums(cites_out[cites_out$REFID %in% c("Zipf_1941_Unity_disunity",
                                                                "Zipf_1949_Human_Behavior_Principle_Least_Effort"),6:71]))
colnames(nozipf) <- "ref_zipf"
nozipf$ref_zipf <- ifelse(nozipf$ref_zipf == 0 , "no ref to zipf", "ref to zipf")
nozipf$REFID <- rownames(nozipf)
cites_for_ref_zipfs <- cites[1:66,]
referencing_zipf <- data.frame(cites_for_ref_zipfs, nozipf[match(cites_for_ref_zipfs$REFID, nozipf$REFID),])
rfczpf <- referencing_zipf[,c("YEAR", "DISCIPLINE", "ref_zipf")]

q <- ggplot(rfczpf, aes(x=YEAR))
q + geom_histogram(aes(y = stat(density), color = ref_zipf, fill = ref_zipf), 
                   alpha = 0.4, position = "identity", binwidth = 1) +
  geom_density(aes(color = ref_zipf), size = 1) +
  scale_color_manual(values = c("Coral2", "dodgerblue3")) +
scale_fill_manual(values = c("Coral2", "dodgerblue3"))  + labs(color = "") + guides(fill = FALSE, size = FALSE)+ theme(legend.position = "top")

table(rfczpf$ref_zipf, rfczpf$DISCIPLINE)
                
                    ECO GEO PHY REG OTHER STAT
  no ref to zipf  0  11   5   0  10     0    0
  ref to zipf     0  12   8   4  16     0    0

Which are the authors cited from Urban Studies?

cites_out[cites_out$JOURNAL == "Urban Studies","AUTHOR"]
 [1] Alperovich                     Batten                         Begg                           Bergsman Greenston Healy      
 [5] Boddy                          Chen Fu Zhang                  Cheshire Carbonaro             Clark Stabler                 
 [9] Ettlinger                      Garmestani Allen Gallagher al  Garmestani Allen Gallagher al  Hsu                           
[13] Huzinec                        Kuiper Kuiper Paelink          Lanaspa Pueyo Sans             Lipshitz                      
[17] Marshall                       Ogawa                          Parr                           Parr Suzuki                   
[21] Resende                        SuarezVilla                    Thompson                       VonBoventer                   
[25] Xu Zhu                         Zhao Zhang                     <NA>                          
987 Levels:  Alperovich G. Amalraj V. C. & Subbarayan A. Anderson G. & Ge Y. Aragon J. A. O. & Queiroz V. Arribas-Bel D. et al. ... Zipf 

Size of bibliography of corpus articles

n_citations <- as.data.frame(colSums(cites_out[,6:71], na.rm=T))
colnames(n_citations) <- "n_citations"
n_citations$REFID <- rownames(n_citations)
n_citations_corpus <- data.frame(cites_for_ref_zipfs, n_citations[match(cites_for_ref_zipfs$REFID, n_citations$REFID),])
n_citations_corpus$ref <- paste(n_citations_corpus$AUTHOR, n_citations_corpus$YEAR, sep=" ")

q <- ggplot(n_citations_corpus, aes(x=ref, y = n_citations))
q + geom_lollipop(aes(reorder(ref, -n_citations)),color = "dodgerblue3", cex=1) +
  coord_flip() +
  labs(x="Reference", y="Size of bibliography by corpus article")

Most cited external aticles

jou_out <- as.data.frame(table(cites_out$JOURNAL))
jou_out <- jou_out[order(-jou_out$Freq),] 
colnames(jou_out) <- c("ref", "n")
jou <- subset(jou_out[-100,], n>=5)
q <- ggplot(jou, aes(x=ref, y = n))
q + geom_lollipop(aes(reorder(ref, -n)),color = "goldenrod3", cex=1) +
  coord_flip() +
  labs(x="Journal", y="Number of citations from the corpus (>=5)")

Construction of the citation similarity network

outcitemat <- as.matrix(cites_out[,6:71])
toutcitemat <- t(outcitemat)
refSim <- rownames(toutcitemat)
cosSim <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
    k <- k + 1
    cosSim[k,1] <- i
    cosSim[k,2] <- j
    vi <- toutcitemat[i,]
    vj <- toutcitemat[j,]
    cosSim[k,3] <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
    }
  }
}
colnames(cosSim) <- c('i', 'j', 'cosSim')
write.csv(cosSim[order(-cosSim$cosSim),], "simNets/SimilarCitations.csv")

summary(cosSim$cosSim)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
0.00000 0.00000 0.04550 0.06399 0.10020 0.48670 
cs.cit <- cosSim[cosSim$cosSim >= 0.25,]
g.cit <- graph_from_data_frame(cs.cit, directed=F)

citingNs <- as.data.frame(apply(toutcitemat[rownames(toutcitemat) %in% V(g.cit)$name,],1, FUN = norm_vec))
colnames(citingNs) <- "citingN"
citingNs$ref <- rownames(citingNs)
orderedName <- data.frame(V(g.cit)$name)
citingN <- data.frame(orderedName, citingNs[match(orderedName$V.g.cit..name, citingNs$ref),])[,"citingN"]
citingN <- citingN[!is.na(citingN)] 

par(mar = c(0,0,0,0))
clln.cit <- cluster_louvain(g.cit)
layout <- layout_nicely(g.cit,2)
g.cit$layout <- layout
plot(g.cit, edge.width = sqrt(cs.cit$cosSim) * 2, vertex.size = citingN,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.cit))

Construction of the discipline similarity network

discipline2ref <- aggregate(cites_out[,c(6:71)], by=list(cites_out$DISCIPLINE), FUN = sumNum)
rownames(discipline2ref) <- discipline2ref$Group.1
discipline2ref$Group.1 <- NULL
cols <- colnames(discipline2ref)
for(i in cols){
  absolute <- discipline2ref[,i]
  total <- sum(absolute)
  relative <- absolute/total
  discipline2ref[,paste0("freq_",i)] <- relative
}

disc2ref <- as.matrix(discipline2ref[,67:132])
colnames(disc2ref) <- cols
scaled_disc2ref <- disc2ref / colSums(disc2ref)
tdisc2ref <- t(disc2ref)

refSim <- rownames(tdisc2ref)
cosSim <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      cosSim[k,1] <- i
      cosSim[k,2] <- j
      vi <- tdisc2ref[i,]
      vj <- tdisc2ref[j,]
      cosSim[k,3] <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
    }
  }
}
colnames(cosSim) <- c('i', 'j', 'cosSim')
write.csv(cosSim[order(-cosSim$cosSim),], "simNets/SimilarDisciplinesCited_rel.csv")
summary(cosSim$cosSim)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
0.07909 0.61930 0.79130 0.73710 0.88950 0.99690 
cs.cit <- cosSim[cosSim$cosSim >= 0.9,]
g.cit <- graph_from_data_frame(cs.cit, directed=F)

disCitedNs <- as.data.frame(apply(toutcitemat[rownames(tdisc2ref) %in% V(g.cit)$name,],1, FUN = norm_vec))
colnames(disCitedNs) <- "disCitedNs"
disCitedNs$ref <- rownames(disCitedNs)
orderedName <- data.frame(V(g.cit)$name)
disCitedNs <- data.frame(orderedName, disCitedNs[match(orderedName$V.g.cit..name, disCitedNs$ref),])[,"disCitedNs"]
disCitedNs <- disCitedNs[!is.na(disCitedNs)] 

colnames(orderedName) <- "REFID"
refinfo <- cites[1:66,c("REFID", "DISCIPLINE")]
own_discipline <- data.frame(orderedName, refinfo[match(orderedName$REFID, refinfo$REFID),])
odisc <- own_discipline$DISCIPLINE

layout <- layout_nicely(g.cit,2)
g.cit$layout <- layout
par(mar = c(0,0,0,0))
plot(g.cit, edge.width = sqrt(cs.cit$cosSim) * 2, vertex.size = disCitedNs,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = odisc)

Construction of full-text similarity network

docs <- tm_map(docs, toSpace, "-")
docs <- tm_map(docs, toSpace, ":")
docs <- tm_map(docs, toSpace, "'")
docs <- tm_map(docs, toSpace, "`")
docs <- tm_map(docs, toSpace, "‘")
docs <- tm_map(docs, toSpace, "_")
docs <- tm_map(docs, toSpace, "–")
docs <- tm_map(docs, toSpace, "/")
docs <- tm_map(docs, removePunctuation)
docs <- tm_map(docs, tolower)   
docs <- tm_map(docs, removeNumbers)   
docs <- tm_map(docs, removeWords, stopwords("english"))   
dtm <- DocumentTermMatrix(docs)   
dtm.m = as.matrix(dtm)
tdm <- TermDocumentMatrix(docs)   
tdm.m = as.matrix(tdm)

 tdm.df = as.data.frame(tdm.m)
 tdm.df.f <- tdm.df / colSums(tdm.df)

n_words <- as.data.frame(colSums(tdm.df, na.rm=T))
 colnames(n_words) <- "n_words"
 n_words$REFID <- substr(rownames(n_words), 1,8)
 n_words_corpus <- data.frame(cites_for_ref_zipfs, n_words[match(cites_for_ref_zipfs$REFID, n_words$REFID),])
 n_words_corpus$ref <- paste(n_words_corpus$AUTHOR, n_words_corpus$YEAR, sep=" ")
 n_words_corpus <- n_words_corpus[n_words_corpus$AUTHOR != "Krakover S.",]
 q <- ggplot(n_words_corpus, aes(x=ref, y = n_words))
 q + geom_lollipop(aes(reorder(ref, -n_words)),color = "seagreen4", cex=1) +
   coord_flip() +
   labs(x="Reference", y="Number of words by corpus article")

 termmat <- t(as.matrix(tdm.df.f))
 
 refSimTerm <- rownames(termmat)
 cosSimTerm <- data.frame()
 k=0
 ilist <- c()
 for(i in refSimTerm){
   ilist <- c(ilist, i)
   for(j in refSimTerm){
     if (j %!in% ilist){
       k <- k + 1
       cosSimTerm[k,1] <- i
       cosSimTerm[k,2] <- j
       vi <- termmat[i,]
       vj <- termmat[j,]
       cosSimTerm[k,3] <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
     }
   }
 }
 colnames(cosSimTerm) <- c('i', 'j', 'cosSimTerm')
 write.csv(cosSimTerm[order(-cosSimTerm$cosSimTerm),], "simNets/SimilarWording.csv")
 summary(cosSimTerm)
      i                  j               cosSimTerm    
 Length:2145        Length:2145        Min.   :0.1229  
 Class :character   Class :character   1st Qu.:0.3685  
 Mode  :character   Mode  :character   Median :0.4741  
                                       Mean   :0.4747  
                                       3rd Qu.:0.5777  
                                       Max.   :0.8728  
 cs <- cosSimTerm[cosSimTerm$cosSimTerm > 0.7,]
 g.term <- graph_from_data_frame(cs, directed=F)
 totalTerm <- as.data.frame(apply(termmat[rownames(termmat) %in% V(g.term)$name,],1, FUN = norm_vec))
 colnames(totalTerm) <- "totalTerms"
 totalTerm$ref <- rownames(totalTerm)
 orderedName <- data.frame(V(g.term)$name)
 totalTerms <- data.frame(orderedName, totalTerm[match(orderedName$V.g.term..name, totalTerm$ref),])[,"totalTerms"]
 totalTerms <- totalTerms[!is.na(totalTerms)] 
 clln.term <- cluster_louvain(g.term)
 layout <- layout_nicely(g.term,2)
 g.term$layout <- layout
 par(mar = c(0,0,0,0))
 plot(g.term, edge.width = sqrt(cs$cosSimTerm) * 2, vertex.size = totalTerms *50,
      vertex.label.cex = 0.7,  
      edge.curved=.2, vertex.color = membership(clln.term))

Construction country similarity network

  paperList <- colnames(cites_out[,6:71])
  countryData <- data[data$TERRITORY_TYPE == "Country" & data$REFID %in% paperList,]
country2Ref <- table(countryData$CNTR_ID, countryData$REFID)[-1,]
country2Ref.mat <- as.matrix(country2Ref[rowSums(country2Ref)>0,colnames(country2Ref) %in% paperList])
country2Ref.mat[country2Ref.mat>0] <- 1
countrymat <- t(country2Ref.mat)

refSim <- rownames(countrymat)
cosSimC <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      cosSimC[k,1] <- i
      cosSimC[k,2] <- j
      vi <- countrymat[i,]
      vj <- countrymat[j,]
      s <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
      cosSimC[k,3] <- ifelse(!is.na(s), s, 0)
    }
  }
}
colnames(cosSimC) <- c('i', 'j', 'cosSimC')
write.csv(cosSimC[order(-cosSimC$cosSimC),], "simNets/SimilarCountries.csv")
summary(cosSimC)
      i                  j                cosSimC       
 Length:2080        Length:2080        Min.   :0.00000  
 Class :character   Class :character   1st Qu.:0.00000  
 Mode  :character   Mode  :character   Median :0.00000  
                                       Mean   :0.09676  
                                       3rd Qu.:0.00000  
                                       Max.   :1.00000  
cs.cntr <- cosSimC[cosSimC$cosSimC >= 0.2,]
g.cntr <- graph_from_data_frame(cs.cntr, directed=F)
countryN <- as.data.frame(apply(countrymat[rownames(countrymat) %in% V(g.cntr)$name,],1, FUN = norm_vec))
colnames(countryN) <- "n_countries"
countryN$ref <- rownames(countryN)
orderedName <- data.frame(V(g.cntr)$name)
orderedCountryN <- data.frame(orderedName, countryN[match(orderedName$V.g.cntr..name, countryN$ref),])[,"n_countries"]
orderedCountryN <- orderedCountryN[!is.na(orderedCountryN)] 
clln.cntr <- cluster_louvain(g.cntr)
layout <- layout_nicely(g.cntr,2)
g.cntr$layout <- layout
 par(mar = c(0,0,0,0))
 plot(g.cntr, edge.width = sqrt(cs.cntr$cosSimC) * 2, vertex.size = orderedCountryN * 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.cntr))

Construction city definition similarity network

cityData <- data[!is.na(data$URBANSCALE) & data$REFID %in% paperList,]
city2Ref <- table(cityData$URBANSCALE, cityData$REFID)[,]
city2Ref.mat <- as.matrix(city2Ref[rowSums(city2Ref)>0,colnames(city2Ref) %in% paperList])
city2Ref.mat[city2Ref.mat>0] <- 1
citymat <- t(city2Ref.mat)

refSim <- rownames(citymat)
cosSimCt <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      cosSimCt[k,1] <- i
      cosSimCt[k,2] <- j
      vi <- citymat[i,]
      vj <- citymat[j,]
      s <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj)) 
      cosSimCt[k,3] <- ifelse(!is.na(s), s, 0)
    }
  }
}
colnames(cosSimCt) <- c('i', 'j', 'cosSimCt')
write.csv(cosSimCt[order(-cosSimCt$cosSimCt),], "simNets/SimilarCities.csv")
summary(cosSimCt)
      i                  j                cosSimCt     
 Length:2080        Length:2080        Min.   :0.0000  
 Class :character   Class :character   1st Qu.:0.0000  
 Mode  :character   Mode  :character   Median :0.0000  
                                       Mean   :0.4247  
                                       3rd Qu.:1.0000  
                                       Max.   :1.0000  
cs.city <- cosSimCt[cosSimCt$cosSimCt >= 0.1,]

g.city <- graph_from_data_frame(cs.city, directed=F)
cityN <- as.data.frame(apply(citymat[rownames(citymat) %in% V(g.city)$name,],1, FUN = norm_vec))
colnames(cityN) <- "n_cities"
cityN$ref <- rownames(cityN)
orderedName <- data.frame(V(g.city)$name)
orderedcityN <- data.frame(orderedName, cityN[match(orderedName$V.g.city..name, cityN$ref),])[,"n_cities"]
orderedcityN <- orderedcityN[!is.na(orderedcityN)] 

clln.city <- cluster_louvain(g.city)
layout <- layout_nicely(g.city,2)
g.city$layout <- layout
 par(mar = c(0,0,0,0))
 plot(g.city, edge.width = sqrt(cs.city$cosSimCt) * 2, vertex.size = orderedcityN * 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.city))

Construction decade similarity network

decadeData <- data[!is.na(data$DATE) & data$REFID %in% paperList,]
decadeData$DECADE <- paste0(substr(as.character(decadeData$DATE), 1, 3), 0, "s")
decade2Ref <- table(decadeData$DECADE, decadeData$REFID)[,]
decade2Ref.mat <- as.matrix(decade2Ref[rowSums(decade2Ref)>0,colnames(decade2Ref) %in% paperList])
decade2Ref.mat[decade2Ref.mat>0] <- 1
decademat <- t(decade2Ref.mat)

refSim <- rownames(decademat)
cosSimCt <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      cosSimCt[k,1] <- i
      cosSimCt[k,2] <- j
      vi <- decademat[i,]
      vj <- decademat[j,]
      s <- (sumNum(vi * vj)) / (norm_vec(vi) *  norm_vec(vj))
      cosSimCt[k,3] <- ifelse(!is.na(s), s, 0)
    }
  }
}
colnames(cosSimCt) <- c('i', 'j', 'cosSimCt')
write.csv(cosSimCt[order(-cosSimCt$cosSimCt),], "simNets/SimilarDecades.csv")
summary(cosSimCt$cosSimCt)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.0000  0.3780  0.3639  0.5774  1.0000 
cs.decade <- cosSimCt[cosSimCt$cosSimCt >= 0.65,]

g.decade <- graph_from_data_frame(cs.decade, directed=F)
decadeN <- as.data.frame(apply(decademat[rownames(decademat) %in% V(g.decade)$name,],1, FUN = norm_vec))
colnames(decadeN) <- "n_decades"
decadeN$ref <- rownames(decadeN)
orderedName <- data.frame(V(g.decade)$name)
ordereddecadeN <- data.frame(orderedName, decadeN[match(orderedName$V.g.decade..name, decadeN$ref),])[,"n_decades"]
ordereddecadeN <- ordereddecadeN[!is.na(ordereddecadeN)]

clln.decade <- cluster_louvain(g.decade)
layout <- layout_nicely(g.decade,2)
g.decade$layout <- layout
par(mar = c(0,0,0,0))
plot(g.decade, edge.width = sqrt(cs.decade$cosSimCt) * 2, vertex.size = ordereddecadeN * 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.decade))

Construction of the networks of alpha similarity

alphaData <- data[!is.na(data$ALPHALOTKA) & data$REFID %in% paperList,]
alphaData$n <- 1
meanAlphaPerRef <- aggregate(alphaData[,"ALPHALOTKA"], by=list(alphaData$REFID), FUN=meanNum)
sdAlphaPerRef <- aggregate(alphaData[,"ALPHALOTKA"], by=list(alphaData$REFID), FUN=sdNum)
sdAlphaPerRef[is.na(sdAlphaPerRef$x),"x"] <- 0
nAlphaPerRef <- aggregate(alphaData[,"n"], by=list(alphaData$REFID), FUN=sumNum)

similarAlpha <- cbind(meanAlphaPerRef, sdAlphaPerRef, nAlphaPerRef)
rownames(similarAlpha) <- similarAlpha$Group.1
similarAlpha[,c(1,3, 5)] <- NULL
colnames(similarAlpha) <- c("meanAlpha", "sdAlpha", "nAlpha")

alphamat <- as.matrix(similarAlpha)

meanData <- mean(alphaData[,"ALPHALOTKA"])
sdData <- sd(alphaData[,"ALPHALOTKA"])
meanN <- mean(similarAlpha$nAlpha)

refSim <- rownames(alphamat)
diff_mean <- data.frame()
diff_sd <- data.frame()
diff_n <- data.frame()
k=0
ilist <- c()
for(i in refSim){
  ilist <- c(ilist, i)
  for(j in refSim){
    if (j %!in% ilist){
      k <- k + 1
      diff_mean[k,1] <- i
      diff_mean[k,2] <- j
      mi <- similarAlpha[i,1]
      mj <- similarAlpha[j,1]
      m <- abs((mi - mj) / meanData)
      diff_mean[k,3] <- m
      
      diff_sd[k,1] <- i
      diff_sd[k,2] <- j
      sdi <-similarAlpha[i,2]
      sdj <- similarAlpha[j,2]
      sd <- abs((sdi - sdj) / sdData)
      diff_sd[k,3] <- sd
      
      diff_n[k,1] <- i
      diff_n[k,2] <- j
      ni <-similarAlpha[i,3]
      nj <- similarAlpha[j,3]
      n <- abs((ni - nj) / meanN)
      diff_n[k,3] <- n
    }
  }
}

colnames(diff_mean) <- c('i', 'j', 'diff_mean')
write.csv(diff_mean[order(diff_mean$diff_mean),], "simNets/diff_mean.csv")
summary(diff_mean$diff_mean)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
0.0003241 0.0773200 0.1593000 0.2142000 0.2773000 1.2080000 
colnames(diff_sd) <- c('i', 'j', 'diff_sd')
write.csv(diff_sd[order(diff_sd$diff_sd),], "simNets/diff_sd.csv")
summary(diff_sd$diff_sd)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.1345  0.3152  0.4388  0.5466  3.1350 
colnames(diff_n) <- c('i', 'j', 'diff_n')
write.csv(diff_n[order(diff_n$diff_n),], "simNets/diff_n.csv")
summary(diff_n$diff_n)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.2305  0.6454  1.2150  1.3830  9.0820 

Similarity of mean alpha

cs.alpha <- diff_mean[diff_mean$diff_mean < 0.025,]
g.alpha <- graph_from_data_frame(cs.alpha, directed=F)
alphaM <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.alpha)$name,],1, FUN = norm_vec))
colnames(alphaM) <- "mean_alphas"
alphaM$ref <- rownames(alphaM)
orderedName <- data.frame(V(g.alpha)$name)
orderedalphaM <- data.frame(orderedName, alphaM[match(orderedName$V.g.alpha..name, alphaM$ref),])[,"mean_alphas"]
orderedalphaM <- orderedalphaM[!is.na(orderedalphaM)]
similarAlpha$REFID <- rownames(similarAlpha)
clln.alpha <- cluster_louvain(g.alpha)
layout <- layout_nicely(g.alpha,2)
g.alpha$layout <- layout

memb <- as.list(membership(clln.alpha))

vertexData <- data.frame(orderedREFID= names(membership(clln.alpha)))
vertexData <- data.frame(vertexData, similarAlpha[match(vertexData$orderedREFID, similarAlpha$REFID),])

for (r in vertexData$REFID){
  vertexData[vertexData$REFID == r,"memb_mean"] <- memb[r]
}

par(mar = c(0,0,0,0))
plot(g.alpha, edge.width = sqrt(cs.alpha$diff_mean) * 2, vertex.size = vertexData$meanAlpha^2 * 5,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.alpha))

# mean average value of alpha reported by group
aggregate(vertexData[,"meanAlpha"], by=list(vertexData$memb_mean), FUN=meanNum)

Similarity of sd alpha

cs.alpha <- diff_sd[diff_sd$diff_sd < 0.1,]
g.alpha <- graph_from_data_frame(cs.alpha, directed=F)
alphaSD <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.alpha)$name,],1, FUN = norm_vec))
colnames(alphaSD) <- "mean_sds"
alphaSD$ref <- rownames(alphaSD)
orderedName <- data.frame(V(g.alpha)$name)
orderedalphaSD <- data.frame(orderedName, alphaSD[match(orderedName$V.g.alpha..name, alphaSD$ref),])[,"mean_sds"]
orderedalphaSD <- orderedalphaSD[!is.na(orderedalphaSD)]

clln.alpha <- cluster_louvain(g.alpha)
layout <- layout_nicely(g.alpha,2)
g.alpha$layout <- layout

memb <- as.list(membership(clln.alpha))

vertexData <- data.frame(orderedREFID= names(membership(clln.alpha)))
vertexData <- data.frame(vertexData, similarAlpha[match(vertexData$orderedREFID, similarAlpha$REFID),])

for (r in vertexData$REFID){
  vertexData[vertexData$REFID == r,"memb_sd"] <- memb[r]
}

par(mar = c(0,0,0,0))
plot(g.alpha, edge.width = sqrt(cs.alpha$diff_sd) * 2, vertex.size = vertexData$sdAlpha * 50,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.alpha))

# mean average value of alpha reported by group
aggregate(vertexData[,"sdAlpha"], by=list(vertexData$memb_sd), FUN=meanNum)

Similarity of n alpha

cs.alpha <- diff_n[diff_n$diff_n < 0.1,]
g.alpha <- graph_from_data_frame(cs.alpha, directed=F)
alphaN <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.alpha)$name,],1, FUN = norm_vec))
colnames(alphaN) <- "mean_ns"
alphaN$ref <- rownames(alphaN)
orderedName <- data.frame(V(g.alpha)$name)
orderedalphaN <- data.frame(orderedName, alphaN[match(orderedName$V.g.alpha..name, alphaN$ref),])[,"mean_ns"]
orderedalphaN <- orderedalphaN[!is.na(orderedalphaN)]

clln.alpha <- cluster_louvain(g.alpha)
layout <- layout_nicely(g.alpha,2)
g.alpha$layout <- layout

memb <- as.list(membership(clln.alpha))

vertexData <- data.frame(orderedREFID= names(membership(clln.alpha)))
vertexData <- data.frame(vertexData, similarAlpha[match(vertexData$orderedREFID, similarAlpha$REFID),])

for (r in vertexData$REFID){
  vertexData[vertexData$REFID == r,"memb_n"] <- memb[r]
}

par(mar = c(0,0,0,0))
plot(g.alpha, edge.width = sqrt(cs.alpha$diff_n) * 2, vertex.size = vertexData$nAlpha * 0.4,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = membership(clln.alpha))

# mean average value of alpha reported by group
aggregate(vertexData[,"nAlpha"], by=list(vertexData$memb_n), FUN=meanNum)

Regression models of similarity in mean and sd alpha

Preparation of data

# import diff in alpha means
meanAlphaDyads <- read.csv2("simNets/diff_mean.csv", sep=",", stringsAsFactors = F)[,-1]
meanAlphaDyads$dyadID <- paste(meanAlphaDyads$i, meanAlphaDyads$j, sep = "_")
meanAlphaDyads$meanAlphaSim <- -as.numeric(meanAlphaDyads$diff_mean)
meanAlphaDyads[,1:3] <- NULL
DYADS <- meanAlphaDyads
DYAD_ID_order <- DYADS$dyadID

# import diff in alpha sd
sdAlphaDyads <- read.csv2("simNets/diff_sd.csv", sep=",", stringsAsFactors = F)[,-1]
sdAlphaDyads$dyadIJ <- paste(substr(sdAlphaDyads$i, 1, 8), 
                             substr(sdAlphaDyads$j, 1, 8), sep = "_")
sdAlphaDyads$dyadJI <- paste(substr(sdAlphaDyads$i, 1, 8), 
                             substr(sdAlphaDyads$j, 1, 8), sep = "_")
sdAlphaDyads$dyadID <- ifelse(sdAlphaDyads$dyadIJ %in% DYAD_ID_order, sdAlphaDyads$dyadIJ, sdAlphaDyads$dyadJI)

sdAlphaDyads$sdAlphaSim <- -as.numeric(sdAlphaDyads$diff_sd)
sdAlphaDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, sdAlphaDyads[match(DYADS$dyadID, sdAlphaDyads$dyadID),"sdAlphaSim"])

# import diff in n alpha 
nAlphaDyads <- read.csv2("simNets/diff_n.csv", sep=",", stringsAsFactors = F)[,-1]
nAlphaDyads$dyadIJ <- paste(substr(nAlphaDyads$i, 1, 8), 
                             substr(nAlphaDyads$j, 1, 8), sep = "_")
nAlphaDyads$dyadJI <- paste(substr(nAlphaDyads$i, 1, 8), 
                             substr(nAlphaDyads$j, 1, 8), sep = "_")
nAlphaDyads$dyadID <- ifelse(nAlphaDyads$dyadIJ %in% DYAD_ID_order, nAlphaDyads$dyadIJ, nAlphaDyads$dyadJI)

nAlphaDyads$nAlphaSim <- -as.numeric(nAlphaDyads$diff_n)
nAlphaDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, nAlphaDyads[match(DYADS$dyadID, nAlphaDyads$dyadID),"nAlphaSim"])

# import similarity in wording as explanation
wordingDyads <- read.csv2("simNets/SimilarWording.csv", sep=",", stringsAsFactors = F)[,-1]
head(wordingDyads)
wordingDyads$dyadIJ <- paste(substr(wordingDyads$i, 1, 8), 
                             substr(wordingDyads$j, 1, 8), sep = "_")
wordingDyads$dyadJI <- paste(substr(wordingDyads$i, 1, 8), 
                             substr(wordingDyads$j, 1, 8), sep = "_")
wordingDyads$dyadID <- ifelse(wordingDyads$dyadIJ %in% DYAD_ID_order, wordingDyads$dyadIJ, wordingDyads$dyadJI)

wordingDyads$wordingCosSim <- as.numeric(wordingDyads$cosSimTerm)
wordingDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, wordingDyads[match(DYADS$dyadID, wordingDyads$dyadID),"wordingCosSim"])

# import similarity in citation as explanation
citationDyads <- read.csv2("simNets/SimilarCitations.csv", sep=",", stringsAsFactors = F)[,-1]
citationDyads$dyadIJ <- paste(citationDyads$i, citationDyads$j, sep = "_")
citationDyads$dyadJI <- paste(citationDyads$j, citationDyads$i, sep = "_")
citationDyads$dyadID <- ifelse(citationDyads$dyadIJ %in% DYAD_ID_order, citationDyads$dyadIJ, citationDyads$dyadJI)
citationDyads$citationCosSim <- as.numeric(citationDyads$cosSim)
citationDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, citationDyads[match(DYADS$dyadID, citationDyads$dyadID),"citationCosSim"])

# import similarity in discipline as explanation
disciplineDyads <- read.csv2("simNets/SimilarDisciplinesCited_rel.csv", sep=",", stringsAsFactors = F)[,-1]
disciplineDyads$dyadIJ <- paste(disciplineDyads$i, disciplineDyads$j, sep = "_")
disciplineDyads$dyadJI <- paste(disciplineDyads$j, disciplineDyads$i, sep = "_")
disciplineDyads$dyadID <- ifelse(disciplineDyads$dyadIJ %in% DYAD_ID_order, disciplineDyads$dyadIJ, disciplineDyads$dyadJI)
disciplineDyads$disciplineCosSim <- as.numeric(disciplineDyads$cosSim)
disciplineDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, disciplineDyads[match(DYADS$dyadID, disciplineDyads$dyadID),"disciplineCosSim"])

# import similarity in countries studied as control
countryDyads <- read.csv2("simNets/SimilarCountries.csv", sep=",", stringsAsFactors = F)[,-1]
countryDyads$dyadIJ <- paste(countryDyads$i, countryDyads$j, sep = "_")
countryDyads$dyadJI <- paste(countryDyads$j, countryDyads$i, sep = "_")
countryDyads$dyadID <- ifelse(countryDyads$dyadIJ %in% DYAD_ID_order, countryDyads$dyadIJ, countryDyads$dyadJI)
countryDyads$countryCosSim <- as.numeric(countryDyads$cosSimC)
countryDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, countryDyads[match(DYADS$dyadID, countryDyads$dyadID),"countryCosSim"])

# import similarity in decades studied as control
decadeDyads <- read.csv2("simNets/SimilarDecades.csv", sep=",", stringsAsFactors = F)[,-1]
decadeDyads$dyadIJ <- paste(decadeDyads$i, decadeDyads$j, sep = "_")
decadeDyads$dyadJI <- paste(decadeDyads$j, decadeDyads$i, sep = "_")
decadeDyads$dyadID <- ifelse(decadeDyads$dyadIJ %in% DYAD_ID_order, decadeDyads$dyadIJ, decadeDyads$dyadJI)
decadeDyads$decadeCosSim <- as.numeric(decadeDyads$cosSimCt)
decadeDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, decadeDyads[match(DYADS$dyadID, decadeDyads$dyadID),"decadeCosSim"])

# import similarity in city definition used as control
cityDefDyads <- read.csv2("simNets/SimilarCities.csv", sep=",", stringsAsFactors = F)[,-1]
cityDefDyads$dyadIJ <- paste(cityDefDyads$i, cityDefDyads$j, sep = "_")
cityDefDyads$dyadJI <- paste(cityDefDyads$j, cityDefDyads$i, sep = "_")
cityDefDyads$dyadID <- ifelse(cityDefDyads$dyadIJ %in% DYAD_ID_order, cityDefDyads$dyadIJ, cityDefDyads$dyadJI)
cityDefDyads$cityDefCosSim <- as.numeric(cityDefDyads$cosSimCt)
cityDefDyads[,1:5] <- NULL
DYADS <- data.frame(DYADS, cityDefDyads[match(DYADS$dyadID, cityDefDyads$dyadID),"cityDefCosSim"])

colnames(DYADS) <- c("dyadID","meanAlphaSim", "sdAlphaSim", "nAlphaSim", 
                     "fullTextCosSim", "externalCitationCosSim", "disciplineCitationCosSim",
                     "countriesCosSim", "decadesCosSim", "cityDefCosSim")

# scale all variables
DYADS$meanAlphaSim_scaled <- scale(DYADS$meanAlphaSim)
DYADS$sdAlphaSim_scaled <- scale(DYADS$sdAlphaSim)
DYADS$nAlphaSim_scaled <- scale(DYADS$nAlphaSim)
DYADS$fullTextCosSim_scaled <- scale(DYADS$fullTextCosSim)
DYADS$externalCitationCosSim_scaled <- scale(DYADS$externalCitationCosSim)
DYADS$disciplineCitationCosSim_scaled <- scale(DYADS$disciplineCitationCosSim)
DYADS$countriesCosSim_scaled <- scale(DYADS$countriesCosSim)
DYADS$decadesCosSim_scaled <- scale(DYADS$decadesCosSim)
DYADS$cityDefCosSim_scaled <- scale(DYADS$cityDefCosSim)

DYADSwithNA <- DYADS
DYADS <- DYADS[complete.cases(DYADS),]

modeldata<- DYADS[,c("dyadID","meanAlphaSim_scaled", "sdAlphaSim_scaled", "nAlphaSim_scaled",
                     "fullTextCosSim_scaled", "externalCitationCosSim_scaled", "disciplineCitationCosSim_scaled",
                     "countriesCosSim_scaled", "decadesCosSim_scaled", "cityDefCosSim_scaled")]
colnames(modeldata) <- c("ID", "alpha", "sd_alpha", "n_estim","text", "citation", "discipline", "country", "decade", "city")

Models of mean alpha

ftm_a <- lm(data = modeldata,
            formula = alpha ~ text,
            na.action = na.omit)
ecm_a <- lm(data = modeldata,
            formula = alpha ~ citation,
            na.action = na.omit)
dcm_a <- lm(data = modeldata,
            formula = alpha ~ discipline,
            na.action = na.omit)
ctrm_a <- lm(data = modeldata,
            formula = alpha ~ n_estim +
             country * decade * city,
            na.action = na.omit)
fullmodel_a <- lm(data = modeldata,
            formula = alpha ~ 
              text + citation + discipline + n_estim +
              country * decade * city,
            na.action = na.omit)

sgm<- stargazer(ftm_a, ecm_a, dcm_a,
          ctrm_a,
          fullmodel_a,
          type="text", out="results/model_comp_results_meanAlpha.html", font.size = "small", column.sep.width = "1pt")

=========================================================================================================================================
                                                                     Dependent variable:                                                 
                    ---------------------------------------------------------------------------------------------------------------------
                                                                            alpha                                                        
                             (1)                     (2)                    (3)                    (4)                     (5)           
-----------------------------------------------------------------------------------------------------------------------------------------
text                       0.048**                                                                                       0.050**         
                           (0.022)                                                                                       (0.023)         
                                                                                                                                         
citation                                          0.062***                                                               0.069***        
                                                   (0.022)                                                               (0.024)         
                                                                                                                                         
discipline                                                                0.043*                                          0.015          
                                                                          (0.022)                                        (0.024)         
                                                                                                                                         
n_estim                                                                                         -0.053**                 -0.046**        
                                                                                                 (0.022)                 (0.022)         
                                                                                                                                         
country                                                                                         0.063***                 0.063***        
                                                                                                 (0.023)                 (0.023)         
                                                                                                                                         
decade                                                                                          -0.100***               -0.123***        
                                                                                                 (0.022)                 (0.023)         
                                                                                                                                         
city                                                                                             -0.001                   -0.015         
                                                                                                 (0.022)                 (0.023)         
                                                                                                                                         
country:decade                                                                                   -0.014                   -0.013         
                                                                                                 (0.021)                 (0.021)         
                                                                                                                                         
country:city                                                                                     0.049**                 0.053**         
                                                                                                 (0.022)                 (0.022)         
                                                                                                                                         
decade:city                                                                                      0.037*                   0.038*         
                                                                                                 (0.022)                 (0.022)         
                                                                                                                                         
country:decade:city                                                                              -0.017                   -0.014         
                                                                                                 (0.021)                 (0.021)         
                                                                                                                                         
Constant                    0.015                   0.015                  0.015                  0.013                   0.012          
                           (0.022)                 (0.022)                (0.022)                (0.022)                 (0.022)         
                                                                                                                                         
-----------------------------------------------------------------------------------------------------------------------------------------
Observations                2,016                   2,016                  2,016                  2,016                   2,016          
R2                          0.002                   0.004                  0.002                  0.021                   0.030          
Adjusted R2                 0.002                   0.003                  0.001                  0.017                   0.025          
Residual Std. Error   1.003 (df = 2014)       1.003 (df = 2014)      1.004 (df = 2014)      0.996 (df = 2007)       0.992 (df = 2004)    
F Statistic         4.519** (df = 1; 2014) 7.799*** (df = 1; 2014) 3.682* (df = 1; 2014) 5.403*** (df = 8; 2007) 5.707*** (df = 11; 2004)
=========================================================================================================================================
Note:                                                                                                         *p<0.1; **p<0.05; ***p<0.01

Models of sd alpha

ftm_sd <- lm(data = modeldata,
            formula = sd_alpha ~ text,
            na.action = na.omit)
ecm_sd <- lm(data = modeldata,
            formula = sd_alpha ~ citation,
            na.action = na.omit)
dcm_sd <- lm(data = modeldata,
            formula = sd_alpha ~ discipline,
            na.action = na.omit)
 n_sd <- lm(data = modeldata,
             formula = sd_alpha ~ n_estim,
             na.action = na.omit)
ctrm_sd <- lm(data = modeldata,
             formula = sd_alpha ~ 
               country * decade * city,
             na.action = na.omit)
fullmodel_sd <- lm(data = modeldata,
                  formula = sd_alpha ~ 
                    text + citation + discipline + n_estim +
                    country * decade * city,
                  na.action = na.omit)

sgm<- stargazer(ftm_sd, ecm_sd, dcm_sd,n_sd,
                ctrm_sd,
                fullmodel_sd,
                type="text", out="results/model_comp_results_sdAlpha.html", font.size = "small", column.sep.width = "1pt")

=================================================================================================================================================================
                                                                                 Dependent variable:                                                             
                    ---------------------------------------------------------------------------------------------------------------------------------------------
                                                                                      sd_alpha                                                                   
                              (1)                    (2)                  (3)                    (4)                      (5)                      (6)           
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
text                        0.112***                                                                                                            0.116***         
                            (0.022)                                                                                                              (0.023)         
                                                                                                                                                                 
citation                                            -0.013                                                                                       -0.006          
                                                   (0.022)                                                                                       (0.024)         
                                                                                                                                                                 
discipline                                                               -0.004                                                                  -0.009          
                                                                        (0.022)                                                                  (0.024)         
                                                                                                                                                                 
n_estim                                                                                        0.134***                                         0.133***         
                                                                                               (0.022)                                           (0.022)         
                                                                                                                                                                 
country                                                                                                                -0.096***                -0.078***        
                                                                                                                        (0.023)                  (0.022)         
                                                                                                                                                                 
decade                                                                                                                 -0.077***                -0.076***        
                                                                                                                        (0.022)                  (0.023)         
                                                                                                                                                                 
city                                                                                                                   0.088***                 0.083***         
                                                                                                                        (0.022)                  (0.022)         
                                                                                                                                                                 
country:decade                                                                                                          0.041*                   0.042**         
                                                                                                                        (0.021)                  (0.021)         
                                                                                                                                                                 
country:city                                                                                                            0.050**                  0.051**         
                                                                                                                        (0.022)                  (0.022)         
                                                                                                                                                                 
decade:city                                                                                                             0.050**                  0.051**         
                                                                                                                        (0.022)                  (0.022)         
                                                                                                                                                                 
country:decade:city                                                                                                     -0.023                   -0.016          
                                                                                                                        (0.021)                  (0.021)         
                                                                                                                                                                 
Constant                     -0.009                 -0.009               -0.009                 -0.008                  -0.014                   -0.013          
                            (0.022)                (0.022)              (0.022)                (0.022)                  (0.022)                  (0.022)         
                                                                                                                                                                 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Observations                 2,016                  2,016                2,016                  2,016                    2,016                    2,016          
R2                           0.012                  0.0002              0.00002                 0.018                    0.027                    0.055          
Adjusted R2                  0.012                 -0.0003              -0.0005                 0.017                    0.023                    0.050          
Residual Std. Error    0.999 (df = 2014)      1.005 (df = 2014)    1.005 (df = 2014)      0.996 (df = 2014)        0.993 (df = 2008)        0.980 (df = 2004)    
F Statistic         25.463*** (df = 1; 2014) 0.336 (df = 1; 2014) 0.032 (df = 1; 2014) 36.782*** (df = 1; 2014) 7.818*** (df = 7; 2008) 10.685*** (df = 11; 2004)
=================================================================================================================================================================
Note:                                                                                                                                 *p<0.1; **p<0.05; ***p<0.01

Residuals analysis

modeldata$res <- fullmodel_a$residuals
head(modeldata[order(-modeldata$res),])
modeldata$i <- substr(modeldata$ID, 1,8)
modeldata$j <- substr(modeldata$ID, 10, 17)

cs.residuals_resPos <- modeldata[modeldata$res > 1.1,c("i", "j", "res")]
g.residuals <- graph_from_data_frame(cs.residuals_resPos, directed=F)
resPos <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.residuals)$name,],1, FUN = norm_vec))
colnames(resPos) <- "residuals"
resPos$ref <- rownames(resPos)
orderedName <- data.frame(V(g.residuals)$name)
orderedresidualsRes <- data.frame(orderedName, resPos[match(orderedName$V.g.residuals..name, resPos$ref),])[,"residuals"]
orderedresidualsRes <- orderedresidualsRes[!is.na(orderedresidualsRes)]

layout <- layout_nicely(g.residuals,2)
g.residuals$layout <- layout
par(mar = c(0,0,1,0))
plot(g.residuals, edge.width = sqrt(cs.residuals_resPos$res) * 2, vertex.size = 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = "green", edge.color = "coral3", 
     main = "Most positive residuals in mean alpha similarity")

cs.residuals_resNeg <- modeldata[modeldata$res < -2,c("i", "j", "res")]
g.residuals <- graph_from_data_frame(cs.residuals_resNeg, directed=F)
resNeg <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.residuals)$name,],1, FUN = norm_vec))
colnames(resNeg) <- "residuals"
resNeg$ref <- rownames(resNeg)
orderedName <- data.frame(V(g.residuals)$name)
orderedresidualsRes <- data.frame(orderedName, resNeg[match(orderedName$V.g.residuals..name, resNeg$ref),])[,"residuals"]
orderedresidualsRes <- orderedresidualsRes[!is.na(orderedresidualsRes)]

layout <- layout_nicely(g.residuals,2)
g.residuals$layout <- layout
par(mar = c(0,0,1,0))
plot(g.residuals, edge.width = sqrt(cs.residuals_resNeg$res) * 2, vertex.size = 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = "orange", edge.color = "dodgerblue3", 
     main = "Most negative residuals in mean alpha similarity")

modeldata$res <- fullmodel_sd$residuals
modeldata$i <- substr(modeldata$ID, 1,8)
modeldata$j <- substr(modeldata$ID, 10, 17)

cs.residuals_resPos <- modeldata[modeldata$res > 1,c("i", "j", "res")]
g.residuals <- graph_from_data_frame(cs.residuals_resPos, directed=F)
resPos <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.residuals)$name,],1, FUN = norm_vec))
colnames(resPos) <- "residuals"
resPos$ref <- rownames(resPos)
orderedName <- data.frame(V(g.residuals)$name)
orderedresidualsRes <- data.frame(orderedName, resPos[match(orderedName$V.g.residuals..name, resPos$ref),])[,"residuals"]
orderedresidualsRes <- orderedresidualsRes[!is.na(orderedresidualsRes)]

#clln.residuals <- cluster_louvain(g.residuals)
layout <- layout_nicely(g.residuals,2)
g.residuals$layout <- layout
par(mar = c(0,0,1,0))
plot(g.residuals, edge.width = sqrt(cs.residuals_resPos$res) * 2, vertex.size = 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = "green", edge.color = "coral3", 
     main = "Most positive residuals in sd alpha similarity")

cs.residuals_resNeg <- modeldata[modeldata$res < -1.5,c("i", "j", "res")]
g.residuals <- graph_from_data_frame(cs.residuals_resNeg, directed=F)
resNeg <- as.data.frame(apply(alphamat[rownames(alphamat) %in% V(g.residuals)$name,],1, FUN = norm_vec))
colnames(resNeg) <- "residuals"
resNeg$ref <- rownames(resNeg)
orderedName <- data.frame(V(g.residuals)$name)
orderedresidualsRes <- data.frame(orderedName, resNeg[match(orderedName$V.g.residuals..name, resNeg$ref),])[,"residuals"]
orderedresidualsRes <- orderedresidualsRes[!is.na(orderedresidualsRes)]

layout <- layout_nicely(g.residuals,2)
g.residuals$layout <- layout
par(mar = c(0,0,1,0))
plot(g.residuals, edge.width = sqrt(cs.residuals_resNeg$res) * 2, vertex.size = 2,
     vertex.label.cex = 0.7,  edge.curved=.2, vertex.color = "orange", edge.color = "dodgerblue3", 
     main = "Most negative residuals in sd alpha similarity")

LS0tCnRpdGxlOiAiVGhlIE1ldGFNZXRhWmlwZiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBSIE5vdGVib29rIHdoaWNoIHJlcHJvZHVjZXMgdGhlIGFuYWx5c2lzLCB0YWJsZXMgYW5kIGZpZ3VyZXMgb2YgdGhlIHdvcmtpbmcgcGFwZXIgIk1ldGFNZXRhWmlwZi4gV2hhdCBkbyBhbmFseXNlcyBvZiBjaXR5IHNpemUgZGlzdHJpYnV0aW9ucyBoYXZlIGluIGNvbW1vbj8iLCBhcyBvZiBBdWd1c3QgMjAyMC4gVGhlIGRhdGEgaXMgc3RvcmVkIG9uIHRoZSBbTWV0YVppcGZdKGh0dHBzOi8vZ2l0aHViLmNvbS9DbGVtZW50aW5lQ3R0bi9NZXRhWmlwZikgR2l0SHViIHJlcG9zaXRvcnkuCgpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeShpZ3JhcGgpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KHdlc2FuZGVyc29uKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShnZ2FsdCkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHRtKQpsaWJyYXJ5KGNsdXN0ZXIpCmxpYnJhcnkoU25vd2JhbGxDKQpsaWJyYXJ5KHN0YXJnYXplcikKbGlicmFyeShyZXNoYXBlMikKCgonJSFpbiUnIDwtIGZ1bmN0aW9uKHgseSkhKCclaW4lJyh4LHkpKQpub3JtX3ZlYyA8LSBmdW5jdGlvbih4KSBzcXJ0KHN1bU51bSh4XjIpKQoKc3VtTnVtID0gZnVuY3Rpb24oeCkgeyAKICBzID0gc3VtKHgsIG5hLnJtID0gVCkKICByZXR1cm4ocykKfQptZWFuTnVtID0gZnVuY3Rpb24oeCkgeyAKICBzID0gbWVhbih4LCBuYS5ybSA9IFQpCiAgcmV0dXJuKHMpCn0KCnNkTnVtID0gZnVuY3Rpb24oeCkgeyAKICBzID0gc2QoeCwgbmEucm0gPSBUKQogIHJldHVybihzKQp9Cgp0b1NwYWNlIDwtIGNvbnRlbnRfdHJhbnNmb3JtZXIoZnVuY3Rpb24oeCwgcGF0dGVybikgewogIHJldHVybiAoZ3N1YihwYXR0ZXJuLCAiICIsIHgpKQp9KQoKc3RhdC5jb21wPC0gIGZ1bmN0aW9uKCB4LHkpewogIEsgPC1sZW5ndGgodW5pcXVlKHkpKQogIG4gPC1sZW5ndGgoeCkKICBtIDwtbWVhbih4KQogIFRTUyA8LXN1bSgoeC1tKV4yKQogIG5rPC10YWJsZSh5KQogIG1rPC10YXBwbHkoeCx5LG1lYW4pCiAgQlNTIDwtc3VtKG5rKiAobWstbSleMikKICByZXN1bHQ8LWMobWssMTAwLjAqQlNTL1RTUykKICBuYW1lcyhyZXN1bHQpIDwtYyggcGFzdGUoIkciLDE6SyksIiUgZXBsLiIpCiAgcmV0dXJuKHJlc3VsdCkKfQoKYGBgCgoKIyBJbXBvcnRpbmcgRGF0YSBmcm9tIHRoZSBtZXRhWmlwZiBwcm9qZWN0OiAKKiB0aGUgaW5mb3JtYXRpb24gYWJvdXQgYXJ0aWNsZXMgaW4gdGhlIGNvcnB1cyAocmVmcykKKiB0aGUgZW1waXJpY2FsIGVzdGltYXRpb25zIHRoZXkgcmVwb3J0IGFsb25nIHdpdGggdGhlaXIgc3BlY2lmaWNhdGlvbnMgKGRhdGEpCiogdGhlIGNpdGF0aW9uIG1hdHJpeCAoY2l0ZXMpCiogdGhlIGNsZWFuZWQgZnVsbC10ZXh0cyAoZG9jcykKKiB0aGUgbG9va3VwIHRhYmxlIGZyb20gam91cm5hbCB0byBkaXNjaXBsaW5lIChKMkQpCgpgYGB7ciBpbXBvcnR9CnJlZnMgPC0gcmVhZC5jc3YyKCJkYXRhL3ppcGZfcmVmcy5jc3YiLCBzZXA9JzsnKQpjaXRlcyA8LSByZWFkLmNzdjIoImRhdGEvemlwZl9jaXRlcy5jc3YiLCBzZXA9JywnKQpkYXRhIDwtIHJlYWQuY3N2MigiZGF0YS96aXBmX21ldGEuY3N2Iiwgc2VwPSIsIiwgZGVjPSIuIikKY25hbWUgPC0gImRhdGEvRnVsbFRleHQvIgpkb2NzIDwtIENvcnB1cyhEaXJTb3VyY2UoY25hbWUpKSAgIApKMkQgPC0gcmVhZC5jc3YyKCJkYXRhL2pvdXJuYWxzMkRpc2NpcGxpbmVzLmNzdiIsIHNlcD0nOycpCmBgYAoKCiMjIENsZWFuaW5nIGNpdGF0aW9uIGRhdGEKYGBge3IgY2xlYW5DaXRhdGlvbiwgd2FybmluZz1GQUxTRX0KY2l0ZXNfb3V0IDwtIGNpdGVzWzY3OjEyMjEsXQpjaXRlc19vdXQkWUVBUiA8LSBhcy5udW1lcmljKGdzdWIoIlxcRCsiLCAiIiwgY2l0ZXNfb3V0JFJFRklEKSkKY2l0ZXNfb3V0JEpPVVJOQUwgPC0gZ3N1YigiLipcXGQuIiwgIiIsIGNpdGVzX291dCRSRUZJRCkKY2l0ZXNfb3V0JEFVVEhPUiA8LSBnc3ViKCJcXGQuKiIsICIiLCBjaXRlc19vdXQkUkVGSUQpCmNpdGVzX291dCRKT1VSTkFMIDwtIGdzdWIoIltbOnB1bmN0Ol1dIiwgIiAiLCBjaXRlc19vdXQkSk9VUk5BTCkKY2l0ZXNfb3V0JEFVVEhPUiA8LSBnc3ViKCJbWzpwdW5jdDpdXSIsICIgIiwgY2l0ZXNfb3V0JEFVVEhPUikKY2l0ZXNfb3V0IDwtIGRhdGEuZnJhbWUoY2l0ZXNfb3V0LEoyRFttYXRjaChjaXRlc19vdXQkSk9VUk5BTCwgSjJEJEpPVVJOQUwpLF0pCmNpdGVzX291dCRESVNDSVBMSU5FIDwtIGNpdGVzX291dCRESVNDUExJTkUKY2l0ZXNfb3V0JERJU0NQTElORSA8LSBOVUxMCmNpdGVzX291dCRKT1VSTkFMLjEgPC0gTlVMTApjaXRlcyA8LSByYmluZChjaXRlc1sxOjY2LF0sY2l0ZXNfb3V0KQpjaXRlc1tpcy5uYShjaXRlcyldIDwtIDAKY2l0ZXNfd2l0aGluIDwtIGNpdGVzWzE6NjYsYygxLDY6NzEpXQpoZWFkKGNpdGVzKQpgYGAKCiMjIENvcnB1cyBhbmFseXNpcwoKYGBge3IgY29ycHVzQW5hbHlzaXN9CgpqIDwtIGNpdGVzWzE6NjYsMTo1XQpqJG4gPC0gMQpqb3VybmFscyA8LSBhZ2dyZWdhdGUoalssIm4iXSwgYnk9bGlzdChqWywiSk9VUk5BTCJdKSwgRlVOID0gc3VtKQpkaXNjaXBsaW5lcyA8LSBhZ2dyZWdhdGUoalssIm4iXSwgYnk9bGlzdChqWywiRElTQ0lQTElORSJdKSwgRlVOID0gc3VtKQpxIDwtIGdncGxvdChqb3VybmFscywgYWVzKHg9IEdyb3VwLjEsIHkgPSB4KSkKIHEgKyBnZW9tX2xvbGxpcG9wKGFlcyhyZW9yZGVyKCBHcm91cC4xLCAteCkpLGNvbG9yID0gIm9yYW5nZXJlZCIsIGNleD0xKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKHg9IkpvdXJuYWwiLCB5PSJOdW1iZXIgb2YgYXJ0aWNsZXMgaW4gdGhlIGNvcnB1cyIpCgpyb3duYW1lcyhjaXRlc193aXRoaW4pIDwtIGNpdGVzX3dpdGhpbiRSRUZJRApjaXRlc193aXRoaW4kUkVGSUQgPC0gTlVMTApjbWF0IDwtIHQoYXMubWF0cml4KGNpdGVzX3dpdGhpbikpCmMgPC0gY29sU3VtcyhjbWF0KQpjbyA8LSBjW29yZGVyKC1jKV0KcmVmIDwtIG5hbWVzKGNvKQpjb3BlIDwtIGRhdGEuZnJhbWUocmVmLCBjbykKY29wZV9mdWxsX25hbWVzIDwtIGRhdGEuZnJhbWUoY29wZSwgY2l0ZXNbbWF0Y2goY29wZSRyZWYsIGNpdGVzJFJFRklEKSxjKCJBVVRIT1IiLCAiWUVBUiIsICJKT1VSTkFMIildKQpjb3BlX2Z1bGxfbmFtZXMkcmVmIDwtIHBhc3RlKGNvcGVfZnVsbF9uYW1lcyRBVVRIT1IsIGNvcGVfZnVsbF9uYW1lcyRZRUFSLCBzZXA9IiAiKQoKcGFyKG1hciA9IGMoMiwyLDIsMikpCnEgPC0gZ2dwbG90KGNvcGVfZnVsbF9uYW1lcywgYWVzKHg9cmVmLCB5ID0gY28pKQpxICsgZ2VvbV9sb2xsaXBvcChhZXMocmVvcmRlcihyZWYsIC1jbykpLGNvbG9yID0gInNlYWdyZWVuMyIsIGNleD0xKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKHg9IlJlZmVyZW5jZSIsIHk9Ik51bWJlciBvZiBpbi1jaXRhdGlvbnMgZnJvbSB0aGUgY29ycHVzIikKCgphZ2Vfam91cm5hbHMgPC0gZGF0YS5mcmFtZShhZ2dyZWdhdGUoalssIllFQVIiXSwgYnk9bGlzdChqWywiSk9VUk5BTCJdKSwgRlVOID0gbWVhbiksIGpvdXJuYWxzJHgpCmFnZV9kaXNjaXBsaW5lcyA8LSBkYXRhLmZyYW1lKGFnZ3JlZ2F0ZShqWywiWUVBUiJdLCBieT1saXN0KGpbLCJESVNDSVBMSU5FIl0pLCBGVU4gPSBtZWFuKSwgZGlzY2lwbGluZXMkeCkKcm93bmFtZXMoYWdlX2Rpc2NpcGxpbmVzKSA9IGFnZV9kaXNjaXBsaW5lcyRHcm91cC4xCnJvd25hbWVzKGFnZV9qb3VybmFscykgPSBhZ2Vfam91cm5hbHMkR3JvdXAuMQphZ2VfZGlzY2lwbGluZXMkR3JvdXAuMSA8LSBOVUxMCmFnZV9qb3VybmFscyRHcm91cC4xIDwtIE5VTEwKY29sbmFtZXMoYWdlX2Rpc2NpcGxpbmVzKSA8LSBjKCJtZWFuIGFnZSIsICJuIGFydGljbGVzIikKY29sbmFtZXMoYWdlX2pvdXJuYWxzKSA8LSBjKCJtZWFuIGFnZSIsICJuIGFydGljbGVzIikKcm91bmQobWVhbihqJFlFQVIpLCBkaWdpdD0wKQpyb3VuZChhZ2VfZGlzY2lwbGluZXMsIGRpZ2l0PTApCmNvcnB1c3N1bW1hcnkgPC0gZGF0YS5mcmFtZShqLCBjb3BlW21hdGNoKGokUkVGSUQsIGNvcGUkcmVmKSxdKQpjb2xuYW1lcyhjb3JwdXNzdW1tYXJ5KVs4XSA8LSAiaW5fY2l0YXRpb25zIgptZWFuKGNvcnB1c3N1bW1hcnlbY29ycHVzc3VtbWFyeSRpbl9jaXRhdGlvbnMgPiAxMCwgIllFQVIiXSkKYGBgCgojIyBFeHRlcm5hbCBjaXRhdGlvbiBhbmFseXNpcwoKYGBge3IgY2l0YXRpb25BbmFseXNpc30KY2l0ZXNfb3V0IDwtIGNpdGVzWzY3OjEyMjEsXQpjaXRlc19vdXQkbl9jaXRlcyA8LSByb3dTdW1zKGNpdGVzX291dFssNjo3MV0pCnNpbmdsZV9vdXRjaXRlcyA8LSBjaXRlc19vdXRbb3JkZXIoLWNpdGVzX291dCRuX2NpdGVzKSxjKDE6NSw3MildIApzX291dGNpdGVzIDwtIHNpbmdsZV9vdXRjaXRlc1ssYygiUkVGSUQiLCAibl9jaXRlcyIpXQpjb2xuYW1lcyhzX291dGNpdGVzKSA8LSBjKCJyZWYiLCAibiIpCnNfb3V0Y2l0ZXMgPC0gc3Vic2V0KHNfb3V0Y2l0ZXNbLTEwMCxdLCBuPj01KQpxIDwtIGdncGxvdChzX291dGNpdGVzLCBhZXMoeD1yZWYsIHkgPSBuKSkKcSArIGdlb21fbG9sbGlwb3AoYWVzKHJlb3JkZXIocmVmLCAtbikpLGNvbG9yID0gImNvcmFsMyIsIGNleD0xKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKHg9IlJlZmVyZW5jZSIsIHk9Ik51bWJlciBvZiBjaXRhdGlvbnMgZnJvbSB0aGUgY29ycHVzICg+PTUpIikKYGBgCgpXaG8gY2l0ZWQgTml0c2NoICgyMDA1KT8KYGBge3IgZXhhbXBsZUNpdGF0aW9ufQp3aG8gPC0gY2l0ZXNfb3V0W2NpdGVzX291dCRSRUZJRCA9PSAiTml0c2NoXzIwMDVfSm91cm5hbF9VcmJhbl9FY29ub21pY3MiLDY6NzFdCndob1sxLF0KYGBgCgpXaG8gZGlkIG5vdCBjaXRlIEcuIEsuIFppcGYgaGltc2VsZj8KYGBge3Igbm9aaXBmQ2l0YXRpb259Cm5vemlwZjwtIGFzLmRhdGEuZnJhbWUoY29sU3VtcyhjaXRlc19vdXRbY2l0ZXNfb3V0JFJFRklEICVpbiUgYygiWmlwZl8xOTQxX1VuaXR5X2Rpc3VuaXR5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJaaXBmXzE5NDlfSHVtYW5fQmVoYXZpb3JfUHJpbmNpcGxlX0xlYXN0X0VmZm9ydCIpLDY6NzFdKSkKY29sbmFtZXMobm96aXBmKSA8LSAicmVmX3ppcGYiCm5vemlwZiRyZWZfemlwZiA8LSBpZmVsc2Uobm96aXBmJHJlZl96aXBmID09IDAgLCAibm8gcmVmIHRvIHppcGYiLCAicmVmIHRvIHppcGYiKQpub3ppcGYkUkVGSUQgPC0gcm93bmFtZXMobm96aXBmKQpjaXRlc19mb3JfcmVmX3ppcGZzIDwtIGNpdGVzWzE6NjYsXQpyZWZlcmVuY2luZ196aXBmIDwtIGRhdGEuZnJhbWUoY2l0ZXNfZm9yX3JlZl96aXBmcywgbm96aXBmW21hdGNoKGNpdGVzX2Zvcl9yZWZfemlwZnMkUkVGSUQsIG5vemlwZiRSRUZJRCksXSkKcmZjenBmIDwtIHJlZmVyZW5jaW5nX3ppcGZbLGMoIllFQVIiLCAiRElTQ0lQTElORSIsICJyZWZfemlwZiIpXQoKcSA8LSBnZ3Bsb3QocmZjenBmLCBhZXMoeD1ZRUFSKSkKcSArIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gc3RhdChkZW5zaXR5KSwgY29sb3IgPSByZWZfemlwZiwgZmlsbCA9IHJlZl96aXBmKSwgCiAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNCwgcG9zaXRpb24gPSAiaWRlbnRpdHkiLCBiaW53aWR0aCA9IDEpICsKICBnZW9tX2RlbnNpdHkoYWVzKGNvbG9yID0gcmVmX3ppcGYpLCBzaXplID0gMSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJDb3JhbDIiLCAiZG9kZ2VyYmx1ZTMiKSkgKwpzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJDb3JhbDIiLCAiZG9kZ2VyYmx1ZTMiKSkgICsgbGFicyhjb2xvciA9ICIiKSArIGd1aWRlcyhmaWxsID0gRkFMU0UsIHNpemUgPSBGQUxTRSkrIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGFibGUocmZjenBmJHJlZl96aXBmLCByZmN6cGYkRElTQ0lQTElORSkKYGBgCgpXaGljaCBhcmUgdGhlIGF1dGhvcnMgY2l0ZWQgZnJvbSBVcmJhbiBTdHVkaWVzPwpgYGB7ciBleENpdGF0aW9uRnJvbUpvdXJuYWx9CmNpdGVzX291dFtjaXRlc19vdXQkSk9VUk5BTCA9PSAiVXJiYW4gU3R1ZGllcyIsIkFVVEhPUiJdCmBgYAoKU2l6ZSBvZiBiaWJsaW9ncmFwaHkgb2YgY29ycHVzIGFydGljbGVzCmBgYHtyIHNpemVCaWJsaW99Cm5fY2l0YXRpb25zIDwtIGFzLmRhdGEuZnJhbWUoY29sU3VtcyhjaXRlc19vdXRbLDY6NzFdLCBuYS5ybT1UKSkKY29sbmFtZXMobl9jaXRhdGlvbnMpIDwtICJuX2NpdGF0aW9ucyIKbl9jaXRhdGlvbnMkUkVGSUQgPC0gcm93bmFtZXMobl9jaXRhdGlvbnMpCm5fY2l0YXRpb25zX2NvcnB1cyA8LSBkYXRhLmZyYW1lKGNpdGVzX2Zvcl9yZWZfemlwZnMsIG5fY2l0YXRpb25zW21hdGNoKGNpdGVzX2Zvcl9yZWZfemlwZnMkUkVGSUQsIG5fY2l0YXRpb25zJFJFRklEKSxdKQpuX2NpdGF0aW9uc19jb3JwdXMkcmVmIDwtIHBhc3RlKG5fY2l0YXRpb25zX2NvcnB1cyRBVVRIT1IsIG5fY2l0YXRpb25zX2NvcnB1cyRZRUFSLCBzZXA9IiAiKQoKcSA8LSBnZ3Bsb3Qobl9jaXRhdGlvbnNfY29ycHVzLCBhZXMoeD1yZWYsIHkgPSBuX2NpdGF0aW9ucykpCnEgKyBnZW9tX2xvbGxpcG9wKGFlcyhyZW9yZGVyKHJlZiwgLW5fY2l0YXRpb25zKSksY29sb3IgPSAiZG9kZ2VyYmx1ZTMiLCBjZXg9MSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh4PSJSZWZlcmVuY2UiLCB5PSJTaXplIG9mIGJpYmxpb2dyYXBoeSBieSBjb3JwdXMgYXJ0aWNsZSIpCgpgYGAKCk1vc3QgY2l0ZWQgZXh0ZXJuYWwgYXRpY2xlcwpgYGB7ciBNb3N0Q2l0ZWRBcnRpY2xlc30KCmpvdV9vdXQgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShjaXRlc19vdXQkSk9VUk5BTCkpCmpvdV9vdXQgPC0gam91X291dFtvcmRlcigtam91X291dCRGcmVxKSxdIApjb2xuYW1lcyhqb3Vfb3V0KSA8LSBjKCJyZWYiLCAibiIpCmpvdSA8LSBzdWJzZXQoam91X291dFstMTAwLF0sIG4+PTUpCnEgPC0gZ2dwbG90KGpvdSwgYWVzKHg9cmVmLCB5ID0gbikpCnEgKyBnZW9tX2xvbGxpcG9wKGFlcyhyZW9yZGVyKHJlZiwgLW4pKSxjb2xvciA9ICJnb2xkZW5yb2QzIiwgY2V4PTEpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoeD0iSm91cm5hbCIsIHk9Ik51bWJlciBvZiBjaXRhdGlvbnMgZnJvbSB0aGUgY29ycHVzICg+PTUpIikKYGBgCgojIENvbnN0cnVjdGlvbiBvZiB0aGUgY2l0YXRpb24gc2ltaWxhcml0eSBuZXR3b3JrCmBgYHtyIGNpdGF0aW9uU2ltaWxhcml0eU5ldHdvcmt9CgpvdXRjaXRlbWF0IDwtIGFzLm1hdHJpeChjaXRlc19vdXRbLDY6NzFdKQp0b3V0Y2l0ZW1hdCA8LSB0KG91dGNpdGVtYXQpCnJlZlNpbSA8LSByb3duYW1lcyh0b3V0Y2l0ZW1hdCkKY29zU2ltIDwtIGRhdGEuZnJhbWUoKQprPTAKaWxpc3QgPC0gYygpCmZvcihpIGluIHJlZlNpbSl7CiAgaWxpc3QgPC0gYyhpbGlzdCwgaSkKICBmb3IoaiBpbiByZWZTaW0pewogICAgaWYgKGogJSFpbiUgaWxpc3QpewogICAgayA8LSBrICsgMQogICAgY29zU2ltW2ssMV0gPC0gaQogICAgY29zU2ltW2ssMl0gPC0gagogICAgdmkgPC0gdG91dGNpdGVtYXRbaSxdCiAgICB2aiA8LSB0b3V0Y2l0ZW1hdFtqLF0KICAgIGNvc1NpbVtrLDNdIDwtIChzdW1OdW0odmkgKiB2aikpIC8gKG5vcm1fdmVjKHZpKSAqICBub3JtX3ZlYyh2aikpIAogICAgfQogIH0KfQpjb2xuYW1lcyhjb3NTaW0pIDwtIGMoJ2knLCAnaicsICdjb3NTaW0nKQp3cml0ZS5jc3YoY29zU2ltW29yZGVyKC1jb3NTaW0kY29zU2ltKSxdLCAic2ltTmV0cy9TaW1pbGFyQ2l0YXRpb25zLmNzdiIpCgpzdW1tYXJ5KGNvc1NpbSRjb3NTaW0pCmNzLmNpdCA8LSBjb3NTaW1bY29zU2ltJGNvc1NpbSA+PSAwLjI1LF0KZy5jaXQgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLmNpdCwgZGlyZWN0ZWQ9RikKCmNpdGluZ05zIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkodG91dGNpdGVtYXRbcm93bmFtZXModG91dGNpdGVtYXQpICVpbiUgVihnLmNpdCkkbmFtZSxdLDEsIEZVTiA9IG5vcm1fdmVjKSkKY29sbmFtZXMoY2l0aW5nTnMpIDwtICJjaXRpbmdOIgpjaXRpbmdOcyRyZWYgPC0gcm93bmFtZXMoY2l0aW5nTnMpCm9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLmNpdCkkbmFtZSkKY2l0aW5nTiA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCBjaXRpbmdOc1ttYXRjaChvcmRlcmVkTmFtZSRWLmcuY2l0Li5uYW1lLCBjaXRpbmdOcyRyZWYpLF0pWywiY2l0aW5nTiJdCmNpdGluZ04gPC0gY2l0aW5nTlshaXMubmEoY2l0aW5nTildIAoKcGFyKG1hciA9IGMoMCwwLDAsMCkpCmNsbG4uY2l0IDwtIGNsdXN0ZXJfbG91dmFpbihnLmNpdCkKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5jaXQsMikKZy5jaXQkbGF5b3V0IDwtIGxheW91dApwbG90KGcuY2l0LCBlZGdlLndpZHRoID0gc3FydChjcy5jaXQkY29zU2ltKSAqIDIsIHZlcnRleC5zaXplID0gY2l0aW5nTiwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC43LCAgZWRnZS5jdXJ2ZWQ9LjIsIHZlcnRleC5jb2xvciA9IG1lbWJlcnNoaXAoY2xsbi5jaXQpKQpgYGAKCiMgQ29uc3RydWN0aW9uIG9mIHRoZSBkaXNjaXBsaW5lIHNpbWlsYXJpdHkgbmV0d29yawpgYGB7ciBkaXNjaXBsaW5lTmV0d29ya30KZGlzY2lwbGluZTJyZWYgPC0gYWdncmVnYXRlKGNpdGVzX291dFssYyg2OjcxKV0sIGJ5PWxpc3QoY2l0ZXNfb3V0JERJU0NJUExJTkUpLCBGVU4gPSBzdW1OdW0pCnJvd25hbWVzKGRpc2NpcGxpbmUycmVmKSA8LSBkaXNjaXBsaW5lMnJlZiRHcm91cC4xCmRpc2NpcGxpbmUycmVmJEdyb3VwLjEgPC0gTlVMTApjb2xzIDwtIGNvbG5hbWVzKGRpc2NpcGxpbmUycmVmKQpmb3IoaSBpbiBjb2xzKXsKICBhYnNvbHV0ZSA8LSBkaXNjaXBsaW5lMnJlZlssaV0KICB0b3RhbCA8LSBzdW0oYWJzb2x1dGUpCiAgcmVsYXRpdmUgPC0gYWJzb2x1dGUvdG90YWwKICBkaXNjaXBsaW5lMnJlZlsscGFzdGUwKCJmcmVxXyIsaSldIDwtIHJlbGF0aXZlCn0KCmRpc2MycmVmIDwtIGFzLm1hdHJpeChkaXNjaXBsaW5lMnJlZlssNjc6MTMyXSkKY29sbmFtZXMoZGlzYzJyZWYpIDwtIGNvbHMKc2NhbGVkX2Rpc2MycmVmIDwtIGRpc2MycmVmIC8gY29sU3VtcyhkaXNjMnJlZikKdGRpc2MycmVmIDwtIHQoZGlzYzJyZWYpCgpyZWZTaW0gPC0gcm93bmFtZXModGRpc2MycmVmKQpjb3NTaW0gPC0gZGF0YS5mcmFtZSgpCms9MAppbGlzdCA8LSBjKCkKZm9yKGkgaW4gcmVmU2ltKXsKICBpbGlzdCA8LSBjKGlsaXN0LCBpKQogIGZvcihqIGluIHJlZlNpbSl7CiAgICBpZiAoaiAlIWluJSBpbGlzdCl7CiAgICAgIGsgPC0gayArIDEKICAgICAgY29zU2ltW2ssMV0gPC0gaQogICAgICBjb3NTaW1baywyXSA8LSBqCiAgICAgIHZpIDwtIHRkaXNjMnJlZltpLF0KICAgICAgdmogPC0gdGRpc2MycmVmW2osXQogICAgICBjb3NTaW1baywzXSA8LSAoc3VtTnVtKHZpICogdmopKSAvIChub3JtX3ZlYyh2aSkgKiAgbm9ybV92ZWModmopKSAKICAgIH0KICB9Cn0KY29sbmFtZXMoY29zU2ltKSA8LSBjKCdpJywgJ2onLCAnY29zU2ltJykKd3JpdGUuY3N2KGNvc1NpbVtvcmRlcigtY29zU2ltJGNvc1NpbSksXSwgInNpbU5ldHMvU2ltaWxhckRpc2NpcGxpbmVzQ2l0ZWRfcmVsLmNzdiIpCnN1bW1hcnkoY29zU2ltJGNvc1NpbSkKY3MuY2l0IDwtIGNvc1NpbVtjb3NTaW0kY29zU2ltID49IDAuOSxdCmcuY2l0IDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcy5jaXQsIGRpcmVjdGVkPUYpCgpkaXNDaXRlZE5zIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkodG91dGNpdGVtYXRbcm93bmFtZXModGRpc2MycmVmKSAlaW4lIFYoZy5jaXQpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKGRpc0NpdGVkTnMpIDwtICJkaXNDaXRlZE5zIgpkaXNDaXRlZE5zJHJlZiA8LSByb3duYW1lcyhkaXNDaXRlZE5zKQpvcmRlcmVkTmFtZSA8LSBkYXRhLmZyYW1lKFYoZy5jaXQpJG5hbWUpCmRpc0NpdGVkTnMgPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgZGlzQ2l0ZWROc1ttYXRjaChvcmRlcmVkTmFtZSRWLmcuY2l0Li5uYW1lLCBkaXNDaXRlZE5zJHJlZiksXSlbLCJkaXNDaXRlZE5zIl0KZGlzQ2l0ZWROcyA8LSBkaXNDaXRlZE5zWyFpcy5uYShkaXNDaXRlZE5zKV0gCgpjb2xuYW1lcyhvcmRlcmVkTmFtZSkgPC0gIlJFRklEIgpyZWZpbmZvIDwtIGNpdGVzWzE6NjYsYygiUkVGSUQiLCAiRElTQ0lQTElORSIpXQpvd25fZGlzY2lwbGluZSA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCByZWZpbmZvW21hdGNoKG9yZGVyZWROYW1lJFJFRklELCByZWZpbmZvJFJFRklEKSxdKQpvZGlzYyA8LSBvd25fZGlzY2lwbGluZSRESVNDSVBMSU5FCgpsYXlvdXQgPC0gbGF5b3V0X25pY2VseShnLmNpdCwyKQpnLmNpdCRsYXlvdXQgPC0gbGF5b3V0CnBhcihtYXIgPSBjKDAsMCwwLDApKQpwbG90KGcuY2l0LCBlZGdlLndpZHRoID0gc3FydChjcy5jaXQkY29zU2ltKSAqIDIsIHZlcnRleC5zaXplID0gZGlzQ2l0ZWROcywKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC43LCAgZWRnZS5jdXJ2ZWQ9LjIsIHZlcnRleC5jb2xvciA9IG9kaXNjKQoKCmBgYAoKIyBDb25zdHJ1Y3Rpb24gb2YgZnVsbC10ZXh0IHNpbWlsYXJpdHkgbmV0d29yawpgYGB7ciBmdWxsVGV4dFNpbX0KZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgIi0iKQpkb2NzIDwtIHRtX21hcChkb2NzLCB0b1NwYWNlLCAiOiIpCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHRvU3BhY2UsICInIikKZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgImAiKQpkb2NzIDwtIHRtX21hcChkb2NzLCB0b1NwYWNlLCAi4oCYIikKZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgIl8iKQpkb2NzIDwtIHRtX21hcChkb2NzLCB0b1NwYWNlLCAi4oCTIikKZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9TcGFjZSwgIi8iKQpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVQdW5jdHVhdGlvbikKZG9jcyA8LSB0bV9tYXAoZG9jcywgdG9sb3dlcikgICAKZG9jcyA8LSB0bV9tYXAoZG9jcywgcmVtb3ZlTnVtYmVycykgICAKZG9jcyA8LSB0bV9tYXAoZG9jcywgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW5nbGlzaCIpKSAgIApkdG0gPC0gRG9jdW1lbnRUZXJtTWF0cml4KGRvY3MpICAgCmR0bS5tID0gYXMubWF0cml4KGR0bSkKdGRtIDwtIFRlcm1Eb2N1bWVudE1hdHJpeChkb2NzKSAgIAp0ZG0ubSA9IGFzLm1hdHJpeCh0ZG0pCgogdGRtLmRmID0gYXMuZGF0YS5mcmFtZSh0ZG0ubSkKIHRkbS5kZi5mIDwtIHRkbS5kZiAvIGNvbFN1bXModGRtLmRmKQoKbl93b3JkcyA8LSBhcy5kYXRhLmZyYW1lKGNvbFN1bXModGRtLmRmLCBuYS5ybT1UKSkKIGNvbG5hbWVzKG5fd29yZHMpIDwtICJuX3dvcmRzIgogbl93b3JkcyRSRUZJRCA8LSBzdWJzdHIocm93bmFtZXMobl93b3JkcyksIDEsOCkKIG5fd29yZHNfY29ycHVzIDwtIGRhdGEuZnJhbWUoY2l0ZXNfZm9yX3JlZl96aXBmcywgbl93b3Jkc1ttYXRjaChjaXRlc19mb3JfcmVmX3ppcGZzJFJFRklELCBuX3dvcmRzJFJFRklEKSxdKQogbl93b3Jkc19jb3JwdXMkcmVmIDwtIHBhc3RlKG5fd29yZHNfY29ycHVzJEFVVEhPUiwgbl93b3Jkc19jb3JwdXMkWUVBUiwgc2VwPSIgIikKIG5fd29yZHNfY29ycHVzIDwtIG5fd29yZHNfY29ycHVzW25fd29yZHNfY29ycHVzJEFVVEhPUiAhPSAiS3Jha292ZXIgUy4iLF0KIHEgPC0gZ2dwbG90KG5fd29yZHNfY29ycHVzLCBhZXMoeD1yZWYsIHkgPSBuX3dvcmRzKSkKIHEgKyBnZW9tX2xvbGxpcG9wKGFlcyhyZW9yZGVyKHJlZiwgLW5fd29yZHMpKSxjb2xvciA9ICJzZWFncmVlbjQiLCBjZXg9MSkgKwogICBjb29yZF9mbGlwKCkgKwogICBsYWJzKHg9IlJlZmVyZW5jZSIsIHk9Ik51bWJlciBvZiB3b3JkcyBieSBjb3JwdXMgYXJ0aWNsZSIpCiAKIHRlcm1tYXQgPC0gdChhcy5tYXRyaXgodGRtLmRmLmYpKQogCiByZWZTaW1UZXJtIDwtIHJvd25hbWVzKHRlcm1tYXQpCiBjb3NTaW1UZXJtIDwtIGRhdGEuZnJhbWUoKQogaz0wCiBpbGlzdCA8LSBjKCkKIGZvcihpIGluIHJlZlNpbVRlcm0pewogICBpbGlzdCA8LSBjKGlsaXN0LCBpKQogICBmb3IoaiBpbiByZWZTaW1UZXJtKXsKICAgICBpZiAoaiAlIWluJSBpbGlzdCl7CiAgICAgICBrIDwtIGsgKyAxCiAgICAgICBjb3NTaW1UZXJtW2ssMV0gPC0gaQogICAgICAgY29zU2ltVGVybVtrLDJdIDwtIGoKICAgICAgIHZpIDwtIHRlcm1tYXRbaSxdCiAgICAgICB2aiA8LSB0ZXJtbWF0W2osXQogICAgICAgY29zU2ltVGVybVtrLDNdIDwtIChzdW1OdW0odmkgKiB2aikpIC8gKG5vcm1fdmVjKHZpKSAqICBub3JtX3ZlYyh2aikpIAogICAgIH0KICAgfQogfQogY29sbmFtZXMoY29zU2ltVGVybSkgPC0gYygnaScsICdqJywgJ2Nvc1NpbVRlcm0nKQogd3JpdGUuY3N2KGNvc1NpbVRlcm1bb3JkZXIoLWNvc1NpbVRlcm0kY29zU2ltVGVybSksXSwgInNpbU5ldHMvU2ltaWxhcldvcmRpbmcuY3N2IikKIHN1bW1hcnkoY29zU2ltVGVybSkKCiBjcyA8LSBjb3NTaW1UZXJtW2Nvc1NpbVRlcm0kY29zU2ltVGVybSA+IDAuNyxdCiBnLnRlcm0gPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLCBkaXJlY3RlZD1GKQogdG90YWxUZXJtIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkodGVybW1hdFtyb3duYW1lcyh0ZXJtbWF0KSAlaW4lIFYoZy50ZXJtKSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQogY29sbmFtZXModG90YWxUZXJtKSA8LSAidG90YWxUZXJtcyIKIHRvdGFsVGVybSRyZWYgPC0gcm93bmFtZXModG90YWxUZXJtKQogb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcudGVybSkkbmFtZSkKIHRvdGFsVGVybXMgPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgdG90YWxUZXJtW21hdGNoKG9yZGVyZWROYW1lJFYuZy50ZXJtLi5uYW1lLCB0b3RhbFRlcm0kcmVmKSxdKVssInRvdGFsVGVybXMiXQogdG90YWxUZXJtcyA8LSB0b3RhbFRlcm1zWyFpcy5uYSh0b3RhbFRlcm1zKV0gCiBjbGxuLnRlcm0gPC0gY2x1c3Rlcl9sb3V2YWluKGcudGVybSkKIGxheW91dCA8LSBsYXlvdXRfbmljZWx5KGcudGVybSwyKQogZy50ZXJtJGxheW91dCA8LSBsYXlvdXQKIHBhcihtYXIgPSBjKDAsMCwwLDApKQogcGxvdChnLnRlcm0sIGVkZ2Uud2lkdGggPSBzcXJ0KGNzJGNvc1NpbVRlcm0pICogMiwgdmVydGV4LnNpemUgPSB0b3RhbFRlcm1zICo1MCwKICAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIAogICAgICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gbWVtYmVyc2hpcChjbGxuLnRlcm0pKQogCmBgYAoKIyBDb25zdHJ1Y3Rpb24gY291bnRyeSBzaW1pbGFyaXR5IG5ldHdvcmsKYGBge3IgY291bnRyeVNpbX0KCiAgcGFwZXJMaXN0IDwtIGNvbG5hbWVzKGNpdGVzX291dFssNjo3MV0pCiAgY291bnRyeURhdGEgPC0gZGF0YVtkYXRhJFRFUlJJVE9SWV9UWVBFID09ICJDb3VudHJ5IiAmIGRhdGEkUkVGSUQgJWluJSBwYXBlckxpc3QsXQpjb3VudHJ5MlJlZiA8LSB0YWJsZShjb3VudHJ5RGF0YSRDTlRSX0lELCBjb3VudHJ5RGF0YSRSRUZJRClbLTEsXQpjb3VudHJ5MlJlZi5tYXQgPC0gYXMubWF0cml4KGNvdW50cnkyUmVmW3Jvd1N1bXMoY291bnRyeTJSZWYpPjAsY29sbmFtZXMoY291bnRyeTJSZWYpICVpbiUgcGFwZXJMaXN0XSkKY291bnRyeTJSZWYubWF0W2NvdW50cnkyUmVmLm1hdD4wXSA8LSAxCmNvdW50cnltYXQgPC0gdChjb3VudHJ5MlJlZi5tYXQpCgpyZWZTaW0gPC0gcm93bmFtZXMoY291bnRyeW1hdCkKY29zU2ltQyA8LSBkYXRhLmZyYW1lKCkKaz0wCmlsaXN0IDwtIGMoKQpmb3IoaSBpbiByZWZTaW0pewogIGlsaXN0IDwtIGMoaWxpc3QsIGkpCiAgZm9yKGogaW4gcmVmU2ltKXsKICAgIGlmIChqICUhaW4lIGlsaXN0KXsKICAgICAgayA8LSBrICsgMQogICAgICBjb3NTaW1DW2ssMV0gPC0gaQogICAgICBjb3NTaW1DW2ssMl0gPC0gagogICAgICB2aSA8LSBjb3VudHJ5bWF0W2ksXQogICAgICB2aiA8LSBjb3VudHJ5bWF0W2osXQogICAgICBzIDwtIChzdW1OdW0odmkgKiB2aikpIC8gKG5vcm1fdmVjKHZpKSAqICBub3JtX3ZlYyh2aikpIAogICAgICBjb3NTaW1DW2ssM10gPC0gaWZlbHNlKCFpcy5uYShzKSwgcywgMCkKICAgIH0KICB9Cn0KY29sbmFtZXMoY29zU2ltQykgPC0gYygnaScsICdqJywgJ2Nvc1NpbUMnKQp3cml0ZS5jc3YoY29zU2ltQ1tvcmRlcigtY29zU2ltQyRjb3NTaW1DKSxdLCAic2ltTmV0cy9TaW1pbGFyQ291bnRyaWVzLmNzdiIpCnN1bW1hcnkoY29zU2ltQykKY3MuY250ciA8LSBjb3NTaW1DW2Nvc1NpbUMkY29zU2ltQyA+PSAwLjIsXQpnLmNudHIgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLmNudHIsIGRpcmVjdGVkPUYpCmNvdW50cnlOIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkoY291bnRyeW1hdFtyb3duYW1lcyhjb3VudHJ5bWF0KSAlaW4lIFYoZy5jbnRyKSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQpjb2xuYW1lcyhjb3VudHJ5TikgPC0gIm5fY291bnRyaWVzIgpjb3VudHJ5TiRyZWYgPC0gcm93bmFtZXMoY291bnRyeU4pCm9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLmNudHIpJG5hbWUpCm9yZGVyZWRDb3VudHJ5TiA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCBjb3VudHJ5TlttYXRjaChvcmRlcmVkTmFtZSRWLmcuY250ci4ubmFtZSwgY291bnRyeU4kcmVmKSxdKVssIm5fY291bnRyaWVzIl0Kb3JkZXJlZENvdW50cnlOIDwtIG9yZGVyZWRDb3VudHJ5TlshaXMubmEob3JkZXJlZENvdW50cnlOKV0gCmNsbG4uY250ciA8LSBjbHVzdGVyX2xvdXZhaW4oZy5jbnRyKQpsYXlvdXQgPC0gbGF5b3V0X25pY2VseShnLmNudHIsMikKZy5jbnRyJGxheW91dCA8LSBsYXlvdXQKIHBhcihtYXIgPSBjKDAsMCwwLDApKQogcGxvdChnLmNudHIsIGVkZ2Uud2lkdGggPSBzcXJ0KGNzLmNudHIkY29zU2ltQykgKiAyLCB2ZXJ0ZXguc2l6ZSA9IG9yZGVyZWRDb3VudHJ5TiAqIDIsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSBtZW1iZXJzaGlwKGNsbG4uY250cikpCgpgYGAKCiMgQ29uc3RydWN0aW9uIGNpdHkgZGVmaW5pdGlvbiBzaW1pbGFyaXR5IG5ldHdvcmsKYGBge3IgY2l0eURlZlNpbX0KCmNpdHlEYXRhIDwtIGRhdGFbIWlzLm5hKGRhdGEkVVJCQU5TQ0FMRSkgJiBkYXRhJFJFRklEICVpbiUgcGFwZXJMaXN0LF0KY2l0eTJSZWYgPC0gdGFibGUoY2l0eURhdGEkVVJCQU5TQ0FMRSwgY2l0eURhdGEkUkVGSUQpWyxdCmNpdHkyUmVmLm1hdCA8LSBhcy5tYXRyaXgoY2l0eTJSZWZbcm93U3VtcyhjaXR5MlJlZik+MCxjb2xuYW1lcyhjaXR5MlJlZikgJWluJSBwYXBlckxpc3RdKQpjaXR5MlJlZi5tYXRbY2l0eTJSZWYubWF0PjBdIDwtIDEKY2l0eW1hdCA8LSB0KGNpdHkyUmVmLm1hdCkKCnJlZlNpbSA8LSByb3duYW1lcyhjaXR5bWF0KQpjb3NTaW1DdCA8LSBkYXRhLmZyYW1lKCkKaz0wCmlsaXN0IDwtIGMoKQpmb3IoaSBpbiByZWZTaW0pewogIGlsaXN0IDwtIGMoaWxpc3QsIGkpCiAgZm9yKGogaW4gcmVmU2ltKXsKICAgIGlmIChqICUhaW4lIGlsaXN0KXsKICAgICAgayA8LSBrICsgMQogICAgICBjb3NTaW1DdFtrLDFdIDwtIGkKICAgICAgY29zU2ltQ3RbaywyXSA8LSBqCiAgICAgIHZpIDwtIGNpdHltYXRbaSxdCiAgICAgIHZqIDwtIGNpdHltYXRbaixdCiAgICAgIHMgPC0gKHN1bU51bSh2aSAqIHZqKSkgLyAobm9ybV92ZWModmkpICogIG5vcm1fdmVjKHZqKSkgCiAgICAgIGNvc1NpbUN0W2ssM10gPC0gaWZlbHNlKCFpcy5uYShzKSwgcywgMCkKICAgIH0KICB9Cn0KY29sbmFtZXMoY29zU2ltQ3QpIDwtIGMoJ2knLCAnaicsICdjb3NTaW1DdCcpCndyaXRlLmNzdihjb3NTaW1DdFtvcmRlcigtY29zU2ltQ3QkY29zU2ltQ3QpLF0sICJzaW1OZXRzL1NpbWlsYXJDaXRpZXMuY3N2IikKc3VtbWFyeShjb3NTaW1DdCkKY3MuY2l0eSA8LSBjb3NTaW1DdFtjb3NTaW1DdCRjb3NTaW1DdCA+PSAwLjEsXQoKZy5jaXR5IDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcy5jaXR5LCBkaXJlY3RlZD1GKQpjaXR5TiA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KGNpdHltYXRbcm93bmFtZXMoY2l0eW1hdCkgJWluJSBWKGcuY2l0eSkkbmFtZSxdLDEsIEZVTiA9IG5vcm1fdmVjKSkKY29sbmFtZXMoY2l0eU4pIDwtICJuX2NpdGllcyIKY2l0eU4kcmVmIDwtIHJvd25hbWVzKGNpdHlOKQpvcmRlcmVkTmFtZSA8LSBkYXRhLmZyYW1lKFYoZy5jaXR5KSRuYW1lKQpvcmRlcmVkY2l0eU4gPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgY2l0eU5bbWF0Y2gob3JkZXJlZE5hbWUkVi5nLmNpdHkuLm5hbWUsIGNpdHlOJHJlZiksXSlbLCJuX2NpdGllcyJdCm9yZGVyZWRjaXR5TiA8LSBvcmRlcmVkY2l0eU5bIWlzLm5hKG9yZGVyZWRjaXR5TildIAoKY2xsbi5jaXR5IDwtIGNsdXN0ZXJfbG91dmFpbihnLmNpdHkpCmxheW91dCA8LSBsYXlvdXRfbmljZWx5KGcuY2l0eSwyKQpnLmNpdHkkbGF5b3V0IDwtIGxheW91dAogcGFyKG1hciA9IGMoMCwwLDAsMCkpCiBwbG90KGcuY2l0eSwgZWRnZS53aWR0aCA9IHNxcnQoY3MuY2l0eSRjb3NTaW1DdCkgKiAyLCB2ZXJ0ZXguc2l6ZSA9IG9yZGVyZWRjaXR5TiAqIDIsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSBtZW1iZXJzaGlwKGNsbG4uY2l0eSkpCgpgYGAKCgojIENvbnN0cnVjdGlvbiBkZWNhZGUgc2ltaWxhcml0eSBuZXR3b3JrCmBgYHtyIGRlY2FkZVNpbX0KCmRlY2FkZURhdGEgPC0gZGF0YVshaXMubmEoZGF0YSREQVRFKSAmIGRhdGEkUkVGSUQgJWluJSBwYXBlckxpc3QsXQpkZWNhZGVEYXRhJERFQ0FERSA8LSBwYXN0ZTAoc3Vic3RyKGFzLmNoYXJhY3RlcihkZWNhZGVEYXRhJERBVEUpLCAxLCAzKSwgMCwgInMiKQpkZWNhZGUyUmVmIDwtIHRhYmxlKGRlY2FkZURhdGEkREVDQURFLCBkZWNhZGVEYXRhJFJFRklEKVssXQpkZWNhZGUyUmVmLm1hdCA8LSBhcy5tYXRyaXgoZGVjYWRlMlJlZltyb3dTdW1zKGRlY2FkZTJSZWYpPjAsY29sbmFtZXMoZGVjYWRlMlJlZikgJWluJSBwYXBlckxpc3RdKQpkZWNhZGUyUmVmLm1hdFtkZWNhZGUyUmVmLm1hdD4wXSA8LSAxCmRlY2FkZW1hdCA8LSB0KGRlY2FkZTJSZWYubWF0KQoKcmVmU2ltIDwtIHJvd25hbWVzKGRlY2FkZW1hdCkKY29zU2ltQ3QgPC0gZGF0YS5mcmFtZSgpCms9MAppbGlzdCA8LSBjKCkKZm9yKGkgaW4gcmVmU2ltKXsKICBpbGlzdCA8LSBjKGlsaXN0LCBpKQogIGZvcihqIGluIHJlZlNpbSl7CiAgICBpZiAoaiAlIWluJSBpbGlzdCl7CiAgICAgIGsgPC0gayArIDEKICAgICAgY29zU2ltQ3RbaywxXSA8LSBpCiAgICAgIGNvc1NpbUN0W2ssMl0gPC0gagogICAgICB2aSA8LSBkZWNhZGVtYXRbaSxdCiAgICAgIHZqIDwtIGRlY2FkZW1hdFtqLF0KICAgICAgcyA8LSAoc3VtTnVtKHZpICogdmopKSAvIChub3JtX3ZlYyh2aSkgKiAgbm9ybV92ZWModmopKQogICAgICBjb3NTaW1DdFtrLDNdIDwtIGlmZWxzZSghaXMubmEocyksIHMsIDApCiAgICB9CiAgfQp9CmNvbG5hbWVzKGNvc1NpbUN0KSA8LSBjKCdpJywgJ2onLCAnY29zU2ltQ3QnKQp3cml0ZS5jc3YoY29zU2ltQ3Rbb3JkZXIoLWNvc1NpbUN0JGNvc1NpbUN0KSxdLCAic2ltTmV0cy9TaW1pbGFyRGVjYWRlcy5jc3YiKQpzdW1tYXJ5KGNvc1NpbUN0JGNvc1NpbUN0KQpjcy5kZWNhZGUgPC0gY29zU2ltQ3RbY29zU2ltQ3QkY29zU2ltQ3QgPj0gMC42NSxdCgpnLmRlY2FkZSA8LSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoY3MuZGVjYWRlLCBkaXJlY3RlZD1GKQpkZWNhZGVOIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkoZGVjYWRlbWF0W3Jvd25hbWVzKGRlY2FkZW1hdCkgJWluJSBWKGcuZGVjYWRlKSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQpjb2xuYW1lcyhkZWNhZGVOKSA8LSAibl9kZWNhZGVzIgpkZWNhZGVOJHJlZiA8LSByb3duYW1lcyhkZWNhZGVOKQpvcmRlcmVkTmFtZSA8LSBkYXRhLmZyYW1lKFYoZy5kZWNhZGUpJG5hbWUpCm9yZGVyZWRkZWNhZGVOIDwtIGRhdGEuZnJhbWUob3JkZXJlZE5hbWUsIGRlY2FkZU5bbWF0Y2gob3JkZXJlZE5hbWUkVi5nLmRlY2FkZS4ubmFtZSwgZGVjYWRlTiRyZWYpLF0pWywibl9kZWNhZGVzIl0Kb3JkZXJlZGRlY2FkZU4gPC0gb3JkZXJlZGRlY2FkZU5bIWlzLm5hKG9yZGVyZWRkZWNhZGVOKV0KCmNsbG4uZGVjYWRlIDwtIGNsdXN0ZXJfbG91dmFpbihnLmRlY2FkZSkKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5kZWNhZGUsMikKZy5kZWNhZGUkbGF5b3V0IDwtIGxheW91dApwYXIobWFyID0gYygwLDAsMCwwKSkKcGxvdChnLmRlY2FkZSwgZWRnZS53aWR0aCA9IHNxcnQoY3MuZGVjYWRlJGNvc1NpbUN0KSAqIDIsIHZlcnRleC5zaXplID0gb3JkZXJlZGRlY2FkZU4gKiAyLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gbWVtYmVyc2hpcChjbGxuLmRlY2FkZSkpCiAKYGBgCgojIENvbnN0cnVjdGlvbiBvZiB0aGUgbmV0d29ya3Mgb2YgYWxwaGEgc2ltaWxhcml0eQpgYGB7ciBhbHBoYVNpbX0KYWxwaGFEYXRhIDwtIGRhdGFbIWlzLm5hKGRhdGEkQUxQSEFMT1RLQSkgJiBkYXRhJFJFRklEICVpbiUgcGFwZXJMaXN0LF0KYWxwaGFEYXRhJG4gPC0gMQptZWFuQWxwaGFQZXJSZWYgPC0gYWdncmVnYXRlKGFscGhhRGF0YVssIkFMUEhBTE9US0EiXSwgYnk9bGlzdChhbHBoYURhdGEkUkVGSUQpLCBGVU49bWVhbk51bSkKc2RBbHBoYVBlclJlZiA8LSBhZ2dyZWdhdGUoYWxwaGFEYXRhWywiQUxQSEFMT1RLQSJdLCBieT1saXN0KGFscGhhRGF0YSRSRUZJRCksIEZVTj1zZE51bSkKc2RBbHBoYVBlclJlZltpcy5uYShzZEFscGhhUGVyUmVmJHgpLCJ4Il0gPC0gMApuQWxwaGFQZXJSZWYgPC0gYWdncmVnYXRlKGFscGhhRGF0YVssIm4iXSwgYnk9bGlzdChhbHBoYURhdGEkUkVGSUQpLCBGVU49c3VtTnVtKQoKc2ltaWxhckFscGhhIDwtIGNiaW5kKG1lYW5BbHBoYVBlclJlZiwgc2RBbHBoYVBlclJlZiwgbkFscGhhUGVyUmVmKQpyb3duYW1lcyhzaW1pbGFyQWxwaGEpIDwtIHNpbWlsYXJBbHBoYSRHcm91cC4xCnNpbWlsYXJBbHBoYVssYygxLDMsIDUpXSA8LSBOVUxMCmNvbG5hbWVzKHNpbWlsYXJBbHBoYSkgPC0gYygibWVhbkFscGhhIiwgInNkQWxwaGEiLCAibkFscGhhIikKCmFscGhhbWF0IDwtIGFzLm1hdHJpeChzaW1pbGFyQWxwaGEpCgptZWFuRGF0YSA8LSBtZWFuKGFscGhhRGF0YVssIkFMUEhBTE9US0EiXSkKc2REYXRhIDwtIHNkKGFscGhhRGF0YVssIkFMUEhBTE9US0EiXSkKbWVhbk4gPC0gbWVhbihzaW1pbGFyQWxwaGEkbkFscGhhKQoKcmVmU2ltIDwtIHJvd25hbWVzKGFscGhhbWF0KQpkaWZmX21lYW4gPC0gZGF0YS5mcmFtZSgpCmRpZmZfc2QgPC0gZGF0YS5mcmFtZSgpCmRpZmZfbiA8LSBkYXRhLmZyYW1lKCkKaz0wCmlsaXN0IDwtIGMoKQpmb3IoaSBpbiByZWZTaW0pewogIGlsaXN0IDwtIGMoaWxpc3QsIGkpCiAgZm9yKGogaW4gcmVmU2ltKXsKICAgIGlmIChqICUhaW4lIGlsaXN0KXsKICAgICAgayA8LSBrICsgMQogICAgICBkaWZmX21lYW5baywxXSA8LSBpCiAgICAgIGRpZmZfbWVhbltrLDJdIDwtIGoKICAgICAgbWkgPC0gc2ltaWxhckFscGhhW2ksMV0KICAgICAgbWogPC0gc2ltaWxhckFscGhhW2osMV0KICAgICAgbSA8LSBhYnMoKG1pIC0gbWopIC8gbWVhbkRhdGEpCiAgICAgIGRpZmZfbWVhbltrLDNdIDwtIG0KICAgICAgCiAgICAgIGRpZmZfc2RbaywxXSA8LSBpCiAgICAgIGRpZmZfc2RbaywyXSA8LSBqCiAgICAgIHNkaSA8LXNpbWlsYXJBbHBoYVtpLDJdCiAgICAgIHNkaiA8LSBzaW1pbGFyQWxwaGFbaiwyXQogICAgICBzZCA8LSBhYnMoKHNkaSAtIHNkaikgLyBzZERhdGEpCiAgICAgIGRpZmZfc2RbaywzXSA8LSBzZAogICAgICAKICAgICAgZGlmZl9uW2ssMV0gPC0gaQogICAgICBkaWZmX25baywyXSA8LSBqCiAgICAgIG5pIDwtc2ltaWxhckFscGhhW2ksM10KICAgICAgbmogPC0gc2ltaWxhckFscGhhW2osM10KICAgICAgbiA8LSBhYnMoKG5pIC0gbmopIC8gbWVhbk4pCiAgICAgIGRpZmZfbltrLDNdIDwtIG4KICAgIH0KICB9Cn0KCmNvbG5hbWVzKGRpZmZfbWVhbikgPC0gYygnaScsICdqJywgJ2RpZmZfbWVhbicpCndyaXRlLmNzdihkaWZmX21lYW5bb3JkZXIoZGlmZl9tZWFuJGRpZmZfbWVhbiksXSwgInNpbU5ldHMvZGlmZl9tZWFuLmNzdiIpCnN1bW1hcnkoZGlmZl9tZWFuJGRpZmZfbWVhbikKY29sbmFtZXMoZGlmZl9zZCkgPC0gYygnaScsICdqJywgJ2RpZmZfc2QnKQp3cml0ZS5jc3YoZGlmZl9zZFtvcmRlcihkaWZmX3NkJGRpZmZfc2QpLF0sICJzaW1OZXRzL2RpZmZfc2QuY3N2IikKc3VtbWFyeShkaWZmX3NkJGRpZmZfc2QpCmNvbG5hbWVzKGRpZmZfbikgPC0gYygnaScsICdqJywgJ2RpZmZfbicpCndyaXRlLmNzdihkaWZmX25bb3JkZXIoZGlmZl9uJGRpZmZfbiksXSwgInNpbU5ldHMvZGlmZl9uLmNzdiIpCnN1bW1hcnkoZGlmZl9uJGRpZmZfbikKCmBgYAoKIyMgU2ltaWxhcml0eSBvZiBtZWFuIGFscGhhCmBgYHtyIG1lYW5BbHBoYVNpbX0KY3MuYWxwaGEgPC0gZGlmZl9tZWFuW2RpZmZfbWVhbiRkaWZmX21lYW4gPCAwLjAyNSxdCmcuYWxwaGEgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLmFscGhhLCBkaXJlY3RlZD1GKQphbHBoYU0gPC0gYXMuZGF0YS5mcmFtZShhcHBseShhbHBoYW1hdFtyb3duYW1lcyhhbHBoYW1hdCkgJWluJSBWKGcuYWxwaGEpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKGFscGhhTSkgPC0gIm1lYW5fYWxwaGFzIgphbHBoYU0kcmVmIDwtIHJvd25hbWVzKGFscGhhTSkKb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcuYWxwaGEpJG5hbWUpCm9yZGVyZWRhbHBoYU0gPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgYWxwaGFNW21hdGNoKG9yZGVyZWROYW1lJFYuZy5hbHBoYS4ubmFtZSwgYWxwaGFNJHJlZiksXSlbLCJtZWFuX2FscGhhcyJdCm9yZGVyZWRhbHBoYU0gPC0gb3JkZXJlZGFscGhhTVshaXMubmEob3JkZXJlZGFscGhhTSldCnNpbWlsYXJBbHBoYSRSRUZJRCA8LSByb3duYW1lcyhzaW1pbGFyQWxwaGEpCmNsbG4uYWxwaGEgPC0gY2x1c3Rlcl9sb3V2YWluKGcuYWxwaGEpCmxheW91dCA8LSBsYXlvdXRfbmljZWx5KGcuYWxwaGEsMikKZy5hbHBoYSRsYXlvdXQgPC0gbGF5b3V0CgptZW1iIDwtIGFzLmxpc3QobWVtYmVyc2hpcChjbGxuLmFscGhhKSkKCnZlcnRleERhdGEgPC0gZGF0YS5mcmFtZShvcmRlcmVkUkVGSUQ9IG5hbWVzKG1lbWJlcnNoaXAoY2xsbi5hbHBoYSkpKQp2ZXJ0ZXhEYXRhIDwtIGRhdGEuZnJhbWUodmVydGV4RGF0YSwgc2ltaWxhckFscGhhW21hdGNoKHZlcnRleERhdGEkb3JkZXJlZFJFRklELCBzaW1pbGFyQWxwaGEkUkVGSUQpLF0pCgpmb3IgKHIgaW4gdmVydGV4RGF0YSRSRUZJRCl7CiAgdmVydGV4RGF0YVt2ZXJ0ZXhEYXRhJFJFRklEID09IHIsIm1lbWJfbWVhbiJdIDwtIG1lbWJbcl0KfQoKcGFyKG1hciA9IGMoMCwwLDAsMCkpCnBsb3QoZy5hbHBoYSwgZWRnZS53aWR0aCA9IHNxcnQoY3MuYWxwaGEkZGlmZl9tZWFuKSAqIDIsIHZlcnRleC5zaXplID0gdmVydGV4RGF0YSRtZWFuQWxwaGFeMiAqIDUsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSBtZW1iZXJzaGlwKGNsbG4uYWxwaGEpKQoKIyBtZWFuIGF2ZXJhZ2UgdmFsdWUgb2YgYWxwaGEgcmVwb3J0ZWQgYnkgZ3JvdXAKYWdncmVnYXRlKHZlcnRleERhdGFbLCJtZWFuQWxwaGEiXSwgYnk9bGlzdCh2ZXJ0ZXhEYXRhJG1lbWJfbWVhbiksIEZVTj1tZWFuTnVtKQoKYGBgCgojIyBTaW1pbGFyaXR5IG9mIHNkIGFscGhhCmBgYHtyIHNkQWxwaGFTaW19CmNzLmFscGhhIDwtIGRpZmZfc2RbZGlmZl9zZCRkaWZmX3NkIDwgMC4xLF0KZy5hbHBoYSA8LSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoY3MuYWxwaGEsIGRpcmVjdGVkPUYpCmFscGhhU0QgPC0gYXMuZGF0YS5mcmFtZShhcHBseShhbHBoYW1hdFtyb3duYW1lcyhhbHBoYW1hdCkgJWluJSBWKGcuYWxwaGEpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKGFscGhhU0QpIDwtICJtZWFuX3NkcyIKYWxwaGFTRCRyZWYgPC0gcm93bmFtZXMoYWxwaGFTRCkKb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcuYWxwaGEpJG5hbWUpCm9yZGVyZWRhbHBoYVNEIDwtIGRhdGEuZnJhbWUob3JkZXJlZE5hbWUsIGFscGhhU0RbbWF0Y2gob3JkZXJlZE5hbWUkVi5nLmFscGhhLi5uYW1lLCBhbHBoYVNEJHJlZiksXSlbLCJtZWFuX3NkcyJdCm9yZGVyZWRhbHBoYVNEIDwtIG9yZGVyZWRhbHBoYVNEWyFpcy5uYShvcmRlcmVkYWxwaGFTRCldCgpjbGxuLmFscGhhIDwtIGNsdXN0ZXJfbG91dmFpbihnLmFscGhhKQpsYXlvdXQgPC0gbGF5b3V0X25pY2VseShnLmFscGhhLDIpCmcuYWxwaGEkbGF5b3V0IDwtIGxheW91dAoKbWVtYiA8LSBhcy5saXN0KG1lbWJlcnNoaXAoY2xsbi5hbHBoYSkpCgp2ZXJ0ZXhEYXRhIDwtIGRhdGEuZnJhbWUob3JkZXJlZFJFRklEPSBuYW1lcyhtZW1iZXJzaGlwKGNsbG4uYWxwaGEpKSkKdmVydGV4RGF0YSA8LSBkYXRhLmZyYW1lKHZlcnRleERhdGEsIHNpbWlsYXJBbHBoYVttYXRjaCh2ZXJ0ZXhEYXRhJG9yZGVyZWRSRUZJRCwgc2ltaWxhckFscGhhJFJFRklEKSxdKQoKZm9yIChyIGluIHZlcnRleERhdGEkUkVGSUQpewogIHZlcnRleERhdGFbdmVydGV4RGF0YSRSRUZJRCA9PSByLCJtZW1iX3NkIl0gPC0gbWVtYltyXQp9CgpwYXIobWFyID0gYygwLDAsMCwwKSkKcGxvdChnLmFscGhhLCBlZGdlLndpZHRoID0gc3FydChjcy5hbHBoYSRkaWZmX3NkKSAqIDIsIHZlcnRleC5zaXplID0gdmVydGV4RGF0YSRzZEFscGhhICogNTAsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSBtZW1iZXJzaGlwKGNsbG4uYWxwaGEpKQoKIyBtZWFuIGF2ZXJhZ2UgdmFsdWUgb2YgYWxwaGEgcmVwb3J0ZWQgYnkgZ3JvdXAKYWdncmVnYXRlKHZlcnRleERhdGFbLCJzZEFscGhhIl0sIGJ5PWxpc3QodmVydGV4RGF0YSRtZW1iX3NkKSwgRlVOPW1lYW5OdW0pCgpgYGAKCgojIyBTaW1pbGFyaXR5IG9mIG4gYWxwaGEKYGBge3IgbkFscGhhU2ltfQpjcy5hbHBoYSA8LSBkaWZmX25bZGlmZl9uJGRpZmZfbiA8IDAuMSxdCmcuYWxwaGEgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLmFscGhhLCBkaXJlY3RlZD1GKQphbHBoYU4gPC0gYXMuZGF0YS5mcmFtZShhcHBseShhbHBoYW1hdFtyb3duYW1lcyhhbHBoYW1hdCkgJWluJSBWKGcuYWxwaGEpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKGFscGhhTikgPC0gIm1lYW5fbnMiCmFscGhhTiRyZWYgPC0gcm93bmFtZXMoYWxwaGFOKQpvcmRlcmVkTmFtZSA8LSBkYXRhLmZyYW1lKFYoZy5hbHBoYSkkbmFtZSkKb3JkZXJlZGFscGhhTiA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCBhbHBoYU5bbWF0Y2gob3JkZXJlZE5hbWUkVi5nLmFscGhhLi5uYW1lLCBhbHBoYU4kcmVmKSxdKVssIm1lYW5fbnMiXQpvcmRlcmVkYWxwaGFOIDwtIG9yZGVyZWRhbHBoYU5bIWlzLm5hKG9yZGVyZWRhbHBoYU4pXQoKY2xsbi5hbHBoYSA8LSBjbHVzdGVyX2xvdXZhaW4oZy5hbHBoYSkKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5hbHBoYSwyKQpnLmFscGhhJGxheW91dCA8LSBsYXlvdXQKCm1lbWIgPC0gYXMubGlzdChtZW1iZXJzaGlwKGNsbG4uYWxwaGEpKQoKdmVydGV4RGF0YSA8LSBkYXRhLmZyYW1lKG9yZGVyZWRSRUZJRD0gbmFtZXMobWVtYmVyc2hpcChjbGxuLmFscGhhKSkpCnZlcnRleERhdGEgPC0gZGF0YS5mcmFtZSh2ZXJ0ZXhEYXRhLCBzaW1pbGFyQWxwaGFbbWF0Y2godmVydGV4RGF0YSRvcmRlcmVkUkVGSUQsIHNpbWlsYXJBbHBoYSRSRUZJRCksXSkKCmZvciAociBpbiB2ZXJ0ZXhEYXRhJFJFRklEKXsKICB2ZXJ0ZXhEYXRhW3ZlcnRleERhdGEkUkVGSUQgPT0gciwibWVtYl9uIl0gPC0gbWVtYltyXQp9CgpwYXIobWFyID0gYygwLDAsMCwwKSkKcGxvdChnLmFscGhhLCBlZGdlLndpZHRoID0gc3FydChjcy5hbHBoYSRkaWZmX24pICogMiwgdmVydGV4LnNpemUgPSB2ZXJ0ZXhEYXRhJG5BbHBoYSAqIDAuNCwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC43LCAgZWRnZS5jdXJ2ZWQ9LjIsIHZlcnRleC5jb2xvciA9IG1lbWJlcnNoaXAoY2xsbi5hbHBoYSkpCgojIG1lYW4gYXZlcmFnZSB2YWx1ZSBvZiBhbHBoYSByZXBvcnRlZCBieSBncm91cAphZ2dyZWdhdGUodmVydGV4RGF0YVssIm5BbHBoYSJdLCBieT1saXN0KHZlcnRleERhdGEkbWVtYl9uKSwgRlVOPW1lYW5OdW0pCgoKYGBgCgojIFJlZ3Jlc3Npb24gbW9kZWxzIG9mIHNpbWlsYXJpdHkgaW4gbWVhbiBhbmQgc2QgYWxwaGEKIyMgUHJlcGFyYXRpb24gb2YgZGF0YSAKYGBge3IgcHJlcG1vZGVsbGluZ30KCiMgaW1wb3J0IGRpZmYgaW4gYWxwaGEgbWVhbnMKbWVhbkFscGhhRHlhZHMgPC0gcmVhZC5jc3YyKCJzaW1OZXRzL2RpZmZfbWVhbi5jc3YiLCBzZXA9IiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gRilbLC0xXQptZWFuQWxwaGFEeWFkcyRkeWFkSUQgPC0gcGFzdGUobWVhbkFscGhhRHlhZHMkaSwgbWVhbkFscGhhRHlhZHMkaiwgc2VwID0gIl8iKQptZWFuQWxwaGFEeWFkcyRtZWFuQWxwaGFTaW0gPC0gLWFzLm51bWVyaWMobWVhbkFscGhhRHlhZHMkZGlmZl9tZWFuKQptZWFuQWxwaGFEeWFkc1ssMTozXSA8LSBOVUxMCkRZQURTIDwtIG1lYW5BbHBoYUR5YWRzCkRZQURfSURfb3JkZXIgPC0gRFlBRFMkZHlhZElECgojIGltcG9ydCBkaWZmIGluIGFscGhhIHNkCnNkQWxwaGFEeWFkcyA8LSByZWFkLmNzdjIoInNpbU5ldHMvZGlmZl9zZC5jc3YiLCBzZXA9IiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gRilbLC0xXQpzZEFscGhhRHlhZHMkZHlhZElKIDwtIHBhc3RlKHN1YnN0cihzZEFscGhhRHlhZHMkaSwgMSwgOCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnN0cihzZEFscGhhRHlhZHMkaiwgMSwgOCksIHNlcCA9ICJfIikKc2RBbHBoYUR5YWRzJGR5YWRKSSA8LSBwYXN0ZShzdWJzdHIoc2RBbHBoYUR5YWRzJGksIDEsIDgpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzdHIoc2RBbHBoYUR5YWRzJGosIDEsIDgpLCBzZXAgPSAiXyIpCnNkQWxwaGFEeWFkcyRkeWFkSUQgPC0gaWZlbHNlKHNkQWxwaGFEeWFkcyRkeWFkSUogJWluJSBEWUFEX0lEX29yZGVyLCBzZEFscGhhRHlhZHMkZHlhZElKLCBzZEFscGhhRHlhZHMkZHlhZEpJKQoKc2RBbHBoYUR5YWRzJHNkQWxwaGFTaW0gPC0gLWFzLm51bWVyaWMoc2RBbHBoYUR5YWRzJGRpZmZfc2QpCnNkQWxwaGFEeWFkc1ssMTo1XSA8LSBOVUxMCkRZQURTIDwtIGRhdGEuZnJhbWUoRFlBRFMsIHNkQWxwaGFEeWFkc1ttYXRjaChEWUFEUyRkeWFkSUQsIHNkQWxwaGFEeWFkcyRkeWFkSUQpLCJzZEFscGhhU2ltIl0pCgojIGltcG9ydCBkaWZmIGluIG4gYWxwaGEgCm5BbHBoYUR5YWRzIDwtIHJlYWQuY3N2Migic2ltTmV0cy9kaWZmX24uY3N2Iiwgc2VwPSIsIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpWywtMV0KbkFscGhhRHlhZHMkZHlhZElKIDwtIHBhc3RlKHN1YnN0cihuQWxwaGFEeWFkcyRpLCAxLCA4KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic3RyKG5BbHBoYUR5YWRzJGosIDEsIDgpLCBzZXAgPSAiXyIpCm5BbHBoYUR5YWRzJGR5YWRKSSA8LSBwYXN0ZShzdWJzdHIobkFscGhhRHlhZHMkaSwgMSwgOCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnN0cihuQWxwaGFEeWFkcyRqLCAxLCA4KSwgc2VwID0gIl8iKQpuQWxwaGFEeWFkcyRkeWFkSUQgPC0gaWZlbHNlKG5BbHBoYUR5YWRzJGR5YWRJSiAlaW4lIERZQURfSURfb3JkZXIsIG5BbHBoYUR5YWRzJGR5YWRJSiwgbkFscGhhRHlhZHMkZHlhZEpJKQoKbkFscGhhRHlhZHMkbkFscGhhU2ltIDwtIC1hcy5udW1lcmljKG5BbHBoYUR5YWRzJGRpZmZfbikKbkFscGhhRHlhZHNbLDE6NV0gPC0gTlVMTApEWUFEUyA8LSBkYXRhLmZyYW1lKERZQURTLCBuQWxwaGFEeWFkc1ttYXRjaChEWUFEUyRkeWFkSUQsIG5BbHBoYUR5YWRzJGR5YWRJRCksIm5BbHBoYVNpbSJdKQoKIyBpbXBvcnQgc2ltaWxhcml0eSBpbiB3b3JkaW5nIGFzIGV4cGxhbmF0aW9uCndvcmRpbmdEeWFkcyA8LSByZWFkLmNzdjIoInNpbU5ldHMvU2ltaWxhcldvcmRpbmcuY3N2Iiwgc2VwPSIsIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpWywtMV0KaGVhZCh3b3JkaW5nRHlhZHMpCndvcmRpbmdEeWFkcyRkeWFkSUogPC0gcGFzdGUoc3Vic3RyKHdvcmRpbmdEeWFkcyRpLCAxLCA4KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic3RyKHdvcmRpbmdEeWFkcyRqLCAxLCA4KSwgc2VwID0gIl8iKQp3b3JkaW5nRHlhZHMkZHlhZEpJIDwtIHBhc3RlKHN1YnN0cih3b3JkaW5nRHlhZHMkaSwgMSwgOCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnN0cih3b3JkaW5nRHlhZHMkaiwgMSwgOCksIHNlcCA9ICJfIikKd29yZGluZ0R5YWRzJGR5YWRJRCA8LSBpZmVsc2Uod29yZGluZ0R5YWRzJGR5YWRJSiAlaW4lIERZQURfSURfb3JkZXIsIHdvcmRpbmdEeWFkcyRkeWFkSUosIHdvcmRpbmdEeWFkcyRkeWFkSkkpCgp3b3JkaW5nRHlhZHMkd29yZGluZ0Nvc1NpbSA8LSBhcy5udW1lcmljKHdvcmRpbmdEeWFkcyRjb3NTaW1UZXJtKQp3b3JkaW5nRHlhZHNbLDE6NV0gPC0gTlVMTApEWUFEUyA8LSBkYXRhLmZyYW1lKERZQURTLCB3b3JkaW5nRHlhZHNbbWF0Y2goRFlBRFMkZHlhZElELCB3b3JkaW5nRHlhZHMkZHlhZElEKSwid29yZGluZ0Nvc1NpbSJdKQoKIyBpbXBvcnQgc2ltaWxhcml0eSBpbiBjaXRhdGlvbiBhcyBleHBsYW5hdGlvbgpjaXRhdGlvbkR5YWRzIDwtIHJlYWQuY3N2Migic2ltTmV0cy9TaW1pbGFyQ2l0YXRpb25zLmNzdiIsIHNlcD0iLCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKVssLTFdCmNpdGF0aW9uRHlhZHMkZHlhZElKIDwtIHBhc3RlKGNpdGF0aW9uRHlhZHMkaSwgY2l0YXRpb25EeWFkcyRqLCBzZXAgPSAiXyIpCmNpdGF0aW9uRHlhZHMkZHlhZEpJIDwtIHBhc3RlKGNpdGF0aW9uRHlhZHMkaiwgY2l0YXRpb25EeWFkcyRpLCBzZXAgPSAiXyIpCmNpdGF0aW9uRHlhZHMkZHlhZElEIDwtIGlmZWxzZShjaXRhdGlvbkR5YWRzJGR5YWRJSiAlaW4lIERZQURfSURfb3JkZXIsIGNpdGF0aW9uRHlhZHMkZHlhZElKLCBjaXRhdGlvbkR5YWRzJGR5YWRKSSkKY2l0YXRpb25EeWFkcyRjaXRhdGlvbkNvc1NpbSA8LSBhcy5udW1lcmljKGNpdGF0aW9uRHlhZHMkY29zU2ltKQpjaXRhdGlvbkR5YWRzWywxOjVdIDwtIE5VTEwKRFlBRFMgPC0gZGF0YS5mcmFtZShEWUFEUywgY2l0YXRpb25EeWFkc1ttYXRjaChEWUFEUyRkeWFkSUQsIGNpdGF0aW9uRHlhZHMkZHlhZElEKSwiY2l0YXRpb25Db3NTaW0iXSkKCiMgaW1wb3J0IHNpbWlsYXJpdHkgaW4gZGlzY2lwbGluZSBhcyBleHBsYW5hdGlvbgpkaXNjaXBsaW5lRHlhZHMgPC0gcmVhZC5jc3YyKCJzaW1OZXRzL1NpbWlsYXJEaXNjaXBsaW5lc0NpdGVkX3JlbC5jc3YiLCBzZXA9IiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gRilbLC0xXQpkaXNjaXBsaW5lRHlhZHMkZHlhZElKIDwtIHBhc3RlKGRpc2NpcGxpbmVEeWFkcyRpLCBkaXNjaXBsaW5lRHlhZHMkaiwgc2VwID0gIl8iKQpkaXNjaXBsaW5lRHlhZHMkZHlhZEpJIDwtIHBhc3RlKGRpc2NpcGxpbmVEeWFkcyRqLCBkaXNjaXBsaW5lRHlhZHMkaSwgc2VwID0gIl8iKQpkaXNjaXBsaW5lRHlhZHMkZHlhZElEIDwtIGlmZWxzZShkaXNjaXBsaW5lRHlhZHMkZHlhZElKICVpbiUgRFlBRF9JRF9vcmRlciwgZGlzY2lwbGluZUR5YWRzJGR5YWRJSiwgZGlzY2lwbGluZUR5YWRzJGR5YWRKSSkKZGlzY2lwbGluZUR5YWRzJGRpc2NpcGxpbmVDb3NTaW0gPC0gYXMubnVtZXJpYyhkaXNjaXBsaW5lRHlhZHMkY29zU2ltKQpkaXNjaXBsaW5lRHlhZHNbLDE6NV0gPC0gTlVMTApEWUFEUyA8LSBkYXRhLmZyYW1lKERZQURTLCBkaXNjaXBsaW5lRHlhZHNbbWF0Y2goRFlBRFMkZHlhZElELCBkaXNjaXBsaW5lRHlhZHMkZHlhZElEKSwiZGlzY2lwbGluZUNvc1NpbSJdKQoKIyBpbXBvcnQgc2ltaWxhcml0eSBpbiBjb3VudHJpZXMgc3R1ZGllZCBhcyBjb250cm9sCmNvdW50cnlEeWFkcyA8LSByZWFkLmNzdjIoInNpbU5ldHMvU2ltaWxhckNvdW50cmllcy5jc3YiLCBzZXA9IiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gRilbLC0xXQpjb3VudHJ5RHlhZHMkZHlhZElKIDwtIHBhc3RlKGNvdW50cnlEeWFkcyRpLCBjb3VudHJ5RHlhZHMkaiwgc2VwID0gIl8iKQpjb3VudHJ5RHlhZHMkZHlhZEpJIDwtIHBhc3RlKGNvdW50cnlEeWFkcyRqLCBjb3VudHJ5RHlhZHMkaSwgc2VwID0gIl8iKQpjb3VudHJ5RHlhZHMkZHlhZElEIDwtIGlmZWxzZShjb3VudHJ5RHlhZHMkZHlhZElKICVpbiUgRFlBRF9JRF9vcmRlciwgY291bnRyeUR5YWRzJGR5YWRJSiwgY291bnRyeUR5YWRzJGR5YWRKSSkKY291bnRyeUR5YWRzJGNvdW50cnlDb3NTaW0gPC0gYXMubnVtZXJpYyhjb3VudHJ5RHlhZHMkY29zU2ltQykKY291bnRyeUR5YWRzWywxOjVdIDwtIE5VTEwKRFlBRFMgPC0gZGF0YS5mcmFtZShEWUFEUywgY291bnRyeUR5YWRzW21hdGNoKERZQURTJGR5YWRJRCwgY291bnRyeUR5YWRzJGR5YWRJRCksImNvdW50cnlDb3NTaW0iXSkKCiMgaW1wb3J0IHNpbWlsYXJpdHkgaW4gZGVjYWRlcyBzdHVkaWVkIGFzIGNvbnRyb2wKZGVjYWRlRHlhZHMgPC0gcmVhZC5jc3YyKCJzaW1OZXRzL1NpbWlsYXJEZWNhZGVzLmNzdiIsIHNlcD0iLCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKVssLTFdCmRlY2FkZUR5YWRzJGR5YWRJSiA8LSBwYXN0ZShkZWNhZGVEeWFkcyRpLCBkZWNhZGVEeWFkcyRqLCBzZXAgPSAiXyIpCmRlY2FkZUR5YWRzJGR5YWRKSSA8LSBwYXN0ZShkZWNhZGVEeWFkcyRqLCBkZWNhZGVEeWFkcyRpLCBzZXAgPSAiXyIpCmRlY2FkZUR5YWRzJGR5YWRJRCA8LSBpZmVsc2UoZGVjYWRlRHlhZHMkZHlhZElKICVpbiUgRFlBRF9JRF9vcmRlciwgZGVjYWRlRHlhZHMkZHlhZElKLCBkZWNhZGVEeWFkcyRkeWFkSkkpCmRlY2FkZUR5YWRzJGRlY2FkZUNvc1NpbSA8LSBhcy5udW1lcmljKGRlY2FkZUR5YWRzJGNvc1NpbUN0KQpkZWNhZGVEeWFkc1ssMTo1XSA8LSBOVUxMCkRZQURTIDwtIGRhdGEuZnJhbWUoRFlBRFMsIGRlY2FkZUR5YWRzW21hdGNoKERZQURTJGR5YWRJRCwgZGVjYWRlRHlhZHMkZHlhZElEKSwiZGVjYWRlQ29zU2ltIl0pCgojIGltcG9ydCBzaW1pbGFyaXR5IGluIGNpdHkgZGVmaW5pdGlvbiB1c2VkIGFzIGNvbnRyb2wKY2l0eURlZkR5YWRzIDwtIHJlYWQuY3N2Migic2ltTmV0cy9TaW1pbGFyQ2l0aWVzLmNzdiIsIHNlcD0iLCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKVssLTFdCmNpdHlEZWZEeWFkcyRkeWFkSUogPC0gcGFzdGUoY2l0eURlZkR5YWRzJGksIGNpdHlEZWZEeWFkcyRqLCBzZXAgPSAiXyIpCmNpdHlEZWZEeWFkcyRkeWFkSkkgPC0gcGFzdGUoY2l0eURlZkR5YWRzJGosIGNpdHlEZWZEeWFkcyRpLCBzZXAgPSAiXyIpCmNpdHlEZWZEeWFkcyRkeWFkSUQgPC0gaWZlbHNlKGNpdHlEZWZEeWFkcyRkeWFkSUogJWluJSBEWUFEX0lEX29yZGVyLCBjaXR5RGVmRHlhZHMkZHlhZElKLCBjaXR5RGVmRHlhZHMkZHlhZEpJKQpjaXR5RGVmRHlhZHMkY2l0eURlZkNvc1NpbSA8LSBhcy5udW1lcmljKGNpdHlEZWZEeWFkcyRjb3NTaW1DdCkKY2l0eURlZkR5YWRzWywxOjVdIDwtIE5VTEwKRFlBRFMgPC0gZGF0YS5mcmFtZShEWUFEUywgY2l0eURlZkR5YWRzW21hdGNoKERZQURTJGR5YWRJRCwgY2l0eURlZkR5YWRzJGR5YWRJRCksImNpdHlEZWZDb3NTaW0iXSkKCmNvbG5hbWVzKERZQURTKSA8LSBjKCJkeWFkSUQiLCJtZWFuQWxwaGFTaW0iLCAic2RBbHBoYVNpbSIsICJuQWxwaGFTaW0iLCAKICAgICAgICAgICAgICAgICAgICAgImZ1bGxUZXh0Q29zU2ltIiwgImV4dGVybmFsQ2l0YXRpb25Db3NTaW0iLCAiZGlzY2lwbGluZUNpdGF0aW9uQ29zU2ltIiwKICAgICAgICAgICAgICAgICAgICAgImNvdW50cmllc0Nvc1NpbSIsICJkZWNhZGVzQ29zU2ltIiwgImNpdHlEZWZDb3NTaW0iKQoKIyBzY2FsZSBhbGwgdmFyaWFibGVzCkRZQURTJG1lYW5BbHBoYVNpbV9zY2FsZWQgPC0gc2NhbGUoRFlBRFMkbWVhbkFscGhhU2ltKQpEWUFEUyRzZEFscGhhU2ltX3NjYWxlZCA8LSBzY2FsZShEWUFEUyRzZEFscGhhU2ltKQpEWUFEUyRuQWxwaGFTaW1fc2NhbGVkIDwtIHNjYWxlKERZQURTJG5BbHBoYVNpbSkKRFlBRFMkZnVsbFRleHRDb3NTaW1fc2NhbGVkIDwtIHNjYWxlKERZQURTJGZ1bGxUZXh0Q29zU2ltKQpEWUFEUyRleHRlcm5hbENpdGF0aW9uQ29zU2ltX3NjYWxlZCA8LSBzY2FsZShEWUFEUyRleHRlcm5hbENpdGF0aW9uQ29zU2ltKQpEWUFEUyRkaXNjaXBsaW5lQ2l0YXRpb25Db3NTaW1fc2NhbGVkIDwtIHNjYWxlKERZQURTJGRpc2NpcGxpbmVDaXRhdGlvbkNvc1NpbSkKRFlBRFMkY291bnRyaWVzQ29zU2ltX3NjYWxlZCA8LSBzY2FsZShEWUFEUyRjb3VudHJpZXNDb3NTaW0pCkRZQURTJGRlY2FkZXNDb3NTaW1fc2NhbGVkIDwtIHNjYWxlKERZQURTJGRlY2FkZXNDb3NTaW0pCkRZQURTJGNpdHlEZWZDb3NTaW1fc2NhbGVkIDwtIHNjYWxlKERZQURTJGNpdHlEZWZDb3NTaW0pCgpEWUFEU3dpdGhOQSA8LSBEWUFEUwpEWUFEUyA8LSBEWUFEU1tjb21wbGV0ZS5jYXNlcyhEWUFEUyksXQoKbW9kZWxkYXRhPC0gRFlBRFNbLGMoImR5YWRJRCIsIm1lYW5BbHBoYVNpbV9zY2FsZWQiLCAic2RBbHBoYVNpbV9zY2FsZWQiLCAibkFscGhhU2ltX3NjYWxlZCIsCiAgICAgICAgICAgICAgICAgICAgICJmdWxsVGV4dENvc1NpbV9zY2FsZWQiLCAiZXh0ZXJuYWxDaXRhdGlvbkNvc1NpbV9zY2FsZWQiLCAiZGlzY2lwbGluZUNpdGF0aW9uQ29zU2ltX3NjYWxlZCIsCiAgICAgICAgICAgICAgICAgICAgICJjb3VudHJpZXNDb3NTaW1fc2NhbGVkIiwgImRlY2FkZXNDb3NTaW1fc2NhbGVkIiwgImNpdHlEZWZDb3NTaW1fc2NhbGVkIildCmNvbG5hbWVzKG1vZGVsZGF0YSkgPC0gYygiSUQiLCAiYWxwaGEiLCAic2RfYWxwaGEiLCAibl9lc3RpbSIsInRleHQiLCAiY2l0YXRpb24iLCAiZGlzY2lwbGluZSIsICJjb3VudHJ5IiwgImRlY2FkZSIsICJjaXR5IikKCmBgYAoKCiMjIE1vZGVscyBvZiBtZWFuIGFscGhhCmBgYHtyIG1lYW5BbHBoYU1vZGVsc30KCmZ0bV9hIDwtIGxtKGRhdGEgPSBtb2RlbGRhdGEsCiAgICAgICAgICAgIGZvcm11bGEgPSBhbHBoYSB+IHRleHQsCiAgICAgICAgICAgIG5hLmFjdGlvbiA9IG5hLm9taXQpCmVjbV9hIDwtIGxtKGRhdGEgPSBtb2RlbGRhdGEsCiAgICAgICAgICAgIGZvcm11bGEgPSBhbHBoYSB+IGNpdGF0aW9uLAogICAgICAgICAgICBuYS5hY3Rpb24gPSBuYS5vbWl0KQpkY21fYSA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICBmb3JtdWxhID0gYWxwaGEgfiBkaXNjaXBsaW5lLAogICAgICAgICAgICBuYS5hY3Rpb24gPSBuYS5vbWl0KQpjdHJtX2EgPC0gbG0oZGF0YSA9IG1vZGVsZGF0YSwKICAgICAgICAgICAgZm9ybXVsYSA9IGFscGhhIH4gbl9lc3RpbSArCiAgICAgICAgICAgICBjb3VudHJ5ICogZGVjYWRlICogY2l0eSwKICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEub21pdCkKZnVsbG1vZGVsX2EgPC0gbG0oZGF0YSA9IG1vZGVsZGF0YSwKICAgICAgICAgICAgZm9ybXVsYSA9IGFscGhhIH4gCiAgICAgICAgICAgICAgdGV4dCArIGNpdGF0aW9uICsgZGlzY2lwbGluZSArIG5fZXN0aW0gKwogICAgICAgICAgICAgIGNvdW50cnkgKiBkZWNhZGUgKiBjaXR5LAogICAgICAgICAgICBuYS5hY3Rpb24gPSBuYS5vbWl0KQoKc2dtPC0gc3RhcmdhemVyKGZ0bV9hLCBlY21fYSwgZGNtX2EsCiAgICAgICAgICBjdHJtX2EsCiAgICAgICAgICBmdWxsbW9kZWxfYSwKICAgICAgICAgIHR5cGU9InRleHQiLCBvdXQ9InJlc3VsdHMvbW9kZWxfY29tcF9yZXN1bHRzX21lYW5BbHBoYS5odG1sIiwgZm9udC5zaXplID0gInNtYWxsIiwgY29sdW1uLnNlcC53aWR0aCA9ICIxcHQiKQoKYGBgCgojIyBNb2RlbHMgb2Ygc2QgYWxwaGEKYGBge3Igc2RBbHBoYU1vZGVsc30KCmZ0bV9zZCA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICBmb3JtdWxhID0gc2RfYWxwaGEgfiB0ZXh0LAogICAgICAgICAgICBuYS5hY3Rpb24gPSBuYS5vbWl0KQplY21fc2QgPC0gbG0oZGF0YSA9IG1vZGVsZGF0YSwKICAgICAgICAgICAgZm9ybXVsYSA9IHNkX2FscGhhIH4gY2l0YXRpb24sCiAgICAgICAgICAgIG5hLmFjdGlvbiA9IG5hLm9taXQpCmRjbV9zZCA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICBmb3JtdWxhID0gc2RfYWxwaGEgfiBkaXNjaXBsaW5lLAogICAgICAgICAgICBuYS5hY3Rpb24gPSBuYS5vbWl0KQogbl9zZCA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICAgZm9ybXVsYSA9IHNkX2FscGhhIH4gbl9lc3RpbSwKICAgICAgICAgICAgIG5hLmFjdGlvbiA9IG5hLm9taXQpCmN0cm1fc2QgPC0gbG0oZGF0YSA9IG1vZGVsZGF0YSwKICAgICAgICAgICAgIGZvcm11bGEgPSBzZF9hbHBoYSB+IAogICAgICAgICAgICAgICBjb3VudHJ5ICogZGVjYWRlICogY2l0eSwKICAgICAgICAgICAgIG5hLmFjdGlvbiA9IG5hLm9taXQpCmZ1bGxtb2RlbF9zZCA8LSBsbShkYXRhID0gbW9kZWxkYXRhLAogICAgICAgICAgICAgICAgICBmb3JtdWxhID0gc2RfYWxwaGEgfiAKICAgICAgICAgICAgICAgICAgICB0ZXh0ICsgY2l0YXRpb24gKyBkaXNjaXBsaW5lICsgbl9lc3RpbSArCiAgICAgICAgICAgICAgICAgICAgY291bnRyeSAqIGRlY2FkZSAqIGNpdHksCiAgICAgICAgICAgICAgICAgIG5hLmFjdGlvbiA9IG5hLm9taXQpCgpzZ208LSBzdGFyZ2F6ZXIoZnRtX3NkLCBlY21fc2QsIGRjbV9zZCxuX3NkLAogICAgICAgICAgICAgICAgY3RybV9zZCwKICAgICAgICAgICAgICAgIGZ1bGxtb2RlbF9zZCwKICAgICAgICAgICAgICAgIHR5cGU9InRleHQiLCBvdXQ9InJlc3VsdHMvbW9kZWxfY29tcF9yZXN1bHRzX3NkQWxwaGEuaHRtbCIsIGZvbnQuc2l6ZSA9ICJzbWFsbCIsIGNvbHVtbi5zZXAud2lkdGggPSAiMXB0IikKCmBgYAoKIyMgUmVzaWR1YWxzIGFuYWx5c2lzCmBgYHtyIHJlc2lkdWFscywgd2FybmluZz1GQUxTRX0KCm1vZGVsZGF0YSRyZXMgPC0gZnVsbG1vZGVsX2EkcmVzaWR1YWxzCmhlYWQobW9kZWxkYXRhW29yZGVyKC1tb2RlbGRhdGEkcmVzKSxdKQptb2RlbGRhdGEkaSA8LSBzdWJzdHIobW9kZWxkYXRhJElELCAxLDgpCm1vZGVsZGF0YSRqIDwtIHN1YnN0cihtb2RlbGRhdGEkSUQsIDEwLCAxNykKCmNzLnJlc2lkdWFsc19yZXNQb3MgPC0gbW9kZWxkYXRhW21vZGVsZGF0YSRyZXMgPiAxLjEsYygiaSIsICJqIiwgInJlcyIpXQpnLnJlc2lkdWFscyA8LSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoY3MucmVzaWR1YWxzX3Jlc1BvcywgZGlyZWN0ZWQ9RikKcmVzUG9zIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkoYWxwaGFtYXRbcm93bmFtZXMoYWxwaGFtYXQpICVpbiUgVihnLnJlc2lkdWFscykkbmFtZSxdLDEsIEZVTiA9IG5vcm1fdmVjKSkKY29sbmFtZXMocmVzUG9zKSA8LSAicmVzaWR1YWxzIgpyZXNQb3MkcmVmIDwtIHJvd25hbWVzKHJlc1BvcykKb3JkZXJlZE5hbWUgPC0gZGF0YS5mcmFtZShWKGcucmVzaWR1YWxzKSRuYW1lKQpvcmRlcmVkcmVzaWR1YWxzUmVzIDwtIGRhdGEuZnJhbWUob3JkZXJlZE5hbWUsIHJlc1Bvc1ttYXRjaChvcmRlcmVkTmFtZSRWLmcucmVzaWR1YWxzLi5uYW1lLCByZXNQb3MkcmVmKSxdKVssInJlc2lkdWFscyJdCm9yZGVyZWRyZXNpZHVhbHNSZXMgPC0gb3JkZXJlZHJlc2lkdWFsc1Jlc1shaXMubmEob3JkZXJlZHJlc2lkdWFsc1JlcyldCgpsYXlvdXQgPC0gbGF5b3V0X25pY2VseShnLnJlc2lkdWFscywyKQpnLnJlc2lkdWFscyRsYXlvdXQgPC0gbGF5b3V0CnBhcihtYXIgPSBjKDAsMCwxLDApKQpwbG90KGcucmVzaWR1YWxzLCBlZGdlLndpZHRoID0gc3FydChjcy5yZXNpZHVhbHNfcmVzUG9zJHJlcykgKiAyLCB2ZXJ0ZXguc2l6ZSA9IDIsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuNywgIGVkZ2UuY3VydmVkPS4yLCB2ZXJ0ZXguY29sb3IgPSAiZ3JlZW4iLCBlZGdlLmNvbG9yID0gImNvcmFsMyIsIAogICAgIG1haW4gPSAiTW9zdCBwb3NpdGl2ZSByZXNpZHVhbHMgaW4gbWVhbiBhbHBoYSBzaW1pbGFyaXR5IikKCgoKY3MucmVzaWR1YWxzX3Jlc05lZyA8LSBtb2RlbGRhdGFbbW9kZWxkYXRhJHJlcyA8IC0yLGMoImkiLCAiaiIsICJyZXMiKV0KZy5yZXNpZHVhbHMgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLnJlc2lkdWFsc19yZXNOZWcsIGRpcmVjdGVkPUYpCnJlc05lZyA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KGFscGhhbWF0W3Jvd25hbWVzKGFscGhhbWF0KSAlaW4lIFYoZy5yZXNpZHVhbHMpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKHJlc05lZykgPC0gInJlc2lkdWFscyIKcmVzTmVnJHJlZiA8LSByb3duYW1lcyhyZXNOZWcpCm9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLnJlc2lkdWFscykkbmFtZSkKb3JkZXJlZHJlc2lkdWFsc1JlcyA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCByZXNOZWdbbWF0Y2gob3JkZXJlZE5hbWUkVi5nLnJlc2lkdWFscy4ubmFtZSwgcmVzTmVnJHJlZiksXSlbLCJyZXNpZHVhbHMiXQpvcmRlcmVkcmVzaWR1YWxzUmVzIDwtIG9yZGVyZWRyZXNpZHVhbHNSZXNbIWlzLm5hKG9yZGVyZWRyZXNpZHVhbHNSZXMpXQoKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5yZXNpZHVhbHMsMikKZy5yZXNpZHVhbHMkbGF5b3V0IDwtIGxheW91dApwYXIobWFyID0gYygwLDAsMSwwKSkKcGxvdChnLnJlc2lkdWFscywgZWRnZS53aWR0aCA9IHNxcnQoY3MucmVzaWR1YWxzX3Jlc05lZyRyZXMpICogMiwgdmVydGV4LnNpemUgPSAyLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gIm9yYW5nZSIsIGVkZ2UuY29sb3IgPSAiZG9kZ2VyYmx1ZTMiLCAKICAgICBtYWluID0gIk1vc3QgbmVnYXRpdmUgcmVzaWR1YWxzIGluIG1lYW4gYWxwaGEgc2ltaWxhcml0eSIpCgoKCm1vZGVsZGF0YSRyZXMgPC0gZnVsbG1vZGVsX3NkJHJlc2lkdWFscwptb2RlbGRhdGEkaSA8LSBzdWJzdHIobW9kZWxkYXRhJElELCAxLDgpCm1vZGVsZGF0YSRqIDwtIHN1YnN0cihtb2RlbGRhdGEkSUQsIDEwLCAxNykKCmNzLnJlc2lkdWFsc19yZXNQb3MgPC0gbW9kZWxkYXRhW21vZGVsZGF0YSRyZXMgPiAxLGMoImkiLCAiaiIsICJyZXMiKV0KZy5yZXNpZHVhbHMgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGNzLnJlc2lkdWFsc19yZXNQb3MsIGRpcmVjdGVkPUYpCnJlc1BvcyA8LSBhcy5kYXRhLmZyYW1lKGFwcGx5KGFscGhhbWF0W3Jvd25hbWVzKGFscGhhbWF0KSAlaW4lIFYoZy5yZXNpZHVhbHMpJG5hbWUsXSwxLCBGVU4gPSBub3JtX3ZlYykpCmNvbG5hbWVzKHJlc1BvcykgPC0gInJlc2lkdWFscyIKcmVzUG9zJHJlZiA8LSByb3duYW1lcyhyZXNQb3MpCm9yZGVyZWROYW1lIDwtIGRhdGEuZnJhbWUoVihnLnJlc2lkdWFscykkbmFtZSkKb3JkZXJlZHJlc2lkdWFsc1JlcyA8LSBkYXRhLmZyYW1lKG9yZGVyZWROYW1lLCByZXNQb3NbbWF0Y2gob3JkZXJlZE5hbWUkVi5nLnJlc2lkdWFscy4ubmFtZSwgcmVzUG9zJHJlZiksXSlbLCJyZXNpZHVhbHMiXQpvcmRlcmVkcmVzaWR1YWxzUmVzIDwtIG9yZGVyZWRyZXNpZHVhbHNSZXNbIWlzLm5hKG9yZGVyZWRyZXNpZHVhbHNSZXMpXQoKI2NsbG4ucmVzaWR1YWxzIDwtIGNsdXN0ZXJfbG91dmFpbihnLnJlc2lkdWFscykKbGF5b3V0IDwtIGxheW91dF9uaWNlbHkoZy5yZXNpZHVhbHMsMikKZy5yZXNpZHVhbHMkbGF5b3V0IDwtIGxheW91dApwYXIobWFyID0gYygwLDAsMSwwKSkKcGxvdChnLnJlc2lkdWFscywgZWRnZS53aWR0aCA9IHNxcnQoY3MucmVzaWR1YWxzX3Jlc1BvcyRyZXMpICogMiwgdmVydGV4LnNpemUgPSAyLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjcsICBlZGdlLmN1cnZlZD0uMiwgdmVydGV4LmNvbG9yID0gImdyZWVuIiwgZWRnZS5jb2xvciA9ICJjb3JhbDMiLCAKICAgICBtYWluID0gIk1vc3QgcG9zaXRpdmUgcmVzaWR1YWxzIGluIHNkIGFscGhhIHNpbWlsYXJpdHkiKQoKCgpjcy5yZXNpZHVhbHNfcmVzTmVnIDwtIG1vZGVsZGF0YVttb2RlbGRhdGEkcmVzIDwgLTEuNSxjKCJpIiwgImoiLCAicmVzIildCmcucmVzaWR1YWxzIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShjcy5yZXNpZHVhbHNfcmVzTmVnLCBkaXJlY3RlZD1GKQpyZXNOZWcgPC0gYXMuZGF0YS5mcmFtZShhcHBseShhbHBoYW1hdFtyb3duYW1lcyhhbHBoYW1hdCkgJWluJSBWKGcucmVzaWR1YWxzKSRuYW1lLF0sMSwgRlVOID0gbm9ybV92ZWMpKQpjb2xuYW1lcyhyZXNOZWcpIDwtICJyZXNpZHVhbHMiCnJlc05lZyRyZWYgPC0gcm93bmFtZXMocmVzTmVnKQpvcmRlcmVkTmFtZSA8LSBkYXRhLmZyYW1lKFYoZy5yZXNpZHVhbHMpJG5hbWUpCm9yZGVyZWRyZXNpZHVhbHNSZXMgPC0gZGF0YS5mcmFtZShvcmRlcmVkTmFtZSwgcmVzTmVnW21hdGNoKG9yZGVyZWROYW1lJFYuZy5yZXNpZHVhbHMuLm5hbWUsIHJlc05lZyRyZWYpLF0pWywicmVzaWR1YWxzIl0Kb3JkZXJlZHJlc2lkdWFsc1JlcyA8LSBvcmRlcmVkcmVzaWR1YWxzUmVzWyFpcy5uYShvcmRlcmVkcmVzaWR1YWxzUmVzKV0KCmxheW91dCA8LSBsYXlvdXRfbmljZWx5KGcucmVzaWR1YWxzLDIpCmcucmVzaWR1YWxzJGxheW91dCA8LSBsYXlvdXQKcGFyKG1hciA9IGMoMCwwLDEsMCkpCnBsb3QoZy5yZXNpZHVhbHMsIGVkZ2Uud2lkdGggPSBzcXJ0KGNzLnJlc2lkdWFsc19yZXNOZWckcmVzKSAqIDIsIHZlcnRleC5zaXplID0gMiwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC43LCAgZWRnZS5jdXJ2ZWQ9LjIsIHZlcnRleC5jb2xvciA9ICJvcmFuZ2UiLCBlZGdlLmNvbG9yID0gImRvZGdlcmJsdWUzIiwgCiAgICAgbWFpbiA9ICJNb3N0IG5lZ2F0aXZlIHJlc2lkdWFscyBpbiBzZCBhbHBoYSBzaW1pbGFyaXR5IikKCgpgYGAKCg==