Trata base de comunicados RPC (deduplicação de comunicados) considerando os casos especiais identificados na IN DIPRO nº 13/2006 antes e depois das alterações implementadas pela entrada em vigor da IN DIPRO nº 47/2014.
Preparação
# grava data de entrada em vigor da IN 47
dt.in47 <- ymd("2014-12-04")
Load datasets
Nota: a base do RPC a ser tratada tem que trazer pelo menos uma sequencia de 2 anos de reajustes aplicados (filtrar pelo campo dt_inic_aplicacao)
# Base(s) RPC
files <- list.files(path = "_datasets/RPC", pattern = "*.csv", full.names = T)
rpc <- rbindlist(lapply(files, fread, showProgress = FALSE)) |>
lazy_dt() |>
rename_with(tolower) |>
select(-c(nm_justificativa, nm_justificativa_tratada, cd_plano, cd_operadora)) |>
# indexa a base original para resgatar todos os atributos dos comunicados após deduplicações
arrange(dt_protocolo) |>
mutate(id_envio = row_number(),
dt_inic_aplicacao = ymd(dt_inic_aplicacao)) |>
as_tibble()
remove(files)
# Enxuga o dataset do RPC para poder trabalhar com base gigantesca
rpc0 <- rpc |>
select(id_comunicado, id_plano,
dt_inic_aplicacao,
starts_with("lg_"),
benef = benef_comunicado, percentual, dt_protocolo, id_envio) |>
mutate(
dt_envio = as_date(dt_protocolo),
lg_rps = if_else(id_plano > 0, 1, 0)
) |>
select(-c(lg_introducao_franquia_copt, lg_adesao, lg_parcelado,
dt_protocolo, id_plano)) |>
relocate(dt_envio, .after = id_comunicado)
Período de abrangência do dataset pela data de aplicação do reajuste (dt_inic_aplicacao) Nota: a base do RPC a ser tratada tem que trazer pelo menos 11 meses a mais do que o último mês de interesse da consulta. Ou seja, se o período de consulta for jan a dez 2010, é necessário trazer tratar uma base de reajustes com data de início de aplicação até novembro de 2011.
[1] "jan-2005" "dez-2010"
Período de abrangência do dataset pela data de envio do comunicado (dt_envio))
Note que podem existir comunicados enviados antes e depois do marco de entrada em vigor das alterações da IN DIPRO nº 13 (04/12/2004).
[1] "2004-11-22" "2021-06-15"
Deduplicação
Existem 5 casos especiais de comunicado RPC que geram duplicidade de envio de comunicados no RPC e foram alterados pela IN DIPRO nº 47/2014 para comunicados enviados a partir de 04 de dezembro de 2014:
- CANCELAMENTO - Cancelamento de comunicados anteriores
- RETIFICACAO - Retificações de comunicados anteriores
- EM NEGOCIACAO - Aviso de “reajuste em negociação”
- ADESÃO - Casos excepcionais de contratos autorizados a aplicar reajustes por data de adesão do beneficiário
- PARCELADO - Casos excepicionais de contratos autorizados a aplicar reajuste parcelado
Estes casos serão tratados a seguir.
Cancelamento
[pré IN 47]
Não existia a possibilidade de cancelar comunicados antes da IN 47.
[pós IN 47]
TRECHO REPRODUZIDO DO ANEXO II DA IN nº 13/2006
5.2) Para cancelar um comunicado de reajuste, a operadora deverá enviar um novo comunicado, de acordo com a Tabela 4 deste Anexo.
Tabela 4
| Nº de Registro do Plano |
O mesmo do comunicado a ser cancelado |
| Código do plano na operadora |
O mesmo do comunicado a ser cancelado |
| Nº do contrato ou apólice |
O mesmo do comunicado a ser cancelado |
| Mês/Ano Início Período da Aplicação |
O mesmo do comunicado a ser cancelado |
| Percentual de Reajuste |
0 (ZERO) |
| Característica do Reajuste |
Sem Reajuste |
| Justificativa Técnica |
(a) Preencher obrigatoriamente com a expressão “CANCELAR COMUNICADO” (b) Justificativa para o cancelamento. |
5.3) Para retificar as informações de: “Nº de Registro do Plano”, “Código do plano na operadora”, “Nº do contrato ou apólice”, e “Mês/Ano Início Período de Aplicação”, o comunicado deverá ser cancelado, conforme definido no item 5.2, e um novo comunicado deverá ser enviado.
TRATAMENTOS
Resumo das regras a serem aplicadas por id_comunicado e dt_inic_aplicacao:
- [pós IN 47] Excluir aviso de CANCELAMENTO e o comunicado original a ser cancelado
Totaliza avisos de cancelamento por ano.
rpc0 |>
group_by(ano = year(dt_inic_aplicacao)) |>
summarise(cancelamentos = sum(lg_cancelamento),
pct = round(cancelamentos/n()*100,3))
Exclui o aviso de CANCELAMENTO e o comunicado original a ser cancelado.
# Identifica cancelamentos
last.row <- nrow(rpc0)
rpc1 <- rpc0 |>
# corrige se cancelamento tiver sido enviado antes da IN 47
mutate(lg_cancelamento = if_else(lg_cancelamento == 1L & dt_envio >= dt.in47, 1L, 0L)) |>
# marca comunicados a serem deletados
arrange(id_comunicado, dt_inic_aplicacao, dt_envio) |>
mutate(
lg.delete = case_when(
# quando o comunicado for anterior a um aviso de cancelamento
row_number() != last.row
& lead(id_comunicado) == id_comunicado
& lead(dt_inic_aplicacao) == dt_inic_aplicacao
& lead(lg_cancelamento == 1) ~ 1L,
# quando for o próprio aviso de cancelamento
lg_cancelamento == 1 ~ 1L,
TRUE ~ 0L
)
) |>
# exclui avisos de cancelamento e comunicados cancelados
filter(lg.delete == 0L) |> select(-lg.delete, -lg_cancelamento)
remove(last.row)
rpc1 |> group_by(ano = year(dt_inic_aplicacao)) |>
summarise(envios = n(),
comunicados = n_distinct(id_comunicado, dt_inic_aplicacao),
.groups = "drop") |>
mutate(envios.por.comunicado = round(envios/comunicados, 2))
Retificação
TRECHOS REPRODUZIDOS DO ANEXO II DA IN 13/2006
[pré IN 47]
5.3) Para retificar apenas o percentual de reajuste, a operadora deverá informar, via aplicativo, a diferença ou acréscimo de forma que o percentual final seja o que deveria ser originalmente enviado, mantendo as demais informações do comunicado original.
Nesse caso o percentual efetivamente aplicado ao comunicado deverá ser calculado de acordo com a seguinte fórmula:
PA = [(1 + PC) * (1 + PN)] - 1
onde:
PA é o percentual aplicado ao contrato
PC é o percentual inicialmente comunicado à ANS
PN é o percentual novo do comunicado de retificação
[pós IN 47]
5.1) Para retificar quaisquer informações do comunicado de reajuste definidas no Anexo I desta Instrução Normativa, com exceção de: “Nº de Registro do Plano”, “Código do plano na operadora”, “Nº do contrato ou apólice”, e “Mês/Ano Início Período de Aplicação”, a operadora deverá enviar um novo comunicado via RPC, de acordo com a Tabela 3 deste Anexo.
Tabela 3
| Nº de Registro do Plano |
O mesmo do comunicado a ser retificado |
| Código do plano na operadora |
O mesmo do comunicado a ser retificado |
| Nº do contrato ou apólice |
O mesmo do comunicado a ser retificado |
| Mês/Ano Início Período da Aplicação |
O mesmo do comunicado a ser retificado |
| Justificativa Técnica |
(a) Preencher obrigatoriamente com a expressão “RETIFICAÇÃO DE REAJUSTE” (b)Justificativa para a retificação. |
TRATAMENTOS
Resumo das regras a serem aplicadas por id_comunicado e dt_inic_aplicacao:
- [pós IN 47] Excluir comunicado original que foi substituído por uma retificação
- [pré IN 47] Calcula o reajuste efetivamente aplicado ao contrato, com base no original e sua retificação
rpc1 |> group_by(ano = year(dt_inic_aplicacao)) |>
summarise(retificacoes = sum(lg_retificacao),
pct = round(retificacoes/n()*100,1))
Marca comunicados de retificação e seus originais a serem alterados conforme o caso.
# Identifica retificações
rpc1 <- rpc1 |>
# identifica comunicados a serem retificados
filter(lg_retificacao == 1) |>
distinct(id_comunicado, dt_inic_aplicacao) |>
mutate(lg.alterar = 1L) |>
right_join(rpc1, by = c("id_comunicado", "dt_inic_aplicacao")) |>
mutate(
# marca se retificação foi enviada antes ou depois da IN 47
lg.in47 = if_else(lg_retificacao == 1L & dt_envio >= dt.in47, 1L, 0L)
)
rpc1$lg.alterar[is.na(rpc1$lg.alterar)] <- 0L
Trata retificações aplicando as regras apropriadas para envios anteriores e posteriores à entrada em vigor da IN 47.
# Aplica retificações aos comunicados originais
rpc2 <- rpc1 |>
filter(lg.alterar != 0L) |> # Trata apenas dos casos de retificação
# marca a sequência (ordem) de envios do mais antigo para o mais recente
arrange(id_comunicado, dt_inic_aplicacao, id_envio) |>
group_by(id_comunicado, dt_inic_aplicacao) |>
mutate(ord = row_number(),
n.obs = n(),
lg.in47 = sum(lg.in47)) |>
ungroup() |>
# quando houver alguma retificação pós IN47, vale o último comunicado enviado
mutate(lg.delete = if_else(lg.in47 > 0 & ord != n.obs, 1L, 0L)) |>
filter(lg.delete == 0L) |> select(-lg.delete) |>
# quando não houver nenhuma retificação pós IN47, junta a retificação e o comunicado
# anterior pela fórmula de cálculo da IN
# nota: pode haver mais de 1 retificação, mas sempre vai aplicar a última retificação sobre o
# primeiro comunicado enviado (comunicado original). Todos os outros comunicados serão
# desconsiderados.
filter(ord == 1 | ord == n.obs) |> # filtra o comunicado original e a última retificação
arrange(id_comunicado, dt_inic_aplicacao, ord) |>
mutate(
pct.i = percentual/100+1, # indexa o percentual para aplicar a fórmula de retificação
lg.delete = if_else(lg.in47 == 0 & ord != n.obs, 1L, 0L), # marca o comunicado original
# recalcula o percentual do último comunicado, juntando com o percentual do comunicado original
percentual = if_else(
lg.in47 == 0 & ord == n.obs # se for pré IN47 e for o último envio
& row_number() != 1 # se não for a primeira linha da tabela
& lag(id_comunicado) == id_comunicado # e a linha anterior for do mesmo comunicado
& lag(dt_inic_aplicacao) == dt_inic_aplicacao, # na mesma data de aplicação
((lag(pct.i) * pct.i) - 1) * 100, # aplica a fórmula da IN
percentual # se não, mantém o percentual inalterado
)
) |>
filter(lg.delete == 0L) |>
# acerta a ordem das colunas para ser a mesma do rpc1 e poder juntar as duas
select(colnames(rpc1)) |>
rbind(rpc1 |> filter(lg.alterar == 0L)) |>
select(-lg_retificacao, -lg.in47, -lg.alterar)
Negociação
TRECHOS REPRODUZIDOS DO ANEXO II DA IN 13/2006
[pré IN 47]
1) Quando a negociação anual tenha ultrapassado o mês de aniversário do contrato:
1.1) Comunicar em até 30 dias do aniversário do contrato a manutenção da contraprestação pecuniária, por meio do RPC, de acordo com a tabela 1.
Tabela 1
| Mês/Ano Início Período da Aplicação |
Mês/Ano do aniversário do contrato |
| Mês/Ano Final Período de Aplicação |
Mês/Ano imediatamente anterior ao próximo aniversário do contrato |
| Percentual de Reajuste |
0 |
| Característica do Reajuste |
Sem Reajuste |
| Justificativa Técnica |
Preencher obrigatoriamente a expressão “EM NEGOCIAÇÃO” |
Caso não seja aplicado reajuste ao longo dos 12 meses que sucederem a data de aniversário do contrato não deverá ser transmitido novo comunicado.
1.2) Após o término das negociações, caso seja aplicado algum reajuste (positivo ou negativo), a operadora deverá comunicá-lo em até 30 dias, de acordo com a tabela 2 deste Anexo.
Tabela 2
| Mês/Ano Início Período da Aplicação |
Mês/Ano no qual o reajuste foi efetivamente aplicado |
Mês/Ano do aniversário do contrato. |
| Mês/Ano Final Período de Aplicação |
Mês/Ano imediatamente anterior ao próximo aniversário do contrato |
Mês/Ano imediatamente anterior ao próximo aniversário do contrato |
| Justificativa Técnica |
(a) Justificativa técnica; (b) data de aniversário do contrato; |
(a) Justificativa técnica; (b) mês/ano em que a cobrança foi efetivamente iniciada; (c) informação de que será efetuada a cobrança retroativa acordada entre as partes. |
De acordo com o § 2º do art. 2º para cada período de 12 meses deverá haver ao menos uma comunicação de reajuste (positivo ou negativo), revisão ou manutenção da contraprestação pecuniária.
[pós IN 47]
Comunicados “EM NEGOCIAÇÃO” não são mais considerados comunicados definitivos de reajuste.
TRATAMENTOS
Resumo das regras a serem aplicadas por id_comunicado:
- [pós IN 47] Excluir aviso de comunicado em atraso por NEGOCIACAO
- [pré IN 47] Excluir aviso de NEGOCIAÇÃO quando houver comunicados com aplicação anterior ao próximo aniversário do contrato
Nota: esse script de tratamento de comunicados de negociação deve ser aplicado sobre uma base que traga pelo menos 11 meses além da última data de interesse da consulta para que o programa possa eliminar os avisos de atraso no envio por negociação se houverem comunicados de reajuste posteriores referentes aos casos sem cobrança retroativa ao mês de aniversário.
rpc2 |> group_by(ano = year(dt_inic_aplicacao)) |>
summarise(negoc = sum(lg_negociacao),
pct = round(negoc/n()*100,1))
Marca avisos de comunicado em atraso por NEGOCIACAO e seus substitutos posteriores conforme o caso.
rpc2 <- rpc2 |>
# se tiver marcação de aviso de negociação, porém o percentual informado for diferente de zero,
# o filtro dos termos usados no campo texto da justificativa falhou e precisa ser corrigido
mutate(lg_negociacao = if_else(lg_negociacao == 1 & percentual == 0, 1, 0)) |>
# marca se algum aviso de negociacao foi enviado após IN 47
mutate(lg.in47 = if_else(lg_negociacao == 1 & dt_envio >= dt.in47, 1, 0)) |>
# marca comunicados com avisos de negociação
group_by(id_comunicado) |>
mutate(lg.alterar = if_else(sum(lg_negociacao) > 0, 1L, 0L)) |>
ungroup()
Note que não haviam avisos de negociação enviados após a IN 47 na base extraída - talvez esses comunicados tenham sido excluídos na extração da base RPC.
Trata avisos de comunicado em atraso por NEGOCIACAO aplicando as regras apropriadas para envios anteriores e posteriores à entrada em vigor da IN 47.
last.row <- nrow(rpc2)
rpc3 <- rpc2 |>
filter(lg.alterar != 0L) |> # Trata apenas dos casos de negociação
# exclui avisos de negociacao enviados após IN 47
filter(!(lg.in47 == 1L & lg_negociacao == 1L)) |>
# exclui avisos de negociacao enviados pré IN 47 que tenham comunicado definitivo posterior
# com início de aplicação a menos de 12 meses do aviso de negociação
arrange(id_comunicado, dt_inic_aplicacao, desc(lg_negociacao), id_envio) |>
filter(!( # Exclui a linha SE
lg_negociacao == 1L # for aviso de negociação
& lg.in47 == 0L # enviado antes da IN 47
& row_number() != last.row # não for a última linha da tabela
& lead(id_comunicado) == id_comunicado # a próxima linha for do mesmo comunicado
# e seu início de aplicação for em um intervalo inferior a 12 meses
& interval(dt_inic_aplicacao, lead(dt_inic_aplicacao)) %/% months(1) < 12
)) |>
# acerta a ordem das colunas para juntar as bases
select(colnames(rpc2)) |>
rbind(filter(rpc2, lg.alterar == 0L))
remove(last.row)
Adesão
Exclusivamente para contratos vigentes que permaneçam incompatíveis com a RN nº 195, de 2009, quando a definição do percentual de reajuste e do período de aplicação de um mesmo plano e contrato for diferenciada em função da data de adesão de seus beneficiários:
[pré IN 47]
A cada mês em que haja aniversário de adesão de beneficiários, a operadora deverá informar a variação positiva, negativa ou nula.
[pós IN 47]
A operadora deverá comunicar um percentual único e calculado como a média dos reajustes aplicados a cada mês em que houve aniversário de adesão de beneficiários ponderada pela quantidade de beneficiários em cada grupo de adesão, de acordo com a seguinte fórmula:
PF = [ (r1 x b1) + (r2 x b2) + … + (rn x bn) ] / QB
onde:
PF é o percentual final que deverá ser comunicado
QB é a quantidade total de beneficiários do contrato
r é o reajuste aplicado ao grupo de adesão
b é a quantidade de beneficiários do grupo de adesão
rn é o reajuste aplicado ao n-ésimo grupo de adesão
bn é a quantidade de beneficiários do n-ésimo grupo de adesão e n é a quantidade de grupos de adesão, limitada a 12.
TRATAMENTOS
Não cabe aplicação de tratamentos especiais para casos excepcionais de contratos não adaptados à RN nº 195 que apliquem reajustes diferenciados por data de adesão do beneficiário. Tanto antes quanto depois das alterações da IN DIPRO nº 47/2014 todos os comunicados que seguem essas regras devem ser incorporados na base de reajustes de planos coletivos conforme as instruções de envio e são compatíveis com os cálculos de reajuste médio ponderado pela quantidade de beneficiários.
Parcelado
Quando o reajuste for aplicado de forma parcelada (mais de um reajuste ao longo de um período de 12 meses). Lembrando que a RN nº 195 determina que nenhum contrato poderá receber qualquer variação positiva na contraprestação pecuniária em periodicidade inferior a doze meses, ressalvados os reajustes por variação de faixa etária e migração ou adaptação de contrato.
[pré IN 47]
Cada uma das parcelas deve ser comunicada em até 30 dias da sua aplicação. A operadora deverá informar o percentual de reajuste, o período de aplicação e justificativa.
As parcelas deverão ser calculadas de acordo com a seguinte fórmula:
PT = [(1+P1) x (1+P2) x … x (1+Pn)] - 1
Onde:
PT é o percentual total
P1 é a parcela referente ao 1º reajuste
P2 é a parcela referente ao 2º reajuste
Pn é a parcela referente ao n-ésimo reajuste
pós IN 47:
Informar, nos moldes do Anexo I desta IN, o percentual que reflita o reajuste total que será aplicado ao contrato após a aplicação de todas as parcelas, de acordo com a seguinte fórmula:
RT = [(1+P1) x (1+P2) x … x (1+Pn)] - 1
Onde:
RT é o percentual de reajuste total que será aplicado
P1 é a 1ª parcela do reajuste
P2 é a 2ª parcela do reajuste
Pn é a n-ésima parcela do reajuste e
n é a quantidade de parcelas, limitada a 12.
TRATAMENTOS
Não cabe aplicação de tratamentos especiais para casos de reajustes parcelados. Tanto antes quanto depois das alterações da IN DIPRO nº 47/2014 todos os comunicados que seguem essas regras devem ser incorporados na base de reajustes de planos coletivos conforme as instruções de envio e são compatíveis com os cálculos de reajuste médio ponderado pela quantidade de beneficiários.
Grava datasets
Prepara datasets para exportar em formato .csv
# RPS
rps <- fread("_datasets/vw_rps_cadop.csv") |>
lazy_dt() |>
rename_with(tolower) |>
select(id_plano, cd_plano, cd_operadora, tp_vigencia = vigencia_plano) |>
as_tibble()
# dataset modelo publicado no PDA
pda <- fread("_datasets/PDA_RPC_201501.csv") |>
lazy_dt() |>
rename_with(tolower) |>
as_tibble()
rpc.final <- select(rpc3, id_envio, benef_comunicado = benef, percentual) |>
inner_join(select(rpc, -c(benef_comunicado, percentual)), by = "id_envio") |>
select(-id_envio) |>
inner_join(rps, by = "id_plano") |>
# exclui o último ano da base (só foi usado para deduplicação de avisos de negociação
# de contratos com aniversário até dezembro do ano anterior)
filter(dt_inic_aplicacao <= max(rpc$dt_inic_aplicacao) - years(1)) |>
select(colnames(pda))
# registra total de envios e comunicados por ano para controle
tt.ano.pre <- rpc0 |>
# exclui o último ano da base (só foi usado para deduplicação de avisos de negociação
# de contratos com aniversário até dezembro do ano anterior)
filter(dt_inic_aplicacao <= max(rpc$dt_inic_aplicacao) - years(1)) |>
group_by(ano = year(dt_inic_aplicacao)) |>
summarise(envios = n(),
comunicados = n_distinct(id_comunicado),
.groups = "drop")
tt.ano.pos <- rpc.final |>
group_by(ano = year(dt_inic_aplicacao)) |>
summarise(envios = n(),
comunicados = n_distinct(id_plano, id_contrato),
.groups = "drop")
tt.ano <- tt.ano.pre |>
inner_join(tt.ano.pos, by = c("ano"), suffix = c(".pre",".pos")) |>
rbind(fread("total_por_ano.csv"))
remove(tt.ano.pre, tt.ano.pos)
Exporta datasets
fwrite(rpc.final |> select(colnames(pda)),
paste0("_datasets_PDA/rpc_pda ",
format(max(rpc.final$dt_inic_aplicacao), "%Y"), ".csv"))
fwrite(tt.ano, "total_por_ano.csv")
LS0tDQp0aXRsZTogIlRyYXRhbWVudG8gZGUgZGFkb3MgUlBDIg0KYXV0aG9yOiAiQWfDqm5jaWEgTmFjaW9uYWwgZGUgU2HDumRlIFN1cGxlbWVudGFyIg0KZGF0ZTogIjE1LzA5LzIwMjEiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDMNCiAgICB0b2NfZmxvYXQ6IHllcw0KLS0tDQogDQpUcmF0YSBiYXNlIGRlIGNvbXVuaWNhZG9zIFJQQyAoZGVkdXBsaWNhw6fDo28gZGUgY29tdW5pY2Fkb3MpIGNvbnNpZGVyYW5kbyBvcyBjYXNvcyBlc3BlY2lhaXMgaWRlbnRpZmljYWRvcyBuYSBJTiBESVBSTyBuwrogMTMvMjAwNiBhbnRlcyBlIGRlcG9pcyBkYXMgYWx0ZXJhw6fDtWVzIGltcGxlbWVudGFkYXMgcGVsYSBlbnRyYWRhIGVtIHZpZ29yIGRhIElOIERJUFJPIG7CuiA0Ny8yMDE0LiAgICAgDQogICAgICAgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRQ0KKQ0KDQojIFBBQ09URVMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpsaWJyYXJ5KGRhdGEudGFibGUpICMgcGFyYSB0cmFiYWxoYXIgY29tIHRhYmVsYXMgZ2lnYW50ZXMNCmxpYnJhcnkodGlkeXZlcnNlKSAjIHBhcmEgdHJhYmFsaGFyIGNvbSB0YWJlbGFzDQpsaWJyYXJ5KGR0cGx5cikgIyBwYXJhIHVzYXIgdmVsb2NpZGFkZSBkYXRhLnRhYmxlIG5vIGRwbHlyDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgIyBwYXJhIHRyYWJhbGhhciBjb20gZGF0YXMNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KDQpvcHRpb25zKHNjaXBlbj05OTkpICMgIkRlc2xpZ2EiIG5vdGHDp8OjbyBjaWVudMOtZmljYS4gDQpybShsaXN0PWxzKCkpICMgTGltcGEgbyBnbG9iYWwgZW52aXJvbm1lbnQNCg0KIyBQTE9UUyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoIGJhc2Vfc2l6ZSA9IDEwICkgKSAjIHNldCBkZWZhdWx0IHBsb3QgdGhlbWUNCiMgY2hvb3NlIHNldHRpbmdzIGZvciBzcGVjaWZpYyBwbG90IGVsZW1lbnRzDQp0aGVtZV91cGRhdGUoDQogIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksICMgcmVtb3ZlIG1ham9yIGdyaWQgbGluZXMNCiAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgIyByZW1vdmUgYWxsIG1pbm9yIGdyaWQgbGluZXMNCiAgbGVnZW5kLnRpdGxlICAgICA9IGVsZW1lbnRfYmxhbmsoKSwgIyByZW1vdmUgdMOtdHVsbyBkYSBsZWdlbmRhDQogIGF4aXMudGl0bGUgICAgICAgPSBlbGVtZW50X2JsYW5rKCksICMgcmVtb3ZlIGF4aXMgdGl0bGVzDQogIGxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gJ2dyYXk4MCcpLA0KICByZWN0ID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICdncmF5ODAnKSwNCiAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAnZ3JheTYwJyksDQogIHBsb3QudGl0bGUgICAgPSBlbGVtZW50X3RleHQoZmFjZSA9ICdib2xkJyksDQogIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICdpdGFsaWMnKSwNCiAgcGxvdC5jYXB0aW9uICA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgaGp1c3QgPSAwKSwNCiAgYXhpcy50ZXh0ICAgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2dyYXk3MCcpLA0KICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgY29sb3IgPSAnZ3JheTUwJyksDQogIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmV5ODUiKSwNCiAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2dyYXk0MCcpDQopDQp0aGVtZS5saW5lIDwtIGZ1bmN0aW9uKCkgew0KICB0aGVtZSgNCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAnZGFzaGVkJykNCiAgKQ0KfQ0KDQojIElOSUNJTyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCnJtKGxpc3Q9bHMoKSkgIyBMaW1wYSBvIGdsb2JhbCBlbnZpcm9ubWVudA0KDQp3cml0ZS5leGNlbCA8LSBmdW5jdGlvbih4LCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1UUlVFLC4uLikgew0KICB3cml0ZS50YWJsZSh4LCJjbGlwYm9hcmQiLA0KICAgICAgICAgICAgICBzZXA9Ilx0IiwNCiAgICAgICAgICAgICAgcm93Lm5hbWVzPXJvdy5uYW1lcywgY29sLm5hbWVzPWNvbC5uYW1lcywuLi4pDQp9ICMgZnVuY3Rpb24gdG8gY29weSBhIGRmIHRvIGNsaXBib2FyZCBhbmQgcGFzdGUgdG8gRXhjZWwNCmBgYA0KDQoqKioNCiMgUHJlcGFyYcOnw6NvDQoNCmBgYHtyfQ0KIyBncmF2YSBkYXRhIGRlIGVudHJhZGEgZW0gdmlnb3IgZGEgSU4gNDcNCmR0LmluNDcgPC0geW1kKCIyMDE0LTEyLTA0IikgDQpgYGANCg0KDQojIyBMb2FkIGRhdGFzZXRzDQoNCipOb3RhOiBhIGJhc2UgZG8gUlBDIGEgc2VyIHRyYXRhZGEgdGVtIHF1ZSB0cmF6ZXIgcGVsbyBtZW5vcyB1bWEgc2VxdWVuY2lhIGRlIDIgYW5vcyBkZSByZWFqdXN0ZXMgYXBsaWNhZG9zIChmaWx0cmFyIHBlbG8gY2FtcG8gYGR0X2luaWNfYXBsaWNhY2FvYCkqDQoNCmBgYHtyfQ0KIyBCYXNlKHMpIFJQQw0KZmlsZXMgPC0gbGlzdC5maWxlcyhwYXRoID0gIl9kYXRhc2V0cy9SUEMiLCBwYXR0ZXJuID0gIiouY3N2IiwgZnVsbC5uYW1lcyA9IFQpDQpycGMgPC0gcmJpbmRsaXN0KGxhcHBseShmaWxlcywgZnJlYWQsIHNob3dQcm9ncmVzcyA9IEZBTFNFKSkgfD4NCiAgbGF6eV9kdCgpIHw+DQogIHJlbmFtZV93aXRoKHRvbG93ZXIpIHw+DQogIHNlbGVjdCgtYyhubV9qdXN0aWZpY2F0aXZhLCBubV9qdXN0aWZpY2F0aXZhX3RyYXRhZGEsIGNkX3BsYW5vLCBjZF9vcGVyYWRvcmEpKSB8PiANCiAgIyBpbmRleGEgYSBiYXNlIG9yaWdpbmFsIHBhcmEgcmVzZ2F0YXIgdG9kb3Mgb3MgYXRyaWJ1dG9zIGRvcyBjb211bmljYWRvcyBhcMOzcyBkZWR1cGxpY2HDp8O1ZXMNCiAgYXJyYW5nZShkdF9wcm90b2NvbG8pIHw+IA0KICBtdXRhdGUoaWRfZW52aW8gPSByb3dfbnVtYmVyKCksDQogICAgICAgICBkdF9pbmljX2FwbGljYWNhbyA9IHltZChkdF9pbmljX2FwbGljYWNhbykpIHw+IA0KICBhc190aWJibGUoKQ0KcmVtb3ZlKGZpbGVzKQ0KDQoNCiMgRW54dWdhIG8gZGF0YXNldCBkbyBSUEMgcGFyYSBwb2RlciB0cmFiYWxoYXIgY29tIGJhc2UgZ2lnYW50ZXNjYQ0KcnBjMCA8LSBycGMgfD4gDQogIHNlbGVjdChpZF9jb211bmljYWRvLCBpZF9wbGFubywgDQogICAgICAgICBkdF9pbmljX2FwbGljYWNhbywNCiAgICAgICAgIHN0YXJ0c193aXRoKCJsZ18iKSwNCiAgICAgICAgIGJlbmVmID0gYmVuZWZfY29tdW5pY2FkbywgcGVyY2VudHVhbCwgZHRfcHJvdG9jb2xvLCBpZF9lbnZpbykgfD4NCiAgbXV0YXRlKA0KICAgIGR0X2VudmlvID0gYXNfZGF0ZShkdF9wcm90b2NvbG8pLA0KICAgIGxnX3JwcyA9IGlmX2Vsc2UoaWRfcGxhbm8gPiAwLCAxLCAwKQ0KICApIHw+IA0KICBzZWxlY3QoLWMobGdfaW50cm9kdWNhb19mcmFucXVpYV9jb3B0LCBsZ19hZGVzYW8sIGxnX3BhcmNlbGFkbywgDQogICAgICAgICAgICBkdF9wcm90b2NvbG8sIGlkX3BsYW5vKSkgfD4gDQogIHJlbG9jYXRlKGR0X2VudmlvLCAuYWZ0ZXIgPSBpZF9jb211bmljYWRvKQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpycGMwIHw+IGdyb3VwX2J5KGxnX3JwcykgfD4gDQogIHN1bW1hcmlzZShlbnZpb3MgPSBuKCksIA0KICAgICAgICAgICAgY29tdW5pY2Fkb3MgPSBuX2Rpc3RpbmN0KGlkX2NvbXVuaWNhZG8pLA0KICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIikgfD4gDQogIGFkZF90YWxseSh3ID0gY29tdW5pY2Fkb3MsIG5hbWUgPSAidG90YWwiKSB8PiANCiAgbXV0YXRlKHBjdCA9IHJvdW5kKGNvbXVuaWNhZG9zL3RvdGFsKjEwMCwgMSksDQogICAgICAgICBlbnZpb3MucG9yLmNvbXVuaWNhZG8gPSByb3VuZChlbnZpb3MvY29tdW5pY2Fkb3MsIDEpKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIHJlZ2lzdHJhIGVudmlvcyBzZW0gbWF0Y2ggbm8gcnBzIHBhcmEgY29udHJvbGUNCnR0LnJwcyA8LSBycGMwIHw+IA0KICBmaWx0ZXIoZHRfaW5pY19hcGxpY2FjYW8gPD0gbWF4KHJwYyRkdF9pbmljX2FwbGljYWNhbykgLSB5ZWFycygxKSkgfD4gDQogIGdyb3VwX2J5KGxnX3JwcykgfD4gDQogIHN1bW1hcmlzZShlbnZpb3MgPSBuKCksIA0KICAgICAgICAgICAgY29tdW5pY2Fkb3MgPSBuX2Rpc3RpbmN0KGlkX2NvbXVuaWNhZG8pLA0KICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIikgfD4gDQogIG11dGF0ZShhbm8gPSB5ZWFyKG1pbihycGMkZHRfaW5pY19hcGxpY2FjYW8pKSkgfD4gDQogIHJiaW5kKGZyZWFkKCJ0b3RhbF9tYXRjaF9ycHMuY3N2IikpDQoNCmZ3cml0ZSh0dC5ycHMsICJ0b3RhbF9tYXRjaF9ycHMuY3N2IikNCnJlbW92ZSh0dC5ycHMpDQpgYGANCg0KDQo8YnI+DQpQZXLDrW9kbyBkZSBhYnJhbmfDqm5jaWEgZG8gZGF0YXNldCBwZWxhIGRhdGEgZGUgYXBsaWNhw6fDo28gZG8gcmVhanVzdGUgKGBkdF9pbmljX2FwbGljYWNhb2ApDQoqTm90YTogYSBiYXNlIGRvIFJQQyBhIHNlciB0cmF0YWRhIHRlbSBxdWUgdHJhemVyIHBlbG8gbWVub3MgMTEgbWVzZXMgYSBtYWlzIGRvIHF1ZSBvIMO6bHRpbW8gbcOqcyBkZSBpbnRlcmVzc2UgZGEgY29uc3VsdGEuIE91IHNlamEsIHNlIG8gcGVyw61vZG8gZGUgY29uc3VsdGEgZm9yIGphbiBhIGRleiAyMDEwLCDDqSBuZWNlc3PDoXJpbyB0cmF6ZXIgdHJhdGFyIHVtYSBiYXNlIGRlIHJlYWp1c3RlcyBjb20gZGF0YSBkZSBpbsOtY2lvIGRlIGFwbGljYcOnw6NvIGF0w6kgbm92ZW1icm8gZGUgMjAxMS4qDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpmb3JtYXQocmFuZ2UocnBjMCRkdF9pbmljX2FwbGljYWNhbyksICIlYi0lWSIpDQpgYGANCg0KPGJyPg0KUGVyw61vZG8gZGUgYWJyYW5nw6puY2lhIGRvIGRhdGFzZXQgcGVsYSBkYXRhIGRlIGVudmlvIGRvIGNvbXVuaWNhZG8gKGBkdF9lbnZpb2ApKSAgICAgIA0KKk5vdGUgcXVlIHBvZGVtIGV4aXN0aXIgY29tdW5pY2Fkb3MgZW52aWFkb3MgYW50ZXMgZSBkZXBvaXMgZG8gbWFyY28gZGUgZW50cmFkYSBlbSB2aWdvciBkYXMgYWx0ZXJhw6fDtWVzIGRhIElOIERJUFJPIG7CuiAxMyAoMDQvMTIvMjAwNCkuKg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcmFuZ2UoYXNfZGF0ZShycGMkZHRfcHJvdG9jb2xvKSkNCmBgYA0KDQo8YnI+DQoNCioqKg0KIyBEZWR1cGxpY2HDp8OjbyAgICAgIA0KKioqDQogICAgICAgICANCkV4aXN0ZW0gNSBjYXNvcyBlc3BlY2lhaXMgZGUgY29tdW5pY2FkbyBSUEMgcXVlIGdlcmFtIGR1cGxpY2lkYWRlIGRlIGVudmlvIGRlIGNvbXVuaWNhZG9zIG5vIFJQQyBlIGZvcmFtIGFsdGVyYWRvcyBwZWxhIElOIERJUFJPIG7CuiA0Ny8yMDE0IHBhcmEgY29tdW5pY2Fkb3MgZW52aWFkb3MgYSBwYXJ0aXIgZGUgMDQgZGUgZGV6ZW1icm8gZGUgMjAxNDogICAgIA0KICAgICAgIA0KMS4gQ0FOQ0VMQU1FTlRPIC0gQ2FuY2VsYW1lbnRvIGRlIGNvbXVuaWNhZG9zIGFudGVyaW9yZXMgICAgIA0KMi4gUkVUSUZJQ0FDQU8gLSBSZXRpZmljYcOnw7VlcyBkZSBjb211bmljYWRvcyBhbnRlcmlvcmVzICAgICANCjMuIEVNIE5FR09DSUFDQU8gLSBBdmlzbyBkZSAicmVhanVzdGUgZW0gbmVnb2NpYcOnw6NvIiAgICAgDQo0LiBBREVTw4NPIC0gQ2Fzb3MgZXhjZXBjaW9uYWlzIGRlIGNvbnRyYXRvcyBhdXRvcml6YWRvcyBhIGFwbGljYXIgcmVhanVzdGVzIHBvciBkYXRhIGRlIGFkZXPDo28gZG8gYmVuZWZpY2nDoXJpbyAgICAgDQo1LiBQQVJDRUxBRE8gLSBDYXNvcyBleGNlcGljaW9uYWlzIGRlIGNvbnRyYXRvcyBhdXRvcml6YWRvcyBhIGFwbGljYXIgcmVhanVzdGUgcGFyY2VsYWRvICAgICAgIA0KICAgICAgIA0KRXN0ZXMgY2Fzb3Mgc2Vyw6NvIHRyYXRhZG9zIGEgc2VndWlyLg0KICAgICAgIA0KKioqDQojIyBDYW5jZWxhbWVudG8gICAgICANCiAgICAgIA0KDQoqKltwcsOpIElOIDQ3XSoqICAgICAgDQpOw6NvIGV4aXN0aWEgYSBwb3NzaWJpbGlkYWRlIGRlIGNhbmNlbGFyIGNvbXVuaWNhZG9zIGFudGVzIGRhIElOIDQ3Lg0KICAgICAgICAgICAgDQogICAgICAgICAgICANCioqW3DDs3MgSU4gNDddKiogICAgIA0KVFJFQ0hPIFJFUFJPRFVaSURPIERPIEFORVhPIElJIERBIElOIG7CuiAxMy8yMDA2ICAgICAgICAgDQoqNS4yKSBQYXJhIGNhbmNlbGFyIHVtIGNvbXVuaWNhZG8gZGUgcmVhanVzdGUsIGEgb3BlcmFkb3JhIGRldmVyw6EgZW52aWFyIHVtIG5vdm8gY29tdW5pY2FkbywgZGUgYWNvcmRvIGNvbSBhIFRhYmVsYSA0IGRlc3RlIEFuZXhvLiogICAgIA0KICAgICAgDQoqVGFiZWxhIDQqICAgICAgDQogICAgICANCkNhbXBvIAkJCQkJCQkJICAgICAgICAgICAgICB8IEluc3RydcOnw6NvDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICAgICB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KTsK6IGRlIFJlZ2lzdHJvIGRvIFBsYW5vIAkJCSAgICAgIHwgTyBtZXNtbyBkbyBjb211bmljYWRvIGEgc2VyIGNhbmNlbGFkbw0KQ8OzZGlnbyBkbyBwbGFubyBuYSBvcGVyYWRvcmEgCQkgICAgfCBPIG1lc21vIGRvIGNvbXVuaWNhZG8gYSBzZXIgY2FuY2VsYWRvDQpOwrogZG8gY29udHJhdG8gb3UgYXDDs2xpY2UgCQkJICAgIHwgTyBtZXNtbyBkbyBjb211bmljYWRvIGEgc2VyIGNhbmNlbGFkbw0KTcOqcy9Bbm8gSW7DrWNpbyBQZXLDrW9kbyBkYSBBcGxpY2HDp8OjbyB8IE8gbWVzbW8gZG8gY29tdW5pY2FkbyBhIHNlciBjYW5jZWxhZG8NClBlcmNlbnR1YWwgZGUgUmVhanVzdGUgCQkJCSAgICAgIHwgMCAoWkVSTykNCkNhcmFjdGVyw61zdGljYSBkbyBSZWFqdXN0ZSAJCQkgICAgfCBTZW0gUmVhanVzdGUNCkp1c3RpZmljYXRpdmEgVMOpY25pY2EJCQkJICAgICAgICB8IChhKSBQcmVlbmNoZXIgb2JyaWdhdG9yaWFtZW50ZSBjb20gYSBleHByZXNzw6NvIOKAnENBTkNFTEFSIENPTVVOSUNBRE/igJ0gKGIpIEp1c3RpZmljYXRpdmEgcGFyYSBvIGNhbmNlbGFtZW50by4NCiAgICAgIA0KNS4zKSBQYXJhIHJldGlmaWNhciBhcyBpbmZvcm1hw6fDtWVzIGRlOiAiTsK6IGRlIFJlZ2lzdHJvIGRvIFBsYW5vIiwgIkPDs2RpZ28gZG8gcGxhbm8gbmEgb3BlcmFkb3JhIiwgIk7CuiBkbyBjb250cmF0byBvdSBhcMOzbGljZSIsIGUgIk3DqnMvQW5vIEluw61jaW8gUGVyw61vZG8gZGUgQXBsaWNhw6fDo28iLCBvIGNvbXVuaWNhZG8gZGV2ZXLDoSBzZXIgY2FuY2VsYWRvLCBjb25mb3JtZSBkZWZpbmlkbyBubyBpdGVtIDUuMiwgZSB1bSBub3ZvIGNvbXVuaWNhZG8gZGV2ZXLDoSBzZXIgZW52aWFkby4gICAgICANCiAgICAgDQogICAgICANCg0KKioqDQoqKlRSQVRBTUVOVE9TKiogICAgICANCiAgICAgDQo6Ojogey5hbGVydCAuYWxlcnQtYmxvY2sgLmFsZXJ0LWRhbmdlcn0NClJlc3VtbyBkYXMgcmVncmFzIGEgc2VyZW0gYXBsaWNhZGFzIHBvciBgaWRfY29tdW5pY2Fkb2AgZSBgZHRfaW5pY19hcGxpY2FjYW9gOiAgICAgDQogICAgICAgDQoqIFtww7NzIElOIDQ3XSBFeGNsdWlyIGF2aXNvIGRlIENBTkNFTEFNRU5UTyBlIG8gY29tdW5pY2FkbyBvcmlnaW5hbCBhIHNlciBjYW5jZWxhZG8gICAgICANCg0KOjo6DQogICAgIA0KVG90YWxpemEgYXZpc29zIGRlIGNhbmNlbGFtZW50byBwb3IgYW5vLg0KDQpgYGB7cn0NCnJwYzAgfD4gDQogIGdyb3VwX2J5KGFubyA9IHllYXIoZHRfaW5pY19hcGxpY2FjYW8pKSB8Pg0KICBzdW1tYXJpc2UoY2FuY2VsYW1lbnRvcyA9IHN1bShsZ19jYW5jZWxhbWVudG8pLA0KICAgICAgICAgICAgcGN0ID0gcm91bmQoY2FuY2VsYW1lbnRvcy9uKCkqMTAwLDMpKQ0KYGBgDQoNCg0KPGJyPg0KICAgICAgICANCkV4Y2x1aSBvIGF2aXNvIGRlIENBTkNFTEFNRU5UTyBlIG8gY29tdW5pY2FkbyBvcmlnaW5hbCBhIHNlciBjYW5jZWxhZG8uIA0KDQpgYGB7cn0NCiMgSWRlbnRpZmljYSBjYW5jZWxhbWVudG9zDQpsYXN0LnJvdyA8LSBucm93KHJwYzApDQpycGMxIDwtIHJwYzAgfD4NCiAgIyBjb3JyaWdlIHNlIGNhbmNlbGFtZW50byB0aXZlciBzaWRvIGVudmlhZG8gYW50ZXMgZGEgSU4gNDcNCiAgbXV0YXRlKGxnX2NhbmNlbGFtZW50byA9IGlmX2Vsc2UobGdfY2FuY2VsYW1lbnRvID09IDFMICYgZHRfZW52aW8gPj0gZHQuaW40NywgMUwsIDBMKSkgfD4NCiAgIyBtYXJjYSBjb211bmljYWRvcyBhIHNlcmVtIGRlbGV0YWRvcw0KICBhcnJhbmdlKGlkX2NvbXVuaWNhZG8sIGR0X2luaWNfYXBsaWNhY2FvLCBkdF9lbnZpbykgfD4NCiAgbXV0YXRlKA0KICAgIGxnLmRlbGV0ZSA9IGNhc2Vfd2hlbigNCiAgICAgICMgcXVhbmRvIG8gY29tdW5pY2FkbyBmb3IgYW50ZXJpb3IgYSB1bSBhdmlzbyBkZSBjYW5jZWxhbWVudG8NCiAgICAgIHJvd19udW1iZXIoKSAhPSBsYXN0LnJvdw0KICAgICAgJiBsZWFkKGlkX2NvbXVuaWNhZG8pID09IGlkX2NvbXVuaWNhZG8NCiAgICAgICYgbGVhZChkdF9pbmljX2FwbGljYWNhbykgPT0gZHRfaW5pY19hcGxpY2FjYW8NCiAgICAgICYgbGVhZChsZ19jYW5jZWxhbWVudG8gPT0gMSkgfiAxTCwNCiAgICAgICMgcXVhbmRvIGZvciBvIHByw7NwcmlvIGF2aXNvIGRlIGNhbmNlbGFtZW50bw0KICAgICAgbGdfY2FuY2VsYW1lbnRvID09IDEgfiAxTCwNCiAgICAgIFRSVUUgfiAwTA0KICAgICkNCiAgKSB8PiANCiAgIyBleGNsdWkgYXZpc29zIGRlIGNhbmNlbGFtZW50byBlIGNvbXVuaWNhZG9zIGNhbmNlbGFkb3MNCiAgZmlsdGVyKGxnLmRlbGV0ZSA9PSAwTCkgfD4gc2VsZWN0KC1sZy5kZWxldGUsIC1sZ19jYW5jZWxhbWVudG8pDQoNCnJlbW92ZShsYXN0LnJvdykNCmBgYA0KDQo8YnI+DQoNCmBgYHtyIGVjaG89RkFMU0V9DQpycGMwIHw+IA0KICBncm91cF9ieShhbm8gPSB5ZWFyKGR0X2luaWNfYXBsaWNhY2FvKSkgfD4NCiAgc3VtbWFyaXNlKGFudGVzID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSB8PiANCiAgaW5uZXJfam9pbigNCiAgICBycGMxIHw+IA0KICAgICAgZ3JvdXBfYnkoYW5vID0geWVhcihkdF9pbmljX2FwbGljYWNhbykpIHw+DQogICAgICBzdW1tYXJpc2UoZGVwb2lzID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSwNCiAgICBieSA9ICJhbm8iDQogICkgfD4gDQogIG11dGF0ZShkaWZlcmVuY2EgPSBkZXBvaXMgLSBhbnRlcykNCmBgYA0KDQpgYGB7cn0NCnJwYzEgfD4gZ3JvdXBfYnkoYW5vID0geWVhcihkdF9pbmljX2FwbGljYWNhbykpIHw+IA0KICBzdW1tYXJpc2UoZW52aW9zID0gbigpLCANCiAgICAgICAgICAgIGNvbXVuaWNhZG9zID0gbl9kaXN0aW5jdChpZF9jb211bmljYWRvLCBkdF9pbmljX2FwbGljYWNhbyksDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKSB8PiANCiAgbXV0YXRlKGVudmlvcy5wb3IuY29tdW5pY2FkbyA9IHJvdW5kKGVudmlvcy9jb211bmljYWRvcywgMikpDQpgYGANCg0KDQoqKioNCg0KIyMgUmV0aWZpY2HDp8OjbyAgICAgIA0KICAgICAgICANClRSRUNIT1MgUkVQUk9EVVpJRE9TIERPIEFORVhPIElJIERBIElOIDEzLzIwMDYgICAgICANCiAgICAgICAgICAgICANCioqW3Byw6kgSU4gNDddKiogICAgIA0KKjUuMykgUGFyYSByZXRpZmljYXIgYXBlbmFzIG8gcGVyY2VudHVhbCBkZSByZWFqdXN0ZSwgYSBvcGVyYWRvcmEgZGV2ZXLDoSBpbmZvcm1hciwgdmlhIGFwbGljYXRpdm8sIGEgZGlmZXJlbsOnYSBvdSBhY3LDqXNjaW1vIGRlIGZvcm1hIHF1ZSBvIHBlcmNlbnR1YWwgZmluYWwgc2VqYSBvIHF1ZSBkZXZlcmlhIHNlciBvcmlnaW5hbG1lbnRlIGVudmlhZG8sIG1hbnRlbmRvIGFzIGRlbWFpcyBpbmZvcm1hw6fDtWVzIGRvIGNvbXVuaWNhZG8gb3JpZ2luYWwuKg0KDQpOZXNzZSBjYXNvIG8gcGVyY2VudHVhbCBlZmV0aXZhbWVudGUgYXBsaWNhZG8gYW8gY29tdW5pY2FkbyBkZXZlcsOhIHNlciBjYWxjdWxhZG8gZGUgYWNvcmRvIGNvbSBhIHNlZ3VpbnRlIGbDs3JtdWxhOg0KDQpQQSAgPSBbKDEgKyBQQykgKiAoMSArIFBOKV0gLSAxDQogICAgICANCm9uZGU6ICAgICANClBBIMOpIG8gcGVyY2VudHVhbCBhcGxpY2FkbyBhbyBjb250cmF0byAgICAgDQpQQyDDqSBvIHBlcmNlbnR1YWwgaW5pY2lhbG1lbnRlIGNvbXVuaWNhZG8gw6AgQU5TICAgICANClBOIMOpIG8gcGVyY2VudHVhbCBub3ZvIGRvIGNvbXVuaWNhZG8gZGUgcmV0aWZpY2HDp8OjbyAgICAgDQoNCg0KKipbcMOzcyBJTiA0N10qKiAgICAgIA0KKjUuMSkgUGFyYSByZXRpZmljYXIgcXVhaXNxdWVyIGluZm9ybWHDp8O1ZXMgZG8gY29tdW5pY2FkbyBkZSByZWFqdXN0ZSBkZWZpbmlkYXMgbm8gQW5leG8gSSBkZXN0YSBJbnN0cnXDp8OjbyBOb3JtYXRpdmEsIGNvbSBleGNlw6fDo28gZGU6ICJOwrogZGUgUmVnaXN0cm8gZG8gUGxhbm8iLCAiQ8OzZGlnbyBkbyBwbGFubyBuYSBvcGVyYWRvcmEiLCAiTsK6IGRvIGNvbnRyYXRvIG91IGFww7NsaWNlIiwgZSAiTcOqcy9Bbm8gSW7DrWNpbyBQZXLDrW9kbyBkZSBBcGxpY2HDp8OjbyIsIGEgb3BlcmFkb3JhIGRldmVyw6EgZW52aWFyIHVtIG5vdm8gY29tdW5pY2FkbyB2aWEgUlBDLCBkZSBhY29yZG8gY29tIGEgVGFiZWxhIDMgZGVzdGUgQW5leG8uKiAgICAgDQogICAgICAgDQoqVGFiZWxhIDMqICAgIA0KICAgICAgIA0KQ2FtcG8gCQkJCQkJCQkgICAgICAgICAgICAgIHwgSW5zdHJ1w6fDo28NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gICAgICAgIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpOwrogZGUgUmVnaXN0cm8gZG8gUGxhbm8gCQkJICAgICAgfCBPIG1lc21vIGRvIGNvbXVuaWNhZG8gYSBzZXIgcmV0aWZpY2Fkbw0KQ8OzZGlnbyBkbyBwbGFubyBuYSBvcGVyYWRvcmEgCSAgICAgIHwJTyBtZXNtbyBkbyBjb211bmljYWRvIGEgc2VyIHJldGlmaWNhZG8NCk7CuiBkbyBjb250cmF0byBvdSBhcMOzbGljZSAJCSAgICAgIHwJTyBtZXNtbyBkbyBjb211bmljYWRvIGEgc2VyIHJldGlmaWNhZG8NCk3DqnMvQW5vIEluw61jaW8gUGVyw61vZG8gZGEgQXBsaWNhw6fDo28gfCBPIG1lc21vIGRvIGNvbXVuaWNhZG8gYSBzZXIgcmV0aWZpY2Fkbw0KSnVzdGlmaWNhdGl2YSBUw6ljbmljYQkJCQkgICAgICAgIHwgKGEpIFByZWVuY2hlciBvYnJpZ2F0b3JpYW1lbnRlIGNvbSBhIGV4cHJlc3PDo28g4oCcUkVUSUZJQ0HDh8ODTyBERSBSRUFKVVNUReKAnSAoYilKdXN0aWZpY2F0aXZhIHBhcmEgYSByZXRpZmljYcOnw6NvLg0KDQoqKioNCioqVFJBVEFNRU5UT1MqKiAgICAgIA0KICAgICANCjo6OiB7LmFsZXJ0IC5hbGVydC1ibG9jayAuYWxlcnQtZGFuZ2VyfQ0KUmVzdW1vIGRhcyByZWdyYXMgYSBzZXJlbSBhcGxpY2FkYXMgcG9yIGBpZF9jb211bmljYWRvYCBlIGBkdF9pbmljX2FwbGljYWNhb2A6ICAgICANCiAgICAgICANCiogW3DDs3MgSU4gNDddIEV4Y2x1aXIgY29tdW5pY2FkbyBvcmlnaW5hbCBxdWUgZm9pIHN1YnN0aXR1w61kbyBwb3IgdW1hIHJldGlmaWNhw6fDo28gICAgICAgIA0KKiBbcHLDqSBJTiA0N10gQ2FsY3VsYSBvIHJlYWp1c3RlIGVmZXRpdmFtZW50ZSBhcGxpY2FkbyBhbyBjb250cmF0bywgY29tIGJhc2Ugbm8gb3JpZ2luYWwgZSBzdWEgcmV0aWZpY2HDp8OjbyAgICAgICAgIA0KOjo6DQogICAgIA0KICAgICAgICANCmBgYHtyfQ0KcnBjMSB8PiBncm91cF9ieShhbm8gPSB5ZWFyKGR0X2luaWNfYXBsaWNhY2FvKSkgfD4NCiAgc3VtbWFyaXNlKHJldGlmaWNhY29lcyA9IHN1bShsZ19yZXRpZmljYWNhbyksDQogICAgICAgICAgICBwY3QgPSByb3VuZChyZXRpZmljYWNvZXMvbigpKjEwMCwxKSkNCmBgYA0KDQpNYXJjYSBjb211bmljYWRvcyBkZSByZXRpZmljYcOnw6NvIGUgc2V1cyBvcmlnaW5haXMgYSBzZXJlbSBhbHRlcmFkb3MgY29uZm9ybWUgbyBjYXNvLg0KDQpgYGB7cn0NCiMgSWRlbnRpZmljYSByZXRpZmljYcOnw7Vlcw0KcnBjMSA8LSBycGMxIHw+DQogICMgaWRlbnRpZmljYSBjb211bmljYWRvcyBhIHNlcmVtIHJldGlmaWNhZG9zDQogIGZpbHRlcihsZ19yZXRpZmljYWNhbyA9PSAxKSB8PiANCiAgZGlzdGluY3QoaWRfY29tdW5pY2FkbywgZHRfaW5pY19hcGxpY2FjYW8pIHw+IA0KICBtdXRhdGUobGcuYWx0ZXJhciA9IDFMKSB8PiANCiAgcmlnaHRfam9pbihycGMxLCBieSA9IGMoImlkX2NvbXVuaWNhZG8iLCAiZHRfaW5pY19hcGxpY2FjYW8iKSkgfD4gDQogIG11dGF0ZSgNCiAgICAjIG1hcmNhIHNlIHJldGlmaWNhw6fDo28gZm9pIGVudmlhZGEgYW50ZXMgb3UgZGVwb2lzIGRhIElOIDQ3DQogICAgbGcuaW40NyA9IGlmX2Vsc2UobGdfcmV0aWZpY2FjYW8gPT0gMUwgJiBkdF9lbnZpbyA+PSBkdC5pbjQ3LCAxTCwgMEwpDQogICkgDQpycGMxJGxnLmFsdGVyYXJbaXMubmEocnBjMSRsZy5hbHRlcmFyKV0gPC0gMEwNCmBgYA0KDQoNCjxicj4NClRyYXRhICoqcmV0aWZpY2HDp8O1ZXMqKiBhcGxpY2FuZG8gYXMgcmVncmFzIGFwcm9wcmlhZGFzIHBhcmEgZW52aW9zIGFudGVyaW9yZXMgZSBwb3N0ZXJpb3JlcyDDoCBlbnRyYWRhIGVtIHZpZ29yIGRhIElOIDQ3Lg0KDQpgYGB7cn0NCiMgQXBsaWNhIHJldGlmaWNhw6fDtWVzIGFvcyBjb211bmljYWRvcyBvcmlnaW5haXMNCnJwYzIgPC0gcnBjMSB8Pg0KICBmaWx0ZXIobGcuYWx0ZXJhciAhPSAwTCkgfD4gIyBUcmF0YSBhcGVuYXMgZG9zIGNhc29zIGRlIHJldGlmaWNhw6fDo28NCg0KICAjIG1hcmNhIGEgc2VxdcOqbmNpYSAob3JkZW0pIGRlIGVudmlvcyBkbyBtYWlzIGFudGlnbyBwYXJhIG8gbWFpcyByZWNlbnRlDQogIGFycmFuZ2UoaWRfY29tdW5pY2FkbywgZHRfaW5pY19hcGxpY2FjYW8sIGlkX2VudmlvKSB8Pg0KICBncm91cF9ieShpZF9jb211bmljYWRvLCBkdF9pbmljX2FwbGljYWNhbykgfD4NCiAgbXV0YXRlKG9yZCA9IHJvd19udW1iZXIoKSwNCiAgICAgICAgIG4ub2JzID0gbigpLA0KICAgICAgICAgbGcuaW40NyA9IHN1bShsZy5pbjQ3KSkgfD4NCiAgdW5ncm91cCgpIHw+DQoNCiAgIyBxdWFuZG8gaG91dmVyIGFsZ3VtYSByZXRpZmljYcOnw6NvIHDDs3MgSU40NywgdmFsZSBvIMO6bHRpbW8gY29tdW5pY2FkbyBlbnZpYWRvDQogIG11dGF0ZShsZy5kZWxldGUgPSBpZl9lbHNlKGxnLmluNDcgPiAwICYgb3JkICE9IG4ub2JzLCAxTCwgMEwpKSB8Pg0KICBmaWx0ZXIobGcuZGVsZXRlID09IDBMKSB8PiBzZWxlY3QoLWxnLmRlbGV0ZSkgfD4NCg0KICAjIHF1YW5kbyBuw6NvIGhvdXZlciBuZW5odW1hIHJldGlmaWNhw6fDo28gcMOzcyBJTjQ3LCBqdW50YSBhIHJldGlmaWNhw6fDo28gZSBvIGNvbXVuaWNhZG8gDQogICMgYW50ZXJpb3IgcGVsYSBmw7NybXVsYSBkZSBjw6FsY3VsbyBkYSBJTg0KICAjIG5vdGE6IHBvZGUgaGF2ZXIgbWFpcyBkZSAxIHJldGlmaWNhw6fDo28sIG1hcyBzZW1wcmUgdmFpIGFwbGljYXIgYSDDumx0aW1hIHJldGlmaWNhw6fDo28gc29icmUgbyANCiAgIyBwcmltZWlybyBjb211bmljYWRvIGVudmlhZG8gKGNvbXVuaWNhZG8gb3JpZ2luYWwpLiBUb2RvcyBvcyBvdXRyb3MgY29tdW5pY2Fkb3Mgc2Vyw6NvIA0KICAjIGRlc2NvbnNpZGVyYWRvcy4NCiAgZmlsdGVyKG9yZCA9PSAxIHwgb3JkID09IG4ub2JzKSB8PiAjIGZpbHRyYSBvIGNvbXVuaWNhZG8gb3JpZ2luYWwgZSBhIMO6bHRpbWEgcmV0aWZpY2HDp8Ojbw0KICBhcnJhbmdlKGlkX2NvbXVuaWNhZG8sIGR0X2luaWNfYXBsaWNhY2FvLCBvcmQpIHw+DQogIG11dGF0ZSgNCiAgICBwY3QuaSA9IHBlcmNlbnR1YWwvMTAwKzEsICMgaW5kZXhhIG8gcGVyY2VudHVhbCBwYXJhIGFwbGljYXIgYSBmw7NybXVsYSBkZSByZXRpZmljYcOnw6NvDQogICAgbGcuZGVsZXRlID0gaWZfZWxzZShsZy5pbjQ3ID09IDAgJiBvcmQgIT0gbi5vYnMsIDFMLCAwTCksICMgbWFyY2EgbyBjb211bmljYWRvIG9yaWdpbmFsDQogICAgDQogICAgIyByZWNhbGN1bGEgbyBwZXJjZW50dWFsIGRvIMO6bHRpbW8gY29tdW5pY2FkbywganVudGFuZG8gY29tIG8gcGVyY2VudHVhbCBkbyBjb211bmljYWRvIG9yaWdpbmFsDQogICAgcGVyY2VudHVhbCA9IGlmX2Vsc2UoDQogICAgICBsZy5pbjQ3ID09IDAgJiBvcmQgPT0gbi5vYnMgICAgICAgICAgICAgICAgICAgICMgc2UgZm9yIHByw6kgSU40NyBlIGZvciBvIMO6bHRpbW8gZW52aW8NCiAgICAgICYgcm93X251bWJlcigpICE9IDEgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzZSBuw6NvIGZvciBhIHByaW1laXJhIGxpbmhhIGRhIHRhYmVsYQ0KICAgICAgJiBsYWcoaWRfY29tdW5pY2FkbykgPT0gaWRfY29tdW5pY2FkbyAgICAgICAgICAjIGUgYSBsaW5oYSBhbnRlcmlvciBmb3IgZG8gbWVzbW8gY29tdW5pY2Fkbw0KICAgICAgJiBsYWcoZHRfaW5pY19hcGxpY2FjYW8pID09IGR0X2luaWNfYXBsaWNhY2FvLCAjIG5hIG1lc21hIGRhdGEgZGUgYXBsaWNhw6fDo28NCiAgICAgICgobGFnKHBjdC5pKSAqIHBjdC5pKSAtIDEpICogMTAwLCAgICAgICAgICAgICAgIyBhcGxpY2EgYSBmw7NybXVsYSBkYSBJTg0KICAgICAgcGVyY2VudHVhbCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNlIG7Do28sIG1hbnTDqW0gbyBwZXJjZW50dWFsIGluYWx0ZXJhZG8NCiAgICApDQogICkgfD4NCiAgZmlsdGVyKGxnLmRlbGV0ZSA9PSAwTCkgfD4gDQoNCiAgIyBhY2VydGEgYSBvcmRlbSBkYXMgY29sdW5hcyBwYXJhIHNlciBhIG1lc21hIGRvIHJwYzEgZSBwb2RlciBqdW50YXIgYXMgZHVhcw0KICBzZWxlY3QoY29sbmFtZXMocnBjMSkpIHw+DQogIHJiaW5kKHJwYzEgfD4gZmlsdGVyKGxnLmFsdGVyYXIgPT0gMEwpKSB8Pg0KICBzZWxlY3QoLWxnX3JldGlmaWNhY2FvLCAtbGcuaW40NywgLWxnLmFsdGVyYXIpDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcnBjMSB8PiANCiAgZ3JvdXBfYnkoYW5vID0geWVhcihkdF9pbmljX2FwbGljYWNhbykpIHw+DQogIHN1bW1hcmlzZShhbnRlcyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikgfD4gDQogIGlubmVyX2pvaW4oDQogICAgcnBjMiB8PiANCiAgICAgIGdyb3VwX2J5KGFubyA9IHllYXIoZHRfaW5pY19hcGxpY2FjYW8pKSB8Pg0KICAgICAgc3VtbWFyaXNlKGRlcG9pcyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIiksDQogICAgYnkgPSAiYW5vIg0KICApIHw+IA0KICBtdXRhdGUoZGlmZXJlbmNhID0gZGVwb2lzIC0gYW50ZXMpDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcnBjMiB8PiBncm91cF9ieShhbm8gPSB5ZWFyKGR0X2luaWNfYXBsaWNhY2FvKSkgfD4gDQogIHN1bW1hcmlzZShlbnZpb3MgPSBuKCksIA0KICAgICAgICAgICAgY29tdW5pY2Fkb3MgPSBuX2Rpc3RpbmN0KGlkX2NvbXVuaWNhZG8sIGR0X2luaWNfYXBsaWNhY2FvKSwNCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpIHw+IA0KICBtdXRhdGUoZW52aW9zLnBvci5jb211bmljYWRvID0gcm91bmQoZW52aW9zL2NvbXVuaWNhZG9zLCAyKSkNCmBgYA0KDQoNCioqKg0KIyMgTmVnb2NpYcOnw6NvICAgICAgDQogICAgICANClRSRUNIT1MgUkVQUk9EVVpJRE9TIERPIEFORVhPIElJIERBIElOIDEzLzIwMDYgICAgICAgDQogICAgICAgICAgICAgDQoqKltwcsOpIElOIDQ3XSoqICAgICANCioxKSBRdWFuZG8gYSBuZWdvY2lhw6fDo28gYW51YWwgdGVuaGEgdWx0cmFwYXNzYWRvIG8gbcOqcyBkZSBhbml2ZXJzw6FyaW8gZG8gY29udHJhdG86KiAgICAgDQoqMS4xKSBDb211bmljYXIgZW0gYXTDqSAzMCBkaWFzIGRvIGFuaXZlcnPDoXJpbyBkbyBjb250cmF0byBhIG1hbnV0ZW7Dp8OjbyBkYSBjb250cmFwcmVzdGHDp8OjbyBwZWN1bmnDoXJpYSwgcG9yIG1laW8gZG8gUlBDLCBkZSBhY29yZG8gY29tIGEgdGFiZWxhIDEuKiAgICAgDQogICAgIA0KKlRhYmVsYSAxKiAgICAgDQogICAgIA0KQ2FtcG8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBJbnN0cnXDp8OjbyAgICAgDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgICB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KTcOqcy9Bbm8gSW7DrWNpbyBQZXLDrW9kbyBkYSBBcGxpY2HDp8OjbyB8IE3DqnMvQW5vIGRvIGFuaXZlcnPDoXJpbyBkbyBjb250cmF0bw0KTcOqcy9Bbm8gRmluYWwgUGVyw61vZG8gZGUgQXBsaWNhw6fDo28JfCBNw6pzL0FubyBpbWVkaWF0YW1lbnRlIGFudGVyaW9yIGFvIHByw7N4aW1vIGFuaXZlcnPDoXJpbyBkbyBjb250cmF0bw0KUGVyY2VudHVhbCBkZSBSZWFqdXN0ZSAgICAgICAgICAgICAgfCAwDQpDYXJhY3RlcsOtc3RpY2EgZG8gUmVhanVzdGUgICAgICAgICAgfCBTZW0gUmVhanVzdGUNCkp1c3RpZmljYXRpdmEgVMOpY25pY2EgICAgICAgICAgICAgICB8IFByZWVuY2hlciBvYnJpZ2F0b3JpYW1lbnRlIGEgZXhwcmVzc8OjbyDigJxFTSBORUdPQ0lBw4fDg0/igJ0NCiAgICAgICAgDQoqKkNhc28gbsOjbyBzZWphIGFwbGljYWRvIHJlYWp1c3RlIGFvIGxvbmdvIGRvcyAxMiBtZXNlcyBxdWUgc3VjZWRlcmVtIGEgZGF0YSBkZSBhbml2ZXJzw6FyaW8gZG8gY29udHJhdG8gbsOjbyBkZXZlcsOhIHNlciB0cmFuc21pdGlkbyBub3ZvIGNvbXVuaWNhZG8uKiogICAgIA0KICAgICANCioxLjIpIEFww7NzIG8gdMOpcm1pbm8gZGFzIG5lZ29jaWHDp8O1ZXMsIGNhc28gc2VqYSBhcGxpY2FkbyBhbGd1bSByZWFqdXN0ZSAocG9zaXRpdm8gb3UgbmVnYXRpdm8pLCBhIG9wZXJhZG9yYSBkZXZlcsOhIGNvbXVuaWPDoS1sbyBlbSBhdMOpIDMwIGRpYXMsIGRlIGFjb3JkbyBjb20gYSB0YWJlbGEgMiBkZXN0ZSBBbmV4by4qICAgICANCiAgICAgDQoqVGFiZWxhIDIgKiAgICAgIA0KICAgICAgICAgIA0KQ2FtcG8gfCBDb2JyYW7Dp2EgbsOjbyByZXRyb2F0aXZhIGFvIG3DqnMgZGUgYW5pdmVyc8OhcmlvIHwgQ29icmFuw6dhIHJldHJvYXRpdmEgYW8gbcOqcyBkZSBhbml2ZXJzw6FyaW8NCi0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gICAgICAgIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpNw6pzL0FubyBJbsOtY2lvIFBlcsOtb2RvIGRhIEFwbGljYcOnw6NvIHwgTcOqcy9Bbm8gbm8gcXVhbCBvIHJlYWp1c3RlIGZvaSBlZmV0aXZhbWVudGUgYXBsaWNhZG8gfCBNw6pzL0FubyBkbyBhbml2ZXJzw6FyaW8gZG8gY29udHJhdG8uDQpNw6pzL0FubyBGaW5hbCBQZXLDrW9kbyBkZSBBcGxpY2HDp8OjbyB8IE3DqnMvQW5vIGltZWRpYXRhbWVudGUgYW50ZXJpb3IgYW8gcHLDs3hpbW8gYW5pdmVyc8OhcmlvIGRvIGNvbnRyYXRvIHwgTcOqcy9Bbm8gaW1lZGlhdGFtZW50ZSBhbnRlcmlvciBhbyBwcsOzeGltbyBhbml2ZXJzw6FyaW8gZG8gY29udHJhdG8NCkp1c3RpZmljYXRpdmEgVMOpY25pY2F8IChhKSBKdXN0aWZpY2F0aXZhIHTDqWNuaWNhOyAoYikgZGF0YSBkZSBhbml2ZXJzw6FyaW8gZG8gY29udHJhdG87IHwgKGEpIEp1c3RpZmljYXRpdmEgdMOpY25pY2E7IChiKSBtw6pzL2FubyBlbSBxdWUgYSBjb2JyYW7Dp2EgZm9pIGVmZXRpdmFtZW50ZSBpbmljaWFkYTsgKGMpIGluZm9ybWHDp8OjbyBkZSBxdWUgc2Vyw6EgZWZldHVhZGEgYSBjb2JyYW7Dp2EgcmV0cm9hdGl2YSBhY29yZGFkYSBlbnRyZSBhcyBwYXJ0ZXMuICAgICANCgkJCQkJCQkJCQkJCQkNCiAgICAgIA0KKkRlIGFjb3JkbyBjb20gbyDCpyAywrogZG8gYXJ0LiAywrogcGFyYSBjYWRhIHBlcsOtb2RvIGRlIDEyIG1lc2VzIGRldmVyw6EgaGF2ZXIgYW8gbWVub3MgdW1hIGNvbXVuaWNhw6fDo28gZGUgcmVhanVzdGUgKHBvc2l0aXZvIG91IG5lZ2F0aXZvKSwgcmV2aXPDo28gb3UgbWFudXRlbsOnw6NvIGRhIGNvbnRyYXByZXN0YcOnw6NvIHBlY3VuacOhcmlhLioNCiAgICAgICAgICAgICAgICANCioqW3DDs3MgSU4gNDddKiogICAgICANCkNvbXVuaWNhZG9zICJFTSBORUdPQ0lBw4fDg08iIG7Do28gc8OjbyBtYWlzIGNvbnNpZGVyYWRvcyBjb211bmljYWRvcyBkZWZpbml0aXZvcyBkZSByZWFqdXN0ZS4gICAgICANCiAgICAgDQoNCg0KKioqDQoqKlRSQVRBTUVOVE9TKiogICAgIA0KICAgICANCjo6OiB7LmFsZXJ0IC5hbGVydC1ibG9jayAuYWxlcnQtZGFuZ2VyfQ0KUmVzdW1vIGRhcyByZWdyYXMgYSBzZXJlbSBhcGxpY2FkYXMgcG9yIGBpZF9jb211bmljYWRvYDogICAgIA0KICAgICANCiogW3DDs3MgSU4gNDddIEV4Y2x1aXIgYXZpc28gZGUgY29tdW5pY2FkbyBlbSBhdHJhc28gcG9yIE5FR09DSUFDQU8gICAgICANCiogW3Byw6kgSU4gNDddIEV4Y2x1aXIgYXZpc28gZGUgTkVHT0NJQcOHw4NPIHF1YW5kbyBob3V2ZXIgY29tdW5pY2Fkb3MgY29tIGFwbGljYcOnw6NvIGFudGVyaW9yIGFvIHByw7N4aW1vIGFuaXZlcnPDoXJpbyBkbyBjb250cmF0byAgICAgIA0KICAgICANCjxicj4NCipOb3RhOiBlc3NlIHNjcmlwdCBkZSB0cmF0YW1lbnRvIGRlIGNvbXVuaWNhZG9zIGRlIG5lZ29jaWHDp8OjbyBkZXZlIHNlciBhcGxpY2FkbyBzb2JyZSB1bWEgYmFzZSBxdWUgdHJhZ2EgcGVsbyBtZW5vcyAxMSBtZXNlcyBhbMOpbSBkYSDDumx0aW1hIGRhdGEgZGUgaW50ZXJlc3NlIGRhIGNvbnN1bHRhIHBhcmEgcXVlIG8gcHJvZ3JhbWEgcG9zc2EgZWxpbWluYXIgb3MgYXZpc29zIGRlIGF0cmFzbyBubyBlbnZpbyBwb3IgbmVnb2NpYcOnw6NvIHNlIGhvdXZlcmVtIGNvbXVuaWNhZG9zIGRlIHJlYWp1c3RlIHBvc3RlcmlvcmVzIHJlZmVyZW50ZXMgYW9zIGNhc29zIHNlbSBjb2JyYW7Dp2EgcmV0cm9hdGl2YSBhbyBtw6pzIGRlIGFuaXZlcnPDoXJpby4qDQo6OjoNCiAgICAgIA0KDQpgYGB7cn0NCnJwYzIgfD4gZ3JvdXBfYnkoYW5vID0geWVhcihkdF9pbmljX2FwbGljYWNhbykpIHw+DQogIHN1bW1hcmlzZShuZWdvYyA9IHN1bShsZ19uZWdvY2lhY2FvKSwNCiAgICAgICAgICAgIHBjdCA9IHJvdW5kKG5lZ29jL24oKSoxMDAsMSkpDQpgYGANCg0KTWFyY2EgYXZpc29zIGRlIGNvbXVuaWNhZG8gZW0gYXRyYXNvIHBvciBORUdPQ0lBQ0FPIGUgc2V1cyBzdWJzdGl0dXRvcyBwb3N0ZXJpb3JlcyBjb25mb3JtZSBvIGNhc28uIA0KDQpgYGB7cn0NCnJwYzIgPC0gcnBjMiB8PiANCiAgIyBzZSB0aXZlciBtYXJjYcOnw6NvIGRlIGF2aXNvIGRlIG5lZ29jaWHDp8OjbywgcG9yw6ltIG8gcGVyY2VudHVhbCBpbmZvcm1hZG8gZm9yIGRpZmVyZW50ZSBkZSB6ZXJvLA0KICAjIG8gZmlsdHJvIGRvcyB0ZXJtb3MgdXNhZG9zIG5vIGNhbXBvIHRleHRvIGRhIGp1c3RpZmljYXRpdmEgZmFsaG91IGUgcHJlY2lzYSBzZXIgY29ycmlnaWRvDQogIG11dGF0ZShsZ19uZWdvY2lhY2FvID0gaWZfZWxzZShsZ19uZWdvY2lhY2FvID09IDEgJiBwZXJjZW50dWFsID09IDAsIDEsIDApKSB8PiANCiAgIyBtYXJjYSBzZSBhbGd1bSBhdmlzbyBkZSBuZWdvY2lhY2FvIGZvaSBlbnZpYWRvIGFww7NzIElOIDQ3DQogIG11dGF0ZShsZy5pbjQ3ID0gaWZfZWxzZShsZ19uZWdvY2lhY2FvID09IDEgJiBkdF9lbnZpbyA+PSBkdC5pbjQ3LCAxLCAwKSkgfD4gDQogICMgbWFyY2EgY29tdW5pY2Fkb3MgY29tIGF2aXNvcyBkZSBuZWdvY2lhw6fDo28NCiAgZ3JvdXBfYnkoaWRfY29tdW5pY2FkbykgfD4gDQogIG11dGF0ZShsZy5hbHRlcmFyID0gaWZfZWxzZShzdW0obGdfbmVnb2NpYWNhbykgPiAwLCAxTCwgMEwpKSB8PiANCiAgdW5ncm91cCgpDQpgYGANCg0KPGJyPg0KDQpOb3RlIHF1ZSBuw6NvIGhhdmlhbSBhdmlzb3MgZGUgbmVnb2NpYcOnw6NvIGVudmlhZG9zIGFww7NzIGEgSU4gNDcgbmEgYmFzZSBleHRyYcOtZGEgLSB0YWx2ZXogZXNzZXMgY29tdW5pY2Fkb3MgdGVuaGFtIHNpZG8gZXhjbHXDrWRvcyBuYSBleHRyYcOnw6NvIGRhIGJhc2UgUlBDLg0KICAgICAgIA0KDQo8YnI+DQoNClRyYXRhIGF2aXNvcyBkZSBjb211bmljYWRvIGVtIGF0cmFzbyBwb3IgTkVHT0NJQUNBTyBhcGxpY2FuZG8gYXMgcmVncmFzIGFwcm9wcmlhZGFzIHBhcmEgZW52aW9zIGFudGVyaW9yZXMgZSBwb3N0ZXJpb3JlcyDDoCBlbnRyYWRhIGVtIHZpZ29yIGRhIElOIDQ3Lg0KDQpgYGB7cn0NCmxhc3Qucm93IDwtIG5yb3cocnBjMikNCnJwYzMgPC0gcnBjMiB8PiANCiAgZmlsdGVyKGxnLmFsdGVyYXIgIT0gMEwpIHw+ICMgVHJhdGEgYXBlbmFzIGRvcyBjYXNvcyBkZSBuZWdvY2lhw6fDo28NCiAgDQogICMgZXhjbHVpIGF2aXNvcyBkZSBuZWdvY2lhY2FvIGVudmlhZG9zIGFww7NzIElOIDQ3DQogIGZpbHRlcighKGxnLmluNDcgPT0gMUwgJiBsZ19uZWdvY2lhY2FvID09IDFMKSkgfD4gDQogIA0KICAjIGV4Y2x1aSBhdmlzb3MgZGUgbmVnb2NpYWNhbyBlbnZpYWRvcyBwcsOpIElOIDQ3IHF1ZSB0ZW5oYW0gY29tdW5pY2FkbyBkZWZpbml0aXZvIHBvc3Rlcmlvcg0KICAjIGNvbSBpbsOtY2lvIGRlIGFwbGljYcOnw6NvIGEgbWVub3MgZGUgMTIgbWVzZXMgZG8gYXZpc28gZGUgbmVnb2NpYcOnw6NvDQogIGFycmFuZ2UoaWRfY29tdW5pY2FkbywgZHRfaW5pY19hcGxpY2FjYW8sIGRlc2MobGdfbmVnb2NpYWNhbyksIGlkX2VudmlvKSB8PiANCiAgZmlsdGVyKCEoICMgRXhjbHVpIGEgbGluaGEgU0UNCiAgICBsZ19uZWdvY2lhY2FvID09IDFMICAgICAgICAgICAgICAgICAgICAjIGZvciBhdmlzbyBkZSBuZWdvY2lhw6fDo28NCiAgICAmIGxnLmluNDcgPT0gMEwgICAgICAgICAgICAgICAgICAgICAgICAjIGVudmlhZG8gYW50ZXMgZGEgSU4gNDcNCiAgICAmIHJvd19udW1iZXIoKSAhPSBsYXN0LnJvdyAgICAgICAgICAgICAjIG7Do28gZm9yIGEgw7psdGltYSBsaW5oYSBkYSB0YWJlbGENCiAgICAmIGxlYWQoaWRfY29tdW5pY2FkbykgPT0gaWRfY29tdW5pY2FkbyAjIGEgcHLDs3hpbWEgbGluaGEgZm9yIGRvIG1lc21vIGNvbXVuaWNhZG8NCiAgICAjIGUgc2V1IGluw61jaW8gZGUgYXBsaWNhw6fDo28gZm9yIGVtIHVtIGludGVydmFsbyBpbmZlcmlvciBhIDEyIG1lc2VzDQogICAgJiBpbnRlcnZhbChkdF9pbmljX2FwbGljYWNhbywgbGVhZChkdF9pbmljX2FwbGljYWNhbykpICUvJSBtb250aHMoMSkgPCAxMiANCiAgKSkgfD4gICANCiAgDQogICMgYWNlcnRhIGEgb3JkZW0gZGFzIGNvbHVuYXMgcGFyYSBqdW50YXIgYXMgYmFzZXMNCiAgc2VsZWN0KGNvbG5hbWVzKHJwYzIpKSB8PiANCiAgcmJpbmQoZmlsdGVyKHJwYzIsIGxnLmFsdGVyYXIgPT0gMEwpKQ0KDQpyZW1vdmUobGFzdC5yb3cpDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcnBjMiB8PiANCiAgZ3JvdXBfYnkoYW5vID0geWVhcihkdF9pbmljX2FwbGljYWNhbykpIHw+DQogIHN1bW1hcmlzZShhbnRlcyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikgfD4gDQogIGlubmVyX2pvaW4oDQogICAgcnBjMyB8PiANCiAgICAgIGdyb3VwX2J5KGFubyA9IHllYXIoZHRfaW5pY19hcGxpY2FjYW8pKSB8Pg0KICAgICAgc3VtbWFyaXNlKGRlcG9pcyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIiksDQogICAgYnkgPSAiYW5vIg0KICApIHw+IA0KICBtdXRhdGUoZGlmZXJlbmNhID0gZGVwb2lzIC0gYW50ZXMpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCnJwYzMgfD4gZ3JvdXBfYnkoYW5vID0geWVhcihkdF9pbmljX2FwbGljYWNhbykpIHw+IA0KICBzdW1tYXJpc2UoZW52aW9zID0gbigpLCANCiAgICAgICAgICAgIGNvbXVuaWNhZG9zID0gbl9kaXN0aW5jdChpZF9jb211bmljYWRvLCBkdF9pbmljX2FwbGljYWNhbyksDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKSB8PiANCiAgbXV0YXRlKGVudmlvcy5wb3IuY29tdW5pY2FkbyA9IHJvdW5kKGVudmlvcy9jb211bmljYWRvcywgMykpDQpgYGANCg0KDQoNCioqKg0KIyMgQWRlc8OjbyAgICAgDQogICAgICANCkV4Y2x1c2l2YW1lbnRlIHBhcmEgY29udHJhdG9zIHZpZ2VudGVzIHF1ZSBwZXJtYW5lw6dhbSBpbmNvbXBhdMOtdmVpcyBjb20gYSBSTiBuwrogMTk1LCBkZSAyMDA5LCBxdWFuZG8gYSBkZWZpbmnDp8OjbyBkbyBwZXJjZW50dWFsIGRlIHJlYWp1c3RlIGUgZG8gcGVyw61vZG8gZGUgYXBsaWNhw6fDo28gZGUgdW0gbWVzbW8gcGxhbm8gZSBjb250cmF0byBmb3IgZGlmZXJlbmNpYWRhIGVtIGZ1bsOnw6NvIGRhIGRhdGEgZGUgYWRlc8OjbyBkZSBzZXVzIGJlbmVmaWNpw6FyaW9zOiAgICAgIA0KDQoqKltwcsOpIElOIDQ3XSoqICAgIA0KQSBjYWRhIG3DqnMgZW0gcXVlIGhhamEgYW5pdmVyc8OhcmlvIGRlIGFkZXPDo28gZGUgYmVuZWZpY2nDoXJpb3MsIGEgb3BlcmFkb3JhIGRldmVyw6EgaW5mb3JtYXIgYSB2YXJpYcOnw6NvIHBvc2l0aXZhLCBuZWdhdGl2YSBvdSBudWxhLiAgICAgIA0KICAgDQoNCioqW3DDs3MgSU4gNDddKiogICAgIA0KQSBvcGVyYWRvcmEgZGV2ZXLDoSBjb211bmljYXIgdW0gcGVyY2VudHVhbCDDum5pY28gZSBjYWxjdWxhZG8gY29tbyBhIG3DqWRpYSBkb3MgcmVhanVzdGVzIGFwbGljYWRvcyBhIGNhZGEgbcOqcyBlbSBxdWUgaG91dmUgYW5pdmVyc8OhcmlvIGRlIGFkZXPDo28gZGUgYmVuZWZpY2nDoXJpb3MgcG9uZGVyYWRhIHBlbGEgcXVhbnRpZGFkZSBkZSBiZW5lZmljacOhcmlvcyBlbSBjYWRhIGdydXBvIGRlIGFkZXPDo28sIGRlIGFjb3JkbyBjb20gYSBzZWd1aW50ZSBmw7NybXVsYToNCiAgICAgICAgIA0KUEYgPSBbIChyMSB4IGIxKSArIChyMiB4IGIyKSArIC4uLiArIChybiB4IGJuKSBdIC8gUUINCiAgICAgIA0Kb25kZTogICAgIA0KUEYgw6kgbyBwZXJjZW50dWFsIGZpbmFsIHF1ZSBkZXZlcsOhIHNlciBjb211bmljYWRvICAgICANClFCIMOpIGEgcXVhbnRpZGFkZSB0b3RhbCBkZSBiZW5lZmljacOhcmlvcyBkbyBjb250cmF0byAgICAgDQpyIMOpIG8gcmVhanVzdGUgYXBsaWNhZG8gYW8gZ3J1cG8gZGUgYWRlc8OjbyAgICAgDQpiIMOpIGEgcXVhbnRpZGFkZSBkZSBiZW5lZmljacOhcmlvcyBkbyBncnVwbyBkZSBhZGVzw6NvICAgICANCnJuIMOpIG8gcmVhanVzdGUgYXBsaWNhZG8gYW8gbi3DqXNpbW8gZ3J1cG8gZGUgYWRlc8OjbyAgICANCmJuIMOpIGEgcXVhbnRpZGFkZSBkZSBiZW5lZmljacOhcmlvcyBkbyBuLcOpc2ltbyBncnVwbyBkZSBhZGVzw6NvIGUgbiDDqSBhIHF1YW50aWRhZGUgZGUgZ3J1cG9zIGRlIGFkZXPDo28sIGxpbWl0YWRhIGEgMTIuICAgICANCiAgICAgICANCg0KKioqDQoqKlRSQVRBTUVOVE9TKiogICAgIA0KICAgICAgICAgIA0KOjo6IHsuYWxlcnQgLmFsZXJ0LWJsb2NrIC5hbGVydC1kYW5nZXJ9ICAgICANCk7Do28gY2FiZSBhcGxpY2HDp8OjbyBkZSB0cmF0YW1lbnRvcyBlc3BlY2lhaXMgcGFyYSBjYXNvcyBleGNlcGNpb25haXMgZGUgY29udHJhdG9zIG7Do28gYWRhcHRhZG9zIMOgIFJOIG7CuiAxOTUgcXVlIGFwbGlxdWVtIHJlYWp1c3RlcyBkaWZlcmVuY2lhZG9zIHBvciBkYXRhIGRlIGFkZXPDo28gZG8gYmVuZWZpY2nDoXJpby4gVGFudG8gYW50ZXMgcXVhbnRvIGRlcG9pcyBkYXMgYWx0ZXJhw6fDtWVzIGRhIElOIERJUFJPIG7CuiA0Ny8yMDE0IHRvZG9zIG9zIGNvbXVuaWNhZG9zIHF1ZSBzZWd1ZW0gZXNzYXMgcmVncmFzIGRldmVtIHNlciBpbmNvcnBvcmFkb3MgbmEgYmFzZSBkZSByZWFqdXN0ZXMgZGUgcGxhbm9zIGNvbGV0aXZvcyBjb25mb3JtZSBhcyBpbnN0cnXDp8O1ZXMgZGUgZW52aW8gZSBzw6NvIGNvbXBhdMOtdmVpcyBjb20gb3MgY8OhbGN1bG9zIGRlIHJlYWp1c3RlIG3DqWRpbyBwb25kZXJhZG8gcGVsYSBxdWFudGlkYWRlIGRlIGJlbmVmaWNpw6FyaW9zLg0KOjo6DQogICAgIA0KKioqDQojIyBQYXJjZWxhZG8NCiAgICAgIA0KUXVhbmRvIG8gcmVhanVzdGUgZm9yIGFwbGljYWRvIGRlIGZvcm1hIHBhcmNlbGFkYSAobWFpcyBkZSB1bSByZWFqdXN0ZSBhbyBsb25nbyBkZSB1bSBwZXLDrW9kbyBkZSAxMiBtZXNlcykuIExlbWJyYW5kbyBxdWUgYSBSTiBuwrogMTk1IGRldGVybWluYSBxdWUgbmVuaHVtIGNvbnRyYXRvIHBvZGVyw6EgcmVjZWJlciBxdWFscXVlciB2YXJpYcOnw6NvICoqcG9zaXRpdmEqKiBuYSBjb250cmFwcmVzdGHDp8OjbyBwZWN1bmnDoXJpYSBlbSBwZXJpb2RpY2lkYWRlIGluZmVyaW9yIGEgZG96ZSBtZXNlcywgcmVzc2FsdmFkb3Mgb3MgcmVhanVzdGVzIHBvciB2YXJpYcOnw6NvIGRlIGZhaXhhIGV0w6FyaWEgZSBtaWdyYcOnw6NvIG91IGFkYXB0YcOnw6NvIGRlIGNvbnRyYXRvLiAgICAgIA0KDQoqKltwcsOpIElOIDQ3XSoqICAgIA0KQ2FkYSB1bWEgZGFzIHBhcmNlbGFzIGRldmUgc2VyIGNvbXVuaWNhZGEgZW0gYXTDqSAzMCBkaWFzIGRhIHN1YSBhcGxpY2HDp8Ojby4gQSBvcGVyYWRvcmEgZGV2ZXLDoSBpbmZvcm1hciBvIHBlcmNlbnR1YWwgZGUgcmVhanVzdGUsIG8gcGVyw61vZG8gZGUgYXBsaWNhw6fDo28gZSBqdXN0aWZpY2F0aXZhLiAgIA0KDQpBcyBwYXJjZWxhcyBkZXZlcsOjbyBzZXIgY2FsY3VsYWRhcyBkZSBhY29yZG8gY29tIGEgc2VndWludGUgZsOzcm11bGE6ICAgICANCiAgICAgICAgDQpQVCA9IFsoMStQMSkgeCAoMStQMikgeCAuLi4geCAoMStQbildIC0gMSAgICAgDQogICAgICAgIA0KT25kZTogICAgDQpQVCDDqSBvIHBlcmNlbnR1YWwgdG90YWwgICAgDQpQMSDDqSBhIHBhcmNlbGEgcmVmZXJlbnRlIGFvIDHCuiByZWFqdXN0ZSAgICAgDQpQMiDDqSBhIHBhcmNlbGEgcmVmZXJlbnRlIGFvIDLCuiByZWFqdXN0ZSAgICAgDQpQbiDDqSBhIHBhcmNlbGEgcmVmZXJlbnRlIGFvIG4tw6lzaW1vIHJlYWp1c3RlICAgICAgDQogICAgICAgDQoNCioqcMOzcyBJTiA0NzoqKiAgICAgIA0KSW5mb3JtYXIsIG5vcyBtb2xkZXMgZG8gQW5leG8gSSBkZXN0YSBJTiwgbyBwZXJjZW50dWFsIHF1ZSByZWZsaXRhIG8gcmVhanVzdGUgdG90YWwgcXVlIHNlcsOhIGFwbGljYWRvIGFvIGNvbnRyYXRvIGFww7NzIGEgYXBsaWNhw6fDo28gZGUgdG9kYXMgYXMgcGFyY2VsYXMsIGRlIGFjb3JkbyBjb20gYSBzZWd1aW50ZSBmw7NybXVsYTogICAgICAgICAgDQogICAgICAgICAgIA0KUlQgPSBbKDErUDEpIHggKDErUDIpIHggLi4uIHggKDErUG4pXSAtIDEgICAgICANCiAgICAgICANCk9uZGU6ICAgICAgDQpSVCDDqSBvIHBlcmNlbnR1YWwgZGUgcmVhanVzdGUgdG90YWwgcXVlIHNlcsOhIGFwbGljYWRvICAgICANClAxIMOpIGEgMcKqIHBhcmNlbGEgZG8gcmVhanVzdGUgICAgIA0KUDIgw6kgYSAywqogcGFyY2VsYSBkbyByZWFqdXN0ZSAgICANClBuIMOpIGEgbi3DqXNpbWEgcGFyY2VsYSBkbyByZWFqdXN0ZSBlICAgICANCm4gw6kgYSBxdWFudGlkYWRlIGRlIHBhcmNlbGFzLCBsaW1pdGFkYSBhIDEyLiAgICAgICANCg0KDQoqKioNCioqVFJBVEFNRU5UT1MqKiAgICAgIA0KICAgICAgIA0KOjo6IHsuYWxlcnQgLmFsZXJ0LWJsb2NrIC5hbGVydC1kYW5nZXJ9DQpOw6NvIGNhYmUgYXBsaWNhw6fDo28gZGUgdHJhdGFtZW50b3MgZXNwZWNpYWlzIHBhcmEgY2Fzb3MgZGUgcmVhanVzdGVzIHBhcmNlbGFkb3MuIFRhbnRvIGFudGVzIHF1YW50byBkZXBvaXMgZGFzIGFsdGVyYcOnw7VlcyBkYSBJTiBESVBSTyBuwrogNDcvMjAxNCB0b2RvcyBvcyBjb211bmljYWRvcyBxdWUgc2VndWVtIGVzc2FzIHJlZ3JhcyBkZXZlbSBzZXIgaW5jb3Jwb3JhZG9zIG5hIGJhc2UgZGUgcmVhanVzdGVzIGRlIHBsYW5vcyBjb2xldGl2b3MgY29uZm9ybWUgYXMgaW5zdHJ1w6fDtWVzIGRlIGVudmlvIGUgc8OjbyBjb21wYXTDrXZlaXMgY29tIG9zIGPDoWxjdWxvcyBkZSByZWFqdXN0ZSBtw6lkaW8gcG9uZGVyYWRvIHBlbGEgcXVhbnRpZGFkZSBkZSBiZW5lZmljacOhcmlvcy4gICAgIA0KOjo6DQogICAgICAgDQo8YnI+DQoNCioqKg0KIyBHcmF2YSBkYXRhc2V0cyAgICAgIA0KICAgICANClByZXBhcmEgZGF0YXNldHMgcGFyYSBleHBvcnRhciBlbSBmb3JtYXRvIC5jc3YNCg0KYGBge3J9DQojIFJQUw0KcnBzIDwtIGZyZWFkKCJfZGF0YXNldHMvdndfcnBzX2NhZG9wLmNzdiIpIHw+IA0KICBsYXp5X2R0KCkgfD4gDQogIHJlbmFtZV93aXRoKHRvbG93ZXIpIHw+IA0KICBzZWxlY3QoaWRfcGxhbm8sIGNkX3BsYW5vLCBjZF9vcGVyYWRvcmEsIHRwX3ZpZ2VuY2lhID0gdmlnZW5jaWFfcGxhbm8pIHw+IA0KICBhc190aWJibGUoKQ0KDQojIGRhdGFzZXQgbW9kZWxvIHB1YmxpY2FkbyBubyBQREENCnBkYSA8LSBmcmVhZCgiX2RhdGFzZXRzL1BEQV9SUENfMjAxNTAxLmNzdiIpIHw+IA0KICBsYXp5X2R0KCkgfD4gDQogIHJlbmFtZV93aXRoKHRvbG93ZXIpIHw+IA0KICBhc190aWJibGUoKQ0KDQpycGMuZmluYWwgPC0gc2VsZWN0KHJwYzMsIGlkX2VudmlvLCBiZW5lZl9jb211bmljYWRvID0gYmVuZWYsIHBlcmNlbnR1YWwpIHw+IA0KICBpbm5lcl9qb2luKHNlbGVjdChycGMsIC1jKGJlbmVmX2NvbXVuaWNhZG8sIHBlcmNlbnR1YWwpKSwgYnkgPSAiaWRfZW52aW8iKSB8PiANCiAgc2VsZWN0KC1pZF9lbnZpbykgfD4gDQogIGlubmVyX2pvaW4ocnBzLCBieSA9ICJpZF9wbGFubyIpIHw+IA0KICAjIGV4Y2x1aSBvIMO6bHRpbW8gYW5vIGRhIGJhc2UgKHPDsyBmb2kgdXNhZG8gcGFyYSBkZWR1cGxpY2HDp8OjbyBkZSBhdmlzb3MgZGUgbmVnb2NpYcOnw6NvIA0KICAjIGRlIGNvbnRyYXRvcyBjb20gYW5pdmVyc8OhcmlvIGF0w6kgZGV6ZW1icm8gZG8gYW5vIGFudGVyaW9yKQ0KICBmaWx0ZXIoZHRfaW5pY19hcGxpY2FjYW8gPD0gbWF4KHJwYyRkdF9pbmljX2FwbGljYWNhbykgLSB5ZWFycygxKSkgfD4gDQogIHNlbGVjdChjb2xuYW1lcyhwZGEpKQ0KYGBgDQoNCg0KDQpgYGB7cn0NCiMgcmVnaXN0cmEgdG90YWwgZGUgZW52aW9zIGUgY29tdW5pY2Fkb3MgcG9yIGFubyBwYXJhIGNvbnRyb2xlDQp0dC5hbm8ucHJlIDwtIHJwYzAgfD4gDQogICMgZXhjbHVpIG8gw7psdGltbyBhbm8gZGEgYmFzZSAoc8OzIGZvaSB1c2FkbyBwYXJhIGRlZHVwbGljYcOnw6NvIGRlIGF2aXNvcyBkZSBuZWdvY2lhw6fDo28gDQogICMgZGUgY29udHJhdG9zIGNvbSBhbml2ZXJzw6FyaW8gYXTDqSBkZXplbWJybyBkbyBhbm8gYW50ZXJpb3IpDQogIGZpbHRlcihkdF9pbmljX2FwbGljYWNhbyA8PSBtYXgocnBjJGR0X2luaWNfYXBsaWNhY2FvKSAtIHllYXJzKDEpKSB8PiANCiAgZ3JvdXBfYnkoYW5vID0geWVhcihkdF9pbmljX2FwbGljYWNhbykpIHw+IA0KICBzdW1tYXJpc2UoZW52aW9zID0gbigpLCANCiAgICAgICAgICAgIGNvbXVuaWNhZG9zID0gbl9kaXN0aW5jdChpZF9jb211bmljYWRvKSwgDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKQ0KDQp0dC5hbm8ucG9zIDwtIHJwYy5maW5hbCB8PiANCiAgZ3JvdXBfYnkoYW5vID0geWVhcihkdF9pbmljX2FwbGljYWNhbykpIHw+IA0KICBzdW1tYXJpc2UoZW52aW9zID0gbigpLCANCiAgICAgICAgICAgIGNvbXVuaWNhZG9zID0gbl9kaXN0aW5jdChpZF9wbGFubywgaWRfY29udHJhdG8pLA0KICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIikgDQoNCnR0LmFubyA8LSB0dC5hbm8ucHJlIHw+DQogIGlubmVyX2pvaW4odHQuYW5vLnBvcywgYnkgPSBjKCJhbm8iKSwgc3VmZml4ID0gYygiLnByZSIsIi5wb3MiKSkgfD4gDQogIHJiaW5kKGZyZWFkKCJ0b3RhbF9wb3JfYW5vLmNzdiIpKQ0KDQpyZW1vdmUodHQuYW5vLnByZSwgdHQuYW5vLnBvcykNCmBgYA0KDQoNCg0KRXhwb3J0YSBkYXRhc2V0cw0KDQpgYGB7cn0NCmZ3cml0ZShycGMuZmluYWwgfD4gc2VsZWN0KGNvbG5hbWVzKHBkYSkpLCANCiAgICAgICBwYXN0ZTAoIl9kYXRhc2V0c19QREEvcnBjX3BkYSAiLCANCiAgICAgICAgICAgICAgZm9ybWF0KG1heChycGMuZmluYWwkZHRfaW5pY19hcGxpY2FjYW8pLCAiJVkiKSwgIi5jc3YiKSkNCg0KZndyaXRlKHR0LmFubywgInRvdGFsX3Bvcl9hbm8uY3N2IikNCmBgYA0KDQo=