UTS SURVIVAL MODEL

Tugas UTS


*Kontak : \(\downarrow\)*
Email
Instagram https://www.instagram.com/m_naufalardiansyah/
RPubs https://rpubs.com/muhamad_naufal/

Survival analysis 1: A gentle Introduction into Kaplan-Meier Curves

Analisis waktu Survival diperlukan dalam penelitian apa pun yang menyelidiki waktu untuk hasil tertentu yang menarik. Studi kanker dalam bidang kedokteran dan kegagalan pertama mobil dalam bidang teknik (analisis waktu kegagalan) adalah contoh yang baik. Hasil yang diinginkan dapat berupa kematian, remisi untuk kambuh, perkembangan, atau kegagalan. Titik waktu untuk mencapai hasil tersebut umumnya disebut peristiwa.Tidak semua “event” berakibat fatal, tetapi kadang-kadang bahkan bisa menjadi hasil yang menguntungkan seperti keluar dari rumah sakit. Dan dengan demikian, analisis ketahanan hidup juga merupakan istilah umum, karena ini bukan hanya tentang kelangsungan hidup.

library(tidyverse)  # data wrangling and visualization
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.1     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(sjPlot)     # for plotting results of log.regr.
## Learn more about sjPlot with 'browseVignettes("sjPlot")'.
library(effects)    # for probability output and plots
## Loading required package: carData
## lattice theme set by effectsTheme()
## See ?effectsTheme for details.
library(survival)   # for core survival analysis routines
library(survminer)  # for drawing survival curves
## Loading required package: ggpubr
## 
## Attaching package: 'survminer'
## 
## The following object is masked from 'package:survival':
## 
##     myeloma
library(knitr)      # for a wonderful-looking tables

Dalam materi ini akan dipelajari :

  • Konsep-konsep terpenting dalam analisis survival: kurva survival, penyensoran, dan uji log-rank,
  • Menghitung secara manual, kemudian mengkomputasi dan menginterpretasikan kurva survival, dan
  • Menguji perbedaan kelangsungan hidup antara dua atau lebih kelompok, misalnya perempuan vs laki-laki

Mengapa harus mempelajari analisis survival?

library(tidyverse)

d <- tibble(
  time   = c(1,1,1,2,2,3,4,5,7,10), 
  status = c(1,1,1,1,0,1,0,0,1,0)
)

d %>% kable()
time status
1 1
1 1
1 1
2 1
2 0
3 1
4 0
5 0
7 1
10 0

Pada subbab ini dalam menjawab pertanyaan mengapa harus mempelajari analisis survival dapat menggunakan contoh kasus penyintas Titanic: Dimana hanya 10 orang dan hanya 10 hari di laut setelah kecelakaan dan menganalisisnya dengan metode statistik klasik, regresi linier dan logistik. Problem yang akan dibahas yaitu berapa banyak orang dan berapa lama bertahan dan berapa banyak yang meninggal pada hari tertentu. Sehingga memiliki dua parameter utama adalah (1) waktu (dalam hari) dan (2) “status kehidupan” orang, di mana “status = 1” berarti kematian dan “status = 0” berarti bukan kematian. Dengan status orang maka dapat menghitung orang yang selamat dan tidak selamat pada setiap hari.

ggplot(d, aes(time, fill = factor(status)))+
  geom_bar(position = position_dodge())+
  theme_bw()

Pada plot diatas belum dapat disimpulkan dalam menjawab permasalah sebelumnya sehingga dapat dilakukan analisis.

  1. “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.

  2. Tidak memiliki data untuk setiap 10 hari ini. Kelangsungan hidup pada data ini juga dapat dipengaruhi oleh kondisi tubuh atau pasokan makan untuk bertahan hidup yang tidak diketahui. Demikian pula, penurunan probabilitas kelangsungan hidup juga terakumulasi dari waktu ke waktu , yang tidak dapat ditentukan dengan penghitungan sederhana antara orang yang selamat dengan tidak selamat pada hari tertentu.

Dengan permasalahan diatas, dapat menentukan metode yang tepat.

  1. Melihat variabel numerik “waktu”, mungkin dapat tergoda untuk menggunakan regresi linier untuk memodelkan waktu bertahan hidup untuk dua kelompok status yang berbeda, 0 & 1:
m <- lm(time ~ status, d %>% mutate(status = factor(status)))

library(effects)
plot(allEffects(m))

Namun, ketika membuat plot hasil modelnya, dapat disadari bahwa ada sesuatu yang tidak beres di sana. Semua informasi yang dimiliki untuk memodelkan waktu bertahan hidup adalah angka nol dan satu. Dan waktu rata-rata kematian (status = 1) sebesar 2,5 hari melewatkan banyak informasi. Sebagai contoh, setengah dari orang-orang (3 orang) meninggal pada hari pertama! Dan semakin jauh melangkah ke depan, semakin sedikit orang yang meninggal, yang dapat dilihat pada plot hitungan pertama di atas. Jadi, waktu bertahan hidup tidak benar-benar linier dan tentu saja tidak dapat digambarkan hanya dengan angka nol dan satu! Sehingga disini model linier tampaknya tidak berguna.

  1. Karena disini memiliki angka nol dan satu pada kolom status, dapat menggunakan regresi logistik, Terutama karena kurva probabilitasnya tidak linier dan akan menangkap tren kelangsungan hidup dari waktu ke waktu.
m <- glm(status ~ time, d, family = binomial)

library(sjPlot)
plot_model(m, type = "pred", ci.lvl = NA)
## $time

Sekarang dapat dilihat bahwa probabilitas kelangsungan hidup non-linear, yang merupakan peningkatan besar dibandingkan dengan regresi linier. Namun, pengamatan kelima memiliki status 0 pada hari ke-2. Ini berarti bahwa orang tersebut pasti bertahan hidup selama 2 hari, tetapi hilang setelahnya. Probabilitas dalam regresi logistik akan menghitung orang ini sebagai 100% selamat setelah hari kedua hanya karena statusnya tidak “=1”, yang salah (atau bias), karena tidak diketahui apakah orang ini selamat. Dengan demikian, regresi logistik melebih-lebihkan probabilitas kelangsungan hidup dan oleh karena itu juga merupakan alat yang tidak tepat untuk menganalisis data kelangsungan hidup.

Jadi tidak dapat dilakukan analisis data Survival dengan metode klasik. Sehingga membutuhkan metode analisis survival.

Sementara model regresi linier menggambarkan waktu, tetapi melewatkan probabilitas kelangsungan hidup non-linier, regresi logistik menangkap tren non-linier, tetapi melebih-lebihkan probabilitas kelangsungan hidup. Sebaliknya, analisis survival memecahkan kedua masalah tersebut, karena model ini memodelkan probabilitas kelangsungan hidup non-linear dari waktu ke waktu sambil memperhitungkan subjek penelitian yang hilang, baik yang meninggal maupun yang selamat.

Kematian bukanlah satu-satunya pilihan! Atau: “Apakah yang dimaksud dengan peristiwa?”

Analisis waktu survival diperlukan dalam penelitian apa pun yang menyelidiki waktu untuk hasil tertentu yang menarik. Penelitian kanker dalam bidang kedokteran dan kegagalan pertama mobil dalam bidang teknik (analisis waktu kegagalan) adalah contoh yang baik. Hasil yang diinginkan dapat berupa kematian, remisi untuk kambuh, perkembangan, atau kegagalan. Titik waktu untuk mencapai hasil tersebut umumnya disebut peristiwa. sehingga, tidak semua “event” berakibat fatal , tetapi kadang-kadang bahkan bisa menjadi hasil yang menguntungkan seperti keluar dari rumah sakit. Dan dengan demikian, analisis survival juga merupakan istilah umum, karena ini bukan hanya tentang kelangsungan hidup.

Kejadian, sebagai titik waktu yang tetap diperlukan karena tidak dapat dilakukan pengamatan atau bereksperimen selamanya. Jika dipelajari kanker paru-paru, maka tidak bisa menunggu sampai pasien meninggal karena penyebab lain, misalnya karena sudah tua. Hanya ketika beberapa pasien selamat dari kanker, atau beberapa mobil tidak rusak pada waktu tertentu (peristiwa), kita bisa mendapatkan wawasan yang berharga. Misalnya, berapa lama waktu dari awal pengobatan hingga perkembangannya, atau berapa probabilitas untuk bertahan hidup dari kanker paru-paru setelah tepat 1 tahun? Selain itu, hal ini membuka kemungkinan untuk membandingkan waktu kelangsungan hidup atau kegagalan di antara kelompok yang berbeda, misalnya kanker paru-paru antara perokok dan non-perokok, atau waktu kerusakan antara mobil Jerman dan Korea.

Penyensoran

Sensoring diperlukan karena waktu kelangsungan hidup yang sebenarnya tidak akan diketahui oleh beberapa individu. Ada banyak cara untuk kehilangan subjek studi:

  1. Dapat kehilangan seseorang tanpa alasan, ketika itu tidak muncul lagi

  2. Individu mungkin mengalami peristiwa lain, misalnya kematian atau kecelakaan

  3. Bahkan pasien yang bertahan hingga akhir penelitian dapat diperlakukan sebagai disensor karena waktu kelangsungan hidup yang tidak diketahui

Semua contoh di atas dianggap sebagai sensoring kanan karena arahnya dari kiri ke kanan pada sumbu waktu. Sebagian besar data kelangsungan hidup disensor dengan benar. Ada dua jenis sensoring lainnya. Sensor kiri muncul jika tidak tahu dari mana penyakit itu bermula, sedangkan sensor interval terjadi ketika waktu pasti kehilangan pasien tidak diketahui, tetapi hanya jendela waktu. Sensoring kiri dan interval jarang terjadi, sulit dianalisis, seringkali merupakan hasil dari desain studi yang buruk.

Cara menghitung kurva survival Kaplan-Meier “secara manual” langkah demi langkah

Dengan membayangkan hari yang cerah dan damai tepat sebelum kecelakaan Titanic terjadi. Tidak ada yang meninggal, tetapi semua 10 orang berisiko tinggi (bahaya) meninggal, hanya saja mereka belum mengetahuinya. Dapat menebak berapa banyak orang yang mungkin akan meninggal sehari sebelum kecelakaan. Jawabannya adalah - mungkin nol. Secara harfiah, kemungkinan kematian adalah nol, karena kita tahu bahwa kecelakaan tidak akan terjadi sehari sebelum tabrakan yang sebenarnya. Untuk menjawab pertanyaan ini dengan lebih tepat, kita perlu mengingat definisi probabilitas: Probabilitas adalah rasio dari sesuatu yang terjadi, terhadap segala sesuatu yang dapat terjadi. Jadi, jika tidak ada seorang pun dari 10 orang yang meninggal sehari sebelum kecelakaan, maka probabilitas kematiannya adalah 0%, sedangkan probabilitas selamat adalah 100%:

\[ probability \ of \ dying = \frac{0}{10} = 0\]

\[ probability \ of \ surviving = \frac{10}{10} = 1 = 100\%\]

Untuk representasi yang lebih baik, mari kita letakkan semua angka dalam satu tabel:

tribble(
  ~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
  0, 10, 0, "0/10 = 0", "10/10 = 1"
) %>% kable()
time_in_days N_at_risk N_died P_dying P_surviving
0 10 0 0/10 = 0 10/10 = 1

Kemudian, pada hari kecelakaan , di mana semua 10 orang sekarang tahu bahwa mereka berisiko tinggi meninggal, 3 dari mereka benar-benar meninggal. Probabilitas kematian pada hari pertama adalah kemudian \(3/10 = 0.3 \approx 30\%\) dan kemungkinan bertahan hidup adalah \(7/10 = 0.7 \approx 70\%\). Sehingga kelangsungan hidup juga dapat dihitung dari kemungkinan kematian \(1-0.3 = 0.7\).

Peluang Survival

Satu momen penting di sini adalah bahwa kemungkinan untuk bertahan hidup bersifat kumulatif, yang berarti terakumulasi dari hari ke hari. Akumulasi ini terjadi melalui mengalikan probabilitas baru untuk bertahan hidup pada hari ke-1 \((1 - \frac{d_i}{n_i}) = (1 - \frac{3}{10}) = 70\%\) dengan probabilitas lama untuk bertahan hidup sepanjang waktu sebelumnya, yang dalam kasus kami adalah sehari sebelum kecelakaan, atau - hari ke-nol \(S(t_{i-1}) = 100\%\):

\[ S(t_i) = S(t_{i-1})*(1 - \frac{d_i}{n_i}) = 1 * (1 - \frac{3}{10}) = 0.7 \]

Dimana,

  • \(S(t_{i−1})\) = probabilitas untuk hidup di \(t_{i−1}\)
  • \(n_i\) = jumlah pasien yang masih hidup sebelum \(t_i\)
  • \(d_i\) = Jumlah kejadian saat \(t_i\)
  • \(t_0\) = 0, \(S(0)\) = 1

Probabilitas bertahan hidup pada waktu tertentu, \(S(t)\), adalah syarat karena orang tersebut harus bertahan hidup setelah waktu tertentu, misalnya hari ke-nol (itulah syaratnya) untuk tetap berada dalam eksperimen untuk hari pertama.

tribble(
  ~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
  0, 10, 0, "0/10 = 0",   "10/10      = 1",
  1, 10, 3, "3/10 = 0.3", "1 * (7/10) = 0.7",
) %>% kable()
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

Pada hari kedua sedikit lebih menarik, karena satu orang meninggal dan satu orang hilang begitu saja (status = 0). Orang yang hilang ini kemungkinan besar terbawa ombak dan mudah-mudahan bisa diselamatkan. Harapannya besar, karena semakin jauh orang tersebar di lautan, semakin besar kemungkinan salah satu dari mereka akan ditemukan dalam keadaan hidup. Dan hal ini akan memberi tahu dunia bahwa ada orang lain yang masih berada di luar sana. Jadi, meskipun orang hilang terlihat buruk, hal ini bisa jadi merupakan hal yang baik. Jadi, kita tentu tidak bisa menganggap orang yang hilang sebagai orang yang sudah mati. Selain itu, seperti kata pepatah Jerman: “Harapan adalah yang terakhir mati”.

Tetapi karena kita juga tidak yakin apakah orang ini masih hidup, kita tidak bisa mengatakan - orang tersebut selamat. Hal ini menimbulkan dilema: meskipun tidak meninggal, orang tersebut bukan bagian dari eksperimen kami lagi dan kami harus menghapusnya dari jumlah orang yang berisiko. Jadi, sementara hari kedua akan memiliki 7 orang yang berisiko yang tersisa (karena 3 orang telah meninggal di hari pertama), hari ketiga akan tersisa hanya 5 orang, karena 1 orang meninggal dan satu orang menghilang (disensor) dibandingkan dengan hari kedua. Sama halnya dengan hari pertama, probabilitas kelangsungan hidup bersifat kumulatif dan selalu menyertakan probabilitas hari sebelumnya.

tribble(
  ~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
  0, 10, 0, "0/10 = 0",    "10/10       = 1",
  1, 10, 3, "3/10 = 0.3",  "1 * (7/10)  = 0.7",
  2, 7,  1, "1/7  = 0.14", "0.7 * (6/7) = 0.6",
  3, 5,  1, "1/5  = 0.20", "0.6 * (4/5) = 0.48"
) %>% kable()
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

Pada dua hari berikutnya, dua orang menghilang, jadi kita menyensor mereka. Tidak perlu menghitung sesuatu untuk data yang disensor dalam analisis kelangsungan hidup, karena kita tidak tahu apakah mereka selamat atau tidak. Dan karena kita tertarik pada kelangsungan hidup atau kematian, tabel akhir di bawah ini berisi kasus yang hanya mati. Pada hari ke 6 tidak ada yang mati atau menghilang, oleh karena itu kami juga tidak menghitung apa pun untuk hari itu. Orang terakhir dalam eksperimen kami meninggal pada hari ke 7. Jadi, “N_meninggal” akan menjadi 1, dan “N_berisiko” akan menjadi 2, karena 1 dari 5 orang yang tersisa telah meninggal dan 2 orang disensor. Dengan demikian, tabel yang dihitung secara “manual” akan terlihat :

tribble(
  ~time_in_days, ~N_at_risk, ~N_died, ~P_dying, ~`P_surviving`,
  0, 10, 0, "0/10 = 0",    "10/10        = 1",
  1, 10, 3, "3/10 = 0.3",  "1 * (7/10)   = 0.7",
  2, 7,  1, "1/7  = 0.14", "0.7 * (6/7)  = 0.6",
  3, 5,  1, "1/5  = 0.20", "0.6 * (4/5)  = 0.48",
  7, 2,  1, "1/2  = 0.50", "0.48 * (1/2) = 0.24"
) %>% kable()
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

Namun, apa yang akan terjadi jika kita mengabaikan penyensoran dan hanya menghitung probabilitas untuk tidak mati? Dikarenakan 4 orang tidak mati pada hari ke-7, probabilitas untuk bertahan hidup akan menjadi \(\frac{4}{10} = 40\%\) yang hampir dua kali lipat lebih tinggi, dan dengan demikian kita akan melebihkan probabilitas untuk bertahan hidup, dibandingkan dengan probabilitas sebenarnya yaitu 0,24 yang memperhitungkan penyensoran.

SUMBER

Hanya memperhatikan orang yang selamat* bahkan memiliki nama - bias penyintas, dan ada cerita kecil di baliknya. Selama Perang Dunia Kedua, beberapa pesawat kembali dari medan perang dengan banyak kerusakan akibat peluru. Mereka hampir tidak bisa terbang, tapi mereka tetap kembali. Jadi, pihak militer memutuskan untuk melindungi pesawat dengan lebih banyak pelindung di bagian yang paling banyak lubang peluru, seperti sayap, dan mengurangi pelindung di bagian yang tidak berlubang peluru. Anehnya, persentase pesawat yang kembali tidak meningkat. Para insinyur bingung! Hingga seorang ahli matematika, Abraham Walt, yang diundang untuk memecahkan masalah ini berkata: “Pasang lebih banyak lapis baja di tempat-tempat yang tidak memiliki lubang peluru, karena jika tempat ini ditembak, pesawat tidak akan kembali.” Dan ketika yang lain memikirkannya, mereka menyadari bahwa semua pesawat yang kembali tidak memiliki lubang peluru di kokpit atau mesin. Lubang peluru menunjukkan semua tempat di mana pesawat bisa ditembak tapi masih bisa kembali, atau selamat! Itulah yang disebut dengan bias bertahan hidup. Jadi, menurut saya, regresi logistik memiliki survivorship bias dibandingkan dengan analisis ketahanan hidup jika kita ingin menganalisis data ketahanan hidup.

Cara menghitung kurva survival Kaplan-Meier

library(tidyverse)  # data wrangling and visualization
library(knitr)      # beautifying tables
library(car)        # for checking assumptions, e.g. vif etc.
## 
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
## 
##     recode
## The following object is masked from 'package:purrr':
## 
##     some
library(broom)      # for tidy model output
library(sjPlot)     # for plotting results of log.regr.
library(sjmisc)     # for plotting results of log.regr.
## 
## Attaching package: 'sjmisc'
## The following object is masked from 'package:purrr':
## 
##     is_empty
## The following object is masked from 'package:tidyr':
## 
##     replace_na
## The following object is masked from 'package:tibble':
## 
##     add_case
library(effects)    # for probability output and plots

Pada regresi logistik 1 adalah kelangsungan hidup, sedangkan dalam analisis kelangsungan hidup 1 adalah kematian. Kedua, membedakan kasus yang disensor, misalnya dapat menandainya dengan tanda plus di data atau di plot. Data di bawah ini menunjukkan bahwa orang disensor pada hari ke 2+, 4+, 5+ dan 10+. Instal dan muat survivalpaket untuk dapat mengeksekusi kode di bawah ini:

# install.packages("survival")
library(survival)

Surv(time = d$time, event = d$status)
##  [1]  1   1   1   2   2+  3   4+  5+  7  10+

Fungsi Surv menyatukan data “waktu” dan “status” ke dalam satu objek “survival” tunggal, yang memungkinkan untuk “memperhitungkan pengamatan yang disensor”. Objek ini kemudian dapat digunakan untuk memodelkan probabilitas kelangsungan hidup dengan fungsi survfit. Kita memodelkan kelangsungan hidup dengan menambahkan “~1” pada objek tersebut, di mana 1 berarti tidak ada variabel yang dapat mempengaruhi kelangsungan hidup. Objek kelangsungan hidup kita di sisi kiri tilde adalah variabel respons dan di sisi kanan ~ (tilde) adalah prediktor, atau dalam kasus “1” - tidak ada.Selanjutnya dapat dibuat model survival pertama dan melihat keluaran modelnya:

survival_model <- survfit(Surv(time, status) ~ 1, data = d)

# small summary
survival_model
## Call: survfit(formula = Surv(time, status) ~ 1, data = d)
## 
##       n events median 0.95LCL 0.95UCL
## [1,] 10      6      3       1      NA

Dimana akan didapat - n - jumlah peserta, - event - jumlah kematian, yang secara umum disebut event karena dapat mempelajari jenis-jenis “deadlines” lainnya, seperti kambuhnya penyakit, atau kerusakan pertama pada mobil, - perkiraan waktu bertahan hidup median, bukan rata-rata karena sifat non-parametrik (dijelaskan nanti) dari analisis ketahanan hidup dan - Interval kepercayaan 95%** untuk waktu ketahanan hidup median

Lebih banyak informasi dapat dinilai dengan fungsi ringkasan, yang memberikan tabel yang sama dengan perhitung secara manual di atas:

# big summary
summary(survival_model)
## Call: survfit(formula = Surv(time, status) ~ 1, data = d)
## 
##  time n.risk n.event survival std.err lower 95% CI upper 95% CI
##     1     10       3     0.70   0.145       0.4665        1.000
##     2      7       1     0.60   0.155       0.3617        0.995
##     3      5       1     0.48   0.164       0.2458        0.938
##     7      2       1     0.24   0.188       0.0515        1.000

Sehingga dapat dilihat bahwa perhitungan sebelumya benar dan telah berhasil mempelajari cara melakukan analisis survival. Sehingga mulai sekarang dapat mulai menggunakan perangkat lunak. Perangkat lunak ini memiliki banyak keuntungan. Sebagai contoh, fungsi summary, yang hanya menampilkan hasil dari kasus yang mati, dapat diisi dengan argumen tambahan censored = TRUE, yang menampilkan semua kasus, baik yang mati maupun yang disensor:

summary(survival_model, censored = T)
## Call: survfit(formula = Surv(time, status) ~ 1, data = d)
## 
##  time n.risk n.event survival std.err lower 95% CI upper 95% CI
##     1     10       3     0.70   0.145       0.4665        1.000
##     2      7       1     0.60   0.155       0.3617        0.995
##     3      5       1     0.48   0.164       0.2458        0.938
##     4      4       0     0.48   0.164       0.2458        0.938
##     5      3       0     0.48   0.164       0.2458        0.938
##     7      2       1     0.24   0.188       0.0515        1.000
##    10      1       0     0.24   0.188       0.0515        1.000

Selanjutnya dapat menentukan hasil dari hari mana yang ingin dilihat dengan menambahkan argumen times = ... ke fungsi summary. Bahkan dapat juga meminta hari-hari yang tidak tersedia datanya, misalnya hari ke-8 atau ke-9 dalam contoh sederhana kita. Sebagai contoh, probabilitas kelangsungan hidup setelah hari ke-8 adalah 24%:

summary(survival_model, times = c(8, 9))
## Call: survfit(formula = Surv(time, status) ~ 1, data = d)
## 
##  time n.risk n.event survival std.err lower 95% CI upper 95% CI
##     8      1       6     0.24   0.188       0.0515            1
##     9      1       0     0.24   0.188       0.0515            1

Sekarang, karena kita mengetahui probabilitas yang tepat untuk bertahan hidup pada setiap hari, bahkan pada hari-hari dimana kita tidak memiliki datanya, kita dapat memvisualisasikan hasil model. Install dan muat paket survminer untuk dapat menjalankan kode di bawah ini:

# install.packages("survminer")
library(survminer)
ggsurvplot(
  survival_model, 
  conf.int = FALSE, 
  surv.median.line = "hv",
  xlab = "Days", 
  ylab = "Survival probability", 
  break.time.by = 1,
  risk.table = T
)

Dari output diatas dapat dilihat interval kepercayaan (CI) untuk kelangsungan hidup sehari-hari atau alur bertahan hidup. CI divisualisasikan secara default, tetapi dapat dihapus jika diperlukan melalui conf.int = FALSE_perintah. Baris terakhir pada kode di atas menampilkan tabel “Angka berisiko”, yang dihitung secara manual di atas.

Kurva ini dijelaskan secara independen oleh dua ilmuwan berbeda pada saat bersamaan. Edward Kaplan dan Paul Meier kemudian menerbitkan temuan mereka bersama sebagai estimator Kaplan-Meier (KM) pada tahun 1958 dan survfitfungsi cocok dengan type = “kaplan-meier”kurva secara default.

Sebagian besar data kelangsungan hidup menunjukkan banyak peristiwa di awal dan jumlah peristiwa yang lebih rendah sepanjang waktu. Hal ini membuat kurva kelangsungan hidup non-linier dan sebagian besar data kelangsungan hidup terdistribusi miring atau tidak normal (tidak berbentuk lonceng). Ini adalah alasan mengapa metode KM memperkirakan waktu bertahan hidup median daripada rata-rata sebagai ukuran tendensi sentral. Non-linearitas dan “stepiness” dari kurva KM tidak memungkinkan untuk meringkas data menjadi satu parameter tunggal , misalnya kemiringan , yang membuat metode KM non-parametrik .

Interpretasi Kurva Kaplan-Meier

Sumbu x mewakili waktu dalam hari, dan sumbu y menunjukkan probabilitas bertahan hidup atau proporsi orang yang bertahan hidup. Jadi, kurva itu sendiri menunjukkan probabilitas kelangsungan hidup yang tepat dari waktu ke waktu . Penurunan vertikal pada kurva menunjukkan setidaknya satu peristiwa . Ketinggian penurunan vertikal menunjukkan perubahan probabilitas kelangsungan hidup kumulatif. Bagian horizontal dari kurva mewakili durasi kelangsungan hidup untuk interval waktu tertentu , yang diakhiri oleh peristiwa berikutnya (dan penurunan kurva). Kurva KM terlihat seperti tangga aneh dengan anak tangga yang tidak rata, di mana probabilitas bertahan hidup konstan di antara peristiwa, dan karenanya merupakan fungsi langkah yang mengubah nilai hanya pada saat setiap peristiwa. Dengan cara ini setiap pasien menyumbangkan informasi berharga untuk perhitungan selama masih hidup. Orang yang disensor ditampilkan persis seperti pada objek bertahan hidup, dengan plus , seperti yang dilihat pada hari ke-2. Namun, sebagian besar plus terlihat seperti kutu vertikal , karena terletak di bagian horizontal kurva, yaitu hari 4 dan 5 Tanda centang ditampilkan secara default, tetapi dapat ditekan menggunakan argumen censor = FALSE. Tabel risiko di bawah plot menunjukkan jumlah orang yang berisiko , yang sebenarnya semua orang yang “benar-benar hidup” dalam percobaan yang tidak mengalami kejadian atau penyensoran pada titik waktu tertentu. Garis putus-putus mewakili waktu kelangsungan hidup rata-rata yang sesuai dengan probabilitas kelangsungan hidup 50% . Dan jika kita mengabaikan penyensoran dan hanya memperkirakan median waktu (hanya untuk orang mati), kita akan mendapatkan 1,5 bukannya 3, yang akan meningkatkan kemungkinan bertahan hidup dari 48% menjadi 70%. Sekali lagi, mengabaikan penyensoran akan menghasilkan kemungkinan bertahan hidup yang terlalu tinggi karena bias keberlangsungan hidup.

d %>% 
  filter(status == 1) %>% 
  summarize(median_survival_whithout_censoring = median(time))

Membandingkan kelangsungan hidup kelompok

2 group

Dengan menggunakan conoth data 100 orang setelah kecelakaan Titanic alih-alih 10 dan lihat kelangsungan hidup mereka menggunakan kurva Kaplan-Meier. Angka-angka dalam tabel risiko semakin besar dan sebaiknya kami menampilkan persentase berisiko dalam tanda kurung di dekat nilai absolut. Argumen risk.table = “abs_pct” membantu dengan itu. Contoh “bulat” dari 100 orang menunjukan persentase yang persis sama dengan angka absolut, namun dengan jumlah “bulat” yang lebih sedikit atau beberapa kelompok, persentase akan menjadi sangat berguna. Rata-rata waktu bertahan hidup orang-orang di lautan dingin adalah sekitar 70 hari dan interval kepercayaannya tidak terlalu lebar.

set.seed(999) # for reproducible example
library(rlang)
## 
## Attaching package: 'rlang'
## The following object is masked from 'package:sjmisc':
## 
##     is_empty
## The following objects are masked from 'package:purrr':
## 
##     %@%, flatten, flatten_chr, flatten_dbl, flatten_int, flatten_lgl,
##     flatten_raw, invoke, splice
library(dplyr)
library(tidyverse)
d <- ggstatsplot::Titanic_full %>% 
  mutate(survived = ifelse(Survived == "No", 1, 0),
         time     = runif(n=2201, min=1, max=100)) %>% 
  sample_n(100) 

m <- survfit(Surv(time, survived) ~ 1, data = d)

ggsurvplot(m, 
           conf.int = TRUE, 
           risk.table = "abs_pct", 
           surv.median.line = "hv")

Misalnya, membandingkan probabilitas kelangsungan hidup laki-laki dengan perempuan. Dengan mengganti rumus model dengan nama variabel kategori yang diminati, misalnya sex. Plot bertahan hidup kemudian menampilkan kurva Kaplan-Meier untuk setiap kategori variabel yang ada:

m <- survfit(Surv(time, survived) ~ Sex, data = d)

ggsurvplot(m, 
           pval = TRUE, 
           conf.int = TRUE, 
           risk.table = "abs_pct", 
           surv.median.line = "hv") 

Interpretasi perbandingan kelompok menggunakan 4 tolok ukur

  1. 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.

  2. 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.

  3. Perkiraan waktu kelangsungan hidup Nilai Tengah mengungkapkan lebih dari interval kepercayaan. Waktu kelangsungan hidup rata-rata untuk setiap kelompok mewakili waktu di mana probabilitas kelangsungan hidup adalah 50%. Misalnya kelangsungan hidup rata-rata Betina jauh lebih tinggi (87 hari) daripada jantan (65 hari). Perbedaan 23 hari yang begitu besar, karena perempuan memiliki 23 hari lagi untuk ditemukan oleh beberapa kapal penangkap ikan. Di sini sekali lagi, hanya tes yang dapat mengetahui dan itulah mengapa tolok ukur terakhir untuk membandingkan dua kelompok adalah p-value yang diestimasi oleh tes Log-Rank (Peto et al, 1977), yang sangat penting, sehingga perlu bab tambahan.

m
## Call: survfit(formula = Surv(time, survived) ~ Sex, data = d)
## 
##             n events median 0.95LCL 0.95UCL
## Sex=Female 31     10   87.0    60.9      NA
## Sex=Male   69     54   64.5    53.6    72.9

Log-Rank test

  1. Uji statistik non-parametrik Log-Rank (kadang-kadang disebut Mantel-Haenszel) membandingkan median waktu kelangsungan hidup kelompok. Uji Log-Rank mirip dengan uji Wilcoxon-Rank non parametrik (1), yang juga membandingkan median dengan menggunakan peringkat dan juga mirip dengan uji Chi-square (2), di mana kita membandingkan jumlah kejadian yang diamati dengan yang diharapkan dengan menghitung statistik Chi-square:

\[ X^2 = \sum_{i = 1}^{g} \frac{(O_i - E_i)^2}{E_i}\]

Jumlah kejadian yang diharapkan dihitung untuk setiap titik waktu dan setiap kelompok dibandingkan dengan titik waktu sebelumnya. Nilai-nilai ini kemudian dijumlahkan pada semua titik waktu untuk memberikan jumlah total kejadian yang diharapkan pada setiap kelompok.

Sifat non-parametrik dari tes ini membuat tidak ada asumsi tentang distribusi kelangsungan hidup. Jadi, apakah waktu kelangsungan hidup normal (“lonceng melengkung”)? Bisa saja, tetapi tidak harus Faktanya, data kelangsungan hidup sangat jarang berdistribusi normal, tetapi sering kali miring karena biasanya banyak kejadian awal dan relatif sedikit kejadian akhir.

Hipotesis nol dari uji Log-Rank adalah tidak ada perbedaan dalam ketahanan hidup antara kedua kelompok. Nilai p-value sebesar 0,011 memungkinkan kita untuk menolak hipotesis nol dan mengindikasikan adanya perbedaan rata-rata yang signifikan dalam waktu kelangsungan hidup antara perempuan dan laki-laki.

Uji Log-Rank sangat banyak digunakan untuk membandingkan dua atau lebih kurva kelangsungan hidup, sehingga harus benar-benar membenarkan penggunaan uji lainnya.

Fungsi survdiff() menghitung uji Log-Rank dan mengembalikan komponen-komponen berikut:

  • Jumlah subjek dalam setiap kelompok.
  • Jumlah kejadian teramati tertimbang **dalam setiap kelompok.
  • Jumlah kejadian tertimbang * yang diharapkan* dalam setiap kelompok.
  • Statistik chi-square untuk uji kesetaraan
  • dan p-value untuk perbedaan kelangsungan hidup di antara kelompok
survdiff(Surv(time, survived) ~ Sex, data = d)
## Call:
## survdiff(formula = Surv(time, survived) ~ Sex, data = d)
## 
##             N Observed Expected (O-E)^2/E (O-E)^2/V
## Sex=Female 31       10     19.3      4.45      6.46
## Sex=Male   69       54     44.7      1.92      6.46
## 
##  Chisq= 6.5  on 1 degrees of freedom, p= 0.01

Apakah tes Log-Rank sempurna? Sayangnya, tidak. Salah satu masalahnya adalah: uji ini tidak memberikan ukuran efek yang membuat kita hanya memiliki p-value sebagai ukuran perbedaan. Masalah lain dengan uji Log-Rank (dan metode Kaplan-Meier secara umum) adalah bahwa uji ini tidak mengizinkan adanya perancu, uji ini mengabaikan faktor/variabel lain. Untungnya, kita masih bisa membandingkan lebih dari dua kelompok dengan satu variabel.

2 kelompok dan beberapa uji Log-Rank berpasangan (post-hoc)

Tes Log-Rank dapat membandingkan lebih dari dua kelompok dan mengatakan apakah ada perbedaan yang signifikan (p-value <0,05) di antara kelompok-kelompok ini. Hasil pengujian yang ditampilkan pada tabel dan kurva KM di bawah ini menunjukkan bahwa terdapat perbedaan kelangsungan hidup yang signifikan (p-value = 0,024) di antara kelompok orang pada kelas tiket yang berbeda. Namun, seperti kebanyakan tes lainnya (misalnya ANOVA), tidak disebutkan di antara kelompok mana tepatnya. Oleh karena itu diperlukan analisis tambahan yang membandingkan secara berpasangan setiap kelompok satu dengan kelompok lainnya. Analisis semacam itu sering disebut post-hoc.

survdiff(Surv(time, survived) ~ Class, data = d)
## Call:
## survdiff(formula = Surv(time, survived) ~ Class, data = d)
## 
##             N Observed Expected (O-E)^2/E (O-E)^2/V
## Class=1st  14        4    11.03     4.477     5.532
## Class=2nd  13        5     8.49     1.432     1.666
## Class=3rd  37       30    21.81     3.074     4.760
## Class=Crew 36       25    22.68     0.238     0.383
## 
##  Chisq= 9.5  on 3 degrees of freedom, p= 0.02
m <- survfit(Surv(time, survived) ~ Class, data = d)

ggsurvplot(m, 
           pval = TRUE, 
           conf.int = FALSE, 
           risk.table = "abs_pct", 
           surv.median.line = "hv",
           ncensor.plot = TRUE,
           break.time.by = 20,
           risk.table.y.text.col = TRUE, risk.table.y.text = FALSE) 

Tiga argumen plot yang berguna lebih lanjut yang dapat membantu memvisualisasikan data ketahanan hidup dengan lebih baik adalah:

  • break.time.by = 20 memecah sumbu x menjadi interval waktu yang diinginkan.
  • risk.table.y.text.col = TRUE dan risk.table.y.text = FALSE memplot batang, bukan nama dalam anotasi teks legenda tabel risiko
  • ncensor.plot = TRUE menampilkan jumlah subjek yang disensor, yang membantu untuk memahami apa yang menjadi penyebab angka risiko menjadi lebih kecil: peristiwa atau penyensoran.

Penafsiran

Kelangsungan hidup rata-rata adalah ca. 90 hari untuk penumpang kelas 1 dan 2, 58 hari untuk kelas 3 dan 65 hari untuk awak Titanic, menunjukkan kelangsungan hidup orang kaya yang baik, dibandingkan dengan yang lain. Dengan p-value yang rendah (p = 0,024) menunjukkan bahwa ada perbedaan yang signifikan dalam kelangsungan hidup antar kelompok . Di antaranya, hanya post-hoc yang tahu. Hasil dari analisis Log-Rank post-hoc tersebut dapat dilakukan dengan fungsi pairwise_survdiff dari survminer dan ditampilkan di bawah ini. Seperti biasa, jika memiliki banyak perbandingan sehingga berisiko membuat penemuan yang salah atau melewatkan penemuan penting. Jadi, harus menyesuaikan p-value untuk mengurangi kemungkinan terjadinya kesalahan.

pairwise_survdiff(
  formula = Surv(time, survived) ~ Class, data = d, p.adjust.method = "fdr"
  )
## 
##  Pairwise comparisons using Log-Rank test 
## 
## data:  d and Class 
## 
##      1st   2nd   3rd  
## 2nd  0.414 -     -    
## 3rd  0.028 0.139 -    
## Crew 0.095 0.317 0.414
## 
## P value adjustment method: fdr

Hasil analisis post-hoc mengungkapkan bahwa kelangsungan hidup kelas 1 secara signifikan lebih tinggi dibandingkan dengan kelas 3 dan Awak. Dan terlepas dari kenyataan bahwa rata-rata kelangsungan hidup penumpang kelas 2 sangat mirip dengan kelas 1, interval kepercayaan kelangsungan hidup ini sangat lebar dan banyak tumpang tindih dengan kelompok lain (tidak ditunjukkan untuk menghindari kekacauan). Itulah mengapa penumpang kelas 2 tidak umumnya memiliki waktu bertahan hidup yang lebih tinggi secara signifikan meskipun memiliki waktu bertahan hidup yang jauh lebih tinggi.

Multiple kurva Survival

Seperti disebutkan di atas, uji Log-Rank tidak dapat diterapkan pada beberapa variabel. Namun masih dapat memplot kurva kelangsungan hidup dari beberapa variabel untuk mendapatkan intuisi untuk data ini. Metode lebih lanjut, misalnya model Cox, dapat mengestimasi perbedaan di antara beberapa variabel, tetapi metode ini lebih kompleks daripada metode KM dan dengan demikian akan dibahas di posting mendatang.

m2 <- survfit( Surv(time, survived) ~ Sex + Class, data = d )

ggsurv <- ggsurvplot(m2, conf.int = TRUE)
   
ggsurv$plot +theme_bw() + 
  theme (legend.position = "right")+
  facet_grid(Sex ~ .)

Intuisi yang dapat kita peroleh dari plot di atas adalah bahwa wanita kaya (kelas tiket 1 dan 2) dan (hanya 2) wanita dari kru kapal memiliki probabilitas 100% untuk bertahan hidup, sementara wanita murni di kelas 3 akan mati dengan kepastian yang sama dengan pria. CI yang sangat tumpang tindih dari kelangsungan hidup pria menunjukkan bahwa semua pria pada akhirnya akan mati setelah kecelakaan Titanic.

Kesimpulan

Analisis ketahanan hidup menyelidiki waktu yang dibutuhkan untuk suatu peristiwa yang menarik untuk terjadi. Sebagian besar analisis ketahanan hidup univariat (variabel tunggal) menggunakan plot Kaplan-Meier untuk memvisualisasikan kurva ketahanan hidup dan Uji Log-Rank untuk membandingkan kurva ketahanan hidup dua atau lebih kelompok.

  • Keuntungan
  1. Keuntungan krusial kurva probabilitas bertahan hidup vs. kurva regresi logistik memperhitungkan data yang disensor, yang tidak mati, atau hidup. Regresi logistik memperlakukan semua orang yang tidak mati sebagai orang yang selamat, itu salah, hanya karena kita tidak mengetahui status kelangsungan hidup orang yang tidak terjawab. Pasien meninggalkan studi karena dua alasan utama, mereka merasa sangat buruk, sehingga mereka tidak lagi peduli dengan eksperimen , atau mereka merasa jauh lebih baik dan melupakan studi. Beberapa pasien mungkin hanya pindah ke kota lain tanpa berkata apa-apa. Menghitung semuanya sebagai selamat, seperti halnya regresi logistik, akan melebih-lebihkan kemungkinan bertahan hidup (survivorship bias) dan meremehkan bahaya kematian. Oleh karena itu, analisis kelangsungan hidup lebih tepat dibandingkan dengan regresi logistik, sementara itu masih menangkap tren probabilitas non-linier.

  2. 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
  1. “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.

  2. Metode Kaplan-Meier tidak dapat memodelkan variabel numerik , tetapi hanya kategorikal.

  3. 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

  1. Selalu menampilkan ketidakpastian statistik dengan memasukkan 95% CI atau/dan nilai p dari uji Log-Rank. Menampilkan CI pada beberapa titik waktu penting pada plot untuk setiap kelompok perlakuan terkadang lebih jelas daripada menampilkannya untuk semua titik waktu. CI yang tidak tumpang tindih menunjukkan perbedaan yang signifikan antar kelompok.

  2. Mempertimbangkan untuk memotong sumbu x . karena mata secara alami tertarik ke bagian kanan plot, di mana waktu berakhir. Namun, akhir plot berisi paling sedikit informasi dan ketidakpastian terbesar karena hanya sedikit peserta yang tersisa. Seberapa jauh waktu untuk memperpanjang plot? Terserah kamu.

  3. Selalu menampilkan tabel risiko yang menunjukkan jumlah pasien bebas kejadian dan masih dalam tindak lanjut di setiap kelompok perlakuan pada titik waktu yang relevan.

Survival analysis 2: Parametric Survival Models

Metode Kaplan-Meier (KM) non-parametrik tidak dapat menggambarkan probabilitas bertahan hidup dengan fungsi yang halus, yang berarti tidak dapat memprediksi apa pun. Model parametrik (mis. Eksponensial, Weibull, dll.) Selain itu, jika model parametrik sesuai, model tersebut lebih tepat, lebih efektif, dan lebih informatif daripada KM atau Cox. Namun sayangnya, langkah ini sering ditinggalkan karena penggunaan model parametrik belakang. Dalam posting ini akan mencoba untuk menutup celah ini.

library(tidyverse)  # data wrangling and visualization
library(sjPlot)     # for plotting results of log.regr.
library(effects)    # for probability output and plots
library(survival)   # for core survival analysis routines
library(survminer)  # for drawing survival curves
library(flexsurv)   # for Parametric Survival Modelling
library(knitr)      # for a wonderful-looking tables 

Mengapa kita membutuhkan model kelangsungan hidup parametrik

d2 <- tibble(
  time   = c(1,1,1,2,2,3,4,5,7,10), 
  status = c(1,1,1,1,0,1,0,0,1,0)
)
m <- survfit(Surv(time, status) ~ 1, data = d2)
ggsurvplot(
  m, 
  conf.int = FALSE, 
  surv.median.line = "hv",
  xlab = "Days", 
  ylab = "Survival probability", 
  break.time.by = 1,
  risk.table = F
)

Kerugian utama dari metode non-parametrik Kaplan-Meier (KM) yang ditunjukkan pada gambar di atas adalah tidak dapat dijelaskan probabilitas bertahan hidup dengan fungsi yang halus, yang artinya tidak dapat memprediksi apapun. Model parametrik (seperti Eksponensial, Weibull, dll.) Selain itu, model parametrik adalah langkah logis dalam perjalanan dari KM ke model Cox semi-parametrik , karena mereka dengan indah menghubungkan titik-titik antara model KM dan Cox dan dengan demikian sangat meningkatkan pemahaman tentang analisis kelangsungan hidup. Selain itu, jika model parametrik sesuai, model tersebut lebih tepat, lebih efektif, dan lebih informatif dari KM atau Cox. Namun sayangnya, langkah ini sering ditinggalkan karena penggunaan model parametrik belakang.

Apakah Waktu itu Variabel atau Konstanta?

Kematian dapat digambarkan dengan dua hal: peristiwa kematian itu sendiri dan titik waktu tertentu saat kematian terjadi. Dua hal ini selalu menggambarkan satu peristiwa, karena satu hanya mati sekali. Dengan demikian, waktu kematian akan bervariasi dan jumlah kematian akan bertambah seiring waktu, yang akan menjadikan waktu itu sendiri sebagai variabel . Begitulah beberapa peristiwa kematian pada titik waktu yang berbeda memungkinkan untuk mengungkapkan kematian dalam dua cara:

  1. 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.

  2. Melalui bentangan waktu berlalu yang berbeda per jumlah peristiwa yang tetap . Interval waktu biasanya diukur hingga peristiwa berikutnya terjadi. Ini membuat waktu menjadi variabel.

Perubahan stabil dalam bahaya dan kelangsungan hidup

Bayangkan setiap hari tepat 3 dari 10 orang meninggal di air laut yang dingin setelah kecelakaan Titanic. Ini tingkat kematian yang cukup stabil , atau Bahaya , sebesar 30%. Jika bahaya untuk mati terus tumbuh dengan laju yang sama, maka kemungkinan untuk bertahan hidup akan terus berkurang dengan laju yang sama. Dengan demikian, Bahaya dan Kelangsungan Hidup dapat diekspresikan satu sama lain. Secara khusus, Bahaya kematian dari waktu ke waktu dapat dilihat sebagai Gagal bertahan hidup \(F( t )\) dan kelangsungan hidup dari waktu ke waktu \(S( t )\) yang dapat dilihat sebagai Hazard of NOT-dying , atau hanya Hazard negatif , yang secara matematis dapat dinyatakan sebagai tanda minus “-”, atau “1-”, di depan Hazard. Kedua fungsi tersebut menghasilkan garis lurus, di mana Bahaya terus meningkat dan kelangsungan hidup terus menurun (plot di bawah): \[ F(t) = Hazard * t \] \[S(t) = 1 - Hazard * t\]

Peningkatan atau penurunan yang stabil dalam bahaya atau kelangsungan hidup seperti itu agak tidak alami, tidak realistis. Dalam memperkirakan kematian dapat dikatakn sulit. Bahaya biasanya meningkat secara eksponensial, misalnya dalam kasus kelaparan, atau menurun secara eksponensial, misalnya dalam kasus pandemi setelah vaksin ditemukan.

Perubahan eksponensial positif dalam bahaya dan kelangsungan hidup

Pikirkan tentang kelaparan sejenak. Semakin lama kondisi kelaparan, semakin tinggi kemungkinan (risiko) mati. Plot kiri di bawah menunjukkan perkembangan seperti itu, di mana bahaya kematian \(F( t )\) dinyatakan dalam probabilitas kecil pada awalnya (beberapa kematian), tetapi tumbuh secara eksponensial dengan waktu (semakin banyak kematian). Saya suka menyebut tren seperti itu sebagai perubahan eksponensial yang positif, atau mempercepat. “exp” dalam rumus kiri di bawah adalah semua yang diperlukan untuk merencanakan tren tersebut.

Sekali lagi, karena kelangsungan hidup dapat dilihat sebagai bahaya negatif dapat menyatakan kelangsungan hidup \(S( t )\) dengan hanya menggunakan tanda minus (atau “1-”) di depan Hazard. Plot di sebelah kanan menampilkan hasil dari fungsi bertahan hidup tersebut.Jika bahaya kematian rendah di awal “waktu”, maka kemungkinan bertahan hidup tinggi. Di akhir “waktu”, Kelangsungan Hidup turun secara eksponensial karena peningkatan Bahaya secara eksponensial. \[ F(t)= exp^{Hazard * t} \] \[S(t) = 1 - exp^{Hazard * t}\]

Perubahan eksponensial negatif dalam bahaya dan kelangsungan hidup

Namun, dalam beberapa kasus, lebih banyak orang meninggal pada awal “waktu”, di mana tingkat kematian menurun dari waktu ke waktu. Pikirkan tentang pandemi, atau kecelakaan besar. Perubahannya masih eksponensial, dan menuju ke arah yang sama: naik, dalam kasus Bahaya, dan turun, dalam kasus bertahan hidup. Namun, perubahan eksponensial agak terbalik (membungkuk). Saya suka menyebutnya sebagai perubahan eksponensial yang negatif, atau melambat.

Seperti “pembengkokan ke dalam” dapat dicapai dengan “-” minus sing di depan Hazard dan fungsi eksponensial itu sendiri (persamaan kiri dan gambar di bawah). Minus ini tidak menggambarkan hazard negatif, seperti pada contoh di atas. Itu hanya mengubah kurva dari percepatan ke perlambatan. Untuk mendapatkan kelangsungan hidup untuk fungsi ini seperti pada contoh di atas, harus menggunakan “-” (atau “1-”) di depan seluruh ekspresi hazard eksponensial. Menariknya, dua tanda minus di depan “exp” dalam rumus Survival saling menetralkan dan menjadi nilai tambah, yang menyisakan dengan

\[F(t)= - exp^{-Hazard * t}\]

\[S(t) = 1 - ( - exp^{-Hazard * t}) = exp^{-Hazard * t}\]

Membangun Model Ekponensial

Sejak fungsi bertahan hidup \(S( t )\) menunjukkan probabilitas bertahan hidup melewati titik waktu tertentu ,

\[S(t) = P(T > t)\]

dan fungsi eksponensial \(F( t )\) menunjukkan probabilitas Failed-survival melewati titik waktu tertentu ,

\[F(t) = P(T \leq t) = 1 - exp^{-Hazard * t}\]

fungsi bertahan hidup kemudian dapat dinyatakan dalam bentuk fungsi tidak bertahan hidup (eksponensial):

\[S(t) = P(T > t) = 1 - P(T \leq t) = 1 - F(t) = 1 - [1 - exp^{-Hazard * t}] = exp^{-Hazard * t}\]

Sehingga fungsi survival yang menunjukkan laju penurunan adalah fungsi flipped hazard yang menunjukkan laju kenaikan. Dengan demikian, dapat menulis ulang \(S( t )\) sebagai:

\[S(t) = exp^{- Hazard * t} = exp^{- \lambda* t}\]

di mana -Hazard dan waktu adalah dua parameter yang menggambarkan perubahan eksponensial dalam probabilitas bertahan hidup, itulah sebabnya model seperti itu memiliki nama - model eksponensial parametrik . Dan karena Hazard adalah negative , dan fungsi eksponensial tidak linier (alias. curvy ) - model keluar menghasilkan kurva eksponensial negatif (lihat di bawah). Tingkat penurunan yang mulus seperti itu menggambarkan probabilitas bertahan hidup jauh lebih baik daripada metode Kaplan-Meier, yang secara tiba-tiba (secara bertahap) menurunkan probabilitas hanya setelah suatu peristiwa, sambil menjaga probabilitas tetap konstan di antara peristiwa tersebut.

Cara menghitung model parametrik

library(flexsurv)    # for Parametric Survival Modelling

ex <- flexsurvreg(Surv(time, status) ~ 1, data = d2, dist="exponential")
we <- flexsurvreg(Surv(time, status) ~ 1, data = d2, dist="weibull")

ggsurvplot(
  ex, 
  conf.int = FALSE, 
  surv.median.line = "hv",
  xlab = "Days", 
  ylab = "Survival probability", 
  break.time.by = 1,
  risk.table = F
)

Parameter kurva (\(-\lambda * t\)) memungkinkan kita untuk memodelkan dan memprediksi kelangsungan hidup dan bahaya dari waktu ke waktu, yang merupakan keuntungan utama dari model eksponensial dibandingkan dengan metode Kaplan-Meier, yang tidak bersifat parametrik dan oleh karena itu tidak dapat dimodelkan. Namun, non-linearitas sering kali merepotkan, dan kami lebih suka menggunakan konsep regresi linear, yang meringkas (meregresikan) banyak angka menjadi beberapa angka, seperti intersep (\(\beta_0\)) dan kemiringan (\(\beta_1\)). Untungnya, kurva non-linier dapat dengan mudah “dilinierkan” melalui logaritma natural. Untuk melakukan ini, kita bahkan tidak perlu memahami cara kerja logaritma atau fungsi eksponensial, kita hanya perlu mengetahui bahwa keduanya saling menetralkan satu sama lain. Selain itu, menggunakan “log” (melogaritmakan kedua sisi persamaan di bawah ini) menghasilkan tiga efek samping yang positif:

  1. Pertama, di sisi kanan persamaan, ini akan memindahkan kurva kita (\(-\lambda * t\)) menjadi sebuah garis (\(b_0 + b_1x_1 + ... + b_kx_k\)), di mana kita akan dapat memiliki intersep dan koefisien \(\beta\) seperti pada regresi logistik linier biasa \[Hazard = exp^{b_0 + b_1x_1 + ... + b_kx_k}\]

atau

\[ log(Hazard) = b_0 + b_1x_1 + ... + b_kx_k \]

Model survival seperti itu sebenarnya adalah model Poisson. Oleh karena itu, akan sangat membantu jika sudah mengeuasai distribusi Poisson.

  1. Kedua, ini akan membantu kita untuk terhubung ke model-model selanjutnya, seperti model Weibull dan Cox, karena perbedaan di antara keduanya terutama terletak pada intersep “\(b_0\)”;

  2. Terakhir, ini akan sangat meningkatkan kemampuan interpretasi, karena Hazard-Ratios (HRs) (yang dihasilkan oleh model eksponensial) dapat diinterpretasikan persis seperti Odds-Ratios (ORs) dari regresi logistik (seperti yang dijelaskan dalam posting saya tentang regresi logistik). Sama halnya dengan Odds dalam regresi logistik, Hazard itu sendiri, yang merupakan probabilitas meninggal SEKARANG, kurang berguna dibandingkan dengan Hazard-Ratio. Hazard-Ratio adalah rasio bahaya seseorang yang terpapar (sakit) terhadap seseorang yang tidak terpapar (sehat). Misalnya jika HR = 2, risiko kematian seseorang yang terpapar adalah dua kali lipat dibandingkan dengan seseorang yang tidak terpapar.

Pikiran akhir

Apakah model parametrik berguna?

  • Tiga kurva di atas yang menggambarkan berbagai jenis perubahan dalam kelangsungan hidup dan bahaya dari waktu ke waktu dimaksudkan untuk mengatakan bahwa distribusi bisa sangat berbeda. Jika distribusi yang sesuai dapat ditemukan, model parametrik lebih informatif daripada model KM atau Cox

  • model ini dapat memprediksi probabilitas ketahanan hidup pada titik waktu tertentu, hazard kejadian, rata-rata dan median waktu ketahanan hidup sudah tersedia

  • model ini juga sedikit lebih efisien dan menghasilkan estimasi yang lebih tepat karena kecocokan yang lebih baik (lihat gambar di atas)

Apakah model parametrik itu sempurna? Tentu saja tidak!

  • model parametrik perlu menentukan distribusi, yang mungkin sulit untuk diidentifikasi

  • model ini juga secara matematis lebih kompleks, misalnya KM, dan oleh karena itu lebih jarang digunakan, sehingga mengurangi perbandingan hasil antar studi. Karena popularitasnya yang lebih rendah, saya tidak akan membahas lebih dalam tentang model parametrik tertentu: Model Weibull, Gompertz, model Waktu Kegagalan yang Dipercepat, dll.

Jadi, terlepas dari kenyataan bahwa model parametrik adalah alternatif yang baik untuk model regresi KM dan Cox (yang tidak perlu menentukan distribusi apa pun), KM dan Cox tetap menjadi metode yang paling populer untuk menganalisis data survival. Dan itulah mengapa langkah logis berikutnya dalam perjalanan statistik dalam mempelajari Model Cox Proportional Hazard (sedang berlangsung).

LS0tDQp0aXRsZTogIlVUUyBTVVJWSVZBTCBNT0RFTCAiDQpzdWJ0aXRsZTogIlR1Z2FzIFVUUyINCmF1dGhvcjogIk11aGFtbWFkIE5hdWZhbCBBcmRpYW5zeWFoICgyMDIwNDkyMDAxNykiDQpkYXRlOiAgImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyb2JvYm9vazogICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNzczogInN0eWxlLmNzcyINCg0KLS0tDQoNCg0KDQoNCjxicj4NCg0KDQo8aW1nIHN0eWxlPSJmbG9hdDogcmlnaHQ7IG1hcmdpbjogLTUwcHggNTBweCAwcHggNTBweDsgd2lkdGg6MjUlIiBzcmM9Im5hdWZhbC5qcGVnIi8+IA0KDQp8DQo6LS0tLSB8Oi0tLS0NCipLb250YWt8ICo6ICokXGRvd25hcnJvdyQqDQpFbWFpbHwgbmF1ZmFsMzQzM0BnbWFpbC5jb20NCkluc3RhZ3JhbSB8IGh0dHBzOi8vd3d3Lmluc3RhZ3JhbS5jb20vbV9uYXVmYWxhcmRpYW5zeWFoLyANClJQdWJzICB8IGh0dHBzOi8vcnB1YnMuY29tL211aGFtYWRfbmF1ZmFsLyANCg0KKioqDQoNCiMgU3Vydml2YWwgYW5hbHlzaXMgMTogQSBnZW50bGUgSW50cm9kdWN0aW9uIGludG8gS2FwbGFuLU1laWVyIEN1cnZlcw0KDQpBbmFsaXNpcyB3YWt0dSBTdXJ2aXZhbCBkaXBlcmx1a2FuIGRhbGFtIHBlbmVsaXRpYW4gYXBhIHB1biB5YW5nIG1lbnllbGlkaWtpIHdha3R1IHVudHVrIGhhc2lsIHRlcnRlbnR1IHlhbmcgbWVuYXJpay4gU3R1ZGkga2Fua2VyIGRhbGFtIGJpZGFuZyBrZWRva3RlcmFuIGRhbiBrZWdhZ2FsYW4gcGVydGFtYSBtb2JpbCBkYWxhbSBiaWRhbmcgdGVrbmlrIChhbmFsaXNpcyB3YWt0dSBrZWdhZ2FsYW4pIGFkYWxhaCBjb250b2ggeWFuZyBiYWlrLiBIYXNpbCB5YW5nIGRpaW5naW5rYW4gZGFwYXQgYmVydXBhIGtlbWF0aWFuLCByZW1pc2kgdW50dWsga2FtYnVoLCBwZXJrZW1iYW5nYW4sIGF0YXUga2VnYWdhbGFuLiBUaXRpayB3YWt0dSB1bnR1ayBtZW5jYXBhaSBoYXNpbCB0ZXJzZWJ1dCB1bXVtbnlhIGRpc2VidXQgcGVyaXN0aXdhLlRpZGFrIHNlbXVhICJldmVudCIgYmVyYWtpYmF0IGZhdGFsLCB0ZXRhcGkga2FkYW5nLWthZGFuZyBiYWhrYW4gYmlzYSBtZW5qYWRpIGhhc2lsIHlhbmcgbWVuZ3VudHVuZ2thbiBzZXBlcnRpIGtlbHVhciBkYXJpIHJ1bWFoIHNha2l0LiBEYW4gZGVuZ2FuIGRlbWlraWFuLCBhbmFsaXNpcyBrZXRhaGFuYW4gaGlkdXAganVnYSBtZXJ1cGFrYW4gaXN0aWxhaCB1bXVtLCBrYXJlbmEgaW5pIGJ1a2FuIGhhbnlhIHRlbnRhbmcga2VsYW5nc3VuZ2FuIGhpZHVwLg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKSAgIyBkYXRhIHdyYW5nbGluZyBhbmQgdmlzdWFsaXphdGlvbg0KbGlicmFyeShzalBsb3QpICAgICAjIGZvciBwbG90dGluZyByZXN1bHRzIG9mIGxvZy5yZWdyLg0KbGlicmFyeShlZmZlY3RzKSAgICAjIGZvciBwcm9iYWJpbGl0eSBvdXRwdXQgYW5kIHBsb3RzDQpsaWJyYXJ5KHN1cnZpdmFsKSAgICMgZm9yIGNvcmUgc3Vydml2YWwgYW5hbHlzaXMgcm91dGluZXMNCmxpYnJhcnkoc3Vydm1pbmVyKSAgIyBmb3IgZHJhd2luZyBzdXJ2aXZhbCBjdXJ2ZXMNCmxpYnJhcnkoa25pdHIpICAgICAgIyBmb3IgYSB3b25kZXJmdWwtbG9va2luZyB0YWJsZXMNCmBgYA0KDQpEYWxhbSBtYXRlcmkgaW5pIGFrYW4gZGlwZWxhamFyaSA6DQoNCi0gS29uc2VwLWtvbnNlcCB0ZXJwZW50aW5nIGRhbGFtIGFuYWxpc2lzIHN1cnZpdmFsOiBrdXJ2YSBzdXJ2aXZhbCwgcGVueWVuc29yYW4sIGRhbiB1amkgbG9nLXJhbmssDQotIE1lbmdoaXR1bmcgc2VjYXJhIG1hbnVhbCwga2VtdWRpYW4gbWVuZ2tvbXB1dGFzaSBkYW4gbWVuZ2ludGVycHJldGFzaWthbiBrdXJ2YSBzdXJ2aXZhbCwgZGFuDQotIE1lbmd1amkgcGVyYmVkYWFuIGtlbGFuZ3N1bmdhbiBoaWR1cCBhbnRhcmEgZHVhIGF0YXUgbGViaWgga2Vsb21wb2ssIG1pc2FsbnlhIHBlcmVtcHVhbiB2cyBsYWtpLWxha2kNCg0KIyMgTWVuZ2FwYSBoYXJ1cyBtZW1wZWxhamFyaSBhbmFsaXNpcyBzdXJ2aXZhbD8NCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KZCA8LSB0aWJibGUoDQogIHRpbWUgICA9IGMoMSwxLDEsMiwyLDMsNCw1LDcsMTApLCANCiAgc3RhdHVzID0gYygxLDEsMSwxLDAsMSwwLDAsMSwwKQ0KKQ0KDQpkICU+JSBrYWJsZSgpDQpgYGANCg0KUGFkYSBzdWJiYWIgaW5pIGRhbGFtIG1lbmphd2FiIHBlcnRhbnlhYW4gbWVuZ2FwYSBoYXJ1cyBtZW1wZWxhamFyaSBhbmFsaXNpcyBzdXJ2aXZhbCBkYXBhdCBtZW5nZ3VuYWthbiBjb250b2gga2FzdXMgcGVueWludGFzIFRpdGFuaWM6IERpbWFuYSBoYW55YSAxMCBvcmFuZyBkYW4gaGFueWEgMTAgaGFyaSBkaSBsYXV0IHNldGVsYWgga2VjZWxha2FhbiBkYW4gbWVuZ2FuYWxpc2lzbnlhIGRlbmdhbiBtZXRvZGUgc3RhdGlzdGlrIGtsYXNpaywgcmVncmVzaSBsaW5pZXIgZGFuIGxvZ2lzdGlrLiBQcm9ibGVtIHlhbmcgYWthbiBkaWJhaGFzIHlhaXR1IGJlcmFwYSBiYW55YWsgb3JhbmcgZGFuIGJlcmFwYSBsYW1hIGJlcnRhaGFuIGRhbiBiZXJhcGEgYmFueWFrIHlhbmcgbWVuaW5nZ2FsIHBhZGEgaGFyaSB0ZXJ0ZW50dS4gU2VoaW5nZ2EgbWVtaWxpa2kgZHVhIHBhcmFtZXRlciB1dGFtYSBhZGFsYWggKDEpIHdha3R1IChkYWxhbSBoYXJpKSBkYW4gKDIpICJzdGF0dXMga2VoaWR1cGFuIiBvcmFuZywgZGkgbWFuYSAic3RhdHVzID0gMSIgYmVyYXJ0aSBrZW1hdGlhbiBkYW4gInN0YXR1cyA9IDAiIGJlcmFydGkgYnVrYW4ga2VtYXRpYW4uIERlbmdhbiBzdGF0dXMgb3JhbmcgbWFrYSBkYXBhdCBtZW5naGl0dW5nIG9yYW5nIHlhbmcgc2VsYW1hdCBkYW4gdGlkYWsgc2VsYW1hdCBwYWRhIHNldGlhcCBoYXJpLg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KZ2dwbG90KGQsIGFlcyh0aW1lLCBmaWxsID0gZmFjdG9yKHN0YXR1cykpKSsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNClBhZGEgcGxvdCBkaWF0YXMgYmVsdW0gZGFwYXQgZGlzaW1wdWxrYW4gZGFsYW0gbWVuamF3YWIgcGVybWFzYWxhaCBzZWJlbHVtbnlhIHNlaGluZ2dhIGRhcGF0IGRpbGFrdWthbiBhbmFsaXNpcy4NCg0KMS4g4oCcc3RhdHVzID0gMOKAnSB0aWRhayBzZWxhbHUgYmVyYXJ0aSBiZXJ0YWhhbiBoaWR1cC4gUGVydGFtYSwgb3JhbmcgdGVyc2VidXQgbXVuZ2tpbiB0ZXJiYXdhIG9tYmFrIGRhbiBtZW5naGlsYW5nIHNlaGluZ2dhIHRpZGFrIGRpa2V0YWh1aSBzdGF0dXNueWEuIE11bmdraW4gc3VkYWggbWF0aSwgbXVuZ2tpbiBkaXNlbGFtYXRrYW4gb2xlaCBwZXJhaHUgbmVsYXlhbiBhdGF1IG1hc2loIGhpZHVwIGRpIHN1YXR1IHRlbXBhdCBkaSBsYXV0YW4uIERlbmdhbiBkZW1pa2lhbiAqb3JhbmcgeWFuZyBoaWxhbmcgaW5pIHRpZGFrIGRhcGF0IGRpYW5nZ2FwIG1hdGkgYXRhdSBzZWxhbWF0KiAuIEtlZHVhLCBqaWthIGJlYmVyYXBhIG9yYW5nIGJlcnRhaGFuIDEwIGhhcmksIG1lcmVrYSBtdW5na2luIG1hdGkgcGFkYSBoYXJpIGtlIDExIHNlaGluZ2dhIHdha3R1IG1lbmphZGkgc2FsYWggc2F0dSBmYWt0b3IgcGVybWFzYWxhaGFuLg0KDQoyLiBUaWRhayBtZW1pbGlraSBkYXRhIHVudHVrIHNldGlhcCAxMCBoYXJpIGluaS4gS2VsYW5nc3VuZ2FuIGhpZHVwIHBhZGEgZGF0YSBpbmkganVnYSBkYXBhdCBkaXBlbmdhcnVoaSBvbGVoIGtvbmRpc2kgdHVidWggYXRhdSBwYXNva2FuIG1ha2FuIHVudHVrIGJlcnRhaGFuIGhpZHVwIHlhbmcgdGlkYWsgZGlrZXRhaHVpLiBEZW1pa2lhbiBwdWxhLCBwZW51cnVuYW4gcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCBqdWdhICp0ZXJha3VtdWxhc2kgZGFyaSB3YWt0dSBrZSB3YWt0dSogLCB5YW5nIHRpZGFrIGRhcGF0IGRpdGVudHVrYW4gZGVuZ2FuIHBlbmdoaXR1bmdhbiBzZWRlcmhhbmEgYW50YXJhIG9yYW5nIHlhbmcgc2VsYW1hdCBkZW5nYW4gdGlkYWsgc2VsYW1hdCBwYWRhIGhhcmkgdGVydGVudHUuDQoNCkRlbmdhbiBwZXJtYXNhbGFoYW4gZGlhdGFzLCBkYXBhdCBtZW5lbnR1a2FuIG1ldG9kZSB5YW5nIHRlcGF0Lg0KDQoxLiBNZWxpaGF0IHZhcmlhYmVsIG51bWVyaWsg4oCcd2FrdHXigJ0sIG11bmdraW4gZGFwYXQgdGVyZ29kYSB1bnR1ayBtZW5nZ3VuYWthbiByZWdyZXNpIGxpbmllciB1bnR1ayBtZW1vZGVsa2FuIHdha3R1IGJlcnRhaGFuIGhpZHVwIHVudHVrIGR1YSBrZWxvbXBvayBzdGF0dXMgeWFuZyBiZXJiZWRhLCAwICYgMToNCg0KYGBge3J9DQptIDwtIGxtKHRpbWUgfiBzdGF0dXMsIGQgJT4lIG11dGF0ZShzdGF0dXMgPSBmYWN0b3Ioc3RhdHVzKSkpDQoNCmxpYnJhcnkoZWZmZWN0cykNCnBsb3QoYWxsRWZmZWN0cyhtKSkNCmBgYA0KDQpOYW11biwga2V0aWthIG1lbWJ1YXQgcGxvdCBoYXNpbCBtb2RlbG55YSwgZGFwYXQgZGlzYWRhcmkgYmFod2EgYWRhIHNlc3VhdHUgeWFuZyB0aWRhayBiZXJlcyBkaSBzYW5hLiBTZW11YSBpbmZvcm1hc2kgeWFuZyBkaW1pbGlraSB1bnR1ayBtZW1vZGVsa2FuIHdha3R1IGJlcnRhaGFuIGhpZHVwIGFkYWxhaCBhbmdrYSBub2wgZGFuIHNhdHUuIERhbiB3YWt0dSByYXRhLXJhdGEga2VtYXRpYW4gKHN0YXR1cyA9IDEpIHNlYmVzYXIgMiw1IGhhcmkgbWVsZXdhdGthbiBiYW55YWsgaW5mb3JtYXNpLiBTZWJhZ2FpIGNvbnRvaCwgc2V0ZW5nYWggZGFyaSBvcmFuZy1vcmFuZyAoMyBvcmFuZykgbWVuaW5nZ2FsIHBhZGEgaGFyaSBwZXJ0YW1hISBEYW4gc2VtYWtpbiBqYXVoIG1lbGFuZ2thaCBrZSBkZXBhbiwgc2VtYWtpbiBzZWRpa2l0IG9yYW5nIHlhbmcgbWVuaW5nZ2FsLCB5YW5nIGRhcGF0IGRpbGloYXQgcGFkYSBwbG90IGhpdHVuZ2FuIHBlcnRhbWEgZGkgYXRhcy4gSmFkaSwgd2FrdHUgYmVydGFoYW4gaGlkdXAgdGlkYWsgYmVuYXItYmVuYXIgbGluaWVyIGRhbiB0ZW50dSBzYWphIHRpZGFrIGRhcGF0IGRpZ2FtYmFya2FuIGhhbnlhIGRlbmdhbiBhbmdrYSBub2wgZGFuIHNhdHUhIFNlaGluZ2dhIGRpc2luaSBtb2RlbCBsaW5pZXIgdGFtcGFrbnlhIHRpZGFrIGJlcmd1bmEuDQoNCjIuIEthcmVuYSBkaXNpbmkgbWVtaWxpa2kgYW5na2Egbm9sIGRhbiBzYXR1IHBhZGEga29sb20gc3RhdHVzLCBkYXBhdCBtZW5nZ3VuYWthbiByZWdyZXNpIGxvZ2lzdGlrLCAgVGVydXRhbWEga2FyZW5hIGt1cnZhIHByb2JhYmlsaXRhc255YSB0aWRhayBsaW5pZXIgZGFuIGFrYW4gbWVuYW5na2FwIHRyZW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGRhcmkgd2FrdHUga2Ugd2FrdHUuIA0KDQpgYGB7cn0NCm0gPC0gZ2xtKHN0YXR1cyB+IHRpbWUsIGQsIGZhbWlseSA9IGJpbm9taWFsKQ0KDQpsaWJyYXJ5KHNqUGxvdCkNCnBsb3RfbW9kZWwobSwgdHlwZSA9ICJwcmVkIiwgY2kubHZsID0gTkEpDQpgYGANCg0KU2VrYXJhbmcgZGFwYXQgZGlsaWhhdCBiYWh3YSBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIG5vbi1saW5lYXIsIHlhbmcgbWVydXBha2FuIHBlbmluZ2thdGFuIGJlc2FyIGRpYmFuZGluZ2thbiBkZW5nYW4gcmVncmVzaSBsaW5pZXIuIE5hbXVuLCBwZW5nYW1hdGFuIGtlbGltYSBtZW1pbGlraSBzdGF0dXMgMCBwYWRhIGhhcmkga2UtMi4gSW5pIGJlcmFydGkgYmFod2Egb3JhbmcgdGVyc2VidXQgcGFzdGkgYmVydGFoYW4gaGlkdXAgc2VsYW1hIDIgaGFyaSwgdGV0YXBpIGhpbGFuZyBzZXRlbGFobnlhLiBQcm9iYWJpbGl0YXMgZGFsYW0gcmVncmVzaSBsb2dpc3RpayBha2FuIG1lbmdoaXR1bmcgb3JhbmcgaW5pIHNlYmFnYWkgMTAwJSBzZWxhbWF0IHNldGVsYWggaGFyaSBrZWR1YSBoYW55YSBrYXJlbmEgc3RhdHVzbnlhIHRpZGFrICI9MSIsIHlhbmcgc2FsYWggKGF0YXUgYmlhcyksIGthcmVuYSB0aWRhayBkaWtldGFodWkgYXBha2FoIG9yYW5nIGluaSBzZWxhbWF0LiBEZW5nYW4gZGVtaWtpYW4sIHJlZ3Jlc2kgbG9naXN0aWsgbWVsZWJpaC1sZWJpaGthbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGRhbiBvbGVoIGthcmVuYSBpdHUganVnYSBtZXJ1cGFrYW4gYWxhdCB5YW5nIHRpZGFrIHRlcGF0IHVudHVrIG1lbmdhbmFsaXNpcyBkYXRhIGtlbGFuZ3N1bmdhbiBoaWR1cC4NCg0KSmFkaSB0aWRhayBkYXBhdCBkaWxha3VrYW4gYW5hbGlzaXMgKmRhdGEgU3Vydml2YWwqIGRlbmdhbiBtZXRvZGUga2xhc2lrLiBTZWhpbmdnYSBtZW1idXR1aGthbiBtZXRvZGUgYW5hbGlzaXMgc3Vydml2YWwuDQoNClNlbWVudGFyYSBtb2RlbCByZWdyZXNpIGxpbmllciBtZW5nZ2FtYmFya2FuIHdha3R1LCB0ZXRhcGkgbWVsZXdhdGthbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIG5vbi1saW5pZXIsIHJlZ3Jlc2kgbG9naXN0aWsgbWVuYW5na2FwIHRyZW4gbm9uLWxpbmllciwgdGV0YXBpIG1lbGViaWgtbGViaWhrYW4gcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cC4gU2ViYWxpa255YSwgKmFuYWxpc2lzIHN1cnZpdmFsKiBtZW1lY2Foa2FuIGtlZHVhIG1hc2FsYWggdGVyc2VidXQsIGthcmVuYSBtb2RlbCBpbmkgbWVtb2RlbGthbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIG5vbi1saW5lYXIgZGFyaSB3YWt0dSBrZSB3YWt0dSBzYW1iaWwgbWVtcGVyaGl0dW5na2FuIHN1YmplayBwZW5lbGl0aWFuIHlhbmcgaGlsYW5nLCBiYWlrIHlhbmcgbWVuaW5nZ2FsIG1hdXB1biB5YW5nIHNlbGFtYXQuIA0KDQojIyBLZW1hdGlhbiBidWthbmxhaCBzYXR1LXNhdHVueWEgcGlsaWhhbiEgQXRhdTogIkFwYWthaCB5YW5nIGRpbWFrc3VkIGRlbmdhbiBwZXJpc3Rpd2E/Ig0KDQpBbmFsaXNpcyB3YWt0dSBzdXJ2aXZhbCBkaXBlcmx1a2FuIGRhbGFtIHBlbmVsaXRpYW4gYXBhIHB1biB5YW5nIG1lbnllbGlkaWtpIHdha3R1IHVudHVrIGhhc2lsIHRlcnRlbnR1IHlhbmcgbWVuYXJpay4gUGVuZWxpdGlhbiBrYW5rZXIgZGFsYW0gYmlkYW5nIGtlZG9rdGVyYW4gZGFuIGtlZ2FnYWxhbiBwZXJ0YW1hIG1vYmlsIGRhbGFtIGJpZGFuZyB0ZWtuaWsgKGFuYWxpc2lzIHdha3R1IGtlZ2FnYWxhbikgYWRhbGFoIGNvbnRvaCB5YW5nIGJhaWsuIEhhc2lsIHlhbmcgZGlpbmdpbmthbiBkYXBhdCBiZXJ1cGEga2VtYXRpYW4sIHJlbWlzaSB1bnR1ayBrYW1idWgsIHBlcmtlbWJhbmdhbiwgYXRhdSBrZWdhZ2FsYW4uIFRpdGlrIHdha3R1IHVudHVrIG1lbmNhcGFpIGhhc2lsIHRlcnNlYnV0IHVtdW1ueWEgZGlzZWJ1dCBwZXJpc3Rpd2EuIHNlaGluZ2dhLCB0aWRhayBzZW11YSAiZXZlbnQiIGJlcmFraWJhdCBmYXRhbCAsIHRldGFwaSBrYWRhbmcta2FkYW5nIGJhaGthbiBiaXNhIG1lbmphZGkgaGFzaWwgeWFuZyBtZW5ndW50dW5na2FuIHNlcGVydGkga2VsdWFyIGRhcmkgcnVtYWggc2FraXQuIERhbiBkZW5nYW4gZGVtaWtpYW4sIGFuYWxpc2lzIHN1cnZpdmFsIGp1Z2EgbWVydXBha2FuIGlzdGlsYWggdW11bSwga2FyZW5hIGluaSBidWthbiBoYW55YSB0ZW50YW5nIGtlbGFuZ3N1bmdhbiBoaWR1cC4NCg0KS2VqYWRpYW4sIHNlYmFnYWkgdGl0aWsgd2FrdHUgeWFuZyB0ZXRhcCBkaXBlcmx1a2FuIGthcmVuYSB0aWRhayBkYXBhdCBkaWxha3VrYW4gcGVuZ2FtYXRhbiBhdGF1IGJlcmVrc3BlcmltZW4gc2VsYW1hbnlhLiBKaWthIGRpcGVsYWphcmkga2Fua2VyIHBhcnUtcGFydSwgbWFrYSB0aWRhayBiaXNhIG1lbnVuZ2d1IHNhbXBhaSBwYXNpZW4gbWVuaW5nZ2FsIGthcmVuYSBwZW55ZWJhYiBsYWluLCBtaXNhbG55YSBrYXJlbmEgc3VkYWggdHVhLiBIYW55YSBrZXRpa2EgYmViZXJhcGEgcGFzaWVuIHNlbGFtYXQgZGFyaSBrYW5rZXIsIGF0YXUgYmViZXJhcGEgbW9iaWwgdGlkYWsgcnVzYWsgcGFkYSB3YWt0dSB0ZXJ0ZW50dSAocGVyaXN0aXdhKSwga2l0YSBiaXNhIG1lbmRhcGF0a2FuIHdhd2FzYW4geWFuZyBiZXJoYXJnYS4gTWlzYWxueWEsIGJlcmFwYSBsYW1hIHdha3R1IGRhcmkgYXdhbCBwZW5nb2JhdGFuIGhpbmdnYSBwZXJrZW1iYW5nYW5ueWEsIGF0YXUgYmVyYXBhIHByb2JhYmlsaXRhcyB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBkYXJpIGthbmtlciBwYXJ1LXBhcnUgc2V0ZWxhaCB0ZXBhdCAxIHRhaHVuPyBTZWxhaW4gaXR1LCBoYWwgaW5pIG1lbWJ1a2Ega2VtdW5na2luYW4gdW50dWsgbWVtYmFuZGluZ2thbiB3YWt0dSBrZWxhbmdzdW5nYW4gaGlkdXAgYXRhdSBrZWdhZ2FsYW4gZGkgYW50YXJhIGtlbG9tcG9rIHlhbmcgYmVyYmVkYSwgbWlzYWxueWEga2Fua2VyIHBhcnUtcGFydSBhbnRhcmEgcGVyb2tvayBkYW4gbm9uLXBlcm9rb2ssIGF0YXUgd2FrdHUga2VydXNha2FuIGFudGFyYSBtb2JpbCBKZXJtYW4gZGFuIEtvcmVhLg0KDQoNCipQZW55ZW5zb3JhbioNCg0KU2Vuc29yaW5nIGRpcGVybHVrYW4ga2FyZW5hIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCB5YW5nIHNlYmVuYXJueWEgdGlkYWsgYWthbiBkaWtldGFodWkgb2xlaCBiZWJlcmFwYSBpbmRpdmlkdS4gQWRhIGJhbnlhayBjYXJhIHVudHVrIGtlaGlsYW5nYW4gc3ViamVrIHN0dWRpOg0KDQoxLiBEYXBhdCBrZWhpbGFuZ2FuIHNlc2VvcmFuZyB0YW5wYSBhbGFzYW4sIGtldGlrYSBpdHUgdGlkYWsgbXVuY3VsIGxhZ2kNCg0KMi4gSW5kaXZpZHUgbXVuZ2tpbiBtZW5nYWxhbWkgcGVyaXN0aXdhIGxhaW4sIG1pc2FsbnlhIGtlbWF0aWFuIGF0YXUga2VjZWxha2Fhbg0KDQozLiBCYWhrYW4gcGFzaWVuIHlhbmcgYmVydGFoYW4gaGluZ2dhIGFraGlyIHBlbmVsaXRpYW4gZGFwYXQgZGlwZXJsYWt1a2FuIHNlYmFnYWkgZGlzZW5zb3Iga2FyZW5hIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCB5YW5nIHRpZGFrIGRpa2V0YWh1aSANCg0KU2VtdWEgY29udG9oIGRpIGF0YXMgZGlhbmdnYXAgc2ViYWdhaSBzZW5zb3Jpbmcga2FuYW4ga2FyZW5hIGFyYWhueWEgZGFyaSBraXJpIGtlIGthbmFuIHBhZGEgc3VtYnUgd2FrdHUuIFNlYmFnaWFuIGJlc2FyIGRhdGEga2VsYW5nc3VuZ2FuIGhpZHVwIGRpc2Vuc29yIGRlbmdhbiBiZW5hci4gQWRhIGR1YSBqZW5pcyBzZW5zb3JpbmcgbGFpbm55YS4gU2Vuc29yIGtpcmkgbXVuY3VsIGppa2EgdGlkYWsgdGFodSBkYXJpIG1hbmEgcGVueWFraXQgaXR1IGJlcm11bGEsIHNlZGFuZ2thbiBzZW5zb3IgaW50ZXJ2YWwgdGVyamFkaSBrZXRpa2Egd2FrdHUgcGFzdGkga2VoaWxhbmdhbiBwYXNpZW4gdGlkYWsgZGlrZXRhaHVpLCB0ZXRhcGkgaGFueWEgamVuZGVsYSB3YWt0dS4gU2Vuc29yaW5nIGtpcmkgZGFuIGludGVydmFsIGphcmFuZyB0ZXJqYWRpLCBzdWxpdCBkaWFuYWxpc2lzLCBzZXJpbmdrYWxpIG1lcnVwYWthbiBoYXNpbCBkYXJpIGRlc2FpbiBzdHVkaSB5YW5nIGJ1cnVrLg0KDQojIyBDYXJhIG1lbmdoaXR1bmcga3VydmEgc3Vydml2YWwgS2FwbGFuLU1laWVyICJzZWNhcmEgbWFudWFsIiBsYW5na2FoIGRlbWkgbGFuZ2thaA0KDQpEZW5nYW4gbWVtYmF5YW5na2FuIGhhcmkgeWFuZyBjZXJhaCBkYW4gZGFtYWkgdGVwYXQgc2ViZWx1bSBrZWNlbGFrYWFuIFRpdGFuaWMgdGVyamFkaS4gVGlkYWsgYWRhIHlhbmcgbWVuaW5nZ2FsLCB0ZXRhcGkgc2VtdWEgMTAgb3JhbmcgYmVyaXNpa28gdGluZ2dpIChiYWhheWEpIG1lbmluZ2dhbCwgaGFueWEgc2FqYSBtZXJla2EgYmVsdW0gbWVuZ2V0YWh1aW55YS4gRGFwYXQgbWVuZWJhayBiZXJhcGEgYmFueWFrIG9yYW5nIHlhbmcgbXVuZ2tpbiBha2FuIG1lbmluZ2dhbCBzZWhhcmkgc2ViZWx1bSBrZWNlbGFrYWFuLiBKYXdhYmFubnlhIGFkYWxhaCAtIG11bmdraW4gbm9sLiBTZWNhcmEgaGFyZmlhaCwga2VtdW5na2luYW4ga2VtYXRpYW4gYWRhbGFoIG5vbCwga2FyZW5hIGtpdGEgdGFodSBiYWh3YSBrZWNlbGFrYWFuIHRpZGFrIGFrYW4gdGVyamFkaSBzZWhhcmkgc2ViZWx1bSB0YWJyYWthbiB5YW5nIHNlYmVuYXJueWEuIFVudHVrIG1lbmphd2FiIHBlcnRhbnlhYW4gaW5pIGRlbmdhbiBsZWJpaCB0ZXBhdCwga2l0YSBwZXJsdSBtZW5naW5nYXQgZGVmaW5pc2kgcHJvYmFiaWxpdGFzOiAqUHJvYmFiaWxpdGFzIGFkYWxhaCByYXNpbyBkYXJpIHNlc3VhdHUgeWFuZyB0ZXJqYWRpLCB0ZXJoYWRhcCBzZWdhbGEgc2VzdWF0dSB5YW5nIGRhcGF0IHRlcmphZGkuKiBKYWRpLCBqaWthIHRpZGFrIGFkYSBzZW9yYW5nIHB1biBkYXJpIDEwIG9yYW5nIHlhbmcgbWVuaW5nZ2FsIHNlaGFyaSBzZWJlbHVtIGtlY2VsYWthYW4sIG1ha2EgcHJvYmFiaWxpdGFzIGtlbWF0aWFubnlhIGFkYWxhaCAwJSwgc2VkYW5na2FuIHByb2JhYmlsaXRhcyBzZWxhbWF0IGFkYWxhaCAxMDAlOg0KDQokJCBwcm9iYWJpbGl0eSBcIG9mIFwgZHlpbmcgPSBcZnJhY3swfXsxMH0gPSAwJCQNCg0KJCQgcHJvYmFiaWxpdHkgXCBvZiBcIHN1cnZpdmluZyA9IFxmcmFjezEwfXsxMH0gPSAxICA9IDEwMFwlJCQNCg0KVW50dWsgcmVwcmVzZW50YXNpIHlhbmcgbGViaWggYmFpaywgbWFyaSBraXRhIGxldGFra2FuIHNlbXVhIGFuZ2thIGRhbGFtIHNhdHUgdGFiZWw6DQoNCmBgYHtyfQ0KdHJpYmJsZSgNCiAgfnRpbWVfaW5fZGF5cywgfk5fYXRfcmlzaywgfk5fZGllZCwgflBfZHlpbmcsIH5gUF9zdXJ2aXZpbmdgLA0KICAwLCAxMCwgMCwgIjAvMTAgPSAwIiwgIjEwLzEwID0gMSINCikgJT4lIGthYmxlKCkNCmBgYA0KDQpLZW11ZGlhbiwgcGFkYSBoYXJpIGtlY2VsYWthYW4gLCBkaSBtYW5hIHNlbXVhIDEwIG9yYW5nIHNla2FyYW5nIHRhaHUgYmFod2EgbWVyZWthIGJlcmlzaWtvIHRpbmdnaSBtZW5pbmdnYWwsIDMgZGFyaSBtZXJla2EgYmVuYXItYmVuYXIgbWVuaW5nZ2FsLiBQcm9iYWJpbGl0YXMga2VtYXRpYW4gcGFkYSBoYXJpIHBlcnRhbWEgYWRhbGFoIGtlbXVkaWFuICQzLzEwID0gMC4zIFxhcHByb3ggMzBcJSQgZGFuIGtlbXVuZ2tpbmFuIGJlcnRhaGFuIGhpZHVwIGFkYWxhaCAkNy8xMCA9IDAuNyBcYXBwcm94IDcwXCUkLiBTZWhpbmdnYSBrZWxhbmdzdW5nYW4gaGlkdXAganVnYSBkYXBhdCBkaWhpdHVuZyBkYXJpIGtlbXVuZ2tpbmFuIGtlbWF0aWFuICQxLTAuMyA9IDAuNyQuDQoNCiMjICpQZWx1YW5nIFN1cnZpdmFsKg0KDQpTYXR1IG1vbWVuIHBlbnRpbmcgZGkgc2luaSBhZGFsYWggYmFod2EgKmtlbXVuZ2tpbmFuIHVudHVrIGJlcnRhaGFuIGhpZHVwIGJlcnNpZmF0IGt1bXVsYXRpZiosIHlhbmcgYmVyYXJ0aSAqdGVyYWt1bXVsYXNpKiBkYXJpIGhhcmkga2UgaGFyaS4gQWt1bXVsYXNpIGluaSB0ZXJqYWRpIG1lbGFsdWkgKm1lbmdhbGlrYW4gcHJvYmFiaWxpdGFzIGJhcnUgdW50dWsgYmVydGFoYW4gaGlkdXAgcGFkYSBoYXJpIGtlLTEqICQoMSAtIFxmcmFje2RfaX17bl9pfSkgPSAoMSAtIFxmcmFjezN9ezEwfSkgPSA3MFwlJCBkZW5nYW4gKnByb2JhYmlsaXRhcyBsYW1hKiB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBzZXBhbmphbmcgd2FrdHUgc2ViZWx1bW55YSwgeWFuZyBkYWxhbSBrYXN1cyBrYW1pIGFkYWxhaCBzZWhhcmkgc2ViZWx1bSBrZWNlbGFrYWFuLCBhdGF1IC0gaGFyaSBrZS1ub2wgJFModF97aS0xfSkgPSAxMDBcJSQ6DQoNCiQkIFModF9pKSA9IFModF97aS0xfSkqKDEgLSBcZnJhY3tkX2l9e25faX0pID0gMSAqICgxIC0gXGZyYWN7M317MTB9KSA9IDAuNyAkJA0KDQpEaW1hbmEsDQoNCi0gJFModF97aeKIkjF9KSQgPSBwcm9iYWJpbGl0YXMgdW50dWsgaGlkdXAgZGkgJHRfe2niiJIxfSQNCi0gJG5faSQgPSBqdW1sYWggcGFzaWVuIHlhbmcgbWFzaWggaGlkdXAgc2ViZWx1bSAkdF9pJA0KLSAkZF9pJCA9IEp1bWxhaCBrZWphZGlhbiBzYWF0ICR0X2kkDQotICR0XzAkID0gMCwgJFMoMCkkID0gMQ0KDQpQcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgcGFkYSB3YWt0dSB0ZXJ0ZW50dSwgJFModCkkLCBhZGFsYWggKnN5YXJhdCBrYXJlbmEgb3JhbmcgdGVyc2VidXQgaGFydXMgYmVydGFoYW4gaGlkdXAgc2V0ZWxhaCB3YWt0dSB0ZXJ0ZW50dSosIG1pc2FsbnlhIGhhcmkga2Utbm9sIChpdHVsYWggc3lhcmF0bnlhKSB1bnR1ayB0ZXRhcCBiZXJhZGEgZGFsYW0gZWtzcGVyaW1lbiB1bnR1ayBoYXJpIHBlcnRhbWEuDQoNCmBgYHtyfQ0KdHJpYmJsZSgNCiAgfnRpbWVfaW5fZGF5cywgfk5fYXRfcmlzaywgfk5fZGllZCwgflBfZHlpbmcsIH5gUF9zdXJ2aXZpbmdgLA0KICAwLCAxMCwgMCwgIjAvMTAgPSAwIiwgICAiMTAvMTAgICAgICA9IDEiLA0KICAxLCAxMCwgMywgIjMvMTAgPSAwLjMiLCAiMSAqICg3LzEwKSA9IDAuNyIsDQopICU+JSBrYWJsZSgpDQpgYGANCg0KKlBhZGEgaGFyaSBrZWR1YSogc2VkaWtpdCBsZWJpaCBtZW5hcmlrLCBrYXJlbmEgc2F0dSBvcmFuZyBtZW5pbmdnYWwgZGFuIHNhdHUgb3JhbmcgaGlsYW5nIGJlZ2l0dSBzYWphIChzdGF0dXMgPSAwKS4gT3JhbmcgeWFuZyBoaWxhbmcgaW5pIGtlbXVuZ2tpbmFuIGJlc2FyIHRlcmJhd2Egb21iYWsgZGFuIG11ZGFoLW11ZGFoYW4gYmlzYSBkaXNlbGFtYXRrYW4uIEhhcmFwYW5ueWEgYmVzYXIsIGthcmVuYSBzZW1ha2luIGphdWggb3JhbmcgdGVyc2ViYXIgZGkgbGF1dGFuLCBzZW1ha2luIGJlc2FyIGtlbXVuZ2tpbmFuIHNhbGFoIHNhdHUgZGFyaSBtZXJla2EgYWthbiBkaXRlbXVrYW4gZGFsYW0ga2VhZGFhbiBoaWR1cC4gRGFuIGhhbCBpbmkgYWthbiBtZW1iZXJpIHRhaHUgZHVuaWEgYmFod2EgYWRhIG9yYW5nIGxhaW4geWFuZyBtYXNpaCBiZXJhZGEgZGkgbHVhciBzYW5hLiBKYWRpLCBtZXNraXB1biBvcmFuZyBoaWxhbmcgdGVybGloYXQgYnVydWssIGhhbCBpbmkgYmlzYSBqYWRpIG1lcnVwYWthbiBoYWwgeWFuZyBiYWlrLiBKYWRpLCBraXRhIHRlbnR1IHRpZGFrIGJpc2EgbWVuZ2FuZ2dhcCBvcmFuZyB5YW5nIGhpbGFuZyBzZWJhZ2FpIG9yYW5nIHlhbmcgc3VkYWggbWF0aS4gU2VsYWluIGl0dSwgc2VwZXJ0aSBrYXRhIHBlcGF0YWggSmVybWFuOiAiSGFyYXBhbiBhZGFsYWggeWFuZyB0ZXJha2hpciBtYXRpIi4gDQoNClRldGFwaSBrYXJlbmEga2l0YSBqdWdhIHRpZGFrIHlha2luIGFwYWthaCBvcmFuZyBpbmkgbWFzaWggaGlkdXAsIGtpdGEgdGlkYWsgYmlzYSBtZW5nYXRha2FuIC0gb3JhbmcgdGVyc2VidXQgc2VsYW1hdC4gSGFsIGluaSBtZW5pbWJ1bGthbiBkaWxlbWE6IG1lc2tpcHVuIHRpZGFrIG1lbmluZ2dhbCwgb3JhbmcgdGVyc2VidXQgYnVrYW4gYmFnaWFuIGRhcmkgZWtzcGVyaW1lbiBrYW1pIGxhZ2kgZGFuIGthbWkgaGFydXMgbWVuZ2hhcHVzbnlhIGRhcmkganVtbGFoIG9yYW5nIHlhbmcgYmVyaXNpa28uIEphZGksIHNlbWVudGFyYSAqaGFyaSBrZWR1YSogYWthbiBtZW1pbGlraSA3IG9yYW5nIHlhbmcgYmVyaXNpa28geWFuZyB0ZXJzaXNhIChrYXJlbmEgMyBvcmFuZyB0ZWxhaCBtZW5pbmdnYWwgZGkgaGFyaSBwZXJ0YW1hKSwgKmhhcmkga2V0aWdhKiBha2FuIHRlcnNpc2EgaGFueWEgNSBvcmFuZywga2FyZW5hIDEgb3JhbmcgbWVuaW5nZ2FsIGRhbiBzYXR1IG9yYW5nIG1lbmdoaWxhbmcgKGRpc2Vuc29yKSBkaWJhbmRpbmdrYW4gZGVuZ2FuIGhhcmkga2VkdWEuIFNhbWEgaGFsbnlhIGRlbmdhbiBoYXJpIHBlcnRhbWEsIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgYmVyc2lmYXQga3VtdWxhdGlmIGRhbiBzZWxhbHUgbWVueWVydGFrYW4gcHJvYmFiaWxpdGFzIGhhcmkgc2ViZWx1bW55YS4NCg0KYGBge3J9DQp0cmliYmxlKA0KICB+dGltZV9pbl9kYXlzLCB+Tl9hdF9yaXNrLCB+Tl9kaWVkLCB+UF9keWluZywgfmBQX3N1cnZpdmluZ2AsDQogIDAsIDEwLCAwLCAiMC8xMCA9IDAiLCAgICAiMTAvMTAgICAgICAgPSAxIiwNCiAgMSwgMTAsIDMsICIzLzEwID0gMC4zIiwgICIxICogKDcvMTApICA9IDAuNyIsDQogIDIsIDcsICAxLCAiMS83ICA9IDAuMTQiLCAiMC43ICogKDYvNykgPSAwLjYiLA0KICAzLCA1LCAgMSwgIjEvNSAgPSAwLjIwIiwgIjAuNiAqICg0LzUpID0gMC40OCINCikgJT4lIGthYmxlKCkNCmBgYA0KDQoqUGFkYSBkdWEgaGFyaSBiZXJpa3V0bnlhKiwgZHVhIG9yYW5nIG1lbmdoaWxhbmcsIGphZGkga2l0YSBtZW55ZW5zb3IgbWVyZWthLiBUaWRhayBwZXJsdSBtZW5naGl0dW5nIHNlc3VhdHUgdW50dWsgZGF0YSB5YW5nIGRpc2Vuc29yIGRhbGFtIGFuYWxpc2lzIGtlbGFuZ3N1bmdhbiBoaWR1cCwga2FyZW5hIGtpdGEgdGlkYWsgdGFodSBhcGFrYWggbWVyZWthIHNlbGFtYXQgYXRhdSB0aWRhay4gRGFuIGthcmVuYSBraXRhIHRlcnRhcmlrIHBhZGEga2VsYW5nc3VuZ2FuIGhpZHVwIGF0YXUga2VtYXRpYW4sIHRhYmVsIGFraGlyIGRpIGJhd2FoIGluaSBiZXJpc2kga2FzdXMgeWFuZyAqaGFueWEgbWF0aSouIFBhZGEgKmhhcmkga2UgNiogdGlkYWsgYWRhIHlhbmcgbWF0aSBhdGF1IG1lbmdoaWxhbmcsIG9sZWgga2FyZW5hIGl0dSBrYW1pIGp1Z2EgdGlkYWsgbWVuZ2hpdHVuZyBhcGEgcHVuIHVudHVrIGhhcmkgaXR1LiBPcmFuZyB0ZXJha2hpciBkYWxhbSBla3NwZXJpbWVuIGthbWkgbWVuaW5nZ2FsIHBhZGEgKmhhcmkga2UgNyouIEphZGksICJOX21lbmluZ2dhbCIgYWthbiBtZW5qYWRpIDEsIGRhbiAiTl9iZXJpc2lrbyIgYWthbiBtZW5qYWRpIDIsIGthcmVuYSAxIGRhcmkgNSBvcmFuZyB5YW5nIHRlcnNpc2EgdGVsYWggbWVuaW5nZ2FsIGRhbiAyIG9yYW5nIGRpc2Vuc29yLiBEZW5nYW4gZGVtaWtpYW4sIHRhYmVsIHlhbmcgZGloaXR1bmcgc2VjYXJhICJtYW51YWwiIGFrYW4gdGVybGloYXQgOg0KDQpgYGB7cn0NCnRyaWJibGUoDQogIH50aW1lX2luX2RheXMsIH5OX2F0X3Jpc2ssIH5OX2RpZWQsIH5QX2R5aW5nLCB+YFBfc3Vydml2aW5nYCwNCiAgMCwgMTAsIDAsICIwLzEwID0gMCIsICAgICIxMC8xMCAgICAgICAgPSAxIiwNCiAgMSwgMTAsIDMsICIzLzEwID0gMC4zIiwgICIxICogKDcvMTApICAgPSAwLjciLA0KICAyLCA3LCAgMSwgIjEvNyAgPSAwLjE0IiwgIjAuNyAqICg2LzcpICA9IDAuNiIsDQogIDMsIDUsICAxLCAiMS81ICA9IDAuMjAiLCAiMC42ICogKDQvNSkgID0gMC40OCIsDQogIDcsIDIsICAxLCAiMS8yICA9IDAuNTAiLCAiMC40OCAqICgxLzIpID0gMC4yNCINCikgJT4lIGthYmxlKCkNCmBgYA0KDQoNCk5hbXVuLCBhcGEgeWFuZyBha2FuIHRlcmphZGkgKmppa2Ega2l0YSBtZW5nYWJhaWthbiBwZW55ZW5zb3JhbiogZGFuIGhhbnlhIG1lbmdoaXR1bmcgcHJvYmFiaWxpdGFzIHVudHVrIHRpZGFrIG1hdGk/IERpa2FyZW5ha2FuIDQgb3JhbmcgdGlkYWsgbWF0aSBwYWRhIGhhcmkga2UtNywgcHJvYmFiaWxpdGFzIHVudHVrIGJlcnRhaGFuIGhpZHVwIGFrYW4gbWVuamFkaSAkXGZyYWN7NH17MTB9ID0gNDBcJSQgeWFuZyBoYW1waXIgZHVhIGthbGkgbGlwYXQgbGViaWggdGluZ2dpLCBkYW4gZGVuZ2FuIGRlbWlraWFuIGtpdGEgYWthbiAqbWVsZWJpaGthbiBwcm9iYWJpbGl0YXMgdW50dWsgYmVydGFoYW4gaGlkdXAqLCBkaWJhbmRpbmdrYW4gZGVuZ2FuIHByb2JhYmlsaXRhcyBzZWJlbmFybnlhIHlhaXR1IDAsMjQgeWFuZyBtZW1wZXJoaXR1bmdrYW4gcGVueWVuc29yYW4uDQoNCipTVU1CRVIqDQoNCkhhbnlhIG1lbXBlcmhhdGlrYW4gb3JhbmcgeWFuZyBzZWxhbWF0KiBiYWhrYW4gbWVtaWxpa2kgbmFtYSAtIGJpYXMgcGVueWludGFzLCBkYW4gYWRhIGNlcml0YSBrZWNpbCBkaSBiYWxpa255YS4gU2VsYW1hIFBlcmFuZyBEdW5pYSBLZWR1YSwgYmViZXJhcGEgcGVzYXdhdCBrZW1iYWxpIGRhcmkgbWVkYW4gcGVyYW5nIGRlbmdhbiBiYW55YWsga2VydXNha2FuIGFraWJhdCBwZWx1cnUuIE1lcmVrYSBoYW1waXIgdGlkYWsgYmlzYSB0ZXJiYW5nLCB0YXBpIG1lcmVrYSB0ZXRhcCBrZW1iYWxpLiBKYWRpLCBwaWhhayBtaWxpdGVyIG1lbXV0dXNrYW4gdW50dWsgbWVsaW5kdW5naSBwZXNhd2F0IGRlbmdhbiBsZWJpaCBiYW55YWsgcGVsaW5kdW5nIGRpIGJhZ2lhbiB5YW5nIHBhbGluZyBiYW55YWsgbHViYW5nIHBlbHVydSwgc2VwZXJ0aSBzYXlhcCwgZGFuIG1lbmd1cmFuZ2kgcGVsaW5kdW5nIGRpIGJhZ2lhbiB5YW5nIHRpZGFrIGJlcmx1YmFuZyBwZWx1cnUuIEFuZWhueWEsIHBlcnNlbnRhc2UgcGVzYXdhdCB5YW5nIGtlbWJhbGkgdGlkYWsgbWVuaW5na2F0LiBQYXJhIGluc2lueXVyIGJpbmd1bmchIEhpbmdnYSBzZW9yYW5nIGFobGkgbWF0ZW1hdGlrYSwgQWJyYWhhbSBXYWx0LCB5YW5nIGRpdW5kYW5nIHVudHVrIG1lbWVjYWhrYW4gbWFzYWxhaCBpbmkgYmVya2F0YTogIlBhc2FuZyBsZWJpaCBiYW55YWsgbGFwaXMgYmFqYSBkaSB0ZW1wYXQtdGVtcGF0IHlhbmcgdGlkYWsgbWVtaWxpa2kgbHViYW5nIHBlbHVydSwga2FyZW5hIGppa2EgdGVtcGF0IGluaSBkaXRlbWJhaywgcGVzYXdhdCB0aWRhayBha2FuIGtlbWJhbGkuIiBEYW4ga2V0aWthIHlhbmcgbGFpbiBtZW1pa2lya2FubnlhLCBtZXJla2EgbWVueWFkYXJpIGJhaHdhIHNlbXVhIHBlc2F3YXQgeWFuZyBrZW1iYWxpIHRpZGFrIG1lbWlsaWtpIGx1YmFuZyBwZWx1cnUgZGkga29rcGl0IGF0YXUgbWVzaW4uIEx1YmFuZyBwZWx1cnUgbWVudW5qdWtrYW4gc2VtdWEgdGVtcGF0IGRpIG1hbmEgcGVzYXdhdCBiaXNhIGRpdGVtYmFrIHRhcGkgbWFzaWggYmlzYSBrZW1iYWxpLCBhdGF1IHNlbGFtYXQhIEl0dWxhaCB5YW5nIGRpc2VidXQgZGVuZ2FuIGJpYXMgYmVydGFoYW4gaGlkdXAuIEphZGksIG1lbnVydXQgc2F5YSwgcmVncmVzaSBsb2dpc3RpayBtZW1pbGlraSBzdXJ2aXZvcnNoaXAgYmlhcyBkaWJhbmRpbmdrYW4gZGVuZ2FuIGFuYWxpc2lzIGtldGFoYW5hbiBoaWR1cCBqaWthIGtpdGEgaW5naW4gbWVuZ2FuYWxpc2lzIGRhdGEga2V0YWhhbmFuIGhpZHVwLg0KDQojIyBDYXJhIG1lbmdoaXR1bmcga3VydmEgc3Vydml2YWwgS2FwbGFuLU1laWVyDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpICAjIGRhdGEgd3JhbmdsaW5nIGFuZCB2aXN1YWxpemF0aW9uDQpsaWJyYXJ5KGtuaXRyKSAgICAgICMgYmVhdXRpZnlpbmcgdGFibGVzDQpsaWJyYXJ5KGNhcikgICAgICAgICMgZm9yIGNoZWNraW5nIGFzc3VtcHRpb25zLCBlLmcuIHZpZiBldGMuDQpsaWJyYXJ5KGJyb29tKSAgICAgICMgZm9yIHRpZHkgbW9kZWwgb3V0cHV0DQpsaWJyYXJ5KHNqUGxvdCkgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KHNqbWlzYykgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KGVmZmVjdHMpICAgICMgZm9yIHByb2JhYmlsaXR5IG91dHB1dCBhbmQgcGxvdHMNCmBgYA0KDQpQYWRhIHJlZ3Jlc2kgbG9naXN0aWsgMSBhZGFsYWgga2VsYW5nc3VuZ2FuIGhpZHVwLCBzZWRhbmdrYW4gZGFsYW0gYW5hbGlzaXMga2VsYW5nc3VuZ2FuIGhpZHVwIDEgYWRhbGFoIGtlbWF0aWFuLiBLZWR1YSwgbWVtYmVkYWthbiBrYXN1cyB5YW5nIGRpc2Vuc29yLCBtaXNhbG55YSBkYXBhdCBtZW5hbmRhaW55YSBkZW5nYW4gdGFuZGEgcGx1cyBkaSBkYXRhIGF0YXUgZGkgcGxvdC4gRGF0YSBkaSBiYXdhaCBpbmkgbWVudW5qdWtrYW4gYmFod2Egb3JhbmcgZGlzZW5zb3IgcGFkYSBoYXJpIGtlIDIrLCA0KywgNSsgZGFuIDEwKy4gSW5zdGFsIGRhbiBtdWF0IHN1cnZpdmFscGFrZXQgdW50dWsgZGFwYXQgbWVuZ2Vrc2VrdXNpIGtvZGUgZGkgYmF3YWggaW5pOg0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygic3Vydml2YWwiKQ0KbGlicmFyeShzdXJ2aXZhbCkNCg0KU3Vydih0aW1lID0gZCR0aW1lLCBldmVudCA9IGQkc3RhdHVzKQ0KYGBgDQoNCkZ1bmdzaSBgU3VydmAgbWVueWF0dWthbiBkYXRhICJ3YWt0dSIgZGFuICJzdGF0dXMiIGtlIGRhbGFtIHNhdHUgb2JqZWsgInN1cnZpdmFsIiB0dW5nZ2FsLCB5YW5nIG1lbXVuZ2tpbmthbiB1bnR1ayAibWVtcGVyaGl0dW5na2FuIHBlbmdhbWF0YW4geWFuZyBkaXNlbnNvciIuIE9iamVrIGluaSBrZW11ZGlhbiBkYXBhdCBkaWd1bmFrYW4gdW50dWsgbWVtb2RlbGthbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGRlbmdhbiBmdW5nc2kgYHN1cnZmaXRgLiBLaXRhIG1lbW9kZWxrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGRlbmdhbiBtZW5hbWJhaGthbiAifjEiIHBhZGEgb2JqZWsgdGVyc2VidXQsIGRpIG1hbmEgMSBiZXJhcnRpIHRpZGFrIGFkYSB2YXJpYWJlbCB5YW5nIGRhcGF0IG1lbXBlbmdhcnVoaSBrZWxhbmdzdW5nYW4gaGlkdXAuIE9iamVrIGtlbGFuZ3N1bmdhbiBoaWR1cCBraXRhIGRpIHNpc2kga2lyaSB0aWxkZSBhZGFsYWggdmFyaWFiZWwgcmVzcG9ucyBkYW4gZGkgc2lzaSBrYW5hbiB+ICh0aWxkZSkgYWRhbGFoIHByZWRpa3RvciwgYXRhdSBkYWxhbSBrYXN1cyAiMSIgLSB0aWRhayBhZGEuU2VsYW5qdXRueWEgZGFwYXQgZGlidWF0IG1vZGVsIHN1cnZpdmFsIHBlcnRhbWEgIGRhbiBtZWxpaGF0IGtlbHVhcmFuIG1vZGVsbnlhOg0KDQpgYGB7cn0NCnN1cnZpdmFsX21vZGVsIDwtIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gMSwgZGF0YSA9IGQpDQoNCiMgc21hbGwgc3VtbWFyeQ0Kc3Vydml2YWxfbW9kZWwNCmBgYA0KRGltYW5hIGFrYW4gZGlkYXBhdA0KLSAqbiogLSBqdW1sYWggcGVzZXJ0YSwgDQotICpldmVudCogLSBqdW1sYWgga2VtYXRpYW4sIHlhbmcgc2VjYXJhIHVtdW0gZGlzZWJ1dCAqZXZlbnQqIGthcmVuYSBkYXBhdCBtZW1wZWxhamFyaSBqZW5pcy1qZW5pcyAiKmRlYWQqbGluZXMiIGxhaW5ueWEsIHNlcGVydGkga2FtYnVobnlhIHBlbnlha2l0LCBhdGF1IGtlcnVzYWthbiBwZXJ0YW1hIHBhZGEgbW9iaWwsDQotIHBlcmtpcmFhbiB3YWt0dSBiZXJ0YWhhbiBoaWR1cCAqbWVkaWFuKiwgYnVrYW4gcmF0YS1yYXRhIGthcmVuYSBzaWZhdCBub24tcGFyYW1ldHJpayAoZGlqZWxhc2thbiBuYW50aSkgZGFyaSBhbmFsaXNpcyBrZXRhaGFuYW4gaGlkdXAgZGFuDQotIEludGVydmFsIGtlcGVyY2F5YWFuIDk1JSoqIHVudHVrIHdha3R1IGtldGFoYW5hbiBoaWR1cCBtZWRpYW4NCg0KTGViaWggYmFueWFrIGluZm9ybWFzaSBkYXBhdCBkaW5pbGFpIGRlbmdhbiBmdW5nc2kgYHJpbmdrYXNhbmAsIHlhbmcgbWVtYmVyaWthbiB0YWJlbCB5YW5nIHNhbWEgZGVuZ2FuIHBlcmhpdHVuZyBzZWNhcmEgbWFudWFsIGRpIGF0YXM6DQoNCmBgYHtyfQ0KIyBiaWcgc3VtbWFyeQ0Kc3VtbWFyeShzdXJ2aXZhbF9tb2RlbCkNCmBgYA0KDQpTZWhpbmdnYSBkYXBhdCBkaWxpaGF0IGJhaHdhIHBlcmhpdHVuZ2FuIHNlYmVsdW15YSBiZW5hciBkYW4gdGVsYWggYmVyaGFzaWwgbWVtcGVsYWphcmkgY2FyYSBtZWxha3VrYW4gYW5hbGlzaXMgc3Vydml2YWwuIFNlaGluZ2dhIG11bGFpIHNla2FyYW5nIGRhcGF0IG11bGFpIG1lbmdndW5ha2FuIHBlcmFuZ2thdCBsdW5hay4gUGVyYW5na2F0IGx1bmFrIGluaSBtZW1pbGlraSBiYW55YWsga2V1bnR1bmdhbi4gU2ViYWdhaSBjb250b2gsIGZ1bmdzaSBgc3VtbWFyeWAsIHlhbmcgaGFueWEgbWVuYW1waWxrYW4gaGFzaWwgZGFyaSBrYXN1cyB5YW5nIG1hdGksIGRhcGF0IGRpaXNpIGRlbmdhbiBhcmd1bWVuIHRhbWJhaGFuIGBjZW5zb3JlZCA9IFRSVUVgLCB5YW5nIG1lbmFtcGlsa2FuIHNlbXVhIGthc3VzLCBiYWlrIHlhbmcgbWF0aSBtYXVwdW4geWFuZyBkaXNlbnNvcjoNCg0KYGBge3J9DQpzdW1tYXJ5KHN1cnZpdmFsX21vZGVsLCBjZW5zb3JlZCA9IFQpDQpgYGANCg0KU2VsYW5qdXRueWEgZGFwYXQgbWVuZW50dWthbiBoYXNpbCBkYXJpIGhhcmkgbWFuYSB5YW5nIGluZ2luIGRpbGloYXQgZGVuZ2FuIG1lbmFtYmFoa2FuIGFyZ3VtZW4gYHRpbWVzID0gLi4uYCBrZSBmdW5nc2kgYHN1bW1hcnlgLiBCYWhrYW4gZGFwYXQganVnYSBtZW1pbnRhIGhhcmktaGFyaSB5YW5nIHRpZGFrIHRlcnNlZGlhIGRhdGFueWEsIG1pc2FsbnlhIGhhcmkga2UtOCBhdGF1IGtlLTkgZGFsYW0gY29udG9oIHNlZGVyaGFuYSBraXRhLiBTZWJhZ2FpIGNvbnRvaCwgcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCBzZXRlbGFoIGhhcmkga2UtOCBhZGFsYWggMjQlOg0KDQpgYGB7cn0NCnN1bW1hcnkoc3Vydml2YWxfbW9kZWwsIHRpbWVzID0gYyg4LCA5KSkNCmBgYA0KDQpTZWthcmFuZywga2FyZW5hIGtpdGEgbWVuZ2V0YWh1aSBwcm9iYWJpbGl0YXMgeWFuZyB0ZXBhdCB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBwYWRhICpzZXRpYXAgaGFyaSosIGJhaGthbiBwYWRhIGhhcmktaGFyaSBkaW1hbmEga2l0YSB0aWRhayBtZW1pbGlraSBkYXRhbnlhLCBraXRhIGRhcGF0IG1lbXZpc3VhbGlzYXNpa2FuIGhhc2lsIG1vZGVsLiBJbnN0YWxsIGRhbiBtdWF0IHBha2V0IGBzdXJ2bWluZXJgIHVudHVrIGRhcGF0IG1lbmphbGFua2FuIGtvZGUgZGkgYmF3YWggaW5pOg0KDQpgYGB7ciBldmFsID0gRkFMU0V9DQojIGluc3RhbGwucGFja2FnZXMoInN1cnZtaW5lciIpDQpsaWJyYXJ5KHN1cnZtaW5lcikNCmdnc3VydnBsb3QoDQogIHN1cnZpdmFsX21vZGVsLCANCiAgY29uZi5pbnQgPSBGQUxTRSwgDQogIHN1cnYubWVkaWFuLmxpbmUgPSAiaHYiLA0KICB4bGFiID0gIkRheXMiLCANCiAgeWxhYiA9ICJTdXJ2aXZhbCBwcm9iYWJpbGl0eSIsIA0KICBicmVhay50aW1lLmJ5ID0gMSwNCiAgcmlzay50YWJsZSA9IFQNCikNCmBgYA0KYGBge3IgaW1hZ2UxLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSIiLGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzEwMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm91dHB1dDEucG5nIikNCmBgYA0KDQpEYXJpIG91dHB1dCBkaWF0YXMgZGFwYXQgZGlsaWhhdCBpbnRlcnZhbCBrZXBlcmNheWFhbiAoQ0kpIHVudHVrIGtlbGFuZ3N1bmdhbiBoaWR1cCBzZWhhcmktaGFyaSBhdGF1IGFsdXIgYmVydGFoYW4gaGlkdXAuIENJIGRpdmlzdWFsaXNhc2lrYW4gc2VjYXJhIGRlZmF1bHQsIHRldGFwaSBkYXBhdCBkaWhhcHVzICBqaWthIGRpcGVybHVrYW4gbWVsYWx1aSBjb25mLmludCA9IEZBTFNFX3BlcmludGFoLiBCYXJpcyB0ZXJha2hpciBwYWRhIGtvZGUgZGkgYXRhcyBtZW5hbXBpbGthbiB0YWJlbCDigJxBbmdrYSBiZXJpc2lrb+KAnSwgeWFuZyBkaWhpdHVuZyBzZWNhcmEgbWFudWFsIGRpIGF0YXMuIA0KDQpLdXJ2YSBpbmkgZGlqZWxhc2thbiBzZWNhcmEgaW5kZXBlbmRlbiBvbGVoIGR1YSBpbG11d2FuIGJlcmJlZGEgcGFkYSBzYWF0IGJlcnNhbWFhbi4gRWR3YXJkIEthcGxhbiBkYW4gUGF1bCBNZWllciBrZW11ZGlhbiBtZW5lcmJpdGthbiB0ZW11YW4gbWVyZWthIGJlcnNhbWEgc2ViYWdhaSBlc3RpbWF0b3IgS2FwbGFuLU1laWVyIChLTSkgcGFkYSB0YWh1biAxOTU4IGRhbiBzdXJ2Zml0ZnVuZ3NpIGNvY29rIGRlbmdhbiB0eXBlID0gImthcGxhbi1tZWllciJrdXJ2YSBzZWNhcmEgZGVmYXVsdC4NCg0KU2ViYWdpYW4gYmVzYXIgZGF0YSBrZWxhbmdzdW5nYW4gaGlkdXAgbWVudW5qdWtrYW4gYmFueWFrIHBlcmlzdGl3YSBkaSBhd2FsIGRhbiBqdW1sYWggcGVyaXN0aXdhIHlhbmcgbGViaWggcmVuZGFoIHNlcGFuamFuZyB3YWt0dS4gSGFsIGluaSBtZW1idWF0IGt1cnZhIGtlbGFuZ3N1bmdhbiBoaWR1cCBub24tbGluaWVyIGRhbiBzZWJhZ2lhbiBiZXNhciBkYXRhIGtlbGFuZ3N1bmdhbiBoaWR1cCB0ZXJkaXN0cmlidXNpIG1pcmluZyBhdGF1IHRpZGFrIG5vcm1hbCAodGlkYWsgYmVyYmVudHVrIGxvbmNlbmcpLiBJbmkgYWRhbGFoIGFsYXNhbiBtZW5nYXBhIG1ldG9kZSBLTSBtZW1wZXJraXJha2FuIHdha3R1IGJlcnRhaGFuIGhpZHVwIG1lZGlhbiBkYXJpcGFkYSByYXRhLXJhdGEgc2ViYWdhaSB1a3VyYW4gdGVuZGVuc2kgc2VudHJhbC4gTm9uLWxpbmVhcml0YXMgZGFuICJzdGVwaW5lc3MiIGRhcmkga3VydmEgS00gdGlkYWsgbWVtdW5na2lua2FuIHVudHVrIG1lcmluZ2thcyBkYXRhIG1lbmphZGkgc2F0dSBwYXJhbWV0ZXIgdHVuZ2dhbCAsIG1pc2FsbnlhIGtlbWlyaW5nYW4gLCB5YW5nIG1lbWJ1YXQgbWV0b2RlIEtNIG5vbi1wYXJhbWV0cmlrIC4NCg0KIyMgSW50ZXJwcmV0YXNpIEt1cnZhIEthcGxhbi1NZWllcg0KDQpTdW1idSB4IG1ld2FraWxpIHdha3R1IGRhbGFtIGhhcmksIGRhbiBzdW1idSB5IG1lbnVuanVra2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBhdGF1IHByb3BvcnNpIG9yYW5nIHlhbmcgYmVydGFoYW4gaGlkdXAuIEphZGksIGt1cnZhIGl0dSBzZW5kaXJpIG1lbnVuanVra2FuIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgeWFuZyB0ZXBhdCBkYXJpIHdha3R1IGtlIHdha3R1IC4gUGVudXJ1bmFuIHZlcnRpa2FsIHBhZGEga3VydmEgbWVudW5qdWtrYW4gc2V0aWRha255YSBzYXR1IHBlcmlzdGl3YSAuIEtldGluZ2dpYW4gcGVudXJ1bmFuIHZlcnRpa2FsIG1lbnVuanVra2FuIHBlcnViYWhhbiBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGt1bXVsYXRpZi4gQmFnaWFuIGhvcml6b250YWwgZGFyaSBrdXJ2YSBtZXdha2lsaSBkdXJhc2kga2VsYW5nc3VuZ2FuIGhpZHVwIHVudHVrIGludGVydmFsIHdha3R1IHRlcnRlbnR1ICwgeWFuZyBkaWFraGlyaSBvbGVoIHBlcmlzdGl3YSBiZXJpa3V0bnlhIChkYW4gcGVudXJ1bmFuIGt1cnZhKS4gS3VydmEgS00gdGVybGloYXQgc2VwZXJ0aSB0YW5nZ2EgYW5laCBkZW5nYW4gYW5hayB0YW5nZ2EgeWFuZyB0aWRhayByYXRhLCBkaSBtYW5hIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBrb25zdGFuIGRpIGFudGFyYSBwZXJpc3Rpd2EsIGRhbiBrYXJlbmFueWEgbWVydXBha2FuIGZ1bmdzaSBsYW5na2FoIHlhbmcgbWVuZ3ViYWggbmlsYWkgaGFueWEgcGFkYSBzYWF0IHNldGlhcCBwZXJpc3Rpd2EuIERlbmdhbiBjYXJhIGluaSBzZXRpYXAgcGFzaWVuIG1lbnl1bWJhbmdrYW4gaW5mb3JtYXNpIGJlcmhhcmdhIHVudHVrIHBlcmhpdHVuZ2FuIHNlbGFtYSBtYXNpaCBoaWR1cC4gT3JhbmcgeWFuZyBkaXNlbnNvciBkaXRhbXBpbGthbiBwZXJzaXMgc2VwZXJ0aSBwYWRhIG9iamVrIGJlcnRhaGFuIGhpZHVwLCBkZW5nYW4gcGx1cyAsIHNlcGVydGkgeWFuZyBkaWxpaGF0IHBhZGEgaGFyaSBrZS0yLiBOYW11biwgc2ViYWdpYW4gYmVzYXIgcGx1cyB0ZXJsaWhhdCBzZXBlcnRpIGt1dHUgdmVydGlrYWwgLCBrYXJlbmEgdGVybGV0YWsgZGkgYmFnaWFuIGhvcml6b250YWwga3VydmEsIHlhaXR1IGhhcmkgNCBkYW4gNSBUYW5kYSBjZW50YW5nIGRpdGFtcGlsa2FuIHNlY2FyYSBkZWZhdWx0LCB0ZXRhcGkgZGFwYXQgZGl0ZWthbiBtZW5nZ3VuYWthbiBhcmd1bWVuIGNlbnNvciA9IEZBTFNFLiBUYWJlbCByaXNpa28gZGkgYmF3YWggcGxvdCBtZW51bmp1a2thbiBqdW1sYWggb3JhbmcgeWFuZyBiZXJpc2lrbyAsIHlhbmcgc2ViZW5hcm55YSBzZW11YSBvcmFuZyB5YW5nIOKAnGJlbmFyLWJlbmFyIGhpZHVw4oCdIGRhbGFtIHBlcmNvYmFhbiB5YW5nIHRpZGFrIG1lbmdhbGFtaSBrZWphZGlhbiBhdGF1IHBlbnllbnNvcmFuIHBhZGEgdGl0aWsgd2FrdHUgdGVydGVudHUuIEdhcmlzIHB1dHVzLXB1dHVzIG1ld2FraWxpIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCByYXRhLXJhdGEgeWFuZyBzZXN1YWkgZGVuZ2FuIHByb2JhYmlsaXRhcyBrZWxhbmdzdW5nYW4gaGlkdXAgNTAlIC4gRGFuIGppa2Ega2l0YSBtZW5nYWJhaWthbiBwZW55ZW5zb3JhbiBkYW4gaGFueWEgbWVtcGVya2lyYWthbiBtZWRpYW4gd2FrdHUgKGhhbnlhIHVudHVrIG9yYW5nIG1hdGkpLCBraXRhIGFrYW4gbWVuZGFwYXRrYW4gMSw1IGJ1a2FubnlhIDMsIHlhbmcgYWthbiBtZW5pbmdrYXRrYW4ga2VtdW5na2luYW4gYmVydGFoYW4gaGlkdXAgZGFyaSA0OCUgbWVuamFkaSA3MCUuIFNla2FsaSBsYWdpLCBtZW5nYWJhaWthbiBwZW55ZW5zb3JhbiBha2FuIG1lbmdoYXNpbGthbiBrZW11bmdraW5hbiBiZXJ0YWhhbiBoaWR1cCB5YW5nIHRlcmxhbHUgdGluZ2dpIGthcmVuYSBiaWFzIGtlYmVybGFuZ3N1bmdhbiBoaWR1cC4NCg0KYGBge3J9DQpkICU+JSANCiAgZmlsdGVyKHN0YXR1cyA9PSAxKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fc3Vydml2YWxfd2hpdGhvdXRfY2Vuc29yaW5nID0gbWVkaWFuKHRpbWUpKQ0KYGBgDQoNCiMjIE1lbWJhbmRpbmdrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIGtlbG9tcG9rDQoNCioyIGdyb3VwKg0KDQpEZW5nYW4gbWVuZ2d1bmFrYW4gY29ub3RoIGRhdGEgIDEwMCBvcmFuZyBzZXRlbGFoIGtlY2VsYWthYW4gVGl0YW5pYyBhbGloLWFsaWggMTAgZGFuIGxpaGF0IGtlbGFuZ3N1bmdhbiBoaWR1cCBtZXJla2EgbWVuZ2d1bmFrYW4ga3VydmEgS2FwbGFuLU1laWVyLiBBbmdrYS1hbmdrYSBkYWxhbSB0YWJlbCByaXNpa28gc2VtYWtpbiBiZXNhciBkYW4gc2ViYWlrbnlhIGthbWkgbWVuYW1waWxrYW4gcGVyc2VudGFzZSBiZXJpc2lrbyBkYWxhbSB0YW5kYSBrdXJ1bmcgZGkgZGVrYXQgbmlsYWkgYWJzb2x1dC4gQXJndW1lbiByaXNrLnRhYmxlID0gImFic19wY3QiIG1lbWJhbnR1IGRlbmdhbiBpdHUuIENvbnRvaCAiYnVsYXQiIGRhcmkgMTAwIG9yYW5nIG1lbnVuanVrYW4gcGVyc2VudGFzZSB5YW5nIHBlcnNpcyBzYW1hIGRlbmdhbiBhbmdrYSBhYnNvbHV0LCBuYW11biBkZW5nYW4ganVtbGFoICJidWxhdCIgeWFuZyBsZWJpaCBzZWRpa2l0IGF0YXUgYmViZXJhcGEga2Vsb21wb2ssIHBlcnNlbnRhc2UgYWthbiBtZW5qYWRpIHNhbmdhdCBiZXJndW5hLiBSYXRhLXJhdGEgd2FrdHUgYmVydGFoYW4gaGlkdXAgb3Jhbmctb3JhbmcgZGkgbGF1dGFuIGRpbmdpbiBhZGFsYWggc2VraXRhciA3MCBoYXJpIGRhbiBpbnRlcnZhbCBrZXBlcmNheWFhbm55YSB0aWRhayB0ZXJsYWx1IGxlYmFyLg0KDQpgYGB7cn0NCnNldC5zZWVkKDk5OSkgIyBmb3IgcmVwcm9kdWNpYmxlIGV4YW1wbGUNCmxpYnJhcnkocmxhbmcpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpkIDwtIGdnc3RhdHNwbG90OjpUaXRhbmljX2Z1bGwgJT4lIA0KICBtdXRhdGUoc3Vydml2ZWQgPSBpZmVsc2UoU3Vydml2ZWQgPT0gIk5vIiwgMSwgMCksDQogICAgICAgICB0aW1lICAgICA9IHJ1bmlmKG49MjIwMSwgbWluPTEsIG1heD0xMDApKSAlPiUgDQogIHNhbXBsZV9uKDEwMCkgDQoNCm0gPC0gc3VydmZpdChTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IDEsIGRhdGEgPSBkKQ0KDQpnZ3N1cnZwbG90KG0sIA0KICAgICAgICAgICBjb25mLmludCA9IFRSVUUsIA0KICAgICAgICAgICByaXNrLnRhYmxlID0gImFic19wY3QiLCANCiAgICAgICAgICAgc3Vydi5tZWRpYW4ubGluZSA9ICJodiIpDQpgYGANCg0KTWlzYWxueWEsIG1lbWJhbmRpbmdrYW4gcHJvYmFiaWxpdGFzIGtlbGFuZ3N1bmdhbiBoaWR1cCBsYWtpLWxha2kgZGVuZ2FuIHBlcmVtcHVhbi4gRGVuZ2FuIG1lbmdnYW50aSBydW11cyBtb2RlbCBkZW5nYW4gbmFtYSB2YXJpYWJlbCBrYXRlZ29yaSB5YW5nIGRpbWluYXRpLCBtaXNhbG55YSBzZXguIFBsb3QgYmVydGFoYW4gaGlkdXAga2VtdWRpYW4gbWVuYW1waWxrYW4ga3VydmEgS2FwbGFuLU1laWVyIHVudHVrIHNldGlhcCBrYXRlZ29yaSB2YXJpYWJlbCB5YW5nIGFkYToNCg0KYGBge3J9DQptIDwtIHN1cnZmaXQoU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBTZXgsIGRhdGEgPSBkKQ0KDQpnZ3N1cnZwbG90KG0sIA0KICAgICAgICAgICBwdmFsID0gVFJVRSwgDQogICAgICAgICAgIGNvbmYuaW50ID0gVFJVRSwgDQogICAgICAgICAgIHJpc2sudGFibGUgPSAiYWJzX3BjdCIsIA0KICAgICAgICAgICBzdXJ2Lm1lZGlhbi5saW5lID0gImh2IikgDQpgYGANCg0KIyMgKipJbnRlcnByZXRhc2kgcGVyYmFuZGluZ2FuIGtlbG9tcG9rIG1lbmdndW5ha2FuIDQgdG9sb2sgdWt1cioqDQoNCjEuICoqUGVyYmFuZGluZ2FuIHZpc3VhbCBrdXJ2YSoqIDogaGFueWEgZGVuZ2FuIG1lbGloYXQgZHVhIGtlbG9tcG9rIHNlaGluZ2dhIGRhcGF0IG1lbmdhdGFrYW4gYXBha2FoIGFkYSBwZXJiZWRhYW4uIE1pc2FsbnlhLCBwbG90IG1lbmd1bmdrYXBrYW4gYmFod2EgcGVyZW1wdWFuIG1lbWlsaWtpIGtlbXVuZ2tpbmFuIGxlYmloIHRpbmdnaSB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBoYW1waXIgc2VwYW5qYW5nIHBlcmlvZGUgd2FrdHUgKHN1bWJ1IHgpLiBOYW11biwgYXBha2FoIHBlcmJlZGFhbiBpbmkgc2lnbmlmaWthbiBzZWNhcmEgc3RhdGlzdGlrIG1lbWVybHVrYW4gdWppIHN0YXRpc3RpayBmb3JtYWwgLiBEZW5nYW4gbWVsaWhhdCBhbmdrYSBrdXJ2YSwgbWlzYWxueWE6IHBhZGEgaGFyaSB5YW5nIGNlcmFoIGRhbiBpbmRhaCBzZWJlbHVtIGhpbXBpdGFuLCBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAga2VkdWEga2Vsb21wb2sgYWRhbGFoIDEsMCAoYXRhdSAxMDAlIHBlbnVtcGFuZyBtYXNpaCBoaWR1cCkuIFBhZGEgaGFyaSBrZSA1MCwga2VtdW5na2luYW4gYmVydGFoYW4gaGlkdXAgYmV0aW5hIGFkYWxhaCBjYS4gMCw3NSAoYXRhdSA3NSUpIGRhbiBoYW55YSBjYS4gMCw2NSAoYXRhdSA2NSUpIHVudHVrIGxha2ktbGFraS4gUGFkYSBoYXJpIGtlIDc1LCBrZWxhbmdzdW5nYW4gaGlkdXAgYWRhbGFoIGNhLiA2MCBkYW4ga2lyYS1raXJhIDMwJSBzZXN1YWkuDQoNCjIuICoqUGVyYmFuZGluZ2FuIGludGVydmFsIGtlcGVyY2F5YWFuIChDSSkqKiA6IENJIHlhbmcgdHVtcGFuZyB0aW5kaWggbWVudW5qdWtrYW4gYmFod2Ega2VsYW5nc3VuZ2FuIGhpZHVwIGphbnRhbiBkYW4gYmV0aW5hIHRpZGFrIHRlcmxhbHUgYmVyYmVkYSBkYW4gYmlzYSBqYWRpIGthcmVuYSBrZWJldHVsYW4gaGluZ2dhIDgwIGhhcmkuIFNldGVsYWggODAgaGFyaSBDSSBiZXJoZW50aSB0dW1wYW5nIHRpbmRpaCB5YW5nIG1lbnVuanVra2FuIHBlcmJlZGFhbiBzaWduaWZpa2FuIGRhbGFtIGJlcnRhaGFuIGhpZHVwIHBhZGEgdGl0aWsgd2FrdHUgdGVydGVudHUsIGthdGFrYW5sYWggOTAgaGFyaS4NCg0KMy4gKipQZXJraXJhYW4gd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIE5pbGFpIFRlbmdhaCoqIG1lbmd1bmdrYXBrYW4gbGViaWggZGFyaSBpbnRlcnZhbCBrZXBlcmNheWFhbi4gV2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIHJhdGEtcmF0YSB1bnR1ayBzZXRpYXAga2Vsb21wb2sgbWV3YWtpbGkgd2FrdHUgZGkgbWFuYSBwcm9iYWJpbGl0YXMga2VsYW5nc3VuZ2FuIGhpZHVwIGFkYWxhaCA1MCUuIE1pc2FsbnlhIGtlbGFuZ3N1bmdhbiBoaWR1cCByYXRhLXJhdGEgQmV0aW5hIGphdWggbGViaWggdGluZ2dpICg4NyBoYXJpKSBkYXJpcGFkYSBqYW50YW4gKDY1IGhhcmkpLiBQZXJiZWRhYW4gMjMgaGFyaSB5YW5nIGJlZ2l0dSBiZXNhciwga2FyZW5hIHBlcmVtcHVhbiBtZW1pbGlraSAyMyBoYXJpIGxhZ2kgdW50dWsgZGl0ZW11a2FuIG9sZWggYmViZXJhcGEga2FwYWwgcGVuYW5na2FwIGlrYW4uIERpIHNpbmkgc2VrYWxpIGxhZ2ksIGhhbnlhIHRlcyB5YW5nIGRhcGF0IG1lbmdldGFodWkgZGFuIGl0dWxhaCBtZW5nYXBhIHRvbG9rIHVrdXIgdGVyYWtoaXIgdW50dWsgbWVtYmFuZGluZ2thbiBkdWEga2Vsb21wb2sgYWRhbGFoIHAtdmFsdWUgeWFuZyBkaWVzdGltYXNpIG9sZWggdGVzIExvZy1SYW5rIChQZXRvIGV0IGFsLCAxOTc3KSwgeWFuZyBzYW5nYXQgcGVudGluZywgc2VoaW5nZ2EgcGVybHUgYmFiIHRhbWJhaGFuLg0KDQpgYGB7cn0NCm0NCmBgYA0KDQojIyBMb2ctUmFuayB0ZXN0DQoNCjQuIFVqaSBzdGF0aXN0aWsgKm5vbi1wYXJhbWV0cmlrIExvZy1SYW5rKiAoa2FkYW5nLWthZGFuZyBkaXNlYnV0IE1hbnRlbC1IYWVuc3plbCkgbWVtYmFuZGluZ2thbiBtZWRpYW4gd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIGtlbG9tcG9rLiBVamkgTG9nLVJhbmsgbWlyaXAgZGVuZ2FuIHVqaSBXaWxjb3hvbi1SYW5rIG5vbiBwYXJhbWV0cmlrICgxKSwgeWFuZyBqdWdhIG1lbWJhbmRpbmdrYW4gbWVkaWFuIGRlbmdhbiBtZW5nZ3VuYWthbiBwZXJpbmdrYXQgZGFuIGp1Z2EgbWlyaXAgZGVuZ2FuIHVqaSBDaGktc3F1YXJlICgyKSwgZGkgbWFuYSBraXRhIG1lbWJhbmRpbmdrYW4ganVtbGFoIGtlamFkaWFuIHlhbmcgZGlhbWF0aSBkZW5nYW4geWFuZyBkaWhhcmFwa2FuIGRlbmdhbiBtZW5naGl0dW5nIHN0YXRpc3RpayBDaGktc3F1YXJlOg0KDQokJCBYXjIgPSBcc3VtX3tpID0gMX1ee2d9IFxmcmFjeyhPX2kgLSBFX2kpXjJ9e0VfaX0kJA0KDQpKdW1sYWgga2VqYWRpYW4geWFuZyBkaWhhcmFwa2FuIGRpaGl0dW5nIHVudHVrICpzZXRpYXAgdGl0aWsgd2FrdHUgZGFuIHNldGlhcCBrZWxvbXBvayogZGliYW5kaW5na2FuIGRlbmdhbiB0aXRpayB3YWt0dSBzZWJlbHVtbnlhLiBOaWxhaS1uaWxhaSBpbmkga2VtdWRpYW4gZGlqdW1sYWhrYW4gcGFkYSBzZW11YSB0aXRpayB3YWt0dSB1bnR1ayBtZW1iZXJpa2FuIGp1bWxhaCB0b3RhbCBrZWphZGlhbiB5YW5nIGRpaGFyYXBrYW4gcGFkYSBzZXRpYXAga2Vsb21wb2suDQoNClNpZmF0IG5vbi1wYXJhbWV0cmlrIGRhcmkgdGVzIGluaSBtZW1idWF0IHRpZGFrIGFkYSBhc3Vtc2kgdGVudGFuZyBkaXN0cmlidXNpIGtlbGFuZ3N1bmdhbiBoaWR1cC4gSmFkaSwgYXBha2FoIHdha3R1IGtlbGFuZ3N1bmdhbiBoaWR1cCBub3JtYWwgKCJsb25jZW5nIG1lbGVuZ2t1bmciKT8gQmlzYSBzYWphLCB0ZXRhcGkgdGlkYWsgaGFydXMgRmFrdGFueWEsIGRhdGEga2VsYW5nc3VuZ2FuIGhpZHVwIHNhbmdhdCBqYXJhbmcgYmVyZGlzdHJpYnVzaSBub3JtYWwsIHRldGFwaSBzZXJpbmcga2FsaSBtaXJpbmcga2FyZW5hIGJpYXNhbnlhIGJhbnlhayBrZWphZGlhbiBhd2FsIGRhbiByZWxhdGlmIHNlZGlraXQga2VqYWRpYW4gYWtoaXIuIA0KDQpIaXBvdGVzaXMgbm9sIGRhcmkgdWppIExvZy1SYW5rIGFkYWxhaCB0aWRhayBhZGEgcGVyYmVkYWFuIGRhbGFtIGtldGFoYW5hbiBoaWR1cCBhbnRhcmEga2VkdWEga2Vsb21wb2suIE5pbGFpIHAtdmFsdWUgc2ViZXNhciAwLDAxMSBtZW11bmdraW5rYW4ga2l0YSB1bnR1ayBtZW5vbGFrIGhpcG90ZXNpcyBub2wgZGFuIG1lbmdpbmRpa2FzaWthbiBhZGFueWEgcGVyYmVkYWFuIHJhdGEtcmF0YSB5YW5nIHNpZ25pZmlrYW4gZGFsYW0gd2FrdHUga2VsYW5nc3VuZ2FuIGhpZHVwIGFudGFyYSBwZXJlbXB1YW4gZGFuIGxha2ktbGFraS4NCg0KVWppIExvZy1SYW5rIHNhbmdhdCBiYW55YWsgZGlndW5ha2FuIHVudHVrIG1lbWJhbmRpbmdrYW4gZHVhIGF0YXUgbGViaWgga3VydmEga2VsYW5nc3VuZ2FuIGhpZHVwLCBzZWhpbmdnYSBoYXJ1cyBiZW5hci1iZW5hciBtZW1iZW5hcmthbiBwZW5nZ3VuYWFuIHVqaSBsYWlubnlhLg0KDQpGdW5nc2kgYHN1cnZkaWZmKClgIG1lbmdoaXR1bmcgdWppIExvZy1SYW5rIGRhbiBtZW5nZW1iYWxpa2FuIGtvbXBvbmVuLWtvbXBvbmVuIGJlcmlrdXQ6DQoNCi0gKkp1bWxhaCogc3ViamVrIGRhbGFtIHNldGlhcCBrZWxvbXBvay4NCi0gSnVtbGFoIGtlamFkaWFuICoqdGVyYW1hdGkgKip0ZXJ0aW1iYW5nICoqZGFsYW0gc2V0aWFwIGtlbG9tcG9rLg0KLSBKdW1sYWgga2VqYWRpYW4gdGVydGltYmFuZyAqIHlhbmcgZGloYXJhcGthbiogZGFsYW0gc2V0aWFwIGtlbG9tcG9rLg0KLSAqU3RhdGlzdGlrIGNoaS1zcXVhcmUqIHVudHVrIHVqaSBrZXNldGFyYWFuDQotIGRhbiAqcC12YWx1ZSogdW50dWsgcGVyYmVkYWFuIGtlbGFuZ3N1bmdhbiBoaWR1cCBkaSBhbnRhcmEga2Vsb21wb2sNCg0KYGBge3J9DQpzdXJ2ZGlmZihTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IFNleCwgZGF0YSA9IGQpDQpgYGANCg0KQXBha2FoIHRlcyBMb2ctUmFuayBzZW1wdXJuYT8gU2F5YW5nbnlhLCB0aWRhay4gU2FsYWggc2F0dSBtYXNhbGFobnlhIGFkYWxhaDogdWppIGluaSAqdGlkYWsgbWVtYmVyaWthbiB1a3VyYW4gZWZlayogeWFuZyBtZW1idWF0IGtpdGEgaGFueWEgbWVtaWxpa2kgcC12YWx1ZSBzZWJhZ2FpIHVrdXJhbiBwZXJiZWRhYW4uIE1hc2FsYWggbGFpbiBkZW5nYW4gdWppIExvZy1SYW5rIChkYW4gbWV0b2RlIEthcGxhbi1NZWllciBzZWNhcmEgdW11bSkgYWRhbGFoIGJhaHdhIHVqaSBpbmkgKnRpZGFrIG1lbmdpemlua2FuIGFkYW55YSBwZXJhbmN1KiwgdWppIGluaSBtZW5nYWJhaWthbiBmYWt0b3IvdmFyaWFiZWwgbGFpbi4gVW50dW5nbnlhLCBraXRhIG1hc2loIGJpc2EgbWVtYmFuZGluZ2thbiBsZWJpaCBkYXJpIGR1YSBrZWxvbXBvayBkZW5nYW4gc2F0dSB2YXJpYWJlbC4NCg0KPiAyIGtlbG9tcG9rIGRhbiBiZWJlcmFwYSB1amkgTG9nLVJhbmsgYmVycGFzYW5nYW4gKHBvc3QtaG9jKQ0KDQpUZXMgTG9nLVJhbmsgZGFwYXQgbWVtYmFuZGluZ2thbiBsZWJpaCBkYXJpIGR1YSBrZWxvbXBvayBkYW4gbWVuZ2F0YWthbiBhcGFrYWggYWRhIHBlcmJlZGFhbiB5YW5nIHNpZ25pZmlrYW4gKHAtdmFsdWUgPDAsMDUpIGRpIGFudGFyYSBrZWxvbXBvay1rZWxvbXBvayBpbmkuIEhhc2lsIHBlbmd1amlhbiB5YW5nIGRpdGFtcGlsa2FuIHBhZGEgdGFiZWwgZGFuIGt1cnZhIEtNIGRpIGJhd2FoIGluaSBtZW51bmp1a2thbiBiYWh3YSB0ZXJkYXBhdCBwZXJiZWRhYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIHlhbmcgc2lnbmlmaWthbiAocC12YWx1ZSA9IDAsMDI0KSBkaSBhbnRhcmEga2Vsb21wb2sgb3JhbmcgcGFkYSBrZWxhcyB0aWtldCB5YW5nIGJlcmJlZGEuIE5hbXVuLCBzZXBlcnRpIGtlYmFueWFrYW4gdGVzIGxhaW5ueWEgKG1pc2FsbnlhIEFOT1ZBKSwgdGlkYWsgZGlzZWJ1dGthbiBkaSBhbnRhcmEga2Vsb21wb2sgbWFuYSB0ZXBhdG55YS4gT2xlaCBrYXJlbmEgaXR1IGRpcGVybHVrYW4gYW5hbGlzaXMgdGFtYmFoYW4geWFuZyBtZW1iYW5kaW5na2FuIHNlY2FyYSBiZXJwYXNhbmdhbiBzZXRpYXAga2Vsb21wb2sgc2F0dSBkZW5nYW4ga2Vsb21wb2sgbGFpbm55YS4gQW5hbGlzaXMgc2VtYWNhbSBpdHUgc2VyaW5nIGRpc2VidXQgcG9zdC1ob2MuDQoNCmBgYHtyfQ0Kc3VydmRpZmYoU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBDbGFzcywgZGF0YSA9IGQpDQpgYGANCg0KYGBge3J9DQptIDwtIHN1cnZmaXQoU3Vydih0aW1lLCBzdXJ2aXZlZCkgfiBDbGFzcywgZGF0YSA9IGQpDQoNCmdnc3VydnBsb3QobSwgDQogICAgICAgICAgIHB2YWwgPSBUUlVFLCANCiAgICAgICAgICAgY29uZi5pbnQgPSBGQUxTRSwgDQogICAgICAgICAgIHJpc2sudGFibGUgPSAiYWJzX3BjdCIsIA0KICAgICAgICAgICBzdXJ2Lm1lZGlhbi5saW5lID0gImh2IiwNCiAgICAgICAgICAgbmNlbnNvci5wbG90ID0gVFJVRSwNCiAgICAgICAgICAgYnJlYWsudGltZS5ieSA9IDIwLA0KICAgICAgICAgICByaXNrLnRhYmxlLnkudGV4dC5jb2wgPSBUUlVFLCByaXNrLnRhYmxlLnkudGV4dCA9IEZBTFNFKSANCmBgYA0KDQoNClRpZ2EgYXJndW1lbiBwbG90IHlhbmcgYmVyZ3VuYSBsZWJpaCBsYW5qdXQgeWFuZyBkYXBhdCBtZW1iYW50dSBtZW12aXN1YWxpc2FzaWthbiBkYXRhIGtldGFoYW5hbiBoaWR1cCBkZW5nYW4gbGViaWggYmFpayBhZGFsYWg6DQoNCi0gYGJyZWFrLnRpbWUuYnkgPSAyMGAgbWVtZWNhaCBzdW1idSB4IG1lbmphZGkgaW50ZXJ2YWwgd2FrdHUgeWFuZyBkaWluZ2lua2FuLg0KLSBgcmlzay50YWJsZS55LnRleHQuY29sID0gVFJVRWAgZGFuIGByaXNrLnRhYmxlLnkudGV4dCA9IEZBTFNFYCBtZW1wbG90IGJhdGFuZywgYnVrYW4gbmFtYSBkYWxhbSBhbm90YXNpIHRla3MgbGVnZW5kYSB0YWJlbCByaXNpa28NCi0gYG5jZW5zb3IucGxvdCA9IFRSVUVgIG1lbmFtcGlsa2FuIGp1bWxhaCBzdWJqZWsgeWFuZyBkaXNlbnNvciwgeWFuZyBtZW1iYW50dSB1bnR1ayBtZW1haGFtaSBhcGEgeWFuZyBtZW5qYWRpIHBlbnllYmFiIGFuZ2thIHJpc2lrbyBtZW5qYWRpIGxlYmloIGtlY2lsOiBwZXJpc3Rpd2EgYXRhdSBwZW55ZW5zb3Jhbi4NCg0KIyMgUGVuYWZzaXJhbg0KDQpLZWxhbmdzdW5nYW4gaGlkdXAgcmF0YS1yYXRhIGFkYWxhaCBjYS4gOTAgaGFyaSB1bnR1ayBwZW51bXBhbmcga2VsYXMgMSBkYW4gMiwgNTggaGFyaSB1bnR1ayBrZWxhcyAzIGRhbiA2NSBoYXJpIHVudHVrIGF3YWsgVGl0YW5pYywgbWVudW5qdWtrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIG9yYW5nIGtheWEgeWFuZyBiYWlrLCBkaWJhbmRpbmdrYW4gZGVuZ2FuIHlhbmcgbGFpbi4gRGVuZ2FuIHAtdmFsdWUgeWFuZyByZW5kYWggKHAgPSAwLDAyNCkgbWVudW5qdWtrYW4gYmFod2EgYWRhIHBlcmJlZGFhbiB5YW5nIHNpZ25pZmlrYW4gZGFsYW0ga2VsYW5nc3VuZ2FuIGhpZHVwIGFudGFyIGtlbG9tcG9rIC4gRGkgYW50YXJhbnlhLCBoYW55YSBwb3N0LWhvYyB5YW5nIHRhaHUuIEhhc2lsIGRhcmkgYW5hbGlzaXMgTG9nLVJhbmsgcG9zdC1ob2MgdGVyc2VidXQgZGFwYXQgZGlsYWt1a2FuIGRlbmdhbiBmdW5nc2kgcGFpcndpc2Vfc3VydmRpZmYgZGFyaSBzdXJ2bWluZXIgZGFuIGRpdGFtcGlsa2FuIGRpIGJhd2FoIGluaS4gU2VwZXJ0aSBiaWFzYSwgamlrYSBtZW1pbGlraSBiYW55YWsgcGVyYmFuZGluZ2FuIHNlaGluZ2dhIGJlcmlzaWtvIG1lbWJ1YXQgcGVuZW11YW4geWFuZyBzYWxhaCBhdGF1IG1lbGV3YXRrYW4gcGVuZW11YW4gcGVudGluZy4gSmFkaSwgaGFydXMgbWVueWVzdWFpa2FuIHAtdmFsdWUgdW50dWsgbWVuZ3VyYW5naSBrZW11bmdraW5hbiB0ZXJqYWRpbnlhIGtlc2FsYWhhbi4gDQoNCmBgYHtyfQ0KcGFpcndpc2Vfc3VydmRpZmYoDQogIGZvcm11bGEgPSBTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IENsYXNzLCBkYXRhID0gZCwgcC5hZGp1c3QubWV0aG9kID0gImZkciINCiAgKQ0KYGBgDQoNCkhhc2lsIGFuYWxpc2lzIHBvc3QtaG9jIG1lbmd1bmdrYXBrYW4gYmFod2Ega2VsYW5nc3VuZ2FuIGhpZHVwIGtlbGFzIDEgc2VjYXJhIHNpZ25pZmlrYW4gbGViaWggdGluZ2dpIGRpYmFuZGluZ2thbiBkZW5nYW4ga2VsYXMgMyBkYW4gQXdhay4gRGFuIHRlcmxlcGFzIGRhcmkga2VueWF0YWFuIGJhaHdhIHJhdGEtcmF0YSBrZWxhbmdzdW5nYW4gaGlkdXAgcGVudW1wYW5nIGtlbGFzIDIgc2FuZ2F0IG1pcmlwIGRlbmdhbiBrZWxhcyAxLCBpbnRlcnZhbCBrZXBlcmNheWFhbiBrZWxhbmdzdW5nYW4gaGlkdXAgaW5pIHNhbmdhdCBsZWJhciBkYW4gYmFueWFrIHR1bXBhbmcgdGluZGloIGRlbmdhbiBrZWxvbXBvayBsYWluICh0aWRhayBkaXR1bmp1a2thbiB1bnR1ayBtZW5naGluZGFyaSBrZWthY2F1YW4pLiBJdHVsYWggbWVuZ2FwYSBwZW51bXBhbmcga2VsYXMgMiB0aWRhayB1bXVtbnlhIG1lbWlsaWtpIHdha3R1IGJlcnRhaGFuIGhpZHVwIHlhbmcgbGViaWggdGluZ2dpIHNlY2FyYSBzaWduaWZpa2FuIG1lc2tpcHVuIG1lbWlsaWtpIHdha3R1IGJlcnRhaGFuIGhpZHVwIHlhbmcgamF1aCBsZWJpaCB0aW5nZ2kuDQoNCiMjIE11bHRpcGxlIGt1cnZhIFN1cnZpdmFsDQoNClNlcGVydGkgZGlzZWJ1dGthbiBkaSBhdGFzLCB1amkgTG9nLVJhbmsgdGlkYWsgZGFwYXQgZGl0ZXJhcGthbiBwYWRhIGJlYmVyYXBhIHZhcmlhYmVsLiBOYW11biBtYXNpaCBkYXBhdCBtZW1wbG90IGt1cnZhIGtlbGFuZ3N1bmdhbiBoaWR1cCBkYXJpIGJlYmVyYXBhIHZhcmlhYmVsIHVudHVrIG1lbmRhcGF0a2FuIGludHVpc2kgdW50dWsgZGF0YSBpbmkuIE1ldG9kZSBsZWJpaCBsYW5qdXQsIG1pc2FsbnlhIG1vZGVsIENveCwgZGFwYXQgbWVuZ2VzdGltYXNpIHBlcmJlZGFhbiBkaSBhbnRhcmEgYmViZXJhcGEgdmFyaWFiZWwsIHRldGFwaSBtZXRvZGUgaW5pIGxlYmloIGtvbXBsZWtzIGRhcmlwYWRhIG1ldG9kZSBLTSBkYW4gZGVuZ2FuIGRlbWlraWFuIGFrYW4gZGliYWhhcyBkaSBwb3N0aW5nIG1lbmRhdGFuZy4NCg0KYGBge3J9DQptMiA8LSBzdXJ2Zml0KCBTdXJ2KHRpbWUsIHN1cnZpdmVkKSB+IFNleCArIENsYXNzLCBkYXRhID0gZCApDQoNCmdnc3VydiA8LSBnZ3N1cnZwbG90KG0yLCBjb25mLmludCA9IFRSVUUpDQogICANCmdnc3VydiRwbG90ICt0aGVtZV9idygpICsgDQogIHRoZW1lIChsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSsNCiAgZmFjZXRfZ3JpZChTZXggfiAuKQ0KYGBgDQoNCkludHVpc2kgeWFuZyBkYXBhdCBraXRhIHBlcm9sZWggZGFyaSBwbG90IGRpIGF0YXMgYWRhbGFoIGJhaHdhIHdhbml0YSBrYXlhIChrZWxhcyB0aWtldCAxIGRhbiAyKSBkYW4gKGhhbnlhIDIpIHdhbml0YSBkYXJpIGtydSBrYXBhbCBtZW1pbGlraSBwcm9iYWJpbGl0YXMgMTAwJSB1bnR1ayBiZXJ0YWhhbiBoaWR1cCwgc2VtZW50YXJhIHdhbml0YSBtdXJuaSBkaSBrZWxhcyAzIGFrYW4gbWF0aSBkZW5nYW4ga2VwYXN0aWFuIHlhbmcgc2FtYSBkZW5nYW4gcHJpYS4gQ0kgeWFuZyBzYW5nYXQgdHVtcGFuZyB0aW5kaWggZGFyaSBrZWxhbmdzdW5nYW4gaGlkdXAgcHJpYSBtZW51bmp1a2thbiBiYWh3YSBzZW11YSBwcmlhIHBhZGEgYWtoaXJueWEgYWthbiBtYXRpIHNldGVsYWgga2VjZWxha2FhbiBUaXRhbmljLg0KDQojIyBLZXNpbXB1bGFuDQoNCkFuYWxpc2lzIGtldGFoYW5hbiBoaWR1cCBtZW55ZWxpZGlraSAqd2FrdHUgeWFuZyBkaWJ1dHVoa2FuIHVudHVrIHN1YXR1IHBlcmlzdGl3YSB5YW5nIG1lbmFyaWsqIHVudHVrIHRlcmphZGkuIFNlYmFnaWFuIGJlc2FyIGFuYWxpc2lzIGtldGFoYW5hbiBoaWR1cCB1bml2YXJpYXQgKHZhcmlhYmVsIHR1bmdnYWwpIG1lbmdndW5ha2FuICpwbG90IEthcGxhbi1NZWllciogdW50dWsgbWVtdmlzdWFsaXNhc2lrYW4ga3VydmEga2V0YWhhbmFuIGhpZHVwIGRhbiAqVWppIExvZy1SYW5rKiB1bnR1ayBtZW1iYW5kaW5na2FuIGt1cnZhIGtldGFoYW5hbiBoaWR1cCBkdWEgYXRhdSBsZWJpaCBrZWxvbXBvay4NCg0KLSBLZXVudHVuZ2FuDQoNCjEuIEtldW50dW5nYW4ga3J1c2lhbCBrdXJ2YSBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgdnMuIGt1cnZhIHJlZ3Jlc2kgbG9naXN0aWsgbWVtcGVyaGl0dW5na2FuIGRhdGEgeWFuZyBkaXNlbnNvciwgeWFuZyB0aWRhayBtYXRpLCBhdGF1IGhpZHVwLiBSZWdyZXNpIGxvZ2lzdGlrIG1lbXBlcmxha3VrYW4gc2VtdWEgb3JhbmcgeWFuZyB0aWRhayBtYXRpIHNlYmFnYWkgb3JhbmcgeWFuZyBzZWxhbWF0LCBpdHUgc2FsYWgsIGhhbnlhIGthcmVuYSBraXRhIHRpZGFrIG1lbmdldGFodWkgc3RhdHVzIGtlbGFuZ3N1bmdhbiBoaWR1cCBvcmFuZyB5YW5nIHRpZGFrIHRlcmphd2FiLiBQYXNpZW4gbWVuaW5nZ2Fsa2FuIHN0dWRpIGthcmVuYSBkdWEgYWxhc2FuIHV0YW1hLCBtZXJla2EgbWVyYXNhIHNhbmdhdCBidXJ1aywgc2VoaW5nZ2EgbWVyZWthIHRpZGFrIGxhZ2kgcGVkdWxpIGRlbmdhbiBla3NwZXJpbWVuICwgYXRhdSBtZXJla2EgbWVyYXNhIGphdWggbGViaWggYmFpayBkYW4gbWVsdXBha2FuIHN0dWRpLiBCZWJlcmFwYSBwYXNpZW4gbXVuZ2tpbiBoYW55YSBwaW5kYWgga2Uga290YSBsYWluIHRhbnBhIGJlcmthdGEgYXBhLWFwYS4gTWVuZ2hpdHVuZyBzZW11YW55YSBzZWJhZ2FpIHNlbGFtYXQsIHNlcGVydGkgaGFsbnlhIHJlZ3Jlc2kgbG9naXN0aWssIGFrYW4gbWVsZWJpaC1sZWJpaGthbiBrZW11bmdraW5hbiBiZXJ0YWhhbiBoaWR1cCAoc3Vydml2b3JzaGlwIGJpYXMpIGRhbiBtZXJlbWVoa2FuIGJhaGF5YSBrZW1hdGlhbi4gT2xlaCBrYXJlbmEgaXR1LCBhbmFsaXNpcyBrZWxhbmdzdW5nYW4gaGlkdXAgbGViaWggdGVwYXQgZGliYW5kaW5na2FuIGRlbmdhbiByZWdyZXNpIGxvZ2lzdGlrLCBzZW1lbnRhcmEgaXR1IG1hc2loIG1lbmFuZ2thcCB0cmVuIHByb2JhYmlsaXRhcyBub24tbGluaWVyLg0KDQoyLiBLZXVuZ2d1bGFuIGxhaW5ueWEgYWRhbGFoIHNpZmF0IG5vbnBhcmFtZXRyaWsgZGFyaSBtZXRvZGUgS2FwbGFuLU1laWVyLCB5YWl0dSB0aWRhayBtZW1pbGlraSB0ZXJsYWx1IGJhbnlhayBhc3Vtc2kuIFNlYmVuYXJueWEgc2F0dS1zYXR1bnlhIGFzdW1zaSBwZW50aW5nIGFkYWxhaCBiYWh3YSBwZW55ZW5zb3JhbiBoYXJ1cyBiZXJzaWZhdCBub24taW5mb3JtYXRpZiAuIE1lbmdhcGE/IExlYmloIGJhbnlhayBpbmZvcm1hc2kgc2VsYWx1IGxlYmloIGJhaWssIGJ1a2FuPyBZYSEgVGFwaSBqaWthIGtpdGEgdGFodSBtZW5nYXBhIG9yYW5nIG1lbmluZ2dhbGthbiBwZW5lbGl0aWFuLCBraXRhIGJpc2EgbWVuZ2d1bmFrYW4gaW5mb3JtYXNpIGluaSBzZWJhZ2FpIHZhcmlhYmVsIGJhcnUgZGFuIG1lbXBlbGFqYXJpIHBlbmdhcnVobnlhIHRlcmhhZGFwIGtlbGFuZ3N1bmdhbiBoaWR1cC4gTWV0b2RlIEtNIGFrYW4gbWVuamFkaSB0aWRhayB0ZXBhdCwga2FyZW5hIGFrYW4gbWVsZXdhdGthbiBpbmZvcm1hc2kgaW5pLiBOYW11biwgc2VyaW5na2FsaSB0aWRhayB0YWh1ICh0aWRhayBhZGEgaW5mbykgbWVuZ2FwYSBvcmFuZyBrZWx1YXIgKGRpc2Vuc29yKS4gRGFuIGRhbGFtIGhhbCBpbmkgbWV0b2RlIEtNIG1lbWVyYXMgaW5mZXJlbnNpIHBhbGluZyBiYW55YWsgZGFyaSBkYXRhIG5vbi1pbmZvcm1hdGlmIHRlcnNlYnV0Lg0KDQotIEtlcnVnaWFuDQoNCjEuICJLdXJ2YSIgS2FwbGFuLU1laWVyIHNlYmVuYXJueWEgdGlkYWsgdGVybGloYXQgc2VwZXJ0aSBrdXJ2YS4gQmVybGF3YW5hbiBkZW5nYW4gcmVncmVzaSBsb2dpc3RpayBtZXRvZGUgS2FwbGFuLU1laWVyIHRpZGFrIGRhcGF0IGRpZ2FtYmFya2FuIHNlYmFnYWkgZnVuZ3NpIGhhbHVzIChrdXJ2YSkgZGVuZ2FuIGJlYmVyYXBhIHBhcmFtZXRlciwgbWlzYWxueWEga2VtaXJpbmdhbiBhdGF1IHJhc2lvIG9kZHMgLiBJdHUgc2ViYWJueWEgIG1lbWJ1dHVoa2FuIHRhYmVsIGhhc2lsIGJvZG9oIGF0YXUgZ3JhZmlrLg0KDQoyLiBNZXRvZGUgS2FwbGFuLU1laWVyIHRpZGFrIGRhcGF0IG1lbW9kZWxrYW4gdmFyaWFiZWwgbnVtZXJpayAsIHRldGFwaSBoYW55YSBrYXRlZ29yaWthbC4NCg0KMy4gTWV0b2RlIEthcGxhbi1NZWllciB0aWRhayBkYXBhdCBtZW55ZXJ0YWthbiBiYW55YWsgdmFyaWFiZWwgcGVuamVsYXMgLiBJdHUgYnVydWssIGthcmVuYSBtZW1iYW5kaW5na2FuIGtlbG9tcG9rIGRhbGFtIGhhbCBiZXJ0YWhhbiBoaWR1cCBtdW5na2luIG1lbGV3YXRrYW4gZWZlayBmYWt0b3IgbGFpbiwgeWFuZyBkaWtlbmFsIHNlYmFnYWkga292YXJpYXQgYXRhdSBwZXJhbmN1LCB5YW5nIGJlcnBvdGVuc2kgbWVtZW5nYXJ1aGkgd2FrdHUgYmVydGFoYW4gaGlkdXAga2Vsb21wb2sgdGVydGVudHUuDQoNClNhcmFuDQoNCjEuIFNlbGFsdSBtZW5hbXBpbGthbiBrZXRpZGFrcGFzdGlhbiBzdGF0aXN0aWsgZGVuZ2FuIG1lbWFzdWtrYW4gOTUlIENJIGF0YXUvZGFuIG5pbGFpIHAgZGFyaSB1amkgTG9nLVJhbmsuIE1lbmFtcGlsa2FuIENJIHBhZGEgYmViZXJhcGEgdGl0aWsgd2FrdHUgcGVudGluZyBwYWRhIHBsb3QgdW50dWsgc2V0aWFwIGtlbG9tcG9rIHBlcmxha3VhbiB0ZXJrYWRhbmcgbGViaWggamVsYXMgZGFyaXBhZGEgbWVuYW1waWxrYW5ueWEgdW50dWsgc2VtdWEgdGl0aWsgd2FrdHUuIENJIHlhbmcgdGlkYWsgdHVtcGFuZyB0aW5kaWggbWVudW5qdWtrYW4gcGVyYmVkYWFuIHlhbmcgc2lnbmlmaWthbiBhbnRhciBrZWxvbXBvay4NCg0KMi4gTWVtcGVydGltYmFuZ2thbiB1bnR1ayBtZW1vdG9uZyBzdW1idSB4IC4ga2FyZW5hIG1hdGEgc2VjYXJhIGFsYW1pIHRlcnRhcmlrIGtlIGJhZ2lhbiBrYW5hbiBwbG90LCBkaSBtYW5hIHdha3R1IGJlcmFraGlyLiBOYW11biwgYWtoaXIgcGxvdCBiZXJpc2kgcGFsaW5nIHNlZGlraXQgaW5mb3JtYXNpIGRhbiBrZXRpZGFrcGFzdGlhbiB0ZXJiZXNhciBrYXJlbmEgaGFueWEgc2VkaWtpdCBwZXNlcnRhIHlhbmcgdGVyc2lzYS4gU2ViZXJhcGEgamF1aCB3YWt0dSB1bnR1ayBtZW1wZXJwYW5qYW5nIHBsb3Q/IFRlcnNlcmFoIGthbXUuDQoNCjMuIFNlbGFsdSBtZW5hbXBpbGthbiB0YWJlbCByaXNpa28geWFuZyBtZW51bmp1a2thbiBqdW1sYWggcGFzaWVuIGJlYmFzIGtlamFkaWFuIGRhbiBtYXNpaCBkYWxhbSB0aW5kYWsgbGFuanV0IGRpIHNldGlhcCBrZWxvbXBvayBwZXJsYWt1YW4gcGFkYSB0aXRpayB3YWt0dSB5YW5nIHJlbGV2YW4uDQoNCiMgU3Vydml2YWwgYW5hbHlzaXMgMjogUGFyYW1ldHJpYyBTdXJ2aXZhbCBNb2RlbHMNCg0KTWV0b2RlIEthcGxhbi1NZWllciAoS00pIG5vbi1wYXJhbWV0cmlrIHRpZGFrIGRhcGF0IG1lbmdnYW1iYXJrYW4gcHJvYmFiaWxpdGFzIGJlcnRhaGFuIGhpZHVwIGRlbmdhbiBmdW5nc2kgeWFuZyBoYWx1cywgeWFuZyBiZXJhcnRpIHRpZGFrIGRhcGF0IG1lbXByZWRpa3NpIGFwYSBwdW4uIE1vZGVsIHBhcmFtZXRyaWsgKG1pcy4gRWtzcG9uZW5zaWFsLCBXZWlidWxsLCBkbGwuKSBTZWxhaW4gaXR1LCBqaWthIG1vZGVsIHBhcmFtZXRyaWsgc2VzdWFpLCBtb2RlbCB0ZXJzZWJ1dCBsZWJpaCB0ZXBhdCwgbGViaWggZWZla3RpZiwgZGFuIGxlYmloIGluZm9ybWF0aWYgZGFyaXBhZGEgS00gYXRhdSBDb3guIE5hbXVuIHNheWFuZ255YSwgbGFuZ2thaCBpbmkgc2VyaW5nIGRpdGluZ2dhbGthbiBrYXJlbmEgcGVuZ2d1bmFhbiBtb2RlbCBwYXJhbWV0cmlrIGJlbGFrYW5nLiBEYWxhbSBwb3N0aW5nIGluaSBha2FuIG1lbmNvYmEgdW50dWsgbWVudXR1cCBjZWxhaCBpbmkuDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpICAjIGRhdGEgd3JhbmdsaW5nIGFuZCB2aXN1YWxpemF0aW9uDQpsaWJyYXJ5KHNqUGxvdCkgICAgICMgZm9yIHBsb3R0aW5nIHJlc3VsdHMgb2YgbG9nLnJlZ3IuDQpsaWJyYXJ5KGVmZmVjdHMpICAgICMgZm9yIHByb2JhYmlsaXR5IG91dHB1dCBhbmQgcGxvdHMNCmxpYnJhcnkoc3Vydml2YWwpICAgIyBmb3IgY29yZSBzdXJ2aXZhbCBhbmFseXNpcyByb3V0aW5lcw0KbGlicmFyeShzdXJ2bWluZXIpICAjIGZvciBkcmF3aW5nIHN1cnZpdmFsIGN1cnZlcw0KbGlicmFyeShmbGV4c3VydikgICAjIGZvciBQYXJhbWV0cmljIFN1cnZpdmFsIE1vZGVsbGluZw0KbGlicmFyeShrbml0cikgICAgICAjIGZvciBhIHdvbmRlcmZ1bC1sb29raW5nIHRhYmxlcyANCmBgYA0KIyMgTWVuZ2FwYSBraXRhIG1lbWJ1dHVoa2FuIG1vZGVsIGtlbGFuZ3N1bmdhbiBoaWR1cCBwYXJhbWV0cmlrDQoNCmBgYHtyfQ0KZDIgPC0gdGliYmxlKA0KICB0aW1lICAgPSBjKDEsMSwxLDIsMiwzLDQsNSw3LDEwKSwgDQogIHN0YXR1cyA9IGMoMSwxLDEsMSwwLDEsMCwwLDEsMCkNCikNCm0gPC0gc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiAxLCBkYXRhID0gZDIpDQpnZ3N1cnZwbG90KA0KICBtLCANCiAgY29uZi5pbnQgPSBGQUxTRSwgDQogIHN1cnYubWVkaWFuLmxpbmUgPSAiaHYiLA0KICB4bGFiID0gIkRheXMiLCANCiAgeWxhYiA9ICJTdXJ2aXZhbCBwcm9iYWJpbGl0eSIsIA0KICBicmVhay50aW1lLmJ5ID0gMSwNCiAgcmlzay50YWJsZSA9IEYNCikNCmBgYA0KDQpLZXJ1Z2lhbiB1dGFtYSBkYXJpICoqbWV0b2RlIG5vbi1wYXJhbWV0cmlrIEthcGxhbi1NZWllciAoS00pKiogeWFuZyBkaXR1bmp1a2thbiBwYWRhIGdhbWJhciBkaSBhdGFzIGFkYWxhaCB0aWRhayBkYXBhdCBkaWplbGFza2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBkZW5nYW4gZnVuZ3NpIHlhbmcgaGFsdXMsIHlhbmcgYXJ0aW55YSB0aWRhayBkYXBhdCBtZW1wcmVkaWtzaSBhcGFwdW4uIE1vZGVsIHBhcmFtZXRyaWsgKHNlcGVydGkgRWtzcG9uZW5zaWFsLCBXZWlidWxsLCBkbGwuKSBTZWxhaW4gaXR1LCAqKm1vZGVsIHBhcmFtZXRyaWsqKiBhZGFsYWggbGFuZ2thaCBsb2dpcyBkYWxhbSBwZXJqYWxhbmFuIGRhcmkgS00ga2UgbW9kZWwgQ294IHNlbWktcGFyYW1ldHJpayAsIGthcmVuYSBtZXJla2EgZGVuZ2FuIGluZGFoIG1lbmdodWJ1bmdrYW4gdGl0aWstdGl0aWsgYW50YXJhIG1vZGVsIEtNIGRhbiBDb3ggZGFuIGRlbmdhbiBkZW1pa2lhbiBzYW5nYXQgbWVuaW5na2F0a2FuIHBlbWFoYW1hbiB0ZW50YW5nIGFuYWxpc2lzIGtlbGFuZ3N1bmdhbiBoaWR1cC4gU2VsYWluIGl0dSwgamlrYSAqKm1vZGVsIHBhcmFtZXRyaWsgc2VzdWFpLCBtb2RlbCB0ZXJzZWJ1dCBsZWJpaCB0ZXBhdCwgbGViaWggZWZla3RpZiwgZGFuIGxlYmloIGluZm9ybWF0aWYqKiBkYXJpIEtNIGF0YXUgQ294LiBOYW11biBzYXlhbmdueWEsIGxhbmdrYWggaW5pIHNlcmluZyBkaXRpbmdnYWxrYW4ga2FyZW5hIHBlbmdndW5hYW4gbW9kZWwgcGFyYW1ldHJpayBiZWxha2FuZy4gDQoNCiMjIEFwYWthaCBXYWt0dSBpdHUgVmFyaWFiZWwgYXRhdSBLb25zdGFudGE/DQoNCktlbWF0aWFuIGRhcGF0IGRpZ2FtYmFya2FuIGRlbmdhbiBkdWEgaGFsOiBwZXJpc3Rpd2Ega2VtYXRpYW4gaXR1IHNlbmRpcmkgZGFuIHRpdGlrIHdha3R1IHRlcnRlbnR1IHNhYXQga2VtYXRpYW4gdGVyamFkaS4gRHVhIGhhbCBpbmkgc2VsYWx1IG1lbmdnYW1iYXJrYW4gc2F0dSBwZXJpc3Rpd2EsIGthcmVuYSBzYXR1IGhhbnlhIG1hdGkgc2VrYWxpLiBEZW5nYW4gZGVtaWtpYW4sIHdha3R1IGtlbWF0aWFuIGFrYW4gYmVydmFyaWFzaSBkYW4ganVtbGFoIGtlbWF0aWFuIGFrYW4gYmVydGFtYmFoIHNlaXJpbmcgd2FrdHUsIHlhbmcgYWthbiBtZW5qYWRpa2FuIHdha3R1IGl0dSBzZW5kaXJpIHNlYmFnYWkgdmFyaWFiZWwgLiBCZWdpdHVsYWggYmViZXJhcGEgcGVyaXN0aXdhIGtlbWF0aWFuIHBhZGEgdGl0aWsgd2FrdHUgeWFuZyBiZXJiZWRhIG1lbXVuZ2tpbmthbiB1bnR1ayBtZW5ndW5na2Fwa2FuIGtlbWF0aWFuIGRhbGFtIGR1YSBjYXJhOg0KDQoxLiBNZWxhbHVpIHNlanVtbGFoIGtlamFkaWFuIHlhbmcgYmVyYmVkYSBwZXIgc2F0dWFuIHdha3R1IHRldGFwICwgeWFuZyBzZXJpbmcgZGlzZWJ1dCBSaXNpa28gKEhhemFyZCkgdW50dWsgbWF0aSAsIGF0YXUgaGFueWEgSGF6YXJkICjOuyAtIGxhbWJkYSApLiBJbmkgbWVtYnVhdCBqdW1sYWgga2VqYWRpYW4gbWVuamFkaSB2YXJpYWJlbCwgZGFuIEJhaGF5YSBtZW5qYWRpIHRpbmdrYXQga2VtYXRpYW4gLCBtaXNhbG55YSwgcGVyIGhhcmkuIA0KDQoyLiBNZWxhbHVpIGJlbnRhbmdhbiB3YWt0dSBiZXJsYWx1IHlhbmcgYmVyYmVkYSBwZXIganVtbGFoIHBlcmlzdGl3YSB5YW5nIHRldGFwIC4gSW50ZXJ2YWwgd2FrdHUgYmlhc2FueWEgZGl1a3VyIGhpbmdnYSBwZXJpc3Rpd2EgYmVyaWt1dG55YSB0ZXJqYWRpLiBJbmkgbWVtYnVhdCB3YWt0dSBtZW5qYWRpIHZhcmlhYmVsLg0KDQojIyBQZXJ1YmFoYW4gc3RhYmlsIGRhbGFtIGJhaGF5YSBkYW4ga2VsYW5nc3VuZ2FuIGhpZHVwDQoNCkJheWFuZ2thbiBzZXRpYXAgaGFyaSB0ZXBhdCAzIGRhcmkgMTAgb3JhbmcgbWVuaW5nZ2FsIGRpIGFpciBsYXV0IHlhbmcgZGluZ2luIHNldGVsYWgga2VjZWxha2FhbiBUaXRhbmljLiBJbmkgdGluZ2thdCBrZW1hdGlhbiB5YW5nIGN1a3VwIHN0YWJpbCAsIGF0YXUgQmFoYXlhICwgc2ViZXNhciAzMCUuIEppa2EgYmFoYXlhIHVudHVrIG1hdGkgdGVydXMgdHVtYnVoIGRlbmdhbiBsYWp1IHlhbmcgc2FtYSwgbWFrYSBrZW11bmdraW5hbiB1bnR1ayBiZXJ0YWhhbiBoaWR1cCBha2FuIHRlcnVzIGJlcmt1cmFuZyBkZW5nYW4gbGFqdSB5YW5nIHNhbWEuIERlbmdhbiBkZW1pa2lhbiwgQmFoYXlhIGRhbiBLZWxhbmdzdW5nYW4gSGlkdXAgZGFwYXQgZGlla3NwcmVzaWthbiBzYXR1IHNhbWEgbGFpbi4gU2VjYXJhIGtodXN1cywgQmFoYXlhIGtlbWF0aWFuIGRhcmkgd2FrdHUga2Ugd2FrdHUgZGFwYXQgZGlsaWhhdCBzZWJhZ2FpIEdhZ2FsIGJlcnRhaGFuIGhpZHVwICRGKCB0ICkkIGRhbiBrZWxhbmdzdW5nYW4gaGlkdXAgZGFyaSB3YWt0dSBrZSB3YWt0dSAkUyggdCApJCB5YW5nICBkYXBhdCBkaWxpaGF0IHNlYmFnYWkgSGF6YXJkIG9mIE5PVC1keWluZyAsIGF0YXUgaGFueWEgSGF6YXJkIG5lZ2F0aWYgLCB5YW5nIHNlY2FyYSBtYXRlbWF0aXMgZGFwYXQgZGlueWF0YWthbiBzZWJhZ2FpIHRhbmRhIG1pbnVzIOKAnC3igJ0sIGF0YXUg4oCcMS3igJ0sIGRpIGRlcGFuIEhhemFyZC4gS2VkdWEgZnVuZ3NpIHRlcnNlYnV0IG1lbmdoYXNpbGthbiBnYXJpcyBsdXJ1cywgZGkgbWFuYSBCYWhheWEgdGVydXMgbWVuaW5na2F0IGRhbiBrZWxhbmdzdW5nYW4gaGlkdXAgdGVydXMgbWVudXJ1biAocGxvdCBkaSBiYXdhaCk6DQokJCBGKHQpID0gSGF6YXJkICogdCAkJA0KJCRTKHQpID0gMSAtIEhhemFyZCAqIHQkJA0KDQpgYGB7ciBpbWFnZTIsIGVjaG89RkFMU0UsIGZpZy5jYXA9IiIsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnMTAwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygib3V0cHV0Mi5wbmciKQ0KYGBgDQoNClBlbmluZ2thdGFuIGF0YXUgcGVudXJ1bmFuIHlhbmcgc3RhYmlsIGRhbGFtIGJhaGF5YSBhdGF1IGtlbGFuZ3N1bmdhbiBoaWR1cCBzZXBlcnRpIGl0dSBhZ2FrIHRpZGFrIGFsYW1pLCB0aWRhayByZWFsaXN0aXMuIERhbGFtIG1lbXBlcmtpcmFrYW4ga2VtYXRpYW4gZGFwYXQgZGlrYXRha24gc3VsaXQuIEJhaGF5YSBiaWFzYW55YSBtZW5pbmdrYXQgc2VjYXJhIGVrc3BvbmVuc2lhbCwgbWlzYWxueWEgZGFsYW0ga2FzdXMga2VsYXBhcmFuLCBhdGF1IG1lbnVydW4gc2VjYXJhIGVrc3BvbmVuc2lhbCwgbWlzYWxueWEgZGFsYW0ga2FzdXMgcGFuZGVtaSBzZXRlbGFoIHZha3NpbiBkaXRlbXVrYW4uDQoNCiMjIFBlcnViYWhhbiBla3Nwb25lbnNpYWwgcG9zaXRpZiBkYWxhbSBiYWhheWEgZGFuIGtlbGFuZ3N1bmdhbiBoaWR1cA0KDQpQaWtpcmthbiB0ZW50YW5nIGtlbGFwYXJhbiBzZWplbmFrLiBTZW1ha2luIGxhbWEga29uZGlzaSBrZWxhcGFyYW4sIHNlbWFraW4gdGluZ2dpIGtlbXVuZ2tpbmFuIChyaXNpa28pIG1hdGkuIFBsb3Qga2lyaSBkaSBiYXdhaCBtZW51bmp1a2thbiBwZXJrZW1iYW5nYW4gc2VwZXJ0aSBpdHUsIGRpIG1hbmEgYmFoYXlhIGtlbWF0aWFuICRGKCB0ICkkIGRpbnlhdGFrYW4gZGFsYW0gcHJvYmFiaWxpdGFzIGtlY2lsIHBhZGEgYXdhbG55YSAoYmViZXJhcGEga2VtYXRpYW4pLCB0ZXRhcGkgdHVtYnVoIHNlY2FyYSBla3Nwb25lbnNpYWwgZGVuZ2FuIHdha3R1IChzZW1ha2luIGJhbnlhayBrZW1hdGlhbikuIFNheWEgc3VrYSBtZW55ZWJ1dCB0cmVuIHNlcGVydGkgaXR1IHNlYmFnYWkgcGVydWJhaGFuIGVrc3BvbmVuc2lhbCB5YW5nIHBvc2l0aWYsIGF0YXUgbWVtcGVyY2VwYXQuICJleHAiIGRhbGFtIHJ1bXVzIGtpcmkgZGkgYmF3YWggYWRhbGFoIHNlbXVhIHlhbmcgZGlwZXJsdWthbiB1bnR1ayBtZXJlbmNhbmFrYW4gdHJlbiB0ZXJzZWJ1dC4NCg0KU2VrYWxpIGxhZ2ksIGthcmVuYSBrZWxhbmdzdW5nYW4gaGlkdXAgZGFwYXQgZGlsaWhhdCBzZWJhZ2FpIGJhaGF5YSBuZWdhdGlmIGRhcGF0IG1lbnlhdGFrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwICRTKCB0ICkkIGRlbmdhbiBoYW55YSBtZW5nZ3VuYWthbiB0YW5kYSBtaW51cyAoYXRhdSDigJwxLeKAnSkgZGkgZGVwYW4gSGF6YXJkLiBQbG90IGRpIHNlYmVsYWgga2FuYW4gbWVuYW1waWxrYW4gaGFzaWwgZGFyaSBmdW5nc2kgYmVydGFoYW4gaGlkdXAgdGVyc2VidXQuSmlrYSBiYWhheWEga2VtYXRpYW4gcmVuZGFoIGRpIGF3YWwgIndha3R1IiwgbWFrYSBrZW11bmdraW5hbiBiZXJ0YWhhbiBoaWR1cCB0aW5nZ2kuIERpIGFraGlyICJ3YWt0dSIsIEtlbGFuZ3N1bmdhbiBIaWR1cCB0dXJ1biBzZWNhcmEgZWtzcG9uZW5zaWFsIGthcmVuYSBwZW5pbmdrYXRhbiBCYWhheWEgc2VjYXJhIGVrc3BvbmVuc2lhbC4NCiQkIEYodCk9IGV4cF57SGF6YXJkICogdH0gJCQNCiQkUyh0KSA9IDEgLSBleHBee0hhemFyZCAqIHR9JCQNCg0KYGBge3IgaW1hZ2UzLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSIiLGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzEwMCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm91dHB1dDMucG5nIikNCmBgYA0KDQojIyBQZXJ1YmFoYW4gZWtzcG9uZW5zaWFsIG5lZ2F0aWYgZGFsYW0gYmFoYXlhIGRhbiBrZWxhbmdzdW5nYW4gaGlkdXANCg0KTmFtdW4sIGRhbGFtIGJlYmVyYXBhIGthc3VzLCBsZWJpaCBiYW55YWsgb3JhbmcgbWVuaW5nZ2FsIHBhZGEgYXdhbCAid2FrdHUiLCBkaSBtYW5hIHRpbmdrYXQga2VtYXRpYW4gbWVudXJ1biBkYXJpIHdha3R1IGtlIHdha3R1LiBQaWtpcmthbiB0ZW50YW5nIHBhbmRlbWksIGF0YXUga2VjZWxha2FhbiBiZXNhci4gUGVydWJhaGFubnlhIG1hc2loIGVrc3BvbmVuc2lhbCwgZGFuIG1lbnVqdSBrZSBhcmFoIHlhbmcgc2FtYTogbmFpaywgZGFsYW0ga2FzdXMgQmFoYXlhLCBkYW4gdHVydW4sIGRhbGFtIGthc3VzIGJlcnRhaGFuIGhpZHVwLiBOYW11biwgcGVydWJhaGFuIGVrc3BvbmVuc2lhbCBhZ2FrIHRlcmJhbGlrIChtZW1idW5na3VrKS4gU2F5YSBzdWthIG1lbnllYnV0bnlhIHNlYmFnYWkgcGVydWJhaGFuIGVrc3BvbmVuc2lhbCB5YW5nIG5lZ2F0aWYsIGF0YXUgbWVsYW1iYXQuDQoNClNlcGVydGkgInBlbWJlbmdrb2thbiBrZSBkYWxhbSIgZGFwYXQgZGljYXBhaSBkZW5nYW4gIi0iIG1pbnVzIHNpbmcgZGkgZGVwYW4gSGF6YXJkIGRhbiBmdW5nc2kgZWtzcG9uZW5zaWFsIGl0dSBzZW5kaXJpIChwZXJzYW1hYW4ga2lyaSBkYW4gZ2FtYmFyIGRpIGJhd2FoKS4gTWludXMgaW5pIHRpZGFrIG1lbmdnYW1iYXJrYW4gaGF6YXJkIG5lZ2F0aWYsIHNlcGVydGkgcGFkYSBjb250b2ggZGkgYXRhcy4gSXR1IGhhbnlhIG1lbmd1YmFoIGt1cnZhIGRhcmkgcGVyY2VwYXRhbiBrZSBwZXJsYW1iYXRhbi4gVW50dWsgbWVuZGFwYXRrYW4ga2VsYW5nc3VuZ2FuIGhpZHVwIHVudHVrIGZ1bmdzaSBpbmkgc2VwZXJ0aSBwYWRhIGNvbnRvaCBkaSBhdGFzLCBoYXJ1cyBtZW5nZ3VuYWthbiAiLSIgKGF0YXUgIjEtIikgZGkgZGVwYW4gc2VsdXJ1aCBla3NwcmVzaSBoYXphcmQgZWtzcG9uZW5zaWFsLiBNZW5hcmlrbnlhLCBkdWEgdGFuZGEgbWludXMgZGkgZGVwYW4gImV4cCIgZGFsYW0gcnVtdXMgU3Vydml2YWwgc2FsaW5nIG1lbmV0cmFsa2FuIGRhbiBtZW5qYWRpIG5pbGFpIHRhbWJhaCwgeWFuZyBtZW55aXNha2FuIGRlbmdhbiANCg0KJCRGKHQpPSAtIGV4cF57LUhhemFyZCAqIHR9JCQNCg0KJCRTKHQpID0gMSAtICggLSBleHBeey1IYXphcmQgKiB0fSkgPSBleHBeey1IYXphcmQgKiB0fSQkDQoNCmBgYHtyIGltYWdlNCwgZWNobz1GQUxTRSwgZmlnLmNhcD0iIixmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICcxMDAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJvdXRwdXQ0LnBuZyIpDQpgYGANCg0KIyMgTWVtYmFuZ3VuIE1vZGVsIEVrcG9uZW5zaWFsDQoNClNlamFrIGZ1bmdzaSBiZXJ0YWhhbiBoaWR1cCAkUyggdCApJCBtZW51bmp1a2thbiBwcm9iYWJpbGl0YXMgYmVydGFoYW4gaGlkdXAgbWVsZXdhdGkgdGl0aWsgd2FrdHUgdGVydGVudHUgLA0KDQokJFModCkgPSBQKFQgPiB0KSQkDQoNCmRhbiBmdW5nc2kgZWtzcG9uZW5zaWFsICRGKCB0ICkkIG1lbnVuanVra2FuIHByb2JhYmlsaXRhcyBGYWlsZWQtc3Vydml2YWwgbWVsZXdhdGkgdGl0aWsgd2FrdHUgdGVydGVudHUgLA0KDQokJEYodCkgPSBQKFQgXGxlcSB0KSA9IDEgLSBleHBeey1IYXphcmQgKiB0fSQkDQoNCmZ1bmdzaSBiZXJ0YWhhbiBoaWR1cCBrZW11ZGlhbiBkYXBhdCBkaW55YXRha2FuIGRhbGFtIGJlbnR1ayBmdW5nc2kgdGlkYWsgYmVydGFoYW4gaGlkdXAgKGVrc3BvbmVuc2lhbCk6DQoNCiQkUyh0KSA9IFAoVCA+IHQpID0gMSAtIFAoVCBcbGVxIHQpID0gMSAtIEYodCkgPSAxIC0gWzEgLSBleHBeey1IYXphcmQgKiB0fV0gPSBleHBeey1IYXphcmQgKiB0fSQkDQoNClNlaGluZ2dhIGZ1bmdzaSBzdXJ2aXZhbCB5YW5nIG1lbnVuanVra2FuIGxhanUgcGVudXJ1bmFuIGFkYWxhaCBmdW5nc2kgZmxpcHBlZCBoYXphcmQgeWFuZyBtZW51bmp1a2thbiBsYWp1IGtlbmFpa2FuLiBEZW5nYW4gZGVtaWtpYW4sIGRhcGF0IG1lbnVsaXMgdWxhbmcgJFMoIHQgKSQgc2ViYWdhaToNCg0KJCRTKHQpID0gZXhwXnstIEhhemFyZCAqIHR9ID0gZXhwXnstIFxsYW1iZGEqIHR9JCQNCg0KZGkgbWFuYSAtSGF6YXJkIGRhbiB3YWt0dSBhZGFsYWggZHVhIHBhcmFtZXRlciB5YW5nIG1lbmdnYW1iYXJrYW4gcGVydWJhaGFuIGVrc3BvbmVuc2lhbCAgZGFsYW0gcHJvYmFiaWxpdGFzIGJlcnRhaGFuIGhpZHVwLCBpdHVsYWggc2ViYWJueWEgbW9kZWwgc2VwZXJ0aSBpdHUgbWVtaWxpa2kgbmFtYSAtIG1vZGVsIGVrc3BvbmVuc2lhbCBwYXJhbWV0cmlrIC4gRGFuIGthcmVuYSBIYXphcmQgYWRhbGFoIG5lZ2F0aXZlICwgZGFuIGZ1bmdzaSBla3Nwb25lbnNpYWwgdGlkYWsgbGluaWVyIChhbGlhcy4gY3VydnkgKSAtIG1vZGVsIGtlbHVhciBtZW5naGFzaWxrYW4ga3VydmEgZWtzcG9uZW5zaWFsIG5lZ2F0aWYgKGxpaGF0IGRpIGJhd2FoKS4gVGluZ2thdCBwZW51cnVuYW4geWFuZyBtdWx1cyBzZXBlcnRpIGl0dSBtZW5nZ2FtYmFya2FuIHByb2JhYmlsaXRhcyBiZXJ0YWhhbiBoaWR1cCBqYXVoIGxlYmloIGJhaWsgZGFyaXBhZGEgbWV0b2RlIEthcGxhbi1NZWllciwgeWFuZyBzZWNhcmEgdGliYS10aWJhIChzZWNhcmEgYmVydGFoYXApIG1lbnVydW5rYW4gcHJvYmFiaWxpdGFzIGhhbnlhIHNldGVsYWggc3VhdHUgcGVyaXN0aXdhLCBzYW1iaWwgbWVuamFnYSBwcm9iYWJpbGl0YXMgdGV0YXAga29uc3RhbiBkaSBhbnRhcmEgcGVyaXN0aXdhIHRlcnNlYnV0Lg0KDQoNCiMjIENhcmEgbWVuZ2hpdHVuZyBtb2RlbCBwYXJhbWV0cmlrDQoNCmBgYHtyfQ0KbGlicmFyeShmbGV4c3VydikgICAgIyBmb3IgUGFyYW1ldHJpYyBTdXJ2aXZhbCBNb2RlbGxpbmcNCg0KZXggPC0gZmxleHN1cnZyZWcoU3Vydih0aW1lLCBzdGF0dXMpIH4gMSwgZGF0YSA9IGQyLCBkaXN0PSJleHBvbmVudGlhbCIpDQp3ZSA8LSBmbGV4c3VydnJlZyhTdXJ2KHRpbWUsIHN0YXR1cykgfiAxLCBkYXRhID0gZDIsIGRpc3Q9IndlaWJ1bGwiKQ0KDQpnZ3N1cnZwbG90KA0KICBleCwgDQogIGNvbmYuaW50ID0gRkFMU0UsIA0KICBzdXJ2Lm1lZGlhbi5saW5lID0gImh2IiwNCiAgeGxhYiA9ICJEYXlzIiwgDQogIHlsYWIgPSAiU3Vydml2YWwgcHJvYmFiaWxpdHkiLCANCiAgYnJlYWsudGltZS5ieSA9IDEsDQogIHJpc2sudGFibGUgPSBGDQopDQpgYGANCg0KUGFyYW1ldGVyIGt1cnZhICgkLVxsYW1iZGEgKiB0JCkgbWVtdW5na2lua2FuIGtpdGEgdW50dWsgbWVtb2RlbGthbiBkYW4gKm1lbXByZWRpa3NpKiBrZWxhbmdzdW5nYW4gaGlkdXAgZGFuIGJhaGF5YSBkYXJpIHdha3R1IGtlIHdha3R1LCB5YW5nICptZXJ1cGFrYW4ga2V1bnR1bmdhbiB1dGFtYSogZGFyaSBtb2RlbCBla3Nwb25lbnNpYWwgZGliYW5kaW5na2FuIGRlbmdhbiBtZXRvZGUgS2FwbGFuLU1laWVyLCB5YW5nIHRpZGFrIGJlcnNpZmF0IHBhcmFtZXRyaWsgZGFuIG9sZWgga2FyZW5hIGl0dSB0aWRhayBkYXBhdCBkaW1vZGVsa2FuLiBOYW11biwgbm9uLWxpbmVhcml0YXMgc2VyaW5nIGthbGkgbWVyZXBvdGthbiwgZGFuIGthbWkgbGViaWggc3VrYSBtZW5nZ3VuYWthbiBrb25zZXAgKnJlZ3Jlc2kgbGluZWFyKiwgeWFuZyBtZXJpbmdrYXMgKG1lcmVncmVzaWthbikgYmFueWFrIGFuZ2thIG1lbmphZGkgYmViZXJhcGEgYW5na2EsIHNlcGVydGkgaW50ZXJzZXAgKCRcYmV0YV8wJCkgZGFuIGtlbWlyaW5nYW4gKCRcYmV0YV8xJCkuIFVudHVuZ255YSwga3VydmEgbm9uLWxpbmllciBkYXBhdCBkZW5nYW4gbXVkYWggImRpbGluaWVya2FuIiBtZWxhbHVpIGxvZ2FyaXRtYSBuYXR1cmFsLiBVbnR1ayBtZWxha3VrYW4gaW5pLCBraXRhIGJhaGthbiB0aWRhayBwZXJsdSBtZW1haGFtaSBjYXJhIGtlcmphIGxvZ2FyaXRtYSBhdGF1IGZ1bmdzaSBla3Nwb25lbnNpYWwsIGtpdGEgaGFueWEgcGVybHUgbWVuZ2V0YWh1aSBiYWh3YSBrZWR1YW55YSBzYWxpbmcgbWVuZXRyYWxrYW4gc2F0dSBzYW1hIGxhaW4uIFNlbGFpbiBpdHUsIG1lbmdndW5ha2FuICJsb2ciIChtZWxvZ2FyaXRtYWthbiBrZWR1YSBzaXNpIHBlcnNhbWFhbiBkaSBiYXdhaCBpbmkpIG1lbmdoYXNpbGthbiB0aWdhIGVmZWsgc2FtcGluZyB5YW5nIHBvc2l0aWY6DQoNCjEuIFBlcnRhbWEsIGRpIHNpc2kga2FuYW4gcGVyc2FtYWFuLCBpbmkgYWthbiAqbWVtaW5kYWhrYW4ga3VydmEga2l0YSogKCQtXGxhbWJkYSAqIHQkKSAqbWVuamFkaSBzZWJ1YWggZ2FyaXMqICgkYl8wICsgYl8xeF8xICsgLi4uICsgYl9reF9rJCksIGRpIG1hbmEga2l0YSBha2FuIGRhcGF0IG1lbWlsaWtpIGludGVyc2VwIGRhbiBrb2VmaXNpZW4gJFxiZXRhJCBzZXBlcnRpIHBhZGEgcmVncmVzaSBsb2dpc3RpayBsaW5pZXIgYmlhc2EgDQokJEhhemFyZCA9IGV4cF57Yl8wICsgYl8xeF8xICsgLi4uICsgYl9reF9rfSQkIA0KDQphdGF1DQoNCiQkIGxvZyhIYXphcmQpID0gYl8wICsgYl8xeF8xICsgLi4uICsgYl9reF9rICQkIA0KDQpNb2RlbCBzdXJ2aXZhbCBzZXBlcnRpIGl0dSBzZWJlbmFybnlhIGFkYWxhaCBtb2RlbCBQb2lzc29uLiBPbGVoIGthcmVuYSBpdHUsIGFrYW4gc2FuZ2F0IG1lbWJhbnR1IGppa2Egc3VkYWggbWVuZ2V1YXNhaSBkaXN0cmlidXNpIFBvaXNzb24uIA0KDQoyLiBLZWR1YSwgaW5pIGFrYW4gbWVtYmFudHUga2l0YSB1bnR1ayB0ZXJodWJ1bmcga2UgbW9kZWwtbW9kZWwgc2VsYW5qdXRueWEsIHNlcGVydGkgbW9kZWwgV2VpYnVsbCBkYW4gQ294LCBrYXJlbmEgcGVyYmVkYWFuIGRpIGFudGFyYSBrZWR1YW55YSB0ZXJ1dGFtYSB0ZXJsZXRhayBwYWRhIGludGVyc2VwICIkYl8wJCI7DQoNCjMuIFRlcmFraGlyLCBpbmkgYWthbiBzYW5nYXQgbWVuaW5na2F0a2FuIGtlbWFtcHVhbiBpbnRlcnByZXRhc2ksIGthcmVuYSBIYXphcmQtUmF0aW9zIChIUnMpICh5YW5nIGRpaGFzaWxrYW4gb2xlaCBtb2RlbCBla3Nwb25lbnNpYWwpIGRhcGF0IGRpaW50ZXJwcmV0YXNpa2FuIHBlcnNpcyBzZXBlcnRpIE9kZHMtUmF0aW9zIChPUnMpIGRhcmkgcmVncmVzaSBsb2dpc3RpayAoc2VwZXJ0aSB5YW5nIGRpamVsYXNrYW4gZGFsYW0gcG9zdGluZyBzYXlhIHRlbnRhbmcgcmVncmVzaSBsb2dpc3RpaykuIFNhbWEgaGFsbnlhIGRlbmdhbiBPZGRzIGRhbGFtIHJlZ3Jlc2kgbG9naXN0aWssICpIYXphcmQgaXR1IHNlbmRpcmksIHlhbmcgbWVydXBha2FuIHByb2JhYmlsaXRhcyBtZW5pbmdnYWwgU0VLQVJBTkcqLCBrdXJhbmcgYmVyZ3VuYSBkaWJhbmRpbmdrYW4gZGVuZ2FuIEhhemFyZC1SYXRpby4gSGF6YXJkLVJhdGlvIGFkYWxhaCByYXNpbyBiYWhheWEgc2VzZW9yYW5nIHlhbmcgdGVycGFwYXIgKHNha2l0KSB0ZXJoYWRhcCBzZXNlb3JhbmcgeWFuZyB0aWRhayB0ZXJwYXBhciAoc2VoYXQpLiBNaXNhbG55YSBqaWthIEhSID0gMiwgcmlzaWtvIGtlbWF0aWFuIHNlc2VvcmFuZyB5YW5nIHRlcnBhcGFyIGFkYWxhaCBkdWEga2FsaSBsaXBhdCBkaWJhbmRpbmdrYW4gZGVuZ2FuIHNlc2VvcmFuZyB5YW5nIHRpZGFrIHRlcnBhcGFyLiANCg0KDQojIyBQaWtpcmFuIGFraGlyDQoNCioqQXBha2FoIG1vZGVsIHBhcmFtZXRyaWsgYmVyZ3VuYT8qKg0KDQotIFRpZ2Ega3VydmEgZGkgYXRhcyB5YW5nIG1lbmdnYW1iYXJrYW4gYmVyYmFnYWkgamVuaXMgcGVydWJhaGFuIGRhbGFtIGtlbGFuZ3N1bmdhbiBoaWR1cCBkYW4gYmFoYXlhIGRhcmkgd2FrdHUga2Ugd2FrdHUgZGltYWtzdWRrYW4gdW50dWsgbWVuZ2F0YWthbiBiYWh3YSBkaXN0cmlidXNpIGJpc2Egc2FuZ2F0IGJlcmJlZGEuIEppa2EgZGlzdHJpYnVzaSB5YW5nIHNlc3VhaSBkYXBhdCBkaXRlbXVrYW4sIG1vZGVsIHBhcmFtZXRyaWsgbGViaWggaW5mb3JtYXRpZiBkYXJpcGFkYSBtb2RlbCBLTSBhdGF1IENveCANCg0KLSBtb2RlbCBpbmkgZGFwYXQgbWVtcHJlZGlrc2kgcHJvYmFiaWxpdGFzIGtldGFoYW5hbiBoaWR1cCBwYWRhIHRpdGlrIHdha3R1IHRlcnRlbnR1LCBoYXphcmQga2VqYWRpYW4sIHJhdGEtcmF0YSBkYW4gbWVkaWFuIHdha3R1IGtldGFoYW5hbiBoaWR1cCBzdWRhaCB0ZXJzZWRpYQ0KDQotIG1vZGVsIGluaSBqdWdhIHNlZGlraXQgbGViaWggZWZpc2llbiBkYW4gbWVuZ2hhc2lsa2FuIGVzdGltYXNpIHlhbmcgbGViaWggdGVwYXQga2FyZW5hIGtlY29jb2thbiB5YW5nIGxlYmloIGJhaWsgKGxpaGF0IGdhbWJhciBkaSBhdGFzKQ0KDQoqQXBha2FoIG1vZGVsIHBhcmFtZXRyaWsgaXR1IHNlbXB1cm5hPyBUZW50dSBzYWphIHRpZGFrISoNCg0KLSBtb2RlbCBwYXJhbWV0cmlrIHBlcmx1IG1lbmVudHVrYW4gZGlzdHJpYnVzaSwgeWFuZyBtdW5na2luIHN1bGl0IHVudHVrIGRpaWRlbnRpZmlrYXNpDQoNCi0gbW9kZWwgaW5pIGp1Z2Egc2VjYXJhIG1hdGVtYXRpcyBsZWJpaCBrb21wbGVrcywgbWlzYWxueWEgS00sIGRhbiBvbGVoIGthcmVuYSBpdHUgbGViaWggamFyYW5nIGRpZ3VuYWthbiwgc2VoaW5nZ2EgbWVuZ3VyYW5naSBwZXJiYW5kaW5nYW4gaGFzaWwgYW50YXIgc3R1ZGkuIEthcmVuYSBwb3B1bGFyaXRhc255YSB5YW5nIGxlYmloIHJlbmRhaCwgc2F5YSB0aWRhayBha2FuIG1lbWJhaGFzIGxlYmloIGRhbGFtIHRlbnRhbmcgbW9kZWwgcGFyYW1ldHJpayB0ZXJ0ZW50dTogTW9kZWwgV2VpYnVsbCwgR29tcGVydHosIG1vZGVsIFdha3R1IEtlZ2FnYWxhbiB5YW5nIERpcGVyY2VwYXQsIGRsbC4NCg0KSmFkaSwgdGVybGVwYXMgZGFyaSBrZW55YXRhYW4gYmFod2EgbW9kZWwgcGFyYW1ldHJpayBhZGFsYWggYWx0ZXJuYXRpZiB5YW5nIGJhaWsgdW50dWsgbW9kZWwgcmVncmVzaSBLTSBkYW4gQ294ICh5YW5nIHRpZGFrIHBlcmx1IG1lbmVudHVrYW4gZGlzdHJpYnVzaSBhcGEgcHVuKSwgS00gZGFuIENveCB0ZXRhcCBtZW5qYWRpIG1ldG9kZSB5YW5nIHBhbGluZyBwb3B1bGVyIHVudHVrIG1lbmdhbmFsaXNpcyBkYXRhIHN1cnZpdmFsLiBEYW4gaXR1bGFoIG1lbmdhcGEgbGFuZ2thaCBsb2dpcyBiZXJpa3V0bnlhIGRhbGFtIHBlcmphbGFuYW4gc3RhdGlzdGlrIGRhbGFtIG1lbXBlbGFqYXJpIE1vZGVsIENveCBQcm9wb3J0aW9uYWwgSGF6YXJkIChzZWRhbmcgYmVybGFuZ3N1bmcpLg0KDQojIFJlZmVyZW5zaSANCi0gaHR0cHM6Ly95dXphci1ibG9nLm5ldGxpZnkuYXBwL3Bvc3RzLzIwMjEtMDEtMDMtc3Vydml2YWwtYW5hbHlzaXMtMS1hLWdlbnRsZS1pbnRyb2R1Y3Rpb24taW50by1rYXBsYW4tbWVpZXItY3VydmVzLw0KDQotIGh0dHBzOi8veXV6YXItYmxvZy5uZXRsaWZ5LmFwcC9wb3N0cy8yMDIxLTAxLTA2LXN1cnZpdmFsLWFuYWx5c2lzLTItcGFyYW1ldHJpYy1zdXJ2aXZhbC1tb2RlbHMvDQo=