Neste problema, utilizaremos dados românticos descritos e disponíveis aqui: https://github.com/nazareno/ciencia-de-dados-1/tree/master/5-regressao/speed-dating

Especialmente, atente para uma coluna chamada dec, que diz se houve match entre os dois participantes do encontro – isso é: ambos disseram que gostariam de se encontrar novamente depois: https://github.com/nazareno/ciencia-de-dados-1/blob/master/5-regressao/speed-dating/speed-dating2.csv

Sua missão é utilizar regressão logística em um conjunto de variáveis explicativas que você escolher (com no mínimo 4 variáveis) para responder o seguinte com esses dados em um RMarkdown:

Que fatores nos dados têm efeito re;evante na chance do casal ter um match? Descreva se os efeitos são positivos ou negativos e sua magnitude.

Lembre que temos apenas uma amostra de encontros.

Lembre de fazer um descritivo das variáveis antes, e de escrever o relatório de maneira que alguém que saiba sobre regressão mas não sabe nada sobre os dados entenda.

Registered S3 method overwritten by 'dplyr':
  method           from
  print.rowwise_df     
── Attaching packages ─────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 3.2.0     ✔ purrr   0.3.2
✔ tibble  2.1.3     ✔ dplyr   0.8.3
✔ tidyr   0.8.3     ✔ stringr 1.4.0
✔ readr   1.3.1     ✔ forcats 0.4.0
── Conflicts ────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()

Attaching package: ‘modelr’

The following object is masked from ‘package:broom’:

    bootstrap

here() starts at /cloud/project/5-regressao
Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2

Attaching package: ‘GGally’

The following object is masked from ‘package:dplyr’:

    nasa

Classes and Methods for R developed in the
Political Science Computational Laboratory
Department of Political Science
Stanford University
Simon Jackman
hurdle and zeroinfl functions by Achim Zeileis

Dados dos speed datings

dados = read_csv(here::here("speed-dating/speed-dating2.csv"))
Parsed with column specification:
cols(
  .default = col_double(),
  field = col_character(),
  from = col_character(),
  career = col_character(),
  attr3_s = col_logical(),
  sinc3_s = col_logical(),
  intel3_s = col_logical(),
  fun3_s = col_logical(),
  amb3_s = col_logical(),
  dec = col_character()
)
See spec(...) for full column specifications.
10220 parsing failures.
 row      col           expected actual                                                        file
1847 attr3_s  1/0/T/F/TRUE/FALSE  8.00  '/cloud/project/5-regressao/speed-dating/speed-dating2.csv'
1847 sinc3_s  1/0/T/F/TRUE/FALSE  10.00 '/cloud/project/5-regressao/speed-dating/speed-dating2.csv'
1847 intel3_s 1/0/T/F/TRUE/FALSE  9.00  '/cloud/project/5-regressao/speed-dating/speed-dating2.csv'
1847 fun3_s   1/0/T/F/TRUE/FALSE  10    '/cloud/project/5-regressao/speed-dating/speed-dating2.csv'
1847 amb3_s   1/0/T/F/TRUE/FALSE  10    '/cloud/project/5-regressao/speed-dating/speed-dating2.csv'
.... ........ .................. ...... ...........................................................
See problems(...) for more details.
dados = dados %>%
  filter(!is.na(attr), !is.na(fun), !is.na(intel), !is.na(sinc), !is.na(amb), !is.na(shar), !is.na(prob), !is.na(like)) %>%
  mutate(dec = case_when(.$dec == "no" ~ 0, 
                              .$dec == "yes" ~ 1))

glimpse(dados)
Observations: 4,101
Variables: 44
$ iid      <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,…
$ gender   <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ order    <dbl> 4, 3, 5, 7, 6, 1, 2, 8, 9, 10, 9, 6, 1, 3, 2, 7, 8, 4, 5, 6, 5, 2, 7, 3, 4, 10, …
$ pid      <dbl> 11, 12, 14, 15, 16, 17, 18, 19, 20, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 11, …
$ int_corr <dbl> 0.14, 0.54, 0.61, 0.21, 0.25, 0.34, 0.50, 0.28, -0.36, 0.29, 0.18, 0.10, -0.21, …
$ samerace <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,…
$ age_o    <dbl> 27, 22, 23, 24, 25, 30, 27, 28, 24, 27, 22, 22, 23, 24, 25, 30, 27, 28, 24, 27, …
$ age      <dbl> 21, 21, 21, 21, 21, 21, 21, 21, 21, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, …
$ field    <chr> "Law", "Law", "Law", "Law", "Law", "Law", "Law", "Law", "Law", "law", "law", "la…
$ race     <dbl> 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,…
$ from     <chr> "Chicago", "Chicago", "Chicago", "Chicago", "Chicago", "Chicago", "Chicago", "Ch…
$ career   <chr> "lawyer", "lawyer", "lawyer", "lawyer", "lawyer", "lawyer", "lawyer", "lawyer", …
$ sports   <dbl> 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,…
$ tvsports <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8,…
$ exercise <dbl> 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,…
$ dining   <dbl> 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 8…
$ museums  <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5, 5, 5,…
$ art      <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5,…
$ hiking   <dbl> 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8, 8,…
$ gaming   <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,…
$ clubbing <dbl> 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5, 5, 5,…
$ reading  <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 7, 7, 7, 7, 7…
$ tv       <dbl> 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 8, 8, 8, 8, 8, 8,…
$ theater  <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7,…
$ movies   <dbl> 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7,…
$ concerts <dbl> 10, 10, 10, 10, 10, 10, 10, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,…
$ music    <dbl> 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5, 5, 5,…
$ shopping <dbl> 8, 8, 8, 8, 8, 8, 8, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8, 8,…
$ yoga     <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7,…
$ attr     <dbl> 6, 7, 7, 5, 4, 7, 4, 7, 5, 5, 8, 5, 7, 6, 8, 7, 5, 7, 6, 7, 9, 7, 9, 8, 7, 9, 8,…
$ sinc     <dbl> 9, 8, 6, 6, 9, 6, 9, 6, 6, 7, 5, 8, 9, 8, 7, 5, 8, 6, 7, 9, 7, 9, 7, 9, 9, 9, 7,…
$ intel    <dbl> 7, 7, 8, 7, 7, 7, 7, 8, 6, 8, 6, 9, 7, 7, 8, 9, 7, 8, 8, 10, 9, 9, 9, 10, 9, 9, …
$ fun      <dbl> 7, 8, 7, 7, 4, 4, 6, 9, 8, 4, 6, 6, 6, 9, 3, 6, 5, 9, 7, 7, 8, 7, 7, 7, 8, 9, 7,…
$ amb      <dbl> 6, 5, 6, 6, 6, 6, 5, 8, 10, 6, 9, 3, 5, 7, 6, 7, 9, 4, 9, 8, 9, 9, 9, 7, 9, 9, 9…
$ shar     <dbl> 5, 6, 8, 6, 4, 7, 6, 8, 8, 3, 6, 4, 7, 8, 2, 9, 5, 5, 8, 9, 7, 7, 7, 9, 7, 9, 7,…
$ like     <dbl> 7, 7, 7, 6, 6, 6, 6, 7, 6, 6, 7, 6, 7, 8, 6, 8, 5, 5, 8, 8, 8, 8, 8, 8, 8, 9, 8,…
$ prob     <dbl> 6, 5, 6, 6, 5, 5, 7, 7, 6, 4, 3, 7, 8, 6, 5, 7, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,…
$ match_es <dbl> 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, NA, NA, NA, NA, NA, NA,…
$ attr3_s  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ sinc3_s  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ intel3_s <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ fun3_s   <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ amb3_s   <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ dec      <dbl> 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,…

Olhada rápida nos dados

skimr::skim(dados)
Skim summary statistics
 n obs: 4101 
 n variables: 44 

── Variable type:character ─────────────────────────────────────────────────────────────────────────
 variable missing complete    n min max empty n_unique
   career      38     4063 4101   2  77     0      215
    field      13     4088 4101   3  51     0      145
     from      28     4073 4101   2  58     0      171

── Variable type:logical ───────────────────────────────────────────────────────────────────────────
 variable missing complete    n mean count
   amb3_s    4101        0 4101  NaN  4101
  attr3_s    4101        0 4101  NaN  4101
   fun3_s    4101        0 4101  NaN  4101
 intel3_s    4101        0 4101  NaN  4101
  sinc3_s    4101        0 4101  NaN  4101

── Variable type:numeric ───────────────────────────────────────────────────────────────────────────
 variable missing complete    n   mean     sd    p0   p25    p50    p75  p100     hist
      age      37     4064 4101  25.7    3.23 18    23     25     28     38   ▁▇▆▇▃▁▁▁
    age_o      43     4058 4101  25.72   3.32 18    23     25     28     39   ▁▇▆▇▃▁▁▁
      amb       0     4101 4101   6.68   1.84  0     5.5    7      8     10   ▁▁▁▇▇▇▇▆
      art      28     4073 4101   6.59   2.33  0     5      7      8     10   ▁▁▃▇▃▆▇▇
     attr       0     4101 4101   6.05   1.94  0     5      6      7     10   ▁▁▂▇▆▆▅▃
 clubbing      28     4073 4101   5.72   2.46  0     4      6      8     10   ▃▂▃▇▆▆▇▅
 concerts      28     4073 4101   6.81   2.14  0     6      7      8     10   ▁▁▂▅▆▆▆▇
      dec       0     4101 4101   0.42   0.49  0     0      0      1      1   ▇▁▁▁▁▁▁▆
   dining      28     4073 4101   7.69   1.77  1     7      8      9     10   ▁▁▁▂▂▅▅▇
 exercise      28     4073 4101   6.13   2.35  1     5      6      8     10   ▅▃▃▆▇▇▇▇
      fun       0     4101 4101   6.27   1.99  0     5      6      8     10   ▁▁▂▇▇▇▆▅
   gaming      28     4073 4101   4.04   2.65  0     2      4      6     14   ▆▇▆▆▂▁▁▁
   gender       0     4101 4101   0.5    0.5   0     0      0      1      1   ▇▁▁▁▁▁▁▇
   hiking      28     4073 4101   5.66   2.54  0     4      6      8     10   ▂▃▅▇▆▅▆▆
      iid       0     4101 4101 273.48 184.73  1    87    271    433    552   ▇▇▁▆▃▅▃▇
 int_corr      52     4049 4101   0.19   0.31 -0.73 -0.03   0.21   0.43   0.9 ▁▂▅▆▇▇▅▁
    intel       0     4101 4101   7.25   1.59  0     6      7      8     10   ▁▁▁▃▅▇▇▆
     like       0     4101 4101   6.03   1.86  0     5      6      7     10   ▁▁▂▇▇▇▅▂
 match_es     348     3753 4101   3.1    2.4   0     2      3      4     10   ▇▇▆▆▁▁▁▂
   movies      28     4073 4101   7.94   1.72  0     7      8      9     10   ▁▁▁▁▂▃▅▇
  museums      28     4073 4101   6.89   2.11  0     6      7      8     10   ▁▁▂▅▃▇▆▇
    music      28     4073 4101   7.8    1.88  1     7      8      9     10   ▁▁▁▂▂▃▃▇
    order       0     4101 4101   9.09   5.61  1     4      8     13     22   ▇▇▅▆▅▃▃▂
      pid       8     4093 4101 273.74 184.24  1    88    273    433    552   ▇▇▁▆▃▅▃▇
     prob       0     4101 4101   5.04   2.18  0     4      5      7     10   ▂▂▂▇▃▃▂▁
     race      13     4088 4101   2.75   1.23  1     2      2      4      6   ▁▇▁▁▃▁▁▁
  reading      28     4073 4101   7.65   2.06  1     7      8      9     13   ▁▁▁▅▃▇▁▁
 samerace       0     4101 4101   0.4    0.49  0     0      0      1      1   ▇▁▁▁▁▁▁▆
     shar       0     4101 4101   5.3    2.16  0     4      5      7     10   ▁▂▂▇▅▃▂▂
 shopping      28     4073 4101   5.51   2.59  1     4      6      7     10   ▇▃▅▆▆▆▅▆
     sinc       0     4101 4101   7.03   1.81  0     6      7      8     10   ▁▁▁▅▆▇▇▆
   sports      28     4073 4101   6.37   2.53  1     5      7      8     10   ▃▂▃▃▅▅▆▇
  theater      28     4073 4101   6.69   2.28  0     5      7      8     10   ▁▁▂▆▃▆▅▇
       tv      28     4073 4101   5.32   2.47  1     3      6      7     10   ▇▃▃▆▇▆▆▃
 tvsports      28     4073 4101   4.55   2.81  1     2      4      7     10   ▇▃▂▂▂▂▂▃
     yoga      28     4073 4101   4.17   2.72  0     2      3      6     10   ▇▆▆▆▃▃▂▃

Após essa análise rápida, vamos analisar melhor alguns dos dados no próximo tópico.

Histogramas

Faremos a análise das informações que o participante dá uma nota de 1 a 10 no formulário que recebe. Essas informações são as seguintes:

As quantidades para cada resposta foram:


dados %>% 
  ggplot(aes(attr)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 10, 1))


dados %>% 
  ggplot(aes(sinc)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 10, 1))



dados %>% 
  ggplot(aes(intel)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 10, 1))



dados %>% 
  ggplot(aes(fun)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 10, 1))


dados %>% 
  ggplot(aes(amb)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 10, 1))


dados %>% 
  ggplot(aes(shar)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 10, 1))


dados %>% 
  ggplot(aes(like)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 10, 1))


dados %>% 
  ggplot(aes(prob)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 10, 1))

Com isso, temos material para inferir que talvez essas variáveis se relacionem e possam influenciar no match, visto que essas distribuições das respostas se aproximam de uma distribuição normal. Veremos também o número de decisões “não” (0 no gráfico) e “sim” (1 no gráfico)

# decisoes (0 = no, 1 = yes)
dados %>% 
  ggplot(aes(dec)) + 
  geom_bar() + 
  scale_x_continuous(breaks=seq(0, 1, by = 1))

Visto isso, parece que há alguma relação entre as variáveis escolhidas e a decisão de se encontrar novamente. Já podemos passar para a modelagem.

Modelando a regressão logística multivariada


modelo1 <- glm(dec ~ attr + fun + intel + sinc + amb + shar + like + prob, 
          data = dados, 
          family = "binomial")

tidy(modelo1, conf.int = TRUE)
tidy(modelo1, conf.int = TRUE, exponentiate = TRUE)

glance(modelo1)
pR2(modelo1)
          llh       llhNull            G2      McFadden          r2ML          r2CU 
-1888.4241414 -2793.2364426  1809.6246024     0.3239297     0.3567773     0.4795981 

Com isso, podemos obter uma regressão dos speed datings:

dec = 0,43 attr + 0,12 fun - 0,04 intel - 0,23 sinc - 0,21 amb + 0,15 shar + 0,62 like + 0,16 prob - 5,99


Descrevendo se os efeitos são positivos ou negativos e sua magnitude:

  • attr : o aumento de 1 unidade de atraente produz um aumento de 0,43 na decisão
  • fun : o aumento de 1 unidade de divertido produz um aumento de 0,12 na decisão
  • intel : o aumento de 1 unidade de inteligente produz uma redução de 0,04 na decisão
  • sinc : o aumento de 1 unidade de sincero produz uma redução de 0,23 na decisão
  • amb : o aumento de 1 unidade de ambicioso produz uma redução de 0,21 na decisão
  • shar : o aumento de 1 unidade de compartilha interesses e hobbies produz um aumento de 0,15 na decisão
  • like : o aumento de 1 unidade de quanto gostou produz um aumento de 0,62 na decisão
  • prob : o aumento de 1 unidade de probabilidade de querer se encontrar novamente produz um aumento de 0,16 na decisão

Tudo isso aconteceria caso a regressão fosse linear. Como não é, precisamos EXPONENCIAR.


EXPONENCIANDO:

Como aqui y = exp(b0)exp(b1x1), aumentar em uma unidade x, faz com que y seja multiplicado por exp(b1)

dec = exp(1.54 * attr) * exp(1.13 * fun) * exp(0.95 * intel) * exp(0.79 * sinc) * exp(0.80 * amb) * exp(1.16 * shar) * exp(1.85 * like) * exp(1.18 * prob) * 0.002


Descrevendo se os efeitos são positivos ou negativos e sua magnitude:

  • attr : aumentar em uma unidade faz com que y seja multiplicado por 1.54
  • fun : aumentar em uma unidade faz com que y seja multiplicado por 1.13
  • intel : aumentar em uma unidade faz com que y seja multiplicado por 0.95
  • sinc : aumentar em uma unidade faz com que y seja multiplicado por 0.79
  • amb : aumentar em uma unidade faz com que y seja multiplicado por 0.80
  • shar : aumentar em uma unidade faz com que y seja multiplicado por 1.16
  • like : aumentar em uma unidade faz com que y seja multiplicado por 1.85
  • prob : aumentar em uma unidade faz com que y seja multiplicado por 1.18

Plotando o gráfico para a regressão utilizando apenas dec e fun:

dados %>% ggplot(aes(fun, dec))+geom_jitter(size=0.5)+geom_smooth(method = "glm", 
    method.args = list(family = "binomial"), 
    se = FALSE)

Fit relacionando preferências e gêneros em speed dating

dados %>%
  mutate(dec = as.factor(dec),
         gender = as.factor(gender))
gendermodel = glm(dec ~ gender,
                  data = dados,
                  family = "binomial")
tidy(gendermodel, conf.int = TRUE, exponentiate = TRUE)
glance(gendermodel)
pR2(gendermodel)
          llh       llhNull            G2      McFadden          r2ML          r2CU 
-2.760453e+03 -2.793236e+03  6.556702e+01  1.173675e-02  1.586093e-02  2.132106e-02 
expectativa_realidade <- augment(gendermodel,
                                type.predict = "response")

expectativa_realidade %>%
  mutate(genderNum = ifelse(gender == "1", 1, 0)) %>%
  ggplot(aes(x = gender )) +
  geom_count(aes(y = genderNum), alpha = 0.5) +
  geom_line(aes(y = .fitted))


expectativa_realidade = expectativa_realidade %>%
  mutate(categoria_prevista = ifelse(.fitted > .5, "1", "0"))

table(expectativa_realidade$categoria_prevista, expectativa_realidade$gender)
   
       0    1
  0 2068 2033

LS0tCnRpdGxlOiAiUmVncmVzc8OjbyBSb23Dom50aWNhIC0gU3BlZWQgRGF0aW5nIgphdXRob3I6ICJBbmRyw6kgRmVsaXBlIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpOZXN0ZSBwcm9ibGVtYSwgdXRpbGl6YXJlbW9zIGRhZG9zIHJvbcOibnRpY29zIGRlc2NyaXRvcyBlIGRpc3BvbsOtdmVpcyBhcXVpOiBodHRwczovL2dpdGh1Yi5jb20vbmF6YXJlbm8vY2llbmNpYS1kZS1kYWRvcy0xL3RyZWUvbWFzdGVyLzUtcmVncmVzc2FvL3NwZWVkLWRhdGluZyAKCkVzcGVjaWFsbWVudGUsIGF0ZW50ZSBwYXJhIHVtYSBjb2x1bmEgY2hhbWFkYSBgZGVjYCwgcXVlIGRpeiBzZSBob3V2ZSBtYXRjaCBlbnRyZSBvcyBkb2lzIHBhcnRpY2lwYW50ZXMgZG8gZW5jb250cm8gLS0gaXNzbyDDqTogYW1ib3MgZGlzc2VyYW0gcXVlIGdvc3RhcmlhbSBkZSBzZSBlbmNvbnRyYXIgbm92YW1lbnRlIGRlcG9pczogaHR0cHM6Ly9naXRodWIuY29tL25hemFyZW5vL2NpZW5jaWEtZGUtZGFkb3MtMS9ibG9iL21hc3Rlci81LXJlZ3Jlc3Nhby9zcGVlZC1kYXRpbmcvc3BlZWQtZGF0aW5nMi5jc3YKClN1YSBtaXNzw6NvIMOpIHV0aWxpemFyIHJlZ3Jlc3PDo28gbG9nw61zdGljYSBlbSB1bSBjb25qdW50byBkZSB2YXJpw6F2ZWlzIGV4cGxpY2F0aXZhcyBxdWUgdm9jw6ogZXNjb2xoZXIgKGNvbSBubyBtw61uaW1vIDQgdmFyacOhdmVpcykgcGFyYSByZXNwb25kZXIgbyBzZWd1aW50ZSBjb20gZXNzZXMgZGFkb3MgZW0gdW0gUk1hcmtkb3duOiAKClF1ZSBmYXRvcmVzIG5vcyBkYWRvcyB0w6ptIGVmZWl0byByZTtldmFudGUgbmEgY2hhbmNlIGRvIGNhc2FsIHRlciB1bSBtYXRjaD8gRGVzY3JldmEgc2Ugb3MgZWZlaXRvcyBzw6NvIHBvc2l0aXZvcyBvdSBuZWdhdGl2b3MgZSBzdWEgbWFnbml0dWRlLiAKCkxlbWJyZSBxdWUgdGVtb3MgYXBlbmFzIHVtYSBhbW9zdHJhIGRlIGVuY29udHJvcy4KCkxlbWJyZSBkZSBmYXplciB1bSBkZXNjcml0aXZvIGRhcyB2YXJpw6F2ZWlzIGFudGVzLCBlIGRlIGVzY3JldmVyIG8gcmVsYXTDs3JpbyBkZSBtYW5laXJhIHF1ZSBhbGd1w6ltIHF1ZSBzYWliYSBzb2JyZSByZWdyZXNzw6NvIG1hcyBuw6NvIHNhYmUgbmFkYSBzb2JyZSBvcyBkYWRvcyBlbnRlbmRhLgoKYGBge3Igd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkobW9kZWxyKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoR0dhbGx5KQpsaWJyYXJ5KHBzY2wpCmxpYnJhcnkoY2FUb29scykKIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImhhZGxleS9tb2RlbHIiKQoKCnRoZW1lX3NldCh0aGVtZV9idygpKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KHRpZHkgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDYsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0ID0gNSkKCnBhbGV0YSA9IGMoIiM0MDRFNEQiLAogICAgICAgICAgICIjOTJEQ0U1IiwKICAgICAgICAgICAiIzkzOEJBMSIsCiAgICAgICAgICAgIiMyRDMxNDIiLAogICAgICAgICAgICIjRjQ3NDNCIikKYGBgCgojIyBEYWRvcyBkb3Mgc3BlZWQgZGF0aW5ncwoKYGBge3J9CmRhZG9zID0gcmVhZF9jc3YoaGVyZTo6aGVyZSgic3BlZWQtZGF0aW5nL3NwZWVkLWRhdGluZzIuY3N2IikpCgpkYWRvcyA9IGRhZG9zICU+JQogIGZpbHRlcighaXMubmEoYXR0ciksICFpcy5uYShmdW4pLCAhaXMubmEoaW50ZWwpLCAhaXMubmEoc2luYyksICFpcy5uYShhbWIpLCAhaXMubmEoc2hhciksICFpcy5uYShwcm9iKSwgIWlzLm5hKGxpa2UpKSAlPiUKICBtdXRhdGUoZGVjID0gY2FzZV93aGVuKC4kZGVjID09ICJubyIgfiAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLiRkZWMgPT0gInllcyIgfiAxKSkKCmdsaW1wc2UoZGFkb3MpCmBgYAoKIyMgT2xoYWRhIHLDoXBpZGEgbm9zIGRhZG9zCgpgYGB7cn0Kc2tpbXI6OnNraW0oZGFkb3MpCmBgYAoKQXDDs3MgZXNzYSBhbsOhbGlzZSByw6FwaWRhLCB2YW1vcyBhbmFsaXNhciBtZWxob3IgYWxndW5zIGRvcyBkYWRvcyBubyBwcsOzeGltbyB0w7NwaWNvLgoKIyMgSGlzdG9ncmFtYXMKCkZhcmVtb3MgYSBhbsOhbGlzZSBkYXMgaW5mb3JtYcOnw7VlcyBxdWUgbyBwYXJ0aWNpcGFudGUgZMOhIHVtYSBub3RhIGRlIDEgYSAxMCBubyBmb3JtdWzDoXJpbyBxdWUgcmVjZWJlLiBFc3NhcyBpbmZvcm1hw6fDtWVzIHPDo28gYXMgc2VndWludGVzOgoKLSBhdHRyIDogcXXDo28gYXRyYWVudGUgcDEgYWNob3UgcDIKLSBzaW5jIDogcXXDo28gc2luY2VybyBwMSBhY2hvdSBwMgotIGludGVsIDogcXXDo28gaW50ZWxpZ2VudGUgcDEgYWNob3UgcDIgICAgCi0gZnVuIDogcXXDo28gZGl2ZXJ0aWRvIHAxIGFjaG91IHAyCi0gYW1iIDogcXXDo28gYW1iaWNpb3NvIHAxIGFjaG91IHAyCi0gc2hhciA6IHF1YW50byBwMSBhY2hvdSBxdWUgY29tcGFydGlsaGEgaW50ZXJlc3NlcyBlIGhvYmJpZXMgY29tIHAyCi0gbGlrZSA6IG5vIGdlcmFsLCBxdWFudG8gcDEgZ29zdG91IGRlIHAyCi0gcHJvYiA6IHF1ZSBwcm9iYWJpbGlkYWRlIHAxIGFjaGEgcXVlIHAyIHRlbSBkZSBxdWVyZXIgc2UgZW5jb250cmFyIG5vdmFtZW50ZSBjb20gcAoKQXMgcXVhbnRpZGFkZXMgcGFyYSBjYWRhIHJlc3Bvc3RhIGZvcmFtOgoKYGBge3J9CgpkYWRvcyAlPiUgCiAgZ2dwbG90KGFlcyhhdHRyKSkgKyAKICBnZW9tX2JhcigpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwgMTAsIDEpKQoKZGFkb3MgJT4lIAogIGdncGxvdChhZXMoc2luYykpICsgCiAgZ2VvbV9iYXIoKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDAsIDEwLCAxKSkKCgpkYWRvcyAlPiUgCiAgZ2dwbG90KGFlcyhpbnRlbCkpICsgCiAgZ2VvbV9iYXIoKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDAsIDEwLCAxKSkKCgpkYWRvcyAlPiUgCiAgZ2dwbG90KGFlcyhmdW4pKSArIAogIGdlb21fYmFyKCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLCAxMCwgMSkpCgpkYWRvcyAlPiUgCiAgZ2dwbG90KGFlcyhhbWIpKSArIAogIGdlb21fYmFyKCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLCAxMCwgMSkpCgpkYWRvcyAlPiUgCiAgZ2dwbG90KGFlcyhzaGFyKSkgKyAKICBnZW9tX2JhcigpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwgMTAsIDEpKQoKZGFkb3MgJT4lIAogIGdncGxvdChhZXMobGlrZSkpICsgCiAgZ2VvbV9iYXIoKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDAsIDEwLCAxKSkKCmRhZG9zICU+JSAKICBnZ3Bsb3QoYWVzKHByb2IpKSArIAogIGdlb21fYmFyKCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLCAxMCwgMSkpCgpgYGAKCkNvbSBpc3NvLCB0ZW1vcyBtYXRlcmlhbCBwYXJhIGluZmVyaXIgcXVlIHRhbHZleiBlc3NhcyB2YXJpw6F2ZWlzIHNlIHJlbGFjaW9uZW0gZSBwb3NzYW0gaW5mbHVlbmNpYXIgbm8gbWF0Y2gsIHZpc3RvIHF1ZSBlc3NhcyBkaXN0cmlidWnDp8O1ZXMgZGFzIHJlc3Bvc3RhcyBzZSBhcHJveGltYW0gZGUgdW1hIGRpc3RyaWJ1acOnw6NvIG5vcm1hbC4KVmVyZW1vcyB0YW1iw6ltIG8gbsO6bWVybyBkZSBkZWNpc8O1ZXMgIm7Do28iICgwIG5vIGdyw6FmaWNvKSBlICJzaW0iICgxIG5vIGdyw6FmaWNvKQoKYGBge3J9CiMgZGVjaXNvZXMgKDAgPSBubywgMSA9IHllcykKZGFkb3MgJT4lIAogIGdncGxvdChhZXMoZGVjKSkgKyAKICBnZW9tX2JhcigpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwgMSwgYnkgPSAxKSkKCmBgYAoKClZpc3RvIGlzc28sIHBhcmVjZSBxdWUgaMOhIGFsZ3VtYSByZWxhw6fDo28gZW50cmUgYXMgdmFyacOhdmVpcyBlc2NvbGhpZGFzIGUgYSBkZWNpc8OjbyBkZSBzZSBlbmNvbnRyYXIgbm92YW1lbnRlLiBKw6EgcG9kZW1vcyBwYXNzYXIgcGFyYSBhIG1vZGVsYWdlbS4KCiMgTW9kZWxhbmRvIGEgcmVncmVzc8OjbyBsb2fDrXN0aWNhIG11bHRpdmFyaWFkYQoKYGBge3J9Cgptb2RlbG8xIDwtIGdsbShkZWMgfiBhdHRyICsgZnVuICsgaW50ZWwgKyBzaW5jICsgYW1iICsgc2hhciArIGxpa2UgKyBwcm9iLCAKICAgICAgICAgIGRhdGEgPSBkYWRvcywgCiAgICAgICAgICBmYW1pbHkgPSAiYmlub21pYWwiKQoKdGlkeShtb2RlbG8xLCBjb25mLmludCA9IFRSVUUpCnRpZHkobW9kZWxvMSwgY29uZi5pbnQgPSBUUlVFLCBleHBvbmVudGlhdGUgPSBUUlVFKQoKZ2xhbmNlKG1vZGVsbzEpCnBSMihtb2RlbG8xKQoKYGBgCgoKQ29tIGlzc28sIHBvZGVtb3Mgb2J0ZXIgdW1hIHJlZ3Jlc3PDo28gZG9zIHNwZWVkIGRhdGluZ3M6Ci0tLQoKPiBkZWMgPSAwLDQzIGF0dHIgKyAwLDEyIGZ1biAtIDAsMDQgaW50ZWwgLSAwLDIzIHNpbmMgLSAwLDIxIGFtYiArIDAsMTUgc2hhciArIDAsNjIgbGlrZSArIDAsMTYgcHJvYiAtIDUsOTkKCi0tLQoKRGVzY3JldmVuZG8gc2Ugb3MgZWZlaXRvcyBzw6NvIHBvc2l0aXZvcyBvdSBuZWdhdGl2b3MgZSBzdWEgbWFnbml0dWRlOgoKLSBhdHRyIDogbyBhdW1lbnRvIGRlIDEgdW5pZGFkZSBkZSBhdHJhZW50ZSBwcm9kdXogdW0gYXVtZW50byBkZSAwLDQzIG5hIGRlY2lzw6NvCi0gZnVuIDogbyBhdW1lbnRvIGRlIDEgdW5pZGFkZSBkZSBkaXZlcnRpZG8gcHJvZHV6IHVtIGF1bWVudG8gZGUgMCwxMiBuYSBkZWNpc8OjbwotIGludGVsIDogbyBhdW1lbnRvIGRlIDEgdW5pZGFkZSBkZSBpbnRlbGlnZW50ZSBwcm9kdXogdW1hIHJlZHXDp8OjbyBkZSAwLDA0IG5hIGRlY2lzw6NvICAgIAotIHNpbmMgOiBvIGF1bWVudG8gZGUgMSB1bmlkYWRlIGRlIHNpbmNlcm8gcHJvZHV6IHVtYSByZWR1w6fDo28gZGUgMCwyMyBuYSBkZWNpc8OjbwotIGFtYiA6IG8gYXVtZW50byBkZSAxIHVuaWRhZGUgZGUgYW1iaWNpb3NvIHByb2R1eiB1bWEgcmVkdcOnw6NvIGRlIDAsMjEgbmEgZGVjaXPDo28KLSBzaGFyIDogbyBhdW1lbnRvIGRlIDEgdW5pZGFkZSBkZSBjb21wYXJ0aWxoYSBpbnRlcmVzc2VzIGUgaG9iYmllcyBwcm9kdXogdW0gYXVtZW50byBkZSAwLDE1IG5hIGRlY2lzw6NvCi0gbGlrZSA6IG8gYXVtZW50byBkZSAxIHVuaWRhZGUgZGUgcXVhbnRvIGdvc3RvdSBwcm9kdXogdW0gYXVtZW50byBkZSAwLDYyIG5hIGRlY2lzw6NvCi0gcHJvYiA6IG8gYXVtZW50byBkZSAxIHVuaWRhZGUgZGUgcHJvYmFiaWxpZGFkZSBkZSBxdWVyZXIgc2UgZW5jb250cmFyIG5vdmFtZW50ZSBwcm9kdXogdW0gYXVtZW50byBkZSAwLDE2IG5hIGRlY2lzw6NvCgpUdWRvIGlzc28gYWNvbnRlY2VyaWEgY2FzbyBhIHJlZ3Jlc3PDo28gZm9zc2UgbGluZWFyLiBDb21vIG7Do28gw6ksIHByZWNpc2Ftb3MgRVhQT05FTkNJQVIuCgotLS0KCiMgRVhQT05FTkNJQU5ETzoKCkNvbW8gYXF1aSB5ID0gZXhwKGIwKSpleHAoYjEqeDEpLCBhdW1lbnRhciBlbSB1bWEgdW5pZGFkZSB4LCBmYXogY29tIHF1ZSB5IHNlamEgbXVsdGlwbGljYWRvIHBvciBleHAoYjEpCi0tLQoKPiBkZWMgPSBleHAoMS41NCAqIGF0dHIpICogZXhwKDEuMTMgKiBmdW4pICogZXhwKDAuOTUgKiBpbnRlbCkgKiBleHAoMC43OSAqIHNpbmMpICogZXhwKDAuODAgKiBhbWIpICogZXhwKDEuMTYgKiBzaGFyKSAqIGV4cCgxLjg1ICogbGlrZSkgKiBleHAoMS4xOCAqIHByb2IpICogMC4wMDIKCi0tLQoKRGVzY3JldmVuZG8gc2Ugb3MgZWZlaXRvcyBzw6NvIHBvc2l0aXZvcyBvdSBuZWdhdGl2b3MgZSBzdWEgbWFnbml0dWRlOgoKLSBhdHRyIDogYXVtZW50YXIgZW0gdW1hIHVuaWRhZGUgZmF6IGNvbSBxdWUgeSBzZWphIG11bHRpcGxpY2FkbyBwb3IgMS41NAotIGZ1biA6IGF1bWVudGFyIGVtIHVtYSB1bmlkYWRlIGZheiBjb20gcXVlIHkgc2VqYSBtdWx0aXBsaWNhZG8gcG9yIDEuMTMKLSBpbnRlbCA6IGF1bWVudGFyIGVtIHVtYSB1bmlkYWRlIGZheiBjb20gcXVlIHkgc2VqYSBtdWx0aXBsaWNhZG8gcG9yIDAuOTUgICAgCi0gc2luYyA6IGF1bWVudGFyIGVtIHVtYSB1bmlkYWRlIGZheiBjb20gcXVlIHkgc2VqYSBtdWx0aXBsaWNhZG8gcG9yIDAuNzkKLSBhbWIgOiBhdW1lbnRhciBlbSB1bWEgdW5pZGFkZSBmYXogY29tIHF1ZSB5IHNlamEgbXVsdGlwbGljYWRvIHBvciAwLjgwCi0gc2hhciA6IGF1bWVudGFyIGVtIHVtYSB1bmlkYWRlIGZheiBjb20gcXVlIHkgc2VqYSBtdWx0aXBsaWNhZG8gcG9yIDEuMTYKLSBsaWtlIDogYXVtZW50YXIgZW0gdW1hIHVuaWRhZGUgZmF6IGNvbSBxdWUgeSBzZWphIG11bHRpcGxpY2FkbyBwb3IgMS44NQotIHByb2IgOiBhdW1lbnRhciBlbSB1bWEgdW5pZGFkZSBmYXogY29tIHF1ZSB5IHNlamEgbXVsdGlwbGljYWRvIHBvciAxLjE4CgotLS0KCgpQbG90YW5kbyBvIGdyw6FmaWNvIHBhcmEgYSByZWdyZXNzw6NvIHV0aWxpemFuZG8gYXBlbmFzIGRlYyBlIGZ1bjoKCmBgYHtyfQpkYWRvcyAlPiUgZ2dwbG90KGFlcyhmdW4sIGRlYykpK2dlb21faml0dGVyKHNpemU9MC41KStnZW9tX3Ntb290aChtZXRob2QgPSAiZ2xtIiwgCiAgICBtZXRob2QuYXJncyA9IGxpc3QoZmFtaWx5ID0gImJpbm9taWFsIiksIAogICAgc2UgPSBGQUxTRSkKYGBgCgoKIyBGaXQgcmVsYWNpb25hbmRvIHByZWZlcsOqbmNpYXMgZSBnw6puZXJvcyBlbSBzcGVlZCBkYXRpbmcKCmBgYHtyfQpkYWRvcyAlPiUKICBtdXRhdGUoZGVjID0gYXMuZmFjdG9yKGRlYyksCiAgICAgICAgIGdlbmRlciA9IGFzLmZhY3RvcihnZW5kZXIpKQpnZW5kZXJtb2RlbCA9IGdsbShkZWMgfiBnZW5kZXIsCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYWRvcywKICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gImJpbm9taWFsIikKdGlkeShnZW5kZXJtb2RlbCwgY29uZi5pbnQgPSBUUlVFLCBleHBvbmVudGlhdGUgPSBUUlVFKQpnbGFuY2UoZ2VuZGVybW9kZWwpCnBSMihnZW5kZXJtb2RlbCkKCmV4cGVjdGF0aXZhX3JlYWxpZGFkZSA8LSBhdWdtZW50KGdlbmRlcm1vZGVsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUucHJlZGljdCA9ICJyZXNwb25zZSIpCgpleHBlY3RhdGl2YV9yZWFsaWRhZGUgJT4lCiAgbXV0YXRlKGdlbmRlck51bSA9IGlmZWxzZShnZW5kZXIgPT0gIjEiLCAxLCAwKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2VuZGVyICkpICsKICBnZW9tX2NvdW50KGFlcyh5ID0gZ2VuZGVyTnVtKSwgYWxwaGEgPSAwLjUpICsKICBnZW9tX2xpbmUoYWVzKHkgPSAuZml0dGVkKSkKCmV4cGVjdGF0aXZhX3JlYWxpZGFkZSA9IGV4cGVjdGF0aXZhX3JlYWxpZGFkZSAlPiUKICBtdXRhdGUoY2F0ZWdvcmlhX3ByZXZpc3RhID0gaWZlbHNlKC5maXR0ZWQgPiAuNSwgIjEiLCAiMCIpKQoKdGFibGUoZXhwZWN0YXRpdmFfcmVhbGlkYWRlJGNhdGVnb3JpYV9wcmV2aXN0YSwgZXhwZWN0YXRpdmFfcmVhbGlkYWRlJGdlbmRlcikKYGBgCgo8IS0tCk91dHJvIGV4ZW1wbG8gZGUgcmVncmVzc8OjbyBsb2fDrXN0aWNhOiBodHRwczovL3JwdWJzLmNvbS9CZW5hcmRpL3NwZWVkX2RhdGluZ19sb2dpc3RpYwotLT4KCi0tLQ==