Introdução

Mantemos a série histórica dos chutes em disciplinas da UFABC. As pessoas mais caretas chamam isso de matrículas indeferidas na primeira fase de matrícula.

Logo

Logo

Código fonte e dados

Nossos códigos e dados são open source. Usem e abusem!

código fonte Licença GPLv3 licença

Importando os Dados

Vamos começar carregando alguns pacotes. Talvez seja necessário instalá-los.

# Se for necessário intalar esses pacotes
# install.packages("squash")
# install.packages("gridExtra")
# install.packages("plotrix")
# install.packages(c("ggplot2","RColorBrewer","scales"))
# install.packages("manipulate")
# install.packages("parallel")
# install.packages("rmarkdown")
# Carregando os Pacotes Necessários
# install.packages("dplyr")
library( dplyr)
library(squash); library(gridExtra); library(plotrix)
library(ggplot2); library(scales); library(grid); library(RColorBrewer)
library(manipulate)
library(knitr)
library(kableExtra)
library(rmarkdown)
library(gridExtra)
library(grid)
options(knitr.table.format = "markdown") 
# Pacotes para paralelizar
# library(parallel)
# numero cores (total-1)  Esse é o máximo razoavel
# no_cores <- detectCores() - 1
# Iniciar o cluster
# cl <- makeCluster(no_cores)

Vamos importar os dados dos arquivos. Esses arquivos estão na pasta dados

# Importa arquivos de Dados de Disciplina
disciplinas.bct<-read.csv("./dados/listasdedisciplinas/discbct.csv")
disciplinas.bch<-read.csv("./dados/listasdedisciplinas/discbch.csv")
disciplinas.nucleo<-read.csv("./dados/listasdedisciplinas/discnucleo.csv")
disciplinas.bct.mat<-read.csv("./dados/listasdedisciplinas/discmatbi.csv")
disciplinas<-unique(as.data.frame(read.csv("./dados/listasdedisciplinas/disciplinas.csv")))
rotulos.cursos<-disciplinas
disciplinas<-unique(disciplinas[1])
# Importa arquivos com Dados de Chutes
chutes.2011.1<-readLines("./dados/chutes/2011.1.txt")
chutes.2011.2<-readLines("./dados/chutes/2011.2.txt")
chutes.2011.3<-readLines("./dados/chutes/2011.3.txt")
chutes.2012.1<-readLines("./dados/chutes/2012.1.txt")
chutes.2012.2<-readLines("./dados/chutes/2012.2.txt")
chutes.2012.3<-readLines("./dados/chutes/2012.3.txt")
chutes.2013.1<-readLines("./dados/chutes/2013.1.txt")
chutes.2013.2<-readLines("./dados/chutes/2013.2.txt")
chutes.2013.3<-readLines("./dados/chutes/2013.3.txt")
chutes.2014.1<-readLines("./dados/chutes/2014.1.txt")
chutes.2014.2<-readLines("./dados/chutes/2014.2.txt")
chutes.2014.3<-readLines("./dados/chutes/2014.3.txt")
chutes.2015.1<-readLines("./dados/chutes/2015.1.txt")
chutes.2015.2<-readLines("./dados/chutes/2015.2.txt")
chutes.2015.3<-readLines("./dados/chutes/2015.3.txt")
chutes.2016.1<-readLines("./dados/chutes/2016.1.txt")
chutes.2016.2<-readLines("./dados/chutes/2016.2.txt")
chutes.2016.3<-readLines("./dados/chutes/2016.3.txt")
chutes.2017.1<-readLines("./dados/chutes/2017.1.txt")
chutes.2017.2<-readLines("./dados/chutes/2017.2.txt")
chutes.2017.3<-readLines("./dados/chutes/2017.3.txt")
chutes.2018.1<-readLines("./dados/chutes/2018.1.txt")
chutes.2018.2<-readLines("./dados/chutes/2018.2.txt")
ultimo=chutes.2018.2
qual.quad=2018.2
numero.quad=23

A função a seguir é a função mais importante! Ela conta a ocorrência de uma string num arquivo. É com ela que contaremos os chutes nos arquivos de chutes

# Conta chutes
contachutes<-function(v,w){length(grep(v,w))}

Vamos colocar rótulos nas disciplinas

func.rotulo<-function(v){
     if(v %in% t(disciplinas.nucleo))
  { "nucleocomum"} else {
tolower(paste(t(rotulos.cursos[rotulos.cursos[,1] ==v,2,drop=FALSE]),collapse=" "))}}
rotulos.disciplinas<-sapply(t(disciplinas[1]),func.rotulo)
rotulos.disciplinas<-data.matrix(rotulos.disciplinas)
colnames(rotulos.disciplinas) <- c("Cursos")

Chutes do Último Quadrimestre

Vamos contar os chutes em todas as disciplinas no ultimo quadrimestre. (filtrar para mostrar apenas as com mais de 50 chutes e ordenar.)

# Boa parte do que faremos consiste em aplicar uma função numa lista com sapply
chutes <-sapply(t(disciplinas),contachutes, w=ultimo)
chutes <-sort(chutes[which(chutes > 40)],  decreasing = TRUE)
chutes<-data.matrix(chutes)
colnames(chutes) <- c("Chutes")

Vamos ver as disciplinas com mais chutes

chutes.label<-merge(chutes,rotulos.disciplinas, by = "row.names")
chutes.label=chutes.label[order(chutes.label[,2],decreasing = TRUE),]
kable(chutes.label)


|   |Row.names                                          | Chutes|Cursos                    |
|:--|:--------------------------------------------------|------:|:-------------------------|
|46 |mecanica dos solidos i                             |    402|nucleocomum               |
|54 |principios de administracao                        |    370|nucleocomum               |
|37 |introducao as equacoes diferenciais ordinarias     |    355|bct                       |
|17 |engenharia economica                               |    327|nucleocomum               |
|20 |engenharia unificada i                             |    279|nucleocomum               |
|24 |fenomenos eletromagneticos                         |    255|bct                       |
|14 |economia de empresas                               |    226|egest                     |
|51 |pensamento economico                               |    215|bch                       |
|35 |introducao a probabilidade e a estatistica         |    210|bch bct                   |
|25 |fundamentos de desenho tecnico                     |    197|nucleocomum               |
|4  |bases epistemologicas da ciencia moderna           |    187|bct bch                   |
|5  |bases matematicas                                  |    179|bct bch                   |
|47 |metodos experimentais em engenharia                |    157|nucleocomum               |
|36 |introducao as engenharias                          |    148|nucleocomum               |
|7  |circuitos eletricos e fotonica                     |    140|nucleocomum               |
|45 |materiais e suas propriedades                      |    130|nucleocomum               |
|34 |interpretacoes do brasil                           |    122|bch                       |
|59 |sistemas digitais                                  |    122|bcc                       |
|50 |organizacao do trabalho                            |    118|egest                     |
|40 |libras                                             |    107|lbio lmat lfis lqui lfilo |
|8  |circuitos eletricos i                              |    105|een eiar einfo ebiom      |
|32 |identidade e cultura                               |    104|bch                       |
|18 |engenharia economica aplicada a sistemas de gestao |    103|egest                     |
|57 |sistemas cad/cam                                   |     99|eiar                      |
|41 |macroeconomia i                                    |     96|bceco                     |
|53 |praticas em ciencias e humanidades                 |     93|bch                       |
|52 |pesquisa operacional                               |     87|egest                     |
|61 |temas e problemas em filosofia                     |     83|bch                       |
|60 |sistemas e processos de producao                   |     80|egest                     |
|10 |desenvolvimento e sustentabilidade                 |     79|bch                       |
|58 |sistemas cam                                       |     76|egest                     |
|23 |fenomenos de transporte                            |     73|nucleocomum               |
|39 |laboratorio de maquinas eletricas                  |     72|een eiar                  |
|42 |maquinas eletricas                                 |     72|een eiar                  |
|21 |estado e relacoes de poder                         |     70|bch                       |
|19 |engenharia laboral                                 |     67|egest                     |
|3  |bases computacionais da ciencia                    |     65|bch bct                   |
|56 |projeto assistido por computador                   |     64|eiar                      |
|11 |desenvolvimento integrado do produto               |     62|egest                     |
|1  |aeroelasticidade                                   |     60|eaero                     |
|13 |economia brasileira contemporanea i                |     60|bceco                     |
|33 |interacoes atomicas e moleculares                  |     59|bct                       |
|9  |custos                                             |     58|egest                     |
|62 |termodinamica aplica                               |     58|descon                    |
|63 |termodinamica aplicada                             |     58|descon                    |
|64 |termodinamica aplicada i                           |     58|nucleocomum               |
|6  |bioetica                                           |     57|bnc bbio                  |
|30 |gestao de operacoes                                |     56|egest                     |
|12 |econometria 3                                      |     51|bceco                     |
|27 |geracao distribuida                                |     51|descon                    |
|48 |microeconomia i                                    |     51|bceco                     |
|28 |gerencia de ativos                                 |     49|egest                     |
|2  |analise de sistemas e modelagem ambiental          |     47|eau                       |
|15 |economia institucional i                           |     47|bceco                     |
|55 |programacao para web                               |     47|descon                    |
|22 |estrutura e dinamica social                        |     46|bct bch                   |
|16 |economia internacional i                           |     45|bceco                     |
|38 |laboratorio de guiagem                             |     45|navegacao e controle      |
|49 |navegacao e controle                               |     45|descon                    |
|26 |fundamentos de robotica                            |     43|eiar                      |
|43 |materiais compositos                               |     43|emat                      |
|44 |materiais compositos e aplicacoes estruturais      |     43|eaero                     |
|29 |gestao da inovacao                                 |     41|descon                    |
|31 |historia do pensamento economico                   |     41|bceco                     |

Vamos colocar esses dados num Barplot básico:

barplot(t(chutes),20,main="Chutes por Disciplina")

Vamos analisar alguns grupos de disciplinas em especial. Começaremos pelo BC&T

BC&T

listadedisciplinas<-t(disciplinas.bct)
chutes.bct <- sapply(listadedisciplinas, contachutes,w=ultimo)
chutes.bct<-unique(data.matrix(chutes.bct))
colnames(chutes.bct) <- c("Chutes")
chutes.bct<-chutes.bct[order(chutes.bct,decreasing = TRUE),]
chutes.bct
introducao as equacoes diferenciais ordinarias                     fenomenos eletromagneticos 
                                           355                                            255 
    introducao a probabilidade e a estatistica       bases epistemologicas da ciencia moderna 
                                           210                                            187 
                             bases matematicas              interacoes atomicas e moleculares 
                                           179                                             59 
                   estrutura e dinamica social                ciencia, tecnologia e sociedade 
                                            46                                             37 
                          estrutura da materia                        transformacoes quimicas 
                                            20                                             18 
                            comunicacao e rede                    funcoes de varias variaveis 
                                            15                                             11 
                   processamento da informacao      bases experimentais das ciencias naturais 
                                             9                                              0 

Total de Chutes no BC&T

sum(data.matrix(chutes.bct))
[1] 1401

BC&H

listadedisciplinas<-t(disciplinas.bch)
chutes.bch <- sapply(listadedisciplinas, contachutes,w=ultimo)
chutes.bch<-unique(data.matrix(chutes.bch))
colnames(chutes.bch) <- c("Chutes")
chutes.bch<-chutes.bch[order(chutes.bch,decreasing = TRUE),]
chutes.bch
                      pensamento economico introducao a probabilidade e a estatistica 
                                       215                                        210 
  bases epistemologicas da ciencia moderna                          bases matematicas 
                                       187                                        179 
        desenvolvimento e sustentabilidade                 estado e relacoes de poder 
                                        79                                         70 
           bases computacionais da ciencia                estrutura e dinamica social 
                                        65                                         46 
           ciencia, tecnologia e sociedade                       estrutura da materia 
                                        37                                         20 
                        pensamento critico 
                                         0 
kable(chutes.bch)


|                                           |   x|
|:------------------------------------------|---:|
|pensamento economico                       | 215|
|introducao a probabilidade e a estatistica | 210|
|bases epistemologicas da ciencia moderna   | 187|
|bases matematicas                          | 179|
|desenvolvimento e sustentabilidade         |  79|
|estado e relacoes de poder                 |  70|
|bases computacionais da ciencia            |  65|
|estrutura e dinamica social                |  46|
|ciencia, tecnologia e sociedade            |  37|
|estrutura da materia                       |  20|
|pensamento critico                         |   0|

Total de Chutes no BC&H

sum(data.matrix(chutes.bch))
[1] 1108

Núcleo Comum da Engenharia

chutes.nucleo <- sapply(t(disciplinas.nucleo), contachutes,w=ultimo)
chutes.nucleo<-unique(data.matrix(chutes.nucleo))
colnames(chutes.nucleo) <- c("Chutes")
chutes.nucleo<-chutes.nucleo[order(chutes.nucleo,decreasing = TRUE),]
chutes.nucleo
             mecanica dos solidos i         principios de administracao                engenharia economica 
                                402                                 370                                 327 
             engenharia unificada i      fundamentos de desenho tecnico metodos experimentais em engenharia 
                                279                                 197                                 157 
          introducao as engenharias      circuitos eletricos e fotonica       materiais e suas propriedades 
                                148                                 140                                 130 
             circuitos eletricos i              fenomenos de transporte            termodinamica aplicada i 
                                105                                  73                                  58 
             mecanica dos fluidos i               circuitos eletricos 2                    calculo numerico 
                                 30                                  28                                   0 

Chutes por Cursos

Disciplinas por Cursos

Abaixo criamos a lista de cursos e uma função que retorna as disciplinas desse curso.

cursos<-unique(rotulos.cursos[,2])
disciplinasw<-data.frame(disciplinas)
rotulos.disciplinas2<-data.frame(disciplinasw[,1], sapply(disciplinasw[,1],func.rotulo))
colnames(rotulos.disciplinas2) <- c("disciplinas","Cursos")
disciplinas.curso<-function(v){rotulos.disciplinas2[grepl(tolower(v),rotulos.disciplinas2[,2]),1,drop=FALSE]}
func.chutes.curso<-function(v){chutes.label[grepl(tolower(v),chutes.label[,3]),2 ,drop=FALSE]}
soma.chutes.curso<-function(v){  if(dim(func.chutes.curso(v))[1]>0){as.numeric(sum(func.chutes.curso(v)))} else {0}}
chutes.cursos<-c()
for (i in 1:length(cursos)) { 
   chutes.cursos[[i]]<-as.numeric(soma.chutes.curso(cursos[i]))
}
matrixd<-data.frame(as.vector(cursos), chutes.cursos)
# matrixd<-transform(matrixd,   chutes.cursos = as.numeric(chutes.cursos))
matrixd<-matrixd[(matrixd[,2]>90),]
matrixd<-matrixd[(matrixd[,1]!=""),]
matrixd<-matrixd[(matrixd[,1]!="descon"),]
matrixd<-matrixd[order(t(matrixd[,2]), decreasing = TRUE),]
colnames(matrixd)<-c("disciplinas","chutes")
kable(matrixd,row.names=FALSE)


|disciplinas | chutes|
|:-----------|------:|
|nucleocomum |   2281|
|BCH         |   1453|
|BCT         |   1356|
|EGEST       |    982|
|EIAR        |    455|
|BCECO       |    391|
|EEN         |    249|
|BCC         |    122|
|LMAT        |    107|
|LQUI        |    107|
|LBIO        |    107|
|LFILO       |    107|
|LFIS        |    107|
|EINFO       |    105|
|EBIOM       |    105|
|EAERO       |    103|

Engenharia de Gestão

chutes.egest <- sapply(t(disciplinas.curso("EGEST")), contachutes,w=ultimo)
chutes.egest<-data.matrix(chutes.egest)
colnames(chutes.egest) <- c("Chutes")
chutes.egest<-chutes.egest[order(chutes.egest,decreasing = TRUE),]
chutes.egest
                                   economia de empresas 
                                                    226 
                                organizacao do trabalho 
                                                    118 
     engenharia economica aplicada a sistemas de gestao 
                                                    103 
                                   pesquisa operacional 
                                                     87 
                       sistemas e processos de producao 
                                                     80 
                                           sistemas cam 
                                                     76 
                                     engenharia laboral 
                                                     67 
                   desenvolvimento integrado do produto 
                                                     62 
                                                 custos 
                                                     58 
                                    gestao de operacoes 
                                                     56 
                                     gerencia de ativos 
                                                     49 
                                         algebra linear 
                                                     36 
                                   inovacao tecnologica 
                                                     35 
                                       sistemas cad/cae 
                                                     30 
                                   engenharia logistica 
                                                     29 
introducao aos processos de fabricacao metal - mecanico 
                                                     20 
                    planejamento e controle da producao 
                                                     12 
             estagio curricular em engenharia de gestao 
                                                      0 
              estatistica aplicada a sistemas de gestao 
                                                      0 
                                  qualidade em sistemas 
                                                      0 
        trabalho de graduacao i em engenharia de gestao 
                                                      0 
        trabalho de graduacao 2 em engenharia de gestao 
                                                      0 
        trabalho de graduacao 3 em engenharia de gestao 
                                                      0 

Série Histórica

A função abaixo contas os chutes em todas as disciplinas em todos os quadrimestres. ## Chutes Vamos construir a tabela com a série histórica em todas as disciplinas. Mas não vamos exibir agora. Ps: a execução do comando demora alguns minutinhos.

arquivos = list.files(path="./dados/chutes/", pattern="*.txt") # Importa os arquivos do diretório
quad=gsub(".txt","",arquivos)
bct=list()
##### Conta os Chutes - Essa função 
for (i in 1:numero.quad) { 
   bct[[i]]<-sapply(t(disciplinas),contachutes, w=readLines(paste("./dados/chutes/",arquivos[i],sep="")))
}
##### Transforma numa matriz
bct2<-data.frame(bct)
bct2<-data.matrix(bct2)
colnames(bct2) <- quad

Vamos exportar esses dados para o arquivo serie.bct.csv

write.csv(bct2, file = "./saidas/serie.bct.csv")

Arquivo série histórica

https://sheet.zoho.com/sheet/view.do?url=http://hostel.ufabc.edu.br/~daniel.miranda/chutes/saidas/serie.bct.csv

Vamos calcular o número total de chutes por quadrimestre.

arquivos = list.files(path="./dados/chutes/", pattern="*.txt") 
quad=gsub(".txt","",arquivos)
x4=list()
for (i in 1:numero.quad) { 
   x4[[i]]=sum(bct[[i]])
}
z4<-data.frame(x4)
z4<-data.matrix(z4)
colnames(z4) <- quad
rownames(z4)<-"chutes"
t(z4)
       chutes
2011.1   3626
2011.2   3333
2011.3   3946
2012.1   5353
2012.2   3882
2012.3   4834
2013.1   4485
2013.2   4176
2013.3   5178
2014.1   6100
2014.2   6514
2014.3   7345
2015.1   8143
2015.2   9123
2015.3  10488
2016.1   8188
2016.2   7281
2016.3   9437
2017.1   8352
2017.2   8970
2017.3   7957
2018.1   7542
2018.2   8497

Vamos fazer um barplot

barplot(z4,main="Total de Chutes por Quadrimestre")

Chutes no BC&T

x=list()
for (i in 1:numero.quad) { 
   x[[i]]=sapply(t(disciplinas.bct),contachutes, w=readLines(paste("./dados/chutes/",arquivos[i],sep="")))
}
z<-data.frame(x)
z<-data.matrix(z)
colnames(z) <- quad
library(knitr)
kable(z) 


|                                               | 2011.1| 2011.2| 2011.3| 2012.1| 2012.2| 2012.3| 2013.1| 2013.2| 2013.3| 2014.1| 2014.2| 2014.3| 2015.1| 2015.2| 2015.3| 2016.1| 2016.2| 2016.3| 2017.1| 2017.2| 2017.3| 2018.1| 2018.2|
|:----------------------------------------------|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|
|bases experimentais das ciencias naturais      |      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|
|estrutura da materia                           |      0|     81|      0|     14|      8|      0|      0|     40|     40|      0|     11|     10|      6|      1|      0|      0|      5|      0|      0|     30|      0|      0|     20|
|bases matematicas                              |     84|     10|      0|     80|      0|      0|      0|      0|      0|     42|     67|     17|      0|     56|     48|      0|    158|     83|     46|     68|     37|    124|    179|
|origem da vida e diversidade dos seres vivos   |      0|     22|      0|     20|     10|     34|      0|      0|     61|      0|     14|      0|     17|      3|      0|      0|      0|      0|      0|      0|      0|      0|      0|
|natureza da informacao                         |      0|      0|    118|      0|      0|      0|     15|      0|      0|     30|      0|      0|      0|      0|      0|     53|      0|      7|      9|      0|      6|     22|      0|
|fenomenos mecanicos                            |     79|      0|    229|      0|      7|      0|     19|      0|     64|     99|      0|      6|    139|      0|      0|     79|      0|      0|    301|      0|    323|      0|      0|
|transformacoes nos seres vivos e ambiente      |      0|      0|     10|      0|      2|      0|     20|      0|      5|      9|      0|      0|      0|      0|      0|      3|      0|      0|      0|      0|      0|      0|      0|
|funcoes de uma variavel                        |      6|     96|     94|      0|      2|      0|      0|      0|     17|    132|     84|      0|    117|    267|     23|    100|      0|    209|     83|      0|    135|     35|      0|
|geometria analitica                            |      0|     80|     95|      0|     24|    129|      0|      0|      0|    123|     68|     61|    123|      0|      0|    143|      0|    148|     79|      0|     59|     66|      0|
|processamento da informacao                    |    243|      0|     60|    210|      0|     38|     25|      3|      0|      0|    216|     77|    115|     27|     55|    180|     25|      0|     56|      0|      0|     81|      9|
|fenomenos termicos                             |    180|      0|      0|    306|      0|    174|    104|     47|      0|    283|     95|      0|    279|      0|    323|    153|      0|    210|    248|      0|      0|    162|      0|
|transformacoes quimicas                        |     96|      0|      4|    163|      0|     40|     70|     13|      0|    315|     43|      0|    141|     16|      0|    247|      9|      0|     40|      1|      0|    188|     18|
|introducao as equacoes diferenciais ordinarias |    111|      0|    127|    110|      0|    300|     94|     22|      0|     20|    177|     66|      0|    161|    303|      0|    227|     19|      0|    148|     33|      0|    355|
|bases epistemologicas da ciencia moderna       |     92|      1|      0|     16|      0|      0|    491|     89|    215|    322|      0|     13|     83|     56|     28|     17|    143|      0|     28|    163|     74|     21|    187|
|comunicacao e rede                             |      0|    134|      0|     98|      0|      0|      0|     26|     50|    138|      0|      0|     41|      2|      0|     68|     90|      0|     83|     24|      0|     26|     15|
|fenomenos eletromagneticos                     |      0|    304|      0|    174|     33|      0|      0|    142|     67|      0|    157|     93|      0|    579|      0|      0|    285|      0|      0|    231|      0|      0|    255|
|transformacoes bioquimicas                     |      0|    551|      0|    185|    178|      0|      0|    483|    126|     51|      0|    113|      2|      0|    274|      0|      0|      0|      0|      0|      0|      0|      0|
|funcoes de varias variaveis                    |      0|    265|      0|     32|      0|      0|     21|      5|     61|    391|    265|    260|    311|    104|      0|    122|     15|      0|     32|    215|      0|    119|     11|
|estrutura e dinamica social                    |     14|    146|      0|     53|      2|      0|      0|     94|     26|     26|     83|     94|     22|    151|     72|     64|     25|    100|     94|    315|     21|     22|     46|
|energia: origem, conversao e uso               |      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|      0|
|fisica quantica                                |      0|     95|    127|      0|     88|     78|      0|      0|    127|     16|      0|     75|     32|      0|    303|     83|      0|     95|     33|      0|    300|     99|      0|
|ciencia, tecnologia e sociedade                |      0|      0|    130|      0|     28|      0|      0|      0|    205|     60|      0|     15|     22|     28|     62|     50|     42|     18|     17|     54|     42|     32|     37|
|introducao a probabilidade e a estatistica     |     10|     83|     30|     40|      0|     39|    109|      0|     43|     76|     99|     79|     31|     24|     52|      0|    246|     16|      0|    135|    141|      0|    210|
|interacoes atomicas e moleculares              |      0|      0|     74|     52|      0|    116|     15|      0|      0|     77|     15|     26|     91|     62|      0|    110|    128|      0|    232|    123|      0|     51|     59|

Chutes Totais no BC&T

Vamos analisar a série histórica de chutes no BC%T

x2=list()
for (i in 1:numero.quad) { 
   x2[[i]]=sum(x[[i]])
}
z31<-data.frame(x2)
colnames(z31) <- quad
rownames(z31)<-"chutes"
z3<-data.matrix(z31)
t(z3)
        chutes
Q2014.1    915
Q2014.2   1868
Q2014.3   1098
Q2015.1   1553
Q2015.2    382
Q2015.3    948
Q2016.1    983
Q2016.2    964
Q2016.3   1107
Q2017.1   2210
Q2017.2   1394
Q2017.3   1005
<NA>      1572
<NA>      1537
<NA>      1543
<NA>      1472
<NA>      1398
<NA>       905
<NA>      1381
<NA>      1507
<NA>      1171
<NA>      1048
<NA>      1401

Barplot

barplot(z3,main="Total de Chutes no BCT por Quadrimestre")

Análise de Chutes por Aluno

###################### Numero de chutes por Aluno
chutesporaluno<-read.csv("./dados/chutes/2018.2.csv")
Ras<-unique(chutesporaluno[1])
Ras<-Ras[!is.na(Ras)]
output4<-margin.table(table(chutesporaluno), 1)
output5<-table(output4)
numero.alunos.chutados<-sum(output5)
barplot(output4,main="Chutes por Aluno")

Vamos ver o número de chutes por aluno:

data_dist <- table(output4)
numero.chutes<-function(v){   if(v==0){numero.alunos.matriculados.2018.1[1]-sum(data_dist)} else { as.numeric(data_dist[v])} }
data_dist2<-t(data.frame(0:8,sapply(0:8,numero.chutes)))
colnames(data_dist2)<-0:8
manipulate(barplot(data_dist2, main="Número de Chutes por Aluno"), x = slider(1,length(data_dist)), y = slider(1, length(data_dist2)))

da<-matrix(data_dist2)

E sua frequência

data_dist4 <- data_dist2/numero.alunos.matriculados.2018.1[1]
manipulate(barplot(data_dist4, main="Percentagem  de Número de Chutes por Aluno"), x = slider(1,length(data_dist)), y = slider(8, length(data_dist)))

Número de Alunos chutado em pelo menos 1 disciplina

sum(data_dist)
[1] 4470

Matrículas Deferida no quadrimestre anterior

deferidasporaluno.2018.1<-read.csv("./dados/chutes/deferidas2018.1.csv")
numero.matriculas.2018.1<-dim(deferidasporaluno.2018.1)
numero.alunos.matriculados.2018.1<-dim(unique(deferidasporaluno.2018.1))
output6<-margin.table(table(deferidasporaluno.2018.1),1)
data_distw <- table(output6)
manipulate(barplot(data_distw[x:y], main="Número de Matrículas Deferidas por Aluno"), x = slider(1,length(data_distw)), y = slider(8, length(data_distw)))

Desvio Padrão

sqrt(var((data_dist)))
[1] 725.2551
slices <- table(output6)
lbls <- 1:7
pie3D(slices,labels=lbls,explode=0.061,
      main="Número de Matrículas Deferida por Aluno")

Algumas Estatísticas Interessantes

Total de alunos que fizeram matrícula no Q1

numero.alunos.matriculados.2018.1[1]
[1] 10158

Total de pedidos de matriculas em disciplina no Q1

numero.matriculas.2018.1[1]
[1] 41317

Média de disciplinas matriculadas por aluno

numero.matriculas.2018.1[1]/numero.alunos.matriculados.2018.1[1]
[1] 4.067435

Percentagem de alunos chutados em alguma disciplina.

percent(sum(data_dist)/numero.alunos.matriculados.2018.1[1])
[1] "44%"

Analise por RA

Vamos começar classificando os RAS por ano

Classifica RAS

# Funçao que retorna os n ultimos caracteres
substrultimos <- function(x, n){
  substr(x, nchar(x)-n+1, nchar(x))}
ano.ingresso.ra<-function(v){
    if( grepl(2018, v)[1]){
      18 }
      else
        {if( grepl(2017, v)[1]){
          17}
      else {
    if(as.numeric(substrultimos(v,2)) <17 &&
        as.numeric(substrultimos(v,2))>6 ){  as.numeric(substrultimos(v,2))} else 0}}}
temponauniversidade<-function(v){18-ano.ingresso.ra(v)}
Ras.ingresso<-data.frame(Ras,sapply(Ras, ano.ingresso.ra))
colnames(Ras.ingresso)<-c("RA", "Ano")

Vamos ver a frequência de chutes por ano de ingresso.

anos<-6:17
listadechutes<-data.frame(output4)
listadechutes<-listadechutes[!is.na(listadechutes[,1]),]
colnames(listadechutes)<-c("RA", "Chutes")
dfa<-merge(listadechutes, Ras.ingresso, by="RA")
df2=data.frame(dfa[3],dfa[2])
addmargins(table(df2))
     Chutes
Ano      1    2    3    4    5    6    7    8   10  Sum
  0      1    2    1    2    1    0    0    0    6   13
  7      0    0    0    0    0    0    0    0    1    1
  8     13    2    1    0    0    0    0    0    1   17
  9     19    2    2    1    0    0    0    0    1   25
  10    41   18    6    5    0    0    0    0    1   71
  11    88   31   23    7    2    3    0    0    0  154
  12   158   91   46   27    8    2    1    0    0  333
  13   210  120   65   32   13    3    2    1    0  446
  14   271  167   96   39   20   12    1    0    0  606
  15   363  247  142   66   33   10    5    2    0  868
  16   404  288  155   91   34   13    4    3    0  992
  17   512  245  104   25    6    0    0    0    0  892
  18    14   11   22    4    1    0    0    0    0   52
  Sum 2094 1224  663  299  118   43   13    6   10 4470
write.csv(addmargins(table(df2)), file="test.csv")

Densidade no Q2 Densidade.

barplot(table(dfa[3]))

slices2<-table(df2$Ano)
pie3D(slices2,labels=6:17,explode=0.1,
      main="Número de Alunos Chutados por Ano")

Chutes por Disciplinas

# Filtrar por disciplina
filtro.disciplina<-function(v){toString(ultimo[grepl(v,ultimo)])}
# filtro.disciplina("principios de administracao")
filtro.disciplina.Ra<-function(v){
 aux<- unique(na.omit(as.numeric(unlist(strsplit(unlist(filtro.disciplina(v)), "[^0-9]+")))))
aux<-aux[as.numeric(aux)>9999]
  aux
}
Ras.ingresso.disciplina<-function(v){data.frame(filtro.disciplina.Ra(v),sapply(filtro.disciplina.Ra(v), ano.ingresso.ra))}

Vamos olhar Princípios de Administração

barplot(table(Ras.ingresso.disciplina("principios de administracao")[2]), main = "Chutes em principios de administracao")

Engenharia Unificada i

barplot(table(Ras.ingresso.disciplina("engenharia unificada i")[2]), main = "engenharia unificada i")

Circuitos Eletricos e Fotonica

Vamos olhar circuitos elétricos e fotônica

barplot(table(Ras.ingresso.disciplina("circuitos eletricos e fotonica")[2]), main = "Chutes em circuitos eletricos e fotonica")

Turno

turno<-function(v,w){length(grep(v,ultimo))}
chutes.turno<-data.frame(c("diurno","noturno"), c(turno("matutino") ,turno("noturno")))
colnames(chutes.turno)<-c("turno", "chutes")
chutes.turno
    turno chutes
1  diurno   2733
2 noturno   5976

Barplot

pie3D(t(chutes.turno[2]),labels=c("diurno","noturno"))

Campus

campus<-function(v){length(grep(v,ultimo))}
chutes.campus<-data.frame(c("SA","SBC"), c(turno("santo andre") ,turno("sao bernardo")))
colnames(chutes.campus)<-c("campus", "chutes")
chutes.campus
  campus chutes
1     SA   4405
2    SBC   4263

Barplot

pie3D(t(chutes.campus[2]),labels=c("SA","SBC"))

São Bernardo Noturno é o Inferno?

Melhorou a situação em SBC a noite neste quadrimestre.

campus<-function(v){length(grep(v,ultimo))}
campus.turno <-function(camp,tur){ length(grep(tur,ultimo[grep(camp,ultimo)]))}
vcampus.turno <- Vectorize(campus.turno, SIMPLIFY = FALSE)
chutes.campus<-data.frame(c("SA -","SBC"), c(turno("noturno (sao bernardo)") ,turno("sao bernardo")))
colnames(chutes.campus)<-c("campus", "chutes")
turnos<-c("matutino","noturno")
campus<-c("santo andre","sao bernardo")
chutes.campus.turno<- outer(turnos, campus, vcampus.turno) 
colnames(chutes.campus.turno)<-campus
rownames(chutes.campus.turno)<-turnos
chutes.campus.turno
         santo andre sao bernardo
matutino 1355        1346        
noturno  3050        2917        

Série Histórica

sa.hist<-function(w){length(grep("santo andre",w))}
sbc.hist<-function(w){length(grep("sao bernardo",w))}
arquivos = list.files(path="./dados/chutes/", pattern="*.txt") # Importa os arquivos do diretório
quad=gsub(".txt","",arquivos)
sa=list()
sbc=list()
##### Conta os Chutes - Essa função já é paralelizada!
for (i in 1:numero.quad) { 
   sa[[i]]<-sa.hist(readLines(paste("./dados/chutes/",arquivos[i],sep="")))
   sbc[[i]]<-sbc.hist(readLines(paste("./dados/chutes/",arquivos[i],sep="")))
}
plot(matrix(t(sa)),type = "o",ylab="SA", main="Chutes em SA")

plot(matrix(t(sbc)),type = "o",ylab="SBC", main="Chutes em SBC")

plot(matrix(t(sa)),type = "o",ylab="SBC", main="Chutes em SA e SBC",col="red",  ylim=c(1, 7100))
points(matrix(t(sbc)),col="green",pch = 19,type = "p")
lines(matrix(t(sbc)),col="green")

Deferidas

Matrículas Deferidas

arquivos2 = list.files(path="./dados/deferidas/", pattern="*.txt") # Importa os arquivos do diretório
quad2=gsub("def","",gsub(".txt","",arquivos2))
filtro.Ra<-function(v){
  aux<-unique(na.omit(unlist(strsplit(unlist(v), "[^0-9]+"))))
 aux<- aux[as.numeric(aux)>99999]
  aux
}
def=c()
for (i in 1:length(arquivos2)) { 
   def[[i]]<-length(filtro.Ra(readLines(paste("./dados/deferidas/",arquivos2[i],sep=""))))
}
vdef<-def
def<-data.frame(def)
rownames(def) <- quad2
barplot(t(as.vector(def)),main="Alunos Matriculados")

def
         def
2013.1  5742
2013.2  7289
2013.3  6924
2014.1  6647
2014.3  7727
2015.1  7676
2015.2  7324
2015.3  9097
2016.1  8752
2016.2  8328
2017.1  9804
2017.2  9069
2017.3 10522
2018.1 10159
plot(vdef,type="o")

Densidade de Chutes

Conta o numero de alunos chutados por quadrimestre

chutados=c()
for (i in 1:length(arquivos)) { 
  chutados[[i]]<-length(filtro.Ra(readLines(paste("./dados/chutes/",arquivos[i],sep=""))))
}
chutados<-data.frame(chutados)
quad=gsub(".txt","",arquivos)
rownames(chutados) <- quad

Modelo de numero de alunos UFABC

### Log fit - be sure to use quotes around the variable names in the call
logdef<-data.frame(1:14,def[1])
colnames(logdef)<-c("quad","chutes")
log.fit <- function( yourdata,dep, ind){
  # Self-starting...
  
  y <- yourdata[, dep]
  x <- yourdata[, ind]
  
  log.ss <- nls(y ~ SSlogis(x, phi1, phi2, phi3))
  
  # C
  C <- summary(log.ss)$coef[1]
  # a
  A <- exp((summary(log.ss)$coef[2]) * (1/summary(log.ss)$coef[3]))
  # k
  K <- (1 / summary(log.ss)$coef[3])
  
  plot(y ~ x, main = "Curva Logistica", xlab=ind, ylab=dep,type="o")
  lines(0:max(x), predict(log.ss, data.frame(x=0:max(x))), col="red")
  
  r1 <- sum((x - mean(x))^2)
  r2 <- sum(residuals(log.ss)^2)
  
  r_sq <- (r1 - r2) / r1
  
  out <- data.frame(cbind(c(C=C, a=A, k=K, R.value=sqrt(r_sq))))
  names(out)[1] <- "Curva Logistica"
  
  return(out)
}
log.fit(logdef,"chutes","quad")
        Curva Logistica
C          2.467767e+04
a          3.111124e+00
k          5.754050e-02
R.value             NaN

Usando a logística temos o seguinte numero de alunos previsto como máximo efetivamente matriculados

  1.245091e+04  
[1] 12450.91

Cancelamentos

arquivos = list.files(path="./dados/cancelamento/", pattern="*.txt") # Importa os arquivos do diretório
cancelamentos=list()
##### Conta os Chutes - Essa função 
for (i in 1:length(arquivos)) { 
cancelamentos[[i]]<-sapply(t(disciplinas),contachutes, w=readLines(paste("./dados/cancelamento/",arquivos[i],sep="")))
}
cancelamentos<-data.frame(cancelamentos)
#cancelamentos <-sort(cancelamentos[which(cancelamentos > 12)],  decreasing = TRUE)
quad=gsub("_",".",gsub("cancelamento_disciplinas_","Q",gsub(".txt","",arquivos)))
cancelamentos<-data.frame(cancelamentos)
colnames(cancelamentos)<-quad
colSums(data.frame(cancelamentos))
Q2014.1 Q2014.2 Q2014.3 Q2015.1 Q2015.2 Q2015.3 Q2016.1 Q2016.2 Q2016.3 Q2017.1 Q2017.2 Q2017.3 
   4432    4979    5296    6178    6515    6888    6450    4344    3230    3545    3380    3178 
 barplot( colSums(data.frame(cancelamentos)),main="Número de Cancelamentos")

Conta o numero de alunos chutados por quadrimestre por curso

Lembramos a distribuição geral da UFABC

barplot(data_dist, main="Número de Chutes por Aluno")

Agora vamos criar funções para contar os chutes por curso:

###################### Numero de chutes por Aluno
chutesporaluno.ultimoq<-data.frame(read.csv("./dados/chutes/2018.2.csv"))
colnames(chutesporaluno.ultimoq)<-c("ra","turma")
Ras<-unique(chutesporaluno.ultimoq[1])
Ras<-Ras[!is.na(Ras)]
output4<-margin.table(table(chutesporaluno.ultimoq), 1)
chutes.alunos.curso.Ra<-function(v){
     chutesporaluno.ultimoq[grep(paste(t(disciplinas.curso(v)),collapse="|"),
                       chutesporaluno.ultimoq$turma),][1]
}
chutes.alunos.curso<-function(v){
    chutesporaluno.ultimoq[grep(paste(t(chutes.alunos.curso.Ra(v)),collapse="|"),
                        chutesporaluno.ultimoq$ra),]
}

Vamos ver alguns casos

Gestão

total<-length(t(table(chutes.alunos.curso("EGEST")[1])))
CHEGEST<-t(table(chutes.alunos.curso("EGEST")[1]))
barplot(table(CHEGEST),main="Número de chutes por Aluno na Gestão")

Economia

total<-length(t(table(chutes.alunos.curso("BCECO")[1])))
CHEBCECO<-t(table(chutes.alunos.curso("BCECO")[1]))
barplot(table(CHEBCECO),main="Número de chutes por Aluno na Economia")

EIAR

total<-length(t(table(chutes.alunos.curso("EIAR")[1])))
CHEGEST<-t(table(chutes.alunos.curso("EIAR")[1]))
barplot(table(CHEGEST),main="Número de chutes por Aluno na EIAR")

Nucleo Comum

total<-length(t(table(chutes.alunos.curso("nucleocomum")[1])))
CHnucleocomum<-t(table(chutes.alunos.curso("nucleocomum")[1]))
barplot(table(CHnucleocomum),main="Número de chutes por Aluno no Núcleo Comum")

BCT

total<-length(t(table(chutes.alunos.curso("bct")[1])))
CHbct<-t(table(chutes.alunos.curso("bct")[1]))
barplot(table(CHbct),main="Número de chutes por Aluno no BC&T")

BCC

total<-length(t(table(chutes.alunos.curso("BCC")[1])))
CHEGEST<-t(table(chutes.alunos.curso("BCC")[1]))
barplot(table(CHEGEST),main="Número de chutes por Aluno no Bach. em Comp.")

Alunos Chutados por Curso

Vamos analisar o numero de alunos chutados em cada curso

chutes.alunos.curso.Ra<-function(v){
     unique(chutesporaluno.ultimoq[grep(paste(t(disciplinas.curso(v)),collapse="|"),
                       chutesporaluno.ultimoq$turma),][1])
}
chutes.alunos.curso2<-function(v){
    unique(chutesporaluno.ultimoq[grep(paste(t(chutes.alunos.curso.Ra(v)),collapse="|"),
                        chutesporaluno.ultimoq$ra),][1])
}
nomes.cursos<-read.csv("./dados/listasdedisciplinas/cursos.csv")
nomes.cursos<-nomes.cursos[1:28,]
alunoschutadosporcurso<-function(v){nrow(chutes.alunos.curso.Ra(v))}
chutes.out<-t(sapply( nomes.cursos,alunoschutadosporcurso))
library(knitr)
colnames(chutes.out)<-nomes.cursos
rownames(chutes.out)<-c( "Alunos chutados em pelo menos 1 disciplina do curso")
as<-chutes.out[,order(-chutes.out[1,])]
kable(as[1:12],col.names="Alunos chutados em pelo menos 1 disciplina do curso")


|            | Alunos chutados em pelo menos 1 disciplina do curso|
|:-----------|---------------------------------------------------:|
|nucleocomum |                                                1655|
|BCT         |                                                1216|
|BCH         |                                                1090|
|EGEST       |                                                 653|
|EIAR        |                                                 469|
|BCECO       |                                                 347|
|EEN         |                                                 261|
|BCC         |                                                 226|
|EAERO       |                                                 192|
|EINFO       |                                                 189|
|LMAT        |                                                 165|
|EBIOM       |                                                 155|
LS0tCnRpdGxlOiAiQ2h1dG9tZXRyaWEgLSBBbsOhbGlzZSBkZSBDaHV0ZXMiCm91dHB1dDoKICBodG1sX25vdGVib29rOiAKICAgIHRoZW1lOiB1bml0ZWQKICAgIHRvYzogeWVzCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIHRvYzogeWVzCi0tLQoKIyBJbnRyb2R1w6fDo28KTWFudGVtb3MgYSBzw6lyaWUgaGlzdMOzcmljYSBkb3MgY2h1dGVzIGVtIGRpc2NpcGxpbmFzIGRhIFVGQUJDLiBBcyAgcGVzc29hcyBtYWlzIGNhcmV0YXMgY2hhbWFtIGlzc28gZGUgbWF0csOtY3VsYXMgaW5kZWZlcmlkYXMgbmEgcHJpbWVpcmEgZmFzZSBkZSBtYXRyw61jdWxhLgoKCgoKIVtMb2dvXShodHRwOi8vaG9zdGVsLnVmYWJjLmVkdS5ici9+ZGFuaWVsLm1pcmFuZGEvY2h1dGVzL2NodXRlcy5wbmcpCgoKCgoKIyBDw7NkaWdvIGZvbnRlIGUgZGFkb3MKCk5vc3NvcyBjw7NkaWdvcyBlIGRhZG9zIHPDo28gb3BlbiBzb3VyY2UuIFVzZW0gZSBhYnVzZW0hCgogW2PDs2RpZ28gZm9udGVdKGNodXRlcy1SLnppcCkKIExpY2Vuw6dhIEdQTHYzCiBbbGljZW7Dp2FdKGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvZ3BsLTMuMC5lbi5odG1sKQogCiMgSW1wb3J0YW5kbyBvcyBEYWRvcwoKVmFtb3MgY29tZcOnYXIgY2FycmVnYW5kbyBhbGd1bnMgcGFjb3Rlcy4gVGFsdmV6IHNlamEgbmVjZXNzw6FyaW8gaW5zdGFsw6EtbG9zLgpgYGB7cn0KIyBTZSBmb3IgbmVjZXNzw6FyaW8gaW50YWxhciBlc3NlcyBwYWNvdGVzCiMgaW5zdGFsbC5wYWNrYWdlcygic3F1YXNoIikKIyBpbnN0YWxsLnBhY2thZ2VzKCJncmlkRXh0cmEiKQojIGluc3RhbGwucGFja2FnZXMoInBsb3RyaXgiKQojIGluc3RhbGwucGFja2FnZXMoYygiZ2dwbG90MiIsIlJDb2xvckJyZXdlciIsInNjYWxlcyIpKQojIGluc3RhbGwucGFja2FnZXMoIm1hbmlwdWxhdGUiKQojIGluc3RhbGwucGFja2FnZXMoInBhcmFsbGVsIikKIyBpbnN0YWxsLnBhY2thZ2VzKCJybWFya2Rvd24iKQojIENhcnJlZ2FuZG8gb3MgUGFjb3RlcyBOZWNlc3PDoXJpb3MKIyBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCmxpYnJhcnkoIGRwbHlyKQpsaWJyYXJ5KHNxdWFzaCk7IGxpYnJhcnkoZ3JpZEV4dHJhKTsgbGlicmFyeShwbG90cml4KQpsaWJyYXJ5KGdncGxvdDIpOyBsaWJyYXJ5KHNjYWxlcyk7IGxpYnJhcnkoZ3JpZCk7IGxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KG1hbmlwdWxhdGUpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShybWFya2Rvd24pCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGdyaWQpCgoKb3B0aW9ucyhrbml0ci50YWJsZS5mb3JtYXQgPSAibWFya2Rvd24iKSAKCiMgUGFjb3RlcyBwYXJhIHBhcmFsZWxpemFyCiMgbGlicmFyeShwYXJhbGxlbCkKIyBudW1lcm8gY29yZXMgKHRvdGFsLTEpICBFc3NlIMOpIG8gbcOheGltbyByYXpvYXZlbAojIG5vX2NvcmVzIDwtIGRldGVjdENvcmVzKCkgLSAxCiMgSW5pY2lhciBvIGNsdXN0ZXIKIyBjbCA8LSBtYWtlQ2x1c3Rlcihub19jb3JlcykKYGBgClZhbW9zIGltcG9ydGFyIG9zIGRhZG9zIGRvcyBhcnF1aXZvcy4gRXNzZXMgYXJxdWl2b3MgZXN0w6NvIG5hIHBhc3RhIGRhZG9zCmBgYHtyfQojIEltcG9ydGEgYXJxdWl2b3MgZGUgRGFkb3MgZGUgRGlzY2lwbGluYQpkaXNjaXBsaW5hcy5iY3Q8LXJlYWQuY3N2KCIuL2RhZG9zL2xpc3Rhc2RlZGlzY2lwbGluYXMvZGlzY2JjdC5jc3YiKQpkaXNjaXBsaW5hcy5iY2g8LXJlYWQuY3N2KCIuL2RhZG9zL2xpc3Rhc2RlZGlzY2lwbGluYXMvZGlzY2JjaC5jc3YiKQpkaXNjaXBsaW5hcy5udWNsZW88LXJlYWQuY3N2KCIuL2RhZG9zL2xpc3Rhc2RlZGlzY2lwbGluYXMvZGlzY251Y2xlby5jc3YiKQpkaXNjaXBsaW5hcy5iY3QubWF0PC1yZWFkLmNzdigiLi9kYWRvcy9saXN0YXNkZWRpc2NpcGxpbmFzL2Rpc2NtYXRiaS5jc3YiKQpkaXNjaXBsaW5hczwtdW5pcXVlKGFzLmRhdGEuZnJhbWUocmVhZC5jc3YoIi4vZGFkb3MvbGlzdGFzZGVkaXNjaXBsaW5hcy9kaXNjaXBsaW5hcy5jc3YiKSkpCnJvdHVsb3MuY3Vyc29zPC1kaXNjaXBsaW5hcwpkaXNjaXBsaW5hczwtdW5pcXVlKGRpc2NpcGxpbmFzWzFdKQoKIyBJbXBvcnRhIGFycXVpdm9zIGNvbSBEYWRvcyBkZSBDaHV0ZXMKY2h1dGVzLjIwMTEuMTwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDExLjEudHh0IikKY2h1dGVzLjIwMTEuMjwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDExLjIudHh0IikKY2h1dGVzLjIwMTEuMzwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDExLjMudHh0IikKY2h1dGVzLjIwMTIuMTwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDEyLjEudHh0IikKY2h1dGVzLjIwMTIuMjwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDEyLjIudHh0IikKY2h1dGVzLjIwMTIuMzwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDEyLjMudHh0IikKY2h1dGVzLjIwMTMuMTwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDEzLjEudHh0IikKY2h1dGVzLjIwMTMuMjwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDEzLjIudHh0IikKY2h1dGVzLjIwMTMuMzwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDEzLjMudHh0IikKY2h1dGVzLjIwMTQuMTwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE0LjEudHh0IikKY2h1dGVzLjIwMTQuMjwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE0LjIudHh0IikKY2h1dGVzLjIwMTQuMzwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE0LjMudHh0IikKY2h1dGVzLjIwMTUuMTwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE1LjEudHh0IikKY2h1dGVzLjIwMTUuMjwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE1LjIudHh0IikKY2h1dGVzLjIwMTUuMzwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE1LjMudHh0IikKY2h1dGVzLjIwMTYuMTwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE2LjEudHh0IikKY2h1dGVzLjIwMTYuMjwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE2LjIudHh0IikKY2h1dGVzLjIwMTYuMzwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE2LjMudHh0IikKY2h1dGVzLjIwMTcuMTwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE3LjEudHh0IikKY2h1dGVzLjIwMTcuMjwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE3LjIudHh0IikKY2h1dGVzLjIwMTcuMzwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE3LjMudHh0IikKY2h1dGVzLjIwMTguMTwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE4LjEudHh0IikKY2h1dGVzLjIwMTguMjwtcmVhZExpbmVzKCIuL2RhZG9zL2NodXRlcy8yMDE4LjIudHh0IikKCnVsdGltbz1jaHV0ZXMuMjAxOC4yCnF1YWwucXVhZD0yMDE4LjIKbnVtZXJvLnF1YWQ9MjMKCmBgYApBIGZ1bsOnw6NvIGEgc2VndWlyIMOpIGEgZnVuw6fDo28gbWFpcyBpbXBvcnRhbnRlISBFbGEgY29udGEgYSBvY29ycsOqbmNpYSBkZSB1bWEgc3RyaW5nIG51bSBhcnF1aXZvLiDDiSBjb20gZWxhIHF1ZSBjb250YXJlbW9zIG9zIGNodXRlcyBub3MgYXJxdWl2b3MgZGUgY2h1dGVzCmBgYHtyfQojIENvbnRhIGNodXRlcwpjb250YWNodXRlczwtZnVuY3Rpb24odix3KXtsZW5ndGgoZ3JlcCh2LHcpKX0KYGBgClZhbW9zIGNvbG9jYXIgcsOzdHVsb3MgbmFzIGRpc2NpcGxpbmFzCmBgYHtyfQpmdW5jLnJvdHVsbzwtZnVuY3Rpb24odil7CiAgICAgaWYodiAlaW4lIHQoZGlzY2lwbGluYXMubnVjbGVvKSkKICB7ICJudWNsZW9jb211bSJ9IGVsc2Ugewp0b2xvd2VyKHBhc3RlKHQocm90dWxvcy5jdXJzb3Nbcm90dWxvcy5jdXJzb3NbLDFdID09diwyLGRyb3A9RkFMU0VdKSxjb2xsYXBzZT0iICIpKX19CnJvdHVsb3MuZGlzY2lwbGluYXM8LXNhcHBseSh0KGRpc2NpcGxpbmFzWzFdKSxmdW5jLnJvdHVsbykKcm90dWxvcy5kaXNjaXBsaW5hczwtZGF0YS5tYXRyaXgocm90dWxvcy5kaXNjaXBsaW5hcykKY29sbmFtZXMocm90dWxvcy5kaXNjaXBsaW5hcykgPC0gYygiQ3Vyc29zIikKYGBgCiMgQ2h1dGVzIGRvIMOabHRpbW8gUXVhZHJpbWVzdHJlClZhbW9zIGNvbnRhciBvcyBjaHV0ZXMgZW0gdG9kYXMgYXMgZGlzY2lwbGluYXMgbm8gdWx0aW1vIHF1YWRyaW1lc3RyZS4gKGZpbHRyYXIgcGFyYSBtb3N0cmFyIGFwZW5hcyBhcyBjb20gbWFpcyBkZSA1MCBjaHV0ZXMgZSBvcmRlbmFyLikKCgoKCmBgYHtyfQojIEJvYSBwYXJ0ZSBkbyBxdWUgZmFyZW1vcyBjb25zaXN0ZSBlbSBhcGxpY2FyIHVtYSBmdW7Dp8OjbyBudW1hIGxpc3RhIGNvbSBzYXBwbHkKY2h1dGVzIDwtc2FwcGx5KHQoZGlzY2lwbGluYXMpLGNvbnRhY2h1dGVzLCB3PXVsdGltbykKY2h1dGVzIDwtc29ydChjaHV0ZXNbd2hpY2goY2h1dGVzID4gNDApXSwgIGRlY3JlYXNpbmcgPSBUUlVFKQpjaHV0ZXM8LWRhdGEubWF0cml4KGNodXRlcykKY29sbmFtZXMoY2h1dGVzKSA8LSBjKCJDaHV0ZXMiKQpgYGAKVmFtb3MgdmVyIGFzIGRpc2NpcGxpbmFzIGNvbSBtYWlzIGNodXRlcwpgYGB7cn0KY2h1dGVzLmxhYmVsPC1tZXJnZShjaHV0ZXMscm90dWxvcy5kaXNjaXBsaW5hcywgYnkgPSAicm93Lm5hbWVzIikKY2h1dGVzLmxhYmVsPWNodXRlcy5sYWJlbFtvcmRlcihjaHV0ZXMubGFiZWxbLDJdLGRlY3JlYXNpbmcgPSBUUlVFKSxdCmthYmxlKGNodXRlcy5sYWJlbCkKYGBgClZhbW9zIGNvbG9jYXIgZXNzZXMgZGFkb3MgbnVtICBCYXJwbG90IGLDoXNpY286CmBgYHtyfQpiYXJwbG90KHQoY2h1dGVzKSwyMCxtYWluPSJDaHV0ZXMgcG9yIERpc2NpcGxpbmEiKQpgYGAKVmFtb3MgYW5hbGlzYXIgYWxndW5zIGdydXBvcyBkZSBkaXNjaXBsaW5hcyBlbSBlc3BlY2lhbC4gQ29tZcOnYXJlbW9zIHBlbG8gQkMmVAoKIyBCQyZUCmBgYHtyfQpsaXN0YWRlZGlzY2lwbGluYXM8LXQoZGlzY2lwbGluYXMuYmN0KQpjaHV0ZXMuYmN0IDwtIHNhcHBseShsaXN0YWRlZGlzY2lwbGluYXMsIGNvbnRhY2h1dGVzLHc9dWx0aW1vKQpjaHV0ZXMuYmN0PC11bmlxdWUoZGF0YS5tYXRyaXgoY2h1dGVzLmJjdCkpCmNvbG5hbWVzKGNodXRlcy5iY3QpIDwtIGMoIkNodXRlcyIpCmNodXRlcy5iY3Q8LWNodXRlcy5iY3Rbb3JkZXIoY2h1dGVzLmJjdCxkZWNyZWFzaW5nID0gVFJVRSksXQpjaHV0ZXMuYmN0CmBgYApUb3RhbCBkZSBDaHV0ZXMgbm8gQkMmVApgYGB7cn0Kc3VtKGRhdGEubWF0cml4KGNodXRlcy5iY3QpKQpgYGAKIyMgQkMmSApgYGB7cn0KbGlzdGFkZWRpc2NpcGxpbmFzPC10KGRpc2NpcGxpbmFzLmJjaCkKY2h1dGVzLmJjaCA8LSBzYXBwbHkobGlzdGFkZWRpc2NpcGxpbmFzLCBjb250YWNodXRlcyx3PXVsdGltbykKY2h1dGVzLmJjaDwtdW5pcXVlKGRhdGEubWF0cml4KGNodXRlcy5iY2gpKQpjb2xuYW1lcyhjaHV0ZXMuYmNoKSA8LSBjKCJDaHV0ZXMiKQpjaHV0ZXMuYmNoPC1jaHV0ZXMuYmNoW29yZGVyKGNodXRlcy5iY2gsZGVjcmVhc2luZyA9IFRSVUUpLF0KY2h1dGVzLmJjaAprYWJsZShjaHV0ZXMuYmNoKQpgYGAKVG90YWwgZGUgQ2h1dGVzIG5vIEJDJkgKYGBge3J9CnN1bShkYXRhLm1hdHJpeChjaHV0ZXMuYmNoKSkKYGBgCiMjIE7DumNsZW8gQ29tdW0gZGEgRW5nZW5oYXJpYQpgYGB7cn0KY2h1dGVzLm51Y2xlbyA8LSBzYXBwbHkodChkaXNjaXBsaW5hcy5udWNsZW8pLCBjb250YWNodXRlcyx3PXVsdGltbykKY2h1dGVzLm51Y2xlbzwtdW5pcXVlKGRhdGEubWF0cml4KGNodXRlcy5udWNsZW8pKQpjb2xuYW1lcyhjaHV0ZXMubnVjbGVvKSA8LSBjKCJDaHV0ZXMiKQpjaHV0ZXMubnVjbGVvPC1jaHV0ZXMubnVjbGVvW29yZGVyKGNodXRlcy5udWNsZW8sZGVjcmVhc2luZyA9IFRSVUUpLF0KY2h1dGVzLm51Y2xlbwpgYGAKCgojIyBDaHV0ZXMgcG9yIEN1cnNvcwojIyMgRGlzY2lwbGluYXMgcG9yIEN1cnNvcwoKQWJhaXhvIGNyaWFtb3MgYSBsaXN0YSBkZSBjdXJzb3MgZSB1bWEgZnVuw6fDo28gcXVlIHJldG9ybmEgYXMgZGlzY2lwbGluYXMgZGVzc2UgY3Vyc28uCmBgYHtyfQpjdXJzb3M8LXVuaXF1ZShyb3R1bG9zLmN1cnNvc1ssMl0pCmRpc2NpcGxpbmFzdzwtZGF0YS5mcmFtZShkaXNjaXBsaW5hcykKcm90dWxvcy5kaXNjaXBsaW5hczI8LWRhdGEuZnJhbWUoZGlzY2lwbGluYXN3WywxXSwgc2FwcGx5KGRpc2NpcGxpbmFzd1ssMV0sZnVuYy5yb3R1bG8pKQpjb2xuYW1lcyhyb3R1bG9zLmRpc2NpcGxpbmFzMikgPC0gYygiZGlzY2lwbGluYXMiLCJDdXJzb3MiKQpkaXNjaXBsaW5hcy5jdXJzbzwtZnVuY3Rpb24odil7cm90dWxvcy5kaXNjaXBsaW5hczJbZ3JlcGwodG9sb3dlcih2KSxyb3R1bG9zLmRpc2NpcGxpbmFzMlssMl0pLDEsZHJvcD1GQUxTRV19CmZ1bmMuY2h1dGVzLmN1cnNvPC1mdW5jdGlvbih2KXtjaHV0ZXMubGFiZWxbZ3JlcGwodG9sb3dlcih2KSxjaHV0ZXMubGFiZWxbLDNdKSwyICxkcm9wPUZBTFNFXX0Kc29tYS5jaHV0ZXMuY3Vyc288LWZ1bmN0aW9uKHYpeyAgaWYoZGltKGZ1bmMuY2h1dGVzLmN1cnNvKHYpKVsxXT4wKXthcy5udW1lcmljKHN1bShmdW5jLmNodXRlcy5jdXJzbyh2KSkpfSBlbHNlIHswfX0KCmNodXRlcy5jdXJzb3M8LWMoKQpmb3IgKGkgaW4gMTpsZW5ndGgoY3Vyc29zKSkgeyAKICAgY2h1dGVzLmN1cnNvc1tbaV1dPC1hcy5udW1lcmljKHNvbWEuY2h1dGVzLmN1cnNvKGN1cnNvc1tpXSkpCn0KbWF0cml4ZDwtZGF0YS5mcmFtZShhcy52ZWN0b3IoY3Vyc29zKSwgY2h1dGVzLmN1cnNvcykKIyBtYXRyaXhkPC10cmFuc2Zvcm0obWF0cml4ZCwgICBjaHV0ZXMuY3Vyc29zID0gYXMubnVtZXJpYyhjaHV0ZXMuY3Vyc29zKSkKCm1hdHJpeGQ8LW1hdHJpeGRbKG1hdHJpeGRbLDJdPjkwKSxdCm1hdHJpeGQ8LW1hdHJpeGRbKG1hdHJpeGRbLDFdIT0iIiksXQptYXRyaXhkPC1tYXRyaXhkWyhtYXRyaXhkWywxXSE9ImRlc2NvbiIpLF0KCm1hdHJpeGQ8LW1hdHJpeGRbb3JkZXIodChtYXRyaXhkWywyXSksIGRlY3JlYXNpbmcgPSBUUlVFKSxdCmNvbG5hbWVzKG1hdHJpeGQpPC1jKCJkaXNjaXBsaW5hcyIsImNodXRlcyIpCmthYmxlKG1hdHJpeGQscm93Lm5hbWVzPUZBTFNFKQpgYGAKIyMgRW5nZW5oYXJpYSBkZSAgR2VzdMOjbwoKYGBge3J9CgoKY2h1dGVzLmVnZXN0IDwtIHNhcHBseSh0KGRpc2NpcGxpbmFzLmN1cnNvKCJFR0VTVCIpKSwgY29udGFjaHV0ZXMsdz11bHRpbW8pCmNodXRlcy5lZ2VzdDwtZGF0YS5tYXRyaXgoY2h1dGVzLmVnZXN0KQoKY29sbmFtZXMoY2h1dGVzLmVnZXN0KSA8LSBjKCJDaHV0ZXMiKQpjaHV0ZXMuZWdlc3Q8LWNodXRlcy5lZ2VzdFtvcmRlcihjaHV0ZXMuZWdlc3QsZGVjcmVhc2luZyA9IFRSVUUpLF0KCmNodXRlcy5lZ2VzdApgYGAKCgoKIyBTw6lyaWUgSGlzdMOzcmljYQpBIGZ1bsOnw6NvIGFiYWl4byBjb250YXMgb3MgIGNodXRlcyBlbSB0b2RhcyBhcyBkaXNjaXBsaW5hcyBlbSB0b2RvcyBvcyBxdWFkcmltZXN0cmVzLgojIyBDaHV0ZXMgClZhbW9zIGNvbnN0cnVpciBhIHRhYmVsYSBjb20gYSBzw6lyaWUgaGlzdMOzcmljYSBlbSB0b2RhcyBhcyBkaXNjaXBsaW5hcy4gTWFzIG7Do28gdmFtb3MgZXhpYmlyIGFnb3JhLgpQczogYSBleGVjdcOnw6NvIGRvIGNvbWFuZG8gZGVtb3JhIGFsZ3VucyBtaW51dGluaG9zLgpgYGB7cn0KYXJxdWl2b3MgPSBsaXN0LmZpbGVzKHBhdGg9Ii4vZGFkb3MvY2h1dGVzLyIsIHBhdHRlcm49IioudHh0IikgIyBJbXBvcnRhIG9zIGFycXVpdm9zIGRvIGRpcmV0w7NyaW8KcXVhZD1nc3ViKCIudHh0IiwiIixhcnF1aXZvcykKYmN0PWxpc3QoKQojIyMjIyBDb250YSBvcyBDaHV0ZXMgLSBFc3NhIGZ1bsOnw6NvIApmb3IgKGkgaW4gMTpudW1lcm8ucXVhZCkgeyAKICAgYmN0W1tpXV08LXNhcHBseSh0KGRpc2NpcGxpbmFzKSxjb250YWNodXRlcywgdz1yZWFkTGluZXMocGFzdGUoIi4vZGFkb3MvY2h1dGVzLyIsYXJxdWl2b3NbaV0sc2VwPSIiKSkpCn0KCmBgYAoKCmBgYHtyfQojIyMjIyBUcmFuc2Zvcm1hIG51bWEgbWF0cml6CmJjdDI8LWRhdGEuZnJhbWUoYmN0KQpiY3QyPC1kYXRhLm1hdHJpeChiY3QyKQpjb2xuYW1lcyhiY3QyKSA8LSBxdWFkCmBgYAoKVmFtb3MgZXhwb3J0YXIgZXNzZXMgZGFkb3MgcGFyYSBvIGFycXVpdm8gIHNlcmllLmJjdC5jc3YKYGBge3J9CndyaXRlLmNzdihiY3QyLCBmaWxlID0gIi4vc2FpZGFzL3NlcmllLmJjdC5jc3YiKQpgYGAKKipBcnF1aXZvIHPDqXJpZSBoaXN0w7NyaWNhKioKCltodHRwczovL3NoZWV0LnpvaG8uY29tL3NoZWV0L3ZpZXcuZG8/dXJsPWh0dHA6Ly9ob3N0ZWwudWZhYmMuZWR1LmJyL35kYW5pZWwubWlyYW5kYS9jaHV0ZXMvc2FpZGFzL3NlcmllLmJjdC5jc3ZdKGh0dHBzOi8vc2hlZXQuem9oby5jb20vc2hlZXQvdmlldy5kbz91cmw9aHR0cDovL2hvc3RlbC51ZmFiYy5lZHUuYnIvfmRhbmllbC5taXJhbmRhL2NodXRlcy9zYWlkYXMvc2VyaWUuYmN0LmNzdikKCgpWYW1vcyBjYWxjdWxhciBvIG7Dum1lcm8gdG90YWwgZGUgY2h1dGVzIHBvciBxdWFkcmltZXN0cmUuCmBgYHtyfQphcnF1aXZvcyA9IGxpc3QuZmlsZXMocGF0aD0iLi9kYWRvcy9jaHV0ZXMvIiwgcGF0dGVybj0iKi50eHQiKSAKcXVhZD1nc3ViKCIudHh0IiwiIixhcnF1aXZvcykKCng0PWxpc3QoKQpmb3IgKGkgaW4gMTpudW1lcm8ucXVhZCkgeyAKICAgeDRbW2ldXT1zdW0oYmN0W1tpXV0pCn0KejQ8LWRhdGEuZnJhbWUoeDQpCno0PC1kYXRhLm1hdHJpeCh6NCkKY29sbmFtZXMoejQpIDwtIHF1YWQKcm93bmFtZXMoejQpPC0iY2h1dGVzIgp0KHo0KQpgYGAKClZhbW9zIGZhemVyIHVtIGJhcnBsb3QKYGBge3J9CmJhcnBsb3QoejQsbWFpbj0iVG90YWwgZGUgQ2h1dGVzIHBvciBRdWFkcmltZXN0cmUiKQpgYGAKIyMgQ2h1dGVzIG5vIEJDJlQgCmBgYHtyfQp4PWxpc3QoKQpmb3IgKGkgaW4gMTpudW1lcm8ucXVhZCkgeyAKICAgeFtbaV1dPXNhcHBseSh0KGRpc2NpcGxpbmFzLmJjdCksY29udGFjaHV0ZXMsIHc9cmVhZExpbmVzKHBhc3RlKCIuL2RhZG9zL2NodXRlcy8iLGFycXVpdm9zW2ldLHNlcD0iIikpKQp9Cno8LWRhdGEuZnJhbWUoeCkKejwtZGF0YS5tYXRyaXgoeikKY29sbmFtZXMoeikgPC0gcXVhZApsaWJyYXJ5KGtuaXRyKQprYWJsZSh6KSAKYGBgCgojIyBDaHV0ZXMgVG90YWlzIG5vIEJDJlQKVmFtb3MgYW5hbGlzYXIgYSBzw6lyaWUgaGlzdMOzcmljYSBkZSBjaHV0ZXMgbm8gQkMlVApgYGB7cn0KeDI9bGlzdCgpCmZvciAoaSBpbiAxOm51bWVyby5xdWFkKSB7IAogICB4MltbaV1dPXN1bSh4W1tpXV0pCn0KejMxPC1kYXRhLmZyYW1lKHgyKQpjb2xuYW1lcyh6MzEpIDwtIHF1YWQKcm93bmFtZXMoejMxKTwtImNodXRlcyIKejM8LWRhdGEubWF0cml4KHozMSkKdCh6MykKYGBgCkJhcnBsb3QKYGBge3J9CmJhcnBsb3QoejMsbWFpbj0iVG90YWwgZGUgQ2h1dGVzIG5vIEJDVCBwb3IgUXVhZHJpbWVzdHJlIikKYGBgCgoKIyBBbsOhbGlzZSBkZSBDaHV0ZXMgcG9yIEFsdW5vCmBgYHtyfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIE51bWVybyBkZSBjaHV0ZXMgcG9yIEFsdW5vCmNodXRlc3BvcmFsdW5vPC1yZWFkLmNzdigiLi9kYWRvcy9jaHV0ZXMvMjAxOC4yLmNzdiIpClJhczwtdW5pcXVlKGNodXRlc3BvcmFsdW5vWzFdKQpSYXM8LVJhc1shaXMubmEoUmFzKV0Kb3V0cHV0NDwtbWFyZ2luLnRhYmxlKHRhYmxlKGNodXRlc3BvcmFsdW5vKSwgMSkKb3V0cHV0NTwtdGFibGUob3V0cHV0NCkKbnVtZXJvLmFsdW5vcy5jaHV0YWRvczwtc3VtKG91dHB1dDUpCmJhcnBsb3Qob3V0cHV0NCxtYWluPSJDaHV0ZXMgcG9yIEFsdW5vIikKYGBgClZhbW9zIHZlciBvIG7Dum1lcm8gZGUgY2h1dGVzIHBvciBhbHVubzoKYGBge3J9CmRhdGFfZGlzdCA8LSB0YWJsZShvdXRwdXQ0KQpudW1lcm8uY2h1dGVzPC1mdW5jdGlvbih2KXsgICBpZih2PT0wKXtudW1lcm8uYWx1bm9zLm1hdHJpY3VsYWRvcy4yMDE4LjFbMV0tc3VtKGRhdGFfZGlzdCl9IGVsc2UgeyBhcy5udW1lcmljKGRhdGFfZGlzdFt2XSl9IH0KZGF0YV9kaXN0MjwtdChkYXRhLmZyYW1lKDA6OCxzYXBwbHkoMDo4LG51bWVyby5jaHV0ZXMpKSkKY29sbmFtZXMoZGF0YV9kaXN0Mik8LTA6OAptYW5pcHVsYXRlKGJhcnBsb3QoZGF0YV9kaXN0MiwgbWFpbj0iTsO6bWVybyBkZSBDaHV0ZXMgcG9yIEFsdW5vIiksIHggPSBzbGlkZXIoMSxsZW5ndGgoZGF0YV9kaXN0KSksIHkgPSBzbGlkZXIoMSwgbGVuZ3RoKGRhdGFfZGlzdDIpKSkKZGE8LW1hdHJpeChkYXRhX2Rpc3QyKQpgYGAKRSBzdWEgZnJlcXXDqm5jaWEKYGBge3J9CmRhdGFfZGlzdDQgPC0gZGF0YV9kaXN0Mi9udW1lcm8uYWx1bm9zLm1hdHJpY3VsYWRvcy4yMDE4LjFbMV0KbWFuaXB1bGF0ZShiYXJwbG90KGRhdGFfZGlzdDQsIG1haW49IlBlcmNlbnRhZ2VtICBkZSBOw7ptZXJvIGRlIENodXRlcyBwb3IgQWx1bm8iKSwgeCA9IHNsaWRlcigxLGxlbmd0aChkYXRhX2Rpc3QpKSwgeSA9IHNsaWRlcig4LCBsZW5ndGgoZGF0YV9kaXN0KSkpCmBgYAoKCiMgTsO6bWVybyBkZSBBbHVub3MgY2h1dGFkbyBlbSBwZWxvIG1lbm9zIDEgZGlzY2lwbGluYQpgYGB7cn0Kc3VtKGRhdGFfZGlzdCkKYGBgCgoKCiMgTWF0csOtY3VsYXMgRGVmZXJpZGEgbm8gcXVhZHJpbWVzdHJlIGFudGVyaW9yCmBgYHtyfQpkZWZlcmlkYXNwb3JhbHVuby4yMDE4LjE8LXJlYWQuY3N2KCIuL2RhZG9zL2NodXRlcy9kZWZlcmlkYXMyMDE4LjEuY3N2IikKbnVtZXJvLm1hdHJpY3VsYXMuMjAxOC4xPC1kaW0oZGVmZXJpZGFzcG9yYWx1bm8uMjAxOC4xKQpudW1lcm8uYWx1bm9zLm1hdHJpY3VsYWRvcy4yMDE4LjE8LWRpbSh1bmlxdWUoZGVmZXJpZGFzcG9yYWx1bm8uMjAxOC4xKSkKb3V0cHV0NjwtbWFyZ2luLnRhYmxlKHRhYmxlKGRlZmVyaWRhc3BvcmFsdW5vLjIwMTguMSksMSkKZGF0YV9kaXN0dyA8LSB0YWJsZShvdXRwdXQ2KQptYW5pcHVsYXRlKGJhcnBsb3QoZGF0YV9kaXN0d1t4OnldLCBtYWluPSJOw7ptZXJvIGRlIE1hdHLDrWN1bGFzIERlZmVyaWRhcyBwb3IgQWx1bm8iKSwgeCA9IHNsaWRlcigxLGxlbmd0aChkYXRhX2Rpc3R3KSksIHkgPSBzbGlkZXIoOCwgbGVuZ3RoKGRhdGFfZGlzdHcpKSkKYGBgCgojIyMjIERlc3ZpbyBQYWRyw6NvCmBgYHtyfQpzcXJ0KHZhcigoZGF0YV9kaXN0KSkpCgpgYGAKCgoKYGBge3J9CnNsaWNlcyA8LSB0YWJsZShvdXRwdXQ2KQpsYmxzIDwtIDE6NwpwaWUzRChzbGljZXMsbGFiZWxzPWxibHMsZXhwbG9kZT0wLjA2MSwKICAgICAgbWFpbj0iTsO6bWVybyBkZSBNYXRyw61jdWxhcyBEZWZlcmlkYSBwb3IgQWx1bm8iKQpgYGAKIyMgQWxndW1hcyBFc3RhdMOtc3RpY2FzIEludGVyZXNzYW50ZXMKVG90YWwgZGUgYWx1bm9zIHF1ZSBmaXplcmFtIG1hdHLDrWN1bGEgbm8gUTEKYGBge3J9Cm51bWVyby5hbHVub3MubWF0cmljdWxhZG9zLjIwMTguMVsxXQpgYGAKVG90YWwgZGUgcGVkaWRvcyBkZSBtYXRyaWN1bGFzIGVtIGRpc2NpcGxpbmEgIG5vIFExCmBgYHtyfQpudW1lcm8ubWF0cmljdWxhcy4yMDE4LjFbMV0KYGBgCgpNw6lkaWEgZGUgZGlzY2lwbGluYXMgbWF0cmljdWxhZGFzIHBvciBhbHVubwoKYGBge3J9Cm51bWVyby5tYXRyaWN1bGFzLjIwMTguMVsxXS9udW1lcm8uYWx1bm9zLm1hdHJpY3VsYWRvcy4yMDE4LjFbMV0KYGBgCgoKUGVyY2VudGFnZW0gZGUgYWx1bm9zIGNodXRhZG9zIGVtIGFsZ3VtYSBkaXNjaXBsaW5hLgpgYGB7cn0KcGVyY2VudChzdW0oZGF0YV9kaXN0KS9udW1lcm8uYWx1bm9zLm1hdHJpY3VsYWRvcy4yMDE4LjFbMV0pCgpgYGAKIyBBbmFsaXNlIHBvciBSQQpWYW1vcyBjb21lw6dhciBjbGFzc2lmaWNhbmRvIG9zIFJBUyBwb3IgYW5vCgoKCiMjIENsYXNzaWZpY2EgUkFTCmBgYHtyfQojIEZ1bsOnYW8gcXVlIHJldG9ybmEgb3MgbiB1bHRpbW9zIGNhcmFjdGVyZXMKc3Vic3RydWx0aW1vcyA8LSBmdW5jdGlvbih4LCBuKXsKICBzdWJzdHIoeCwgbmNoYXIoeCktbisxLCBuY2hhcih4KSl9CmFuby5pbmdyZXNzby5yYTwtZnVuY3Rpb24odil7CiAgICBpZiggZ3JlcGwoMjAxOCwgdilbMV0pewogICAgICAxOCB9CiAgICAgIGVsc2UKICAgICAgICB7aWYoIGdyZXBsKDIwMTcsIHYpWzFdKXsKICAgICAgICAgIDE3fQogICAgICBlbHNlIHsKICAgIGlmKGFzLm51bWVyaWMoc3Vic3RydWx0aW1vcyh2LDIpKSA8MTcgJiYKICAgICAgICBhcy5udW1lcmljKHN1YnN0cnVsdGltb3ModiwyKSk+NiApeyAgYXMubnVtZXJpYyhzdWJzdHJ1bHRpbW9zKHYsMikpfSBlbHNlIDB9fX0KdGVtcG9uYXVuaXZlcnNpZGFkZTwtZnVuY3Rpb24odil7MTgtYW5vLmluZ3Jlc3NvLnJhKHYpfQpSYXMuaW5ncmVzc288LWRhdGEuZnJhbWUoUmFzLHNhcHBseShSYXMsIGFuby5pbmdyZXNzby5yYSkpCmNvbG5hbWVzKFJhcy5pbmdyZXNzbyk8LWMoIlJBIiwgIkFubyIpCmBgYApWYW1vcyB2ZXIgYSBmcmVxdcOqbmNpYSBkZSBjaHV0ZXMgcG9yIGFubyBkZSBpbmdyZXNzby4KYGBge3J9CmFub3M8LTY6MTcKbGlzdGFkZWNodXRlczwtZGF0YS5mcmFtZShvdXRwdXQ0KQpsaXN0YWRlY2h1dGVzPC1saXN0YWRlY2h1dGVzWyFpcy5uYShsaXN0YWRlY2h1dGVzWywxXSksXQpjb2xuYW1lcyhsaXN0YWRlY2h1dGVzKTwtYygiUkEiLCAiQ2h1dGVzIikKZGZhPC1tZXJnZShsaXN0YWRlY2h1dGVzLCBSYXMuaW5ncmVzc28sIGJ5PSJSQSIpCmRmMj1kYXRhLmZyYW1lKGRmYVszXSxkZmFbMl0pCmFkZG1hcmdpbnModGFibGUoZGYyKSkKd3JpdGUuY3N2KGFkZG1hcmdpbnModGFibGUoZGYyKSksIGZpbGU9InRlc3QuY3N2IikKYGBgCkRlbnNpZGFkZSBubyBRMgohW0RlbnNpZGFkZS5dKC4vc2FpZGFzL2ZyZXF1ZW5jaWFzZGVjaHV0ZXNwb3Jhbm8ucG5nKQpgYGB7cn0KYmFycGxvdCh0YWJsZShkZmFbM10pKQpgYGAKCgpgYGB7cn0Kc2xpY2VzMjwtdGFibGUoZGYyJEFubykKcGllM0Qoc2xpY2VzMixsYWJlbHM9NjoxNyxleHBsb2RlPTAuMSwKICAgICAgbWFpbj0iTsO6bWVybyBkZSBBbHVub3MgQ2h1dGFkb3MgcG9yIEFubyIpCmBgYAoKIyMgQ2h1dGVzIHBvciBEaXNjaXBsaW5hcwpgYGB7cn0KIyBGaWx0cmFyIHBvciBkaXNjaXBsaW5hCmZpbHRyby5kaXNjaXBsaW5hPC1mdW5jdGlvbih2KXt0b1N0cmluZyh1bHRpbW9bZ3JlcGwodix1bHRpbW8pXSl9CiMgZmlsdHJvLmRpc2NpcGxpbmEoInByaW5jaXBpb3MgZGUgYWRtaW5pc3RyYWNhbyIpCmZpbHRyby5kaXNjaXBsaW5hLlJhPC1mdW5jdGlvbih2KXsKIGF1eDwtIHVuaXF1ZShuYS5vbWl0KGFzLm51bWVyaWModW5saXN0KHN0cnNwbGl0KHVubGlzdChmaWx0cm8uZGlzY2lwbGluYSh2KSksICJbXjAtOV0rIikpKSkpCmF1eDwtYXV4W2FzLm51bWVyaWMoYXV4KT45OTk5XQogIGF1eAp9CgpSYXMuaW5ncmVzc28uZGlzY2lwbGluYTwtZnVuY3Rpb24odil7ZGF0YS5mcmFtZShmaWx0cm8uZGlzY2lwbGluYS5SYSh2KSxzYXBwbHkoZmlsdHJvLmRpc2NpcGxpbmEuUmEodiksIGFuby5pbmdyZXNzby5yYSkpfQpgYGAKVmFtb3Mgb2xoYXIgUHJpbmPDrXBpb3MgZGUgQWRtaW5pc3RyYcOnw6NvCmBgYHtyfQpiYXJwbG90KHRhYmxlKFJhcy5pbmdyZXNzby5kaXNjaXBsaW5hKCJwcmluY2lwaW9zIGRlIGFkbWluaXN0cmFjYW8iKVsyXSksIG1haW4gPSAiQ2h1dGVzIGVtIHByaW5jaXBpb3MgZGUgYWRtaW5pc3RyYWNhbyIpCmBgYAojIyBFbmdlbmhhcmlhIFVuaWZpY2FkYSBpCmBgYHtyfQpiYXJwbG90KHRhYmxlKFJhcy5pbmdyZXNzby5kaXNjaXBsaW5hKCJlbmdlbmhhcmlhIHVuaWZpY2FkYSBpIilbMl0pLCBtYWluID0gImVuZ2VuaGFyaWEgdW5pZmljYWRhIGkiKQpgYGAKCgojIyBDaXJjdWl0b3MgRWxldHJpY29zIGUgRm90b25pY2EKVmFtb3Mgb2xoYXIgY2lyY3VpdG9zIGVsw6l0cmljb3MgZSBmb3TDtG5pY2EKYGBge3J9CmJhcnBsb3QodGFibGUoUmFzLmluZ3Jlc3NvLmRpc2NpcGxpbmEoImNpcmN1aXRvcyBlbGV0cmljb3MgZSBmb3RvbmljYSIpWzJdKSwgbWFpbiA9ICJDaHV0ZXMgZW0gY2lyY3VpdG9zIGVsZXRyaWNvcyBlIGZvdG9uaWNhIikKYGBgCgojIFR1cm5vCmBgYHtyfQp0dXJubzwtZnVuY3Rpb24odix3KXtsZW5ndGgoZ3JlcCh2LHVsdGltbykpfQpjaHV0ZXMudHVybm88LWRhdGEuZnJhbWUoYygiZGl1cm5vIiwibm90dXJubyIpLCBjKHR1cm5vKCJtYXR1dGlubyIpICx0dXJubygibm90dXJubyIpKSkKY29sbmFtZXMoY2h1dGVzLnR1cm5vKTwtYygidHVybm8iLCAiY2h1dGVzIikKY2h1dGVzLnR1cm5vCmBgYApCYXJwbG90CmBgYHtyfQpwaWUzRCh0KGNodXRlcy50dXJub1syXSksbGFiZWxzPWMoImRpdXJubyIsIm5vdHVybm8iKSkKYGBgCgoKIyBDYW1wdXMKYGBge3J9CmNhbXB1czwtZnVuY3Rpb24odil7bGVuZ3RoKGdyZXAodix1bHRpbW8pKX0KY2h1dGVzLmNhbXB1czwtZGF0YS5mcmFtZShjKCJTQSIsIlNCQyIpLCBjKHR1cm5vKCJzYW50byBhbmRyZSIpICx0dXJubygic2FvIGJlcm5hcmRvIikpKQpjb2xuYW1lcyhjaHV0ZXMuY2FtcHVzKTwtYygiY2FtcHVzIiwgImNodXRlcyIpCmNodXRlcy5jYW1wdXMKYGBgCkJhcnBsb3QKYGBge3J9CnBpZTNEKHQoY2h1dGVzLmNhbXB1c1syXSksbGFiZWxzPWMoIlNBIiwiU0JDIikpCmBgYAoKIyMgU8OjbyBCZXJuYXJkbyBOb3R1cm5vIMOpIG8gSW5mZXJubz8KTWVsaG9yb3UgYSBzaXR1YcOnw6NvIGVtIFNCQyBhIG5vaXRlIG5lc3RlIHF1YWRyaW1lc3RyZS4KCmBgYHtyfQpjYW1wdXM8LWZ1bmN0aW9uKHYpe2xlbmd0aChncmVwKHYsdWx0aW1vKSl9CmNhbXB1cy50dXJubyA8LWZ1bmN0aW9uKGNhbXAsdHVyKXsgbGVuZ3RoKGdyZXAodHVyLHVsdGltb1tncmVwKGNhbXAsdWx0aW1vKV0pKX0KdmNhbXB1cy50dXJubyA8LSBWZWN0b3JpemUoY2FtcHVzLnR1cm5vLCBTSU1QTElGWSA9IEZBTFNFKQpjaHV0ZXMuY2FtcHVzPC1kYXRhLmZyYW1lKGMoIlNBIC0iLCJTQkMiKSwgYyh0dXJubygibm90dXJubyAoc2FvIGJlcm5hcmRvKSIpICx0dXJubygic2FvIGJlcm5hcmRvIikpKQpjb2xuYW1lcyhjaHV0ZXMuY2FtcHVzKTwtYygiY2FtcHVzIiwgImNodXRlcyIpCnR1cm5vczwtYygibWF0dXRpbm8iLCJub3R1cm5vIikKY2FtcHVzPC1jKCJzYW50byBhbmRyZSIsInNhbyBiZXJuYXJkbyIpCmNodXRlcy5jYW1wdXMudHVybm88LSBvdXRlcih0dXJub3MsIGNhbXB1cywgdmNhbXB1cy50dXJubykgCmNvbG5hbWVzKGNodXRlcy5jYW1wdXMudHVybm8pPC1jYW1wdXMKcm93bmFtZXMoY2h1dGVzLmNhbXB1cy50dXJubyk8LXR1cm5vcwpjaHV0ZXMuY2FtcHVzLnR1cm5vCmBgYAoKIyMjIFPDqXJpZSBIaXN0w7NyaWNhCmBgYHtyfQpzYS5oaXN0PC1mdW5jdGlvbih3KXtsZW5ndGgoZ3JlcCgic2FudG8gYW5kcmUiLHcpKX0Kc2JjLmhpc3Q8LWZ1bmN0aW9uKHcpe2xlbmd0aChncmVwKCJzYW8gYmVybmFyZG8iLHcpKX0KCmFycXVpdm9zID0gbGlzdC5maWxlcyhwYXRoPSIuL2RhZG9zL2NodXRlcy8iLCBwYXR0ZXJuPSIqLnR4dCIpICMgSW1wb3J0YSBvcyBhcnF1aXZvcyBkbyBkaXJldMOzcmlvCnF1YWQ9Z3N1YigiLnR4dCIsIiIsYXJxdWl2b3MpCnNhPWxpc3QoKQpzYmM9bGlzdCgpCgojIyMjIyBDb250YSBvcyBDaHV0ZXMgLSBFc3NhIGZ1bsOnw6NvIGrDoSDDqSBwYXJhbGVsaXphZGEhCmZvciAoaSBpbiAxOm51bWVyby5xdWFkKSB7IAogICBzYVtbaV1dPC1zYS5oaXN0KHJlYWRMaW5lcyhwYXN0ZSgiLi9kYWRvcy9jaHV0ZXMvIixhcnF1aXZvc1tpXSxzZXA9IiIpKSkKICAgc2JjW1tpXV08LXNiYy5oaXN0KHJlYWRMaW5lcyhwYXN0ZSgiLi9kYWRvcy9jaHV0ZXMvIixhcnF1aXZvc1tpXSxzZXA9IiIpKSkKCn0KcGxvdChtYXRyaXgodChzYSkpLHR5cGUgPSAibyIseWxhYj0iU0EiLCBtYWluPSJDaHV0ZXMgZW0gU0EiKQpgYGAKCmBgYHtyfQpwbG90KG1hdHJpeCh0KHNiYykpLHR5cGUgPSAibyIseWxhYj0iU0JDIiwgbWFpbj0iQ2h1dGVzIGVtIFNCQyIpCmBgYAoKYGBge3J9CnBsb3QobWF0cml4KHQoc2EpKSx0eXBlID0gIm8iLHlsYWI9IlNCQyIsIG1haW49IkNodXRlcyBlbSBTQSBlIFNCQyIsY29sPSJyZWQiLCAgeWxpbT1jKDEsIDcxMDApKQpwb2ludHMobWF0cml4KHQoc2JjKSksY29sPSJncmVlbiIscGNoID0gMTksdHlwZSA9ICJwIikKbGluZXMobWF0cml4KHQoc2JjKSksY29sPSJncmVlbiIpCmBgYAoKCgojIERlZmVyaWRhcyAKCiMgTWF0csOtY3VsYXMgRGVmZXJpZGFzCmBgYHtyfQphcnF1aXZvczIgPSBsaXN0LmZpbGVzKHBhdGg9Ii4vZGFkb3MvZGVmZXJpZGFzLyIsIHBhdHRlcm49IioudHh0IikgIyBJbXBvcnRhIG9zIGFycXVpdm9zIGRvIGRpcmV0w7NyaW8KcXVhZDI9Z3N1YigiZGVmIiwiIixnc3ViKCIudHh0IiwiIixhcnF1aXZvczIpKQpmaWx0cm8uUmE8LWZ1bmN0aW9uKHYpewogIGF1eDwtdW5pcXVlKG5hLm9taXQodW5saXN0KHN0cnNwbGl0KHVubGlzdCh2KSwgIlteMC05XSsiKSkpKQogYXV4PC0gYXV4W2FzLm51bWVyaWMoYXV4KT45OTk5OV0KICBhdXgKfQpkZWY9YygpCmZvciAoaSBpbiAxOmxlbmd0aChhcnF1aXZvczIpKSB7IAogICBkZWZbW2ldXTwtbGVuZ3RoKGZpbHRyby5SYShyZWFkTGluZXMocGFzdGUoIi4vZGFkb3MvZGVmZXJpZGFzLyIsYXJxdWl2b3MyW2ldLHNlcD0iIikpKSkKCn0KdmRlZjwtZGVmCmRlZjwtZGF0YS5mcmFtZShkZWYpCnJvd25hbWVzKGRlZikgPC0gcXVhZDIKCmBgYAoKCmBgYHtyfQpiYXJwbG90KHQoYXMudmVjdG9yKGRlZikpLG1haW49IkFsdW5vcyBNYXRyaWN1bGFkb3MiKQoKYGBgCgpgYGB7cn0KZGVmCmBgYAoKYGBge3J9CnBsb3QodmRlZix0eXBlPSJvIikKYGBgCgoKIyBEZW5zaWRhZGUgZGUgQ2h1dGVzCgpDb250YSBvIG51bWVybyBkZSBhbHVub3MgY2h1dGFkb3MgcG9yIHF1YWRyaW1lc3RyZQpgYGB7cn0KY2h1dGFkb3M9YygpCmZvciAoaSBpbiAxOmxlbmd0aChhcnF1aXZvcykpIHsgCiAgY2h1dGFkb3NbW2ldXTwtbGVuZ3RoKGZpbHRyby5SYShyZWFkTGluZXMocGFzdGUoIi4vZGFkb3MvY2h1dGVzLyIsYXJxdWl2b3NbaV0sc2VwPSIiKSkpKQoKfQpjaHV0YWRvczwtZGF0YS5mcmFtZShjaHV0YWRvcykKcXVhZD1nc3ViKCIudHh0IiwiIixhcnF1aXZvcykKcm93bmFtZXMoY2h1dGFkb3MpIDwtIHF1YWQKYGBgCgoKCk1vZGVsbyBkZSBudW1lcm8gZGUgYWx1bm9zIFVGQUJDCgpgYGB7cn0KIyMjIExvZyBmaXQgLSBiZSBzdXJlIHRvIHVzZSBxdW90ZXMgYXJvdW5kIHRoZSB2YXJpYWJsZSBuYW1lcyBpbiB0aGUgY2FsbApsb2dkZWY8LWRhdGEuZnJhbWUoMToxNCxkZWZbMV0pCmNvbG5hbWVzKGxvZ2RlZik8LWMoInF1YWQiLCJjaHV0ZXMiKQoKbG9nLmZpdCA8LSBmdW5jdGlvbiggeW91cmRhdGEsZGVwLCBpbmQpewogICMgU2VsZi1zdGFydGluZy4uLgogIAogIHkgPC0geW91cmRhdGFbLCBkZXBdCiAgeCA8LSB5b3VyZGF0YVssIGluZF0KICAKICBsb2cuc3MgPC0gbmxzKHkgfiBTU2xvZ2lzKHgsIHBoaTEsIHBoaTIsIHBoaTMpKQogIAogICMgQwogIEMgPC0gc3VtbWFyeShsb2cuc3MpJGNvZWZbMV0KICAjIGEKICBBIDwtIGV4cCgoc3VtbWFyeShsb2cuc3MpJGNvZWZbMl0pICogKDEvc3VtbWFyeShsb2cuc3MpJGNvZWZbM10pKQogICMgawogIEsgPC0gKDEgLyBzdW1tYXJ5KGxvZy5zcykkY29lZlszXSkKICAKICBwbG90KHkgfiB4LCBtYWluID0gIkN1cnZhIExvZ2lzdGljYSIsIHhsYWI9aW5kLCB5bGFiPWRlcCx0eXBlPSJvIikKICBsaW5lcygwOm1heCh4KSwgcHJlZGljdChsb2cuc3MsIGRhdGEuZnJhbWUoeD0wOm1heCh4KSkpLCBjb2w9InJlZCIpCiAgCiAgcjEgPC0gc3VtKCh4IC0gbWVhbih4KSleMikKICByMiA8LSBzdW0ocmVzaWR1YWxzKGxvZy5zcyleMikKICAKICByX3NxIDwtIChyMSAtIHIyKSAvIHIxCiAgCiAgb3V0IDwtIGRhdGEuZnJhbWUoY2JpbmQoYyhDPUMsIGE9QSwgaz1LLCBSLnZhbHVlPXNxcnQocl9zcSkpKSkKICBuYW1lcyhvdXQpWzFdIDwtICJDdXJ2YSBMb2dpc3RpY2EiCiAgCiAgcmV0dXJuKG91dCkKfQpsb2cuZml0KGxvZ2RlZiwiY2h1dGVzIiwicXVhZCIpCmBgYAoKVXNhbmRvIGEgbG9nw61zdGljYSB0ZW1vcyBvIHNlZ3VpbnRlIG51bWVybyBkZSBhbHVub3MgcHJldmlzdG8gY29tbyBtw6F4aW1vIGVmZXRpdmFtZW50ZSBtYXRyaWN1bGFkb3MKYGBge3J9CiAgMS4yNDUwOTFlKzA0CQpgYGAKCiMgQ2FuY2VsYW1lbnRvcwoKYGBge3J9CmFycXVpdm9zID0gbGlzdC5maWxlcyhwYXRoPSIuL2RhZG9zL2NhbmNlbGFtZW50by8iLCBwYXR0ZXJuPSIqLnR4dCIpICMgSW1wb3J0YSBvcyBhcnF1aXZvcyBkbyBkaXJldMOzcmlvCmNhbmNlbGFtZW50b3M9bGlzdCgpCiMjIyMjIENvbnRhIG9zIENodXRlcyAtIEVzc2EgZnVuw6fDo28gCmZvciAoaSBpbiAxOmxlbmd0aChhcnF1aXZvcykpIHsgCmNhbmNlbGFtZW50b3NbW2ldXTwtc2FwcGx5KHQoZGlzY2lwbGluYXMpLGNvbnRhY2h1dGVzLCB3PXJlYWRMaW5lcyhwYXN0ZSgiLi9kYWRvcy9jYW5jZWxhbWVudG8vIixhcnF1aXZvc1tpXSxzZXA9IiIpKSkKfQpgYGAKCmBgYHtyfQpjYW5jZWxhbWVudG9zPC1kYXRhLmZyYW1lKGNhbmNlbGFtZW50b3MpCiNjYW5jZWxhbWVudG9zIDwtc29ydChjYW5jZWxhbWVudG9zW3doaWNoKGNhbmNlbGFtZW50b3MgPiAxMildLCAgZGVjcmVhc2luZyA9IFRSVUUpCgpgYGAKCgpgYGB7cn0KcXVhZD1nc3ViKCJfIiwiLiIsZ3N1YigiY2FuY2VsYW1lbnRvX2Rpc2NpcGxpbmFzXyIsIlEiLGdzdWIoIi50eHQiLCIiLGFycXVpdm9zKSkpCmNhbmNlbGFtZW50b3M8LWRhdGEuZnJhbWUoY2FuY2VsYW1lbnRvcykKY29sbmFtZXMoY2FuY2VsYW1lbnRvcyk8LXF1YWQKY29sU3VtcyhkYXRhLmZyYW1lKGNhbmNlbGFtZW50b3MpKQpgYGAKYGBge3J9CiBiYXJwbG90KCBjb2xTdW1zKGRhdGEuZnJhbWUoY2FuY2VsYW1lbnRvcykpLG1haW49Ik7Dum1lcm8gZGUgQ2FuY2VsYW1lbnRvcyIpCmBgYAoKIyBDb250YSBvIG51bWVybyBkZSBhbHVub3MgY2h1dGFkb3MgcG9yIHF1YWRyaW1lc3RyZSBwb3IgY3Vyc28KCkxlbWJyYW1vcyBhIGRpc3RyaWJ1acOnw6NvIGdlcmFsIGRhIFVGQUJDCmBgYHtyfQpiYXJwbG90KGRhdGFfZGlzdCwgbWFpbj0iTsO6bWVybyBkZSBDaHV0ZXMgcG9yIEFsdW5vIikKYGBgCgoKQWdvcmEgdmFtb3MgY3JpYXIgZnVuw6fDtWVzIHBhcmEgY29udGFyIG9zIGNodXRlcyBwb3IgY3Vyc286CgpgYGB7cn0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBOdW1lcm8gZGUgY2h1dGVzIHBvciBBbHVubwpjaHV0ZXNwb3JhbHVuby51bHRpbW9xPC1kYXRhLmZyYW1lKHJlYWQuY3N2KCIuL2RhZG9zL2NodXRlcy8yMDE4LjIuY3N2IikpCmNvbG5hbWVzKGNodXRlc3BvcmFsdW5vLnVsdGltb3EpPC1jKCJyYSIsInR1cm1hIikKUmFzPC11bmlxdWUoY2h1dGVzcG9yYWx1bm8udWx0aW1vcVsxXSkKUmFzPC1SYXNbIWlzLm5hKFJhcyldCm91dHB1dDQ8LW1hcmdpbi50YWJsZSh0YWJsZShjaHV0ZXNwb3JhbHVuby51bHRpbW9xKSwgMSkKCmBgYAoKYGBge3J9CgoKY2h1dGVzLmFsdW5vcy5jdXJzby5SYTwtZnVuY3Rpb24odil7CiAgICAgY2h1dGVzcG9yYWx1bm8udWx0aW1vcVtncmVwKHBhc3RlKHQoZGlzY2lwbGluYXMuY3Vyc28odikpLGNvbGxhcHNlPSJ8IiksCiAgICAgICAgICAgICAgICAgICAgICAgY2h1dGVzcG9yYWx1bm8udWx0aW1vcSR0dXJtYSksXVsxXQp9CgpjaHV0ZXMuYWx1bm9zLmN1cnNvPC1mdW5jdGlvbih2KXsKICAgIGNodXRlc3BvcmFsdW5vLnVsdGltb3FbZ3JlcChwYXN0ZSh0KGNodXRlcy5hbHVub3MuY3Vyc28uUmEodikpLGNvbGxhcHNlPSJ8IiksCiAgICAgICAgICAgICAgICAgICAgICAgIGNodXRlc3BvcmFsdW5vLnVsdGltb3EkcmEpLF0KfQpgYGAKClZhbW9zIHZlciBhbGd1bnMgY2Fzb3MKCiMgR2VzdMOjbwpgYGB7cn0KdG90YWw8LWxlbmd0aCh0KHRhYmxlKGNodXRlcy5hbHVub3MuY3Vyc28oIkVHRVNUIilbMV0pKSkKQ0hFR0VTVDwtdCh0YWJsZShjaHV0ZXMuYWx1bm9zLmN1cnNvKCJFR0VTVCIpWzFdKSkKYmFycGxvdCh0YWJsZShDSEVHRVNUKSxtYWluPSJOw7ptZXJvIGRlIGNodXRlcyBwb3IgQWx1bm8gbmEgR2VzdMOjbyIpCgpgYGAKCiMgRWNvbm9taWEKYGBge3J9CnRvdGFsPC1sZW5ndGgodCh0YWJsZShjaHV0ZXMuYWx1bm9zLmN1cnNvKCJCQ0VDTyIpWzFdKSkpCkNIRUJDRUNPPC10KHRhYmxlKGNodXRlcy5hbHVub3MuY3Vyc28oIkJDRUNPIilbMV0pKQpiYXJwbG90KHRhYmxlKENIRUJDRUNPKSxtYWluPSJOw7ptZXJvIGRlIGNodXRlcyBwb3IgQWx1bm8gbmEgRWNvbm9taWEiKQoKYGBgCgojIEVJQVIKYGBge3J9CnRvdGFsPC1sZW5ndGgodCh0YWJsZShjaHV0ZXMuYWx1bm9zLmN1cnNvKCJFSUFSIilbMV0pKSkKQ0hFR0VTVDwtdCh0YWJsZShjaHV0ZXMuYWx1bm9zLmN1cnNvKCJFSUFSIilbMV0pKQpiYXJwbG90KHRhYmxlKENIRUdFU1QpLG1haW49Ik7Dum1lcm8gZGUgY2h1dGVzIHBvciBBbHVubyBuYSBFSUFSIikKCmBgYAoKCiMgTnVjbGVvIENvbXVtCmBgYHtyfQp0b3RhbDwtbGVuZ3RoKHQodGFibGUoY2h1dGVzLmFsdW5vcy5jdXJzbygibnVjbGVvY29tdW0iKVsxXSkpKQpDSG51Y2xlb2NvbXVtPC10KHRhYmxlKGNodXRlcy5hbHVub3MuY3Vyc28oIm51Y2xlb2NvbXVtIilbMV0pKQpiYXJwbG90KHRhYmxlKENIbnVjbGVvY29tdW0pLG1haW49Ik7Dum1lcm8gZGUgY2h1dGVzIHBvciBBbHVubyBubyBOw7pjbGVvIENvbXVtIikKCmBgYAoKCiMgQkNUCmBgYHtyfQp0b3RhbDwtbGVuZ3RoKHQodGFibGUoY2h1dGVzLmFsdW5vcy5jdXJzbygiYmN0IilbMV0pKSkKQ0hiY3Q8LXQodGFibGUoY2h1dGVzLmFsdW5vcy5jdXJzbygiYmN0IilbMV0pKQpiYXJwbG90KHRhYmxlKENIYmN0KSxtYWluPSJOw7ptZXJvIGRlIGNodXRlcyBwb3IgQWx1bm8gbm8gQkMmVCIpCgpgYGAKCiMgQkNDCmBgYHtyfQoKdG90YWw8LWxlbmd0aCh0KHRhYmxlKGNodXRlcy5hbHVub3MuY3Vyc28oIkJDQyIpWzFdKSkpCkNIRUdFU1Q8LXQodGFibGUoY2h1dGVzLmFsdW5vcy5jdXJzbygiQkNDIilbMV0pKQpiYXJwbG90KHRhYmxlKENIRUdFU1QpLG1haW49Ik7Dum1lcm8gZGUgY2h1dGVzIHBvciBBbHVubyBubyBCYWNoLiBlbSBDb21wLiIpCgpgYGAKCiMgQWx1bm9zIENodXRhZG9zIHBvciBDdXJzbwpWYW1vcyBhbmFsaXNhciBvIG51bWVybyBkZSBhbHVub3MgY2h1dGFkb3MgZW0gY2FkYSBjdXJzbwoKYGBge3J9CgpjaHV0ZXMuYWx1bm9zLmN1cnNvLlJhPC1mdW5jdGlvbih2KXsKICAgICB1bmlxdWUoY2h1dGVzcG9yYWx1bm8udWx0aW1vcVtncmVwKHBhc3RlKHQoZGlzY2lwbGluYXMuY3Vyc28odikpLGNvbGxhcHNlPSJ8IiksCiAgICAgICAgICAgICAgICAgICAgICAgY2h1dGVzcG9yYWx1bm8udWx0aW1vcSR0dXJtYSksXVsxXSkKfQoKY2h1dGVzLmFsdW5vcy5jdXJzbzI8LWZ1bmN0aW9uKHYpewogICAgdW5pcXVlKGNodXRlc3BvcmFsdW5vLnVsdGltb3FbZ3JlcChwYXN0ZSh0KGNodXRlcy5hbHVub3MuY3Vyc28uUmEodikpLGNvbGxhcHNlPSJ8IiksCiAgICAgICAgICAgICAgICAgICAgICAgIGNodXRlc3BvcmFsdW5vLnVsdGltb3EkcmEpLF1bMV0pCn0KYGBgCgoKYGBge3J9Cm5vbWVzLmN1cnNvczwtcmVhZC5jc3YoIi4vZGFkb3MvbGlzdGFzZGVkaXNjaXBsaW5hcy9jdXJzb3MuY3N2IikKbm9tZXMuY3Vyc29zPC1ub21lcy5jdXJzb3NbMToyOCxdCmFsdW5vc2NodXRhZG9zcG9yY3Vyc288LWZ1bmN0aW9uKHYpe25yb3coY2h1dGVzLmFsdW5vcy5jdXJzby5SYSh2KSl9CmNodXRlcy5vdXQ8LXQoc2FwcGx5KCBub21lcy5jdXJzb3MsYWx1bm9zY2h1dGFkb3Nwb3JjdXJzbykpCgpgYGAKCgpgYGB7cn0KbGlicmFyeShrbml0cikKY29sbmFtZXMoY2h1dGVzLm91dCk8LW5vbWVzLmN1cnNvcwpyb3duYW1lcyhjaHV0ZXMub3V0KTwtYyggIkFsdW5vcyBjaHV0YWRvcyBlbSBwZWxvIG1lbm9zIDEgZGlzY2lwbGluYSBkbyBjdXJzbyIpCmFzPC1jaHV0ZXMub3V0WyxvcmRlcigtY2h1dGVzLm91dFsxLF0pXQprYWJsZShhc1sxOjEyXSxjb2wubmFtZXM9IkFsdW5vcyBjaHV0YWRvcyBlbSBwZWxvIG1lbm9zIDEgZGlzY2lwbGluYSBkbyBjdXJzbyIpCgpgYGAKCgo=