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==