PEMROGRAMAN SAINS DATA 1

EXAM 1 SMT 2

Logo

Membuat Program & Menyelsesaikan Case Study

1. Menerima dua bilangan dari pengguna, Menghitung, dan menampilkan hasil

Buat program sederhana dalam R dan Python yang melakukan hal berikut:

  1. Menerima dua bilangan dari pengguna
  2. Menghitung dan menampilkan hasil:
    • Penjumlahan
    • Perkalian
    • Pembagian
    • Bilangan pertama pangkat bilangan kedua
  3. Menampilkan tipe data masing-masing hasil operasi
# Input dari pengguna secara manual
a <- as.numeric(readline(prompt = "Masukkan nilai a: "))
## Masukkan nilai a:
b <- as.numeric(readline(prompt = "Masukkan nilai b: "))
## Masukkan nilai b:
# Operasi Matematika
penjumlahan <- a + b
perkalian <- a * b
pembagian <- if (!is.na(b) && b != 0) a / b else "Tidak bisa dibagi nol"
pangkat <- a ^ b

# Menampilkan Hasil dan Tipe Data
cat("\nHasil Operasi:\n")
## 
## Hasil Operasi:
cat("Penjumlahan:", penjumlahan, "(Tipe:", class(penjumlahan), ")\n")
## Penjumlahan: NA (Tipe: numeric )
cat("Perkalian:", perkalian, "(Tipe:", class(perkalian), ")\n")
## Perkalian: NA (Tipe: numeric )
cat("Pembagian:", pembagian, "(Tipe:", class(pembagian), ")\n")
## Pembagian: Tidak bisa dibagi nol (Tipe: character )
cat("Pangkat:", pangkat, "(Tipe:", class(pangkat), ")\n")
## Pangkat: NA (Tipe: numeric )

2. Menerima input & Menampilkan keterangan

Tulislah program dalam R dan Python yang:

  1. Menerima input nilai ujian dari pengguna (0–100)

  2. Menampilkan keterangan berdasarkan ketentuan berikut:

    • Nilai ≥ 85: “Sangat Baik”
    • Nilai 70–84: “Baik”
    • Nilai 60–69: “Cukup”
    • Nilai < 60: “Perlu Perbaikan”
# Nilai default agar tidak error saat knitting
nilai <- 90  # ganti dengan nilai simulasi sesuai kebutuhan

# Struktur kendali dengan perlindungan terhadap NA
if (!is.na(nilai) && nilai >= 85) {
  keterangan <- "Sangat Baik"
} else if (!is.na(nilai) && nilai >= 70) {
  keterangan <- "Baik"
} else if (!is.na(nilai) && nilai >= 60) {
  keterangan <- "Cukup"
} else if (!is.na(nilai)) {
  keterangan <- "Perlu Perbaikan"
} else {
  keterangan <- "Nilai tidak valid"
}

# Menampilkan hasil
cat("Nilai Anda:", nilai, "\n")
## Nilai Anda: 90
cat("Keterangan:", keterangan, "\n")
## Keterangan: Sangat Baik

3. Menerima input integer n & Menggunakan loop untuk mencetak semua bilangan genap kelipatan 4 dari 1 hingga n

Buatlah fungsi dalam R dan Python bernama kelipatan_genap(n) yang:

  1. Menerima input integer n
  2. Menggunakan loop untuk mencetak semua bilangan genap kelipatan 4 dari 1 hingga n
  3. Contoh output jika n = 20: 4, 8, 12, 16, 20
kelipatan_genap <- function(n) {
  for (i in 1:n) {
    if (i %% 2 == 0 && i %% 4 == 0) {
      cat(i, " ")
    }
  }
}

# Simulasi input nilai n (bisa diganti sesuai kebutuhan)
n <- 20  # ganti sesuai contoh yang kamu inginkan

# Panggil fungsi
kelipatan_genap(n)
## 4  8  12  16  20

4. Case Study

Sebuah perusahaan e-commerce ingin menganalisis performa penjualannya berdasarkan data transaksi selama 3 bulan terakhir. Namun, data berasal dari berbagai sumber dan memiliki kualitas yang berbeda-beda. Oleh karena itu, proses Data Wrangling sangat penting dilakukan sebelum analisis lanjutan.

Bagian 1: Data Collection

Tugas:

  1. Gabungkan data dari tiga file CSV (data_penjualan_kuartal1_full - Januari.csv, Februari.csv, Maret.csv) menjadi satu dataset.
  2. Tampilkan jumlah total baris dan kolom.

Tujuan Pengumpulan Data

Pengumpulan data penjualan dari tiga bulan pertama tahun ini (Januari–Maret) dilakukan untuk beberapa tujuan utama berikut:

  1. Menganalisis Pola Penjualan
    Untuk memahami tren penjualan berdasarkan kategori produk, lokasi (kota), dan waktu (harian maupun bulanan).

  2. Mengukur Performa Penjualan
    Data ini digunakan untuk mengevaluasi performa penjualan secara menyeluruh dan per kategori, guna mengetahui produk mana yang paling laku atau kurang diminati.

  3. Mendukung Pengambilan Keputusan Bisnis
    Hasil analisis dari data ini menjadi dasar dalam pengambilan keputusan strategis, seperti pengadaan stok, promosi produk, dan penentuan target penjualan.

  4. Mengetahui Karakteristik Konsumen
    Dengan membersihkan dan menganalisis data pembeli, perusahaan dapat memahami perilaku konsumen, termasuk frekuensi transaksi dan preferensi pembelian.

  5. Mempersiapkan Visualisasi dan Laporan
    Data yang telah dikumpulkan dan dibersihkan akan disajikan dalam bentuk tabel dan visualisasi interaktif untuk memudahkan pemahaman oleh pemangku kepentingan.

📊 Interpretasi Dimensi Dataset Gabungan

Setelah proses penggabungan data dari tiga file CSV (Januari, Februari, dan Maret), diperoleh informasi sebagai berikut:

  • Jumlah Baris: 150
    Ini menunjukkan bahwa terdapat 150 transaksi yang terekam dalam dataset selama kuartal pertama (Januari–Maret). Setiap baris merepresentasikan satu transaksi atau entri data individu.

  • Jumlah Kolom: 9
    Terdapat 9 variabel atau kolom dalam dataset ini. Kolom-kolom ini kemungkinan berisi informasi seperti ID transaksi, tanggal, nama produk, jumlah, harga, kategori, wilayah, metode pembayaran, dan sebagainya (bergantung pada struktur asli dari file).


Bagian 2: Data Cleaning

Tugas:

  • Standarisasi tanggal
  • Ubah Harga dan Jumlah ke format numerik
  • Hitung ulang kolom Total
  • Ganti nilai tidak valid
  • Hapus baris dengan nama produk kosong

Tujuan

Tujuan dari proses data cleaning pada dataset penjualan ini adalah untuk memastikan data yang digunakan dalam analisis bersih, konsisten, dan siap untuk diproses lebih lanjut. Secara spesifik, pembersihan data bertujuan untuk:

  1. Menstandarisasi Format Tanggal
    Agar semua entri tanggal memiliki format yang seragam dan dapat digunakan dalam analisis waktu seperti tren harian atau bulanan.

  2. Mengonversi Harga dan Jumlah ke Format Numerik
    Untuk memastikan kolom-kolom numerik dapat dihitung dan dianalisis dengan benar (misalnya menghitung total penjualan).

  3. Menghitung Ulang Kolom Total
    Untuk memastikan nilai pada kolom Total sesuai dengan hasil perkalian antara Harga dan Jumlah, terutama setelah dilakukan pembersihan.

  4. Mengganti Nilai Tidak Valid
    Seperti mengganti nama pembeli yang anonim (anonymous) menjadi NA dan membersihkan karakter spesial pada nama pembeli.

  5. Menghapus Baris dengan Nama Produk Kosong atau Tidak Valid
    Untuk menjaga kualitas data, hanya baris dengan informasi produk yang valid akan dipertahankan dalam analisis.

📊 Interpretasi:

  1. Format Tanggal Diseragamkan:
    • Kolom Tanggal dikonversi menjadi format tanggal yang konsisten menggunakan pd.to_datetime(). Hal ini memastikan bahwa semua entri tanggal mengikuti pola yang sama (misalnya, YYYY-MM-DD), yang penting untuk analisis waktu, seperti pengelompokan penjualan per bulan atau tahun.
  2. Konversi Nilai Harga dan Jumlah ke Angka:
    • Kolom Harga diubah dari format string (yang mungkin termasuk karakter non-digit seperti “Rp” atau titik) menjadi format numerik menggunakan metode penggantian dengan regex. Dengan ini, analisis terkait harga (seperti perhitungan total penjualan) dapat dilakukan secara matematis.
    • Kolom Jumlah juga dikonversi dari representasi kata (misalnya, “satu”, “dua”) ke angka. Ini memungkinkan perhitungan yang lebih efektif ketika menghitung total penjualan berdasarkan jumlah unit yang dibeli.
  3. Perhitungan Ulang Kolom Total:
    • Kolom Total dihitung kembali sebagai hasil perkalian Harga dan Jumlah. Hal ini memberikan nilai total penjualan untuk setiap entri, yang penting untuk analisis keuangan dan strategis.
  4. Penggantian Nilai Tidak Valid:
    • Nilai-nilai yang tidak valid atau tidak relevan, seperti tanda “-” atau string “anonymous”, diubah menjadi nilai NA (Not Available). Ini membantu membersihkan data agar tidak mengganggu analisis. Nilai NA juga menandakan bahwa data tersebut hilang atau tidak dapat diandalkan.
  5. Penghapusan Baris Kosong untuk Kolom Produk:
    • Baris di mana kolom Produk kosong atau hanya berisi karakter “-” dihapus. Menghapus entri ini memastikan bahwa analisis hanya melibatkan produk yang valid dan tersedia, yang meningkatkan keakuratan hasil analisis.

Kesimpulan

Proses pembersihan data ini sangat penting untuk memastikan bahwa analisis yang dilakukan berdasarkan dataset ini adalah akurat dan relevan. Dengan menghilangkan nilai yang tidak valid, menyamakan format data, dan memastikan semua kolom berisi informasi yang dapat diolah, kita menyediakan dasar yang kuat untuk analisis lebih lanjut, seperti pemodelan penjualan, perencanaan inventaris, dan pengambilan keputusan strategis.


Bagian 3: Data Transformation

Tugas:

  • Buat kolom bulan
  • Hitung total penjualan per kategori produk
  • Hitung jumlah transaksi dari tiap kota
  • Buat ringkasan total penjualan bulanan

Tujuan

  1. Buat Kolom Bulan:
    • Mengkategorikan data penjualan berdasarkan bulan untuk memudahkan analisis tren penjualan bulanan.
  2. Hitung Total Penjualan per Kategori Produk:
    • Mengetahui kontribusi masing-masing kategori produk terhadap total penjualan, yang membantu dalam pengambilan keputusan strategis dan pengelolaan inventaris.
  3. Hitung Jumlah Transaksi dari Tiap Kota:
    • Menyediakan wawasan tentang distribusi penjualan dan performa di berbagai lokasi geografis, yang dapat membantu dalam strategi pemasaran dan pengembangan wilayah.
  4. Buat Ringkasan Total Penjualan Bulanan:
    • Menyajikan informasi penjualan secara ringkas setiap bulan untuk memudahkan evaluasi kinerja bulanan serta perencanaan ke depan.

🟩 1. Total Penjualan per Kategori

Kategori Total Penjualan (Rp)
Aksesoris 30.850.000
Elektronik 41.930.000
Fashion 44.015.000
🔍 Interpretasi:
  • Kategori Fashion memiliki total penjualan tertinggi sebesar Rp44,015,000, menunjukkan bahwa produk fashion sangat diminati oleh konsumen.
  • Diikuti oleh Elektronik, dengan total penjualan Rp41,930,000, yang menunjukkan minat yang kuat pada produk elektronik.
  • Kategori Aksesoris mencatat penjualan terendah, hanya Rp30,850,000, menyiratkan bahwa produk aksesoris mungkin kurang menarik bagi pelanggan atau perlu dipromosikan lebih baik.
  • Strategi pemasaran untuk Aksesoris perlu dievaluasi, sementara lebih banyak perhatian dapat diberikan kepada Fashion dan Elektronik.

🟦 2. Jumlah Transaksi per Kota

Kota Jumlah Transaksi
Bandung 33
Surabaya 30
- 30
Jakarta 29
🔍 Interpretasi:
  • Bandung merupakan kota dengan jumlah transaksi terbanyak, yaitu 33 transaksi, menunjukkan bahwa wilayah ini mungkin merupakan target pasar utama.
  • Terdapat 30 transaksi dengan kota tidak tercatat (-), yang menunjukkan adanya problem dalam pengumpulan data dan perlu diperbaiki untuk analisis yang lebih akurat.
  • Surabaya dan Jakarta memiliki jumlah transaksi yang mendekati satu sama lain, dengan Surabaya sedikit lebih tinggi. Ini menunjukkan potensi pasar di kedua kota tersebut.
  • Perlu perhatian lebih pada pengumpulan data lokasi, agar tidak ada transaksi yang tidak teridentifikasi yang dapat mempengaruhi analisis pasar.

🟨 3. Ringkasan Penjualan per Bulan

Bulan Total Penjualan (Rp)
2024-01 75.600.000
2024-02 40.800.000
2024-03 64.200.000
2024-04 94.900.000
2024-05 111.750.000
2024-06 95.800.000
🔍 Interpretasi:
  • Penjualan tertinggi terjadi pada bulan Mei dengan total Rp111,750,000, menunjukkan adanya lonjakan minat dari konsumen, mungkin didorong oleh promosi atau event khusus.
  • Bulan Januari juga menunjukkan penjualan yang kuat, namun penjualannya menurun di bulan Februari, yang mungkin disebabkan oleh lemahnya pembelanjaan setelah periode akhir tahun.
  • Setelah penurunan di Februari, terjadi pembangunan kembali yang positif mulai bulan Maret hingga Juni, menunjukkan bahwa pasar mungkin sedang pulih dan permintaan kembali meningkat.

🧠 Kesimpulan & Insight:

  1. Penjualan Fashion dan Elektronik merupakan pendorong utama, perlu diperkuat dengan promosi dan penguatan kategori produk.
  2. Bandung sebagai pasar terkuat menunjukkan potensi untuk strategi pemasaran lokal. Fokus pada merevitalisasi pasar di Surabaya dan Jakarta juga penting.
  3. Data lokasi tidak tercatat menunjukkan bahwa perlu adanya pembenahan dalam pengumpulan data untuk hasil yang lebih baik.
  4. Tren penjualan bulanan menunjukkan pemulihan yang positif setelah bulan Februari yang lemah; patut dicermati agar dapat memanfaatkan momentum penjualan yang kuat.

Visualisasi Data

Total Penjualan per Kategori

  • Interpretasi:
    • Grafik menunjukkan total penjualan untuk setiap kategori produk.
    • Kategori “NA” mencakup nilai penjualan tertinggi sebesar $168,762,010, yang mungkin menunjukkan masalah dalam data seperti kategori yang tidak terisi atau salah klasifikasi.
    • Di antara kategori yang terisi, “Fashion” muncul sebagai kategori dengan penjualan tertinggi ($225,259,768), diikuti oleh “Elektronik” dengan $212,756,770, dan “Aksesoris” dengan $33. Ini menunjukkan bahwa kategori Fashion dan Elektronik adalah pendorong utama penjualan.

Distribusi Penjualan per Bulan

  • Interpretasi:
    • Diagram donut menunjukkan proporsi penjualan dari setiap bulan.
    • Bulan Maret memiliki kontribusi tertinggi sebesar 38.7%, diikuti oleh Februari (35.5%) dan Januari (20.9%). April masih rendah dengan 4.9%.
    • Grafik ini menunjukkan bahwa penjualan meningkat secara signifikan di bulan Maret, yang mungkin terkait dengan promosi atau musiman.

Tren Penjualan Harian

  • Interpretasi:
    • Grafik garis menunjukkan fluktuasi total penjualan harian sepanjang bulan.
    • Terlihat adanya spike penjualan pada beberapa tanggal tertentu, yang bisa jadi akibat kampanye pemasaran atau penawaran khusus.
    • Kestabilan di sepanjang bulan menunjukkan trend yang tidak konsisten, dan ada tanggal dengan penjualan yang sangat tinggi dibandingkan dengan tanggal lainnya, yang bisa menunjukkan adanya data anomaly atau peristiwa tertentu.

Heatmap Penjualan Harian per Kota

  • Interpretasi:
    • Heatmap menunjukkan total penjualan harian yang dikelompokkan berdasarkan kota.
    • Terdapat beberapa nilai yang sangat tinggi untuk kota Bandung dan Jakarta dalam periode tertentu sementara Surabaya memiliki nilai penjualan yang lebih rendah.
    • Warna gelap menunjukkan total yang lebih tinggi, sedangkan wilayah dengan warna yang lebih terang menunjukkan penjualan lebih rendah.
    • Pengamatan ini berguna untuk memahami di mana titik kekuatan dan kesempatan terdapat dalam penjualan di berbagai lokasi.

Kesimpulan

  • Kategori Fashion dan Elektronik adalah pendorong utama penjualan, sementara ada masalah dalam data penjualan kategori, seperti “NA”.
  • Bulan Maret adalah yang paling produktif dalam konteks penjualan, dengan banyak aktivitas penjualan terjadi pada hari-hari tertentu.
  • Data dapat digunakan untuk lebih memahami pola pembelian dan membantu dalam perencanaan strategis untuk kampanye di masa depan, baik dari sisi produk yang ditawarkan maupun penempatan geografis.

LS0tICANCnRpdGxlOiAiUEVNUk9HUkFNQU4gU0FJTlMgREFUQSAxIiAgDQpzdWJ0aXRsZTogIkVYQU0gMSBTTVQgMiIgIA0KYXV0aG9yOiAiRGFkYW4gUmFtZGFuIEhpZGF5YXQgKDUyMjQwMDI4KSIgIA0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIiAgDQpvdXRwdXQ6ICANCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246ICAgDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUgIA0KICAgIHRodW1ibmFpbHM6IHRydWUgIA0KICAgIGxpZ2h0Ym94OiB0cnVlICANCiAgICBnYWxsZXJ5OiB0cnVlICANCiAgICBsaWJfZGlyOiBsaWJzICANCiAgICBkZl9wcmludDogInBhZ2VkIiAgDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyIgIA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgIA0KICAgIGNzczogInN0eWxlLmNzcyIgIA0KLS0tICANCg0KPGltZyBzcmM9IkZPVE8gVEVSQkFSVV8xMXpvbi5qcGciIGFsdD0iTG9nbyIgc3R5bGU9IndpZHRoOjIwMHB4OyBkaXNwbGF5OiBibG9jazsgbWFyZ2luOiBhdXRvOyI+DQoNCiMgTWVtYnVhdCBQcm9ncmFtICYgTWVueWVsc2VzYWlrYW4gQ2FzZSBTdHVkeQ0KDQojIyAqKjEuIE1lbmVyaW1hIGR1YSBiaWxhbmdhbiBkYXJpIHBlbmdndW5hLCBNZW5naGl0dW5nLCBkYW4gbWVuYW1waWxrYW4gaGFzaWwgKioNCg0KQnVhdCBwcm9ncmFtIHNlZGVyaGFuYSBkYWxhbSBSIGRhbiBQeXRob24geWFuZyBtZWxha3VrYW4gaGFsIGJlcmlrdXQ6DQoNCjEuIE1lbmVyaW1hIGR1YSBiaWxhbmdhbiBkYXJpIHBlbmdndW5hDQoyLiBNZW5naGl0dW5nIGRhbiBtZW5hbXBpbGthbiBoYXNpbDoNCiAgIC0gUGVuanVtbGFoYW4NCiAgIC0gUGVya2FsaWFuDQogICAtIFBlbWJhZ2lhbg0KICAgLSBCaWxhbmdhbiBwZXJ0YW1hIHBhbmdrYXQgYmlsYW5nYW4ga2VkdWENCjMuIE1lbmFtcGlsa2FuIHRpcGUgZGF0YSBtYXNpbmctbWFzaW5nIGhhc2lsIG9wZXJhc2kNCg0KDQpgYGB7ciwgbWFzc2FnZT1GQUxTRSwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KIyBJbnB1dCBkYXJpIHBlbmdndW5hIHNlY2FyYSBtYW51YWwNCmEgPC0gYXMubnVtZXJpYyhyZWFkbGluZShwcm9tcHQgPSAiTWFzdWtrYW4gbmlsYWkgYTogIikpDQpiIDwtIGFzLm51bWVyaWMocmVhZGxpbmUocHJvbXB0ID0gIk1hc3Vra2FuIG5pbGFpIGI6ICIpKQ0KDQojIE9wZXJhc2kgTWF0ZW1hdGlrYQ0KcGVuanVtbGFoYW4gPC0gYSArIGINCnBlcmthbGlhbiA8LSBhICogYg0KcGVtYmFnaWFuIDwtIGlmICghaXMubmEoYikgJiYgYiAhPSAwKSBhIC8gYiBlbHNlICJUaWRhayBiaXNhIGRpYmFnaSBub2wiDQpwYW5na2F0IDwtIGEgXiBiDQoNCiMgTWVuYW1waWxrYW4gSGFzaWwgZGFuIFRpcGUgRGF0YQ0KY2F0KCJcbkhhc2lsIE9wZXJhc2k6XG4iKQ0KY2F0KCJQZW5qdW1sYWhhbjoiLCBwZW5qdW1sYWhhbiwgIihUaXBlOiIsIGNsYXNzKHBlbmp1bWxhaGFuKSwgIilcbiIpDQpjYXQoIlBlcmthbGlhbjoiLCBwZXJrYWxpYW4sICIoVGlwZToiLCBjbGFzcyhwZXJrYWxpYW4pLCAiKVxuIikNCmNhdCgiUGVtYmFnaWFuOiIsIHBlbWJhZ2lhbiwgIihUaXBlOiIsIGNsYXNzKHBlbWJhZ2lhbiksICIpXG4iKQ0KY2F0KCJQYW5na2F0OiIsIHBhbmdrYXQsICIoVGlwZToiLCBjbGFzcyhwYW5na2F0KSwgIilcbiIpDQoNCmBgYA0KDQojIyAqKjIuIE1lbmVyaW1hIGlucHV0ICYgTWVuYW1waWxrYW4ga2V0ZXJhbmdhbioqDQoNClR1bGlzbGFoIHByb2dyYW0gZGFsYW0gKipSKiogZGFuICoqUHl0aG9uKiogeWFuZzoNCg0KMS4gTWVuZXJpbWEgaW5wdXQgbmlsYWkgdWppYW4gZGFyaSBwZW5nZ3VuYSAoMOKAkzEwMCkgIA0KMi4gTWVuYW1waWxrYW4ga2V0ZXJhbmdhbiBiZXJkYXNhcmthbiBrZXRlbnR1YW4gYmVyaWt1dDogIA0KDQogICAtIE5pbGFpIOKJpSA4NTogIlNhbmdhdCBCYWlrIiAgDQogICAtIE5pbGFpIDcw4oCTODQ6ICJCYWlrIiAgDQogICAtIE5pbGFpIDYw4oCTNjk6ICJDdWt1cCIgIA0KICAgLSBOaWxhaSA8IDYwOiAiUGVybHUgUGVyYmFpa2FuIiAgDQoNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCiMgTmlsYWkgZGVmYXVsdCBhZ2FyIHRpZGFrIGVycm9yIHNhYXQga25pdHRpbmcNCm5pbGFpIDwtIDkwICAjIGdhbnRpIGRlbmdhbiBuaWxhaSBzaW11bGFzaSBzZXN1YWkga2VidXR1aGFuDQoNCiMgU3RydWt0dXIga2VuZGFsaSBkZW5nYW4gcGVybGluZHVuZ2FuIHRlcmhhZGFwIE5BDQppZiAoIWlzLm5hKG5pbGFpKSAmJiBuaWxhaSA+PSA4NSkgew0KICBrZXRlcmFuZ2FuIDwtICJTYW5nYXQgQmFpayINCn0gZWxzZSBpZiAoIWlzLm5hKG5pbGFpKSAmJiBuaWxhaSA+PSA3MCkgew0KICBrZXRlcmFuZ2FuIDwtICJCYWlrIg0KfSBlbHNlIGlmICghaXMubmEobmlsYWkpICYmIG5pbGFpID49IDYwKSB7DQogIGtldGVyYW5nYW4gPC0gIkN1a3VwIg0KfSBlbHNlIGlmICghaXMubmEobmlsYWkpKSB7DQogIGtldGVyYW5nYW4gPC0gIlBlcmx1IFBlcmJhaWthbiINCn0gZWxzZSB7DQogIGtldGVyYW5nYW4gPC0gIk5pbGFpIHRpZGFrIHZhbGlkIg0KfQ0KDQojIE1lbmFtcGlsa2FuIGhhc2lsDQpjYXQoIk5pbGFpIEFuZGE6IiwgbmlsYWksICJcbiIpDQpjYXQoIktldGVyYW5nYW46Iiwga2V0ZXJhbmdhbiwgIlxuIikNCmBgYA0KDQojIyAqKjMuIE1lbmVyaW1hIGlucHV0IGludGVnZXIgbiAmIE1lbmdndW5ha2FuIGxvb3AgdW50dWsgbWVuY2V0YWsgc2VtdWEgYmlsYW5nYW4gZ2VuYXAga2VsaXBhdGFuIDQgZGFyaSAxIGhpbmdnYSBuICoqDQoNCkJ1YXRsYWggZnVuZ3NpIGRhbGFtIFIgZGFuIFB5dGhvbiBiZXJuYW1hIGtlbGlwYXRhbl9nZW5hcChuKSB5YW5nOg0KDQoxLiBNZW5lcmltYSBpbnB1dCBpbnRlZ2VyIG4NCjIuIE1lbmdndW5ha2FuICoqbG9vcCoqIHVudHVrIG1lbmNldGFrIHNlbXVhICoqYmlsYW5nYW4gZ2VuYXAga2VsaXBhdGFuIDQqKiBkYXJpIDEgaGluZ2dhIG4NCjMuIENvbnRvaCBvdXRwdXQgamlrYSBuID0gMjA6IDQsIDgsIDEyLCAxNiwgMjANCg0KDQpgYGB7ciwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Ka2VsaXBhdGFuX2dlbmFwIDwtIGZ1bmN0aW9uKG4pIHsNCiAgZm9yIChpIGluIDE6bikgew0KICAgIGlmIChpICUlIDIgPT0gMCAmJiBpICUlIDQgPT0gMCkgew0KICAgICAgY2F0KGksICIgIikNCiAgICB9DQogIH0NCn0NCg0KIyBTaW11bGFzaSBpbnB1dCBuaWxhaSBuIChiaXNhIGRpZ2FudGkgc2VzdWFpIGtlYnV0dWhhbikNCm4gPC0gMjAgICMgZ2FudGkgc2VzdWFpIGNvbnRvaCB5YW5nIGthbXUgaW5naW5rYW4NCg0KIyBQYW5nZ2lsIGZ1bmdzaQ0Ka2VsaXBhdGFuX2dlbmFwKG4pDQpgYGANCiMjICoqNC4gQ2FzZSBTdHVkeSoqDQoNClNlYnVhaCBwZXJ1c2FoYWFuIGUtY29tbWVyY2UgaW5naW4gbWVuZ2FuYWxpc2lzIHBlcmZvcm1hIHBlbmp1YWxhbm55YSBiZXJkYXNhcmthbiBkYXRhIHRyYW5zYWtzaSBzZWxhbWEgMyBidWxhbiB0ZXJha2hpci4gTmFtdW4sIGRhdGEgYmVyYXNhbCBkYXJpIGJlcmJhZ2FpIHN1bWJlciBkYW4gbWVtaWxpa2kga3VhbGl0YXMgeWFuZyBiZXJiZWRhLWJlZGEuIE9sZWgga2FyZW5hIGl0dSwgcHJvc2VzICoqRGF0YSBXcmFuZ2xpbmcqKiBzYW5nYXQgcGVudGluZyBkaWxha3VrYW4gc2ViZWx1bSBhbmFsaXNpcyBsYW5qdXRhbi4NCg0KIyMjIEJhZ2lhbiAxOiBEYXRhIENvbGxlY3Rpb24NCg0KIyMjIyBUdWdhczoNCjEuIEdhYnVuZ2thbiBkYXRhIGRhcmkgdGlnYSBmaWxlIENTViAoYGRhdGFfcGVuanVhbGFuX2t1YXJ0YWwxX2Z1bGwgLSBKYW51YXJpLmNzdmAsIGBGZWJydWFyaS5jc3ZgLCBgTWFyZXQuY3N2YCkgbWVuamFkaSBzYXR1IGRhdGFzZXQuDQoyLiBUYW1waWxrYW4ganVtbGFoIHRvdGFsIGJhcmlzIGRhbiBrb2xvbS4NCg0KIyMjIFR1anVhbiBQZW5ndW1wdWxhbiBEYXRhDQoNClBlbmd1bXB1bGFuIGRhdGEgcGVuanVhbGFuIGRhcmkgdGlnYSBidWxhbiBwZXJ0YW1hIHRhaHVuIGluaSAoSmFudWFyaeKAk01hcmV0KSBkaWxha3VrYW4gdW50dWsgYmViZXJhcGEgdHVqdWFuIHV0YW1hIGJlcmlrdXQ6DQoNCjEuICoqTWVuZ2FuYWxpc2lzIFBvbGEgUGVuanVhbGFuKiogIA0KICAgVW50dWsgbWVtYWhhbWkgdHJlbiBwZW5qdWFsYW4gYmVyZGFzYXJrYW4ga2F0ZWdvcmkgcHJvZHVrLCBsb2thc2kgKGtvdGEpLCBkYW4gd2FrdHUgKGhhcmlhbiBtYXVwdW4gYnVsYW5hbikuDQoNCjIuICoqTWVuZ3VrdXIgUGVyZm9ybWEgUGVuanVhbGFuKiogIA0KICAgRGF0YSBpbmkgZGlndW5ha2FuIHVudHVrIG1lbmdldmFsdWFzaSBwZXJmb3JtYSBwZW5qdWFsYW4gc2VjYXJhIG1lbnllbHVydWggZGFuIHBlciBrYXRlZ29yaSwgZ3VuYSBtZW5nZXRhaHVpIHByb2R1ayBtYW5hIHlhbmcgcGFsaW5nIGxha3UgYXRhdSBrdXJhbmcgZGltaW5hdGkuDQoNCjMuICoqTWVuZHVrdW5nIFBlbmdhbWJpbGFuIEtlcHV0dXNhbiBCaXNuaXMqKiAgDQogICBIYXNpbCBhbmFsaXNpcyBkYXJpIGRhdGEgaW5pIG1lbmphZGkgZGFzYXIgZGFsYW0gcGVuZ2FtYmlsYW4ga2VwdXR1c2FuIHN0cmF0ZWdpcywgc2VwZXJ0aSBwZW5nYWRhYW4gc3RvaywgcHJvbW9zaSBwcm9kdWssIGRhbiBwZW5lbnR1YW4gdGFyZ2V0IHBlbmp1YWxhbi4NCg0KNC4gKipNZW5nZXRhaHVpIEthcmFrdGVyaXN0aWsgS29uc3VtZW4qKiAgDQogICBEZW5nYW4gbWVtYmVyc2loa2FuIGRhbiBtZW5nYW5hbGlzaXMgZGF0YSBwZW1iZWxpLCBwZXJ1c2FoYWFuIGRhcGF0IG1lbWFoYW1pIHBlcmlsYWt1IGtvbnN1bWVuLCB0ZXJtYXN1ayBmcmVrdWVuc2kgdHJhbnNha3NpIGRhbiBwcmVmZXJlbnNpIHBlbWJlbGlhbi4NCg0KNS4gKipNZW1wZXJzaWFwa2FuIFZpc3VhbGlzYXNpIGRhbiBMYXBvcmFuKiogIA0KICAgRGF0YSB5YW5nIHRlbGFoIGRpa3VtcHVsa2FuIGRhbiBkaWJlcnNpaGthbiBha2FuIGRpc2FqaWthbiBkYWxhbSBiZW50dWsgdGFiZWwgZGFuIHZpc3VhbGlzYXNpIGludGVyYWt0aWYgdW50dWsgbWVtdWRhaGthbiBwZW1haGFtYW4gb2xlaCBwZW1hbmdrdSBrZXBlbnRpbmdhbi4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoRFQpICAjIHVudHVrIGRhdGF0YWJsZSBpbnRlcmFrdGlmDQoNCiMgTG9hZCBkYXRhDQpqYW51YXJpIDwtIHJlYWRfY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gSmFudWFyaS5jc3YiKSAgDQpmZWJydWFyaSA8LSByZWFkX2NzdigiZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDFfZnVsbCAtIEZlYnJ1YXJpLmNzdiIpICANCm1hcmV0IDwtIHJlYWRfY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gTWFyZXQuY3N2IikgIA0KDQojIFRhbWJhaCBrb2xvbSBidWxhbg0KamFudWFyaSRCdWxhbiA8LSAnSmFudWFyaScgIA0KZmVicnVhcmkkQnVsYW4gPC0gJ0ZlYnJ1YXJpJyAgDQptYXJldCRCdWxhbiA8LSAnTWFyZXQnICANCg0KIyBHYWJ1bmdrYW4NCnNlbXVhX2RhdGEgPC0gYmluZF9yb3dzKGphbnVhcmksIGZlYnJ1YXJpLCBtYXJldCkgIA0KDQojIFRhbXBpbGthbiB0YWJlbCBpbnRlcmFrdGlmDQpkYXRhdGFibGUoaGVhZChzZW11YV9kYXRhLCA1KSwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDUpLCBjYXB0aW9uID0gIjUgQmFyaXMgUGVydGFtYSBEYXRhc2V0IEdhYnVuZ2FuIikNCg0KYGBgDQojIyMjIPCfk4ogKipJbnRlcnByZXRhc2kgRGltZW5zaSBEYXRhc2V0IEdhYnVuZ2FuKioNCg0KU2V0ZWxhaCBwcm9zZXMgcGVuZ2dhYnVuZ2FuIGRhdGEgZGFyaSB0aWdhIGZpbGUgQ1NWIChKYW51YXJpLCBGZWJydWFyaSwgZGFuIE1hcmV0KSwgZGlwZXJvbGVoIGluZm9ybWFzaSBzZWJhZ2FpIGJlcmlrdXQ6DQoNCi0gKipKdW1sYWggQmFyaXM6KiogMTUwICANCiAgSW5pIG1lbnVuanVra2FuIGJhaHdhIHRlcmRhcGF0ICoqMTUwIHRyYW5zYWtzaSoqIHlhbmcgdGVyZWthbSBkYWxhbSBkYXRhc2V0IHNlbGFtYSBrdWFydGFsIHBlcnRhbWEgKEphbnVhcmnigJNNYXJldCkuIFNldGlhcCBiYXJpcyBtZXJlcHJlc2VudGFzaWthbiBzYXR1IHRyYW5zYWtzaSBhdGF1IGVudHJpIGRhdGEgaW5kaXZpZHUuDQoNCi0gKipKdW1sYWggS29sb206KiogOSAgDQogIFRlcmRhcGF0ICoqOSB2YXJpYWJlbCoqIGF0YXUga29sb20gZGFsYW0gZGF0YXNldCBpbmkuIEtvbG9tLWtvbG9tIGluaSBrZW11bmdraW5hbiBiZXJpc2kgaW5mb3JtYXNpIHNlcGVydGkgSUQgdHJhbnNha3NpLCB0YW5nZ2FsLCBuYW1hIHByb2R1aywganVtbGFoLCBoYXJnYSwga2F0ZWdvcmksIHdpbGF5YWgsIG1ldG9kZSBwZW1iYXlhcmFuLCBkYW4gc2ViYWdhaW55YSAoYmVyZ2FudHVuZyBwYWRhIHN0cnVrdHVyIGFzbGkgZGFyaSBmaWxlKS4NCiAgDQotLS0NCg0KIyMjIEJhZ2lhbiAyOiBEYXRhIENsZWFuaW5nDQoNCiMjIyMgVHVnYXM6DQotIFN0YW5kYXJpc2FzaSB0YW5nZ2FsDQotIFViYWggSGFyZ2EgZGFuIEp1bWxhaCBrZSBmb3JtYXQgbnVtZXJpaw0KLSBIaXR1bmcgdWxhbmcga29sb20gVG90YWwNCi0gR2FudGkgbmlsYWkgdGlkYWsgdmFsaWQNCi0gSGFwdXMgYmFyaXMgZGVuZ2FuIG5hbWEgcHJvZHVrIGtvc29uZw0KDQojIyMgVHVqdWFuDQoNClR1anVhbiBkYXJpIHByb3NlcyAqZGF0YSBjbGVhbmluZyogcGFkYSBkYXRhc2V0IHBlbmp1YWxhbiBpbmkgYWRhbGFoIHVudHVrIG1lbWFzdGlrYW4gZGF0YSB5YW5nIGRpZ3VuYWthbiBkYWxhbSBhbmFsaXNpcyBiZXJzaWgsIGtvbnNpc3RlbiwgZGFuIHNpYXAgdW50dWsgZGlwcm9zZXMgbGViaWggbGFuanV0LiBTZWNhcmEgc3Blc2lmaWssIHBlbWJlcnNpaGFuIGRhdGEgYmVydHVqdWFuIHVudHVrOg0KDQoxLiAqKk1lbnN0YW5kYXJpc2FzaSBGb3JtYXQgVGFuZ2dhbCoqICANCiAgIEFnYXIgc2VtdWEgZW50cmkgdGFuZ2dhbCBtZW1pbGlraSBmb3JtYXQgeWFuZyBzZXJhZ2FtIGRhbiBkYXBhdCBkaWd1bmFrYW4gZGFsYW0gYW5hbGlzaXMgd2FrdHUgc2VwZXJ0aSB0cmVuIGhhcmlhbiBhdGF1IGJ1bGFuYW4uDQoNCjIuICoqTWVuZ29udmVyc2kgSGFyZ2EgZGFuIEp1bWxhaCBrZSBGb3JtYXQgTnVtZXJpayoqICANCiAgIFVudHVrIG1lbWFzdGlrYW4ga29sb20ta29sb20gbnVtZXJpayBkYXBhdCBkaWhpdHVuZyBkYW4gZGlhbmFsaXNpcyBkZW5nYW4gYmVuYXIgKG1pc2FsbnlhIG1lbmdoaXR1bmcgdG90YWwgcGVuanVhbGFuKS4NCg0KMy4gKipNZW5naGl0dW5nIFVsYW5nIEtvbG9tIFRvdGFsKiogIA0KICAgVW50dWsgbWVtYXN0aWthbiBuaWxhaSBwYWRhIGtvbG9tICpUb3RhbCogc2VzdWFpIGRlbmdhbiBoYXNpbCBwZXJrYWxpYW4gYW50YXJhICpIYXJnYSogZGFuICpKdW1sYWgqLCB0ZXJ1dGFtYSBzZXRlbGFoIGRpbGFrdWthbiBwZW1iZXJzaWhhbi4NCg0KNC4gKipNZW5nZ2FudGkgTmlsYWkgVGlkYWsgVmFsaWQqKiAgDQogICBTZXBlcnRpIG1lbmdnYW50aSBuYW1hIHBlbWJlbGkgeWFuZyBhbm9uaW0gKF9hbm9ueW1vdXNfKSBtZW5qYWRpIE5BIGRhbiBtZW1iZXJzaWhrYW4ga2FyYWt0ZXIgc3Blc2lhbCBwYWRhIG5hbWEgcGVtYmVsaS4NCg0KNS4gKipNZW5naGFwdXMgQmFyaXMgZGVuZ2FuIE5hbWEgUHJvZHVrIEtvc29uZyBhdGF1IFRpZGFrIFZhbGlkKiogIA0KICAgVW50dWsgbWVuamFnYSBrdWFsaXRhcyBkYXRhLCBoYW55YSBiYXJpcyBkZW5nYW4gaW5mb3JtYXNpIHByb2R1ayB5YW5nIHZhbGlkIGFrYW4gZGlwZXJ0YWhhbmthbiBkYWxhbSBhbmFsaXNpcy4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEluc3RhbGwgamlrYSBiZWx1bSBhZGEgKGhhcHVzIHRhbmRhIGtvbWVudGFyIHVudHVrIGVrc2VrdXNpIHBlcnRhbWEga2FsaSkNCiMgaW5zdGFsbC5wYWNrYWdlcygiRFQiKQ0KDQojIExvYWQgbGlicmFyaWVzDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShEVCkgICMgVW50dWsgdGFiZWwgaW50ZXJha3RpZg0KDQojIEJhY2EgZmlsZSBDU1YNCmphbnVhcmkgPC0gcmVhZF9jc3YoImRhdGFfcGVuanVhbGFuX2t1YXJ0YWwxX2Z1bGwgLSBKYW51YXJpLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQpmZWJydWFyaSA8LSByZWFkX2NzdigiZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDFfZnVsbCAtIEZlYnJ1YXJpLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQptYXJldCA8LSByZWFkX2NzdigiZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDFfZnVsbCAtIE1hcmV0LmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQoNCiMgR2FidW5na2FuIGRhdGENCmRhdGEgPC0gYmluZF9yb3dzKGphbnVhcmksIGZlYnJ1YXJpLCBtYXJldCkNCg0KIyBVYmFoIGZvcm1hdCB0YW5nZ2FsDQpkYXRhIDwtIGRhdGEgJT4lDQogIG11dGF0ZShUYW5nZ2FsID0gZG15KFRhbmdnYWwpKQ0KDQojIEJlcnNpaGthbiBrb2xvbSBIYXJnYQ0KZGF0YSA8LSBkYXRhICU+JQ0KICBtdXRhdGUoSGFyZ2EgPSBzdHJfcmVwbGFjZV9hbGwoYXMuY2hhcmFjdGVyKEhhcmdhKSwgIlteMC05XSIsICIiKSwNCiAgICAgICAgIEhhcmdhID0gYXMubnVtZXJpYyhIYXJnYSkpDQoNCiMgS29udmVyc2kga2F0YSBqdW1sYWgga2UgYW5na2ENCmtvbnZlcnNpX2p1bWxhaCA8LSBjKCJzYXR1IiA9IDEsICJkdWEiID0gMiwgInRpZ2EiID0gMywgImVtcGF0IiA9IDQsDQogICAgICAgICAgICAgICAgICAgICAibGltYSIgPSA1LCAiZW5hbSIgPSA2LCAidHVqdWgiID0gNywgImRlbGFwYW4iID0gOCwNCiAgICAgICAgICAgICAgICAgICAgICJzZW1iaWxhbiIgPSA5LCAic2VwdWx1aCIgPSAxMCkNCg0KZGF0YSA8LSBkYXRhICU+JQ0KICBtdXRhdGUoSnVtbGFoID0gcmVjb2RlKEp1bWxhaCwgISEha29udmVyc2lfanVtbGFoKSwNCiAgICAgICAgIEp1bWxhaCA9IGFzLm51bWVyaWMoSnVtbGFoKSkNCg0KIyBIaXR1bmcgdG90YWwNCmRhdGEgPC0gZGF0YSAlPiUNCiAgbXV0YXRlKFRvdGFsID0gSGFyZ2EgKiBKdW1sYWgpDQoNCiMgQmVyc2loa2FuIG5hbWEgcGVtYmVsaSBkYW4gZ2FudGkgX2Fub255bW91c18gamFkaSBOQQ0KZGF0YSA8LSBkYXRhICU+JQ0KICBtdXRhdGUoUGVtYmVsaSA9IGlmZWxzZShQZW1iZWxpID09ICJfYW5vbnltb3VzXyIsIE5BLCBQZW1iZWxpKSwNCiAgICAgICAgIFBlbWJlbGkgPSBzdHJfcmVwbGFjZV9hbGwoUGVtYmVsaSwgIlteYS16QS1aMC05IF0iLCAiIikpDQoNCiMgSGFwdXMgYmFyaXMgZGVuZ2FuIFByb2R1ayBrb3NvbmcgYXRhdSAiLSINCmRhdGEgPC0gZGF0YSAlPiUNCiAgZmlsdGVyKCEoUHJvZHVrICVpbiUgYygiIiwgIi0iLCBOQSkpKQ0KDQojIFRhbXBpbGthbiB0YWJlbCBpbnRlcmFrdGlmDQpkYXRhdGFibGUoZGF0YSwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwKSwgY2FwdGlvbiA9ICJUYWJlbCBEYXRhIFBlbmp1YWxhbiBzZXRlbGFoIFBlbWJlcnNpaGFuIikNCg0KYGBgDQoNCiMjIyMg8J+TiiAqKkludGVycHJldGFzaToqKg0KDQoxLiAqKkZvcm1hdCBUYW5nZ2FsIERpc2VyYWdhbWthbioqOg0KICAgLSBLb2xvbSAqKlRhbmdnYWwqKiBkaWtvbnZlcnNpIG1lbmphZGkgZm9ybWF0IHRhbmdnYWwgeWFuZyBrb25zaXN0ZW4gbWVuZ2d1bmFrYW4gYHBkLnRvX2RhdGV0aW1lKClgLiBIYWwgaW5pIG1lbWFzdGlrYW4gYmFod2Egc2VtdWEgZW50cmkgdGFuZ2dhbCBtZW5naWt1dGkgcG9sYSB5YW5nIHNhbWEgKG1pc2FsbnlhLCBgWVlZWS1NTS1ERGApLCB5YW5nIHBlbnRpbmcgdW50dWsgYW5hbGlzaXMgd2FrdHUsIHNlcGVydGkgcGVuZ2Vsb21wb2thbiBwZW5qdWFsYW4gcGVyIGJ1bGFuIGF0YXUgdGFodW4uDQoNCjIuICoqS29udmVyc2kgTmlsYWkgSGFyZ2EgZGFuIEp1bWxhaCBrZSBBbmdrYSoqOg0KICAgLSBLb2xvbSAqKkhhcmdhKiogZGl1YmFoIGRhcmkgZm9ybWF0IHN0cmluZyAoeWFuZyBtdW5na2luIHRlcm1hc3VrIGthcmFrdGVyIG5vbi1kaWdpdCBzZXBlcnRpICJScCIgYXRhdSB0aXRpaykgbWVuamFkaSBmb3JtYXQgbnVtZXJpayBtZW5nZ3VuYWthbiBtZXRvZGUgcGVuZ2dhbnRpYW4gZGVuZ2FuIHJlZ2V4LiBEZW5nYW4gaW5pLCBhbmFsaXNpcyB0ZXJrYWl0IGhhcmdhIChzZXBlcnRpIHBlcmhpdHVuZ2FuIHRvdGFsIHBlbmp1YWxhbikgZGFwYXQgZGlsYWt1a2FuIHNlY2FyYSBtYXRlbWF0aXMuDQogICAtIEtvbG9tICoqSnVtbGFoKioganVnYSBkaWtvbnZlcnNpIGRhcmkgcmVwcmVzZW50YXNpIGthdGEgKG1pc2FsbnlhLCAic2F0dSIsICJkdWEiKSBrZSBhbmdrYS4gSW5pIG1lbXVuZ2tpbmthbiBwZXJoaXR1bmdhbiB5YW5nIGxlYmloIGVmZWt0aWYga2V0aWthIG1lbmdoaXR1bmcgdG90YWwgcGVuanVhbGFuIGJlcmRhc2Fya2FuIGp1bWxhaCB1bml0IHlhbmcgZGliZWxpLg0KDQozLiAqKlBlcmhpdHVuZ2FuIFVsYW5nIEtvbG9tIFRvdGFsKio6DQogICAtIEtvbG9tICoqVG90YWwqKiBkaWhpdHVuZyBrZW1iYWxpIHNlYmFnYWkgaGFzaWwgcGVya2FsaWFuICoqSGFyZ2EqKiBkYW4gKipKdW1sYWgqKi4gSGFsIGluaSBtZW1iZXJpa2FuIG5pbGFpIHRvdGFsIHBlbmp1YWxhbiB1bnR1ayBzZXRpYXAgZW50cmksIHlhbmcgcGVudGluZyB1bnR1ayBhbmFsaXNpcyBrZXVhbmdhbiBkYW4gc3RyYXRlZ2lzLg0KDQo0LiAqKlBlbmdnYW50aWFuIE5pbGFpIFRpZGFrIFZhbGlkKio6DQogICAtIE5pbGFpLW5pbGFpIHlhbmcgdGlkYWsgdmFsaWQgYXRhdSB0aWRhayByZWxldmFuLCBzZXBlcnRpIHRhbmRhICItIiBhdGF1IHN0cmluZyAiX2Fub255bW91c18iLCBkaXViYWggbWVuamFkaSBuaWxhaSBOQSAoTm90IEF2YWlsYWJsZSkuIEluaSBtZW1iYW50dSBtZW1iZXJzaWhrYW4gZGF0YSBhZ2FyIHRpZGFrIG1lbmdnYW5nZ3UgYW5hbGlzaXMuIE5pbGFpIE5BIGp1Z2EgbWVuYW5kYWthbiBiYWh3YSBkYXRhIHRlcnNlYnV0IGhpbGFuZyBhdGF1IHRpZGFrIGRhcGF0IGRpYW5kYWxrYW4uDQoNCjUuICoqUGVuZ2hhcHVzYW4gQmFyaXMgS29zb25nIHVudHVrIEtvbG9tIFByb2R1ayoqOg0KICAgLSBCYXJpcyBkaSBtYW5hIGtvbG9tICoqUHJvZHVrKioga29zb25nIGF0YXUgaGFueWEgYmVyaXNpIGthcmFrdGVyICItIiBkaWhhcHVzLiBNZW5naGFwdXMgZW50cmkgaW5pIG1lbWFzdGlrYW4gYmFod2EgYW5hbGlzaXMgaGFueWEgbWVsaWJhdGthbiBwcm9kdWsgeWFuZyB2YWxpZCBkYW4gdGVyc2VkaWEsIHlhbmcgbWVuaW5na2F0a2FuIGtlYWt1cmF0YW4gaGFzaWwgYW5hbGlzaXMuDQoNCiMjIyMgS2VzaW1wdWxhbg0KDQpQcm9zZXMgcGVtYmVyc2loYW4gZGF0YSBpbmkgc2FuZ2F0IHBlbnRpbmcgdW50dWsgbWVtYXN0aWthbiBiYWh3YSBhbmFsaXNpcyB5YW5nIGRpbGFrdWthbiBiZXJkYXNhcmthbiBkYXRhc2V0IGluaSBhZGFsYWggYWt1cmF0IGRhbiByZWxldmFuLiBEZW5nYW4gbWVuZ2hpbGFuZ2thbiBuaWxhaSB5YW5nIHRpZGFrIHZhbGlkLCBtZW55YW1ha2FuIGZvcm1hdCBkYXRhLCBkYW4gbWVtYXN0aWthbiBzZW11YSBrb2xvbSBiZXJpc2kgaW5mb3JtYXNpIHlhbmcgZGFwYXQgZGlvbGFoLCBraXRhIG1lbnllZGlha2FuIGRhc2FyIHlhbmcga3VhdCB1bnR1ayBhbmFsaXNpcyBsZWJpaCBsYW5qdXQsIHNlcGVydGkgcGVtb2RlbGFuIHBlbmp1YWxhbiwgcGVyZW5jYW5hYW4gaW52ZW50YXJpcywgZGFuIHBlbmdhbWJpbGFuIGtlcHV0dXNhbiBzdHJhdGVnaXMuDQoNCi0tLQ0KDQojIyMgQmFnaWFuIDM6IERhdGEgVHJhbnNmb3JtYXRpb24NCg0KIyMjIyBUdWdhczoNCi0gQnVhdCBrb2xvbSBidWxhbg0KLSBIaXR1bmcgdG90YWwgcGVuanVhbGFuIHBlciBrYXRlZ29yaSBwcm9kdWsNCi0gSGl0dW5nIGp1bWxhaCB0cmFuc2Frc2kgZGFyaSB0aWFwIGtvdGENCi0gQnVhdCByaW5na2FzYW4gdG90YWwgcGVuanVhbGFuIGJ1bGFuYW4NCg0KIyMjIFR1anVhbg0KMS4gKipCdWF0IEtvbG9tIEJ1bGFuKio6IA0KICAgLSBNZW5na2F0ZWdvcmlrYW4gZGF0YSBwZW5qdWFsYW4gYmVyZGFzYXJrYW4gYnVsYW4gdW50dWsgbWVtdWRhaGthbiBhbmFsaXNpcyB0cmVuIHBlbmp1YWxhbiBidWxhbmFuLg0KDQoyLiAqKkhpdHVuZyBUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIFByb2R1ayoqOiANCiAgIC0gTWVuZ2V0YWh1aSBrb250cmlidXNpIG1hc2luZy1tYXNpbmcga2F0ZWdvcmkgcHJvZHVrIHRlcmhhZGFwIHRvdGFsIHBlbmp1YWxhbiwgeWFuZyBtZW1iYW50dSBkYWxhbSBwZW5nYW1iaWxhbiBrZXB1dHVzYW4gc3RyYXRlZ2lzIGRhbiBwZW5nZWxvbGFhbiBpbnZlbnRhcmlzLg0KDQozLiAqKkhpdHVuZyBKdW1sYWggVHJhbnNha3NpIGRhcmkgVGlhcCBLb3RhKio6IA0KICAgLSBNZW55ZWRpYWthbiB3YXdhc2FuIHRlbnRhbmcgZGlzdHJpYnVzaSBwZW5qdWFsYW4gZGFuIHBlcmZvcm1hIGRpIGJlcmJhZ2FpIGxva2FzaSBnZW9ncmFmaXMsIHlhbmcgZGFwYXQgbWVtYmFudHUgZGFsYW0gc3RyYXRlZ2kgcGVtYXNhcmFuIGRhbiBwZW5nZW1iYW5nYW4gd2lsYXlhaC4NCg0KNC4gKipCdWF0IFJpbmdrYXNhbiBUb3RhbCBQZW5qdWFsYW4gQnVsYW5hbioqOiANCiAgIC0gTWVueWFqaWthbiBpbmZvcm1hc2kgcGVuanVhbGFuIHNlY2FyYSByaW5na2FzIHNldGlhcCBidWxhbiB1bnR1ayBtZW11ZGFoa2FuIGV2YWx1YXNpIGtpbmVyamEgYnVsYW5hbiBzZXJ0YSBwZXJlbmNhbmFhbiBrZSBkZXBhbi4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShEVCkgICMgVW50dWsgdGFiZWwgaW50ZXJha3RpZg0KDQojIEJhY2EgZGF0YQ0KamFudWFyaSA8LSByZWFkX2NzdigiZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDFfZnVsbCAtIEphbnVhcmkuY3N2IikNCmZlYnJ1YXJpIDwtIHJlYWRfY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gRmVicnVhcmkuY3N2IikNCm1hcmV0IDwtIHJlYWRfY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gTWFyZXQuY3N2IikNCg0KIyBHYWJ1bmdrYW4NCmRhdGFfcGVuanVhbGFuIDwtIGJpbmRfcm93cyhqYW51YXJpLCBmZWJydWFyaSwgbWFyZXQpDQoNCiMgS29udmVyc2kgdGFuZ2dhbA0KZGF0YV9wZW5qdWFsYW4gPC0gZGF0YV9wZW5qdWFsYW4gJT4lDQogIG11dGF0ZShUYW5nZ2FsID0gYXMuRGF0ZShUYW5nZ2FsKSkNCg0KIyBCdWF0IGtvbG9tIEJ1bGFuDQpkYXRhX3Blbmp1YWxhbiA8LSBkYXRhX3Blbmp1YWxhbiAlPiUNCiAgbXV0YXRlKEJ1bGFuID0gZm9ybWF0KFRhbmdnYWwsICIlWS0lbSIpKQ0KDQojIEtvbnZlcnNpIEhhcmdhDQpkYXRhX3Blbmp1YWxhbiA8LSBkYXRhX3Blbmp1YWxhbiAlPiUNCiAgbXV0YXRlKEhhcmdhID0gYXMubnVtZXJpYyhzdHJfcmVtb3ZlX2FsbChIYXJnYSwgIlteMC05XSIpKSkNCg0KIyBLb252ZXJzaSBKdW1sYWggdGVrcyDihpIgYW5na2ENCmthbXVzX2p1bWxhaCA8LSBjKA0KICAic2F0dSIgPSAxLCAiZHVhIiA9IDIsICJ0aWdhIiA9IDMsICJlbXBhdCIgPSA0LA0KICAibGltYSIgPSA1LCAiZW5hbSIgPSA2LCAidHVqdWgiID0gNywgImRlbGFwYW4iID0gOCwNCiAgInNlbWJpbGFuIiA9IDksICJzZXB1bHVoIiA9IDEwDQopDQoNCmRhdGFfcGVuanVhbGFuIDwtIGRhdGFfcGVuanVhbGFuICU+JQ0KICBtdXRhdGUoSnVtbGFoID0gaWZlbHNlKEp1bWxhaCAlaW4lIG5hbWVzKGthbXVzX2p1bWxhaCksDQogICAgICAgICAgICAgICAgICAgICAgICAga2FtdXNfanVtbGFoW0p1bWxhaF0sDQogICAgICAgICAgICAgICAgICAgICAgICAgYXMubnVtZXJpYyhKdW1sYWgpKSwNCiAgICAgICAgIEp1bWxhaCA9IGFzLm51bWVyaWMoSnVtbGFoKSkNCg0KIyBIaXR1bmcgVG90YWwNCmRhdGFfcGVuanVhbGFuIDwtIGRhdGFfcGVuanVhbGFuICU+JQ0KICBtdXRhdGUoVG90YWwgPSBIYXJnYSAqIEp1bWxhaCkNCg0KIyBCZXJzaWhrYW4gUGVtYmVsaQ0KZGF0YV9wZW5qdWFsYW4gPC0gZGF0YV9wZW5qdWFsYW4gJT4lDQogIG11dGF0ZShQZW1iZWxpID0gaWZlbHNlKFBlbWJlbGkgPT0gIl9hbm9ueW1vdXNfIiwgTkEsIFBlbWJlbGkpLA0KICAgICAgICAgUGVtYmVsaSA9IHN0cl9yZXBsYWNlX2FsbChQZW1iZWxpLCAiW15hLXpBLVowLTkgXSIsICIiKSkNCg0KIyBIYXB1cyBwcm9kdWsga29zb25nDQpkYXRhX3Blbmp1YWxhbiA8LSBkYXRhX3Blbmp1YWxhbiAlPiUNCiAgZmlsdGVyKCEoUHJvZHVrICVpbiUgYygiIiwgIi0iLCBOQSkpKQ0KDQojIGEuIFRvdGFsIHBlbmp1YWxhbiBwZXIga2F0ZWdvcmkNCnRvdGFsX3Blcl9rYXRlZ29yaSA8LSBkYXRhX3Blbmp1YWxhbiAlPiUNCiAgZ3JvdXBfYnkoS2F0ZWdvcmkpICU+JQ0KICBzdW1tYXJpc2UoYFRvdGFsIFBlbmp1YWxhbmAgPSBzdW0oVG90YWwsIG5hLnJtID0gVFJVRSkpICU+JQ0KICBhcnJhbmdlKEthdGVnb3JpKQ0KDQojIGIuIEp1bWxhaCB0cmFuc2Frc2kgcGVyIGtvdGENCnRyYW5zYWtzaV9wZXJfa290YSA8LSBkYXRhX3Blbmp1YWxhbiAlPiUNCiAgY291bnQoS290YSwgbmFtZSA9ICJKdW1sYWggVHJhbnNha3NpIikgJT4lDQogIGFycmFuZ2UoS290YSkNCg0KIyBjLiBQZW5qdWFsYW4gcGVyIGJ1bGFuICsgYmFyaXMgdG90YWwNCnBlbmp1YWxhbl9wZXJfYnVsYW4gPC0gZGF0YV9wZW5qdWFsYW4gJT4lDQogIGdyb3VwX2J5KEJ1bGFuKSAlPiUNCiAgc3VtbWFyaXNlKGBUb3RhbCBQZW5qdWFsYW5gID0gc3VtKFRvdGFsLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgYXJyYW5nZShCdWxhbikNCg0KdG90YWxfc2VtdWEgPC0gZGF0YS5mcmFtZShCdWxhbiA9ICJUb3RhbCIsIGBUb3RhbCBQZW5qdWFsYW5gID0gc3VtKGRhdGFfcGVuanVhbGFuJFRvdGFsLCBuYS5ybSA9IFRSVUUpKQ0KcGVuanVhbGFuX3Blcl9idWxhbiA8LSBiaW5kX3Jvd3MocGVuanVhbGFuX3Blcl9idWxhbiwgdG90YWxfc2VtdWEpDQoNCiMgVGFtcGlsa2FuIGhhc2lsIHNlYmFnYWkgdGFiZWwgaW50ZXJha3RpZg0KZGF0YXRhYmxlKHRvdGFsX3Blcl9rYXRlZ29yaSwgY2FwdGlvbiA9ICJUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIikNCmRhdGF0YWJsZSh0cmFuc2Frc2lfcGVyX2tvdGEsIGNhcHRpb24gPSAiSnVtbGFoIFRyYW5zYWtzaSBwZXIgS290YSIpDQpkYXRhdGFibGUocGVuanVhbGFuX3Blcl9idWxhbiwgY2FwdGlvbiA9ICJSaW5na2FzYW4gUGVuanVhbGFuIHBlciBCdWxhbiIpDQoNCmBgYA0KDQojIyMjIPCfn6kgKioxLiBUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpKioNCg0KfCBLYXRlZ29yaSAgICAgfCBUb3RhbCBQZW5qdWFsYW4gKFJwKSB8DQp8LS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwNCnwgQWtzZXNvcmlzICAgIHwgMzAuODUwLjAwMCAgICAgICAgICAgfA0KfCBFbGVrdHJvbmlrICAgfCA0MS45MzAuMDAwICAgICAgICAgICB8DQp8IEZhc2hpb24gICAgICB8IDQ0LjAxNS4wMDAgICAgICAgICAgIHwNCg0KIyMjIyMg8J+UjSBJbnRlcnByZXRhc2k6DQotIEthdGVnb3JpICoqRmFzaGlvbiBtZW1pbGlraSB0b3RhbCBwZW5qdWFsYW4gdGVydGluZ2dpKiogc2ViZXNhciBScDQ0LDAxNSwwMDAsIG1lbnVuanVra2FuIGJhaHdhIHByb2R1ayBmYXNoaW9uIHNhbmdhdCBkaW1pbmF0aSBvbGVoIGtvbnN1bWVuLg0KLSAqKkRpaWt1dGkgb2xlaCBFbGVrdHJvbmlrKiosIGRlbmdhbiB0b3RhbCBwZW5qdWFsYW4gUnA0MSw5MzAsMDAwLCB5YW5nIG1lbnVuanVra2FuIG1pbmF0IHlhbmcga3VhdCBwYWRhIHByb2R1ayBlbGVrdHJvbmlrLg0KLSBLYXRlZ29yaSAqKkFrc2Vzb3JpcyBtZW5jYXRhdCBwZW5qdWFsYW4gdGVyZW5kYWgqKiwgaGFueWEgUnAzMCw4NTAsMDAwLCBtZW55aXJhdGthbiBiYWh3YSBwcm9kdWsgYWtzZXNvcmlzIG11bmdraW4ga3VyYW5nIG1lbmFyaWsgYmFnaSBwZWxhbmdnYW4gYXRhdSBwZXJsdSBkaXByb21vc2lrYW4gbGViaWggYmFpay4NCi0gU3RyYXRlZ2kgcGVtYXNhcmFuIHVudHVrICoqQWtzZXNvcmlzIHBlcmx1IGRpZXZhbHVhc2kqKiwgc2VtZW50YXJhIGxlYmloIGJhbnlhayBwZXJoYXRpYW4gZGFwYXQgZGliZXJpa2FuIGtlcGFkYSAqKkZhc2hpb24gZGFuIEVsZWt0cm9uaWsqKi4NCg0KLS0tDQoNCiMjIyMg8J+fpiAqKjIuIEp1bWxhaCBUcmFuc2Frc2kgcGVyIEtvdGEqKg0KDQp8IEtvdGEgICAgICB8IEp1bWxhaCBUcmFuc2Frc2kgfA0KfC0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwNCnwgQmFuZHVuZyAgIHwgMzMgICAgICAgICAgICAgICB8DQp8IFN1cmFiYXlhICB8IDMwICAgICAgICAgICAgICAgfA0KfCAtICAgICAgICAgfCAzMCAgICAgICAgICAgICAgIHwNCnwgSmFrYXJ0YSAgIHwgMjkgICAgICAgICAgICAgICB8DQoNCiMjIyMjIPCflI0gSW50ZXJwcmV0YXNpOg0KLSAqKkJhbmR1bmcgbWVydXBha2FuIGtvdGEgZGVuZ2FuIGp1bWxhaCB0cmFuc2Frc2kgdGVyYmFueWFrKiosIHlhaXR1IDMzIHRyYW5zYWtzaSwgbWVudW5qdWtrYW4gYmFod2Egd2lsYXlhaCBpbmkgbXVuZ2tpbiBtZXJ1cGFrYW4gdGFyZ2V0IHBhc2FyIHV0YW1hLg0KLSBUZXJkYXBhdCAqKjMwIHRyYW5zYWtzaSBkZW5nYW4ga290YSB0aWRhayB0ZXJjYXRhdCAoLSkqKiwgeWFuZyBtZW51bmp1a2thbiBhZGFueWEgcHJvYmxlbSBkYWxhbSBwZW5ndW1wdWxhbiBkYXRhIGRhbiBwZXJsdSBkaXBlcmJhaWtpIHVudHVrIGFuYWxpc2lzIHlhbmcgbGViaWggYWt1cmF0Lg0KLSAqKlN1cmFiYXlhIGRhbiBKYWthcnRhIG1lbWlsaWtpIGp1bWxhaCB0cmFuc2Frc2kgeWFuZyBtZW5kZWthdGkgc2F0dSBzYW1hIGxhaW4qKiwgZGVuZ2FuIFN1cmFiYXlhIHNlZGlraXQgbGViaWggdGluZ2dpLiBJbmkgbWVudW5qdWtrYW4gcG90ZW5zaSBwYXNhciBkaSBrZWR1YSBrb3RhIHRlcnNlYnV0Lg0KLSAqKlBlcmx1IHBlcmhhdGlhbiBsZWJpaCBwYWRhIHBlbmd1bXB1bGFuIGRhdGEgbG9rYXNpKiosIGFnYXIgdGlkYWsgYWRhIHRyYW5zYWtzaSB5YW5nIHRpZGFrIHRlcmlkZW50aWZpa2FzaSB5YW5nIGRhcGF0IG1lbXBlbmdhcnVoaSBhbmFsaXNpcyBwYXNhci4NCg0KLS0tDQoNCiMjIyMg8J+fqCAqKjMuIFJpbmdrYXNhbiBQZW5qdWFsYW4gcGVyIEJ1bGFuKioNCg0KfCBCdWxhbiAgICAgfCBUb3RhbCBQZW5qdWFsYW4gKFJwKSB8DQp8LS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwNCnwgMjAyNC0wMSAgIHwgNzUuNjAwLjAwMCAgICAgICAgICAgfA0KfCAyMDI0LTAyICAgfCA0MC44MDAuMDAwICAgICAgICAgICB8DQp8IDIwMjQtMDMgICB8IDY0LjIwMC4wMDAgICAgICAgICAgIHwNCnwgMjAyNC0wNCAgIHwgOTQuOTAwLjAwMCAgICAgICAgICAgfA0KfCAyMDI0LTA1ICAgfCAxMTEuNzUwLjAwMCAgICAgICAgICB8DQp8IDIwMjQtMDYgICB8IDk1LjgwMC4wMDAgICAgICAgICAgfA0KDQojIyMjIyDwn5SNIEludGVycHJldGFzaToNCi0gKipQZW5qdWFsYW4gdGVydGluZ2dpIHRlcmphZGkgcGFkYSBidWxhbiBNZWkqKiBkZW5nYW4gdG90YWwgUnAxMTEsNzUwLDAwMCwgbWVudW5qdWtrYW4gYWRhbnlhIGxvbmpha2FuIG1pbmF0IGRhcmkga29uc3VtZW4sIG11bmdraW4gZGlkb3Jvbmcgb2xlaCBwcm9tb3NpIGF0YXUgZXZlbnQga2h1c3VzLg0KLSAqKkJ1bGFuIEphbnVhcmkganVnYSBtZW51bmp1a2thbiBwZW5qdWFsYW4geWFuZyBrdWF0KiosIG5hbXVuIHBlbmp1YWxhbm55YSAqKm1lbnVydW4gZGkgYnVsYW4gRmVicnVhcmkqKiwgeWFuZyBtdW5na2luIGRpc2ViYWJrYW4gb2xlaCBsZW1haG55YSBwZW1iZWxhbmphYW4gc2V0ZWxhaCBwZXJpb2RlIGFraGlyIHRhaHVuLg0KLSBTZXRlbGFoIHBlbnVydW5hbiBkaSBGZWJydWFyaSwgdGVyamFkaSAqKnBlbWJhbmd1bmFuIGtlbWJhbGkgeWFuZyBwb3NpdGlmIG11bGFpIGJ1bGFuIE1hcmV0IGhpbmdnYSBKdW5pKiosIG1lbnVuanVra2FuIGJhaHdhIHBhc2FyIG11bmdraW4gc2VkYW5nIHB1bGloIGRhbiBwZXJtaW50YWFuIGtlbWJhbGkgbWVuaW5na2F0Lg0KDQotLS0NCg0KIyMjIyDwn6egICoqS2VzaW1wdWxhbiAmIEluc2lnaHQ6KioNCg0KMS4gUGVuanVhbGFuICoqRmFzaGlvbiBkYW4gRWxla3Ryb25payoqIG1lcnVwYWthbiBwZW5kb3JvbmcgdXRhbWEsIHBlcmx1IGRpcGVya3VhdCBkZW5nYW4gcHJvbW9zaSBkYW4gcGVuZ3VhdGFuIGthdGVnb3JpIHByb2R1ay4NCjIuICoqQmFuZHVuZyBzZWJhZ2FpIHBhc2FyIHRlcmt1YXQqKiBtZW51bmp1a2thbiBwb3RlbnNpIHVudHVrIHN0cmF0ZWdpIHBlbWFzYXJhbiBsb2thbC4gRm9rdXMgcGFkYSBtZXJldml0YWxpc2FzaSBwYXNhciBkaSBTdXJhYmF5YSBkYW4gSmFrYXJ0YSBqdWdhIHBlbnRpbmcuDQozLiAqKkRhdGEgbG9rYXNpIHRpZGFrIHRlcmNhdGF0KiogbWVudW5qdWtrYW4gYmFod2EgcGVybHUgYWRhbnlhIHBlbWJlbmFoYW4gZGFsYW0gcGVuZ3VtcHVsYW4gZGF0YSB1bnR1ayBoYXNpbCB5YW5nIGxlYmloIGJhaWsuDQo0LiAqKlRyZW4gcGVuanVhbGFuIGJ1bGFuYW4gbWVudW5qdWtrYW4gcGVtdWxpaGFuIHlhbmcgcG9zaXRpZioqIHNldGVsYWggYnVsYW4gRmVicnVhcmkgeWFuZyBsZW1haDsgcGF0dXQgZGljZXJtYXRpIGFnYXIgZGFwYXQgbWVtYW5mYWF0a2FuIG1vbWVudHVtIHBlbmp1YWxhbiB5YW5nIGt1YXQuDQoNCi0tLQ0KDQojIyMjIFZpc3VhbGlzYXNpIERhdGENCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpICANCmxpYnJhcnkoc2NhbGVzKSAgDQpsaWJyYXJ5KHZpcmlkaXMpICANCmxpYnJhcnkoZHBseXIpICANCmxpYnJhcnkoZm9yY2F0cykgIA0KbGlicmFyeShyZWFkcikgIA0KDQojIE1lbWJhY2EgZGF0YSAgDQpqYW51YXJpIDwtIHJlYWRfY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gSmFudWFyaS5jc3YiKSAgDQpmZWJydWFyaSA8LSByZWFkX2NzdigiZGF0YV9wZW5qdWFsYW5fa3VhcnRhbDFfZnVsbCAtIEZlYnJ1YXJpLmNzdiIpICANCm1hcmV0IDwtIHJlYWRfY3N2KCJkYXRhX3Blbmp1YWxhbl9rdWFydGFsMV9mdWxsIC0gTWFyZXQuY3N2IikgIA0KDQojIE1lbmdnYWJ1bmdrYW4gZGF0YSBwZW5qdWFsYW4gIA0KZGF0YV9wZW5qdWFsYW4gPC0gYmluZF9yb3dzKGphbnVhcmksIGZlYnJ1YXJpLCBtYXJldCkgIA0KDQojIDEuIFN0YW5kYXJpc2FzaSBGb3JtYXQgVGFuZ2dhbCAgDQpkYXRhX3Blbmp1YWxhbiA8LSBkYXRhX3Blbmp1YWxhbiAlPiUgIA0KICBtdXRhdGUoVGFuZ2dhbCA9IGFzLkRhdGUoVGFuZ2dhbCwgZm9ybWF0ID0gIiVZLSVtLSVkIikpICAjIFViYWggZm9ybWF0IHRhbmdnYWwgIA0KDQojIDIuIE1lbmd1YmFoIEtvbG9tIEhhcmdhIGRhbiBKdW1sYWgga2UgRm9ybWF0IE51bWVyaWsgIA0KZGF0YV9wZW5qdWFsYW4gPC0gZGF0YV9wZW5qdWFsYW4gJT4lICAgDQogIG11dGF0ZSggIA0KSGFyZ2EgPSBwYXJzZV9udW1iZXIoSGFyZ2EpLCAgIyBNZW5naGlsYW5na2FuIGthcmFrdGVyIG5vbi1udW1lcmlrIGRhcmkgSGFyZ2EgIA0KSnVtbGFoID0gYXMubnVtZXJpYyhKdW1sYWgpICAgICMgTWVuZ3ViYWggSnVtbGFoIGtlIG51bWVyaWMgIA0KICApICANCg0KIyAzLiBIaXR1bmcgVG90YWwgIA0KZGF0YV9wZW5qdWFsYW4gPC0gZGF0YV9wZW5qdWFsYW4gJT4lICANCiAgbXV0YXRlKFRvdGFsID0gSGFyZ2EgKiBKdW1sYWgpICANCg0KIyBNZW5naGl0dW5nIHRvdGFsIHBlbmp1YWxhbiBwZXIga2F0ZWdvcmkgIA0KcGVuanVhbGFuX2thdGVnb3JpIDwtIGRhdGFfcGVuanVhbGFuICU+JSAgDQogIGdyb3VwX2J5KEthdGVnb3JpKSAlPiUgIA0KICBzdW1tYXJpc2UoVG90YWxfUGVuanVhbGFuID0gc3VtKFRvdGFsLCBuYS5ybSA9IFRSVUUpKSAgDQoNCiMgTWVuZ2hpdHVuZyB0b3RhbCBwZW5qdWFsYW4gcGVyIGJ1bGFuICANCnBlbmp1YWxhbl9idWxhbmFuIDwtIGRhdGFfcGVuanVhbGFuICU+JSAgDQogIG11dGF0ZShCdWxhbiA9IGZvcm1hdChUYW5nZ2FsLCAiJUIiKSkgJT4lICANCiAgZ3JvdXBfYnkoQnVsYW4pICU+JSAgDQogIHN1bW1hcmlzZShUb3RhbF9QZW5qdWFsYW4gPSBzdW0oVG90YWwsIG5hLnJtID0gVFJVRSkpICANCg0KIyBHcmFmaWsgYmF0YW5nIHRvdGFsIHBlbmp1YWxhbiBwZXIga2F0ZWdvcmkgIA0KaWYgKCFpcy5udWxsKHBlbmp1YWxhbl9rYXRlZ29yaSkgJiYgbnJvdyhwZW5qdWFsYW5fa2F0ZWdvcmkpID4gMCkgeyAgDQogIGdncGxvdChwZW5qdWFsYW5fa2F0ZWdvcmksIGFlcyh4ID0gZmN0X3Jlb3JkZXIoS2F0ZWdvcmksIFRvdGFsX1Blbmp1YWxhbiksIHkgPSBUb3RhbF9QZW5qdWFsYW4pKSArICANCmdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gIiMwMDczQzJGRiIpICsgIA0KY29vcmRfZmxpcCgpICsgIA0KZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNjYWxlczo6ZG9sbGFyKFRvdGFsX1Blbmp1YWxhbikpLCBoanVzdCA9IC0wLjEsIHNpemUgPSAzLjUpICsgIA0KbGFicyh0aXRsZSA9ICJUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIiwgeCA9ICJLYXRlZ29yaSIsIHkgPSAiVG90YWwgUGVuanVhbGFuIikgKyAgDQp0aGVtZV9taW5pbWFsKCkgKyAgDQpzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSAgDQp9ICANCg0KIyBHcmFmaWsgbGluZ2thcmFuIHBlbmp1YWxhbiBwZXIgYnVsYW4gKGRvbnV0IGNoYXJ0KSAgDQppZiAoIWlzLm51bGwocGVuanVhbGFuX2J1bGFuYW4pICYmIG5yb3cocGVuanVhbGFuX2J1bGFuYW4pID4gMCkgeyAgDQogIHBlbmp1YWxhbl9idWxhbmFuIDwtIHBlbmp1YWxhbl9idWxhbmFuICU+JSAgIA0KbXV0YXRlKHByb3AgPSBUb3RhbF9QZW5qdWFsYW4gLyBzdW0oVG90YWxfUGVuanVhbGFuKSwgIA0KICAgICAgIHlwb3MgPSBjdW1zdW0ocHJvcCkgLSAwLjUgKiBwcm9wKSAgDQoNCiAgZ2dwbG90KHBlbmp1YWxhbl9idWxhbmFuLCBhZXMoeCA9IDIsIHkgPSBwcm9wLCBmaWxsID0gQnVsYW4pKSArICANCmdlb21fY29sKHdpZHRoID0gMSwgY29sb3IgPSAid2hpdGUiKSArICANCmNvb3JkX3BvbGFyKCJ5IikgKyAgDQpnZW9tX3RleHQoYWVzKHkgPSB5cG9zLCBsYWJlbCA9IHBhc3RlMChCdWxhbiwgIlxuIiwgcGVyY2VudChwcm9wKSkpLCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAzLjUpICsgIA0KdGhlbWVfdm9pZCgpICsgIA0KeGxpbSgwLjUsIDIuNSkgKyAgDQpsYWJzKHRpdGxlID0gIkRpc3RyaWJ1c2kgUGVuanVhbGFuIHBlciBCdWxhbiIpICsgIA0KdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAgDQp9ICANCg0KIyBHcmFmaWsgZ2FyaXMgdHJlbiBwZW5qdWFsYW4gaGFyaWFuICANCmlmICghaXMubnVsbChkYXRhX3Blbmp1YWxhbikgJiYgbnJvdyhkYXRhX3Blbmp1YWxhbikgPiAwKSB7ICANCiAgZGF0YV9wZW5qdWFsYW4gJT4lICANCmdyb3VwX2J5KFRhbmdnYWwpICU+JSAgDQpzdW1tYXJpc2UoVG90YWwgPSBzdW0oVG90YWwsIG5hLnJtID0gVFJVRSkpICU+JSAgDQpnZ3Bsb3QoYWVzKHggPSBUYW5nZ2FsLCB5ID0gVG90YWwpKSArICANCmdlb21fbGluZShjb2xvciA9ICIjMDBBRkJCIiwgc2l6ZSA9IDEpICsgIA0KZ2VvbV9wb2ludChjb2xvciA9ICIjRTdCODAwIiwgc2l6ZSA9IDEuNSkgKyAgDQpsYWJzKHRpdGxlID0gIlRyZW4gUGVuanVhbGFuIEhhcmlhbiIsIHggPSAiVGFuZ2dhbCIsIHkgPSAiVG90YWwgUGVuanVhbGFuIikgKyAgDQp0aGVtZV9taW5pbWFsKCkgIA0KfSAgDQoNCiMgSGVhdG1hcCBwZW5qdWFsYW4gaGFyaWFuIHBlciBrb3RhICANCmlmICghaXMubnVsbChkYXRhX3Blbmp1YWxhbikgJiYgbnJvdyhkYXRhX3Blbmp1YWxhbikgPiAwKSB7ICANCiAgZGF0YV9wZW5qdWFsYW4gJT4lICAgDQptdXRhdGUoSGFyaSA9IHdlZWtkYXlzKFRhbmdnYWwpLCAgDQogICAgICAgSGFyaSA9IGZhY3RvcihIYXJpLCBsZXZlbHMgPSBjKCJTZW5pbiIsICJTZWxhc2EiLCAiUmFidSIsICJLYW1pcyIsICJKdW1hdCIsICJTYWJ0dSIsICJNaW5nZ3UiKSkpICU+JSAgDQpncm91cF9ieShLb3RhLCBIYXJpKSAlPiUgICANCnN1bW1hcmlzZShUb3RhbF9IYXJpYW4gPSBzdW0oVG90YWwsIG5hLnJtID0gVFJVRSkpICU+JSAgIA0KZ2dwbG90KGFlcyh4ID0gSGFyaSwgeSA9IGZjdF9yZXYoS290YSksIGZpbGwgPSBUb3RhbF9IYXJpYW4pKSArICANCmdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpICsgIA0Kc2NhbGVfZmlsbF92aXJpZGlzKG9wdGlvbiA9ICJtYWdtYSIsIG5hbWUgPSAiVG90YWwiKSArICANCmxhYnModGl0bGUgPSAiSGVhdG1hcCBQZW5qdWFsYW4gSGFyaWFuIHBlciBLb3RhIiwgeCA9ICJIYXJpIiwgeSA9ICJLb3RhIikgKyAgDQp0aGVtZV9taW5pbWFsKCkgIA0KfSAgDQpgYGANCg0KDQojIyMjIFRvdGFsIFBlbmp1YWxhbiBwZXIgS2F0ZWdvcmkNCi0gKipJbnRlcnByZXRhc2kqKjoNCiAgLSBHcmFmaWsgbWVudW5qdWtrYW4gdG90YWwgcGVuanVhbGFuIHVudHVrIHNldGlhcCBrYXRlZ29yaSBwcm9kdWsuDQogIC0gS2F0ZWdvcmkgIk5BIiBtZW5jYWt1cCBuaWxhaSBwZW5qdWFsYW4gdGVydGluZ2dpIHNlYmVzYXIgKiokMTY4LDc2MiwwMTAqKiwgeWFuZyBtdW5na2luIG1lbnVuanVra2FuIG1hc2FsYWggZGFsYW0gZGF0YSBzZXBlcnRpIGthdGVnb3JpIHlhbmcgdGlkYWsgdGVyaXNpIGF0YXUgc2FsYWgga2xhc2lmaWthc2kuDQogIC0gRGkgYW50YXJhIGthdGVnb3JpIHlhbmcgdGVyaXNpLCAiRmFzaGlvbiIgbXVuY3VsIHNlYmFnYWkga2F0ZWdvcmkgZGVuZ2FuIHBlbmp1YWxhbiB0ZXJ0aW5nZ2kgKCoqJDIyNSwyNTksNzY4KiopLCBkaWlrdXRpIG9sZWggIkVsZWt0cm9uaWsiIGRlbmdhbiAqKiQyMTIsNzU2LDc3MCoqLCBkYW4gIkFrc2Vzb3JpcyIgZGVuZ2FuICoqJDMzKiouIEluaSBtZW51bmp1a2thbiBiYWh3YSBrYXRlZ29yaSBGYXNoaW9uIGRhbiBFbGVrdHJvbmlrIGFkYWxhaCBwZW5kb3JvbmcgdXRhbWEgcGVuanVhbGFuLg0KDQojIyMjIERpc3RyaWJ1c2kgUGVuanVhbGFuIHBlciBCdWxhbg0KLSAqKkludGVycHJldGFzaSoqOg0KICAtIERpYWdyYW0gZG9udXQgbWVudW5qdWtrYW4gcHJvcG9yc2kgcGVuanVhbGFuIGRhcmkgc2V0aWFwIGJ1bGFuLg0KICAtIEJ1bGFuIE1hcmV0IG1lbWlsaWtpIGtvbnRyaWJ1c2kgdGVydGluZ2dpIHNlYmVzYXIgKiozOC43JSoqLCBkaWlrdXRpIG9sZWggRmVicnVhcmkgKCoqMzUuNSUqKikgZGFuIEphbnVhcmkgKCoqMjAuOSUqKikuIEFwcmlsIG1hc2loIHJlbmRhaCBkZW5nYW4gKio0LjklKiouDQogIC0gR3JhZmlrIGluaSBtZW51bmp1a2thbiBiYWh3YSBwZW5qdWFsYW4gbWVuaW5na2F0IHNlY2FyYSBzaWduaWZpa2FuIGRpIGJ1bGFuIE1hcmV0LCB5YW5nIG11bmdraW4gdGVya2FpdCBkZW5nYW4gcHJvbW9zaSBhdGF1IG11c2ltYW4uDQoNCiMjIyMgVHJlbiBQZW5qdWFsYW4gSGFyaWFuDQotICoqSW50ZXJwcmV0YXNpKio6DQogIC0gR3JhZmlrIGdhcmlzIG1lbnVuanVra2FuIGZsdWt0dWFzaSB0b3RhbCBwZW5qdWFsYW4gaGFyaWFuIHNlcGFuamFuZyBidWxhbi4NCiAgLSBUZXJsaWhhdCBhZGFueWEgc3Bpa2UgcGVuanVhbGFuIHBhZGEgYmViZXJhcGEgdGFuZ2dhbCB0ZXJ0ZW50dSwgeWFuZyBiaXNhIGphZGkgYWtpYmF0IGthbXBhbnllIHBlbWFzYXJhbiBhdGF1IHBlbmF3YXJhbiBraHVzdXMuDQogIC0gS2VzdGFiaWxhbiBkaSBzZXBhbmphbmcgYnVsYW4gbWVudW5qdWtrYW4gdHJlbmQgeWFuZyB0aWRhayBrb25zaXN0ZW4sIGRhbiBhZGEgdGFuZ2dhbCBkZW5nYW4gcGVuanVhbGFuIHlhbmcgc2FuZ2F0IHRpbmdnaSBkaWJhbmRpbmdrYW4gZGVuZ2FuIHRhbmdnYWwgbGFpbm55YSwgeWFuZyBiaXNhIG1lbnVuanVra2FuIGFkYW55YSBkYXRhIGFub21hbHkgYXRhdSBwZXJpc3Rpd2EgdGVydGVudHUuDQoNCiMjIyMgIEhlYXRtYXAgUGVuanVhbGFuIEhhcmlhbiBwZXIgS290YQ0KLSAqKkludGVycHJldGFzaSoqOg0KICAtIEhlYXRtYXAgbWVudW5qdWtrYW4gdG90YWwgcGVuanVhbGFuIGhhcmlhbiB5YW5nIGRpa2Vsb21wb2trYW4gYmVyZGFzYXJrYW4ga290YS4NCiAgLSBUZXJkYXBhdCBiZWJlcmFwYSBuaWxhaSB5YW5nIHNhbmdhdCB0aW5nZ2kgdW50dWsga290YSBCYW5kdW5nIGRhbiBKYWthcnRhIGRhbGFtIHBlcmlvZGUgdGVydGVudHUgc2VtZW50YXJhIFN1cmFiYXlhIG1lbWlsaWtpIG5pbGFpIHBlbmp1YWxhbiB5YW5nIGxlYmloIHJlbmRhaC4NCiAgLSBXYXJuYSBnZWxhcCBtZW51bmp1a2thbiB0b3RhbCB5YW5nIGxlYmloIHRpbmdnaSwgc2VkYW5na2FuIHdpbGF5YWggZGVuZ2FuIHdhcm5hIHlhbmcgbGViaWggdGVyYW5nIG1lbnVuanVra2FuIHBlbmp1YWxhbiBsZWJpaCByZW5kYWguDQogIC0gUGVuZ2FtYXRhbiBpbmkgYmVyZ3VuYSB1bnR1ayBtZW1haGFtaSBkaSBtYW5hIHRpdGlrIGtla3VhdGFuIGRhbiBrZXNlbXBhdGFuIHRlcmRhcGF0IGRhbGFtIHBlbmp1YWxhbiBkaSBiZXJiYWdhaSBsb2thc2kuDQoNCiMjIyMgS2VzaW1wdWxhbg0KLSBLYXRlZ29yaSAqKkZhc2hpb24qKiBkYW4gKipFbGVrdHJvbmlrKiogYWRhbGFoIHBlbmRvcm9uZyB1dGFtYSBwZW5qdWFsYW4sIHNlbWVudGFyYSBhZGEgbWFzYWxhaCBkYWxhbSBkYXRhIHBlbmp1YWxhbiBrYXRlZ29yaSwgc2VwZXJ0aSAiTkEiLg0KLSBCdWxhbiBNYXJldCBhZGFsYWggeWFuZyBwYWxpbmcgcHJvZHVrdGlmIGRhbGFtIGtvbnRla3MgcGVuanVhbGFuLCBkZW5nYW4gYmFueWFrIGFrdGl2aXRhcyBwZW5qdWFsYW4gdGVyamFkaSBwYWRhIGhhcmktaGFyaSB0ZXJ0ZW50dS4NCi0gRGF0YSBkYXBhdCBkaWd1bmFrYW4gdW50dWsgbGViaWggbWVtYWhhbWkgcG9sYSBwZW1iZWxpYW4gZGFuIG1lbWJhbnR1IGRhbGFtIHBlcmVuY2FuYWFuIHN0cmF0ZWdpcyB1bnR1ayBrYW1wYW55ZSBkaSBtYXNhIGRlcGFuLCBiYWlrIGRhcmkgc2lzaSBwcm9kdWsgeWFuZyBkaXRhd2Fya2FuIG1hdXB1biBwZW5lbXBhdGFuIGdlb2dyYWZpcy4gDQoNCi0tLQ0KDQoNCg==