1 Giới thiệu tổng quát về bộ dữ liệu Diamonds

  • Bộ dữ liệu Diamonds là bộ dữ liệu đã có sẵn trong Rstudio
  • Gán bộ dữ liệu diamonds thành g
library(ggplot2)
g <- diamonds
  • Bộ dữ liệu Diamonds nói về thông số các tính chất đặc tính của những viên kim cương với các kích thước khác nhau, gồm 53.940 biến ứng với 53.940 kích thước khác nhau của viên kim cương, có 10 quan sát ứng với 10 đặc tính khác nhau như:
dim(g)
## [1] 53940    10
names(g)
##  [1] "carat"   "cut"     "color"   "clarity" "depth"   "table"   "price"  
##  [8] "x"       "y"       "z"
  • Carat: kích thước của viên kim cương
  • Cut: chất lượng cắt (khá, tốt, rất tốt, đặc biệt, lý tưởng)
  • Color: màu sắc (J - kém nhất, D - tốt nhất)
  • Clarity: độ trong suốt (từ IF (tốt nhất) đến I1 (kém nhất))
  • Depth: Tỷ lệ phần trăm độ sâu (tính theo z / x)
  • Table: Chiều rộng của mặt bàn (tính theo % của đường kính)
  • Price: Giá (USD)
  • X: Chiều dài của viên kim cương (mm)
  • Y: Chiều rộng của viên kim cương (mm)
  • Z: Độ sâu của viên kim cương (mm)

2 Vẽ biểu đồ

2.1 Biểu đồ của dữ liệu cut

  • Cut: là chất lượng cắt của mặt kim cương, có 5 loại chất lượng khác nhau tùy vào mặt cắt mà phân bổ thành 6 loại:
    • Ideal: lý tưởng
    • Predium: tuyệt hảo
    • Very good: rất tốt
    • Good: tốt
    • Fair: kém

Vẽ biểu đồ thể hiện chất lượng của mặt cắt của các viên kim cương

  • Biểu đồ biểu thị số lượng các viên kim cương theo mặt cắt (không có số lượng cụ thể)
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
g %>% ggplot(aes(x = cut)) +
    geom_bar() +
    labs(title = "Hình cut1: Biểu đồ số lượng kim cương theo mặt cắt",x = 'Loại', y = 'Số lượng')

Nhận xét: - Từ kết quả trên ta thấy được số lượng kim cương có chất lượng mặt cắt ideal(lý tưởng) chiếm đa số và số lượng viên kim cương có chất lượng fair(kém) là thấp nhất.

  • Biểu đồ biểu thị số lượng các viên kim cương theo mặt cắt (có số lượng cụ thể)
g %>% group_by(cut) %>% summarise(n = n()) %>%
  ggplot(aes(cut,n)) +
    geom_col(fill='pink') +
    geom_text(aes(label = n),vjust = 2, color = 'brown') +
    labs(title  = "Hình 1: Biểu đồ thể hiện chi tiết số lượng các viên kim cương theo chất lượng mặt cắt",x = 'Loại', y = 'Số lượng')

Giải thích - Từ kết quả ta thu được có 1.610 viên kim cương có chất lượng mặt cắt kém, 4.906 viên kim cương có chất lượng mặt cắt tốt, có 12.082 viên kim cương có chất lượng mặt cắt rất tốt, có 13.791 viên kim cương có chất lượng mặt cắt tuyệt hảo và 21.551 viên kim cương có chất lượng mặt cắt lý tưởng. - Vậy số viên kim cương có chất lượng mặt cắt ideal gấp 13 lần loại fair (chiếm 1/2 số lượng viên kim cương)

  • Để dễ dàng tính toán và hình dung ta có thể chuyển biểu đồ như trên sang dạng %.
# Load the scales package
library(scales)

# Define a custom percent function
percent <- function(x) {
  paste0(formatC(x * 100, format = "f", digits = 1), "%")
}

# Use the percent function
result <- percent(0.75)
print(result)
## [1] "75.0%"
g %>% group_by(cut) %>% summarise(n = n()) %>%
  ggplot(aes(cut,n)) +
    geom_col(fill='gray') +
    labs(title = "Biểu đồ thể hiện số lượng kim cương theo mặt cắt dưới dạng phần trăm ") +
    theme_classic() +
    geom_text(aes(label = percent(n/length(g$cut))),vjust = 2, color = 'red') +
    labs(x = 'Thang đo Cut', y = 'Số lượng')

Giải thích: - Nhìn vào biểu đồ ta thấy ngay phần trăm số kim cương loại ideal trên tổng thể là 40%, trong khi đó loại fair chỉ chiếm 3% trên tổng thể tức là các viên kim cương sẽ có chất lượng bề mặt cắt cao nên từ đó sẽ được lựa chọn nhiều và bán được dễ dàng hơn.

2.2 Biểu đồ của dữ liệu color

Vẽ biểu đồ theo màu sắc của các viên kim cương

  • Tổng quan về màu sắc của các viên kim cương có 7 màu từ D đến J tương ứng với 2 cấp độ là không màu (D,E,F) và gần như không màu (G,H,I,J).
table (g$color)
## 
##     D     E     F     G     H     I     J 
##  6775  9797  9542 11292  8304  5422  2808
  • Biểu đồ thể hiện số lượng viên kim cương theo màu sắc
g %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(x = 'màu sắc', y = 'số lượng',fill = color)) +
    geom_col() +
    geom_text(aes(label = n),position = position_stack(vjust = 1))

Nhận xét: - Cấp độ không màu có tổng số kim cương là 6.775 có màu D, 9.797 có màu loại E, 9.542 có màu loại F - Cấp độ gần như không màu có tổng số kim cương là 11.292 có màu G, 8.304 có màu loại H, 5.422 có màu loại I, 2.808 có màu loại J.

  • Biểu đồ nằm ngang thể hiện số lượng viên kim cương theo màu sắc
g %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(n,color)) +
    geom_col(fill='blue') +
    labs(title = " Biểu đồ thể hiện nhóm theo Color (màu sắc) ") +
    geom_text(aes(label = n),vjust = 1, color = 'yellow') +
    labs(x = 'Số lượng', y = 'Các màu sắc')

Nhận xét: - Như ta thấy màu G chiếm đa số trong tất cả các màu là màu phổ biến trong tổng số các viên kim cương lên đến 11.292 số lượng kim cương có màu G - Ngược lại số lượng kim cương màu J chỉ chiếm số ít trong tổng số kim cương là 2.808 viên - Từ đó có thể thấy số lượng viên kim cương màu G gấp 5 lần số lượng kim cương có màu J - Xét theo cấp độ thì tổng số kim cương ở cấp không màu chiếm một lượng ít hơn với cấp gần như không màu

  • Dựa vào đồ thị trên ta chuyển sang dạng % để có thể dễ hình dung và phân tích
g %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(n,color)) +
    geom_col(fill='gray') +
    labs(title = "Biểu đồ thể hiện % theo Color (màu sắc) ") +
    theme_classic() +
    geom_text(aes(label = percent(n/length(g$color))),vjust = 1, color = 'black') +
    labs(x = 'Số lượng', y = 'màu sắc')

Nhận xét: - Cũng tương tự như nhận xết ở trên - Biểu đồ thể hiện % số lượng kim cương của các màu, có 20.93% trên tổng số kim cương có màu G, có 18.16% trên tổng số kim cương có màu E, có 17.96% trên tổng số kim cương có màu F, có 15.39% trên tổng số kim cương có màu H, có 12.56% trên tổng số kim cương có màu D, có 10.05% trên tổng số kim cương có màu I, có 5.21% trên tổng số kim cương có màu J.

2.3 Biểu đồ của dữ liệu clarity

  • Độ tinh khiết/ Độ trong của kim cương là số lượng và khả năng hiển thị của các đặc điểm bên trong (tạp chất) và bên ngoài(vết trầy xước) của một viên kim cương.
  • có 8 cấp độ tinh khiết trong bộ dữ liệu, gồm:
    • Internally Flawless - IF : Hoàn hảo bên trong, chỉ có tỳ vết không quan trọng bên ngoài
    • Very Very Slightly Included - VVS - gồm 2 cấp nhỏ (VVS1, VVS2) : Có những tạp chất, vết trầy nhỏ, khó thấy được
    • Very Slightly Included - VS - có 2 cấp nhỏ (VS1, VS2) : Có những tạp chất, vết trầy từ khó thấy đến dễ thấy
    • Slightly Included - SI - có 2 cấp nhỏ (SI1, SI2) : Có những tạp chất, vết trầy dễ thấy hoặc rất dễ thấy
    • Included - I - có 3 cấp nhỏ (I1,I2,I3) : Không hoàn hảo lẫn bên trong lẫn bên ngoài

Vẽ biểu đồ theo độ tinh khiết (clarity) của các viên kim cương

  • Biểu đồ thể hiện số lượng theo clarity
g %>% group_by(clarity) %>% summarise(n = n()) %>%
  ggplot(aes(clarity,n)) +
    geom_col(fill='lightblue') +
    geom_text(aes(label = n),vjust = 2, color = 'brown') +
    labs(title ="Hình 4: Biểu đồ số lượng kim cương theo clarity (độ tinh khiết)",x = 'độ tinh khiết ', y = 'Số lượng')

Nhận xét: - Loại SI1 có số lượng kim cương cao nhất (13065) - Loại I1 có số lượng kim cương thấp nhất (741) - Số lượng kim cương có độ tinh khiết I1(Bao thể hiện thị): 741 - Số lượng kim cương có độ tinh khiết SI2/SI1(Bao thể nhỏ): 9194/13605 - Số lượng kim cương có độ tinh khiết VS2/VS1(Bao thể nhỏ cấp 2/ cấp 1):12258/8171 - Số lượng kim cương có độ tinh khiết VVS2/VVS1(Khuyết tật rất nhỏ):5066/3655 - Số lượng kim cương có độ tinh khiết IF(Hoàn toàn tinh khiết): 1790

  • Biểu đồ thể hiện phần trăm theo clarity
  • Dựa vào biểu đồ trên ta vẽ thêm biểu đồ thể hiện dưới dạng phần trăm
g %>% group_by(clarity) %>% summarise(n = n()) %>%
  ggplot(aes(clarity, n)) +
    geom_col(fill='purple') +
    geom_text(aes(label = percent(n/length(g$clarity))),vjust = 1, color = 'black')+
    labs(title ="Hình 4: Biểu đồ số lượng kim cương theo clarity (độ tinh khiết)",x = 'Số lượng', y = 'Độ tinh khiết')

Nhận xét: - Tương tự với biểu đồ trên nhưng thay bằng %, với phần trăm là 24,2% - mức SI1 có tỷ lệ chiếm cao nhất - Các tỷ lệ đứng thứ 2,3,4 lần lượt là VS2 22,7% - SI2 17% - VS1 15,1% - Tỷ lệ của 3 mức độ này cách mức độ đứng đầu khoảng 2 - 10% - Từ đó ta thấy được, không có mức độ nào là có số lượng cao hơn hẳn/ rõ rệt hơn các mức còn lại - Mức VVS2 và VVS1 đứng gần áp chót của biểu đồ với tỷ lệ ít hơn : 9,4% và 6,8% - Và cuối cùng, mức có tỷ lệ ít nhất trong bảng lần lượt là IF - 3,3% và I1 - 1,1% - Khoảng cách của 2 mức nhiều và ít nhất là khoảng hơn 22%

2.4 Biểu đồ giá trị trung bình của dữ liệu depth

  • vẽ biểu đồ giá trị trung bình của depth theo cut và clarity
g %>% group_by(cut, clarity)%>%summarise(m=mean(depth))%>%ggplot(aes(x=cut, y= m))+
  geom_col(position='dodge')+
  facet_wrap(~clarity)+
  geom_text(aes(label= round(m)), vjust=2, color='gray')+ 
  labs(x= 'Loại', y= 'Độ sâu trung bình',title='Hình 2: Giá trị trung bình của depth theo cut và clarity ')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

Nhận xét: - group_by(cut, clarity) : Nhóm dữ liệu theo cột “cut” và “clarity”. - summarise(m = mean(depth)) : Tính giá trị trung bình của cột “depth” trong mỗi nhóm và tạo một cột mới có tên “m” để lưu giá trị trung bình. - ggplot(aes(x = cut, y = m)) : Tạo một đối tượng ggplot với trục x là “cut” và trục y là “m”. - geom_col(position = ‘dodge’) : Vẽ biểu đồ cột sử dụng hình dạng mặc định và sử dụng phương pháp “dodge” để xếp chồng các cột của các nhóm. - facet_wrap(~clarity) : Chia biểu đồ thành các panel riêng biệt dựa trên cột “clarity”. - geom_text(aes(label = round(m)), vjust = 2, color = ‘red’): Thêm nhãn dữ liệu trên mỗi cột, với giá trị được làm tròn và màu chữ đỏ. Tham số vjust = 2 làm tăng khoảng cách giữa cột và nhãn. - Độ sâu trung bình của các loại kim cương ở các mức độ tinh khiết không có sự chênh lệch nhiều, đều dao động ở các mức độ 60,61,62,63,64.

  • vẽ biểu đồ giá trị trung bình của depth theo cut và color
g %>% group_by(cut,color) %>% summarise(m = mean(depth)) %>%
  ggplot(aes(x = cut,y = m)) +
    geom_col(position = 'dodge') +
    facet_wrap(~color) +
    geom_text(aes(label= round(m)), vjust=2, color='gray')+ 
  labs(x= 'Loại', y= 'Độ sâu trung bình',title='Hình 23: Giá trị trung bình của depth theo cut và color ')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

Nhận xét: - Độ sâu trung bình của các loại kim cương ở các màu sắc khác nhau không có sự chênh lệch nhiều, đều dao động ở các mức độ 60,61,62,63,64.

2.5 Biểu đồ thể hiện giá trị trung bình giá bán theo biến: cut, color và clarity

Vẽ biểu đồ thể hiện giá trị trung bình giá bán theo màu sắc kim cương

  • Biểu đồ này thể hiện giá trị trung bình của giá bán theo từng màu sắc của kim cương trong bộ dữ liệu diamonds.
g <- diamonds
g %>% group_by(color) %>% summarise(k= mean(price)) %>%
  ggplot(aes(color,k)) +
    geom_col(fill='skyblue') + 
    geom_text(aes(label = round(k,2)),vjust = 1, color = 'black') +
    labs(x = 'Màu', y = 'Số lượng')

Nhận xét: - Trục x: Thể hiện các màu sắc khác nhau của kim cương. - Trục y: Thể hiện giá trị trung bình (k) giá bán, được làm tròn đến 2 chữ số thập phân (round(k, 2)), của kim cương thuộc mỗi màu sắc. - Cột màu xanh nhạt (“skyblue”): Chiều cao của mỗi cột tỷ lệ thuận với giá trị trung bình giá bán của kim cương có màu sắc tương ứng. - Chú thích văn bản màu đen (“black”): Hiển thị giá trị trung bình chính xác (được làm tròn) nằm trên đỉnh mỗi cột. - Ví dụ cụ thể:

  • Màu J cao nhất trong biểu đồ. Điều này có nghĩa là kim cương màu J có giá trị trung bình giá bán cao nhất trong số các màu sắc. Ví dụ, chú thích trên cột màu J có thể hiển thị giá trị 5323,82 USD, cho biết kim cương màu J trung bình có giá bán 5323,82 USD.

  • Màu E thấp nhất trong biểu đồ. Điều này có nghĩa là kim cương màu E có giá trị trung bình giá bán thấp nhất trong số các màu sắc. Ví dụ, chú thích trên cột màu M có thể hiển thị giá trị 3076,75 USD, cho biết kim cương màu M trung bình có giá bán 3076,75 USD.

Vẽ biểu đồ thể hiện giá trị trung bình giá bán theo chất lượng cắt

  • Biểu đồ này thể hiện giá trị trung bình của giá bán theo từng chất lượng cắt của kim cương trong bộ dữ liệu diamonds.
g <- diamonds
g %>% group_by(cut) %>% summarise(k= mean(price)) %>%
  ggplot(aes(cut,k)) +
    geom_col(fill='lightyellow') + 
    geom_text(aes(label = round(k,2)),vjust = 1, color = 'black') +
    labs(x = 'Chất lượng cắt', y = 'Số lượng')

Nhận xét: - Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Poor” (kém) đến “Ideal” (hoàn hảo). - Trục y: Thể hiện giá trị trung bình (k) giá bán, được làm tròn đến 2 chữ số thập phân (round(k, 2)), của kim cương thuộc mỗi chất lượng cắt. - Cột màu xanh nhạt (“skyblue”): Chiều cao của mỗi cột tỷ lệ thuận với giá trị trung bình giá bán của kim cương có chất lượng cắt tương ứng. - Chú thích văn bản màu đen (“black”): Hiển thị giá trị trung bình chính xác (được làm tròn) nằm trên đỉnh mỗi cột.

Biểu đồ thể hiện giá trị trung bình giá bán theo độ trong suốt

  • Biểu đồ này thể hiện giá trị trung bình của giá bán theo từng độ trong suốt của kim cương trong bộ dữ liệu diamonds.
g <- diamonds
g %>% group_by(clarity) %>% summarise(k= mean(price)) %>%
  ggplot(aes(clarity,k)) +
    geom_col(fill='lightyellow') + 
    geom_text(aes(label = round(k,2)),vjust = 1, color = 'black') +
    labs(x = 'Độ trong suốt', y = 'Số lượng')

Nhận xét: - Trục x: Thể hiện các độ trong suốt khác nhau của kim cương, từ “I1” (kém trong) đến “IF” (hoàn hảo không tì vết). - Trục y: Thể hiện giá trị trung bình (k) giá bán, được làm tròn đến 2 chữ số thập phân (round(k, 2)), của kim cương thuộc mỗi độ trong suốt. - Cột màu xanh nhạt (“skyblue”): Chiều cao của mỗi cột tỷ lệ thuận với giá trị trung bình giá bán của kim cương có độ trong suốt tương ứng. - Chú thích văn bản màu đen (“black”): Hiển thị giá trị trung bình chính xác (được làm tròn) nằm trên đỉnh mỗi cột.

2.6 Biểu đồ cột thể hiện phương sai giá bán theo các biến: cut, color và clarity.

Biểu đồ cột thể hiện phương sai giá bán theo màu sắc kim cương

  • Biểu đồ này thể hiện phương sai của giá bán theo từng màu sắc của kim cương trong bộ dữ liệu diamonds. Phương sai là một thước đo mức độ phân tán của dữ liệu.
g <- diamonds
g %>% group_by(color) %>% summarise(k= var(price)) %>%
  ggplot(aes(color,k)) +
    geom_col(fill='gray') + 
    geom_text(aes(label = round(k,2)),vjust = 1, color = 'black') +
    labs(x = 'Màu', y = 'Số lượng')

Nhận xét: - Trục x: Thể hiện các màu sắc khác nhau của kim cương. - Trục y: Thể hiện phương sai (k) của giá bán (được làm tròn đến 2 chữ số thập phân (round(k, 2))), cho biết mức độ trải rộng của giá bán - Giá trị cao hơn trên trục y cho biết phương sai cao hơn, nghĩa là giá bán của kim cương có màu sắc đó phân tán rộng hơn xung quanh giá trung bình. - Giá trị thấp hơn menunjukkan phương sai thấp hơn, nghĩa là giá bán của kim cương có màu sắc đó ít phân tán hơn xung quanh giá trung bình. - Các cột màu xám (“gray”): Chiều cao của mỗi cột tỷ lệ thuận với phương sai giá bán của kim cương có màu sắc tương ứng. - Chú thích văn bản màu đen (“black”): Hiển thị phương sai chính xác (được làm tròn) nằm trên đỉnh mỗi cột.

Biểu đồ cột thể hiện phương sai giá bán theo chất lượng cắt

  • Biểu đồ này thể hiện phương sai của giá bán theo từng chất lượng cắt của kim cương trong bộ dữ liệu diamonds. Phương sai là một thước đo mức độ phân tán của dữ liệu.
g <- diamonds
g %>% group_by(cut) %>% summarise(k= var(price)) %>%
  ggplot(aes(cut,k)) +
    geom_col(fill='lightyellow') + 
    geom_text(aes(label = round(k,2)),vjust = 1, color = 'black') +
    labs(x = 'Chất lượng cắt', y = 'Số lượng')

  • Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Poor” (kém) đến “Ideal” (hoàn hảo).
  • Trục y: Thể hiện phương sai (k) của giá bán (được làm tròn đến 2 chữ số thập phân (round(k, 2))), cho biết mức độ trải rộng của giá bán
  • Giá trị cao hơn trên trục y cho biết phương sai cao hơn, nghĩa là giá bán của kim cương có chất lượng cắt đó phân tán rộng hơn xung quanh giá trung bình.
  • Giá trị thấp hơn menunjukkan phương sai thấp hơn, nghĩa là giá bán của kim cương có chất lượng cắt đó ít phân tán hơn xung quanh giá trung bình.
  • Các cột màu vàng nhạt (“lightyellow”): Chiều cao của mỗi cột tỷ lệ thuận với phương sai giá bán của kim cương có chất lượng cắt tương ứng.
  • Chú thích văn bản màu đen (“black”): Hiển thị phương sai chính xác (được làm tròn) nằm trên đỉnh mỗi cột.

Biểu đồ cột thể hiện phương sai giá bán theo độ trong suốt

  • Biểu đồ này thể hiện phương sai của giá bán theo từng độ trong suốt của kim cương trong bộ dữ liệu diamonds. Phương sai là một thước đo mức độ phân tán của dữ liệu.
g <- diamonds
g %>% group_by(clarity) %>% summarise(k= var(price)) %>%
  ggplot(aes(clarity,k)) +
    geom_col(fill='lightyellow') + 
    geom_text(aes(label = round(k,2)),vjust = 0.85, color = 'black') +
    labs(x = 'Độ trong suốt', y = 'Số lượng')

Nhận xét: - Trục x: Thể hiện các độ trong suốt khác nhau của kim cương, từ “I1” (kém trong) đến “IF” (hoàn hảo không tì vết). - Trục y: Thể hiện phương sai (k) của giá bán (được làm tròn đến 2 chữ số thập phân (round(k, 2))), cho biết mức độ trải rộng của giá bán - Giá trị cao hơn trên trục y cho biết phương sai cao hơn, nghĩa là giá bán của kim cương có độ trong suốt đó phân tán rộng hơn xung quanh giá trung bình. - Giá trị thấp hơn menunjukkan phương sai thấp hơn, nghĩa là giá bán của kim cương có độ trong suốt đó ít phân tán hơn xung quanh giá trung bình. - Các cột màu vàng nhạt (“lightyellow”): Chiều cao của mỗi cột tỷ lệ thuận với phương sai giá bán của kim cương có độ trong suốt tương ứng. - Chú thích văn bản màu đen (“black”): Hiển thị phương sai chính xác (được làm tròn) nằm gần đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 0.85 để tránh chồng chéo lên các cột.

2.7 Biểu đồ cột thể hiện phương sai trọng lượng carat theo các biến: Cut, color, clarity.

Biểu đồ cột thể hiện phương sai trọng lượng carat theo màu sắc kim cương

  • Biểu đồ này thể hiện mức độ phân tán của trọng lượng carat (k) theo từng màu sắc của kim cương trong tập dữ liệu diamonds.
g <- diamonds
g %>% group_by(color) %>% summarise(k= var(carat)) %>%
  ggplot(aes(color,k)) +
    geom_col(fill='lightyellow') + 
    geom_text(aes(label = round(k,2)),vjust = 1, color = 'black') +
    labs(x = 'Màu', y = 'Số lượng')

Nhận xét: - Trục x: Thể hiện các màu sắc khác nhau của kim cương. - Trục y: Thể hiện phương sai (k) của trọng lượng carat (đã được làm tròn đến 2 chữ số thập phân), cho biết mức độ trải rộng của trọng lượng carat: - Giá trị cao hơn trên trục y cho biết phương sai cao hơn, nghĩa là trọng lượng carat của kim cương có màu sắc đó phân tán rộng hơn xung quanh giá trị trung bình. - Giá trị thấp hơn cho biết phương sai thấp hơn, nghĩa là trọng lượng carat của kim cương có màu sắc đó ít phân tán hơn xung quanh giá trị trung bình. - Cột màu vàng nhạt: Chiều cao của mỗi cột tỷ lệ thuận với phương sai trọng lượng carat của kim cương có màu sắc tương ứng. - Chú thích văn bản màu đen: Hiển thị phương sai chính xác (đã được làm tròn) nằm trên đỉnh mỗi cột.

Biểu đồ cột thể hiện phương sai trọng lượng carat theo chất lượng cắt

  • Biểu đồ này thể hiện phương sai của trọng lượng carat theo từng chất lượng cắt của kim cương trong bộ dữ liệu diamonds. Phương sai là một thước đo mức độ phân tán của dữ liệu.
g <- diamonds
g %>% group_by(cut) %>% summarise(k= var(carat)) %>%
  ggplot(aes(cut,k)) +
    geom_col(fill='lightyellow') + 
    geom_text(aes(label = round(k,3)),vjust = 1, color = 'black') +
    labs(x = 'Chất lượng cắt', y = 'Số lượng')

  • Biểu đồ này thể hiện phương sai của trọng lượng carat theo từng chất lượng cắt của kim cương trong bộ dữ liệu diamonds. Phương sai là một thước đo mức độ phân tán của dữ liệu.
    • Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Poor” (kém) đến “Ideal” (hoàn hảo).
    • Trục y: Thể hiện phương sai (k) của trọng lượng carat (được làm tròn đến 2 chữ số thập phân (round(k, 2))), cho biết mức độ trải rộng của trọng lượng carat
      • Giá trị cao hơn trên trục y cho biết phương sai cao hơn, nghĩa là trọng lượng carat của kim cương có chất lượng cắt đó phân tán rộng hơn xung quanh giá trị trung bình.
      • Giá trị thấp hơn trên trục y cho biết phương sai thấp hơn, nghĩa là trọng lượng carat của kim cương có chất lượng cắt đó ít phân tán hơn xung quanh giá trị trung bình.
    • Các cột màu vàng nhạt (“yellow”): Chiều cao của mỗi cột tỷ lệ thuận với phương sai trọng lượng carat của kim cương có chất lượng cắt tương ứng.
    • Chú thích văn bản màu đen (“black”): Hiển thị phương sai chính xác (được làm tròn) nằm trên đỉnh mỗi cột.

Biểu đồ cột thể hiện phương sai trọng lượng carat theo độ trong suốt

g <- diamonds
g %>% group_by(clarity) %>% summarise(k= var(carat)) %>%
  ggplot(aes(clarity,k)) +
    geom_col(fill='lightyellow') + 
    geom_text(aes(label = round(k,2)),vjust = 1, color = 'black') +
    labs(x = 'Độ trong suốt', y = 'Số lượng')

  • Biểu đồ này thể hiện phương sai của trọng lượng carat theo từng độ trong suốt của kim cương trong bộ dữ liệu diamonds. Phương sai là một thước đo mức độ phân tán của dữ liệu.

    • Trục x: Thể hiện các độ trong suốt khác nhau của kim cương, từ “I1” (kém trong) đến “IF” (hoàn hảo không tì vết).
    • Trục y: Thể hiện phương sai (k) của trọng lượng carat (được làm tròn đến 2 chữ số thập phân (round(k, 2))), cho biết mức độ trải rộng của trọng lượng carat
    • Giá trị cao hơn trên trục y cho biết phương sai cao hơn, nghĩa là trọng lượng carat của kim cương có độ trong suốt đó phân tán rộng hơn xung quanh giá trị trung bình.
    • Giá trị thấp hơn trên trục y cho biết phương sai thấp hơn, nghĩa là trọng lượng carat của kim cương có độ trong suốt đó ít phân tán hơn xung quanh giá trị trung bình.
    • Các cột màu vàng nhạt (“lightyellow”): Chiều cao của mỗi cột tỷ lệ thuận với phương sai trọng lượng carat của kim cương có độ trong suốt tương ứng. Chú thích văn bản màu đen (“black”): Hiển thị phương sai chính xác (được làm tròn) nằm trên đỉnh mỗi cột.

2.8 Biểu đồ cột kép thể hiện phân bố số lượng kim cương theo chất lượng cắt và màu sắc

Biểu đồ cột kép thể hiện phân bố số lượng kim cương theo chất lượng cắt và màu sắc của kim cương loại E và H

  • Biểu đồ này thể hiện số lượng kim cương theo từng chất lượng cắt (cut) và màu sắc (color) trong bộ dữ liệu diamonds.
g <- diamonds
g <- g %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
g %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = g %>% filter(color == 'E'), fill = 'lightyellow') +
  geom_col(data = g %>% filter(color == 'H'), fill = 'pink')

Nhận xét: - Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Fair” (kém) đến “Ideal” (hoàn hảo). - Trục y: Thể hiện số lượng (n) kim cương. - Cột màu vàngvàng nhạt (“skyblue”): Biểu thị số lượng kim cương có màu E theo từng chất lượng cắt. - Cột màu hồng (“pink”): Biểu thị số lượng kim cương có màu H theo từng chất lượng cắt.

Biểu đồ cột kép thể hiện phân bố số lượng kim cương theo chất lượng cắt và màu sắc của kim cương loại E và H

  • Biểu đồ này thể hiện số lượng kim cương theo từng chất lượng cắt (cut) và màu sắc (color) trong bộ dữ liệu diamonds.
g <- diamonds
g <- g %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
g %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = g %>% filter(color == 'E'), fill = 'lightyellow') +
  geom_col(data = g %>% filter(color == 'I'), fill = 'pink')

Nhận xét: - Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Fair” (kém) đến “Ideal” (hoàn hảo). - Trục y: Thể hiện số lượng (n) kim cương. - Cột màu xanh nhạt (“skyblue”): Biểu thị số lượng kim cương có màu E theo từng chất lượng cắt. - Cột màu hồng (“pink”): Biểu thị số lượng kim cương có màu I theo từng chất lượng cắt.

2.9 Biểu đồ thanh thể hiện phân bố chất lượng cắt kim cương

  • Biểu đồ này thể hiện phân bố của chất lượng cắt kim cương trong bộ dữ liệu diamonds.
g <- diamonds 
g <- g %>% mutate(caratC = cut(carat,5, label = c('rất nhỏ', 'nhỏ','vừa','lớn','rất lớn')))
g %>% ggplot(aes(x = caratC)) +
  geom_bar(fill = 'blue')

  labs(x= 'Chất lượng cắt')
## $x
## [1] "Chất lượng cắt"
## 
## attr(,"class")
## [1] "labels"

Nhận xét: - Trục x: Thể hiện các chất lượng cắt được chia thành 5 nhóm: “rất nhỏ”, “nhỏ”, “vừa”, “lớn”, “rất lớn”. - Trục y: Thể hiện số lượng kim cương thuộc mỗi nhóm chất lượng cắt. Cột màu vàng: Biểu thị số lượng kim cương cho mỗi nhóm chất lượng cắt.

2.10 Biểu đồ cột kép theo mặt cắt (cut) phân tách theo màu sắc (color)

  • Biểu đồ này thể hiện phân bố số lượng kim cương theo chất lượng cắt (cut) được tách riêng theo màu sắc (color) trong bộ dữ liệu g.
g %>% group_by(cut,color) %>% summarise(n =n()) %>%
  ggplot(aes(x = cut,y = n)) +
    geom_col(position = 'dodge', fill= 'lightyellow') +
    facet_wrap(~color) +
    geom_text(aes(label = n),vjust = 0.65, color = 'black') +
    labs(x = 'Loại', y = 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

Các thành phần:

  • Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Poor” (kém) đến “Ideal” (hoàn hảo).
  • Trục y: Thể hiện số lượng (n) kim cương.
  • Các mặt cắt (facets): Biểu đồ được chia thành hai mặt cắt theo màu sắc (color) của kim cương, được phân biệt bằng nhãn ở phía trên mỗi mặt cắt.
    • Mặt cắt D: Biểu thị phân bố số lượng kim cương theo chất lượng cắt cho màu sắc D.
    • Mặt cắt E: Biểu thị phân bố số lượng kim cương theo chất lượng cắt cho màu sắc E.
    • Mặt cắt F: Biểu thị phân bố số lượng kim cương theo chất lượng cắt cho màu sắc F.
    • Mặt cắt G: Biểu thị phân bố số lượng kim cương theo chất lượng cắt cho màu sắc G.
    • Mặt cắt H: Biểu thị phân bố số lượng kim cương theo chất lượng cắt cho màu sắc H.
    • Mặt cắt I: Biểu thị phân bố số lượng kim cương theo chất lượng cắt cho màu sắc I.
    • Mặt cắt J: Biểu thị phân bố số lượng kim cương theo chất lượng cắt cho màu sắc J.
  • Cột màu vàng nhạt (“lightyellow”): Biểu thị số lượng kim cương cho mỗi chất lượng cắt trong mỗi mặt cắt.
  • Chú thích văn bản màu đen (“black”): Hiển thị số lượng kim cương chính xác (n) nằm trên đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 0.65 để tránh chồng chéo lên các cột.

2.11 Biểu đồ cột kép theo mặt cắt (cut) phân tách theo màu sắc (color), thể hiện giá trung bình

  • Biểu đồ này thể hiện giá trung bình của kim cương theo chất lượng cắt (cut) được tách riêng theo màu sắc (color) trong bộ dữ liệu g.
g %>% group_by(cut,color) %>% summarise(k =mean(price)) %>%
  ggplot(aes(x = cut,y = k)) +
    geom_col(position = 'dodge', fill= 'lightyellow') +
    facet_wrap(~color) +
    geom_text(aes(label = round(k,1)),vjust = 0.25, color = 'black') +
    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: Các thành phần:

  • Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Poor” (kém) đến “Ideal” (hoàn hảo).
  • Trục y: Thể hiện giá trung bình (k) được làm tròn đến 1 chữ số thập phân (round(k, 1)).
  • Các mặt cắt (facets): Biểu đồ được chia thành hai mặt cắt theo màu sắc (color) của kim cương, được phân biệt bằng nhãn ở phía trên mỗi mặt cắt.
    • Mặt cắt D: Biểu thị giá trung bình của kim cương theo chất lượng cắt cho màu sắc D.
    • Mặt cắt E: Biểu thị giá trung bình của kim cương theo chất lượng cắt cho màu sắc E.
    • Mặt cắt F: Biểu thị giá trung bình của kim cương theo chất lượng cắt cho màu sắc F.
    • Mặt cắt G: Biểu thị giá trung bình của kim cương theo chất lượng cắt cho màu sắc G.
    • Mặt cắt H: Biểu thị giá trung bình của kim cương theo chất lượng cắt cho màu sắc H.
    • Mặt cắt I: Biểu thị giá trung bình của kim cương theo chất lượng cắt cho màu sắc I.
    • Mặt cắt J: Biểu thị giá trung bình của kim cương theo chất lượng cắt cho màu sắc J.
  • Cột màu vàng nhạt (“lightyellow”): Biểu thị giá trung bình cho mỗi chất lượng cắt trong mỗi mặt cắt.
  • Chú thích văn bản màu đen (“black”): Hiển thị giá trung bình chính xác (được làm tròn) nằm trên đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 0.25 để tránh chồng chéo lên các cột.

2.12 Biểu đồ cột kép theo mặt cắt (cut) phân tách theo màu sắc (color), thể hiện trọng lượng carat trung bình

  • Biểu đồ này thể hiện trọng lượng carat trung bình của kim cương theo chất lượng cắt (cut) được tách riêng theo màu sắc (color) trong bộ dữ liệu g.
g %>% group_by(cut,color) %>% summarise(k=mean(carat)) %>%
  ggplot(aes(x = cut,y = k)) +
    geom_col(position = 'dodge', fill= 'lightyellow') +
    facet_wrap(~color) +
    geom_text(aes(label = round(k,2)),vjust = 0.65, color = 'black') +
    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: Các thành phần:

  • Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Poor” (kém) đến “Ideal” (hoàn hảo).
  • Trục y: Thể hiện trọng lượng carat trung bình (k) được làm tròn đến 2 chữ số thập phân (round(k, 2)).
  • Các mặt cắt (facets): Biểu đồ được chia thành hai mặt cắt theo màu sắc (color) của kim cương, được phân biệt bằng nhãn ở phía trên mỗi mặt cắt.
    • Mặt cắt D: Biểu thị trọng lượng carat trung bình của kim cương theo chất lượng cắt cho màu sắc D.
    • Mặt cắt E: Biểu thị trọng lượng carat trung bình của kim cương theo chất lượng cắt cho màu sắc E.
    • Mặt cắt F: Biểu thị trọng lượng carat trung bình của kim cương theo chất lượng cắt cho màu sắc F.
    • Mặt cắt G: Biểu thị trọng lượng carat trung bình của kim cương theo chất lượng cắt cho màu sắc G.
    • Mặt cắt H: Biểu thị trọng lượng carat trung bình của kim cương theo chất lượng cắt cho màu sắc H.
    • Mặt cắt I: Biểu thị trọng lượng carat trung bình của kim cương theo chất lượng cắt cho màu sắc I.
    • Mặt cắt J: Biểu thị trọng lượng carat trung bình của kim cương theo chất lượng cắt cho màu sắc J.
  • Cột màu vàng nhạt (“lightyellow”): Biểu thị trọng lượng carat trung bình cho mỗi chất lượng cắt trong mỗi mặt cắt.
  • Chú thích văn bản màu đen (“black”): Hiển thị trọng lượng carat trung bình chính xác (được làm tròn) nằm trên đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 0.65 để tránh chồng chéo lên các cột.

2.13 Biểu đồ cột thể hiện trung vị trọng lượng carat theo các biến: cut, color, clarity

Biểu đồ cột thể hiện trung vị trọng lượng carat theo chất lượng cắt (cut)

  • Biểu đồ này thể hiện trung vị của trọng lượng carat theo chất lượng cắt (cut) trong bộ dữ liệu g.
g %>% group_by(cut) %>% summarise(m= median(carat)) %>%
  ggplot(aes(x = cut,y = m)) +
    geom_col(position = 'dodge', fill= 'lightyellow') +
    geom_text(aes(label = round(m,2)), vjust = 2, color = 'pink') +
    labs(x = 'cut', y = 'Median')

Nhận xét: - Các thành phần:

  • Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Fair” (kém) đến “Ideal” (hoàn hảo).
  • Trục y: Thể hiện trọng lượng carat trung vị (m) được làm tròn đến 2 chữ số thập phân (round(m, 2)).
  • Cột màu vàng nhạt (“lightyellow”): Biểu thị trọng lượng carat trung vị cho mỗi chất lượng cắt.
  • Chú thích văn bản màu hồng (“pink”): Hiển thị trọng lượng carat trung vị chính xác (được làm tròn) nằm trên đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 2 để tránh chồng chéo lên các cột.
  • Tựa đề “Median”: Thể hiện trên trục y, cho biết giá trị được hiển thị là trung vị.
    • Ý nghĩa:

      Trung vị (median) là giá trị ở giữa của một tập dữ liệu đã được sắp xếp theo thứ tự. So với trung bình cộng (mean), trung vị ít bị ảnh hưởng bởi các giá trị ngoại lai (outliers) - những giá trị nằm rất xa so với phần còn lại của dữ liệu. Do đó, biểu đồ này giúp hiểu rõ hơn về trọng lượng carat điển hình của kim cương theo chất lượng cắt, ít bị ảnh hưởng bởi những viên kim cương có trọng lượng rất cao hoặc rất thấp.

Biểu đồ cột thể hiện trung vị trọng lượng carat theo màu sắc (color)

  • Biểu đồ này thể hiện trung vị của trọng lượng carat theo màu sắc (color) trong bộ dữ liệu g.
g %>% group_by(color) %>% summarise(m= median(carat)) %>%
  ggplot(aes(x = color,y = m)) +
    geom_col(position = 'dodge', fill= 'lightyellow') +
    geom_text(aes(label = round(m,3)), vjust = 2, color = 'pink') +
    labs(x = 'color', y = 'Median')

Nhận xét: Các thành phần:

  • Trục x: Thể hiện các màu sắc khác nhau của kim cương.
  • Trục y: Thể hiện trọng lượng carat trung vị (m) được làm tròn đến 2 chữ số thập phân (round(m, 2)).
  • Cột màu vàng nhạt (“lightyellow”): Biểu thị trọng lượng carat trung vị cho mỗi màu sắc.
  • Chú thích văn bản màu hồng (“pink”): Hiển thị trọng lượng carat trung vị chính xác (được làm tròn) nằm trên đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 2 để tránh chồng chéo lên các cột.
  • Tựa đề “Median”: Thể hiện trên trục y, cho biết giá trị được hiển thị là trung vị.
    • Ý nghĩa:
    Trung vị (median) là giá trị ở giữa của một tập dữ liệu đã được sắp xếp theo thứ tự. So với trung bình cộng (mean), trung vị ít bị ảnh hưởng bởi các giá trị ngoại lai (outliers) - những giá trị nằm rất xa so với phần còn lại của dữ liệu. Do đó, biểu đồ này giúp hiểu rõ hơn về trọng lượng carat điển hình của kim cương theo màu sắc, ít bị ảnh hưởng bởi những viên kim cương có trọng lượng rất cao hoặc rất thấp.

Biểu đồ cột thể hiện trung vị trọng lượng carat theo độ tinh khiết (clarity)

Biểu đồ này thể hiện trung vị của trọng lượng carat theo độ tinh khiết (clarity) của kim cương trong bộ dữ liệu g.

g %>% group_by(clarity) %>% summarise(m= median(carat)) %>%
  ggplot(aes(x = clarity,y = m)) +
    geom_col(position = 'dodge', fill= 'lightyellow') +
    geom_text(aes(label = round(m,2)), vjust = 2, color = 'pink') +
    labs(x = 'clarity', y = 'Median')

Nhận xét: - Các thành phần:

  • Trục x: Thể hiện các mức độ tinh khiết khác nhau của kim cương, thường được ký hiệu bằng chữ cái (ví dụ: IF, VVS1, VS1, SI1, v.v.).
  • Trục y: Thể hiện trọng lượng carat trung vị (m) được làm tròn đến 2 chữ số thập phân (round(m, 2)).
  • Cột màu vàng nhạt (“lightyellow”): Biểu thị trọng lượng carat trung vị cho mỗi mức độ tinh khiết.
  • Chú thích văn bản màu hồng (“pink”): Hiển thị trọng lượng carat trung vị chính xác (được làm tròn) nằm trên đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 2 để tránh chồng chéo lên các cột.
  • Tựa đề “Median”: Thể hiện trên trục y, cho biết giá trị được hiển thị là trung vị.

2.14 Biểu đồ cột thể hiện trung vị giá của kim cương theo các biến: cut, color, clarity

Biểu đồ cột thể hiện trung vị giá của kim cương theo chất lượng cắt (cut)

Biểu đồ này thể hiện trung vị của giá kim cương theo chất lượng cắt (cut) trong bộ dữ liệu gg.

g %>% group_by(cut) %>% summarise(m= median(price)) %>%
  ggplot(aes(x = cut,y = m)) +
    geom_col(position = 'dodge', fill= 'lightyellow') +
    geom_text(aes(label = round(m,2)), vjust = 2, color = 'pink') +
    labs(x = 'cut', y = 'Median')

Nhận xét: - Các thành phần:

  • Trục x: Thể hiện các chất lượng cắt khác nhau của kim cương, từ “Fair” (kém) đến “Ideal” (hoàn hảo).
  • Trục y: Thể hiện trọng lượng carat trung vị (m) được làm tròn đến 2 chữ số thập phân (round(m, 2)).
  • Cột màu vàng nhạt (“lightyellow”): Biểu thị trọng lượng carat trung vị cho mỗi chất lượng cắt.
  • Chú thích văn bản màu hồng (“pink”): Hiển thị giá kim cương trung vị chính xác (được làm tròn) nằm trên đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 2 để tránh chồng chéo lên các cột.
  • Tựa đề “Median”: Thể hiện trên trục y, cho biết giá trị được hiển thị là trung vị.

Biểu đồ cột thể hiện trung vị giá của kim cương theo màu sắc kim cương (color)

  • Biểu đồ này thể hiện trung vị của giá kim cương theo màu sắc (color) trong bộ dữ liệu g.
g %>% group_by(color) %>% summarise(m= median(price)) %>%
  ggplot(aes(x = color,y = m)) +
    geom_col(position = 'dodge', fill= 'lightyellow') +
    geom_text(aes(label = round(m,2)), vjust = 2, color = 'pink') +
    labs(x = 'color', y = 'Median')

Nhận xét: Các thành phần:

  • Trục x: Thể hiện các màu sắc khác nhau của kim cương.
  • Trục y: Thể hiện giá kim cương trung vị (m) được làm tròn đến 2 chữ số thập phân (round(m, 2)).
  • Cột màu nâu (“brown”): Biểu thị trọng lượng carat trung vị cho mỗi màu sắc.
  • Chú thích văn bản màu hồng (“pink”): Hiển thị trọng lượng carat trung vị chính xác (được làm tròn) nằm trên đỉnh mỗi cột, được điều chỉnh vị trí bằng vjust = 2 để tránh chồng chéo lên các cột.
  • Tựa đề “Median”: Thể hiện trên trục y, cho biết giá trị được hiển thị là trung vị.
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA0Ig0KYXV0aG9yOiAicHRxR2lhbyINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVIOiVNOiVTLCAlZCAtICVtICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBrYWJsZQ0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6ICcyJw0KICBwZGZfZG9jdW1lbnQ6DQogICAgbGF0ZXhfZW5naW5lOiB4ZWxhdGV4DQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KIyAqKkdp4bubaSB0aGnhu4d1IHThu5VuZyBxdcOhdCB24buBIGLhu5kgZOG7ryBsaeG7h3UgRGlhbW9uZHMqKg0KDQotIELhu5kgZOG7ryBsaeG7h3UgRGlhbW9uZHMgbMOgIGLhu5kgZOG7ryBsaeG7h3UgxJHDoyBjw7Mgc+G6tW4gdHJvbmcgUnN0dWRpbw0KLSBHw6FuIGLhu5kgZOG7ryBsaeG7h3UgZGlhbW9uZHMgdGjDoG5oICBnIA0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpnIDwtIGRpYW1vbmRzDQpgYGANCg0KLSBC4buZIGThu68gbGnhu4d1IERpYW1vbmRzIG7Ds2kgduG7gSB0aMO0bmcgc+G7kSBjw6FjIHTDrW5oIGNo4bqldCDEkeG6t2MgdMOtbmggY+G7p2Egbmjhu69uZyB2acOqbiBraW0gY8awxqFuZyB24bubaSBjw6FjIGvDrWNoIHRoxrDhu5tjIGtow6FjIG5oYXUsIGfhu5NtIDUzLjk0MCBiaeG6v24g4bupbmcgduG7m2kgNTMuOTQwIGvDrWNoIHRoxrDhu5tjIGtow6FjIG5oYXUgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcsIGPDsyAxMCBxdWFuIHPDoXQg4bupbmcgduG7m2kgMTAgxJHhurdjIHTDrW5oIGtow6FjIG5oYXUgbmjGsDoNCmBgYHtyfQ0KZGltKGcpDQpgYGANCg0KYGBge3J9DQpuYW1lcyhnKQ0KYGBgDQogIC0gKkNhcmF0Kjoga8OtY2ggdGjGsOG7m2MgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgDQogIC0gKkN1dCo6IGNo4bqldCBsxrDhu6NuZyBj4bqvdCAoa2jDoSwgdOG7kXQsIHLhuqV0IHThu5F0LCDEkeG6t2MgYmnhu4d0LCBsw70gdMaw4bufbmcpDQogIC0gKkNvbG9yKjogbcOgdSBz4bqvYyAoSiAtIGvDqW0gbmjhuqV0LCBEIC0gdOG7kXQgbmjhuqV0KQ0KICAtICpDbGFyaXR5KjogxJHhu5kgdHJvbmcgc3Xhu5F0ICh04burIElGICh04buRdCBuaOG6pXQpIMSR4bq/biBJMSAoa8OpbSBuaOG6pXQpKQ0KICAtICpEZXB0aCo6IFThu7cgbOG7hyBwaOG6p24gdHLEg20gxJHhu5kgc8OidSAodMOtbmggdGhlbyB6IC8geCkNCiAgLSAqVGFibGUqOiBDaGnhu4F1IHLhu5luZyBj4bunYSBt4bq3dCBiw6BuICh0w61uaCB0aGVvICUgY+G7p2EgxJHGsOG7nW5nIGvDrW5oKQ0KICAtICpQcmljZSo6IEdpw6EgKFVTRCkNCiAgLSAqWCo6IENoaeG7gXUgZMOgaSBj4bunYSB2acOqbiBraW0gY8awxqFuZyAobW0pDQogIC0gKlkqOiBDaGnhu4F1IHLhu5luZyBj4bunYSB2acOqbiBraW0gY8awxqFuZyAobW0pDQogIC0gKloqOiDEkOG7mSBzw6J1IGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nIChtbSkNCiAgDQojICoqVuG6vSBiaeG7g3UgxJHhu5MqKg0KDQojIyAqKkJp4buDdSDEkeG7kyBj4bunYSBk4buvIGxp4buHdSBjdXQqKg0KDQotIEN1dDogbMOgIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBj4bunYSBt4bq3dCBraW0gY8awxqFuZywgY8OzIDUgbG/huqFpIGNo4bqldCBsxrDhu6NuZyBraMOhYyBuaGF1IHTDuXkgdsOgbyBt4bq3dCBj4bqvdCBtw6AgcGjDom4gYuG7lSB0aMOgbmggNiBsb+G6oWk6DQogIC0gSWRlYWw6IGzDvSB0xrDhu59uZw0KICAtIFByZWRpdW06IHR1eeG7h3QgaOG6o28gDQogIC0gVmVyeSBnb29kOiBy4bqldCB04buRdCANCiAgLSBHb29kOiB04buRdA0KICAtIEZhaXI6IGvDqW0gDQogIA0KKioqVuG6vSBiaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGNo4bqldCBsxrDhu6NuZyBj4bunYSBt4bq3dCBj4bqvdCBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nKioqDQoNCi0gQmnhu4N1IMSR4buTIGJp4buDdSB0aOG7iyBz4buRIGzGsOG7o25nIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyBt4bq3dCBj4bqvdCAoa2jDtG5nIGPDsyBz4buRIGzGsOG7o25nIGPhu6UgdGjhu4MpDQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmcgJT4lIGdncGxvdChhZXMoeCA9IGN1dCkpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBsYWJzKHRpdGxlID0gIkjDrG5oIGN1dDE6IEJp4buDdSDEkeG7kyBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gbeG6t3QgY+G6r3QiLHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQogICpOaOG6rW4geMOpdDoqDQogIC0gVOG7qyBr4bq/dCBxdeG6oyB0csOqbiB0YSB0aOG6pXkgxJHGsOG7o2Mgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgY2jhuqV0IGzGsOG7o25nIG3hurd0IGPhuq90IGlkZWFsKGzDvSB0xrDhu59uZykgY2hp4bq/bSDEkWEgc+G7kSB2w6Agc+G7kSBsxrDhu6NuZyB2acOqbiBraW0gY8awxqFuZyBjw7MgY2jhuqV0IGzGsOG7o25nIGZhaXIoa8OpbSkgbMOgIHRo4bqlcCBuaOG6pXQuDQoNCi0gQmnhu4N1IMSR4buTIGJp4buDdSB0aOG7iyBz4buRIGzGsOG7o25nIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyBt4bq3dCBj4bqvdCAoY8OzIHPhu5EgbMaw4bujbmcgY+G7pSB0aOG7gykNCmBgYHtyfQ0KZyAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3BpbmsnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnYnJvd24nKSArDQogICAgbGFicyh0aXRsZSAgPSAiSMOsbmggMTogQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBjaGkgdGnhur90IHPhu5EgbMaw4bujbmcgY8OhYyB2acOqbiBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBt4bq3dCBj4bqvdCIseCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiAgKipHaeG6o2kgdGjDrWNoKioNCiAgLSBU4burIGvhur90IHF14bqjIHRhIHRodSDEkcaw4bujYyBjw7MgMS42MTAgdmnDqm4ga2ltIGPGsMahbmcgY8OzIGNo4bqldCBsxrDhu6NuZyBt4bq3dCBj4bqvdCBrw6ltLCA0LjkwNiB2acOqbiBraW0gY8awxqFuZyBjw7MgY2jhuqV0IGzGsOG7o25nIG3hurd0IGPhuq90IHThu5F0LCBjw7MgMTIuMDgyIHZpw6puIGtpbSBjxrDGoW5nIGPDsyBjaOG6pXQgbMaw4bujbmcgbeG6t3QgY+G6r3QgcuG6pXQgdOG7kXQsIGPDsyAxMy43OTEgdmnDqm4ga2ltIGPGsMahbmcgY8OzIGNo4bqldCBsxrDhu6NuZyBt4bq3dCBj4bqvdCB0dXnhu4d0IGjhuqNvIHbDoCAyMS41NTEgdmnDqm4ga2ltIGPGsMahbmcgY8OzIGNo4bqldCBsxrDhu6NuZyBt4bq3dCBj4bqvdCBsw70gdMaw4bufbmcuDQogIC0gVuG6rXkgc+G7kSB2acOqbiBraW0gY8awxqFuZyBjw7MgY2jhuqV0IGzGsOG7o25nIG3hurd0IGPhuq90IGlkZWFsIGfhuqVwIDEzIGzhuqduIGxv4bqhaSBmYWlyIChjaGnhur9tIDEvMiBz4buRIGzGsOG7o25nIHZpw6puIGtpbSBjxrDGoW5nKQ0KDQotIMSQ4buDIGThu4UgZMOgbmcgdMOtbmggdG/DoW4gdsOgIGjDrG5oIGR1bmcgdGEgY8OzIHRo4buDIGNodXnhu4NuIGJp4buDdSDEkeG7kyBuaMawIHRyw6puIHNhbmcgZOG6oW5nICUuDQpgYGB7cn0NCiMgTG9hZCB0aGUgc2NhbGVzIHBhY2thZ2UNCmxpYnJhcnkoc2NhbGVzKQ0KDQojIERlZmluZSBhIGN1c3RvbSBwZXJjZW50IGZ1bmN0aW9uDQpwZXJjZW50IDwtIGZ1bmN0aW9uKHgpIHsNCiAgcGFzdGUwKGZvcm1hdEMoeCAqIDEwMCwgZm9ybWF0ID0gImYiLCBkaWdpdHMgPSAxKSwgIiUiKQ0KfQ0KDQojIFVzZSB0aGUgcGVyY2VudCBmdW5jdGlvbg0KcmVzdWx0IDwtIHBlcmNlbnQoMC43NSkNCnByaW50KHJlc3VsdCkNCg0KZyAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2dyYXknKSArDQogICAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBt4bq3dCBj4bqvdCBkxrDhu5tpIGThuqFuZyBwaOG6p24gdHLEg20gIikgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgoZyRjdXQpKSksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgbGFicyh4ID0gJ1RoYW5nIMSRbyBDdXQnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiAgKkdp4bqjaSB0aMOtY2g6Kg0KICAtIE5ow6xuIHbDoG8gYmnhu4N1IMSR4buTIHRhIHRo4bqleSBuZ2F5IHBo4bqnbiB0csSDbSBz4buRIGtpbSBjxrDGoW5nIGxv4bqhaSBpZGVhbCB0csOqbiB04buVbmcgdGjhu4MgbMOgIDQwJSwgdHJvbmcga2hpIMSRw7MgbG/huqFpIGZhaXIgY2jhu4kgY2hp4bq/bSAzJSB0csOqbiB04buVbmcgdGjhu4MgdOG7qWMgbMOgIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgc+G6vSBjw7MgY2jhuqV0IGzGsOG7o25nIGLhu4EgbeG6t3QgY+G6r3QgY2FvIG7Dqm4gdOG7qyDEkcOzIHPhur0gxJHGsOG7o2MgbOG7sWEgY2jhu41uIG5oaeG7gXUgdsOgIGLDoW4gxJHGsOG7o2MgZOG7hSBkw6BuZyBoxqFuLg0KDQojIyAqKkJp4buDdSDEkeG7kyBj4bunYSBk4buvIGxp4buHdSBjb2xvcioqDQoNCioqKlbhur0gYmnhu4N1IMSR4buTIHRoZW8gbcOgdSBz4bqvYyBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nKioqDQoNCi0gVOG7lW5nIHF1YW4gduG7gSBtw6B1IHPhuq9jIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgY8OzIDcgbcOgdSB04burIEQgxJHhur9uIEogdMawxqFuZyDhu6luZyB24bubaSAyIGPhuqVwIMSR4buZIGzDoCBraMO0bmcgbcOgdSAoRCxFLEYpIHbDoCBn4bqnbiBuaMawIGtow7RuZyBtw6B1IChHLEgsSSxKKS4NCmBgYHtyfQ0KdGFibGUgKGckY29sb3IpDQpgYGANCg0KLSBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jIA0KDQpgYGB7cn0NCmcgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAnbcOgdSBz4bqvYycsIHkgPSAnc+G7kSBsxrDhu6NuZycsZmlsbCA9IGNvbG9yKSkgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSxwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMSkpDQpgYGANCg0KICAqTmjhuq1uIHjDqXQ6Kg0KICAtIEPhuqVwIMSR4buZIGtow7RuZyBtw6B1IGPDsyB04buVbmcgc+G7kSBraW0gY8awxqFuZyBsw6AgNi43NzUgY8OzIG3DoHUgRCwgOS43OTcgY8OzIG3DoHUgbG/huqFpIEUsIDkuNTQyIGPDsyBtw6B1IGxv4bqhaSBGDQogIC0gQ+G6pXAgxJHhu5kgZ+G6p24gbmjGsCBraMO0bmcgbcOgdSBjw7MgdOG7lW5nIHPhu5Ega2ltIGPGsMahbmcgbMOgIDExLjI5MiBjw7MgbcOgdSBHLCA4LjMwNCBjw7MgbcOgdSBsb+G6oWkgSCwgNS40MjIgY8OzIG3DoHUgbG/huqFpIEksIDIuODA4IGPDsyBtw6B1IGxv4bqhaSBKLg0KICANCi0gQmnhu4N1IMSR4buTIG7hurFtIG5nYW5nIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIHZpw6puIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYyANCmBgYHtyfQ0KZyAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMobixjb2xvcikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdibHVlJykgKw0KICAgIGxhYnModGl0bGUgPSAiIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gbmjDs20gdGhlbyBDb2xvciAobcOgdSBz4bqvYykgIikgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDEsIGNvbG9yID0gJ3llbGxvdycpICsNCiAgICBsYWJzKHggPSAnU+G7kSBsxrDhu6NuZycsIHkgPSAnQ8OhYyBtw6B1IHPhuq9jJykNCmBgYA0KICAqTmjhuq1uIHjDqXQ6Kg0KICAtIE5oxrAgdGEgdGjhuqV5IG3DoHUgRyBjaGnhur9tIMSRYSBz4buRIHRyb25nIHThuqV0IGPhuqMgY8OhYyBtw6B1IGzDoCBtw6B1IHBo4buVIGJp4bq/biB0cm9uZyB04buVbmcgc+G7kSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIGzDqm4gxJHhur9uIDExLjI5MiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEcgDQogIC0gTmfGsOG7o2MgbOG6oWkgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBtw6B1IEogY2jhu4kgY2hp4bq/bSBz4buRIMOtdCB0cm9uZyB04buVbmcgc+G7kSBraW0gY8awxqFuZyBsw6AgMi44MDggdmnDqm4gDQogIC0gVOG7qyDEkcOzIGPDsyB0aOG7gyB0aOG6pXkgc+G7kSBsxrDhu6NuZyB2acOqbiBraW0gY8awxqFuZyBtw6B1IEcgZ+G6pXAgNSBs4bqnbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEogDQogIC0gWMOpdCB0aGVvIGPhuqVwIMSR4buZIHRow6wgdOG7lW5nIHPhu5Ega2ltIGPGsMahbmcg4bufIGPhuqVwIGtow7RuZyBtw6B1IGNoaeG6v20gbeG7mXQgbMaw4bujbmcgw610IGjGoW4gduG7m2kgY+G6pXAgZ+G6p24gbmjGsCBraMO0bmcgbcOgdSANCiAgDQotIEThu7FhIHbDoG8gxJHhu5MgdGjhu4sgdHLDqm4gdGEgY2h1eeG7g24gc2FuZyBk4bqhbmcgJSDEkeG7gyBjw7MgdGjhu4MgZOG7hSBow6xuaCBkdW5nIHbDoCBwaMOibiB0w61jaA0KYGBge3J9DQpnICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhuLGNvbG9yKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2dyYXknKSArDQogICAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duICUgdGhlbyBDb2xvciAobcOgdSBz4bqvYykgIikgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgoZyRjb2xvcikpKSx2anVzdCA9IDEsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICdT4buRIGzGsOG7o25nJywgeSA9ICdtw6B1IHPhuq9jJykNCmBgYA0KDQoqTmjhuq1uIHjDqXQ6Kg0KLSBDxaluZyB0xrDGoW5nIHThu7EgbmjGsCBuaOG6rW4geOG6v3Qg4bufIHRyw6puDQotIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gJSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPhu6dhIGPDoWMgbcOgdSwgY8OzIDIwLjkzJSB0csOqbiB04buVbmcgc+G7kSBraW0gY8awxqFuZyBjw7MgbcOgdSBHLCBjw7MgMTguMTYlIHRyw6puIHThu5VuZyBz4buRIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEUsIGPDsyAxNy45NiUgdHLDqm4gdOG7lW5nIHPhu5Ega2ltIGPGsMahbmcgY8OzIG3DoHUgRiwgY8OzIDE1LjM5JSB0csOqbiB04buVbmcgc+G7kSBraW0gY8awxqFuZyBjw7MgbcOgdSBILCBjw7MgMTIuNTYlIHRyw6puIHThu5VuZyBz4buRIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEQsIGPDsyAxMC4wNSUgdHLDqm4gdOG7lW5nIHPhu5Ega2ltIGPGsMahbmcgY8OzIG3DoHUgSSwgY8OzIDUuMjElIHRyw6puIHThu5VuZyBz4buRIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEouDQoNCiMjICoqQmnhu4N1IMSR4buTIGPhu6dhIGThu68gbGnhu4d1IGNsYXJpdHkqKg0KDQotIMSQ4buZIHRpbmgga2hp4bq/dC8gxJDhu5kgdHJvbmcgY+G7p2Ega2ltIGPGsMahbmcgbMOgIHPhu5EgbMaw4bujbmcgdsOgIGto4bqjIG7Eg25nIGhp4buDbiB0aOG7iyBj4bunYSBjw6FjIMSR4bq3YyDEkWnhu4NtIGLDqm4gdHJvbmcgKHThuqFwIGNo4bqldCkgdsOgIGLDqm4gbmdvw6BpKHbhur90IHRy4bqneSB4xrDhu5tjKSBj4bunYSBt4buZdCB2acOqbiBraW0gY8awxqFuZy4NCi0gY8OzIDggY+G6pXAgxJHhu5kgdGluaCBraGnhur90IHRyb25nIGLhu5kgZOG7ryBsaeG7h3UsIGfhu5NtOg0KICAtIEludGVybmFsbHkgRmxhd2xlc3MgLSBJRiA6IEhvw6BuIGjhuqNvIGLDqm4gdHJvbmcsIGNo4buJIGPDsyB04buzIHbhur90IGtow7RuZyBxdWFuIHRy4buNbmcgYsOqbiBuZ2/DoGkNCiAgLSBWZXJ5IFZlcnkgU2xpZ2h0bHkgSW5jbHVkZWQgLSBWVlMgLSBn4buTbSAyIGPhuqVwIG5o4buPIChWVlMxLCBWVlMyKSA6IEPDsyBuaOG7r25nIHThuqFwIGNo4bqldCwgduG6v3QgdHLhuqd5IG5o4buPLCBraMOzIHRo4bqleSDEkcaw4bujYw0KICAtIFZlcnkgU2xpZ2h0bHkgSW5jbHVkZWQgLSBWUyAtIGPDsyAyIGPhuqVwIG5o4buPIChWUzEsIFZTMikgOiBDw7Mgbmjhu69uZyB04bqhcCBjaOG6pXQsIHbhur90IHRy4bqneSB04burIGtow7MgdGjhuqV5IMSR4bq/biBk4buFIHRo4bqleQ0KICAtIFNsaWdodGx5IEluY2x1ZGVkIC0gU0kgLSBjw7MgMiBj4bqlcCBuaOG7jyAoU0kxLCBTSTIpIDogQ8OzIG5o4buvbmcgdOG6oXAgY2jhuqV0LCB24bq/dCB0cuG6p3kgZOG7hSB0aOG6pXkgaG/hurdjIHLhuqV0IGThu4UgdGjhuqV5DQogIC0gSW5jbHVkZWQgLSBJIC0gY8OzIDMgY+G6pXAgbmjhu48gKEkxLEkyLEkzKSA6IEtow7RuZyBob8OgbiBo4bqjbyBs4bqrbiBiw6puIHRyb25nIGzhuqtuIGLDqm4gbmdvw6BpDQoNCioqKlbhur0gYmnhu4N1IMSR4buTIHRoZW8gxJHhu5kgdGluaCBraGnhur90IChjbGFyaXR5KSBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nKioqDQoNCi0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIHRoZW8gY2xhcml0eQ0KDQpgYGB7cn0NCmcgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY2xhcml0eSxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2xpZ2h0Ymx1ZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdicm93bicpICsNCiAgICBsYWJzKHRpdGxlID0iSMOsbmggNDogQmnhu4N1IMSR4buTIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjbGFyaXR5ICjEkeG7mSB0aW5oIGtoaeG6v3QpIix4ID0gJ8SR4buZIHRpbmgga2hp4bq/dCAnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogICpOaOG6rW4geMOpdDoqDQogIC0gTG/huqFpIFNJMSBjw7Mgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjYW8gbmjhuqV0ICgxMzA2NSkNCiAgLSBMb+G6oWkgSTEgY8OzIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGjhuqVwIG5o4bqldCAoNzQxKQ0KICAtIFPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY8OzIMSR4buZIHRpbmgga2hp4bq/dCBJMShCYW8gdGjhu4MgaGnhu4duIHRo4buLKTogNzQxDQogIC0gU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgxJHhu5kgdGluaCBraGnhur90IFNJMi9TSTEoQmFvIHRo4buDIG5o4buPKTogOTE5NC8xMzYwNQ0KICAtIFPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY8OzIMSR4buZIHRpbmgga2hp4bq/dCBWUzIvVlMxKEJhbyB0aOG7gyBuaOG7jyBj4bqlcCAyLyBj4bqlcCAxKToxMjI1OC84MTcxDQogIC0gU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgxJHhu5kgdGluaCBraGnhur90IFZWUzIvVlZTMShLaHV54bq/dCB04bqtdCBy4bqldCBuaOG7jyk6NTA2Ni8zNjU1DQogIC0gU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgxJHhu5kgdGluaCBraGnhur90IElGKEhvw6BuIHRvw6BuIHRpbmgga2hp4bq/dCk6IDE3OTANCiAgDQotIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gcGjhuqduIHRyxINtIHRoZW8gY2xhcml0eQ0KIC0gROG7sWEgdsOgbyBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgduG6vSB0aMOqbSBiaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGTGsOG7m2kgZOG6oW5nIHBo4bqnbiB0csSDbQ0KYGBge3J9DQpnICU+JSBncm91cF9ieShjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGNsYXJpdHksIG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0ncHVycGxlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKGckY2xhcml0eSkpKSx2anVzdCA9IDEsIGNvbG9yID0gJ2JsYWNrJykrDQogICAgbGFicyh0aXRsZSA9IkjDrG5oIDQ6IEJp4buDdSDEkeG7kyBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gY2xhcml0eSAoxJHhu5kgdGluaCBraGnhur90KSIseCA9ICdT4buRIGzGsOG7o25nJywgeSA9ICfEkOG7mSB0aW5oIGtoaeG6v3QnKQ0KYGBgDQogICpOaOG6rW4geMOpdDoqDQogIC0gVMawxqFuZyB04buxIHbhu5tpIGJp4buDdSDEkeG7kyB0csOqbiBuaMawbmcgdGhheSBi4bqxbmcgJSwgduG7m2kgcGjhuqduIHRyxINtIGzDoCAyNCwyJSAtIG3hu6ljIFNJMSBjw7MgdOG7tyBs4buHIGNoaeG6v20gY2FvIG5o4bqldA0KICAtIEPDoWMgdOG7tyBs4buHIMSR4bupbmcgdGjhu6kgMiwzLDQgbOG6p24gbMaw4bujdCBsw6AgVlMyIDIyLDclIC0gU0kyIDE3JSAtIFZTMSAxNSwxJQ0KICAtIFThu7cgbOG7hyBj4bunYSAzIG3hu6ljIMSR4buZIG7DoHkgY8OhY2ggbeG7qWMgxJHhu5kgxJHhu6luZyDEkeG6p3Uga2hv4bqjbmcgMiAtIDEwJQ0KICAtIFThu6sgxJHDsyB0YSB0aOG6pXkgxJHGsOG7o2MsIGtow7RuZyBjw7MgbeG7qWMgxJHhu5kgbsOgbyBsw6AgY8OzIHPhu5EgbMaw4bujbmcgY2FvIGjGoW4gaOG6s24vIHLDtSBy4buHdCBoxqFuIGPDoWMgbeG7qWMgY8OybiBs4bqhaQ0KICAtIE3hu6ljIFZWUzIgdsOgIFZWUzEgxJHhu6luZyBn4bqnbiDDoXAgY2jDs3QgY+G7p2EgYmnhu4N1IMSR4buTIHbhu5tpIHThu7cgbOG7hyDDrXQgaMahbiA6IDksNCUgdsOgIDYsOCUNCiAgLSBWw6AgY3Xhu5FpIGPDuW5nLCBt4bupYyBjw7MgdOG7tyBs4buHIMOtdCBuaOG6pXQgdHJvbmcgYuG6o25nIGzhuqduIGzGsOG7o3QgbMOgIElGIC0gMywzJSB2w6AgSTEgLSAxLDElDQogIC0gS2hv4bqjbmcgY8OhY2ggY+G7p2EgMiBt4bupYyBuaGnhu4F1IHbDoCDDrXQgbmjhuqV0IGzDoCBraG/huqNuZyBoxqFuIDIyJQ0KDQojIyAqKkJp4buDdSDEkeG7kyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGThu68gbGnhu4d1IGRlcHRoKioNCg0KLSB24bq9IGJp4buDdSDEkeG7kyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGRlcHRoIHRoZW8gY3V0IHbDoCBjbGFyaXR5DQoNCmBgYHtyfQ0KZyAlPiUgZ3JvdXBfYnkoY3V0LCBjbGFyaXR5KSU+JXN1bW1hcmlzZShtPW1lYW4oZGVwdGgpKSU+JWdncGxvdChhZXMoeD1jdXQsIHk9IG0pKSsNCiAgZ2VvbV9jb2wocG9zaXRpb249J2RvZGdlJykrDQogIGZhY2V0X3dyYXAofmNsYXJpdHkpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPSByb3VuZChtKSksIHZqdXN0PTIsIGNvbG9yPSdncmF5JykrIA0KICBsYWJzKHg9ICdMb+G6oWknLCB5PSAnxJDhu5kgc8OidSB0cnVuZyBiw6xuaCcsdGl0bGU9J0jDrG5oIDI6IEdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgZGVwdGggdGhlbyBjdXQgdsOgIGNsYXJpdHkgJykNCmBgYA0KICAqTmjhuq1uIHjDqXQ6Kg0KICAtIGdyb3VwX2J5KGN1dCwgY2xhcml0eSkgOiBOaMOzbSBk4buvIGxp4buHdSB0aGVvIGPhu5l0IOKAnGN1dOKAnSB2w6Ag4oCcY2xhcml0eeKAnS4NCiAgLSBzdW1tYXJpc2UobSA9IG1lYW4oZGVwdGgpKSA6IFTDrW5oIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgY+G7mXQg4oCcZGVwdGjigJ0gdHJvbmcgbeG7l2kgbmjDs20gdsOgIHThuqFvIG3hu5l0IGPhu5l0IG3hu5tpIGPDsyB0w6puIOKAnG3igJ0gxJHhu4MgbMawdSBnacOhIHRy4buLIHRydW5nIGLDrG5oLg0KICAtIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG0pKSA6IFThuqFvIG3hu5l0IMSR4buRaSB0xrDhu6NuZyBnZ3Bsb3QgduG7m2kgdHLhu6VjIHggbMOgIOKAnGN1dOKAnSB2w6AgdHLhu6VjIHkgbMOgIOKAnG3igJ0uDQogIC0gZ2VvbV9jb2wocG9zaXRpb24gPSDigJhkb2RnZeKAmSkgOiBW4bq9IGJp4buDdSDEkeG7kyBj4buZdCBz4butIGThu6VuZyBow6xuaCBk4bqhbmcgbeG6t2MgxJHhu4tuaCB2w6Agc+G7rSBk4bulbmcgcGjGsMahbmcgcGjDoXAg4oCcZG9kZ2XigJ0gxJHhu4MgeOG6v3AgY2jhu5NuZyBjw6FjIGPhu5l0IGPhu6dhIGPDoWMgbmjDs20uDQogIC0gZmFjZXRfd3JhcCh+Y2xhcml0eSkgOiBDaGlhIGJp4buDdSDEkeG7kyB0aMOgbmggY8OhYyBwYW5lbCByacOqbmcgYmnhu4d0IGThu7FhIHRyw6puIGPhu5l0IOKAnGNsYXJpdHnigJ0uDQogIC0gZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0pKSwgdmp1c3QgPSAyLCBjb2xvciA9IOKAmHJlZOKAmSk6IFRow6ptIG5ow6NuIGThu68gbGnhu4d1IHRyw6puIG3hu5dpIGPhu5l0LCB24bubaSBnacOhIHRy4buLIMSRxrDhu6NjIGzDoG0gdHLDsm4gdsOgIG3DoHUgY2jhu68gxJHhu48uIFRoYW0gc+G7kSB2anVzdCA9IDIgbMOgbSB0xINuZyBraG/huqNuZyBjw6FjaCBnaeG7r2EgY+G7mXQgdsOgIG5ow6NuLg0KICAtIMSQ4buZIHPDonUgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBsb+G6oWkga2ltIGPGsMahbmcg4bufIGPDoWMgbeG7qWMgxJHhu5kgdGluaCBraGnhur90IGtow7RuZyBjw7Mgc+G7sSBjaMOqbmggbOG7h2NoIG5oaeG7gXUsIMSR4buBdSBkYW8gxJHhu5luZyDhu58gY8OhYyBt4bupYyDEkeG7mSA2MCw2MSw2Miw2Myw2NC4NCiAgDQoNCi0gduG6vSBiaeG7g3UgxJHhu5MgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBkZXB0aCB0aGVvIGN1dCB2w6AgY29sb3INCg0KYGBge3J9DQpnICU+JSBncm91cF9ieShjdXQsY29sb3IpICU+JSBzdW1tYXJpc2UobSA9IG1lYW4oZGVwdGgpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmNvbG9yKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbD0gcm91bmQobSkpLCB2anVzdD0yLCBjb2xvcj0nZ3JheScpKyANCiAgbGFicyh4PSAnTG/huqFpJywgeT0gJ8SQ4buZIHPDonUgdHJ1bmcgYsOsbmgnLHRpdGxlPSdIw6xuaCAyMzogR2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBkZXB0aCB0aGVvIGN1dCB2w6AgY29sb3IgJykNCmBgYA0KICAqTmjhuq1uIHjDqXQ6Kg0KICAtIMSQ4buZIHPDonUgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBsb+G6oWkga2ltIGPGsMahbmcg4bufIGPDoWMgbcOgdSBz4bqvYyBraMOhYyBuaGF1IGtow7RuZyBjw7Mgc+G7sSBjaMOqbmggbOG7h2NoIG5oaeG7gXUsIMSR4buBdSBkYW8gxJHhu5luZyDhu58gY8OhYyBt4bupYyDEkeG7mSA2MCw2MSw2Miw2Myw2NC4NCiAgDQojIyAqQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBnacOhIHRy4buLIHRydW5nIGLDrG5oIGdpw6EgYsOhbiB0aGVvIGJp4bq/bjogY3V0LCBjb2xvciB2w6AgY2xhcml0eSogDQoNCioqKlbhur0gYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBnacOhIHRy4buLIHRydW5nIGLDrG5oIGdpw6EgYsOhbiB0aGVvIG3DoHUgc+G6r2Mga2ltIGPGsMahbmcqKioNCg0KLSBCaeG7g3UgxJHhu5MgbsOgeSB0aOG7gyBoaeG7h24gZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBnacOhIGLDoW4gdGhlbyB04burbmcgbcOgdSBz4bqvYyBj4bunYSBraW0gY8awxqFuZyB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLg0KDQpgYGB7cn0NCmcgPC0gZGlhbW9uZHMNCmcgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKGs9IG1lYW4ocHJpY2UpKSAlPiUNCiAgZ2dwbG90KGFlcyhjb2xvcixrKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3NreWJsdWUnKSArIA0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChrLDIpKSx2anVzdCA9IDEsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICdNw6B1JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqTmjhuq1uIHjDqXQ6Kg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBtw6B1IHPhuq9jIGtow6FjIG5oYXUgY+G7p2Ega2ltIGPGsMahbmcuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiBnacOhIHRy4buLIHRydW5nIGLDrG5oIChrKSBnacOhIGLDoW4sIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gICAgc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKGssIDIpKSwgY+G7p2Ega2ltIGPGsMahbmcgdGh14buZYyBt4buXaSBtw6B1IHPhuq9jLg0KICAtIEPhu5l0IG3DoHUgeGFuaCBuaOG6oXQgKCJza3libHVlIik6IENoaeG7gXUgY2FvIGPhu6dhIG3hu5dpIGPhu5l0IHThu7cgbOG7hyB0aHXhuq1uIHbhu5tpIGdpw6EgICAgdHLhu4sgdHJ1bmcgYsOsbmggZ2nDoSBiw6FuIGPhu6dhIGtpbSBjxrDGoW5nIGPDsyBtw6B1IHPhuq9jIHTGsMahbmcg4bupbmcuDQogIC0gQ2jDuiB0aMOtY2ggdsSDbiBi4bqjbiBtw6B1IMSRZW4gKCJibGFjayIpOiBIaeG7g24gdGjhu4sgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBjaMOtbmggeMOhYyAgKMSRxrDhu6NjIGzDoG0gdHLDsm4pIG7hurFtIHRyw6puIMSR4buJbmggbeG7l2kgY+G7mXQuDQotIFbDrSBk4bulIGPhu6UgdGjhu4M6DQoNCiAgLSBNw6B1IEogY2FvIG5o4bqldCB0cm9uZyBiaeG7g3UgxJHhu5MuIMSQaeG7gXUgbsOgeSBjw7MgbmdoxKlhIGzDoCBraW0gY8awxqFuZyBtw6B1IEogY8OzIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggZ2nDoSBiw6FuIGNhbyBuaOG6pXQgdHJvbmcgc+G7kSBjw6FjIG3DoHUgc+G6r2MuIFbDrSBk4bulLCBjaMO6IHRow61jaCB0csOqbiBj4buZdCBtw6B1IEogY8OzIHRo4buDIGhp4buDbiB0aOG7iyBnacOhIHRy4buLIDUzMjMsODIgVVNELCBjaG8gYmnhur90IGtpbSBjxrDGoW5nIG3DoHUgSiB0cnVuZyBiw6xuaCBjw7MgZ2nDoSBiw6FuIDUzMjMsODIgVVNELg0KDQogIC0gTcOgdSBFIHRo4bqlcCBuaOG6pXQgdHJvbmcgYmnhu4N1IMSR4buTLiDEkGnhu4F1IG7DoHkgY8OzIG5naMSpYSBsw6Aga2ltIGPGsMahbmcgbcOgdSBFIGPDsyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGdpw6EgYsOhbiB0aOG6pXAgbmjhuqV0IHRyb25nIHPhu5EgY8OhYyBtw6B1IHPhuq9jLiBWw60gZOG7pSwgY2jDuiB0aMOtY2ggdHLDqm4gY+G7mXQgbcOgdSBNIGPDsyB0aOG7gyBoaeG7g24gdGjhu4sgZ2nDoSB0cuG7iyAzMDc2LDc1IFVTRCwgY2hvIGJp4bq/dCBraW0gY8awxqFuZyBtw6B1IE0gdHJ1bmcgYsOsbmggY8OzIGdpw6EgYsOhbiAzMDc2LDc1IFVTRC4NCg0KKioqVuG6vSBiaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggZ2nDoSBiw6FuIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90KioqDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgZ2nDoSBiw6FuIHRoZW8gdOG7q25nIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLg0KYGBge3J9DQpnIDwtIGRpYW1vbmRzDQpnICU+JSBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2Uoaz0gbWVhbihwcmljZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxrKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2xpZ2h0eWVsbG93JykgKyANCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoaywyKSksdmp1c3QgPSAxLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnQ2jhuqV0IGzGsOG7o25nIGPhuq90JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KICAqTmjhuq1uIHjDqXQ6Kg0KIC0gVHLhu6VjIHg6IFRo4buDIGhp4buHbiBjw6FjIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBraMOhYyBuaGF1IGPhu6dhIGtpbSBjxrDGoW5nLCB04burICJQb29yIiAoa8OpbSkgxJHhur9uICJJZGVhbCIgKGhvw6BuIGjhuqNvKS4NCiAgLSBUcuG7pWMgeTogVGjhu4MgaGnhu4duIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggKGspIGdpw6EgYsOhbiwgxJHGsOG7o2MgbMOgbSB0csOybiDEkeG6v24gMiBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiAocm91bmQoaywgMikpLCBj4bunYSBraW0gY8awxqFuZyB0aHXhu5ljIG3hu5dpIGNo4bqldCBsxrDhu6NuZyBj4bqvdC4NCiAgLSBD4buZdCBtw6B1IHhhbmggbmjhuqF0ICgic2t5Ymx1ZSIpOiBDaGnhu4F1IGNhbyBj4bunYSBt4buXaSBj4buZdCB04bu3IGzhu4cgdGh14bqtbiB24bubaSBnacOhIHRy4buLIHRydW5nIGLDrG5oIGdpw6EgYsOhbiBj4bunYSBraW0gY8awxqFuZyBjw7MgY2jhuqV0IGzGsOG7o25nIGPhuq90IHTGsMahbmcg4bupbmcuDQogIC0gQ2jDuiB0aMOtY2ggdsSDbiBi4bqjbiBtw6B1IMSRZW4gKCJibGFjayIpOiBIaeG7g24gdGjhu4sgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBjaMOtbmggeMOhYyAoxJHGsOG7o2MgbMOgbSB0csOybikgbuG6sW0gdHLDqm4gxJHhu4luaCBt4buXaSBj4buZdC4NCiAgDQoqKipCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggZ2nDoSBiw6FuIHRoZW8gxJHhu5kgdHJvbmcgc3Xhu5F0KioqDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgZ2nDoSBiw6FuIHRoZW8gdOG7q25nIMSR4buZIHRyb25nIHN14buRdCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLg0KYGBge3J9DQpnIDwtIGRpYW1vbmRzDQpnICU+JSBncm91cF9ieShjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKGs9IG1lYW4ocHJpY2UpKSAlPiUNCiAgZ2dwbG90KGFlcyhjbGFyaXR5LGspKSArDQogICAgZ2VvbV9jb2woZmlsbD0nbGlnaHR5ZWxsb3cnKSArIA0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChrLDIpKSx2anVzdCA9IDEsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICfEkOG7mSB0cm9uZyBzdeG7kXQnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoqTmjhuq1uIHjDqXQ6Kg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyDEkeG7mSB0cm9uZyBzdeG7kXQga2jDoWMgbmhhdSBj4bunYSBraW0gY8awxqFuZywgdOG7qyAiSTEiIChrw6ltIHRyb25nKSDEkeG6v24gIklGIiAoaG/DoG4gaOG6o28ga2jDtG5nIHTDrCB24bq/dCkuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiBnacOhIHRy4buLIHRydW5nIGLDrG5oIChrKSBnacOhIGLDoW4sIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKGssIDIpKSwgY+G7p2Ega2ltIGPGsMahbmcgdGh14buZYyBt4buXaSDEkeG7mSB0cm9uZyBzdeG7kXQuDQogIC0gQ+G7mXQgbcOgdSB4YW5oIG5o4bqhdCAoInNreWJsdWUiKTogQ2hp4buBdSBjYW8gY+G7p2EgbeG7l2kgY+G7mXQgdOG7tyBs4buHIHRodeG6rW4gduG7m2kgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBnacOhIGLDoW4gY+G7p2Ega2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCB0xrDGoW5nIOG7qW5nLg0KICAtIENow7ogdGjDrWNoIHbEg24gYuG6o24gbcOgdSDEkWVuICgiYmxhY2siKTogSGnhu4NuIHRo4buLIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY2jDrW5oIHjDoWMgKMSRxrDhu6NjIGzDoG0gdHLDsm4pIG7hurFtIHRyw6puIMSR4buJbmggbeG7l2kgY+G7mXQuDQoNCiMjICpCaeG7g3UgxJHhu5MgY+G7mXQgdGjhu4MgaGnhu4duIHBoxrDGoW5nIHNhaSBnacOhIGLDoW4gdGhlbyBjw6FjIGJp4bq/bjogY3V0LCBjb2xvciB2w6AgY2xhcml0eS4qDQoNCioqKkJp4buDdSDEkeG7kyBj4buZdCB0aOG7gyBoaeG7h24gcGjGsMahbmcgc2FpIGdpw6EgYsOhbiB0aGVvIG3DoHUgc+G6r2Mga2ltIGPGsMahbmcqKioNCg0KLSBCaeG7g3UgxJHhu5MgbsOgeSB0aOG7gyBoaeG7h24gcGjGsMahbmcgc2FpIGPhu6dhIGdpw6EgYsOhbiB0aGVvIHThu6tuZyBtw6B1IHPhuq9jIGPhu6dhIGtpbSBjxrDGoW5nIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgZGlhbW9uZHMuIFBoxrDGoW5nIHNhaSBsw6AgbeG7mXQgdGjGsOG7m2MgxJFvIG3hu6ljIMSR4buZIHBow6JuIHTDoW4gY+G7p2EgZOG7ryBsaeG7h3UuDQoNCmBgYHtyfQ0KZyA8LSBkaWFtb25kcw0KZyAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2Uoaz0gdmFyKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoY29sb3IsaykpICsNCiAgICBnZW9tX2NvbChmaWxsPSdncmF5JykgKyANCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoaywyKSksdmp1c3QgPSAxLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnTcOgdScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCipOaOG6rW4geMOpdDoqDQogIC0gVHLhu6VjIHg6IFRo4buDIGhp4buHbiBjw6FjIG3DoHUgc+G6r2Mga2jDoWMgbmhhdSBj4bunYSBraW0gY8awxqFuZy4NCiAgLSBUcuG7pWMgeTogVGjhu4MgaGnhu4duIHBoxrDGoW5nIHNhaSAoaykgY+G7p2EgZ2nDoSBiw6FuICjEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAyIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuIChyb3VuZChrLCAyKSkpLCBjaG8gYmnhur90IG3hu6ljIMSR4buZIHRy4bqjaSBy4buZbmcgY+G7p2EgZ2nDoSBiw6FuDQogIC0gR2nDoSB0cuG7iyBjYW8gaMahbiB0csOqbiB0cuG7pWMgeSBjaG8gYmnhur90IHBoxrDGoW5nIHNhaSBjYW8gaMahbiwgbmdoxKlhIGzDoCBnacOhIGLDoW4gY+G7p2Ega2ltIGPGsMahbmcgY8OzIG3DoHUgc+G6r2MgxJHDsyBwaMOibiB0w6FuIHLhu5luZyBoxqFuIHh1bmcgcXVhbmggZ2nDoSB0cnVuZyBiw6xuaC4NCiAgLSBHacOhIHRy4buLIHRo4bqlcCBoxqFuIG1lbnVuanVra2FuIHBoxrDGoW5nIHNhaSB0aOG6pXAgaMahbiwgbmdoxKlhIGzDoCBnacOhIGLDoW4gY+G7p2Ega2ltIGPGsMahbmcgY8OzIG3DoHUgc+G6r2MgxJHDsyDDrXQgcGjDom4gdMOhbiBoxqFuIHh1bmcgcXVhbmggZ2nDoSB0cnVuZyBiw6xuaC4NCiAgLSBDw6FjIGPhu5l0IG3DoHUgeMOhbSAoImdyYXkiKTogQ2hp4buBdSBjYW8gY+G7p2EgbeG7l2kgY+G7mXQgdOG7tyBs4buHIHRodeG6rW4gduG7m2kgcGjGsMahbmcgc2FpIGdpw6EgYsOhbiBj4bunYSBraW0gY8awxqFuZyBjw7MgbcOgdSBz4bqvYyB0xrDGoW5nIOG7qW5nLg0KICAtIENow7ogdGjDrWNoIHbEg24gYuG6o24gbcOgdSDEkWVuICgiYmxhY2siKTogSGnhu4NuIHRo4buLIHBoxrDGoW5nIHNhaSBjaMOtbmggeMOhYyAoxJHGsOG7o2MgbMOgbSB0csOybikgbuG6sW0gdHLDqm4gxJHhu4luaCBt4buXaSBj4buZdC4NCg0KKioqQmnhu4N1IMSR4buTIGPhu5l0IHRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgZ2nDoSBiw6FuIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90KioqDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIHBoxrDGoW5nIHNhaSBj4bunYSBnacOhIGLDoW4gdGhlbyB04burbmcgY2jhuqV0IGzGsOG7o25nIGPhuq90IGPhu6dhIGtpbSBjxrDGoW5nIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgZGlhbW9uZHMuIFBoxrDGoW5nIHNhaSBsw6AgbeG7mXQgdGjGsOG7m2MgxJFvIG3hu6ljIMSR4buZIHBow6JuIHTDoW4gY+G7p2EgZOG7ryBsaeG7h3UuDQpgYGB7cn0NCmcgPC0gZGlhbW9uZHMNCmcgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShrPSB2YXIocHJpY2UpKSAlPiUNCiAgZ2dwbG90KGFlcyhjdXQsaykpICsNCiAgICBnZW9tX2NvbChmaWxsPSdsaWdodHllbGxvdycpICsgDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGssMikpLHZqdXN0ID0gMSwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0No4bqldCBsxrDhu6NuZyBj4bqvdCcsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBjaOG6pXQgbMaw4bujbmcgY+G6r3Qga2jDoWMgbmhhdSBj4bunYSBraW0gY8awxqFuZywgdOG7qyAiUG9vciIgKGvDqW0pIMSR4bq/biAiSWRlYWwiIChob8OgbiBo4bqjbykuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgKGspIGPhu6dhIGdpw6EgYsOhbiAoxJHGsOG7o2MgbMOgbSB0csOybiDEkeG6v24gMiBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiAocm91bmQoaywgMikpKSwgY2hvIGJp4bq/dCBt4bupYyDEkeG7mSB0cuG6o2kgcuG7mW5nIGPhu6dhIGdpw6EgYsOhbg0KICAtIEdpw6EgdHLhu4sgY2FvIGjGoW4gdHLDqm4gdHLhu6VjIHkgY2hvIGJp4bq/dCBwaMawxqFuZyBzYWkgY2FvIGjGoW4sIG5naMSpYSBsw6AgZ2nDoSBiw6FuIGPhu6dhIGtpbSBjxrDGoW5nIGPDsyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgxJHDsyBwaMOibiB0w6FuIHLhu5luZyBoxqFuIHh1bmcgcXVhbmggZ2nDoSB0cnVuZyBiw6xuaC4NCiAgLSBHacOhIHRy4buLIHRo4bqlcCBoxqFuIG1lbnVuanVra2FuIHBoxrDGoW5nIHNhaSB0aOG6pXAgaMahbiwgbmdoxKlhIGzDoCBnacOhIGLDoW4gY+G7p2Ega2ltIGPGsMahbmcgY8OzIGNo4bqldCBsxrDhu6NuZyBj4bqvdCDEkcOzIMOtdCBwaMOibiB0w6FuIGjGoW4geHVuZyBxdWFuaCBnacOhIHRydW5nIGLDrG5oLg0KICAtIEPDoWMgY+G7mXQgbcOgdSB2w6BuZyBuaOG6oXQgKCJsaWdodHllbGxvdyIpOiBDaGnhu4F1IGNhbyBj4bunYSBt4buXaSBj4buZdCB04bu3IGzhu4cgdGh14bqtbiB24bubaSBwaMawxqFuZyBzYWkgZ2nDoSBiw6FuIGPhu6dhIGtpbSBjxrDGoW5nIGPDsyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdMawxqFuZyDhu6luZy4NCiAgLSBDaMO6IHRow61jaCB2xINuIGLhuqNuIG3DoHUgxJFlbiAoImJsYWNrIik6IEhp4buDbiB0aOG7iyBwaMawxqFuZyBzYWkgY2jDrW5oIHjDoWMgKMSRxrDhu6NjIGzDoG0gdHLDsm4pIG7hurFtIHRyw6puIMSR4buJbmggbeG7l2kgY+G7mXQuDQoNCioqKkJp4buDdSDEkeG7kyBj4buZdCB0aOG7gyBoaeG7h24gcGjGsMahbmcgc2FpIGdpw6EgYsOhbiB0aGVvIMSR4buZIHRyb25nIHN14buRdCoqKg0KDQotIEJp4buDdSDEkeG7kyBuw6B5IHRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgY+G7p2EgZ2nDoSBiw6FuIHRoZW8gdOG7q25nIMSR4buZIHRyb25nIHN14buRdCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLiBQaMawxqFuZyBzYWkgbMOgIG3hu5l0IHRoxrDhu5tjIMSRbyBt4bupYyDEkeG7mSBwaMOibiB0w6FuIGPhu6dhIGThu68gbGnhu4d1Lg0KYGBge3J9DQpnIDwtIGRpYW1vbmRzDQpnICU+JSBncm91cF9ieShjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKGs9IHZhcihwcmljZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKGNsYXJpdHksaykpICsNCiAgICBnZW9tX2NvbChmaWxsPSdsaWdodHllbGxvdycpICsgDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGssMikpLHZqdXN0ID0gMC44NSwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ8SQ4buZIHRyb25nIHN14buRdCcsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCipOaOG6rW4geMOpdDoqDQogIC0gVHLhu6VjIHg6IFRo4buDIGhp4buHbiBjw6FjIMSR4buZIHRyb25nIHN14buRdCBraMOhYyBuaGF1IGPhu6dhIGtpbSBjxrDGoW5nLCB04burICJJMSIgKGvDqW0gdHJvbmcpIMSR4bq/biAiSUYiIChob8OgbiBo4bqjbyBraMO0bmcgdMOsIHbhur90KS4NCiAgLSBUcuG7pWMgeTogVGjhu4MgaGnhu4duIHBoxrDGoW5nIHNhaSAoaykgY+G7p2EgZ2nDoSBiw6FuICjEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAyIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuIChyb3VuZChrLCAyKSkpLCBjaG8gYmnhur90IG3hu6ljIMSR4buZIHRy4bqjaSBy4buZbmcgY+G7p2EgZ2nDoSBiw6FuDQogIC0gR2nDoSB0cuG7iyBjYW8gaMahbiB0csOqbiB0cuG7pWMgeSBjaG8gYmnhur90IHBoxrDGoW5nIHNhaSBjYW8gaMahbiwgbmdoxKlhIGzDoCBnacOhIGLDoW4gY+G7p2Ega2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCDEkcOzIHBow6JuIHTDoW4gcuG7mW5nIGjGoW4geHVuZyBxdWFuaCBnacOhIHRydW5nIGLDrG5oLg0KICAtIEdpw6EgdHLhu4sgdGjhuqVwIGjGoW4gbWVudW5qdWtrYW4gcGjGsMahbmcgc2FpIHRo4bqlcCBoxqFuLCBuZ2jEqWEgbMOgIGdpw6EgYsOhbiBj4bunYSBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IMSRw7Mgw610IHBow6JuIHTDoW4gaMahbiB4dW5nIHF1YW5oIGdpw6EgdHJ1bmcgYsOsbmguDQogIC0gQ8OhYyBj4buZdCBtw6B1IHbDoG5nIG5o4bqhdCAoImxpZ2h0eWVsbG93Iik6IENoaeG7gXUgY2FvIGPhu6dhIG3hu5dpIGPhu5l0IHThu7cgbOG7hyB0aHXhuq1uIHbhu5tpIHBoxrDGoW5nIHNhaSBnacOhIGLDoW4gY+G7p2Ega2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCB0xrDGoW5nIOG7qW5nLg0KICAtIENow7ogdGjDrWNoIHbEg24gYuG6o24gbcOgdSDEkWVuICgiYmxhY2siKTogSGnhu4NuIHRo4buLIHBoxrDGoW5nIHNhaSBjaMOtbmggeMOhYyAoxJHGsOG7o2MgbMOgbSB0csOybikgbuG6sW0gZ+G6p24gxJHhu4luaCBt4buXaSBj4buZdCwgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIHbhu4sgdHLDrSBi4bqxbmcgdmp1c3QgPSAwLjg1IMSR4buDIHRyw6FuaCBjaOG7k25nIGNow6lvIGzDqm4gY8OhYyBj4buZdC4NCiAgDQojIyAqQmnhu4N1IMSR4buTIGPhu5l0IHRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0aGVvIGPDoWMgYmnhur9uOiBDdXQsIGNvbG9yLCBjbGFyaXR5LioNCg0KKioqQmnhu4N1IMSR4buTIGPhu5l0IHRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0aGVvIG3DoHUgc+G6r2Mga2ltIGPGsMahbmcqKiogDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIG3hu6ljIMSR4buZIHBow6JuIHTDoW4gY+G7p2EgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCAoaykgdGhlbyB04burbmcgbcOgdSBz4bqvYyBj4bunYSBraW0gY8awxqFuZyB0cm9uZyB04bqtcCBk4buvIGxp4buHdSBkaWFtb25kcy4NCmBgYHtyfQ0KZyA8LSBkaWFtb25kcw0KZyAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2Uoaz0gdmFyKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoY29sb3IsaykpICsNCiAgICBnZW9tX2NvbChmaWxsPSdsaWdodHllbGxvdycpICsgDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGssMikpLHZqdXN0ID0gMSwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ03DoHUnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoqTmjhuq1uIHjDqXQ6Kg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBtw6B1IHPhuq9jIGtow6FjIG5oYXUgY+G7p2Ega2ltIGPGsMahbmcuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgKGspIGPhu6dhIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgKMSRw6MgxJHGsOG7o2MgbMOgbSB0csOybiDEkeG6v24gMiBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiksIGNobyBiaeG6v3QgbeG7qWMgxJHhu5kgdHLhuqNpIHLhu5luZyBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGNhcmF0Og0KICAtIEdpw6EgdHLhu4sgY2FvIGjGoW4gdHLDqm4gdHLhu6VjIHkgY2hvIGJp4bq/dCBwaMawxqFuZyBzYWkgY2FvIGjGoW4sIG5naMSpYSBsw6AgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCBj4bunYSBraW0gY8awxqFuZyBjw7MgbcOgdSBz4bqvYyDEkcOzIHBow6JuIHTDoW4gcuG7mW5nIGjGoW4geHVuZyBxdWFuaCBnacOhIHRy4buLIHRydW5nIGLDrG5oLg0KICAtIEdpw6EgdHLhu4sgdGjhuqVwIGjGoW4gY2hvIGJp4bq/dCBwaMawxqFuZyBzYWkgdGjhuqVwIGjGoW4sIG5naMSpYSBsw6AgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCBj4bunYSBraW0gY8awxqFuZyBjw7MgbcOgdSBz4bqvYyDEkcOzIMOtdCBwaMOibiB0w6FuIGjGoW4geHVuZyBxdWFuaCBnacOhIHRy4buLIHRydW5nIGLDrG5oLg0KICAtIEPhu5l0IG3DoHUgdsOgbmcgbmjhuqF0OiBDaGnhu4F1IGNhbyBj4bunYSBt4buXaSBj4buZdCB04bu3IGzhu4cgdGh14bqtbiB24bubaSBwaMawxqFuZyBzYWkgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCBj4bunYSBraW0gY8awxqFuZyBjw7MgbcOgdSBz4bqvYyB0xrDGoW5nIOG7qW5nLg0KICAtIENow7ogdGjDrWNoIHbEg24gYuG6o24gbcOgdSDEkWVuOiBIaeG7g24gdGjhu4sgcGjGsMahbmcgc2FpIGNow61uaCB4w6FjICjEkcOjIMSRxrDhu6NjIGzDoG0gdHLDsm4pIG7hurFtIHRyw6puIMSR4buJbmggbeG7l2kgY+G7mXQuDQoNCioqKkJp4buDdSDEkeG7kyBj4buZdCB0aOG7gyBoaeG7h24gcGjGsMahbmcgc2FpIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QqKiogDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIHBoxrDGoW5nIHNhaSBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRoZW8gdOG7q25nIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLiBQaMawxqFuZyBzYWkgbMOgIG3hu5l0IHRoxrDhu5tjIMSRbyBt4bupYyDEkeG7mSBwaMOibiB0w6FuIGPhu6dhIGThu68gbGnhu4d1Lg0KYGBge3J9DQpnIDwtIGRpYW1vbmRzDQpnICU+JSBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2Uoaz0gdmFyKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoY3V0LGspKSArDQogICAgZ2VvbV9jb2woZmlsbD0nbGlnaHR5ZWxsb3cnKSArIA0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChrLDMpKSx2anVzdCA9IDEsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICdDaOG6pXQgbMaw4bujbmcgY+G6r3QnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIHBoxrDGoW5nIHNhaSBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRoZW8gdOG7q25nIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBj4bunYSBraW0gY8awxqFuZyB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLiBQaMawxqFuZyBzYWkgbMOgIG3hu5l0IHRoxrDhu5tjIMSRbyBt4bupYyDEkeG7mSBwaMOibiB0w6FuIGPhu6dhIGThu68gbGnhu4d1Lg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBjaOG6pXQgbMaw4bujbmcgY+G6r3Qga2jDoWMgbmhhdSBj4bunYSBraW0gY8awxqFuZywgdOG7qyAiUG9vciIgKGvDqW0pIMSR4bq/biAiSWRlYWwiIChob8OgbiBo4bqjbykuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgKGspIGPhu6dhIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgKMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKGssIDIpKSksIGNobyBiaeG6v3QgbeG7qWMgxJHhu5kgdHLhuqNpIHLhu5luZyBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGNhcmF0DQogICAgLSBHacOhIHRy4buLIGNhbyBoxqFuIHRyw6puIHRy4bulYyB5IGNobyBiaeG6v3QgcGjGsMahbmcgc2FpIGNhbyBoxqFuLCBuZ2jEqWEgbMOgIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgY+G7p2Ega2ltIGPGsMahbmcgY8OzIGNo4bqldCBsxrDhu6NuZyBj4bqvdCDEkcOzIHBow6JuIHTDoW4gcuG7mW5nIGjGoW4geHVuZyBxdWFuaCBnacOhIHRy4buLIHRydW5nIGLDrG5oLg0KICAgIC0gR2nDoSB0cuG7iyB0aOG6pXAgaMahbiB0csOqbiB0cuG7pWMgeSBjaG8gYmnhur90IHBoxrDGoW5nIHNhaSB0aOG6pXAgaMahbiwgbmdoxKlhIGzDoCB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IGPhu6dhIGtpbSBjxrDGoW5nIGPDsyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgxJHDsyDDrXQgcGjDom4gdMOhbiBoxqFuIHh1bmcgcXVhbmggZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaC4NCiAgLSBDw6FjIGPhu5l0IG3DoHUgdsOgbmcgbmjhuqF0ICgieWVsbG93Iik6IENoaeG7gXUgY2FvIGPhu6dhIG3hu5dpIGPhu5l0IHThu7cgbOG7hyB0aHXhuq1uIHbhu5tpIHBoxrDGoW5nIHNhaSB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IGPhu6dhIGtpbSBjxrDGoW5nIGPDsyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdMawxqFuZyDhu6luZy4NCiAgLSBDaMO6IHRow61jaCB2xINuIGLhuqNuIG3DoHUgxJFlbiAoImJsYWNrIik6IEhp4buDbiB0aOG7iyBwaMawxqFuZyBzYWkgY2jDrW5oIHjDoWMgKMSRxrDhu6NjIGzDoG0gdHLDsm4pIG7hurFtIHRyw6puIMSR4buJbmggbeG7l2kgY+G7mXQuDQogIA0KKioqQmnhu4N1IMSR4buTIGPhu5l0IHRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0aGVvIMSR4buZIHRyb25nIHN14buRdCoqKiANCg0KDQpgYGB7cn0NCmcgPC0gZGlhbW9uZHMNCmcgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2Uoaz0gdmFyKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoY2xhcml0eSxrKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2xpZ2h0eWVsbG93JykgKyANCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoaywyKSksdmp1c3QgPSAxLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnxJDhu5kgdHJvbmcgc3Xhu5F0JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQotIEJp4buDdSDEkeG7kyBuw6B5IHRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgY+G7p2EgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0aGVvIHThu6tuZyDEkeG7mSB0cm9uZyBzdeG7kXQgY+G7p2Ega2ltIGPGsMahbmcgdHJvbmcgYuG7mSBk4buvIGxp4buHdSBkaWFtb25kcy4gUGjGsMahbmcgc2FpIGzDoCBt4buZdCB0aMaw4bubYyDEkW8gbeG7qWMgxJHhu5kgcGjDom4gdMOhbiBj4bunYSBk4buvIGxp4buHdS4NCg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyDEkeG7mSB0cm9uZyBzdeG7kXQga2jDoWMgbmhhdSBj4bunYSBraW0gY8awxqFuZywgdOG7qyAiSTEiIChrw6ltIHRyb25nKSDEkeG6v24gIklGIiAoaG/DoG4gaOG6o28ga2jDtG5nIHTDrCB24bq/dCkuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiBwaMawxqFuZyBzYWkgKGspIGPhu6dhIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgKMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKGssIDIpKSksIGNobyBiaeG6v3QgbeG7qWMgxJHhu5kgdHLhuqNpIHLhu5luZyBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGNhcmF0DQogIC0gR2nDoSB0cuG7iyBjYW8gaMahbiB0csOqbiB0cuG7pWMgeSBjaG8gYmnhur90IHBoxrDGoW5nIHNhaSBjYW8gaMahbiwgbmdoxKlhIGzDoCB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IGPhu6dhIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgxJHDsyBwaMOibiB0w6FuIHLhu5luZyBoxqFuIHh1bmcgcXVhbmggZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaC4NCiAgLSBHacOhIHRy4buLIHRo4bqlcCBoxqFuIHRyw6puIHRy4bulYyB5IGNobyBiaeG6v3QgcGjGsMahbmcgc2FpIHRo4bqlcCBoxqFuLCBuZ2jEqWEgbMOgIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgY+G7p2Ega2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCDEkcOzIMOtdCBwaMOibiB0w6FuIGjGoW4geHVuZyBxdWFuaCBnacOhIHRy4buLIHRydW5nIGLDrG5oLg0KICAtIEPDoWMgY+G7mXQgbcOgdSB2w6BuZyBuaOG6oXQgKCJsaWdodHllbGxvdyIpOiBDaGnhu4F1IGNhbyBj4bunYSBt4buXaSBj4buZdCB04bu3IGzhu4cgdGh14bqtbiB24bubaSBwaMawxqFuZyBzYWkgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCBj4bunYSBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IHTGsMahbmcg4bupbmcuDQpDaMO6IHRow61jaCB2xINuIGLhuqNuIG3DoHUgxJFlbiAoImJsYWNrIik6IEhp4buDbiB0aOG7iyBwaMawxqFuZyBzYWkgY2jDrW5oIHjDoWMgKMSRxrDhu6NjIGzDoG0gdHLDsm4pIG7hurFtIHRyw6puIMSR4buJbmggbeG7l2kgY+G7mXQuDQoNCg0KIyMgKkJp4buDdSDEkeG7kyBj4buZdCBrw6lwIHRo4buDIGhp4buHbiBwaMOibiBi4buRIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdsOgIG3DoHUgc+G6r2MqDQoNCioqKkJp4buDdSDEkeG7kyBj4buZdCBrw6lwIHRo4buDIGhp4buHbiBwaMOibiBi4buRIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdsOgIG3DoHUgc+G6r2MgY+G7p2Ega2ltIGPGsMahbmcgbG/huqFpIEUgdsOgIEgqKioNCg0KLSBCaeG7g3UgxJHhu5MgbsOgeSB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgKGN1dCkgdsOgIG3DoHUgc+G6r2MgKGNvbG9yKSB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLg0KYGBge3J9DQpnIDwtIGRpYW1vbmRzDQpnIDwtIGcgJT4lIGdyb3VwX2J5KGN1dCwgY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCmcgJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSBnICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0UnKSwgZmlsbCA9ICdsaWdodHllbGxvdycpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGcgJT4lIGZpbHRlcihjb2xvciA9PSAnSCcpLCBmaWxsID0gJ3BpbmsnKQ0KYGBgDQoqTmjhuq1uIHjDqXQ6Kg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBjaOG6pXQgbMaw4bujbmcgY+G6r3Qga2jDoWMgbmhhdSBj4bunYSBraW0gY8awxqFuZywgdOG7qyAiRmFpciIgKGvDqW0pIMSR4bq/biAiSWRlYWwiIChob8OgbiBo4bqjbykuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIChuKSBraW0gY8awxqFuZy4NCiAgLSBD4buZdCBtw6B1IHbDoG5ndsOgbmcgbmjhuqF0ICgic2t5Ymx1ZSIpOiBCaeG7g3UgdGjhu4sgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgbcOgdSBFIHRoZW8gdOG7q25nIGNo4bqldCBsxrDhu6NuZyBj4bqvdC4NCiAgLSBD4buZdCBtw6B1IGjhu5NuZyAoInBpbmsiKTogQmnhu4N1IHRo4buLIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY8OzIG3DoHUgSCB0aGVvIHThu6tuZyBjaOG6pXQgbMaw4bujbmcgY+G6r3QuDQoNCioqKkJp4buDdSDEkeG7kyBj4buZdCBrw6lwIHRo4buDIGhp4buHbiBwaMOibiBi4buRIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdsOgIG3DoHUgc+G6r2MgY+G7p2Ega2ltIGPGsMahbmcgbG/huqFpIEUgdsOgIEgqKioNCg0KLSBCaeG7g3UgxJHhu5MgbsOgeSB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgKGN1dCkgdsOgIG3DoHUgc+G6r2MgKGNvbG9yKSB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLg0KYGBge3J9DQpnIDwtIGRpYW1vbmRzDQpnIDwtIGcgJT4lIGdyb3VwX2J5KGN1dCwgY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCmcgJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSBnICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0UnKSwgZmlsbCA9ICdsaWdodHllbGxvdycpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGcgJT4lIGZpbHRlcihjb2xvciA9PSAnSScpLCBmaWxsID0gJ3BpbmsnKQ0KYGBgDQogICpOaOG6rW4geMOpdDoqDQogIC0gVHLhu6VjIHg6IFRo4buDIGhp4buHbiBjw6FjIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBraMOhYyBuaGF1IGPhu6dhIGtpbSBjxrDGoW5nLCB04burICJGYWlyIiAoa8OpbSkgxJHhur9uICJJZGVhbCIgKGhvw6BuIGjhuqNvKS4NCiAgLSBUcuG7pWMgeTogVGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgKG4pIGtpbSBjxrDGoW5nLg0KICAtIEPhu5l0IG3DoHUgeGFuaCBuaOG6oXQgKCJza3libHVlIik6IEJp4buDdSB0aOG7iyBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEUgdGhlbyB04burbmcgY2jhuqV0IGzGsOG7o25nIGPhuq90Lg0KICAtIEPhu5l0IG3DoHUgaOG7k25nICgicGluayIpOiBCaeG7g3UgdGjhu4sgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgbcOgdSBJIHRoZW8gdOG7q25nIGNo4bqldCBsxrDhu6NuZyBj4bqvdC4NCg0KIyMgKkJp4buDdSDEkeG7kyB0aGFuaCB0aOG7gyBoaeG7h24gcGjDom4gYuG7kSBjaOG6pXQgbMaw4bujbmcgY+G6r3Qga2ltIGPGsMahbmcqDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIHBow6JuIGLhu5EgY+G7p2EgY2jhuqV0IGzGsOG7o25nIGPhuq90IGtpbSBjxrDGoW5nIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgZGlhbW9uZHMuDQoNCmBgYHtyfQ0KZyA8LSBkaWFtb25kcyANCmcgPC0gZyAlPiUgbXV0YXRlKGNhcmF0QyA9IGN1dChjYXJhdCw1LCBsYWJlbCA9IGMoJ3LhuqV0IG5o4buPJywgJ25o4buPJywnduG7q2EnLCds4bubbicsJ3LhuqV0IGzhu5tuJykpKQ0KZyAlPiUgZ2dwbG90KGFlcyh4ID0gY2FyYXRDKSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ2JsdWUnKQ0KICBsYWJzKHg9ICdDaOG6pXQgbMaw4bujbmcgY+G6r3QnKQ0KYGBgDQoqTmjhuq1uIHjDqXQ6Kg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgxJHGsOG7o2MgY2hpYSB0aMOgbmggNSBuaMOzbTogInLhuqV0IG5o4buPIiwgIm5o4buPIiwgInbhu6thIiwgImzhu5tuIiwgInLhuqV0IGzhu5tuIi4NCiAgLSBUcuG7pWMgeTogVGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGh14buZYyBt4buXaSBuaMOzbSBjaOG6pXQgbMaw4bujbmcgY+G6r3QuDQpD4buZdCBtw6B1IHbDoG5nOiBCaeG7g3UgdGjhu4sgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjaG8gbeG7l2kgbmjDs20gY2jhuqV0IGzGsOG7o25nIGPhuq90LiANCg0KIyMgKkJp4buDdSDEkeG7kyBj4buZdCBrw6lwIHRoZW8gbeG6t3QgY+G6r3QgKGN1dCkgcGjDom4gdMOhY2ggdGhlbyBtw6B1IHPhuq9jIChjb2xvcikqDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCAoY3V0KSDEkcaw4bujYyB0w6FjaCByacOqbmcgdGhlbyBtw6B1IHPhuq9jIChjb2xvcikgdHJvbmcgYuG7mSBk4buvIGxp4buHdSBnLg0KDQpgYGB7cn0NCmcgJT4lIGdyb3VwX2J5KGN1dCxjb2xvcikgJT4lIHN1bW1hcmlzZShuID1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjdXQseSA9IG4pKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnLCBmaWxsPSAnbGlnaHR5ZWxsb3cnKSArDQogICAgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLjY1LCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoNCg0KQ8OhYyB0aMOgbmggcGjhuqduOg0KDQogIC0gVHLhu6VjIHg6IFRo4buDIGhp4buHbiBjw6FjIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBraMOhYyBuaGF1IGPhu6dhIGtpbSBjxrDGoW5nLCB04burICJQb29yIiAoa8OpbSkgxJHhur9uICJJZGVhbCIgKGhvw6BuIGjhuqNvKS4NCiAgLSBUcuG7pWMgeTogVGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgKG4pIGtpbSBjxrDGoW5nLg0KICAtIEPDoWMgbeG6t3QgY+G6r3QgKGZhY2V0cyk6IEJp4buDdSDEkeG7kyDEkcaw4bujYyBjaGlhIHRow6BuaCBoYWkgbeG6t3QgY+G6r3QgdGhlbyBtw6B1IHPhuq9jIChjb2xvcikgY+G7p2Ega2ltIGPGsMahbmcsIMSRxrDhu6NjIHBow6JuIGJp4buHdCBi4bqxbmcgbmjDo24g4bufIHBow61hIHRyw6puIG3hu5dpIG3hurd0IGPhuq90Lg0KICAgIC0gTeG6t3QgY+G6r3QgRDogQmnhu4N1IHRo4buLIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBELg0KICAgIC0gTeG6t3QgY+G6r3QgRTogQmnhu4N1IHRo4buLIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBFLg0KICAgIC0gTeG6t3QgY+G6r3QgRjogQmnhu4N1IHRo4buLIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBGLg0KICAgIC0gTeG6t3QgY+G6r3QgRzogQmnhu4N1IHRo4buLIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBHLg0KICAgIC0gTeG6t3QgY+G6r3QgSDogQmnhu4N1IHRo4buLIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBILg0KICAgIC0gTeG6t3QgY+G6r3QgSTogQmnhu4N1IHRo4buLIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBJLiANCiAgICAtIE3hurd0IGPhuq90IEo6IEJp4buDdSB0aOG7iyBwaMOibiBi4buRIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgY2hvIG3DoHUgc+G6r2MgSi4NCiAgLSBD4buZdCBtw6B1IHbDoG5nIG5o4bqhdCAoImxpZ2h0eWVsbG93Iik6IEJp4buDdSB0aOG7iyBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGNobyBt4buXaSBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdHJvbmcgbeG7l2kgbeG6t3QgY+G6r3QuDQogIC0gQ2jDuiB0aMOtY2ggdsSDbiBi4bqjbiBtw6B1IMSRZW4gKCJibGFjayIpOiBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjaMOtbmggeMOhYyAobikgbuG6sW0gdHLDqm4gxJHhu4luaCBt4buXaSBj4buZdCwgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIHbhu4sgdHLDrSBi4bqxbmcgdmp1c3QgPSAwLjY1IMSR4buDIHRyw6FuaCBjaOG7k25nIGNow6lvIGzDqm4gY8OhYyBj4buZdC4NCg0KIyMgKkJp4buDdSDEkeG7kyBj4buZdCBrw6lwIHRoZW8gbeG6t3QgY+G6r3QgKGN1dCkgcGjDom4gdMOhY2ggdGhlbyBtw6B1IHPhuq9jIChjb2xvciksIHRo4buDIGhp4buHbiBnacOhIHRydW5nIGLDrG5oKiAgIA0KDQotIEJp4buDdSDEkeG7kyBuw6B5IHRo4buDIGhp4buHbiBnacOhIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IChjdXQpIMSRxrDhu6NjIHTDoWNoIHJpw6puZyB0aGVvIG3DoHUgc+G6r2MgKGNvbG9yKSB0cm9uZyBi4buZIGThu68gbGnhu4d1IGcuDQpgYGB7cn0NCmcgJT4lIGdyb3VwX2J5KGN1dCxjb2xvcikgJT4lIHN1bW1hcmlzZShrID1tZWFuKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gaykpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScsIGZpbGw9ICdsaWdodHllbGxvdycpICsNCiAgICBmYWNldF93cmFwKH5jb2xvcikgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChrLDEpKSx2anVzdCA9IDAuMjUsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoqTmjhuq1uIHjDqXQ6Kg0KQ8OhYyB0aMOgbmggcGjhuqduOg0KDQogIC0gVHLhu6VjIHg6IFRo4buDIGhp4buHbiBjw6FjIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBraMOhYyBuaGF1IGPhu6dhIGtpbSBjxrDGoW5nLCB04burICJQb29yIiAoa8OpbSkgxJHhur9uICJJZGVhbCIgKGhvw6BuIGjhuqNvKS4NCiAgLSBUcuG7pWMgeTogVGjhu4MgaGnhu4duIGdpw6EgdHJ1bmcgYsOsbmggKGspIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDEgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKGssIDEpKS4NCiAgLSBDw6FjIG3hurd0IGPhuq90IChmYWNldHMpOiBCaeG7g3UgxJHhu5MgxJHGsOG7o2MgY2hpYSB0aMOgbmggaGFpIG3hurd0IGPhuq90IHRoZW8gbcOgdSBz4bqvYyAoY29sb3IpIGPhu6dhIGtpbSBjxrDGoW5nLCDEkcaw4bujYyBwaMOibiBiaeG7h3QgYuG6sW5nIG5ow6NuIOG7nyBwaMOtYSB0csOqbiBt4buXaSBt4bq3dCBj4bqvdC4NCiAgICAtIE3hurd0IGPhuq90IEQ6IEJp4buDdSB0aOG7iyBnacOhIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IGNobyBtw6B1IHPhuq9jIEQuDQogICAgLSBN4bq3dCBj4bqvdCBFOiBCaeG7g3UgdGjhu4sgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBFLg0KICAgIC0gTeG6t3QgY+G6r3QgRjogQmnhu4N1IHRo4buLIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgY2hvIG3DoHUgc+G6r2MgRi4NCiAgICAtIE3hurd0IGPhuq90IEc6IEJp4buDdSB0aOG7iyBnacOhIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IGNobyBtw6B1IHPhuq9jIEcuDQogICAgLSBN4bq3dCBj4bqvdCBIOiBCaeG7g3UgdGjhu4sgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBILg0KICAgIC0gTeG6t3QgY+G6r3QgSTogQmnhu4N1IHRo4buLIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgY2hvIG3DoHUgc+G6r2MgSS4gDQogICAgLSBN4bq3dCBj4bqvdCBKOiBCaeG7g3UgdGjhu4sgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBKLg0KICAtIEPhu5l0IG3DoHUgdsOgbmcgbmjhuqF0ICgibGlnaHR5ZWxsb3ciKTogQmnhu4N1IHRo4buLIGdpw6EgdHJ1bmcgYsOsbmggY2hvIG3hu5dpIGNo4bqldCBsxrDhu6NuZyBj4bqvdCB0cm9uZyBt4buXaSBt4bq3dCBj4bqvdC4NCiAgLSBDaMO6IHRow61jaCB2xINuIGLhuqNuIG3DoHUgxJFlbiAoImJsYWNrIik6IEhp4buDbiB0aOG7iyBnacOhIHRydW5nIGLDrG5oIGNow61uaCB4w6FjICjEkcaw4bujYyBsw6BtIHRyw7JuKSBu4bqxbSB0csOqbiDEkeG7iW5oIG3hu5dpIGPhu5l0LCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIGLhurFuZyB2anVzdCA9IDAuMjUgxJHhu4MgdHLDoW5oIGNo4buTbmcgY2jDqW8gbMOqbiBjw6FjIGPhu5l0Lg0KDQojIyAqQmnhu4N1IMSR4buTIGPhu5l0IGvDqXAgdGhlbyBt4bq3dCBj4bqvdCAoY3V0KSBwaMOibiB0w6FjaCB0aGVvIG3DoHUgc+G6r2MgKGNvbG9yKSwgdGjhu4MgaGnhu4duIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmgqIA0KDQotIEJp4buDdSDEkeG7kyBuw6B5IHRo4buDIGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IChjdXQpIMSRxrDhu6NjIHTDoWNoIHJpw6puZyB0aGVvIG3DoHUgc+G6r2MgKGNvbG9yKSB0cm9uZyBi4buZIGThu68gbGnhu4d1IGcuDQpgYGB7cn0NCmcgJT4lIGdyb3VwX2J5KGN1dCxjb2xvcikgJT4lIHN1bW1hcmlzZShrPW1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBrKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJywgZmlsbD0gJ2xpZ2h0eWVsbG93JykgKw0KICAgIGZhY2V0X3dyYXAofmNvbG9yKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGssMikpLHZqdXN0ID0gMC42NSwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCipOaOG6rW4geMOpdDoqDQpDw6FjIHRow6BuaCBwaOG6p246DQoNCiAgLSBUcuG7pWMgeDogVGjhu4MgaGnhu4duIGPDoWMgY2jhuqV0IGzGsOG7o25nIGPhuq90IGtow6FjIG5oYXUgY+G7p2Ega2ltIGPGsMahbmcsIHThu6sgIlBvb3IiIChrw6ltKSDEkeG6v24gIklkZWFsIiAoaG/DoG4gaOG6o28pLg0KICAtIFRy4bulYyB5OiBUaOG7gyBoaeG7h24gdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCAoaykgxJHGsOG7o2MgbMOgbSB0csOybiDEkeG6v24gMiBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiAocm91bmQoaywgMikpLg0KICAtIEPDoWMgbeG6t3QgY+G6r3QgKGZhY2V0cyk6IEJp4buDdSDEkeG7kyDEkcaw4bujYyBjaGlhIHRow6BuaCBoYWkgbeG6t3QgY+G6r3QgdGhlbyBtw6B1IHPhuq9jIChjb2xvcikgY+G7p2Ega2ltIGPGsMahbmcsIMSRxrDhu6NjIHBow6JuIGJp4buHdCBi4bqxbmcgbmjDo24g4bufIHBow61hIHRyw6puIG3hu5dpIG3hurd0IGPhuq90Lg0KICAgIC0gTeG6t3QgY+G6r3QgRDogQmnhu4N1IHRo4buLIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgY2hvIG3DoHUgc+G6r2MgRC4NCiAgICAtIE3hurd0IGPhuq90IEU6IEJp4buDdSB0aOG7iyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IGNobyBtw6B1IHPhuq9jIEUuDQogICAgLSBN4bq3dCBj4bqvdCBGOiBCaeG7g3UgdGjhu4sgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBGLg0KICAgIC0gTeG6t3QgY+G6r3QgRzogQmnhu4N1IHRo4buLIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgY2hvIG3DoHUgc+G6r2MgRy4NCiAgICAtIE3hurd0IGPhuq90IEg6IEJp4buDdSB0aOG7iyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IGNobyBtw6B1IHPhuq9jIEguDQogICAgLSBN4bq3dCBj4bqvdCBJOiBCaeG7g3UgdGjhu4sgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCBjaG8gbcOgdSBz4bqvYyBJLiANCiAgICAtIE3hurd0IGPhuq90IEo6IEJp4buDdSB0aOG7iyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IGNobyBtw6B1IHPhuq9jIEouDQogIC0gQ+G7mXQgbcOgdSB2w6BuZyBuaOG6oXQgKCJsaWdodHllbGxvdyIpOiBCaeG7g3UgdGjhu4sgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCBjaG8gbeG7l2kgY2jhuqV0IGzGsOG7o25nIGPhuq90IHRyb25nIG3hu5dpIG3hurd0IGPhuq90Lg0KICAtIENow7ogdGjDrWNoIHbEg24gYuG6o24gbcOgdSDEkWVuICgiYmxhY2siKTogSGnhu4NuIHRo4buLIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggY2jDrW5oIHjDoWMgKMSRxrDhu6NjIGzDoG0gdHLDsm4pIG7hurFtIHRyw6puIMSR4buJbmggbeG7l2kgY+G7mXQsIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCB24buLIHRyw60gYuG6sW5nIHZqdXN0ID0gMC42NSDEkeG7gyB0csOhbmggY2jhu5NuZyBjaMOpbyBsw6puIGPDoWMgY+G7mXQuDQoNCg0KIyMgKkJp4buDdSDEkeG7kyBj4buZdCB0aOG7gyBoaeG7h24gdHJ1bmcgduG7iyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRoZW8gY8OhYyBiaeG6v246IGN1dCwgY29sb3IsIGNsYXJpdHkqIA0KDQoqKipCaeG7g3UgxJHhu5MgY+G7mXQgdGjhu4MgaGnhu4duIHRydW5nIHbhu4sgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCAoY3V0KSoqKg0KDQotIEJp4buDdSDEkeG7kyBuw6B5IHRo4buDIGhp4buHbiB0cnVuZyB24buLIGPhu6dhIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgKGN1dCkgdHJvbmcgYuG7mSBk4buvIGxp4buHdSBnLg0KDQpgYGB7cn0NCmcgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShtPSBtZWRpYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJywgZmlsbD0gJ2xpZ2h0eWVsbG93JykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDIpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICdwaW5rJykgKw0KICAgIGxhYnMoeCA9ICdjdXQnLCB5ID0gJ01lZGlhbicpDQpgYGANCipOaOG6rW4geMOpdDoqDQotIEPDoWMgdGjDoG5oIHBo4bqnbjoNCg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBjaOG6pXQgbMaw4bujbmcgY+G6r3Qga2jDoWMgbmhhdSBj4bunYSBraW0gY8awxqFuZywgdOG7qyAiRmFpciIgKGvDqW0pIMSR4bq/biAiSWRlYWwiIChob8OgbiBo4bqjbykuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIHbhu4sgKG0pIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKG0sIDIpKS4NCiAgLSBD4buZdCBtw6B1IHbDoG5nIG5o4bqhdCAoImxpZ2h0eWVsbG93Iik6IEJp4buDdSB0aOG7iyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIHbhu4sgY2hvIG3hu5dpIGNo4bqldCBsxrDhu6NuZyBj4bqvdC4NCiAgLSBDaMO6IHRow61jaCB2xINuIGLhuqNuIG3DoHUgaOG7k25nICgicGluayIpOiBIaeG7g24gdGjhu4sgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0cnVuZyB24buLIGNow61uaCB4w6FjICjEkcaw4bujYyBsw6BtIHRyw7JuKSBu4bqxbSB0csOqbiDEkeG7iW5oIG3hu5dpIGPhu5l0LCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIGLhurFuZyB2anVzdCA9IDIgxJHhu4MgdHLDoW5oIGNo4buTbmcgY2jDqW8gbMOqbiBjw6FjIGPhu5l0Lg0KICAtIFThu7FhIMSR4buBICJNZWRpYW4iOiBUaOG7gyBoaeG7h24gdHLDqm4gdHLhu6VjIHksIGNobyBiaeG6v3QgZ2nDoSB0cuG7iyDEkcaw4bujYyBoaeG7g24gdGjhu4sgbMOgIHRydW5nIHbhu4suDQogICAgLSDDnSBuZ2jEqWE6DQoNCiAgICAgIFRydW5nIHbhu4sgKG1lZGlhbikgbMOgIGdpw6EgdHLhu4sg4bufIGdp4buvYSBj4bunYSBt4buZdCB04bqtcCBk4buvIGxp4buHdSDEkcOjIMSRxrDhu6NjIHPhuq9wIHjhur9wIHRoZW8gdGjhu6kgdOG7sS4gU28gduG7m2kgdHJ1bmcgYsOsbmggY+G7mW5nIChtZWFuKSwgdHJ1bmcgduG7iyDDrXQgYuG7iyDhuqNuaCBoxrDhu59uZyBi4bufaSBjw6FjIGdpw6EgdHLhu4sgbmdv4bqhaSBsYWkgKG91dGxpZXJzKSAtIG5o4buvbmcgZ2nDoSB0cuG7iyBu4bqxbSBy4bqldCB4YSBzbyB24bubaSBwaOG6p24gY8OybiBs4bqhaSBj4bunYSBk4buvIGxp4buHdS4gRG8gxJHDsywgYmnhu4N1IMSR4buTIG7DoHkgZ2nDunAgaGnhu4N1IHLDtSBoxqFuIHbhu4EgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCDEkWnhu4NuIGjDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90LA0Kw610IGLhu4sg4bqjbmggaMaw4bufbmcgYuG7n2kgbmjhu69uZyB2acOqbiBraW0gY8awxqFuZyBjw7MgdHLhu41uZyBsxrDhu6NuZyBy4bqldCBjYW8gaG/hurdjIHLhuqV0IHRo4bqlcC4NCg0KKioqQmnhu4N1IMSR4buTIGPhu5l0IHRo4buDIGhp4buHbiB0cnVuZyB24buLIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdGhlbyBtw6B1IHPhuq9jIChjb2xvcikqKioNCg0KLSBCaeG7g3UgxJHhu5MgbsOgeSB0aOG7gyBoaeG7h24gdHJ1bmcgduG7iyBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRoZW8gbcOgdSBz4bqvYyAoY29sb3IpIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgZy4NCmBgYHtyfQ0KZyAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobT0gbWVkaWFuKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNvbG9yLHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJywgZmlsbD0gJ2xpZ2h0eWVsbG93JykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDMpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICdwaW5rJykgKw0KICAgIGxhYnMoeCA9ICdjb2xvcicsIHkgPSAnTWVkaWFuJykNCmBgYA0KKk5o4bqtbiB4w6l0OioNCkPDoWMgdGjDoG5oIHBo4bqnbjoNCg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBtw6B1IHPhuq9jIGtow6FjIG5oYXUgY+G7p2Ega2ltIGPGsMahbmcuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIHbhu4sgKG0pIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKG0sIDIpKS4NCiAgLSBD4buZdCBtw6B1IHbDoG5nIG5o4bqhdCAoImxpZ2h0eWVsbG93Iik6IEJp4buDdSB0aOG7iyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIHbhu4sgY2hvIG3hu5dpIG3DoHUgc+G6r2MuDQogIC0gQ2jDuiB0aMOtY2ggdsSDbiBi4bqjbiBtw6B1IGjhu5NuZyAoInBpbmsiKTogSGnhu4NuIHRo4buLIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdHJ1bmcgduG7iyBjaMOtbmggeMOhYyAoxJHGsOG7o2MgbMOgbSB0csOybikgbuG6sW0gdHLDqm4gxJHhu4luaCBt4buXaSBj4buZdCwgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIHbhu4sgdHLDrSBi4bqxbmcgdmp1c3QgPSAyIMSR4buDIHRyw6FuaCBjaOG7k25nIGNow6lvIGzDqm4gY8OhYyBj4buZdC4NCiAgLSBU4buxYSDEkeG7gSAiTWVkaWFuIjogVGjhu4MgaGnhu4duIHRyw6puIHRy4bulYyB5LCBjaG8gYmnhur90IGdpw6EgdHLhu4sgxJHGsOG7o2MgaGnhu4NuIHRo4buLIGzDoCB0cnVuZyB24buLLg0KICAgIC0gw50gbmdoxKlhOg0KDQogICAgVHJ1bmcgduG7iyAobWVkaWFuKSBsw6AgZ2nDoSB0cuG7iyDhu58gZ2nhu69hIGPhu6dhIG3hu5l0IHThuq1wIGThu68gbGnhu4d1IMSRw6MgxJHGsOG7o2Mgc+G6r3AgeOG6v3AgdGhlbyB0aOG7qSB04buxLiBTbyB24bubaSB0cnVuZyBiw6xuaCBj4buZbmcgKG1lYW4pLCB0cnVuZyB24buLIMOtdCBi4buLIOG6o25oIGjGsOG7n25nIGLhu59pIGPDoWMgZ2nDoSB0cuG7iyBuZ2/huqFpIGxhaSAob3V0bGllcnMpIC0gbmjhu69uZyBnacOhIHRy4buLIG7hurFtIHLhuqV0IHhhIHNvIHbhu5tpIHBo4bqnbiBjw7JuIGzhuqFpIGPhu6dhIGThu68gbGnhu4d1LiBEbyDEkcOzLCBiaeG7g3UgxJHhu5MgbsOgeSBnacO6cCBoaeG7g3UgcsO1IGjGoW4gduG7gSB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IMSRaeG7g24gaMOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jLA0Kw610IGLhu4sg4bqjbmggaMaw4bufbmcgYuG7n2kgbmjhu69uZyB2acOqbiBraW0gY8awxqFuZyBjw7MgdHLhu41uZyBsxrDhu6NuZyBy4bqldCBjYW8gaG/hurdjIHLhuqV0IHRo4bqlcC4NCg0KKioqQmnhu4N1IMSR4buTIGPhu5l0IHRo4buDIGhp4buHbiB0cnVuZyB24buLIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdGhlbyDEkeG7mSB0aW5oIGtoaeG6v3QgKGNsYXJpdHkpKioqDQoNCkJp4buDdSDEkeG7kyBuw6B5IHRo4buDIGhp4buHbiB0cnVuZyB24buLIGPhu6dhIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdGhlbyDEkeG7mSB0aW5oIGtoaeG6v3QgKGNsYXJpdHkpIGPhu6dhIGtpbSBjxrDGoW5nIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgZy4NCmBgYHtyfQ0KZyAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShtPSBtZWRpYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSx5ID0gbSkpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScsIGZpbGw9ICdsaWdodHllbGxvdycpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAncGluaycpICsNCiAgICBsYWJzKHggPSAnY2xhcml0eScsIHkgPSAnTWVkaWFuJykNCmBgYA0KKk5o4bqtbiB4w6l0OioNCi0gQ8OhYyB0aMOgbmggcGjhuqduOg0KDQogIC0gVHLhu6VjIHg6IFRo4buDIGhp4buHbiBjw6FjIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dCBraMOhYyBuaGF1IGPhu6dhIGtpbSBjxrDGoW5nLCB0aMaw4budbmcgxJHGsOG7o2Mga8O9IGhp4buHdSBi4bqxbmcgY2jhu68gY8OhaSAodsOtIGThu6U6IElGLCBWVlMxLCBWUzEsIFNJMSwgdi52LikuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIHbhu4sgKG0pIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKG0sIDIpKS4NCiAgLSBD4buZdCBtw6B1IHbDoG5nIG5o4bqhdCAoImxpZ2h0eWVsbG93Iik6IEJp4buDdSB0aOG7iyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIHbhu4sgY2hvIG3hu5dpIG3hu6ljIMSR4buZIHRpbmgga2hp4bq/dC4NCiAgLSBDaMO6IHRow61jaCB2xINuIGLhuqNuIG3DoHUgaOG7k25nICgicGluayIpOiBIaeG7g24gdGjhu4sgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0cnVuZyB24buLIGNow61uaCB4w6FjICjEkcaw4bujYyBsw6BtIHRyw7JuKSBu4bqxbSB0csOqbiDEkeG7iW5oIG3hu5dpIGPhu5l0LCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIGLhurFuZyB2anVzdCA9IDIgxJHhu4MgdHLDoW5oIGNo4buTbmcgY2jDqW8gbMOqbiBjw6FjIGPhu5l0Lg0KICAtIFThu7FhIMSR4buBICJNZWRpYW4iOiBUaOG7gyBoaeG7h24gdHLDqm4gdHLhu6VjIHksIGNobyBiaeG6v3QgZ2nDoSB0cuG7iyDEkcaw4bujYyBoaeG7g24gdGjhu4sgbMOgIHRydW5nIHbhu4suDQoNCiMjICpCaeG7g3UgxJHhu5MgY+G7mXQgdGjhu4MgaGnhu4duIHRydW5nIHbhu4sgZ2nDoSBj4bunYSBraW0gY8awxqFuZyB0aGVvIGPDoWMgYmnhur9uOiBjdXQsIGNvbG9yLCBjbGFyaXR5Kg0KDQoqKipCaeG7g3UgxJHhu5MgY+G7mXQgdGjhu4MgaGnhu4duIHRydW5nIHbhu4sgZ2nDoSBj4bunYSBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdCAoY3V0KSoqKg0KDQpCaeG7g3UgxJHhu5MgbsOgeSB0aOG7gyBoaeG7h24gdHJ1bmcgduG7iyBj4bunYSBnacOhIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IChjdXQpIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgZ2cuDQpgYGB7cn0NCmcgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShtPSBtZWRpYW4ocHJpY2UpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJywgZmlsbD0gJ2xpZ2h0eWVsbG93JykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDIpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICdwaW5rJykgKw0KICAgIGxhYnMoeCA9ICdjdXQnLCB5ID0gJ01lZGlhbicpDQpgYGANCipOaOG6rW4geMOpdDoqDQotIEPDoWMgdGjDoG5oIHBo4bqnbjoNCg0KICAtIFRy4bulYyB4OiBUaOG7gyBoaeG7h24gY8OhYyBjaOG6pXQgbMaw4bujbmcgY+G6r3Qga2jDoWMgbmhhdSBj4bunYSBraW0gY8awxqFuZywgdOG7qyAiRmFpciIgKGvDqW0pIMSR4bq/biAiSWRlYWwiIChob8OgbiBo4bqjbykuDQogIC0gVHLhu6VjIHk6IFRo4buDIGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIHbhu4sgKG0pIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gKHJvdW5kKG0sIDIpKS4NCiAgLSBD4buZdCBtw6B1IHbDoG5nIG5o4bqhdCAoImxpZ2h0eWVsbG93Iik6IEJp4buDdSB0aOG7iyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IHRydW5nIHbhu4sgY2hvIG3hu5dpIGNo4bqldCBsxrDhu6NuZyBj4bqvdC4NCiAgLSBDaMO6IHRow61jaCB2xINuIGLhuqNuIG3DoHUgaOG7k25nICgicGluayIpOiBIaeG7g24gdGjhu4sgZ2nDoSBraW0gY8awxqFuZyB0cnVuZyB24buLIGNow61uaCB4w6FjICjEkcaw4bujYyBsw6BtIHRyw7JuKSBu4bqxbSB0csOqbiDEkeG7iW5oIG3hu5dpIGPhu5l0LCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIGLhurFuZyB2anVzdCA9IDIgxJHhu4MgdHLDoW5oIGNo4buTbmcgY2jDqW8gbMOqbiBjw6FjIGPhu5l0Lg0KICAtIFThu7FhIMSR4buBICJNZWRpYW4iOiBUaOG7gyBoaeG7h24gdHLDqm4gdHLhu6VjIHksIGNobyBiaeG6v3QgZ2nDoSB0cuG7iyDEkcaw4bujYyBoaeG7g24gdGjhu4sgbMOgIHRydW5nIHbhu4suDQoNCioqKkJp4buDdSDEkeG7kyBj4buZdCB0aOG7gyBoaeG7h24gdHJ1bmcgduG7iyBnacOhIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYyBraW0gY8awxqFuZyAoY29sb3IpKioqDQoNCi0gQmnhu4N1IMSR4buTIG7DoHkgdGjhu4MgaGnhu4duIHRydW5nIHbhu4sgY+G7p2EgZ2nDoSBraW0gY8awxqFuZyB0aGVvIG3DoHUgc+G6r2MgKGNvbG9yKSB0cm9uZyBi4buZIGThu68gbGnhu4d1IGcuDQpgYGB7cn0NCmcgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG09IG1lZGlhbihwcmljZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjb2xvcix5ID0gbSkpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScsIGZpbGw9ICdsaWdodHllbGxvdycpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAncGluaycpICsNCiAgICBsYWJzKHggPSAnY29sb3InLCB5ID0gJ01lZGlhbicpDQpgYGANCipOaOG6rW4geMOpdDoqDQpDw6FjIHRow6BuaCBwaOG6p246DQoNCiAgLSBUcuG7pWMgeDogVGjhu4MgaGnhu4duIGPDoWMgbcOgdSBz4bqvYyBraMOhYyBuaGF1IGPhu6dhIGtpbSBjxrDGoW5nLg0KICAtIFRy4bulYyB5OiBUaOG7gyBoaeG7h24gZ2nDoSBraW0gY8awxqFuZyB0cnVuZyB24buLIChtKSDEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAyIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuIChyb3VuZChtLCAyKSkuDQogIC0gQ+G7mXQgbcOgdSBuw6J1ICgiYnJvd24iKTogQmnhu4N1IHRo4buLIHRy4buNbmcgbMaw4bujbmcgY2FyYXQgdHJ1bmcgduG7iyBjaG8gbeG7l2kgbcOgdSBz4bqvYy4NCiAgLSBDaMO6IHRow61jaCB2xINuIGLhuqNuIG3DoHUgaOG7k25nICgicGluayIpOiBIaeG7g24gdGjhu4sgdHLhu41uZyBsxrDhu6NuZyBjYXJhdCB0cnVuZyB24buLIGNow61uaCB4w6FjICjEkcaw4bujYyBsw6BtIHRyw7JuKSBu4bqxbSB0csOqbiDEkeG7iW5oIG3hu5dpIGPhu5l0LCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIGLhurFuZyB2anVzdCA9IDIgxJHhu4MgdHLDoW5oIGNo4buTbmcgY2jDqW8gbMOqbiBjw6FjIGPhu5l0Lg0KICAtIFThu7FhIMSR4buBICJNZWRpYW4iOiBUaOG7gyBoaeG7h24gdHLDqm4gdHLhu6VjIHksIGNobyBiaeG6v3QgZ2nDoSB0cuG7iyDEkcaw4bujYyBoaeG7g24gdGjhu4sgbMOgIHRydW5nIHbhu4suDQoNCg==