Pengantar

R dapat digunakan untuk membuat grafik dengan banyak fungsi grafik yang sudah disediakan. Package untuk membuat grafik di antara yaitu graphics, ggplot2, dan lattice. Materi yang akan dibahas yaitu fungsi-fungsi pada package graphics dengan perintah dasarnya yaitu fungsi plot.

Devices

Plot grafik digambarkan dalam sebuah media yaitu devices. Beberapa device yang ada di R: X11, windows, postscript, pdf, pictex, png, jpeg, bmp, xfig, bitmap.

Sewaktu menjalankan plot untuk membuat grafik, terdapat devices default yang digunakan:

  • X11 di Linux berbasis GUI dan MacOS
  • windows di MS Windows
  • pdf di Linux berbasis text

Disarankan file grafik disimpan menggunakan jpeg atau png.

Berikut adalah beberapa fungsi dalam devices:

  • dev.list() : digunakan untuk melihat daftar device yang sudah dibuat
  • dev.cur() : digunakan untuk melihat device aktif
  • dev.set() : digunakan untuk mengganti device aktif
  • dev.off() : digunakan untuk menutup device yang aktif
  • graphics.off() : digunakan untuk menutup semua device
  • dev.copy() : digunakan untuk mencopy isi dari device

Fungsi plot

Perintah grafik dasar dengan syntax: plot(x,y,...)

x dan y merupakan vektor untuk koordinat pada grafik, sementara … adalah pilihan lain.

x <- 1:16
y <- rnorm(16,8,1)
plot(x,y)

Bila hanya ada 1 peubah dalam argumen fungsi maka output berupa plot antara indeks (sumbu x) dengan nilai peubah (sumbu y).

plot(y)

plot(x)

Pilihan type

Pilihan type digunakan untuk bentuk grafik:

par(mfrow=c(3,3))
plot(x,y,type="p") # titik (default)
plot(x,y,type="l") # garis
plot(x,y,type="b") # garis & titik
plot(x,y,type="o") # garis & titik overlaid
plot(x,y,type="n") # nothing
plot(x,y,type="s") # tangga, segmen pertama horizontal
plot(x,y,type="S") # tangga, segmen pertama vertikal
plot(x,y,type="h") # garis vertikal dari sumbu-x ke titik sesuai nilai y

Pilihan Karakter

Pilihan karakter yang sering digunakan yaitu

  • pch untuk mengatur simbol dari titik koordinat plot.
  • cex untuk mengatur ukuran/size dari pch, semakin besar nilainya (>1) maka semakin besar ukuran simbolnya.

Berikut adalah ilustrasinya

par(mfrow=c(2,2))
plot(x,y,pch="*")
plot(x,y,pch=19)
plot(x,y,pch="*",cex=2)
plot(x,y,pch=19,cex=2)

Pilihan Garis

Pilihan garis yang sering digunakan yaitu

  • lty untuk mengatur tipe garis (1=solid, 2=small breaks, dll).
  • lwd untuk mengatur ketebalan garis, semakin besar angka maka garis akan semakin tebal.

Berikut adalah ilustrasinya.

par(mfrow=c(2,2))
plot(x,y,type="l",lty=1)
plot(x,y,type="l",lty=2)
plot(x,y,type="l",lty=1,lwd=2)
plot(x,y,type="l",lty=2,lwd=2)

Pilihan-pilihan Lain

Sumbu axis

axes berupa boolean apakah sumbu axis pada sumbu x dan y digambarkan

par(mfrow=c(1,2))
plot(x,y,axes=TRUE)
plot(x,y,axes=FALSE)

Batas nilai sumbu

xlim digunakan untuk membatasi sumbu x dengan nilai yang ditentukan. misalkan xlim=c(0,10)

par(mfrow=c(1,2))
plot(x,y)
plot(x,y,xlim=c(0,10))

berarti sumbu x dibatasi hanya antara 0 sampai 10

ylim digunakan untuk membatasi sumbu y dengan nilai yang ditentukan. misalkan ylim=c(5,8)

par(mfrow=c(1,2))
plot(x,y)
plot(x,y,ylim=c(5,8))

berarti sumbu y dibatasi hanya antara 5 sampai 8

Warna

col digunakan untuk mengganti warna titik/garis. Terdapat beberapa cara:

  • dengan angka 1-8
par(mfrow=c(3,3))
plot(x,y,pch=19,col=1)
plot(x,y,pch=19,col=2)
plot(x,y,pch=19,col=3)
plot(x,y,pch=19,col=4)
plot(x,y,type="l",col=5)
plot(x,y,type="l",col=6)
plot(x,y,type="l",col=7)
plot(x,y,type="l",col=8)

  • dengan nama warna (dalam bahasa inggris)
par(mfrow=c(2,3))
plot(x,y,pch=19,col="red")
plot(x,y,pch=19,col="orange")
plot(x,y,pch=19,col="yellow")
plot(x,y,type="l",col="green")
plot(x,y,type="l",col="blue")
plot(x,y,type="l",col="purple")

list warna yang bisa digunakan dapat dilihat pada:

warna <- data.frame(colors())
warna
  • dengan fungsi rgb()
par(mfrow=c(2,3))
plot(x,y,pch=19,col=rgb(1,0,0)) #merah
plot(x,y,pch=19,col=rgb(0,1,0)) #hijau
plot(x,y,pch=19,col=rgb(0,0,1)) #biru
plot(x,y,type="l",col=rgb(0,0,0)) #hitam 
plot(x,y,type="l",col=rgb(1,1,1)) #putih
plot(x,y,type="l",col=rgb(0.5,0.5,0.5)) #abu-abu

  • dengan fungsi rainbow()
```r
par(mfrow=c(1,2))
a <- c("A","B","C","D","E")
b <- c(8,2,5,8,4)
barplot(b,col=rainbow(3)) 
pie(b,labels=a,col = rainbow(length(b)))
```
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAApkAAAGbCAMAAAC4UXv2AAAAYFBMVEUAAAAAADoAAGYAAP8AOjoAOpAAZrYAZv8A/wAA/2Y6AAA6ADo6kNtmAABmZjpmtv+QOgCQ2/+2ZgC225C2///MAP/M/wDbkDrb////AAD/tmb/trb/25D//7b//9v///8zDZLlAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAMMElEQVR4nO3dC3fayB2G8YnbOE3WNNh1S0ID+v7fcpEQF4Fuo/mP5tXoec4eZ4+XFdLwy+iCjVxBpJhLvQJErSGTNEMmaYZM0gyZpBkySTNkkmbIJM2QSZohkzRDJmmGTNIMmaQZMkkzZJJmyCTNkEmaIZM0QyZphkzSDJmkGTJJM2SSZsgkzZBJmiGTNEMmaYZM0gyZpBkySTNkkmbIJM2QSZohkzRDJmmGTNLMT+aHc6/HrXPuZ6TVIarzkrn7+uuE87UoDpu3WCtEVOUj87g9edx/eS/ORoki5iPzsDntxPcvn8Xl620p156+0ZnZJjyU8KnJMOM58yrz91DxZKZ7ajJs2nFmZbRvccikwIzPzZFJRhm/Ssgko5BJmiGTNEMmaYZM0gyZpBkySTNkkmbIJM2QSZohkzRDJmmGTNIMmaQZMkkzZJJmyCTNkEmaIZM0QyZphkzSDJmkGTJJM2SSZsgkzZBJmiGTNEMmaYZM0gyZpBkySTNkkmbIJM2QSZohkzRDJmmGTNIMmaQZMkkzZJJmyCTNkEmaIZM0QyZphkzSDJmkGTJJM2SSZsgkzZBJmiGTNEMmaYbMzPpwZV/eU69HcMjMrI+vv05fd2NpumZRV80vZGbWWeZh8zbwuJri49Do8ERmZl1k/ux+SBtJPZ7IzKx6b/7a/l+HUArxRGZmnc+AXOXzodO3/zeO5R3P+bfgsrZxFofMVJ3nzL17nDRLlmV+NEucfU/mhg5np4fMzDrLLD5ePu+/W7OcILPP5p+//t18Gsv8XqVye//86LlchszU1TJ3JZnrq3F1OUVm90599/KfHz1nWmF5vUoVzL/ee079kJm6y5xZ/lFv6J3LaTJ/t0+cx+3r6Z9YG+LzKlUXyT6qVdm1HWEXyEzf5TizmjrKLXUNmJNpttjcn3adoy/pe+cn8+fp70l1zLt/PIx5eBMBmalqvDvp3KPL6TKfbZZ/CYYv6U/Nb2/+erlSxpy5iJ5dhsh8GLk/P0qUH7HOgbxepcPm5bOaNPddczgyhWpzaUhzV+8mI50Deb5K+/PKdB72IlOndpdhMq+n6a6oT34Om0jnQFzPzLUumGEyf58PN91tvxnrHAiZedaxJ7eQWQ6gu16eqg83I2xBnMUhM23dLo1onkBeji8jnQMhM8N6Jkwbmf3vphttRJzFITNh/S5NZM4wiMjMriGYC6GJzNwahmkjM/YwIjOzRsA0khl5HJGZVQPnPrYy4w4kMnPKff+eDU1kZtQJ5jiaVjJjDiUyM6qSOYammcyIY4nMfDrDzIUmMrPpAnMMTTuZ0UYTmbl0gzmCpqHMWMOJzEy6hzkvTWSOXYV0T52wJsxhmvqTJjLz6FHmEE1LmXEGFJlZ9ARzVplRRhSZOfQMc/mTJjIzqA3mEE35SROZGdQus5+mrcwIY4rM5dcBc+E0kbn4OmH200Tm3DyQOY6msUzzUUXm0uuD2UcTmXPzQGYeNJG58AZg9tC0lmk8rshceIMyO2kic2Ye65I5DHOpNBcj0w0X66mVGyOziyYyTbbC/WOoNcocBbOLprlM05FF5pIbCbODJjJNNgKZLY2WuUCayFxw42G200SmxTYg8zkfmW007WUaji0yF5yXzHloIhOZhaRMu8FF5oLzk9lCE5kGW4DMpzxhttBEpsEWIPMpb5lz0ETm2mQet865xt0+/WE+00Rm+BasXObeVbcfvb9f2RSZjzSFd+fIXET1faGO29usOQnmDDSRuSqZl7t2//92u7KJMh9oIjN4A1Yts74vbqOpMps0dXfnyFxCh03zrqPV7XKnymzQRGbw+iOz0elEfbLMZdBE5hJq2ZsHwGzQRGbo6q9a5vUMaO8u924OknlHE5mhq79umc9XjcJkRqWJzBXJPF9pP25vV9oDZd5oIjNw9Vcu83QS1Hx3MlTmlSYyA1d/7TIfC5YZjyYy1ywzHOaVJjLDVh+ZjSxk1jRFd+fIXGbInLg4ZEbORGYsmshEpglNZAatPTIbGcmsaCIzaO2R2chKZhSayWTWb5X1LQ6ZcTODWdFcvMzqbYi6l8/WhyBzngxlnmguXmb9a1LMmemzlPndLV/madYs37l9lvn4ub+LkDn6U4wFM5VpTjPJcWb5e6WZzJnuX0OtR6Z1Fpvo+z/s3Bsyk2d5BuTct2/uv6YlkXmaMf+JzNTZXTQ6sfxmLTPVVaPj1iEzcUZvTtYurWlypX29Mi1+PPPG0pomMpFpxNKYJjKROdXlI0tkItOogE/oaHVpShOZyDRjaUoTmci0Y2lJE5nI9HLZzxKZyLTI97YWI1za0UQmMi1ZmtG0GTZkZi7Tg6UVTWSuWeZImn4skYnM8EbI9JwuzWgiE5nWLG1oIhOZdntxQ5pGo4bM/GROni6RiUyDOmgGsjSgiUxkxmAZThOZyDQ8uDSkicyVy3ygaTRdIhOZwblILANpWg0aMhcv05xlGE1kItP44NKGptmYIXPJMqNMl8j0XDIyH4vHcjpNuyFD5oJlxoQ5kSYykVlI0kQmMgtFmYYjhkxkGtJEJjKr1GhaDhgykWlHE5nIrBObNJGJzDqtSfMyXh/1Z2Lf3Y59wqZZjM/z4pA5U1I0L5/P/hFE8rJl4YtoWxwyZyq6TA+arnxbqhwzZCJTTeY5ZCJTieZttJCJzEKI5p3M+gzoLWi7gkemdXHInC8RmneDxZyJzDJk+iwOmTMmQfN+rJCJzKr4ModpNoYKmcg8J0ATmchsK/n+vDlSl3PzL+8h2xQ2JF2LQ+a8JaYZY6CQicxgmlHGCZlZyExLE5nI7C7h/jzOMCEzE5npaEYaJWTmIjMVzViDhMxsZKahGW2MkInMEJnxhgiZ+chMQROZyBzT7DQjjhAyc5I5N82YA4TMrGTO+7uUUccHmXnJnJGmizs8yMxMZuTPe73RjD04yMxNZvxp080BE5kZypzjczXjD43fM+yccz+rf3n57F0cMpMWeY/uZoDpJ3P35b04bF4LZMoX9+YCcwyMz3Mct2/V16+/kClfRJrzDIvPsxw21Z68/AWkB5nu2uUbo3kMVz8QmX5Fu4XVTKPiP2ee+ng1mzNH80CmdzFozuXS9ziz9njYOGQuIHOa87n0Pzc/78+PW2QuIdu7/83pMv31TGRGzszmvC6Rmb1MK5uzjwUys5dpsVOfe8IskLkKmUXgxJnAJTLXInOyzbuL1DOvb5zFIVMw/516KpXV2sZZHDI187KZkGWBzJXJrN8NHrUPT7z1yFyVzPufVtBFWYXM7GXWn7NavXt3v0W9P0CTPmTmL7P6bOo/P8qfq13QFiFzJTKLfdBnU88fMtci87h9Tb0mXiFzLTJt7jgxX8hcjcyun/YWDZnI1AyZq5HJ3rz6E5kycQZ0vzhk6sRVo/vFIVOny5X2t9Qr4hcy85d59+7kgkJm9jIXGjKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpGTKRqRkykakZMpGpmd/gH7fnux513vUVmWSU1+DvXH2HuL3ruFUcMskon8E/bq8edx13JEYmGeUz+IfN9d6F++b+3F17+kZny3kgpch4ziQyyvM4s540O48ziYzy22EdNue9HDMmxY5DKdIMmaQZMkkzZJJmyCTNkEmaIZM0QyZphkzSDJmkGTJJM2SSZsgkzZBJmiGTNEMmaYZM0gyZpBkySTNkkmbIJM2QSZohkzRDJmmGTNIMmaQZMkkzZJJmyCTNkEmaIZM0QyZphkzSDJmkGTJJM2SSZsgkzZBJmiGTNEMmaYZM0gyZpBkySTNkkmbIJM2QSZohkzRDJmmGTNIMmaQZMkkzZJJmyCTNkEmaIZM0QyZphkzSDJmkGTJJM2SSZsgkzZBJmiGTNEMmaYZM0gyZpBkySTNkkmbIJM2QSZohkzRDJmmGTNIMmaQZMkkzZJJmyCTNkEmaIZM0QyZphkzSDJmkGTJJM2SSZsgkzZBJmiGTNEMmaYZM0gyZpBkySTNkkmbIJM2QSZohkzRDJmmGTNLsbw0X3C7FTBBdAAAAAElFTkSuQmCC" />

Pada barplot karena rainbow di set =3 maka plot hanya memiliki 3 warna dan warna tersebut diulang kembali sesuai urutan. Penggunaan perbedaan warna yang lebih tepat yaitu untuk membedakan kategori data seperti pada pie chart.

Pilihan pelabelan pada grafik

main digunakan untuk memberi label pada judul utama paling atas

x1 <- rnorm(16,70,10)
x2 <- rnorm(16,80,10)
plot(x1,x2,main="Sebaran Nilai")

sub digunakan untuk memberi label pada sub judul paling bawah

plot(x1,x2,main="Sebaran Nilai", sub="Plot antara nilai1 dan nilai2")

xlab digunakan untuk memberi label sumbu x

plot(x1,x2,main="Sebaran Nilai", sub="Plot antara nilai1 dan nilai2",xlab="Nilai1")

ylab digunakan untuk memberi label sumbu y

plot(x1,x2,main="Sebaran Nilai", sub="Plot antara nilai1 dan nilai2",xlab="Nilai1",ylab="Nilai2")

Fungsi-fungsi Grafik Lain

Fungsi Tambahan

Fungsi plot() akan menghapus grafik yang ada dan diganti dengan yang baru. Jika ingin menambahkan sesuatu pada grafik yang sudah ada, maka digunakan fungsi-fungsi: - points(x,y) : menambah tipe poin karakter

x <- 1:16
y <- rnorm(16,8,1)
xnew <- c(4,8,16)
ynew <- c(8,9,7)
plot(x,y,points(xnew,ynew,pch=19,col="blue"))

  • lines(x,y) : menambah tipe garis
plot(x,y,lines(x,y,col="blue"))

  • abline (a,b), abline(h=y), abline(v=x) : menambahkan garis lurus berdasarkan fungsi y=a+bx, horisontal, dan vertikal
par(mfrow=c(2,2))
plot(x,y,abline(h=7))
plot(x,y,abline(v=14))
plot(x,y,abline(4,0.5))
plot(x,y,abline(10,-0.5))

  • segments(x1,y1,x2,y2) : menambahkan garis lurus dari titik (x1,y1) ke (x2,y2)
  • arrows(x1,y1,x2,y2) : menambahkan garis dan panah dari titik (x1,y1) ke (x2,y2)
par(mfrow=c(1,2))
plot(x,y,segments(4,7,12,9))
plot(x,y,arrows(4,7,12,9))

  • poligons(x,y) : membuat poligon
plot(x,y,polygon(x,y))

  • text(x,y,teks) : menuliskan teks pada koordinat (x,y)
  • mtext : menuliskan label pada judul dan garis sumbu
par(mfrow=c(2,3))
plot(x,y,text(4.5,8.3,"ditandai"))
plot(x,y,mtext("label khusus",side=1))
plot(x,y,mtext("label khusus",side=2))
plot(x,y,mtext("label khusus",side=3))
plot(x,y,mtext("label khusus",side=4))

Teladan untuk penggunaan mtext

f <- function(x) cumsum(x)
x <- 1:20
y <- f(x)
plot(x, y, xlab = "", ylab = "")
mtext("Plotting the expression", side = 3, line = 1)
mtext(expression(y[i] == sum(x[j],j==1,i)), side = 3, line = -2.5)
mtext("The first variable", side= 1, line = 3)
mtext("The second variable",side = 2, line = 3) 

Terdapat beberapa simbol dalam expression() sebagai teks:

Fungsi untuk membuat plot dari plot kosong (type=“n” atau axes=FALSE)

axis digunakan untuk menambahkan titik-titik sumbu

x = 1:16
y = rnorm(16,7,1)
plot(x,y,type="n",axes=F)
axis(1, c(5,10,15,20))
axis(2, c(5,6,7,8,9,10))

box digunakan untuk membuat kotak axis

plot(x,y,type="n",axes=F)
axis(1, c(5,10,15,20))
axis(2, c(5,6,7,8,9,10))
box()

titledigunakan untuk menambahkan label untuk main, sub, xlab, ylab

plot(x,y,type="n",axes=F)
axis(1, c(5,10,15,20))
axis(2, c(5,6,7,8,9,10))
box()
title(main="Contoh plot", sub="Plot antara x dan y", xlab="Sumbu x", ylab="Sumbu y")

Teladan:

plot(x,y,type="l",axes=F)
axis(1,c(1,3,7,10),c("Jan","Mar","Jul","Okt"))
axis(2,seq(5,10,by=0.5))
box()
abline(h=7)

Fungsi grafik jenis lainnya

Berikut beberapa fungsi grafik yang sering digunakan

d <- round(rnorm(10,10,5))
e <- rep(c("A","B","C","D","E"),2)
par(mfrow=c(2,3))
barplot(d)
hist(d)
boxplot(d)
pie(round(rnorm(5,10,5)), labels=e)
qqplot(d,1:10)
qqnorm(d)

Berikut beberapa fungsi grafik lainnya yang dapat digunakan

g <- matrix(c(1:16),nrow=4) 
par(mfrow=c(2,2))
dotchart(d)
stars(g)
image(g)

pairs(g)

Parameter Grafik

Parameter-parameter dari grafik dapat disetting ulang melalui fungsi plot atau par(). Pilihan yang dikontrol oleh fungsi par() :

  • text and symbols: adj, ann, cex, crt, exp, font, mex, mkh, pch, ps, smo, srt
  • plot area: bty, new, pin, plt, pty, uin, usr, xpd
  • axes and tickmarks: exp, lab, las, mgp, tck, xaxp, xaxs, xaxt, yaxp, yaxs, yaxt
  • margins: mai, mar, mex, oma, omd, omi
  • figure and page areas: fig, fin, fty, mfg, mfcol, mfrow, oma, omd, omi
  • color: bg, col, fg, gamma
  • misc: ask, col, err, lty, lwd
  • Information: “1em”, acc, cin, cra, csi, cxy, dev, din, frm, omo , rsz, tsp, uin

Menggambar Banyak Grafik dalam Satu Device

Terdapat 3 cara untuk menampilkan beberapa grafik dalam satu device

  • Mengubah setting parameter par() –> mfrow atau mfcol
  • fungsi split.screen()
  • fungsi layout()

Setting Parameter

  • Parameter yang diubah mfrow atau mfcol –> par(mfrow=c(2,2))
  • Setting margin seperti mar untuk meningkatkan/menurunkan ruang sekeliling plot
par(mfrow=c(1,2))
plot(x,y,par(mar=c(4,4,4,4)))
plot(x,y,par(mar=c(2,2,2,2)))

oma untuk meningkatkan/menurunkan ruang antara matriks plot

par(mfrow=c(2,2), oma=c(4,4,4,4))
plot(x,y)
plot(y,x)
hist(x)
hist(y)

ruang antar matriks plot di atas besar sehingga grafik ditampilkan berukuran kecil. Sementara untuk memperkecil ruang antar plot bisa dengan menurunkan nilai pada oma seperti berikut.

par(mfrow=c(2,2), oma=c(2,2,2,2))
plot(x,y)
plot(y,x)
hist(x)
hist(y)

  • par(mfrow=c(1,1)) mengembalikan ke layout default

Fungsi split.screen

  • Menggunakan fungsi split.screen() –> split.screen(c(2,2)) seperti par(mfrow=c(2,2))
  • Berpindah antar area plot menggunakan fungsi screen(i)
  • Fungsi close.screen(all=T) mengembalikan ke default
x <- rnorm(10); y<- rnorm(10)
split.screen(c(2,2))
[1] 1 2 3 4
screen(1)
plot(x=1:10,x)
screen(2)
plot(x=1:10,y)
screen(3)
boxplot(x)
screen(4)
boxplot(y)
close.screen(all=TRUE)

Fungsi ’layoutDengan fungsilayout()ukuran grafiknya lebih fleksibel (bervariasi) dibanding setting parameter atau fungsisplit.screen()`.

Langkah pertama adalah membuat matriks rancangan dengan nilai integer positif (untuk area grafik) dan 0 untuk area kosong.

rancangan <- matrix(c(1,1,3,1,1,3,2,2,4,2,2,4), nrow=3)
obj <- layout(rancangan)
layout.show(obj)

plot(x=1:10,x)
plot(x=1:10,y)
boxplot(x,horizontal = TRUE)
boxplot(y,horizontal = TRUE)
layout(1)


  1. Mahasiswa Statistika dan Sains Data IPB, ↩︎

LS0tDQp0aXRsZTogIlBlbXJvZ3JhbWFuIEdyYWZpayBkZW5nYW4gUGFja2FnZSBncmFwaGljcyINCmF1dGhvcjogIkFubmlzc2EgTnVyIEZpdHJpYSBGYXRoaW5hXltNYWhhc2lzd2EgU3RhdGlzdGlrYSBkYW4gU2FpbnMgRGF0YSBJUEIsIGFubmlzc2FfbmZmQGFwcHMuaXBiLmFjLmlkXSINCmRhdGU6ICIxNS80LzIwMjIiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIGhpZ2hsaWdodDogcHlnbWVudHMNCmVkaXRvcl9vcHRpb25zOiANCiAgbWFya2Rvd246IA0KICAgIHdyYXA6IHNlbnRlbmNlDQotLS0NCg0KIyBQZW5nYW50YXINCg0KUiBkYXBhdCBkaWd1bmFrYW4gdW50dWsgbWVtYnVhdCBncmFmaWsgZGVuZ2FuIGJhbnlhayBmdW5nc2kgZ3JhZmlrIHlhbmcgc3VkYWggZGlzZWRpYWthbi4NClBhY2thZ2UgdW50dWsgbWVtYnVhdCBncmFmaWsgZGkgYW50YXJhIHlhaXR1IGBncmFwaGljc2AsIGBnZ3Bsb3QyYCwgZGFuIGBsYXR0aWNlYC4NCk1hdGVyaSB5YW5nIGFrYW4gZGliYWhhcyB5YWl0dSBmdW5nc2ktZnVuZ3NpIHBhZGEgcGFja2FnZSBgZ3JhcGhpY3NgIGRlbmdhbiBwZXJpbnRhaCBkYXNhcm55YSB5YWl0dSBmdW5nc2kgYHBsb3RgLg0KDQojIERldmljZXMNCg0KUGxvdCBncmFmaWsgZGlnYW1iYXJrYW4gZGFsYW0gc2VidWFoIG1lZGlhIHlhaXR1IGBkZXZpY2VzYC4NCkJlYmVyYXBhIGRldmljZSB5YW5nIGFkYSBkaSBSOiBYMTEsIHdpbmRvd3MsIHBvc3RzY3JpcHQsIHBkZiwgcGljdGV4LCBwbmcsIGpwZWcsIGJtcCwgeGZpZywgYml0bWFwLg0KDQpTZXdha3R1IG1lbmphbGFua2FuIHBsb3QgdW50dWsgbWVtYnVhdCBncmFmaWssIHRlcmRhcGF0IGRldmljZXMgZGVmYXVsdCB5YW5nIGRpZ3VuYWthbjoNCg0KLSAgIFgxMSBkaSBMaW51eCBiZXJiYXNpcyBHVUkgZGFuIE1hY09TDQotICAgd2luZG93cyBkaSBNUyBXaW5kb3dzDQotICAgcGRmIGRpIExpbnV4IGJlcmJhc2lzIHRleHQNCg0KRGlzYXJhbmthbiBmaWxlIGdyYWZpayBkaXNpbXBhbiBtZW5nZ3VuYWthbiBqcGVnIGF0YXUgcG5nLg0KDQpCZXJpa3V0IGFkYWxhaCBiZWJlcmFwYSBmdW5nc2kgZGFsYW0gZGV2aWNlczoNCg0KLSAgIGBkZXYubGlzdCgpYCA6IGRpZ3VuYWthbiB1bnR1ayBtZWxpaGF0IGRhZnRhciBkZXZpY2UgeWFuZyBzdWRhaCBkaWJ1YXQNCi0gICBgZGV2LmN1cigpYCA6IGRpZ3VuYWthbiB1bnR1ayBtZWxpaGF0IGRldmljZSBha3RpZg0KLSAgIGBkZXYuc2V0KClgIDogZGlndW5ha2FuIHVudHVrIG1lbmdnYW50aSBkZXZpY2UgYWt0aWYNCi0gICBgZGV2Lm9mZigpYCA6IGRpZ3VuYWthbiB1bnR1ayBtZW51dHVwIGRldmljZSB5YW5nIGFrdGlmDQotICAgYGdyYXBoaWNzLm9mZigpYCA6IGRpZ3VuYWthbiB1bnR1ayBtZW51dHVwIHNlbXVhIGRldmljZQ0KLSAgIGBkZXYuY29weSgpYCA6IGRpZ3VuYWthbiB1bnR1ayBtZW5jb3B5IGlzaSBkYXJpIGRldmljZQ0KDQojIEZ1bmdzaSBgcGxvdGANCg0KUGVyaW50YWggZ3JhZmlrIGRhc2FyIGRlbmdhbiBzeW50YXg6IGBwbG90KHgseSwuLi4pYA0KDQp4IGRhbiB5IG1lcnVwYWthbiB2ZWt0b3IgdW50dWsga29vcmRpbmF0IHBhZGEgZ3JhZmlrLCBzZW1lbnRhcmEgLi4uIGFkYWxhaCBwaWxpaGFuIGxhaW4uDQoNCmBgYHtyfQ0KeCA8LSAxOjE2DQp5IDwtIHJub3JtKDE2LDgsMSkNCnBsb3QoeCx5KQ0KYGBgDQoNCkJpbGEgaGFueWEgYWRhIDEgcGV1YmFoIGRhbGFtIGFyZ3VtZW4gZnVuZ3NpIG1ha2Egb3V0cHV0IGJlcnVwYSBwbG90IGFudGFyYSBpbmRla3MgKHN1bWJ1IHgpIGRlbmdhbiBuaWxhaSBwZXViYWggKHN1bWJ1IHkpLg0KDQpgYGB7cn0NCnBsb3QoeSkNCnBsb3QoeCkNCmBgYA0KDQojIyBQaWxpaGFuIGB0eXBlYA0KDQpQaWxpaGFuIGB0eXBlYCBkaWd1bmFrYW4gdW50dWsgYmVudHVrIGdyYWZpazoNCg0KYGBge3J9DQpwYXIobWZyb3c9YygzLDMpKQ0KcGxvdCh4LHksdHlwZT0icCIpICMgdGl0aWsgKGRlZmF1bHQpDQpwbG90KHgseSx0eXBlPSJsIikgIyBnYXJpcw0KcGxvdCh4LHksdHlwZT0iYiIpICMgZ2FyaXMgJiB0aXRpaw0KcGxvdCh4LHksdHlwZT0ibyIpICMgZ2FyaXMgJiB0aXRpayBvdmVybGFpZA0KcGxvdCh4LHksdHlwZT0ibiIpICMgbm90aGluZw0KcGxvdCh4LHksdHlwZT0icyIpICMgdGFuZ2dhLCBzZWdtZW4gcGVydGFtYSBob3Jpem9udGFsDQpwbG90KHgseSx0eXBlPSJTIikgIyB0YW5nZ2EsIHNlZ21lbiBwZXJ0YW1hIHZlcnRpa2FsDQpwbG90KHgseSx0eXBlPSJoIikgIyBnYXJpcyB2ZXJ0aWthbCBkYXJpIHN1bWJ1LXgga2UgdGl0aWsgc2VzdWFpIG5pbGFpIHkNCmBgYA0KDQojIyBQaWxpaGFuIEthcmFrdGVyDQoNClBpbGloYW4ga2FyYWt0ZXIgeWFuZyBzZXJpbmcgZGlndW5ha2FuIHlhaXR1DQoNCi0gICBgcGNoYCB1bnR1ayBtZW5nYXR1ciBzaW1ib2wgZGFyaSB0aXRpayBrb29yZGluYXQgcGxvdC4NCi0gICBgY2V4YCB1bnR1ayBtZW5nYXR1ciB1a3VyYW4vc2l6ZSBkYXJpIHBjaCwgc2VtYWtpbiBiZXNhciBuaWxhaW55YSAoXD4xKSBtYWthIHNlbWFraW4gYmVzYXIgdWt1cmFuIHNpbWJvbG55YS4NCg0KQmVyaWt1dCBhZGFsYWggaWx1c3RyYXNpbnlhDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMiwyKSkNCnBsb3QoeCx5LHBjaD0iKiIpDQpwbG90KHgseSxwY2g9MTkpDQpwbG90KHgseSxwY2g9IioiLGNleD0yKQ0KcGxvdCh4LHkscGNoPTE5LGNleD0yKQ0KYGBgDQoNCiMjIFBpbGloYW4gR2FyaXMNCg0KUGlsaWhhbiBnYXJpcyB5YW5nIHNlcmluZyBkaWd1bmFrYW4geWFpdHUNCg0KLSAgIGBsdHlgIHVudHVrIG1lbmdhdHVyIHRpcGUgZ2FyaXMgKDE9c29saWQsIDI9c21hbGwgYnJlYWtzLCBkbGwpLg0KLSAgIGBsd2RgIHVudHVrIG1lbmdhdHVyIGtldGViYWxhbiBnYXJpcywgc2VtYWtpbiBiZXNhciBhbmdrYSBtYWthIGdhcmlzIGFrYW4gc2VtYWtpbiB0ZWJhbC4NCg0KQmVyaWt1dCBhZGFsYWggaWx1c3RyYXNpbnlhLg0KDQpgYGB7cn0NCnBhcihtZnJvdz1jKDIsMikpDQpwbG90KHgseSx0eXBlPSJsIixsdHk9MSkNCnBsb3QoeCx5LHR5cGU9ImwiLGx0eT0yKQ0KcGxvdCh4LHksdHlwZT0ibCIsbHR5PTEsbHdkPTIpDQpwbG90KHgseSx0eXBlPSJsIixsdHk9Mixsd2Q9MikNCmBgYA0KDQojIyBQaWxpaGFuLXBpbGloYW4gTGFpbg0KDQojIyMgU3VtYnUgYXhpcw0KDQpgYXhlc2AgYmVydXBhIGJvb2xlYW4gYXBha2FoIHN1bWJ1IGF4aXMgcGFkYSBzdW1idSB4IGRhbiB5IGRpZ2FtYmFya2FuDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QoeCx5LGF4ZXM9VFJVRSkNCnBsb3QoeCx5LGF4ZXM9RkFMU0UpDQpgYGANCg0KIyMjIEJhdGFzIG5pbGFpIHN1bWJ1DQoNCmB4bGltYCBkaWd1bmFrYW4gdW50dWsgbWVtYmF0YXNpIHN1bWJ1IHggZGVuZ2FuIG5pbGFpIHlhbmcgZGl0ZW50dWthbi4NCm1pc2Fsa2FuIHhsaW09YygwLDEwKQ0KDQpgYGB7cn0NCnBhcihtZnJvdz1jKDEsMikpDQpwbG90KHgseSkNCnBsb3QoeCx5LHhsaW09YygwLDEwKSkNCmBgYA0KDQpiZXJhcnRpIHN1bWJ1IHggZGliYXRhc2kgaGFueWEgYW50YXJhIDAgc2FtcGFpIDEwDQoNCmB5bGltYCBkaWd1bmFrYW4gdW50dWsgbWVtYmF0YXNpIHN1bWJ1IHkgZGVuZ2FuIG5pbGFpIHlhbmcgZGl0ZW50dWthbi4NCm1pc2Fsa2FuIHlsaW09Yyg1LDgpDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QoeCx5KQ0KcGxvdCh4LHkseWxpbT1jKDUsOCkpDQpgYGANCg0KYmVyYXJ0aSBzdW1idSB5IGRpYmF0YXNpIGhhbnlhIGFudGFyYSA1IHNhbXBhaSA4DQoNCiMjIyBXYXJuYQ0KDQpgY29sYCBkaWd1bmFrYW4gdW50dWsgbWVuZ2dhbnRpIHdhcm5hIHRpdGlrL2dhcmlzLg0KVGVyZGFwYXQgYmViZXJhcGEgY2FyYToNCg0KLSAgIGRlbmdhbiBhbmdrYSAxLTgNCg0KYGBge3J9DQpwYXIobWZyb3c9YygzLDMpKQ0KcGxvdCh4LHkscGNoPTE5LGNvbD0xKQ0KcGxvdCh4LHkscGNoPTE5LGNvbD0yKQ0KcGxvdCh4LHkscGNoPTE5LGNvbD0zKQ0KcGxvdCh4LHkscGNoPTE5LGNvbD00KQ0KcGxvdCh4LHksdHlwZT0ibCIsY29sPTUpDQpwbG90KHgseSx0eXBlPSJsIixjb2w9NikNCnBsb3QoeCx5LHR5cGU9ImwiLGNvbD03KQ0KcGxvdCh4LHksdHlwZT0ibCIsY29sPTgpDQpgYGANCg0KLSAgIGRlbmdhbiBuYW1hIHdhcm5hIChkYWxhbSBiYWhhc2EgaW5nZ3JpcykNCg0KYGBge3J9DQpwYXIobWZyb3c9YygyLDMpKQ0KcGxvdCh4LHkscGNoPTE5LGNvbD0icmVkIikNCnBsb3QoeCx5LHBjaD0xOSxjb2w9Im9yYW5nZSIpDQpwbG90KHgseSxwY2g9MTksY29sPSJ5ZWxsb3ciKQ0KcGxvdCh4LHksdHlwZT0ibCIsY29sPSJncmVlbiIpDQpwbG90KHgseSx0eXBlPSJsIixjb2w9ImJsdWUiKQ0KcGxvdCh4LHksdHlwZT0ibCIsY29sPSJwdXJwbGUiKQ0KYGBgDQoNCmxpc3Qgd2FybmEgeWFuZyBiaXNhIGRpZ3VuYWthbiBkYXBhdCBkaWxpaGF0IHBhZGE6DQoNCmBgYHtyfQ0Kd2FybmEgPC0gZGF0YS5mcmFtZShjb2xvcnMoKSkNCndhcm5hDQpgYGANCg0KLSAgIGRlbmdhbiBmdW5nc2kgYHJnYigpYA0KDQpgYGB7cn0NCnBhcihtZnJvdz1jKDIsMykpDQpwbG90KHgseSxwY2g9MTksY29sPXJnYigxLDAsMCkpICNtZXJhaA0KcGxvdCh4LHkscGNoPTE5LGNvbD1yZ2IoMCwxLDApKSAjaGlqYXUNCnBsb3QoeCx5LHBjaD0xOSxjb2w9cmdiKDAsMCwxKSkgI2JpcnUNCnBsb3QoeCx5LHR5cGU9ImwiLGNvbD1yZ2IoMCwwLDApKSAjaGl0YW0gDQpwbG90KHgseSx0eXBlPSJsIixjb2w9cmdiKDEsMSwxKSkgI3B1dGloDQpwbG90KHgseSx0eXBlPSJsIixjb2w9cmdiKDAuNSwwLjUsMC41KSkgI2FidS1hYnUNCmBgYA0KDQotICAgZGVuZ2FuIGZ1bmdzaSBgcmFpbmJvdygpYA0KDQogICAgYGBge3J9DQogICAgcGFyKG1mcm93PWMoMSwyKSkNCiAgICBhIDwtIGMoIkEiLCJCIiwiQyIsIkQiLCJFIikNCiAgICBiIDwtIGMoOCwyLDUsOCw0KQ0KICAgIGJhcnBsb3QoYixjb2w9cmFpbmJvdygzKSkgDQogICAgcGllKGIsbGFiZWxzPWEsY29sID0gcmFpbmJvdyhsZW5ndGgoYikpKQ0KICAgIGBgYA0KDQpQYWRhIGJhcnBsb3Qga2FyZW5hIHJhaW5ib3cgZGkgc2V0ID0zIG1ha2EgcGxvdCBoYW55YSBtZW1pbGlraSAzIHdhcm5hIGRhbiB3YXJuYSB0ZXJzZWJ1dCBkaXVsYW5nIGtlbWJhbGkgc2VzdWFpIHVydXRhbi4NClBlbmdndW5hYW4gcGVyYmVkYWFuIHdhcm5hIHlhbmcgbGViaWggdGVwYXQgeWFpdHUgdW50dWsgbWVtYmVkYWthbiBrYXRlZ29yaSBkYXRhIHNlcGVydGkgcGFkYSBwaWUgY2hhcnQuDQoNCiMjIyBQaWxpaGFuIHBlbGFiZWxhbiBwYWRhIGdyYWZpaw0KDQpgbWFpbmAgZGlndW5ha2FuIHVudHVrIG1lbWJlcmkgbGFiZWwgcGFkYSBqdWR1bCB1dGFtYSBwYWxpbmcgYXRhcw0KDQpgYGB7cn0NCngxIDwtIHJub3JtKDE2LDcwLDEwKQ0KeDIgPC0gcm5vcm0oMTYsODAsMTApDQpwbG90KHgxLHgyLG1haW49IlNlYmFyYW4gTmlsYWkiKQ0KYGBgDQoNCmBzdWJgIGRpZ3VuYWthbiB1bnR1ayBtZW1iZXJpIGxhYmVsIHBhZGEgc3ViIGp1ZHVsIHBhbGluZyBiYXdhaA0KDQpgYGB7cn0NCnBsb3QoeDEseDIsbWFpbj0iU2ViYXJhbiBOaWxhaSIsIHN1Yj0iUGxvdCBhbnRhcmEgbmlsYWkxIGRhbiBuaWxhaTIiKQ0KYGBgDQoNCmB4bGFiYCBkaWd1bmFrYW4gdW50dWsgbWVtYmVyaSBsYWJlbCBzdW1idSB4DQoNCmBgYHtyfQ0KcGxvdCh4MSx4MixtYWluPSJTZWJhcmFuIE5pbGFpIiwgc3ViPSJQbG90IGFudGFyYSBuaWxhaTEgZGFuIG5pbGFpMiIseGxhYj0iTmlsYWkxIikNCmBgYA0KDQpgeWxhYmAgZGlndW5ha2FuIHVudHVrIG1lbWJlcmkgbGFiZWwgc3VtYnUgeQ0KDQpgYGB7cn0NCnBsb3QoeDEseDIsbWFpbj0iU2ViYXJhbiBOaWxhaSIsIHN1Yj0iUGxvdCBhbnRhcmEgbmlsYWkxIGRhbiBuaWxhaTIiLHhsYWI9Ik5pbGFpMSIseWxhYj0iTmlsYWkyIikNCmBgYA0KDQojIEZ1bmdzaS1mdW5nc2kgR3JhZmlrIExhaW4NCg0KIyMgRnVuZ3NpIFRhbWJhaGFuDQoNCkZ1bmdzaSBgcGxvdCgpYCBha2FuIG1lbmdoYXB1cyBncmFmaWsgeWFuZyBhZGEgZGFuIGRpZ2FudGkgZGVuZ2FuIHlhbmcgYmFydS4NCkppa2EgaW5naW4gbWVuYW1iYWhrYW4gc2VzdWF0dSBwYWRhIGdyYWZpayB5YW5nIHN1ZGFoIGFkYSwgbWFrYSBkaWd1bmFrYW4gZnVuZ3NpLWZ1bmdzaTogLSBgcG9pbnRzKHgseSlgIDogbWVuYW1iYWggdGlwZSBwb2luIGthcmFrdGVyDQoNCmBgYHtyfQ0KeCA8LSAxOjE2DQp5IDwtIHJub3JtKDE2LDgsMSkNCnhuZXcgPC0gYyg0LDgsMTYpDQp5bmV3IDwtIGMoOCw5LDcpDQpwbG90KHgseSxwb2ludHMoeG5ldyx5bmV3LHBjaD0xOSxjb2w9ImJsdWUiKSkNCmBgYA0KDQotICAgYGxpbmVzKHgseSlgIDogbWVuYW1iYWggdGlwZSBnYXJpcw0KDQpgYGB7cn0NCnBsb3QoeCx5LGxpbmVzKHgseSxjb2w9ImJsdWUiKSkNCmBgYA0KDQotICAgYGFibGluZSAoYSxiKWAsIGBhYmxpbmUoaD15KWAsIGBhYmxpbmUodj14KWAgOiBtZW5hbWJhaGthbiBnYXJpcyBsdXJ1cyBiZXJkYXNhcmthbiBmdW5nc2kgeT1hK2J4LCBob3Jpc29udGFsLCBkYW4gdmVydGlrYWwNCg0KYGBge3J9DQpwYXIobWZyb3c9YygyLDIpKQ0KcGxvdCh4LHksYWJsaW5lKGg9NykpDQpwbG90KHgseSxhYmxpbmUodj0xNCkpDQpwbG90KHgseSxhYmxpbmUoNCwwLjUpKQ0KcGxvdCh4LHksYWJsaW5lKDEwLC0wLjUpKQ0KYGBgDQoNCi0gICBgc2VnbWVudHMoeDEseTEseDIseTIpYCA6IG1lbmFtYmFoa2FuIGdhcmlzIGx1cnVzIGRhcmkgdGl0aWsgKHgxLHkxKSBrZSAoeDIseTIpDQotICAgYGFycm93cyh4MSx5MSx4Mix5MilgIDogbWVuYW1iYWhrYW4gZ2FyaXMgZGFuIHBhbmFoIGRhcmkgdGl0aWsgKHgxLHkxKSBrZSAoeDIseTIpDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QoeCx5LHNlZ21lbnRzKDQsNywxMiw5KSkNCnBsb3QoeCx5LGFycm93cyg0LDcsMTIsOSkpDQpgYGANCg0KLSAgIGBwb2xpZ29ucyh4LHkpYCA6IG1lbWJ1YXQgcG9saWdvbg0KDQpgYGB7cn0NCnBsb3QoeCx5LHBvbHlnb24oeCx5KSkNCmBgYA0KDQotICAgYHRleHQoeCx5LHRla3MpYCA6IG1lbnVsaXNrYW4gdGVrcyBwYWRhIGtvb3JkaW5hdCAoeCx5KQ0KLSAgIGBtdGV4dGAgOiBtZW51bGlza2FuIGxhYmVsIHBhZGEganVkdWwgZGFuIGdhcmlzIHN1bWJ1DQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMiwzKSkNCnBsb3QoeCx5LHRleHQoNC41LDguMywiZGl0YW5kYWkiKSkNCnBsb3QoeCx5LG10ZXh0KCJsYWJlbCBraHVzdXMiLHNpZGU9MSkpDQpwbG90KHgseSxtdGV4dCgibGFiZWwga2h1c3VzIixzaWRlPTIpKQ0KcGxvdCh4LHksbXRleHQoImxhYmVsIGtodXN1cyIsc2lkZT0zKSkNCnBsb3QoeCx5LG10ZXh0KCJsYWJlbCBraHVzdXMiLHNpZGU9NCkpDQpgYGANCg0KVGVsYWRhbiB1bnR1ayBwZW5nZ3VuYWFuIGBtdGV4dGANCg0KYGBge3J9DQpmIDwtIGZ1bmN0aW9uKHgpIGN1bXN1bSh4KQ0KeCA8LSAxOjIwDQp5IDwtIGYoeCkNCnBsb3QoeCwgeSwgeGxhYiA9ICIiLCB5bGFiID0gIiIpDQptdGV4dCgiUGxvdHRpbmcgdGhlIGV4cHJlc3Npb24iLCBzaWRlID0gMywgbGluZSA9IDEpDQptdGV4dChleHByZXNzaW9uKHlbaV0gPT0gc3VtKHhbal0saj09MSxpKSksIHNpZGUgPSAzLCBsaW5lID0gLTIuNSkNCm10ZXh0KCJUaGUgZmlyc3QgdmFyaWFibGUiLCBzaWRlPSAxLCBsaW5lID0gMykNCm10ZXh0KCJUaGUgc2Vjb25kIHZhcmlhYmxlIixzaWRlID0gMiwgbGluZSA9IDMpIA0KYGBgDQoNClRlcmRhcGF0IGJlYmVyYXBhIHNpbWJvbCBkYWxhbSBgZXhwcmVzc2lvbigpYCBzZWJhZ2FpIHRla3M6DQoNCiFbXShzaW1ib2wuanBlZyl7d2lkdGg9IjIyNSJ9DQoNCiMjIEZ1bmdzaSB1bnR1ayBtZW1idWF0IHBsb3QgZGFyaSBwbG90IGtvc29uZyAodHlwZT0ibiIgYXRhdSBheGVzPUZBTFNFKQ0KDQpgYXhpc2AgZGlndW5ha2FuIHVudHVrIG1lbmFtYmFoa2FuIHRpdGlrLXRpdGlrIHN1bWJ1DQoNCmBgYHtyfQ0KeCA9IDE6MTYNCnkgPSBybm9ybSgxNiw3LDEpDQpwbG90KHgseSx0eXBlPSJuIixheGVzPUYpDQpheGlzKDEsIGMoNSwxMCwxNSwyMCkpDQpheGlzKDIsIGMoNSw2LDcsOCw5LDEwKSkNCmBgYA0KDQpgYm94YCBkaWd1bmFrYW4gdW50dWsgbWVtYnVhdCBrb3RhayBheGlzDQoNCmBgYHtyfQ0KcGxvdCh4LHksdHlwZT0ibiIsYXhlcz1GKQ0KYXhpcygxLCBjKDUsMTAsMTUsMjApKQ0KYXhpcygyLCBjKDUsNiw3LDgsOSwxMCkpDQpib3goKQ0KYGBgDQoNCmB0aXRsZWBkaWd1bmFrYW4gdW50dWsgbWVuYW1iYWhrYW4gbGFiZWwgdW50dWsgbWFpbiwgc3ViLCB4bGFiLCB5bGFiDQoNCmBgYHtyfQ0KcGxvdCh4LHksdHlwZT0ibiIsYXhlcz1GKQ0KYXhpcygxLCBjKDUsMTAsMTUsMjApKQ0KYXhpcygyLCBjKDUsNiw3LDgsOSwxMCkpDQpib3goKQ0KdGl0bGUobWFpbj0iQ29udG9oIHBsb3QiLCBzdWI9IlBsb3QgYW50YXJhIHggZGFuIHkiLCB4bGFiPSJTdW1idSB4IiwgeWxhYj0iU3VtYnUgeSIpDQpgYGANCg0KVGVsYWRhbjoNCg0KYGBge3J9DQpwbG90KHgseSx0eXBlPSJsIixheGVzPUYpDQpheGlzKDEsYygxLDMsNywxMCksYygiSmFuIiwiTWFyIiwiSnVsIiwiT2t0IikpDQpheGlzKDIsc2VxKDUsMTAsYnk9MC41KSkNCmJveCgpDQphYmxpbmUoaD03KQ0KYGBgDQoNCiMjIEZ1bmdzaSBncmFmaWsgamVuaXMgbGFpbm55YQ0KDQpCZXJpa3V0IGJlYmVyYXBhIGZ1bmdzaSBncmFmaWsgeWFuZyBzZXJpbmcgZGlndW5ha2FuDQoNCmBgYHtyfQ0KZCA8LSByb3VuZChybm9ybSgxMCwxMCw1KSkNCmUgPC0gcmVwKGMoIkEiLCJCIiwiQyIsIkQiLCJFIiksMikNCnBhcihtZnJvdz1jKDIsMykpDQpiYXJwbG90KGQpDQpoaXN0KGQpDQpib3hwbG90KGQpDQpwaWUocm91bmQocm5vcm0oNSwxMCw1KSksIGxhYmVscz1lKQ0KcXFwbG90KGQsMToxMCkNCnFxbm9ybShkKQ0KYGBgDQoNCkJlcmlrdXQgYmViZXJhcGEgZnVuZ3NpIGdyYWZpayBsYWlubnlhIHlhbmcgZGFwYXQgZGlndW5ha2FuDQoNCmBgYHtyfQ0KZyA8LSBtYXRyaXgoYygxOjE2KSxucm93PTQpIA0KcGFyKG1mcm93PWMoMiwyKSkNCmRvdGNoYXJ0KGQpDQpzdGFycyhnKQ0KaW1hZ2UoZykNCmBgYA0KDQpgYGB7cn0NCnBhaXJzKGcpDQpgYGANCg0KIyBQYXJhbWV0ZXIgR3JhZmlrDQoNClBhcmFtZXRlci1wYXJhbWV0ZXIgZGFyaSBncmFmaWsgZGFwYXQgZGlzZXR0aW5nIHVsYW5nIG1lbGFsdWkgZnVuZ3NpIGBwbG90YCBhdGF1IGBwYXIoKS5gIFBpbGloYW4geWFuZyBkaWtvbnRyb2wgb2xlaCBmdW5nc2kgYHBhcigpYCA6DQoNCi0gICB0ZXh0IGFuZCBzeW1ib2xzOiBhZGosIGFubiwgY2V4LCBjcnQsIGV4cCwgZm9udCwgbWV4LCBta2gsIHBjaCwgcHMsIHNtbywgc3J0DQotICAgcGxvdCBhcmVhOiBidHksIG5ldywgcGluLCBwbHQsIHB0eSwgdWluLCB1c3IsIHhwZA0KLSAgIGF4ZXMgYW5kIHRpY2ttYXJrczogZXhwLCBsYWIsIGxhcywgbWdwLCB0Y2ssIHhheHAsIHhheHMsIHhheHQsIHlheHAsIHlheHMsIHlheHQNCi0gICBtYXJnaW5zOiBtYWksIG1hciwgbWV4LCBvbWEsIG9tZCwgb21pDQotICAgZmlndXJlIGFuZCBwYWdlIGFyZWFzOiBmaWcsIGZpbiwgZnR5LCBtZmcsIG1mY29sLCBtZnJvdywgb21hLCBvbWQsIG9taQ0KLSAgIGNvbG9yOiBiZywgY29sLCBmZywgZ2FtbWENCi0gICBtaXNjOiBhc2ssIGNvbCwgZXJyLCBsdHksIGx3ZA0KLSAgIEluZm9ybWF0aW9uOiAiMWVtIiwgYWNjLCBjaW4sIGNyYSwgY3NpLCBjeHksIGRldiwgZGluLCBmcm0sIG9tbyAsIHJzeiwgdHNwLCB1aW4NCg0KIyBNZW5nZ2FtYmFyIEJhbnlhayBHcmFmaWsgZGFsYW0gU2F0dSBEZXZpY2UNCg0KVGVyZGFwYXQgMyBjYXJhIHVudHVrIG1lbmFtcGlsa2FuIGJlYmVyYXBhIGdyYWZpayBkYWxhbSBzYXR1IGRldmljZQ0KDQotICAgTWVuZ3ViYWggc2V0dGluZyBwYXJhbWV0ZXIgYHBhcigpIOKAkz4gbWZyb3dgIGF0YXUgYG1mY29sYA0KLSAgIGZ1bmdzaSBgc3BsaXQuc2NyZWVuKClgDQotICAgZnVuZ3NpIGBsYXlvdXQoKWANCg0KIyMgU2V0dGluZyBQYXJhbWV0ZXINCg0KLSAgIFBhcmFtZXRlciB5YW5nIGRpdWJhaCBgbWZyb3dgIGF0YXUgYG1mY29sIOKAkz4gcGFyKG1mcm93PWMoMiwyKSlgDQotICAgU2V0dGluZyBtYXJnaW4gc2VwZXJ0aSBgbWFyYCB1bnR1ayBtZW5pbmdrYXRrYW4vbWVudXJ1bmthbiBydWFuZyBzZWtlbGlsaW5nIHBsb3QNCg0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KcGxvdCh4LHkscGFyKG1hcj1jKDQsNCw0LDQpKSkNCnBsb3QoeCx5LHBhcihtYXI9YygyLDIsMiwyKSkpDQpgYGANCg0KYG9tYWAgdW50dWsgbWVuaW5na2F0a2FuL21lbnVydW5rYW4gcnVhbmcgYW50YXJhIG1hdHJpa3MgcGxvdA0KDQpgYGB7cn0NCnBhcihtZnJvdz1jKDIsMiksIG9tYT1jKDQsNCw0LDQpKQ0KcGxvdCh4LHkpDQpwbG90KHkseCkNCmhpc3QoeCkNCmhpc3QoeSkNCmBgYA0KDQpydWFuZyBhbnRhciBtYXRyaWtzIHBsb3QgZGkgYXRhcyBiZXNhciBzZWhpbmdnYSBncmFmaWsgZGl0YW1waWxrYW4gYmVydWt1cmFuIGtlY2lsLg0KU2VtZW50YXJhIHVudHVrIG1lbXBlcmtlY2lsIHJ1YW5nIGFudGFyIHBsb3QgYmlzYSBkZW5nYW4gbWVudXJ1bmthbiBuaWxhaSBwYWRhIGBvbWFgIHNlcGVydGkgYmVyaWt1dC4NCg0KYGBge3J9DQpwYXIobWZyb3c9YygyLDIpLCBvbWE9YygyLDIsMiwyKSkNCnBsb3QoeCx5KQ0KcGxvdCh5LHgpDQpoaXN0KHgpDQpoaXN0KHkpDQpgYGANCg0KLSAgIGBwYXIobWZyb3c9YygxLDEpKWAgbWVuZ2VtYmFsaWthbiBrZSBsYXlvdXQgZGVmYXVsdA0KDQojIyBGdW5nc2kgYHNwbGl0LnNjcmVlbmANCg0KLSAgIE1lbmdndW5ha2FuIGZ1bmdzaSBgc3BsaXQuc2NyZWVuKCkg4oCTPiBzcGxpdC5zY3JlZW4oYygyLDIpKWAgc2VwZXJ0aSBwYXIobWZyb3c9YygyLDIpKQ0KLSAgIEJlcnBpbmRhaCBhbnRhciBhcmVhIHBsb3QgbWVuZ2d1bmFrYW4gZnVuZ3NpIGBzY3JlZW4oaSlgDQotICAgRnVuZ3NpIGBjbG9zZS5zY3JlZW4oYWxsPVQpYCBtZW5nZW1iYWxpa2FuIGtlIGRlZmF1bHQNCg0KYGBge3J9DQp4IDwtIHJub3JtKDEwKTsgeTwtIHJub3JtKDEwKQ0Kc3BsaXQuc2NyZWVuKGMoMiwyKSkNCnNjcmVlbigxKQ0KcGxvdCh4PTE6MTAseCkNCnNjcmVlbigyKQ0KcGxvdCh4PTE6MTAseSkNCnNjcmVlbigzKQ0KYm94cGxvdCh4KQ0Kc2NyZWVuKDQpDQpib3hwbG90KHkpDQpjbG9zZS5zY3JlZW4oYWxsPVRSVUUpDQpgYGANCg0KIyMgRnVuZ3NpICdsYXlvdXRgRGVuZ2FuIGZ1bmdzaWBsYXlvdXQoKWB1a3VyYW4gZ3JhZmlrbnlhIGxlYmloIGZsZWtzaWJlbCAoYmVydmFyaWFzaSkgZGliYW5kaW5nIHNldHRpbmcgcGFyYW1ldGVyIGF0YXUgZnVuZ3NpYHNwbGl0LnNjcmVlbigpXGAuDQoNCkxhbmdrYWggcGVydGFtYSBhZGFsYWggbWVtYnVhdCBtYXRyaWtzIHJhbmNhbmdhbiBkZW5nYW4gbmlsYWkgaW50ZWdlciBwb3NpdGlmICh1bnR1ayBhcmVhIGdyYWZpaykgZGFuIDAgdW50dWsgYXJlYSBrb3NvbmcuDQoNCmBgYHtyfQ0KcmFuY2FuZ2FuIDwtIG1hdHJpeChjKDEsMSwzLDEsMSwzLDIsMiw0LDIsMiw0KSwgbnJvdz0zKQ0Kb2JqIDwtIGxheW91dChyYW5jYW5nYW4pDQpsYXlvdXQuc2hvdyhvYmopDQpwbG90KHg9MToxMCx4KQ0KcGxvdCh4PTE6MTAseSkNCmJveHBsb3QoeCxob3Jpem9udGFsID0gVFJVRSkNCmJveHBsb3QoeSxob3Jpem9udGFsID0gVFJVRSkNCmxheW91dCgxKQ0KYGBgDQo=