===== Demanda habitacional no Distrito Federal ====

Esses códigos foram elaborados pela equipe da Diretoria de Estudos e Políticas Ambientais e Territoriais (DEPAT), sob trabalhos diretos da Coordenação de Estudos Territoriais (COET). O relatório da pesquisa está disponível em https://www.ipe.df.gov.br/deficit-e-demanda-habitacional-do-distrito-federal-2021/ A DEPAT é parte do IPEDF Instituto de Pesquisa e Estatística do Distrito Federal (IPEDF) Os códigos a seguir dizem respeito ao ajuste da base de dados da Pesquisa de modo a permitir a expansão e realização de inferências. Há também algumas das tabelas utilizadas. Todos os demais agrupamentos e cálculos presentes no relatório foram feitos com base na metodologia. Pedimos a gentileza de reportarem bugs ou erros nos códigos abaixo. E-mail: Todos os dados foram obtidos a partir da Pesquisa Distrital por Amostra de Domicílios (PDAD) O dicionário de variáveis e outras informações sobre a PDAD 2021 podem ser encontrados no site do IPEDF: https://www.ipe.df.gov.br/microdados-pdad-2021/

===== Configurações R ====

Criando um ambiente virtual Para manter a memória dos pacotes utilizados, de modo que possam ser totalmente reproduzidos, sugere-se utilizar o pacote renv.

Para isso, o pacote deve ser instalado inicialmente. Este procedimento foi feito com o renv 1.0.2.

## Adotando a versão correta dos pacotes.

Junto com esse script, estão disponíveis os arquivos renv.lock, .Rprofile, renv/settings.json e renv/activate.R.

Para que os pacotes sejam os mesmos utilizados neste projeto, as informações das versões dos pacotes ficarão registradas no arquivo renv.lock. Com esse arquivo na mesma pasta do projeto, pode-se recuperar as versões adequadas em qualquer outra máquina com conexão ao repositório ou à internet com a função renv::restore().

Configurações opcionais


#rm(list = ls(all = TRUE))
options(scipen = 999)
salariominimo<-1302

===== 0. Carregar pacotes e leitura dos dados ====

Pacotes necessários

# O pacote `pacman`, por meio de sua função p_load()
  # é utilizado para instalar e carregar os pacotes necessários
  # Primeiro, testa-se se o pacote está instalado. Se não, esta será feita.
if(!require("pacman")) install.packages("pacman")

pacman::p_load(
               tidyverse,     # Pacote para manipulação de dados
               readxl,        # Pacote para leitura de arquivos .xls e .xlsx
               lubridate,     # Pacote para manipulação de datas
               data.table,    # Pacote para manipulação de dados
               survey,        # Pacote para manipulação de dados survey
               srvyr          # Pacote que ajusta a família tidyverse para dados survey        
               )
library(googledrive)
library(googlesheets4)

Importar dados:

Dic_mor <- read_csv("Dic_mor.csv")
Rows: 19018 Columns: 4
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): coluna, desc_coluna, desc_valor
dbl (1): valor

ℹ 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.
#pdad2023 <- read_csv("pdad2023_tratada.csv")
pdad2023 <- read_csv("pdad2024out.csv")
New names:
• `` -> `...1`
Aviso: One or more parsing issues, call `problems()` on your data frame for details, e.g.:
  dat <- vroom(...)
  problems(dat)
Rows: 69542 Columns: 268
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr    (6): ficha, morador_id, E04_1_1, E06_1, E08_1, chave_morador
dbl  (260): ...1, A01uf, localidade, setor_distrito, indice, idade_calculada, E02_3, E03, E03_1, E03_1_1, E03_2, E03_2_1, E04, E04_1, E...
date   (2): E02_1, E02_2

ℹ 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.
Dic_Dom <- read_csv("Dic_Dom.csv")
Rows: 733 Columns: 4
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): coluna, desc_coluna, desc_valor
dbl (1): valor

ℹ 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.

===== Ajustes iniciais ====

O objetivo é calcular a demanda habitacional com a taxa de chefia tradicional - que leva em conta todos os chefes daquela faixa etária.

# Fazer a junção das bases de moradores e domicílios
  # Trazer as informações de pessoas para domicílios

#rm(pdad_dom_2021, pdad_mor_2021)

#ajustes

pdad2023$UF[pdad2023$A01uf==52]<-"PMB"
Aviso: Unknown or uninitialised column: `UF`.
pdad2023$UF[pdad2023$A01uf==53]<-"DF"
pdad2023$UF |> table()

   DF   PMB 
50643 18899 

Dic_Dom |> filter(str_detect(coluna,"loca"))
pdad2023 |> 
    left_join(Dic_Dom |> filter(coluna=="localidade") |> mutate(strata_localidade=desc_valor) |> select(-coluna,-desc_coluna,-desc_valor),by=c("localidade"="valor"))->pdad2023

pdad2023$idade<-pdad2023$idade_calculada
pdad2023$A01nficha<-pdad2023$ficha
pdad2023$RA_nome<-pdad2023$strata_localidade
pdad2023<-pdad2023 %>% mutate(grupo_pdadA=case_when(RA_nome=="Área Rural"~"Área Rural",
                                          UF=="DF"~"DF",
                                          TRUE~UF))# %>% select(grupo_pdadA) %>% table()


#pdad2023$A01npessoas
#pdad2023 %>% select(ficha,morador_id) %>% 
#  mutate(n_morador=as.numeric(str_remove(morador_id,paste0(ficha,"-")))) %>% 
#  group_by(ficha) %>%summarise(A01npessoas=max(n_morador)) %>% 
#  right_join(pdad2023,by=c("ficha") )->pdad2023

                                                                                                          
# Deixar apenas os domicílios/moradores onde o responsável tem entre 24 e 64 anos.
pdad2023_original <- pdad2023

pdad2023 <-
  subset(pdad2023,
         ficha %in% subset(pdad2023, E04 == 1 &
                                 idade_calculada %in% c(24:64))$ficha)

#pdad2023 %>% 

Agora, deve-se identificar os domicílios que têm demanda habitacional, e trabalhar apenas com estes.

# Criação das classificações de famílias

matriz_familiar <- pdad2023 %>% 
  # select(A01nficha, A01npessoas, E04, idade) %>% 
  mutate(condicao = 1, 
         E04_edit = case_when(E04 == 1 ~ 'responsavel', 
                              E04 == 2 ~ 'conjuge', 
                              E04 == 3 ~ 'conjuge', 
                              E04 == 4 & idade < 24 ~ 'filho_menor24', 
                              E04 == 5 & idade < 24 ~ 'filho_menor24',
                              E04 == 6 & idade < 24 ~ 'filho_menor24' , 
                              E04 == 4 & idade >=24 ~ 'filho_maior24', 
                              E04 == 5 & idade >=24 ~ 'filho_maior24',
                              E04 == 6 & idade >=24 ~ 'filho_maior24', 
                              E04 == 7 ~ 'genro_nora', 
                              E04 == 8 ~ 'pais', 
                              E04 == 9 ~ 'sogros', 
                              E04 == 10 ~ 'neto', 
                              E04 == 11 ~ 'bisneto', 
                              E04 == 12 ~ 'irmao', 
                              E04 == 13 ~ 'avos',
                              E04 == 14 ~ 'outro_parente', 
                              E04 == 15 ~ 'agregado',
                              E04 == 16 ~ 'convivente', 
                              E04 == 17 ~ 'pensionista',
                              E04 == 18 ~ 'empregado_domestico', 
                              E04 == 19 ~ 'parente_empregado')) %>% 
  group_by(A01nficha, A01npessoas,
           E04_edit) %>% 
  summarise(n = sum(condicao)) %>%  
  spread(E04_edit, n)
`summarise()` has grouped output by 'A01nficha', 'A01npessoas'. You can override using the `.groups` argument.

Criar variável indicadora de idoso no domicílio

pdad2023$idoso <- ifelse(pdad2023$idade >= 65, 1, 0)

matriz_idosos <-
  as.data.frame(table(pdad2023$A01nficha, pdad2023$idoso))

pdad2023$idoso <- NULL

matriz_idosos$idosos <-
  as.numeric(levels(matriz_idosos$Var2))[matriz_idosos$Var2] * matriz_idosos$Freq

names(matriz_idosos)[1] <- "A01nficha"

matriz_idosos <- subset(matriz_idosos, idosos > 0)

matriz_familiar <-
  merge(matriz_familiar,
        matriz_idosos,
        by = "A01nficha",
        all.x = TRUE)

#rm(matriz_idosos)
matriz_idosos

# Indicadora se o idoso é responsável ou cônjuge.

matriz_familiar$idoso_conj <-
  ifelse(
    matriz_familiar$A01nficha %in% subset(pdad2023, E04 %in% c(2, 3) &
                                            idade >= 65)$A01nficha,
    1,
    0
  )

# Criar variável indicadora se alguém entre 24 e 64 anos mora no domicílio e não é responsável ou cônjuge.

pdad2023$adulto <-
  ifelse(pdad2023$idade >= 24 & pdad2023$idade < 65, 1, 0)

matriz_adulto <-
  as.data.frame(table(pdad2023$A01nficha, pdad2023$adulto))

pdad2023$adulto <- NULL

matriz_adulto$adulto <-
  as.numeric(levels(matriz_adulto$Var2))[matriz_adulto$Var2] * matriz_adulto$Freq

names(matriz_adulto)[1] <- "A01nficha"

matriz_adulto <- subset(matriz_adulto, adulto > 0)

matriz_familiar <-
  merge(matriz_familiar,
        matriz_adulto,
        by = "A01nficha",
        all.x = TRUE)

#rm(matriz_adulto)

Indicadora se o adulto é responsável ou cônjuge.

matriz_familiar$adulto_resp <-
  ifelse(
    matriz_familiar$A01nficha %in% subset(pdad2023, E04 == 1 &
                                            idade >= 24 & idade < 65)$A01nficha,
    1,
    0
  )
matriz_familiar %>% group_by(adulto_resp) %>% summarise(n=n()) ### todos os domicilios tem adultos como responsaveis pelo domicilio
matriz_familiar$adulto_conj <-
  ifelse(
    matriz_familiar$A01nficha %in% subset(pdad2023, E04 %in% c(2, 3) &
                                            idade >= 24 & idade < 65)$A01nficha,
    1,
    0
  )

matriz_familiar %>% group_by(adulto_conj) %>% summarise(n=n()) ### todos os domicilios tem adultos como responsaveis pelo domicilio
NA

Indicação de que não há demanda nos domicílios onde mora só o responsável com o cônjuge,

# filhos menores de 24 anos e idosos.
matriz_familiar$demanda <- NA
matriz_familiar$co
NULL
matriz_familiar$demanda <-
  ifelse(((
    rowSums(matriz_familiar[, c("responsavel", "conjuge", "filho_menor24", "idosos")], na.rm =TRUE) 
    - (matriz_familiar[, c("idoso_conj")])
  ) == matriz_familiar$A01npessoas) == TRUE,
  0,
  matriz_familiar$demanda)

matriz_familiar$demanda %>% table()
.
    0 
14211 
  # Número de pessoas no domicílio que demandam habitação - i.e tem pessoas entre 24 e 64 anos
  # que não são responsáveis ou cônjuges.
matriz_familiar$demanda <-
  ifelse((matriz_familiar$A01npessoas - (
    rowSums(matriz_familiar[, c("responsavel", "conjuge", "filho_menor24", "idosos")], na.rm =
              TRUE) - (matriz_familiar[, c("idoso_conj")])
  )) > 0,
  (
    matriz_familiar$adulto - rowSums(matriz_familiar[, c("adulto_resp", "adulto_conj")], na.rm =
                                       TRUE)
  ),
  matriz_familiar$demanda
  )

Transformando a demanda dos casos em que os pais, avós filhos/genro/nora moram no domicílio.

# Considerar a idade da pessoa mais velha do casal. 
  # Se a pessoa mais velha do casal for idosa, o casal não tem demanda por habitação.
  # Primeiro, cria-se uma variável indicadora para o tipo de casal.
matriz_familiar$casal_avos <- ifelse(matriz_familiar$avos == 2, 1, NA)

matriz_familiar$casal_pais <- ifelse(matriz_familiar$pais == 2, 1, NA)

matriz_familiar$casal_sogros <-
  ifelse(matriz_familiar$sogros == 2, 1, NA)

A indicação da existência de casal de filhos é a própria variável de de genro/nora.

  # Faz-se para cada tipo de casal separado porque pode ter mais de um tipo de casal por domicílio.

  # Separa-se os indivíduos de cada casal para calcular a idade máxima dele.
idade_casal_avos <-
  subset(
    pdad2023,
    A01nficha %in% subset(matriz_familiar, casal_avos == 1 &
                            demanda > 0)$A01nficha
  ) %>%
  subset(E04 == 13)

idade_casal_sogros <-
  subset(
    pdad2023,
    A01nficha %in% subset(matriz_familiar, casal_sogros == 1 &
                            demanda > 0)$A01nficha
  ) %>%
  subset(E04 == 9)

idade_casal_pais <-
  subset(
    pdad2023,
    A01nficha %in% subset(matriz_familiar, casal_pais == 1 &
                            demanda > 0)$A01nficha
  ) %>%
  subset(E04 == 8)
# Calculo a idade do cônjuge mais velho para determinar o chefe do casal.
idade_casal_avos2 <- idade_casal_avos %>%
  group_by(A01nficha) %>%
  summarise(chefe_idade = max(idade))

idade_casal_avos <-
  merge(idade_casal_avos,
        idade_casal_avos2,
        by = "A01nficha",
        all.x = TRUE)

idade_casal_avos <- idade_casal_avos %>%
  group_by(A01nficha) %>%
  mutate(chefe_id = ifelse(
    sum(idade) / 2 == chefe_idade,
    min(morador_id),
    ifelse(idade == chefe_idade, morador_id, 0)
  )) %>%
  mutate(chefe_casal = ifelse(morador_id == chefe_id, 1, 0)) %>%
  mutate(conj_casal = ifelse(morador_id != chefe_id, 1, 0))

#rm(idade_casal_avos2)

idade_casal_sogros2 <- idade_casal_sogros %>% 
  group_by(A01nficha) %>% 
  summarise(chefe_idade = max(idade))

idade_casal_sogros <-
  merge(idade_casal_sogros,
        idade_casal_sogros2,
        by = "A01nficha",
        all.x = TRUE)

idade_casal_sogros <- idade_casal_sogros %>%
  group_by(A01nficha) %>%
  mutate(chefe_id = ifelse(
    sum(idade) / 2 == chefe_idade,
    min(morador_id),
    ifelse(idade == chefe_idade, morador_id, 0)
  )) %>%
  mutate(chefe_casal = ifelse(morador_id == chefe_id, 1, 0)) %>%
  mutate(conj_casal = ifelse(morador_id != chefe_id, 1, 0))

#rm(idade_casal_sogros2)

idade_casal_pais2 <- idade_casal_pais %>%
  group_by(A01nficha) %>%
  summarise(chefe_idade = max(idade))

idade_casal_pais <-
  merge(idade_casal_pais,
        idade_casal_pais2,
        by = "A01nficha",
        all.x = TRUE)

idade_casal_pais <- idade_casal_pais %>%
  group_by(A01nficha) %>%
  mutate(chefe_id = ifelse(
    sum(idade) / 2 == chefe_idade,
    min(morador_id),
    ifelse(idade == chefe_idade, morador_id, 0)
  )) %>%
  mutate(chefe_casal = ifelse(morador_id == chefe_id, 1, 0)) %>%
  mutate(conj_casal = ifelse(morador_id != chefe_id, 1, 0))

#rm(idade_casal_pais2)
# Identificação dos casos de genro/nora e filhos.
idade_casal_filhos01 <-
  subset(
    pdad2023,
    A01nficha %in% subset(matriz_familiar, genro_nora == 1 &
                            filho_maior24 == 1, demanda > 0)$A01nficha
  ) %>%
  subset(E04 == 7 | (E04 %in% c(4:6) & idade >= 24))

idade_casal_filhos01b <- idade_casal_filhos01 %>% 
  group_by(A01nficha) %>% 
  summarise(chefe_idade = max(idade))

idade_casal_filhos01 <-
  merge(idade_casal_filhos01,
        idade_casal_filhos01b,
        by = "A01nficha",
        all.x = TRUE)

idade_casal_filhos01 <- idade_casal_filhos01 %>%
  group_by(A01nficha) %>%
  mutate(chefe_id = ifelse(
    sum(idade) / 2 == chefe_idade,
    min(morador_id),
    ifelse(idade == chefe_idade, morador_id, 0)
  )) %>%
  mutate(chefe_casal = ifelse(morador_id == chefe_id, 1, 0)) %>%
  mutate(conj_casal = ifelse(morador_id != chefe_id, 1, 0))

#rm(idade_casal_filhos01b)

idade_casal_filhos02 <-
  subset(
    pdad2023,
    A01nficha %in% subset(matriz_familiar, genro_nora == 1 &
                            filho_maior24 >= 2, demanda > 0)$A01nficha
  ) %>%
  subset(E04 == 7 | (E04 %in% c(4:6) & idade >= 24))

idade_casal_filhos02ad <- idade_casal_filhos02 %>%
  group_by(A01nficha) %>%
  filter(E04 %in% c(4:6)) %>%
  summarise(idade_filho = max(idade))

idade_casal_filhos02 <-
  merge(idade_casal_filhos02,
        idade_casal_filhos02ad,
        by = "A01nficha",
        all.x = TRUE) %>%   subset(E04 == 7 | idade == idade_filho) %>%
  subset(!(A01nficha == 57658 & morador_id == 4)) # Retira-se este caso específico em que os dois filhos mais velhos são gêmeos.

#rm(idade_casal_filhos02ad)

idade_casal_filhos02b <- idade_casal_filhos02 %>%
  group_by(A01nficha) %>%
  summarise(chefe_idade = max(idade))

idade_casal_filhos02 <-
  merge(idade_casal_filhos02,
        idade_casal_filhos02b,
        by = "A01nficha",
        all.x = TRUE)

idade_casal_filhos02 <- idade_casal_filhos02 %>%
  group_by(A01nficha) %>%
  mutate(chefe_id = ifelse(
    sum(idade) / 2 == chefe_idade,
    min(morador_id),
    ifelse(idade == chefe_idade, morador_id, 0)
  )) %>%
  mutate(chefe_casal = ifelse(morador_id == chefe_id, 1, 0)) %>%
  mutate(conj_casal = ifelse(morador_id != chefe_id, 1, 0))

#rm(idade_casal_filhos02b)
# O genro/nora vai ser o chefe neste caso. Imputam-se os filhos mais velhos como cônjuge.
idade_casal_filhos03genro <-
  subset(
    pdad2023,
    A01nficha %in% subset(matriz_familiar, genro_nora == 2 &
                            demanda > 0)$A01nficha
  ) %>%
  subset(E04 == 7)

  # Tem alguns casos que tem dois genros/noras, e não tem filhos com mais de 24 anos, apenas filhos menores.
idade_casal_filhos03filho <-
  subset(
    pdad2023,
    A01nficha %in% subset(matriz_familiar, genro_nora == 2 &
                            demanda > 0)$A01nficha
  ) %>%
  subset(E04 %in% c(4:6)) %>%
  arrange(desc(idade)) %>%
  group_by(A01nficha) %>%
  slice(1:2)

  # Junto os dados dos genros e filhos.
idade_casal_filhos03 <-
  rbind(idade_casal_filhos03genro, idade_casal_filhos03filho)

idade_casal_filhos03 <- idade_casal_filhos03 %>%
  group_by(A01nficha) %>%
  mutate(chefe_casal = ifelse(E04 == 7, 1, 0)) %>%
  mutate(conj_casal = ifelse(E04 != 7, 1, 0)) %>%
  mutate(chefe_id = ifelse(chefe_casal == 1, morador_id, 0))

#rm(idade_casal_filhos03genro, idade_casal_filhos03filho)
# Junção de todos os casos de casais
library(data.table)
casais <-
  bind_rows(
    #list(
      idade_casal_avos,
      idade_casal_pais,
      idade_casal_sogros,
      idade_casal_filhos01,
      idade_casal_filhos02,
      idade_casal_filhos03
    )
New names:
• `...1` -> `...2`
New names:
• `...1` -> `...2`
New names:
• `...1` -> `...2`
New names:
• `...1` -> `...2`
New names:
• `...1` -> `...2`
  # Apesar de o objeto ser "casais", o número de observações é ímpar porque têm casais que só tem o genro.
casais <-
  casais[, c("A01nficha",
             "morador_id",
             "chefe_casal",
             "conj_casal",
             "chefe_id")]

casais <- as.data.frame(casais)
# Adição da informação sobre casais na PDAD.
pdad2023_original <-
  merge(
    pdad2023_original,
    casais,
    all.x = TRUE,
    by = c("morador_id","A01nficha")
  )

pdad2023_original$conj_casal <-
  ifelse(is.na(pdad2023_original$conj_casal) == TRUE,
         0,
         pdad2023_original$conj_casal)

#pdad2023_original$conj_casal %>% table()
  # Juntando as informações de demanda habitacional com a PDAD.
pdad2023_original <-
  merge(pdad2023_original,
        matriz_familiar[, c("A01nficha", "demanda")],
        by = "A01nficha",
        all.x = TRUE)
# Contabilizando a renda do responsável pelo domicílio.
pdad_renda <- pdad2023_original %>%
  filter(E04 == 1) %>%
  mutate(
    renda_resp = case_when(
      renda_ind_r <= 1100 ~ "ate01SM",
      renda_ind_r > 1100 &
        renda_ind_r <= 3300 ~ "1a3SM",
      renda_ind_r > 3300 &
        renda_ind_r <= 5500 ~ "3a5SM",
      renda_ind_r > 5500 &
        renda_ind_r <= 13200 ~ "5a12SM",
      renda_ind_r > 13200 ~ "maisde12SM"
    )
  ) %>%
  select(A01nficha, renda_resp)
# Junção dos dados de renda dos responsável com as demais informações da PDAD.
pdad2023_original <-
  merge(pdad2023_original,
        pdad_renda,
        by = "A01nficha",
        all.x = TRUE)

#rm(pdad_renda, idade_casal_avos, idade_casal_filhos01,
#   idade_casal_filhos02, idade_casal_filhos03, idade_casal_pais,
#   idade_casal_sogros, matriz_familiar, casais)

Expansão da amostra

pdad2023_original$demanda
   [1]  0  0  0  0  0 NA NA NA NA NA NA NA  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  0  0  0  0  0
  [45]  2  2  2  2  2  0  0  0 NA NA  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 NA NA NA  0  0  0  0  2  2  2  2  0  0  0  0  0  0  0
  [89]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  2  2  2 NA NA NA  1  1  1 NA  0  0  0  0  1  1  1  0 NA NA NA NA NA  0  0  0  0
 [133]  0  0  0  0  0  1  1  1  1  0  0  0  0  0  0  0  1  1  2  2  2  2  0  0  1  1  1  0  0  0  0  0  0 NA NA NA  0  1  1  1  1  1  0  0
 [177]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  2  2  2  2  2  2  0  0  0  1  1  1  1  0  0 NA NA  0 NA NA NA NA NA  0  0  0  0  0  0  0
 [221]  0  0  0  0  1  1  1  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  0  0  0  0 NA NA NA NA  1  1
 [265]  1  1  0  0  0  0  0  0 NA NA NA  0  0  0  0 NA  0  0  0  0  0  0  0  0  1  1  1  0  0  0  0  1  1  1  1  0  0 NA NA NA NA  1  1  0
 [309]  0  0  0 NA NA NA NA NA  0  0  0  0  0  0  0  2  2  2  3  3  3  3  3  3  3  3 NA NA NA NA NA NA NA NA  2  2  2  0  0  0  0 NA NA NA
 [353]  0  0  0 NA NA NA NA NA  0  0  0  2  2  2  2 NA NA  3  3  3  3  3  1  1  1  1  1  0  0  0  0  0  0 NA  0  0 NA NA NA NA  0  0  0  0
 [397]  1  1 NA NA  0  0  0  0  0  0  0  0 NA NA  0  0  0  0  0 NA NA NA NA  0  0  0  0  0  0  0  0  0  0  0  0 NA NA NA NA NA NA NA NA  0
 [441]  0  0  0  0  2  2  2  2  2  2  2  2  2 NA NA NA  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  2  2  2  2 NA NA NA  0
 [485]  0  0  0 NA NA NA NA  1  1  1  1  1  1  0 NA NA NA NA  0 NA NA NA NA NA NA  0  0  0  0  0  1  1  1  0  0  0  0  0  0  0  0  0  0  0
 [529]  0  0  0  0  0  1  1  1  1  1  0  0  0  0  0  1  1  1  1  0  0  0  0  0  0 NA NA  0  0  0  0  0  1  1  1  1 NA NA NA NA NA  0  0  0
 [573]  0 NA NA NA NA NA NA  0  0  0  0  0  0  0  0  0  0  0  0  0  2  2  2  2  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 [617]  0 NA NA NA  0  0  0  0  0  0  0 NA NA NA  0  0  0  0  0  0  1  1  0  0  0  0  0  0  0  0 NA NA  0  0  0  0  0  0  0  1  1  0  0  0
 [661]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 NA NA NA  0  0  0  0  0  0  0  0 NA  1  1  1 NA NA  0  0  1  1  1  1  0  0  0  0
 [705]  2  2  2  2  0  0  0 NA NA  0  0  0  0  1  1  1  0  0 NA NA  0  0  1  1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 NA NA  0
 [749]  0 NA NA  0  0  0  0  0  0  0  0  0  0  0 NA NA NA  0  0  0  0  0  0  0  0  0  0  1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 [793]  2  2  2  2  0  0  1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  3  3  3  3  3  3 NA NA NA  0 NA  0  0  2  2  2  0  0  0
 [837]  0  0  0  0  0  0  0  0  2  2  2  2  0  0  0  0  0  0  0 NA  0  0 NA  0  0  0  0  0  0  0  0  0  0  0 NA NA NA NA  0  0  0  0  0  0
 [881]  0  0  0  0  0  0  0  0  0  0  4  4  4  4  4  0  0 NA NA NA  0  0  0  0 NA NA  1  1  0  0  0  0  0  1  1  1  1  0  0 NA  1  1  1  1
 [925] NA NA NA  0  0  0  0  0  0  0  0  2  2  2  2  0  0  0  2  2  2  2  2  0  0  0  0  0  0  0  2  2  2  2  2  1  1  1 NA NA  0  0  0  1
 [969]  1  1 NA  2  2  2  2  0  1  1  1  1  1  1  1  1  1  0  0  1  1  1  1  0  0  0  0  0 NA NA  1  1
 [ reached getOption("max.print") -- omitted 68542 entries ]

# Declarar o desenho incial

amostra_mor <- 
  survey::svydesign(id = ~ficha,
                    strata = ~setor_distrito,
                    weights = ~peso_mor,
                    nest=TRUE,
                    data=pdad2023_original) 

amostra_mor <- srvyr::as_survey(amostra_mor)

  # Exclui arquivos não mais usados
#rm(amostra, sample_pdad, post_pop, pdad2023_original)

Resultados e inferências

Calculando a taxa de chefia por grupo etário.

Calculando o total de pessoas na população.

pop_total <- amostra_mor %>%
  srvyr::mutate(
    grupo_etario = case_when(
      idade %in% c(24:29) ~ "idade_24_29",
      idade %in% c(30:39) ~ "idade_30_39",
      idade %in% c(40:64) ~ "idade_40_64"
    )
  ) %>%
  srvyr::group_by(grupo_etario,grupo_pdadA) %>%
  srvyr::summarise(pop_total = survey_total(vartype = c("cv", "ci")))

pop_total <- subset(pop_total,!is.na(grupo_etario))
pop_total

# Juntando as tabelas para calcular a taxa de chefia por idade.

tx_chefia_idade <- cbind(tx_chefia, pop_total[, -c(1,2)])

tx_chefia_idade$tx_chefia <-
  tx_chefia_idade$total_chefes / tx_chefia_idade$pop_total

  # Teste para ver se é possível fazer inferência sobre os dados.
  # Necessário coeficiente de variação (cv) menor do que 25%
tx_chefia_idade <- as.data.frame(tx_chefia_idade)

tx_chefia_idade$tx_chefia <-
  ifelse(tx_chefia_idade$total_chefes_cv > 0.25,
         NA,
         tx_chefia_idade$tx_chefia)

#rm(tx_chefia, pop_total)

Cálculo a taxa de chefia por idade e RA.

tx_chefia_idade_ra <- amostra_mor %>% 
  srvyr::mutate(grupo_etario = case_when(idade %in% c(24:29) ~ "idade_24_29",
                                         idade %in% c(30:39) ~ "idade_30_39",
                                         idade %in% c(40:64) ~ "idade_40_64")) %>% 
  srvyr::filter(E04==1) %>% 
  srvyr::group_by(grupo_etario, RA_nome,grupo_pdadA) %>% 
  srvyr::summarise(total_chefes=survey_total(vartype = c("cv", "ci")))

tx_chefia_idade_ra <- subset(tx_chefia_idade_ra, !is.na(grupo_etario))

pop_idade_ra <- amostra_mor %>% 
  srvyr::mutate(grupo_etario = case_when(idade %in% c(24:29) ~ "idade_24_29",
                                         idade %in% c(30:39) ~ "idade_30_39",
                                         idade %in% c(40:64) ~ "idade_40_64")) %>% 
  srvyr::group_by(grupo_etario, RA_nome,grupo_pdadA) %>% 
  srvyr::summarise(pop_total=survey_total(vartype = c("cv", "ci")))

pop_idade_ra <- subset(pop_idade_ra, !is.na(grupo_etario))

tx_chefia_idade_raf <-
  cbind(tx_chefia_idade_ra, pop_idade_ra[, -c(1,2,3)])

tx_chefia_idade_raf$tx_chefia <-
  tx_chefia_idade_raf$total_chefes / tx_chefia_idade_raf$pop_total

tx_chefia_idade_raf <-
  subset(tx_chefia_idade_raf,!is.na(grupo_etario))

  # Teste para ver se inferências podem ser feitas 
tx_chefia_idade_raf <- as.data.frame(tx_chefia_idade_raf)

tx_chefia_idade_raf$tx_chefia <-
  ifelse(tx_chefia_idade_raf$total_chefes_cv > 0.25,
         NA,
         tx_chefia_idade_raf$tx_chefia)

save tx chefia————

Calcular o número de adultos que têm demanda habitacional por grupo etário.

demanda_idade <- amostra_mor  %>% 
   srvyr::filter(demanda > 0 & !(E04 %in% c(1:3))) %>%
   srvyr::mutate(demanda_ind = ifelse(idade %in% c(24:64) &
                                        conj_casal == 0, 1, 0)) %>%
   srvyr::mutate(
     grupo_etario = case_when(
       idade %in% c(24:29) ~ "idade_24_29",
       idade %in% c(30:39) ~ "idade_30_39",
       idade %in% c(40:64) ~ "idade_40_64"
     )
   ) %>%
   srvyr::group_by(grupo_etario,grupo_pdadA) %>%
   srvyr::summarise(demanda_ = survey_total(demanda_ind, vartype = c("cv", "ci"), na.rm =
                                              TRUE))
 
 
  # Teste para ver se é possível fazer inferência sobre os dados.
 demanda_idade <- as.data.frame(demanda_idade)
 
 demanda_idade$demanda_ <-
   ifelse(demanda_idade$demanda__cv > 0.25, NA, demanda_idade$demanda_)
 
 demanda_idade <- subset(demanda_idade,!is.na(grupo_etario))
 
 demanda_idade_final  <-
   merge(demanda_idade, tx_chefia_idade, by = c("grupo_etario","grupo_pdadA"))
 
 demanda_idade_final$demanda_final <-
   demanda_idade_final$demanda_ * demanda_idade_final$tx_chefia

Tabela final

demanda_idade_final %>% filter(grupo_pdadA=="DF")%>% janitor::adorn_totals()
 grupo_etario grupo_pdadA  demanda_ demanda__cv demanda__low demanda__upp total_chefes total_chefes_cv total_chefes_low total_chefes_upp
  idade_24_29          DF 116140.53  0.03277222    108678.35    123602.71     75125.59     0.036912226         69690.25         80560.94
  idade_30_39          DF  84400.93  0.03983517     77809.34     90992.51    203635.50     0.021343422        195116.54        212154.47
  idade_40_64          DF  56287.51  0.04524773     51294.25     61280.78    500393.82     0.009685936        490893.83        509893.80
        Total           - 256828.97  0.11785512    237781.94    275876.00    779154.91     0.067941584        755700.61        802609.21
 pop_total pop_total_cv pop_total_low pop_total_upp tx_chefia demanda_final
  269847.7  0.021446792      258504.1      281191.3 0.2784000      32333.53
  470022.4  0.015739596      455522.0      484522.9 0.4332464      36566.39
  930598.7  0.008547462      915007.9      946189.6 0.5377117      30266.45
 1670468.8  0.045733849     1629034.0     1711903.7 1.2493581      99166.37
demanda_idade_final %>% filter(grupo_pdadA=="DF")%>% janitor::adorn_totals()
 grupo_etario grupo_pdadA  demanda_ demanda__cv demanda__low demanda__upp total_chefes total_chefes_cv total_chefes_low total_chefes_upp
  idade_24_29          DF 116140.53  0.03277222    108678.35    123602.71     75125.59     0.036912226         69690.25         80560.94
  idade_30_39          DF  84400.93  0.03983517     77809.34     90992.51    203635.50     0.021343422        195116.54        212154.47
  idade_40_64          DF  56287.51  0.04524773     51294.25     61280.78    500393.82     0.009685936        490893.83        509893.80
        Total           - 256828.97  0.11785512    237781.94    275876.00    779154.91     0.067941584        755700.61        802609.21
 pop_total pop_total_cv pop_total_low pop_total_upp tx_chefia demanda_final
  269847.7  0.021446792      258504.1      281191.3 0.2784000      32333.53
  470022.4  0.015739596      455522.0      484522.9 0.4332464      36566.39
  930598.7  0.008547462      915007.9      946189.6 0.5377117      30266.45
 1670468.8  0.045733849     1629034.0     1711903.7 1.2493581      99166.37
demanda_idade_final %>% filter(grupo_pdadA=="PMB") %>% janitor::adorn_totals()
 grupo_etario grupo_pdadA  demanda_ demanda__cv demanda__low demanda__upp total_chefes total_chefes_cv total_chefes_low total_chefes_upp
  idade_24_29         PMB  48550.49  0.05858833     42973.75     54127.23     41675.72      0.05351186         37304.50         46046.94
  idade_30_39         PMB  31807.72  0.07692748     27010.49     36604.94    102881.11      0.03559510         95703.24        110058.97
  idade_40_64         PMB  19893.31  0.07707627     16887.21     22899.41    201480.99      0.01529425        195441.07        207520.91
        Total           - 100251.51  0.21259209     86871.44    113631.58    346037.81      0.10440121        328448.81        363626.82
 pop_total pop_total_cv pop_total_low pop_total_upp tx_chefia demanda_final
  131315.2   0.03382109      122610.1      140020.2 0.3173717      15408.55
  214762.8   0.02709482      203357.3      226168.3 0.4790453      15237.34
  356191.4   0.01393277      346464.1      365918.6 0.5656537      11252.72
  702269.3   0.07484868      672431.5      732107.2 1.3620708      41898.61

Calcular o número de adultos que têm demanda habitacional por grupo etário e RA.

demanda_idade_RA <- amostra_mor %>%
  srvyr::filter(demanda > 0 & !(E04 %in% c(1:3))) %>%
  srvyr::mutate(demanda_ind = ifelse(idade %in% c(24:64) &
                                       conj_casal == 0, 1, 0)) %>%
  srvyr::mutate(
    grupo_etario = case_when(
      idade %in% c(24:29) ~ "idade_24_29",
      idade %in% c(30:39) ~ "idade_30_39",
      idade %in% c(40:64) ~ "idade_40_64"
    )
  ) %>%
  srvyr::group_by(grupo_etario, RA_nome,grupo_pdadA) %>%
  srvyr::summarise(demanda_ = survey_total(demanda_ind, vartype = c("cv", "ci"), na.rm =
                                             TRUE))

  # Teste para ver se é possível fazer inferência sobre os dados.
demanda_idade_RA <- as.data.frame(demanda_idade_RA)

demanda_idade_RA$demanda_ <-
  ifelse(demanda_idade_RA$demanda__cv > 0.25,
         NA,
         demanda_idade_RA$demanda_)

demanda_idade_RA <- subset(demanda_idade_RA,!is.na(grupo_etario))

demanda_idade_RA_final  <-
  merge(demanda_idade_RA,
        tx_chefia_idade_raf,
        by = c("grupo_etario", "RA_nome","grupo_pdadA"))

demanda_idade_RA_final$demanda_final <-
  demanda_idade_RA_final$demanda_ * demanda_idade_RA_final$tx_chefia

Tabela final

demanda_idade_RA_final%>%   janitor::adorn_totals()  %>% arrange(grupo_pdadA) %>% select(-contains("cv"),-contains("low"),-contains("upp"))
 grupo_etario                     RA_nome grupo_pdadA    demanda_  total_chefes    pop_total  tx_chefia demanda_final
        Total                           -           - 350286.0980 1157056.52474 2440759.2488 61.4772799  132079.86001
  idade_24_29                 Água Quente          DF    493.5458     439.05312    1160.5154  0.3783260     186.72119
  idade_24_29                Águas Claras          DF   3382.5608    5039.92020   11405.7130  0.4418768    1494.67520
  idade_24_29                   Arapoanga          DF   2458.2894    1451.31004    5494.2105  0.2641526     649.36355
  idade_24_29                  Arniqueira          DF   1985.9388    1291.59800    4416.8004  0.2924284     580.74496
  idade_24_29                  Brazlândia          DF   1897.0864    1082.90761    3998.1138  0.2708546     513.83461
  idade_24_29              Candangolândia          DF    510.4859     567.98767    1461.8530  0.3885395     198.34395
  idade_24_29                   Ceilândia          DF  10078.9992    9781.78332   27807.0389  0.3517736    3545.52626
  idade_24_29                    Cruzeiro          DF    980.4008     680.08664    2378.6321  0.2859150     280.31132
  idade_24_29                      Fercal          DF    244.9685     310.67548     820.8257  0.3784914      92.71846
  idade_24_29                        Gama          DF   4874.9701    2453.03528   11783.5485  0.2081746    1014.84487
  idade_24_29                       Guará          DF   3634.0539    3790.68294   11631.9459  0.3258855    1184.28560
  idade_24_29                      Itapoã          DF   2585.5233    2717.28402    7197.1618  0.3775494     976.16274
  idade_24_29             Jardim Botânico          DF   3147.8164     813.63019    4946.7141         NA            NA
  idade_24_29                  Lago Norte          DF   1402.6112    1166.78564    3366.4709  0.3465901     486.13122
  idade_24_29                    Lago Sul          DF   1002.7672      52.53336    1672.9974         NA            NA
  idade_24_29          Núcleo Bandeirante          DF    862.7962     773.62539    2359.9654  0.3278122     282.83511
  idade_24_29                     Paranoá          DF   2560.4486    1509.23339    5249.0636  0.2875243     736.19121
  idade_24_29                    Park Way          DF   1065.8514     191.38948    1561.0942         NA            NA
  idade_24_29                  Planaltina          DF   5676.5972    2410.41232   12362.8126  0.1949728    1106.78211
  idade_24_29                Plano Piloto          DF   6381.3830    4337.93174   15357.8123  0.2824577    1802.47052
  idade_24_29            Recanto Das Emas          DF   5687.9851    2619.77745   11748.1073  0.2229957    1268.39624
  idade_24_29             Riacho Fundo II          DF   3528.7965    1607.77931    7013.8135  0.2292304     808.90746
  idade_24_29                Riacho Fundo          DF   2026.8811    1541.21740    4750.6859  0.3244200     657.56072
  idade_24_29                   Samambaia          DF  11308.9122    5325.55318   23915.7269  0.2226800    2518.26815
  idade_24_29                 Santa Maria          DF   6896.2149    3442.12225   13001.9344  0.2647392    1825.69871
  idade_24_29               São Sebastião          DF   4950.2658    4153.86578   11528.1824  0.3603227    1783.69313
  idade_24_29                        SCIA          DF   1355.5173    1442.15463    4152.3241  0.3473126     470.78830
  idade_24_29                         SIA          DF          NA     255.12815     875.4585         NA            NA
  idade_24_29               Sobradinho II          DF   3461.7094    2123.40268    7388.7780  0.2873821     994.83338
  idade_24_29                  Sobradinho          DF   3339.1371    1240.56334    6420.8438  0.1932088     645.15058
  idade_24_29   Sol Nascente / Pôr do Sol          DF   4083.7883    3051.05278   10182.9202  0.2996245    1223.60320
  idade_24_29        Sudoeste e Octogonal          DF   1014.3846    1584.15101    3536.3450  0.4479628     454.40657
  idade_24_29                  Taguatinga          DF   8592.0172    3444.65345   18908.1479  0.1821783    1565.27873
  idade_24_29                      Varjão          DF    475.7688     441.47909    1180.5783  0.3739516     177.91448
  idade_24_29               Vicente Pires          DF   3768.0473    1990.82846    8810.5370  0.2259599     851.42775
  idade_30_39                 Água Quente          DF    287.8489     852.08317    1710.7155  0.4980858     143.37348
  idade_30_39                Águas Claras          DF   3219.3115   16319.43673   29930.1499  0.5452508    1755.33200
  idade_30_39                   Arapoanga          DF   1356.5490    3528.20571    7535.2643  0.4682259     635.17135
  idade_30_39                  Arniqueira          DF   1438.7230    3173.50055    7045.0185  0.4504602     648.08748
  idade_30_39                  Brazlândia          DF   1373.0668    2614.33189    6091.5670  0.4291723     589.28226
  idade_30_39              Candangolândia          DF    350.2303    1154.49146    2477.6836  0.4659560     163.19191
  idade_30_39                   Ceilândia          DF   8592.4609   17775.90869   43946.7832  0.4044871    3475.53996
  idade_30_39                    Cruzeiro          DF    722.8424    1865.96733    4547.4298  0.4103345     296.60716
  idade_30_39                      Fercal          DF    166.3365     675.35659    1448.3929  0.4662800      77.55938
  idade_30_39                        Gama          DF   4930.9725    8130.62323   19790.6390  0.4108318    2025.80016
  idade_30_39                       Guará          DF   3885.1506   10616.88551   23330.4840  0.4550649    1767.99584
  idade_30_39                      Itapoã          DF   1320.5350    5846.39083   10521.1860  0.5556779     733.79213
  idade_30_39             Jardim Botânico          DF   1825.8712    4634.24211   11981.3593  0.3867877     706.22447
  idade_30_39                  Lago Norte          DF    955.5726    3314.19509    7052.5447  0.4699290     449.05125
  idade_30_39                    Lago Sul          DF          NA     440.75768    2713.9318         NA            NA
  idade_30_39          Núcleo Bandeirante          DF    812.9707    1492.00794    3919.2713  0.3806850     309.48578
  idade_30_39                     Paranoá          DF   1418.3391    4095.16067    9028.8119  0.4535658     643.31017
  idade_30_39                    Park Way          DF    744.5043     809.45429    2881.3594  0.2809279     209.15205
  idade_30_39                  Planaltina          DF   3523.6693    8128.03097   18988.0691  0.4280599    1508.34152
  idade_30_39                Plano Piloto          DF   4414.6579   16142.52510   36356.6895  0.4440043    1960.12693
  idade_30_39            Recanto Das Emas          DF   3374.9587    7034.01893   16988.1691  0.4140540    1397.41505
  idade_30_39             Riacho Fundo II          DF   2380.0515    4630.46525   11192.6478  0.4137060     984.64152
  idade_30_39                Riacho Fundo          DF   1668.6283    3060.42865    7285.9019  0.4200480     700.90399
  idade_30_39                   Samambaia          DF   7872.0894   18275.39925   41098.9657  0.4446681    3500.46707
  idade_30_39                 Santa Maria          DF   5163.5150    7075.08958   20257.4507  0.3492586    1803.40220
  idade_30_39               São Sebastião          DF   2721.7219    8094.23179   17000.6871  0.4761120    1295.84458
  idade_30_39                        SCIA          DF    795.8081    2945.42932    6250.5333  0.4712285     375.00744
  idade_30_39                         SIA          DF          NA     772.69805    1325.7243  0.5828497            NA
  idade_30_39               Sobradinho II          DF   2583.2088    5111.00206   12382.2876  0.4127672    1066.26385
  idade_30_39                  Sobradinho          DF   2720.8906    3328.74701   10975.8884  0.3032781     825.18663
  idade_30_39   Sol Nascente / Pôr do Sol          DF          NA    7266.47401   16373.0880  0.4438060            NA
  idade_30_39        Sudoeste e Octogonal          DF          NA    5479.26080    9106.5297  0.6016848            NA
  idade_30_39                  Taguatinga          DF   6093.6598   12528.38170   31188.4821  0.4016990    2447.81698
  idade_30_39                      Varjão          DF    267.1354     697.13466    1519.5631  0.4587731     122.55453
  idade_30_39               Vicente Pires          DF   3467.3860    5727.18420   15779.1414  0.3629592    1258.51958
  idade_40_64                 Água Quente          DF    156.2707    1997.89223    3397.9554  0.5879689      91.88234
  idade_40_64                Águas Claras          DF          NA   31801.07677   51187.7192  0.6212638            NA
  idade_40_64                   Arapoanga          DF          NA    8312.76626   14153.6104  0.5873248            NA
  idade_40_64                  Arniqueira          DF    864.7397    8425.26655   15402.2540  0.5470152     473.02575
  idade_40_64                  Brazlândia          DF    810.7226    7260.60628   12952.1389  0.5605720     454.46840
  idade_40_64              Candangolândia          DF    313.9302    2311.32130    4513.8143  0.5120550     160.74952
  idade_40_64                   Ceilândia          DF   8174.8832   47435.07224   90520.7527  0.5240243    4283.83730
  idade_40_64                    Cruzeiro          DF          NA    5547.42715    9475.9988  0.5854187            NA
  idade_40_64                      Fercal          DF          NA    1431.87380    2603.7203  0.5499338            NA
  idade_40_64                        Gama          DF   3207.2421   22553.46989   45866.0216  0.4917250    1577.08113
  idade_40_64                       Guará          DF   2923.8173   21339.60749   43734.4076  0.4879364    1426.63674
  idade_40_64                      Itapoã          DF          NA   11889.77732   18858.6026  0.6304697            NA
  idade_40_64             Jardim Botânico          DF          NA   15346.61455   28716.0378  0.5344266            NA
  idade_40_64                  Lago Norte          DF    782.7023    7934.71342   14942.2750  0.5310245     415.63408
  idade_40_64                    Lago Sul          DF          NA    3790.69660   10086.1129  0.3758333            NA
  idade_40_64          Núcleo Bandeirante          DF    560.5301    3776.12575    7391.5012  0.5108740     286.36027
  idade_40_64                     Paranoá          DF          NA   10563.66758   16231.4632  0.6508143            NA
  idade_40_64                    Park Way          DF          NA    4054.45566    8556.1281  0.4738657            NA
  idade_40_64                  Planaltina          DF   2453.2553   20507.73698   37866.2030  0.5415842    1328.64427
  idade_40_64                Plano Piloto          DF   3267.9941   39670.49269   75874.8222  0.5228413    1708.64239
  idade_40_64            Recanto Das Emas          DF   1713.0998   17281.52394   31419.9558  0.5500174     942.23476
  idade_40_64             Riacho Fundo II          DF          NA   13274.30847   22942.3671  0.5785937            NA
  idade_40_64                Riacho Fundo          DF    987.1921    7319.25454   13023.7505  0.5619928     554.79491
  idade_40_64                   Samambaia          DF   4273.3822   34322.89415   67081.8000  0.5116573    2186.50727
  idade_40_64                 Santa Maria          DF   2824.3309   18932.87967   36843.0685  0.5138790    1451.36437
  idade_40_64               São Sebastião          DF   1794.3684   16560.10724   28457.5264  0.5819236    1044.18540
  idade_40_64                        SCIA          DF    488.8376    5227.29134    9383.8485  0.5570520     272.30797
  idade_40_64                         SIA          DF          NA     864.70360    1535.7138  0.5630630            NA
  idade_40_64               Sobradinho II          DF   1646.6233   13192.20946   26322.7468  0.5011715     825.24060
  idade_40_64                  Sobradinho          DF   1875.0944   11972.24504   24026.0721  0.4983022     934.36371
  idade_40_64   Sol Nascente / Pôr do Sol          DF   1564.7535   19827.52665   32379.9018  0.6123405     958.16198
  idade_40_64        Sudoeste e Octogonal          DF          NA   10909.66153   17768.9377  0.6139738            NA
  idade_40_64                  Taguatinga          DF   5776.0452   34999.05318   67841.6522  0.5158933    2979.82295
  idade_40_64                      Varjão          DF    227.1546    1330.15373    2331.6383  0.5704803     129.58725
  idade_40_64               Vicente Pires          DF   1677.3167   18429.34244   36908.2137  0.4993290     837.53290
  idade_24_29       Águas Lindas de Goiás         PMB  11600.4041    5476.74801   24463.4964  0.2238743    2597.03230
  idade_24_29                    Alexânia         PMB    765.0834     954.74083    2438.7402  0.3914894     299.52202
  idade_24_29            Cidade Ocidental         PMB   4031.8785    3391.35186    9960.6794  0.3404739    1372.74959
  idade_24_29         Cocalzinho de Goiás         PMB          NA     812.05595    1849.3300  0.4391082            NA
  idade_24_29                  Cristalina         PMB   1792.5354    1891.36203    6039.2537  0.3131781     561.38285
  idade_24_29                     Formosa         PMB   4379.6839    3435.81370   11510.7657  0.2984870    1307.27861
  idade_24_29                    Luziânia         PMB   7561.9968    6951.45894   20895.7208  0.3326738    2515.67825
  idade_24_29                   Novo Gama         PMB   4096.6967    3664.49465   11425.6860  0.3207243    1313.91001
  idade_24_29              Padre Bernardo         PMB    917.9369     938.73366    2903.5298  0.3233077     296.77610
  idade_24_29                  Planaltina         PMB   3882.0138    4074.23531   11395.1797  0.3575402    1387.97615
  idade_24_29 Santo Antônio do Descoberto         PMB   1772.3925    3277.19981    7144.0760  0.4587297     813.04909
  idade_24_29         Valparaíso de Goiás         PMB   7421.5455    6807.52490   21288.6948  0.3197718    2373.20121
  idade_30_39       Águas Lindas de Goiás         PMB   6864.2106   17309.62459   39744.9797  0.4355173    2989.48217
  idade_30_39                    Alexânia         PMB    533.1949    1711.36344    3579.6495  0.4780813     254.91048
  idade_30_39            Cidade Ocidental         PMB   2246.0300    7512.80832   16662.7545  0.4508743    1012.67730
  idade_30_39         Cocalzinho de Goiás         PMB          NA    1551.91097    3089.6939  0.5022863            NA
  idade_30_39                  Cristalina         PMB   1911.5657    3991.88081    9563.2316  0.4174197     797.92508
  idade_30_39                     Formosa         PMB   2701.9619    9197.97449   18722.4401  0.4912808    1327.42189
  idade_30_39                    Luziânia         PMB   5276.0253   15347.73217   33598.9986  0.4567914    2410.04275
 [ reached 'max' / getOption("max.print") -- omitted 20 rows ]
demanda_idade_RA_final_TXDF%>% arrange(grupo_pdadA) %>% select(-contains("cv"),-contains("low"),-contains("upp")) %>% 
  write_sheet("https://docs.google.com/spreadsheets/d/1sCJ7p_GitJXDw4PuYNYAB5Yj7eOseCG3fXyCq_WsHis/edit?usp=sharing",
                                     sheet="Demanda_RA_Txchefia_DF")
✔ Writing to Demanda Habitacional.
✔ Writing to sheet Demanda_RA_Txchefia_DF.

Remover tabelas não mais usadas

Comparação grupo etário e rendimento

demanda_ss <- amostra_mor %>% 
  srvyr::filter(demanda>0) %>% 
  srvyr::mutate(demanda_ind=ifelse(idade %in% c(24:64) & conj_casal==0, 1, 0)) %>% 
  srvyr::mutate(grupo_etario = case_when(idade %in% c(24:29) ~ "idade_24_29",
                                         idade %in% c(30:39) ~ "idade_30_39",
                                         idade %in% c(40:64) ~ "idade_40_64"),
                arranjo2 = ifelse(arranjos %in% c(1,3:6),"Uni/Casais",
                                  ifelse(arranjos == 2,"Monoparental Fem",
                                         ifelse(arranjos == 7,"Outro",NA)))) %>%
  srvyr::group_by(grupo_etario, arranjo2,grupo_pdadA) %>% 
  srvyr::summarise(demanda_=survey_total(vartype = c("cv", "ci"), na.rm=TRUE)) %>% 
  dplyr::filter(!is.na(grupo_etario))
Error in `dplyr::filter()`:
ℹ In argument: `demanda > 0`.
Caused by error:
! objeto 'demanda' não encontrado
Run `]8;;x-r-run:rlang::last_trace()rlang::last_trace()]8;;` to see where the error occurred.

salv——-

demanda_ss  %>% filter(grupo_pdadA=="DF") %>% 
  mutate(percentual=demanda_final/sum(demanda_final)) %>% 
  janitor::adorn_totals()%>% arrange(grupo_pdadA) %>%
  write_sheet("https://docs.google.com/spreadsheets/d/1sCJ7p_GitJXDw4PuYNYAB5Yj7eOseCG3fXyCq_WsHis/edit?usp=sharing",
                                     sheet="Demanda_Arranjos")
The googlesheets4 package is requesting access to your Google account.
Enter '1' to start a new auth process or select a pre-authorized account.
1: Send me to the browser for a new auth process.
2: ngthiagogp@gmail.com
1
Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
Authentication complete.
✔ Writing to Demanda Habitacional 2025.
✔ Writing to sheet Demanda_Arranjos.
tb_demanda_geral <- demanda_idade %>% 
  inner_join(tx_chefia) %>% 
  inner_join(pop_total) %>% 
    inner_join(dom_total) %>% 

  select(-contains("cv"), -contains("low"), -contains("upp")) %>% 
  mutate(demanda_final = demanda_*total_chefes/pop_total) 
Joining with `by = join_by(grupo_etario, grupo_pdadA)`
Joining with `by = join_by(grupo_etario, grupo_pdadA)`
Joining with `by = join_by(grupo_etario, grupo_pdadA, pop_total, pop_total_cv,
pop_total_low, pop_total_upp)`
# Tabela de renda domiciliar dos demandantes
tb_renda_demandante <-
  amostra_mor %>%
  srvyr::filter(demanda > 0 & !(E04 %in% c(1:3))) %>%
  srvyr::mutate(demanda_ind = ifelse(idade %in% c(24:64) &
                                       conj_casal == 0, 1, 0)) %>%
  srvyr::mutate(
    grupo_etario = case_when(
      idade %in% c(24:29) ~ "idade_24_29",
      idade %in% c(30:39) ~ "idade_30_39",
      idade %in% c(40:64) ~ "idade_40_64"
    ),
    renda_dom = case_when(
      renda_ind_r <= sm ~ "ate03SM",
      renda_ind_r > 1100 &
        renda_ind_r <= 3300 ~ "3a8SM",
      renda_ind_r > 5500 &
        renda_ind_r <= 13200 ~ "8a12SM",
      renda_ind_r > 13200 ~ "maisde12SM"
    )
  ) %>%
  srvyr::group_by(grupo_etario,grupo_pdadA, renda_dom) %>%
  srvyr::summarise(demanda_ = survey_total(demanda_ind, vartype = c("cv", "ci"), na.rm =
                                             TRUE)) ->t
Error in `mutate()`:
ℹ In argument: `renda_dom = case_when(...)`.
Caused by error in `case_when()`:
! Failed to evaluate the left-hand side of formula 1.
Caused by error:
! objeto 'sm' não encontrado
Run `]8;;x-r-run:rlang::last_trace()rlang::last_trace()]8;;` to see where the error occurred.

renda ———-

tb_renda_demandante
Erro: objeto 'tb_renda_demandante' não encontrado

7.2 Escolaridade

###Por grupo Etário

demanda_idade_strata2 %>% 
  inner_join(tx_chefia) %>% 
  inner_join(pop_total) %>% 
  

  #select(-contains("cv"), -contains("low"), -contains("upp")) %>% 
  select(-contains("cv"),-contains("upp"),-contains("low")) %>% 
  mutate(demanda_final = demanda*total_chefes/pop_total,
         tx_chefia=total_chefes/pop_total) %>% 
  write_sheet("https://docs.google.com/spreadsheets/d/1sCJ7p_GitJXDw4PuYNYAB5Yj7eOseCG3fXyCq_WsHis/edit?usp=sharing",
                                     sheet="Demanda_instrução")
Joining with `by = join_by(grupo_etario, grupo_pdadA)`
Joining with `by = join_by(grupo_etario, grupo_pdadA)`
The googlesheets4 package is requesting access to your Google account.
Enter '1' to start a new auth process or select a pre-authorized account.
1: Send me to the browser for a new auth process.
2: ngthiagogp@gmail.com
1
Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
Authentication complete.
✔ Writing to Demanda Habitacional 2025.
✔ Writing to sheet Demanda_instrução.

7.2 salariominimo

###Por grupo Etário

Renda Domiciliar

demanda_idade_strata3 <- amostra_mor %>%#Filtra apenas observações com demanda positiva
  srvyr::filter(#e07<6,
                demanda > 0 & !(E04 %in% c(1:3)),!grupo_etario=="Outro") %>%#Cria variável binária: adulto entre 24 e 64 anos, que não é cônjuge nem chefe de casal
  srvyr::mutate(demanda_ind = ifelse(idade %in% c(24:64) & conj_casal == 0, 1, 0),
                strata_renda=case_when(renda_domiciliar<salariominimo~"0-1SM",
                                       renda_domiciliar<3*salariominimo~"1-3SM",
                                       renda_domiciliar>3*salariominimo~"5+SM",
                                       #renda_ind<salariominimo~"maior4SM",
                                       #       TRUE~"Não Sabe / Não se Aplica"
                                       )) %>%#Classifica faixas etárias de interesse
  srvyr::group_by(grupo_etario, grupo_pdadA,strata_renda) %>%
  srvyr::summarise(demanda = survey_total(demanda_ind, vartype = c("cv", "ci"), na.rm = TRUE)) %>%
  as.data.frame() %>%  #Converte para data.frame e aplica filtro de precisão
  mutate(demanda=ifelse(demanda_cv>params$cv_max,NA,demanda))
Error in `dplyr::filter()`:
ℹ In argument: `!grupo_etario == "Outro"`.
Caused by error:
! objeto 'grupo_etario' não encontrado
Run `]8;;x-r-run:rlang::last_trace()rlang::last_trace()]8;;` to see where the error occurred.

Intenção de formar novo domicílio particular nos próximos 12 meses

###Por grupo Etário

demanda_strata_mudança %>% filter(grupo_pdadA=="DF") %>% filter(!strata_mudança=="Não Sabe / Não se Aplica") %>% 
  select(grupo_etario,grupo_pdadA,strata_mudança, demanda_ajustada) %>% 
  spread(strata_mudança, demanda_ajustada) %>%  adorn_totals(where = "row") %>%   
  mutate(percentual = (sim/(sim+Não)))  %>% 
    write_sheet("https://docs.google.com/spreadsheets/d/1sCJ7p_GitJXDw4PuYNYAB5Yj7eOseCG3fXyCq_WsHis/edit?usp=sharing",
                                     sheet="Demanda por Intenção de formar novo domicilia")
✔ Writing to Demanda Habitacional 2025.
✔ Writing to sheet Demanda por Intenção de formar novo domicilia.

FIM

```

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyAgICAgPT09PT0gICAgICAgRGVtYW5kYSBoYWJpdGFjaW9uYWwgbm8gRGlzdHJpdG8gRmVkZXJhbCAgICAgID09PT0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KDQogRXNzZXMgY8OzZGlnb3MgZm9yYW0gZWxhYm9yYWRvcyBwZWxhIGVxdWlwZSBkYSBEaXJldG9yaWEgZGUgRXN0dWRvcyBlDQogUG9sw610aWNhcyBBbWJpZW50YWlzIGUgVGVycml0b3JpYWlzIChERVBBVCksDQogc29iIHRyYWJhbGhvcyBkaXJldG9zIGRhIENvb3JkZW5hw6fDo28gZGUgRXN0dWRvcyBUZXJyaXRvcmlhaXMgKENPRVQpLg0KIE8gcmVsYXTDs3JpbyBkYSBwZXNxdWlzYSBlc3TDoSBkaXNwb27DrXZlbCBlbQ0KIGh0dHBzOi8vd3d3LmlwZS5kZi5nb3YuYnIvZGVmaWNpdC1lLWRlbWFuZGEtaGFiaXRhY2lvbmFsLWRvLWRpc3RyaXRvLWZlZGVyYWwtMjAyMS8NCiBBIERFUEFUIMOpIHBhcnRlIGRvIElQRURGIEluc3RpdHV0byBkZSBQZXNxdWlzYSBlIEVzdGF0w61zdGljYSBkbyBEaXN0cml0byBGZWRlcmFsIChJUEVERikNCiBPcyBjw7NkaWdvcyBhIHNlZ3VpciBkaXplbSByZXNwZWl0byBhbyBhanVzdGUgZGEgYmFzZSBkZSBkYWRvcyBkYSBQZXNxdWlzYQ0KIGRlIG1vZG8gYSBwZXJtaXRpciBhIGV4cGFuc8OjbyBlIHJlYWxpemHDp8OjbyBkZSBpbmZlcsOqbmNpYXMuIEjDoSB0YW1iw6ltIGFsZ3VtYXMNCiBkYXMgdGFiZWxhcyB1dGlsaXphZGFzLiBUb2RvcyBvcyBkZW1haXMgYWdydXBhbWVudG9zDQogZSBjw6FsY3Vsb3MgcHJlc2VudGVzIG5vIHJlbGF0w7NyaW8gZm9yYW0gZmVpdG9zIGNvbSBiYXNlIG5hIG1ldG9kb2xvZ2lhLg0KIFBlZGltb3MgYSBnZW50aWxlemEgZGUgcmVwb3J0YXJlbSBidWdzIG91IGVycm9zIG5vcyBjw7NkaWdvcyBhYmFpeG8uDQogRS1tYWlsOiBnYWItZGVwYXRAaXBlLmRmLmdvdi5icg0KIFRvZG9zIG9zIGRhZG9zIGZvcmFtIG9idGlkb3MgYSBwYXJ0aXIgZGEgUGVzcXVpc2EgRGlzdHJpdGFsIHBvcg0KIEFtb3N0cmEgZGUgRG9taWPDrWxpb3MgKFBEQUQpIA0KIE8gZGljaW9uw6FyaW8gZGUgdmFyacOhdmVpcyBlIG91dHJhcyBpbmZvcm1hw6fDtWVzIHNvYnJlIGEgUERBRCAyMDIxDQogcG9kZW0gc2VyIGVuY29udHJhZG9zIG5vIHNpdGUgZG8gSVBFREY6DQogaHR0cHM6Ly93d3cuaXBlLmRmLmdvdi5ici9taWNyb2RhZG9zLXBkYWQtMjAyMS8NCg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojICAgICAgICAgICAgICAgICAgICAgPT09PT0gQ29uZmlndXJhw6fDtWVzIFIgPT09PQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIENyaWFuZG8gdW0gYW1iaWVudGUgdmlydHVhbA0KIFBhcmEgbWFudGVyIGEgbWVtw7NyaWEgZG9zIHBhY290ZXMgdXRpbGl6YWRvcywgZGUgbW9kbyBxdWUgcG9zc2FtIHNlciB0b3RhbG1lbnRlIHJlcHJvZHV6aWRvcywNCiBzdWdlcmUtc2UgdXRpbGl6YXIgbyBwYWNvdGUgW2ByZW52YF0oaHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9yZW52L2FydGljbGVzL3JlbnYuaHRtbCkuIA0KIA0KIFBhcmEgaXNzbywgbyBwYWNvdGUgZGV2ZSBzZXIgaW5zdGFsYWRvIGluaWNpYWxtZW50ZS4gRXN0ZSBwcm9jZWRpbWVudG8gZm9pIGZlaXRvIA0KIGNvbSBvIHJlbnYgMS4wLjIuDQogDQogIyMgQWRvdGFuZG8gYSB2ZXJzw6NvIGNvcnJldGEgZG9zIHBhY290ZXMuDQogDQogSnVudG8gY29tIGVzc2Ugc2NyaXB0LCBlc3TDo28gZGlzcG9uw612ZWlzIG9zIGFycXVpdm9zIGByZW52LmxvY2tgLCBgLlJwcm9maWxlYCwNCiBgcmVudi9zZXR0aW5ncy5qc29uYCBlIGByZW52L2FjdGl2YXRlLlJgLg0KDQogUGFyYSBxdWUgb3MgcGFjb3RlcyBzZWphbSBvcyBtZXNtb3MgdXRpbGl6YWRvcyBuZXN0ZSBwcm9qZXRvLA0KIGFzIGluZm9ybWHDp8O1ZXMgZGFzIHZlcnPDtWVzIGRvcyBwYWNvdGVzIGZpY2Fyw6NvIHJlZ2lzdHJhZGFzIG5vIGFycXVpdm8gYHJlbnYubG9ja2AuDQogQ29tIGVzc2UgYXJxdWl2byBuYSBtZXNtYSBwYXN0YSBkbyBwcm9qZXRvLCBwb2RlLXNlIHJlY3VwZXJhciBhcyB2ZXJzw7VlcyBhZGVxdWFkYXMNCiBlbSBxdWFscXVlciBvdXRyYSBtw6FxdWluYSBjb20gY29uZXjDo28gYW8gcmVwb3NpdMOzcmlvDQogb3Ugw6AgaW50ZXJuZXQgY29tIGEgZnVuw6fDo28gYHJlbnY6OnJlc3RvcmUoKWAuDQoNCg0KDQojIENvbmZpZ3VyYcOnw7VlcyBvcGNpb25haXMNCmBgYHtyfQ0KDQojcm0obGlzdCA9IGxzKGFsbCA9IFRSVUUpKQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpDQpzYWxhcmlvbWluaW1vPC0xMzAyDQoNCmBgYA0KDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgPT09PT0gMC4gQ2FycmVnYXIgcGFjb3RlcyBlIGxlaXR1cmEgZG9zIGRhZG9zID09PT0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KDQojIFBhY290ZXMgbmVjZXNzw6FyaW9zDQpgYGB7cn0NCiMgTyBwYWNvdGUgYHBhY21hbmAsIHBvciBtZWlvIGRlIHN1YSBmdW7Dp8OjbyBwX2xvYWQoKQ0KICAjIMOpIHV0aWxpemFkbyBwYXJhIGluc3RhbGFyIGUgY2FycmVnYXIgb3MgcGFjb3RlcyBuZWNlc3PDoXJpb3MNCiAgIyBQcmltZWlybywgdGVzdGEtc2Ugc2UgbyBwYWNvdGUgZXN0w6EgaW5zdGFsYWRvLiBTZSBuw6NvLCBlc3RhIHNlcsOhIGZlaXRhLg0KaWYoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KDQoNCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSwgICAgIyBNYW5pcHVsYcOnw6NvIGUgdmlzdWFsaXphw6fDo28gZGUgZGFkb3MNCiAgICAgICAgICAgICAgIGRhdGEudGFibGUsICAgIyBMZWl0dXJhIGUgb3BlcmHDp8O1ZXMgZWZpY2llbnRlcyBjb20gZ3JhbmRlcyBiYXNlcw0KICAgICAgICAgICAgICAgamFuaXRvciwgICAgICAjIFBhZHJvbml6YcOnw6NvIGRlIG5vbWVzIGUgbGltcGV6YSBkZSB0YWJlbGFzDQogICAgICAgICAgICAgICBzdHJpbmdyLCAgICAgICMgTWFuaXB1bGHDp8OjbyBkZSBzdHJpbmdzICh0ZXh0bykNCiAgICAgICAgICAgICAgIGx1YnJpZGF0ZSwgICAgIyBNYW5pcHVsYcOnw6NvIGRlIGRhdGFzDQogICAgICAgICAgICAgICBzdXJ2ZXksICAgICAgICMgRGVzZW5obyBlIGFuw6FsaXNlIGRlIGRhZG9zIGFtb3N0cmFpcyBjb21wbGV4b3MNCiAgICAgICAgICAgICAgIHNydnlyLCAgICAgICAgIyBJbnRlcmZhY2UgdGlkeSBwYXJhIG8gcGFjb3RlIHN1cnZleQ0KICAgICAgICAgICAgICAgZ3QsICAgICAgICAgICAjIEdlcmHDp8OjbyBkZSB0YWJlbGFzIGZvcm1hdGFkYXMNCiAgICAgICAgICAgICAgIHNjYWxlcywgICAgICAgIyBFc2NhbGFzIG51bcOpcmljYXMgZSByb3R1bGFnZW0gcGFyYSBncsOhZmljb3MNCiAgICAgICAgICAgICAgIHJlYWRyLCAgICAgICAgIyBMZWl0dXJhIGRlIGFycXVpdm9zIENTVg0KICAgICAgICAgICAgICAgcmVhZHhsLCAgICAgICAjIExlaXR1cmEgZGUgcGxhbmlsaGFzIEV4Y2VsDQogICAgICAgICAgICAgICBnbHVlICAgICAgICAgICMgQ29uc3RydcOnw6NvIGRpbsOibWljYSBkZSB0ZXh0b3MgZSBleHByZXNzw7Vlcw0KKQ0KbGlicmFyeShnb29nbGVkcml2ZSkNCmxpYnJhcnkoZ29vZ2xlc2hlZXRzNCkNCmBgYA0KDQpJbXBvcnRhciBkYWRvczoNCmBgYHtyfQ0KRGljX21vciA8LSByZWFkX2NzdigiRGljX21vci5jc3YiKQ0KI3BkYWQyMDIzIDwtIHJlYWRfY3N2KCJwZGFkMjAyM190cmF0YWRhLmNzdiIpDQpwZGFkMjAyMyA8LSByZWFkX2NzdigicGRhZDIwMjRvdXQuY3N2IikNCg0KRGljX0RvbSA8LSByZWFkX2NzdigiRGljX0RvbS5jc3YiKQ0KDQpgYGANCg0KDQojICAgICAgICAgICAgICAgICA9PT09PSBBanVzdGVzIGluaWNpYWlzID09PT0NCg0KDQogTyBvYmpldGl2byDDqSBjYWxjdWxhciBhIGRlbWFuZGEgaGFiaXRhY2lvbmFsIGNvbSBhIHRheGEgZGUgY2hlZmlhIHRyYWRpY2lvbmFsDQogLSBxdWUgbGV2YSBlbSBjb250YSB0b2RvcyBvcyBjaGVmZXMgZGFxdWVsYSBmYWl4YSBldMOhcmlhLg0KDQoNCmBgYHtyfQ0KIyBGYXplciBhIGp1bsOnw6NvIGRhcyBiYXNlcyBkZSBtb3JhZG9yZXMgZSBkb21pY8OtbGlvcw0KICAjIFRyYXplciBhcyBpbmZvcm1hw6fDtWVzIGRlIHBlc3NvYXMgcGFyYSBkb21pY8OtbGlvcw0KDQojcm0ocGRhZF9kb21fMjAyMSwgcGRhZF9tb3JfMjAyMSkNCmBgYA0KDQoNCg0KDQoNCiNhanVzdGVzDQpgYGB7cn0NCnBkYWQyMDIzJFVGW3BkYWQyMDIzJEEwMXVmPT01Ml08LSJQTUIiDQpwZGFkMjAyMyRVRltwZGFkMjAyMyRBMDF1Zj09NTNdPC0iREYiDQpwZGFkMjAyMyRVRiB8PiB0YWJsZSgpDQpgYGANCg0KYGBge3J9DQoNCkRpY19Eb20gfD4gZmlsdGVyKHN0cl9kZXRlY3QoY29sdW5hLCJsb2NhIikpDQpwZGFkMjAyMyB8PiANCiAgICBsZWZ0X2pvaW4oRGljX0RvbSB8PiBmaWx0ZXIoY29sdW5hPT0ibG9jYWxpZGFkZSIpIHw+IG11dGF0ZShzdHJhdGFfbG9jYWxpZGFkZT1kZXNjX3ZhbG9yKSB8PiBzZWxlY3QoLWNvbHVuYSwtZGVzY19jb2x1bmEsLWRlc2NfdmFsb3IpLGJ5PWMoImxvY2FsaWRhZGUiPSJ2YWxvciIpKS0+cGRhZDIwMjMNCmBgYA0KDQoNCmBgYHtyfQ0KDQpwZGFkMjAyMyRpZGFkZTwtcGRhZDIwMjMkaWRhZGVfY2FsY3VsYWRhDQpwZGFkMjAyMyRBMDFuZmljaGE8LXBkYWQyMDIzJGZpY2hhDQpwZGFkMjAyMyRSQV9ub21lPC1wZGFkMjAyMyRzdHJhdGFfbG9jYWxpZGFkZQ0KcGRhZDIwMjM8LXBkYWQyMDIzICU+JSBtdXRhdGUoZ3J1cG9fcGRhZEE9Y2FzZV93aGVuKFJBX25vbWU9PSLDgXJlYSBSdXJhbCJ+IsOBcmVhIFJ1cmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVGPT0iREYifiJERiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFflVGKSkjICU+JSBzZWxlY3QoZ3J1cG9fcGRhZEEpICU+JSB0YWJsZSgpDQoNCg0KI3BkYWQyMDIzJEEwMW5wZXNzb2FzDQojcGRhZDIwMjMgJT4lIHNlbGVjdChmaWNoYSxtb3JhZG9yX2lkKSAlPiUgDQojICBtdXRhdGUobl9tb3JhZG9yPWFzLm51bWVyaWMoc3RyX3JlbW92ZShtb3JhZG9yX2lkLHBhc3RlMChmaWNoYSwiLSIpKSkpICU+JSANCiMgIGdyb3VwX2J5KGZpY2hhKSAlPiVzdW1tYXJpc2UoQTAxbnBlc3NvYXM9bWF4KG5fbW9yYWRvcikpICU+JSANCiMgIHJpZ2h0X2pvaW4ocGRhZDIwMjMsYnk9YygiZmljaGEiKSApLT5wZGFkMjAyMw0KDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmBgYA0KIA0KYGBge3J9DQojIERlaXhhciBhcGVuYXMgb3MgZG9taWPDrWxpb3MvbW9yYWRvcmVzIG9uZGUgbyByZXNwb25zw6F2ZWwgdGVtIGVudHJlIDI0IGUgNjQgYW5vcy4NCnBkYWQyMDIzX29yaWdpbmFsIDwtIHBkYWQyMDIzDQoNCnBkYWQyMDIzIDwtDQogIHN1YnNldChwZGFkMjAyMywNCiAgICAgICAgIGZpY2hhICVpbiUgc3Vic2V0KHBkYWQyMDIzLCBFMDQgPT0gMSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZV9jYWxjdWxhZGEgJWluJSBjKDI0OjY0KSkkZmljaGEpDQoNCiNwZGFkMjAyMyAlPiUgDQpgYGANCkFnb3JhLCBkZXZlLXNlIGlkZW50aWZpY2FyIG9zIGRvbWljw61saW9zIHF1ZSB0w6ptIGRlbWFuZGEgaGFiaXRhY2lvbmFsLCBlIHRyYWJhbGhhciBhcGVuYXMgY29tIGVzdGVzLg0KDQogICMgQ3JpYcOnw6NvIGRhcyBjbGFzc2lmaWNhw6fDtWVzIGRlIGZhbcOtbGlhcw0KDQpgYGB7cn0NCm1hdHJpel9mYW1pbGlhciA8LSBwZGFkMjAyMyAlPiUgDQogICMgc2VsZWN0KEEwMW5maWNoYSwgQTAxbnBlc3NvYXMsIEUwNCwgaWRhZGUpICU+JSANCiAgbXV0YXRlKGNvbmRpY2FvID0gMSwgDQogICAgICAgICBFMDRfZWRpdCA9IGNhc2Vfd2hlbihFMDQgPT0gMSB+ICdyZXNwb25zYXZlbCcsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRTA0ID09IDIgfiAnY29uanVnZScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRTA0ID09IDMgfiAnY29uanVnZScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRTA0ID09IDQgJiBpZGFkZSA8IDI0IH4gJ2ZpbGhvX21lbm9yMjQnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEUwNCA9PSA1ICYgaWRhZGUgPCAyNCB+ICdmaWxob19tZW5vcjI0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEUwNCA9PSA2ICYgaWRhZGUgPCAyNCB+ICdmaWxob19tZW5vcjI0JyAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRTA0ID09IDQgJiBpZGFkZSA+PTI0IH4gJ2ZpbGhvX21haW9yMjQnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEUwNCA9PSA1ICYgaWRhZGUgPj0yNCB+ICdmaWxob19tYWlvcjI0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEUwNCA9PSA2ICYgaWRhZGUgPj0yNCB+ICdmaWxob19tYWlvcjI0JywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFMDQgPT0gNyB+ICdnZW5yb19ub3JhJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFMDQgPT0gOCB+ICdwYWlzJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFMDQgPT0gOSB+ICdzb2dyb3MnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEUwNCA9PSAxMCB+ICduZXRvJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFMDQgPT0gMTEgfiAnYmlzbmV0bycsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRTA0ID09IDEyIH4gJ2lybWFvJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFMDQgPT0gMTMgfiAnYXZvcycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFMDQgPT0gMTQgfiAnb3V0cm9fcGFyZW50ZScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRTA0ID09IDE1IH4gJ2FncmVnYWRvJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEUwNCA9PSAxNiB+ICdjb252aXZlbnRlJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFMDQgPT0gMTcgfiAncGVuc2lvbmlzdGEnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRTA0ID09IDE4IH4gJ2VtcHJlZ2Fkb19kb21lc3RpY28nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEUwNCA9PSAxOSB+ICdwYXJlbnRlX2VtcHJlZ2FkbycpKSAlPiUgDQogIGdyb3VwX2J5KEEwMW5maWNoYSwgQTAxbnBlc3NvYXMsDQogICAgICAgICAgIEUwNF9lZGl0KSAlPiUgDQogIHN1bW1hcmlzZShuID0gc3VtKGNvbmRpY2FvKSkgJT4lICANCiAgc3ByZWFkKEUwNF9lZGl0LCBuKQ0KDQpgYGANCg0KDQojIENyaWFyIHZhcmnDoXZlbCBpbmRpY2Fkb3JhIGRlIGlkb3NvIG5vIGRvbWljw61saW8NCmBgYHtyfQ0KcGRhZDIwMjMkaWRvc28gPC0gaWZlbHNlKHBkYWQyMDIzJGlkYWRlID49IDY1LCAxLCAwKQ0KDQptYXRyaXpfaWRvc29zIDwtDQogIGFzLmRhdGEuZnJhbWUodGFibGUocGRhZDIwMjMkQTAxbmZpY2hhLCBwZGFkMjAyMyRpZG9zbykpDQoNCnBkYWQyMDIzJGlkb3NvIDwtIE5VTEwNCg0KbWF0cml6X2lkb3NvcyRpZG9zb3MgPC0NCiAgYXMubnVtZXJpYyhsZXZlbHMobWF0cml6X2lkb3NvcyRWYXIyKSlbbWF0cml6X2lkb3NvcyRWYXIyXSAqIG1hdHJpel9pZG9zb3MkRnJlcQ0KDQpuYW1lcyhtYXRyaXpfaWRvc29zKVsxXSA8LSAiQTAxbmZpY2hhIg0KDQptYXRyaXpfaWRvc29zIDwtIHN1YnNldChtYXRyaXpfaWRvc29zLCBpZG9zb3MgPiAwKQ0KDQptYXRyaXpfZmFtaWxpYXIgPC0NCiAgbWVyZ2UobWF0cml6X2ZhbWlsaWFyLA0KICAgICAgICBtYXRyaXpfaWRvc29zLA0KICAgICAgICBieSA9ICJBMDFuZmljaGEiLA0KICAgICAgICBhbGwueCA9IFRSVUUpDQoNCiNybShtYXRyaXpfaWRvc29zKQ0KbWF0cml6X2lkb3Nvcw0KYGBgDQoNCiAgIyBJbmRpY2Fkb3JhIHNlIG8gaWRvc28gw6kgcmVzcG9uc8OhdmVsIG91IGPDtG5qdWdlLg0KDQpgYGB7cn0NCm1hdHJpel9mYW1pbGlhciRpZG9zb19jb25qIDwtDQogIGlmZWxzZSgNCiAgICBtYXRyaXpfZmFtaWxpYXIkQTAxbmZpY2hhICVpbiUgc3Vic2V0KHBkYWQyMDIzLCBFMDQgJWluJSBjKDIsIDMpICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhZGUgPj0gNjUpJEEwMW5maWNoYSwNCiAgICAxLA0KICAgIDANCiAgKQ0KDQpgYGANCg0KICAjIENyaWFyIHZhcmnDoXZlbCBpbmRpY2Fkb3JhIHNlIGFsZ3XDqW0gZW50cmUgMjQgZSA2NCBhbm9zIG1vcmEgbm8gZG9taWPDrWxpbyBlIG7Do28gw6kgcmVzcG9uc8OhdmVsIG91IGPDtG5qdWdlLg0KDQpgYGB7cn0NCnBkYWQyMDIzJGFkdWx0byA8LQ0KICBpZmVsc2UocGRhZDIwMjMkaWRhZGUgPj0gMjQgJiBwZGFkMjAyMyRpZGFkZSA8IDY1LCAxLCAwKQ0KDQptYXRyaXpfYWR1bHRvIDwtDQogIGFzLmRhdGEuZnJhbWUodGFibGUocGRhZDIwMjMkQTAxbmZpY2hhLCBwZGFkMjAyMyRhZHVsdG8pKQ0KDQpwZGFkMjAyMyRhZHVsdG8gPC0gTlVMTA0KDQptYXRyaXpfYWR1bHRvJGFkdWx0byA8LQ0KICBhcy5udW1lcmljKGxldmVscyhtYXRyaXpfYWR1bHRvJFZhcjIpKVttYXRyaXpfYWR1bHRvJFZhcjJdICogbWF0cml6X2FkdWx0byRGcmVxDQoNCm5hbWVzKG1hdHJpel9hZHVsdG8pWzFdIDwtICJBMDFuZmljaGEiDQoNCm1hdHJpel9hZHVsdG8gPC0gc3Vic2V0KG1hdHJpel9hZHVsdG8sIGFkdWx0byA+IDApDQoNCm1hdHJpel9mYW1pbGlhciA8LQ0KICBtZXJnZShtYXRyaXpfZmFtaWxpYXIsDQogICAgICAgIG1hdHJpel9hZHVsdG8sDQogICAgICAgIGJ5ID0gIkEwMW5maWNoYSIsDQogICAgICAgIGFsbC54ID0gVFJVRSkNCg0KI3JtKG1hdHJpel9hZHVsdG8pDQpgYGANCg0KIyBJbmRpY2Fkb3JhIHNlIG8gYWR1bHRvIMOpIHJlc3BvbnPDoXZlbCBvdSBjw7RuanVnZS4NCg0KYGBge3J9DQptYXRyaXpfZmFtaWxpYXIkYWR1bHRvX3Jlc3AgPC0NCiAgaWZlbHNlKA0KICAgIG1hdHJpel9mYW1pbGlhciRBMDFuZmljaGEgJWluJSBzdWJzZXQocGRhZDIwMjMsIEUwNCA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhZGUgPj0gMjQgJiBpZGFkZSA8IDY1KSRBMDFuZmljaGEsDQogICAgMSwNCiAgICAwDQogICkNCm1hdHJpel9mYW1pbGlhciAlPiUgZ3JvdXBfYnkoYWR1bHRvX3Jlc3ApICU+JSBzdW1tYXJpc2Uobj1uKCkpICMjIyB0b2RvcyBvcyBkb21pY2lsaW9zIHRlbSBhZHVsdG9zIGNvbW8gcmVzcG9uc2F2ZWlzIHBlbG8gZG9taWNpbGlvDQptYXRyaXpfZmFtaWxpYXIkYWR1bHRvX2NvbmogPC0NCiAgaWZlbHNlKA0KICAgIG1hdHJpel9mYW1pbGlhciRBMDFuZmljaGEgJWluJSBzdWJzZXQocGRhZDIwMjMsIEUwNCAlaW4lIGMoMiwgMykgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSA+PSAyNCAmIGlkYWRlIDwgNjUpJEEwMW5maWNoYSwNCiAgICAxLA0KICAgIDANCiAgKQ0KDQptYXRyaXpfZmFtaWxpYXIgJT4lIGdyb3VwX2J5KGFkdWx0b19jb25qKSAlPiUgc3VtbWFyaXNlKG49bigpKSAjIyMgdG9kb3Mgb3MgZG9taWNpbGlvcyB0ZW0gYWR1bHRvcyBjb21vIHJlc3BvbnNhdmVpcyBwZWxvIGRvbWljaWxpbw0KDQpgYGANCg0KIyBJbmRpY2HDp8OjbyBkZSBxdWUgbsOjbyBow6EgZGVtYW5kYSBub3MgZG9taWPDrWxpb3Mgb25kZSBtb3JhIHPDsyBvIHJlc3BvbnPDoXZlbCBjb20gbyBjw7RuanVnZSwNCg0KYGBge3J9DQojIGZpbGhvcyBtZW5vcmVzIGRlIDI0IGFub3MgZSBpZG9zb3MuDQptYXRyaXpfZmFtaWxpYXIkZGVtYW5kYSA8LSBOQQ0KbWF0cml6X2ZhbWlsaWFyJGNvDQptYXRyaXpfZmFtaWxpYXIkZGVtYW5kYSA8LQ0KICBpZmVsc2UoKCgNCiAgICByb3dTdW1zKG1hdHJpel9mYW1pbGlhclssIGMoInJlc3BvbnNhdmVsIiwgImNvbmp1Z2UiLCAiZmlsaG9fbWVub3IyNCIsICJpZG9zb3MiKV0sIG5hLnJtID1UUlVFKSANCiAgICAtIChtYXRyaXpfZmFtaWxpYXJbLCBjKCJpZG9zb19jb25qIildKQ0KICApID09IG1hdHJpel9mYW1pbGlhciRBMDFucGVzc29hcykgPT0gVFJVRSwNCiAgMCwNCiAgbWF0cml6X2ZhbWlsaWFyJGRlbWFuZGEpDQoNCm1hdHJpel9mYW1pbGlhciRkZW1hbmRhICU+JSB0YWJsZSgpDQoNCiAgIyBOw7ptZXJvIGRlIHBlc3NvYXMgbm8gZG9taWPDrWxpbyBxdWUgZGVtYW5kYW0gaGFiaXRhw6fDo28gLSBpLmUgdGVtIHBlc3NvYXMgZW50cmUgMjQgZSA2NCBhbm9zDQogICMgcXVlIG7Do28gc8OjbyByZXNwb25zw6F2ZWlzIG91IGPDtG5qdWdlcy4NCm1hdHJpel9mYW1pbGlhciRkZW1hbmRhIDwtDQogIGlmZWxzZSgobWF0cml6X2ZhbWlsaWFyJEEwMW5wZXNzb2FzIC0gKA0KICAgIHJvd1N1bXMobWF0cml6X2ZhbWlsaWFyWywgYygicmVzcG9uc2F2ZWwiLCAiY29uanVnZSIsICJmaWxob19tZW5vcjI0IiwgImlkb3NvcyIpXSwgbmEucm0gPQ0KICAgICAgICAgICAgICBUUlVFKSAtIChtYXRyaXpfZmFtaWxpYXJbLCBjKCJpZG9zb19jb25qIildKQ0KICApKSA+IDAsDQogICgNCiAgICBtYXRyaXpfZmFtaWxpYXIkYWR1bHRvIC0gcm93U3VtcyhtYXRyaXpfZmFtaWxpYXJbLCBjKCJhZHVsdG9fcmVzcCIsICJhZHVsdG9fY29uaiIpXSwgbmEucm0gPQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSkNCiAgKSwNCiAgbWF0cml6X2ZhbWlsaWFyJGRlbWFuZGENCiAgKQ0KYGBgDQoNCiMgVHJhbnNmb3JtYW5kbyBhIGRlbWFuZGEgZG9zIGNhc29zIGVtIHF1ZSBvcyBwYWlzLCBhdsOzcyBmaWxob3MvZ2Vucm8vbm9yYSBtb3JhbSBubyBkb21pY8OtbGlvLg0KDQpgYGB7cn0NCiMgQ29uc2lkZXJhciBhIGlkYWRlIGRhIHBlc3NvYSBtYWlzIHZlbGhhIGRvIGNhc2FsLiANCiAgIyBTZSBhIHBlc3NvYSBtYWlzIHZlbGhhIGRvIGNhc2FsIGZvciBpZG9zYSwgbyBjYXNhbCBuw6NvIHRlbSBkZW1hbmRhIHBvciBoYWJpdGHDp8Ojby4NCiAgIyBQcmltZWlybywgY3JpYS1zZSB1bWEgdmFyacOhdmVsIGluZGljYWRvcmEgcGFyYSBvIHRpcG8gZGUgY2FzYWwuDQptYXRyaXpfZmFtaWxpYXIkY2FzYWxfYXZvcyA8LSBpZmVsc2UobWF0cml6X2ZhbWlsaWFyJGF2b3MgPT0gMiwgMSwgTkEpDQoNCm1hdHJpel9mYW1pbGlhciRjYXNhbF9wYWlzIDwtIGlmZWxzZShtYXRyaXpfZmFtaWxpYXIkcGFpcyA9PSAyLCAxLCBOQSkNCg0KbWF0cml6X2ZhbWlsaWFyJGNhc2FsX3NvZ3JvcyA8LQ0KICBpZmVsc2UobWF0cml6X2ZhbWlsaWFyJHNvZ3JvcyA9PSAyLCAxLCBOQSkNCmBgYA0KDQoNCiBBIGluZGljYcOnw6NvIGRhIGV4aXN0w6puY2lhIGRlIGNhc2FsIGRlIGZpbGhvcyDDqSBhIHByw7NwcmlhIHZhcmnDoXZlbCBkZSBkZSBnZW5yby9ub3JhLiANCmBgYHtyfQ0KICAjIEZhei1zZSBwYXJhIGNhZGEgdGlwbyBkZSBjYXNhbCBzZXBhcmFkbyBwb3JxdWUgcG9kZSB0ZXIgbWFpcyBkZSB1bSB0aXBvIGRlIGNhc2FsIHBvciBkb21pY8OtbGlvLg0KDQogICMgU2VwYXJhLXNlIG9zIGluZGl2w61kdW9zIGRlIGNhZGEgY2FzYWwgcGFyYSBjYWxjdWxhciBhIGlkYWRlIG3DoXhpbWEgZGVsZS4NCmlkYWRlX2Nhc2FsX2F2b3MgPC0NCiAgc3Vic2V0KA0KICAgIHBkYWQyMDIzLA0KICAgIEEwMW5maWNoYSAlaW4lIHN1YnNldChtYXRyaXpfZmFtaWxpYXIsIGNhc2FsX2F2b3MgPT0gMSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVtYW5kYSA+IDApJEEwMW5maWNoYQ0KICApICU+JQ0KICBzdWJzZXQoRTA0ID09IDEzKQ0KDQppZGFkZV9jYXNhbF9zb2dyb3MgPC0NCiAgc3Vic2V0KA0KICAgIHBkYWQyMDIzLA0KICAgIEEwMW5maWNoYSAlaW4lIHN1YnNldChtYXRyaXpfZmFtaWxpYXIsIGNhc2FsX3NvZ3JvcyA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZW1hbmRhID4gMCkkQTAxbmZpY2hhDQogICkgJT4lDQogIHN1YnNldChFMDQgPT0gOSkNCg0KaWRhZGVfY2FzYWxfcGFpcyA8LQ0KICBzdWJzZXQoDQogICAgcGRhZDIwMjMsDQogICAgQTAxbmZpY2hhICVpbiUgc3Vic2V0KG1hdHJpel9mYW1pbGlhciwgY2FzYWxfcGFpcyA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZW1hbmRhID4gMCkkQTAxbmZpY2hhDQogICkgJT4lDQogIHN1YnNldChFMDQgPT0gOCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBDYWxjdWxvIGEgaWRhZGUgZG8gY8O0bmp1Z2UgbWFpcyB2ZWxobyBwYXJhIGRldGVybWluYXIgbyBjaGVmZSBkbyBjYXNhbC4NCmlkYWRlX2Nhc2FsX2F2b3MyIDwtIGlkYWRlX2Nhc2FsX2F2b3MgJT4lDQogIGdyb3VwX2J5KEEwMW5maWNoYSkgJT4lDQogIHN1bW1hcmlzZShjaGVmZV9pZGFkZSA9IG1heChpZGFkZSkpDQoNCmlkYWRlX2Nhc2FsX2F2b3MgPC0NCiAgbWVyZ2UoaWRhZGVfY2FzYWxfYXZvcywNCiAgICAgICAgaWRhZGVfY2FzYWxfYXZvczIsDQogICAgICAgIGJ5ID0gIkEwMW5maWNoYSIsDQogICAgICAgIGFsbC54ID0gVFJVRSkNCg0KaWRhZGVfY2FzYWxfYXZvcyA8LSBpZGFkZV9jYXNhbF9hdm9zICU+JQ0KICBncm91cF9ieShBMDFuZmljaGEpICU+JQ0KICBtdXRhdGUoY2hlZmVfaWQgPSBpZmVsc2UoDQogICAgc3VtKGlkYWRlKSAvIDIgPT0gY2hlZmVfaWRhZGUsDQogICAgbWluKG1vcmFkb3JfaWQpLA0KICAgIGlmZWxzZShpZGFkZSA9PSBjaGVmZV9pZGFkZSwgbW9yYWRvcl9pZCwgMCkNCiAgKSkgJT4lDQogIG11dGF0ZShjaGVmZV9jYXNhbCA9IGlmZWxzZShtb3JhZG9yX2lkID09IGNoZWZlX2lkLCAxLCAwKSkgJT4lDQogIG11dGF0ZShjb25qX2Nhc2FsID0gaWZlbHNlKG1vcmFkb3JfaWQgIT0gY2hlZmVfaWQsIDEsIDApKQ0KDQojcm0oaWRhZGVfY2FzYWxfYXZvczIpDQoNCmlkYWRlX2Nhc2FsX3NvZ3JvczIgPC0gaWRhZGVfY2FzYWxfc29ncm9zICU+JSANCiAgZ3JvdXBfYnkoQTAxbmZpY2hhKSAlPiUgDQogIHN1bW1hcmlzZShjaGVmZV9pZGFkZSA9IG1heChpZGFkZSkpDQoNCmlkYWRlX2Nhc2FsX3NvZ3JvcyA8LQ0KICBtZXJnZShpZGFkZV9jYXNhbF9zb2dyb3MsDQogICAgICAgIGlkYWRlX2Nhc2FsX3NvZ3JvczIsDQogICAgICAgIGJ5ID0gIkEwMW5maWNoYSIsDQogICAgICAgIGFsbC54ID0gVFJVRSkNCg0KaWRhZGVfY2FzYWxfc29ncm9zIDwtIGlkYWRlX2Nhc2FsX3NvZ3JvcyAlPiUNCiAgZ3JvdXBfYnkoQTAxbmZpY2hhKSAlPiUNCiAgbXV0YXRlKGNoZWZlX2lkID0gaWZlbHNlKA0KICAgIHN1bShpZGFkZSkgLyAyID09IGNoZWZlX2lkYWRlLA0KICAgIG1pbihtb3JhZG9yX2lkKSwNCiAgICBpZmVsc2UoaWRhZGUgPT0gY2hlZmVfaWRhZGUsIG1vcmFkb3JfaWQsIDApDQogICkpICU+JQ0KICBtdXRhdGUoY2hlZmVfY2FzYWwgPSBpZmVsc2UobW9yYWRvcl9pZCA9PSBjaGVmZV9pZCwgMSwgMCkpICU+JQ0KICBtdXRhdGUoY29ual9jYXNhbCA9IGlmZWxzZShtb3JhZG9yX2lkICE9IGNoZWZlX2lkLCAxLCAwKSkNCg0KI3JtKGlkYWRlX2Nhc2FsX3NvZ3JvczIpDQoNCmlkYWRlX2Nhc2FsX3BhaXMyIDwtIGlkYWRlX2Nhc2FsX3BhaXMgJT4lDQogIGdyb3VwX2J5KEEwMW5maWNoYSkgJT4lDQogIHN1bW1hcmlzZShjaGVmZV9pZGFkZSA9IG1heChpZGFkZSkpDQoNCmlkYWRlX2Nhc2FsX3BhaXMgPC0NCiAgbWVyZ2UoaWRhZGVfY2FzYWxfcGFpcywNCiAgICAgICAgaWRhZGVfY2FzYWxfcGFpczIsDQogICAgICAgIGJ5ID0gIkEwMW5maWNoYSIsDQogICAgICAgIGFsbC54ID0gVFJVRSkNCg0KaWRhZGVfY2FzYWxfcGFpcyA8LSBpZGFkZV9jYXNhbF9wYWlzICU+JQ0KICBncm91cF9ieShBMDFuZmljaGEpICU+JQ0KICBtdXRhdGUoY2hlZmVfaWQgPSBpZmVsc2UoDQogICAgc3VtKGlkYWRlKSAvIDIgPT0gY2hlZmVfaWRhZGUsDQogICAgbWluKG1vcmFkb3JfaWQpLA0KICAgIGlmZWxzZShpZGFkZSA9PSBjaGVmZV9pZGFkZSwgbW9yYWRvcl9pZCwgMCkNCiAgKSkgJT4lDQogIG11dGF0ZShjaGVmZV9jYXNhbCA9IGlmZWxzZShtb3JhZG9yX2lkID09IGNoZWZlX2lkLCAxLCAwKSkgJT4lDQogIG11dGF0ZShjb25qX2Nhc2FsID0gaWZlbHNlKG1vcmFkb3JfaWQgIT0gY2hlZmVfaWQsIDEsIDApKQ0KDQojcm0oaWRhZGVfY2FzYWxfcGFpczIpDQpgYGANCg0KDQpgYGB7cn0NCiMgSWRlbnRpZmljYcOnw6NvIGRvcyBjYXNvcyBkZSBnZW5yby9ub3JhIGUgZmlsaG9zLg0KaWRhZGVfY2FzYWxfZmlsaG9zMDEgPC0NCiAgc3Vic2V0KA0KICAgIHBkYWQyMDIzLA0KICAgIEEwMW5maWNoYSAlaW4lIHN1YnNldChtYXRyaXpfZmFtaWxpYXIsIGdlbnJvX25vcmEgPT0gMSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsaG9fbWFpb3IyNCA9PSAxLCBkZW1hbmRhID4gMCkkQTAxbmZpY2hhDQogICkgJT4lDQogIHN1YnNldChFMDQgPT0gNyB8IChFMDQgJWluJSBjKDQ6NikgJiBpZGFkZSA+PSAyNCkpDQoNCmlkYWRlX2Nhc2FsX2ZpbGhvczAxYiA8LSBpZGFkZV9jYXNhbF9maWxob3MwMSAlPiUgDQogIGdyb3VwX2J5KEEwMW5maWNoYSkgJT4lIA0KICBzdW1tYXJpc2UoY2hlZmVfaWRhZGUgPSBtYXgoaWRhZGUpKQ0KDQppZGFkZV9jYXNhbF9maWxob3MwMSA8LQ0KICBtZXJnZShpZGFkZV9jYXNhbF9maWxob3MwMSwNCiAgICAgICAgaWRhZGVfY2FzYWxfZmlsaG9zMDFiLA0KICAgICAgICBieSA9ICJBMDFuZmljaGEiLA0KICAgICAgICBhbGwueCA9IFRSVUUpDQoNCmlkYWRlX2Nhc2FsX2ZpbGhvczAxIDwtIGlkYWRlX2Nhc2FsX2ZpbGhvczAxICU+JQ0KICBncm91cF9ieShBMDFuZmljaGEpICU+JQ0KICBtdXRhdGUoY2hlZmVfaWQgPSBpZmVsc2UoDQogICAgc3VtKGlkYWRlKSAvIDIgPT0gY2hlZmVfaWRhZGUsDQogICAgbWluKG1vcmFkb3JfaWQpLA0KICAgIGlmZWxzZShpZGFkZSA9PSBjaGVmZV9pZGFkZSwgbW9yYWRvcl9pZCwgMCkNCiAgKSkgJT4lDQogIG11dGF0ZShjaGVmZV9jYXNhbCA9IGlmZWxzZShtb3JhZG9yX2lkID09IGNoZWZlX2lkLCAxLCAwKSkgJT4lDQogIG11dGF0ZShjb25qX2Nhc2FsID0gaWZlbHNlKG1vcmFkb3JfaWQgIT0gY2hlZmVfaWQsIDEsIDApKQ0KDQojcm0oaWRhZGVfY2FzYWxfZmlsaG9zMDFiKQ0KDQppZGFkZV9jYXNhbF9maWxob3MwMiA8LQ0KICBzdWJzZXQoDQogICAgcGRhZDIwMjMsDQogICAgQTAxbmZpY2hhICVpbiUgc3Vic2V0KG1hdHJpel9mYW1pbGlhciwgZ2Vucm9fbm9yYSA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxob19tYWlvcjI0ID49IDIsIGRlbWFuZGEgPiAwKSRBMDFuZmljaGENCiAgKSAlPiUNCiAgc3Vic2V0KEUwNCA9PSA3IHwgKEUwNCAlaW4lIGMoNDo2KSAmIGlkYWRlID49IDI0KSkNCg0KaWRhZGVfY2FzYWxfZmlsaG9zMDJhZCA8LSBpZGFkZV9jYXNhbF9maWxob3MwMiAlPiUNCiAgZ3JvdXBfYnkoQTAxbmZpY2hhKSAlPiUNCiAgZmlsdGVyKEUwNCAlaW4lIGMoNDo2KSkgJT4lDQogIHN1bW1hcmlzZShpZGFkZV9maWxobyA9IG1heChpZGFkZSkpDQoNCmlkYWRlX2Nhc2FsX2ZpbGhvczAyIDwtDQogIG1lcmdlKGlkYWRlX2Nhc2FsX2ZpbGhvczAyLA0KICAgICAgICBpZGFkZV9jYXNhbF9maWxob3MwMmFkLA0KICAgICAgICBieSA9ICJBMDFuZmljaGEiLA0KICAgICAgICBhbGwueCA9IFRSVUUpICU+JSAgIHN1YnNldChFMDQgPT0gNyB8IGlkYWRlID09IGlkYWRlX2ZpbGhvKSAlPiUNCiAgc3Vic2V0KCEoQTAxbmZpY2hhID09IDU3NjU4ICYgbW9yYWRvcl9pZCA9PSA0KSkgIyBSZXRpcmEtc2UgZXN0ZSBjYXNvIGVzcGVjw61maWNvIGVtIHF1ZSBvcyBkb2lzIGZpbGhvcyBtYWlzIHZlbGhvcyBzw6NvIGfDqm1lb3MuDQoNCiNybShpZGFkZV9jYXNhbF9maWxob3MwMmFkKQ0KDQppZGFkZV9jYXNhbF9maWxob3MwMmIgPC0gaWRhZGVfY2FzYWxfZmlsaG9zMDIgJT4lDQogIGdyb3VwX2J5KEEwMW5maWNoYSkgJT4lDQogIHN1bW1hcmlzZShjaGVmZV9pZGFkZSA9IG1heChpZGFkZSkpDQoNCmlkYWRlX2Nhc2FsX2ZpbGhvczAyIDwtDQogIG1lcmdlKGlkYWRlX2Nhc2FsX2ZpbGhvczAyLA0KICAgICAgICBpZGFkZV9jYXNhbF9maWxob3MwMmIsDQogICAgICAgIGJ5ID0gIkEwMW5maWNoYSIsDQogICAgICAgIGFsbC54ID0gVFJVRSkNCg0KaWRhZGVfY2FzYWxfZmlsaG9zMDIgPC0gaWRhZGVfY2FzYWxfZmlsaG9zMDIgJT4lDQogIGdyb3VwX2J5KEEwMW5maWNoYSkgJT4lDQogIG11dGF0ZShjaGVmZV9pZCA9IGlmZWxzZSgNCiAgICBzdW0oaWRhZGUpIC8gMiA9PSBjaGVmZV9pZGFkZSwNCiAgICBtaW4obW9yYWRvcl9pZCksDQogICAgaWZlbHNlKGlkYWRlID09IGNoZWZlX2lkYWRlLCBtb3JhZG9yX2lkLCAwKQ0KICApKSAlPiUNCiAgbXV0YXRlKGNoZWZlX2Nhc2FsID0gaWZlbHNlKG1vcmFkb3JfaWQgPT0gY2hlZmVfaWQsIDEsIDApKSAlPiUNCiAgbXV0YXRlKGNvbmpfY2FzYWwgPSBpZmVsc2UobW9yYWRvcl9pZCAhPSBjaGVmZV9pZCwgMSwgMCkpDQoNCiNybShpZGFkZV9jYXNhbF9maWxob3MwMmIpDQpgYGANCg0KDQpgYGB7cn0NCiMgTyBnZW5yby9ub3JhIHZhaSBzZXIgbyBjaGVmZSBuZXN0ZSBjYXNvLiBJbXB1dGFtLXNlIG9zIGZpbGhvcyBtYWlzIHZlbGhvcyBjb21vIGPDtG5qdWdlLg0KaWRhZGVfY2FzYWxfZmlsaG9zMDNnZW5ybyA8LQ0KICBzdWJzZXQoDQogICAgcGRhZDIwMjMsDQogICAgQTAxbmZpY2hhICVpbiUgc3Vic2V0KG1hdHJpel9mYW1pbGlhciwgZ2Vucm9fbm9yYSA9PSAyICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZW1hbmRhID4gMCkkQTAxbmZpY2hhDQogICkgJT4lDQogIHN1YnNldChFMDQgPT0gNykNCg0KICAjIFRlbSBhbGd1bnMgY2Fzb3MgcXVlIHRlbSBkb2lzIGdlbnJvcy9ub3JhcywgZSBuw6NvIHRlbSBmaWxob3MgY29tIG1haXMgZGUgMjQgYW5vcywgYXBlbmFzIGZpbGhvcyBtZW5vcmVzLg0KaWRhZGVfY2FzYWxfZmlsaG9zMDNmaWxobyA8LQ0KICBzdWJzZXQoDQogICAgcGRhZDIwMjMsDQogICAgQTAxbmZpY2hhICVpbiUgc3Vic2V0KG1hdHJpel9mYW1pbGlhciwgZ2Vucm9fbm9yYSA9PSAyICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZW1hbmRhID4gMCkkQTAxbmZpY2hhDQogICkgJT4lDQogIHN1YnNldChFMDQgJWluJSBjKDQ6NikpICU+JQ0KICBhcnJhbmdlKGRlc2MoaWRhZGUpKSAlPiUNCiAgZ3JvdXBfYnkoQTAxbmZpY2hhKSAlPiUNCiAgc2xpY2UoMToyKQ0KDQogICMgSnVudG8gb3MgZGFkb3MgZG9zIGdlbnJvcyBlIGZpbGhvcy4NCmlkYWRlX2Nhc2FsX2ZpbGhvczAzIDwtDQogIHJiaW5kKGlkYWRlX2Nhc2FsX2ZpbGhvczAzZ2Vucm8sIGlkYWRlX2Nhc2FsX2ZpbGhvczAzZmlsaG8pDQoNCmlkYWRlX2Nhc2FsX2ZpbGhvczAzIDwtIGlkYWRlX2Nhc2FsX2ZpbGhvczAzICU+JQ0KICBncm91cF9ieShBMDFuZmljaGEpICU+JQ0KICBtdXRhdGUoY2hlZmVfY2FzYWwgPSBpZmVsc2UoRTA0ID09IDcsIDEsIDApKSAlPiUNCiAgbXV0YXRlKGNvbmpfY2FzYWwgPSBpZmVsc2UoRTA0ICE9IDcsIDEsIDApKSAlPiUNCiAgbXV0YXRlKGNoZWZlX2lkID0gaWZlbHNlKGNoZWZlX2Nhc2FsID09IDEsIG1vcmFkb3JfaWQsIDApKQ0KDQojcm0oaWRhZGVfY2FzYWxfZmlsaG9zMDNnZW5ybywgaWRhZGVfY2FzYWxfZmlsaG9zMDNmaWxobykNCmBgYA0KDQoNCmBgYHtyfQ0KIyBKdW7Dp8OjbyBkZSB0b2RvcyBvcyBjYXNvcyBkZSBjYXNhaXMNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmNhc2FpcyA8LQ0KICBiaW5kX3Jvd3MoDQogICAgI2xpc3QoDQogICAgICBpZGFkZV9jYXNhbF9hdm9zLA0KICAgICAgaWRhZGVfY2FzYWxfcGFpcywNCiAgICAgIGlkYWRlX2Nhc2FsX3NvZ3JvcywNCiAgICAgIGlkYWRlX2Nhc2FsX2ZpbGhvczAxLA0KICAgICAgaWRhZGVfY2FzYWxfZmlsaG9zMDIsDQogICAgICBpZGFkZV9jYXNhbF9maWxob3MwMw0KICAgICkNCg0KICAjIEFwZXNhciBkZSBvIG9iamV0byBzZXIgImNhc2FpcyIsIG8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIMOpIMOtbXBhciBwb3JxdWUgdMOqbSBjYXNhaXMgcXVlIHPDsyB0ZW0gbyBnZW5yby4NCmNhc2FpcyA8LQ0KICBjYXNhaXNbLCBjKCJBMDFuZmljaGEiLA0KICAgICAgICAgICAgICJtb3JhZG9yX2lkIiwNCiAgICAgICAgICAgICAiY2hlZmVfY2FzYWwiLA0KICAgICAgICAgICAgICJjb25qX2Nhc2FsIiwNCiAgICAgICAgICAgICAiY2hlZmVfaWQiKV0NCg0KY2FzYWlzIDwtIGFzLmRhdGEuZnJhbWUoY2FzYWlzKQ0KYGBgDQoNCg0KYGBge3J9DQojIEFkacOnw6NvIGRhIGluZm9ybWHDp8OjbyBzb2JyZSBjYXNhaXMgbmEgUERBRC4NCnBkYWQyMDIzX29yaWdpbmFsIDwtDQogIG1lcmdlKA0KICAgIHBkYWQyMDIzX29yaWdpbmFsLA0KICAgIGNhc2FpcywNCiAgICBhbGwueCA9IFRSVUUsDQogICAgYnkgPSBjKCJtb3JhZG9yX2lkIiwiQTAxbmZpY2hhIikNCiAgKQ0KDQpwZGFkMjAyM19vcmlnaW5hbCRjb25qX2Nhc2FsIDwtDQogIGlmZWxzZShpcy5uYShwZGFkMjAyM19vcmlnaW5hbCRjb25qX2Nhc2FsKSA9PSBUUlVFLA0KICAgICAgICAgMCwNCiAgICAgICAgIHBkYWQyMDIzX29yaWdpbmFsJGNvbmpfY2FzYWwpDQoNCiNwZGFkMjAyM19vcmlnaW5hbCRjb25qX2Nhc2FsICU+JSB0YWJsZSgpDQogICMgSnVudGFuZG8gYXMgaW5mb3JtYcOnw7VlcyBkZSBkZW1hbmRhIGhhYml0YWNpb25hbCBjb20gYSBQREFELg0KcGRhZDIwMjNfb3JpZ2luYWwgPC0NCiAgbWVyZ2UocGRhZDIwMjNfb3JpZ2luYWwsDQogICAgICAgIG1hdHJpel9mYW1pbGlhclssIGMoIkEwMW5maWNoYSIsICJkZW1hbmRhIildLA0KICAgICAgICBieSA9ICJBMDFuZmljaGEiLA0KICAgICAgICBhbGwueCA9IFRSVUUpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBDb250YWJpbGl6YW5kbyBhIHJlbmRhIGRvIHJlc3BvbnPDoXZlbCBwZWxvIGRvbWljw61saW8uDQpwZGFkX3JlbmRhIDwtIHBkYWQyMDIzX29yaWdpbmFsICU+JQ0KICBmaWx0ZXIoRTA0ID09IDEpICU+JQ0KICBtdXRhdGUoDQogICAgcmVuZGFfcmVzcCA9IGNhc2Vfd2hlbigNCiAgICAgIHJlbmRhX2luZF9yIDw9IDExMDAgfiAiYXRlMDFTTSIsDQogICAgICByZW5kYV9pbmRfciA+IDExMDAgJg0KICAgICAgICByZW5kYV9pbmRfciA8PSAzMzAwIH4gIjFhM1NNIiwNCiAgICAgIHJlbmRhX2luZF9yID4gMzMwMCAmDQogICAgICAgIHJlbmRhX2luZF9yIDw9IDU1MDAgfiAiM2E1U00iLA0KICAgICAgcmVuZGFfaW5kX3IgPiA1NTAwICYNCiAgICAgICAgcmVuZGFfaW5kX3IgPD0gMTMyMDAgfiAiNWExMlNNIiwNCiAgICAgIHJlbmRhX2luZF9yID4gMTMyMDAgfiAibWFpc2RlMTJTTSINCiAgICApDQogICkgJT4lDQogIHNlbGVjdChBMDFuZmljaGEsIHJlbmRhX3Jlc3ApDQpgYGANCg0KDQpgYGB7cn0NCiMgSnVuw6fDo28gZG9zIGRhZG9zIGRlIHJlbmRhIGRvcyByZXNwb25zw6F2ZWwgY29tIGFzIGRlbWFpcyBpbmZvcm1hw6fDtWVzIGRhIFBEQUQuDQpwZGFkMjAyM19vcmlnaW5hbCA8LQ0KICBtZXJnZShwZGFkMjAyM19vcmlnaW5hbCwNCiAgICAgICAgcGRhZF9yZW5kYSwNCiAgICAgICAgYnkgPSAiQTAxbmZpY2hhIiwNCiAgICAgICAgYWxsLnggPSBUUlVFKQ0KDQojcm0ocGRhZF9yZW5kYSwgaWRhZGVfY2FzYWxfYXZvcywgaWRhZGVfY2FzYWxfZmlsaG9zMDEsDQojICAgaWRhZGVfY2FzYWxfZmlsaG9zMDIsIGlkYWRlX2Nhc2FsX2ZpbGhvczAzLCBpZGFkZV9jYXNhbF9wYWlzLA0KIyAgIGlkYWRlX2Nhc2FsX3NvZ3JvcywgbWF0cml6X2ZhbWlsaWFyLCBjYXNhaXMpDQpgYGANCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyAgICAgICAgICAgICAgICAgICAgICAgICBFeHBhbnPDo28gZGEgYW1vc3RyYSANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpgYGB7cn0NCnBkYWQyMDIzX29yaWdpbmFsJGRlbWFuZGENCmBgYA0KDQoNCiAgIyBEZWNsYXJhciBvIGRlc2VuaG8gaW5jaWFsDQpgYGB7cn0NCmFtb3N0cmFfbW9yIDwtIA0KICBzdXJ2ZXk6OnN2eWRlc2lnbihpZCA9IH5maWNoYSwNCiAgICAgICAgICAgICAgICAgICAgc3RyYXRhID0gfnNldG9yX2Rpc3RyaXRvLA0KICAgICAgICAgICAgICAgICAgICB3ZWlnaHRzID0gfnBlc29fbW9yLA0KICAgICAgICAgICAgICAgICAgICBuZXN0PVRSVUUsDQogICAgICAgICAgICAgICAgICAgIGRhdGE9cGRhZDIwMjNfb3JpZ2luYWwpIA0KDQphbW9zdHJhX21vciA8LSBzcnZ5cjo6YXNfc3VydmV5KGFtb3N0cmFfbW9yKQ0KDQogICMgRXhjbHVpIGFycXVpdm9zIG7Do28gbWFpcyB1c2Fkb3MNCiNybShhbW9zdHJhLCBzYW1wbGVfcGRhZCwgcG9zdF9wb3AsIHBkYWQyMDIzX29yaWdpbmFsKQ0KDQoNCmBgYA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgICAgICAgICAgICAgICAgICAgICAgICAgUmVzdWx0YWRvcyBlIGluZmVyw6puY2lhcw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyBDYWxjdWxhbmRvIGEgdGF4YSBkZSBjaGVmaWEgcG9yIGdydXBvIGV0w6FyaW8uDQoNCmBgYHtyfQ0KdHhfY2hlZmlhIDwtIGFtb3N0cmFfbW9yICU+JSANCiAgc3J2eXI6Om11dGF0ZShncnVwb19ldGFyaW8gPSBjYXNlX3doZW4oaWRhZGUgJWluJSBjKDI0OjI5KSB+ICJpZGFkZV8yNF8yOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoNDA6NjQpIH4gImlkYWRlXzQwXzY0IikpICU+JSANCiAgc3J2eXI6OmZpbHRlcihFMDQ9PTEpICU+JSANCiAgc3J2eXI6Omdyb3VwX2J5KGdydXBvX2V0YXJpbyxncnVwb19wZGFkQSkgJT4lIA0KICBzcnZ5cjo6c3VtbWFyaXNlKHRvdGFsX2NoZWZlcz1zdXJ2ZXlfdG90YWwodmFydHlwZSA9IGMoImN2IiwgImNpIikpKQ0KDQp0eF9jaGVmaWEgPC0gc3Vic2V0KHR4X2NoZWZpYSwgIWlzLm5hKGdydXBvX2V0YXJpbykpDQp0eF9jaGVmaWENCmBgYA0KDQojIENhbGN1bGFuZG8gbyB0b3RhbCBkZSBwZXNzb2FzIG5hIHBvcHVsYcOnw6NvLg0KDQpgYGB7cn0NCnBvcF90b3RhbCA8LSBhbW9zdHJhX21vciAlPiUNCiAgc3J2eXI6Om11dGF0ZSgNCiAgICBncnVwb19ldGFyaW8gPSBjYXNlX3doZW4oDQogICAgICBpZGFkZSAlaW4lIGMoMjQ6MjkpIH4gImlkYWRlXzI0XzI5IiwNCiAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgaWRhZGUgJWluJSBjKDQwOjY0KSB+ICJpZGFkZV80MF82NCINCiAgICApDQogICkgJT4lDQogIHNydnlyOjpncm91cF9ieShncnVwb19ldGFyaW8sZ3J1cG9fcGRhZEEpICU+JQ0KICBzcnZ5cjo6c3VtbWFyaXNlKHBvcF90b3RhbCA9IHN1cnZleV90b3RhbCh2YXJ0eXBlID0gYygiY3YiLCAiY2kiKSkpDQoNCnBvcF90b3RhbCA8LSBzdWJzZXQocG9wX3RvdGFsLCFpcy5uYShncnVwb19ldGFyaW8pKQ0KcG9wX3RvdGFsDQpgYGANCiAgIyBKdW50YW5kbyBhcyB0YWJlbGFzIHBhcmEgY2FsY3VsYXIgYSB0YXhhIGRlIGNoZWZpYSBwb3IgaWRhZGUuDQoNCg0KYGBge3J9DQp0eF9jaGVmaWFfaWRhZGUgPC0gY2JpbmQodHhfY2hlZmlhLCBwb3BfdG90YWxbLCAtYygxLDIpXSkNCg0KdHhfY2hlZmlhX2lkYWRlJHR4X2NoZWZpYSA8LQ0KICB0eF9jaGVmaWFfaWRhZGUkdG90YWxfY2hlZmVzIC8gdHhfY2hlZmlhX2lkYWRlJHBvcF90b3RhbA0KDQogICMgVGVzdGUgcGFyYSB2ZXIgc2Ugw6kgcG9zc8OtdmVsIGZhemVyIGluZmVyw6puY2lhIHNvYnJlIG9zIGRhZG9zLg0KICAjIE5lY2Vzc8OhcmlvIGNvZWZpY2llbnRlIGRlIHZhcmlhw6fDo28gKGN2KSBtZW5vciBkbyBxdWUgMjUlDQp0eF9jaGVmaWFfaWRhZGUgPC0gYXMuZGF0YS5mcmFtZSh0eF9jaGVmaWFfaWRhZGUpDQoNCnR4X2NoZWZpYV9pZGFkZSR0eF9jaGVmaWEgPC0NCiAgaWZlbHNlKHR4X2NoZWZpYV9pZGFkZSR0b3RhbF9jaGVmZXNfY3YgPiAwLjI1LA0KICAgICAgICAgTkEsDQogICAgICAgICB0eF9jaGVmaWFfaWRhZGUkdHhfY2hlZmlhKQ0KDQojcm0odHhfY2hlZmlhLCBwb3BfdG90YWwpDQpgYGANCg0KIyBDw6FsY3VsbyBhIHRheGEgZGUgY2hlZmlhIHBvciBpZGFkZSBlIFJBLg0KDQpgYGB7cn0NCnR4X2NoZWZpYV9pZGFkZV9yYSA8LSBhbW9zdHJhX21vciAlPiUgDQogIHNydnlyOjptdXRhdGUoZ3J1cG9fZXRhcmlvID0gY2FzZV93aGVuKGlkYWRlICVpbiUgYygyNDoyOSkgfiAiaWRhZGVfMjRfMjkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoMzA6MzkpIH4gImlkYWRlXzMwXzM5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhZGUgJWluJSBjKDQwOjY0KSB+ICJpZGFkZV80MF82NCIpKSAlPiUgDQogIHNydnlyOjpmaWx0ZXIoRTA0PT0xKSAlPiUgDQogIHNydnlyOjpncm91cF9ieShncnVwb19ldGFyaW8sIFJBX25vbWUsZ3J1cG9fcGRhZEEpICU+JSANCiAgc3J2eXI6OnN1bW1hcmlzZSh0b3RhbF9jaGVmZXM9c3VydmV5X3RvdGFsKHZhcnR5cGUgPSBjKCJjdiIsICJjaSIpKSkNCg0KdHhfY2hlZmlhX2lkYWRlX3JhIDwtIHN1YnNldCh0eF9jaGVmaWFfaWRhZGVfcmEsICFpcy5uYShncnVwb19ldGFyaW8pKQ0KDQpwb3BfaWRhZGVfcmEgPC0gYW1vc3RyYV9tb3IgJT4lIA0KICBzcnZ5cjo6bXV0YXRlKGdydXBvX2V0YXJpbyA9IGNhc2Vfd2hlbihpZGFkZSAlaW4lIGMoMjQ6MjkpIH4gImlkYWRlXzI0XzI5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhZGUgJWluJSBjKDMwOjM5KSB+ICJpZGFkZV8zMF8zOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYyg0MDo2NCkgfiAiaWRhZGVfNDBfNjQiKSkgJT4lIA0KICBzcnZ5cjo6Z3JvdXBfYnkoZ3J1cG9fZXRhcmlvLCBSQV9ub21lLGdydXBvX3BkYWRBKSAlPiUgDQogIHNydnlyOjpzdW1tYXJpc2UocG9wX3RvdGFsPXN1cnZleV90b3RhbCh2YXJ0eXBlID0gYygiY3YiLCAiY2kiKSkpDQoNCnBvcF9pZGFkZV9yYSA8LSBzdWJzZXQocG9wX2lkYWRlX3JhLCAhaXMubmEoZ3J1cG9fZXRhcmlvKSkNCg0KdHhfY2hlZmlhX2lkYWRlX3JhZiA8LQ0KICBjYmluZCh0eF9jaGVmaWFfaWRhZGVfcmEsIHBvcF9pZGFkZV9yYVssIC1jKDEsMiwzKV0pDQoNCnR4X2NoZWZpYV9pZGFkZV9yYWYkdHhfY2hlZmlhIDwtDQogIHR4X2NoZWZpYV9pZGFkZV9yYWYkdG90YWxfY2hlZmVzIC8gdHhfY2hlZmlhX2lkYWRlX3JhZiRwb3BfdG90YWwNCg0KdHhfY2hlZmlhX2lkYWRlX3JhZiA8LQ0KICBzdWJzZXQodHhfY2hlZmlhX2lkYWRlX3JhZiwhaXMubmEoZ3J1cG9fZXRhcmlvKSkNCg0KICAjIFRlc3RlIHBhcmEgdmVyIHNlIGluZmVyw6puY2lhcyBwb2RlbSBzZXIgZmVpdGFzIA0KdHhfY2hlZmlhX2lkYWRlX3JhZiA8LSBhcy5kYXRhLmZyYW1lKHR4X2NoZWZpYV9pZGFkZV9yYWYpDQoNCnR4X2NoZWZpYV9pZGFkZV9yYWYkdHhfY2hlZmlhIDwtDQogIGlmZWxzZSh0eF9jaGVmaWFfaWRhZGVfcmFmJHRvdGFsX2NoZWZlc19jdiA+IDAuMjUsDQogICAgICAgICBOQSwNCiAgICAgICAgIHR4X2NoZWZpYV9pZGFkZV9yYWYkdHhfY2hlZmlhKQ0KYGBgDQojIHNhdmUgdHggY2hlZmlhLS0tLS0tLS0tLS0tDQoNCmBgYHtyfQ0KdHhfY2hlZmlhX2lkYWRlX3JhZiAlPiUgc2VsZWN0KC1jb250YWlucygiY3YiKSwtY29udGFpbnMoInVwcCIpLC1jb250YWlucygibG93IikpICU+JSANCiAgd3JpdGVfc2hlZXQoImh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFzQ0o3cF9HaXRKWER3NFB1WU5ZQUI1WWo3ZU9zZUNHM2ZYeUNxX1dzSGlzL2VkaXQ/dXNwPXNoYXJpbmciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoZWV0PSJ0eF9jaGVmaWFfaWRhZGVfcmEiKQ0KICANCg0KYGBgDQoNCiMgQ2FsY3VsYXIgbyBuw7ptZXJvIGRlIGFkdWx0b3MgcXVlIHTDqm0gZGVtYW5kYSBoYWJpdGFjaW9uYWwgcG9yIGdydXBvIGV0w6FyaW8uDQoNCmBgYHtyfQ0KZGVtYW5kYV9pZGFkZSA8LSBhbW9zdHJhX21vciAgJT4lIA0KICAgc3J2eXI6OmZpbHRlcihkZW1hbmRhID4gMCAmICEoRTA0ICVpbiUgYygxOjMpKSkgJT4lDQogICBzcnZ5cjo6bXV0YXRlKGRlbWFuZGFfaW5kID0gaWZlbHNlKGlkYWRlICVpbiUgYygyNDo2NCkgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmpfY2FzYWwgPT0gMCwgMSwgMCkpICU+JQ0KICAgc3J2eXI6Om11dGF0ZSgNCiAgICAgZ3J1cG9fZXRhcmlvID0gY2FzZV93aGVuKA0KICAgICAgIGlkYWRlICVpbiUgYygyNDoyOSkgfiAiaWRhZGVfMjRfMjkiLA0KICAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgIGlkYWRlICVpbiUgYyg0MDo2NCkgfiAiaWRhZGVfNDBfNjQiDQogICAgICkNCiAgICkgJT4lDQogICBzcnZ5cjo6Z3JvdXBfYnkoZ3J1cG9fZXRhcmlvLGdydXBvX3BkYWRBKSAlPiUNCiAgIHNydnlyOjpzdW1tYXJpc2UoZGVtYW5kYV8gPSBzdXJ2ZXlfdG90YWwoZGVtYW5kYV9pbmQsIHZhcnR5cGUgPSBjKCJjdiIsICJjaSIpLCBuYS5ybSA9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSkpDQogDQogDQogICMgVGVzdGUgcGFyYSB2ZXIgc2Ugw6kgcG9zc8OtdmVsIGZhemVyIGluZmVyw6puY2lhIHNvYnJlIG9zIGRhZG9zLg0KIGRlbWFuZGFfaWRhZGUgPC0gYXMuZGF0YS5mcmFtZShkZW1hbmRhX2lkYWRlKQ0KIA0KIGRlbWFuZGFfaWRhZGUkZGVtYW5kYV8gPC0NCiAgIGlmZWxzZShkZW1hbmRhX2lkYWRlJGRlbWFuZGFfX2N2ID4gMC4yNSwgTkEsIGRlbWFuZGFfaWRhZGUkZGVtYW5kYV8pDQogDQogZGVtYW5kYV9pZGFkZSA8LSBzdWJzZXQoZGVtYW5kYV9pZGFkZSwhaXMubmEoZ3J1cG9fZXRhcmlvKSkNCiANCiBkZW1hbmRhX2lkYWRlX2ZpbmFsICA8LQ0KICAgbWVyZ2UoZGVtYW5kYV9pZGFkZSwgdHhfY2hlZmlhX2lkYWRlLCBieSA9IGMoImdydXBvX2V0YXJpbyIsImdydXBvX3BkYWRBIikpDQogDQogZGVtYW5kYV9pZGFkZV9maW5hbCRkZW1hbmRhX2ZpbmFsIDwtDQogICBkZW1hbmRhX2lkYWRlX2ZpbmFsJGRlbWFuZGFfICogZGVtYW5kYV9pZGFkZV9maW5hbCR0eF9jaGVmaWENCmBgYA0KDQojIFRhYmVsYSBmaW5hbCANCg0KYGBge3J9DQpkZW1hbmRhX2lkYWRlX2ZpbmFsICU+JSBmaWx0ZXIoZ3J1cG9fcGRhZEE9PSJERiIpJT4lIGphbml0b3I6OmFkb3JuX3RvdGFscygpDQoNCmBgYA0KDQpgYGB7cn0NCmRlbWFuZGFfaWRhZGVfZmluYWwgJT4lIGZpbHRlcihncnVwb19wZGFkQT09IsOBcmVhIFJ1cmFsIiklPiUgamFuaXRvcjo6YWRvcm5fdG90YWxzKCkNCmRlbWFuZGFfaWRhZGVfZmluYWwlPiUgc2VsZWN0KC1jb250YWlucygiY3YiKSwtY29udGFpbnMoInVwcCIpLC1jb250YWlucygibG93IikpICU+JSANCiAgd3JpdGVfc2hlZXQoImh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFzQ0o3cF9HaXRKWER3NFB1WU5ZQUI1WWo3ZU9zZUNHM2ZYeUNxX1dzSGlzL2VkaXQ/dXNwPXNoYXJpbmciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoZWV0PSJEZW1hbmRhX0RGIikNCg0KYGBgDQpgYGB7cn0NCmRlbWFuZGFfaWRhZGVfZmluYWwgJT4lIGZpbHRlcihncnVwb19wZGFkQT09IlBNQiIpICU+JSBqYW5pdG9yOjphZG9ybl90b3RhbHMoKQ0KDQpgYGANCg0KIyBDYWxjdWxhciBvIG7Dum1lcm8gZGUgYWR1bHRvcyBxdWUgdMOqbSBkZW1hbmRhIGhhYml0YWNpb25hbCBwb3IgZ3J1cG8gZXTDoXJpbyBlIFJBLg0KDQpgYGB7cn0NCmRlbWFuZGFfaWRhZGVfUkEgPC0gYW1vc3RyYV9tb3IgJT4lDQogIHNydnlyOjpmaWx0ZXIoZGVtYW5kYSA+IDAgJiAhKEUwNCAlaW4lIGMoMTozKSkpICU+JQ0KICBzcnZ5cjo6bXV0YXRlKGRlbWFuZGFfaW5kID0gaWZlbHNlKGlkYWRlICVpbiUgYygyNDo2NCkgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ual9jYXNhbCA9PSAwLCAxLCAwKSkgJT4lDQogIHNydnlyOjptdXRhdGUoDQogICAgZ3J1cG9fZXRhcmlvID0gY2FzZV93aGVuKA0KICAgICAgaWRhZGUgJWluJSBjKDI0OjI5KSB+ICJpZGFkZV8yNF8yOSIsDQogICAgICBpZGFkZSAlaW4lIGMoMzA6MzkpIH4gImlkYWRlXzMwXzM5IiwNCiAgICAgIGlkYWRlICVpbiUgYyg0MDo2NCkgfiAiaWRhZGVfNDBfNjQiDQogICAgKQ0KICApICU+JQ0KICBzcnZ5cjo6Z3JvdXBfYnkoZ3J1cG9fZXRhcmlvLCBSQV9ub21lLGdydXBvX3BkYWRBKSAlPiUNCiAgc3J2eXI6OnN1bW1hcmlzZShkZW1hbmRhXyA9IHN1cnZleV90b3RhbChkZW1hbmRhX2luZCwgdmFydHlwZSA9IGMoImN2IiwgImNpIiksIG5hLnJtID0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUpKQ0KDQogICMgVGVzdGUgcGFyYSB2ZXIgc2Ugw6kgcG9zc8OtdmVsIGZhemVyIGluZmVyw6puY2lhIHNvYnJlIG9zIGRhZG9zLg0KZGVtYW5kYV9pZGFkZV9SQSA8LSBhcy5kYXRhLmZyYW1lKGRlbWFuZGFfaWRhZGVfUkEpDQoNCmRlbWFuZGFfaWRhZGVfUkEkZGVtYW5kYV8gPC0NCiAgaWZlbHNlKGRlbWFuZGFfaWRhZGVfUkEkZGVtYW5kYV9fY3YgPiAwLjI1LA0KICAgICAgICAgTkEsDQogICAgICAgICBkZW1hbmRhX2lkYWRlX1JBJGRlbWFuZGFfKQ0KDQpkZW1hbmRhX2lkYWRlX1JBIDwtIHN1YnNldChkZW1hbmRhX2lkYWRlX1JBLCFpcy5uYShncnVwb19ldGFyaW8pKQ0KDQpkZW1hbmRhX2lkYWRlX1JBX2ZpbmFsICA8LQ0KICBtZXJnZShkZW1hbmRhX2lkYWRlX1JBLA0KICAgICAgICB0eF9jaGVmaWFfaWRhZGVfcmFmLA0KICAgICAgICBieSA9IGMoImdydXBvX2V0YXJpbyIsICJSQV9ub21lIiwiZ3J1cG9fcGRhZEEiKSkNCg0KZGVtYW5kYV9pZGFkZV9SQV9maW5hbCRkZW1hbmRhX2ZpbmFsIDwtDQogIGRlbWFuZGFfaWRhZGVfUkFfZmluYWwkZGVtYW5kYV8gKiBkZW1hbmRhX2lkYWRlX1JBX2ZpbmFsJHR4X2NoZWZpYQ0KYGBgDQoNCiMgVGFiZWxhIGZpbmFsDQoNCmBgYHtyfQ0KZGVtYW5kYV9pZGFkZV9SQV9maW5hbCU+JSAgIGphbml0b3I6OmFkb3JuX3RvdGFscygpICAlPiUgYXJyYW5nZShncnVwb19wZGFkQSkgJT4lIHNlbGVjdCgtY29udGFpbnMoImN2IiksLWNvbnRhaW5zKCJsb3ciKSwtY29udGFpbnMoInVwcCIpKQ0KDQpgYGANCmBgYHtyfQ0KZGVtYW5kYV9pZGFkZV9SQV9maW5hbF9UWERGICA8LQ0KICBtZXJnZShkZW1hbmRhX2lkYWRlX1JBLA0KICAgICAgICB0eF9jaGVmaWFfaWRhZGUsDQogICAgICAgIGJ5ID0gYygiZ3J1cG9fZXRhcmlvIiwiZ3J1cG9fcGRhZEEiKSkNCg0KZGVtYW5kYV9pZGFkZV9SQV9maW5hbF9UWERGJGRlbWFuZGFfZmluYWwgPC0NCiAgZGVtYW5kYV9pZGFkZV9SQV9maW5hbF9UWERGJGRlbWFuZGFfICogZGVtYW5kYV9pZGFkZV9SQV9maW5hbF9UWERGJHR4X2NoZWZpYQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShnb29nbGVkcml2ZSkNCmxpYnJhcnkoZ29vZ2xlc2hlZXRzNCkNCg0KZGVtYW5kYV9pZGFkZV9SQV9maW5hbF9UWERGJT4lIGFycmFuZ2UoZ3J1cG9fcGRhZEEpICU+JSBzZWxlY3QoLWNvbnRhaW5zKCJjdiIpLC1jb250YWlucygibG93IiksLWNvbnRhaW5zKCJ1cHAiKSkgJT4lIA0KICB3cml0ZV9zaGVldCgiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMXNDSjdwX0dpdEpYRHc0UHVZTllBQjVZajdlT3NlQ0czZlh5Q3FfV3NIaXMvZWRpdD91c3A9c2hhcmluZyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQ9IkRlbWFuZGFfUkFfVHhjaGVmaWFfREYiKQ0KYGBgDQoNCiMgUmVtb3ZlciB0YWJlbGFzIG7Do28gbWFpcyB1c2FkYXMNCmBgYHtyfQ0KI3JtKHR4X2NoZWZpYV9pZGFkZSwgdHhfY2hlZmlhX2lkYWRlX3JhLCB0eF9jaGVmaWFfaWRhZGVfcmFmLA0KIyAgIGRlbWFuZGFfaWRhZGVfUkEsIHBvcF9pZGFkZV9yYSkNCmBgYA0KDQoNCiMgQ29tcGFyYcOnw6NvIGdydXBvIGV0w6FyaW8gZSByZW5kaW1lbnRvDQpgYGB7cn0NCnBkYWQyMDIzDQpkZW1hbmRhX3NzIDwtIGFtb3N0cmFfbW9yICU+JSANCiAgc3J2eXI6OmZpbHRlcihkZW1hbmRhPjApICU+JSANCiAgc3J2eXI6Om11dGF0ZShkZW1hbmRhX2luZD1pZmVsc2UoaWRhZGUgJWluJSBjKDI0OjY0KSAmIGNvbmpfY2FzYWw9PTAsIDEsIDApKSAlPiUgDQogIHNydnlyOjptdXRhdGUoZ3J1cG9fZXRhcmlvID0gY2FzZV93aGVuKGlkYWRlICVpbiUgYygyNDoyOSkgfiAiaWRhZGVfMjRfMjkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoMzA6MzkpIH4gImlkYWRlXzMwXzM5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhZGUgJWluJSBjKDQwOjY0KSB+ICJpZGFkZV80MF82NCIpLA0KICAgICAgICAgICAgICAgIGFycmFuam8yID0gaWZlbHNlKGFycmFuam9zICVpbiUgYygxLDM6NiksIlVuaS9DYXNhaXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShhcnJhbmpvcyA9PSAyLCJNb25vcGFyZW50YWwgRmVtIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGFycmFuam9zID09IDcsIk91dHJvIixOQSkpKSkgJT4lDQogIHNydnlyOjpncm91cF9ieShncnVwb19ldGFyaW8sIGFycmFuam8yLGdydXBvX3BkYWRBKSAlPiUgDQogIHNydnlyOjpzdW1tYXJpc2UoZGVtYW5kYV89c3VydmV5X3RvdGFsKHZhcnR5cGUgPSBjKCJjdiIsICJjaSIpLCBuYS5ybT1UUlVFKSkgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShncnVwb19ldGFyaW8pKQ0KDQp0eF9jaGVmaWEgPC0gYW1vc3RyYV9tb3IgJT4lIA0KICBzcnZ5cjo6bXV0YXRlKGRlbWFuZGFfaW5kPWlmZWxzZShpZGFkZSAlaW4lIGMoMjQ6NjQpICYgY29ual9jYXNhbD09MCwgMSwgMCkpICU+JSANCiAgc3J2eXI6Om11dGF0ZShncnVwb19ldGFyaW8gPSBjYXNlX3doZW4oaWRhZGUgJWluJSBjKDI0OjI5KSB+ICJpZGFkZV8yNF8yOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoNDA6NjQpIH4gImlkYWRlXzQwXzY0IiksDQogICAgICAgICAgICAgICAgYXJyYW5qbzIgPSBpZmVsc2UoYXJyYW5qb3MgJWluJSBjKDEsMzo2KSwiVW5pL0Nhc2FpcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGFycmFuam9zID09IDIsIk1vbm9wYXJlbnRhbCBGZW0iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoYXJyYW5qb3MgPT0gNywiT3V0cm8iLE5BKSkpKSAlPiUgDQogIHNydnlyOjpmaWx0ZXIoRTA0PT0xKSAlPiUgDQogIHNydnlyOjpncm91cF9ieShncnVwb19ldGFyaW8sZ3J1cG9fcGRhZEEpICU+JSANCiAgc3J2eXI6OnN1bW1hcmlzZSh0b3RhbF9jaGVmZXM9c3VydmV5X3RvdGFsKHZhcnR5cGUgPSBjKCJjdiIsICJjaSIpKSkgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShncnVwb19ldGFyaW8pKQ0KDQpwb3BfdG90YWwgPC0gYW1vc3RyYV9tb3IgJT4lIA0KICBzcnZ5cjo6bXV0YXRlKGRlbWFuZGFfaW5kPWlmZWxzZShpZGFkZSAlaW4lIGMoMjQ6NjQpICYgY29ual9jYXNhbD09MCwgMSwgMCkpICU+JSANCiAgc3J2eXI6Om11dGF0ZShncnVwb19ldGFyaW8gPSBjYXNlX3doZW4oaWRhZGUgJWluJSBjKDI0OjI5KSB+ICJpZGFkZV8yNF8yOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoNDA6NjQpIH4gImlkYWRlXzQwXzY0IikpICU+JSANCiAgc3J2eXI6Omdyb3VwX2J5KGdydXBvX2V0YXJpbyxncnVwb19wZGFkQSkgJT4lIA0KICBzcnZ5cjo6c3VtbWFyaXNlKHBvcF90b3RhbD1zdXJ2ZXlfdG90YWwodmFydHlwZSA9IGMoImN2IiwgImNpIikpKSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGdydXBvX2V0YXJpbykpDQpkb21fdG90YWwgPC0gYW1vc3RyYV9tb3IgJT4lIA0KICBzcnZ5cjo6bXV0YXRlKGRlbWFuZGFfaW5kPWlmZWxzZShpZGFkZSAlaW4lIGMoMjQ6NjQpICYgY29ual9jYXNhbD09MCwgMSwgMCkpICU+JSANCiAgc3J2eXI6Om11dGF0ZShncnVwb19ldGFyaW8gPSBjYXNlX3doZW4oaWRhZGUgJWluJSBjKDI0OjI5KSB+ICJpZGFkZV8yNF8yOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoNDA6NjQpIH4gImlkYWRlXzQwXzY0IikpICU+JSANCiAgc3J2eXI6Omdyb3VwX2J5KGdydXBvX2V0YXJpbyxncnVwb19wZGFkQSkgJT4lIA0KICBzcnZ5cjo6c3VtbWFyaXNlKHBvcF90b3RhbD1zdXJ2ZXlfdG90YWwodmFydHlwZSA9IGMoImN2IiwgImNpIikpKSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGdydXBvX2V0YXJpbykpDQpgYGANCg0KDQpgYGB7cn0NCmRlbWFuZGFfc3MgPC0gZGVtYW5kYV9zcyAlPiUgDQogIGlubmVyX2pvaW4odHhfY2hlZmlhKSAlPiUgDQogIGlubmVyX2pvaW4ocG9wX3RvdGFsKSAlPiUgDQogIGlubmVyX2pvaW4oZG9tX3RvdGFsKSAlPiUgDQoNCiAgc2VsZWN0KC1jb250YWlucygiY3YiKSwgLWNvbnRhaW5zKCJsb3ciKSwgLWNvbnRhaW5zKCJ1cHAiKSkgJT4lIA0KICBtdXRhdGUoZGVtYW5kYV9maW5hbCA9IGRlbWFuZGFfKnRvdGFsX2NoZWZlcy9wb3BfdG90YWwsDQogICAgICAgICB0eF9jaGVmaWE9dG90YWxfY2hlZmVzL3BvcF90b3RhbCkgDQpgYGANCiMjIyMgc2Fsdi0tLS0tLS0NCmBgYHtyfQ0KDQpkZW1hbmRhX3NzICAlPiUgZmlsdGVyKGdydXBvX3BkYWRBPT0iREYiKSAlPiUgDQogIGphbml0b3I6OmFkb3JuX3RvdGFscygpJT4lIGFycmFuZ2UoZ3J1cG9fcGRhZEEpDQpkZW1hbmRhX3NzICAlPiUgZmlsdGVyKGdydXBvX3BkYWRBPT0iREYiKSAlPiUgDQogIG11dGF0ZShwZXJjZW50dWFsPWRlbWFuZGFfZmluYWwvc3VtKGRlbWFuZGFfZmluYWwpKSAlPiUgDQogIGphbml0b3I6OmFkb3JuX3RvdGFscygpJT4lIGFycmFuZ2UoZ3J1cG9fcGRhZEEpICU+JQ0KICB3cml0ZV9zaGVldCgiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMXNDSjdwX0dpdEpYRHc0UHVZTllBQjVZajdlT3NlQ0czZlh5Q3FfV3NIaXMvZWRpdD91c3A9c2hhcmluZyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQ9IkRlbWFuZGFfQXJyYW5qb3MiKQ0KYGBgDQoNCmBgYHtyfQ0KdGJfZGVtYW5kYV9nZXJhbCA8LSBkZW1hbmRhX2lkYWRlICU+JSANCiAgaW5uZXJfam9pbih0eF9jaGVmaWEpICU+JSANCiAgaW5uZXJfam9pbihwb3BfdG90YWwpICU+JSANCiAgICBpbm5lcl9qb2luKGRvbV90b3RhbCkgJT4lIA0KDQogIHNlbGVjdCgtY29udGFpbnMoImN2IiksIC1jb250YWlucygibG93IiksIC1jb250YWlucygidXBwIikpICU+JSANCiAgbXV0YXRlKGRlbWFuZGFfZmluYWwgPSBkZW1hbmRhXyp0b3RhbF9jaGVmZXMvcG9wX3RvdGFsKSANCiAgDQoNCnRiX3R4X2NoZWZpYSA8LSANCnRiX2RlbWFuZGFfZ2VyYWwgJT4lIA0KICBtdXRhdGUodHguY2hlZmlhID0gdG90YWxfY2hlZmVzL3BvcF90b3RhbCkgJT4lIA0KICBzZWxlY3QoZ3J1cG9fZXRhcmlvLGdydXBvX3BkYWRBICAgLHR4LmNoZWZpYSkNCmBgYA0KDQpgYGB7cn0NCnRiX3R4X2NoZWZpYSAlPiUgYXJyYW5nZShncnVwb19wZGFkQSkgDQp0Yl9kZW1hbmRhX2dlcmFsICU+JSBncm91cF9ieShncnVwb19wZGFkQSkgJT4lIHN1bW1hcmlzZShkZW1hbmRhX3RvdGFsPXN1bShkZW1hbmRhX2ZpbmFsLCBuYS5ybT1UUlVFKSkgJT4lIGphbml0b3I6OmFkb3JuX3RvdGFscygpDQpgYGANCg0KDQpgYGB7cn0NCiMgVGFiZWxhIGRlIHJlbmRhIGRvbWljaWxpYXIgZG9zIGRlbWFuZGFudGVzDQp0Yl9yZW5kYV9kZW1hbmRhbnRlIDwtDQogIGFtb3N0cmFfbW9yICU+JQ0KICBzcnZ5cjo6ZmlsdGVyKGRlbWFuZGEgPiAwICYgIShFMDQgJWluJSBjKDE6MykpKSAlPiUNCiAgc3J2eXI6Om11dGF0ZShkZW1hbmRhX2luZCA9IGlmZWxzZShpZGFkZSAlaW4lIGMoMjQ6NjQpICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmpfY2FzYWwgPT0gMCwgMSwgMCkpICU+JQ0KICBzcnZ5cjo6bXV0YXRlKA0KICAgIGdydXBvX2V0YXJpbyA9IGNhc2Vfd2hlbigNCiAgICAgIGlkYWRlICVpbiUgYygyNDoyOSkgfiAiaWRhZGVfMjRfMjkiLA0KICAgICAgaWRhZGUgJWluJSBjKDMwOjM5KSB+ICJpZGFkZV8zMF8zOSIsDQogICAgICBpZGFkZSAlaW4lIGMoNDA6NjQpIH4gImlkYWRlXzQwXzY0Ig0KICAgICksDQogICAgcmVuZGFfZG9tID0gY2FzZV93aGVuKA0KICAgICAgcmVuZGFfaW5kX3IgPD0gc20gfiAiYXRlMDNTTSIsDQogICAgICByZW5kYV9pbmRfciA+IDExMDAgJg0KICAgICAgICByZW5kYV9pbmRfciA8PSAzMzAwIH4gIjNhOFNNIiwNCiAgICAgIHJlbmRhX2luZF9yID4gNTUwMCAmDQogICAgICAgIHJlbmRhX2luZF9yIDw9IDEzMjAwIH4gIjhhMTJTTSIsDQogICAgICByZW5kYV9pbmRfciA+IDEzMjAwIH4gIm1haXNkZTEyU00iDQogICAgKQ0KICApICU+JQ0KICBzcnZ5cjo6Z3JvdXBfYnkoZ3J1cG9fZXRhcmlvLGdydXBvX3BkYWRBLCByZW5kYV9kb20pICU+JQ0KICBzcnZ5cjo6c3VtbWFyaXNlKGRlbWFuZGFfID0gc3VydmV5X3RvdGFsKGRlbWFuZGFfaW5kLCB2YXJ0eXBlID0gYygiY3YiLCAiY2kiKSwgbmEucm0gPQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSkpIC0+dA0KdCAlPiUgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShncnVwb19ldGFyaW8pKSAlPiUNCiAgaW5uZXJfam9pbih0Yl90eF9jaGVmaWEpICU+JQ0KICANCiAgbXV0YXRlKGRlbWFuZGFfZmluYWwgPSBkZW1hbmRhXyAqIHR4LmNoZWZpYSkgDQogICNzZWxlY3QoZ3J1cG9fZXRhcmlvLCByZW5kYV9kb20sIGRlbWFuZGFfZmluYWwpICU+JQ0KICAjdGlkeXI6OnNwcmVhZChncnVwb19ldGFyaW8sIGRlbWFuZGFfZmluYWwpDQpgYGANCg0KIyByZW5kYSAtLS0tLS0tLS0tDQpgYGB7cn0NCiMgVGFiZWxhIGZpbmFsDQp0Yl9yZW5kYV9kZW1hbmRhbnRlJT4lDQogIGlubmVyX2pvaW4odHhfY2hlZmlhKSAlPiUgDQogIGlubmVyX2pvaW4ocG9wX3RvdGFsKSAlPiUgDQogICAgaW5uZXJfam9pbihkb21fdG90YWwpICU+JSANCg0KICAjc2VsZWN0KC1jb250YWlucygiY3YiKSwgLWNvbnRhaW5zKCJsb3ciKSwgLWNvbnRhaW5zKCJ1cHAiKSkgJT4lIA0KICBzZWxlY3QoLWNvbnRhaW5zKCJjdiIpLC1jb250YWlucygidXBwIiksLWNvbnRhaW5zKCJsb3ciKSkgJT4lIA0KICBtdXRhdGUoZGVtYW5kYV9maW5hbCA9IGRlbWFuZGFfKnRvdGFsX2NoZWZlcy9wb3BfdG90YWwsDQogICAgICAgICB0eF9jaGVmaWE9dG90YWxfY2hlZmVzL3BvcF90b3RhbCkgJT4lIA0KICB3cml0ZV9zaGVldCgiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMXNDSjdwX0dpdEpYRHc0UHVZTllBQjVZajdlT3NlQ0czZlh5Q3FfV3NIaXMvZWRpdD91c3A9c2hhcmluZyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQ9IkRlbWFuZGFfcmVuZGFfZG9tIikNCg0KYGBgDQoNCiMjIDcuMiBFc2NvbGFyaWRhZGUgDQojIyNQb3IgZ3J1cG8gRXTDoXJpbw0KYGBge3J9DQpwZGFkMjAyMyRlc2NvbGFyaWRhZGUjRXN0YWRvIGNpdmlsDQpkZW1hbmRhX2lkYWRlX3N0cmF0YTIgPC0gYW1vc3RyYV9tb3IgJT4lI0ZpbHRyYSBhcGVuYXMgb2JzZXJ2YcOnw7VlcyBjb20gZGVtYW5kYSBwb3NpdGl2YQ0KICBzcnZ5cjo6ZmlsdGVyKGRlbWFuZGEgPiAwKSAlPiUNCiAgc3J2eXI6Om11dGF0ZShkZW1hbmRhX2luZCA9IGlmZWxzZShpZGFkZSAlaW4lIGMoMjQ6NjQpICYgY29ual9jYXNhbCA9PSAwLCAxLCAwKSwNCiAgICAgICAgICAgICAgICBncnVwb19ldGFyaW8gPSBjYXNlX3doZW4oaWRhZGUgJWluJSBjKDI0OjI5KSB+ICJpZGFkZV8yNF8yOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoNDA6NjQpIH4gImlkYWRlXzQwXzY0IiksDQogICAgICAgICAgICAgICAgc3RyYXRhX2VzY29sYXJpZGFkZT1jYXNlX3doZW4oZXNjb2xhcmlkYWRlPT0xfiJTZW0gaW5zdHJ1w6fDo28iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzY29sYXJpZGFkZT09Mn4iRnVuZGFtZW50YWwgaW5jb21wbGV0byBvdSBlcXVpdmFsZW50ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXNjb2xhcmlkYWRlPT0zfiJGdW5kYW1lbnRhbCBjb21wbGV0byBvdSBlcXVpdmFsZW50ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXNjb2xhcmlkYWRlPT00fiJNw6lkaW8gaW5jb21wbGV0byBvdSBlcXVpdmFsZW50ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXNjb2xhcmlkYWRlPT01fiJNw6lkaW8gY29tcGxldG8gb3UgZXF1aXZhbGVudGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzY29sYXJpZGFkZT09Nn4iU3VwZXJpb3IgaW5jb21wbGV0byBvdSBlcXVpdmFsZW50ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXNjb2xhcmlkYWRlPT03fiJTdXBlcmlvciBjb21wbGV0byAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzY29sYXJpZGFkZT09OH4iU2VtIGNsYXNzaWZpY2HDp8OjbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRX4iTsOjbyBTYWJlIC8gTsOjbyBzZSBBcGxpY2EiKSkgJT4lI0NsYXNzaWZpY2EgZmFpeGFzIGV0w6FyaWFzIGRlIGludGVyZXNzZQ0KICBzcnZ5cjo6Z3JvdXBfYnkoZ3J1cG9fZXRhcmlvLCBncnVwb19wZGFkQSxzdHJhdGFfZXNjb2xhcmlkYWRlKSAlPiUNCiAgc3J2eXI6OnN1bW1hcmlzZShkZW1hbmRhID0gc3VydmV5X3RvdGFsKGRlbWFuZGFfaW5kLCB2YXJ0eXBlID0gYygiY3YiLCAiY2kiKSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgICNDb252ZXJ0ZSBwYXJhIGRhdGEuZnJhbWUgZSBhcGxpY2EgZmlsdHJvIGRlIHByZWNpc8Ojbw0KICBtdXRhdGUoZGVtYW5kYT1pZmVsc2UoZGVtYW5kYV9jdj4wLjI1LE5BLGRlbWFuZGEpKQ0KZGVtYW5kYV9pZGFkZV9zdHJhdGEyICU+JSBmaWx0ZXIoZ3J1cG9fcGRhZEE9PSJERiIpDQoNCmRlbWFuZGFfaWRhZGVfc3RyYXRhMiA8LQ0KICBtZXJnZShkZW1hbmRhX2lkYWRlX3N0cmF0YTIsIHR4X2NoZWZpYV9pZGFkZSwNCiAgICAgICAgYnkgPSBjKCJncnVwb19ldGFyaW8iLCAiZ3J1cG9fcGRhZEEiKSkgJT4lIA0KICBtdXRhdGUoZGVtYW5kYV9hanVzdGFkYSA9IGRlbWFuZGEgKiB0YXhhX2NoZWZpYSkgJT4lIHNlbGVjdChncnVwb19ldGFyaW8sZ3J1cG9fcGRhZEEsc3RyYXRhX2VzY29sYXJpZGFkZSxkZW1hbmRhX2FqdXN0YWRhLGRlbWFuZGEsdGF4YV9jaGVmaWEscG9wX2NoZWZlLHBvcF90b3RhbCkNCmRlbWFuZGFfaWRhZGVfc3RyYXRhMiAlPiUgZmlsdGVyKGdydXBvX3BkYWRBPT0iREYiKSAlPiUgYWRvcm5fdG90YWxzKCkNCmRlbWFuZGFfaWRhZGVfc3RyYXRhMg0KYGBgDQoNCmBgYHtyfQ0KZGVtYW5kYV9pZGFkZV9zdHJhdGEyICU+JSANCiAgaW5uZXJfam9pbih0eF9jaGVmaWEpICU+JSANCiAgaW5uZXJfam9pbihwb3BfdG90YWwpICU+JSANCiAgDQoNCiAgI3NlbGVjdCgtY29udGFpbnMoImN2IiksIC1jb250YWlucygibG93IiksIC1jb250YWlucygidXBwIikpICU+JSANCiAgc2VsZWN0KC1jb250YWlucygiY3YiKSwtY29udGFpbnMoInVwcCIpLC1jb250YWlucygibG93IikpICU+JSANCiAgbXV0YXRlKGRlbWFuZGFfZmluYWwgPSBkZW1hbmRhKnRvdGFsX2NoZWZlcy9wb3BfdG90YWwsDQogICAgICAgICB0eF9jaGVmaWE9dG90YWxfY2hlZmVzL3BvcF90b3RhbCkgJT4lIA0KICB3cml0ZV9zaGVldCgiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMXNDSjdwX0dpdEpYRHc0UHVZTllBQjVZajdlT3NlQ0czZlh5Q3FfV3NIaXMvZWRpdD91c3A9c2hhcmluZyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQ9IkRlbWFuZGFfaW5zdHJ1w6fDo28iKQ0KYGBgDQoNCg0KDQoNCg0KIyMgNy4yIHNhbGFyaW9taW5pbW8NCiMjI1BvciBncnVwbyBFdMOhcmlvDQpgYGB7cn0NCnBkYWQyMDIzX29yaWdpbmFsJHJlbmRhDQoNCmBgYA0KDQpgYGB7cn0NCnBkYWQyMDIzJHJlbmRhX2luZCNFc3RhZG8gY2l2aWwNCmRlbWFuZGFfaWRhZGVfc3RyYXRhMyA8LSBhbW9zdHJhX21vciAlPiUjRmlsdHJhIGFwZW5hcyBvYnNlcnZhw6fDtWVzIGNvbSBkZW1hbmRhIHBvc2l0aXZhDQogIHNydnlyOjpmaWx0ZXIoZGVtYW5kYSA+IDApICU+JQ0KIHNydnlyOjptdXRhdGUoZGVtYW5kYV9pbmQgPSBpZmVsc2UoaWRhZGUgJWluJSBjKDI0OjY0KSAmIGNvbmpfY2FzYWwgPT0gMCwgMSwgMCksDQogICAgICAgICAgICAgICBncnVwb19ldGFyaW8gPSBjYXNlX3doZW4oaWRhZGUgJWluJSBjKDI0OjI5KSB+ICJpZGFkZV8yNF8yOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoNDA6NjQpIH4gImlkYWRlXzQwXzY0IiksDQogICAgICAgICAgICAgICAgc3RyYXRhX3JlbmRhPWNhc2Vfd2hlbihyZW5kYV9pbmQ8MypzYWxhcmlvbWluaW1vfiIwLTNTTSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kYV9pbmQ8NSpzYWxhcmlvbWluaW1vfiIzLTVTTSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kYV9pbmQ+NSpzYWxhcmlvbWluaW1vfiI1K1NNIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNyZW5kYV9pbmQ8c2FsYXJpb21pbmltb34ibWFpb3I0U00iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICBUUlVFfiJOw6NvIFNhYmUgLyBOw6NvIHNlIEFwbGljYSINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpICU+JSNDbGFzc2lmaWNhIGZhaXhhcyBldMOhcmlhcyBkZSBpbnRlcmVzc2UNCiAgc3J2eXI6Omdyb3VwX2J5KGdydXBvX2V0YXJpbywgZ3J1cG9fcGRhZEEsc3RyYXRhX3JlbmRhKSAlPiUNCiAgc3J2eXI6OnN1bW1hcmlzZShkZW1hbmRhID0gc3VydmV5X3RvdGFsKGRlbWFuZGFfaW5kLCB2YXJ0eXBlID0gYygiY3YiLCAiY2kiKSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgICNDb252ZXJ0ZSBwYXJhIGRhdGEuZnJhbWUgZSBhcGxpY2EgZmlsdHJvIGRlIHByZWNpc8Ojbw0KICBtdXRhdGUoZGVtYW5kYT1pZmVsc2UoZGVtYW5kYV9jdj5wYXJhbXMkY3ZfbWF4LE5BLGRlbWFuZGEpKQ0KZGVtYW5kYV9pZGFkZV9zdHJhdGEzICU+JSBmaWx0ZXIoZ3J1cG9fcGRhZEE9PSJERiIpDQoNCmRlbWFuZGFfaWRhZGVfc3RyYXRhMyA8LQ0KICBtZXJnZShkZW1hbmRhX2lkYWRlX3N0cmF0YTMsIHRheGFfY2hlZmlhX2dyb3Vwb19BLA0KYnkgPSBjKCJncnVwb19ldGFyaW8iLCAiZ3J1cG9fcGRhZEEiKSkgJT4lIA0KICBtdXRhdGUoZGVtYW5kYV9hanVzdGFkYSA9IGRlbWFuZGEgKiB0YXhhX2NoZWZpYSkgJT4lIHNlbGVjdChncnVwb19ldGFyaW8sZ3J1cG9fcGRhZEEsc3RyYXRhX3JlbmRhLGRlbWFuZGFfYWp1c3RhZGEsZGVtYW5kYSx0YXhhX2NoZWZpYSxwb3BfY2hlZmUscG9wX3RvdGFsKQ0KZGVtYW5kYV9pZGFkZV9zdHJhdGEzICU+JSBmaWx0ZXIoZ3J1cG9fcGRhZEE9PSJERiIpICU+JSBhZG9ybl90b3RhbHMoKQ0KYGBgDQoNCg0KYGBge3J9DQpkZW1hbmRhX2lkYWRlX3N0cmF0YTMgPC0gYW1vc3RyYV9tb3IgJT4lI0ZpbHRyYSBhcGVuYXMgb2JzZXJ2YcOnw7VlcyBjb20gZGVtYW5kYSBwb3NpdGl2YQ0KICBzcnZ5cjo6ZmlsdGVyKCNlMDc8NiwNCiAgICAgICAgICAgICAgICBkZW1hbmRhID4gMCAmICEoZTA0ICVpbiUgYygxOjMpKSwhZ3J1cG9fZXRhcmlvPT0iT3V0cm8iKSAlPiUjQ3JpYSB2YXJpw6F2ZWwgYmluw6FyaWE6IGFkdWx0byBlbnRyZSAyNCBlIDY0IGFub3MsIHF1ZSBuw6NvIMOpIGPDtG5qdWdlIG5lbSBjaGVmZSBkZSBjYXNhbA0KICBzcnZ5cjo6bXV0YXRlKGRlbWFuZGFfaW5kID0gaWZlbHNlKGlkYWRlICVpbiUgYygyNDo2NCkgJiBjb25qX2Nhc2FsID09IDAsIDEsIDApLA0KICAgICAgICAgICAgICAgIGdydXBvX2V0YXJpbyA9IGNhc2Vfd2hlbihpZGFkZSAlaW4lIGMoMjQ6MjkpIH4gImlkYWRlXzI0XzI5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhZGUgJWluJSBjKDMwOjM5KSB+ICJpZGFkZV8zMF8zOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYyg0MDo2NCkgfiAiaWRhZGVfNDBfNjQiKSwNCiAgICAgICAgICAgICAgICBzdHJhdGFfcmVuZGE9Y2FzZV93aGVuKHJlbmRhX2luZDxzYWxhcmlvbWluaW1vfiIwLTFTTSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kYV9pbmQ8MypzYWxhcmlvbWluaW1vfiIxLTNTTSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kYV9pbmQ+MypzYWxhcmlvbWluaW1vfiI1K1NNIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNyZW5kYV9pbmQ8c2FsYXJpb21pbmltb34ibWFpb3I0U00iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICBUUlVFfiJOw6NvIFNhYmUgLyBOw6NvIHNlIEFwbGljYSINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpICU+JSNDbGFzc2lmaWNhIGZhaXhhcyBldMOhcmlhcyBkZSBpbnRlcmVzc2UNCiAgc3J2eXI6Omdyb3VwX2J5KGdydXBvX2V0YXJpbywgZ3J1cG9fcGRhZEEsc3RyYXRhX3JlbmRhKSAlPiUNCiAgc3J2eXI6OnN1bW1hcmlzZShkZW1hbmRhID0gc3VydmV5X3RvdGFsKGRlbWFuZGFfaW5kLCB2YXJ0eXBlID0gYygiY3YiLCAiY2kiKSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgICNDb252ZXJ0ZSBwYXJhIGRhdGEuZnJhbWUgZSBhcGxpY2EgZmlsdHJvIGRlIHByZWNpc8Ojbw0KICBtdXRhdGUoZGVtYW5kYT1pZmVsc2UoZGVtYW5kYV9jdj5wYXJhbXMkY3ZfbWF4LE5BLGRlbWFuZGEpKQ0KZGVtYW5kYV9pZGFkZV9zdHJhdGEzICU+JSBmaWx0ZXIoZ3J1cG9fcGRhZEE9PSJERiIpDQoNCmRlbWFuZGFfaWRhZGVfc3RyYXRhMyA8LQ0KICBtZXJnZShkZW1hbmRhX2lkYWRlX3N0cmF0YTMsIHRheGFfY2hlZmlhX2dyb3Vwb19BLA0KYnkgPSBjKCJncnVwb19ldGFyaW8iLCAiZ3J1cG9fcGRhZEEiKSkgJT4lIA0KICBtdXRhdGUoZGVtYW5kYV9hanVzdGFkYSA9IGRlbWFuZGEgKiB0YXhhX2NoZWZpYSkgJT4lIHNlbGVjdChncnVwb19ldGFyaW8sZ3J1cG9fcGRhZEEsc3RyYXRhX3JlbmRhLGRlbWFuZGFfYWp1c3RhZGEsZGVtYW5kYSx0YXhhX2NoZWZpYSxwb3BfY2hlZmUscG9wX3RvdGFsKQ0KZGVtYW5kYV9pZGFkZV9zdHJhdGEzICU+JSBmaWx0ZXIoZ3J1cG9fcGRhZEE9PSJERiIpICU+JSBhZG9ybl90b3RhbHMoKQ0KYGBgDQojIyBSZW5kYSBEb21pY2lsaWFyDQpgYGB7cn0NCg0KZGVtYW5kYV9pZGFkZV9zdHJhdGEzIDwtIGFtb3N0cmFfbW9yICU+JSNGaWx0cmEgYXBlbmFzIG9ic2VydmHDp8O1ZXMgY29tIGRlbWFuZGEgcG9zaXRpdmENCiAgc3J2eXI6OmZpbHRlcihkZW1hbmRhID4gMCkgJT4lDQogIHNydnlyOjptdXRhdGUoZGVtYW5kYV9pbmQgPSBpZmVsc2UoaWRhZGUgJWluJSBjKDI0OjY0KSAmIGNvbmpfY2FzYWwgPT0gMCwgMSwgMCksDQogICAgICAgICAgICAgICAgZ3J1cG9fZXRhcmlvID0gY2FzZV93aGVuKGlkYWRlICVpbiUgYygyNDoyOSkgfiAiaWRhZGVfMjRfMjkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoMzA6MzkpIH4gImlkYWRlXzMwXzM5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhZGUgJWluJSBjKDQwOjY0KSB+ICJpZGFkZV80MF82NCIpLA0KICAgICAgICAgICAgICAgIHN0cmF0YV9yZW5kYT1jYXNlX3doZW4ocmVuZGFfZG9taWNpbGlhcjxzYWxhcmlvbWluaW1vfiIwLTFTTSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kYV9kb21pY2lsaWFyPDMqc2FsYXJpb21pbmltb34iMS0zU00iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGFfZG9taWNpbGlhcj4zKnNhbGFyaW9taW5pbW9+IjUrU00iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI3JlbmRhX2luZDxzYWxhcmlvbWluaW1vfiJtYWlvcjRTTSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgIFRSVUV+Ik7Do28gU2FiZSAvIE7Do28gc2UgQXBsaWNhIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkgJT4lI0NsYXNzaWZpY2EgZmFpeGFzIGV0w6FyaWFzIGRlIGludGVyZXNzZQ0KICBzcnZ5cjo6Z3JvdXBfYnkoZ3J1cG9fZXRhcmlvLCBncnVwb19wZGFkQSxzdHJhdGFfcmVuZGEpICU+JQ0KICBzcnZ5cjo6c3VtbWFyaXNlKGRlbWFuZGEgPSBzdXJ2ZXlfdG90YWwoZGVtYW5kYV9pbmQsIHZhcnR5cGUgPSBjKCJjdiIsICJjaSIpLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAgI0NvbnZlcnRlIHBhcmEgZGF0YS5mcmFtZSBlIGFwbGljYSBmaWx0cm8gZGUgcHJlY2lzw6NvDQogIG11dGF0ZShkZW1hbmRhPWlmZWxzZShkZW1hbmRhX2N2PnBhcmFtcyRjdl9tYXgsTkEsZGVtYW5kYSkpDQpkZW1hbmRhX2lkYWRlX3N0cmF0YTMgJT4lIGZpbHRlcihncnVwb19wZGFkQT09IkRGIikNCg0KZGVtYW5kYV9pZGFkZV9zdHJhdGEzIDwtDQogIG1lcmdlKGRlbWFuZGFfaWRhZGVfc3RyYXRhMywgdGF4YV9jaGVmaWFfZ3JvdXBvX0EsDQpieSA9IGMoImdydXBvX2V0YXJpbyIsICJncnVwb19wZGFkQSIpKSAlPiUgDQogIG11dGF0ZShkZW1hbmRhX2FqdXN0YWRhID0gZGVtYW5kYSAqIHRheGFfY2hlZmlhKSAlPiUgc2VsZWN0KGdydXBvX2V0YXJpbyxncnVwb19wZGFkQSxzdHJhdGFfcmVuZGEsZGVtYW5kYV9hanVzdGFkYSxkZW1hbmRhLHRheGFfY2hlZmlhLHBvcF9jaGVmZSxwb3BfdG90YWwpDQpkZW1hbmRhX2lkYWRlX3N0cmF0YTMgJT4lIGZpbHRlcihncnVwb19wZGFkQT09IkRGIikgJT4lIGFkb3JuX3RvdGFscygpDQpgYGANCg0KDQpgYGB7cn0NCmRlbWFuZGFfaWRhZGVfc3RyYXRhMyA8LSBhbW9zdHJhX21vciAlPiUjRmlsdHJhIGFwZW5hcyBvYnNlcnZhw6fDtWVzIGNvbSBkZW1hbmRhIHBvc2l0aXZhDQogIHNydnlyOjpmaWx0ZXIoI2UwNzw2LA0KICAgICAgICAgICAgICAgIGRlbWFuZGEgPiAwICYgIShlMDQgJWluJSBjKDE6MykpLCFncnVwb19ldGFyaW89PSJPdXRybyIpICU+JSNDcmlhIHZhcmnDoXZlbCBiaW7DoXJpYTogYWR1bHRvIGVudHJlIDI0IGUgNjQgYW5vcywgcXVlIG7Do28gw6kgY8O0bmp1Z2UgbmVtIGNoZWZlIGRlIGNhc2FsDQogIHNydnlyOjptdXRhdGUoZGVtYW5kYV9pbmQgPSBpZmVsc2UoaWRhZGUgJWluJSBjKDI0OjY0KSAmIGNvbmpfY2FzYWwgPT0gMCwgMSwgMCksDQogICAgICAgICAgICAgICAgZ3J1cG9fZXRhcmlvID0gY2FzZV93aGVuKGlkYWRlICVpbiUgYygyNDoyOSkgfiAiaWRhZGVfMjRfMjkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoMzA6MzkpIH4gImlkYWRlXzMwXzM5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhZGUgJWluJSBjKDQwOjY0KSB+ICJpZGFkZV80MF82NCIpLA0KICAgICAgICAgICAgICAgIHN0cmF0YV9yZW5kYT1jYXNlX3doZW4ocmVuZGFfaW5kPHNhbGFyaW9taW5pbW9+IjAtMVNNIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRhX2luZDwzKnNhbGFyaW9taW5pbW9+IjEtM1NNIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRhX2luZD4zKnNhbGFyaW9taW5pbW9+IjUrU00iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI3JlbmRhX2luZDxzYWxhcmlvbWluaW1vfiJtYWlvcjRTTSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgIFRSVUV+Ik7Do28gU2FiZSAvIE7Do28gc2UgQXBsaWNhIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkgJT4lI0NsYXNzaWZpY2EgZmFpeGFzIGV0w6FyaWFzIGRlIGludGVyZXNzZQ0KICBzcnZ5cjo6Z3JvdXBfYnkoZ3J1cG9fZXRhcmlvLCBncnVwb19wZGFkQSxzdHJhdGFfcmVuZGEpICU+JQ0KICBzcnZ5cjo6c3VtbWFyaXNlKGRlbWFuZGEgPSBzdXJ2ZXlfdG90YWwoZGVtYW5kYV9pbmQsIHZhcnR5cGUgPSBjKCJjdiIsICJjaSIpLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAgI0NvbnZlcnRlIHBhcmEgZGF0YS5mcmFtZSBlIGFwbGljYSBmaWx0cm8gZGUgcHJlY2lzw6NvDQogIG11dGF0ZShkZW1hbmRhPWlmZWxzZShkZW1hbmRhX2N2PnBhcmFtcyRjdl9tYXgsTkEsZGVtYW5kYSkpDQpkZW1hbmRhX2lkYWRlX3N0cmF0YTMgJT4lIGZpbHRlcihncnVwb19wZGFkQT09IkRGIikNCg0KZGVtYW5kYV9pZGFkZV9zdHJhdGEzIDwtDQogIG1lcmdlKGRlbWFuZGFfaWRhZGVfc3RyYXRhMywgdGF4YV9jaGVmaWFfZ3JvdXBvX0EsDQpieSA9IGMoImdydXBvX2V0YXJpbyIsICJncnVwb19wZGFkQSIpKSAlPiUgDQogIG11dGF0ZShkZW1hbmRhX2FqdXN0YWRhID0gZGVtYW5kYSAqIHRheGFfY2hlZmlhKSAlPiUgc2VsZWN0KGdydXBvX2V0YXJpbyxncnVwb19wZGFkQSxzdHJhdGFfcmVuZGEsZGVtYW5kYV9hanVzdGFkYSxkZW1hbmRhLHRheGFfY2hlZmlhLHBvcF9jaGVmZSxwb3BfdG90YWwpDQpkZW1hbmRhX2lkYWRlX3N0cmF0YTMgJT4lIGZpbHRlcihncnVwb19wZGFkQT09IkRGIikgJT4lIGFkb3JuX3RvdGFscygpDQpgYGANCg0KDQojIyBJbnRlbsOnw6NvIGRlIGZvcm1hciBub3ZvIGRvbWljw61saW8gcGFydGljdWxhciBub3MgcHLDs3hpbW9zIDEyIG1lc2VzDQoNCg0KIyMjUG9yIGdydXBvIEV0w6FyaW8NCmBgYHtyfQ0KcGRhZDIwMjNfb3JpZ2luYWwkRTIyDQoNCmRlbWFuZGFfc3RyYXRhX211ZGFuw6dhIDwtIGFtb3N0cmFfbW9yICU+JSNGaWx0cmEgYXBlbmFzIG9ic2VydmHDp8O1ZXMgY29tIGRlbWFuZGEgcG9zaXRpdmENCiAgc3J2eXI6OmZpbHRlcihFMjI8MywNCiAgICAgICAgICAgICAgICBkZW1hbmRhID4gMCkgJT4lI0NyaWEgdmFyacOhdmVsIGJpbsOhcmlhOiBhZHVsdG8gZW50cmUgMjQgZSA2NCBhbm9zLCBxdWUgbsOjbyDDqSBjw7RuanVnZSBuZW0gY2hlZmUgZGUgY2FzYWwNCiAgc3J2eXI6Om11dGF0ZShkZW1hbmRhX2luZCA9IGlmZWxzZShpZGFkZSAlaW4lIGMoMjQ6NjQpICYgY29ual9jYXNhbCA9PSAwLCAxLCAwKSwNCiAgICAgICAgICAgICAgICBncnVwb19ldGFyaW8gPSBjYXNlX3doZW4oaWRhZGUgJWluJSBjKDI0OjI5KSB+ICJpZGFkZV8yNF8yOSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYWRlICVpbiUgYygzMDozOSkgfiAiaWRhZGVfMzBfMzkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGFkZSAlaW4lIGMoNDA6NjQpIH4gImlkYWRlXzQwXzY0IiksDQogICAgICAgICAgICAgICAgc3RyYXRhX211ZGFuw6dhPWNhc2Vfd2hlbihFMjI9PTF+InNpbSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRTIyPT0yfiJOw6NvIixUUlVFfiJOw6NvIFNhYmUgLyBOw6NvIHNlIEFwbGljYSIpKSAlPiUjQ2xhc3NpZmljYSBmYWl4YXMgZXTDoXJpYXMgZGUgaW50ZXJlc3NlDQogIHNydnlyOjpncm91cF9ieShncnVwb19ldGFyaW8sIGdydXBvX3BkYWRBLHN0cmF0YV9tdWRhbsOnYSkgJT4lDQogIHNydnlyOjpzdW1tYXJpc2UoZGVtYW5kYSA9IHN1cnZleV90b3RhbChkZW1hbmRhX2luZCwgdmFydHlwZSA9IGMoImN2IiwgImNpIiksIG5hLnJtID0gVFJVRSkpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkgJT4lICAjQ29udmVydGUgcGFyYSBkYXRhLmZyYW1lIGUgYXBsaWNhIGZpbHRybyBkZSBwcmVjaXPDo28NCiAgbXV0YXRlKGRlbWFuZGE9aWZlbHNlKGRlbWFuZGFfY3Y+MC4yNSxOQSxkZW1hbmRhKSkNCmRlbWFuZGFfc3RyYXRhX211ZGFuw6dhICU+JSBmaWx0ZXIoZ3J1cG9fcGRhZEE9PSJERiIpDQoNCmRlbWFuZGFfc3RyYXRhX211ZGFuw6dhIDwtDQogIG1lcmdlKGRlbWFuZGFfc3RyYXRhX211ZGFuw6dhLCB0eF9jaGVmaWFfaWRhZGUsDQogICAgICAgIGJ5ID0gYygiZ3J1cG9fZXRhcmlvIiwgImdydXBvX3BkYWRBIikpICU+JQ0KICAgIG11dGF0ZShkZW1hbmRhX2FqdXN0YWRhID0gZGVtYW5kYSAqIHR4X2NoZWZpYSkgJT4lDQogICAgc2VsZWN0KGdydXBvX2V0YXJpbyxncnVwb19wZGFkQSxzdHJhdGFfbXVkYW7Dp2EsZGVtYW5kYV9hanVzdGFkYSxkZW1hbmRhLHR4X2NoZWZpYSxwb3BfdG90YWwpIA0KZGVtYW5kYV9zdHJhdGFfbXVkYW7Dp2EgJT4lIGZpbHRlcihncnVwb19wZGFkQT09IkRGIikgJT4lICNmaWx0ZXIoIXN0cmF0YV9tdWRhbsOnYT09Ik7Do28gU2FiZSAvIE7Do28gc2UgQXBsaWNhIikgJT4lDQogIGFkb3JuX3RvdGFscygpDQpkZW1hbmRhX3N0cmF0YV9tdWRhbsOnYSAlPiUgZmlsdGVyKGdydXBvX3BkYWRBPT0iREYiKSAlPiUgZmlsdGVyKCFzdHJhdGFfbXVkYW7Dp2E9PSJOw6NvIFNhYmUgLyBOw6NvIHNlIEFwbGljYSIpICU+JSANCiAgc2VsZWN0KGdydXBvX2V0YXJpbyxncnVwb19wZGFkQSxzdHJhdGFfbXVkYW7Dp2EsIGRlbWFuZGFfYWp1c3RhZGEpICU+JSANCiAgc3ByZWFkKHN0cmF0YV9tdWRhbsOnYSwgZGVtYW5kYV9hanVzdGFkYSkgJT4lICBhZG9ybl90b3RhbHMod2hlcmUgPSAicm93IikgJT4lICAgDQogIG11dGF0ZShwZXJjZW50dWFsID0gKHNpbS8oc2ltK07Do28pKSkgICU+JSANCiAgICB3cml0ZV9zaGVldCgiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMXNDSjdwX0dpdEpYRHc0UHVZTllBQjVZajdlT3NlQ0czZlh5Q3FfV3NIaXMvZWRpdD91c3A9c2hhcmluZyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQ9IkRlbWFuZGEgcG9yIEludGVuw6fDo28gZGUgZm9ybWFyIG5vdm8gZG9taWNpbGlhIikNCg0KYGBgDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZJTSANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpgYGANCg0KDQo=