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

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

plot(cars)

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

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

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

ls()
#rm(dane)
rm(list=ls())


m <- matrix(1:9, ncol=3, byrow = TRUE)
m
str(m)

m1 <- cbind(m,10:12)
m1
m2 <- rbind(m1, 13:16)
m2

2*m
lapply(m, str)
#sapply, vapply

outer(1:2,3:5, "*")
outer(c(TRUE,FALSE,NA), c(TRUE,FALSE),"&")

m
m[2,1]
#m[3,4]
typeof(m)
m[2,2] <- 1L

#macierz[wiersz,kolumna]
m
m[2:3,]
m[,]

m[1,,drop=FALSE]


a <- array(1:24, dim=c(2,4,3))
a
str(a)

dimnames(a) <- list(c("p1","p2"),c("q1","q2","q3","q4"),c("r1","r2","r3"))
a

class(m);mode(m);is.matrix(m);is.array(m)
class(a);mode(a);is.matrix(a);is.array(a)


m
#sum(m)
t(m)
isSymmetric(m*t(m))
m*t(m)

m3 <- matrix(9:1, ncol=3)
m
m3
m*m3
m %*% m3

i <- matrix(c(1,0,0, 0,1,0, 0,0,1), ncol=3)
i
i %*% i

i %*% m
m %*% i


#Obroty 2D
w <- c(0,1)
w
kat <- pi/4
o <- matrix(c(cos(kat), sin(kat),  -sin(kat), cos(kat)), ncol=2)
o
w1 <- o %*% w

#Skalowanie x=2, y=0.5
s <- matrix(c(2,0, 0,0.5), ncol=2)
s
s %*% w1

d <- diag(c(1,2,3))
d
diag(nrow=3)

m
diag(m)
diag(m) <- 0

tr <- function(m) {return(sum(diag(m)))}
tr(m)

m
apply(a,1:2,sum)
l <- c("pn", "wt", "śr", "cz", "pt", "so", "n")
dni <- factor(c("pn", "wt", "śr", "pn", "so", "so", "pn", "śr", "cz"), levels=l, ordered=TRUE)
dni
is.vector(dni)
str(dni)

v <- sample(0:9, 100, TRUE)
v
str(v)
f <- factor(v)
f
str(f)
as.vector(f)
as.integer(f)

dni
which(dni == "pn")

f
length(which(f==1))

dni
droplevels(dni)

v
cut(v, c("0","3","6","9"))

split(v, f)

dni
summary(dni)
#Data.frames

wyniki <- data.frame(
  id = c(1,2,3,4,5),
  plec = c("M", "K", "K", "M", "K"),
  wzrost=c(181,176,165,156,179),
  waga=c(107,71,68,71,89),
  stringsAsFactors = TRUE
)
wyniki
str(wyniki)
print(wyniki)
as.matrix(wyniki)

wyniki$plec

is.data.frame(wyniki)
typeof(wyniki)
is.list(wyniki)
attributes(wyniki)
dim(wyniki)
dimnames(wyniki)
row.names(wyniki)
colnames(wyniki)
names(wyniki)

row.names(wyniki) <- c("A","B","C","D","E")
wyniki
as.matrix(wyniki)
wyniki$plec
wyniki[[2]]
wyniki[2]
wyniki$plec[3]
subset(wyniki, wzrost>170 & plec=="K")
subset(wyniki, select=c(plec, wzrost))
subset(wyniki, select=-plec)

wyniki$waga <- wyniki$waga-10

wyniki2 <- cbind(wyniki, wiek=c(47,47,20,15,18))
wyniki2

split(wyniki, wyniki$plec)

wyniki_wiek <- data.frame(
  id = c(1,2,3,4,6),
  wiek = c(47,47,20,15,18)
)
wyniki_wiek
wyniki

wyniki3 <- merge(wyniki,wyniki_wiek, all.x = FALSE,all.y=FALSE)
wyniki3

#sortowanie
wyniki[order(wyniki$waga, wyniki$wzrost, decreasing = TRUE),]

head(wyniki)
tail(wyniki)

filePath <- "wyniki.csv"
write.table(wyniki, filePath, row.names=TRUE, eol="\n",sep=";",dec=",")

wyniki4 <- read.csv(filePath, sep=";", dec=",", header=FALSE, skip=2)
wyniki4
str(wyniki4)
dane1 <- read.csv("1.csv", sep=";", dec=",")
dim(dane1)
str(dane1)

levels(dane1$ButtonsLayoutType)
dane1$DemoMode
dane2 <- dane1[dane1$DemoMode != "True",]
is.numeric(dane2$CzasOstatniejCyfryMs)
is.numeric(dane2$CzasPierwszejCyfryMs)
is.numeric(dane2$CzasWpisywaniaMs)
czasWpisywania <- dane2$CzasOstatniejCyfryMs - dane2$CzasPierwszejCyfryMs
czasWpisywania
dane3 <- cbind(dane2, czasWpisywania2 = czasWpisywania)
max(abs(dane3$czasWpisywania2-dane3$CzasWpisywaniaMs))
dane3$GazeControlType
dane4 <- split(dane3, levels(dane3$GazeControlType))
names(dane4)
plot(dane4$DwellTime$CzasWpisywaniaMs, col="red")
points(dane4$Fixation$CzasWpisywaniaMs, col="green")
points(dane4$EnterAndLeavePositions$CzasWpisywaniaMs, col="blue")

mean(dane4$DwellTime$CzasWpisywaniaMs);sd(dane4$DwellTime$CzasWpisywaniaMs)
mean(dane4$Fixation$CzasWpisywaniaMs);sd(dane4$Fixation$CzasWpisywaniaMs)
mean(dane4$EnterAndLeavePositions$CzasWpisywaniaMs);sd(dane4$EnterAndLeavePositions$CzasWpisywaniaMs)

gornyLimit <- mean(dane4$DwellTime$CzasWpisywaniaMs) + 2*sd(dane4$DwellTime$CzasWpisywaniaMs)
gornyLimit

nrow(dane4$DwellTime)
dane5 <- dane4$DwellTime[dane4$DwellTime$CzasWpisywaniaMs < gornyLimit,]
dane4$DwellTime$CzasWpisywaniaMs < gornyLimit

plot(dane5$CzasWpisywaniaMs, col="red")
mean(dane5$CzasWpisywaniaMs);sd(dane5$CzasWpisywaniaMs)

shapiro.test(dane5$CzasWpisywaniaMs)
shapiro.test(dane4$DwellTime$CzasWpisywaniaMs)

png("czasWpisywania.png")
plot(dane5$CzasWpisywaniaMs, col="red")
dev.off()
oblicz.srednie.czasy.wpisywania <- function(filename)
{
  stopifnot(file.exists(filename))
  on.exit(print(paste("Zakończone przetwarzanie pliku ",filename), quote=FALSE))
  print(paste("Przetwarzam plik ",filename), quote=FALSE)
  dane1 <- read.csv(filename, sep=";", dec=",")
  dane2 <- dane1[dane1$DemoMode != "True",]
  stopifnot(is.numeric(dane2$CzasOstatniejCyfryMs))
  stopifnot(is.numeric(dane2$CzasPierwszejCyfryMs))
  stopifnot(is.numeric(dane2$CzasWpisywaniaMs))
  czasWpisywania <- dane2$CzasOstatniejCyfryMs - dane2$CzasPierwszejCyfryMs
  dane4 <- split(dane2, levels(dane2$GazeControlType))
  result <- c(
    dwelltime_meantime = mean(dane4$DwellTime$CzasWpisywaniaMs),
    dwelltime_sd = sd(dane4$DwellTime$CzasWpisywaniaMs),
    fixation_meantime = mean(dane4$Fixation$CzasWpisywaniaMs),
    fixation_sd = sd(dane4$Fixation$CzasWpisywaniaMs),
    eal_meantime = mean(dane4$EnterAndLeavePositions$CzasWpisywaniaMs),
    eal_sd = sd(dane4$EnterAndLeavePositions$CzasWpisywaniaMs)
  )
  return(result)
}

oblicz.srednie.czasy.wpisywania("1.csv")


normalizePath("1.csv")
basename("1.csv")
basename(normalizePath("1.csv"))
normalizePath(dirname("1.csv"))
tempdir()
tempfile()
getwd()
file.exists("1.csv")
file.info("1.csv")

pliki <- list.files(getwd(), pattern = "*.csv", full.names = TRUE)
pliki
oblicz.srednie.czasy.wpisywania(pliki[1])

wyniki2 <- lapply(pliki, oblicz.srednie.czasy.wpisywania)
wyniki2
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCg0KYGBge3J9DQpwbG90KGNhcnMpDQpgYGANCg0KQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLg0KDQpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4NCg0KVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLg0KDQpgYGB7cn0NCmxzKCkNCiNybShkYW5lKQ0Kcm0obGlzdD1scygpKQ0KDQoNCm0gPC0gbWF0cml4KDE6OSwgbmNvbD0zLCBieXJvdyA9IFRSVUUpDQptDQpzdHIobSkNCg0KbTEgPC0gY2JpbmQobSwxMDoxMikNCm0xDQptMiA8LSByYmluZChtMSwgMTM6MTYpDQptMg0KDQoyKm0NCmxhcHBseShtLCBzdHIpDQojc2FwcGx5LCB2YXBwbHkNCg0Kb3V0ZXIoMToyLDM6NSwgIioiKQ0Kb3V0ZXIoYyhUUlVFLEZBTFNFLE5BKSwgYyhUUlVFLEZBTFNFKSwiJiIpDQoNCm0NCm1bMiwxXQ0KI21bMyw0XQ0KdHlwZW9mKG0pDQptWzIsMl0gPC0gMUwNCg0KI21hY2llcnpbd2llcnN6LGtvbHVtbmFdDQptDQptWzI6MyxdDQptWyxdDQoNCm1bMSwsZHJvcD1GQUxTRV0NCg0KDQphIDwtIGFycmF5KDE6MjQsIGRpbT1jKDIsNCwzKSkNCmENCnN0cihhKQ0KDQpkaW1uYW1lcyhhKSA8LSBsaXN0KGMoInAxIiwicDIiKSxjKCJxMSIsInEyIiwicTMiLCJxNCIpLGMoInIxIiwicjIiLCJyMyIpKQ0KYQ0KDQpjbGFzcyhtKTttb2RlKG0pO2lzLm1hdHJpeChtKTtpcy5hcnJheShtKQ0KY2xhc3MoYSk7bW9kZShhKTtpcy5tYXRyaXgoYSk7aXMuYXJyYXkoYSkNCg0KDQptDQojc3VtKG0pDQp0KG0pDQppc1N5bW1ldHJpYyhtKnQobSkpDQptKnQobSkNCg0KbTMgPC0gbWF0cml4KDk6MSwgbmNvbD0zKQ0KbQ0KbTMNCm0qbTMNCm0gJSolIG0zDQoNCmkgPC0gbWF0cml4KGMoMSwwLDAsIDAsMSwwLCAwLDAsMSksIG5jb2w9MykNCmkNCmkgJSolIGkNCg0KaSAlKiUgbQ0KbSAlKiUgaQ0KDQoNCiNPYnJvdHkgMkQNCncgPC0gYygwLDEpDQp3DQprYXQgPC0gcGkvNA0KbyA8LSBtYXRyaXgoYyhjb3Moa2F0KSwgc2luKGthdCksICAtc2luKGthdCksIGNvcyhrYXQpKSwgbmNvbD0yKQ0Kbw0KdzEgPC0gbyAlKiUgdw0KDQojU2thbG93YW5pZSB4PTIsIHk9MC41DQpzIDwtIG1hdHJpeChjKDIsMCwgMCwwLjUpLCBuY29sPTIpDQpzDQpzICUqJSB3MQ0KDQpkIDwtIGRpYWcoYygxLDIsMykpDQpkDQpkaWFnKG5yb3c9MykNCg0KbQ0KZGlhZyhtKQ0KZGlhZyhtKSA8LSAwDQoNCnRyIDwtIGZ1bmN0aW9uKG0pIHtyZXR1cm4oc3VtKGRpYWcobSkpKX0NCnRyKG0pDQoNCm0NCmFwcGx5KGEsMToyLHN1bSkNCmBgYA0KDQpgYGB7cn0NCmwgPC0gYygicG4iLCAid3QiLCAixZtyIiwgImN6IiwgInB0IiwgInNvIiwgIm4iKQ0KZG5pIDwtIGZhY3RvcihjKCJwbiIsICJ3dCIsICLFm3IiLCAicG4iLCAic28iLCAic28iLCAicG4iLCAixZtyIiwgImN6IiksIGxldmVscz1sLCBvcmRlcmVkPVRSVUUpDQpkbmkNCmlzLnZlY3RvcihkbmkpDQpzdHIoZG5pKQ0KDQp2IDwtIHNhbXBsZSgwOjksIDEwMCwgVFJVRSkNCnYNCnN0cih2KQ0KZiA8LSBmYWN0b3IodikNCmYNCnN0cihmKQ0KYXMudmVjdG9yKGYpDQphcy5pbnRlZ2VyKGYpDQoNCmRuaQ0Kd2hpY2goZG5pID09ICJwbiIpDQoNCmYNCmxlbmd0aCh3aGljaChmPT0xKSkNCg0KZG5pDQpkcm9wbGV2ZWxzKGRuaSkNCg0Kdg0KY3V0KHYsIGMoIjAiLCIzIiwiNiIsIjkiKSkNCg0Kc3BsaXQodiwgZikNCg0KZG5pDQpzdW1tYXJ5KGRuaSkNCmBgYA0KDQpgYGB7cn0NCiNEYXRhLmZyYW1lcw0KDQp3eW5pa2kgPC0gZGF0YS5mcmFtZSgNCiAgaWQgPSBjKDEsMiwzLDQsNSksDQogIHBsZWMgPSBjKCJNIiwgIksiLCAiSyIsICJNIiwgIksiKSwNCiAgd3pyb3N0PWMoMTgxLDE3NiwxNjUsMTU2LDE3OSksDQogIHdhZ2E9YygxMDcsNzEsNjgsNzEsODkpLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRQ0KKQ0Kd3luaWtpDQpzdHIod3luaWtpKQ0KcHJpbnQod3luaWtpKQ0KYXMubWF0cml4KHd5bmlraSkNCg0Kd3luaWtpJHBsZWMNCg0KaXMuZGF0YS5mcmFtZSh3eW5pa2kpDQp0eXBlb2Yod3luaWtpKQ0KaXMubGlzdCh3eW5pa2kpDQphdHRyaWJ1dGVzKHd5bmlraSkNCmRpbSh3eW5pa2kpDQpkaW1uYW1lcyh3eW5pa2kpDQpyb3cubmFtZXMod3luaWtpKQ0KY29sbmFtZXMod3luaWtpKQ0KbmFtZXMod3luaWtpKQ0KDQpyb3cubmFtZXMod3luaWtpKSA8LSBjKCJBIiwiQiIsIkMiLCJEIiwiRSIpDQp3eW5pa2kNCmFzLm1hdHJpeCh3eW5pa2kpDQp3eW5pa2kkcGxlYw0Kd3luaWtpW1syXV0NCnd5bmlraVsyXQ0Kd3luaWtpJHBsZWNbM10NCnN1YnNldCh3eW5pa2ksIHd6cm9zdD4xNzAgJiBwbGVjPT0iSyIpDQpzdWJzZXQod3luaWtpLCBzZWxlY3Q9YyhwbGVjLCB3enJvc3QpKQ0Kc3Vic2V0KHd5bmlraSwgc2VsZWN0PS1wbGVjKQ0KDQp3eW5pa2kkd2FnYSA8LSB3eW5pa2kkd2FnYS0xMA0KDQp3eW5pa2kyIDwtIGNiaW5kKHd5bmlraSwgd2llaz1jKDQ3LDQ3LDIwLDE1LDE4KSkNCnd5bmlraTINCg0Kc3BsaXQod3luaWtpLCB3eW5pa2kkcGxlYykNCg0Kd3luaWtpX3dpZWsgPC0gZGF0YS5mcmFtZSgNCiAgaWQgPSBjKDEsMiwzLDQsNiksDQogIHdpZWsgPSBjKDQ3LDQ3LDIwLDE1LDE4KQ0KKQ0Kd3luaWtpX3dpZWsNCnd5bmlraQ0KDQp3eW5pa2kzIDwtIG1lcmdlKHd5bmlraSx3eW5pa2lfd2llaywgYWxsLnggPSBGQUxTRSxhbGwueT1GQUxTRSkNCnd5bmlraTMNCg0KI3NvcnRvd2FuaWUNCnd5bmlraVtvcmRlcih3eW5pa2kkd2FnYSwgd3luaWtpJHd6cm9zdCwgZGVjcmVhc2luZyA9IFRSVUUpLF0NCg0KaGVhZCh3eW5pa2kpDQp0YWlsKHd5bmlraSkNCg0KZmlsZVBhdGggPC0gInd5bmlraS5jc3YiDQp3cml0ZS50YWJsZSh3eW5pa2ksIGZpbGVQYXRoLCByb3cubmFtZXM9VFJVRSwgZW9sPSJcbiIsc2VwPSI7IixkZWM9IiwiKQ0KDQp3eW5pa2k0IDwtIHJlYWQuY3N2KGZpbGVQYXRoLCBzZXA9IjsiLCBkZWM9IiwiLCBoZWFkZXI9RkFMU0UsIHNraXA9MikNCnd5bmlraTQNCnN0cih3eW5pa2k0KQ0KYGBgDQpgYGB7cn0NCmRhbmUxIDwtIHJlYWQuY3N2KCIxLmNzdiIsIHNlcD0iOyIsIGRlYz0iLCIpDQpkaW0oZGFuZTEpDQpzdHIoZGFuZTEpDQoNCmxldmVscyhkYW5lMSRCdXR0b25zTGF5b3V0VHlwZSkNCmRhbmUxJERlbW9Nb2RlDQpkYW5lMiA8LSBkYW5lMVtkYW5lMSREZW1vTW9kZSAhPSAiVHJ1ZSIsXQ0KaXMubnVtZXJpYyhkYW5lMiRDemFzT3N0YXRuaWVqQ3lmcnlNcykNCmlzLm51bWVyaWMoZGFuZTIkQ3phc1BpZXJ3c3plakN5ZnJ5TXMpDQppcy5udW1lcmljKGRhbmUyJEN6YXNXcGlzeXdhbmlhTXMpDQpjemFzV3Bpc3l3YW5pYSA8LSBkYW5lMiRDemFzT3N0YXRuaWVqQ3lmcnlNcyAtIGRhbmUyJEN6YXNQaWVyd3N6ZWpDeWZyeU1zDQpjemFzV3Bpc3l3YW5pYQ0KZGFuZTMgPC0gY2JpbmQoZGFuZTIsIGN6YXNXcGlzeXdhbmlhMiA9IGN6YXNXcGlzeXdhbmlhKQ0KbWF4KGFicyhkYW5lMyRjemFzV3Bpc3l3YW5pYTItZGFuZTMkQ3phc1dwaXN5d2FuaWFNcykpDQpkYW5lMyRHYXplQ29udHJvbFR5cGUNCmRhbmU0IDwtIHNwbGl0KGRhbmUzLCBsZXZlbHMoZGFuZTMkR2F6ZUNvbnRyb2xUeXBlKSkNCm5hbWVzKGRhbmU0KQ0KcGxvdChkYW5lNCREd2VsbFRpbWUkQ3phc1dwaXN5d2FuaWFNcywgY29sPSJyZWQiKQ0KcG9pbnRzKGRhbmU0JEZpeGF0aW9uJEN6YXNXcGlzeXdhbmlhTXMsIGNvbD0iZ3JlZW4iKQ0KcG9pbnRzKGRhbmU0JEVudGVyQW5kTGVhdmVQb3NpdGlvbnMkQ3phc1dwaXN5d2FuaWFNcywgY29sPSJibHVlIikNCg0KbWVhbihkYW5lNCREd2VsbFRpbWUkQ3phc1dwaXN5d2FuaWFNcyk7c2QoZGFuZTQkRHdlbGxUaW1lJEN6YXNXcGlzeXdhbmlhTXMpDQptZWFuKGRhbmU0JEZpeGF0aW9uJEN6YXNXcGlzeXdhbmlhTXMpO3NkKGRhbmU0JEZpeGF0aW9uJEN6YXNXcGlzeXdhbmlhTXMpDQptZWFuKGRhbmU0JEVudGVyQW5kTGVhdmVQb3NpdGlvbnMkQ3phc1dwaXN5d2FuaWFNcyk7c2QoZGFuZTQkRW50ZXJBbmRMZWF2ZVBvc2l0aW9ucyRDemFzV3Bpc3l3YW5pYU1zKQ0KDQpnb3JueUxpbWl0IDwtIG1lYW4oZGFuZTQkRHdlbGxUaW1lJEN6YXNXcGlzeXdhbmlhTXMpICsgMipzZChkYW5lNCREd2VsbFRpbWUkQ3phc1dwaXN5d2FuaWFNcykNCmdvcm55TGltaXQNCg0KbnJvdyhkYW5lNCREd2VsbFRpbWUpDQpkYW5lNSA8LSBkYW5lNCREd2VsbFRpbWVbZGFuZTQkRHdlbGxUaW1lJEN6YXNXcGlzeXdhbmlhTXMgPCBnb3JueUxpbWl0LF0NCmRhbmU0JER3ZWxsVGltZSRDemFzV3Bpc3l3YW5pYU1zIDwgZ29ybnlMaW1pdA0KDQpwbG90KGRhbmU1JEN6YXNXcGlzeXdhbmlhTXMsIGNvbD0icmVkIikNCm1lYW4oZGFuZTUkQ3phc1dwaXN5d2FuaWFNcyk7c2QoZGFuZTUkQ3phc1dwaXN5d2FuaWFNcykNCg0Kc2hhcGlyby50ZXN0KGRhbmU1JEN6YXNXcGlzeXdhbmlhTXMpDQpzaGFwaXJvLnRlc3QoZGFuZTQkRHdlbGxUaW1lJEN6YXNXcGlzeXdhbmlhTXMpDQoNCnBuZygiY3phc1dwaXN5d2FuaWEucG5nIikNCnBsb3QoZGFuZTUkQ3phc1dwaXN5d2FuaWFNcywgY29sPSJyZWQiKQ0KZGV2Lm9mZigpDQpgYGANCmBgYHtyfQ0Kb2JsaWN6LnNyZWRuaWUuY3phc3kud3Bpc3l3YW5pYSA8LSBmdW5jdGlvbihmaWxlbmFtZSkNCnsNCiAgc3RvcGlmbm90KGZpbGUuZXhpc3RzKGZpbGVuYW1lKSkNCiAgb24uZXhpdChwcmludChwYXN0ZSgiWmFrb8WEY3pvbmUgcHJ6ZXR3YXJ6YW5pZSBwbGlrdSAiLGZpbGVuYW1lKSwgcXVvdGU9RkFMU0UpKQ0KICBwcmludChwYXN0ZSgiUHJ6ZXR3YXJ6YW0gcGxpayAiLGZpbGVuYW1lKSwgcXVvdGU9RkFMU0UpDQogIGRhbmUxIDwtIHJlYWQuY3N2KGZpbGVuYW1lLCBzZXA9IjsiLCBkZWM9IiwiKQ0KICBkYW5lMiA8LSBkYW5lMVtkYW5lMSREZW1vTW9kZSAhPSAiVHJ1ZSIsXQ0KICBzdG9waWZub3QoaXMubnVtZXJpYyhkYW5lMiRDemFzT3N0YXRuaWVqQ3lmcnlNcykpDQogIHN0b3BpZm5vdChpcy5udW1lcmljKGRhbmUyJEN6YXNQaWVyd3N6ZWpDeWZyeU1zKSkNCiAgc3RvcGlmbm90KGlzLm51bWVyaWMoZGFuZTIkQ3phc1dwaXN5d2FuaWFNcykpDQogIGN6YXNXcGlzeXdhbmlhIDwtIGRhbmUyJEN6YXNPc3RhdG5pZWpDeWZyeU1zIC0gZGFuZTIkQ3phc1BpZXJ3c3plakN5ZnJ5TXMNCiAgZGFuZTQgPC0gc3BsaXQoZGFuZTIsIGxldmVscyhkYW5lMiRHYXplQ29udHJvbFR5cGUpKQ0KICByZXN1bHQgPC0gYygNCiAgICBkd2VsbHRpbWVfbWVhbnRpbWUgPSBtZWFuKGRhbmU0JER3ZWxsVGltZSRDemFzV3Bpc3l3YW5pYU1zKSwNCiAgICBkd2VsbHRpbWVfc2QgPSBzZChkYW5lNCREd2VsbFRpbWUkQ3phc1dwaXN5d2FuaWFNcyksDQogICAgZml4YXRpb25fbWVhbnRpbWUgPSBtZWFuKGRhbmU0JEZpeGF0aW9uJEN6YXNXcGlzeXdhbmlhTXMpLA0KICAgIGZpeGF0aW9uX3NkID0gc2QoZGFuZTQkRml4YXRpb24kQ3phc1dwaXN5d2FuaWFNcyksDQogICAgZWFsX21lYW50aW1lID0gbWVhbihkYW5lNCRFbnRlckFuZExlYXZlUG9zaXRpb25zJEN6YXNXcGlzeXdhbmlhTXMpLA0KICAgIGVhbF9zZCA9IHNkKGRhbmU0JEVudGVyQW5kTGVhdmVQb3NpdGlvbnMkQ3phc1dwaXN5d2FuaWFNcykNCiAgKQ0KICByZXR1cm4ocmVzdWx0KQ0KfQ0KDQpvYmxpY3ouc3JlZG5pZS5jemFzeS53cGlzeXdhbmlhKCIxLmNzdiIpDQoNCg0Kbm9ybWFsaXplUGF0aCgiMS5jc3YiKQ0KYmFzZW5hbWUoIjEuY3N2IikNCmJhc2VuYW1lKG5vcm1hbGl6ZVBhdGgoIjEuY3N2IikpDQpub3JtYWxpemVQYXRoKGRpcm5hbWUoIjEuY3N2IikpDQp0ZW1wZGlyKCkNCnRlbXBmaWxlKCkNCmdldHdkKCkNCmZpbGUuZXhpc3RzKCIxLmNzdiIpDQpmaWxlLmluZm8oIjEuY3N2IikNCg0KcGxpa2kgPC0gbGlzdC5maWxlcyhnZXR3ZCgpLCBwYXR0ZXJuID0gIiouY3N2IiwgZnVsbC5uYW1lcyA9IFRSVUUpDQpwbGlraQ0Kb2JsaWN6LnNyZWRuaWUuY3phc3kud3Bpc3l3YW5pYShwbGlraVsxXSkNCg0Kd3luaWtpMiA8LSBsYXBwbHkocGxpa2ksIG9ibGljei5zcmVkbmllLmN6YXN5LndwaXN5d2FuaWEpDQp3eW5pa2kyDQpgYGANCg0K