O conjunto de dados trabalhados contém algumas estatísticas de quatro jogadores da NBA durante os playoffs, no ano de 2021.

A estrutura dos dados é resumida abaixo:

VARIÁVEL TIPO DESCRIÇÃO
SHOOTER character Nome do jogador que fez o arremesso
X numérico Distância horizontal do tiro tirado da cesta em pés
Y numérico Distância vertical do tiro dado da cesta em pés
FAIXA numérico Raio de alcance do arremesso feito da cesta em pés
DEFENSOR character Nome do jogador que defendeu o chute
PONTUAÇÃO character ‘ACERTO’ se o tiro for marcado, caso contrário ‘ERRO’

No início, realizamos o carregamento dos dados e alteramos alguns termos visando a composição futura dos gráficos.

data <- read_csv("nba_players_shooting.csv", show_col_types = FALSE)
data <- data %>% 
  mutate(RANGE = gsub("\"", "", RANGE)) %>% 
  mutate(RANGE = recode(RANGE,
                        "(0, 4)" = "0-4",
                        "(5, 9)" = "5-9",
                        "(10, 14)" = "10-14",
                        "(15, 19)" = "15-19",
                        "(20, 24)" = "20-24",
                        "(25, 29)" = "25-29")) %>% 
  mutate(SCORE = recode(SCORE,
                        "MADE" = "ACERTO",
                        "MISSED" = "ERRO")) %>% 
  mutate(X = round(X, 2)) %>% 
  mutate(Y = round(Y, 2))

data$RANGE <- factor(data$RANGE,
                     levels = c("0-4", "5-9", "10-14", "15-19", "20-24", "25-29"))
data %>% 
  DT::datatable()

Com base nos dados, iremos responder algumas perguntas:

1. Dos arremessos realizados, quantos foram acertos e erros?

data %>%
  group_by(SCORE) %>% 
  summarise(total = n()) %>% 
  ggplot(aes(x = SCORE, y = total, fill = SCORE)) +
  geom_bar(alpha = .5, width = .75, stat = 'identity') +
  labs(
    title = "Arremessos: Falhas e Acertos",
    fill = "",
    y = "count",
    x = "ARREMESSOS"
  ) +
  scale_fill_manual(values = c("green", "red")) +
  scale_y_continuous(breaks = seq(0, 450, 50)) +
  theme_bw() +
  theme(
    legend.position = "",
     legend.box.margin = margin(t = -10),
    plot.title = element_text(size = 10,
                              face = "bold",
                              hjust = .5)) +
  geom_text(aes(y = total, label = total), position = position_stack(vjust = 0.9), fontface = 'bold')

É observado que há mais arremessos falhos do que acertos, de forma geral:

data %>%
  group_by(SCORE) %>% 
  summarise(total = n()) %>% 
  mutate(percent = round(total/sum(total) * 100, 2)) %>% 
  DT::datatable()

2. Qual jogador faz mais arremessos? Quantos destes são falhas e quantos são acertos?

data %>% 
  group_by(SHOOTER, SCORE) %>% 
  summarise(total = n()) %>% 
  ggplot(aes(x = SHOOTER, y = total, fill = SCORE)) +
  geom_col(position = 'dodge', alpha = .5, width = .75) +
  labs(
    x = "JOGADORES",
    fill = '',
    title = 'arremessos totais: acertos/erros por jogador') +
  scale_fill_manual(values = c('green', 'red')) +
  theme_bw() +
  theme(
    legend.position = 'bottom',
    plot.title = element_text(size = 10,
                              face = 'bold',
                              hjust = .5),
    legend.box.margin = margin(t = -10)) +
      geom_text(aes(SHOOTER, label = total), position = position_dodge(width = 0.75), size = 4, vjust = 1.5, fontface = 'bold')
`summarise()` has grouped output by 'SHOOTER'. You can override using the `.groups` argument.

Percebe-se que o Trae Young é o jogador que faz mais arremessos, sendo vários desses acertos, mas a maioria são falhos. O único que acerta mais do que erra é o jogador Seth Curry.

Agora vamos observar em termos de porcentagem:

data %>% 
  group_by(SHOOTER, SCORE) %>% 
  summarise(total = n())  %>% 
  mutate(percent = round(total/sum(total)*100, 2)) %>% 
  ggplot(aes(x = SHOOTER, y = percent, fill = SCORE)) +
  geom_col(position = 'stack', alpha = .5) +
  scale_fill_manual(values = c('green', 'red')) +
  labs(x = 'JOGADORES',
       y = '%',
       title = '% erros/acertos por jogador') +
  theme_bw() +
  theme(legend.position = 'bottom',
        plot.title = element_text(size = 10,
                                  face = 'bold',
                                  hjust = .5),
        legend.box.margin = margin(t = -13)) +
  geom_text(aes(label = percent), position = position_stack(vjust = .5), fontface = 'bold')
`summarise()` has grouped output by 'SHOOTER'. You can override using the `.groups` argument.

Percebe-se que, apesar de ser o líder em arremessos, o Trae Young só acerta 43.16% deles, enquanto o Seth Curry lidera em termos de acertos, com 57.82% de êxito. Já o jogador Russel é o que mais erra, com 66.67% de falha em seus arremessos.

3. Quantos acertos/erros se relacionam com a distância da cesta e o local de arremesso da bola?

data %>% 
  group_by(RANGE, SCORE) %>% 
  summarise(total = n()) %>%
  mutate(percent = round(total/sum(total) * 100, 2)) %>% 
  ggplot(aes(x = RANGE, y = total, fill = SCORE)) +
  geom_col(position = 'dodge', alpha = .5, width = .75) +
  labs(x = 'RANGE',
       y = 'count',
       fill = '',
       title = 'acertos e erros em relação ao range') +
  scale_fill_manual(values = c('green', 'red')) +
  scale_y_continuous(breaks = seq(0, 200, 25)) +
  theme_bw() +
  theme(legend.position = 'bottom',
        plot.title = element_text(size = 10,
                                  face = 'bold',
                                  hjust = .5),
        legend.box.margin = margin(t = -10)) +
  geom_text(aes(label = paste0(percent, '%')), 
            position = position_dodge(width = 0.75), 
            vjust = -.5,
            size = 2.5, fontface = 'bold')
`summarise()` has grouped output by 'RANGE'. You can override using the `.groups` argument.

Observa-se que a única distância com relação acerto/erro positiva é 0-4, supõe-se que por ser mais perto da cesta, a chance de um êxito seja maior. Também é possível analisar que a distância 25-29 é a mais dificil de acertar, com cerca de 2/3 de falhas, podendo inferir que por ser mais distante, a precisão do arremesso diminua.

4. Em quais posições da quadra os jogadores mais acertam/erram ?

data %>%
    group_by(SHOOTER, RANGE, SCORE) %>% 
    summarise(total = n(),) %>% 
    mutate(percent = round(total/sum(total) * 100, 2)) %>% 
    ggplot(aes(x = RANGE, y = percent, fill = SCORE)) +
    geom_col(alpha = .5, width = .85, position = "dodge") +
    scale_fill_manual(values = c('green', 'red')) +
    scale_y_continuous(limits = c(0, 100)) +
    labs(
      title = "% acerto/erro dos jogadores por range",
      y = "% de acerto/erro por range",
      x = "RANGE",
      fill = ""
    ) +
    facet_wrap(~ SHOOTER, ncol = 2) +
    theme_bw() +
    theme(
      plot.title = element_text(size = 10,
                                face = "bold",
                                hjust = .5),
      legend.position = "bottom",
      legend.box.margin = margin(t = -10)) +
    geom_text(aes(label = paste0(percent, '%')), position = position_dodge(width = .75), vjust = -.5, size = 2.5, fontface = 'bold')
`summarise()` has grouped output by 'SHOOTER', 'RANGE'. You can override using the `.groups` argument.

Observações:

5. Qual o desempenho dos jogadores atacantes em relação aos seus defensores?

data %>% 
  filter(SHOOTER %in% SHOOTER) %>%
  group_by(SHOOTER, DEFENDER, SCORE) %>% 
  summarise(total = n()) %>% 
  mutate(perc = round(total/sum(total)*100, 2)) %>% 
  ggplot(aes(x = DEFENDER, fill = SCORE)) +
  geom_bar(aes(y = perc), stat = 'identity', alpha = .5, width = .75, position = 'dodge') +
  labs(x = 'DEFENSOR',
       y = '% DEFESA',
       fill = '',
       title = 'Desempenho dos atacantes em relação aos defensores') +
  scale_y_continuous(limits = c(0, 100)) +
  scale_fill_manual(values = c('green', 'red')) +
  facet_wrap(~ SHOOTER, ncol = 2) +
  theme_bw() +
  theme(legend.position = 'bottom',
        legend.box.margin = margin(t = -10),
        plot.title = element_text(size = 10,
                                  face = 'bold',
                                  hjust = .5)) +
  geom_text(aes(y = perc, label = paste0(perc, '%')),
            position = position_dodge(width = .75),
            vjust = -.5,
            size = 2,
            fontface = 'bold')
`summarise()` has grouped output by 'SHOOTER', 'DEFENDER'. You can override using the `.groups` argument.

Observações:

Por fim, quais as posições dos arremessos feitos pelos jogadores em situações de acertos/erros?


ggplot(data, aes(x = X, y = Y, color = SCORE)) +
  geom_point(alpha = .7, size = 1.5) +
  scale_color_manual(values = c('green', 'red')) +
  labs(title = 'Posição dos arremessos',
       color = '') +
  facet_wrap(~ SHOOTER, ncol = 2) +
  theme_bw() +
  theme(legend.position = 'bottom',
        legend.box.margin = margin(t = -12),
        plot.title = element_text(size = 10,
                                  face = 'bold',
                                  hjust = .5)) +
  guides(color = guide_legend(override.aes = ))

De maneira geral, o gráfico permite visualizar o desempenho dos jogadores em relação à posição de seus arremessos, indicando quais jogadores tiveram uma melhor precisão e efetividade durante o jogo.

Conclusão: - Apesar de trazer informações interessantes (de forma gráfica), o dataset utilizado possui somente dados de jogos de alguns playoffs da NBA (2021), fazendo com que o volume de informações seja muito pequena e, portanto, não é recomendado tirar conclusões assertivas acerca dos jogadores, mas sim apenas algumas ideias e visualizações que ocorreram nesses jogos em questão.

LS0tDQp0aXRsZTogIkFOw4FMSVNFIEVYUExPUkFUw5NSSUEgREUgREFET1MgREUgSk9HQURPUkVTIERFIEJBU1FVRVRFIC0gUExBWU9GRlMgTkJBIDIwMjEiDQphdXRob3I6ICJNaWd1ZWwgR2FicmllbCINCmRhdGU6ICIxOC8xMi8yMDI0Ig0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KTyBjb25qdW50byBkZSBkYWRvcyB0cmFiYWxoYWRvcyBjb250w6ltIGFsZ3VtYXMgZXN0YXTDrXN0aWNhcyBkZSBxdWF0cm8gam9nYWRvcmVzIGRhIE5CQSBkdXJhbnRlIG9zIHBsYXlvZmZzLCBubyBhbm8gZGUgMjAyMS4NCg0KQSBlc3RydXR1cmEgZG9zIGRhZG9zIMOpIHJlc3VtaWRhIGFiYWl4bzoNCg0KfCBWQVJJw4FWRUwgfCBUSVBPIHwgREVTQ1JJw4fDg08gfA0KfCA6LS0tOiB8IDotLS06IHwgOi0tLTogfA0KfCBTSE9PVEVSIHwgY2hhcmFjdGVyIHwgTm9tZSBkbyBqb2dhZG9yIHF1ZSBmZXogbyBhcnJlbWVzc28gfA0KfCBYIHwgbnVtw6lyaWNvIHwgRGlzdMOibmNpYSBob3Jpem9udGFsIGRvIHRpcm8gdGlyYWRvIGRhIGNlc3RhIGVtIHDDqXMgfA0KfCBZIHwgbnVtw6lyaWNvIHwgRGlzdMOibmNpYSB2ZXJ0aWNhbCBkbyB0aXJvIGRhZG8gZGEgY2VzdGEgZW0gcMOpcyB8DQp8IEZBSVhBIHwgbnVtw6lyaWNvIHwgUmFpbyBkZSBhbGNhbmNlIGRvIGFycmVtZXNzbyBmZWl0byBkYSBjZXN0YSBlbSBww6lzIHwNCnwgREVGRU5TT1IgfCBjaGFyYWN0ZXIgfCBOb21lIGRvIGpvZ2Fkb3IgcXVlIGRlZmVuZGV1IG8gY2h1dGUgfA0KfCBQT05UVUHDh8ODTyB8IGNoYXJhY3RlciB8ICdBQ0VSVE8nIHNlIG8gdGlybyBmb3IgbWFyY2FkbywgY2FzbyBjb250csOhcmlvICdFUlJPJyB8DQoNCk5vIGluw61jaW8sIHJlYWxpemFtb3MgbyBjYXJyZWdhbWVudG8gZG9zIGRhZG9zIGUgYWx0ZXJhbW9zIGFsZ3VucyB0ZXJtb3MgdmlzYW5kbyBhIGNvbXBvc2nDp8OjbyBmdXR1cmEgZG9zIGdyw6FmaWNvcy4NCmBgYHtyfQ0KZGF0YSA8LSByZWFkX2NzdigibmJhX3BsYXllcnNfc2hvb3RpbmcuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkNCmRhdGEgPC0gZGF0YSAlPiUgDQogIG11dGF0ZShSQU5HRSA9IGdzdWIoIlwiIiwgIiIsIFJBTkdFKSkgJT4lIA0KICBtdXRhdGUoUkFOR0UgPSByZWNvZGUoUkFOR0UsDQogICAgICAgICAgICAgICAgICAgICAgICAiKDAsIDQpIiA9ICIwLTQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIig1LCA5KSIgPSAiNS05IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICIoMTAsIDE0KSIgPSAiMTAtMTQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIigxNSwgMTkpIiA9ICIxNS0xOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiKDIwLCAyNCkiID0gIjIwLTI0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICIoMjUsIDI5KSIgPSAiMjUtMjkiKSkgJT4lIA0KICBtdXRhdGUoU0NPUkUgPSByZWNvZGUoU0NPUkUsDQogICAgICAgICAgICAgICAgICAgICAgICAiTUFERSIgPSAiQUNFUlRPIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJNSVNTRUQiID0gIkVSUk8iKSkgJT4lIA0KICBtdXRhdGUoWCA9IHJvdW5kKFgsIDIpKSAlPiUgDQogIG11dGF0ZShZID0gcm91bmQoWSwgMikpDQoNCmRhdGEkUkFOR0UgPC0gZmFjdG9yKGRhdGEkUkFOR0UsDQogICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCIwLTQiLCAiNS05IiwgIjEwLTE0IiwgIjE1LTE5IiwgIjIwLTI0IiwgIjI1LTI5IikpDQpkYXRhICU+JSANCiAgRFQ6OmRhdGF0YWJsZSgpDQpgYGANCkNvbSBiYXNlIG5vcyBkYWRvcywgaXJlbW9zIHJlc3BvbmRlciBhbGd1bWFzIHBlcmd1bnRhczoNCg0KKioxLiBEb3MgYXJyZW1lc3NvcyByZWFsaXphZG9zLCBxdWFudG9zIGZvcmFtIGFjZXJ0b3MgZSBlcnJvcz8qKg0KYGBge3J9DQpkYXRhICU+JQ0KICBncm91cF9ieShTQ09SRSkgJT4lIA0KICBzdW1tYXJpc2UodG90YWwgPSBuKCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gU0NPUkUsIHkgPSB0b3RhbCwgZmlsbCA9IFNDT1JFKSkgKw0KICBnZW9tX2JhcihhbHBoYSA9IC41LCB3aWR0aCA9IC43NSwgc3RhdCA9ICdpZGVudGl0eScpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJBcnJlbWVzc29zOiBGYWxoYXMgZSBBY2VydG9zIiwNCiAgICBmaWxsID0gIiIsDQogICAgeSA9ICJjb3VudCIsDQogICAgeCA9ICJBUlJFTUVTU09TIg0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZ3JlZW4iLCAicmVkIikpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA0NTAsIDUwKSkgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUoDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIiIsDQogICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKHQgPSAtMTApLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gLjUpKSArDQogIGdlb21fdGV4dChhZXMoeSA9IHRvdGFsLCBsYWJlbCA9IHRvdGFsKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuOSksIGZvbnRmYWNlID0gJ2JvbGQnKQ0KYGBgDQrDiSBvYnNlcnZhZG8gcXVlIGjDoSBtYWlzIGFycmVtZXNzb3MgZmFsaG9zIGRvIHF1ZSBhY2VydG9zLCBkZSBmb3JtYSBnZXJhbDoNCmBgYHtyfQ0KZGF0YSAlPiUNCiAgZ3JvdXBfYnkoU0NPUkUpICU+JSANCiAgc3VtbWFyaXNlKHRvdGFsID0gbigpKSAlPiUgDQogIG11dGF0ZShwZXJjZW50ID0gcm91bmQodG90YWwvc3VtKHRvdGFsKSAqIDEwMCwgMikpICU+JSANCiAgRFQ6OmRhdGF0YWJsZSgpDQpgYGANCg0KKioyLiBRdWFsIGpvZ2Fkb3IgZmF6IG1haXMgYXJyZW1lc3Nvcz8gUXVhbnRvcyBkZXN0ZXMgc8OjbyBmYWxoYXMgZSBxdWFudG9zIHPDo28gYWNlcnRvcz8qKg0KYGBge3J9DQpkYXRhICU+JSANCiAgZ3JvdXBfYnkoU0hPT1RFUiwgU0NPUkUpICU+JSANCiAgc3VtbWFyaXNlKHRvdGFsID0gbigpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFNIT09URVIsIHkgPSB0b3RhbCwgZmlsbCA9IFNDT1JFKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScsIGFscGhhID0gLjUsIHdpZHRoID0gLjc1KSArDQogIGxhYnMoDQogICAgeCA9ICJKT0dBRE9SRVMiLA0KICAgIGZpbGwgPSAnJywNCiAgICB0aXRsZSA9ICdhcnJlbWVzc29zIHRvdGFpczogYWNlcnRvcy9lcnJvcyBwb3Igam9nYWRvcicpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygnZ3JlZW4nLCAncmVkJykpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICdib2xkJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gLjUpLA0KICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKHQgPSAtMTApKSArDQogICAgICBnZW9tX3RleHQoYWVzKFNIT09URVIsIGxhYmVsID0gdG90YWwpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43NSksIHNpemUgPSA0LCB2anVzdCA9IDEuNSwgZm9udGZhY2UgPSAnYm9sZCcpDQpgYGANCg0KUGVyY2ViZS1zZSBxdWUgbyBUcmFlIFlvdW5nIMOpIG8gam9nYWRvciBxdWUgZmF6IG1haXMgYXJyZW1lc3Nvcywgc2VuZG8gdsOhcmlvcyBkZXNzZXMgYWNlcnRvcywgbWFzIGEgbWFpb3JpYSBzw6NvIGZhbGhvcy4gTyDDum5pY28gcXVlIGFjZXJ0YSBtYWlzIGRvIHF1ZSBlcnJhIMOpIG8gam9nYWRvciBTZXRoIEN1cnJ5Lg0KDQpBZ29yYSB2YW1vcyBvYnNlcnZhciBlbSB0ZXJtb3MgZGUgcG9yY2VudGFnZW06DQoNCmBgYHtyfQ0KZGF0YSAlPiUgDQogIGdyb3VwX2J5KFNIT09URVIsIFNDT1JFKSAlPiUgDQogIHN1bW1hcmlzZSh0b3RhbCA9IG4oKSkgICU+JSANCiAgbXV0YXRlKHBlcmNlbnQgPSByb3VuZCh0b3RhbC9zdW0odG90YWwpKjEwMCwgMikpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gU0hPT1RFUiwgeSA9IHBlcmNlbnQsIGZpbGwgPSBTQ09SRSkpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAnc3RhY2snLCBhbHBoYSA9IC41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoJ2dyZWVuJywgJ3JlZCcpKSArDQogIGxhYnMoeCA9ICdKT0dBRE9SRVMnLA0KICAgICAgIHkgPSAnJScsDQogICAgICAgdGl0bGUgPSAnJSBlcnJvcy9hY2VydG9zIHBvciBqb2dhZG9yJykgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAnYm9sZCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAuNSksDQogICAgICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKHQgPSAtMTMpKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSwgZm9udGZhY2UgPSAnYm9sZCcpDQpgYGANCg0KUGVyY2ViZS1zZSBxdWUsIGFwZXNhciBkZSBzZXIgbyBsw61kZXIgZW0gYXJyZW1lc3NvcywgbyBUcmFlIFlvdW5nIHPDsyBhY2VydGEgNDMuMTYlIGRlbGVzLCBlbnF1YW50byBvIFNldGggQ3VycnkgbGlkZXJhIGVtIHRlcm1vcyBkZSBhY2VydG9zLCBjb20gNTcuODIlIGRlIMOqeGl0by4gSsOhIG8gam9nYWRvciBSdXNzZWwgw6kgbyBxdWUgbWFpcyBlcnJhLCBjb20gNjYuNjclIGRlIGZhbGhhIGVtIHNldXMgYXJyZW1lc3Nvcy4NCg0KKiozLiBRdWFudG9zIGFjZXJ0b3MvZXJyb3Mgc2UgcmVsYWNpb25hbSBjb20gYSBkaXN0w6JuY2lhIGRhIGNlc3RhIGUgbyBsb2NhbCBkZSBhcnJlbWVzc28gZGEgYm9sYT8qKg0KYGBge3J9DQpkYXRhICU+JSANCiAgZ3JvdXBfYnkoUkFOR0UsIFNDT1JFKSAlPiUgDQogIHN1bW1hcmlzZSh0b3RhbCA9IG4oKSkgJT4lDQogIG11dGF0ZShwZXJjZW50ID0gcm91bmQodG90YWwvc3VtKHRvdGFsKSAqIDEwMCwgMikpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gUkFOR0UsIHkgPSB0b3RhbCwgZmlsbCA9IFNDT1JFKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScsIGFscGhhID0gLjUsIHdpZHRoID0gLjc1KSArDQogIGxhYnMoeCA9ICdSQU5HRScsDQogICAgICAgeSA9ICdjb3VudCcsDQogICAgICAgZmlsbCA9ICcnLA0KICAgICAgIHRpdGxlID0gJ2FjZXJ0b3MgZSBlcnJvcyBlbSByZWxhw6fDo28gYW8gcmFuZ2UnKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoJ2dyZWVuJywgJ3JlZCcpKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMjAwLCAyNSkpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gJ2JvbGQnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gLjUpLA0KICAgICAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbih0ID0gLTEwKSkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHBlcmNlbnQsICclJykpLCANCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjc1KSwgDQogICAgICAgICAgICB2anVzdCA9IC0uNSwNCiAgICAgICAgICAgIHNpemUgPSAyLjUsIGZvbnRmYWNlID0gJ2JvbGQnKQ0KYGBgDQpPYnNlcnZhLXNlIHF1ZSBhIMO6bmljYSBkaXN0w6JuY2lhIGNvbSByZWxhw6fDo28gYWNlcnRvL2Vycm8gcG9zaXRpdmEgw6kgMC00LCBzdXDDtWUtc2UgcXVlIHBvciBzZXIgbWFpcyBwZXJ0byBkYSBjZXN0YSwgYSBjaGFuY2UgZGUgdW0gw6p4aXRvIHNlamEgbWFpb3IuDQpUYW1iw6ltIMOpIHBvc3PDrXZlbCBhbmFsaXNhciBxdWUgYSBkaXN0w6JuY2lhIDI1LTI5IMOpIGEgbWFpcyBkaWZpY2lsIGRlIGFjZXJ0YXIsIGNvbSBjZXJjYSBkZSAyLzMgZGUgZmFsaGFzLCBwb2RlbmRvIGluZmVyaXIgcXVlIHBvciBzZXIgbWFpcyBkaXN0YW50ZSwgYSBwcmVjaXPDo28gZG8gYXJyZW1lc3NvIGRpbWludWEuDQoNCioqNC4gRW0gcXVhaXMgcG9zacOnw7VlcyBkYSBxdWFkcmEgb3Mgam9nYWRvcmVzIG1haXMgYWNlcnRhbS9lcnJhbSA/KioNCmBgYHtyLGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTh9DQpkYXRhICU+JQ0KICAgIGdyb3VwX2J5KFNIT09URVIsIFJBTkdFLCBTQ09SRSkgJT4lIA0KICAgIHN1bW1hcmlzZSh0b3RhbCA9IG4oKSwpICU+JSANCiAgICBtdXRhdGUocGVyY2VudCA9IHJvdW5kKHRvdGFsL3N1bSh0b3RhbCkgKiAxMDAsIDIpKSAlPiUgDQogICAgZ2dwbG90KGFlcyh4ID0gUkFOR0UsIHkgPSBwZXJjZW50LCBmaWxsID0gU0NPUkUpKSArDQogICAgZ2VvbV9jb2woYWxwaGEgPSAuNSwgd2lkdGggPSAuODUsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoJ2dyZWVuJywgJ3JlZCcpKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTAwKSkgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9ICIlIGFjZXJ0by9lcnJvIGRvcyBqb2dhZG9yZXMgcG9yIHJhbmdlIiwNCiAgICAgIHkgPSAiJSBkZSBhY2VydG8vZXJybyBwb3IgcmFuZ2UiLA0KICAgICAgeCA9ICJSQU5HRSIsDQogICAgICBmaWxsID0gIiINCiAgICApICsNCiAgICBmYWNldF93cmFwKH4gU0hPT1RFUiwgbmNvbCA9IDIpICsNCiAgICB0aGVtZV9idygpICsNCiAgICB0aGVtZSgNCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IC41KSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgbGVnZW5kLmJveC5tYXJnaW4gPSBtYXJnaW4odCA9IC0xMCkpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHBlcmNlbnQsICclJykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjc1KSwgdmp1c3QgPSAtLjUsIHNpemUgPSAyLjUsIGZvbnRmYWNlID0gJ2JvbGQnKQ0KYGBgDQoqKk9ic2VydmHDp8O1ZXM6KioNCg0KLSBBY2VydG9zDQpDaHJpcyBQYXVsOiBzdWFzIHRheGFzIGRlIGFjZXJ0byBtYWlvciBzw6NvIG5vcyByYW5nZXMgMTAtMTQgZSAxNS0xOSwgc2VuZG8gYWNpbWEgZGUgMjUlOw0KU2V0aCBDdXJyeTogcG9zc3VpIG1haW9yIHRheGEgZGUgYWNlcnRvIGRlIHRvZG9zIG5vIHJhbmdlIDI1LTI5IGUgZW0gMjAtMjQsIGVsZSDDqSBib20gZW0gYWNlcnRhciBkZSBsb25nZTsNClJ1c3NlbCBXZXN0YnJvb2s6IHBvc3N1aSBhIG1haW9yIHRheGEgZGUgYWNlcnRvIG5vIHJhbmdlIDAtNGUgZSBlbXBhdGEgY29tIENocmlzIFBhdWwgbm8gMTUtMTk7DQpUcmFlIFlvdW5nOiDDqSBib20gdGFudG8gZGUgbG9uZ2UgY29tbyBkZSBwZXJ0bywgcG9zc3VpbmRvIHBvbnR1YcOnw7VlcyBlcXVpdmFsZW50ZXMgZGUgMC00LCAxNS0xOSBlIDI1LTI5Lg0KDQotIEVycm9zDQpDaGlzIFBhdWw6IGEgbWVub3IgdGF4YSBkZSBlcnJvIMOpIG5vIHJhbmdlIDAtNCwgbyBqb2dhZG9yIMOpIGJvbSDDoCBjdXJ0YSBkaXN0w6JuY2lhIGRhIGNlc3RhOw0KU2V0aCBDdXJyeTogNTAlIGRvcyBlcnJvcyBmb3JhbSBubyByYW5nZSAyNS0yOSwgcG9yw6ltIGVycmEgbWVub3MgbmEgZGlzdMOibmNpYSBkZSAwIGEgMTksIHByZWNpc2EgZm9jYXIgbmVzc2UgcmFuZ2U7DQpSdXNzZWwgV2VzdGJyb29rOiBtZW5vciB0YXhhIGRlIGVycm8gbm8gcmFuZ2UgMTAtMTQ7DQpUcmFlIFlvdW5nOiBhcGVzYXIgZGUgYWNlcnRhciBtdWl0byBkZSBsb25nZSwgYSBtYWlvciB0YXhhIGRlIGVycm8gZGVsZSDDqSBlbSAyNS0yOSwgY29tIGEgbWVub3IgZW0gMTUtMTkuDQoNCg0KKio1LiBRdWFsIG8gZGVzZW1wZW5obyBkb3Mgam9nYWRvcmVzIGF0YWNhbnRlcyBlbSByZWxhw6fDo28gYW9zIHNldXMgZGVmZW5zb3Jlcz8qKg0KDQpgYGB7cixmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTR9DQpkYXRhICU+JSANCiAgZmlsdGVyKFNIT09URVIgJWluJSBTSE9PVEVSKSAlPiUNCiAgZ3JvdXBfYnkoU0hPT1RFUiwgREVGRU5ERVIsIFNDT1JFKSAlPiUgDQogIHN1bW1hcmlzZSh0b3RhbCA9IG4oKSkgJT4lIA0KICBtdXRhdGUocGVyYyA9IHJvdW5kKHRvdGFsL3N1bSh0b3RhbCkqMTAwLCAyKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBERUZFTkRFUiwgZmlsbCA9IFNDT1JFKSkgKw0KICBnZW9tX2JhcihhZXMoeSA9IHBlcmMpLCBzdGF0ID0gJ2lkZW50aXR5JywgYWxwaGEgPSAuNSwgd2lkdGggPSAuNzUsIHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICBsYWJzKHggPSAnREVGRU5TT1InLA0KICAgICAgIHkgPSAnJSBERUZFU0EnLA0KICAgICAgIGZpbGwgPSAnJywNCiAgICAgICB0aXRsZSA9ICdEZXNlbXBlbmhvIGRvcyBhdGFjYW50ZXMgZW0gcmVsYcOnw6NvIGFvcyBkZWZlbnNvcmVzJykgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoJ2dyZWVuJywgJ3JlZCcpKSArDQogIGZhY2V0X3dyYXAofiBTSE9PVEVSLCBuY29sID0gMikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScsDQogICAgICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKHQgPSAtMTApLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gJ2JvbGQnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gLjUpKSArDQogIGdlb21fdGV4dChhZXMoeSA9IHBlcmMsIGxhYmVsID0gcGFzdGUwKHBlcmMsICclJykpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IC43NSksDQogICAgICAgICAgICB2anVzdCA9IC0uNSwNCiAgICAgICAgICAgIHNpemUgPSAyLA0KICAgICAgICAgICAgZm9udGZhY2UgPSAnYm9sZCcpDQpgYGANCioqT2JzZXJ2YcOnw7VlczoqKg0KDQotIENocmlzIFBhdWw6IMOpIHVtIGV4Y2VsZW50ZSBkZWZlbnNvciBzZSBmaWNhciBtYXJjYW5kbyBvIGpvZ2Fkb3IgUnVzc2VsbDsNCi0gUnVzc2VsbCBXZXN0YnJvb2s6IGFwZXNhciBkZSBmYWxoYXIgbmEgbWFpb3JpYSBkZSBzZXVzIGFycmVtZXNzb3MsIMOpIHVtIG1hcmNhZG9yIG11aXRvIGJvbSwgY2F1c2FuZG8gZmFsaGEgbm9zIGFycmVtZXNzb3MgZG9zIG91dHJvcyBqb2dhZG9yZXMgZW0gbWFpcyBkZSA3MCU7DQotIFNldGggQ3Vycnk6IMOpIHVtIMOzdGltbyBqb2dhZG9yIHBhcmEgZGVmZW5kZXIgb3MgYXJyZW1lc3NvcyBkbyBSdXNzZWwsIHBvcsOpbSBtYW50w6ltIG8gZXF1aWzDrWJyaW8gY29tIG8gQ2hyaXMgZSBvIFRyYWU7DQotIFRyYWUgWW91bmc6IMOpIHDDqXNzaW1vIGVtIGRlZmVuZGVyIG9zIGFycmVtZXNzb3MgZG8gU2V0aCBDdXJyeSBlIGRvIENocmlzIFBhdWwsIHRlbmRvIG1haW9yIMOqeGl0byBjb250cmEgbyBSdXNzZWwgKG8gcXVhbCBhaW5kYSBjb25zZWd1ZSBzYWlyIHBvc2l0aXZvKS4NCg0KDQoqKlBvciBmaW0sIHF1YWlzIGFzIHBvc2nDp8O1ZXMgZG9zIGFycmVtZXNzb3MgZmVpdG9zIHBlbG9zIGpvZ2Fkb3JlcyBlbSBzaXR1YcOnw7VlcyBkZSBhY2VydG9zL2Vycm9zPyoqDQoNCmBgYHtyfQ0KDQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBYLCB5ID0gWSwgY29sb3IgPSBTQ09SRSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IC43LCBzaXplID0gMS41KSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCdncmVlbicsICdyZWQnKSkgKw0KICBsYWJzKHRpdGxlID0gJ1Bvc2nDp8OjbyBkb3MgYXJyZW1lc3NvcycsDQogICAgICAgY29sb3IgPSAnJykgKw0KICBmYWNldF93cmFwKH4gU0hPT1RFUiwgbmNvbCA9IDIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nLA0KICAgICAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbih0ID0gLTEyKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICdib2xkJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IC41KSkgKw0KICBndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gKSkNCmBgYA0KRGUgbWFuZWlyYSBnZXJhbCwgbyBncsOhZmljbyBwZXJtaXRlIHZpc3VhbGl6YXIgbyBkZXNlbXBlbmhvIGRvcyBqb2dhZG9yZXMgZW0gcmVsYcOnw6NvIMOgIHBvc2nDp8OjbyBkZSBzZXVzIGFycmVtZXNzb3MsIGluZGljYW5kbyBxdWFpcyBqb2dhZG9yZXMgdGl2ZXJhbSB1bWEgbWVsaG9yIHByZWNpc8OjbyBlIGVmZXRpdmlkYWRlIGR1cmFudGUgbyBqb2dvLg0KDQotIENocmlzIFBhdWw6IHNldXMgYXJyZW1lc3NvcyBlc3TDo28gY29uY2VudHJhZG9zIG5hIHJlZ2nDo28gY2VudHJhbCBkbyBncsOhZmljbywgY29tIHVtYSBib2EgcHJvcG9yw6fDo28gZGUgYWNlcnRvcyBlIGVycm9zOw0KLSBSdXNzZWxsIFdlc3Ricm9vazogZmF6IHBvdWNvcyBhcnJlbWVzc29zIGVtIGNvbXBhcmHDp8OjbyBhb3Mgb3V0cm9zIGpvZ2Fkb3JlcywgdGVuZG8gbWFpcyBlcnJvcyBkbyBxdWUgYWNlcnRvcywgc2VuZG8gdW0gdGFudG8gZGlzcGVyc29zOw0KLSBTZXRoIEN1cnJ5OiBjb25zZWd1ZSBhcnJlbWVzc2FyIGEgYm9sYSBlIGZhemVyIGNlc3RhIGVtIGRpdmVyc2FzIHBvc2nDp8O1ZXMgZGEgcXVhZHJhOw0KLSBUcmFlIFlvdW5nOiBhcnJlbWVzc2EgZGUgZGl2ZXJzYXMgcG9zacOnw7VlcywgcG9yw6ltIHPDsyBwb3NzdWkgcmVsYcOnw6NvIHBvc2l0aXZhIG5vIHJhbmdlIDAtNA0KDQoqKkNvbmNsdXPDo286KioNCi0gQXBlc2FyIGRlIHRyYXplciBpbmZvcm1hw6fDtWVzIGludGVyZXNzYW50ZXMgKGRlIGZvcm1hIGdyw6FmaWNhKSwgbyBkYXRhc2V0IHV0aWxpemFkbyBwb3NzdWkgc29tZW50ZSBkYWRvcyBkZSBqb2dvcyBkZSBhbGd1bnMgcGxheW9mZnMgZGEgTkJBICgyMDIxKSwgZmF6ZW5kbyBjb20gcXVlIG8gdm9sdW1lIGRlIGluZm9ybWHDp8O1ZXMgc2VqYSBtdWl0byBwZXF1ZW5hIGUsIHBvcnRhbnRvLCBuw6NvIMOpIHJlY29tZW5kYWRvIHRpcmFyIGNvbmNsdXPDtWVzIGFzc2VydGl2YXMgYWNlcmNhIGRvcyBqb2dhZG9yZXMsIG1hcyBzaW0gYXBlbmFzIGFsZ3VtYXMgaWRlaWFzIGUgdmlzdWFsaXphw6fDtWVzIHF1ZSBvY29ycmVyYW0gbmVzc2VzIGpvZ29zIGVtIHF1ZXN0w6NvLiA=