Objetivo: Aprender importar, transformar e visualizar dados no R com o tidyverse, usando pouquíssimas bases (principalmente penguins) e um exemplo prático para cada conceito.

0.1 1. Preparação do Ambiente

0.1.1 1.2 Filosofia tidy

  • Uma observação por linha; uma variável por coluna; um valor por célula.

  • Verbos coesos (select, filter, mutate, summarise, …).

  • Pipelines para legibilidade (|> recomendado).

Exemplo (estruturar e encadear):

penguins |>
  select(species, bill_length_mm, body_mass_g) |>
  filter(!is.na(bill_length_mm), !is.na(body_mass_g)) |>
  mutate(relacao = body_mass_g / bill_length_mm) |>
  head(3)
select: dropped 5 variables (island, bill_depth_mm, flipper_length_mm, sex, year)
filter: removed 2 rows (1%), 342 rows remaining
mutate: new variable 'relacao' (double) with 334 unique values and 0% NA

0.1.2 1.3 Operadores de pipe

  • Nativo R |> (preferido) e magrittr %>% (legado).
```r
1:5 |> mean()
```
```
[1] 3
```

0.2 2. tibbles e inspeção de dados

Conceitos: tibble, glimpse, impressão amigável, tipos.

Exemplo: criar tibble e inspecionar

glimpse(tb)
Rows: 5
Columns: 3
$ id   <int> 1, 2, 3, 4, 5
$ nome <chr> "ana", "bruno", "carla", "diego", "eva"
$ nota <dbl> 7.5, 8.2, 6.9, 9.1, 7.8
glimpse(penguins)
Rows: 344
Columns: 8
$ species           <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adel…
$ island            <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Torger…
$ bill_length_mm    <dbl> 39.1, 39.5, 40.3, NA, 36.7, 39.3, 38.9, 39.2, 34.1, 42.0, 37.8, 37.8, 41.1, 38.6, 34.6, 36.6, 38.7, 42.5, 34.4, 46.0…
$ bill_depth_mm     <dbl> 18.7, 17.4, 18.0, NA, 19.3, 20.6, 17.8, 19.6, 18.1, 20.2, 17.1, 17.3, 17.6, 21.2, 21.1, 17.8, 19.0, 20.7, 18.4, 21.5…
$ flipper_length_mm <int> 181, 186, 195, NA, 193, 190, 181, 195, 193, 190, 186, 180, 182, 191, 198, 185, 195, 197, 184, 194, 174, 180, 189, 18…
$ body_mass_g       <int> 3750, 3800, 3250, NA, 3450, 3650, 3625, 4675, 3475, 4250, 3300, 3700, 3200, 3800, 4400, 3700, 3450, 4500, 3325, 4200…
$ sex               <fct> male, female, female, NA, female, male, female, male, NA, NA, NA, NA, female, male, male, female, female, male, fema…
$ year              <int> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 20…

Exemplo: limpar nomes de colunas

tb_sujos <- tibble("Nome do Aluno" = c("Ana","Bruno"), "Nota Final (%)" = c(8.7, 9.2))
tb_limpos <- tb_sujos |> janitor::clean_names()
tb_limpos
NA

0.3 3. Importação com readr

Conceitos: read_csv, write_csv, tipos e NA.

Exemplo: escrever e ler CSV

tmp <- tempfile(fileext = ".csv")
write_csv(tb, tmp)
dados <- readr::read_csv(tmp, show_col_types = FALSE)
glimpse(dados)
Rows: 5
Columns: 3
$ id   <dbl> 1, 2, 3, 4, 5
$ nome <chr> "ana", "bruno", "carla", "diego", "eva"
$ nota <dbl> 7.5, 8.2, 6.9, 9.1, 7.8

Exemplo: declarar tipos e NA

glimpse(dados2)
Rows: 2
Columns: 3
$ id   <int> 1, 2
$ nome <chr> "Ana", "Bruno"
$ nota <dbl> 8.1, NA

0.4 4. Manipulação com dplyr

0.4.1 4.1 select e helpers

Exemplo: escolher colunas e renomear

penguins |>
  select(especie = species, starts_with("bill"))
select: renamed one variable (especie) and dropped 5 variables

0.4.2 4.2 arrange

Exemplo: ordenar por massa decrescente

penguins |>
  arrange(desc(body_mass_g)) |>
  #arrange(body_mass_g) |>
  select(species, body_mass_g) |>
  head(5)
select: dropped 6 variables (island, bill_length_mm, bill_depth_mm, flipper_length_mm, sex, …)

Exemplo: filtrar linhas com condições lógicas

penguins |>
  filter(species == "Adelie", !is.na(flipper_length_mm))
filter: removed 193 rows (56%), 151 rows remaining

0.5 4. Manipulação com dplyr

0.5.1 4.1 select e helpers

Exemplo: escolher colunas e renomear

penguins |>   select(especie = species, starts_with("bill"))
select: renamed one variable (especie) and dropped 5 variables

0.5.2 4.2 arrange

Exemplo: ordenar por massa decrescente

penguins |>   arrange(desc(body_mass_g)) |>   select(species, body_mass_g) |>   head(5)
select: dropped 6 variables (island, bill_length_mm, bill_depth_mm, flipper_length_mm, sex, …)

0.5.3 4.3 filter

Exemplo: filtrar linhas com condições lógicas

penguins |>   filter(species == "Adelie", !is.na(flipper_length_mm))
filter: removed 193 rows (56%), 151 rows remaining

0.5.4 4.4 mutate, case_when e across

Exemplo: criar variável categórica por faixas

penguins |>   
  mutate(faixa_massa = case_when(     
    body_mass_g < 3500 ~ "leve",    
    body_mass_g < 4500 ~ "média",     
    TRUE ~ "pesada"   )) |>   count(faixa_massa)
mutate: new variable 'faixa_massa' (character) with 3 unique values and 0% NA
count: now 3 rows and 2 columns, ungrouped

Exemplo: padronizar múltiplas colunas numéricas (across)

penguins |>   
  mutate(across(c(bill_length_mm, bill_depth_mm), ~ (.x - mean(.x, na.rm = TRUE))/sd(.x, na.rm = TRUE)))
mutate: changed 342 values (99%) of 'bill_length_mm' (0 new NAs)
        changed 342 values (99%) of 'bill_depth_mm' (0 new NAs)

0.5.5 4.5 summarise, group_by, n()

Exemplo: resumo por espécie e sexo

penguins |>   group_by(species, sex) |>
  summarise(n = n(),
            massa_media = mean(body_mass_g, na.rm = TRUE),
            asa_media = mean(flipper_length_mm, na.rm = TRUE),
            .groups = "drop"   )
group_by: 2 grouping variables (species, sex)
summarise: now 8 rows and 5 columns, ungrouped

0.5.6 4.6 Joins essenciais

Exemplo com pequenas tabelas sintéticas (sem sair do contexto):

chaves |> left_join(atributos, by = "id")
left_join: added one column (nota_obs)
           > rows only in chaves     2
           > rows only in atributos (1)
           > matched rows            4    (includes duplicates)
           >                        ===
           > rows total              6

0.5.7 4.7 bind_rows e bind_cols

Exemplo: empilhar e combinar

a <- tibble(id = 1:2, x = c("a","b"))
b <- tibble(id = 3:4, x = c("c","d"))
bind_rows(a, b)

bind_cols(tibble(u = 1:3), tibble(v = 4:6))
NA

0.6 5. Organização com tidyr

0.6.1 5.1 pivot_longer / pivot_wider

Exemplo:

longo |> pivot_wider(names_from = prova, values_from = nota)
pivot_wider: reorganized (prova, nota) into (P1, P2) [was 6x3, now 3x3]

0.6.2 5.2 separate / unite

Exemplo:

0.6.3 5.3 Aninhamento nest / unnest

Exemplo com penguins:

by_species$data
[[1]]

[[2]]

[[3]]
NA

0.7 6. Strings com stringr

Conceitos: str_to_lower, str_trim, str_detect, str_replace.

Exemplo: padronização de texto

tibble(nome = c("  ana  ", "BRUNO", "cArLa?")) |>
  mutate(
    nome_limp = str_to_title(str_trim(nome)),
    tem_interrogacao = str_detect(nome, "\\?"),
    sem_interrogacao = str_replace(nome, "\\?", "")
  )
mutate: new variable 'nome_limp' (character) with 3 unique values and 0% NA
        new variable 'tem_interrogacao' (logical) with 2 unique values and 0% NA
        new variable 'sem_interrogacao' (character) with 3 unique values and 0% NA

0.8 7. Datas com lubridate

Conceitos: parsing, extração de componentes, manipulação.

Exemplo: converter e extrair partes

tibble(texto = c("2025-08-21", "2025-08-22")) |>
  mutate(
    dt = parse_date_time(texto, "Y-m-d"),
    ano = year(dt),
    mes = month(dt),
    Dia_do_ano = yday(dt),
    semana2 = wday(dt))
mutate: new variable 'dt' (double) with 2 unique values and 0% NA
        new variable 'ano' (integer) with one unique value and 0% NA
        new variable 'mes' (integer) with one unique value and 0% NA
        new variable 'Dia_do_ano' (integer) with 2 unique values and 0% NA
        new variable 'semana2' (integer) with 2 unique values and 0% NA

0.9 8. Visualização com ggplot2

0.9.1 9.1 Gramática básica

Exemplo: dispersão com linha de tendência

penguins |>
  ggplot(aes(x = bill_length_mm, y = body_mass_g, color = species)) +
  geom_point(alpha = 0.7, na.rm = TRUE) +
  geom_smooth(method = "lm", se = FALSE) +
  labs(title = "Massa vs. comprimento do bico — penguins",
       x = "Comprimento do bico (mm)",
       y = "Massa (g)")
`geom_smooth()` using formula = 'y ~ x'
Aviso: Removed 2 rows containing non-finite outside the scale range (`stat_smooth()`).

0.9.2 9.2 Facets e rótulos

Exemplo: facetar por espécie

penguins |>
  ggplot(aes(x = flipper_length_mm, y = body_mass_g)) +
  geom_point(alpha = 0.6, na.rm = TRUE) +
  facet_wrap(~species) +
  labs(title = "Relação asa × massa por espécie")

0.10

LS0tDQp0aXRsZTogIkF1bGEgUHLDoXRpY2EgZSBFbnh1dGE6IHRpZHl2ZXJzZSBkbyBaZXJvIGFvIEVzc2VuY2lhbCINCmF1dGhvcjogIlRoaWFnbyBHYXJkaW4g4oCUIFIgTm90ZWJvb2siDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclZC8lbS8lWScpYCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDMNCiAgICBkZl9wcmludDogcGFnZWQNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQo+ICoqT2JqZXRpdm8qKjogQXByZW5kZXIgKippbXBvcnRhciwgdHJhbnNmb3JtYXIgZSB2aXN1YWxpemFyKiogZGFkb3Mgbm8gUiBjb20gbyAqKnRpZHl2ZXJzZSoqLCB1c2FuZG8gKipwb3VxdcOtc3NpbWFzIGJhc2VzKiogKHByaW5jaXBhbG1lbnRlIGBwZW5ndWluc2ApIGUgKip1bSBleGVtcGxvIHByw6F0aWNvIHBhcmEgY2FkYSBjb25jZWl0byoqLg0KDQojIyAxLiBQcmVwYXJhw6fDo28gZG8gQW1iaWVudGUNCg0KYGBge3Igc2V0dXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEluc3RhbGUgKHVtYSB2ZXogcG9yIG3DoXF1aW5hKQ0KIyBpbnN0YWxsLnBhY2thZ2VzKGMoInRpZHl2ZXJzZSIsICJwYWxtZXJwZW5ndWlucyIsICJqYW5pdG9yIiwgImx1YnJpZGF0ZSIsICJzdHJpbmdyIiwgImZvcmNhdHMiKSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShwYWxtZXJwZW5ndWlucykgICMgYmFzZSBwcmluY2lwYWwgZGEgYXVsYQ0KDQpgYGANCg0KIyMjIDEuMiBGaWxvc29maWEgdGlkeQ0KDQotICAgVW1hIG9ic2VydmHDp8OjbyBwb3IgbGluaGE7IHVtYSB2YXJpw6F2ZWwgcG9yIGNvbHVuYTsgdW0gdmFsb3IgcG9yIGPDqWx1bGEuDQoNCi0gICBWZXJib3MgY29lc29zIChzZWxlY3QsIGZpbHRlciwgbXV0YXRlLCBzdW1tYXJpc2UsIOKApikuDQoNCi0gICBQaXBlbGluZXMgcGFyYSBsZWdpYmlsaWRhZGUgKFx8XD4gcmVjb21lbmRhZG8pLg0KDQpFeGVtcGxvIChlc3RydXR1cmFyIGUgZW5jYWRlYXIpOg0KDQpgYGB7cn0NCnBlbmd1aW5zIHw+DQogIHNlbGVjdChzcGVjaWVzLCBiaWxsX2xlbmd0aF9tbSwgYm9keV9tYXNzX2cpIHw+DQogIGZpbHRlcighaXMubmEoYmlsbF9sZW5ndGhfbW0pLCAhaXMubmEoYm9keV9tYXNzX2cpKSB8Pg0KICBtdXRhdGUocmVsYWNhbyA9IGJvZHlfbWFzc19nIC8gYmlsbF9sZW5ndGhfbW0pIHw+DQogIGhlYWQoMykNCg0KYGBgDQoNCiMjIyAxLjMgT3BlcmFkb3JlcyBkZSBwaXBlDQoNCi0gICAqKk5hdGl2byBSIGB8PmAqKiAocHJlZmVyaWRvKSBlICoqbWFncml0dHIgYCU+JWAqKiAobGVnYWRvKS4NCg0KICAgIGBgYHtyfQ0KICAgIDE6NSB8PiBtZWFuKCkNCg0KICAgIGBgYA0KDQojIyAyLiB0aWJibGVzIGUgaW5zcGXDp8OjbyBkZSBkYWRvcw0KDQoqKkNvbmNlaXRvczoqKiBgdGliYmxlYCwgYGdsaW1wc2VgLCBpbXByZXNzw6NvIGFtaWfDoXZlbCwgdGlwb3MuDQoNCioqRXhlbXBsbzogY3JpYXIgdGliYmxlIGUgaW5zcGVjaW9uYXIqKg0KDQpgYGB7cn0NCnRiIDwtIHRpYmJsZTo6dGliYmxlKA0KICBpZCA9IDE6NSwNCiAgbm9tZSA9IGMoImFuYSIsICJicnVubyIsICJjYXJsYSIsICJkaWVnbyIsICJldmEiKSwNCiAgbm90YSA9IGMoNy41LCA4LjIsIDYuOSwgOS4xLCA3LjgpDQopDQp0Yg0KZ2xpbXBzZSh0YikNCg0KYGBgDQoNCmBgYHtyfQ0KDQpnbGltcHNlKHBlbmd1aW5zKQ0KDQpgYGANCg0KKipFeGVtcGxvOiBsaW1wYXIgbm9tZXMgZGUgY29sdW5hcyoqDQoNCmBgYHtyfQ0KdGJfc3Vqb3MgPC0gdGliYmxlKCJOb21lIGRvIEFsdW5vIiA9IGMoIkFuYSIsIkJydW5vIiksICJOb3RhIEZpbmFsICglKSIgPSBjKDguNywgOS4yKSkNCnRiX2xpbXBvcyA8LSB0Yl9zdWpvcyB8PiBqYW5pdG9yOjpjbGVhbl9uYW1lcygpDQp0Yl9saW1wb3MNCg0KYGBgDQoNCiMjIDMuIEltcG9ydGHDp8OjbyBjb20gYHJlYWRyYA0KDQoqKkNvbmNlaXRvczoqKiBgcmVhZF9jc3ZgLCBgd3JpdGVfY3N2YCwgdGlwb3MgZSBOQS4NCg0KKipFeGVtcGxvOiBlc2NyZXZlciBlIGxlciBDU1YqKg0KDQpgYGB7cn0NCnRtcCA8LSB0ZW1wZmlsZShmaWxlZXh0ID0gIi5jc3YiKQ0Kd3JpdGVfY3N2KHRiLCB0bXApDQpkYWRvcyA8LSByZWFkcjo6cmVhZF9jc3YodG1wLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQ0KZ2xpbXBzZShkYWRvcykNCg0KYGBgDQoNCioqRXhlbXBsbzogZGVjbGFyYXIgdGlwb3MgZSBOQSoqDQoNCmBgYHtyfQ0KdHh0IDwtICJpZCxub21lLG5vdGENCjEsQW5hLDguMQ0KMixCcnVubywuIg0KZGFkb3MyIDwtIHJlYWRyOjpyZWFkX2NzdihJKHR4dCksIG5hID0gIi4iLCBjb2xfdHlwZXMgPSAiaWNkIikNCmdsaW1wc2UoZGFkb3MyKQ0KDQpgYGANCg0KIyMgNC4gTWFuaXB1bGHDp8OjbyBjb20gYGRwbHlyYA0KDQojIyMgNC4xIGBzZWxlY3RgIGUgaGVscGVycw0KDQoqKkV4ZW1wbG86IGVzY29saGVyIGNvbHVuYXMgZSByZW5vbWVhcioqDQoNCmBgYHtyfQ0KcGVuZ3VpbnMgfD4NCiAgc2VsZWN0KGVzcGVjaWUgPSBzcGVjaWVzLCBzdGFydHNfd2l0aCgiYmlsbCIpKQ0KDQpgYGANCg0KIyMjIDQuMiBgYXJyYW5nZWANCg0KKipFeGVtcGxvOiBvcmRlbmFyIHBvciBtYXNzYSBkZWNyZXNjZW50ZSoqDQoNCmBgYHtyfQ0KcGVuZ3VpbnMgfD4NCiAgYXJyYW5nZShkZXNjKGJvZHlfbWFzc19nKSkgfD4NCiAgI2FycmFuZ2UoYm9keV9tYXNzX2cpIHw+DQogIHNlbGVjdChzcGVjaWVzLCBib2R5X21hc3NfZykgfD4NCiAgaGVhZCg1KQ0KDQpgYGANCg0KKipFeGVtcGxvOiBmaWx0cmFyIGxpbmhhcyBjb20gY29uZGnDp8O1ZXMgbMOzZ2ljYXMqKg0KDQpgYGB7cn0NCnBlbmd1aW5zIHw+DQogIGZpbHRlcihzcGVjaWVzID09ICJBZGVsaWUiLCAhaXMubmEoZmxpcHBlcl9sZW5ndGhfbW0pKQ0KDQoNCmBgYA0KDQojIyA0LiBNYW5pcHVsYcOnw6NvIGNvbSBgZHBseXJgDQoNCiMjIyA0LjEgYHNlbGVjdGAgZSBoZWxwZXJzDQoNCioqRXhlbXBsbzogZXNjb2xoZXIgY29sdW5hcyBlIHJlbm9tZWFyKioNCg0KYGBge3J9DQpwZW5ndWlucyB8PiAgIHNlbGVjdChlc3BlY2llID0gc3BlY2llcywgc3RhcnRzX3dpdGgoImJpbGwiKSkNCmBgYA0KDQojIyMgNC4yIGBhcnJhbmdlYA0KDQoqKkV4ZW1wbG86IG9yZGVuYXIgcG9yIG1hc3NhIGRlY3Jlc2NlbnRlKioNCg0KYGBge3J9DQpwZW5ndWlucyB8PiAgIGFycmFuZ2UoZGVzYyhib2R5X21hc3NfZykpIHw+ICAgc2VsZWN0KHNwZWNpZXMsIGJvZHlfbWFzc19nKSB8PiAgIGhlYWQoNSkNCmBgYA0KDQojIyMgNC4zIGBmaWx0ZXJgDQoNCioqRXhlbXBsbzogZmlsdHJhciBsaW5oYXMgY29tIGNvbmRpw6fDtWVzIGzDs2dpY2FzKioNCg0KYGBge3J9DQpwZW5ndWlucyB8PiAgIGZpbHRlcihzcGVjaWVzID09ICJBZGVsaWUiLCAhaXMubmEoZmxpcHBlcl9sZW5ndGhfbW0pKQ0KYGBgDQoNCiMjIyA0LjQgYG11dGF0ZWAsIGBjYXNlX3doZW5gIGUgYGFjcm9zc2ANCg0KKipFeGVtcGxvOiBjcmlhciB2YXJpw6F2ZWwgY2F0ZWfDs3JpY2EgcG9yIGZhaXhhcyoqDQoNCmBgYHtyfQ0KcGVuZ3VpbnMgfD4gICANCiAgbXV0YXRlKGZhaXhhX21hc3NhID0gY2FzZV93aGVuKCAgICAgDQogICAgYm9keV9tYXNzX2cgPCAzNTAwIH4gImxldmUiLCAgICANCiAgICBib2R5X21hc3NfZyA8IDQ1MDAgfiAibcOpZGlhIiwgICAgIA0KICAgIFRSVUUgfiAicGVzYWRhIiAgICkpIHw+ICAgY291bnQoZmFpeGFfbWFzc2EpDQpgYGANCg0KKipFeGVtcGxvOiBwYWRyb25pemFyIG3Dumx0aXBsYXMgY29sdW5hcyBudW3DqXJpY2FzIChgYWNyb3NzYCkqKg0KDQpgYGB7cn0NCnBlbmd1aW5zIHw+ICAgDQogIG11dGF0ZShhY3Jvc3MoYyhiaWxsX2xlbmd0aF9tbSwgYmlsbF9kZXB0aF9tbSksIH4gKC54IC0gbWVhbigueCwgbmEucm0gPSBUUlVFKSkvc2QoLngsIG5hLnJtID0gVFJVRSkpKQ0KDQoNCg0KYGBgDQoNCiMjIyA0LjUgYHN1bW1hcmlzZWAsIGBncm91cF9ieWAsIGBuKClgDQoNCioqRXhlbXBsbzogcmVzdW1vIHBvciBlc3DDqWNpZSBlIHNleG8qKg0KDQpgYGB7cn0NCnBlbmd1aW5zIHw+ICAgZ3JvdXBfYnkoc3BlY2llcywgc2V4KSB8Pg0KICBzdW1tYXJpc2UobiA9IG4oKSwNCiAgICAgICAgICAgIG1hc3NhX21lZGlhID0gbWVhbihib2R5X21hc3NfZywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIGFzYV9tZWRpYSA9IG1lYW4oZmxpcHBlcl9sZW5ndGhfbW0sIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiICAgKQ0KYGBgDQoNCiMjIyA0LjYgSm9pbnMgZXNzZW5jaWFpcw0KDQoqKkV4ZW1wbG8gY29tIHBlcXVlbmFzIHRhYmVsYXMgc2ludMOpdGljYXMgKHNlbSBzYWlyIGRvIGNvbnRleHRvKToqKg0KDQpgYGB7cn0NCmNoYXZlcyA8LSANCiAgcGVuZ3VpbnMgfD4NCiAgbXV0YXRlKGlkID0gcm93X251bWJlcigpKSB8PiBzZWxlY3QoaWQsc3BlY2llcykgJT4lIA0KICBoZWFkKDUpDQoNCmF0cmlidXRvcyA8LSB0aWJibGUoDQogIGlkID0gYygxLDEsMiwzLDYpLCANCiAgbm90YV9vYnMgPSBjKCJvayIsInJldmlzYXIiLCJvayIsIm9rIiwiZm9yYSIpDQopDQoNCmNoYXZlcyB8PiBsZWZ0X2pvaW4oYXRyaWJ1dG9zLCBieSA9ICJpZCIpDQoNCmBgYA0KDQojIyMgNC43IGBiaW5kX3Jvd3NgIGUgYGJpbmRfY29sc2ANCg0KKipFeGVtcGxvOiBlbXBpbGhhciBlIGNvbWJpbmFyKioNCg0KYGBge3J9DQphIDwtIHRpYmJsZShpZCA9IDE6MiwgeCA9IGMoImEiLCJiIikpDQpiIDwtIHRpYmJsZShpZCA9IDM6NCwgeCA9IGMoImMiLCJkIikpDQpiaW5kX3Jvd3MoYSwgYikNCg0KYmluZF9jb2xzKHRpYmJsZSh1ID0gMTozKSwgdGliYmxlKHYgPSA0OjYpKQ0KDQpgYGANCg0KIyMgNS4gT3JnYW5pemHDp8OjbyBjb20gYHRpZHlyYA0KDQojIyMgNS4xIGBwaXZvdF9sb25nZXJgIC8gYHBpdm90X3dpZGVyYA0KDQoqKkV4ZW1wbG86KioNCg0KYGBge3J9DQp3IDwtIHRpYmJsZSgNCiAgaWQgPSAxOjMsIFAxID0gYyg3LDgsNiksIFAyID0gYyg5LDcsOCkNCikNCncNCmxvbmdvIDwtIHcgfD4NCiAgcGl2b3RfbG9uZ2VyKHN0YXJ0c193aXRoKCJQIiksIG5hbWVzX3RvID0gInByb3ZhIiwgdmFsdWVzX3RvID0gIm5vdGEiKQ0KbG9uZ28NCmxvbmdvIHw+IHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwcm92YSwgdmFsdWVzX2Zyb20gPSBub3RhKQ0KDQpgYGANCg0KIyMjIDUuMiBgc2VwYXJhdGVgIC8gYHVuaXRlYA0KDQoqKkV4ZW1wbG86KioNCg0KYGBge3J9DQp0IDwtIHRpYmJsZShub21lID0gYygiQW5hIFNpbHZhIiwgIkJydW5vIFNvdXphIikpDQp0IHw+IA0KICBzZXBhcmF0ZShub21lLCBpbnRvID0gYygibm9tZSIsInNvYnJlbm9tZSIpLCBzZXAgPSAiICIpIHw+DQogIHVuaXRlKCJub21lX2NvbXBsZXRvIiwgbm9tZSwgc29icmVub21lLCBzZXAgPSAiICIpDQoNCmBgYA0KDQojIyMgNS4zIEFuaW5oYW1lbnRvIGBuZXN0YCAvIGB1bm5lc3RgDQoNCioqRXhlbXBsbyBjb20gYHBlbmd1aW5zYDoqKg0KDQpgYGB7cn0NCmJ5X3NwZWNpZXMgPC0gcGVuZ3VpbnMgfD4NCiAgZHJvcF9uYShiaWxsX2xlbmd0aF9tbSwgYm9keV9tYXNzX2cpIHw+DQogIGdyb3VwX2J5KHNwZWNpZXMpIHw+DQogIG5lc3QoKQ0KDQpieV9zcGVjaWVzDQpieV9zcGVjaWVzJGRhdGENCmJ5X3NwZWNpZXMkZGF0YVtbMV1dIHw+IGhlYWQoKQ0KDQoNCmBgYA0KDQojIyA2LiBTdHJpbmdzIGNvbSBgc3RyaW5ncmANCg0KKipDb25jZWl0b3M6KiogYHN0cl90b19sb3dlcmAsIGBzdHJfdHJpbWAsIGBzdHJfZGV0ZWN0YCwgYHN0cl9yZXBsYWNlYC4NCg0KKipFeGVtcGxvOiBwYWRyb25pemHDp8OjbyBkZSB0ZXh0byoqDQoNCmBgYHtyfQ0KdGliYmxlKG5vbWUgPSBjKCIgIGFuYSAgIiwgIkJSVU5PIiwgImNBckxhPyIpKSB8Pg0KICBtdXRhdGUoDQogICAgbm9tZV9saW1wID0gc3RyX3RvX3RpdGxlKHN0cl90cmltKG5vbWUpKSwNCiAgICB0ZW1faW50ZXJyb2dhY2FvID0gc3RyX2RldGVjdChub21lLCAiXFw/IiksDQogICAgc2VtX2ludGVycm9nYWNhbyA9IHN0cl9yZXBsYWNlKG5vbWUsICJcXD8iLCAiIikNCiAgKQ0KDQpgYGANCg0KIyMgNy4gRGF0YXMgY29tIGBsdWJyaWRhdGVgDQoNCioqQ29uY2VpdG9zOioqIHBhcnNpbmcsIGV4dHJhw6fDo28gZGUgY29tcG9uZW50ZXMsIG1hbmlwdWxhw6fDo28uDQoNCioqRXhlbXBsbzogY29udmVydGVyIGUgZXh0cmFpciBwYXJ0ZXMqKg0KDQpgYGB7cn0NCnRpYmJsZSh0ZXh0byA9IGMoIjIwMjUtMDgtMjEiLCAiMjAyNS0wOC0yMiIpKSB8Pg0KICBtdXRhdGUoDQogICAgZHQgPSBwYXJzZV9kYXRlX3RpbWUodGV4dG8sICJZLW0tZCIpLA0KICAgIGFubyA9IHllYXIoZHQpLA0KICAgIG1lcyA9IG1vbnRoKGR0KSwNCiAgICBEaWFfZG9fYW5vID0geWRheShkdCksDQogICAgc2VtYW5hMiA9IHdkYXkoZHQpKQ0KDQogIA0KDQpgYGANCg0KIyMgOC4gVmlzdWFsaXphw6fDo28gY29tIGBnZ3Bsb3QyYA0KDQojIyMgOS4xIEdyYW3DoXRpY2EgYsOhc2ljYQ0KDQoqKkV4ZW1wbG86IGRpc3BlcnPDo28gY29tIGxpbmhhIGRlIHRlbmTDqm5jaWEqKg0KDQpgYGB7cn0NCnBlbmd1aW5zIHw+DQogIGdncGxvdChhZXMoeCA9IGJpbGxfbGVuZ3RoX21tLCB5ID0gYm9keV9tYXNzX2csIGNvbG9yID0gc3BlY2llcykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNywgbmEucm0gPSBUUlVFKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsNCiAgbGFicyh0aXRsZSA9ICJNYXNzYSB2cy4gY29tcHJpbWVudG8gZG8gYmljbyDigJQgcGVuZ3VpbnMiLA0KICAgICAgIHggPSAiQ29tcHJpbWVudG8gZG8gYmljbyAobW0pIiwNCiAgICAgICB5ID0gIk1hc3NhIChnKSIpDQoNCg0KYGBgDQoNCiMjIyA5LjIgRmFjZXRzIGUgcsOzdHVsb3MNCg0KKipFeGVtcGxvOiBmYWNldGFyIHBvciBlc3DDqWNpZSoqDQoNCmBgYHtyfQ0KcGVuZ3VpbnMgfD4NCiAgZ2dwbG90KGFlcyh4ID0gZmxpcHBlcl9sZW5ndGhfbW0sIHkgPSBib2R5X21hc3NfZykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNiwgbmEucm0gPSBUUlVFKSArDQogIGZhY2V0X3dyYXAofnNwZWNpZXMpICsNCiAgbGFicyh0aXRsZSA9ICJSZWxhw6fDo28gYXNhIMOXIG1hc3NhIHBvciBlc3DDqWNpZSIpDQoNCmBgYA0KDQojIyANCg==