knitr::opts_chunk$set(echo = TRUE)
Text mining merupakan pendekatan analitis yang digunakan
untuk mengekstraksi informasi dan pola bermakna dari data teks tidak
terstruktur, seperti percakapan daring, dokumen, maupun media sosial.
Berbeda dengan data numerik yang memiliki struktur baku, data teks
bersifat bebas, kaya konteks, dan mengandung variasi bahasa yang tinggi,
sehingga memerlukan teknik khusus dalam pengolahannya. Melalui tahapan
seperti pembersihan teks, tokenisasi, normalisasi, dan pembobotan kata,
text mining memungkinkan teks diubah menjadi representasi
terstruktur yang dapat dianalisis secara kuantitatif. Pendekatan ini
semakin relevan seiring meningkatnya volume data tekstual dalam
aktivitas komunikasi digital.
Tujuan utama text mining adalah untuk mengidentifikasi pola,
kecenderungan, dan makna tersembunyi yang tidak mudah ditangkap melalui
pembacaan manual, terutama pada data berskala besar. Dalam konteks
analisis percakapan, text mining digunakan untuk memahami
dinamika komunikasi, mengukur intensitas dan fokus pembahasan, serta
mendeteksi indikasi sentimen atau isu tertentu yang muncul berulang.
Dengan demikian, text mining tidak hanya berfungsi sebagai alat
eksplorasi data, tetapi juga sebagai dasar pengambilan keputusan
berbasis bukti, evaluasi kebijakan, dan pemahaman perilaku komunikasi
secara sistematis dan objektif.
library(tidyverse)
library(tidytext)
library(rwhatsapp)
library(ggplot2)
library(lubridate)
library(wordcloud2)
Load Data
Data percakapan WhatsApp diperoleh dari file ekspor riwayat chat grup
dalam format .txt. Data kemudian dibaca menggunakan fungsi
rwa_read() dari paket rwhatsapp. Untuk menjaga
relevansi analisis, data dibatasi hanya pada pesan yang dikirim mulai 1
Januari 2025, sehingga analisis merepresentasikan dinamika komunikasi
sepanjang tahun berjalan.
Tahap awal eksplorasi data dilakukan dengan menampilkan beberapa
baris pertama dan memeriksa struktur data menggunakan
glimpse(). Pemeriksaan ini bertujuan untuk memastikan
konsistensi variabel, khususnya kolom waktu (time), penulis
pesan (author), dan isi pesan (text).
Analisis percakapan WhatsApp dilakukan menggunakan pendekatan
text mining, yaitu serangkaian teknik untuk mengekstraksi
informasi bermakna dari data teks tidak terstruktur. Pendekatan ini
mencakup tahapan pembersihan teks, tokenisasi, pembobotan kata, serta
analisis frekuensi dan kemiripan teks untuk mengidentifikasi pola
komunikasi yang tersembunyi dalam data percakapan (Feldman & Sanger,
2007; Manning et al., 2008).
## # A tibble: 6 × 6
## time author text source emoji emoji_name
## <dttm> <fct> <chr> <chr> <list> <list>
## 1 2025-01-02 09:28:00 Ofi Ana Sari "Pak @Raden Sinang… Whats… <chr> <chr [2]>
## 2 2025-01-02 09:33:00 Raden Sinang "Tanggal 7 rencanan… Whats… <NULL> <NULL>
## 3 2025-01-02 09:36:00 Mayang Sari "tgl 2,3,6 masih fr… Whats… <NULL> <NULL>
## 4 2025-01-02 09:38:00 Ofi Ana Sari "dah ngelupain kerj… Whats… <NULL> <NULL>
## 5 2025-01-02 09:41:00 Raden Sinang "tunggu aja, siapa … Whats… <NULL> <NULL>
## 6 2025-01-02 09:44:00 Budi Santoso "Ketua tim yg sdh y… Whats… <chr> <chr [1]>
Pembersihan Data (Data Cleaning)
Salah satu isu yang ditemukan adalah adanya pesan tanpa identitas
pengirim (nilai NA pada kolom author). Pesan-pesan tersebut umumnya
merupakan notifikasi sistem atau pesan non-individual, sehingga
dikeluarkan dari analisis. Setelah proses pembersihan ini, dataset hanya
berisi pesan yang memiliki pengirim yang jelas.
Langkah ini penting untuk menjamin bahwa analisis frekuensi,
partisipasi, dan sentimen benar-benar mencerminkan perilaku komunikasi
antaranggota grup.
glimpse(history)
## Rows: 4,570
## Columns: 6
## $ time <dttm> 2025-01-02 09:28:00, 2025-01-02 09:33:00, 2025-01-02 09:36…
## $ author <fct> Ofi Ana Sari, Raden Sinang, Mayang Sari, Ofi Ana Sari, Rade…
## $ text <chr> "Pak @Raden Sinang pembagian tim 2025 belum ade kah? dah…
## $ source <chr> "WhatsApp Chat with Ngobrolin Roempian2025.txt", "WhatsApp …
## $ emoji <list> <"😅", "😂">, <NULL>, <NULL>, <NULL>, <NULL>, "😂", <NULL>, <…
## $ emoji_name <list> <"grinning face with sweat", "face with tears of joy">, <N…
# Cek Jumlah NA pada Kolom Author
history %>% summarise(na_author = sum(is.na(author)))
## # A tibble: 1 × 1
## na_author
## <int>
## 1 23
# Tampilkan Baris dengan Author NA
history %>% filter(is.na(author)) %>% head(10)
## # A tibble: 10 × 6
## time author text source emoji emoji_name
## <dttm> <fct> <chr> <chr> <list> <list>
## 1 2025-01-11 09:48:00 <NA> Amalia Noviani was added Whats… <NULL> <NULL>
## 2 2025-01-11 09:48:00 <NA> Amalia Noviani left Whats… <NULL> <NULL>
## 3 2025-02-21 03:30:00 <NA> Bu Ida Eridawaty added H… Whats… <NULL> <NULL>
## 4 2025-02-21 03:40:00 <NA> Bu Nona Iriana was added Whats… <NULL> <NULL>
## 5 2025-02-21 03:40:00 <NA> Bu Nona Iriana joined us… Whats… <NULL> <NULL>
## 6 2025-02-21 03:40:00 <NA> Amiek Chamami joined usi… Whats… <NULL> <NULL>
## 7 2025-04-09 09:37:00 <NA> Raden Sinang added Ruth … Whats… <NULL> <NULL>
## 8 2025-06-04 10:50:00 <NA> Raden Sinang added Nathi… Whats… <NULL> <NULL>
## 9 2025-07-04 10:44:00 <NA> Mayang Sari removed Herl… Whats… <NULL> <NULL>
## 10 2025-07-04 10:44:00 <NA> Mayang Sari removed Dwi … Whats… <NULL> <NULL>
# Hapus Baris yang Tidak Memiliki Author
history <- history %>% drop_na(author)
Total Chat
Analisis deskriptif awal dilakukan dengan menghitung total jumlah
pesan yang terkirim selama periode pengamatan. Selanjutnya, dilakukan
penghitungan jumlah pesan berdasarkan pengirim (author) untuk
mengidentifikasi anggota grup yang paling aktif.
history %>%
summarise(total_chat = n())
## # A tibble: 1 × 1
## total_chat
## <int>
## 1 4547
Hasilnya divisualisasikan dalam bentuk diagram batang horizontal.
Visualisasi ini memberikan gambaran yang jelas mengenai distribusi
kontribusi pesan antaranggota, sekaligus membantu mengidentifikasi pola
dominasi komunikasi dalam grup.
history %>%
count(author, sort = TRUE) %>%
ggplot(aes(x = n, y = reorder(author, n), fill = author)) +
geom_col(alpha = 0.9, width = 0.7) +
geom_text(aes(label = n), hjust = -0.1, size = 3) +
scale_x_continuous(expand = expansion(mult = c(0, 0.2))) +
scale_fill_viridis_d("Nama") +
theme_minimal() +
theme(
legend.position = "none",
axis.title.y = element_blank(),
plot.margin = margin(10, 40, 10, 10)
) +
ggtitle("Jumlah Chat yang Dikirim (1 Jan – 31 Des 2025)")

Visualisasi Chat
Untuk menganalisis pola temporal, format waktu dikonversi ke dalam
bahasa Indonesia dengan mengatur sistem lokal. Selanjutnya, dibuat
variabel hari (day) berdasarkan tanggal pengiriman pesan.
Distribusi jumlah pesan per hari dianalisis dan divisualisasikan,
sehingga dapat diketahui hari-hari tertentu dengan intensitas komunikasi
yang lebih tinggi. Analisis ini berguna untuk memahami ritme aktivitas
grup, misalnya apakah percakapan lebih aktif pada hari kerja atau akhir
pekan.
Selain itu, waktu pesan juga diuraikan lebih detail menggunakan
lubridate menjadi komponen tahun, bulan, tanggal, jam,
menit, dan detik. Informasi ini membuka peluang analisis lanjutan
terkait jam sibuk komunikasi atau tren musiman.
## [1] "id_ID.utf8"
history %>%
count(day) %>%
ggplot(aes(x = n, y = reorder(day, n), fill = day)) +
geom_col() +
geom_text(aes(label = n), hjust = -0.1, size = 3.5) +
scale_x_continuous(expand = expansion(mult = c(0, 0.2))) +
scale_fill_viridis_d() +
theme_minimal() +
theme(
legend.position = "none"
) +
labs(
y = "Hari",
x = "Jumlah Chat",
title = "Jumlah Chat per Hari"
)

Wordcloud
Untuk memahami topik dan kosakata yang dominan dalam percakapan grup,
dilakukan analisis teks menggunakan pendekatan bag-of-words.
Pendekatan ini merepresentasikan dokumen sebagai kumpulan kata tanpa
memperhatikan urutan, sehingga memungkinkan analisis frekuensi
kemunculan kata secara sistematis (Manning et al., 2008).
Pesan yang berupa placeholder media dikeluarkan dari
analisis, kemudian dilakukan tokenisasi untuk memecah teks menjadi kata
tunggal. Angka, kata sangat pendek, serta stopwords Bahasa
Indonesia dihapus guna meningkatkan kualitas representasi teks.
Kata-kata yang tersisa dihitung frekuensinya dan divisualisasikan dalam
bentuk wordcloud, yang mencerminkan kata-kata dominan dalam percakapan
grup (Silge & Robinson, 2017).
stopwords <- read.csv("stopwordbahasa.csv")
colnames(stopwords) <- c("stopword")
Kata yang paling sering digunakan (tanpa Stopwords)
history %>%
filter(text != "<Media tidak disertakan>") %>%
unnest_tokens(kata, text) %>%
filter(
!str_detect(kata, "\\d"), # buang angka
nchar(kata) > 2 # buang kata <= 2 huruf
) %>%
anti_join(stopwords, by = c("kata" = "stopword")) %>%
count(kata, sort = TRUE) %>%
wordcloud2()
Frekuensi Frase
Tertentu
Selain analisis kata tunggal, dilakukan pula analisis frasa tertentu
yang secara substantif mencerminkan dinamika komunikasi, seperti
ekspresi persetujuan, permintaan, atau kesopanan.
Sebelum penghitungan, dilakukan normalisasi teks untuk menyamakan
variasi penulisan dengan makna yang sama (misalnya “ok”, “oke”, “okay”).
Setelah itu, frekuensi kemunculan frasa-frasa tertentu dihitung
menggunakan pencocokan berbasis pola kata (regular expression).
Pendekatan ini memungkinkan analisis yang lebih semantik dibanding
sekadar frekuensi kata.
Normalisasi teks dilakukan untuk menyamakan variasi penulisan kata
atau frasa yang memiliki makna serupa, sehingga analisis tidak
terdistorsi oleh perbedaan ejaan atau gaya bahasa. Pendekatan ini
penting dalam text mining karena variasi linguistik yang tinggi
pada data percakapan informal dapat memengaruhi hasil analisis frekuensi
dan interpretasi makna (Feldman & Sanger, 2007).
hasil_frasa <- count_phrases(text_norm, frasa)
hasil_frasa
## # A tibble: 7 × 2
## frasa jumlah
## <chr> <int>
## 1 baik pak 6
## 2 siap pak 2
## 3 noted 7
## 4 ok 14
## 5 terima kasih 271
## 6 maaf 66
## 7 tolong 27
Frekuensi Chat
Frekuensi pesan per hari dianalisis dan divisualisasikan menggunakan
heatmap kalender, di mana warna merepresentasikan tingkat kepadatan
pesan. Visualisasi ini memudahkan identifikasi hari-hari dengan
aktivitas komunikasi yang sangat tinggi atau sangat rendah.
Selanjutnya, dilakukan analisis hari teramai pada setiap bulan.
Dengan mengelompokkan data berdasarkan bulan dan hari, kemudian memilih
hari dengan jumlah pesan tertinggi, diperoleh gambaran pola aktivitas
dominan pada setiap bulan. Hasilnya divisualisasikan kembali dalam
bentuk heatmap dua dimensi (hari × bulan).
library(dplyr)
library(lubridate)
hasil_hari_terramai <- history %>%
mutate(
bulan = month(time, label = TRUE, abbr = FALSE),
hari = weekdays(as.Date(time))
) %>%
group_by(bulan, hari) %>%
summarise(jumlah_chat = n(), .groups = "drop") %>%
group_by(bulan) %>%
slice_max(jumlah_chat, n = 1, with_ties = FALSE) %>%
arrange(bulan)
hasil_hari_terramai
## # A tibble: 12 × 3
## # Groups: bulan [12]
## bulan hari jumlah_chat
## <ord> <chr> <int>
## 1 Januari Jumat 73
## 2 Februari Kamis 120
## 3 Maret Rabu 236
## 4 April Rabu 112
## 5 Mei Rabu 48
## 6 Juni Selasa 70
## 7 Juli Rabu 96
## 8 Agustus Jumat 175
## 9 September Senin 168
## 10 Oktober Rabu 112
## 11 November Jumat 82
## 12 Desember Selasa 186
Tabel menunjukkan distribusi jumlah chat selama satu tahun yang
dikelompokkan berdasarkan bulan dan hari dominan terjadinya aktivitas
chat pada bulan tersebut.
Secara umum, aktivitas chat tidak merata sepanjang tahun dan
menunjukkan pola fluktuatif yang cukup jelas.
Puncak aktivitas chat terjadi pada bulan Maret dengan total 236
chat, yang didominasi pada hari Rabu. Hal ini mengindikasikan adanya
peningkatan intensitas komunikasi pada periode awal tahun, yang
kemungkinan berkaitan dengan aktivitas koordinasi, perencanaan, atau
dinamika kerja pasca-awal tahun.
Aktivitas chat relatif tinggi juga terlihat pada Agustus (175
chat, Jumat) dan September (168 chat, Senin). Pola ini dapat
mencerminkan meningkatnya kebutuhan komunikasi menjelang atau sesudah
periode tertentu, seperti evaluasi tengah tahun atau penyesuaian
program.
Aktivitas terendah tercatat pada bulan Mei dengan hanya 48 chat,
meskipun masih didominasi hari Rabu. Rendahnya intensitas ini dapat
mengindikasikan periode aktivitas yang lebih stabil atau berkurangnya
kebutuhan koordinasi.
Dari sisi hari, Rabu muncul sebagai hari yang paling sering
menjadi hari dominan (Maret, April, Mei, Juli, Oktober), menunjukkan
bahwa pertengahan minggu merupakan waktu yang relatif aktif untuk
komunikasi.
Sementara itu, Jumat dan Selasa juga beberapa kali muncul sebagai
hari dominan, tetapi dengan frekuensi yang lebih rendah, sedangkan Senin
hanya dominan pada satu bulan, yaitu September.
history %>%
mutate(
bulan = month(time, label = TRUE, abbr = FALSE),
hari = factor(
weekdays(as.Date(time)),
levels = c("Senin","Selasa","Rabu","Kamis","Jumat","Sabtu","Minggu")
)
) %>%
count(bulan, hari) %>%
ggplot(aes(hari, bulan, fill = n)) +
geom_tile(color = "white") +
scale_fill_viridis_c() +
theme_minimal() +
labs(
title = "Hari Teramai Chat per Bulan",
x = "Hari",
y = "Bulan",
fill = "Jumlah Chat"
)

Sentimen Negatif
Analisis sentimen dilakukan secara eksploratif dengan fokus pada
identifikasi indikasi sentimen negatif dalam percakapan grup. Pendekatan
yang digunakan bersifat lexicon-based, yaitu dengan
memanfaatkan daftar kata negatif yang secara konseptual
merepresentasikan ketidakpuasan, kesalahan, atau kendala dalam
komunikasi (Liu, 2012).
Setiap pesan diberikan skor negatif berdasarkan jumlah kemunculan
kata negatif. Pesan dengan skor lebih dari nol dianggap mengandung
sentimen negatif dan dianalisis lebih lanjut.
Untuk menghindari duplikasi makna akibat variasi redaksi kalimat,
diterapkan pendekatan Term Frequency–Inverse Document Frequency
(TF-IDF) sebagai metode pembobotan kata. TF-IDF memberikan bobot lebih
tinggi pada kata yang bersifat spesifik terhadap suatu pesan dan
menurunkan pengaruh kata yang umum muncul di banyak pesan (Salton &
Buckley, 1988).
Selanjutnya, tingkat kemiripan antar pesan diukur menggunakan
cosine similarity berbasis vektor TF-IDF. Pendekatan ini
memungkinkan identifikasi pesan-pesan yang secara semantik memiliki
makna serupa meskipun berbeda secara struktur kalimat (Singhal,
2001).
pesan_makna_unik <- sentimen_chat %>%
filter(!text_clean %in% similarity$item2) %>%
arrange(desc(skor_negatif))
pesan_makna_unik %>%
select(time, author, text, skor_negatif)
## # A tibble: 259 × 4
## time author text skor_negatif
## <dttm> <fct> <chr> <int>
## 1 2025-04-14 10:43:00 Karunia Ramadhani "Selamat pagi Bapa… 9
## 2 2025-06-18 08:09:00 Mayang Sari "Info kemarin dr J… 6
## 3 2025-12-30 03:31:00 Karunia Ramadhani "Sehubungan dengan… 5
## 4 2025-03-26 09:15:00 Ofi Ana Sari "disni sy bukan *p… 4
## 5 2025-03-26 09:16:00 Freshy Windy "Bukan mbaaakkk ka… 4
## 6 2025-04-16 06:12:00 Asy-Syaja'ul Haqqul Amin "Assalamu'alaikum … 4
## 7 2025-04-21 10:23:00 Raden Sinang "Usul saya, inisia… 4
## 8 2025-10-15 08:56:00 Karunia Ramadhani "Untuk konfirmasi … 4
## 9 2025-09-25 02:10:00 Raden Sinang "Yth.Teman2, menin… 3
## 10 2025-01-02 04:49:00 Ketut Krisna "Bapak/Ibu mohon u… 2
## # ℹ 249 more rows
Penutup
Secara keseluruhan, analisis ini mengombinasikan pendekatan
deskriptif dan text mining untuk menggambarkan dinamika
komunikasi dalam grup WhatsApp. Melalui analisis frekuensi, visualisasi
temporal, eksplorasi kosakata, serta reduksi semantik pesan negatif,
penelitian ini menunjukkan bagaimana data percakapan digital dapat
dimanfaatkan untuk memahami pola interaksi sosial secara lebih
sistematis. Pendekatan ini sejalan dengan praktik analisis teks modern
yang menekankan integrasi metode statistik dan linguistik dalam
pengolahan data tidak terstruktur (Manning et al., 2008; Silge &
Robinson, 2017).
Referensi
[1] Feldman, R., & Sanger, J. (2007). The text mining
handbook: Advanced approaches in analyzing unstructured data.
Cambridge University Press.
[2] Liu, B. (2012). Sentiment analysis and opinion mining. Morgan
& Claypool Publishers. https://doi.org/10.2200/S00416ED1V01Y201204HLT016
[3] Manning, C. D., Raghavan, P., & Schütze, H. (2008).
Introduction to information retrieval. Cambridge University
Press.
[4] Salton, G., & Buckley, C. (1988). Term-weighting
approaches in automatic text retrieval. Information Processing &
Management, 24(5), 513–523. https://doi.org/10.1016/0306-4573(88)90021-0
[5] Silge, J., & Robinson, D. (2017). Text mining with R: A
tidy approach. O’Reilly Media.
[6] Singhal, A. (2001). Modern information retrieval: A brief
overview. IEEE Data Engineering Bulletin, 24(4), 35–43.
Direktorat Statistik Kesejahteraan Rakyat, BPS, saptahas@bps.go.id
LS0tDQp0aXRsZTogIkFuYWxpc2lzIFBlcmNha2FwYW4gV2hhdHNBcHAgPGJyPiBkZW5nYW4gUGVuZGVrYXRhbiBUZXh0IE1pbmluZyINCnN1YnRpdGxlOiAiQWt0aXZpdGFzIFdoYXRzQXBwIEdydXAgKEFrdXNpc2kgZGF0YTogMSBKYW51YXJpIDIwMjUpIg0KYXV0aG9yOiAiU2FwdGEgSGFzdGhvIFBvbmNvIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IGpvdXJuYWwNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCi0tLQ0KDQpgYGB7PWh0bWx9DQo8c3R5bGU+DQpib2R5ew0KdGV4dC1hbGlnbjoganVzdGlmeX0NCjwvc3R5bGU+DQpgYGANCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1UUlVFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCl9UZXh0IG1pbmluZ18gbWVydXBha2FuIHBlbmRla2F0YW4gYW5hbGl0aXMgeWFuZyBkaWd1bmFrYW4gdW50dWsgbWVuZ2Vrc3RyYWtzaSBpbmZvcm1hc2kgZGFuIHBvbGEgYmVybWFrbmEgZGFyaSBkYXRhIHRla3MgdGlkYWsgdGVyc3RydWt0dXIsIHNlcGVydGkgcGVyY2FrYXBhbiBkYXJpbmcsIGRva3VtZW4sIG1hdXB1biBtZWRpYSBzb3NpYWwuIEJlcmJlZGEgZGVuZ2FuIGRhdGEgbnVtZXJpayB5YW5nIG1lbWlsaWtpIHN0cnVrdHVyIGJha3UsIGRhdGEgdGVrcyBiZXJzaWZhdCBiZWJhcywga2F5YSBrb250ZWtzLCBkYW4gbWVuZ2FuZHVuZyB2YXJpYXNpIGJhaGFzYSB5YW5nIHRpbmdnaSwgc2VoaW5nZ2EgbWVtZXJsdWthbiB0ZWtuaWsga2h1c3VzIGRhbGFtIHBlbmdvbGFoYW5ueWEuIE1lbGFsdWkgdGFoYXBhbiBzZXBlcnRpIHBlbWJlcnNpaGFuIHRla3MsIHRva2VuaXNhc2ksIG5vcm1hbGlzYXNpLCBkYW4gcGVtYm9ib3RhbiBrYXRhLCBfdGV4dCBtaW5pbmdfIG1lbXVuZ2tpbmthbiB0ZWtzIGRpdWJhaCBtZW5qYWRpIHJlcHJlc2VudGFzaSB0ZXJzdHJ1a3R1ciB5YW5nIGRhcGF0IGRpYW5hbGlzaXMgc2VjYXJhIGt1YW50aXRhdGlmLiBQZW5kZWthdGFuIGluaSBzZW1ha2luIHJlbGV2YW4gc2VpcmluZyBtZW5pbmdrYXRueWEgdm9sdW1lIGRhdGEgdGVrc3R1YWwgZGFsYW0gYWt0aXZpdGFzIGtvbXVuaWthc2kgZGlnaXRhbC4NCg0KVHVqdWFuIHV0YW1hIF90ZXh0IG1pbmluZ18gYWRhbGFoIHVudHVrIG1lbmdpZGVudGlmaWthc2kgcG9sYSwga2VjZW5kZXJ1bmdhbiwgZGFuIG1ha25hIHRlcnNlbWJ1bnlpIHlhbmcgdGlkYWsgbXVkYWggZGl0YW5na2FwIG1lbGFsdWkgcGVtYmFjYWFuIG1hbnVhbCwgdGVydXRhbWEgcGFkYSBkYXRhIGJlcnNrYWxhIGJlc2FyLiBEYWxhbSBrb250ZWtzIGFuYWxpc2lzIHBlcmNha2FwYW4sIF90ZXh0IG1pbmluZ18gZGlndW5ha2FuIHVudHVrIG1lbWFoYW1pIGRpbmFtaWthIGtvbXVuaWthc2ksIG1lbmd1a3VyIGludGVuc2l0YXMgZGFuIGZva3VzIHBlbWJhaGFzYW4sIHNlcnRhIG1lbmRldGVrc2kgaW5kaWthc2kgc2VudGltZW4gYXRhdSBpc3UgdGVydGVudHUgeWFuZyBtdW5jdWwgYmVydWxhbmcuIERlbmdhbiBkZW1pa2lhbiwgX3RleHQgbWluaW5nXyB0aWRhayBoYW55YSBiZXJmdW5nc2kgc2ViYWdhaSBhbGF0IGVrc3Bsb3Jhc2kgZGF0YSwgdGV0YXBpIGp1Z2Egc2ViYWdhaSBkYXNhciBwZW5nYW1iaWxhbiBrZXB1dHVzYW4gYmVyYmFzaXMgYnVrdGksIGV2YWx1YXNpIGtlYmlqYWthbiwgZGFuIHBlbWFoYW1hbiBwZXJpbGFrdSBrb211bmlrYXNpIHNlY2FyYSBzaXN0ZW1hdGlzIGRhbiBvYmpla3RpZi4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkodGlkeXRleHQpDQpsaWJyYXJ5KHJ3aGF0c2FwcCkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeSh3b3JkY2xvdWQyKQ0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0Kc2V0d2QoIkQ6XFwyLiBQZW5nZW1iYW5nYW4gZGlyaVxcMSBFeGVyY2lzZSBCYWd1c1xcVGV4dCBhbmQgU2NyYXBwaW5nXFwiKQ0KYGBgDQoNCiMgTG9hZCBEYXRhDQoNCkRhdGEgcGVyY2FrYXBhbiBXaGF0c0FwcCBkaXBlcm9sZWggZGFyaSBmaWxlIGVrc3BvciByaXdheWF0IGNoYXQgZ3J1cCBkYWxhbSBmb3JtYXQgLnR4dC4gRGF0YSBrZW11ZGlhbiBkaWJhY2EgbWVuZ2d1bmFrYW4gZnVuZ3NpIGByd2FfcmVhZCgpYCBkYXJpIHBha2V0IGByd2hhdHNhcHBgLiBVbnR1ayBtZW5qYWdhIHJlbGV2YW5zaSBhbmFsaXNpcywgZGF0YSBkaWJhdGFzaSBoYW55YSBwYWRhIHBlc2FuIHlhbmcgZGlraXJpbSBtdWxhaSAxIEphbnVhcmkgMjAyNSwgc2VoaW5nZ2EgYW5hbGlzaXMgbWVyZXByZXNlbnRhc2lrYW4gZGluYW1pa2Ega29tdW5pa2FzaSBzZXBhbmphbmcgdGFodW4gYmVyamFsYW4uDQoNClRhaGFwIGF3YWwgZWtzcGxvcmFzaSBkYXRhIGRpbGFrdWthbiBkZW5nYW4gbWVuYW1waWxrYW4gYmViZXJhcGEgYmFyaXMgcGVydGFtYSBkYW4gbWVtZXJpa3NhIHN0cnVrdHVyIGRhdGEgbWVuZ2d1bmFrYW4gYGdsaW1wc2UoKWAuIFBlbWVyaWtzYWFuIGluaSBiZXJ0dWp1YW4gdW50dWsgbWVtYXN0aWthbiBrb25zaXN0ZW5zaSB2YXJpYWJlbCwga2h1c3VzbnlhIGtvbG9tIHdha3R1IChgdGltZWApLCBwZW51bGlzIHBlc2FuIChgYXV0aG9yYCksIGRhbiBpc2kgcGVzYW4gKGB0ZXh0YCkuDQoNCkFuYWxpc2lzIHBlcmNha2FwYW4gV2hhdHNBcHAgZGlsYWt1a2FuIG1lbmdndW5ha2FuIHBlbmRla2F0YW4gX3RleHQgbWluaW5nXywgeWFpdHUgc2VyYW5na2FpYW4gdGVrbmlrIHVudHVrIG1lbmdla3N0cmFrc2kgaW5mb3JtYXNpIGJlcm1ha25hIGRhcmkgZGF0YSB0ZWtzIHRpZGFrIHRlcnN0cnVrdHVyLiBQZW5kZWthdGFuIGluaSBtZW5jYWt1cCB0YWhhcGFuIHBlbWJlcnNpaGFuIHRla3MsIHRva2VuaXNhc2ksIHBlbWJvYm90YW4ga2F0YSwgc2VydGEgYW5hbGlzaXMgZnJla3VlbnNpIGRhbiBrZW1pcmlwYW4gdGVrcyB1bnR1ayBtZW5naWRlbnRpZmlrYXNpIHBvbGEga29tdW5pa2FzaSB5YW5nIHRlcnNlbWJ1bnlpIGRhbGFtIGRhdGEgcGVyY2FrYXBhbiAoRmVsZG1hbiAmIFNhbmdlciwgMjAwNzsgTWFubmluZyBldCBhbC4sIDIwMDgpLg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmhpc3RvcnkgPC0gcndhX3JlYWQoIldoYXRzQXBwIENoYXQgd2l0aCBOZ29icm9saW4gUm9lbXBpYW4yMDI1LnR4dCIpICU+JQ0KICBmaWx0ZXIoYXMuRGF0ZSh0aW1lKSA+PSBhcy5EYXRlKCIyMDI1LTAxLTAxIikpDQpoZWFkKGhpc3RvcnkpDQpgYGANCg0KKipQZW1iZXJzaWhhbiBEYXRhIChEYXRhIENsZWFuaW5nKSoqDQoNClNhbGFoIHNhdHUgaXN1IHlhbmcgZGl0ZW11a2FuIGFkYWxhaCBhZGFueWEgcGVzYW4gdGFucGEgaWRlbnRpdGFzIHBlbmdpcmltIChuaWxhaSBOQSBwYWRhIGtvbG9tIGF1dGhvcikuIFBlc2FuLXBlc2FuIHRlcnNlYnV0IHVtdW1ueWEgbWVydXBha2FuIG5vdGlmaWthc2kgc2lzdGVtIGF0YXUgcGVzYW4gbm9uLWluZGl2aWR1YWwsIHNlaGluZ2dhIGRpa2VsdWFya2FuIGRhcmkgYW5hbGlzaXMuIFNldGVsYWggcHJvc2VzIHBlbWJlcnNpaGFuIGluaSwgZGF0YXNldCBoYW55YSBiZXJpc2kgcGVzYW4geWFuZyBtZW1pbGlraSBwZW5naXJpbSB5YW5nIGplbGFzLg0KDQpMYW5na2FoIGluaSBwZW50aW5nIHVudHVrIG1lbmphbWluIGJhaHdhIGFuYWxpc2lzIGZyZWt1ZW5zaSwgcGFydGlzaXBhc2ksIGRhbiBzZW50aW1lbiBiZW5hci1iZW5hciBtZW5jZXJtaW5rYW4gcGVyaWxha3Uga29tdW5pa2FzaSBhbnRhcmFuZ2dvdGEgZ3J1cC4NCg0KYGBge3J9DQpnbGltcHNlKGhpc3RvcnkpDQoNCiMgQ2VrIEp1bWxhaCBOQSBwYWRhIEtvbG9tIEF1dGhvcg0KaGlzdG9yeSAlPiUgc3VtbWFyaXNlKG5hX2F1dGhvciA9IHN1bShpcy5uYShhdXRob3IpKSkNCg0KIyBUYW1waWxrYW4gQmFyaXMgZGVuZ2FuIEF1dGhvciBOQQ0KaGlzdG9yeSAlPiUgZmlsdGVyKGlzLm5hKGF1dGhvcikpICU+JSBoZWFkKDEwKQ0KDQojIEhhcHVzIEJhcmlzIHlhbmcgVGlkYWsgTWVtaWxpa2kgQXV0aG9yDQpoaXN0b3J5IDwtIGhpc3RvcnkgJT4lIGRyb3BfbmEoYXV0aG9yKQ0KYGBgDQoNCiMgVG90YWwgQ2hhdA0KDQpBbmFsaXNpcyBkZXNrcmlwdGlmIGF3YWwgZGlsYWt1a2FuIGRlbmdhbiBtZW5naGl0dW5nIHRvdGFsIGp1bWxhaCBwZXNhbiB5YW5nIHRlcmtpcmltIHNlbGFtYSBwZXJpb2RlIHBlbmdhbWF0YW4uIFNlbGFuanV0bnlhLCBkaWxha3VrYW4gcGVuZ2hpdHVuZ2FuIGp1bWxhaCBwZXNhbiBiZXJkYXNhcmthbiBwZW5naXJpbSAoYXV0aG9yKSB1bnR1ayBtZW5naWRlbnRpZmlrYXNpIGFuZ2dvdGEgZ3J1cCB5YW5nIHBhbGluZyBha3RpZi4NCg0KYGBge3J9DQpoaXN0b3J5ICU+JQ0KICBzdW1tYXJpc2UodG90YWxfY2hhdCA9IG4oKSkNCmBgYA0KDQpIYXNpbG55YSBkaXZpc3VhbGlzYXNpa2FuIGRhbGFtIGJlbnR1ayBkaWFncmFtIGJhdGFuZyBob3Jpem9udGFsLiBWaXN1YWxpc2FzaSBpbmkgbWVtYmVyaWthbiBnYW1iYXJhbiB5YW5nIGplbGFzIG1lbmdlbmFpIGRpc3RyaWJ1c2kga29udHJpYnVzaSBwZXNhbiBhbnRhcmFuZ2dvdGEsIHNla2FsaWd1cyBtZW1iYW50dSBtZW5naWRlbnRpZmlrYXNpIHBvbGEgZG9taW5hc2kga29tdW5pa2FzaSBkYWxhbSBncnVwLg0KDQpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9DQpoaXN0b3J5ICU+JQ0KICBjb3VudChhdXRob3IsIHNvcnQgPSBUUlVFKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbiwgeSA9IHJlb3JkZXIoYXV0aG9yLCBuKSwgZmlsbCA9IGF1dGhvcikpICsNCiAgZ2VvbV9jb2woYWxwaGEgPSAwLjksIHdpZHRoID0gMC43KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSwgaGp1c3QgPSAtMC4xLCBzaXplID0gMykgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMikpKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCJOYW1hIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDEwLCA0MCwgMTAsIDEwKQ0KICApICsNCiAgZ2d0aXRsZSgiSnVtbGFoIENoYXQgeWFuZyBEaWtpcmltICgxIEphbiDigJMgMzEgRGVzIDIwMjUpIikNCg0KYGBgDQoNCioqVmlzdWFsaXNhc2kgQ2hhdCoqDQoNCg0KVW50dWsgbWVuZ2FuYWxpc2lzIHBvbGEgdGVtcG9yYWwsIGZvcm1hdCB3YWt0dSBkaWtvbnZlcnNpIGtlIGRhbGFtIGJhaGFzYSBJbmRvbmVzaWEgZGVuZ2FuIG1lbmdhdHVyIHNpc3RlbSBsb2thbC4gU2VsYW5qdXRueWEsIGRpYnVhdCB2YXJpYWJlbCBoYXJpIChfZGF5XykgYmVyZGFzYXJrYW4gdGFuZ2dhbCBwZW5naXJpbWFuIHBlc2FuLg0KDQpEaXN0cmlidXNpIGp1bWxhaCBwZXNhbiBwZXIgaGFyaSBkaWFuYWxpc2lzIGRhbiBkaXZpc3VhbGlzYXNpa2FuLCBzZWhpbmdnYSBkYXBhdCBkaWtldGFodWkgaGFyaS1oYXJpIHRlcnRlbnR1IGRlbmdhbiBpbnRlbnNpdGFzIGtvbXVuaWthc2kgeWFuZyBsZWJpaCB0aW5nZ2kuIEFuYWxpc2lzIGluaSBiZXJndW5hIHVudHVrIG1lbWFoYW1pIHJpdG1lIGFrdGl2aXRhcyBncnVwLCBtaXNhbG55YSBhcGFrYWggcGVyY2FrYXBhbiBsZWJpaCBha3RpZiBwYWRhIGhhcmkga2VyamEgYXRhdSBha2hpciBwZWthbi4NCg0KU2VsYWluIGl0dSwgd2FrdHUgcGVzYW4ganVnYSBkaXVyYWlrYW4gbGViaWggZGV0YWlsIG1lbmdndW5ha2FuIGBsdWJyaWRhdGVgIG1lbmphZGkga29tcG9uZW4gdGFodW4sIGJ1bGFuLCB0YW5nZ2FsLCBqYW0sIG1lbml0LCBkYW4gZGV0aWsuIEluZm9ybWFzaSBpbmkgbWVtYnVrYSBwZWx1YW5nIGFuYWxpc2lzIGxhbmp1dGFuIHRlcmthaXQgamFtIHNpYnVrIGtvbXVuaWthc2kgYXRhdSB0cmVuIG11c2ltYW4uDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KIyBNZW5nYXR1ciBGb3JtYXQgSGFyaSBkYWxhbSBCYWhhc2EgSW5kb25lc2lhDQpTeXMuc2V0bG9jYWxlKCJMQ19USU1FIiwgImlkX0lELnV0ZjgiKQ0KDQojIE1lbmFtYmFoa2FuIEtvbG9tIEhhcmkNCmhpc3RvcnkgPC0gaGlzdG9yeSAlPiUNCiAgbXV0YXRlKGRheSA9IHdlZWtkYXlzKGFzLkRhdGUodGltZSkpKQ0KDQojIEtvbnZlcnNpIEZha3RvciBIYXJpDQpoYXJpIDwtIGMoIlNlbmluIiwgIlNlbGFzYSIsICJSYWJ1IiwgIkthbWlzIiwgIkp1bWF0IiwgIlNhYnR1IiwgIk1pbmdndSIpDQpoaXN0b3J5JGRheSA8LSBmYWN0b3IoaGlzdG9yeSRkYXksIGxldmVscyA9IGhhcmkpDQpgYGANCg0KYGBge3J9DQpoaXN0b3J5ICU+JQ0KICBjb3VudChkYXkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBuLCB5ID0gcmVvcmRlcihkYXksIG4pLCBmaWxsID0gZGF5KSkgKyANCiAgZ2VvbV9jb2woKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSwgaGp1c3QgPSAtMC4xLCBzaXplID0gMy41KSArDQogIHNjYWxlX3hfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4yKSkpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIg0KICApICsNCiAgbGFicygNCiAgICB5ID0gIkhhcmkiLA0KICAgIHggPSAiSnVtbGFoIENoYXQiLA0KICAgIHRpdGxlID0gIkp1bWxhaCBDaGF0IHBlciBIYXJpIg0KICApDQpgYGANCg0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KI0Vrc3RyYWtzaSBUYW5nZ2FsIGRhbiBXYWt0dQ0KaGlzdG9yeSA8LSBoaXN0b3J5ICU+JQ0KICBtdXRhdGUoDQogICAgdGltZSA9IHltZF9obXModGltZSksDQogICAgdGFodW4gPSB5ZWFyKHRpbWUpLA0KICAgIGJ1bGFuID0gbW9udGgodGltZSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpLA0KICAgIHRhbmdnYWwgPSBkYXkodGltZSksDQogICAgamFtID0gaG91cih0aW1lKSwNCiAgICBtZW5pdCA9IG1pbnV0ZSh0aW1lKSwNCiAgICBkZXRpayA9IHNlY29uZCh0aW1lKQ0KICApDQpgYGANCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCBlY2hvPUZBTFNFfQ0KbGlicmFyeShEVCkNCkRUOjpkYXRhdGFibGUoaGlzdG9yeSkNCmBgYA0KDQojIFdvcmRjbG91ZA0KDQpVbnR1ayBtZW1haGFtaSB0b3BpayBkYW4ga29zYWthdGEgeWFuZyBkb21pbmFuIGRhbGFtIHBlcmNha2FwYW4gZ3J1cCwgZGlsYWt1a2FuIGFuYWxpc2lzIHRla3MgbWVuZ2d1bmFrYW4gcGVuZGVrYXRhbiBfYmFnLW9mLXdvcmRzXy4gUGVuZGVrYXRhbiBpbmkgbWVyZXByZXNlbnRhc2lrYW4gZG9rdW1lbiBzZWJhZ2FpIGt1bXB1bGFuIGthdGEgdGFucGEgbWVtcGVyaGF0aWthbiB1cnV0YW4sIHNlaGluZ2dhIG1lbXVuZ2tpbmthbiBhbmFsaXNpcyBmcmVrdWVuc2kga2VtdW5jdWxhbiBrYXRhIHNlY2FyYSBzaXN0ZW1hdGlzIChNYW5uaW5nIGV0IGFsLiwgMjAwOCkuDQoNClBlc2FuIHlhbmcgYmVydXBhIF9wbGFjZWhvbGRlcl8gbWVkaWEgZGlrZWx1YXJrYW4gZGFyaSBhbmFsaXNpcywga2VtdWRpYW4gZGlsYWt1a2FuIHRva2VuaXNhc2kgdW50dWsgbWVtZWNhaCB0ZWtzIG1lbmphZGkga2F0YSB0dW5nZ2FsLiBBbmdrYSwga2F0YSBzYW5nYXQgcGVuZGVrLCBzZXJ0YSBfc3RvcHdvcmRzXyBCYWhhc2EgSW5kb25lc2lhIGRpaGFwdXMgZ3VuYSBtZW5pbmdrYXRrYW4ga3VhbGl0YXMgcmVwcmVzZW50YXNpIHRla3MuIEthdGEta2F0YSB5YW5nIHRlcnNpc2EgZGloaXR1bmcgZnJla3VlbnNpbnlhIGRhbiBkaXZpc3VhbGlzYXNpa2FuIGRhbGFtIGJlbnR1ayB3b3JkY2xvdWQsIHlhbmcgbWVuY2VybWlua2FuIGthdGEta2F0YSBkb21pbmFuIGRhbGFtIHBlcmNha2FwYW4gZ3J1cCAoU2lsZ2UgJiBSb2JpbnNvbiwgMjAxNykuDQoNCmBgYHtyfQ0Kc3RvcHdvcmRzIDwtIHJlYWQuY3N2KCJzdG9wd29yZGJhaGFzYS5jc3YiKQ0KY29sbmFtZXMoc3RvcHdvcmRzKSA8LSBjKCJzdG9wd29yZCIpDQpgYGANCg0KS2F0YSB5YW5nIHBhbGluZyBzZXJpbmcgZGlndW5ha2FuICh0YW5wYSBTdG9wd29yZHMpDQoNCmBgYHtyfQ0KaGlzdG9yeSAlPiUNCiAgZmlsdGVyKHRleHQgIT0gIjxNZWRpYSB0aWRhayBkaXNlcnRha2FuPiIpICU+JQ0KICB1bm5lc3RfdG9rZW5zKGthdGEsIHRleHQpICU+JQ0KICBmaWx0ZXIoDQogICAgIXN0cl9kZXRlY3Qoa2F0YSwgIlxcZCIpLCAgICAgICAgIyBidWFuZyBhbmdrYQ0KICAgIG5jaGFyKGthdGEpID4gMiAgICAgICAgICAgICAgICAgICMgYnVhbmcga2F0YSA8PSAyIGh1cnVmDQogICkgJT4lDQogIGFudGlfam9pbihzdG9wd29yZHMsIGJ5ID0gYygia2F0YSIgPSAic3RvcHdvcmQiKSkgJT4lDQogIGNvdW50KGthdGEsIHNvcnQgPSBUUlVFKSAlPiUNCiAgd29yZGNsb3VkMigpDQpgYGANCg0KIyBGcmVrdWVuc2kgRnJhc2UgVGVydGVudHUNCg0KU2VsYWluIGFuYWxpc2lzIGthdGEgdHVuZ2dhbCwgZGlsYWt1a2FuIHB1bGEgYW5hbGlzaXMgZnJhc2EgdGVydGVudHUgeWFuZyBzZWNhcmEgc3Vic3RhbnRpZiBtZW5jZXJtaW5rYW4gZGluYW1pa2Ega29tdW5pa2FzaSwgc2VwZXJ0aSBla3NwcmVzaSBwZXJzZXR1anVhbiwgcGVybWludGFhbiwgYXRhdSBrZXNvcGFuYW4uDQoNClNlYmVsdW0gcGVuZ2hpdHVuZ2FuLCBkaWxha3VrYW4gbm9ybWFsaXNhc2kgdGVrcyB1bnR1ayBtZW55YW1ha2FuIHZhcmlhc2kgcGVudWxpc2FuIGRlbmdhbiBtYWtuYSB5YW5nIHNhbWEgKG1pc2FsbnlhIOKAnG9r4oCdLCDigJxva2XigJ0sIOKAnG9rYXnigJ0pLiBTZXRlbGFoIGl0dSwgZnJla3VlbnNpIGtlbXVuY3VsYW4gZnJhc2EtZnJhc2EgdGVydGVudHUgZGloaXR1bmcgbWVuZ2d1bmFrYW4gcGVuY29jb2thbiBiZXJiYXNpcyBwb2xhIGthdGEgKF9yZWd1bGFyIGV4cHJlc3Npb25fKS4gUGVuZGVrYXRhbiBpbmkgbWVtdW5na2lua2FuIGFuYWxpc2lzIHlhbmcgbGViaWggc2VtYW50aWsgZGliYW5kaW5nIHNla2FkYXIgZnJla3VlbnNpIGthdGEuDQoNCk5vcm1hbGlzYXNpIHRla3MgZGlsYWt1a2FuIHVudHVrIG1lbnlhbWFrYW4gdmFyaWFzaSBwZW51bGlzYW4ga2F0YSBhdGF1IGZyYXNhIHlhbmcgbWVtaWxpa2kgbWFrbmEgc2VydXBhLCBzZWhpbmdnYSBhbmFsaXNpcyB0aWRhayB0ZXJkaXN0b3JzaSBvbGVoIHBlcmJlZGFhbiBlamFhbiBhdGF1IGdheWEgYmFoYXNhLiBQZW5kZWthdGFuIGluaSBwZW50aW5nIGRhbGFtIF90ZXh0IG1pbmluZ18ga2FyZW5hIHZhcmlhc2kgbGluZ3Vpc3RpayB5YW5nIHRpbmdnaSBwYWRhIGRhdGEgcGVyY2FrYXBhbiBpbmZvcm1hbCBkYXBhdCBtZW1lbmdhcnVoaSBoYXNpbCBhbmFsaXNpcyBmcmVrdWVuc2kgZGFuIGludGVycHJldGFzaSBtYWtuYSAoRmVsZG1hbiAmIFNhbmdlciwgMjAwNykuDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KHB1cnJyKQ0KbGlicmFyeSh0aWJibGUpDQoNCiMgTm9ybWFsaXNhc2kgdGVrcyAobWFrbmEgZGlzYW1ha2FuKQ0Kbm9ybWFsaXplX3RleHQgPC0gZnVuY3Rpb24odGV4dCkgew0KICB0ZXh0ICU+JQ0KICAgIHN0cl90b19sb3dlcigpICU+JQ0KICAgIHN0cl9yZXBsYWNlX2FsbCgiXFxiKG9rZXxva2F5fG9rZXl8b2spXGIiLCAib2siKSAlPiUNCiAgICBzdHJfcmVwbGFjZV9hbGwoIlxcYihtYWthc2lofG1ha2FzaXx0aGFua3N8dGh4KVxiIiwgInRlcmltYSBrYXNpaCIpICU+JQ0KICAgIHN0cl9yZXBsYWNlX2FsbCgiXFxiKHNpYXB8c2lhcCBQYWt8c2lhcCwgUGFrfHNpYXAgcGFrKVxiIiwgInNpYXAgcGFrIikgJT4lDQogICAgc3RyX3JlcGxhY2VfYWxsKCJcXHMrIiwgIiAiKSAlPiUNCiAgICBzdHJfdHJpbSgpDQp9DQoNCiMgSGl0dW5nIGZyZWt1ZW5zaSBmcmFzYQ0KY291bnRfcGhyYXNlcyA8LSBmdW5jdGlvbih0ZXh0LCBwaHJhc2VzKSB7DQogIG1hcF9kZihwaHJhc2VzLCBmdW5jdGlvbihwKSB7DQogICAgdGliYmxlKA0KICAgICAgZnJhc2EgPSBwLA0KICAgICAganVtbGFoID0gc3VtKA0KICAgICAgICBzdHJfZGV0ZWN0KHRleHQsIHBhc3RlMCgiXFxiIiwgcCwgIlxcYiIpKSwNCiAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICApDQogICAgKQ0KICB9KQ0KfQ0KDQojIE5vcm1hbGlzYXNpIHNlbHVydWggY2hhdA0KdGV4dF9ub3JtIDwtIG5vcm1hbGl6ZV90ZXh0KGhpc3RvcnkkdGV4dCkNCg0KIyBEYWZ0YXIgZnJhc2EgeWFuZyBpbmdpbiBkaWhpdHVuZw0KZnJhc2EgPC0gYygNCiAgImJhaWsgcGFrIiwNCiAgInNpYXAgcGFrIiwNCiAgIm5vdGVkIiwNCiAgIm9rIiwNCiAgInRlcmltYSBrYXNpaCIsDQogICJtYWFmIiwNCiAgInRvbG9uZyINCikNCmBgYA0KDQpgYGB7cn0NCmhhc2lsX2ZyYXNhIDwtIGNvdW50X3BocmFzZXModGV4dF9ub3JtLCBmcmFzYSkNCmhhc2lsX2ZyYXNhDQpgYGANCg0KKipGcmVrdWVuc2kgQ2hhdCoqDQoNCkZyZWt1ZW5zaSBwZXNhbiBwZXIgaGFyaSBkaWFuYWxpc2lzIGRhbiBkaXZpc3VhbGlzYXNpa2FuIG1lbmdndW5ha2FuIGhlYXRtYXAga2FsZW5kZXIsIGRpIG1hbmEgd2FybmEgbWVyZXByZXNlbnRhc2lrYW4gdGluZ2thdCBrZXBhZGF0YW4gcGVzYW4uIFZpc3VhbGlzYXNpIGluaSBtZW11ZGFoa2FuIGlkZW50aWZpa2FzaSBoYXJpLWhhcmkgZGVuZ2FuIGFrdGl2aXRhcyBrb211bmlrYXNpIHlhbmcgc2FuZ2F0IHRpbmdnaSBhdGF1IHNhbmdhdCByZW5kYWguDQoNClNlbGFuanV0bnlhLCBkaWxha3VrYW4gYW5hbGlzaXMgaGFyaSB0ZXJhbWFpIHBhZGEgc2V0aWFwIGJ1bGFuLiBEZW5nYW4gbWVuZ2Vsb21wb2trYW4gZGF0YSBiZXJkYXNhcmthbiBidWxhbiBkYW4gaGFyaSwga2VtdWRpYW4gbWVtaWxpaCBoYXJpIGRlbmdhbiBqdW1sYWggcGVzYW4gdGVydGluZ2dpLCBkaXBlcm9sZWggZ2FtYmFyYW4gcG9sYSBha3Rpdml0YXMgZG9taW5hbiBwYWRhIHNldGlhcCBidWxhbi4gSGFzaWxueWEgZGl2aXN1YWxpc2FzaWthbiBrZW1iYWxpIGRhbGFtIGJlbnR1ayBoZWF0bWFwIGR1YSBkaW1lbnNpIChoYXJpIMOXIGJ1bGFuKS4NCg0KYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQ0KYWFhIDwtIGhpc3RvcnkgJT4lDQogIG11dGF0ZSh0YW5nZ2FsID0gYXMuRGF0ZSh0aW1lKSkgJT4lDQogIGNvdW50KHRhbmdnYWwpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB0YW5nZ2FsLCB5ID0gMSwgZmlsbCA9IG4pKSArDQogIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiZ3JlZW4iLCBoaWdoID0gInJlZCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSkgKw0KICBsYWJzKHRpdGxlID0gIkZyZWt1ZW5zaSBQZXNhbiBwZXIgSGFyaSIsIHggPSAiVGFuZ2dhbCIsIHkgPSBOVUxMLCBmaWxsID0gIkp1bWxhaCBQZXNhbiIpDQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCg0KaGFzaWxfaGFyaV90ZXJyYW1haSA8LSBoaXN0b3J5ICU+JQ0KICBtdXRhdGUoDQogICAgYnVsYW4gPSBtb250aCh0aW1lLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSksDQogICAgaGFyaSA9IHdlZWtkYXlzKGFzLkRhdGUodGltZSkpDQogICkgJT4lDQogIGdyb3VwX2J5KGJ1bGFuLCBoYXJpKSAlPiUNCiAgc3VtbWFyaXNlKGp1bWxhaF9jaGF0ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgZ3JvdXBfYnkoYnVsYW4pICU+JQ0KICBzbGljZV9tYXgoanVtbGFoX2NoYXQsIG4gPSAxLCB3aXRoX3RpZXMgPSBGQUxTRSkgJT4lDQogIGFycmFuZ2UoYnVsYW4pDQoNCmhhc2lsX2hhcmlfdGVycmFtYWkNCmBgYA0KDQpUYWJlbCBtZW51bmp1a2thbiBkaXN0cmlidXNpIGp1bWxhaCBjaGF0IHNlbGFtYSBzYXR1IHRhaHVuIHlhbmcgZGlrZWxvbXBva2thbiBiZXJkYXNhcmthbiBidWxhbiBkYW4gaGFyaSBkb21pbmFuIHRlcmphZGlueWEgYWt0aXZpdGFzIGNoYXQgcGFkYSBidWxhbiB0ZXJzZWJ1dC4NCg0KU2VjYXJhIHVtdW0sIGFrdGl2aXRhcyBjaGF0IHRpZGFrIG1lcmF0YSBzZXBhbmphbmcgdGFodW4gZGFuIG1lbnVuanVra2FuIHBvbGEgZmx1a3R1YXRpZiB5YW5nIGN1a3VwIGplbGFzLg0KDQoxLiAgUHVuY2FrIGFrdGl2aXRhcyBjaGF0IHRlcmphZGkgcGFkYSBidWxhbiBNYXJldCBkZW5nYW4gdG90YWwgMjM2IGNoYXQsIHlhbmcgZGlkb21pbmFzaSBwYWRhIGhhcmkgUmFidS4gSGFsIGluaSBtZW5naW5kaWthc2lrYW4gYWRhbnlhIHBlbmluZ2thdGFuIGludGVuc2l0YXMga29tdW5pa2FzaSBwYWRhIHBlcmlvZGUgYXdhbCB0YWh1biwgeWFuZyBrZW11bmdraW5hbiBiZXJrYWl0YW4gZGVuZ2FuIGFrdGl2aXRhcyBrb29yZGluYXNpLCBwZXJlbmNhbmFhbiwgYXRhdSBkaW5hbWlrYSBrZXJqYSBwYXNjYS1hd2FsIHRhaHVuLg0KDQoyLiAgQWt0aXZpdGFzIGNoYXQgcmVsYXRpZiB0aW5nZ2kganVnYSB0ZXJsaWhhdCBwYWRhIEFndXN0dXMgKDE3NSBjaGF0LCBKdW1hdCkgZGFuIFNlcHRlbWJlciAoMTY4IGNoYXQsIFNlbmluKS4gUG9sYSBpbmkgZGFwYXQgbWVuY2VybWlua2FuIG1lbmluZ2thdG55YSBrZWJ1dHVoYW4ga29tdW5pa2FzaSBtZW5qZWxhbmcgYXRhdSBzZXN1ZGFoIHBlcmlvZGUgdGVydGVudHUsIHNlcGVydGkgZXZhbHVhc2kgdGVuZ2FoIHRhaHVuIGF0YXUgcGVueWVzdWFpYW4gcHJvZ3JhbS4NCg0KMy4gIEFrdGl2aXRhcyB0ZXJlbmRhaCB0ZXJjYXRhdCBwYWRhIGJ1bGFuIE1laSBkZW5nYW4gaGFueWEgNDggY2hhdCwgbWVza2lwdW4gbWFzaWggZGlkb21pbmFzaSBoYXJpIFJhYnUuIFJlbmRhaG55YSBpbnRlbnNpdGFzIGluaSBkYXBhdCBtZW5naW5kaWthc2lrYW4gcGVyaW9kZSBha3Rpdml0YXMgeWFuZyBsZWJpaCBzdGFiaWwgYXRhdSBiZXJrdXJhbmdueWEga2VidXR1aGFuIGtvb3JkaW5hc2kuDQoNCjQuICBEYXJpIHNpc2kgaGFyaSwgUmFidSBtdW5jdWwgc2ViYWdhaSBoYXJpIHlhbmcgcGFsaW5nIHNlcmluZyBtZW5qYWRpIGhhcmkgZG9taW5hbiAoTWFyZXQsIEFwcmlsLCBNZWksIEp1bGksIE9rdG9iZXIpLCBtZW51bmp1a2thbiBiYWh3YSBwZXJ0ZW5nYWhhbiBtaW5nZ3UgbWVydXBha2FuIHdha3R1IHlhbmcgcmVsYXRpZiBha3RpZiB1bnR1ayBrb211bmlrYXNpLg0KDQo1LiAgU2VtZW50YXJhIGl0dSwgSnVtYXQgZGFuIFNlbGFzYSBqdWdhIGJlYmVyYXBhIGthbGkgbXVuY3VsIHNlYmFnYWkgaGFyaSBkb21pbmFuLCB0ZXRhcGkgZGVuZ2FuIGZyZWt1ZW5zaSB5YW5nIGxlYmloIHJlbmRhaCwgc2VkYW5na2FuIFNlbmluIGhhbnlhIGRvbWluYW4gcGFkYSBzYXR1IGJ1bGFuLCB5YWl0dSBTZXB0ZW1iZXIuDQoNCg0KDQpgYGB7cn0NCmhpc3RvcnkgJT4lDQogIG11dGF0ZSgNCiAgICBidWxhbiA9IG1vbnRoKHRpbWUsIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFKSwNCiAgICBoYXJpID0gZmFjdG9yKA0KICAgICAgd2Vla2RheXMoYXMuRGF0ZSh0aW1lKSksDQogICAgICBsZXZlbHMgPSBjKCJTZW5pbiIsIlNlbGFzYSIsIlJhYnUiLCJLYW1pcyIsIkp1bWF0IiwiU2FidHUiLCJNaW5nZ3UiKQ0KICAgICkNCiAgKSAlPiUNCiAgY291bnQoYnVsYW4sIGhhcmkpICU+JQ0KICBnZ3Bsb3QoYWVzKGhhcmksIGJ1bGFuLCBmaWxsID0gbikpICsNCiAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYygpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJIYXJpIFRlcmFtYWkgQ2hhdCBwZXIgQnVsYW4iLA0KICAgIHggPSAiSGFyaSIsDQogICAgeSA9ICJCdWxhbiIsDQogICAgZmlsbCA9ICJKdW1sYWggQ2hhdCINCiAgKQ0KYGBgDQoNCg0KIyBTZW50aW1lbiBOZWdhdGlmDQoNCkFuYWxpc2lzIHNlbnRpbWVuIGRpbGFrdWthbiBzZWNhcmEgZWtzcGxvcmF0aWYgZGVuZ2FuIGZva3VzIHBhZGEgaWRlbnRpZmlrYXNpIGluZGlrYXNpIHNlbnRpbWVuIG5lZ2F0aWYgZGFsYW0gcGVyY2FrYXBhbiBncnVwLiBQZW5kZWthdGFuIHlhbmcgZGlndW5ha2FuIGJlcnNpZmF0IF9sZXhpY29uLWJhc2VkXywgeWFpdHUgZGVuZ2FuIG1lbWFuZmFhdGthbiBkYWZ0YXIga2F0YSBuZWdhdGlmIHlhbmcgc2VjYXJhIGtvbnNlcHR1YWwgbWVyZXByZXNlbnRhc2lrYW4ga2V0aWRha3B1YXNhbiwga2VzYWxhaGFuLCBhdGF1IGtlbmRhbGEgZGFsYW0ga29tdW5pa2FzaSAoTGl1LCAyMDEyKS4NCg0KU2V0aWFwIHBlc2FuIGRpYmVyaWthbiBza29yIG5lZ2F0aWYgYmVyZGFzYXJrYW4ganVtbGFoIGtlbXVuY3VsYW4ga2F0YSBuZWdhdGlmLiBQZXNhbiBkZW5nYW4gc2tvciBsZWJpaCBkYXJpIG5vbCBkaWFuZ2dhcCBtZW5nYW5kdW5nIHNlbnRpbWVuIG5lZ2F0aWYgZGFuIGRpYW5hbGlzaXMgbGViaWggbGFuanV0Lg0KDQpVbnR1ayBtZW5naGluZGFyaSBkdXBsaWthc2kgbWFrbmEgYWtpYmF0IHZhcmlhc2kgcmVkYWtzaSBrYWxpbWF0LCBkaXRlcmFwa2FuIHBlbmRla2F0YW4gX1Rlcm0gRnJlcXVlbmN54oCTSW52ZXJzZSBEb2N1bWVudCBGcmVxdWVuY3lfIChURi1JREYpIHNlYmFnYWkgbWV0b2RlIHBlbWJvYm90YW4ga2F0YS4gVEYtSURGIG1lbWJlcmlrYW4gYm9ib3QgbGViaWggdGluZ2dpIHBhZGEga2F0YSB5YW5nIGJlcnNpZmF0IHNwZXNpZmlrIHRlcmhhZGFwIHN1YXR1IHBlc2FuIGRhbiBtZW51cnVua2FuIHBlbmdhcnVoIGthdGEgeWFuZyB1bXVtIG11bmN1bCBkaSBiYW55YWsgcGVzYW4gKFNhbHRvbiAmIEJ1Y2tsZXksIDE5ODgpLg0KDQpTZWxhbmp1dG55YSwgdGluZ2thdCBrZW1pcmlwYW4gYW50YXIgcGVzYW4gZGl1a3VyIG1lbmdndW5ha2FuIF9jb3NpbmUgc2ltaWxhcml0eV8gYmVyYmFzaXMgdmVrdG9yIFRGLUlERi4gUGVuZGVrYXRhbiBpbmkgbWVtdW5na2lua2FuIGlkZW50aWZpa2FzaSBwZXNhbi1wZXNhbiB5YW5nIHNlY2FyYSBzZW1hbnRpayBtZW1pbGlraSBtYWtuYSBzZXJ1cGEgbWVza2lwdW4gYmVyYmVkYSBzZWNhcmEgc3RydWt0dXIga2FsaW1hdCAoU2luZ2hhbCwgMjAwMSkuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXRleHQpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KHdpZHlyKQ0KDQpzZW50aW1lbl9uZWdhdGlmIDwtIGMoDQogICJ0aWRhayIsImJ1a2FuIiwiYmVsdW0iLCJzYWxhaCIsImt1cmFuZyIsDQogICJsYW1iYXQiLCJ0ZWxhdCIsIm1hc2FsYWgiLCJlcnJvciIsImdhZ2FsIiwNCiAgInJpYmV0Iiwic3VzYWgiLCJrZWNld2EiLCJwYXJhaCIsICJwcm90ZXMiDQopDQoNCiMgQ0xFQU5JTkcgVEVLUw0KY2hhdF9jbGVhbiA8LSBoaXN0b3J5ICU+JQ0KICBmaWx0ZXIodGV4dCAhPSAiPE1lZGlhIHRpZGFrIGRpc2VydGFrYW4+IikgJT4lDQogIG11dGF0ZSgNCiAgICB0ZXh0X2NsZWFuID0gdGV4dCAlPiUNCiAgICAgIHN0cl90b19sb3dlcigpICU+JQ0KICAgICAgc3RyX3JlcGxhY2VfYWxsKCJbXmEtelxcc10iLCAiICIpICU+JQ0KICAgICAgc3RyX3NxdWlzaCgpDQogICkNCg0KIyBISVRVTkcgU0tPUiBORUdBVElGDQpzZW50aW1lbl9jaGF0IDwtIGNoYXRfY2xlYW4gJT4lDQogIHVubmVzdF90b2tlbnMoa2F0YSwgdGV4dF9jbGVhbiwgdG9rZW4gPSAid29yZHMiKSAlPiUNCiAgbXV0YXRlKG5lZ2F0aWYgPSBrYXRhICVpbiUgc2VudGltZW5fbmVnYXRpZikgJT4lDQogIGdyb3VwX2J5KHRpbWUsIGF1dGhvciwgdGV4dCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBza29yX25lZ2F0aWYgPSBzdW0obmVnYXRpZiksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApICU+JQ0KICBmaWx0ZXIoc2tvcl9uZWdhdGlmID4gMCkgJT4lDQogIGxlZnRfam9pbigNCiAgICBjaGF0X2NsZWFuICU+JSBzZWxlY3QodGltZSwgdGV4dCwgdGV4dF9jbGVhbiksDQogICAgYnkgPSBjKCJ0aW1lIiwgInRleHQiKQ0KICApDQoNCiMgVE9LRU5JU0FTSQ0KdGZpZGZfZGF0YSA8LSBzZW50aW1lbl9jaGF0ICU+JQ0KICB1bm5lc3RfdG9rZW5zKGthdGEsIHRleHRfY2xlYW4sIHRva2VuID0gIndvcmRzIiwgZHJvcCA9IEZBTFNFKQ0KDQojIFRGLUlERg0KdGZpZGYgPC0gdGZpZGZfZGF0YSAlPiUNCiAgY291bnQodGV4dF9jbGVhbiwga2F0YSkgJT4lDQogIGJpbmRfdGZfaWRmKGthdGEsIHRleHRfY2xlYW4sIG4pDQoNCiMgQ09TSU5FIFNJTUlMQVJJVFkNCnNpbWlsYXJpdHkgPC0gdGZpZGYgJT4lDQogIHBhaXJ3aXNlX3NpbWlsYXJpdHkoDQogICAgaXRlbSA9IHRleHRfY2xlYW4sDQogICAgZmVhdHVyZSA9IGthdGEsDQogICAgdmFsdWUgPSB0Zl9pZGYNCiAgKSAlPiUNCiAgZmlsdGVyKHNpbWlsYXJpdHkgPiAwLjg1KQ0KYGBgDQoNCmBgYHtyfQ0KcGVzYW5fbWFrbmFfdW5payA8LSBzZW50aW1lbl9jaGF0ICU+JQ0KICBmaWx0ZXIoIXRleHRfY2xlYW4gJWluJSBzaW1pbGFyaXR5JGl0ZW0yKSAlPiUNCiAgYXJyYW5nZShkZXNjKHNrb3JfbmVnYXRpZikpDQoNCnBlc2FuX21ha25hX3VuaWsgJT4lDQogIHNlbGVjdCh0aW1lLCBhdXRob3IsIHRleHQsIHNrb3JfbmVnYXRpZikNCmBgYA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZScsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KERUKQ0KRFQ6OmRhdGF0YWJsZSgNCiAgcGVzYW5fbWFrbmFfdW5paywNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgcGFnZUxlbmd0aCA9IDEwLA0KICAgIGF1dG9XaWR0aCA9IFRSVUUNCiAgKQ0KKQ0KYGBgDQoNCiMgUGVudXR1cA0KDQpTZWNhcmEga2VzZWx1cnVoYW4sIGFuYWxpc2lzIGluaSBtZW5nb21iaW5hc2lrYW4gcGVuZGVrYXRhbiBkZXNrcmlwdGlmIGRhbiBfdGV4dCBtaW5pbmdfIHVudHVrIG1lbmdnYW1iYXJrYW4gZGluYW1pa2Ega29tdW5pa2FzaSBkYWxhbSBncnVwIFdoYXRzQXBwLiBNZWxhbHVpIGFuYWxpc2lzIGZyZWt1ZW5zaSwgdmlzdWFsaXNhc2kgdGVtcG9yYWwsIGVrc3Bsb3Jhc2kga29zYWthdGEsIHNlcnRhIHJlZHVrc2kgc2VtYW50aWsgcGVzYW4gbmVnYXRpZiwgcGVuZWxpdGlhbiBpbmkgbWVudW5qdWtrYW4gYmFnYWltYW5hIGRhdGEgcGVyY2FrYXBhbiBkaWdpdGFsIGRhcGF0IGRpbWFuZmFhdGthbiB1bnR1ayBtZW1haGFtaSBwb2xhIGludGVyYWtzaSBzb3NpYWwgc2VjYXJhIGxlYmloIHNpc3RlbWF0aXMuIFBlbmRla2F0YW4gaW5pIHNlamFsYW4gZGVuZ2FuIHByYWt0aWsgYW5hbGlzaXMgdGVrcyBtb2Rlcm4geWFuZyBtZW5la2Fua2FuIGludGVncmFzaSBtZXRvZGUgc3RhdGlzdGlrIGRhbiBsaW5ndWlzdGlrIGRhbGFtIHBlbmdvbGFoYW4gZGF0YSB0aWRhayB0ZXJzdHJ1a3R1ciAoTWFubmluZyBldCBhbC4sIDIwMDg7IFNpbGdlICYgUm9iaW5zb24sIDIwMTcpLg0KDQojIFJlZmVyZW5zaQ0KDQpbMV0gRmVsZG1hbiwgUi4sICYgU2FuZ2VyLCBKLiAoMjAwNykuIF9UaGUgdGV4dCBtaW5pbmcgaGFuZGJvb2s6IEFkdmFuY2VkIGFwcHJvYWNoZXMgaW4gYW5hbHl6aW5nIHVuc3RydWN0dXJlZCBkYXRhXy4gQ2FtYnJpZGdlIFVuaXZlcnNpdHkgUHJlc3MuDQoNClsyXSBMaXUsIEIuICgyMDEyKS4gX1NlbnRpbWVudCBhbmFseXNpcyBhbmQgb3BpbmlvbiBtaW5pbmcuIE1vcmdhbiAmIENsYXlwb29sIFB1Ymxpc2hlcnNfLiBodHRwczovL2RvaS5vcmcvMTAuMjIwMC9TMDA0MTZFRDFWMDFZMjAxMjA0SExUMDE2DQoNClszXSBNYW5uaW5nLCBDLiBELiwgUmFnaGF2YW4sIFAuLCAmIFNjaMO8dHplLCBILiAoMjAwOCkuIF9JbnRyb2R1Y3Rpb24gdG8gaW5mb3JtYXRpb24gcmV0cmlldmFsXy4gQ2FtYnJpZGdlIFVuaXZlcnNpdHkgUHJlc3MuDQoNCls0XSBTYWx0b24sIEcuLCAmIEJ1Y2tsZXksIEMuICgxOTg4KS4gX1Rlcm0td2VpZ2h0aW5nIGFwcHJvYWNoZXMgaW4gYXV0b21hdGljIHRleHQgcmV0cmlldmFsLiBJbmZvcm1hdGlvbiBQcm9jZXNzaW5nICYgTWFuYWdlbWVudF8sIDI0KDUpLCA1MTPigJM1MjMuIGh0dHBzOi8vZG9pLm9yZy8xMC4xMDE2LzAzMDYtNDU3Myg4OCk5MDAyMS0wDQoNCls1XSBTaWxnZSwgSi4sICYgUm9iaW5zb24sIEQuICgyMDE3KS4gX1RleHQgbWluaW5nIHdpdGggUjogQSB0aWR5IGFwcHJvYWNoXy4gT+KAmVJlaWxseSBNZWRpYS4NCg0KWzZdIFNpbmdoYWwsIEEuICgyMDAxKS4gX01vZGVybiBpbmZvcm1hdGlvbiByZXRyaWV2YWw6IEEgYnJpZWYgb3ZlcnZpZXdfLiBJRUVFIERhdGEgRW5naW5lZXJpbmcgQnVsbGV0aW4sIDI0KDQpLCAzNeKAkzQzLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KPiBEaXJla3RvcmF0IFN0YXRpc3RpayBLZXNlamFodGVyYWFuIFJha3lhdCwgQlBTLCBzYXB0YWhhc0BicHMuZ28uaWQNCg0KDQoNCg0K