Bab 2 Fungsi grafik
2.1 Grafik fungsi matematika
Ingat bahwa fungsi adalah transformasi dari input ke output. Fungsi
digunakan untuk menyatakan hubungan antar besaran. Dalam mengevaluasi
suatu fungsi , Anda menentukan apa inputnya dan fungsi menerjemahkannya
ke dalam output.
Dalam banyak notasi matematika tradisional yang telah Anda gunakan,
fungsi memiliki nama seperti: f atau g atau kamu , dan input dinotasikan
sebagai x . Huruf lain digunakan untuk mewakili parameter . Misalnya,
persamaan garis biasanya ditulis dengan cara ini kamu = m x + b .
Untuk menerapkan konsep matematika ke pengaturan realistis di dunia,
penting untuk mengenali tiga hal yang disukai notasi: kamu = mx + b
tidak mendukung dengan baik:
Hubungan dunia nyata umumnya melibatkan lebih dari dua kuantitas.
(Misalnya, Hukum Gas Ideal dalam kimia, PV = nRT , melibatkan tiga
variabel: tekanan, volume, dan suhu.) Untuk alasan ini, Anda memerlukan
notasi yang memungkinkan Anda menjelaskan beberapa input ke suatu fungsi
dan yang memungkinkan Anda melacak input mana.
Kuantitas dunia nyata biasanya tidak diberi nama x dan kamu , tetapi
adalah jumlah seperti “konsentrasi AMP siklik” atau “tegangan membran”
atau “pengeluaran pemerintah”. Tentu saja, Anda bisa memanggil semua hal
seperti itu x ataukamu , tetapi lebih mudah untuk memahami hal-hal
ketika nama mengingatkan Anda tentang kuantitas yang diwakili.
Situasi dunia nyata melibatkan banyak hubungan yang berbeda, dan
model matematika dari mereka dapat melibatkan perkiraan dan representasi
yang berbeda dari hubungan tersebut. Karena itu, penting untuk dapat
memberi nama pada hubungan, sehingga Anda dapat melacak berbagai hal
yang sedang Anda kerjakan.
Untuk alasan ini, notasi yang akan Anda gunakan harus lebih umum
daripada notasi yang biasa digunakan dalam aljabar sekolah menengah.
Pada awalnya, ini akan tampak aneh, tetapi keanehan tidak terlalu
berkaitan dengan fakta bahwa notasi digunakan oleh komputer sebanyak
untuk alasan matematika yang diberikan di atas.
Namun ada satu aspek notasi yang berasal langsung dari penggunaan
keyboard untuk berkomunikasi dengan komputer. Dalam menulis operasi
matematika, Anda akan menggunakan ekspresi seperti a * bdan 2 ^ ndan a /
bbukan tradisional sebuah b atau 2n atau sebuah b, dan Anda akan
menggunakan tanda kurung untuk mengelompokkan ekspresi dan untuk
menerapkan fungsi ke inputnya.
Dalam merencanakan suatu fungsi, Anda perlu menentukan beberapa
hal:
Apa fungsinya . Ini biasanya diberikan oleh ekspresi, misalnya m * x
+ batau A * x ^ 2atau sin(2 * t)Nanti, Anda juga akan memberi nama pada
fungsi dan menggunakan nama-nama itu dalam ekspresi, seperti sinhalnya
nama fungsi trigonometri. Apa inputnya . Ingat, tidak ada alasan untuk
berasumsi bahwa x selalu menjadi input, dan Anda akan menggunakan
variabel dengan nama seperti Gdan cAMP. Jadi, Anda harus eksplisit dalam
mengatakan apa yang masuk dan apa yang tidak. Notasi R untuk ini
melibatkan ~simbol (“tilde”). Misalnya, untuk menentukan fungsi linier
dengan x sebagai input, Anda dapat menulism * x + b ~ x Berapa kisaran
input untuk membuat plot berakhir . Anggap ini sebagai batas sumbu
horizontal di mana Anda ingin membuat plot. Nilai parameter apa pun .
Ingat, notasi m * x + b ~ xtidak hanya melibatkan input variabel xtetapi
juga dua kuantitas lainnya, mdan b. Untuk membuat plot fungsi, Anda
perlu memilih nilai spesifik untuk mdan bdan memberi tahu komputer apa
itu. Ada tiga fungsi grafik {mosaicCalc}yang memungkinkan Anda membuat
grafik fungsi, dan melapisi plot tersebut dengan grafik fungsi atau data
lain. Ini adalah:
slice_plot()untuk fungsi satu variabel. contour_plot()untuk fungsi
dua variabel. interactive_plot()yang menghasilkan widget HTML untuk
berinteraksi dengan fungsi dua variabel. Ketiganya digunakan dengan cara
yang hampir sama. Berikut adalah contoh memplot fungsi garis lurus:
slice_plot(3 * x - 2 ~ x, domain(x = range(0, 10)))

Seringkali, wajar untuk menulis hubungan seperti itu dengan parameter
yang diwakili oleh simbol. (Ini dapat membantu Anda mengingat parameter
mana, misalnya, yang merupakan kemiringan dan mana yang merupakan
intersep. Ketika Anda melakukan ini, ingatlah untuk memberikan nilai
numerik tertentu untuk parameter, seperti ini:
m = -3
b = -2
slice_plot(m * x + b ~ x, domain(x = range(0, 10)))

Atau contoh berikut
A = 100
slice_plot( A * x ^ 2 ~ x, domain(x = range(-2, 3)))

A = 5
slice_plot( A * x ^ 2 ~ x, domain(x = range(0, 3)), color="red" )

slice_plot( cos(t) ~ t, domain(t = range(0,4*pi) ))

Anda dapat menggunakan makeFun( )untuk memberi nama pada fungsi.
Contohnya:
g <- makeFun(2*x^2 - 5*x + 2 ~ x)
slice_plot(g(x) ~ x , domain(x = range(-2, 2)))

Tentu saja, Anda juga dapat membuat ekspresi baru dari fungsi yang
telah Anda buat. Coba ekspresi yang agak rumit ini:
slice_plot(sqrt(abs(g(x))) ~ x, domain(x = range(-5,5)))

2.2 Membuat scatterplot
Seringkali, model matematika yang akan Anda buat akan dimotivasi oleh
data. Untuk apresiasi mendalam tentang hubungan antara data dan model,
Anda akan ingin mempelajari pemodelan statistik. Namun, di sini, kita
akan mengambil potongan pertama pada subjek dalam bentuk penyesuaian
kurva , proses pengaturan parameter fungsi matematika untuk membuat
fungsi tersebut menjadi representasi dekat dari beberapa data.
Ini berarti Anda harus mempelajari sesuatu tentang cara mengakses
data dalam file komputer, bagaimana data disimpan, dan bagaimana
memvisualisasikan data. Untungnya, R dan mosaicpaket membuatnya
mudah.
File data yang akan Anda gunakan disimpan sebagai spreadsheet di
Internet. Biasanya, spreadsheet akan memiliki banyak variabel; setiap
variabel disimpan sebagai satu kolom. (Barisnya adalah “cases”,
kadang-kadang disebut “data point.”) Untuk membaca data ke R, Anda perlu
mengetahui nama file dan lokasinya. Seringkali, lokasi akan menjadi
alamat di Internet.
Berikut cara membacanya menjadi R:
Housing = read.csv("http://www.mosaic-web.org/go/datasets/Income-Housing.csv")
Ada dua hal penting yang perlu diperhatikan dari pernyataan di atas.
Pertama, read.csv()fungsi mengembalikan nilai yang disimpan dalam objek
yang disebut housing. Pilihan Housingsebagai nama adalah
sewenang-wenang; Anda bisa menyimpannya sebagai xatau Equadoratau apa
pun. Lebih mudah untuk memilih nama yang membantu Anda mengingat apa
yang disimpan di mana.
Kedua, nama “http://www.mosaic-web.org/go/datasets/Income-Housing.csv"diapit
oleh tanda kutip. Ini adalah tanda kutip ganda satu karakter, yaitu,”dan
bukan tanda kutip tunggal berulang ’ ’atau perumahan ` .
Setelah data dibaca, Anda dapat melihat data hanya dengan mengetikkan
nama objek (tanpa tanda kutip!) yang menyimpan data. Contohnya,
Housing
## Income IncomePercentile CrimeProblem AbandonedBuildings
## 1 3914 5 39.6 12.6
## 2 10817 15 32.4 10.0
## 3 21097 30 26.7 7.1
## 4 34548 50 23.9 4.1
## 5 51941 70 21.4 2.3
## 6 72079 90 19.9
Semua variabel dalam kumpulan data akan ditampilkan (walaupun hanya
empat variabel yang dicetak di sini).
Anda dapat melihat nama semua variabel dalam format yang ringkas
dengan names( )perintah:
names(Housing)
[1] "Income" "IncomePercentile"
"CrimeProblem" "AbandonedBuildings"
[5] "IncompleteBathroom" "NoCentralHeat"
[7] "AirConditioning"
[9] "TwoBathrooms" "MotorVehicle"
[11] "TwoVehicles" "ClothesWasher"
[13] "ClothesDryer" "Dishwasher"
[15] "Telephone" "DoctorVisitsUnder7"
[17] "DoctorVisits7To18"
[19] "NoDoctorVisit7To18"
## [1] "Income" "IncomePercentile" "CrimeProblem"
## [4] "AbandonedBuildings" "IncompleteBathroom" "NoCentralHeat"
## [7] "ExposedWires" "AirConditioning" "TwoBathrooms"
## [10] "MotorVehicle" "TwoVehicles" "ClothesWasher"
## [13] "ClothesDryer" "Dishwasher" "Telephone"
## [19] "NoDoctorVisit7To18"
Saat Anda ingin mengakses salah satu variabel, Anda memberi nama
seluruh kumpulan data diikuti dengan nama variabel, dengan dua nama
dipisahkan oleh $tanda, seperti ini:
Housing$Income
[1] 3914 10817 21097 34548 51941 72079
## [1] 3914 10817 21097 34548 51941 72079
Housing$CrimeProblem
[1] 39.6 32.4 26.7 23.9 21.4 19.9
## [1] 39.6 32.4 26.7 23.9 21.4 19.9
Meskipun output dari names( )menunjukkan nama variabel dalam tanda
kutip, Anda tidak akan menggunakan kutipan di sekitar nama variabel.
Ejaan dan penggunaan huruf kapital itu penting. Jika Anda membuat
kesalahan, tidak peduli seberapa sepele bagi pembaca manusia, R tidak
akan mengetahui apa yang Anda inginkan. Misalnya, berikut ini adalah
kesalahan ejaan nama variabel, yang mengakibatkan tidak ada ( NULL) yang
dikembalikan.
Housing$crim
NULL
## NULL
Biasanya penyajian data yang paling informatif adalah grafis. Salah
satu bentuk grafik yang paling dikenal adalah scatter-plot , format di
mana setiap “kasus” atau “titik data” diplot sebagai titik di lokasi
koordinat yang diberikan oleh dua variabel. Sebagai contoh, berikut
adalah plot pencar dari fraksi rumah tangga yang menganggap lingkungan
mereka memiliki masalah kejahatan, versus pendapatan rata-rata di braket
mereka.
gf_point(CrimeProblem ~ Income, data = Housing )

Pernyataan R secara dekat mengikuti padanan bahasa Inggris: “plot
sebagai poin CrimeProblemversus (atau, sebagai fungsi dari) Income,
menggunakan data dari housingobjek.
Grafik dibangun berlapis-lapis. Jika Anda ingin memplot fungsi
matematika di atas data, Anda harus menggunakan fungsi plot untuk
membuat layer lain. Kemudian, untuk menampilkan dua lapisan dalam plot
yang sama, hubungkan dengan %>%simbol (disebut “pipa”). Perhatikan
bahwa tidak pernah%>% bisa pergi di awal baris baru.
gf_point(
CrimeProblem ~ Income, data=Housing ) %>%
slice_plot(
40 - Income/2000 ~ Income, color = "red")

Fungsi matematika yang digambar tidak cocok dengan data, tetapi
bacaan ini adalah tentang cara menggambar grafik, bukan cara memilih
keluarga fungsi atau menemukan parameter!
Jika, saat memplot data Anda, Anda lebih suka menetapkan batas sumbu
ke sesuatu yang Anda pilih sendiri, Anda bisa melakukan ini.
Contohnya:
gf_point(
CrimeProblem ~ Income, data = Housing) %>%
slice_plot(
gf_lims(
x = range(0,100000),
y=range(0,50))

Grafik ilmiah yang dibuat dengan benar harus memiliki nama sumbu yang
informatif. Anda dapat mengatur nama sumbu secara langsung menggunakan
gf_labs:
gf_point(
CrimeProblem ~ Income, data=Housing) %>%
gf_labs(x= "Income Bracket ($US per household)/year",
y = "Fraction of Households",
main = "Crime Problem") %>%
gf_lims(x = range(0,100000), y = range(0,50))

Perhatikan penggunaan tanda kutip ganda untuk membatasi string
karakter, dan bagaimana x dan kamu digunakan untuk merujuk pada sumbu
horizontal dan vertikal masing-masing.
2.3 Grafik fungsi dua variabel
Anda telah melihat cara memplot grafik fungsi dari satu variabel,
misalnya:
slice_plot(
95 - 73*exp(-.2*t) ~ t,
domain(t = 0:20) )

Pelajaran ini adalah tentang merencanakan fungsi dari dua variabel.
Untuk sebagian besar, format yang digunakan adalah plot kontur .
Anda gunakan contour_plot()untuk memplot dengan dua variabel input.
Anda perlu membuat daftar dua variabel di sebelah kanan +tanda, dan Anda
perlu memberikan rentang untuk masing-masing variabel. Sebagai
contoh:
contour_plot(
sin(2*pi*t/10)*exp(-.2*x) ~ t & x,
domain(t = range(0,20), x = range(0,10)))

Setiap kontur diberi label, dan secara default plot diisi dengan
warna untuk membantu memandu mata. Jika Anda lebih suka hanya melihat
kontur, tanpa isian warna, gunakan tile=FALSEargumen.
contour_plot(
sin(2*pi*t/10)*exp(-.2*x) ~ t & x,
domain(t=0:20, x=0:10))

Kadang-kadang, orang ingin melihat fungsi sebagai permukaan , diplot
dalam 3 dimensi. Anda bisa membuat komputer menampilkan plot perspektif
3 dimensi dengan menggunakan interactive_plot()fungsi. Seperti yang akan
Anda lihat dengan mengarahkan mouse di sekitar plot, ini interaktif.
Sangat sulit untuk membaca nilai kuantitatif dari plot permukaan —
plot kontur jauh lebih berguna untuk itu. Di sisi lain, orang tampaknya
memiliki intuisi yang kuat tentang bentuk permukaan. Mampu menerjemahkan
dalam pikiran Anda dari kontur ke permukaan (dan sebaliknya ) adalah
keterampilan yang berharga.
Untuk membuat fungsi yang dapat Anda evaluasi secara numerik, buat
fungsi tersebut dengan makeFun(). Sebagai contoh:
g <- makeFun(
sin(2*pi*t/10)*exp(-.2*x) ~ t & x)
contour_plot(
g(t, x) ~ t + x,
domain(t=0:20, x=0:10))

g(x = 4, t = 7)
[1] -0.4273372
Pastikan untuk memberi nama argumen secara eksplisit saat memasukkan
nilai. Dengan begitu Anda akan yakin bahwa Anda tidak membalikkannya
secara tidak sengaja. Misalnya, perhatikan bahwa pernyataan ini
memberikan nilai yang berbeda dari yang di atas:
g(4, 7)
[1] 0.1449461
Alasan perbedaannya adalah ketika argumen diberikan tanpa nama,
posisi dalam urutan argumenlah yang penting. Jadi, di atas, 4 digunakan
untuk nilai tdan 7 untuk nilai x. Sangat mudah untuk dibingungkan oleh
situasi ini, jadi praktik yang baik adalah mengidentifikasi argumen
secara eksplisit dengan nama:
g(t = 7, x = 4)
[1] -0.4273372
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpCYWIgMiBGdW5nc2kgZ3JhZmlrDQoNCjIuMSBHcmFmaWsgZnVuZ3NpIG1hdGVtYXRpa2ENCg0KSW5nYXQgYmFod2EgZnVuZ3NpIGFkYWxhaCB0cmFuc2Zvcm1hc2kgZGFyaSBpbnB1dCBrZSBvdXRwdXQuIEZ1bmdzaSBkaWd1bmFrYW4gdW50dWsgbWVueWF0YWthbiBodWJ1bmdhbiBhbnRhciBiZXNhcmFuLiBEYWxhbSBtZW5nZXZhbHVhc2kgc3VhdHUgZnVuZ3NpICwgQW5kYSBtZW5lbnR1a2FuIGFwYSBpbnB1dG55YSBkYW4gZnVuZ3NpIG1lbmVyamVtYWhrYW5ueWEga2UgZGFsYW0gb3V0cHV0Lg0KDQpEYWxhbSBiYW55YWsgbm90YXNpIG1hdGVtYXRpa2EgdHJhZGlzaW9uYWwgeWFuZyB0ZWxhaCBBbmRhIGd1bmFrYW4sIGZ1bmdzaSBtZW1pbGlraSBuYW1hIHNlcGVydGk6IA0KZg0KIGF0YXUgDQpnDQogYXRhdSANCmthbXUNCiAsIGRhbiBpbnB1dCBkaW5vdGFzaWthbiBzZWJhZ2FpIA0KeA0KIC4gSHVydWYgbGFpbiBkaWd1bmFrYW4gdW50dWsgbWV3YWtpbGkgcGFyYW1ldGVyIC4gTWlzYWxueWEsIHBlcnNhbWFhbiBnYXJpcyBiaWFzYW55YSBkaXR1bGlzIGRlbmdhbiBjYXJhIGluaQ0Ka2FtdQ0KPQ0KbQ0KeA0KKw0KYg0KLg0KIA0KVW50dWsgbWVuZXJhcGthbiBrb25zZXAgbWF0ZW1hdGlrYSBrZSBwZW5nYXR1cmFuIHJlYWxpc3RpcyBkaSBkdW5pYSwgcGVudGluZyB1bnR1ayBtZW5nZW5hbGkgdGlnYSBoYWwgeWFuZyBkaXN1a2FpIG5vdGFzaTogDQprYW11ID0gbXggKyBiDQogdGlkYWsgbWVuZHVrdW5nIGRlbmdhbiBiYWlrOg0KDQpIdWJ1bmdhbiBkdW5pYSBueWF0YSB1bXVtbnlhIG1lbGliYXRrYW4gbGViaWggZGFyaSBkdWEga3VhbnRpdGFzLiAoTWlzYWxueWEsIEh1a3VtIEdhcyBJZGVhbCBkYWxhbSBraW1pYSwgDQpQViA9IG5SVA0KICwgbWVsaWJhdGthbiB0aWdhIHZhcmlhYmVsOiB0ZWthbmFuLCB2b2x1bWUsIGRhbiBzdWh1LikgVW50dWsgYWxhc2FuIGluaSwgQW5kYSBtZW1lcmx1a2FuIG5vdGFzaSB5YW5nIG1lbXVuZ2tpbmthbiBBbmRhIG1lbmplbGFza2FuIGJlYmVyYXBhIGlucHV0IGtlIHN1YXR1IGZ1bmdzaSBkYW4geWFuZyBtZW11bmdraW5rYW4gQW5kYSBtZWxhY2FrIGlucHV0IG1hbmEuDQoNCkt1YW50aXRhcyBkdW5pYSBueWF0YSBiaWFzYW55YSB0aWRhayBkaWJlcmkgbmFtYSANCnggZGFuIGthbXUNCiAsIHRldGFwaSBhZGFsYWgganVtbGFoIHNlcGVydGkgImtvbnNlbnRyYXNpIEFNUCBzaWtsaWsiIGF0YXUgInRlZ2FuZ2FuIG1lbWJyYW4iIGF0YXUgInBlbmdlbHVhcmFuIHBlbWVyaW50YWgiLiBUZW50dSBzYWphLCBBbmRhIGJpc2EgbWVtYW5nZ2lsIHNlbXVhIGhhbCBzZXBlcnRpIGl0dSANCnggYXRhdWthbXUNCiAsIHRldGFwaSBsZWJpaCBtdWRhaCB1bnR1ayBtZW1haGFtaSBoYWwtaGFsIGtldGlrYSBuYW1hIG1lbmdpbmdhdGthbiBBbmRhIHRlbnRhbmcga3VhbnRpdGFzIHlhbmcgZGl3YWtpbGkuDQoNClNpdHVhc2kgZHVuaWEgbnlhdGEgbWVsaWJhdGthbiBiYW55YWsgaHVidW5nYW4geWFuZyBiZXJiZWRhLCBkYW4gbW9kZWwgbWF0ZW1hdGlrYSBkYXJpIG1lcmVrYSBkYXBhdCBtZWxpYmF0a2FuIHBlcmtpcmFhbiBkYW4gcmVwcmVzZW50YXNpIHlhbmcgYmVyYmVkYSBkYXJpIGh1YnVuZ2FuIHRlcnNlYnV0LiBLYXJlbmEgaXR1LCBwZW50aW5nIHVudHVrIGRhcGF0IG1lbWJlcmkgbmFtYSBwYWRhIGh1YnVuZ2FuLCBzZWhpbmdnYSBBbmRhIGRhcGF0IG1lbGFjYWsgYmVyYmFnYWkgaGFsIHlhbmcgc2VkYW5nIEFuZGEga2VyamFrYW4uDQoNClVudHVrIGFsYXNhbiBpbmksIG5vdGFzaSB5YW5nIGFrYW4gQW5kYSBndW5ha2FuIGhhcnVzIGxlYmloIHVtdW0gZGFyaXBhZGEgbm90YXNpIHlhbmcgYmlhc2EgZGlndW5ha2FuIGRhbGFtIGFsamFiYXIgc2Vrb2xhaCBtZW5lbmdhaC4gUGFkYSBhd2FsbnlhLCBpbmkgYWthbiB0YW1wYWsgYW5laCwgdGV0YXBpIGtlYW5laGFuIHRpZGFrIHRlcmxhbHUgYmVya2FpdGFuIGRlbmdhbiBmYWt0YSBiYWh3YSBub3Rhc2kgZGlndW5ha2FuIG9sZWgga29tcHV0ZXIgc2ViYW55YWsgdW50dWsgYWxhc2FuIG1hdGVtYXRpa2EgeWFuZyBkaWJlcmlrYW4gZGkgYXRhcy4NCg0KTmFtdW4gYWRhIHNhdHUgYXNwZWsgbm90YXNpIHlhbmcgYmVyYXNhbCBsYW5nc3VuZyBkYXJpIHBlbmdndW5hYW4ga2V5Ym9hcmQgdW50dWsgYmVya29tdW5pa2FzaSBkZW5nYW4ga29tcHV0ZXIuIERhbGFtIG1lbnVsaXMgb3BlcmFzaSBtYXRlbWF0aWthLCBBbmRhIGFrYW4gbWVuZ2d1bmFrYW4gZWtzcHJlc2kgc2VwZXJ0aSBhICogYmRhbiAyIF4gbmRhbiBhIC8gYmJ1a2FuIHRyYWRpc2lvbmFsIA0Kc2VidWFoIGIgYXRhdSAybiBhdGF1IHNlYnVhaCBiLCBkYW4gQW5kYSBha2FuIG1lbmdndW5ha2FuIHRhbmRhIGt1cnVuZyB1bnR1ayBtZW5nZWxvbXBva2thbiBla3NwcmVzaSBkYW4gdW50dWsgbWVuZXJhcGthbiBmdW5nc2kga2UgaW5wdXRueWEuDQoNCkRhbGFtIG1lcmVuY2FuYWthbiBzdWF0dSBmdW5nc2ksIEFuZGEgcGVybHUgbWVuZW50dWthbiBiZWJlcmFwYSBoYWw6DQoNCkFwYSBmdW5nc2lueWEgLiBJbmkgYmlhc2FueWEgZGliZXJpa2FuIG9sZWggZWtzcHJlc2ksIG1pc2FsbnlhIG0gKiB4ICsgYmF0YXUgQSAqIHggXiAyYXRhdSBzaW4oMiAqIHQpTmFudGksIEFuZGEganVnYSBha2FuIG1lbWJlcmkgbmFtYSBwYWRhIGZ1bmdzaSBkYW4gbWVuZ2d1bmFrYW4gbmFtYS1uYW1hIGl0dSBkYWxhbSBla3NwcmVzaSwgc2VwZXJ0aSBzaW5oYWxueWEgbmFtYSBmdW5nc2kgdHJpZ29ub21ldHJpLg0KQXBhIGlucHV0bnlhIC4gSW5nYXQsIHRpZGFrIGFkYSBhbGFzYW4gdW50dWsgYmVyYXN1bXNpIGJhaHdhIHggc2VsYWx1IG1lbmphZGkgaW5wdXQsIGRhbiBBbmRhIGFrYW4gbWVuZ2d1bmFrYW4gdmFyaWFiZWwgZGVuZ2FuIG5hbWEgc2VwZXJ0aSBHZGFuIGNBTVAuIEphZGksIEFuZGEgaGFydXMgZWtzcGxpc2l0IGRhbGFtIG1lbmdhdGFrYW4gYXBhIHlhbmcgbWFzdWsgZGFuIGFwYSB5YW5nIHRpZGFrLiBOb3Rhc2kgUiB1bnR1ayBpbmkgbWVsaWJhdGthbiB+c2ltYm9sICgidGlsZGUiKS4gTWlzYWxueWEsIHVudHVrIG1lbmVudHVrYW4gZnVuZ3NpIGxpbmllciBkZW5nYW4gIHggc2ViYWdhaSBpbnB1dCwgQW5kYSBkYXBhdCBtZW51bGlzbSAqIHggKyBiIH4geA0KQmVyYXBhIGtpc2FyYW4gaW5wdXQgdW50dWsgbWVtYnVhdCBwbG90IGJlcmFraGlyIC4gQW5nZ2FwIGluaSBzZWJhZ2FpIGJhdGFzIHN1bWJ1IGhvcml6b250YWwgZGkgbWFuYSBBbmRhIGluZ2luIG1lbWJ1YXQgcGxvdC4NCk5pbGFpIHBhcmFtZXRlciBhcGEgcHVuIC4gSW5nYXQsIG5vdGFzaSBtICogeCArIGIgfiB4dGlkYWsgaGFueWEgbWVsaWJhdGthbiBpbnB1dCB2YXJpYWJlbCB4dGV0YXBpIGp1Z2EgZHVhIGt1YW50aXRhcyBsYWlubnlhLCBtZGFuIGIuIFVudHVrIG1lbWJ1YXQgcGxvdCBmdW5nc2ksIEFuZGEgcGVybHUgbWVtaWxpaCBuaWxhaSBzcGVzaWZpayB1bnR1ayBtZGFuIGJkYW4gbWVtYmVyaSB0YWh1IGtvbXB1dGVyIGFwYSBpdHUuDQpBZGEgdGlnYSBmdW5nc2kgZ3JhZmlrIHttb3NhaWNDYWxjfXlhbmcgbWVtdW5na2lua2FuIEFuZGEgbWVtYnVhdCBncmFmaWsgZnVuZ3NpLCBkYW4gbWVsYXBpc2kgcGxvdCB0ZXJzZWJ1dCBkZW5nYW4gZ3JhZmlrIGZ1bmdzaSBhdGF1IGRhdGEgbGFpbi4gSW5pIGFkYWxhaDoNCg0Kc2xpY2VfcGxvdCgpdW50dWsgZnVuZ3NpIHNhdHUgdmFyaWFiZWwuDQpjb250b3VyX3Bsb3QoKXVudHVrIGZ1bmdzaSBkdWEgdmFyaWFiZWwuDQppbnRlcmFjdGl2ZV9wbG90KCl5YW5nIG1lbmdoYXNpbGthbiB3aWRnZXQgSFRNTCB1bnR1ayBiZXJpbnRlcmFrc2kgZGVuZ2FuIGZ1bmdzaSBkdWEgdmFyaWFiZWwuDQpLZXRpZ2FueWEgZGlndW5ha2FuIGRlbmdhbiBjYXJhIHlhbmcgaGFtcGlyIHNhbWEuIEJlcmlrdXQgYWRhbGFoIGNvbnRvaCBtZW1wbG90IGZ1bmdzaSBnYXJpcyBsdXJ1czoNCg0KYGBge3J9DQpzbGljZV9wbG90KDMgKiB4IC0gMiB+IHgsIGRvbWFpbih4ID0gcmFuZ2UoMCwgMTApKSkNCmBgYA0KU2VyaW5na2FsaSwgd2FqYXIgdW50dWsgbWVudWxpcyBodWJ1bmdhbiBzZXBlcnRpIGl0dSBkZW5nYW4gcGFyYW1ldGVyIHlhbmcgZGl3YWtpbGkgb2xlaCBzaW1ib2wuIChJbmkgZGFwYXQgbWVtYmFudHUgQW5kYSBtZW5naW5nYXQgcGFyYW1ldGVyIG1hbmEsIG1pc2FsbnlhLCB5YW5nIG1lcnVwYWthbiBrZW1pcmluZ2FuIGRhbiBtYW5hIHlhbmcgbWVydXBha2FuIGludGVyc2VwLiBLZXRpa2EgQW5kYSBtZWxha3VrYW4gaW5pLCBpbmdhdGxhaCB1bnR1ayBtZW1iZXJpa2FuIG5pbGFpIG51bWVyaWsgdGVydGVudHUgdW50dWsgcGFyYW1ldGVyLCBzZXBlcnRpIGluaToNCg0KYGBge3J9DQptID0gLTMNCmIgPSAtMg0Kc2xpY2VfcGxvdChtICogeCArIGIgfiB4LCBkb21haW4oeCA9IHJhbmdlKDAsIDEwKSkpDQpgYGANCkF0YXUgY29udG9oIGJlcmlrdXQNCg0KYGBge3J9DQpBID0gMTAwDQpzbGljZV9wbG90KCBBICogeCBeIDIgfiB4LCBkb21haW4oeCA9IHJhbmdlKC0yLCAzKSkpIA0KDQpBID0gNQ0Kc2xpY2VfcGxvdCggQSAqIHggXiAyIH4geCwgIGRvbWFpbih4ID0gcmFuZ2UoMCwgMykpLCAgY29sb3I9InJlZCIgKQ0Kc2xpY2VfcGxvdCggY29zKHQpIH4gdCwgZG9tYWluKHQgPSByYW5nZSgwLDQqcGkpICkpDQpgYGANCkFuZGEgZGFwYXQgbWVuZ2d1bmFrYW4gbWFrZUZ1biggKXVudHVrIG1lbWJlcmkgbmFtYSBwYWRhIGZ1bmdzaS4gQ29udG9obnlhOg0KYGBge3J9DQpnICA8LSBtYWtlRnVuKDIqeF4yIC0gNSp4ICsgMiB+IHgpDQpzbGljZV9wbG90KGcoeCkgfiB4ICwgZG9tYWluKHggPSByYW5nZSgtMiwgMikpKQ0KYGBgDQpUZW50dSBzYWphLCBBbmRhIGp1Z2EgZGFwYXQgbWVtYnVhdCBla3NwcmVzaSBiYXJ1IGRhcmkgZnVuZ3NpIHlhbmcgdGVsYWggQW5kYSBidWF0LiBDb2JhIGVrc3ByZXNpIHlhbmcgYWdhayBydW1pdCBpbmk6DQoNCmBgYHtyfQ0Kc2xpY2VfcGxvdChzcXJ0KGFicyhnKHgpKSkgfiB4LCBkb21haW4oeCA9IHJhbmdlKC01LDUpKSkNCmBgYA0KDQoyLjIgTWVtYnVhdCBzY2F0dGVycGxvdA0KDQpTZXJpbmdrYWxpLCBtb2RlbCBtYXRlbWF0aWthIHlhbmcgYWthbiBBbmRhIGJ1YXQgYWthbiBkaW1vdGl2YXNpIG9sZWggZGF0YS4gVW50dWsgYXByZXNpYXNpIG1lbmRhbGFtIHRlbnRhbmcgaHVidW5nYW4gYW50YXJhIGRhdGEgZGFuIG1vZGVsLCBBbmRhIGFrYW4gaW5naW4gbWVtcGVsYWphcmkgcGVtb2RlbGFuIHN0YXRpc3Rpay4gTmFtdW4sIGRpIHNpbmksIGtpdGEgYWthbiBtZW5nYW1iaWwgcG90b25nYW4gcGVydGFtYSBwYWRhIHN1YmplayBkYWxhbSBiZW50dWsgcGVueWVzdWFpYW4ga3VydmEgLCBwcm9zZXMgcGVuZ2F0dXJhbiBwYXJhbWV0ZXIgZnVuZ3NpIG1hdGVtYXRpa2EgdW50dWsgbWVtYnVhdCBmdW5nc2kgdGVyc2VidXQgbWVuamFkaSByZXByZXNlbnRhc2kgZGVrYXQgZGFyaSBiZWJlcmFwYSBkYXRhLg0KDQpJbmkgYmVyYXJ0aSBBbmRhIGhhcnVzIG1lbXBlbGFqYXJpIHNlc3VhdHUgdGVudGFuZyBjYXJhIG1lbmdha3NlcyBkYXRhIGRhbGFtIGZpbGUga29tcHV0ZXIsIGJhZ2FpbWFuYSBkYXRhIGRpc2ltcGFuLCBkYW4gYmFnYWltYW5hIG1lbXZpc3VhbGlzYXNpa2FuIGRhdGEuIFVudHVuZ255YSwgUiBkYW4gbW9zYWljcGFrZXQgbWVtYnVhdG55YSBtdWRhaC4NCg0KRmlsZSBkYXRhIHlhbmcgYWthbiBBbmRhIGd1bmFrYW4gZGlzaW1wYW4gc2ViYWdhaSBzcHJlYWRzaGVldCBkaSBJbnRlcm5ldC4gQmlhc2FueWEsIHNwcmVhZHNoZWV0IGFrYW4gbWVtaWxpa2kgYmFueWFrIHZhcmlhYmVsOyBzZXRpYXAgdmFyaWFiZWwgZGlzaW1wYW4gc2ViYWdhaSBzYXR1IGtvbG9tLiAoQmFyaXNueWEgYWRhbGFoIOKAnGNhc2Vz4oCdLCBrYWRhbmcta2FkYW5nIGRpc2VidXQg4oCcZGF0YSBwb2ludC7igJ0pIFVudHVrIG1lbWJhY2EgZGF0YSBrZSBSLCBBbmRhIHBlcmx1IG1lbmdldGFodWkgbmFtYSBmaWxlIGRhbiBsb2thc2lueWEuIFNlcmluZ2thbGksIGxva2FzaSBha2FuIG1lbmphZGkgYWxhbWF0IGRpIEludGVybmV0Lg0KDQpCZXJpa3V0IGNhcmEgbWVtYmFjYW55YSBtZW5qYWRpIFI6DQoNCmBgYHtyfQ0KSG91c2luZyA9IHJlYWQuY3N2KCJodHRwOi8vd3d3Lm1vc2FpYy13ZWIub3JnL2dvL2RhdGFzZXRzL0luY29tZS1Ib3VzaW5nLmNzdiIpDQpgYGANCg0KQWRhIGR1YSBoYWwgcGVudGluZyB5YW5nIHBlcmx1IGRpcGVyaGF0aWthbiBkYXJpIHBlcm55YXRhYW4gZGkgYXRhcy4gUGVydGFtYSwgcmVhZC5jc3YoKWZ1bmdzaSBtZW5nZW1iYWxpa2FuIG5pbGFpIHlhbmcgZGlzaW1wYW4gZGFsYW0gb2JqZWsgeWFuZyBkaXNlYnV0IGhvdXNpbmcuIFBpbGloYW4gSG91c2luZ3NlYmFnYWkgbmFtYSBhZGFsYWggc2V3ZW5hbmctd2VuYW5nOyBBbmRhIGJpc2EgbWVueWltcGFubnlhIHNlYmFnYWkgeGF0YXUgRXF1YWRvcmF0YXUgYXBhIHB1bi4gTGViaWggbXVkYWggdW50dWsgbWVtaWxpaCBuYW1hIHlhbmcgbWVtYmFudHUgQW5kYSBtZW5naW5nYXQgYXBhIHlhbmcgZGlzaW1wYW4gZGkgbWFuYS4NCg0KS2VkdWEsIG5hbWEgImh0dHA6Ly93d3cubW9zYWljLXdlYi5vcmcvZ28vZGF0YXNldHMvSW5jb21lLUhvdXNpbmcuY3N2ImRpYXBpdCBvbGVoIHRhbmRhIGt1dGlwLiBJbmkgYWRhbGFoIHRhbmRhIGt1dGlwIGdhbmRhIHNhdHUga2FyYWt0ZXIsIHlhaXR1LCAiZGFuIGJ1a2FuIHRhbmRhIGt1dGlwIHR1bmdnYWwgYmVydWxhbmcgJyAnYXRhdSBwZXJ1bWFoYW4gYCAuIA0KDQpTZXRlbGFoIGRhdGEgZGliYWNhLCBBbmRhIGRhcGF0IG1lbGloYXQgZGF0YSBoYW55YSBkZW5nYW4gbWVuZ2V0aWtrYW4gbmFtYSBvYmplayAodGFucGEgdGFuZGEga3V0aXAhKSB5YW5nIG1lbnlpbXBhbiBkYXRhLiBDb250b2hueWEsDQoNCmBgYHtyfQ0KSG91c2luZyANCiMjICAgSW5jb21lIEluY29tZVBlcmNlbnRpbGUgQ3JpbWVQcm9ibGVtIEFiYW5kb25lZEJ1aWxkaW5ncw0KIyMgMSAgIDM5MTQgICAgICAgICAgICAgICAgNSAgICAgICAgIDM5LjYgICAgICAgICAgICAgICAxMi42DQojIyAyICAxMDgxNyAgICAgICAgICAgICAgIDE1ICAgICAgICAgMzIuNCAgICAgICAgICAgICAgIDEwLjANCiMjIDMgIDIxMDk3ICAgICAgICAgICAgICAgMzAgICAgICAgICAyNi43ICAgICAgICAgICAgICAgIDcuMQ0KIyMgNCAgMzQ1NDggICAgICAgICAgICAgICA1MCAgICAgICAgIDIzLjkgICAgICAgICAgICAgICAgNC4xDQojIyA1ICA1MTk0MSAgICAgICAgICAgICAgIDcwICAgICAgICAgMjEuNCAgICAgICAgICAgICAgICAyLjMNCiMjIDYgIDcyMDc5ICAgICAgICAgICAgICAgOTAgICAgICAgICAxOS45ICAgICAgICAgICAgIA0KYGBgDQoNClNlbXVhIHZhcmlhYmVsIGRhbGFtIGt1bXB1bGFuIGRhdGEgYWthbiBkaXRhbXBpbGthbiAod2FsYXVwdW4gaGFueWEgZW1wYXQgdmFyaWFiZWwgeWFuZyBkaWNldGFrIGRpIHNpbmkpLg0KDQpBbmRhIGRhcGF0IG1lbGloYXQgbmFtYSBzZW11YSB2YXJpYWJlbCBkYWxhbSBmb3JtYXQgeWFuZyByaW5na2FzIGRlbmdhbiBuYW1lcyggKXBlcmludGFoOg0KDQpgYGB7cn0NCm5hbWVzKEhvdXNpbmcpIA0KIyMgIFsxXSAiSW5jb21lIiAgICAgICAgICAgICAgIkluY29tZVBlcmNlbnRpbGUiICAgICJDcmltZVByb2JsZW0iICAgICAgIA0KIyMgIFs0XSAiQWJhbmRvbmVkQnVpbGRpbmdzIiAgIkluY29tcGxldGVCYXRocm9vbSIgICJOb0NlbnRyYWxIZWF0IiAgICAgIA0KIyMgIFs3XSAiRXhwb3NlZFdpcmVzIiAgICAgICAgIkFpckNvbmRpdGlvbmluZyIgICAgICJUd29CYXRocm9vbXMiICAgICAgIA0KIyMgWzEwXSAiTW90b3JWZWhpY2xlIiAgICAgICAgIlR3b1ZlaGljbGVzIiAgICAgICAgICJDbG90aGVzV2FzaGVyIiAgICAgIA0KIyMgWzEzXSAiQ2xvdGhlc0RyeWVyIiAgICAgICAgIkRpc2h3YXNoZXIiICAgICAgICAgICJUZWxlcGhvbmUiICAgICAgICAgIA0KIyMgWzE2XSAiRG9jdG9yVmlzaXRzVW5kZXI3IiAgIkRvY3RvclZpc2l0czdUbzE4IiAgICJOb0RvY3RvclZpc2l0VW5kZXI3Ig0KIyMgWzE5XSAiTm9Eb2N0b3JWaXNpdDdUbzE4Ig0KYGBgDQoNClNhYXQgQW5kYSBpbmdpbiBtZW5nYWtzZXMgc2FsYWggc2F0dSB2YXJpYWJlbCwgQW5kYSBtZW1iZXJpIG5hbWEgc2VsdXJ1aCBrdW1wdWxhbiBkYXRhIGRpaWt1dGkgZGVuZ2FuIG5hbWEgdmFyaWFiZWwsIGRlbmdhbiBkdWEgbmFtYSBkaXBpc2Foa2FuIG9sZWggJHRhbmRhLCBzZXBlcnRpIGluaToNCg0KYGBge3J9DQpIb3VzaW5nJEluY29tZQ0KIyMgWzFdICAzOTE0IDEwODE3IDIxMDk3IDM0NTQ4IDUxOTQxIDcyMDc5DQpIb3VzaW5nJENyaW1lUHJvYmxlbQ0KIyMgWzFdIDM5LjYgMzIuNCAyNi43IDIzLjkgMjEuNCAxOS45DQpgYGANCk1lc2tpcHVuIG91dHB1dCBkYXJpIG5hbWVzKCApbWVudW5qdWtrYW4gbmFtYSB2YXJpYWJlbCBkYWxhbSB0YW5kYSBrdXRpcCwgQW5kYSB0aWRhayBha2FuIG1lbmdndW5ha2FuIGt1dGlwYW4gZGkgc2VraXRhciBuYW1hIHZhcmlhYmVsLg0KDQpFamFhbiBkYW4gcGVuZ2d1bmFhbiBodXJ1ZiBrYXBpdGFsIGl0dSBwZW50aW5nLiBKaWthIEFuZGEgbWVtYnVhdCBrZXNhbGFoYW4sIHRpZGFrIHBlZHVsaSBzZWJlcmFwYSBzZXBlbGUgYmFnaSBwZW1iYWNhIG1hbnVzaWEsIFIgdGlkYWsgYWthbiBtZW5nZXRhaHVpIGFwYSB5YW5nIEFuZGEgaW5naW5rYW4uIE1pc2FsbnlhLCBiZXJpa3V0IGluaSBhZGFsYWgga2VzYWxhaGFuIGVqYWFuIG5hbWEgdmFyaWFiZWwsIHlhbmcgbWVuZ2FraWJhdGthbiB0aWRhayBhZGEgKCBOVUxMKSB5YW5nIGRpa2VtYmFsaWthbi4NCg0KDQpgYGB7cn0NCkhvdXNpbmckY3JpbQ0KIyMgTlVMTA0KYGBgDQpCaWFzYW55YSBwZW55YWppYW4gZGF0YSB5YW5nIHBhbGluZyBpbmZvcm1hdGlmIGFkYWxhaCBncmFmaXMuIFNhbGFoIHNhdHUgYmVudHVrIGdyYWZpayB5YW5nIHBhbGluZyBkaWtlbmFsIGFkYWxhaCBzY2F0dGVyLXBsb3QgLCBmb3JtYXQgZGkgbWFuYSBzZXRpYXAgImthc3VzIiBhdGF1ICJ0aXRpayBkYXRhIiBkaXBsb3Qgc2ViYWdhaSB0aXRpayBkaSBsb2thc2kga29vcmRpbmF0IHlhbmcgZGliZXJpa2FuIG9sZWggZHVhIHZhcmlhYmVsLiBTZWJhZ2FpIGNvbnRvaCwgYmVyaWt1dCBhZGFsYWggcGxvdCBwZW5jYXIgZGFyaSBmcmFrc2kgcnVtYWggdGFuZ2dhIHlhbmcgbWVuZ2FuZ2dhcCBsaW5na3VuZ2FuIG1lcmVrYSBtZW1pbGlraSBtYXNhbGFoIGtlamFoYXRhbiwgdmVyc3VzIHBlbmRhcGF0YW4gcmF0YS1yYXRhIGRpIGJyYWtldCBtZXJla2EuDQoNCmBgYHtyfQ0KZ2ZfcG9pbnQoQ3JpbWVQcm9ibGVtIH4gSW5jb21lLCBkYXRhID0gSG91c2luZyApDQpgYGANCg0KUGVybnlhdGFhbiBSIHNlY2FyYSBkZWthdCBtZW5naWt1dGkgcGFkYW5hbiBiYWhhc2EgSW5nZ3JpczogInBsb3Qgc2ViYWdhaSBwb2luIENyaW1lUHJvYmxlbXZlcnN1cyAoYXRhdSwgc2ViYWdhaSBmdW5nc2kgZGFyaSkgSW5jb21lLCBtZW5nZ3VuYWthbiBkYXRhIGRhcmkgaG91c2luZ29iamVrLg0KDQpHcmFmaWsgZGliYW5ndW4gYmVybGFwaXMtbGFwaXMuIEppa2EgQW5kYSBpbmdpbiBtZW1wbG90IGZ1bmdzaSBtYXRlbWF0aWthIGRpIGF0YXMgZGF0YSwgQW5kYSBoYXJ1cyBtZW5nZ3VuYWthbiBmdW5nc2kgcGxvdCB1bnR1ayBtZW1idWF0IGxheWVyIGxhaW4uIEtlbXVkaWFuLCB1bnR1ayBtZW5hbXBpbGthbiBkdWEgbGFwaXNhbiBkYWxhbSBwbG90IHlhbmcgc2FtYSwgaHVidW5na2FuIGRlbmdhbiAlPiVzaW1ib2wgKGRpc2VidXQgInBpcGEiKS4gUGVyaGF0aWthbiBiYWh3YSB0aWRhayBwZXJuYWglPiUgYmlzYSBwZXJnaSBkaSBhd2FsIGJhcmlzIGJhcnUuDQoNCmBgYHtyfQ0KZ2ZfcG9pbnQoIA0KICBDcmltZVByb2JsZW0gfiBJbmNvbWUsIGRhdGE9SG91c2luZyApICU+JQ0KICBzbGljZV9wbG90KA0KICAgIDQwIC0gSW5jb21lLzIwMDAgfiBJbmNvbWUsIGNvbG9yID0gInJlZCIpDQpgYGANCg0KRnVuZ3NpIG1hdGVtYXRpa2EgeWFuZyBkaWdhbWJhciB0aWRhayBjb2NvayBkZW5nYW4gZGF0YSwgdGV0YXBpIGJhY2FhbiBpbmkgYWRhbGFoIHRlbnRhbmcgY2FyYSBtZW5nZ2FtYmFyIGdyYWZpaywgYnVrYW4gY2FyYSBtZW1pbGloIGtlbHVhcmdhIGZ1bmdzaSBhdGF1IG1lbmVtdWthbiBwYXJhbWV0ZXIhDQoNCkppa2EsIHNhYXQgbWVtcGxvdCBkYXRhIEFuZGEsIEFuZGEgbGViaWggc3VrYSBtZW5ldGFwa2FuIGJhdGFzIHN1bWJ1IGtlIHNlc3VhdHUgeWFuZyBBbmRhIHBpbGloIHNlbmRpcmksIEFuZGEgYmlzYSBtZWxha3VrYW4gaW5pLiBDb250b2hueWE6DQoNCmBgYHtyfQ0KZ2ZfcG9pbnQoDQogIENyaW1lUHJvYmxlbSB+IEluY29tZSwgZGF0YSA9IEhvdXNpbmcpICU+JSANCiAgc2xpY2VfcGxvdCgNCiAgICA0MCAtIEluY29tZSAvIDIwMDAgfiBJbmNvbWUsIGNvbG9yID0gImJsdWUiKSAlPiUNCiAgZ2ZfbGltcygNCiAgICB4ID0gcmFuZ2UoMCwxMDAwMDApLCANCiAgICB5PXJhbmdlKDAsNTApKQ0KYGBgDQoNCkdyYWZpayBpbG1pYWggeWFuZyBkaWJ1YXQgZGVuZ2FuIGJlbmFyIGhhcnVzIG1lbWlsaWtpIG5hbWEgc3VtYnUgeWFuZyBpbmZvcm1hdGlmLiBBbmRhIGRhcGF0IG1lbmdhdHVyIG5hbWEgc3VtYnUgc2VjYXJhIGxhbmdzdW5nIG1lbmdndW5ha2FuIGdmX2xhYnM6DQoNCmBgYHtyfQ0KZ2ZfcG9pbnQoDQogIENyaW1lUHJvYmxlbSB+IEluY29tZSwgZGF0YT1Ib3VzaW5nKSAlPiUNCiAgZ2ZfbGFicyh4PSAiSW5jb21lIEJyYWNrZXQgKCRVUyBwZXIgaG91c2Vob2xkKS95ZWFyIiwNCiAgICAgICAgICB5ID0gIkZyYWN0aW9uIG9mIEhvdXNlaG9sZHMiLA0KICAgICAgICAgIG1haW4gPSAiQ3JpbWUgUHJvYmxlbSIpICU+JQ0KICBnZl9saW1zKHggPSByYW5nZSgwLDEwMDAwMCksIHkgPSByYW5nZSgwLDUwKSkNCmBgYA0KUGVyaGF0aWthbiBwZW5nZ3VuYWFuIHRhbmRhIGt1dGlwIGdhbmRhIHVudHVrIG1lbWJhdGFzaSBzdHJpbmcga2FyYWt0ZXIsIGRhbiBiYWdhaW1hbmEgDQp4DQogZGFuIA0Ka2FtdQ0KIGRpZ3VuYWthbiB1bnR1ayBtZXJ1anVrIHBhZGEgc3VtYnUgaG9yaXpvbnRhbCBkYW4gdmVydGlrYWwgbWFzaW5nLW1hc2luZy4NCiANCiAyLjMgR3JhZmlrIGZ1bmdzaSBkdWEgdmFyaWFiZWwNCiANCiBBbmRhIHRlbGFoIG1lbGloYXQgY2FyYSBtZW1wbG90IGdyYWZpayBmdW5nc2kgZGFyaSBzYXR1IHZhcmlhYmVsLCBtaXNhbG55YToNCiANCmBgYHtyfQ0Kc2xpY2VfcGxvdCgNCiAgOTUgLSA3MypleHAoLS4yKnQpIH4gdCwgDQogIGRvbWFpbih0ID0gMDoyMCkgKQ0KYGBgDQogUGVsYWphcmFuIGluaSBhZGFsYWggdGVudGFuZyBtZXJlbmNhbmFrYW4gZnVuZ3NpIGRhcmkgZHVhIHZhcmlhYmVsLiBVbnR1ayBzZWJhZ2lhbiBiZXNhciwgZm9ybWF0IHlhbmcgZGlndW5ha2FuIGFkYWxhaCBwbG90IGtvbnR1ciAuDQoNCkFuZGEgZ3VuYWthbiBjb250b3VyX3Bsb3QoKXVudHVrIG1lbXBsb3QgZGVuZ2FuIGR1YSB2YXJpYWJlbCBpbnB1dC4gQW5kYSBwZXJsdSBtZW1idWF0IGRhZnRhciBkdWEgdmFyaWFiZWwgZGkgc2ViZWxhaCBrYW5hbiArdGFuZGEsIGRhbiBBbmRhIHBlcmx1IG1lbWJlcmlrYW4gcmVudGFuZyB1bnR1ayBtYXNpbmctbWFzaW5nIHZhcmlhYmVsLiBTZWJhZ2FpIGNvbnRvaDoNCg0KYGBge3J9DQpjb250b3VyX3Bsb3QoDQogIHNpbigyKnBpKnQvMTApKmV4cCgtLjIqeCkgfiB0ICYgeCwgDQogIGRvbWFpbih0ID0gcmFuZ2UoMCwyMCksIHggPSByYW5nZSgwLDEwKSkpDQpgYGANClNldGlhcCBrb250dXIgZGliZXJpIGxhYmVsLCBkYW4gc2VjYXJhIGRlZmF1bHQgcGxvdCBkaWlzaSBkZW5nYW4gd2FybmEgdW50dWsgbWVtYmFudHUgbWVtYW5kdSBtYXRhLiBKaWthIEFuZGEgbGViaWggc3VrYSBoYW55YSBtZWxpaGF0IGtvbnR1ciwgdGFucGEgaXNpYW4gd2FybmEsIGd1bmFrYW4gdGlsZT1GQUxTRWFyZ3VtZW4uDQoNCmBgYHtyfQ0KY29udG91cl9wbG90KCANCiAgc2luKDIqcGkqdC8xMCkqZXhwKC0uMip4KSB+IHQgJiB4LCANCiAgZG9tYWluKHQ9MDoyMCwgeD0wOjEwKSkNCmBgYA0KS2FkYW5nLWthZGFuZywgb3JhbmcgaW5naW4gbWVsaWhhdCBmdW5nc2kgc2ViYWdhaSBwZXJtdWthYW4gLCBkaXBsb3QgZGFsYW0gMyBkaW1lbnNpLiBBbmRhIGJpc2EgbWVtYnVhdCBrb21wdXRlciBtZW5hbXBpbGthbiBwbG90IHBlcnNwZWt0aWYgMyBkaW1lbnNpIGRlbmdhbiBtZW5nZ3VuYWthbiBpbnRlcmFjdGl2ZV9wbG90KClmdW5nc2kuIFNlcGVydGkgeWFuZyBha2FuIEFuZGEgbGloYXQgZGVuZ2FuIG1lbmdhcmFoa2FuIG1vdXNlIGRpIHNla2l0YXIgcGxvdCwgaW5pIGludGVyYWt0aWYuDQoNClNhbmdhdCBzdWxpdCB1bnR1ayBtZW1iYWNhIG5pbGFpIGt1YW50aXRhdGlmIGRhcmkgcGxvdCBwZXJtdWthYW4g4oCUIHBsb3Qga29udHVyIGphdWggbGViaWggYmVyZ3VuYSB1bnR1ayBpdHUuIERpIHNpc2kgbGFpbiwgb3JhbmcgdGFtcGFrbnlhIG1lbWlsaWtpIGludHVpc2kgeWFuZyBrdWF0IHRlbnRhbmcgYmVudHVrIHBlcm11a2Fhbi4gTWFtcHUgbWVuZXJqZW1haGthbiBkYWxhbSBwaWtpcmFuIEFuZGEgZGFyaSBrb250dXIga2UgcGVybXVrYWFuIChkYW4gc2ViYWxpa255YSApIGFkYWxhaCBrZXRlcmFtcGlsYW4geWFuZyBiZXJoYXJnYS4NCg0KVW50dWsgbWVtYnVhdCBmdW5nc2kgeWFuZyBkYXBhdCBBbmRhIGV2YWx1YXNpIHNlY2FyYSBudW1lcmlrLCBidWF0IGZ1bmdzaSB0ZXJzZWJ1dCBkZW5nYW4gbWFrZUZ1bigpLiBTZWJhZ2FpIGNvbnRvaDoNCg0KYGBge3J9DQpnIDwtIG1ha2VGdW4oDQogIHNpbigyKnBpKnQvMTApKmV4cCgtLjIqeCkgfiB0ICYgeCkNCmNvbnRvdXJfcGxvdCgNCiAgZyh0LCB4KSB+IHQgKyB4LCAgDQogIGRvbWFpbih0PTA6MjAsIHg9MDoxMCkpDQpgYGANCiBnKHggPSA0LCB0ID0gNykNCg0KIyMgWzFdIC0wLjQyNzMzNzINCiANCiBQYXN0aWthbiB1bnR1ayBtZW1iZXJpIG5hbWEgYXJndW1lbiBzZWNhcmEgZWtzcGxpc2l0IHNhYXQgbWVtYXN1a2thbiBuaWxhaS4gRGVuZ2FuIGJlZ2l0dSBBbmRhIGFrYW4geWFraW4gYmFod2EgQW5kYSB0aWRhayBtZW1iYWxpa2thbm55YSBzZWNhcmEgdGlkYWsgc2VuZ2FqYS4gTWlzYWxueWEsIHBlcmhhdGlrYW4gYmFod2EgcGVybnlhdGFhbiBpbmkgbWVtYmVyaWthbiBuaWxhaSB5YW5nIGJlcmJlZGEgZGFyaSB5YW5nIGRpIGF0YXM6DQogDQogZyg0LCA3KQ0KDQojIyBbMV0gMC4xNDQ5NDYxDQogDQpBbGFzYW4gcGVyYmVkYWFubnlhIGFkYWxhaCBrZXRpa2EgYXJndW1lbiBkaWJlcmlrYW4gdGFucGEgbmFtYSwgcG9zaXNpIGRhbGFtIHVydXRhbiBhcmd1bWVubGFoIHlhbmcgcGVudGluZy4gSmFkaSwgZGkgYXRhcywgNCBkaWd1bmFrYW4gdW50dWsgbmlsYWkgdGRhbiA3IHVudHVrIG5pbGFpIHguIFNhbmdhdCBtdWRhaCB1bnR1ayBkaWJpbmd1bmdrYW4gb2xlaCBzaXR1YXNpIGluaSwgamFkaSBwcmFrdGlrIHlhbmcgYmFpayBhZGFsYWggbWVuZ2lkZW50aWZpa2FzaSBhcmd1bWVuIHNlY2FyYSBla3NwbGlzaXQgZGVuZ2FuIG5hbWE6DQoNCmcodCA9IDcsIHggPSA0KQ0KDQojIyBbMV0gLTAuNDI3MzM3Mg==