개인과제2. 162STG26조현선

과제 소개:

library(ggplot2)
library(grid)
library(gridExtra)
library(dplyr)
mpg

Q1.

What happens if you try to facet by a continuous variable like hwy? What about cyl? What’s the key difference?

문제를 진행하기에 앞서, x축은 displ변수를, y축은 cty변수를 넣어 그래프를 그려보았다.

ggplot(data=mpg, aes(x=displ, y=cty)) + geom_point()

전반적인 트랜드는 볼 수 있었으나, 면분할 기능을 이용하여 다른 변수를 추가하여 좀 더 자세한 비교를 해보고자 한다.

ggplot(data=mpg, aes(x=displ, y=cty)) + geom_point() + facet_wrap( ~hwy, nrow=4) 

위의 그래프는 연속형 변수인 hwy를 기준으로 면을 분할하였다. 그러자 집단들간의 비교가 한 눈에 들어오지 않고 전반적인 트랜드를 파악하기가 더 어려워짐을 확인하였다. 따라서 이런 경우에는 이 연속형 변수를 하나의 그래프에 넣고 분류하고자 하는 변수에 대해 색상같은 에스테틱에 대입하는 것이, 분할하는 방법보다 나을 것이다. 즉, 아래처럼 수정한 플랏이 더 알맞다고 생각된다.

ggplot(data=mpg) + geom_point(mapping=aes(x=displ, y=cty, color=hwy )) 

다음으로 범주형 변수를 기준으로 면을 분할해보고자 한다. 면을 분할하는 방향은 비교를 할 때 무엇을 강조하고자 하느냐에 따라 달라진다. 예를 들어 막대의 높이를 비교하고 싶다면 면을 아래와 같이 수평으로 분할하는 게 낫다. 다음의 코드를 실행한 결과를 보자.

ggplot(data=mpg, aes(x=displ, y=cty)) + geom_point() + facet_wrap( ~cyl, nrow=1) 

cyl의 값에 따른 cty분포를 비교하기가 용이해졌다. 정리하자면, facet을 이용하여 비교를 하고자 할 때는 분할하는 기준이 되는 변수는 범주형 변수가 적절함을 확인하였다.

Q2.

Use facetting to explore the 3-way relationship between fuel economy,engine size, and number of cylinders. How does facetting by number of cylinders change your assessement of the relationship between engine size and fuel economy?

hwy는 연료의 경제성, displ은 엔진의 사이즈를 의미하고, cyl은 실린더의 개수이다. 먼저 엔진의 사이즈와 연료경제성만을 가지고 그래프를 그려보면, 엔진의 크기가 커질 수록 연료의 경제성이 줄어드는 모습을 볼 수 있다.

ggplot(data=mpg, aes(x=displ, y=hwy)) + geom_point() 

연비에 영향을 미치는 요인이 엔진의 크기 때문이라고 결론을 내리기 전에, 실린더의 개수도 고려하여 그래프를 그려보았다.

ggplot(data=mpg, aes(x=displ, y=hwy)) + geom_point() + facet_grid(.~cyl) 

그러자 위와 같이, 실린더의 갯수가 많을 수록 엔진의 크기가 큰 값을 가진다는것을 볼 수 있었다. 따라서, 실린더의 갯수에 따라 엔진의 크기가 영향을 받을 것이고, 연비를 낮추는 요인으로 작용할 것이라는 걸 파악할 수 있게 되었다.

Q3.

What does the scales argument to facet_wrap() do? When might you use it?

축의 범위 또는 항목이 다른 하위 그래프들을 그리고 싶을 때가 있다. 이럴 때는 scales를 “free_x”,“free_y”또는 “free”로 설정한다. scale에 대한 조정을 하지 않은 class로 분할된 기본 그래프를 먼저 그려보았다.

ggplot(mpg, aes(x=displ, y=hwy))+geom_point()+facet_wrap(~class, nrow=2)

위의 그림을 보면, 축의 기준이 같으므로 전반적인 트랜드는 확인 할 수 있다. 그러나 그래프 개개인의 분포가 뭉개진듯이 특성이 보이지 않고 뭉쳐서 보이므로, 각 도표마다의 특성을 확인 하고 싶을 수 있다. 그럴 때는 아래와 같이 scales에 free라고 옵션을 주어 x 및 y 축 눈금을 자유롭게 해보았다.

ggplot(mpg, aes(x=displ, y=hwy))+geom_point()+facet_wrap(~class, nrow=2, scales="free")

이제 x와 y눈금이 자유롭게 만들어져서 적용됨을 확인할 수 있었다. 그리고 전의 그래프에서는 보이지 않던 각 class 에 따른 수준의 특성들이 보임을 알 수 있다. 과제 1번부터 3번 문항을 정리해보면, “이산” 값 축을 사용하면서 “눈금을 자유롭게” 변경하여 면 분할 하는 방법을 살펴보았다.

Q4.

What’s the problem with the plot created by ggplot(mpg, aes(cty, hwy)) + geom_point()? Which of the geoms described above is most effective at remedying the problem?

nrow(mpg)
[1] 234
ggplot(mpg, aes(cty, hwy)) + geom_point()

위의 그림의 문제점은, 234개정도의 데이터 점들이 서로 겹쳐서 그래프를 볼 때 데이터의 분포를 정확히 가늠하기가 어렵고, 상대적인 밀도를 알아보기 어렵다는 것이다. 이것을 ’overplot’이라고 표현하는데, 이해 대한 해결책이 몇 가지를 제시해보면 다음과 같다.

데이터의 x축과 y축을 연속형으로 보고, 앞의 두가지 방법에 대해 실행해보고자 한다. 먼저 반투명하게 점을 그리는 과정이다.

ggplot(mpg, aes(cty, hwy)) + geom_point(alpha=0.2)

조금 경향이 잘 보이기는 하나, gray scale이므로 여전히 모호한 부분이 있다. 다음으로 점들을 정사각형으로 bin을 주고, 점들의 밀도에 따라 색상을 준다.

ggplot(mpg, aes(cty, hwy)) + stat_bin2d() + scale_fill_gradient(low="lightblue", high="red")

Q5.

One challenge with ggplot(mpg, aes(class, hwy)) + geom_boxplot() is that the ordering of class is alphabetical, which is not terribly useful. How could you change the factor levels to be more informative?

p1 = ggplot(mpg, aes(class, hwy)) + geom_boxplot()
p2 = ggplot(mpg, aes(x=reorder(class,hwy,FUN = median ),y=hwy)) + geom_boxplot()+labs(x= 'class')
grid.arrange(p1, p2, ncol = 2)

왼쪽의 그래프처럼 알파벳 순으로 박스플랏을 그린 경우, 보기도 어렵고 한 눈에 데이터 파악이 쉽지않다. 따라서 오른쪽의 그림처럼 median의 값이 작은 순서대로 차례로 박스플랏을 그려주는 것이 보기 좋다. reorder option을 사용하여 x와 y에 대해 재정렬을 해주었음을 코드를 통해 확인할 수 있다.

Q6.

Using the techniques already discussed in this chapter, come up with three ways to visualize a 2d categorical distribution. Try them out by visualising the distribution of model and manufacturer, trans and class, and cyl and trans.

CASE.1 model and manufacturer

model과 manufacturer에 대해 그래프를 그리기 전에 데이터를 정리하였다.

df1<-as.data.frame(cbind(mpg$manufacturer,mpg$model))
colnames(df1) <- c("manufacturer","model")
df2<-as.data.frame(table(mpg$model))
colnames(df2) <- c("model","freq")
new_tables<-as.data.frame(unique(merge(x=df1,y=df2,by="model")))[,c("manufacturer","model","freq")]
new_tables<-arrange(new_tables,manufacturer,desc(freq),model)
nameorder <- new_tables$model[order(new_tables$manufacturer,new_tables$freq)]
new_tables$model <- factor(new_tables$model,levels =nameorder)
new_tables

이렇게 정리한 데이터를 이용하여 그래프를 그리고자 한다. 이 데이터를 표현하기 위해 “크리블랜드 점 그래프(Cleveland dot plot)”을 만들고자 한다. 클리블랜드 점 그래프는 보기에 덜 어수선하고 보기 쉬워 막대 그래프 대신에 사용되곤 한다. 자동차 제조사별로 묶어서 구분을 하고, 그 안에서 많이 조사된 모델별로 sort하여 그림을 나타내면 다음과 같이 표현할 수 있다.

ggplot(new_tables, aes(x=freq,y=model))+
  geom_segment(aes(yend=model),xend=0,colour="grey50")+
  geom_point(size=3, aes(colour=manufacturer))+
  theme_bw()+
  theme(panel.grid.major.y = element_blank())+
  facet_grid(manufacturer~.,scale="free_y",space="free_y")+
  theme(strip.text.y = element_text(angle=0,face="bold"))

CASE.2 trans and class

범주형 변수인 trans와 class를 도식화하기 전에 두 변수를 정리하고 해당하는 빈도에 대해 다음과 같이 표로 정리해보았다.

df3<-as.data.frame(cbind(mpg$trans,mpg$class))
colnames(df3)<-c("trans","class")
trans_class<-arrange(df3,factor(trans),class)
table(trans_class)
            class
trans        2seater compact midsize minivan pickup subcompact suv
  auto(av)         0       2       3       0      0          0   0
  auto(l3)         0       1       0       1      0          0   0
  auto(l4)         1       8      14       8     12         11  29
  auto(l5)         0       4       5       0      8          4  18
  auto(l6)         0       0       0       2      0          0   4
  auto(s4)         0       2       1       0      0          0   0
  auto(s5)         0       2       0       0      0          0   1
  auto(s6)         1       5       6       0      0          1   3
  manual(m5)       0      18       9       0      8         16   7
  manual(m6)       3       5       3       0      5          3   0

이 table을 이용하여 data frame을 정의하고 이를 이용하여 heatmap을 도식화하면 아래와 같고, 그림을 보면 위의 table을 그대로 잘 표현해냈음을 확인할 수 있다.

tr_cl<-as.data.frame(table(trans_class))
ggplot(tr_cl,aes(x=class, y=trans, fill=Freq)) + geom_raster() + ylim(rev(levels(tr_cl$trans)))+
  scale_fill_gradient(low="#FFCCFF", high="#660066")

CASE.3 cyl and trans

마지막으로 실린더수(cyl)과 변속기(trans) 사이의 관계에 대해 그림으로 나타내고자 한다. 변속기 변수를 살펴 보면 크게 auto와 manual로 명칭이 나누어져 있음을 알 수 있다. 이를 고려하여 새로운 데이터 프레임 형태를 만들어 보았다.

big_trans <- NULL
for (i in 1:length(trans)){
  if(grepl(auto,trans[i])==TRUE){
    big_trans[i] <- "auto"
  }else{
    big_trans[i] <- "manual"
  }
}
trdf<-as.data.frame(cbind(mpg$trans, mpg$cyl, big_trans))
colnames(trdf)<-c("trans","cyl","auto_manual")
autogroup<-table(arrange(trdf,factor(trans),cyl,auto_manual))[,,1][-c(9:10),]
manualgroup<-table(arrange(trdf,factor(trans),cyl,auto_manual))[,,2][-c(1:8),]
auto_df<-as.data.frame(autogroup)
manual_df<-as.data.frame(manualgroup)
print(autogroup)
          cyl
trans       4  5  6  8
  auto(av)  2  0  3  0
  auto(l3)  2  0  0  0
  auto(l4) 24  0 29 30
  auto(l5)  6  0 16 17
  auto(l6)  0  0  2  4
  auto(s4)  2  0  0  1
  auto(s5)  1  0  1  1
  auto(s6)  4  2  5  5
print(manualgroup)
            cyl
trans         4  5  6  8
  manual(m5) 33  2 18  5
  manual(m6)  7  0  5  7

위처럼 변속기의 구성이 자동과 수동으로 크게 두 개의 테이블로 나누었다. 이제 이를 이용하여 heatmap처럼 도식화하여 표현하면 다음과 같다.

a1<-ggplot(auto_df,aes(x=cyl, y=trans, fill=Freq)) + geom_raster() + ylim(rev(levels(auto_df$trans)))+
  scale_fill_gradient(low="#CCCCCC", high="#CC0000",limits=c(1,35),breaks=c(0,10,20,30))+
  ggtitle("Auto transmission distribution")
a2<-ggplot(manual_df,aes(x=cyl, y=trans, fill=Freq)) + geom_raster() + ylim(rev(levels(manual_df$trans)))+
  scale_fill_gradient(low="#CCCCCC", high="#CC0000",limits=c(0,35),breaks=c(0,10,20,30))+
  ggtitle("Manual transmission distribution")
grid.arrange(a1, a2, nrow = 2)

위의 그래프를 보면 자동변속기에서는 cyl개수가 5개인 차량은 거의 없었고, 대부분의 cyl개수와 상관없이 auto(I4)라는 변속기 종류가 관측이 많이 되었음을 볼 수 있었다. 수동변속기에서는 cyl개수가 4개인 경우가 많았고, m5종류가 m6보다 많음을 시각적으로 확인할 수 있었다.

LS0tDQp0aXRsZTogIlN0YXRpc3RpY2FsIEdyYXBoaWNzIEhXMiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KZm9udGZhbWlseTogbWF0aHBhem8NCmZvbnRzaXplOiAxMXB0DQotLS0NCiMjIyMjIyDqsJzsnbjqs7zsoJwyLiAxNjJTVEcyNuyhsO2YhOyEoA0KIyMjIOqzvOygnCDshozqsJw6IA0KICog642w7J207YSwIOyLnOqwge2ZlOulvCDtlaAg65WMIOqwgOyepSDsnKDsmqntlZwg7YWM7YGs64uJIOykkSDtlZjrgpjqsIAg642w7J207YSwIOynkeuLqOuTpOydhCDshJzroZzsnZgg7JiG7JeQIOychOy5mOyLnOy8nCDruYTqtZDqsIAg7Jqp7J207ZWY64+E66GdIOunjOuTnOuKlCDqsoPsnbTri6QuICBnZ3Bsb3Qy7JeQ7ISc64qUICfrqbQg67aE7ZWgKGZhY2V0KSfsnbTrnbwg7Lmt7ZWc64ukLiDsnbTrsogg6rO87KCc7JeQ7ISc64qUIOuptCDrtoTtlaDsnYQg7Ja065a76rKMIOyCrOyaqe2VmOuKlOyngCDslYzslYTrs7Tqs6DsnpAg7ZWc64ukLg0KIA0KICogVXNlIG1wZyBkYXRhIGluIGdncGxvdDIgcGFja2FnZSANCiANCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShncmlkKQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KGRwbHlyKQ0KbXBnDQpgYGANCg0KIyMjUTEuIA0KIyMjIFdoYXQgaGFwcGVucyBpZiB5b3UgdHJ5IHRvIGZhY2V0IGJ5IGEgY29udGludW91cyB2YXJpYWJsZSBsaWtlIGh3eT8gV2hhdCBhYm91dCBjeWw/IFdoYXQncyB0aGUga2V5IGRpZmZlcmVuY2U/DQog66y47KCc66W8IOynhO2Wie2VmOq4sOyXkCDslZ7shJwsIHjstpXsnYAgZGlzcGzrs4DsiJjrpbwsIHnstpXsnYAgY3R567OA7IiY66W8IOuEo+yWtCDqt7jrnpjtlITrpbwg6re466Ck67O07JWY64ukLg0KYGBge3IsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTl9DQpnZ3Bsb3QoZGF0YT1tcGcsIGFlcyh4PWRpc3BsLCB5PWN0eSkpICsgZ2VvbV9wb2ludCgpDQpgYGANCuyghOuwmOyggeyduCDtirjrnpzrk5zripQg67O8IOyImCDsnojsl4jsnLzrgpgsIOuptOu2hO2VoCDquLDriqXsnYQg7J207Jqp7ZWY7JesIOuLpOuluCDrs4DsiJjrpbwg7LaU6rCA7ZWY7JesIOyigCDrjZQg7J6Q7IS47ZWcIOu5hOq1kOulvCDtlbTrs7Tqs6DsnpAg7ZWc64ukLg0KDQpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0V9DQpnZ3Bsb3QoZGF0YT1tcGcsIGFlcyh4PWRpc3BsLCB5PWN0eSkpICsgZ2VvbV9wb2ludCgpICsgZmFjZXRfd3JhcCggfmh3eSwgbnJvdz00KSANCmBgYA0KIOychOydmCDqt7jrnpjtlITripQg7Jew7IaN7ZiVIOuzgOyImOyduCBod3nrpbwg6riw7KSA7Jy866GcIOuptOydhCDrtoTtlaDtlZjsmIDri6QuIOq3uOufrOyekCDsp5Hri6jrk6TqsITsnZgg67mE6rWQ6rCAIO2VnCDriIjsl5Ag65Ok7Ja07Jik7KeAIOyViuqzoCDsoITrsJjsoIHsnbgg7Yq4656c65Oc66W8IO2MjOyVhe2VmOq4sOqwgCDrjZQg7Ja066Ck7JuM7KeQ7J2EIO2ZleyduO2VmOyYgOuLpC4g65Sw65287IScIOydtOufsCDqsr3smrDsl5DripQg7J20IOyXsOyGje2YlSDrs4DsiJjrpbwg7ZWY64KY7J2YIOq3uOuemO2UhOyXkCDrhKPqs6Ag67aE66WY7ZWY6rOg7J6QIO2VmOuKlCDrs4DsiJjsl5Ag64yA7ZW0IOyDieyDgeqwmeydgCDsl5DsiqTthYzti7Hsl5Ag64yA7J6F7ZWY64qUIOqyg+ydtCwg67aE7ZWg7ZWY64qUIOuwqeuyleuztOuLpCDrgpjsnYQg6rKD7J2064ukLiDspoksIOyVhOuemOyymOufvCDsiJjsoJXtlZwg7ZSM656P7J20IOuNlCDslYzrp57ri6Tqs6Ag7IOd6rCB65Cc64ukLg0KYGBge3IsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTEwfQ0KZ2dwbG90KGRhdGE9bXBnKSArIGdlb21fcG9pbnQobWFwcGluZz1hZXMoeD1kaXNwbCwgeT1jdHksIGNvbG9yPWh3eSApKSANCmBgYA0KDQogDQog64uk7J2M7Jy866GcIOuylOyjvO2YlSDrs4DsiJjrpbwg6riw7KSA7Jy866GcIOuptOydhCDrtoTtlaDtlbTrs7Tqs6DsnpAg7ZWc64ukLiDrqbTsnYQg67aE7ZWg7ZWY64qUIOuwqe2WpeydgCDruYTqtZDrpbwg7ZWgIOuVjCDrrLTsl4fsnYQg6rCV7KGw7ZWY6rOg7J6QIO2VmOuKkOuDkOyXkCDrlLDrnbwg64us65287KeE64ukLiDsmIjrpbwg65Ok7Ja0IOunieuMgOydmCDrhpLsnbTrpbwg67mE6rWQ7ZWY6rOgIOyLtuuLpOuptCDrqbTsnYQg7JWE656Y7JmAIOqwmeydtCDsiJjtj4nsnLzroZwg67aE7ZWg7ZWY64qUIOqyjCDrgqvri6QuIOuLpOydjOydmCDsvZTrk5zrpbwg7Iuk7ZaJ7ZWcIOqysOqzvOulvCDrs7TsnpAuDQpgYGB7ciwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9MTB9DQpnZ3Bsb3QoZGF0YT1tcGcsIGFlcyh4PWRpc3BsLCB5PWN0eSkpICsgZ2VvbV9wb2ludCgpICsgZmFjZXRfd3JhcCggfmN5bCwgbnJvdz0xKSANCmBgYA0KY3ls7J2YIOqwkuyXkCDrlLDrpbggY3R567aE7Y+s66W8IOu5hOq1kO2VmOq4sOqwgCDsmqnsnbTtlbTsoYzri6QuIOygleumrO2VmOyekOuptCwgZmFjZXTsnYQg7J207Jqp7ZWY7JesIOu5hOq1kOulvCDtlZjqs6DsnpAg7ZWgIOuVjOuKlCDrtoTtlaDtlZjripQg6riw7KSA7J20IOuQmOuKlCDrs4DsiJjripQg67KU7KO87ZiVIOuzgOyImOqwgCDsoIHsoIjtlajsnYQg7ZmV7J247ZWY7JiA64ukLg0KDQoNCg0KIyMjUTIuIA0KIyMjIFVzZSBmYWNldHRpbmcgdG8gZXhwbG9yZSB0aGUgMy13YXkgcmVsYXRpb25zaGlwIGJldHdlZW4gZnVlbCBlY29ub215LGVuZ2luZSBzaXplLCBhbmQgbnVtYmVyIG9mIGN5bGluZGVycy4gSG93IGRvZXMgZmFjZXR0aW5nIGJ5IG51bWJlciBvZiBjeWxpbmRlcnMgY2hhbmdlIHlvdXIgYXNzZXNzZW1lbnQgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGVuZ2luZSBzaXplIGFuZCBmdWVsIGVjb25vbXk/DQoNCmh3eeuKlCDsl7Dro4zsnZgg6rK97KCc7ISxLCBkaXNwbOydgCDsl5Tsp4TsnZgg7IKs7J207KaI66W8IOydmOuvuO2VmOqzoCwgY3ls7J2AIOyLpOumsOuNlOydmCDqsJzsiJjsnbTri6QuIOuovOyggCDsl5Tsp4TsnZgg7IKs7J207KaI7JmAIOyXsOujjOqyveygnOyEseunjOydhCDqsIDsp4Dqs6Ag6re4656Y7ZSE66W8IOq3uOugpOuztOuptCwg7JeU7KeE7J2YIO2BrOq4sOqwgCDsu6Tsp4gg7IiY66GdIOyXsOujjOydmCDqsr3soJzshLHsnbQg7KSE7Ja065Oc64qUIOuqqOyKteydhCDrs7wg7IiYIOyeiOuLpC4gDQpgYGB7ciwgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0xMH0NCmdncGxvdChkYXRhPW1wZywgYWVzKHg9ZGlzcGwsIHk9aHd5KSkgKyBnZW9tX3BvaW50KCkgDQpgYGANCiDsl7DruYTsl5Ag7JiB7Zal7J2EIOuvuOy5mOuKlCDsmpTsnbjsnbQg7JeU7KeE7J2YIO2BrOq4sCDrlYzrrLjsnbTrnbzqs6Ag6rKw66Gg7J2EIOuCtOumrOq4sCDsoITsl5AsIOyLpOumsOuNlOydmCDqsJzsiJjrj4Qg6rOg66Ck7ZWY7JesIOq3uOuemO2UhOulvCDqt7jroKTrs7TslZjri6QuIA0KYGBge3IsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTEwfQ0KZ2dwbG90KGRhdGE9bXBnLCBhZXMoeD1kaXNwbCwgeT1od3kpKSArIGdlb21fcG9pbnQoKSArIGZhY2V0X2dyaWQoLn5jeWwpIA0KYGBgDQrqt7jrn6zsnpAg7JyE7JmAIOqwmeydtCwg7Iuk66aw642U7J2YIOqwr+yImOqwgCDrp47snYQg7IiY66GdIOyXlOynhOydmCDtgazquLDqsIAg7YGwIOqwkuydhCDqsIDsp4Tri6TripTqsoPsnYQg67O8IOyImCDsnojsl4jri6QuIOuUsOudvOyEnCwg7Iuk66aw642U7J2YIOqwr+yImOyXkCDrlLDrnbwg7JeU7KeE7J2YIO2BrOq4sOqwgCDsmIHtlqXsnYQg67Cb7J2EIOqyg+ydtOqzoCwg7Jew67mE66W8IOuCruy2lOuKlCDsmpTsnbjsnLzroZwg7J6R7Jqp7ZWgIOqyg+ydtOudvOuKlCDqsbgg7YyM7JWF7ZWgIOyImCDsnojqsowg65CY7JeI64ukLg0KDQojIyNRMy4gDQojIyMgV2hhdCBkb2VzIHRoZSBzY2FsZXMgYXJndW1lbnQgdG8gZmFjZXRfd3JhcCgpIGRvPyBXaGVuIG1pZ2h0IHlvdSB1c2UgaXQ/DQrstpXsnZgg67KU7JyEIOuYkOuKlCDtla3rqqnsnbQg64uk66W4IO2VmOychCDqt7jrnpjtlITrk6TsnYQg6re466as6rOgIOyLtuydhCDrlYzqsIAg7J6I64ukLiDsnbTrn7Qg65WM64qUIHNjYWxlc+ulvCAiZnJlZV94IiwiZnJlZV95IuuYkOuKlCAiZnJlZSLroZwg7ISk7KCV7ZWc64ukLg0Kc2NhbGXsl5Ag64yA7ZWcIOyhsOygleydhCDtlZjsp4Ag7JWK7J2AIGNsYXNz66GcIOu2hO2VoOuQnCDquLDrs7gg6re4656Y7ZSE66W8IOuovOyggCDqt7jroKTrs7TslZjri6QuDQpgYGB7ciwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9MTB9DQpnZ3Bsb3QobXBnLCBhZXMoeD1kaXNwbCwgeT1od3kpKStnZW9tX3BvaW50KCkrZmFjZXRfd3JhcCh+Y2xhc3MsIG5yb3c9MikNCmBgYA0KIOychOydmCDqt7jrprzsnYQg67O066m0LCDstpXsnZgg6riw7KSA7J20IOqwmeycvOuvgOuhnCDsoITrsJjsoIHsnbgg7Yq4656c65Oc64qUIO2ZleyduCDtlaAg7IiYIOyeiOuLpC4g6re465+s64KYIOq3uOuemO2UhCDqsJzqsJzsnbjsnZgg67aE7Y+s6rCAIOutieqwnOynhOuTr+ydtCDtirnshLHsnbQg67O07J207KeAIOyViuqzoCDrrYnss5DshJwg67O07J2066+A66GcLCDqsIEg64+E7ZGc66eI64uk7J2YIO2KueyEseydhCDtmZXsnbgg7ZWY6rOgIOyLtuydhCDsiJgg7J6I64ukLiDqt7jrn7Qg65WM64qUIOyVhOuemOyZgCDqsJnsnbQgc2NhbGVz7JeQIGZyZWXrnbzqs6Ag7Ji17IWY7J2EIOyjvOyWtCB4IOuwjyB5IOy2lSDriIjquIjsnYQg7J6Q7Jyg66Gt6rKMIO2VtOuztOyVmOuLpC4NCiANCiANCmBgYHtyLCBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTEwfQ0KZ2dwbG90KG1wZywgYWVzKHg9ZGlzcGwsIHk9aHd5KSkrZ2VvbV9wb2ludCgpK2ZhY2V0X3dyYXAofmNsYXNzLCBucm93PTIsIHNjYWxlcz0iZnJlZSIpDQpgYGANCg0K7J207KCcIHjsmYAgeeuIiOq4iOydtCDsnpDsnKDroa3qsowg66eM65Ok7Ja07KC47IScIOyggeyaqeuQqOydhCDtmZXsnbjtlaAg7IiYIOyeiOyXiOuLpC4g6re466as6rOgIOyghOydmCDqt7jrnpjtlITsl5DshJzripQg67O07J207KeAIOyViuuNmCDqsIEgY2xhc3Mg7JeQIOuUsOuluCDsiJjspIDsnZgg7Yq57ISx65Ok7J20IOuztOyehOydhCDslYwg7IiYIOyeiOuLpC4g6rO87KCcIDHrsojrtoDthLAgM+uyiCDrrLjtla3snYQg7KCV66as7ZW067O066m0LCAi7J207IKwIiDqsJIg7LaV7J2EIOyCrOyaqe2VmOuptOyEnCAi64iI6riI7J2EIOyekOycoOuhreqyjCIg67OA6rK97ZWY7JesIOuptCDrtoTtlaAg7ZWY64qUIOuwqeuyleydhCDsgrTtjrTrs7TslZjri6QuDQoNCiMjI1E0LiANCiMjIyBXaGF0J3MgdGhlIHByb2JsZW0gd2l0aCB0aGUgcGxvdCBjcmVhdGVkIGJ5IGdncGxvdChtcGcsIGFlcyhjdHksIGh3eSkpICsgZ2VvbV9wb2ludCgpPyBXaGljaCBvZiB0aGUgZ2VvbXMgZGVzY3JpYmVkIGFib3ZlIGlzIG1vc3QgZWZmZWN0aXZlIGF0IHJlbWVkeWluZyB0aGUgcHJvYmxlbT8NCmBgYHtyfQ0KbnJvdyhtcGcpDQpgYGANCmBgYHtyLCBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTEwfQ0KZ2dwbG90KG1wZywgYWVzKGN0eSwgaHd5KSkgKyBnZW9tX3BvaW50KCkNCmBgYA0KIOychOydmCDqt7jrprzsnZgg66y47KCc7KCQ7J2ALCAyMzTqsJzsoJXrj4TsnZgg642w7J207YSwIOygkOuTpOydtCDshJzroZwg6rK57LOQ7IScIOq3uOuemO2UhOulvCDrs7wg65WMIOuNsOydtO2EsOydmCDrtoTtj6zrpbwg7KCV7ZmV7Z6IIOqwgOuKoO2VmOq4sOqwgCDslrTroLXqs6AsIOyDgeuMgOyggeyduCDrsIDrj4Trpbwg7JWM7JWE67O06riwIOyWtOugteuLpOuKlCDqsoPsnbTri6QuIOydtOqyg+ydhCAnb3ZlcnBsb3Qn7J2065286rOgIO2RnO2YhO2VmOuKlOuNsCwg7J207ZW0IOuMgO2VnCDtlbTqsrDssYXsnbQg66qHIOqwgOyngOulvCDsoJzsi5ztlbTrs7TrqbQg64uk7J2M6rO8IOqwmeuLpC4NCiANCiAgICogYWxwaGHqsJLsnYQg7IKs7Jqp7ZWY7JesIOygkOydhCDrsJjtiKzrqoXtlZjqsowg66eM65Og64ukLg0KICAgKiDtmLnsnYAg7KCQ65Ok7J2EIOygleyCrOqwge2YleycvOuhnCAnYmluJ+2ZlCDsi5zsvJzshJwg7KCQ65Ok7J2YIOuwgOuPhOulvCDsgqzqsIHtmJXrk6TsnZgg7LGE7Jqw6riwIOyDieyDgeyXkCDsp4DsoJXtlZzri6QuDQogICAqIOuNsOydtO2EsOulvCDrspTso7ztmZTtlZjsl6wg66m07J2EIOu2hO2VoO2VmOyXrCDtkZztmITtlZzri6QuDQogICAqIOyWkeyqvSDstpUg66qo65GQ6rCAIOydtOyCsOyduCDqsr3smrDsl5DripQgcG9zaXRpb25faml0dGVyKCnrpbwg7IKs7Jqp7ZWY7JesIOygkOuTpOydhCDrnpzrjaTtlZjqsowg7KGw6riI7JSpIOybgOyngeyXrChqaXR0ZXIp7KO866m0IOuQnOuLpC4NCiAgICog7ZWcIOy2leydgCDsnbTsgrDtmJUsIOuLpOuluCDtlZwg7LaV7J2AIOyXsOyGje2YleydtOudvOuptCDrsJXsiqQg7ZSM66Gv7J2EIOyggeygiO2eiCDsgqzsmqntlZjripQg6rKD7J20IO2DgOuLue2VoCDrlYzrj4Qg7J6I64ukLg0KDQrrjbDsnbTthLDsnZggeOy2leqzvCB57LaV7J2EIOyXsOyGje2YleycvOuhnCDrs7Tqs6AsIOyVnuydmCDrkZDqsIDsp4Ag67Cp67KV7JeQIOuMgO2VtCDsi6TtlontlbTrs7Tqs6DsnpAg7ZWc64ukLiDrqLzsoIAg67CY7Yis66qF7ZWY6rKMIOygkOydhCDqt7jrpqzripQg6rO87KCV7J2064ukLiANCmBgYHtyLCBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTEwfQ0KZ2dwbG90KG1wZywgYWVzKGN0eSwgaHd5KSkgKyBnZW9tX3BvaW50KGFscGhhPTAuMikNCmBgYA0K7KGw6riIIOqyve2WpeydtCDsnpgg67O07J206riw64qUIO2VmOuCmCwgZ3JheSBzY2FsZeydtOuvgOuhnCDsl6zsoITtnogg66qo7Zi47ZWcIOu2gOu2hOydtCDsnojri6QuIOuLpOydjOycvOuhnCDsoJDrk6TsnYQg7KCV7IKs6rCB7ZiV7Jy866GcIGJpbuydhCDso7zqs6AsIOygkOuTpOydmCDrsIDrj4Tsl5Ag65Sw6528IOyDieyDgeydhCDspIDri6QuDQpgYGB7ciwgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0xMH0NCmdncGxvdChtcGcsIGFlcyhjdHksIGh3eSkpICsgc3RhdF9iaW4yZCgpICsgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9ImxpZ2h0Ymx1ZSIsIGhpZ2g9InJlZCIpDQoNCmBgYA0KDQojIyNRNS4gDQojIyMgT25lIGNoYWxsZW5nZSB3aXRoIGdncGxvdChtcGcsIGFlcyhjbGFzcywgaHd5KSkgKyBnZW9tX2JveHBsb3QoKSBpcyB0aGF0IHRoZSBvcmRlcmluZyBvZiBjbGFzcyBpcyBhbHBoYWJldGljYWwsIHdoaWNoIGlzIG5vdCB0ZXJyaWJseSB1c2VmdWwuIEhvdyBjb3VsZCB5b3UgY2hhbmdlIHRoZSBmYWN0b3IgbGV2ZWxzIHRvIGJlIG1vcmUgaW5mb3JtYXRpdmU/DQpgYGB7ciwgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0xMX0NCnAxID0gZ2dwbG90KG1wZywgYWVzKGNsYXNzLCBod3kpKSArIGdlb21fYm94cGxvdCgpDQpwMiA9IGdncGxvdChtcGcsIGFlcyh4PXJlb3JkZXIoY2xhc3MsaHd5LEZVTiA9IG1lZGlhbikseT1od3kpKSArIGdlb21fYm94cGxvdCgpK2xhYnMoeD0gJ2NsYXNzJykNCmdyaWQuYXJyYW5nZShwMSwgcDIsIG5jb2wgPSAyKQ0KYGBgDQrsmbzsqr3snZgg6re4656Y7ZSE7LKY65+8IOyVjO2MjOuysyDsiJzsnLzroZwg67CV7Iqk7ZSM656P7J2EIOq3uOumsCDqsr3smrAsIOuztOq4sOuPhCDslrTroLXqs6Ag7ZWcIOuIiOyXkCDrjbDsnbTthLAg7YyM7JWF7J20IOyJveyngOyViuuLpC4g65Sw65287IScIOyYpOuluOyqveydmCDqt7jrprzsspjrn7wgbWVkaWFu7J2YIOqwkuydtCDsnpHsnYAg7Iic7ISc64yA66GcIOywqOuhgOuhnCDrsJXsiqTtlIzrno/snYQg6re466Ck7KO864qUIOqyg+ydtCDrs7TquLAg7KKL64ukLiByZW9yZGVyIG9wdGlvbuydhCDsgqzsmqntlZjsl6wgeOyZgCB57JeQIOuMgO2VtCDsnqzsoJXroKzsnYQg7ZW07KO87JeI7J2M7J2EIOy9lOuTnOulvCDthrXtlbQg7ZmV7J247ZWgIOyImCDsnojri6QuDQoNCiMjI1E2LiANCiMjIyBVc2luZyB0aGUgdGVjaG5pcXVlcyBhbHJlYWR5IGRpc2N1c3NlZCBpbiB0aGlzIGNoYXB0ZXIsIGNvbWUgdXAgd2l0aCB0aHJlZSB3YXlzIHRvIHZpc3VhbGl6ZSBhIDJkIGNhdGVnb3JpY2FsIGRpc3RyaWJ1dGlvbi4gVHJ5IHRoZW0gb3V0IGJ5IHZpc3VhbGlzaW5nIHRoZSBkaXN0cmlidXRpb24gb2YgbW9kZWwgYW5kIG1hbnVmYWN0dXJlciwgdHJhbnMgYW5kIGNsYXNzLCBhbmQgY3lsIGFuZCB0cmFucy4NCg0KIyMjI0NBU0UuMSBtb2RlbCBhbmQgbWFudWZhY3R1cmVyDQptb2RlbOqzvCBtYW51ZmFjdHVyZXLsl5Ag64yA7ZW0IOq3uOuemO2UhOulvCDqt7jrpqzquLAg7KCE7JeQIOuNsOydtO2EsOulvCDsoJXrpqztlZjsmIDri6QuDQpgYGB7cixlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTV9DQpkZjE8LWFzLmRhdGEuZnJhbWUoY2JpbmQobXBnJG1hbnVmYWN0dXJlcixtcGckbW9kZWwpKQ0KY29sbmFtZXMoZGYxKSA8LSBjKCJtYW51ZmFjdHVyZXIiLCJtb2RlbCIpDQpkZjI8LWFzLmRhdGEuZnJhbWUodGFibGUobXBnJG1vZGVsKSkNCmNvbG5hbWVzKGRmMikgPC0gYygibW9kZWwiLCJmcmVxIikNCm5ld190YWJsZXM8LWFzLmRhdGEuZnJhbWUodW5pcXVlKG1lcmdlKHg9ZGYxLHk9ZGYyLGJ5PSJtb2RlbCIpKSlbLGMoIm1hbnVmYWN0dXJlciIsIm1vZGVsIiwiZnJlcSIpXQ0KbmV3X3RhYmxlczwtYXJyYW5nZShuZXdfdGFibGVzLG1hbnVmYWN0dXJlcixkZXNjKGZyZXEpLG1vZGVsKQ0KbmFtZW9yZGVyIDwtIG5ld190YWJsZXMkbW9kZWxbb3JkZXIobmV3X3RhYmxlcyRtYW51ZmFjdHVyZXIsbmV3X3RhYmxlcyRmcmVxKV0NCm5ld190YWJsZXMkbW9kZWwgPC0gZmFjdG9yKG5ld190YWJsZXMkbW9kZWwsbGV2ZWxzID1uYW1lb3JkZXIpDQpuZXdfdGFibGVzDQpgYGANCuydtOugh+qyjCDsoJXrpqztlZwg642w7J207YSw66W8IOydtOyaqe2VmOyXrCDqt7jrnpjtlITrpbwg6re466as6rOg7J6QIO2VnOuLpC4g7J20IOuNsOydtO2EsOulvCDtkZztmITtlZjquLAg7JyE7ZW0ICLtgazrpqzruJTrnpzrk5wg7KCQIOq3uOuemO2UhChDbGV2ZWxhbmQgZG90IHBsb3QpIuydhCDrp4zrk6Tqs6DsnpAg7ZWc64ukLiDtgbTrpqzruJTrnpzrk5wg7KCQIOq3uOuemO2UhOuKlCDrs7TquLDsl5Ag642cIOyWtOyImOyEoO2VmOqzoCDrs7TquLAg7Ims7JuMIOunieuMgCDqt7jrnpjtlIQg64yA7Iug7JeQIOyCrOyaqeuQmOqzpCDtlZzri6QuIOyekOuPmeywqCDsoJzsobDsgqzrs4TroZwg66y27Ja07IScIOq1rOu2hOydhCDtlZjqs6AsIOq3uCDslYjsl5DshJwg66eO7J20IOyhsOyCrOuQnCDrqqjrjbjrs4TroZwgc29ydO2VmOyXrCDqt7jrprzsnYQg64KY7YOA64K066m0IOuLpOydjOqzvCDqsJnsnbQg7ZGc7ZiE7ZWgIOyImCDsnojri6QuIA0KDQpgYGB7cixlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMH0NCmdncGxvdChuZXdfdGFibGVzLCBhZXMoeD1mcmVxLHk9bW9kZWwpKSsNCiAgZ2VvbV9zZWdtZW50KGFlcyh5ZW5kPW1vZGVsKSx4ZW5kPTAsY29sb3VyPSJncmV5NTAiKSsNCiAgZ2VvbV9wb2ludChzaXplPTMsIGFlcyhjb2xvdXI9bWFudWZhY3R1cmVyKSkrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSkrDQogIGZhY2V0X2dyaWQobWFudWZhY3R1cmVyfi4sc2NhbGU9ImZyZWVfeSIsc3BhY2U9ImZyZWVfeSIpKw0KICB0aGVtZShzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGU9MCxmYWNlPSJib2xkIikpDQoNCmBgYA0KDQojIyMjQ0FTRS4yIHRyYW5zIGFuZCBjbGFzcw0KIOuylOyjvO2YlSDrs4DsiJjsnbggdHJhbnPsmYAgY2xhc3Prpbwg64+E7Iud7ZmU7ZWY6riwIOyghOyXkCDrkZAg67OA7IiY66W8IOygleumrO2VmOqzoCDtlbTri7ntlZjripQg67mI64+E7JeQIOuMgO2VtCDri6TsnYzqs7wg6rCZ7J20IO2RnOuhnCDsoJXrpqztlbTrs7TslZjri6QuIA0KYGBge3IsIGVjaG89VFJVRX0NCmRmMzwtYXMuZGF0YS5mcmFtZShjYmluZChtcGckdHJhbnMsbXBnJGNsYXNzKSkNCmNvbG5hbWVzKGRmMyk8LWMoInRyYW5zIiwiY2xhc3MiKQ0KdHJhbnNfY2xhc3M8LWFycmFuZ2UoZGYzLGZhY3Rvcih0cmFucyksY2xhc3MpDQp0YWJsZSh0cmFuc19jbGFzcykNCmBgYA0K7J20IHRhYmxl7J2EIOydtOyaqe2VmOyXrCBkYXRhIGZyYW1l7J2EIOygleydmO2VmOqzoCDsnbTrpbwg7J207Jqp7ZWY7JesIGhlYXRtYXDsnYQg64+E7Iud7ZmU7ZWY66m0IOyVhOuemOyZgCDqsJnqs6AsIOq3uOumvOydhCDrs7TrqbQg7JyE7J2YIHRhYmxl7J2EIOq3uOuMgOuhnCDsnpgg7ZGc7ZiE7ZW064OI7J2M7J2EIO2ZleyduO2VoCDsiJgg7J6I64ukLg0KYGBge3IsZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQ0KdHJfY2w8LWFzLmRhdGEuZnJhbWUodGFibGUodHJhbnNfY2xhc3MpKQ0KZ2dwbG90KHRyX2NsLGFlcyh4PWNsYXNzLCB5PXRyYW5zLCBmaWxsPUZyZXEpKSArIGdlb21fcmFzdGVyKCkgKyB5bGltKHJldihsZXZlbHModHJfY2wkdHJhbnMpKSkrDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93PSIjRkZDQ0ZGIiwgaGlnaD0iIzY2MDA2NiIpDQpgYGANCg0KIyMjI0NBU0UuMyBjeWwgYW5kIHRyYW5zDQrrp4jsp4Drp4nsnLzroZwg7Iuk66aw642U7IiYKGN5bCnqs7wg67OA7IaN6riwKHRyYW5zKSDsgqzsnbTsnZgg6rSA6rOE7JeQIOuMgO2VtCDqt7jrprzsnLzroZwg64KY7YOA64K06rOg7J6QIO2VnOuLpC4g67OA7IaN6riwIOuzgOyImOulvCDsgrTtjrQg67O066m0IO2BrOqyjCBhdXRv7JmAIG1hbnVhbOuhnCDrqoXsua3snbQg64KY64iE7Ja07KC4IOyeiOydjOydhCDslYwg7IiYIOyeiOuLpC4g7J2066W8IOqzoOugpO2VmOyXrCDsg4jroZzsmrQg642w7J207YSwIO2UhOugiOyehCDtmJXtg5zrpbwg66eM65Ok7Ja0IOuztOyVmOuLpC4NCmBgYHtyfQ0KYmlnX3RyYW5zIDwtIE5VTEwNCmZvciAoaSBpbiAxOmxlbmd0aCh0cmFucykpew0KICBpZihncmVwbChhdXRvLHRyYW5zW2ldKT09VFJVRSl7DQogICAgYmlnX3RyYW5zW2ldIDwtICJhdXRvIg0KICB9ZWxzZXsNCiAgICBiaWdfdHJhbnNbaV0gPC0gIm1hbnVhbCINCiAgfQ0KfQ0KDQp0cmRmPC1hcy5kYXRhLmZyYW1lKGNiaW5kKG1wZyR0cmFucywgbXBnJGN5bCwgYmlnX3RyYW5zKSkNCmNvbG5hbWVzKHRyZGYpPC1jKCJ0cmFucyIsImN5bCIsImF1dG9fbWFudWFsIikNCmF1dG9ncm91cDwtdGFibGUoYXJyYW5nZSh0cmRmLGZhY3Rvcih0cmFucyksY3lsLGF1dG9fbWFudWFsKSlbLCwxXVstYyg5OjEwKSxdDQptYW51YWxncm91cDwtdGFibGUoYXJyYW5nZSh0cmRmLGZhY3Rvcih0cmFucyksY3lsLGF1dG9fbWFudWFsKSlbLCwyXVstYygxOjgpLF0NCg0KYXV0b19kZjwtYXMuZGF0YS5mcmFtZShhdXRvZ3JvdXApDQptYW51YWxfZGY8LWFzLmRhdGEuZnJhbWUobWFudWFsZ3JvdXApDQoNCnByaW50KGF1dG9ncm91cCkNCnByaW50KG1hbnVhbGdyb3VwKQ0KYGBgDQog7JyE7LKY65+8IOuzgOyGjeq4sOydmCDqtazshLHsnbQg7J6Q64+Z6rO8IOyImOuPmeycvOuhnCDtgazqsowg65GQIOqwnOydmCDthYzsnbTruJTroZwg64KY64iE7JeI64ukLiDsnbTsoJwg7J2066W8IOydtOyaqe2VmOyXrCBoZWF0bWFw7LKY65+8IOuPhOyLne2ZlO2VmOyXrCDtkZztmITtlZjrqbQg64uk7J2M6rO8IOqwmeuLpC4NCg0KYGBge3J9DQphMTwtZ2dwbG90KGF1dG9fZGYsYWVzKHg9Y3lsLCB5PXRyYW5zLCBmaWxsPUZyZXEpKSArIGdlb21fcmFzdGVyKCkgKyB5bGltKHJldihsZXZlbHMoYXV0b19kZiR0cmFucykpKSsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9IiNDQ0NDQ0MiLCBoaWdoPSIjQ0MwMDAwIixsaW1pdHM9YygxLDM1KSxicmVha3M9YygwLDEwLDIwLDMwKSkrDQogIGdndGl0bGUoIkF1dG8gdHJhbnNtaXNzaW9uIGRpc3RyaWJ1dGlvbiIpDQoNCmEyPC1nZ3Bsb3QobWFudWFsX2RmLGFlcyh4PWN5bCwgeT10cmFucywgZmlsbD1GcmVxKSkgKyBnZW9tX3Jhc3RlcigpICsgeWxpbShyZXYobGV2ZWxzKG1hbnVhbF9kZiR0cmFucykpKSsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9IiNDQ0NDQ0MiLCBoaWdoPSIjQ0MwMDAwIixsaW1pdHM9YygwLDM1KSxicmVha3M9YygwLDEwLDIwLDMwKSkrDQogIGdndGl0bGUoIk1hbnVhbCB0cmFuc21pc3Npb24gZGlzdHJpYnV0aW9uIikNCg0KZ3JpZC5hcnJhbmdlKGExLCBhMiwgbnJvdyA9IDIpDQpgYGANCuychOydmCDqt7jrnpjtlITrpbwg67O066m0IOyekOuPmeuzgOyGjeq4sOyXkOyEnOuKlCBjeWzqsJzsiJjqsIAgNeqwnOyduCDssKjrn4nsnYAg6rGw7J2YIOyXhuyXiOqzoCwg64yA67aA67aE7J2YIGN5bOqwnOyImOyZgCDsg4HqtIDsl4bsnbQgYXV0byhJNCnrnbzripQg67OA7IaN6riwIOyiheulmOqwgCDqtIDsuKHsnbQg66eO7J20IOuQmOyXiOydjOydhCDrs7wg7IiYIOyeiOyXiOuLpC4g7IiY64+Z67OA7IaN6riw7JeQ7ISc64qUIGN5bOqwnOyImOqwgCA06rCc7J24IOqyveyasOqwgCDrp47slZjqs6AsIG017KKF66WY6rCAIG0267O064ukIOunjuydjOydhCDsi5zqsIHsoIHsnLzroZwg7ZmV7J247ZWgIOyImCDsnojsl4jri6Qu