Bu çalışma dosyasının orjinali Gökberk Can’ın kendi web sayfasında sunulmuştur. Bütün kullanım hakları Creative Commons - CC BY-NC-SA lisansı altındadır. R Markdown Notebook kullanılarak hazırlanmıştır.

R ve Analiz

Bu yazıyı yazmaktaki amacım R kullanarak bilimsel çalışma yapmak isteyen fakat bir sebepten başlayamayanlara aslında sürecin ne kadar kolay olduğunu göstermek. Metin içinde kullanılan bilgileri farklı kaynaklar elde ettim. Paketlerin kullanımını, fonksiyonların içeriğini paketlerde yer alan vinyetlerden okuyarak öğrendim. Buradaki bilgilerin bazılarını Datacamp’de aldığım R kurslardan edindim. Bugüne kadar tamamladığım bütün kursların (career track) isimlerini en sonda yazdım.

Burada bahsi geçen konuların şahsım adına çok zorlaştığı noktalarda Stack Exchange, Stack Overflow ve ücretsiz R sitelerinde yazılanları takip ederek sonuca ulaştım. Hangi sayfa benim için en kolay anlatımı yaptıysa (ben nasıl öğrendiysem), ona atıf yaptım. Kullandığım bütün kaynakları kodlardan önce paylaştım.

Önce hangi kodun ne işe yaradığını yorumlarla yanına yazdım, ancak kopyala-yapıştır ile konsola attığımda çok uğraştırdı. O yüzden daha anlaşılır olması amacıyla kodların altına ekledim.

Buradaki temel anlatımından elde edilecek faydayı büyütmek, farklı boyutlara getirmek tamamiyle sizin çabanızla ilgili. R kullanarak istatistiki analize giriş yapmak isteyenler için faydalı olması dileğiyle.

Haydi başlayalım!

R Paketleri

Burada yapacağımız işlemlere başlamadan önce aşağıdaki R paketlerinin kurulması ve çalıştırılması gerekli. RStudio kullanacağımız için readxl paketi zaten veri aktarımı yapılırken etkinleşeceği için aşağıdaki tabloya eklemedim. Her bir paket için kurulum ve etkinleştirme komutları aşağıdaki tabloda. Kopyala yapıştır yapıp konsola aktarabileceğiniz gibi R alışkanlığınızın artması için tek tek yazmanızı tavsiye ederim.

Paket Adı Neden? Kurulum Etkinleştirme
ggplot2 Güzel grafikler install.packages(“ggplot2”) library(ggplot2)
dplyr Veriseti manipülasyonu install.packages(“dplyr”) library(dplyr)
lmtest Düzeltilmiş standartlar hatalar install.packages(“lmtest”) library(lmtest)
sandwich Düzeltilmiş standartlar hatalar install.packages(“sandwich”) library(sandwich)
Hmisc Korelasyon Matrisi install.packages(“Hmisc”) library(Hmisc)
quantreg Kantil Regresyon install.packages(“quantreg”) library(quantreg)

Kurulum

install.packages("ggplot2")
install.packages("dplyr")
install.packages("lmtest")
install.packages("sandwich")
install.packages("Hmisc")
install.packages("quantreg")

Etkinleştirme

library(ggplot2)
library(dplyr)
library(lmtest)
library(sandwich)
library(Hmisc)
library(quantreg)

Veri seti

MODAVICA 2020’de sunduğum “Effect of Life Cycles on Capital Expenditures: Evidence from Borsa Istanbul” bildirisinde kullandığım veri setinin buradaki anlatıma göre düzenlenmiş hali. Setin yapısı aşağıda sunulmuştur. Veri setimizin ilk üç sütunu tanımsal değerler olduğu için bazı fonksiyonlarda aralıkları kullanacağız.

Değişken Kodu Değişken Adı Değişken Yapısı
ID Birim Tanımsal
FY Yıl Tanımsal
SC Sektör Tanımsal
BD Bağımlı Değişken Sürekli
X1 Bağımsız Sürekli
X2 Kontrol Sürekli
X3 Kontrol Sürekli
X4 Kontrol Kukla
X5 Kontrol Kukla

Veri setinin aktarımı

Öncelikle aşağıdaki veri setini bilgisayarınıza indirin.

Veriseti

Şahsi tercihim RStudio’da bir proje oluşturmanız. Bunu iki sebeple söylüyorum:

  1. .RData dosyasınız sadece burada yaptıklarınızla ilgili olacaktır. Veri setini bozsanız bile başka çalışmalara ait dosyalarınız yerli yerinde duracaktır (deneyim diyelim).
  2. En son aşamada kullandığımız not defteri de açtığınız projenin bir parçası olacağı için komutları hatırlamak daha kolay olacak (bu sitenin hiçbir kazanç amacı yoktur).

RStudio’daki “Import Dataset” butonu ile dosyayı indirdiğiniz konumdan içeri vseti ismiyle aktarın.

Çalışma Planımız

  1. Deskriptif istatistik hesaplayacağız
  1. BD = X1+KD1+KD2+KD3+KD4+KD5 modelini yıl ve birim için kukla değişkenler kullanarak sabit etkiler ile test edeceğiz.
  1. Aynı modeli kantil regresyon ile test edeceğiz.
  1. Bütün elde ettiğimiz sonuçları paylaşılabilir hale getireceğiz.

Deskriptif İstatistikler

Özet İstatistiki

Öncelikle veri setimizde ne neymiş bir bakalım. Gözlemlerimin tanımlarının (ilk üç sütun) herhangi bir istatistiki karşılığı olmadığı için istastiki özetimize eklemiyoruz. summary fonksiyonu içindeki vseti[,4:10] tanımının da amacı ilk üçü istemediğimizi belirtmek. Daha kapsamlı özet istatistikler için bu makaleyi kullanabilirsiniz. Bana bu kadar sıfır yetmez daha fazla isterim diyorsanız da üçüncü komutu çalıştırın.

desk<-summary(vseti[,4:10])
desk
options(digits = 7)

Korelasyon Matrisi

Korelasyon matrisini iki şekilde elde edebiliriz R’da. Birinci yöntem R’ın kendi korelasyon matris fonksiyonu olan “cor” ile yapılabilir ancak bu fonksiyona dair esas sorun ilişkilerin istatistiki anlamlılığı raporlanmaz.

kormat<-cor(vseti[,4:10])
kormat

Peki nedir bu sorunun çözümü? Hmisc paketi. Aşağıdaki komutları çalıştırdığınızda karşınıza gelen korelasyon matrisinde iki kısım olacak. Birincisi değişkenler arası korelasyon, ikincisi korelasyonların istatistiki anlamlılığı.

kormat_pv<-rcorr(as.matrix((vseti[,4:10])))
kormat_pv

Farkların Anlamlığı Testi

Elimizdeki veri setindeki X1 değişkeninde 0.00, 0.25, 0.50, 0.75 ve 1.00 değerlerinden 39’ar adet olmak üzere 195 gözlem var. Hiçbir birim için eksik gözlemimiz yok. X1 değişkeni içindeki grupların Y ortalamaları arasında bir fark olup olmadığını inceleyelim şimdi. Değerleri nasıl gruplayacağız.

X1 Değeri Grup
0.00 1
0.25 2
0.50 3
0.75 4
1.00 5
Grup12 <- vseti %>%
filter(X1 == 0 | X1 == 0.25) %>%
select(X1, BD)
Grup13 <- vseti %>%
filter(X1 == 0 | X1 == 0.5) %>%
select(X1, BD)
Grup14 <- vseti %>%
filter(X1 == 0 | X1 == 0.75) %>%
select(X1, BD)
Grup15 <- vseti %>%
filter(X1 == 0 | X1 == 1) %>%
select(X1, BD)
Grup23 <- vseti %>%
filter(X1 == 0.25 | X1 == 0.5) %>%
select(X1, BD)
Grup24 <- vseti %>%
filter(X1 == 0.25 | X1 == 0.75) %>% 
select(X1, BD)
Grup25 <- vseti %>%
filter(X1 == 0.25 | X1 == 1) %>%
select(X1, BD)
Grup34 <- vseti %>%
filter(X1 == 0.5 | X1 == 0.75) %>%
select(X1, BD)
Grup35 <- vseti %>% 
filter(X1 == 0.5 | X1 == 1) %>%
select(X1, BD)
Grup45 <- vseti %>%
filter(X1 == 0.75 | X1 == 1) %>%
select(X1, BD)

Üstteki komutları kısaca izah etmek isterim. dplyr paketini etkinleştirdiğimiz için %>% operatörü ile bütün komutu ile tek bir satırda yazmak yerine parçalara bölmüş oluyoruz.

Grup12 <- vseti %>%
filter(X1 == 0 | X1 == 0.25) %>%
select(X1, BD)

# Grup12 tablosunu oluştur ve vseti isimli veri setini kullan
# vseti içerisindeki X1 değişkeni için 0 ve 0.25 olan gözlemleri filtrele
# vseti içindeki 0 ve 0.25 olan X1 gözlemlerini için X1 ve BDS değişkenlerini Grup12 tablosuna yerleştir.

Grupları oluşturduğumuza göre anlamlılık testlerimiz yapalım her bir grup için (UC Business Analytics R Programming Guide).

t.test(BD ~ X1, data = Grup12)
t.test(BD ~ X1, data = Grup13)
t.test(BD ~ X1, data = Grup14)
t.test(BD ~ X1, data = Grup15)
t.test(BD ~ X1, data = Grup23)
t.test(BD ~ X1, data = Grup24)
t.test(BD ~ X1, data = Grup25)
t.test(BD ~ X1, data = Grup34)
t.test(BD ~ X1, data = Grup35)
t.test(BD ~ X1, data = Grup45)

Grafiklerin Oluşturulması

Grafikleri oluşturmak için önce her bir grubun ve grupların yıllara göre ortalamasını veri setimize ekleyelim.

vseti<- vseti %>% 
group_by(X1) %>%
mutate(BD_X1_ort=mean(BD))
# vseti kullanarak vseti'ne işlemleri yap
# vseti'ni X1 kullanarak grupla 
# vseti'nin sonuna BD'nin X1 gruplarına göre ortalamasını ekle
vseti <- vseti %>%
group_by(X1, FY) %>% 
mutate(BD_X1_FY_ort=mean(BD)) 
# vseti kullanarak vseti'ne işlemleri yap 
# vseti'ni X1 ve FY kullanarak grupla 
# vseti'nin sonuna BD'nin X1-FY gruplarına göre ortalamasını ekle

Şimdi grafikleri çıkartabiliriz. Önce toplamdan gidelim (ggplot2 ve ggplot2 cheat sheet)

ggplot(vseti, aes(x=X1, y=BD_X1_ort, fill=X1))+
geom_point(size=3,aes(colour=X1))+
labs(title="Grafigin Ana Basligi", x ="X1 Gruplari", y = "Ortalama Bagimli Degisken")+
theme(plot.title = element_text(hjust = 0.5))+
scale_y_continuous(breaks = seq(0,0.1,0.01))

#vseti'ni kullanarak BD~X1 grafiğini oluştur.
#noktaları göster, nokta büyüklüğü 3 olsun, X1'e göre renklendir
#eksenleri ve grafiğin adını yaz
#grafiğin adını ortala
#y eksenindeki ara değerleri ayarla

Şimdi yıllara göre grafikleri çıkartalım

ggplot(vseti, aes(x=FY, y=BD_X1_FY_ort, fill=X1))+
geom_line(aes(colour=X1, group=X1))+
geom_point(size=1,aes(colour=X1))+
labs(title="Grafigin Ana Basligi", x ="X1 Gruplari", y = "Yillara Gore Ortalama Bagimli Degisken")+
theme(plot.title = element_text(hjust = 0.5))+
scale_y_continuous(breaks = seq(0,0.1,0.01))+
scale_x_continuous(breaks = seq(2015,2017,1))
#vseti'ni kullanarak BD~FY grafiğini oluştur.
#çizgi grafik oluştur
#noktaları göster, nokta büyüklüğü 3 olsun, X1'e göre renklendir
#eksenleri ve grafiğin adını yaz
#grafiğin adını ortala
#y eksenindeki ara değerleri ayarla

Regresyon Modeli

Çalışmamızdaki temel varsayımımız (hipotez) aşağıdaki gibidir:

H0: X1 BD’yi etkilememektedir

H1: X1 BD’yi etkilemektedir (Beklenen işaret: )

Bu varsayımı test etmek modelimizi en küçük kareler regresyonu olarak kaydedelim. Modele birim ve yıl sayesinde sabit etkileri de test etmiş oluyoruz. Açıkçası birim ve yıl olmadan daha güzel sonuçlar elde edebilirsiniz ancak iyi bir dergide doğrudan kabul görmesi mümkün olmayacak. Modelin sonuçlarını görmek için ikinci komutu çalıştırın.

model<-lm(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti)
summary(model)
#factor() fonksiyonunun amacı her bir birim koduna ve yıla kukla değişken vermek yerine hepsini çalıştırmak. R her bir gruptan bir tanesini analize dahil etmeyecek

Standart Hatalar Düzeltilmiş Model

Doğrusal ile test ettiğimiz modelde bir sorun var. Modelin standart hatalarını birim ve yıllara göre kümeleyerek sonuçların istatistiki olarak sağlamlığını yapacağız.

model_SE<-coeftest(model,vcov=vcovHC(model,type="HC1",cluster=c(PDS$ID,PDS$FY)))

Modelin kantil regresyon ile test edilmesi

Varsayalım ki doğrusal regresyon için gerekli şartları sağlayamadık (Baltagi, 2011 ve modelimizi parametrik olmayan regresyon ile test etmemiz gerekiyor. Koenker ve Basset (1978) tarafından geliştirilen kantil regresyon bu amaçla kullanabileceğiniz yöntemlerden biri. Analiz için gereken paket bizzat regresyonu geliştiren Koenker’e ait. Modeli bir kere çalıştırmak ve kaydetmek yetmeyecek. Ne yapacağız peki? Toplamda 7 kere çalıştırmış olacağız. rq fonksiyonu içindeki tau hangi kantil değerinin test edileceğini göstermektedir.

model_0.05<-rq(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti, tau=0.05)
model_0.10<-rq(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti, tau=0.10)
model_0.25<-rq(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti, tau=0.25)
model_0.50<-rq(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti, tau=0.50)
model_0.75<-rq(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti, tau=0.75)
model_0.90<-rq(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti, tau=0.90)
model_0.95<-rq(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti, tau=0.95)

Kantil regresyon ve bootstrapping

En küçük kareler yönteminde standart hataları birim/yıl olarak kümeleyerek modelin sağlamlığını yapmıştık. Kantil regresyonda neden böyle bir şey yapmıyoruz? Kantil regresyonda standart hataların kümelenmesi için sonuçların yeniden önyüklenmesi gerekiyor (Hao ve Naiman, 2007). Bu işlem esas modelde yaptığımıza göre daha kolay.

summary.rq(model_0.05,se="boot")
summary.rq(model_0.10,se="boot")
summary.rq(model_0.25,se="boot")
summary.rq(model_0.50,se="boot")
summary.rq(model_0.75,se="boot")
summary.rq(model_0.90,se="boot")
summary.rq(model_0.95,se="boot")

Kantil regresyon için R2 hesaplamak

Koenker diyor ki

I don’t much like R1, or R2 for that matter, so it isn’t likely to be automatically provided in quantreg any time soon. (R1 veya R2’den çok hoşlanmıyorum, bu yüzden de yakın bir zamanda quantreg’de otomatik olarak yer alması olası değil (Çeviri: GC)

Peki siz bu modellerin altında R2 eklemek istiyorsanız ne yapmanız lazım? (Çözüm için Koenker ve Machado, 1999. R-squared in quantile regression, Dimitriy V. Masterov (https://stats.stackexchange.com/users/7071/dimitriy-v-masterov), R-squared in quantile regression, URL (version: 2014-12-17): https://stats.stackexchange.com/q/129251)

fit0 <- rq(BD~1,tau=0.95,data=vseti)
fit1<-rq(BD~X1+KD1+KD2+KD3+KD4+KD5+factor(ID)+factor(FY),data=vseti, tau=0.05)
rho <- function(u,tau=.5)u*(tau - (u < 0))
R1 <- 1 - fit1$rho/fit0$rho
R1

Bu formülü her bir kantil noktası için tek tek (0.05, 0.10, 0.25, 0.50, 0.75, 0.90 ve 0.95) hesaplamanız gerekiyor.

R Notebook

Sizinle paylaştığım kodları çalışmanızın (ödevler de dahil olmak üzere) analizine uygun olarak değiştirebilir, sonuçları tek bir dosyada raporlayabilirsiniz. Kodların ne işe yaradığını gösteremeyen bir not uygulaması yerine gerçek bir çalışma defteri isterseniz R Notebook işinizi görecektir. R Markdown kullanarak metni istediğiniz gibi biçimlendirebilirsiniz. Kodları R Notebook’ta nasıl kullanacaksınız?

desk<-summary(vseti[,4:10])
desk

Yukarıdaki kod yığını (chunk) hem sizin aldığınız notları saklayacak hem de bu kodun ne anlama geldiğini merak ettiğinizde yığının en sağındaki oynat tuşuna basarak (“Run Current Chunk”) sonuçları da görmenizi sağlayacak.

Datacamp Career Track

Statistician with R - Tamamlandı

Quantitative Analyst with R - Devam ediyor

LS0tCnRpdGxlOiAiUidkYSBUZW1lbCBWZXJpIEFuYWxpemkiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKQnUgw6dhbMSxxZ9tYSBkb3N5YXPEsW7EsW4gW29yamluYWxpXShodHRwOi8vd3d3Lmdva2JlcmtjYW4uY29tLz9wPTE4OTcpIEfDtmtiZXJrIENhbifEsW4ga2VuZGkgd2ViIHNheWZhc8SxbmRhIHN1bnVsbXXFn3R1ci4gQsO8dMO8biBrdWxsYW7EsW0gaGFrbGFyxLEgW0NyZWF0aXZlIENvbW1vbnMgLSBDQyBCWS1OQy1TQSBsaXNhbnPEsV0oaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLXNhLzQuMC8pIGFsdMSxbmRhZMSxci4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rIGt1bGxhbsSxbGFyYWsgaGF6xLFybGFubcSxxZ90xLFyLiAKCiMgUiB2ZSBBbmFsaXoKQnUgeWF6xLF5xLEgeWF6bWFrdGFraSBhbWFjxLFtIFIga3VsbGFuYXJhayBiaWxpbXNlbCDDp2FsxLHFn21hIHlhcG1hayBpc3RleWVuIGZha2F0IGJpciBzZWJlcHRlbiBiYcWfbGF5YW1heWFubGFyYSBhc2zEsW5kYSBzw7xyZWNpbiBuZSBrYWRhciBrb2xheSBvbGR1xJ91bnUgZ8O2c3Rlcm1lay4gTWV0aW4gacOnaW5kZSBrdWxsYW7EsWxhbiBiaWxnaWxlcmkgZmFya2zEsSBrYXluYWtsYXIgZWxkZSBldHRpbS4gUGFrZXRsZXJpbiBrdWxsYW7EsW3EsW7EsSwgZm9ua3NpeW9ubGFyxLFuIGnDp2VyacSfaW5pIHBha2V0bGVyZGUgeWVyIGFsYW4gdmlueWV0bGVyZGVuIG9rdXlhcmFrIMO2xJ9yZW5kaW0uIEJ1cmFkYWtpIGJpbGdpbGVyaW4gYmF6xLFsYXLEsW7EsSBEYXRhY2FtcOKAmWRlIGFsZMSxxJ/EsW0gUiBrdXJzbGFyZGFuIGVkaW5kaW0uIEJ1Z8O8bmUga2FkYXIgdGFtYW1sYWTEscSfxLFtIGLDvHTDvG4ga3Vyc2xhcsSxbiAoY2FyZWVyIHRyYWNrKSBpc2ltbGVyaW5pIGVuIHNvbmRhIHlhemTEsW0uCgpCdXJhZGEgYmFoc2kgZ2XDp2VuIGtvbnVsYXLEsW4gxZ9haHPEsW0gYWTEsW5hIMOnb2sgem9ybGHFn3TEscSfxLEgbm9rdGFsYXJkYSBTdGFjayBFeGNoYW5nZSwgU3RhY2sgT3ZlcmZsb3cgdmUgw7xjcmV0c2l6IFIgc2l0ZWxlcmluZGUgeWF6xLFsYW5sYXLEsSB0YWtpcCBlZGVyZWsgc29udWNhIHVsYcWfdMSxbS4gSGFuZ2kgc2F5ZmEgYmVuaW0gacOnaW4gZW4ga29sYXkgYW5sYXTEsW3EsSB5YXB0xLF5c2EgKGJlbiBuYXPEsWwgw7bEn3JlbmRpeXNlbSksIG9uYSBhdMSxZiB5YXB0xLFtLiBLdWxsYW5kxLHEn8SxbSBiw7x0w7xuIGtheW5ha2xhcsSxIGtvZGxhcmRhbiDDtm5jZSBwYXlsYcWfdMSxbS4KCsOWbmNlIGhhbmdpIGtvZHVuIG5lIGnFn2UgeWFyYWTEscSfxLFuxLEgeW9ydW1sYXJsYSB5YW7EsW5hIHlhemTEsW0sIGFuY2FrIGtvcHlhbGEteWFwxLHFn3TEsXIgaWxlIGtvbnNvbGEgYXR0xLHEn8SxbWRhIMOnb2sgdcSfcmHFn3TEsXJkxLEuIE8gecO8emRlbiBkYWhhIGFubGHFn8SxbMSxciBvbG1hc8SxIGFtYWPEsXlsYSBrb2RsYXLEsW4gYWx0xLFuYSBla2xlZGltLgoKQnVyYWRha2kgdGVtZWwgYW5sYXTEsW3EsW5kYW4gZWxkZSBlZGlsZWNlayBmYXlkYXnEsSBiw7x5w7x0bWVrLCBmYXJrbMSxIGJveXV0bGFyYSBnZXRpcm1layB0YW1hbWl5bGUgc2l6aW4gw6dhYmFuxLF6bGEgaWxnaWxpLiBSIGt1bGxhbmFyYWsgaXN0YXRpc3Rpa2kgYW5hbGl6ZSBnaXJpxZ8geWFwbWFrIGlzdGV5ZW5sZXIgacOnaW4gZmF5ZGFsxLEgb2xtYXPEsSBkaWxlxJ9peWxlLgoKSGF5ZGkgYmHFn2xheWFsxLFtIQoKIyBSIFBha2V0bGVyaQpCdXJhZGEgeWFwYWNhxJ/EsW3EsXogacWfbGVtbGVyZSBiYcWfbGFtYWRhbiDDtm5jZSBhxZ9hxJ/EsWRha2kgUiBwYWtldGxlcmluaW4ga3VydWxtYXPEsSB2ZSDDp2FsxLHFn3TEsXLEsWxtYXPEsSBnZXJla2xpLiBSU3R1ZGlvIGt1bGxhbmFjYcSfxLFtxLF6IGnDp2luIHJlYWR4bCBwYWtldGkgemF0ZW4gdmVyaSBha3RhcsSxbcSxIHlhcMSxbMSxcmtlbiBldGtpbmxlxZ9lY2XEn2kgacOnaW4gYcWfYcSfxLFkYWtpIHRhYmxveWEgZWtsZW1lZGltLiBIZXIgYmlyIHBha2V0IGnDp2luIGt1cnVsdW0gdmUgZXRraW5sZcWfdGlybWUga29tdXRsYXLEsSBhxZ9hxJ/EsWRha2kgdGFibG9kYS4gS29weWFsYSB5YXDEscWfdMSxciB5YXDEsXAga29uc29sYSBha3RhcmFiaWxlY2XEn2luaXogZ2liaSBSIGFsxLHFn2thbmzEscSfxLFuxLF6xLFuIGFydG1hc8SxIGnDp2luIHRlayB0ZWsgeWF6bWFuxLF6xLEgdGF2c2l5ZSBlZGVyaW0uCgp8UGFrZXQgQWTEsXxOZWRlbj98S3VydWx1bXxFdGtpbmxlxZ90aXJtZXwKfC0tLXwtLS18LS0tfC0tLXwKfGdncGxvdDJ8R8O8emVsIGdyYWZpa2xlcnxpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIil8bGlicmFyeShnZ3Bsb3QyKXwKfGRwbHlyfFZlcmlzZXRpIG1hbmlww7xsYXN5b251fGluc3RhbGwucGFja2FnZXMoImRwbHlyIil8bGlicmFyeShkcGx5cil8CnxsbXRlc3R8RMO8emVsdGlsbWnFnyBzdGFuZGFydGxhciBoYXRhbGFyfGluc3RhbGwucGFja2FnZXMoImxtdGVzdCIpfGxpYnJhcnkobG10ZXN0KXwKfHNhbmR3aWNofETDvHplbHRpbG1pxZ8gc3RhbmRhcnRsYXIgaGF0YWxhcnxpbnN0YWxsLnBhY2thZ2VzKCJzYW5kd2ljaCIpfGxpYnJhcnkoc2FuZHdpY2gpfAp8SG1pc2N8S29yZWxhc3lvbiBNYXRyaXNpfGluc3RhbGwucGFja2FnZXMoIkhtaXNjIil8bGlicmFyeShIbWlzYyl8CnxxdWFudHJlZ3xLYW50aWwgUmVncmVzeW9ufGluc3RhbGwucGFja2FnZXMoInF1YW50cmVnIil8bGlicmFyeShxdWFudHJlZyl8CgojIyBLdXJ1bHVtCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQppbnN0YWxsLnBhY2thZ2VzKCJsbXRlc3QiKQppbnN0YWxsLnBhY2thZ2VzKCJzYW5kd2ljaCIpCmluc3RhbGwucGFja2FnZXMoIkhtaXNjIikKaW5zdGFsbC5wYWNrYWdlcygicXVhbnRyZWciKQpgYGAKCiMjIEV0a2lubGXFn3Rpcm1lCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobG10ZXN0KQpsaWJyYXJ5KHNhbmR3aWNoKQpsaWJyYXJ5KEhtaXNjKQpsaWJyYXJ5KHF1YW50cmVnKQpgYGAKCiMgVmVyaSBzZXRpCk1PREFWSUNBIDIwMjDigJlkZSBzdW5kdcSfdW0g4oCcRWZmZWN0IG9mIExpZmUgQ3ljbGVzIG9uIENhcGl0YWwgRXhwZW5kaXR1cmVzOiBFdmlkZW5jZSBmcm9tIEJvcnNhIElzdGFuYnVs4oCdIGJpbGRpcmlzaW5kZSBrdWxsYW5kxLHEn8SxbSB2ZXJpIHNldGluaW4gYnVyYWRha2kgYW5sYXTEsW1hIGfDtnJlIGTDvHplbmxlbm1pxZ8gaGFsaS4gU2V0aW4geWFwxLFzxLEgYcWfYcSfxLFkYSBzdW51bG11xZ90dXIuIFZlcmkgc2V0aW1pemluIGlsayDDvMOnIHPDvHR1bnUgdGFuxLFtc2FsIGRlxJ9lcmxlciBvbGR1xJ91IGnDp2luIGJhesSxIGZvbmtzaXlvbmxhcmRhIGFyYWzEsWtsYXLEsSBrdWxsYW5hY2HEn8Sxei4KCnxEZcSfacWfa2VuIEtvZHV8RGXEn2nFn2tlbiBBZMSxfERlxJ9pxZ9rZW4gWWFwxLFzxLF8CnwtLS18LS0tfC0tLXwKfElEfEJpcmltfFRhbsSxbXNhbHwKfEZZfFnEsWx8VGFuxLFtc2FsfAp8U0N8U2VrdMO2cnxUYW7EsW1zYWx8CnxCRHxCYcSfxLFtbMSxIERlxJ9pxZ9rZW58U8O8cmVrbGl8CnxYMXxCYcSfxLFtc8SxenxTw7xyZWtsaXwKfFgyfEtvbnRyb2x8U8O8cmVrbGl8CnxYM3xLb250cm9sfFPDvHJla2xpfAp8WDR8S29udHJvbHxLdWtsYXwKfFg1fEtvbnRyb2x8S3VrbGF8CgojIyBWZXJpIHNldGluaW4gYWt0YXLEsW3EsQrDlm5jZWxpa2xlIGHFn2HEn8SxZGFraSB2ZXJpIHNldGluaSBiaWxnaXNheWFyxLFuxLF6YSBpbmRpcmluLgoKW1ZlcmlzZXRpXShodHRwczovL2JpdC5seS8zMlBhZ1NTKQoKxZ5haHNpIHRlcmNpaGltIFJTdHVkaW/igJlkYSBiaXIgcHJvamUgb2x1xZ90dXJtYW7EsXouIEJ1bnUgaWtpIHNlYmVwbGUgc8O2eWzDvHlvcnVtOgoKMS4gLlJEYXRhIGRvc3lhc8SxbsSxeiBzYWRlY2UgYnVyYWRhIHlhcHTEsWtsYXLEsW7EsXpsYSBpbGdpbGkgb2xhY2FrdMSxci4gVmVyaSBzZXRpbmkgYm96c2FuxLF6IGJpbGUgYmHFn2thIMOnYWzEscWfbWFsYXJhIGFpdCBkb3N5YWxhcsSxbsSxeiB5ZXJsaSB5ZXJpbmRlIGR1cmFjYWt0xLFyIChkZW5leWltIGRpeWVsaW0pLgoyLiBFbiBzb24gYcWfYW1hZGEga3VsbGFuZMSxxJ/EsW3EsXogbm90IGRlZnRlcmkgZGUgYcOndMSxxJ/EsW7EsXogcHJvamVuaW4gYmlyIHBhcsOnYXPEsSBvbGFjYcSfxLEgacOnaW4ga29tdXRsYXLEsSBoYXTEsXJsYW1hayBkYWhhIGtvbGF5IG9sYWNhayAoYnUgc2l0ZW5pbiBoacOnYmlyIGthemFuw6cgYW1hY8SxIHlva3R1cikuCgpSU3R1ZGlv4oCZZGFraSDigJxJbXBvcnQgRGF0YXNldOKAnSBidXRvbnUgaWxlIGRvc3lhecSxIGluZGlyZGnEn2luaXoga29udW1kYW4gacOnZXJpIHZzZXRpIGlzbWl5bGUgYWt0YXLEsW4uCgojIMOHYWzEscWfbWEgUGxhbsSxbcSxegoxLiBEZXNrcmlwdGlmIGlzdGF0aXN0aWsgaGVzYXBsYXlhY2HEn8SxegotIMOWemV0IGlzdGF0aXN0aWtrbGVyaSByYXBvcmxheWFjYcSfxLF6LgotIEJELCBYMSwgS0QxLEtEMixLRDMsS0Q0IHZlIEtENSBpw6dpbiBrb3JlbGFzeW9uIG1hdHJpc2kgaGF6xLFybGF5YWNhxJ/EsXouCi0gWDEgZGXEn2nFn2tlbmluaSBiYXogYWzEsXAgZ3J1cGxhciBpw6dpbiBmYXJrbGFyIHRlc3RpIHlhcGFjYcSfxLF6Ci0gR3J1cGxhcsSxIGt1bGxhbmFyYWsgdG9wbGFtIHZlIHnEsWxsYXJhIGfDtnJlIGdyYWZpa2xlciBoYXrEsXJsYXlhY2HEn8Sxei4KMi4gQkQgPSBYMStLRDErS0QyK0tEMytLRDQrS0Q1IG1vZGVsaW5pIHnEsWwgdmUgYmlyaW0gacOnaW4ga3VrbGEgZGXEn2nFn2tlbmxlciBrdWxsYW5hcmFrIHNhYml0IGV0a2lsZXIgaWxlIHRlc3QgZWRlY2XEn2l6LgotIE1vZGVsaSBzdGFuZGFydCBoYXRhbGFyxLFuIGTDvHplbHRlcmVrIHJhcG9ybGF5YWNhxJ/EsXouCjMuIEF5bsSxIG1vZGVsaSBrYW50aWwgcmVncmVzeW9uIGlsZSB0ZXN0IGVkZWNlxJ9pei4KLSBLYW50aWwgcmVncmVzeW9uIG1vZGVsaW5lIGJvb3RzdHJhcHBpbmcgeWFwYWNhxJ/EsXouCi0gS2FudGlsIHJlZ3Jlc3lvbiBtb2RlbGluZGUgUjIgaGVzYXBsYXlhY2HEn8Sxei4KLSBLYW50aWwgUmVncmVzeW9uIG1vZGVsaW5pIHRvcGxhbSBvbGFyYWsgcmFwb3JsYXlhY2HEn8Sxei4KNC4gQsO8dMO8biBlbGRlIGV0dGnEn2ltaXogc29udcOnbGFyxLEgcGF5bGHFn8SxbGFiaWxpciBoYWxlIGdldGlyZWNlxJ9pei4KCiMgRGVza3JpcHRpZiDEsHN0YXRpc3Rpa2xlcgoKIyMgw5Z6ZXQgxLBzdGF0aXN0aWtpCsOWbmNlbGlrbGUgdmVyaSBzZXRpbWl6ZGUgbmUgbmV5bWnFnyBiaXIgYmFrYWzEsW0uIEfDtnpsZW1sZXJpbWluIHRhbsSxbWxhcsSxbsSxbiAoaWxrIMO8w6cgc8O8dHVuKSBoZXJoYW5naSBiaXIgaXN0YXRpc3Rpa2kga2FyxZ/EsWzEscSfxLEgb2xtYWTEscSfxLEgacOnaW4gaXN0YXN0aWtpIMO2emV0aW1pemUgZWtsZW1peW9ydXouIHN1bW1hcnkgZm9ua3NpeW9udSBpw6dpbmRla2kgdnNldGlbLDQ6MTBdIHRhbsSxbcSxbsSxbiBkYSBhbWFjxLEgaWxrIMO8w6fDvCBpc3RlbWVkacSfaW1pemkgYmVsaXJ0bWVrLiBEYWhhIGthcHNhbWzEsSDDtnpldCBpc3RhdGlzdGlrbGVyIGnDp2luIFtidSBtYWthbGV5aV0oaHR0cHM6Ly9zdXphbi5yYmluZC5pby8yMDE4LzA0L2RwbHlyLXR1dG9yaWFsLTQvKSBrdWxsYW5hYmlsaXJzaW5pei4gQmFuYSBidSBrYWRhciBzxLFmxLFyIHlldG1leiBkYWhhIGZhemxhIGlzdGVyaW0gZGl5b3JzYW7EsXogZGEgw7zDp8O8bmPDvCBrb211dHUgw6dhbMSxxZ90xLFyxLFuLgoKYGBge3J9CmRlc2s8LXN1bW1hcnkodnNldGlbLDQ6MTBdKQpkZXNrCm9wdGlvbnMoZGlnaXRzID0gNykKYGBgCgojIyBLb3JlbGFzeW9uIE1hdHJpc2kKS29yZWxhc3lvbiBtYXRyaXNpbmkgaWtpIMWfZWtpbGRlIGVsZGUgZWRlYmlsaXJpeiBS4oCZZGEuIEJpcmluY2kgecO2bnRlbSBS4oCZxLFuIGtlbmRpIGtvcmVsYXN5b24gbWF0cmlzIGZvbmtzaXlvbnUgb2xhbiDigJxjb3LigJ0gaWxlIHlhcMSxbGFiaWxpciBhbmNhayBidSBmb25rc2l5b25hIGRhaXIgZXNhcyBzb3J1biBpbGnFn2tpbGVyaW4gaXN0YXRpc3Rpa2kgYW5sYW1sxLFsxLHEn8SxIHJhcG9ybGFubWF6LgoKYGBge3J9Cmtvcm1hdDwtY29yKHZzZXRpWyw0OjEwXSkKa29ybWF0CmBgYAoKUGVraSBuZWRpciBidSBzb3J1bnVuIMOnw7Z6w7xtw7w/IEhtaXNjIHBha2V0aS4gQcWfYcSfxLFkYWtpIGtvbXV0bGFyxLEgw6dhbMSxxZ90xLFyZMSxxJ/EsW7EsXpkYSBrYXLFn8SxbsSxemEgZ2VsZW4ga29yZWxhc3lvbiBtYXRyaXNpbmRlIGlraSBrxLFzxLFtIG9sYWNhay4gQmlyaW5jaXNpIGRlxJ9pxZ9rZW5sZXIgYXJhc8SxIGtvcmVsYXN5b24sIGlraW5jaXNpIGtvcmVsYXN5b25sYXLEsW4gaXN0YXRpc3Rpa2kgYW5sYW1sxLFsxLHEn8SxLgpgYGB7cn0Ka29ybWF0X3B2PC1yY29ycihhcy5tYXRyaXgoKHZzZXRpWyw0OjEwXSkpKQprb3JtYXRfcHYKYGBgCgojIyBGYXJrbGFyxLFuIEFubGFtbMSxxJ/EsSBUZXN0aQpFbGltaXpkZWtpIHZlcmkgc2V0aW5kZWtpIFgxIGRlxJ9pxZ9rZW5pbmRlIDAuMDAsIDAuMjUsIDAuNTAsIDAuNzUgdmUgMS4wMCBkZcSfZXJsZXJpbmRlbiAzOeKAmWFyIGFkZXQgb2xtYWsgw7x6ZXJlIDE5NSBnw7Z6bGVtIHZhci4gSGnDp2JpciBiaXJpbSBpw6dpbiBla3NpayBnw7Z6bGVtaW1peiB5b2suIFgxIGRlxJ9pxZ9rZW5pIGnDp2luZGVraSBncnVwbGFyxLFuIFkgb3J0YWxhbWFsYXLEsSBhcmFzxLFuZGEgYmlyIGZhcmsgb2x1cCBvbG1hZMSxxJ/EsW7EsSBpbmNlbGV5ZWxpbSDFn2ltZGkuIERlxJ9lcmxlcmkgbmFzxLFsIGdydXBsYXlhY2HEn8Sxei4KCnxYMSBEZcSfZXJpfEdydXB8CnwtLS18LS0tfAp8MC4wMHwxfAp8MC4yNXwyfAp8MC41MHwzfAp8MC43NXw0fAp8MS4wMHw1fAoKYGBge3J9CkdydXAxMiA8LSB2c2V0aSAlPiUKZmlsdGVyKFgxID09IDAgfCBYMSA9PSAwLjI1KSAlPiUKc2VsZWN0KFgxLCBCRCkKR3J1cDEzIDwtIHZzZXRpICU+JQpmaWx0ZXIoWDEgPT0gMCB8IFgxID09IDAuNSkgJT4lCnNlbGVjdChYMSwgQkQpCkdydXAxNCA8LSB2c2V0aSAlPiUKZmlsdGVyKFgxID09IDAgfCBYMSA9PSAwLjc1KSAlPiUKc2VsZWN0KFgxLCBCRCkKR3J1cDE1IDwtIHZzZXRpICU+JQpmaWx0ZXIoWDEgPT0gMCB8IFgxID09IDEpICU+JQpzZWxlY3QoWDEsIEJEKQpHcnVwMjMgPC0gdnNldGkgJT4lCmZpbHRlcihYMSA9PSAwLjI1IHwgWDEgPT0gMC41KSAlPiUKc2VsZWN0KFgxLCBCRCkKR3J1cDI0IDwtIHZzZXRpICU+JQpmaWx0ZXIoWDEgPT0gMC4yNSB8IFgxID09IDAuNzUpICU+JSAKc2VsZWN0KFgxLCBCRCkKR3J1cDI1IDwtIHZzZXRpICU+JQpmaWx0ZXIoWDEgPT0gMC4yNSB8IFgxID09IDEpICU+JQpzZWxlY3QoWDEsIEJEKQpHcnVwMzQgPC0gdnNldGkgJT4lCmZpbHRlcihYMSA9PSAwLjUgfCBYMSA9PSAwLjc1KSAlPiUKc2VsZWN0KFgxLCBCRCkKR3J1cDM1IDwtIHZzZXRpICU+JSAKZmlsdGVyKFgxID09IDAuNSB8IFgxID09IDEpICU+JQpzZWxlY3QoWDEsIEJEKQpHcnVwNDUgPC0gdnNldGkgJT4lCmZpbHRlcihYMSA9PSAwLjc1IHwgWDEgPT0gMSkgJT4lCnNlbGVjdChYMSwgQkQpCmBgYArDnHN0dGVraSBrb211dGxhcsSxIGvEsXNhY2EgaXphaCBldG1layBpc3RlcmltLiBkcGx5ciBwYWtldGluaSBldGtpbmxlxZ90aXJkacSfaW1peiBpw6dpbiAlPiUgb3BlcmF0w7Zyw7wgaWxlIGLDvHTDvG4ga29tdXR1IGlsZSB0ZWsgYmlyIHNhdMSxcmRhIHlhem1hayB5ZXJpbmUgcGFyw6dhbGFyYSBiw7ZsbcO8xZ8gb2x1eW9ydXouCgpgYGB7cn0KR3J1cDEyIDwtIHZzZXRpICU+JQpmaWx0ZXIoWDEgPT0gMCB8IFgxID09IDAuMjUpICU+JQpzZWxlY3QoWDEsIEJEKQoKIyBHcnVwMTIgdGFibG9zdW51IG9sdcWfdHVyIHZlIHZzZXRpIGlzaW1saSB2ZXJpIHNldGluaSBrdWxsYW4KIyB2c2V0aSBpw6dlcmlzaW5kZWtpIFgxIGRlxJ9pxZ9rZW5pIGnDp2luIDAgdmUgMC4yNSBvbGFuIGfDtnpsZW1sZXJpIGZpbHRyZWxlCiMgdnNldGkgacOnaW5kZWtpIDAgdmUgMC4yNSBvbGFuIFgxIGfDtnpsZW1sZXJpbmkgacOnaW4gWDEgdmUgQkRTIGRlxJ9pxZ9rZW5sZXJpbmkgR3J1cDEyIHRhYmxvc3VuYSB5ZXJsZcWfdGlyLgpgYGAKCkdydXBsYXLEsSBvbHXFn3R1cmR1xJ91bXV6YSBnw7ZyZSBhbmxhbWzEsWzEsWsgdGVzdGxlcmltaXogeWFwYWzEsW0gaGVyIGJpciBncnVwIGnDp2luIChbVUMgQnVzaW5lc3MgQW5hbHl0aWNzIFIgUHJvZ3JhbW1pbmcgR3VpZGVdKCBodHRwczovL3VjLXIuZ2l0aHViLmlvL3RfdGVzdCkpLgpgYGB7cn0KdC50ZXN0KEJEIH4gWDEsIGRhdGEgPSBHcnVwMTIpCnQudGVzdChCRCB+IFgxLCBkYXRhID0gR3J1cDEzKQp0LnRlc3QoQkQgfiBYMSwgZGF0YSA9IEdydXAxNCkKdC50ZXN0KEJEIH4gWDEsIGRhdGEgPSBHcnVwMTUpCnQudGVzdChCRCB+IFgxLCBkYXRhID0gR3J1cDIzKQp0LnRlc3QoQkQgfiBYMSwgZGF0YSA9IEdydXAyNCkKdC50ZXN0KEJEIH4gWDEsIGRhdGEgPSBHcnVwMjUpCnQudGVzdChCRCB+IFgxLCBkYXRhID0gR3J1cDM0KQp0LnRlc3QoQkQgfiBYMSwgZGF0YSA9IEdydXAzNSkKdC50ZXN0KEJEIH4gWDEsIGRhdGEgPSBHcnVwNDUpCmBgYAoKIyMgR3JhZmlrbGVyaW4gT2x1xZ90dXJ1bG1hc8SxCkdyYWZpa2xlcmkgb2x1xZ90dXJtYWsgacOnaW4gw7ZuY2UgaGVyIGJpciBncnVidW4gdmUgZ3J1cGxhcsSxbiB5xLFsbGFyYSBnw7ZyZSBvcnRhbGFtYXPEsW7EsSB2ZXJpIHNldGltaXplIGVrbGV5ZWxpbS4KYGBge3J9CnZzZXRpPC0gdnNldGkgJT4lIApncm91cF9ieShYMSkgJT4lCm11dGF0ZShCRF9YMV9vcnQ9bWVhbihCRCkpCiMgdnNldGkga3VsbGFuYXJhayB2c2V0aSduZSBpxZ9sZW1sZXJpIHlhcAojIHZzZXRpJ25pIFgxIGt1bGxhbmFyYWsgZ3J1cGxhIAojIHZzZXRpJ25pbiBzb251bmEgQkQnbmluIFgxIGdydXBsYXLEsW5hIGfDtnJlIG9ydGFsYW1hc8SxbsSxIGVrbGUKdnNldGkgPC0gdnNldGkgJT4lCmdyb3VwX2J5KFgxLCBGWSkgJT4lIAptdXRhdGUoQkRfWDFfRllfb3J0PW1lYW4oQkQpKSAKIyB2c2V0aSBrdWxsYW5hcmFrIHZzZXRpJ25lIGnFn2xlbWxlcmkgeWFwIAojIHZzZXRpJ25pIFgxIHZlIEZZIGt1bGxhbmFyYWsgZ3J1cGxhIAojIHZzZXRpJ25pbiBzb251bmEgQkQnbmluIFgxLUZZIGdydXBsYXLEsW5hIGfDtnJlIG9ydGFsYW1hc8SxbsSxIGVrbGUKYGBgCsWeaW1kaSBncmFmaWtsZXJpIMOnxLFrYXJ0YWJpbGlyaXouIMOWbmNlIHRvcGxhbWRhbiBnaWRlbGltIChbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKSB2ZSBbZ2dwbG90MiBjaGVhdCBzaGVldF0oaHR0cHM6Ly9yc3R1ZGlvLmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxNS8wMy9nZ3Bsb3QyLWNoZWF0c2hlZXQucGRmKSkKCmBgYHtyfQpnZ3Bsb3QodnNldGksIGFlcyh4PVgxLCB5PUJEX1gxX29ydCwgZmlsbD1YMSkpKwpnZW9tX3BvaW50KHNpemU9MyxhZXMoY29sb3VyPVgxKSkrCmxhYnModGl0bGU9IkdyYWZpZ2luIEFuYSBCYXNsaWdpIiwgeCA9IlgxIEdydXBsYXJpIiwgeSA9ICJPcnRhbGFtYSBCYWdpbWxpIERlZ2lza2VuIikrCnRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSsKc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDAuMSwwLjAxKSkKCiN2c2V0aSduaSBrdWxsYW5hcmFrIEJEflgxIGdyYWZpxJ9pbmkgb2x1xZ90dXIuCiNub2t0YWxhcsSxIGfDtnN0ZXIsIG5va3RhIGLDvHnDvGtsw7zEn8O8IDMgb2xzdW4sIFgxJ2UgZ8O2cmUgcmVua2xlbmRpcgojZWtzZW5sZXJpIHZlIGdyYWZpxJ9pbiBhZMSxbsSxIHlhegojZ3JhZmnEn2luIGFkxLFuxLEgb3J0YWxhCiN5IGVrc2VuaW5kZWtpIGFyYSBkZcSfZXJsZXJpIGF5YXJsYQpgYGAKxZ5pbWRpIHnEsWxsYXJhIGfDtnJlIGdyYWZpa2xlcmkgw6fEsWthcnRhbMSxbQpgYGB7cn0KZ2dwbG90KHZzZXRpLCBhZXMoeD1GWSwgeT1CRF9YMV9GWV9vcnQsIGZpbGw9WDEpKSsKZ2VvbV9saW5lKGFlcyhjb2xvdXI9WDEsIGdyb3VwPVgxKSkrCmdlb21fcG9pbnQoc2l6ZT0xLGFlcyhjb2xvdXI9WDEpKSsKbGFicyh0aXRsZT0iR3JhZmlnaW4gQW5hIEJhc2xpZ2kiLCB4ID0iWDEgR3J1cGxhcmkiLCB5ID0gIllpbGxhcmEgR29yZSBPcnRhbGFtYSBCYWdpbWxpIERlZ2lza2VuIikrCnRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSsKc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDAuMSwwLjAxKSkrCnNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAxNSwyMDE3LDEpKQojdnNldGknbmkga3VsbGFuYXJhayBCRH5GWSBncmFmacSfaW5pIG9sdcWfdHVyLgojw6dpemdpIGdyYWZpayBvbHXFn3R1cgojbm9rdGFsYXLEsSBnw7ZzdGVyLCBub2t0YSBiw7x5w7xrbMO8xJ/DvCAzIG9sc3VuLCBYMSdlIGfDtnJlIHJlbmtsZW5kaXIKI2Vrc2VubGVyaSB2ZSBncmFmacSfaW4gYWTEsW7EsSB5YXoKI2dyYWZpxJ9pbiBhZMSxbsSxIG9ydGFsYQojeSBla3NlbmluZGVraSBhcmEgZGXEn2VybGVyaSBheWFybGEKYGBgCiMgUmVncmVzeW9uIE1vZGVsaQrDh2FsxLHFn21hbcSxemRha2kgdGVtZWwgdmFyc2F5xLFtxLFtxLF6IChoaXBvdGV6KSBhxZ9hxJ/EsWRha2kgZ2liaWRpcjoKCj5IMDogWDEgQkQneWkgZXRraWxlbWVtZWt0ZWRpcgoKPkgxOiBYMSBCRCd5aSBldGtpbGVtZWt0ZWRpciAoQmVrbGVuZW4gacWfYXJldDogKQoKQnUgdmFyc2F5xLFtxLEgdGVzdCBldG1layBtb2RlbGltaXppIGVuIGvDvMOnw7xrIGthcmVsZXIgcmVncmVzeW9udSBvbGFyYWsga2F5ZGVkZWxpbS4gTW9kZWxlIGJpcmltIHZlIHnEsWwgc2F5ZXNpbmRlIHNhYml0IGV0a2lsZXJpIGRlIHRlc3QgZXRtacWfIG9sdXlvcnV6LiBBw6fEsWvDp2FzxLEgYmlyaW0gdmUgecSxbCBvbG1hZGFuIGRhaGEgZ8O8emVsIHNvbnXDp2xhciBlbGRlIGVkZWJpbGlyc2luaXogYW5jYWsgaXlpIGJpciBkZXJnaWRlIGRvxJ9ydWRhbiBrYWJ1bCBnw7ZybWVzaSBtw7xta8O8biBvbG1heWFjYWsuIE1vZGVsaW4gc29udcOnbGFyxLFuxLEgZ8O2cm1layBpw6dpbiBpa2luY2kga29tdXR1IMOnYWzEscWfdMSxcsSxbi4KCmBgYHtyfQptb2RlbDwtbG0oQkR+WDErS0QxK0tEMitLRDMrS0Q0K0tENStmYWN0b3IoSUQpK2ZhY3RvcihGWSksZGF0YT12c2V0aSkKc3VtbWFyeShtb2RlbCkKI2ZhY3RvcigpIGZvbmtzaXlvbnVudW4gYW1hY8SxIGhlciBiaXIgYmlyaW0ga29kdW5hIHZlIHnEsWxhIGt1a2xhIGRlxJ9pxZ9rZW4gdmVybWVrIHllcmluZSBoZXBzaW5pIMOnYWzEscWfdMSxcm1hay4gUiBoZXIgYmlyIGdydXB0YW4gYmlyIHRhbmVzaW5pIGFuYWxpemUgZGFoaWwgZXRtZXllY2VrCmBgYAoKIyMgU3RhbmRhcnQgSGF0YWxhciBEw7x6ZWx0aWxtacWfIE1vZGVsCkRvxJ9ydXNhbCBpbGUgdGVzdCBldHRpxJ9pbWl6IG1vZGVsZGUgYmlyIHNvcnVuIHZhci4gTW9kZWxpbiBzdGFuZGFydCBoYXRhbGFyxLFuxLEgYmlyaW0gdmUgecSxbGxhcmEgZ8O2cmUga8O8bWVsZXllcmVrIHNvbnXDp2xhcsSxbiBpc3RhdGlzdGlraSBvbGFyYWsgc2HEn2xhbWzEscSfxLFuxLEgeWFwYWNhxJ/EsXouCmBgYHtyfQptb2RlbF9TRTwtY29lZnRlc3QobW9kZWwsdmNvdj12Y292SEMobW9kZWwsdHlwZT0iSEMxIixjbHVzdGVyPWMoUERTJElELFBEUyRGWSkpKQpgYGAKCiMgTW9kZWxpbiBrYW50aWwgcmVncmVzeW9uIGlsZSB0ZXN0IGVkaWxtZXNpClZhcnNheWFsxLFtIGtpIGRvxJ9ydXNhbCByZWdyZXN5b24gacOnaW4gZ2VyZWtsaSDFn2FydGxhcsSxIHNhxJ9sYXlhbWFkxLFrIChbQmFsdGFnaSwgMjAxMV0oaHR0cHM6Ly93d3cuc3ByaW5nZXIuY29tL2dwL2Jvb2svOTc4MzY0MjIwMDU4OCkgdmUgbW9kZWxpbWl6aSBwYXJhbWV0cmlrIG9sbWF5YW4gcmVncmVzeW9uIGlsZSB0ZXN0IGV0bWVtaXogZ2VyZWtpeW9yLiBLb2Vua2VyIHZlIEJhc3NldCAoMTk3OCkgdGFyYWbEsW5kYW4gZ2VsacWfdGlyaWxlbiBrYW50aWwgcmVncmVzeW9uIGJ1IGFtYcOnbGEga3VsbGFuYWJpbGVjZcSfaW5peiB5w7ZudGVtbGVyZGVuIGJpcmkuIEFuYWxpeiBpw6dpbiBnZXJla2VuIHBha2V0IGJpenphdCByZWdyZXN5b251IGdlbGnFn3RpcmVuIEtvZW5rZXLigJllIGFpdC4gTW9kZWxpIGJpciBrZXJlIMOnYWzEscWfdMSxcm1hayB2ZSBrYXlkZXRtZWsgeWV0bWV5ZWNlay4gTmUgeWFwYWNhxJ/EsXogcGVraT8gVG9wbGFtZGEgNyBrZXJlIMOnYWzEscWfdMSxcm3EscWfIG9sYWNhxJ/EsXouIHJxIGZvbmtzaXlvbnUgacOnaW5kZWtpIHRhdSBoYW5naSBrYW50aWwgZGXEn2VyaW5pbiB0ZXN0IGVkaWxlY2XEn2luaSBnw7ZzdGVybWVrdGVkaXIuCgpgYGB7cn0KbW9kZWxfMC4wNTwtcnEoQkR+WDErS0QxK0tEMitLRDMrS0Q0K0tENStmYWN0b3IoSUQpK2ZhY3RvcihGWSksZGF0YT12c2V0aSwgdGF1PTAuMDUpCm1vZGVsXzAuMTA8LXJxKEJEflgxK0tEMStLRDIrS0QzK0tENCtLRDUrZmFjdG9yKElEKStmYWN0b3IoRlkpLGRhdGE9dnNldGksIHRhdT0wLjEwKQptb2RlbF8wLjI1PC1ycShCRH5YMStLRDErS0QyK0tEMytLRDQrS0Q1K2ZhY3RvcihJRCkrZmFjdG9yKEZZKSxkYXRhPXZzZXRpLCB0YXU9MC4yNSkKbW9kZWxfMC41MDwtcnEoQkR+WDErS0QxK0tEMitLRDMrS0Q0K0tENStmYWN0b3IoSUQpK2ZhY3RvcihGWSksZGF0YT12c2V0aSwgdGF1PTAuNTApCm1vZGVsXzAuNzU8LXJxKEJEflgxK0tEMStLRDIrS0QzK0tENCtLRDUrZmFjdG9yKElEKStmYWN0b3IoRlkpLGRhdGE9dnNldGksIHRhdT0wLjc1KQptb2RlbF8wLjkwPC1ycShCRH5YMStLRDErS0QyK0tEMytLRDQrS0Q1K2ZhY3RvcihJRCkrZmFjdG9yKEZZKSxkYXRhPXZzZXRpLCB0YXU9MC45MCkKbW9kZWxfMC45NTwtcnEoQkR+WDErS0QxK0tEMitLRDMrS0Q0K0tENStmYWN0b3IoSUQpK2ZhY3RvcihGWSksZGF0YT12c2V0aSwgdGF1PTAuOTUpCmBgYAoKIyMgS2FudGlsIHJlZ3Jlc3lvbiB2ZSBib290c3RyYXBwaW5nCkVuIGvDvMOnw7xrIGthcmVsZXIgecO2bnRlbWluZGUgc3RhbmRhcnQgaGF0YWxhcsSxIGJpcmltL3nEsWwgb2xhcmFrIGvDvG1lbGV5ZXJlayBtb2RlbGluIHNhxJ9sYW1sxLHEn8SxbsSxIHlhcG3EscWfdMSxay4gS2FudGlsIHJlZ3Jlc3lvbmRhIG5lZGVuIGLDtnlsZSBiaXIgxZ9leSB5YXBtxLF5b3J1ej8gS2FudGlsIHJlZ3Jlc3lvbmRhIHN0YW5kYXJ0IGhhdGFsYXLEsW4ga8O8bWVsZW5tZXNpIGnDp2luIHNvbnXDp2xhcsSxbiB5ZW5pZGVuIMO2bnnDvGtsZW5tZXNpIGdlcmVraXlvciAoW0hhbyB2ZSBOYWltYW4sIDIwMDddKGh0dHBzOi8vdXMuc2FnZXB1Yi5jb20vZW4tdXMvbmFtL3F1YW50aWxlLXJlZ3Jlc3Npb24vYm9vazIyODMzNykpLiBCdSBpxZ9sZW0gZXNhcyBtb2RlbGRlIHlhcHTEscSfxLFtxLF6YSBnw7ZyZSBkYWhhIGtvbGF5LgpgYGB7cn0Kc3VtbWFyeS5ycShtb2RlbF8wLjA1LHNlPSJib290IikKc3VtbWFyeS5ycShtb2RlbF8wLjEwLHNlPSJib290IikKc3VtbWFyeS5ycShtb2RlbF8wLjI1LHNlPSJib290IikKc3VtbWFyeS5ycShtb2RlbF8wLjUwLHNlPSJib290IikKc3VtbWFyeS5ycShtb2RlbF8wLjc1LHNlPSJib290IikKc3VtbWFyeS5ycShtb2RlbF8wLjkwLHNlPSJib290IikKc3VtbWFyeS5ycShtb2RlbF8wLjk1LHNlPSJib290IikKYGBgCgojIyBLYW50aWwgcmVncmVzeW9uIGnDp2luIFJeMl4gaGVzYXBsYW1hawpbS29lbmtlciBkaXlvciBraV0oaHR0cHM6Ly9zdGF0LmV0aHouY2gvcGlwZXJtYWlsL3ItaGVscC8yMDA2LUF1Z3VzdC8xMTAzODYuaHRtbCkKCj5JIGRvbid0IG11Y2ggbGlrZSBSMSwgb3IgUjIgZm9yIHRoYXQgbWF0dGVyLCBzbyBpdCBpc24ndCBsaWtlbHkgdG8gYmUgYXV0b21hdGljYWxseSBwcm92aWRlZCBpbiBxdWFudHJlZyBhbnkgdGltZSBzb29uLiAoUjEgdmV5YSBSMidkZW4gw6dvayBob8WfbGFubcSxeW9ydW0sIGJ1IHnDvHpkZW4gZGUgeWFrxLFuIGJpciB6YW1hbmRhIHF1YW50cmVnJ2RlIG90b21hdGlrIG9sYXJhayB5ZXIgYWxtYXPEsSBvbGFzxLEgZGXEn2lsICjDh2V2aXJpOiBHQykKClBla2kgc2l6IGJ1IG1vZGVsbGVyaW4gYWx0xLFuZGEgUjIgZWtsZW1layBpc3RpeW9yc2FuxLF6IG5lIHlhcG1hbsSxeiBsYXrEsW0/ICjDh8O2esO8bSBpw6dpbiBbS29lbmtlciB2ZSBNYWNoYWRvLCAxOTk5XShodHRwczovL3d3dy5tYXRocy51c3lkLmVkdS5hdS91L2pjaGFuL0dMTS9Lb2Vua2VyJk1hY2hhZG8xOTk5SW5mZXJlbmNlUXVhbnRpbGVSZWcucGRmKS4gUi1zcXVhcmVkIGluIHF1YW50aWxlIHJlZ3Jlc3Npb24sIERpbWl0cml5IFYuIE1hc3Rlcm92IChodHRwczovL3N0YXRzLnN0YWNrZXhjaGFuZ2UuY29tL3VzZXJzLzcwNzEvZGltaXRyaXktdi1tYXN0ZXJvdiksIFItc3F1YXJlZCBpbiBxdWFudGlsZSByZWdyZXNzaW9uLCBVUkwgKHZlcnNpb246IDIwMTQtMTItMTcpOiBodHRwczovL3N0YXRzLnN0YWNrZXhjaGFuZ2UuY29tL3EvMTI5MjUxKQoKYGBge3J9CmZpdDAgPC0gcnEoQkR+MSx0YXU9MC45NSxkYXRhPXZzZXRpKQpmaXQxPC1ycShCRH5YMStLRDErS0QyK0tEMytLRDQrS0Q1K2ZhY3RvcihJRCkrZmFjdG9yKEZZKSxkYXRhPXZzZXRpLCB0YXU9MC4wNSkKcmhvIDwtIGZ1bmN0aW9uKHUsdGF1PS41KXUqKHRhdSAtICh1IDwgMCkpClIxIDwtIDEgLSBmaXQxJHJoby9maXQwJHJobwpSMQpgYGAKQnUgZm9ybcO8bMO8IGhlciBiaXIga2FudGlsIG5va3Rhc8SxIGnDp2luIHRlayB0ZWsgKDAuMDUsIDAuMTAsIDAuMjUsIDAuNTAsIDAuNzUsIDAuOTAgdmUgMC45NSkgaGVzYXBsYW1hbsSxeiBnZXJla2l5b3IuCgojIFIgTm90ZWJvb2sKU2l6aW5sZSBwYXlsYcWfdMSxxJ/EsW0ga29kbGFyxLEgw6dhbMSxxZ9tYW7EsXrEsW4gKMO2ZGV2bGVyIGRlIGRhaGlsIG9sbWFrIMO8emVyZSkgYW5hbGl6aW5lIHV5Z3VuIG9sYXJhayBkZcSfacWfdGlyZWJpbGlyLCBzb251w6dsYXLEsSB0ZWsgYmlyIGRvc3lhZGEgcmFwb3JsYXlhYmlsaXJzaW5pei4gS29kbGFyxLFuIG5lIGnFn2UgeWFyYWTEscSfxLFuxLEgZ8O2c3RlcmVtZXllbiBiaXIgbm90IHV5Z3VsYW1hc8SxIHllcmluZSBnZXLDp2VrIGJpciDDp2FsxLHFn21hIGRlZnRlcmkgaXN0ZXJzZW5peiBSIE5vdGVib29rIGnFn2luaXppIGfDtnJlY2VrdGlyLiBSIE1hcmtkb3duIGt1bGxhbmFyYWsgbWV0bmkgaXN0ZWRpxJ9pbml6IGdpYmkgYmnDp2ltbGVuZGlyZWJpbGlyc2luaXouIEtvZGxhcsSxIFIgTm90ZWJvb2vigJl0YSBuYXPEsWwga3VsbGFuYWNha3PEsW7EsXo/CgpgYGB7cn0KZGVzazwtc3VtbWFyeSh2c2V0aVssNDoxMF0pCmRlc2sKYGBgCll1a2FyxLFkYWtpIGtvZCB5xLHEn8SxbsSxIChjaHVuaykgaGVtIHNpemluIGFsZMSxxJ/EsW7EsXogbm90bGFyxLEgc2FrbGF5YWNhayBoZW0gZGUgYnUga29kdW4gbmUgYW5sYW1hIGdlbGRpxJ9pbmkgbWVyYWsgZXR0acSfaW5pemRlIHnEscSfxLFuxLFuIGVuIHNhxJ/EsW5kYWtpIG95bmF0IHR1xZ91bmEgYmFzYXJhayAo4oCcUnVuIEN1cnJlbnQgQ2h1bmvigJ0pIHNvbnXDp2xhcsSxIGRhIGfDtnJtZW5pemkgc2HEn2xheWFjYWsuCgojIERhdGFjYW1wIENhcmVlciBUcmFjawpbU3RhdGlzdGljaWFuIHdpdGggUl0oaHR0cHM6Ly9sZWFybi5kYXRhY2FtcC5jb20vY2FyZWVyLXRyYWNrcy9zdGF0aXN0aWNpYW4td2l0aC1yKSAtIFRhbWFtbGFuZMSxCgpbUXVhbnRpdGF0aXZlIEFuYWx5c3Qgd2l0aCBSXShodHRwczovL2xlYXJuLmRhdGFjYW1wLmNvbS9jYXJlZXItdHJhY2tzL3F1YW50aXRhdGl2ZS1hbmFseXN0LXdpdGgtcikgLSBEZXZhbSBlZGl5b3IKCg==