Survival analysis 1: A gentle Introduction into Kaplan-Meier
Curves
Analisis waktu Survival diperlukan dalam penelitian apa pun yang
menyelidiki waktu untuk hasil tertentu yang menarik. Studi kanker dalam
bidang kedokteran dan kegagalan pertama mobil dalam bidang teknik
(analisis waktu kegagalan) adalah contoh yang baik. Hasil yang
diinginkan dapat berupa kematian, remisi untuk kambuh, perkembangan,
atau kegagalan. Titik waktu untuk mencapai hasil tersebut umumnya
disebut peristiwa.Tidak semua “event” berakibat fatal, tetapi
kadang-kadang bahkan bisa menjadi hasil yang menguntungkan seperti
keluar dari rumah sakit. Dan dengan demikian, analisis ketahanan hidup
juga merupakan istilah umum, karena ini bukan hanya tentang kelangsungan
hidup.
library(tidyverse) # data wrangling and visualization
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.1 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.0
## ✔ ggplot2 3.4.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.2 ✔ tidyr 1.3.0
## ✔ purrr 1.0.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(sjPlot) # for plotting results of log.regr.
## Learn more about sjPlot with 'browseVignettes("sjPlot")'.
library(effects) # for probability output and plots
## Loading required package: carData
## lattice theme set by effectsTheme()
## See ?effectsTheme for details.
library(survival) # for core survival analysis routines
library(survminer) # for drawing survival curves
## Loading required package: ggpubr
##
## Attaching package: 'survminer'
##
## The following object is masked from 'package:survival':
##
## myeloma
library(knitr) # for a wonderful-looking tables
Dalam materi ini akan dipelajari :
- Konsep-konsep terpenting dalam analisis survival: kurva survival,
penyensoran, dan uji log-rank,
- Menghitung secara manual, kemudian mengkomputasi dan
menginterpretasikan kurva survival, dan
- Menguji perbedaan kelangsungan hidup antara dua atau lebih kelompok,
misalnya perempuan vs laki-laki
Mengapa harus mempelajari analisis survival?
library(tidyverse)
d <- tibble(
time = c(1,1,1,2,2,3,4,5,7,10),
status = c(1,1,1,1,0,1,0,0,1,0)
)
d %>% kable()
1 |
1 |
1 |
1 |
1 |
1 |
2 |
1 |
2 |
0 |
3 |
1 |
4 |
0 |
5 |
0 |
7 |
1 |
10 |
0 |
Pada subbab ini dalam menjawab pertanyaan mengapa harus mempelajari
analisis survival dapat menggunakan contoh kasus penyintas Titanic:
Dimana hanya 10 orang dan hanya 10 hari di laut setelah kecelakaan dan
menganalisisnya dengan metode statistik klasik, regresi linier dan
logistik. Problem yang akan dibahas yaitu berapa banyak orang dan berapa
lama bertahan dan berapa banyak yang meninggal pada hari tertentu.
Sehingga memiliki dua parameter utama adalah (1) waktu (dalam hari) dan
(2) “status kehidupan” orang, di mana “status = 1” berarti kematian dan
“status = 0” berarti bukan kematian. Dengan status orang maka dapat
menghitung orang yang selamat dan tidak selamat pada setiap hari.
ggplot(d, aes(time, fill = factor(status)))+
geom_bar(position = position_dodge())+
theme_bw()
Pada plot diatas belum dapat disimpulkan dalam menjawab permasalah
sebelumnya sehingga dapat dilakukan analisis.
“status = 0” tidak selalu berarti bertahan hidup. Pertama, orang
tersebut mungkin terbawa ombak dan menghilang sehingga tidak diketahui
statusnya. Mungkin sudah mati, mungkin diselamatkan oleh perahu nelayan
atau masih hidup di suatu tempat di lautan. Dengan demikian orang
yang hilang ini tidak dapat dianggap mati atau selamat . Kedua,
jika beberapa orang bertahan 10 hari, mereka mungkin mati pada hari ke
11 sehingga waktu menjadi salah satu faktor permasalahan.
Tidak memiliki data untuk setiap 10 hari ini. Kelangsungan hidup
pada data ini juga dapat dipengaruhi oleh kondisi tubuh atau pasokan
makan untuk bertahan hidup yang tidak diketahui. Demikian pula,
penurunan probabilitas kelangsungan hidup juga terakumulasi dari
waktu ke waktu , yang tidak dapat ditentukan dengan penghitungan
sederhana antara orang yang selamat dengan tidak selamat pada hari
tertentu.
Dengan permasalahan diatas, dapat menentukan metode yang tepat.
- Melihat variabel numerik “waktu”, mungkin dapat tergoda untuk
menggunakan regresi linier untuk memodelkan waktu bertahan hidup untuk
dua kelompok status yang berbeda, 0 & 1:
m <- lm(time ~ status, d %>% mutate(status = factor(status)))
library(effects)
plot(allEffects(m))

Namun, ketika membuat plot hasil modelnya, dapat disadari bahwa ada
sesuatu yang tidak beres di sana. Semua informasi yang dimiliki untuk
memodelkan waktu bertahan hidup adalah angka nol dan satu. Dan waktu
rata-rata kematian (status = 1) sebesar 2,5 hari melewatkan banyak
informasi. Sebagai contoh, setengah dari orang-orang (3 orang) meninggal
pada hari pertama! Dan semakin jauh melangkah ke depan, semakin sedikit
orang yang meninggal, yang dapat dilihat pada plot hitungan pertama di
atas. Jadi, waktu bertahan hidup tidak benar-benar linier dan tentu saja
tidak dapat digambarkan hanya dengan angka nol dan satu! Sehingga disini
model linier tampaknya tidak berguna.
- Karena disini memiliki angka nol dan satu pada kolom status, dapat
menggunakan regresi logistik, Terutama karena kurva probabilitasnya
tidak linier dan akan menangkap tren kelangsungan hidup dari waktu ke
waktu.
m <- glm(status ~ time, d, family = binomial)
library(sjPlot)
plot_model(m, type = "pred", ci.lvl = NA)
## $time

Sekarang dapat dilihat bahwa probabilitas kelangsungan hidup
non-linear, yang merupakan peningkatan besar dibandingkan dengan regresi
linier. Namun, pengamatan kelima memiliki status 0 pada hari ke-2. Ini
berarti bahwa orang tersebut pasti bertahan hidup selama 2 hari, tetapi
hilang setelahnya. Probabilitas dalam regresi logistik akan menghitung
orang ini sebagai 100% selamat setelah hari kedua hanya karena statusnya
tidak “=1”, yang salah (atau bias), karena tidak diketahui apakah orang
ini selamat. Dengan demikian, regresi logistik melebih-lebihkan
probabilitas kelangsungan hidup dan oleh karena itu juga merupakan alat
yang tidak tepat untuk menganalisis data kelangsungan hidup.
Jadi tidak dapat dilakukan analisis data Survival dengan
metode klasik. Sehingga membutuhkan metode analisis survival.
Sementara model regresi linier menggambarkan waktu, tetapi melewatkan
probabilitas kelangsungan hidup non-linier, regresi logistik menangkap
tren non-linier, tetapi melebih-lebihkan probabilitas kelangsungan
hidup. Sebaliknya, analisis survival memecahkan kedua masalah
tersebut, karena model ini memodelkan probabilitas kelangsungan hidup
non-linear dari waktu ke waktu sambil memperhitungkan subjek penelitian
yang hilang, baik yang meninggal maupun yang selamat.
Kematian bukanlah satu-satunya pilihan! Atau: “Apakah yang dimaksud
dengan peristiwa?”
Analisis waktu survival diperlukan dalam penelitian apa pun yang
menyelidiki waktu untuk hasil tertentu yang menarik. Penelitian kanker
dalam bidang kedokteran dan kegagalan pertama mobil dalam bidang teknik
(analisis waktu kegagalan) adalah contoh yang baik. Hasil yang
diinginkan dapat berupa kematian, remisi untuk kambuh, perkembangan,
atau kegagalan. Titik waktu untuk mencapai hasil tersebut umumnya
disebut peristiwa. sehingga, tidak semua “event” berakibat fatal ,
tetapi kadang-kadang bahkan bisa menjadi hasil yang menguntungkan
seperti keluar dari rumah sakit. Dan dengan demikian, analisis survival
juga merupakan istilah umum, karena ini bukan hanya tentang kelangsungan
hidup.
Kejadian, sebagai titik waktu yang tetap diperlukan karena tidak
dapat dilakukan pengamatan atau bereksperimen selamanya. Jika dipelajari
kanker paru-paru, maka tidak bisa menunggu sampai pasien meninggal
karena penyebab lain, misalnya karena sudah tua. Hanya ketika beberapa
pasien selamat dari kanker, atau beberapa mobil tidak rusak pada waktu
tertentu (peristiwa), kita bisa mendapatkan wawasan yang berharga.
Misalnya, berapa lama waktu dari awal pengobatan hingga perkembangannya,
atau berapa probabilitas untuk bertahan hidup dari kanker paru-paru
setelah tepat 1 tahun? Selain itu, hal ini membuka kemungkinan untuk
membandingkan waktu kelangsungan hidup atau kegagalan di antara kelompok
yang berbeda, misalnya kanker paru-paru antara perokok dan non-perokok,
atau waktu kerusakan antara mobil Jerman dan Korea.
Penyensoran
Sensoring diperlukan karena waktu kelangsungan hidup yang sebenarnya
tidak akan diketahui oleh beberapa individu. Ada banyak cara untuk
kehilangan subjek studi:
Dapat kehilangan seseorang tanpa alasan, ketika itu tidak muncul
lagi
Individu mungkin mengalami peristiwa lain, misalnya kematian atau
kecelakaan
Bahkan pasien yang bertahan hingga akhir penelitian dapat
diperlakukan sebagai disensor karena waktu kelangsungan hidup yang tidak
diketahui
Semua contoh di atas dianggap sebagai sensoring kanan karena arahnya
dari kiri ke kanan pada sumbu waktu. Sebagian besar data kelangsungan
hidup disensor dengan benar. Ada dua jenis sensoring lainnya. Sensor
kiri muncul jika tidak tahu dari mana penyakit itu bermula, sedangkan
sensor interval terjadi ketika waktu pasti kehilangan pasien tidak
diketahui, tetapi hanya jendela waktu. Sensoring kiri dan interval
jarang terjadi, sulit dianalisis, seringkali merupakan hasil dari desain
studi yang buruk.
Cara menghitung kurva survival Kaplan-Meier “secara manual” langkah
demi langkah
Dengan membayangkan hari yang cerah dan damai tepat sebelum
kecelakaan Titanic terjadi. Tidak ada yang meninggal, tetapi semua 10
orang berisiko tinggi (bahaya) meninggal, hanya saja mereka belum
mengetahuinya. Dapat menebak berapa banyak orang yang mungkin akan
meninggal sehari sebelum kecelakaan. Jawabannya adalah - mungkin nol.
Secara harfiah, kemungkinan kematian adalah nol, karena kita tahu bahwa
kecelakaan tidak akan terjadi sehari sebelum tabrakan yang sebenarnya.
Untuk menjawab pertanyaan ini dengan lebih tepat, kita perlu mengingat
definisi probabilitas: Probabilitas adalah rasio dari sesuatu yang
terjadi, terhadap segala sesuatu yang dapat terjadi. Jadi, jika
tidak ada seorang pun dari 10 orang yang meninggal sehari sebelum
kecelakaan, maka probabilitas kematiannya adalah 0%, sedangkan
probabilitas selamat adalah 100%:
\[ probability \ of \ dying = \frac{0}{10}
= 0\]
\[ probability \ of \ surviving =
\frac{10}{10} = 1 = 100\%\]
Untuk representasi yang lebih baik, mari kita letakkan semua angka
dalam satu tabel:
tribble(
~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
0, 10, 0, "0/10 = 0", "10/10 = 1"
) %>% kable()
0 |
10 |
0 |
0/10 = 0 |
10/10 = 1 |
Kemudian, pada hari kecelakaan , di mana semua 10 orang sekarang tahu
bahwa mereka berisiko tinggi meninggal, 3 dari mereka benar-benar
meninggal. Probabilitas kematian pada hari pertama adalah kemudian \(3/10 = 0.3 \approx 30\%\) dan kemungkinan
bertahan hidup adalah \(7/10 = 0.7 \approx
70\%\). Sehingga kelangsungan hidup juga dapat dihitung dari
kemungkinan kematian \(1-0.3 =
0.7\).
Peluang Survival
Satu momen penting di sini adalah bahwa kemungkinan untuk
bertahan hidup bersifat kumulatif, yang berarti
terakumulasi dari hari ke hari. Akumulasi ini terjadi melalui
mengalikan probabilitas baru untuk bertahan hidup pada hari
ke-1 \((1 - \frac{d_i}{n_i}) = (1 -
\frac{3}{10}) = 70\%\) dengan probabilitas lama untuk
bertahan hidup sepanjang waktu sebelumnya, yang dalam kasus kami adalah
sehari sebelum kecelakaan, atau - hari ke-nol \(S(t_{i-1}) = 100\%\):
\[ S(t_i) = S(t_{i-1})*(1 -
\frac{d_i}{n_i}) = 1 * (1 - \frac{3}{10}) = 0.7 \]
Dimana,
- \(S(t_{i−1})\) = probabilitas untuk
hidup di \(t_{i−1}\)
- \(n_i\) = jumlah pasien yang masih
hidup sebelum \(t_i\)
- \(d_i\) = Jumlah kejadian saat
\(t_i\)
- \(t_0\) = 0, \(S(0)\) = 1
Probabilitas bertahan hidup pada waktu tertentu, \(S(t)\), adalah syarat karena orang
tersebut harus bertahan hidup setelah waktu tertentu, misalnya hari
ke-nol (itulah syaratnya) untuk tetap berada dalam eksperimen untuk hari
pertama.
tribble(
~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
0, 10, 0, "0/10 = 0", "10/10 = 1",
1, 10, 3, "3/10 = 0.3", "1 * (7/10) = 0.7",
) %>% kable()
0 |
10 |
0 |
0/10 = 0 |
10/10 = 1 |
1 |
10 |
3 |
3/10 = 0.3 |
1 * (7/10) = 0.7 |
Pada hari kedua sedikit lebih menarik, karena satu orang
meninggal dan satu orang hilang begitu saja (status = 0). Orang yang
hilang ini kemungkinan besar terbawa ombak dan mudah-mudahan bisa
diselamatkan. Harapannya besar, karena semakin jauh orang tersebar di
lautan, semakin besar kemungkinan salah satu dari mereka akan ditemukan
dalam keadaan hidup. Dan hal ini akan memberi tahu dunia bahwa ada orang
lain yang masih berada di luar sana. Jadi, meskipun orang hilang
terlihat buruk, hal ini bisa jadi merupakan hal yang baik. Jadi, kita
tentu tidak bisa menganggap orang yang hilang sebagai orang yang sudah
mati. Selain itu, seperti kata pepatah Jerman: “Harapan adalah yang
terakhir mati”.
Tetapi karena kita juga tidak yakin apakah orang ini masih hidup,
kita tidak bisa mengatakan - orang tersebut selamat. Hal ini menimbulkan
dilema: meskipun tidak meninggal, orang tersebut bukan bagian dari
eksperimen kami lagi dan kami harus menghapusnya dari jumlah orang yang
berisiko. Jadi, sementara hari kedua akan memiliki 7 orang yang
berisiko yang tersisa (karena 3 orang telah meninggal di hari pertama),
hari ketiga akan tersisa hanya 5 orang, karena 1 orang
meninggal dan satu orang menghilang (disensor) dibandingkan dengan hari
kedua. Sama halnya dengan hari pertama, probabilitas kelangsungan hidup
bersifat kumulatif dan selalu menyertakan probabilitas hari
sebelumnya.
tribble(
~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
0, 10, 0, "0/10 = 0", "10/10 = 1",
1, 10, 3, "3/10 = 0.3", "1 * (7/10) = 0.7",
2, 7, 1, "1/7 = 0.14", "0.7 * (6/7) = 0.6",
3, 5, 1, "1/5 = 0.20", "0.6 * (4/5) = 0.48"
) %>% kable()
0 |
10 |
0 |
0/10 = 0 |
10/10 = 1 |
1 |
10 |
3 |
3/10 = 0.3 |
1 * (7/10) = 0.7 |
2 |
7 |
1 |
1/7 = 0.14 |
0.7 * (6/7) = 0.6 |
3 |
5 |
1 |
1/5 = 0.20 |
0.6 * (4/5) = 0.48 |
Pada dua hari berikutnya, dua orang menghilang, jadi kita
menyensor mereka. Tidak perlu menghitung sesuatu untuk data yang
disensor dalam analisis kelangsungan hidup, karena kita tidak tahu
apakah mereka selamat atau tidak. Dan karena kita tertarik pada
kelangsungan hidup atau kematian, tabel akhir di bawah ini berisi kasus
yang hanya mati. Pada hari ke 6 tidak ada yang mati
atau menghilang, oleh karena itu kami juga tidak menghitung apa pun
untuk hari itu. Orang terakhir dalam eksperimen kami meninggal pada
hari ke 7. Jadi, “N_meninggal” akan menjadi 1, dan “N_berisiko”
akan menjadi 2, karena 1 dari 5 orang yang tersisa telah meninggal dan 2
orang disensor. Dengan demikian, tabel yang dihitung secara “manual”
akan terlihat :
tribble(
~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
0, 10, 0, "0/10 = 0", "10/10 = 1",
1, 10, 3, "3/10 = 0.3", "1 * (7/10) = 0.7",
2, 7, 1, "1/7 = 0.14", "0.7 * (6/7) = 0.6",
3, 5, 1, "1/5 = 0.20", "0.6 * (4/5) = 0.48",
7, 2, 1, "1/2 = 0.50", "0.48 * (1/2) = 0.24"
) %>% kable()
0 |
10 |
0 |
0/10 = 0 |
10/10 = 1 |
1 |
10 |
3 |
3/10 = 0.3 |
1 * (7/10) = 0.7 |
2 |
7 |
1 |
1/7 = 0.14 |
0.7 * (6/7) = 0.6 |
3 |
5 |
1 |
1/5 = 0.20 |
0.6 * (4/5) = 0.48 |
7 |
2 |
1 |
1/2 = 0.50 |
0.48 * (1/2) = 0.24 |
Namun, apa yang akan terjadi jika kita mengabaikan
penyensoran dan hanya menghitung probabilitas untuk tidak mati?
Dikarenakan 4 orang tidak mati pada hari ke-7, probabilitas untuk
bertahan hidup akan menjadi \(\frac{4}{10} =
40\%\) yang hampir dua kali lipat lebih tinggi, dan dengan
demikian kita akan melebihkan probabilitas untuk bertahan
hidup, dibandingkan dengan probabilitas sebenarnya yaitu 0,24 yang
memperhitungkan penyensoran.
SUMBER
Hanya memperhatikan orang yang selamat* bahkan memiliki nama - bias
penyintas, dan ada cerita kecil di baliknya. Selama Perang Dunia Kedua,
beberapa pesawat kembali dari medan perang dengan banyak kerusakan
akibat peluru. Mereka hampir tidak bisa terbang, tapi mereka tetap
kembali. Jadi, pihak militer memutuskan untuk melindungi pesawat dengan
lebih banyak pelindung di bagian yang paling banyak lubang peluru,
seperti sayap, dan mengurangi pelindung di bagian yang tidak berlubang
peluru. Anehnya, persentase pesawat yang kembali tidak meningkat. Para
insinyur bingung! Hingga seorang ahli matematika, Abraham Walt, yang
diundang untuk memecahkan masalah ini berkata: “Pasang lebih banyak
lapis baja di tempat-tempat yang tidak memiliki lubang peluru, karena
jika tempat ini ditembak, pesawat tidak akan kembali.” Dan ketika yang
lain memikirkannya, mereka menyadari bahwa semua pesawat yang kembali
tidak memiliki lubang peluru di kokpit atau mesin. Lubang peluru
menunjukkan semua tempat di mana pesawat bisa ditembak tapi masih bisa
kembali, atau selamat! Itulah yang disebut dengan bias bertahan hidup.
Jadi, menurut saya, regresi logistik memiliki survivorship bias
dibandingkan dengan analisis ketahanan hidup jika kita ingin
menganalisis data ketahanan hidup.
Cara menghitung kurva survival Kaplan-Meier
library(tidyverse) # data wrangling and visualization
library(knitr) # beautifying tables
library(car) # for checking assumptions, e.g. vif etc.
##
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
##
## recode
## The following object is masked from 'package:purrr':
##
## some
library(broom) # for tidy model output
library(sjPlot) # for plotting results of log.regr.
library(sjmisc) # for plotting results of log.regr.
##
## Attaching package: 'sjmisc'
## The following object is masked from 'package:purrr':
##
## is_empty
## The following object is masked from 'package:tidyr':
##
## replace_na
## The following object is masked from 'package:tibble':
##
## add_case
library(effects) # for probability output and plots
Pada regresi logistik 1 adalah kelangsungan hidup, sedangkan dalam
analisis kelangsungan hidup 1 adalah kematian. Kedua, membedakan kasus
yang disensor, misalnya dapat menandainya dengan tanda plus di data atau
di plot. Data di bawah ini menunjukkan bahwa orang disensor pada hari ke
2+, 4+, 5+ dan 10+. Instal dan muat survivalpaket untuk dapat
mengeksekusi kode di bawah ini:
# install.packages("survival")
library(survival)
Surv(time = d$time, event = d$status)
## [1] 1 1 1 2 2+ 3 4+ 5+ 7 10+
Fungsi Surv
menyatukan data “waktu” dan “status” ke
dalam satu objek “survival” tunggal, yang memungkinkan untuk
“memperhitungkan pengamatan yang disensor”. Objek ini kemudian dapat
digunakan untuk memodelkan probabilitas kelangsungan hidup dengan fungsi
survfit
. Kita memodelkan kelangsungan hidup dengan
menambahkan “~1” pada objek tersebut, di mana 1 berarti tidak ada
variabel yang dapat mempengaruhi kelangsungan hidup. Objek kelangsungan
hidup kita di sisi kiri tilde adalah variabel respons dan di sisi kanan
~ (tilde) adalah prediktor, atau dalam kasus “1” - tidak ada.Selanjutnya
dapat dibuat model survival pertama dan melihat keluaran modelnya:
survival_model <- survfit(Surv(time, status) ~ 1, data = d)
# small summary
survival_model
## Call: survfit(formula = Surv(time, status) ~ 1, data = d)
##
## n events median 0.95LCL 0.95UCL
## [1,] 10 6 3 1 NA
Dimana akan didapat - n - jumlah peserta, - event -
jumlah kematian, yang secara umum disebut event karena dapat
mempelajari jenis-jenis “deadlines” lainnya, seperti kambuhnya
penyakit, atau kerusakan pertama pada mobil, - perkiraan waktu bertahan
hidup median, bukan rata-rata karena sifat non-parametrik
(dijelaskan nanti) dari analisis ketahanan hidup dan - Interval
kepercayaan 95%** untuk waktu ketahanan hidup median
Lebih banyak informasi dapat dinilai dengan fungsi
ringkasan
, yang memberikan tabel yang sama dengan perhitung
secara manual di atas:
# big summary
summary(survival_model)
## Call: survfit(formula = Surv(time, status) ~ 1, data = d)
##
## time n.risk n.event survival std.err lower 95% CI upper 95% CI
## 1 10 3 0.70 0.145 0.4665 1.000
## 2 7 1 0.60 0.155 0.3617 0.995
## 3 5 1 0.48 0.164 0.2458 0.938
## 7 2 1 0.24 0.188 0.0515 1.000
Sehingga dapat dilihat bahwa perhitungan sebelumya benar dan telah
berhasil mempelajari cara melakukan analisis survival. Sehingga mulai
sekarang dapat mulai menggunakan perangkat lunak. Perangkat lunak ini
memiliki banyak keuntungan. Sebagai contoh, fungsi summary
,
yang hanya menampilkan hasil dari kasus yang mati, dapat diisi dengan
argumen tambahan censored = TRUE
, yang menampilkan semua
kasus, baik yang mati maupun yang disensor:
summary(survival_model, censored = T)
## Call: survfit(formula = Surv(time, status) ~ 1, data = d)
##
## time n.risk n.event survival std.err lower 95% CI upper 95% CI
## 1 10 3 0.70 0.145 0.4665 1.000
## 2 7 1 0.60 0.155 0.3617 0.995
## 3 5 1 0.48 0.164 0.2458 0.938
## 4 4 0 0.48 0.164 0.2458 0.938
## 5 3 0 0.48 0.164 0.2458 0.938
## 7 2 1 0.24 0.188 0.0515 1.000
## 10 1 0 0.24 0.188 0.0515 1.000
Selanjutnya dapat menentukan hasil dari hari mana yang ingin dilihat
dengan menambahkan argumen times = ...
ke fungsi
summary
. Bahkan dapat juga meminta hari-hari yang tidak
tersedia datanya, misalnya hari ke-8 atau ke-9 dalam contoh sederhana
kita. Sebagai contoh, probabilitas kelangsungan hidup setelah hari ke-8
adalah 24%:
summary(survival_model, times = c(8, 9))
## Call: survfit(formula = Surv(time, status) ~ 1, data = d)
##
## time n.risk n.event survival std.err lower 95% CI upper 95% CI
## 8 1 6 0.24 0.188 0.0515 1
## 9 1 0 0.24 0.188 0.0515 1
Sekarang, karena kita mengetahui probabilitas yang tepat untuk
bertahan hidup pada setiap hari, bahkan pada hari-hari dimana
kita tidak memiliki datanya, kita dapat memvisualisasikan hasil model.
Install dan muat paket survminer
untuk dapat menjalankan
kode di bawah ini:
# install.packages("survminer")
library(survminer)
ggsurvplot(
survival_model,
conf.int = FALSE,
surv.median.line = "hv",
xlab = "Days",
ylab = "Survival probability",
break.time.by = 1,
risk.table = T
)

Dari output diatas dapat dilihat interval kepercayaan (CI) untuk
kelangsungan hidup sehari-hari atau alur bertahan hidup. CI
divisualisasikan secara default, tetapi dapat dihapus jika diperlukan
melalui conf.int = FALSE_perintah. Baris terakhir pada kode di atas
menampilkan tabel “Angka berisiko”, yang dihitung secara manual di
atas.
Kurva ini dijelaskan secara independen oleh dua ilmuwan berbeda pada
saat bersamaan. Edward Kaplan dan Paul Meier kemudian menerbitkan temuan
mereka bersama sebagai estimator Kaplan-Meier (KM) pada tahun 1958 dan
survfitfungsi cocok dengan type = “kaplan-meier”kurva secara
default.
Sebagian besar data kelangsungan hidup menunjukkan banyak peristiwa
di awal dan jumlah peristiwa yang lebih rendah sepanjang waktu. Hal ini
membuat kurva kelangsungan hidup non-linier dan sebagian besar data
kelangsungan hidup terdistribusi miring atau tidak normal (tidak
berbentuk lonceng). Ini adalah alasan mengapa metode KM memperkirakan
waktu bertahan hidup median daripada rata-rata sebagai ukuran tendensi
sentral. Non-linearitas dan “stepiness” dari kurva KM tidak memungkinkan
untuk meringkas data menjadi satu parameter tunggal , misalnya
kemiringan , yang membuat metode KM non-parametrik .
Interpretasi Kurva Kaplan-Meier
Sumbu x mewakili waktu dalam hari, dan sumbu y menunjukkan
probabilitas bertahan hidup atau proporsi orang yang bertahan hidup.
Jadi, kurva itu sendiri menunjukkan probabilitas kelangsungan hidup yang
tepat dari waktu ke waktu . Penurunan vertikal pada kurva menunjukkan
setidaknya satu peristiwa . Ketinggian penurunan vertikal menunjukkan
perubahan probabilitas kelangsungan hidup kumulatif. Bagian horizontal
dari kurva mewakili durasi kelangsungan hidup untuk interval waktu
tertentu , yang diakhiri oleh peristiwa berikutnya (dan penurunan
kurva). Kurva KM terlihat seperti tangga aneh dengan anak tangga yang
tidak rata, di mana probabilitas bertahan hidup konstan di antara
peristiwa, dan karenanya merupakan fungsi langkah yang mengubah nilai
hanya pada saat setiap peristiwa. Dengan cara ini setiap pasien
menyumbangkan informasi berharga untuk perhitungan selama masih hidup.
Orang yang disensor ditampilkan persis seperti pada objek bertahan
hidup, dengan plus , seperti yang dilihat pada hari ke-2. Namun,
sebagian besar plus terlihat seperti kutu vertikal , karena terletak di
bagian horizontal kurva, yaitu hari 4 dan 5 Tanda centang ditampilkan
secara default, tetapi dapat ditekan menggunakan argumen censor = FALSE.
Tabel risiko di bawah plot menunjukkan jumlah orang yang berisiko , yang
sebenarnya semua orang yang “benar-benar hidup” dalam percobaan yang
tidak mengalami kejadian atau penyensoran pada titik waktu tertentu.
Garis putus-putus mewakili waktu kelangsungan hidup rata-rata yang
sesuai dengan probabilitas kelangsungan hidup 50% . Dan jika kita
mengabaikan penyensoran dan hanya memperkirakan median waktu (hanya
untuk orang mati), kita akan mendapatkan 1,5 bukannya 3, yang akan
meningkatkan kemungkinan bertahan hidup dari 48% menjadi 70%. Sekali
lagi, mengabaikan penyensoran akan menghasilkan kemungkinan bertahan
hidup yang terlalu tinggi karena bias keberlangsungan hidup.
d %>%
filter(status == 1) %>%
summarize(median_survival_whithout_censoring = median(time))
Membandingkan kelangsungan hidup kelompok
2 group
Dengan menggunakan conoth data 100 orang setelah kecelakaan Titanic
alih-alih 10 dan lihat kelangsungan hidup mereka menggunakan kurva
Kaplan-Meier. Angka-angka dalam tabel risiko semakin besar dan sebaiknya
kami menampilkan persentase berisiko dalam tanda kurung di dekat nilai
absolut. Argumen risk.table = “abs_pct” membantu dengan itu. Contoh
“bulat” dari 100 orang menunjukan persentase yang persis sama dengan
angka absolut, namun dengan jumlah “bulat” yang lebih sedikit atau
beberapa kelompok, persentase akan menjadi sangat berguna. Rata-rata
waktu bertahan hidup orang-orang di lautan dingin adalah sekitar 70 hari
dan interval kepercayaannya tidak terlalu lebar.
set.seed(999) # for reproducible example
library(rlang)
##
## Attaching package: 'rlang'
## The following object is masked from 'package:sjmisc':
##
## is_empty
## The following objects are masked from 'package:purrr':
##
## %@%, flatten, flatten_chr, flatten_dbl, flatten_int, flatten_lgl,
## flatten_raw, invoke, splice
library(dplyr)
library(tidyverse)
d <- ggstatsplot::Titanic_full %>%
mutate(survived = ifelse(Survived == "No", 1, 0),
time = runif(n=2201, min=1, max=100)) %>%
sample_n(100)
m <- survfit(Surv(time, survived) ~ 1, data = d)
ggsurvplot(m,
conf.int = TRUE,
risk.table = "abs_pct",
surv.median.line = "hv")

Misalnya, membandingkan probabilitas kelangsungan hidup laki-laki
dengan perempuan. Dengan mengganti rumus model dengan nama variabel
kategori yang diminati, misalnya sex. Plot bertahan hidup kemudian
menampilkan kurva Kaplan-Meier untuk setiap kategori variabel yang
ada:
m <- survfit(Surv(time, survived) ~ Sex, data = d)
ggsurvplot(m,
pval = TRUE,
conf.int = TRUE,
risk.table = "abs_pct",
surv.median.line = "hv")

Interpretasi perbandingan kelompok menggunakan 4 tolok
ukur
Perbandingan visual kurva : hanya dengan melihat
dua kelompok sehingga dapat mengatakan apakah ada perbedaan. Misalnya,
plot mengungkapkan bahwa perempuan memiliki kemungkinan lebih tinggi
untuk bertahan hidup hampir sepanjang periode waktu (sumbu x). Namun,
apakah perbedaan ini signifikan secara statistik memerlukan uji
statistik formal . Dengan melihat angka kurva, misalnya: pada hari yang
cerah dan indah sebelum himpitan, probabilitas bertahan hidup kedua
kelompok adalah 1,0 (atau 100% penumpang masih hidup). Pada hari ke 50,
kemungkinan bertahan hidup betina adalah ca. 0,75 (atau 75%) dan hanya
ca. 0,65 (atau 65%) untuk laki-laki. Pada hari ke 75, kelangsungan hidup
adalah ca. 60 dan kira-kira 30% sesuai.
Perbandingan interval kepercayaan (CI) : CI yang
tumpang tindih menunjukkan bahwa kelangsungan hidup jantan dan betina
tidak terlalu berbeda dan bisa jadi karena kebetulan hingga 80 hari.
Setelah 80 hari CI berhenti tumpang tindih yang menunjukkan perbedaan
signifikan dalam bertahan hidup pada titik waktu tertentu, katakanlah 90
hari.
Perkiraan waktu kelangsungan hidup Nilai Tengah
mengungkapkan lebih dari interval kepercayaan. Waktu kelangsungan hidup
rata-rata untuk setiap kelompok mewakili waktu di mana probabilitas
kelangsungan hidup adalah 50%. Misalnya kelangsungan hidup rata-rata
Betina jauh lebih tinggi (87 hari) daripada jantan (65 hari). Perbedaan
23 hari yang begitu besar, karena perempuan memiliki 23 hari lagi untuk
ditemukan oleh beberapa kapal penangkap ikan. Di sini sekali lagi, hanya
tes yang dapat mengetahui dan itulah mengapa tolok ukur terakhir untuk
membandingkan dua kelompok adalah p-value yang diestimasi oleh tes
Log-Rank (Peto et al, 1977), yang sangat penting, sehingga perlu bab
tambahan.
## Call: survfit(formula = Surv(time, survived) ~ Sex, data = d)
##
## n events median 0.95LCL 0.95UCL
## Sex=Female 31 10 87.0 60.9 NA
## Sex=Male 69 54 64.5 53.6 72.9
Log-Rank test
- Uji statistik non-parametrik Log-Rank (kadang-kadang
disebut Mantel-Haenszel) membandingkan median waktu kelangsungan hidup
kelompok. Uji Log-Rank mirip dengan uji Wilcoxon-Rank non parametrik
(1), yang juga membandingkan median dengan menggunakan peringkat dan
juga mirip dengan uji Chi-square (2), di mana kita membandingkan jumlah
kejadian yang diamati dengan yang diharapkan dengan menghitung statistik
Chi-square:
\[ X^2 = \sum_{i = 1}^{g} \frac{(O_i -
E_i)^2}{E_i}\]
Jumlah kejadian yang diharapkan dihitung untuk setiap titik waktu
dan setiap kelompok dibandingkan dengan titik waktu sebelumnya.
Nilai-nilai ini kemudian dijumlahkan pada semua titik waktu untuk
memberikan jumlah total kejadian yang diharapkan pada setiap
kelompok.
Sifat non-parametrik dari tes ini membuat tidak ada asumsi tentang
distribusi kelangsungan hidup. Jadi, apakah waktu kelangsungan hidup
normal (“lonceng melengkung”)? Bisa saja, tetapi tidak harus Faktanya,
data kelangsungan hidup sangat jarang berdistribusi normal, tetapi
sering kali miring karena biasanya banyak kejadian awal dan relatif
sedikit kejadian akhir.
Hipotesis nol dari uji Log-Rank adalah tidak ada perbedaan dalam
ketahanan hidup antara kedua kelompok. Nilai p-value sebesar 0,011
memungkinkan kita untuk menolak hipotesis nol dan mengindikasikan adanya
perbedaan rata-rata yang signifikan dalam waktu kelangsungan hidup
antara perempuan dan laki-laki.
Uji Log-Rank sangat banyak digunakan untuk membandingkan dua atau
lebih kurva kelangsungan hidup, sehingga harus benar-benar membenarkan
penggunaan uji lainnya.
Fungsi survdiff()
menghitung uji Log-Rank dan
mengembalikan komponen-komponen berikut:
- Jumlah subjek dalam setiap kelompok.
- Jumlah kejadian teramati tertimbang **dalam setiap
kelompok.
- Jumlah kejadian tertimbang * yang diharapkan* dalam setiap
kelompok.
- Statistik chi-square untuk uji kesetaraan
- dan p-value untuk perbedaan kelangsungan hidup di antara
kelompok
survdiff(Surv(time, survived) ~ Sex, data = d)
## Call:
## survdiff(formula = Surv(time, survived) ~ Sex, data = d)
##
## N Observed Expected (O-E)^2/E (O-E)^2/V
## Sex=Female 31 10 19.3 4.45 6.46
## Sex=Male 69 54 44.7 1.92 6.46
##
## Chisq= 6.5 on 1 degrees of freedom, p= 0.01
Apakah tes Log-Rank sempurna? Sayangnya, tidak. Salah satu masalahnya
adalah: uji ini tidak memberikan ukuran efek yang membuat kita
hanya memiliki p-value sebagai ukuran perbedaan. Masalah lain dengan uji
Log-Rank (dan metode Kaplan-Meier secara umum) adalah bahwa uji ini
tidak mengizinkan adanya perancu, uji ini mengabaikan
faktor/variabel lain. Untungnya, kita masih bisa membandingkan lebih
dari dua kelompok dengan satu variabel.
2 kelompok dan beberapa uji Log-Rank berpasangan (post-hoc)
Tes Log-Rank dapat membandingkan lebih dari dua kelompok dan
mengatakan apakah ada perbedaan yang signifikan (p-value <0,05) di
antara kelompok-kelompok ini. Hasil pengujian yang ditampilkan pada
tabel dan kurva KM di bawah ini menunjukkan bahwa terdapat perbedaan
kelangsungan hidup yang signifikan (p-value = 0,024) di antara kelompok
orang pada kelas tiket yang berbeda. Namun, seperti kebanyakan tes
lainnya (misalnya ANOVA), tidak disebutkan di antara kelompok mana
tepatnya. Oleh karena itu diperlukan analisis tambahan yang
membandingkan secara berpasangan setiap kelompok satu dengan kelompok
lainnya. Analisis semacam itu sering disebut post-hoc.
survdiff(Surv(time, survived) ~ Class, data = d)
## Call:
## survdiff(formula = Surv(time, survived) ~ Class, data = d)
##
## N Observed Expected (O-E)^2/E (O-E)^2/V
## Class=1st 14 4 11.03 4.477 5.532
## Class=2nd 13 5 8.49 1.432 1.666
## Class=3rd 37 30 21.81 3.074 4.760
## Class=Crew 36 25 22.68 0.238 0.383
##
## Chisq= 9.5 on 3 degrees of freedom, p= 0.02
m <- survfit(Surv(time, survived) ~ Class, data = d)
ggsurvplot(m,
pval = TRUE,
conf.int = FALSE,
risk.table = "abs_pct",
surv.median.line = "hv",
ncensor.plot = TRUE,
break.time.by = 20,
risk.table.y.text.col = TRUE, risk.table.y.text = FALSE)

Tiga argumen plot yang berguna lebih lanjut yang dapat membantu
memvisualisasikan data ketahanan hidup dengan lebih baik adalah:
break.time.by = 20
memecah sumbu x menjadi interval
waktu yang diinginkan.
risk.table.y.text.col = TRUE
dan
risk.table.y.text = FALSE
memplot batang, bukan nama dalam
anotasi teks legenda tabel risiko
ncensor.plot = TRUE
menampilkan jumlah subjek yang
disensor, yang membantu untuk memahami apa yang menjadi penyebab angka
risiko menjadi lebih kecil: peristiwa atau penyensoran.
Penafsiran
Kelangsungan hidup rata-rata adalah ca. 90 hari untuk penumpang kelas
1 dan 2, 58 hari untuk kelas 3 dan 65 hari untuk awak Titanic,
menunjukkan kelangsungan hidup orang kaya yang baik, dibandingkan dengan
yang lain. Dengan p-value yang rendah (p = 0,024) menunjukkan bahwa ada
perbedaan yang signifikan dalam kelangsungan hidup antar kelompok . Di
antaranya, hanya post-hoc yang tahu. Hasil dari analisis Log-Rank
post-hoc tersebut dapat dilakukan dengan fungsi pairwise_survdiff dari
survminer dan ditampilkan di bawah ini. Seperti biasa, jika memiliki
banyak perbandingan sehingga berisiko membuat penemuan yang salah atau
melewatkan penemuan penting. Jadi, harus menyesuaikan p-value untuk
mengurangi kemungkinan terjadinya kesalahan.
pairwise_survdiff(
formula = Surv(time, survived) ~ Class, data = d, p.adjust.method = "fdr"
)
##
## Pairwise comparisons using Log-Rank test
##
## data: d and Class
##
## 1st 2nd 3rd
## 2nd 0.414 - -
## 3rd 0.028 0.139 -
## Crew 0.095 0.317 0.414
##
## P value adjustment method: fdr
Hasil analisis post-hoc mengungkapkan bahwa kelangsungan hidup kelas
1 secara signifikan lebih tinggi dibandingkan dengan kelas 3 dan Awak.
Dan terlepas dari kenyataan bahwa rata-rata kelangsungan hidup penumpang
kelas 2 sangat mirip dengan kelas 1, interval kepercayaan kelangsungan
hidup ini sangat lebar dan banyak tumpang tindih dengan kelompok lain
(tidak ditunjukkan untuk menghindari kekacauan). Itulah mengapa
penumpang kelas 2 tidak umumnya memiliki waktu bertahan hidup yang lebih
tinggi secara signifikan meskipun memiliki waktu bertahan hidup yang
jauh lebih tinggi.
Multiple kurva Survival
Seperti disebutkan di atas, uji Log-Rank tidak dapat diterapkan pada
beberapa variabel. Namun masih dapat memplot kurva kelangsungan hidup
dari beberapa variabel untuk mendapatkan intuisi untuk data ini. Metode
lebih lanjut, misalnya model Cox, dapat mengestimasi perbedaan di antara
beberapa variabel, tetapi metode ini lebih kompleks daripada metode KM
dan dengan demikian akan dibahas di posting mendatang.
m2 <- survfit( Surv(time, survived) ~ Sex + Class, data = d )
ggsurv <- ggsurvplot(m2, conf.int = TRUE)
ggsurv$plot +theme_bw() +
theme (legend.position = "right")+
facet_grid(Sex ~ .)

Intuisi yang dapat kita peroleh dari plot di atas adalah bahwa wanita
kaya (kelas tiket 1 dan 2) dan (hanya 2) wanita dari kru kapal memiliki
probabilitas 100% untuk bertahan hidup, sementara wanita murni di kelas
3 akan mati dengan kepastian yang sama dengan pria. CI yang sangat
tumpang tindih dari kelangsungan hidup pria menunjukkan bahwa semua pria
pada akhirnya akan mati setelah kecelakaan Titanic.
Kesimpulan
Analisis ketahanan hidup menyelidiki waktu yang dibutuhkan untuk
suatu peristiwa yang menarik untuk terjadi. Sebagian besar analisis
ketahanan hidup univariat (variabel tunggal) menggunakan plot
Kaplan-Meier untuk memvisualisasikan kurva ketahanan hidup dan
Uji Log-Rank untuk membandingkan kurva ketahanan hidup dua atau
lebih kelompok.
Keuntungan krusial kurva probabilitas bertahan hidup vs. kurva
regresi logistik memperhitungkan data yang disensor, yang tidak mati,
atau hidup. Regresi logistik memperlakukan semua orang yang tidak mati
sebagai orang yang selamat, itu salah, hanya karena kita tidak
mengetahui status kelangsungan hidup orang yang tidak terjawab. Pasien
meninggalkan studi karena dua alasan utama, mereka merasa sangat buruk,
sehingga mereka tidak lagi peduli dengan eksperimen , atau mereka merasa
jauh lebih baik dan melupakan studi. Beberapa pasien mungkin hanya
pindah ke kota lain tanpa berkata apa-apa. Menghitung semuanya sebagai
selamat, seperti halnya regresi logistik, akan melebih-lebihkan
kemungkinan bertahan hidup (survivorship bias) dan meremehkan bahaya
kematian. Oleh karena itu, analisis kelangsungan hidup lebih tepat
dibandingkan dengan regresi logistik, sementara itu masih menangkap tren
probabilitas non-linier.
Keunggulan lainnya adalah sifat nonparametrik dari metode
Kaplan-Meier, yaitu tidak memiliki terlalu banyak asumsi. Sebenarnya
satu-satunya asumsi penting adalah bahwa penyensoran harus bersifat
non-informatif . Mengapa? Lebih banyak informasi selalu lebih baik,
bukan? Ya! Tapi jika kita tahu mengapa orang meninggalkan penelitian,
kita bisa menggunakan informasi ini sebagai variabel baru dan
mempelajari pengaruhnya terhadap kelangsungan hidup. Metode KM akan
menjadi tidak tepat, karena akan melewatkan informasi ini. Namun,
seringkali tidak tahu (tidak ada info) mengapa orang keluar (disensor).
Dan dalam hal ini metode KM memeras inferensi paling banyak dari data
non-informatif tersebut.
“Kurva” Kaplan-Meier sebenarnya tidak terlihat seperti kurva.
Berlawanan dengan regresi logistik metode Kaplan-Meier tidak dapat
digambarkan sebagai fungsi halus (kurva) dengan beberapa parameter,
misalnya kemiringan atau rasio odds . Itu sebabnya membutuhkan tabel
hasil bodoh atau grafik.
Metode Kaplan-Meier tidak dapat memodelkan variabel numerik ,
tetapi hanya kategorikal.
Metode Kaplan-Meier tidak dapat menyertakan banyak variabel
penjelas . Itu buruk, karena membandingkan kelompok dalam hal bertahan
hidup mungkin melewatkan efek faktor lain, yang dikenal sebagai kovariat
atau perancu, yang berpotensi memengaruhi waktu bertahan hidup kelompok
tertentu.
Saran
Selalu menampilkan ketidakpastian statistik dengan memasukkan 95%
CI atau/dan nilai p dari uji Log-Rank. Menampilkan CI pada beberapa
titik waktu penting pada plot untuk setiap kelompok perlakuan terkadang
lebih jelas daripada menampilkannya untuk semua titik waktu. CI yang
tidak tumpang tindih menunjukkan perbedaan yang signifikan antar
kelompok.
Mempertimbangkan untuk memotong sumbu x . karena mata secara
alami tertarik ke bagian kanan plot, di mana waktu berakhir. Namun,
akhir plot berisi paling sedikit informasi dan ketidakpastian terbesar
karena hanya sedikit peserta yang tersisa. Seberapa jauh waktu untuk
memperpanjang plot? Terserah kamu.
Selalu menampilkan tabel risiko yang menunjukkan jumlah pasien
bebas kejadian dan masih dalam tindak lanjut di setiap kelompok
perlakuan pada titik waktu yang relevan.
Survival analysis 2: Parametric Survival Models
Metode Kaplan-Meier (KM) non-parametrik tidak dapat menggambarkan
probabilitas bertahan hidup dengan fungsi yang halus, yang berarti tidak
dapat memprediksi apa pun. Model parametrik (mis. Eksponensial, Weibull,
dll.) Selain itu, jika model parametrik sesuai, model tersebut lebih
tepat, lebih efektif, dan lebih informatif daripada KM atau Cox. Namun
sayangnya, langkah ini sering ditinggalkan karena penggunaan model
parametrik belakang. Dalam posting ini akan mencoba untuk menutup celah
ini.
library(tidyverse) # data wrangling and visualization
library(sjPlot) # for plotting results of log.regr.
library(effects) # for probability output and plots
library(survival) # for core survival analysis routines
library(survminer) # for drawing survival curves
library(flexsurv) # for Parametric Survival Modelling
library(knitr) # for a wonderful-looking tables
Mengapa kita membutuhkan model kelangsungan hidup parametrik
d2 <- tibble(
time = c(1,1,1,2,2,3,4,5,7,10),
status = c(1,1,1,1,0,1,0,0,1,0)
)
m <- survfit(Surv(time, status) ~ 1, data = d2)
ggsurvplot(
m,
conf.int = FALSE,
surv.median.line = "hv",
xlab = "Days",
ylab = "Survival probability",
break.time.by = 1,
risk.table = F
)

Kerugian utama dari metode non-parametrik Kaplan-Meier
(KM) yang ditunjukkan pada gambar di atas adalah tidak dapat
dijelaskan probabilitas bertahan hidup dengan fungsi yang halus, yang
artinya tidak dapat memprediksi apapun. Model parametrik (seperti
Eksponensial, Weibull, dll.) Selain itu, model
parametrik adalah langkah logis dalam perjalanan dari KM ke
model Cox semi-parametrik , karena mereka dengan indah menghubungkan
titik-titik antara model KM dan Cox dan dengan demikian sangat
meningkatkan pemahaman tentang analisis kelangsungan hidup. Selain itu,
jika model parametrik sesuai, model tersebut lebih tepat, lebih
efektif, dan lebih informatif dari KM atau Cox. Namun
sayangnya, langkah ini sering ditinggalkan karena penggunaan model
parametrik belakang.
Apakah Waktu itu Variabel atau Konstanta?
Kematian dapat digambarkan dengan dua hal: peristiwa kematian itu
sendiri dan titik waktu tertentu saat kematian terjadi. Dua hal ini
selalu menggambarkan satu peristiwa, karena satu hanya mati sekali.
Dengan demikian, waktu kematian akan bervariasi dan jumlah kematian akan
bertambah seiring waktu, yang akan menjadikan waktu itu sendiri sebagai
variabel . Begitulah beberapa peristiwa kematian pada titik waktu yang
berbeda memungkinkan untuk mengungkapkan kematian dalam dua cara:
Melalui sejumlah kejadian yang berbeda per satuan waktu tetap ,
yang sering disebut Risiko (Hazard) untuk mati , atau hanya Hazard (λ -
lambda ). Ini membuat jumlah kejadian menjadi variabel, dan Bahaya
menjadi tingkat kematian , misalnya, per hari.
Melalui bentangan waktu berlalu yang berbeda per jumlah peristiwa
yang tetap . Interval waktu biasanya diukur hingga peristiwa berikutnya
terjadi. Ini membuat waktu menjadi variabel.
Perubahan stabil dalam bahaya dan kelangsungan hidup
Bayangkan setiap hari tepat 3 dari 10 orang meninggal di air laut
yang dingin setelah kecelakaan Titanic. Ini tingkat kematian yang cukup
stabil , atau Bahaya , sebesar 30%. Jika bahaya untuk mati terus tumbuh
dengan laju yang sama, maka kemungkinan untuk bertahan hidup akan terus
berkurang dengan laju yang sama. Dengan demikian, Bahaya dan
Kelangsungan Hidup dapat diekspresikan satu sama lain. Secara khusus,
Bahaya kematian dari waktu ke waktu dapat dilihat sebagai Gagal bertahan
hidup \(F( t )\) dan kelangsungan hidup
dari waktu ke waktu \(S( t )\) yang
dapat dilihat sebagai Hazard of NOT-dying , atau hanya Hazard negatif ,
yang secara matematis dapat dinyatakan sebagai tanda minus “-”, atau
“1-”, di depan Hazard. Kedua fungsi tersebut menghasilkan garis lurus,
di mana Bahaya terus meningkat dan kelangsungan hidup terus menurun
(plot di bawah): \[ F(t) = Hazard * t
\] \[S(t) = 1 - Hazard *
t\]

Peningkatan atau penurunan yang stabil dalam bahaya atau kelangsungan
hidup seperti itu agak tidak alami, tidak realistis. Dalam memperkirakan
kematian dapat dikatakn sulit. Bahaya biasanya meningkat secara
eksponensial, misalnya dalam kasus kelaparan, atau menurun secara
eksponensial, misalnya dalam kasus pandemi setelah vaksin ditemukan.
Perubahan eksponensial positif dalam bahaya dan kelangsungan
hidup
Pikirkan tentang kelaparan sejenak. Semakin lama kondisi kelaparan,
semakin tinggi kemungkinan (risiko) mati. Plot kiri di bawah menunjukkan
perkembangan seperti itu, di mana bahaya kematian \(F( t )\) dinyatakan dalam probabilitas
kecil pada awalnya (beberapa kematian), tetapi tumbuh secara
eksponensial dengan waktu (semakin banyak kematian). Saya suka menyebut
tren seperti itu sebagai perubahan eksponensial yang positif, atau
mempercepat. “exp” dalam rumus kiri di bawah adalah semua yang
diperlukan untuk merencanakan tren tersebut.
Sekali lagi, karena kelangsungan hidup dapat dilihat sebagai bahaya
negatif dapat menyatakan kelangsungan hidup \(S( t )\) dengan hanya menggunakan tanda
minus (atau “1-”) di depan Hazard. Plot di sebelah kanan menampilkan
hasil dari fungsi bertahan hidup tersebut.Jika bahaya kematian rendah di
awal “waktu”, maka kemungkinan bertahan hidup tinggi. Di akhir “waktu”,
Kelangsungan Hidup turun secara eksponensial karena peningkatan Bahaya
secara eksponensial. \[ F(t)= exp^{Hazard *
t} \] \[S(t) = 1 - exp^{Hazard *
t}\]

Perubahan eksponensial negatif dalam bahaya dan kelangsungan
hidup
Namun, dalam beberapa kasus, lebih banyak orang meninggal pada awal
“waktu”, di mana tingkat kematian menurun dari waktu ke waktu. Pikirkan
tentang pandemi, atau kecelakaan besar. Perubahannya masih eksponensial,
dan menuju ke arah yang sama: naik, dalam kasus Bahaya, dan turun, dalam
kasus bertahan hidup. Namun, perubahan eksponensial agak terbalik
(membungkuk). Saya suka menyebutnya sebagai perubahan eksponensial yang
negatif, atau melambat.
Seperti “pembengkokan ke dalam” dapat dicapai dengan “-” minus sing
di depan Hazard dan fungsi eksponensial itu sendiri (persamaan kiri dan
gambar di bawah). Minus ini tidak menggambarkan hazard negatif, seperti
pada contoh di atas. Itu hanya mengubah kurva dari percepatan ke
perlambatan. Untuk mendapatkan kelangsungan hidup untuk fungsi ini
seperti pada contoh di atas, harus menggunakan “-” (atau “1-”) di depan
seluruh ekspresi hazard eksponensial. Menariknya, dua tanda minus di
depan “exp” dalam rumus Survival saling menetralkan dan menjadi nilai
tambah, yang menyisakan dengan
\[F(t)= - exp^{-Hazard * t}\]
\[S(t) = 1 - ( - exp^{-Hazard * t}) =
exp^{-Hazard * t}\]

Membangun Model Ekponensial
Sejak fungsi bertahan hidup \(S( t
)\) menunjukkan probabilitas bertahan hidup melewati titik waktu
tertentu ,
\[S(t) = P(T > t)\]
dan fungsi eksponensial \(F( t )\)
menunjukkan probabilitas Failed-survival melewati titik waktu tertentu
,
\[F(t) = P(T \leq t) = 1 - exp^{-Hazard *
t}\]
fungsi bertahan hidup kemudian dapat dinyatakan dalam bentuk fungsi
tidak bertahan hidup (eksponensial):
\[S(t) = P(T > t) = 1 - P(T \leq t) = 1
- F(t) = 1 - [1 - exp^{-Hazard * t}] = exp^{-Hazard * t}\]
Sehingga fungsi survival yang menunjukkan laju penurunan adalah
fungsi flipped hazard yang menunjukkan laju kenaikan. Dengan demikian,
dapat menulis ulang \(S( t )\)
sebagai:
\[S(t) = exp^{- Hazard * t} = exp^{-
\lambda* t}\]
di mana -Hazard dan waktu adalah dua parameter yang menggambarkan
perubahan eksponensial dalam probabilitas bertahan hidup, itulah
sebabnya model seperti itu memiliki nama - model eksponensial parametrik
. Dan karena Hazard adalah negative , dan fungsi eksponensial tidak
linier (alias. curvy ) - model keluar menghasilkan kurva eksponensial
negatif (lihat di bawah). Tingkat penurunan yang mulus seperti itu
menggambarkan probabilitas bertahan hidup jauh lebih baik daripada
metode Kaplan-Meier, yang secara tiba-tiba (secara bertahap) menurunkan
probabilitas hanya setelah suatu peristiwa, sambil menjaga probabilitas
tetap konstan di antara peristiwa tersebut.
Cara menghitung model parametrik
library(flexsurv) # for Parametric Survival Modelling
ex <- flexsurvreg(Surv(time, status) ~ 1, data = d2, dist="exponential")
we <- flexsurvreg(Surv(time, status) ~ 1, data = d2, dist="weibull")
ggsurvplot(
ex,
conf.int = FALSE,
surv.median.line = "hv",
xlab = "Days",
ylab = "Survival probability",
break.time.by = 1,
risk.table = F
)

Parameter kurva (\(-\lambda * t\))
memungkinkan kita untuk memodelkan dan memprediksi kelangsungan
hidup dan bahaya dari waktu ke waktu, yang merupakan keuntungan
utama dari model eksponensial dibandingkan dengan metode
Kaplan-Meier, yang tidak bersifat parametrik dan oleh karena itu tidak
dapat dimodelkan. Namun, non-linearitas sering kali merepotkan, dan kami
lebih suka menggunakan konsep regresi linear, yang meringkas
(meregresikan) banyak angka menjadi beberapa angka, seperti intersep
(\(\beta_0\)) dan kemiringan (\(\beta_1\)). Untungnya, kurva non-linier
dapat dengan mudah “dilinierkan” melalui logaritma natural. Untuk
melakukan ini, kita bahkan tidak perlu memahami cara kerja logaritma
atau fungsi eksponensial, kita hanya perlu mengetahui bahwa keduanya
saling menetralkan satu sama lain. Selain itu, menggunakan “log”
(melogaritmakan kedua sisi persamaan di bawah ini) menghasilkan tiga
efek samping yang positif:
- Pertama, di sisi kanan persamaan, ini akan memindahkan kurva
kita (\(-\lambda * t\))
menjadi sebuah garis (\(b_0 + b_1x_1
+ ... + b_kx_k\)), di mana kita akan dapat memiliki intersep dan
koefisien \(\beta\) seperti pada
regresi logistik linier biasa \[Hazard =
exp^{b_0 + b_1x_1 + ... + b_kx_k}\]
atau
\[ log(Hazard) = b_0 + b_1x_1 + ... +
b_kx_k \]
Model survival seperti itu sebenarnya adalah model Poisson. Oleh
karena itu, akan sangat membantu jika sudah mengeuasai distribusi
Poisson.
Kedua, ini akan membantu kita untuk terhubung ke model-model
selanjutnya, seperti model Weibull dan Cox, karena perbedaan di antara
keduanya terutama terletak pada intersep “\(b_0\)”;
Terakhir, ini akan sangat meningkatkan kemampuan interpretasi,
karena Hazard-Ratios (HRs) (yang dihasilkan oleh model eksponensial)
dapat diinterpretasikan persis seperti Odds-Ratios (ORs) dari regresi
logistik (seperti yang dijelaskan dalam posting saya tentang regresi
logistik). Sama halnya dengan Odds dalam regresi logistik, Hazard
itu sendiri, yang merupakan probabilitas meninggal SEKARANG, kurang
berguna dibandingkan dengan Hazard-Ratio. Hazard-Ratio adalah rasio
bahaya seseorang yang terpapar (sakit) terhadap seseorang yang tidak
terpapar (sehat). Misalnya jika HR = 2, risiko kematian seseorang yang
terpapar adalah dua kali lipat dibandingkan dengan seseorang yang tidak
terpapar.
Pikiran akhir
Apakah model parametrik berguna?
Tiga kurva di atas yang menggambarkan berbagai jenis perubahan
dalam kelangsungan hidup dan bahaya dari waktu ke waktu dimaksudkan
untuk mengatakan bahwa distribusi bisa sangat berbeda. Jika distribusi
yang sesuai dapat ditemukan, model parametrik lebih informatif daripada
model KM atau Cox
model ini dapat memprediksi probabilitas ketahanan hidup pada
titik waktu tertentu, hazard kejadian, rata-rata dan median waktu
ketahanan hidup sudah tersedia
model ini juga sedikit lebih efisien dan menghasilkan estimasi
yang lebih tepat karena kecocokan yang lebih baik (lihat gambar di
atas)
Apakah model parametrik itu sempurna? Tentu saja tidak!
model parametrik perlu menentukan distribusi, yang mungkin sulit
untuk diidentifikasi
model ini juga secara matematis lebih kompleks, misalnya KM, dan
oleh karena itu lebih jarang digunakan, sehingga mengurangi perbandingan
hasil antar studi. Karena popularitasnya yang lebih rendah, saya tidak
akan membahas lebih dalam tentang model parametrik tertentu: Model
Weibull, Gompertz, model Waktu Kegagalan yang Dipercepat, dll.
Jadi, terlepas dari kenyataan bahwa model parametrik adalah
alternatif yang baik untuk model regresi KM dan Cox (yang tidak perlu
menentukan distribusi apa pun), KM dan Cox tetap menjadi metode yang
paling populer untuk menganalisis data survival. Dan itulah mengapa
langkah logis berikutnya dalam perjalanan statistik dalam mempelajari
Model Cox Proportional Hazard (sedang berlangsung).
LS0tDQp0aXRsZTogIlVUUyBTVVJWSVZBTCBNT0RFTCAiDQpzdWJ0aXRsZTogIlR1Z2FzIFVUUyINCmF1dGhvcjogIk11aGFtbWFkIE5hdWZhbCBBcmRpYW5zeWFoICgyMDIwNDkyMDAxNykiDQpkYXRlOiAgImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyb2JvYm9vazogICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNzczogInN0eWxlLmNzcyINCg0KLS0tDQoNCg0KDQoNCjxicj4NCg0KDQo8aW1nIHN0eWxlPSJmbG9hdDogcmlnaHQ7IG1hcmdpbjogLTUwcHggNTBweCAwcHggNTBweDsgd2lkdGg6MjUlIiBzcmM9Im5hdWZhbC5qcGVnIi8+IA0KDQp8DQo6LS0tLSB8Oi0tLS0NCipLb250YWt8ICo6ICokXGRvd25hcnJvdyQqDQpFbWFpbHwgbmF1ZmFsMzQzM0BnbWFpbC5jb20NCkluc3RhZ3JhbSB8IGh0dHBzOi8vd3d3Lmluc3RhZ3JhbS5jb20vbV9uYXVmYWxhcmRpYW5zeWFoLyANClJQdWJzICB8IGh0dHBzOi8vcnB1YnMuY29tL211aGFtYWRfbmF1ZmFsLyANCg0KKioqDQoNCiMgU3Vydml2YWwgYW5hbHlzaXMgMTogQSBnZW50bGUgSW50cm9kdWN0aW9uIGludG8gS2FwbGFuLU1laWVyIEN1cnZlcw0KDQpBbmFsaXNpcyB3YWt0dSBTdXJ2aXZhbCBkaXBlcmx1a2FuIGRhbGFtIHBlbmVsaXRpYW4gYXBhIHB1biB5YW5nIG1lbnllbGlkaWtpIHdha3R1IHVudHVrIGhhc2lsIHRlcnRlbnR1IHlhbmcgbWVuYXJpay4gU3R1ZGkga2Fua2VyIGRhbGFtIGJpZGFuZyBrZWRva3RlcmFuIGRhbiBrZWdhZ2FsYW4gcGVydGFtYSBtb2JpbCBkYWxhbSBiaWRhbmcgdGVrbmlrIChhbmFsaXNpcyB3YWt0dSBrZWdhZ2FsYW4pIGFkYWxhaCBjb250b2ggeWFuZyBiYWlrLiBIYXNpbCB5YW5nIGRpaW5naW5rYW4gZGFwYXQgYmVydXBhIGtlbWF0aWFuLCByZW1pc2kgdW50dWsga2FtYnVoLCBwZXJrZW1iYW5nYW4sIGF0YXUga2VnYWdhbGFuLiBUaXRpayB3YWt0dSB1bnR1ayBtZW5jYXBhaSBoYXNpbCB0ZXJzZWJ1dCB1bXVtbnlhIGRpc2VidXQgcGVyaXN0aXdhLlRpZGFrIHNlbXVhICJldmVudCIgYmVyYWtpYmF0IGZhdGFsLCB0ZXRhcGkga2FkYW5nLWthZGFuZyBiYWhrYW4gYmlzYSBtZW5qYWRpIGhhc2lsIHlhbmcgbWVuZ3VudHVuZ2thbiBzZXBlcnRpIGtlbHVhciBkYXJpIHJ1bWFoIHNha2l0LiBEYW4gZGVuZ2FuIGRlbWlraWFuLCBhbmFsaXNpcyBrZXRhaGFuYW4gaGlkdXAganVnYSBtZXJ1cGFrYW4gaXN0aWxhaCB1bXVtLCBrYXJlbmEgaW5pIGJ1a2FuIGhhbnlhIHRlbnRhbmcga2VsYW5nc3VuZ2FuIGhpZHVwLg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKSAgIyBkYXRhIHdyYW5nbGluZyBhbmQgdmlzdWFsaXphdGlvbg0KbGlicmFyeShzalBsb3QpICAgICAjIGZvciBwbG90dGluZyByZXN1bHRzIG9mIGxvZy5yZWdyLg0KbGlicmFyeShlZmZlY3RzKSAgICAjIGZvciBwcm9iYWJpbGl0eSBvdXRwdXQgYW5kIHBsb3RzDQpsaWJyYXJ5KHN1cnZpdmFsKSAgICMgZm9yIGNvcmUgc3Vydml2YWwgYW5hbHlzaXMgcm91dGluZXMNCmxpYnJhcnkoc3Vydm1pbmVyKSAgIyBmb3IgZHJhd2luZyBzdXJ2aXZhbCBjdXJ2ZXMNCmxpYnJhcnkoa25pdHIpICAgICAgIyBmb3IgYSB3b25kZXJmdWwtbG9va2luZyB0YWJsZXMNCmBgYA0KDQpEYWxhbSBtYXRlcmkgaW5pIGFrYW4gZGlwZWxhamFyaSA6DQoNCi0gS29uc2VwLWtvbnNlcCB0ZXJwZW50aW5nIGRhbGFtIGFuYWxpc2lzIHN1cnZpdmFsOiBrdXJ2YSBzdXJ2aXZhbCwgcGVueWVuc29yYW4sIGRhbiB1amkgbG9nLXJhbmssDQotIE1lbmdoaXR1bmcgc2VjYXJhIG1hbnVhbCwga2VtdWRpYW4gbWVuZ2tvbXB1dGFzaSBkYW4gbWVuZ2ludGVycHJldGFzaWthbiBrdXJ2YSBzdXJ2aXZhbCwgZGFuDQotIE1lbmd1amkgcGVyYmVkYWFuIGtlbGFuZ3N1bmdhbiBoaWR1cCBhbnRhcmEgZHVhIGF0YXUgbGViaWgga2Vsb21wb2ssIG1pc2FsbnlhIHBlcmVtcHVhbiB2cyBsYWtpLWxha2kNCg0KIyMgTWVuZ2FwYSBoYXJ1cyBtZW1wZWxhamFyaSBhbmFsaXNpcyBzdXJ2aXZhbD8NCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KZCA8LSB0aWJibGUoDQogIHRpbWUgICA9IGMoMSwxLDEsMiwyLDMsNCw1LDcsMTApLCANCiAgc3RhdHVzID0gYygxLDEsMSwxLDAsMSwwLDAsMSwwKQ0KKQ0KDQpkICU+JSBrYWJsZSgpDQpgYGANCg0KUGFkYSBzdWJiYWIgaW5pIGRhbGFtIG1lbmphd2FiIHBlcnRhbnlhYW4gbWVuZ2FwYSBoYXJ1cyBtZW1wZWxhamFyaSBhbmFsaXNpcyBzdXJ2aXZhbCBkYXBhdCBtZW5nZ3VuYWthbiBjb250b2gga2FzdXMgcGVueWludGFzIFRpdGFuaWM6IERpbWFuYSBoYW55YSAxMCBvcmFuZyBkYW4gaGFueWEgMTAgaGFyaSBkaSBsYXV0IHNldGVsYWgga2VjZWxha2FhbiBkYW4gbWVuZ2FuYWxpc2lzbnlhIGRlbmdhbiBtZXRvZGUgc3RhdGlzdGlrIGtsYXNpaywgcmVncmVzaSBsaW5pZXIgZGFuIGxvZ2lzdGlrLiBQcm9ibGVtIHlhbmcgYWthbiBkaWJhaGFzIHlhaXR1IGJlcmFwYSBiYW55YWsgb3JhbmcgZGFuIGJlcmFwYSBsYW1hIGJlcnRhaGFuIGRhbiBiZXJhcGEgYmFueWFrIHlhbmcgbWVuaW5nZ2FsIHBhZGEgaGFyaSB0ZXJ0ZW50dS4gU2VoaW5nZ2EgbWVtaWxpa2kgZHVhIHBhcmFtZXRlciB1dGFtYSBhZGFsYWggKDEpIHdha3R1IChkYWxhbSBoYXJpKSBkYW4gKDIpICJzdGF0dXMga2VoaWR1cGFuIiBvcmFuZywgZGkgbWFuYSAic3RhdHVzID0gMSIgYmVyYXJ0aSBrZW1hdGlhbiBkYW4gInN0YXR1cyA9IDAiIGJlcmFydGkgYnVrYW4ga2VtYXRpYW4uIERlbmdhbiBzdGF0dXMgb3JhbmcgbWFrYSBkYXBhdCBtZW5naGl0dW5nIG9yYW5nIHlhbmcgc2VsYW1hdCBkYW4gdGlkYWsgc2VsYW1hdCBwYWRhIHNldGlhcCBoYXJpLg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KZ2dwbG90KGQsIGFlcyh0aW1lLCBmaWxsID0gZmFjdG9yKHN0YXR1cykpKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNClBhZGEgcGxvdCBkaWF0YXMgYmVsdW0gZGFwYXQgZGlzaW1wdWxrYW4gZGFsYW0gbWVuamF3YWIgcGVybWFzYWxhaCBzZWJlbHVtbnlhIHNlaGluZ2dhIGRhcGF0IGRpbGFrdWthbiBhbmFsaXNpcy4NCg0KMS4g4oCcc3RhdHVzID0gMOKAnSB0aWRhayBzZWxhbHUgYmVyYXJ0aSBiZXJ0YWhhbiBoaWR1cC4gUGVydGFtYSwgb3JhbmcgdGVyc2VidXQgbXVuZ2tpbiB0ZXJiYXdhIG9tYmFrIGRhbiBtZW5naGlsYW5nIHNlaGluZ2dhIHRpZGFrIGRpa2V0YWh1aSBzdGF0dXNueWEuIE11bmdraW4gc3VkYWggbWF0aSwgbXVuZ2tpbiBkaXNlbGFtYXRrYW4gb2xlaCBwZXJhaHUgbmVsYXlhbiBhdGF1IG1hc2loIGhpZHVwIGRpIHN1YXR1IHRlbXBhdCBkaSBsYXV0YW4uIERlbmdhbiBkZW1pa2lhbiAqb3JhbmcgeWFuZyBoaWxhbmcgaW5pIHRpZGFrIGRhcGF0IGRpYW5nZ2FwIG1hdGkgYXRhdSBzZWxhbWF0KiAuIEtlZHVhLCBqaWthIGJlYmVyYXBhIG9yYW5nIGJlcnRhaGFuIDEwIGhhcmksIG1lcmVrYSBtdW5na2luIG1hdGkgcGFkYSBoYXJpIGtlIDExIHNlaGluZ2dhIHdha3R1IG1lbmphZGkgc2FsYWggc2F0dSBmYWt0b3IgcGVybWFzYWxhaGFuLg0KDQoyLiBUaWRhayBtZW1pbGlraSBkYXRhIHVudHVrIHNldGlhcCAxMCBoYXJpIGluaS4gS2VsYW5nc3VuZ2FuIGhpZHVwIHBhZGEgZGF0YSBpbmkganVnYSBkYXBhdCBkaXBlbmdhcnVoaSBvbGVoIGtvbmRpc2kgdHVidWggYXRhdSBwYXNva2FuIG1ha2FuIHVudHVrIGJlcnRhaGFuIGhpZHVwIHlhbmcgdGlkYWsgZGlrZXRhaHVpLiBEZW1pa2lhbiBwdWxhLCBwZW51cnVuYW4gcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCBqdWdhICp0ZXJha3VtdWxhc2kgZGFyaSB3YWt0dSBrZSB3YWt0dSogLCB5YW5nIHRpZGFrIGRhcGF0IGRpdGVudHVrYW4gZGVuZ2FuIHBlbmdoaXR1bmdhbiBzZWRlcmhhbmEgYW50YXJhIG9yYW5nIHlhbmcgc2VsYW1hdCBkZW5nYW4gdGlkYWsgc2VsYW1hdCBwYWRhIGhhcmkgdGVydGVudHUuDQoNCkRlbmdhbiBwZXJtYXNhbGFoYW4gZGlhdGFzLCBkYXBhdCBtZW5lbnR1a2FuIG1ldG9kZSB5YW5nIHRlcGF0Lg0KDQoxLiBNZWxpaGF0IHZhcmlhYmVsIG51bWVyaWsg4oCcd2FrdHXigJ0sIG11bmdraW4gZGFwYXQgdGVyZ29kYSB1bnR1ayBtZW5nZ3VuYWthbiByZWdyZXNpIGxpbmllciB1bnR1ayBtZW1vZGVsa2FuIHdha3R1IGJlcnRhaGFuIGhpZHVwIHVudHVrIGR1YSBrZWxvbXBvayBzdGF0dXMgeWFuZyBiZXJiZWRhLCAwICYgMToNCg0KYGBge3J9DQptIDwtIGxtKHRpbWUgfiBzdGF0dXMsIGQgJT4lIG11dGF0ZShzdGF0dXMgPSBmYWN0b3Ioc3RhdHVzKSkpDQoNCmxpYnJhcnkoZWZmZWN0cykNCnBsb3QoYWxsRWZmZWN0cyhtKSkNCmBgYA0KDQpOYW11biwga2V0aWthIG1lbWJ1YXQgcGxvdCBoYXNpbCBtb2RlbG55YSwgZGFwYXQgZGlzYWRhcmkgYmFod2EgYWRhIHNlc3VhdHUgeWFuZyB0aWRhayBiZXJlcyBkaSBzYW5hLiBTZW11YSBpbmZvcm1hc2kgeWFuZyBkaW1pbGlraSB1bnR1ayBtZW1vZGVsa2FuIHdha3R1IGJlcnRhaGFuIGhpZHVwIGFkYWxhaCBhbmdrYSBub2wgZGFuIHNhdHUuIERhbiB3YWt0dSByYXRhLXJhdGEga2VtYXRpYW4gKHN0YXR1cyA9IDEpIHNlYmVzYXIgMiw1IGhhcmkgbWVsZXdhdGthbiBiYW55YWsgaW5mb3JtYXNpLiBTZWJhZ2FpIGNvbnRvaCwgc2V0ZW5nYWggZGFyaSBvcmFuZy1vcmFuZyAoMyBvcmFuZykgbWVuaW5nZ2FsIHBhZGEgaGFyaSBwZXJ0YW1hISBEYW4gc2VtYWtpbiBqYXVoIG1lbGFuZ2thaCBrZSBkZXBhbiwgc2VtYWtpbiBzZWRpa2l0IG9yYW5nIHlhbmcgbWVuaW5nZ2FsLCB5YW5nIGRhcGF0IGRpbGloYXQgcGFkYSBwbG90IGhpdHVuZ2FuIHBlcnRhbWEgZGkgYXRhcy4gSmFkaSwgd2FrdHUgYmVydGFoYW4gaGlkdXAgdGlkYWsgYmVuYXItYmVuYXIgbGluaWVyIGRhbiB0ZW50dSBzYWphIHRpZGFrIGRhcGF0IGRpZ2FtYmFya2FuIGhhbnlhIGRlbmdhbiBhbmdrYSBub2wgZGFuIHNhdHUhIFNlaGluZ2dhIGRpc2luaSBtb2RlbCBsaW5pZXIgdGFtcGFrbnlhIHRpZGFrIGJlcmd1bmEuDQoNCjIuIEthcmVuYSBkaXNpbmkgbWVtaWxpa2kgYW5na2Egbm9sIGRhbiBzYXR1IHBhZGEga29sb20gc3RhdHVzLCBkYXBhdCBtZW5nZ3VuYWthbiByZWdyZXNpIGxvZ2lzdGlrLCAgVGVydXRhbWEga2FyZW5hIGt1cnZhIHByb2JhYmlsaXRhc255YSB0aWRhayBsaW5pZXIgZGFuIGFrYW4gbWVuYW5na2FwIHRyZW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGRhcmkgd2FrdHUga2Ugd2FrdHUuIA0KDQpgYGB7cn0NCm0gPC0gZ2xtKHN0YXR1cyB+IHRpbWUsIGQsIGZhbWlseSA9IGJpbm9taWFsKQ0KDQpsaWJyYXJ5KHNqUGxvdCkNCnBsb3RfbW9kZWwobSwgdHlwZSA9ICJwcmVkIiwgY2kubHZsID0gTkEpDQpgYGANCg0KU2VrYXJhbmcgZGFwYXQgZGlsaWhhdCBiYWh3YSBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIG5vbi1saW5lYXIsIHlhbmcgbWVydXBha2FuIHBlbmluZ2thdGFuIGJlc2FyIGRpYmFuZGluZ2thbiBkZW5nYW4gcmVncmVzaSBsaW5pZXIuIE5hbXVuLCBwZW5nYW1hdGFuIGtlbGltYSBtZW1pbGlraSBzdGF0dXMgMCBwYWRhIGhhcmkga2UtMi4gSW5pIGJlcmFydGkgYmFod2Egb3JhbmcgdGVyc2VidXQgcGFzdGkgYmVydGFoYW4gaGlkdXAgc2VsYW1hIDIgaGFyaSwgdGV0YXBpIGhpbGFuZyBzZXRlbGFobnlhLiBQcm9iYWJpbGl0YXMgZGFsYW0gcmVncmVzaSBsb2dpc3RpayBha2FuIG1lbmdoaXR1bmcgb3JhbmcgaW5pIHNlYmFnYWkgMTAwJSBzZWxhbWF0IHNldGVsYWggaGFyaSBrZWR1YSBoYW55YSBrYXJlbmEgc3RhdHVzbnlhIHRpZGFrICI9MSIsIHlhbmcgc2FsYWggKGF0YXUgYmlhcyksIGthcmVuYSB0aWRhayBkaWtldGFodWkgYXBha2FoIG9yYW5nIGluaSBzZWxhbWF0LiBEZW5nYW4gZGVtaWtpYW4sIHJlZ3Jlc2kgbG9naXN0aWsgbWVsZWJpaC1sZWJpaGthbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGRhbiBvbGVoIGthcmVuYSBpdHUganVnYSBtZXJ1cGFrYW4gYWxhdCB5YW5nIHRpZGFrIHRlcGF0IHVudHVrIG1lbmdhbmFsaXNpcyBkYXRhIGtlbGFuZ3N1bmdhbiBoaWR1cC4NCg0KSmFkaSB0aWRhayBkYXBhdCBkaWxha3VrYW4gYW5hbGlzaXMgKmRhdGEgU3Vydml2YWwqIGRlbmdhbiBtZXRvZGUga2xhc2lrLiBTZWhpbmdnYSBtZW1idXR1aGthbiBtZXRvZGUgYW5hbGlzaXMgc3Vydml2YWwuDQoNClNlbWVudGFyYSBtb2RlbCByZWdyZXNpIGxpbmllciBtZW5nZ2FtYmFya2FuIHdha3R1LCB0ZXRhcGkgbWVsZXdhdGthbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIG5vbi1saW5pZXIsIHJlZ3Jlc2kgbG9naXN0aWsgbWVuYW5na2FwIHRyZW4gbm9uLWxpbmllciwgdGV0YXBpIG1lbGViaWgtbGViaWhrYW4gcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cC4gU2ViYWxpa255YSwgKmFuYWxpc2lzIHN1cnZpdmFsKiBtZW1lY2Foa2FuIGtlZHVhIG1hc2FsYWggdGVyc2VidXQsIGthcmVuYSBtb2RlbCBpbmkgbWVtb2RlbGthbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIG5vbi1saW5lYXIgZGFyaSB3YWt0dSBrZSB3YWt0dSBzYW1iaWwgbWVtcGVyaGl0dW5na2FuIHN1YmplayBwZW5lbGl0aWFuIHlhbmcgaGlsYW5nLCBiYWlrIHlhbmcgbWVuaW5nZ2FsIG1hdXB1biB5YW5nIHNlbGFtYXQuIA0KDQojIyBLZW1hdGlhbiBidWthbmxhaCBzYXR1LXNhdHVueWEgcGlsaWhhbiEgQXRhdTogIkFwYWthaCB5YW5nIGRpbWFrc3VkIGRlbmdhbiBwZXJpc3Rpd2E/Ig0KDQpBbmFsaXNpcyB3YWt0dSBzdXJ2aXZhbCBkaXBlcmx1a2FuIGRhbGFtIHBlbmVsaXRpYW4gYXBhIHB1biB5YW5nIG1lbnllbGlkaWtpIHdha3R1IHVudHVrIGhhc2lsIHRlcnRlbnR1IHlhbmcgbWVuYXJpay4gUGVuZWxpdGlhbiBrYW5rZXIgZGFsYW0gYmlkYW5nIGtlZG9rdGVyYW4gZGFuIGtlZ2FnYWxhbiBwZXJ0YW1hIG1vYmlsIGRhbGFtIGJpZGFuZyB0ZWtuaWsgKGFuYWxpc2lzIHdha3R1IGtlZ2FnYWxhbikgYWRhbGFoIGNvbnRvaCB5YW5nIGJhaWsuIEhhc2lsIHlhbmcgZGlpbmdpbmthbiBkYXBhdCBiZXJ1cGEga2VtYXRpYW4sIHJlbWlzaSB1bnR1ayBrYW1idWgsIHBlcmtlbWJhbmdhbiwgYXRhdSBrZWdhZ2FsYW4uIFRpdGlrIHdha3R1IHVudHVrIG1lbmNhcGFpIGhhc2lsIHRlcnNlYnV0IHVtdW1ueWEgZGlzZWJ1dCBwZXJpc3Rpd2EuIHNlaGluZ2dhLCB0aWRhayBzZW11YSAiZXZlbnQiIGJlcmFraWJhdCBmYXRhbCAsIHRldGFwaSBrYWRhbmcta2FkYW5nIGJhaGthbiBiaXNhIG1lbmphZGkgaGFzaWwgeWFuZyBtZW5ndW50dW5na2FuIHNlcGVydGkga2VsdWFyIGRhcmkgcnVtYWggc2FraXQuIERhbiBkZW5nYW4gZGVtaWtpYW4sIGFuYWxpc2lzIHN1cnZpdmFsIGp1Z2EgbWVydXBha2FuIGlzdGlsYWggdW11bSwga2FyZW5hIGluaSBidWthbiBoYW55YSB0ZW50YW5nIGtlbGFuZ3N1bmdhbiBoaWR1cC4NCg0KS2VqYWRpYW4sIHNlYmFnYWkgdGl0aWsgd2FrdHUgeWFuZyB0ZXRhcCBkaXBlcmx1a2FuIGthcmVuYSB0aWRhayBkYXBhdCBkaWxha3VrYW4gcGVuZ2FtYXRhbiBhdGF1IGJlcmVrc3BlcmltZW4gc2VsYW1hbnlhLiBKaWthIGRpcGVsYWphcmkga2Fua2VyIHBhcnUtcGFydSwgbWFrYSB0aWRhayBiaXNhIG1lbnVuZ2d1IHNhbXBhaSBwYXNpZW4gbWVuaW5nZ2FsIGthcmVuYSBwZW55ZWJhYiBsYWluLCBtaXNhbG55YSBrYXJlbmEgc3VkYWggdHVhLiBIYW55YSBrZXRpa2EgYmViZXJhcGEgcGFzaWVuIHNlbGFtYXQgZGFyaSBrYW5rZXIsIGF0YXUgYmViZXJhcGEgbW9iaWwgdGlkYWsgcnVzYWsgcGFkYSB3YWt0dSB0ZXJ0ZW50dSAocGVyaXN0aXdhKSwga2l0YSBiaXNhIG1lbmRhcGF0a2FuIHdhd2FzYW4geWFuZyBiZXJoYXJnYS4gTWlzYWxueWEsIGJlcmFwYSBsYW1hIHdha3R1IGRhcmkgYXdhbCBwZW5nb2JhdGFuIGhpbmdnYSBwZXJrZW1iYW5nYW5ueWEsIGF0YXUgYmVyYXBhIHByb2JhYmlsaXRhcyB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBkYXJpIGthbmtlciBwYXJ1LXBhcnUgc2V0ZWxhaCB0ZXBhdCAxIHRhaHVuPyBTZWxhaW4gaXR1LCBoYWwgaW5pIG1lbWJ1a2Ega2VtdW5na2luYW4gdW50dWsgbWVtYmFuZGluZ2thbiB3YWt0dSBrZWxhbmdzdW5nYW4gaGlkdXAgYXRhdSBrZWdhZ2FsYW4gZGkgYW50YXJhIGtlbG9tcG9rIHlhbmcgYmVyYmVkYSwgbWlzYWxueWEga2Fua2VyIHBhcnUtcGFydSBhbnRhcmEgcGVyb2tvayBkYW4gbm9uLXBlcm9rb2ssIGF0YXUgd2FrdHUga2VydXNha2FuIGFudGFyYSBtb2JpbCBKZXJtYW4gZGFuIEtvcmVhLg0KDQoNCipQZW55ZW5zb3JhbioNCg0KU2Vuc29yaW5nIGRpcGVybHVrYW4ga2FyZW5hIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCB5YW5nIHNlYmVuYXJueWEgdGlkYWsgYWthbiBkaWtldGFodWkgb2xlaCBiZWJlcmFwYSBpbmRpdmlkdS4gQWRhIGJhbnlhayBjYXJhIHVudHVrIGtlaGlsYW5nYW4gc3ViamVrIHN0dWRpOg0KDQoxLiBEYXBhdCBrZWhpbGFuZ2FuIHNlc2VvcmFuZyB0YW5wYSBhbGFzYW4sIGtldGlrYSBpdHUgdGlkYWsgbXVuY3VsIGxhZ2kNCg0KMi4gSW5kaXZpZHUgbXVuZ2tpbiBtZW5nYWxhbWkgcGVyaXN0aXdhIGxhaW4sIG1pc2FsbnlhIGtlbWF0aWFuIGF0YXUga2VjZWxha2Fhbg0KDQozLiBCYWhrYW4gcGFzaWVuIHlhbmcgYmVydGFoYW4gaGluZ2dhIGFraGlyIHBlbmVsaXRpYW4gZGFwYXQgZGlwZXJsYWt1a2FuIHNlYmFnYWkgZGlzZW5zb3Iga2FyZW5hIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCB5YW5nIHRpZGFrIGRpa2V0YWh1aSANCg0KU2VtdWEgY29udG9oIGRpIGF0YXMgZGlhbmdnYXAgc2ViYWdhaSBzZW5zb3Jpbmcga2FuYW4ga2FyZW5hIGFyYWhueWEgZGFyaSBraXJpIGtlIGthbmFuIHBhZGEgc3VtYnUgd2FrdHUuIFNlYmFnaWFuIGJlc2FyIGRhdGEga2VsYW5nc3VuZ2FuIGhpZHVwIGRpc2Vuc29yIGRlbmdhbiBiZW5hci4gQWRhIGR1YSBqZW5pcyBzZW5zb3JpbmcgbGFpbm55YS4gU2Vuc29yIGtpcmkgbXVuY3VsIGppa2EgdGlkYWsgdGFodSBkYXJpIG1hbmEgcGVueWFraXQgaXR1IGJlcm11bGEsIHNlZGFuZ2thbiBzZW5zb3IgaW50ZXJ2YWwgdGVyamFkaSBrZXRpa2Egd2FrdHUgcGFzdGkga2VoaWxhbmdhbiBwYXNpZW4gdGlkYWsgZGlrZXRhaHVpLCB0ZXRhcGkgaGFueWEgamVuZGVsYSB3YWt0dS4gU2Vuc29yaW5nIGtpcmkgZGFuIGludGVydmFsIGphcmFuZyB0ZXJqYWRpLCBzdWxpdCBkaWFuYWxpc2lzLCBzZXJpbmdrYWxpIG1lcnVwYWthbiBoYXNpbCBkYXJpIGRlc2FpbiBzdHVkaSB5YW5nIGJ1cnVrLg0KDQojIyBDYXJhIG1lbmdoaXR1bmcga3VydmEgc3Vydml2YWwgS2FwbGFuLU1laWVyICJzZWNhcmEgbWFudWFsIiBsYW5na2FoIGRlbWkgbGFuZ2thaA0KDQpEZW5nYW4gbWVtYmF5YW5na2FuIGhhcmkgeWFuZyBjZXJhaCBkYW4gZGFtYWkgdGVwYXQgc2ViZWx1bSBrZWNlbGFrYWFuIFRpdGFuaWMgdGVyamFkaS4gVGlkYWsgYWRhIHlhbmcgbWVuaW5nZ2FsLCB0ZXRhcGkgc2VtdWEgMTAgb3JhbmcgYmVyaXNpa28gdGluZ2dpIChiYWhheWEpIG1lbmluZ2dhbCwgaGFueWEgc2FqYSBtZXJla2EgYmVsdW0gbWVuZ2V0YWh1aW55YS4gRGFwYXQgbWVuZWJhayBiZXJhcGEgYmFueWFrIG9yYW5nIHlhbmcgbXVuZ2tpbiBha2FuIG1lbmluZ2dhbCBzZWhhcmkgc2ViZWx1bSBrZWNlbGFrYWFuLiBKYXdhYmFubnlhIGFkYWxhaCAtIG11bmdraW4gbm9sLiBTZWNhcmEgaGFyZmlhaCwga2VtdW5na2luYW4ga2VtYXRpYW4gYWRhbGFoIG5vbCwga2FyZW5hIGtpdGEgdGFodSBiYWh3YSBrZWNlbGFrYWFuIHRpZGFrIGFrYW4gdGVyamFkaSBzZWhhcmkgc2ViZWx1bSB0YWJyYWthbiB5YW5nIHNlYmVuYXJueWEuIFVudHVrIG1lbmphd2FiIHBlcnRhbnlhYW4gaW5pIGRlbmdhbiBsZWJpaCB0ZXBhdCwga2l0YSBwZXJsdSBtZW5naW5nYXQgZGVmaW5pc2kgcHJvYmFiaWxpdGFzOiAqUHJvYmFiaWxpdGFzIGFkYWxhaCByYXNpbyBkYXJpIHNlc3VhdHUgeWFuZyB0ZXJqYWRpLCB0ZXJoYWRhcCBzZWdhbGEgc2VzdWF0dSB5YW5nIGRhcGF0IHRlcmphZGkuKiBKYWRpLCBqaWthIHRpZGFrIGFkYSBzZW9yYW5nIHB1biBkYXJpIDEwIG9yYW5nIHlhbmcgbWVuaW5nZ2FsIHNlaGFyaSBzZWJlbHVtIGtlY2VsYWthYW4sIG1ha2EgcHJvYmFiaWxpdGFzIGtlbWF0aWFubnlhIGFkYWxhaCAwJSwgc2VkYW5na2FuIHByb2JhYmlsaXRhcyBzZWxhbWF0IGFkYWxhaCAxMDAlOg0KDQokJCBwcm9iYWJpbGl0eSBcIG9mIFwgZHlpbmcgPSBcZnJhY3swfXsxMH0gPSAwJCQNCg0KJCQgcHJvYmFiaWxpdHkgXCBvZiBcIHN1cnZpdmluZyA9IFxmcmFjezEwfXsxMH0gPSAxICA9IDEwMFwlJCQNCg0KVW50dWsgcmVwcmVzZW50YXNpIHlhbmcgbGViaWggYmFpaywgbWFyaSBraXRhIGxldGFra2FuIHNlbXVhIGFuZ2thIGRhbGFtIHNhdHUgdGFiZWw6DQoNCmBgYHtyfQ0KdHJpYmJsZSgNCiAgfnRpbWVfaW5fZGF5cywgfk5fYXRfcmlzaywgfk5fZGllZCwgflBfZHlpbmcsIH5gUF9zdXJ2aXZpbmdgLA0KICAwLCAxMCwgMCwgIjAvMTAgPSAwIiwgIjEwLzEwID0gMSINCikgJT4lIGthYmxlKCkNCmBgYA0KDQpLZW11ZGlhbiwgcGFkYSBoYXJpIGtlY2VsYWthYW4gLCBkaSBtYW5hIHNlbXVhIDEwIG9yYW5nIHNla2FyYW5nIHRhaHUgYmFod2EgbWVyZWthIGJlcmlzaWtvIHRpbmdnaSBtZW5pbmdnYWwsIDMgZGFyaSBtZXJla2EgYmVuYXItYmVuYXIgbWVuaW5nZ2FsLiBQcm9iYWJpbGl0YXMga2VtYXRpYW4gcGFkYSBoYXJpIHBlcnRhbWEgYWRhbGFoIGtlbXVkaWFuICQzLzEwID0gMC4zIFxhcHByb3ggMzBcJSQgZGFuIGtlbXVuZ2tpbmFuIGJlcnRhaGFuIGhpZHVwIGFkYWxhaCAkNy8xMCA9IDAuNyBcYXBwcm94IDcwXCUkLiBTZWhpbmdnYSBrZWxhbmdzdW5nYW4gaGlkdXAganVnYSBkYXBhdCBkaWhpdHVuZyBkYXJpIGtlbXVuZ2tpbmFuIGtlbWF0aWFuICQxLTAuMyA9IDAuNyQuDQoNCiMjICpQZWx1YW5nIFN1cnZpdmFsKg0KDQpTYXR1IG1vbWVuIHBlbnRpbmcgZGkgc2luaSBhZGFsYWggYmFod2EgKmtlbXVuZ2tpbmFuIHVudHVrIGJlcnRhaGFuIGhpZHVwIGJlcnNpZmF0IGt1bXVsYXRpZiosIHlhbmcgYmVyYXJ0aSAqdGVyYWt1bXVsYXNpKiBkYXJpIGhhcmkga2UgaGFyaS4gQWt1bXVsYXNpIGluaSB0ZXJqYWRpIG1lbGFsdWkgKm1lbmdhbGlrYW4gcHJvYmFiaWxpdGFzIGJhcnUgdW50dWsgYmVydGFoYW4gaGlkdXAgcGFkYSBoYXJpIGtlLTEqICQoMSAtIFxmcmFje2RfaX17bl9pfSkgPSAoMSAtIFxmcmFjezN9ezEwfSkgPSA3MFwlJCBkZW5nYW4gKnByb2JhYmlsaXRhcyBsYW1hKiB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBzZXBhbmphbmcgd2FrdHUgc2ViZWx1bW55YSwgeWFuZyBkYWxhbSBrYXN1cyBrYW1pIGFkYWxhaCBzZWhhcmkgc2ViZWx1bSBrZWNlbGFrYWFuLCBhdGF1IC0gaGFyaSBrZS1ub2wgJFModF97aS0xfSkgPSAxMDBcJSQ6DQoNCiQkIFModF9pKSA9IFModF97aS0xfSkqKDEgLSBcZnJhY3tkX2l9e25faX0pID0gMSAqICgxIC0gXGZyYWN7M317MTB9KSA9IDAuNyAkJA0KDQpEaW1hbmEsDQoNCi0gJFModF97aeKIkjF9KSQgPSBwcm9iYWJpbGl0YXMgdW50dWsgaGlkdXAgZGkgJHRfe2niiJIxfSQNCi0gJG5faSQgPSBqdW1sYWggcGFzaWVuIHlhbmcgbWFzaWggaGlkdXAgc2ViZWx1bSAkdF9pJA0KLSAkZF9pJCA9IEp1bWxhaCBrZWphZGlhbiBzYWF0ICR0X2kkDQotICR0XzAkID0gMCwgJFMoMCkkID0gMQ0KDQpQcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgcGFkYSB3YWt0dSB0ZXJ0ZW50dSwgJFModCkkLCBhZGFsYWggKnN5YXJhdCBrYXJlbmEgb3JhbmcgdGVyc2VidXQgaGFydXMgYmVydGFoYW4gaGlkdXAgc2V0ZWxhaCB3YWt0dSB0ZXJ0ZW50dSosIG1pc2FsbnlhIGhhcmkga2Utbm9sIChpdHVsYWggc3lhcmF0bnlhKSB1bnR1ayB0ZXRhcCBiZXJhZGEgZGFsYW0gZWtzcGVyaW1lbiB1bnR1ayBoYXJpIHBlcnRhbWEuDQoNCmBgYHtyfQ0KdHJpYmJsZSgNCiAgfnRpbWVfaW5fZGF5cywgfk5fYXRfcmlzaywgfk5fZGllZCwgflBfZHlpbmcsIH5gUF9zdXJ2aXZpbmdgLA0KICAwLCAxMCwgMCwgIjAvMTAgPSAwIiwgICAiMTAvMTAgICAgICA9IDEiLA0KICAxLCAxMCwgMywgIjMvMTAgPSAwLjMiLCAiMSAqICg3LzEwKSA9IDAuNyIsDQopICU+JSBrYWJsZSgpDQpgYGANCg0KKlBhZGEgaGFyaSBrZWR1YSogc2VkaWtpdCBsZWJpaCBtZW5hcmlrLCBrYXJlbmEgc2F0dSBvcmFuZyBtZW5pbmdnYWwgZGFuIHNhdHUgb3JhbmcgaGlsYW5nIGJlZ2l0dSBzYWphIChzdGF0dXMgPSAwKS4gT3JhbmcgeWFuZyBoaWxhbmcgaW5pIGtlbXVuZ2tpbmFuIGJlc2FyIHRlcmJhd2Egb21iYWsgZGFuIG11ZGFoLW11ZGFoYW4gYmlzYSBkaXNlbGFtYXRrYW4uIEhhcmFwYW5ueWEgYmVzYXIsIGthcmVuYSBzZW1ha2luIGphdWggb3JhbmcgdGVyc2ViYXIgZGkgbGF1dGFuLCBzZW1ha2luIGJlc2FyIGtlbXVuZ2tpbmFuIHNhbGFoIHNhdHUgZGFyaSBtZXJla2EgYWthbiBkaXRlbXVrYW4gZGFsYW0ga2VhZGFhbiBoaWR1cC4gRGFuIGhhbCBpbmkgYWthbiBtZW1iZXJpIHRhaHUgZHVuaWEgYmFod2EgYWRhIG9yYW5nIGxhaW4geWFuZyBtYXNpaCBiZXJhZGEgZGkgbHVhciBzYW5hLiBKYWRpLCBtZXNraXB1biBvcmFuZyBoaWxhbmcgdGVybGloYXQgYnVydWssIGhhbCBpbmkgYmlzYSBqYWRpIG1lcnVwYWthbiBoYWwgeWFuZyBiYWlrLiBKYWRpLCBraXRhIHRlbnR1IHRpZGFrIGJpc2EgbWVuZ2FuZ2dhcCBvcmFuZyB5YW5nIGhpbGFuZyBzZWJhZ2FpIG9yYW5nIHlhbmcgc3VkYWggbWF0aS4gU2VsYWluIGl0dSwgc2VwZXJ0aSBrYXRhIHBlcGF0YWggSmVybWFuOiAiSGFyYXBhbiBhZGFsYWggeWFuZyB0ZXJha2hpciBtYXRpIi4gDQoNClRldGFwaSBrYXJlbmEga2l0YSBqdWdhIHRpZGFrIHlha2luIGFwYWthaCBvcmFuZyBpbmkgbWFzaWggaGlkdXAsIGtpdGEgdGlkYWsgYmlzYSBtZW5nYXRha2FuIC0gb3JhbmcgdGVyc2VidXQgc2VsYW1hdC4gSGFsIGluaSBtZW5pbWJ1bGthbiBkaWxlbWE6IG1lc2tpcHVuIHRpZGFrIG1lbmluZ2dhbCwgb3JhbmcgdGVyc2VidXQgYnVrYW4gYmFnaWFuIGRhcmkgZWtzcGVyaW1lbiBrYW1pIGxhZ2kgZGFuIGthbWkgaGFydXMgbWVuZ2hhcHVzbnlhIGRhcmkganVtbGFoIG9yYW5nIHlhbmcgYmVyaXNpa28uIEphZGksIHNlbWVudGFyYSAqaGFyaSBrZWR1YSogYWthbiBtZW1pbGlraSA3IG9yYW5nIHlhbmcgYmVyaXNpa28geWFuZyB0ZXJzaXNhIChrYXJlbmEgMyBvcmFuZyB0ZWxhaCBtZW5pbmdnYWwgZGkgaGFyaSBwZXJ0YW1hKSwgKmhhcmkga2V0aWdhKiBha2FuIHRlcnNpc2EgaGFueWEgNSBvcmFuZywga2FyZW5hIDEgb3JhbmcgbWVuaW5nZ2FsIGRhbiBzYXR1IG9yYW5nIG1lbmdoaWxhbmcgKGRpc2Vuc29yKSBkaWJhbmRpbmdrYW4gZGVuZ2FuIGhhcmkga2VkdWEuIFNhbWEgaGFsbnlhIGRlbmdhbiBoYXJpIHBlcnRhbWEsIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgYmVyc2lmYXQga3VtdWxhdGlmIGRhbiBzZWxhbHUgbWVueWVydGFrYW4gcHJvYmFiaWxpdGFzIGhhcmkgc2ViZWx1bW55YS4NCg0KYGBge3J9DQp0cmliYmxlKA0KICB+dGltZV9pbl9kYXlzLCB+Tl9hdF9yaXNrLCB+Tl9kaWVkLCB+UF9keWluZywgfmBQX3N1cnZpdmluZ2AsDQogIDAsIDEwLCAwLCAiMC8xMCA9IDAiLCAgICAiMTAvMTAgICAgICAgPSAxIiwNCiAgMSwgMTAsIDMsICIzLzEwID0gMC4zIiwgICIxICogKDcvMTApICA9IDAuNyIsDQogIDIsIDcsICAxLCAiMS83ICA9IDAuMTQiLCAiMC43ICogKDYvNykgPSAwLjYiLA0KICAzLCA1LCAgMSwgIjEvNSAgPSAwLjIwIiwgIjAuNiAqICg0LzUpID0gMC40OCINCikgJT4lIGthYmxlKCkNCmBgYA0KDQoqUGFkYSBkdWEgaGFyaSBiZXJpa3V0bnlhKiwgZHVhIG9yYW5nIG1lbmdoaWxhbmcsIGphZGkga2l0YSBtZW55ZW5zb3IgbWVyZWthLiBUaWRhayBwZXJsdSBtZW5naGl0dW5nIHNlc3VhdHUgdW50dWsgZGF0YSB5YW5nIGRpc2Vuc29yIGRhbGFtIGFuYWxpc2lzIGtlbGFuZ3N1bmdhbiBoaWR1cCwga2FyZW5hIGtpdGEgdGlkYWsgdGFodSBhcGFrYWggbWVyZWthIHNlbGFtYXQgYXRhdSB0aWRhay4gRGFuIGthcmVuYSBraXRhIHRlcnRhcmlrIHBhZGEga2VsYW5nc3VuZ2FuIGhpZHVwIGF0YXUga2VtYXRpYW4sIHRhYmVsIGFraGlyIGRpIGJhd2FoIGluaSBiZXJpc2kga2FzdXMgeWFuZyAqaGFueWEgbWF0aSouIFBhZGEgKmhhcmkga2UgNiogdGlkYWsgYWRhIHlhbmcgbWF0aSBhdGF1IG1lbmdoaWxhbmcsIG9sZWgga2FyZW5hIGl0dSBrYW1pIGp1Z2EgdGlkYWsgbWVuZ2hpdHVuZyBhcGEgcHVuIHVudHVrIGhhcmkgaXR1LiBPcmFuZyB0ZXJha2hpciBkYWxhbSBla3NwZXJpbWVuIGthbWkgbWVuaW5nZ2FsIHBhZGEgKmhhcmkga2UgNyouIEphZGksICJOX21lbmluZ2dhbCIgYWthbiBtZW5qYWRpIDEsIGRhbiAiTl9iZXJpc2lrbyIgYWthbiBtZW5qYWRpIDIsIGthcmVuYSAxIGRhcmkgNSBvcmFuZyB5YW5nIHRlcnNpc2EgdGVsYWggbWVuaW5nZ2FsIGRhbiAyIG9yYW5nIGRpc2Vuc29yLiBEZW5nYW4gZGVtaWtpYW4sIHRhYmVsIHlhbmcgZGloaXR1bmcgc2VjYXJhICJtYW51YWwiIGFrYW4gdGVybGloYXQgOg0KDQpgYGB7cn0NCnRyaWJibGUoDQogIH50aW1lX2luX2RheXMsIH5OX2F0X3Jpc2ssIH5OX2RpZWQsIH5QX2R5aW5nLCB+YFBfc3Vydml2aW5nYCwNCiAgMCwgMTAsIDAsICIwLzEwID0gMCIsICAgICIxMC8xMCAgICAgICAgPSAxIiwNCiAgMSwgMTAsIDMsICIzLzEwID0gMC4zIiwgICIxICogKDcvMTApICAgPSAwLjciLA0KICAyLCA3LCAgMSwgIjEvNyAgPSAwLjE0IiwgIjAuNyAqICg2LzcpICA9IDAuNiIsDQogIDMsIDUsICAxLCAiMS81ICA9IDAuMjAiLCAiMC42ICogKDQvNSkgID0gMC40OCIsDQogIDcsIDIsICAxLCAiMS8yICA9IDAuNTAiLCAiMC40OCAqICgxLzIpID0gMC4yNCINCikgJT4lIGthYmxlKCkNCmBgYA0KDQoNCk5hbXVuLCBhcGEgeWFuZyBha2FuIHRlcmphZGkgKmppa2Ega2l0YSBtZW5nYWJhaWthbiBwZW55ZW5zb3JhbiogZGFuIGhhbnlhIG1lbmdoaXR1bmcgcHJvYmFiaWxpdGFzIHVudHVrIHRpZGFrIG1hdGk/IERpa2FyZW5ha2FuIDQgb3JhbmcgdGlkYWsgbWF0aSBwYWRhIGhhcmkga2UtNywgcHJvYmFiaWxpdGFzIHVudHVrIGJlcnRhaGFuIGhpZHVwIGFrYW4gbWVuamFkaSAkXGZyYWN7NH17MTB9ID0gNDBcJSQgeWFuZyBoYW1waXIgZHVhIGthbGkgbGlwYXQgbGViaWggdGluZ2dpLCBkYW4gZGVuZ2FuIGRlbWlraWFuIGtpdGEgYWthbiAqbWVsZWJpaGthbiBwcm9iYWJpbGl0YXMgdW50dWsgYmVydGFoYW4gaGlkdXAqLCBkaWJhbmRpbmdrYW4gZGVuZ2FuIHByb2JhYmlsaXRhcyBzZWJlbmFybnlhIHlhaXR1IDAsMjQgeWFuZyBtZW1wZXJoaXR1bmdrYW4gcGVueWVuc29yYW4uDQoNCipTVU1CRVIqDQoNCkhhbnlhIG1lbXBlcmhhdGlrYW4gb3JhbmcgeWFuZyBzZWxhbWF0KiBiYWhrYW4gbWVtaWxpa2kgbmFtYSAtIGJpYXMgcGVueWludGFzLCBkYW4gYWRhIGNlcml0YSBrZWNpbCBkaSBiYWxpa255YS4gU2VsYW1hIFBlcmFuZyBEdW5pYSBLZWR1YSwgYmViZXJhcGEgcGVzYXdhdCBrZW1iYWxpIGRhcmkgbWVkYW4gcGVyYW5nIGRlbmdhbiBiYW55YWsga2VydXNha2FuIGFraWJhdCBwZWx1cnUuIE1lcmVrYSBoYW1waXIgdGlkYWsgYmlzYSB0ZXJiYW5nLCB0YXBpIG1lcmVrYSB0ZXRhcCBrZW1iYWxpLiBKYWRpLCBwaWhhayBtaWxpdGVyIG1lbXV0dXNrYW4gdW50dWsgbWVsaW5kdW5naSBwZXNhd2F0IGRlbmdhbiBsZWJpaCBiYW55YWsgcGVsaW5kdW5nIGRpIGJhZ2lhbiB5YW5nIHBhbGluZyBiYW55YWsgbHViYW5nIHBlbHVydSwgc2VwZXJ0aSBzYXlhcCwgZGFuIG1lbmd1cmFuZ2kgcGVsaW5kdW5nIGRpIGJhZ2lhbiB5YW5nIHRpZGFrIGJlcmx1YmFuZyBwZWx1cnUuIEFuZWhueWEsIHBlcnNlbnRhc2UgcGVzYXdhdCB5YW5nIGtlbWJhbGkgdGlkYWsgbWVuaW5na2F0LiBQYXJhIGluc2lueXVyIGJpbmd1bmchIEhpbmdnYSBzZW9yYW5nIGFobGkgbWF0ZW1hdGlrYSwgQWJyYWhhbSBXYWx0LCB5YW5nIGRpdW5kYW5nIHVudHVrIG1lbWVjYWhrYW4gbWFzYWxhaCBpbmkgYmVya2F0YTogIlBhc2FuZyBsZWJpaCBiYW55YWsgbGFwaXMgYmFqYSBkaSB0ZW1wYXQtdGVtcGF0IHlhbmcgdGlkYWsgbWVtaWxpa2kgbHViYW5nIHBlbHVydSwga2FyZW5hIGppa2EgdGVtcGF0IGluaSBkaXRlbWJhaywgcGVzYXdhdCB0aWRhayBha2FuIGtlbWJhbGkuIiBEYW4ga2V0aWthIHlhbmcgbGFpbiBtZW1pa2lya2FubnlhLCBtZXJla2EgbWVueWFkYXJpIGJhaHdhIHNlbXVhIHBlc2F3YXQgeWFuZyBrZW1iYWxpIHRpZGFrIG1lbWlsaWtpIGx1YmFuZyBwZWx1cnUgZGkga29rcGl0IGF0YXUgbWVzaW4uIEx1YmFuZyBwZWx1cnUgbWVudW5qdWtrYW4gc2VtdWEgdGVtcGF0IGRpIG1hbmEgcGVzYXdhdCBiaXNhIGRpdGVtYmFrIHRhcGkgbWFzaWggYmlzYSBrZW1iYWxpLCBhdGF1IHNlbGFtYXQhIEl0dWxhaCB5YW5nIGRpc2VidXQgZGVuZ2FuIGJpYXMgYmVydGFoYW4gaGlkdXAuIEphZGksIG1lbnVydXQgc2F5YSwgcmVncmVzaSBsb2dpc3RpayBtZW1pbGlraSBzdXJ2aXZvcnNoaXAgYmlhcyBkaWJhbmRpbmdrYW4gZGVuZ2FuIGFuYWxpc2lzIGtldGFoYW5hbiBoaWR1cCBqaWthIGtpdGEgaW5naW4gbWVuZ2FuYWxpc2lzIGRhdGEga2V0YWhhbmFuIGhpZHVwLg0KDQojIyBDYXJhIG1lbmdoaXR1bmcga3VydmEgc3Vydml2YWwgS2FwbGFuLU1laWVyDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpICAjIGRhdGEgd3JhbmdsaW5nIGFuZCB2aXN1YWxpemF0aW9uDQpsaWJyYXJ5KGtuaXRyKSAgICAgICMgYmVhdXRpZnlpbmcgdGFibGVzDQpsaWJyYXJ5KGNhcikgICAgICAgICMgZm9yIGNoZWNraW5nIGFzc3VtcHRpb25zLCBlLmcuIHZpZiBldGMuDQpsaWJyYXJ5KGJyb29tKSAgICAgICMgZm9yIHRpZHkgbW9kZWwgb3V0cHV0DQpsaWJyYXJ5KHNqUGxvdCkgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KHNqbWlzYykgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KGVmZmVjdHMpICAgICMgZm9yIHByb2JhYmlsaXR5IG91dHB1dCBhbmQgcGxvdHMNCmBgYA0KDQpQYWRhIHJlZ3Jlc2kgbG9naXN0aWsgMSBhZGFsYWgga2VsYW5nc3VuZ2FuIGhpZHVwLCBzZWRhbmdrYW4gZGFsYW0gYW5hbGlzaXMga2VsYW5nc3VuZ2FuIGhpZHVwIDEgYWRhbGFoIGtlbWF0aWFuLiBLZWR1YSwgbWVtYmVkYWthbiBrYXN1cyB5YW5nIGRpc2Vuc29yLCBtaXNhbG55YSBkYXBhdCBtZW5hbmRhaW55YSBkZW5nYW4gdGFuZGEgcGx1cyBkaSBkYXRhIGF0YXUgZGkgcGxvdC4gRGF0YSBkaSBiYXdhaCBpbmkgbWVudW5qdWtrYW4gYmFod2Egb3JhbmcgZGlzZW5zb3IgcGFkYSBoYXJpIGtlIDIrLCA0KywgNSsgZGFuIDEwKy4gSW5zdGFsIGRhbiBtdWF0IHN1cnZpdmFscGFrZXQgdW50dWsgZGFwYXQgbWVuZ2Vrc2VrdXNpIGtvZGUgZGkgYmF3YWggaW5pOg0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygic3Vydml2YWwiKQ0KbGlicmFyeShzdXJ2aXZhbCkNCg0KU3Vydih0aW1lID0gZCR0aW1lLCBldmVudCA9IGQkc3RhdHVzKQ0KYGBgDQoNCkZ1bmdzaSBgU3VydmAgbWVueWF0dWthbiBkYXRhICJ3YWt0dSIgZGFuICJzdGF0dXMiIGtlIGRhbGFtIHNhdHUgb2JqZWsgInN1cnZpdmFsIiB0dW5nZ2FsLCB5YW5nIG1lbXVuZ2tpbmthbiB1bnR1ayAibWVtcGVyaGl0dW5na2FuIHBlbmdhbWF0YW4geWFuZyBkaXNlbnNvciIuIE9iamVrIGluaSBrZW11ZGlhbiBkYXBhdCBkaWd1bmFrYW4gdW50dWsgbWVtb2RlbGthbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGRlbmdhbiBmdW5nc2kgYHN1cnZmaXRgLiBLaXRhIG1lbW9kZWxrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGRlbmdhbiBtZW5hbWJhaGthbiAifjEiIHBhZGEgb2JqZWsgdGVyc2VidXQsIGRpIG1hbmEgMSBiZXJhcnRpIHRpZGFrIGFkYSB2YXJpYWJlbCB5YW5nIGRhcGF0IG1lbXBlbmdhcnVoaSBrZWxhbmdzdW5nYW4gaGlkdXAuIE9iamVrIGtlbGFuZ3N1bmdhbiBoaWR1cCBraXRhIGRpIHNpc2kga2lyaSB0aWxkZSBhZGFsYWggdmFyaWFiZWwgcmVzcG9ucyBkYW4gZGkgc2lzaSBrYW5hbiB+ICh0aWxkZSkgYWRhbGFoIHByZWRpa3RvciwgYXRhdSBkYWxhbSBrYXN1cyAiMSIgLSB0aWRhayBhZGEuU2VsYW5qdXRueWEgZGFwYXQgZGlidWF0IG1vZGVsIHN1cnZpdmFsIHBlcnRhbWEgIGRhbiBtZWxpaGF0IGtlbHVhcmFuIG1vZGVsbnlhOg0KDQpgYGB7cn0NCnN1cnZpdmFsX21vZGVsIDwtIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gMSwgZGF0YSA9IGQpDQoNCiMgc21hbGwgc3VtbWFyeQ0Kc3Vydml2YWxfbW9kZWwNCmBgYA0KRGltYW5hIGFrYW4gZGlkYXBhdA0KLSAqbiogLSBqdW1sYWggcGVzZXJ0YSwgDQotICpldmVudCogLSBqdW1sYWgga2VtYXRpYW4sIHlhbmcgc2VjYXJhIHVtdW0gZGlzZWJ1dCAqZXZlbnQqIGthcmVuYSBkYXBhdCBtZW1wZWxhamFyaSBqZW5pcy1qZW5pcyAiKmRlYWQqbGluZXMiIGxhaW5ueWEsIHNlcGVydGkga2FtYnVobnlhIHBlbnlha2l0LCBhdGF1IGtlcnVzYWthbiBwZXJ0YW1hIHBhZGEgbW9iaWwsDQotIHBlcmtpcmFhbiB3YWt0dSBiZXJ0YWhhbiBoaWR1cCAqbWVkaWFuKiwgYnVrYW4gcmF0YS1yYXRhIGthcmVuYSBzaWZhdCBub24tcGFyYW1ldHJpayAoZGlqZWxhc2thbiBuYW50aSkgZGFyaSBhbmFsaXNpcyBrZXRhaGFuYW4gaGlkdXAgZGFuDQotIEludGVydmFsIGtlcGVyY2F5YWFuIDk1JSoqIHVudHVrIHdha3R1IGtldGFoYW5hbiBoaWR1cCBtZWRpYW4NCg0KTGViaWggYmFueWFrIGluZm9ybWFzaSBkYXBhdCBkaW5pbGFpIGRlbmdhbiBmdW5nc2kgYHJpbmdrYXNhbmAsIHlhbmcgbWVtYmVyaWthbiB0YWJlbCB5YW5nIHNhbWEgZGVuZ2FuIHBlcmhpdHVuZyBzZWNhcmEgbWFudWFsIGRpIGF0YXM6DQoNCmBgYHtyfQ0KIyBiaWcgc3VtbWFyeQ0Kc3VtbWFyeShzdXJ2aXZhbF9tb2RlbCkNCmBgYA0KDQpTZWhpbmdnYSBkYXBhdCBkaWxpaGF0IGJhaHdhIHBlcmhpdHVuZ2FuIHNlYmVsdW15YSBiZW5hciBkYW4gdGVsYWggYmVyaGFzaWwgbWVtcGVsYWphcmkgY2FyYSBtZWxha3VrYW4gYW5hbGlzaXMgc3Vydml2YWwuIFNlaGluZ2dhIG11bGFpIHNla2FyYW5nIGRhcGF0IG11bGFpIG1lbmdndW5ha2FuIHBlcmFuZ2thdCBsdW5hay4gUGVyYW5na2F0IGx1bmFrIGluaSBtZW1pbGlraSBiYW55YWsga2V1bnR1bmdhbi4gU2ViYWdhaSBjb250b2gsIGZ1bmdzaSBgc3VtbWFyeWAsIHlhbmcgaGFueWEgbWVuYW1waWxrYW4gaGFzaWwgZGFyaSBrYXN1cyB5YW5nIG1hdGksIGRhcGF0IGRpaXNpIGRlbmdhbiBhcmd1bWVuIHRhbWJhaGFuIGBjZW5zb3JlZCA9IFRSVUVgLCB5YW5nIG1lbmFtcGlsa2FuIHNlbXVhIGthc3VzLCBiYWlrIHlhbmcgbWF0aSBtYXVwdW4geWFuZyBkaXNlbnNvcjoNCg0KYGBge3J9DQpzdW1tYXJ5KHN1cnZpdmFsX21vZGVsLCBjZW5zb3JlZCA9IFQpDQpgYGANCg0KU2VsYW5qdXRueWEgZGFwYXQgbWVuZW50dWthbiBoYXNpbCBkYXJpIGhhcmkgbWFuYSB5YW5nIGluZ2luIGRpbGloYXQgZGVuZ2FuIG1lbmFtYmFoa2FuIGFyZ3VtZW4gYHRpbWVzID0gLi4uYCBrZSBmdW5nc2kgYHN1bW1hcnlgLiBCYWhrYW4gZGFwYXQganVnYSBtZW1pbnRhIGhhcmktaGFyaSB5YW5nIHRpZGFrIHRlcnNlZGlhIGRhdGFueWEsIG1pc2FsbnlhIGhhcmkga2UtOCBhdGF1IGtlLTkgZGFsYW0gY29udG9oIHNlZGVyaGFuYSBraXRhLiBTZWJhZ2FpIGNvbnRvaCwgcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCBzZXRlbGFoIGhhcmkga2UtOCBhZGFsYWggMjQlOg0KDQpgYGB7cn0NCnN1bW1hcnkoc3Vydml2YWxfbW9kZWwsIHRpbWVzID0gYyg4LCA5KSkNCmBgYA0KDQpTZWthcmFuZywga2FyZW5hIGtpdGEgbWVuZ2V0YWh1aSBwcm9iYWJpbGl0YXMgeWFuZyB0ZXBhdCB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBwYWRhICpzZXRpYXAgaGFyaSosIGJhaGthbiBwYWRhIGhhcmktaGFyaSBkaW1hbmEga2l0YSB0aWRhayBtZW1pbGlraSBkYXRhbnlhLCBraXRhIGRhcGF0IG1lbXZpc3VhbGlzYXNpa2FuIGhhc2lsIG1vZGVsLiBJbnN0YWxsIGRhbiBtdWF0IHBha2V0IGBzdXJ2bWluZXJgIHVudHVrIGRhcGF0IG1lbmphbGFua2FuIGtvZGUgZGkgYmF3YWggaW5pOg0KDQpgYGB7ciBldmFsID0gRkFMU0V9DQojIGluc3RhbGwucGFja2FnZXMoInN1cnZtaW5lciIpDQpsaWJyYXJ5KHN1cnZtaW5lcikNCmdnc3VydnBsb3QoDQogIHN1cnZpdmFsX21vZGVsLCANCiAgY29uZi5pbnQgPSBGQUxTRSwgDQogIHN1cnYubWVkaWFuLmxpbmUgPSAiaHYiLA0KICB4bGFiID0gIkRheXMiLCANCiAgeWxhYiA9ICJTdXJ2aXZhbCBwcm9iYWJpbGl0eSIsIA0KICBicmVhay50aW1lLmJ5ID0gMSwNCiAgcmlzay50YWJsZSA9IFQNCikNCmBgYA0KYGBge3IgaW1hZ2UxLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSIiLGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzEwMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm91dHB1dDEucG5nIikNCmBgYA0KDQpEYXJpIG91dHB1dCBkaWF0YXMgZGFwYXQgZGlsaWhhdCBpbnRlcnZhbCBrZXBlcmNheWFhbiAoQ0kpIHVudHVrIGtlbGFuZ3N1bmdhbiBoaWR1cCBzZWhhcmktaGFyaSBhdGF1IGFsdXIgYmVydGFoYW4gaGlkdXAuIENJIGRpdmlzdWFsaXNhc2lrYW4gc2VjYXJhIGRlZmF1bHQsIHRldGFwaSBkYXBhdCBkaWhhcHVzICBqaWthIGRpcGVybHVrYW4gbWVsYWx1aSBjb25mLmludCA9IEZBTFNFX3BlcmludGFoLiBCYXJpcyB0ZXJha2hpciBwYWRhIGtvZGUgZGkgYXRhcyBtZW5hbXBpbGthbiB0YWJlbCDigJxBbmdrYSBiZXJpc2lrb+KAnSwgeWFuZyBkaWhpdHVuZyBzZWNhcmEgbWFudWFsIGRpIGF0YXMuIA0KDQpLdXJ2YSBpbmkgZGlqZWxhc2thbiBzZWNhcmEgaW5kZXBlbmRlbiBvbGVoIGR1YSBpbG11d2FuIGJlcmJlZGEgcGFkYSBzYWF0IGJlcnNhbWFhbi4gRWR3YXJkIEthcGxhbiBkYW4gUGF1bCBNZWllciBrZW11ZGlhbiBtZW5lcmJpdGthbiB0ZW11YW4gbWVyZWthIGJlcnNhbWEgc2ViYWdhaSBlc3RpbWF0b3IgS2FwbGFuLU1laWVyIChLTSkgcGFkYSB0YWh1biAxOTU4IGRhbiBzdXJ2Zml0ZnVuZ3NpIGNvY29rIGRlbmdhbiB0eXBlID0gImthcGxhbi1tZWllciJrdXJ2YSBzZWNhcmEgZGVmYXVsdC4NCg0KU2ViYWdpYW4gYmVzYXIgZGF0YSBrZWxhbmdzdW5nYW4gaGlkdXAgbWVudW5qdWtrYW4gYmFueWFrIHBlcmlzdGl3YSBkaSBhd2FsIGRhbiBqdW1sYWggcGVyaXN0aXdhIHlhbmcgbGViaWggcmVuZGFoIHNlcGFuamFuZyB3YWt0dS4gSGFsIGluaSBtZW1idWF0IGt1cnZhIGtlbGFuZ3N1bmdhbiBoaWR1cCBub24tbGluaWVyIGRhbiBzZWJhZ2lhbiBiZXNhciBkYXRhIGtlbGFuZ3N1bmdhbiBoaWR1cCB0ZXJkaXN0cmlidXNpIG1pcmluZyBhdGF1IHRpZGFrIG5vcm1hbCAodGlkYWsgYmVyYmVudHVrIGxvbmNlbmcpLiBJbmkgYWRhbGFoIGFsYXNhbiBtZW5nYXBhIG1ldG9kZSBLTSBtZW1wZXJraXJha2FuIHdha3R1IGJlcnRhaGFuIGhpZHVwIG1lZGlhbiBkYXJpcGFkYSByYXRhLXJhdGEgc2ViYWdhaSB1a3VyYW4gdGVuZGVuc2kgc2VudHJhbC4gTm9uLWxpbmVhcml0YXMgZGFuICJzdGVwaW5lc3MiIGRhcmkga3VydmEgS00gdGlkYWsgbWVtdW5na2lua2FuIHVudHVrIG1lcmluZ2thcyBkYXRhIG1lbmphZGkgc2F0dSBwYXJhbWV0ZXIgdHVuZ2dhbCAsIG1pc2FsbnlhIGtlbWlyaW5nYW4gLCB5YW5nIG1lbWJ1YXQgbWV0b2RlIEtNIG5vbi1wYXJhbWV0cmlrIC4NCg0KIyMgSW50ZXJwcmV0YXNpIEt1cnZhIEthcGxhbi1NZWllcg0KDQpTdW1idSB4IG1ld2FraWxpIHdha3R1IGRhbGFtIGhhcmksIGRhbiBzdW1idSB5IG1lbnVuanVra2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBhdGF1IHByb3BvcnNpIG9yYW5nIHlhbmcgYmVydGFoYW4gaGlkdXAuIEphZGksIGt1cnZhIGl0dSBzZW5kaXJpIG1lbnVuanVra2FuIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgeWFuZyB0ZXBhdCBkYXJpIHdha3R1IGtlIHdha3R1IC4gUGVudXJ1bmFuIHZlcnRpa2FsIHBhZGEga3VydmEgbWVudW5qdWtrYW4gc2V0aWRha255YSBzYXR1IHBlcmlzdGl3YSAuIEtldGluZ2dpYW4gcGVudXJ1bmFuIHZlcnRpa2FsIG1lbnVuanVra2FuIHBlcnViYWhhbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGt1bXVsYXRpZi4gQmFnaWFuIGhvcml6b250YWwgZGFyaSBrdXJ2YSBtZXdha2lsaSBkdXJhc2kga2VsYW5nc3VuZ2FuIGhpZHVwIHVudHVrIGludGVydmFsIHdha3R1IHRlcnRlbnR1ICwgeWFuZyBkaWFraGlyaSBvbGVoIHBlcmlzdGl3YSBiZXJpa3V0bnlhIChkYW4gcGVudXJ1bmFuIGt1cnZhKS4gS3VydmEgS00gdGVybGloYXQgc2VwZXJ0aSB0YW5nZ2EgYW5laCBkZW5nYW4gYW5hayB0YW5nZ2EgeWFuZyB0aWRhayByYXRhLCBkaSBtYW5hIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBrb25zdGFuIGRpIGFudGFyYSBwZXJpc3Rpd2EsIGRhbiBrYXJlbmFueWEgbWVydXBha2FuIGZ1bmdzaSBsYW5na2FoIHlhbmcgbWVuZ3ViYWggbmlsYWkgaGFueWEgcGFkYSBzYWF0IHNldGlhcCBwZXJpc3Rpd2EuIERlbmdhbiBjYXJhIGluaSBzZXRpYXAgcGFzaWVuIG1lbnl1bWJhbmdrYW4gaW5mb3JtYXNpIGJlcmhhcmdhIHVudHVrIHBlcmhpdHVuZ2FuIHNlbGFtYSBtYXNpaCBoaWR1cC4gT3JhbmcgeWFuZyBkaXNlbnNvciBkaXRhbXBpbGthbiBwZXJzaXMgc2VwZXJ0aSBwYWRhIG9iamVrIGJlcnRhaGFuIGhpZHVwLCBkZW5nYW4gcGx1cyAsIHNlcGVydGkgeWFuZyBkaWxpaGF0IHBhZGEgaGFyaSBrZS0yLiBOYW11biwgc2ViYWdpYW4gYmVzYXIgcGx1cyB0ZXJsaWhhdCBzZXBlcnRpIGt1dHUgdmVydGlrYWwgLCBrYXJlbmEgdGVybGV0YWsgZGkgYmFnaWFuIGhvcml6b250YWwga3VydmEsIHlhaXR1IGhhcmkgNCBkYW4gNSBUYW5kYSBjZW50YW5nIGRpdGFtcGlsa2FuIHNlY2FyYSBkZWZhdWx0LCB0ZXRhcGkgZGFwYXQgZGl0ZWthbiBtZW5nZ3VuYWthbiBhcmd1bWVuIGNlbnNvciA9IEZBTFNFLiBUYWJlbCByaXNpa28gZGkgYmF3YWggcGxvdCBtZW51bmp1a2thbiBqdW1sYWggb3JhbmcgeWFuZyBiZXJpc2lrbyAsIHlhbmcgc2ViZW5hcm55YSBzZW11YSBvcmFuZyB5YW5nIOKAnGJlbmFyLWJlbmFyIGhpZHVw4oCdIGRhbGFtIHBlcmNvYmFhbiB5YW5nIHRpZGFrIG1lbmdhbGFtaSBrZWphZGlhbiBhdGF1IHBlbnllbnNvcmFuIHBhZGEgdGl0aWsgd2FrdHUgdGVydGVudHUuIEdhcmlzIHB1dHVzLXB1dHVzIG1ld2FraWxpIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCByYXRhLXJhdGEgeWFuZyBzZXN1YWkgZGVuZ2FuIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgNTAlIC4gRGFuIGppa2Ega2l0YSBtZW5nYWJhaWthbiBwZW55ZW5zb3JhbiBkYW4gaGFueWEgbWVtcGVya2lyYWthbiBtZWRpYW4gd2FrdHUgKGhhbnlhIHVudHVrIG9yYW5nIG1hdGkpLCBraXRhIGFrYW4gbWVuZGFwYXRrYW4gMSw1IGJ1a2FubnlhIDMsIHlhbmcgYWthbiBtZW5pbmdrYXRrYW4ga2VtdW5na2luYW4gYmVydGFoYW4gaGlkdXAgZGFyaSA0OCUgbWVuamFkaSA3MCUuIFNla2FsaSBsYWdpLCBtZW5nYWJhaWthbiBwZW55ZW5zb3JhbiBha2FuIG1lbmdoYXNpbGthbiBrZW11bmdraW5hbiBiZXJ0YWhhbiBoaWR1cCB5YW5nIHRlcmxhbHUgdGluZ2dpIGthcmVuYSBiaWFzIGtlYmVybGFuZ3N1bmdhbiBoaWR1cC4NCg0KYGBge3J9DQpkICU+JSANCiAgZmlsdGVyKHN0YXR1cyA9PSAxKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fc3Vydml2YWxfd2hpdGhvdXRfY2Vuc29yaW5nID0gbWVkaWFuKHRpbWUpKQ0KYGBgDQoNCiMjIE1lbWJhbmRpbmdrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGtlbG9tcG9rDQoNCioyIGdyb3VwKg0KDQpEZW5nYW4gbWVuZ2d1bmFrYW4gY29ub3RoIGRhdGEgIDEwMCBvcmFuZyBzZXRlbGFoIGtlY2VsYWthYW4gVGl0YW5pYyBhbGloLWFsaWggMTAgZGFuIGxpaGF0IGtlbGFuZ3N1bmdhbiBoaWR1cCBtZXJla2EgbWVuZ2d1bmFrYW4ga3VydmEgS2FwbGFuLU1laWVyLiBBbmdrYS1hbmdrYSBkYWxhbSB0YWJlbCByaXNpa28gc2VtYWtpbiBiZXNhciBkYW4gc2ViYWlrbnlhIGthbWkgbWVuYW1waWxrYW4gcGVyc2VudGFzZSBiZXJpc2lrbyBkYWxhbSB0YW5kYSBrdXJ1bmcgZGkgZGVrYXQgbmlsYWkgYWJzb2x1dC4gQXJndW1lbiByaXNrLnRhYmxlID0gImFic19wY3QiIG1lbWJhbnR1IGRlbmdhbiBpdHUuIENvbnRvaCAiYnVsYXQiIGRhcmkgMTAwIG9yYW5nIG1lbnVuanVrYW4gcGVyc2VudGFzZSB5YW5nIHBlcnNpcyBzYW1hIGRlbmdhbiBhbmdrYSBhYnNvbHV0LCBuYW11biBkZW5nYW4ganVtbGFoICJidWxhdCIgeWFuZyBsZWJpaCBzZWRpa2l0IGF0YXUgYmViZXJhcGEga2Vsb21wb2ssIHBlcnNlbnRhc2UgYWthbiBtZW5qYWRpIHNhbmdhdCBiZXJndW5hLiBSYXRhLXJhdGEgd2FrdHUgYmVydGFoYW4gaGlkdXAgb3Jhbmctb3JhbmcgZGkgbGF1dGFuIGRpbmdpbiBhZGFsYWggc2VraXRhciA3MCBoYXJpIGRhbiBpbnRlcnZhbCBrZXBlcmNheWFhbm55YSB0aWRhayB0ZXJsYWx1IGxlYmFyLg0KDQpgYGB7cn0NCnNldC5zZWVkKDk5OSkgIyBmb3IgcmVwcm9kdWNpYmxlIGV4YW1wbGUNCmxpYnJhcnkocmxhbmcpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpkIDwtIGdnc3RhdHNwbG90OjpUaXRhbmljX2Z1bGwgJT4lIA0KICBtdXRhdGUoc3Vydml2ZWQgPSBpZmVsc2UoU3Vydml2ZWQgPT0gIk5vIiwgMSwgMCksDQogICAgICAgICB0aW1lICAgICA9IHJ1bmlmKG49MjIwMSwgbWluPTEsIG1heD0xMDApKSAlPiUgDQogIHNhbXBsZV9uKDEwMCkgDQoNCm0gPC0gc3VydmZpdChTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IDEsIGRhdGEgPSBkKQ0KDQpnZ3N1cnZwbG90KG0sIA0KICAgICAgICAgICBjb25mLmludCA9IFRSVUUsIA0KICAgICAgICAgICByaXNrLnRhYmxlID0gImFic19wY3QiLCANCiAgICAgICAgICAgc3Vydi5tZWRpYW4ubGluZSA9ICJodiIpDQpgYGANCg0KTWlzYWxueWEsIG1lbWJhbmRpbmdrYW4gcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCBsYWtpLWxha2kgZGVuZ2FuIHBlcmVtcHVhbi4gRGVuZ2FuIG1lbmdnYW50aSBydW11cyBtb2RlbCBkZW5nYW4gbmFtYSB2YXJpYWJlbCBrYXRlZ29yaSB5YW5nIGRpbWluYXRpLCBtaXNhbG55YSBzZXguIFBsb3QgYmVydGFoYW4gaGlkdXAga2VtdWRpYW4gbWVuYW1waWxrYW4ga3VydmEgS2FwbGFuLU1laWVyIHVudHVrIHNldGlhcCBrYXRlZ29yaSB2YXJpYWJlbCB5YW5nIGFkYToNCg0KYGBge3J9DQptIDwtIHN1cnZmaXQoU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBTZXgsIGRhdGEgPSBkKQ0KDQpnZ3N1cnZwbG90KG0sIA0KICAgICAgICAgICBwdmFsID0gVFJVRSwgDQogICAgICAgICAgIGNvbmYuaW50ID0gVFJVRSwgDQogICAgICAgICAgIHJpc2sudGFibGUgPSAiYWJzX3BjdCIsIA0KICAgICAgICAgICBzdXJ2Lm1lZGlhbi5saW5lID0gImh2IikgDQpgYGANCg0KIyMgKipJbnRlcnByZXRhc2kgcGVyYmFuZGluZ2FuIGtlbG9tcG9rIG1lbmdndW5ha2FuIDQgdG9sb2sgdWt1cioqDQoNCjEuICoqUGVyYmFuZGluZ2FuIHZpc3VhbCBrdXJ2YSoqIDogaGFueWEgZGVuZ2FuIG1lbGloYXQgZHVhIGtlbG9tcG9rIHNlaGluZ2dhIGRhcGF0IG1lbmdhdGFrYW4gYXBha2FoIGFkYSBwZXJiZWRhYW4uIE1pc2FsbnlhLCBwbG90IG1lbmd1bmdrYXBrYW4gYmFod2EgcGVyZW1wdWFuIG1lbWlsaWtpIGtlbXVuZ2tpbmFuIGxlYmloIHRpbmdnaSB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBoYW1waXIgc2VwYW5qYW5nIHBlcmlvZGUgd2FrdHUgKHN1bWJ1IHgpLiBOYW11biwgYXBha2FoIHBlcmJlZGFhbiBpbmkgc2lnbmlmaWthbiBzZWNhcmEgc3RhdGlzdGlrIG1lbWVybHVrYW4gdWppIHN0YXRpc3RpayBmb3JtYWwgLiBEZW5nYW4gbWVsaWhhdCBhbmdrYSBrdXJ2YSwgbWlzYWxueWE6IHBhZGEgaGFyaSB5YW5nIGNlcmFoIGRhbiBpbmRhaCBzZWJlbHVtIGhpbXBpdGFuLCBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAga2VkdWEga2Vsb21wb2sgYWRhbGFoIDEsMCAoYXRhdSAxMDAlIHBlbnVtcGFuZyBtYXNpaCBoaWR1cCkuIFBhZGEgaGFyaSBrZSA1MCwga2VtdW5na2luYW4gYmVydGFoYW4gaGlkdXAgYmV0aW5hIGFkYWxhaCBjYS4gMCw3NSAoYXRhdSA3NSUpIGRhbiBoYW55YSBjYS4gMCw2NSAoYXRhdSA2NSUpIHVudHVrIGxha2ktbGFraS4gUGFkYSBoYXJpIGtlIDc1LCBrZWxhbmdzdW5nYW4gaGlkdXAgYWRhbGFoIGNhLiA2MCBkYW4ga2lyYS1raXJhIDMwJSBzZXN1YWkuDQoNCjIuICoqUGVyYmFuZGluZ2FuIGludGVydmFsIGtlcGVyY2F5YWFuIChDSSkqKiA6IENJIHlhbmcgdHVtcGFuZyB0aW5kaWggbWVudW5qdWtrYW4gYmFod2Ega2VsYW5nc3VuZ2FuIGhpZHVwIGphbnRhbiBkYW4gYmV0aW5hIHRpZGFrIHRlcmxhbHUgYmVyYmVkYSBkYW4gYmlzYSBqYWRpIGthcmVuYSBrZWJldHVsYW4gaGluZ2dhIDgwIGhhcmkuIFNldGVsYWggODAgaGFyaSBDSSBiZXJoZW50aSB0dW1wYW5nIHRpbmRpaCB5YW5nIG1lbnVuanVra2FuIHBlcmJlZGFhbiBzaWduaWZpa2FuIGRhbGFtIGJlcnRhaGFuIGhpZHVwIHBhZGEgdGl0aWsgd2FrdHUgdGVydGVudHUsIGthdGFrYW5sYWggOTAgaGFyaS4NCg0KMy4gKipQZXJraXJhYW4gd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIE5pbGFpIFRlbmdhaCoqIG1lbmd1bmdrYXBrYW4gbGViaWggZGFyaSBpbnRlcnZhbCBrZXBlcmNheWFhbi4gV2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIHJhdGEtcmF0YSB1bnR1ayBzZXRpYXAga2Vsb21wb2sgbWV3YWtpbGkgd2FrdHUgZGkgbWFuYSBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGFkYWxhaCA1MCUuIE1pc2FsbnlhIGtlbGFuZ3N1bmdhbiBoaWR1cCByYXRhLXJhdGEgQmV0aW5hIGphdWggbGViaWggdGluZ2dpICg4NyBoYXJpKSBkYXJpcGFkYSBqYW50YW4gKDY1IGhhcmkpLiBQZXJiZWRhYW4gMjMgaGFyaSB5YW5nIGJlZ2l0dSBiZXNhciwga2FyZW5hIHBlcmVtcHVhbiBtZW1pbGlraSAyMyBoYXJpIGxhZ2kgdW50dWsgZGl0ZW11a2FuIG9sZWggYmViZXJhcGEga2FwYWwgcGVuYW5na2FwIGlrYW4uIERpIHNpbmkgc2VrYWxpIGxhZ2ksIGhhbnlhIHRlcyB5YW5nIGRhcGF0IG1lbmdldGFodWkgZGFuIGl0dWxhaCBtZW5nYXBhIHRvbG9rIHVrdXIgdGVyYWtoaXIgdW50dWsgbWVtYmFuZGluZ2thbiBkdWEga2Vsb21wb2sgYWRhbGFoIHAtdmFsdWUgeWFuZyBkaWVzdGltYXNpIG9sZWggdGVzIExvZy1SYW5rIChQZXRvIGV0IGFsLCAxOTc3KSwgeWFuZyBzYW5nYXQgcGVudGluZywgc2VoaW5nZ2EgcGVybHUgYmFiIHRhbWJhaGFuLg0KDQpgYGB7cn0NCm0NCmBgYA0KDQojIyBMb2ctUmFuayB0ZXN0DQoNCjQuIFVqaSBzdGF0aXN0aWsgKm5vbi1wYXJhbWV0cmlrIExvZy1SYW5rKiAoa2FkYW5nLWthZGFuZyBkaXNlYnV0IE1hbnRlbC1IYWVuc3plbCkgbWVtYmFuZGluZ2thbiBtZWRpYW4gd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIGtlbG9tcG9rLiBVamkgTG9nLVJhbmsgbWlyaXAgZGVuZ2FuIHVqaSBXaWxjb3hvbi1SYW5rIG5vbiBwYXJhbWV0cmlrICgxKSwgeWFuZyBqdWdhIG1lbWJhbmRpbmdrYW4gbWVkaWFuIGRlbmdhbiBtZW5nZ3VuYWthbiBwZXJpbmdrYXQgZGFuIGp1Z2EgbWlyaXAgZGVuZ2FuIHVqaSBDaGktc3F1YXJlICgyKSwgZGkgbWFuYSBraXRhIG1lbWJhbmRpbmdrYW4ganVtbGFoIGtlamFkaWFuIHlhbmcgZGlhbWF0aSBkZW5nYW4geWFuZyBkaWhhcmFwa2FuIGRlbmdhbiBtZW5naGl0dW5nIHN0YXRpc3RpayBDaGktc3F1YXJlOg0KDQokJCBYXjIgPSBcc3VtX3tpID0gMX1ee2d9IFxmcmFjeyhPX2kgLSBFX2kpXjJ9e0VfaX0kJA0KDQpKdW1sYWgga2VqYWRpYW4geWFuZyBkaWhhcmFwa2FuIGRpaGl0dW5nIHVudHVrICpzZXRpYXAgdGl0aWsgd2FrdHUgZGFuIHNldGlhcCBrZWxvbXBvayogZGliYW5kaW5na2FuIGRlbmdhbiB0aXRpayB3YWt0dSBzZWJlbHVtbnlhLiBOaWxhaS1uaWxhaSBpbmkga2VtdWRpYW4gZGlqdW1sYWhrYW4gcGFkYSBzZW11YSB0aXRpayB3YWt0dSB1bnR1ayBtZW1iZXJpa2FuIGp1bWxhaCB0b3RhbCBrZWphZGlhbiB5YW5nIGRpaGFyYXBrYW4gcGFkYSBzZXRpYXAga2Vsb21wb2suDQoNClNpZmF0IG5vbi1wYXJhbWV0cmlrIGRhcmkgdGVzIGluaSBtZW1idWF0IHRpZGFrIGFkYSBhc3Vtc2kgdGVudGFuZyBkaXN0cmlidXNpIGtlbGFuZ3N1bmdhbiBoaWR1cC4gSmFkaSwgYXBha2FoIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCBub3JtYWwgKCJsb25jZW5nIG1lbGVuZ2t1bmciKT8gQmlzYSBzYWphLCB0ZXRhcGkgdGlkYWsgaGFydXMgRmFrdGFueWEsIGRhdGEga2VsYW5nc3VuZ2FuIGhpZHVwIHNhbmdhdCBqYXJhbmcgYmVyZGlzdHJpYnVzaSBub3JtYWwsIHRldGFwaSBzZXJpbmcga2FsaSBtaXJpbmcga2FyZW5hIGJpYXNhbnlhIGJhbnlhayBrZWphZGlhbiBhd2FsIGRhbiByZWxhdGlmIHNlZGlraXQga2VqYWRpYW4gYWtoaXIuIA0KDQpIaXBvdGVzaXMgbm9sIGRhcmkgdWppIExvZy1SYW5rIGFkYWxhaCB0aWRhayBhZGEgcGVyYmVkYWFuIGRhbGFtIGtldGFoYW5hbiBoaWR1cCBhbnRhcmEga2VkdWEga2Vsb21wb2suIE5pbGFpIHAtdmFsdWUgc2ViZXNhciAwLDAxMSBtZW11bmdraW5rYW4ga2l0YSB1bnR1ayBtZW5vbGFrIGhpcG90ZXNpcyBub2wgZGFuIG1lbmdpbmRpa2FzaWthbiBhZGFueWEgcGVyYmVkYWFuIHJhdGEtcmF0YSB5YW5nIHNpZ25pZmlrYW4gZGFsYW0gd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIGFudGFyYSBwZXJlbXB1YW4gZGFuIGxha2ktbGFraS4NCg0KVWppIExvZy1SYW5rIHNhbmdhdCBiYW55YWsgZGlndW5ha2FuIHVudHVrIG1lbWJhbmRpbmdrYW4gZHVhIGF0YXUgbGViaWgga3VydmEga2VsYW5nc3VuZ2FuIGhpZHVwLCBzZWhpbmdnYSBoYXJ1cyBiZW5hci1iZW5hciBtZW1iZW5hcmthbiBwZW5nZ3VuYWFuIHVqaSBsYWlubnlhLg0KDQpGdW5nc2kgYHN1cnZkaWZmKClgIG1lbmdoaXR1bmcgdWppIExvZy1SYW5rIGRhbiBtZW5nZW1iYWxpa2FuIGtvbXBvbmVuLWtvbXBvbmVuIGJlcmlrdXQ6DQoNCi0gKkp1bWxhaCogc3ViamVrIGRhbGFtIHNldGlhcCBrZWxvbXBvay4NCi0gSnVtbGFoIGtlamFkaWFuICoqdGVyYW1hdGkgKip0ZXJ0aW1iYW5nICoqZGFsYW0gc2V0aWFwIGtlbG9tcG9rLg0KLSBKdW1sYWgga2VqYWRpYW4gdGVydGltYmFuZyAqIHlhbmcgZGloYXJhcGthbiogZGFsYW0gc2V0aWFwIGtlbG9tcG9rLg0KLSAqU3RhdGlzdGlrIGNoaS1zcXVhcmUqIHVudHVrIHVqaSBrZXNldGFyYWFuDQotIGRhbiAqcC12YWx1ZSogdW50dWsgcGVyYmVkYWFuIGtlbGFuZ3N1bmdhbiBoaWR1cCBkaSBhbnRhcmEga2Vsb21wb2sNCg0KYGBge3J9DQpzdXJ2ZGlmZihTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IFNleCwgZGF0YSA9IGQpDQpgYGANCg0KQXBha2FoIHRlcyBMb2ctUmFuayBzZW1wdXJuYT8gU2F5YW5nbnlhLCB0aWRhay4gU2FsYWggc2F0dSBtYXNhbGFobnlhIGFkYWxhaDogdWppIGluaSAqdGlkYWsgbWVtYmVyaWthbiB1a3VyYW4gZWZlayogeWFuZyBtZW1idWF0IGtpdGEgaGFueWEgbWVtaWxpa2kgcC12YWx1ZSBzZWJhZ2FpIHVrdXJhbiBwZXJiZWRhYW4uIE1hc2FsYWggbGFpbiBkZW5nYW4gdWppIExvZy1SYW5rIChkYW4gbWV0b2RlIEthcGxhbi1NZWllciBzZWNhcmEgdW11bSkgYWRhbGFoIGJhaHdhIHVqaSBpbmkgKnRpZGFrIG1lbmdpemlua2FuIGFkYW55YSBwZXJhbmN1KiwgdWppIGluaSBtZW5nYWJhaWthbiBmYWt0b3IvdmFyaWFiZWwgbGFpbi4gVW50dW5nbnlhLCBraXRhIG1hc2loIGJpc2EgbWVtYmFuZGluZ2thbiBsZWJpaCBkYXJpIGR1YSBrZWxvbXBvayBkZW5nYW4gc2F0dSB2YXJpYWJlbC4NCg0KPiAyIGtlbG9tcG9rIGRhbiBiZWJlcmFwYSB1amkgTG9nLVJhbmsgYmVycGFzYW5nYW4gKHBvc3QtaG9jKQ0KDQpUZXMgTG9nLVJhbmsgZGFwYXQgbWVtYmFuZGluZ2thbiBsZWJpaCBkYXJpIGR1YSBrZWxvbXBvayBkYW4gbWVuZ2F0YWthbiBhcGFrYWggYWRhIHBlcmJlZGFhbiB5YW5nIHNpZ25pZmlrYW4gKHAtdmFsdWUgPDAsMDUpIGRpIGFudGFyYSBrZWxvbXBvay1rZWxvbXBvayBpbmkuIEhhc2lsIHBlbmd1amlhbiB5YW5nIGRpdGFtcGlsa2FuIHBhZGEgdGFiZWwgZGFuIGt1cnZhIEtNIGRpIGJhd2FoIGluaSBtZW51bmp1a2thbiBiYWh3YSB0ZXJkYXBhdCBwZXJiZWRhYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIHlhbmcgc2lnbmlmaWthbiAocC12YWx1ZSA9IDAsMDI0KSBkaSBhbnRhcmEga2Vsb21wb2sgb3JhbmcgcGFkYSBrZWxhcyB0aWtldCB5YW5nIGJlcmJlZGEuIE5hbXVuLCBzZXBlcnRpIGtlYmFueWFrYW4gdGVzIGxhaW5ueWEgKG1pc2FsbnlhIEFOT1ZBKSwgdGlkYWsgZGlzZWJ1dGthbiBkaSBhbnRhcmEga2Vsb21wb2sgbWFuYSB0ZXBhdG55YS4gT2xlaCBrYXJlbmEgaXR1IGRpcGVybHVrYW4gYW5hbGlzaXMgdGFtYmFoYW4geWFuZyBtZW1iYW5kaW5na2FuIHNlY2FyYSBiZXJwYXNhbmdhbiBzZXRpYXAga2Vsb21wb2sgc2F0dSBkZW5nYW4ga2Vsb21wb2sgbGFpbm55YS4gQW5hbGlzaXMgc2VtYWNhbSBpdHUgc2VyaW5nIGRpc2VidXQgcG9zdC1ob2MuDQoNCmBgYHtyfQ0Kc3VydmRpZmYoU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBDbGFzcywgZGF0YSA9IGQpDQpgYGANCg0KYGBge3J9DQptIDwtIHN1cnZmaXQoU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBDbGFzcywgZGF0YSA9IGQpDQoNCmdnc3VydnBsb3QobSwgDQogICAgICAgICAgIHB2YWwgPSBUUlVFLCANCiAgICAgICAgICAgY29uZi5pbnQgPSBGQUxTRSwgDQogICAgICAgICAgIHJpc2sudGFibGUgPSAiYWJzX3BjdCIsIA0KICAgICAgICAgICBzdXJ2Lm1lZGlhbi5saW5lID0gImh2IiwNCiAgICAgICAgICAgbmNlbnNvci5wbG90ID0gVFJVRSwNCiAgICAgICAgICAgYnJlYWsudGltZS5ieSA9IDIwLA0KICAgICAgICAgICByaXNrLnRhYmxlLnkudGV4dC5jb2wgPSBUUlVFLCByaXNrLnRhYmxlLnkudGV4dCA9IEZBTFNFKSANCmBgYA0KDQoNClRpZ2EgYXJndW1lbiBwbG90IHlhbmcgYmVyZ3VuYSBsZWJpaCBsYW5qdXQgeWFuZyBkYXBhdCBtZW1iYW50dSBtZW12aXN1YWxpc2FzaWthbiBkYXRhIGtldGFoYW5hbiBoaWR1cCBkZW5nYW4gbGViaWggYmFpayBhZGFsYWg6DQoNCi0gYGJyZWFrLnRpbWUuYnkgPSAyMGAgbWVtZWNhaCBzdW1idSB4IG1lbmphZGkgaW50ZXJ2YWwgd2FrdHUgeWFuZyBkaWluZ2lua2FuLg0KLSBgcmlzay50YWJsZS55LnRleHQuY29sID0gVFJVRWAgZGFuIGByaXNrLnRhYmxlLnkudGV4dCA9IEZBTFNFYCBtZW1wbG90IGJhdGFuZywgYnVrYW4gbmFtYSBkYWxhbSBhbm90YXNpIHRla3MgbGVnZW5kYSB0YWJlbCByaXNpa28NCi0gYG5jZW5zb3IucGxvdCA9IFRSVUVgIG1lbmFtcGlsa2FuIGp1bWxhaCBzdWJqZWsgeWFuZyBkaXNlbnNvciwgeWFuZyBtZW1iYW50dSB1bnR1ayBtZW1haGFtaSBhcGEgeWFuZyBtZW5qYWRpIHBlbnllYmFiIGFuZ2thIHJpc2lrbyBtZW5qYWRpIGxlYmloIGtlY2lsOiBwZXJpc3Rpd2EgYXRhdSBwZW55ZW5zb3Jhbi4NCg0KIyMgUGVuYWZzaXJhbg0KDQpLZWxhbmdzdW5nYW4gaGlkdXAgcmF0YS1yYXRhIGFkYWxhaCBjYS4gOTAgaGFyaSB1bnR1ayBwZW51bXBhbmcga2VsYXMgMSBkYW4gMiwgNTggaGFyaSB1bnR1ayBrZWxhcyAzIGRhbiA2NSBoYXJpIHVudHVrIGF3YWsgVGl0YW5pYywgbWVudW5qdWtrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIG9yYW5nIGtheWEgeWFuZyBiYWlrLCBkaWJhbmRpbmdrYW4gZGVuZ2FuIHlhbmcgbGFpbi4gRGVuZ2FuIHAtdmFsdWUgeWFuZyByZW5kYWggKHAgPSAwLDAyNCkgbWVudW5qdWtrYW4gYmFod2EgYWRhIHBlcmJlZGFhbiB5YW5nIHNpZ25pZmlrYW4gZGFsYW0ga2VsYW5nc3VuZ2FuIGhpZHVwIGFudGFyIGtlbG9tcG9rIC4gRGkgYW50YXJhbnlhLCBoYW55YSBwb3N0LWhvYyB5YW5nIHRhaHUuIEhhc2lsIGRhcmkgYW5hbGlzaXMgTG9nLVJhbmsgcG9zdC1ob2MgdGVyc2VidXQgZGFwYXQgZGlsYWt1a2FuIGRlbmdhbiBmdW5nc2kgcGFpcndpc2Vfc3VydmRpZmYgZGFyaSBzdXJ2bWluZXIgZGFuIGRpdGFtcGlsa2FuIGRpIGJhd2FoIGluaS4gU2VwZXJ0aSBiaWFzYSwgamlrYSBtZW1pbGlraSBiYW55YWsgcGVyYmFuZGluZ2FuIHNlaGluZ2dhIGJlcmlzaWtvIG1lbWJ1YXQgcGVuZW11YW4geWFuZyBzYWxhaCBhdGF1IG1lbGV3YXRrYW4gcGVuZW11YW4gcGVudGluZy4gSmFkaSwgaGFydXMgbWVueWVzdWFpa2FuIHAtdmFsdWUgdW50dWsgbWVuZ3VyYW5naSBrZW11bmdraW5hbiB0ZXJqYWRpbnlhIGtlc2FsYWhhbi4gDQoNCmBgYHtyfQ0KcGFpcndpc2Vfc3VydmRpZmYoDQogIGZvcm11bGEgPSBTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IENsYXNzLCBkYXRhID0gZCwgcC5hZGp1c3QubWV0aG9kID0gImZkciINCiAgKQ0KYGBgDQoNCkhhc2lsIGFuYWxpc2lzIHBvc3QtaG9jIG1lbmd1bmdrYXBrYW4gYmFod2Ega2VsYW5nc3VuZ2FuIGhpZHVwIGtlbGFzIDEgc2VjYXJhIHNpZ25pZmlrYW4gbGViaWggdGluZ2dpIGRpYmFuZGluZ2thbiBkZW5nYW4ga2VsYXMgMyBkYW4gQXdhay4gRGFuIHRlcmxlcGFzIGRhcmkga2VueWF0YWFuIGJhaHdhIHJhdGEtcmF0YSBrZWxhbmdzdW5nYW4gaGlkdXAgcGVudW1wYW5nIGtlbGFzIDIgc2FuZ2F0IG1pcmlwIGRlbmdhbiBrZWxhcyAxLCBpbnRlcnZhbCBrZXBlcmNheWFhbiBrZWxhbmdzdW5nYW4gaGlkdXAgaW5pIHNhbmdhdCBsZWJhciBkYW4gYmFueWFrIHR1bXBhbmcgdGluZGloIGRlbmdhbiBrZWxvbXBvayBsYWluICh0aWRhayBkaXR1bmp1a2thbiB1bnR1ayBtZW5naGluZGFyaSBrZWthY2F1YW4pLiBJdHVsYWggbWVuZ2FwYSBwZW51bXBhbmcga2VsYXMgMiB0aWRhayB1bXVtbnlhIG1lbWlsaWtpIHdha3R1IGJlcnRhaGFuIGhpZHVwIHlhbmcgbGViaWggdGluZ2dpIHNlY2FyYSBzaWduaWZpa2FuIG1lc2tpcHVuIG1lbWlsaWtpIHdha3R1IGJlcnRhaGFuIGhpZHVwIHlhbmcgamF1aCBsZWJpaCB0aW5nZ2kuDQoNCiMjIE11bHRpcGxlIGt1cnZhIFN1cnZpdmFsDQoNClNlcGVydGkgZGlzZWJ1dGthbiBkaSBhdGFzLCB1amkgTG9nLVJhbmsgdGlkYWsgZGFwYXQgZGl0ZXJhcGthbiBwYWRhIGJlYmVyYXBhIHZhcmlhYmVsLiBOYW11biBtYXNpaCBkYXBhdCBtZW1wbG90IGt1cnZhIGtlbGFuZ3N1bmdhbiBoaWR1cCBkYXJpIGJlYmVyYXBhIHZhcmlhYmVsIHVudHVrIG1lbmRhcGF0a2FuIGludHVpc2kgdW50dWsgZGF0YSBpbmkuIE1ldG9kZSBsZWJpaCBsYW5qdXQsIG1pc2FsbnlhIG1vZGVsIENveCwgZGFwYXQgbWVuZ2VzdGltYXNpIHBlcmJlZGFhbiBkaSBhbnRhcmEgYmViZXJhcGEgdmFyaWFiZWwsIHRldGFwaSBtZXRvZGUgaW5pIGxlYmloIGtvbXBsZWtzIGRhcmlwYWRhIG1ldG9kZSBLTSBkYW4gZGVuZ2FuIGRlbWlraWFuIGFrYW4gZGliYWhhcyBkaSBwb3N0aW5nIG1lbmRhdGFuZy4NCg0KYGBge3J9DQptMiA8LSBzdXJ2Zml0KCBTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IFNleCArIENsYXNzLCBkYXRhID0gZCApDQoNCmdnc3VydiA8LSBnZ3N1cnZwbG90KG0yLCBjb25mLmludCA9IFRSVUUpDQogICANCmdnc3VydiRwbG90ICt0aGVtZV9idygpICsgDQogIHRoZW1lIChsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSsNCiAgZmFjZXRfZ3JpZChTZXggfiAuKQ0KYGBgDQoNCkludHVpc2kgeWFuZyBkYXBhdCBraXRhIHBlcm9sZWggZGFyaSBwbG90IGRpIGF0YXMgYWRhbGFoIGJhaHdhIHdhbml0YSBrYXlhIChrZWxhcyB0aWtldCAxIGRhbiAyKSBkYW4gKGhhbnlhIDIpIHdhbml0YSBkYXJpIGtydSBrYXBhbCBtZW1pbGlraSBwcm9iYWJpbGl0YXMgMTAwJSB1bnR1ayBiZXJ0YWhhbiBoaWR1cCwgc2VtZW50YXJhIHdhbml0YSBtdXJuaSBkaSBrZWxhcyAzIGFrYW4gbWF0aSBkZW5nYW4ga2VwYXN0aWFuIHlhbmcgc2FtYSBkZW5nYW4gcHJpYS4gQ0kgeWFuZyBzYW5nYXQgdHVtcGFuZyB0aW5kaWggZGFyaSBrZWxhbmdzdW5nYW4gaGlkdXAgcHJpYSBtZW51bmp1a2thbiBiYWh3YSBzZW11YSBwcmlhIHBhZGEgYWtoaXJueWEgYWthbiBtYXRpIHNldGVsYWgga2VjZWxha2FhbiBUaXRhbmljLg0KDQojIyBLZXNpbXB1bGFuDQoNCkFuYWxpc2lzIGtldGFoYW5hbiBoaWR1cCBtZW55ZWxpZGlraSAqd2FrdHUgeWFuZyBkaWJ1dHVoa2FuIHVudHVrIHN1YXR1IHBlcmlzdGl3YSB5YW5nIG1lbmFyaWsqIHVudHVrIHRlcmphZGkuIFNlYmFnaWFuIGJlc2FyIGFuYWxpc2lzIGtldGFoYW5hbiBoaWR1cCB1bml2YXJpYXQgKHZhcmlhYmVsIHR1bmdnYWwpIG1lbmdndW5ha2FuICpwbG90IEthcGxhbi1NZWllciogdW50dWsgbWVtdmlzdWFsaXNhc2lrYW4ga3VydmEga2V0YWhhbmFuIGhpZHVwIGRhbiAqVWppIExvZy1SYW5rKiB1bnR1ayBtZW1iYW5kaW5na2FuIGt1cnZhIGtldGFoYW5hbiBoaWR1cCBkdWEgYXRhdSBsZWJpaCBrZWxvbXBvay4NCg0KLSBLZXVudHVuZ2FuDQoNCjEuIEtldW50dW5nYW4ga3J1c2lhbCBrdXJ2YSBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgdnMuIGt1cnZhIHJlZ3Jlc2kgbG9naXN0aWsgbWVtcGVyaGl0dW5na2FuIGRhdGEgeWFuZyBkaXNlbnNvciwgeWFuZyB0aWRhayBtYXRpLCBhdGF1IGhpZHVwLiBSZWdyZXNpIGxvZ2lzdGlrIG1lbXBlcmxha3VrYW4gc2VtdWEgb3JhbmcgeWFuZyB0aWRhayBtYXRpIHNlYmFnYWkgb3JhbmcgeWFuZyBzZWxhbWF0LCBpdHUgc2FsYWgsIGhhbnlhIGthcmVuYSBraXRhIHRpZGFrIG1lbmdldGFodWkgc3RhdHVzIGtlbGFuZ3N1bmdhbiBoaWR1cCBvcmFuZyB5YW5nIHRpZGFrIHRlcmphd2FiLiBQYXNpZW4gbWVuaW5nZ2Fsa2FuIHN0dWRpIGthcmVuYSBkdWEgYWxhc2FuIHV0YW1hLCBtZXJla2EgbWVyYXNhIHNhbmdhdCBidXJ1aywgc2VoaW5nZ2EgbWVyZWthIHRpZGFrIGxhZ2kgcGVkdWxpIGRlbmdhbiBla3NwZXJpbWVuICwgYXRhdSBtZXJla2EgbWVyYXNhIGphdWggbGViaWggYmFpayBkYW4gbWVsdXBha2FuIHN0dWRpLiBCZWJlcmFwYSBwYXNpZW4gbXVuZ2tpbiBoYW55YSBwaW5kYWgga2Uga290YSBsYWluIHRhbnBhIGJlcmthdGEgYXBhLWFwYS4gTWVuZ2hpdHVuZyBzZW11YW55YSBzZWJhZ2FpIHNlbGFtYXQsIHNlcGVydGkgaGFsbnlhIHJlZ3Jlc2kgbG9naXN0aWssIGFrYW4gbWVsZWJpaC1sZWJpaGthbiBrZW11bmdraW5hbiBiZXJ0YWhhbiBoaWR1cCAoc3Vydml2b3JzaGlwIGJpYXMpIGRhbiBtZXJlbWVoa2FuIGJhaGF5YSBrZW1hdGlhbi4gT2xlaCBrYXJlbmEgaXR1LCBhbmFsaXNpcyBrZWxhbmdzdW5nYW4gaGlkdXAgbGViaWggdGVwYXQgZGliYW5kaW5na2FuIGRlbmdhbiByZWdyZXNpIGxvZ2lzdGlrLCBzZW1lbnRhcmEgaXR1IG1hc2loIG1lbmFuZ2thcCB0cmVuIHByb2JhYmlsaXRhcyBub24tbGluaWVyLg0KDQoyLiBLZXVuZ2d1bGFuIGxhaW5ueWEgYWRhbGFoIHNpZmF0IG5vbnBhcmFtZXRyaWsgZGFyaSBtZXRvZGUgS2FwbGFuLU1laWVyLCB5YWl0dSB0aWRhayBtZW1pbGlraSB0ZXJsYWx1IGJhbnlhayBhc3Vtc2kuIFNlYmVuYXJueWEgc2F0dS1zYXR1bnlhIGFzdW1zaSBwZW50aW5nIGFkYWxhaCBiYWh3YSBwZW55ZW5zb3JhbiBoYXJ1cyBiZXJzaWZhdCBub24taW5mb3JtYXRpZiAuIE1lbmdhcGE/IExlYmloIGJhbnlhayBpbmZvcm1hc2kgc2VsYWx1IGxlYmloIGJhaWssIGJ1a2FuPyBZYSEgVGFwaSBqaWthIGtpdGEgdGFodSBtZW5nYXBhIG9yYW5nIG1lbmluZ2dhbGthbiBwZW5lbGl0aWFuLCBraXRhIGJpc2EgbWVuZ2d1bmFrYW4gaW5mb3JtYXNpIGluaSBzZWJhZ2FpIHZhcmlhYmVsIGJhcnUgZGFuIG1lbXBlbGFqYXJpIHBlbmdhcnVobnlhIHRlcmhhZGFwIGtlbGFuZ3N1bmdhbiBoaWR1cC4gTWV0b2RlIEtNIGFrYW4gbWVuamFkaSB0aWRhayB0ZXBhdCwga2FyZW5hIGFrYW4gbWVsZXdhdGthbiBpbmZvcm1hc2kgaW5pLiBOYW11biwgc2VyaW5na2FsaSB0aWRhayB0YWh1ICh0aWRhayBhZGEgaW5mbykgbWVuZ2FwYSBvcmFuZyBrZWx1YXIgKGRpc2Vuc29yKS4gRGFuIGRhbGFtIGhhbCBpbmkgbWV0b2RlIEtNIG1lbWVyYXMgaW5mZXJlbnNpIHBhbGluZyBiYW55YWsgZGFyaSBkYXRhIG5vbi1pbmZvcm1hdGlmIHRlcnNlYnV0Lg0KDQotIEtlcnVnaWFuDQoNCjEuICJLdXJ2YSIgS2FwbGFuLU1laWVyIHNlYmVuYXJueWEgdGlkYWsgdGVybGloYXQgc2VwZXJ0aSBrdXJ2YS4gQmVybGF3YW5hbiBkZW5nYW4gcmVncmVzaSBsb2dpc3RpayBtZXRvZGUgS2FwbGFuLU1laWVyIHRpZGFrIGRhcGF0IGRpZ2FtYmFya2FuIHNlYmFnYWkgZnVuZ3NpIGhhbHVzIChrdXJ2YSkgZGVuZ2FuIGJlYmVyYXBhIHBhcmFtZXRlciwgbWlzYWxueWEga2VtaXJpbmdhbiBhdGF1IHJhc2lvIG9kZHMgLiBJdHUgc2ViYWJueWEgIG1lbWJ1dHVoa2FuIHRhYmVsIGhhc2lsIGJvZG9oIGF0YXUgZ3JhZmlrLg0KDQoyLiBNZXRvZGUgS2FwbGFuLU1laWVyIHRpZGFrIGRhcGF0IG1lbW9kZWxrYW4gdmFyaWFiZWwgbnVtZXJpayAsIHRldGFwaSBoYW55YSBrYXRlZ29yaWthbC4NCg0KMy4gTWV0b2RlIEthcGxhbi1NZWllciB0aWRhayBkYXBhdCBtZW55ZXJ0YWthbiBiYW55YWsgdmFyaWFiZWwgcGVuamVsYXMgLiBJdHUgYnVydWssIGthcmVuYSBtZW1iYW5kaW5na2FuIGtlbG9tcG9rIGRhbGFtIGhhbCBiZXJ0YWhhbiBoaWR1cCBtdW5na2luIG1lbGV3YXRrYW4gZWZlayBmYWt0b3IgbGFpbiwgeWFuZyBkaWtlbmFsIHNlYmFnYWkga292YXJpYXQgYXRhdSBwZXJhbmN1LCB5YW5nIGJlcnBvdGVuc2kgbWVtZW5nYXJ1aGkgd2FrdHUgYmVydGFoYW4gaGlkdXAga2Vsb21wb2sgdGVydGVudHUuDQoNClNhcmFuDQoNCjEuIFNlbGFsdSBtZW5hbXBpbGthbiBrZXRpZGFrcGFzdGlhbiBzdGF0aXN0aWsgZGVuZ2FuIG1lbWFzdWtrYW4gOTUlIENJIGF0YXUvZGFuIG5pbGFpIHAgZGFyaSB1amkgTG9nLVJhbmsuIE1lbmFtcGlsa2FuIENJIHBhZGEgYmViZXJhcGEgdGl0aWsgd2FrdHUgcGVudGluZyBwYWRhIHBsb3QgdW50dWsgc2V0aWFwIGtlbG9tcG9rIHBlcmxha3VhbiB0ZXJrYWRhbmcgbGViaWggamVsYXMgZGFyaXBhZGEgbWVuYW1waWxrYW5ueWEgdW50dWsgc2VtdWEgdGl0aWsgd2FrdHUuIENJIHlhbmcgdGlkYWsgdHVtcGFuZyB0aW5kaWggbWVudW5qdWtrYW4gcGVyYmVkYWFuIHlhbmcgc2lnbmlmaWthbiBhbnRhciBrZWxvbXBvay4NCg0KMi4gTWVtcGVydGltYmFuZ2thbiB1bnR1ayBtZW1vdG9uZyBzdW1idSB4IC4ga2FyZW5hIG1hdGEgc2VjYXJhIGFsYW1pIHRlcnRhcmlrIGtlIGJhZ2lhbiBrYW5hbiBwbG90LCBkaSBtYW5hIHdha3R1IGJlcmFraGlyLiBOYW11biwgYWtoaXIgcGxvdCBiZXJpc2kgcGFsaW5nIHNlZGlraXQgaW5mb3JtYXNpIGRhbiBrZXRpZGFrcGFzdGlhbiB0ZXJiZXNhciBrYXJlbmEgaGFueWEgc2VkaWtpdCBwZXNlcnRhIHlhbmcgdGVyc2lzYS4gU2ViZXJhcGEgamF1aCB3YWt0dSB1bnR1ayBtZW1wZXJwYW5qYW5nIHBsb3Q/IFRlcnNlcmFoIGthbXUuDQoNCjMuIFNlbGFsdSBtZW5hbXBpbGthbiB0YWJlbCByaXNpa28geWFuZyBtZW51bmp1a2thbiBqdW1sYWggcGFzaWVuIGJlYmFzIGtlamFkaWFuIGRhbiBtYXNpaCBkYWxhbSB0aW5kYWsgbGFuanV0IGRpIHNldGlhcCBrZWxvbXBvayBwZXJsYWt1YW4gcGFkYSB0aXRpayB3YWt0dSB5YW5nIHJlbGV2YW4uDQoNCiMgU3Vydml2YWwgYW5hbHlzaXMgMjogUGFyYW1ldHJpYyBTdXJ2aXZhbCBNb2RlbHMNCg0KTWV0b2RlIEthcGxhbi1NZWllciAoS00pIG5vbi1wYXJhbWV0cmlrIHRpZGFrIGRhcGF0IG1lbmdnYW1iYXJrYW4gcHJvYmFiaWxpdGFzIGJlcnRhaGFuIGhpZHVwIGRlbmdhbiBmdW5nc2kgeWFuZyBoYWx1cywgeWFuZyBiZXJhcnRpIHRpZGFrIGRhcGF0IG1lbXByZWRpa3NpIGFwYSBwdW4uIE1vZGVsIHBhcmFtZXRyaWsgKG1pcy4gRWtzcG9uZW5zaWFsLCBXZWlidWxsLCBkbGwuKSBTZWxhaW4gaXR1LCBqaWthIG1vZGVsIHBhcmFtZXRyaWsgc2VzdWFpLCBtb2RlbCB0ZXJzZWJ1dCBsZWJpaCB0ZXBhdCwgbGViaWggZWZla3RpZiwgZGFuIGxlYmloIGluZm9ybWF0aWYgZGFyaXBhZGEgS00gYXRhdSBDb3guIE5hbXVuIHNheWFuZ255YSwgbGFuZ2thaCBpbmkgc2VyaW5nIGRpdGluZ2dhbGthbiBrYXJlbmEgcGVuZ2d1bmFhbiBtb2RlbCBwYXJhbWV0cmlrIGJlbGFrYW5nLiBEYWxhbSBwb3N0aW5nIGluaSBha2FuIG1lbmNvYmEgdW50dWsgbWVudXR1cCBjZWxhaCBpbmkuDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpICAjIGRhdGEgd3JhbmdsaW5nIGFuZCB2aXN1YWxpemF0aW9uDQpsaWJyYXJ5KHNqUGxvdCkgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KGVmZmVjdHMpICAgICMgZm9yIHByb2JhYmlsaXR5IG91dHB1dCBhbmQgcGxvdHMNCmxpYnJhcnkoc3Vydml2YWwpICAgIyBmb3IgY29yZSBzdXJ2aXZhbCBhbmFseXNpcyByb3V0aW5lcw0KbGlicmFyeShzdXJ2bWluZXIpICAjIGZvciBkcmF3aW5nIHN1cnZpdmFsIGN1cnZlcw0KbGlicmFyeShmbGV4c3VydikgICAjIGZvciBQYXJhbWV0cmljIFN1cnZpdmFsIE1vZGVsbGluZw0KbGlicmFyeShrbml0cikgICAgICAjIGZvciBhIHdvbmRlcmZ1bC1sb29raW5nIHRhYmxlcyANCmBgYA0KIyMgTWVuZ2FwYSBraXRhIG1lbWJ1dHVoa2FuIG1vZGVsIGtlbGFuZ3N1bmdhbiBoaWR1cCBwYXJhbWV0cmlrDQoNCmBgYHtyfQ0KZDIgPC0gdGliYmxlKA0KICB0aW1lICAgPSBjKDEsMSwxLDIsMiwzLDQsNSw3LDEwKSwgDQogIHN0YXR1cyA9IGMoMSwxLDEsMSwwLDEsMCwwLDEsMCkNCikNCm0gPC0gc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiAxLCBkYXRhID0gZDIpDQpnZ3N1cnZwbG90KA0KICBtLCANCiAgY29uZi5pbnQgPSBGQUxTRSwgDQogIHN1cnYubWVkaWFuLmxpbmUgPSAiaHYiLA0KICB4bGFiID0gIkRheXMiLCANCiAgeWxhYiA9ICJTdXJ2aXZhbCBwcm9iYWJpbGl0eSIsIA0KICBicmVhay50aW1lLmJ5ID0gMSwNCiAgcmlzay50YWJsZSA9IEYNCikNCmBgYA0KDQpLZXJ1Z2lhbiB1dGFtYSBkYXJpICoqbWV0b2RlIG5vbi1wYXJhbWV0cmlrIEthcGxhbi1NZWllciAoS00pKiogeWFuZyBkaXR1bmp1a2thbiBwYWRhIGdhbWJhciBkaSBhdGFzIGFkYWxhaCB0aWRhayBkYXBhdCBkaWplbGFza2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBkZW5nYW4gZnVuZ3NpIHlhbmcgaGFsdXMsIHlhbmcgYXJ0aW55YSB0aWRhayBkYXBhdCBtZW1wcmVkaWtzaSBhcGFwdW4uIE1vZGVsIHBhcmFtZXRyaWsgKHNlcGVydGkgRWtzcG9uZW5zaWFsLCBXZWlidWxsLCBkbGwuKSBTZWxhaW4gaXR1LCAqKm1vZGVsIHBhcmFtZXRyaWsqKiBhZGFsYWggbGFuZ2thaCBsb2dpcyBkYWxhbSBwZXJqYWxhbmFuIGRhcmkgS00ga2UgbW9kZWwgQ294IHNlbWktcGFyYW1ldHJpayAsIGthcmVuYSBtZXJla2EgZGVuZ2FuIGluZGFoIG1lbmdodWJ1bmdrYW4gdGl0aWstdGl0aWsgYW50YXJhIG1vZGVsIEtNIGRhbiBDb3ggZGFuIGRlbmdhbiBkZW1pa2lhbiBzYW5nYXQgbWVuaW5na2F0a2FuIHBlbWFoYW1hbiB0ZW50YW5nIGFuYWxpc2lzIGtlbGFuZ3N1bmdhbiBoaWR1cC4gU2VsYWluIGl0dSwgamlrYSAqKm1vZGVsIHBhcmFtZXRyaWsgc2VzdWFpLCBtb2RlbCB0ZXJzZWJ1dCBsZWJpaCB0ZXBhdCwgbGViaWggZWZla3RpZiwgZGFuIGxlYmloIGluZm9ybWF0aWYqKiBkYXJpIEtNIGF0YXUgQ294LiBOYW11biBzYXlhbmdueWEsIGxhbmdrYWggaW5pIHNlcmluZyBkaXRpbmdnYWxrYW4ga2FyZW5hIHBlbmdndW5hYW4gbW9kZWwgcGFyYW1ldHJpayBiZWxha2FuZy4gDQoNCiMjIEFwYWthaCBXYWt0dSBpdHUgVmFyaWFiZWwgYXRhdSBLb25zdGFudGE/DQoNCktlbWF0aWFuIGRhcGF0IGRpZ2FtYmFya2FuIGRlbmdhbiBkdWEgaGFsOiBwZXJpc3Rpd2Ega2VtYXRpYW4gaXR1IHNlbmRpcmkgZGFuIHRpdGlrIHdha3R1IHRlcnRlbnR1IHNhYXQga2VtYXRpYW4gdGVyamFkaS4gRHVhIGhhbCBpbmkgc2VsYWx1IG1lbmdnYW1iYXJrYW4gc2F0dSBwZXJpc3Rpd2EsIGthcmVuYSBzYXR1IGhhbnlhIG1hdGkgc2VrYWxpLiBEZW5nYW4gZGVtaWtpYW4sIHdha3R1IGtlbWF0aWFuIGFrYW4gYmVydmFyaWFzaSBkYW4ganVtbGFoIGtlbWF0aWFuIGFrYW4gYmVydGFtYmFoIHNlaXJpbmcgd2FrdHUsIHlhbmcgYWthbiBtZW5qYWRpa2FuIHdha3R1IGl0dSBzZW5kaXJpIHNlYmFnYWkgdmFyaWFiZWwgLiBCZWdpdHVsYWggYmViZXJhcGEgcGVyaXN0aXdhIGtlbWF0aWFuIHBhZGEgdGl0aWsgd2FrdHUgeWFuZyBiZXJiZWRhIG1lbXVuZ2tpbmthbiB1bnR1ayBtZW5ndW5na2Fwa2FuIGtlbWF0aWFuIGRhbGFtIGR1YSBjYXJhOg0KDQoxLiBNZWxhbHVpIHNlanVtbGFoIGtlamFkaWFuIHlhbmcgYmVyYmVkYSBwZXIgc2F0dWFuIHdha3R1IHRldGFwICwgeWFuZyBzZXJpbmcgZGlzZWJ1dCBSaXNpa28gKEhhemFyZCkgdW50dWsgbWF0aSAsIGF0YXUgaGFueWEgSGF6YXJkICjOuyAtIGxhbWJkYSApLiBJbmkgbWVtYnVhdCBqdW1sYWgga2VqYWRpYW4gbWVuamFkaSB2YXJpYWJlbCwgZGFuIEJhaGF5YSBtZW5qYWRpIHRpbmdrYXQga2VtYXRpYW4gLCBtaXNhbG55YSwgcGVyIGhhcmkuIA0KDQoyLiBNZWxhbHVpIGJlbnRhbmdhbiB3YWt0dSBiZXJsYWx1IHlhbmcgYmVyYmVkYSBwZXIganVtbGFoIHBlcmlzdGl3YSB5YW5nIHRldGFwIC4gSW50ZXJ2YWwgd2FrdHUgYmlhc2FueWEgZGl1a3VyIGhpbmdnYSBwZXJpc3Rpd2EgYmVyaWt1dG55YSB0ZXJqYWRpLiBJbmkgbWVtYnVhdCB3YWt0dSBtZW5qYWRpIHZhcmlhYmVsLg0KDQojIyBQZXJ1YmFoYW4gc3RhYmlsIGRhbGFtIGJhaGF5YSBkYW4ga2VsYW5nc3VuZ2FuIGhpZHVwDQoNCkJheWFuZ2thbiBzZXRpYXAgaGFyaSB0ZXBhdCAzIGRhcmkgMTAgb3JhbmcgbWVuaW5nZ2FsIGRpIGFpciBsYXV0IHlhbmcgZGluZ2luIHNldGVsYWgga2VjZWxha2FhbiBUaXRhbmljLiBJbmkgdGluZ2thdCBrZW1hdGlhbiB5YW5nIGN1a3VwIHN0YWJpbCAsIGF0YXUgQmFoYXlhICwgc2ViZXNhciAzMCUuIEppa2EgYmFoYXlhIHVudHVrIG1hdGkgdGVydXMgdHVtYnVoIGRlbmdhbiBsYWp1IHlhbmcgc2FtYSwgbWFrYSBrZW11bmdraW5hbiB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBha2FuIHRlcnVzIGJlcmt1cmFuZyBkZW5nYW4gbGFqdSB5YW5nIHNhbWEuIERlbmdhbiBkZW1pa2lhbiwgQmFoYXlhIGRhbiBLZWxhbmdzdW5nYW4gSGlkdXAgZGFwYXQgZGlla3NwcmVzaWthbiBzYXR1IHNhbWEgbGFpbi4gU2VjYXJhIGtodXN1cywgQmFoYXlhIGtlbWF0aWFuIGRhcmkgd2FrdHUga2Ugd2FrdHUgZGFwYXQgZGlsaWhhdCBzZWJhZ2FpIEdhZ2FsIGJlcnRhaGFuIGhpZHVwICRGKCB0ICkkIGRhbiBrZWxhbmdzdW5nYW4gaGlkdXAgZGFyaSB3YWt0dSBrZSB3YWt0dSAkUyggdCApJCB5YW5nICBkYXBhdCBkaWxpaGF0IHNlYmFnYWkgSGF6YXJkIG9mIE5PVC1keWluZyAsIGF0YXUgaGFueWEgSGF6YXJkIG5lZ2F0aWYgLCB5YW5nIHNlY2FyYSBtYXRlbWF0aXMgZGFwYXQgZGlueWF0YWthbiBzZWJhZ2FpIHRhbmRhIG1pbnVzIOKAnC3igJ0sIGF0YXUg4oCcMS3igJ0sIGRpIGRlcGFuIEhhemFyZC4gS2VkdWEgZnVuZ3NpIHRlcnNlYnV0IG1lbmdoYXNpbGthbiBnYXJpcyBsdXJ1cywgZGkgbWFuYSBCYWhheWEgdGVydXMgbWVuaW5na2F0IGRhbiBrZWxhbmdzdW5nYW4gaGlkdXAgdGVydXMgbWVudXJ1biAocGxvdCBkaSBiYXdhaCk6DQokJCBGKHQpID0gSGF6YXJkICogdCAkJA0KJCRTKHQpID0gMSAtIEhhemFyZCAqIHQkJA0KDQpgYGB7ciBpbWFnZTIsIGVjaG89RkFMU0UsIGZpZy5jYXA9IiIsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnMTAwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygib3V0cHV0Mi5wbmciKQ0KYGBgDQoNClBlbmluZ2thdGFuIGF0YXUgcGVudXJ1bmFuIHlhbmcgc3RhYmlsIGRhbGFtIGJhaGF5YSBhdGF1IGtlbGFuZ3N1bmdhbiBoaWR1cCBzZXBlcnRpIGl0dSBhZ2FrIHRpZGFrIGFsYW1pLCB0aWRhayByZWFsaXN0aXMuIERhbGFtIG1lbXBlcmtpcmFrYW4ga2VtYXRpYW4gZGFwYXQgZGlrYXRha24gc3VsaXQuIEJhaGF5YSBiaWFzYW55YSBtZW5pbmdrYXQgc2VjYXJhIGVrc3BvbmVuc2lhbCwgbWlzYWxueWEgZGFsYW0ga2FzdXMga2VsYXBhcmFuLCBhdGF1IG1lbnVydW4gc2VjYXJhIGVrc3BvbmVuc2lhbCwgbWlzYWxueWEgZGFsYW0ga2FzdXMgcGFuZGVtaSBzZXRlbGFoIHZha3NpbiBkaXRlbXVrYW4uDQoNCiMjIFBlcnViYWhhbiBla3Nwb25lbnNpYWwgcG9zaXRpZiBkYWxhbSBiYWhheWEgZGFuIGtlbGFuZ3N1bmdhbiBoaWR1cA0KDQpQaWtpcmthbiB0ZW50YW5nIGtlbGFwYXJhbiBzZWplbmFrLiBTZW1ha2luIGxhbWEga29uZGlzaSBrZWxhcGFyYW4sIHNlbWFraW4gdGluZ2dpIGtlbXVuZ2tpbmFuIChyaXNpa28pIG1hdGkuIFBsb3Qga2lyaSBkaSBiYXdhaCBtZW51bmp1a2thbiBwZXJrZW1iYW5nYW4gc2VwZXJ0aSBpdHUsIGRpIG1hbmEgYmFoYXlhIGtlbWF0aWFuICRGKCB0ICkkIGRpbnlhdGFrYW4gZGFsYW0gcHJvYmFiaWxpdGFzIGtlY2lsIHBhZGEgYXdhbG55YSAoYmViZXJhcGEga2VtYXRpYW4pLCB0ZXRhcGkgdHVtYnVoIHNlY2FyYSBla3Nwb25lbnNpYWwgZGVuZ2FuIHdha3R1IChzZW1ha2luIGJhbnlhayBrZW1hdGlhbikuIFNheWEgc3VrYSBtZW55ZWJ1dCB0cmVuIHNlcGVydGkgaXR1IHNlYmFnYWkgcGVydWJhaGFuIGVrc3BvbmVuc2lhbCB5YW5nIHBvc2l0aWYsIGF0YXUgbWVtcGVyY2VwYXQuICJleHAiIGRhbGFtIHJ1bXVzIGtpcmkgZGkgYmF3YWggYWRhbGFoIHNlbXVhIHlhbmcgZGlwZXJsdWthbiB1bnR1ayBtZXJlbmNhbmFrYW4gdHJlbiB0ZXJzZWJ1dC4NCg0KU2VrYWxpIGxhZ2ksIGthcmVuYSBrZWxhbmdzdW5nYW4gaGlkdXAgZGFwYXQgZGlsaWhhdCBzZWJhZ2FpIGJhaGF5YSBuZWdhdGlmIGRhcGF0IG1lbnlhdGFrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwICRTKCB0ICkkIGRlbmdhbiBoYW55YSBtZW5nZ3VuYWthbiB0YW5kYSBtaW51cyAoYXRhdSDigJwxLeKAnSkgZGkgZGVwYW4gSGF6YXJkLiBQbG90IGRpIHNlYmVsYWgga2FuYW4gbWVuYW1waWxrYW4gaGFzaWwgZGFyaSBmdW5nc2kgYmVydGFoYW4gaGlkdXAgdGVyc2VidXQuSmlrYSBiYWhheWEga2VtYXRpYW4gcmVuZGFoIGRpIGF3YWwgIndha3R1IiwgbWFrYSBrZW11bmdraW5hbiBiZXJ0YWhhbiBoaWR1cCB0aW5nZ2kuIERpIGFraGlyICJ3YWt0dSIsIEtlbGFuZ3N1bmdhbiBIaWR1cCB0dXJ1biBzZWNhcmEgZWtzcG9uZW5zaWFsIGthcmVuYSBwZW5pbmdrYXRhbiBCYWhheWEgc2VjYXJhIGVrc3BvbmVuc2lhbC4NCiQkIEYodCk9IGV4cF57SGF6YXJkICogdH0gJCQNCiQkUyh0KSA9IDEgLSBleHBee0hhemFyZCAqIHR9JCQNCg0KYGBge3IgaW1hZ2UzLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSIiLGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzEwMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm91dHB1dDMucG5nIikNCmBgYA0KDQojIyBQZXJ1YmFoYW4gZWtzcG9uZW5zaWFsIG5lZ2F0aWYgZGFsYW0gYmFoYXlhIGRhbiBrZWxhbmdzdW5nYW4gaGlkdXANCg0KTmFtdW4sIGRhbGFtIGJlYmVyYXBhIGthc3VzLCBsZWJpaCBiYW55YWsgb3JhbmcgbWVuaW5nZ2FsIHBhZGEgYXdhbCAid2FrdHUiLCBkaSBtYW5hIHRpbmdrYXQga2VtYXRpYW4gbWVudXJ1biBkYXJpIHdha3R1IGtlIHdha3R1LiBQaWtpcmthbiB0ZW50YW5nIHBhbmRlbWksIGF0YXUga2VjZWxha2FhbiBiZXNhci4gUGVydWJhaGFubnlhIG1hc2loIGVrc3BvbmVuc2lhbCwgZGFuIG1lbnVqdSBrZSBhcmFoIHlhbmcgc2FtYTogbmFpaywgZGFsYW0ga2FzdXMgQmFoYXlhLCBkYW4gdHVydW4sIGRhbGFtIGthc3VzIGJlcnRhaGFuIGhpZHVwLiBOYW11biwgcGVydWJhaGFuIGVrc3BvbmVuc2lhbCBhZ2FrIHRlcmJhbGlrIChtZW1idW5na3VrKS4gU2F5YSBzdWthIG1lbnllYnV0bnlhIHNlYmFnYWkgcGVydWJhaGFuIGVrc3BvbmVuc2lhbCB5YW5nIG5lZ2F0aWYsIGF0YXUgbWVsYW1iYXQuDQoNClNlcGVydGkgInBlbWJlbmdrb2thbiBrZSBkYWxhbSIgZGFwYXQgZGljYXBhaSBkZW5nYW4gIi0iIG1pbnVzIHNpbmcgZGkgZGVwYW4gSGF6YXJkIGRhbiBmdW5nc2kgZWtzcG9uZW5zaWFsIGl0dSBzZW5kaXJpIChwZXJzYW1hYW4ga2lyaSBkYW4gZ2FtYmFyIGRpIGJhd2FoKS4gTWludXMgaW5pIHRpZGFrIG1lbmdnYW1iYXJrYW4gaGF6YXJkIG5lZ2F0aWYsIHNlcGVydGkgcGFkYSBjb250b2ggZGkgYXRhcy4gSXR1IGhhbnlhIG1lbmd1YmFoIGt1cnZhIGRhcmkgcGVyY2VwYXRhbiBrZSBwZXJsYW1iYXRhbi4gVW50dWsgbWVuZGFwYXRrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIHVudHVrIGZ1bmdzaSBpbmkgc2VwZXJ0aSBwYWRhIGNvbnRvaCBkaSBhdGFzLCBoYXJ1cyBtZW5nZ3VuYWthbiAiLSIgKGF0YXUgIjEtIikgZGkgZGVwYW4gc2VsdXJ1aCBla3NwcmVzaSBoYXphcmQgZWtzcG9uZW5zaWFsLiBNZW5hcmlrbnlhLCBkdWEgdGFuZGEgbWludXMgZGkgZGVwYW4gImV4cCIgZGFsYW0gcnVtdXMgU3Vydml2YWwgc2FsaW5nIG1lbmV0cmFsa2FuIGRhbiBtZW5qYWRpIG5pbGFpIHRhbWJhaCwgeWFuZyBtZW55aXNha2FuIGRlbmdhbiANCg0KJCRGKHQpPSAtIGV4cF57LUhhemFyZCAqIHR9JCQNCg0KJCRTKHQpID0gMSAtICggLSBleHBeey1IYXphcmQgKiB0fSkgPSBleHBeey1IYXphcmQgKiB0fSQkDQoNCmBgYHtyIGltYWdlNCwgZWNobz1GQUxTRSwgZmlnLmNhcD0iIixmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICcxMDAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJvdXRwdXQ0LnBuZyIpDQpgYGANCg0KIyMgTWVtYmFuZ3VuIE1vZGVsIEVrcG9uZW5zaWFsDQoNClNlamFrIGZ1bmdzaSBiZXJ0YWhhbiBoaWR1cCAkUyggdCApJCBtZW51bmp1a2thbiBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgbWVsZXdhdGkgdGl0aWsgd2FrdHUgdGVydGVudHUgLA0KDQokJFModCkgPSBQKFQgPiB0KSQkDQoNCmRhbiBmdW5nc2kgZWtzcG9uZW5zaWFsICRGKCB0ICkkIG1lbnVuanVra2FuIHByb2JhYmlsaXRhcyBGYWlsZWQtc3Vydml2YWwgbWVsZXdhdGkgdGl0aWsgd2FrdHUgdGVydGVudHUgLA0KDQokJEYodCkgPSBQKFQgXGxlcSB0KSA9IDEgLSBleHBeey1IYXphcmQgKiB0fSQkDQoNCmZ1bmdzaSBiZXJ0YWhhbiBoaWR1cCBrZW11ZGlhbiBkYXBhdCBkaW55YXRha2FuIGRhbGFtIGJlbnR1ayBmdW5nc2kgdGlkYWsgYmVydGFoYW4gaGlkdXAgKGVrc3BvbmVuc2lhbCk6DQoNCiQkUyh0KSA9IFAoVCA+IHQpID0gMSAtIFAoVCBcbGVxIHQpID0gMSAtIEYodCkgPSAxIC0gWzEgLSBleHBeey1IYXphcmQgKiB0fV0gPSBleHBeey1IYXphcmQgKiB0fSQkDQoNClNlaGluZ2dhIGZ1bmdzaSBzdXJ2aXZhbCB5YW5nIG1lbnVuanVra2FuIGxhanUgcGVudXJ1bmFuIGFkYWxhaCBmdW5nc2kgZmxpcHBlZCBoYXphcmQgeWFuZyBtZW51bmp1a2thbiBsYWp1IGtlbmFpa2FuLiBEZW5nYW4gZGVtaWtpYW4sIGRhcGF0IG1lbnVsaXMgdWxhbmcgJFMoIHQgKSQgc2ViYWdhaToNCg0KJCRTKHQpID0gZXhwXnstIEhhemFyZCAqIHR9ID0gZXhwXnstIFxsYW1iZGEqIHR9JCQNCg0KZGkgbWFuYSAtSGF6YXJkIGRhbiB3YWt0dSBhZGFsYWggZHVhIHBhcmFtZXRlciB5YW5nIG1lbmdnYW1iYXJrYW4gcGVydWJhaGFuIGVrc3BvbmVuc2lhbCAgZGFsYW0gcHJvYmFiaWxpdGFzIGJlcnRhaGFuIGhpZHVwLCBpdHVsYWggc2ViYWJueWEgbW9kZWwgc2VwZXJ0aSBpdHUgbWVtaWxpa2kgbmFtYSAtIG1vZGVsIGVrc3BvbmVuc2lhbCBwYXJhbWV0cmlrIC4gRGFuIGthcmVuYSBIYXphcmQgYWRhbGFoIG5lZ2F0aXZlICwgZGFuIGZ1bmdzaSBla3Nwb25lbnNpYWwgdGlkYWsgbGluaWVyIChhbGlhcy4gY3VydnkgKSAtIG1vZGVsIGtlbHVhciBtZW5naGFzaWxrYW4ga3VydmEgZWtzcG9uZW5zaWFsIG5lZ2F0aWYgKGxpaGF0IGRpIGJhd2FoKS4gVGluZ2thdCBwZW51cnVuYW4geWFuZyBtdWx1cyBzZXBlcnRpIGl0dSBtZW5nZ2FtYmFya2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBqYXVoIGxlYmloIGJhaWsgZGFyaXBhZGEgbWV0b2RlIEthcGxhbi1NZWllciwgeWFuZyBzZWNhcmEgdGliYS10aWJhIChzZWNhcmEgYmVydGFoYXApIG1lbnVydW5rYW4gcHJvYmFiaWxpdGFzIGhhbnlhIHNldGVsYWggc3VhdHUgcGVyaXN0aXdhLCBzYW1iaWwgbWVuamFnYSBwcm9iYWJpbGl0YXMgdGV0YXAga29uc3RhbiBkaSBhbnRhcmEgcGVyaXN0aXdhIHRlcnNlYnV0Lg0KDQoNCiMjIENhcmEgbWVuZ2hpdHVuZyBtb2RlbCBwYXJhbWV0cmlrDQoNCmBgYHtyfQ0KbGlicmFyeShmbGV4c3VydikgICAgIyBmb3IgUGFyYW1ldHJpYyBTdXJ2aXZhbCBNb2RlbGxpbmcNCg0KZXggPC0gZmxleHN1cnZyZWcoU3Vydih0aW1lLCBzdGF0dXMpIH4gMSwgZGF0YSA9IGQyLCBkaXN0PSJleHBvbmVudGlhbCIpDQp3ZSA8LSBmbGV4c3VydnJlZyhTdXJ2KHRpbWUsIHN0YXR1cykgfiAxLCBkYXRhID0gZDIsIGRpc3Q9IndlaWJ1bGwiKQ0KDQpnZ3N1cnZwbG90KA0KICBleCwgDQogIGNvbmYuaW50ID0gRkFMU0UsIA0KICBzdXJ2Lm1lZGlhbi5saW5lID0gImh2IiwNCiAgeGxhYiA9ICJEYXlzIiwgDQogIHlsYWIgPSAiU3Vydml2YWwgcHJvYmFiaWxpdHkiLCANCiAgYnJlYWsudGltZS5ieSA9IDEsDQogIHJpc2sudGFibGUgPSBGDQopDQpgYGANCg0KUGFyYW1ldGVyIGt1cnZhICgkLVxsYW1iZGEgKiB0JCkgbWVtdW5na2lua2FuIGtpdGEgdW50dWsgbWVtb2RlbGthbiBkYW4gKm1lbXByZWRpa3NpKiBrZWxhbmdzdW5nYW4gaGlkdXAgZGFuIGJhaGF5YSBkYXJpIHdha3R1IGtlIHdha3R1LCB5YW5nICptZXJ1cGFrYW4ga2V1bnR1bmdhbiB1dGFtYSogZGFyaSBtb2RlbCBla3Nwb25lbnNpYWwgZGliYW5kaW5na2FuIGRlbmdhbiBtZXRvZGUgS2FwbGFuLU1laWVyLCB5YW5nIHRpZGFrIGJlcnNpZmF0IHBhcmFtZXRyaWsgZGFuIG9sZWgga2FyZW5hIGl0dSB0aWRhayBkYXBhdCBkaW1vZGVsa2FuLiBOYW11biwgbm9uLWxpbmVhcml0YXMgc2VyaW5nIGthbGkgbWVyZXBvdGthbiwgZGFuIGthbWkgbGViaWggc3VrYSBtZW5nZ3VuYWthbiBrb25zZXAgKnJlZ3Jlc2kgbGluZWFyKiwgeWFuZyBtZXJpbmdrYXMgKG1lcmVncmVzaWthbikgYmFueWFrIGFuZ2thIG1lbmphZGkgYmViZXJhcGEgYW5na2EsIHNlcGVydGkgaW50ZXJzZXAgKCRcYmV0YV8wJCkgZGFuIGtlbWlyaW5nYW4gKCRcYmV0YV8xJCkuIFVudHVuZ255YSwga3VydmEgbm9uLWxpbmllciBkYXBhdCBkZW5nYW4gbXVkYWggImRpbGluaWVya2FuIiBtZWxhbHVpIGxvZ2FyaXRtYSBuYXR1cmFsLiBVbnR1ayBtZWxha3VrYW4gaW5pLCBraXRhIGJhaGthbiB0aWRhayBwZXJsdSBtZW1haGFtaSBjYXJhIGtlcmphIGxvZ2FyaXRtYSBhdGF1IGZ1bmdzaSBla3Nwb25lbnNpYWwsIGtpdGEgaGFueWEgcGVybHUgbWVuZ2V0YWh1aSBiYWh3YSBrZWR1YW55YSBzYWxpbmcgbWVuZXRyYWxrYW4gc2F0dSBzYW1hIGxhaW4uIFNlbGFpbiBpdHUsIG1lbmdndW5ha2FuICJsb2ciIChtZWxvZ2FyaXRtYWthbiBrZWR1YSBzaXNpIHBlcnNhbWFhbiBkaSBiYXdhaCBpbmkpIG1lbmdoYXNpbGthbiB0aWdhIGVmZWsgc2FtcGluZyB5YW5nIHBvc2l0aWY6DQoNCjEuIFBlcnRhbWEsIGRpIHNpc2kga2FuYW4gcGVyc2FtYWFuLCBpbmkgYWthbiAqbWVtaW5kYWhrYW4ga3VydmEga2l0YSogKCQtXGxhbWJkYSAqIHQkKSAqbWVuamFkaSBzZWJ1YWggZ2FyaXMqICgkYl8wICsgYl8xeF8xICsgLi4uICsgYl9reF9rJCksIGRpIG1hbmEga2l0YSBha2FuIGRhcGF0IG1lbWlsaWtpIGludGVyc2VwIGRhbiBrb2VmaXNpZW4gJFxiZXRhJCBzZXBlcnRpIHBhZGEgcmVncmVzaSBsb2dpc3RpayBsaW5pZXIgYmlhc2EgDQokJEhhemFyZCA9IGV4cF57Yl8wICsgYl8xeF8xICsgLi4uICsgYl9reF9rfSQkIA0KDQphdGF1DQoNCiQkIGxvZyhIYXphcmQpID0gYl8wICsgYl8xeF8xICsgLi4uICsgYl9reF9rICQkIA0KDQpNb2RlbCBzdXJ2aXZhbCBzZXBlcnRpIGl0dSBzZWJlbmFybnlhIGFkYWxhaCBtb2RlbCBQb2lzc29uLiBPbGVoIGthcmVuYSBpdHUsIGFrYW4gc2FuZ2F0IG1lbWJhbnR1IGppa2Egc3VkYWggbWVuZ2V1YXNhaSBkaXN0cmlidXNpIFBvaXNzb24uIA0KDQoyLiBLZWR1YSwgaW5pIGFrYW4gbWVtYmFudHUga2l0YSB1bnR1ayB0ZXJodWJ1bmcga2UgbW9kZWwtbW9kZWwgc2VsYW5qdXRueWEsIHNlcGVydGkgbW9kZWwgV2VpYnVsbCBkYW4gQ294LCBrYXJlbmEgcGVyYmVkYWFuIGRpIGFudGFyYSBrZWR1YW55YSB0ZXJ1dGFtYSB0ZXJsZXRhayBwYWRhIGludGVyc2VwICIkYl8wJCI7DQoNCjMuIFRlcmFraGlyLCBpbmkgYWthbiBzYW5nYXQgbWVuaW5na2F0a2FuIGtlbWFtcHVhbiBpbnRlcnByZXRhc2ksIGthcmVuYSBIYXphcmQtUmF0aW9zIChIUnMpICh5YW5nIGRpaGFzaWxrYW4gb2xlaCBtb2RlbCBla3Nwb25lbnNpYWwpIGRhcGF0IGRpaW50ZXJwcmV0YXNpa2FuIHBlcnNpcyBzZXBlcnRpIE9kZHMtUmF0aW9zIChPUnMpIGRhcmkgcmVncmVzaSBsb2dpc3RpayAoc2VwZXJ0aSB5YW5nIGRpamVsYXNrYW4gZGFsYW0gcG9zdGluZyBzYXlhIHRlbnRhbmcgcmVncmVzaSBsb2dpc3RpaykuIFNhbWEgaGFsbnlhIGRlbmdhbiBPZGRzIGRhbGFtIHJlZ3Jlc2kgbG9naXN0aWssICpIYXphcmQgaXR1IHNlbmRpcmksIHlhbmcgbWVydXBha2FuIHByb2JhYmlsaXRhcyBtZW5pbmdnYWwgU0VLQVJBTkcqLCBrdXJhbmcgYmVyZ3VuYSBkaWJhbmRpbmdrYW4gZGVuZ2FuIEhhemFyZC1SYXRpby4gSGF6YXJkLVJhdGlvIGFkYWxhaCByYXNpbyBiYWhheWEgc2VzZW9yYW5nIHlhbmcgdGVycGFwYXIgKHNha2l0KSB0ZXJoYWRhcCBzZXNlb3JhbmcgeWFuZyB0aWRhayB0ZXJwYXBhciAoc2VoYXQpLiBNaXNhbG55YSBqaWthIEhSID0gMiwgcmlzaWtvIGtlbWF0aWFuIHNlc2VvcmFuZyB5YW5nIHRlcnBhcGFyIGFkYWxhaCBkdWEga2FsaSBsaXBhdCBkaWJhbmRpbmdrYW4gZGVuZ2FuIHNlc2VvcmFuZyB5YW5nIHRpZGFrIHRlcnBhcGFyLiANCg0KDQojIyBQaWtpcmFuIGFraGlyDQoNCioqQXBha2FoIG1vZGVsIHBhcmFtZXRyaWsgYmVyZ3VuYT8qKg0KDQotIFRpZ2Ega3VydmEgZGkgYXRhcyB5YW5nIG1lbmdnYW1iYXJrYW4gYmVyYmFnYWkgamVuaXMgcGVydWJhaGFuIGRhbGFtIGtlbGFuZ3N1bmdhbiBoaWR1cCBkYW4gYmFoYXlhIGRhcmkgd2FrdHUga2Ugd2FrdHUgZGltYWtzdWRrYW4gdW50dWsgbWVuZ2F0YWthbiBiYWh3YSBkaXN0cmlidXNpIGJpc2Egc2FuZ2F0IGJlcmJlZGEuIEppa2EgZGlzdHJpYnVzaSB5YW5nIHNlc3VhaSBkYXBhdCBkaXRlbXVrYW4sIG1vZGVsIHBhcmFtZXRyaWsgbGViaWggaW5mb3JtYXRpZiBkYXJpcGFkYSBtb2RlbCBLTSBhdGF1IENveCANCg0KLSBtb2RlbCBpbmkgZGFwYXQgbWVtcHJlZGlrc2kgcHJvYmFiaWxpdGFzIGtldGFoYW5hbiBoaWR1cCBwYWRhIHRpdGlrIHdha3R1IHRlcnRlbnR1LCBoYXphcmQga2VqYWRpYW4sIHJhdGEtcmF0YSBkYW4gbWVkaWFuIHdha3R1IGtldGFoYW5hbiBoaWR1cCBzdWRhaCB0ZXJzZWRpYQ0KDQotIG1vZGVsIGluaSBqdWdhIHNlZGlraXQgbGViaWggZWZpc2llbiBkYW4gbWVuZ2hhc2lsa2FuIGVzdGltYXNpIHlhbmcgbGViaWggdGVwYXQga2FyZW5hIGtlY29jb2thbiB5YW5nIGxlYmloIGJhaWsgKGxpaGF0IGdhbWJhciBkaSBhdGFzKQ0KDQoqQXBha2FoIG1vZGVsIHBhcmFtZXRyaWsgaXR1IHNlbXB1cm5hPyBUZW50dSBzYWphIHRpZGFrISoNCg0KLSBtb2RlbCBwYXJhbWV0cmlrIHBlcmx1IG1lbmVudHVrYW4gZGlzdHJpYnVzaSwgeWFuZyBtdW5na2luIHN1bGl0IHVudHVrIGRpaWRlbnRpZmlrYXNpDQoNCi0gbW9kZWwgaW5pIGp1Z2Egc2VjYXJhIG1hdGVtYXRpcyBsZWJpaCBrb21wbGVrcywgbWlzYWxueWEgS00sIGRhbiBvbGVoIGthcmVuYSBpdHUgbGViaWggamFyYW5nIGRpZ3VuYWthbiwgc2VoaW5nZ2EgbWVuZ3VyYW5naSBwZXJiYW5kaW5nYW4gaGFzaWwgYW50YXIgc3R1ZGkuIEthcmVuYSBwb3B1bGFyaXRhc255YSB5YW5nIGxlYmloIHJlbmRhaCwgc2F5YSB0aWRhayBha2FuIG1lbWJhaGFzIGxlYmloIGRhbGFtIHRlbnRhbmcgbW9kZWwgcGFyYW1ldHJpayB0ZXJ0ZW50dTogTW9kZWwgV2VpYnVsbCwgR29tcGVydHosIG1vZGVsIFdha3R1IEtlZ2FnYWxhbiB5YW5nIERpcGVyY2VwYXQsIGRsbC4NCg0KSmFkaSwgdGVybGVwYXMgZGFyaSBrZW55YXRhYW4gYmFod2EgbW9kZWwgcGFyYW1ldHJpayBhZGFsYWggYWx0ZXJuYXRpZiB5YW5nIGJhaWsgdW50dWsgbW9kZWwgcmVncmVzaSBLTSBkYW4gQ294ICh5YW5nIHRpZGFrIHBlcmx1IG1lbmVudHVrYW4gZGlzdHJpYnVzaSBhcGEgcHVuKSwgS00gZGFuIENveCB0ZXRhcCBtZW5qYWRpIG1ldG9kZSB5YW5nIHBhbGluZyBwb3B1bGVyIHVudHVrIG1lbmdhbmFsaXNpcyBkYXRhIHN1cnZpdmFsLiBEYW4gaXR1bGFoIG1lbmdhcGEgbGFuZ2thaCBsb2dpcyBiZXJpa3V0bnlhIGRhbGFtIHBlcmphbGFuYW4gc3RhdGlzdGlrIGRhbGFtIG1lbXBlbGFqYXJpIE1vZGVsIENveCBQcm9wb3J0aW9uYWwgSGF6YXJkIChzZWRhbmcgYmVybGFuZ3N1bmcpLg0KDQojIFJlZmVyZW5zaSANCi0gaHR0cHM6Ly95dXphci1ibG9nLm5ldGxpZnkuYXBwL3Bvc3RzLzIwMjEtMDEtMDMtc3Vydml2YWwtYW5hbHlzaXMtMS1hLWdlbnRsZS1pbnRyb2R1Y3Rpb24taW50by1rYXBsYW4tbWVpZXItY3VydmVzLw0KDQotIGh0dHBzOi8veXV6YXItYmxvZy5uZXRsaWZ5LmFwcC9wb3N0cy8yMDIxLTAxLTA2LXN1cnZpdmFsLWFuYWx5c2lzLTItcGFyYW1ldHJpYy1zdXJ2aXZhbC1tb2RlbHMvDQo=