SUBJECT: eCommerce & Supply Chain


Versions: 24 Apr 2019, 29 Apr 2019, 03 May 2019, 15 May 2019, 06 Feb 2020.


Model Bisnis Olist

Olist adalah Brazilian department store (marketplace) yang beroperasi di segmen e-commerce, bukan e-commerce itu senderi (seperti yang dikatakan). Ini beroperasi sebagai perusahaan teknologi SaaS (Perangkat Lunak sebagai Layanan) Sejak tahun 2015. ini menawarkan solusi pasar (segment e-commerce) kepada pemilik toko dari semua ukuran (dan sebagian untuk segmen) Untuk meningkatkan penjualan mereka apakah mereka hadir secara online atau tidak.

Solusi Olist

Solusi olist terderi dari tiga aspek yaitu Perangkat Lunak, Kontrak dengan pasar utama, dan Berbagai Reputasi. Diagram dibawah ini menunjukkan bagaimana Olist menghubungkan pasar, konsumen (Portuguese: consumidores), dan pengecer (Portuguese: varejistas)

Olist’s marketplace model

Apa yang dikatan Olist?

Olist mengatakan dia…

  1. … adalah department store besar di pasar.
  2. … terhubung ke e-commerce utama Brazil.
  3. … tidak membeli produk.
  4. … tidak menyimpan produk dalam persediaan.
  5. … tidak melakukan pengeriman produk apa pun yang ditawarkan di tokonya.
  6. Semua produk di jual dan dikirimkan oleh ribuan pemilik toko (terdaftar di Olist*) yang menjual melalui Olist.
  7. Kekuatan terletak pada persatuan semua pemilik toko (terdaftar di Olist) yang menjual melalui Olist.
  8. Penjaga toko peserta yang bertanggung jawab untuk memisahkan, mengemas, dan membawa produk ke operator logistik.

Harap perhatikan perspektif Olist(Pertinjau rantai pasokan): dia menjelaskan ada banyak faktor yang dapat mempengaruhi penjualan penjaga toko, misalnya jenis produk, permintaan, musim, harga kompetitif, persyaratan, inventaris, dan lain-lain.

Pada gambar di bawah Olist menjelaskan (dalam bahasa Portugis) bagaiman ia membedakan dirinya dari pasar lain berdasarkan reputasi, penempatan produk, tim yang berdedikasi untuk penjualan & layanan pelanggan, pengurangan waktu untuk mulai menjual, kontrol terpusat dari operasi dan alat kompetitif lainya.

Olist’s niche — way to differentiate

Data Model

Di Kaggele, dia membagikan data 100 ribu pesanan dari 2016 hingga 2018. Ada 8+1 kumpulan data untuk di analysis. Model data telah dijelaskan pada gambar di bawah dan diatur dan dinormalisasi untuk setiap kategori.

Data Model

Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     

Attaching package: ‘kableExtra’

The following object is masked from ‘package:dplyr’:

    group_rows

Kumpulan Data Utama

Kumpulan data pesanan

  • Order ID (ID Pemasanan)
  • Customer ID (ID Pelanggan)
  • Order Status (Status Pemesanan)
  • Order Purchase Timestamp (Stempel Waktu Pembelian Pesanan)
  • Order Approved at (Pesanan Yang Disetujui)
  • Order Delivered Carrier date (Pesanan Dikirim Tanggal Pembawa)
  • Order Delivered Customer date (Pesanan Dikirim Tanggal Pelanggan)
  • Order Estimated delivered date (Pesanan Perkiraan Tanggal Pengeriman)
Orders dataset
order_id customer_id order_status order_purchase_timestamp order_approved_at order_delivered_carrier_date order_delivered_customer_date order_estimated_delivery_date
e481f51cbdc54678b7cc49136f2d6af7 9ef432eb6251297304e76186b10a928d delivered 2017-10-02 10:56:33 2017-10-02 11:07:15 2017-10-04 19:55:00 2017-10-10 21:25:13 2017-10-18 00:00:00
53cdb2fc8bc7dce0b6741e2150273451 b0830fb4747a6c6d20dea0b8c802d7ef delivered 2018-07-24 20:41:37 2018-07-26 03:24:27 2018-07-26 14:31:00 2018-08-07 15:27:45 2018-08-13 00:00:00
47770eb9100c2d0c44946d9cf07ec65d 41ce2a54c0b03bf3443c3d931a367089 delivered 2018-08-08 08:38:49 2018-08-08 08:55:23 2018-08-08 13:50:00 2018-08-17 18:06:29 2018-09-04 00:00:00
949d5b44dbf5de918fe9c16f97b45f8a f88197465ea7920adcdbec7375364d82 delivered 2017-11-18 19:28:06 2017-11-18 19:45:59 2017-11-22 13:39:59 2017-12-02 00:28:42 2017-12-15 00:00:00
ad21c59c0840e6cb83a9ceb5573f8159 8ab97904e6daea8866dbdbc4fb7aad2c delivered 2018-02-13 21:18:39 2018-02-13 22:20:29 2018-02-14 19:46:34 2018-02-16 18:17:02 2018-02-26 00:00:00
a4591c265e18cb1dcee52889e2d8acc3 503740e9ca751ccdda7ba28e9ab8f608 delivered 2017-07-09 21:57:05 2017-07-09 22:10:13 2017-07-11 14:58:04 2017-07-26 10:57:55 2017-08-01 00:00:00

Kumpulan Data lainya

Dataset Pelanggan

  • Customer ID (ID Pelanggan )
  • Customer Unique ID (ID Unik Pelanggan)
  • Customer Zip Code prefix (Awalan Kode Pos Pelanggan)
  • Customer City (Kota Pelanggan)
  • Customer State (Negari Pelanggan)
Customers dataset
customer_id customer_unique_id customer_zip_code_prefix customer_city customer_state
06b8999e2fba1a1fbc88172c00ba8bc7 861eff4711a542e4b93843c6dd7febb0 14409 franca SP
18955e83d337fd6b2def6b18a428ac77 290c77bc529b7ac935b93aa66c333dc3 9790 sao bernardo do campo SP
4e7b3e00288586ebd08712fdd0374a03 060e732b5b29e8181a18229c7b0b2b5e 1151 sao paulo SP
b2b6027bc5c5109e529d4dc6358b12c3 259dac757896d24d7702b9acbbff3f3c 8775 mogi das cruzes SP
4f2d8ab171c80ec8364f7c12e35b23ad 345ecd01c38d18a9036ed96c73b8d066 13056 campinas SP
879864dab9bc3047522c92c82e1212b8 4c93744516667ad3b8f1fb645a3116a4 89254 jaragua do sul SC

Kumpulan Data Geolokasi

  • Geolocation Zip Code prefix (Awalan Kode Pos Geolokasi)
  • Geolocation Lat. (Geolokasi Lat)
  • Geolocation Lng. (Geolokasi Lng)
  • Geolocation City (Kota Geolokasi)
  • Geolocation State (Status Geolokasi)
Geolocation dataset
geolocation_zip_code_prefix geolocation_lat geolocation_lng geolocation_city geolocation_state
1037 -23.54562 -46.63929 sao paulo SP
1046 -23.54608 -46.64482 sao paulo SP
1046 -23.54613 -46.64295 sao paulo SP
1041 -23.54439 -46.63950 sao paulo SP
1035 -23.54158 -46.64161 sao paulo SP
1012 -23.54776 -46.63536 são paulo SP

Kumpulan Data Item

  • Order ID (ID Pemesanan)
  • Order Item ID (ID barang Pesanan)
  • Seller ID (Tanggal Batas Pengeriman)
  • Shipping limit date (Tanggal Batas Pengeriman)
  • Price (Harga)
  • Freight Value (Nilai Pengiriman)
Items dataset
order_id order_item_id product_id seller_id shipping_limit_date price freight_value
00010242fe8c5a6d1ba2dd792cb16214 1 4244733e06e7ecb4970a6e2683c13e61 48436dade18ac8b2bce089ec2a041202 2017-09-19 09:45:35 58.90 13.29
00018f77f2f0320c557190d7a144bdd3 1 e5f2d52b802189ee658865ca93d83a8f dd7ddc04e1b6c2c614352b383efe2d36 2017-05-03 11:05:13 239.90 19.93
000229ec398224ef6ca0657da4fc703e 1 c777355d18b72b67abbeef9df44fd0fd 5b51032eddd242adc84c38acab88f23d 2018-01-18 14:48:30 199.00 17.87
00024acbcdf0a6daa1e931b038114c75 1 7634da152a4610f1595efa32f14722fc 9d7a1d34a5052409006425275ba1c2b4 2018-08-15 10:10:18 12.99 12.79
00042b26cf59d7ce69dfabb4e55b4fd9 1 ac6c3623068f30de03045865e4e10089 df560393f3a51e74553ab94004ba5c87 2017-02-13 13:57:51 199.90 18.14
00048cc3ae777c65dbb7d2a0634bc1ea 1 ef92defde845ab8450f9d70c526ef70f 6426d21aca402a131fc0a5d0960a3c90 2017-05-23 03:55:27 21.90 12.69

Kumpulan Data Pembayaran

  • Order ID (ID Pemesanan
  • Payment Sequential (Urutan Pembayaran)
  • Payment Type (Tipe Pembayaran)
  • Payment Installments (Angsuran Pembayaran)
  • Payment Value (Nilai Pembayaran)
Payments dataset
order_id payment_sequential payment_type payment_installments payment_value
b81ef226f3fe1789b1e8b2acac839d17 1 credit_card 8 99.33
a9810da82917af2d9aefd1278f1dcfa0 1 credit_card 1 24.39
25e8ea4e93396b6fa0d3dd708e76c1bd 1 credit_card 1 65.71
ba78997921bbcdc1373bb41e913ab953 1 credit_card 8 107.78
42fdf880ba16b47b59251dd489d4441a 1 credit_card 2 128.45
298fcdf1f73eb413e4d26d01b25bc1cd 1 credit_card 2 96.12

Kumpulan Data Produk

  • Product ID (ID Produk)
  • Product Category name (Nama Kategori Produk)
  • Product Name length (Nama Produk Panjang)
  • Product Photos (quantity) (Foto produk(jumlah))
  • Product Weight (grams) (Berat Produk(gram))
  • Product Length (cm) (Panjang Produk(cm))
  • Product Height (cm) (Tinggi Produk(cm))
  • Product Width (cm) (Lebar Produk(cm))
Products dataset
product_id product_category_name product_name_lenght product_description_lenght product_photos_qty product_weight_g product_length_cm product_height_cm product_width_cm
1e9e8ef04dbcff4541ed26657ea517e5 perfumaria 40 287 1 225 16 10 14
3aa071139cb16b67ca9e5dea641aaa2f artes 44 276 1 1000 30 18 20
96bd76ec8810374ed1b65e291975717f esporte_lazer 46 250 1 154 18 9 15
cef67bcfe19066a932b7673e239eb23d bebes 27 261 1 371 26 4 26
9dc1a7de274444849c219cff195d0b71 utilidades_domesticas 37 402 4 625 20 17 13
41d3672d4792049fa1779bb35283ed13 instrumentos_musicais 60 745 1 200 38 5 11

Ulasan Kumpulan Data

  • Review ID
  • Order ID (ID Pemesanan)
  • Review Score (Skor Ulasan)
  • Review Comment title (Tinjau Komentar Judul)
  • Review Comment message (Tinjau Pesanan Komentar)
  • Review Creation date (Tinjau Tanggal Pembuatan)
  • Review Answer timestamp (Tinjau Stempel Waktu Jawaban)
Reviews dataset
review_id order_id review_score review_comment_title review_comment_message review_creation_date review_answer_timestamp
7bc2406110b926393aa56f80a40eba40 73fc7af87114b39712e6da79b0a377eb 4 2018-01-18 00:00:00 2018-01-18 21:46:59
80e641a11e56f04c1ad469d5645fdfde a548910a1c6147796b98fdf73dbeba33 5 2018-03-10 00:00:00 2018-03-11 03:05:13
228ce5500dc1d8e020d8d1322874b6f0 f9e4b658b201a9f2ecdecbb34bed034b 5 2018-02-17 00:00:00 2018-02-18 14:36:24
e64fb393e7b32834bb789ff8bb30750e 658677c97b385a9be170737859d3511b 5 Recebi bem antes do prazo estipulado. 2017-04-21 00:00:00 2017-04-21 22:02:06
f7c4243c7fe1938f181bec41a392bdeb 8e6bfb81e283fa7e4f11123a3fb894f1 5 Parabéns lojas lannister adorei comprar pela Internet seguro e prático Parabéns a todos feliz Páscoa 2018-03-01 00:00:00 2018-03-02 10:26:53
15197aa66ff4d0650b5434f1b46cda19 b18dcdf73be66366873cd26c5724d1dc 1 2018-04-13 00:00:00 2018-04-16 00:39:37

Kumpulan Data Penjual

  • Seller ID (ID Penjualan)
  • Seller Zip Code prefix (Awalan Kode Pos Penjual)
  • Selller City (Kota Penjual)
  • Seller State (Negara Penjual)
Sellers dataset
seller_id seller_zip_code_prefix seller_city seller_state
3442f8959a84dea7ee197c632cb2df15 13023 campinas SP
d1b65fc7debc3361ea86b5f14c68d2e2 13844 mogi guacu SP
ce3ad9de960102d0677a81f5d0bb7b2d 20031 rio de janeiro RJ
c0f3eea2e14555b6faeea3dd58c1b1c3 4195 sao paulo SP
51a04a8a6bdcb23deccc82b0b80742cf 12914 braganca paulista SP
c240c4061717ac1806ae6ee72be3533b 20920 rio de janeiro RJ

Dataset Terjemahaan Kategori Produk

  • Product Category name (Portugis) (Nama Kategori Produk Portugis)
  • Product Category name (English) (Nama Kategori Produk bahasa Inggris)
Translation dataset
product_category_name product_category_name_english
beleza_saude health_beauty
informatica_acessorios computers_accessories
automotivo auto
cama_mesa_banho bed_bath_table
moveis_decoracao furniture_decor
esporte_lazer sports_leisure

Stimulasi sebagai ƒ(Pelanggan, Kategori Produk, Penjual)

Olist telah dirancang dengan penambahan pelanggan, Kategori Produk, dan Penjualan sesuai data, ada aliran pelanggan dan penjual yang terdaftar di platform Olist. Kemajuan ini, sering dengan peningkatan reguler dalam jumlah kategori produk baru yang ditawarkan telah mempertahankan momentum pertumbuhan olist

Trend Pendaftaran Pelanggan Baru

Grafik menunjukkan, pada tahun 2017, telah terjadi trend line positef dalam jumlah Pelanggan Baru [Identitas Unik Pelanggan] yang terdaftar di Olist. Pada tahun 2018, lebih dari 6000 ribu mendaftar setiap bulan.

Galvanisation Berdasarkan Kategori Produk

Menurut pendapat saya, penambahan +50 (Perkiraan) Kategori Produk Baru Per Bulan - Sebagai Penawaran - telah mengembangkan lonjakan pelanggan baru yang mendaftar. Konsinten fenome ini menjadi bauh bibir Olist selama 20 bulan yakni sejak Januari 2017 hingga Agustus 2018.

Keterlibatan Penjual

Penjual juga mempertahankan tren yang sama dengan pelanggan, dalam kerangka waktu data ini, Olist akhirnya memiliki + 3095 Penjual terdaftar di platformnya.

Kategori Produk FAST MOVING

Kategori Produk dapat diukur dari seberapa sering suatu kategori produk dibeli oleh pelanggan? atau manakah kategori produk “FAST MOVING” yang didorong oleh pelanggan? Kernel Informasi ini dapat bertindak sebagai salah satu parameter yang mungkin yang mungkin digunakan oleh perusahaan (dan dalam hal ini Olisst) Untuk membagun portofolio.

Model data ini memiliki informasi 100 ribu pesanan oleh karena itu, dengan mengambil petunjuk dari distribusi data kuartil, saya membaginya lebih lanjut menjadi 6 sub bagian. ini membantu saya menentukan secara visual (dalam bentuk tidak ilmiah) Kategori produk mana yang bergerak cepat sesuai dengan setiap sub-bagian.

Pembelian Dilakukan Beberapa Kali

Mari kita mulai dengan kasus di mana semua kategori Produk dibeli beberapa kali. Grafik di bawah ini menunjukkan kategori mana yang merupakan kategori frekuensi tinggi.

Harap Dicatat: Ini tidak termasuk semua kategori yang dibeli sebagai: satu kategori produk perbulan dan pertahun.

Enam Sub - Bagian

Satu Pesanan Per Kategori Produk

Kasus di mana hanya satu pesanan yang dilakukan untuk satu Kategori produk dalam satu bulan dan pada tahun tertentu.

Dibeli “1 < n < 6” Kali

Kasus di mana Pesanan dilakukan untuk berbagai Kategori Produk dan setiap Kategori produk dibeli Lebih dari selai tetapi kurang dari enam kali. Plus, daftar di bawah ini menyediakan beberapa kategori yang paling sering dipesan.

  • Construction Tools (Alat Konstruksi)
  • Cine Photo (Foto Film)
  • DVDs Blue Ray (DVD Blue Ray)
  • Fashion Female Clothing (Busana Wanita Fashion)
  • Music (Musik)

Dibeli “5 < n < 21” Kali

Kasus dimana pesanan ditempatkan untuk berbagai kategori produk dan setiap kategori produk dibeli lebih dari 5 tetapi kurang dari 21 kali. Plus, daftar di bawah ini menyediakan beberapa kategori yang paling sering dipesan.

  • Air Conditioning (AC)
  • Construction tools Garden (Alat Konstruksi Taman)
  • Fixed Telephony (Telepon Tetap)
  • Home Appliances 2 (Perlatan Rumah Tangga 2)
  • Market Place (Pasar)

Dibeli “20 < n < 93” kali

Kusus dimana pesanan ditemapatkan untuk berabagai kategori produk dan setiap kategori produk debeli Lebih dari dua puluh tetapi kurang dari sembilan puluh tiga kali. Plus, daftar di bawah ini menyediakan beberapa kategori yang paling sering dipesan.

  • Books general interest (Buku Minat Umum)
  • Console games (Game Konsol)
  • Home appliances (Peralatan Rumah Tangga)
  • Luggage accessories (Aksesoris Bagasi)
  • Musical instruments (Alat-alat Musik)
  • Small appliances (Perlatan Kecil)

Dibeli Waktu “92 < n < 251” Kali

Kasus dimana pesanan ditempatkan untuk berbagai kategori produk dan setiap kategori produk dibeli lebih dari sembilan puluh dua tetapi kurang dari dua ratus lima puluh satu kali. Plus, daftari dibawah ini menyediakan beberapa kategori yang paling sering dipesan.

  • Baby (Baby)
  • Cool stuff (Barang Keren)
  • Garden tools (Peralatan Kebun)
  • Perfumery (Wewangian)
  • Toys (Mainan)

Dibeli “250 < n” Kali

Kasus dimana pesanan ditempatkan untuk berbagai kategori produk dan setiap kategori produk dibeli lebih dari dua ratus lima puluh kali. Plus, daftar dibawah ini menyediakan beberapa kategori yang paling sering dipesan.

  • Bed bath table (Meja Kamar Mandi Tempat Tidur)
  • Computer accessories (Aksesoris Komputer)
  • Furniture decor (Dekorasi Furnitur)
  • Health beauty (Kencatikan Kesehatan)
  • Housewares (Perlatan Rumah Tangga)
  • Sports leisure (Olahraga Rekresi)

Fitur, Relasi, & Persamaan Penting

k-means clustering telah digunakan untuk membuat cluster dan menemukan fitur yang signifikan, ini membantu saya melihat kedalam; bagaimana fitur-fitur itu berinteraksi dan apa hubungan di antara mereka? Cluster dibuat untuk melihat data dalam bentuk tabel dan untuk menemukan persamaan polinomial.

k - means Clustering

Tidak ada metode ilmiah yang digunakan untuk menghitung jumlah cluster, saya memasang 6 sebagai jumlah pusat, untuk menjaga agar semuanya tetap bernomor. pertama, sebuah tabel besar telah dibuat yang berisi semua fitur yang relevan dari semua kumpulan data (Setidaknya dari sudut pandang analysis saya). Saya melakukan berbagai premutasi dan kombinasi untuk menghasilkan fitur paling signifikan yang dapat mempertahankan jumlah tupel yang kira-kira sama di setiap cluster. Latihan ini memberi saya fitur berikut, yang nilainya pertama kali dinormalisasi dan kemudian mereka bertidak sebagai tulang punggung kluster saya.

  • Waktu Led Aktual (hari): Jumlah hari yang dibutuhkan untuk mengerimkan produk ke pelanggan, dari saat pesanan telah ditempatkan di sistem.
  • ID Pesanan: Identifikasi Pesanan.
  • Waktu Perstujuan (menit): Waktu yang dibutuhkan oleh sistem Olist untuk menyetujui pesanan setelah pesanan dilakukan dan sebelum diberitahukan kepada pemasok/pengangkut barang.
  • ID Barang Pesanan: Jumlah barang/pesanan.
  • Harga: Harga/Barang, dibebankan dari pelanggan.
  • Nilai Pengeriman: Biaya Pengeriman/Barang, dibebankan dari pelanggan.
  • Berat Produk (gms): Berat Produk dalam Gram

Harap Dicatat: Harga & Nilai Pengeriman adalah jumlah yang dibebankan per item dan bukan per pesanan. Plus, Pesanan mungkin memiliki lebih dari satu item.

Cluster 1

Factors for k-means clustering & their values
Factor 01
Factor 02
Factor 03
Cluster Quarter Actual Lead Time (days) Approval (mins) Itmes per Order Price Freight Value Weight (gms)
Year 2016
Cluster1 2016.4 18 686.5 1 238.48 34.22 10475
Year 2017
Cluster1 2017.1 12 12.0 1 129.00 29.03 9850
Cluster1 2017.2 12 15.0 1 134.08 31.12 9750
Cluster1 2017.3 11 16.0 1 159.99 28.59 10125
Cluster1 2017.4 14 22.0 1 149.90 33.25 10700
Year 2018
Cluster1 2018.1 16 21.0 1 149.00 30.40 10800
Cluster1 2018.2 10 31.0 1 169.90 33.31 10800
Cluster1 2018.3 8 20.0 1 179.90 44.25 10550
Note:
Values :: 1 Only MEDIANs per quarter per factor are stated
Order Status :: a Orders delivered

Cluster 2

Factors for k-means clustering & their values
Factor 01
Factor 02
Factor 03
Cluster Quarter Actual Lead Time (days) Approval (mins) Itmes per Order Price Freight Value Weight (gms)
Year 2016
Cluster2 2016.4 20 1772.0 1 59.9 15.98 610
Year 2017
Cluster2 2017.1 11 1836.5 1 49.0 15.05 450
Cluster2 2017.2 12 1718.0 1 59.9 15.50 550
Cluster2 2017.3 11 1728.0 1 59.9 15.50 600
Cluster2 2017.4 13 1919.5 1 59.9 15.35 550
Year 2018
Cluster2 2018.1 14 1693.0 1 60.0 15.60 500
Cluster2 2018.2 9 1682.0 1 69.0 16.68 550
Cluster2 2018.3 7 1629.0 1 66.9 18.15 475
Note:
Values :: 1 Only MEDIANs per quarter per factor are stated
Order Status :: a Orders delivered

Cluster 3

Factors for k-means clustering & their values
Factor 01
Factor 02
Factor 03
Cluster Quarter Actual Lead Time (days) Approval (mins) Itmes per Order Price Freight Value Weight (gms)
Year 2016
Cluster3 2016.4 16 4581.5 1 72.40 15.08 1000
Year 2017
Cluster3 2017.1 13 5223.0 1 49.98 15.05 500
Cluster3 2017.2 13 4746.5 1 61.95 16.05 600
Cluster3 2017.3 12 4764.0 1 59.90 15.79 600
Cluster3 2017.4 15 4629.0 1 59.90 16.11 600
Year 2018
Cluster3 2018.1 14 4755.0 1 63.90 16.11 600
Cluster3 2018.2 10 4833.5 1 63.99 16.45 650
Cluster3 2018.3 9 4796.0 1 53.90 18.32 500
Note:
Values :: 1 Only MEDIANs per quarter per factor are stated
Order Status :: a Orders delivered

Cluster 4

Factors for k-means clustering & their values
Factor 01
Factor 02
Factor 03
Cluster Quarter Actual Lead Time (days) Approval (mins) Itmes per Order Price Freight Value Weight (gms)
Year 2016
Cluster4 2016.3 54.0 0.0 2 44.99 2.83 1000.0
Year 2017
Cluster4 2016.4 15.5 83.5 1 64.40 15.95 864.5
Cluster4 2017.1 9.0 10.0 1 62.90 15.56 600.0
Cluster4 2017.2 10.0 12.0 1 64.99 15.11 550.0
Cluster4 2017.3 9.0 14.0 1 59.90 15.20 600.0
Year 2018
Cluster4 2017.4 11.0 16.0 1 62.80 15.15 550.0
Cluster4 2018.1 12.0 16.0 1 59.90 15.23 450.0
Cluster4 2018.2 8.0 21.0 1 66.67 15.72 500.0
Cluster4 2018.3 6.0 14.0 1 65.49 16.44 450.0
Note:
Values :: 1 Only MEDIANs per quarter per factor are stated
Order Status :: a Orders delivered

Cluster 5

Factors for k-means clustering & their values
Factor 01
Factor 02
Factor 03
Cluster Quarter Actual Lead Time (days) Approval (mins) Itmes per Order Price Freight Value Weight (gms)
Year 2016
Cluster5 2016.4 40 440.0 1 499.99 93.23 20900
Year 2017
Cluster5 2017.1 11 10.5 1 199.99 49.94 20275
Cluster5 2017.2 11 18.0 1 239.90 50.77 20800
Cluster5 2017.3 12 17.5 1 219.99 57.38 19600
Cluster5 2017.4 14 23.0 1 249.44 59.91 19300
Year 2018
Cluster5 2018.1 17 23.0 1 229.99 53.48 18150
Cluster5 2018.2 11 27.0 1 235.90 66.40 18950
Cluster5 2018.3 8 112.0 1 395.00 77.10 19700
Note:
Values :: 1 Only MEDIANs per quarter per factor are stated
Order Status :: a Orders delivered

Cluster 6

Factors for k-means clustering & their values
Factor 01
Factor 02
Factor 03
Cluster Quarter Actual Lead Time (days) Approval (mins) Itmes per Order Price Freight Value Weight (gms)
Year 2016
Cluster6 2016.4 25 1201 1 129.99 21.97 5470.0
Year 2017
Cluster6 2017.1 10 11 1 139.00 22.29 5150.0
Cluster6 2017.2 11 14 1 117.30 19.75 5600.0
Cluster6 2017.3 10 16 1 139.40 20.10 5300.0
Cluster6 2017.4 12 20 1 129.00 22.72 5950.0
Year 2018
Cluster6 2018.1 13 19 1 135.00 21.89 5700.0
Cluster6 2018.2 9 25 1 129.00 23.31 5450.0
Cluster6 2018.3 7 20 1 139.90 27.59 5562.5
Note:
Values :: 1 Only MEDIANs per quarter per factor are stated
Order Status :: a Orders delivered

Interpretabilitas hubungan

Di bagian ini, upaya saya adalah untuk melihat hubungan antara Nilai Pengeriman Per Pesanan Yang dibayar pelanggan dan Jumlah Barang Per Pesanan. Sekarang untuk menafsirkan hubungan ini saya menggunakan Persamaan Regresi, terutama yang dapat membantuu dalam inferensi dan jauh lebih dapat ditafsirkan, Saya telah memilih Persamaan Kuasi-Poisson - Karean disini kita melihat data hitungan dan Persamaan Polinomial - sebagai upaya umum (Tanpa uji tuntas pada akurasi atau pembuatan model).

Mari kita mulai dengan Grafik terlebih dahulu: Grafik ini adalah (Trade-Off antara Fleksibilitas dan Interpretabilltas) maka persamaan saya rendah pada fleksibilitas atau akurasi dan relatif tinggi pada interpretasi - seperti yang ditunjukkan oleh status Gray POINT Pada grafik.

[Perlu Dicatat] Saya tidak menunjukkan interval kepercayaan untuk parameter model dan grafik residual untuk menentukan apakah model cocok atau tidak.

Data Lengkap

Itu \(\frac{\text{Penyimpangan Sisa}}{\text{Derajat Kebebasan}} > 1 \text{ atau} \text{ } \frac{\text{Variance}}{\text{Mean}} \neq 1\) for Poisson Regression beraada di 7.772, jadi mungkin ada overdispersi. Kami menyesuaikan untuk memperhitungkan overdispersi dan menggunakan Quasi-Poisson Regression Persamaan.

Quasi-Poisson: regression equation

\[\text{Angkutan Nilai} \approx 3.037 - 0.0357x + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]

Interpretasi: Prediktor signifikan sebagai nilai-p \(\approx\) NOL, Parameter Dispersi untuk Quasi-Poisson keluarga diambil pada 12.387. itu \(\beta = -0.0357\) atau \(\beta < 0\) menyeritkan dengam Setiap Kenaikan Unit Item per pesanan nilai pengeriman akan berkurang dengan dan akan dikalikan dengan -0.0357.

Jika kita mengambil 8 parameter berbeda untuk menentukan Nilai Freight kemudian menggunakan Quasi-Poisson regression - Prediktor berikut signifikan dengan nilai \(\approx\) NOL:

  • Intercept (Mencegat)
  • Number of Items per order (Jumlah Item Per Pesanan)
  • Price (Harga)
  • Estimated lead time (Perkiraan Waktu Tunggu)
  • Actaul lead time (Waktu Tunggu Aktual)
  • Product’s Weight (g) (Berat Produk)
  • Product’s Length (cm) (Panjang Produk)
  • Product’s Height (cm) (Tinggi Produk)
  • Product’s Width (cm) (Lebar Produk)

…dan terkahir jarak belum diperhintungkan.

NB: - coret paramter yang tidak-singnigkan. kode dapat diperoleh dari bagian ‘kode’.


Polynomial: regression equation

\[\text{Angkutan Nilai} \approx 19.98 - 152.50x + 44.46x^2 - 79.47x^3 + 77.62x^4 + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per order}, \text{ } \epsilon \Rightarrow \text{error}\]


Persamaan Klater 1

Itu \(\frac{\text{Penyimpanan Sisa}}{\text{Derajat Kebebasan}} > 1 \text{ atau} \text{ } \frac{\text{Variance}}{\text{Mean}} \neq 1\) for Poisson Regression berada di 3.207, Jadi mungkin ada oversipersi, Kami menyesuaikan untuk memperhitungkan overdispersidan menggunakan Quasi-Poisson Regression Persamaan.

Quasi-Poisson: regression Persamaan

\[\text{Nilai Pengiriman}_\text{ Cluster 1} \approx 2.830 - 0.037x + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Peroder}, \text{ } \epsilon \Rightarrow \text{error}\]

Interpretasi: Prediktor signifikan sebagai nilai-p \(\approx\) NOL, Parameter Dispersi untuk Quasi-Poisson keluarga diambil menjadi 3.984. itu \(\beta = -0.037\) atau \(\beta < 0\) menyeritkan dengan setiap kenaikan unit barang per pesanan nilai pengeriman akan berkurang dan akan dikalikan dengan -0.037.

Jika kita mengambil 8 parameter berbeda untuk menentukan Nilai Freight kemudian menggunakan Quasi-Poisson regression - prediktor berikut signifikan dengan nilai -p \(\approx\) NOL:

  • Intercept (Mencegat)
  • Number of Items per order (Jumlah Item Per Pesanan)
  • Price (Harga)
  • Estimated lead time (Perkiraan Waktu Tunggu)
  • Actaul lead time (waktu Tunggu Aktual)
  • Product’s Weight (g) (Berat Produk)
  • Product’s Length (cm) (Panjang Produk)
  • Product’s Height (cm) (Tinggi Produk)
  • Product’s Width (cm) (Lebar Produk)

…dan terkahir jark belum diperhitungkan.

NB: - Coret Paramater yang tidak signifikan. Kode dapat diperoleh dari bagian ’Kode.


Polynomial: regression persamaan

\[\text{Nilai Pengeriman}_\text{ Cluster 1} \approx 16.22 - 96.55x - 20.80x^3 + 29.69x^4 - 20.78x^5 + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]


Persamaan Klaster 2

Itu \(\frac{\text{Penyimpanan Sisa}}{Derajat Kebebasan} > 1 \text{ atau} \text{ } \frac{\text{Variance}}{\text{Mean}} \neq 1\) for Poisson Regression berada di 3.528, Jadi mungkin ada overdispersi. Kami menyesuaikan untuk memperhitungkan overdispersi dan menggunakan Quasi-Poisson Regression persamaan.

Quasi-Poisson: regression Persamaan

\[\text{Nilai Pengeriman}_\text{ Cluster 2} \approx 2.867 - 0.018x + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Perorder}, \text{ } \epsilon \Rightarrow \text{error}\]

Interpretasi: Prediktor signifikan sebagai nilai-p \(\approx\) NOL, parameter Dsipersi untuk Quasi-Poisson keluarga di ambil pada 4.204. Itu \(\beta = -0.018\) atau \(\beta < 0\) emnyiratkan dengan setiap kenaikan unit Item perpesanan nilai pengeriman akan berkurang dan akan dikalikan dengan -0.018.

Jika kita mengambil 8 paramter berbeda untuk menentukan Nilai Freight kemudian menggunakan Quasi-Poisson regression - Prediktor berikut signifikan dengan nilai -p \(\approx\) NOL:

  • Intercept (Mencegat)
  • Number of Items per order (Jumlah item perpesanan)
  • Price (Harga)
  • Estimated lead time (Periraan Waktu Tunggu)
  • Actaul lead time (Waktu Tunggu Aktual)
  • Product’s Weight (g) (Berat Produk)
  • Product’s Length (cm) (Panjang Produk)
  • Tinggi Produk (cm)
  • Lebar Produk (cm)

…dan terkakhir jarak belum diperhitungkan.

NB: - coret adalah paramter yang tidak signigikan. kode dapat diperoleh dari bagian ‘kode’.


Polynomial: regression equation

\[\text{Nilai Pengriman}_\text{ Cluster 2} \approx 17.14 - 34.91x + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]


Persamaan Kluster 3

Itu \(\frac{\text{Penyimpanan Sisa}}{Derajat Kebebasan} > 1 \text{ atau} \text{ } \frac{\text{Variance}}{\text{Mean}} \neq 1\) for Poisson Regression berada di 35.237, Jadi mungkin ada overdispersi. Kami menyesuaikan untuk memperhitungkan overdispersi dan menggunakan Quasi-Poisson Regression persamaan

Quasi-Poisson: regression Persamaan`

\[\text{Nilai Pengeriman}_\text{ Cluster 3} \approx 4.525 - 0.032x + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]

Interpretasi: Prediktor signifikan sebagai nilai-p \(\approx\) NOL, parameter Dsipersi untuk Quasi-Poisson keluarga di ambil pada 38.974. Itu \(\beta = -0.032\) atau \(\beta < 0\) emnyiratkan dengan setiap kenaikan unit Item perpesanan nilai pengeriman akan berkurang dan akan dikalikan dengan -0.018.

Jika kita mengambil 8 paramter berbeda untuk menentukan Nilai Freight kemudian menggunakan Quasi-Poisson regression - Prediktor berikut signifikan dengan nilai -p \(\approx\) NOL:

  • Intercept (Mencegat)
  • Jumlah Item Per Pesanan
  • Price (Harga)
  • Estimated lead time (Pekiraan waktu Tunggu)
  • Waktu tunggu aktual
  • Berat Produk (g)
  • Product’s Length (cm) (Panjang Produk)
  • Product’s Height (cm) (Tinggi Produk)
  • Product’s Width (cm) (Lebar Produk)

…dan terakhir jarak belum diperhitungkan.

NB: - coret parameter yang tidak signifikan kode dapat diperoleh dari bagian ‘kode’.


Polynomial: regression equation

\[\text{Nilai Pengiriman}_\text{ Cluster 3} \approx 89.06 + \epsilon \]

\[ \epsilon \Rightarrow \text{error} \]


Persamaan Cluster 4

itu \(\frac{\text{Penyimpangan Sisa}}{\text{Derajat Kebebasan}} > 1 \text{ or} \text{ } \frac{\text{Variance}}{\text{Mean}} \neq 1\) untuk Poisson Regression berada di 18.649, jadi mungkin ada overdispersi. Kami menyesuaikan untuk memperhitungkan overdispersi dan menggunakan Quasi-Poisson Regression persamaan.

Quasi-Poisson: regression persamaan

\[\text{Nilai Pengeriman}_\text{ Cluster 4} \approx 3.964 - 0.028x + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]

Interpretasi: Prediktor signifikan sebagai nilai-p \(\approx\) NOL, parameter Dsipersi untuk Quasi-Poisson keluarga di ambil pada 23.213. Itu \(\beta = -0.028\) atau \(\beta < 0\) emnyiratkan dengan setiap kenaikan unit Item perpesanan nilai pengeriman akan berkurang dan akan dikalikan dengan -0.028.

Jika kita mengambil 8 paramter berbeda untuk menentukan Nilai Freight kemudian menggunakan Quasi-Poisson regression - Prediktor berikut signifikan dengan nilai -p \(\approx\) NOL:

  • Intercept (Mencegat)
  • Jumlah Item Perpesanan
  • Price (Harga)
  • Estimated lead time (Perkiraan Waktu Tunggu)
  • Waktu tunggu aktual
  • Product’s Weight (g) (Berat produk)
  • Product’s Length (cm) (Panjang Produk)
  • Product’s Height (cm) (Tinggi Produk)
  • Product’s Width (cm) (Lebar produk)

…dan terakhir jarak belum diperhitungkan.

NB: - coret adalah paramater yang tidak signifikan. kode dapat diperoleh dari bagian ‘kode’.


Polynomial: regression Persamaan

\[\text{Nilai Pengriman}_\text{ Cluster 4} \approx 50.88 + 98.48x^2 - 90.17x^3 + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]


Kluster Persamaan 5

The \(\frac{\text{Penyimpanan Sisa}}{\text{Derajat Kebebasan}} > 1 \text{ atau} \text{ } \frac{\text{Variance}}{\text{Mean}} \neq 1\) for Poisson Regression berada di 4.810, jadi mungkin ada overdispersi, kami menyesuaikan untuk memperhitungkan overispersi dan menggunakanQuasi-Poisson Regression persamaan.

Quasi-Poisson: regression persamaan

\[\text{Nilai Pengeriman}_\text{ Cluster 5} \approx 3.169 - 0.068x + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]

Interpretasi: Prediktor signifikan sebagai nilai-p \(\approx\) NOL, parameter Dispersi untuk Quasi-Poisson keluarga di ambil pada 4.810. Itu \(\beta = -0.068\) atau \(\beta < 0\) emnyiratkan dengan setiap kenaikan unit Item perpesanan nilai pengeriman akan berkurang dan akan dikalikan dengan -0.068.

Jika kita mengambil 8 paramter berbeda untuk menentukan Nilai Freight kemudian menggunakan Quasi-Poisson regression - Prediktor berikut signifikan dengan nilai -p \(\approx\) NOL:

  • Intercept (mencegat)
  • Number of Items per order (jumlah item per pesanan)
  • Price (Harga)
  • Estimated lead time (Perkiraan waktu tunggu)
  • Actaul lead time (waktu tunggu aktual)
  • Product’s Weight (g) (berat produk)
  • Product’s Length (cm) (panjang produk)
  • Product’s Height (cm) (tinggi produk)
  • Product’s Width (cm) (lebar produk)

…dan terakhir jarak belum diperhitungkan.

NB: - coret adalah parameter yang tidak signifikan. Kode dapat diperoleh dari bagian ‘kode’.


Polynomial: regression persamaan

\[\text{Nilai Pengriman}_\text{ Cluster 5} \approx 22.00 - 95.53x + 27.75x^2 + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]


Persamaan Kluster 6

Itu \(\frac{\text{Penyimpangan Sisa}}{\text{Derajat Kebebasan}} > 1 \text{ or} \text{ } \frac{\text{Variance}}{\text{Mean}} \neq 1\) for Poisson Regression berada di 9.993, jadi mungkin ada overdispersi. kami menyesuaikan untuk memperhitungkan oversipersi dan menggunakan Quasi-Poisson Regression persamaan.

Quasi-Poisson: regression persamaan

\[\text{Nilai Pengiriman}_\text{ Cluster 6} \approx 3.461 - 0.012x + \epsilon \]

\[ x \Rightarrow \text{Jumlah Item Per Order}, \text{ } \epsilon \Rightarrow \text{error}\]

Interpretasi: Prediktor signifikan sebagai nilai-p \(\approx\) NOL, parameter Dsipersi untuk Quasi-Poisson keluarga di ambil pada 12.102. Itu \(\beta = -0.012\) atau \(\beta < 0\) emnyiratkan dengan setiap kenaikan unit Item perpesanan nilai pengeriman akan berkurang dan akan dikalikan dengan -0.012.

Jika kita mengambil 8 paramter berbeda untuk menentukan Nilai Freight kemudian menggunakan Quasi-Poisson regression - Prediktor berikut signifikan dengan nilai -p \(\approx\) NOL:

  • Intercept (Mencegat)
  • Jumlah item per pesanan
  • Price (Harga)
  • Estimated lead time (Perkiraan waktu tunggu)
  • Actaul lead time (Waktu tunggu aktual)
  • Product’s Weight (g) (Berat Produk)
  • Product’s Length (cm) (Panjang Produk)
  • Product’s Height (cm) (Tinggi Produk)
  • Product’s Width (cm) (Lebar Produk)

…dan terakhir jaral belum diperhitungkan.

NB: - coret adalah paramter yang tidak signifikan. kkode dapat diperoleh dari bagian ‘kode’.


Polynomial: regression persamaan

\[\text{Nilai Pengeriman}_\text{ Cluster 6} \approx 31.41 + 49.12x^2 + \epsilon \]

\[ x \Rightarrow \text{Jumlah item per Order}, \text{ } \epsilon \Rightarrow \text{error}\]


Penjual vs Pelanggan tersebar di seluruh negara bagian

Grafik di bawah ini menenjukkan bagaiman kepadatan pelanggan dan penjual tersebar di berbagai negara bagian Brazil. ini adalah prenstasi stagnan dari grafik “customers.sellers.states.gif.

Kesan Siklus Pesanan Pelanggan

Grafik adalah wawasan bergambar pertama tentang: bagaimana Siklus Pesanan Pelanggan (Waktu Pengriman Barang) telah berubah saat Olist mulai berkembang Grafik ini adalah presentasi stagnan dari grafik “Lead.Times.gift”, yang telah ditempatkan di bawah ini

Kesimpulan

Terimakasih telah memberikan waktu anda untuk buku catatan panjang ini.

Lampiran

Lampiran 01

Kode grafik “Pelanggan.Penjualan.Negara.gif” telah disediakan dibawah ini paket gganimate tetapi karean ketidak cocokan versi API.

Olist’s Customers - Sellers States’ density

CS.states %>% ggplot(aes(y = customer_state, x = seller_state))+ geom_jitter(fill = alpha(“blue”, 0.001), color = “white”, alpha = 0.36, size = 2.1, shape = 21)+ coord_polar(start = 0)+ theme_minimal()+ labs(title =“Order Status’ Density :: …{closest_state}…”, x = “Seller’s State”, y = “Customer’s State”, subtitle = “States :: Sellers vs. Customers”)+ transition_states(order_status, transition_length = 5, state_length = 5)


Lampiran 02

Grafik sebenarnya tealh dibuat dengan paket gganimate tetapi karena ketidak cocokan versi API, Kode Grafik “Lead Times.Gif”.

Average Lead Times per Quarter per Year

Lead.Time %>% ggplot(aes(x = purchase_quart, y =Est.Lead.t))+ geom_line(color = “red”, alpha = 0.81, linetype = “longdash”)+ geom_segment(aes(xend = 2018.4, yend = Est.Lead.t), linetype = 2, colour = ‘grey51’)+ geom_text(aes(x = 2018.3, label = Quart.Y, hjust = 1))+ geom_point(size=3, color=“red”, fill=alpha(“orange”, 0.63), alpha=0.54, shape=21, stroke=1)+ facet_wrap(~order_status)+ coord_polar(start = 0)+ transition_reveal(purchase_quart)+ theme(axis.text.x = element_blank(), axis.ticks = element_blank(), panel.background = element_blank(), panel.grid.major.x = element_line(color = “coral”, linetype = 3), panel.grid.major.y = element_line(color = “coral”, linetype = 3), strip.background = element_blank())+ labs(title = “Change in proposed average lead times per Quarter/Year”, subtitle = “Proposed average number of days to delivery”, x = “Purchasing Quarter/Year”, y= ” Estimated average lead time [… in Days]“, caption =”derived from Thomas Lin Pedersen’s Dec 2018 graph: ~github.com/thomasp85”)


LS0tDQp0aXRsZTogIk9saXN0IEJyYXppbGlhbiBlLWNvbW1lcmNlIg0KYXV0aG9yOiAiXFUwMDAxRjVFMyBKYW1hbGx1ZGluIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2M6IHllcw0KICAgIGZpZ193aWR0aDogNw0KICAgIGZpZ19oZWlnaHQ6IDQuNQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCi0tLQ0KDQo8aHI+DQoNCioqU1VCSkVDVDogZUNvbW1lcmNlICYgU3VwcGx5IENoYWluKioNCg0KLSAkMV57c3R9IFx0ZXh0eyBjYXNlIGlzIGFib3V0IGF9JCBbKipTcGFuaXNoKiogZUNvbW1lcmNlIFVsYWJveF0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9hbnNodW1vdWRnaWwvdWxhYm94LWVjb21tZXJjZS1oeXBvdGhlc2lzLXN0cmF0ZWd5LWNsdXN0ZXJpbmcpDQotICQyXntuZH0gXHRleHR7IGNhc2UgaXMgYWJvdXQgYX0kIFsqKkJyYXppbGlhbioqIGVDb21tZXJjZSBPbGlzdF0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9hbnNodW1vdWRnaWwvb2xpc3QtZWNvbW1lcmNlLWFuYWx5dGljcy1jbHVzdGVycy1wb2x5LWVxdWF0aW9uKQ0KDQo8aHI+DQoNClZlcnNpb25zOiAyNCBBcHIgMjAxOSwgMjkgQXByIDIwMTksIDAzIE1heSAyMDE5LCAxNSBNYXkgMjAxOSwgMDYgRmViIDIwMjAuDQoNCjxocj4NCg0KDQoNCiMgTW9kZWwgQmlzbmlzIE9saXN0DQoNCioqW09saXN0XShodHRwOi8vd3d3Lm9saXN0LmNvbS8pKiogYWRhbGFoICoqQnJhemlsaWFuKiogZGVwYXJ0bWVudCBzdG9yZSAoKm1hcmtldHBsYWNlKikgeWFuZyAqKmJlcm9wZXJhc2kgZGkgc2VnbWVuIGUtY29tbWVyY2UsIGJ1a2FuIGUtY29tbWVyY2UgaXR1IHNlbmRlcmkqKiAoKnNlcGVydGkgeWFuZyBkaWthdGFrYW4qKS4gSW5pIGJlcm9wZXJhc2kgc2ViYWdhaSBwZXJ1c2FoYWFuIHRla25vbG9naSBTYWFTICgqUGVyYW5na2F0IEx1bmFrIHNlYmFnYWkgTGF5YW5hbiopIFNlamFrIHRhaHVuIDIwMTUuIGluaSBtZW5hd2Fya2FuIHNvbHVzaSBwYXNhciAoKnNlZ21lbnQgZS1jb21tZXJjZSopIGtlcGFkYSBwZW1pbGlrIHRva28gZGFyaSBzZW11YSB1a3VyYW4gKCpkYW4gc2ViYWdpYW4gdW50dWsgc2VnbWVuKikgVW50dWsgbWVuaW5na2F0a2FuIHBlbmp1YWxhbiBtZXJla2EgYXBha2FoIG1lcmVrYSBoYWRpciBzZWNhcmEgb25saW5lIGF0YXUgdGlkYWsuIA0KDQojIyBTb2x1c2kgT2xpc3QNCg0KU29sdXNpIG9saXN0IHRlcmRlcmkgZGFyaSB0aWdhIGFzcGVrIHlhaXR1IFBlcmFuZ2thdCBMdW5haywgS29udHJhayBkZW5nYW4gcGFzYXIgdXRhbWEsIGRhbiBCZXJiYWdhaSBSZXB1dGFzaS4gRGlhZ3JhbSBkaWJhd2FoIGluaSBtZW51bmp1a2thbiBiYWdhaW1hbmEgT2xpc3QgbWVuZ2h1YnVuZ2thbiBwYXNhciwga29uc3VtZW4gKCpQb3J0dWd1ZXNlOiBjb25zdW1pZG9yZXMqKSwgZGFuIHBlbmdlY2VyICgqUG9ydHVndWVzZTogdmFyZWppc3RhcyopDQoNCiFbT2xpc3TigJlzIG1hcmtldHBsYWNlIG1vZGVsXShodHRwczovL29saXN0LmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxOC8wNC9Hcm91cC00MC5zdmcpDQoNCiMjIEFwYSB5YW5nIGRpa2F0YW4gT2xpc3Q/DQoNCk9saXN0IG1lbmdhdGFrYW4gZGlhLi4uIA0KDQoxLiAuLi4gYWRhbGFoIGRlcGFydG1lbnQgc3RvcmUgYmVzYXIgZGkgcGFzYXIuDQoyLiAuLi4gdGVyaHVidW5nIGtlIGUtY29tbWVyY2UgdXRhbWEgQnJhemlsLg0KMy4gLi4uIHRpZGFrIG1lbWJlbGkgcHJvZHVrLiANCjQuIC4uLiB0aWRhayBtZW55aW1wYW4gcHJvZHVrIGRhbGFtIHBlcnNlZGlhYW4uDQo1LiAuLi4gdGlkYWsgbWVsYWt1a2FuIHBlbmdlcmltYW4gcHJvZHVrIGFwYSBwdW4geWFuZyBkaXRhd2Fya2FuIGRpIHRva29ueWEuIA0KNi4gU2VtdWEgcHJvZHVrIGRpIGp1YWwgZGFuIGRpa2lyaW1rYW4gb2xlaCByaWJ1YW4gcGVtaWxpayB0b2tvICgqKnRlcmRhZnRhciBkaSBPbGlzdCoqKikgeWFuZyBtZW5qdWFsIG1lbGFsdWkgT2xpc3QuDQo3LiBLZWt1YXRhbiB0ZXJsZXRhayBwYWRhIHBlcnNhdHVhbiBzZW11YSBwZW1pbGlrIHRva28gKCoqdGVyZGFmdGFyIGRpIE9saXN0KiopIHlhbmcgbWVuanVhbCBtZWxhbHVpIE9saXN0LiANCjguIFBlbmphZ2EgdG9rbyBwZXNlcnRhIHlhbmcgYmVydGFuZ2d1bmcgamF3YWIgdW50dWsgbWVtaXNhaGthbiwgbWVuZ2VtYXMsIGRhbiBtZW1iYXdhIHByb2R1ayBrZSBvcGVyYXRvciBsb2dpc3Rpay4NCg0KKipIYXJhcCBwZXJoYXRpa2FuIHBlcnNwZWt0aWYgT2xpc3QoUGVydGluamF1IHJhbnRhaSBwYXNva2FuKToqKiBkaWEgbWVuamVsYXNrYW4gYWRhIGJhbnlhayBmYWt0b3IgeWFuZyBkYXBhdCBtZW1wZW5nYXJ1aGkgcGVuanVhbGFuIHBlbmphZ2EgdG9rbywgbWlzYWxueWEgamVuaXMgcHJvZHVrLCBwZXJtaW50YWFuLCBtdXNpbSwgaGFyZ2Ega29tcGV0aXRpZiwgcGVyc3lhcmF0YW4sIGludmVudGFyaXMsIGRhbiBsYWluLWxhaW4uDQoNClBhZGEgZ2FtYmFyIGRpIGJhd2FoIE9saXN0IG1lbmplbGFza2FuICAoKmRhbGFtIGJhaGFzYSBQb3J0dWdpcyopIGJhZ2FpbWFuIGlhIG1lbWJlZGFrYW4gZGlyaW55YSBkYXJpIHBhc2FyIGxhaW4gYmVyZGFzYXJrYW4gcmVwdXRhc2ksIHBlbmVtcGF0YW4gcHJvZHVrLCB0aW0geWFuZyBiZXJkZWRpa2FzaSB1bnR1ayBwZW5qdWFsYW4gJiBsYXlhbmFuIHBlbGFuZ2dhbiwgcGVuZ3VyYW5nYW4gd2FrdHUgdW50dWsgbXVsYWkgbWVuanVhbCwga29udHJvbCB0ZXJwdXNhdCBkYXJpIG9wZXJhc2kgZGFuIGFsYXQga29tcGV0aXRpZiBsYWlueWEuDQoNCiFbT2xpc3TigJlzIG5pY2hlIOKAlCB3YXkgdG8gZGlmZmVyZW50aWF0ZV0oaHR0cHM6Ly9vbGlzdC5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTkvMDIvaWx1c3RyYWNhby1ob21lLmdpZikNCg0KIyBEYXRhIE1vZGVsDQoNCkRpIEthZ2dlbGUsIGRpYSBtZW1iYWdpa2FuIGRhdGEgMTAwIHJpYnUgcGVzYW5hbiBkYXJpIDIwMTYgaGluZ2dhIDIwMTguIEFkYSA4KzEga3VtcHVsYW4gZGF0YSB1bnR1ayBkaSBhbmFseXNpcy4gTW9kZWwgZGF0YSB0ZWxhaCBkaWplbGFza2FuIHBhZGEgZ2FtYmFyIGRpIGJhd2FoIGRhbiBkaWF0dXIgZGFuIGRpbm9ybWFsaXNhc2kgdW50dWsgc2V0aWFwIGthdGVnb3JpLg0KDQohW0RhdGEgTW9kZWxdKGh0dHBzOi8vaS5pbWd1ci5jb20vSFJoZDJZMC5wbmcpIA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmxpYnJhcnkobGF0dGljZSkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQoNCkN1c3RvbWVycyA8LSByZWFkLmNzdigib2xpc3RfY3VzdG9tZXJzX2RhdGFzZXQuY3N2IiwgaGVhZGVyID0gVFJVRSkNCkdlb2xvY2F0aW9uIDwtIHJlYWQuY3N2KCJvbGlzdF9nZW9sb2NhdGlvbl9kYXRhc2V0LmNzdiIsIGhlYWRlciA9IFRSVUUpDQpJdGVtcyA8LSByZWFkLmNzdigib2xpc3Rfb3JkZXJfaXRlbXNfZGF0YXNldC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KUGF5bWVudHMgPC0gcmVhZC5jc3YoIm9saXN0X29yZGVyX3BheW1lbnRzX2RhdGFzZXQuY3N2IiwgaGVhZGVyID0gVFJVRSkNClJldmlld3MgPC0gcmVhZC5jc3YoIm9saXN0X29yZGVyX3Jldmlld3NfZGF0YXNldC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KT3JkZXJzIDwtIHJlYWQuY3N2KCJvbGlzdF9vcmRlcnNfZGF0YXNldC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KUHJvZHVjdHMgPC0gcmVhZC5jc3YoIm9saXN0X3Byb2R1Y3RzX2RhdGFzZXQuY3N2IiwgaGVhZGVyID0gVFJVRSkNClNlbGxlcnMgPC0gcmVhZC5jc3YoIm9saXN0X3NlbGxlcnNfZGF0YXNldC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KUGR0dHJhbnMgPC0gcmVhZC5jc3YoInByb2R1Y3RfY2F0ZWdvcnlfbmFtZV90cmFuc2xhdGlvbi5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KDQpgYGANCg0KIyMgS3VtcHVsYW4gRGF0YSBVdGFtYQ0KDQpLdW1wdWxhbiBkYXRhIHBlc2FuYW4NCg0KLSBPcmRlciBJRCAoSUQgUGVtYXNhbmFuKQ0KLSBDdXN0b21lciBJRCAoSUQgUGVsYW5nZ2FuKQ0KLSBPcmRlciBTdGF0dXMgKFN0YXR1cyBQZW1lc2FuYW4pDQotIE9yZGVyIFB1cmNoYXNlIFRpbWVzdGFtcCAoU3RlbXBlbCBXYWt0dSBQZW1iZWxpYW4gUGVzYW5hbikNCi0gT3JkZXIgQXBwcm92ZWQgYXQgKFBlc2FuYW4gWWFuZyBEaXNldHVqdWkpDQotIE9yZGVyIERlbGl2ZXJlZCBDYXJyaWVyIGRhdGUgKFBlc2FuYW4gRGlraXJpbSBUYW5nZ2FsIFBlbWJhd2EpDQotIE9yZGVyIERlbGl2ZXJlZCBDdXN0b21lciBkYXRlIChQZXNhbmFuIERpa2lyaW0gVGFuZ2dhbCBQZWxhbmdnYW4pDQotIE9yZGVyIEVzdGltYXRlZCBkZWxpdmVyZWQgZGF0ZSAoUGVzYW5hbiBQZXJraXJhYW4gVGFuZ2dhbCBQZW5nZXJpbWFuKQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmthYmxlKGhlYWQoT3JkZXJzKSwgZm9ybWF0ID0gIm1hcmtkb3duIixjYXB0aW9uID0gIk9yZGVycyBkYXRhc2V0IikNCmBgYA0KDQojIyBLdW1wdWxhbiBEYXRhIGxhaW55YSB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30NCg0KIyMjIERhdGFzZXQgUGVsYW5nZ2FuDQoNCi0gQ3VzdG9tZXIgSUQgKElEIFBlbGFuZ2dhbiApDQotIEN1c3RvbWVyIFVuaXF1ZSBJRCAoSUQgVW5payBQZWxhbmdnYW4pDQotIEN1c3RvbWVyIFppcCBDb2RlIHByZWZpeCAoQXdhbGFuIEtvZGUgUG9zIFBlbGFuZ2dhbikNCi0gQ3VzdG9tZXIgQ2l0eSAoS290YSBQZWxhbmdnYW4pDQotIEN1c3RvbWVyIFN0YXRlIChOZWdhcmkgUGVsYW5nZ2FuKQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmthYmxlKGhlYWQoQ3VzdG9tZXJzKSwgZm9ybWF0ID0gIm1hcmtkb3duIiwgY2FwdGlvbiA9ICJDdXN0b21lcnMgZGF0YXNldCIpDQpgYGANCg0KIyMjIEt1bXB1bGFuIERhdGEgR2VvbG9rYXNpDQoNCi0gR2VvbG9jYXRpb24gWmlwIENvZGUgcHJlZml4IChBd2FsYW4gS29kZSBQb3MgR2VvbG9rYXNpKQ0KLSBHZW9sb2NhdGlvbiBMYXQuIChHZW9sb2thc2kgTGF0KQ0KLSBHZW9sb2NhdGlvbiBMbmcuIChHZW9sb2thc2kgTG5nKQ0KLSBHZW9sb2NhdGlvbiBDaXR5IChLb3RhIEdlb2xva2FzaSkNCi0gR2VvbG9jYXRpb24gU3RhdGUgKFN0YXR1cyBHZW9sb2thc2kpDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0Ka2FibGUoaGVhZChHZW9sb2NhdGlvbiksIGZvcm1hdCA9ICJtYXJrZG93biIsIGNhcHRpb24gPSAiR2VvbG9jYXRpb24gZGF0YXNldCIpDQpgYGANCg0KIyMjIEt1bXB1bGFuIERhdGEgSXRlbQ0KDQotIE9yZGVyIElEIChJRCBQZW1lc2FuYW4pDQotIE9yZGVyIEl0ZW0gSUQgKElEIGJhcmFuZyBQZXNhbmFuKQ0KLSBTZWxsZXIgSUQgKFRhbmdnYWwgQmF0YXMgUGVuZ2VyaW1hbikNCi0gU2hpcHBpbmcgbGltaXQgZGF0ZSAoVGFuZ2dhbCBCYXRhcyBQZW5nZXJpbWFuKQ0KLSBQcmljZSAoSGFyZ2EpDQotIEZyZWlnaHQgVmFsdWUgKE5pbGFpIFBlbmdpcmltYW4pDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0Ka2FibGUoaGVhZChJdGVtcyksIGZvcm1hdCA9ICJtYXJrZG93biIsIGNhcHRpb24gPSAiSXRlbXMgZGF0YXNldCIpDQpgYGANCg0KIyMjIEt1bXB1bGFuIERhdGEgUGVtYmF5YXJhbg0KDQotIE9yZGVyIElEIChJRCBQZW1lc2FuYW4NCi0gUGF5bWVudCBTZXF1ZW50aWFsIChVcnV0YW4gUGVtYmF5YXJhbikNCi0gUGF5bWVudCBUeXBlIChUaXBlIFBlbWJheWFyYW4pDQotIFBheW1lbnQgSW5zdGFsbG1lbnRzIChBbmdzdXJhbiBQZW1iYXlhcmFuKQ0KLSBQYXltZW50IFZhbHVlIChOaWxhaSBQZW1iYXlhcmFuKQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmthYmxlKGhlYWQoUGF5bWVudHMpLCBmb3JtYXQgPSAibWFya2Rvd24iLCBjYXB0aW9uID0gIlBheW1lbnRzIGRhdGFzZXQiKQ0KYGBgDQoNCiMjIyBLdW1wdWxhbiBEYXRhIFByb2R1aw0KDQotIFByb2R1Y3QgSUQgKElEIFByb2R1aykNCi0gUHJvZHVjdCBDYXRlZ29yeSBuYW1lIChOYW1hIEthdGVnb3JpIFByb2R1aykNCi0gUHJvZHVjdCBOYW1lIGxlbmd0aCAoTmFtYSBQcm9kdWsgUGFuamFuZykNCi0gUHJvZHVjdCBQaG90b3MgKHF1YW50aXR5KSAoRm90byBwcm9kdWsoanVtbGFoKSkgDQotIFByb2R1Y3QgV2VpZ2h0IChncmFtcykgKEJlcmF0IFByb2R1ayhncmFtKSkNCi0gUHJvZHVjdCBMZW5ndGggKGNtKSAoUGFuamFuZyBQcm9kdWsoY20pKQ0KLSBQcm9kdWN0IEhlaWdodCAoY20pIChUaW5nZ2kgUHJvZHVrKGNtKSkNCi0gUHJvZHVjdCBXaWR0aCAoY20pIChMZWJhciBQcm9kdWsoY20pKQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmthYmxlKGhlYWQoUHJvZHVjdHMpLCBmb3JtYXQgPSAibWFya2Rvd24iLCBjYXB0aW9uID0gIlByb2R1Y3RzIGRhdGFzZXQiKQ0KYGBgDQoNCiMjIyBVbGFzYW4gS3VtcHVsYW4gRGF0YQ0KDQotIFJldmlldyBJRCANCi0gT3JkZXIgSUQgKElEIFBlbWVzYW5hbikNCi0gUmV2aWV3IFNjb3JlIChTa29yIFVsYXNhbikNCi0gUmV2aWV3IENvbW1lbnQgdGl0bGUgKFRpbmphdSBLb21lbnRhciBKdWR1bCkNCi0gUmV2aWV3IENvbW1lbnQgbWVzc2FnZSAoVGluamF1IFBlc2FuYW4gS29tZW50YXIpDQotIFJldmlldyBDcmVhdGlvbiBkYXRlIChUaW5qYXUgVGFuZ2dhbCBQZW1idWF0YW4pDQotIFJldmlldyBBbnN3ZXIgdGltZXN0YW1wIChUaW5qYXUgU3RlbXBlbCBXYWt0dSBKYXdhYmFuKQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCmthYmxlKGhlYWQoUmV2aWV3cyksIGZvcm1hdCA9ICJtYXJrZG93biIsIGNhcHRpb24gPSAiUmV2aWV3cyBkYXRhc2V0IikNCmBgYA0KDQojIyMgS3VtcHVsYW4gRGF0YSBQZW5qdWFsDQoNCi0gU2VsbGVyIElEIChJRCBQZW5qdWFsYW4pDQotIFNlbGxlciBaaXAgQ29kZSBwcmVmaXggKEF3YWxhbiBLb2RlIFBvcyBQZW5qdWFsKQ0KLSBTZWxsbGVyIENpdHkgKEtvdGEgUGVuanVhbCkNCi0gU2VsbGVyIFN0YXRlIChOZWdhcmEgUGVuanVhbCkNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQprYWJsZShoZWFkKFNlbGxlcnMpLCBmb3JtYXQgPSAibWFya2Rvd24iLCBjYXB0aW9uID0gIlNlbGxlcnMgZGF0YXNldCIpDQpgYGANCg0KIyMjIERhdGFzZXQgVGVyamVtYWhhYW4gS2F0ZWdvcmkgUHJvZHVrDQoNCi0gUHJvZHVjdCBDYXRlZ29yeSBuYW1lIChQb3J0dWdpcykgKE5hbWEgS2F0ZWdvcmkgUHJvZHVrIFBvcnR1Z2lzKQ0KLSBQcm9kdWN0IENhdGVnb3J5IG5hbWUgKEVuZ2xpc2gpIChOYW1hIEthdGVnb3JpIFByb2R1ayBiYWhhc2EgSW5nZ3JpcykNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQprYWJsZShoZWFkKFBkdHRyYW5zKSwgZm9ybWF0ID0gIm1hcmtkb3duIiwgY2FwdGlvbiA9ICJUcmFuc2xhdGlvbiBkYXRhc2V0IikNCmBgYA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCg0KT3JkZXJzIDwtIG11dGF0ZShPcmRlcnMsIEVzdC5MZWFkLnQgPSBpbnRlcnZhbCh5bWRfaG1zKE9yZGVycyRvcmRlcl9wdXJjaGFzZV90aW1lc3RhbXApLCB5bWRfaG1zKE9yZGVycyRvcmRlcl9lc3RpbWF0ZWRfZGVsaXZlcnlfZGF0ZSkpICUvJSBkYXlzKHggPSAxKSkNCk9yZGVycyA8LSBtdXRhdGUoT3JkZXJzLCBBY3QuTGVhZC50ID0gaW50ZXJ2YWwoeW1kX2htcyhPcmRlcnMkb3JkZXJfcHVyY2hhc2VfdGltZXN0YW1wKSwgeW1kX2htcyhPcmRlcnMkb3JkZXJfZGVsaXZlcmVkX2N1c3RvbWVyX2RhdGUpKSAlLyUgZGF5cyh4ID0gMSkpDQpPcmRlcnMgPC0gbXV0YXRlKE9yZGVycywgQXBwcm92YWwubWlucyA9IGludGVydmFsKHltZF9obXMoT3JkZXJzJG9yZGVyX3B1cmNoYXNlX3RpbWVzdGFtcCksIHltZF9obXMoT3JkZXJzJG9yZGVyX2FwcHJvdmVkX2F0KSkgJS8lIG1pbnV0ZXMoeCA9IDEpKQ0KT3JkZXJzIDwtIG11dGF0ZShPcmRlcnMsIEFwcHIudG8uQ2FyID0gaW50ZXJ2YWwoeW1kX2htcyhPcmRlcnMkb3JkZXJfcHVyY2hhc2VfdGltZXN0YW1wKSwgeW1kX2htcyhPcmRlcnMkb3JkZXJfZGVsaXZlcmVkX2NhcnJpZXJfZGF0ZSkpICUvJSBkYXlzKHggPSAxKSkNCk9yZGVycyA8LSBtdXRhdGUoT3JkZXJzLCBDYXIudG8uQ3VzID0gaW50ZXJ2YWwoeW1kX2htcyhPcmRlcnMkb3JkZXJfZGVsaXZlcmVkX2NhcnJpZXJfZGF0ZSksIHltZF9obXMoT3JkZXJzJG9yZGVyX2RlbGl2ZXJlZF9jdXN0b21lcl9kYXRlKSkgJS8lIGRheXMoeCA9IDEpKQ0KT3JkZXJzIDwtIG11dGF0ZShPcmRlcnMsIHB1cmNoYXNlX3F1YXJ0ID0gcXVhcnRlcihPcmRlcnMkb3JkZXJfcHVyY2hhc2VfdGltZXN0YW1wLCB3aXRoX3llYXIgPSBUUlVFKSkNCk9yZGVycyA8LSBtdXRhdGUoT3JkZXJzLCBwdXJjaGFzZV9tb250aCA9IG1vbnRoKE9yZGVycyRvcmRlcl9wdXJjaGFzZV90aW1lc3RhbXAsIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFKSkNCk9yZGVycyA8LSBtdXRhdGUoT3JkZXJzLCBwdXJjaGFzZV95ZWFyID0geWVhcihPcmRlcnMkb3JkZXJfcHVyY2hhc2VfdGltZXN0YW1wKSkNCg0KSXRlbXMgPC0gbXV0YXRlKEl0ZW1zLCBvcmRlci5wcmljZSA9IChvcmRlcl9pdGVtX2lkKnByaWNlKSkNCkl0ZW1zIDwtIG11dGF0ZShJdGVtcywgb3JkZXIuZnJlaWdodCA9IChvcmRlcl9pdGVtX2lkKmZyZWlnaHRfdmFsdWUpKQ0KSXRlbXMgPC0gbXV0YXRlKEl0ZW1zLCB0b3RhbC5vcmRlci5jb3N0ID0gKG9yZGVyLnByaWNlICsgb3JkZXIuZnJlaWdodCkpDQpJdGVtcyA8LSBtdXRhdGUoSXRlbXMsIGZyLnN1cC5wciA9IGlmX2Vsc2UoZnJlaWdodF92YWx1ZSA+PSBwcmljZSwgMSwgMCkpDQpgYGANCg0KIyBTdGltdWxhc2kgc2ViYWdhaSAqxpIoUGVsYW5nZ2FuLCBLYXRlZ29yaSBQcm9kdWssIFBlbmp1YWwpKg0KDQpPbGlzdCB0ZWxhaCBkaXJhbmNhbmcgZGVuZ2FuIHBlbmFtYmFoYW4gcGVsYW5nZ2FuLCBLYXRlZ29yaSBQcm9kdWssIGRhbiAgUGVuanVhbGFuIHNlc3VhaSBkYXRhLCBhZGEgYWxpcmFuIHBlbGFuZ2dhbiBkYW4gcGVuanVhbCB5YW5nIHRlcmRhZnRhciBkaSBwbGF0Zm9ybSBPbGlzdC4gS2VtYWp1YW4gaW5pLCBzZXJpbmcgZGVuZ2FuIHBlbmluZ2thdGFuIHJlZ3VsZXIgZGFsYW0ganVtbGFoIGthdGVnb3JpIHByb2R1ayBiYXJ1IHlhbmcgZGl0YXdhcmthbiB0ZWxhaCBtZW1wZXJ0YWhhbmthbiBtb21lbnR1bSBwZXJ0dW1idWhhbiBvbGlzdCANCg0KIyMgVHJlbmQgUGVuZGFmdGFyYW4gUGVsYW5nZ2FuIEJhcnUNCg0KR3JhZmlrIG1lbnVuanVra2FuLCBwYWRhIHRhaHVuIDIwMTcsIHRlbGFoIHRlcmphZGkgdHJlbmQgbGluZSBwb3NpdGVmIGRhbGFtIGp1bWxhaCBQZWxhbmdnYW4gQmFydSBbKipJZGVudGl0YXMgVW5payBQZWxhbmdnYW4qKl0geWFuZyB0ZXJkYWZ0YXIgZGkgT2xpc3QuIFBhZGEgdGFodW4gMjAxOCwgbGViaWggZGFyaSA2MDAwIHJpYnUgbWVuZGFmdGFyIHNldGlhcCBidWxhbi4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCg0KQ3VzdC5nciA8LSBpbm5lcl9qb2luKE9yZGVycywgQ3VzdG9tZXJzLCBieSA9ICJjdXN0b21lcl9pZCIpDQoNCkN1c3QuZ3IgJT4lIHNlbGVjdF9hdCh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoLCBjdXN0b21lcl91bmlxdWVfaWQpKSAlPiUgZGlzdGluY3RfYXQodmFycyhwdXJjaGFzZV95ZWFyLCBwdXJjaGFzZV9tb250aCwgY3VzdG9tZXJfdW5pcXVlX2lkKSkgJT4lIGFycmFuZ2VfYXQodmFycyhwdXJjaGFzZV95ZWFyLCBwdXJjaGFzZV9tb250aCkpICU+JSBjb3VudF8odmFycyhwdXJjaGFzZV95ZWFyLCBwdXJjaGFzZV9tb250aCkpICU+JSBnZ3Bsb3QoYWVzKHkgPSBuLCB4ID0gYXMuZmFjdG9yKHB1cmNoYXNlX21vbnRoKSwgbGFiZWwgPSBuLCBjb2xvciA9IGZhY3RvcihwdXJjaGFzZV95ZWFyKSkpKw0KICBnZW9tX3BvaW50KHNpemUgPSA1LCBjb2xvciA9ICduYXZ5Jywgc2hhcGUgPSAyMSwgYWxwaGEgPSAwLjU0KSsNCiAgZ2VvbV9wb2ludChzaXplID0gMy43NSwgY29sb3IgPSAnbmF2eScsIHNoYXBlID0gMjEsIGFscGhhID0gMC43MikrDQogIGdlb21fbGFiZWwoYWVzKGZpbGwgPSBmYWN0b3IocHVyY2hhc2VfeWVhcikpLCBjb2xvdXIgPSAid2hpdGUiLCBmb250ZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAxLCBzaXplID0gNC4yNSkrDQogIGZhY2V0X2dyaWQoLn5wdXJjaGFzZV95ZWFyKSsNCiAgICAgICAgICAgICAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuMSwwLjcpKSsNCiAgbGFicyh0aXRsZSA9ICJUcmVuIFBlbmRhZnRhcmFuIFBlbG5nZ2dhbiBCYXJ1IFBlciBCdWxhbiIsIHggPSAiQnVsYW4iLCB5ID0gIkp1bWxhaCBQZWxhbmdnYW4iLCBmaWxsID0gIlRhaHVuIFBlbWJlbGlhbiIpDQoNCmBgYA0KDQojIyBHYWx2YW5pc2F0aW9uIEJlcmRhc2Fya2FuIEthdGVnb3JpIFByb2R1aw0KDQpNZW51cnV0IHBlbmRhcGF0IHNheWEsIHBlbmFtYmFoYW4gKzUwICgqUGVya2lyYWFuKikgS2F0ZWdvcmkgUHJvZHVrIEJhcnUgUGVyIEJ1bGFuIC0gKlNlYmFnYWkgUGVuYXdhcmFuKiAtIHRlbGFoIG1lbmdlbWJhbmdrYW4gbG9uamFrYW4gcGVsYW5nZ2FuIGJhcnUgeWFuZyBtZW5kYWZ0YXIuIEtvbnNpbnRlbiBmZW5vbWUgaW5pIG1lbmphZGkgYmF1aCBiaWJpciBPbGlzdCBzZWxhbWEgMjAgYnVsYW4geWFrbmkgc2VqYWsgSmFudWFyaSAyMDE3IGhpbmdnYSBBZ3VzdHVzIDIwMTguDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGVjaG89RkFMU0V9DQoNClByb2R1Y3RzIDwtIGxlZnRfam9pbihQcm9kdWN0cywgUGR0dHJhbnMsIGJ5ID0gInByb2R1Y3RfY2F0ZWdvcnlfbmFtZSIpDQpJdGVtcyA8LSBsZWZ0X2pvaW4oSXRlbXMsIFByb2R1Y3RzLCBieSA9ICJwcm9kdWN0X2lkIikNClBkdC5HciA8LSBpbm5lcl9qb2luKE9yZGVycywgSXRlbXMsIGJ5ID0gIm9yZGVyX2lkIikNCg0KUGR0LkdyICU+JSBzZWxlY3RfYXQodmFycyhwdXJjaGFzZV95ZWFyLCBwdXJjaGFzZV9tb250aCwgcHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpKSAlPiUgZGlzdGluY3RfYXQodmFycyhwdXJjaGFzZV95ZWFyLCBwdXJjaGFzZV9tb250aCwgcHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpKSAlPiUgYXJyYW5nZV9hdCh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoKSkgJT4lIGNvdW50Xyh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoKSkgJT4lIGdncGxvdChhZXMoeCA9IGZhY3RvcihwdXJjaGFzZV9tb250aCksIHkgPSBuKSkrDQogIGdlb21fcG9pbnQoY29sb3IgPSAiZGFya29yY2hpZCIsIGFscGhhID0gMC43Miwgc2hhcGUgPSAyMSwgYWVzKHNpemUgPSBuKSwgZmlsbCA9IGFscGhhKCJzbm93MiIsIDAuMykpKw0KICBnZW9tX3BvaW50KGNvbG9yID0gImRhcmtvcmNoaWQiLCBhbHBoYSA9IDAuODEsIHNoYXBlID0gMjEsIGFlcyhzaXplID0gbiowLjYpLCBmaWxsID0gYWxwaGEoInNub3cyIiwgMC4zKSkrDQogIGdlb21fc2VnbWVudChhZXMoeCA9IHB1cmNoYXNlX21vbnRoLCB4ZW5kID0gcHVyY2hhc2VfbW9udGgsIHkgPSAwLCB5ZW5kID0gbiksIGFscGhhID0gMC40NSwgbGluZXR5cGUgPSAzLCBjb2xvciA9ICJkYXJrb3JjaGlkIikrDQogIGNvb3JkX3BvbGFyKHN0YXJ0ID0gMikrDQogIGZhY2V0X3dyYXAoLn5wdXJjaGFzZV95ZWFyKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSsNCiAgbGFicyh0aXRsZSA9ICJLYXRlZ29yaSBQcm9kdWsgQmFydSBZYW5nIERpcGVya2VuYWxrYW4gUGVyIEJ1bGFuIiwgeCA9ICJCdWxhbiIsIHkgPSAiSnVtbGFoIEthdGVnb3JpIFByb2R1ayIpDQoNCmBgYA0KDQojIyBLZXRlcmxpYmF0YW4gUGVuanVhbA0KDQpQZW5qdWFsIGp1Z2EgbWVtcGVydGFoYW5rYW4gdHJlbiB5YW5nIHNhbWEgZGVuZ2FuIHBlbGFuZ2dhbiwgZGFsYW0ga2VyYW5na2Egd2FrdHUgZGF0YSBpbmksIE9saXN0IGFraGlybnlhIG1lbWlsaWtpICsgMzA5NSBQZW5qdWFsIHRlcmRhZnRhciBkaSBwbGF0Zm9ybW55YS4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZWNobz1GQUxTRX0NCg0KU2VsbGVyLkdyIDwtIGlubmVyX2pvaW4oT3JkZXJzLCBsZWZ0X2pvaW4oSXRlbXMsIFNlbGxlcnMsIGJ5ID0gInNlbGxlcl9pZCIpLCBieSA9ICJvcmRlcl9pZCIpDQoNClNlbGxlci5HciAlPiUgc2VsZWN0X2F0KHZhcnMocHVyY2hhc2VfeWVhciwgcHVyY2hhc2VfbW9udGgsIHNlbGxlcl9pZCkpICU+JSBkaXN0aW5jdF9hdCh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoLCBzZWxsZXJfaWQpKSAlPiUgYXJyYW5nZV9hdCh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoKSkgJT4lIGNvdW50Xyh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoKSkgJT4lIGdncGxvdChhZXMoeCA9IGZhY3RvcihwdXJjaGFzZV9tb250aCksIHkgPSBuKSkrDQogIGdlb21fcG9pbnQoY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjYzLCBzaGFwZSA9IDIxLCBhZXMoc2l6ZSA9IG4pLCBmaWxsID0gYWxwaGEoImNvcm5zaWxrIiwgMC4zKSkrDQogIGdlb21fcG9pbnQoY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjgxLCBzaGFwZSA9IDIxLCBhZXMoc2l6ZSA9IG4qMC42KSwgZmlsbCA9IGFscGhhKCJjb3Juc2lsayIsIDAuMykpKw0KICBnZW9tX3NlZ21lbnQoYWVzKHggPSBwdXJjaGFzZV9tb250aCwgeGVuZCA9IHB1cmNoYXNlX21vbnRoLCB5ID0gMCwgeWVuZCA9IG4pLCBhbHBoYSA9IDAuNDUsIGxpbmV0eXBlID0gMywgY29sb3IgPSAicmVkIikrDQogIGNvb3JkX3BvbGFyKHN0YXJ0ID0gMikrDQogIGZhY2V0X3dyYXAoLn5wdXJjaGFzZV95ZWFyKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSsNCiAgbGFicyh0aXRsZSA9ICJQZW5pbmdrYXRhbiBKdW1sYWggUGVuanVhbCBQZXIgQnVsYW4iLCB4ID0gIkJ1bGFuIiwgeSA9ICJKdW1sYWggUGVuanVhbCIpDQoNCmBgYA0KDQojIEthdGVnb3JpIFByb2R1ayBGQVNUIE1PVklORw0KDQpLYXRlZ29yaSBQcm9kdWsgZGFwYXQgZGl1a3VyIGRhcmkgc2ViZXJhcGEgc2VyaW5nIHN1YXR1IGthdGVnb3JpIHByb2R1ayBkaWJlbGkgb2xlaCBwZWxhbmdnYW4/IGF0YXUgbWFuYWthaCBrYXRlZ29yaSBwcm9kdWsgIkZBU1QgTU9WSU5HIiB5YW5nIGRpZG9yb25nIG9sZWggcGVsYW5nZ2FuPyBLZXJuZWwgSW5mb3JtYXNpIGluaSBkYXBhdCBiZXJ0aW5kYWsgc2ViYWdhaSBzYWxhaCBzYXR1IHBhcmFtZXRlciB5YW5nIG11bmdraW4geWFuZyBtdW5na2luIGRpZ3VuYWthbiBvbGVoIHBlcnVzYWhhYW4gKCpkYW4gZGFsYW0gaGFsIGluaSBPbGlzc3QqKSBVbnR1ayBtZW1iYWd1biBwb3J0b2ZvbGlvLiANCg0KTW9kZWwgZGF0YSBpbmkgbWVtaWxpa2kgaW5mb3JtYXNpIDEwMCByaWJ1IHBlc2FuYW4gb2xlaCBrYXJlbmEgaXR1LCBkZW5nYW4gbWVuZ2FtYmlsIHBldHVuanVrIGRhcmkgZGlzdHJpYnVzaSBkYXRhIGt1YXJ0aWwsIHNheWEgbWVtYmFnaW55YSBsZWJpaCBsYW5qdXQgbWVuamFkaSA2IHN1YiBiYWdpYW4uICBpbmkgbWVtYmFudHUgc2F5YSBtZW5lbnR1a2FuIHNlY2FyYSB2aXN1YWwgKCpkYWxhbSBiZW50dWsgdGlkYWsgaWxtaWFoKikgS2F0ZWdvcmkgcHJvZHVrIG1hbmEgeWFuZyBiZXJnZXJhayBjZXBhdCBzZXN1YWkgZGVuZ2FuIHNldGlhcCBzdWItYmFnaWFuLiANCg0KIyMgUGVtYmVsaWFuIERpbGFrdWthbiBCZWJlcmFwYSBLYWxpDQoNCk1hcmkga2l0YSBtdWxhaSBkZW5nYW4ga2FzdXMgZGkgbWFuYSBzZW11YSBrYXRlZ29yaSBQcm9kdWsgZGliZWxpIGJlYmVyYXBhIGthbGkuIEdyYWZpayBkaSBiYXdhaCBpbmkgbWVudW5qdWtrYW4ga2F0ZWdvcmkgbWFuYSB5YW5nIG1lcnVwYWthbiBrYXRlZ29yaSBmcmVrdWVuc2kgdGluZ2dpLg0KDQoqKkhhcmFwIERpY2F0YXQ6KiogSW5pIHRpZGFrIHRlcm1hc3VrIHNlbXVhIGthdGVnb3JpIHlhbmcgZGliZWxpIHNlYmFnYWk6IHNhdHUga2F0ZWdvcmkgcHJvZHVrIHBlcmJ1bGFuIGRhbiBwZXJ0YWh1bi4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OSwgZmlnLndpZHRoPTcuNX0NCg0KUGR0LkdyICU+JSBncm91cF9ieV9hdCh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoLCBwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkpICU+JSBmaWx0ZXIoIWlzLm5hKHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSklPiUgY291bnQocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpICU+JSBhcnJhbmdlKGRlc2MobikpICU+JSBmaWx0ZXIoIWlzLm5hKHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSAmIG4gPjEpICU+JSBnZ3Bsb3QoYWVzKHggPSBwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCwgeSA9IG4pKSsNCiAgZ2VvbV9ib3hwbG90KGNvbG9yID0gImJsdWV2aW9sZXQiLCBhbHBoYSA9IDAuNjMpKw0KICBjb29yZF9mbGlwKCkrDQogIGZhY2V0X3dyYXAoLn5yZW9yZGVyKHB1cmNoYXNlX3llYXIsIGRlc2MocHVyY2hhc2VfeWVhcikpLCBzY2FsZXMgPSAiZnJlZV94IikrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgc2NhbGVfeV9yZXZlcnNlKCkrDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3LjI1KSwgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gIndoaXRlIiksIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJ3aGl0ZSIpLCBwYW5lbC5ncmlkLm1ham9yLnkgPSAgZWxlbWVudF9saW5lKGNvbG9yID0gImdyZXk5NSIsIGxpbmV0eXBlID0gMykpKw0KICBsYWJzKHRpdGxlID0gIkthdGVnb3JpIFlhbmcgRGliZWxpIERlbmdhbiBGcmVrdWVuc2kgVGluZ2dpIFBlcnRhaHVuIiwgeSA9ICJCZXJhcGEgS2FsaSBLYXRlZ29yaSBQcm9kdWsgWWFuZyBEaWJlbGkiKQ0KDQpgYGANCg0KIyMgRW5hbSBTdWIgLSBCYWdpYW4gey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNCiMjIyBTYXR1IFBlc2FuYW4gUGVyIEthdGVnb3JpIFByb2R1aw0KDQpLYXN1cyBkaSBtYW5hIGhhbnlhIHNhdHUgcGVzYW5hbiB5YW5nIGRpbGFrdWthbiB1bnR1ayBzYXR1IEthdGVnb3JpIHByb2R1ayBkYWxhbSBzYXR1IGJ1bGFuIGRhbiBwYWRhIHRhaHVuIHRlcnRlbnR1Lg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OH0NCg0KUGR0LkdyICU+JSBncm91cF9ieV9hdCh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoLCBwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkpICU+JSBmaWx0ZXIoIWlzLm5hKHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSklPiUgY291bnQocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpICU+JSBhcnJhbmdlKGRlc2MobikpICU+JSBmaWx0ZXIoIWlzLm5hKHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSAmIG4gPT0xKSAlPiUgZ2dwbG90KGFlcyh4ID0gcHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gsIHkgPSBmYWN0b3IobikpKSsNCiAgZ2VvbV9ydWcoY29sb3IgPSAid2hpdGUiLCBhbHBoYSA9IDAuMDEpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpLCBzaXplID0gMy4yNSwgY29sb3IgPSAiZmlyZWJyaWNrIiwgdmp1c3QgPSAwKSsNCiAgY29vcmRfZmxpcCgpKw0KICBmYWNldF93cmFwKC5+cHVyY2hhc2VfeWVhciwgc2NhbGVzID0gImZyZWUiKSsNCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSwgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG9yID0gIndoaXRlIiksIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpKw0KICBsYWJzKHRpdGxlID0gIlNhdHUgUGVzYW5hbiBVbnR1ayBTYXR1IEthdGVnb3JpIFByb2R1ay9CdWxhbi9UYWh1biIsc3VidGl0bGUgPSAiVGlkYWsgQWRhIEthc3VzIFBlbmd1bGFuZ2FuIixjYXB0aW9uID0gIkNhdGF0YW46IFBlc2FuYW4gVGVycGlzYWggVW50dWsgS2F0ZWdvcmkgTGFpbiBEYXBhdCBEaWxha3VrYW4gRGkgQnVsYW4gWWFuZyBTYW1hIiwgeCA9ICJLYXRlZ29yaSBQcm9kdWsgRGliZWxpIiwgeSA9ICIuLi4gSGFueWEgU2F0dSBQZXNhbmFuIikNCg0KYGBgDQoNCiMjIyBEaWJlbGkgKioiMSA8IG4gPCA2IioqIEthbGkNCg0KS2FzdXMgZGkgbWFuYSBQZXNhbmFuIGRpbGFrdWthbiB1bnR1ayBiZXJiYWdhaSBLYXRlZ29yaSBQcm9kdWsgZGFuIHNldGlhcCBLYXRlZ29yaSBwcm9kdWsgZGliZWxpICoqTGViaWggZGFyaSBzZWxhaSB0ZXRhcGkga3VyYW5nIGRhcmkgZW5hbSBrYWxpKiouIFBsdXMsIGRhZnRhciBkaSBiYXdhaCBpbmkgbWVueWVkaWFrYW4gYmViZXJhcGEga2F0ZWdvcmkgeWFuZyBwYWxpbmcgc2VyaW5nIGRpcGVzYW4uDQoNCi0gQ29uc3RydWN0aW9uIFRvb2xzIChBbGF0IEtvbnN0cnVrc2kpDQotIENpbmUgUGhvdG8gKEZvdG8gRmlsbSkNCi0gRFZEcyBCbHVlIFJheSAoRFZEIEJsdWUgUmF5KQ0KLSBGYXNoaW9uIEZlbWFsZSBDbG90aGluZyAoQnVzYW5hIFdhbml0YSBGYXNoaW9uKQ0KLSBNdXNpYyAoTXVzaWspDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTksIGZpZy53aWR0aD04fQ0KDQpQZHQuR3IgJT4lIGdyb3VwX2J5X2F0KHZhcnMocHVyY2hhc2VfeWVhciwgcHVyY2hhc2VfbW9udGgsIHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSkgJT4lIGZpbHRlcighaXMubmEocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpKSU+JSBjb3VudChwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkgJT4lIGFycmFuZ2UoZGVzYyhuKSkgJT4lIGZpbHRlcighaXMubmEocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpKSAlPiUgZmlsdGVyKG4gPiAxICYgbiA8IDYpICU+JSBnZ3Bsb3QoYWVzKHggPSBwdXJjaGFzZV9tb250aCwgeSA9IG4pKSsNCiAgZ2VvbV9ib3hwbG90KGNvbG9yID0gIm9yYW5nZXJlZCIsIGFscGhhID0gMC42MykrDQogIGNvb3JkX2ZsaXAoKSsNCiAgZmFjZXRfd3JhcCgufmZhY3Rvcihwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCksIHNjYWxlcyA9ICJmcmVlX3giKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUuNSksIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJ3aGl0ZSIpLCBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSwgcGFuZWwuZ3JpZC5tYWpvci55ID0gIGVsZW1lbnRfbGluZShjb2xvciA9ICJjb3Juc2lsayIsIGxpbmV0eXBlID0gMykpKw0KICBsYWJzKHRpdGxlID0gIkJhZ2lhbiAwMjogS2F0ZWdvcmkgWWFuZyBTZXJpbmcgRGliZWxpICcxIDwgbiA8IDYnIGthbGkiLCB4ID0gIkJ1bGFuOiBKYW51YXJ5IC4uLiBEZWNlbWJlciIsIHkgPSAibiA9IEJlYmVyYXBhIEthbGkgS2F0ZWdvcmkgUHJvZHVrIFlhbmcgRGliZWxpIikNCg0KYGBgDQoNCiMjIyBEaWJlbGkgKioiNSA8IG4gPCAyMSIqKiBLYWxpDQoNCkthc3VzIGRpbWFuYSBwZXNhbmFuIGRpdGVtcGF0a2FuIHVudHVrIGJlcmJhZ2FpIGthdGVnb3JpIHByb2R1ayBkYW4gc2V0aWFwIGthdGVnb3JpIHByb2R1ayBkaWJlbGkgKipsZWJpaCBkYXJpIDUgdGV0YXBpIGt1cmFuZyBkYXJpIDIxIGthbGkqKi4gUGx1cywgZGFmdGFyIGRpIGJhd2FoIGluaSBtZW55ZWRpYWthbiBiZWJlcmFwYSBrYXRlZ29yaSB5YW5nIHBhbGluZyBzZXJpbmcgZGlwZXNhbi4NCg0KLSBBaXIgQ29uZGl0aW9uaW5nIChBQykNCi0gQ29uc3RydWN0aW9uIHRvb2xzIEdhcmRlbiAoQWxhdCBLb25zdHJ1a3NpIFRhbWFuKQ0KLSBGaXhlZCBUZWxlcGhvbnkgKFRlbGVwb24gVGV0YXApDQotIEhvbWUgQXBwbGlhbmNlcyAyIChQZXJsYXRhbiBSdW1haCBUYW5nZ2EgMikNCi0gTWFya2V0IFBsYWNlIChQYXNhcikNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OSwgZmlnLndpZHRoPTh9DQpQZHQuR3IgJT4lIGdyb3VwX2J5X2F0KHZhcnMocHVyY2hhc2VfeWVhciwgcHVyY2hhc2VfbW9udGgsIHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSkgJT4lIGZpbHRlcighaXMubmEocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpKSU+JSBjb3VudChwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkgJT4lIGFycmFuZ2UoZGVzYyhuKSkgJT4lIGZpbHRlcighaXMubmEocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpKSAlPiUgZmlsdGVyKG4gPiA1ICYgbiA8IDIxKSAlPiUgZ2dwbG90KGFlcyh4ID0gcHVyY2hhc2VfbW9udGgsIHkgPSBuKSkrDQogIGdlb21fYm94cGxvdChjb2xvciA9ICJuYXZ5Ymx1ZSIsIGFscGhhID0gMC40NSkrDQogIGNvb3JkX2ZsaXAoKSsNCiAgZmFjZXRfd3JhcCgufmZhY3Rvcihwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCksIHNjYWxlcyA9ICJmcmVlX3giKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUuNSksIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJ3aGl0ZSIpLCBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSwgcGFuZWwuZ3JpZC5tYWpvci55ID0gIGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5ODkiLCBsaW5ldHlwZSA9IDMpKSsNCiAgbGFicyh0aXRsZSA9ICJCYWdpYW4gMDM6IEthdGVnb3JpIFlhbmcgU2VyaW5nIERpYmVsaSAnNSA8IG4gPCAyMScgS2FsaSIsIHggPSAiQnVsYW46IEphbnVhcnkgLi4uIERlY2VtYmVyIiwgeSA9ICJuID0gQmVyYXBhIGthbGkgS2F0ZWdvcmkgUHJvZHVrIERpYmVsaSIpDQoNCmBgYA0KDQojIyMgRGliZWxpICoqIjIwIDwgbiA8IDkzIioqIGthbGkNCg0KS3VzdXMgZGltYW5hIHBlc2FuYW4gZGl0ZW1hcGF0a2FuIHVudHVrIGJlcmFiYWdhaSBrYXRlZ29yaSBwcm9kdWsgZGFuIHNldGlhcCBrYXRlZ29yaSBwcm9kdWsgZGViZWxpICoqTGViaWggZGFyaSBkdWEgcHVsdWggdGV0YXBpIGt1cmFuZyBkYXJpIHNlbWJpbGFuIHB1bHVoIHRpZ2Ega2FsaSoqLiBQbHVzLCBkYWZ0YXIgZGkgYmF3YWggaW5pIG1lbnllZGlha2FuIGJlYmVyYXBhIGthdGVnb3JpIHlhbmcgcGFsaW5nIHNlcmluZyBkaXBlc2FuLg0KDQotIEJvb2tzIGdlbmVyYWwgaW50ZXJlc3QgKEJ1a3UgTWluYXQgVW11bSkNCi0gQ29uc29sZSBnYW1lcyAoR2FtZSBLb25zb2wpDQotIEhvbWUgYXBwbGlhbmNlcyAoUGVyYWxhdGFuIFJ1bWFoIFRhbmdnYSkNCi0gTHVnZ2FnZSBhY2Nlc3NvcmllcyAoQWtzZXNvcmlzIEJhZ2FzaSkNCi0gTXVzaWNhbCBpbnN0cnVtZW50cyAoQWxhdC1hbGF0IE11c2lrKQ0KLSBTbWFsbCBhcHBsaWFuY2VzIChQZXJsYXRhbiBLZWNpbCkNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OSwgZmlnLndpZHRoPTh9DQoNClBkdC5HciAlPiUgZ3JvdXBfYnlfYXQodmFycyhwdXJjaGFzZV95ZWFyLCBwdXJjaGFzZV9tb250aCwgcHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpKSAlPiUgZmlsdGVyKCFpcy5uYShwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkpJT4lIGNvdW50KHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSAlPiUgYXJyYW5nZShkZXNjKG4pKSAlPiUgZmlsdGVyKCFpcy5uYShwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkpICU+JSBmaWx0ZXIobiA+IDIwICYgbiA8IDkzKSAlPiUgZ2dwbG90KGFlcyh4ID0gcHVyY2hhc2VfbW9udGgsIHkgPSBuKSkrDQogIGdlb21fYm94cGxvdChjb2xvciA9ICJvcmFuZ2VyZWQiLCBhbHBoYSA9IDAuNjMpKw0KICBjb29yZF9mbGlwKCkrDQogIGZhY2V0X3dyYXAoLn5mYWN0b3IocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpLCBzY2FsZXMgPSAiZnJlZV94IikrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1LjUpLCBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSwgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gIndoaXRlIiksIHBhbmVsLmdyaWQubWFqb3IueSA9ICBlbGVtZW50X2xpbmUoY29sb3IgPSAiY29ybnNpbGsiLCBsaW5ldHlwZSA9IDMpKSsNCiAgbGFicyh0aXRsZSA9ICJCYWdpYW4gMDQ6IEthdGVnb3JpIFlhbmcgU2VyaW5nIERpYmVsaSAnMjAgPCBuIDwgOTMnIEthbGkiLCB4ID0gIkJ1bGFuOiBKYW51YXJ5IC4uLiBEZWNlbWJlciIsIHkgPSAibiA9IEJlcmFwYSBrYWxpIFByb2R1ayBZYW5nIERpYmVsaSIpDQoNCmBgYA0KDQojIyMgRGliZWxpIFdha3R1ICoqIjkyIDwgbiA8IDI1MSIqKiBLYWxpDQoNCkthc3VzIGRpbWFuYSBwZXNhbmFuIGRpdGVtcGF0a2FuIHVudHVrIGJlcmJhZ2FpIGthdGVnb3JpIHByb2R1ayBkYW4gc2V0aWFwIGthdGVnb3JpIHByb2R1ayBkaWJlbGkgKipsZWJpaCBkYXJpIHNlbWJpbGFuIHB1bHVoIGR1YSB0ZXRhcGkga3VyYW5nIGRhcmkgZHVhIHJhdHVzIGxpbWEgcHVsdWggc2F0dSBrYWxpKiouIFBsdXMsIGRhZnRhcmkgZGliYXdhaCBpbmkgbWVueWVkaWFrYW4gYmViZXJhcGEga2F0ZWdvcmkgeWFuZyBwYWxpbmcgc2VyaW5nIGRpcGVzYW4uDQoNCi0gQmFieSAoQmFieSkNCi0gQ29vbCBzdHVmZiAoQmFyYW5nIEtlcmVuKQ0KLSBHYXJkZW4gdG9vbHMgKFBlcmFsYXRhbiBLZWJ1bikNCi0gUGVyZnVtZXJ5IChXZXdhbmdpYW4pDQotIFRveXMgKE1haW5hbikNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OSwgZmlnLndpZHRoPTh9DQoNClBkdC5HciAlPiUgZ3JvdXBfYnlfYXQodmFycyhwdXJjaGFzZV95ZWFyLCBwdXJjaGFzZV9tb250aCwgcHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpKSAlPiUgZmlsdGVyKCFpcy5uYShwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkpJT4lIGNvdW50KHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSAlPiUgYXJyYW5nZShkZXNjKG4pKSAlPiUgZmlsdGVyKCFpcy5uYShwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkpICU+JSBmaWx0ZXIobiA+IDkyICYgbiA8IDI1MSkgJT4lIGdncGxvdChhZXMoeCA9IHB1cmNoYXNlX21vbnRoLCB5ID0gbikpKw0KICBnZW9tX2JveHBsb3QoY29sb3IgPSAibmF2eWJsdWUiLCBhbHBoYSA9IDAuNDUpKw0KICBjb29yZF9mbGlwKCkrDQogIGZhY2V0X3dyYXAoLn5mYWN0b3IocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpLCBzY2FsZXMgPSAiZnJlZV94IikrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1LjUpLCBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSwgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gIndoaXRlIiksIHBhbmVsLmdyaWQubWFqb3IueSA9ICBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTg5IiwgbGluZXR5cGUgPSAzKSkrDQogIGxhYnModGl0bGUgPSAiQmFnaWFuIDA1OiBLYXRlZ29yaSBQcm9kdWsgU2VyaW5nIERpYmVsaSAnOTIgPCBuIDwgMjUxJyBLYWxpIiwgeCA9ICJCdWxhbjogSmFudWFyeSAuLi4gRGVjZW1iZXIiLCB5ID0gIm4gPSBCZXJhcGEgS2FsaSBQcm9kdWsgWWFuZyBEaWJlbGkiKQ0KDQpgYGANCg0KIyMjIERpYmVsaSAqKiIyNTAgPCBuIioqIEthbGkNCg0KS2FzdXMgZGltYW5hIHBlc2FuYW4gZGl0ZW1wYXRrYW4gdW50dWsgYmVyYmFnYWkga2F0ZWdvcmkgcHJvZHVrIGRhbiBzZXRpYXAga2F0ZWdvcmkgcHJvZHVrIGRpYmVsaSAqKmxlYmloIGRhcmkgZHVhIHJhdHVzIGxpbWEgcHVsdWgga2FsaSoqLiBQbHVzLCBkYWZ0YXIgZGliYXdhaCBpbmkgbWVueWVkaWFrYW4gYmViZXJhcGEga2F0ZWdvcmkgeWFuZyBwYWxpbmcgc2VyaW5nIGRpcGVzYW4uDQoNCi0gQmVkIGJhdGggdGFibGUgKE1lamEgS2FtYXIgTWFuZGkgVGVtcGF0IFRpZHVyKQ0KLSBDb21wdXRlciBhY2Nlc3NvcmllcyAoQWtzZXNvcmlzIEtvbXB1dGVyKQ0KLSBGdXJuaXR1cmUgZGVjb3IgKERla29yYXNpIEZ1cm5pdHVyKQ0KLSBIZWFsdGggYmVhdXR5IChLZW5jYXRpa2FuIEtlc2VoYXRhbikNCi0gSG91c2V3YXJlcyAoUGVybGF0YW4gUnVtYWggVGFuZ2dhKQ0KLSBTcG9ydHMgbGVpc3VyZSAoT2xhaHJhZ2EgUmVrcmVzaSkNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OX0NCg0KUGR0LkdyICU+JSBncm91cF9ieV9hdCh2YXJzKHB1cmNoYXNlX3llYXIsIHB1cmNoYXNlX21vbnRoLCBwcm9kdWN0X2NhdGVnb3J5X25hbWVfZW5nbGlzaCkpICU+JSBmaWx0ZXIoIWlzLm5hKHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSklPiUgY291bnQocHJvZHVjdF9jYXRlZ29yeV9uYW1lX2VuZ2xpc2gpICU+JSBhcnJhbmdlKGRlc2MobikpICU+JSBmaWx0ZXIoIWlzLm5hKHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSAmIG4gPjI1MCkgJT4lIGdncGxvdChhZXMoeCA9IHB1cmNoYXNlX21vbnRoLCB5ID0gbikpKw0KICBnZW9tX2JveHBsb3QoY29sb3IgPSAib3JhbmdlcmVkIiwgYWxwaGEgPSAwLjYzKSsNCiAgY29vcmRfZmxpcCgpKw0KICBmYWNldF93cmFwKC5+ZmFjdG9yKHByb2R1Y3RfY2F0ZWdvcnlfbmFtZV9lbmdsaXNoKSwgc2NhbGVzID0gImZyZWVfeCIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJ3aGl0ZSIpLCBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSwgcGFuZWwuZ3JpZC5tYWpvci55ID0gIGVsZW1lbnRfbGluZShjb2xvciA9ICJjb3Juc2lsayIsIGxpbmV0eXBlID0gMykpKw0KICBsYWJzKHRpdGxlID0gIkJhZ2lhbiAwNjogUHJvZHVrIFlhbmcgU2VyaW5nIERpYmVsaSAnbiA+IDI1MCcgS2FsaSIsIHggPSAiQnVsYW46IEphbnVhcnkgLi4uIERlY2VtYmVyIiwgeSA9ICJuID0gQmVyYXBhIEthbGkgUHJvZHVrIFlhbmcgRGliZWxpIikNCg0KYGBgDQoNCiMgRml0dXIsIFJlbGFzaSwgJiBQZXJzYW1hYW4gUGVudGluZw0KDQprLW1lYW5zIGNsdXN0ZXJpbmcgdGVsYWggZGlndW5ha2FuIHVudHVrIG1lbWJ1YXQgY2x1c3RlciBkYW4gbWVuZW11a2FuIGZpdHVyIHlhbmcgc2lnbmlmaWthbiwgaW5pIG1lbWJhbnR1IHNheWEgbWVsaWhhdCBrZWRhbGFtOyBiYWdhaW1hbmEgZml0dXItZml0dXIgaXR1IGJlcmludGVyYWtzaSBkYW4gYXBhIGh1YnVuZ2FuIGRpIGFudGFyYSBtZXJla2E/IENsdXN0ZXIgZGlidWF0IHVudHVrIG1lbGloYXQgZGF0YSBkYWxhbSBiZW50dWsgdGFiZWwgZGFuIHVudHVrIG1lbmVtdWthbiBwZXJzYW1hYW4gcG9saW5vbWlhbC4NCg0KIyMgayAtIG1lYW5zIENsdXN0ZXJpbmcgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNClRpZGFrIGFkYSBtZXRvZGUgaWxtaWFoIHlhbmcgZGlndW5ha2FuIHVudHVrIG1lbmdoaXR1bmcganVtbGFoIGNsdXN0ZXIsIHNheWEgbWVtYXNhbmcgNiBzZWJhZ2FpIGp1bWxhaCBwdXNhdCwgdW50dWsgbWVuamFnYSBhZ2FyIHNlbXVhbnlhIHRldGFwIGJlcm5vbW9yLiBwZXJ0YW1hLCBzZWJ1YWggdGFiZWwgYmVzYXIgdGVsYWggZGlidWF0IHlhbmcgYmVyaXNpIHNlbXVhIGZpdHVyIHlhbmcgcmVsZXZhbiBkYXJpIHNlbXVhIGt1bXB1bGFuIGRhdGEgKCpTZXRpZGFrbnlhIGRhcmkgc3VkdXQgcGFuZGFuZyBhbmFseXNpcyBzYXlhKikuIFNheWEgbWVsYWt1a2FuIGJlcmJhZ2FpIHByZW11dGFzaSBkYW4ga29tYmluYXNpIHVudHVrIG1lbmdoYXNpbGthbiBmaXR1ciBwYWxpbmcgc2lnbmlmaWthbiB5YW5nIGRhcGF0IG1lbXBlcnRhaGFua2FuIGp1bWxhaCB0dXBlbCB5YW5nIGtpcmEta2lyYSBzYW1hIGRpIHNldGlhcCBjbHVzdGVyLiBMYXRpaGFuIGluaSBtZW1iZXJpIHNheWEgZml0dXIgYmVyaWt1dCwgeWFuZyBuaWxhaW55YSBwZXJ0YW1hIGthbGkgZGlub3JtYWxpc2FzaSBkYW4ga2VtdWRpYW4gbWVyZWthIGJlcnRpZGFrIHNlYmFnYWkgdHVsYW5nIHB1bmdndW5nIGtsdXN0ZXIgc2F5YS4NCg0KLSAqKldha3R1IExlZCBBa3R1YWwgKGhhcmkpOioqIEp1bWxhaCBoYXJpIHlhbmcgZGlidXR1aGthbiB1bnR1ayBtZW5nZXJpbWthbiBwcm9kdWsga2UgcGVsYW5nZ2FuLCBkYXJpIHNhYXQgcGVzYW5hbiB0ZWxhaCBkaXRlbXBhdGthbiBkaSBzaXN0ZW0uDQotICoqSUQgUGVzYW5hbjoqKiBJZGVudGlmaWthc2kgUGVzYW5hbi4NCi0gKipXYWt0dSBQZXJzdHVqdWFuIChtZW5pdCk6KiogV2FrdHUgeWFuZyBkaWJ1dHVoa2FuIG9sZWggc2lzdGVtIE9saXN0IHVudHVrIG1lbnlldHVqdWkgcGVzYW5hbiBzZXRlbGFoIHBlc2FuYW4gZGlsYWt1a2FuIGRhbiBzZWJlbHVtIGRpYmVyaXRhaHVrYW4ga2VwYWRhIHBlbWFzb2svcGVuZ2FuZ2t1dCBiYXJhbmcuDQotICoqSUQgQmFyYW5nIFBlc2FuYW46KiogSnVtbGFoIGJhcmFuZy9wZXNhbmFuLg0KLSAqKkhhcmdhOioqIEhhcmdhL0JhcmFuZywgZGliZWJhbmthbiBkYXJpIHBlbGFuZ2dhbi4NCi0gKipOaWxhaSBQZW5nZXJpbWFuOioqIEJpYXlhIFBlbmdlcmltYW4vQmFyYW5nLCBkaWJlYmFua2FuIGRhcmkgcGVsYW5nZ2FuLg0KLSAqKkJlcmF0IFByb2R1ayAoZ21zKToqKiBCZXJhdCBQcm9kdWsgZGFsYW0gR3JhbQ0KDQoqKkhhcmFwIERpY2F0YXQ6KiogSGFyZ2EgJiBOaWxhaSBQZW5nZXJpbWFuIGFkYWxhaCBqdW1sYWggeWFuZyBkaWJlYmFua2FuIHBlciBpdGVtIGRhbiBidWthbiBwZXIgcGVzYW5hbi4gUGx1cywgUGVzYW5hbiBtdW5na2luIG1lbWlsaWtpIGxlYmloIGRhcmkgc2F0dSBpdGVtLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCg0KVG90YWwuR3IgPC0gaW5uZXJfam9pbihTZWxsZXIuR3IsIEN1c3RvbWVycywgYnkgPSJjdXN0b21lcl9pZCIpDQoNClRvdC5HciA8LSBuYS5vbWl0KFRvdGFsLkdyKQ0KVG90LkdyMiA8LSBUb3QuR3IgJT4lIHNlbGVjdF9hdCh2YXJzKG9yZGVyX2lkLCBBY3QuTGVhZC50LCBBcHByb3ZhbC5taW5zLCBvcmRlcl9pdGVtX2lkLCBwcmljZSwgZnJlaWdodF92YWx1ZSAscHJvZHVjdF93ZWlnaHRfZykpDQoNCnNldC5zZWVkKDMyMTIzKQ0KcHJlcHJvYyA8LSBwcmVQcm9jZXNzKFRvdC5HcjJbMjo3XSwgbWV0aG9kID0gYygicmFuZ2UiKSkNClRvdC5Hcm4gPC0gcHJlZGljdChwcmVwcm9jLCBUb3QuR3IyKQ0KDQpUb3QuR3JrbSA8LSBrbWVhbnMoVG90LkdyMlsyOjddLCBjZW50ZXJzID0gNiwgaXRlci5tYXggPSAxMDAwKQ0KDQpUb3QuR3JrbTEgPC0gc3Vic2V0KFRvdC5HciwgVG90Lkdya20kY2x1c3RlciA9PSAxKQ0KVG90Lkdya20yIDwtIHN1YnNldChUb3QuR3IsIFRvdC5HcmttJGNsdXN0ZXIgPT0gMikNClRvdC5HcmttMyA8LSBzdWJzZXQoVG90LkdyLCBUb3QuR3JrbSRjbHVzdGVyID09IDMpDQpUb3QuR3JrbTQgPC0gc3Vic2V0KFRvdC5HciwgVG90Lkdya20kY2x1c3RlciA9PSA0KQ0KVG90Lkdya201IDwtIHN1YnNldChUb3QuR3IsIFRvdC5HcmttJGNsdXN0ZXIgPT0gNSkNClRvdC5HcmttNiA8LSBzdWJzZXQoVG90LkdyLCBUb3QuR3JrbSRjbHVzdGVyID09IDYpDQoNClRvdC5HcmttMSA8LSBtdXRhdGUoVG90Lkdya20xLCBDbHVzdCA9ICJDbHVzdGVyMSIpDQpUb3QuR3JrbTIgPC0gbXV0YXRlKFRvdC5HcmttMiwgQ2x1c3QgPSAiQ2x1c3RlcjIiKQ0KVG90Lkdya20zIDwtIG11dGF0ZShUb3QuR3JrbTMsIENsdXN0ID0gIkNsdXN0ZXIzIikNClRvdC5HcmttNCA8LSBtdXRhdGUoVG90Lkdya200LCBDbHVzdCA9ICJDbHVzdGVyNCIpDQpUb3QuR3JrbTUgPC0gbXV0YXRlKFRvdC5HcmttNSwgQ2x1c3QgPSAiQ2x1c3RlcjUiKQ0KVG90Lkdya202IDwtIG11dGF0ZShUb3QuR3JrbTYsIENsdXN0ID0gIkNsdXN0ZXI2IikNCg0KVG90LkdyMyA8LSB1bmlvbl9hbGwoVG90Lkdya20xLCBUb3QuR3JrbTIpDQpUb3QuR3IzIDwtIHVuaW9uX2FsbChUb3QuR3IzLCBUb3QuR3JrbTMpDQpUb3QuR3IzIDwtIHVuaW9uX2FsbChUb3QuR3IzLCBUb3QuR3JrbTQpDQpUb3QuR3IzIDwtIHVuaW9uX2FsbChUb3QuR3IzLCBUb3QuR3JrbTUpDQpUb3QuR3IzIDwtIHVuaW9uX2FsbChUb3QuR3IzLCBUb3QuR3JrbTYpDQoNCncgPC0gVG90LkdyMyAlPiUgZmlsdGVyKG9yZGVyX3N0YXR1cyA9PSAiZGVsaXZlcmVkIiklPiUgc2VsZWN0X2F0KHZhcnMoQ2x1c3QsIHB1cmNoYXNlX3F1YXJ0LCBBY3QuTGVhZC50LCBBcHByb3ZhbC5taW5zLCBvcmRlcl9pdGVtX2lkLCBwcmljZSwgZnJlaWdodF92YWx1ZSAscHJvZHVjdF93ZWlnaHRfZykpICU+JSBncm91cF9ieShDbHVzdCwgcHVyY2hhc2VfcXVhcnQpICU+JSBzdW1tYXJpc2VfZWFjaChmdW5zKG1lZGlhbikpDQpjb2xuYW1lcyh3KSA8LSBjKCJDbHVzdGVyIiwiUXVhcnRlciIsIkFjdHVhbCBMZWFkIFRpbWUgKGRheXMpIiwiQXBwcm92YWwgKG1pbnMpIiwiSXRtZXMgcGVyIE9yZGVyIiwiUHJpY2UiLCJGcmVpZ2h0IFZhbHVlIiwiV2VpZ2h0IChnbXMpIikNCg0KYGBgDQoNCiMjIyBDbHVzdGVyIDENCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQoNCncxIDwtIHcgJT4lIGZpbHRlcihDbHVzdGVyID09ICJDbHVzdGVyMSIpDQprYWJsZSh3MSwgZGlnaXRzID0gMiwgY2FwdGlvbiA9ICJGYWN0b3JzIGZvciBrLW1lYW5zIGNsdXN0ZXJpbmcgJiB0aGVpciB2YWx1ZXMiKSAlPiUga2FibGVfc3R5bGluZyhjKCJzdHJpcGVkIiwiYm9yZGVyZWQiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKSU+JSBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiPTIsIkZhY3RvciAwMSIgPSAyLCAiRmFjdG9yIDAyIiA9IDMsICJGYWN0b3IgMDMiID0gMSkpICU+JSBncm91cF9yb3dzKGluZGV4ID0gYygiWWVhciAyMDE2IiA9IDEsICJZZWFyIDIwMTciID0gNCwgIlllYXIgMjAxOCIgPSAzKSkgJT4lIGZvb3Rub3RlKGdlbmVyYWwgPSAiICAgIiwgYWxwaGFiZXQgPSBjKCJPcmRlcnMgZGVsaXZlcmVkIiksbnVtYmVyID0gYygiT25seSBNRURJQU5zIHBlciBxdWFydGVyIHBlciBmYWN0b3IgYXJlIHN0YXRlZCIpLCBhbHBoYWJldF90aXRsZSA9ICJPcmRlciBTdGF0dXMgOjoiLCBudW1iZXJfdGl0bGUgPSAiVmFsdWVzIDo6Iixmb290bm90ZV9hc19jaHVuayA9IFQpDQpgYGANCg0KIyMjIENsdXN0ZXIgMg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCg0KdzIgPC0gdyAlPiUgZmlsdGVyKENsdXN0ZXIgPT0gIkNsdXN0ZXIyIikNCmthYmxlKHcyLCBkaWdpdHMgPSAyLCBjYXB0aW9uID0gIkZhY3RvcnMgZm9yIGstbWVhbnMgY2x1c3RlcmluZyAmIHRoZWlyIHZhbHVlcyIpICU+JSBrYWJsZV9zdHlsaW5nKGMoInN0cmlwZWQiLCJib3JkZXJlZCIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEYpJT4lIGFkZF9oZWFkZXJfYWJvdmUoYygiICI9MiwiRmFjdG9yIDAxIiA9IDIsICJGYWN0b3IgMDIiID0gMywgIkZhY3RvciAwMyIgPSAxKSkgJT4lIGdyb3VwX3Jvd3MoaW5kZXggPSBjKCJZZWFyIDIwMTYiID0gMSwgIlllYXIgMjAxNyIgPSA0LCAiWWVhciAyMDE4IiA9IDMpKSAlPiUgZm9vdG5vdGUoZ2VuZXJhbCA9ICIgICAiLCBhbHBoYWJldCA9IGMoIk9yZGVycyBkZWxpdmVyZWQiKSxudW1iZXIgPSBjKCJPbmx5IE1FRElBTnMgcGVyIHF1YXJ0ZXIgcGVyIGZhY3RvciBhcmUgc3RhdGVkIiksIGFscGhhYmV0X3RpdGxlID0gIk9yZGVyIFN0YXR1cyA6OiIsIG51bWJlcl90aXRsZSA9ICJWYWx1ZXMgOjoiLGZvb3Rub3RlX2FzX2NodW5rID0gVCkNCmBgYA0KDQojIyMgQ2x1c3RlciAzDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KDQp3MyA8LSB3ICU+JSBmaWx0ZXIoQ2x1c3RlciA9PSAiQ2x1c3RlcjMiKQ0Ka2FibGUodzMsIGRpZ2l0cyA9IDIsIGNhcHRpb24gPSAiRmFjdG9ycyBmb3Igay1tZWFucyBjbHVzdGVyaW5nICYgdGhlaXIgdmFsdWVzIikgJT4lIGthYmxlX3N0eWxpbmcoYygic3RyaXBlZCIsImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRiklPiUgYWRkX2hlYWRlcl9hYm92ZShjKCIgIj0yLCJGYWN0b3IgMDEiID0gMiwgIkZhY3RvciAwMiIgPSAzLCAiRmFjdG9yIDAzIiA9IDEpKSAlPiUgZ3JvdXBfcm93cyhpbmRleCA9IGMoIlllYXIgMjAxNiIgPSAxLCAiWWVhciAyMDE3IiA9IDQsICJZZWFyIDIwMTgiID0gMykpICU+JSBmb290bm90ZShnZW5lcmFsID0gIiAgICIsIGFscGhhYmV0ID0gYygiT3JkZXJzIGRlbGl2ZXJlZCIpLG51bWJlciA9IGMoIk9ubHkgTUVESUFOcyBwZXIgcXVhcnRlciBwZXIgZmFjdG9yIGFyZSBzdGF0ZWQiKSwgYWxwaGFiZXRfdGl0bGUgPSAiT3JkZXIgU3RhdHVzIDo6IiwgbnVtYmVyX3RpdGxlID0gIlZhbHVlcyA6OiIsZm9vdG5vdGVfYXNfY2h1bmsgPSBUKQ0KYGBgDQoNCiMjIyBDbHVzdGVyIDQNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQoNCnc0IDwtIHcgJT4lIGZpbHRlcihDbHVzdGVyID09ICJDbHVzdGVyNCIpDQprYWJsZSh3NCwgZGlnaXRzID0gMiwgY2FwdGlvbiA9ICJGYWN0b3JzIGZvciBrLW1lYW5zIGNsdXN0ZXJpbmcgJiB0aGVpciB2YWx1ZXMiKSAlPiUga2FibGVfc3R5bGluZyhjKCJzdHJpcGVkIiwiYm9yZGVyZWQiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKSU+JSBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiPTIsIkZhY3RvciAwMSIgPSAyLCAiRmFjdG9yIDAyIiA9IDMsICJGYWN0b3IgMDMiID0gMSkpICU+JSBncm91cF9yb3dzKGluZGV4ID0gYygiWWVhciAyMDE2IiA9IDEsICJZZWFyIDIwMTciID0gNCwgIlllYXIgMjAxOCIgPSAzKSkgJT4lIGZvb3Rub3RlKGdlbmVyYWwgPSAiICAgIiwgYWxwaGFiZXQgPSBjKCJPcmRlcnMgZGVsaXZlcmVkIiksbnVtYmVyID0gYygiT25seSBNRURJQU5zIHBlciBxdWFydGVyIHBlciBmYWN0b3IgYXJlIHN0YXRlZCIpLCBhbHBoYWJldF90aXRsZSA9ICJPcmRlciBTdGF0dXMgOjoiLCBudW1iZXJfdGl0bGUgPSAiVmFsdWVzIDo6Iixmb290bm90ZV9hc19jaHVuayA9IFQpDQpgYGANCg0KIyMjIENsdXN0ZXIgNQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCg0KdzUgPC0gdyAlPiUgZmlsdGVyKENsdXN0ZXIgPT0gIkNsdXN0ZXI1IikNCmthYmxlKHc1LCBkaWdpdHMgPSAyLCBjYXB0aW9uID0gIkZhY3RvcnMgZm9yIGstbWVhbnMgY2x1c3RlcmluZyAmIHRoZWlyIHZhbHVlcyIpICU+JSBrYWJsZV9zdHlsaW5nKGMoInN0cmlwZWQiLCJib3JkZXJlZCIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEYpJT4lIGFkZF9oZWFkZXJfYWJvdmUoYygiICI9MiwiRmFjdG9yIDAxIiA9IDIsICJGYWN0b3IgMDIiID0gMywgIkZhY3RvciAwMyIgPSAxKSkgJT4lIGdyb3VwX3Jvd3MoaW5kZXggPSBjKCJZZWFyIDIwMTYiID0gMSwgIlllYXIgMjAxNyIgPSA0LCAiWWVhciAyMDE4IiA9IDMpKSAlPiUgZm9vdG5vdGUoZ2VuZXJhbCA9ICIgICAiLCBhbHBoYWJldCA9IGMoIk9yZGVycyBkZWxpdmVyZWQiKSxudW1iZXIgPSBjKCJPbmx5IE1FRElBTnMgcGVyIHF1YXJ0ZXIgcGVyIGZhY3RvciBhcmUgc3RhdGVkIiksIGFscGhhYmV0X3RpdGxlID0gIk9yZGVyIFN0YXR1cyA6OiIsIG51bWJlcl90aXRsZSA9ICJWYWx1ZXMgOjoiLGZvb3Rub3RlX2FzX2NodW5rID0gVCkNCmBgYA0KDQojIyMgQ2x1c3RlciA2DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KDQp3NiA8LSB3ICU+JSBmaWx0ZXIoQ2x1c3RlciA9PSAiQ2x1c3RlcjYiKQ0Ka2FibGUodzYsIGRpZ2l0cyA9IDIsIGNhcHRpb24gPSAiRmFjdG9ycyBmb3Igay1tZWFucyBjbHVzdGVyaW5nICYgdGhlaXIgdmFsdWVzIikgJT4lIGthYmxlX3N0eWxpbmcoYygic3RyaXBlZCIsImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRiklPiUgYWRkX2hlYWRlcl9hYm92ZShjKCIgIj0yLCJGYWN0b3IgMDEiID0gMiwgIkZhY3RvciAwMiIgPSAzLCAiRmFjdG9yIDAzIiA9IDEpKSAlPiUgZ3JvdXBfcm93cyhpbmRleCA9IGMoIlllYXIgMjAxNiIgPSAxLCAiWWVhciAyMDE3IiA9IDQsICJZZWFyIDIwMTgiID0gMykpICU+JSBmb290bm90ZShnZW5lcmFsID0gIiAgICIsIGFscGhhYmV0ID0gYygiT3JkZXJzIGRlbGl2ZXJlZCIpLG51bWJlciA9IGMoIk9ubHkgTUVESUFOcyBwZXIgcXVhcnRlciBwZXIgZmFjdG9yIGFyZSBzdGF0ZWQiKSwgYWxwaGFiZXRfdGl0bGUgPSAiT3JkZXIgU3RhdHVzIDo6IiwgbnVtYmVyX3RpdGxlID0gIlZhbHVlcyA6OiIsZm9vdG5vdGVfYXNfY2h1bmsgPSBUKQ0KYGBgDQoNCiMjIEludGVycHJldGFiaWxpdGFzIGh1YnVuZ2FuIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQ0KDQpEaSBiYWdpYW4gaW5pLCB1cGF5YSBzYXlhIGFkYWxhaCB1bnR1ayBtZWxpaGF0IGh1YnVuZ2FuIGFudGFyYSAgKipOaWxhaSBQZW5nZXJpbWFuIFBlciBQZXNhbmFuKiogWWFuZyBkaWJheWFyIHBlbGFuZ2dhbiBkYW4gICoqSnVtbGFoIEJhcmFuZyBQZXIgUGVzYW5hbioqLiBTZWthcmFuZyB1bnR1ayBtZW5hZnNpcmthbiBodWJ1bmdhbiBpbmkgc2F5YSBtZW5nZ3VuYWthbiAqKlBlcnNhbWFhbiBSZWdyZXNpKiosIHRlcnV0YW1hIHlhbmcgZGFwYXQgbWVtYmFudHV1IGRhbGFtIGluZmVyZW5zaSBkYW4gamF1aCBsZWJpaCBkYXBhdCBkaXRhZnNpcmthbiwgU2F5YSB0ZWxhaCBtZW1pbGloICoqUGVyc2FtYWFuIEt1YXNpLVBvaXNzb24qKiAtIEthcmVhbiBkaXNpbmkga2l0YSBtZWxpaGF0IGRhdGEgaGl0dW5nYW4gZGFuICoqUGVyc2FtYWFuIFBvbGlub21pYWwqKiAtIHNlYmFnYWkgdXBheWEgdW11bSAqKFRhbnBhIHVqaSB0dW50YXMgcGFkYSBha3VyYXNpIGF0YXUgcGVtYnVhdGFuIG1vZGVsKSouIA0KDQpNYXJpIGtpdGEgbXVsYWkgZGVuZ2FuIEdyYWZpayB0ZXJsZWJpaCBkYWh1bHU6IEdyYWZpayBpbmkgYWRhbGFoICgqVHJhZGUtT2ZmIGFudGFyYSBGbGVrc2liaWxpdGFzIGRhbiBJbnRlcnByZXRhYmlsbHRhcyopIG1ha2EgcGVyc2FtYWFuIHNheWEgcmVuZGFoIHBhZGEgZmxla3NpYmlsaXRhcyBhdGF1IGFrdXJhc2kgZGFuIHJlbGF0aWYgdGluZ2dpIHBhZGEgaW50ZXJwcmV0YXNpIC0gc2VwZXJ0aSB5YW5nIGRpdHVuanVra2FuIG9sZWggc3RhdHVzICoqR3JheSBQT0lOVCoqIFBhZGEgZ3JhZmlrLg0KDQoqWyoqUGVybHUgRGljYXRhdCoqXSBTYXlhIHRpZGFrIG1lbnVuanVra2FuIGludGVydmFsIGtlcGVyY2F5YWFuIHVudHVrIHBhcmFtZXRlciBtb2RlbCBkYW4gZ3JhZmlrIHJlc2lkdWFsIHVudHVrIG1lbmVudHVrYW4gYXBha2FoIG1vZGVsIGNvY29rIGF0YXUgdGlkYWsuKg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBlY2hvPUZBTFNFfQ0KDQpnZ3Bsb3QoKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpKw0KICBnZW9tX3RleHQoYWVzKHggPSAxLCB5ID0gNiwgbGFiZWwgPSAiSGlnaCIpLCBpbmhlcml0LmFlcyA9IEZBTFNFKSsNCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMSwgeSA9IDEuNSwgbGFiZWwgPSAiTG93IiksIGluaGVyaXQuYWVzID0gRkFMU0UpKw0KICBnZW9tX3RleHQoYWVzKHggPSA2LCB5ID0gMS41LCBsYWJlbCA9ICJIaWdoIiksIGluaGVyaXQuYWVzID0gRkFMU0UpKw0KICBnZW9tX3RleHQoYWVzKHggPSAwLjg1LCB5ID0gNCwgbGFiZWwgPSAiSW50ZXJwcmV0YWJpbGl0eSB+IGxlc3MgYWNjdXJhY3kiLCBhbmdsZSA9IDkwKSwgaW5oZXJpdC5hZXMgPSBGQUxTRSkrDQogIGdlb21fdGV4dChhZXMoeCA9IDMuNzUsIHkgPSAxLjI1LCBsYWJlbCA9ICJGbGV4aWJpbGl0eSB+IG1vcmUgYWNjdXJhY3kiKSwgaW5oZXJpdC5hZXMgPSBGQUxTRSkrDQogIGdlb21fdGV4dChhZXMoeSA9IDQuNzUsIHggPSAyLjQ1LCBsYWJlbCA9ICJSZWdyZXNzaW9uczogUG9pc3NvbiAmIFBvbHlub21pYWwiKSwgaW5oZXJpdC5hZXMgPSBGQUxTRSkrDQogIGdlb21fdGV4dChhZXMoeCA9IDMuNzUsIHkgPSA0LCBsYWJlbCA9ICJJbiB0aGlzICdUcmFkZS1vZmYnIGNoYXJ0IG15IGVxdWF0aW9ucyBzdGFuZDogaGVyZSIpLCBpbmhlcml0LmFlcyA9IEZBTFNFKSsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IDEuODUsIHkgPSA0LjUpLCBzaXplID0gNCwgY29sb3IgPSAiZ3JleTkiLCBhbHBoYSA9IDAuODEsIHNoYXBlID0gMjEsIGZpbGwgPSBhbHBoYSgiZ3JheTYzIiwgMC4zKSwgaW5oZXJpdC5hZXMgPSBGQUxTRSkrDQogIGdlb21fc2VnbWVudChhZXMoeCA9IDEsIHhlbmQgPSAxLCB5ID0gMiwgeWVuZCA9IDUuNSksIGxpbmVlbmQgPSAicm91bmQiLCBsaW5ldHlwZT0gMixpbmhlcml0LmFlcyA9IEZBTFNFKSsNCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMS41LCB4ZW5kID0gNS41LCB5ID0gMS41LCB5ZW5kID0gMS41KSwgbGluZWVuZCA9ICJyb3VuZCIsIGxpbmV0eXBlPSAyLGluaGVyaXQuYWVzID0gRkFMU0UpKw0KICBnZW9tX3NlZ21lbnQoYWVzKHggPSAzLjUsIHhlbmQgPSAyLCB5ID0gNC4yNSwgeWVuZCA9IDQuNDUpLCBsaW5lZW5kID0gInJvdW5kIiwgbGluZXR5cGU9IDEsIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgwLjEsImluY2hlcyIpKSxpbmhlcml0LmFlcyA9IEZBTFNFKSsNCiAgbGFicyh4ID0gIiIsIHkgPSAiIiwgdGl0bGUgPSAiVHJhZGUtb2ZmIGFudGFyYSBGbGVraWJpbGl0YXMgJiBJbnRlcnByZXRhYmlsaXRhcyIsIA0KICAgICAgIHN1YnRpdGxlID0gIkJlcmFzYWwgRGFyaTogJ1BlbmdhbnRhciBQZW1iZWxhamFybiBTdGF0aXN0aWsnLCBCYWIgMiwgSGFsYW1hbiAtIDI1LCBHYW1iYXIgMi43IiwNCiAgICAgICBjYXB0aW9uID0gIlBlbnVsaXM6IEdhcmV0aCBKYW1lcywgRGFuaWVsYSBXaXR0ZW4sIFRyZXZvciBIYXN0aWUsIFJvYmVydCBUaWJzaGlyYW5pIikNCmBgYA0KDQoqKkRhdGEgTGVuZ2thcCoqDQoNCkl0dSAkXGZyYWN7XHRleHR7UGVueWltcGFuZ2FuIFNpc2F9fXtcdGV4dHtEZXJhamF0IEtlYmViYXNhbn19ID4gMSBcdGV4dHsgYXRhdX0gXHRleHR7IH0gXGZyYWN7XHRleHR7VmFyaWFuY2V9fXtcdGV4dHtNZWFufX0gXG5lcSAxJCBmb3IgYFBvaXNzb24gUmVncmVzc2lvbmAgYmVyYWFkYSBkaSA3Ljc3MiwgamFkaSBtdW5na2luIGFkYSBvdmVyZGlzcGVyc2kuIEthbWkgbWVueWVzdWFpa2FuIHVudHVrIG1lbXBlcmhpdHVuZ2thbiBvdmVyZGlzcGVyc2kgZGFuIG1lbmdndW5ha2FuIGBRdWFzaS1Qb2lzc29uIFJlZ3Jlc3Npb25gIFBlcnNhbWFhbi4NCg0KYFF1YXNpLVBvaXNzb246IHJlZ3Jlc3Npb24gZXF1YXRpb25gDQoNCiQkXHRleHR7QW5na3V0YW4gTmlsYWl9IFxhcHByb3ggMy4wMzcgLSAwLjAzNTd4ICsgXGVwc2lsb24gJCQNCg0KJCQgeCBcUmlnaHRhcnJvdyBcdGV4dHtKdW1sYWggSXRlbSBQZXIgT3JkZXJ9LCBcdGV4dHsgfSBcZXBzaWxvbiBcUmlnaHRhcnJvdyBcdGV4dHtlcnJvcn0kJA0KDQoqKkludGVycHJldGFzaToqKiBQcmVkaWt0b3Igc2lnbmlmaWthbiBzZWJhZ2FpIG5pbGFpLXAgJFxhcHByb3gkIE5PTCwgUGFyYW1ldGVyIERpc3BlcnNpIHVudHVrIGBRdWFzaS1Qb2lzc29uYCBrZWx1YXJnYSBkaWFtYmlsIHBhZGEgMTIuMzg3LiBpdHUgJFxiZXRhID0gLTAuMDM1NyQgYXRhdSAkXGJldGEgPCAwJCBtZW55ZXJpdGthbiBkZW5nYW0gKipTZXRpYXAgS2VuYWlrYW4gVW5pdCoqIEl0ZW0gcGVyIHBlc2FuYW4gbmlsYWkgcGVuZ2VyaW1hbiAqKmFrYW4gYmVya3VyYW5nIGRlbmdhbioqIGRhbiBha2FuIGRpa2FsaWthbiBkZW5nYW4gLTAuMDM1Ny4NCg0KSmlrYSBraXRhIG1lbmdhbWJpbCA4IHBhcmFtZXRlciBiZXJiZWRhIHVudHVrIG1lbmVudHVrYW4gKipOaWxhaSBGcmVpZ2h0Kioga2VtdWRpYW4gbWVuZ2d1bmFrYW4gYFF1YXNpLVBvaXNzb24gcmVncmVzc2lvbmAgLSBQcmVkaWt0b3IgYmVyaWt1dCBzaWduaWZpa2FuIGRlbmdhbiBuaWxhaSAkXGFwcHJveCQgTk9MOiANCg0KLSBJbnRlcmNlcHQgKE1lbmNlZ2F0KQ0KLSBOdW1iZXIgb2YgSXRlbXMgcGVyIG9yZGVyIChKdW1sYWggSXRlbSBQZXIgUGVzYW5hbikNCi0gUHJpY2UgKEhhcmdhKQ0KLSBFc3RpbWF0ZWQgbGVhZCB0aW1lIChQZXJraXJhYW4gV2FrdHUgVHVuZ2d1KQ0KLSBBY3RhdWwgbGVhZCB0aW1lIChXYWt0dSBUdW5nZ3UgQWt0dWFsKQ0KLSBQcm9kdWN0J3MgV2VpZ2h0IChnKSAoQmVyYXQgUHJvZHVrKQ0KLSBQcm9kdWN0J3MgTGVuZ3RoIChjbSkgKFBhbmphbmcgUHJvZHVrKQ0KLSBQcm9kdWN0J3MgSGVpZ2h0IChjbSkgKFRpbmdnaSBQcm9kdWspDQotIFByb2R1Y3QncyBXaWR0aCAoY20pIChMZWJhciBQcm9kdWspDQoNCi4uLmRhbiB0ZXJrYWhpciBqYXJhayBiZWx1bSBkaXBlcmhpbnR1bmdrYW4uDQoNCipOQjogLSB+fmNvcmV0fn4gcGFyYW10ZXIgeWFuZyB0aWRhay1zaW5nbmlna2FuLiBrb2RlIGRhcGF0IGRpcGVyb2xlaCBkYXJpIGJhZ2lhbiAna29kZScuKg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMjVEczY2QxIDwtIGdsbShBbmdrdXRhX05pbGFpIH4gb3JkZXJfaXRlbV9pZCwgZGF0YSA9IFRvdC5HcjMsIGZhbWlseT0icG9pc3NvbiBvciBxdWFzaXBvaXNzb24iKQ0KIyNzdW1tYXJ5KFRHM2NkMSkNCmBgYA0KDQo8aHI+DQoNCmBQb2x5bm9taWFsOiByZWdyZXNzaW9uIGVxdWF0aW9uYA0KDQokJFx0ZXh0e0FuZ2t1dGFuIE5pbGFpfSBcYXBwcm94IDE5Ljk4IC0gMTUyLjUweCArIDQ0LjQ2eF4yIC0gNzkuNDd4XjMgKyA3Ny42MnheNCArIFxlcHNpbG9uICQkDQoNCiQkIHggXFJpZ2h0YXJyb3cgXHRleHR7SnVtbGFoIEl0ZW0gUGVyIG9yZGVyfSwgXHRleHR7IH0gXGVwc2lsb24gXFJpZ2h0YXJyb3cgXHRleHR7ZXJyb3J9JCQNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQojI1RHMGNkMSA8LSBsbShmcmVpZ2h0X3ZhbHVlIH4gcG9seShvcmRlcl9pdGVtX2lkLCA2KSwgZGF0YSA9IFRvdC5HcjMpDQojI3N1bW1hcnkoVEcwY2QxKQ0KYGBgDQoNCjxocj4NCg0KIyMjIFBlcnNhbWFhbiBLbGF0ZXIgMQ0KDQpJdHUgJFxmcmFje1x0ZXh0e1BlbnlpbXBhbmFuIFNpc2F9fXtcdGV4dHtEZXJhamF0IEtlYmViYXNhbn19ID4gMSBcdGV4dHsgYXRhdX0gXHRleHR7IH0gXGZyYWN7XHRleHR7VmFyaWFuY2V9fXtcdGV4dHtNZWFufX0gXG5lcSAxJCBmb3IgYFBvaXNzb24gUmVncmVzc2lvbmAgYmVyYWRhIGRpIDMuMjA3LCBKYWRpIG11bmdraW4gYWRhIG92ZXJzaXBlcnNpLCBLYW1pIG1lbnllc3VhaWthbiB1bnR1ayBtZW1wZXJoaXR1bmdrYW4gb3ZlcmRpc3BlcnNpZGFuIG1lbmdndW5ha2FuIGBRdWFzaS1Qb2lzc29uIFJlZ3Jlc3Npb25gIFBlcnNhbWFhbi4NCg0KYFF1YXNpLVBvaXNzb246IHJlZ3Jlc3Npb24gUGVyc2FtYWFuYA0KDQokJFx0ZXh0e05pbGFpIFBlbmdpcmltYW59X1x0ZXh0eyBDbHVzdGVyIDF9IFxhcHByb3ggMi44MzAgLSAwLjAzN3ggKyBcZXBzaWxvbiAkJA0KDQokJCB4IFxSaWdodGFycm93IFx0ZXh0e0p1bWxhaCBJdGVtIFBlcm9kZXJ9LCBcdGV4dHsgfSBcZXBzaWxvbiBcUmlnaHRhcnJvdyBcdGV4dHtlcnJvcn0kJA0KICANCioqSW50ZXJwcmV0YXNpOioqIFByZWRpa3RvciBzaWduaWZpa2FuIHNlYmFnYWkgbmlsYWktcCAkXGFwcHJveCQgTk9MLCBQYXJhbWV0ZXIgRGlzcGVyc2kgdW50dWsgIGBRdWFzaS1Qb2lzc29uYCBrZWx1YXJnYSBkaWFtYmlsIG1lbmphZGkgMy45ODQuIGl0dSAkXGJldGEgPSAtMC4wMzckIGF0YXUgJFxiZXRhIDwgMCQgbWVueWVyaXRrYW4gZGVuZ2FuICoqc2V0aWFwIGtlbmFpa2FuIHVuaXQqKiBiYXJhbmcgcGVyIHBlc2FuYW4gbmlsYWkgcGVuZ2VyaW1hbiAgKipha2FuIGJlcmt1cmFuZyoqIGRhbiBha2FuIGRpa2FsaWthbiBkZW5nYW4gLTAuMDM3Lg0KDQpKaWthIGtpdGEgbWVuZ2FtYmlsIDggcGFyYW1ldGVyIGJlcmJlZGEgdW50dWsgbWVuZW50dWthbiAqKk5pbGFpIEZyZWlnaHQqKiBrZW11ZGlhbiBtZW5nZ3VuYWthbiBgUXVhc2ktUG9pc3NvbiByZWdyZXNzaW9uYCAtIHByZWRpa3RvciBiZXJpa3V0IHNpZ25pZmlrYW4gZGVuZ2FuIG5pbGFpIC1wICRcYXBwcm94JCBOT0w6IA0KDQotIEludGVyY2VwdCAoTWVuY2VnYXQpDQotIE51bWJlciBvZiBJdGVtcyBwZXIgb3JkZXIgKEp1bWxhaCBJdGVtIFBlciBQZXNhbmFuKQ0KLSBQcmljZSAoSGFyZ2EpDQotIEVzdGltYXRlZCBsZWFkIHRpbWUgKFBlcmtpcmFhbiBXYWt0dSBUdW5nZ3UpDQotIEFjdGF1bCBsZWFkIHRpbWUgKHdha3R1IFR1bmdndSBBa3R1YWwpDQotIFByb2R1Y3QncyBXZWlnaHQgKGcpIChCZXJhdCBQcm9kdWspDQotIFByb2R1Y3QncyBMZW5ndGggKGNtKSAoUGFuamFuZyBQcm9kdWspDQotIFByb2R1Y3QncyBIZWlnaHQgKGNtKSAoVGluZ2dpIFByb2R1aykNCi0gUHJvZHVjdCdzIFdpZHRoIChjbSkgKExlYmFyIFByb2R1aykNCg0KLi4uZGFuIHRlcmthaGlyIGphcmsgYmVsdW0gZGlwZXJoaXR1bmdrYW4uDQoNCipOQjogLSB+fkNvcmV0fn4gUGFyYW1hdGVyIHlhbmcgdGlkYWsgc2lnbmlmaWthbi4gS29kZSBkYXBhdCBkaXBlcm9sZWggZGFyaSBiYWdpYW4gJ0tvZGUuKg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMjVEczMSA8LSBnbG0oZnJlaWdodF92YWx1ZSB+IG9yZGVyX2l0ZW1faWQsIGRhdGEgPSBUb3QuR3JrbTEsIGZhbWlseT0icG9pc3NvbiBvciBxdWFzaXBvaXNzb24iKQ0KIyNzdW1tYXJ5KFRHMzEpDQpgYGANCg0KPGhyPg0KDQpgUG9seW5vbWlhbDogcmVncmVzc2lvbiBwZXJzYW1hYW5gDQoNCiQkXHRleHR7TmlsYWkgUGVuZ2VyaW1hbn1fXHRleHR7IENsdXN0ZXIgMX0gXGFwcHJveCAxNi4yMiAtIDk2LjU1eCAtIDIwLjgweF4zICsgMjkuNjl4XjQgLSAyMC43OHheNSArIFxlcHNpbG9uICQkDQoNCiQkIHggXFJpZ2h0YXJyb3cgXHRleHR7SnVtbGFoIEl0ZW0gUGVyIE9yZGVyfSwgXHRleHR7IH0gXGVwc2lsb24gXFJpZ2h0YXJyb3cgXHRleHR7ZXJyb3J9JCQNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQojI1RHMSA8LSBsbShmcmVpZ2h0X3ZhbHVlIH4gcG9seShvcmRlcl9pdGVtX2lkLCA2KSwgZGF0YSA9IFRvdC5HcmttMSkNCiMjc3VtbWFyeShURzEpDQpgYGANCg0KPGhyPg0KDQojIyMgUGVyc2FtYWFuIEtsYXN0ZXIgMg0KDQpJdHUgJFxmcmFje1x0ZXh0e1BlbnlpbXBhbmFuIFNpc2F9fXtEZXJhamF0IEtlYmViYXNhbn0gPiAxIFx0ZXh0eyBhdGF1fSBcdGV4dHsgfSBcZnJhY3tcdGV4dHtWYXJpYW5jZX19e1x0ZXh0e01lYW59fSBcbmVxIDEkIGZvciBgUG9pc3NvbiBSZWdyZXNzaW9uYCBiZXJhZGEgZGkgMy41MjgsIEphZGkgbXVuZ2tpbiBhZGEgb3ZlcmRpc3BlcnNpLiBLYW1pIG1lbnllc3VhaWthbiB1bnR1ayBtZW1wZXJoaXR1bmdrYW4gb3ZlcmRpc3BlcnNpIGRhbiBtZW5nZ3VuYWthbiBgUXVhc2ktUG9pc3NvbiBSZWdyZXNzaW9uYCBwZXJzYW1hYW4uDQoNCmBRdWFzaS1Qb2lzc29uOiByZWdyZXNzaW9uIFBlcnNhbWFhbmANCg0KJCRcdGV4dHtOaWxhaSBQZW5nZXJpbWFufV9cdGV4dHsgQ2x1c3RlciAyfSBcYXBwcm94IDIuODY3IC0gMC4wMTh4ICsgXGVwc2lsb24gJCQNCg0KJCQgeCBcUmlnaHRhcnJvdyBcdGV4dHtKdW1sYWggSXRlbSBQZXJvcmRlcn0sIFx0ZXh0eyB9IFxlcHNpbG9uIFxSaWdodGFycm93IFx0ZXh0e2Vycm9yfSQkDQoNCioqSW50ZXJwcmV0YXNpOioqIFByZWRpa3RvciBzaWduaWZpa2FuIHNlYmFnYWkgbmlsYWktcCAkXGFwcHJveCQgTk9MLCBwYXJhbWV0ZXIgRHNpcGVyc2kgdW50dWsgYFF1YXNpLVBvaXNzb25gIGtlbHVhcmdhIGRpIGFtYmlsIHBhZGEgNC4yMDQuIEl0dSAkXGJldGEgPSAtMC4wMTgkIGF0YXUgJFxiZXRhIDwgMCQgZW1ueWlyYXRrYW4gZGVuZ2FuICoqc2V0aWFwIGtlbmFpa2FuIHVuaXQqKiBJdGVtIHBlcnBlc2FuYW4gbmlsYWkgcGVuZ2VyaW1hbiAqKmFrYW4gYmVya3VyYW5nKiogZGFuIGFrYW4gZGlrYWxpa2FuIGRlbmdhbiAtMC4wMTguDQoNCkppa2Ega2l0YSBtZW5nYW1iaWwgOCBwYXJhbXRlciBiZXJiZWRhIHVudHVrIG1lbmVudHVrYW4gICoqTmlsYWkgRnJlaWdodCoqIGtlbXVkaWFuIG1lbmdndW5ha2FuIGBRdWFzaS1Qb2lzc29uIHJlZ3Jlc3Npb25gIC0gUHJlZGlrdG9yIGJlcmlrdXQgc2lnbmlmaWthbiBkZW5nYW4gbmlsYWkgLXAgJFxhcHByb3gkIE5PTDogDQoNCi0gSW50ZXJjZXB0IChNZW5jZWdhdCkNCi0gTnVtYmVyIG9mIEl0ZW1zIHBlciBvcmRlciAoSnVtbGFoIGl0ZW0gcGVycGVzYW5hbikNCi0gUHJpY2UgKEhhcmdhKQ0KLSBFc3RpbWF0ZWQgbGVhZCB0aW1lIChQZXJpcmFhbiBXYWt0dSBUdW5nZ3UpDQotIEFjdGF1bCBsZWFkIHRpbWUgKFdha3R1IFR1bmdndSBBa3R1YWwpDQotIFByb2R1Y3QncyBXZWlnaHQgKGcpIChCZXJhdCBQcm9kdWspDQotIFByb2R1Y3QncyBMZW5ndGggKGNtKSAoUGFuamFuZyBQcm9kdWspDQotIH5+VGluZ2dpIFByb2R1ayAoY20pfn4gDQotIH5+TGViYXIgUHJvZHVrIChjbSl+fg0KDQouLi5kYW4gdGVya2FraGlyIGphcmFrIGJlbHVtIGRpcGVyaGl0dW5na2FuLg0KDQoqTkI6IC0gfn5jb3JldH5+IGFkYWxhaCBwYXJhbXRlciB5YW5nIHRpZGFrIHNpZ25pZ2lrYW4uIGtvZGUgZGFwYXQgZGlwZXJvbGVoIGRhcmkgYmFnaWFuICdrb2RlJy4qDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyNURzMyIDwtIGdsbShmcmVpZ2h0X3ZhbHVlIH4gb3JkZXJfaXRlbV9pZCwgZGF0YSA9IFRvdC5HcmttMiwgZmFtaWx5PSJwb2lzc29uIG9yIHF1YXNpcG9pc3NvbiIpDQojI3N1bW1hcnkoVEczMikNCmBgYA0KDQo8aHI+DQoNCmBQb2x5bm9taWFsOiByZWdyZXNzaW9uIGVxdWF0aW9uYA0KDQokJFx0ZXh0e05pbGFpIFBlbmdyaW1hbn1fXHRleHR7IENsdXN0ZXIgMn0gXGFwcHJveCAxNy4xNCAtIDM0LjkxeCArIFxlcHNpbG9uICQkDQoNCiQkIHggXFJpZ2h0YXJyb3cgXHRleHR7SnVtbGFoIEl0ZW0gUGVyIE9yZGVyfSwgXHRleHR7IH0gXGVwc2lsb24gXFJpZ2h0YXJyb3cgXHRleHR7ZXJyb3J9JCQNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0V9DQojI1RHMiA8LSBsbShmcmVpZ2h0X3ZhbHVlIH4gcG9seShvcmRlcl9pdGVtX2lkLCA2KSwgZGF0YSA9IFRvdC5HcmttMikNCiMjc3VtbWFyeShURzIpDQpgYGANCg0KPGhyPg0KDQojIyMgUGVyc2FtYWFuIEtsdXN0ZXIgMw0KDQoNCkl0dSAkXGZyYWN7XHRleHR7UGVueWltcGFuYW4gU2lzYX19e0RlcmFqYXQgS2ViZWJhc2FufSA+IDEgXHRleHR7IGF0YXV9IFx0ZXh0eyB9IFxmcmFje1x0ZXh0e1ZhcmlhbmNlfX17XHRleHR7TWVhbn19IFxuZXEgMSQgZm9yIGBQb2lzc29uIFJlZ3Jlc3Npb25gIGJlcmFkYSBkaSAzNS4yMzcsIEphZGkgbXVuZ2tpbiBhZGEgb3ZlcmRpc3BlcnNpLiBLYW1pIG1lbnllc3VhaWthbiB1bnR1ayBtZW1wZXJoaXR1bmdrYW4gb3ZlcmRpc3BlcnNpIGRhbiBtZW5nZ3VuYWthbiBgUXVhc2ktUG9pc3NvbiBSZWdyZXNzaW9uYCBwZXJzYW1hYW4NCg0KUXVhc2ktUG9pc3NvbjogcmVncmVzc2lvbiBQZXJzYW1hYW5gDQoNCiQkXHRleHR7TmlsYWkgUGVuZ2VyaW1hbn1fXHRleHR7IENsdXN0ZXIgM30gXGFwcHJveCA0LjUyNSAtIDAuMDMyeCArIFxlcHNpbG9uICQkDQoNCiQkIHggXFJpZ2h0YXJyb3cgXHRleHR7SnVtbGFoIEl0ZW0gUGVyIE9yZGVyfSwgXHRleHR7IH0gXGVwc2lsb24gXFJpZ2h0YXJyb3cgXHRleHR7ZXJyb3J9JCQNCg0KICoqSW50ZXJwcmV0YXNpOioqIFByZWRpa3RvciBzaWduaWZpa2FuIHNlYmFnYWkgbmlsYWktcCAkXGFwcHJveCQgTk9MLCBwYXJhbWV0ZXIgRHNpcGVyc2kgdW50dWsgYFF1YXNpLVBvaXNzb25gIGtlbHVhcmdhIGRpIGFtYmlsIHBhZGEgMzguOTc0LiBJdHUgJFxiZXRhID0gLTAuMDMyJCBhdGF1ICRcYmV0YSA8IDAkIGVtbnlpcmF0a2FuIGRlbmdhbiAqKnNldGlhcCBrZW5haWthbiB1bml0KiogSXRlbSBwZXJwZXNhbmFuIG5pbGFpIHBlbmdlcmltYW4gKipha2FuIGJlcmt1cmFuZyoqIGRhbiBha2FuIGRpa2FsaWthbiBkZW5nYW4gLTAuMDE4Lg0KDQpKaWthIGtpdGEgbWVuZ2FtYmlsIDggcGFyYW10ZXIgYmVyYmVkYSB1bnR1ayBtZW5lbnR1a2FuICAqKk5pbGFpIEZyZWlnaHQqKiBrZW11ZGlhbiBtZW5nZ3VuYWthbiBgUXVhc2ktUG9pc3NvbiByZWdyZXNzaW9uYCAtIFByZWRpa3RvciBiZXJpa3V0IHNpZ25pZmlrYW4gZGVuZ2FuIG5pbGFpIC1wICRcYXBwcm94JCBOT0w6DQoNCi0gSW50ZXJjZXB0IChNZW5jZWdhdCkNCi0gfn5KdW1sYWggSXRlbSBQZXIgUGVzYW5hbn5+DQotIFByaWNlIChIYXJnYSkNCi0gRXN0aW1hdGVkIGxlYWQgdGltZSAoUGVraXJhYW4gd2FrdHUgVHVuZ2d1KQ0KLSB+fldha3R1IHR1bmdndSBha3R1YWx+fiANCi0gfn5CZXJhdCBQcm9kdWsgKGcpfn4NCi0gUHJvZHVjdCdzIExlbmd0aCAoY20pIChQYW5qYW5nIFByb2R1aykNCi0gUHJvZHVjdCdzIEhlaWdodCAoY20pIChUaW5nZ2kgUHJvZHVrKQ0KLSBQcm9kdWN0J3MgV2lkdGggKGNtKSAoTGViYXIgUHJvZHVrKQ0KDQouLi5kYW4gdGVyYWtoaXIgamFyYWsgYmVsdW0gZGlwZXJoaXR1bmdrYW4uDQoNCipOQjogLSB+fmNvcmV0fn4gcGFyYW1ldGVyIHlhbmcgdGlkYWsgc2lnbmlmaWthbiBrb2RlIGRhcGF0IGRpcGVyb2xlaCBkYXJpIGJhZ2lhbiAna29kZScuKg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMjVEczMyA8LSBnbG0oZnJlaWdodF92YWx1ZSB+IG9yZGVyX2l0ZW1faWQsIGRhdGEgPSBUb3QuR3JrbTMsIGZhbWlseT0icG9pc3NvbiBvciBxdWFzaXBvaXNzb24iKQ0KIyNzdW1tYXJ5KFRHMzMpDQpgYGANCg0KPGhyPg0KDQpgUG9seW5vbWlhbDogcmVncmVzc2lvbiBlcXVhdGlvbmANCg0KJCRcdGV4dHtOaWxhaSBQZW5naXJpbWFufV9cdGV4dHsgQ2x1c3RlciAzfSBcYXBwcm94IDg5LjA2ICsgXGVwc2lsb24gJCQNCg0KJCQgXGVwc2lsb24gXFJpZ2h0YXJyb3cgXHRleHR7ZXJyb3J9ICQkDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KIyNURzMgPC0gbG0oZnJlaWdodF92YWx1ZSB+IHBvbHkob3JkZXJfaXRlbV9pZCwgNSksIGRhdGEgPSBUb3QuR3JrbTMpDQojI3N1bW1hcnkoVEczKQ0KYGBgDQoNCjxocj4NCg0KIyMjIFBlcnNhbWFhbiBDbHVzdGVyIDQNCg0KaXR1ICRcZnJhY3tcdGV4dHtQZW55aW1wYW5nYW4gU2lzYX19e1x0ZXh0e0RlcmFqYXQgS2ViZWJhc2FufX0gPiAxIFx0ZXh0eyBvcn0gXHRleHR7IH0gXGZyYWN7XHRleHR7VmFyaWFuY2V9fXtcdGV4dHtNZWFufX0gXG5lcSAxJCB1bnR1ayBgUG9pc3NvbiBSZWdyZXNzaW9uYCBiZXJhZGEgZGkgMTguNjQ5LCBqYWRpIG11bmdraW4gYWRhIG92ZXJkaXNwZXJzaS4gS2FtaSBtZW55ZXN1YWlrYW4gdW50dWsgbWVtcGVyaGl0dW5na2FuIG92ZXJkaXNwZXJzaSBkYW4gbWVuZ2d1bmFrYW4gYFF1YXNpLVBvaXNzb24gUmVncmVzc2lvbmAgcGVyc2FtYWFuLg0KDQpgUXVhc2ktUG9pc3NvbjogcmVncmVzc2lvbiBwZXJzYW1hYW5gDQoNCiQkXHRleHR7TmlsYWkgUGVuZ2VyaW1hbn1fXHRleHR7IENsdXN0ZXIgNH0gXGFwcHJveCAzLjk2NCAtIDAuMDI4eCArIFxlcHNpbG9uICQkDQoNCiQkIHggXFJpZ2h0YXJyb3cgXHRleHR7SnVtbGFoIEl0ZW0gUGVyIE9yZGVyfSwgXHRleHR7IH0gXGVwc2lsb24gXFJpZ2h0YXJyb3cgXHRleHR7ZXJyb3J9JCQNCg0KKipJbnRlcnByZXRhc2k6KiogUHJlZGlrdG9yIHNpZ25pZmlrYW4gc2ViYWdhaSBuaWxhaS1wICRcYXBwcm94JCBOT0wsIHBhcmFtZXRlciBEc2lwZXJzaSB1bnR1ayBgUXVhc2ktUG9pc3NvbmAga2VsdWFyZ2EgZGkgYW1iaWwgcGFkYSAyMy4yMTMuIEl0dSAkXGJldGEgPSAtMC4wMjgkIGF0YXUgJFxiZXRhIDwgMCQgZW1ueWlyYXRrYW4gZGVuZ2FuICoqc2V0aWFwIGtlbmFpa2FuIHVuaXQqKiBJdGVtIHBlcnBlc2FuYW4gbmlsYWkgcGVuZ2VyaW1hbiAqKmFrYW4gYmVya3VyYW5nKiogZGFuIGFrYW4gZGlrYWxpa2FuIGRlbmdhbiAtMC4wMjguDQoNCkppa2Ega2l0YSBtZW5nYW1iaWwgOCBwYXJhbXRlciBiZXJiZWRhIHVudHVrIG1lbmVudHVrYW4gICoqTmlsYWkgRnJlaWdodCoqIGtlbXVkaWFuIG1lbmdndW5ha2FuIGBRdWFzaS1Qb2lzc29uIHJlZ3Jlc3Npb25gIC0gUHJlZGlrdG9yIGJlcmlrdXQgc2lnbmlmaWthbiBkZW5nYW4gbmlsYWkgLXAgJFxhcHByb3gkIE5PTDogDQoNCi0gSW50ZXJjZXB0IChNZW5jZWdhdCkNCi0gfn5KdW1sYWggSXRlbSBQZXJwZXNhbmFufn4NCi0gUHJpY2UgKEhhcmdhKQ0KLSBFc3RpbWF0ZWQgbGVhZCB0aW1lIChQZXJraXJhYW4gV2FrdHUgVHVuZ2d1KQ0KLSB+fldha3R1IHR1bmdndSBha3R1YWx+fg0KLSBQcm9kdWN0J3MgV2VpZ2h0IChnKSAoQmVyYXQgcHJvZHVrKQ0KLSBQcm9kdWN0J3MgTGVuZ3RoIChjbSkgKFBhbmphbmcgUHJvZHVrKQ0KLSBQcm9kdWN0J3MgSGVpZ2h0IChjbSkgKFRpbmdnaSBQcm9kdWspDQotIFByb2R1Y3QncyBXaWR0aCAoY20pIChMZWJhciBwcm9kdWspDQoNCi4uLmRhbiB0ZXJha2hpciBqYXJhayBiZWx1bSBkaXBlcmhpdHVuZ2thbi4NCg0KKk5COiAtIH5+Y29yZXR+fiBhZGFsYWggcGFyYW1hdGVyIHlhbmcgdGlkYWsgc2lnbmlmaWthbi4ga29kZSBkYXBhdCBkaXBlcm9sZWggZGFyaSBiYWdpYW4gJ2tvZGUnLioNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQojI1RHMzQgPC0gZ2xtKGZyZWlnaHRfdmFsdWUgfiBvcmRlcl9pdGVtX2lkLCBkYXRhID0gVG90Lkdya200LCBmYW1pbHk9InBvaXNzb24gb3IgcXVhc2lwb2lzc29uIikNCiMjc3VtbWFyeShURzM0KQ0KYGBgDQoNCjxocj4NCg0KYFBvbHlub21pYWw6IHJlZ3Jlc3Npb24gUGVyc2FtYWFuYA0KDQokJFx0ZXh0e05pbGFpIFBlbmdyaW1hbn1fXHRleHR7IENsdXN0ZXIgNH0gXGFwcHJveCA1MC44OCArIDk4LjQ4eF4yIC0gOTAuMTd4XjMgKyBcZXBzaWxvbiAkJA0KDQokJCB4IFxSaWdodGFycm93IFx0ZXh0e0p1bWxhaCBJdGVtIFBlciBPcmRlcn0sIFx0ZXh0eyB9IFxlcHNpbG9uIFxSaWdodGFycm93IFx0ZXh0e2Vycm9yfSQkDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KIyNURzQgPC0gbG0oZnJlaWdodF92YWx1ZSB+IHBvbHkob3JkZXJfaXRlbV9pZCwgNiksIGRhdGEgPSBUb3QuR3JrbTQpDQojI3N1bW1hcnkoVEc0KQ0KYGBgDQoNCjxocj4NCg0KIyMjIEtsdXN0ZXIgUGVyc2FtYWFuIDUNCg0KVGhlICRcZnJhY3tcdGV4dHtQZW55aW1wYW5hbiBTaXNhfX17XHRleHR7RGVyYWphdCBLZWJlYmFzYW59fSA+IDEgXHRleHR7IGF0YXV9IFx0ZXh0eyB9IFxmcmFje1x0ZXh0e1ZhcmlhbmNlfX17XHRleHR7TWVhbn19IFxuZXEgMSQgZm9yIGBQb2lzc29uIFJlZ3Jlc3Npb25gIGJlcmFkYSBkaSA0LjgxMCwgamFkaSBtdW5na2luIGFkYSBvdmVyZGlzcGVyc2ksIGthbWkgbWVueWVzdWFpa2FuIHVudHVrIG1lbXBlcmhpdHVuZ2thbiBvdmVyaXNwZXJzaSBkYW4gbWVuZ2d1bmFrYW5gUXVhc2ktUG9pc3NvbiBSZWdyZXNzaW9uYCBwZXJzYW1hYW4uDQoNCmBRdWFzaS1Qb2lzc29uOiByZWdyZXNzaW9uIHBlcnNhbWFhbmANCg0KJCRcdGV4dHtOaWxhaSBQZW5nZXJpbWFufV9cdGV4dHsgQ2x1c3RlciA1fSBcYXBwcm94IDMuMTY5IC0gMC4wNjh4ICsgXGVwc2lsb24gJCQNCg0KJCQgeCBcUmlnaHRhcnJvdyBcdGV4dHtKdW1sYWggSXRlbSBQZXIgT3JkZXJ9LCBcdGV4dHsgfSBcZXBzaWxvbiBcUmlnaHRhcnJvdyBcdGV4dHtlcnJvcn0kJA0KDQoqKkludGVycHJldGFzaToqKiBQcmVkaWt0b3Igc2lnbmlmaWthbiBzZWJhZ2FpIG5pbGFpLXAgJFxhcHByb3gkIE5PTCwgcGFyYW1ldGVyIERpc3BlcnNpIHVudHVrIGBRdWFzaS1Qb2lzc29uYCBrZWx1YXJnYSBkaSBhbWJpbCBwYWRhIDQuODEwLiBJdHUgJFxiZXRhID0gLTAuMDY4JCBhdGF1ICRcYmV0YSA8IDAkIGVtbnlpcmF0a2FuIGRlbmdhbiAqKnNldGlhcCBrZW5haWthbiB1bml0KiogSXRlbSBwZXJwZXNhbmFuIG5pbGFpIHBlbmdlcmltYW4gKipha2FuIGJlcmt1cmFuZyoqIGRhbiBha2FuIGRpa2FsaWthbiBkZW5nYW4gLTAuMDY4Lg0KDQpKaWthIGtpdGEgbWVuZ2FtYmlsIDggcGFyYW10ZXIgYmVyYmVkYSB1bnR1ayBtZW5lbnR1a2FuICAqKk5pbGFpIEZyZWlnaHQqKiBrZW11ZGlhbiBtZW5nZ3VuYWthbiBgUXVhc2ktUG9pc3NvbiByZWdyZXNzaW9uYCAtIFByZWRpa3RvciBiZXJpa3V0IHNpZ25pZmlrYW4gZGVuZ2FuIG5pbGFpIC1wICRcYXBwcm94JCBOT0w6IA0KDQotIEludGVyY2VwdCAobWVuY2VnYXQpDQotIE51bWJlciBvZiBJdGVtcyBwZXIgb3JkZXIgKGp1bWxhaCBpdGVtIHBlciBwZXNhbmFuKQ0KLSBQcmljZSAoSGFyZ2EpDQotIEVzdGltYXRlZCBsZWFkIHRpbWUgKFBlcmtpcmFhbiB3YWt0dSB0dW5nZ3UpDQotIEFjdGF1bCBsZWFkIHRpbWUgKHdha3R1IHR1bmdndSBha3R1YWwpDQotIFByb2R1Y3QncyBXZWlnaHQgKGcpIChiZXJhdCBwcm9kdWspDQotIFByb2R1Y3QncyBMZW5ndGggKGNtKSAocGFuamFuZyBwcm9kdWspDQotIFByb2R1Y3QncyBIZWlnaHQgKGNtKSAodGluZ2dpIHByb2R1aykNCi0gUHJvZHVjdCdzIFdpZHRoIChjbSkgKGxlYmFyIHByb2R1aykNCg0KLi4uZGFuIHRlcmFraGlyIGphcmFrIGJlbHVtIGRpcGVyaGl0dW5na2FuLg0KDQoqTkI6IC0gfn5jb3JldH5+IGFkYWxhaCBwYXJhbWV0ZXIgeWFuZyB0aWRhayBzaWduaWZpa2FuLiBLb2RlIGRhcGF0IGRpcGVyb2xlaCBkYXJpIGJhZ2lhbiAna29kZScuKg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMjVEczNSA8LSBnbG0oZnJlaWdodF92YWx1ZSB+IG9yZGVyX2l0ZW1faWQsIGRhdGEgPSBUb3QuR3JrbTUsIGZhbWlseT0icG9pc3NvbiBvciBxdWFzaXBvaXNzb24iKQ0KIyNzdW1tYXJ5KFRHMzUpDQpgYGANCg0KPGhyPg0KDQpgUG9seW5vbWlhbDogcmVncmVzc2lvbiBwZXJzYW1hYW5gDQoNCiQkXHRleHR7TmlsYWkgUGVuZ3JpbWFufV9cdGV4dHsgQ2x1c3RlciA1fSBcYXBwcm94IDIyLjAwIC0gOTUuNTN4ICsgMjcuNzV4XjIgKyBcZXBzaWxvbiAkJA0KDQokJCB4IFxSaWdodGFycm93IFx0ZXh0e0p1bWxhaCBJdGVtIFBlciBPcmRlcn0sIFx0ZXh0eyB9IFxlcHNpbG9uIFxSaWdodGFycm93IFx0ZXh0e2Vycm9yfSQkDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KIyNURzUgPC0gbG0oZnJlaWdodF92YWx1ZSB+IHBvbHkob3JkZXJfaXRlbV9pZCwgNiksIGRhdGEgPSBUb3QuR3JrbTUpDQojI3N1bW1hcnkoVEc1KQ0KYGBgDQoNCjxocj4NCg0KIyMjIFBlcnNhbWFhbiBLbHVzdGVyIDYNCg0KSXR1ICRcZnJhY3tcdGV4dHtQZW55aW1wYW5nYW4gU2lzYX19e1x0ZXh0e0RlcmFqYXQgS2ViZWJhc2FufX0gPiAxIFx0ZXh0eyBvcn0gXHRleHR7IH0gXGZyYWN7XHRleHR7VmFyaWFuY2V9fXtcdGV4dHtNZWFufX0gXG5lcSAxJCBmb3IgYFBvaXNzb24gUmVncmVzc2lvbmAgYmVyYWRhIGRpIDkuOTkzLCBqYWRpIG11bmdraW4gYWRhIG92ZXJkaXNwZXJzaS4ga2FtaSBtZW55ZXN1YWlrYW4gdW50dWsgbWVtcGVyaGl0dW5na2FuIG92ZXJzaXBlcnNpIGRhbiBtZW5nZ3VuYWthbiBgUXVhc2ktUG9pc3NvbiBSZWdyZXNzaW9uYCBwZXJzYW1hYW4uDQoNCmBRdWFzaS1Qb2lzc29uOiByZWdyZXNzaW9uIHBlcnNhbWFhbmANCg0KJCRcdGV4dHtOaWxhaSBQZW5naXJpbWFufV9cdGV4dHsgQ2x1c3RlciA2fSBcYXBwcm94IDMuNDYxIC0gMC4wMTJ4ICsgXGVwc2lsb24gJCQNCg0KJCQgeCBcUmlnaHRhcnJvdyBcdGV4dHtKdW1sYWggSXRlbSBQZXIgT3JkZXJ9LCBcdGV4dHsgfSBcZXBzaWxvbiBcUmlnaHRhcnJvdyBcdGV4dHtlcnJvcn0kJA0KDQoqKkludGVycHJldGFzaToqKiBQcmVkaWt0b3Igc2lnbmlmaWthbiBzZWJhZ2FpIG5pbGFpLXAgJFxhcHByb3gkIE5PTCwgcGFyYW1ldGVyIERzaXBlcnNpIHVudHVrIGBRdWFzaS1Qb2lzc29uYCBrZWx1YXJnYSBkaSBhbWJpbCBwYWRhIDEyLjEwMi4gSXR1ICRcYmV0YSA9IC0wLjAxMiQgYXRhdSAkXGJldGEgPCAwJCBlbW55aXJhdGthbiBkZW5nYW4gKipzZXRpYXAga2VuYWlrYW4gdW5pdCoqIEl0ZW0gcGVycGVzYW5hbiBuaWxhaSBwZW5nZXJpbWFuICoqYWthbiBiZXJrdXJhbmcqKiBkYW4gYWthbiBkaWthbGlrYW4gZGVuZ2FuIC0wLjAxMi4NCg0KSmlrYSBraXRhIG1lbmdhbWJpbCA4IHBhcmFtdGVyIGJlcmJlZGEgdW50dWsgbWVuZW50dWthbiAgKipOaWxhaSBGcmVpZ2h0Kioga2VtdWRpYW4gbWVuZ2d1bmFrYW4gYFF1YXNpLVBvaXNzb24gcmVncmVzc2lvbmAgLSBQcmVkaWt0b3IgYmVyaWt1dCBzaWduaWZpa2FuIGRlbmdhbiBuaWxhaSAtcCAkXGFwcHJveCQgTk9MOg0KDQotIEludGVyY2VwdCAoTWVuY2VnYXQpDQotIH5+SnVtbGFoIGl0ZW0gcGVyIHBlc2FuYW5+fg0KLSBQcmljZSAoSGFyZ2EpDQotIEVzdGltYXRlZCBsZWFkIHRpbWUgKFBlcmtpcmFhbiB3YWt0dSB0dW5nZ3UpDQotIEFjdGF1bCBsZWFkIHRpbWUgKFdha3R1IHR1bmdndSBha3R1YWwpDQotIFByb2R1Y3QncyBXZWlnaHQgKGcpIChCZXJhdCBQcm9kdWspDQotIFByb2R1Y3QncyBMZW5ndGggKGNtKSAoUGFuamFuZyBQcm9kdWspDQotIFByb2R1Y3QncyBIZWlnaHQgKGNtKSAoVGluZ2dpIFByb2R1aykNCi0gUHJvZHVjdCdzIFdpZHRoIChjbSkgKExlYmFyIFByb2R1aykNCg0KLi4uZGFuIHRlcmFraGlyIGphcmFsIGJlbHVtIGRpcGVyaGl0dW5na2FuLg0KDQoqTkI6IC0gfn5jb3JldH5+IGFkYWxhaCBwYXJhbXRlciB5YW5nIHRpZGFrIHNpZ25pZmlrYW4uIGtrb2RlIGRhcGF0IGRpcGVyb2xlaCBkYXJpIGJhZ2lhbiAna29kZScuKg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMjVEczNiA8LSBnbG0oZnJlaWdodF92YWx1ZSB+IG9yZGVyX2l0ZW1faWQsIGRhdGEgPSBUb3QuR3JrbTYsIGZhbWlseT0icG9pc3NvbiBvciBxdWFzaXBvaXNzb24iKQ0KIyNzdW1tYXJ5KFRHMzYpDQpgYGANCg0KPGhyPg0KDQpgUG9seW5vbWlhbDogcmVncmVzc2lvbiBwZXJzYW1hYW5gDQoNCiQkXHRleHR7TmlsYWkgUGVuZ2VyaW1hbn1fXHRleHR7IENsdXN0ZXIgNn0gXGFwcHJveCAzMS40MSArIDQ5LjEyeF4yICsgXGVwc2lsb24gJCQNCg0KJCQgeCBcUmlnaHRhcnJvdyBcdGV4dHtKdW1sYWggaXRlbSBwZXIgT3JkZXJ9LCBcdGV4dHsgfSBcZXBzaWxvbiBcUmlnaHRhcnJvdyBcdGV4dHtlcnJvcn0kJA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCiMjVEc2IDwtIGxtKGZyZWlnaHRfdmFsdWUgfiBwb2x5KG9yZGVyX2l0ZW1faWQsIDYpLCBkYXRhID0gVG90Lkdya202KQ0KIyNzdW1tYXJ5KFRHNikNCmBgYA0KPGhyPg0KDQojIyBQZW5qdWFsIHZzIFBlbGFuZ2dhbiB0ZXJzZWJhciBkaSBzZWx1cnVoIG5lZ2FyYSBiYWdpYW4gDQoNCkdyYWZpayBkaSBiYXdhaCBpbmkgbWVuZW5qdWtrYW4gYmFnYWltYW4ga2VwYWRhdGFuIHBlbGFuZ2dhbiBkYW4gcGVuanVhbCB0ZXJzZWJhciBkaSBiZXJiYWdhaSBuZWdhcmEgYmFnaWFuIEJyYXppbC4gaW5pIGFkYWxhaCBwcmVuc3Rhc2kgc3RhZ25hbiBkYXJpIGdyYWZpayAiY3VzdG9tZXJzLnNlbGxlcnMuc3RhdGVzLmdpZi4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LjI1fQ0KQ1Muc3RhdGVzIDwtIGlubmVyX2pvaW4obGVmdF9qb2luKEN1c3RvbWVycyxzZWxlY3QoT3JkZXJzLCBvcmRlcl9pZCwgY3VzdG9tZXJfaWQsIG9yZGVyX3N0YXR1cywgRXN0LkxlYWQudCwgQWN0LkxlYWQudCwgQXBwcm92YWwubWlucywgQXBwci50by5DYXIsIENhci50by5DdXMpLCBieSA9ICJjdXN0b21lcl9pZCIpLGxlZnRfam9pbihJdGVtcywgU2VsbGVycywgYnkgPSAic2VsbGVyX2lkIiksIGJ5ID0gIm9yZGVyX2lkIikNCg0KQ1Muc3RhdGVzIDwtIG11dGF0ZShDUy5zdGF0ZXMsIGNzLnNzPSBpZl9lbHNlKGN1c3RvbWVyX3ppcF9jb2RlX3ByZWZpeCA9PSBzZWxsZXJfemlwX2NvZGVfcHJlZml4LDEsMCkpDQoNCkNTUy5EIDwtIENTLnN0YXRlcyAlPiUgZmlsdGVyKG9yZGVyX3N0YXR1cyA9PSAiZGVsaXZlcmVkIiklPiUgZ2dwbG90KGFlcyh5ID0gY3VzdG9tZXJfc3RhdGUsIHggPSBzZWxsZXJfc3RhdGUpKSsNCiAgZ2VvbV9qaXR0ZXIoZmlsbCA9IGFscGhhKCJibHVlIiwgMC4wMDEpLCBjb2xvciA9ICJ3aGl0ZSIsIGFscGhhID0gMC4zNiwgc2l6ZSA9IDIuMSwgc2hhcGUgPSAyMSkrDQogIGNvb3JkX3BvbGFyKHN0YXJ0ID0gMCkrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNy41KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSkpKw0KICBsYWJzKHggPSAiUGVuanVhbGFuLiBOZWdhcmEiLCB5ID0gIlBlbGFuZ2dhbi4gTmVnYXJhIiwgc3VidGl0bGUgPSAiR3JvdXA6IFBlc2FuYW4gVGVya2lyaW0iKQ0KDQpDU1MuUyA8LSBDUy5zdGF0ZXMgJT4lIGZpbHRlcihvcmRlcl9zdGF0dXMgPT0gInNoaXBwZWQiKSU+JSBnZ3Bsb3QoYWVzKHkgPSBjdXN0b21lcl9zdGF0ZSwgeCA9IHNlbGxlcl9zdGF0ZSkpKw0KICBnZW9tX2ppdHRlcihmaWxsID0gYWxwaGEoInJlZCIsIDAuMDAxKSwgY29sb3IgPSAid2hpdGUiLCBhbHBoYSA9IDAuMzYsIHNpemUgPSAyLjEsIHNoYXBlID0gMjEpKw0KICBjb29yZF9wb2xhcihzdGFydCA9IDApKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcuNSksIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpKSsNCiAgbGFicyh4ID0gIlBlbmp1bGFuLiBOZWdhcmEiLCB5ID0gIlBlbGFuZ2dhbiBOZWdhcmEiLCBzdWJ0aXRsZSA9ICJHcm91cDogUGVzYW5hbiBUZXJraXJpbSIpDQoNCkNTUy5QIDwtIENTLnN0YXRlcyAlPiUgZmlsdGVyKG9yZGVyX3N0YXR1cyA9PSAicHJvY2Vzc2luZyIpJT4lIGdncGxvdChhZXMoeSA9IGN1c3RvbWVyX3N0YXRlLCB4ID0gc2VsbGVyX3N0YXRlKSkrDQogIGdlb21faml0dGVyKGZpbGwgPSBhbHBoYSgib2xpdmVkcmFiIiwgMC4wMDEpLCBjb2xvciA9ICJ3aGl0ZSIsIGFscGhhID0gMC4zNiwgc2l6ZSA9IDIuMSwgc2hhcGUgPSAyMSkrDQogIGNvb3JkX3BvbGFyKHN0YXJ0ID0gMCkrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNy41KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSkpKw0KICBsYWJzKHggPSAiUGVuanVhbGFuLiBOZWdhcmEiLCB5ID0gIlBlbGFuZ2dhbi4gTmVnYXJhIiwgc3VidGl0bGUgPSAiR3JvdXA6IFBlc2FuYW4gU2VkYW5nIERpcHJvc2VzIikNCg0KQ1NTLkkgPC0gQ1Muc3RhdGVzICU+JSBmaWx0ZXIob3JkZXJfc3RhdHVzID09ICJpbnZvaWNlZCIpJT4lIGdncGxvdChhZXMoeSA9IGN1c3RvbWVyX3N0YXRlLCB4ID0gc2VsbGVyX3N0YXRlKSkrDQogIGdlb21faml0dGVyKGZpbGwgPSBhbHBoYSgiYmx1ZXZpb2xldCIsIDAuMDAxKSwgY29sb3IgPSAid2hpdGUiLCBhbHBoYSA9IDAuMzYsIHNpemUgPSAyLjEsIHNoYXBlID0gMjEpKw0KICBjb29yZF9wb2xhcihzdGFydCA9IDApKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcuNSksIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpKSsNCiAgbGFicyh4ID0gIlBlbmp1YWxhbi4gTmVnYXJhIiwgeSA9ICJQZWxhbmdnYW4gTmVnYXJhIiwgc3VidGl0bGUgPSAiR3JvdXA6IFBlc2FuYW4gWWFuZyBEaXRhZ2loIikNCg0KZ3JpZC5hcnJhbmdlKENTUy5ELCBDU1MuUCwgQ1NTLlMsIENTUy5JLCBuY29sID0gMikNCg0KYGBgDQoNCiMjIEtlc2FuIFNpa2x1cyBQZXNhbmFuIFBlbGFuZ2dhbiANCg0KR3JhZmlrIGFkYWxhaCB3YXdhc2FuIGJlcmdhbWJhciBwZXJ0YW1hIHRlbnRhbmc6IGJhZ2FpbWFuYSBTaWtsdXMgUGVzYW5hbiBQZWxhbmdnYW4gKCpXYWt0dSBQZW5ncmltYW4gQmFyYW5nKikgdGVsYWggYmVydWJhaCBzYWF0IE9saXN0IG11bGFpIGJlcmtlbWJhbmcgR3JhZmlrIGluaSBhZGFsYWggcHJlc2VudGFzaSBzdGFnbmFuIGRhcmkgZ3JhZmlrICJMZWFkLlRpbWVzLmdpZnQiLCB5YW5nIHRlbGFoIGRpdGVtcGF0a2FuIGRpIGJhd2FoIGluaSANCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCkxlYWQuVGltZSA8LSBPcmRlcnMgJT4lIGdyb3VwX2J5X2F0KHZhcnMocHVyY2hhc2VfcXVhcnQsIG9yZGVyX3N0YXR1cykpICU+JSBzdW1tYXJpc2VfYXQoYygiRXN0LkxlYWQudCIsIkFjdC5MZWFkLnQiLCJBcHByb3ZhbC5taW5zIiwgIkFwcHIudG8uQ2FyIiwgIkNhci50by5DdXMiKSwgbWVhbiwgbmEucm0gPSBUUlVFKSAlPiUgYXJyYW5nZV9hdCh2YXJzKHB1cmNoYXNlX3F1YXJ0LCBvcmRlcl9zdGF0dXMpKQ0KTGVhZC5UaW1lIDwtIG11dGF0ZShMZWFkLlRpbWUsIFF1YXJ0LlkgPSBwYXN0ZTAocHVyY2hhc2VfcXVhcnQsIHNlcCA9IlEiKSkNCkxlYWQuVGltZSRRdWFydC5ZIDwtIGFzLmZhY3RvcihMZWFkLlRpbWUkUXVhcnQuWSkNCg0KTFQuRCA8LSBMZWFkLlRpbWUgJT4lIGZpbHRlcihvcmRlcl9zdGF0dXMgPT0iZGVsaXZlcmVkIiklPiUgZ2dwbG90KGFlcyh4ID0gcHVyY2hhc2VfcXVhcnQsIHkgPUVzdC5MZWFkLnQpKSsNCiAgZ2VvbV9wb2ludChzaXplPTQsIGNvbG9yPSJyZWQiLCBmaWxsPWFscGhhKCJvcmFuZ2UiLCAwLjQ1KSwgYWxwaGE9MC42Mywgc2hhcGU9MjEsIHN0cm9rZT0xKSsNCiAgZmFjZXRfd3JhcCh+UXVhcnQuWSwgc3RyaXAucG9zaXRpb24gPSAiYm90dG9tIikrDQogIGNvb3JkX3BvbGFyKHN0YXJ0ID0gMCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSA0KSwgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gMyksIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpKw0KICBsYWJzKHN1YnRpdGxlID0gIlN0YXR1cyBQZXNhbmFuIDogVGVya2lyaW0iLCB4ID0gIiIsIHkgPSAiIikNCg0KTFQuUyA8LSBMZWFkLlRpbWUgJT4lIGZpbHRlcihvcmRlcl9zdGF0dXMgPT0ic2hpcHBlZCIpJT4lIGdncGxvdChhZXMoeCA9IHB1cmNoYXNlX3F1YXJ0LCB5ID1Fc3QuTGVhZC50KSkrDQogIGdlb21fcG9pbnQoc2l6ZT00LCBjb2xvcj0ibmF2eWJsdWUiLCBmaWxsPWFscGhhKCJibHVlIiwgMC40NSksIGFscGhhPTAuNjMsIHNoYXBlPTIxLCBzdHJva2U9MSkrDQogIGZhY2V0X3dyYXAoflF1YXJ0LlksIHN0cmlwLnBvc2l0aW9uID0gImJvdHRvbSIpKw0KICBjb29yZF9wb2xhcihzdGFydCA9IDApKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJyb3lhbGJsdWUiLCBsaW5ldHlwZSA9IDQpLCBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAicm95YWxibHVlIiwgbGluZXR5cGUgPSAzKSwgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkrDQogIGxhYnMoc3VidGl0bGUgPSAiU3RhdHVzIFBlc2FuYW46IFRlcmtpcmltIiwgeCA9ICIiLCB5ID0gIiIpDQoNCmdyaWQuYXJyYW5nZShMVC5ELCBMVC5TLCBuY29sID0gMiwgdG9wID0gIkNoYW5nZSBpbiBhdmVyYWdlIGxlYWQgdGltZXMgcGVyIFF1YXJ0ZXIiLCBsZWZ0PSJFc3RpbWF0ZWQgYXZlcmFnZSBsZWFkIHRpbWUgWy4uaW4gRGF5c10iLCBib3R0b20gPSAiUHVyY2hhc2luZyBRdWFydGVyIikNCg0KYGBgDQoNCg0KIyBLZXNpbXB1bGFuIA0KDQpUZXJpbWFrYXNpaCB0ZWxhaCBtZW1iZXJpa2FuIHdha3R1IGFuZGEgdW50dWsgYnVrdSBjYXRhdGFuIHBhbmphbmcgaW5pLg0KDQoNCiMgTGFtcGlyYW4NCg0KPGhlPg0KDQoqKkxhbXBpcmFuIDAxKioNCg0KS29kZSBncmFmaWsgIlBlbGFuZ2dhbi5QZW5qdWFsYW4uTmVnYXJhLmdpZiIgdGVsYWggZGlzZWRpYWthbiBkaWJhd2FoIGluaSAqKnBha2V0IGdnYW5pbWF0ZSoqIHRldGFwaSBrYXJlYW4ga2V0aWRhayBjb2Nva2FuIHZlcnNpIEFQSS4NCg0KIVtPbGlzdCdzIEN1c3RvbWVycyAtIFNlbGxlcnMgU3RhdGVzJyBkZW5zaXR5XShodHRwczovL2Ftb3VkZ2lsLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxOS8wNC9jcy5naWY/dz01MjkpDQoNCkNTLnN0YXRlcyAlPiUgDQpnZ3Bsb3QoYWVzKHkgPSBjdXN0b21lcl9zdGF0ZSwgeCA9IHNlbGxlcl9zdGF0ZSkpKw0KICBnZW9tX2ppdHRlcihmaWxsID0gYWxwaGEoImJsdWUiLCAwLjAwMSksIGNvbG9yID0gIndoaXRlIiwgYWxwaGEgPSAwLjM2LCBzaXplID0gMi4xLCBzaGFwZSA9IDIxKSsNCiAgY29vcmRfcG9sYXIoc3RhcnQgPSAwKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICBsYWJzKHRpdGxlID0iT3JkZXIgU3RhdHVzJyBEZW5zaXR5IDo6IC4uLntjbG9zZXN0X3N0YXRlfS4uLiIsIA0KICB4ID0gIlNlbGxlcidzIFN0YXRlIiwgeSA9ICJDdXN0b21lcidzIFN0YXRlIiwgDQogIHN1YnRpdGxlID0gIlN0YXRlcyA6OiBTZWxsZXJzIHZzLiBDdXN0b21lcnMiKSsNCnRyYW5zaXRpb25fc3RhdGVzKG9yZGVyX3N0YXR1cywgdHJhbnNpdGlvbl9sZW5ndGggPSA1LCBzdGF0ZV9sZW5ndGggPSA1KQ0KDQo8aHI+DQoNCioqTGFtcGlyYW4gMDIqKg0KDQpHcmFmaWsgc2ViZW5hcm55YSB0ZWFsaCBkaWJ1YXQgZGVuZ2FuICAqKnBha2V0IGdnYW5pbWF0ZSoqIHRldGFwaSBrYXJlbmEga2V0aWRhayBjb2Nva2FuIHZlcnNpIEFQSSwgS29kZSBHcmFmaWsgIkxlYWQgVGltZXMuR2lmIi4NCg0KIVtBdmVyYWdlIExlYWQgVGltZXMgcGVyIFF1YXJ0ZXIgcGVyIFllYXJdKGh0dHBzOi8vYW1vdWRnaWwuZmlsZXMud29yZHByZXNzLmNvbS8yMDE5LzA0L2x0LmdpZj93PTUyOSkNCg0KTGVhZC5UaW1lICU+JSBnZ3Bsb3QoYWVzKHggPSBwdXJjaGFzZV9xdWFydCwgeSA9RXN0LkxlYWQudCkpKw0KICBnZW9tX2xpbmUoY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjgxLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIpKw0KICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSAyMDE4LjQsIHllbmQgPSBFc3QuTGVhZC50KSwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAnZ3JleTUxJykrDQogIGdlb21fdGV4dChhZXMoeCA9IDIwMTguMywgbGFiZWwgPSBRdWFydC5ZLCBoanVzdCA9IDEpKSsNCiAgZ2VvbV9wb2ludChzaXplPTMsIGNvbG9yPSJyZWQiLCBmaWxsPWFscGhhKCJvcmFuZ2UiLCAwLjYzKSwgYWxwaGE9MC41NCwgc2hhcGU9MjEsIHN0cm9rZT0xKSsNCiAgZmFjZXRfd3JhcCh+b3JkZXJfc3RhdHVzKSsNCiAgY29vcmRfcG9sYXIoc3RhcnQgPSAwKSsNCiAgdHJhbnNpdGlvbl9yZXZlYWwocHVyY2hhc2VfcXVhcnQpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImNvcmFsIiwgbGluZXR5cGUgPSAzKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImNvcmFsIiwgbGluZXR5cGUgPSAzKSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkrDQogIGxhYnModGl0bGUgPSAiQ2hhbmdlIGluIHByb3Bvc2VkIGF2ZXJhZ2UgbGVhZCB0aW1lcyBwZXIgUXVhcnRlci9ZZWFyIiwgDQogIHN1YnRpdGxlID0gIlByb3Bvc2VkIGF2ZXJhZ2UgbnVtYmVyIG9mIGRheXMgdG8gZGVsaXZlcnkiLCANCiAgeCA9ICJQdXJjaGFzaW5nIFF1YXJ0ZXIvWWVhciIsIA0KICB5PSAiIEVzdGltYXRlZCBhdmVyYWdlIGxlYWQgdGltZSBbLi4uIGluIERheXNdIiwgDQogIGNhcHRpb24gPSAiZGVyaXZlZCBmcm9tIFRob21hcyBMaW4gUGVkZXJzZW4ncyBEZWMgMjAxOCBncmFwaDogfmdpdGh1Yi5jb20vdGhvbWFzcDg1IikNCg0KPGhyPg0KDQo=