NETLOGO TOY MODEL
TODO
- changer le script scala pour passer des parametres directement depuis le notebook !
- prendre en sorte le fait qu’on a 3 données par pas de temps dans le graphique
Producing csv outputs
You could produce csv outputs of Netlogo MeatModel using Netlogo interface by opening the ./toy/PicSaintLoup/MeatModel-V5
model, running some experiments, and when you’re donne, clic on the button save-csv.
If you have sbt
build engine installed on your computer you could also run this headless script by running this chunk directly from R/RStudio.
./toy/PicSaintLoup/MeatModel-V5
folder.
Producing explorations
TO LONG DATA AGE
gdfFinalAge <- merge(gdFinalByAge_valueOpinion, gdFinalByAge_nbVoisin, by=c("age","time"), type="inner")
gdfFinalAge <- merge(gdfFinalAge, gdFinalByAge_apparie, by=c("age","time"), type="inner")
gDfToLongAge <- gather(gdfFinalAge, facteur, value , by=c(ValueOpinion,nb,nbVoisins))
p <- ggplot(data=gDfToLongAge, aes(x=time, y=value, group=age, fill=age, colour=as.character(age)))
p <- p + geom_line(size=1) + facet_grid(facteur ~ .) #show.legend = FALSE
p

TO LONG DATA EDU
gdfFinalEdu <- merge(gdFinalByEdu_valueOpinion, gdFinalByEdu_nbVoisin, by=c("edu", "time"), type="inner")
gdfFinalEdu <- merge(gdfFinalEdu, gdFinalByEdu_apparie, by=c("edu","time"), type="inner")
gDfToLongEdu <- gather(gdfFinalEdu, facteur, value , by=c(ValueOpinion,nb,nbVoisins))
p <- ggplot(data=gDfToLongEdu, aes(x=time, y=value, group=edu, fill=edu, colour=as.character(edu)))
p <- p + geom_line(size=1) + facet_grid(facteur ~ .) #show.legend = FALSE
p

TO LONG DATA SEX
gdfFinalSex <- merge(gdFinalBySex_valueOpinion, gdFinalBySex_nbVoisin, by=c("sex", "time"), type="inner")
gdfFinalSex <- merge(gdfFinalSex, gdFinalBySex_apparie, by=c("sex","time"), type="inner")
gDfToLongSex <- gather(gdfFinalSex, facteur, value , by=c(ValueOpinion,nb,nbVoisins))
p <- ggplot(data=gDfToLongSex, aes(x=time, y=value, group=sex, fill=sex, colour=as.character(sex)))
p <- p + geom_line(size=1) + facet_grid(facteur ~ .) #show.legend = FALSE
p

FAT MODEL
specialRead <- function(x) {
read_csv(file=x, col_names = TRUE, col_types= "nnnnnnnnnn")
}
concatFiles <- function (base, folder){
fullPath = paste(base,folder,sep="")
list.files(path = fullPath, full.names = TRUE, pattern = "(\\d_\\d_\\d)") %>% lapply(specialRead) %>% bind_rows
}
Exploring scenarii
random residential scenario 1
RANDOM POP NO MOVE SEED 42
sortie_sc1 <- concatFiles(base,"results_ose_Scenario1_RandomPop_NoMove_42")
sortie_sc1$propHealthy <- sortie_sc1$healthy / sortie_sc1$effective
sortieLong_sc1 <- gather(sortie_sc1, facteur, valeur, by=c(propHealthy,avgOpinion) )
sortieLong_sc1 <- mutate(sortieLong_sc1, "ds" = gsub(" ", "", paste(paste("[",paste(sortieLong_sc1$day, sortieLong_sc1$slice)),"]")))
p <- ggplot(data=sortieLong_sc1, aes(x=ds, y=valeur, group=educ, fill=educ, colour=as.character(educ)))
p <- p + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
p <- p + geom_line(size=0.5) + facet_grid(facteur ~ sex ~ age, labeller = label_both) #show.legend = FALSE
p

ggsave("sc1_randomPop_noMove.pdf")
Saving 20 x 12.4 in image
survey residential scenario 2
sortie_sc2 <- concatFiles(base,"results_ose_Scenario2_RandomPop_RandomMove_42")
sortie_sc2$propHealthy <- sortie_sc2$healthy / sortie_sc2$effective
sortieLong_sc2 <- gather(sortie_sc2, facteur, valeur, by=c(propHealthy,avgOpinion) )
sortieLong_sc2 <- mutate(sortieLong_sc2, "ds" = gsub(" ", "", paste(paste("[",paste(sortieLong_sc2$day, sortieLong_sc2$slice)),"]")))
p <- ggplot(data=sortieLong_sc2, aes(x=ds, y=valeur, group=educ, fill=educ, colour=as.character(educ)))
p <- p + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
p <- p + geom_line(size=0.5) + facet_grid(facteur ~ sex ~ age, labeller = label_both) #show.legend = FALSE
p

ggsave("sc2_randomPop_randomMove.pdf")
Saving 20 x 12.4 in image
random activity scenario 3
sortie_sc3 <- concatFiles(base,"results_ose_Scenario3_ObservedPop_NoMove_42")
sortie_sc3$propHealthy <- sortie_sc3$healthy / sortie_sc3$effective
sortieLong_sc3 <- gather(sortie_sc3, facteur, valeur, by=c(propHealthy,avgOpinion) )
sortieLong_sc3 <- mutate(sortieLong_sc3, "ds" = gsub(" ", "", paste(paste("[",paste(sortieLong_sc3$day, sortieLong_sc3$slice)),"]")))
p <- ggplot(data=sortieLong_sc3, aes(x=ds, y=valeur, group=educ, fill=educ, colour=as.character(educ)))
p <- p + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
p <- p + geom_line(size=0.5) + facet_grid(facteur ~ sex ~ age, labeller = label_both) #show.legend = FALSE
p

ggsave("sc3_obsPop_noMove.pdf")
Saving 20 x 12.4 in image
survey activity scenario 4
sortie_sc4 <- concatFiles(base,"results_ose_Scenario4_ObservedPop_RandomMove_42")
sortie_sc4$propHealthy <- sortie_sc4$healthy / sortie_sc4$effective
sortieLong_sc4 <- gather(sortie_sc4, facteur, valeur, by=c(propHealthy,avgOpinion) )
sortieLong_sc4 <- mutate(sortieLong_sc4, "ds" = gsub(" ", "", paste(paste("[",paste(sortieLong_sc4$day, sortieLong_sc4$slice)),"]")))
p <- ggplot(data=sortieLong_sc4, aes(x=ds, y=valeur, group=educ, fill=educ, colour=as.character(educ)))
p <- p + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
p <- p + geom_line(size=0.5) + facet_grid(facteur ~ sex ~ age, labeller = label_both) #show.legend = FALSE
p

ggsave("sc4_obsPop_randomMove.pdf")
Saving 20 x 12.4 in image
survey activity scenario 4
sortie_sc5 <- concatFiles(base,"results_ose_Scenario5_ObservedPop_ObservedMove_42")
sortie_sc5$propHealthy <- sortie_sc5$healthy / sortie_sc5$effective
sortieLong_sc5 <- gather(sortie_sc5, facteur, valeur, by=c(propHealthy,avgOpinion) )
sortieLong_sc5 <- mutate(sortieLong_sc5, "ds" = gsub(" ", "", paste(paste("[",paste(sortieLong_sc5$day, sortieLong_sc5$slice)),"]")))
p <- ggplot(data=sortieLong_sc5, aes(x=ds, y=valeur, group=educ, fill=educ, colour=as.character(educ)))
p <- p + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
p <- p + geom_line(size=0.5) + facet_grid(facteur ~ sex ~ age, labeller = label_both) #show.legend = FALSE
p

ggsave("sc5_obsPop_obsMove.pdf")
Saving 20 x 12.4 in image
LS0tCnRpdGxlOiAiRXhwbG9yaW5nIE1lYXQgdG95IG1vZGVsIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KHBseXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShtYWdyaXR0cikKCgpiYXNlIDwtICIvaG9tZS9yZXltYW4vUHJvamV0cy9oMjRfaXNjcGlmL2RhdGEvVEhFT1FVQU5UMjAxOS8iCgpgYGAKCiAKIyBORVRMT0dPIFRPWSBNT0RFTAoKX19UT0RPX18KCi0gY2hhbmdlciBsZSBzY3JpcHQgc2NhbGEgcG91ciBwYXNzZXIgZGVzIHBhcmFtZXRyZXMgZGlyZWN0ZW1lbnQgZGVwdWlzIGxlIG5vdGVib29rICEKLSBwcmVuZHJlIGVuIHNvcnRlIGxlIGZhaXQgcXUnb24gYSAzIGRvbm7DqWVzIHBhciBwYXMgZGUgdGVtcHMgZGFucyBsZSBncmFwaGlxdWUgCgojIyBQcm9kdWNpbmcgY3N2IG91dHB1dHMKCllvdSBjb3VsZCBwcm9kdWNlIGNzdiBvdXRwdXRzIG9mIE5ldGxvZ28gTWVhdE1vZGVsIHVzaW5nIE5ldGxvZ28gaW50ZXJmYWNlIGJ5IG9wZW5pbmcgdGhlIGAuL3RveS9QaWNTYWludExvdXAvTWVhdE1vZGVsLVY1YCBtb2RlbCwgcnVubmluZyBzb21lIGV4cGVyaW1lbnRzLCBhbmQgd2hlbiB5b3UncmUgZG9ubmUsIGNsaWMgb24gdGhlIGJ1dHRvbiBzYXZlLWNzdi4gCgpJZiB5b3UgaGF2ZSBgc2J0YCBidWlsZCBlbmdpbmUgaW5zdGFsbGVkIG9uIHlvdXIgY29tcHV0ZXIgeW91IGNvdWxkIGFsc28gcnVuIHRoaXMgaGVhZGxlc3Mgc2NyaXB0IGJ5IHJ1bm5pbmcgdGhpcyBjaHVuayBkaXJlY3RseSBmcm9tIFIvUlN0dWRpby4gCgpgLi90b3kvUGljU2FpbnRMb3VwL01lYXRNb2RlbC1WNWAgZm9sZGVyLiAKYGBge2Jhc2gsIGluY2x1ZGU9RkFMU0V9CmNkIC4uL3RveS9QaWNTYWludExvdXAvCnNidCBydW4KYGBgCgojIyBQcm9kdWNpbmcgZXhwbG9yYXRpb25zCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KYXBwYXJpZSA8LSByZWFkX2NzdigiLi4vdG95L1BpY1NhaW50TG91cC9tb2RlbHMvb3V0cHV0cy9hcHBhcmllLmNzdiIsY29sX25hbWVzID0gRkFMU0UpIAp2b2lzaW5zIDwtIHJlYWRfY3N2KCIuLi90b3kvUGljU2FpbnRMb3VwL21vZGVscy9vdXRwdXRzL3ZvaXNpbnMuY3N2Iixjb2xfbmFtZXMgPSBGQUxTRSkgCm9waW5pb24gPC0gcmVhZF9jc3YoIi4uL3RveS9QaWNTYWludExvdXAvbW9kZWxzL291dHB1dHMvb3Bpbmlvbi5jc3YiLGNvbF9uYW1lcyA9IEZBTFNFKSAKCmFwcGFyaWUkWDUgPC0gIGdzdWIoIlxcW3xcXF0iLCAiIiwgYXBwYXJpZSRYNSkKdm9pc2lucyRYNSA8LSBnc3ViKCJcXFt8XFxdIiwgIiIsIHZvaXNpbnMkWDUpCm9waW5pb24kWDUgPC0gZ3N1YigiXFxbfFxcXSIsICIiLCBvcGluaW9uJFg1KQoKbCA8LSBzdHJzcGxpdChmaXJzdChhcHBhcmllJFg1KSwiICIgKQpzaXplU2VxIDwtIHNlcShsZW5ndGhzKGwpKQoKZGZBcHBhcmllIDwtIHdpdGgoYXBwYXJpZSwgY2JpbmQoWDEsWDIsWDMsWDQsIGNvbHNwbGl0KGFwcGFyaWUkWDUsICIgIiwgbmFtZXMgPSBzaXplU2VxKSApKQoKZGZWb2lzaW5zIDwtIHdpdGgodm9pc2lucywgY2JpbmQoWDEsWDIsWDMsWDQsIGNvbHNwbGl0KHZvaXNpbnMkWDUsICIgIiwgbmFtZXMgPSBzaXplU2VxKSApKQoKZGZPcGluaW9uIDwtIHdpdGgob3BpbmlvbiwgY2JpbmQoWDEsWDIsWDMsWDQsIGNvbHNwbGl0KG9waW5pb24kWDUsICIgIiwgbmFtZXMgPSBzaXplU2VxKSApKQoKbmFtZXMoZGZBcHBhcmllKVsxXSA8LSBwYXN0ZSgid2hvIikKbmFtZXMoZGZBcHBhcmllKVsyXSA8LSBwYXN0ZSgiYWdlIikKbmFtZXMoZGZBcHBhcmllKVszXSA8LSBwYXN0ZSgic2V4IikKbmFtZXMoZGZBcHBhcmllKVs0XSA8LSBwYXN0ZSgiZWR1IikKCm5hbWVzKGRmVm9pc2lucylbMV0gPC0gcGFzdGUoIndobyIpCm5hbWVzKGRmVm9pc2lucylbMl0gPC0gcGFzdGUoImFnZSIpCm5hbWVzKGRmVm9pc2lucylbM10gPC0gcGFzdGUoInNleCIpCm5hbWVzKGRmVm9pc2lucylbNF0gPC0gcGFzdGUoImVkdSIpCgpuYW1lcyhkZk9waW5pb24pWzFdIDwtIHBhc3RlKCJ3aG8iKQpuYW1lcyhkZk9waW5pb24pWzJdIDwtIHBhc3RlKCJhZ2UiKQpuYW1lcyhkZk9waW5pb24pWzNdIDwtIHBhc3RlKCJzZXgiKQpuYW1lcyhkZk9waW5pb24pWzRdIDwtIHBhc3RlKCJlZHUiKQoKZ0RmQXBwYXJpZSA8LSBnYXRoZXIoZGF0YSA9IGRmQXBwYXJpZSwga2V5ID0gdGltZSwgdmFsdWU9IG5iLCAgYyg1OjM0KSkKZ0RmT3BpbmlvbiA8LSBnYXRoZXIoZGZPcGluaW9uLCB0aW1lLCBWYWx1ZU9waW5pb24sIGMoNTozNCkpCmdEZlZvaXNpbnMgPC0gZ2F0aGVyKGRmVm9pc2lucywgdGltZSwgbmJWb2lzaW5zLCBjKDU6MzQpKSAKCmdkZkZpbmFsIDwtIGpvaW4oZ0RmQXBwYXJpZSwgZ0RmT3BpbmlvbiwgYnk9Yygid2hvIiwiYWdlIiwic2V4IiwiZWR1IiwidGltZSIpLCB0eXBlPSJpbm5lciIpCmdkZkZpbmFsIDwtIGpvaW4oZ2RmRmluYWwsIGdEZlZvaXNpbnMsIGJ5PWMoIndobyIsImFnZSIsInNleCIsImVkdSIsInRpbWUiKSwgdHlwZT0iaW5uZXIiKQpnZGZGaW5hbCR0aW1lIDwtIGFzLm51bWVyaWMoZ2RmRmluYWwkdGltZSkKICAKI2dkRmluYWxTdWJzZXQgPC0gZ2RmRmluYWxbZ2RmRmluYWwkdGltZSA8IDIwLjAsXQoKZ2RGaW5hbEJ5QWdlX3ZhbHVlT3BpbmlvbiA8LSBnZGZGaW5hbCAlPiUgZ3JvdXBfYnkoYWdlLHRpbWUpICU+JQogIHN1bW1hcmlzZV9lYWNoKGZ1bnMobWVhbiksIFZhbHVlT3BpbmlvbikKCmdkRmluYWxCeVNleF92YWx1ZU9waW5pb24gPC0gZ2RmRmluYWwgJT4lIGdyb3VwX2J5KHNleCx0aW1lKSAlPiUKICBzdW1tYXJpc2VfZWFjaChmdW5zKG1lYW4pLCBWYWx1ZU9waW5pb24pCgpnZEZpbmFsQnlFZHVfdmFsdWVPcGluaW9uIDwtIGdkZkZpbmFsICU+JSBncm91cF9ieShlZHUsdGltZSkgJT4lCiAgc3VtbWFyaXNlX2VhY2goZnVucyhtZWFuKSwgVmFsdWVPcGluaW9uKQoKCmdkRmluYWxCeUFnZV9uYlZvaXNpbiA8LSBnZGZGaW5hbCAlPiUgZ3JvdXBfYnkoYWdlLHRpbWUpICU+JQogIHN1bW1hcmlzZV9lYWNoKGZ1bnMobWVhbiksIG5iVm9pc2lucykKCmdkRmluYWxCeVNleF9uYlZvaXNpbiA8LSBnZGZGaW5hbCAlPiUgZ3JvdXBfYnkoc2V4LHRpbWUpICU+JQogIHN1bW1hcmlzZV9lYWNoKGZ1bnMobWVhbiksIG5iVm9pc2lucykKCmdkRmluYWxCeUVkdV9uYlZvaXNpbiA8LSBnZGZGaW5hbCAlPiUgZ3JvdXBfYnkoZWR1LHRpbWUpICU+JQogIHN1bW1hcmlzZV9lYWNoKGZ1bnMobWVhbiksIG5iVm9pc2lucykKCgpnZEZpbmFsQnlBZ2VfYXBwYXJpZSA8LSBnZGZGaW5hbCAlPiUgZ3JvdXBfYnkoYWdlLHRpbWUpICU+JQogIHN1bW1hcmlzZV9lYWNoKGZ1bnMobWVhbiksIG5iKQoKZ2RGaW5hbEJ5U2V4X2FwcGFyaWUgPC0gZ2RmRmluYWwgJT4lIGdyb3VwX2J5KHNleCx0aW1lKSAlPiUKICBzdW1tYXJpc2VfZWFjaChmdW5zKG1lYW4pLCBuYikKCmdkRmluYWxCeUVkdV9hcHBhcmllIDwtIGdkZkZpbmFsICU+JSBncm91cF9ieShlZHUsdGltZSkgJT4lCiAgc3VtbWFyaXNlX2VhY2goZnVucyhtZWFuKSwgbmIpCmBgYAoKIyMjIFRPIExPTkcgREFUQSBBR0UKCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpnZGZGaW5hbEFnZSA8LSBtZXJnZShnZEZpbmFsQnlBZ2VfdmFsdWVPcGluaW9uLCBnZEZpbmFsQnlBZ2VfbmJWb2lzaW4sIGJ5PWMoImFnZSIsInRpbWUiKSwgdHlwZT0iaW5uZXIiKQpnZGZGaW5hbEFnZSA8LSBtZXJnZShnZGZGaW5hbEFnZSwgZ2RGaW5hbEJ5QWdlX2FwcGFyaWUsIGJ5PWMoImFnZSIsInRpbWUiKSwgdHlwZT0iaW5uZXIiKQoKZ0RmVG9Mb25nQWdlIDwtIGdhdGhlcihnZGZGaW5hbEFnZSwgZmFjdGV1ciwgdmFsdWUgLCBieT1jKFZhbHVlT3BpbmlvbixuYixuYlZvaXNpbnMpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1nRGZUb0xvbmdBZ2UsIGFlcyh4PXRpbWUsIHk9dmFsdWUsIGdyb3VwPWFnZSwgZmlsbD1hZ2UsIGNvbG91cj1hcy5jaGFyYWN0ZXIoYWdlKSkpCnAgPC0gcCArIGdlb21fbGluZShzaXplPTEpICsgZmFjZXRfZ3JpZChmYWN0ZXVyIH4gLikgI3Nob3cubGVnZW5kID0gRkFMU0UKcApgYGAKCiMjIyBUTyBMT05HIERBVEEgRURVCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KZ2RmRmluYWxFZHUgPC0gbWVyZ2UoZ2RGaW5hbEJ5RWR1X3ZhbHVlT3BpbmlvbiwgZ2RGaW5hbEJ5RWR1X25iVm9pc2luLCBieT1jKCJlZHUiLCAidGltZSIpLCB0eXBlPSJpbm5lciIpCmdkZkZpbmFsRWR1IDwtIG1lcmdlKGdkZkZpbmFsRWR1LCBnZEZpbmFsQnlFZHVfYXBwYXJpZSwgYnk9YygiZWR1IiwidGltZSIpLCB0eXBlPSJpbm5lciIpCgpnRGZUb0xvbmdFZHUgPC0gZ2F0aGVyKGdkZkZpbmFsRWR1LCBmYWN0ZXVyLCB2YWx1ZSAsIGJ5PWMoVmFsdWVPcGluaW9uLG5iLG5iVm9pc2lucykpCgpwIDwtIGdncGxvdChkYXRhPWdEZlRvTG9uZ0VkdSwgYWVzKHg9dGltZSwgeT12YWx1ZSwgZ3JvdXA9ZWR1LCBmaWxsPWVkdSwgY29sb3VyPWFzLmNoYXJhY3RlcihlZHUpKSkKcCA8LSBwICsgZ2VvbV9saW5lKHNpemU9MSkgKyBmYWNldF9ncmlkKGZhY3RldXIgfiAuKSAjc2hvdy5sZWdlbmQgPSBGQUxTRQpwCmBgYAoKIyMjIFRPIExPTkcgREFUQSBTRVgKCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpnZGZGaW5hbFNleCA8LSBtZXJnZShnZEZpbmFsQnlTZXhfdmFsdWVPcGluaW9uLCBnZEZpbmFsQnlTZXhfbmJWb2lzaW4sIGJ5PWMoInNleCIsICJ0aW1lIiksIHR5cGU9ImlubmVyIikKZ2RmRmluYWxTZXggPC0gbWVyZ2UoZ2RmRmluYWxTZXgsIGdkRmluYWxCeVNleF9hcHBhcmllLCBieT1jKCJzZXgiLCJ0aW1lIiksIHR5cGU9ImlubmVyIikKCmdEZlRvTG9uZ1NleCA8LSBnYXRoZXIoZ2RmRmluYWxTZXgsIGZhY3RldXIsIHZhbHVlICwgYnk9YyhWYWx1ZU9waW5pb24sbmIsbmJWb2lzaW5zKSkKCnAgPC0gZ2dwbG90KGRhdGE9Z0RmVG9Mb25nU2V4LCBhZXMoeD10aW1lLCB5PXZhbHVlLCBncm91cD1zZXgsIGZpbGw9c2V4LCBjb2xvdXI9YXMuY2hhcmFjdGVyKHNleCkpKQpwIDwtIHAgKyBnZW9tX2xpbmUoc2l6ZT0xKSArIGZhY2V0X2dyaWQoZmFjdGV1ciB+IC4pICNzaG93LmxlZ2VuZCA9IEZBTFNFCnAKYGBgCgojIEZBVCBNT0RFTCAKCmBgYHtyfQoKc3BlY2lhbFJlYWQgPC0gZnVuY3Rpb24oeCkgewogIHJlYWRfY3N2KGZpbGU9eCwgY29sX25hbWVzID0gVFJVRSwgY29sX3R5cGVzPSAibm5ubm5ubm5ubiIpCn0gCgpjb25jYXRGaWxlcyA8LSBmdW5jdGlvbiAoYmFzZSwgZm9sZGVyKXsKICAgZnVsbFBhdGggPSBwYXN0ZShiYXNlLGZvbGRlcixzZXA9IiIpCiAgIGxpc3QuZmlsZXMocGF0aCA9IGZ1bGxQYXRoLCBmdWxsLm5hbWVzID0gVFJVRSwgcGF0dGVybiA9ICIoXFxkX1xcZF9cXGQpIikgJT4lIGxhcHBseShzcGVjaWFsUmVhZCkgJT4lIGJpbmRfcm93cwp9CgpgYGAKCiMjIEV4cGxvcmluZyBzY2VuYXJpaQoKIyByYW5kb20gcmVzaWRlbnRpYWwgc2NlbmFyaW8gMQoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIG1heFByb2JhVG9Td2l0Y2ggICAgY29uc3RyYWludHNTdHJlbmd0aCAgICAgICAgIGluZXJ0aWFDb2VmZmljaWVudCAgICAgICAgIGhlYWx0aHlEaWV0UmV3YXJkICAgICAgICAgc2VlZAotLS0tLS0tLS0tLS0tLS0tLSAgICAtLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0gICAgICAgICAtLS0tCjAuOCAgICAgICAgICAgICAgICAgIDAuMDUgICAgICAgICAgICAgICAgICAgICAgICAgMC41ICAgICAgICAgICAgICAgICAgICAgICAgMC40ICAgICAgICAgICAgICAgICAgICAgICA0MgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKUkFORE9NIFBPUCBOTyBNT1ZFIFNFRUQgNDIKCmBgYHtyLCBmaWcud2lkdGg9MjB9CnNvcnRpZV9zYzEgPC0gY29uY2F0RmlsZXMoYmFzZSwicmVzdWx0c19vc2VfU2NlbmFyaW8xX1JhbmRvbVBvcF9Ob01vdmVfNDIiKQoKc29ydGllX3NjMSRwcm9wSGVhbHRoeSA8LSBzb3J0aWVfc2MxJGhlYWx0aHkgLyBzb3J0aWVfc2MxJGVmZmVjdGl2ZSAKICAKc29ydGllTG9uZ19zYzEgPC0gZ2F0aGVyKHNvcnRpZV9zYzEsIGZhY3RldXIsIHZhbGV1ciwgYnk9Yyhwcm9wSGVhbHRoeSxhdmdPcGluaW9uKSApIAoKc29ydGllTG9uZ19zYzEgPC0gbXV0YXRlKHNvcnRpZUxvbmdfc2MxLCAiZHMiID0gZ3N1YigiICIsICIiLCBwYXN0ZShwYXN0ZSgiWyIscGFzdGUoc29ydGllTG9uZ19zYzEkZGF5LCBzb3J0aWVMb25nX3NjMSRzbGljZSkpLCJdIikpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1zb3J0aWVMb25nX3NjMSwgYWVzKHg9ZHMsIHk9dmFsZXVyLCBncm91cD1lZHVjLCBmaWxsPWVkdWMsIGNvbG91cj1hcy5jaGFyYWN0ZXIoZWR1YykpKQpwIDwtIHAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCnAgPC0gcCArIGdlb21fbGluZShzaXplPTAuNSkgKyBmYWNldF9ncmlkKGZhY3RldXIgfiBzZXggfiBhZ2UsIGxhYmVsbGVyID0gbGFiZWxfYm90aCkgI3Nob3cubGVnZW5kID0gRkFMU0UKcApnZ3NhdmUoInNjMV9yYW5kb21Qb3Bfbm9Nb3ZlLnBkZiIpCmBgYAoKIyBzdXJ2ZXkgcmVzaWRlbnRpYWwgc2NlbmFyaW8gMgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIG1heFByb2JhVG9Td2l0Y2ggICAgY29uc3RyYWludHNTdHJlbmd0aCAgICAgICAgIGluZXJ0aWFDb2VmZmljaWVudCAgICAgICAgIGhlYWx0aHlEaWV0UmV3YXJkICAgICAgICAgc2VlZAotLS0tLS0tLS0tLS0tLS0tLSAgICAtLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0gICAgICAgICAtLS0tCjAuOCAgICAgICAgICAgICAgICAgIDAuMDUgICAgICAgICAgICAgICAgICAgICAgICAgMC41ICAgICAgICAgICAgICAgICAgICAgICAgMC40ICAgICAgICAgICAgICAgICAgICAgICA0MgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCgpgYGB7ciwgZmlnLndpZHRoPTIwfQpzb3J0aWVfc2MyIDwtIGNvbmNhdEZpbGVzKGJhc2UsInJlc3VsdHNfb3NlX1NjZW5hcmlvMl9SYW5kb21Qb3BfUmFuZG9tTW92ZV80MiIpCgpzb3J0aWVfc2MyJHByb3BIZWFsdGh5IDwtIHNvcnRpZV9zYzIkaGVhbHRoeSAvIHNvcnRpZV9zYzIkZWZmZWN0aXZlIAogIApzb3J0aWVMb25nX3NjMiA8LSBnYXRoZXIoc29ydGllX3NjMiwgZmFjdGV1ciwgdmFsZXVyLCBieT1jKHByb3BIZWFsdGh5LGF2Z09waW5pb24pICkgCgpzb3J0aWVMb25nX3NjMiA8LSBtdXRhdGUoc29ydGllTG9uZ19zYzIsICJkcyIgPSBnc3ViKCIgIiwgIiIsIHBhc3RlKHBhc3RlKCJbIixwYXN0ZShzb3J0aWVMb25nX3NjMiRkYXksIHNvcnRpZUxvbmdfc2MyJHNsaWNlKSksIl0iKSkpCgpwIDwtIGdncGxvdChkYXRhPXNvcnRpZUxvbmdfc2MyLCBhZXMoeD1kcywgeT12YWxldXIsIGdyb3VwPWVkdWMsIGZpbGw9ZWR1YywgY29sb3VyPWFzLmNoYXJhY3RlcihlZHVjKSkpCnAgPC0gcCArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSkKcCA8LSBwICsgZ2VvbV9saW5lKHNpemU9MC41KSArIGZhY2V0X2dyaWQoZmFjdGV1ciB+IHNleCB+IGFnZSwgbGFiZWxsZXIgPSBsYWJlbF9ib3RoKSAjc2hvdy5sZWdlbmQgPSBGQUxTRQpwCmdnc2F2ZSgic2MyX3JhbmRvbVBvcF9yYW5kb21Nb3ZlLnBkZiIpCgpgYGAKCiMgcmFuZG9tIGFjdGl2aXR5IHNjZW5hcmlvIDMKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiBtYXhQcm9iYVRvU3dpdGNoICAgIGNvbnN0cmFpbnRzU3RyZW5ndGggICAgICAgICBpbmVydGlhQ29lZmZpY2llbnQgICAgICAgICBoZWFsdGh5RGlldFJld2FyZCAgICAgICAgIHNlZWQKLS0tLS0tLS0tLS0tLS0tLS0gICAgLS0tLS0tLS0tLS0tLS0tLS0tLSAgICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLSAgICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tICAgICAgICAgLS0tLQowLjggICAgICAgICAgICAgICAgICAwLjUgICAgICAgICAgICAgICAgICAgICAgICAgMC41ICAgICAgICAgICAgICAgICAgICAgICAgMC40ICAgICAgICAgICAgICAgICAgICAgICA0MgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKYGBge3IsIGZpZy53aWR0aD0yMH0Kc29ydGllX3NjMyA8LSBjb25jYXRGaWxlcyhiYXNlLCJyZXN1bHRzX29zZV9TY2VuYXJpbzNfT2JzZXJ2ZWRQb3BfTm9Nb3ZlXzQyIikKc29ydGllX3NjMyRwcm9wSGVhbHRoeSA8LSBzb3J0aWVfc2MzJGhlYWx0aHkgLyBzb3J0aWVfc2MzJGVmZmVjdGl2ZSAKICAKc29ydGllTG9uZ19zYzMgPC0gZ2F0aGVyKHNvcnRpZV9zYzMsIGZhY3RldXIsIHZhbGV1ciwgYnk9Yyhwcm9wSGVhbHRoeSxhdmdPcGluaW9uKSApIAoKc29ydGllTG9uZ19zYzMgPC0gbXV0YXRlKHNvcnRpZUxvbmdfc2MzLCAiZHMiID0gZ3N1YigiICIsICIiLCBwYXN0ZShwYXN0ZSgiWyIscGFzdGUoc29ydGllTG9uZ19zYzMkZGF5LCBzb3J0aWVMb25nX3NjMyRzbGljZSkpLCJdIikpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1zb3J0aWVMb25nX3NjMywgYWVzKHg9ZHMsIHk9dmFsZXVyLCBncm91cD1lZHVjLCBmaWxsPWVkdWMsIGNvbG91cj1hcy5jaGFyYWN0ZXIoZWR1YykpKQpwIDwtIHAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCnAgPC0gcCArIGdlb21fbGluZShzaXplPTAuNSkgKyBmYWNldF9ncmlkKGZhY3RldXIgfiBzZXggfiBhZ2UsIGxhYmVsbGVyID0gbGFiZWxfYm90aCkgI3Nob3cubGVnZW5kID0gRkFMU0UKcApnZ3NhdmUoInNjM19vYnNQb3Bfbm9Nb3ZlLnBkZiIpCgpgYGAKCiMgc3VydmV5IGFjdGl2aXR5IHNjZW5hcmlvIDQKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiBtYXhQcm9iYVRvU3dpdGNoICAgIGNvbnN0cmFpbnRzU3RyZW5ndGggICAgICAgICBpbmVydGlhQ29lZmZpY2llbnQgICAgICAgICBoZWFsdGh5RGlldFJld2FyZCAgICAgICAgIHNlZWQKLS0tLS0tLS0tLS0tLS0tLS0gICAgLS0tLS0tLS0tLS0tLS0tLS0tLSAgICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLSAgICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tICAgICAgICAgLS0tLQowLjggICAgICAgICAgICAgICAgICAwLjA1ICAgICAgICAgICAgICAgICAgICAgICAgMC41ICAgICAgICAgICAgICAgICAgICAgICAgMC40ICAgICAgICAgICAgICAgICAgICAgICA0MgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKYGBge3IsIGZpZy53aWR0aD0yMH0Kc29ydGllX3NjNCA8LSBjb25jYXRGaWxlcyhiYXNlLCJyZXN1bHRzX29zZV9TY2VuYXJpbzRfT2JzZXJ2ZWRQb3BfUmFuZG9tTW92ZV80MiIpCnNvcnRpZV9zYzQkcHJvcEhlYWx0aHkgPC0gc29ydGllX3NjNCRoZWFsdGh5IC8gc29ydGllX3NjNCRlZmZlY3RpdmUgCiAgCnNvcnRpZUxvbmdfc2M0IDwtIGdhdGhlcihzb3J0aWVfc2M0LCBmYWN0ZXVyLCB2YWxldXIsIGJ5PWMocHJvcEhlYWx0aHksYXZnT3BpbmlvbikgKSAKc29ydGllTG9uZ19zYzQgPC0gbXV0YXRlKHNvcnRpZUxvbmdfc2M0LCAiZHMiID0gZ3N1YigiICIsICIiLCBwYXN0ZShwYXN0ZSgiWyIscGFzdGUoc29ydGllTG9uZ19zYzQkZGF5LCBzb3J0aWVMb25nX3NjNCRzbGljZSkpLCJdIikpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1zb3J0aWVMb25nX3NjNCwgYWVzKHg9ZHMsIHk9dmFsZXVyLCBncm91cD1lZHVjLCBmaWxsPWVkdWMsIGNvbG91cj1hcy5jaGFyYWN0ZXIoZWR1YykpKQpwIDwtIHAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCnAgPC0gcCArIGdlb21fbGluZShzaXplPTAuNSkgKyBmYWNldF9ncmlkKGZhY3RldXIgfiBzZXggfiBhZ2UsIGxhYmVsbGVyID0gbGFiZWxfYm90aCkgI3Nob3cubGVnZW5kID0gRkFMU0UKcApnZ3NhdmUoInNjNF9vYnNQb3BfcmFuZG9tTW92ZS5wZGYiKQoKYGBgCgojIHN1cnZleSBhY3Rpdml0eSBzY2VuYXJpbyA0CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogbWF4UHJvYmFUb1N3aXRjaCAgICBjb25zdHJhaW50c1N0cmVuZ3RoICAgICAgICAgaW5lcnRpYUNvZWZmaWNpZW50ICAgICAgICAgaGVhbHRoeURpZXRSZXdhcmQgICAgICAgICBzZWVkCi0tLS0tLS0tLS0tLS0tLS0tICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0gICAgICAgICAtLS0tLS0tLS0tLS0tLS0tLS0gICAgICAgICAtLS0tLS0tLS0tLS0tLS0tLSAgICAgICAgIC0tLS0KMC44ICAgICAgICAgICAgICAgICAgMC4wNSAgICAgICAgICAgICAgICAgICAgICAgIDAuNSAgICAgICAgICAgICAgICAgICAgICAgIDAuNCAgICAgICAgICAgICAgICAgICAgICAgNDIKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyLCBmaWcud2lkdGg9MjB9CnNvcnRpZV9zYzUgPC0gY29uY2F0RmlsZXMoYmFzZSwicmVzdWx0c19vc2VfU2NlbmFyaW81X09ic2VydmVkUG9wX09ic2VydmVkTW92ZV80MiIpCnNvcnRpZV9zYzUkcHJvcEhlYWx0aHkgPC0gc29ydGllX3NjNSRoZWFsdGh5IC8gc29ydGllX3NjNSRlZmZlY3RpdmUgCiAgCnNvcnRpZUxvbmdfc2M1IDwtIGdhdGhlcihzb3J0aWVfc2M1LCBmYWN0ZXVyLCB2YWxldXIsIGJ5PWMocHJvcEhlYWx0aHksYXZnT3BpbmlvbikgKSAKc29ydGllTG9uZ19zYzUgPC0gbXV0YXRlKHNvcnRpZUxvbmdfc2M1LCAiZHMiID0gZ3N1YigiICIsICIiLCBwYXN0ZShwYXN0ZSgiWyIscGFzdGUoc29ydGllTG9uZ19zYzUkZGF5LCBzb3J0aWVMb25nX3NjNSRzbGljZSkpLCJdIikpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1zb3J0aWVMb25nX3NjNSwgYWVzKHg9ZHMsIHk9dmFsZXVyLCBncm91cD1lZHVjLCBmaWxsPWVkdWMsIGNvbG91cj1hcy5jaGFyYWN0ZXIoZWR1YykpKQpwIDwtIHAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCnAgPC0gcCArIGdlb21fbGluZShzaXplPTAuNSkgKyBmYWNldF9ncmlkKGZhY3RldXIgfiBzZXggfiBhZ2UsIGxhYmVsbGVyID0gbGFiZWxfYm90aCkgI3Nob3cubGVnZW5kID0gRkFMU0UKcApnZ3NhdmUoInNjNV9vYnNQb3Bfb2JzTW92ZS5wZGYiKQoKYGBgCgo=