1 PRE

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

replacemask snc: #replacemask# 14061.5

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

plot(cars)

1.1 cats

Add a new katze hund dreimal schwarz by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

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

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

2 process

2.1 preliminary

load libraries and set SBC ressources adress

#20240103(07.42)
###############################################################
### this script runs without local files, all data fetched from online sources.
###############################################################################
R.1<-"https://www.linguistics.ucsb.edu/research/santa-barbara-corpus"
Q.2<-"https://www.linguistics.ucsb.edu/sites/secure.lsit.ucsb.edu.ling.d7/files/sitefiles/research/SBC/SBCorpus.zip"
library(utils)
library(stringi)
library(readr)
library(quanteda.textstats) 
library(quanteda)
library(udpipe) # for pos tagging
library(writexl)

#knitr::write_bib(c(.packages()), "packages.bib")

2.1.1 load pos-tag model and corpus .zip

local<-"~/boxHKW/21S/DH/local/SPUND/corpuslx"
udpipepath<-sprintf("%s/english-ewt-ud-2.5-191206.udpipe",local)
### if not yet, the model must be downloaded, comment in above line 

get.udp<-function(){
udpipe_download_model("english",model_dir = tempdir("md"))
mdf<-list.files(tempdir())
mdw<-grep(".udpipe",mdf)
mdfile<-paste0(tempdir(),"/",mdf[mdw])
md<-udpipe_load_model(mdfile)
}

### if the model is not on disk, it is downloaded
ifelse(exists("udpipepath"),md<-udpipe_load_model(udpipepath),md<-get.udp())
getwd()

### tempfile to store zip
sbctemp<-tempfile("SBCtemp.zip")
sbctempdir<-tempdir()
download.file(Q.2,sbctemp)
unzip(sbctemp,exdir = sbctempdir)

sbctrn<-paste0(sbctempdir,"/TRN/")
filestrn<-list.files(sbctrn)
trndf<-data.frame(scb=NA,id=NA,text=NA)
#k<-1

2.1.2 read in files

for(k in 1:length(filestrn)){
  #cat(k,"\n")
trntemp<-read_delim(paste0(sbctrn,filestrn[k]), 
                         delim = "\t", escape_double = FALSE, 
                         trim_ws = TRUE,col_names = c("id","spk","text"))

l1<-length(trntemp)
trntext<-trntemp[,l1]
colnames(trntext)<-"text"
trntemp.2<-data.frame(scb=k,id=1:length(trntext$text),text=trntext)
  
trndf<-rbind(trndf,trntemp.2)

}

2.1.2.1 which look like this

trn.doc.1<-readLines(paste0(sbctrn,filestrn[1]))
print(trn.doc.1[1:15])

2.1.3 subsets

create subsets for /make/ /take/ /give/

trndf.2<-trndf[2:length(trndf$scb),]
trndf.2$lfd<-1:length(trndf.2$scb)
rownames(trndf.2)<-trndf.2$lfd
#trndf$lfd<-1:length(trndf$scb)
trndf<-trndf.2

2.2 annotate for /make/

the annotation of concrete/light use of lemma /make/ was done in a subset table of the corpus, assigning either 0 for concrete and 1 for light use of the verb in context. concrete use would include forms with objects of the lemma that (for /make/) that (in the sense of the alternate constructions) can be also produced, built, generated, created. these are obvious semantic alternatives of /make/ defined in (Mehl 2021).

######################################
### instances concrete vs. light
### Q.1: (Mehl 2021)
i.make.w<-c(concrete=68,light=321) #17% vs. 83% written ICE 
i.make.s<-c(concrete=96,light=353) #spoken ICE
i.take<-c(con=62,light=85) 
i.give<-c(con=52,light=167) 
###########################
#trndf_sf<-trndf # saved created, load only annotations dataframe
# dtemp<-tempfile()
# download.file("https://github.com/esteeschwarz/SPUND-LX/raw/main/corpusLX/14015-HA/data/SBC.ann.df.RData",dtemp)
# load(dtemp)
# get.ann.x<-function(scb,ann.df){
#   trndf.lm<-cbind(scb,ann.df)
# }
# trndf.lm<-get.ann.x(trndf.2,scb.ann.df)

2.3 PoS tagging

tokenize and lemmatize/pos-tag df

################
### new with preloaded/built df
#load("~/boxHKW/21S/DH/local/SPUND/corpuslx/stefanowitsch/HA/data/trndf.lm.cpt.RData")
scb.unique<-unique(trndf$scb)
k<-1
#scb.unique<-unique(trndf$scb)
scb<-1
# scb.ann.list<-list()

write.ann.df<-function(df){
scb.ann.list<-list()
scb.token.list<-list()
trndf.lm<-df  
for(scb in 1:length(scb.unique)){
  cat(scb,"\n")
###14043.
  sbc<-trndf.lm
  scb.id<-scb.unique[scb]
  scb.sub<-subset(sbc,sbc$scb==scb.id)
  colnames(scb.sub)[1]<-"doc_id"
  scb.sub$text<-gsub("[+%?~,-.0-9()=<>@]|\\]|\\[","",scb.sub$text)
  scb.sub$text<-gsub("(^ )","",scb.sub$text)
  colnames(scb.sub)[3]<-"text_field"
  sbc.sub.c<-corpus(scb.sub,docid_field = 'doc_id',text_field = 'text_field',unique_docnames = F)
  an4<-udpipe_annotate(md,x=sbc.sub.c,tokenizer="tokenizer",tagger = "default",trace = 2)
  ###wks.
  an7<-data.frame(an4)
  an7$doc_id<-gsub("doc","",an7$doc_id)
  colnames(an7)[1]<-"line"
  an8<-an7[,c(1,4,5,6,7,8,9,10,11,12)]
  an8$sbc.id<-scb.id
  an8<-an8[,c(11,1,2,3,4,5,6,7,8,9,10)]
  an8$alt<-"a-other"
  an8$light<-NA
  line.u<-unique(an8$line)
ns.list<-paste0("sbc",scb.id)
scb.ann.list[[ns.list]]<-an8
}
return(scb.ann.list)
}
### call above function which tokenizes, lemmatizes and postags the corpus & writes xlsx-tables per interview / returns dataframe (list type) of annotated corpus
sbc.token.list<-write.ann.df(trndf.lm)
ann.x<-write.ann.df(trndf.lm)
scb.pos.df.list<-ann.x
scb.ann.list<-scb.pos.df.list
#save(scb.pos.df.list,file = "~/boxHKW/21S/DH/local/SPUND/corpuslx/stefanowitsch/HA/data/scb.ann.list.pos-all-dfs.RData")
#wks.
#save(scb.ann.list,file="~/boxHKW/21S/DH/local/SPUND/corpuslx/stefanowitsch/HA/data/scb.ann.list.RData")
#t<-grep("token",colnames(scb.ann.list$sbc1))
t<-colnames(scb.ann.list$sbc1)=="token"
t<-which(t)
scbns<-colnames(scb.ann.list$sbc1)
### this is necessary for pepper to recognize the token column in the df
scbns[t]<-"tok"
scbns<-gsub("\\.","_",scbns)
rename.list<-function(x){
  x2<-data.frame(x)
  colnames(x2)=scbns
  return(x2)
}
scb.ann.list.nr<-lapply(scb.ann.list, rename.list)
head(scb.ann.list.nr$sbc1)
scb.ann.list<-scb.ann.list.nr

### same as above writing xlsx, here from annotated list
# for(k in 1:length(scb.ann.list)){
#   colnames(scb.ann.list[[k]])<-scbns
#   xldir<-"~/boxHKW/21S/DH/local/SPUND/corpuslx/annis/xls"
#   ns.df<-paste0(xldir,"/SCB-pos_",k,".xlsx")
#   write_xlsx(scb.ann.list[[k]],ns.df)
#   
#   }
#x<-scb.ann.list$sbc1
export.ann<-function(x){
  ns<-colnames(x)
  wns<-ns=="sentence"|ns=="tok"
  wns
  x1<-x[,!wns]
  return(x1)
}
sbc.only.pos.annotation<-lapply(scb.ann.list, export.ann)
#save(sbc.only.pos.annotation,file = "~/Documents/GitHub/SPUND-LX/corpusLX/14015-HA/data/sbc.only.pos.annotation.RData")

2.4 create ANNIS corpus

the evaluation statistics can be done already with the df, but for different purposes e.g. the better visualisation of the corpus and extensive queries an ANNIS (Druskat, Gast, and Krause (2016)) has been created.

call to external scripts which run pepper on the provided xlsx and create an ANNIS graph file for import to the ANNIS installation.

pepper.call("~/boxHKW/21S/DH/local/SPUND/corpuslx/annis/r-conxl5.pepper","SBC_v1.0.1","SBC_v1.0.1")
pepper.call("~/boxHKW/21S/DH/local/SPUND/corpuslx/annis/r-conxl6.pepper","SBC_v1.0.1","SBC_v1.0.1")
zipannis("SBC_annis","SBC_annis.zip")

2.4.1 xlsx to treetagger format

configuration xml: r-conxl5.pepper

<?xml version='1.0' encoding='UTF-8'?>
<pepper-job id="tt001" version="1.0">
<importer name="SpreadsheetImporter" path="./xls"/> 
<exporter name="TreetaggerExporter" path="./SBC_v1.0.1/"/>
</pepper-job>

2.4.2 treetagger to ANNIS graph

configuration xml: r-conxl6.pepper

<?xml version='1.0' encoding='UTF-8'?>
<pepper-job id="tt001" version="1.0">
<importer name="TreetaggerImporter" path="./SBC_v1.0.1/">
</importer>
<exporter name="ANNISExporter" path="./SBC_annis/">
</exporter>
</pepper-job>

3 frequency evaluations

3.1 get matrix df of annotated list

# dtemp<-tempfile()
# download.file("https://github.com/esteeschwarz/SPUND-LX/raw/main/corpusLX/14015-HA/data/sbc.only.pos.annotation.RData",dtemp)
# load(dtemp)
get.corpus.deprel<-function(x){
  ns<-colnames(x)
  x2<-cbind()
  # assign unique id to token
  x$sbc.token.id<-as.double(paste0(x$sbc_id,"_",  1:length(x$sbc.id)))  
  x$pos.0<-"lfd.pos"  
  x$obj<-NA
  tdf<-t(x)
  rtdf<-rownames(tdf)
  rtdf.0<-which(rtdf=="pos.0")
  all.zero<-which(tdf=="lfd.pos")-rtdf.0
  #########################################
  pos.deprel<-all.zero+grep("dep",rtdf)
  pos.head<-all.zero+grep("head",rtdf)
  pos.upos<-all.zero+grep("upos",rtdf)
  pos.lemma<-all.zero+grep("lemma",rtdf)
  pos.token<-all.zero+which(rtdf=="token")
  pos.token.id<-all.zero+which(rtdf=="token_id")
  #########################
  t.head<-pos.head
  t.id<-pos.token.id
  t.tag<-pos.upos
  t.token<-pos.token
  t.lemma<-pos.lemma
  t.deprel<-pos.deprel
  m.h.t.0<-which(tdf[t.head]==0)
  h.t.pos.rel<-as.double(tdf[t.id])-as.double(tdf[t.head])
  h.t.pos.rel[m.h.t.0]<-0
  h.t.pos.abs<-t.id-(h.t.pos.rel*length(tdf[,1]))
  h.t.value<-t.token-(h.t.pos.rel*length(tdf[,1]))
  m1<-which(h.t.value<0)
  sum(m1)
  h.t.value[m1]<-1 # prevent negative subscripts
  h.l.value<-t.lemma-(h.t.pos.rel*length(tdf[,1]))
  m2<-which(h.l.value<0)
  sum(m2)
  h.l.value[m2]<-1 # prevent negative subscripts
  head(tdf[h.l.value])
  ####################
  all.obj<-tdf=="obj"
  all.ob.w<-which(all.obj)
  all.ob.w
  obj.head<-as.double(all.ob.w-1)
  tdf[obj.head]
  obj.tag<-all.ob.w-4 #4 
  tdf[obj.tag]
  obj.lemma<-all.ob.w-5 #5
  tdf[obj.lemma]
  obj.token<-all.ob.w-6 #6
  tdf[obj.token]
  obj.id<-as.double(all.ob.w-7) #7
  tdf[obj.id]
  h.t.o.pos.rel<-as.double(tdf[obj.id])-as.double(tdf[obj.head])
  h.t.o.pos.abs<-obj.id-(h.t.o.pos.rel*length(tdf[,1]))
  tdf[h.t.o.pos.abs]
  h.t.o.value<-obj.token-(h.t.o.pos.rel*length(tdf[,1]))
  tdf[h.t.o.value]
  h.l.o.value<-obj.lemma-(h.t.o.pos.rel*length(tdf[,1]))
  tdf[h.l.o.value]
  obj.pos<-all.ob.w+5
  tdf[obj.pos]<-tdf[h.l.o.value]
  ####################
  tdf.r<-as.data.frame(t(tdf))
  m<-!is.na(tdf.r$obj)
  x$obj<-tdf.r$obj
  x$head_token_value<-tdf[h.t.value]
  x$head_lemma_value<-tdf[h.l.value]
  mode(x$line)<-"double"
  mode(x$sbc.id)<-"double"
  mode(x$token_id)<-"double"
  mode(x$head_token_id)<-"double"
  return(x)  
}

corpus.head.list<-lapply(scb.pos.df.list, get.corpus.deprel)
### get corpus object
corpus.df.deprel_f<-data.frame(corpus.head.list$sbc1)
for (k in 2:length(corpus.head.list)){
  corpus.df.deprel_f<-rbind(corpus.df.deprel_f,corpus.head.list[[k]])
}

3.2 concrete/light assignment

on base of concrete object arrays for make/take/give

get.light.annotation<-function(corpus.df.deprel){
  concrete.give<-c(1066,2620,10469,20369,20373,20377,31957,41100,45424,45538,48045,50236,51759,52340,52341,54654,56016,60668,
                   61952,64351,67497,69012,70356,71167,74595,75162,76991,77442,77553,81098,81099,81859,81860,94278,
                   96953,99281,99880)
  
  concrete.give.txt<-c("sticker","sweets","antibiotic","gift","iguana","recognition","toothpick","herb","anything","enzyme","cake","lettuce","candy","card","literature","ornament","tape","ticket","pair","clothes","juice","pepper","money","goldfish","machine","cup","kiss","amount","bit","picture","mine","pass","dollar","ten","drink","something","car","lot")
  
  concrete.make.txt<-c("horseshoe","sound","cartilage","ceviche","food","noise","hay","grape","cookie","spatula","clothes","wiper","quilt","outfit","copy","tape","string","intercession","application","balloon","basket","kebab","salad","juice","gravy","tamale","sauce","ton","tail","stuff","papers","pasta","loaf","sandwich","ornament","picture","pillow","database","statue","pizza","fudge","recipe","pan","plate","decaf","tart")
  
  concrete.take<-c(848,6381,14466,16674,18611,18809,19366,22031,24813,24827,24829,24831,24832,24834,24835,29159,32908,36540,
                   38239,38243,38247,38253,38254,38258,45020,45021,45032,49577,49582,49583,49588,53267,56405,56406,56409,
                   59372,61588,61592,65654,65656,65657,66021,69440,71127,72201,72320,73797,73798,78435,78440,78442,
                   79454,79456,82282,83099,83834,83836,84599,85311,85932,88155,89310,91865,93070,96464,96465,99149,
                   99745,104020,117695)
  
  concrete.take.txt<-c("balloon","shelf","checkbook","car","bag","everything","puppies","silverware","torque","tree","Tupperware","wastebasket","wire","money","capsule","guitar","stub","tail","Tylenol","blanket","clipping","tablecloth","crown","medicine","nail","spacesuit","sweater","hers","knife","rack","rock","diary","woodwork","pill","ticket","trash","plug","some","tape","band","flip","water","container","pants","buck","insulin","foot","painting","drug","gift","cart","hair","egg","ball","dollar","pound","drink","thing","NPH")
  concrete.false.take<-c("while","time","care","advantage","picture","half","off","down","dollars to do it","look","with me","out","them to")
  concrete.false.take.regx<-paste0(concrete.false.take,collapse = "|")
  concrete.false.take.regx<-paste0("(",concrete.false.take.regx,")")
  #concrete.take.txt<-gsub("\\.[NA0-1]","",concrete.take.txt)
  # write_clip(paste0(concrete.take.txt,collapse = '","'))
  
  alt.array<-c(make=c("build","create","produce","generate"),take=c("carry","bring"),give="give")
  ##########################################################
  ### apply light label
  corpus.df.deprel$light<-NA
  corpus.df.deprel$alt<-"a-other"
  ###
#   q.lemma<-"make|made|making"
#   q.lemma<-"give|given|gave"
#   lemma<-"make"
#   lemma<-"give"
#   ###
# #  concrete.array<-c(concrete.make.txt)
# #  concrete.array<-c(concrete.give.txt)
#   # #  concrete.array
  apply.light<-function(corpus.df.deprel=corpus.df.deprel,q.lemma,lemma,concrete.array){
    corpus.df.deprel$lemma<-gsub("[^a-zA-z']","",corpus.df.deprel$lemma)
    corpus.df.deprel$head_lemma_value<-gsub("[^a-zA-z']","",corpus.df.deprel$head_lemma_value)
    m5<-corpus.df.deprel$lemma==""
    corpus.df.deprel$lemma[m5]<-NA
    m6<-corpus.df.deprel$head_lemma_value==""
    corpus.df.deprel$head_lemma_value[m6]<-NA
    m1<-grepl(q.lemma,corpus.df.deprel$sentence)
    m13<-grepl(lemma,corpus.df.deprel$lemma)
    m14<-grepl(lemma,corpus.df.deprel$head_lemma_value)
    
    # sum(m1)
    # sum(m13)
    # #corpus.df.deprel$sentence[m1]
    # #unique(corpus.df.deprel$head_lemma_value)
    # length(unique(corpus.df.deprel$head_token_value))
    # length(unique(corpus.df.deprel$token))
    # #table(corpus.df.deprel$lemma)
    corpus.df.deprel$alt[m1]<-lemma # set concrete instances
    corpus.df.deprel$light[m13]<-1 # set all to light
    #lemma
    library(stringi)
    library(purrr)
    concrete.regx<-paste0(concrete.array,collapse = "|")
    concrete.regx<-paste0('(',concrete.regx,')')
    m38<-grepl(concrete.regx,corpus.df.deprel$lemma)
    m41.alt<-corpus.df.deprel$alt==lemma
    #sum(m41)
    corpus.df.deprel$light[m41.alt]<-1
    m42.conc<-corpus.df.deprel$lemma[m41.alt]%in%concrete.array|corpus.df.deprel$token[m41.alt]%in%concrete.array
  #  sum(m42.conc)
    m43.obj<-corpus.df.deprel$obj[m41.alt][m42.conc]==lemma
    corpus.df.deprel$light[m41.alt][m42.conc][m43.obj]<-0
    #    sum(m40)
    #   corpus.df.deprel$lemma[m41][m39][m40]
    m39.conc.sent<-grepl(concrete.regx,corpus.df.deprel$sentence[m41.alt])
    m40.lemma.alt.sent<-grepl(lemma,corpus.df.deprel$lemma[m41.alt][m39.conc.sent])
    # sum(lemma,corpus.df.deprel$lemma[m39][m40])
    # corpus.df.deprel$light[m38]<-0
    corpus.df.deprel$light[m41.alt][m39.conc.sent][m40.lemma.alt.sent]<-0
    return(corpus.df.deprel)
  }
  
  corpus.df.deprel<-apply.light(corpus.df.deprel,"make|made|making","make",concrete.make.txt)
  corpus.df.deprel<-apply.light(corpus.df.deprel,"take|took|taken|taking","take",concrete.take.txt)
  corpus.df.deprel<-apply.light(corpus.df.deprel,"give|gave|given|giving","give",concrete.give.txt)
  corpus.df.deprel<-apply.light(corpus.df.deprel,"(produce[^r]|produced|producing)","produce",concrete.make.txt)
  corpus.df.deprel<-apply.light(corpus.df.deprel,"create|created|creating","create",concrete.make.txt)
  corpus.df.deprel<-apply.light(corpus.df.deprel,"generate|generated|generating","generate",concrete.make.txt)
  corpus.df.deprel<-apply.light(corpus.df.deprel,"build|built|building","build",concrete.make.txt)
  corpus.df.deprel<-apply.light(corpus.df.deprel,"carry|carried|carrying","carry",concrete.take.txt)
  corpus.df.deprel<-apply.light(corpus.df.deprel,"bring|brought|bringing","bring",concrete.take.txt)
  table(corpus.df.deprel$alt,corpus.df.deprel$light,corpus.df.deprel$head_lemma_value)
  #chk
  return(corpus.df.deprel)
}
corpus.df.deprel.new<-get.light.annotation(corpus.df.deprel)

3.3 collostruction df

functions to create a subset and feed into collexeme analysis

get.collex<-function(coll6,filter.pos,vers,na.rm=FALSE){
  m3<-coll6$lemma==coll6$head_lemma_value # remove observations with lemma==head_lemma
  sum(m3,na.rm = T)
  #coll6na<-coll6
  coll6<-coll6[!m3,]
  m4<-!is.na(coll6$light)
#  sum(m4)
 # k<-1
  if(na.rm==F)
    coll6$light[m4]<-"n.a."
  # m5<-is.na(coll6$obj.to)
  # coll6<-coll6[!m5,]
  if(length(filter.pos)>0){
    for(k in length(filter.pos)){
      col<-names(filter.pos[k])
      coll6<-coll6[coll6[[col]]%in%filter.pos[[k]],]
    }
  }
  if(vers=="light"){
    colldf.light<-data.frame(head_lemma=coll6$head_lemma_value,lemma=coll6$lemma,light=coll6$light)
    coll6.2<-collex.covar.mult(colldf.light,threshold = 1,decimals = 3)
  }
  #  coll6.2
  if(vers=="lemma"){
    colldf.lemma<-data.frame(head_lemma=coll6$head_lemma_value,lemma=coll6$lemma)
    coll6.2<-collex.covar(colldf.lemma,decimals = 3)
  }
  return(coll6.2)
}
#discard<-"queen"
get.collex.obj<-function(coll6,display.light=NULL,select.filter=NULL,display.filter=NULL,discard=NULL){
  coll6.obj<-data.frame(lemma=unlist(coll6$lemma),obj=unlist(coll6$obj),upos=unlist(coll6$upos),light=coll6$light)
  coll6.obj.n<-coll6.obj[coll6.obj$upos=="NOUN"&!is.na(coll6.obj$obj),]
  colldf<-data.frame(obj=coll6.obj.n$obj,lemma=coll6.obj.n$lemma,light=coll6.obj.n$light)
  
  if(length(select.filter)>0){
    colldf<-colldf[colldf$obj%in%select.filter,]
  }
  
  if(length(discard)>0){
    colldf<-colldf[colldf$lemma!=discard,]
  }
  
  if(length(display.light)==0){
    coll6.2<-collex.covar(data.frame(colldf[,1],colldf[,2]),decimals = 3)
  }
  
  if(length(display.light)>0){
    coll6.2<-collex.covar.mult(colldf,threshold = 1,decimals = 3)
    coll6.2<-coll6.2[coll6.2$light%in%display.light,]
  }
  
  if(length(display.filter)>0){
    coll6.2<-coll6.2[coll6.2[,1]%in%display.filter,]
  }
  return(coll6.2)
}

coll6<-corpus.df.deprel.new
#############
### instances concrete vs. light
### Q.1: (Mehl 2021)
i.make.w<-c(concrete=68,light=321) #17% vs. 83% written ICE 
i.make.s<-c(concrete=96,light=353) #spoken ICE
i.take.w<-c(con=62,light=85) 
i.give.w<-c(con=52,light=167)
i.take.s<-c(con=131,light=79) 
i.give.s<-c(con=105,light=227)
"in the written portion of ICE-GB, the light use of each verb is more common than the concrete sense. 
For example, out of the total number of instances of make in all concrete and light uses, 
just over 80% of instances are the light use, and just under 20% are the concrete use."
rownames(plotdf.ann$plot.dist)<-c("concrete","light")
lsbc<-length(corpus.df.deprel$sbc.id)
plotdf.ann<-list(lsbc=lsbc,plot.dist=plotdf1,ann=list(main="distribution of lemmas over corpora",ylab="absolute occurences",
                                       legend.text = c("concrete use","light use")))
rownames(plotdf.ann$plot.dist)<-c("concrete","light")

3.4 call collex functions

define subsets and create collex df

 coll6.2<-get.collex.obj(coll6,display.light=c(0,1),display.filter = "make")
 coll6.2<-get.collex.obj(coll6,display.light=NULL,display.filter = c("make","take","give"))
 coll6.2.light<-get.collex.obj(coll6,display.light=c(0))
 #table(coll6.2.light$obj)
 coll6.2.obj<-get.collex.obj(coll6,display.light=NULL)
 obj.array<-c(make.array,take.array,"give")
 display.filter<- obj.array
 coll6.2.obj.f<-get.collex.obj(coll6,display.light=c(0,1),display.filter = obj.array)

3.5 evaluation of collex df

apply.model<-function(coll6,p.lower.tail,select.filter=NULL){
  #boxplot(amodel$COLL.STR.LOGL~amodel$SLOT1)
  amodel<-get.collex.obj(coll6,select.filter = select.filter)
  df<-length(levels(factor(amodel$SLOT1)))-1
  df
  amodel$p<-pt(amodel$COLL.STR.LOGL,df,lower.tail = p.lower.tail)
  amodel<-amodel[amodel$SLOT1%in%make.array,]
  amodel<-rbind(amodel[duplicated(amodel$SLOT2,fromLast = T),],amodel[duplicated(amodel$SLOT2,fromLast = F),])
  #amodel<-amodel.d[amodel.d$SLOT1%in%make.array,]
  ifelse(length(select.filter)>0,model<-"model2",model<-"model1")
  xlab<-sprintf("lemma in equivalent context; lower.tail=%s, %s",p.lower.tail,model)
  boxplot(amodel$COLL.STR.LOGL~amodel$SLOT1,outline=F,main="preference of make vs. alternates",xlab = xlab,ylab = "T-score of lemma/object association strength")
  boxplot(amodel$p~amodel$SLOT1,outline=F,main="preference of make vs. alternates",xlab = xlab,ylab = "p-value of lemma/object association strength")
  ### preference of make over produce
  amodel<-get.collex.obj(coll6)
  df<-length(levels(factor(amodel$SLOT1)))-1
  df
  amodel$p<-pt(amodel$COLL.STR.LOGL,df,lower.tail = p.lower.tail)
  amodel<-amodel[amodel$SLOT1%in%take.array,]
  amodel<-rbind(amodel[duplicated(amodel$SLOT2,fromLast = T),],amodel[duplicated(amodel$SLOT2,fromLast = F),])
  #amodel<-amodel.d[amodel.d$SLOT1%in%make.array,]
  boxplot(amodel$COLL.STR.LOGL~amodel$SLOT1,outline=F,main="preference of take vs. alternates",xlab = xlab,ylab = "T-score of lemma/object association strength")
  boxplot(amodel$p~amodel$SLOT1,outline=F,main="preference of take vs. alternates",
          xlab = xlab,ylab = "p-value of lemma/object association strength")
  
}
obj.make<-coll6.2.obj[coll6.2.obj$SLOT1%in%make.array,]
sema.make<-obj.make[obj.make$SLOT2%in%obj.make[duplicated(obj.make$SLOT2),][,2],]
obj.take<-coll6.2.obj[coll6.2.obj$SLOT1%in%take.array,]
sema.take<-obj.take[obj.take$SLOT2%in%obj.take[duplicated(obj.take$SLOT2),][,2],]
coll.sema.1<-list(make=sema.make,take=sema.take)
x<-sema.make
y<-make.array
sema.sum<-function(y)y=sum(x['COLL.STR.LOGL'][x['SLOT1']==y])
make.sum<-list(make.array)
make.sum[make.array]<-lapply(y, sema.sum)    
make.sum
x<-sema.take
y<-take.array
sema.sum<-function(y)y=sum(x['COLL.STR.LOGL'][x['SLOT1']==y])
take.sum<-list(take.array)
take.sum[take.array]<-lapply(y, sema.sum)   
df<-factor(coll6.2.obj$SLOT1)
df<-length(levels(df))
get.p<-function(x)pt(x,df,lower.tail = F)
#get.p<-function(x)pt(x,df,lower.tail = T)
eval1<-sema.make
eval1$p<-unlist(lapply(eval1$COLL.STR.LOGL, get.p))
eval2<-sema.take
eval2$p<-unlist(lapply(eval2$COLL.STR.LOGL, get.p))
par(las=3)
eval.make<-eval1
eval.take<-eval2

3.6 lemma-object collexeme analysis

### concrete objects frequency
make.array<-c("make","generate","produce","create","build")
take.array<-c("carry","bring")
obj.array<-c(make.array,take.array,"give")
display.filter<- obj.array
coll6.2.obj.f<-get.collex.obj(coll6,display.light=NULL,display.filter = obj.array)
coll6.2.obj.f
obj.t<-table(coll6.2.obj.f[,1])
obj.all.t<-obj.t[obj.t!=0]
### concrete objects:
concrete.array<-c("give",concrete.make.txt,concrete.take.txt)
sub.obj.t<-coll6.2.obj.f[coll6.2.obj.f$SLOT2%in%concrete.array,]
conc.obj.t<-table(sub.obj.t[,1])
obj.all.conc.t<-conc.obj.t[conc.obj.t!=0]
obj.eval<-rbind(all.objects=obj.all.t,all.conc.obj=obj.all.conc.t)
obj.eval

4 B references

Benoit, Kenneth, Kohei Watanabe, Haiyan Wang, Jiong Wei Lua, and Jouni Kuha. 2023. Quanteda.textstats: Textual Statistics for the Quantitative Analysis of Textual Data. https://quanteda.io.
Benoit, Kenneth, Kohei Watanabe, Haiyan Wang, Paul Nulty, Adam Obeng, Stefan Müller, Akitaka Matsuo, and William Lowe. 2022. Quanteda: Quantitative Analysis of Textual Data. https://quanteda.io.
Druskat, Stephan, Volker Gast, and Thomas Krause. 2016. “Corpus-Tools.org: An Interoperable Generic Software Tool Set for Multi-Layer Linguistic Corpora. Proceedings of the Tenth International Conference on Language Resources and Evaluation (LREC 2016).” http://www.lrec-conf.org/proceedings/lrec2016/summaries/918.html.
Gagolewski, Marek, Bartek Tartanus, others; Unicode, Inc., et al. 2021. Stringi: Character String Processing Facilities. https://CRAN.R-project.org/package=stringi.
Mehl, Seth. 2021. “What We Talk about When We Talk about Corpus Frequency: The Example of Polysemous Verbs with Light and Concrete Senses.” Corpus Linguistics and Linguistic Theory 17 (1): 223–47. https://doi.org/10.1515/cllt-2017-0039.
Ooms, Jeroen. 2023. Writexl: Export Data Frames to Excel Xlsx Format. https://CRAN.R-project.org/package=writexl.
Wickham, Hadley, Jim Hester, and Jennifer Bryan. 2022. Readr: Read Rectangular Text Data. https://CRAN.R-project.org/package=readr.
Wijffels, Jan. 2023. Udpipe: Tokenization, Parts of Speech Tagging, Lemmatization and Dependency Parsing with the UDPipe ’NLP’ Toolkit. https://CRAN.R-project.org/package=udpipe.
LS0tCnRpdGxlOiAiMTczNzMudG9waWNfNi5kb2t1IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBodG1sX25vdGVib29rOgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQpuYXZiYXI6CiAgdGl0bGU6IHRvcGljIDYKICBsZWZ0OgogIC0gdGV4dDogaW5kZXgKICAgIGhyZWY6IGluZGV4Lmh0bWwKICAtIHRleHQ6IHBhcGVyCiAgICBocmVmOiBwYXBlci5odG1sCiAgLSB0ZXh0OiBzbGlkZQogICAgaHJlZjogIkhBLXNsaWRlcy5odG1sIgogICAgaWQ6IHNsaWRlcwogIC0gdGV4dDogZG9rdQogICAgaHJlZjogX2Rva3UubmIuaHRtbApiaWJsaW9ncmFwaHk6IFsncGFja2FnZXMuYmliJywnQ09SUFVTLUxYLmJpYiddCm5vY2l0ZTogfAogQFItdWRwaXBlLEBSLXF1YW50ZWRhLEBSLXF1YW50ZWRhLnRleHRzdGF0cyxAUi1yZWFkcixAUi1zdHJpbmdpLEBSLXN0YXRzLEBSLXV0aWxzLEBSLXdyaXRleGwKYmlibGlvLXN0eWxlOiBhcGFsaWtlCmxpbmstY2l0YXRpb25zOiB5ZXMKLS0tCiMgUFJFClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuCgpyZXBsYWNlbWFzayBzbmM6ICNyZXBsYWNlbWFzayMgMTQwNjEuNQoKVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkNtZCtTaGlmdCtFbnRlciouIAoKYGBge3IsZXZhbD1GQUxTRX0KcGxvdChjYXJzKQpgYGAKCiMjIGNhdHMKQWRkIGEgbmV3IGthdHplIGh1bmQgZHJlaW1hbCBzY2h3YXJ6IGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkNtZCtPcHRpb24rSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkNtZCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLiAKClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4KCiMgcHJvY2VzcwoKIyMgcHJlbGltaW5hcnkKbG9hZCBsaWJyYXJpZXMgYW5kIHNldCBTQkMgcmVzc291cmNlcyBhZHJlc3MgICAKPCEtLSBsaWJzOiBAdWRwaXBlLEBxdWFudGVkYSxAcmVhZHIsQHN0cmluZ2ksQHN0YXRzLEB1dGlscyxAc2NobWlkX2VzdGltYXRpb25fMjAwOCAtLT4KYGBge3IgcHJlLTE0MDE1LGV2YWw9VCxlY2hvPVQsd2FybmluZz1GQUxTRX0KIzIwMjQwMTAzKDA3LjQyKQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIHRoaXMgc2NyaXB0IHJ1bnMgd2l0aG91dCBsb2NhbCBmaWxlcywgYWxsIGRhdGEgZmV0Y2hlZCBmcm9tIG9ubGluZSBzb3VyY2VzLgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjClIuMTwtImh0dHBzOi8vd3d3Lmxpbmd1aXN0aWNzLnVjc2IuZWR1L3Jlc2VhcmNoL3NhbnRhLWJhcmJhcmEtY29ycHVzIgpRLjI8LSJodHRwczovL3d3dy5saW5ndWlzdGljcy51Y3NiLmVkdS9zaXRlcy9zZWN1cmUubHNpdC51Y3NiLmVkdS5saW5nLmQ3L2ZpbGVzL3NpdGVmaWxlcy9yZXNlYXJjaC9TQkMvU0JDb3JwdXMuemlwIgpsaWJyYXJ5KHV0aWxzKQpsaWJyYXJ5KHN0cmluZ2kpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkocXVhbnRlZGEudGV4dHN0YXRzKSAKbGlicmFyeShxdWFudGVkYSkKbGlicmFyeSh1ZHBpcGUpICMgZm9yIHBvcyB0YWdnaW5nCmxpYnJhcnkod3JpdGV4bCkKCiNrbml0cjo6d3JpdGVfYmliKGMoLnBhY2thZ2VzKCkpLCAicGFja2FnZXMuYmliIikKYGBgCgoKIyMjIGxvYWQgcG9zLXRhZyBtb2RlbCBhbmQgY29ycHVzIC56aXAKYGBge3Igc2NyaXB0LTE0MDE1LGV2YWw9VCxlY2hvPVQsd2FybmluZz1GQUxTRX0KbG9jYWw8LSJ+L2JveEhLVy8yMVMvREgvbG9jYWwvU1BVTkQvY29ycHVzbHgiCnVkcGlwZXBhdGg8LXNwcmludGYoIiVzL2VuZ2xpc2gtZXd0LXVkLTIuNS0xOTEyMDYudWRwaXBlIixsb2NhbCkKIyMjIGlmIG5vdCB5ZXQsIHRoZSBtb2RlbCBtdXN0IGJlIGRvd25sb2FkZWQsIGNvbW1lbnQgaW4gYWJvdmUgbGluZSAKCmdldC51ZHA8LWZ1bmN0aW9uKCl7CnVkcGlwZV9kb3dubG9hZF9tb2RlbCgiZW5nbGlzaCIsbW9kZWxfZGlyID0gdGVtcGRpcigibWQiKSkKbWRmPC1saXN0LmZpbGVzKHRlbXBkaXIoKSkKbWR3PC1ncmVwKCIudWRwaXBlIixtZGYpCm1kZmlsZTwtcGFzdGUwKHRlbXBkaXIoKSwiLyIsbWRmW21kd10pCm1kPC11ZHBpcGVfbG9hZF9tb2RlbChtZGZpbGUpCn0KCiMjIyBpZiB0aGUgbW9kZWwgaXMgbm90IG9uIGRpc2ssIGl0IGlzIGRvd25sb2FkZWQKaWZlbHNlKGV4aXN0cygidWRwaXBlcGF0aCIpLG1kPC11ZHBpcGVfbG9hZF9tb2RlbCh1ZHBpcGVwYXRoKSxtZDwtZ2V0LnVkcCgpKQpnZXR3ZCgpCgojIyMgdGVtcGZpbGUgdG8gc3RvcmUgemlwCnNiY3RlbXA8LXRlbXBmaWxlKCJTQkN0ZW1wLnppcCIpCnNiY3RlbXBkaXI8LXRlbXBkaXIoKQpkb3dubG9hZC5maWxlKFEuMixzYmN0ZW1wKQp1bnppcChzYmN0ZW1wLGV4ZGlyID0gc2JjdGVtcGRpcikKCnNiY3RybjwtcGFzdGUwKHNiY3RlbXBkaXIsIi9UUk4vIikKZmlsZXN0cm48LWxpc3QuZmlsZXMoc2JjdHJuKQp0cm5kZjwtZGF0YS5mcmFtZShzY2I9TkEsaWQ9TkEsdGV4dD1OQSkKI2s8LTEKYGBgCgoKIyMjIHJlYWQgaW4gZmlsZXMKYGBge3IsIGVjaG89VFJVRSxldmFsPUZBTFNFfQpmb3IoayBpbiAxOmxlbmd0aChmaWxlc3RybikpewogICNjYXQoaywiXG4iKQp0cm50ZW1wPC1yZWFkX2RlbGltKHBhc3RlMChzYmN0cm4sZmlsZXN0cm5ba10pLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGltID0gIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHRyaW1fd3MgPSBUUlVFLGNvbF9uYW1lcyA9IGMoImlkIiwic3BrIiwidGV4dCIpKQoKbDE8LWxlbmd0aCh0cm50ZW1wKQp0cm50ZXh0PC10cm50ZW1wWyxsMV0KY29sbmFtZXModHJudGV4dCk8LSJ0ZXh0Igp0cm50ZW1wLjI8LWRhdGEuZnJhbWUoc2NiPWssaWQ9MTpsZW5ndGgodHJudGV4dCR0ZXh0KSx0ZXh0PXRybnRleHQpCiAgCnRybmRmPC1yYmluZCh0cm5kZix0cm50ZW1wLjIpCgp9CmBgYAoKCiMjIyMgd2hpY2ggbG9vayBsaWtlIHRoaXMKYGBge3Igc2hvdy10cm4tcmF3ZGF0YSxldmFsPVRSVUUsZWNobz1UUlVFfQp0cm4uZG9jLjE8LXJlYWRMaW5lcyhwYXN0ZTAoc2JjdHJuLGZpbGVzdHJuWzFdKSkKcHJpbnQodHJuLmRvYy4xWzE6MTVdKQpgYGAKCgojIyMgc3Vic2V0cwpjcmVhdGUgc3Vic2V0cyBmb3IgL21ha2UvIC90YWtlLyAvZ2l2ZS8KYGBge3IsZXZhbD1GQUxTRSx3YXJuaW5nPUYsZWNobz1UfQp0cm5kZi4yPC10cm5kZlsyOmxlbmd0aCh0cm5kZiRzY2IpLF0KdHJuZGYuMiRsZmQ8LTE6bGVuZ3RoKHRybmRmLjIkc2NiKQpyb3duYW1lcyh0cm5kZi4yKTwtdHJuZGYuMiRsZmQKI3RybmRmJGxmZDwtMTpsZW5ndGgodHJuZGYkc2NiKQp0cm5kZjwtdHJuZGYuMgpgYGAKCgojIyBhbm5vdGF0ZSBmb3IgL21ha2UvCnRoZSBhbm5vdGF0aW9uIG9mIGNvbmNyZXRlL2xpZ2h0IHVzZSBvZiBsZW1tYSAvbWFrZS8gd2FzIGRvbmUgaW4gYSBzdWJzZXQgdGFibGUgb2YgdGhlIGNvcnB1cywgYXNzaWduaW5nIGVpdGhlciAwIGZvciBjb25jcmV0ZSBhbmQgMSBmb3IgbGlnaHQgdXNlIG9mIHRoZSB2ZXJiIGluIGNvbnRleHQuIGNvbmNyZXRlIHVzZSB3b3VsZCBpbmNsdWRlIGZvcm1zIHdpdGggb2JqZWN0cyBvZiB0aGUgbGVtbWEgdGhhdCAoZm9yIC9tYWtlLykgdGhhdCAoaW4gdGhlIHNlbnNlIG9mIHRoZSBhbHRlcm5hdGUgY29uc3RydWN0aW9ucykgY2FuIGJlIGFsc28gYHByb2R1Y2VkLCBidWlsdCwgZ2VuZXJhdGVkLCBjcmVhdGVkYC4gdGhlc2UgYXJlIG9idmlvdXMgc2VtYW50aWMgYWx0ZXJuYXRpdmVzIG9mIC9tYWtlLyBkZWZpbmVkIGluIFtAbWVobF93aGF0XzIwMjFdLgpgYGB7cixlY2hvPVQsd2FybmluZz1GLGV2YWw9VH0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIGluc3RhbmNlcyBjb25jcmV0ZSB2cy4gbGlnaHQKIyMjIFEuMTogKE1laGwgMjAyMSkKaS5tYWtlLnc8LWMoY29uY3JldGU9NjgsbGlnaHQ9MzIxKSAjMTclIHZzLiA4MyUgd3JpdHRlbiBJQ0UgCmkubWFrZS5zPC1jKGNvbmNyZXRlPTk2LGxpZ2h0PTM1MykgI3Nwb2tlbiBJQ0UKaS50YWtlPC1jKGNvbj02MixsaWdodD04NSkgCmkuZ2l2ZTwtYyhjb249NTIsbGlnaHQ9MTY3KSAKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiN0cm5kZl9zZjwtdHJuZGYgIyBzYXZlZCBjcmVhdGVkLCBsb2FkIG9ubHkgYW5ub3RhdGlvbnMgZGF0YWZyYW1lCiMgZHRlbXA8LXRlbXBmaWxlKCkKIyBkb3dubG9hZC5maWxlKCJodHRwczovL2dpdGh1Yi5jb20vZXN0ZWVzY2h3YXJ6L1NQVU5ELUxYL3Jhdy9tYWluL2NvcnB1c0xYLzE0MDE1LUhBL2RhdGEvU0JDLmFubi5kZi5SRGF0YSIsZHRlbXApCiMgbG9hZChkdGVtcCkKIyBnZXQuYW5uLng8LWZ1bmN0aW9uKHNjYixhbm4uZGYpewojICAgdHJuZGYubG08LWNiaW5kKHNjYixhbm4uZGYpCiMgfQojIHRybmRmLmxtPC1nZXQuYW5uLngodHJuZGYuMixzY2IuYW5uLmRmKQoKYGBgCgoKIyMgUG9TIHRhZ2dpbmcKdG9rZW5pemUgYW5kIGxlbW1hdGl6ZS9wb3MtdGFnIGRmCmBgYHtyIHRva2VuaXplLGV2YWw9RixlY2hvPVQsd2FybmluZz1GQUxTRX0KIyMjIyMjIyMjIyMjIyMjIwojIyMgbmV3IHdpdGggcHJlbG9hZGVkL2J1aWx0IGRmCiNsb2FkKCJ+L2JveEhLVy8yMVMvREgvbG9jYWwvU1BVTkQvY29ycHVzbHgvc3RlZmFub3dpdHNjaC9IQS9kYXRhL3RybmRmLmxtLmNwdC5SRGF0YSIpCnNjYi51bmlxdWU8LXVuaXF1ZSh0cm5kZiRzY2IpCms8LTEKI3NjYi51bmlxdWU8LXVuaXF1ZSh0cm5kZiRzY2IpCnNjYjwtMQojIHNjYi5hbm4ubGlzdDwtbGlzdCgpCgp3cml0ZS5hbm4uZGY8LWZ1bmN0aW9uKGRmKXsKc2NiLmFubi5saXN0PC1saXN0KCkKc2NiLnRva2VuLmxpc3Q8LWxpc3QoKQp0cm5kZi5sbTwtZGYgIApmb3Ioc2NiIGluIDE6bGVuZ3RoKHNjYi51bmlxdWUpKXsKICBjYXQoc2NiLCJcbiIpCiMjIzE0MDQzLgogIHNiYzwtdHJuZGYubG0KICBzY2IuaWQ8LXNjYi51bmlxdWVbc2NiXQogIHNjYi5zdWI8LXN1YnNldChzYmMsc2JjJHNjYj09c2NiLmlkKQogIGNvbG5hbWVzKHNjYi5zdWIpWzFdPC0iZG9jX2lkIgogIHNjYi5zdWIkdGV4dDwtZ3N1YigiWyslP34sLS4wLTkoKT08PkBdfFxcXXxcXFsiLCIiLHNjYi5zdWIkdGV4dCkKICBzY2Iuc3ViJHRleHQ8LWdzdWIoIiheICkiLCIiLHNjYi5zdWIkdGV4dCkKICBjb2xuYW1lcyhzY2Iuc3ViKVszXTwtInRleHRfZmllbGQiCiAgc2JjLnN1Yi5jPC1jb3JwdXMoc2NiLnN1Yixkb2NpZF9maWVsZCA9ICdkb2NfaWQnLHRleHRfZmllbGQgPSAndGV4dF9maWVsZCcsdW5pcXVlX2RvY25hbWVzID0gRikKICBhbjQ8LXVkcGlwZV9hbm5vdGF0ZShtZCx4PXNiYy5zdWIuYyx0b2tlbml6ZXI9InRva2VuaXplciIsdGFnZ2VyID0gImRlZmF1bHQiLHRyYWNlID0gMikKICAjIyN3a3MuCiAgYW43PC1kYXRhLmZyYW1lKGFuNCkKICBhbjckZG9jX2lkPC1nc3ViKCJkb2MiLCIiLGFuNyRkb2NfaWQpCiAgY29sbmFtZXMoYW43KVsxXTwtImxpbmUiCiAgYW44PC1hbjdbLGMoMSw0LDUsNiw3LDgsOSwxMCwxMSwxMildCiAgYW44JHNiYy5pZDwtc2NiLmlkCiAgYW44PC1hbjhbLGMoMTEsMSwyLDMsNCw1LDYsNyw4LDksMTApXQogIGFuOCRhbHQ8LSJhLW90aGVyIgogIGFuOCRsaWdodDwtTkEKICBsaW5lLnU8LXVuaXF1ZShhbjgkbGluZSkKbnMubGlzdDwtcGFzdGUwKCJzYmMiLHNjYi5pZCkKc2NiLmFubi5saXN0W1tucy5saXN0XV08LWFuOAp9CnJldHVybihzY2IuYW5uLmxpc3QpCn0KIyMjIGNhbGwgYWJvdmUgZnVuY3Rpb24gd2hpY2ggdG9rZW5pemVzLCBsZW1tYXRpemVzIGFuZCBwb3N0YWdzIHRoZSBjb3JwdXMgJiB3cml0ZXMgeGxzeC10YWJsZXMgcGVyIGludGVydmlldyAvIHJldHVybnMgZGF0YWZyYW1lIChsaXN0IHR5cGUpIG9mIGFubm90YXRlZCBjb3JwdXMKc2JjLnRva2VuLmxpc3Q8LXdyaXRlLmFubi5kZih0cm5kZi5sbSkKYW5uLng8LXdyaXRlLmFubi5kZih0cm5kZi5sbSkKc2NiLnBvcy5kZi5saXN0PC1hbm4ueApzY2IuYW5uLmxpc3Q8LXNjYi5wb3MuZGYubGlzdAojc2F2ZShzY2IucG9zLmRmLmxpc3QsZmlsZSA9ICJ+L2JveEhLVy8yMVMvREgvbG9jYWwvU1BVTkQvY29ycHVzbHgvc3RlZmFub3dpdHNjaC9IQS9kYXRhL3NjYi5hbm4ubGlzdC5wb3MtYWxsLWRmcy5SRGF0YSIpCiN3a3MuCiNzYXZlKHNjYi5hbm4ubGlzdCxmaWxlPSJ+L2JveEhLVy8yMVMvREgvbG9jYWwvU1BVTkQvY29ycHVzbHgvc3RlZmFub3dpdHNjaC9IQS9kYXRhL3NjYi5hbm4ubGlzdC5SRGF0YSIpCiN0PC1ncmVwKCJ0b2tlbiIsY29sbmFtZXMoc2NiLmFubi5saXN0JHNiYzEpKQp0PC1jb2xuYW1lcyhzY2IuYW5uLmxpc3Qkc2JjMSk9PSJ0b2tlbiIKdDwtd2hpY2godCkKc2NibnM8LWNvbG5hbWVzKHNjYi5hbm4ubGlzdCRzYmMxKQojIyMgdGhpcyBpcyBuZWNlc3NhcnkgZm9yIHBlcHBlciB0byByZWNvZ25pemUgdGhlIHRva2VuIGNvbHVtbiBpbiB0aGUgZGYKc2NibnNbdF08LSJ0b2siCnNjYm5zPC1nc3ViKCJcXC4iLCJfIixzY2JucykKcmVuYW1lLmxpc3Q8LWZ1bmN0aW9uKHgpewogIHgyPC1kYXRhLmZyYW1lKHgpCiAgY29sbmFtZXMoeDIpPXNjYm5zCiAgcmV0dXJuKHgyKQp9CnNjYi5hbm4ubGlzdC5ucjwtbGFwcGx5KHNjYi5hbm4ubGlzdCwgcmVuYW1lLmxpc3QpCmhlYWQoc2NiLmFubi5saXN0Lm5yJHNiYzEpCnNjYi5hbm4ubGlzdDwtc2NiLmFubi5saXN0Lm5yCgojIyMgc2FtZSBhcyBhYm92ZSB3cml0aW5nIHhsc3gsIGhlcmUgZnJvbSBhbm5vdGF0ZWQgbGlzdAojIGZvcihrIGluIDE6bGVuZ3RoKHNjYi5hbm4ubGlzdCkpewojICAgY29sbmFtZXMoc2NiLmFubi5saXN0W1trXV0pPC1zY2JucwojICAgeGxkaXI8LSJ+L2JveEhLVy8yMVMvREgvbG9jYWwvU1BVTkQvY29ycHVzbHgvYW5uaXMveGxzIgojICAgbnMuZGY8LXBhc3RlMCh4bGRpciwiL1NDQi1wb3NfIixrLCIueGxzeCIpCiMgICB3cml0ZV94bHN4KHNjYi5hbm4ubGlzdFtba11dLG5zLmRmKQojICAgCiMgICB9CiN4PC1zY2IuYW5uLmxpc3Qkc2JjMQpleHBvcnQuYW5uPC1mdW5jdGlvbih4KXsKICBuczwtY29sbmFtZXMoeCkKICB3bnM8LW5zPT0ic2VudGVuY2UifG5zPT0idG9rIgogIHducwogIHgxPC14Wywhd25zXQogIHJldHVybih4MSkKfQpzYmMub25seS5wb3MuYW5ub3RhdGlvbjwtbGFwcGx5KHNjYi5hbm4ubGlzdCwgZXhwb3J0LmFubikKI3NhdmUoc2JjLm9ubHkucG9zLmFubm90YXRpb24sZmlsZSA9ICJ+L0RvY3VtZW50cy9HaXRIdWIvU1BVTkQtTFgvY29ycHVzTFgvMTQwMTUtSEEvZGF0YS9zYmMub25seS5wb3MuYW5ub3RhdGlvbi5SRGF0YSIpCmBgYAoKCiMjIGNyZWF0ZSBBTk5JUyBjb3JwdXMKdGhlIGV2YWx1YXRpb24gc3RhdGlzdGljcyBjYW4gYmUgZG9uZSBhbHJlYWR5IHdpdGggdGhlIGRmLCBidXQgZm9yIGRpZmZlcmVudCBwdXJwb3NlcyBlLmcuIHRoZSBiZXR0ZXIgdmlzdWFsaXNhdGlvbiBvZiB0aGUgY29ycHVzIGFuZCBleHRlbnNpdmUgcXVlcmllcyBhbiBBTk5JUyAoQGRydXNrYXRfY29ycHVzLXRvb2xzb3JnXzIwMTYpIGhhcyBiZWVuIGNyZWF0ZWQuICAgCgpjYWxsIHRvIGV4dGVybmFsIHNjcmlwdHMgd2hpY2ggcnVuIHBlcHBlciBvbiB0aGUgcHJvdmlkZWQgeGxzeCBhbmQgY3JlYXRlIGFuIEFOTklTIGdyYXBoIGZpbGUgZm9yIGltcG9ydCB0byB0aGUgQU5OSVMgaW5zdGFsbGF0aW9uLgpgYGB7ciBjYWxsLXBlcHBlcixldmFsPUZ9CnBlcHBlci5jYWxsKCJ+L2JveEhLVy8yMVMvREgvbG9jYWwvU1BVTkQvY29ycHVzbHgvYW5uaXMvci1jb254bDUucGVwcGVyIiwiU0JDX3YxLjAuMSIsIlNCQ192MS4wLjEiKQpwZXBwZXIuY2FsbCgifi9ib3hIS1cvMjFTL0RIL2xvY2FsL1NQVU5EL2NvcnB1c2x4L2FubmlzL3ItY29ueGw2LnBlcHBlciIsIlNCQ192MS4wLjEiLCJTQkNfdjEuMC4xIikKemlwYW5uaXMoIlNCQ19hbm5pcyIsIlNCQ19hbm5pcy56aXAiKQpgYGAKCgojIyMgeGxzeCB0byB0cmVldGFnZ2VyIGZvcm1hdApjb25maWd1cmF0aW9uIHhtbDogci1jb254bDUucGVwcGVyCmBgYHt9Cjw/eG1sIHZlcnNpb249JzEuMCcgZW5jb2Rpbmc9J1VURi04Jz8+CjxwZXBwZXItam9iIGlkPSJ0dDAwMSIgdmVyc2lvbj0iMS4wIj4KPGltcG9ydGVyIG5hbWU9IlNwcmVhZHNoZWV0SW1wb3J0ZXIiIHBhdGg9Ii4veGxzIi8+CQo8ZXhwb3J0ZXIgbmFtZT0iVHJlZXRhZ2dlckV4cG9ydGVyIiBwYXRoPSIuL1NCQ192MS4wLjEvIi8+CjwvcGVwcGVyLWpvYj4KYGBgCgoKIyMjIHRyZWV0YWdnZXIgdG8gQU5OSVMgZ3JhcGgKY29uZmlndXJhdGlvbiB4bWw6IHItY29ueGw2LnBlcHBlcgpgYGB7fQo8P3htbCB2ZXJzaW9uPScxLjAnIGVuY29kaW5nPSdVVEYtOCc/Pgo8cGVwcGVyLWpvYiBpZD0idHQwMDEiIHZlcnNpb249IjEuMCI+CjxpbXBvcnRlciBuYW1lPSJUcmVldGFnZ2VySW1wb3J0ZXIiIHBhdGg9Ii4vU0JDX3YxLjAuMS8iPgo8L2ltcG9ydGVyPgo8ZXhwb3J0ZXIgbmFtZT0iQU5OSVNFeHBvcnRlciIgcGF0aD0iLi9TQkNfYW5uaXMvIj4KPC9leHBvcnRlcj4KPC9wZXBwZXItam9iPgpgYGAKCiMgZnJlcXVlbmN5IGV2YWx1YXRpb25zCiMjIGdldCBtYXRyaXggZGYgb2YgYW5ub3RhdGVkIGxpc3QKYGBge3IgY29ycHVzLW1hdHJpeCxldmFsPUYsZWNobz1UfQojIGR0ZW1wPC10ZW1wZmlsZSgpCiMgZG93bmxvYWQuZmlsZSgiaHR0cHM6Ly9naXRodWIuY29tL2VzdGVlc2Nod2Fyei9TUFVORC1MWC9yYXcvbWFpbi9jb3JwdXNMWC8xNDAxNS1IQS9kYXRhL3NiYy5vbmx5LnBvcy5hbm5vdGF0aW9uLlJEYXRhIixkdGVtcCkKIyBsb2FkKGR0ZW1wKQpnZXQuY29ycHVzLmRlcHJlbDwtZnVuY3Rpb24oeCl7CiAgbnM8LWNvbG5hbWVzKHgpCiAgeDI8LWNiaW5kKCkKICAjIGFzc2lnbiB1bmlxdWUgaWQgdG8gdG9rZW4KICB4JHNiYy50b2tlbi5pZDwtYXMuZG91YmxlKHBhc3RlMCh4JHNiY19pZCwiXyIsICAxOmxlbmd0aCh4JHNiYy5pZCkpKSAgCiAgeCRwb3MuMDwtImxmZC5wb3MiICAKICB4JG9iajwtTkEKICB0ZGY8LXQoeCkKICBydGRmPC1yb3duYW1lcyh0ZGYpCiAgcnRkZi4wPC13aGljaChydGRmPT0icG9zLjAiKQogIGFsbC56ZXJvPC13aGljaCh0ZGY9PSJsZmQucG9zIiktcnRkZi4wCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKICBwb3MuZGVwcmVsPC1hbGwuemVybytncmVwKCJkZXAiLHJ0ZGYpCiAgcG9zLmhlYWQ8LWFsbC56ZXJvK2dyZXAoImhlYWQiLHJ0ZGYpCiAgcG9zLnVwb3M8LWFsbC56ZXJvK2dyZXAoInVwb3MiLHJ0ZGYpCiAgcG9zLmxlbW1hPC1hbGwuemVybytncmVwKCJsZW1tYSIscnRkZikKICBwb3MudG9rZW48LWFsbC56ZXJvK3doaWNoKHJ0ZGY9PSJ0b2tlbiIpCiAgcG9zLnRva2VuLmlkPC1hbGwuemVybyt3aGljaChydGRmPT0idG9rZW5faWQiKQogICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKICB0LmhlYWQ8LXBvcy5oZWFkCiAgdC5pZDwtcG9zLnRva2VuLmlkCiAgdC50YWc8LXBvcy51cG9zCiAgdC50b2tlbjwtcG9zLnRva2VuCiAgdC5sZW1tYTwtcG9zLmxlbW1hCiAgdC5kZXByZWw8LXBvcy5kZXByZWwKICBtLmgudC4wPC13aGljaCh0ZGZbdC5oZWFkXT09MCkKICBoLnQucG9zLnJlbDwtYXMuZG91YmxlKHRkZlt0LmlkXSktYXMuZG91YmxlKHRkZlt0LmhlYWRdKQogIGgudC5wb3MucmVsW20uaC50LjBdPC0wCiAgaC50LnBvcy5hYnM8LXQuaWQtKGgudC5wb3MucmVsKmxlbmd0aCh0ZGZbLDFdKSkKICBoLnQudmFsdWU8LXQudG9rZW4tKGgudC5wb3MucmVsKmxlbmd0aCh0ZGZbLDFdKSkKICBtMTwtd2hpY2goaC50LnZhbHVlPDApCiAgc3VtKG0xKQogIGgudC52YWx1ZVttMV08LTEgIyBwcmV2ZW50IG5lZ2F0aXZlIHN1YnNjcmlwdHMKICBoLmwudmFsdWU8LXQubGVtbWEtKGgudC5wb3MucmVsKmxlbmd0aCh0ZGZbLDFdKSkKICBtMjwtd2hpY2goaC5sLnZhbHVlPDApCiAgc3VtKG0yKQogIGgubC52YWx1ZVttMl08LTEgIyBwcmV2ZW50IG5lZ2F0aXZlIHN1YnNjcmlwdHMKICBoZWFkKHRkZltoLmwudmFsdWVdKQogICMjIyMjIyMjIyMjIyMjIyMjIyMjCiAgYWxsLm9iajwtdGRmPT0ib2JqIgogIGFsbC5vYi53PC13aGljaChhbGwub2JqKQogIGFsbC5vYi53CiAgb2JqLmhlYWQ8LWFzLmRvdWJsZShhbGwub2Iudy0xKQogIHRkZltvYmouaGVhZF0KICBvYmoudGFnPC1hbGwub2Iudy00ICM0IAogIHRkZltvYmoudGFnXQogIG9iai5sZW1tYTwtYWxsLm9iLnctNSAjNQogIHRkZltvYmoubGVtbWFdCiAgb2JqLnRva2VuPC1hbGwub2Iudy02ICM2CiAgdGRmW29iai50b2tlbl0KICBvYmouaWQ8LWFzLmRvdWJsZShhbGwub2Iudy03KSAjNwogIHRkZltvYmouaWRdCiAgaC50Lm8ucG9zLnJlbDwtYXMuZG91YmxlKHRkZltvYmouaWRdKS1hcy5kb3VibGUodGRmW29iai5oZWFkXSkKICBoLnQuby5wb3MuYWJzPC1vYmouaWQtKGgudC5vLnBvcy5yZWwqbGVuZ3RoKHRkZlssMV0pKQogIHRkZltoLnQuby5wb3MuYWJzXQogIGgudC5vLnZhbHVlPC1vYmoudG9rZW4tKGgudC5vLnBvcy5yZWwqbGVuZ3RoKHRkZlssMV0pKQogIHRkZltoLnQuby52YWx1ZV0KICBoLmwuby52YWx1ZTwtb2JqLmxlbW1hLShoLnQuby5wb3MucmVsKmxlbmd0aCh0ZGZbLDFdKSkKICB0ZGZbaC5sLm8udmFsdWVdCiAgb2JqLnBvczwtYWxsLm9iLncrNQogIHRkZltvYmoucG9zXTwtdGRmW2gubC5vLnZhbHVlXQogICMjIyMjIyMjIyMjIyMjIyMjIyMjCiAgdGRmLnI8LWFzLmRhdGEuZnJhbWUodCh0ZGYpKQogIG08LSFpcy5uYSh0ZGYuciRvYmopCiAgeCRvYmo8LXRkZi5yJG9iagogIHgkaGVhZF90b2tlbl92YWx1ZTwtdGRmW2gudC52YWx1ZV0KICB4JGhlYWRfbGVtbWFfdmFsdWU8LXRkZltoLmwudmFsdWVdCiAgbW9kZSh4JGxpbmUpPC0iZG91YmxlIgogIG1vZGUoeCRzYmMuaWQpPC0iZG91YmxlIgogIG1vZGUoeCR0b2tlbl9pZCk8LSJkb3VibGUiCiAgbW9kZSh4JGhlYWRfdG9rZW5faWQpPC0iZG91YmxlIgogIHJldHVybih4KSAgCn0KCmNvcnB1cy5oZWFkLmxpc3Q8LWxhcHBseShzY2IucG9zLmRmLmxpc3QsIGdldC5jb3JwdXMuZGVwcmVsKQojIyMgZ2V0IGNvcnB1cyBvYmplY3QKY29ycHVzLmRmLmRlcHJlbF9mPC1kYXRhLmZyYW1lKGNvcnB1cy5oZWFkLmxpc3Qkc2JjMSkKZm9yIChrIGluIDI6bGVuZ3RoKGNvcnB1cy5oZWFkLmxpc3QpKXsKICBjb3JwdXMuZGYuZGVwcmVsX2Y8LXJiaW5kKGNvcnB1cy5kZi5kZXByZWxfZixjb3JwdXMuaGVhZC5saXN0W1trXV0pCn0KYGBgCgoKIyMgY29uY3JldGUvbGlnaHQgYXNzaWdubWVudApvbiBiYXNlIG9mIGNvbmNyZXRlIG9iamVjdCBhcnJheXMgZm9yIG1ha2UvdGFrZS9naXZlCmBgYHtyIGxpZ2h0LWFubixldmFsPUYsZWNobz1UfQpnZXQubGlnaHQuYW5ub3RhdGlvbjwtZnVuY3Rpb24oY29ycHVzLmRmLmRlcHJlbCl7CiAgY29uY3JldGUuZ2l2ZTwtYygxMDY2LDI2MjAsMTA0NjksMjAzNjksMjAzNzMsMjAzNzcsMzE5NTcsNDExMDAsNDU0MjQsNDU1MzgsNDgwNDUsNTAyMzYsNTE3NTksNTIzNDAsNTIzNDEsNTQ2NTQsNTYwMTYsNjA2NjgsCiAgICAgICAgICAgICAgICAgICA2MTk1Miw2NDM1MSw2NzQ5Nyw2OTAxMiw3MDM1Niw3MTE2Nyw3NDU5NSw3NTE2Miw3Njk5MSw3NzQ0Miw3NzU1Myw4MTA5OCw4MTA5OSw4MTg1OSw4MTg2MCw5NDI3OCwKICAgICAgICAgICAgICAgICAgIDk2OTUzLDk5MjgxLDk5ODgwKQogIAogIGNvbmNyZXRlLmdpdmUudHh0PC1jKCJzdGlja2VyIiwic3dlZXRzIiwiYW50aWJpb3RpYyIsImdpZnQiLCJpZ3VhbmEiLCJyZWNvZ25pdGlvbiIsInRvb3RocGljayIsImhlcmIiLCJhbnl0aGluZyIsImVuenltZSIsImNha2UiLCJsZXR0dWNlIiwiY2FuZHkiLCJjYXJkIiwibGl0ZXJhdHVyZSIsIm9ybmFtZW50IiwidGFwZSIsInRpY2tldCIsInBhaXIiLCJjbG90aGVzIiwianVpY2UiLCJwZXBwZXIiLCJtb25leSIsImdvbGRmaXNoIiwibWFjaGluZSIsImN1cCIsImtpc3MiLCJhbW91bnQiLCJiaXQiLCJwaWN0dXJlIiwibWluZSIsInBhc3MiLCJkb2xsYXIiLCJ0ZW4iLCJkcmluayIsInNvbWV0aGluZyIsImNhciIsImxvdCIpCiAgCiAgY29uY3JldGUubWFrZS50eHQ8LWMoImhvcnNlc2hvZSIsInNvdW5kIiwiY2FydGlsYWdlIiwiY2V2aWNoZSIsImZvb2QiLCJub2lzZSIsImhheSIsImdyYXBlIiwiY29va2llIiwic3BhdHVsYSIsImNsb3RoZXMiLCJ3aXBlciIsInF1aWx0Iiwib3V0Zml0IiwiY29weSIsInRhcGUiLCJzdHJpbmciLCJpbnRlcmNlc3Npb24iLCJhcHBsaWNhdGlvbiIsImJhbGxvb24iLCJiYXNrZXQiLCJrZWJhYiIsInNhbGFkIiwianVpY2UiLCJncmF2eSIsInRhbWFsZSIsInNhdWNlIiwidG9uIiwidGFpbCIsInN0dWZmIiwicGFwZXJzIiwicGFzdGEiLCJsb2FmIiwic2FuZHdpY2giLCJvcm5hbWVudCIsInBpY3R1cmUiLCJwaWxsb3ciLCJkYXRhYmFzZSIsInN0YXR1ZSIsInBpenphIiwiZnVkZ2UiLCJyZWNpcGUiLCJwYW4iLCJwbGF0ZSIsImRlY2FmIiwidGFydCIpCiAgCiAgY29uY3JldGUudGFrZTwtYyg4NDgsNjM4MSwxNDQ2NiwxNjY3NCwxODYxMSwxODgwOSwxOTM2NiwyMjAzMSwyNDgxMywyNDgyNywyNDgyOSwyNDgzMSwyNDgzMiwyNDgzNCwyNDgzNSwyOTE1OSwzMjkwOCwzNjU0MCwKICAgICAgICAgICAgICAgICAgIDM4MjM5LDM4MjQzLDM4MjQ3LDM4MjUzLDM4MjU0LDM4MjU4LDQ1MDIwLDQ1MDIxLDQ1MDMyLDQ5NTc3LDQ5NTgyLDQ5NTgzLDQ5NTg4LDUzMjY3LDU2NDA1LDU2NDA2LDU2NDA5LAogICAgICAgICAgICAgICAgICAgNTkzNzIsNjE1ODgsNjE1OTIsNjU2NTQsNjU2NTYsNjU2NTcsNjYwMjEsNjk0NDAsNzExMjcsNzIyMDEsNzIzMjAsNzM3OTcsNzM3OTgsNzg0MzUsNzg0NDAsNzg0NDIsCiAgICAgICAgICAgICAgICAgICA3OTQ1NCw3OTQ1Niw4MjI4Miw4MzA5OSw4MzgzNCw4MzgzNiw4NDU5OSw4NTMxMSw4NTkzMiw4ODE1NSw4OTMxMCw5MTg2NSw5MzA3MCw5NjQ2NCw5NjQ2NSw5OTE0OSwKICAgICAgICAgICAgICAgICAgIDk5NzQ1LDEwNDAyMCwxMTc2OTUpCiAgCiAgY29uY3JldGUudGFrZS50eHQ8LWMoImJhbGxvb24iLCJzaGVsZiIsImNoZWNrYm9vayIsImNhciIsImJhZyIsImV2ZXJ5dGhpbmciLCJwdXBwaWVzIiwic2lsdmVyd2FyZSIsInRvcnF1ZSIsInRyZWUiLCJUdXBwZXJ3YXJlIiwid2FzdGViYXNrZXQiLCJ3aXJlIiwibW9uZXkiLCJjYXBzdWxlIiwiZ3VpdGFyIiwic3R1YiIsInRhaWwiLCJUeWxlbm9sIiwiYmxhbmtldCIsImNsaXBwaW5nIiwidGFibGVjbG90aCIsImNyb3duIiwibWVkaWNpbmUiLCJuYWlsIiwic3BhY2VzdWl0Iiwic3dlYXRlciIsImhlcnMiLCJrbmlmZSIsInJhY2siLCJyb2NrIiwiZGlhcnkiLCJ3b29kd29yayIsInBpbGwiLCJ0aWNrZXQiLCJ0cmFzaCIsInBsdWciLCJzb21lIiwidGFwZSIsImJhbmQiLCJmbGlwIiwid2F0ZXIiLCJjb250YWluZXIiLCJwYW50cyIsImJ1Y2siLCJpbnN1bGluIiwiZm9vdCIsInBhaW50aW5nIiwiZHJ1ZyIsImdpZnQiLCJjYXJ0IiwiaGFpciIsImVnZyIsImJhbGwiLCJkb2xsYXIiLCJwb3VuZCIsImRyaW5rIiwidGhpbmciLCJOUEgiKQogIGNvbmNyZXRlLmZhbHNlLnRha2U8LWMoIndoaWxlIiwidGltZSIsImNhcmUiLCJhZHZhbnRhZ2UiLCJwaWN0dXJlIiwiaGFsZiIsIm9mZiIsImRvd24iLCJkb2xsYXJzIHRvIGRvIGl0IiwibG9vayIsIndpdGggbWUiLCJvdXQiLCJ0aGVtIHRvIikKICBjb25jcmV0ZS5mYWxzZS50YWtlLnJlZ3g8LXBhc3RlMChjb25jcmV0ZS5mYWxzZS50YWtlLGNvbGxhcHNlID0gInwiKQogIGNvbmNyZXRlLmZhbHNlLnRha2UucmVneDwtcGFzdGUwKCIoIixjb25jcmV0ZS5mYWxzZS50YWtlLnJlZ3gsIikiKQogICNjb25jcmV0ZS50YWtlLnR4dDwtZ3N1YigiXFwuW05BMC0xXSIsIiIsY29uY3JldGUudGFrZS50eHQpCiAgIyB3cml0ZV9jbGlwKHBhc3RlMChjb25jcmV0ZS50YWtlLnR4dCxjb2xsYXBzZSA9ICciLCInKSkKICAKICBhbHQuYXJyYXk8LWMobWFrZT1jKCJidWlsZCIsImNyZWF0ZSIsInByb2R1Y2UiLCJnZW5lcmF0ZSIpLHRha2U9YygiY2FycnkiLCJicmluZyIpLGdpdmU9ImdpdmUiKQogICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKICAjIyMgYXBwbHkgbGlnaHQgbGFiZWwKICBjb3JwdXMuZGYuZGVwcmVsJGxpZ2h0PC1OQQogIGNvcnB1cy5kZi5kZXByZWwkYWx0PC0iYS1vdGhlciIKICAjIyMKIyAgIHEubGVtbWE8LSJtYWtlfG1hZGV8bWFraW5nIgojICAgcS5sZW1tYTwtImdpdmV8Z2l2ZW58Z2F2ZSIKIyAgIGxlbW1hPC0ibWFrZSIKIyAgIGxlbW1hPC0iZ2l2ZSIKIyAgICMjIwojICMgIGNvbmNyZXRlLmFycmF5PC1jKGNvbmNyZXRlLm1ha2UudHh0KQojICMgIGNvbmNyZXRlLmFycmF5PC1jKGNvbmNyZXRlLmdpdmUudHh0KQojICAgIyAjICBjb25jcmV0ZS5hcnJheQogIGFwcGx5LmxpZ2h0PC1mdW5jdGlvbihjb3JwdXMuZGYuZGVwcmVsPWNvcnB1cy5kZi5kZXByZWwscS5sZW1tYSxsZW1tYSxjb25jcmV0ZS5hcnJheSl7CiAgICBjb3JwdXMuZGYuZGVwcmVsJGxlbW1hPC1nc3ViKCJbXmEtekEteiddIiwiIixjb3JwdXMuZGYuZGVwcmVsJGxlbW1hKQogICAgY29ycHVzLmRmLmRlcHJlbCRoZWFkX2xlbW1hX3ZhbHVlPC1nc3ViKCJbXmEtekEteiddIiwiIixjb3JwdXMuZGYuZGVwcmVsJGhlYWRfbGVtbWFfdmFsdWUpCiAgICBtNTwtY29ycHVzLmRmLmRlcHJlbCRsZW1tYT09IiIKICAgIGNvcnB1cy5kZi5kZXByZWwkbGVtbWFbbTVdPC1OQQogICAgbTY8LWNvcnB1cy5kZi5kZXByZWwkaGVhZF9sZW1tYV92YWx1ZT09IiIKICAgIGNvcnB1cy5kZi5kZXByZWwkaGVhZF9sZW1tYV92YWx1ZVttNl08LU5BCiAgICBtMTwtZ3JlcGwocS5sZW1tYSxjb3JwdXMuZGYuZGVwcmVsJHNlbnRlbmNlKQogICAgbTEzPC1ncmVwbChsZW1tYSxjb3JwdXMuZGYuZGVwcmVsJGxlbW1hKQogICAgbTE0PC1ncmVwbChsZW1tYSxjb3JwdXMuZGYuZGVwcmVsJGhlYWRfbGVtbWFfdmFsdWUpCiAgICAKICAgICMgc3VtKG0xKQogICAgIyBzdW0obTEzKQogICAgIyAjY29ycHVzLmRmLmRlcHJlbCRzZW50ZW5jZVttMV0KICAgICMgI3VuaXF1ZShjb3JwdXMuZGYuZGVwcmVsJGhlYWRfbGVtbWFfdmFsdWUpCiAgICAjIGxlbmd0aCh1bmlxdWUoY29ycHVzLmRmLmRlcHJlbCRoZWFkX3Rva2VuX3ZhbHVlKSkKICAgICMgbGVuZ3RoKHVuaXF1ZShjb3JwdXMuZGYuZGVwcmVsJHRva2VuKSkKICAgICMgI3RhYmxlKGNvcnB1cy5kZi5kZXByZWwkbGVtbWEpCiAgICBjb3JwdXMuZGYuZGVwcmVsJGFsdFttMV08LWxlbW1hICMgc2V0IGNvbmNyZXRlIGluc3RhbmNlcwogICAgY29ycHVzLmRmLmRlcHJlbCRsaWdodFttMTNdPC0xICMgc2V0IGFsbCB0byBsaWdodAogICAgI2xlbW1hCiAgICBsaWJyYXJ5KHN0cmluZ2kpCiAgICBsaWJyYXJ5KHB1cnJyKQogICAgY29uY3JldGUucmVneDwtcGFzdGUwKGNvbmNyZXRlLmFycmF5LGNvbGxhcHNlID0gInwiKQogICAgY29uY3JldGUucmVneDwtcGFzdGUwKCcoJyxjb25jcmV0ZS5yZWd4LCcpJykKICAgIG0zODwtZ3JlcGwoY29uY3JldGUucmVneCxjb3JwdXMuZGYuZGVwcmVsJGxlbW1hKQogICAgbTQxLmFsdDwtY29ycHVzLmRmLmRlcHJlbCRhbHQ9PWxlbW1hCiAgICAjc3VtKG00MSkKICAgIGNvcnB1cy5kZi5kZXByZWwkbGlnaHRbbTQxLmFsdF08LTEKICAgIG00Mi5jb25jPC1jb3JwdXMuZGYuZGVwcmVsJGxlbW1hW200MS5hbHRdJWluJWNvbmNyZXRlLmFycmF5fGNvcnB1cy5kZi5kZXByZWwkdG9rZW5bbTQxLmFsdF0laW4lY29uY3JldGUuYXJyYXkKICAjICBzdW0obTQyLmNvbmMpCiAgICBtNDMub2JqPC1jb3JwdXMuZGYuZGVwcmVsJG9ialttNDEuYWx0XVttNDIuY29uY109PWxlbW1hCiAgICBjb3JwdXMuZGYuZGVwcmVsJGxpZ2h0W200MS5hbHRdW200Mi5jb25jXVttNDMub2JqXTwtMAogICAgIyAgICBzdW0obTQwKQogICAgIyAgIGNvcnB1cy5kZi5kZXByZWwkbGVtbWFbbTQxXVttMzldW200MF0KICAgIG0zOS5jb25jLnNlbnQ8LWdyZXBsKGNvbmNyZXRlLnJlZ3gsY29ycHVzLmRmLmRlcHJlbCRzZW50ZW5jZVttNDEuYWx0XSkKICAgIG00MC5sZW1tYS5hbHQuc2VudDwtZ3JlcGwobGVtbWEsY29ycHVzLmRmLmRlcHJlbCRsZW1tYVttNDEuYWx0XVttMzkuY29uYy5zZW50XSkKICAgICMgc3VtKGxlbW1hLGNvcnB1cy5kZi5kZXByZWwkbGVtbWFbbTM5XVttNDBdKQogICAgIyBjb3JwdXMuZGYuZGVwcmVsJGxpZ2h0W20zOF08LTAKICAgIGNvcnB1cy5kZi5kZXByZWwkbGlnaHRbbTQxLmFsdF1bbTM5LmNvbmMuc2VudF1bbTQwLmxlbW1hLmFsdC5zZW50XTwtMAogICAgcmV0dXJuKGNvcnB1cy5kZi5kZXByZWwpCiAgfQogIAogIGNvcnB1cy5kZi5kZXByZWw8LWFwcGx5LmxpZ2h0KGNvcnB1cy5kZi5kZXByZWwsIm1ha2V8bWFkZXxtYWtpbmciLCJtYWtlIixjb25jcmV0ZS5tYWtlLnR4dCkKICBjb3JwdXMuZGYuZGVwcmVsPC1hcHBseS5saWdodChjb3JwdXMuZGYuZGVwcmVsLCJ0YWtlfHRvb2t8dGFrZW58dGFraW5nIiwidGFrZSIsY29uY3JldGUudGFrZS50eHQpCiAgY29ycHVzLmRmLmRlcHJlbDwtYXBwbHkubGlnaHQoY29ycHVzLmRmLmRlcHJlbCwiZ2l2ZXxnYXZlfGdpdmVufGdpdmluZyIsImdpdmUiLGNvbmNyZXRlLmdpdmUudHh0KQogIGNvcnB1cy5kZi5kZXByZWw8LWFwcGx5LmxpZ2h0KGNvcnB1cy5kZi5kZXByZWwsIihwcm9kdWNlW15yXXxwcm9kdWNlZHxwcm9kdWNpbmcpIiwicHJvZHVjZSIsY29uY3JldGUubWFrZS50eHQpCiAgY29ycHVzLmRmLmRlcHJlbDwtYXBwbHkubGlnaHQoY29ycHVzLmRmLmRlcHJlbCwiY3JlYXRlfGNyZWF0ZWR8Y3JlYXRpbmciLCJjcmVhdGUiLGNvbmNyZXRlLm1ha2UudHh0KQogIGNvcnB1cy5kZi5kZXByZWw8LWFwcGx5LmxpZ2h0KGNvcnB1cy5kZi5kZXByZWwsImdlbmVyYXRlfGdlbmVyYXRlZHxnZW5lcmF0aW5nIiwiZ2VuZXJhdGUiLGNvbmNyZXRlLm1ha2UudHh0KQogIGNvcnB1cy5kZi5kZXByZWw8LWFwcGx5LmxpZ2h0KGNvcnB1cy5kZi5kZXByZWwsImJ1aWxkfGJ1aWx0fGJ1aWxkaW5nIiwiYnVpbGQiLGNvbmNyZXRlLm1ha2UudHh0KQogIGNvcnB1cy5kZi5kZXByZWw8LWFwcGx5LmxpZ2h0KGNvcnB1cy5kZi5kZXByZWwsImNhcnJ5fGNhcnJpZWR8Y2FycnlpbmciLCJjYXJyeSIsY29uY3JldGUudGFrZS50eHQpCiAgY29ycHVzLmRmLmRlcHJlbDwtYXBwbHkubGlnaHQoY29ycHVzLmRmLmRlcHJlbCwiYnJpbmd8YnJvdWdodHxicmluZ2luZyIsImJyaW5nIixjb25jcmV0ZS50YWtlLnR4dCkKICB0YWJsZShjb3JwdXMuZGYuZGVwcmVsJGFsdCxjb3JwdXMuZGYuZGVwcmVsJGxpZ2h0LGNvcnB1cy5kZi5kZXByZWwkaGVhZF9sZW1tYV92YWx1ZSkKICAjY2hrCiAgcmV0dXJuKGNvcnB1cy5kZi5kZXByZWwpCn0KY29ycHVzLmRmLmRlcHJlbC5uZXc8LWdldC5saWdodC5hbm5vdGF0aW9uKGNvcnB1cy5kZi5kZXByZWwpCmBgYAoKCiMjIGNvbGxvc3RydWN0aW9uIGRmCmZ1bmN0aW9ucyB0byBjcmVhdGUgYSBzdWJzZXQgYW5kIGZlZWQgaW50byBjb2xsZXhlbWUgYW5hbHlzaXMKYGBge3IgY29sbGV4LWZ1bmMsZXZhbD1GLGVjaG89VH0KZ2V0LmNvbGxleDwtZnVuY3Rpb24oY29sbDYsZmlsdGVyLnBvcyx2ZXJzLG5hLnJtPUZBTFNFKXsKICBtMzwtY29sbDYkbGVtbWE9PWNvbGw2JGhlYWRfbGVtbWFfdmFsdWUgIyByZW1vdmUgb2JzZXJ2YXRpb25zIHdpdGggbGVtbWE9PWhlYWRfbGVtbWEKICBzdW0obTMsbmEucm0gPSBUKQogICNjb2xsNm5hPC1jb2xsNgogIGNvbGw2PC1jb2xsNlshbTMsXQogIG00PC0haXMubmEoY29sbDYkbGlnaHQpCiMgIHN1bShtNCkKICMgazwtMQogIGlmKG5hLnJtPT1GKQogICAgY29sbDYkbGlnaHRbbTRdPC0ibi5hLiIKICAjIG01PC1pcy5uYShjb2xsNiRvYmoudG8pCiAgIyBjb2xsNjwtY29sbDZbIW01LF0KICBpZihsZW5ndGgoZmlsdGVyLnBvcyk+MCl7CiAgICBmb3IoayBpbiBsZW5ndGgoZmlsdGVyLnBvcykpewogICAgICBjb2w8LW5hbWVzKGZpbHRlci5wb3Nba10pCiAgICAgIGNvbGw2PC1jb2xsNltjb2xsNltbY29sXV0laW4lZmlsdGVyLnBvc1tba11dLF0KICAgIH0KICB9CiAgaWYodmVycz09ImxpZ2h0Iil7CiAgICBjb2xsZGYubGlnaHQ8LWRhdGEuZnJhbWUoaGVhZF9sZW1tYT1jb2xsNiRoZWFkX2xlbW1hX3ZhbHVlLGxlbW1hPWNvbGw2JGxlbW1hLGxpZ2h0PWNvbGw2JGxpZ2h0KQogICAgY29sbDYuMjwtY29sbGV4LmNvdmFyLm11bHQoY29sbGRmLmxpZ2h0LHRocmVzaG9sZCA9IDEsZGVjaW1hbHMgPSAzKQogIH0KICAjICBjb2xsNi4yCiAgaWYodmVycz09ImxlbW1hIil7CiAgICBjb2xsZGYubGVtbWE8LWRhdGEuZnJhbWUoaGVhZF9sZW1tYT1jb2xsNiRoZWFkX2xlbW1hX3ZhbHVlLGxlbW1hPWNvbGw2JGxlbW1hKQogICAgY29sbDYuMjwtY29sbGV4LmNvdmFyKGNvbGxkZi5sZW1tYSxkZWNpbWFscyA9IDMpCiAgfQogIHJldHVybihjb2xsNi4yKQp9CiNkaXNjYXJkPC0icXVlZW4iCmdldC5jb2xsZXgub2JqPC1mdW5jdGlvbihjb2xsNixkaXNwbGF5LmxpZ2h0PU5VTEwsc2VsZWN0LmZpbHRlcj1OVUxMLGRpc3BsYXkuZmlsdGVyPU5VTEwsZGlzY2FyZD1OVUxMKXsKICBjb2xsNi5vYmo8LWRhdGEuZnJhbWUobGVtbWE9dW5saXN0KGNvbGw2JGxlbW1hKSxvYmo9dW5saXN0KGNvbGw2JG9iaiksdXBvcz11bmxpc3QoY29sbDYkdXBvcyksbGlnaHQ9Y29sbDYkbGlnaHQpCiAgY29sbDYub2JqLm48LWNvbGw2Lm9ialtjb2xsNi5vYmokdXBvcz09Ik5PVU4iJiFpcy5uYShjb2xsNi5vYmokb2JqKSxdCiAgY29sbGRmPC1kYXRhLmZyYW1lKG9iaj1jb2xsNi5vYmoubiRvYmosbGVtbWE9Y29sbDYub2JqLm4kbGVtbWEsbGlnaHQ9Y29sbDYub2JqLm4kbGlnaHQpCiAgCiAgaWYobGVuZ3RoKHNlbGVjdC5maWx0ZXIpPjApewogICAgY29sbGRmPC1jb2xsZGZbY29sbGRmJG9iaiVpbiVzZWxlY3QuZmlsdGVyLF0KICB9CiAgCiAgaWYobGVuZ3RoKGRpc2NhcmQpPjApewogICAgY29sbGRmPC1jb2xsZGZbY29sbGRmJGxlbW1hIT1kaXNjYXJkLF0KICB9CiAgCiAgaWYobGVuZ3RoKGRpc3BsYXkubGlnaHQpPT0wKXsKICAgIGNvbGw2LjI8LWNvbGxleC5jb3ZhcihkYXRhLmZyYW1lKGNvbGxkZlssMV0sY29sbGRmWywyXSksZGVjaW1hbHMgPSAzKQogIH0KICAKICBpZihsZW5ndGgoZGlzcGxheS5saWdodCk+MCl7CiAgICBjb2xsNi4yPC1jb2xsZXguY292YXIubXVsdChjb2xsZGYsdGhyZXNob2xkID0gMSxkZWNpbWFscyA9IDMpCiAgICBjb2xsNi4yPC1jb2xsNi4yW2NvbGw2LjIkbGlnaHQlaW4lZGlzcGxheS5saWdodCxdCiAgfQogIAogIGlmKGxlbmd0aChkaXNwbGF5LmZpbHRlcik+MCl7CiAgICBjb2xsNi4yPC1jb2xsNi4yW2NvbGw2LjJbLDFdJWluJWRpc3BsYXkuZmlsdGVyLF0KICB9CiAgcmV0dXJuKGNvbGw2LjIpCn0KCmNvbGw2PC1jb3JwdXMuZGYuZGVwcmVsLm5ldwpgYGAKCgpgYGB7ciBpY2UtZGF0YSxldmFsPUYsZWNobz1UfQojIyMjIyMjIyMjIyMjCiMjIyBpbnN0YW5jZXMgY29uY3JldGUgdnMuIGxpZ2h0CiMjIyBRLjE6IChNZWhsIDIwMjEpCmkubWFrZS53PC1jKGNvbmNyZXRlPTY4LGxpZ2h0PTMyMSkgIzE3JSB2cy4gODMlIHdyaXR0ZW4gSUNFIAppLm1ha2UuczwtYyhjb25jcmV0ZT05NixsaWdodD0zNTMpICNzcG9rZW4gSUNFCmkudGFrZS53PC1jKGNvbj02MixsaWdodD04NSkgCmkuZ2l2ZS53PC1jKGNvbj01MixsaWdodD0xNjcpCmkudGFrZS5zPC1jKGNvbj0xMzEsbGlnaHQ9NzkpIAppLmdpdmUuczwtYyhjb249MTA1LGxpZ2h0PTIyNykKImluIHRoZSB3cml0dGVuIHBvcnRpb24gb2YgSUNFLUdCLCB0aGUgbGlnaHQgdXNlIG9mIGVhY2ggdmVyYiBpcyBtb3JlIGNvbW1vbiB0aGFuIHRoZSBjb25jcmV0ZSBzZW5zZS4gCkZvciBleGFtcGxlLCBvdXQgb2YgdGhlIHRvdGFsIG51bWJlciBvZiBpbnN0YW5jZXMgb2YgbWFrZSBpbiBhbGwgY29uY3JldGUgYW5kIGxpZ2h0IHVzZXMsIApqdXN0IG92ZXIgODAlIG9mIGluc3RhbmNlcyBhcmUgdGhlIGxpZ2h0IHVzZSwgYW5kIGp1c3QgdW5kZXIgMjAlIGFyZSB0aGUgY29uY3JldGUgdXNlLiIKcm93bmFtZXMocGxvdGRmLmFubiRwbG90LmRpc3QpPC1jKCJjb25jcmV0ZSIsImxpZ2h0IikKbHNiYzwtbGVuZ3RoKGNvcnB1cy5kZi5kZXByZWwkc2JjLmlkKQpwbG90ZGYuYW5uPC1saXN0KGxzYmM9bHNiYyxwbG90LmRpc3Q9cGxvdGRmMSxhbm49bGlzdChtYWluPSJkaXN0cmlidXRpb24gb2YgbGVtbWFzIG92ZXIgY29ycG9yYSIseWxhYj0iYWJzb2x1dGUgb2NjdXJlbmNlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gYygiY29uY3JldGUgdXNlIiwibGlnaHQgdXNlIikpKQpyb3duYW1lcyhwbG90ZGYuYW5uJHBsb3QuZGlzdCk8LWMoImNvbmNyZXRlIiwibGlnaHQiKQoKYGBgCgojIyBjYWxsIGNvbGxleCBmdW5jdGlvbnMKZGVmaW5lIHN1YnNldHMgYW5kIGNyZWF0ZSBjb2xsZXggZGYKYGBge3IgY29sbC1kZnMsZXZhbD1GLGVjaG89VH0KIGNvbGw2LjI8LWdldC5jb2xsZXgub2JqKGNvbGw2LGRpc3BsYXkubGlnaHQ9YygwLDEpLGRpc3BsYXkuZmlsdGVyID0gIm1ha2UiKQogY29sbDYuMjwtZ2V0LmNvbGxleC5vYmooY29sbDYsZGlzcGxheS5saWdodD1OVUxMLGRpc3BsYXkuZmlsdGVyID0gYygibWFrZSIsInRha2UiLCJnaXZlIikpCiBjb2xsNi4yLmxpZ2h0PC1nZXQuY29sbGV4Lm9iaihjb2xsNixkaXNwbGF5LmxpZ2h0PWMoMCkpCiAjdGFibGUoY29sbDYuMi5saWdodCRvYmopCiBjb2xsNi4yLm9iajwtZ2V0LmNvbGxleC5vYmooY29sbDYsZGlzcGxheS5saWdodD1OVUxMKQogb2JqLmFycmF5PC1jKG1ha2UuYXJyYXksdGFrZS5hcnJheSwiZ2l2ZSIpCiBkaXNwbGF5LmZpbHRlcjwtIG9iai5hcnJheQogY29sbDYuMi5vYmouZjwtZ2V0LmNvbGxleC5vYmooY29sbDYsZGlzcGxheS5saWdodD1jKDAsMSksZGlzcGxheS5maWx0ZXIgPSBvYmouYXJyYXkpCiAKYGBgCgojIyBldmFsdWF0aW9uIG9mIGNvbGxleCBkZgpgYGB7ciBsZW1tYS1vYmotMSxldmFsPUZ9CmFwcGx5Lm1vZGVsPC1mdW5jdGlvbihjb2xsNixwLmxvd2VyLnRhaWwsc2VsZWN0LmZpbHRlcj1OVUxMKXsKICAjYm94cGxvdChhbW9kZWwkQ09MTC5TVFIuTE9HTH5hbW9kZWwkU0xPVDEpCiAgYW1vZGVsPC1nZXQuY29sbGV4Lm9iaihjb2xsNixzZWxlY3QuZmlsdGVyID0gc2VsZWN0LmZpbHRlcikKICBkZjwtbGVuZ3RoKGxldmVscyhmYWN0b3IoYW1vZGVsJFNMT1QxKSkpLTEKICBkZgogIGFtb2RlbCRwPC1wdChhbW9kZWwkQ09MTC5TVFIuTE9HTCxkZixsb3dlci50YWlsID0gcC5sb3dlci50YWlsKQogIGFtb2RlbDwtYW1vZGVsW2Ftb2RlbCRTTE9UMSVpbiVtYWtlLmFycmF5LF0KICBhbW9kZWw8LXJiaW5kKGFtb2RlbFtkdXBsaWNhdGVkKGFtb2RlbCRTTE9UMixmcm9tTGFzdCA9IFQpLF0sYW1vZGVsW2R1cGxpY2F0ZWQoYW1vZGVsJFNMT1QyLGZyb21MYXN0ID0gRiksXSkKICAjYW1vZGVsPC1hbW9kZWwuZFthbW9kZWwuZCRTTE9UMSVpbiVtYWtlLmFycmF5LF0KICBpZmVsc2UobGVuZ3RoKHNlbGVjdC5maWx0ZXIpPjAsbW9kZWw8LSJtb2RlbDIiLG1vZGVsPC0ibW9kZWwxIikKICB4bGFiPC1zcHJpbnRmKCJsZW1tYSBpbiBlcXVpdmFsZW50IGNvbnRleHQ7IGxvd2VyLnRhaWw9JXMsICVzIixwLmxvd2VyLnRhaWwsbW9kZWwpCiAgYm94cGxvdChhbW9kZWwkQ09MTC5TVFIuTE9HTH5hbW9kZWwkU0xPVDEsb3V0bGluZT1GLG1haW49InByZWZlcmVuY2Ugb2YgbWFrZSB2cy4gYWx0ZXJuYXRlcyIseGxhYiA9IHhsYWIseWxhYiA9ICJULXNjb3JlIG9mIGxlbW1hL29iamVjdCBhc3NvY2lhdGlvbiBzdHJlbmd0aCIpCiAgYm94cGxvdChhbW9kZWwkcH5hbW9kZWwkU0xPVDEsb3V0bGluZT1GLG1haW49InByZWZlcmVuY2Ugb2YgbWFrZSB2cy4gYWx0ZXJuYXRlcyIseGxhYiA9IHhsYWIseWxhYiA9ICJwLXZhbHVlIG9mIGxlbW1hL29iamVjdCBhc3NvY2lhdGlvbiBzdHJlbmd0aCIpCiAgIyMjIHByZWZlcmVuY2Ugb2YgbWFrZSBvdmVyIHByb2R1Y2UKICBhbW9kZWw8LWdldC5jb2xsZXgub2JqKGNvbGw2KQogIGRmPC1sZW5ndGgobGV2ZWxzKGZhY3RvcihhbW9kZWwkU0xPVDEpKSktMQogIGRmCiAgYW1vZGVsJHA8LXB0KGFtb2RlbCRDT0xMLlNUUi5MT0dMLGRmLGxvd2VyLnRhaWwgPSBwLmxvd2VyLnRhaWwpCiAgYW1vZGVsPC1hbW9kZWxbYW1vZGVsJFNMT1QxJWluJXRha2UuYXJyYXksXQogIGFtb2RlbDwtcmJpbmQoYW1vZGVsW2R1cGxpY2F0ZWQoYW1vZGVsJFNMT1QyLGZyb21MYXN0ID0gVCksXSxhbW9kZWxbZHVwbGljYXRlZChhbW9kZWwkU0xPVDIsZnJvbUxhc3QgPSBGKSxdKQogICNhbW9kZWw8LWFtb2RlbC5kW2Ftb2RlbC5kJFNMT1QxJWluJW1ha2UuYXJyYXksXQogIGJveHBsb3QoYW1vZGVsJENPTEwuU1RSLkxPR0x+YW1vZGVsJFNMT1QxLG91dGxpbmU9RixtYWluPSJwcmVmZXJlbmNlIG9mIHRha2UgdnMuIGFsdGVybmF0ZXMiLHhsYWIgPSB4bGFiLHlsYWIgPSAiVC1zY29yZSBvZiBsZW1tYS9vYmplY3QgYXNzb2NpYXRpb24gc3RyZW5ndGgiKQogIGJveHBsb3QoYW1vZGVsJHB+YW1vZGVsJFNMT1QxLG91dGxpbmU9RixtYWluPSJwcmVmZXJlbmNlIG9mIHRha2UgdnMuIGFsdGVybmF0ZXMiLAogICAgICAgICAgeGxhYiA9IHhsYWIseWxhYiA9ICJwLXZhbHVlIG9mIGxlbW1hL29iamVjdCBhc3NvY2lhdGlvbiBzdHJlbmd0aCIpCiAgCn0KCmBgYAoKCgoKYGBge3Igc2VtYS1zdW1zLGV2YWw9RixlY2hvPVR9Cm9iai5tYWtlPC1jb2xsNi4yLm9ialtjb2xsNi4yLm9iaiRTTE9UMSVpbiVtYWtlLmFycmF5LF0Kc2VtYS5tYWtlPC1vYmoubWFrZVtvYmoubWFrZSRTTE9UMiVpbiVvYmoubWFrZVtkdXBsaWNhdGVkKG9iai5tYWtlJFNMT1QyKSxdWywyXSxdCm9iai50YWtlPC1jb2xsNi4yLm9ialtjb2xsNi4yLm9iaiRTTE9UMSVpbiV0YWtlLmFycmF5LF0Kc2VtYS50YWtlPC1vYmoudGFrZVtvYmoudGFrZSRTTE9UMiVpbiVvYmoudGFrZVtkdXBsaWNhdGVkKG9iai50YWtlJFNMT1QyKSxdWywyXSxdCmNvbGwuc2VtYS4xPC1saXN0KG1ha2U9c2VtYS5tYWtlLHRha2U9c2VtYS50YWtlKQp4PC1zZW1hLm1ha2UKeTwtbWFrZS5hcnJheQpzZW1hLnN1bTwtZnVuY3Rpb24oeSl5PXN1bSh4WydDT0xMLlNUUi5MT0dMJ11beFsnU0xPVDEnXT09eV0pCm1ha2Uuc3VtPC1saXN0KG1ha2UuYXJyYXkpCm1ha2Uuc3VtW21ha2UuYXJyYXldPC1sYXBwbHkoeSwgc2VtYS5zdW0pICAgIAptYWtlLnN1bQp4PC1zZW1hLnRha2UKeTwtdGFrZS5hcnJheQpzZW1hLnN1bTwtZnVuY3Rpb24oeSl5PXN1bSh4WydDT0xMLlNUUi5MT0dMJ11beFsnU0xPVDEnXT09eV0pCnRha2Uuc3VtPC1saXN0KHRha2UuYXJyYXkpCnRha2Uuc3VtW3Rha2UuYXJyYXldPC1sYXBwbHkoeSwgc2VtYS5zdW0pICAgCmRmPC1mYWN0b3IoY29sbDYuMi5vYmokU0xPVDEpCmRmPC1sZW5ndGgobGV2ZWxzKGRmKSkKZ2V0LnA8LWZ1bmN0aW9uKHgpcHQoeCxkZixsb3dlci50YWlsID0gRikKI2dldC5wPC1mdW5jdGlvbih4KXB0KHgsZGYsbG93ZXIudGFpbCA9IFQpCmV2YWwxPC1zZW1hLm1ha2UKZXZhbDEkcDwtdW5saXN0KGxhcHBseShldmFsMSRDT0xMLlNUUi5MT0dMLCBnZXQucCkpCmV2YWwyPC1zZW1hLnRha2UKZXZhbDIkcDwtdW5saXN0KGxhcHBseShldmFsMiRDT0xMLlNUUi5MT0dMLCBnZXQucCkpCnBhcihsYXM9MykKZXZhbC5tYWtlPC1ldmFsMQpldmFsLnRha2U8LWV2YWwyCgpgYGAKCiMjIGxlbW1hLW9iamVjdCBjb2xsZXhlbWUgYW5hbHlzaXMKYGBge3IgZXZhbC1vYmosZXZhbD1GLGVjaG89VH0KIyMjIGNvbmNyZXRlIG9iamVjdHMgZnJlcXVlbmN5Cm1ha2UuYXJyYXk8LWMoIm1ha2UiLCJnZW5lcmF0ZSIsInByb2R1Y2UiLCJjcmVhdGUiLCJidWlsZCIpCnRha2UuYXJyYXk8LWMoImNhcnJ5IiwiYnJpbmciKQpvYmouYXJyYXk8LWMobWFrZS5hcnJheSx0YWtlLmFycmF5LCJnaXZlIikKZGlzcGxheS5maWx0ZXI8LSBvYmouYXJyYXkKY29sbDYuMi5vYmouZjwtZ2V0LmNvbGxleC5vYmooY29sbDYsZGlzcGxheS5saWdodD1OVUxMLGRpc3BsYXkuZmlsdGVyID0gb2JqLmFycmF5KQpjb2xsNi4yLm9iai5mCm9iai50PC10YWJsZShjb2xsNi4yLm9iai5mWywxXSkKb2JqLmFsbC50PC1vYmoudFtvYmoudCE9MF0KIyMjIGNvbmNyZXRlIG9iamVjdHM6CmNvbmNyZXRlLmFycmF5PC1jKCJnaXZlIixjb25jcmV0ZS5tYWtlLnR4dCxjb25jcmV0ZS50YWtlLnR4dCkKc3ViLm9iai50PC1jb2xsNi4yLm9iai5mW2NvbGw2LjIub2JqLmYkU0xPVDIlaW4lY29uY3JldGUuYXJyYXksXQpjb25jLm9iai50PC10YWJsZShzdWIub2JqLnRbLDFdKQpvYmouYWxsLmNvbmMudDwtY29uYy5vYmoudFtjb25jLm9iai50IT0wXQpvYmouZXZhbDwtcmJpbmQoYWxsLm9iamVjdHM9b2JqLmFsbC50LGFsbC5jb25jLm9iaj1vYmouYWxsLmNvbmMudCkKb2JqLmV2YWwKYGBgCgoKCmBgYHtyIGNpdGUtcGtnLGV2YWw9VCxlY2hvPUZBTFNFfQogI2tuaXRyOjp3cml0ZV9iaWIoYygucGFja2FnZXMoKSksICJwYWNrYWdlcy5iaWIiKQoKYGBgCgotLS0tLS0KIyBCIHJlZmVyZW5jZXM=