1. Bibliotecas utilizadas
library(tidyverse)
library(here)
library(lubridate)
library(ggplot2)
library(knitr)
theme_set(theme_bw())
2. Carregando os dados para análise
Para melhor compreensão da análise, foi adicionada uma nova coluna nos dados referente a data realizada da busca, onde foi excluida a informação de horas.
É necessário realizar a comparação do número de clicks ifelse(num_clicks>0,1,0) e criar uma nova coluna (clicks) para armazenar esses dados de ‘0’ e ‘1’, tendo em vista que será considerado apenas o valor de ‘1’ click, mesmo que o usuário tenha clicado ‘2’ ou mais vezes.
buscas = read_csv(here::here("data/search_data.csv")) %>%
head(100000) %>%
mutate(day = round_date(session_start_date, unit = "day")) %>%
mutate (clicks = ifelse(num_clicks>0,1,0))
2.1 Variáveis utilizadas nas análises
group : Um marcador (“a” ou “b”);
results : Número de ocorrências retornadas para o usuário;
num_clicks: Número de ocorrências clicadas pelo usuário;
first_click: Posição da ocorrência que o usuário clicou primeiro;
session_start_date: Data do início da busca;
session_length: Duração da sessão.
3. Respostas para as questões
3.1 Qual é a taxa de cliques geral diária? Como isso varia entre os grupos?
Primeiramente, para relizar a análise do taxa de cliques geral os dados foram agrupados por sessão, por meio da variável session_id. A partir disso, foi criado um sumário para armazenar o valor máximo de cliques (ou seja, com valor 1), com também o dia e grupo por sessão. Logo em seguida, foi feito o agrupamento por dia, para que fosse possível realizar o cálculo da taxa de cliques geral diária. Por fim, a partir das análises efetuadas foi possível gerar o gráfico da Figura 1, em que no geral a taxa encontra-se entre 40%, havendo uma pequena variação de um dia para o outro.
clicks_rate = buscas %>%
group_by(session_id) %>%
summarise(click = max(clicks),
day = max(day),
group = max(group))
clickthrough_rate = clicks_rate %>%
group_by(day) %>%
summarise(clickthrough_rate = (sum(click)/length(session_id)))
clickthrough_rate %>%
ggplot(aes(x = day ,y = clickthrough_rate)) +
geom_bar(stat = "identity", fill = "#008B8B") +
labs(x = "day", y = "clickthrough rate", title = "Figura 1 - Taxa de cliques geral diária")

Enquanto na relação por grupos, um novo sumário foi criado por meio do anterior, onde os dados além de serem agrupados por dia, foram agrupados também por grupo. Dessa forma, foi gerado o gráfico de barras da Figura 2, em que é possível observar que o grupo ‘a’ apresenta a taxa de clique diária superior que o grupo ‘b’.
clicks_rate = buscas %>%
group_by(session_id) %>%
summarise(click = max(clicks),
day = max(day),
group = max(group))
clickthrough_rate_group = clicks_rate %>%
group_by(day, group) %>%
summarise(clickthrough_rate = (sum(click)/length(session_id)))
clickthrough_rate_group %>%
ggplot(mapping = aes(x = day, y = clickthrough_rate, fill = group)) +
geom_bar(stat = "identity", position = position_dodge(), color = "black") +
scale_fill_manual(values = c("#999999", "#FF8C00")) +
labs(x = "day", y = "clickthrough rate", title = "Figura 2 - Taxa de cliques geral diária entre os grupos")

3.2 Quais resultados as pessoas tendem a tentar primeiro? Como isso muda no dia-a-dia?
Como o objetivo da questão é realizar o levantamento de quais resultados as pessoas tendem a tentar primeiro, a variável first_click é responsável por armazenar o primeiro resultado de busca clicada por sessão. Dessa maneira, foi aplicado dois filtros para que somente sejam retornados os valores diferentes de NA e maiores que zero.
Na Figura 3 é verificado de forma mais clara, através de escala logarítmica, que a maioria tedem a tentar o primeiro resultado.
results = buscas %>%
filter(!is.na(first_click)) %>%
filter(first_click != 0)
glimpse(dados)
Observations: 24,268
Variables: 11
$ session_id [3m[38;5;246m<chr>[39m[23m "0001382e027b2ea4", "0001e8bb90445cb2", "00064fe77404...
$ search_index [3m[38;5;246m<dbl>[39m[23m 1, 1, 2, 1, 1, 1, 2, 2, 1, 3, 2, 1, 1, 1, 1, 1, 2, 1,...
$ session_length [3m[38;5;246m<dbl>[39m[23m 303, 435, 43, 339, 444, 112, 213, 443, 439, 84, 197, ...
$ session_start_timestamp [3m[38;5;246m<dbl>[39m[23m 2.016031e+13, 2.016031e+13, 2.016031e+13, 2.016030e+1...
$ session_start_date [3m[38;5;246m<dttm>[39m[23m 2016-03-07 08:49:55, 2016-03-05 09:24:15, 2016-03-05...
$ group [3m[38;5;246m<chr>[39m[23m "b", "b", "a", "a", "b", "a", "a", "a", "b", "a", "a"...
$ results [3m[38;5;246m<dbl>[39m[23m 18, 20, 1, 20, 20, 20, 20, 20, 9, 20, 1, 20, 20, 7, 7...
$ num_clicks [3m[38;5;246m<dbl>[39m[23m 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,...
$ first_click [3m[38;5;246m<dbl>[39m[23m 1, 1, 1, 1, 5, 1, 1, 1, 1, 4, 1, 1, 2, 1, 1, 2, 1, 1,...
$ day [3m[38;5;246m<dttm>[39m[23m 2016-03-07, 2016-03-05, 2016-03-05, 2016-03-04, 2016...
$ clicks [3m[38;5;246m<dbl>[39m[23m 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
results %>%
ggplot(aes(x=first_click)) +
geom_histogram(binwidth = 1, fill = "#CD5C5C") +
scale_x_log10() +
labs(y = "quantity", x = "first click", title = "Figura 3 - Resultados que as pessoas tendem a tentar primeiro")

Considerando a distribuição dos cliques por dia, é verificado no histograma da Figura 4 que na maioria dos dias os usuários continuam tentar o primeiro resultado, como também os 10 primeiros links.
buscas %>%
ggplot(aes(x = first_click, fill = day)) +
geom_histogram(binwidth = 2, fill = "#CD5C5C") +
scale_x_continuous(limits=c(0,30)) +
scale_y_continuous(limits=c(0, 1000)) +
facet_grid(~day) +
labs(x = "first click", y = "quantity", title = "Figura 4 - Distribuição diária") +
theme_grey()

3.3 Qual a taxa de resultados zero no geral? Como isso varia entre os grupos?
De acordo com a Wikimedia, a taxa de resultados zero trata-se da proporção de buscas que renderam em 0 resultados. Assim, na Figura 5 foi verificada esta distribuição por dia e observou-se que a taxa encontra-se entre 15% a 21%, com maiores destaques para o primeiro e último dia.
results_rate = buscas %>%
group_by(day) %>%
summarise(sessions = length(session_id),
results_zero = sum(results == 0),
rate = (results_zero/sessions) * 100)
glimpse (results_rate)
Observations: 9
Variables: 4
$ day [3m[38;5;246m<dttm>[39m[23m 2016-03-01, 2016-03-02, 2016-03-03, 2016-03-04, 2016-03-05, 201...
$ sessions [3m[38;5;246m<int>[39m[23m 5515, 13580, 13793, 13822, 10724, 10191, 12199, 13888, 6288
$ results_zero [3m[38;5;246m<int>[39m[23m 1160, 2573, 2534, 2580, 1877, 1915, 2209, 2474, 1255
$ rate [3m[38;5;246m<dbl>[39m[23m 21.03354, 18.94698, 18.37164, 18.66589, 17.50280, 18.79109, 18.1...
results_rate %>%
ggplot(aes(x = day, y = rate)) +
geom_bar(stat = "identity", fill = "#008B8B") +
labs(x = "day", y = "zero results rate", title = "Figura 5 - Taxa de resultados zero geral por dia")

Já com relação a variação entre os grupos ‘a’ e ‘b’, foi gerado um sumário onde os dados foram agrupados por dia, grupo e resultados, realizando o cálculo de proporção entre o somatório da variável criada session_group dividido por length(group).
Nesta Figura 6, é possível observar que nenhum grupo encontra-se acima ou abaixo do outro. No quinto dia o grupo ‘a’ apresentou maior taxa quando comparado a ‘b’, enquanto para o grupo ’b’o sexto dia mostra-se como maior taxa.
results_rate = buscas %>%
group_by(day, group, results) %>%
summarise(session_group = length(group)) %>%
mutate(rate_group = sum(session_group)/session_group)
glimpse (results_rate)
Observations: 477
Variables: 5
Groups: day, group [18]
$ day [3m[38;5;246m<dttm>[39m[23m 2016-03-01, 2016-03-01, 2016-03-01, 2016-03-01, 2016-03-01, 20...
$ group [3m[38;5;246m<chr>[39m[23m "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"...
$ results [3m[38;5;246m<dbl>[39m[23m 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 1...
$ session_group [3m[38;5;246m<int>[39m[23m 835, 242, 136, 86, 58, 64, 33, 25, 31, 24, 15, 20, 23, 17, 13, ...
$ rate_group [3m[38;5;246m<dbl>[39m[23m 4.649102, 16.041322, 28.544118, 45.139535, 66.931034, 60.656250...
results_rate %>%filter(results==0) %>%
ggplot(mapping = aes(x = day, y = rate_group, fill = group)) +
geom_bar(stat = "identity", position = position_dodge(), color = "black") +
scale_fill_manual(values = c("#999999", "#FF8C00")) +
labs(x = "day", y = "zero results rate", title = "Figura 6 - Taxa de resultados zero geral por dia entre os grupos")

LS0tDQp0aXRsZTogIkZ1bmRhbWVudG9zIGRlIFBlc3F1aXNhIGVtIENpw6puY2lhIGRhIENvbXB1dGHDp8OjbyBJSSINCmF1dGhvcjogIkwyUDIgLSBHw6lzc2ljYSBBbHZlcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiNFeHBsb3JhbmRvIG9zIGRhZG9zIGRhcyBTZXNzw7VlcywgQnVzY2FzIGUgTmF2ZWdhw6fDo28gZGEgV2lraW1lZGlhDQoNCk5vIHByZXNlbnRlIHJlbGF0w7NyaW8gw6kgdXRpbGl6YWRhIGEgZXhwbG9yYcOnw6NvIGRlIGRhZG9zIGRvIGRhdGFzZXQgZGlzcG9uaWJpbGl6YWRvIHBlbGEgV2lraW1lZGlhIEZvdW5kYXRpb24uIEFsw6ltIGRvIGRhdGFzZXQsIGVsZXMgYXByZXNlbnRhcmFtIGluc3RydcOnw7VlcyBlIHF1YXRybyBwZXJndW50YXMgYSBzZXJlbSByZXNwb25kaWRhcyBwb3IgbWVpbyBkb3MgZGFkb3MgZGlzcG9uaWJpbGl6YWRvcy4NCg0KTmFzIHNlw6fDtWVzIHNlZ3VpbnRlcyBzw6NvIGFwcmVzZW50YWRhcyBhcyBiaWJsaW90ZWNhcyBlIGRhZG9zIHV0aWxpemFkb3MgbmFzIGFuw6FsaXNlcywgYmVtIGNvbW8gYXMgcmVzcG9zdGFzIGUgYW7DoWxpc2VzIHBhcmEgYXMgcXVhdHJvIHBlcmd1bnRhcyBlbGVuY2FkYXMgcGVsYSBXaWtpbWVkaWEuIA0KDQojIDEuIEJpYmxpb3RlY2FzIHV0aWxpemFkYXMNCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGhlcmUpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoa25pdHIpDQp0aGVtZV9zZXQodGhlbWVfYncoKSkNCmBgYA0KDQojIDIuIENhcnJlZ2FuZG8gb3MgZGFkb3MgcGFyYSBhbsOhbGlzZSANCg0KUGFyYSBtZWxob3IgY29tcHJlZW5zw6NvIGRhIGFuw6FsaXNlLCBmb2kgYWRpY2lvbmFkYSB1bWEgbm92YSBjb2x1bmEgbm9zIGRhZG9zIHJlZmVyZW50ZSBhIGRhdGEgcmVhbGl6YWRhIGRhIGJ1c2NhLCBvbmRlIGZvaSBleGNsdWlkYSBhIGluZm9ybWHDp8OjbyBkZSBob3Jhcy4gIA0KDQrDiSBuZWNlc3PDoXJpbyByZWFsaXphciBhIGNvbXBhcmHDp8OjbyBkbyBuw7ptZXJvIGRlIGNsaWNrcyBpZmVsc2UobnVtX2NsaWNrcz4wLDEsMCkgZSBjcmlhciB1bWEgbm92YSBjb2x1bmEgKGNsaWNrcykgcGFyYSBhcm1hemVuYXIgZXNzZXMgZGFkb3MgZGUgJzAnIGUgJzEnLCB0ZW5kbyBlbSB2aXN0YSBxdWUgc2Vyw6EgY29uc2lkZXJhZG8gYXBlbmFzIG8gdmFsb3IgZGUgJzEnIGNsaWNrLCBtZXNtbyBxdWUgbyB1c3XDoXJpbyB0ZW5oYSBjbGljYWRvICcyJyBvdSBtYWlzIHZlemVzLg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KYnVzY2FzID0gcmVhZF9jc3YoaGVyZTo6aGVyZSgiZGF0YS9zZWFyY2hfZGF0YS5jc3YiKSkgJT4lDQpoZWFkKDEwMDAwMCkgJT4lIA0KbXV0YXRlKGRheSA9IHJvdW5kX2RhdGUoc2Vzc2lvbl9zdGFydF9kYXRlLCB1bml0ID0gImRheSIpKSAlPiUgDQptdXRhdGUgKGNsaWNrcyA9IGlmZWxzZShudW1fY2xpY2tzPjAsMSwwKSkNCmBgYA0KDQojIDIuMSBWYXJpw6F2ZWlzIHV0aWxpemFkYXMgbmFzIGFuw6FsaXNlcw0KDQpncm91cCA6IFVtIG1hcmNhZG9yICjigJxh4oCdIG91IOKAnGLigJ0pOw0KDQpyZXN1bHRzIDogTsO6bWVybyBkZSBvY29ycsOqbmNpYXMgcmV0b3JuYWRhcyBwYXJhIG8gdXN1w6FyaW87DQoNCm51bV9jbGlja3M6IE7Dum1lcm8gZGUgb2NvcnLDqm5jaWFzIGNsaWNhZGFzIHBlbG8gdXN1w6FyaW87DQoNCmZpcnN0X2NsaWNrOiBQb3Npw6fDo28gZGEgb2NvcnLDqm5jaWEgcXVlIG8gdXN1w6FyaW8gY2xpY291IHByaW1laXJvOw0KDQpzZXNzaW9uX3N0YXJ0X2RhdGU6IERhdGEgZG8gaW7DrWNpbyBkYSBidXNjYTsNCg0Kc2Vzc2lvbl9sZW5ndGg6IER1cmHDp8OjbyBkYSBzZXNzw6NvLg0KDQojIDMuIFJlc3Bvc3RhcyBwYXJhIGFzIHF1ZXN0w7Vlcw0KDQojIDMuMSBRdWFsIMOpIGEgdGF4YSBkZSBjbGlxdWVzIGdlcmFsIGRpw6FyaWE/IENvbW8gaXNzbyB2YXJpYSBlbnRyZSBvcyBncnVwb3M/DQoNClByaW1laXJhbWVudGUsIHBhcmEgcmVsaXphciBhIGFuw6FsaXNlIGRvIHRheGEgZGUgY2xpcXVlcyBnZXJhbCBvcyBkYWRvcyBmb3JhbSBhZ3J1cGFkb3MgcG9yIHNlc3PDo28sIHBvciBtZWlvIGRhIHZhcmnDoXZlbCBzZXNzaW9uX2lkLiBBIHBhcnRpciBkaXNzbywgZm9pIGNyaWFkbyB1bSBzdW3DoXJpbyBwYXJhIGFybWF6ZW5hciBvIHZhbG9yIG3DoXhpbW8gZGUgY2xpcXVlcyAob3Ugc2VqYSwgY29tIHZhbG9yIDEpLCBjb20gdGFtYsOpbSBvIGRpYSBlIGdydXBvIHBvciBzZXNzw6NvLiBMb2dvIGVtIHNlZ3VpZGEsIGZvaSBmZWl0byBvIGFncnVwYW1lbnRvIHBvciBkaWEsIHBhcmEgcXVlIGZvc3NlIHBvc3PDrXZlbCByZWFsaXphciBvIGPDoWxjdWxvIGRhIHRheGEgZGUgY2xpcXVlcyBnZXJhbCBkacOhcmlhLiBQb3IgZmltLCBhIHBhcnRpciBkYXMgYW7DoWxpc2VzIGVmZXR1YWRhcyBmb2kgcG9zc8OtdmVsIGdlcmFyIG8gZ3LDoWZpY28gZGEgRmlndXJhIDEsIGVtIHF1ZSBubyBnZXJhbCBhIHRheGEgZW5jb250cmEtc2UgZW50cmUgNDAlLCBoYXZlbmRvIHVtYSBwZXF1ZW5hIHZhcmlhw6fDo28gZGUgdW0gZGlhIHBhcmEgbyBvdXRyby4NCg0KYGBge3J9DQpjbGlja3NfcmF0ZSA9IGJ1c2NhcyAlPiUNCiAgICBncm91cF9ieShzZXNzaW9uX2lkKSAlPiUNCiAgICBzdW1tYXJpc2UoY2xpY2sgPSBtYXgoY2xpY2tzKSwNCiAgICAgICAgICAgICAgZGF5ID0gbWF4KGRheSksDQogICAgICAgICAgICAgIGdyb3VwID0gbWF4KGdyb3VwKSkNCg0KY2xpY2t0aHJvdWdoX3JhdGUgPSBjbGlja3NfcmF0ZSAlPiUNCiAgICBncm91cF9ieShkYXkpICU+JQ0KICAgIHN1bW1hcmlzZShjbGlja3Rocm91Z2hfcmF0ZSA9IChzdW0oY2xpY2spL2xlbmd0aChzZXNzaW9uX2lkKSkpDQoNCmNsaWNrdGhyb3VnaF9yYXRlICU+JQ0KICAgIGdncGxvdChhZXMoeCA9IGRheSAseSA9IGNsaWNrdGhyb3VnaF9yYXRlKSkgKw0KICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gIiMwMDhCOEIiKSArDQogICAgbGFicyh4ID0gImRheSIsIHkgPSAiY2xpY2t0aHJvdWdoIHJhdGUiLCB0aXRsZSA9ICJGaWd1cmEgMSAtIFRheGEgZGUgY2xpcXVlcyBnZXJhbCBkacOhcmlhIikNCmBgYA0KDQpFbnF1YW50byBuYSByZWxhw6fDo28gcG9yIGdydXBvcywgdW0gbm92byBzdW3DoXJpbyBmb2kgY3JpYWRvIHBvciBtZWlvIGRvIGFudGVyaW9yLCBvbmRlIG9zIGRhZG9zIGFsw6ltIGRlIHNlcmVtIGFncnVwYWRvcyBwb3IgZGlhLCBmb3JhbSBhZ3J1cGFkb3MgdGFtYsOpbSBwb3IgZ3J1cG8uIERlc3NhIGZvcm1hLCBmb2kgZ2VyYWRvIG8gZ3LDoWZpY28gZGUgYmFycmFzIGRhIEZpZ3VyYSAyLCBlbSBxdWUgw6kgcG9zc8OtdmVsIG9ic2VydmFyIHF1ZSBvIGdydXBvICdhJyBhcHJlc2VudGEgYSB0YXhhIGRlIGNsaXF1ZSBkacOhcmlhIHN1cGVyaW9yIHF1ZSBvIGdydXBvICdiJy4NCg0KYGBge3J9DQpjbGlja3NfcmF0ZSA9IGJ1c2NhcyAlPiUNCiAgICBncm91cF9ieShzZXNzaW9uX2lkKSAlPiUNCiAgICBzdW1tYXJpc2UoY2xpY2sgPSBtYXgoY2xpY2tzKSwNCiAgICAgICAgICAgICAgZGF5ID0gbWF4KGRheSksDQogICAgICAgICAgICAgIGdyb3VwID0gbWF4KGdyb3VwKSkNCg0KY2xpY2t0aHJvdWdoX3JhdGVfZ3JvdXAgPSBjbGlja3NfcmF0ZSAlPiUNCiAgICBncm91cF9ieShkYXksIGdyb3VwKSAlPiUNCiAgICBzdW1tYXJpc2UoY2xpY2t0aHJvdWdoX3JhdGUgPSAoc3VtKGNsaWNrKS9sZW5ndGgoc2Vzc2lvbl9pZCkpKQ0KDQpjbGlja3Rocm91Z2hfcmF0ZV9ncm91cCAlPiUNCiAgICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gZGF5LCB5ID0gY2xpY2t0aHJvdWdoX3JhdGUsIGZpbGwgPSBncm91cCkpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpLCBjb2xvciA9ICJibGFjayIpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOTk5OTk5IiwgIiNGRjhDMDAiKSkgKw0KICAgIGxhYnMoeCA9ICJkYXkiLCB5ID0gImNsaWNrdGhyb3VnaCByYXRlIiwgdGl0bGUgPSAiRmlndXJhIDIgLSBUYXhhIGRlIGNsaXF1ZXMgZ2VyYWwgZGnDoXJpYSBlbnRyZSBvcyBncnVwb3MiKQ0KYGBgDQoNCiMgMy4yIFF1YWlzIHJlc3VsdGFkb3MgYXMgcGVzc29hcyB0ZW5kZW0gYSB0ZW50YXIgcHJpbWVpcm8/IENvbW8gaXNzbyBtdWRhIG5vIGRpYS1hLWRpYT8NCg0KQ29tbyBvIG9iamV0aXZvIGRhIHF1ZXN0w6NvIMOpIHJlYWxpemFyIG8gbGV2YW50YW1lbnRvIGRlIHF1YWlzIHJlc3VsdGFkb3MgYXMgcGVzc29hcyB0ZW5kZW0gYSB0ZW50YXIgcHJpbWVpcm8sIGEgdmFyacOhdmVsIGZpcnN0X2NsaWNrIMOpIHJlc3BvbnPDoXZlbCBwb3IgYXJtYXplbmFyIG8gcHJpbWVpcm8gcmVzdWx0YWRvIGRlIGJ1c2NhIGNsaWNhZGEgcG9yIHNlc3PDo28uIERlc3NhIG1hbmVpcmEsIGZvaSBhcGxpY2FkbyBkb2lzIGZpbHRyb3MgcGFyYSBxdWUgc29tZW50ZSBzZWphbSByZXRvcm5hZG9zIG9zIHZhbG9yZXMgZGlmZXJlbnRlcyBkZSBOQSBlIG1haW9yZXMgcXVlIHplcm8uDQoNCk5hIEZpZ3VyYSAzIMOpIHZlcmlmaWNhZG8gZGUgZm9ybWEgbWFpcyBjbGFyYSwgYXRyYXbDqXMgZGUgZXNjYWxhIGxvZ2Fyw610bWljYSwgcXVlIGEgbWFpb3JpYSB0ZWRlbSBhIHRlbnRhciBvIHByaW1laXJvIHJlc3VsdGFkby4gDQoNCmBgYHtyfQ0KcmVzdWx0cyA9IGJ1c2NhcyAlPiUNCiAgICBmaWx0ZXIoIWlzLm5hKGZpcnN0X2NsaWNrKSkgJT4lDQogICAgZmlsdGVyKGZpcnN0X2NsaWNrICE9IDApDQoNCmdsaW1wc2UoZGFkb3MpDQoNCnJlc3VsdHMgJT4lDQogICAgZ2dwbG90KGFlcyh4PWZpcnN0X2NsaWNrKSkgKyANCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAiI0NENUM1QyIpICsgDQogICAgc2NhbGVfeF9sb2cxMCgpICsNCiAgICBsYWJzKHkgPSAicXVhbnRpdHkiLCB4ID0gImZpcnN0IGNsaWNrIiwgdGl0bGUgPSAiRmlndXJhIDMgLSBSZXN1bHRhZG9zIHF1ZSBhcyBwZXNzb2FzIHRlbmRlbSBhIHRlbnRhciBwcmltZWlybyIpDQpgYGANCg0KQ29uc2lkZXJhbmRvIGEgZGlzdHJpYnVpw6fDo28gZG9zIGNsaXF1ZXMgcG9yIGRpYSwgw6kgdmVyaWZpY2FkbyBubyBoaXN0b2dyYW1hIGRhIEZpZ3VyYSA0IHF1ZSBuYSBtYWlvcmlhIGRvcyBkaWFzIG9zIHVzdcOhcmlvcyBjb250aW51YW0gdGVudGFyIG8gcHJpbWVpcm8gcmVzdWx0YWRvLCBjb21vIHRhbWLDqW0gb3MgMTAgcHJpbWVpcm9zIGxpbmtzLg0KDQpgYGB7cn0NCmJ1c2NhcyAlPiUNCiAgICBnZ3Bsb3QoYWVzKHggPSBmaXJzdF9jbGljaywgZmlsbCA9IGRheSkpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIsIGZpbGwgPSAiI0NENUM1QyIpICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwzMCkpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwgMTAwMCkpICsNCiAgICBmYWNldF9ncmlkKH5kYXkpICsNCiAgICBsYWJzKHggPSAiZmlyc3QgY2xpY2siLCB5ID0gInF1YW50aXR5IiwgdGl0bGUgPSAiRmlndXJhIDQgLSBEaXN0cmlidWnDp8OjbyBkacOhcmlhIikgKyAgICAgICAgDQogICAgdGhlbWVfZ3JleSgpDQpgYGANCg0KIyAzLjMgUXVhbCBhIHRheGEgZGUgcmVzdWx0YWRvcyB6ZXJvIG5vIGdlcmFsPyBDb21vIGlzc28gdmFyaWEgZW50cmUgb3MgZ3J1cG9zPw0KDQpEZSBhY29yZG8gY29tIGEgV2lraW1lZGlhLCBhIHRheGEgZGUgcmVzdWx0YWRvcyB6ZXJvIHRyYXRhLXNlIGRhIHByb3BvcsOnw6NvIGRlIGJ1c2NhcyBxdWUgcmVuZGVyYW0gZW0gMCByZXN1bHRhZG9zLiBBc3NpbSwgbmEgRmlndXJhIDUgZm9pIHZlcmlmaWNhZGEgZXN0YSBkaXN0cmlidWnDp8OjbyBwb3IgZGlhIGUgb2JzZXJ2b3Utc2UgcXVlIGEgdGF4YSBlbmNvbnRyYS1zZSBlbnRyZSAxNSUgYSAyMSUsIGNvbSBtYWlvcmVzIGRlc3RhcXVlcyBwYXJhIG8gcHJpbWVpcm8gZSDDumx0aW1vIGRpYS4NCg0KYGBge3J9DQpyZXN1bHRzX3JhdGUgPSBidXNjYXMgJT4lDQogICAgZ3JvdXBfYnkoZGF5KSAlPiUNCiAgICBzdW1tYXJpc2Uoc2Vzc2lvbnMgPSBsZW5ndGgoc2Vzc2lvbl9pZCksIA0KICAgICAgICAgICAgICByZXN1bHRzX3plcm8gPSBzdW0ocmVzdWx0cyA9PSAwKSwgDQogICAgICAgICAgICAgIHJhdGUgPSAocmVzdWx0c196ZXJvL3Nlc3Npb25zKSAqIDEwMCkNCg0KZ2xpbXBzZSAocmVzdWx0c19yYXRlKQ0KDQpyZXN1bHRzX3JhdGUgJT4lDQogICAgZ2dwbG90KGFlcyh4ID0gZGF5LCB5ID0gcmF0ZSkpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICIjMDA4QjhCIikgKw0KICAgIGxhYnMoeCA9ICJkYXkiLCB5ID0gInplcm8gcmVzdWx0cyByYXRlIiwgdGl0bGUgPSAiRmlndXJhIDUgLSBUYXhhIGRlIHJlc3VsdGFkb3MgemVybyBnZXJhbCBwb3IgZGlhIikNCmBgYA0KDQpKw6EgY29tIHJlbGHDp8OjbyBhIHZhcmlhw6fDo28gZW50cmUgb3MgZ3J1cG9zICdhJyBlICdiJywgZm9pIGdlcmFkbyB1bSBzdW3DoXJpbyBvbmRlIG9zIGRhZG9zIGZvcmFtIGFncnVwYWRvcyBwb3IgZGlhLCBncnVwbyBlIHJlc3VsdGFkb3MsIHJlYWxpemFuZG8gbyBjw6FsY3VsbyBkZSBwcm9wb3LDp8OjbyBlbnRyZSBvIHNvbWF0w7NyaW8gZGEgdmFyacOhdmVsIGNyaWFkYSBzZXNzaW9uX2dyb3VwIGRpdmlkaWRvIHBvciBsZW5ndGgoZ3JvdXApLiANCg0KTmVzdGEgRmlndXJhIDYsIMOpIHBvc3PDrXZlbCBvYnNlcnZhciBxdWUgbmVuaHVtIGdydXBvIGVuY29udHJhLXNlIGFjaW1hIG91IGFiYWl4byBkbyBvdXRyby4gTm8gcXVpbnRvIGRpYSBvIGdydXBvICdhJyBhcHJlc2VudG91IG1haW9yIHRheGEgcXVhbmRvIGNvbXBhcmFkbyBhICdiJywgZW5xdWFudG8gcGFyYSBvIGdydXBvICdiJ28gc2V4dG8gZGlhIG1vc3RyYS1zZSBjb21vIG1haW9yIHRheGEuDQoNCmBgYHtyfQ0KDQpyZXN1bHRzX3JhdGUgPSBidXNjYXMgJT4lDQogICAgZ3JvdXBfYnkoZGF5LCBncm91cCwgcmVzdWx0cykgJT4lDQogICAgc3VtbWFyaXNlKHNlc3Npb25fZ3JvdXAgPSBsZW5ndGgoZ3JvdXApKSAlPiUNCiAgICBtdXRhdGUocmF0ZV9ncm91cCA9IHN1bShzZXNzaW9uX2dyb3VwKS9zZXNzaW9uX2dyb3VwKQ0KDQpnbGltcHNlIChyZXN1bHRzX3JhdGUpDQoNCnJlc3VsdHNfcmF0ZSAlPiVmaWx0ZXIocmVzdWx0cz09MCkgJT4lDQogICAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGRheSwgeSA9IHJhdGVfZ3JvdXAsIGZpbGwgPSBncm91cCkpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpLCBjb2xvciA9ICJibGFjayIpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOTk5OTk5IiwgIiNGRjhDMDAiKSkgKw0KICAgIGxhYnMoeCA9ICJkYXkiLCB5ID0gInplcm8gcmVzdWx0cyByYXRlIiwgdGl0bGUgPSAiRmlndXJhIDYgLSBUYXhhIGRlIHJlc3VsdGFkb3MgemVybyBnZXJhbCBwb3IgZGlhIGVudHJlIG9zIGdydXBvcyIpDQpgYGANCg0KIyAzLjQgQSBkdXJhw6fDo28gZGEgc2Vzc8OjbyDDqSBhcHJveGltYWRhbWVudGUgbyB0ZW1wbyBlbnRyZSBvIHByaW1laXJvIGUgbyDDumx0aW1vIGV2ZW50byBkZSB1bWEgc2Vzc8Ojby4gRXNjb2xoYSB1bWEgdmFyacOhdmVsIGRvIGNvbmp1bnRvIGRlIGRhZG9zIGUgZGVzY3JldmEgc3VhIHJlbGHDp8OjbyBjb20gbyB0YW1hbmhvIGRhIHNlc3PDo28uIFZpc3VhbGl6ZSBvIHJlbGFjaW9uYW1lbnRvLg0KDQpOYSBGaWd1cmEgNywgYSB2YXJpw6F2ZWwgZmlyc3RfY2xpY2sgZm9pIHJlbGFjaW9uYWRhIGNvbSBhIGR1cmHDp8OjbyBkYSBzZXNzw6NvIChzZXNzaW9uX2xlbmd0aCksIGRlIG1vZG8gYSBpbnZlc3RpZ2FyIHNlIHF1YW5kbyBvIHVzdcOhcmlvIGNsaWNhIG5vcyBwcmltZWlyb3MgcmVzdWx0YWRvcyBlbGUgcGFzc2EgYSBkdXJhciBtYWlzIHRlbXBvIG91IG7Do28gbmEgc2Vzc8Ojby4gDQoNCkFvIG9ic2VydmFyIG8gZ3LDoWZpY28gZ2VyYWRvLCDDqSB2aXN0byBxdWUgb3MgdXN1w6FyaW9zIHRlcm1pbmFtIHBhc3NhbmRvIG1haXMgdGVtcG8gbm9zIHByaW1laXJvcyByZXN1bHRhZG9zLiBUZW5kbyBlbSB2aXN0YSBxdWUgaMOhIHVtYSBtYWlvciBjb25jZW50cmHDp8OjbyBkb3MgZGFkb3Mgbm8gaW50ZXJ2YWxvIGRlIDAgw6AgMTAgbm8gZWl4byB2ZXJ0aWNhbCBjb20gcmVsYcOnw6NvIGFvIGVpeG8gaG9yaXpvbnRhbCBjb20gbWFpb3IgY29uY2VudHJhw6fDo28gZG9zIGRhZG9zIG5vIGludGVydmFsbyBkZSAwIMOgIDEwMDAuDQoNCg0KYGBge3J9DQpidXNjYXMgJT4lDQogICAgZmlsdGVyKGZpcnN0X2NsaWNrIDw9IDUwKSAgJT4lDQogICAgZ2dwbG90KGFlcyh4ID0gc2Vzc2lvbl9sZW5ndGgsIHkgPSBmaXJzdF9jbGljaykpICsNCiAgICBnZW9tX3BvaW50KGFscGhhID0gLjIsIHNpemUgPSAyLCBjb2xvciA9ICIjQTUyQTJBIikgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLCA1MCkpICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMDAwKSkgKw0KICAgIGxhYnMoeCA9ICJzZXNzaW9uIGxlbmd0aCAoc2VjKSIsIHkgPSAiZmlyc3QgY2xpY2siLCB0aXRsZSA9ICJGaWd1cmEgNyAtIFJlbGHDp8OjbyBkYSBkdXJhw6fDo28gZGEgc2Vzc8OjbyBlbSBzZWd1bmRvcyBlIGNsaXF1ZXMiKSANCg0KYGBgDQoNCg0KDQo=