library(tidyverse)
library(readxl)
library(sf)
library(spdep)
library(ggrepel)
library(knitr)
library(kableExtra)
library(MASS)
library(car)
library(scales)
library(corrplot)
library(CARBayes)    # model spasial CAR Poisson

1 Abstrak

Latar belakang. Tuberkulosis (TB) masih menjadi tantangan utama kesehatan masyarakat, dan Indonesia secara konsisten tergolong negara dengan beban TB tertinggi kedua di dunia. Karena itu, faktor kejadian TB menunjukkan variasi antarwilayah yang dipengaruhi kondisi demografi, sosial ekonomi, lingkungan, dan akses pelayanan kesehatan, pemahaman atas pola spasial dan determinannya penting untuk mendukung pengendalian yang tepat sasaran.

Metode. Penelitian ini menganalisis data agregat tingkat provinsi (34 provinsi yang memiliki data lengkap dan konsisten dengan batas wilayah) selama 2022-2024, bersumber dari publikasi BPS dan Profil Kesehatan Indonesia. Kejadian TB dideskripsikan melalui incidence rate (IR) dan standardized incidence ratio (SIR), divisualisasikan dalam peta tematik. Autokorelasi spasial global dievaluasi dengan indeks Moran’s I, klaster lokal dengan Local Indicators of Spatial Association (LISA), dan intensitas pengelompokan dengan statistik Getis-Ord Gi*. Determinan jumlah kasus dimodelkan menggunakan regresi data cacah dengan offset jumlah penduduk terhadap lima prediktor: indeks pembangunan manusia (IPM), persentase penduduk miskin, akses sanitasi layak, kepadatan penduduk, dan rasio Puskesmas per kecamatan. Pemilihan model ditentukan secara empiris: uji overdispersi mengarahkan penggunaan regresi Negative Binomial, dan uji autokorelasi spasial pada residual menentukan kebutuhan model spasial. Bila residual tidak berautokorelasi, Negative Binomial dinilai memadai; bila residual berautokorelasi spasial, digunakan model Conditional Autoregressive (CAR) Poisson dengan efek acak spasial.

Hasil. Total kasus TB ternotifikasi meningkat dari 724.309 (2022) menjadi 842.383 (2024), dengan rata-rata incidence rate (IR) antarprovinsi naik dari 245,3 menjadi 286,3 per 100.000 penduduk. Berdasarkan SIR 2022, sdebanyak sembilan provinsi memiliki risiko di atas rata-rata nasional, tertinggi di DKI Jakarta (SIR=1,83), Gorontalo (1,51), dan Jawa Barat (1,44). Indeks Moran’s I positif dan signifikan sepanjang periode (I=0,233–0,273; p<0,05), menunjukkan autokorelasi spasial yang konsisten — provinsi ber-IR tinggi cenderung mengelompok secara geografis. Pada model Negative Binomial 2022, rasio Puskesmas per kecamatan berasosiasi signifikan dengan penurunan insidens (IRR=0,644; 95% CI: 0,456–0,918) dan kepadatan penduduk dengan kenaikan insidens (p=0,002), sementara IPM, kemiskinan, dan sanitasi tidak signifikan. Uji autokorelasi residual mengarahkan penggunaan model CAR Poisson untuk 2024 (residual berautokorelasi, p=0,044), yang hasilnya konsisten dengan model Negative Binomial.

Kesimpulan. Insidens TB di Indonesia menunjukkan tren meningkat dan pengelompokan spasial yang menetap antarprovinsi sepanjang 2022–2024, dengan beban tertinggi terkonsentrasi di provinsi padat penduduk seperti DKI Jakarta dan sekitarnya. Rasio Puskesmas per kecamatan yang lebih tinggi berasosiasi dengan insidens lebih rendah, mengindikasikan peran penting ketersediaan fasilitas kesehatan primer. Temuan ini mendukung strategi pengendalian TB berbasis wilayah yang menargetkan provinsi hotspot dan penguatan layanan kesehatan primer.

Kata kunci: tuberkulosis; epidemiologi spasial; incidence rate; Indonesia; autokorelasi spasial; Negative Binomial; model CAR.

2 Pendahuluan

Tuberkulosis (TB) merupakan salah satu penyakit menular yang masih menjadi tantangan utama kesehatan masyarakat di dunia. Penyakit yang disebabkan oleh Mycobacterium tuberculosis ini ditularkan melalui udara dan menjadi salah satu penyebab utama kematian akibat penyakit infeksi. Indonesia termasuk negara dengan beban TB tertinggi kedua di dunia dan secara konsisten berada dalam kelompok negara prioritas pengendalian TB menurut Organisasi Kesehatan Dunia (WHO). Tingginya jumlah kasus dan kematian akibat TB menunjukkan bahwa upaya pengendalian penyakit ini masih memerlukan perhatian serius, terutama dalam mengidentifikasi wilayah berisiko tinggi serta faktor-faktor yang berkontribusi terhadap tingginya kejadian penyakit.

Dalam epidemiologi, distribusi penyakit dipelajari berdasarkan dimensi orang (person), tempat (place), dan waktu (time). Dimensi tempat berperan penting karena kejadian TB sering menunjukkan variasi antarwilayah yang dipengaruhi oleh kondisi demografi, sosial ekonomi, lingkungan, maupun akses terhadap pelayanan kesehatan. Sebagai negara kepulauan dengan karakteristik antarprovinsi yang sangat beragam, Indonesia berpotensi mengalami perbedaan beban TB antarwilayah, sehingga pemahaman atas pola distribusi geografisnya menjadi penting untuk perencanaan program pengendalian yang efektif dan tepat sasaran.

Pendekatan epidemiologi spasial memungkinkan identifikasi pola persebaran penyakit dan hubungan antarwilayah yang berdekatan secara geografis. Salah satu metode yang umum digunakan adalah analisis autokorelasi spasial global menggunakan indeks Moran’s I; nilai yang positif dan signifikan menunjukkan wilayah berdekatan cenderung memiliki tingkat kejadian serupa sehingga membentuk pola pengelompokan (spatial clustering). Selain itu, karena jumlah kasus TB merupakan data cacah (count data) yang sering mengalami overdispersi (varians melebihi rata-rata), model Negative Binomial lebih sesuai dibandingkan Poisson standar untuk mengestimasi hubungan antara faktor sosial, demografi, dan kesehatan dengan jumlah kasus secara lebih akurat.

Beberapa penelitian sebelumnya menerapkan pemodelan spasiotemporal Bayesian kompleks pada data TB tingkat kabupaten/kota dengan jumlah unit spasial besar. Pada tingkat provinsi dengan unit wilayah lebih terbatas, regresi Negative Binomial memberikan alternatif yang lebih sederhana namun tetap memadai untuk mengidentifikasi determinan kejadian TB. Berdasarkan latar belakang tersebut, penelitian ini bertujuan untuk: (1) menggambarkan distribusi spasial kasus TB antarprovinsi di Indonesia; (2) mengevaluasi keberadaan autokorelasi spasial menggunakan indeks Moran’s I; dan (3) mengidentifikasi determinan yang berhubungan dengan jumlah kasus TB menggunakan regresi data cacah.

Pertanyaan penelitian.

  1. Bagaimana distribusi spasial kasus tuberkulosis antarprovinsi di Indonesia?
  2. Apakah terdapat autokorelasi spasial pada distribusi kasus tuberkulosis antarprovinsi?
  3. Faktor-faktor apa yang berhubungan dengan variasi jumlah kasus tuberkulosis pada tingkat provinsi di Indonesia?

3 Data dan Metode

3.1 Sumber dan Unit Data

sumber: Data dikumpulkan dari publikasi BPS dan Profil Kesehatan Indonesia yang diakses pada tanggal 12 Juni 2026. Unit: provinsi (34), 3 tahun.

Variabel Definisi Satuan
Kasus Jumlah kasus TB ternotifikasi (L+P) kasus
Penduduk Jumlah penduduk jiwa
IR Insidens rate = Kasus/Penduduk x 100.000 per 100.000
IPM Indeks Pembangunan Manusia indeks
Miskin Persentase penduduk miskin %
Sanitasi Persentase sanitasi layak %
Kepadatan Kepadatan penduduk per km2
Rasio_Pkm Rasio Puskesmas per kecamatan rasio
JKN Total peserta aktif JKN jiwa

3.2 Pembacaan Data (dari GitHub)

user   <- "Winaliaagwil"
repo   <- "analisis_tb_indonesia"
branch <- "main"
base   <- sprintf("https://raw.githubusercontent.com/%s/%s/%s/", user, repo, branch)

url_xlsx <- paste0(base, "Data%20TB%202022_2024.xlsx")
url_zip  <- paste0(base, "indonesia_34_provinsi.zip")

download.file(url_xlsx, "DataTB.xlsx", mode = "wb", quiet = TRUE)
download.file(url_zip,  "shp.zip",     mode = "wb", quiet = TRUE)
unzip("shp.zip", exdir = "shp_folder")

rename_map <- c(
  "Wilayah / Provinsi"             = "Provinsi",
  "IPM"                            = "IPM",
  "Persentase Penduduk Miskin"     = "Miskin",
  "Persentase Sanitasi Layak"      = "Sanitasi",
  "Kepadatan penduduk (per km2)"   = "Kepadatan",
  "Rasio Puskesmas per Kecamatan"  = "Rasio_Pkm",
  "Total Peserta Aktif JKN (Jiwa)" = "JKN",
  "IR TB per 100000 Penduduk"      = "IR",
  "Jumlah Kasus TB"                = "Kasus",
  "Jumlah Penduduk"                = "Penduduk"
)

baca_sheet <- function(path, sheet) {
  df <- read_excel(path, sheet = sheet)
  names(df) <- dplyr::recode(names(df), !!!rename_map)
  prov <- str_squish(toupper(df$Provinsi))
  prov[prov == "DI YOGYAKARTA"]        <- "DAERAH ISTIMEWA YOGYAKARTA"
  prov[prov == "KEP. BANGKA BELITUNG"] <- "KEPULAUAN BANGKA BELITUNG"
  df$Provinsi <- prov
  df$Tahun <- as.integer(sheet)
  df %>%
    dplyr::select(Provinsi, Tahun, Kasus, Penduduk, IR,
                  IPM, Miskin, Sanitasi, Kepadatan, Rasio_Pkm, JKN)
}

tb_all <- bind_rows(lapply(c("2022","2023","2024"),
                           function(s) baca_sheet("DataTB.xlsx", s)))
tb22 <- filter(tb_all, Tahun == 2022)
tb23 <- filter(tb_all, Tahun == 2023)
tb24 <- filter(tb_all, Tahun == 2024)

indo <- st_read(list.files("shp_folder", pattern="\\.shp$", full.names=TRUE)[1], quiet=TRUE)
indo$Provinsi <- str_squish(toupper(indo$Provinsi))

sf::sf_use_s2(FALSE)
indo <- sf::st_make_valid(indo)

tidak_cocok <- setdiff(indo$Provinsi, tb22$Provinsi)
if (length(tidak_cocok)>0) message("Provinsi peta tanpa data: ", paste(tidak_cocok, collapse=", "))

# daftar data per tahun untuk dipakai ulang
data_tahun <- list("2022"=tb22, "2023"=tb23, "2024"=tb24)

Tahun 2022

724,309
Total kasus
245.3
Rata-rata IR
34
Provinsi
Dki Jakarta
IR tertinggi

Tahun 2023

810,882
Total kasus
282.7
Rata-rata IR
34
Provinsi
Papua
IR tertinggi

Tahun 2024

842,383
Total kasus
286.3
Rata-rata IR
34
Provinsi
Papua
IR tertinggi

3.3 Metode Statistik

Incidence Rate (IR) dan Standardized Incidence Ratio (SIR): \[ IR=\frac{O_i}{P_i}\times 100{,}000, \qquad E_i=\bar r\times P_i, \qquad SIR_i=\frac{O_i}{E_i} \] dengan \(\bar r\) rate nasional. SIR > 1 = risiko di atas rata-rata nasional.

Pola & hotspot spasial. Moran’s I global (autokorelasi), LISA (klaster lokal), dan Getis-Ord Gi* (hotspot/coldspot). Pembobot k-nearest neighbours (k=4) dipakai karena Indonesia kepulauan.

Determinan. Karena outcome berupa cacahan kasus dengan populasi sebagai offset, dipakai regresi count. Overdispersi diuji (Poisson vs Negative Binomial), autokorelasi spasial residual diuji, dan model spasial (CAR Poisson) disertakan sebagai analisis sensitivitas.

# ============================================================
# Fungsi-fungsi pembuat peta agar bisa dipakai ulang per tahun
# ============================================================

# bobot spasial (sama untuk semua tahun karena geometri tetap)
coords  <- suppressWarnings(st_coordinates(st_centroid(indo)))
k       <- 4
nb_k    <- knn2nb(knearneigh(coords, k=k))
lw      <- nb2listw(nb_k, style="W")
lw_self <- nb2listw(include.self(nb_k), style="W")

# --- Peta IR ---
peta_ir <- function(df, th){
  peta <- indo %>% left_join(df, by="Provinsi")
  top5 <- peta %>% filter(!is.na(IR)) %>% slice_max(IR, n=5)
  co <- as.data.frame(st_coordinates(suppressWarnings(st_centroid(top5))))
  co$label <- paste0(str_to_title(top5$Provinsi), "\n", round(top5$IR,1))
  ggplot(peta) +
    geom_sf(aes(fill=IR), color="white", linewidth=0.15) +
    scale_fill_viridis_c(option="plasma", direction=-1, name="IR TB\n(per 100.000)", na.value="grey85") +
    geom_point(data=co, aes(X,Y), size=1.3) +
    ggrepel::geom_label_repel(data=co, aes(X,Y,label=label), size=3, fontface="bold",
      alpha=0.9, box.padding=0.8, min.segment.length=0, segment.size=0.5,
      arrow=arrow(length=unit(0.015,"npc")), seed=42) +
    labs(title=paste0("Angka Insidensi TB per Provinsi, ", th),
         caption=paste0("Sumber: Profil Kesehatan Indonesia ", th)) +
    theme_minimal(base_size=12) +
    theme(axis.text=element_blank(), axis.title=element_blank(),
          axis.ticks=element_blank(), panel.grid=element_blank())
}

# --- Hitung SIR ---
hitung_sir <- function(df){
  rn <- sum(df$Kasus)/sum(df$Penduduk)
  df %>% mutate(Expected=rn*Penduduk, SIR=Kasus/Expected)
}

# --- Peta SIR ---
peta_sir_fun <- function(df, th){
  sir <- hitung_sir(df)
  peta <- indo %>% left_join(sir, by="Provinsi")
  ggplot(peta) +
    geom_sf(aes(fill=SIR), color="white", linewidth=0.15) +
    scale_fill_gradient2(low="#2166ac", mid="white", high="#b2182b", midpoint=1,
                         name="SIR", na.value="grey85") +
    labs(title=paste0("Standardized Incidence Ratio (SIR) TB, ", th),
         caption="SIR > 1 (merah) = risiko di atas rata-rata nasional") +
    theme_minimal(base_size=12) +
    theme(axis.text=element_blank(), axis.title=element_blank(),
          axis.ticks=element_blank(), panel.grid=element_blank())
}

# --- Tabel SIR ---
tabel_sir <- function(df, th){
  hitung_sir(df) %>% arrange(desc(SIR)) %>%
    transmute(Provinsi=str_to_title(Provinsi), Observed=Kasus,
              Expected=round(Expected,0), SIR=round(SIR,2)) %>%
    head(10) %>%
    kable(caption=paste0("Sepuluh provinsi SIR tertinggi (", th, ").")) %>%
    kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
}

# --- Peta LISA ---
peta_lisa <- function(df, th){
  peta <- indo %>% left_join(df, by="Provinsi")
  x <- peta$IR; xs <- as.numeric(scale(x)); lagxs <- lag.listw(lw, xs)
  locm <- localmoran(x, lw, zero.policy=TRUE); sig <- locm[,5] < 0.05
  peta$klaster <- "Tidak signifikan"
  peta$klaster[sig & xs>0 & lagxs>0] <- "High-High"
  peta$klaster[sig & xs<0 & lagxs<0] <- "Low-Low"
  peta$klaster[sig & xs>0 & lagxs<0] <- "High-Low"
  peta$klaster[sig & xs<0 & lagxs>0] <- "Low-High"
  peta$klaster <- factor(peta$klaster,
    levels=c("High-High","Low-Low","High-Low","Low-High","Tidak signifikan"))
  ggplot(peta) +
    geom_sf(aes(fill=klaster), color="white", linewidth=0.15) +
    scale_fill_manual(values=c("High-High"="#b2182b","Low-Low"="#2166ac",
      "High-Low"="#ef8a62","Low-High"="#67a9cf","Tidak signifikan"="grey88"),
      name="Klaster LISA", drop=FALSE) +
    labs(title=paste0("Klaster Spasial LISA Insidens TB, ", th),
         caption="High-High = hotspot; Low-Low = coldspot") +
    theme_minimal(base_size=12) +
    theme(axis.text=element_blank(), axis.title=element_blank(),
          axis.ticks=element_blank(), panel.grid=element_blank())
}

# --- Peta Hotspot Getis-Ord Gi* ---
peta_getis <- function(df, th){
  peta <- indo %>% left_join(df, by="Provinsi")
  gi <- as.numeric(localG(peta$IR, lw_self, zero.policy=TRUE))
  peta$hot <- cut(gi, breaks=c(-Inf,-2.58,-1.96,-1.65,1.65,1.96,2.58,Inf),
    labels=c("Coldspot 99%","Coldspot 95%","Coldspot 90%","Tidak signifikan",
             "Hotspot 90%","Hotspot 95%","Hotspot 99%"))
  warna_g <- c("Coldspot 99%"="#2166ac","Coldspot 95%"="#67a9cf","Coldspot 90%"="#d1e5f0",
    "Tidak signifikan"="grey88","Hotspot 90%"="#fddbc7","Hotspot 95%"="#ef8a62","Hotspot 99%"="#b2182b")
  ggplot(peta) +
    geom_sf(aes(fill=hot), color="white", linewidth=0.15) +
    scale_fill_manual(values=warna_g, name="Getis-Ord Gi*", drop=FALSE) +
    labs(title=paste0("Hotspot Insidens TB (Getis-Ord Gi*), ", th),
         caption="Merah = hotspot (kumpulan IR tinggi); biru = coldspot") +
    theme_minimal(base_size=12) +
    theme(axis.text=element_blank(), axis.title=element_blank(),
          axis.ticks=element_blank(), panel.grid=element_blank())
}

4 Hasil Analisis

4.1 Analisis Deskriptif

4.1.1 Tren Nasional

tb_all %>% group_by(Tahun) %>% summarise(Total=sum(Kasus)) %>%
  ggplot(aes(Tahun, Total)) +
  geom_col(fill="#1a6985", width=0.6) +
  geom_text(aes(label=comma(Total)), vjust=-0.5, size=3.5) +
  scale_x_continuous(breaks=2022:2024) +
  scale_y_continuous(labels=comma, expand=expansion(mult=c(0,0.12))) +
  labs(x=NULL, y="Total kasus TB") + theme_minimal(base_size=12)
Total kasus TB nasional, 2022-2024.

Total kasus TB nasional, 2022-2024.

Interpretasi. Total kasus TB nasional bergerak dari 724,309 (2022) menjadi 842,383 (2024), menunjukkan tren yang meningkat selama periode pengamatan. Perubahan ini dapat mencerminkan dinamika penemuan kasus (notifikasi) maupun beban penyakit yang sesungguhnya.

4.1.2 Provinsi IR Tertinggi

plot_top10 <- function(df, th){
  df %>% slice_max(IR, n=10) %>%
    ggplot(aes(reorder(str_to_title(Provinsi), IR), IR)) +
    geom_col(fill="#e07b39") +
    geom_text(aes(label=round(IR,0)), hjust=-0.2, size=3) +
    coord_flip() + scale_y_continuous(expand=expansion(mult=c(0,0.12))) +
    labs(x=NULL, y=paste0("IR TB per 100.000 (", th, ")")) + theme_minimal(base_size=12)
}

4.1.2.1 2022

plot_top10(tb22, 2022)
Sepuluh provinsi IR tertinggi (2022).

Sepuluh provinsi IR tertinggi (2022).

4.1.2.2 2023

plot_top10(tb23, 2023)
Sepuluh provinsi IR tertinggi (2023).

Sepuluh provinsi IR tertinggi (2023).

4.1.2.3 2024

plot_top10(tb24, 2024)
Sepuluh provinsi IR tertinggi (2024).

Sepuluh provinsi IR tertinggi (2024).

4.1.3 Ringkasan Statistik

tb_all %>% group_by(Tahun) %>%
  summarise(Total_kasus=sum(Kasus), IR_min=round(min(IR),1),
            IR_median=round(median(IR),1), IR_mean=round(mean(IR),1),
            IR_max=round(max(IR),1)) %>%
  kable(caption="Tabel 1. Ringkasan kasus & IR per tahun.") %>%
  kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
Tabel 1. Ringkasan kasus & IR per tahun.
Tahun Total_kasus IR_min IR_median IR_mean IR_max
2022 724309 105.7 231.8 245.3 480.2
2023 810882 120.4 264.2 282.7 570.2
2024 842383 121.9 265.4 286.3 615.7

Interpretasi. Rata-rata IR antarprovinsi berkisar 245.3-286.3 per 100.000 penduduk sepanjang 2022-2024. Rentang nilai yang lebar (minimum sekitar 105.7 hingga maksimum 615.7) mengindikasikan disparitas insidens yang besar antarprovinsi, yang menjadi dasar perlunya analisis spasial untuk mengetahui apakah provinsi ber-IR tinggi cenderung mengelompok secara geografis.

4.1.4 Ringkasan Variabel per Tahun

Statistik deskriptif (min, median, rata-rata, maks) untuk seluruh variabel pada tiap tahun.

ringkas_var <- function(df, th){
  df %>%
    dplyr::select(Kasus, IR, IPM, Miskin, Sanitasi, Kepadatan, Rasio_Pkm) %>%
    pivot_longer(everything(), names_to="Variabel", values_to="Nilai") %>%
    group_by(Variabel) %>%
    summarise(Min=round(min(Nilai),1), Median=round(median(Nilai),1),
              Mean=round(mean(Nilai),1), Maks=round(max(Nilai),1), .groups="drop") %>%
    kable(caption=paste0("Ringkasan variabel, ", th, ".")) %>%
    kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
}

4.1.4.1 2022

ringkas_var(tb22, 2022)
Ringkasan variabel, 2022.
Variabel Min Median Mean Maks
IPM 61.4 72.2 72.0 81.7
IR 105.7 231.8 245.3 480.2
Kasus 1738.0 8793.0 21303.2 184406.0
Kepadatan 10.0 100.5 772.9 17031.0
Miskin 4.5 8.5 10.3 26.8
Rasio_Pkm 0.7 1.4 1.6 7.2
Sanitasi 40.3 81.7 81.0 96.2

4.1.4.2 2023

ringkas_var(tb23, 2023)
Ringkasan variabel, 2023.
Variabel Min Median Mean Maks
IPM 63.0 73.9 73.8 83.6
IR 120.4 264.2 282.7 570.2
Kasus 1982.0 9980.0 23849.5 212613.0
Kepadatan 9.0 103.5 783.0 17153.0
Miskin 4.3 8.4 10.1 26.0
Rasio_Pkm 0.9 1.4 1.4 2.1
Sanitasi 43.0 83.4 82.6 96.4

4.1.4.3 2024

ringkas_var(tb24, 2024)
Ringkasan variabel, 2024.
Variabel Min Median Mean Maks
IPM 67.7 74.5 74.7 84.2
IR 121.9 265.4 286.3 615.7
Kasus 2051.0 9960.0 24776.0 225841.0
Kepadatan 9.6 105.1 774.3 16685.9
Miskin 3.8 7.5 9.2 21.1
Rasio_Pkm 0.9 1.4 1.4 2.1
Sanitasi 72.8 84.6 85.0 96.8

4.2 Peta Insidens Rate (IR)

4.2.1 2022

peta_ir(tb22, 2022)

4.2.2 2023

peta_ir(tb23, 2023)

4.2.3 2024

peta_ir(tb24, 2024)

Interpretasi. Peta menunjukkan provinsi dengan warna lebih pekat memiliki insidens TB lebih tinggi. Tiga provinsi dengan IR tertinggi relatif konsisten antar tahun (mis. pada 2022: Dki Jakarta, Gorontalo, Jawa Barat), mengindikasikan beban TB yang terkonsentrasi pada wilayah-wilayah tertentu. Klik tab tiap tahun untuk membandingkan perubahan sebaran.

4.3 Standardized Incidence Ratio (SIR)

4.3.1 2022

tabel_sir(tb22, 2022)
Sepuluh provinsi SIR tertinggi (2022).
Provinsi Observed Expected SIR
Dki Jakarta 54025 29582 1.83
Gorontalo 4786 3169 1.51
Jawa Barat 184406 127891 1.44
Papua 15822 11457 1.38
Banten 42429 31935 1.33
Sulawesi Utara 8784 7005 1.25
Papua Barat 3393 3053 1.11
Kepulauan Riau 5825 5525 1.05
Sumatera Utara 41057 40245 1.02
Sumatera Barat 14844 14788 1.00
peta_sir_fun(tb22, 2022)

4.3.2 2023

tabel_sir(tb23, 2023)
Sepuluh provinsi SIR tertinggi (2023).
Provinsi Observed Expected SIR
Papua 6187 3179 1.95
Dki Jakarta 60362 33220 1.82
Papua Barat 2668 1658 1.61
Jawa Barat 212613 146205 1.45
Banten 52887 36537 1.45
Gorontalo 5000 3624 1.38
Sulawesi Utara 10192 7794 1.31
Sumatera Utara 49425 45332 1.09
Sulawesi Tenggara 8580 8069 1.06
Kepulauan Riau 6633 6384 1.04
peta_sir_fun(tb23, 2023)

4.3.3 2024

tabel_sir(tb24, 2024)
Sepuluh provinsi SIR tertinggi (2024).
Provinsi Observed Expected SIR
Papua 6787 3305 2.05
Dki Jakarta 63403 33096 1.92
Papua Barat 2892 1728 1.67
Jawa Barat 225841 153865 1.47
Banten 56130 38623 1.45
Gorontalo 4964 3751 1.32
Sulawesi Utara 10082 7932 1.27
Sumatera Utara 50409 46897 1.07
Kepulauan Riau 7100 6812 1.04
Sulawesi Selatan 29154 28569 1.02
peta_sir_fun(tb24, 2024)

Interpretasi. SIR membandingkan jumlah kasus teramati dengan yang diharapkan bila provinsi memiliki risiko setara rata-rata nasional. Pada 2022, sebanyak 10 dari 34 provinsi memiliki SIR > 1 (risiko di atas rata-rata nasional, ditandai warna merah pada peta), sedangkan sisanya di bawah rata-rata. Provinsi dengan SIR tinggi menjadi prioritas perhatian karena bebannya melampaui ekspektasi populasi.

4.4 Analisis Pola Spasial: Moran’s I Global

moran_tahun <- function(df, th){
  peta <- indo %>% left_join(df, by="Provinsi")
  mc <- moran.mc(peta$IR, lw, nsim=999, zero.policy=TRUE)
  data.frame(Tahun=th, Moran_I=round(unname(mc$statistic),3), p_value=round(mc$p.value,3))
}
moran_tab <- rbind(moran_tahun(tb22,2022), moran_tahun(tb23,2023), moran_tahun(tb24,2024))
moran_tab %>%
  kable(caption="Tabel 2. Moran's I global IR per tahun (999 permutasi).") %>%
  kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
Tabel 2. Moran’s I global IR per tahun (999 permutasi).
Tahun Moran_I p_value
2022 0.233 0.015
2023 0.273 0.008
2024 0.262 0.003

Interpretasi. Nilai Moran’s I berkisar 0.233-0.273 dan signifikan pada ketiga tahun (p < 0,05). Nilai positif menandakan autokorelasi spasial positif: provinsi dengan IR tinggi cenderung berdekatan dengan provinsi ber-IR tinggi lainnya, membentuk pola pengelompokan (spatial clustering). Konsistensi nilai antar tahun menunjukkan pola spasial yang stabil sepanjang periode, sehingga keberadaan klaster ini bukan kejadian sesaat melainkan karakteristik yang menetap.

Cara baca. Moran’s I mendekati +1 = pengelompokan spasial positif; mendekati 0 = acak. Jika p-value < 0,05, autokorelasi spasial signifikan.

4.5 Peta Klaster LISA (Local Moran)

4.5.1 2022

peta_lisa(tb22, 2022)

4.5.2 2023

peta_lisa(tb23, 2023)

4.5.3 2024

peta_lisa(tb24, 2024)

Interpretasi. Pada 2022, analisis LISA mengidentifikasi 1 provinsi klaster High-High (Banten) — yaitu provinsi ber-IR tinggi yang dikelilingi provinsi ber-IR tinggi (hotspot), dan 1 provinsi klaster Low-Low (coldspot). Klaster High-High menandai wilayah prioritas intervensi karena bebannya tinggi dan menyebar secara terkonsentrasi. Bandingkan antar tahun melalui tab.

Cara baca LISA. High-High = hotspot; Low-Low = coldspot; High-Low / Low-High = outlier spasial.

4.6 Peta Hotspot Getis-Ord Gi*

4.6.1 2022

peta_getis(tb22, 2022)

4.6.2 2023

peta_getis(tb23, 2023)

4.6.3 2024

peta_getis(tb24, 2024)

Interpretasi. Statistik Getis-Ord Gi* pada 2022 mengidentifikasi 4 provinsi sebagai hotspot (skor-Z > 1,65; kumpulan IR tinggi) dan 4 provinsi sebagai coldspot (IR rendah terkelompok). Provinsi hotspot mencakup: Maluku Utara, Dki Jakarta, Jawa Barat, Banten. Hotspot ini memperkuat temuan LISA dan menandai wilayah dengan intensitas pengelompokan kasus tertinggi yang layak diprioritaskan.

Cara baca hotspot. Gi* tinggi positif = provinsi tersebut dan tetangganya sama-sama ber-IR tinggi (hotspot). Gi* negatif = kumpulan IR rendah (coldspot). Tingkat 90/95/99% menunjukkan keyakinan statistik.

4.7 Analisis Determinan: Pemodelan Count

Outcome: jumlah kasus TB dengan offset(log(Penduduk)). Prediktor (5 covariate): IPM, % penduduk miskin, % sanitasi layak, kepadatan penduduk, dan rasio Puskesmas per kecamatan. Pemilihan model (NB vs model CAR spasial) ditentukan oleh uji autokorelasi spasial pada residual tiap tahun.

4.7.1 Eksplorasi Korelasi antar Prediktor

Matriks korelasi antar enam prediktor (tanpa IR, karena IR bukan prediktor melainkan turunan dari outcome) untuk memeriksa potensi multikolinearitas.

plot_corr <- function(df){
  vars <- df %>% dplyr::select(IPM, Miskin, Sanitasi, Kepadatan, Rasio_Pkm)
  corrplot(cor(vars), method="color", type="upper", addCoef.col="black",
           number.cex=0.7, tl.col="black", tl.srt=45)
}

4.7.1.1 2022

plot_corr(tb22)
Matriks korelasi antar prediktor (2022).

Matriks korelasi antar prediktor (2022).

4.7.1.2 2023

plot_corr(tb23)
Matriks korelasi antar prediktor (2023).

Matriks korelasi antar prediktor (2023).

4.7.1.3 2024

plot_corr(tb24)
Matriks korelasi antar prediktor (2024).

Matriks korelasi antar prediktor (2024).

4.7.2 Uji Overdispersi & Autokorelasi Residual (per Tahun)

f_cov <- Kasus ~ IPM + Miskin + Sanitasi + Kepadatan + Rasio_Pkm

diagnostik <- function(df, th){
  mp <- glm(f_cov, family=poisson("log"), offset=log(Penduduk), data=df)
  disp <- sum(residuals(mp, type="pearson")^2)/mp$df.residual
  mnb <- glm.nb(update(f_cov, .~. + offset(log(Penduduk))), data=df)
  rdf <- df %>% mutate(.r=residuals(mnb, type="pearson")) %>% dplyr::select(Provinsi, .r)
  peta <- indo %>% left_join(rdf, by="Provinsi")
  mc <- moran.mc(peta$.r, lw, nsim=999, zero.policy=TRUE)
  data.frame(Tahun=th, Dispersi=round(disp,1),
             Moran_residual=round(unname(mc$statistic),3),
             p_value=round(mc$p.value,3),
             Model=ifelse(mc$p.value<0.05, "Model CAR", "NB"))
}
tabel_diag <- rbind(diagnostik(tb22,2022), diagnostik(tb23,2023), diagnostik(tb24,2024))
tabel_diag %>%
  kable(caption="Tabel 3. Uji overdispersi & autokorelasi residual NB per tahun.") %>%
  kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
Tabel 3. Uji overdispersi & autokorelasi residual NB per tahun.
Tahun Dispersi Moran_residual p_value Model
2022 1790.5 0.071 0.165 NB
2023 1920.8 0.145 0.062 NB
2024 2343.4 0.156 0.052 NB

Interpretasi. Rasio dispersi jauh di atas 1 (1790.5-2343.4) pada semua tahun menegaskan adanya overdispersi, sehingga Poisson standar tidak memadai dan Negative Binomial menjadi titik awal yang tepat. Selanjutnya, uji Moran’s I pada residual menentukan kebutuhan model spasial: Tahun 2022, 2023, 2024 (residual acak, p > 0,05) cukup dimodelkan dengan Negative Binomial. Logika berbasis bukti ini memastikan pemilihan model didasarkan pada karakteristik data, bukan asumsi.

Logika pemilihan model. Rasio dispersi >> 1 pada ketiga tahun menegaskan penggunaan Negative Binomial (bukan Poisson). Uji Moran’s I residual kemudian menentukan: bila p > 0,05 (tidak ada autokorelasi tersisa) NB memadai; bila p < 0,05 digunakan model CAR spasial. Hasil: 2022 -> NB (residual acak), 2023 & 2024 -> Model CAR (residual berautokorelasi).

4.7.3 Model 2022: Negative Binomial

4.7.3.1 Ringkasan & IRR

m_nb22 <- glm.nb(update(f_cov, .~. + offset(log(Penduduk))), data=tb22)
summary(m_nb22)
## 
## Call:
## glm.nb(formula = update(f_cov, . ~ . + offset(log(Penduduk))), 
##     data = tb22, init.theta = 18.50380797, link = log)
## 
## Coefficients:
##                Estimate  Std. Error z value Pr(>|z|)   
## (Intercept) -3.92546584  1.31222101  -2.991  0.00278 **
## IPM         -0.01346706  0.01616374  -0.833  0.40475   
## Miskin      -0.00370327  0.01099262  -0.337  0.73620   
## Sanitasi    -0.00685009  0.00416233  -1.646  0.09982 . 
## Kepadatan    0.00019950  0.00006372   3.131  0.00174 **
## Rasio_Pkm   -0.43954797  0.18689015  -2.352  0.01868 * 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for Negative Binomial(18.5038) family taken to be 1)
## 
##     Null deviance: 57.060  on 33  degrees of freedom
## Residual deviance: 34.297  on 28  degrees of freedom
## AIC: 642.43
## 
## Number of Fisher Scoring iterations: 1
## 
## 
##               Theta:  18.50 
##           Std. Err.:  4.46 
## 
##  2 x log-likelihood:  -628.43
irr22 <- exp(cbind(IRR=coef(m_nb22), confint(m_nb22)))
round(irr22,3) %>%
  kable(caption="Tabel 4. IRR & 95% CI - Negative Binomial 2022.") %>%
  kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
Tabel 4. IRR & 95% CI - Negative Binomial 2022.
IRR 2.5 % 97.5 %
(Intercept) 0.020 0.001 0.291
IPM 0.987 0.954 1.021
Miskin 0.996 0.975 1.018
Sanitasi 0.993 0.985 1.001
Kepadatan 1.000 1.000 1.000
Rasio_Pkm 0.644 0.456 0.918

Interpretasi. IRR menyatakan perubahan rate TB per kenaikan satu satuan prediktor (dengan prediktor lain konstan). Faktor yang berasosiasi signifikan (95% CI tidak memuat 1): kepadatan penduduk (IRR=1.000, meningkatkan rate TB); rasio Puskesmas per kecamatan (IRR=0.644, menurunkan rate TB). Prediktor dengan IRR di atas 1 berasosiasi dengan insidens lebih tinggi, sedangkan di bawah 1 dengan insidens lebih rendah.

4.7.3.2 Multikolinearitas (VIF)

vif22 <- car::vif(m_nb22)
data.frame(VIF=round(vif22,2)) %>%
  kable(caption="Tabel 5. VIF prediktor (2022).") %>%
  kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
Tabel 5. VIF prediktor (2022).
VIF
IPM 2.42
Miskin 2.06
Sanitasi 1.01
Kepadatan 20.83
Rasio_Pkm 22.21

Interpretasi. Nilai VIF melebihi 10, menandakan multikolinearitas serius (tertinggi pada Rasio_Pkm = 22.21). Dengan demikian, estimasi koefisien model dapat dianggap ditafsirkan dengan hati-hati.

Interpretasi IRR. IRR=exp(koef). IRR>1 = kenaikan covariate berasosiasi dengan kenaikan rate TB; IRR<1 = penurunan. Signifikan bila 95% CI tidak memuat 1.

4.7.4 Model CAR (Poisson Spasial): 2023 & 2024

Karena residual NB pada 2023 dan 2024 menunjukkan autokorelasi spasial, digunakan model CAR (Conditional Autoregressive) dengan likelihood Poisson dan efek acak spasial (formulasi Leroux). Pada model ini, overdispersi tidak ditangani lewat parameter dispersi (seperti NB), melainkan diserap oleh efek acak spasial dan tak terstruktur — pendekatan yang konsisten dengan Farkhan et al. yang menemukan Poisson berstruktur spasial memadai. Estimasi Bayesian via CARBayes::S.CARleroux (MCMC); koefisien di-eksponen menjadi rate ratio.

# matriks ketetanggaan biner (dipakai kedua tahun)
W <- nb2mat(nb_k, style="B", zero.policy=TRUE)
W <- pmax(W, t(W))

fit_car <- function(df){
  CARBayes::S.CARleroux(
    formula = update(f_cov, .~. + offset(log(Penduduk))),
    family  = "poisson", W = W, data = df,
    burnin = 20000, n.sample = 120000, thin = 10, verbose = FALSE)
}
ringkas_car <- function(m, th){
  tab <- exp(m$summary.results[, c("Median","2.5%","97.5%")])
  round(tab,3) %>% as.data.frame() %>%
    kable(caption=paste0("Rate Ratio (Model CAR) & 95% CrI - ", th, ".")) %>%
    kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
}

4.7.4.1 2023

m_car23 <- fit_car(tb23)
ringkas_car <- function(m, th){
  tab <- exp(m$summary.results[, c("Mean","2.5%","97.5%")])
  colnames(tab) <- c("RateRatio","CI_2.5%","CI_97.5%")
  round(tab, 3) %>% as.data.frame() %>%
    kable(caption=paste0("Rate Ratio (Model CAR) & 95% CrI - ", th, ".")) %>%
    kable_styling(full_width=FALSE, bootstrap_options=c("striped","hover"))
}

4.7.4.2 2024

m_car24 <- fit_car(tb24)
ringkas_car(m_car24, 2024)
Rate Ratio (Model CAR) & 95% CrI - 2024.
RateRatio CI_2.5% CI_97.5%
(Intercept) 0.384 0.068 4.398
IPM 0.949 0.924 0.983
Miskin 0.999 0.976 1.015
Sanitasi 0.990 0.965 1.006
Kepadatan 1.000 1.000 1.000
Rasio_Pkm 0.834 0.351 1.825
tau2 1.200 1.089 1.504
rho 1.137 1.003 1.658

Interpretasi. Setelah memperhitungkan efek acak spasial melalui model CAR, faktor yang berasosiasi (95% CrI tidak memuat 1) adalah: 2023 — IPM, penduduk miskin, sanitasi layak, kepadatan penduduk, NA, NA; 2024 — IPM, kepadatan penduduk, NA, NA. Konsistensi arah rate ratio dengan model NB 2022 memperkuat keandalan temuan determinan. Interval kredibel yang lebar wajar mengingat hanya 34 area, sehingga interpretasi difokuskan pada arah asosiasi, bukan presisi titik estimasi.

Catatan. Model CAR Bayesian untuk 34 area bersifat eksploratif; interval kredibel cenderung lebar. Fokuskan interpretasi pada arah & konsistensi rate ratio dengan model NB 2022, serta faktor yang kredibel intervalnya tidak memuat 1.

5 Pembahasan

Sesuai pedoman bagian F. Bahas: temuan utama (IR, SIR, hotspot, determinan signifikan); makna epidemiologis; implikasi kebijakan; keterbatasan (data agregat/ekologis, 34 area membatasi prediktor & model spasial Bayesian, 3 tahun, kemungkinan under-reporting). Bandingkan dengan paper acuan: di sana Poisson + BYM lebih baik (514 kabupaten dengan random effect spasial), sedangkan pada skala 34 provinsi tanpa random effect, NB lebih tepat untuk mengakomodasi overdispersi. Analisis determinan difokuskan pada 2022 karena pola spasial stabil sepanjang periode (Moran’s I 0,23-0,27; p < 0,05).

Catatan data JKN. Variabel cakupan Jaminan Kesehatan Nasional tidak dimasukkan ke dalam model karena ditemukan inkonsistensi antara data peserta JKN dan jumlah penduduk: proporsi cakupan melebihi 100% pada beberapa provinsi (mencapai sekitar 387% di Papua pada 2023-2024). Hal ini kemungkinan disebabkan oleh ketidaksesuaian batas wilayah administratif dan periode pendataan, khususnya pasca-pemekaran provinsi Papua tahun 2022. Memasukkan variabel dengan inkonsistensi sebesar ini berisiko membiaskan estimasi, sehingga variabel ini dikeluarkan demi menjaga validitas model.

(Tuliskan pembahasan di sini.)

6 Kesimpulan

(Ringkasan temuan & rekomendasi proporsional.)

7 Daftar Pustaka

  1. (Sumber kasus TB & treatment - SITB/Profil Kesehatan Kemenkes.)
  2. (Sumber penduduk - BPS.)
  3. (Sumber covariate - BPS: IPM, kemiskinan, sanitasi, kepadatan; JKN.)
  4. (Shapefile batas provinsi.)
  5. Farkhan A, dkk. Spatiotemporal epidemiology and associated risk factors of TB incidence and mortality in Indonesia 2017-2022. Population Health Metrics. 2026.
  6. (Referensi metode: Moran’s I, LISA, Getis-Ord, Negative Binomial, CAR.)

8 Lampiran: Kontribusi Anggota

Anggota Kontribusi
Sinta Septi Pangastuti (…)
Winalia Agwil (…)

Informasi sesi R
sessionInfo()
## R version 4.5.2 (2025-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=Dutch_Belgium.utf8  LC_CTYPE=Dutch_Belgium.utf8   
## [3] LC_MONETARY=Dutch_Belgium.utf8 LC_NUMERIC=C                  
## [5] LC_TIME=Dutch_Belgium.utf8    
## 
## time zone: Europe/Brussels
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] CARBayes_6.1.1   Rcpp_1.1.1-1.1   corrplot_0.95    scales_1.4.0    
##  [5] car_3.1-5        carData_3.0-6    MASS_7.3-65      kableExtra_1.4.0
##  [9] knitr_1.51       ggrepel_0.9.8    spdep_1.4-2      spData_2.3.5    
## [13] sf_1.1-1         readxl_1.5.0     lubridate_1.9.5  forcats_1.0.1   
## [17] stringr_1.6.0    dplyr_1.2.1      purrr_1.2.2      readr_2.2.0     
## [21] tidyr_1.3.2      tibble_3.3.1     ggplot2_4.0.3    tidyverse_2.0.0 
## 
## loaded via a namespace (and not attached):
##  [1] DBI_1.3.0          deldir_2.0-4       s2_1.1.11          rlang_1.2.0       
##  [5] magrittr_2.0.5     otel_0.2.0         e1071_1.7-17       compiler_4.5.2    
##  [9] png_0.1-9          systemfonts_1.3.2  vctrs_0.7.3        quantreg_6.1      
## [13] pkgconfig_2.0.3    wk_0.9.5           shape_1.4.6.1      fastmap_1.2.0     
## [17] mcmc_0.9-8         labeling_0.4.3     leafem_0.2.5       rmarkdown_2.31    
## [21] tzdb_0.5.0         MatrixModels_0.5-4 xfun_0.58          satellite_1.0.6   
## [25] glmnet_5.0         cachem_1.1.0       jsonlite_2.0.0     CARBayesdata_3.0  
## [29] mapview_2.11.4     terra_1.9-27       parallel_4.5.2     R6_2.6.1          
## [33] bslib_0.11.0       stringi_1.8.7      RColorBrewer_1.1-3 GGally_2.4.0      
## [37] boot_1.3-32        jquerylib_0.1.4    cellranger_1.1.0   iterators_1.0.14  
## [41] base64enc_0.1-6    igraph_2.3.2       splines_4.5.2      Matrix_1.7-4      
## [45] timechange_0.4.0   tidyselect_1.2.1   rstudioapi_0.19.0  abind_1.4-8       
## [49] yaml_2.3.12        codetools_0.2-20   lattice_0.22-7     withr_3.0.2       
## [53] S7_0.2.2           coda_0.19-4.1      evaluate_1.0.5     survival_3.8-3    
## [57] ggstats_0.13.0     units_1.0-1        proxy_0.4-29       xml2_1.5.2        
## [61] pillar_1.11.1      KernSmooth_2.23-26 foreach_1.5.2      stats4_4.5.2      
## [65] generics_0.1.4     sp_2.2-1           truncnorm_1.0-9    hms_1.1.4         
## [69] class_7.3-23       glue_1.8.1         tools_4.5.2        SparseM_1.84-2    
## [73] dotCall64_1.2      grid_4.5.2         MCMCpack_1.7-1     crosstalk_1.2.2   
## [77] raster_3.6-32      Formula_1.2-5      cli_3.6.6          textshaping_1.0.5 
## [81] spam_2.11-4        viridisLite_0.4.3  svglite_2.2.2      gtable_0.3.6      
## [85] sass_0.4.10        digest_0.6.39      classInt_0.4-11    htmlwidgets_1.6.4 
## [89] farver_2.1.2       htmltools_0.5.9    lifecycle_1.0.5    leaflet_2.2.3
LS0tDQp0aXRsZTogIkFuYWxpc2lzIEVwaWRlbWlvbG9naSBUdWJlcmt1bG9zaXMgZGkgSW5kb25lc2lhIg0Kc3VidGl0bGU6ICJJbnNpZGVucywgUGVtZXRhYW4gUmlzaWtvLCBIb3RzcG90IFNwYXNpYWwsIGRhbiBEZXRlcm1pbmFuIGFudGFycHJvdmluc2ksIDIwMjItMjAyNCINCmF1dGhvcjogIlNpbnRhIFNlcHRpIFBhbmdhc3R1dGkgJm5ic3A7JmJ1bGw7Jm5ic3A7IFdpbmFsaWEgQWd3aWwiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclZCAlQiAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0aGVtZToNCiAgICAgIHZlcnNpb246IDUNCiAgICAgIGJvb3Rzd2F0Y2g6IGNvc21vDQogICAgICBwcmltYXJ5OiAiIzFhNjk4NSINCiAgICAgIGJhc2VfZm9udDogeyBnb29nbGU6ICJJbnRlciIgfQ0KICAgICAgaGVhZGluZ19mb250OiB7IGdvb2dsZTogIlBvcHBpbnMiIH0NCiAgICAgIGNvZGVfZm9udDogeyBnb29nbGU6ICJKZXRCcmFpbnMgTW9ubyIgfQ0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogeyBjb2xsYXBzZWQ6IGZhbHNlLCBzbW9vdGhfc2Nyb2xsOiB0cnVlIH0NCiAgICB0b2NfZGVwdGg6IDMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgZmlnX2NhcHRpb246IHRydWUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwNCiAgZmlnLmFsaWduID0gImNlbnRlciIsIGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA1LCBkcGkgPSAxNTAsIG91dC53aWR0aCA9ICIxMDAlIikNCm9wdGlvbnMoc2NpcGVuID0gOTk5KQ0KYGBgDQoNCmBgYHtjc3MgY3VzdG9tLWlubGluZSwgZWNobz1GQUxTRX0NCjpyb290eyAtLWFjY2VudDojMWE2OTg1OyAtLWFjY2VudDI6I2UwN2IzOTsgLS1zb2Z0OiNmNGY4ZmE7IH0NCmJvZHl7IGxpbmUtaGVpZ2h0OjEuNzsgY29sb3I6IzJiMmIyYjsgdGV4dC1hbGlnbjoganVzdGlmeTsgfQ0KaDEsaDIsaDN7IGxldHRlci1zcGFjaW5nOi4ycHg7IH0NCmgxLnRpdGxleyBmb250LXdlaWdodDo3MDA7IH0NCi50b2NpZnl7IGJvcmRlcjpub25lICFpbXBvcnRhbnQ7IGJveC1zaGFkb3c6MCAycHggMTRweCByZ2JhKDAsMCwwLC4wNik7IGJvcmRlci1yYWRpdXM6MTJweDsgcGFkZGluZzo2cHg7IH0NCi50b2NpZnktaXRlbXsgYm9yZGVyLXJhZGl1czo4cHggIWltcG9ydGFudDsgZm9udC1zaXplOi45cmVtOyB9DQoudG9jaWZ5IC5hY3RpdmV7IGJhY2tncm91bmQ6dmFyKC0tYWNjZW50KSAhaW1wb3J0YW50OyBjb2xvcjojZmZmICFpbXBvcnRhbnQ7IH0NCi5iYW5uZXJ7IGJhY2tncm91bmQ6bGluZWFyLWdyYWRpZW50KDEzNWRlZywjMWE2OTg1IDAlLCMyZjkzYjUgMTAwJSk7IGNvbG9yOiNmZmY7DQogIHBhZGRpbmc6MjhweCAzMnB4OyBib3JkZXItcmFkaXVzOjE2cHg7IG1hcmdpbi1ib3R0b206MjZweDsgYm94LXNoYWRvdzowIDhweCAyNHB4IHJnYmEoMjYsMTA1LDEzMywuMjUpOyB9DQouYmFubmVyIGgyeyBjb2xvcjojZmZmOyBtYXJnaW4tdG9wOjA7IGZvbnQtd2VpZ2h0OjYwMDsgfQ0KLmJhbm5lciBweyBtYXJnaW4tYm90dG9tOjA7IG9wYWNpdHk6Ljk1OyB9DQouaW5mb2JveHsgYmFja2dyb3VuZDp2YXIoLS1zb2Z0KTsgYm9yZGVyLWxlZnQ6NXB4IHNvbGlkIHZhcigtLWFjY2VudCk7IHBhZGRpbmc6MTZweCAyMHB4OyBib3JkZXItcmFkaXVzOjEwcHg7IG1hcmdpbjoxOHB4IDA7IH0NCi5jYWxsb3V0eyBiYWNrZ3JvdW5kOiNmZmY3ZWY7IGJvcmRlci1sZWZ0OjVweCBzb2xpZCB2YXIoLS1hY2NlbnQyKTsgcGFkZGluZzoxNnB4IDIwcHg7IGJvcmRlci1yYWRpdXM6MTBweDsgbWFyZ2luOjE4cHggMDsgfQ0KLm1ldHJpYy1yb3d7IGRpc3BsYXk6ZmxleDsgZ2FwOjE2cHg7IGZsZXgtd3JhcDp3cmFwOyBtYXJnaW46MjBweCAwOyB9DQoubWV0cmljeyBmbGV4OjE7IG1pbi13aWR0aDoxNTBweDsgYmFja2dyb3VuZDojZmZmOyBib3JkZXI6MXB4IHNvbGlkICNlNmVkZjA7IGJvcmRlci1yYWRpdXM6MTRweDsNCiAgcGFkZGluZzoxOHB4OyB0ZXh0LWFsaWduOmNlbnRlcjsgYm94LXNoYWRvdzowIDJweCAxMHB4IHJnYmEoMCwwLDAsLjA0KTsgfQ0KLm1ldHJpYyAubnVteyBmb250LXNpemU6MS45cmVtOyBmb250LXdlaWdodDo3MDA7IGNvbG9yOnZhcigtLWFjY2VudCk7IGZvbnQtZmFtaWx5OidQb3BwaW5zJyxzYW5zLXNlcmlmOyB9DQoubWV0cmljIC5sYWJ7IGZvbnQtc2l6ZTouODJyZW07IGNvbG9yOiM2YjdjODU7IHRleHQtdHJhbnNmb3JtOnVwcGVyY2FzZTsgbGV0dGVyLXNwYWNpbmc6LjZweDsgfQ0KaW1neyBib3JkZXItcmFkaXVzOjEwcHg7IH0gdGFibGV7IGZvbnQtc2l6ZTouOTJyZW07IH0NCmJsb2NrcXVvdGV7IGJvcmRlci1sZWZ0OjRweCBzb2xpZCB2YXIoLS1hY2NlbnQpOyBiYWNrZ3JvdW5kOnZhcigtLXNvZnQpOyBib3JkZXItcmFkaXVzOjAgMTBweCAxMHB4IDA7IH0NCmBgYA0KDQpgYGB7ciBsaWJyYXJ5fQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KHNwZGVwKQ0KbGlicmFyeShnZ3JlcGVsKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeShDQVJCYXllcykgICAgIyBtb2RlbCBzcGFzaWFsIENBUiBQb2lzc29uDQpgYGANCg0KOjo6IHsuYmFubmVyfQ0KPGgyPlJpbmdrYXNhbiBQcm95ZWs8L2gyPg0KPHA+U3R1ZGkgZWtvbG9naSB0aW5na2F0IHByb3ZpbnNpIHRlcmhhZGFwIHBvbGEgc3Bhc2lhbCBkYW4gZGV0ZXJtaW5hbiBrZWphZGlhbiB0dWJlcmt1bG9zaXMNCmRpIEluZG9uZXNpYSBwZXJpb2RlIDIwMjItMjAyNC4gQW5hbGlzaXMgbWVuY2FrdXAgcGVtZXRhYW4gdGVtYXRpayBrZWphZGlhbiAoaW5jaWRlbmNlIHJhdGUNCiYgU0lSKSwgZXZhbHVhc2kgYXV0b2tvcmVsYXNpIHNwYXNpYWwgKE1vcmFuJ3MgSSBnbG9iYWwsIExJU0EsIEdldGlzLU9yZCBHaSopLCBkYW4NCmlkZW50aWZpa2FzaSBkZXRlcm1pbmFuIG1lbGFsdWkgcmVncmVzaSBkYXRhIGNhY2FoIChOZWdhdGl2ZSBCaW5vbWlhbCBkYW4gbW9kZWwgQ0FSIFBvaXNzb24NCnNwYXNpYWwpIHRlcmhhZGFwIGZha3RvciBzb3Npb2Vrb25vbWksIGRlbW9ncmFmaSwgc2VydGEgc2lzdGVtIGtlc2VoYXRhbi48L3A+DQo6OjoNCg0KIyBBYnN0cmFrIHsjYWJzdHJha30NCg0KKipMYXRhciBiZWxha2FuZy4qKiBUdWJlcmt1bG9zaXMgKFRCKSBtYXNpaCBtZW5qYWRpIHRhbnRhbmdhbiB1dGFtYSBrZXNlaGF0YW4gbWFzeWFyYWthdCwNCmRhbiBJbmRvbmVzaWEgc2VjYXJhIGtvbnNpc3RlbiB0ZXJnb2xvbmcgbmVnYXJhIGRlbmdhbiBiZWJhbiBUQiB0ZXJ0aW5nZ2kga2VkdWEgZGkgZHVuaWEuIEthcmVuYSBpdHUsIGZha3RvciANCmtlamFkaWFuIFRCIG1lbnVuanVra2FuIHZhcmlhc2kgYW50YXJ3aWxheWFoIHlhbmcgZGlwZW5nYXJ1aGkga29uZGlzaSBkZW1vZ3JhZmksIHNvc2lhbA0KZWtvbm9taSwgbGluZ2t1bmdhbiwgZGFuIGFrc2VzIHBlbGF5YW5hbiBrZXNlaGF0YW4sIHBlbWFoYW1hbiBhdGFzIHBvbGEgc3Bhc2lhbCBkYW4NCmRldGVybWluYW5ueWEgcGVudGluZyB1bnR1ayBtZW5kdWt1bmcgcGVuZ2VuZGFsaWFuIHlhbmcgdGVwYXQgc2FzYXJhbi4NCg0KKipNZXRvZGUuKiogUGVuZWxpdGlhbiBpbmkgbWVuZ2FuYWxpc2lzIGRhdGEgYWdyZWdhdCB0aW5na2F0IHByb3ZpbnNpICgzNCBwcm92aW5zaSB5YW5nDQptZW1pbGlraSBkYXRhIGxlbmdrYXAgZGFuIGtvbnNpc3RlbiBkZW5nYW4gYmF0YXMgd2lsYXlhaCkgc2VsYW1hIDIwMjItMjAyNCwgYmVyc3VtYmVyIGRhcmkNCnB1Ymxpa2FzaSBCUFMgZGFuIFByb2ZpbCBLZXNlaGF0YW4gSW5kb25lc2lhLiBLZWphZGlhbiBUQiBkaWRlc2tyaXBzaWthbiBtZWxhbHVpICppbmNpZGVuY2UNCnJhdGUqIChJUikgZGFuICpzdGFuZGFyZGl6ZWQgaW5jaWRlbmNlIHJhdGlvKiAoU0lSKSwgZGl2aXN1YWxpc2FzaWthbiBkYWxhbSBwZXRhIHRlbWF0aWsuDQpBdXRva29yZWxhc2kgc3Bhc2lhbCBnbG9iYWwgZGlldmFsdWFzaSBkZW5nYW4gaW5kZWtzIE1vcmFuJ3MgSSwga2xhc3RlciBsb2thbCBkZW5nYW4NCipMb2NhbCBJbmRpY2F0b3JzIG9mIFNwYXRpYWwgQXNzb2NpYXRpb24qIChMSVNBKSwgZGFuIGludGVuc2l0YXMgcGVuZ2Vsb21wb2thbiBkZW5nYW4NCnN0YXRpc3RpayBHZXRpcy1PcmQgR2lcKi4gRGV0ZXJtaW5hbiBqdW1sYWgga2FzdXMgZGltb2RlbGthbiBtZW5nZ3VuYWthbiByZWdyZXNpIGRhdGEgY2FjYWgNCmRlbmdhbiBvZmZzZXQganVtbGFoIHBlbmR1ZHVrIHRlcmhhZGFwIGxpbWEgcHJlZGlrdG9yOiBpbmRla3MgcGVtYmFuZ3VuYW4gbWFudXNpYSAoSVBNKSwNCnBlcnNlbnRhc2UgcGVuZHVkdWsgbWlza2luLCBha3NlcyBzYW5pdGFzaSBsYXlhaywga2VwYWRhdGFuIHBlbmR1ZHVrLCBkYW4gcmFzaW8gUHVza2VzbWFzDQpwZXIga2VjYW1hdGFuLiBQZW1pbGloYW4gbW9kZWwgZGl0ZW50dWthbiBzZWNhcmEgZW1waXJpczogdWppIG92ZXJkaXNwZXJzaSBtZW5nYXJhaGthbg0KcGVuZ2d1bmFhbiByZWdyZXNpICpOZWdhdGl2ZSBCaW5vbWlhbCosIGRhbiB1amkgYXV0b2tvcmVsYXNpIHNwYXNpYWwgcGFkYSByZXNpZHVhbA0KbWVuZW50dWthbiBrZWJ1dHVoYW4gbW9kZWwgc3Bhc2lhbC4gQmlsYSByZXNpZHVhbCB0aWRhayBiZXJhdXRva29yZWxhc2ksICpOZWdhdGl2ZSBCaW5vbWlhbCoNCmRpbmlsYWkgbWVtYWRhaTsgYmlsYSByZXNpZHVhbCBiZXJhdXRva29yZWxhc2kgc3Bhc2lhbCwgZGlndW5ha2FuIG1vZGVsICpDb25kaXRpb25hbA0KQXV0b3JlZ3Jlc3NpdmUqIChDQVIpIFBvaXNzb24gZGVuZ2FuIGVmZWsgYWNhayBzcGFzaWFsLg0KDQoqKkhhc2lsLioqIFRvdGFsIGthc3VzIFRCIHRlcm5vdGlmaWthc2kgbWVuaW5na2F0IGRhcmkgNzI0LjMwOSAoMjAyMikgbWVuamFkaSA4NDIuMzgzICgyMDI0KSwgZGVuZ2FuIHJhdGEtcmF0YSBpbmNpZGVuY2UgcmF0ZSAoSVIpIGFudGFycHJvdmluc2kgbmFpayBkYXJpIDI0NSwzIG1lbmphZGkgMjg2LDMgcGVyIDEwMC4wMDAgcGVuZHVkdWsuIEJlcmRhc2Fya2FuIFNJUiAyMDIyLCBzZGViYW55YWsgc2VtYmlsYW4gcHJvdmluc2kgbWVtaWxpa2kgcmlzaWtvIGRpIGF0YXMgcmF0YS1yYXRhIG5hc2lvbmFsLCB0ZXJ0aW5nZ2kgZGkgREtJIEpha2FydGEgKFNJUj0xLDgzKSwgR29yb250YWxvICgxLDUxKSwgZGFuIEphd2EgQmFyYXQgKDEsNDQpLiBJbmRla3MgTW9yYW4ncyBJIHBvc2l0aWYgZGFuIHNpZ25pZmlrYW4gc2VwYW5qYW5nIHBlcmlvZGUgKEk9MCwyMzPigJMwLDI3MzsgcDwwLDA1KSwgbWVudW5qdWtrYW4gYXV0b2tvcmVsYXNpIHNwYXNpYWwgeWFuZyBrb25zaXN0ZW4g4oCUIHByb3ZpbnNpIGJlci1JUiB0aW5nZ2kgY2VuZGVydW5nIG1lbmdlbG9tcG9rIHNlY2FyYSBnZW9ncmFmaXMuIFBhZGEgbW9kZWwgTmVnYXRpdmUgQmlub21pYWwgMjAyMiwgcmFzaW8gUHVza2VzbWFzIHBlciBrZWNhbWF0YW4gYmVyYXNvc2lhc2kgc2lnbmlmaWthbiBkZW5nYW4gcGVudXJ1bmFuIGluc2lkZW5zIChJUlI9MCw2NDQ7IDk1JSBDSTogMCw0NTbigJMwLDkxOCkgZGFuIGtlcGFkYXRhbiBwZW5kdWR1ayBkZW5nYW4ga2VuYWlrYW4gaW5zaWRlbnMgKHA9MCwwMDIpLCBzZW1lbnRhcmEgSVBNLCBrZW1pc2tpbmFuLCBkYW4gc2FuaXRhc2kgdGlkYWsgc2lnbmlmaWthbi4gVWppIGF1dG9rb3JlbGFzaSByZXNpZHVhbCBtZW5nYXJhaGthbiBwZW5nZ3VuYWFuIG1vZGVsIENBUiBQb2lzc29uIHVudHVrIDIwMjQgKHJlc2lkdWFsIGJlcmF1dG9rb3JlbGFzaSwgcD0wLDA0NCksIHlhbmcgaGFzaWxueWEga29uc2lzdGVuIGRlbmdhbiBtb2RlbCBOZWdhdGl2ZSBCaW5vbWlhbC4NCg0KKipLZXNpbXB1bGFuLioqIEluc2lkZW5zIFRCIGRpIEluZG9uZXNpYSBtZW51bmp1a2thbiB0cmVuIG1lbmluZ2thdCBkYW4gcGVuZ2Vsb21wb2thbiBzcGFzaWFsIHlhbmcgbWVuZXRhcCBhbnRhcnByb3ZpbnNpIHNlcGFuamFuZyAyMDIy4oCTMjAyNCwgZGVuZ2FuIGJlYmFuIHRlcnRpbmdnaSB0ZXJrb25zZW50cmFzaSBkaSBwcm92aW5zaSBwYWRhdCBwZW5kdWR1ayBzZXBlcnRpIERLSSBKYWthcnRhIGRhbiBzZWtpdGFybnlhLiBSYXNpbyBQdXNrZXNtYXMgcGVyIGtlY2FtYXRhbiB5YW5nIGxlYmloIHRpbmdnaSBiZXJhc29zaWFzaSBkZW5nYW4gaW5zaWRlbnMgbGViaWggcmVuZGFoLCBtZW5naW5kaWthc2lrYW4gcGVyYW4gcGVudGluZyBrZXRlcnNlZGlhYW4gZmFzaWxpdGFzIGtlc2VoYXRhbiBwcmltZXIuIFRlbXVhbiBpbmkgbWVuZHVrdW5nIHN0cmF0ZWdpIHBlbmdlbmRhbGlhbiBUQiBiZXJiYXNpcyB3aWxheWFoIHlhbmcgbWVuYXJnZXRrYW4gcHJvdmluc2kgaG90c3BvdCBkYW4gcGVuZ3VhdGFuIGxheWFuYW4ga2VzZWhhdGFuIHByaW1lci4NCg0KDQoqKkthdGEga3VuY2k6KiogdHViZXJrdWxvc2lzOyBlcGlkZW1pb2xvZ2kgc3Bhc2lhbDsgaW5jaWRlbmNlIHJhdGU7IEluZG9uZXNpYTsgYXV0b2tvcmVsYXNpDQpzcGFzaWFsOyBOZWdhdGl2ZSBCaW5vbWlhbDsgbW9kZWwgQ0FSLg0KDQojIFBlbmRhaHVsdWFuIHsjcGVuZGFodWx1YW59DQoNClR1YmVya3Vsb3NpcyAoVEIpIG1lcnVwYWthbiBzYWxhaCBzYXR1IHBlbnlha2l0IG1lbnVsYXIgeWFuZyBtYXNpaCBtZW5qYWRpIHRhbnRhbmdhbiB1dGFtYQ0Ka2VzZWhhdGFuIG1hc3lhcmFrYXQgZGkgZHVuaWEuIFBlbnlha2l0IHlhbmcgZGlzZWJhYmthbiBvbGVoICpNeWNvYmFjdGVyaXVtIHR1YmVyY3Vsb3NpcyoNCmluaSBkaXR1bGFya2FuIG1lbGFsdWkgdWRhcmEgZGFuIG1lbmphZGkgc2FsYWggc2F0dSBwZW55ZWJhYiB1dGFtYSBrZW1hdGlhbiBha2liYXQgcGVueWFraXQNCmluZmVrc2kuIEluZG9uZXNpYSB0ZXJtYXN1ayBuZWdhcmEgZGVuZ2FuIGJlYmFuIFRCIHRlcnRpbmdnaSBrZWR1YSBkaSBkdW5pYSBkYW4gc2VjYXJhIGtvbnNpc3Rlbg0KYmVyYWRhIGRhbGFtIGtlbG9tcG9rIG5lZ2FyYSBwcmlvcml0YXMgcGVuZ2VuZGFsaWFuIFRCIG1lbnVydXQgT3JnYW5pc2FzaSBLZXNlaGF0YW4gRHVuaWENCihXSE8pLiBUaW5nZ2lueWEganVtbGFoIGthc3VzIGRhbiBrZW1hdGlhbiBha2liYXQgVEIgbWVudW5qdWtrYW4gYmFod2EgdXBheWEgcGVuZ2VuZGFsaWFuDQpwZW55YWtpdCBpbmkgbWFzaWggbWVtZXJsdWthbiBwZXJoYXRpYW4gc2VyaXVzLCB0ZXJ1dGFtYSBkYWxhbSBtZW5naWRlbnRpZmlrYXNpIHdpbGF5YWgNCmJlcmlzaWtvIHRpbmdnaSBzZXJ0YSBmYWt0b3ItZmFrdG9yIHlhbmcgYmVya29udHJpYnVzaSB0ZXJoYWRhcCB0aW5nZ2lueWEga2VqYWRpYW4gcGVueWFraXQuDQoNCkRhbGFtIGVwaWRlbWlvbG9naSwgZGlzdHJpYnVzaSBwZW55YWtpdCBkaXBlbGFqYXJpIGJlcmRhc2Fya2FuIGRpbWVuc2kgb3JhbmcgKCpwZXJzb24qKSwNCnRlbXBhdCAoKnBsYWNlKiksIGRhbiB3YWt0dSAoKnRpbWUqKS4gRGltZW5zaSB0ZW1wYXQgYmVycGVyYW4gcGVudGluZyBrYXJlbmEga2VqYWRpYW4gVEINCnNlcmluZyBtZW51bmp1a2thbiB2YXJpYXNpIGFudGFyd2lsYXlhaCB5YW5nIGRpcGVuZ2FydWhpIG9sZWgga29uZGlzaSBkZW1vZ3JhZmksIHNvc2lhbA0KZWtvbm9taSwgbGluZ2t1bmdhbiwgbWF1cHVuIGFrc2VzIHRlcmhhZGFwIHBlbGF5YW5hbiBrZXNlaGF0YW4uIFNlYmFnYWkgbmVnYXJhIGtlcHVsYXVhbg0KZGVuZ2FuIGthcmFrdGVyaXN0aWsgYW50YXJwcm92aW5zaSB5YW5nIHNhbmdhdCBiZXJhZ2FtLCBJbmRvbmVzaWEgYmVycG90ZW5zaSBtZW5nYWxhbWkNCnBlcmJlZGFhbiBiZWJhbiBUQiBhbnRhcndpbGF5YWgsIHNlaGluZ2dhIHBlbWFoYW1hbiBhdGFzIHBvbGEgZGlzdHJpYnVzaSBnZW9ncmFmaXNueWENCm1lbmphZGkgcGVudGluZyB1bnR1ayBwZXJlbmNhbmFhbiBwcm9ncmFtIHBlbmdlbmRhbGlhbiB5YW5nIGVmZWt0aWYgZGFuIHRlcGF0IHNhc2FyYW4uDQoNClBlbmRla2F0YW4gZXBpZGVtaW9sb2dpIHNwYXNpYWwgbWVtdW5na2lua2FuIGlkZW50aWZpa2FzaSBwb2xhIHBlcnNlYmFyYW4gcGVueWFraXQgZGFuDQpodWJ1bmdhbiBhbnRhcndpbGF5YWggeWFuZyBiZXJkZWthdGFuIHNlY2FyYSBnZW9ncmFmaXMuIFNhbGFoIHNhdHUgbWV0b2RlIHlhbmcgdW11bQ0KZGlndW5ha2FuIGFkYWxhaCBhbmFsaXNpcyBhdXRva29yZWxhc2kgc3Bhc2lhbCBnbG9iYWwgbWVuZ2d1bmFrYW4gaW5kZWtzIE1vcmFuJ3MgSTsgbmlsYWkNCnlhbmcgcG9zaXRpZiBkYW4gc2lnbmlmaWthbiBtZW51bmp1a2thbiB3aWxheWFoIGJlcmRla2F0YW4gY2VuZGVydW5nIG1lbWlsaWtpIHRpbmdrYXQNCmtlamFkaWFuIHNlcnVwYSBzZWhpbmdnYSBtZW1iZW50dWsgcG9sYSBwZW5nZWxvbXBva2FuICgqc3BhdGlhbCBjbHVzdGVyaW5nKikuIFNlbGFpbiBpdHUsDQprYXJlbmEganVtbGFoIGthc3VzIFRCIG1lcnVwYWthbiBkYXRhIGNhY2FoICgqY291bnQgZGF0YSopIHlhbmcgc2VyaW5nIG1lbmdhbGFtaSBvdmVyZGlzcGVyc2kNCih2YXJpYW5zIG1lbGViaWhpIHJhdGEtcmF0YSksIG1vZGVsICpOZWdhdGl2ZSBCaW5vbWlhbCogbGViaWggc2VzdWFpIGRpYmFuZGluZ2thbiBQb2lzc29uDQpzdGFuZGFyIHVudHVrIG1lbmdlc3RpbWFzaSBodWJ1bmdhbiBhbnRhcmEgZmFrdG9yIHNvc2lhbCwgZGVtb2dyYWZpLCBkYW4ga2VzZWhhdGFuIGRlbmdhbg0KanVtbGFoIGthc3VzIHNlY2FyYSBsZWJpaCBha3VyYXQuDQoNCkJlYmVyYXBhIHBlbmVsaXRpYW4gc2ViZWx1bW55YSBtZW5lcmFwa2FuIHBlbW9kZWxhbiBzcGFzaW90ZW1wb3JhbCBCYXllc2lhbiBrb21wbGVrcyBwYWRhDQpkYXRhIFRCIHRpbmdrYXQga2FidXBhdGVuL2tvdGEgZGVuZ2FuIGp1bWxhaCB1bml0IHNwYXNpYWwgYmVzYXIuIFBhZGEgdGluZ2thdCBwcm92aW5zaSBkZW5nYW4NCnVuaXQgd2lsYXlhaCBsZWJpaCB0ZXJiYXRhcywgcmVncmVzaSAqTmVnYXRpdmUgQmlub21pYWwqIG1lbWJlcmlrYW4gYWx0ZXJuYXRpZiB5YW5nIGxlYmloDQpzZWRlcmhhbmEgbmFtdW4gdGV0YXAgbWVtYWRhaSB1bnR1ayBtZW5naWRlbnRpZmlrYXNpIGRldGVybWluYW4ga2VqYWRpYW4gVEIuIEJlcmRhc2Fya2FuDQpsYXRhciBiZWxha2FuZyB0ZXJzZWJ1dCwgcGVuZWxpdGlhbiBpbmkgYmVydHVqdWFuIHVudHVrOiAoMSkgbWVuZ2dhbWJhcmthbiBkaXN0cmlidXNpIHNwYXNpYWwNCmthc3VzIFRCIGFudGFycHJvdmluc2kgZGkgSW5kb25lc2lhOyAoMikgbWVuZ2V2YWx1YXNpIGtlYmVyYWRhYW4gYXV0b2tvcmVsYXNpIHNwYXNpYWwNCm1lbmdndW5ha2FuIGluZGVrcyBNb3JhbidzIEk7IGRhbiAoMykgbWVuZ2lkZW50aWZpa2FzaSBkZXRlcm1pbmFuIHlhbmcgYmVyaHVidW5nYW4gZGVuZ2FuDQpqdW1sYWgga2FzdXMgVEIgbWVuZ2d1bmFrYW4gcmVncmVzaSBkYXRhIGNhY2FoLg0KDQoqKlBlcnRhbnlhYW4gcGVuZWxpdGlhbi4qKg0KDQoxLiBCYWdhaW1hbmEgZGlzdHJpYnVzaSBzcGFzaWFsIGthc3VzIHR1YmVya3Vsb3NpcyBhbnRhcnByb3ZpbnNpIGRpIEluZG9uZXNpYT8NCjIuIEFwYWthaCB0ZXJkYXBhdCBhdXRva29yZWxhc2kgc3Bhc2lhbCBwYWRhIGRpc3RyaWJ1c2kga2FzdXMgdHViZXJrdWxvc2lzIGFudGFycHJvdmluc2k/DQozLiBGYWt0b3ItZmFrdG9yIGFwYSB5YW5nIGJlcmh1YnVuZ2FuIGRlbmdhbiB2YXJpYXNpIGp1bWxhaCBrYXN1cyB0dWJlcmt1bG9zaXMgcGFkYSB0aW5na2F0DQogICBwcm92aW5zaSBkaSBJbmRvbmVzaWE/DQoNCiMgRGF0YSBkYW4gTWV0b2RlIHsjZGF0YS1tZXRvZGV9DQoNCiMjIFN1bWJlciBkYW4gVW5pdCBEYXRhDQoNCjo6OiB7LmluZm9ib3h9DQpzdW1iZXI6IERhdGEgZGlrdW1wdWxrYW4gZGFyaSBwdWJsaWthc2kgQlBTIGRhbiBQcm9maWwgS2VzZWhhdGFuIEluZG9uZXNpYSB5YW5nIGRpYWtzZXMgcGFkYSB0YW5nZ2FsIDEyIEp1bmkgMjAyNi4gVW5pdDogcHJvdmluc2kgKDM0KSwNCjMgdGFodW4uDQo6OjoNCg0KfCBWYXJpYWJlbCB8IERlZmluaXNpIHwgU2F0dWFuIHwNCnwtLS18LS0tfC0tLXwNCnwgYEthc3VzYCB8IEp1bWxhaCBrYXN1cyBUQiB0ZXJub3RpZmlrYXNpIChMK1ApIHwga2FzdXMgfA0KfCBgUGVuZHVkdWtgIHwgSnVtbGFoIHBlbmR1ZHVrIHwgaml3YSB8DQp8IGBJUmAgfCBJbnNpZGVucyByYXRlID0gS2FzdXMvUGVuZHVkdWsgeCAxMDAuMDAwIHwgcGVyIDEwMC4wMDAgfA0KfCBgSVBNYCB8IEluZGVrcyBQZW1iYW5ndW5hbiBNYW51c2lhIHwgaW5kZWtzIHwNCnwgYE1pc2tpbmAgfCBQZXJzZW50YXNlIHBlbmR1ZHVrIG1pc2tpbiB8ICUgfA0KfCBgU2FuaXRhc2lgIHwgUGVyc2VudGFzZSBzYW5pdGFzaSBsYXlhayB8ICUgfA0KfCBgS2VwYWRhdGFuYCB8IEtlcGFkYXRhbiBwZW5kdWR1ayB8IHBlciBrbTIgfA0KfCBgUmFzaW9fUGttYCB8IFJhc2lvIFB1c2tlc21hcyBwZXIga2VjYW1hdGFuIHwgcmFzaW8gfA0KfCBgSktOYCB8IFRvdGFsIHBlc2VydGEgYWt0aWYgSktOIHwgaml3YSB8DQoNCiMjIFBlbWJhY2FhbiBEYXRhIChkYXJpIEdpdEh1YikNCg0KYGBge3IgYmFjYS1kYXRhfQ0KdXNlciAgIDwtICJXaW5hbGlhYWd3aWwiDQpyZXBvICAgPC0gImFuYWxpc2lzX3RiX2luZG9uZXNpYSINCmJyYW5jaCA8LSAibWFpbiINCmJhc2UgICA8LSBzcHJpbnRmKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vJXMvJXMvJXMvIiwgdXNlciwgcmVwbywgYnJhbmNoKQ0KDQp1cmxfeGxzeCA8LSBwYXN0ZTAoYmFzZSwgIkRhdGElMjBUQiUyMDIwMjJfMjAyNC54bHN4IikNCnVybF96aXAgIDwtIHBhc3RlMChiYXNlLCAiaW5kb25lc2lhXzM0X3Byb3ZpbnNpLnppcCIpDQoNCmRvd25sb2FkLmZpbGUodXJsX3hsc3gsICJEYXRhVEIueGxzeCIsIG1vZGUgPSAid2IiLCBxdWlldCA9IFRSVUUpDQpkb3dubG9hZC5maWxlKHVybF96aXAsICAic2hwLnppcCIsICAgICBtb2RlID0gIndiIiwgcXVpZXQgPSBUUlVFKQ0KdW56aXAoInNocC56aXAiLCBleGRpciA9ICJzaHBfZm9sZGVyIikNCg0KcmVuYW1lX21hcCA8LSBjKA0KICAiV2lsYXlhaCAvIFByb3ZpbnNpIiAgICAgICAgICAgICA9ICJQcm92aW5zaSIsDQogICJJUE0iICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gIklQTSIsDQogICJQZXJzZW50YXNlIFBlbmR1ZHVrIE1pc2tpbiIgICAgID0gIk1pc2tpbiIsDQogICJQZXJzZW50YXNlIFNhbml0YXNpIExheWFrIiAgICAgID0gIlNhbml0YXNpIiwNCiAgIktlcGFkYXRhbiBwZW5kdWR1ayAocGVyIGttMikiICAgPSAiS2VwYWRhdGFuIiwNCiAgIlJhc2lvIFB1c2tlc21hcyBwZXIgS2VjYW1hdGFuIiAgPSAiUmFzaW9fUGttIiwNCiAgIlRvdGFsIFBlc2VydGEgQWt0aWYgSktOIChKaXdhKSIgPSAiSktOIiwNCiAgIklSIFRCIHBlciAxMDAwMDAgUGVuZHVkdWsiICAgICAgPSAiSVIiLA0KICAiSnVtbGFoIEthc3VzIFRCIiAgICAgICAgICAgICAgICA9ICJLYXN1cyIsDQogICJKdW1sYWggUGVuZHVkdWsiICAgICAgICAgICAgICAgID0gIlBlbmR1ZHVrIg0KKQ0KDQpiYWNhX3NoZWV0IDwtIGZ1bmN0aW9uKHBhdGgsIHNoZWV0KSB7DQogIGRmIDwtIHJlYWRfZXhjZWwocGF0aCwgc2hlZXQgPSBzaGVldCkNCiAgbmFtZXMoZGYpIDwtIGRwbHlyOjpyZWNvZGUobmFtZXMoZGYpLCAhISFyZW5hbWVfbWFwKQ0KICBwcm92IDwtIHN0cl9zcXVpc2godG91cHBlcihkZiRQcm92aW5zaSkpDQogIHByb3ZbcHJvdiA9PSAiREkgWU9HWUFLQVJUQSJdICAgICAgICA8LSAiREFFUkFIIElTVElNRVdBIFlPR1lBS0FSVEEiDQogIHByb3ZbcHJvdiA9PSAiS0VQLiBCQU5HS0EgQkVMSVRVTkciXSA8LSAiS0VQVUxBVUFOIEJBTkdLQSBCRUxJVFVORyINCiAgZGYkUHJvdmluc2kgPC0gcHJvdg0KICBkZiRUYWh1biA8LSBhcy5pbnRlZ2VyKHNoZWV0KQ0KICBkZiAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KFByb3ZpbnNpLCBUYWh1biwgS2FzdXMsIFBlbmR1ZHVrLCBJUiwNCiAgICAgICAgICAgICAgICAgIElQTSwgTWlza2luLCBTYW5pdGFzaSwgS2VwYWRhdGFuLCBSYXNpb19Qa20sIEpLTikNCn0NCg0KdGJfYWxsIDwtIGJpbmRfcm93cyhsYXBwbHkoYygiMjAyMiIsIjIwMjMiLCIyMDI0IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbihzKSBiYWNhX3NoZWV0KCJEYXRhVEIueGxzeCIsIHMpKSkNCnRiMjIgPC0gZmlsdGVyKHRiX2FsbCwgVGFodW4gPT0gMjAyMikNCnRiMjMgPC0gZmlsdGVyKHRiX2FsbCwgVGFodW4gPT0gMjAyMykNCnRiMjQgPC0gZmlsdGVyKHRiX2FsbCwgVGFodW4gPT0gMjAyNCkNCg0KaW5kbyA8LSBzdF9yZWFkKGxpc3QuZmlsZXMoInNocF9mb2xkZXIiLCBwYXR0ZXJuPSJcXC5zaHAkIiwgZnVsbC5uYW1lcz1UUlVFKVsxXSwgcXVpZXQ9VFJVRSkNCmluZG8kUHJvdmluc2kgPC0gc3RyX3NxdWlzaCh0b3VwcGVyKGluZG8kUHJvdmluc2kpKQ0KDQpzZjo6c2ZfdXNlX3MyKEZBTFNFKQ0KaW5kbyA8LSBzZjo6c3RfbWFrZV92YWxpZChpbmRvKQ0KDQp0aWRha19jb2NvayA8LSBzZXRkaWZmKGluZG8kUHJvdmluc2ksIHRiMjIkUHJvdmluc2kpDQppZiAobGVuZ3RoKHRpZGFrX2NvY29rKT4wKSBtZXNzYWdlKCJQcm92aW5zaSBwZXRhIHRhbnBhIGRhdGE6ICIsIHBhc3RlKHRpZGFrX2NvY29rLCBjb2xsYXBzZT0iLCAiKSkNCg0KIyBkYWZ0YXIgZGF0YSBwZXIgdGFodW4gdW50dWsgZGlwYWthaSB1bGFuZw0KZGF0YV90YWh1biA8LSBsaXN0KCIyMDIyIj10YjIyLCAiMjAyMyI9dGIyMywgIjIwMjQiPXRiMjQpDQpgYGANCg0KYGBge3IgbWV0cmlrLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30NCmthcnR1X3RhaHVuIDwtIGZ1bmN0aW9uKGRmLCB0aCl7DQogIHRvdCA8LSBjb21tYShzdW0oZGYkS2FzdXMpKQ0KICBpcm0gPC0gcm91bmQobWVhbihkZiRJUiksMSkNCiAgcHRvcCA8LSBzdHJfdG9fdGl0bGUoZGYkUHJvdmluc2lbd2hpY2gubWF4KGRmJElSKV0pDQogIHNwcmludGYoJw0KPHAgc3R5bGU9ImZvbnQtd2VpZ2h0OjYwMDtjb2xvcjojMWE2OTg1O21hcmdpbjoxNHB4IDAgNHB4OyI+VGFodW4gJXM8L3A+DQo8ZGl2IGNsYXNzPSJtZXRyaWMtcm93Ij4NCiAgPGRpdiBjbGFzcz0ibWV0cmljIj48ZGl2IGNsYXNzPSJudW0iPiVzPC9kaXY+PGRpdiBjbGFzcz0ibGFiIj5Ub3RhbCBrYXN1czwvZGl2PjwvZGl2Pg0KICA8ZGl2IGNsYXNzPSJtZXRyaWMiPjxkaXYgY2xhc3M9Im51bSI+JXM8L2Rpdj48ZGl2IGNsYXNzPSJsYWIiPlJhdGEtcmF0YSBJUjwvZGl2PjwvZGl2Pg0KICA8ZGl2IGNsYXNzPSJtZXRyaWMiPjxkaXYgY2xhc3M9Im51bSI+MzQ8L2Rpdj48ZGl2IGNsYXNzPSJsYWIiPlByb3ZpbnNpPC9kaXY+PC9kaXY+DQogIDxkaXYgY2xhc3M9Im1ldHJpYyI+PGRpdiBjbGFzcz0ibnVtIj4lczwvZGl2PjxkaXYgY2xhc3M9ImxhYiI+SVIgdGVydGluZ2dpPC9kaXY+PC9kaXY+DQo8L2Rpdj4nLCB0aCwgdG90LCBpcm0sIHB0b3ApDQp9DQpjYXQoa2FydHVfdGFodW4odGIyMiwgMjAyMikpDQpjYXQoa2FydHVfdGFodW4odGIyMywgMjAyMykpDQpjYXQoa2FydHVfdGFodW4odGIyNCwgMjAyNCkpDQpgYGANCg0KIyMgTWV0b2RlIFN0YXRpc3Rpaw0KDQoqKkluY2lkZW5jZSBSYXRlIChJUikqKiBkYW4gKipTdGFuZGFyZGl6ZWQgSW5jaWRlbmNlIFJhdGlvIChTSVIpOioqDQokJCBJUj1cZnJhY3tPX2l9e1BfaX1cdGltZXMgMTAweyx9MDAwLCBccXF1YWQgRV9pPVxiYXIgclx0aW1lcyBQX2ksIFxxcXVhZCBTSVJfaT1cZnJhY3tPX2l9e0VfaX0gJCQNCmRlbmdhbiAkXGJhciByJCByYXRlIG5hc2lvbmFsLiBTSVIgPiAxID0gcmlzaWtvIGRpIGF0YXMgcmF0YS1yYXRhIG5hc2lvbmFsLg0KDQoqKlBvbGEgJiBob3RzcG90IHNwYXNpYWwuKiogTW9yYW4ncyBJIGdsb2JhbCAoYXV0b2tvcmVsYXNpKSwgTElTQSAoa2xhc3RlciBsb2thbCksIGRhbg0KR2V0aXMtT3JkIEdpKiAoaG90c3BvdC9jb2xkc3BvdCkuIFBlbWJvYm90ICprLW5lYXJlc3QgbmVpZ2hib3VycyogKGs9NCkgZGlwYWthaSBrYXJlbmENCkluZG9uZXNpYSBrZXB1bGF1YW4uDQoNCioqRGV0ZXJtaW5hbi4qKiBLYXJlbmEgb3V0Y29tZSBiZXJ1cGEgY2FjYWhhbiBrYXN1cyBkZW5nYW4gcG9wdWxhc2kgc2ViYWdhaSBvZmZzZXQsDQpkaXBha2FpIHJlZ3Jlc2kgY291bnQuIE92ZXJkaXNwZXJzaSBkaXVqaSAoUG9pc3NvbiB2cyBOZWdhdGl2ZSBCaW5vbWlhbCksIGF1dG9rb3JlbGFzaQ0Kc3Bhc2lhbCByZXNpZHVhbCBkaXVqaSwgZGFuIG1vZGVsIHNwYXNpYWwgKENBUiBQb2lzc29uKSBkaXNlcnRha2FuIHNlYmFnYWkNCmFuYWxpc2lzIHNlbnNpdGl2aXRhcy4NCg0KYGBge3IgZnVuZ3NpLXBldGF9DQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBGdW5nc2ktZnVuZ3NpIHBlbWJ1YXQgcGV0YSBhZ2FyIGJpc2EgZGlwYWthaSB1bGFuZyBwZXIgdGFodW4NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgYm9ib3Qgc3Bhc2lhbCAoc2FtYSB1bnR1ayBzZW11YSB0YWh1biBrYXJlbmEgZ2VvbWV0cmkgdGV0YXApDQpjb29yZHMgIDwtIHN1cHByZXNzV2FybmluZ3Moc3RfY29vcmRpbmF0ZXMoc3RfY2VudHJvaWQoaW5kbykpKQ0KayAgICAgICA8LSA0DQpuYl9rICAgIDwtIGtubjJuYihrbmVhcm5laWdoKGNvb3Jkcywgaz1rKSkNCmx3ICAgICAgPC0gbmIybGlzdHcobmJfaywgc3R5bGU9IlciKQ0KbHdfc2VsZiA8LSBuYjJsaXN0dyhpbmNsdWRlLnNlbGYobmJfayksIHN0eWxlPSJXIikNCg0KIyAtLS0gUGV0YSBJUiAtLS0NCnBldGFfaXIgPC0gZnVuY3Rpb24oZGYsIHRoKXsNCiAgcGV0YSA8LSBpbmRvICU+JSBsZWZ0X2pvaW4oZGYsIGJ5PSJQcm92aW5zaSIpDQogIHRvcDUgPC0gcGV0YSAlPiUgZmlsdGVyKCFpcy5uYShJUikpICU+JSBzbGljZV9tYXgoSVIsIG49NSkNCiAgY28gPC0gYXMuZGF0YS5mcmFtZShzdF9jb29yZGluYXRlcyhzdXBwcmVzc1dhcm5pbmdzKHN0X2NlbnRyb2lkKHRvcDUpKSkpDQogIGNvJGxhYmVsIDwtIHBhc3RlMChzdHJfdG9fdGl0bGUodG9wNSRQcm92aW5zaSksICJcbiIsIHJvdW5kKHRvcDUkSVIsMSkpDQogIGdncGxvdChwZXRhKSArDQogICAgZ2VvbV9zZihhZXMoZmlsbD1JUiksIGNvbG9yPSJ3aGl0ZSIsIGxpbmV3aWR0aD0wLjE1KSArDQogICAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uPSJwbGFzbWEiLCBkaXJlY3Rpb249LTEsIG5hbWU9IklSIFRCXG4ocGVyIDEwMC4wMDApIiwgbmEudmFsdWU9ImdyZXk4NSIpICsNCiAgICBnZW9tX3BvaW50KGRhdGE9Y28sIGFlcyhYLFkpLCBzaXplPTEuMykgKw0KICAgIGdncmVwZWw6Omdlb21fbGFiZWxfcmVwZWwoZGF0YT1jbywgYWVzKFgsWSxsYWJlbD1sYWJlbCksIHNpemU9MywgZm9udGZhY2U9ImJvbGQiLA0KICAgICAgYWxwaGE9MC45LCBib3gucGFkZGluZz0wLjgsIG1pbi5zZWdtZW50Lmxlbmd0aD0wLCBzZWdtZW50LnNpemU9MC41LA0KICAgICAgYXJyb3c9YXJyb3cobGVuZ3RoPXVuaXQoMC4wMTUsIm5wYyIpKSwgc2VlZD00MikgKw0KICAgIGxhYnModGl0bGU9cGFzdGUwKCJBbmdrYSBJbnNpZGVuc2kgVEIgcGVyIFByb3ZpbnNpLCAiLCB0aCksDQogICAgICAgICBjYXB0aW9uPXBhc3RlMCgiU3VtYmVyOiBQcm9maWwgS2VzZWhhdGFuIEluZG9uZXNpYSAiLCB0aCkpICsNCiAgICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZT0xMikgKw0KICAgIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGU9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgIGF4aXMudGlja3M9ZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkPWVsZW1lbnRfYmxhbmsoKSkNCn0NCg0KIyAtLS0gSGl0dW5nIFNJUiAtLS0NCmhpdHVuZ19zaXIgPC0gZnVuY3Rpb24oZGYpew0KICBybiA8LSBzdW0oZGYkS2FzdXMpL3N1bShkZiRQZW5kdWR1aykNCiAgZGYgJT4lIG11dGF0ZShFeHBlY3RlZD1ybipQZW5kdWR1aywgU0lSPUthc3VzL0V4cGVjdGVkKQ0KfQ0KDQojIC0tLSBQZXRhIFNJUiAtLS0NCnBldGFfc2lyX2Z1biA8LSBmdW5jdGlvbihkZiwgdGgpew0KICBzaXIgPC0gaGl0dW5nX3NpcihkZikNCiAgcGV0YSA8LSBpbmRvICU+JSBsZWZ0X2pvaW4oc2lyLCBieT0iUHJvdmluc2kiKQ0KICBnZ3Bsb3QocGV0YSkgKw0KICAgIGdlb21fc2YoYWVzKGZpbGw9U0lSKSwgY29sb3I9IndoaXRlIiwgbGluZXdpZHRoPTAuMTUpICsNCiAgICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3c9IiMyMTY2YWMiLCBtaWQ9IndoaXRlIiwgaGlnaD0iI2IyMTgyYiIsIG1pZHBvaW50PTEsDQogICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iU0lSIiwgbmEudmFsdWU9ImdyZXk4NSIpICsNCiAgICBsYWJzKHRpdGxlPXBhc3RlMCgiU3RhbmRhcmRpemVkIEluY2lkZW5jZSBSYXRpbyAoU0lSKSBUQiwgIiwgdGgpLA0KICAgICAgICAgY2FwdGlvbj0iU0lSID4gMSAobWVyYWgpID0gcmlzaWtvIGRpIGF0YXMgcmF0YS1yYXRhIG5hc2lvbmFsIikgKw0KICAgIHRoZW1lX21pbmltYWwoYmFzZV9zaXplPTEyKSArDQogICAgdGhlbWUoYXhpcy50ZXh0PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpKQ0KfQ0KDQojIC0tLSBUYWJlbCBTSVIgLS0tDQp0YWJlbF9zaXIgPC0gZnVuY3Rpb24oZGYsIHRoKXsNCiAgaGl0dW5nX3NpcihkZikgJT4lIGFycmFuZ2UoZGVzYyhTSVIpKSAlPiUNCiAgICB0cmFuc211dGUoUHJvdmluc2k9c3RyX3RvX3RpdGxlKFByb3ZpbnNpKSwgT2JzZXJ2ZWQ9S2FzdXMsDQogICAgICAgICAgICAgIEV4cGVjdGVkPXJvdW5kKEV4cGVjdGVkLDApLCBTSVI9cm91bmQoU0lSLDIpKSAlPiUNCiAgICBoZWFkKDEwKSAlPiUNCiAgICBrYWJsZShjYXB0aW9uPXBhc3RlMCgiU2VwdWx1aCBwcm92aW5zaSBTSVIgdGVydGluZ2dpICgiLCB0aCwgIikuIikpICU+JQ0KICAgIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aD1GQUxTRSwgYm9vdHN0cmFwX29wdGlvbnM9Yygic3RyaXBlZCIsImhvdmVyIikpDQp9DQoNCiMgLS0tIFBldGEgTElTQSAtLS0NCnBldGFfbGlzYSA8LSBmdW5jdGlvbihkZiwgdGgpew0KICBwZXRhIDwtIGluZG8gJT4lIGxlZnRfam9pbihkZiwgYnk9IlByb3ZpbnNpIikNCiAgeCA8LSBwZXRhJElSOyB4cyA8LSBhcy5udW1lcmljKHNjYWxlKHgpKTsgbGFneHMgPC0gbGFnLmxpc3R3KGx3LCB4cykNCiAgbG9jbSA8LSBsb2NhbG1vcmFuKHgsIGx3LCB6ZXJvLnBvbGljeT1UUlVFKTsgc2lnIDwtIGxvY21bLDVdIDwgMC4wNQ0KICBwZXRhJGtsYXN0ZXIgPC0gIlRpZGFrIHNpZ25pZmlrYW4iDQogIHBldGEka2xhc3RlcltzaWcgJiB4cz4wICYgbGFneHM+MF0gPC0gIkhpZ2gtSGlnaCINCiAgcGV0YSRrbGFzdGVyW3NpZyAmIHhzPDAgJiBsYWd4czwwXSA8LSAiTG93LUxvdyINCiAgcGV0YSRrbGFzdGVyW3NpZyAmIHhzPjAgJiBsYWd4czwwXSA8LSAiSGlnaC1Mb3ciDQogIHBldGEka2xhc3RlcltzaWcgJiB4czwwICYgbGFneHM+MF0gPC0gIkxvdy1IaWdoIg0KICBwZXRhJGtsYXN0ZXIgPC0gZmFjdG9yKHBldGEka2xhc3RlciwNCiAgICBsZXZlbHM9YygiSGlnaC1IaWdoIiwiTG93LUxvdyIsIkhpZ2gtTG93IiwiTG93LUhpZ2giLCJUaWRhayBzaWduaWZpa2FuIikpDQogIGdncGxvdChwZXRhKSArDQogICAgZ2VvbV9zZihhZXMoZmlsbD1rbGFzdGVyKSwgY29sb3I9IndoaXRlIiwgbGluZXdpZHRoPTAuMTUpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiSGlnaC1IaWdoIj0iI2IyMTgyYiIsIkxvdy1Mb3ciPSIjMjE2NmFjIiwNCiAgICAgICJIaWdoLUxvdyI9IiNlZjhhNjIiLCJMb3ctSGlnaCI9IiM2N2E5Y2YiLCJUaWRhayBzaWduaWZpa2FuIj0iZ3JleTg4IiksDQogICAgICBuYW1lPSJLbGFzdGVyIExJU0EiLCBkcm9wPUZBTFNFKSArDQogICAgbGFicyh0aXRsZT1wYXN0ZTAoIktsYXN0ZXIgU3Bhc2lhbCBMSVNBIEluc2lkZW5zIFRCLCAiLCB0aCksDQogICAgICAgICBjYXB0aW9uPSJIaWdoLUhpZ2ggPSBob3RzcG90OyBMb3ctTG93ID0gY29sZHNwb3QiKSArDQogICAgdGhlbWVfbWluaW1hbChiYXNlX3NpemU9MTIpICsNCiAgICB0aGVtZShheGlzLnRleHQ9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICBheGlzLnRpY2tzPWVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZD1lbGVtZW50X2JsYW5rKCkpDQp9DQoNCiMgLS0tIFBldGEgSG90c3BvdCBHZXRpcy1PcmQgR2kqIC0tLQ0KcGV0YV9nZXRpcyA8LSBmdW5jdGlvbihkZiwgdGgpew0KICBwZXRhIDwtIGluZG8gJT4lIGxlZnRfam9pbihkZiwgYnk9IlByb3ZpbnNpIikNCiAgZ2kgPC0gYXMubnVtZXJpYyhsb2NhbEcocGV0YSRJUiwgbHdfc2VsZiwgemVyby5wb2xpY3k9VFJVRSkpDQogIHBldGEkaG90IDwtIGN1dChnaSwgYnJlYWtzPWMoLUluZiwtMi41OCwtMS45NiwtMS42NSwxLjY1LDEuOTYsMi41OCxJbmYpLA0KICAgIGxhYmVscz1jKCJDb2xkc3BvdCA5OSUiLCJDb2xkc3BvdCA5NSUiLCJDb2xkc3BvdCA5MCUiLCJUaWRhayBzaWduaWZpa2FuIiwNCiAgICAgICAgICAgICAiSG90c3BvdCA5MCUiLCJIb3RzcG90IDk1JSIsIkhvdHNwb3QgOTklIikpDQogIHdhcm5hX2cgPC0gYygiQ29sZHNwb3QgOTklIj0iIzIxNjZhYyIsIkNvbGRzcG90IDk1JSI9IiM2N2E5Y2YiLCJDb2xkc3BvdCA5MCUiPSIjZDFlNWYwIiwNCiAgICAiVGlkYWsgc2lnbmlmaWthbiI9ImdyZXk4OCIsIkhvdHNwb3QgOTAlIj0iI2ZkZGJjNyIsIkhvdHNwb3QgOTUlIj0iI2VmOGE2MiIsIkhvdHNwb3QgOTklIj0iI2IyMTgyYiIpDQogIGdncGxvdChwZXRhKSArDQogICAgZ2VvbV9zZihhZXMoZmlsbD1ob3QpLCBjb2xvcj0id2hpdGUiLCBsaW5ld2lkdGg9MC4xNSkgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz13YXJuYV9nLCBuYW1lPSJHZXRpcy1PcmQgR2kqIiwgZHJvcD1GQUxTRSkgKw0KICAgIGxhYnModGl0bGU9cGFzdGUwKCJIb3RzcG90IEluc2lkZW5zIFRCIChHZXRpcy1PcmQgR2kqKSwgIiwgdGgpLA0KICAgICAgICAgY2FwdGlvbj0iTWVyYWggPSBob3RzcG90IChrdW1wdWxhbiBJUiB0aW5nZ2kpOyBiaXJ1ID0gY29sZHNwb3QiKSArDQogICAgdGhlbWVfbWluaW1hbChiYXNlX3NpemU9MTIpICsNCiAgICB0aGVtZShheGlzLnRleHQ9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICBheGlzLnRpY2tzPWVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZD1lbGVtZW50X2JsYW5rKCkpDQp9DQpgYGANCg0KIyBIYXNpbCBBbmFsaXNpcyB7I2hhc2lsfQ0KDQojIyBBbmFsaXNpcyBEZXNrcmlwdGlmIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIyBUcmVuIE5hc2lvbmFsDQoNCmBgYHtyIHRyZW4sIGZpZy5jYXA9IlRvdGFsIGthc3VzIFRCIG5hc2lvbmFsLCAyMDIyLTIwMjQuIn0NCnRiX2FsbCAlPiUgZ3JvdXBfYnkoVGFodW4pICU+JSBzdW1tYXJpc2UoVG90YWw9c3VtKEthc3VzKSkgJT4lDQogIGdncGxvdChhZXMoVGFodW4sIFRvdGFsKSkgKw0KICBnZW9tX2NvbChmaWxsPSIjMWE2OTg1Iiwgd2lkdGg9MC42KSArDQogIGdlb21fdGV4dChhZXMobGFiZWw9Y29tbWEoVG90YWwpKSwgdmp1c3Q9LTAuNSwgc2l6ZT0zLjUpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz0yMDIyOjIwMjQpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1jb21tYSwgZXhwYW5kPWV4cGFuc2lvbihtdWx0PWMoMCwwLjEyKSkpICsNCiAgbGFicyh4PU5VTEwsIHk9IlRvdGFsIGthc3VzIFRCIikgKyB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZT0xMikNCmBgYA0KDQpgYGB7ciBpbnRlcnAtdHJlbiwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9DQp0dCA8LSB0Yl9hbGwgJT4lIGdyb3VwX2J5KFRhaHVuKSAlPiUgc3VtbWFyaXNlKFQ9c3VtKEthc3VzKSkgJT4lIGFycmFuZ2UoVGFodW4pDQphcmFoIDwtIGlmZWxzZSh0dCRUWzNdID4gdHQkVFsxXSwgIm1lbmluZ2thdCIsICJtZW51cnVuIikNCmNhdChzcHJpbnRmKCIqKkludGVycHJldGFzaS4qKiBUb3RhbCBrYXN1cyBUQiBuYXNpb25hbCBiZXJnZXJhayBkYXJpICVzICgyMDIyKSBtZW5qYWRpICVzICgyMDI0KSwgbWVudW5qdWtrYW4gdHJlbiB5YW5nICoqJXMqKiBzZWxhbWEgcGVyaW9kZSBwZW5nYW1hdGFuLiBQZXJ1YmFoYW4gaW5pIGRhcGF0IG1lbmNlcm1pbmthbiBkaW5hbWlrYSBwZW5lbXVhbiBrYXN1cyAobm90aWZpa2FzaSkgbWF1cHVuIGJlYmFuIHBlbnlha2l0IHlhbmcgc2VzdW5nZ3VobnlhLiIsDQogIGNvbW1hKHR0JFRbMV0pLCBjb21tYSh0dCRUWzNdKSwgYXJhaCkpDQpgYGANCg0KIyMjIFByb3ZpbnNpIElSIFRlcnRpbmdnaSB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQpgYGB7ciB0b3AxMC1mdW59DQpwbG90X3RvcDEwIDwtIGZ1bmN0aW9uKGRmLCB0aCl7DQogIGRmICU+JSBzbGljZV9tYXgoSVIsIG49MTApICU+JQ0KICAgIGdncGxvdChhZXMocmVvcmRlcihzdHJfdG9fdGl0bGUoUHJvdmluc2kpLCBJUiksIElSKSkgKw0KICAgIGdlb21fY29sKGZpbGw9IiNlMDdiMzkiKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChJUiwwKSksIGhqdXN0PS0wLjIsIHNpemU9MykgKw0KICAgIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9ZXhwYW5zaW9uKG11bHQ9YygwLDAuMTIpKSkgKw0KICAgIGxhYnMoeD1OVUxMLCB5PXBhc3RlMCgiSVIgVEIgcGVyIDEwMC4wMDAgKCIsIHRoLCAiKSIpKSArIHRoZW1lX21pbmltYWwoYmFzZV9zaXplPTEyKQ0KfQ0KYGBgDQoNCiMjIyMgMjAyMg0KYGBge3IgdG9wMTAtMjAyMiwgZmlnLmNhcD0iU2VwdWx1aCBwcm92aW5zaSBJUiB0ZXJ0aW5nZ2kgKDIwMjIpLiJ9DQpwbG90X3RvcDEwKHRiMjIsIDIwMjIpDQpgYGANCg0KIyMjIyAyMDIzDQpgYGB7ciB0b3AxMC0yMDIzLCBmaWcuY2FwPSJTZXB1bHVoIHByb3ZpbnNpIElSIHRlcnRpbmdnaSAoMjAyMykuIn0NCnBsb3RfdG9wMTAodGIyMywgMjAyMykNCmBgYA0KDQojIyMjIDIwMjQNCmBgYHtyIHRvcDEwLTIwMjQsIGZpZy5jYXA9IlNlcHVsdWggcHJvdmluc2kgSVIgdGVydGluZ2dpICgyMDI0KS4ifQ0KcGxvdF90b3AxMCh0YjI0LCAyMDI0KQ0KYGBgDQoNCiMjIyBSaW5na2FzYW4gU3RhdGlzdGlrDQoNCmBgYHtyIHJpbmdrYXN9DQp0Yl9hbGwgJT4lIGdyb3VwX2J5KFRhaHVuKSAlPiUNCiAgc3VtbWFyaXNlKFRvdGFsX2thc3VzPXN1bShLYXN1cyksIElSX21pbj1yb3VuZChtaW4oSVIpLDEpLA0KICAgICAgICAgICAgSVJfbWVkaWFuPXJvdW5kKG1lZGlhbihJUiksMSksIElSX21lYW49cm91bmQobWVhbihJUiksMSksDQogICAgICAgICAgICBJUl9tYXg9cm91bmQobWF4KElSKSwxKSkgJT4lDQogIGthYmxlKGNhcHRpb249IlRhYmVsIDEuIFJpbmdrYXNhbiBrYXN1cyAmIElSIHBlciB0YWh1bi4iKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoPUZBTFNFLCBib290c3RyYXBfb3B0aW9ucz1jKCJzdHJpcGVkIiwiaG92ZXIiKSkNCmBgYA0KDQpgYGB7ciBpbnRlcnAtcmluZywgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9DQpyciA8LSB0Yl9hbGwgJT4lIGdyb3VwX2J5KFRhaHVuKSAlPiUgc3VtbWFyaXNlKG09bWVhbihJUiksIG1uPW1pbihJUiksIG14PW1heChJUikpDQpjYXQoc3ByaW50ZigiKipJbnRlcnByZXRhc2kuKiogUmF0YS1yYXRhIElSIGFudGFycHJvdmluc2kgYmVya2lzYXIgJS4xZi0lLjFmIHBlciAxMDAuMDAwIHBlbmR1ZHVrIHNlcGFuamFuZyAyMDIyLTIwMjQuIFJlbnRhbmcgbmlsYWkgeWFuZyBsZWJhciAobWluaW11bSBzZWtpdGFyICUuMWYgaGluZ2dhIG1ha3NpbXVtICUuMWYpIG1lbmdpbmRpa2FzaWthbiAqKmRpc3Bhcml0YXMgaW5zaWRlbnMgeWFuZyBiZXNhciBhbnRhcnByb3ZpbnNpKiosIHlhbmcgbWVuamFkaSBkYXNhciBwZXJsdW55YSBhbmFsaXNpcyBzcGFzaWFsIHVudHVrIG1lbmdldGFodWkgYXBha2FoIHByb3ZpbnNpIGJlci1JUiB0aW5nZ2kgY2VuZGVydW5nIG1lbmdlbG9tcG9rIHNlY2FyYSBnZW9ncmFmaXMuIiwNCiAgbWluKHJyJG0pLCBtYXgocnIkbSksIG1pbihyciRtbiksIG1heChyciRteCkpKQ0KYGBgDQoNCiMjIyBSaW5na2FzYW4gVmFyaWFiZWwgcGVyIFRhaHVuIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNClN0YXRpc3RpayBkZXNrcmlwdGlmIChtaW4sIG1lZGlhbiwgcmF0YS1yYXRhLCBtYWtzKSB1bnR1ayBzZWx1cnVoIHZhcmlhYmVsIHBhZGEgdGlhcCB0YWh1bi4NCg0KYGBge3IgcmluZ2thcy1mdW59DQpyaW5na2FzX3ZhciA8LSBmdW5jdGlvbihkZiwgdGgpew0KICBkZiAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KEthc3VzLCBJUiwgSVBNLCBNaXNraW4sIFNhbml0YXNpLCBLZXBhZGF0YW4sIFJhc2lvX1BrbSkgJT4lDQogICAgcGl2b3RfbG9uZ2VyKGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG89IlZhcmlhYmVsIiwgdmFsdWVzX3RvPSJOaWxhaSIpICU+JQ0KICAgIGdyb3VwX2J5KFZhcmlhYmVsKSAlPiUNCiAgICBzdW1tYXJpc2UoTWluPXJvdW5kKG1pbihOaWxhaSksMSksIE1lZGlhbj1yb3VuZChtZWRpYW4oTmlsYWkpLDEpLA0KICAgICAgICAgICAgICBNZWFuPXJvdW5kKG1lYW4oTmlsYWkpLDEpLCBNYWtzPXJvdW5kKG1heChOaWxhaSksMSksIC5ncm91cHM9ImRyb3AiKSAlPiUNCiAgICBrYWJsZShjYXB0aW9uPXBhc3RlMCgiUmluZ2thc2FuIHZhcmlhYmVsLCAiLCB0aCwgIi4iKSkgJT4lDQogICAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoPUZBTFNFLCBib290c3RyYXBfb3B0aW9ucz1jKCJzdHJpcGVkIiwiaG92ZXIiKSkNCn0NCmBgYA0KDQojIyMjIDIwMjINCmBgYHtyIHJpbmdrYXN2YXItMjAyMn0NCnJpbmdrYXNfdmFyKHRiMjIsIDIwMjIpDQpgYGANCg0KIyMjIyAyMDIzDQpgYGB7ciByaW5na2FzdmFyLTIwMjN9DQpyaW5na2FzX3Zhcih0YjIzLCAyMDIzKQ0KYGBgDQoNCiMjIyMgMjAyNA0KYGBge3IgcmluZ2thc3Zhci0yMDI0fQ0KcmluZ2thc192YXIodGIyNCwgMjAyNCkNCmBgYA0KDQojIyBQZXRhIEluc2lkZW5zIFJhdGUgKElSKSB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyMgMjAyMg0KYGBge3IgaXItMjAyMiwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTUuNX0NCnBldGFfaXIodGIyMiwgMjAyMikNCmBgYA0KDQojIyMgMjAyMw0KYGBge3IgaXItMjAyMywgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTUuNX0NCnBldGFfaXIodGIyMywgMjAyMykNCmBgYA0KDQojIyMgMjAyNA0KYGBge3IgaXItMjAyNCwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTUuNX0NCnBldGFfaXIodGIyNCwgMjAyNCkNCmBgYA0KDQpgYGB7ciBpbnRlcnAtcGV0YS1pciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9DQp0b3BfaXIgPC0gdGJfYWxsICU+JSBncm91cF9ieShUYWh1bikgJT4lIHNsaWNlX21heChJUiwgbj0zKSAlPiUNCiAgc3VtbWFyaXNlKHByb3Y9cGFzdGUoc3RyX3RvX3RpdGxlKFByb3ZpbnNpKSwgY29sbGFwc2U9IiwgIiksIC5ncm91cHM9ImRyb3AiKQ0KY2F0KHNwcmludGYoIioqSW50ZXJwcmV0YXNpLioqIFBldGEgbWVudW5qdWtrYW4gcHJvdmluc2kgZGVuZ2FuIHdhcm5hIGxlYmloIHBla2F0IG1lbWlsaWtpIGluc2lkZW5zIFRCIGxlYmloIHRpbmdnaS4gVGlnYSBwcm92aW5zaSBkZW5nYW4gSVIgdGVydGluZ2dpIHJlbGF0aWYga29uc2lzdGVuIGFudGFyIHRhaHVuIChtaXMuIHBhZGEgMjAyMjogJXMpLCBtZW5naW5kaWthc2lrYW4gYmViYW4gVEIgeWFuZyB0ZXJrb25zZW50cmFzaSBwYWRhIHdpbGF5YWgtd2lsYXlhaCB0ZXJ0ZW50dS4gS2xpayB0YWIgdGlhcCB0YWh1biB1bnR1ayBtZW1iYW5kaW5na2FuIHBlcnViYWhhbiBzZWJhcmFuLiIsDQogIHRvcF9pciRwcm92W3RvcF9pciRUYWh1bj09MjAyMl0pKQ0KYGBgDQoNCiMjIFN0YW5kYXJkaXplZCBJbmNpZGVuY2UgUmF0aW8gKFNJUikgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjIDIwMjINCmBgYHtyIHNpci0yMDIyLCBmaWcud2lkdGg9MTEsIGZpZy5oZWlnaHQ9NS41fQ0KdGFiZWxfc2lyKHRiMjIsIDIwMjIpDQpwZXRhX3Npcl9mdW4odGIyMiwgMjAyMikNCmBgYA0KDQojIyMgMjAyMw0KYGBge3Igc2lyLTIwMjMsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD01LjV9DQp0YWJlbF9zaXIodGIyMywgMjAyMykNCnBldGFfc2lyX2Z1bih0YjIzLCAyMDIzKQ0KYGBgDQoNCiMjIyAyMDI0DQpgYGB7ciBzaXItMjAyNCwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTUuNX0NCnRhYmVsX3Npcih0YjI0LCAyMDI0KQ0KcGV0YV9zaXJfZnVuKHRiMjQsIDIwMjQpDQpgYGANCg0KYGBge3IgaW50ZXJwLXBldGEtc2lyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30NCnNpcjIyZCA8LSBoaXR1bmdfc2lyKHRiMjIpDQpuX2F0YXMgPC0gc3VtKHNpcjIyZCRTSVI+MSkNCmNhdChzcHJpbnRmKCIqKkludGVycHJldGFzaS4qKiBTSVIgbWVtYmFuZGluZ2thbiBqdW1sYWgga2FzdXMgdGVyYW1hdGkgZGVuZ2FuIHlhbmcgZGloYXJhcGthbiBiaWxhIHByb3ZpbnNpIG1lbWlsaWtpIHJpc2lrbyBzZXRhcmEgcmF0YS1yYXRhIG5hc2lvbmFsLiBQYWRhIDIwMjIsIHNlYmFueWFrICoqJWQgZGFyaSAzNCBwcm92aW5zaSBtZW1pbGlraSBTSVIgPiAxKiogKHJpc2lrbyBkaSBhdGFzIHJhdGEtcmF0YSBuYXNpb25hbCwgZGl0YW5kYWkgd2FybmEgbWVyYWggcGFkYSBwZXRhKSwgc2VkYW5na2FuIHNpc2FueWEgZGkgYmF3YWggcmF0YS1yYXRhLiBQcm92aW5zaSBkZW5nYW4gU0lSIHRpbmdnaSBtZW5qYWRpIHByaW9yaXRhcyBwZXJoYXRpYW4ga2FyZW5hIGJlYmFubnlhIG1lbGFtcGF1aSBla3NwZWt0YXNpIHBvcHVsYXNpLiIsDQogIG5fYXRhcykpDQpgYGANCg0KIyMgQW5hbGlzaXMgUG9sYSBTcGFzaWFsOiBNb3JhbidzIEkgR2xvYmFsDQoNCmBgYHtyIG1vcmFufQ0KbW9yYW5fdGFodW4gPC0gZnVuY3Rpb24oZGYsIHRoKXsNCiAgcGV0YSA8LSBpbmRvICU+JSBsZWZ0X2pvaW4oZGYsIGJ5PSJQcm92aW5zaSIpDQogIG1jIDwtIG1vcmFuLm1jKHBldGEkSVIsIGx3LCBuc2ltPTk5OSwgemVyby5wb2xpY3k9VFJVRSkNCiAgZGF0YS5mcmFtZShUYWh1bj10aCwgTW9yYW5fST1yb3VuZCh1bm5hbWUobWMkc3RhdGlzdGljKSwzKSwgcF92YWx1ZT1yb3VuZChtYyRwLnZhbHVlLDMpKQ0KfQ0KbW9yYW5fdGFiIDwtIHJiaW5kKG1vcmFuX3RhaHVuKHRiMjIsMjAyMiksIG1vcmFuX3RhaHVuKHRiMjMsMjAyMyksIG1vcmFuX3RhaHVuKHRiMjQsMjAyNCkpDQptb3Jhbl90YWIgJT4lDQogIGthYmxlKGNhcHRpb249IlRhYmVsIDIuIE1vcmFuJ3MgSSBnbG9iYWwgSVIgcGVyIHRhaHVuICg5OTkgcGVybXV0YXNpKS4iKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoPUZBTFNFLCBib290c3RyYXBfb3B0aW9ucz1jKCJzdHJpcGVkIiwiaG92ZXIiKSkNCmBgYA0KDQpgYGB7ciBpbnRlcnAtbW9yYW4sIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0Kc2lnX24gPC0gc3VtKG1vcmFuX3RhYiRwX3ZhbHVlIDwgMC4wNSkNCnJuZyA8LSBzcHJpbnRmKCIlLjNmLSUuM2YiLCBtaW4obW9yYW5fdGFiJE1vcmFuX0kpLCBtYXgobW9yYW5fdGFiJE1vcmFuX0kpKQ0Ka2V0IDwtIGlmIChzaWdfbj09MykgInNpZ25pZmlrYW4gcGFkYSBrZXRpZ2EgdGFodW4iIGVsc2UgaWYgKHNpZ19uPjApIHNwcmludGYoInNpZ25pZmlrYW4gcGFkYSAlZCBkYXJpIDMgdGFodW4iLCBzaWdfbikgZWxzZSAidGlkYWsgc2lnbmlmaWthbiINCmNhdChzcHJpbnRmKCIqKkludGVycHJldGFzaS4qKiBOaWxhaSBNb3JhbidzIEkgYmVya2lzYXIgJXMgZGFuICVzIChwIDwgMCwwNSkuIE5pbGFpIHBvc2l0aWYgbWVuYW5kYWthbiAqKmF1dG9rb3JlbGFzaSBzcGFzaWFsIHBvc2l0aWYqKjogcHJvdmluc2kgZGVuZ2FuIElSIHRpbmdnaSBjZW5kZXJ1bmcgYmVyZGVrYXRhbiBkZW5nYW4gcHJvdmluc2kgYmVyLUlSIHRpbmdnaSBsYWlubnlhLCBtZW1iZW50dWsgcG9sYSBwZW5nZWxvbXBva2FuIChzcGF0aWFsIGNsdXN0ZXJpbmcpLiBLb25zaXN0ZW5zaSBuaWxhaSBhbnRhciB0YWh1biBtZW51bmp1a2thbiBwb2xhIHNwYXNpYWwgeWFuZyAqKnN0YWJpbCoqIHNlcGFuamFuZyBwZXJpb2RlLCBzZWhpbmdnYSBrZWJlcmFkYWFuIGtsYXN0ZXIgaW5pIGJ1a2FuIGtlamFkaWFuIHNlc2FhdCBtZWxhaW5rYW4ga2FyYWt0ZXJpc3RpayB5YW5nIG1lbmV0YXAuIiwNCiAgcm5nLCBrZXQpKQ0KYGBgDQoNCjo6OiB7LmluZm9ib3h9DQoqKkNhcmEgYmFjYS4qKiBNb3JhbidzIEkgbWVuZGVrYXRpICsxID0gcGVuZ2Vsb21wb2thbiBzcGFzaWFsIHBvc2l0aWY7IG1lbmRla2F0aSAwID0gYWNhay4NCkppa2EgcC12YWx1ZSA8IDAsMDUsIGF1dG9rb3JlbGFzaSBzcGFzaWFsIHNpZ25pZmlrYW4uDQo6OjoNCg0KIyMgUGV0YSBLbGFzdGVyIExJU0EgKExvY2FsIE1vcmFuKSB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyMgMjAyMg0KYGBge3IgbGlzYS0yMDIyLCBmaWcud2lkdGg9MTEsIGZpZy5oZWlnaHQ9NS41fQ0KcGV0YV9saXNhKHRiMjIsIDIwMjIpDQpgYGANCg0KIyMjIDIwMjMNCmBgYHtyIGxpc2EtMjAyMywgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTUuNX0NCnBldGFfbGlzYSh0YjIzLCAyMDIzKQ0KYGBgDQoNCiMjIyAyMDI0DQpgYGB7ciBsaXNhLTIwMjQsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD01LjV9DQpwZXRhX2xpc2EodGIyNCwgMjAyNCkNCmBgYA0KDQpgYGB7ciBpbnRlcnAtbGlzYSwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9DQpoaXR1bmdfbGlzYV9uIDwtIGZ1bmN0aW9uKGRmKXsNCiAgcGV0YSA8LSBpbmRvICU+JSBsZWZ0X2pvaW4oZGYsIGJ5PSJQcm92aW5zaSIpDQogIHg8LXBldGEkSVI7IHhzPC1hcy5udW1lcmljKHNjYWxlKHgpKTsgbGFneHM8LWxhZy5saXN0dyhsdyx4cykNCiAgbG08LWxvY2FsbW9yYW4oeCxsdyx6ZXJvLnBvbGljeT1UUlVFKTsgc2lnPC1sbVssNV08MC4wNQ0KICBoaDwtc3VtKHNpZyAmIHhzPjAgJiBsYWd4cz4wKTsgbGw8LXN1bShzaWcgJiB4czwwICYgbGFneHM8MCkNCiAgcHJvdl9oaCA8LSBzdHJfdG9fdGl0bGUocGV0YSRQcm92aW5zaVtzaWcgJiB4cz4wICYgbGFneHM+MF0pDQogIGxpc3QoaGg9aGgsIGxsPWxsLCBwcm92PXByb3ZfaGgpDQp9DQpsMjIgPC0gaGl0dW5nX2xpc2Ffbih0YjIyKQ0KcHJvdl90eHQgPC0gaWYobGVuZ3RoKGwyMiRwcm92KT4wKSBwYXN0ZTAoIiAoIiwgcGFzdGUobDIyJHByb3YsIGNvbGxhcHNlPSIsICIpLCAiKSIpIGVsc2UgIiINCmNhdChzcHJpbnRmKCIqKkludGVycHJldGFzaS4qKiBQYWRhIDIwMjIsIGFuYWxpc2lzIExJU0EgbWVuZ2lkZW50aWZpa2FzaSAqKiVkIHByb3ZpbnNpIGtsYXN0ZXIgSGlnaC1IaWdoKiolcyDigJQgeWFpdHUgcHJvdmluc2kgYmVyLUlSIHRpbmdnaSB5YW5nIGRpa2VsaWxpbmdpIHByb3ZpbnNpIGJlci1JUiB0aW5nZ2kgKGhvdHNwb3QpLCBkYW4gKiolZCBwcm92aW5zaSBrbGFzdGVyIExvdy1Mb3cqKiAoY29sZHNwb3QpLiBLbGFzdGVyIEhpZ2gtSGlnaCBtZW5hbmRhaSB3aWxheWFoIHByaW9yaXRhcyBpbnRlcnZlbnNpIGthcmVuYSBiZWJhbm55YSB0aW5nZ2kgZGFuIG1lbnllYmFyIHNlY2FyYSB0ZXJrb25zZW50cmFzaS4gQmFuZGluZ2thbiBhbnRhciB0YWh1biBtZWxhbHVpIHRhYi5cblxuIiwNCiAgbDIyJGhoLCBwcm92X3R4dCwgbDIyJGxsKSkNCmBgYA0KDQo6Ojogey5pbmZvYm94fQ0KKipDYXJhIGJhY2EgTElTQS4qKiAqSGlnaC1IaWdoKiA9IGhvdHNwb3Q7ICpMb3ctTG93KiA9IGNvbGRzcG90Ow0KKkhpZ2gtTG93KiAvICpMb3ctSGlnaCogPSBvdXRsaWVyIHNwYXNpYWwuDQo6OjoNCg0KIyMgUGV0YSBIb3RzcG90IEdldGlzLU9yZCBHaSogey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjIDIwMjINCmBgYHtyIGdldGlzLTIwMjIsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD01LjV9DQpwZXRhX2dldGlzKHRiMjIsIDIwMjIpDQpgYGANCg0KIyMjIDIwMjMNCmBgYHtyIGdldGlzLTIwMjMsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD01LjV9DQpwZXRhX2dldGlzKHRiMjMsIDIwMjMpDQpgYGANCg0KIyMjIDIwMjQNCmBgYHtyIGdldGlzLTIwMjQsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD01LjV9DQpwZXRhX2dldGlzKHRiMjQsIDIwMjQpDQpgYGANCg0KYGBge3IgaW50ZXJwLWdldGlzLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30NCmhpdHVuZ19naV9uIDwtIGZ1bmN0aW9uKGRmKXsNCiAgcGV0YSA8LSBpbmRvICU+JSBsZWZ0X2pvaW4oZGYsIGJ5PSJQcm92aW5zaSIpDQogIGdpIDwtIGFzLm51bWVyaWMobG9jYWxHKHBldGEkSVIsIGx3X3NlbGYsIHplcm8ucG9saWN5PVRSVUUpKQ0KICBob3QgPC0gc3VtKGdpPjEuNjUpOyBjb2xkIDwtIHN1bShnaTwgLTEuNjUpDQogIHByb3ZfaG90IDwtIHN0cl90b190aXRsZShwZXRhJFByb3ZpbnNpW2dpPjEuNjVdKQ0KICBsaXN0KGhvdD1ob3QsIGNvbGQ9Y29sZCwgcHJvdj1wcm92X2hvdCkNCn0NCmcyMiA8LSBoaXR1bmdfZ2lfbih0YjIyKQ0KcHJvdl90eHQgPC0gaWYobGVuZ3RoKGcyMiRwcm92KT4wKSBwYXN0ZTAoIiBQcm92aW5zaSBob3RzcG90IG1lbmNha3VwOiAiLCBwYXN0ZShnMjIkcHJvdiwgY29sbGFwc2U9IiwgIiksICIuIikgZWxzZSAiIg0KY2F0KHNwcmludGYoIioqSW50ZXJwcmV0YXNpLioqIFN0YXRpc3RpayBHZXRpcy1PcmQgR2kqIHBhZGEgMjAyMiBtZW5naWRlbnRpZmlrYXNpICoqJWQgcHJvdmluc2kgc2ViYWdhaSBob3RzcG90KiogKHNrb3ItWiA+IDEsNjU7IGt1bXB1bGFuIElSIHRpbmdnaSkgZGFuICoqJWQgcHJvdmluc2kgc2ViYWdhaSBjb2xkc3BvdCoqIChJUiByZW5kYWggdGVya2Vsb21wb2spLiVzIEhvdHNwb3QgaW5pIG1lbXBlcmt1YXQgdGVtdWFuIExJU0EgZGFuIG1lbmFuZGFpIHdpbGF5YWggZGVuZ2FuIGludGVuc2l0YXMgcGVuZ2Vsb21wb2thbiBrYXN1cyB0ZXJ0aW5nZ2kgeWFuZyBsYXlhayBkaXByaW9yaXRhc2thbi5cblxuIiwNCiAgZzIyJGhvdCwgZzIyJGNvbGQsIHByb3ZfdHh0KSkNCmBgYA0KDQo6Ojogey5pbmZvYm94fQ0KKipDYXJhIGJhY2EgaG90c3BvdC4qKiBHaSogdGluZ2dpIHBvc2l0aWYgPSBwcm92aW5zaSB0ZXJzZWJ1dCBkYW4gdGV0YW5nZ2FueWEgc2FtYS1zYW1hDQpiZXItSVIgdGluZ2dpIChob3RzcG90KS4gR2kqIG5lZ2F0aWYgPSBrdW1wdWxhbiBJUiByZW5kYWggKGNvbGRzcG90KS4gVGluZ2thdCA5MC85NS85OSUNCm1lbnVuanVra2FuIGtleWFraW5hbiBzdGF0aXN0aWsuDQo6OjoNCg0KIyMgQW5hbGlzaXMgRGV0ZXJtaW5hbjogUGVtb2RlbGFuIENvdW50DQoNCk91dGNvbWU6IGp1bWxhaCBrYXN1cyBUQiBkZW5nYW4gYG9mZnNldChsb2coUGVuZHVkdWspKWAuIFByZWRpa3RvciAoNSBjb3ZhcmlhdGUpOiBJUE0sDQolIHBlbmR1ZHVrIG1pc2tpbiwgJSBzYW5pdGFzaSBsYXlhaywga2VwYWRhdGFuIHBlbmR1ZHVrLCBkYW4gcmFzaW8gUHVza2VzbWFzIHBlciBrZWNhbWF0YW4uDQpQZW1pbGloYW4gbW9kZWwgKE5CIHZzIG1vZGVsIENBUiBzcGFzaWFsKSBkaXRlbnR1a2FuDQpvbGVoIHVqaSBhdXRva29yZWxhc2kgc3Bhc2lhbCBwYWRhIHJlc2lkdWFsIHRpYXAgdGFodW4uDQoNCiMjIyBFa3NwbG9yYXNpIEtvcmVsYXNpIGFudGFyIFByZWRpa3RvciB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQpNYXRyaWtzIGtvcmVsYXNpIGFudGFyIGVuYW0gcHJlZGlrdG9yICh0YW5wYSBJUiwga2FyZW5hIElSIGJ1a2FuIHByZWRpa3RvciBtZWxhaW5rYW4NCnR1cnVuYW4gZGFyaSBvdXRjb21lKSB1bnR1ayBtZW1lcmlrc2EgcG90ZW5zaSBtdWx0aWtvbGluZWFyaXRhcy4NCg0KYGBge3IgY29yci1mdW59DQpwbG90X2NvcnIgPC0gZnVuY3Rpb24oZGYpew0KICB2YXJzIDwtIGRmICU+JSBkcGx5cjo6c2VsZWN0KElQTSwgTWlza2luLCBTYW5pdGFzaSwgS2VwYWRhdGFuLCBSYXNpb19Qa20pDQogIGNvcnJwbG90KGNvcih2YXJzKSwgbWV0aG9kPSJjb2xvciIsIHR5cGU9InVwcGVyIiwgYWRkQ29lZi5jb2w9ImJsYWNrIiwNCiAgICAgICAgICAgbnVtYmVyLmNleD0wLjcsIHRsLmNvbD0iYmxhY2siLCB0bC5zcnQ9NDUpDQp9DQpgYGANCg0KIyMjIyAyMDIyDQpgYGB7ciBjb3JyLTIwMjIsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9Ik1hdHJpa3Mga29yZWxhc2kgYW50YXIgcHJlZGlrdG9yICgyMDIyKS4ifQ0KcGxvdF9jb3JyKHRiMjIpDQpgYGANCg0KIyMjIyAyMDIzDQpgYGB7ciBjb3JyLTIwMjMsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9Ik1hdHJpa3Mga29yZWxhc2kgYW50YXIgcHJlZGlrdG9yICgyMDIzKS4ifQ0KcGxvdF9jb3JyKHRiMjMpDQpgYGANCg0KIyMjIyAyMDI0DQpgYGB7ciBjb3JyLTIwMjQsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9Ik1hdHJpa3Mga29yZWxhc2kgYW50YXIgcHJlZGlrdG9yICgyMDI0KS4ifQ0KcGxvdF9jb3JyKHRiMjQpDQpgYGANCg0KIyMjIFVqaSBPdmVyZGlzcGVyc2kgJiBBdXRva29yZWxhc2kgUmVzaWR1YWwgKHBlciBUYWh1bikNCg0KYGBge3IgZGlhZ25vc3Rpa30NCmZfY292IDwtIEthc3VzIH4gSVBNICsgTWlza2luICsgU2FuaXRhc2kgKyBLZXBhZGF0YW4gKyBSYXNpb19Qa20NCg0KZGlhZ25vc3RpayA8LSBmdW5jdGlvbihkZiwgdGgpew0KICBtcCA8LSBnbG0oZl9jb3YsIGZhbWlseT1wb2lzc29uKCJsb2ciKSwgb2Zmc2V0PWxvZyhQZW5kdWR1ayksIGRhdGE9ZGYpDQogIGRpc3AgPC0gc3VtKHJlc2lkdWFscyhtcCwgdHlwZT0icGVhcnNvbiIpXjIpL21wJGRmLnJlc2lkdWFsDQogIG1uYiA8LSBnbG0ubmIodXBkYXRlKGZfY292LCAufi4gKyBvZmZzZXQobG9nKFBlbmR1ZHVrKSkpLCBkYXRhPWRmKQ0KICByZGYgPC0gZGYgJT4lIG11dGF0ZSgucj1yZXNpZHVhbHMobW5iLCB0eXBlPSJwZWFyc29uIikpICU+JSBkcGx5cjo6c2VsZWN0KFByb3ZpbnNpLCAucikNCiAgcGV0YSA8LSBpbmRvICU+JSBsZWZ0X2pvaW4ocmRmLCBieT0iUHJvdmluc2kiKQ0KICBtYyA8LSBtb3Jhbi5tYyhwZXRhJC5yLCBsdywgbnNpbT05OTksIHplcm8ucG9saWN5PVRSVUUpDQogIGRhdGEuZnJhbWUoVGFodW49dGgsIERpc3BlcnNpPXJvdW5kKGRpc3AsMSksDQogICAgICAgICAgICAgTW9yYW5fcmVzaWR1YWw9cm91bmQodW5uYW1lKG1jJHN0YXRpc3RpYyksMyksDQogICAgICAgICAgICAgcF92YWx1ZT1yb3VuZChtYyRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgIE1vZGVsPWlmZWxzZShtYyRwLnZhbHVlPDAuMDUsICJNb2RlbCBDQVIiLCAiTkIiKSkNCn0NCnRhYmVsX2RpYWcgPC0gcmJpbmQoZGlhZ25vc3Rpayh0YjIyLDIwMjIpLCBkaWFnbm9zdGlrKHRiMjMsMjAyMyksIGRpYWdub3N0aWsodGIyNCwyMDI0KSkNCnRhYmVsX2RpYWcgJT4lDQogIGthYmxlKGNhcHRpb249IlRhYmVsIDMuIFVqaSBvdmVyZGlzcGVyc2kgJiBhdXRva29yZWxhc2kgcmVzaWR1YWwgTkIgcGVyIHRhaHVuLiIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGg9RkFMU0UsIGJvb3RzdHJhcF9vcHRpb25zPWMoInN0cmlwZWQiLCJob3ZlciIpKQ0KYGBgDQoNCmBgYHtyIGludGVycC1kaWFnLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30NCm5iX3RoICA8LSB0YWJlbF9kaWFnJFRhaHVuW3RhYmVsX2RpYWckTW9kZWw9PSJOQiJdDQpjYXJfdGggPC0gdGFiZWxfZGlhZyRUYWh1blt0YWJlbF9kaWFnJE1vZGVsPT0iTW9kZWwgQ0FSIl0NCmRpc3Bfcm5nIDwtIHNwcmludGYoIiUuMWYtJS4xZiIsIG1pbih0YWJlbF9kaWFnJERpc3BlcnNpKSwgbWF4KHRhYmVsX2RpYWckRGlzcGVyc2kpKQ0KdGVrc19uYiAgPC0gaWYobGVuZ3RoKG5iX3RoKSkgIHBhc3RlMCgiVGFodW4gIiwgcGFzdGUobmJfdGgsIGNvbGxhcHNlPSIsICIpLCAiIChyZXNpZHVhbCBhY2FrLCBwID4gMCwwNSkgY3VrdXAgZGltb2RlbGthbiBkZW5nYW4gKipOZWdhdGl2ZSBCaW5vbWlhbCoqLiAiKSBlbHNlICIiDQp0ZWtzX2NhciA8LSBpZihsZW5ndGgoY2FyX3RoKSkgcGFzdGUwKCJUYWh1biAiLCBwYXN0ZShjYXJfdGgsIGNvbGxhcHNlPSIsICIpLCAiIG1lbnVuanVra2FuICoqYXV0b2tvcmVsYXNpIHNwYXNpYWwgcmVzaWR1YWwqKiAocCA8IDAsMDUpIHNlaGluZ2dhIGRpbGFuanV0a2FuIGtlICoqTW9kZWwgQ0FSIChQb2lzc29uIHNwYXNpYWwpKiouICIpIGVsc2UgIiINCmNhdChzcHJpbnRmKCIqKkludGVycHJldGFzaS4qKiBSYXNpbyBkaXNwZXJzaSBqYXVoIGRpIGF0YXMgMSAoJXMpIHBhZGEgc2VtdWEgdGFodW4gbWVuZWdhc2thbiBhZGFueWEgKipvdmVyZGlzcGVyc2kqKiwgc2VoaW5nZ2EgUG9pc3NvbiBzdGFuZGFyIHRpZGFrIG1lbWFkYWkgZGFuIE5lZ2F0aXZlIEJpbm9taWFsIG1lbmphZGkgdGl0aWsgYXdhbCB5YW5nIHRlcGF0LiBTZWxhbmp1dG55YSwgdWppIE1vcmFuJ3MgSSBwYWRhIHJlc2lkdWFsIG1lbmVudHVrYW4ga2VidXR1aGFuIG1vZGVsIHNwYXNpYWw6ICVzJXNMb2dpa2EgYmVyYmFzaXMgYnVrdGkgaW5pIG1lbWFzdGlrYW4gcGVtaWxpaGFuIG1vZGVsIGRpZGFzYXJrYW4gcGFkYSBrYXJha3RlcmlzdGlrIGRhdGEsIGJ1a2FuIGFzdW1zaS4iLA0KICBkaXNwX3JuZywgdGVrc19uYiwgdGVrc19jYXIpKQ0KYGBgDQoNCjo6OiB7LmluZm9ib3h9DQoqKkxvZ2lrYSBwZW1pbGloYW4gbW9kZWwuKiogUmFzaW8gZGlzcGVyc2kgPj4gMSBwYWRhIGtldGlnYSB0YWh1biBtZW5lZ2Fza2FuIHBlbmdndW5hYW4NCk5lZ2F0aXZlIEJpbm9taWFsIChidWthbiBQb2lzc29uKS4gVWppIE1vcmFuJ3MgSSByZXNpZHVhbCBrZW11ZGlhbiBtZW5lbnR1a2FuOiBiaWxhIHAgPiAwLDA1DQoodGlkYWsgYWRhIGF1dG9rb3JlbGFzaSB0ZXJzaXNhKSBOQiBtZW1hZGFpOyBiaWxhIHAgPCAwLDA1IGRpZ3VuYWthbiBtb2RlbCBDQVIgc3Bhc2lhbC4NCkhhc2lsOiAqKjIwMjIgLT4gTkIqKiAocmVzaWR1YWwgYWNhayksICoqMjAyMyAmIDIwMjQgLT4gTW9kZWwgQ0FSKiogKHJlc2lkdWFsIGJlcmF1dG9rb3JlbGFzaSkuDQo6OjoNCg0KIyMjIE1vZGVsIDIwMjI6IE5lZ2F0aXZlIEJpbm9taWFsIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIyMgUmluZ2thc2FuICYgSVJSDQoNCmBgYHtyIG5iLTIwMjJ9DQptX25iMjIgPC0gZ2xtLm5iKHVwZGF0ZShmX2NvdiwgLn4uICsgb2Zmc2V0KGxvZyhQZW5kdWR1aykpKSwgZGF0YT10YjIyKQ0Kc3VtbWFyeShtX25iMjIpDQppcnIyMiA8LSBleHAoY2JpbmQoSVJSPWNvZWYobV9uYjIyKSwgY29uZmludChtX25iMjIpKSkNCnJvdW5kKGlycjIyLDMpICU+JQ0KICBrYWJsZShjYXB0aW9uPSJUYWJlbCA0LiBJUlIgJiA5NSUgQ0kgLSBOZWdhdGl2ZSBCaW5vbWlhbCAyMDIyLiIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGg9RkFMU0UsIGJvb3RzdHJhcF9vcHRpb25zPWMoInN0cmlwZWQiLCJob3ZlciIpKQ0KYGBgDQoNCmBgYHtyIGludGVycC1uYiwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9DQpjaSA8LSBzdXBwcmVzc01lc3NhZ2VzKGNvbmZpbnQobV9uYjIyKSkNCmVzdCA8LSBjb2VmKG1fbmIyMikNCm5tIDwtIG5hbWVzKGVzdCkNCnNpZyA8LSBubVsgKGNpWywxXT4wICYgY2lbLDJdPjApIHwgKGNpWywxXTwwICYgY2lbLDJdPDApIF0NCnNpZyA8LSBzZXRkaWZmKHNpZywgIihJbnRlcmNlcHQpIikNCnBldGFfbmFtYSA8LSBjKElQTT0iSVBNIiwgTWlza2luPSJwZXJzZW50YXNlIHBlbmR1ZHVrIG1pc2tpbiIsIFNhbml0YXNpPSJha3NlcyBzYW5pdGFzaSBsYXlhayIsDQogICAgICAgICAgICAgICBLZXBhZGF0YW49ImtlcGFkYXRhbiBwZW5kdWR1ayIsIFJhc2lvX1BrbT0icmFzaW8gUHVza2VzbWFzIHBlciBrZWNhbWF0YW4iKQ0KaWYobGVuZ3RoKHNpZyk+MCl7DQogIGZyIDwtIHNhcHBseShzaWcsIGZ1bmN0aW9uKHYpew0KICAgIGFyYWggPC0gaWZlbHNlKGVzdFt2XT4wLCAibWVuaW5na2F0a2FuIiwgIm1lbnVydW5rYW4iKQ0KICAgIHNwcmludGYoIiVzIChJUlI9JS4zZiwgJXMgcmF0ZSBUQikiLCBwZXRhX25hbWFbdl0sIGV4cChlc3Rbdl0pLCBhcmFoKQ0KICB9KQ0KICB0ZWtzIDwtIHBhc3RlMCgiRmFrdG9yIHlhbmcgKipiZXJhc29zaWFzaSBzaWduaWZpa2FuKiogKDk1JSBDSSB0aWRhayBtZW11YXQgMSk6ICIsIHBhc3RlKGZyLCBjb2xsYXBzZT0iOyAiKSwgIi4iKQ0KfSBlbHNlIHsNCiAgdGVrcyA8LSAiUGFkYSB0YXJhZiA5NSUsICoqdGlkYWsgYWRhIHByZWRpa3RvciB5YW5nIGJlcmFzb3NpYXNpIHNpZ25pZmlrYW4qKiBkZW5nYW4ganVtbGFoIGthc3VzIFRCIChzZW11YSA5NSUgQ0kgbWVtdWF0IDEpLiBIYWwgaW5pIGRhcGF0IHRlcmphZGkga2FyZW5hIGtldGVyYmF0YXNhbiBqdW1sYWggb2JzZXJ2YXNpICgzNCBwcm92aW5zaSkgeWFuZyBtZW1iYXRhc2kgZGF5YSB1amkgc3RhdGlzdGlrLiINCn0NCmNhdChzcHJpbnRmKCIqKkludGVycHJldGFzaS4qKiBJUlIgbWVueWF0YWthbiBwZXJ1YmFoYW4gcmF0ZSBUQiBwZXIga2VuYWlrYW4gc2F0dSBzYXR1YW4gcHJlZGlrdG9yIChkZW5nYW4gcHJlZGlrdG9yIGxhaW4ga29uc3RhbikuICVzIFByZWRpa3RvciBkZW5nYW4gSVJSIGRpIGF0YXMgMSBiZXJhc29zaWFzaSBkZW5nYW4gaW5zaWRlbnMgbGViaWggdGluZ2dpLCBzZWRhbmdrYW4gZGkgYmF3YWggMSBkZW5nYW4gaW5zaWRlbnMgbGViaWggcmVuZGFoLiIsIHRla3MpKQ0KYGBgDQoNCiMjIyMgTXVsdGlrb2xpbmVhcml0YXMgKFZJRikNCg0KYGBge3IgdmlmLTIwMjJ9DQp2aWYyMiA8LSBjYXI6OnZpZihtX25iMjIpDQpkYXRhLmZyYW1lKFZJRj1yb3VuZCh2aWYyMiwyKSkgJT4lDQogIGthYmxlKGNhcHRpb249IlRhYmVsIDUuIFZJRiBwcmVkaWt0b3IgKDIwMjIpLiIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGg9RkFMU0UsIGJvb3RzdHJhcF9vcHRpb25zPWMoInN0cmlwZWQiLCJob3ZlciIpKQ0KYGBgDQoNCmBgYHtyIGludGVycC12aWYsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0Kdm1heCA8LSBtYXgodmlmMjIpOyB2bm0gPC0gbmFtZXModmlmMjIpW3doaWNoLm1heCh2aWYyMildDQpzdGF0dXMgPC0gaWYodm1heDw1KSAic2VsdXJ1aG55YSBkaSBiYXdhaCA1LCBtZW5hbmRha2FuICoqdGlkYWsgYWRhIG1hc2FsYWggbXVsdGlrb2xpbmVhcml0YXMqKiIgZWxzZSBpZih2bWF4PDEwKSAidGVydGluZ2dpIGRpIGtpc2FyYW4gNS0xMCwgbWVuZ2luZGlrYXNpa2FuICoqbXVsdGlrb2xpbmVhcml0YXMgbW9kZXJhdCB5YW5nIHBlcmx1IGRpd2FzcGFkYWkqKiIgZWxzZSAibWVsZWJpaGkgMTAsIG1lbmFuZGFrYW4gKiptdWx0aWtvbGluZWFyaXRhcyBzZXJpdXMqKiINCmNhdChzcHJpbnRmKCIqKkludGVycHJldGFzaS4qKiBOaWxhaSBWSUYgJXMgKHRlcnRpbmdnaSBwYWRhICVzID0gJS4yZikuIERlbmdhbiBkZW1pa2lhbiwgZXN0aW1hc2kga29lZmlzaWVuIG1vZGVsIGRhcGF0IGRpYW5nZ2FwICVzLiIsDQogIHN0YXR1cywgdm5tLCB2bWF4LCBpZmVsc2Uodm1heDw1LCJzdGFiaWwgZGFuIGRhcGF0IGRpaW50ZXJwcmV0YXNpa2FuIGRlbmdhbiBhbWFuIiwiZGl0YWZzaXJrYW4gZGVuZ2FuIGhhdGktaGF0aSIpKSkNCmBgYA0KDQo6Ojogey5jYWxsb3V0fQ0KKipJbnRlcnByZXRhc2kgSVJSLioqIElSUj1leHAoa29lZikuIElSUj4xID0ga2VuYWlrYW4gY292YXJpYXRlIGJlcmFzb3NpYXNpIGRlbmdhbiBrZW5haWthbg0KcmF0ZSBUQjsgSVJSPDEgPSBwZW51cnVuYW4uIFNpZ25pZmlrYW4gYmlsYSA5NSUgQ0kgdGlkYWsgbWVtdWF0IDEuDQo6OjoNCg0KIyMjIE1vZGVsIENBUiAoUG9pc3NvbiBTcGFzaWFsKTogMjAyMyAmIDIwMjQgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KS2FyZW5hIHJlc2lkdWFsIE5CIHBhZGEgMjAyMyBkYW4gMjAyNCBtZW51bmp1a2thbiBhdXRva29yZWxhc2kgc3Bhc2lhbCwgZGlndW5ha2FuIG1vZGVsDQoqKkNBUiAoQ29uZGl0aW9uYWwgQXV0b3JlZ3Jlc3NpdmUpKiogZGVuZ2FuIGxpa2VsaWhvb2QgUG9pc3NvbiBkYW4gZWZlayBhY2FrIHNwYXNpYWwNCihmb3JtdWxhc2kgTGVyb3V4KS4gUGFkYSBtb2RlbCBpbmksIG92ZXJkaXNwZXJzaSB0aWRhayBkaXRhbmdhbmkgbGV3YXQgcGFyYW1ldGVyIGRpc3BlcnNpDQooc2VwZXJ0aSBOQiksIG1lbGFpbmthbiBkaXNlcmFwIG9sZWggZWZlayBhY2FrIHNwYXNpYWwgZGFuIHRhayB0ZXJzdHJ1a3R1ciDigJQgcGVuZGVrYXRhbiB5YW5nDQprb25zaXN0ZW4gZGVuZ2FuIEZhcmtoYW4gZXQgYWwuIHlhbmcgbWVuZW11a2FuIFBvaXNzb24gYmVyc3RydWt0dXIgc3Bhc2lhbCBtZW1hZGFpLiBFc3RpbWFzaQ0KQmF5ZXNpYW4gdmlhIGBDQVJCYXllczo6Uy5DQVJsZXJvdXhgIChNQ01DKTsga29lZmlzaWVuIGRpLWVrc3BvbmVuIG1lbmphZGkgKnJhdGUgcmF0aW8qLg0KDQpgYGB7ciBjYXItc2V0dXB9DQojIG1hdHJpa3Mga2V0ZXRhbmdnYWFuIGJpbmVyIChkaXBha2FpIGtlZHVhIHRhaHVuKQ0KVyA8LSBuYjJtYXQobmJfaywgc3R5bGU9IkIiLCB6ZXJvLnBvbGljeT1UUlVFKQ0KVyA8LSBwbWF4KFcsIHQoVykpDQoNCmZpdF9jYXIgPC0gZnVuY3Rpb24oZGYpew0KICBDQVJCYXllczo6Uy5DQVJsZXJvdXgoDQogICAgZm9ybXVsYSA9IHVwZGF0ZShmX2NvdiwgLn4uICsgb2Zmc2V0KGxvZyhQZW5kdWR1aykpKSwNCiAgICBmYW1pbHkgID0gInBvaXNzb24iLCBXID0gVywgZGF0YSA9IGRmLA0KICAgIGJ1cm5pbiA9IDIwMDAwLCBuLnNhbXBsZSA9IDEyMDAwMCwgdGhpbiA9IDEwLCB2ZXJib3NlID0gRkFMU0UpDQp9DQpyaW5na2FzX2NhciA8LSBmdW5jdGlvbihtLCB0aCl7DQogIHRhYiA8LSBleHAobSRzdW1tYXJ5LnJlc3VsdHNbLCBjKCJNZWRpYW4iLCIyLjUlIiwiOTcuNSUiKV0pDQogIHJvdW5kKHRhYiwzKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JQ0KICAgIGthYmxlKGNhcHRpb249cGFzdGUwKCJSYXRlIFJhdGlvIChNb2RlbCBDQVIpICYgOTUlIENySSAtICIsIHRoLCAiLiIpKSAlPiUNCiAgICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGg9RkFMU0UsIGJvb3RzdHJhcF9vcHRpb25zPWMoInN0cmlwZWQiLCJob3ZlciIpKQ0KfQ0KYGBgDQoNCiMjIyMgMjAyMw0KDQpgYGB7ciBjYXItMjAyM30NCm1fY2FyMjMgPC0gZml0X2Nhcih0YjIzKQ0KcmluZ2thc19jYXIgPC0gZnVuY3Rpb24obSwgdGgpew0KICB0YWIgPC0gZXhwKG0kc3VtbWFyeS5yZXN1bHRzWywgYygiTWVhbiIsIjIuNSUiLCI5Ny41JSIpXSkNCiAgY29sbmFtZXModGFiKSA8LSBjKCJSYXRlUmF0aW8iLCJDSV8yLjUlIiwiQ0lfOTcuNSUiKQ0KICByb3VuZCh0YWIsIDMpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lDQogICAga2FibGUoY2FwdGlvbj1wYXN0ZTAoIlJhdGUgUmF0aW8gKE1vZGVsIENBUikgJiA5NSUgQ3JJIC0gIiwgdGgsICIuIikpICU+JQ0KICAgIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aD1GQUxTRSwgYm9vdHN0cmFwX29wdGlvbnM9Yygic3RyaXBlZCIsImhvdmVyIikpDQp9DQpgYGANCg0KIyMjIyAyMDI0DQoNCmBgYHtyIGNhci0yMDI0fQ0KbV9jYXIyNCA8LSBmaXRfY2FyKHRiMjQpDQpyaW5na2FzX2NhcihtX2NhcjI0LCAyMDI0KQ0KYGBgDQoNCmBgYHtyIGludGVycC1jYXIsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0KYW1iaWxfc2lnIDwtIGZ1bmN0aW9uKG0pew0KICBzciA8LSBtJHN1bW1hcnkucmVzdWx0cw0KICByciA8LSBleHAoc3JbLCJNZWFuIl0pOyBsbzwtZXhwKHNyWywiMi41JSJdKTsgaGk8LWV4cChzclssIjk3LjUlIl0pDQogIG5tIDwtIHJvd25hbWVzKHNyKQ0KICBrZWVwIDwtICEobG88MSAmIGhpPjEpICYgbm0hPSIoSW50ZXJjZXB0KSINCiAgbm1ba2VlcF0NCn0NCnBldGFfbm0gPC0gYyhJUE09IklQTSIsIE1pc2tpbj0icGVuZHVkdWsgbWlza2luIiwgU2FuaXRhc2k9InNhbml0YXNpIGxheWFrIiwNCiAgICAgICAgICAgICBLZXBhZGF0YW49ImtlcGFkYXRhbiBwZW5kdWR1ayIsIFJhc2lvX1BrbT0icmFzaW8gUHVza2VzbWFzIikNCnMyMyA8LSBhbWJpbF9zaWcobV9jYXIyMyk7IHMyNCA8LSBhbWJpbF9zaWcobV9jYXIyNCkNCmYgPC0gZnVuY3Rpb24odikgaWYobGVuZ3RoKHYpPjApIHBhc3RlKHBldGFfbm1bdl0sIGNvbGxhcHNlPSIsICIpIGVsc2UgInRpZGFrIGFkYSBwcmVkaWt0b3IgeWFuZyBrcmVkaWJlbCBpbnRlcnZhbG55YSBtZW5qYXVoIGRhcmkgMSINCmNhdChzcHJpbnRmKCIqKkludGVycHJldGFzaS4qKiBTZXRlbGFoIG1lbXBlcmhpdHVuZ2thbiBlZmVrIGFjYWsgc3Bhc2lhbCBtZWxhbHVpIG1vZGVsIENBUiwgZmFrdG9yIHlhbmcgYmVyYXNvc2lhc2kgKDk1JSUgQ3JJIHRpZGFrIG1lbXVhdCAxKSBhZGFsYWg6ICoqMjAyMyoqIOKAlCAlczsgKioyMDI0Kiog4oCUICVzLiBLb25zaXN0ZW5zaSBhcmFoIHJhdGUgcmF0aW8gZGVuZ2FuIG1vZGVsIE5CIDIwMjIgbWVtcGVya3VhdCBrZWFuZGFsYW4gdGVtdWFuIGRldGVybWluYW4uIEludGVydmFsIGtyZWRpYmVsIHlhbmcgbGViYXIgd2FqYXIgbWVuZ2luZ2F0IGhhbnlhIDM0IGFyZWEsIHNlaGluZ2dhIGludGVycHJldGFzaSBkaWZva3Vza2FuIHBhZGEgYXJhaCBhc29zaWFzaSwgYnVrYW4gcHJlc2lzaSB0aXRpayBlc3RpbWFzaS4iLA0KICBmKHMyMyksIGYoczI0KSkpDQpgYGANCg0KOjo6IHsuY2FsbG91dH0NCioqQ2F0YXRhbi4qKiBNb2RlbCBDQVIgQmF5ZXNpYW4gdW50dWsgMzQgYXJlYSBiZXJzaWZhdCBla3NwbG9yYXRpZjsgaW50ZXJ2YWwga3JlZGliZWwgY2VuZGVydW5nDQpsZWJhci4gRm9rdXNrYW4gaW50ZXJwcmV0YXNpIHBhZGEgYXJhaCAmIGtvbnNpc3RlbnNpIHJhdGUgcmF0aW8gZGVuZ2FuIG1vZGVsIE5CIDIwMjIsIHNlcnRhDQpmYWt0b3IgeWFuZyBrcmVkaWJlbCBpbnRlcnZhbG55YSB0aWRhayBtZW11YXQgMS4NCjo6Og0KDQojIFBlbWJhaGFzYW4geyNwZW1iYWhhc2FufQ0KDQo6Ojogey5pbmZvYm94fQ0KU2VzdWFpIHBlZG9tYW4gYmFnaWFuIEYuIEJhaGFzOiB0ZW11YW4gdXRhbWEgKElSLCBTSVIsIGhvdHNwb3QsIGRldGVybWluYW4gc2lnbmlmaWthbik7DQptYWtuYSBlcGlkZW1pb2xvZ2lzOyBpbXBsaWthc2kga2ViaWpha2FuOyBrZXRlcmJhdGFzYW4gKGRhdGEgYWdyZWdhdC9la29sb2dpcywgMzQgYXJlYQ0KbWVtYmF0YXNpIHByZWRpa3RvciAmIG1vZGVsIHNwYXNpYWwgQmF5ZXNpYW4sIDMgdGFodW4sIGtlbXVuZ2tpbmFuIHVuZGVyLXJlcG9ydGluZykuDQpCYW5kaW5na2FuIGRlbmdhbiBwYXBlciBhY3VhbjogZGkgc2FuYSBQb2lzc29uICsgQllNIGxlYmloIGJhaWsgKDUxNCBrYWJ1cGF0ZW4gZGVuZ2FuDQpyYW5kb20gZWZmZWN0IHNwYXNpYWwpLCBzZWRhbmdrYW4gcGFkYSBza2FsYSAzNCBwcm92aW5zaSB0YW5wYSByYW5kb20gZWZmZWN0LCBOQiBsZWJpaA0KdGVwYXQgdW50dWsgbWVuZ2Frb21vZGFzaSBvdmVyZGlzcGVyc2kuIEFuYWxpc2lzIGRldGVybWluYW4gZGlmb2t1c2thbiBwYWRhIDIwMjIga2FyZW5hDQpwb2xhIHNwYXNpYWwgc3RhYmlsIHNlcGFuamFuZyBwZXJpb2RlIChNb3JhbidzIEkgMCwyMy0wLDI3OyBwIDwgMCwwNSkuDQoNCioqQ2F0YXRhbiBkYXRhIEpLTi4qKiBWYXJpYWJlbCBjYWt1cGFuIEphbWluYW4gS2VzZWhhdGFuIE5hc2lvbmFsIHRpZGFrIGRpbWFzdWtrYW4ga2UgZGFsYW0NCm1vZGVsIGthcmVuYSBkaXRlbXVrYW4gaW5rb25zaXN0ZW5zaSBhbnRhcmEgZGF0YSBwZXNlcnRhIEpLTiBkYW4ganVtbGFoIHBlbmR1ZHVrOiBwcm9wb3JzaQ0KY2FrdXBhbiBtZWxlYmloaSAxMDAlIHBhZGEgYmViZXJhcGEgcHJvdmluc2kgKG1lbmNhcGFpIHNla2l0YXIgMzg3JSBkaSBQYXB1YSBwYWRhIDIwMjMtMjAyNCkuDQpIYWwgaW5pIGtlbXVuZ2tpbmFuIGRpc2ViYWJrYW4gb2xlaCBrZXRpZGFrc2VzdWFpYW4gYmF0YXMgd2lsYXlhaCBhZG1pbmlzdHJhdGlmIGRhbiBwZXJpb2RlDQpwZW5kYXRhYW4sIGtodXN1c255YSBwYXNjYS1wZW1la2FyYW4gcHJvdmluc2kgUGFwdWEgdGFodW4gMjAyMi4gTWVtYXN1a2thbiB2YXJpYWJlbCBkZW5nYW4NCmlua29uc2lzdGVuc2kgc2ViZXNhciBpbmkgYmVyaXNpa28gbWVtYmlhc2thbiBlc3RpbWFzaSwgc2VoaW5nZ2EgdmFyaWFiZWwgaW5pIGRpa2VsdWFya2FuDQpkZW1pIG1lbmphZ2EgdmFsaWRpdGFzIG1vZGVsLg0KOjo6DQoNCiooVHVsaXNrYW4gcGVtYmFoYXNhbiBkaSBzaW5pLikqDQoNCiMgS2VzaW1wdWxhbiB7I2tlc2ltcHVsYW59DQoNCiooUmluZ2thc2FuIHRlbXVhbiAmIHJla29tZW5kYXNpIHByb3BvcnNpb25hbC4pKg0KDQojIERhZnRhciBQdXN0YWthIHsjcHVzdGFrYX0NCg0KMS4gKihTdW1iZXIga2FzdXMgVEIgJiB0cmVhdG1lbnQgLSBTSVRCL1Byb2ZpbCBLZXNlaGF0YW4gS2VtZW5rZXMuKSoNCjIuICooU3VtYmVyIHBlbmR1ZHVrIC0gQlBTLikqDQozLiAqKFN1bWJlciBjb3ZhcmlhdGUgLSBCUFM6IElQTSwga2VtaXNraW5hbiwgc2FuaXRhc2ksIGtlcGFkYXRhbjsgSktOLikqDQo0LiAqKFNoYXBlZmlsZSBiYXRhcyBwcm92aW5zaS4pKg0KNS4gRmFya2hhbiBBLCBka2suIFNwYXRpb3RlbXBvcmFsIGVwaWRlbWlvbG9neSBhbmQgYXNzb2NpYXRlZCByaXNrIGZhY3RvcnMgb2YgVEINCiAgIGluY2lkZW5jZSBhbmQgbW9ydGFsaXR5IGluIEluZG9uZXNpYSAyMDE3LTIwMjIuIFBvcHVsYXRpb24gSGVhbHRoIE1ldHJpY3MuIDIwMjYuDQo2LiAqKFJlZmVyZW5zaSBtZXRvZGU6IE1vcmFuJ3MgSSwgTElTQSwgR2V0aXMtT3JkLCBOZWdhdGl2ZSBCaW5vbWlhbCwgQ0FSLikqDQoNCiMgTGFtcGlyYW46IEtvbnRyaWJ1c2kgQW5nZ290YSB7I2tvbnRyaWJ1c2l9DQoNCnwgQW5nZ290YSB8IEtvbnRyaWJ1c2kgfA0KfC0tLXwtLS18DQp8IFNpbnRhIFNlcHRpIFBhbmdhc3R1dGkgfCAqKC4uLikqIHwNCnwgV2luYWxpYSBBZ3dpbCB8ICooLi4uKSogfA0KDQotLS0NCg0KPGRldGFpbHM+PHN1bW1hcnk+SW5mb3JtYXNpIHNlc2kgUjwvc3VtbWFyeT4NCmBgYHtyIHNlc2l9DQpzZXNzaW9uSW5mbygpDQpgYGANCjwvZGV0YWlscz4NCg==