PROJECT - Apartment Analysis
- Preprocessing
## 'data.frame': 807353 obs. of 28 variables:
## $ 거래금액 : int 100000 110000 26500 30000 25900 25300 25000 27900 27800 26800 ...
## $ 건축년도 : int 2008 2004 2005 1999 1993 1992 1993 1992 1992 1993 ...
## $ 년 : int 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 ...
## $ 도로명 : chr "사직로8길" "경희궁2길" "율곡로2길" "혜화로3길" ...
## $ 도로명건물본번호코드: int 4 5 7 5 198 19 198 19 19 198 ...
## $ 도로명건물부번호코드: int 0 5 0 0 0 0 0 0 0 0 ...
## $ 도로명시군구코드 : int 11110 11110 11110 11110 11110 11110 11110 11110 11110 11110 ...
## $ 도로명일련번호코드 : int 3 1 1 2 2 1 2 1 1 2 ...
## $ 도로명지상지하코드 : int 0 0 0 0 0 0 0 0 0 0 ...
## $ 도로명코드 : int 4100135 4100005 4100234 4100545 4100020 4100065 4100020 4100065 4100065 4100020 ...
## $ 법정동 : chr "사직동" "내수동" "수송동" "명륜2가" ...
## $ 법정동본번코드 : int 9 110 85 237 703 702 703 702 702 703 ...
## $ 법정동부번코드 : int 0 15 0 0 0 0 0 0 0 0 ...
## $ 법정동시군구코드 : int 11110 11110 11110 11110 11110 11110 11110 11110 11110 11110 ...
## $ 법정동읍면동코드 : int 11500 11800 12400 17100 17400 17400 17400 17400 17400 17400 ...
## $ 법정동지번코드 : chr "1" "1" "1" "1" ...
## $ 아파트 : chr "광화문풍림스페이스본(101동~105동)" "킹스매너" "로얄팰리스스위트" "아남3" ...
## $ 월 : int 1 1 1 1 1 1 1 1 1 1 ...
## $ 일 : int 20 8 11 13 5 7 8 11 15 18 ...
## $ 일련번호 : chr "11110-2203" "11110-118" "11110-205" "11110-26" ...
## $ 전용면적 : num 136.4 194.4 40.1 47.4 64.7 ...
## $ 지번 : chr "9" "110-15" "85" "237" ...
## $ 지역코드 : int 11110 11110 11110 11110 11110 11110 11110 11110 11110 11110 ...
## $ 층 : int 7 6 8 4 3 2 11 11 13 11 ...
## $ qrt : chr "Q1" "Q1" "Q1" "Q1" ...
## $ yyyyqrt : chr "2010Q1" "2010Q1" "2010Q1" "2010Q1" ...
## $ 평수 : int 41 59 12 14 20 17 20 17 17 20 ...
## $ 평단가 : num 2439 1864 2208 2143 1295 ...
#----------------------------------------------------
# gsub ~바꾸기
#----------------------------------------------------
#gsub(' ','', df$???뜝?룞?삕??) -> df$???뜝?룞?삕??
#----------------------------------------------------
# Creating Columns using information
#----------------------------------------------------
#df[, -c(25,26,27,28)] -> df_1
#ifelse(df_1$?? < 4, 'Q1',
# ifelse(df_1$?? < 7, 'Q2',
# ifelse(df_1$?? < 10, 'Q3', 'Q4'))) -> df_1$qrt
#df_1$yyyyqrt <- paste0(df_1$??, df_1$qrt)
#df_1$???? <- round(df_1$????????/3.3)
#df_1$???訝?? <- df_1$??궧???셿?/df$????
분석 가설 설정 하기
서울 전체 아파트 VS 강남 아파트 가격의 변화 양상은 다를 것이다.
서울 전체 아파트 평균 평당 매매가 VS 강남구의 평균 평당 매매가
- 강남 아파트의 가격 변화에 따라서 가격이 변화하는 지역이 있을 것 이다.
반포동 3개월 이전까지의 추세와 유사한 지역을 탐색 - 계층적 군집 분석 수행
## # A tibble: 42 x 2
## yyyyqrt mean
## * <chr> <dbl>
## 1 2010Q1 2079.
## 2 2010Q2 1906.
## 3 2010Q3 1966.
## 4 2010Q4 2085.
## 5 2011Q1 1934.
## 6 2011Q2 1895.
## 7 2011Q3 1925.
## 8 2011Q4 1961.
## 9 2012Q1 1875.
## 10 2012Q2 1908.
## # ... with 32 more rows
ggplot(df.1, aes(yyyyqrt, mean, group=1))+
geom_line(size=0.7)+
geom_smooth(method = "lm", col= "indianred")+
theme(axis.text = element_text(angle=90))+
ylim(0, max(df.1$mean))+
theme(text = element_text(family = font),
legend.position = "none",
axis.ticks = element_blank(),
plot.background = element_rect("#EBEBEB"),
panel.background = element_blank(),
axis.title = element_text(color = "#292929", face = "bold"),
axis.text = element_text(color = "#292929", face = "bold"),
plot.subtitle = element_markdown(face = "bold", color = "#292929"),
strip.text.x = element_text(face = "bold", color = "#292929"),
strip.background = element_blank(),
panel.spacing = unit(2, "lines"))+
labs(x= "Year Quaters", y= "Means of price", title= "The Average price of apartment in Korea baed on Quarters")

가설 1 : 서울 전체 아파트와 강남 아파트 가격은 변화하는 양상이 다를 것이다.
서울 전체 VS 강남구 아파트 (반포, 서초, 삼성동, 압구정동)
library(ggthemes)
df%>%
filter(법정동 %in% c("반포동", "서초동?","삼성동","압구정동")) %>%
group_by(yyyyqrt, 년) %>%
summarise(mean = mean(평단가)) -> gangnam
ggplot(gangnam, aes(yyyyqrt, mean, group=1))+
geom_line(size=0.8, col="#EC1D27") +
geom_smooth(method = "lm", col= "cornflowerblue")+
ylim(0, max(gangnam$mean))+
theme(text = element_text(family = font),
legend.position = "none",
axis.ticks = element_blank(),
plot.background = element_rect("#EBEBEB"),
panel.background = element_blank(),
axis.title = element_text(color = "#292929", face = "bold"),
axis.text = element_text(color = "#292929", face = "bold"),
plot.subtitle = element_markdown(face = "bold", color = "#292929"),
strip.text.x = element_text(face = "bold", color = "#292929"),
strip.background = element_blank(),
panel.spacing = unit(2, "lines"))+
labs(x= "Year/Quarter", y= "Average Price", title= "The Average Price in Gangnam areas")+
theme(plot.title = element_text(family = font, face ="bold",size = 18, color = "grey20")) +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank())-> seoul_plot
seoul_plot

서초, 삼성, 압구정동의 각 평균 단가 시각화
#-----------------------------------------------------
# 서초동
#-----------------------------------------------------
df %>%
filter(법정동 == '서초동') %>%
group_by(yyyyqrt) %>%
summarise(price = mean(평단가)) %>%
ggplot(aes(yyyyqrt, price, group =1))+
geom_line(size=0.8, col="#EC1D27")+
geom_smooth(method = "lm", col= "cornflowerblue")+
theme(axis.text = element_text(angle=90))+
ylim(0, max(gangnam$mean))+
theme(text = element_text(family = font),
legend.position = "none",
axis.ticks = element_blank(),
plot.background = element_rect("#EBEBEB"),
panel.background = element_blank(),
axis.title = element_text(color = "#292929", face = "bold"),
axis.text = element_text(color = "#292929", face = "bold"),
plot.subtitle = element_markdown(face = "bold", color = "#292929"),
strip.text.x = element_text(face = "bold", color = "#292929"),
strip.background = element_blank(),
panel.spacing = unit(2, "lines"))+
labs(x= "Year/Quarter", y= "Average Price", title= "The Average Price in Seocho dong")+
theme(plot.title = element_text(family = font, face ="bold",size = 18, color = "grey20"))+
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank())->plot_1
df %>%
filter(법정동 == '삼성동') %>%
group_by(yyyyqrt) %>%
summarise(price = mean(평단가)) %>%
ggplot(aes(yyyyqrt, price, group =1))+
geom_line(size=0.8, col="#EC1D27")+
geom_smooth(method = "lm", col= "cornflowerblue")+
theme(axis.text = element_text(angle=90))+
ylim(0, max(gangnam$mean))+
theme(text = element_text(family = font),
legend.position = "none",
axis.ticks = element_blank(),
plot.background = element_rect("#EBEBEB"),
panel.background = element_blank(),
axis.title = element_text(color = "#292929", face = "bold"),
axis.text = element_text(color = "#292929", face = "bold"),
plot.subtitle = element_markdown(face = "bold", color = "#292929"),
strip.text.x = element_text(face = "bold", color = "#292929"),
strip.background = element_blank(),
panel.spacing = unit(2, "lines"))+
labs(x= "Year/Quarter", y= "Average Price", title= "The Average Price in 삼성동")+
theme(plot.title = element_text(family = font, face ="bold",size = 18, color = "grey20")) +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank())-> plot_2
df %>%
filter(법정동 == '압구정동') %>%
group_by(yyyyqrt) %>%
summarise(price = mean(평단가)) %>%
ggplot(aes(yyyyqrt, price, group =1))+
geom_line(size=0.8, col="#EC1D27")+
geom_smooth(method = "lm", col= "cornflowerblue")+
theme(axis.text = element_text(angle=90))+
ylim(0, max(gangnam$mean))+
theme(text = element_text(family = font),
legend.position = "none",
axis.ticks = element_blank(),
plot.background = element_rect("#EBEBEB"),
panel.background = element_blank(),
axis.title = element_text(color = "#292929", face = "bold"),
axis.text = element_text(color = "#292929", face = "bold"),
plot.subtitle = element_markdown(face = "bold", color = "#292929"),
strip.text.x = element_text(face = "bold", color = "#292929"),
strip.background = element_blank(),
panel.spacing = unit(2, "lines"))+
labs(x= "Year/Quarter", y= "Average Price", title= "The Average Price in 압구정")+
theme(plot.title = element_text(family = font, face ="bold",size = 18, color = "grey20"))+
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank()) -> plot_3
plot_3


가설 2 : 2. 강남 아파트의 가격 변화에 따라서 가격이 변화하는 지역이 있을 것 이다.
분석 내용 가정: 2020년 가격하락세는 코로나 여파로 인한 일시적인 현상이며, 이전 수준을 회복할 것으로 예측 -> 2020년 이전의 데이터로 반포동과 유사한 추세지역을 찾기 -> 동별 가격 변화 추세로 계층적 군집 분석
각 동별 가격 추세의 상관관계를 유사도(거리)행렬로 사용
유사도 행렬로 계층적 군집분석
법정동 기준, 분기 발생이 없는 지역을 제거
반포동 데이터/ 반포동 미 데이터만 추려서 데이터 병함 (dcast 함수 사용 )
Cor 함수를 사용한 유사도 행렬 데이터 셋 준비

계층적 군집 분석 실행

반포동과 유사한 패턴을 보이는 지역을 확인
반포동과 유사한 패턴을 보이는 지역을 확인

반포동과 유사한 패턴의 지역 미래 가격 예측
2020년 초 거래 가격으로 수준으로 3개월 내 회복 예측
iii{r}
LS0tDQp0aXRsZTogIlByb2plY3RzIg0KYXV0aG9yOiAiRE9FVU4iDQpkYXRlOiAiMDMvMDMvMjAyMSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgICMgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgIyBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiAiZmxhdGx5Ig0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgY2FjaGUgPSBUUlVFKQ0KDQoNCg0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGV4dHJhZm9udCkNCmxpYnJhcnkoZ2d0ZXh0KQ0KbGlicmFyeShDYWlybykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkod2FmZmxlKQ0KDQoNCmBgYA0KDQoNCiMgVW5kZXJzdGFuZGluZyBEYXRhIEFuYWx5c2lzIHsudGFic2V0IH0NCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KDQpzZXR3ZCgiQzovVXNlcnMvQWRtaW5pc3RyYXRvci9EZXNrdG9wL1IgQW5hbHlzaXMvRmFzdCBDYW1wdXMiKQ0KDQpyZWdpb25fY2QgPC0gcmVhZC5jc3YoJ3JlZ2lvbl9jZC5jc3YnKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIGdyZXAxIDogDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiNyZWdpb25fY2QgJT4lIA0KIyAgZmlsdGVyKGdyZXBsKCc/Pz8/P+uThT8/Pz8nLCByZWdpb24pKSAtPiBMQVdEX0NEDQoNCiNMQVdEX0NEWywyXSAtPiBMQVdEX0NEDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyDsl7Av7JuUIOyDneyEsSANCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoNCm1lcmdlKGMoMjAxMDoyMDIwKSwgYygxOjEyKSkgLT4gdGVtcA0KDQoNCmlmX2Vsc2UodGVtcCR5IDwgMTAsIA0KICAgICAgICBwYXN0ZTAoMCwgdGVtcCR5KSwNCiAgICAgICAgYXMuY2hhcmFjdGVyKHRlbXAkeSkpIC0+IHRlbXAkeQ0KDQoNCg0KcGFzdGUwKHRlbXAkeCwgdGVtcCR5KSAlPiUgDQogIGFzLmludGVnZXIoKSAtPiBERUFMX1lNRA0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIEFQSSDtmZzsmqkg642w7J207YSwIOuBjOyWtOyYpOq4sCANCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoNCiNkZiA8LSBOVUxMIA0KDQojQVBJX0tFWSA8LSAnRjgyVnhSU3VxTk9DYkFqbVpwdEhyT3d5aW5PYjJjJTJCczNSWjRmcWpKTkw4eUNrd2dwb2hDT2MxNnFWQ0dxaSUyRiUyRm9BJTJCVXM3RkxvdGV0aGx0eDNSNXR4dyUzRCUzRCcNCiNsaWJyYXJ5KFhNTCkNCg0KDQojZm9yIChpIGluIExBV0RfQ0QpIHsNCiMjICBwcmludChpKQ0KIyAgZm9yIChsIGluIERFQUxfWU1EKSB7DQogICAgDQojICAgIHVybCA8LSBwYXN0ZTAoJ2h0dHA6Ly9vcGVuYXBpLm1vbGl0LmdvLmtyL09wZW5BUElfVG9vbEluc3RhbGxQYWNrYWdlL3NlcnZpY2UvcmVzdC9SVE1TT0JKU3ZjL2dldFJUTVNEYXRhU3ZjQXB0VHJhZGVEZXY/X3dhZGwmdHlwZT14bWwnKQ0KICAgIA0KIyAgICByYXcuZGF0YSA8LXhtbFRyZWVQYXJzZSh1cmwsIHVzZUludGVybmFsTm9kZXMgPSBUUlVFKQ0KIyAgICB4bWxfcm9vdE5vZGUgPC0gdHJ5KHhtbFJvb3QocmF3LmRhdGEpKQ0KIyAgICB4bWxfcmVzdWx0IDwtIHhtbFRvRGF0YUZyYW1lKHhtbF9yb290Tm9kZVtbMl1dW1snaXRlbXMnXV0pDQojICAgIGRmIDwtIHJiaW5kKGRmLCB4bWxfcmVzdWx0KQ0KICAgIA0KIyAgfQ0KI30NCg0KYGBgDQoNCg0KIyBQUk9KRUNUIC0gQXBhcnRtZW50IEFuYWx5c2lzDQoNCjEuIFByZXByb2Nlc3NpbmcgDQoNCmBgYHtyfQ0KDQoNCnNldHdkKCJDOi9Vc2Vycy9BZG1pbmlzdHJhdG9yL0Rlc2t0b3AvUiBBbmFseXNpcyIpDQpyZWFkLmNzdignYXB0X2RhdGFfMjAxMF8yMDIwLmNzdicpLT4gZGYNCnN0cihkZikNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgZ3N1YiB+67CU6r646riwIA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KI2dzdWIoJyAnLCcnLCBkZiQ/Pz/rnJ0/66OeP+yClT8/KSAtPiBkZiQ/Pz/rnJ0/66OeP+yClT8/DQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICAgIENyZWF0aW5nIENvbHVtbnMgdXNpbmcgaW5mb3JtYXRpb24gDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojZGZbLCAtYygyNSwyNiwyNywyOCldIC0+IGRmXzENCg0KI2lmZWxzZShkZl8xJD8/IDwgNCwgJ1ExJywgDQojICAgICAgIGlmZWxzZShkZl8xJD8/IDwgNywgJ1EyJywgDQojICAgICAgICAgICAgICBpZmVsc2UoZGZfMSQ/PyA8IDEwLCAnUTMnLCAnUTQnKSkpIC0+IGRmXzEkcXJ0DQoNCg0KI2RmXzEkeXl5eXFydCA8LSBwYXN0ZTAoZGZfMSQ/PywgZGZfMSRxcnQpDQoNCg0KI2RmXzEkPz8/PyA8LSByb3VuZChkZl8xJD8/Pz8/Pz8/LzMuMykNCg0KDQojZGZfMSQ/Pz/oqJ0/PyA8LSBkZl8xJD8/6ranPz8/7IW/Py9kZiQ/Pz8/DQoNCmBgYA0KDQoNCjIuIOu2hOyEnSDqsIDshKQg7ISk7KCVIO2VmOq4sCANCg0KICAxLiDshJzsmrgg7KCE7LK0IOyVhO2MjO2KuCBWUyDqsJXrgqgg7JWE7YyM7Yq4IOqwgOqyqeydmCDrs4DtmZQg7JaR7IOB7J2AIOuLpOulvCDqsoPsnbTri6QuIA0KICANCiAgPiDshJzsmrgg7KCE7LK0IOyVhO2MjO2KuCDtj4nqt6Ag7Y+J64u5IOunpOunpOqwgCBWUyDqsJXrgqjqtazsnZgg7Y+J6regIO2PieuLuSDrp6Trp6TqsIANCiAgDQogDQogIDIuIOqwleuCqCDslYTtjIztirjsnZgg6rCA6rKpIOuzgO2ZlOyXkCDrlLDrnbzshJwg6rCA6rKp7J20IOuzgO2ZlO2VmOuKlCDsp4Dsl63snbQg7J6I7J2EIOqygyDsnbTri6QuIA0KICANCiAgPiDrsJjtj6zrj5kgM+qwnOyblCDsnbTsoITquYzsp4DsnZgg7LaU7IS47JmAIOycoOyCrO2VnCDsp4Dsl63snYQg7YOQ7IOJIC0g6rOE7Li17KCBIOq1sOynkSDrtoTshJ0g7IiY7ZaJIA0KDQpgYGB7cn0NCg0KZm9udCA8LSJSb2JvdG8gQ29uZGVuc2VkIg0KDQpkZiAlPiUgIA0KICBncm91cF9ieSh5eXl5cXJ0KSAlPiUgIA0KICBzdW1tYXJpc2UobWVhbiA9IG1lYW4o7Y+J64uo6rCAKSkgLT4gZGYuMQ0KDQpkZi4xDQoNCmdncGxvdChkZi4xLCBhZXMoeXl5eXFydCwgbWVhbiwgZ3JvdXA9MSkpKyANCiAgZ2VvbV9saW5lKHNpemU9MC43KSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sPSAiaW5kaWFucmVkIikrIA0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoYW5nbGU9OTApKSsNCiAgeWxpbSgwLCBtYXgoZGYuMSRtZWFuKSkrDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gZm9udCksIA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgiI0VCRUJFQiIpLA0KICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIiMyOTI5MjkiLCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIiMyOTI5MjkiLCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfbWFya2Rvd24oZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiIzI5MjkyOSIpLA0KICAgICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiIzI5MjkyOSIpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgyLCAibGluZXMiKSkrIA0KICBsYWJzKHg9ICJZZWFyIFF1YXRlcnMiLCB5PSAiTWVhbnMgb2YgcHJpY2UiLCB0aXRsZT0gIlRoZSBBdmVyYWdlIHByaWNlIG9mIGFwYXJ0bWVudCBpbiBLb3JlYSBiYWVkIG9uIFF1YXJ0ZXJzIikNCmBgYA0KDQoNCuqwgOyEpCAxIDog7ISc7Jq4IOyghOyytCDslYTtjIztirjsmYAg6rCV64KoIOyVhO2MjO2KuCDqsIDqsqnsnYAg67OA7ZmU7ZWY64qUIOyWkeyDgeydtCDri6Trpbwg6rKD7J2064ukLiANCg0KICAgICAgICANCiAgICAgICAg7ISc7Jq4IOyghOyytCBWUyDqsJXrgqjqtawg7JWE7YyM7Yq4ICjrsJjtj6wsIOyEnOy0iCwg7IK87ISx64+ZLCDslZXqtazsoJXrj5kpDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KGdndGhlbWVzKQ0KDQoNCmRmJT4lICANCiAgZmlsdGVyKOuyleygleuPmSAlaW4lIGMoIuuwmO2PrOuPmSIsICLshJzstIjrj5k/Iiwi7IK87ISx64+ZIiwi7JWV6rWs7KCV64+ZIikpICU+JSANCiAgZ3JvdXBfYnkoeXl5eXFydCwg64WEKSAlPiUgDQogIHN1bW1hcmlzZShtZWFuID0gbWVhbijtj4nri6jqsIApKSAtPiBnYW5nbmFtDQoNCg0KDQoNCmdncGxvdChnYW5nbmFtLCBhZXMoeXl5eXFydCwgbWVhbiwgZ3JvdXA9MSkpKyANCiAgZ2VvbV9saW5lKHNpemU9MC44LCBjb2w9IiNFQzFEMjciKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbD0gICJjb3JuZmxvd2VyYmx1ZSIpKw0KICB5bGltKDAsIG1heChnYW5nbmFtJG1lYW4pKSsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSBmb250KSwgDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KCIjRUJFQkVCIiksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiIzI5MjkyOSIsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiIzI5MjkyOSIsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF9tYXJrZG93bihmYWNlID0gImJvbGQiLCBjb2xvciA9ICIjMjkyOTI5IiksDQogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBjb2xvciA9ICIjMjkyOTI5IiksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDIsICJsaW5lcyIpKSsgDQogIGxhYnMoeD0gIlllYXIvUXVhcnRlciIsIHk9ICJBdmVyYWdlIFByaWNlIiwgdGl0bGU9ICJUaGUgQXZlcmFnZSBQcmljZSBpbiBHYW5nbmFtIGFyZWFzIikrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gZm9udCwgZmFjZSA9ImJvbGQiLHNpemUgPSAxOCwgY29sb3IgPSAiZ3JleTIwIikpICsNCiAgICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpLT4gc2VvdWxfcGxvdA0KDQoNCnNlb3VsX3Bsb3QNCmBgYA0KDQoNCuyEnOy0iCwg7IK87ISxLCDslZXqtazsoJXrj5nsnZgg6rCBIO2Pieq3oCDri6jqsIAg7Iuc6rCB7ZmUIA0KDQpgYGB7cn0NCg0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgICAg7ISc7LSI64+ZIA0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCmRmICU+JSAgDQogIGZpbHRlcijrspXsoJXrj5kgPT0gJ+yEnOy0iOuPmScpICU+JSANCiAgZ3JvdXBfYnkoeXl5eXFydCkgJT4lIA0KICBzdW1tYXJpc2UocHJpY2UgPSBtZWFuKO2PieuLqOqwgCkpICU+JSANCiAgZ2dwbG90KGFlcyh5eXl5cXJ0LCBwcmljZSwgZ3JvdXAgPTEpKSsgDQogIGdlb21fbGluZShzaXplPTAuOCwgY29sPSIjRUMxRDI3IikrDQogICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2w9ICAiY29ybmZsb3dlcmJsdWUiKSsNCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSkrDQogIHlsaW0oMCwgbWF4KGdhbmduYW0kbWVhbikpKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9IGZvbnQpLCANCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoIiNFQkVCRUIiKSwNCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjMjkyOTI5IiwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjMjkyOTI5IiwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X21hcmtkb3duKGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gIiMyOTI5MjkiKSwNCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gIiMyOTI5MjkiKSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMiwgImxpbmVzIikpKyANCiAgbGFicyh4PSAiWWVhci9RdWFydGVyIiwgeT0gIkF2ZXJhZ2UgUHJpY2UiLCB0aXRsZT0gIlRoZSBBdmVyYWdlIFByaWNlIGluIFNlb2NobyBkb25nIikrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gZm9udCwgZmFjZSA9ImJvbGQiLHNpemUgPSAxOCwgY29sb3IgPSAiZ3JleTIwIikpKw0KICAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpKS0+cGxvdF8xDQoNCg0KZGYgJT4lICANCiAgZmlsdGVyKOuyleygleuPmSA9PSAn7IK87ISx64+ZJykgJT4lIA0KICBncm91cF9ieSh5eXl5cXJ0KSAlPiUgDQogIHN1bW1hcmlzZShwcmljZSA9IG1lYW4o7Y+J64uo6rCAKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHl5eXlxcnQsIHByaWNlLCBncm91cCA9MSkpKyANCiAgZ2VvbV9saW5lKHNpemU9MC44LCBjb2w9IiNFQzFEMjciKSsNCiAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbD0gICJjb3JuZmxvd2VyYmx1ZSIpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoYW5nbGU9OTApKSsNCiAgeWxpbSgwLCBtYXgoZ2FuZ25hbSRtZWFuKSkrDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gZm9udCksIA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgiI0VCRUJFQiIpLA0KICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIiMyOTI5MjkiLCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIiMyOTI5MjkiLCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfbWFya2Rvd24oZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiIzI5MjkyOSIpLA0KICAgICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiIzI5MjkyOSIpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgyLCAibGluZXMiKSkrIA0KICBsYWJzKHg9ICJZZWFyL1F1YXJ0ZXIiLCB5PSAiQXZlcmFnZSBQcmljZSIsIHRpdGxlPSAiVGhlIEF2ZXJhZ2UgUHJpY2UgaW4g7IK87ISx64+ZIikrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gZm9udCwgZmFjZSA9ImJvbGQiLHNpemUgPSAxOCwgY29sb3IgPSAiZ3JleTIwIikpICsNCiAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSktPiBwbG90XzINCg0KDQpkZiAlPiUgIA0KICBmaWx0ZXIo67KV7KCV64+ZID09ICfslZXqtazsoJXrj5knKSAlPiUgDQogIGdyb3VwX2J5KHl5eXlxcnQpICU+JSANCiAgc3VtbWFyaXNlKHByaWNlID0gbWVhbijtj4nri6jqsIApKSAlPiUgDQogIGdncGxvdChhZXMoeXl5eXFydCwgcHJpY2UsIGdyb3VwID0xKSkrIA0KICBnZW9tX2xpbmUoc2l6ZT0wLjgsIGNvbD0iI0VDMUQyNyIpKw0KICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sPSAgImNvcm5mbG93ZXJibHVlIikrDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCkpKw0KICB5bGltKDAsIG1heChnYW5nbmFtJG1lYW4pKSsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSBmb250KSwgDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KCIjRUJFQkVCIiksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiIzI5MjkyOSIsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiIzI5MjkyOSIsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF9tYXJrZG93bihmYWNlID0gImJvbGQiLCBjb2xvciA9ICIjMjkyOTI5IiksDQogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBjb2xvciA9ICIjMjkyOTI5IiksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDIsICJsaW5lcyIpKSsgDQogIGxhYnMoeD0gIlllYXIvUXVhcnRlciIsIHk9ICJBdmVyYWdlIFByaWNlIiwgdGl0bGU9ICJUaGUgQXZlcmFnZSBQcmljZSBpbiAg7JWV6rWs7KCVIikrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gZm9udCwgZmFjZSA9ImJvbGQiLHNpemUgPSAxOCwgY29sb3IgPSAiZ3JleTIwIikpKw0KIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSkgLT4gcGxvdF8zDQogcGxvdF8zDQoNCg0KbGlicmFyeShncmlkRXh0cmEpDQoNCg0KDQpncmlkLmFycmFuZ2Uoc2VvdWxfcGxvdCwgcGxvdF8xLCBwbG90XzIsIHBsb3RfMywgbnJvdz0yLCBuY29sPTIpDQpgYGANCg0KDQoNCuqwgOyEpCAyIDogMi4g6rCV64KoIOyVhO2MjO2KuOydmCDqsIDqsqkg67OA7ZmU7JeQIOuUsOudvOyEnCDqsIDqsqnsnbQg67OA7ZmU7ZWY64qUIOyngOyXreydtCDsnojsnYQg6rKDIOydtOuLpC4gDQogIA0KICDrtoTshJ0g64K07JqpIA0KICAgIOqwgOyglTogMjAyMOuFhCDqsIDqsqntlZjrnb3shLjripQg7L2U66Gc64KYIOyXrO2MjOuhnCDsnbjtlZwg7J287Iuc7KCB7J24IO2YhOyDgeydtOupsCwg7J207KCEIOyImOykgOydhCANCiAgICAgICAgICDtmozrs7XtlaAg6rKD7Jy866GcIOyYiOy4oSANCiAgICAtPiAyMDIw64WEIOydtOyghOydmCDrjbDsnbTthLDroZwg67CY7Y+s64+Z6rO8IOycoOyCrO2VnCDstpTshLjsp4Dsl63snYQg7LC+6riwIA0KICAgIC0+IOuPmeuzhCDqsIDqsqkg67OA7ZmUIOy2lOyEuOuhnCDqs4TsuLXsoIEg6rWw7KeRIOu2hOyEnSANCiAgICANCiAgICDqsIEg64+Z67OEIOqwgOqyqSDstpTshLjsnZgg7IOB6rSA6rSA6rOE66W8IOycoOyCrOuPhCjqsbDrpqwp7ZaJ66Cs66GcIOyCrOyaqSANCiAgICDsnKDsgqzrj4Qg7ZaJ66Cs66GcIOqzhOy4teyggSDqtbDsp5HrtoTshJ0gDQogICAgICAgICAgDQoNCmBgYHtyfQ0KbGlicmFyeShUVFIpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KDQpkZiAlPiUgDQogIGZpbHRlcigheXl5eXFydCAlaW4lIGMoJzIwMjBRMScsJzIwMjBRMicpKSAtPiBkZi5maWwNCg0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgIOycoOyCrOuPhCDtlonroKwg642w7J207YSwIOyFiyDspIDruYQgDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KDQoNCmRmLmZpbCAlPiUgDQogIHNlbGVjdCjrspXsoJXrj5ksIHl5eXlxcnQs7Y+J64uo6rCAKSAlPiUNCiAgZ3JvdXBfYnko67KV7KCV64+ZLHl5eXlxcnQpICU+JSANCiAgc3VtbWFyaXNlKHByaWNlID0gcm91bmQobWVhbijtj4nri6jqsIApLDMpKSAlPiUgDQogIG11dGF0ZShtYTMgPSByb3VuZChydW5NZWFuKHByaWNlLDMpLDMpKSAlPiUgICPsnbTrj5ntj4nqt6AgMyDqs4TsgrAgDQogIG5hLm9taXQoKSAtPiBkZi50cw0KDQoNCkRUOjpkYXRhdGFibGUoZGYudHMpDQoNCmBgYA0KDQoNCjEuIOuyleygleuPmSDquLDspIAsIOu2hOq4sCDrsJzsg53snbQg7JeG64qUIOyngOyXreydhCDsoJzqsbAgDQoNCg0KMi4g67CY7Y+s64+ZIOuNsOydtO2EsC8g67CY7Y+s64+ZIOuvuCDrjbDsnbTthLDrp4wg7LaU66Ck7IScIOuNsOydtO2EsCDrs5HtlaggKGRjYXN0IO2VqOyImCDsgqzsmqkgKQ0KYGBge3J9DQoNCg0KDQoNCmRmLnRzICU+JSANCiAgZ3JvdXBfYnko67KV7KCV64+ZKSAlPiUgDQogIHN1bW1hcmlzZShjbnQgPSBuX2Rpc3RpbmN0KHl5eXlxcnQpKSAlPiUgDQogIGZpbHRlcihjbnQgPT0gMzgpICU+JSANCiAgc2VsZWN0KOuyleygleuPmSkgLT4gZG9uZy5saXN0DQoNCg0KDQojIOuwmO2PrOuPmeunjCDstpTstpwgDQoNCmRmLnRzLmJhbnBvIDwtIGRmLnRzICU+JSAgZmlsdGVyKOuyleygleuPmSA9PSAn67CY7Y+s64+ZJykNCg0KDQojIOuwmO2PrOuPmSDsoJzsmbgg7LaU7LacIA0KZGYudHMgPC0gZGYudHMgJT4lIGZpbHRlcijrspXsoJXrj5kgJWluJSBkb25nLmxpc3Qk67KV7KCV64+ZLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICDrspXsoJXrj5kgIT0gJ+uwmO2PrOuPmScpDQoNCg0KDQojIOuwmO2PrOuPmSDsoJzsmbgg7LaU7LacIGRjYXN0IOuzgO2ZmCANCmRjYXN0KGRmLnRzLCB5eXl5cXJ0IH4g67KV7KCV64+ZKSAtPiBkY2FzdA0KDQpkY2FzdFssLTFdIC0+IGNvbWxlX2RjYXN0DQoNCg0KDQogDQpkY2FzdChkZi50cy5iYW5wbywgeXl5eXFydCB+IOuyleygleuPmSkgLT4gZGNhc3RfYmFucG8NCmRjYXN0X2JhbnBvWywtMV0gLT4gY29tcGxlX2RjYXN0X2JhbnBvDQoNCg0KY2JpbmQoY29tbGVfZGNhc3QsIGNvbXBsZV9kY2FzdF9iYW5wbykgLT4gZGYudHJlbmQNCg0KDQoNCmBgYA0KDQpDb3Ig7ZWo7IiY66W8IOyCrOyaqe2VnCDsnKDsgqzrj4Qg7ZaJ66CsIOuNsOydtO2EsCDshYsg7KSA67mEIA0KDQpgYGB7cn0NCg0KY29yKGRmLnRyZW5kKSAtPiBkZi5jb3INCmhlYXRtYXAoZGYuY29yKQ0KYGBgDQoNCg0K6rOE7Li17KCBIOq1sOynkSDrtoTshJ0g7Iuk7ZaJIA0KDQpgYGB7cn0NCg0KDQpoY2x1c3QoYXMuZGlzdChkZi5jb3IpLCBtZXRob2QgPSAnd2FyZC5EMicpIC0+IGhjDQoNCnBsb3QoaGMsIGhhbmc9LTEsIGNleD0wLjM1KQ0KDQpgYGANCg0KDQrrsJjtj6zrj5nqs7wg7Jyg7IKs7ZWcIO2MqO2EtOydhCDrs7TsnbTripQg7KeA7Jet7J2EIO2ZleyduCANCg0KDQpgYGB7cn0NCg0KZGYuY29yWzE5NywgMToxOTddICU+JSAgYXMuZGF0YS5mcmFtZSgpIC0+IGNvci5iYW5wbw0KDQoNCmBgYA0KDQrrsJjtj6zrj5nqs7wg7Jyg7IKs7ZWcIO2MqO2EtOydhCDrs7TsnbTripQg7KeA7Jet7J2EIO2ZleyduCANCg0KYGBge3J9DQoNCnBhcihtZnJvdyA9IChjKDIsMykpKQ0KDQpwbG90KGRmLnRyZW5kJGNvbXBsZV9kY2FzdF9iYW5wbywgdHlwZSA9ICdsJykNCnBsb3QoZGYudHJlbmQk7JaR7Y+J64+ZNeqwgCwgdHlwZSA9ICdsJykNCnBsb3QoZGYudHJlbmQk7IKs64u564+ZLCB0eXBlID0gJ2wnKQ0KcGxvdChkZi50cmVuZCTrrLjrnpjrj5k26rCALCB0eXBlID0gJ2wnKQ0KcGxvdChkZi50cmVuZCTqsIDrnb3rj5ksIHR5cGUgPSAnbCcpDQpwbG90KGRmLnRyZW5kJOqwgOyCsOuPmSwgdHlwZSA9ICdsJykNCmBgYA0KDQoNCuuwmO2PrOuPmeqzvCDsnKDsgqztlZwg7Yyo7YS07J2YIOyngOyXrSDrr7jrnpgg6rCA6rKpIOyYiOy4oSANCg0KMjAyMOuFhCDstIgg6rGw656YIOqwgOqyqeycvOuhnCDsiJjspIDsnLzroZwgM+qwnOyblCDrgrQg7ZqM67O1IOyYiOy4oSANCg0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQppaWlgYGB7cn0NCmBgYA0KDQoNCg==