Indentação e RMarkdown

Você deve ter percebido que, em listas numeradas, não é preciso começar cada item com o número correto. Basta iniciar, por exemplo, com “\(1\).”.

Depois do primeiro parágrafo do item, todo texto que estiver indentado com \(3\) ou mais espaços vai fazer parte do mesmo item numerado.

Qualquer texto (ou chunk) com indentação menor que \(3\) espaços vai quebrar a sequência dos itens numerados.

Foi por isso que vários dos arquivos entregues pelos alunos tinham listas onde todos os itens eram numerados com \(1\).

Além disso, no RStudio, os chunks só são reconhecidos e executados com ctrl-enter se estiverem sem indentação ou se estiverem indentados com \(4\) espaços.

Conclusão: para que o HTML seja gerado corretamente e para que você ainda consiga executar os chunks interativamente, com ctrl-enter, a indentação precisa ser feita como na figura:

Da linha \(247\) até a linha \(269\), tudo pertence ao primeiro item da lista numerada; por isso, todo este texto está indentado no mínimo \(3\) espaços.

O chunk da linha \(257\) à linha \(269\) está indentado \(4\) espaços, para que o RStudio o reconheça.

Na linha \(271\), começa o próximo item da lista, sem indentação, que será numerado como \(2\).

AVISO

INSTRUÇÕES

1 Sumário

Nesta atividade, você vai trabalhar com o conjunto de dados atletas.

  1. Entre ?atletas para ver a documentação.

  2. Use glimpse(atletas) para ver a estrutura da tibble.

  3. Use a função dfSummary, do pacote summaryTools, para ver um sumário mais detalhado da tibble.

    atletas %>% dfSummary() %>% print(method = 'render')
    Variável Estatísticas / Valores Freqs (% de Válidos) Grafo Faltante
    id [numeric]
    Média (dp) : 68046,7 (39166,6)
    mín < mediana < máx:
    1 < 68436 < 135568
    IQE (CV) : 67796 (0,6)
    97456 valores distintos 0 (0,0%)
    nome [character]
    1. Joseph "Josy" Stoffel
    2. Takashi Ono
    3. Andreas Wecker
    4. Johann "Hans" Sauter
    5. Michel Mathiot
    6. Karl Tore William Thoress
    7. Michael Fred Phelps, II
    8. Yordan Yovchev Yovchev
    9. Oksana Aleksandrovna Chus
    10. Fabian Hambchen
    [ 96886 outros ]
    38(0,0%)
    33(0,0%)
    32(0,0%)
    31(0,0%)
    31(0,0%)
    30(0,0%)
    30(0,0%)
    30(0,0%)
    29(0,0%)
    26(0,0%)
    185759(99,8%)
    0 (0,0%)
    sexo [character]
    1. F
    2. M
    57652(31,0%)
    128417(69,0%)
    0 (0,0%)
    idade [numeric]
    Média (dp) : 25,2 (5,9)
    mín < mediana < máx:
    11 < 24 < 84
    IQE (CV) : 7 (0,2)
    67 valores distintos 3102 (1,7%)
    altura [numeric]
    Média (dp) : 175,5 (11)
    mín < mediana < máx:
    127 < 175 < 226
    IQE (CV) : 15 (0,1)
    95 valores distintos 21780 (11,7%)
    peso [numeric]
    Média (dp) : 70,6 (14,9)
    mín < mediana < máx:
    25 < 70 < 214
    IQE (CV) : 19 (0,2)
    219 valores distintos 22124 (11,9%)
    pais [character]
    1. USA
    2. GBR
    3. AUS
    4. FRA
    5. ITA
    6. CAN
    7. JPN
    8. GER
    9. HUN
    10. URS
    [ 215 outros ]
    10541(5,7%)
    7647(4,1%)
    6888(3,7%)
    6837(3,7%)
    6483(3,5%)
    5941(3,2%)
    5685(3,1%)
    5571(3,0%)
    4843(2,6%)
    4622(2,5%)
    121011(65,0%)
    0 (0,0%)
    ano [numeric]
    Média (dp) : 1987,2 (20,1)
    mín < mediana < máx:
    1948 < 1992 < 2016
    IQE (CV) : 32 (0)
    18 valores distintos 0 (0,0%)
    cidade [character]
    1. London
    2. Sydney
    3. Atlanta
    4. Rio de Janeiro
    5. Beijing
    6. Athina
    7. Barcelona
    8. Seoul
    9. Munich
    10. Los Angeles
    [ 8 outros ]
    19325(10,4%)
    13821(7,4%)
    13780(7,4%)
    13688(7,4%)
    13602(7,3%)
    13443(7,2%)
    12977(7,0%)
    12037(6,5%)
    10304(5,5%)
    9454(5,1%)
    53638(28,8%)
    0 (0,0%)
    esporte [character]
    1. Athletics
    2. Gymnastics
    3. Swimming
    4. Cycling
    5. Rowing
    6. Shooting
    7. Fencing
    8. Canoeing
    9. Wrestling
    10. Sailing
    [ 27 outros ]
    31500(16,9%)
    22543(12,1%)
    21244(11,4%)
    8918(4,8%)
    8831(4,7%)
    8052(4,3%)
    7643(4,1%)
    6028(3,2%)
    5885(3,2%)
    5606(3,0%)
    59819(32,1%)
    0 (0,0%)
    evento [character]
    1. Football Men's Football
    2. Hockey Men's Hockey
    3. Basketball Men's Basketba
    4. Water Polo Men's Water Po
    5. Cycling Men's Road Race,
    6. Handball Men's Handball
    7. Volleyball Men's Volleyba
    8. Gymnastics Men's Individu
    9. Rowing Men's Coxed Eights
    10. Gymnastics Men's Parallel
    [ 396 outros ]
    4493(2,4%)
    3495(1,9%)
    3081(1,7%)
    2714(1,5%)
    2467(1,3%)
    2159(1,2%)
    1861(1,0%)
    1764(0,9%)
    1749(0,9%)
    1746(0,9%)
    160540(86,3%)
    0 (0,0%)
    medalha [character]
    1. Bronze
    2. Gold
    3. Silver
    8955(34,2%)
    8690(33,2%)
    8542(32,6%)
    159882 (85,9%)

    Gerado por summarytools 1.0.0 (R versão 4.1.2)
    2022-01-13

2 Idades e esportes

Nesta seção, você vai explorar os dados, mas sem gerar gráficos.

  1. Qual a idade dos atletas mais jovens? Quem são? De onde são? Em que ano competiram? Em que esportes? Ganharam medalha? Use a função slice_min.

    atletas %>% 
      slice_min(idade) %>% 
      select(id, nome, idade, pais, ano, esporte, medalha) %>% 
      arrange(ano)
  2. Qual a idade dos atletas mais velhos? Quem são? De onde são? Em que ano competiram? Em que esportes? Ganharam medalha? Use a função slice_max.

    atletas %>% 
      slice_max(idade) %>% 
      select(id, nome, idade, pais, ano, esporte, medalha) %>% 
      arrange(ano)
  3. Aposto que você não sabia que havia competição de artes nas Olimpíadas! Até que ano isto aconteceu?

    atletas %>% 
      filter(esporte == 'Art Competitions') %>% 
      pull(ano) %>% 
      max()
    ## [1] 1948
  4. Quais eram os eventos das competições de artes? Use a função distinct.

    atletas %>% 
      filter(esporte == 'Art Competitions') %>% 
      distinct(evento) %>% 
      arrange(evento)
  5. Elimine do data frame as linhas relativas a artes.

    atletas <- 
      atletas %>% 
        filter(esporte != 'Art Competitions')
  6. Quais as idades mínima e máxima agora?

    atletas %>% 
      pull(idade) %>% 
      summary()
    ##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
    ##   11,00   21,00   24,00   25,13   28,00   71,00    3025
  7. Quais os dados dos atletas que têm a idade máxima?

    atletas %>% 
      slice_max(idade) %>% 
      select(id, nome, idade, pais, ano, esporte, medalha) %>% 
      arrange(ano)
  8. Quais os atletas mais jovens a ganhar medalha? De onde são? Em que anos ganharam? Em que esportes? Quais medalhas?

    atletas %>% 
      filter(!is.na(medalha)) %>% 
      slice_min(idade) %>% 
      select(nome, idade, pais, ano, esporte, medalha)
  9. Quais os atletas mais velhos a ganhar medalha? De onde são? Em que anos ganharam? Em que esportes? Quais medalhas?

    atletas %>% 
      filter(!is.na(medalha)) %>% 
      slice_max(idade) %>% 
      select(nome, idade, pais, ano, esporte, medalha)

3 Scatterplots

  1. Usando group_by e summarize, crie o data frame medalhas_atletas com as colunas pais, ano, atletas (total de participações do país naquele ano) e medalhas (total de medalhas do país naquele ano). Descarte os registros onde o número de medalhas é menor que \(50\).

    O código abaixo conta os ids dos atletas, com atletas = n_distinct(id), cada id apenas uma vez.

    Se você usar atletas = n(), cada participação de cada atleta será contada.

    Considerei as duas alternativas como corretas.

    medalhas_atletas <- atletas %>% 
      group_by(pais, ano) %>% 
      summarize(
        atletas = n_distinct(id),
        medalhas = sum(!is.na(medalha)),
        .groups = 'drop'
      ) %>% 
      filter(medalhas >= 50) %>% 
      arrange(pais)
    
    medalhas_atletas
  2. Gere um scatterplot de número de medalhas por número de participações. Use geom_smooth para traçar uma reta de regressão. Comente o resultado.

    sp_medalha_atletas <- medalhas_atletas %>% 
      ggplot(aes(atletas, medalhas)) +
        geom_point(alpha = .3) +
        geom_smooth(se = FALSE, method = 'lm')
    
    sp_medalha_atletas
    ## `geom_smooth()` using formula 'y ~ x'

  3. Facete o scatterplot anterior por ano. Disponha os subgráficos em \(3\) linhas e \(6\) colunas.

    sp_medalha_atletas +
      facet_wrap(~ano, nrow = 3)
    ## `geom_smooth()` using formula 'y ~ x'

  4. Como você interpreta as diferentes quantidades de pontos em cada subgráfico?

    • Ao longo dos anos, a quantidade de países que ganharam \(50\) ou mais medalhas aumentou.

    • Ao longo dos anos, a quantidade de participações de alguns países aumentou.

    • Ao longo dos anos, a variação da quantidade de participações aumentou. Em \(1948\), o gráfico mostra entre \(100\) e \(300\) participações. Em \(2016\), foram entre \(100\) e \(600\) participações, aproximadamente.

  5. Houve uma única vez em que um país ganhou mais de \(400\) medalhas em um ano. Descubra o que aconteceu para facilitar essa ocorrência.

    Em \(1980\), os jogos foram realizados em Moscou, na União Soviética, e os Estados Unidos comandaram um boicote aos jogos por motivos políticos, fazendo com que \(69\) países deixassem de enviar atletas.

    Em \(1984\), foi a vez de a União Soviética e outros países comunistas boicotarem os jogos de Los Angeles, mas o gráfico de \(1984\) mostra que os efeitos não foram tão drásticos quanto os do boicote de \(1980\).

  6. Considere agora apenas os registros onde medalhas é maior que \(200\). Faça um scatterplot de número de medalhas por número de participações, onde cada ponto é colorido de acordo com o país. Aumente o tamanho de todos os pontos para facilitar a leitura. Não gere a reta de regressão. Comente o resultado.

    medalhas_atletas %>% 
      filter(medalhas > 200) %>% 
      ggplot(aes(atletas, medalhas, color = pais)) +
        geom_point(size = 4)

    Considerando apenas os países e os anos onde o país ganhou mais de \(200\) medalhas:

    • Apenas os Estados Unidos tiveram mais de \(500\) participações, com quantidade de medalhas entre \(200\) e \(350\), aproximadamente.

    • A União Soviética teve entre \(350\) e \(500\) participações, mas, com exceção das quase \(450\) medalhas em Moscou \(1980\), chegou no máximo a \(300\) medalhas.

    • Rússia (EUN) e Alemanha Oriental (GDR) aparecem com números pouco expressivos em comparação com Estados Unidos e União Soviética.

4 Histogramas

  1. Usando o data frame atletas (sem as artes), gere um histograma das idades de todos os atletas, com classes de \(5\) anos de largura.

    breaks <- seq(10, 75, 5)
    
    hist_idades <- atletas %>% 
      ggplot(aes(idade)) +
        geom_histogram(breaks = breaks) +
        scale_x_continuous(breaks = breaks) +
        scale_y_continuous(labels = label_number_si()) +
        labs(
          y = NULL,
          title = paste(
            'Idades dos atletas em olimpíadas desde', 
            ano_inicial
          )
        )
    
    hist_idades
    ## Warning: Removed 3025 rows containing non-finite values (stat_bin).

  2. Faça a mesma coisa, mas apenas para idades maiores ou iguais a \(55\) anos.

    breaks <- seq(55, 75, 5)
    
    hist_idades_velhos <- atletas %>% 
      filter(idade >= 55) %>% 
      ggplot(aes(idade)) +
        geom_histogram(breaks = breaks) +
        scale_x_continuous(breaks = breaks) +
        scale_y_continuous(labels = label_number_si()) +
        labs(
          y = NULL,
          title = paste('Idades dos atletas em olimpíadas desde', ano_inicial),
          subtitle = '(atletas com 55 anos ou mais)'
        )
    
    hist_idades_velhos

  3. Gere dois histogramas de todas as idades, por sexo, com classes de \(5\) anos de largura. Use facet_wrap.

    hist_idades +
      labs(subtitle = 'por sexo') +
      facet_wrap(~sexo)
    ## Warning: Removed 3025 rows containing non-finite values (stat_bin).

  4. Comente o resultado, sobretudo nas idades abaixo de \(20\) anos. Por que você acha que acontece isso? Analise os dados como você achar mais adequado para confirmar ou refutar sua hipótese.

    • Há muito mais homens que mulheres, no total e na maioria das faixas etárias.

    • Uma faixa etária onde há muito mais mulheres do que homens é a de \(10\) a \(15\) anos.

    • Mais abaixo, você vai constatar que isso é por causa da ginástica rítmica, onde competem apenas mulheres, grande parte delas muito jovens.

  5. Quais são os esportes com a menor idade média e a maior idade média? Use group_by e summarize. Ignore os valores NA na hora de computar a média (veja a ajuda da função mean).

    extremos <- atletas %>% 
      group_by(esporte) %>% 
      summarize(media = mean(idade, na.rm = TRUE)) %>% 
      arrange(media) %>% 
      slice(c(1, n()))
    
    extremos
  6. Quais são os esportes com a menor idade mediana e a maior idade mediana? Use group_by e summarize. Ignore os valores NA na hora de computar a mediana (veja a ajuda da função median).

    atletas %>% 
      group_by(esporte) %>% 
      summarize(mediana = median(idade, na.rm = TRUE)) %>% 
      arrange(mediana) %>% 
      slice(c(1, n()))
  7. Usando somente os atletas dos esportes com menor idade média e maior idade média (achados acima), gere dois histogramas das idades, por esporte, com classes de \(5\) anos. Use facet_wrap.

    breaks <- seq(10, 90, 5)
    esportes <- extremos %>% pull(esporte)
    
    atletas %>% 
      filter(esporte %in% esportes) %>% 
      ggplot(aes(idade)) +
        geom_histogram(breaks = breaks) +
        scale_x_continuous(breaks = breaks) +
        scale_y_continuous(labels = label_number_si()) +
        labs(
          y = NULL,
          title = paste('Idades dos atletas em olimpíadas desde', ano_inicial),
          subtitle = 'nos esportes com maior e menor idades médias'
        ) +
        facet_wrap(~esporte)
    ## Warning: Removed 91 rows containing non-finite values (stat_bin).

  8. Repita o item anterior, desta vez usando facet_grid em vez de facet_wrap, para gerar \(4\) histogramas, cada um com um esporte e um sexo. Comente o resultado.

    breaks <- seq(10, 90, 5)
    esportes <- extremos %>% pull(esporte)
    
    atletas %>% 
      filter(esporte %in% esportes) %>% 
      ggplot(aes(idade)) +
        geom_histogram(breaks = breaks) +
        scale_x_continuous(breaks = breaks) +
        scale_y_continuous(labels = label_number_si()) +
        labs(
          y = NULL,
          title = paste('Idades dos atletas em olimpíadas desde', ano_inicial),
          subtitle = 'por sexo, nos esportes com maior e menor idades médias'
        ) +
        facet_grid(cols = vars(sexo), rows = vars(esporte))
    ## Warning: Removed 91 rows containing non-finite values (stat_bin).

5 Boxplots

  1. Gere boxplots lado a lado, um boxplot por ano, para as alturas de todos os atletas. Comente o resultado.

    box_alturas <- atletas %>% 
      ggplot(aes(ano, altura, group = ano)) +
        geom_boxplot()
    
    box_alturas
    ## Warning: Removed 21310 rows containing non-finite values (stat_boxplot).

    • A mediana se manteve próxima de \(175\)cm ao longo dos anos.

    • A variação aumentou nos anos \(60\).

  2. Repita o item anterior, facetando por sexo. Use coord_flip. Comente os resultados.

    box_alturas +
      facet_wrap(~sexo) +
      coord_flip()
    ## Warning: Removed 21310 rows containing non-finite values (stat_boxplot).

    • A mediana da altura das mulheres aumentou desde os anos \(50\).

    • A mediana da altura dos homens aumentou desde os anos \(60\).

    • Estas mudanças não apareciam no gráfico do item anterior porque estávamos considerando homens e mulheres em conjunto.

  3. Gere dois boxplots lado a lado, um para os brasileiros (BRA), um para os holandeses (NED), para as alturas dos atletas. Comente o resultado.

    box_bra_ned <- atletas %>% 
      filter(pais %in% c('BRA', 'NED')) %>% 
      ggplot(aes(pais, altura, group = pais)) +
        geom_boxplot()
    
    box_bra_ned
    ## Warning: Removed 811 rows containing non-finite values (stat_boxplot).

    • A mediana e os quartis das alturas dos holandeses (considerando homens e mulheres em conjunto) são um pouco maiores do que os valores correspondentes dos brasileiros.

    • Curiosamente, existe um brasileiro mais alto do que todos os holandeses.

  4. Repita o item anterior, facetando por sexo. Comente os resultados.

    box_bra_ned +
      facet_wrap(~sexo)
    ## Warning: Removed 811 rows containing non-finite values (stat_boxplot).

    • Valem as mesmas observações do item anterior, quando examinamos os dados separados por sexo.

    • Existe uma mulher brasileira mais alta que todas as mulheres holandesas.

6 Gráficos de barras

  1. Gere um gráfico de barras horizontais com as quantidades de medalhas de ouro dos \(10\) países que ganharam mais medalhas de ouro nas olimpíadas de \(2016\). Coloque as barras em ordem decrescente.

    atletas %>% 
      filter(ano == 2016 & medalha == 'Gold') %>% 
      group_by(pais) %>% 
      summarize(ouro = n()) %>% 
      slice_max(ouro, n = 10) %>% 
      ggplot(aes(fct_reorder(pais, ouro), ouro)) +
        geom_col() +
        labs(
          x = NULL
        ) +
        coord_flip()

  2. Gere um gráfico de barras para as quantidades totais de medalhas do Brasil, por ano. No eixo \(x\), coloque rótulos para todos os anos de Olimpíada desde \(1948\). Para os rótulos ficarem legíveis, use coord_flip.

    atletas %>% 
      filter(pais == 'BRA' & !is.na(medalha)) %>% 
      ggplot(aes(ano)) +
        geom_bar() +
        labs(y = NULL) +
        scale_x_continuous(breaks = seq(ano_inicial, 2020, 4)) +
        coord_flip()

  3. Repita o item anterior, com duas barras lado a lado por ano, uma para cada sexo. O que você nota de estranho no resultado?

    atletas %>% 
      filter(pais == 'BRA' & !is.na(medalha)) %>% 
      ggplot(aes(ano, fill = sexo)) +
        geom_bar(position = 'dodge') +
        labs(y = NULL) +
        scale_x_continuous(breaks = seq(ano_inicial, 2020, 4)) +
        coord_flip()

    A primeira vez em que uma mulher brasileira ganhou medalha foi em \(1996\)!

DESAFIO: Qual foi o primeiro ano em que cada país teve uma atleta do sexo feminino ganhando uma medalha? Construa um data frame. O resultado terá \(98\) linhas.

atletas %>% 
  filter(sexo == 'F') %>% 
  group_by(pais, ano) %>% 
  summarize(
    medalhas = sum(!is.na(medalha)),
    acumulado = cumsum(medalhas),
    .groups = 'drop'
  ) %>% 
  filter(acumulado > 0) %>% 
  group_by(pais) %>% 
  summarize(ano_primeira_medalha_f = min(ano)) %>% 
  arrange(desc(ano_primeira_medalha_f))

Uma solução mais simples, sem soma acumulada, semelhante à apresentada por alguns alunos:

atletas %>% 
  filter(sexo == 'F', !is.na(medalha)) %>% 
  select(pais, ano) %>% 
  group_by(pais) %>% 
  slice_min(ano) %>% 
  distinct() %>% 
  ungroup()

7 Gráficos de linha

  1. Faça um gráfico de linha com os totais de atletas que o Brasil enviou a cada Olimpíada. Sobreponha pontos à linha. No eixo \(x\), coloque rótulos para todos os anos de Olimpíada desde \(1948\). Para os rótulos ficarem legíveis, gire-os em \(45\) graus.

    desempenho_brasil <- atletas %>% 
      filter(pais == 'BRA') %>% 
      group_by(ano) %>% 
      summarize(
        n_atletas = n(),
        n_medalhas = sum(!is.na(medalha)),
        perc = n_medalhas / n_atletas
      )
    
    linha_atletas <- desempenho_brasil %>% 
      ggplot(aes(ano)) +
        geom_line(aes(y = n_atletas, color = 'atletas')) +
        geom_point(aes(y = n_atletas, color = 'atletas')) +
        scale_x_continuous(breaks = seq(ano_inicial, 2020, 4)) +
        theme(axis.text.x = element_text(angle = 45)) +
        labs(
          color = NULL,
          y = NULL
        )
    
    linha_atletas

  2. Acrescente ao gráfico do item anterior uma linha de outra cor, também com pontos, com as quantidades de medalhas obtidas pelo Brasil a cada ano. As cores das linhas devem aparecer na legenda, com as identificações “atletas” e “medalhas”.

    linha_atletas +
      geom_line(aes(y = n_medalhas, color = 'medalhas')) +
      geom_point(aes(y = n_medalhas, color = 'medalhas'))

  3. Calcule, para cada ano, o percentual de medalhas ganhas em relação ao total de participações de atletas brasileiros. Gere um gráfico de linha com pontos sobrepostos. No eixo \(x\), coloque rótulos para todas os anos de Olimpíada desde \(1948\). Para os rótulos ficarem legíveis, gire-os em \(45\) graus. Use o pacote scales para rotular o eixo \(y\) com percentagens.

    desempenho_brasil %>% 
      ggplot(aes(ano, perc)) +
        geom_line() +
        geom_point() +
        scale_y_continuous(labels = label_percent()) +
        labs(
          y = NULL
        ) +
        scale_x_continuous(breaks = seq(ano_inicial, 2020, 4)) +
        theme(axis.text.x = element_text(angle = 45))

LS0tCnRpdGxlOiAnSm9nb3MgT2zDrW1waWNvcyBkZSBWZXLDo286IHNvbHXDp8O1ZXMnCmF1dGhvcjogJ2ZuYXVmZWwnCmRhdGU6ICcwNi8xMi8yMDIxICh2LiBgciBmb3JtYXQoU3lzLkRhdGUoKSwgIiVkLyVtLyVZIilgKScKbGFuZzogJ3B0JwpvdXRwdXQ6IHJtZGZvcm1hdDo6Zm5hdWZlbF9ybWRfZm9ybWF0CiMgVG8gaW5zdGFsbCB0aGlzIGZvcm1hdCwgZW50ZXIKIyAgIGluc3RhbGwucGFja2FnZXMoImRldnRvb2xzIikKIyAgIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZm5hdWZlbC9ybWRmb3JtYXQiKQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKb3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsIAogICMgY29sbGFwc2UgPSBUUlVFLAogICMgY2FjaGUgPSBUUlVFLAogIG91dC53aWR0aCA9ICI5MCUiLAogIGZpZy5hbGlnbiA9ICdjZW50ZXInLAogIGZpZy53aWR0aCA9IDcsCiAgZmlnLnNob3cgPSAiaG9sZCIKKQoKIyBTdXByZXNzIGNyYXlvbiBvdXRwdXQKb3B0aW9ucyhjcmF5b24uZW5hYmxlZCA9IEZBTFNFKQoKb3B0aW9ucygKICAjIEF2b2lkIHNjaWVudGlmaWMgbm90YXRpb24KICBzY2lwZW4gPSAxNSwKICAjIFVzZSBhIGNvbW1hIGFzIGRlY2ltYWwgc2VwYXJhdG9yCiAgT3V0RGVjID0gJywnLAogICMgTnVtYmVyIG9mIGRlY2ltYWwgZGlnaXRzIGZvciBudW1iZXJzIHByb2R1Y2VkIGJ5IGlubGluZSBSIGNvZGUKICBmbWRpZ2l0cyA9IDIKKQoKIyBVc2VmdWwgbGlicmFyaWVzCmxpYnJhcnkoa2FibGVFeHRyYSkKb3B0aW9ucyhrbml0ci5rYWJsZS5OQSA9ICcnKQoKIyBGb3IgbmljZSBkYXRhZnJhbWUgc3VtbWFyaWVzCmxpYnJhcnkoc3VtbWFyeXRvb2xzKQpzdF9vcHRpb25zKAogIHBsYWluLmFzY2lpID0gRkFMU0UsCiAgZGZTdW1tYXJ5LnN0eWxlID0gJ2dyaWQnLAogIGRmU3VtbWFyeS52YXJudW1iZXJzID0gRkFMU0UsCiAgZGZTdW1tYXJ5LnZhbGlkLmNvbCA9IEZBTFNFLAogIGRmU3VtbWFyeS5ncmFwaC5jb2wgPSBpc19odG1sX291dHB1dCgpLAogIGhlYWRpbmdzID0gRkFMU0UsCiAgZGZTdW1tYXJ5LmdyYXBoLm1hZ25pZiA9IDEsCiAgIyB0bXAuaW1nLmRpciA9ICdkc2ltZycsCiAgbGFuZyA9ICdwdCcsCiAgc3VidGl0bGUuZW1waGFzaXMgPSBGQUxTRQopCgojIFRpZHkhCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNjYWxlcykKCiMgVXNlZnVsIGZ1bmN0aW9ucyBwcm92aWRlZCBieSB0aGUgcm1kZm9ybWF0IHBhY2thZ2UKIyAKIyBFeGVjdXRlIAojIAojICAgY2F0KHN5c3RlbS5maWxlKCJybWFya2Rvd24vcmVzb3VyY2VzL2NvbW1vbi5SIiwgcGFja2FnZSA9ICJybWRmb3JtYXQiKSkKIyAKIyB0byBzZWUgdGhlIGxvY2F0aW9uIG9mIHRoZSBmaWxlCnNvdXJjZSgKICBzeXN0ZW0uZmlsZSgKICAgICJybWFya2Rvd24vcmVzb3VyY2VzL2NvbW1vbi5SIiwKICAgIHBhY2thZ2UgPSAicm1kZm9ybWF0IgogICkKKQoKIyBQYXJhIGRlYnVnYXIgcGlwZXMKaWYoIXJlcXVpcmUoVmlld1BpcGVTdGVwcykpCiAgaW5zdGFsbC5wYWNrYWdlcygiVmlld1BpcGVTdGVwcyIpCgojIENhcnJlZ2FyIGRhZG9zIGRhIGF0aXZpZGFkZQpsaWJyYXJ5KE9saW1waWFkYXMpCmFub19pbmljaWFsIDwtIDE5NDgKYGBgCgoKOjo6IHsucm1kaW1wb3J0YW50IGxhdGV4PTF9CgpbKipJbmRlbnRhw6fDo28gZSBSTWFya2Rvd24qKl17LmhsfQoKVm9jw6ogZGV2ZSB0ZXIgcGVyY2ViaWRvIHF1ZSwgZW0gbGlzdGFzIG51bWVyYWRhcywgbsOjbyDDqSBwcmVjaXNvIGNvbWXDp2FyIGNhZGEgaXRlbSBjb20gbyBuw7ptZXJvIGNvcnJldG8uIEJhc3RhIGluaWNpYXIsIHBvciBleGVtcGxvLCBjb20gIiQxJC4iLgoKRGVwb2lzIGRvIHByaW1laXJvIHBhcsOhZ3JhZm8gZG8gaXRlbSwgdG9kbyB0ZXh0byBxdWUgZXN0aXZlciBpbmRlbnRhZG8gY29tICQzJCBvdSBtYWlzIGVzcGHDp29zIHZhaSBmYXplciBwYXJ0ZSBkbyBtZXNtbyBpdGVtIG51bWVyYWRvLgoKUXVhbHF1ZXIgdGV4dG8gKG91ICpjaHVuayopIGNvbSBpbmRlbnRhw6fDo28gbWVub3IgcXVlICQzJCBlc3Bhw6dvcyBbdmFpIHF1ZWJyYXIgYSBzZXF1w6puY2lhIGRvcyBpdGVucyBudW1lcmFkb3MuXXsuaGx9CgpGb2kgcG9yIGlzc28gcXVlIHbDoXJpb3MgZG9zIGFycXVpdm9zIGVudHJlZ3VlcyBwZWxvcyBhbHVub3MgdGluaGFtIGxpc3RhcyBvbmRlIHRvZG9zIG9zIGl0ZW5zIGVyYW0gbnVtZXJhZG9zIGNvbSAkMSQuCgpBbMOpbSBkaXNzbywgbm8gUlN0dWRpbywgW29zICpjaHVua3MqIHPDsyBzw6NvIHJlY29uaGVjaWRvcyBlIGV4ZWN1dGFkb3MgY29tIGN0cmwtZW50ZXIgc2UgZXN0aXZlcmVtIHNlbSBpbmRlbnRhw6fDo28gb3Ugc2UgZXN0aXZlcmVtIGluZGVudGFkb3MgY29tICQ0JCBlc3Bhw6dvcy5dey5obH0KCkNvbmNsdXPDo286IHBhcmEgcXVlIG8gSFRNTCBzZWphIGdlcmFkbyBjb3JyZXRhbWVudGUgZSBwYXJhIHF1ZSB2b2PDqiBhaW5kYSBjb25zaWdhIGV4ZWN1dGFyIG9zICpjaHVua3MqIGludGVyYXRpdmFtZW50ZSwgY29tIGN0cmwtZW50ZXIsIGEgaW5kZW50YcOnw6NvIHByZWNpc2Egc2VyIGZlaXRhIGNvbW8gbmEgZmlndXJhOgoKIVtdKGNodW5rcy5wbmcpCgpEYSBsaW5oYSAkMjQ3JCBhdMOpIGEgbGluaGEgJDI2OSQsIHR1ZG8gcGVydGVuY2UgYW8gcHJpbWVpcm8gaXRlbSBkYSBsaXN0YSBudW1lcmFkYTsgcG9yIGlzc28sIHRvZG8gZXN0ZSB0ZXh0byBlc3TDoSBpbmRlbnRhZG8gbm8gbcOtbmltbyAkMyQgZXNwYcOnb3MuCgpPICpjaHVuayogZGEgbGluaGEgJDI1NyQgw6AgbGluaGEgJDI2OSQgZXN0w6EgaW5kZW50YWRvICQ0JCBlc3Bhw6dvcywgcGFyYSBxdWUgbyBSU3R1ZGlvIG8gcmVjb25oZcOnYS4KCk5hIGxpbmhhICQyNzEkLCBjb21lw6dhIG8gcHLDs3hpbW8gaXRlbSBkYSBsaXN0YSwgc2VtIGluZGVudGHDp8OjbywgcXVlIHNlcsOhIG51bWVyYWRvIGNvbW8gJDIkLgoKOjo6Cgo6Ojogey5ybWR3YXJuaW5nIGxhdGV4PTF9CgpbKipBVklTTyoqXXsuaGx9CgoqIE9zIGRhZG9zIHVzYWRvcyBwYXJhIGVzdGEgbGlzdGEgZm9yYW0gYmFzZWFkb3MgZW0gaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9oZWVzb28zNy8xMjAteWVhcnMtb2Ytb2x5bXBpYy1oaXN0b3J5LWF0aGxldGVzLWFuZC1yZXN1bHRzCgoqIEVzdGVzLCBwb3Igc3VhIHZleiwgZm9yYW0gcmFzcGFkb3MgZGUgaHR0cDovL3d3dy5zcG9ydHMtcmVmZXJlbmNlLmNvbS8sIHVzYW5kbyBvIGPDs2RpZ28gUiBlbSBodHRwczovL2dpdGh1Yi5jb20vcmdyaWZmMjMvT2x5bXBpY19oaXN0b3J5L2Jsb2IvbWFzdGVyL1Ivb2x5bXBpY3MlMjBzY3JhcGUuUiBlIGVtIGh0dHBzOi8vZ2l0aHViLmNvbS9yZ3JpZmYyMy9PbHltcGljX2hpc3RvcnkvYmxvYi9tYXN0ZXIvUi9vbHltcGljcyUyMHdyYW5nbGUuUgoKKiBRdWFuZG8gdm9jw6ogZm9yIGNhbGN1bGFyIHRvdGFpcyBkZSBtZWRhbGhhcyBwb3IgcGHDrXMsIHZhaSBjaGVnYXIgYSB2YWxvcmVzIG1haW9yZXMgZG8gcXVlIG9zIHZlcmRhZGVpcm9zLiBQb3IgZXhlbXBsbywgW2RlIGFjb3JkbyBjb20gYSB3aWtpcMOpZGlhXShodHRwczovL3B0Lndpa2lwZWRpYS5vcmcvd2lraS9MaXN0YV9kZV9tZWRhbGhhc19icmFzaWxlaXJhc19ub3NfSm9nb3NfT2wlQzMlQURtcGljb3MpLCBvIEJyYXNpbCBudW5jYSBnYW5ob3UgbWFpcyBxdWUgJDIxJCBtZWRhbGhhcyAoZGUgcXVhbHF1ZXIgdGlwbykgZW0gdW1hIG9saW1ww61hZGEuCgoqIE8gbW90aXZvIHBhcmEgaXN0byDDqSBxdWUgW2VzdGUgY29uanVudG8gZGUgZGFkb3MgdGVtIGNvbW8gdW5pZGFkZXMgb3MgYXRsZXRhc117LmhsfS4gRW0gZXNwb3J0ZXMgY29sZXRpdm9zLCBjb21vIGZ1dGVib2wsIFt1bSBwYcOtcyBnYW5oYXIgdW1hIG1lZGFsaGEgw6kgcmVnaXN0cmFkbyBuZXN0ZSAqZGF0YSBmcmFtZSogY29tbyBjYWRhIGF0bGV0YSBkYSBlcXVpcGUgZ2FuaGFuZG8gdW1hIG1lZGFsaGEuXXsuaGx9CgoqIENvbmNsdXPDo286IG5vcyByZXN1bHRhZG9zLCBvcyB0b3RhaXMgZGUgbWVkYWxoYXMgY29udGFtIHVtYSBtZWRhbGhhIHBhcmEgY2FkYSBhdGxldGEgZGEgZXF1aXBlIHF1ZSBnYW5ob3UgbWVkYWxoYS4gT3MgZGFkb3MgbsOjbyBlc3TDo28gZXJyYWRvczsgc8OzIGVzdMOjbyBlc3RydXR1cmFkb3MgZGUgdW0gamVpdG8gcXVlIG7Do28gw6kgbyBub3JtYWwgcGFyYSBjb250YXIgdG90YWlzIGRlIG1lZGFsaGFzIGRvcyBwYcOtc2VzLgoKOjo6Cgo6Ojogey5ybWRpbXBvcnRhbnQgbGF0ZXg9MX0KClsqKklOU1RSVcOHw5VFUyoqXXsuaGx9CgoqIEZpcXVlIMOgIHZvbnRhZGUgcGFyYSBjb25zdWx0YXIgb3MgY29sZWd1aW5oYXMsIG1hcyBuw6NvIGNvcGllIGFzIHJlc3Bvc3RhcyBkZWxlcy4gU2UgZXUgYWNoYXIgcXVlIHZvY8OqIGNvcGlvdSwgdmFtb3MgdGVyIHVtYSBlbnRyZXZpc3RhIHPDrW5jcm9uYSwgcG9yIHbDrWRlbywgY29tIGhvcmFzIGRlIGR1cmHDp8OjbywgcGFyYSBxdWUgZXUgdGVuaGEgY2VydGV6YSBkZSBxdWUgdm9jw6ogc2FiZSBvIHF1ZSBmZXouCgoqIEVudHJlZ3VlIFsodmlhIE1vb2RsZSkgZXN0ZSBhcnF1aXZvIC5SbWRdey5obH0gY29tIHN1YXMgcmVzcG9zdGFzLiBOw6NvIGVzcXVlw6dhIGRlIGNvbG9jYXIgbyBzZXUgbm9tZSBubyBjYW1wbyBgYXV0aG9yYCwgbm8gaW7DrWNpbyBkbyBhcnF1aXZvLgoKKiBBbMOpbSBkbyBhcnF1aXZvIC5SbWQsIGVudHJlZ3VlIHRhbWLDqW0gWyh2aWEgTW9vZGxlKV17LmhsfSB1bSBhcnF1aXZvIGNvbnRlbmRvIHVtIHbDrWRlbyBkZSBubyBtw6F4aW1vIDUgbWludXRvcyBvbmRlIHZvY8OqIGV4cGxpY2EgZW0gZGV0YWxoZXMgYSByZXNvbHXDp8OjbyBkZSB1bWEgZGFzIHN1YXMgcXVlc3TDtWVzLgoKKiBUb2RvcyBvcyBncsOhZmljb3MgZGV2ZW0gc2VyIGZlaXRvcyBjb20gbyBwYWNvdGUgYGdncGxvdDJgLgoKKiBUb2RvcyBvcyBncsOhZmljb3MgZGV2ZW0gaW5jbHVpciB0w610dWxvcywgcsOzdHVsb3MsIGxlZ2VuZGFzIChxdWFuZG8gbmVjZXNzw6FyaWFzKSwgZSBvdXRyb3MgZWxlbWVudG9zIHBhcmEgZmFjaWxpdGFyIGEgY29tcHJlZW5zw6NvLiBJbWFnaW5lIHF1ZSBzZXVzIGdyw6FmaWNvcyBzZXLDo28gcHVibGljYWRvcyBlbSB1bWEgcmV2aXN0YS4KCiogVHJhdGUgbyB0ZXh0byBlIG8gY8OzZGlnbyBjb20gbyBtZXNtbyBjdWlkYWRvLiBVc2UgcGFyw6FncmFmb3Mgbm8gdGV4dG8gZSBpbmRlbnRhw6fDo28gZSBxdWVicmFzIGRlIGxpbmhhIG5vIGPDs2RpZ28uIFtBIGxlZ2liaWxpZGFkZSBkbyB0ZXh0byBlIGRvIGPDs2RpZ28gdGFtYsOpbSBmYXplbSBwYXJ0ZSBkYSBhcHJlc2VudGHDp8Ojby5dey5obH0KCiogQm9tIHRyYWJhbGhvLgoKOjo6CgoKIyBTdW3DoXJpbwoKTmVzdGEgYXRpdmlkYWRlLCB2b2PDqiB2YWkgdHJhYmFsaGFyIGNvbSBvIGNvbmp1bnRvIGRlIGRhZG9zIGBhdGxldGFzYC4KCjEuIEVudHJlIGA/YXRsZXRhc2AgcGFyYSB2ZXIgYSBkb2N1bWVudGHDp8Ojby4KCjEuIFVzZSBgZ2xpbXBzZShhdGxldGFzKWAgcGFyYSB2ZXIgYSBlc3RydXR1cmEgZGEgKnRpYmJsZSouCgoxLiBVc2UgYSBmdW7Dp8OjbyBgZGZTdW1tYXJ5YCwgZG8gcGFjb3RlIGBzdW1tYXJ5VG9vbHNgLCBwYXJhIHZlciB1bSBzdW3DoXJpbyBtYWlzIGRldGFsaGFkbyBkYSAqdGliYmxlKi4KCiAgICBgYGB7cn0KICAgIGF0bGV0YXMgJT4lIGRmU3VtbWFyeSgpICU+JSBwcmludChtZXRob2QgPSAncmVuZGVyJykKICAgIGBgYAoKCiMgSWRhZGVzIGUgZXNwb3J0ZXMKCk5lc3RhIHNlw6fDo28sIHZvY8OqIHZhaSBleHBsb3JhciBvcyBkYWRvcywgbWFzIHNlbSBnZXJhciBncsOhZmljb3MuCgoxLiBRdWFsIGEgaWRhZGUgZG9zIGF0bGV0YXMgbWFpcyBqb3ZlbnM/IFF1ZW0gc8Ojbz8gRGUgb25kZSBzw6NvPyBFbSBxdWUgYW5vIGNvbXBldGlyYW0/IEVtIHF1ZSBlc3BvcnRlcz8gR2FuaGFyYW0gbWVkYWxoYT8gVXNlIGEgZnVuw6fDo28gYHNsaWNlX21pbmAuCgogICAgYGBge3J9CiAgICBhdGxldGFzICU+JSAKICAgICAgc2xpY2VfbWluKGlkYWRlKSAlPiUgCiAgICAgIHNlbGVjdChpZCwgbm9tZSwgaWRhZGUsIHBhaXMsIGFubywgZXNwb3J0ZSwgbWVkYWxoYSkgJT4lIAogICAgICBhcnJhbmdlKGFubykKICAgIGBgYAoKMS4gUXVhbCBhIGlkYWRlIGRvcyBhdGxldGFzIG1haXMgdmVsaG9zPyBRdWVtIHPDo28/IERlIG9uZGUgc8Ojbz8gRW0gcXVlIGFubyBjb21wZXRpcmFtPyBFbSBxdWUgZXNwb3J0ZXM/IEdhbmhhcmFtIG1lZGFsaGE/IFVzZSBhIGZ1bsOnw6NvIGBzbGljZV9tYXhgLgoKICAgIGBgYHtyfQogICAgYXRsZXRhcyAlPiUgCiAgICAgIHNsaWNlX21heChpZGFkZSkgJT4lIAogICAgICBzZWxlY3QoaWQsIG5vbWUsIGlkYWRlLCBwYWlzLCBhbm8sIGVzcG9ydGUsIG1lZGFsaGEpICU+JSAKICAgICAgYXJyYW5nZShhbm8pCiAgICBgYGAKCjEuIEFwb3N0byBxdWUgdm9jw6ogbsOjbyBzYWJpYSBxdWUgaGF2aWEgY29tcGV0acOnw6NvIGRlIGFydGVzIG5hcyBPbGltcMOtYWRhcyEgQXTDqSBxdWUgYW5vIGlzdG8gYWNvbnRlY2V1PwoKICAgIGBgYHtyfQogICAgYXRsZXRhcyAlPiUgCiAgICAgIGZpbHRlcihlc3BvcnRlID09ICdBcnQgQ29tcGV0aXRpb25zJykgJT4lIAogICAgICBwdWxsKGFubykgJT4lIAogICAgICBtYXgoKQogICAgYGBgCgoxLiBRdWFpcyBlcmFtIG9zIGV2ZW50b3MgZGFzIGNvbXBldGnDp8O1ZXMgZGUgYXJ0ZXM/IFVzZSBhIGZ1bsOnw6NvIGBkaXN0aW5jdGAuCgogICAgYGBge3J9CiAgICBhdGxldGFzICU+JSAKICAgICAgZmlsdGVyKGVzcG9ydGUgPT0gJ0FydCBDb21wZXRpdGlvbnMnKSAlPiUgCiAgICAgIGRpc3RpbmN0KGV2ZW50bykgJT4lIAogICAgICBhcnJhbmdlKGV2ZW50bykKICAgIGBgYAoKMS4gRWxpbWluZSBkbyAqZGF0YSBmcmFtZSogYXMgbGluaGFzIHJlbGF0aXZhcyBhIGFydGVzLgoKICAgIGBgYHtyfQogICAgYXRsZXRhcyA8LSAKICAgICAgYXRsZXRhcyAlPiUgCiAgICAgICAgZmlsdGVyKGVzcG9ydGUgIT0gJ0FydCBDb21wZXRpdGlvbnMnKQogICAgYGBgCgoKMS4gUXVhaXMgYXMgaWRhZGVzIG3DrW5pbWEgZSBtw6F4aW1hIGFnb3JhPwoKICAgIGBgYHtyfQogICAgYXRsZXRhcyAlPiUgCiAgICAgIHB1bGwoaWRhZGUpICU+JSAKICAgICAgc3VtbWFyeSgpCiAgICBgYGAKCgoxLiBRdWFpcyBvcyBkYWRvcyBkb3MgYXRsZXRhcyBxdWUgdMOqbSBhIGlkYWRlIG3DoXhpbWE/CgogICAgYGBge3J9CiAgICBhdGxldGFzICU+JSAKICAgICAgc2xpY2VfbWF4KGlkYWRlKSAlPiUgCiAgICAgIHNlbGVjdChpZCwgbm9tZSwgaWRhZGUsIHBhaXMsIGFubywgZXNwb3J0ZSwgbWVkYWxoYSkgJT4lIAogICAgICBhcnJhbmdlKGFubykKICAgIGBgYAoKMS4gUXVhaXMgb3MgYXRsZXRhcyBtYWlzIGpvdmVucyBhIGdhbmhhciBtZWRhbGhhPyBEZSBvbmRlIHPDo28/IEVtIHF1ZSBhbm9zIGdhbmhhcmFtPyBFbSBxdWUgZXNwb3J0ZXM/IFF1YWlzIG1lZGFsaGFzPwoKICAgIGBgYHtyfQogICAgYXRsZXRhcyAlPiUgCiAgICAgIGZpbHRlcighaXMubmEobWVkYWxoYSkpICU+JSAKICAgICAgc2xpY2VfbWluKGlkYWRlKSAlPiUgCiAgICAgIHNlbGVjdChub21lLCBpZGFkZSwgcGFpcywgYW5vLCBlc3BvcnRlLCBtZWRhbGhhKQogICAgYGBgCgoKMS4gUXVhaXMgb3MgYXRsZXRhcyBtYWlzIHZlbGhvcyBhIGdhbmhhciBtZWRhbGhhPyBEZSBvbmRlIHPDo28/IEVtIHF1ZSBhbm9zIGdhbmhhcmFtPyBFbSBxdWUgZXNwb3J0ZXM/IFF1YWlzIG1lZGFsaGFzPwoKICAgIGBgYHtyfQogICAgYXRsZXRhcyAlPiUgCiAgICAgIGZpbHRlcighaXMubmEobWVkYWxoYSkpICU+JSAKICAgICAgc2xpY2VfbWF4KGlkYWRlKSAlPiUgCiAgICAgIHNlbGVjdChub21lLCBpZGFkZSwgcGFpcywgYW5vLCBlc3BvcnRlLCBtZWRhbGhhKQogICAgYGBgCgoKIyAqU2NhdHRlcnBsb3RzKgoKMS4gVXNhbmRvIGBncm91cF9ieWAgZSBgc3VtbWFyaXplYCwgY3JpZSBvICpkYXRhIGZyYW1lKiBgbWVkYWxoYXNfYXRsZXRhc2AgY29tIGFzIGNvbHVuYXMgYHBhaXNgLCBgYW5vYCwgYGF0bGV0YXNgICh0b3RhbCBkZSBwYXJ0aWNpcGHDp8O1ZXMgZG8gcGHDrXMgbmFxdWVsZSBhbm8pIGUgYG1lZGFsaGFzYCAodG90YWwgZGUgbWVkYWxoYXMgZG8gcGHDrXMgbmFxdWVsZSBhbm8pLiBEZXNjYXJ0ZSBvcyByZWdpc3Ryb3Mgb25kZSBvIG7Dum1lcm8gZGUgbWVkYWxoYXMgw6kgbWVub3IgcXVlICQ1MCQuCgogICA6Ojogey5ybWRub3RlIGxhdGV4PTF9CiAgICAKICAgTyBjw7NkaWdvIGFiYWl4byBjb250YSBvcyAqaWRzKiBkb3MgYXRsZXRhcywgY29tIGBhdGxldGFzID0gbl9kaXN0aW5jdChpZClgLCBjYWRhICppZCogYXBlbmFzIHVtYSB2ZXouCiAgICAKICAgU2Ugdm9jw6ogdXNhciBgYXRsZXRhcyA9IG4oKWAsIGNhZGEgcGFydGljaXBhw6fDo28gZGUgY2FkYSBhdGxldGEgc2Vyw6EgY29udGFkYS4gCiAgICAKICAgQ29uc2lkZXJlaSBhcyBkdWFzIGFsdGVybmF0aXZhcyBjb21vIGNvcnJldGFzLgogICAgICAgIAogICA6OjoKCiAgICBgYGB7cn0KICAgIG1lZGFsaGFzX2F0bGV0YXMgPC0gYXRsZXRhcyAlPiUgCiAgICAgIGdyb3VwX2J5KHBhaXMsIGFubykgJT4lIAogICAgICBzdW1tYXJpemUoCiAgICAgICAgYXRsZXRhcyA9IG5fZGlzdGluY3QoaWQpLAogICAgICAgIG1lZGFsaGFzID0gc3VtKCFpcy5uYShtZWRhbGhhKSksCiAgICAgICAgLmdyb3VwcyA9ICdkcm9wJwogICAgICApICU+JSAKICAgICAgZmlsdGVyKG1lZGFsaGFzID49IDUwKSAlPiUgCiAgICAgIGFycmFuZ2UocGFpcykKICAgIAogICAgbWVkYWxoYXNfYXRsZXRhcwogICAgYGBgCgoxLiBHZXJlIHVtICpzY2F0dGVycGxvdCogZGUgbsO6bWVybyBkZSBtZWRhbGhhcyBwb3IgbsO6bWVybyBkZSBwYXJ0aWNpcGHDp8O1ZXMuIFVzZSBgZ2VvbV9zbW9vdGhgIHBhcmEgdHJhw6dhciB1bWEgcmV0YSBkZSByZWdyZXNzw6NvLiBDb21lbnRlIG8gcmVzdWx0YWRvLgoKICAgIGBgYHtyfQogICAgc3BfbWVkYWxoYV9hdGxldGFzIDwtIG1lZGFsaGFzX2F0bGV0YXMgJT4lIAogICAgICBnZ3Bsb3QoYWVzKGF0bGV0YXMsIG1lZGFsaGFzKSkgKwogICAgICAgIGdlb21fcG9pbnQoYWxwaGEgPSAuMykgKwogICAgICAgIGdlb21fc21vb3RoKHNlID0gRkFMU0UsIG1ldGhvZCA9ICdsbScpCiAgICAKICAgIHNwX21lZGFsaGFfYXRsZXRhcwogICAgYGBgCgoxLiBGYWNldGUgbyAqc2NhdHRlcnBsb3QqIGFudGVyaW9yIHBvciBhbm8uIERpc3BvbmhhIG9zIHN1Ymdyw6FmaWNvcyBlbSAkMyQgbGluaGFzIGUgJDYkIGNvbHVuYXMuCgogICAgYGBge3J9CiAgICBzcF9tZWRhbGhhX2F0bGV0YXMgKwogICAgICBmYWNldF93cmFwKH5hbm8sIG5yb3cgPSAzKQogICAgYGBgCgoxLiBDb21vIHZvY8OqIGludGVycHJldGEgYXMgZGlmZXJlbnRlcyBxdWFudGlkYWRlcyBkZSBwb250b3MgZW0gY2FkYSBzdWJncsOhZmljbz8KCiAgIDo6OiB7LnJtZGJveCBsYXRleD0xfQoKICAgKiBBbyBsb25nbyBkb3MgYW5vcywgYSBxdWFudGlkYWRlIGRlIHBhw61zZXMgcXVlIGdhbmhhcmFtICQ1MCQgb3UgbWFpcyBtZWRhbGhhcyBhdW1lbnRvdS4KICAgCiAgICogQW8gbG9uZ28gZG9zIGFub3MsIGEgcXVhbnRpZGFkZSBkZSBwYXJ0aWNpcGHDp8O1ZXMgZGUgYWxndW5zIHBhw61zZXMgYXVtZW50b3UuCiAgIAogICAqIEFvIGxvbmdvIGRvcyBhbm9zLCBhIFt2YXJpYcOnw6NvXXsuaGx9IGRhIHF1YW50aWRhZGUgZGUgcGFydGljaXBhw6fDtWVzIGF1bWVudG91LiBFbSAkMTk0OCQsIG8gZ3LDoWZpY28gbW9zdHJhIGVudHJlICQxMDAkIGUgJDMwMCQgcGFydGljaXBhw6fDtWVzLiBFbSAkMjAxNiQsIGZvcmFtIGVudHJlICQxMDAkIGUgJDYwMCQgcGFydGljaXBhw6fDtWVzLCBhcHJveGltYWRhbWVudGUuCiAgIAogICA6OjoKCjEuIEhvdXZlIHVtYSDDum5pY2EgdmV6IGVtIHF1ZSB1bSBwYcOtcyBnYW5ob3UgbWFpcyBkZSAkNDAwJCBtZWRhbGhhcyBlbSB1bSBhbm8uIERlc2N1YnJhIG8gcXVlIGFjb250ZWNldSBwYXJhIGZhY2lsaXRhciBlc3NhIG9jb3Jyw6puY2lhLgoKICAgOjo6IHsucm1kYm94IGxhdGV4PTF9CgogICBFbSAkMTk4MCQsIG9zIFtqb2dvcyBmb3JhbSByZWFsaXphZG9zIGVtIE1vc2NvdSwgbmEgVW5pw6NvIFNvdmnDqXRpY2FdKGh0dHBzOi8vcHQud2lraXBlZGlhLm9yZy93aWtpL0pvZ29zX09sJUMzJUFEbXBpY29zX2RlX1ZlciVDMyVBM29fZGVfMTk4MCksIGUgb3MgRXN0YWRvcyBVbmlkb3MgY29tYW5kYXJhbSB1bSBib2ljb3RlIGFvcyBqb2dvcyBwb3IgbW90aXZvcyBwb2zDrXRpY29zLCBmYXplbmRvIGNvbSBxdWUgJDY5JCBwYcOtc2VzIGRlaXhhc3NlbSBkZSBlbnZpYXIgYXRsZXRhcy4KICAgCiAgIEVtICQxOTg0JCwgZm9pIGEgdmV6IGRlIGEgVW5pw6NvIFNvdmnDqXRpY2EgZSBvdXRyb3MgcGHDrXNlcyBjb211bmlzdGFzIFtib2ljb3RhcmVtIG9zIGpvZ29zIGRlIExvcyBBbmdlbGVzXShodHRwczovL3B0Lndpa2lwZWRpYS5vcmcvd2lraS9Kb2dvc19PbCVDMyVBRG1waWNvc19kZV9WZXIlQzMlQTNvX2RlXzE5ODQjQm9pY290ZSksIG1hcyBvIGdyw6FmaWNvIGRlICQxOTg0JCBtb3N0cmEgcXVlIG9zIGVmZWl0b3MgbsOjbyBmb3JhbSB0w6NvIGRyw6FzdGljb3MgcXVhbnRvIG9zIGRvIGJvaWNvdGUgZGUgJDE5ODAkLgoKICAgOjo6CgoxLiBbQ29uc2lkZXJlIGFnb3JhIGFwZW5hcyBvcyByZWdpc3Ryb3Mgb25kZSBgbWVkYWxoYXNgIMOpIG1haW9yIHF1ZSAkMjAwJC5dey5obH0gRmHDp2EgdW0gKnNjYXR0ZXJwbG90KiBkZSBuw7ptZXJvIGRlIG1lZGFsaGFzIHBvciBuw7ptZXJvIGRlIHBhcnRpY2lwYcOnw7Vlcywgb25kZSBjYWRhIHBvbnRvIMOpIGNvbG9yaWRvIGRlIGFjb3JkbyBjb20gbyBwYcOtcy4gQXVtZW50ZSBvIHRhbWFuaG8gZGUgdG9kb3Mgb3MgcG9udG9zIHBhcmEgZmFjaWxpdGFyIGEgbGVpdHVyYS4gW07Do29dey5obH0gZ2VyZSBhIHJldGEgZGUgcmVncmVzc8Ojby4gQ29tZW50ZSBvIHJlc3VsdGFkby4KCiAgICBgYGB7cn0KICAgIG1lZGFsaGFzX2F0bGV0YXMgJT4lIAogICAgICBmaWx0ZXIobWVkYWxoYXMgPiAyMDApICU+JSAKICAgICAgZ2dwbG90KGFlcyhhdGxldGFzLCBtZWRhbGhhcywgY29sb3IgPSBwYWlzKSkgKwogICAgICAgIGdlb21fcG9pbnQoc2l6ZSA9IDQpCiAgICBgYGAKCiAgIDo6OiB7LnJtZGJveCBsYXRleD0xfQogICAKICAgQ29uc2lkZXJhbmRvIGFwZW5hcyBvcyBwYcOtc2VzIGUgb3MgYW5vcyBvbmRlIG8gcGHDrXMgZ2FuaG91IG1haXMgZGUgJDIwMCQgbWVkYWxoYXM6CiAgIAogICAqIEFwZW5hcyBvcyBFc3RhZG9zIFVuaWRvcyB0aXZlcmFtIG1haXMgZGUgJDUwMCQgcGFydGljaXBhw6fDtWVzLCBjb20gcXVhbnRpZGFkZSBkZSBtZWRhbGhhcyBlbnRyZSAkMjAwJCBlICQzNTAkLCBhcHJveGltYWRhbWVudGUuCiAgIAogICAqIEEgVW5pw6NvIFNvdmnDqXRpY2EgdGV2ZSBlbnRyZSAkMzUwJCBlICQ1MDAkIHBhcnRpY2lwYcOnw7VlcywgbWFzLCBjb20gZXhjZcOnw6NvIGRhcyBxdWFzZSAkNDUwJCBtZWRhbGhhcyBlbSBNb3Njb3UgJDE5ODAkLCBjaGVnb3Ugbm8gbcOheGltbyBhICQzMDAkIG1lZGFsaGFzLgogICAKICAgKiBSw7pzc2lhIChFVU4pIGUgQWxlbWFuaGEgT3JpZW50YWwgKEdEUikgYXBhcmVjZW0gY29tIG7Dum1lcm9zIHBvdWNvIGV4cHJlc3Npdm9zIGVtIGNvbXBhcmHDp8OjbyBjb20gRXN0YWRvcyBVbmlkb3MgZSBVbmnDo28gU292acOpdGljYS4KCiAgIDo6OgoKIyBIaXN0b2dyYW1hcwoKMS4gVXNhbmRvIG8gKmRhdGEgZnJhbWUqIGBhdGxldGFzYCBbKHNlbSBhcyBhcnRlcyldey5obH0sIGdlcmUgdW0gaGlzdG9ncmFtYSBkYXMgaWRhZGVzIGRlIHRvZG9zIG9zIGF0bGV0YXMsIGNvbSBjbGFzc2VzIGRlICQ1JCBhbm9zIGRlIGxhcmd1cmEuCgogICAgYGBge3J9CiAgICBicmVha3MgPC0gc2VxKDEwLCA3NSwgNSkKICAgIAogICAgaGlzdF9pZGFkZXMgPC0gYXRsZXRhcyAlPiUgCiAgICAgIGdncGxvdChhZXMoaWRhZGUpKSArCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oYnJlYWtzID0gYnJlYWtzKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGJyZWFrcykgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9udW1iZXJfc2koKSkgKwogICAgICAgIGxhYnMoCiAgICAgICAgICB5ID0gTlVMTCwKICAgICAgICAgIHRpdGxlID0gcGFzdGUoCiAgICAgICAgICAgICdJZGFkZXMgZG9zIGF0bGV0YXMgZW0gb2xpbXDDrWFkYXMgZGVzZGUnLCAKICAgICAgICAgICAgYW5vX2luaWNpYWwKICAgICAgICAgICkKICAgICAgICApCiAgICAKICAgIGhpc3RfaWRhZGVzCiAgICBgYGAKCjEuIEZhw6dhIGEgbWVzbWEgY29pc2EsIG1hcyBhcGVuYXMgcGFyYSBpZGFkZXMgbWFpb3JlcyBvdSBpZ3VhaXMgYSAkNTUkIGFub3MuCgogICAgYGBge3J9CiAgICBicmVha3MgPC0gc2VxKDU1LCA3NSwgNSkKICAgIAogICAgaGlzdF9pZGFkZXNfdmVsaG9zIDwtIGF0bGV0YXMgJT4lIAogICAgICBmaWx0ZXIoaWRhZGUgPj0gNTUpICU+JSAKICAgICAgZ2dwbG90KGFlcyhpZGFkZSkpICsKICAgICAgICBnZW9tX2hpc3RvZ3JhbShicmVha3MgPSBicmVha3MpICsKICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzKSArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX251bWJlcl9zaSgpKSArCiAgICAgICAgbGFicygKICAgICAgICAgIHkgPSBOVUxMLAogICAgICAgICAgdGl0bGUgPSBwYXN0ZSgnSWRhZGVzIGRvcyBhdGxldGFzIGVtIG9saW1ww61hZGFzIGRlc2RlJywgYW5vX2luaWNpYWwpLAogICAgICAgICAgc3VidGl0bGUgPSAnKGF0bGV0YXMgY29tIDU1IGFub3Mgb3UgbWFpcyknCiAgICAgICAgKQogICAgCiAgICBoaXN0X2lkYWRlc192ZWxob3MKICAgIGBgYAoKMS4gR2VyZSBkb2lzIGhpc3RvZ3JhbWFzIFtkZSB0b2RhcyBhcyBpZGFkZXNdey5obH0sIFtwb3Igc2V4b117LmhsfSwgY29tIGNsYXNzZXMgZGUgJDUkIGFub3MgZGUgbGFyZ3VyYS4gVXNlIGBmYWNldF93cmFwYC4KCiAgICBgYGB7cn0KICAgIGhpc3RfaWRhZGVzICsKICAgICAgbGFicyhzdWJ0aXRsZSA9ICdwb3Igc2V4bycpICsKICAgICAgZmFjZXRfd3JhcCh+c2V4bykKICAgIGBgYAoKMS4gQ29tZW50ZSBvIHJlc3VsdGFkbywgc29icmV0dWRvIG5hcyBpZGFkZXMgYWJhaXhvIGRlICQyMCQgYW5vcy4gUG9yIHF1ZSB2b2PDqiBhY2hhIHF1ZSBhY29udGVjZSBpc3NvPyBBbmFsaXNlIG9zIGRhZG9zIGNvbW8gdm9jw6ogYWNoYXIgbWFpcyBhZGVxdWFkbyBwYXJhIGNvbmZpcm1hciBvdSByZWZ1dGFyIHN1YSBoaXDDs3Rlc2UuCgogICA6Ojogey5ybWRib3ggbGF0ZXg9MX0KICAgCiAgICogSMOhIG11aXRvIG1haXMgaG9tZW5zIHF1ZSBtdWxoZXJlcywgbm8gdG90YWwgZSBuYSBtYWlvcmlhIGRhcyBmYWl4YXMgZXTDoXJpYXMuCiAgIAogICAqIFVtYSBmYWl4YSBldMOhcmlhIG9uZGUgaMOhIG11aXRvIG1haXMgbXVsaGVyZXMgZG8gcXVlIGhvbWVucyDDqSBhIGRlICQxMCQgYSAkMTUkIGFub3MuCiAgIAogICAqIE1haXMgYWJhaXhvLCB2b2PDqiB2YWkgY29uc3RhdGFyIHF1ZSBpc3NvIMOpIHBvciBjYXVzYSBkYSBnaW7DoXN0aWNhIHLDrXRtaWNhLCBvbmRlIGNvbXBldGVtIGFwZW5hcyBtdWxoZXJlcywgZ3JhbmRlIHBhcnRlIGRlbGFzIG11aXRvIGpvdmVucy4KICAgCiAgIDo6OgoKMS4gUXVhaXMgc8OjbyBvcyBlc3BvcnRlcyBjb20gYSBtZW5vciBpZGFkZSBbbcOpZGlhXXsuaGx9IGUgYSBtYWlvciBpZGFkZSBbbcOpZGlhXXsuaGx9PyBVc2UgYGdyb3VwX2J5YCBlIGBzdW1tYXJpemVgLiBJZ25vcmUgb3MgdmFsb3JlcyBgTkFgIG5hIGhvcmEgZGUgY29tcHV0YXIgYSBtw6lkaWEgKHZlamEgYSBhanVkYSBkYSBmdW7Dp8OjbyBgbWVhbmApLgoKICAgIGBgYHtyfQogICAgZXh0cmVtb3MgPC0gYXRsZXRhcyAlPiUgCiAgICAgIGdyb3VwX2J5KGVzcG9ydGUpICU+JSAKICAgICAgc3VtbWFyaXplKG1lZGlhID0gbWVhbihpZGFkZSwgbmEucm0gPSBUUlVFKSkgJT4lIAogICAgICBhcnJhbmdlKG1lZGlhKSAlPiUgCiAgICAgIHNsaWNlKGMoMSwgbigpKSkKICAgIAogICAgZXh0cmVtb3MKICAgIGBgYAoKMS4gUXVhaXMgc8OjbyBvcyBlc3BvcnRlcyBjb20gYSBtZW5vciBpZGFkZSBbbWVkaWFuYV17LmhsfSBlIGEgbWFpb3IgaWRhZGUgW21lZGlhbmFdey5obH0/IFVzZSBgZ3JvdXBfYnlgIGUgYHN1bW1hcml6ZWAuIElnbm9yZSBvcyB2YWxvcmVzIGBOQWAgbmEgaG9yYSBkZSBjb21wdXRhciBhIG1lZGlhbmEgKHZlamEgYSBhanVkYSBkYSBmdW7Dp8OjbyBgbWVkaWFuYCkuCgogICAgYGBge3J9CiAgICBhdGxldGFzICU+JSAKICAgICAgZ3JvdXBfYnkoZXNwb3J0ZSkgJT4lIAogICAgICBzdW1tYXJpemUobWVkaWFuYSA9IG1lZGlhbihpZGFkZSwgbmEucm0gPSBUUlVFKSkgJT4lIAogICAgICBhcnJhbmdlKG1lZGlhbmEpICU+JSAKICAgICAgc2xpY2UoYygxLCBuKCkpKQogICAgYGBgCgoxLiBbVXNhbmRvIHNvbWVudGUgb3MgYXRsZXRhcyBkb3MgZXNwb3J0ZXMgY29tIG1lbm9yIGlkYWRlIG3DqWRpYSBlIG1haW9yIGlkYWRlIG3DqWRpYSAoYWNoYWRvcyBhY2ltYSksXXsuaGx9IGdlcmUgZG9pcyBoaXN0b2dyYW1hcyBkYXMgaWRhZGVzLCBwb3IgZXNwb3J0ZSwgY29tIGNsYXNzZXMgZGUgJDUkIGFub3MuIFVzZSBgZmFjZXRfd3JhcGAuCgogICAgYGBge3J9CiAgICBicmVha3MgPC0gc2VxKDEwLCA5MCwgNSkKICAgIGVzcG9ydGVzIDwtIGV4dHJlbW9zICU+JSBwdWxsKGVzcG9ydGUpCiAgICAKICAgIGF0bGV0YXMgJT4lIAogICAgICBmaWx0ZXIoZXNwb3J0ZSAlaW4lIGVzcG9ydGVzKSAlPiUgCiAgICAgIGdncGxvdChhZXMoaWRhZGUpKSArCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oYnJlYWtzID0gYnJlYWtzKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGJyZWFrcykgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9udW1iZXJfc2koKSkgKwogICAgICAgIGxhYnMoCiAgICAgICAgICB5ID0gTlVMTCwKICAgICAgICAgIHRpdGxlID0gcGFzdGUoJ0lkYWRlcyBkb3MgYXRsZXRhcyBlbSBvbGltcMOtYWRhcyBkZXNkZScsIGFub19pbmljaWFsKSwKICAgICAgICAgIHN1YnRpdGxlID0gJ25vcyBlc3BvcnRlcyBjb20gbWFpb3IgZSBtZW5vciBpZGFkZXMgbcOpZGlhcycKICAgICAgICApICsKICAgICAgICBmYWNldF93cmFwKH5lc3BvcnRlKQogICAgYGBgCgoxLiBSZXBpdGEgbyBpdGVtIGFudGVyaW9yLCBkZXN0YSB2ZXogdXNhbmRvIGBmYWNldF9ncmlkYCBlbSB2ZXogZGUgYGZhY2V0X3dyYXBgLCBwYXJhIGdlcmFyICQ0JCBoaXN0b2dyYW1hcywgY2FkYSB1bSBjb20gdW0gZXNwb3J0ZSBlIHVtIHNleG8uIENvbWVudGUgbyByZXN1bHRhZG8uCgogICAgYGBge3J9CiAgICBicmVha3MgPC0gc2VxKDEwLCA5MCwgNSkKICAgIGVzcG9ydGVzIDwtIGV4dHJlbW9zICU+JSBwdWxsKGVzcG9ydGUpCiAgICAKICAgIGF0bGV0YXMgJT4lIAogICAgICBmaWx0ZXIoZXNwb3J0ZSAlaW4lIGVzcG9ydGVzKSAlPiUgCiAgICAgIGdncGxvdChhZXMoaWRhZGUpKSArCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oYnJlYWtzID0gYnJlYWtzKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGJyZWFrcykgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9udW1iZXJfc2koKSkgKwogICAgICAgIGxhYnMoCiAgICAgICAgICB5ID0gTlVMTCwKICAgICAgICAgIHRpdGxlID0gcGFzdGUoJ0lkYWRlcyBkb3MgYXRsZXRhcyBlbSBvbGltcMOtYWRhcyBkZXNkZScsIGFub19pbmljaWFsKSwKICAgICAgICAgIHN1YnRpdGxlID0gJ3BvciBzZXhvLCBub3MgZXNwb3J0ZXMgY29tIG1haW9yIGUgbWVub3IgaWRhZGVzIG3DqWRpYXMnCiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfZ3JpZChjb2xzID0gdmFycyhzZXhvKSwgcm93cyA9IHZhcnMoZXNwb3J0ZSkpCiAgICBgYGAKCgojICpCb3hwbG90cyoKCjEuIEdlcmUgKmJveHBsb3RzKiBsYWRvIGEgbGFkbywgdW0gKmJveHBsb3QqIHBvciBhbm8sIHBhcmEgYXMgYWx0dXJhcyBkZSB0b2RvcyBvcyBhdGxldGFzLiBDb21lbnRlIG8gcmVzdWx0YWRvLgoKICAgIGBgYHtyfQogICAgYm94X2FsdHVyYXMgPC0gYXRsZXRhcyAlPiUgCiAgICAgIGdncGxvdChhZXMoYW5vLCBhbHR1cmEsIGdyb3VwID0gYW5vKSkgKwogICAgICAgIGdlb21fYm94cGxvdCgpCiAgICAKICAgIGJveF9hbHR1cmFzCiAgICBgYGAKCiAgIDo6OiB7LnJtZGJveCBsYXRleD0xfQogICAKICAgKiBBIG1lZGlhbmEgc2UgbWFudGV2ZSBwcsOzeGltYSBkZSAkMTc1JGNtIGFvIGxvbmdvIGRvcyBhbm9zLgogICAKICAgKiBBIHZhcmlhw6fDo28gYXVtZW50b3Ugbm9zIGFub3MgJDYwJC4KICAgCiAgIDo6OgoKMS4gUmVwaXRhIG8gaXRlbSBhbnRlcmlvciwgZmFjZXRhbmRvIHBvciBzZXhvLiBVc2UgYGNvb3JkX2ZsaXBgLiBDb21lbnRlIG9zIHJlc3VsdGFkb3MuCgogICAgYGBge3J9CiAgICBib3hfYWx0dXJhcyArCiAgICAgIGZhY2V0X3dyYXAofnNleG8pICsKICAgICAgY29vcmRfZmxpcCgpCiAgICBgYGAKCiAgIDo6OiB7LnJtZGJveCBsYXRleD0xfQogICAKICAgKiBBIG1lZGlhbmEgZGEgYWx0dXJhIGRhcyBtdWxoZXJlcyBhdW1lbnRvdSBkZXNkZSBvcyBhbm9zICQ1MCQuCiAgIAogICAqIEEgbWVkaWFuYSBkYSBhbHR1cmEgZG9zIGhvbWVucyBhdW1lbnRvdSBkZXNkZSBvcyBhbm9zICQ2MCQuCiAgIAogICAqIEVzdGFzIG11ZGFuw6dhcyBuw6NvIGFwYXJlY2lhbSBubyBncsOhZmljbyBkbyBpdGVtIGFudGVyaW9yIHBvcnF1ZSBlc3TDoXZhbW9zIGNvbnNpZGVyYW5kbyBob21lbnMgZSBtdWxoZXJlcyBlbSBjb25qdW50by4KICAgCiAgIDo6OgoKMS4gR2VyZSBkb2lzICpib3hwbG90cyogbGFkbyBhIGxhZG8sIHVtIHBhcmEgb3MgYnJhc2lsZWlyb3MgKEJSQSksIHVtIHBhcmEgb3MgaG9sYW5kZXNlcyAoTkVEKSwgcGFyYSBhcyBhbHR1cmFzIGRvcyBhdGxldGFzLiBDb21lbnRlIG8gcmVzdWx0YWRvLgoKICAgIGBgYHtyfQogICAgYm94X2JyYV9uZWQgPC0gYXRsZXRhcyAlPiUgCiAgICAgIGZpbHRlcihwYWlzICVpbiUgYygnQlJBJywgJ05FRCcpKSAlPiUgCiAgICAgIGdncGxvdChhZXMocGFpcywgYWx0dXJhLCBncm91cCA9IHBhaXMpKSArCiAgICAgICAgZ2VvbV9ib3hwbG90KCkKICAgIAogICAgYm94X2JyYV9uZWQKICAgIGBgYAoKICAgOjo6IHsucm1kYm94IGxhdGV4PTF9CiAgIAogICAqIEEgbWVkaWFuYSBlIG9zIHF1YXJ0aXMgZGFzIGFsdHVyYXMgZG9zIGhvbGFuZGVzZXMgKGNvbnNpZGVyYW5kbyBob21lbnMgZSBtdWxoZXJlcyBlbSBjb25qdW50bykgc8OjbyB1bSBwb3VjbyBtYWlvcmVzIGRvIHF1ZSBvcyB2YWxvcmVzIGNvcnJlc3BvbmRlbnRlcyBkb3MgYnJhc2lsZWlyb3MuCiAgIAogICAqIEN1cmlvc2FtZW50ZSwgZXhpc3RlIHVtIGJyYXNpbGVpcm8gbWFpcyBhbHRvIGRvIHF1ZSB0b2RvcyBvcyBob2xhbmRlc2VzLgogICAKICAgOjo6CgoxLiBSZXBpdGEgbyBpdGVtIGFudGVyaW9yLCBmYWNldGFuZG8gcG9yIHNleG8uIENvbWVudGUgb3MgcmVzdWx0YWRvcy4KCiAgICBgYGB7cn0KICAgIGJveF9icmFfbmVkICsKICAgICAgZmFjZXRfd3JhcCh+c2V4bykKICAgIGBgYAoKICAgOjo6IHsucm1kYm94IGxhdGV4PTF9CiAgIAogICAqIFZhbGVtIGFzIG1lc21hcyBvYnNlcnZhw6fDtWVzIGRvIGl0ZW0gYW50ZXJpb3IsIHF1YW5kbyBleGFtaW5hbW9zIG9zIGRhZG9zIHNlcGFyYWRvcyBwb3Igc2V4by4KICAgCiAgICogRXhpc3RlIHVtYSBtdWxoZXIgYnJhc2lsZWlyYSBtYWlzIGFsdGEgcXVlIHRvZGFzIGFzIG11bGhlcmVzIGhvbGFuZGVzYXMuCiAgIAogICA6OjoKCiMgR3LDoWZpY29zIGRlIGJhcnJhcwoKMS4gR2VyZSB1bSBncsOhZmljbyBkZSBiYXJyYXMgW2hvcml6b250YWlzXXsuaGx9IGNvbSBhcyBxdWFudGlkYWRlcyBkZSBtZWRhbGhhcyBkZSBvdXJvIGRvcyAkMTAkIHBhw61zZXMgcXVlIGdhbmhhcmFtIG1haXMgbWVkYWxoYXMgZGUgb3VybyBbbmFzIG9saW1ww61hZGFzIGRlICQyMDE2JF17LmhsfS4gQ29sb3F1ZSBhcyBiYXJyYXMgZW0gb3JkZW0gZGVjcmVzY2VudGUuCgogICAgYGBge3J9CiAgICBhdGxldGFzICU+JSAKICAgICAgZmlsdGVyKGFubyA9PSAyMDE2ICYgbWVkYWxoYSA9PSAnR29sZCcpICU+JSAKICAgICAgZ3JvdXBfYnkocGFpcykgJT4lIAogICAgICBzdW1tYXJpemUob3VybyA9IG4oKSkgJT4lIAogICAgICBzbGljZV9tYXgob3VybywgbiA9IDEwKSAlPiUgCiAgICAgIGdncGxvdChhZXMoZmN0X3Jlb3JkZXIocGFpcywgb3VybyksIG91cm8pKSArCiAgICAgICAgZ2VvbV9jb2woKSArCiAgICAgICAgbGFicygKICAgICAgICAgIHggPSBOVUxMCiAgICAgICAgKSArCiAgICAgICAgY29vcmRfZmxpcCgpCiAgICBgYGAKCjEuIEdlcmUgdW0gZ3LDoWZpY28gZGUgYmFycmFzIHBhcmEgYXMgcXVhbnRpZGFkZXMgdG90YWlzIGRlIG1lZGFsaGFzIGRvIEJyYXNpbCwgcG9yIGFuby4gTm8gZWl4byAkeCQsIGNvbG9xdWUgcsOzdHVsb3MgcGFyYSBbdG9kb3Ndey5obH0gb3MgYW5vcyBkZSBPbGltcMOtYWRhIGRlc2RlICQxOTQ4JC4gUGFyYSBvcyByw7N0dWxvcyBmaWNhcmVtIGxlZ8OtdmVpcywgdXNlIGBjb29yZF9mbGlwYC4KCiAgICBgYGB7cn0KICAgIGF0bGV0YXMgJT4lIAogICAgICBmaWx0ZXIocGFpcyA9PSAnQlJBJyAmICFpcy5uYShtZWRhbGhhKSkgJT4lIAogICAgICBnZ3Bsb3QoYWVzKGFubykpICsKICAgICAgICBnZW9tX2JhcigpICsKICAgICAgICBsYWJzKHkgPSBOVUxMKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShhbm9faW5pY2lhbCwgMjAyMCwgNCkpICsKICAgICAgICBjb29yZF9mbGlwKCkKICAgIGBgYAoKMS4gUmVwaXRhIG8gaXRlbSBhbnRlcmlvciwgY29tIGR1YXMgYmFycmFzIGxhZG8gYSBsYWRvIHBvciBhbm8sIHVtYSBwYXJhIGNhZGEgc2V4by4gTyBxdWUgdm9jw6ogbm90YSBkZSBlc3RyYW5obyBubyByZXN1bHRhZG8/IAoKICAgIGBgYHtyfQogICAgYXRsZXRhcyAlPiUgCiAgICAgIGZpbHRlcihwYWlzID09ICdCUkEnICYgIWlzLm5hKG1lZGFsaGEpKSAlPiUgCiAgICAgIGdncGxvdChhZXMoYW5vLCBmaWxsID0gc2V4bykpICsKICAgICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICdkb2RnZScpICsKICAgICAgICBsYWJzKHkgPSBOVUxMKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShhbm9faW5pY2lhbCwgMjAyMCwgNCkpICsKICAgICAgICBjb29yZF9mbGlwKCkKICAgIGBgYAoKICAgOjo6IHsucm1kYm94IGxhdGV4PTF9CiAgIAogICBBIHByaW1laXJhIHZleiBlbSBxdWUgdW1hIG11bGhlciBicmFzaWxlaXJhIGdhbmhvdSBtZWRhbGhhIGZvaSBlbSAkMTk5NiQhCiAgIAogICA6OjoKCjo6OiB7LnJtZGltcG9ydGFudCBsYXRleD0xfQoKWyoqREVTQUZJTzoqKl17LmhsfSBRdWFsIGZvaSBvIHByaW1laXJvIGFubyBlbSBxdWUgY2FkYSBwYcOtcyB0ZXZlIHVtYSBhdGxldGEgZG8gc2V4byBmZW1pbmlubyBnYW5oYW5kbyB1bWEgbWVkYWxoYT8gQ29uc3RydWEgdW0gKmRhdGEgZnJhbWUqLiBPIHJlc3VsdGFkbyB0ZXLDoSAkOTgkIGxpbmhhcy4KCmBgYHtyfQphdGxldGFzICU+JSAKICBmaWx0ZXIoc2V4byA9PSAnRicpICU+JSAKICBncm91cF9ieShwYWlzLCBhbm8pICU+JSAKICBzdW1tYXJpemUoCiAgICBtZWRhbGhhcyA9IHN1bSghaXMubmEobWVkYWxoYSkpLAogICAgYWN1bXVsYWRvID0gY3Vtc3VtKG1lZGFsaGFzKSwKICAgIC5ncm91cHMgPSAnZHJvcCcKICApICU+JSAKICBmaWx0ZXIoYWN1bXVsYWRvID4gMCkgJT4lIAogIGdyb3VwX2J5KHBhaXMpICU+JSAKICBzdW1tYXJpemUoYW5vX3ByaW1laXJhX21lZGFsaGFfZiA9IG1pbihhbm8pKSAlPiUgCiAgYXJyYW5nZShkZXNjKGFub19wcmltZWlyYV9tZWRhbGhhX2YpKQpgYGAKClVtYSBzb2x1w6fDo28gbWFpcyBzaW1wbGVzLCBzZW0gc29tYSBhY3VtdWxhZGEsIHNlbWVsaGFudGUgw6AgYXByZXNlbnRhZGEgcG9yIGFsZ3VucyBhbHVub3M6CgpgYGB7cn0KYXRsZXRhcyAlPiUgCiAgZmlsdGVyKHNleG8gPT0gJ0YnLCAhaXMubmEobWVkYWxoYSkpICU+JSAKICBzZWxlY3QocGFpcywgYW5vKSAlPiUgCiAgZ3JvdXBfYnkocGFpcykgJT4lIAogIHNsaWNlX21pbihhbm8pICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICB1bmdyb3VwKCkKYGBgCgo6OjoKCgojIEdyw6FmaWNvcyBkZSBsaW5oYQoKMS4gRmHDp2EgdW0gZ3LDoWZpY28gZGUgbGluaGEgY29tIG9zIHRvdGFpcyBkZSBhdGxldGFzIHF1ZSBvIEJyYXNpbCBlbnZpb3UgYSBjYWRhIE9saW1ww61hZGEuIFNvYnJlcG9uaGEgcG9udG9zIMOgIGxpbmhhLiBObyBlaXhvICR4JCwgY29sb3F1ZSByw7N0dWxvcyBwYXJhIFt0b2Rvc117LmhsfSBvcyBhbm9zIGRlIE9saW1ww61hZGEgZGVzZGUgJDE5NDgkLiBQYXJhIG9zIHLDs3R1bG9zIGZpY2FyZW0gbGVnw612ZWlzLCBnaXJlLW9zIGVtICQ0NSQgZ3JhdXMuCgogICAgYGBge3J9CiAgICBkZXNlbXBlbmhvX2JyYXNpbCA8LSBhdGxldGFzICU+JSAKICAgICAgZmlsdGVyKHBhaXMgPT0gJ0JSQScpICU+JSAKICAgICAgZ3JvdXBfYnkoYW5vKSAlPiUgCiAgICAgIHN1bW1hcml6ZSgKICAgICAgICBuX2F0bGV0YXMgPSBuKCksCiAgICAgICAgbl9tZWRhbGhhcyA9IHN1bSghaXMubmEobWVkYWxoYSkpLAogICAgICAgIHBlcmMgPSBuX21lZGFsaGFzIC8gbl9hdGxldGFzCiAgICAgICkKICAgIAogICAgbGluaGFfYXRsZXRhcyA8LSBkZXNlbXBlbmhvX2JyYXNpbCAlPiUgCiAgICAgIGdncGxvdChhZXMoYW5vKSkgKwogICAgICAgIGdlb21fbGluZShhZXMoeSA9IG5fYXRsZXRhcywgY29sb3IgPSAnYXRsZXRhcycpKSArCiAgICAgICAgZ2VvbV9wb2ludChhZXMoeSA9IG5fYXRsZXRhcywgY29sb3IgPSAnYXRsZXRhcycpKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShhbm9faW5pY2lhbCwgMjAyMCwgNCkpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1KSkgKwogICAgICAgIGxhYnMoCiAgICAgICAgICBjb2xvciA9IE5VTEwsCiAgICAgICAgICB5ID0gTlVMTAogICAgICAgICkKICAgIAogICAgbGluaGFfYXRsZXRhcwogICAgYGBgCgoxLiBBY3Jlc2NlbnRlIGFvIGdyw6FmaWNvIGRvIGl0ZW0gYW50ZXJpb3IgdW1hIGxpbmhhIGRlIG91dHJhIGNvciwgdGFtYsOpbSBjb20gcG9udG9zLCBjb20gYXMgcXVhbnRpZGFkZXMgZGUgbWVkYWxoYXMgb2J0aWRhcyBwZWxvIEJyYXNpbCBhIGNhZGEgYW5vLiBBcyBjb3JlcyBkYXMgbGluaGFzIGRldmVtIGFwYXJlY2VyIG5hIGxlZ2VuZGEsIGNvbSBhcyBpZGVudGlmaWNhw6fDtWVzICJhdGxldGFzIiBlICJtZWRhbGhhcyIuCgogICAgYGBge3J9CiAgICBsaW5oYV9hdGxldGFzICsKICAgICAgZ2VvbV9saW5lKGFlcyh5ID0gbl9tZWRhbGhhcywgY29sb3IgPSAnbWVkYWxoYXMnKSkgKwogICAgICBnZW9tX3BvaW50KGFlcyh5ID0gbl9tZWRhbGhhcywgY29sb3IgPSAnbWVkYWxoYXMnKSkKICAgIGBgYAoKMS4gQ2FsY3VsZSwgcGFyYSBjYWRhIGFubywgbyBwZXJjZW50dWFsIGRlIG1lZGFsaGFzIGdhbmhhcyBlbSByZWxhw6fDo28gYW8gdG90YWwgZGUgcGFydGljaXBhw6fDtWVzIGRlIGF0bGV0YXMgYnJhc2lsZWlyb3MuIEdlcmUgdW0gZ3LDoWZpY28gZGUgbGluaGEgY29tIHBvbnRvcyBzb2JyZXBvc3Rvcy4gTm8gZWl4byAkeCQsIGNvbG9xdWUgcsOzdHVsb3MgcGFyYSBbdG9kYXNdey5obH0gb3MgYW5vcyBkZSBPbGltcMOtYWRhIGRlc2RlICQxOTQ4JC4gUGFyYSBvcyByw7N0dWxvcyBmaWNhcmVtIGxlZ8OtdmVpcywgZ2lyZS1vcyBlbSAkNDUkIGdyYXVzLiBVc2UgbyBwYWNvdGUgYHNjYWxlc2AgcGFyYSByb3R1bGFyIG8gZWl4byAkeSQgY29tIHBlcmNlbnRhZ2Vucy4KCiAgICBgYGB7cn0KICAgIGRlc2VtcGVuaG9fYnJhc2lsICU+JSAKICAgICAgZ2dwbG90KGFlcyhhbm8sIHBlcmMpKSArCiAgICAgICAgZ2VvbV9saW5lKCkgKwogICAgICAgIGdlb21fcG9pbnQoKSArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoKSkgKwogICAgICAgIGxhYnMoCiAgICAgICAgICB5ID0gTlVMTAogICAgICAgICkgKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoYW5vX2luaWNpYWwsIDIwMjAsIDQpKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSkpCiAgICAKICAgIGBgYAoK