“18:28:40, 02 - 03 - 2024”
***

0.1 Giới thiệu về nguồn gốc của bộ dữ liệu Diamonds.

  • Diamonds là một trong các dữ bộ dữ liệu của packages ggplot2.
  • Trong bài viết này chúng ta sẽ gán diamonds thành r.
  • ggplot2 là một packages hỗ trợ vẽ các dạng đồ thị như bar chart,histogram,pie,…
  • Khi dùng ggplot2 để vẽ đồ thị chúng ta có:
    • ggplot():chỉ định phần dữ liệu dùng để vẽ đồ thị.
    • geom_: chỉ định dạng đồ thị cần vẽ.

0.2 Giới thiệu về bộ dữ liệu diamonds

library(ggplot2)
str(diamonds)
## tibble [53,940 × 10] (S3: tbl_df/tbl/data.frame)
##  $ carat  : num [1:53940] 0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
##  $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...
##  $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2 5 ...
##  $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4 5 ...
##  $ depth  : num [1:53940] 61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
##  $ table  : num [1:53940] 55 61 65 58 58 57 57 55 61 61 ...
##  $ price  : int [1:53940] 326 326 327 334 335 336 336 337 337 338 ...
##  $ x      : num [1:53940] 3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
##  $ y      : num [1:53940] 3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
##  $ z      : num [1:53940] 2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...
names(diamonds)
##  [1] "carat"   "cut"     "color"   "clarity" "depth"   "table"   "price"  
##  [8] "x"       "y"       "z"
library(skimr)
skim(diamonds)
Data summary
Name diamonds
Number of rows 53940
Number of columns 10
_______________________
Column type frequency:
factor 3
numeric 7
________________________
Group variables None

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
cut 0 1 TRUE 5 Ide: 21551, Pre: 13791, Ver: 12082, Goo: 4906
color 0 1 TRUE 7 G: 11292, E: 9797, F: 9542, H: 8304
clarity 0 1 TRUE 8 SI1: 13065, VS2: 12258, SI2: 9194, VS1: 8171

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
carat 0 1 0.80 0.47 0.2 0.40 0.70 1.04 5.01 ▇▂▁▁▁
depth 0 1 61.75 1.43 43.0 61.00 61.80 62.50 79.00 ▁▁▇▁▁
table 0 1 57.46 2.23 43.0 56.00 57.00 59.00 95.00 ▁▇▁▁▁
price 0 1 3932.80 3989.44 326.0 950.00 2401.00 5324.25 18823.00 ▇▂▁▁▁
x 0 1 5.73 1.12 0.0 4.71 5.70 6.54 10.74 ▁▁▇▃▁
y 0 1 5.73 1.14 0.0 4.72 5.71 6.54 58.90 ▇▁▁▁▁
z 0 1 3.54 0.71 0.0 2.91 3.53 4.04 31.80 ▇▁▁▁▁
  • Sau khi dùng lệnh lệnh str() và names(), ta thu được thông tin của bộ dữ liệu Diamonds gồm có:

  • 10 cột có tên lần lượt là: carat, cut, color, clarity, depth, table, price, x, y, z.

  • 53,940 quan sát

    • Mỗi một quan sát tương ứng với 1 viên kim cương.
    • 10 biến tương ứng với các đặc tính của kim cương.
  • Giải thích đặc tính:

  • Carat:Trọng lượng của viên kim cương (gram)

  • Cut: giác cắt tạo ra khi xử lý kim cương thô.

  • Color: màu của viên kim cương.

  • Clarity: độ tinh khiết của kim cương.

  • Depth: độ sâu của kim cương.

  • Table :Bề mặt của kim cương nằm ở trên đỉnh kim cương.

  • Price: giá thành của kim cương.

  • x: chiều dài của kim cương.

  • y: chiều rộng kim cương.

  • z: Chiều cao kim cương.

  • Công cụ vẽ đồ thị:

  • Dùng packages ggplot2.

  • Câu lệnh geom_bar: vẽ đồ thị dạng bar, tương tự với các dạng biểu đồ column, histogram,…
    +Labs: dùng để đặt tên, ví dụ như là các trục x,y và title: đặt tên cho biểu đồ.
    +Fill: chọn màu cho biểu đồ.

  • aes: xác định dữ liệu cần vẽ biểu đồ.
    +Group_by:phân nhóm dữ liệu.
    +Summarise: Tạo biến mới.

  • mean: trung bình

  • median: trung vị

  • var: phương sai

0.3 Vẽ biểu đồ cột color theo dạng đồ thị bar.

Trong bộ dữ liệu Diamonds, kim cương có 7 màu sắc, chúng được phân vào hai cấp độ màu sắc khác nhau:
+D,E,F: cấp độ không màu (Colorless)
+G,H,I,J: Cấp độ gần như không màu(Near Colorless)
+Dưới đây là số lượng viên kim cương của mỗi màu:

table(diamonds$color)
## 
##     D     E     F     G     H     I     J 
##  6775  9797  9542 11292  8304  5422  2808

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(magrittr)
library(scales)
r <- diamonds
r %>% ggplot(aes(x = color)) +
    geom_bar(fill='green') +
    labs(x = 'Loại', y = 'Số lượng', title = 'Color of Diamonds')

  • Quan sát biểu đồ trên, ta thấy được:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 1500.
    • Đồ thị tên là Color of Diamonds.
    • Cột x là Loại (D,E,F,G,H,I,J), cột y là Số lượng.
    • Cột G là cột có số lượng nhiều nhất (11292).
    • Cột J là cột có số lượng nhỏ nhất ( 2808).
    • Khi so sánh hai màu G và J ta thấy màu G gần bằng 4 lần màu J.
    • Dựa vào biểu đồ ta thấy rõ số kim cương không màu ít hơn kim cương gần như không màu.

0.4 Vẽ đồ thị cột cut theo dạng đồ thị bar.

Giác cắt kim cương_yếu tố quang trọngđể đánh giá 1 viên kim cương có đẹp hay không.
* Người ta lập ra 1 thang đo nhằm đánh giá giác cắt kim cương theo 2 tiêu chí là tỷ lệ và góc độ của mặt cắt:
+ Ideal: mức độ lý tưởng
+Premium: mức độ tuyệt vời
+Very Good: mức độ rất tốt
+Good: mức độ tốt
+Fair: mức độ trung bình
* Số lương viên kim cương của mỗi loại mặt cắt:

table(r$cut)
## 
##      Fair      Good Very Good   Premium     Ideal 
##      1610      4906     12082     13791     21551
r %>% ggplot(aes(x = cut)) +
    geom_bar(fill='pink') +
    labs(x = 'Mặt cắt kim cương', y= 'Số lượng' , title = 'Cut of Diamonds')

  • Quan sát đồ thị trên:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 2500.
    • Đồ thị tên là Cut of Diamonds.
    • Cột x là Loại mặt cắt (Fair,Good, Very Good, Premium, Ideal), cột y là Số lượng.
    • Cột Ideal có số lượng nhiều nhất (21551)
      +Mặt cắt Ideal chiếm gần nửa số lượng quan sát. +Khi chế tác các viên kim cương, người thợ luôn phải tính toán tỉ mỉ trước khi chế tác, nên loại Ideal cut chiếm số lượng nhiều.
    • Cột Fair có số lượng ít nhất (1610)
    • Nhìn vào biểu đồ ta thấy số lượng mỗi lại tăng dần theo thứ tự loại mặt cắt.

0.5 Vẽ biểu đồ cột carat theo dạng bar.

Ta có thể xác định trọng lượng của viên kim cương bằng cân điện tử, việc xác định trọng lượng rất quan trọng trọng việc đánh giá giá thành của viên kim cương.

r %>% ggplot(aes(x = carat)) +
    geom_bar(fill='purple') +
    labs(x = 'carat', y= 'Số lượng' , title = 'Carat of Diamonds')

  • Nhận xét:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 500.
    • Đồ thị tên là Carat of Diamonds.
    • Cột x là carat(0.23,0.,…), cột y là Số lượng.
    • Cột khoảng từ 0 đến 0.5 có số lượng nhiều nhất
    • Cột từ 4 đến5 có số lượng ít nhất
    • Nhìn vào biểu đồ ta thấy số lượng mỗi lại giảm dần theo thứ tự loại mặt cắt.

0.6 Vẽ biểu đồ clarity theo dạng bar.

Thang đo độ tinh khiết của kim cương:

  • Internally Flawless ( kim cương độ sạch IF ): không nhìn thấy tạp chất bên trong mà chỉ có một vài vết mờ trên bề mặt của nó. Độ tinh khiết IF của kim cương được đánh giá là tuyệt vời.

  • Very Very Slightly Included ( độ trong kim cương VVS1, VVS2 ): các tạp chất bên trong cực kỳ nhỏ và khó nhìn thấy dưới kính hiển vi đá quý có độ phóng đại 10 lần. Độ tinh khiết khi rơi vào nhóm này được đánh giá cao.

  • Very Slightly Included (Độ sạch kim cương VS1, VS2): có các tạp chất rất nhỏ, có thể nhìn thấy dưới độ phóng đại 10 lần. khi rơi vào nhóm này độ tinh khiết được đánh giá trên mức trung bình.

  • Slightly Included ( Độ tinh khiết kim cương SI1, SI2 ): kim cương có các tạp chất dễ nhận thấy dưới độ phóng đại 10 lần. Độ tinh khiết của nhóm này được đánh giá ở mức trung bình.

  • Included ( Độ sạch của kim cương I1– I3 ): các tạp chất rõ ràng có thể nhìn thấy bằng mắt thường

  • Số lượng kim cương của mỗi clarrity:

table(r$color)
## 
##     D     E     F     G     H     I     J 
##  6775  9797  9542 11292  8304  5422  2808

r %>% ggplot(aes(x = clarity)) +
    geom_bar(fill='red') +
    labs(x = 'độ trong', y= 'Số lượng' , title = 'Clarity of Diamonds')

  • Quan sát đồ thị trên:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 2500.
    • Đồ thị tên là Clarity of Diamonds.
    • Cột x là độ trong (I1,SI2,SI1,VS2,VS1,VVS2.VVS1.IF), cột y là Số lượng.
    • Cột SI1 có số lượng nhiều nhất (13065), những viên kim cương chứa tạp chất dễ thấy chiếm số lượng nhiều.
    • Cột I1 có số lượng ít nhất (741)
    • Số lượng kim cương SI1 gấp 10 lần so với I1
    • Số lượng kim cương chênh lệch giữa các mức độ không quá nhiều.

0.7 Vẽ biểu đồ cột depth theo dạng bar.

r %>% ggplot(aes(x = depth)) +
    geom_bar(fill='blue') +
    labs(x = 'độ sâu', y= 'Số lượng' , title = 'Depth of Diamonds')

  • Quan sát đồ thị trên:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 500.
    • Đồ thị tên là Depth of Diamonds.
    • Cột x là độ sâu (50 ~ 80), cột y là Số lượng.
    • Đa phần các giá trị có độ sâu từ 60 ~ 63.
    • Các cột còn lại có các quan sát nhưng không nhiều.

0.8 Vẽ biểu đồ cột table theo dạng bar.

r %>% ggplot(aes(x = table)) +
    geom_bar(fill='black') +
    labs(x = 'table', y= 'Số lượng' , title = 'table of Diamonds')

  • Quan sát đồ thị trên:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 2500.
    • Đồ thị tên là Table of Diamonds.
    • Cột x table, cột y là Số lượng.
    • Đa phần các giá trị có độ sâu từ 50 ~ 60.
    • Các cột còn lại có các quan sát nhưng không nhiều.

0.9 Vẽ biểu đồ cột price theo dạng bar.

r %>% ggplot(aes(x = price)) +
    geom_bar(fill='brown') +
    labs(x = 'giá', y= 'Số lượng' , title = 'price of Diamonds')

  • Quan sát đồ thị trên:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 50.
    • Đồ thị tên là Price of Diamonds.
    • Cột x là giá, cột y là Số lượng.
    • Đa phần các giá trị có độ sâu từ 1000 trở xuống.
    • Giá càng tăng số lượng càng ít.

0.10 Vẽ biểu đồ cột x theo dạng bar.

Phân loại x thành 2 nhóm ngắn và dài để dễ quan sát hơn

r %>% mutate(x1 = cut(x,2,label = c('ngắn','dài'))) %>% ggplot(aes(x = x1)) +
    geom_bar(fill='violet') + 
    labs(x = 'x', y= 'Số lượng' , title = 'X of Diamonds')

  • Quan sát đồ thị trên:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 50.
    • Đồ thị tên là X of Diamonds.
    • Cột x là x, cột y là Số lượng.
    • Cột dài có số lượng lớn hơn cột ngắn.

0.11 Vẽ biểu đồ cột y theo dạng bar.

Chia y thành 2 nhóm gồm lớn và nhỏ.

r %>% mutate(y1 = cut(y,2,label = c(' nhỏ','lớn'))) %>% ggplot(aes(x = y1)) +
    geom_bar(fill='salmon') + 
    labs(x = 'chiều rộng', y= 'Số lượng' , title = 'Y of Diamonds')

  • Quan sát đồ thị trên:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 50.
    • Đồ thị tên là Y of Diamonds.
    • Cột x là y, cột y là Số lượng.
    • Cột nhỏ có số lượng nhiều hơn
    • Cột còn lại có các quan sát nhưng không nhiều.

0.12 Vẽ biểu đồ cột z theo dạng bar.

Phân loại biến z thành 2 nhóm thấp và cao

r %>% mutate(z1 = cut(z,2,label = c('thấp','cao'))) %>%  ggplot(aes(x = z1)) +
    geom_bar(fill='navy') +
    labs(x = 'chiều cao', y= 'Số lượng' , title = 'Z of Diamonds')

  • Quan sát đồ thị trên:
    • Tỷ lệ khoảng cách số lượng trên đồ thị là 1 đơn vị tương ứng với 100.
    • Đồ thị tên là Z of Diamonds.
    • Cột x là z, cột y là Số lượng.
    • Đa phần các giá trị có độ sâu từ 2,5 đến 5.
    • Cột thấp có số lượng nhiều hơn cột cao.
    • Các cột còn lại có các quan sát nhưng không nhiều.

0.13 ** Tổng kết quan sát x,y,z.**

  • Số lượng viên kim cương có chiều dài lớn chiếm >50% trên tổng số.
  • Số lượng viên kim cương có chiều rộng nhỏ hơn áp đảo số còn lại.
  • Số viên kim cương có chiều cao thấp áp đảo kim cương còn lại.
  • Nhìn chung, số lượng viên kim cương có kích thước lớn không nhiều, dẫn đến giá thành không cao.

0.14 Vẽ đồ thị theo color và carat.

  • Thao tác thực hiện: sử dụng group_by để phân nhóm dữ liệu theo hai tiêu chí là cut và color. Sau đó sử dung summarise để tạo ra biến mới tương ứng với những nhóm đã phân ra trước đó. sử dụng những biến mới để vẽ đồ thị bằng geom_col và facet_wrap để vẽ ra từng biểu đồ tương ứng với các nhóm.

r %>% group_by(color,cut) %>% summarise(n=n()) %>%
  ggplot(aes(x= cut,y= n)) + 
  geom_col(fill= 'green') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 500 tương ứng với 1 đơn vị.
    • Có 7 đồ thị : đồ thị loại D (color) với cut, loại E với Cut,loại F với Cut, loại G với Cut,loại H với cut, loại I với cut, loại J với cut.
    • Ở 7 đồ thị trên loại Ideal luôn có số lượng lớn nhất và Fair có số lượng nhỏ nhất.
    • Ta thấy tổ hợp giữa G và cut có tần số xuất hiện nhiều nhất và J và cut có số lượng ít nhất.

0.15 Vẽ đồ thị theo carat và color.

r %>% group_by(color,carat) %>% summarise(n=n()) %>%
  ggplot(aes(x= carat,y= n)) + 
  geom_col(fill= 'purple') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 100 tương ứng với 1 đơn vị.
    • Có 7 đồ thị : đồ thị loại D (color) với carat, loại E với carat,loại F với Carat, loại G với Carat,loại H với carat, loại I với carat, loại J với carat.
    • Ta thấy tổ hợp giữa E và carat có tần số xuất hiện nhiều nhất ; J và carat có số lượng ít nhất.

0.16 Vẽ đồ thị theo depth và color.

r %>% group_by(color,depth) %>% summarise(n=n()) %>%
  ggplot(aes(x= depth,y= n)) + 
  geom_col(fill= 'blue') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 50 tương ứng với 1 đơn vị.
    • Có 7 đồ thị : đồ thị loại D (color) với depth, loại E với depth,loại F với depth, loại G với deptht,loại H với depth, loại I với depth, loại J với depth.
    • Ta thấy tổ hợp giữa G và deptht có tần số xuất hiện nhiều nhất ; J và depth có số lượng ít nhất.

0.17 Vẽ đồ thị theo clarity và color.

r %>% group_by(color,clarity) %>% summarise(n=n()) %>%
  ggplot(aes(x= clarity,y= n)) + 
  geom_col(fill= 'red') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 250 tương ứng với 1 đơn vị.
    • Có 7 đồ thị : đồ thị loại D (color) với clarity, loại E với claruty,loại F với Clarity, loại G với Clarity,loại H với clarity, loại I với clarity, loại J với clarity.
    • Trong mỗi đồ thị thì tổ hợp color và SI1,SI2 luôn có tần số xuất hiện cao nhất.
    • Ta thấy tổ hợp giữa E và clarity có tần số xuất hiện nhiều nhất ; J và clarity có số lượng ít nhất.

0.18 Vẽ đồ thị theo table và color.

r %>% group_by(color,table) %>% summarise(n=n()) %>%
  ggplot(aes(x= table,y= n)) + 
  geom_col(fill= 'black') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 250 tương ứng với 1 đơn vị.
    • Có 7 đồ thị : đồ thị loại D (color) với table, loại E với table,loại F với table, loại G với table,loại H với table, loại I với table, loại J với table.
    • Ta thấy tổ hợp giữa E và table có tần số xuất hiện nhiều nhất ; J và table có số lượng ít nhất.

0.19 Vẽ đồ thị theo price và color.

r %>% group_by(color,price) %>% summarise(n=n()) %>%
  ggplot(aes(x= price,y= n)) + 
  geom_col(fill= 'brown') + geom_text(aes(label=round(n,2)), vjust=2, color='black') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 10 tương ứng với 1 đơn vị.
    • Có 7 đồ thị : đồ thị loại D (color) với price, loại E với price,loại F với price, loại G với price,loại H với price, loại I với price, loại J với price.
    • Ta thấy tổ hợp giữa F và price có tần số xuất hiện nhiều nhất ; J và price có số lượng ít nhất.

0.20 Vẽ đồ thị theo x và color.

r %>% group_by(color,x) %>% summarise(n=n()) %>%
  ggplot(aes(x= x,y= n)) + 
  geom_col(fill= 'violet') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 12.5 tương ứng với 1 đơn vị.
    • Có 7 đồ thị : đồ thị loại D (color) với x, loại E với x,loại F với x, loại G với x,loại H với x, loại I với x, loại J với x.
    • Ta thấy tổ hợp giữa G và x có tần số xuất hiện nhiều nhất ; J và x có số lượng ít nhất.

0.21 Vẽ đồ thị theo y và color.

r %>% group_by(color,y) %>% summarise(n=n()) %>%
  ggplot(aes(x= y,y= n)) + 
  geom_col(fill= 'salmon') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 15 tương ứng với 1 đơn vị.

    • Có 7 đồ thị : đồ thị loại D (color) với y, loại E với y,loại F với y, loại G với y,loại H với y, loại I với y, loại J với y.

    • Ta thấy tổ hợp giữa E và y có tần số xuất hiện nhiều nhất

    +J và y có số lượng ít nhất , luôn khiêm tốn hơn so với các màu khác.

0.22 Vẽ đồ thị theo z và color.

r %>% group_by(color,z) %>% summarise(n=n()) %>%
  ggplot(aes(x= z,y= n)) + 
  geom_col(fill= 'navy') + facet_wrap(~color) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 100 tương ứng với 1 đơn vị.
    • Có 7 đồ thị : đồ thị loại D (color) với z, loại E với z,loại F với z, loại G với z,loại H với z, loại I với z, loại J với z.
    • Ta thấy tổ hợp giữa G và z có tần số xuất hiện nhiều nhất ; J và z có số lượng ít nhất.

0.23 Vẽ đồ thị theo carat và cut.

r %>% group_by(cut,carat) %>% summarise(n=n()) %>%
  ggplot(aes(x= carat,y= n)) + 
  geom_col(fill= 'pink') + facet_wrap(~cut) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 100 tương ứng với 1 đơn vị.
    • Có 5 đồ thị : đồ thị loại Fair (cut) với carat, loại Good với carat,loại Very Good với Carat, loại Premium với Carat,loại Ideal với carat.
    • Ta thấy tổ hợp giữa Ideal và carat có tần số xuất hiện nhiều nhất ; Fair và carat có số lượng ít nhất.

0.24 Vẽ đồ thị theo cut và price.

r %>% group_by(cut,price) %>% summarise(n=n()) %>%
  ggplot(aes(x= price,y= n)) + 
  geom_col(fill= 'brown') + facet_wrap(~cut) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 10 tương ứng với 1 đơn vị.
    • Có 5 đồ thị : đồ thị loại Fair (cut) với price, loại Good với price,loại Very Good với price, loại Premium với price,loại Ideal với price.
    • Ta thấy tổ hợp giữa Ideal và price có tần số xuất hiện nhiều nhất ; Fair và price có số lượng ít nhất.

0.25 Vẽ đồ thị theo cut và clarity.

r %>% group_by(cut,clarity) %>% summarise(n=n()) %>%
  ggplot(aes(x= clarity,y= n)) + 
  geom_col(fill= 'red') + facet_wrap(~cut) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 500 tương ứng với 1 đơn vị.
    • Có 5 đồ thị : đồ thị loại Fair (cut) với clarity, loại Good với clarity,loại Very Good với clarity, loại Premium với clarity,loại Ideal với clarity.
    • Ta thấy tổ hợp giữa Ideal và clarity có tần số xuất hiện nhiều nhất ; Fair và clarity có số lượng ít nhất.
    • Trong 5 đồ thị tổ hợp SI1 và cut luôn có tần số xuất hiện cao nhất.

0.26 Vẽ đồ thị theo cut và table.

r %>% group_by(cut,table) %>% summarise(n=n()) %>%
  ggplot(aes(x= table,y= n)) + 
  geom_col(fill= 'black') + facet_wrap(~cut) +
  labs( x= 'Loại', y= 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 1000 tương ứng với 1 đơn vị.
    • Có 5 đồ thị : đồ thị loại Fair (cut) với table, loại Good với table,loại Very Good với table, loại Premium với table,loại Ideal với table.
    • Ta thấy tổ hợp giữa Ideal và table có tần số xuất hiện nhiều nhất ; Fair và table có số lượng ít nhất.

0.27 Vẽ đồ thị theo cut và depth.

r %>% group_by(cut,depth) %>% summarise(n=n()) %>% 
  ggplot(aes(x=depth,y=n)) +
  geom_col(fill= 'blue') + facet_wrap(~cut) +
  labs(x= 'Loại',y= 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 250 tương ứng với 1 đơn vị.
    • Có 5 đồ thị : đồ thị loại Fair (cut) với depth, loại Good với depth,loại Very Good với depth, loại Premium với depth,loại Ideal với depth.
    • Ta thấy tổ hợp giữa Ideal và depth có tần số xuất hiện nhiều nhất ; Fair và depth có số lượng ít nhất.

0.28 Vẽ đồ thị theo cut và x.

r %>% group_by(cut,x) %>% summarise(n=n()) %>% 
  ggplot(aes(x=x,y=n)) +
  geom_col(fill= 'violet') + facet_wrap(~cut) +
  labs(x= 'Loại',y= 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 50 tương ứng với 1 đơn vị.
    • Có 5 đồ thị : đồ thị loại Fair (cut) với x, loại Good với x,loại Very Good với x, loại Premium với x,loại Ideal với x.
    • Ta thấy tổ hợp giữa Ideal và x có tần số xuất hiện nhiều nhất ; Fair và x có số lượng ít nhất.

0.29 Vẽ đồ thị theo cut và y.

r %>% group_by(cut,y) %>% summarise(n=n()) %>% 
  ggplot(aes(x=y,y=n)) +
  geom_col(fill= 'salmon') + facet_wrap(~cut) +
  labs(x= 'Loại',y= 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 50 tương ứng với 1 đơn vị.
    • Có 5 đồ thị : đồ thị loại Fair (cut) với y, loại Good với y,loại Very Good với y, loại Premium với y,loại Ideal với y.
    • Ta thấy tổ hợp giữa Ideal và y có tần số xuất hiện nhiều nhất ; Fair và y có số lượng ít nhất.

0.30 Vẽ đồ thị theo cut và z.

r %>% group_by(cut,z) %>% summarise(n=n()) %>% 
  ggplot(aes(x=z,y=n)) +
  geom_col(fill= 'navy') + facet_wrap(~cut) +
  labs(x= 'Loại',y= 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Nhận xét:
    • Tỷ lệ trên cột số lượng là 50 tương ứng với 1 đơn vị.
    • Có 5 đồ thị : đồ thị loại Fair (cut) với z, loại Good với z,loại Very Good với z, loại Premium với z,loại Ideal với z.
    • Ta thấy tổ hợp giữa Ideal và z có tần số xuất hiện nhiều nhất ; Fair và z có số lượng ít nhất.

0.31 Vẽ đồ thị theo price và color trên cùng 1 đồ thị.

r %>% ggplot(aes(x = price, fill = color)) +
  geom_bar()  

0.32 Vẽ đồ thị phân loại price.

  • Thao tác thực hiện : dùng mutate tạo biến mới tên price1 gán cho các giá trị phân loại price theo 3 tiêu chuẩn :thấp, vừa, cao. Dùng cut để cắt price thành 3 nhóm dựa trên giá trị.
r <- r %>% mutate(price1 = cut(price,3,label = c('thấp','vừa','cao')))
r %>% ggplot(aes(x=price1)) +
  geom_bar(fill='pink')

  • Nhận xét:
    • Quan sát biểu đồ ta thấy loại giá thấp có số lượng nhiều nhất, còn giá cao có số lượng ít nhất.

0.33 Vẽ đồ thị phân loại depth.

  • Thực hiện thao tác giống phân loại price.
r <- r %>% mutate(depth1 = cut(depth,4,label = c('rất nhỏ','nhỏ','vừa','lớn')))
r %>% ggplot(aes(x=depth1)) +
  geom_bar(fill='salmon')

  • Nhận xét:
    • Loại depth vừa có số lượng nhiều nhất.
    • Hai loại rất nhỏ và lớn có nhưng số lượng rất ít.

0.34 Vẽ đồ thị giá trị trung bình của table theo biến cut.

  • Thao tác thực hiện:
    • Group_by(cut): thực hiện việc nhóm dữ liệu theo các giá trị của biến cut.
      +Summarise(w=mean(table)): trong mỗi nhóm được tạo bởi group_by, tính các giá trị trung bình của các giá trị trong biến table, lưu trữ nó trong 1 biến mới có tên w.
      +aes(label = round(w, 2)) định dạng văn bản được hiển thị dưới dạng các giá trị được làm tròn (đến hai chữ số thập phân) trong biến w.
      +vjust = 2 điều chỉnh vị trí theo chiều dọc của các nhãn văn bản hơi cao hơn các thanh để dễ đọc hơn.
      +color = ‘black’ đặt màu của các nhãn văn bản thành màu đen.
r %>% group_by(cut) %>% summarise(w=mean(table)) %>%
  ggplot(aes(x=cut,y=w)) + 
  geom_col(position= 'dodge', fill='salmon') +
  geom_text(aes(label= round(w,2)),vjust= 2, color= 'black') +
              labs(x='cut', y= 'mean')

  • Nhận xét:
    +Cột Fair có trung bình(điểm chính giữa) cao nhất 59.05 theo biến cut.
    +Cột Ideal có trung bình thấp nhất là 55.95 tính theo cut.

0.35 Vẽ đồ thị trung vị của depth theo biến clarity.

  • Thao tác thực hiện:
    • Group_by(clarity): thực hiện việc nhóm dữ liệu theo các giá trị của biến clarity.
      +Summarise(w=mean(depth)): trong mỗi nhóm được tạo bởi group_by, tính các giá trị trung bình của các giá trị trong biến depth, lưu trữ nó trong 1 biến mới có tên e.
      +aes(label = round(e, 2)) định dạng văn bản được hiển thị dưới dạng các giá trị được làm tròn (đến hai chữ số thập phân) trong biến e.
      +vjust = 2 điều chỉnh vị trí theo chiều dọc của các nhãn văn bản hơi cao hơn các thanh để dễ đọc hơn.
      +color = ‘red’ đặt màu của các nhãn văn bản thành màu đỏ.
r %>% group_by(clarity) %>% summarise(e=median(depth)) %>%
  ggplot(aes(x=clarity,y=e)) +
  geom_col(position='dodge',fill='violet') +
  geom_text(aes(label=round(e,2)), vjust=2, color='red') + labs(x='clarity',y='median')

  • Nhận xét:
    +Quan sát biểu đồ ta thấy trung vị(điểm ở giữa) của depth theo các loại clarity đều xấp xỉ nhau.
    +Cột I1 có điểm trung vị cao nhất của depth theo I1 là 62.2.

0.36 Vẽ đồ thi phương sai của y theo biến color.

  • Thao tác thực hiện:
    • Group_by(color): thực hiện việc nhóm dữ liệu theo các giá trị của biến color.
      +Summarise(w=mean(y)): trong mỗi nhóm được tạo bởi group_by, tính các giá trị trung bình của các giá trị trong biến y, lưu trữ nó trong 1 biến mới có tên g.
      +aes(label = round(e, 2)) định dạng văn bản được hiển thị dưới dạng các giá trị được làm tròn (đến hai chữ số thập phân) trong biến g.
      +vjust = 2 điều chỉnh vị trí theo chiều dọc của các nhãn văn bản hơi cao hơn các thanh để dễ đọc hơn.
      +color = ‘black’ đặt màu của các nhãn văn bản thành màu đen.
r %>% group_by(color) %>% summarise(g=var(y)) %>% 
  ggplot(aes(x=color,y=g)) +
  geom_col(position='dodge',fill='navy') +
  geom_text(aes(label=round(g,2)),vjust=2, color='black') + labs(x='màu',y='phương sai')

  • Nhận xét:
    +Cột H có phương sai (độ phân tán) của y cao nhất là 1.74.
    +Cột D có phương sai của y thấp nhất là 0.88.

0.37 Vẽ đồ thi phương sai của price theo biến color.

  • Thao tác thực hiện:
    • Group_by(color): thực hiện việc nhóm dữ liệu theo các giá trị của biến color.
      +Summarise(w=mean(price)): trong mỗi nhóm được tạo bởi group_by, tính các giá trị trung bình của các giá trị trong biến price, lưu trữ nó trong 1 biến mới có tên k.
      +aes(label = round(k, 2)) định dạng văn bản được hiển thị dưới dạng các giá trị được làm tròn (đến hai chữ số thập phân) trong biến g.
      +vjust = 2 điều chỉnh vị trí theo chiều dọc của các nhãn văn bản hơi cao hơn các thanh để dễ đọc hơn.
      +color = ‘black’ đặt màu của các nhãn văn bản thành màu đen.
r %>% group_by(color) %>% summarise(k=var(price)) %>% 
  ggplot(aes(x=color,y=k)) +
  geom_col(position='dodge',fill='green') +
  geom_text(aes(label=round(k,2)),vjust=2, color='black') + labs(x='màu',y='phương sai')

  • Nhận xét:
    +Cột I có phương sai (độ phân tán) của price cao nhất là 22300944.68.
    +Cột E có phương sai của price thấp nhất là 1183397.31.

0.38 Vẽ biểu đồ phương sai của x theo color.

r %>% group_by(color) %>% summarise(o=var(x)) %>% 
  ggplot(aes(x=color,y=o)) +
  geom_col(position='dodge',fill='yellow') +
  geom_text(aes(label=round(o,2)),vjust=2, color='black') + labs(x='màu',y='phương sai')

  • Nhận xét:
    +Cột I có phương sai (độ phân tán) của x cao nhất là 1.57.
    +Cột D có phương sai của x thấp nhất là 0.88.

0.39 Vẽ biểu đồ phương sai của z theo color.

r %>% group_by(color) %>% summarise(u=var(z)) %>% 
  ggplot(aes(x=color,y=u)) +
  geom_col(position='dodge',fill='salmon') +
  geom_text(aes(label=round(u,2)),vjust=2, color='black') + labs(x='màu',y='phương sai')

  • Nhận xét:
    +Cột I có phương sai (độ phân tán) của z cao nhất là 0.59.
    +Cột D có phương sai của z thấp nhất là 0.33.

0.40 Vẽ biểu đồ phương sai của x theo clarity.

r %>% group_by(clarity) %>% summarise(j=var(x)) %>% 
  ggplot(aes(x=clarity,y=j)) +
  geom_col(position='dodge',fill='pink') +
  geom_text(aes(label=round(j,2)),vjust=2, color='black') + labs(x='clarity',y='phương sai')

  • Nhận xét:
    +Cột VS1 có phương sai (độ phân tán) của x cao nhất là 1.18.
    +Cột VVS1 có phương sai của x thấp nhất là 0.72.

0.41 Vẽ biểu đồ phương sai của y theo clarity.

r %>% group_by(clarity) %>% summarise(f=var(y)) %>% 
  ggplot(aes(x=clarity,y=f)) +
  geom_col(position='dodge',fill='blue') +
  geom_text(aes(label=round(f,2)),vjust=2, color='black') + labs(x='clarity',y='phương sai')

  • Nhận xét:
    +Cột SI1 có phương sai (độ phân tán) của y cao nhất là 1.4.
    +Cột VVS1 có phương sai của y thấp nhất là 0.72.

0.42 Vẽ biểu đồ phương sai của z theo clarity.

r %>% group_by(clarity) %>% summarise(d=var(z)) %>% 
  ggplot(aes(x=clarity,y=d)) +
  geom_col(position='dodge',fill='brown') +
  geom_text(aes(label=round(d,2)),vjust=2, color='black') + labs(x='clarity',y='phương sai')

  • Nhận xét:
    +Cột VS1 có phương sai (độ phân tán) của z cao nhất là 0.53.
    +Cột VVS1 có phương sai của z thấp nhất là 0.27.
LS0tDQp0aXRsZTogIm52NCINCmF1dGhvcjogInBubWluaGNoYXUiDQpkYXRlOiAiMjAyNC0wMy0wMSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtOiAiZGVmYXVsdCINCiAgICB0b2NfZGVwdGg6IDMNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQoiYHIgZm9ybWF0KFN5cy50aW1lKCksJyVIOiVNOiVTLCAlZCAtICVtIC0gJVknKWAiICANCioqKg0KDQojIyAqKkdp4bubaSB0aGnhu4d1IHbhu4Egbmd14buTbiBn4buRYyBj4bunYSBi4buZIGThu68gbGnhu4d1IERpYW1vbmRzLioqICANCiogRGlhbW9uZHMgbMOgIG3hu5l0IHRyb25nIGPDoWMgZOG7ryBi4buZIGThu68gbGnhu4d1IGPhu6dhIHBhY2thZ2VzIGdncGxvdDIuICANCiogVHJvbmcgYsOgaSB2aeG6v3QgbsOgeSBjaMO6bmcgdGEgc+G6vSBnw6FuIGRpYW1vbmRzIHRow6BuaCByLiAgDQoqIGdncGxvdDIgbMOgIG3hu5l0IHBhY2thZ2VzIGjhu5cgdHLhu6MgduG6vSBjw6FjIGThuqFuZyDEkeG7kyB0aOG7iyBuaMawIGJhciBjaGFydCxoaXN0b2dyYW0scGllLC4uLiAgDQoqIEtoaSBkw7luZyBnZ3Bsb3QyIMSR4buDIHbhur0gxJHhu5MgdGjhu4sgY2jDum5nIHRhIGPDszogDQogICsgZ2dwbG90KCk6Y2jhu4kgxJHhu4tuaCBwaOG6p24gZOG7ryBsaeG7h3UgZMO5bmcgxJHhu4MgduG6vSDEkeG7kyB0aOG7iy4gIA0KICArIGdlb21fOiBjaOG7iSDEkeG7i25oIGThuqFuZyDEkeG7kyB0aOG7iyBj4bqnbiB24bq9LiAgIA0KDQojIyAqKkdp4bubaSB0aGnhu4d1IHbhu4EgYuG7mSBk4buvIGxp4buHdSBkaWFtb25kcyoqICANCg0KYGBge3IsZWNobz1UUlVFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0Kc3RyKGRpYW1vbmRzKQ0KbmFtZXMoZGlhbW9uZHMpDQpsaWJyYXJ5KHNraW1yKQ0Kc2tpbShkaWFtb25kcykNCmBgYA0KDQoqIFNhdSBraGkgZMO5bmcgbOG7h25oIGzhu4duaCBzdHIoKSB2w6AgbmFtZXMoKSwgdGEgdGh1IMSRxrDhu6NjIHRow7RuZyB0aW4gY+G7p2EgYuG7mSBk4buvIGxp4buHdSAqKkRpYW1vbmRzKiogZ+G7k20gY8OzOiAgDQorIDEwIGPhu5l0IGPDsyB0w6puIGzhuqduIGzGsOG7o3QgbMOgOiBjYXJhdCwgY3V0LCBjb2xvciwgY2xhcml0eSwgZGVwdGgsIHRhYmxlLCBwcmljZSwgeCwgeSwgei4gIA0KKyA1Myw5NDAgcXVhbiBzw6F0ICAgDQogICsgTeG7l2kgbeG7mXQgcXVhbiBzw6F0IHTGsMahbmcg4bupbmcgduG7m2kgMSB2acOqbiBraW0gY8awxqFuZy4gIA0KICArIDEwIGJp4bq/biB0xrDGoW5nIOG7qW5nIHbhu5tpIGPDoWMgxJHhurdjIHTDrW5oIGPhu6dhIGtpbSBjxrDGoW5nLiAgDQoqIEdp4bqjaSB0aMOtY2ggxJHhurdjIHTDrW5oOg0KICsgQ2FyYXQ6VHLhu41uZyBsxrDhu6NuZyBj4bunYSB2acOqbiBraW0gY8awxqFuZyAoZ3JhbSkNCiArIEN1dDogZ2nDoWMgY+G6r3QgdOG6oW8gcmEga2hpIHjhu60gbMO9IGtpbSBjxrDGoW5nIHRow7QuICANCiArIENvbG9yOiBtw6B1IGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nLiAgDQogKyBDbGFyaXR5OiDEkeG7mSB0aW5oIGtoaeG6v3QgY+G7p2Ega2ltIGPGsMahbmcuICANCiArIERlcHRoOiDEkeG7mSBzw6J1IGPhu6dhIGtpbSBjxrDGoW5nLiAgDQogKyBUYWJsZSA6QuG7gSBt4bq3dCBj4bunYSBraW0gY8awxqFuZyBu4bqxbSDhu58gdHLDqm4gxJHhu4luaCBraW0gY8awxqFuZy4gIA0KICsgUHJpY2U6IGdpw6EgdGjDoG5oIGPhu6dhIGtpbSBjxrDGoW5nLiAgDQogKyB4OiBjaGnhu4F1IGTDoGkgY+G7p2Ega2ltIGPGsMahbmcuICANCiArIHk6IGNoaeG7gXUgcuG7mW5nIGtpbSBjxrDGoW5nLiAgDQogKyB6OiBDaGnhu4F1IGNhbyBraW0gY8awxqFuZy4gIA0KDQoqICoqQ8O0bmcgY+G7pSB24bq9IMSR4buTIHRo4buLOioqDQogKyBEw7luZyBwYWNrYWdlcyBnZ3Bsb3QyLiAgDQogKyBDw6J1IGzhu4duaCBnZW9tX2JhcjogduG6vSDEkeG7kyB0aOG7iyBk4bqhbmcgYmFyLCB0xrDGoW5nIHThu7EgduG7m2kgY8OhYyBk4bqhbmcgYmnhu4N1IMSR4buTIGNvbHVtbiwgaGlzdG9ncmFtLC4uLiAgDQogK0xhYnM6IGTDuW5nIMSR4buDIMSR4bq3dCB0w6puLCB2w60gZOG7pSBuaMawIGzDoCBjw6FjIHRy4bulYyB4LHkgdsOgIHRpdGxlOiDEkeG6t3QgdMOqbiBjaG8gYmnhu4N1IMSR4buTLiAgDQogK0ZpbGw6IGNo4buNbiBtw6B1IGNobyBiaeG7g3UgxJHhu5MuICANCiArIGFlczogeMOhYyDEkeG7i25oIGThu68gbGnhu4d1IGPhuqduIHbhur0gYmnhu4N1IMSR4buTLiAgDQogK0dyb3VwX2J5OnBow6JuIG5ow7NtIGThu68gbGnhu4d1LiAgDQogK1N1bW1hcmlzZTogVOG6oW8gYmnhur9uIG3hu5tpLiANCiArIG1lYW46IHRydW5nIGLDrG5oDQogKyBtZWRpYW46IHRydW5nIHbhu4sgIA0KICsgdmFyOiBwaMawxqFuZyBzYWkgIA0KIA0KDQojIyAqKlbhur0gYmnhu4N1IMSR4buTIGPhu5l0IGNvbG9yIHRoZW8gZOG6oW5nIMSR4buTIHRo4buLIGJhci4qKiANCg0KDQpUcm9uZyBi4buZIGThu68gbGnhu4d1IERpYW1vbmRzLCBraW0gY8awxqFuZyBjw7MgNyBtw6B1IHPhuq9jLCBjaMO6bmcgxJHGsOG7o2MgcGjDom4gdsOgbyBoYWkgY+G6pXAgxJHhu5kgbcOgdSBz4bqvYyBraMOhYyBuaGF1OiAgDQogICsqKkQsRSxGKio6IGPhuqVwIMSR4buZIGtow7RuZyBtw6B1IChDb2xvcmxlc3MpICANCiAgKyoqRyxILEksSioqOiBD4bqlcCDEkeG7mSBn4bqnbiBuaMawIGtow7RuZyBtw6B1KE5lYXIgQ29sb3JsZXNzKSAgDQogICtExrDhu5tpIMSRw6J5IGzDoCBz4buRIGzGsOG7o25nIHZpw6puIGtpbSBjxrDGoW5nIGPhu6dhIG3hu5dpIG3DoHU6ICANCiAgDQpgYGB7cixlY2hvPVRSVUV9DQp0YWJsZShkaWFtb25kcyRjb2xvcikNCmBgYA0KDQoqKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkobWFncml0dHIpDQpsaWJyYXJ5KHNjYWxlcykNCnIgPC0gZGlhbW9uZHMNCnIgJT4lIGdncGxvdChhZXMoeCA9IGNvbG9yKSkgKw0KICAgIGdlb21fYmFyKGZpbGw9J2dyZWVuJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnLCB0aXRsZSA9ICdDb2xvciBvZiBEaWFtb25kcycpDQpgYGANCg0KKiBRdWFuIHPDoXQgYmnhu4N1IMSR4buTIHRyw6puLCB0YSB0aOG6pXkgxJHGsOG7o2M6ICAgIA0KICArIFThu7cgbOG7hyBraG/huqNuZyBjw6FjaCBz4buRIGzGsOG7o25nIHRyw6puIMSR4buTIHRo4buLIGzDoCAxIMSRxqFuIHbhu4sgdMawxqFuZyDhu6luZyB24bubaSAxNTAwLiAgDQogICsgxJDhu5MgdGjhu4sgdMOqbiBsw6AgQ29sb3Igb2YgRGlhbW9uZHMuICANCiAgKyBD4buZdCB4IGzDoCBMb+G6oWkgKEQsRSxGLEcsSCxJLEopLCBj4buZdCB5IGzDoCBT4buRIGzGsOG7o25nLiAgDQogICsgKipD4buZdCBHKiogbMOgIGPhu5l0IGPDsyBz4buRIGzGsOG7o25nICoqbmhp4buBdSBuaOG6pXQqKiAoMTEyOTIpLiAgDQogICsgKipD4buZdCBKKiogbMOgIGPhu5l0IGPDsyBz4buRIGzGsOG7o25nICoqbmjhu48gbmjhuqV0KiogKCAyODA4KS4gICANCiAgKyBLaGkgc28gc8OhbmggaGFpIG3DoHUgRyB2w6AgSiB0YSB0aOG6pXkgbcOgdSBHIGfhuqduIGLhurFuZyAqKjQgbOG6p24qKiBtw6B1IEouIA0KICArIEThu7FhIHbDoG8gYmnhu4N1IMSR4buTIHRhIHRo4bqleSByw7Ugc+G7kSBraW0gY8awxqFuZyBraMO0bmcgbcOgdSDDrXQgaMahbiBraW0gY8awxqFuZyBn4bqnbiBuaMawIGtow7RuZyBtw6B1LiAgDQogIA0KIyMgKipW4bq9IMSR4buTIHRo4buLIGPhu5l0IGN1dCB0aGVvIGThuqFuZyDEkeG7kyB0aOG7iyBiYXIuKioNCg0KR2nDoWMgY+G6r3Qga2ltIGPGsMahbmdfeeG6v3UgdOG7kSBxdWFuZyB0cuG7jW5nxJHhu4MgxJHDoW5oIGdpw6EgMSB2acOqbiBraW0gY8awxqFuZyBjw7MgxJHhurlwIGhheSBraMO0bmcuICANCiogTmfGsOG7nWkgdGEgbOG6rXAgcmEgMSB0aGFuZyDEkW8gbmjhurFtIMSRw6FuaCBnacOhIGdpw6FjIGPhuq90IGtpbSBjxrDGoW5nIHRoZW8gMiB0acOqdSBjaMOtIGzDoCB04bu3IGzhu4cgdsOgIGfDs2MgxJHhu5kgY+G7p2EgbeG6t3QgY+G6r3Q6ICANCiAgKyAqKklkZWFsKio6IG3hu6ljIMSR4buZIGzDvSB0xrDhu59uZyAgDQogICsqKlByZW1pdW0qKjogbeG7qWMgxJHhu5kgdHV54buHdCB24budaSAgDQogICsqKlZlcnkgR29vZCoqOiBt4bupYyDEkeG7mSBy4bqldCB04buRdCAgDQogICsqKkdvb2QqKjogbeG7qWMgxJHhu5kgdOG7kXQgIA0KICArKipGYWlyKio6IG3hu6ljIMSR4buZIHRydW5nIGLDrG5oICANCiogU+G7kSBsxrDGoW5nIHZpw6puIGtpbSBjxrDGoW5nIGPhu6dhIG3hu5dpIGxv4bqhaSBt4bq3dCBj4bqvdDogIA0KDQpgYGB7cixlY2hvPVRSVUV9DQp0YWJsZShyJGN1dCkNCmBgYA0KDQoNCmBgYHtyLGVjaG89VFJVRX0NCg0KciAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0KSkgKw0KICAgIGdlb21fYmFyKGZpbGw9J3BpbmsnKSArDQogICAgbGFicyh4ID0gJ03hurd0IGPhuq90IGtpbSBjxrDGoW5nJywgeT0gJ1Phu5EgbMaw4bujbmcnICwgdGl0bGUgPSAnQ3V0IG9mIERpYW1vbmRzJykNCmBgYA0KDQoqIFF1YW4gc8OhdCDEkeG7kyB0aOG7iyB0csOqbjogICANCiAgKyBU4bu3IGzhu4cga2hv4bqjbmcgY8OhY2ggc+G7kSBsxrDhu6NuZyB0csOqbiDEkeG7kyB0aOG7iyBsw6AgMSDEkcahbiB24buLIHTGsMahbmcg4bupbmcgduG7m2kgMjUwMC4gIA0KICArIMSQ4buTIHRo4buLIHTDqm4gbMOgIEN1dCBvZiBEaWFtb25kcy4gIA0KICArIEPhu5l0IHggbMOgIExv4bqhaSBt4bq3dCBj4bqvdCAoRmFpcixHb29kLCBWZXJ5IEdvb2QsIFByZW1pdW0sIElkZWFsKSwgY+G7mXQgeSBsw6AgU+G7kSBsxrDhu6NuZy4gIA0KICArIEPhu5l0ICoqSWRlYWwqKiBjw7Mgc+G7kSBsxrDhu6NuZyAqKm5oaeG7gXUgbmjhuqV0KiogKDIxNTUxKSAgIA0KICAgICtN4bq3dCBj4bqvdCAqKklkZWFsKiogY2hp4bq/bSBn4bqnbiBu4butYSBz4buRIGzGsOG7o25nIHF1YW4gc8OhdC4gDQogICAgK0toaSBjaOG6vyB0w6FjIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcsIG5nxrDhu51pIHRo4bujIGx1w7RuIHBo4bqjaSB0w61uaCB0b8OhbiB04buJIG3hu4kgdHLGsOG7m2Mga2hpIGNo4bq/IHTDoWMsIG7Dqm4gbG/huqFpIElkZWFsIGN1dCBjaGnhur9tIHPhu5EgbMaw4bujbmcgbmhp4buBdS4gIA0KICArIEPhu5l0IEZhaXIgY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldCAoMTYxMCkgIA0KICArIE5ow6xuIHbDoG8gYmnhu4N1IMSR4buTIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIG3hu5dpIGzhuqFpIHTEg25nIGThuqduIHRoZW8gdGjhu6kgdOG7sSBsb+G6oWkgbeG6t3QgY+G6r3QuICANCg0KIyMgKipW4bq9IGJp4buDdSDEkeG7kyBj4buZdCBjYXJhdCB0aGVvIGThuqFuZyBiYXIuKiogIA0KDQpUYSBjw7MgdGjhu4MgeMOhYyDEkeG7i25oIHRy4buNbmcgbMaw4bujbmcgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgYuG6sW5nIGPDom4gxJFp4buHbiB04butLCB2aeG7h2MgeMOhYyDEkeG7i25oIHRy4buNbmcgbMaw4bujbmcgcuG6pXQgcXVhbiB0cuG7jW5nIHRy4buNbmcgdmnhu4djIMSRw6FuaCBnacOhIGdpw6EgdGjDoG5oIGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nLiAgDQoNCg0KYGBge3IsZWNobz1UUlVFfQ0KDQpyICU+JSBnZ3Bsb3QoYWVzKHggPSBjYXJhdCkpICsNCiAgICBnZW9tX2JhcihmaWxsPSdwdXJwbGUnKSArDQogICAgbGFicyh4ID0gJ2NhcmF0JywgeT0gJ1Phu5EgbMaw4bujbmcnICwgdGl0bGUgPSAnQ2FyYXQgb2YgRGlhbW9uZHMnKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgKyBU4bu3IGzhu4cga2hv4bqjbmcgY8OhY2ggc+G7kSBsxrDhu6NuZyB0csOqbiDEkeG7kyB0aOG7iyBsw6AgMSDEkcahbiB24buLIHTGsMahbmcg4bupbmcgduG7m2kgNTAwLiAgDQogICsgxJDhu5MgdGjhu4sgdMOqbiBsw6AgQ2FyYXQgb2YgRGlhbW9uZHMuICANCiAgKyBD4buZdCB4IGzDoCBjYXJhdCgwLjIzLDAuLC4uLiksIGPhu5l0IHkgbMOgIFPhu5EgbMaw4bujbmcuICANCiAgKyBD4buZdCBraG/huqNuZyB04burIDAgxJHhur9uIDAuNSBjw7Mgc+G7kSBsxrDhu6NuZyBuaGnhu4F1IG5o4bqldCAgIA0KICArIEPhu5l0IHThu6sgNCDEkeG6v241IGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pXQgIA0KICArIE5ow6xuIHbDoG8gYmnhu4N1IMSR4buTIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIG3hu5dpIGzhuqFpIGdp4bqjbSBk4bqnbiB0aGVvIHRo4bupIHThu7EgbG/huqFpIG3hurd0IGPhuq90LiAgDQoNCiMjICoqVuG6vSBiaeG7g3UgxJHhu5MgY2xhcml0eSB0aGVvIGThuqFuZyBiYXIuKiogIA0KDQpUaGFuZyDEkW8gxJHhu5kgdGluaCBraGnhur90IGPhu6dhIGtpbSBjxrDGoW5nOiAgDQoNCiogKipJbnRlcm5hbGx5IEZsYXdsZXNzICgga2ltIGPGsMahbmcgxJHhu5kgc+G6oWNoIElGICkqKjoga2jDtG5nIG5ow6xuIHRo4bqleSB04bqhcCBjaOG6pXQgYsOqbiB0cm9uZyBtw6AgY2jhu4kgY8OzIG3hu5l0IHbDoGkgduG6v3QgbeG7nSB0csOqbiBi4buBIG3hurd0IGPhu6dhIG7Dsy4gxJDhu5kgdGluaCBraGnhur90IElGIGPhu6dhIGtpbSBjxrDGoW5nIMSRxrDhu6NjIMSRw6FuaCBnacOhIGzDoCB0dXnhu4d0IHbhu51pLiAgDQoqICoqVmVyeSBWZXJ5IFNsaWdodGx5IEluY2x1ZGVkICggxJHhu5kgdHJvbmcga2ltIGPGsMahbmcgVlZTMSwgVlZTMiApKio6IGPDoWMgdOG6oXAgY2jhuqV0IGLDqm4gdHJvbmcgY+G7sWMga+G7syBuaOG7jyB2w6Aga2jDsyBuaMOsbiB0aOG6pXkgZMaw4bubaSBrw61uaCBoaeG7g24gdmkgxJHDoSBxdcO9IGPDsyDEkeG7mSBwaMOzbmcgxJHhuqFpIDEwIGzhuqduLiDEkOG7mSB0aW5oIGtoaeG6v3Qga2hpIHLGoWkgdsOgbyBuaMOzbSBuw6B5IMSRxrDhu6NjIMSRw6FuaCBnacOhIGNhby4gIA0KKiAqKlZlcnkgU2xpZ2h0bHkgSW5jbHVkZWQgKMSQ4buZIHPhuqFjaCBraW0gY8awxqFuZyBWUzEsIFZTMikqKjogY8OzIGPDoWMgdOG6oXAgY2jhuqV0IHLhuqV0IG5o4buPLCBjw7MgdGjhu4MgbmjDrG4gdGjhuqV5IGTGsOG7m2kgxJHhu5kgcGjDs25nIMSR4bqhaSAxMCBs4bqnbi4ga2hpIHLGoWkgdsOgbyBuaMOzbSBuw6B5IMSR4buZIHRpbmgga2hp4bq/dCDEkcaw4bujYyDEkcOhbmggZ2nDoSB0csOqbiBt4bupYyB0cnVuZyBiw6xuaC4gIA0KKiAqKlNsaWdodGx5IEluY2x1ZGVkICggxJDhu5kgdGluaCBraGnhur90IGtpbSBjxrDGoW5nIFNJMSwgU0kyICkqKjoga2ltIGPGsMahbmcgY8OzIGPDoWMgdOG6oXAgY2jhuqV0IGThu4Ugbmjhuq1uIHRo4bqleSBkxrDhu5tpIMSR4buZIHBow7NuZyDEkeG6oWkgMTAgbOG6p24uIMSQ4buZIHRpbmgga2hp4bq/dCBj4bunYSBuaMOzbSBuw6B5IMSRxrDhu6NjIMSRw6FuaCBnacOhIOG7nyBt4bupYyB0cnVuZyBiw6xuaC4gIA0KKiAqKkluY2x1ZGVkICggxJDhu5kgc+G6oWNoIGPhu6dhIGtpbSBjxrDGoW5nIEkx4oCTIEkzICkqKjogY8OhYyB04bqhcCBjaOG6pXQgcsO1IHLDoG5nIGPDsyB0aOG7gyBuaMOsbiB0aOG6pXkgYuG6sW5nIG3huq90IHRoxrDhu51uZyAgDQoNCiogU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBj4bunYSBt4buXaSBjbGFycml0eTogIA0KDQpgYGB7cixlY2hvPVRSVUV9DQp0YWJsZShyJGNvbG9yKQ0KYGBgDQoNCioqKg0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCnIgJT4lIGdncGxvdChhZXMoeCA9IGNsYXJpdHkpKSArDQogICAgZ2VvbV9iYXIoZmlsbD0ncmVkJykgKw0KICAgIGxhYnMoeCA9ICfEkeG7mSB0cm9uZycsIHk9ICdT4buRIGzGsOG7o25nJyAsIHRpdGxlID0gJ0NsYXJpdHkgb2YgRGlhbW9uZHMnKQ0KYGBgDQoNCiogUXVhbiBzw6F0IMSR4buTIHRo4buLIHRyw6puOiAgIA0KICArIFThu7cgbOG7hyBraG/huqNuZyBjw6FjaCBz4buRIGzGsOG7o25nIHRyw6puIMSR4buTIHRo4buLIGzDoCAxIMSRxqFuIHbhu4sgdMawxqFuZyDhu6luZyB24bubaSAyNTAwLiAgDQogICsgxJDhu5MgdGjhu4sgdMOqbiBsw6AgQ2xhcml0eSBvZiBEaWFtb25kcy4gIA0KICArIEPhu5l0IHggbMOgIMSR4buZIHRyb25nIChJMSxTSTIsU0kxLFZTMixWUzEsVlZTMi5WVlMxLklGKSwgY+G7mXQgeSBsw6AgU+G7kSBsxrDhu6NuZy4gIA0KICArIEPhu5l0ICoqU0kxKiogY8OzIHPhu5EgbMaw4bujbmcgKipuaGnhu4F1IG5o4bqldCoqICgxMzA2NSksIG5o4buvbmcgdmnDqm4ga2ltIGPGsMahbmcgY2jhu6lhIHThuqFwIGNo4bqldCBk4buFIHRo4bqleSBjaGnhur9tIHPhu5EgbMaw4bujbmcgbmhp4buBdS4gICAgIA0KICArIEPhu5l0ICoqSTEqKiBjw7Mgc+G7kSBsxrDhu6NuZyAqKsOtdCBuaOG6pXQqKiAoNzQxKSAgIA0KICArIFPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgU0kxIGfhuqVwICoqMTAgbOG6p24qKiBzbyB24bubaSBJMQ0KICArIFPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY2jDqm5oIGzhu4djaCBnaeG7r2EgY8OhYyBt4bupYyDEkeG7mSBraMO0bmcgcXXDoSBuaGnhu4F1LiAgDQogIA0KIyMgKipW4bq9IGJp4buDdSDEkeG7kyBj4buZdCBkZXB0aCB0aGVvIGThuqFuZyBiYXIuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KDQpyICU+JSBnZ3Bsb3QoYWVzKHggPSBkZXB0aCkpICsNCiAgICBnZW9tX2JhcihmaWxsPSdibHVlJykgKw0KICAgIGxhYnMoeCA9ICfEkeG7mSBzw6J1JywgeT0gJ1Phu5EgbMaw4bujbmcnICwgdGl0bGUgPSAnRGVwdGggb2YgRGlhbW9uZHMnKQ0KYGBgDQoNCiogUXVhbiBzw6F0IMSR4buTIHRo4buLIHRyw6puOiAgIA0KICArIFThu7cgbOG7hyBraG/huqNuZyBjw6FjaCBz4buRIGzGsOG7o25nIHRyw6puIMSR4buTIHRo4buLIGzDoCAxIMSRxqFuIHbhu4sgdMawxqFuZyDhu6luZyB24bubaSA1MDAuICANCiAgKyDEkOG7kyB0aOG7iyB0w6puIGzDoCBEZXB0aCBvZiBEaWFtb25kcy4gIA0KICArIEPhu5l0IHggbMOgIMSR4buZIHPDonUgKDUwIH4gODApLCBj4buZdCB5IGzDoCBT4buRIGzGsOG7o25nLiAgDQogICsgxJBhIHBo4bqnbiBjw6FjIGdpw6EgdHLhu4sgY8OzIMSR4buZIHPDonUgdOG7qyA2MCB+IDYzLiAgIA0KICArIEPDoWMgY+G7mXQgY8OybiBs4bqhaSBjw7MgY8OhYyBxdWFuIHPDoXQgbmjGsG5nIGtow7RuZyBuaGnhu4F1LiAgDQogIA0KIyMgKipW4bq9IGJp4buDdSDEkeG7kyBj4buZdCB0YWJsZSB0aGVvIGThuqFuZyBiYXIuKiogIA0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCnIgJT4lIGdncGxvdChhZXMoeCA9IHRhYmxlKSkgKw0KICAgIGdlb21fYmFyKGZpbGw9J2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICd0YWJsZScsIHk9ICdT4buRIGzGsOG7o25nJyAsIHRpdGxlID0gJ3RhYmxlIG9mIERpYW1vbmRzJykNCmBgYA0KICANCg0KKiBRdWFuIHPDoXQgxJHhu5MgdGjhu4sgdHLDqm46ICAgDQogICsgVOG7tyBs4buHIGtob+G6o25nIGPDoWNoIHPhu5EgbMaw4bujbmcgdHLDqm4gxJHhu5MgdGjhu4sgbMOgIDEgxJHGoW4gduG7iyB0xrDGoW5nIOG7qW5nIHbhu5tpIDI1MDAuICANCiAgKyDEkOG7kyB0aOG7iyB0w6puIGzDoCBUYWJsZSBvZiBEaWFtb25kcy4gIA0KICArIEPhu5l0IHggdGFibGUsIGPhu5l0IHkgbMOgIFPhu5EgbMaw4bujbmcuICANCiAgKyDEkGEgcGjhuqduIGPDoWMgZ2nDoSB0cuG7iyBjw7MgxJHhu5kgc8OidSB04burIDUwIH4gNjAuICAgDQogICsgQ8OhYyBj4buZdCBjw7JuIGzhuqFpIGPDsyBjw6FjIHF1YW4gc8OhdCBuaMawbmcga2jDtG5nIG5oaeG7gXUuICANCiAgDQojIyAqKlbhur0gYmnhu4N1IMSR4buTIGPhu5l0IHByaWNlIHRoZW8gZOG6oW5nIGJhci4qKiAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCg0KciAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UpKSArDQogICAgZ2VvbV9iYXIoZmlsbD0nYnJvd24nKSArDQogICAgbGFicyh4ID0gJ2dpw6EnLCB5PSAnU+G7kSBsxrDhu6NuZycgLCB0aXRsZSA9ICdwcmljZSBvZiBEaWFtb25kcycpDQpgYGANCiAgDQoNCiogUXVhbiBzw6F0IMSR4buTIHRo4buLIHRyw6puOiAgIA0KICArIFThu7cgbOG7hyBraG/huqNuZyBjw6FjaCBz4buRIGzGsOG7o25nIHRyw6puIMSR4buTIHRo4buLIGzDoCAxIMSRxqFuIHbhu4sgdMawxqFuZyDhu6luZyB24bubaSA1MC4gIA0KICArIMSQ4buTIHRo4buLIHTDqm4gbMOgIFByaWNlIG9mIERpYW1vbmRzLiAgDQogICsgQ+G7mXQgeCBsw6AgZ2nDoSwgY+G7mXQgeSBsw6AgU+G7kSBsxrDhu6NuZy4gIA0KICArIMSQYSBwaOG6p24gY8OhYyBnacOhIHRy4buLIGPDsyDEkeG7mSBzw6J1IHThu6sgMTAwMCB0cuG7nyB4deG7kW5nLiAgIA0KICArIEdpw6EgY8OgbmcgdMSDbmcgc+G7kSBsxrDhu6NuZyBjw6BuZyDDrXQuICAgDQoNCiMjICoqVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgeCB0aGVvIGThuqFuZyBiYXIuKiogIA0KDQpQaMOibiBsb+G6oWkgeCB0aMOgbmggMiBuaMOzbSBuZ+G6r24gdsOgIGTDoGkgxJHhu4MgZOG7hSBxdWFuIHPDoXQgaMahbiAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCg0KciAlPiUgbXV0YXRlKHgxID0gY3V0KHgsMixsYWJlbCA9IGMoJ25n4bqvbicsJ2TDoGknKSkpICU+JSBnZ3Bsb3QoYWVzKHggPSB4MSkpICsNCiAgICBnZW9tX2JhcihmaWxsPSd2aW9sZXQnKSArIA0KICAgIGxhYnMoeCA9ICd4JywgeT0gJ1Phu5EgbMaw4bujbmcnICwgdGl0bGUgPSAnWCBvZiBEaWFtb25kcycpDQpgYGANCiAgDQoNCiogUXVhbiBzw6F0IMSR4buTIHRo4buLIHRyw6puOiAgIA0KICArIFThu7cgbOG7hyBraG/huqNuZyBjw6FjaCBz4buRIGzGsOG7o25nIHRyw6puIMSR4buTIHRo4buLIGzDoCAxIMSRxqFuIHbhu4sgdMawxqFuZyDhu6luZyB24bubaSA1MC4gIA0KICArIMSQ4buTIHRo4buLIHTDqm4gbMOgIFggb2YgRGlhbW9uZHMuICANCiAgKyBD4buZdCB4IGzDoCB4LCBj4buZdCB5IGzDoCBT4buRIGzGsOG7o25nLiAgDQogICsgQ+G7mXQgZMOgaSBjw7Mgc+G7kSBsxrDhu6NuZyAqKmzhu5tuIGjGoW4qKiBj4buZdCBuZ+G6r24uICAgDQoNCiMjICoqVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgeSB0aGVvIGThuqFuZyBiYXIuKiogIA0KDQpDaGlhIHkgdGjDoG5oIDIgbmjDs20gZ+G7k20gbOG7m24gdsOgIG5o4buPLiAgICANCg0KYGBge3IsZWNobz1UUlVFfQ0KDQpyICU+JSBtdXRhdGUoeTEgPSBjdXQoeSwyLGxhYmVsID0gYygnIG5o4buPJywnbOG7m24nKSkpICU+JSBnZ3Bsb3QoYWVzKHggPSB5MSkpICsNCiAgICBnZW9tX2JhcihmaWxsPSdzYWxtb24nKSArIA0KICAgIGxhYnMoeCA9ICdjaGnhu4F1IHLhu5luZycsIHk9ICdT4buRIGzGsOG7o25nJyAsIHRpdGxlID0gJ1kgb2YgRGlhbW9uZHMnKQ0KYGBgDQogIA0KDQoqIFF1YW4gc8OhdCDEkeG7kyB0aOG7iyB0csOqbjogICANCiAgKyBU4bu3IGzhu4cga2hv4bqjbmcgY8OhY2ggc+G7kSBsxrDhu6NuZyB0csOqbiDEkeG7kyB0aOG7iyBsw6AgMSDEkcahbiB24buLIHTGsMahbmcg4bupbmcgduG7m2kgNTAuICANCiAgKyDEkOG7kyB0aOG7iyB0w6puIGzDoCBZIG9mIERpYW1vbmRzLiAgDQogICsgQ+G7mXQgeCBsw6AgeSwgY+G7mXQgeSBsw6AgU+G7kSBsxrDhu6NuZy4gIA0KICArIEPhu5l0IG5o4buPIGPDsyBz4buRIGzGsOG7o25nIG5oaeG7gXUgaMahbiAgICANCiAgKyBD4buZdCBjw7JuIGzhuqFpIGPDsyBjw6FjIHF1YW4gc8OhdCBuaMawbmcga2jDtG5nIG5oaeG7gXUuICAgIA0KICANCiMjICoqVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgeiB0aGVvIGThuqFuZyBiYXIuKiogIA0KDQpQaMOibiBsb+G6oWkgYmnhur9uIHogdGjDoG5oIDIgbmjDs20gdGjhuqVwIHbDoCBjYW8NCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgbXV0YXRlKHoxID0gY3V0KHosMixsYWJlbCA9IGMoJ3Ro4bqlcCcsJ2NhbycpKSkgJT4lICBnZ3Bsb3QoYWVzKHggPSB6MSkpICsNCiAgICBnZW9tX2JhcihmaWxsPSduYXZ5JykgKw0KICAgIGxhYnMoeCA9ICdjaGnhu4F1IGNhbycsIHk9ICdT4buRIGzGsOG7o25nJyAsIHRpdGxlID0gJ1ogb2YgRGlhbW9uZHMnKQ0KYGBgDQogIA0KDQoqIFF1YW4gc8OhdCDEkeG7kyB0aOG7iyB0csOqbjogICANCiAgKyBU4bu3IGzhu4cga2hv4bqjbmcgY8OhY2ggc+G7kSBsxrDhu6NuZyB0csOqbiDEkeG7kyB0aOG7iyBsw6AgMSDEkcahbiB24buLIHTGsMahbmcg4bupbmcgduG7m2kgMTAwLiAgDQogICsgxJDhu5MgdGjhu4sgdMOqbiBsw6AgWiBvZiBEaWFtb25kcy4gIA0KICArIEPhu5l0IHggbMOgIHosIGPhu5l0IHkgbMOgIFPhu5EgbMaw4bujbmcuICANCiAgKyDEkGEgcGjhuqduIGPDoWMgZ2nDoSB0cuG7iyBjw7MgxJHhu5kgc8OidSB04burIDIsNSDEkeG6v24gNS4gIA0KICArIEPhu5l0IHRo4bqlcCBjw7Mgc+G7kSBsxrDhu6NuZyBuaGnhu4F1IGjGoW4gY+G7mXQgY2FvLiAgDQogICsgQ8OhYyBj4buZdCBjw7JuIGzhuqFpIGPDsyBjw6FjIHF1YW4gc8OhdCBuaMawbmcga2jDtG5nIG5oaeG7gXUuICAgDQogIA0KIyMgKiogVOG7lW5nIGvhur90IHF1YW4gc8OhdCB4LHksei4qKiAgDQoqIFPhu5EgbMaw4bujbmcgdmnDqm4ga2ltIGPGsMahbmcgY8OzICoqY2hp4buBdSBkw6BpIGzhu5tuIGNoaeG6v20gPjUwJSoqIHRyw6puIHThu5VuZyBz4buRLiAgDQoqIFPhu5EgbMaw4bujbmcgdmnDqm4ga2ltIGPGsMahbmcgY8OzICoqY2hp4buBdSBy4buZbmcgbmjhu48gaMahbiDDoXAgxJHhuqNvKiogc+G7kSBjw7JuIGzhuqFpLiAgDQoqIFPhu5EgdmnDqm4ga2ltIGPGsMahbmcgY8OzICoqY2hp4buBdSBjYW8gdGjhuqVwIMOhcCDEkeG6o28qKiBraW0gY8awxqFuZyBjw7JuIGzhuqFpLiAgDQoqIE5ow6xuIGNodW5nLCBz4buRIGzGsOG7o25nIHZpw6puIGtpbSBjxrDGoW5nIGPDsyBrw61jaCB0aMaw4bubYyBs4bubbiBraMO0bmcgbmhp4buBdSwgZOG6q24gxJHhur9uIGdpw6EgdGjDoG5oIGtow7RuZyBjYW8uICANCg0KIyMgKipW4bq9IMSR4buTIHRo4buLIHRoZW8gY29sb3IgdsOgIGNhcmF0LioqICANCg0KKiBUaGFvIHTDoWMgdGjhu7FjIGhp4buHbjogc+G7rSBk4bulbmcgZ3JvdXBfYnkgxJHhu4MgcGjDom4gbmjDs20gZOG7ryBsaeG7h3UgdGhlbyBoYWkgdGnDqnUgY2jDrSBsw6AgY3V0IHbDoCBjb2xvci4gU2F1IMSRw7Mgc+G7rSBkdW5nIHN1bW1hcmlzZSDEkeG7gyB04bqhbyByYSBiaeG6v24gbeG7m2kgdMawxqFuZyDhu6luZyB24bubaSBuaOG7r25nIG5ow7NtIMSRw6MgcGjDom4gcmEgdHLGsOG7m2MgxJHDsy4gc+G7rSBk4bulbmcgbmjhu69uZyBiaeG6v24gbeG7m2kgxJHhu4MgduG6vSDEkeG7kyB0aOG7iyBi4bqxbmcgZ2VvbV9jb2wgdsOgIGZhY2V0X3dyYXAgxJHhu4MgduG6vSByYSB04burbmcgYmnhu4N1IMSR4buTIHTGsMahbmcg4bupbmcgduG7m2kgY8OhYyBuaMOzbS4gIA0KDQoqKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY29sb3IsY3V0KSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4PSBjdXQseT0gbikpICsgDQogIGdlb21fY29sKGZpbGw9ICdncmVlbicpICsgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgbGFicyggeD0gJ0xv4bqhaScsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDUwMCB0xrDGoW5nIOG7qW5nIHbhu5tpIDEgxJHGoW4gduG7iy4gIA0KICArIEPDsyA3IMSR4buTIHRo4buLIDogxJHhu5MgdGjhu4sgbG/huqFpIEQgKGNvbG9yKSB24bubaSBjdXQsIGxv4bqhaSBFIHbhu5tpIEN1dCxsb+G6oWkgRiB24bubaSBDdXQsIGxv4bqhaSBHIHbhu5tpIEN1dCxsb+G6oWkgSCB24bubaSBjdXQsIGxv4bqhaSBJIHbhu5tpIGN1dCwgbG/huqFpIEogduG7m2kgY3V0LiAgDQogICsg4bueIDcgxJHhu5MgdGjhu4sgdHLDqm4gbG/huqFpIElkZWFsIGx1w7RuIGPDsyBz4buRIGzGsOG7o25nIGzhu5tuIG5o4bqldCB2w6AgRmFpciBjw7Mgc+G7kSBsxrDhu6NuZyBuaOG7jyBuaOG6pXQuICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgRyB2w6AgY3V0IGPDsyB04bqnbiBz4buRIHh14bqldCBoaeG7h24gbmhp4buBdSBuaOG6pXQgdsOgIEogdsOgIGN1dCBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgbmjhuqV0LiAgDQoNCg0KIyMgKipW4bq9IMSR4buTIHRo4buLIHRoZW8gY2FyYXQgdsOgIGNvbG9yLioqDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGNvbG9yLGNhcmF0KSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4PSBjYXJhdCx5PSBuKSkgKyANCiAgZ2VvbV9jb2woZmlsbD0gJ3B1cnBsZScpICsgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgbGFicyggeD0gJ0xv4bqhaScsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDEwMCB0xrDGoW5nIOG7qW5nIHbhu5tpIDEgxJHGoW4gduG7iy4gIA0KICArIEPDsyA3IMSR4buTIHRo4buLIDogxJHhu5MgdGjhu4sgbG/huqFpIEQgKGNvbG9yKSB24bubaSBjYXJhdCwgbG/huqFpIEUgduG7m2kgY2FyYXQsbG/huqFpIEYgduG7m2kgQ2FyYXQsIGxv4bqhaSBHIHbhu5tpIENhcmF0LGxv4bqhaSBIIHbhu5tpIGNhcmF0LCBsb+G6oWkgSSB24bubaSBjYXJhdCwgbG/huqFpIEogduG7m2kgY2FyYXQuICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgRSB2w6AgY2FyYXQgY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEogdsOgIGNhcmF0IGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pXQuICANCiAgDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgdGhlbyBkZXB0aCB2w6AgY29sb3IuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY29sb3IsZGVwdGgpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9IGRlcHRoLHk9IG4pKSArIA0KICBnZW9tX2NvbChmaWxsPSAnYmx1ZScpICsgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgbGFicyggeD0gJ0xv4bqhaScsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDUwIHTGsMahbmcg4bupbmcgduG7m2kgMSDEkcahbiB24buLLiAgDQogICsgQ8OzIDcgxJHhu5MgdGjhu4sgOiDEkeG7kyB0aOG7iyBsb+G6oWkgRCAoY29sb3IpIHbhu5tpIGRlcHRoLCBsb+G6oWkgRSB24bubaSBkZXB0aCxsb+G6oWkgRiB24bubaSBkZXB0aCwgbG/huqFpIEcgduG7m2kgZGVwdGh0LGxv4bqhaSBIIHbhu5tpIGRlcHRoLCBsb+G6oWkgSSB24bubaSBkZXB0aCwgbG/huqFpIEogduG7m2kgZGVwdGguICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgRyB2w6AgZGVwdGh0IGPDsyB04bqnbiBz4buRIHh14bqldCBoaeG7h24gbmhp4buBdSBuaOG6pXQgOyBKIHbDoCBkZXB0aCBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgbmjhuqV0LiAgDQogIA0KIyMgKipW4bq9IMSR4buTIHRo4buLIHRoZW8gY2xhcml0eSB2w6AgY29sb3IuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY29sb3IsY2xhcml0eSkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeD0gY2xhcml0eSx5PSBuKSkgKyANCiAgZ2VvbV9jb2woZmlsbD0gJ3JlZCcpICsgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgbGFicyggeD0gJ0xv4bqhaScsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDI1MCB0xrDGoW5nIOG7qW5nIHbhu5tpIDEgxJHGoW4gduG7iy4gIA0KICArIEPDsyA3IMSR4buTIHRo4buLIDogxJHhu5MgdGjhu4sgbG/huqFpIEQgKGNvbG9yKSB24bubaSBjbGFyaXR5LCBsb+G6oWkgRSB24bubaSBjbGFydXR5LGxv4bqhaSBGIHbhu5tpIENsYXJpdHksIGxv4bqhaSBHIHbhu5tpIENsYXJpdHksbG/huqFpIEggduG7m2kgY2xhcml0eSwgbG/huqFpIEkgduG7m2kgY2xhcml0eSwgbG/huqFpIEogduG7m2kgY2xhcml0eS4gIA0KICArIFRyb25nIG3hu5dpIMSR4buTIHRo4buLIHRow6wgdOG7lSBo4bujcCBjb2xvciB2w6AgU0kxLFNJMiBsdcO0biBjw7MgdOG6p24gc+G7kSB4deG6pXQgaGnhu4duIGNhbyBuaOG6pXQuICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgRSB2w6AgY2xhcml0eSBjw7MgdOG6p24gc+G7kSB4deG6pXQgaGnhu4duIG5oaeG7gXUgbmjhuqV0IDsgSiB2w6AgY2xhcml0eSBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgbmjhuqV0LiAgDQoNCiMjICoqVuG6vSDEkeG7kyB0aOG7iyB0aGVvIHRhYmxlIHbDoCBjb2xvci4qKg0KDQpgYGB7cixlY2hvPVRSVUV9DQpyICU+JSBncm91cF9ieShjb2xvcix0YWJsZSkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeD0gdGFibGUseT0gbikpICsgDQogIGdlb21fY29sKGZpbGw9ICdibGFjaycpICsgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgbGFicyggeD0gJ0xv4bqhaScsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDI1MCB0xrDGoW5nIOG7qW5nIHbhu5tpIDEgxJHGoW4gduG7iy4gIA0KICArIEPDsyA3IMSR4buTIHRo4buLIDogxJHhu5MgdGjhu4sgbG/huqFpIEQgKGNvbG9yKSB24bubaSB0YWJsZSwgbG/huqFpIEUgduG7m2kgdGFibGUsbG/huqFpIEYgduG7m2kgdGFibGUsIGxv4bqhaSBHIHbhu5tpIHRhYmxlLGxv4bqhaSBIIHbhu5tpIHRhYmxlLCBsb+G6oWkgSSB24bubaSB0YWJsZSwgbG/huqFpIEogduG7m2kgdGFibGUuICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgRSB2w6AgdGFibGUgY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEogdsOgIHRhYmxlIGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pXQuICANCg0KIyMgKipW4bq9IMSR4buTIHRo4buLIHRoZW8gcHJpY2UgdsOgIGNvbG9yLioqDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGNvbG9yLHByaWNlKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4PSBwcmljZSx5PSBuKSkgKyANCiAgZ2VvbV9jb2woZmlsbD0gJ2Jyb3duJykgKyBnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKG4sMikpLCB2anVzdD0yLCBjb2xvcj0nYmxhY2snKSArIGZhY2V0X3dyYXAofmNvbG9yKSArDQogIGxhYnMoIHg9ICdMb+G6oWknLCB5PSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiBOaOG6rW4geMOpdDogIA0KICArIFThu7cgbOG7hyB0csOqbiBj4buZdCBz4buRIGzGsOG7o25nIGzDoCAxMCB0xrDGoW5nIOG7qW5nIHbhu5tpIDEgxJHGoW4gduG7iy4gIA0KICArIEPDsyA3IMSR4buTIHRo4buLIDogxJHhu5MgdGjhu4sgbG/huqFpIEQgKGNvbG9yKSB24bubaSBwcmljZSwgbG/huqFpIEUgduG7m2kgcHJpY2UsbG/huqFpIEYgduG7m2kgcHJpY2UsIGxv4bqhaSBHIHbhu5tpIHByaWNlLGxv4bqhaSBIIHbhu5tpIHByaWNlLCBsb+G6oWkgSSB24bubaSBwcmljZSwgbG/huqFpIEogduG7m2kgcHJpY2UuICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgRiB2w6AgcHJpY2UgY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEogdsOgIHByaWNlIGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pXQuICANCg0KIyMgKipW4bq9IMSR4buTIHRo4buLIHRoZW8geCB2w6AgY29sb3IuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY29sb3IseCkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeD0geCx5PSBuKSkgKyANCiAgZ2VvbV9jb2woZmlsbD0gJ3Zpb2xldCcpICsgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgbGFicyggeD0gJ0xv4bqhaScsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDEyLjUgdMawxqFuZyDhu6luZyB24bubaSAxIMSRxqFuIHbhu4suICANCiAgKyBDw7MgNyDEkeG7kyB0aOG7iyA6IMSR4buTIHRo4buLIGxv4bqhaSBEIChjb2xvcikgduG7m2kgeCwgbG/huqFpIEUgduG7m2kgeCxsb+G6oWkgRiB24bubaSB4LCBsb+G6oWkgRyB24bubaSB4LGxv4bqhaSBIIHbhu5tpIHgsIGxv4bqhaSBJIHbhu5tpIHgsIGxv4bqhaSBKIHbhu5tpIHguICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgRyB2w6AgeCBjw7MgdOG6p24gc+G7kSB4deG6pXQgaGnhu4duIG5oaeG7gXUgbmjhuqV0IDsgSiB2w6AgeCBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgbmjhuqV0LiAgDQoNCiMjICoqVuG6vSDEkeG7kyB0aOG7iyB0aGVvIHkgdsOgIGNvbG9yLioqDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGNvbG9yLHkpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9IHkseT0gbikpICsgDQogIGdlb21fY29sKGZpbGw9ICdzYWxtb24nKSArIGZhY2V0X3dyYXAofmNvbG9yKSArDQogIGxhYnMoIHg9ICdMb+G6oWknLCB5PSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiBOaOG6rW4geMOpdDogIA0KICArIFThu7cgbOG7hyB0csOqbiBj4buZdCBz4buRIGzGsOG7o25nIGzDoCAxNSB0xrDGoW5nIOG7qW5nIHbhu5tpIDEgxJHGoW4gduG7iy4gIA0KICANCiAgKyBDw7MgNyDEkeG7kyB0aOG7iyA6IMSR4buTIHRo4buLIGxv4bqhaSBEIChjb2xvcikgduG7m2kgeSwgbG/huqFpIEUgduG7m2kgeSxsb+G6oWkgRiB24bubaSB5LCBsb+G6oWkgRyB24bubaSB5LGxv4bqhaSBIIHbhu5tpIHksIGxv4bqhaSBJIHbhu5tpIHksIGxv4bqhaSBKIHbhu5tpIHkuICANCiAgDQogICsgVGEgdGjhuqV5IHThu5UgaOG7o3AgZ2nhu69hIEUgdsOgIHkgY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCAgIA0KICANCiAgK0ogdsOgIHkgY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldCAsIGx1w7RuIGtoacOqbSB04buRbiBoxqFuIHNvIHbhu5tpIGPDoWMgbcOgdSBraMOhYy4gIA0KICANCiMjICoqVuG6vSDEkeG7kyB0aOG7iyB0aGVvIHogdsOgIGNvbG9yLioqDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGNvbG9yLHopICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9IHoseT0gbikpICsgDQogIGdlb21fY29sKGZpbGw9ICduYXZ5JykgKyBmYWNldF93cmFwKH5jb2xvcikgKw0KICBsYWJzKCB4PSAnTG/huqFpJywgeT0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgKyBU4bu3IGzhu4cgdHLDqm4gY+G7mXQgc+G7kSBsxrDhu6NuZyBsw6AgMTAwIHTGsMahbmcg4bupbmcgduG7m2kgMSDEkcahbiB24buLLiAgDQogICsgQ8OzIDcgxJHhu5MgdGjhu4sgOiDEkeG7kyB0aOG7iyBsb+G6oWkgRCAoY29sb3IpIHbhu5tpIHosIGxv4bqhaSBFIHbhu5tpIHosbG/huqFpIEYgduG7m2kgeiwgbG/huqFpIEcgduG7m2kgeixsb+G6oWkgSCB24bubaSB6LCBsb+G6oWkgSSB24bubaSB6LCBsb+G6oWkgSiB24bubaSB6LiAgDQogICsgVGEgdGjhuqV5IHThu5UgaOG7o3AgZ2nhu69hIEcgdsOgIHogY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEogdsOgIHogY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldC4gIA0KDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgdGhlbyBjYXJhdCB2w6AgY3V0LioqDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGN1dCxjYXJhdCkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeD0gY2FyYXQseT0gbikpICsgDQogIGdlb21fY29sKGZpbGw9ICdwaW5rJykgKyBmYWNldF93cmFwKH5jdXQpICsNCiAgbGFicyggeD0gJ0xv4bqhaScsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDEwMCB0xrDGoW5nIOG7qW5nIHbhu5tpIDEgxJHGoW4gduG7iy4gIA0KICArIEPDsyA1IMSR4buTIHRo4buLIDogxJHhu5MgdGjhu4sgbG/huqFpIEZhaXIgKGN1dCkgduG7m2kgY2FyYXQsIGxv4bqhaSBHb29kIHbhu5tpIGNhcmF0LGxv4bqhaSBWZXJ5IEdvb2QgduG7m2kgQ2FyYXQsIGxv4bqhaSBQcmVtaXVtIHbhu5tpIENhcmF0LGxv4bqhaSBJZGVhbCB24bubaSBjYXJhdC4gICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgSWRlYWwgdsOgIGNhcmF0IGPDsyB04bqnbiBz4buRIHh14bqldCBoaeG7h24gbmhp4buBdSBuaOG6pXQgOyBGYWlyIHbDoCBjYXJhdCBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgbmjhuqV0LiAgDQoNCiMjICoqVuG6vSDEkeG7kyB0aOG7iyB0aGVvIGN1dCB2w6AgcHJpY2UuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY3V0LHByaWNlKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4PSBwcmljZSx5PSBuKSkgKyANCiAgZ2VvbV9jb2woZmlsbD0gJ2Jyb3duJykgKyBmYWNldF93cmFwKH5jdXQpICsNCiAgbGFicyggeD0gJ0xv4bqhaScsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDEwIHTGsMahbmcg4bupbmcgduG7m2kgMSDEkcahbiB24buLLiAgDQogICsgQ8OzIDUgxJHhu5MgdGjhu4sgOiDEkeG7kyB0aOG7iyBsb+G6oWkgRmFpciAoY3V0KSB24bubaSBwcmljZSwgbG/huqFpIEdvb2QgduG7m2kgcHJpY2UsbG/huqFpIFZlcnkgR29vZCB24bubaSBwcmljZSwgbG/huqFpIFByZW1pdW0gduG7m2kgcHJpY2UsbG/huqFpIElkZWFsIHbhu5tpIHByaWNlLiAgIA0KICArIFRhIHRo4bqleSB04buVIGjhu6NwIGdp4buvYSBJZGVhbCB2w6AgcHJpY2UgY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEZhaXIgdsOgIHByaWNlIGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pXQuICANCiAgDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgdGhlbyBjdXQgdsOgIGNsYXJpdHkuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY3V0LGNsYXJpdHkpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9IGNsYXJpdHkseT0gbikpICsgDQogIGdlb21fY29sKGZpbGw9ICdyZWQnKSArIGZhY2V0X3dyYXAofmN1dCkgKw0KICBsYWJzKCB4PSAnTG/huqFpJywgeT0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgKyBU4bu3IGzhu4cgdHLDqm4gY+G7mXQgc+G7kSBsxrDhu6NuZyBsw6AgNTAwIHTGsMahbmcg4bupbmcgduG7m2kgMSDEkcahbiB24buLLiAgDQogICsgQ8OzIDUgxJHhu5MgdGjhu4sgOiDEkeG7kyB0aOG7iyBsb+G6oWkgRmFpciAoY3V0KSB24bubaSBjbGFyaXR5LCBsb+G6oWkgR29vZCB24bubaSBjbGFyaXR5LGxv4bqhaSBWZXJ5IEdvb2QgduG7m2kgY2xhcml0eSwgbG/huqFpIFByZW1pdW0gduG7m2kgY2xhcml0eSxsb+G6oWkgSWRlYWwgduG7m2kgY2xhcml0eS4gICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgSWRlYWwgdsOgIGNsYXJpdHkgY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEZhaXIgdsOgIGNsYXJpdHkgY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldC4gIA0KICArIFRyb25nIDUgxJHhu5MgdGjhu4sgdOG7lSBo4bujcCBTSTEgdsOgIGN1dCBsdcO0biBjw7MgdOG6p24gc+G7kSB4deG6pXQgaGnhu4duIGNhbyBuaOG6pXQuICANCiAgDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgdGhlbyBjdXQgdsOgIHRhYmxlLioqDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGN1dCx0YWJsZSkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeD0gdGFibGUseT0gbikpICsgDQogIGdlb21fY29sKGZpbGw9ICdibGFjaycpICsgZmFjZXRfd3JhcCh+Y3V0KSArDQogIGxhYnMoIHg9ICdMb+G6oWknLCB5PSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiBOaOG6rW4geMOpdDogIA0KICArIFThu7cgbOG7hyB0csOqbiBj4buZdCBz4buRIGzGsOG7o25nIGzDoCAxMDAwIHTGsMahbmcg4bupbmcgduG7m2kgMSDEkcahbiB24buLLiAgDQogICsgQ8OzIDUgxJHhu5MgdGjhu4sgOiDEkeG7kyB0aOG7iyBsb+G6oWkgRmFpciAoY3V0KSB24bubaSB0YWJsZSwgbG/huqFpIEdvb2QgduG7m2kgdGFibGUsbG/huqFpIFZlcnkgR29vZCB24bubaSB0YWJsZSwgbG/huqFpIFByZW1pdW0gduG7m2kgdGFibGUsbG/huqFpIElkZWFsIHbhu5tpIHRhYmxlLiAgIA0KICArIFRhIHRo4bqleSB04buVIGjhu6NwIGdp4buvYSBJZGVhbCB2w6AgdGFibGUgY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEZhaXIgdsOgIHRhYmxlIGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pXQuICANCiAgDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgdGhlbyBjdXQgdsOgIGRlcHRoLioqICANCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY3V0LGRlcHRoKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUgDQogIGdncGxvdChhZXMoeD1kZXB0aCx5PW4pKSArDQogIGdlb21fY29sKGZpbGw9ICdibHVlJykgKyBmYWNldF93cmFwKH5jdXQpICsNCiAgbGFicyh4PSAnTG/huqFpJyx5PSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiBOaOG6rW4geMOpdDogIA0KICArIFThu7cgbOG7hyB0csOqbiBj4buZdCBz4buRIGzGsOG7o25nIGzDoCAyNTAgdMawxqFuZyDhu6luZyB24bubaSAxIMSRxqFuIHbhu4suICANCiAgKyBDw7MgNSDEkeG7kyB0aOG7iyA6IMSR4buTIHRo4buLIGxv4bqhaSBGYWlyIChjdXQpIHbhu5tpIGRlcHRoLCBsb+G6oWkgR29vZCB24bubaSBkZXB0aCxsb+G6oWkgVmVyeSBHb29kIHbhu5tpIGRlcHRoLCBsb+G6oWkgUHJlbWl1bSB24bubaSBkZXB0aCxsb+G6oWkgSWRlYWwgduG7m2kgZGVwdGguICAgDQogICsgVGEgdGjhuqV5IHThu5UgaOG7o3AgZ2nhu69hIElkZWFsIHbDoCBkZXB0aCBjw7MgdOG6p24gc+G7kSB4deG6pXQgaGnhu4duIG5oaeG7gXUgbmjhuqV0IDsgRmFpciB2w6AgZGVwdGggY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldC4gIA0KICANCg0KIyMgKipW4bq9IMSR4buTIHRo4buLIHRoZW8gY3V0IHbDoCB4LioqICANCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY3V0LHgpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JSANCiAgZ2dwbG90KGFlcyh4PXgseT1uKSkgKw0KICBnZW9tX2NvbChmaWxsPSAndmlvbGV0JykgKyBmYWNldF93cmFwKH5jdXQpICsNCiAgbGFicyh4PSAnTG/huqFpJyx5PSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiBOaOG6rW4geMOpdDogIA0KICArIFThu7cgbOG7hyB0csOqbiBj4buZdCBz4buRIGzGsOG7o25nIGzDoCA1MCB0xrDGoW5nIOG7qW5nIHbhu5tpIDEgxJHGoW4gduG7iy4gIA0KICArIEPDsyA1IMSR4buTIHRo4buLIDogxJHhu5MgdGjhu4sgbG/huqFpIEZhaXIgKGN1dCkgduG7m2kgeCwgbG/huqFpIEdvb2QgduG7m2kgeCxsb+G6oWkgVmVyeSBHb29kIHbhu5tpIHgsIGxv4bqhaSBQcmVtaXVtIHbhu5tpIHgsbG/huqFpIElkZWFsIHbhu5tpIHguICAgDQogICsgVGEgdGjhuqV5IHThu5UgaOG7o3AgZ2nhu69hIElkZWFsIHbDoCB4IGPDsyB04bqnbiBz4buRIHh14bqldCBoaeG7h24gbmhp4buBdSBuaOG6pXQgOyBGYWlyIHbDoCB4IGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pXQuICANCiAgDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgdGhlbyBjdXQgdsOgIHkuKiogIA0KDQpgYGB7cixlY2hvPVRSVUV9DQpyICU+JSBncm91cF9ieShjdXQseSkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9eSx5PW4pKSArDQogIGdlb21fY29sKGZpbGw9ICdzYWxtb24nKSArIGZhY2V0X3dyYXAofmN1dCkgKw0KICBsYWJzKHg9ICdMb+G6oWknLHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDUwIHTGsMahbmcg4bupbmcgduG7m2kgMSDEkcahbiB24buLLiAgDQogICsgQ8OzIDUgxJHhu5MgdGjhu4sgOiDEkeG7kyB0aOG7iyBsb+G6oWkgRmFpciAoY3V0KSB24bubaSB5LCBsb+G6oWkgR29vZCB24bubaSB5LGxv4bqhaSBWZXJ5IEdvb2QgduG7m2kgeSwgbG/huqFpIFByZW1pdW0gduG7m2kgeSxsb+G6oWkgSWRlYWwgduG7m2kgeS4gICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgSWRlYWwgdsOgIHkgY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEZhaXIgdsOgIHkgY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldC4gIA0KICANCiMjICoqVuG6vSDEkeG7kyB0aOG7iyB0aGVvIGN1dCB2w6Agei4qKiAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGN1dCx6KSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUgDQogIGdncGxvdChhZXMoeD16LHk9bikpICsNCiAgZ2VvbV9jb2woZmlsbD0gJ25hdnknKSArIGZhY2V0X3dyYXAofmN1dCkgKw0KICBsYWJzKHg9ICdMb+G6oWknLHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgVOG7tyBs4buHIHRyw6puIGPhu5l0IHPhu5EgbMaw4bujbmcgbMOgIDUwIHTGsMahbmcg4bupbmcgduG7m2kgMSDEkcahbiB24buLLiAgDQogICsgQ8OzIDUgxJHhu5MgdGjhu4sgOiDEkeG7kyB0aOG7iyBsb+G6oWkgRmFpciAoY3V0KSB24bubaSB6LCBsb+G6oWkgR29vZCB24bubaSB6LGxv4bqhaSBWZXJ5IEdvb2QgduG7m2kgeiwgbG/huqFpIFByZW1pdW0gduG7m2kgeixsb+G6oWkgSWRlYWwgduG7m2kgei4gICANCiAgKyBUYSB0aOG6pXkgdOG7lSBo4bujcCBnaeG7r2EgSWRlYWwgdsOgIHogY8OzIHThuqduIHPhu5EgeHXhuqV0IGhp4buHbiBuaGnhu4F1IG5o4bqldCA7IEZhaXIgdsOgIHogY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldC4gIA0KICANCiMjICoqVuG6vSDEkeG7kyB0aOG7iyB0aGVvIHByaWNlIHbDoCBjb2xvciB0csOqbiBjw7luZyAxIMSR4buTIHRo4buLLioqICANCg0KDQpgYGB7cixlY2hvPVRSVUV9DQpyICU+JSBnZ3Bsb3QoYWVzKHggPSBwcmljZSwgZmlsbCA9IGNvbG9yKSkgKw0KICBnZW9tX2JhcigpICANCmBgYA0KDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgcGjDom4gbG/huqFpIHByaWNlLioqDQoNCiogVGhhbyB0w6FjIHRo4buxYyBoaeG7h24gOiBkw7luZyBtdXRhdGUgdOG6oW8gYmnhur9uIG3hu5tpIHTDqm4gcHJpY2UxIGfDoW4gY2hvIGPDoWMgZ2nDoSB0cuG7iyBwaMOibiBsb+G6oWkgcHJpY2UgdGhlbyAzIHRpw6p1IGNodeG6qW4gOnRo4bqlcCwgduG7q2EsIGNhby4gRMO5bmcgY3V0IMSR4buDIGPhuq90IHByaWNlIHRow6BuaCAzIG5ow7NtIGThu7FhIHRyw6puIGdpw6EgdHLhu4suICANCg0KYGBge3IsZWNobz1UUlVFfQ0KciA8LSByICU+JSBtdXRhdGUocHJpY2UxID0gY3V0KHByaWNlLDMsbGFiZWwgPSBjKCd0aOG6pXAnLCd24burYScsJ2NhbycpKSkNCnIgJT4lIGdncGxvdChhZXMoeD1wcmljZTEpKSArDQogIGdlb21fYmFyKGZpbGw9J3BpbmsnKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgKyBRdWFuIHPDoXQgYmnhu4N1IMSR4buTIHRhIHRo4bqleSBsb+G6oWkgZ2nDoSB0aOG6pXAgY8OzIHPhu5EgbMaw4bujbmcgbmhp4buBdSBuaOG6pXQsIGPDsm4gZ2nDoSBjYW8gY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldC4gIA0KDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgcGjDom4gbG/huqFpIGRlcHRoLioqICANCg0KKiBUaOG7sWMgaGnhu4duIHRoYW8gdMOhYyBnaeG7kW5nIHBow6JuIGxv4bqhaSBwcmljZS4gIA0KDQpgYGB7cixlY2hvPVRSVUV9DQpyIDwtIHIgJT4lIG11dGF0ZShkZXB0aDEgPSBjdXQoZGVwdGgsNCxsYWJlbCA9IGMoJ3LhuqV0IG5o4buPJywnbmjhu48nLCd24burYScsJ2zhu5tuJykpKQ0KciAlPiUgZ2dwbG90KGFlcyh4PWRlcHRoMSkpICsNCiAgZ2VvbV9iYXIoZmlsbD0nc2FsbW9uJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICsgTG/huqFpIGRlcHRoIHbhu6thIGPDsyBz4buRIGzGsOG7o25nIG5oaeG7gXUgbmjhuqV0Lg0KICArIEhhaSBsb+G6oWkgcuG6pXQgbmjhu48gdsOgIGzhu5tuIGPDsyBuaMawbmcgc+G7kSBsxrDhu6NuZyBy4bqldCDDrXQuICANCiAgDQojIyAqKlbhur0gxJHhu5MgdGjhu4sgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSB0YWJsZSB0aGVvIGJp4bq/biBjdXQuKioNCiAgDQoqIFRoYW8gdMOhYyB0aOG7sWMgaGnhu4duOg0KICArIEdyb3VwX2J5KGN1dCk6IHRo4buxYyBoaeG7h24gdmnhu4djIG5ow7NtIGThu68gbGnhu4d1IHRoZW8gY8OhYyBnacOhIHRy4buLIGPhu6dhIGJp4bq/biBjdXQuICANCiAgK1N1bW1hcmlzZSh3PW1lYW4odGFibGUpKTogdHJvbmcgbeG7l2kgbmjDs20gxJHGsOG7o2MgdOG6oW8gYuG7n2kgZ3JvdXBfYnksIHTDrW5oIGPDoWMgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIGdpw6EgdHLhu4sgdHJvbmcgYmnhur9uIHRhYmxlLCBsxrB1IHRy4buvIG7DsyB0cm9uZyAxIGJp4bq/biBt4bubaSBjw7MgdMOqbiB3LiAgDQogICthZXMobGFiZWwgPSByb3VuZCh3LCAyKSkgxJHhu4tuaCBk4bqhbmcgdsSDbiBi4bqjbiDEkcaw4bujYyBoaeG7g24gdGjhu4sgZMaw4bubaSBk4bqhbmcgY8OhYyBnacOhIHRy4buLIMSRxrDhu6NjIGzDoG0gdHLDsm4gKMSR4bq/biBoYWkgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4pIHRyb25nIGJp4bq/biB3LiAgDQogICt2anVzdCA9IDIgxJFp4buBdSBjaOG7iW5oIHbhu4sgdHLDrSB0aGVvIGNoaeG7gXUgZOG7jWMgY+G7p2EgY8OhYyBuaMOjbiB2xINuIGLhuqNuIGjGoWkgY2FvIGjGoW4gY8OhYyB0aGFuaCDEkeG7gyBk4buFIMSR4buNYyBoxqFuLiAgDQogICtjb2xvciA9ICdibGFjaycgxJHhurd0IG3DoHUgY+G7p2EgY8OhYyBuaMOjbiB2xINuIGLhuqNuIHRow6BuaCBtw6B1IMSRZW4uICANCg0KDQpgYGB7cixlY2hvPVRSVUV9DQpyICU+JSBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2Uodz1tZWFuKHRhYmxlKSkgJT4lDQogIGdncGxvdChhZXMoeD1jdXQseT13KSkgKyANCiAgZ2VvbV9jb2wocG9zaXRpb249ICdkb2RnZScsIGZpbGw9J3NhbG1vbicpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD0gcm91bmQodywyKSksdmp1c3Q9IDIsIGNvbG9yPSAnYmxhY2snKSArDQogICAgICAgICAgICAgIGxhYnMoeD0nY3V0JywgeT0gJ21lYW4nKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgK0Phu5l0IEZhaXIgY8OzIHRydW5nIGLDrG5oKMSRaeG7g20gY2jDrW5oIGdp4buvYSkgY2FvIG5o4bqldCA1OS4wNSB0aGVvIGJp4bq/biBjdXQuICANCiAgK0Phu5l0IElkZWFsIGPDsyB0cnVuZyBiw6xuaCB0aOG6pXAgbmjhuqV0IGzDoCA1NS45NSB0w61uaCB0aGVvIGN1dC4gIA0KICANCiMjICoqVuG6vSDEkeG7kyB0aOG7iyB0cnVuZyB24buLIGPhu6dhIGRlcHRoIHRoZW8gYmnhur9uIGNsYXJpdHkuKioNCg0KKiBUaGFvIHTDoWMgdGjhu7FjIGhp4buHbjoNCiAgKyBHcm91cF9ieShjbGFyaXR5KTogdGjhu7FjIGhp4buHbiB2aeG7h2MgbmjDs20gZOG7ryBsaeG7h3UgdGhlbyBjw6FjIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIGNsYXJpdHkuICANCiAgK1N1bW1hcmlzZSh3PW1lYW4oZGVwdGgpKTogdHJvbmcgbeG7l2kgbmjDs20gxJHGsOG7o2MgdOG6oW8gYuG7n2kgZ3JvdXBfYnksIHTDrW5oIGPDoWMgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIGdpw6EgdHLhu4sgdHJvbmcgYmnhur9uIGRlcHRoLCBsxrB1IHRy4buvIG7DsyB0cm9uZyAxIGJp4bq/biBt4bubaSBjw7MgdMOqbiBlLiAgDQogICthZXMobGFiZWwgPSByb3VuZChlLCAyKSkgxJHhu4tuaCBk4bqhbmcgdsSDbiBi4bqjbiDEkcaw4bujYyBoaeG7g24gdGjhu4sgZMaw4bubaSBk4bqhbmcgY8OhYyBnacOhIHRy4buLIMSRxrDhu6NjIGzDoG0gdHLDsm4gKMSR4bq/biBoYWkgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4pIHRyb25nIGJp4bq/biBlLiAgDQogICt2anVzdCA9IDIgxJFp4buBdSBjaOG7iW5oIHbhu4sgdHLDrSB0aGVvIGNoaeG7gXUgZOG7jWMgY+G7p2EgY8OhYyBuaMOjbiB2xINuIGLhuqNuIGjGoWkgY2FvIGjGoW4gY8OhYyB0aGFuaCDEkeG7gyBk4buFIMSR4buNYyBoxqFuLiAgDQogICtjb2xvciA9ICdyZWQnIMSR4bq3dCBtw6B1IGPhu6dhIGPDoWMgbmjDo24gdsSDbiBi4bqjbiB0aMOgbmggbcOgdSDEkeG7jy4gIA0KDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UoZT1tZWRpYW4oZGVwdGgpKSAlPiUNCiAgZ2dwbG90KGFlcyh4PWNsYXJpdHkseT1lKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbj0nZG9kZ2UnLGZpbGw9J3Zpb2xldCcpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChlLDIpKSwgdmp1c3Q9MiwgY29sb3I9J3JlZCcpICsgbGFicyh4PSdjbGFyaXR5Jyx5PSdtZWRpYW4nKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgK1F1YW4gc8OhdCBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IHRydW5nIHbhu4soxJFp4buDbSDhu58gZ2nhu69hKSBj4bunYSAgZGVwdGggdGhlbyBjw6FjIGxv4bqhaSBjbGFyaXR5IMSR4buBdSB44bqlcCB44buJIG5oYXUuICANCiAgK0Phu5l0IEkxIGPDsyDEkWnhu4NtIHRydW5nIHbhu4sgY2FvIG5o4bqldCBj4bunYSBkZXB0aCB0aGVvIEkxIGzDoCA2Mi4yLiAgDQoNCiMjICoqVuG6vSDEkeG7kyB0aGkgcGjGsMahbmcgc2FpIGPhu6dhIHkgdGhlbyBiaeG6v24gY29sb3IuKioNCg0KKiBUaGFvIHTDoWMgdGjhu7FjIGhp4buHbjoNCiAgKyBHcm91cF9ieShjb2xvcik6IHRo4buxYyBoaeG7h24gdmnhu4djIG5ow7NtIGThu68gbGnhu4d1IHRoZW8gY8OhYyBnacOhIHRy4buLIGPhu6dhIGJp4bq/biBjb2xvci4gIA0KICArU3VtbWFyaXNlKHc9bWVhbih5KSk6IHRyb25nIG3hu5dpIG5ow7NtIMSRxrDhu6NjIHThuqFvIGLhu59pIGdyb3VwX2J5LCB0w61uaCBjw6FjIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBnacOhIHRy4buLIHRyb25nIGJp4bq/biB5LCBsxrB1IHRy4buvIG7DsyB0cm9uZyAxIGJp4bq/biBt4bubaSBjw7MgdMOqbiBnLiAgDQogICthZXMobGFiZWwgPSByb3VuZChlLCAyKSkgxJHhu4tuaCBk4bqhbmcgdsSDbiBi4bqjbiDEkcaw4bujYyBoaeG7g24gdGjhu4sgZMaw4bubaSBk4bqhbmcgY8OhYyBnacOhIHRy4buLIMSRxrDhu6NjIGzDoG0gdHLDsm4gKMSR4bq/biBoYWkgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4pIHRyb25nIGJp4bq/biBnLiAgDQogICt2anVzdCA9IDIgxJFp4buBdSBjaOG7iW5oIHbhu4sgdHLDrSB0aGVvIGNoaeG7gXUgZOG7jWMgY+G7p2EgY8OhYyBuaMOjbiB2xINuIGLhuqNuIGjGoWkgY2FvIGjGoW4gY8OhYyB0aGFuaCDEkeG7gyBk4buFIMSR4buNYyBoxqFuLiAgDQogICtjb2xvciA9ICdibGFjaycgxJHhurd0IG3DoHUgY+G7p2EgY8OhYyBuaMOjbiB2xINuIGLhuqNuIHRow6BuaCBtw6B1IMSRZW4uICANCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UoZz12YXIoeSkpICU+JSANCiAgZ2dwbG90KGFlcyh4PWNvbG9yLHk9ZykpICsNCiAgZ2VvbV9jb2wocG9zaXRpb249J2RvZGdlJyxmaWxsPSduYXZ5JykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKGcsMikpLHZqdXN0PTIsIGNvbG9yPSdibGFjaycpICsgbGFicyh4PSdtw6B1Jyx5PSdwaMawxqFuZyBzYWknKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgK0Phu5l0IEggY8OzIHBoxrDGoW5nIHNhaSAoxJHhu5kgcGjDom4gdMOhbikgY+G7p2EgeSBjYW8gbmjhuqV0IGzDoCAxLjc0LiAgDQogICtD4buZdCBEIGPDsyBwaMawxqFuZyBzYWkgY+G7p2EgeSB0aOG6pXAgbmjhuqV0IGzDoCAwLjg4LiAgDQogIA0KIyMgKipW4bq9IMSR4buTIHRoaSBwaMawxqFuZyBzYWkgY+G7p2EgcHJpY2UgdGhlbyBiaeG6v24gY29sb3IuKioNCg0KKiBUaGFvIHTDoWMgdGjhu7FjIGhp4buHbjoNCiAgKyBHcm91cF9ieShjb2xvcik6IHRo4buxYyBoaeG7h24gdmnhu4djIG5ow7NtIGThu68gbGnhu4d1IHRoZW8gY8OhYyBnacOhIHRy4buLIGPhu6dhIGJp4bq/biBjb2xvci4gIA0KICArU3VtbWFyaXNlKHc9bWVhbihwcmljZSkpOiB0cm9uZyBt4buXaSBuaMOzbSDEkcaw4bujYyB04bqhbyBi4bufaSBncm91cF9ieSwgdMOtbmggY8OhYyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGPDoWMgZ2nDoSB0cuG7iyB0cm9uZyBiaeG6v24gcHJpY2UsIGzGsHUgdHLhu68gbsOzIHRyb25nIDEgYmnhur9uIG3hu5tpIGPDsyB0w6puIGsuICANCiAgK2FlcyhsYWJlbCA9IHJvdW5kKGssIDIpKSDEkeG7i25oIGThuqFuZyB2xINuIGLhuqNuIMSRxrDhu6NjIGhp4buDbiB0aOG7iyBkxrDhu5tpIGThuqFuZyBjw6FjIGdpw6EgdHLhu4sgxJHGsOG7o2MgbMOgbSB0csOybiAoxJHhur9uIGhhaSBjaOG7ryBz4buRIHRo4bqtcCBwaMOibikgdHJvbmcgYmnhur9uIGcuICANCiAgK3ZqdXN0ID0gMiDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIHRoZW8gY2hp4buBdSBk4buNYyBj4bunYSBjw6FjIG5ow6NuIHbEg24gYuG6o24gaMahaSBjYW8gaMahbiBjw6FjIHRoYW5oIMSR4buDIGThu4UgxJHhu41jIGjGoW4uICANCiAgK2NvbG9yID0gJ2JsYWNrJyDEkeG6t3QgbcOgdSBj4bunYSBjw6FjIG5ow6NuIHbEg24gYuG6o24gdGjDoG5oIG3DoHUgxJFlbi4gIA0KDQpgYGB7cixlY2hvPVRSVUV9DQpyICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShrPXZhcihwcmljZSkpICU+JSANCiAgZ2dwbG90KGFlcyh4PWNvbG9yLHk9aykpICsNCiAgZ2VvbV9jb2wocG9zaXRpb249J2RvZGdlJyxmaWxsPSdncmVlbicpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChrLDIpKSx2anVzdD0yLCBjb2xvcj0nYmxhY2snKSArIGxhYnMoeD0nbcOgdScseT0ncGjGsMahbmcgc2FpJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICtD4buZdCBJIGPDsyBwaMawxqFuZyBzYWkgKMSR4buZIHBow6JuIHTDoW4pIGPhu6dhIHByaWNlIGNhbyBuaOG6pXQgbMOgIDIyMzAwOTQ0LjY4LiAgDQogICtD4buZdCBFIGPDsyBwaMawxqFuZyBzYWkgY+G7p2EgcHJpY2UgdGjhuqVwIG5o4bqldCBsw6AgMTE4MzM5Ny4zMS4gIA0KICANCiMjICoqVuG6vSBiaeG7g3UgxJHhu5MgcGjGsMahbmcgc2FpIGPhu6dhIHggdGhlbyBjb2xvci4qKiANCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2Uobz12YXIoeCkpICU+JSANCiAgZ2dwbG90KGFlcyh4PWNvbG9yLHk9bykpICsNCiAgZ2VvbV9jb2wocG9zaXRpb249J2RvZGdlJyxmaWxsPSd5ZWxsb3cnKSArDQogIGdlb21fdGV4dChhZXMobGFiZWw9cm91bmQobywyKSksdmp1c3Q9MiwgY29sb3I9J2JsYWNrJykgKyBsYWJzKHg9J23DoHUnLHk9J3BoxrDGoW5nIHNhaScpDQpgYGANCg0KKiBOaOG6rW4geMOpdDogIA0KICArQ+G7mXQgSSBjw7MgcGjGsMahbmcgc2FpICjEkeG7mSBwaMOibiB0w6FuKSBj4bunYSB4IGNhbyBuaOG6pXQgbMOgIDEuNTcuICANCiAgK0Phu5l0IEQgY8OzIHBoxrDGoW5nIHNhaSBj4bunYSB4IHRo4bqlcCBuaOG6pXQgbMOgIDAuODguICANCg0KIyMgKipW4bq9IGJp4buDdSDEkeG7kyBwaMawxqFuZyBzYWkgY+G7p2EgeiB0aGVvIGNvbG9yLioqIA0KDQpgYGB7cixlY2hvPVRSVUV9DQpyICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZSh1PXZhcih6KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9Y29sb3IseT11KSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbj0nZG9kZ2UnLGZpbGw9J3NhbG1vbicpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZCh1LDIpKSx2anVzdD0yLCBjb2xvcj0nYmxhY2snKSArIGxhYnMoeD0nbcOgdScseT0ncGjGsMahbmcgc2FpJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICtD4buZdCBJIGPDsyBwaMawxqFuZyBzYWkgKMSR4buZIHBow6JuIHTDoW4pIGPhu6dhIHogY2FvIG5o4bqldCBsw6AgMC41OS4gIA0KICArQ+G7mXQgRCBjw7MgcGjGsMahbmcgc2FpIGPhu6dhIHogdGjhuqVwIG5o4bqldCBsw6AgMC4zMy4NCiAgDQojIyAqKlbhur0gYmnhu4N1IMSR4buTIHBoxrDGoW5nIHNhaSBj4bunYSB4IHRoZW8gY2xhcml0eS4qKiANCg0KYGBge3IsZWNobz1UUlVFfQ0KciAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShqPXZhcih4KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9Y2xhcml0eSx5PWopKSArDQogIGdlb21fY29sKHBvc2l0aW9uPSdkb2RnZScsZmlsbD0ncGluaycpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZChqLDIpKSx2anVzdD0yLCBjb2xvcj0nYmxhY2snKSArIGxhYnMoeD0nY2xhcml0eScseT0ncGjGsMahbmcgc2FpJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogICtD4buZdCBWUzEgY8OzIHBoxrDGoW5nIHNhaSAoxJHhu5kgcGjDom4gdMOhbikgY+G7p2EgeCBjYW8gbmjhuqV0IGzDoCAxLjE4LiAgDQogICtD4buZdCBWVlMxIGPDsyBwaMawxqFuZyBzYWkgY+G7p2EgeCB0aOG6pXAgbmjhuqV0IGzDoCAwLjcyLiAgDQogIA0KIyMgKipW4bq9IGJp4buDdSDEkeG7kyBwaMawxqFuZyBzYWkgY+G7p2EgeSB0aGVvIGNsYXJpdHkuKiogDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UoZj12YXIoeSkpICU+JSANCiAgZ2dwbG90KGFlcyh4PWNsYXJpdHkseT1mKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbj0nZG9kZ2UnLGZpbGw9J2JsdWUnKSArDQogIGdlb21fdGV4dChhZXMobGFiZWw9cm91bmQoZiwyKSksdmp1c3Q9MiwgY29sb3I9J2JsYWNrJykgKyBsYWJzKHg9J2NsYXJpdHknLHk9J3BoxrDGoW5nIHNhaScpDQpgYGANCg0KKiBOaOG6rW4geMOpdDogIA0KICArQ+G7mXQgU0kxIGPDsyBwaMawxqFuZyBzYWkgKMSR4buZIHBow6JuIHTDoW4pIGPhu6dhIHkgY2FvIG5o4bqldCBsw6AgMS40LiAgDQogICtD4buZdCBWVlMxIGPDsyBwaMawxqFuZyBzYWkgY+G7p2EgeSB0aOG6pXAgbmjhuqV0IGzDoCAwLjcyLiAgDQogIA0KIyMgKipW4bq9IGJp4buDdSDEkeG7kyBwaMawxqFuZyBzYWkgY+G7p2EgeiB0aGVvIGNsYXJpdHkuKiogDQoNCmBgYHtyLGVjaG89VFJVRX0NCnIgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UoZD12YXIoeikpICU+JSANCiAgZ2dwbG90KGFlcyh4PWNsYXJpdHkseT1kKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbj0nZG9kZ2UnLGZpbGw9J2Jyb3duJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKGQsMikpLHZqdXN0PTIsIGNvbG9yPSdibGFjaycpICsgbGFicyh4PSdjbGFyaXR5Jyx5PSdwaMawxqFuZyBzYWknKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgK0Phu5l0IFZTMSBjw7MgcGjGsMahbmcgc2FpICjEkeG7mSBwaMOibiB0w6FuKSBj4bunYSB6IGNhbyBuaOG6pXQgbMOgIDAuNTMuICANCiAgK0Phu5l0IFZWUzEgY8OzIHBoxrDGoW5nIHNhaSBj4bunYSB6IHRo4bqlcCBuaOG6pXQgbMOgIDAuMjcuICANCiAgDQo=