GIỚI THIỆU
Bộ dữ liệu DIAMONS là bộ dữ liệu nằm trong packages tidyverse với
53940 quan sát và 10 biến về các
loại kim cương
Các biến bao gồm:
carat: Trọng lượng của kim cương.
cut: Loại cắt của kim cương (Fair, Good, Very Good, Premium,
Ideal).
color: Màu sắc của kim cương, được mã hóa từ D (tốt nhất) đến J (kém
nhất).
clarity: Độ trong suốt của kim cương (IF, VVS1, VVS2, VS1, VS2, SI1,
SI2, I1).
depth: Độ sâu của kim cương, được đo từ mặt bên dưới đến mặt trên,
chia cho chiều dài.
table: Chiều rộng của mặt bên trên của kim cương so với điểm cắt,
chia cho chiều rộng lớn nhất.
price: Giá của kim cương (đơn vị: USD).
x: Chiều dài của kim cương (đơn vị: mm).
y: Chiều rộng của kim cương (đơn vị: mm).
z: Chiều sâu của kim cương (đơn vị: mm).
Và dưới đây là các biểu đồ biểu diễn những thông tin của bộ dữ liệu
để dễ dàng thống kê và phân tích
library(ggplot2)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ lubridate 1.9.3 ✔ tibble 3.2.1
## ✔ purrr 1.0.2 ✔ tidyr 1.3.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(scales)
##
## Attaching package: 'scales'
##
## The following object is masked from 'package:purrr':
##
## discard
##
## The following object is masked from 'package:readr':
##
## col_factor
p <- diamonds
I. Tổng hợp số lượng kim cương theo các biến khác
nhau
1. Hình 1.1: Biểu đồ thể hiện số lượng kim cương theo chất
lượng
p %>% ggplot(aes(x = cut)) +
geom_bar() +
labs(x = 'Loại', y = 'Số lượng')+
coord_flip()

Biểu đồ trên ta có thể thấy được: số lượng kim cương tăng dần theo
mức độ chất lượng từ thấp đến cao, cột cao nhất với chất lượng Ideal có
hơn 20000 đơn vị kim cương; cột thấp nhất với chất lượng Fair chiếm
khoảng 2300 đơn vị
2. Hình 1.2
p %>% group_by(cut ) %>% summarise(n = n()) %>%
ggplot(aes(cut,n)) +
geom_col(fill='orange') +
geom_text(aes(label = n),vjust = 2, color = 'yellow') +
labs(x = 'Loại ', y = 'Số lượng')

Cũng như loại biểu đồ trên biểu đồ dưới đây tổng hợp số lương kim
cương theo chất lương nhưng được cụ thể hơn:
- Kim cương có chất lượng Fair thấp nhất chiếm 1610
- Chất lượng Good chiếm 4906
- Chất lượng Very Good chiếm 12082
- Chất lượng Premium chiếm 13791 và cuối cùng vị trí cao nhất là Ideal
chiếm 21551 đơn vị
3. Hình 1.3: Biểu đồ thể hiện số lượng kim cương theo độ
trong suốt
p %>% ggplot(aes(x = clarity)) +
geom_bar() +
labs(x = 'Loại', y = 'Số lượng') +
coord_flip()

Qua biểu đồ ta thấy được số lượng kim cương theo từng loại cụ
thể:
- Kim cương loại SI1 có số lương cao nhất khoảng hơn 15000 đơn vị
- Kim cương loại I1 thấp nhất chiếm khoảng 1200 đơn vị.
4. Hình 1.4
p %>% group_by(clarity ) %>% summarise(n = n()) %>%
ggplot(aes(clarity,n)) +
geom_col(fill='salmon') +
geom_text(aes(label = n),vjust = 2, color = 'navy') +
labs(x = 'Loại ', y = 'Số lượng')

Biểu đồ 1.4 cho ta thấy kim cương có độ trong suốt cụ thể:
- I1 thấp nhất chiếm 741 đơn vị, SI2 chiếm 9194 đơn vị
- SI1 cao nhất chiếm 13065 đơn vị, VS2 chiếm 12258
- VS1 chiếm 8171, VVS2 chiếm 5066
- VVS1 chiếm 3655, IF chiếm 1790
II. Khối lượng carat trung bình của kim cương
1. Hình 2.1: Biểu đồ khối lượng carat trung bình theo chất
lượng
p %>% group_by(cut) %>% summarise(m= mean(carat)) %>%
ggplot(aes(x = cut,y = m)) +
geom_col(fill='pink') +
geom_text(aes(label = round(m,2)), vjust = 2, color = 'red') +
labs(x = 'Loại', y = 'Mean')

Biểu đồ 2.1 thể hiện khối lượng carat trung bình của các viên kim
cương theo chất lượng được cụ thể:
- Chất lượng Fair khối lượng carat trung bình cao nhất là 1.05
- Chất lượng Good khối lượng carat trung bình là 0.85
- Chất lượng Very Good khối lượng carat trung bình là 0.81
- Chất lượng Premium khối lượng carat trung bình là 0.89; cuối cùng
chất lượng Ideal khối lượng carat trung bình thấp nhất là 0.7
2. Hình 2.2: Biểu đồ khối lượng carat trung bình theo độ
trong suốt
p %>% group_by(clarity) %>% summarise(m= mean(carat)) %>%
ggplot(aes(x = clarity,y = m)) +
geom_col(fill='orchid') +
geom_text(aes(label = round(m,2)), vjust = 2, color = 'brown') +
labs(x = 'Độ trong suốt', y = 'Mean')

Độ trong suốt của kim cương có khối lượng carat trung bình được biểu
diễn bằng số liệu cụ thể:
- Kim cương có độ trong suốt I1 cao nhất với khối lượng carat trung
bình là 1.28
- SI2 có khối lượng carat trung bình là 1.08
- VS2 có khối lượng trung bình là 0.76
- VS1 có khối lượng trung bình là 0.73
- VVS2 có khối lượng trung bình là 0.6
- Kim cương có độ trong suốt VVS1 thấp nhất với khối lượng carat trung
bình là 0.5. Cuối cùng là IF chiếm 0.51
3. Hình 2.3: Biểu đồ khối lượng carat trung bình theo màu
p %>% group_by(color) %>% summarise(m= mean(carat)) %>%
ggplot(aes(x = color,y = m)) +
geom_col(fill='yellow') +
geom_text(aes(label = round(m,2)), vjust = 2, color = 'black') +
labs(x = 'Color', y = 'Mean')

Biểu đồ 2.3 cho thấy khối lượng carat trung bình theo màu J cao nhất
chiếm 1.16, khối lượng carat trung bình D và E thấp nhất chiếm 0.66
4. Hình 2.4: Biểu đồ khối lượng carat trung bình theo chiều
sâu vết cắt
p %>% group_by(depth) %>% summarise(n = n()) %>%
ggplot(aes(depth,n)) +
geom_col(fill='blue') +
labs(x = 'Loại', y = 'Số lượng')

III. Phân tích biểu đồ chỉ phần trăm số lượng theo biến
cut
1. Hình 3.1
p %>% group_by(cut) %>% summarise(n = n()) %>%
ggplot(aes(cut,n)) +
geom_col(fill='salmon') +
geom_text(aes(label = percent(n/length(p$carat))),vjust = 2, color = 'black') +
labs(x = 'Loại', y = 'Số lượng')

- Fair : 3% (chiếm tỉ trọng nhỏ nhất)
- Good : 9,1%
- Very Good : 22,4%
- Premium : 25,6%
- Ideal : 40% (chiếm tỉ trọng lớn nhất )
2. Hình 3.2: Phân tích biểu đồ chỉ phần trăm số lượng theo
biến color
p %>% group_by(color) %>% summarise(n = n()) %>%
ggplot(aes(color,n)) +
geom_col(fill='pink') +
geom_text(aes(label = percent(n/length(p$carat))),vjust = 2, color = 'red') +
labs(x = 'Màu sắc', y = 'Số lượng')

Biểu đồ trên được chia theo biến ‘color’và gồm 7 loại lần lượt là
’D’,‘E’,‘F’,‘G’,‘H’,‘I’,‘G’ trục tung là số lượng kim cương ở từng loại
. Từ đồ thị ta thấy được tỉ trọng của từng loại kim cương :
- D : 12,56%
- E : 18,16%
- F : 17,69%
- G : 20,93%
- H : 15,39% (chiếm tỉ trọng lớn nhất )
- I : 10,05%
- J : 5,21% (chiếm tỉ trọng nhỏ nhất)
3. Hình 3.3: Phân tích đồ biểu đồ chỉ phần trăm số lượng
theo biến clarity
p %>% group_by(clarity) %>% summarise(n = n()) %>%
ggplot(aes(clarity,n)) +
geom_col(fill='yellow') +
geom_text(aes(label = percent(n/length(p$carat))),vjust = 2, color = 'red') +
labs(x = 'Màu sắc', y = 'Số lượng')

Trục tung thể hiện cột số lượng
Trục hoành (màu sắc) gồm I1,SI2,SI1,VS2,VS1,VVS2,VVS1,IF là độ trong
suốt của viên kim cương
Các cột thể hiện phần trăm sồ lượng từng loại trên tổng số kim
cương
Biểu đồ 3.3 cho ta thấy kim cương loại:
- I1 chiếm % thấp nhất là 1.4%
- SI2 chiếm 17%
- SI1 cao nhất chiếm 24.2%
- VS2 chiếm 22.7%
- VS1 chiếm 15.1%
- VVS2 chiếm 9.4%
- VVS1 chiếm 6.8%
- IF chiếm 3.3%
IV. So sánh số lượng giữa các loại kim cương ngẫu
nhiên
1. Hình 4.1: Biểu đồ so sánh số lượng kim cương theo chất
tác có màu D và J
p3 <- p %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
p3 %>% ggplot(aes(x = cut, y = n)) +
geom_col(data = p3 %>% filter(color == 'D'), fill = 'red') +
geom_col(data = p3 %>% filter(color == 'J'), fill = 'blue')

Trục tung (n) thể hiện số lượng kim cương
Trục hoành (cut) thể hiện chất lượng gồm Fair,Good,Very
Good,Premium,Ideal
Cột màu đỏ thể hiện màu D
Cột màu xanh thể hiện màu J
Qua biểu đồ ta thấy có sự chênh lệch khá lớn giữa hai màu kim cương
,cột màu đỏ là kim cương màu D có số lượng gấp đôi kim cương màu J là
cột màu xanh
2. Hình 4.2: Biểu đồ so sánh số lượng kim cương theo chất
lượng chế tác có độ trong suốt VS2 và I1
p1 <- p %>% group_by(cut, clarity) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
p1 %>% ggplot(aes(x = cut, y = n)) +
geom_col(data = p1 %>% filter(clarity == 'VS2'), fill = 'yellow') +
geom_col(data = p1 %>% filter(clarity == 'I1'), fill = 'red')

Trục tung (n) số lượng
Trục hoành (cut) gồm Fair,Good,Very Good,Premium,Ideal
Biểu đồ thể hiện hai loại kim cương khác nhau: cột màu vàng thể hiện
kim cương có độ trong suốt VS2, cột màu đỏ thể hiện kim cương có độ
trong suốt I1 được thống kê theo chất lương chế tác
Quan sát biểu đồ cho ta thấy rõ sự cách biệt lớn về số lượng của hai
loại kim cương trên: kim cương có độ trong suốt VS2 có số lương gấp
nhiều lần so với số lượng kim cương có độ trong suốt I1 => chứng tỏ
trên thị trường loại kim cương có độ trong suốt I1 không đc phổ biến
chiếm thị phần nhỏ trên tổng số.
3. Hình 4.3: Biểu đồ so sánh số lượng kim cương theo màu có
độ trong suốt SI1 và VVS1
p2 <- p %>% group_by(clarity, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
p2 %>% ggplot(aes(x = color, y = n)) +
geom_col(data = p2 %>% filter(clarity == 'SI1'), fill = 'yellow') +
geom_col(data = p2 %>% filter(clarity == 'VVS1'), fill = 'orange')

Trục tung(n) số lượng
Trục hoành (color) gồm các màu D,E,F,G,H,I,J
Biểu đồ thể hiện 2 loại kim cương:
- Cột màu vàng thể hiện kim cương có độ trong suốt SI1
- Cột màu cam thể hiện kim cương có độ trong suốt VVS1
- Nhìn vào biểu đồ ta thấy được kim cương độ trong suốt SI1 chiếm số
lượng nhiều hơn kim cương độ trong suốt VVS1
4. Hình 4.4: Biểu đồ so sánh số lượng kim cương theo màu có
độ trong suốt VS1 và VS2
p2 %>% group_by(clarity, color) %>% summarise(n = n()) %>%
ggplot(aes(x = color, y = n)) +
geom_col(data = p2 %>% filter(clarity == 'VS2'), fill = 'yellow') +
geom_col(data = p2 %>% filter(clarity == 'VS1'), fill = 'salmon')
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.

Biểu đồ 4.4 gồm kim cương có độ trong suốt VS2 cột màu vàng, kim
cương có độ trong suốt VS1 cột màu hồng đậm. Cho thấy kim cương loại VS1
chiếm số lượng nhiều hơn VS2 tuy nhiên số lượng nhiều hơn không đáng
kể
V. So sánh theo nhóm kim cương theo số lượng
1. Hình 5.1: Biểu đồ so sánh nhóm kim cương theo màu và chất
lượng chế tác
Ta có nhóm biểu đồ thể hiện số lượng kim cương theo từng loại chế tác
khác nhau từ đó có thể dễ dàng quan sát so sánh giữa các màu của loại
chế tác này gồm D,E,F,G,H,I,J cùng với các chất lượng Fair,Good, Very
Good, Premium,Ideal
p %>% group_by(cut,color) %>% summarise(n=n(),.groups = 'drop') %>%
ggplot(aes(x = color,y = n)) +
geom_col(fill="black") +
facet_wrap(~cut) +
labs(x = 'Loại', y = 'Số lượng')

Cũng như biểu đồ trên biểu đồ dưới đây cũng giúp ta quan sát và so
sánh những vần đề trên nhưng với câu lệnh geom_text(aes(label =
n),vjust = 2, color = ‘yellow’) ta có thể thấy rõ số liệu một
cách cụ thể.
p %>% group_by(cut,color) %>% summarise(n=n(),.groups = 'drop') %>%
ggplot(aes(x = color,y = n)) +
geom_col( fill= 'purple') +
facet_wrap(~cut) +
geom_text(aes(label = n),vjust = 2, color = 'yellow') +
labs(x = 'Loại', y = 'Số lượng')

2. Hình 5.2: Biểu đồ so sánh nhóm kim cương theo độ trong
suốt và chất lượng chế tác
Ta có nhóm biểu đồ thể hiện số lượng kim cương theo từng loại chế tác
khác nhau từ đó có thể dễ dàng quan sát so sánh giữa các loại độ trong
suốt kim cương của loại chế tác này gồm I1,SI2,SI1,VS2,VS1,VVS2,VVS1,IF
cùng với các chất lượng Fair,Good, Very Good, Premium,Ideal
p %>% group_by(cut,clarity) %>% summarise(n=n(),.groups = 'drop') %>%
ggplot(aes(x = clarity,y = n)) +
geom_col(fill="turquoise") +
facet_wrap(~cut) +
labs(x = 'Loại', y = 'Số lượng')

Cũng như biểu đồ trên biểu đồ dưới đây cũng giúp ta quan sát và so
sánh những vần đề trên nhưng với câu lệnh geom_text(aes(label =
n),vjust = 2, color = ‘red’) ta có thể thấy rõ số liệu một cách
cụ thể.
p %>% group_by(clarity,cut) %>% summarise(n=n(),.groups = 'drop') %>%
ggplot(aes(x = clarity,y = n)) +
geom_col( fill= 'green') +
facet_wrap(~ cut) +
geom_text(aes(label = n),vjust = 2, color = 'red') +
labs(x = 'Loại', y = 'Số lượng')

3. Hình 5.3: Biểu đồ so sánh nhóm kim cương theo màu và độ
trong suốt
Ta có nhóm biểu đồ thể hiện số lượng kim cương theo từng loại trong
suốt khác nhau từ đó có thể dễ dàng quan sát so sánh giữa các màu của
loại trong suốt này gồm D,E,F,G,H,I,J với từng loại trong suốt kia
I1,SI2,SI1,VS2,VS1,VVS2,VVS1,IF
p %>% group_by(clarity,color) %>% summarise(n=n(),.groups = 'drop') %>%
ggplot(aes(x = color,y = n)) +
geom_col(fill="red") +
facet_wrap(~clarity) +
labs(x = 'Loại', y = 'Số lượng')

Cũng như biểu đồ trên biểu đồ dưới đây cũng giúp ta quan sát và so
sánh những vần đề trên nhưng với câu lệnh geom_text(aes(label =
n),vjust = 2, color = ‘white’) ta có thể thấy rõ số liệu một
cách cụ thể.
p %>% group_by(clarity,color) %>% summarise(n=n(),.groups = 'drop') %>%
ggplot(aes(x = color,y = n)) +
geom_col( fill= 'brown') +
facet_wrap(~clarity) +
geom_text(aes(label = n),vjust = 2, color = 'white') +
labs(x = 'Loại', y = 'Số lượng')

VI. So sánh nhóm kim cương theo mức giá trung
bình
1. Hình 6.1: Biểu đồ so sánh nhóm kim cương (màu và chất
lượng chế tác)
p %>% group_by(cut,color) %>% summarise(m = mean(price),.groups = 'drop') %>%
ggplot(aes(x = color,y = m)) +
geom_col(position = 'dodge') +
facet_wrap(~cut ) +
geom_text(aes(label = round(m))) +
labs(x = 'Color ', y = 'Số lượng')

Trục tung thể hiện số lượng
Trục hoành biểu diễn các màu gồm D,E,F,G,H,I,J
Biểu đồ nhóm 6.1 là thống kê mức giá trung bình của từng loại kim
cương chế tác theo tất cả các màu có đầy đủ số liệu trên từng biểu
đồ
2. Hình 6.2: Biểu đồ so sánh nhóm kim cương (độ trong suốt
và chất lượng chế tác)
p %>% group_by(cut,clarity) %>% summarise(m = mean(price), .groups = 'drop') %>%
ggplot(aes(x = clarity,y = m)) +
geom_col(position = 'dodge') +
facet_wrap(~cut ) +
geom_text(aes(label = round(m))) +
labs(x = 'clarity ', y = 'Số lượng')

Biểu đồ 6.2 thể hiện sự so sánh mức giá trung bình của từng loại kim
cương chế tác theo màu và độ
trong suốt
3. Hình 6.3: Biểu đồ so sánh nhóm kim cương (màu và độ trong
suốt)
p %>% group_by(clarity,color) %>% summarise(m = mean(price), .groups='drop') %>%
ggplot(aes(x = color,y = m)) +
geom_col(position = 'dodge') +
facet_wrap(~clarity) +
geom_text(aes(label = round(m))) +
labs(x = 'Color ', y = 'Số lượng')

Biểu đồ 6.3 thể hiện sự so sánh mức giá trung bình của từng loại kim
cương chế tác theo tất cả các độ
trong suốt và màu
VII. Phân tích số lượng kim cương theo mức giá và khối lượng
carat
1. Hình 7.1: BIểu đồ phân tích số lượng kim cương theo khối
lượng
p <-p %>% mutate(Carat = cut(carat,5, label = c('rất nhỏ', 'nhỏ','vừa','lớn','rất lớn')))
p %>% ggplot(aes(x = Carat)) +
geom_bar(fill = 'salmon')

Biểu đồ 7.1 cho thấy khối lượng carat được chia làm 5 loại: rất nhỏ,
nhỏ, vừa,lớn,rất lớn. Loại rất nhỏ chiếm số lượng nhiều nhất, trong khi
đó loại lớn và rất lớn hầu như là không có. Vậy trên thị trường carat
loại lớn và rất lớn là cực kì hiếm so với các loại còn lại
2. Hình 7.2: BIểu đồ phân tích số lượng kim cương theo mức
giá
p <- p %>% mutate(Price = cut(price,5, label = c('rất thấp ', 'thấp','tb','cao','rất cao')))
p %>% ggplot(aes(x = Price)) +
geom_bar(fill = 'pink')

Trục tung(count) thể hiện mức giá
Trục hoành(price) gồm rất thấp, thấp, trung bình, cao, rất cao
Biểu đồ 7.2 cho ta thấy mức giá kim cương nằm ở trục tung thể hiện
mức giá loại rất nhỏ thấp hơn các loại còn lại rất nhiều lần, kim cương
loại rất lớn thì hiếm nên giá sẽ cao hơn
3. Hình 7.3
p <- p %>% mutate(color_code = case_when(
color == "D" | color == "E" | color == "F" ~ 1,
color == "G" | color == "H" | color == "I" | color == "J" ~ 2))
p <- mutate(p, colorC = cut(color_code, 2, label = c('không màu', 'gần như không màu')))
p %>% group_by(colorC) %>% summarise(n=n()) %>%
ggplot(aes(colorC, n)) +
geom_col(fill = 'red') +
geom_text(aes(label = n), vjust = 0, color = 'black') +
xlab('Màu sắc') +
ylab('Số lượng (viên)') +
labs()

Trục tung thể hiện số lượng
Trục hoành thể hiện màu săc gồm không màu và gần như không màu
Ta thấy được số lượng viên gần như không màu chiếm số lượng nhiều hơn
vì thế phần lớn carat có dạng trong suốt
4. Hình 7.4
p <- diamonds
p <- p %>% mutate(depthC = cut(depth,5, label = c('Sâu','Khá sâu','Trung bình','Khá nông','Nông')))
p %>% ggplot(aes(x = depthC)) +
geom_bar(fill = 'red')

Biểu đồ 7.4 thể hiện độ nông sâu khi cắt viên kim cương
VIII. Biểu đồ các chỉ số cụ thể theo từng biến
2. Hình 8.2: Mean (giá trị trung bình) của biến
‘price’
p %>% group_by(cut) %>% summarise(m= mean(price)) %>%
ggplot(aes(x = cut,y = m)) +
geom_col(position = 'dodge') +
geom_text(aes(label = round(m,2)), vjust = 2, color = 'yellow') +
labs(x = 'Loại', y = 'Mean')

Câu lệnh trên cho ta một đồ thị dạng Bar Chart với trục hoành là các
loại kim cương được chia theo biến ‘cut’ bao gồm 5 loại lần lượt là
‘Fair’,‘Good’,‘Very Good’,‘Premium’,‘Ideal’, trục tung là trung bình độ
lớn của biến ‘Price’ . Cụ thể như sau:
- Kim cương Fair có độ lớn trung bình của biến ‘Price’ là :
4358.76
- Kim cương Good có độ lớn trung bình của biến ‘Price’ là :
3928.86
- Kim cương Very Good có độ lớn trung bình của biến ‘Price’ là :
3981.76
- Kim cương Premium có độ lớn trung bình của biến ‘Price’ là :
4584.26
- Kim cương Ideal có độ lớn trung bình của biến ‘Price’ là :
3457.54
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA0Ig0KYXV0aG9yOiAiTMOqIFRo4buLIFRoYW5oIFBow7oiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclSDolTTolUywgJWQgLSAlbSAtICVZJylgIg0Kb3V0cHV0Og0KICAgIGh0bWxfZG9jdW1lbnQ6IA0KICAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICAgICB0b2M6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIyAqKkdJ4buaSSBUSEnhu4ZVKiogDQpC4buZIGThu68gbGnhu4d1ICBESUFNT05TIGzDoCBi4buZIGThu68gbGnhu4d1IG7hurFtIHRyb25nIHBhY2thZ2VzIHRpZHl2ZXJzZSB24bubaSA1Mzk0MCBxdWFuIHPDoXQgdsOgIDEwIGJp4bq/biB24buBIGPDoWMNCg0KbG/huqFpIGtpbSBjxrDGoW5nDQoNCkPDoWMgYmnhur9uIGJhbyBn4buTbToNCg0KY2FyYXQ6IFRy4buNbmcgbMaw4bujbmcgY+G7p2Ega2ltIGPGsMahbmcuDQoNCmN1dDogTG/huqFpIGPhuq90IGPhu6dhIGtpbSBjxrDGoW5nIChGYWlyLCBHb29kLCBWZXJ5IEdvb2QsIFByZW1pdW0sIElkZWFsKS4NCg0KY29sb3I6IE3DoHUgc+G6r2MgY+G7p2Ega2ltIGPGsMahbmcsIMSRxrDhu6NjIG3DoyBow7NhIHThu6sgRCAodOG7kXQgbmjhuqV0KSDEkeG6v24gSiAoa8OpbSBuaOG6pXQpLg0KDQpjbGFyaXR5OiDEkOG7mSB0cm9uZyBzdeG7kXQgY+G7p2Ega2ltIGPGsMahbmcgKElGLCBWVlMxLCBWVlMyLCBWUzEsIFZTMiwgU0kxLCBTSTIsIEkxKS4NCg0KZGVwdGg6IMSQ4buZIHPDonUgY+G7p2Ega2ltIGPGsMahbmcsIMSRxrDhu6NjIMSRbyB04burIG3hurd0IGLDqm4gZMaw4bubaSDEkeG6v24gbeG6t3QgdHLDqm4sIGNoaWEgY2hvIGNoaeG7gXUgZMOgaS4NCg0KdGFibGU6IENoaeG7gXUgcuG7mW5nIGPhu6dhIG3hurd0IGLDqm4gdHLDqm4gY+G7p2Ega2ltIGPGsMahbmcgc28gduG7m2kgxJFp4buDbSBj4bqvdCwgY2hpYSBjaG8gY2hp4buBdSBy4buZbmcgbOG7m24gbmjhuqV0Lg0KDQpwcmljZTogR2nDoSBj4bunYSBraW0gY8awxqFuZyAoxJHGoW4gduG7izogVVNEKS4NCg0KeDogQ2hp4buBdSBkw6BpIGPhu6dhIGtpbSBjxrDGoW5nICjEkcahbiB24buLOiBtbSkuDQoNCnk6IENoaeG7gXUgcuG7mW5nIGPhu6dhIGtpbSBjxrDGoW5nICjEkcahbiB24buLOiBtbSkuDQoNCno6IENoaeG7gXUgc8OidSBj4bunYSBraW0gY8awxqFuZyAoxJHGoW4gduG7izogbW0pLg0KDQpWw6AgZMaw4bubaSDEkcOieSBsw6AgY8OhYyBiaeG7g3UgxJHhu5MgYmnhu4N1IGRp4buFbiBuaOG7r25nIHRow7RuZyB0aW4gY+G7p2EgYuG7mSBk4buvIGxp4buHdSDEkeG7gyBk4buFIGTDoG5nIHRo4buRbmcga8OqIHbDoCBwaMOibiB0w61jaCANCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2NhbGVzKQ0KcCA8LSBkaWFtb25kcw0KYGBgDQoNCiMjICoqSS4gVOG7lW5nIGjhu6NwIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjw6FjIGJp4bq/biBraMOhYyBuaGF1KioNCg0KIyMjICoqMS4gSMOsbmggMS4xOiBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgKioNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KcCAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0KSkgKw0KICAgIGdlb21fYmFyKCkgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKSsNCiAgICBjb29yZF9mbGlwKCkNCmBgYCANCg0KDQoNCkJp4buDdSDEkeG7kyB0csOqbiB0YSBjw7MgdGjhu4MgdGjhuqV5IMSRxrDhu6NjOiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHTEg25nIGThuqduIHRoZW8gbeG7qWMgxJHhu5kgY2jhuqV0IGzGsOG7o25nICB04burIHRo4bqlcCDEkeG6v24gY2FvLCBj4buZdCBjYW8gbmjhuqV0IHbhu5tpIGNo4bqldCBsxrDhu6NuZyBJZGVhbCBjw7MgaMahbiAgMjAwMDAgxJHGoW4gduG7iyBraW0gY8awxqFuZzsgY+G7mXQgdGjhuqVwIG5o4bqldCB24bubaSBjaOG6pXQgbMaw4bujbmcgRmFpciBjaGnhur9tIGtob+G6o25nIDIzMDAgxJHGoW4gduG7iw0KDQojIyMgKioyLiBIw6xuaCAxLjIqKg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQpwICU+JSBncm91cF9ieShjdXQgKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J29yYW5nZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICd5ZWxsb3cnKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaSAnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCg0KDQpDxaluZyBuaMawIGxv4bqhaSBiaeG7g3UgxJHhu5MgdHLDqm4gYmnhu4N1IMSR4buTIGTGsOG7m2kgxJHDonkgdOG7lW5nIGjhu6NwIHPhu5EgbMawxqFuZyBraW0gY8awxqFuZyB0aGVvIGNo4bqldCBsxrDGoW5nIG5oxrBuZyDEkcaw4bujYyBj4bulIHRo4buDIGjGoW46DQoNCisgS2ltIGPGsMahbmcgY8OzIGNo4bqldCBsxrDhu6NuZyBGYWlyIHRo4bqlcCBuaOG6pXQgY2hp4bq/bSAxNjEwICANCisgQ2jhuqV0IGzGsOG7o25nIEdvb2QgY2hp4bq/bSA0OTA2ICANCisgQ2jhuqV0IGzGsOG7o25nIFZlcnkgR29vZCBjaGnhur9tIDEyMDgyICANCisgQ2jhuqV0IGzGsOG7o25nIFByZW1pdW0gY2hp4bq/bSAxMzc5MSB2w6AgY3Xhu5FpIGPDuW5nIHbhu4sgdHLDrSBjYW8gbmjhuqV0IGzDoCBJZGVhbCBjaGnhur9tIDIxNTUxIMSRxqFuIHbhu4sgIA0KDQoNCiMjIyAqKjMuIEjDrG5oIDEuMzogQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gxJHhu5kgdHJvbmcgc3Xhu5F0KioNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KcCAlPiUgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSkpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykgKw0KICAgIGNvb3JkX2ZsaXAoKQ0KYGBgIA0KDQoNCg0KUXVhIGJp4buDdSDEkeG7kyB0YSB0aOG6pXkgxJHGsOG7o2Mgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBsb+G6oWkgY+G7pSB0aOG7gzoNCg0KKyBLaW0gY8awxqFuZyBsb+G6oWkgU0kxIGPDsyBz4buRIGzGsMahbmcgY2FvIG5o4bqldCBraG/huqNuZyBoxqFuIDE1MDAwIMSRxqFuIHbhu4sNCisgS2ltIGPGsMahbmcgbG/huqFpIEkxIHRo4bqlcCBuaOG6pXQgY2hp4bq/bSBraG/huqNuZyAxMjAwIMSRxqFuIHbhu4suDQoNCiMjIyAqKjQuIEjDrG5oIDEuNCoqDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnAgJT4lIGdyb3VwX2J5KGNsYXJpdHkgKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGNsYXJpdHksbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdzYWxtb24nKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnbmF2eScpICsNCiAgICBsYWJzKHggPSAnTG/huqFpICcsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KDQoNCkJp4buDdSDEkeG7kyAxLjQgY2hvIHRhIHRo4bqleSBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IGPhu6UgdGjhu4M6DQoNCisgSTEgdGjhuqVwIG5o4bqldCBjaGnhur9tIDc0MSDEkcahbiB24buLLCBTSTIgY2hp4bq/bSA5MTk0IMSRxqFuIHbhu4sNCisgU0kxIGNhbyBuaOG6pXQgY2hp4bq/bSAxMzA2NSDEkcahbiB24buLLCBWUzIgY2hp4bq/bSAxMjI1OA0KKyBWUzEgY2hp4bq/bSA4MTcxLCBWVlMyIGNoaeG6v20gNTA2Ng0KKyBWVlMxIGNoaeG6v20gMzY1NSwgSUYgY2hp4bq/bSAxNzkwDQoNCiMjICoqSUkuIEto4buRaSBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyAqKg0KDQojIyMgKioxLiBIw6xuaCAyLjE6IEJp4buDdSDEkeG7kyBraOG7kWkgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggdGhlbyBjaOG6pXQgbMaw4bujbmcgKiogDQoNCmBgYHtyfQ0KcCAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBtKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3BpbmsnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdNZWFuJykNCmBgYA0KDQoNCg0KQmnhu4N1IMSR4buTIDIuMSB0aOG7gyBoaeG7h24ga2jhu5FpIGzGsOG7o25nIGNhcmF0IHRydW5nIGLDrG5oIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgxJHGsOG7o2MgY+G7pSB0aOG7gzoNCg0KKyBDaOG6pXQgbMaw4bujbmcgRmFpciBraOG7kWkgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggY2FvIG5o4bqldCBsw6AgMS4wNSAgDQorIENo4bqldCBsxrDhu6NuZyBHb29kIGto4buRaSBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCBsw6AgMC44NQ0KKyBDaOG6pXQgbMaw4bujbmcgVmVyeSBHb29kIGto4buRaSBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCBsw6AgMC44MQ0KKyBDaOG6pXQgbMaw4bujbmcgUHJlbWl1bSBraOG7kWkgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggbMOgIDAuODk7IGN14buRaSBjw7luZyBjaOG6pXQgbMaw4bujbmcgSWRlYWwga2jhu5FpIGzGsOG7o25nIGNhcmF0IHRydW5nIGLDrG5oIHRo4bqlcCBuaOG6pXQgbMOgIDAuNw0KDQojIyMgKioyLiBIw6xuaCAyLjI6IEJp4buDdSDEkeG7kyBraOG7kWkgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggdGhlbyDEkeG7mSB0cm9uZyBzdeG7kXQgKioNCg0KYGBge3J9DQpwICU+JSBncm91cF9ieShjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSx5ID0gbSkpICsNCiAgICBnZW9tX2NvbChmaWxsPSdvcmNoaWQnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ2Jyb3duJykgKw0KICAgIGxhYnMoeCA9ICfEkOG7mSB0cm9uZyBzdeG7kXQnLCB5ID0gJ01lYW4nKQ0KYGBgDQoNCg0KDQrEkOG7mSB0cm9uZyBzdeG7kXQgY+G7p2Ega2ltIGPGsMahbmcgY8OzIGto4buRaSBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCDEkcaw4bujYyBiaeG7g3UgZGnhu4VuIGLhurFuZyBz4buRIGxp4buHdSBj4bulIHRo4buDOg0KDQorIEtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgSTEgY2FvIG5o4bqldCB24bubaSBraOG7kWkgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggbMOgIDEuMjgNCisgU0kyIGPDsyBraOG7kWkgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggbMOgIDEuMDgNCisgVlMyIGPDsyBraOG7kWkgbMaw4bujbmcgdHJ1bmcgYsOsbmggbMOgIDAuNzYNCisgVlMxIGPDsyBraOG7kWkgbMaw4bujbmcgdHJ1bmcgYsOsbmggbMOgIDAuNzMNCisgVlZTMiBjw7Mga2jhu5FpIGzGsOG7o25nIHRydW5nIGLDrG5oIGzDoCAwLjYNCisgS2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCBWVlMxIHRo4bqlcCBuaOG6pXQgduG7m2kga2jhu5FpIGzGsOG7o25nIGNhcmF0IHRydW5nIGLDrG5oIGzDoCAwLjUuIEN14buRaSBjw7luZyBsw6AgSUYgY2hp4bq/bSAwLjUxDQoNCiMjIyAqKjMuIEjDrG5oIDIuMzogQmnhu4N1IMSR4buTIGto4buRaSBsxrDhu6NuZyBjYXJhdCB0cnVuZyBiw6xuaCB0aGVvIG3DoHUgKioNCmBgYHtyfQ0KcCAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobT0gbWVhbihjYXJhdCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjb2xvcix5ID0gbSkpICsNCiAgICBnZW9tX2NvbChmaWxsPSd5ZWxsb3cnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICdDb2xvcicsIHkgPSAnTWVhbicpDQpgYGANCg0KDQpCaeG7g3UgxJHhu5MgMi4zIGNobyB0aOG6pXkga2jhu5FpIGzGsOG7o25nIGNhcmF0IHRydW5nIGLDrG5oIHRoZW8gbcOgdSBKIGNhbyBuaOG6pXQgY2hp4bq/bSAxLjE2LCBraOG7kWkgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggRCB2w6AgRSB0aOG6pXAgbmjhuqV0IGNoaeG6v20gMC42Ng0KDQojIyMgKio0LiBIw6xuaCAyLjQ6IEJp4buDdSDEkeG7kyBraOG7kWkgbMaw4bujbmcgY2FyYXQgdHJ1bmcgYsOsbmggdGhlbyBjaGnhu4F1IHPDonUgduG6v3QgY+G6r3QgKioNCmBgYHtyfQ0KcCAlPiUgZ3JvdXBfYnkoZGVwdGgpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoZGVwdGgsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdibHVlJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiMjICoqSUlJLiBQaMOibiB0w61jaCBiaeG7g3UgxJHhu5MgY2jhu4kgcGjhuqduIHRyxINtIHPhu5EgbMaw4bujbmcgdGhlbyBiaeG6v24gY3V0KioNCg0KIyMjICoqMS4gSMOsbmggMy4xKioNCmBgYHtyfQ0KcCAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3NhbG1vbicpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGVyY2VudChuL2xlbmd0aChwJGNhcmF0KSkpLHZqdXN0ID0gMiwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKyBGYWlyIDogMyUgKGNoaeG6v20gdOG7iSB0cuG7jW5nIG5o4buPIG5o4bqldCkNCisgR29vZCA6IDksMSUNCisgVmVyeSBHb29kIDogMjIsNCUNCisgUHJlbWl1bSA6IDI1LDYlDQorIElkZWFsIDogNDAlIChjaGnhur9tIHThu4kgdHLhu41uZyBs4bubbiBuaOG6pXQgKQ0KDQojIyMgKioyLiBIw6xuaCAzLjI6IFBow6JuIHTDrWNoIGJp4buDdSDEkeG7kyBjaOG7iSBwaOG6p24gdHLEg20gc+G7kSBsxrDhu6NuZyB0aGVvIGJp4bq/biBjb2xvcioqDQoNCmBgYHtyfQ0KcCAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY29sb3IsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdwaW5rJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKHAkY2FyYXQpKSksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgbGFicyh4ID0gJ03DoHUgc+G6r2MnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCg0KDQpCaeG7g3UgxJHhu5MgdHLDqm4gxJHGsOG7o2MgY2hpYSB0aGVvIGJp4bq/biDigJhjb2xvcuKAmXbDoCBn4buTbSA3IGxv4bqhaSBs4bqnbiBsxrDhu6N0IGzDoCDigJlE4oCZLOKAmEXigJks4oCYRuKAmSzigJhH4oCZLOKAmEjigJks4oCYSeKAmSzigJhH4oCZIHRy4bulYyB0dW5nIGzDoCBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIOG7nyB04burbmcgbG/huqFpIC4gVOG7qyDEkeG7kyB0aOG7iyB0YSB0aOG6pXkgxJHGsOG7o2MgdOG7iSB0cuG7jW5nIGPhu6dhIHThu6tuZyBsb+G6oWkga2ltIGPGsMahbmcgOg0KDQorIEQgOiAxMiw1NiUNCisgRSA6IDE4LDE2JQ0KKyBGIDogMTcsNjklDQorIEcgOiAyMCw5MyUNCisgSCA6IDE1LDM5JSAoY2hp4bq/bSB04buJIHRy4buNbmcgbOG7m24gbmjhuqV0ICkNCisgSSA6IDEwLDA1JQ0KKyBKIDogNSwyMSUgKGNoaeG6v20gdOG7iSB0cuG7jW5nIG5o4buPIG5o4bqldCkNCg0KIyMjICoqMy4gSMOsbmggMy4zOiBQaMOibiB0w61jaCDEkeG7kyBiaeG7g3UgxJHhu5MgY2jhu4kgcGjhuqduIHRyxINtIHPhu5EgbMaw4bujbmcgdGhlbyBiaeG6v24gY2xhcml0eSoqDQpgYGB7cn0NCnAgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY2xhcml0eSxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3llbGxvdycpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGVyY2VudChuL2xlbmd0aChwJGNhcmF0KSkpLHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICdNw6B1IHPhuq9jJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQpUcuG7pWMgdHVuZyB0aOG7gyBoaeG7h24gY+G7mXQgc+G7kSBsxrDhu6NuZw0KDQpUcuG7pWMgaG/DoG5oIChtw6B1IHPhuq9jKSBn4buTbSBJMSxTSTIsU0kxLFZTMixWUzEsVlZTMixWVlMxLElGIGzDoCDEkeG7mSB0cm9uZyBzdeG7kXQgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcNCg0KQ8OhYyBj4buZdCB0aOG7gyBoaeG7h24gcGjhuqduIHRyxINtIHPhu5MgbMaw4bujbmcgdOG7q25nIGxv4bqhaSB0csOqbiB04buVbmcgc+G7kSBraW0gY8awxqFuZw0KDQpCaeG7g3UgxJHhu5MgMy4zIGNobyB0YSB0aOG6pXkga2ltIGPGsMahbmcgbG/huqFpOg0KDQorIEkxIGNoaeG6v20gJSB0aOG6pXAgbmjhuqV0IGzDoCAxLjQlDQorIFNJMiBjaGnhur9tIDE3JQ0KKyBTSTEgY2FvIG5o4bqldCBjaGnhur9tIDI0LjIlDQorIFZTMiBjaGnhur9tIDIyLjclDQorIFZTMSBjaGnhur9tIDE1LjElDQorIFZWUzIgY2hp4bq/bSA5LjQlDQorIFZWUzEgY2hp4bq/bSA2LjglDQorIElGIGNoaeG6v20gMy4zJQ0KDQojIyAqKklWLiBTbyBzw6FuaCBz4buRIGzGsOG7o25nIGdp4buvYSBjw6FjIGxv4bqhaSAga2ltIGPGsMahbmcgbmfhuqt1IG5oacOqbioqDQoNCiMjIyAqKjEuIEjDrG5oIDQuMTogQmnhu4N1IMSR4buTIHNvIHPDoW5oIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgdMOhYyBjw7MgbcOgdSBEIHbDoCBKKioNCg0KYGBge3J9DQpwMyA8LSBwICU+JSBncm91cF9ieShjdXQsIGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpIA0KcDMgJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSBwMyAlPiUgZmlsdGVyKGNvbG9yID09ICdEJyksIGZpbGwgPSAncmVkJykgKw0KICBnZW9tX2NvbChkYXRhID0gcDMgJT4lIGZpbHRlcihjb2xvciA9PSAnSicpLCBmaWxsID0gJ2JsdWUnKQ0KYGBgDQoNClRy4bulYyB0dW5nIChuKSB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZw0KDQpUcuG7pWMgaG/DoG5oIChjdXQpIHRo4buDIGhp4buHbiBjaOG6pXQgbMaw4bujbmcgZ+G7k20gRmFpcixHb29kLFZlcnkgR29vZCxQcmVtaXVtLElkZWFsDQoNCkPhu5l0IG3DoHUgxJHhu48gdGjhu4MgaGnhu4duIG3DoHUgRA0KDQpD4buZdCBtw6B1IHhhbmggdGjhu4MgaGnhu4duIG3DoHUgSg0KDQoNClF1YSBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IGPDsyBz4buxIGNow6puaCBs4buHY2gga2jDoSBs4bubbiBnaeG7r2EgaGFpIG3DoHUga2ltIGPGsMahbmcgLGPhu5l0IG3DoHUgxJHhu48gbMOgIGtpbSBjxrDGoW5nIG3DoHUgRCBjw7Mgc+G7kSBsxrDhu6NuZyBn4bqlcCDEkcO0aSBraW0gY8awxqFuZyAgbcOgdSBKIGzDoCBj4buZdCBtw6B1IHhhbmggDQoNCiMjIyAqKjIuIEjDrG5oIDQuMjogQmnhu4N1IMSR4buTIHNvIHPDoW5oIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY2jhur8gdMOhYyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IFZTMiB2w6AgSTEqKg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KcDEgPC0gcCAlPiUgZ3JvdXBfYnkoY3V0LCBjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpIA0KcDEgJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSBwMSAlPiUgZmlsdGVyKGNsYXJpdHkgPT0gJ1ZTMicpLCBmaWxsID0gJ3llbGxvdycpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHAxICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnSTEnKSwgZmlsbCA9ICdyZWQnKQ0KYGBgDQoNClRy4bulYyB0dW5nIChuKSBz4buRIGzGsOG7o25nDQoNClRy4bulYyBob8OgbmggKGN1dCkgZ+G7k20gRmFpcixHb29kLFZlcnkgR29vZCxQcmVtaXVtLElkZWFsDQoNCkJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gaGFpIGxv4bqhaSBraW0gY8awxqFuZyBraMOhYyBuaGF1OiBj4buZdCBtw6B1IHbDoG5nIHRo4buDIGhp4buHbiBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IFZTMiwgY+G7mXQgbcOgdSDEkeG7jyB0aOG7gyBoaeG7h24ga2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCBJMSDEkcaw4bujYyB0aOG7kW5nIGvDqiB0aGVvIGNo4bqldCBsxrDGoW5nIGNo4bq/IHTDoWMgDQoNClF1YW4gc8OhdCBiaeG7g3UgxJHhu5MgY2hvIHRhIHRo4bqleSByw7Ugc+G7sSBjw6FjaCBiaeG7h3QgbOG7m24gduG7gSBz4buRIGzGsOG7o25nIGPhu6dhIGhhaSBsb+G6oWkga2ltIGPGsMahbmcgdHLDqm46IGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgVlMyIGPDsyBz4buRIGzGsMahbmcgZ+G6pXAgbmhp4buBdSBs4bqnbiBzbyB24bubaSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgSTEgPT4gY2jhu6luZyB04buPIHRyw6puIHRo4buLIHRyxrDhu51uZyBsb+G6oWkga2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCBJMSBraMO0bmcgxJFjIHBo4buVIGJp4bq/biBjaGnhur9tIHRo4buLIHBo4bqnbiBuaOG7jyB0csOqbiB04buVbmcgc+G7kS4NCg0KIyMjICoqMy4gSMOsbmggNC4zOiBCaeG7g3UgxJHhu5Mgc28gc8Ohbmggc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIG3DoHUgY8OzIMSR4buZIHRyb25nIHN14buRdCBTSTEgdsOgIFZWUzEqKg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQpwMiA8LSBwICU+JSBncm91cF9ieShjbGFyaXR5LCBjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KcDIgJT4lIGdncGxvdChhZXMoeCA9IGNvbG9yLCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHAyICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnU0kxJyksIGZpbGwgPSAneWVsbG93JykgKw0KICBnZW9tX2NvbChkYXRhID0gcDIgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdWVlMxJyksIGZpbGwgPSAnb3JhbmdlJykNCmBgYA0KDQpUcuG7pWMgdHVuZyhuKSBz4buRIGzGsOG7o25nDQoNClRy4bulYyBob8OgbmggKGNvbG9yKSBn4buTbSBjw6FjIG3DoHUgRCxFLEYsRyxILEksSg0KDQpCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIDIgbG/huqFpIGtpbSBjxrDGoW5nOg0KDQorIEPhu5l0IG3DoHUgdsOgbmcgdGjhu4MgaGnhu4duIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgU0kxDQorIEPhu5l0IG3DoHUgY2FtIHRo4buDIGhp4buHbiBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IFZWUzENCisgTmjDrG4gdsOgbyBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IMSRxrDhu6NjIGtpbSBjxrDGoW5nIMSR4buZIHRyb25nIHN14buRdCBTSTEgY2hp4bq/bSBz4buRIGzGsOG7o25nIG5oaeG7gXUgaMahbiBraW0gY8awxqFuZyDEkeG7mSB0cm9uZyBzdeG7kXQgVlZTMQ0KDQojIyMgKio0LiBIw6xuaCA0LjQ6IEJp4buDdSDEkeG7kyBzbyBzw6FuaCBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IFZTMSB2w6AgVlMyKioNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KcDIgJT4lIGdyb3VwX2J5KGNsYXJpdHksIGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JSANCmdncGxvdChhZXMoeCA9IGNvbG9yLCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHAyICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnVlMyJyksIGZpbGwgPSAneWVsbG93JykgKw0KICBnZW9tX2NvbChkYXRhID0gcDIgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdWUzEnKSwgZmlsbCA9ICdzYWxtb24nKQ0KYGBgDQoNCg0KDQpCaeG7g3UgxJHhu5MgNC40IGfhu5NtIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgVlMyIGPhu5l0IG3DoHUgdsOgbmcsIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgVlMxIGPhu5l0IG3DoHUgaOG7k25nIMSR4bqtbS4gQ2hvIHRo4bqleSBraW0gY8awxqFuZyBsb+G6oWkgVlMxIGNoaeG6v20gc+G7kSBsxrDhu6NuZyBuaGnhu4F1IGjGoW4gVlMyIHR1eSBuaGnDqm4gc+G7kSBsxrDhu6NuZyBuaGnhu4F1IGjGoW4ga2jDtG5nIMSRw6FuZyBr4buDDQoNCiMjICoqVi4gU28gc8OhbmggdGhlbyBuaMOzbSBraW0gY8awxqFuZyB0aGVvIHPhu5EgbMaw4bujbmcqKg0KDQojIyMgKioxLiBIw6xuaCA1LjE6IEJp4buDdSDEkeG7kyBzbyBzw6FuaCBuaMOzbSBraW0gY8awxqFuZyB0aGVvIG3DoHUgdsOgIGNo4bqldCBsxrDhu6NuZyBjaOG6vyB0w6FjKioNCg0KVGEgY8OzIG5ow7NtIGJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBsb+G6oWkgY2jhur8gdMOhYyBraMOhYyBuaGF1IHThu6sgxJHDsyBjw7MgdGjhu4MgZOG7hSBkw6BuZyBxdWFuIHPDoXQgc28gc8OhbmggZ2nhu69hIGPDoWMgbcOgdSBj4bunYSBsb+G6oWkgY2jhur8gdMOhYyBuw6B5IGfhu5NtIEQsRSxGLEcsSCxJLEogY8O5bmcgduG7m2kgY8OhYyBjaOG6pXQgbMaw4bujbmcgRmFpcixHb29kLCBWZXJ5IEdvb2QsIFByZW1pdW0sSWRlYWwNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KcCAlPiUgZ3JvdXBfYnkoY3V0LGNvbG9yKSAlPiUgc3VtbWFyaXNlKG49bigpLC5ncm91cHMgPSAnZHJvcCcpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjb2xvcix5ID0gbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSJibGFjayIpICsNCiAgICBmYWNldF93cmFwKH5jdXQpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoNCg0KQ8WpbmcgbmjGsCBiaeG7g3UgxJHhu5MgdHLDqm4gYmnhu4N1IMSR4buTIGTGsOG7m2kgxJHDonkgY8WpbmcgZ2nDunAgdGEgcXVhbiBzw6F0IHbDoCBzbyBzw6FuaCBuaOG7r25nIHbhuqduIMSR4buBIHRyw6puIG5oxrBuZyB24bubaSBjw6J1IGzhu4duaCAqKmdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDIsIGNvbG9yID0gJ3llbGxvdycpKiogdGEgY8OzIHRo4buDIHRo4bqleSByw7Ugc+G7kSBsaeG7h3UgbeG7mXQgY8OhY2ggY+G7pSB0aOG7gy4NCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KcCAlPiUgZ3JvdXBfYnkoY3V0LGNvbG9yKSAlPiUgc3VtbWFyaXNlKG49bigpLC5ncm91cHMgPSAnZHJvcCcpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjb2xvcix5ID0gbikpICsNCiAgICBnZW9tX2NvbCggZmlsbD0gJ3B1cnBsZScpICsNCiAgICBmYWNldF93cmFwKH5jdXQpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICd5ZWxsb3cnKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KDQojIyMgKioyLiBIw6xuaCA1LjI6IEJp4buDdSDEkeG7kyBzbyBzw6FuaCBuaMOzbSBraW0gY8awxqFuZyB0aGVvIMSR4buZIHRyb25nIHN14buRdCB2w6AgY2jhuqV0IGzGsOG7o25nIGNo4bq/IHTDoWMqKg0KDQpUYSBjw7MgbmjDs20gYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gdOG7q25nIGxv4bqhaSBjaOG6vyB0w6FjIGtow6FjIG5oYXUgdOG7qyDEkcOzIGPDsyB0aOG7gyBk4buFIGTDoG5nIHF1YW4gc8OhdCBzbyBzw6FuaCBnaeG7r2EgY8OhYyBsb+G6oWkgxJHhu5kgdHJvbmcgc3Xhu5F0IGtpbSBjxrDGoW5nIGPhu6dhIGxv4bqhaSBjaOG6vyB0w6FjIG7DoHkgZ+G7k20gSTEsU0kyLFNJMSxWUzIsVlMxLFZWUzIsVlZTMSxJRiBjw7luZyB24bubaSBjw6FjIGNo4bqldCBsxrDhu6NuZyBGYWlyLEdvb2QsIFZlcnkgR29vZCwgUHJlbWl1bSxJZGVhbA0KDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnAgJT4lIGdyb3VwX2J5KGN1dCxjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG49bigpLC5ncm91cHMgPSAnZHJvcCcpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjbGFyaXR5LHkgPSBuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9InR1cnF1b2lzZSIpICsNCiAgICBmYWNldF93cmFwKH5jdXQpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoNCg0KQ8WpbmcgbmjGsCBiaeG7g3UgxJHhu5MgdHLDqm4gYmnhu4N1IMSR4buTIGTGsOG7m2kgxJHDonkgY8WpbmcgZ2nDunAgdGEgcXVhbiBzw6F0IHbDoCBzbyBzw6FuaCBuaOG7r25nIHbhuqduIMSR4buBIHRyw6puIG5oxrBuZyB24bubaSBjw6J1IGzhu4duaCAqKmdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpKiogdGEgY8OzIHRo4buDIHRo4bqleSByw7Ugc+G7kSBsaeG7h3UgbeG7mXQgY8OhY2ggY+G7pSB0aOG7gy4NCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KcCAlPiUgZ3JvdXBfYnkoY2xhcml0eSxjdXQpICU+JSBzdW1tYXJpc2Uobj1uKCksLmdyb3VwcyA9ICdkcm9wJykgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG4pKSArDQogICAgZ2VvbV9jb2woIGZpbGw9ICdncmVlbicpICsNCiAgICBmYWNldF93cmFwKH4gY3V0KSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiMjIyAqKjMuIEjDrG5oIDUuMzogQmnhu4N1IMSR4buTIHNvIHPDoW5oIG5ow7NtIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSB2w6AgxJHhu5kgdHJvbmcgc3Xhu5F0KioNCg0KVGEgY8OzIG5ow7NtIGJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBsb+G6oWkgdHJvbmcgc3Xhu5F0IGtow6FjIG5oYXUgdOG7qyDEkcOzIGPDsyB0aOG7gyBk4buFIGTDoG5nIHF1YW4gc8OhdCBzbyBzw6FuaCBnaeG7r2EgY8OhYyBtw6B1IGPhu6dhIGxv4bqhaSB0cm9uZyBzdeG7kXQgbsOgeSBn4buTbSBELEUsRixHLEgsSSxKIHbhu5tpIHThu6tuZyBsb+G6oWkgdHJvbmcgc3Xhu5F0IGtpYSBJMSxTSTIsU0kxLFZTMixWUzEsVlZTMixWVlMxLElGDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnAgJT4lIGdyb3VwX2J5KGNsYXJpdHksY29sb3IpICU+JSBzdW1tYXJpc2Uobj1uKCksLmdyb3VwcyA9ICdkcm9wJykgJT4lDQogIGdncGxvdChhZXMoeCA9IGNvbG9yLHkgPSBuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9InJlZCIpICsNCiAgICBmYWNldF93cmFwKH5jbGFyaXR5KSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KQ8WpbmcgbmjGsCBiaeG7g3UgxJHhu5MgdHLDqm4gYmnhu4N1IMSR4buTIGTGsOG7m2kgxJHDonkgY8WpbmcgZ2nDunAgdGEgcXVhbiBzw6F0IHbDoCBzbyBzw6FuaCBuaOG7r25nIHbhuqduIMSR4buBIHRyw6puIG5oxrBuZyB24bubaSBjw6J1IGzhu4duaCAqKmdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDIsIGNvbG9yID0gJ3doaXRlJykqKiB0YSBjw7MgdGjhu4MgdGjhuqV5IHLDtSBz4buRIGxp4buHdSBt4buZdCBjw6FjaCBj4bulIHRo4buDLiANCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KcCAlPiUgZ3JvdXBfYnkoY2xhcml0eSxjb2xvcikgJT4lIHN1bW1hcmlzZShuPW4oKSwuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY29sb3IseSA9IG4pKSArDQogICAgZ2VvbV9jb2woIGZpbGw9ICdicm93bicpICsNCiAgICBmYWNldF93cmFwKH5jbGFyaXR5KSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KIyMgKipWSS4gU28gc8OhbmggbmjDs20ga2ltIGPGsMahbmcgdGhlbyBt4bupYyBnacOhIHRydW5nIGLDrG5oKioNCg0KIyMjICoqMS4gSMOsbmggNi4xOiBCaeG7g3UgxJHhu5Mgc28gc8OhbmggbmjDs20ga2ltIGPGsMahbmcgKG3DoHUgdsOgIGNo4bqldCBsxrDhu6NuZyBjaOG6vyB0w6FjKSoqDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnAgJT4lIGdyb3VwX2J5KGN1dCxjb2xvcikgJT4lIHN1bW1hcmlzZShtID0gbWVhbihwcmljZSksLmdyb3VwcyA9ICdkcm9wJykgJT4lDQogIGdncGxvdChhZXMoeCA9IGNvbG9yLHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmN1dCApICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSkpKSArDQogICAgbGFicyh4ID0gJ0NvbG9yICcsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KVHLhu6VjIHR1bmcgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcNCg0KVHLhu6VjIGhvw6BuaCBiaeG7g3UgZGnhu4VuIGPDoWMgbcOgdSBn4buTbSBELEUsRixHLEgsSSxKDQoNCkJp4buDdSDEkeG7kyBuaMOzbSA2LjEgbMOgIHRo4buRbmcga8OqIG3hu6ljIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgdOG7q25nIGxv4bqhaSBraW0gY8awxqFuZyBjaOG6vyB0w6FjIHRoZW8gdOG6pXQgY+G6oyBjw6FjIG3DoHUgY8OzIMSR4bqneSDEkeG7pyBz4buRIGxp4buHdSAgdHLDqm4gdOG7q25nIGJp4buDdSDEkeG7kw0KDQojIyMgKioyLiBIw6xuaCA2LjI6IEJp4buDdSDEkeG7kyBzbyBzw6FuaCBuaMOzbSBraW0gY8awxqFuZyAoxJHhu5kgdHJvbmcgc3Xhu5F0IHbDoCBjaOG6pXQgbMaw4bujbmcgY2jhur8gdMOhYykqKg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQpwICU+JSBncm91cF9ieShjdXQsY2xhcml0eSkgJT4lIHN1bW1hcmlzZShtID0gbWVhbihwcmljZSksIC5ncm91cHMgPSAnZHJvcCcpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjbGFyaXR5LHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmN1dCApICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSkpKSArDQogICAgbGFicyh4ID0gJ2NsYXJpdHkgJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoNCg0KQmnhu4N1IMSR4buTIDYuMiB0aOG7gyBoaeG7h24gc+G7sSBzbyBzw6FuaCBt4bupYyBnacOhIHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyBsb+G6oWkga2ltIGPGsMahbmcgY2jhur8gdMOhYyB0aGVvIG3DoHUgdsOgIMSR4buZDQoNCnRyb25nIHN14buRdA0KDQojIyMgKiozLiBIw6xuaCA2LjM6IEJp4buDdSDEkeG7kyBzbyBzw6FuaCBuaMOzbSBraW0gY8awxqFuZyAobcOgdSB2w6AgxJHhu5kgdHJvbmcgc3Xhu5F0KSoqDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnAgJT4lIGdyb3VwX2J5KGNsYXJpdHksY29sb3IpICU+JSBzdW1tYXJpc2UobSA9IG1lYW4ocHJpY2UpLCAuZ3JvdXBzPSdkcm9wJykgJT4lDQogIGdncGxvdChhZXMoeCA9IGNvbG9yLHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmNsYXJpdHkpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSkpKSArDQogICAgbGFicyh4ID0gJ0NvbG9yICcsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KDQoNCkJp4buDdSDEkeG7kyA2LjMgdGjhu4MgaGnhu4duIHPhu7Egc28gc8OhbmggbeG7qWMgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSB04burbmcgbG/huqFpIGtpbSBjxrDGoW5nIGNo4bq/IHTDoWMgdGhlbyB04bqldCBj4bqjIGPDoWMgxJHhu5kNCg0KdHJvbmcgc3Xhu5F0IHbDoCBtw6B1ICANCg0KIyMgKipWSUkuIFBow6JuIHTDrWNoIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyAgbeG7qWMgZ2nDoSB2w6Aga2jhu5FpIGzGsOG7o25nIGNhcmF0KioNCg0KIyMjICoqMS4gSMOsbmggNy4xOiBCSeG7g3UgxJHhu5MgcGjDom4gdMOtY2ggc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGto4buRaSBsxrDhu6NuZyoqDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnAgPC1wICU+JSBtdXRhdGUoQ2FyYXQgPSBjdXQoY2FyYXQsNSwgbGFiZWwgPSBjKCdy4bqldCBuaOG7jycsICduaOG7jycsJ3bhu6thJywnbOG7m24nLCdy4bqldCBs4bubbicpKSkNCnAgJT4lIGdncGxvdChhZXMoeCA9IENhcmF0KSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ3NhbG1vbicpDQpgYGANCg0KDQoNCkJp4buDdSDEkeG7kyA3LjEgY2hvIHRo4bqleSBraOG7kWkgbMaw4bujbmcgY2FyYXQgxJHGsOG7o2MgY2hpYSBsw6BtIDUgbG/huqFpOiBy4bqldCBuaOG7jywgbmjhu48sIHbhu6thLGzhu5tuLHLhuqV0IGzhu5tuLiBMb+G6oWkgcuG6pXQgbmjhu48gY2hp4bq/bSBz4buRIGzGsOG7o25nIG5oaeG7gXUgbmjhuqV0LCB0cm9uZyBraGkgxJHDsyBsb+G6oWkgbOG7m24gdsOgIHLhuqV0IGzhu5tuIGjhuqd1IG5oxrAgbMOgIGtow7RuZyBjw7MuIFbhuq15IHRyw6puIHRo4buLIHRyxrDhu51uZyBjYXJhdCBsb+G6oWkgbOG7m24gdsOgIHLhuqV0IGzhu5tuIGzDoCBj4buxYyBrw6wgaGnhur9tIHNvIHbhu5tpIGPDoWMgbG/huqFpIGPDsm4gbOG6oWkNCg0KIyMjICoqMi4gSMOsbmggNy4yOiBCSeG7g3UgxJHhu5MgcGjDom4gdMOtY2ggc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIG3hu6ljIGdpw6EqKg0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQpwIDwtIHAgJT4lIG11dGF0ZShQcmljZSA9IGN1dChwcmljZSw1LCBsYWJlbCA9IGMoJ3LhuqV0IHRo4bqlcCAnLCAndGjhuqVwJywndGInLCdjYW8nLCdy4bqldCBjYW8nKSkpDQpwICU+JSBnZ3Bsb3QoYWVzKHggPSBQcmljZSkpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICdwaW5rJykNCmBgYA0KDQpUcuG7pWMgdHVuZyhjb3VudCkgdGjhu4MgaGnhu4duIG3hu6ljIGdpw6ENCg0KVHLhu6VjIGhvw6BuaChwcmljZSkgZ+G7k20gcuG6pXQgdGjhuqVwLCB0aOG6pXAsIHRydW5nIGLDrG5oLCBjYW8sIHLhuqV0IGNhbw0KDQpCaeG7g3UgxJHhu5MgNy4yIGNobyB0YSB0aOG6pXkgbeG7qWMgZ2nDoSBraW0gY8awxqFuZyBu4bqxbSDhu58gdHLhu6VjIHR1bmcgdGjhu4MgaGnhu4duIG3hu6ljIGdpw6EgbG/huqFpIHLhuqV0IG5o4buPIHRo4bqlcCBoxqFuIGPDoWMgbG/huqFpIGPDsm4gbOG6oWkgcuG6pXQgbmhp4buBdSBs4bqnbiwga2ltIGPGsMahbmcgbG/huqFpIHLhuqV0IGzhu5tuIHRow6wgaGnhur9tIG7Dqm4gZ2nDoSBz4bq9IGNhbyBoxqFuDQoNCiMjIyAqKjMuIEjDrG5oIDcuMyoqDQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCnAgPC0gcCAlPiUgbXV0YXRlKGNvbG9yX2NvZGUgPSBjYXNlX3doZW4oDQogICAgY29sb3IgPT0gIkQiIHwgY29sb3IgPT0gIkUiIHwgY29sb3IgPT0gIkYiIH4gMSwNCiAgICBjb2xvciA9PSAiRyIgfCBjb2xvciA9PSAiSCIgfCBjb2xvciA9PSAiSSIgfCBjb2xvciA9PSAiSiIgfiAyKSkNCg0KcCA8LSBtdXRhdGUocCwgY29sb3JDID0gY3V0KGNvbG9yX2NvZGUsIDIsIGxhYmVsID0gYygna2jDtG5nIG3DoHUnLCAnZ+G6p24gbmjGsCBraMO0bmcgbcOgdScpKSkNCg0KcCAlPiUgZ3JvdXBfYnkoY29sb3JDKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjb2xvckMsIG4pKSArDQogICAgZ2VvbV9jb2woZmlsbCA9ICdyZWQnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLCB2anVzdCA9IDAsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIHhsYWIoJ03DoHUgc+G6r2MnKSArDQogICAgeWxhYignU+G7kSBsxrDhu6NuZyAodmnDqm4pJykgKyANCiAgICBsYWJzKCkNCmBgYA0KDQpUcuG7pWMgdHVuZyB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZw0KDQpUcuG7pWMgaG/DoG5oIHRo4buDIGhp4buHbiBtw6B1IHPEg2MgZ+G7k20ga2jDtG5nIG3DoHUgdsOgIGfhuqduIG5oxrAga2jDtG5nIG3DoHUNCg0KVGEgdGjhuqV5IMSRxrDhu6NjIHPhu5EgbMaw4bujbmcgdmnDqm4gZ+G6p24gbmjGsCBraMO0bmcgbcOgdSBjaGnhur9tIHPhu5EgbMaw4bujbmcgbmhp4buBdSBoxqFuIHbDrCB0aOG6vyBwaOG6p24gbOG7m24gY2FyYXQgY8OzIGThuqFuZyB0cm9uZyBzdeG7kXQNCg0KIyMjICoqNC4gSMOsbmggNy40KioNCg0KYGBge3J9DQpwIDwtIGRpYW1vbmRzIA0KcCA8LSBwICU+JSBtdXRhdGUoZGVwdGhDID0gY3V0KGRlcHRoLDUsIGxhYmVsID0gYygnU8OidScsJ0tow6Egc8OidScsJ1RydW5nIGLDrG5oJywnS2jDoSBuw7RuZycsJ07DtG5nJykpKQ0KcCAlPiUgZ2dwbG90KGFlcyh4ID0gZGVwdGhDKSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ3JlZCcpDQpgYGANCg0KDQpCaeG7g3UgxJHhu5MgNy40IHRo4buDIGhp4buHbiDEkeG7mSBuw7RuZyBzw6J1IGtoaSBj4bqvdCB2acOqbiBraW0gY8awxqFuZw0KDQojIyAqKlZJSUkuIEJp4buDdSDEkeG7kyBjw6FjIGNo4buJIHPhu5EgY+G7pSB0aOG7gyB0aGVvIHThu6tuZyBiaeG6v24qKg0KDQojIyMgKioxLiBIw6xuaCA4LjE6IE1lZGlhbih0cnVuZyB24buLKSBj4bunYSBiaeG6v24g4oCYY2FyYXTigJkqKg0KDQpgYGB7cn0NCnAgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShtPSBtZWRpYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDIpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICd5ZWxsb3cnKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnTWVkaWFuJykNCmBgYA0KDQoNCg0KQ8OidSBs4buHbmggdHLDqm4gY2hvIHRhIG3hu5l0IGJp4buDdSDEkcOyIGThuqFuZyBCYXIgQ2hhcnQgduG7m2kgdHLhu6VjIGhvw6BuaCBsw6AgY8OhYyBsb+G6oWkga2ltIGPGsMahbmcgxJHGsOG7o2MgY2hpYSB0aGVvIGJp4bq/biDigJhjdXTigJkgYmFvIGfhu5NtIDUgbG/huqFpIGzhuqduIGzGsOG7o3QgbMOgIOKAmEZhaXLigJks4oCYR29vZOKAmSzigJhWZXJ5IEdvb2TigJks4oCYUHJlbWl1beKAmSzigJhJZGVhbOKAmSwgdHLhu6VjIHR1bmcgbMOgIHRydW5nIHbhu4sgxJHhu5kgbOG7m24gY+G7p2EgYmnhur9uIOKAmENhcmF04oCZIC4gQ+G7pSB0aOG7gyBuaMawIHNhdToNCg0KKyBUcnVuZyB24buLIGNhcmF0IGPhu6dhIGxv4bqhaSBraW0gY8awxqFuZyDigJkgRmFpcuKAmSBsw6AgMSAoNTAlIHPhu5Ega2ltIGPGsMahbmcgbG/huqFpIEZhaXIgY8OzIMSR4buZIGzhu5tuIGNhcmF0IGTGsOG7m2kgMSB2w6AgNTAlIGPDsm4gbOG6oWkgY8OzIMSR4buZIGzhu5tuIGNhcmF0IGzhu5tuIGjGoW4gMSApDQorIFRydW5nIHbhu4sgY2FyYXQgY+G7p2EgbG/huqFpIGtpbSBjxrDGoW5nIOKAmSBHb29k4oCZIGzDoCAwLjgyICg1MCUgc+G7kSBraW0gY8awxqFuZyBsb+G6oWkgR29vZCBjw7MgxJHhu5kgbOG7m24gY2FyYXQgZMaw4bubaSAwLjgyIHbDoCA1MCUgY8OybiBs4bqhaSBjw7MgxJHhu5kgbOG7m24gY2FyYXQgbOG7m24gaMahbiAwLjgyICkNCisgVHJ1bmcgduG7iyBjYXJhdCBj4bunYSBsb+G6oWkga2ltIGPGsMahbmcg4oCZIFZlcnkgR29vZOKAmSBsw6AgMC43MSAoNTAlIHPhu5Ega2ltIGPGsMahbmcgbG/huqFpIFZlcnkgR29vZCBjw7MgxJHhu5kgbOG7m24gY2FyYXQgZMaw4bubaSAwLjcxIHbDoCA1MCUgY8OybiBs4bqhaSBjw7MgxJHhu5kgbOG7m24gY2FyYXQgbOG7m24gaMahbiAwLjcxICkNCisgVHJ1bmcgduG7iyBjYXJhdCBj4bunYSBsb+G6oWkga2ltIGPGsMahbmcg4oCYUHJlbWl1beKAmSBsw6AgMC44NiAoNTAlIHPhu5Ega2ltIGPGsMahbmcgbG/huqFpIFByZW1pdW0gY8OzIMSR4buZIGzhu5tuIGNhcmF0IGTGsOG7m2kgMC44NiB2w6AgNTAlIGPDsm4gbOG6oWkgY8OzIMSR4buZIGzhu5tuIGNhcmF0IGzhu5tuIGjGoW4gMC44NiApDQorIFRydW5nIHbhu4sgY2FyYXQgY+G7p2EgbG/huqFpIGtpbSBjxrDGoW5nIOKAmElkZWFs4oCZIGzDoCAwLjU0ICg1MCUgc+G7kSBraW0gY8awxqFuZyBsb+G6oWkgSWRlYWwgY8OzIMSR4buZIGzhu5tuIGNhcmF0IGTGsOG7m2kgMC41NCB2w6AgNTAlIGPDsm4gbOG6oWkgY8OzIMSR4buZIGzhu5tuIGNhcmF0IGzhu5tuIGjGoW4gMC41NCApIA0KDQojIyMgKioyLiBIw6xuaCA4LjI6IE1lYW4gKGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmgpIGPhu6dhIGJp4bq/biDigJhwcmljZeKAmSoqDQpgYGB7cn0NCnAgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShtPSBtZWFuKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gbSkpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAneWVsbG93JykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ01lYW4nKQ0KYGBgDQoNCg0KDQpDw6J1IGzhu4duaCB0csOqbiBjaG8gdGEgbeG7mXQgxJHhu5MgdGjhu4sgZOG6oW5nIEJhciBDaGFydCB24bubaSB0cuG7pWMgaG/DoG5oIGzDoCBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyDEkcaw4bujYyBjaGlhIHRoZW8gYmnhur9uIOKAmGN1dOKAmSBiYW8gZ+G7k20gNSBsb+G6oWkgbOG6p24gbMaw4bujdCBsw6Ag4oCYRmFpcuKAmSzigJhHb29k4oCZLOKAmFZlcnkgR29vZOKAmSzigJhQcmVtaXVt4oCZLOKAmElkZWFs4oCZLCB0cuG7pWMgdHVuZyBsw6AgdHJ1bmcgYsOsbmggxJHhu5kgbOG7m24gY+G7p2EgYmnhur9uIOKAmFByaWNl4oCZIC4gQ+G7pSB0aOG7gyBuaMawIHNhdToNCg0KKyBLaW0gY8awxqFuZyBGYWlyIGPDsyDEkeG7mSBs4bubbiB0cnVuZyBiw6xuaCBj4bunYSBiaeG6v24g4oCYUHJpY2XigJkgbMOgIDogNDM1OC43Ng0KKyBLaW0gY8awxqFuZyBHb29kIGPDsyDEkeG7mSBs4bubbiB0cnVuZyBiw6xuaCBj4bunYSBiaeG6v24g4oCYUHJpY2XigJkgbMOgIDogMzkyOC44Ng0KKyBLaW0gY8awxqFuZyBWZXJ5IEdvb2QgY8OzIMSR4buZIGzhu5tuIHRydW5nIGLDrG5oIGPhu6dhIGJp4bq/biDigJhQcmljZeKAmSBsw6AgOiAzOTgxLjc2DQorIEtpbSBjxrDGoW5nIFByZW1pdW0gY8OzIMSR4buZIGzhu5tuIHRydW5nIGLDrG5oIGPhu6dhIGJp4bq/biDigJhQcmljZeKAmSBsw6AgOiA0NTg0LjI2DQorIEtpbSBjxrDGoW5nIElkZWFsIGPDsyDEkeG7mSBs4bubbiB0cnVuZyBiw6xuaCBj4bunYSBiaeG6v24g4oCYUHJpY2XigJkgbMOgIDogMzQ1Ny41NA0KDQo=