Paula Cazali

En este proyecto se analizará un dataset sobre partidos de futbol, en especifico de la UEFA Champeons League.
Cargando librerias y dataset
library(dplyr)
library(ggplot2)
library(readr)
partidos <- read_csv("spi_matches.csv")
Como todo el dataset es sobre distintos equipos de futbol primero necesitamos obtener solo donde están los partidos de la UEFA Champions League:
uefa <-
partidos %>%
filter(league == "UEFA Champions League")
Por lo que el dataset quedaría de la siguiente forma:
head(uefa)
En el datasest hay algunas columnas que no se necesitan para hacer la predicción, por lo que podemos eliminar esas columnas que en este caso serían: la fecha en la cual se realizó el partido, la liga a la que pertenecen, ya que sabemos que todos los partidos son de la UEFA Champeons League, el id de liga, y otras variables que no tienen información relevante en el dataset. También eliminaremos las filas que no tengan dato en alguna de las columnas.
uefa <-
uefa %>%
select(-date, -league_id, -league, -importance1, -importance2) %>%
filter(xg1 != "NA") %>%
filter(xg2 != "NA")
Por lo que el dataset se vería asi:
head(uefa)
Cambiaremos los nombres de las columnas del dataset para poder tener mejor visión de los equipos locales y los visitantes y sus respectivas observaciones.
colnames(uefa) <- c("local", "visit", "spi_local", "spi_visit", "prob_local", "prob_visit", "probtie", "proj_score1", "proj_score2", "score_local", "score_visit", "xg_local", "xg_visit", "nsxg_local", "nsxg_visit", "adj_score1", "adj_score2")
head(uefa)
- La variable “spi” significa soccer power index es un ranking mundial de los equipos de futbol.
- La varibale “xg” significa expected goals, son los goles esperados por parte de cada equipo.
- La variable “nsxg” significa non-shot expected goals y son los goles esperados no lanzados.
- Y la variable “score” nos dice el resultado final del partido.
A continuación se obtendrán los partidos totales definidos a favor de los locales, los definidos a favor de los visitantes y los empates y se graficarán
Total de partidos jugados como locales:
partidos_local <-
uefa %>%
mutate(cnt = 1) %>%
group_by(local) %>%
summarise(partidos_local = sum(cnt))
partidos_local
Total de partidos jugados como visitantes:
partidos_visit <-
uefa %>%
mutate(cnt = 1) %>%
group_by(visit) %>%
summarise(partidos_visit = sum(cnt))
partidos_visit
Partidos definidos a favor de los locales, a favor de los visitantes y partidos en empate:
Graficando:
Total_Win %>%
ggplot(aes(x=Partidos,y=total_wins))+
geom_bar(stat = "identity", fill = c("blue", "green", "red")) +
ggtitle("Partidos definidos como locales, visitantes y empates") +
labs(x = "Partidos") +
labs(y = "Total")

En esa gráfica se puede apreciar que hay más partidos ganados si se juega de local que si se juega de visitante, para cualquier equipo en la UEFA Champeons League.
Modelo
Se dividirá el dataset en 70% para el modelo de predicción y el 30% para las pruebas del modelo.
uefa.train <- uefa[1:(0.7*(nrow(uefa))), ]
uefa.test <- uefa[(0.7*(nrow(uefa))):nrow(uefa), ]
Introducimos la variable Win1 para los partidos ganados locales y la variable Win2 para los ganados por los visitantes. Un “1” significa que lo ganó y un “0” puede significar que lo perdió o que lo empató.
uefa.train$Win1 <- ifelse((uefa.train$score_local > uefa.train$score_visit), 1, 0)
uefa.train$Win2 <- ifelse((uefa.train$score_visit > uefa.train$score_local), 1, 0)
uefa.test$Win1 <- ifelse((uefa.test$score_local > uefa.test$score_visit), 1, 0)
uefa.test$Win2 <- ifelse((uefa.test$score_visit > uefa.test$score_local), 1, 0)
Para los locales
Regresión binomial tipo logística para predecir la variable Win1 (Si gana o no el partido), en base a los goles esperados de los locales.
logit_reg <- glm(formula = Win1 ~ xg_local,
family = binomial(link = "logit"),
data = uefa.train)
summary(logit_reg)
Call:
glm(formula = Win1 ~ xg_local, family = binomial(link = "logit"),
data = uefa.train)
Deviance Residuals:
Min 1Q Median 3Q Max
-2.3520 -0.8320 -0.5038 0.9089 1.9864
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -2.4363 0.3452 -7.057 1.70e-12 ***
xg_local 1.3627 0.1969 6.921 4.48e-12 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 331.07 on 240 degrees of freedom
Residual deviance: 256.91 on 239 degrees of freedom
AIC: 260.91
Number of Fisher Scoring iterations: 4
exp_goals1 <- seq(min(uefa.train$xg_local), max(uefa.train$xg_local), 0.05)
prediccion <- predict(object = logit_reg,
newdata = list(xg_local = exp_goals1),
type = "response")
graph_predict <- data.frame(exp_goals1, prediccion)
colnames(graph_predict) <- c("Expected_Goals", "Probabilidad")
Gráfica del Modelo para locales
ggplot(data = graph_predict, aes(x = Expected_Goals, y = Probabilidad)) +
geom_line(color = "blue", size = 1) +
ggtitle("Modelo para Locales - Regresión Logística") +
labs(x = "Expected Goals") +
labs(y = "Probabilidad") +
theme_minimal()

Modelo con datos del dataset de pruebas
prediccion_test <- predict(object = logit_reg,
newdata = uefa.test,
type="response")
aux <- data.frame(Win = uefa.test$Win1, Probabilidad = prediccion_test)
uefa.results1 <- data.frame(Local = uefa.test$local, as.data.frame(aux))
uefa.results1
Para los visitantes
Regresión binomial tipo logística para predecir la variable Win2 (Si gana o no el partido), en base a los goles esperados de los visitantes.
logit_reg2 <- glm(formula = Win2 ~ xg_visit,
family = binomial(link = "logit"),
data = uefa.train)
summary(logit_reg2)
Call:
glm(formula = Win2 ~ xg_visit, family = binomial(link = "logit"),
data = uefa.train)
Deviance Residuals:
Min 1Q Median 3Q Max
-1.7648 -0.8087 -0.5242 0.9814 2.0532
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -2.5427 0.3385 -7.512 5.84e-14 ***
xg_visit 1.2543 0.2060 6.090 1.13e-09 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 301.97 on 240 degrees of freedom
Residual deviance: 249.64 on 239 degrees of freedom
AIC: 253.64
Number of Fisher Scoring iterations: 4
exp_goals2 <- seq(min(uefa.train$xg_visit), max(uefa.train$xg_visit), 0.05)
prediccion2 <- predict(object = logit_reg2,
newdata = list(xg_visit = exp_goals2),
type = "response")
graph_predict2 <- data.frame(exp_goals2, prediccion2)
colnames(graph_predict2) <- c("Expected_Goals", "Probabilidad")
Gráfica del Modelo para visitantes
ggplot(data = graph_predict2, aes(x = Expected_Goals, y = Probabilidad)) +
geom_line(color = "blue", size = 1) +
ggtitle("Modelo para Visitantes - Regresión Logística") +
labs(x = "Expected Goals") +
labs(y = "Probabilidad") +
theme_minimal()

Modelo con datos del dataset de pruebas
prediccion2_test <- predict(object = logit_reg2,
newdata = uefa.test,
type="response")
aux2 <- data.frame(Win = uefa.test$Win2, Probabilidad = prediccion2_test)
uefa.results2 <- data.frame(Visitante = uefa.test$visit, as.data.frame(aux2))
uefa.results2
Conclusiones
En el análisis de estos datos usando la variable de goles esperados podemos ver que los equipos que juegan de locales tienen más posibilidades de ganar y echar más goles (debido a los goles esperados) que los equipos que juegan de visitantes.
LS0tDQp0aXRsZTogIlByb3llY3RvIEVjb25vbWV0cmlhIDEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyMgUGF1bGEgQ2F6YWxpIA0KDQohW10oZ2FsaWxlby5wbmcpDQoNCkVuIGVzdGUgcHJveWVjdG8gc2UgYW5hbGl6YXLDoSB1biBkYXRhc2V0IHNvYnJlIHBhcnRpZG9zIGRlIGZ1dGJvbCwgZW4gZXNwZWNpZmljbyBkZSBsYSBVRUZBIENoYW1wZW9ucyBMZWFndWUuDQoNCkNhcmdhbmRvIGxpYnJlcmlhcyB5IGRhdGFzZXQNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocmVhZHIpDQpwYXJ0aWRvcyA8LSByZWFkX2Nzdigic3BpX21hdGNoZXMuY3N2IikNCmBgYA0KDQoNCkNvbW8gdG9kbyBlbCBkYXRhc2V0IGVzIHNvYnJlIGRpc3RpbnRvcyBlcXVpcG9zIGRlIGZ1dGJvbCBwcmltZXJvIG5lY2VzaXRhbW9zIG9idGVuZXIgc29sbyBkb25kZSBlc3TDoW4gbG9zIHBhcnRpZG9zIGRlIGxhIFVFRkEgQ2hhbXBpb25zIExlYWd1ZToNCmBgYHtyfQ0KdWVmYSA8LQ0KcGFydGlkb3MgJT4lIA0KICBmaWx0ZXIobGVhZ3VlID09ICJVRUZBIENoYW1waW9ucyBMZWFndWUiKQ0KYGBgDQoNCg0KUG9yIGxvIHF1ZSBlbCBkYXRhc2V0IHF1ZWRhcsOtYSBkZSBsYSBzaWd1aWVudGUgZm9ybWE6DQpgYGB7cn0NCmhlYWQodWVmYSkNCmBgYA0KDQoNCkVuIGVsIGRhdGFzZXN0IGhheSBhbGd1bmFzIGNvbHVtbmFzIHF1ZSBubyBzZSBuZWNlc2l0YW4gcGFyYSBoYWNlciBsYSBwcmVkaWNjacOzbiwgcG9yIGxvIHF1ZSBwb2RlbW9zIGVsaW1pbmFyIGVzYXMgY29sdW1uYXMgcXVlIGVuIGVzdGUgY2FzbyBzZXLDrWFuOiBsYSBmZWNoYSBlbiBsYSBjdWFsIHNlIHJlYWxpesOzIGVsIHBhcnRpZG8sIGxhIGxpZ2EgYSBsYSBxdWUgcGVydGVuZWNlbiwgeWEgcXVlIHNhYmVtb3MgcXVlIHRvZG9zIGxvcyBwYXJ0aWRvcyBzb24gZGUgbGEgVUVGQSBDaGFtcGVvbnMgTGVhZ3VlLCBlbCBpZCBkZSBsaWdhLCB5IG90cmFzIHZhcmlhYmxlcyBxdWUgbm8gdGllbmVuIGluZm9ybWFjacOzbiByZWxldmFudGUgZW4gZWwgZGF0YXNldC4NClRhbWJpw6luIGVsaW1pbmFyZW1vcyBsYXMgZmlsYXMgcXVlIG5vIHRlbmdhbiBkYXRvIGVuIGFsZ3VuYSBkZSBsYXMgY29sdW1uYXMuDQpgYGB7cn0NCnVlZmEgPC0NCnVlZmEgJT4lIA0KICBzZWxlY3QoLWRhdGUsIC1sZWFndWVfaWQsIC1sZWFndWUsIC1pbXBvcnRhbmNlMSwgLWltcG9ydGFuY2UyKSAlPiUgDQogIGZpbHRlcih4ZzEgIT0gIk5BIikgJT4lIA0KICBmaWx0ZXIoeGcyICE9ICJOQSIpDQpgYGANCg0KDQpQb3IgbG8gcXVlIGVsIGRhdGFzZXQgc2UgdmVyw61hIGFzaToNCmBgYHtyfQ0KaGVhZCh1ZWZhKQ0KYGBgDQoNCkNhbWJpYXJlbW9zIGxvcyBub21icmVzIGRlIGxhcyBjb2x1bW5hcyBkZWwgZGF0YXNldCBwYXJhIHBvZGVyIHRlbmVyIG1lam9yIHZpc2nDs24gZGUgbG9zIGVxdWlwb3MgbG9jYWxlcyB5IGxvcyB2aXNpdGFudGVzIHkgc3VzIHJlc3BlY3RpdmFzIG9ic2VydmFjaW9uZXMuDQpgYGB7cn0NCmNvbG5hbWVzKHVlZmEpIDwtIGMoImxvY2FsIiwgInZpc2l0IiwgInNwaV9sb2NhbCIsICJzcGlfdmlzaXQiLCAicHJvYl9sb2NhbCIsICJwcm9iX3Zpc2l0IiwgInByb2J0aWUiLCAicHJval9zY29yZTEiLCAicHJval9zY29yZTIiLCAic2NvcmVfbG9jYWwiLCAic2NvcmVfdmlzaXQiLCAieGdfbG9jYWwiLCAieGdfdmlzaXQiLCAibnN4Z19sb2NhbCIsICJuc3hnX3Zpc2l0IiwgImFkal9zY29yZTEiLCAiYWRqX3Njb3JlMiIpDQpoZWFkKHVlZmEpDQpgYGANCg0KKiBMYSB2YXJpYWJsZSAic3BpIiBzaWduaWZpY2Egc29jY2VyIHBvd2VyIGluZGV4IGVzIHVuIHJhbmtpbmcgbXVuZGlhbCBkZSBsb3MgZXF1aXBvcyBkZSBmdXRib2wuDQoqIExhIHZhcmliYWxlICJ4ZyIgc2lnbmlmaWNhIGV4cGVjdGVkIGdvYWxzLCBzb24gbG9zIGdvbGVzIGVzcGVyYWRvcyBwb3IgcGFydGUgZGUgY2FkYSBlcXVpcG8uDQoqIExhIHZhcmlhYmxlICJuc3hnIiBzaWduaWZpY2Egbm9uLXNob3QgZXhwZWN0ZWQgZ29hbHMgeSBzb24gbG9zIGdvbGVzIGVzcGVyYWRvcyBubyBsYW56YWRvcy4NCiogWSBsYSB2YXJpYWJsZSAic2NvcmUiIG5vcyBkaWNlIGVsIHJlc3VsdGFkbyBmaW5hbCBkZWwgcGFydGlkby4NCg0KDQojIyMjIEEgY29udGludWFjacOzbiBzZSBvYnRlbmRyw6FuIGxvcyBwYXJ0aWRvcyB0b3RhbGVzIGRlZmluaWRvcyBhIGZhdm9yIGRlIGxvcyBsb2NhbGVzLCBsb3MgZGVmaW5pZG9zIGEgZmF2b3IgZGUgbG9zIHZpc2l0YW50ZXMgeSBsb3MgZW1wYXRlcyB5IHNlIGdyYWZpY2Fyw6FuDQoNClRvdGFsIGRlIHBhcnRpZG9zIGp1Z2Fkb3MgY29tbyBsb2NhbGVzOg0KYGBge3J9DQpwYXJ0aWRvc19sb2NhbCA8LQ0KdWVmYSAlPiUgDQogIG11dGF0ZShjbnQgPSAxKSAlPiUgDQogIGdyb3VwX2J5KGxvY2FsKSAlPiUgDQogIHN1bW1hcmlzZShwYXJ0aWRvc19sb2NhbCA9IHN1bShjbnQpKQ0KcGFydGlkb3NfbG9jYWwNCmBgYA0KDQoNClRvdGFsIGRlIHBhcnRpZG9zIGp1Z2Fkb3MgY29tbyB2aXNpdGFudGVzOg0KYGBge3J9DQpwYXJ0aWRvc192aXNpdCA8LQ0KdWVmYSAlPiUNCiAgbXV0YXRlKGNudCA9IDEpICU+JSANCiAgZ3JvdXBfYnkodmlzaXQpICU+JSANCiAgc3VtbWFyaXNlKHBhcnRpZG9zX3Zpc2l0ID0gc3VtKGNudCkpDQpwYXJ0aWRvc192aXNpdA0KYGBgDQoNCg0KUGFydGlkb3MgZGVmaW5pZG9zIGEgZmF2b3IgZGUgbG9zIGxvY2FsZXMsIGEgZmF2b3IgZGUgbG9zIHZpc2l0YW50ZXMgeSBwYXJ0aWRvcyBlbiBlbXBhdGU6DQpgYGB7cn0NClRvdGFsX1dpbiA8LQ0KdWVmYSAlPiUgDQogIG11dGF0ZShXaW4gPSBpZmVsc2UoKHVlZmEkc2NvcmVfbG9jYWwgPiB1ZWZhJHNjb3JlX3Zpc2l0KSwgYXMuaW50ZWdlcigxKSwgaWZlbHNlKCh1ZWZhJHNjb3JlX3Zpc2l0ID4gdWVmYSRzY29yZV9sb2NhbCksIGFzLmludGVnZXIoMiksIGFzLmludGVnZXIoMykpKSkgJT4lIA0KICBzZWxlY3QoV2luKSAlPiUgDQogIGdyb3VwX2J5KFdpbikgJT4lIA0KICBzdW1tYXJpc2UodG90YWxfY291bnQgPSBzdW0oV2luKSkgJT4lIA0KICBtdXRhdGUoUGFydGlkb3MgPSBjKCJEZWYuIGxvY2FsIiwgIkRlZi52aXNpdCIsICJFbXBhdGUiKSkgJT4lIA0KICBtdXRhdGUodG90YWxfd2lucyA9IHRvdGFsX2NvdW50IC8gV2luKSAlPiUgDQogIHNlbGVjdCgtV2luLCAtdG90YWxfY291bnQpDQoNCmBgYA0KDQpHcmFmaWNhbmRvOg0KYGBge3J9DQpUb3RhbF9XaW4gJT4lIA0KICBnZ3Bsb3QoYWVzKHg9UGFydGlkb3MseT10b3RhbF93aW5zKSkrDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gYygiYmx1ZSIsICJncmVlbiIsICJyZWQiKSkgKw0KICBnZ3RpdGxlKCJQYXJ0aWRvcyBkZWZpbmlkb3MgY29tbyBsb2NhbGVzLCB2aXNpdGFudGVzIHkgZW1wYXRlcyIpICsgDQogIGxhYnMoeCA9ICJQYXJ0aWRvcyIpICsgDQogIGxhYnMoeSA9ICJUb3RhbCIpDQpgYGANCg0KRW4gZXNhIGdyw6FmaWNhIHNlIHB1ZWRlIGFwcmVjaWFyIHF1ZSBoYXkgbcOhcyBwYXJ0aWRvcyBnYW5hZG9zIHNpIHNlIGp1ZWdhIGRlIGxvY2FsIHF1ZSBzaSBzZSBqdWVnYSBkZSB2aXNpdGFudGUsIHBhcmEgY3VhbHF1aWVyIGVxdWlwbyBlbiBsYSBVRUZBIENoYW1wZW9ucyBMZWFndWUuDQoNCg0KIyBNb2RlbG8NCg0KU2UgZGl2aWRpcsOhIGVsIGRhdGFzZXQgZW4gNzAlIHBhcmEgZWwgbW9kZWxvIGRlIHByZWRpY2Npw7NuIHkgZWwgMzAlIHBhcmEgbGFzIHBydWViYXMgZGVsIG1vZGVsby4NCmBgYHtyfQ0KdWVmYS50cmFpbiA8LSB1ZWZhWzE6KDAuNyoobnJvdyh1ZWZhKSkpLCBdDQp1ZWZhLnRlc3QgPC0gdWVmYVsoMC43Kihucm93KHVlZmEpKSk6bnJvdyh1ZWZhKSwgXQ0KYGBgDQoNCg0KSW50cm9kdWNpbW9zIGxhIHZhcmlhYmxlIFdpbjEgcGFyYSBsb3MgcGFydGlkb3MgZ2FuYWRvcyBsb2NhbGVzIHkgbGEgdmFyaWFibGUgV2luMiBwYXJhIGxvcyBnYW5hZG9zIHBvciBsb3MgdmlzaXRhbnRlcy4gVW4gIjEiIHNpZ25pZmljYSBxdWUgbG8gZ2Fuw7MgeSB1biAiMCIgcHVlZGUgc2lnbmlmaWNhciBxdWUgbG8gcGVyZGnDsyBvIHF1ZSBsbyBlbXBhdMOzLg0KYGBge3J9DQp1ZWZhLnRyYWluJFdpbjEgPC0gaWZlbHNlKCh1ZWZhLnRyYWluJHNjb3JlX2xvY2FsID4gdWVmYS50cmFpbiRzY29yZV92aXNpdCksIDEsIDApDQp1ZWZhLnRyYWluJFdpbjIgPC0gaWZlbHNlKCh1ZWZhLnRyYWluJHNjb3JlX3Zpc2l0ID4gdWVmYS50cmFpbiRzY29yZV9sb2NhbCksIDEsIDApDQpgYGANCg0KDQpgYGB7cn0NCnVlZmEudGVzdCRXaW4xIDwtIGlmZWxzZSgodWVmYS50ZXN0JHNjb3JlX2xvY2FsID4gdWVmYS50ZXN0JHNjb3JlX3Zpc2l0KSwgMSwgMCkNCnVlZmEudGVzdCRXaW4yIDwtIGlmZWxzZSgodWVmYS50ZXN0JHNjb3JlX3Zpc2l0ID4gdWVmYS50ZXN0JHNjb3JlX2xvY2FsKSwgMSwgMCkNCmBgYA0KDQoNCiMjIFBhcmEgbG9zIGxvY2FsZXMNClJlZ3Jlc2nDs24gYmlub21pYWwgdGlwbyBsb2fDrXN0aWNhIHBhcmEgcHJlZGVjaXIgbGEgdmFyaWFibGUgV2luMSAoU2kgZ2FuYSBvIG5vIGVsIHBhcnRpZG8pLCBlbiBiYXNlIGEgbG9zIGdvbGVzIGVzcGVyYWRvcyBkZSBsb3MgbG9jYWxlcy4NCmBgYHtyfQ0KbG9naXRfcmVnIDwtIGdsbShmb3JtdWxhID0gV2luMSB+IHhnX2xvY2FsLCANCiAgICAgICAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpLA0KICAgICAgICAgICAgICAgICBkYXRhID0gdWVmYS50cmFpbikNCnN1bW1hcnkobG9naXRfcmVnKQ0KYGBgDQoNCmBgYHtyfQ0KZXhwX2dvYWxzMSA8LSBzZXEobWluKHVlZmEudHJhaW4keGdfbG9jYWwpLCBtYXgodWVmYS50cmFpbiR4Z19sb2NhbCksIDAuMDUpDQoNCnByZWRpY2Npb24gPC0gcHJlZGljdChvYmplY3QgPSBsb2dpdF9yZWcsIA0KICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBsaXN0KHhnX2xvY2FsID0gZXhwX2dvYWxzMSksDQogICAgICAgICAgICAgICAgdHlwZSA9ICJyZXNwb25zZSIpDQoNCmdyYXBoX3ByZWRpY3QgPC0gZGF0YS5mcmFtZShleHBfZ29hbHMxLCBwcmVkaWNjaW9uKQ0KY29sbmFtZXMoZ3JhcGhfcHJlZGljdCkgPC0gYygiRXhwZWN0ZWRfR29hbHMiLCAiUHJvYmFiaWxpZGFkIikNCmBgYA0KDQojIyBHcsOhZmljYSBkZWwgTW9kZWxvIHBhcmEgbG9jYWxlcw0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGdyYXBoX3ByZWRpY3QsIGFlcyh4ID0gRXhwZWN0ZWRfR29hbHMsIHkgPSBQcm9iYWJpbGlkYWQpKSArIA0KICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxKSArIA0KICBnZ3RpdGxlKCJNb2RlbG8gcGFyYSBMb2NhbGVzIC0gUmVncmVzacOzbiBMb2fDrXN0aWNhIikgKw0KICBsYWJzKHggPSAiRXhwZWN0ZWQgR29hbHMiKSArIA0KICBsYWJzKHkgPSAiUHJvYmFiaWxpZGFkIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojIyMgTW9kZWxvIGNvbiBkYXRvcyBkZWwgZGF0YXNldCBkZSBwcnVlYmFzDQoNCmBgYHtyfQ0KcHJlZGljY2lvbl90ZXN0IDwtIHByZWRpY3Qob2JqZWN0ID0gbG9naXRfcmVnLA0KICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSB1ZWZhLnRlc3QsDQogICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0icmVzcG9uc2UiKQ0KYXV4IDwtIGRhdGEuZnJhbWUoV2luID0gdWVmYS50ZXN0JFdpbjEsIFByb2JhYmlsaWRhZCA9IHByZWRpY2Npb25fdGVzdCkNCnVlZmEucmVzdWx0czEgPC0gZGF0YS5mcmFtZShMb2NhbCA9IHVlZmEudGVzdCRsb2NhbCwgYXMuZGF0YS5mcmFtZShhdXgpKQ0KICANCnVlZmEucmVzdWx0czENCmBgYA0KDQoNCiMjIFBhcmEgbG9zIHZpc2l0YW50ZXMNClJlZ3Jlc2nDs24gYmlub21pYWwgdGlwbyBsb2fDrXN0aWNhIHBhcmEgcHJlZGVjaXIgbGEgdmFyaWFibGUgV2luMiAoU2kgZ2FuYSBvIG5vIGVsIHBhcnRpZG8pLCBlbiBiYXNlIGEgbG9zIGdvbGVzIGVzcGVyYWRvcyBkZSBsb3MgdmlzaXRhbnRlcy4NCmBgYHtyfQ0KbG9naXRfcmVnMiA8LSBnbG0oZm9ybXVsYSA9IFdpbjIgfiB4Z192aXNpdCwgDQogICAgICAgICAgICAgICAgIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSwNCiAgICAgICAgICAgICAgICAgZGF0YSA9IHVlZmEudHJhaW4pDQpzdW1tYXJ5KGxvZ2l0X3JlZzIpDQpgYGANCg0KYGBge3J9DQpleHBfZ29hbHMyIDwtIHNlcShtaW4odWVmYS50cmFpbiR4Z192aXNpdCksIG1heCh1ZWZhLnRyYWluJHhnX3Zpc2l0KSwgMC4wNSkNCg0KcHJlZGljY2lvbjIgPC0gcHJlZGljdChvYmplY3QgPSBsb2dpdF9yZWcyLCANCiAgICAgICAgICAgICAgICBuZXdkYXRhID0gbGlzdCh4Z192aXNpdCA9IGV4cF9nb2FsczIpLA0KICAgICAgICAgICAgICAgIHR5cGUgPSAicmVzcG9uc2UiKQ0KDQpncmFwaF9wcmVkaWN0MiA8LSBkYXRhLmZyYW1lKGV4cF9nb2FsczIsIHByZWRpY2Npb24yKQ0KY29sbmFtZXMoZ3JhcGhfcHJlZGljdDIpIDwtIGMoIkV4cGVjdGVkX0dvYWxzIiwgIlByb2JhYmlsaWRhZCIpDQpgYGANCg0KIyMgR3LDoWZpY2EgZGVsIE1vZGVsbyBwYXJhIHZpc2l0YW50ZXMNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBncmFwaF9wcmVkaWN0MiwgYWVzKHggPSBFeHBlY3RlZF9Hb2FscywgeSA9IFByb2JhYmlsaWRhZCkpICsgDQogIGdlb21fbGluZShjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEpICsgDQogIGdndGl0bGUoIk1vZGVsbyBwYXJhIFZpc2l0YW50ZXMgLSBSZWdyZXNpw7NuIExvZ8Otc3RpY2EiKSArDQogIGxhYnMoeCA9ICJFeHBlY3RlZCBHb2FscyIpICsgDQogIGxhYnMoeSA9ICJQcm9iYWJpbGlkYWQiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMjIyBNb2RlbG8gY29uIGRhdG9zIGRlbCBkYXRhc2V0IGRlIHBydWViYXMNCg0KYGBge3J9DQpwcmVkaWNjaW9uMl90ZXN0IDwtIHByZWRpY3Qob2JqZWN0ID0gbG9naXRfcmVnMiwNCiAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gdWVmYS50ZXN0LA0KICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9InJlc3BvbnNlIikNCmF1eDIgPC0gZGF0YS5mcmFtZShXaW4gPSB1ZWZhLnRlc3QkV2luMiwgUHJvYmFiaWxpZGFkID0gcHJlZGljY2lvbjJfdGVzdCkNCnVlZmEucmVzdWx0czIgPC0gZGF0YS5mcmFtZShWaXNpdGFudGUgPSB1ZWZhLnRlc3QkdmlzaXQsIGFzLmRhdGEuZnJhbWUoYXV4MikpDQogIA0KdWVmYS5yZXN1bHRzMg0KYGBgDQoNCiMgQ29uY2x1c2lvbmVzDQojIyMjIEVuIGVsIGFuw6FsaXNpcyBkZSBlc3RvcyBkYXRvcyB1c2FuZG8gbGEgdmFyaWFibGUgZGUgZ29sZXMgZXNwZXJhZG9zIHBvZGVtb3MgdmVyIHF1ZSBsb3MgZXF1aXBvcyBxdWUganVlZ2FuIGRlIGxvY2FsZXMgdGllbmVuIG3DoXMgcG9zaWJpbGlkYWRlcyBkZSBnYW5hciB5IGVjaGFyIG3DoXMgZ29sZXMgKGRlYmlkbyBhIGxvcyBnb2xlcyBlc3BlcmFkb3MpIHF1ZSBsb3MgZXF1aXBvcyBxdWUganVlZ2FuIGRlIHZpc2l0YW50ZXMuDQo=