1. Giới thiệu về bộ dữ liệu Diamonds

Bộ dữ liệu Diamonds

  • Bộ dữ liệu Diamonds là một tập dữ liệu phổ biến được sử dụng trong khoa học dữ liệu và học máy. Nó bao gồm thông tin về 53.940 viên kim cương, với các thuộc tính sau:
  1. carat: Trọng lượng carat của viên kim cương

  2. cut: Chất lượng cắt (Excellent, Very Good, Good, Fair, Poor)

  3. color: Màu sắc (D, E, F, G, H, I, J, K)

  4. clarity: Độ tinh khiết (FL, IF, VVS1, VVS2, VS1, VS2, SI1, SI2, I1, I2, I3)

  5. depth: Tỷ lệ chiều sâu (phần trăm)

  6. table: Tỷ lệ mặt bàn (phần trăm)

  7. price: Giá bán (USD)

  8. x: Chiều dài (mm)

  9. y: Chiều rộng (mm)

  10. z: Chiều sâu (mm)

  • Bộ dữ liệu có cấu trúc bao gồm: 53940 hàng tương ứng với 53940 quan sát và 10 cột tương ứng với 10 biến.
dim(tn)
## [1] 53940    10
  • Bộ dữ liệu Diamonds bao gồm có 10 cột (biến) lần lượt như sau: carat, cut, color, clarity, depth, table, price, x, y, z.
names(tn)
##  [1] "carat"   "cut"     "color"   "clarity" "depth"   "table"   "price"  
##  [8] "x"       "y"       "z"

2. Phân tích bộ dữ liệu Diamonds với các đặc tính của nó

2.1 Carat (Trọng lượng)

  • Cara hay Carat là đơn vị đo khối lượng sử dụng trong ngành đá quý, nó tương đương với 0,2 gram (200 miligram). Trong đời sống hằng ngày, mọi người thường gọi chúng là Cara và viên kim cương có mức cara càng cao thì càng có giá trị.

  • Ta tiến hành chia trọng lượng viên kim cương thành 5 nhóm để dễ dàng nhận thấy

table(cut(tn$carat,5))
## 
## (0.195,1.16]  (1.16,2.12]  (2.12,3.09]  (3.09,4.05]  (4.05,5.01] 
##        43781         9478          667           11            3
  • Sau khi phân chia, ta được 5 nhóm có trọng lượng và số lượng tương ứng với mỗi nhóm như sau:
  1. Rất nhẹ (0.195 đến bằng 1.16 carat): 43781 kim cương

  2. Nhẹ (1.16 đến bằng 2.12 carat): 9478 kim cương

  3. Vừa (2.12 đến bằng 3.09 carat): 667 kim cương

  4. Nặng (3.09 đến bằng 4.05 carat): 11 kim cương

  5. Rất nặng (4.05 đến bằng 5.01): 3 kim cương

=> Qua đó ta có thể nhận xét như sau: Trọng lượng của viên kim cương càng thấp thì số lượng càng cao và ngược lại.

tn <- diamonds
tn1 <- tn %>% mutate(TL = cut(carat,5, label = c('Rất nhẹ', 'Nhẹ','Vừa','Nặng','Rất nặng')))
tn1 %>% group_by(TL) %>% summarise(n = n()) %>%
  ggplot(aes(TL,n)) +
    geom_col(fill='blue') +
    labs(title = " Biểu đồ thể hiện nhóm theo trọng lượng ") +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Trọng Lượng', y = 'Số lượng')

  • Ngoài ra, để có thể dễ dàng nhận thấy từng loại kim cương chiếm bao nhiêu % trong tổng số, ta tiến hành chuyển đổi biểu đồ số lượng thành biểu đồ thể hiện %:
library(scales)
tn1 <- tn %>% mutate(TL = cut(carat,5, label = c('Rất nhẹ', 'Nhẹ','Vừa','Nặng','Rất nặng')))
tn1 %>% group_by(TL) %>% summarise(n = n()) %>%
  ggplot(aes(TL,n)) +
    geom_col(fill='purple') +
    labs(title = " Biểu đồ thể hiện % thang đo trọng lượng ") +
    theme_classic() +
    geom_text(aes(label = percent(n/length(tn$carat))),vjust = 0, color = 'black') +
    labs(x = 'Trọng Lượng', y = 'Số lượng')

2.2 Cut (Giác cắt)

Chữ C này chính là yếu tố quan trọng nhất để xác định được giá trị của kim cương trong 4C.

  • Biểu đồ này hiển thị 5 loại giác cắt kim cương trong bộ dữ liệu, loại Ideal chiếm số lượng kim cương cao nhất, còn loại Fair chiếm số lượng kim cương thấp nhất, tỷ lệ phần trăm của từng loại như sau:
  1. Loại Fair (Trung bình): 3.0%

  2. Loại Good (Tốt): 9.1%

  3. Loại Very Good (Rất tốt): 22.4%

  4. Loại Premium (Tuyệt hảo): 25.6%

  5. Loại Ideal (Lý tưởng): 40.0%

tn %>% group_by(cut) %>% summarise(n = n()) %>%
  ggplot(aes(cut,n)) +
    geom_col(fill='green') +
    labs(title = "Biểu đồ thể hiện % tỷ lệ giác cắt ") +
    theme_classic() +
    geom_text(aes(label = percent(n/length(tn$cut))),vjust = 2, color = 'red') +
    labs(x = 'Giác cắt', y = 'Số lượng')

  • Số lượng cụ thể của từng loại như sau:
  1. Loại Fair (Trung bình): 1610 kim cương

  2. Loại Good (Tốt): 4906 kim cương

  3. Loại Very Good (Rất tốt): 12082 kim cương

  4. Loại Premium (Tuyệt hảo): 13791 kim cương

  5. Loại Ideal (Lý tưởng): 21551 kim cương

tn %>% group_by(cut) %>% summarise(n = n()) %>%
  ggplot(aes(cut,n)) +
    geom_col(fill='yellow') +
    geom_text(aes(label = n),vjust = 2, color = 'red') +
    labs(title = 'Biểu đồ số lượng kim cương theo giác cắt', x = 'Loại', y = 'Số lượng')

2.3 Color (Màu sắc)

Kim cương thường sẽ có màu trắng (hay hồng, xanh, nâu, vàng), và nếu màu sắc càng trắng thì sẽ có trị càng cao. Thang màu được bắt đầu từ ký hiệu D và giảm dần dần xuống E, F, G, H, I, J, Z.

Những kim cương từ cấp độ D – F sẽ là loại không màu; từ G – J là loại có màu vàng một chút, rất ít; cấp độ từ K – M là loại màu vàng nhạt; N – R là loại kim cương có màu vàng nhìn khá rõ, và từ cấp độ S – Z là loại có màu vàng sáng rõ rệt nhất.

  • Biểu đồ này cho thấy tần suất xuất hiện của từng màu sắc của kim cương trong bộ dữ liệu theo đơn vị %.
tn %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(n,color)) +
    geom_col(fill='lightblue') +
    labs(title = "Biểu đồ thể hiện % thang đo màu sắc ") +
    theme_classic() +
    geom_text(aes(label = percent(n/length(tn$color))),vjust = 1, color = 'black') +
    labs(x = 'Số lượng', y = 'Màu sắc')

  • Ngoài ra, để có thể nhìn thấy chi tiết hơn về số liệu, ta tiến hành vẽ thêm biểu đồ số lượng kim cương theo màu sắc để có thể nhìn thấy một cách rõ nhất về sự chênh lệch của chúng, như sau:
  1. D (không màu, trắng tinh khiết): 6775 kim cương

  2. E (không màu, trắng tinh khiết): 9797 kim cương

  3. F (không màu, trắng tinh khiết): 9542 kim cương

  4. G (tựa không màu, trắng hiếm): 11292 kim cương

  5. H (tựa không màu, trắng hiếm): 8304 kim cương

  6. I (tựa không màu, trắng nhạt): 5422 kim cương

  7. J (tựa không màu, trắng nhạt): 2808 kim cương

tn %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(color,n)) +
    geom_col(fill='blue') +
    geom_text(aes(label = n),vjust = 2, color = 'white') +
    labs(title = 'Biểu đồ số lượng kim cương theo màu sắc', x = 'Màu sắc', y = 'Số lượng')

Vậy loại kim cương màu G chiếm số lượng cao nhất là 11292 viên, loại kim cương chiếm số lượng thấp nhất là loại kim cương màu J là 2808 viên.

2.4 Clarity (Độ tinh khiết)

Chỉ một vài thứ trong tự nhiên là hoàn hảo tuyệt đối. Điều này đúng với kim cương như mọi thứ khác. Kim cương có các đặc điểm bên trong, được gọi là inclusion – bao thể và các dấu vết còn sót trên bề mặt, được gọi là blemish – dấu vết bề mặt. Kết hợp 2 yếu tố này, chúng được gọi là đặc điểm độ sạch. Độ sạch – độ tinh khiết là sự vắng mặt tương đối của các bao thể và các dấu vết bề mặt.

Có 11 cấp độ sạch trong hệ thống phân cấp độ sạch của GIA. Chúng là Flawless (FL), Internally Flawless (IF), hai cấp Very, Very Slightly Included (VVS), hai cấp Very Slightly Included (VS), hai cấp Slightly Included (SI) và ba cấp Included (I).

  • Biểu đồ tỷ lệ phần trăm độ tinh khiết của kim cương
tn %>% group_by(clarity) %>% summarise(n = n()) %>%
  ggplot(aes(clarity,n)) +
    geom_col(fill='green') +
    labs(title = "Biểu đồ thể hiện % tỷ lệ độ tinh khiết ") +
    theme_classic() +
    geom_text(aes(label = percent(n/length(tn$clarity))),vjust = 2, color = 'red') +
    labs(x = 'Độ tinh khiết', y = 'Số lượng')

Biểu đồ cho thấy số lượng viên kim cương theo độ tinh khiết có sự phân hóa rõ rệt. Cụ thể được thể hiện bao số liệu như sau:

  • I1 (bao thể rõ): 741 kim cương

  • SI2 (bao thể nhỏ, rất dễ nhận thấy): 9194 kim cương

  • SI1 (bao thể nhỏ, dễ nhận thấy): 13065 kim cương

  • VS2 (bao thể nhỏ cấp 2): 12258 kim cương

  • VS1 (bao thể nhỏ cấp 1): 8171 kim cương

  • VSS2 (bao thể rất nhỏ cấp 2): 5066 kim cương

  • VSS1 (bao thể rất nhỏ cấp 1): 3655 kim cương

  • IF (Hoàn toàn tinh khiết): 1790 kim cương

tn %>% group_by(clarity) %>% summarise(n = n()) %>%
  ggplot(aes(clarity,n)) +
    geom_col(fill='pink') +
    geom_text(aes(label = n),vjust = 2, color = 'black') +
    labs(title= 'Biều đồ số lượng kim cương theo độ tinh khiết', x = 'Độ tinh khiết', y = 'Số lượng')

=> Vậy độ tinh khiết loại SI1 chiếm số lượng nhiều nhất là 13065 viên kim cương, độ tinh khiết loại I1 chiếm số lượng thấp nhất là 741 viên kim cương.

2.5 Depth (Tỷ lệ chiều sâu %)

Diamond Depth dùng chỉ chiều sâu hay còn là chiều cao của kim cương. Được tính từ bề mặt đến đầu nhọn của khối lập phương trên viên kim cương. Độ sâu từ 57,7%-63% là lý tưởng nhất để phản xạ ánh sáng hoàn hảo.

Ta tiến hành phân chia kim cương thành 2 loại: Lý tưởng (57,5%-63%), chưa lý tưởng (<57,5% và >63%)

tn$group <- ifelse(tn$depth >= 57.3 & tn$depth <= 63, "Lý tưởng", "Chưa lý tưởng")
table(tn$group)
## 
## Chưa lý tưởng      Lý tưởng 
##          7344         46596
tn %>% group_by(group) %>% summarise(n = n()) %>%
  ggplot(aes(group,n)) +
    geom_col(fill='gray') +
    geom_text(aes(label = n),vjust = 2, color = 'red') +
    labs(title = " Biểu đồ thể hiện nhóm theo Độ sâu ",x = 'Độ sâu', y = 'Số lượng') 

=> Vậy số viên kim cương lý tưởng (46596) có số lượng cao gấp 6 lần số viên kim cương chưa lý tưởng (7344).

2.6 Table (Tỷ lệ mặt bàn %)

Mỗi viên kim cương đều có một mặt phẳng có hình vuông nằm ở trên đỉnh. Mặt phẳng này chính là Diamond Table hay bề mặt của kim cương. Nó có vai trò vô cùng quan trọng trong việc xác định hình dáng của viên đá.

  • Đối với viên kim cương giác mặt tròn: Lý tưởng (54%-60%), chưa lý tưởng (<54% và >60%)
tn$tron <- ifelse(tn$table >= 54 & tn$table <= 60, "Lý tưởng", "Chưa lý tưởng")
table(tn$tron)
## 
## Chưa lý tưởng      Lý tưởng 
##          5624         48316
tn %>% group_by(tron) %>% summarise(n = n()) %>%
  ggplot(aes(tron,n)) +
    geom_col(fill='gray') +
    geom_text(aes(label = n),vjust = 2, color = 'black') +
    labs(title = " Biểu đồ thể hiện nhóm theo giác cắt tròn ",x = 'Mặt bàn', y = 'Số lượng') 

  • Đối với viên kim cương giác mặt lục bảo: Lý tưởng (66%-72%), chưa lý tưởng (<66% và >72%)
tn$lucbao <- ifelse(tn$table >= 66 & tn$table <= 72, "Lý tưởng", "Chưa lý tưởng")
table(tn$lucbao)
## 
## Chưa lý tưởng      Lý tưởng 
##         53767           173
tn %>% group_by(lucbao) %>% summarise(n = n()) %>%
  ggplot(aes(lucbao,n)) +
    geom_col(fill='gray') +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(title = " Biểu đồ thể hiện nhóm theo giác cắt lục bảo ",x = 'Mặt bàn', y = 'Số lượng') 

2.7 Price (Giá thành)

Kim cương được định giá một cách cơ bản dựa trên tiêu chuẩn 4C bao gồm: Carat - Trọng lượng hoặc kích thước của viên kim cương. Color - Màu sắc của viên kim cương. Clarity - Độ tinh khiết hay độ sạch của viên kim cương hay còn gọi là sự vắng mặt của những tạp chất bên trong và các khiếm khuyết bên ngoài.

Trước tiên, ta chia giá thành của kim cương thành 3 nhóm: Rẻ - Vừa - Đắt:

table(cut(tn$price,3))
## 
##      (308,6.49e+03] (6.49e+03,1.27e+04] (1.27e+04,1.88e+04] 
##               43591                7347                3002

Sau khi tiến hành phân chia xong, ta nhận được số lượng tương ứng với mỗi nhóm giá thành như sau:

  1. Rẻ: 43591 viên kim cương
  2. Vừa: 7347 viên kim cương
  3. Đắt: 3002 viên kim cương

Ta tiến hành vẽ biểu đồ để nhìn rõ sự chệnh lệch số lượng về giá:

tn <- diamonds
tn2 <- tn %>% mutate(gt = cut(price,3, label = c('Rẻ','Vừa','Đắt')))
tn2 %>% group_by(gt) %>% summarise(n = n()) %>%
  ggplot(aes(gt,n)) +
    geom_col(fill='blue') +
    labs(title = " Biểu đồ thể hiện nhóm theo giá") +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Giá', y = 'Số lượng')

2.8 Phân tích chuyên sâu lồng ghép các đặc tính lại với nhau.

Để có thể phân tích kĩ càng cũng như hiểu rỏ hơn về các đặc tính của kim cương. Ta có thể phân tích kết hợp 2 hay nhiều yếu tố lại với nhau trên cùng một biểu đồ Bar chart giúp ta dễ quan sát cũng như dễ dàng so sánh chúng.

Cut - Color

Đây một biểu đồ cột xếp chồng hiển thị tần suất tương đối của biến “cut” và màu fill của các cột dựa trên biến “color”. Biểu đồ này giúp bạn có cái nhìn về phân phối của biến “cut” và “color” trong khung dữ liệu “tn”.

ggplot(tn, aes(x = cut, fill = color)) +
  geom_bar(position = "fill") +
  labs(title = "Tần suất của Cut và Color", x = "Cut", y = "Tần suất") +
  scale_fill_brewer(palette = "Paired") +
  theme_minimal()

Carat - Color - Clarity

Biểu đồ cột này hiển thị giá trị trung bình của biến “price” dựa trên các nhóm “cut” và màu fill của các cột dựa trên biến “clarity”. Biểu đồ này giúp bạn so sánh giá trị trung bình của “price” giữa các nhóm “cut” và xem liệu sự rõ ràng (“clarity”) có ảnh hưởng đến giá trị trung bình không.

tn %>% ggplot(aes(x = cut, y = price, fill = clarity)) +
  geom_bar(stat = "summary", fun.y = "mean", position = "dodge")

Biểu đồ này sẽ giúp bạn phân tích sự khác biệt về giá trị trung bình của “price” giữa các nhóm “cut”. Bạn cũng có thể xem xét tương quan giữa sự rõ ràng (“clarity”) và giá trị trung bình của “price” bằng cách quan sát sự khác biệt màu fill của các cột giữa các nhóm “clarity”.

Cut - Clarity - Color

Biểu đồ cột xếp chồng này cho thấy tần suất của các loại cắt kim cương (“cut”) theo giá trị của biến “clarity”. Mỗi cột biểu thị một loại cắt kim cương và được chia thành các phần tương ứng với các giá trị của biến “clarity”.

Dựa trên biểu đồ, chúng ta có thể nhận thấy một số kết quả sau:

  1. Loại cắt “Ideal” có tần suất cao nhất trong tất cả các mức độ rõ ràng (“clarity”). Đây có thể là loại cắt phổ biến nhất trong tập dữ liệu.

  2. Cắt “Premium” và “Very Good” cũng có tần suất khá cao trong tất cả các mức độ rõ ràng (“clarity”).

  3. Cắt “Fair” có tần suất thấp nhất trong tất cả các mức độ rõ ràng (“clarity”).

  4. Mức độ rõ ràng “SI2” và “I1” có tần suất cao nhất trong các loại cắt, trong khi mức độ rõ ràng “IF” và “VVS1” có tần suất thấp nhất.

  5. Các loại cắt khác nhau có phân phối khác nhau của các mức độ rõ ràng (“clarity”). Ví dụ, cắt “Ideal” và “Premium” có tần suất cao nhất ở mức độ rõ ràng “SI1” và “VS2”, trong khi cắt “Fair” có tần suất cao nhất ở mức độ rõ ràng “I1”.

ggplot(tn, aes(x = cut, fill = clarity)) +
  geom_bar(position = "fill") +
  labs(title = "Tần suất của các loại cắt kim cương theo giá trị", x = "Cắt", y = "Tần suất") +
  scale_fill_brewer(palette = "Paired") +
  theme_minimal()

Biểu đồ này cung cấp một cái nhìn tổng quan về mối quan hệ giữa các loại cắt kim cương và giá trị của biến “clarity”. Nó giúp chúng ta hiểu được phân phối của các loại cắt trong mỗi mức độ rõ ràng, cho phép phân tích sự tương quan giữa hai biến này.

Color - Cut

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Màu sắc “G” và “E” có tần suất cao nhất trong các loại cắt, với loại cắt “Ideal” và “Premium” chiếm tỷ lệ lớn.

  2. Màu sắc “J” có tần suất thấp nhất trong các loại cắt, đặc biệt là loại cắt “Fair” và “Good”.

  3. Cắt “Fair” và “Good” có tần suất tương đối cao trong màu sắc “H” và “I”.

  4. Cắt “Very Good” có tần suất tương đối cao trong màu sắc “F”.

  5. Cắt “Ideal” có tần suất cao trong màu sắc “D”.

Biểu đồ cung cấp một cái nhìn tổng quan về tần suất của các nhóm loại cắt trong từng mức độ màu sắc. Nó giúp chúng ta hiểu được mối quan hệ giữa loại cắt và màu sắc của kim cương trong tập dữ liệu.

tn %>% group_by(cut,color) %>% summarise(n=n()) %>%
  ggplot(aes(x = cut,y = n)) +
    geom_col(position = 'dodge') +
    facet_wrap(~color) +
    geom_text(aes(label = n),vjust = 0, color = 'green') +
    labs(tittle='Color - Cut',x = 'Loại', y = 'Số lượng')

Cut - Clarity

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Mức độ rõ ràng “SI1” và “SI2” có tần suất cao nhất trong các loại cắt, với loại cắt “Ideal” và “Premium” chiếm tỷ lệ lớn.

  2. Mức độ rõ ràng “I1” có tần suất thấp nhất trong các loại cắt, đặc biệt là loại cắt “Fair” và “Good”.

  3. Cắt “Fair” và “Good” có tần suất tương đối cao trong mức độ rõ ràng “SI2”.

  4. Cắt “Ideal” có tần suất cao trong mức độ rõ ràng “VVS1” và “VVS2”.

  5. Cắt “Very Good” có tần suất tương đối cao trong mức độ rõ ràng “VS1” và “VS2”.

Biểu đồ cung cấp một cái nhìn tổng quan về tần suất của các nhóm loại cắt trong từng mức độ rõ ràng. Nó giúp chúng ta hiểu được mối quan hệ giữa loại cắt và mức độ rõ ràng của kim cương trong tập dữ liệu.

tn %>% group_by(cut,clarity) %>% summarise(n=n()) %>%
  ggplot(aes(x = cut,y = n)) +
    geom_col(position = 'dodge') +
    facet_wrap(~clarity) +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Loại', y = 'Số lượng')

Color - Clarity

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Mức độ rõ ràng “SI1” và “SI2” có tần suất cao nhất trong các loại cắt, với loại cắt “Ideal” và “Premium” chiếm tỷ lệ lớn.

  2. Mức độ rõ ràng “I1” có tần suất thấp nhất trong các loại cắt, đặc biệt là loại cắt “Fair” và “Good”.

  3. Cắt “Fair” và “Good” có tần suất tương đối cao trong mức độ rõ ràng “SI2”.

  4. Cắt “Ideal” có tần suất cao trong mức độ rõ ràng “VVS1” và “VVS2”.

  5. Cắt “Very Good” có tần suất tương đối cao trong mức độ rõ ràng “VS1” và “VS2”.

Biểu đồ cho thấy tần suất của các nhóm loại cắt trong từng mức độ rõ ràng. Màu nền xanh làm nổi bật các cột và giúp phân biệt các nhóm. Các con số tần suất được hiển thị trên cột tương ứng với màu chữ đỏ. Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa loại cắt và mức độ rõ ràng của kim cương trong tập dữ liệu.

tn %>% group_by(cut,clarity) %>% summarise(n=n()) %>%
  ggplot(aes(x = cut,y = n)) +
    geom_col(fill = 'green') +
    facet_wrap(~clarity) +
    geom_text(aes(label = n),vjust = 0, color = 'red') +
    labs(x = 'Loại', y = 'Số lượng')

Clarity - Color

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Màu sắc “G” và “E” có tần suất cao nhất trong các mức độ tinh khiết, với mức độ tinh khiết “SI1” và “SI2” chiếm tỷ lệ lớn.

  2. Màu sắc “J” có tần suất thấp nhất trong các mức độ tinh khiết, đặc biệt là mức độ tinh khiết “I1” và “IF”.

  3. Mức độ tinh khiết “I1” có tần suất tương đối cao trong màu sắc “H” và “I”.

  4. Mức độ tinh khiết “IF” có tần suất cao trong màu sắc “D” và “E”.

  5. Mức độ tinh khiết “SI1” và “SI2” có tần suất tương đối cao trong màu sắc “F”.

Biểu đồ cho thấy tần suất của các nhóm mức độ tinh khiết trong từng màu sắc. Màu nền xanh nhạt làm nổi bật các cột và giúp phân biệt các nhóm. Các con số tần suất được hiển thị trên cột tương ứng với màu chữ đen. Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa mức độ tinh khiết và màu sắc của kim cương trong tập dữ liệu.

tn %>% group_by(color,clarity) %>% summarise(n=n()) %>%
  ggplot(aes(x = clarity,y = n)) +
    geom_col(fill = 'lightblue') +
    facet_wrap(~color) +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Mức độ tinh khiết', y = 'Số lượng')

Cut - Mean Carat

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Loại cắt “Ideal” có giá trị trung bình cao nhất cho chỉ số “carat”, theo sau là “Premium” và “Very Good”.

  2. Loại cắt “Fair” và “Good” có giá trị trung bình thấp nhất cho chỉ số “carat”.

Biểu đồ cho thấy sự khác biệt về giá trị trung bình của chỉ số “carat” giữa các loại cắt của kim cương. Màu nền hồng làm nổi bật các cột và giúp phân biệt các loại cắt. Các con số giá trị trung bình được hiển thị trên cột tương ứng với màu chữ trắng. Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa loại cắt và trọng lượng trung bình của kim cương trong tập dữ liệu.

tn %>% group_by(cut) %>% summarise(m= mean(carat)) %>%
  ggplot(aes(x = cut,y = m)) +
    geom_col(fill = 'pink') +
    geom_text(aes(label = round(m,2)), vjust = 2, color = 'white') +
    labs(x = 'Loại', y = 'Mean')

  • Nhóm “Fair” có giá trị trung bình cao nhất (1.05 carat).

  • Nhóm “Ideal” có giá trị trung bình thấp nhất (0.7 carat).

  • Nhìn chung, giá trị trung bình của biến “carat”giảm dần từ nhóm “Fair” đến nhóm “Ideal”. Suy ra, kiểu cắt kim cương ảnh hưởng đến giá trị trung bình của biến “carat”.

Color - Mean Carat

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Màu sắc “J” có giá trị trung bình cao nhất cho chỉ số “carat”, theo sau là “I” và “H”.

  2. Màu sắc “D” có giá trị trung bình thấp nhất cho chỉ số “carat”.

Biểu đồ cho thấy sự khác biệt về giá trị trung bình của chỉ số “carat” giữa các màu sắc của kim cương. Màu nền cam làm nổi bật các cột và giúp phân biệt các màu sắc. Các con số giá trị trung bình được hiển thị trên cột tương ứng với màu chữ đỏ. Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa màu sắc và trọng lượng trung bình của kim cương trong tập dữ liệu.

tn %>% group_by(color) %>% summarise(m= mean(carat)) %>%
  ggplot(aes(x = color,y = m)) +
    geom_col(fill ='orange') +
    geom_text(aes(label = round(m,2)), vjust = 2, color = 'red') +
    labs(x = 'Màu', y = 'Mean')

Clarity - Mean Carat

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Mức độ tinh khiết “I1” có giá trị trung bình cao nhất cho chỉ số “carat”, theo sau là “SI2” và “SI1”.

  2. Mức độ tinh khiết “IF” có giá trị trung bình thấp nhất cho chỉ số “carat”.

Biểu đồ cho thấy sự khác biệt về giá trị trung bình của chỉ số “carat” giữa các mức độ tinh khiết của kim cương. Màu nền trắng làm nổi bật các cột và giúp phân biệt các mức độ tinh khiết. Các con số giá trị trung bình được hiển thị trên cột tương ứng với màu chữ xanh. Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa mức độ tinh khiết và trọng lượng trung bình của kim cương trong tập dữ liệu.

tn %>% group_by(clarity) %>% summarise(m= mean(carat)) %>%
  ggplot(aes(x = clarity,y = m)) +
    geom_col(fill ='white') +
    geom_text(aes(label = round(m,2)), vjust = 2, color = 'blue') +
    labs(x = 'Mức Độ Tinh Khiết', y = 'Mean')

Cut - Mean Price

Giác cắt của kim cương cũng là 1 phần quan trọng ảnh hưởng đến giá bán của chúng. Biểu đồ dưới đây cho ta thấy trung bình giá thành theo từng loại giác cắt.

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Loại cắt “Premium” có giá trị trung bình cao nhất cho giá kim cương, theo sau là “Very Good” và “Ideal”.

  2. Loại cắt “Fair” có giá trị trung bình thấp nhất cho giá kim cương.

Biểu đồ cho thấy sự khác biệt về giá trị trung bình của kim cương giữa các loại cắt. Màu nền xám làm nổi bật các cột và giúp phân biệt các loại cắt. Các con số giá trị trung bình được hiển thị trên cột tương ứng với màu chữ trắng. Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa loại cắt và giá trị trung bình của kim cương trong tập dữ liệu.

tn %>% group_by(cut) %>% summarise(mp= mean(price)) %>%
  ggplot(aes(x = cut,y = mp)) +
    geom_col(fill='grey') +
    geom_text(aes(label = round(mp,2)), vjust = 2, color = 'white') +
    labs(x = 'Loại', y = 'Mean Price')

Color - Mean Price

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Màu sắc “J” có giá trị trung bình cao nhất cho giá kim cương, theo sau là “I” và “H”.

  2. Màu sắc “D” có giá trị trung bình thấp nhất cho giá kim cương.

Biểu đồ cho thấy sự khác biệt về giá trị trung bình của kim cương giữa các màu sắc. Mỗi cột được phân chia theo màu sắc, giúp chúng ta so sánh giá trị trung bình giữa các màu sắc khác nhau. Các con số giá trị trung bình được hiển thị trên cột tương ứng với màu chữ đỏ. Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa màu sắc và giá trị trung bình của kim cương trong tập dữ liệu.

tn %>% group_by(color) %>% summarise(mp= mean(price)) %>%
  ggplot(aes(x = color,y = mp)) +
    geom_col(position = 'dodge') +
    geom_text(aes(label = round(mp,2)), vjust = 2, color = 'red') +
    labs(x = 'Màu', y = 'Mean Price')

Clarity - Mean Price

Dựa trên biểu đồ, chúng ta có thể rút ra một số kết quả sau:

  1. Mức độ tinh khiết “I1” có giá trị trung bình cao nhất cho giá kim cương, theo sau là “SI2” và “SI1”.

  2. Mức độ tinh khiết “IF” có giá trị trung bình thấp nhất cho giá kim cương.

Biểu đồ cho thấy sự khác biệt về giá trị trung bình của kim cương giữa các mức độ tinh khiết. Màu nền nâu làm nổi bật các cột và giúp phân biệt các mức độ tinh khiết. Các con số giá trị trung bình được hiển thị trên cột tương ứng với màu chữ xanh. Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa mức độ tinh khiết và giá trị trung bình của kim cương trong tập dữ liệu.

tn %>% group_by(clarity) %>% summarise(mp= mean(price)) %>%
  ggplot(aes(x = clarity,y = mp)) +
    geom_col(fill='brown') +
    geom_text(aes(label = round(mp,2)), vjust = 2, color = 'blue') +
    labs(x = 'Mức Độ Tinh Khiết', y = 'Mean')

Color - Price

Dựa trên biểu đồ histogram, chúng ta có thể rút ra một số kết quả sau:

  1. Phân phối giá của kim cương có dạng lệch phải, tức là có nhiều kim cương có giá trị thấp hơn và ít kim cương có giá trị cao hơn.

  2. Màu sắc của kim cương được phân bố khá đều trong phạm vi giá.

Biểu đồ histogram giúp chúng ta hiểu được phân phối của giá kim cương trong tập dữ liệu và quan sát mối quan hệ giữa giá và màu sắc của kim cương. Tuy nhiên, để có một phân tích chi tiết hơn về mối quan hệ này, chúng ta có thể cần sử dụng các phương pháp phân tích thống kê khác như phân tích hồi quy hoặc phân tích phân tán.

tn %>% ggplot(aes(x = price, fill = color)) +
  geom_histogram(binwidth = 2000)

Mean Table - Cut - Color

Biểu đồ được chia thành nhiều phần nhỏ (facet) dựa trên màu sắc của kim cương. Mỗi phần nhỏ chứa các cột biểu thị giá trị trung bình của “table” cho từng loại cắt. Các con số giá trị trung bình được hiển thị trên cột tương ứng với màu chữ hồng.

Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa loại cắt, màu sắc và giá trị trung bình của “table” trong tập dữ liệu. Mỗi phần nhỏ trong biểu đồ cho phép chúng ta so sánh giá trị trung bình của “table” giữa các loại cắt khác nhau trong cùng một màu sắc của kim cương.

tn %>% group_by(cut, color)%>%summarise(m=mean(table))%>%ggplot(aes(x=cut, y= m))+
  geom_col(fill ='violet')+
  facet_wrap(~color)+
  geom_text(aes(label= round(m)), vjust=2, color='pink')+ labs(x= 'cut', y= 'Mean',title='Giá trị trung bình của table theo cut và color')

Mean Price - Cut - Clarity

Biểu đồ được chia thành nhiều phần nhỏ (facet) dựa trên mức độ tinh khiết của kim cương. Mỗi phần nhỏ chứa các cột biểu thị giá trị trung bình của “price” cho từng loại cắt. Các con số giá trị trung bình được hiển thị trên cột tương ứng với màu chữ hồng.

Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa loại cắt, mức độ tinh khiết và giá trị trung bình của “price” trong tập dữ liệu. Mỗi phần nhỏ trong biểu đồ cho phép chúng ta so sánh giá trị trung bình của “price” giữa các loại cắt khác nhau trong cùng một mức độ tinh khiết của kim cương.

tn %>% group_by(cut, clarity)%>%summarise(m=mean(price))%>%ggplot(aes(x=cut, y= m))+
  geom_col(fill='blue')+
  facet_wrap(~clarity)+
  geom_text(aes(label= round(m)), vjust=1, color='pink')+ labs(x= 'cut', y= 'Mean',title='Giá trị trung bình của price theo cut và clarity')

Var Depth - Clarity - Color

Biểu đồ được chia thành nhiều phần nhỏ (facet) dựa trên màu sắc của kim cương. Mỗi phần nhỏ chứa các cột biểu thị phương sai của “depth” cho từng mức độ tinh khiết. Các con số phương sai được hiển thị trên cột tương ứng với màu chữ đỏ.

Biểu đồ giúp chúng ta hiểu được mối quan hệ giữa mức độ tinh khiết, màu sắc và phương sai của “depth” trong tập dữ liệu. Mỗi phần nhỏ trong biểu đồ cho phép chúng ta so sánh phương sai của “depth” giữa các mức độ tinh khiết khác nhau trong cùng một màu sắc của kim cương.

tn %>% group_by(clarity,color)%>%summarise(m=var(depth))%>%ggplot(aes(x=clarity, y= m))+
  geom_col(fill='lightgreen')+
  facet_wrap(~color)+
  geom_text(aes(label= round(m)), vjust=0.5, color='red')+ labs(x= 'clarity', y= 'Var',title='Phương sai của depth theo clarity và color')

Tổng kim cương theo Color - Clarity

Dữ liệu được nhóm theo hai biến: cut - color. Trục x của biểu đồ là các loại “cut”, và trục y là số lượng mẫu. Hai cột được vẽ, mỗi cột đại diện cho một màu sắc: “E” và “H”. Phần màu hồng đại diện cho màu “E”, trong khi phần màu nâu đại diện cho màu “H”.

Biểu đồ giúp chúng ta hiểu được sự phân bố của số lượng các mẫu dựa trên màu sắc và mức độ tinh khiết của kim cương trong tập dữ liệu. Trục x biểu thị màu sắc và trục y biểu thị số lượng.

t <- tn %>% group_by(color, clarity) %>% summarise(n = n())
t %>% ggplot(aes(x = color, y = n)) +
  geom_col(data = t %>% filter(clarity == 'SI2'), fill = 'pink') +
  geom_col(data = t %>% filter(clarity == 'VS1'), fill = 'brown') +
  labs(x= 'Màu sắc', y= 'Số lượng')

LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA0Ig0KYXV0aG9yOiAiTMOibSBUw6JtIE5oxrAiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclSDolTTolUywgJWQgLSAlbSAtICVZJylgIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDogDQogICAgaGlnaGxpZ2h0OiBrYXRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRoZW1lOiBwYXBlcg0KICAgIGRmX3ByaW50OiBrYWJsZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KdG4gPC0gZGlhbW9uZHMNCmBgYA0KDQojICoqMS4gR2nhu5tpIHRoaeG7h3UgduG7gSBi4buZIGThu68gbGnhu4d1IERpYW1vbmRzKioNCg0KIyMgKipC4buZIGThu68gbGnhu4d1IERpYW1vbmRzKioNCg0KLSAgIELhu5kgZOG7ryBsaeG7h3UgRGlhbW9uZHMgbMOgIG3hu5l0IHThuq1wIGThu68gbGnhu4d1IHBo4buVIGJp4bq/biDEkcaw4bujYyBz4butIGThu6VuZyB0cm9uZyBraG9hIGjhu41jIGThu68gbGnhu4d1IHbDoCBo4buNYyBtw6F5LiBOw7MgYmFvIGfhu5NtIHRow7RuZyB0aW4gduG7gSA1My45NDAgdmnDqm4ga2ltIGPGsMahbmcsIHbhu5tpIGPDoWMgdGh14buZYyB0w61uaCBzYXU6DQoNCjEuICAgKipjYXJhdCoqOiBUcuG7jW5nIGzGsOG7o25nIGNhcmF0IGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nDQoNCjIuICAqKmN1dCoqOiBDaOG6pXQgbMaw4bujbmcgY+G6r3QgKEV4Y2VsbGVudCwgVmVyeSBHb29kLCBHb29kLCBGYWlyLCBQb29yKQ0KDQozLiAgKipjb2xvcioqOiBNw6B1IHPhuq9jIChELCBFLCBGLCBHLCBILCBJLCBKLCBLKQ0KDQo0LiAgKipjbGFyaXR5Kio6IMSQ4buZIHRpbmgga2hp4bq/dCAoRkwsIElGLCBWVlMxLCBWVlMyLCBWUzEsIFZTMiwgU0kxLCBTSTIsIEkxLCBJMiwgSTMpDQoNCjUuICAqKmRlcHRoKio6IFThu7cgbOG7hyBjaGnhu4F1IHPDonUgKHBo4bqnbiB0csSDbSkNCg0KNi4gICoqdGFibGUqKjogVOG7tyBs4buHIG3hurd0IGLDoG4gKHBo4bqnbiB0csSDbSkNCg0KNy4gICoqcHJpY2UqKjogR2nDoSBiw6FuIChVU0QpDQoNCjguICAqKngqKjogQ2hp4buBdSBkw6BpIChtbSkNCg0KOS4gICoqeSoqOiBDaGnhu4F1IHLhu5luZyAobW0pDQoNCjEwLiAqKnoqKjogQ2hp4buBdSBzw6J1IChtbSkNCg0KLSAgIELhu5kgZOG7ryBsaeG7h3UgY8OzIGPhuqV1IHRyw7pjIGJhbyBn4buTbTogNTM5NDAgaMOgbmcgdMawxqFuZyDhu6luZyB24bubaSA1Mzk0MCBxdWFuIHPDoXQgdsOgIDEwIGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgMTAgYmnhur9uLg0KDQpgYGB7cn0NCmRpbSh0bikNCmBgYA0KDQotICAgQuG7mSBk4buvIGxp4buHdSBEaWFtb25kcyBiYW8gZ+G7k20gY8OzIDEwIGPhu5l0IChiaeG6v24pIGzhuqduIGzGsOG7o3QgbmjGsCBzYXU6IGNhcmF0LCBjdXQsIGNvbG9yLCBjbGFyaXR5LCBkZXB0aCwgdGFibGUsIHByaWNlLCB4LCB5LCB6Lg0KDQpgYGB7cn0NCm5hbWVzKHRuKQ0KYGBgDQoNCiMgKioyLiBQaMOibiB0w61jaCBi4buZIGThu68gbGnhu4d1IERpYW1vbmRzIHbhu5tpIGPDoWMgxJHhurdjIHTDrW5oIGPhu6dhIG7DsyoqDQoNCiMjICoqMi4xIENhcmF0IChUcuG7jW5nIGzGsOG7o25nKSoqDQoNCi0gICBDYXJhIGhheSBDYXJhdCBsw6AgxJHGoW4gduG7iyDEkW8ga2jhu5FpIGzGsOG7o25nIHPhu60gZOG7pW5nIHRyb25nIG5nw6BuaCDEkcOhIHF1w70sIG7DsyB0xrDGoW5nIMSRxrDGoW5nIHbhu5tpIDAsMiBncmFtICgyMDAgbWlsaWdyYW0pLiBUcm9uZyDEkeG7nWkgc+G7kW5nIGjhurFuZyBuZ8OgeSwgbeG7jWkgbmfGsOG7nWkgdGjGsOG7nW5nIGfhu41pIGNow7puZyBsw6AgQ2FyYSB2w6AgdmnDqm4ga2ltIGPGsMahbmcgY8OzIG3hu6ljIGNhcmEgY8OgbmcgY2FvIHRow6wgY8OgbmcgY8OzIGdpw6EgdHLhu4suDQoNCi0gICBUYSB0aeG6v24gaMOgbmggY2hpYSB0cuG7jW5nIGzGsOG7o25nIHZpw6puIGtpbSBjxrDGoW5nIHRow6BuaCAqKjUgbmjDs20qKiDEkeG7gyBk4buFIGTDoG5nIG5o4bqtbiB0aOG6pXkNCg0KYGBge3J9DQp0YWJsZShjdXQodG4kY2FyYXQsNSkpDQpgYGANCg0KLSAgIFNhdSBraGkgcGjDom4gY2hpYSwgdGEgxJHGsOG7o2MgNSBuaMOzbSBjw7MgdHLhu41uZyBsxrDhu6NuZyB2w6Agc+G7kSBsxrDhu6NuZyB0xrDGoW5nIOG7qW5nIHbhu5tpIG3hu5dpIG5ow7NtIG5oxrAgc2F1Og0KDQoxLiAgKipS4bqldCBuaOG6uSoqICgwLjE5NSDEkeG6v24gYuG6sW5nIDEuMTYgY2FyYXQpOiA0Mzc4MSBraW0gY8awxqFuZw0KDQoyLiAgKipOaOG6uSoqICgxLjE2IMSR4bq/biBi4bqxbmcgMi4xMiBjYXJhdCk6IDk0Nzgga2ltIGPGsMahbmcNCg0KMy4gICoqVuG7q2EqKiAoMi4xMiDEkeG6v24gYuG6sW5nIDMuMDkgY2FyYXQpOiA2Njcga2ltIGPGsMahbmcNCg0KNC4gICoqTuG6t25nKiogKDMuMDkgxJHhur9uIGLhurFuZyA0LjA1IGNhcmF0KTogMTEga2ltIGPGsMahbmcNCg0KNS4gICoqUuG6pXQgbuG6t25nKiogKDQuMDUgxJHhur9uIGLhurFuZyA1LjAxKTogMyBraW0gY8awxqFuZw0KDQoqKj1cPioqIFF1YSDEkcOzIHRhIGPDsyB0aOG7gyBuaOG6rW4geMOpdCBuaMawIHNhdTogKipUcuG7jW5nIGzGsOG7o25nIGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nIGPDoG5nIHRo4bqlcCB0aMOsIHPhu5EgbMaw4bujbmcgY8OgbmcgY2FvIHbDoCBuZ8aw4bujYyBs4bqhaS4qKg0KDQpgYGB7cn0NCnRuIDwtIGRpYW1vbmRzDQp0bjEgPC0gdG4gJT4lIG11dGF0ZShUTCA9IGN1dChjYXJhdCw1LCBsYWJlbCA9IGMoJ1LhuqV0IG5o4bq5JywgJ05o4bq5JywnVuG7q2EnLCdO4bq3bmcnLCdS4bqldCBu4bq3bmcnKSkpDQp0bjEgJT4lIGdyb3VwX2J5KFRMKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKFRMLG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0nYmx1ZScpICsNCiAgICBsYWJzKHRpdGxlID0gIiBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG5ow7NtIHRoZW8gdHLhu41uZyBsxrDhu6NuZyAiKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ1Ry4buNbmcgTMaw4bujbmcnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCi0gICBOZ2/DoGkgcmEsIMSR4buDIGPDsyB0aOG7gyBk4buFIGTDoG5nIG5o4bqtbiB0aOG6pXkgdOG7q25nIGxv4bqhaSBraW0gY8awxqFuZyBjaGnhur9tIGJhbyBuaGnDqnUgJSB0cm9uZyB04buVbmcgc+G7kSwgdGEgdGnhur9uIGjDoG5oIGNodXnhu4NuIMSR4buVaSBiaeG7g3UgxJHhu5Mgc+G7kSBsxrDhu6NuZyB0aMOgbmggYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiAlOg0KDQpgYGB7cn0NCmxpYnJhcnkoc2NhbGVzKQ0KdG4xIDwtIHRuICU+JSBtdXRhdGUoVEwgPSBjdXQoY2FyYXQsNSwgbGFiZWwgPSBjKCdS4bqldCBuaOG6uScsICdOaOG6uScsJ1bhu6thJywnTuG6t25nJywnUuG6pXQgbuG6t25nJykpKQ0KdG4xICU+JSBncm91cF9ieShUTCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhUTCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3B1cnBsZScpICsNCiAgICBsYWJzKHRpdGxlID0gIiBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duICUgdGhhbmcgxJFvIHRy4buNbmcgbMaw4bujbmcgIikgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgodG4kY2FyYXQpKSksdmp1c3QgPSAwLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnVHLhu41uZyBMxrDhu6NuZycsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KIyMgKioyLjIgQ3V0IChHacOhYyBj4bqvdCkqKg0KDQpDaOG7ryBDIG7DoHkgY2jDrW5oIGzDoCB54bq/dSB04buRIHF1YW4gdHLhu41uZyBuaOG6pXQgxJHhu4MgeMOhYyDEkeG7i25oIMSRxrDhu6NjIGdpw6EgdHLhu4sgY+G7p2Ega2ltIGPGsMahbmcgdHJvbmcgNEMuDQoNCi0gICBCaeG7g3UgxJHhu5MgbsOgeSBoaeG7g24gdGjhu4sgKio1IGxv4bqhKippIGdpw6FjIGPhuq90IGtpbSBjxrDGoW5nIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UsIGxv4bqhaSAqSWRlYWwqIGNoaeG6v20gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBbY2FvXXsudW5kZXJsaW5lfSBbbmjhuqV0XXsudW5kZXJsaW5lfSwgY8OybiBsb+G6oWkgKkZhaXIqIGNoaeG6v20gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBbdGjhuqVwIG5o4bqldF17LnVuZGVybGluZX0sIHThu7cgbOG7hyBwaOG6p24gdHLEg20gY+G7p2EgdOG7q25nIGxv4bqhaSBuaMawIHNhdToNCg0KMS4gICoqTG/huqFpIEZhaXIqKiAoVHJ1bmcgYsOsbmgpOiAzLjAlDQoNCjIuICAqKkxv4bqhaSBHb29kKiogKFThu5F0KTogOS4xJQ0KDQozLiAgKipMb+G6oWkgVmVyeSBHb29kKiogKFLhuqV0IHThu5F0KTogMjIuNCUNCg0KNC4gICoqTG/huqFpIFByZW1pdW0qKiAoVHV54buHdCBo4bqjbyk6IDI1LjYlDQoNCjUuICAqKkxv4bqhaSBJZGVhbCoqIChMw70gdMaw4bufbmcpOiA0MC4wJQ0KDQpgYGB7cn0NCnRuICU+JSBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY3V0LG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0nZ3JlZW4nKSArDQogICAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duICUgdOG7tyBs4buHIGdpw6FjIGPhuq90ICIpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKHRuJGN1dCkpKSx2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgICBsYWJzKHggPSAnR2nDoWMgY+G6r3QnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCi0gICBT4buRIGzGsOG7o25nIGPhu6UgdGjhu4MgY+G7p2EgdOG7q25nIGxv4bqhaSBuaMawIHNhdToNCg0KMS4gICoqTG/huqFpIEZhaXIqKiAoVHJ1bmcgYsOsbmgpOiAxNjEwIGtpbSBjxrDGoW5nDQoNCjIuICAqKkxv4bqhaSBHb29kKiogKFThu5F0KTogNDkwNiBraW0gY8awxqFuZw0KDQozLiAgKipMb+G6oWkgVmVyeSBHb29kKiogKFLhuqV0IHThu5F0KTogMTIwODIga2ltIGPGsMahbmcNCg0KNC4gICoqTG/huqFpIFByZW1pdW0qKiAoVHV54buHdCBo4bqjbyk6IDEzNzkxIGtpbSBjxrDGoW5nDQoNCjUuICAqKkxv4bqhaSBJZGVhbCoqIChMw70gdMaw4bufbmcpOiAyMTU1MSBraW0gY8awxqFuZw0KDQpgYGB7cn0NCnRuICU+JSBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY3V0LG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0neWVsbG93JykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgICBsYWJzKHRpdGxlID0gJ0Jp4buDdSDEkeG7kyBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gZ2nDoWMgY+G6r3QnLCB4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KIyMgKioyLjMgQ29sb3IgKE3DoHUgc+G6r2MpKioNCg0KS2ltIGPGsMahbmcgdGjGsOG7nW5nIHPhur0gY8OzIG3DoHUgdHLhuq9uZyAoaGF5IGjhu5NuZywgeGFuaCwgbsOidSwgdsOgbmcpLCB2w6AgbuG6v3UgbcOgdSBz4bqvYyBjw6BuZyB0cuG6r25nIHRow6wgc+G6vSBjw7MgdHLhu4sgY8OgbmcgY2FvLiBUaGFuZyBtw6B1IMSRxrDhu6NjIGLhuq90IMSR4bqndSB04burIGvDvSBoaeG7h3UgRCB2w6AgZ2nhuqNtIGThuqduIGThuqduIHh14buRbmcgRSwgRiwgRywgSCwgSSwgSiwgWi4NCg0KTmjhu69uZyBraW0gY8awxqFuZyB04burIGPhuqVwIMSR4buZIEQg4oCTIEYgc+G6vSBsw6AgbG/huqFpIGtow7RuZyBtw6B1OyB04burIEcg4oCTIEogbMOgIGxv4bqhaSBjw7MgbcOgdSB2w6BuZyBt4buZdCBjaMO6dCwgcuG6pXQgw610OyBj4bqlcCDEkeG7mSB04burIEsg4oCTIE0gbMOgIGxv4bqhaSBtw6B1IHbDoG5nIG5o4bqhdDsgTiDigJMgUiBsw6AgbG/huqFpIGtpbSBjxrDGoW5nIGPDsyBtw6B1IHbDoG5nIG5ow6xuIGtow6EgcsO1LCB2w6AgdOG7qyBj4bqlcCDEkeG7mSBTIOKAkyBaIGzDoCBsb+G6oWkgY8OzIG3DoHUgdsOgbmcgc8OhbmcgcsO1IHLhu4d0IG5o4bqldC4NCg0KLSAgIEJp4buDdSDEkeG7kyBuw6B5IGNobyB0aOG6pXkgdOG6p24gc3XhuqV0IHh14bqldCBoaeG7h24gY+G7p2EgdOG7q25nIG3DoHUgc+G6r2MgY+G7p2Ega2ltIGPGsMahbmcgdHJvbmcgYuG7mSBk4buvIGxp4buHdSB0aGVvIMSRxqFuIHbhu4sgJS4NCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMobixjb2xvcikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdsaWdodGJsdWUnKSArDQogICAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duICUgdGhhbmcgxJFvIG3DoHUgc+G6r2MgIikgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgodG4kY29sb3IpKSksdmp1c3QgPSAxLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnU+G7kSBsxrDhu6NuZycsIHkgPSAnTcOgdSBz4bqvYycpDQpgYGANCg0KLSAgIE5nb8OgaSByYSwgxJHhu4MgY8OzIHRo4buDIG5ow6xuIHRo4bqleSBjaGkgdGnhur90IGjGoW4gduG7gSBz4buRIGxp4buHdSwgdGEgdGnhur9uIGjDoG5oIHbhur0gdGjDqm0gYmnhu4N1IMSR4buTIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jIMSR4buDIGPDsyB0aOG7gyBuaMOsbiB0aOG6pXkgbeG7mXQgY8OhY2ggcsO1IG5o4bqldCB24buBIHPhu7EgY2jDqm5oIGzhu4djaCBj4bunYSBjaMO6bmcsIG5oxrAgc2F1Og0KDQoxLiAgRCAoa2jDtG5nIG3DoHUsIHRy4bqvbmcgdGluaCBraGnhur90KTogNjc3NSBraW0gY8awxqFuZw0KDQoyLiAgRSAoa2jDtG5nIG3DoHUsIHRy4bqvbmcgdGluaCBraGnhur90KTogOTc5NyBraW0gY8awxqFuZw0KDQozLiAgRiAoa2jDtG5nIG3DoHUsIHRy4bqvbmcgdGluaCBraGnhur90KTogOTU0MiBraW0gY8awxqFuZw0KDQo0LiAgRyAodOG7sWEga2jDtG5nIG3DoHUsIHRy4bqvbmcgaGnhur9tKTogMTEyOTIga2ltIGPGsMahbmcNCg0KNS4gIEggKHThu7FhIGtow7RuZyBtw6B1LCB0cuG6r25nIGhp4bq/bSk6IDgzMDQga2ltIGPGsMahbmcNCg0KNi4gIEkgKHThu7FhIGtow7RuZyBtw6B1LCB0cuG6r25nIG5o4bqhdCk6IDU0MjIga2ltIGPGsMahbmcNCg0KNy4gIEogKHThu7FhIGtow7RuZyBtw6B1LCB0cuG6r25nIG5o4bqhdCk6IDI4MDgga2ltIGPGsMahbmcNCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY29sb3IsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdibHVlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDIsIGNvbG9yID0gJ3doaXRlJykgKw0KICAgIGxhYnModGl0bGUgPSAnQmnhu4N1IMSR4buTIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jJywgeCA9ICdNw6B1IHPhuq9jJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQpW4bqteSBsb+G6oWkga2ltIGPGsMahbmcgKiptw6B1IEcqKiBjaGnhur9tIHPhu5EgbMaw4bujbmcgKipjYW8gbmjhuqV0KiogbMOgIDExMjkyIHZpw6puLCBsb+G6oWkga2ltIGPGsMahbmcgY2hp4bq/bSBz4buRIGzGsOG7o25nICoqdGjhuqVwKiogKipuaOG6pXQqKiBsw6AgbG/huqFpIGtpbSBjxrDGoW5nICoqbcOgdSBKKiogbMOgIDI4MDggdmnDqm4uDQoNCiMjICoqMi40IENsYXJpdHkgKMSQ4buZIHRpbmgga2hp4bq/dCkqKg0KDQpDaOG7iSBt4buZdCB2w6BpIHRo4bupIHRyb25nIHThu7Egbmhpw6puIGzDoCBob8OgbiBo4bqjbyB0dXnhu4d0IMSR4buRaS4gxJBp4buBdSBuw6B5IMSRw7puZyB24bubaSBraW0gY8awxqFuZyBuaMawIG3hu41pIHRo4bupIGtow6FjLiBLaW0gY8awxqFuZyBjw7MgY8OhYyDEkeG6t2MgxJFp4buDbSBiw6puIHRyb25nLCDEkcaw4bujYyBn4buNaSBsw6AgaW5jbHVzaW9uIOKAkyBiYW8gdGjhu4MgdsOgIGPDoWMgZOG6pXUgduG6v3QgY8OybiBzw7N0IHRyw6puIGLhu4EgbeG6t3QsIMSRxrDhu6NjIGfhu41pIGzDoCBibGVtaXNoIOKAkyBk4bqldSB24bq/dCBi4buBIG3hurd0LiBL4bq/dCBo4bujcCAyIHnhur91IHThu5EgbsOgeSwgY2jDum5nIMSRxrDhu6NjIGfhu41pIGzDoCDEkeG6t2MgxJFp4buDbSDEkeG7mSBz4bqhY2guIMSQ4buZIHPhuqFjaCDigJMgxJHhu5kgdGluaCBraGnhur90IGzDoCBz4buxIHbhuq9uZyBt4bq3dCB0xrDGoW5nIMSR4buRaSBj4bunYSBjw6FjIGJhbyB0aOG7gyB2w6AgY8OhYyBk4bqldSB24bq/dCBi4buBIG3hurd0Lg0KDQpDw7MgMTEgY+G6pXAgxJHhu5kgc+G6oWNoIHRyb25nIGjhu4cgdGjhu5FuZyBwaMOibiBj4bqlcCDEkeG7mSBz4bqhY2ggY+G7p2HCoCoqR0lBKiouIENow7puZyBsw6AgRmxhd2xlc3PCoCoqKEZMKSoqLCBJbnRlcm5hbGx5IEZsYXdsZXNzwqAqKihJRikqKiwgaGFpIGPhuqVwIFZlcnksIFZlcnkgU2xpZ2h0bHkgSW5jbHVkZWTCoCoqKFZWUykqKiwgaGFpIGPhuqVwIFZlcnkgU2xpZ2h0bHkgSW5jbHVkZWTCoCoqKFZTKSoqLCBoYWkgY+G6pXAgU2xpZ2h0bHkgSW5jbHVkZWTCoCoqKFNJKSoqwqB2w6AgYmEgY+G6pXAgSW5jbHVkZWTCoCoqKEkpKiouDQoNCi0gICBCaeG7g3UgxJHhu5MgdOG7tyBs4buHIHBo4bqnbiB0csSDbSDEkeG7mSB0aW5oIGtoaeG6v3QgY+G7p2Ega2ltIGPGsMahbmcNCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjbGFyaXR5LG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0nZ3JlZW4nKSArDQogICAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duICUgdOG7tyBs4buHIMSR4buZIHRpbmgga2hp4bq/dCAiKSArDQogICAgdGhlbWVfY2xhc3NpYygpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGVyY2VudChuL2xlbmd0aCh0biRjbGFyaXR5KSkpLHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICfEkOG7mSB0aW5oIGtoaeG6v3QnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCkJp4buDdSDEkeG7kyBjaG8gdGjhuqV5IHPhu5EgbMaw4bujbmcgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyDEkeG7mSB0aW5oIGtoaeG6v3QgY8OzIHPhu7EgcGjDom4gaMOzYSByw7UgcuG7h3QuIEPhu6UgdGjhu4MgxJHGsOG7o2MgdGjhu4MgaGnhu4duIGJhbyBz4buRIGxp4buHdSBuaMawIHNhdToNCg0KLSAgIEkxIChiYW8gdGjhu4MgcsO1KTogNzQxIGtpbSBjxrDGoW5nDQoNCi0gICBTSTIgKGJhbyB0aOG7gyBuaOG7jywgcuG6pXQgZOG7hSBuaOG6rW4gdGjhuqV5KTogOTE5NCBraW0gY8awxqFuZw0KDQotICAgU0kxIChiYW8gdGjhu4Mgbmjhu48sIGThu4Ugbmjhuq1uIHRo4bqleSk6IDEzMDY1IGtpbSBjxrDGoW5nDQoNCi0gICBWUzIgKGJhbyB0aOG7gyBuaOG7jyBj4bqlcCAyKTogMTIyNTgga2ltIGPGsMahbmcNCg0KLSAgIFZTMSAoYmFvIHRo4buDIG5o4buPIGPhuqVwIDEpOiA4MTcxIGtpbSBjxrDGoW5nDQoNCi0gICBWU1MyIChiYW8gdGjhu4MgcuG6pXQgbmjhu48gY+G6pXAgMik6IDUwNjYga2ltIGPGsMahbmcNCg0KLSAgIFZTUzEgKGJhbyB0aOG7gyBy4bqldCBuaOG7jyBj4bqlcCAxKTogMzY1NSBraW0gY8awxqFuZw0KDQotICAgSUYgKEhvw6BuIHRvw6BuIHRpbmgga2hp4bq/dCk6IDE3OTAga2ltIGPGsMahbmcNCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjbGFyaXR5LG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0ncGluaycpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHRpdGxlPSAnQmnhu4F1IMSR4buTIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyDEkeG7mSB0aW5oIGtoaeG6v3QnLCB4ID0gJ8SQ4buZIHRpbmgga2hp4bq/dCcsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KPVw+IFbhuq15IMSR4buZIHRpbmgga2hp4bq/dCBsb+G6oWkgU0kxIGNoaeG6v20gc+G7kSBsxrDhu6NuZyBuaGnhu4F1IG5o4bqldCBsw6AgMTMwNjUgdmnDqm4ga2ltIGPGsMahbmcsIMSR4buZIHRpbmgga2hp4bq/dCBsb+G6oWkgSTEgY2hp4bq/bSBz4buRIGzGsOG7o25nIHRo4bqlcCBuaOG6pXQgbMOgIDc0MSB2acOqbiBraW0gY8awxqFuZy4NCg0KIyMgKioyLjUgRGVwdGggKFThu7cgbOG7hyBjaGnhu4F1IHPDonUgJSkqKg0KDQpEaWFtb25kIERlcHRoIGTDuW5nIGNo4buJIGNoaeG7gXUgc8OidSBoYXkgY8OybiBsw6AgY2hp4buBdSBjYW8gY+G7p2Ega2ltIGPGsMahbmcuIMSQxrDhu6NjIHTDrW5oIHThu6sgYuG7gSBt4bq3dCDEkeG6v24gxJHhuqd1IG5o4buNbiBj4bunYSBraOG7kWkgbOG6rXAgcGjGsMahbmcgdHLDqm4gdmnDqm4ga2ltIGPGsMahbmcuIMSQ4buZIHPDonUgdOG7qyA1Nyw3JS02MyUgbMOgIGzDvSB0xrDhu59uZyBuaOG6pXQgxJHhu4MgcGjhuqNuIHjhuqEgw6FuaCBzw6FuZyBob8OgbiBo4bqjby4NCg0KVGEgdGnhur9uIGjDoG5oIHBow6JuIGNoaWEga2ltIGPGsMahbmcgdGjDoG5oIDIgbG/huqFpOiBMw70gdMaw4bufbmcgKDU3LDUlLTYzJSksIGNoxrBhIGzDvSB0xrDhu59uZyAoXDw1Nyw1JSB2w6AgXD42MyUpDQoNCmBgYHtyfQ0KdG4kZ3JvdXAgPC0gaWZlbHNlKHRuJGRlcHRoID49IDU3LjMgJiB0biRkZXB0aCA8PSA2MywgIkzDvSB0xrDhu59uZyIsICJDaMawYSBsw70gdMaw4bufbmciKQ0KdGFibGUodG4kZ3JvdXApDQpgYGANCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoZ3JvdXApICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoZ3JvdXAsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdncmF5JykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgICBsYWJzKHRpdGxlID0gIiBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG5ow7NtIHRoZW8gxJDhu5kgc8OidSAiLHggPSAnxJDhu5kgc8OidScsIHkgPSAnU+G7kSBsxrDhu6NuZycpIA0KYGBgDQoNCj1cPiBW4bqteSBz4buRIHZpw6puIGtpbSBjxrDGoW5nIGzDvSB0xrDhu59uZyAoNDY1OTYpIGPDsyBz4buRIGzGsOG7o25nIGNhbyBn4bqlcCA2IGzhuqduIHPhu5EgdmnDqm4ga2ltIGPGsMahbmcgY2jGsGEgbMO9IHTGsOG7n25nICg3MzQ0KS4NCg0KIyMgKioyLjYgVGFibGUgKFThu7cgbOG7hyBt4bq3dCBiw6BuICUpKioNCg0KTeG7l2kgdmnDqm4ga2ltIGPGsMahbmcgxJHhu4F1IGPDsyBt4buZdCBt4bq3dCBwaOG6s25nIGPDsyBow6xuaCB2dcO0bmcgbuG6sW0g4bufIHRyw6puIMSR4buJbmguIE3hurd0IHBo4bqzbmcgbsOgeSBjaMOtbmggbMOgIERpYW1vbmQgVGFibGUgaGF5wqBi4buBIG3hurd0IGPhu6dhIGtpbSBjxrDGoW5nLiBOw7MgY8OzIHZhaSB0csOyIHbDtCBjw7luZyBxdWFuIHRy4buNbmcgdHJvbmcgdmnhu4djIHjDoWMgxJHhu4tuaCBow6xuaCBkw6FuZyBj4bunYSB2acOqbiDEkcOhLg0KDQotICAgxJDhu5FpIHbhu5tpIHZpw6puIGtpbSBjxrDGoW5nIGdpw6FjIG3hurd0IHRyw7JuOiBMw70gdMaw4bufbmcgKDU0JS02MCUpLCBjaMawYSBsw70gdMaw4bufbmcgKFw8NTQlIHbDoCBcPjYwJSkNCg0KYGBge3J9DQp0biR0cm9uIDwtIGlmZWxzZSh0biR0YWJsZSA+PSA1NCAmIHRuJHRhYmxlIDw9IDYwLCAiTMO9IHTGsOG7n25nIiwgIkNoxrBhIGzDvSB0xrDhu59uZyIpDQp0YWJsZSh0biR0cm9uKQ0KYGBgDQoNCmBgYHtyfQ0KdG4gJT4lIGdyb3VwX2J5KHRyb24pICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXModHJvbixuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2dyYXknKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh0aXRsZSA9ICIgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBuaMOzbSB0aGVvIGdpw6FjIGPhuq90IHRyw7JuICIseCA9ICdN4bq3dCBiw6BuJywgeSA9ICdT4buRIGzGsOG7o25nJykgDQpgYGANCg0KLSAgIMSQ4buRaSB24bubaSB2acOqbiBraW0gY8awxqFuZyBnacOhYyBt4bq3dCBs4bulYyBi4bqjbzogTMO9IHTGsOG7n25nICg2NiUtNzIlKSwgY2jGsGEgbMO9IHTGsOG7n25nIChcPDY2JSB2w6AgXD43MiUpDQoNCmBgYHtyfQ0KdG4kbHVjYmFvIDwtIGlmZWxzZSh0biR0YWJsZSA+PSA2NiAmIHRuJHRhYmxlIDw9IDcyLCAiTMO9IHTGsOG7n25nIiwgIkNoxrBhIGzDvSB0xrDhu59uZyIpDQp0YWJsZSh0biRsdWNiYW8pDQpgYGANCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkobHVjYmFvKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGx1Y2JhbyxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2dyYXknKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh0aXRsZSA9ICIgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBuaMOzbSB0aGVvIGdpw6FjIGPhuq90IGzhu6VjIGLhuqNvICIseCA9ICdN4bq3dCBiw6BuJywgeSA9ICdT4buRIGzGsOG7o25nJykgDQpgYGANCg0KIyMgKioyLjcgUHJpY2UgKEdpw6EgdGjDoG5oKSoqDQoNCktpbSBjxrDGoW5nwqDEkcaw4bujYyDEkeG7i25owqBnacOhwqBt4buZdCBjw6FjaCBjxqEgYuG6o27CoGThu7FhIHRyw6puwqB0acOqdSBjaHXhuqluIDRDIGJhbyBn4buTbTogQ2FyYXQgLSBUcuG7jW5nIGzGsOG7o25nIGhv4bq3YyBrw61jaCB0aMaw4bubY8KgY+G7p2HCoHZpw6puwqBraW0gY8awxqFuZy4gQ29sb3IgLSBNw6B1IHPhuq9jwqBj4bunYcKgdmnDqm7CoGtpbSBjxrDGoW5nLiBDbGFyaXR5IC0gxJDhu5kgdGluaCBraGnhur90IGhheSDEkeG7mSBz4bqhY2jCoGPhu6dhwqB2acOqbsKga2ltIGPGsMahbmfCoGhheSBjw7JuIGfhu41pIGzDoCBz4buxIHbhuq9uZyBt4bq3dMKgY+G7p2HCoG5o4buvbmcgdOG6oXAgY2jhuqV0IGLDqm4gdHJvbmcgdsOgIGPDoWMga2hp4bq/bSBraHV54bq/dCBiw6puIG5nb8OgaS4NCg0KVHLGsOG7m2MgdGnDqm4sIHRhIGNoaWEgZ2nDoSB0aMOgbmggY+G7p2Ega2ltIGPGsMahbmcgdGjDoG5oIDMgbmjDs206IFLhursgLSBW4burYSAtIMSQ4bqvdDoNCg0KYGBge3J9DQp0YWJsZShjdXQodG4kcHJpY2UsMykpDQpgYGANCg0KU2F1IGtoaSB0aeG6v24gaMOgbmggcGjDom4gY2hpYSB4b25nLCB0YSBuaOG6rW4gxJHGsOG7o2Mgc+G7kSBsxrDhu6NuZyB0xrDGoW5nIOG7qW5nIHbhu5tpIG3hu5dpIG5ow7NtIGdpw6EgdGjDoG5oIG5oxrAgc2F1Og0KDQoxLiAgUuG6uzogNDM1OTEgdmnDqm4ga2ltIGPGsMahbmcNCjIuICBW4burYTogNzM0NyB2acOqbiBraW0gY8awxqFuZw0KMy4gIMSQ4bqvdDogMzAwMiB2acOqbiBraW0gY8awxqFuZw0KDQpUYSB0aeG6v24gaMOgbmggduG6vSBiaeG7g3UgxJHhu5MgxJHhu4MgbmjDrG4gcsO1IHPhu7EgY2jhu4duaCBs4buHY2ggc+G7kSBsxrDhu6NuZyB24buBIGdpw6E6DQoNCmBgYHtyfQ0KdG4gPC0gZGlhbW9uZHMNCnRuMiA8LSB0biAlPiUgbXV0YXRlKGd0ID0gY3V0KHByaWNlLDMsIGxhYmVsID0gYygnUuG6uycsJ1bhu6thJywnxJDhuq90JykpKQ0KdG4yICU+JSBncm91cF9ieShndCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhndCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2JsdWUnKSArDQogICAgbGFicyh0aXRsZSA9ICIgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBuaMOzbSB0aGVvIGdpw6EiKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0dpw6EnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiMjICoqMi44IFBow6JuIHTDrWNoIGNodXnDqm4gc8OidSBs4buTbmcgZ2jDqXAgY8OhYyDEkeG6t2MgdMOtbmggbOG6oWkgduG7m2kgbmhhdS4qKg0KDQrEkOG7gyBjw7MgdGjhu4MgcGjDom4gdMOtY2gga8SpIGPDoG5nIGPFqW5nIG5oxrAgaGnhu4N1IHLhu48gaMahbiB24buBIGPDoWMgxJHhurdjIHTDrW5oIGPhu6dhIGtpbSBjxrDGoW5nLiBUYSBjw7MgdGjhu4MgcGjDom4gdMOtY2gga+G6v3QgaOG7o3AgMiBoYXkgbmhp4buBdSB54bq/dSB04buRIGzhuqFpIHbhu5tpIG5oYXUgdHLDqm4gY8O5bmcgbeG7mXQgYmnhu4N1IMSR4buTIEJhciBjaGFydCBnacO6cCB0YSBk4buFIHF1YW4gc8OhdCBjxaluZyBuaMawIGThu4UgZMOgbmcgc28gc8OhbmggY2jDum5nLg0KDQojIyMgKipDdXQgLSBDb2xvcioqDQoNCsSQw6J5IG3hu5l0IGJp4buDdSDEkeG7kyBj4buZdCB44bq/cCBjaOG7k25nIGhp4buDbiB0aOG7iyB04bqnbiBzdeG6pXQgdMawxqFuZyDEkeG7kWkgY+G7p2EgYmnhur9uICJjdXQiIHbDoCBtw6B1IGZpbGwgY+G7p2EgY8OhYyBj4buZdCBk4buxYSB0csOqbiBiaeG6v24gImNvbG9yIi4gQmnhu4N1IMSR4buTIG7DoHkgZ2nDunAgYuG6oW4gY8OzIGPDoWkgbmjDrG4gduG7gSBwaMOibiBwaOG7kWkgY+G7p2EgYmnhur9uICJjdXQiIHbDoCAiY29sb3IiIHRyb25nIGtodW5nIGThu68gbGnhu4d1ICJ0biIuDQoNCmBgYHtyfQ0KZ2dwbG90KHRuLCBhZXMoeCA9IGN1dCwgZmlsbCA9IGNvbG9yKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBsYWJzKHRpdGxlID0gIlThuqduIHN14bqldCBj4bunYSBDdXQgdsOgIENvbG9yIiwgeCA9ICJDdXQiLCB5ID0gIlThuqduIHN14bqldCIpICsNCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQYWlyZWQiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMjIyAqKkNhcmF0IC0gQ29sb3IgLSBDbGFyaXR5KioNCg0KQmnhu4N1IMSR4buTIGPhu5l0IG7DoHkgaGnhu4NuIHRo4buLIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgYmnhur9uICJwcmljZSIgZOG7sWEgdHLDqm4gY8OhYyBuaMOzbSAiY3V0IiB2w6AgbcOgdSBmaWxsIGPhu6dhIGPDoWMgY+G7mXQgZOG7sWEgdHLDqm4gYmnhur9uICJjbGFyaXR5Ii4gQmnhu4N1IMSR4buTIG7DoHkgZ2nDunAgYuG6oW4gc28gc8OhbmggZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSAicHJpY2UiIGdp4buvYSBjw6FjIG5ow7NtICJjdXQiIHbDoCB4ZW0gbGnhu4d1IHPhu7EgcsO1IHLDoG5nICgiY2xhcml0eSIpIGPDsyDhuqNuaCBoxrDhu59uZyDEkeG6v24gZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBraMO0bmcuDQoNCmBgYHtyfQ0KdG4gJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IHByaWNlLCBmaWxsID0gY2xhcml0eSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuLnkgPSAibWVhbiIsIHBvc2l0aW9uID0gImRvZGdlIikNCmBgYA0KDQpCaeG7g3UgxJHhu5MgbsOgeSBz4bq9IGdpw7pwIGLhuqFuIHBow6JuIHTDrWNoIHPhu7Ega2jDoWMgYmnhu4d0IHbhu4EgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSAicHJpY2UiIGdp4buvYSBjw6FjIG5ow7NtICJjdXQiLiBC4bqhbiBjxaluZyBjw7MgdGjhu4MgeGVtIHjDqXQgdMawxqFuZyBxdWFuIGdp4buvYSBz4buxIHLDtSByw6BuZyAoImNsYXJpdHkiKSB2w6AgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSAicHJpY2UiIGLhurFuZyBjw6FjaCBxdWFuIHPDoXQgc+G7sSBraMOhYyBiaeG7h3QgbcOgdSBmaWxsIGPhu6dhIGPDoWMgY+G7mXQgZ2nhu69hIGPDoWMgbmjDs20gImNsYXJpdHkiLg0KDQojIyMgKipDdXQgLSBDbGFyaXR5IC0gQ29sb3IqKg0KDQpCaeG7g3UgxJHhu5MgY+G7mXQgeOG6v3AgY2jhu5NuZyBuw6B5IGNobyB0aOG6pXkgdOG6p24gc3XhuqV0IGPhu6dhIGPDoWMgbG/huqFpIGPhuq90IGtpbSBjxrDGoW5nICgiY3V0IikgdGhlbyBnacOhIHRy4buLIGPhu6dhIGJp4bq/biAiY2xhcml0eSIuIE3hu5dpIGPhu5l0IGJp4buDdSB0aOG7iyBt4buZdCBsb+G6oWkgY+G6r3Qga2ltIGPGsMahbmcgdsOgIMSRxrDhu6NjIGNoaWEgdGjDoG5oIGPDoWMgcGjhuqduIHTGsMahbmcg4bupbmcgduG7m2kgY8OhYyBnacOhIHRy4buLIGPhu6dhIGJp4bq/biAiY2xhcml0eSIuDQoNCkThu7FhIHRyw6puIGJp4buDdSDEkeG7kywgY2jDum5nIHRhIGPDsyB0aOG7gyBuaOG6rW4gdGjhuqV5IG3hu5l0IHPhu5Ega+G6v3QgcXXhuqMgc2F1Og0KDQoxLiAgTG/huqFpIGPhuq90ICJJZGVhbCIgY8OzIHThuqduIHN14bqldCBjYW8gbmjhuqV0IHRyb25nIHThuqV0IGPhuqMgY8OhYyBt4bupYyDEkeG7mSByw7UgcsOgbmcgKCJjbGFyaXR5IikuIMSQw6J5IGPDsyB0aOG7gyBsw6AgbG/huqFpIGPhuq90IHBo4buVIGJp4bq/biBuaOG6pXQgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UuDQoNCjIuICBD4bqvdCAiUHJlbWl1bSIgdsOgICJWZXJ5IEdvb2QiIGPFqW5nIGPDsyB04bqnbiBzdeG6pXQga2jDoSBjYW8gdHJvbmcgdOG6pXQgY+G6oyBjw6FjIG3hu6ljIMSR4buZIHLDtSByw6BuZyAoImNsYXJpdHkiKS4NCg0KMy4gIEPhuq90ICJGYWlyIiBjw7MgdOG6p24gc3XhuqV0IHRo4bqlcCBuaOG6pXQgdHJvbmcgdOG6pXQgY+G6oyBjw6FjIG3hu6ljIMSR4buZIHLDtSByw6BuZyAoImNsYXJpdHkiKS4NCg0KNC4gIE3hu6ljIMSR4buZIHLDtSByw6BuZyAiU0kyIiB2w6AgIkkxIiBjw7MgdOG6p24gc3XhuqV0IGNhbyBuaOG6pXQgdHJvbmcgY8OhYyBsb+G6oWkgY+G6r3QsIHRyb25nIGtoaSBt4bupYyDEkeG7mSByw7UgcsOgbmcgIklGIiB2w6AgIlZWUzEiIGPDsyB04bqnbiBzdeG6pXQgdGjhuqVwIG5o4bqldC4NCg0KNS4gIEPDoWMgbG/huqFpIGPhuq90IGtow6FjIG5oYXUgY8OzIHBow6JuIHBo4buRaSBraMOhYyBuaGF1IGPhu6dhIGPDoWMgbeG7qWMgxJHhu5kgcsO1IHLDoG5nICgiY2xhcml0eSIpLiBWw60gZOG7pSwgY+G6r3QgIklkZWFsIiB2w6AgIlByZW1pdW0iIGPDsyB04bqnbiBzdeG6pXQgY2FvIG5o4bqldCDhu58gbeG7qWMgxJHhu5kgcsO1IHLDoG5nICJTSTEiIHbDoCAiVlMyIiwgdHJvbmcga2hpIGPhuq90ICJGYWlyIiBjw7MgdOG6p24gc3XhuqV0IGNhbyBuaOG6pXQg4bufIG3hu6ljIMSR4buZIHLDtSByw6BuZyAiSTEiLg0KDQpgYGB7cn0NCmdncGxvdCh0biwgYWVzKHggPSBjdXQsIGZpbGwgPSBjbGFyaXR5KSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBsYWJzKHRpdGxlID0gIlThuqduIHN14bqldCBj4bunYSBjw6FjIGxv4bqhaSBj4bqvdCBraW0gY8awxqFuZyB0aGVvIGdpw6EgdHLhu4siLCB4ID0gIkPhuq90IiwgeSA9ICJU4bqnbiBzdeG6pXQiKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiUGFpcmVkIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpCaeG7g3UgxJHhu5MgbsOgeSBjdW5nIGPhuqVwIG3hu5l0IGPDoWkgbmjDrG4gdOG7lW5nIHF1YW4gduG7gSBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGPDoWMgbG/huqFpIGPhuq90IGtpbSBjxrDGoW5nIHbDoCBnacOhIHRy4buLIGPhu6dhIGJp4bq/biAiY2xhcml0eSIuIE7DsyBnacO6cCBjaMO6bmcgdGEgaGnhu4N1IMSRxrDhu6NjIHBow6JuIHBo4buRaSBj4bunYSBjw6FjIGxv4bqhaSBj4bqvdCB0cm9uZyBt4buXaSBt4bupYyDEkeG7mSByw7UgcsOgbmcsIGNobyBwaMOpcCBwaMOibiB0w61jaCBz4buxIHTGsMahbmcgcXVhbiBnaeG7r2EgaGFpIGJp4bq/biBuw6B5Lg0KDQojIyMgKipDb2xvciAtIEN1dCoqDQoNCkThu7FhIHRyw6puIGJp4buDdSDEkeG7kywgY2jDum5nIHRhIGPDsyB0aOG7gyByw7p0IHJhIG3hu5l0IHPhu5Ega+G6v3QgcXXhuqMgc2F1Og0KDQoxLiAgTcOgdSBz4bqvYyAiRyIgdsOgICJFIiBjw7MgdOG6p24gc3XhuqV0IGNhbyBuaOG6pXQgdHJvbmcgY8OhYyBsb+G6oWkgY+G6r3QsIHbhu5tpIGxv4bqhaSBj4bqvdCAiSWRlYWwiIHbDoCAiUHJlbWl1bSIgY2hp4bq/bSB04bu3IGzhu4cgbOG7m24uDQoNCjIuICBNw6B1IHPhuq9jICJKIiBjw7MgdOG6p24gc3XhuqV0IHRo4bqlcCBuaOG6pXQgdHJvbmcgY8OhYyBsb+G6oWkgY+G6r3QsIMSR4bq3YyBiaeG7h3QgbMOgIGxv4bqhaSBj4bqvdCAiRmFpciIgdsOgICJHb29kIi4NCg0KMy4gIEPhuq90ICJGYWlyIiB2w6AgIkdvb2QiIGPDsyB04bqnbiBzdeG6pXQgdMawxqFuZyDEkeG7kWkgY2FvIHRyb25nIG3DoHUgc+G6r2MgIkgiIHbDoCAiSSIuDQoNCjQuICBD4bqvdCAiVmVyeSBHb29kIiBjw7MgdOG6p24gc3XhuqV0IHTGsMahbmcgxJHhu5FpIGNhbyB0cm9uZyBtw6B1IHPhuq9jICJGIi4NCg0KNS4gIEPhuq90ICJJZGVhbCIgY8OzIHThuqduIHN14bqldCBjYW8gdHJvbmcgbcOgdSBz4bqvYyAiRCIuDQoNCkJp4buDdSDEkeG7kyBjdW5nIGPhuqVwIG3hu5l0IGPDoWkgbmjDrG4gdOG7lW5nIHF1YW4gduG7gSB04bqnbiBzdeG6pXQgY+G7p2EgY8OhYyBuaMOzbSBsb+G6oWkgY+G6r3QgdHJvbmcgdOG7q25nIG3hu6ljIMSR4buZIG3DoHUgc+G6r2MuIE7DsyBnacO6cCBjaMO6bmcgdGEgaGnhu4N1IMSRxrDhu6NjIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgbG/huqFpIGPhuq90IHbDoCBtw6B1IHPhuq9jIGPhu6dhIGtpbSBjxrDGoW5nIHRyb25nIHThuq1wIGThu68gbGnhu4d1Lg0KDQpgYGB7cn0NCnRuICU+JSBncm91cF9ieShjdXQsY29sb3IpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjdXQseSA9IG4pKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLCBjb2xvciA9ICdncmVlbicpICsNCiAgICBsYWJzKHRpdHRsZT0nQ29sb3IgLSBDdXQnLHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQojIyMgKipDdXQgLSBDbGFyaXR5KioNCg0KROG7sWEgdHLDqm4gYmnhu4N1IMSR4buTLCBjaMO6bmcgdGEgY8OzIHRo4buDIHLDunQgcmEgbeG7mXQgc+G7kSBr4bq/dCBxdeG6oyBzYXU6DQoNCjEuICBN4bupYyDEkeG7mSByw7UgcsOgbmcgIlNJMSIgdsOgICJTSTIiIGPDsyB04bqnbiBzdeG6pXQgY2FvIG5o4bqldCB0cm9uZyBjw6FjIGxv4bqhaSBj4bqvdCwgduG7m2kgbG/huqFpIGPhuq90ICJJZGVhbCIgdsOgICJQcmVtaXVtIiBjaGnhur9tIHThu7cgbOG7hyBs4bubbi4NCg0KMi4gIE3hu6ljIMSR4buZIHLDtSByw6BuZyAiSTEiIGPDsyB04bqnbiBzdeG6pXQgdGjhuqVwIG5o4bqldCB0cm9uZyBjw6FjIGxv4bqhaSBj4bqvdCwgxJHhurdjIGJp4buHdCBsw6AgbG/huqFpIGPhuq90ICJGYWlyIiB2w6AgIkdvb2QiLg0KDQozLiAgQ+G6r3QgIkZhaXIiIHbDoCAiR29vZCIgY8OzIHThuqduIHN14bqldCB0xrDGoW5nIMSR4buRaSBjYW8gdHJvbmcgbeG7qWMgxJHhu5kgcsO1IHLDoG5nICJTSTIiLg0KDQo0LiAgQ+G6r3QgIklkZWFsIiBjw7MgdOG6p24gc3XhuqV0IGNhbyB0cm9uZyBt4bupYyDEkeG7mSByw7UgcsOgbmcgIlZWUzEiIHbDoCAiVlZTMiIuDQoNCjUuICBD4bqvdCAiVmVyeSBHb29kIiBjw7MgdOG6p24gc3XhuqV0IHTGsMahbmcgxJHhu5FpIGNhbyB0cm9uZyBt4bupYyDEkeG7mSByw7UgcsOgbmcgIlZTMSIgdsOgICJWUzIiLg0KDQpCaeG7g3UgxJHhu5MgY3VuZyBj4bqlcCBt4buZdCBjw6FpIG5ow6xuIHThu5VuZyBxdWFuIHbhu4EgdOG6p24gc3XhuqV0IGPhu6dhIGPDoWMgbmjDs20gbG/huqFpIGPhuq90IHRyb25nIHThu6tuZyBt4bupYyDEkeG7mSByw7UgcsOgbmcuIE7DsyBnacO6cCBjaMO6bmcgdGEgaGnhu4N1IMSRxrDhu6NjIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgbG/huqFpIGPhuq90IHbDoCBt4bupYyDEkeG7mSByw7UgcsOgbmcgY+G7p2Ega2ltIGPGsMahbmcgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UuDQoNCmBgYHtyfQ0KdG4gJT4lIGdyb3VwX2J5KGN1dCxjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBuKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmNsYXJpdHkpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQojIyMgKipDb2xvciAtIENsYXJpdHkqKg0KDQpE4buxYSB0csOqbiBiaeG7g3UgxJHhu5MsIGNow7puZyB0YSBjw7MgdGjhu4MgcsO6dCByYSBt4buZdCBz4buRIGvhur90IHF14bqjIHNhdToNCg0KMS4gIE3hu6ljIMSR4buZIHLDtSByw6BuZyAiU0kxIiB2w6AgIlNJMiIgY8OzIHThuqduIHN14bqldCBjYW8gbmjhuqV0IHRyb25nIGPDoWMgbG/huqFpIGPhuq90LCB24bubaSBsb+G6oWkgY+G6r3QgIklkZWFsIiB2w6AgIlByZW1pdW0iIGNoaeG6v20gdOG7tyBs4buHIGzhu5tuLg0KDQoyLiAgTeG7qWMgxJHhu5kgcsO1IHLDoG5nICJJMSIgY8OzIHThuqduIHN14bqldCB0aOG6pXAgbmjhuqV0IHRyb25nIGPDoWMgbG/huqFpIGPhuq90LCDEkeG6t2MgYmnhu4d0IGzDoCBsb+G6oWkgY+G6r3QgIkZhaXIiIHbDoCAiR29vZCIuDQoNCjMuICBD4bqvdCAiRmFpciIgdsOgICJHb29kIiBjw7MgdOG6p24gc3XhuqV0IHTGsMahbmcgxJHhu5FpIGNhbyB0cm9uZyBt4bupYyDEkeG7mSByw7UgcsOgbmcgIlNJMiIuDQoNCjQuICBD4bqvdCAiSWRlYWwiIGPDsyB04bqnbiBzdeG6pXQgY2FvIHRyb25nIG3hu6ljIMSR4buZIHLDtSByw6BuZyAiVlZTMSIgdsOgICJWVlMyIi4NCg0KNS4gIEPhuq90ICJWZXJ5IEdvb2QiIGPDsyB04bqnbiBzdeG6pXQgdMawxqFuZyDEkeG7kWkgY2FvIHRyb25nIG3hu6ljIMSR4buZIHLDtSByw6BuZyAiVlMxIiB2w6AgIlZTMiIuDQoNCkJp4buDdSDEkeG7kyBjaG8gdGjhuqV5IHThuqduIHN14bqldCBj4bunYSBjw6FjIG5ow7NtIGxv4bqhaSBj4bqvdCB0cm9uZyB04burbmcgbeG7qWMgxJHhu5kgcsO1IHLDoG5nLiBNw6B1IG7hu4FuIHhhbmggbMOgbSBu4buVaSBi4bqtdCBjw6FjIGPhu5l0IHbDoCBnacO6cCBwaMOibiBiaeG7h3QgY8OhYyBuaMOzbS4gQ8OhYyBjb24gc+G7kSB04bqnbiBzdeG6pXQgxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgbcOgdSBjaOG7ryDEkeG7jy4gQmnhu4N1IMSR4buTIGdpw7pwIGNow7puZyB0YSBoaeG7g3UgxJHGsOG7o2MgbeG7kWkgcXVhbiBo4buHIGdp4buvYSBsb+G6oWkgY+G6r3QgdsOgIG3hu6ljIMSR4buZIHLDtSByw6BuZyBj4bunYSBraW0gY8awxqFuZyB0cm9uZyB04bqtcCBk4buvIGxp4buHdS4NCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY3V0LGNsYXJpdHkpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjdXQseSA9IG4pKSArDQogICAgZ2VvbV9jb2woZmlsbCA9ICdncmVlbicpICsNCiAgICBmYWNldF93cmFwKH5jbGFyaXR5KSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiMjIyAqKkNsYXJpdHkgLSBDb2xvcioqDQoNCkThu7FhIHRyw6puIGJp4buDdSDEkeG7kywgY2jDum5nIHRhIGPDsyB0aOG7gyByw7p0IHJhIG3hu5l0IHPhu5Ega+G6v3QgcXXhuqMgc2F1Og0KDQoxLiAgTcOgdSBz4bqvYyAiRyIgdsOgICJFIiBjw7MgdOG6p24gc3XhuqV0IGNhbyBuaOG6pXQgdHJvbmcgY8OhYyBt4bupYyDEkeG7mSB0aW5oIGtoaeG6v3QsIHbhu5tpIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCAiU0kxIiB2w6AgIlNJMiIgY2hp4bq/bSB04bu3IGzhu4cgbOG7m24uDQoNCjIuICBNw6B1IHPhuq9jICJKIiBjw7MgdOG6p24gc3XhuqV0IHRo4bqlcCBuaOG6pXQgdHJvbmcgY8OhYyBt4bupYyDEkeG7mSB0aW5oIGtoaeG6v3QsIMSR4bq3YyBiaeG7h3QgbMOgIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCAiSTEiIHbDoCAiSUYiLg0KDQozLiAgTeG7qWMgxJHhu5kgdGluaCBraGnhur90ICJJMSIgY8OzIHThuqduIHN14bqldCB0xrDGoW5nIMSR4buRaSBjYW8gdHJvbmcgbcOgdSBz4bqvYyAiSCIgdsOgICJJIi4NCg0KNC4gIE3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCAiSUYiIGPDsyB04bqnbiBzdeG6pXQgY2FvIHRyb25nIG3DoHUgc+G6r2MgIkQiIHbDoCAiRSIuDQoNCjUuICBN4bupYyDEkeG7mSB0aW5oIGtoaeG6v3QgIlNJMSIgdsOgICJTSTIiIGPDsyB04bqnbiBzdeG6pXQgdMawxqFuZyDEkeG7kWkgY2FvIHRyb25nIG3DoHUgc+G6r2MgIkYiLg0KDQpCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSB04bqnbiBzdeG6pXQgY+G7p2EgY8OhYyBuaMOzbSBt4bupYyDEkeG7mSB0aW5oIGtoaeG6v3QgdHJvbmcgdOG7q25nIG3DoHUgc+G6r2MuIE3DoHUgbuG7gW4geGFuaCBuaOG6oXQgbMOgbSBu4buVaSBi4bqtdCBjw6FjIGPhu5l0IHbDoCBnacO6cCBwaMOibiBiaeG7h3QgY8OhYyBuaMOzbS4gQ8OhYyBjb24gc+G7kSB04bqnbiBzdeG6pXQgxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgbcOgdSBjaOG7ryDEkWVuLiBCaeG7g3UgxJHhu5MgZ2nDunAgY2jDum5nIHRhIGhp4buDdSDEkcaw4bujYyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCB2w6AgbcOgdSBz4bqvYyBj4bunYSBraW0gY8awxqFuZyB0cm9uZyB04bqtcCBk4buvIGxp4buHdS4NCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY29sb3IsY2xhcml0eSkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG4pKSArDQogICAgZ2VvbV9jb2woZmlsbCA9ICdsaWdodGJsdWUnKSArDQogICAgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnTeG7qWMgxJHhu5kgdGluaCBraGnhur90JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQojIyMgKipDdXQgLSBNZWFuIENhcmF0KioNCg0KROG7sWEgdHLDqm4gYmnhu4N1IMSR4buTLCBjaMO6bmcgdGEgY8OzIHRo4buDIHLDunQgcmEgbeG7mXQgc+G7kSBr4bq/dCBxdeG6oyBzYXU6DQoNCjEuICBMb+G6oWkgY+G6r3QgIklkZWFsIiBjw7MgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBjYW8gbmjhuqV0IGNobyBjaOG7iSBz4buRICJjYXJhdCIsIHRoZW8gc2F1IGzDoCAiUHJlbWl1bSIgdsOgICJWZXJ5IEdvb2QiLg0KDQoyLiAgTG/huqFpIGPhuq90ICJGYWlyIiB2w6AgIkdvb2QiIGPDsyBnacOhIHRy4buLIHRydW5nIGLDrG5oIHRo4bqlcCBuaOG6pXQgY2hvIGNo4buJIHPhu5EgImNhcmF0Ii4NCg0KQmnhu4N1IMSR4buTIGNobyB0aOG6pXkgc+G7sSBraMOhYyBiaeG7h3QgduG7gSBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGNo4buJIHPhu5EgImNhcmF0IiBnaeG7r2EgY8OhYyBsb+G6oWkgY+G6r3QgY+G7p2Ega2ltIGPGsMahbmcuIE3DoHUgbuG7gW4gaOG7k25nIGzDoG0gbuG7lWkgYuG6rXQgY8OhYyBj4buZdCB2w6AgZ2nDunAgcGjDom4gYmnhu4d0IGPDoWMgbG/huqFpIGPhuq90LiBDw6FjIGNvbiBz4buRIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgbcOgdSBjaOG7ryB0cuG6r25nLiBCaeG7g3UgxJHhu5MgZ2nDunAgY2jDum5nIHRhIGhp4buDdSDEkcaw4bujYyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGxv4bqhaSBj4bqvdCB2w6AgdHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyB04bqtcCBk4buvIGxp4buHdS4NCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBtKSkgKw0KICAgIGdlb21fY29sKGZpbGwgPSAncGluaycpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnTWVhbicpDQpgYGANCg0KLSAgIE5ow7NtIOKAnEZhaXLigJ0gY8OzIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY2FvIG5o4bqldCAoMS4wNSBjYXJhdCkuDQoNCi0gICBOaMOzbSDigJxJZGVhbOKAnSBjw7MgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCB0aOG6pXAgbmjhuqV0ICgwLjcgY2FyYXQpLg0KDQotICAgTmjDrG4gY2h1bmcsIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgYmnhur9uIOKAnGNhcmF04oCdZ2nhuqNtIGThuqduIHThu6sgbmjDs20g4oCcRmFpcuKAnSDEkeG6v24gbmjDs20g4oCcSWRlYWzigJ0uIFN1eSByYSwga2nhu4N1IGPhuq90IGtpbSBjxrDGoW5nIOG6o25oIGjGsOG7n25nIMSR4bq/biBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGJp4bq/biDigJxjYXJhdOKAnS4NCg0KIyMjICoqQ29sb3IgLSBNZWFuIENhcmF0KioNCg0KROG7sWEgdHLDqm4gYmnhu4N1IMSR4buTLCBjaMO6bmcgdGEgY8OzIHRo4buDIHLDunQgcmEgbeG7mXQgc+G7kSBr4bq/dCBxdeG6oyBzYXU6DQoNCjEuICBNw6B1IHPhuq9jICJKIiBjw7MgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBjYW8gbmjhuqV0IGNobyBjaOG7iSBz4buRICJjYXJhdCIsIHRoZW8gc2F1IGzDoCAiSSIgdsOgICJIIi4NCg0KMi4gIE3DoHUgc+G6r2MgIkQiIGPDsyBnacOhIHRy4buLIHRydW5nIGLDrG5oIHRo4bqlcCBuaOG6pXQgY2hvIGNo4buJIHPhu5EgImNhcmF0Ii4NCg0KQmnhu4N1IMSR4buTIGNobyB0aOG6pXkgc+G7sSBraMOhYyBiaeG7h3QgduG7gSBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGNo4buJIHPhu5EgImNhcmF0IiBnaeG7r2EgY8OhYyBtw6B1IHPhuq9jIGPhu6dhIGtpbSBjxrDGoW5nLiBNw6B1IG7hu4FuIGNhbSBsw6BtIG7hu5VpIGLhuq10IGPDoWMgY+G7mXQgdsOgIGdpw7pwIHBow6JuIGJp4buHdCBjw6FjIG3DoHUgc+G6r2MuIEPDoWMgY29uIHPhu5EgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHLDqm4gY+G7mXQgdMawxqFuZyDhu6luZyB24bubaSBtw6B1IGNo4buvIMSR4buPLiBCaeG7g3UgxJHhu5MgZ2nDunAgY2jDum5nIHRhIGhp4buDdSDEkcaw4bujYyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIG3DoHUgc+G6r2MgdsOgIHRy4buNbmcgbMaw4bujbmcgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UuDQoNCmBgYHtyfQ0KdG4gJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY29sb3IseSA9IG0pKSArDQogICAgZ2VvbV9jb2woZmlsbCA9J29yYW5nZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICdNw6B1JywgeSA9ICdNZWFuJykNCmBgYA0KDQojIyMgKipDbGFyaXR5IC0gTWVhbiBDYXJhdCoqDQoNCkThu7FhIHRyw6puIGJp4buDdSDEkeG7kywgY2jDum5nIHRhIGPDsyB0aOG7gyByw7p0IHJhIG3hu5l0IHPhu5Ega+G6v3QgcXXhuqMgc2F1Og0KDQoxLiAgTeG7qWMgxJHhu5kgdGluaCBraGnhur90ICJJMSIgY8OzIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY2FvIG5o4bqldCBjaG8gY2jhu4kgc+G7kSAiY2FyYXQiLCB0aGVvIHNhdSBsw6AgIlNJMiIgdsOgICJTSTEiLg0KDQoyLiAgTeG7qWMgxJHhu5kgdGluaCBraGnhur90ICJJRiIgY8OzIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggdGjhuqVwIG5o4bqldCBjaG8gY2jhu4kgc+G7kSAiY2FyYXQiLg0KDQpCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSBz4buxIGtow6FjIGJp4buHdCB24buBIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgY2jhu4kgc+G7kSAiY2FyYXQiIGdp4buvYSBjw6FjIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCBj4bunYSBraW0gY8awxqFuZy4gTcOgdSBu4buBbiB0cuG6r25nIGzDoG0gbuG7lWkgYuG6rXQgY8OhYyBj4buZdCB2w6AgZ2nDunAgcGjDom4gYmnhu4d0IGPDoWMgbeG7qWMgxJHhu5kgdGluaCBraGnhur90LiBDw6FjIGNvbiBz4buRIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgbcOgdSBjaOG7ryB4YW5oLiBCaeG7g3UgxJHhu5MgZ2nDunAgY2jDum5nIHRhIGhp4buDdSDEkcaw4bujYyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCB2w6AgdHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyB04bqtcCBk4buvIGxp4buHdS4NCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShtPSBtZWFuKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG0pKSArDQogICAgZ2VvbV9jb2woZmlsbCA9J3doaXRlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDIpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICdibHVlJykgKw0KICAgIGxhYnMoeCA9ICdN4bupYyDEkOG7mSBUaW5oIEtoaeG6v3QnLCB5ID0gJ01lYW4nKQ0KYGBgDQoNCiMjIyAqKkN1dCAtIE1lYW4gUHJpY2UqKg0KDQpHacOhYyBj4bqvdCBj4bunYSBraW0gY8awxqFuZyBjxaluZyBsw6AgMSBwaOG6p24gcXVhbiB0cuG7jW5nIOG6o25oIGjGsOG7n25nIMSR4bq/biBnacOhIGLDoW4gY+G7p2EgY2jDum5nLiBCaeG7g3UgxJHhu5MgZMaw4bubaSDEkcOieSBjaG8gdGEgdGjhuqV5IHRydW5nIGLDrG5oIGdpw6EgdGjDoG5oIHRoZW8gdOG7q25nIGxv4bqhaSBnacOhYyBj4bqvdC4NCg0KROG7sWEgdHLDqm4gYmnhu4N1IMSR4buTLCBjaMO6bmcgdGEgY8OzIHRo4buDIHLDunQgcmEgbeG7mXQgc+G7kSBr4bq/dCBxdeG6oyBzYXU6DQoNCjEuICBMb+G6oWkgY+G6r3QgIlByZW1pdW0iIGPDsyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGNhbyBuaOG6pXQgY2hvIGdpw6Ega2ltIGPGsMahbmcsIHRoZW8gc2F1IGzDoCAiVmVyeSBHb29kIiB2w6AgIklkZWFsIi4NCg0KMi4gIExv4bqhaSBj4bqvdCAiRmFpciIgY8OzIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggdGjhuqVwIG5o4bqldCBjaG8gZ2nDoSBraW0gY8awxqFuZy4NCg0KQmnhu4N1IMSR4buTIGNobyB0aOG6pXkgc+G7sSBraMOhYyBiaeG7h3QgduG7gSBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIGdp4buvYSBjw6FjIGxv4bqhaSBj4bqvdC4gTcOgdSBu4buBbiB4w6FtIGzDoG0gbuG7lWkgYuG6rXQgY8OhYyBj4buZdCB2w6AgZ2nDunAgcGjDom4gYmnhu4d0IGPDoWMgbG/huqFpIGPhuq90LiBDw6FjIGNvbiBz4buRIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgbcOgdSBjaOG7ryB0cuG6r25nLiBCaeG7g3UgxJHhu5MgZ2nDunAgY2jDum5nIHRhIGhp4buDdSDEkcaw4bujYyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGxv4bqhaSBj4bqvdCB2w6AgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyB04bqtcCBk4buvIGxp4buHdS4NCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG1wPSBtZWFuKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gbXApKSArDQogICAgZ2VvbV9jb2woZmlsbD0nZ3JleScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobXAsMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ3doaXRlJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ01lYW4gUHJpY2UnKQ0KYGBgDQoNCiMjIyAqKkNvbG9yIC0gTWVhbiBQcmljZSoqDQoNCkThu7FhIHRyw6puIGJp4buDdSDEkeG7kywgY2jDum5nIHRhIGPDsyB0aOG7gyByw7p0IHJhIG3hu5l0IHPhu5Ega+G6v3QgcXXhuqMgc2F1Og0KDQoxLiAgTcOgdSBz4bqvYyAiSiIgY8OzIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY2FvIG5o4bqldCBjaG8gZ2nDoSBraW0gY8awxqFuZywgdGhlbyBzYXUgbMOgICJJIiB2w6AgIkgiLg0KDQoyLiAgTcOgdSBz4bqvYyAiRCIgY8OzIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggdGjhuqVwIG5o4bqldCBjaG8gZ2nDoSBraW0gY8awxqFuZy4NCg0KQmnhu4N1IMSR4buTIGNobyB0aOG6pXkgc+G7sSBraMOhYyBiaeG7h3QgduG7gSBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIGdp4buvYSBjw6FjIG3DoHUgc+G6r2MuIE3hu5dpIGPhu5l0IMSRxrDhu6NjIHBow6JuIGNoaWEgdGhlbyBtw6B1IHPhuq9jLCBnacO6cCBjaMO6bmcgdGEgc28gc8OhbmggZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBnaeG7r2EgY8OhYyBtw6B1IHPhuq9jIGtow6FjIG5oYXUuIEPDoWMgY29uIHPhu5EgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHLDqm4gY+G7mXQgdMawxqFuZyDhu6luZyB24bubaSBtw6B1IGNo4buvIMSR4buPLiBCaeG7g3UgxJHhu5MgZ2nDunAgY2jDum5nIHRhIGhp4buDdSDEkcaw4bujYyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIG3DoHUgc+G6r2MgdsOgIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UuDQoNCmBgYHtyfQ0KdG4gJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG1wPSBtZWFuKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNvbG9yLHkgPSBtcCkpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobXAsMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgICBsYWJzKHggPSAnTcOgdScsIHkgPSAnTWVhbiBQcmljZScpDQpgYGANCg0KIyMjICoqQ2xhcml0eSAtIE1lYW4gUHJpY2UqKg0KDQpE4buxYSB0csOqbiBiaeG7g3UgxJHhu5MsIGNow7puZyB0YSBjw7MgdGjhu4MgcsO6dCByYSBt4buZdCBz4buRIGvhur90IHF14bqjIHNhdToNCg0KMS4gIE3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCAiSTEiIGPDsyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGNhbyBuaOG6pXQgY2hvIGdpw6Ega2ltIGPGsMahbmcsIHRoZW8gc2F1IGzDoCAiU0kyIiB2w6AgIlNJMSIuDQoNCjIuICBN4bupYyDEkeG7mSB0aW5oIGtoaeG6v3QgIklGIiBjw7MgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCB0aOG6pXAgbmjhuqV0IGNobyBnacOhIGtpbSBjxrDGoW5nLg0KDQpCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSBz4buxIGtow6FjIGJp4buHdCB24buBIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgZ2nhu69hIGPDoWMgbeG7qWMgxJHhu5kgdGluaCBraGnhur90LiBNw6B1IG7hu4FuIG7DonUgbMOgbSBu4buVaSBi4bqtdCBjw6FjIGPhu5l0IHbDoCBnacO6cCBwaMOibiBiaeG7h3QgY8OhYyBt4bupYyDEkeG7mSB0aW5oIGtoaeG6v3QuIEPDoWMgY29uIHPhu5EgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHLDqm4gY+G7mXQgdMawxqFuZyDhu6luZyB24bubaSBtw6B1IGNo4buvIHhhbmguIEJp4buDdSDEkeG7kyBnacO6cCBjaMO6bmcgdGEgaGnhu4N1IMSRxrDhu6NjIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgbeG7qWMgxJHhu5kgdGluaCBraGnhur90IHbDoCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRyb25nIHThuq1wIGThu68gbGnhu4d1Lg0KDQpgYGB7cn0NCnRuICU+JSBncm91cF9ieShjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG1wPSBtZWFuKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG1wKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2Jyb3duJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtcCwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAnYmx1ZScpICsNCiAgICBsYWJzKHggPSAnTeG7qWMgxJDhu5kgVGluaCBLaGnhur90JywgeSA9ICdNZWFuJykNCmBgYA0KDQojIyMgKipDb2xvciAtIFByaWNlKioNCg0KROG7sWEgdHLDqm4gYmnhu4N1IMSR4buTIGhpc3RvZ3JhbSwgY2jDum5nIHRhIGPDsyB0aOG7gyByw7p0IHJhIG3hu5l0IHPhu5Ega+G6v3QgcXXhuqMgc2F1Og0KDQoxLiAgUGjDom4gcGjhu5FpIGdpw6EgY+G7p2Ega2ltIGPGsMahbmcgY8OzIGThuqFuZyBs4buHY2ggcGjhuqNpLCB04bupYyBsw6AgY8OzIG5oaeG7gXUga2ltIGPGsMahbmcgY8OzIGdpw6EgdHLhu4sgdGjhuqVwIGjGoW4gdsOgIMOtdCBraW0gY8awxqFuZyBjw7MgZ2nDoSB0cuG7iyBjYW8gaMahbi4NCg0KMi4gIE3DoHUgc+G6r2MgY+G7p2Ega2ltIGPGsMahbmcgxJHGsOG7o2MgcGjDom4gYuG7kSBraMOhIMSR4buBdSB0cm9uZyBwaOG6oW0gdmkgZ2nDoS4NCg0KQmnhu4N1IMSR4buTIGhpc3RvZ3JhbSBnacO6cCBjaMO6bmcgdGEgaGnhu4N1IMSRxrDhu6NjIHBow6JuIHBo4buRaSBj4bunYSBnacOhIGtpbSBjxrDGoW5nIHRyb25nIHThuq1wIGThu68gbGnhu4d1IHbDoCBxdWFuIHPDoXQgbeG7kWkgcXVhbiBo4buHIGdp4buvYSBnacOhIHbDoCBtw6B1IHPhuq9jIGPhu6dhIGtpbSBjxrDGoW5nLiBUdXkgbmhpw6puLCDEkeG7gyBjw7MgbeG7mXQgcGjDom4gdMOtY2ggY2hpIHRp4bq/dCBoxqFuIHbhu4EgbeG7kWkgcXVhbiBo4buHIG7DoHksIGNow7puZyB0YSBjw7MgdGjhu4MgY+G6p24gc+G7rSBk4bulbmcgY8OhYyBwaMawxqFuZyBwaMOhcCBwaMOibiB0w61jaCB0aOG7kW5nIGvDqiBraMOhYyBuaMawIHBow6JuIHTDrWNoIGjhu5NpIHF1eSBob+G6t2MgcGjDom4gdMOtY2ggcGjDom4gdMOhbi4NCg0KYGBge3J9DQp0biAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UsIGZpbGwgPSBjb2xvcikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAyMDAwKQ0KYGBgDQoNCiMjIyAqKk1lYW4gVGFibGUgLSBDdXQgLSBDb2xvcioqDQoNCkJp4buDdSDEkeG7kyDEkcaw4bujYyBjaGlhIHRow6BuaCBuaGnhu4F1IHBo4bqnbiBuaOG7jyAoZmFjZXQpIGThu7FhIHRyw6puIG3DoHUgc+G6r2MgY+G7p2Ega2ltIGPGsMahbmcuIE3hu5dpIHBo4bqnbiBuaOG7jyBjaOG7qWEgY8OhYyBj4buZdCBiaeG7g3UgdGjhu4sgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSAidGFibGUiIGNobyB04burbmcgbG/huqFpIGPhuq90LiBDw6FjIGNvbiBz4buRIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgbcOgdSBjaOG7ryBo4buTbmcuDQoNCkJp4buDdSDEkeG7kyBnacO6cCBjaMO6bmcgdGEgaGnhu4N1IMSRxrDhu6NjIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgbG/huqFpIGPhuq90LCBtw6B1IHPhuq9jIHbDoCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhICJ0YWJsZSIgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UuIE3hu5dpIHBo4bqnbiBuaOG7jyB0cm9uZyBiaeG7g3UgxJHhu5MgY2hvIHBow6lwIGNow7puZyB0YSBzbyBzw6FuaCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhICJ0YWJsZSIgZ2nhu69hIGPDoWMgbG/huqFpIGPhuq90IGtow6FjIG5oYXUgdHJvbmcgY8O5bmcgbeG7mXQgbcOgdSBz4bqvYyBj4bunYSBraW0gY8awxqFuZy4NCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY3V0LCBjb2xvciklPiVzdW1tYXJpc2UobT1tZWFuKHRhYmxlKSklPiVnZ3Bsb3QoYWVzKHg9Y3V0LCB5PSBtKSkrDQogIGdlb21fY29sKGZpbGwgPSd2aW9sZXQnKSsNCiAgZmFjZXRfd3JhcCh+Y29sb3IpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPSByb3VuZChtKSksIHZqdXN0PTIsIGNvbG9yPSdwaW5rJykrIGxhYnMoeD0gJ2N1dCcsIHk9ICdNZWFuJyx0aXRsZT0nR2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSB0YWJsZSB0aGVvIGN1dCB2w6AgY29sb3InKQ0KYGBgDQoNCiMjIyAqKk1lYW4gUHJpY2UgLSBDdXQgLSBDbGFyaXR5KioNCg0KQmnhu4N1IMSR4buTIMSRxrDhu6NjIGNoaWEgdGjDoG5oIG5oaeG7gXUgcGjhuqduIG5o4buPIChmYWNldCkgZOG7sWEgdHLDqm4gbeG7qWMgxJHhu5kgdGluaCBraGnhur90IGPhu6dhIGtpbSBjxrDGoW5nLiBN4buXaSBwaOG6p24gbmjhu48gY2jhu6lhIGPDoWMgY+G7mXQgYmnhu4N1IHRo4buLIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgInByaWNlIiBjaG8gdOG7q25nIGxv4bqhaSBj4bqvdC4gQ8OhYyBjb24gc+G7kSBnacOhIHRy4buLIHRydW5nIGLDrG5oIMSRxrDhu6NjIGhp4buDbiB0aOG7iyB0csOqbiBj4buZdCB0xrDGoW5nIOG7qW5nIHbhu5tpIG3DoHUgY2jhu68gaOG7k25nLg0KDQpCaeG7g3UgxJHhu5MgZ2nDunAgY2jDum5nIHRhIGhp4buDdSDEkcaw4bujYyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGxv4bqhaSBj4bqvdCwgbeG7qWMgxJHhu5kgdGluaCBraGnhur90IHbDoCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhICJwcmljZSIgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UuIE3hu5dpIHBo4bqnbiBuaOG7jyB0cm9uZyBiaeG7g3UgxJHhu5MgY2hvIHBow6lwIGNow7puZyB0YSBzbyBzw6FuaCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhICJwcmljZSIgZ2nhu69hIGPDoWMgbG/huqFpIGPhuq90IGtow6FjIG5oYXUgdHJvbmcgY8O5bmcgbeG7mXQgbeG7qWMgxJHhu5kgdGluaCBraGnhur90IGPhu6dhIGtpbSBjxrDGoW5nLg0KDQpgYGB7cn0NCnRuICU+JSBncm91cF9ieShjdXQsIGNsYXJpdHkpJT4lc3VtbWFyaXNlKG09bWVhbihwcmljZSkpJT4lZ2dwbG90KGFlcyh4PWN1dCwgeT0gbSkpKw0KICBnZW9tX2NvbChmaWxsPSdibHVlJykrDQogIGZhY2V0X3dyYXAofmNsYXJpdHkpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPSByb3VuZChtKSksIHZqdXN0PTEsIGNvbG9yPSdwaW5rJykrIGxhYnMoeD0gJ2N1dCcsIHk9ICdNZWFuJyx0aXRsZT0nR2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBwcmljZSB0aGVvIGN1dCB2w6AgY2xhcml0eScpDQpgYGANCg0KIyMjICoqVmFyIERlcHRoIC0gQ2xhcml0eSAtIENvbG9yKioNCg0KQmnhu4N1IMSR4buTIMSRxrDhu6NjIGNoaWEgdGjDoG5oIG5oaeG7gXUgcGjhuqduIG5o4buPIChmYWNldCkgZOG7sWEgdHLDqm4gbcOgdSBz4bqvYyBj4bunYSBraW0gY8awxqFuZy4gTeG7l2kgcGjhuqduIG5o4buPIGNo4bupYSBjw6FjIGPhu5l0IGJp4buDdSB0aOG7iyBwaMawxqFuZyBzYWkgY+G7p2EgImRlcHRoIiBjaG8gdOG7q25nIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dC4gQ8OhYyBjb24gc+G7kSBwaMawxqFuZyBzYWkgxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgbcOgdSBjaOG7ryDEkeG7jy4NCg0KQmnhu4N1IMSR4buTIGdpw7pwIGNow7puZyB0YSBoaeG7g3UgxJHGsOG7o2MgbeG7kWkgcXVhbiBo4buHIGdp4buvYSBt4bupYyDEkeG7mSB0aW5oIGtoaeG6v3QsIG3DoHUgc+G6r2MgdsOgIHBoxrDGoW5nIHNhaSBj4bunYSAiZGVwdGgiIHRyb25nIHThuq1wIGThu68gbGnhu4d1LiBN4buXaSBwaOG6p24gbmjhu48gdHJvbmcgYmnhu4N1IMSR4buTIGNobyBwaMOpcCBjaMO6bmcgdGEgc28gc8OhbmggcGjGsMahbmcgc2FpIGPhu6dhICJkZXB0aCIgZ2nhu69hIGPDoWMgbeG7qWMgxJHhu5kgdGluaCBraGnhur90IGtow6FjIG5oYXUgdHJvbmcgY8O5bmcgbeG7mXQgbcOgdSBz4bqvYyBj4bunYSBraW0gY8awxqFuZy4NCg0KYGBge3J9DQp0biAlPiUgZ3JvdXBfYnkoY2xhcml0eSxjb2xvciklPiVzdW1tYXJpc2UobT12YXIoZGVwdGgpKSU+JWdncGxvdChhZXMoeD1jbGFyaXR5LCB5PSBtKSkrDQogIGdlb21fY29sKGZpbGw9J2xpZ2h0Z3JlZW4nKSsNCiAgZmFjZXRfd3JhcCh+Y29sb3IpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPSByb3VuZChtKSksIHZqdXN0PTAuNSwgY29sb3I9J3JlZCcpKyBsYWJzKHg9ICdjbGFyaXR5JywgeT0gJ1ZhcicsdGl0bGU9J1BoxrDGoW5nIHNhaSBj4bunYSBkZXB0aCB0aGVvIGNsYXJpdHkgdsOgIGNvbG9yJykNCmBgYA0KDQojIyMgKipU4buVbmcga2ltIGPGsMahbmcgdGhlbyBDb2xvciAtIENsYXJpdHkqKg0KDQpE4buvIGxp4buHdSDEkcaw4bujYyBuaMOzbSB0aGVvIGhhaSBiaeG6v246IGN1dCAtIGNvbG9yLiBUcuG7pWMgeCBj4bunYSBiaeG7g3UgxJHhu5MgbMOgIGPDoWMgbG/huqFpIOKAnGN1dOKAnSwgdsOgIHRy4bulYyB5IGzDoCBz4buRIGzGsOG7o25nIG3huqt1LiBIYWkgY+G7mXQgxJHGsOG7o2MgduG6vSwgbeG7l2kgY+G7mXQgxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQgbcOgdSBz4bqvYzog4oCcReKAnSB2w6Ag4oCcSOKAnS4gUGjhuqduIG3DoHUgaOG7k25nIMSR4bqhaSBkaeG7h24gY2hvIG3DoHUg4oCcReKAnSwgdHJvbmcga2hpIHBo4bqnbiBtw6B1IG7DonUgxJHhuqFpIGRp4buHbiBjaG8gbcOgdSDigJxI4oCdLg0KDQpCaeG7g3UgxJHhu5MgZ2nDunAgY2jDum5nIHRhIGhp4buDdSDEkcaw4bujYyBz4buxIHBow6JuIGLhu5EgY+G7p2Egc+G7kSBsxrDhu6NuZyBjw6FjIG3huqt1IGThu7FhIHRyw6puIG3DoHUgc+G6r2MgdsOgIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyB04bqtcCBk4buvIGxp4buHdS4gVHLhu6VjIHggYmnhu4N1IHRo4buLIG3DoHUgc+G6r2MgdsOgIHRy4bulYyB5IGJp4buDdSB0aOG7iyBz4buRIGzGsOG7o25nLg0KDQpgYGB7cn0NCnQgPC0gdG4gJT4lIGdyb3VwX2J5KGNvbG9yLCBjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQpgYGANCg0KYGBge3J9DQp0ICU+JSBnZ3Bsb3QoYWVzKHggPSBjb2xvciwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSB0ICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnU0kyJyksIGZpbGwgPSAncGluaycpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHQgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdWUzEnKSwgZmlsbCA9ICdicm93bicpICsNCiAgbGFicyh4PSAnTcOgdSBz4bqvYycsIHk9ICdT4buRIGzGsOG7o25nJykNCmBgYA0K