0. Configuração Inicial

0.1. Apresentação

Este script foi desenvolvido como material de apoio para a aula de introdução à análise de dados macroeconômicos com R. Passaremos por todas as etapas do processo, desde a importação e manipulação de dados até a coleta de séries de fontes oficiais brasileiras e a visualização final.

0.2. Instalação de Pacotes

Para executar este script, é necessário ter alguns pacotes instalados. O código abaixo instala os pacotes que vamos utilizar.

library(tidyverse)
library(rbcb)
library(readxl)
library(writexl)

1. Tipos e Estruturas de Dados no R

1.1. Vetores

Vetores são a estrutura de dados mais fundamental do R. Eles armazenam elementos do mesmo tipo.

Vetor numérico

vetor_numerico <- c(10.5, 5, -3, 8.2)
print(vetor_numerico)
## [1] 10.5  5.0 -3.0  8.2
class(vetor_numerico) # Verifica a classe do objeto
## [1] "numeric"

Vetor de caracteres (texto)

vetor_texto <- c("PIB", "IPCA", "Selic")
print(vetor_texto)
## [1] "PIB"   "IPCA"  "Selic"
class(vetor_texto)
## [1] "character"

Vetor lógico (Booleano)

vetor_logico <- c(TRUE, FALSE, TRUE, TRUE)
print(vetor_logico)
## [1]  TRUE FALSE  TRUE  TRUE
class(vetor_logico)
## [1] "logical"

1.2. Data Frames

Data frames são a estrutura mais comum para armazenar dados tabulares no R. São como tabelas, onde as colunas podem ter tipos de dados diferentes.

df_exemplo <- data.frame(
  Ano = c(2022, 2023, 2024),
  PIB_nominal = c(9.9, 10.9, 11.5), # em trilhões de R$ (hipotético)
  Pais = c("Brasil", "Brasil", "Brasil")
)

print(df_exemplo)
##    Ano PIB_nominal   Pais
## 1 2022         9.9 Brasil
## 2 2023        10.9 Brasil
## 3 2024        11.5 Brasil
str(df_exemplo) # Mostra a estrutura do data frame
## 'data.frame':    3 obs. of  3 variables:
##  $ Ano        : num  2022 2023 2024
##  $ PIB_nominal: num  9.9 10.9 11.5
##  $ Pais       : chr  "Brasil" "Brasil" "Brasil"
summary(df_exemplo) # Fornece um resumo estatístico
##       Ano        PIB_nominal        Pais          
##  Min.   :2022   Min.   : 9.90   Length:3          
##  1st Qu.:2022   1st Qu.:10.40   Class :character  
##  Median :2023   Median :10.90   Mode  :character  
##  Mean   :2023   Mean   :10.77                     
##  3rd Qu.:2024   3rd Qu.:11.20                     
##  Max.   :2024   Max.   :11.50

1.3. Tibbles

Tibbles são a versão moderna de data frames, parte do tidyverse. Eles possuem uma impressão (print) mais amigável e algumas regras mais estritas que evitam erros comuns.

tibble_exemplo <- tibble(
  Ano = c(2022, 2023, 2024),
  PIB_nominal = c(9.9, 10.9, 11.5),
  Pais = c("Brasil", "Brasil", "Brasil")
)

print(tibble_exemplo)
## # A tibble: 3 × 3
##     Ano PIB_nominal Pais  
##   <dbl>       <dbl> <chr> 
## 1  2022         9.9 Brasil
## 2  2023        10.9 Brasil
## 3  2024        11.5 Brasil

2. Importação e Exportação de Dados

2.1. Criando dados de exemplo para exportar

Vamos criar um data frame e salvá-lo como CSV e Excel para simular a importação de arquivos externos.

dados_para_exportar <- data.frame(
  Data = seq(as.Date("2023-01-01"), by = "month", length.out = 12),
  Vendas = round(runif(12, 100, 500)),
  Produto = rep(c("A", "B"), each = 6)
)

Exportando para CSV

O readr (parte do tidyverse) usa a função write_csv()

write_csv(dados_para_exportar, "exemplo_vendas.csv")

Exportando para Excel

Usaremos o pacote writexl

write_xlsx(dados_para_exportar, "exemplo_vendas.xlsx")

2.2. Importando de CSV

A função read_csv() do pacote readr é rápida e eficiente.

dados_csv <- read_csv("exemplo_vendas.csv")
## Rows: 12 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (1): Produto
## dbl  (1): Vendas
## date (1): Data
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(dados_csv)
## # A tibble: 6 × 3
##   Data       Vendas Produto
##   <date>      <dbl> <chr>  
## 1 2023-01-01    260 A      
## 2 2023-02-01    402 A      
## 3 2023-03-01    245 A      
## 4 2023-04-01    421 A      
## 5 2023-05-01    473 A      
## 6 2023-06-01    248 A

2.3. Importando de Excel

A função read_excel() do pacote readxl lê arquivos .xls e .xlsx.

dados_excel <- read_excel("exemplo_vendas.xlsx")
head(dados_excel)
## # A tibble: 6 × 3
##   Data                Vendas Produto
##   <dttm>               <dbl> <chr>  
## 1 2023-01-01 00:00:00    260 A      
## 2 2023-02-01 00:00:00    402 A      
## 3 2023-03-01 00:00:00    245 A      
## 4 2023-04-01 00:00:00    421 A      
## 5 2023-05-01 00:00:00    473 A      
## 6 2023-06-01 00:00:00    248 A

3. Manipulação de Dados com dplyr

O dplyr oferece um conjunto de “verbos” para manipulação de dados. Vamos usar o tibble criado na seção 1.3 e o dados_csv importado.

3.1. O Operador Pipe (%>%)

O pipe permite encadear múltiplas operações de forma legível, passando o resultado da operação anterior como o primeiro argumento da próxima. Lê-se como “e então”.

3.2. filter(): Filtrando linhas

Seleciona linhas com base em condições lógicas. Exemplo: pegar apenas os dados do Produto “A”

vendas_produto_A <- dados_csv %>%
  filter(Produto == "A")

print(vendas_produto_A)
## # A tibble: 6 × 3
##   Data       Vendas Produto
##   <date>      <dbl> <chr>  
## 1 2023-01-01    260 A      
## 2 2023-02-01    402 A      
## 3 2023-03-01    245 A      
## 4 2023-04-01    421 A      
## 5 2023-05-01    473 A      
## 6 2023-06-01    248 A

3.3. select(): Selecionando colunas

Seleciona colunas pelo nome. Exemplo: selecionar apenas as colunas Data e Vendas

vendas_selecionadas <- dados_csv %>%
  select(Data, Vendas)

head(vendas_selecionadas)
## # A tibble: 6 × 2
##   Data       Vendas
##   <date>      <dbl>
## 1 2023-01-01    260
## 2 2023-02-01    402
## 3 2023-03-01    245
## 4 2023-04-01    421
## 5 2023-05-01    473
## 6 2023-06-01    248

Podemos remover uma coluna usando o sinal de menos (-)

vendas_sem_produto <- dados_csv %>%
  select(-Produto)

head(vendas_sem_produto)
## # A tibble: 6 × 2
##   Data       Vendas
##   <date>      <dbl>
## 1 2023-01-01    260
## 2 2023-02-01    402
## 3 2023-03-01    245
## 4 2023-04-01    421
## 5 2023-05-01    473
## 6 2023-06-01    248

3.4. arrange(): Ordenando linhas

Ordena as linhas do data frame com base nos valores de uma ou mais colunas. Exemplo: ordenar por vendas, da maior para a menor

vendas_ordenadas <- dados_csv %>%
  arrange(desc(Vendas))

head(vendas_ordenadas)
## # A tibble: 6 × 3
##   Data       Vendas Produto
##   <date>      <dbl> <chr>  
## 1 2023-05-01    473 A      
## 2 2023-09-01    431 B      
## 3 2023-04-01    421 A      
## 4 2023-10-01    403 B      
## 5 2023-02-01    402 A      
## 6 2023-12-01    383 B

3.5. mutate(): Criando novas colunas

Cria novas colunas (ou modifica existentes) a partir de outras. Exemplo: criar uma coluna com as vendas em milhares

vendas_com_meta <- dados_csv %>%
  mutate(
    Vendas_milhares = Vendas / 1000,
    Atingiu_meta = ifelse(Vendas > 300, "Sim", "Não")
  )

head(vendas_com_meta)
## # A tibble: 6 × 5
##   Data       Vendas Produto Vendas_milhares Atingiu_meta
##   <date>      <dbl> <chr>             <dbl> <chr>       
## 1 2023-01-01    260 A                 0.26  Não         
## 2 2023-02-01    402 A                 0.402 Sim         
## 3 2023-03-01    245 A                 0.245 Não         
## 4 2023-04-01    421 A                 0.421 Sim         
## 5 2023-05-01    473 A                 0.473 Sim         
## 6 2023-06-01    248 A                 0.248 Não

3.6. summarise() e group_by(): Agregando dados

summarise() resume os dados em um único valor (e.g., média, soma). group_by() permite que a sumarização seja feita por grupos. Exemplo: calcular a venda total e a venda média por produto

vendas_por_produto <- dados_csv %>%
  group_by(Produto) %>%
  summarise(
    Venda_Total = sum(Vendas),
    Venda_Media = mean(Vendas),
    Numero_Meses = n() # n() conta o número de observações no grupo
  )

print(vendas_por_produto)
## # A tibble: 2 × 4
##   Produto Venda_Total Venda_Media Numero_Meses
##   <chr>         <dbl>       <dbl>        <int>
## 1 A              2049        342.            6
## 2 B              1825        304.            6

4. Acesso a Dados Macroeconômicos com APIs (rbcb)

APIs (Application Programming Interfaces) são formas de sistemas computacionais conversarem entre si. O Banco Central do Brasil (BCB) oferece uma API para acesso ao seu vasto banco de dados de séries temporais (SGS).

4.1. O pacote rbcb

Este pacote facilita enormemente a busca por dados no SGS do BCB.

4.2. Obtendo as séries de interesse

Precisamos saber os códigos das séries no sistema SGS.

  • PIB Mensal (IBC-Br, índice): 24363

  • IPCA (Variação % mensal): 433

Criando um vetor nomeado com os códigos. Os nomes serão usados nas colunas.

codigos_bcb <- c(
  PIB_IBCBr = 24363,
  IPCA = 433
)

Usando a função get_series para baixar os dados Vamos buscar os dados a partir de 01/01/2003

dados_pib <- get_series(codigos_bcb[1], start_date = "2003-01-01")
dados_ipca <- get_series(codigos_bcb[2], start_date = "2003-01-01")
dados_macro <- full_join(dados_pib, dados_ipca, by = "date")

# Inspecionando os dados baixados
head(dados_macro)
## # A tibble: 6 × 3
##   date       PIB_IBCBr  IPCA
##   <date>         <dbl> <dbl>
## 1 2003-01-01      67.5  2.25
## 2 2003-02-01      69.3  1.57
## 3 2003-03-01      72.6  1.23
## 4 2003-04-01      71.7  0.97
## 5 2003-05-01      70.4  0.61
## 6 2003-06-01      69.2 -0.15
tail(dados_macro)
## # A tibble: 6 × 3
##   date       PIB_IBCBr  IPCA
##   <date>         <dbl> <dbl>
## 1 2025-02-01      107.  1.31
## 2 2025-03-01      114.  0.56
## 3 2025-04-01      112.  0.43
## 4 2025-05-01      108.  0.26
## 5 2025-06-01      107.  0.24
## 6 2025-07-01       NA   0.26

4.3. Manipulando os dados macroeconômicos

Vamos renomear as colunas para português e ajustar o formato da data.

dados_macro <- dados_macro %>%
  rename(
    Data = date
  ) %>%
  mutate(
    Data = as.Date(Data) # Garantindo que a coluna Data é do tipo Date
  )

head(dados_macro)
## # A tibble: 6 × 3
##   Data       PIB_IBCBr  IPCA
##   <date>         <dbl> <dbl>
## 1 2003-01-01      67.5  2.25
## 2 2003-02-01      69.3  1.57
## 3 2003-03-01      72.6  1.23
## 4 2003-04-01      71.7  0.97
## 5 2003-05-01      70.4  0.61
## 6 2003-06-01      69.2 -0.15

5. Breve Exemplo de Visualização com ggplot2

O ggplot2 é baseado na “Gramática dos Gráficos”, permitindo a construção de gráficos complexos de forma intuitiva, camada por camada.

A estrutura básica é:

ggplot(data = <DADOS>, mapping = aes(<MAPEAMENTOS ESTÉTICOS>)) +
   <CAMADA GEOMÉTRICA>()

Vamos criar um gráfico de linhas para uma das séries que baixamos.

# Código para plotar no formato "largo"
ggplot(dados_macro, aes(x = Data, y = PIB_IBCBr)) +
  geom_line() + # Adiciona a camada de linha para criar o gráfico de série temporal
  labs(
    title = "Série Temporal do PIB IBC-Br",
    x = "Data",
    y = "PIB IBC-Br"
  ) +
  theme_minimal() # Um tema limpo para o gráfico (opcional)

LS0tDQp0aXRsZTogIkludHJvZHXDp8OjbyDDoCBtYW5pcHVsYcOnw6NvIGRlIGRhZG9zIGVtIFIiDQphdXRob3I6ICJCcnVubyBNZWxvIGRlIE9saXZlaXJhIFNhbnRvcyINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICB0aGVtZTogbHVtZW4NCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZSANCi0tLQ0KDQojIDAuIENvbmZpZ3VyYcOnw6NvIEluaWNpYWwNCg0KIyMgMC4xLiBBcHJlc2VudGHDp8Ojbw0KDQpFc3RlIHNjcmlwdCBmb2kgZGVzZW52b2x2aWRvIGNvbW8gbWF0ZXJpYWwgZGUgYXBvaW8gcGFyYSBhIGF1bGEgZGUgaW50cm9kdcOnw6NvIMOgIGFuw6FsaXNlIGRlIGRhZG9zIG1hY3JvZWNvbsO0bWljb3MgY29tIFIuIFBhc3NhcmVtb3MgcG9yIHRvZGFzIGFzIGV0YXBhcyBkbyBwcm9jZXNzbywgZGVzZGUgYSBpbXBvcnRhw6fDo28gZSBtYW5pcHVsYcOnw6NvIGRlIGRhZG9zIGF0w6kgYSBjb2xldGEgZGUgc8OpcmllcyBkZSBmb250ZXMgb2ZpY2lhaXMgYnJhc2lsZWlyYXMgZSBhIHZpc3VhbGl6YcOnw6NvIGZpbmFsLg0KDQojIyAwLjIuIEluc3RhbGHDp8OjbyBkZSBQYWNvdGVzDQoNClBhcmEgZXhlY3V0YXIgZXN0ZSBzY3JpcHQsIMOpIG5lY2Vzc8OhcmlvIHRlciBhbGd1bnMgcGFjb3RlcyBpbnN0YWxhZG9zLiBPIGPDs2RpZ28gYWJhaXhvIGluc3RhbGEgb3MgcGFjb3RlcyBxdWUgdmFtb3MgdXRpbGl6YXIuDQoNCmBgYHtyIHBhY290ZXMsIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJiY2IpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkod3JpdGV4bCkNCmBgYA0KDQojIDEuIFRpcG9zIGUgRXN0cnV0dXJhcyBkZSBEYWRvcyBubyBSDQoNCiMjIDEuMS4gVmV0b3Jlcw0KDQpWZXRvcmVzIHPDo28gYSBlc3RydXR1cmEgZGUgZGFkb3MgbWFpcyBmdW5kYW1lbnRhbCBkbyBSLiBFbGVzIGFybWF6ZW5hbSBlbGVtZW50b3MgZG8gbWVzbW8gdGlwby4NCg0KKipWZXRvciBudW3DqXJpY28qKg0KDQpgYGB7ciB2ZXRvciBudW3DqXJpY299DQp2ZXRvcl9udW1lcmljbyA8LSBjKDEwLjUsIDUsIC0zLCA4LjIpDQpwcmludCh2ZXRvcl9udW1lcmljbykNCmNsYXNzKHZldG9yX251bWVyaWNvKSAjIFZlcmlmaWNhIGEgY2xhc3NlIGRvIG9iamV0bw0KYGBgDQoNCioqVmV0b3IgZGUgY2FyYWN0ZXJlcyAodGV4dG8pKioNCg0KYGBge3IgdmV0b3IgdGV4dG99DQp2ZXRvcl90ZXh0byA8LSBjKCJQSUIiLCAiSVBDQSIsICJTZWxpYyIpDQpwcmludCh2ZXRvcl90ZXh0bykNCmNsYXNzKHZldG9yX3RleHRvKQ0KYGBgDQoNCioqVmV0b3IgbMOzZ2ljbyAoQm9vbGVhbm8pKioNCg0KYGBge3IgdmV0b3IgbMOzZ2ljb30NCnZldG9yX2xvZ2ljbyA8LSBjKFRSVUUsIEZBTFNFLCBUUlVFLCBUUlVFKQ0KcHJpbnQodmV0b3JfbG9naWNvKQ0KY2xhc3ModmV0b3JfbG9naWNvKQ0KYGBgDQoNCiMjIDEuMi4gRGF0YSBGcmFtZXMNCg0KRGF0YSBmcmFtZXMgc8OjbyBhIGVzdHJ1dHVyYSBtYWlzIGNvbXVtIHBhcmEgYXJtYXplbmFyIGRhZG9zIHRhYnVsYXJlcyBubyBSLiBTw6NvIGNvbW8gdGFiZWxhcywgb25kZSBhcyBjb2x1bmFzIHBvZGVtIHRlciB0aXBvcyBkZSBkYWRvcyBkaWZlcmVudGVzLg0KDQpgYGB7ciBkYXRhIGZyYW1lfQ0KZGZfZXhlbXBsbyA8LSBkYXRhLmZyYW1lKA0KICBBbm8gPSBjKDIwMjIsIDIwMjMsIDIwMjQpLA0KICBQSUJfbm9taW5hbCA9IGMoOS45LCAxMC45LCAxMS41KSwgIyBlbSB0cmlsaMO1ZXMgZGUgUiQgKGhpcG90w6l0aWNvKQ0KICBQYWlzID0gYygiQnJhc2lsIiwgIkJyYXNpbCIsICJCcmFzaWwiKQ0KKQ0KDQpwcmludChkZl9leGVtcGxvKQ0Kc3RyKGRmX2V4ZW1wbG8pICMgTW9zdHJhIGEgZXN0cnV0dXJhIGRvIGRhdGEgZnJhbWUNCnN1bW1hcnkoZGZfZXhlbXBsbykgIyBGb3JuZWNlIHVtIHJlc3VtbyBlc3RhdMOtc3RpY28NCmBgYA0KDQojIyAxLjMuIFRpYmJsZXMNCg0KVGliYmxlcyBzw6NvIGEgdmVyc8OjbyBtb2Rlcm5hIGRlIGRhdGEgZnJhbWVzLCBwYXJ0ZSBkbyBgdGlkeXZlcnNlYC4gRWxlcyBwb3NzdWVtIHVtYSBpbXByZXNzw6NvIChwcmludCkgbWFpcyBhbWlnw6F2ZWwgZSBhbGd1bWFzIHJlZ3JhcyBtYWlzIGVzdHJpdGFzIHF1ZSBldml0YW0gZXJyb3MgY29tdW5zLg0KDQpgYGB7ciB0aWJibGV9DQp0aWJibGVfZXhlbXBsbyA8LSB0aWJibGUoDQogIEFubyA9IGMoMjAyMiwgMjAyMywgMjAyNCksDQogIFBJQl9ub21pbmFsID0gYyg5LjksIDEwLjksIDExLjUpLA0KICBQYWlzID0gYygiQnJhc2lsIiwgIkJyYXNpbCIsICJCcmFzaWwiKQ0KKQ0KDQpwcmludCh0aWJibGVfZXhlbXBsbykNCmBgYA0KDQojIDIuIEltcG9ydGHDp8OjbyBlIEV4cG9ydGHDp8OjbyBkZSBEYWRvcw0KDQojIyAyLjEuIENyaWFuZG8gZGFkb3MgZGUgZXhlbXBsbyBwYXJhIGV4cG9ydGFyDQoNClZhbW9zIGNyaWFyIHVtIGRhdGEgZnJhbWUgZSBzYWx2w6EtbG8gY29tbyBDU1YgZSBFeGNlbCBwYXJhIHNpbXVsYXIgYSBpbXBvcnRhw6fDo28gZGUgYXJxdWl2b3MgZXh0ZXJub3MuDQoNCmBgYHtyIGRmIGV4ZW1wbG8gaW1wb3J0IGV4cG9ydH0NCmRhZG9zX3BhcmFfZXhwb3J0YXIgPC0gZGF0YS5mcmFtZSgNCiAgRGF0YSA9IHNlcShhcy5EYXRlKCIyMDIzLTAxLTAxIiksIGJ5ID0gIm1vbnRoIiwgbGVuZ3RoLm91dCA9IDEyKSwNCiAgVmVuZGFzID0gcm91bmQocnVuaWYoMTIsIDEwMCwgNTAwKSksDQogIFByb2R1dG8gPSByZXAoYygiQSIsICJCIiksIGVhY2ggPSA2KQ0KKQ0KYGBgDQoNCioqRXhwb3J0YW5kbyBwYXJhIENTVioqDQoNCk8gYHJlYWRyYCAocGFydGUgZG8gdGlkeXZlcnNlKSB1c2EgYSBmdW7Dp8OjbyBgd3JpdGVfY3N2KClgDQoNCmBgYHtyIGV4cG9ydCBjc3Z9DQp3cml0ZV9jc3YoZGFkb3NfcGFyYV9leHBvcnRhciwgImV4ZW1wbG9fdmVuZGFzLmNzdiIpDQpgYGANCg0KKipFeHBvcnRhbmRvIHBhcmEgRXhjZWwqKg0KDQpVc2FyZW1vcyBvIHBhY290ZSBgd3JpdGV4bGANCg0KYGBge3IgZXhwb3J0IHhsc3h9DQp3cml0ZV94bHN4KGRhZG9zX3BhcmFfZXhwb3J0YXIsICJleGVtcGxvX3ZlbmRhcy54bHN4IikNCmBgYA0KDQojIyAyLjIuIEltcG9ydGFuZG8gZGUgQ1NWDQoNCkEgZnVuw6fDo28gYHJlYWRfY3N2KClgIGRvIHBhY290ZSBgcmVhZHJgIMOpIHLDoXBpZGEgZSBlZmljaWVudGUuDQoNCmBgYHtyIGltcG9ydCBjc3Z9DQpkYWRvc19jc3YgPC0gcmVhZF9jc3YoImV4ZW1wbG9fdmVuZGFzLmNzdiIpDQpoZWFkKGRhZG9zX2NzdikNCmBgYA0KDQojIyAyLjMuIEltcG9ydGFuZG8gZGUgRXhjZWwNCg0KQSBmdW7Dp8OjbyBgcmVhZF9leGNlbCgpYCBkbyBwYWNvdGUgYHJlYWR4bGAgbMOqIGFycXVpdm9zIC54bHMgZSAueGxzeC4NCg0KYGBge3IgaW1wb3J0IHhsc3h9DQpkYWRvc19leGNlbCA8LSByZWFkX2V4Y2VsKCJleGVtcGxvX3ZlbmRhcy54bHN4IikNCmhlYWQoZGFkb3NfZXhjZWwpDQpgYGANCg0KIyAzLiBNYW5pcHVsYcOnw6NvIGRlIERhZG9zIGNvbSBkcGx5cg0KDQpPIGBkcGx5cmAgb2ZlcmVjZSB1bSBjb25qdW50byBkZSAidmVyYm9zIiBwYXJhIG1hbmlwdWxhw6fDo28gZGUgZGFkb3MuIFZhbW9zIHVzYXIgbyBgdGliYmxlYCBjcmlhZG8gbmEgc2XDp8OjbyAxLjMgZSBvIGBkYWRvc19jc3ZgIGltcG9ydGFkby4NCg0KIyMgMy4xLiBPIE9wZXJhZG9yIFBpcGUgKGAlPiVgKQ0KDQpPIHBpcGUgcGVybWl0ZSBlbmNhZGVhciBtw7psdGlwbGFzIG9wZXJhw6fDtWVzIGRlIGZvcm1hIGxlZ8OtdmVsLCBwYXNzYW5kbyBvIHJlc3VsdGFkbyBkYSBvcGVyYcOnw6NvIGFudGVyaW9yIGNvbW8gbyBwcmltZWlybyBhcmd1bWVudG8gZGEgcHLDs3hpbWEuIEzDqi1zZSBjb21vICJlIGVudMOjbyIuDQoNCiMjIDMuMi4gYGZpbHRlcigpYDogRmlsdHJhbmRvIGxpbmhhcw0KDQpTZWxlY2lvbmEgbGluaGFzIGNvbSBiYXNlIGVtIGNvbmRpw6fDtWVzIGzDs2dpY2FzLiBFeGVtcGxvOiBwZWdhciBhcGVuYXMgb3MgZGFkb3MgZG8gUHJvZHV0byAiQSINCg0KYGBge3IgZmlsdHJvIEF9DQp2ZW5kYXNfcHJvZHV0b19BIDwtIGRhZG9zX2NzdiAlPiUNCiAgZmlsdGVyKFByb2R1dG8gPT0gIkEiKQ0KDQpwcmludCh2ZW5kYXNfcHJvZHV0b19BKQ0KYGBgDQoNCiMjIDMuMy4gYHNlbGVjdCgpYDogU2VsZWNpb25hbmRvIGNvbHVuYXMNCg0KU2VsZWNpb25hIGNvbHVuYXMgcGVsbyBub21lLiBFeGVtcGxvOiBzZWxlY2lvbmFyIGFwZW5hcyBhcyBjb2x1bmFzIERhdGEgZSBWZW5kYXMNCg0KYGBge3Igc2VsZWNpb25hbmRvIGNvbHVuYXN9DQp2ZW5kYXNfc2VsZWNpb25hZGFzIDwtIGRhZG9zX2NzdiAlPiUNCiAgc2VsZWN0KERhdGEsIFZlbmRhcykNCg0KaGVhZCh2ZW5kYXNfc2VsZWNpb25hZGFzKQ0KYGBgDQoNClBvZGVtb3MgcmVtb3ZlciB1bWEgY29sdW5hIHVzYW5kbyBvIHNpbmFsIGRlIG1lbm9zICgtKQ0KDQpgYGB7cn0NCnZlbmRhc19zZW1fcHJvZHV0byA8LSBkYWRvc19jc3YgJT4lDQogIHNlbGVjdCgtUHJvZHV0bykNCg0KaGVhZCh2ZW5kYXNfc2VtX3Byb2R1dG8pDQpgYGANCg0KIyMgMy40LiBgYXJyYW5nZSgpYDogT3JkZW5hbmRvIGxpbmhhcw0KDQpPcmRlbmEgYXMgbGluaGFzIGRvIGRhdGEgZnJhbWUgY29tIGJhc2Ugbm9zIHZhbG9yZXMgZGUgdW1hIG91IG1haXMgY29sdW5hcy4gRXhlbXBsbzogb3JkZW5hciBwb3IgdmVuZGFzLCBkYSBtYWlvciBwYXJhIGEgbWVub3INCg0KYGBge3J9DQp2ZW5kYXNfb3JkZW5hZGFzIDwtIGRhZG9zX2NzdiAlPiUNCiAgYXJyYW5nZShkZXNjKFZlbmRhcykpDQoNCmhlYWQodmVuZGFzX29yZGVuYWRhcykNCmBgYA0KDQojIyAzLjUuIGBtdXRhdGUoKWA6IENyaWFuZG8gbm92YXMgY29sdW5hcw0KDQpDcmlhIG5vdmFzIGNvbHVuYXMgKG91IG1vZGlmaWNhIGV4aXN0ZW50ZXMpIGEgcGFydGlyIGRlIG91dHJhcy4gRXhlbXBsbzogY3JpYXIgdW1hIGNvbHVuYSBjb20gYXMgdmVuZGFzIGVtIG1pbGhhcmVzDQoNCmBgYHtyfQ0KdmVuZGFzX2NvbV9tZXRhIDwtIGRhZG9zX2NzdiAlPiUNCiAgbXV0YXRlKA0KICAgIFZlbmRhc19taWxoYXJlcyA9IFZlbmRhcyAvIDEwMDAsDQogICAgQXRpbmdpdV9tZXRhID0gaWZlbHNlKFZlbmRhcyA+IDMwMCwgIlNpbSIsICJOw6NvIikNCiAgKQ0KDQpoZWFkKHZlbmRhc19jb21fbWV0YSkNCmBgYA0KDQojIyAzLjYuIGBzdW1tYXJpc2UoKWAgZSBgZ3JvdXBfYnkoKWA6IEFncmVnYW5kbyBkYWRvcw0KDQpgc3VtbWFyaXNlKClgIHJlc3VtZSBvcyBkYWRvcyBlbSB1bSDDum5pY28gdmFsb3IgKGUuZy4sIG3DqWRpYSwgc29tYSkuIGBncm91cF9ieSgpYCBwZXJtaXRlIHF1ZSBhIHN1bWFyaXphw6fDo28gc2VqYSBmZWl0YSBwb3IgZ3J1cG9zLiBFeGVtcGxvOiBjYWxjdWxhciBhIHZlbmRhIHRvdGFsIGUgYSB2ZW5kYSBtw6lkaWEgcG9yIHByb2R1dG8NCg0KYGBge3J9DQp2ZW5kYXNfcG9yX3Byb2R1dG8gPC0gZGFkb3NfY3N2ICU+JQ0KICBncm91cF9ieShQcm9kdXRvKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIFZlbmRhX1RvdGFsID0gc3VtKFZlbmRhcyksDQogICAgVmVuZGFfTWVkaWEgPSBtZWFuKFZlbmRhcyksDQogICAgTnVtZXJvX01lc2VzID0gbigpICMgbigpIGNvbnRhIG8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIG5vIGdydXBvDQogICkNCg0KcHJpbnQodmVuZGFzX3Bvcl9wcm9kdXRvKQ0KYGBgDQoNCiMgNC4gQWNlc3NvIGEgRGFkb3MgTWFjcm9lY29uw7RtaWNvcyBjb20gQVBJcyAocmJjYikNCg0KQVBJcyAoQXBwbGljYXRpb24gUHJvZ3JhbW1pbmcgSW50ZXJmYWNlcykgc8OjbyBmb3JtYXMgZGUgc2lzdGVtYXMgY29tcHV0YWNpb25haXMgY29udmVyc2FyZW0gZW50cmUgc2kuIE8gQmFuY28gQ2VudHJhbCBkbyBCcmFzaWwgKEJDQikgb2ZlcmVjZSB1bWEgQVBJIHBhcmEgYWNlc3NvIGFvIHNldSB2YXN0byBiYW5jbyBkZSBkYWRvcyBkZSBzw6lyaWVzIHRlbXBvcmFpcyAoU0dTKS4NCg0KIyMgNC4xLiBPIHBhY290ZSBgcmJjYmANCg0KRXN0ZSBwYWNvdGUgZmFjaWxpdGEgZW5vcm1lbWVudGUgYSBidXNjYSBwb3IgZGFkb3Mgbm8gU0dTIGRvIEJDQi4NCg0KIyMgNC4yLiBPYnRlbmRvIGFzIHPDqXJpZXMgZGUgaW50ZXJlc3NlDQoNClByZWNpc2Ftb3Mgc2FiZXIgb3MgY8OzZGlnb3MgZGFzIHPDqXJpZXMgbm8gc2lzdGVtYSBTR1MuDQoNCi0gICBQSUIgTWVuc2FsIChJQkMtQnIsIMOtbmRpY2UpOiAyNDM2Mw0KDQotICAgSVBDQSAoVmFyaWHDp8OjbyAlIG1lbnNhbCk6IDQzMw0KDQpDcmlhbmRvIHVtIHZldG9yIG5vbWVhZG8gY29tIG9zIGPDs2RpZ29zLiBPcyBub21lcyBzZXLDo28gdXNhZG9zIG5hcyBjb2x1bmFzLg0KDQpgYGB7cn0NCmNvZGlnb3NfYmNiIDwtIGMoDQogIFBJQl9JQkNCciA9IDI0MzYzLA0KICBJUENBID0gNDMzDQopDQpgYGANCg0KVXNhbmRvIGEgZnVuw6fDo28gYGdldF9zZXJpZXNgIHBhcmEgYmFpeGFyIG9zIGRhZG9zIFZhbW9zIGJ1c2NhciBvcyBkYWRvcyBhIHBhcnRpciBkZSAwMS8wMS8yMDAzDQoNCmBgYHtyfQ0KZGFkb3NfcGliIDwtIGdldF9zZXJpZXMoY29kaWdvc19iY2JbMV0sIHN0YXJ0X2RhdGUgPSAiMjAwMy0wMS0wMSIpDQpkYWRvc19pcGNhIDwtIGdldF9zZXJpZXMoY29kaWdvc19iY2JbMl0sIHN0YXJ0X2RhdGUgPSAiMjAwMy0wMS0wMSIpDQpkYWRvc19tYWNybyA8LSBmdWxsX2pvaW4oZGFkb3NfcGliLCBkYWRvc19pcGNhLCBieSA9ICJkYXRlIikNCg0KIyBJbnNwZWNpb25hbmRvIG9zIGRhZG9zIGJhaXhhZG9zDQpoZWFkKGRhZG9zX21hY3JvKQ0KdGFpbChkYWRvc19tYWNybykNCmBgYA0KDQojIyA0LjMuIE1hbmlwdWxhbmRvIG9zIGRhZG9zIG1hY3JvZWNvbsO0bWljb3MNCg0KVmFtb3MgcmVub21lYXIgYXMgY29sdW5hcyBwYXJhIHBvcnR1Z3XDqnMgZSBhanVzdGFyIG8gZm9ybWF0byBkYSBkYXRhLg0KDQpgYGB7cn0NCmRhZG9zX21hY3JvIDwtIGRhZG9zX21hY3JvICU+JQ0KICByZW5hbWUoDQogICAgRGF0YSA9IGRhdGUNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIERhdGEgPSBhcy5EYXRlKERhdGEpICMgR2FyYW50aW5kbyBxdWUgYSBjb2x1bmEgRGF0YSDDqSBkbyB0aXBvIERhdGUNCiAgKQ0KDQpoZWFkKGRhZG9zX21hY3JvKQ0KYGBgDQoNCiMgNS4gQnJldmUgRXhlbXBsbyBkZSBWaXN1YWxpemHDp8OjbyBjb20gZ2dwbG90Mg0KDQpPIGBnZ3Bsb3QyYCDDqSBiYXNlYWRvIG5hICJHcmFtw6F0aWNhIGRvcyBHcsOhZmljb3MiLCBwZXJtaXRpbmRvIGEgY29uc3RydcOnw6NvIGRlIGdyw6FmaWNvcyBjb21wbGV4b3MgZGUgZm9ybWEgaW50dWl0aXZhLCBjYW1hZGEgcG9yIGNhbWFkYS4NCg0KQSBlc3RydXR1cmEgYsOhc2ljYSDDqToNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpnZ3Bsb3QoZGF0YSA9IDxEQURPUz4sIG1hcHBpbmcgPSBhZXMoPE1BUEVBTUVOVE9TIEVTVMOJVElDT1M+KSkgKw0KICAgPENBTUFEQSBHRU9Nw4lUUklDQT4oKQ0KYGBgDQoNClZhbW9zIGNyaWFyIHVtIGdyw6FmaWNvIGRlIGxpbmhhcyBwYXJhIHVtYSBkYXMgc8OpcmllcyBxdWUgYmFpeGFtb3MuDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KIyBDw7NkaWdvIHBhcmEgcGxvdGFyIG5vIGZvcm1hdG8gImxhcmdvIg0KZ2dwbG90KGRhZG9zX21hY3JvLCBhZXMoeCA9IERhdGEsIHkgPSBQSUJfSUJDQnIpKSArDQogIGdlb21fbGluZSgpICsgIyBBZGljaW9uYSBhIGNhbWFkYSBkZSBsaW5oYSBwYXJhIGNyaWFyIG8gZ3LDoWZpY28gZGUgc8OpcmllIHRlbXBvcmFsDQogIGxhYnMoDQogICAgdGl0bGUgPSAiU8OpcmllIFRlbXBvcmFsIGRvIFBJQiBJQkMtQnIiLA0KICAgIHggPSAiRGF0YSIsDQogICAgeSA9ICJQSUIgSUJDLUJyIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICMgVW0gdGVtYSBsaW1wbyBwYXJhIG8gZ3LDoWZpY28gKG9wY2lvbmFsKQ0KYGBgDQo=