Vẽ biểu
đồ
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.
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.
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%
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.
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.
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.
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 đồ 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.
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.
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.
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.
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.
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ị.
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ị.
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==