Survival analysis 1: a gentle introduction into Kaplan-Meier Curves
Kurva survival Kaplan Meier adalah kurva yang menggambarkan hubungan antara estimasi fungsi survival pada waktu t dengan waktu survival, Pada bagian ini akan membahas mengenai:
Mmepelajari konsep paling penting dari analisis kelangsungan hidup: kurva kelangsungan hidup, penyensoran dan uji log-rank,
Menghitung secara manual , lalu menghitung dan menginterpretasikan kurva kelangsungan hidup, dan
Menguji perbedaan kelangsungan hidup antara dua kelompok atau lebih
install.packages("ggplot2")
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(knitr) # for a wonderful-looking tables
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()
Pada bagian ini menggunakan contoh kasus penyintas Titanic: 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, maka menentukan metode yang tepat.
- Melihat variabel numerik “waktu”, kita mungkin 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))
Dari plot diatas dapat dilihat bahwa informasi yang dimiliki untuk memodelkan waktu bertahan hidup adalah nol dan satu. Rata-rata waktu kematian (status = 1) 2,5 hari banyak yang meleset dari informasi. Misalnya, setengah dari orang (3 orang) meninggal pada hari pertama dan semakin jauh melangkah dalam waktu, semakin sedikit orang yang mati. Jadi, waktu bertahan hidup tidak benar-benar linier dan tentunya tidak bisa digambarkan hanya dengan angka nol dan satu. Dengan demikian, model linier kurang cocok.
- Pada penyelesaian diatas hanya memiliki nol dan satu di kolom status, maka dapat menggunakan regresi logistik karena kurva probabilitas 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)
Dari penyelesaian diatas maka memiliki probabilitas kelangsungan hidup non-linier yang merupakan peningkatan besar dibandingkan dengan regresi linier. Namun pengamatan ke lima berstatus 0 pada hari ke 2. Artinya orang tersebut pasti bertahan selama 2 hari, tetapi hilang setelahnya. Probabilitas dalam regresi logistik akan menghitung orang ini sebagai 100% selamat setelah hari kedua hanya karena statusnya bukan “=1”, yang salah (atau bias), karena tidak diketahui apakah orang ini selamat. Dengan demikian, regresi logistik kurang cocok dalam memperkirakan kemungkinan kelangsungan hidup.
Dari pembahasan diatas maka dalam mengnanalisis kelangsungan hidup tidak dapat menggunakan metode dasar. Sementara model regresi linier menggambarkan waktu, tetapi melewatkan probabilitas bertahan hidup non-linier, regresi logistik menangkap tren non-linier, tetapi melebih-lebihkan probabilitas bertahan hidup. Sebaliknya, analisis kelangsungan hidup menyelesaikan kedua masalah tersebut, karena ini memodelkan probabilitas kelangsungan hidup non-linear dari waktu ke waktu sambil memperhitungkan subjek penelitian yang hilang yang mati atau selamat.
Pengantar : Analisis Kelangsungan Hidup
Analisis waktu kelangsungan hidup diperlukan dalam studi apa pun yang menyelidiki waktu untuk hasil tertentu yang menarik . Studi kanker dalam kedokteran dan kegagalan pertama mobil di bidang teknik ( failure time analysis ) adalah contoh yang baik. Hasil yang menarik bisa berupa kematian, remisi hingga kambuh, perkembangan, atau kegagalan. Titik waktu untuk mencapai hasil tersebut umumnya disebut peristiwa . Syukurlah, tidak semua “kejadian” itu fatal, tapi terkadang bisa menjadi hasil yang menguntungkan seperti keluar dari rumah sakit. Dengan demikian, analisis kelangsungan hidup juga merupakan istilah umum, karena tidak hanya tentang kelangsungan hidup.
Peristiwa, sebagai titik waktu tetap terakhir diperlukan karena tidak dapat mengamati atau bereksperimen selamanya. Jika mempelajari kanker paru-paru, maka tidak bisa menunggu sampai pasien meninggal karena sebab lain, misalnya karena tua. Hanya ketika beberapa pasien selamat dari kanker, atau beberapa mobil tidak mogok pada waktu (kejadian) tertentu , sehingga bisa mendapatkan wawasan yang berharga. Misalnya, berapa lama waktu dari awal pengobatan hingga perkembangan, atau berapa probabilitas bertahan hidup dari kanker paru setelah tepat 1 tahun? Selain itu, ini membuka kemungkinan untuk membandingkan waktu bertahan hidup atau gagal di antara kelompok yang berbeda, misalnya kanker paru-paru antara perokok dan bukan perokok, atau waktu kerusakan antara mobil Jerman dan Korea.
Jadi, waktu bertahan hidup memiliki titik awal dan titik akhir. Tapi bagaimana jika pasien mengundurkan diri dari penelitian karena alasan pribadi, atau mobil dicuri 1 hari sebelum acara? Akankah mereka “bertahan” pada saat acara berlangsung? Tapi mereka pasti bertahan dari awal penelitian sampai kehilangan mereka. Namun bagaimana caranya membedakan penyintas yang “hilang” dari penyintas yang “nyata”? konsep menyensor pasien menjadi lebih mudah digunakan. Karena tidak dapat mengatakan bahwa orang tersebut telah meninggal atau masih hidup, hanya karena kami TIDAK MEMILIKI INFORMASI YANG CUKUP , kedua kesimpulan tersebut tidak tepat , dan dengan demikian, kami menyensor orang ini. Konsep penyensoran sangat penting, sehingga layak mendapat bab tambahan.
Sensoring
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 kelangsungan hidup Kaplan-Meier “secara manual”
Bayangkan hari cerah yang damai tepat sebelum kecelakaan Titanic . Tidak ada yang meninggal, tetapi semua 10 orang berisiko tinggi (bahaya) kematian, mereka belum mengetahuinya. Tebak, berapa banyak orang yang mungkin akan mati sehari sebelum kecelakaan itu? Jawabannya adalah - mungkin nol. Secara harfiah, kemungkinan kematian adalah nol, karena kita tahu kecelakaan itu tidak akan terjadi sehari sebelum kehancuran 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 dari 10 orang yang meninggal sehari sebelum kecelakaan, kemungkinan meninggal adalah 0%, sedangkan kemungkinan selamat adalah 100%:
\[probability \ of \ dying = \frac{0}{10} = 0\]
\[probability \ of \ surviving = \frac{10}{10} = 1 = 100\%\]
tribble(
~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
0, 10, 0, "0/10 = 0", "10/10 = 1"
) %>% kable()
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\).
Probabilitas bertahan hidup
Satu poin penting di sini adalah kemungkinan untuk bertahan hidup bersifat kumulatif , artinya terakumulasi dari hari ke hari. Akumulasi ini terjadi dengan mengalikan probabilitas baru bertahan hari pertama \((1 - \frac{d_i}{n_i}) = (1 - \frac{3}{10}) = 70\%\) dengan probabilitas lama untuk bertahan hidup sepanjang waktu sebelumnya, yang dalam kasus adalah hari sebelum kecelakaan, atau \(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\]
Di mana:
\(S(t_{i−1}) =\) peluang hidup di \(t_{i−1}\)
\(n_i =\) jumlah pasien hidup sesaat sebelumnya \(t_i\)
\(d_i =\) jumlah kejadian pada \(t_i\)
\(t_0 = 0, S(0) =1\)
Probabilitas bertahan hidup pada waktu tertentu, \(S( t )\) , bersyarat karena orang tersebut harus bertahan hidup melebihi waktu tertentu itu , misalnya hari nol (itulah syaratnya) untuk tetap berada dalam percobaan pada 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()
Hari kedua sedikit lebih menarik, karena satu orang meninggal dan satu hilang begitu saja (status = 0). Orang yang hilang ini kemungkinan besar terbawa ombak dan mudah-mudahan bisa diselamatkan. Besar harapannya, karena semakin jauh manusia bertebaran di lautan, semakin besar kemungkinan salah satunya ditemukan dalam keadaan hidup. Dan yang ini akan membuat dunia tahu bahwa masih ada orang lain di luar sana. Jadi, terlepas dari kenyataan bahwa orang hilang tampak buruk, itu bisa menjadi hal yang baik. Sehingga tidak bisa menghitung orang yang terlewatkan sebagai mati.
Tetapi karena pada data tersebut tidak yakin apakah orang ini masih hidup, sehingga tidak dapat mengatakan orang tersebut selamat. Hal ini menjadi pertimbangan: meskipun tidak mati, orang tersebut bukan bagian dari eksperimen dan harus menghapusnya dari jumlah orang yang berisiko. Jadi, sementara hari kedua akan tersisa 7 orang yang berisiko (karena 3 orang meninggal pada hari pertama), hari ketiga akan tersisa hanya 5 orang, karena 1 orang meninggal dan satu menghilang (disensor) dibandingkan dengan hari kedua. Sama halnya dengan hari pertama, probabilitas bertahan hidup bersifat kumulatif dan selalu mencakup 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()
Dua hari berikutnya dua orang menghilang, jadi diperlukan sensoring. Tidak perlu menghitung sesuatu untuk data yang disensor dalam analisis kelangsungan hidup, karena tidak tahu apakah mereka selamat atau tidak. Pada bagian ini lebih tertuju pada bertahan hidup atau mati, tabel terakhir di bawah ini hanya berisi kasus mati. Pada hari ke-6 tidak ada yang mati atau hilang. Oleh karena itu tidak menghitung apapun untuk hari itu. Orang terakhir dalam eksperimen meninggal pada hari ke-7 . Jadi, “N_died” akan menjadi 1, dan “N_at_risk” akan menjadi 2, karena 1 dari 5 yang tersisa telah meninggal dan 2 telah disensor. Dengan demikian, tabel perhitungan “manual” lengkap akan terlihat seperti ini:
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()
Tapi apa yang terjadi jika mengabaikan penyensoran dan hanya menghitung kemungkinan tidak mati? Nah, karena 4 orang tidak mati pada hari ke 7, kemungkinan bertahan hidup adalah \(\frac{4}{10} = 40\%\) yang hampir dua kali lebih tinggi, dan dengan demikian kami akan memperkirakan secara besar-besaran probabilitas bertahan hidup , dibandingkan dengan probabilitas aktual 0,24 yang menyebabkan sensoring.
Cara menghitung kurva kelangsungan hidup Kaplan-Meier
library(tidyverse) # data wrangling and visualization
library(knitr) # beautifying tables
library(car) # for checking assumptions, e.g. vif etc.
library(broom) # for tidy model output
library(sjPlot) # for plotting results of log.regr.
library(sjmisc) # for plotting results of log.regr.
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)
Fungsi ini Survmenyatukan data “waktu” dan “status” menjadi satu objek “bertahan hidup” , yang memungkinkan untuk memperhitungkan pengamatan yang disensor . Objek ini kemudian dapat digunakan untuk memodelkan probabilitas bertahan hidup dengan fungsi survfit tersebut. Sehingga memodelkan kelangsungan hidup dengan menambahkan “~ 1” ke objek, di mana 1 berarti tidak ada variabel yang dapat mempengaruhi kelangsungan hidup. Objek kelangsungan hidup di sisi kiri tilde adalah variabel respons dan di sisi kanan ~ ( tilde ) adalah prediktor, atau dalam kasus “1” - tidak ada.
survival_model <- survfit(Surv(time, status) ~ 1, data = d)
# small summary
survival_model
di mana:
n - jumlah peserta,
peristiwa - jumlah kematian, yang secara umum disebut peristiwa karena Anda dapat mempelajari jenis “batas waktu” lainnya, seperti kambuhnya penyakit, atau kerusakan pertama mobil,
perkiraan waktu kelangsungan hidup rata-rata daripada rata-rata karena sifat non-parametrik (dijelaskan nanti) dari analisis kelangsungan hidup dan
Interval kepercayaan 95% untuk median waktu bertahan hidup
Lebih banyak informasi dapat dinilai oleh fungsinya summary.
# big summary
summary(survival_model)
summary(survival_model, censored = T)
Contoh selanjutnya misalnya hari ke-8 atau ke-9 dengan probabilitas bertahan hidup setelah hari ke-8 adalah 24%:
summary(survival_model, times = c(8, 9))
# 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 Anda lihat 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 grup
Berikut 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
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 rata-rata 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.
Tes Log-Rank
- Uji statistik Log-Rank non-parametrik (terkadang disebut Mantel-Haenszel) membandingkan median waktu kelangsungan hidup kelompok. Tes Log-Rank mirip dengan (1) uji Wilcoxon-Rank non- parametrik dengan membandingkan median menggunakan peringkat dan (2) uji Chi-kuadrat dengan membandingkan jumlah peristiwa yang diamati dengan jumlah yang diharapkan dengan menghitung statistik Chi-kuadrat:
\[X^2 = \sum_{i = 1}^{g} \frac{(O_i - E_i)^2}{E_i}\]
Jumlah peristiwa yang diharapkan dihitung untuk setiap titik waktu dan setiap grup dibandingkan dengan titik waktu sebelumnya. Nilai-nilai ini kemudian dijumlahkan untuk semua titik waktu untuk memberikan jumlah total peristiwa yang diharapkan di setiap grup.
Sifat tes non-parametrik tidak membuat asumsi tentang distribusi kelangsungan hidup . Jadi, apakah waktu bertahan hidup itu normal (“bell curvy”)? Bisa, tapi tidak harus! Faktanya, data kelangsungan hidup sangat jarang terdistribusi secara normal , tetapi sering miring karena biasanya banyak kejadian awal dan relatif sedikit kejadian akhir .
Hipotesis nol dari uji Log-Rank adalah bahwa tidak ada perbedaan kelangsungan hidup antara kedua kelompok . p-value 0,011 memungkinkan untuk menolak hipotesis nol dan menunjukkan perbedaan median yang signifikan dalam waktu bertahan hidup antara perempuan dan laki-laki.
Tes Log-Rank sangat banyak digunakan untuk membandingkan dua atau lebih kurva bertahan hidup, sehingga Anda benar-benar harus membenarkan penggunaan tes lainnya.
Fungsi survdiff() menghitung uji Log-Rank dan mengembalikan komponen berikut:
banyaknya mata pelajaran pada setiap kelompok.
jumlah kejadian tertimbang yang diamati dalam setiap kelompok.
jumlah kejadian tertimbang yang diharapkan dalam setiap kelompok.
statistik Chi-kuadrat untuk uji kesetaraan
p-value untuk perbedaan kelangsungan hidup di antara kelompok
survdiff(Surv(time, survived) ~ Sex, data = d)
Dari output diatas dapat dilihat bahwa hasil Log-Rank kurang baik. Satu masalah adalah: itu tidak memberikan ukuran efek yang hanya memiliki p-value sebagai ukuran perbedaan. Masalah lain dengan tes Log-Rank (dan metode Kaplan-Meier secara umum) adalah tidak mengizinkan pembaur , mengabaikan faktor/variabel lain.
> 2 grup dan beberapa tes 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)
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 berguna lainnya yang dapat membantu memvisualisasikan data kelangsungan hidup dengan lebih baik adalah:
_break.time.by = 20_pecahkan sumbu x menjadi interval waktu yang diinginkan.
risk.table.y.text.col = TRUE dan risk.table.y.text = FALSE memplot bilah alih-alih nama dalam anotasi teks dari tabel legenda risiko
ncensor.plot = TRUE menampilkan jumlah subjek yang disensor, yang membantu untuk memahami apa 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"
)
Hasil analisis post-hoc mengungkapkan bahwa kelangsungan hidup kelas 1 secara signifikan lebih tinggi dibandingkan dengan kelas 3 dan Kru. Dan terlepas dari fakta bahwa rata-rata kelangsungan hidup penumpang kelas 2 sangat mirip dengan yang pertama, interval kepercayaan dari kelangsungan hidup ini lebar dan banyak tumpang tindih dengan kelompok lain (tidak ditampilkan untuk menghindari kekacauan). Itulah mengapa penumpang kelas 2 umumnya tidak memiliki waktu bertahan hidup yang jauh lebih tinggi meskipun waktu bertahan hidup rata -rata jauh lebih tinggi.
Beberapa kurva bertahan hidup
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 ~ .)
Dari plot di atas adalah bahwa wanita kaya (kelas tiket 1 dan 2) dan (hanya 2) wanita dari kru memiliki kemungkinan 100% untuk bertahan hidup, sedangkan wanita murni di kelas 3 akan mati dengan kepastian yang sama. CI yang sangat tumpang tindih dari kelangsungan hidup manusia menunjukkan bahwa semua manusia pada akhirnya akan mati setelah kecelakaan Titanic.
Kesimpulan
Analisis kelangsungan hidup menyelidiki waktu yang diperlukan untuk suatu peristiwa yang menarik terjadi. Sebagian besar analisis kelangsungan hidup univariat (variabel tunggal) menggunakan plot Kaplan-Meier untuk memvisualisasikan kurva kelangsungan hidup dan uji Log-Rank untuk membandingkan kurva kelangsungan hidup dari dua kelompok atau lebih.
- Keuntungan
Keuntungan krusialkurva 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 Anda, atau mereka merasa jauh lebih baik dan melupakan studi Anda. 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.
- Kerugian
“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 tampilkan 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.
pertimbangkan untuk memotong sumbu x . Mengapa? Nah, 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 tampilkan 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
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 informatifdari 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):
\[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.
\[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 \(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 untuk memodelkan dan memprediksi kelangsungan hidup dan bahaya dari waktu ke waktu, yang merupakan keunggulan utama model eksponensial dibandingkan metode Kaplan-Meier, yang bukan parametrik dan karenanya tidak “dapat dimodelkan”. Namun, non-linieritas seringkali merepotkan dan lebih baik jika menggunakan konsep regresi linier , yang meringkas (meregresi) 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 ini, kita bahkan tidak perlu memahami cara kerja logaritma atau fungsi eksponensial, kita hanya perlu mengetahui bahwa keduanya saling menetralkan. Selain itu, menggunakan “log” (logaritma kedua sisi persamaan di bawah) menghasilkan tiga efek samping yang positif:
- Di sisi kanan persamaan, ini akan mentransfer kurva kita \(-\lambda * t\) menjadi garis \(b_0 + b_1x_1 + ... + b_kx_k\), di mana dapat mencegah dan \(\beta\) koefisien seperti dalam regresi logistik linier biasa
\[Hazard = exp^{b_0 + b_1x_1 + ... + b_kx_k}\]
\[log(Hazard) = b_0 + b_1x_1 + ... + b_kx_k\]
Model bertahan hidup seperti itu sebenarnya adalah model Poisson.
Ini akan membantu untuk terhubung ke model lebih lanjut, seperti model Weibull dan Cox, karena perbedaan di antara mereka terutama terletak pada intersep \(b_0\)
Hal ini akan sangat meningkatkan interpretabilitas, karena Hazard-Ratios (HRs) (itulah yang diberikan oleh model eksponensial) dapat ditafsirkan persis seperti Odds-Ratios (ORs) dari regresi logistik. Sama halnya dengan Odds dalam regresi logistik, Hazard itu sendiri, yang kemungkinannya akan mati SEKARANG , kurang berguna daripada Hazard-Ratios. Hazard-Ratio adalah rasio bahaya seseorang yang terpapar (sakit) dengan seseorang yang tidak terpapar (sehat). Misalnya jika HR = 2, maka risiko kematian seseorang yang terpapar adalah dua kali lipat dibandingkan dengan seseorang yang tidak terpapar.
LS0tDQp0aXRsZTogIlNVUlZJVkFMIE1PREVMUyINCnN1YnRpdGxlOiAiV0VFSyA4Ig0KYXV0aG9yOiAiQnJpZ2l0YSBUaWFyYSBFbGdpdHlhbmEgTWVsYW50aWthICgyMDIwNDkyMDAwMSkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50OiANCiAgICBodG1sX2RvY3VtZW50OiBudWxsDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgdGhlbWU6IHNhbmRzdG9uZQ0KICAgIGNzczogc3R5bGUxLmNzcw0KICAgIGhpZ2hsaWdodDogbW9ub2Nocm9tZQ0KLS0tDQoNCmBgYHtyfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNsYXNzLnNvdXJjZSA9ICJub2NvcHkiLA0KICAgICAgICAgICAgICAgICAgICAgIGNsYXNzLm91dHB1dCA9ICJub2NvcHkiLA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGLA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGKQ0KYGBgDQoNCjxpbWcgc3R5bGU9ImZsb2F0OiByaWdodDsgbWFyZ2luOiAwcHggMTAwcHggMHB4IDBweDsgd2lkdGg6MjUlIiBzcmM9ImZvdG9iYXJ1a3UuanBlZyIvPiANCg0KYGBge3IgbG9nbywgZWNobz1GQUxTRSxmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICczMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImxvZ29tYXRhbmEucG5nIikNCmBgYA0KDQpFbWFpbCAmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsmbmJzcDs6ICBicmlnaXRhLm1lbGFudGlrYUBzdHVkZW50Lm1hdGFuYXVuaXZlcnNpdHkuYWMuaWQgPGJyPg0KUlB1YnMgICZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOzogaHR0cHM6Ly9ycHVicy5jb20vYnJpZ2l0YXRpYXJhZW0vIDxicj4NCkp1cnVzYW4gJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOzogW1N0YXRpc3Rpa2FdKGh0dHBzOi8vbWF0YW5hdW5pdmVyc2l0eS5hYy5pZC8/bHk9YWNhZGVtaWMmYz1zYikgPGJyPg0KQWRkcmVzcyAgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7IDogQVJBIENlbnRlciwgTWF0YW5hIFVuaXZlcnNpdHkgVG93ZXIgPGJyPg0KJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsmbmJzcDsgSmwuIENCRCBCYXJhdCBLYXYsIFJULjEsIEN1cnVnIFNhbmdlcmVuZywgS2VsYXBhIER1YSwgVGFuZ2VyYW5nLCBCYW50ZW4gMTU4MTAuDQoNCioqKioNCg0KIyBTdXJ2aXZhbCBhbmFseXNpcyAxOiBhIGdlbnRsZSBpbnRyb2R1Y3Rpb24gaW50byBLYXBsYW4tTWVpZXIgQ3VydmVzDQoNCkt1cnZhIHN1cnZpdmFsIEthcGxhbiBNZWllciBhZGFsYWgga3VydmEgeWFuZyBtZW5nZ2FtYmFya2FuIGh1YnVuZ2FuIGFudGFyYSBlc3RpbWFzaSBmdW5nc2kgc3Vydml2YWwgcGFkYSB3YWt0dSB0IGRlbmdhbiB3YWt0dSBzdXJ2aXZhbCwNClBhZGEgYmFnaWFuIGluaSBha2FuIG1lbWJhaGFzIG1lbmdlbmFpOg0KDQoxLiBNbWVwZWxhamFyaSBrb25zZXAgcGFsaW5nIHBlbnRpbmcgZGFyaSBhbmFsaXNpcyBrZWxhbmdzdW5nYW4gaGlkdXA6IGt1cnZhIGtlbGFuZ3N1bmdhbiBoaWR1cCwgcGVueWVuc29yYW4gZGFuIHVqaSBsb2ctcmFuaywNCg0KMi4gTWVuZ2hpdHVuZyBzZWNhcmEgbWFudWFsICwgbGFsdSBtZW5naGl0dW5nIGRhbiBtZW5naW50ZXJwcmV0YXNpa2FuIGt1cnZhIGtlbGFuZ3N1bmdhbiBoaWR1cCwgZGFuDQoNCjMuIE1lbmd1amkgcGVyYmVkYWFuIGtlbGFuZ3N1bmdhbiBoaWR1cCBhbnRhcmEgZHVhIGtlbG9tcG9rIGF0YXUgbGViaWgNCg0KYGBge3IgZXZhbD1GQUxTRX0NCmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KbGlicmFyeSh0aWR5dmVyc2UpICAjIGRhdGEgd3JhbmdsaW5nIGFuZCB2aXN1YWxpemF0aW9uDQpsaWJyYXJ5KHNqUGxvdCkgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KGVmZmVjdHMpICAgICMgZm9yIHByb2JhYmlsaXR5IG91dHB1dCBhbmQgcGxvdHMNCmxpYnJhcnkoc3Vydml2YWwpICAgIyBmb3IgY29yZSBzdXJ2aXZhbCBhbmFseXNpcyByb3V0aW5lcw0KbGlicmFyeShzdXJ2bWluZXIpICAjIGZvciBkcmF3aW5nIHN1cnZpdmFsIGN1cnZlcw0KbGlicmFyeShrbml0cikgICAgICAjIGZvciBhIHdvbmRlcmZ1bC1sb29raW5nIHRhYmxlcw0KYGBgDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KZCA8LSB0aWJibGUoDQogIHRpbWUgICA9IGMoMSwxLDEsMiwyLDMsNCw1LDcsMTApLCANCiAgc3RhdHVzID0gYygxLDEsMSwxLDAsMSwwLDAsMSwwKQ0KKQ0KDQpkICU+JSBrYWJsZSgpDQpgYGANCg0KUGFkYSBiYWdpYW4gaW5pIG1lbmdndW5ha2FuIGNvbnRvaCBrYXN1cyBwZW55aW50YXMgVGl0YW5pYzogaGFueWEgMTAgb3JhbmcgZGFuIGhhbnlhIDEwIGhhcmkgZGkgbGF1dCBzZXRlbGFoIGtlY2VsYWthYW4gZGFuIG1lbmdhbmFsaXNpc255YSBkZW5nYW4gbWV0b2RlIHN0YXRpc3RpayBrbGFzaWssIHJlZ3Jlc2kgbGluaWVyIGRhbiBsb2dpc3Rpay4gUHJvYmxlbSB5YW5nIGFrYW4gZGliYWhhcyB5YWl0dSBiZXJhcGEgYmFueWFrIG9yYW5nIGRhbiBiZXJhcGEgbGFtYSBiZXJ0YWhhbiBkYW4gYmVyYXBhIGJhbnlhayB5YW5nIG1lbmluZ2dhbCBwYWRhIGhhcmkgdGVydGVudHUuIFNlaGluZ2dhIG1lbWlsaWtpIGR1YSBwYXJhbWV0ZXIgdXRhbWEgYWRhbGFoICgxKSB3YWt0dSAoZGFsYW0gaGFyaSkgZGFuICgyKSAic3RhdHVzIGtlaGlkdXBhbiIgb3JhbmcsIGRpIG1hbmEgInN0YXR1cyA9IDEiIGJlcmFydGkga2VtYXRpYW4gZGFuICJzdGF0dXMgPSAwIiBiZXJhcnRpIGJ1a2FuIGtlbWF0aWFuLiBEZW5nYW4gc3RhdHVzIG9yYW5nIG1ha2EgZGFwYXQgbWVuZ2hpdHVuZyBvcmFuZyB5YW5nIHNlbGFtYXQgZGFuIHRpZGFrIHNlbGFtYXQgcGFkYSBzZXRpYXAgaGFyaS4NCg0KYGBge3IgZXZhbD1GQUxTRX0NCmdncGxvdChkLCBhZXModGltZSwgZmlsbCA9IGZhY3RvcihzdGF0dXMpKSkrDQogIGdlb21fYmFyKHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoKSkrDQogIHRoZW1lX2J3KCkNCmBgYA0KDQpQYWRhIHBsb3QgZGlhdGFzIGJlbHVtIGRhcGF0IGRpc2ltcHVsa2FuIGRhbGFtIG1lbmphd2FiIHBlcm1hc2FsYWggc2ViZWx1bW55YSBzZWhpbmdnYSBkYXBhdCBkaWxha3VrYW4gYW5hbGlzaXMuDQoNCjEuIOKAnHN0YXR1cyA9IDDigJ0gdGlkYWsgc2VsYWx1IGJlcmFydGkgYmVydGFoYW4gaGlkdXAuIFBlcnRhbWEsIG9yYW5nIHRlcnNlYnV0IG11bmdraW4gdGVyYmF3YSBvbWJhayBkYW4gbWVuZ2hpbGFuZyBzZWhpbmdnYSB0aWRhayBkaWtldGFodWkgc3RhdHVzbnlhLiBNdW5na2luIHN1ZGFoIG1hdGksIG11bmdraW4gZGlzZWxhbWF0a2FuIG9sZWggcGVyYWh1IG5lbGF5YW4gYXRhdSBtYXNpaCBoaWR1cCBkaSBzdWF0dSB0ZW1wYXQgZGkgbGF1dGFuLiBEZW5nYW4gZGVtaWtpYW4gb3JhbmcgeWFuZyBoaWxhbmcgaW5pIHRpZGFrIGRhcGF0IGRpYW5nZ2FwIG1hdGkgYXRhdSBzZWxhbWF0IC4gS2VkdWEsIGppa2EgYmViZXJhcGEgb3JhbmcgYmVydGFoYW4gMTAgaGFyaSwgbWVyZWthIG11bmdraW4gbWF0aSBwYWRhIGhhcmkga2UgMTEgc2VoaW5nZ2Egd2FrdHUgbWVuamFkaSBzYWxhaCBzYXR1IGZha3RvciBwZXJtYXNhbGFoYW4uDQoNCjIuIFRpZGFrIG1lbWlsaWtpIGRhdGEgdW50dWsgc2V0aWFwIDEwIGhhcmkgaW5pLiBLZWxhbmdzdW5nYW4gaGlkdXAgcGFkYSBkYXRhIGluaSBqdWdhIGRhcGF0IGRpcGVuZ2FydWhpIG9sZWgga29uZGlzaSB0dWJ1aCBhdGF1IHBhc29rYW4gbWFrYW4gdW50dWsgYmVydGFoYW4gaGlkdXAgeWFuZyB0aWRhayBkaWtldGFodWkuIERlbWlraWFuIHB1bGEsIHBlbnVydW5hbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGp1Z2EgdGVyYWt1bXVsYXNpIGRhcmkgd2FrdHUga2Ugd2FrdHUgLCB5YW5nIHRpZGFrIGRhcGF0IGRpdGVudHVrYW4gZGVuZ2FuIHBlbmdoaXR1bmdhbiBzZWRlcmhhbmEgYW50YXJhIG9yYW5nIHlhbmcgc2VsYW1hdCBkZW5nYW4gdGlkYWsgc2VsYW1hdCBwYWRhIGhhcmkgdGVydGVudHUuDQoNCkRlbmdhbiBwZXJtYXNhbGFoYW4gZGlhdGFzLCBtYWthIG1lbmVudHVrYW4gbWV0b2RlIHlhbmcgdGVwYXQuDQoNCjEuIE1lbGloYXQgdmFyaWFiZWwgbnVtZXJpayDigJx3YWt0deKAnSwga2l0YSBtdW5na2luIHRlcmdvZGEgdW50dWsgbWVuZ2d1bmFrYW4gcmVncmVzaSBsaW5pZXIgdW50dWsgbWVtb2RlbGthbiB3YWt0dSBiZXJ0YWhhbiBoaWR1cCB1bnR1ayBkdWEga2Vsb21wb2sgc3RhdHVzIHlhbmcgYmVyYmVkYSwgMCAmIDE6DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQptIDwtIGxtKHRpbWUgfiBzdGF0dXMsIGQgJT4lIG11dGF0ZShzdGF0dXMgPSBmYWN0b3Ioc3RhdHVzKSkpDQoNCmxpYnJhcnkoZWZmZWN0cykNCnBsb3QoYWxsRWZmZWN0cyhtKSkNCmBgYA0KDQpEYXJpIHBsb3QgZGlhdGFzIGRhcGF0IGRpbGloYXQgYmFod2EgaW5mb3JtYXNpIHlhbmcgZGltaWxpa2kgdW50dWsgbWVtb2RlbGthbiB3YWt0dSBiZXJ0YWhhbiBoaWR1cCBhZGFsYWggbm9sIGRhbiBzYXR1LiBSYXRhLXJhdGEgd2FrdHUga2VtYXRpYW4gKHN0YXR1cyA9IDEpIDIsNSBoYXJpIGJhbnlhayB5YW5nIG1lbGVzZXQgZGFyaSBpbmZvcm1hc2kuIE1pc2FsbnlhLCBzZXRlbmdhaCBkYXJpIG9yYW5nICgzIG9yYW5nKSBtZW5pbmdnYWwgcGFkYSBoYXJpIHBlcnRhbWEgZGFuIHNlbWFraW4gamF1aCBtZWxhbmdrYWggZGFsYW0gd2FrdHUsIHNlbWFraW4gc2VkaWtpdCBvcmFuZyB5YW5nIG1hdGkuIEphZGksIHdha3R1IGJlcnRhaGFuIGhpZHVwIHRpZGFrIGJlbmFyLWJlbmFyIGxpbmllciBkYW4gdGVudHVueWEgdGlkYWsgYmlzYSBkaWdhbWJhcmthbiBoYW55YSBkZW5nYW4gYW5na2Egbm9sIGRhbiBzYXR1LiBEZW5nYW4gZGVtaWtpYW4sIG1vZGVsIGxpbmllciBrdXJhbmcgY29jb2suDQoNCjIuIFBhZGEgcGVueWVsZXNhaWFuIGRpYXRhcyBoYW55YSBtZW1pbGlraSBub2wgZGFuIHNhdHUgZGkga29sb20gc3RhdHVzLCBtYWthIGRhcGF0IG1lbmdndW5ha2FuIHJlZ3Jlc2kgbG9naXN0aWsga2FyZW5hIGt1cnZhIHByb2JhYmlsaXRhcyB0aWRhayBsaW5pZXIgZGFuIGFrYW4gbWVuYW5na2FwIHRyZW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGRhcmkgd2FrdHUga2Ugd2FrdHUuDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQptIDwtIGdsbShzdGF0dXMgfiB0aW1lLCBkLCBmYW1pbHkgPSBiaW5vbWlhbCkNCg0KbGlicmFyeShzalBsb3QpDQpwbG90X21vZGVsKG0sIHR5cGUgPSAicHJlZCIsIGNpLmx2bCA9IE5BKQ0KYGBgDQoNCkRhcmkgcGVueWVsZXNhaWFuIGRpYXRhcyBtYWthIG1lbWlsaWtpIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgbm9uLWxpbmllciB5YW5nIG1lcnVwYWthbiBwZW5pbmdrYXRhbiBiZXNhciBkaWJhbmRpbmdrYW4gZGVuZ2FuIHJlZ3Jlc2kgbGluaWVyLiBOYW11biBwZW5nYW1hdGFuIGtlIGxpbWEgYmVyc3RhdHVzIDAgcGFkYSBoYXJpIGtlIDIuIEFydGlueWEgb3JhbmcgdGVyc2VidXQgcGFzdGkgYmVydGFoYW4gc2VsYW1hIDIgaGFyaSwgdGV0YXBpIGhpbGFuZyBzZXRlbGFobnlhLiBQcm9iYWJpbGl0YXMgZGFsYW0gcmVncmVzaSBsb2dpc3RpayBha2FuIG1lbmdoaXR1bmcgb3JhbmcgaW5pIHNlYmFnYWkgMTAwJSBzZWxhbWF0IHNldGVsYWggaGFyaSBrZWR1YSBoYW55YSBrYXJlbmEgc3RhdHVzbnlhIGJ1a2FuIOKAnD0x4oCdLCB5YW5nIHNhbGFoIChhdGF1IGJpYXMpLCBrYXJlbmEgdGlkYWsgZGlrZXRhaHVpIGFwYWthaCBvcmFuZyBpbmkgc2VsYW1hdC4gRGVuZ2FuIGRlbWlraWFuLCByZWdyZXNpIGxvZ2lzdGlrIGt1cmFuZyBjb2NvayBkYWxhbSBtZW1wZXJraXJha2FuIGtlbXVuZ2tpbmFuIGtlbGFuZ3N1bmdhbiBoaWR1cC4NCg0KRGFyaSBwZW1iYWhhc2FuIGRpYXRhcyBtYWthIGRhbGFtIG1lbmduYW5hbGlzaXMga2VsYW5nc3VuZ2FuIGhpZHVwIHRpZGFrIGRhcGF0IG1lbmdndW5ha2FuIG1ldG9kZSBkYXNhci4gU2VtZW50YXJhIG1vZGVsIHJlZ3Jlc2kgbGluaWVyIG1lbmdnYW1iYXJrYW4gd2FrdHUsIHRldGFwaSBtZWxld2F0a2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBub24tbGluaWVyLCByZWdyZXNpIGxvZ2lzdGlrIG1lbmFuZ2thcCB0cmVuIG5vbi1saW5pZXIsIHRldGFwaSBtZWxlYmloLWxlYmloa2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cC4gU2ViYWxpa255YSwgYW5hbGlzaXMga2VsYW5nc3VuZ2FuIGhpZHVwIG1lbnllbGVzYWlrYW4ga2VkdWEgbWFzYWxhaCB0ZXJzZWJ1dCwga2FyZW5hIGluaSBtZW1vZGVsa2FuIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgbm9uLWxpbmVhciBkYXJpIHdha3R1IGtlIHdha3R1IHNhbWJpbCBtZW1wZXJoaXR1bmdrYW4gc3ViamVrIHBlbmVsaXRpYW4geWFuZyBoaWxhbmcgeWFuZyBtYXRpIGF0YXUgc2VsYW1hdC4NCg0KIyMgUGVuZ2FudGFyIDogQW5hbGlzaXMgS2VsYW5nc3VuZ2FuIEhpZHVwDQoNCkFuYWxpc2lzIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCBkaXBlcmx1a2FuIGRhbGFtIHN0dWRpIGFwYSBwdW4geWFuZyBtZW55ZWxpZGlraSB3YWt0dSB1bnR1ayBoYXNpbCB0ZXJ0ZW50dSB5YW5nIG1lbmFyaWsgLiBTdHVkaSBrYW5rZXIgZGFsYW0ga2Vkb2t0ZXJhbiBkYW4ga2VnYWdhbGFuIHBlcnRhbWEgbW9iaWwgZGkgYmlkYW5nIHRla25payAoIGZhaWx1cmUgdGltZSBhbmFseXNpcyApIGFkYWxhaCBjb250b2ggeWFuZyBiYWlrLiBIYXNpbCB5YW5nIG1lbmFyaWsgYmlzYSBiZXJ1cGEga2VtYXRpYW4sIHJlbWlzaSBoaW5nZ2Ega2FtYnVoLCBwZXJrZW1iYW5nYW4sIGF0YXUga2VnYWdhbGFuLiBUaXRpayB3YWt0dSB1bnR1ayBtZW5jYXBhaSBoYXNpbCB0ZXJzZWJ1dCB1bXVtbnlhIGRpc2VidXQgcGVyaXN0aXdhIC4gU3l1a3VybGFoLCB0aWRhayBzZW11YSDigJxrZWphZGlhbuKAnSBpdHUgZmF0YWwsIHRhcGkgdGVya2FkYW5nIGJpc2EgbWVuamFkaSBoYXNpbCB5YW5nIG1lbmd1bnR1bmdrYW4gc2VwZXJ0aSBrZWx1YXIgZGFyaSBydW1haCBzYWtpdC4gRGVuZ2FuIGRlbWlraWFuLCBhbmFsaXNpcyBrZWxhbmdzdW5nYW4gaGlkdXAganVnYSBtZXJ1cGFrYW4gaXN0aWxhaCB1bXVtLCBrYXJlbmEgdGlkYWsgaGFueWEgdGVudGFuZyBrZWxhbmdzdW5nYW4gaGlkdXAuDQoNClBlcmlzdGl3YSwgc2ViYWdhaSB0aXRpayB3YWt0dSB0ZXRhcCB0ZXJha2hpciBkaXBlcmx1a2FuIGthcmVuYSB0aWRhayBkYXBhdCBtZW5nYW1hdGkgYXRhdSBiZXJla3NwZXJpbWVuIHNlbGFtYW55YS4gSmlrYSBtZW1wZWxhamFyaSBrYW5rZXIgcGFydS1wYXJ1LCBtYWthIHRpZGFrIGJpc2EgbWVudW5nZ3Ugc2FtcGFpIHBhc2llbiBtZW5pbmdnYWwga2FyZW5hIHNlYmFiIGxhaW4sIG1pc2FsbnlhIGthcmVuYSB0dWEuIEhhbnlhIGtldGlrYSBiZWJlcmFwYSBwYXNpZW4gc2VsYW1hdCBkYXJpIGthbmtlciwgYXRhdSBiZWJlcmFwYSBtb2JpbCB0aWRhayBtb2dvayBwYWRhIHdha3R1IChrZWphZGlhbikgdGVydGVudHUgLCBzZWhpbmdnYSBiaXNhIG1lbmRhcGF0a2FuIHdhd2FzYW4geWFuZyBiZXJoYXJnYS4gTWlzYWxueWEsIGJlcmFwYSBsYW1hIHdha3R1IGRhcmkgYXdhbCBwZW5nb2JhdGFuIGhpbmdnYSBwZXJrZW1iYW5nYW4sIGF0YXUgYmVyYXBhIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBkYXJpIGthbmtlciBwYXJ1IHNldGVsYWggdGVwYXQgMSB0YWh1bj8gU2VsYWluIGl0dSwgaW5pIG1lbWJ1a2Ega2VtdW5na2luYW4gdW50dWsgbWVtYmFuZGluZ2thbiB3YWt0dSBiZXJ0YWhhbiBoaWR1cCBhdGF1IGdhZ2FsIGRpIGFudGFyYSBrZWxvbXBvayB5YW5nIGJlcmJlZGEsIG1pc2FsbnlhIGthbmtlciBwYXJ1LXBhcnUgYW50YXJhIHBlcm9rb2sgZGFuIGJ1a2FuIHBlcm9rb2ssIGF0YXUgd2FrdHUga2VydXNha2FuIGFudGFyYSBtb2JpbCBKZXJtYW4gZGFuIEtvcmVhLg0KDQpKYWRpLCB3YWt0dSBiZXJ0YWhhbiBoaWR1cCBtZW1pbGlraSB0aXRpayBhd2FsIGRhbiB0aXRpayBha2hpci4gVGFwaSBiYWdhaW1hbmEgamlrYSBwYXNpZW4gbWVuZ3VuZHVya2FuIGRpcmkgZGFyaSBwZW5lbGl0aWFuIGthcmVuYSBhbGFzYW4gcHJpYmFkaSwgYXRhdSBtb2JpbCBkaWN1cmkgMSBoYXJpIHNlYmVsdW0gYWNhcmE/IEFrYW5rYWggbWVyZWthICJiZXJ0YWhhbiIgcGFkYSBzYWF0IGFjYXJhIGJlcmxhbmdzdW5nPyBUYXBpIG1lcmVrYSBwYXN0aSBiZXJ0YWhhbiBkYXJpIGF3YWwgcGVuZWxpdGlhbiBzYW1wYWkga2VoaWxhbmdhbiBtZXJla2EuIE5hbXVuIGJhZ2FpbWFuYSBjYXJhbnlhIG1lbWJlZGFrYW4gcGVueWludGFzIHlhbmcg4oCcaGlsYW5n4oCdIGRhcmkgcGVueWludGFzIHlhbmcg4oCcbnlhdGHigJ0/IGtvbnNlcCBtZW55ZW5zb3IgcGFzaWVuIG1lbmphZGkgbGViaWggbXVkYWggZGlndW5ha2FuLiBLYXJlbmEgIHRpZGFrIGRhcGF0IG1lbmdhdGFrYW4gYmFod2Egb3JhbmcgdGVyc2VidXQgdGVsYWggbWVuaW5nZ2FsIGF0YXUgbWFzaWggaGlkdXAsIGhhbnlhIGthcmVuYSBrYW1pIFRJREFLIE1FTUlMSUtJIElORk9STUFTSSBZQU5HIENVS1VQICwga2VkdWEga2VzaW1wdWxhbiB0ZXJzZWJ1dCB0aWRhayB0ZXBhdCAsIGRhbiBkZW5nYW4gZGVtaWtpYW4sIGthbWkgbWVueWVuc29yIG9yYW5nIGluaS4gS29uc2VwIHBlbnllbnNvcmFuIHNhbmdhdCBwZW50aW5nLCBzZWhpbmdnYSBsYXlhayBtZW5kYXBhdCBiYWIgdGFtYmFoYW4uDQoNCiMjIFNlbnNvcmluZw0KDQpTZW5zb3JpbmcgZGlwZXJsdWthbiBrYXJlbmEgd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIHlhbmcgc2ViZW5hcm55YSB0aWRhayBha2FuIGRpa2V0YWh1aSBvbGVoIGJlYmVyYXBhIGluZGl2aWR1LiBBZGEgYmFueWFrIGNhcmEgdW50dWsga2VoaWxhbmdhbiBzdWJqZWsgc3R1ZGk6DQoNCjEuIERhcGF0IGtlaGlsYW5nYW4gc2VzZW9yYW5nIHRhbnBhIGFsYXNhbiwga2V0aWthIGl0dSB0aWRhayBtdW5jdWwgbGFnaQ0KDQoyLiBJbmRpdmlkdSBtdW5na2luIG1lbmdhbGFtaSBwZXJpc3Rpd2EgbGFpbiwgbWlzYWxueWEga2VtYXRpYW4gYXRhdSBrZWNlbGFrYWFuDQoNCjMuIEJhaGthbiBwYXNpZW4geWFuZyBiZXJ0YWhhbiBoaW5nZ2EgYWtoaXIgcGVuZWxpdGlhbiBkYXBhdCBkaXBlcmxha3VrYW4gc2ViYWdhaSBkaXNlbnNvciBrYXJlbmEgd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIHlhbmcgdGlkYWsgZGlrZXRhaHVpIA0KDQpTZW11YSBjb250b2ggZGkgYXRhcyBkaWFuZ2dhcCBzZWJhZ2FpIHNlbnNvcmluZyBrYW5hbiBrYXJlbmEgYXJhaG55YSBkYXJpIGtpcmkga2Uga2FuYW4gcGFkYSBzdW1idSB3YWt0dS4gU2ViYWdpYW4gYmVzYXIgZGF0YSBrZWxhbmdzdW5nYW4gaGlkdXAgZGlzZW5zb3IgZGVuZ2FuIGJlbmFyLiBBZGEgZHVhIGplbmlzIHNlbnNvcmluZyBsYWlubnlhLiBTZW5zb3Iga2lyaSBtdW5jdWwgamlrYSB0aWRhayB0YWh1IGRhcmkgbWFuYSBwZW55YWtpdCBpdHUgYmVybXVsYSwgc2VkYW5na2FuIHNlbnNvciBpbnRlcnZhbCB0ZXJqYWRpIGtldGlrYSB3YWt0dSBwYXN0aSBrZWhpbGFuZ2FuIHBhc2llbiB0aWRhayBkaWtldGFodWksIHRldGFwaSBoYW55YSBqZW5kZWxhIHdha3R1LiBTZW5zb3Jpbmcga2lyaSBkYW4gaW50ZXJ2YWwgamFyYW5nIHRlcmphZGksIHN1bGl0IGRpYW5hbGlzaXMsIHNlcmluZ2thbGkgbWVydXBha2FuIGhhc2lsIGRhcmkgZGVzYWluIHN0dWRpIHlhbmcgYnVydWsuDQoNCiMjIENhcmEgbWVuZ2hpdHVuZyBrdXJ2YSBrZWxhbmdzdW5nYW4gaGlkdXAgS2FwbGFuLU1laWVyIOKAnHNlY2FyYSBtYW51YWzigJ0gDQoNCkJheWFuZ2thbiBoYXJpIGNlcmFoIHlhbmcgZGFtYWkgdGVwYXQgc2ViZWx1bSBrZWNlbGFrYWFuIFRpdGFuaWMgLiBUaWRhayBhZGEgeWFuZyBtZW5pbmdnYWwsIHRldGFwaSBzZW11YSAxMCBvcmFuZyBiZXJpc2lrbyB0aW5nZ2kgKGJhaGF5YSkga2VtYXRpYW4sIG1lcmVrYSBiZWx1bSBtZW5nZXRhaHVpbnlhLiBUZWJhaywgYmVyYXBhIGJhbnlhayBvcmFuZyB5YW5nIG11bmdraW4gYWthbiBtYXRpIHNlaGFyaSBzZWJlbHVtIGtlY2VsYWthYW4gaXR1PyBKYXdhYmFubnlhIGFkYWxhaCAtIG11bmdraW4gbm9sLiBTZWNhcmEgaGFyZmlhaCwga2VtdW5na2luYW4ga2VtYXRpYW4gYWRhbGFoIG5vbCwga2FyZW5hIGtpdGEgdGFodSBrZWNlbGFrYWFuIGl0dSB0aWRhayBha2FuIHRlcmphZGkgc2VoYXJpIHNlYmVsdW0ga2VoYW5jdXJhbiB5YW5nIHNlYmVuYXJueWEuIFVudHVrIG1lbmphd2FiIHBlcnRhbnlhYW4gaW5pIGRlbmdhbiBsZWJpaCB0ZXBhdCwga2l0YSBwZXJsdSBtZW5naW5nYXQgZGVmaW5pc2kgcHJvYmFiaWxpdGFzOiBQcm9iYWJpbGl0YXMgYWRhbGFoIHJhc2lvIGRhcmkgc2VzdWF0dSB5YW5nIHRlcmphZGksIHRlcmhhZGFwIHNlZ2FsYSBzZXN1YXR1IHlhbmcgZGFwYXQgdGVyamFkaS4gSmFkaSwgamlrYSB0aWRhayBhZGEgZGFyaSAxMCBvcmFuZyB5YW5nIG1lbmluZ2dhbCBzZWhhcmkgc2ViZWx1bSBrZWNlbGFrYWFuLCBrZW11bmdraW5hbiBtZW5pbmdnYWwgYWRhbGFoIDAlLCBzZWRhbmdrYW4ga2VtdW5na2luYW4gc2VsYW1hdCBhZGFsYWggMTAwJToNCg0KJCRwcm9iYWJpbGl0eSBcIG9mIFwgZHlpbmcgPSBcZnJhY3swfXsxMH0gPSAwJCQNCg0KJCRwcm9iYWJpbGl0eSBcIG9mIFwgc3Vydml2aW5nID0gXGZyYWN7MTB9ezEwfSA9IDEgID0gMTAwXCUkJA0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KdHJpYmJsZSgNCiAgfnRpbWVfaW5fZGF5cywgfk5fYXRfcmlzaywgfk5fZGllZCwgflBfZHlpbmcsIH5gUF9zdXJ2aXZpbmdgLA0KICAwLCAxMCwgMCwgIjAvMTAgPSAwIiwgIjEwLzEwID0gMSINCikgJT4lIGthYmxlKCkNCmBgYA0KDQpLZW11ZGlhbiwgcGFkYSBoYXJpIGtlY2VsYWthYW4gLCBkaSBtYW5hIHNlbXVhIDEwIG9yYW5nIHNla2FyYW5nIHRhaHUgYmFod2EgbWVyZWthIGJlcmlzaWtvIHRpbmdnaSBtZW5pbmdnYWwsIDMgZGFyaSBtZXJla2EgYmVuYXItYmVuYXIgbWVuaW5nZ2FsLiBQcm9iYWJpbGl0YXMga2VtYXRpYW4gcGFkYSBoYXJpIHBlcnRhbWEgYWRhbGFoIGtlbXVkaWFuICQzLzEwID0gMC4zIFxhcHByb3ggMzBcJSQgZGFuIGtlbXVuZ2tpbmFuIGJlcnRhaGFuIGhpZHVwIGFkYWxhaCAkNy8xMCA9IDAuNyBcYXBwcm94IDcwXCUkLiBTZWhpbmdnYSBrZWxhbmdzdW5nYW4gaGlkdXAganVnYSBkYXBhdCBkaWhpdHVuZyBkYXJpIGtlbXVuZ2tpbmFuIGtlbWF0aWFuICQxLTAuMyA9IDAuNyQuDQoNCiMjIFByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cA0KDQpTYXR1IHBvaW4gcGVudGluZyBkaSBzaW5pIGFkYWxhaCBrZW11bmdraW5hbiB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBiZXJzaWZhdCBrdW11bGF0aWYgLCBhcnRpbnlhIHRlcmFrdW11bGFzaSBkYXJpIGhhcmkga2UgaGFyaS4gQWt1bXVsYXNpIGluaSB0ZXJqYWRpIGRlbmdhbiBtZW5nYWxpa2FuIHByb2JhYmlsaXRhcyBiYXJ1IGJlcnRhaGFuIGhhcmkgcGVydGFtYSAkKDEgLSBcZnJhY3tkX2l9e25faX0pID0gKDEgLSBcZnJhY3szfXsxMH0pID0gNzBcJSQgZGVuZ2FuIHByb2JhYmlsaXRhcyBsYW1hIHVudHVrIGJlcnRhaGFuIGhpZHVwIHNlcGFuamFuZyB3YWt0dSBzZWJlbHVtbnlhLCB5YW5nIGRhbGFtIGthc3VzIGFkYWxhaCBoYXJpIHNlYmVsdW0ga2VjZWxha2FhbiwgYXRhdSAkUyh0X3tpLTF9KSA9IDEwMFwlJDoNCg0KJCRTKHRfaSkgPSBTKHRfe2ktMX0pKigxIC0gXGZyYWN7ZF9pfXtuX2l9KSA9IDEgKiAoMSAtIFxmcmFjezN9ezEwfSkgPSAwLjckJA0KDQpEaSBtYW5hOg0KDQoxLiAkUyh0X3tp4oiSMX0pID0kIHBlbHVhbmcgaGlkdXAgZGkgJHRfe2niiJIxfSQNCg0KMi4gJG5faSA9JCBqdW1sYWggcGFzaWVuIGhpZHVwIHNlc2FhdCBzZWJlbHVtbnlhICR0X2kkDQoNCjMuICRkX2kgPSQganVtbGFoIGtlamFkaWFuIHBhZGEgJHRfaSQNCg0KNC4gJHRfMCA9IDAsIFMoMCkgPTEkDQoNClByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBwYWRhIHdha3R1IHRlcnRlbnR1LCAkUyggdCApJCAsIGJlcnN5YXJhdCBrYXJlbmEgb3JhbmcgdGVyc2VidXQgaGFydXMgYmVydGFoYW4gaGlkdXAgbWVsZWJpaGkgd2FrdHUgdGVydGVudHUgaXR1ICwgbWlzYWxueWEgaGFyaSBub2wgKGl0dWxhaCBzeWFyYXRueWEpIHVudHVrIHRldGFwIGJlcmFkYSBkYWxhbSBwZXJjb2JhYW4gcGFkYSBoYXJpIHBlcnRhbWEuDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQp0cmliYmxlKA0KICB+dGltZV9pbl9kYXlzLCB+Tl9hdF9yaXNrLCB+Tl9kaWVkLCB+UF9keWluZywgfmBQX3N1cnZpdmluZ2AsDQogIDAsIDEwLCAwLCAiMC8xMCA9IDAiLCAgICIxMC8xMCAgICAgID0gMSIsDQogIDEsIDEwLCAzLCAiMy8xMCA9IDAuMyIsICIxICogKDcvMTApID0gMC43IiwNCikgJT4lIGthYmxlKCkNCmBgYA0KDQpIYXJpIGtlZHVhIHNlZGlraXQgbGViaWggbWVuYXJpaywga2FyZW5hIHNhdHUgb3JhbmcgbWVuaW5nZ2FsIGRhbiBzYXR1IGhpbGFuZyBiZWdpdHUgc2FqYSAoc3RhdHVzID0gMCkuIE9yYW5nIHlhbmcgaGlsYW5nIGluaSBrZW11bmdraW5hbiBiZXNhciB0ZXJiYXdhIG9tYmFrIGRhbiBtdWRhaC1tdWRhaGFuIGJpc2EgZGlzZWxhbWF0a2FuLiBCZXNhciBoYXJhcGFubnlhLCBrYXJlbmEgc2VtYWtpbiBqYXVoIG1hbnVzaWEgYmVydGViYXJhbiBkaSBsYXV0YW4sIHNlbWFraW4gYmVzYXIga2VtdW5na2luYW4gc2FsYWggc2F0dW55YSBkaXRlbXVrYW4gZGFsYW0ga2VhZGFhbiBoaWR1cC4gRGFuIHlhbmcgaW5pIGFrYW4gbWVtYnVhdCBkdW5pYSB0YWh1IGJhaHdhIG1hc2loIGFkYSBvcmFuZyBsYWluIGRpIGx1YXIgc2FuYS4gSmFkaSwgdGVybGVwYXMgZGFyaSBrZW55YXRhYW4gYmFod2Egb3JhbmcgaGlsYW5nIHRhbXBhayBidXJ1aywgaXR1IGJpc2EgbWVuamFkaSBoYWwgeWFuZyBiYWlrLiBTZWhpbmdnYSAgdGlkYWsgYmlzYSBtZW5naGl0dW5nIG9yYW5nIHlhbmcgdGVybGV3YXRrYW4gc2ViYWdhaSBtYXRpLg0KDQpUZXRhcGkga2FyZW5hIHBhZGEgZGF0YSB0ZXJzZWJ1dCB0aWRhayB5YWtpbiBhcGFrYWggb3JhbmcgaW5pIG1hc2loIGhpZHVwLCBzZWhpbmdnYSB0aWRhayBkYXBhdCBtZW5nYXRha2FuIG9yYW5nIHRlcnNlYnV0IHNlbGFtYXQuIEhhbCBpbmkgbWVuamFkaSBwZXJ0aW1iYW5nYW46IG1lc2tpcHVuIHRpZGFrIG1hdGksIG9yYW5nIHRlcnNlYnV0IGJ1a2FuIGJhZ2lhbiBkYXJpIGVrc3BlcmltZW4gZGFuIGhhcnVzIG1lbmdoYXB1c255YSBkYXJpIGp1bWxhaCBvcmFuZyB5YW5nIGJlcmlzaWtvLiBKYWRpLCBzZW1lbnRhcmEgaGFyaSBrZWR1YSBha2FuIHRlcnNpc2EgNyBvcmFuZyB5YW5nIGJlcmlzaWtvIChrYXJlbmEgMyBvcmFuZyBtZW5pbmdnYWwgcGFkYSBoYXJpIHBlcnRhbWEpLCBoYXJpIGtldGlnYSBha2FuIHRlcnNpc2EgaGFueWEgNSBvcmFuZywga2FyZW5hIDEgb3JhbmcgbWVuaW5nZ2FsIGRhbiBzYXR1IG1lbmdoaWxhbmcgKGRpc2Vuc29yKSBkaWJhbmRpbmdrYW4gZGVuZ2FuIGhhcmkga2VkdWEuIFNhbWEgaGFsbnlhIGRlbmdhbiBoYXJpIHBlcnRhbWEsIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBiZXJzaWZhdCBrdW11bGF0aWYgZGFuIHNlbGFsdSBtZW5jYWt1cCBwcm9iYWJpbGl0YXMgaGFyaSBzZWJlbHVtbnlhLg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KdHJpYmJsZSgNCiAgfnRpbWVfaW5fZGF5cywgfk5fYXRfcmlzaywgfk5fZGllZCwgflBfZHlpbmcsIH5gUF9zdXJ2aXZpbmdgLA0KICAwLCAxMCwgMCwgIjAvMTAgPSAwIiwgICAgIjEwLzEwICAgICAgID0gMSIsDQogIDEsIDEwLCAzLCAiMy8xMCA9IDAuMyIsICAiMSAqICg3LzEwKSAgPSAwLjciLA0KICAyLCA3LCAgMSwgIjEvNyAgPSAwLjE0IiwgIjAuNyAqICg2LzcpID0gMC42IiwNCiAgMywgNSwgIDEsICIxLzUgID0gMC4yMCIsICIwLjYgKiAoNC81KSA9IDAuNDgiDQopICU+JSBrYWJsZSgpDQpgYGANCg0KRHVhIGhhcmkgYmVyaWt1dG55YSBkdWEgb3JhbmcgbWVuZ2hpbGFuZywgamFkaSBkaXBlcmx1a2FuIHNlbnNvcmluZy4gVGlkYWsgcGVybHUgbWVuZ2hpdHVuZyBzZXN1YXR1IHVudHVrIGRhdGEgeWFuZyBkaXNlbnNvciBkYWxhbSBhbmFsaXNpcyBrZWxhbmdzdW5nYW4gaGlkdXAsIGthcmVuYSB0aWRhayB0YWh1IGFwYWthaCBtZXJla2Egc2VsYW1hdCBhdGF1IHRpZGFrLiBQYWRhIGJhZ2lhbiBpbmkgbGViaWggdGVydHVqdSBwYWRhIGJlcnRhaGFuIGhpZHVwIGF0YXUgbWF0aSwgdGFiZWwgdGVyYWtoaXIgZGkgYmF3YWggaW5pIGhhbnlhIGJlcmlzaSBrYXN1cyBtYXRpLiBQYWRhIGhhcmkga2UtNiB0aWRhayBhZGEgeWFuZyBtYXRpIGF0YXUgaGlsYW5nLiBPbGVoIGthcmVuYSBpdHUgdGlkYWsgbWVuZ2hpdHVuZyBhcGFwdW4gdW50dWsgaGFyaSBpdHUuIE9yYW5nIHRlcmFraGlyIGRhbGFtIGVrc3BlcmltZW4gbWVuaW5nZ2FsIHBhZGEgaGFyaSBrZS03IC4gSmFkaSwgKiJOX2RpZWQiKiBha2FuIG1lbmphZGkgMSwgZGFuICoiTl9hdF9yaXNrIiogYWthbiBtZW5qYWRpIDIsIGthcmVuYSAxIGRhcmkgNSB5YW5nIHRlcnNpc2EgdGVsYWggbWVuaW5nZ2FsIGRhbiAyIHRlbGFoIGRpc2Vuc29yLiBEZW5nYW4gZGVtaWtpYW4sIHRhYmVsIHBlcmhpdHVuZ2FuICJtYW51YWwiIGxlbmdrYXAgYWthbiB0ZXJsaWhhdCBzZXBlcnRpIGluaToNCg0KYGBge3IgZXZhbD1GQUxTRX0NCnRyaWJibGUoDQogIH50aW1lX2luX2RheXMsIH5OX2F0X3Jpc2ssIH5OX2RpZWQsIH5QX2R5aW5nLCB+YFBfc3Vydml2aW5nYCwNCiAgMCwgMTAsIDAsICIwLzEwID0gMCIsICAgICIxMC8xMCAgICAgICAgPSAxIiwNCiAgMSwgMTAsIDMsICIzLzEwID0gMC4zIiwgICIxICogKDcvMTApICAgPSAwLjciLA0KICAyLCA3LCAgMSwgIjEvNyAgPSAwLjE0IiwgIjAuNyAqICg2LzcpICA9IDAuNiIsDQogIDMsIDUsICAxLCAiMS81ICA9IDAuMjAiLCAiMC42ICogKDQvNSkgID0gMC40OCIsDQogIDcsIDIsICAxLCAiMS8yICA9IDAuNTAiLCAiMC40OCAqICgxLzIpID0gMC4yNCINCikgJT4lIGthYmxlKCkNCmBgYA0KDQpUYXBpIGFwYSB5YW5nIHRlcmphZGkgamlrYSBtZW5nYWJhaWthbiBwZW55ZW5zb3JhbiBkYW4gaGFueWEgbWVuZ2hpdHVuZyBrZW11bmdraW5hbiB0aWRhayBtYXRpPyBOYWgsIGthcmVuYSA0IG9yYW5nIHRpZGFrIG1hdGkgcGFkYSBoYXJpIGtlIDcsIGtlbXVuZ2tpbmFuIGJlcnRhaGFuIGhpZHVwIGFkYWxhaCAkXGZyYWN7NH17MTB9ID0gNDBcJSQgeWFuZyBoYW1waXIgZHVhIGthbGkgbGViaWggdGluZ2dpLCBkYW4gZGVuZ2FuIGRlbWlraWFuIGthbWkgYWthbiBtZW1wZXJraXJha2FuIHNlY2FyYSBiZXNhci1iZXNhcmFuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCAsIGRpYmFuZGluZ2thbiBkZW5nYW4gcHJvYmFiaWxpdGFzIGFrdHVhbCAwLDI0IHlhbmcgbWVueWViYWJrYW4gc2Vuc29yaW5nLg0KDQojIyBDYXJhIG1lbmdoaXR1bmcga3VydmEga2VsYW5nc3VuZ2FuIGhpZHVwIEthcGxhbi1NZWllcg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpICAjIGRhdGEgd3JhbmdsaW5nIGFuZCB2aXN1YWxpemF0aW9uDQpsaWJyYXJ5KGtuaXRyKSAgICAgICMgYmVhdXRpZnlpbmcgdGFibGVzDQpsaWJyYXJ5KGNhcikgICAgICAgICMgZm9yIGNoZWNraW5nIGFzc3VtcHRpb25zLCBlLmcuIHZpZiBldGMuDQpsaWJyYXJ5KGJyb29tKSAgICAgICMgZm9yIHRpZHkgbW9kZWwgb3V0cHV0DQpsaWJyYXJ5KHNqUGxvdCkgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KHNqbWlzYykgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KGVmZmVjdHMpICAgICMgZm9yIHByb2JhYmlsaXR5IG91dHB1dCBhbmQgcGxvdHMNCmBgYA0KDQpQYWRhIHJlZ3Jlc2kgbG9naXN0aWsgMSBhZGFsYWgga2VsYW5nc3VuZ2FuIGhpZHVwLCBzZWRhbmdrYW4gZGFsYW0gYW5hbGlzaXMga2VsYW5nc3VuZ2FuIGhpZHVwIDEgYWRhbGFoIGtlbWF0aWFuLiBLZWR1YSwgbWVtYmVkYWthbiBrYXN1cyB5YW5nIGRpc2Vuc29yLCBtaXNhbG55YSBkYXBhdCBtZW5hbmRhaW55YSBkZW5nYW4gdGFuZGEgcGx1cyBkaSBkYXRhIGF0YXUgZGkgcGxvdC4gRGF0YSBkaSBiYXdhaCBpbmkgbWVudW5qdWtrYW4gYmFod2Egb3JhbmcgZGlzZW5zb3IgcGFkYSBoYXJpIGtlIDIrLCA0KywgNSsgZGFuIDEwKy4gSW5zdGFsIGRhbiBtdWF0IHN1cnZpdmFscGFrZXQgdW50dWsgZGFwYXQgbWVuZ2Vrc2VrdXNpIGtvZGUgZGkgYmF3YWggaW5pOg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJzdXJ2aXZhbCIpDQpsaWJyYXJ5KHN1cnZpdmFsKQ0KDQpTdXJ2KHRpbWUgPSBkJHRpbWUsIGV2ZW50ID0gZCRzdGF0dXMpDQpgYGANCg0KRnVuZ3NpIGluaSBTdXJ2bWVueWF0dWthbiBkYXRhICJ3YWt0dSIgZGFuICJzdGF0dXMiIG1lbmphZGkgc2F0dSBvYmplayAiYmVydGFoYW4gaGlkdXAiICwgeWFuZyBtZW11bmdraW5rYW4gdW50dWsgbWVtcGVyaGl0dW5na2FuIHBlbmdhbWF0YW4geWFuZyBkaXNlbnNvciAuIE9iamVrIGluaSBrZW11ZGlhbiBkYXBhdCBkaWd1bmFrYW4gdW50dWsgbWVtb2RlbGthbiBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgZGVuZ2FuIGZ1bmdzaSBfc3VydmZpdF8gdGVyc2VidXQuIFNlaGluZ2dhIG1lbW9kZWxrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGRlbmdhbiBtZW5hbWJhaGthbiAifiAxIiBrZSBvYmplaywgZGkgbWFuYSAxIGJlcmFydGkgdGlkYWsgYWRhIHZhcmlhYmVsIHlhbmcgZGFwYXQgbWVtcGVuZ2FydWhpIGtlbGFuZ3N1bmdhbiBoaWR1cC4gT2JqZWsga2VsYW5nc3VuZ2FuIGhpZHVwIGRpIHNpc2kga2lyaSB0aWxkZSBhZGFsYWggdmFyaWFiZWwgcmVzcG9ucyBkYW4gZGkgc2lzaSBrYW5hbiB+ICggdGlsZGUgKSBhZGFsYWggcHJlZGlrdG9yLCBhdGF1IGRhbGFtIGthc3VzICIxIiAtIHRpZGFrIGFkYS4gDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpzdXJ2aXZhbF9tb2RlbCA8LSBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IDEsIGRhdGEgPSBkKQ0KDQojIHNtYWxsIHN1bW1hcnkNCnN1cnZpdmFsX21vZGVsDQpgYGANCg0KZGkgbWFuYToNCg0KMS4gbiAtIGp1bWxhaCBwZXNlcnRhLA0KDQoyLiBwZXJpc3Rpd2EgLSBqdW1sYWgga2VtYXRpYW4sIHlhbmcgc2VjYXJhIHVtdW0gZGlzZWJ1dCBwZXJpc3Rpd2Ega2FyZW5hIEFuZGEgZGFwYXQgbWVtcGVsYWphcmkgamVuaXMgImJhdGFzIHdha3R1IiBsYWlubnlhLCBzZXBlcnRpIGthbWJ1aG55YSBwZW55YWtpdCwgYXRhdSBrZXJ1c2FrYW4gcGVydGFtYSBtb2JpbCwNCg0KMy4gcGVya2lyYWFuIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCByYXRhLXJhdGEgZGFyaXBhZGEgcmF0YS1yYXRhIGthcmVuYSBzaWZhdCBub24tcGFyYW1ldHJpayAoZGlqZWxhc2thbiBuYW50aSkgZGFyaSBhbmFsaXNpcyBrZWxhbmdzdW5nYW4gaGlkdXAgZGFuDQoNCjQuIEludGVydmFsIGtlcGVyY2F5YWFuIDk1JSB1bnR1ayBtZWRpYW4gd2FrdHUgYmVydGFoYW4gaGlkdXANCg0KTGViaWggYmFueWFrIGluZm9ybWFzaSBkYXBhdCBkaW5pbGFpIG9sZWggZnVuZ3NpbnlhIF9zdW1tYXJ5Xy4NCg0KYGBge3IgZXZhbD1GQUxTRX0NCiMgYmlnIHN1bW1hcnkNCnN1bW1hcnkoc3Vydml2YWxfbW9kZWwpDQpgYGANCg0KYGBge3IgZXZhbD1GQUxTRX0NCnN1bW1hcnkoc3Vydml2YWxfbW9kZWwsIGNlbnNvcmVkID0gVCkNCmBgYA0KDQpDb250b2ggc2VsYW5qdXRueWEgbWlzYWxueWEgaGFyaSBrZS04IGF0YXUga2UtOSBkZW5nYW4gcHJvYmFiaWxpdGFzIGJlcnRhaGFuIGhpZHVwIHNldGVsYWggaGFyaSBrZS04IGFkYWxhaCAyNCU6DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpzdW1tYXJ5KHN1cnZpdmFsX21vZGVsLCB0aW1lcyA9IGMoOCwgOSkpDQpgYGANCg0KYGBge3IgZXZhbD1GQUxTRX0NCiMgaW5zdGFsbC5wYWNrYWdlcygic3Vydm1pbmVyIikNCmxpYnJhcnkoc3Vydm1pbmVyKQ0KDQpnZ3N1cnZwbG90KA0KICBzdXJ2aXZhbF9tb2RlbCwgDQogIGNvbmYuaW50ID0gRkFMU0UsIA0KICBzdXJ2Lm1lZGlhbi5saW5lID0gImh2IiwNCiAgeGxhYiA9ICJEYXlzIiwgDQogIHlsYWIgPSAiU3Vydml2YWwgcHJvYmFiaWxpdHkiLCANCiAgYnJlYWsudGltZS5ieSA9IDEsDQogIHJpc2sudGFibGUgPSBUDQopDQpgYGANCg0KRGFyaSBvdXRwdXQgZGlhdGFzIGRhcGF0IGRpbGloYXQgaW50ZXJ2YWwga2VwZXJjYXlhYW4gKENJKSB1bnR1ayBrZWxhbmdzdW5nYW4gaGlkdXAgc2VoYXJpLWhhcmkgYXRhdSBhbHVyIGJlcnRhaGFuIGhpZHVwLiBDSSBkaXZpc3VhbGlzYXNpa2FuIHNlY2FyYSBkZWZhdWx0LCB0ZXRhcGkgZGFwYXQgZGloYXB1cyAgamlrYSBkaXBlcmx1a2FuIG1lbGFsdWkgX2NvbmYuaW50ID0gRkFMU0VfcGVyaW50YWhfLiBCYXJpcyB0ZXJha2hpciBwYWRhIGtvZGUgZGkgYXRhcyBtZW5hbXBpbGthbiB0YWJlbCDigJxBbmdrYSBiZXJpc2lrb+KAnSwgeWFuZyBkaWhpdHVuZyBzZWNhcmEgbWFudWFsIGRpIGF0YXMuIA0KDQpLdXJ2YSBpbmkgZGlqZWxhc2thbiBzZWNhcmEgaW5kZXBlbmRlbiBvbGVoIGR1YSBpbG11d2FuIGJlcmJlZGEgcGFkYSBzYWF0IGJlcnNhbWFhbi4gRWR3YXJkIEthcGxhbiBkYW4gUGF1bCBNZWllciBrZW11ZGlhbiBtZW5lcmJpdGthbiB0ZW11YW4gbWVyZWthIGJlcnNhbWEgc2ViYWdhaSBlc3RpbWF0b3IgS2FwbGFuLU1laWVyIChLTSkgcGFkYSB0YWh1biAxOTU4IGRhbiBzdXJ2Zml0ZnVuZ3NpIGNvY29rIGRlbmdhbiB0eXBlID0gImthcGxhbi1tZWllciJrdXJ2YSBzZWNhcmEgZGVmYXVsdC4NCg0KU2ViYWdpYW4gYmVzYXIgZGF0YSBrZWxhbmdzdW5nYW4gaGlkdXAgbWVudW5qdWtrYW4gYmFueWFrIHBlcmlzdGl3YSBkaSBhd2FsIGRhbiBqdW1sYWggcGVyaXN0aXdhIHlhbmcgbGViaWggcmVuZGFoIHNlcGFuamFuZyB3YWt0dS4gSGFsIGluaSBtZW1idWF0IGt1cnZhIGtlbGFuZ3N1bmdhbiBoaWR1cCBub24tbGluaWVyIGRhbiBzZWJhZ2lhbiBiZXNhciBkYXRhIGtlbGFuZ3N1bmdhbiBoaWR1cCB0ZXJkaXN0cmlidXNpIG1pcmluZyBhdGF1IHRpZGFrIG5vcm1hbCAodGlkYWsgYmVyYmVudHVrIGxvbmNlbmcpLiBJbmkgYWRhbGFoIGFsYXNhbiBtZW5nYXBhIG1ldG9kZSBLTSBtZW1wZXJraXJha2FuIHdha3R1IGJlcnRhaGFuIGhpZHVwIG1lZGlhbiBkYXJpcGFkYSByYXRhLXJhdGEgc2ViYWdhaSB1a3VyYW4gdGVuZGVuc2kgc2VudHJhbC4gTm9uLWxpbmVhcml0YXMgZGFuICJzdGVwaW5lc3MiIGRhcmkga3VydmEgS00gdGlkYWsgbWVtdW5na2lua2FuIHVudHVrIG1lcmluZ2thcyBkYXRhIG1lbmphZGkgc2F0dSBwYXJhbWV0ZXIgdHVuZ2dhbCAsIG1pc2FsbnlhIGtlbWlyaW5nYW4gLCB5YW5nIG1lbWJ1YXQgbWV0b2RlIEtNIG5vbi1wYXJhbWV0cmlrIC4NCg0KIyMgSW50ZXJwcmV0YXNpIEt1cnZhIEthcGxhbi1NZWllcg0KDQpTdW1idSB4IG1ld2FraWxpIHdha3R1IGRhbGFtIGhhcmksIGRhbiBzdW1idSB5IG1lbnVuanVra2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBhdGF1IHByb3BvcnNpIG9yYW5nIHlhbmcgYmVydGFoYW4gaGlkdXAuIEphZGksIGt1cnZhIGl0dSBzZW5kaXJpIG1lbnVuanVra2FuIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgeWFuZyB0ZXBhdCBkYXJpIHdha3R1IGtlIHdha3R1IC4gUGVudXJ1bmFuIHZlcnRpa2FsIHBhZGEga3VydmEgbWVudW5qdWtrYW4gc2V0aWRha255YSBzYXR1IHBlcmlzdGl3YSAuIEtldGluZ2dpYW4gcGVudXJ1bmFuIHZlcnRpa2FsIG1lbnVuanVra2FuIHBlcnViYWhhbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGt1bXVsYXRpZi4gQmFnaWFuIGhvcml6b250YWwgZGFyaSBrdXJ2YSBtZXdha2lsaSBkdXJhc2kga2VsYW5nc3VuZ2FuIGhpZHVwIHVudHVrIGludGVydmFsIHdha3R1IHRlcnRlbnR1ICwgeWFuZyBkaWFraGlyaSBvbGVoIHBlcmlzdGl3YSBiZXJpa3V0bnlhIChkYW4gcGVudXJ1bmFuIGt1cnZhKS4gS3VydmEgS00gdGVybGloYXQgc2VwZXJ0aSB0YW5nZ2EgYW5laCBkZW5nYW4gYW5hayB0YW5nZ2EgeWFuZyB0aWRhayByYXRhLCBkaSBtYW5hIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBrb25zdGFuIGRpIGFudGFyYSBwZXJpc3Rpd2EsIGRhbiBrYXJlbmFueWEgbWVydXBha2FuIGZ1bmdzaSBsYW5na2FoIHlhbmcgbWVuZ3ViYWggbmlsYWkgaGFueWEgcGFkYSBzYWF0IHNldGlhcCBwZXJpc3Rpd2EuIERlbmdhbiBjYXJhIGluaSBzZXRpYXAgcGFzaWVuIG1lbnl1bWJhbmdrYW4gaW5mb3JtYXNpIGJlcmhhcmdhIHVudHVrIHBlcmhpdHVuZ2FuIHNlbGFtYSBtYXNpaCBoaWR1cC4gT3JhbmcgeWFuZyBkaXNlbnNvciBkaXRhbXBpbGthbiBwZXJzaXMgc2VwZXJ0aSBwYWRhIG9iamVrIGJlcnRhaGFuIGhpZHVwLCBkZW5nYW4gcGx1cyAsIHNlcGVydGkgeWFuZyBBbmRhIGxpaGF0IHBhZGEgaGFyaSBrZS0yLiBOYW11biwgc2ViYWdpYW4gYmVzYXIgcGx1cyB0ZXJsaWhhdCBzZXBlcnRpIGt1dHUgdmVydGlrYWwgLCBrYXJlbmEgdGVybGV0YWsgZGkgYmFnaWFuIGhvcml6b250YWwga3VydmEsIHlhaXR1IGhhcmkgNCBkYW4gNSBUYW5kYSBjZW50YW5nIGRpdGFtcGlsa2FuIHNlY2FyYSBkZWZhdWx0LCB0ZXRhcGkgZGFwYXQgZGl0ZWthbiBtZW5nZ3VuYWthbiBhcmd1bWVuIF9jZW5zb3IgPSBGQUxTRV8uIFRhYmVsIHJpc2lrbyBkaSBiYXdhaCBwbG90IG1lbnVuanVra2FuIGp1bWxhaCBvcmFuZyB5YW5nIGJlcmlzaWtvICwgeWFuZyBzZWJlbmFybnlhIHNlbXVhIG9yYW5nIHlhbmcg4oCcYmVuYXItYmVuYXIgaGlkdXDigJ0gZGFsYW0gcGVyY29iYWFuIHlhbmcgdGlkYWsgbWVuZ2FsYW1pIGtlamFkaWFuIGF0YXUgcGVueWVuc29yYW4gcGFkYSB0aXRpayB3YWt0dSB0ZXJ0ZW50dS4gR2FyaXMgcHV0dXMtcHV0dXMgbWV3YWtpbGkgd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIHJhdGEtcmF0YSB5YW5nIHNlc3VhaSBkZW5nYW4gcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCA1MCUgLiBEYW4gamlrYSBraXRhIG1lbmdhYmFpa2FuIHBlbnllbnNvcmFuIGRhbiBoYW55YSBtZW1wZXJraXJha2FuIG1lZGlhbiB3YWt0dSAoaGFueWEgdW50dWsgb3JhbmcgbWF0aSksIGtpdGEgYWthbiBtZW5kYXBhdGthbiAxLDUgYnVrYW5ueWEgMywgeWFuZyBha2FuIG1lbmluZ2thdGthbiBrZW11bmdraW5hbiBiZXJ0YWhhbiBoaWR1cCBkYXJpIDQ4JSBtZW5qYWRpIDcwJS4gU2VrYWxpIGxhZ2ksIG1lbmdhYmFpa2FuIHBlbnllbnNvcmFuIGFrYW4gbWVuZ2hhc2lsa2FuIGtlbXVuZ2tpbmFuIGJlcnRhaGFuIGhpZHVwIHlhbmcgdGVybGFsdSB0aW5nZ2kga2FyZW5hIGJpYXMga2ViZXJsYW5nc3VuZ2FuIGhpZHVwLg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KZCAlPiUgDQogIGZpbHRlcihzdGF0dXMgPT0gMSkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX3N1cnZpdmFsX3doaXRob3V0X2NlbnNvcmluZyA9IG1lZGlhbih0aW1lKSkNCmBgYA0KDQojIyBNZW1iYW5kaW5na2FuIGtlbGFuZ3N1bmdhbiBoaWR1cCBrZWxvbXBvaw0KDQojIyMgMiBncnVwDQoNCkJlcmlrdXQgbWVuZ2d1bmFrYW4gY29ub3RoIGRhdGEgIDEwMCBvcmFuZyBzZXRlbGFoIGtlY2VsYWthYW4gVGl0YW5pYyBhbGloLWFsaWggMTAgZGFuIGxpaGF0IGtlbGFuZ3N1bmdhbiBoaWR1cCBtZXJla2EgbWVuZ2d1bmFrYW4ga3VydmEgS2FwbGFuLU1laWVyLiBBbmdrYS1hbmdrYSBkYWxhbSB0YWJlbCByaXNpa28gc2VtYWtpbiBiZXNhciBkYW4gc2ViYWlrbnlhIGthbWkgbWVuYW1waWxrYW4gcGVyc2VudGFzZSBiZXJpc2lrbyBkYWxhbSB0YW5kYSBrdXJ1bmcgZGkgZGVrYXQgbmlsYWkgYWJzb2x1dC4gQXJndW1lbiBfcmlzay50YWJsZSA9ICJhYnNfcGN0Il8gbWVtYmFudHUgZGVuZ2FuIGl0dS4gQ29udG9oICJidWxhdCIgZGFyaSAxMDAgb3JhbmcgbWVudW5qdWthbiBwZXJzZW50YXNlIHlhbmcgcGVyc2lzIHNhbWEgZGVuZ2FuIGFuZ2thIGFic29sdXQsIG5hbXVuIGRlbmdhbiBqdW1sYWggImJ1bGF0IiB5YW5nIGxlYmloIHNlZGlraXQgYXRhdSBiZWJlcmFwYSBrZWxvbXBvaywgcGVyc2VudGFzZSBha2FuIG1lbmphZGkgc2FuZ2F0IGJlcmd1bmEuIFJhdGEtcmF0YSB3YWt0dSBiZXJ0YWhhbiBoaWR1cCBvcmFuZy1vcmFuZyBkaSBsYXV0YW4gZGluZ2luIGFkYWxhaCBzZWtpdGFyIDcwIGhhcmkgZGFuIGludGVydmFsIGtlcGVyY2F5YWFubnlhIHRpZGFrIHRlcmxhbHUgbGViYXIuDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpzZXQuc2VlZCg5OTkpICMgZm9yIHJlcHJvZHVjaWJsZSBleGFtcGxlDQpkIDwtIGdnc3RhdHNwbG90OjpUaXRhbmljX2Z1bGwgJT4lIA0KICBtdXRhdGUoc3Vydml2ZWQgPSBpZmVsc2UoU3Vydml2ZWQgPT0gIk5vIiwgMSwgMCksDQogICAgICAgICB0aW1lICAgICA9IHJ1bmlmKG49MjIwMSwgbWluPTEsIG1heD0xMDApKSAlPiUgDQogIHNhbXBsZV9uKDEwMCkgDQoNCm0gPC0gc3VydmZpdChTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IDEsIGRhdGEgPSBkKQ0KDQpnZ3N1cnZwbG90KG0sIA0KICAgICAgICAgICBjb25mLmludCA9IFRSVUUsIA0KICAgICAgICAgICByaXNrLnRhYmxlID0gImFic19wY3QiLCANCiAgICAgICAgICAgc3Vydi5tZWRpYW4ubGluZSA9ICJodiIpDQpgYGANCg0KTWlzYWxueWEsIG1lbWJhbmRpbmdrYW4gcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCBsYWtpLWxha2kgZGVuZ2FuIHBlcmVtcHVhbi4gRGVuZ2FuIG1lbmdnYW50aSBydW11cyBtb2RlbCBkZW5nYW4gbmFtYSB2YXJpYWJlbCBrYXRlZ29yaSB5YW5nIGRpbWluYXRpLCBtaXNhbG55YSBfc2V4Xy4gUGxvdCBiZXJ0YWhhbiBoaWR1cCBrZW11ZGlhbiBtZW5hbXBpbGthbiBrdXJ2YSBLYXBsYW4tTWVpZXIgdW50dWsgc2V0aWFwIGthdGVnb3JpIHZhcmlhYmVsIHlhbmcgYWRhOg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KbSA8LSBzdXJ2Zml0KFN1cnYodGltZSwgc3Vydml2ZWQpIH4gU2V4LCBkYXRhID0gZCkNCg0KZ2dzdXJ2cGxvdChtLCANCiAgICAgICAgICAgcHZhbCA9IFRSVUUsIA0KICAgICAgICAgICBjb25mLmludCA9IFRSVUUsIA0KICAgICAgICAgICByaXNrLnRhYmxlID0gImFic19wY3QiLCANCiAgICAgICAgICAgc3Vydi5tZWRpYW4ubGluZSA9ICJodiIpIA0KYGBgDQoNCiMjIyBJbnRlcnByZXRhc2kgcGVyYmFuZGluZ2FuIGtlbG9tcG9rIG1lbmdndW5ha2FuIDQgdG9sb2sgdWt1cg0KDQoxLiAqcGVyYmFuZGluZ2FuIHZpc3VhbCBrdXJ2YSogOiBoYW55YSBkZW5nYW4gbWVsaWhhdCBkdWEga2Vsb21wb2sgc2VoaW5nZ2EgZGFwYXQgbWVuZ2F0YWthbiBhcGFrYWggYWRhIHBlcmJlZGFhbi4gTWlzYWxueWEsIHBsb3QgbWVuZ3VuZ2thcGthbiBiYWh3YSBwZXJlbXB1YW4gbWVtaWxpa2kga2VtdW5na2luYW4gbGViaWggdGluZ2dpIHVudHVrIGJlcnRhaGFuIGhpZHVwIGhhbXBpciBzZXBhbmphbmcgcGVyaW9kZSB3YWt0dSAoc3VtYnUgeCkuIE5hbXVuLCBhcGFrYWggcGVyYmVkYWFuIGluaSBzaWduaWZpa2FuIHNlY2FyYSBzdGF0aXN0aWsgbWVtZXJsdWthbiB1amkgc3RhdGlzdGlrIGZvcm1hbCAuIERlbmdhbiBtZWxpaGF0IGFuZ2thIGt1cnZhLCBtaXNhbG55YTogcGFkYSBoYXJpIHlhbmcgY2VyYWggZGFuIGluZGFoIHNlYmVsdW0gaGltcGl0YW4sIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBrZWR1YSBrZWxvbXBvayBhZGFsYWggMSwwIChhdGF1IDEwMCUgcGVudW1wYW5nIG1hc2loIGhpZHVwKS4gUGFkYSBoYXJpIGtlIDUwLCBrZW11bmdraW5hbiBiZXJ0YWhhbiBoaWR1cCBiZXRpbmEgYWRhbGFoIGNhLiAwLDc1IChhdGF1IDc1JSkgZGFuIGhhbnlhIGNhLiAwLDY1IChhdGF1IDY1JSkgdW50dWsgbGFraS1sYWtpLiBQYWRhIGhhcmkga2UgNzUsIGtlbGFuZ3N1bmdhbiBoaWR1cCBhZGFsYWggY2EuIDYwIGRhbiBraXJhLWtpcmEgMzAlIHNlc3VhaS4NCg0KMi4gKnBlcmJhbmRpbmdhbiBpbnRlcnZhbCBrZXBlcmNheWFhbiAoQ0kpKiA6IENJIHlhbmcgdHVtcGFuZyB0aW5kaWggbWVudW5qdWtrYW4gYmFod2Ega2VsYW5nc3VuZ2FuIGhpZHVwIGphbnRhbiBkYW4gYmV0aW5hIHRpZGFrIHRlcmxhbHUgYmVyYmVkYSBkYW4gYmlzYSBqYWRpIGthcmVuYSBrZWJldHVsYW4gaGluZ2dhIDgwIGhhcmkuIFNldGVsYWggODAgaGFyaSBDSSBiZXJoZW50aSB0dW1wYW5nIHRpbmRpaCB5YW5nIG1lbnVuanVra2FuIHBlcmJlZGFhbiBzaWduaWZpa2FuIGRhbGFtIGJlcnRhaGFuIGhpZHVwIHBhZGEgdGl0aWsgd2FrdHUgdGVydGVudHUsIGthdGFrYW5sYWggOTAgaGFyaS4NCg0KMy4gKnBlcmtpcmFhbiB3YWt0dSBrZWxhbmdzdW5nYW4gaGlkdXAgcmF0YS1yYXRhIG1lbmd1bmdrYXBrYW4gbGViaWggZGFyaSBpbnRlcnZhbCBrZXBlcmNheWFhbiouIFdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCByYXRhLXJhdGEgdW50dWsgc2V0aWFwIGtlbG9tcG9rIG1ld2FraWxpIHdha3R1IGRpIG1hbmEgcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCBhZGFsYWggNTAlLiBNaXNhbG55YSBrZWxhbmdzdW5nYW4gaGlkdXAgcmF0YS1yYXRhIEJldGluYSBqYXVoIGxlYmloIHRpbmdnaSAoODcgaGFyaSkgZGFyaXBhZGEgamFudGFuICg2NSBoYXJpKS4gUGVyYmVkYWFuIDIzIGhhcmkgeWFuZyBiZWdpdHUgYmVzYXIsIGthcmVuYSBwZXJlbXB1YW4gbWVtaWxpa2kgMjMgaGFyaSBsYWdpIHVudHVrIGRpdGVtdWthbiBvbGVoIGJlYmVyYXBhIGthcGFsIHBlbmFuZ2thcCBpa2FuLiBEaSBzaW5pIHNla2FsaSBsYWdpLCBoYW55YSB0ZXMgeWFuZyBkYXBhdCBtZW5nZXRhaHVpIGRhbiBpdHVsYWggbWVuZ2FwYSB0b2xvayB1a3VyIHRlcmFraGlyIHVudHVrIG1lbWJhbmRpbmdrYW4gZHVhIGtlbG9tcG9rIGFkYWxhaCBwLXZhbHVlIHlhbmcgZGllc3RpbWFzaSBvbGVoIHRlcyBMb2ctUmFuayAoUGV0byBldCBhbCwgMTk3NyksIHlhbmcgc2FuZ2F0IHBlbnRpbmcsIHNlaGluZ2dhIHBlcmx1IGJhYiB0YW1iYWhhbi4NCg0KYGBge3IgZXZhbD1GQUxTRX0NCm0NCmBgYA0KDQojIyMgVGVzIExvZy1SYW5rDQoNCjQuIFVqaSBzdGF0aXN0aWsgTG9nLVJhbmsgbm9uLXBhcmFtZXRyaWsgKHRlcmthZGFuZyBkaXNlYnV0IE1hbnRlbC1IYWVuc3plbCkgbWVtYmFuZGluZ2thbiBtZWRpYW4gd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIGtlbG9tcG9rLiBUZXMgTG9nLVJhbmsgbWlyaXAgZGVuZ2FuICgxKSB1amkgV2lsY294b24tUmFuayBub24tIHBhcmFtZXRyaWsgZGVuZ2FuIG1lbWJhbmRpbmdrYW4gbWVkaWFuIG1lbmdndW5ha2FuIHBlcmluZ2thdCBkYW4gKDIpIHVqaSBDaGkta3VhZHJhdCBkZW5nYW4gIG1lbWJhbmRpbmdrYW4ganVtbGFoIHBlcmlzdGl3YSB5YW5nIGRpYW1hdGkgZGVuZ2FuIGp1bWxhaCB5YW5nIGRpaGFyYXBrYW4gZGVuZ2FuIG1lbmdoaXR1bmcgc3RhdGlzdGlrIENoaS1rdWFkcmF0Og0KDQokJFheMiA9IFxzdW1fe2kgPSAxfV57Z30gXGZyYWN7KE9faSAtIEVfaSleMn17RV9pfSQkDQoNCkp1bWxhaCBwZXJpc3Rpd2EgeWFuZyBkaWhhcmFwa2FuIGRpaGl0dW5nIHVudHVrIHNldGlhcCB0aXRpayB3YWt0dSBkYW4gc2V0aWFwIGdydXAgZGliYW5kaW5na2FuIGRlbmdhbiB0aXRpayB3YWt0dSBzZWJlbHVtbnlhLiBOaWxhaS1uaWxhaSBpbmkga2VtdWRpYW4gZGlqdW1sYWhrYW4gdW50dWsgc2VtdWEgdGl0aWsgd2FrdHUgdW50dWsgbWVtYmVyaWthbiBqdW1sYWggdG90YWwgcGVyaXN0aXdhIHlhbmcgZGloYXJhcGthbiBkaSBzZXRpYXAgZ3J1cC4NCg0KU2lmYXQgdGVzIG5vbi1wYXJhbWV0cmlrIHRpZGFrIG1lbWJ1YXQgYXN1bXNpIHRlbnRhbmcgZGlzdHJpYnVzaSBrZWxhbmdzdW5nYW4gaGlkdXAgLiBKYWRpLCBhcGFrYWggd2FrdHUgYmVydGFoYW4gaGlkdXAgaXR1IG5vcm1hbCAo4oCcYmVsbCBjdXJ2eeKAnSk/IEJpc2EsIHRhcGkgdGlkYWsgaGFydXMhIEZha3RhbnlhLCBkYXRhIGtlbGFuZ3N1bmdhbiBoaWR1cCBzYW5nYXQgamFyYW5nIHRlcmRpc3RyaWJ1c2kgc2VjYXJhIG5vcm1hbCAsIHRldGFwaSBzZXJpbmcgbWlyaW5nIGthcmVuYSBiaWFzYW55YSBiYW55YWsga2VqYWRpYW4gYXdhbCBkYW4gcmVsYXRpZiBzZWRpa2l0IGtlamFkaWFuIGFraGlyIC4NCg0KSGlwb3Rlc2lzIG5vbCBkYXJpIHVqaSBMb2ctUmFuayBhZGFsYWggYmFod2EgdGlkYWsgYWRhIHBlcmJlZGFhbiBrZWxhbmdzdW5nYW4gaGlkdXAgYW50YXJhIGtlZHVhIGtlbG9tcG9rIC4gcC12YWx1ZSAwLDAxMSBtZW11bmdraW5rYW4gdW50dWsgbWVub2xhayBoaXBvdGVzaXMgbm9sIGRhbiBtZW51bmp1a2thbiBwZXJiZWRhYW4gbWVkaWFuIHlhbmcgc2lnbmlmaWthbiBkYWxhbSB3YWt0dSBiZXJ0YWhhbiBoaWR1cCBhbnRhcmEgcGVyZW1wdWFuIGRhbiBsYWtpLWxha2kuDQoNClRlcyBMb2ctUmFuayBzYW5nYXQgYmFueWFrIGRpZ3VuYWthbiB1bnR1ayBtZW1iYW5kaW5na2FuIGR1YSBhdGF1IGxlYmloIGt1cnZhIGJlcnRhaGFuIGhpZHVwLCBzZWhpbmdnYSBBbmRhIGJlbmFyLWJlbmFyIGhhcnVzIG1lbWJlbmFya2FuIHBlbmdndW5hYW4gdGVzIGxhaW5ueWEuDQoNCkZ1bmdzaSBfc3VydmRpZmYoKV8gbWVuZ2hpdHVuZyB1amkgTG9nLVJhbmsgZGFuIG1lbmdlbWJhbGlrYW4ga29tcG9uZW4gYmVyaWt1dDoNCg0KMS4gYmFueWFrbnlhIG1hdGEgcGVsYWphcmFuIHBhZGEgc2V0aWFwIGtlbG9tcG9rLg0KDQoyLiBqdW1sYWgga2VqYWRpYW4gdGVydGltYmFuZyB5YW5nIGRpYW1hdGkgZGFsYW0gc2V0aWFwIGtlbG9tcG9rLg0KDQozLiBqdW1sYWgga2VqYWRpYW4gdGVydGltYmFuZyB5YW5nIGRpaGFyYXBrYW4gZGFsYW0gc2V0aWFwIGtlbG9tcG9rLg0KDQo0LiBzdGF0aXN0aWsgQ2hpLWt1YWRyYXQgdW50dWsgdWppIGtlc2V0YXJhYW4NCg0KNS4gcC12YWx1ZSB1bnR1ayBwZXJiZWRhYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGRpIGFudGFyYSBrZWxvbXBvaw0KDQpgYGB7ciBldmFsPUZBTFNFfQ0Kc3VydmRpZmYoU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBTZXgsIGRhdGEgPSBkKQ0KYGBgDQoNCkRhcmkgb3V0cHV0IGRpYXRhcyBkYXBhdCBkaWxpaGF0IGJhaHdhIGhhc2lsIExvZy1SYW5rIGt1cmFuZyBiYWlrLiBTYXR1IG1hc2FsYWggYWRhbGFoOiBpdHUgdGlkYWsgbWVtYmVyaWthbiB1a3VyYW4gZWZlayB5YW5nIGhhbnlhIG1lbWlsaWtpIHAtdmFsdWUgc2ViYWdhaSB1a3VyYW4gcGVyYmVkYWFuLiBNYXNhbGFoIGxhaW4gZGVuZ2FuIHRlcyBMb2ctUmFuayAoZGFuIG1ldG9kZSBLYXBsYW4tTWVpZXIgc2VjYXJhIHVtdW0pIGFkYWxhaCB0aWRhayBtZW5naXppbmthbiBwZW1iYXVyICwgbWVuZ2FiYWlrYW4gZmFrdG9yL3ZhcmlhYmVsIGxhaW4uDQoNCiMjIyA+IDIgZ3J1cCBkYW4gYmViZXJhcGEgdGVzIExvZy1SYW5rIGJlcnBhc2FuZ2FuIChwb3N0LWhvYykuDQoNClRlcyBMb2ctUmFuayBkYXBhdCBtZW1iYW5kaW5na2FuIGxlYmloIGRhcmkgZHVhIGtlbG9tcG9rIGRhbiBtZW5nYXRha2FuIGFwYWthaCBhZGEgcGVyYmVkYWFuIHlhbmcgc2lnbmlmaWthbiAocC12YWx1ZSA8MCwwNSkgZGkgYW50YXJhIGtlbG9tcG9rLWtlbG9tcG9rIGluaS4gSGFzaWwgcGVuZ3VqaWFuIHlhbmcgZGl0YW1waWxrYW4gcGFkYSB0YWJlbCBkYW4ga3VydmEgS00gZGkgYmF3YWggaW5pIG1lbnVuanVra2FuIGJhaHdhIHRlcmRhcGF0IHBlcmJlZGFhbiBrZWxhbmdzdW5nYW4gaGlkdXAgeWFuZyBzaWduaWZpa2FuIChwLXZhbHVlID0gMCwwMjQpIGRpIGFudGFyYSBrZWxvbXBvayBvcmFuZyBwYWRhIGtlbGFzIHRpa2V0IHlhbmcgYmVyYmVkYS4gTmFtdW4sIHNlcGVydGkga2ViYW55YWthbiB0ZXMgbGFpbm55YSAobWlzYWxueWEgQU5PVkEpLCB0aWRhayBkaXNlYnV0a2FuIGRpIGFudGFyYSBrZWxvbXBvayBtYW5hIHRlcGF0bnlhLiBPbGVoIGthcmVuYSBpdHUgZGlwZXJsdWthbiBhbmFsaXNpcyB0YW1iYWhhbiB5YW5nIG1lbWJhbmRpbmdrYW4gc2VjYXJhIGJlcnBhc2FuZ2FuIHNldGlhcCBrZWxvbXBvayBzYXR1IGRlbmdhbiBrZWxvbXBvayBsYWlubnlhLiBBbmFsaXNpcyBzZW1hY2FtIGl0dSBzZXJpbmcgZGlzZWJ1dCBwb3N0LWhvYy4NCg0KYGBge3IgZXZhbD1GQUxTRX0NCnN1cnZkaWZmKFN1cnYodGltZSwgc3Vydml2ZWQpIH4gQ2xhc3MsIGRhdGEgPSBkKQ0KYGBgDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQptIDwtIHN1cnZmaXQoU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBDbGFzcywgZGF0YSA9IGQpDQoNCmdnc3VydnBsb3QobSwgDQogICAgICAgICAgIHB2YWwgPSBUUlVFLCANCiAgICAgICAgICAgY29uZi5pbnQgPSBGQUxTRSwgDQogICAgICAgICAgIHJpc2sudGFibGUgPSAiYWJzX3BjdCIsIA0KICAgICAgICAgICBzdXJ2Lm1lZGlhbi5saW5lID0gImh2IiwNCiAgICAgICAgICAgbmNlbnNvci5wbG90ID0gVFJVRSwNCiAgICAgICAgICAgYnJlYWsudGltZS5ieSA9IDIwLA0KICAgICAgICAgICByaXNrLnRhYmxlLnkudGV4dC5jb2wgPSBUUlVFLCByaXNrLnRhYmxlLnkudGV4dCA9IEZBTFNFKSANCmBgYA0KDQpUaWdhIGFyZ3VtZW4gcGxvdCBiZXJndW5hIGxhaW5ueWEgeWFuZyBkYXBhdCBtZW1iYW50dSBtZW12aXN1YWxpc2FzaWthbiBkYXRhIGtlbGFuZ3N1bmdhbiBoaWR1cCBkZW5nYW4gbGViaWggYmFpayBhZGFsYWg6DQoNCjEuIF9icmVhay50aW1lLmJ5ID0gMjBfcGVjYWhrYW4gc3VtYnUgeCBtZW5qYWRpIGludGVydmFsIHdha3R1IHlhbmcgZGlpbmdpbmthbi4NCg0KMi4gX3Jpc2sudGFibGUueS50ZXh0LmNvbCA9IFRSVUVfIGRhbiBfcmlzay50YWJsZS55LnRleHQgPSBGQUxTRV8gbWVtcGxvdCBiaWxhaCBhbGloLWFsaWggbmFtYSBkYWxhbSBhbm90YXNpIHRla3MgZGFyaSB0YWJlbCBsZWdlbmRhIHJpc2lrbw0KDQozLiBfbmNlbnNvci5wbG90ID0gVFJVRV8gbWVuYW1waWxrYW4ganVtbGFoIHN1YmplayB5YW5nIGRpc2Vuc29yLCB5YW5nIG1lbWJhbnR1IHVudHVrIG1lbWFoYW1pIGFwYSBwZW55ZWJhYiBhbmdrYSByaXNpa28gbWVuamFkaSBsZWJpaCBrZWNpbDogcGVyaXN0aXdhIGF0YXUgcGVueWVuc29yYW4NCg0KIyMjIFBlbmFmc2lyYW4NCg0KS2VsYW5nc3VuZ2FuIGhpZHVwIHJhdGEtcmF0YSBhZGFsYWggY2EuIDkwIGhhcmkgdW50dWsgcGVudW1wYW5nIGtlbGFzIDEgZGFuIDIsIDU4IGhhcmkgdW50dWsga2VsYXMgMyBkYW4gNjUgaGFyaSB1bnR1ayBhd2FrIFRpdGFuaWMsIG1lbnVuanVra2FuIGtlbGFuZ3N1bmdhbiBoaWR1cCBvcmFuZyBrYXlhIHlhbmcgYmFpaywgZGliYW5kaW5na2FuIGRlbmdhbiB5YW5nIGxhaW4uIERlbmdhbiBwLXZhbHVlIHlhbmcgcmVuZGFoIChwID0gMCwwMjQpIG1lbnVuanVra2FuIGJhaHdhIGFkYSBwZXJiZWRhYW4geWFuZyBzaWduaWZpa2FuIGRhbGFtIGtlbGFuZ3N1bmdhbiBoaWR1cCBhbnRhciBrZWxvbXBvayAuIERpIGFudGFyYW55YSwgaGFueWEgcG9zdC1ob2MgeWFuZyB0YWh1LiBIYXNpbCBkYXJpIGFuYWxpc2lzIExvZy1SYW5rIHBvc3QtaG9jIHRlcnNlYnV0IGRhcGF0IGRpbGFrdWthbiBkZW5nYW4gZnVuZ3NpIF9wYWlyd2lzZV9zdXJ2ZGlmZl8gZGFyaSBfc3Vydm1pbmVyXyBkYW4gZGl0YW1waWxrYW4gZGkgYmF3YWggaW5pLiBTZXBlcnRpIGJpYXNhLCBqaWthIG1lbWlsaWtpIGJhbnlhayBwZXJiYW5kaW5nYW4gc2VoaW5nZ2EgYmVyaXNpa28gbWVtYnVhdCBwZW5lbXVhbiB5YW5nIHNhbGFoIGF0YXUgbWVsZXdhdGthbiBwZW5lbXVhbiBwZW50aW5nLiBKYWRpLCBoYXJ1cyBtZW55ZXN1YWlrYW4gcC12YWx1ZSB1bnR1ayBtZW5ndXJhbmdpIGtlbXVuZ2tpbmFuIHRlcmphZGlueWEga2VzYWxhaGFuLiANCg0KYGBge3IgZXZhbD1GQUxTRX0NCnBhaXJ3aXNlX3N1cnZkaWZmKA0KICBmb3JtdWxhID0gU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBDbGFzcywgZGF0YSA9IGQsIHAuYWRqdXN0Lm1ldGhvZCA9ICJmZHIiDQogICkNCmBgYA0KDQpIYXNpbCBhbmFsaXNpcyBwb3N0LWhvYyBtZW5ndW5na2Fwa2FuIGJhaHdhIGtlbGFuZ3N1bmdhbiBoaWR1cCBrZWxhcyAxIHNlY2FyYSBzaWduaWZpa2FuIGxlYmloIHRpbmdnaSBkaWJhbmRpbmdrYW4gZGVuZ2FuIGtlbGFzIDMgZGFuIEtydS4gRGFuIHRlcmxlcGFzIGRhcmkgZmFrdGEgYmFod2EgcmF0YS1yYXRhIGtlbGFuZ3N1bmdhbiBoaWR1cCBwZW51bXBhbmcga2VsYXMgMiBzYW5nYXQgbWlyaXAgZGVuZ2FuIHlhbmcgcGVydGFtYSwgaW50ZXJ2YWwga2VwZXJjYXlhYW4gZGFyaSBrZWxhbmdzdW5nYW4gaGlkdXAgaW5pIGxlYmFyIGRhbiBiYW55YWsgdHVtcGFuZyB0aW5kaWggZGVuZ2FuIGtlbG9tcG9rIGxhaW4gKHRpZGFrIGRpdGFtcGlsa2FuIHVudHVrIG1lbmdoaW5kYXJpIGtla2FjYXVhbikuIEl0dWxhaCBtZW5nYXBhIHBlbnVtcGFuZyBrZWxhcyAyIHVtdW1ueWEgdGlkYWsgbWVtaWxpa2kgd2FrdHUgYmVydGFoYW4gaGlkdXAgeWFuZyBqYXVoIGxlYmloIHRpbmdnaSBtZXNraXB1biB3YWt0dSBiZXJ0YWhhbiBoaWR1cCByYXRhIC1yYXRhIGphdWggbGViaWggdGluZ2dpLg0KDQojIyMgQmViZXJhcGEga3VydmEgYmVydGFoYW4gaGlkdXANCg0KU2VwZXJ0aSBkaXNlYnV0a2FuIGRpIGF0YXMsIHVqaSBMb2ctUmFuayB0aWRhayBkYXBhdCBkaXRlcmFwa2FuIHBhZGEgYmViZXJhcGEgdmFyaWFiZWwuIE5hbXVuIG1hc2loIGRhcGF0IG1lbXBsb3Qga3VydmEga2VsYW5nc3VuZ2FuIGhpZHVwIGRhcmkgYmViZXJhcGEgdmFyaWFiZWwgdW50dWsgbWVuZGFwYXRrYW4gaW50dWlzaSB1bnR1ayBkYXRhIGluaS4gTWV0b2RlIGxlYmloIGxhbmp1dCwgbWlzYWxueWEgbW9kZWwgQ294LCBkYXBhdCBtZW5nZXN0aW1hc2kgcGVyYmVkYWFuIGRpIGFudGFyYSBiZWJlcmFwYSB2YXJpYWJlbCwgdGV0YXBpIG1ldG9kZSBpbmkgbGViaWgga29tcGxla3MgZGFyaXBhZGEgbWV0b2RlIEtNIGRhbiBkZW5nYW4gZGVtaWtpYW4gYWthbiBkaWJhaGFzIGRpIHBvc3RpbmcgbWVuZGF0YW5nLg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KbTIgPC0gc3VydmZpdCggU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBTZXggKyBDbGFzcywgZGF0YSA9IGQgKQ0KDQpnZ3N1cnYgPC0gZ2dzdXJ2cGxvdChtMiwgY29uZi5pbnQgPSBUUlVFKQ0KICAgDQpnZ3N1cnYkcGxvdCArdGhlbWVfYncoKSArIA0KICB0aGVtZSAobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikrDQogIGZhY2V0X2dyaWQoU2V4IH4gLikNCmBgYA0KDQpEYXJpIHBsb3QgZGkgYXRhcyBhZGFsYWggYmFod2Egd2FuaXRhIGtheWEgKGtlbGFzIHRpa2V0IDEgZGFuIDIpIGRhbiAoaGFueWEgMikgd2FuaXRhIGRhcmkga3J1IG1lbWlsaWtpIGtlbXVuZ2tpbmFuIDEwMCUgdW50dWsgYmVydGFoYW4gaGlkdXAsIHNlZGFuZ2thbiB3YW5pdGEgbXVybmkgZGkga2VsYXMgMyBha2FuIG1hdGkgZGVuZ2FuIGtlcGFzdGlhbiB5YW5nIHNhbWEuIENJIHlhbmcgc2FuZ2F0IHR1bXBhbmcgdGluZGloIGRhcmkga2VsYW5nc3VuZ2FuIGhpZHVwIG1hbnVzaWEgbWVudW5qdWtrYW4gYmFod2Egc2VtdWEgbWFudXNpYSBwYWRhIGFraGlybnlhIGFrYW4gbWF0aSBzZXRlbGFoIGtlY2VsYWthYW4gVGl0YW5pYy4NCg0KIyMgS2VzaW1wdWxhbg0KDQpBbmFsaXNpcyBrZWxhbmdzdW5nYW4gaGlkdXAgbWVueWVsaWRpa2kgd2FrdHUgeWFuZyBkaXBlcmx1a2FuIHVudHVrIHN1YXR1IHBlcmlzdGl3YSB5YW5nIG1lbmFyaWsgdGVyamFkaS4gU2ViYWdpYW4gYmVzYXIgYW5hbGlzaXMga2VsYW5nc3VuZ2FuIGhpZHVwIHVuaXZhcmlhdCAodmFyaWFiZWwgdHVuZ2dhbCkgbWVuZ2d1bmFrYW4gcGxvdCBLYXBsYW4tTWVpZXIgdW50dWsgbWVtdmlzdWFsaXNhc2lrYW4ga3VydmEga2VsYW5nc3VuZ2FuIGhpZHVwIGRhbiB1amkgTG9nLVJhbmsgdW50dWsgbWVtYmFuZGluZ2thbiBrdXJ2YSBrZWxhbmdzdW5nYW4gaGlkdXAgZGFyaSBkdWEga2Vsb21wb2sgYXRhdSBsZWJpaC4NCg0KKi0gS2V1bnR1bmdhbioNCg0KMS4gS2V1bnR1bmdhbiBrcnVzaWFsa3VydmEgcHJvYmFiaWxpdGFzIGJlcnRhaGFuIGhpZHVwIHZzLiBrdXJ2YSByZWdyZXNpIGxvZ2lzdGlrIG1lbXBlcmhpdHVuZ2thbiBkYXRhIHlhbmcgZGlzZW5zb3IsIHlhbmcgdGlkYWsgbWF0aSwgYXRhdSBoaWR1cC4gUmVncmVzaSBsb2dpc3RpayBtZW1wZXJsYWt1a2FuIHNlbXVhIG9yYW5nIHlhbmcgdGlkYWsgbWF0aSBzZWJhZ2FpIG9yYW5nIHlhbmcgc2VsYW1hdCwgaXR1IHNhbGFoLCBoYW55YSBrYXJlbmEga2l0YSB0aWRhayBtZW5nZXRhaHVpIHN0YXR1cyBrZWxhbmdzdW5nYW4gaGlkdXAgb3JhbmcgeWFuZyB0aWRhayB0ZXJqYXdhYi4gUGFzaWVuIG1lbmluZ2dhbGthbiBzdHVkaSBrYXJlbmEgZHVhIGFsYXNhbiB1dGFtYSwgbWVyZWthIG1lcmFzYSBzYW5nYXQgYnVydWssIHNlaGluZ2dhIG1lcmVrYSB0aWRhayBsYWdpIHBlZHVsaSBkZW5nYW4gZWtzcGVyaW1lbiBBbmRhLCBhdGF1IG1lcmVrYSBtZXJhc2EgamF1aCBsZWJpaCBiYWlrIGRhbiBtZWx1cGFrYW4gc3R1ZGkgQW5kYS4gQmViZXJhcGEgcGFzaWVuIG11bmdraW4gaGFueWEgcGluZGFoIGtlIGtvdGEgbGFpbiB0YW5wYSBiZXJrYXRhIGFwYS1hcGEuIE1lbmdoaXR1bmcgc2VtdWFueWEgc2ViYWdhaSBzZWxhbWF0LCBzZXBlcnRpIGhhbG55YSByZWdyZXNpIGxvZ2lzdGlrLCBha2FuIG1lbGViaWgtbGViaWhrYW4ga2VtdW5na2luYW4gYmVydGFoYW4gaGlkdXAgKHN1cnZpdm9yc2hpcCBiaWFzKSBkYW4gbWVyZW1laGthbiBiYWhheWEga2VtYXRpYW4uIE9sZWgga2FyZW5hIGl0dSwgYW5hbGlzaXMga2VsYW5nc3VuZ2FuIGhpZHVwIGxlYmloIHRlcGF0IGRpYmFuZGluZ2thbiBkZW5nYW4gcmVncmVzaSBsb2dpc3Rpaywgc2VtZW50YXJhIGl0dSBtYXNpaCBtZW5hbmdrYXAgdHJlbiBwcm9iYWJpbGl0YXMgbm9uLWxpbmllci4NCg0KMi4gS2V1bmdndWxhbiBsYWlubnlhIGFkYWxhaCBzaWZhdCBub25wYXJhbWV0cmlrIGRhcmkgbWV0b2RlIEthcGxhbi1NZWllciwgeWFpdHUgdGlkYWsgbWVtaWxpa2kgdGVybGFsdSBiYW55YWsgYXN1bXNpLiBTZWJlbmFybnlhIHNhdHUtc2F0dW55YSBhc3Vtc2kgcGVudGluZyBhZGFsYWggYmFod2EgcGVueWVuc29yYW4gaGFydXMgYmVyc2lmYXQgbm9uLWluZm9ybWF0aWYgLiBNZW5nYXBhPyBMZWJpaCBiYW55YWsgaW5mb3JtYXNpIHNlbGFsdSBsZWJpaCBiYWlrLCBidWthbj8gWWEhIFRhcGkgamlrYSBraXRhIHRhaHUgbWVuZ2FwYSBvcmFuZyBtZW5pbmdnYWxrYW4gcGVuZWxpdGlhbiwga2l0YSBiaXNhIG1lbmdndW5ha2FuIGluZm9ybWFzaSBpbmkgc2ViYWdhaSB2YXJpYWJlbCBiYXJ1IGRhbiBtZW1wZWxhamFyaSBwZW5nYXJ1aG55YSB0ZXJoYWRhcCBrZWxhbmdzdW5nYW4gaGlkdXAuIE1ldG9kZSBLTSBha2FuIG1lbmphZGkgdGlkYWsgdGVwYXQsIGthcmVuYSBha2FuIG1lbGV3YXRrYW4gaW5mb3JtYXNpIGluaS4gTmFtdW4sIHNlcmluZ2thbGkgdGlkYWsgdGFodSAodGlkYWsgYWRhIGluZm8pIG1lbmdhcGEgb3Jhbmcga2VsdWFyIChkaXNlbnNvcikuIERhbiBkYWxhbSBoYWwgaW5pIG1ldG9kZSBLTSBtZW1lcmFzIGluZmVyZW5zaSBwYWxpbmcgYmFueWFrIGRhcmkgZGF0YSBub24taW5mb3JtYXRpZiB0ZXJzZWJ1dC4NCg0KKi0gS2VydWdpYW4qDQoNCjEuICJLdXJ2YSIgS2FwbGFuLU1laWVyIHNlYmVuYXJueWEgdGlkYWsgdGVybGloYXQgc2VwZXJ0aSBrdXJ2YS4gQmVybGF3YW5hbiBkZW5nYW4gcmVncmVzaSBsb2dpc3RpayBtZXRvZGUgS2FwbGFuLU1laWVyIHRpZGFrIGRhcGF0IGRpZ2FtYmFya2FuIHNlYmFnYWkgZnVuZ3NpIGhhbHVzIChrdXJ2YSkgZGVuZ2FuIGJlYmVyYXBhIHBhcmFtZXRlciwgbWlzYWxueWEga2VtaXJpbmdhbiBhdGF1IHJhc2lvIG9kZHMgLiBJdHUgc2ViYWJueWEgIG1lbWJ1dHVoa2FuIHRhYmVsIGhhc2lsIGJvZG9oIGF0YXUgZ3JhZmlrLg0KDQoyLiBNZXRvZGUgS2FwbGFuLU1laWVyIHRpZGFrIGRhcGF0IG1lbW9kZWxrYW4gdmFyaWFiZWwgbnVtZXJpayAsIHRldGFwaSBoYW55YSBrYXRlZ29yaWthbC4NCg0KMy4gTWV0b2RlIEthcGxhbi1NZWllciB0aWRhayBkYXBhdCBtZW55ZXJ0YWthbiBiYW55YWsgdmFyaWFiZWwgcGVuamVsYXMgLiBJdHUgYnVydWssIGthcmVuYSBtZW1iYW5kaW5na2FuIGtlbG9tcG9rIGRhbGFtIGhhbCBiZXJ0YWhhbiBoaWR1cCBtdW5na2luIG1lbGV3YXRrYW4gZWZlayBmYWt0b3IgbGFpbiwgeWFuZyBkaWtlbmFsIHNlYmFnYWkga292YXJpYXQgYXRhdSBwZXJhbmN1LCB5YW5nIGJlcnBvdGVuc2kgbWVtZW5nYXJ1aGkgd2FrdHUgYmVydGFoYW4gaGlkdXAga2Vsb21wb2sgdGVydGVudHUuDQoNCipTYXJhbioNCg0KMS4gc2VsYWx1IHRhbXBpbGthbiBrZXRpZGFrcGFzdGlhbiBzdGF0aXN0aWsgZGVuZ2FuIG1lbWFzdWtrYW4gOTUlIENJIGF0YXUvZGFuIG5pbGFpIHAgZGFyaSB1amkgTG9nLVJhbmsuIE1lbmFtcGlsa2FuIENJIHBhZGEgYmViZXJhcGEgdGl0aWsgd2FrdHUgcGVudGluZyBwYWRhIHBsb3QgdW50dWsgc2V0aWFwIGtlbG9tcG9rIHBlcmxha3VhbiB0ZXJrYWRhbmcgbGViaWggamVsYXMgZGFyaXBhZGEgbWVuYW1waWxrYW5ueWEgdW50dWsgc2VtdWEgdGl0aWsgd2FrdHUuIENJIHlhbmcgdGlkYWsgdHVtcGFuZyB0aW5kaWggbWVudW5qdWtrYW4gcGVyYmVkYWFuIHlhbmcgc2lnbmlmaWthbiBhbnRhciBrZWxvbXBvay4NCg0KMi4gcGVydGltYmFuZ2thbiB1bnR1ayBtZW1vdG9uZyBzdW1idSB4IC4gTWVuZ2FwYT8gTmFoLCBtYXRhIHNlY2FyYSBhbGFtaSB0ZXJ0YXJpayBrZSBiYWdpYW4ga2FuYW4gcGxvdCwgZGkgbWFuYSB3YWt0dSBiZXJha2hpci4gTmFtdW4sIGFraGlyIHBsb3QgYmVyaXNpIHBhbGluZyBzZWRpa2l0IGluZm9ybWFzaSBkYW4ga2V0aWRha3Bhc3RpYW4gdGVyYmVzYXIga2FyZW5hIGhhbnlhIHNlZGlraXQgcGVzZXJ0YSB5YW5nIHRlcnNpc2EuIFNlYmVyYXBhIGphdWggd2FrdHUgdW50dWsgbWVtcGVycGFuamFuZyBwbG90PyBUZXJzZXJhaCBrYW11Lg0KDQozLiBzZWxhbHUgdGFtcGlsa2FuIHRhYmVsIHJpc2lrbyB5YW5nIG1lbnVuanVra2FuIGp1bWxhaCBwYXNpZW4gYmViYXMga2VqYWRpYW4gZGFuIG1hc2loIGRhbGFtIHRpbmRhayBsYW5qdXQgZGkgc2V0aWFwIGtlbG9tcG9rIHBlcmxha3VhbiBwYWRhIHRpdGlrIHdha3R1IHlhbmcgcmVsZXZhbi4NCg0KIyBTdXJ2aXZhbCBhbmFseXNpcyAyOiBwYXJhbWV0cmljIHN1cnZpdmFsIG1vZGVscw0KDQpNZXRvZGUgS2FwbGFuLU1laWVyIChLTSkgbm9uLXBhcmFtZXRyaWsgdGlkYWsgZGFwYXQgbWVuZ2dhbWJhcmthbiBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgZGVuZ2FuIGZ1bmdzaSB5YW5nIGhhbHVzLCB5YW5nIGJlcmFydGkgdGlkYWsgZGFwYXQgbWVtcHJlZGlrc2kgYXBhIHB1bi4gTW9kZWwgcGFyYW1ldHJpayAobWlzLiBFa3Nwb25lbnNpYWwsIFdlaWJ1bGwsIGRsbC4pIFNlbGFpbiBpdHUsIGppa2EgbW9kZWwgcGFyYW1ldHJpayBzZXN1YWksIG1vZGVsIHRlcnNlYnV0IGxlYmloIHRlcGF0LCBsZWJpaCBlZmVrdGlmLCBkYW4gbGViaWggaW5mb3JtYXRpZiBkYXJpcGFkYSBLTSBhdGF1IENveC4gTmFtdW4gc2F5YW5nbnlhLCBsYW5na2FoIGluaSBzZXJpbmcgZGl0aW5nZ2Fsa2FuIGthcmVuYSBwZW5nZ3VuYWFuIG1vZGVsIHBhcmFtZXRyaWsgYmVsYWthbmcuIERhbGFtIHBvc3RpbmcgaW5pIGFrYW4gbWVuY29iYSB1bnR1ayBtZW51dHVwIGNlbGFoIGluaS4NCg0KYGBge3IgZXZhbD1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKSAgIyBkYXRhIHdyYW5nbGluZyBhbmQgdmlzdWFsaXphdGlvbg0KbGlicmFyeShzalBsb3QpICAgICAjIGZvciBwbG90dGluZyByZXN1bHRzIG9mIGxvZy5yZWdyLg0KbGlicmFyeShlZmZlY3RzKSAgICAjIGZvciBwcm9iYWJpbGl0eSBvdXRwdXQgYW5kIHBsb3RzDQpsaWJyYXJ5KHN1cnZpdmFsKSAgICMgZm9yIGNvcmUgc3Vydml2YWwgYW5hbHlzaXMgcm91dGluZXMNCmxpYnJhcnkoc3Vydm1pbmVyKSAgIyBmb3IgZHJhd2luZyBzdXJ2aXZhbCBjdXJ2ZXMNCmxpYnJhcnkoZmxleHN1cnYpICAgIyBmb3IgUGFyYW1ldHJpYyBTdXJ2aXZhbCBNb2RlbGxpbmcNCmxpYnJhcnkoa25pdHIpICAgICAgIyBmb3IgYSB3b25kZXJmdWwtbG9va2luZyB0YWJsZXMgDQpgYGANCg0KS2VydWdpYW4gdXRhbWEgZGFyaSBtZXRvZGUgbm9uLXBhcmFtZXRyaWsgS2FwbGFuLU1laWVyIChLTSkgeWFuZyBkaXR1bmp1a2thbiBwYWRhIGdhbWJhciBkaSBhdGFzIGFkYWxhaCB0aWRhayBkYXBhdCBkaWplbGFza2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBkZW5nYW4gZnVuZ3NpIHlhbmcgaGFsdXMsIHlhbmcgYXJ0aW55YSB0aWRhayBkYXBhdCBtZW1wcmVkaWtzaSBhcGFwdW4uIE1vZGVsIHBhcmFtZXRyaWsgKHNlcGVydGkgRWtzcG9uZW5zaWFsLCBXZWlidWxsLCBkbGwuKSBTZWxhaW4gaXR1LCBtb2RlbCBwYXJhbWV0cmlrIGFkYWxhaCBsYW5na2FoIGxvZ2lzIGRhbGFtIHBlcmphbGFuYW4gZGFyaSBLTSBrZSBtb2RlbCBDb3ggc2VtaS1wYXJhbWV0cmlrICwga2FyZW5hIG1lcmVrYSBkZW5nYW4gaW5kYWggbWVuZ2h1YnVuZ2thbiB0aXRpay10aXRpayBhbnRhcmEgbW9kZWwgS00gZGFuIENveCBkYW4gZGVuZ2FuIGRlbWlraWFuIHNhbmdhdCBtZW5pbmdrYXRrYW4gcGVtYWhhbWFuIHRlbnRhbmcgYW5hbGlzaXMga2VsYW5nc3VuZ2FuIGhpZHVwLiBTZWxhaW4gaXR1LCBqaWthIG1vZGVsIHBhcmFtZXRyaWsgc2VzdWFpLCBtb2RlbCB0ZXJzZWJ1dCBsZWJpaCB0ZXBhdCwgbGViaWggZWZla3RpZiwgZGFuIGxlYmloIGluZm9ybWF0aWZkYXJpIEtNIGF0YXUgQ294LiBOYW11biBzYXlhbmdueWEsIGxhbmdrYWggaW5pIHNlcmluZyBkaXRpbmdnYWxrYW4ga2FyZW5hIHBlbmdndW5hYW4gbW9kZWwgcGFyYW1ldHJpayBiZWxha2FuZy4gDQoNCiMjIEFwYWthaCBXYWt0dSBpdHUgVmFyaWFiZWwgYXRhdSBLb25zdGFudGE/DQoNCktlbWF0aWFuIGRhcGF0IGRpZ2FtYmFya2FuIGRlbmdhbiBkdWEgaGFsOiBwZXJpc3Rpd2Ega2VtYXRpYW4gaXR1IHNlbmRpcmkgZGFuIHRpdGlrIHdha3R1IHRlcnRlbnR1IHNhYXQga2VtYXRpYW4gdGVyamFkaS4gRHVhIGhhbCBpbmkgc2VsYWx1IG1lbmdnYW1iYXJrYW4gc2F0dSBwZXJpc3Rpd2EsIGthcmVuYSBzYXR1IGhhbnlhIG1hdGkgc2VrYWxpLiBEZW5nYW4gZGVtaWtpYW4sIHdha3R1IGtlbWF0aWFuIGFrYW4gYmVydmFyaWFzaSBkYW4ganVtbGFoIGtlbWF0aWFuIGFrYW4gYmVydGFtYmFoIHNlaXJpbmcgd2FrdHUsIHlhbmcgYWthbiBtZW5qYWRpa2FuIHdha3R1IGl0dSBzZW5kaXJpIHNlYmFnYWkgdmFyaWFiZWwgLiBCZWdpdHVsYWggYmViZXJhcGEgcGVyaXN0aXdhIGtlbWF0aWFuIHBhZGEgdGl0aWsgd2FrdHUgeWFuZyBiZXJiZWRhIG1lbXVuZ2tpbmthbiB1bnR1ayBtZW5ndW5na2Fwa2FuIGtlbWF0aWFuIGRhbGFtIGR1YSBjYXJhOg0KDQoxLiBNZWxhbHVpIHNlanVtbGFoIGtlamFkaWFuIHlhbmcgYmVyYmVkYSBwZXIgc2F0dWFuIHdha3R1IHRldGFwICwgeWFuZyBzZXJpbmcgZGlzZWJ1dCBSaXNpa28gKEhhemFyZCkgdW50dWsgbWF0aSAsIGF0YXUgaGFueWEgSGF6YXJkICjOuyAtIGxhbWJkYSApLiBJbmkgbWVtYnVhdCBqdW1sYWgga2VqYWRpYW4gbWVuamFkaSB2YXJpYWJlbCwgZGFuIEJhaGF5YSBtZW5qYWRpIHRpbmdrYXQga2VtYXRpYW4gLCBtaXNhbG55YSwgcGVyIGhhcmkuIA0KDQoyLiBNZWxhbHVpIGJlbnRhbmdhbiB3YWt0dSBiZXJsYWx1IHlhbmcgYmVyYmVkYSBwZXIganVtbGFoIHBlcmlzdGl3YSB5YW5nIHRldGFwIC4gSW50ZXJ2YWwgd2FrdHUgYmlhc2FueWEgZGl1a3VyIGhpbmdnYSBwZXJpc3Rpd2EgYmVyaWt1dG55YSB0ZXJqYWRpLiBJbmkgbWVtYnVhdCB3YWt0dSBtZW5qYWRpIHZhcmlhYmVsLg0KDQojIyBQZXJ1YmFoYW4gc3RhYmlsIGRhbGFtIGJhaGF5YSBkYW4ga2VsYW5nc3VuZ2FuIGhpZHVwDQoNCkJheWFuZ2thbiBzZXRpYXAgaGFyaSB0ZXBhdCAzIGRhcmkgMTAgb3JhbmcgbWVuaW5nZ2FsIGRpIGFpciBsYXV0IHlhbmcgZGluZ2luIHNldGVsYWgga2VjZWxha2FhbiBUaXRhbmljLiBJbmkgdGluZ2thdCBrZW1hdGlhbiB5YW5nIGN1a3VwIHN0YWJpbCAsIGF0YXUgQmFoYXlhICwgc2ViZXNhciAzMCUuIEppa2EgYmFoYXlhIHVudHVrIG1hdGkgdGVydXMgdHVtYnVoIGRlbmdhbiBsYWp1IHlhbmcgc2FtYSwgbWFrYSBrZW11bmdraW5hbiB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBha2FuIHRlcnVzIGJlcmt1cmFuZyBkZW5nYW4gbGFqdSB5YW5nIHNhbWEuIERlbmdhbiBkZW1pa2lhbiwgQmFoYXlhIGRhbiBLZWxhbmdzdW5nYW4gSGlkdXAgZGFwYXQgZGlla3NwcmVzaWthbiBzYXR1IHNhbWEgbGFpbi4gU2VjYXJhIGtodXN1cywgQmFoYXlhIGtlbWF0aWFuIGRhcmkgd2FrdHUga2Ugd2FrdHUgZGFwYXQgZGlsaWhhdCBzZWJhZ2FpIEdhZ2FsIGJlcnRhaGFuIGhpZHVwICRGKCB0ICkkIGRhbiBrZWxhbmdzdW5nYW4gaGlkdXAgZGFyaSB3YWt0dSBrZSB3YWt0dSAkUyggdCApJCB5YW5nICBkYXBhdCBkaWxpaGF0IHNlYmFnYWkgSGF6YXJkIG9mIE5PVC1keWluZyAsIGF0YXUgaGFueWEgSGF6YXJkIG5lZ2F0aWYgLCB5YW5nIHNlY2FyYSBtYXRlbWF0aXMgZGFwYXQgZGlueWF0YWthbiBzZWJhZ2FpIHRhbmRhIG1pbnVzIOKAnC3igJ0sIGF0YXUg4oCcMS3igJ0sIGRpIGRlcGFuIEhhemFyZC4gS2VkdWEgZnVuZ3NpIHRlcnNlYnV0IG1lbmdoYXNpbGthbiBnYXJpcyBsdXJ1cywgZGkgbWFuYSBCYWhheWEgdGVydXMgbWVuaW5na2F0IGRhbiBrZWxhbmdzdW5nYW4gaGlkdXAgdGVydXMgbWVudXJ1biAocGxvdCBkaSBiYXdhaCk6DQoNCiQkUyh0KSA9IDEgLSBIYXphcmQgKiB0JCQNCg0KUGVuaW5na2F0YW4gYXRhdSBwZW51cnVuYW4geWFuZyBzdGFiaWwgZGFsYW0gYmFoYXlhIGF0YXUga2VsYW5nc3VuZ2FuIGhpZHVwIHNlcGVydGkgaXR1IGFnYWsgdGlkYWsgYWxhbWksIHRpZGFrIHJlYWxpc3Rpcy4gRGFsYW0gbWVtcGVya2lyYWthbiBrZW1hdGlhbiBkYXBhdCBkaWthdGFrbiBzdWxpdC4gQmFoYXlhIGJpYXNhbnlhIG1lbmluZ2thdCBzZWNhcmEgZWtzcG9uZW5zaWFsLCBtaXNhbG55YSBkYWxhbSBrYXN1cyBrZWxhcGFyYW4sIGF0YXUgbWVudXJ1biBzZWNhcmEgZWtzcG9uZW5zaWFsLCBtaXNhbG55YSBkYWxhbSBrYXN1cyBwYW5kZW1pIHNldGVsYWggdmFrc2luIGRpdGVtdWthbi4NCg0KIyMgUGVydWJhaGFuIGVrc3BvbmVuc2lhbCBwb3NpdGlmIGRhbGFtIGJhaGF5YSBkYW4ga2VsYW5nc3VuZ2FuIGhpZHVwDQoNClBpa2lya2FuIHRlbnRhbmcga2VsYXBhcmFuIHNlamVuYWsuIFNlbWFraW4gbGFtYSBrb25kaXNpIGtlbGFwYXJhbiwgc2VtYWtpbiB0aW5nZ2kga2VtdW5na2luYW4gKHJpc2lrbykgbWF0aS4gUGxvdCBraXJpIGRpIGJhd2FoIG1lbnVuanVra2FuIHBlcmtlbWJhbmdhbiBzZXBlcnRpIGl0dSwgZGkgbWFuYSBiYWhheWEga2VtYXRpYW4gJEYoIHQgKSQgZGlueWF0YWthbiBkYWxhbSBwcm9iYWJpbGl0YXMga2VjaWwgcGFkYSBhd2FsbnlhIChiZWJlcmFwYSBrZW1hdGlhbiksIHRldGFwaSB0dW1idWggc2VjYXJhIGVrc3BvbmVuc2lhbCBkZW5nYW4gd2FrdHUgKHNlbWFraW4gYmFueWFrIGtlbWF0aWFuKS4gU2F5YSBzdWthIG1lbnllYnV0IHRyZW4gc2VwZXJ0aSBpdHUgc2ViYWdhaSBwZXJ1YmFoYW4gZWtzcG9uZW5zaWFsIHlhbmcgcG9zaXRpZiwgYXRhdSBtZW1wZXJjZXBhdC4gImV4cCIgZGFsYW0gcnVtdXMga2lyaSBkaSBiYXdhaCBhZGFsYWggc2VtdWEgeWFuZyBkaXBlcmx1a2FuIHVudHVrIG1lcmVuY2FuYWthbiB0cmVuIHRlcnNlYnV0Lg0KDQpTZWthbGkgbGFnaSwga2FyZW5hIGtlbGFuZ3N1bmdhbiBoaWR1cCBkYXBhdCBkaWxpaGF0IHNlYmFnYWkgYmFoYXlhIG5lZ2F0aWYgZGFwYXQgbWVueWF0YWthbiBrZWxhbmdzdW5nYW4gaGlkdXAgJFMoIHQgKSQgZGVuZ2FuIGhhbnlhIG1lbmdndW5ha2FuIHRhbmRhIG1pbnVzIChhdGF1IOKAnDEt4oCdKSBkaSBkZXBhbiBIYXphcmQuIFBsb3QgZGkgc2ViZWxhaCBrYW5hbiBtZW5hbXBpbGthbiBoYXNpbCBkYXJpIGZ1bmdzaSBiZXJ0YWhhbiBoaWR1cCB0ZXJzZWJ1dC5KaWthIGJhaGF5YSBrZW1hdGlhbiByZW5kYWggZGkgYXdhbCAid2FrdHUiLCBtYWthIGtlbXVuZ2tpbmFuIGJlcnRhaGFuIGhpZHVwIHRpbmdnaS4gRGkgYWtoaXIgIndha3R1IiwgS2VsYW5nc3VuZ2FuIEhpZHVwIHR1cnVuIHNlY2FyYSBla3Nwb25lbnNpYWwga2FyZW5hIHBlbmluZ2thdGFuIEJhaGF5YSBzZWNhcmEgZWtzcG9uZW5zaWFsLg0KDQokJFModCkgPSAxIC0gZXhwXntIYXphcmQgKiB0fSQkDQoNCiMjIFBlcnViYWhhbiBla3Nwb25lbnNpYWwgbmVnYXRpZiBkYWxhbSBiYWhheWEgZGFuIGtlbGFuZ3N1bmdhbiBoaWR1cA0KDQpOYW11biwgZGFsYW0gYmViZXJhcGEga2FzdXMsIGxlYmloIGJhbnlhayBvcmFuZyBtZW5pbmdnYWwgcGFkYSBhd2FsICJ3YWt0dSIsIGRpIG1hbmEgdGluZ2thdCBrZW1hdGlhbiBtZW51cnVuIGRhcmkgd2FrdHUga2Ugd2FrdHUuIFBpa2lya2FuIHRlbnRhbmcgcGFuZGVtaSwgYXRhdSBrZWNlbGFrYWFuIGJlc2FyLiBQZXJ1YmFoYW5ueWEgbWFzaWggZWtzcG9uZW5zaWFsLCBkYW4gbWVudWp1IGtlIGFyYWggeWFuZyBzYW1hOiBuYWlrLCBkYWxhbSBrYXN1cyBCYWhheWEsIGRhbiB0dXJ1biwgZGFsYW0ga2FzdXMgYmVydGFoYW4gaGlkdXAuIE5hbXVuLCBwZXJ1YmFoYW4gZWtzcG9uZW5zaWFsIGFnYWsgdGVyYmFsaWsgKG1lbWJ1bmdrdWspLiBTYXlhIHN1a2EgbWVueWVidXRueWEgc2ViYWdhaSBwZXJ1YmFoYW4gZWtzcG9uZW5zaWFsIHlhbmcgbmVnYXRpZiwgYXRhdSBtZWxhbWJhdC4NCg0KU2VwZXJ0aSAicGVtYmVuZ2tva2FuIGtlIGRhbGFtIiBkYXBhdCBkaWNhcGFpIGRlbmdhbiAiLSIgbWludXMgc2luZyBkaSBkZXBhbiBIYXphcmQgZGFuIGZ1bmdzaSBla3Nwb25lbnNpYWwgaXR1IHNlbmRpcmkgKHBlcnNhbWFhbiBraXJpIGRhbiBnYW1iYXIgZGkgYmF3YWgpLiBNaW51cyBpbmkgdGlkYWsgbWVuZ2dhbWJhcmthbiBoYXphcmQgbmVnYXRpZiwgc2VwZXJ0aSBwYWRhIGNvbnRvaCBkaSBhdGFzLiBJdHUgaGFueWEgbWVuZ3ViYWgga3VydmEgZGFyaSBwZXJjZXBhdGFuIGtlIHBlcmxhbWJhdGFuLiBVbnR1ayBtZW5kYXBhdGthbiBrZWxhbmdzdW5nYW4gaGlkdXAgdW50dWsgZnVuZ3NpIGluaSBzZXBlcnRpIHBhZGEgY29udG9oIGRpIGF0YXMsIGhhcnVzIG1lbmdndW5ha2FuICItIiAoYXRhdSAiMS0iKSBkaSBkZXBhbiBzZWx1cnVoIGVrc3ByZXNpIGhhemFyZCBla3Nwb25lbnNpYWwuIE1lbmFyaWtueWEsIGR1YSB0YW5kYSBtaW51cyBkaSBkZXBhbiAiZXhwIiBkYWxhbSBydW11cyBTdXJ2aXZhbCBzYWxpbmcgbWVuZXRyYWxrYW4gZGFuIG1lbmphZGkgbmlsYWkgdGFtYmFoLCB5YW5nIG1lbnlpc2FrYW4gZGVuZ2FuICRleHBeey1IYXphcmQgKiB0fSQNCg0KJCRTKHQpID0gMSAtICggLSBleHBeey1IYXphcmQgKiB0fSkgPSBleHBeey1IYXphcmQgKiB0fSQkDQoNCiMjIE1lbWJhbmd1biBNb2RlbCBFa3BvbmVuc2lhbA0KDQpTZWphayBmdW5nc2kgYmVydGFoYW4gaGlkdXAgJFMoIHQgKSQgbWVudW5qdWtrYW4gcHJvYmFiaWxpdGFzIGJlcnRhaGFuIGhpZHVwIG1lbGV3YXRpIHRpdGlrIHdha3R1IHRlcnRlbnR1ICwNCg0KJCRTKHQpID0gUChUID4gdCkkJA0KDQpkYW4gZnVuZ3NpIGVrc3BvbmVuc2lhbCAkRiggdCApJCBtZW51bmp1a2thbiBwcm9iYWJpbGl0YXMgRmFpbGVkLXN1cnZpdmFsIG1lbGV3YXRpIHRpdGlrIHdha3R1IHRlcnRlbnR1ICwNCg0KJCRGKHQpID0gUChUIFxsZXEgdCkgPSAxIC0gZXhwXnstSGF6YXJkICogdH0kJA0KDQpmdW5nc2kgYmVydGFoYW4gaGlkdXAga2VtdWRpYW4gZGFwYXQgZGlueWF0YWthbiBkYWxhbSBiZW50dWsgZnVuZ3NpIHRpZGFrIGJlcnRhaGFuIGhpZHVwIChla3Nwb25lbnNpYWwpOg0KDQokJFModCkgPSBQKFQgPiB0KSA9IDEgLSBQKFQgXGxlcSB0KSA9IDEgLSBGKHQpID0gMSAtIFsxIC0gZXhwXnstSGF6YXJkICogdH1dID0gZXhwXnstSGF6YXJkICogdH0kJA0KDQpTZWhpbmdnYSBmdW5nc2kgc3Vydml2YWwgeWFuZyBtZW51bmp1a2thbiBsYWp1IHBlbnVydW5hbiBhZGFsYWggZnVuZ3NpIGZsaXBwZWQgaGF6YXJkIHlhbmcgbWVudW5qdWtrYW4gbGFqdSBrZW5haWthbi4gRGVuZ2FuIGRlbWlraWFuLCBkYXBhdCBtZW51bGlzIHVsYW5nICRTKCB0ICkkIHNlYmFnYWk6DQoNCiQkUyh0KSA9IGV4cF57LSBIYXphcmQgKiB0fSA9IGV4cF57LSBcbGFtYmRhKiB0fSQkDQoNCmRpIG1hbmEgLUhhemFyZCBkYW4gd2FrdHUgYWRhbGFoIGR1YSBwYXJhbWV0ZXIgeWFuZyBtZW5nZ2FtYmFya2FuIHBlcnViYWhhbiBla3Nwb25lbnNpYWwgIGRhbGFtIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCwgaXR1bGFoIHNlYmFibnlhIG1vZGVsIHNlcGVydGkgaXR1IG1lbWlsaWtpIG5hbWEgLSBtb2RlbCBla3Nwb25lbnNpYWwgcGFyYW1ldHJpayAuIERhbiBrYXJlbmEgSGF6YXJkIGFkYWxhaCBuZWdhdGl2ZSAsIGRhbiBmdW5nc2kgZWtzcG9uZW5zaWFsIHRpZGFrIGxpbmllciAoYWxpYXMuIGN1cnZ5ICkgLSBtb2RlbCBrZWx1YXIgbWVuZ2hhc2lsa2FuIGt1cnZhIGVrc3BvbmVuc2lhbCBuZWdhdGlmIChsaWhhdCBkaSBiYXdhaCkuIFRpbmdrYXQgcGVudXJ1bmFuIHlhbmcgbXVsdXMgc2VwZXJ0aSBpdHUgbWVuZ2dhbWJhcmthbiBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgamF1aCBsZWJpaCBiYWlrIGRhcmlwYWRhIG1ldG9kZSBLYXBsYW4tTWVpZXIsIHlhbmcgc2VjYXJhIHRpYmEtdGliYSAoc2VjYXJhIGJlcnRhaGFwKSBtZW51cnVua2FuIHByb2JhYmlsaXRhcyBoYW55YSBzZXRlbGFoIHN1YXR1IHBlcmlzdGl3YSwgc2FtYmlsIG1lbmphZ2EgcHJvYmFiaWxpdGFzIHRldGFwIGtvbnN0YW4gZGkgYW50YXJhIHBlcmlzdGl3YSB0ZXJzZWJ1dC4NCg0KIyMgQ2FyYSBtZW5naGl0dW5nIG1vZGVsIHBhcmFtZXRyaWsNCg0KYGBge3IgZXZhbD1GQUxTRX0NCmxpYnJhcnkoZmxleHN1cnYpICAgICMgZm9yIFBhcmFtZXRyaWMgU3Vydml2YWwgTW9kZWxsaW5nDQoNCmV4IDwtIGZsZXhzdXJ2cmVnKFN1cnYodGltZSwgc3RhdHVzKSB+IDEsIGRhdGEgPSBkMiwgZGlzdD0iZXhwb25lbnRpYWwiKQ0Kd2UgPC0gZmxleHN1cnZyZWcoU3Vydih0aW1lLCBzdGF0dXMpIH4gMSwgZGF0YSA9IGQyLCBkaXN0PSJ3ZWlidWxsIikNCg0KZ2dzdXJ2cGxvdCgNCiAgZXgsIA0KICBjb25mLmludCA9IEZBTFNFLCANCiAgc3Vydi5tZWRpYW4ubGluZSA9ICJodiIsDQogIHhsYWIgPSAiRGF5cyIsIA0KICB5bGFiID0gIlN1cnZpdmFsIHByb2JhYmlsaXR5IiwgDQogIGJyZWFrLnRpbWUuYnkgPSAxLA0KICByaXNrLnRhYmxlID0gRg0KKQ0KYGBgDQoNClBhcmFtZXRlciBrdXJ2YSAkLVxsYW1iZGEgKiB0JCBtZW11bmdraW5rYW4gIHVudHVrIG1lbW9kZWxrYW4gZGFuIG1lbXByZWRpa3NpIGtlbGFuZ3N1bmdhbiBoaWR1cCBkYW4gYmFoYXlhIGRhcmkgd2FrdHUga2Ugd2FrdHUsIHlhbmcgbWVydXBha2FuIGtldW5nZ3VsYW4gdXRhbWEgbW9kZWwgZWtzcG9uZW5zaWFsIGRpYmFuZGluZ2thbiBtZXRvZGUgS2FwbGFuLU1laWVyLCB5YW5nIGJ1a2FuIHBhcmFtZXRyaWsgZGFuIGthcmVuYW55YSB0aWRhayAiZGFwYXQgZGltb2RlbGthbiIuIE5hbXVuLCBub24tbGluaWVyaXRhcyBzZXJpbmdrYWxpIG1lcmVwb3RrYW4gZGFuIGxlYmloIGJhaWsgamlrYSBtZW5nZ3VuYWthbiBrb25zZXAgcmVncmVzaSBsaW5pZXIgLCB5YW5nIG1lcmluZ2thcyAobWVyZWdyZXNpKSBiYW55YWsgYW5na2EgbWVuamFkaSBiZWJlcmFwYSBhbmdrYSwgc2VwZXJ0aSBpbnRlcnNlcCAkXGJldGFfMCQgZGFuIGtlbWlyaW5nYW4gJFxiZXRhXzEkLiBVbnR1bmdueWEsIGt1cnZhIG5vbi1saW5pZXIgZGFwYXQgZGVuZ2FuIG11ZGFoIOKAnGRpbGluaWVya2Fu4oCdIG1lbGFsdWkgbG9nYXJpdG1hIG5hdHVyYWwuIFVudHVrIGluaSwga2l0YSBiYWhrYW4gdGlkYWsgcGVybHUgbWVtYWhhbWkgY2FyYSBrZXJqYSBsb2dhcml0bWEgYXRhdSBmdW5nc2kgZWtzcG9uZW5zaWFsLCBraXRhIGhhbnlhIHBlcmx1IG1lbmdldGFodWkgYmFod2Ega2VkdWFueWEgc2FsaW5nIG1lbmV0cmFsa2FuLiBTZWxhaW4gaXR1LCBtZW5nZ3VuYWthbiAibG9nIiAobG9nYXJpdG1hIGtlZHVhIHNpc2kgcGVyc2FtYWFuIGRpIGJhd2FoKSBtZW5naGFzaWxrYW4gdGlnYSBlZmVrIHNhbXBpbmcgeWFuZyBwb3NpdGlmOg0KDQoNCjEuIERpIHNpc2kga2FuYW4gcGVyc2FtYWFuLCBpbmkgYWthbiBtZW50cmFuc2ZlciBrdXJ2YSBraXRhICQtXGxhbWJkYSAqIHQkIG1lbmphZGkgZ2FyaXMgJGJfMCArIGJfMXhfMSArIC4uLiArIGJfa3hfayQsIGRpIG1hbmEgZGFwYXQgbWVuY2VnYWggZGFuICRcYmV0YSQga29lZmlzaWVuIHNlcGVydGkgZGFsYW0gcmVncmVzaSBsb2dpc3RpayBsaW5pZXIgYmlhc2ENCg0KJCRIYXphcmQgPSBleHBee2JfMCArIGJfMXhfMSArIC4uLiArIGJfa3hfa30kJA0KDQokJGxvZyhIYXphcmQpID0gYl8wICsgYl8xeF8xICsgLi4uICsgYl9reF9rJCQNCg0KTW9kZWwgYmVydGFoYW4gaGlkdXAgc2VwZXJ0aSBpdHUgc2ViZW5hcm55YSBhZGFsYWggbW9kZWwgUG9pc3Nvbi4gDQoNCjIuIEluaSBha2FuIG1lbWJhbnR1ICB1bnR1ayB0ZXJodWJ1bmcga2UgbW9kZWwgbGViaWggbGFuanV0LCBzZXBlcnRpIG1vZGVsIFdlaWJ1bGwgZGFuIENveCwga2FyZW5hIHBlcmJlZGFhbiBkaSBhbnRhcmEgbWVyZWthIHRlcnV0YW1hIHRlcmxldGFrIHBhZGEgaW50ZXJzZXAgJGJfMCQNCg0KMy4gSGFsIGluaSBha2FuIHNhbmdhdCBtZW5pbmdrYXRrYW4gaW50ZXJwcmV0YWJpbGl0YXMsIGthcmVuYSBIYXphcmQtUmF0aW9zIChIUnMpIChpdHVsYWggeWFuZyBkaWJlcmlrYW4gb2xlaCBtb2RlbCBla3Nwb25lbnNpYWwpIGRhcGF0IGRpdGFmc2lya2FuIHBlcnNpcyBzZXBlcnRpIE9kZHMtUmF0aW9zIChPUnMpIGRhcmkgcmVncmVzaSBsb2dpc3Rpay4gU2FtYSBoYWxueWEgZGVuZ2FuIE9kZHMgZGFsYW0gcmVncmVzaSBsb2dpc3RpaywgSGF6YXJkIGl0dSBzZW5kaXJpLCB5YW5nIGtlbXVuZ2tpbmFubnlhIGFrYW4gbWF0aSBTRUtBUkFORyAsIGt1cmFuZyBiZXJndW5hIGRhcmlwYWRhIEhhemFyZC1SYXRpb3MuIEhhemFyZC1SYXRpbyBhZGFsYWggcmFzaW8gYmFoYXlhIHNlc2VvcmFuZyB5YW5nIHRlcnBhcGFyIChzYWtpdCkgZGVuZ2FuIHNlc2VvcmFuZyB5YW5nIHRpZGFrIHRlcnBhcGFyIChzZWhhdCkuIE1pc2FsbnlhIGppa2EgSFIgPSAyLCBtYWthIHJpc2lrbyBrZW1hdGlhbiBzZXNlb3JhbmcgeWFuZyB0ZXJwYXBhciBhZGFsYWggZHVhIGthbGkgbGlwYXQgZGliYW5kaW5na2FuIGRlbmdhbiBzZXNlb3JhbmcgeWFuZyB0aWRhayB0ZXJwYXBhci4=