Achmad Ardani Prasha
Latar Belakang
DQLab Finance merupakan perusahaan finance yang sudah mempunyai
banyak cabang tersebar dimana-mana. Sejak berdiri pada Januari 2020,
DQLab Finance konsisten menyalurkan pembiayaan untuk masyarakat dan
semakin berkembang setiap bulannya dengan membuka cabang baru.
Walaupun berumur kurang dari 1 tahun, DQLab Finance sudah mempunyai
banyak cabang, oleh karena itu perlu dipantau bagaimana performa dari
cabang - cabang tersebut.
Pada masing-masing cabang, terdapat agen-agen yang bertugas mencari
dan mendata calon mitra yang akan mengajukan pinjaman kepada DQLab
Finance. Lalu jika sudah disetujui, agen juga yang akan memberikan uang
tersebut kepada mitra
Tugas dan Langkah
- Menganalisis performa cabang pada bulan Mei 2020.
- Langkah-langkah yang dilakukan adalah:
- Memfilter data untuk bulan Mei 2020
- Membuat summary per cabang untuk melihat data 5 cabang terbaik dan
terburuk
- Karena cabang bertambah setiap bulannya, maka perlu dicek umur
cabang dan performa Mei
- Mencari cabang terburuk untuk masing - masing kelompok umur
Library yang Digunakan
Pada analisis kali ini, akan digunakan beberapa package yang membantu
dalam melakukan analisis data
- Package dplyr, merupakan package yang paling sering digunakan dalam
analisis data, sangat membantu dalam manipulasi data, fungsi yang paling
sering digunakan adalah :
- mutate() membuat variabel baru berdasarkan variabel
yang ada
- select() memilih variabel berdasarkan namanya
- filter() memfilter data berdasarkan value dari
variabel
- summarise() mengubah beberapa nilai menjadi satu
ringkasan nilai
- arrange() mengurutkan baris data
- Package ggplot2, merupakan package yang digunakan untuk membuat plot
dengan syntax yang konsisten, secara umum, untuk membuat plot dengan
memanggil fungsi
ggplot(data) + geom_type(aes(x,y,fill,color))
geom_type diganti dengan fungsi sesuai dengan jenis plot yang
diharapkan, misalnya geom_line, geom_bar, geom_point, geom_boxplot, dan
lainnya. 3. Packages scales, digunakan untuk memformat value data
numerik menjadi format yang mudah dibaca, tidak terlalu sering
digunakan, tapi membantu ketika eksplorasi data. fungsi yang biasa
dipakai adalah - comma() mengubah numerik menjadi ada
simbol ribuan, misalnya 10000000000 diubah
menjadi 10,000,000,000 - percent()
mengubah numerik menjadi ada format persen,
misalnya 0.65877 diubah
menjadi 66%
Data yang Digunakan
Untuk Dataset yang digunakan sudah disediakan dalam format rds
sehingga bisa langsung dibaca di R dengan cara :
df_loan <- read.csv('https://storage.googleapis.com/dqlab-dataset/loan_disbursement.csv', stringsAsFactors = F)
stringsAsFactors ini berguna agar data-data yang
bertipe character (seperti nama cabang, agen dan tanggal) tidak diubah
menjadi factor.
untuk melihat datanya, gunakan fungsi glimpse dari
package dplyr. karena hanya pakai 1 fungsi, kita bisa
memanggilnya tanpa load package nya, yakni dengan menggunakan
symbol :: dan
format package::fungsi()
dplyr::glimpse(df_loan)
Rows: 9,754
Columns: 5
$ loan_id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 2~
$ tanggal_cair <chr> "2020-01-06", "2020-01-06", "2020-01-06", "2020-01-06", "2020-01-06", "2020-~
$ cabang <chr> "AA", "AA", "AA", "AA", "AA", "AA", "AB", "AB", "AB", "AB", "AB", "AB", "AC"~
$ agen <chr> "AA-1", "AA-1", "AA-1", "AA-2", "AA-2", "AA-2", "AB-1", "AB-1", "AB-1", "AB-~
$ amount <int> 320000, 440000, 200000, 430000, 360000, 220000, 320000, 470000, 470000, 3500~
Terlihat bahwa ada 9,754 baris data (Observations) dan ada 5 kolom
(Variables), loan_id: unik ID dari data ini
tanggal_cair: tanggal uang diberikan kepada mitra
cabang: lokasi agen bekerja dan tempat mitra terdaftar
agen: petugas lapangan yang melakukan pencairan
amount: jumlah uang yang dicairkan
Memfilter Data Bulan Mei 2020 dan Jumlahkan Data Per Cabang
Untuk melihat data bulan Mei 2020, gunakan fungsi filter untuk
memfilter data df_loan untuk tanggal dari awal Mei ‘2020-05-01’ sampai
dengan akhir Mei ‘2020-05-31’. Lalu hitung total_amount untuk
masing-masing cabang menggunakan group_by dan summarise kemudian
disimpan hasilnya menjadi df_loan_mei.
Load package dplyr dengan cara,
library(dplyr)
Lalu gunakan pipe %>% untuk menyambungkan fungsi dan jalankan
df_loan_mei untuk menampilkan data,
df_loan_mei <- df_loan %>%
filter(tanggal_cair >= '2020-05-01', tanggal_cair <= '2020-05-31') %>%
group_by(cabang) %>%
summarise(total_amount = sum(amount))
df_loan_mei
Tampilkan Data 5 Cabang dengan Total Amount Paling Besar
Tampilkan 5 cabang terbesar dari data df_loan_mei,
urutkan dengan fungsi arrange,
pakai desc untuk mengurutkan dari yang paling besar.
Tampilkan 5 data teratas menggunakan
fungsi head.
Gunakan fungsi comma dari
package scales untuk
menampilkan total_amount agar lebih mudah
dibandingkan.
Sebelumnya load package scales dengan cara,
library(scales)
Gunakan pipe %>% untuk menyambungkan fungsi.
df_loan_mei %>% arrange(desc(total_amount)) %>%
mutate(total_amount = comma(total_amount)) %>%
head(5)
Tampilkan Data 5 Cabang dengan Total Amount Paling Kecil
Tampilkan 5 cabang terkecil dari data df_loan_mei,urutkan dengan
fungsi arrange dari total_amount yang paling kecil tampilkan 5 data
teratas menggunakan fungsi head.
Gunakan fungsi comma dari package scales untuk
menampilkan total_amount agar lebih mudah dibandingkan.
df_loan_mei %>% arrange(total_amount) %>%
mutate(total_amount = comma(total_amount)) %>%
head(5)
Kesimpulan
Terjadi perbedaan yang sangat signifikan antara top 5 dengan bottom
5. Hal ini mungkin karena umur cabang yang berbeda beda karena ada
pertumbuhan cabang baru setiap bulannya.
Selanjutnya perlu dicek apakah ada perbedaan total amount untuk umur
cabang yang berbeda - beda.
Menghitung Umur Cabang dalam Bulan
Karena tidak tersedia data umur cabang, maka perlu dihitung terlebih
dahulu, yakni dengan menghitung sudah berapa lama sejak tanggal cair
pertama sampai dengan bulan Mei.
Gunakan data df_loan yang berisi semua tanggal_cair dari awal lalu
cari tanggal_cair pertama kali per cabang dan simpan
sebagai pertama_cair.
Kemudian hitung umur dengan rumus
umur = as.numeric(as.Date('2020-05-15') - as.Date(pertama_cair)) %/% 30
Untuk memudahkan cara perhitungan umur dengan membagi jumlah selisih
hari dengan 30, karena itu tanggal batas nya menggunakan tanggal tengah
bulan (2020-05-15), agar tidak terlalu mempengaruhi presisi
perhitungan.
Lalu simpan sebagai df_cabang_umur.
Terakhir tampilkan data df_cabang_umur
Gunakan pipe %>% untuk menyambungkan fungsi.
df_cabang_umur <- df_loan %>% group_by(cabang) %>%
summarise(pertama_cair = min(tanggal_cair)) %>%
mutate(umur = as.numeric(as.Date('2020-05-15') - as.Date(pertama_cair)) %/% 30)
df_cabang_umur
Kesimpulan
Terlihat bahwa ada pola semakin tua cabang, maka performanya semakin
baik. Hal ini karena cabang tersebut masih berkembang sehingga belum
sampai pada performa maksimal.
Akan tetapi pada masing - masing umur itu juga ada cabang yang
performanya dibawah yang lain.
Selanjutnya akan dianalisis cabang yang performanya lebih rendah dari
yang lain pada umur yang sama
Mencari Cabang yang Performa Rendah untuk Setiap Umur
Selanjutnya Untuk mencari cabang yang performanya rendah pada setiap
kelompok umur, akan digunakan nilai Quartile dan Inter Quartile
Range (Jangkauan Interkuartil) dari setiap umur. Dalam statistika
jangkauan interkuartil (IQR), adalah selisih antara persentil ke-75
(kuartil atas) dan persentil ke-25 (kuartil bawah). Dengan kata
lain, IQR adalah kuartil ketiga dikurangi kuartil pertama.
Dikatakan rendah jika performanya kurang dari (Q1 - IQR). Untuk itu
perlu dicari dulu nilai Q1, Q3 dan IQR untuk setiap umur dengan
menggunakan data df_loan_mei_umur. Untuk membuat variabel ini,
gunakan group_by dan mutate karena variabel ini akan digunakan lagi oleh
semua data.
Setelah itu buat variabel baru flag yang akan berisi ‘rendah’ jika
performanya kurang dari (Q1 - IQR) dan ‘baik’ untuk selain itu dan
simpan hasilnya sebagai df_loan_mei_flag.
Lalu filter df_loan_mei_flag hanya untuk flag rendah, agar terlihat
cabang mana saja yang masuk kelompok ini, dan ubah kolom numeric
menjadi comma dengan fungsi mutate_if.
Gunakan pipe %>% untuk menyambungkan fungsi.
library(dplyr)
library(scales)
df_loan_mei_flag <- df_loan_mei_umur %>%
group_by(umur) %>%
mutate(Q1 = quantile(total_amount, 0.25),
Q3 = quantile(total_amount, 0.75),
IQR = (Q3-Q1)) %>%
mutate(flag = ifelse(total_amount < (Q1 - IQR), 'rendah','baik'))
df_loan_mei_flag %>%
filter(flag == 'rendah') %>%
mutate_if(is.numeric, funs(comma))
`mutate_if()` ignored the following grouping variables:Warning: `funs()` was deprecated in dplyr 0.8.0.
Please use a list of either functions or lambdas:
# Simple named list:
list(mean = mean, median = median)
# Auto named with `tibble::lst()`:
tibble::lst(mean, median)
# Using lambdas
list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
Buat Scatterplot dan beri warna merah pada cabang yang rendah
Untuk memperjelas bagaimana performa cabang yang rendah ini, plot
lagi seperti sebelumnya. Sekarang menggunakan data yang baru, yakni
df_loan_mei_flag. Lalu beri warna biru untuk cabang dengan flag ‘baik’
dan merah untuk yang ‘rendah’.
Sehingga hasilnya akan menjadi seperti ini:
ggplot(df_loan_mei_flag, aes(x = umur, y = total_amount)) +
geom_point(aes(color = flag)) +
scale_color_manual(breaks = c("baik", "rendah"),
values = c("blue", "red")) +
scale_y_continuous(labels = scales::comma) +
labs(title = "Ada cabang berpeforma rendah padahal tidak termasuk bottom 5 nasional",
color = "",
x = "Umur (bulan)",
y = "Total Amount")

Kesimpulan
Berdasarkan analisis tersebut, dapat disimpulkan bahwa rendahnya
performa dari cabang AE adalah karena salah satu agen yang melakukan
pencairan hanya 4 hari dalam 1 bulan, padahal agen lain bisa aktif 21
hari.
Hal ini membuat total amount dari agen tersebut hanya 20%
dibandingkan agen yang lainnya.
Sedangkan pada cabang AH, performanya sangat baik karena ketiga agen
melakukan pencairan hampir / selalu setiap hari kerja. 2 orang full 21
hari 1 orang 19 hari. Sehingga performa nya terjaga dengan baik.
Perlu diperhatikan juga bahwa untuk membandingkan performa cabang itu
sebaiknya di kelompokkan dulu berdasarkan karakteristik yang sama. Tidak
langsung semua cabang dibandingkan tanpa mengetahui
karakteristiknya.
Apalagi ketika dalam real world nanti cabang ini bisa terletak di
berbeda wilayah (pulau misalnya) yang mempunyai kultur yang berbeda
Selanjutnya perlu dianalisis lebih lanjut kenapa ada agen yang hanya
aktif beberapa hari saja dalam sebulan.
Untuk kedepannya setiap agen agar dipastikan untuk bisa aktif setiap
hari nya, sehingga bisa menjaga performa cabang.
LS0tDQp0aXRsZTogIkRhdGEgQW5hbHlzaXMgZm9yIEZpbmFuY2Ugd2l0aCBSOiBQZXJmb3JtYSBDYWJhbmciDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KQWNobWFkIEFyZGFuaSBQcmFzaGENCg0KIyMgTGF0YXIgQmVsYWthbmcNCkRRTGFiIEZpbmFuY2UgbWVydXBha2FuIHBlcnVzYWhhYW4gZmluYW5jZSB5YW5nIHN1ZGFoIG1lbXB1bnlhaSBiYW55YWsgY2FiYW5nIHRlcnNlYmFyIGRpbWFuYS1tYW5hLiBTZWphayBiZXJkaXJpIHBhZGEgSmFudWFyaSAyMDIwLCBEUUxhYiBGaW5hbmNlIGtvbnNpc3RlbiBtZW55YWx1cmthbiBwZW1iaWF5YWFuIHVudHVrIG1hc3lhcmFrYXQgZGFuIHNlbWFraW4gYmVya2VtYmFuZyBzZXRpYXAgYnVsYW5ueWEgZGVuZ2FuIG1lbWJ1a2EgY2FiYW5nIGJhcnUuDQoNCldhbGF1cHVuIGJlcnVtdXIga3VyYW5nIGRhcmkgMSB0YWh1biwgRFFMYWIgRmluYW5jZSBzdWRhaCBtZW1wdW55YWkgYmFueWFrIGNhYmFuZywgb2xlaCBrYXJlbmEgaXR1IHBlcmx1IGRpcGFudGF1IGJhZ2FpbWFuYSBwZXJmb3JtYSBkYXJpIGNhYmFuZyAtIGNhYmFuZyB0ZXJzZWJ1dC4NCg0KUGFkYSBtYXNpbmctbWFzaW5nIGNhYmFuZywgdGVyZGFwYXQgYWdlbi1hZ2VuIHlhbmcgYmVydHVnYXMgbWVuY2FyaSBkYW4gbWVuZGF0YSBjYWxvbiBtaXRyYSB5YW5nIGFrYW4gbWVuZ2FqdWthbiBwaW5qYW1hbiBrZXBhZGEgRFFMYWIgRmluYW5jZS4gTGFsdSBqaWthIHN1ZGFoIGRpc2V0dWp1aSwgYWdlbiBqdWdhIHlhbmcgYWthbiBtZW1iZXJpa2FuIHVhbmcgdGVyc2VidXQga2VwYWRhIG1pdHJhDQoNCiMjIFR1Z2FzIGRhbiBMYW5na2FoDQotIE1lbmdhbmFsaXNpcyBwZXJmb3JtYSBjYWJhbmcgcGFkYSBidWxhbiBNZWkgMjAyMC4NCi0gTGFuZ2thaC1sYW5na2FoIHlhbmcgZGlsYWt1a2FuIGFkYWxhaDoNCiAgICAtIE1lbWZpbHRlciBkYXRhIHVudHVrIGJ1bGFuIE1laSAyMDIwDQogICAgLSBNZW1idWF0IHN1bW1hcnkgcGVyIGNhYmFuZyB1bnR1ayBtZWxpaGF0IGRhdGEgNSBjYWJhbmcgdGVyYmFpayBkYW4gdGVyYnVydWsNCiAgICAtIEthcmVuYSBjYWJhbmcgYmVydGFtYmFoIHNldGlhcCBidWxhbm55YSwgbWFrYSBwZXJsdSBkaWNlayB1bXVyIGNhYmFuZyBkYW4gcGVyZm9ybWEgTWVpDQogICAgLSBNZW5jYXJpIGNhYmFuZyB0ZXJidXJ1ayB1bnR1ayBtYXNpbmcgLSBtYXNpbmcga2Vsb21wb2sgdW11cg0KICAgIA0KIyMgTGlicmFyeSB5YW5nIERpZ3VuYWthbg0KUGFkYSBhbmFsaXNpcyBrYWxpIGluaSwgYWthbiBkaWd1bmFrYW4gYmViZXJhcGEgcGFja2FnZSB5YW5nIG1lbWJhbnR1IGRhbGFtIG1lbGFrdWthbiBhbmFsaXNpcyBkYXRhDQoNCjEuIFBhY2thZ2UgZHBseXIsIG1lcnVwYWthbiBwYWNrYWdlIHlhbmcgcGFsaW5nIHNlcmluZyBkaWd1bmFrYW4gZGFsYW0gYW5hbGlzaXMgZGF0YSwgc2FuZ2F0IG1lbWJhbnR1IGRhbGFtIG1hbmlwdWxhc2kgZGF0YSwgZnVuZ3NpIHlhbmcgcGFsaW5nIHNlcmluZyBkaWd1bmFrYW4gYWRhbGFoIDoNCg0KICAtICoqbXV0YXRlKiooKSBtZW1idWF0IHZhcmlhYmVsIGJhcnUgYmVyZGFzYXJrYW4gdmFyaWFiZWwgeWFuZyBhZGENCiAgLSAqKnNlbGVjdCoqKCkgbWVtaWxpaCB2YXJpYWJlbCBiZXJkYXNhcmthbiBuYW1hbnlhDQogIC0gKipmaWx0ZXIqKigpIG1lbWZpbHRlciBkYXRhIGJlcmRhc2Fya2FuIHZhbHVlIGRhcmkgdmFyaWFiZWwNCiAgLSAqKnN1bW1hcmlzZSoqKCkgbWVuZ3ViYWggYmViZXJhcGEgbmlsYWkgbWVuamFkaSBzYXR1IHJpbmdrYXNhbiBuaWxhaQ0KICAtICoqYXJyYW5nZSoqKCkgbWVuZ3VydXRrYW4gYmFyaXMgZGF0YQ0KMi4gUGFja2FnZSBnZ3Bsb3QyLCBtZXJ1cGFrYW4gcGFja2FnZSB5YW5nIGRpZ3VuYWthbiB1bnR1ayBtZW1idWF0IHBsb3QgZGVuZ2FuIHN5bnRheCB5YW5nIGtvbnNpc3Rlbiwgc2VjYXJhIHVtdW0sIHVudHVrIG1lbWJ1YXQgcGxvdCBkZW5nYW4gbWVtYW5nZ2lsIGZ1bmdzaQ0KYGBge3J9DQpnZ3Bsb3QoZGF0YSkgKyBnZW9tX3R5cGUoYWVzKHgseSxmaWxsLGNvbG9yKSkNCmBgYA0KZ2VvbV90eXBlIGRpZ2FudGkgZGVuZ2FuIGZ1bmdzaSBzZXN1YWkgZGVuZ2FuIGplbmlzIHBsb3QgeWFuZyBkaWhhcmFwa2FuLCBtaXNhbG55YSBnZW9tX2xpbmUsIGdlb21fYmFyLCBnZW9tX3BvaW50LCBnZW9tX2JveHBsb3QsIGRhbiBsYWlubnlhLg0KMy4gUGFja2FnZXMgc2NhbGVzLCBkaWd1bmFrYW4gdW50dWsgbWVtZm9ybWF0IHZhbHVlIGRhdGEgbnVtZXJpayBtZW5qYWRpIGZvcm1hdCB5YW5nIG11ZGFoIGRpYmFjYSwgdGlkYWsgdGVybGFsdSBzZXJpbmcgZGlndW5ha2FuLCB0YXBpIG1lbWJhbnR1IGtldGlrYSBla3NwbG9yYXNpIGRhdGEuIGZ1bmdzaSB5YW5nIGJpYXNhIGRpcGFrYWkgYWRhbGFoDQogICAgLSAqKmNvbW1hKiooKSBtZW5ndWJhaCBudW1lcmlrIG1lbmphZGkgYWRhIHNpbWJvbCByaWJ1YW4sIG1pc2FsbnlhwqAqKjEwMDAwMDAwMDAwKirCoGRpdWJhaCBtZW5qYWRpwqAqKjEwLDAwMCwwMDAsMDAwKioNCiAgICAtICoqcGVyY2VudCoqKCkgbWVuZ3ViYWggbnVtZXJpayBtZW5qYWRpIGFkYSBmb3JtYXQgcGVyc2VuLCBtaXNhbG55YcKgKiowLjY1ODc3KirCoGRpdWJhaCBtZW5qYWRpwqAqKjY2JSoqDQogICAgDQojIyBEYXRhIHlhbmcgRGlndW5ha2FuDQpVbnR1ayBEYXRhc2V0IHlhbmcgZGlndW5ha2FuIHN1ZGFoIGRpc2VkaWFrYW4gZGFsYW0gZm9ybWF0IHJkcyBzZWhpbmdnYSBiaXNhIGxhbmdzdW5nIGRpYmFjYSBkaSBSIGRlbmdhbiBjYXJhIDoNCmBgYHtyfQ0KZGZfbG9hbiA8LSByZWFkLmNzdignaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2RxbGFiLWRhdGFzZXQvbG9hbl9kaXNidXJzZW1lbnQuY3N2Jywgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQpgYGANCioqc3RyaW5nc0FzRmFjdG9ycyoqwqBpbmkgYmVyZ3VuYSBhZ2FyIGRhdGEtZGF0YSB5YW5nIGJlcnRpcGUgY2hhcmFjdGVyIChzZXBlcnRpIG5hbWEgY2FiYW5nLCBhZ2VuIGRhbiB0YW5nZ2FsKSB0aWRhayBkaXViYWggbWVuamFkaSBmYWN0b3IuDQoNCnVudHVrIG1lbGloYXQgZGF0YW55YSwgZ3VuYWthbiBmdW5nc2nCoGBnbGltcHNlYMKgZGFyaSBwYWNrYWdlwqBgZHBseXJgLiBrYXJlbmEgaGFueWEgcGFrYWkgMSBmdW5nc2ksIGtpdGEgYmlzYSBtZW1hbmdnaWxueWEgdGFucGEgbG9hZCBwYWNrYWdlIG55YSwgeWFrbmkgZGVuZ2FuIG1lbmdndW5ha2FuIHN5bWJvbMKgKio6OioqwqBkYW4gZm9ybWF0wqAqKnBhY2thZ2U6OmZ1bmdzaSoqKCkNCmBgYHtyfQ0KZHBseXI6OmdsaW1wc2UoZGZfbG9hbikNCmBgYA0KVGVybGloYXQgYmFod2EgYWRhIDksNzU0IGJhcmlzIGRhdGEgKE9ic2VydmF0aW9ucykgZGFuIGFkYSA1IGtvbG9tIChWYXJpYWJsZXMpLA0KKipsb2FuX2lkKio6IHVuaWsgSUQgZGFyaSBkYXRhIGluaQ0KKip0YW5nZ2FsX2NhaXIqKjogdGFuZ2dhbCB1YW5nIGRpYmVyaWthbiBrZXBhZGEgbWl0cmENCioqY2FiYW5nKio6IGxva2FzaSBhZ2VuIGJla2VyamEgZGFuIHRlbXBhdCBtaXRyYSB0ZXJkYWZ0YXINCioqYWdlbjoqKiBwZXR1Z2FzIGxhcGFuZ2FuIHlhbmcgbWVsYWt1a2FuIHBlbmNhaXJhbg0KKiphbW91bnQqKjoganVtbGFoIHVhbmcgeWFuZyBkaWNhaXJrYW4NCg0KIyMgTWVtZmlsdGVyIERhdGEgQnVsYW4gTWVpIDIwMjAgZGFuIEp1bWxhaGthbiBEYXRhIFBlciBDYWJhbmcNClVudHVrIG1lbGloYXQgZGF0YSBidWxhbiBNZWkgMjAyMCwgZ3VuYWthbiBmdW5nc2kgZmlsdGVyIHVudHVrIG1lbWZpbHRlciBkYXRhIGRmX2xvYW4gdW50dWsgdGFuZ2dhbCBkYXJpIGF3YWwgTWVpIOKAmDIwMjAtMDUtMDHigJkgc2FtcGFpIGRlbmdhbiBha2hpciBNZWkg4oCYMjAyMC0wNS0zMeKAmS4gTGFsdSBoaXR1bmcgdG90YWxfYW1vdW50ICB1bnR1ayBtYXNpbmctbWFzaW5nIGNhYmFuZyBtZW5nZ3VuYWthbiBncm91cF9ieSBkYW4gc3VtbWFyaXNlIGtlbXVkaWFuIGRpc2ltcGFuIGhhc2lsbnlhIG1lbmphZGkgZGZfbG9hbl9tZWkuDQoNCkxvYWQgcGFja2FnZSBkcGx5ciBkZW5nYW4gY2FyYSwNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmBgYA0KTGFsdSBndW5ha2FuIHBpcGXCoCU+JSB1bnR1ayBtZW55YW1idW5na2FuIGZ1bmdzaSBkYW4gamFsYW5rYW4gZGZfbG9hbl9tZWkgdW50dWsgbWVuYW1waWxrYW4gZGF0YSwNCmBgYHtyfQ0KZGZfbG9hbl9tZWkgPC0gZGZfbG9hbiAlPiUNCglmaWx0ZXIodGFuZ2dhbF9jYWlyID49ICcyMDIwLTA1LTAxJywgdGFuZ2dhbF9jYWlyIDw9ICcyMDIwLTA1LTMxJykgJT4lDQoJZ3JvdXBfYnkoY2FiYW5nKSAlPiUNCglzdW1tYXJpc2UodG90YWxfYW1vdW50ID0gc3VtKGFtb3VudCkpDQpkZl9sb2FuX21laQ0KYGBgDQojIyBUYW1waWxrYW4gRGF0YSA1IENhYmFuZyBkZW5nYW4gVG90YWwgQW1vdW50IFBhbGluZyBCZXNhcg0KVGFtcGlsa2FuIDUgY2FiYW5nIHRlcmJlc2FyIGRhcmkgZGF0YcKgKipkZl9sb2FuX21laSoqLCB1cnV0a2FuIGRlbmdhbiBmdW5nc2nCoCoqYXJyYW5nZSoqLCBwYWthacKgKipkZXNjKirCoHVudHVrIG1lbmd1cnV0a2FuIGRhcmkgeWFuZyBwYWxpbmcgYmVzYXIuIFRhbXBpbGthbsKgKio1IGRhdGEgdGVyYXRhcyoqwqBtZW5nZ3VuYWthbiBmdW5nc2nCoCoqaGVhZCoqLg0KDQpHdW5ha2FuIGZ1bmdzacKgKipjb21tYSoqwqBkYXJpIHBhY2thZ2XCoCoqc2NhbGVzKirCoHVudHVrIG1lbmFtcGlsa2FuwqAqKnRvdGFsX2Ftb3VudCoqwqBhZ2FyIGxlYmloIG11ZGFoIGRpYmFuZGluZ2thbi4NCg0KU2ViZWx1bW55YSBsb2FkIHBhY2thZ2XCoCoqc2NhbGVzKirCoGRlbmdhbiBjYXJhLA0KYGBge3J9DQpsaWJyYXJ5KHNjYWxlcykNCmBgYA0KR3VuYWthbiBwaXBlICU+JSB1bnR1ayBtZW55YW1idW5na2FuIGZ1bmdzaS4NCmBgYHtyfQ0KZGZfbG9hbl9tZWkgJT4lIGFycmFuZ2UoZGVzYyh0b3RhbF9hbW91bnQpKSAlPiUNCgltdXRhdGUodG90YWxfYW1vdW50ID0gY29tbWEodG90YWxfYW1vdW50KSkgJT4lDQoJaGVhZCg1KQ0KYGBgDQojIyBUYW1waWxrYW4gRGF0YSA1IENhYmFuZyBkZW5nYW4gVG90YWwgQW1vdW50IFBhbGluZyBLZWNpbA0KVGFtcGlsa2FuIDUgY2FiYW5nIHRlcmtlY2lsIGRhcmkgZGF0YcKgZGZfbG9hbl9tZWksdXJ1dGthbiBkZW5nYW4gZnVuZ3NpwqBhcnJhbmdlwqBkYXJpIHRvdGFsX2Ftb3VudCB5YW5nIHBhbGluZyBrZWNpbCB0YW1waWxrYW4gNSBkYXRhIHRlcmF0YXMgbWVuZ2d1bmFrYW4gZnVuZ3NpwqBoZWFkLg0KDQpHdW5ha2FuIGZ1bmdzacKgY29tbWHCoGRhcmkgcGFja2FnZcKgc2NhbGVzwqB1bnR1ayBtZW5hbXBpbGthbsKgdG90YWxfYW1vdW50wqBhZ2FyIGxlYmloIG11ZGFoIGRpYmFuZGluZ2thbi4NCmBgYHtyfQ0KZGZfbG9hbl9tZWkgJT4lIGFycmFuZ2UodG90YWxfYW1vdW50KSAlPiUNCgltdXRhdGUodG90YWxfYW1vdW50ID0gY29tbWEodG90YWxfYW1vdW50KSkgJT4lDQoJaGVhZCg1KQ0KYGBgDQojIyBLZXNpbXB1bGFuDQpUZXJqYWRpIHBlcmJlZGFhbiB5YW5nIHNhbmdhdCBzaWduaWZpa2FuIGFudGFyYSB0b3AgNSBkZW5nYW4gYm90dG9tIDUuIEhhbCBpbmkgbXVuZ2tpbiBrYXJlbmEgdW11ciBjYWJhbmcgeWFuZyBiZXJiZWRhIGJlZGEga2FyZW5hIGFkYSBwZXJ0dW1idWhhbiBjYWJhbmcgYmFydSBzZXRpYXAgYnVsYW5ueWEuDQoNClNlbGFuanV0bnlhIHBlcmx1IGRpY2VrIGFwYWthaCBhZGEgcGVyYmVkYWFuIHRvdGFsIGFtb3VudCB1bnR1ayB1bXVyIGNhYmFuZyB5YW5nIGJlcmJlZGEgLSBiZWRhLg0KDQojIyBNZW5naGl0dW5nIFVtdXIgQ2FiYW5nIGRhbGFtIEJ1bGFuDQpLYXJlbmEgdGlkYWsgdGVyc2VkaWEgZGF0YSB1bXVyIGNhYmFuZywgbWFrYSBwZXJsdSBkaWhpdHVuZyB0ZXJsZWJpaCBkYWh1bHUsIHlha25pIGRlbmdhbiBtZW5naGl0dW5nIHN1ZGFoIGJlcmFwYSBsYW1hIHNlamFrIHRhbmdnYWwgY2FpciBwZXJ0YW1hIHNhbXBhaSBkZW5nYW4gYnVsYW4gTWVpLg0KDQpHdW5ha2FuIGRhdGHCoGRmX2xvYW4geWFuZyBiZXJpc2kgc2VtdWEgdGFuZ2dhbF9jYWlyIGRhcmkgYXdhbCBsYWx1IGNhcmnCoHRhbmdnYWxfY2FpciBwZXJ0YW1hIGthbGnCoHBlciBjYWJhbmcgZGFuIHNpbXBhbiBzZWJhZ2FpwqBwZXJ0YW1hX2NhaXIuIA0KDQpLZW11ZGlhbiBoaXR1bmcgdW11ciBkZW5nYW4gcnVtdXMNCmBgYHtyfQ0KdW11ciA9IGFzLm51bWVyaWMoYXMuRGF0ZSgnMjAyMC0wNS0xNScpIC0gYXMuRGF0ZShwZXJ0YW1hX2NhaXIpKSAlLyUgMzANCmBgYA0KVW50dWsgbWVtdWRhaGthbiBjYXJhIHBlcmhpdHVuZ2FuIHVtdXIgZGVuZ2FuIG1lbWJhZ2kganVtbGFoIHNlbGlzaWggaGFyaSBkZW5nYW4gMzAsIGthcmVuYSBpdHUgdGFuZ2dhbCBiYXRhcyBueWEgbWVuZ2d1bmFrYW4gdGFuZ2dhbCB0ZW5nYWggYnVsYW4gKDIwMjAtMDUtMTUpLCBhZ2FyIHRpZGFrIHRlcmxhbHUgbWVtcGVuZ2FydWhpIHByZXNpc2kgcGVyaGl0dW5nYW4uDQoNCkxhbHUgc2ltcGFuIHNlYmFnYWnCoGRmX2NhYmFuZ191bXVyLg0KDQpUZXJha2hpciB0YW1waWxrYW4gZGF0YcKgZGZfY2FiYW5nX3VtdXINCg0KR3VuYWthbiBwaXBlwqAlPiXCoHVudHVrIG1lbnlhbWJ1bmdrYW4gZnVuZ3NpLg0KYGBge3J9DQpkZl9jYWJhbmdfdW11ciA8LSBkZl9sb2FuICU+JSBncm91cF9ieShjYWJhbmcpICU+JQ0KCXN1bW1hcmlzZShwZXJ0YW1hX2NhaXIgPSBtaW4odGFuZ2dhbF9jYWlyKSkgJT4lDQoJbXV0YXRlKHVtdXIgPSBhcy5udW1lcmljKGFzLkRhdGUoJzIwMjAtMDUtMTUnKSAtIGFzLkRhdGUocGVydGFtYV9jYWlyKSkgJS8lIDMwKQ0KZGZfY2FiYW5nX3VtdXIgDQpgYGANCiMjIEdhYnVuZ2thbiBEYXRhIFVtdXIgZGFuIFBlcmZvcm1hIE1laQ0KU2VsYW5qdXRueWEgdW50dWsgbWVtYmFuZGluZ2thbiBkYXRhIHVtdXIgZGFuIHBlcmZvcm1hIGRpIGJ1bGFuIG1laSwgdGVybGViaWggZGFodWx1IHBlcmx1IGRpZ2FidW5na2FuIGR1bHUgZGF0YS1kYXRhIHlhbmcgc3VkYWggZGlidWF0IHNlYmVsdW1ueWEgZGVuZ2FuIG1lbmdndW5ha2FuIGZ1bmdzacKgaW5uZXJfam9pbiwgbGFsdSBzaW1wYW4gc2ViYWdhacKgZGZfbG9hbl9tZWlfdW11ci4NCg0KR3VuYWthbiBwaXBlwqAlPiUgdW50dWsgbWVueWFtYnVuZ2thbiBmdW5nc2kuDQpgYGB7cn0NCmRmX2xvYW5fbWVpX3VtdXIgPC0gZGZfY2FiYW5nX3VtdXIgJT4lIGlubmVyX2pvaW4oZGZfbG9hbl9tZWksIGJ5PSJjYWJhbmciKQ0KZGZfbG9hbl9tZWlfdW11cg0KYGBgDQojIyBQbG90IFJlbGFzaSBVbXVyIGRhbiBQZXJmb3JtYSBNZWkNClVudHVrIG1lbWJ1YXQgcGxvdCwgYWthbiBkaWd1bmFrYW4gcGFja2FnZcKgZ2dwbG90MiBhZ2FyIHNjcmlwdCB5YW5nIGRpZ3VuYWthbiBsZWJpaCBrb25zaXN0ZW4ga2V0aWthIG5hbnRpIGFkYSBwZXJ1YmFoYW4gZGFuIHN1cGF5YSBiaXNhIGxlYmloIGJpc2EgZGlrdXN0b21pc2FzaSBuYW50aW55YS4NCg0KR3VuYWthbiBkYXRhwqBkZl9sb2FuX21laV91bXVywqB5YW5nIHN1ZGFoIGRpYnVhdCBzZWJlbHVtbnlhLg0KDQpTZWhpbmdnYSBoYXNpbG55YSBha2FuIG1lbmphZGkgc2VwZXJ0aSBpbmk6DQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmdncGxvdChkZl9sb2FuX21laV91bXVyLCBhZXMoeCA9IHVtdXIsIHkgPSB0b3RhbF9hbW91bnQpKSArIGdlb21fcG9pbnQoKSArDQoJc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsNCglsYWJzKHRpdGxlID0gIlNlbWFraW4gYmVydW11ciwgcGVyZm9tYSBjYWJhbmcgYWthbiBzZW1ha2luIGJhaWsiLA0KCQkJeCA9ICJVbXVyKGJ1bGFuKSIsIHkgPSAiVG90YWwgQW1vdW50IikNCmBgYA0KIyMgS2VzaW1wdWxhbg0KVGVybGloYXQgYmFod2EgYWRhIHBvbGEgc2VtYWtpbiB0dWEgY2FiYW5nLCBtYWthIHBlcmZvcm1hbnlhIHNlbWFraW4gYmFpay4gSGFsIGluaSBrYXJlbmEgY2FiYW5nIHRlcnNlYnV0IG1hc2loIGJlcmtlbWJhbmcgc2VoaW5nZ2EgYmVsdW0gc2FtcGFpIHBhZGEgcGVyZm9ybWEgbWFrc2ltYWwuDQoNCkFrYW4gdGV0YXBpIHBhZGEgbWFzaW5nIC0gbWFzaW5nIHVtdXIgaXR1IGp1Z2EgYWRhIGNhYmFuZyB5YW5nIHBlcmZvcm1hbnlhIGRpYmF3YWggeWFuZyBsYWluLg0KDQpTZWxhbmp1dG55YSBha2FuIGRpYW5hbGlzaXMgY2FiYW5nIHlhbmcgcGVyZm9ybWFueWEgbGViaWggcmVuZGFoIGRhcmkgeWFuZyBsYWluIHBhZGEgdW11ciB5YW5nIHNhbWENCg0KIyMgTWVuY2FyaSBDYWJhbmcgeWFuZyBQZXJmb3JtYSBSZW5kYWggdW50dWsgU2V0aWFwIFVtdXINClNlbGFuanV0bnlhIFVudHVrIG1lbmNhcmkgY2FiYW5nIHlhbmcgcGVyZm9ybWFueWEgcmVuZGFoIHBhZGEgc2V0aWFwIGtlbG9tcG9rIHVtdXIsIGFrYW4gZGlndW5ha2FuIG5pbGFpwqBRdWFydGlsZcKgZGFuwqBJbnRlciBRdWFydGlsZSBSYW5nZcKgKEphbmdrYXVhbiBJbnRlcmt1YXJ0aWwpIGRhcmkgc2V0aWFwIHVtdXIuIERhbGFtIHN0YXRpc3Rpa2EgamFuZ2thdWFuIGludGVya3VhcnRpbCAoSVFSKSwgYWRhbGFoIHNlbGlzaWggYW50YXJhIHBlcnNlbnRpbCBrZS03NSAoa3VhcnRpbCBhdGFzKSBkYW4gcGVyc2VudGlsIGtlLTI1IChrdWFydGlsIGJhd2FoKS4gRGVuZ2FuIGthdGEgbGFpbizCoElRUiBhZGFsYWgga3VhcnRpbCBrZXRpZ2EgZGlrdXJhbmdpIGt1YXJ0aWwgcGVydGFtYS4NCg0KRGlrYXRha2FuIHJlbmRhaCBqaWthIHBlcmZvcm1hbnlhIGt1cmFuZyBkYXJpwqAoUTEgLSBJUVIpLiBVbnR1ayBpdHUgcGVybHUgZGljYXJpIGR1bHUgbmlsYWnCoFExLCBRM8KgZGFuwqBJUVLCoHVudHVrIHNldGlhcCB1bXVyIGRlbmdhbiBtZW5nZ3VuYWthbiBkYXRhwqBkZl9sb2FuX21laV91bXVyLiBVbnR1ayBtZW1idWF0IHZhcmlhYmVsIGluaSwgZ3VuYWthbsKgZ3JvdXBfYnkgZGFuwqBtdXRhdGUga2FyZW5hIHZhcmlhYmVsIGluaSBha2FuIGRpZ3VuYWthbiBsYWdpIG9sZWggc2VtdWEgZGF0YS4NCg0KU2V0ZWxhaCBpdHUgYnVhdCB2YXJpYWJlbCBiYXJ1wqBmbGFnIHlhbmcgYWthbiBiZXJpc2nCoCdyZW5kYWgnIGppa2EgcGVyZm9ybWFueWHCoGt1cmFuZyBkYXJpwqAoUTEgLSBJUVIpIGRhbsKgJ2JhaWsnIHVudHVrIHNlbGFpbiBpdHUgZGFuIHNpbXBhbiBoYXNpbG55YSBzZWJhZ2FpwqBkZl9sb2FuX21laV9mbGFnLg0KDQpMYWx1IGZpbHRlcsKgZGZfbG9hbl9tZWlfZmxhZyBoYW55YSB1bnR1a8KgZmxhZyByZW5kYWgsIGFnYXIgdGVybGloYXQgY2FiYW5nIG1hbmEgc2FqYSB5YW5nIG1hc3VrIGtlbG9tcG9rIGluaSwgZGFuIHViYWgga29sb20gbnVtZXJpYyBtZW5qYWRpwqBjb21tYSBkZW5nYW4gZnVuZ3NpwqBtdXRhdGVfaWYuDQoNCkd1bmFrYW4gcGlwZcKgJT4lIHVudHVrIG1lbnlhbWJ1bmdrYW4gZnVuZ3NpLg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzY2FsZXMpDQpkZl9sb2FuX21laV9mbGFnIDwtIGRmX2xvYW5fbWVpX3VtdXIgJT4lIA0KICBncm91cF9ieSh1bXVyKSAlPiUgDQogIG11dGF0ZShRMSA9IHF1YW50aWxlKHRvdGFsX2Ftb3VudCwgMC4yNSksDQogICAgICAgUTMgPSBxdWFudGlsZSh0b3RhbF9hbW91bnQsIDAuNzUpLA0KICAgICAgSVFSID0gKFEzLVExKSkgJT4lDQogIG11dGF0ZShmbGFnID0gaWZlbHNlKHRvdGFsX2Ftb3VudCA8IChRMSAtIElRUiksICdyZW5kYWgnLCdiYWlrJykpDQoNCmRmX2xvYW5fbWVpX2ZsYWcgJT4lIA0KICBmaWx0ZXIoZmxhZyA9PSAncmVuZGFoJykgJT4lIA0KICBtdXRhdGVfaWYoaXMubnVtZXJpYywgZnVucyhjb21tYSkpDQpgYGANCiMjIEJ1YXQgU2NhdHRlcnBsb3QgZGFuIGJlcmkgd2FybmEgbWVyYWggcGFkYSBjYWJhbmcgeWFuZyByZW5kYWgNClVudHVrIG1lbXBlcmplbGFzIGJhZ2FpbWFuYSBwZXJmb3JtYSBjYWJhbmcgeWFuZyByZW5kYWggaW5pLCBwbG90IGxhZ2kgc2VwZXJ0aSBzZWJlbHVtbnlhLiBTZWthcmFuZyBtZW5nZ3VuYWthbiBkYXRhIHlhbmcgYmFydSwgeWFrbmkgZGZfbG9hbl9tZWlfZmxhZy4gTGFsdSBiZXJpIHdhcm5hIGJpcnUgdW50dWsgY2FiYW5nIGRlbmdhbiBmbGFnICdiYWlrJyBkYW4gbWVyYWggdW50dWsgeWFuZyAncmVuZGFoJy4NCg0KU2VoaW5nZ2EgaGFzaWxueWEgYWthbiBtZW5qYWRpIHNlcGVydGkgaW5pOg0KYGBge3J9DQpnZ3Bsb3QoZGZfbG9hbl9tZWlfZmxhZywgYWVzKHggPSB1bXVyLCB5ID0gdG90YWxfYW1vdW50KSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGZsYWcpKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbChicmVha3MgPSBjKCJiYWlrIiwgInJlbmRhaCIpLA0KICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygiYmx1ZSIsICJyZWQiKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICBsYWJzKHRpdGxlID0gIkFkYSBjYWJhbmcgYmVycGVmb3JtYSByZW5kYWggcGFkYWhhbCB0aWRhayB0ZXJtYXN1ayBib3R0b20gNSBuYXNpb25hbCIsDQogICAgICAgY29sb3IgPSAiIiwNCiAgICAgICB4ID0gIlVtdXIgKGJ1bGFuKSIsDQogICAgICAgeSA9ICJUb3RhbCBBbW91bnQiKQ0KYGBgDQojIyBMaWhhciBQZXJiYW5kaW5nYW4gUGVyZm9ybWEgQ2FiYW5nIGRpIFVtdXIgeWFuZyBTYW1hDQpTZWxhbmp1dG55YSBha2FuIGRpYW5hbGlzaXMgbGViaWggbGFuanV0IGtlbmFwYSBjYWJhbmcgaXR1IGJpc2EgcGVyZm9ybWFueWEgcmVuZGFoIGRpIG1laQ0KDQpVbnR1ayBrYWxpIGluaSBha2FuIGRpbGloYXQgaGFueWEgdW50dWsgeWFuZyB1bXVyIGRlbmdhbiBwZXJmb3JtYSByZW5kYWggeWFpdHXCoCoqMyBidWxhbioqwqBzYWphLCBkaWxpaGF0IGRldGFpbCBwZXJmb3JtYSBwYWRhIGJ1bGFuIE1laSBkZW5nYW4gbWVuZ2hpdHVuZywNCg0KLSBKdW1sYWggaGFyaSBwZW5jYWlyYW4gZGFsYW0gMSBidWxhbg0KLSBKdW1sYWggYWdlbiB5YW5nIGFrdGlmDQotIFRvdGFsIGxvYW4geWFuZyBjYWlyDQotIFJhdGEgLSByYXRhIGFtb3VudCBjYWlyIHBlciBsb2FuLg0KDQpEYW4gdWJhaCBrb2xvbSBudW1lcmljIG1lbmphZGnCoGNvbW1hwqBkZW5nYW4gZnVuZ3NpwqBtdXRhdGVfaWYuDQoNCkd1bmFrYW4gcGlwZcKgJT4lIHVudHVrIG1lbnlhbWJ1bmdrYW4gZnVuZ3NpLg0KYGBge3J9DQpkZl9sb2FuX21laV9mbGFnICU+JSANCiAgZmlsdGVyKHVtdXIgPT0gMykgJT4lIA0KICBpbm5lcl9qb2luKGRmX2xvYW4sIGJ5ID0gJ2NhYmFuZycpICU+JSANCiAgZmlsdGVyKHRhbmdnYWxfY2FpciA+PSAnMjAyMC0wNS0wMScsIHRhbmdnYWxfY2FpciA8PSAnMjAyMC0wNS0zMScpICU+JSANCiAgZ3JvdXBfYnkoY2FiYW5nLCBmbGFnKSAlPiUgDQogIHN1bW1hcmlzZShqdW1sYWhfaGFyaSA9IG5fZGlzdGluY3QodGFuZ2dhbF9jYWlyKSwNCiAgICAgICAgICAgIGFnZW5fYWt0aWYgPSBuX2Rpc3RpbmN0KGFnZW4pLA0KICAgICAgICAgICAgdG90YWxfbG9hbl9jYWlyID0gbl9kaXN0aW5jdChsb2FuX2lkKSwNCiAgICAgICAgICAgIGF2Z19hbW91bnQgPSBtZWFuKGFtb3VudCksIA0KICAgICAgICAgICAgdG90YWxfYW1vdW50ID0gc3VtKGFtb3VudCkpICU+JSANCiAgYXJyYW5nZSh0b3RhbF9hbW91bnQpICU+JSANCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIGZ1bnMoY29tbWEpKQ0KYGBgDQojIyBMaWhhdCBQZXJiYWRpbmdhbiBQZXJmb3JtYSBBZ2VuIHBhZGEgQ2FiYW5nIHlhbmcgUmVuZGFoDQpEYXJpIGhhc2lsIGVrc3Bsb3Jhc2kgc2ViZWx1bW55YSwgdGVybGloYXQgYmFod2EgeWFuZyBiZXJiZWRhIGphdWggaGFueWEgdG90YWxfbG9hbl9jYWlyIHNhamEuIEp1bWxhaCBoYXJpIGRhbiBqdW1sYWggYWdlbiBkYWxhbSBzYXR1IGJ1bGFuIHNhbWEgc2VtdWEuDQoNClNlbGFuanV0bnlhIHBlcmx1IGRpbGloYXQgYmFnYWltYW5hIHBlcmJhbmRpbmdhbm55YSBwZXIgYWdlbnQuDQoNClVudHVrIG1lbGFuanV0a2FuIHRhZGksIGRpbGloYXQgdW50dWsgeWFuZyB1bXVywqAqKjMgYnVsYW4qKsKgZGFuwqAqKmZsYWcgbnlhIHJlbmRhaCoqwqBkaWxpaGF0IGRldGFpbCBwZXJmb3JtYSBwYWRhIGJ1bGFuIG1laSBwZXIgYWdlbiBkZW5nYW4gbWVuZ2loaXR1bmcsDQoNCi0gSnVtbGFoIGhhcmkgcGVuY2FpcmFuIGRhbGFtIDEgYnVsYW4NCi0gVG90YWwgbG9hbiB5YW5nIGNhaXINCi0gUmF0YSAtIHJhdGEgYW1vdW50IGNhaXIgcGVyIGxvYW4NCi0gVG90YWwgYW1vdW50IGNhaXINCg0KRGFuIHViYWgga29sb20gbnVtZXJpYyBtZW5qYWRpwqBjb21tYcKgZGVuZ2FuIGZ1bmdzacKgbXV0YXRlX2lmLg0KDQpHdW5ha2FuIHBpcGXCoCU+JSB1bnR1ayBtZW55YW1idW5na2FuIGZ1bmdzaS4NCmBgYHtyfQ0KZGZfbG9hbl9tZWlfZmxhZyAlPiUgDQogIGZpbHRlcih1bXVyID09IDMsIGZsYWcgPT0gJ3JlbmRhaCcpICU+JSANCiAgaW5uZXJfam9pbihkZl9sb2FuLCBieSA9ICdjYWJhbmcnKSAlPiUgDQogIGZpbHRlcih0YW5nZ2FsX2NhaXIgPj0gJzIwMjAtMDUtMDEnLCB0YW5nZ2FsX2NhaXIgPD0gJzIwMjAtMDUtMzEnKSAlPiUgDQogIGdyb3VwX2J5KGNhYmFuZywgYWdlbikgJT4lIA0KICBzdW1tYXJpc2UoanVtbGFoX2hhcmkgPSBuX2Rpc3RpbmN0KHRhbmdnYWxfY2FpciksDQogICAgICAgICAgICB0b3RhbF9sb2FuX2NhaXIgPSBuX2Rpc3RpbmN0KGxvYW5faWQpLA0KICAgICAgICAgICAgYXZnX2Ftb3VudCA9IG1lYW4oYW1vdW50KSwgDQogICAgICAgICAgICB0b3RhbF9hbW91bnQgPSBzdW0oYW1vdW50KSkgJT4lIA0KICBhcnJhbmdlKHRvdGFsX2Ftb3VudCkgJT4lIA0KICBtdXRhdGVfaWYoaXMubnVtZXJpYywgZnVucyhjb21tYSkpDQpgYGANCiMjIExpaGF0IFBlcmJhbmRpbmdhbiBQZXJmb3JtYSBBZ2VuIHBhZGEgQ2FiYW5nIHlhbmcgUGFsaW5nIEJhaWsgdW11ciAzIEJ1bGFuDQpQYWRhIHRhYmVsIHNlYmVsdW1ueWEsIHRlcmxpaGF0IHB1bGEgYmFod2EgYWRhIGNhYmFuZyB5YW5nIHB1bnlhIDMgYWdlbiwgdGFwaSBwZXJmb3JtYSBueWEgamF1aCBkaWF0YXMgY2FiYW5nIEFFLCBiYWhrYW4geWFuZyBwYWxpbmcgdGluZ2dpbCBkaWFudGFyYSBjYWJhbmcgbGFpbiBwYWRhIHVtdXIgdGVyc2VidXQsIGxlYmloIHRpbmdnaSBkYXJpIHlhbmcgbWVtcHVueWEgNCBhZ2VuIGNhYmFuZyB0ZXJzZWJ1dCBhZGFsYWggY2FiYW5nIEFILg0KDQpEZW5nYW4gY2FyYSB5YW5nIGhhbXBpciBzYW1hLCBha2FuIGRpbGloYXQgYmFnYWltYW5hIHBlcmZvcm1hIG1hc2luZy1tYXNpbmcgYWdlbiBkYXJpIGNhYmFuZyBBSCB0ZXJzZWJ1dC4gSGFueWEgc2FqYSB1bnR1ayBpbmkgYmlzYSBsYW5nc3VuZyBwYWthaSBkYXRhIGRmX2xvYW4gbGFsdSBmaWx0ZXIgbmFtYSBjYWJhbmcgbnlhIHNhamEuDQpgYGB7cn0NCmRmX2xvYW4gJT4lIA0KICBmaWx0ZXIoY2FiYW5nID09ICdBSCcpICU+JSANCiAgZmlsdGVyKHRhbmdnYWxfY2FpciA+PSAnMjAyMC0wNS0wMScsIHRhbmdnYWxfY2FpciA8PSAnMjAyMC0wNS0zMScpICU+JSANCiAgZ3JvdXBfYnkoY2FiYW5nLCBhZ2VuKSAlPiUgDQogIHN1bW1hcmlzZShqdW1sYWhfaGFpciA9IG5fZGlzdGluY3QodGFuZ2dhbF9jYWlyKSwNCiAgICAgICAgICAgIHRvdGFsX2xvYW5fY2FpciA9IG5fZGlzdGluY3QobG9hbl9pZCksDQogICAgICAgICAgICBhdmdfYW1vdW50ID0gbWVhbihhbW91bnQpLCANCiAgICAgICAgICAgIHRvdGFsX2Ftb3VudCA9IHN1bShhbW91bnQpKSAlPiUgDQogIGFycmFuZ2UodG90YWxfYW1vdW50KSAlPiUgDQogIG11dGF0ZV9pZihpcy5udW1lcmljLCBmdW5zKGNvbW1hKSkNCmBgYA0KIyMgS2VzaW1wdWxhbg0KQmVyZGFzYXJrYW4gYW5hbGlzaXMgdGVyc2VidXQsIGRhcGF0IGRpc2ltcHVsa2FuIGJhaHdhIHJlbmRhaG55YSBwZXJmb3JtYSBkYXJpIGNhYmFuZyBBRSBhZGFsYWgga2FyZW5hIHNhbGFoIHNhdHUgYWdlbiB5YW5nIG1lbGFrdWthbiBwZW5jYWlyYW4gaGFueWEgNCBoYXJpIGRhbGFtIDEgYnVsYW4sIHBhZGFoYWwgYWdlbiBsYWluIGJpc2EgYWt0aWYgMjEgaGFyaS4NCg0KSGFsIGluaSBtZW1idWF0IHRvdGFsIGFtb3VudCBkYXJpIGFnZW4gdGVyc2VidXQgaGFueWEgMjAlIGRpYmFuZGluZ2thbiBhZ2VuIHlhbmcgbGFpbm55YS4NCg0KU2VkYW5na2FuIHBhZGEgY2FiYW5nIEFILCBwZXJmb3JtYW55YSBzYW5nYXQgYmFpayBrYXJlbmEga2V0aWdhIGFnZW4gbWVsYWt1a2FuIHBlbmNhaXJhbiBoYW1waXIgLyBzZWxhbHUgc2V0aWFwIGhhcmkga2VyamEuIDIgb3JhbmcgZnVsbCAyMSBoYXJpIDEgb3JhbmcgMTkgaGFyaS4gU2VoaW5nZ2EgcGVyZm9ybWEgbnlhIHRlcmphZ2EgZGVuZ2FuIGJhaWsuDQoNClBlcmx1IGRpcGVyaGF0aWthbiBqdWdhIGJhaHdhIHVudHVrIG1lbWJhbmRpbmdrYW4gcGVyZm9ybWEgY2FiYW5nIGl0dSBzZWJhaWtueWEgZGkga2Vsb21wb2trYW4gZHVsdSBiZXJkYXNhcmthbiBrYXJha3RlcmlzdGlrIHlhbmcgc2FtYS4gVGlkYWsgbGFuZ3N1bmcgc2VtdWEgY2FiYW5nIGRpYmFuZGluZ2thbiB0YW5wYSBtZW5nZXRhaHVpIGthcmFrdGVyaXN0aWtueWEuDQoNCkFwYWxhZ2kga2V0aWthIGRhbGFtIHJlYWwgd29ybGQgbmFudGkgY2FiYW5nIGluaSBiaXNhIHRlcmxldGFrIGRpIGJlcmJlZGEgd2lsYXlhaCAocHVsYXUgbWlzYWxueWEpIHlhbmcgbWVtcHVueWFpIGt1bHR1ciB5YW5nIGJlcmJlZGENCg0KU2VsYW5qdXRueWEgcGVybHUgZGlhbmFsaXNpcyBsZWJpaCBsYW5qdXQga2VuYXBhIGFkYSBhZ2VuIHlhbmcgaGFueWEgYWt0aWYgYmViZXJhcGEgaGFyaSBzYWphIGRhbGFtIHNlYnVsYW4uDQoNClVudHVrIGtlZGVwYW5ueWEgc2V0aWFwIGFnZW4gYWdhciBkaXBhc3Rpa2FuIHVudHVrIGJpc2EgYWt0aWYgc2V0aWFwIGhhcmkgbnlhLCBzZWhpbmdnYSBiaXNhIG1lbmphZ2EgcGVyZm9ybWEgY2FiYW5nLg==