30 Biểu
đồ
library(tidyverse)
tmp <- diamonds
tmp <- tmp %>% mutate(caratk = cut(carat,3, label = c('nhỏ','vừa','lớn')))
tmp %>% ggplot(aes(x = caratk)) +
geom_bar(fill = 'black')

Giải thích
biểu đồ 1:
đồ thị giúp so sánh số lượng kim cương có kích thước lớn, vừa và nhỏ.
Trong đó số viên kim cương kích thước nhỏ chiếm số lượng lớn nhất trong
toàn bộ dữ liệu, với số lượng hơn 50000. Tiếp đến là kim cương kích
thước vừa khoảng với số lượng khoảng 2000 viên. Không có kim cương loại
lớn.
library(tidyverse)
tmp <- tmp %>% group_by(cut, color) %>% summarise(SL = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
tmp %>% ggplot(aes(x = cut, y = SL)) +
geom_col(data = tmp %>% filter(color == 'D'), fill = 'yellow') +
geom_col(data = tmp %>% filter(color == 'J'), fill = 'pink')

Giải thích
biểu đồ 2:
Đồ thị này cho ta so sánh được tổng số lượng kim cương màu màu D và
màu J của các loại kim cương(cut) có trong bộ dữ liệu. Cụ thể là tổng số
kim cương màu D và J của kim cương loại Fair là ít nhất khoảng dưới 250
viên, tiếp đến là loại Good khoảng 600 viên, tiếp đó là loại Very Good
và Premium lần lượt với khoảng 1500 viên và 1550 viên. Loại Ideal là
loại có tổng số kim cương màu D và J lớn nhất trong bộ dữ liệu với
khoảng 2800 viên.Trong đồ thị này,màu vàng biểu diễn kim cương màu D còn
màu hồng biểu diễn cho kim cương màu J.
library(tidyverse)
tmp <- diamonds
tmp <- tmp %>% group_by(cut, color) %>% summarise(SL = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
tmp %>% ggplot(aes(x = cut, y = SL)) +
geom_col(data = tmp %>% filter(color == 'E'), fill = 'red') +
geom_col(data = tmp %>% filter(color == 'F'), fill = 'pink') +
geom_col(data = tmp %>% filter(color == 'D'), fill = 'blue')

Giải Thích
biểu đồ 3:
Đồ thị này cho ta so sánh được tổng số lượng kim cương màu màu E,F và
màu D của các loại kim cương(cut) có trong bộ dữ liệu. Cụ thể là tổng số
kim cương màu D,E và F của kim cương loại Fair là ít nhất khoảng gần 300
viên, tiếp đến là loại Good khoảng 750 viên, tiếp đó là loại Premium và
loại Very Good lần lượt với khoảng 2400 viên và 2450 viên. Loại Ideal là
loại có tổng số kim cương màu D,E và F lớn nhất trong bộ dữ liệu với
khoảng 3800 viên.
library(tidyverse)
tmp <- diamonds
ggplot(diamonds, aes(x = cut, y = carat)) +
geom_bar(stat = "summary", fun = "mean", fill = "skyblue") +
labs(title = "Giá trị trung bình", x = "Cut", y = "tb")

Giải thích
biểu đồ 4:
geom_bar() được sử dụng để vẽ biểu đồ bar chart, với stat = summary
để tính toán thống kê trên dữ liệu (trong trường hợp này, giá trị trung
bình của carat) và fun = mean để chỉ định rằng chúng ta muốn tính giá
trị trung bình. labs() được sử dụng để đặt tiêu đề cho biểu đồ và các
nhãn trục. Biểu đồ bar chart hiển thị giá trị trung bình của carat cho
từng mức độ cut trong bộ dữ liệu diamonds.Cụ thể là giá trị khối lượng
trung bình của kim cương loại Fair là lớn nhất khoảng 1.05 và thấp nhất
là kim cương loại Ideal khoảng 0.78
library(ggplot2)
# Tính độ lệch chuẩn của carat cho mỗi mức độ cut
SD <- aggregate(carat ~ cut, data = diamonds, FUN = sd)
# Tạo biểu đồ bar chart
ggplot(SD, aes(x = cut, y = carat)) +
geom_bar(stat = "identity", fill = "orange") +
labs(title = "Độ lệch chuẩn", x = "Cut", y = "Sd")

Giải thích
biểu đồ 5:
Chúng ta sử dụng hàm aggregate() để tính độ lệch chuẩn của carat
cho mỗi mức độ cut trong bộ dữ liệu diamonds.
Sau đó, chúng ta tạo biểu đồ bar chart với trục x biểu thị các
mức độ cut và trục y biểu thị độ lệch chuẩn của carat tương
ứng.
Biểu đồ này sẽ hiển thị độ lệch chuẩn của carat cho mỗi mức
độ cut, giúp ta hiểu về mức độ biến động của carat trong từng loại kim
cương
library(ggplot2)
data(diamonds)
# lọc ra những viên kim cương màu D
filtered_data_D <- subset(diamonds, color == "D")
# Tính giá trung bình của các loại kim cương màu D
average_price <- aggregate(price ~ cut, data = filtered_data_D, FUN = mean)
ggplot(average_price, aes(x = cut, y = price, fill = cut)) +
geom_bar(stat = "identity") +
labs(title = "Giá trung bình của các loại kim cương màu D", x = "Cut", y = "Average Price") +
scale_fill_discrete(name = "Cut")

Giải thích
biểu đồ 6
average_price <- aggregate(price ~ cut, data =
filtered_data_D, FUN = mean): dùn để tính giá trung bình cho các viên
kim cương màu D.
labs(title = ) dùng để đặt tên cho các trục và tên của tiêu
đề
scale_fill_discrete(name = “Cut”): dùng để chú giải cho biểu
đồ
Đồ thị này giúp chúng ta có thể so sánh giá trung bình của
kim cương màu D ứng với các kiểu kim cương ( cut)
library(ggplot2)
data(diamonds)
# lọc ra các viên kim cương màu E và F
filtered_data_EF <- subset(diamonds, color %in% c("E", "F"))
# Tính gIá trung bình của kim cương 2 màu E và màu F
average_price <- aggregate(price ~ color, data = filtered_data_EF, FUN = mean)
# Create a bar chart for average prices
ggplot(average_price, aes(x = color, y = price, fill = color)) +
geom_bar(stat = "identity") +
labs(title = "Giá trung bình của 2 màu kim cương E và F", x = "Color", y = "Average Price") +
scale_fill_discrete(name = "Color")

Giải thích
biểu đồ 7:
Trục x của biểu đồ biểu thị các màu kim cương, bao gồm “E” và
“F”.
Trục y của biểu đồ biểu thị giá trị trung bình của các viên kim
cương tương ứng với mỗi màu.
Mỗi cột trong biểu đồ biểu diễn giá trị trung bình của mỗi màu
kim cương.
Biểu đồ này cho chúng ta biết rằng trung bình giá của các viên
kim cương màu “E” và “F” là bao nhiêu. Nếu có sự khác biệt đáng kể giữa
hai màu kim cương này, chúng ta có thể nhận thấy sự biến động trong giá
trị trung bình của giá giữa chúng.
Điều này có thể hữu ích trong việc hiểu về giá trị trung bình của
các viên kim cương có màu khác nhau trong thị trường.
library(ggplot2)
data("diamonds")
# Vẽ biểu đồ cột
ggplot(diamonds, aes(x = cut)) +
geom_bar(fill = "skyblue", color = "red") +
labs(title = "Số lượng kim cương theo chất lượng cắt",
x = "Chất lượng cắt",
y = "Số lượng")

Giải thích
biểu đồ 8
geom_bar() được sử dụng để tạo biểu đồ cột.
fill được sử dụng để chỉ định màu của các cột, và
color là màu của đường viền cột.
labs() được sử dụng để đặt tiêu đề cho biểu đồ và
các trục.
Biểu đồ này cho chúng ta một cái nhìn tổng quan về phân phối
số lượng kim cương theo chất lượng cắt của chúng. Đối với mỗi loại chất
lượng cắt, chúng ta có thể thấy số lượng tương ứng của kim
cương.
library(ggplot2)
data("diamonds")
ggplot(diamonds, aes(x = cut, y = price)) +
geom_bar(stat = "summary", fun = "mean", fill = "red", color = "black") +
labs(title = "Biểu đồ giá trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Giá trung bình (USD)")

Giải thích
biểu đồ 9
Trong đó:
aes(x = cut, y = price): Ta sử dụng cột
cut để làm trục x (chất lượng cắt) và cột
price để làm trục y (giá).
geom_bar(stat = "summary", fun = "mean"): Sử dụng
geom_bar() với stat = "summary" để tính giá
trung bình và vẽ các cột. Chúng ta sử dụng fun = "mean" để
tính giá trung bình.
fill = "red", color = "black": Đặt màu fill cho các
cột là màu đỏ và màu viền là màu đen.
labs(): Đặt tiêu đề cho biểu đồ và các
trục.
Biểu đồ này sẽ hiển thị giá trung bình của kim cương theo mỗi
mức chất lượng cắt tương ứng.
library(ggplot2)
data("diamonds")
ggplot(diamonds, aes(x = cut, y = price)) +
geom_bar(stat = "summary", fun = "mean", fill = "purple", color = "black") +
labs(title = "Biểu đồ giá trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Giá trung bình (USD)") + coord_flip()

Giải thích
biểu đồ 10
Trong đó:
aes(x = cut, y = price): Ta sử dụng cột
cut để làm trục x (chất lượng cắt) và cột
price để làm trục y (giá).
geom_bar(stat = "summary", fun = "mean"): Sử dụng
geom_bar() với stat = "summary" để tính giá
trung bình và vẽ các cột. Chúng ta sử dụng fun = "mean" để
tính giá trung bình.
fill = "purple", color = "black": Đặt màu fill cho
các cột là màu tím và màu viền là màu đen.
labs(): Đặt tiêu đề cho biểu đồ và các
trục.
coord_flip(): làm cho biểu đồ nằm ngang
Biểu đồ này sẽ hiển thị giá trung bình của kim cương theo mỗi
mức chất lượng cắt tương ứng.
library(ggplot2)
data("diamonds")
ggplot(diamonds, aes(x = cut, y = y)) +
geom_bar(stat = "summary", fun = "mean", fill = "green", color = "black") +
labs(title = "Độ rộng y trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Độ rộng y trung bình (mm)")

GIải thích
biểu đồ 11
Trong biểu đồ này:
aes(x = cut, y = y): Chúng ta sử dụng cột
cut để làm trục x (chất lượng cắt) và cột
yđể làm trục y (độ rộng y).
geom_bar(stat = "summary", fun = "mean"): Sử dụng
geom_bar() với stat = "summary" để tính độ
rộng y trung bình và vẽ các cột. Chúng ta sử dụng
fun = "mean" để tính giá trung bình.
fill = "green", color = "black": Đặt màu fill cho
các cột là màu xanh lá cây và màu viền là màu đen.
labs(): Đặt tiêu đề cho biểu đồ và các
trục.
Biểu đồ này sẽ hiển thị độ rộng y trung bình của kim cương
theo mỗi mức chất lượng cắt tương ứng.
library(ggplot2)
data("diamonds")
ggplot(diamonds, aes(x = cut, y = y)) +
geom_bar(stat = "summary", fun = "mean", fill = "green", color = "black") +
labs(title = "Độ rộng y trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Độ rộng y trung bình (mm)") + coord_flip()

GIải thích
biểu đồ 12
Trong biểu đồ này:
aes(x = cut, y = y): Chúng ta sử dụng cột
cut để làm trục x (chất lượng cắt) và cột
yđể làm trục y (độ rộng y).
geom_bar(stat = "summary", fun = "mean"): Sử dụng
geom_bar() với stat = "summary" để tính độ
rộng y trung bình và vẽ các cột. Chúng ta sử dụng
fun = "mean" để tính giá trung bình.
fill = "green", color = "black": Đặt màu fill cho
các cột là màu xanh lá cây và màu viền là màu đen.
labs(): Đặt tiêu đề cho biểu đồ và các
trục.
coord_flip(): làm cho đồ thị nằm ngang
Biểu đồ này sẽ hiển thị độ rộng y trung bình của kim cương
theo mỗi mức chất lượng cắt tương ứng.
library(ggplot2)
data("diamonds")
# Tính giá trung bình của độ dài x theo chất lượng cắt
mean_x <- aggregate(diamonds$x, by = list(diamonds$cut), FUN = mean)
# Vẽ biểu đồ cột
ggplot(diamonds, aes(x = cut, y = x)) +
geom_bar(stat = "summary", fun = "mean", fill = "skyblue", color = "black") +
geom_text(data = mean_x, aes(x = Group.1, y = x, label = round(x, 1)), vjust = -0.5) +
labs(title = "Độ dài x trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Độ dài x trung bình (mm)")

Giải thích
biểu đồ 13
Chúng ta sử dụng hàm aggregate() để tính giá trung
bình của độ dài x theo mỗi mức chất lượng cắt.
geom_text() được sử dụng để thêm số trung bình lên
các cột, với các tham số x là nhóm (mức chất lượng cắt),
y là giá trị trung bình của độ dài x, và
label là số trung bình (được làm tròn đến 1 chữ số thập
phân).
vjust = -0.5 được sử dụng để căn chỉnh văn bản lên
trên các cột.
Biểu đồ này sẽ hiển thị độ dài x trung bình của kim cương
theo mỗi mức chất lượng cắt, và số trung bình sẽ được hiển thị trên đỉnh
của từng cột.
# Load thư viện ggplot2
library(ggplot2)
# Vẽ biểu đồ cột
ggplot(diamonds, aes(x = cut, y = x)) +
geom_bar(stat = "summary", fun = "mean", fill = "blue", color = "black") +
labs(title = "Độ dài x trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Độ dài x trung bình (mm)")

Giải thích
biểu đồ 14
Trong biểu đồ này:
aes(x = cut, y = x): Chúng ta sử dụng cột “cut” để
làm trục x (chất lượng cắt) và cột “x” để làm trục y (độ dài
x).
geom_bar(stat = "summary", fun = "mean"): Sử dụng
geom_bar() với stat = "summary" để tính độ dài
x trung bình và vẽ các cột. Chúng ta sử dụng fun = "mean"
để tính giá trung bình.
fill = "blue", color = "black": Đặt màu fill cho các
cột là màu xanh da trời và màu viền là màu đen.
labs(): Đặt tiêu đề cho biểu đồ và các
trục.
Biểu đồ này sẽ hiển thị độ dài x trung bình của kim cương
theo mỗi mức chất lượng cắt tương ứng.
# Load thư viện ggplot2
library(ggplot2)
# Tính độ dài trung bình của các mẫu kim cương theo màu sắc
mean_length <- aggregate(diamonds$x, by = list(diamonds$color), FUN = mean)
# Vẽ biểu đồ cột
ggplot(mean_length, aes(x = Group.1, y = x)) +
geom_bar(stat = "identity", fill = "red", color = "black") +
geom_text(aes(label = round(x, 1)), vjust = -0.5, color = "black") +
labs(title = "Độ dài trung bình của Kim cương theo Màu sắc",
x = "Màu sắc",
y = "Độ dài trung bình (mm)")

Giải thích
biểu đồ 15
Trong đó:
Chúng ta sử dụng hàm aggregate() để tính độ dài
trung bình của các mẫu kim cương theo màu sắc.
geom_bar(stat = "identity") được sử dụng để vẽ các
cột dựa trên giá trị trong cột y.
geom_text() được sử dụng để thêm số trên các cột,
với các tham số label là giá trị độ dài trung bình của từng
màu sắc (được làm tròn đến 1 chữ số thập phân).
vjust = -0.5 được sử dụng để căn chỉnh văn bản lên
trên các cột.
color = "black" được sử dụng để đặt màu cho văn bản
là màu đen.
Biểu đồ này sẽ hiển thị độ dài trung bình của kim cương theo
mỗi màu sắc, và số trung bình sẽ được hiển thị trên đỉnh của từng
cột.
# Load thư viện ggplot2
library(ggplot2)
# Tính độ sâu trung bình của các mẫu kim cương theo chất lượng cắt
mean_depth <- aggregate(diamonds$depth, by = list(diamonds$cut), FUN = mean)
# Vẽ biểu đồ cột
ggplot(mean_depth, aes(x = Group.1, y = x)) +
geom_bar(stat = "identity", fill = "orange", color = "black") +
geom_text(aes(label = round(x, 1)), vjust = -0.5, color = "green") +
labs(title = "Độ sâu trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Độ sâu trung bình (%)")

Giải thích
biểu đồ 16
Trong biểu đồ này: - Chúng ta sử dụng hàm aggregate() để
tính độ sâu trung bình của các mẫu kim cương theo chất lượng cắt.
geom_bar(stat = "identity") được sử dụng để vẽ các
cột dựa trên giá trị trong cột y.
geom_text() được sử dụng để thêm số trung bình lên
các cột, với label là giá trị độ sâu trung bình của từng
loại chất lượng cắt (được làm tròn đến 1 chữ số thập phân).
vjust = -0.5 được sử dụng để căn chỉnh văn bản lên
trên các cột.
fill = “orange”, color = “black” : màu của biểu đồ là màu cam và
của chữ số trên các cột là màu xanh lá.
Biểu đồ này sẽ hiển thị độ sâu trung bình của kim cương theo
mỗi mức chất lượng cắt tương ứng.
# Load thư viện ggplot2
library(ggplot2)
# Tính độ lệch chuẩn của giá cho các kim cương màu E, F và J
std_dev <- aggregate(price ~ color, data = subset(diamonds, color %in% c("E", "F", "J")), FUN = sd)
# Vẽ biểu đồ cột
ggplot(std_dev, aes(x = color, y = price)) +
geom_bar(stat = "identity", fill = "skyblue", color = "black") +
geom_text(aes(label = round(price, 1)), vjust = -0.5, color = "red") +
labs(title = "Độ lệch chuẩn về giá của Kim cương màu E, F, J",
x = "Màu sắc",
y = "Độ lệch chuẩn giá")

Giải thích
biểu đồ 17
Trong đó:
Chúng ta sử dụng hàm subset() để lấy các mẫu kim
cương có màu sắc là E, F và J từ bộ dữ liệu
diamonds.
Sau đó, chúng ta tính độ lệch chuẩn của giá cho mỗi màu sắc sử
dụng hàm aggregate() với FUN = sd.
geom_bar(stat = "identity") được sử dụng để vẽ các
cột dựa trên giá trị trong cột y.
geom_text() được sử dụng để thêm số độ lệch chuẩn
lên các cột, với label là giá trị độ lệch chuẩn của từng
màu sắc (được làm tròn đến 1 chữ số thập phân).
vjust = -0.5 được sử dụng để căn chỉnh văn bản lên
trên các cột.
fill = “skyblue”, color = “black”: biểu đồ màu xanh da trời và
viền đen
color = “red”: số trên biểu đồ màu đỏ
Biểu đồ này sẽ hiển thị độ lệch chuẩn về giá của các kim
cương màu E, F và J.
# Load thư viện ggplot2
library(ggplot2)
# Tính độ lệch chuẩn của giá cho các kim cương màu D, F và J
std_dev <- aggregate(price ~ color, data = subset(diamonds, color %in% c("D", "F", "J")), FUN = sd)
# Vẽ biểu đồ cột
ggplot(std_dev, aes(x = price, y = color)) +
geom_bar(stat = "identity", fill = "yellow", color = "black") +
geom_text(aes(label = round(price, 1)), hjust = -0.3, color = "red") +
labs(title = "Độ lệch chuẩn về giá của Kim cương màu D, F, J",
x = "Độ lệch chuẩn giá",
y = "Màu sắc") +
coord_flip()

Giải thích
biểu đồ 18:
Tương tự như biểu đồ 17, chỉ đổi màu E thành màu D
# Load thư viện ggplot2
library(ggplot2)
# Tính số lượng của mỗi mức độ clarity
clarity_count <- table(diamonds$clarity)
# Chuyển table thành dataframe để dễ vẽ biểu đồ
clarity_df <- as.data.frame(clarity_count)
names(clarity_df) <- c("Clarity", "Count")
# Vẽ biểu đồ cột
ggplot(clarity_df, aes(x = Clarity, y = Count)) +
geom_bar(stat = "identity", fill = "blue", color = "black") +
geom_text(aes(label = Count), vjust = -0.8, color = "black") +
labs(title = "Số lượng các mức Clarity của Kim cương",
x = "Clarity",
y = "Số lượng")

Giải thích
biểu đồ 19
Trong đó:
Chúng ta sử dụng hàm table() để tính số lượng của
mỗi mức độ clarity trong cột clarity.
Sau đó, chúng ta chuyển kết quả của table() thành
một dataframe để dễ dàng vẽ biểu đồ.
geom_bar(stat = "identity") được sử dụng để vẽ các
cột dựa trên giá trị trong cột y.
geom_text() được sử dụng để thêm số lượng của từng
mức clarity lên trên các cột.
Biểu đồ này sẽ hiển thị số lượng các mức độ clarity của kim
cương, giúp phân tích phân bố của dữ liệu trong cột
clarity.
# Load thư viện ggplot2
library(ggplot2)
# Tính giá trung bình của mỗi mức độ clarity
clarity_price <- aggregate(diamonds$price, by = list(diamonds$clarity), FUN = mean)
# Vẽ biểu đồ cột
ggplot(clarity_price, aes(x = Group.1, y = x)) +
geom_bar(stat = "identity", fill = "black", color = "red") +
geom_text(aes(label = round(x, 1)), vjust = -0.5, color = "green") +
labs(title = "Giá trung bình của Kim cương theo Mức độ Clarity",
x = "Mức độ Clarity",
y = "Giá trung bình")

Giải thích
đồ thị 20
Trong đó:
Chúng ta sử dụng hàm aggregate() để tính giá trung
bình của mỗi mức độ clarity trong cột price.
geom_bar(stat = "identity") được sử dụng để vẽ các
cột dựa trên giá trị trong cột y.
geom_text() được sử dụng để thêm giá trị giá trung
bình lên trên các cột.
aes(label = round(x, 1)), vjust = -0.5, color = “green”: để làm
tròn giá trung bình đến 1 chữ số thập phân và màu chữ số trên các cột là
màu xanh lá
labs(title ): đặt tên tiêu đề và các trục
Biểu đồ này sẽ hiển thị giá trung bình của kim cương theo mỗi
mức độ clarity, giúp phân tích mối quan hệ giữa giá và clarity của kim
cương.
# Load thư viện ggplot2
library(ggplot2)
# Tính giá trung bình của mỗi mức độ clarity
clarity_price <- aggregate(diamonds$price, by = list(diamonds$clarity), FUN = mean)
# Vẽ biểu đồ cột
ggplot(clarity_price, aes(x = Group.1, y = x)) +
geom_bar(stat = "identity", fill = "black", color = "red") +
geom_text(aes(label = round(x, 1)), vjust = -0.5, color = "green") +
labs(title = "Giá trung bình của Kim cương theo Mức độ Clarity",
x = "Mức độ Clarity",
y = "Giá trung bình") + coord_flip()

Giải thích
đồ thị 21
Giống đồ thị 20 nhưng chỉ thay đổi vị trí 2 trục tọa độ
# Load thư viện ggplot2
library(ggplot2)
# Tính giá trung bình của kim cương có màu J theo chất lượng cắt
avg_price <- aggregate(diamonds$price, by = list(diamonds$cut), FUN = mean)
# Vẽ biểu đồ cột
ggplot(subset(diamonds, color == "J"), aes(x = cut, y = price)) +
geom_bar(stat = "summary", fun = "mean", fill = "green", color = "black") +
labs(title = "Giá trung bình của Kim cương màu J theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Giá trung bình")

Giải thích
đồ thị 22
Trong đó:
Chúng ta sử dụng hàm aggregate() để tính giá trung
bình của các mẫu kim cương có màu J theo chất lượng cắt.
subset(diamonds, color == "J") được sử dụng để lấy
ra chỉ các mẫu kim cương có màu J.
geom_bar(stat = "summary", fun = "mean") được sử
dụng để vẽ các cột biểu diễn giá trung bình của các mẫu kim cương theo
chất lượng cắt.
Các cài đặt khác như tiêu đề và chủ đề của biểu đồ vẫn được giữ
nguyên.
Biểu đồ này sẽ hiển thị giá trung bình của các mẫu kim cương
màu J theo từng mức chất lượng cắt.
# Load thư viện ggplot2
library(ggplot2)
# Tính độ sâu trung bình của mỗi mức độ clarity
clarity_depth <- aggregate(diamonds$depth, by = list(diamonds$clarity), FUN = mean)
# Vẽ biểu đồ cột
ggplot(clarity_depth, aes(x = Group.1, y = x)) +
geom_bar(stat = "identity", fill = "skyblue", color = "black") +
geom_text(aes(label = round(x, 1)), vjust = -0.5, color = "orange") +
labs(title = "Độ sâu trung bình của Kim cương theo Mức độ Clarity",
x = "Mức độ Clarity",
y = "Độ sâu trung bình")

Giải thích
đồ thị 23
Trong đó:
Chúng ta sử dụng hàm aggregate() để tính độ sâu
trung bình của mỗi mức độ clarity trong cột depth.
geom_bar(stat = "identity") được sử dụng để vẽ các
cột dựa trên giá trị trong cột y.
geom_text() được sử dụng để thêm số liệu độ sâu
trung bình lên trên các cột, với label là giá trị độ sâu
trung bình của từng mức độ clarity (được làm tròn đến 1 chữ số thập
phân).
Các cài đặt khác như tiêu đề và chủ đề của biểu đồ vẫn được giữ
nguyên tương tự các biểu đồ trên
Biểu đồ này sẽ hiển thị độ sâu trung bình của kim cương theo
mỗi mức độ clarity, giúp phân tích mối quan hệ giữa clarity và độ sâu
của kim cương.
# Load thư viện ggplot2
library(ggplot2)
# Tính trọng lượng trung bình của mỗi mức độ clarity
clarity_carat <- aggregate(diamonds$carat, by = list(diamonds$clarity), FUN = mean)
# Vẽ biểu đồ cột
ggplot(clarity_carat, aes(x = Group.1, y = x)) +
geom_bar(stat = "identity", fill = "green", color = "black") +
geom_text(aes(label = round(x, 2)), vjust = -0.5, color = "blue") +
labs(title = "Trọng lượng trung bình của Kim cương theo Mức độ Clarity",
x = "Mức độ Clarity",
y = "Trọng lượng trung bình (carat)") + coord_flip()

Giải thích
đồ thị 24
Trong đó:
Chúng ta sử dụng hàm aggregate() để tính trọng lượng
trung bình của mỗi mức độ clarity trong cột carat.
geom_bar(stat = "identity") được sử dụng để vẽ các
cột dựa trên giá trị trong cột y.
geom_text() được sử dụng để thêm số liệu trọng lượng
trung bình lên trên các cột, với label là giá trị trọng
lượng trung bình của từng mức độ clarity (được làm tròn đến 2 chữ số
thập phân).
Các cài đặt khác như tiêu đề và chủ đề của biểu đồ vẫn được giữ
nguyên như các đồ thị trên
Biểu đồ này sẽ hiển thị trọng lượng trung bình của kim cương
theo mỗi mức độ clarity, giúp phân tích mối quan hệ giữa clarity và
trọng lượng của kim cương.
tmp %>% group_by(clarity,color) %>% summarise(n=n()) %>%
ggplot(aes(x = clarity,y = n)) +
geom_col(position = 'dodge') +
geom_col(fill='red') +
facet_wrap(~color) +
geom_text(aes(label = n),vjust = 0.5, color = 'darkgreen') +
labs(x = 'Độ tinh khiết', y = 'Số lượng')
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.

Giải thích
biểu đồ 25
Biểu đồ 25 là tập hợp của những biểu đồ nhỏ thể hiện số lượng theo độ
tinh khiết của từng màu. Ví dụ: nhìn vào biểu đồ nhỏ thứ nhất ta có thể
thấy số lượng viên kim cương màu D có độ tinh khiết I1 là 42, số lượng
viên kim cương màu D có độ tinh khiết SI2 là 1370,…
tmp <- diamonds
tmp %>% group_by(clarity) %>% summarise(m= mean(carat)) %>%
ggplot(aes(x = clarity,y = m)) +
geom_col(position = 'dodge') +
geom_col(fill='green') +
geom_text(aes(label = round(m,2)), vjust = 2, color = 'blue') +
labs(x = 'Độ tinh khiết', y = 'Trọng lượng trung bình')

Giải thích
biểu đồ 26
Biểu đồ 26 thể hiện trọng lượng trung bình của những viên kim cương
theo độ tinh khiết. Ta thấy màu I1 có trọng lượng trung bình lớn nhất
với 1.28 carat còn bé nhất là VVS1 với 0.5 carat
# Load thư viện ggplot2
library(ggplot2)
# Tính độ sâu trung bình của các mẫu kim cương theo chất lượng cắt
mean_depth <- aggregate(diamonds$depth, by = list(diamonds$cut), FUN = mean)
# Vẽ biểu đồ cột
ggplot(mean_depth, aes(x = Group.1, y = x)) +
geom_bar(stat = "identity", fill = "lightgreen", color = "black") +
geom_text(aes(label = round(x, 1)), vjust = -0.5, color = "green") +
labs(title = "Độ sâu trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Độ sâu trung bình (%)")

Giải thích
biểu đồ 27
Trong biểu đồ này: - Chúng ta sử dụng hàm aggregate() để
tính độ sâu trung bình của các mẫu kim cương theo chất lượng cắt.
geom_bar(stat = "identity") được sử dụng để vẽ các
cột dựa trên giá trị trong cột y.
geom_text() được sử dụng để thêm số trung bình lên
các cột, với label là giá trị độ sâu trung bình của từng
loại chất lượng cắt (được làm tròn đến 1 chữ số thập phân).
vjust = -0.5 được sử dụng để căn chỉnh văn bản lên
trên các cột.
fill = “orange”, color = “black” : màu của biểu đồ là màu cam và
của chữ số trên các cột là màu xanh lá.
tmp <- diamonds
tmp %>% group_by(color) %>% summarise(m= mean(y)) %>%
ggplot(aes(x = color,y = m)) +
geom_col(position = 'dodge') +
geom_col(fill='darkgreen') +
geom_text(aes(label = round(m,2)), vjust = 2, color = 'red') +
labs(x = 'Màu', y = 'Chiều rộng trung bình')

Giải thích
biểu đồ 28
Biểu đồ 28 thể hiện chiều rộng trung bình của những viên kim cương
theo màu. Ta thấy màu J có chiều dài trung bình lớn nhất với 6.52 mm còn
ngắn nhẩt là màu D và E với 5.42 mm
# Load thư viện ggplot2
library(ggplot2)
# Tính giá trung bình của kim cương có màu J theo chất lượng cắt
avg_price <- aggregate(diamonds$price, by = list(diamonds$cut), FUN = mean)
# Vẽ biểu đồ cột
ggplot(subset(diamonds, color == "J"), aes(x = cut, y = price)) +
geom_bar(stat = "summary", fun = "mean", fill = "green", color = "black") +
labs(title = "Giá trung bình của Kim cương màu J theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Giá trung bình") + coord_flip()

Giải thích
đồ thị 29
Trong đó:
Chúng ta sử dụng hàm aggregate() để tính giá trung
bình của các mẫu kim cương có màu J theo chất lượng cắt.
subset(diamonds, color == "J") được sử dụng để lấy
ra chỉ các mẫu kim cương có màu J.
geom_bar(stat = "summary", fun = "mean") được sử
dụng để vẽ các cột biểu diễn giá trung bình của các mẫu kim cương theo
chất lượng cắt.
Các cài đặt khác như tiêu đề và chủ đề của biểu đồ vẫn được giữ
nguyên.
library(ggplot2)
data("diamonds")
# Tính giá trung bình của độ dài x theo chất lượng cắt
mean_x <- aggregate(diamonds$x, by = list(diamonds$cut), FUN = mean)
# Vẽ biểu đồ cột
ggplot(diamonds, aes(x = cut, y = x)) +
geom_bar(stat = "summary", fun = "mean", fill = "skyblue", color = "black") +
geom_text(data = mean_x, aes(x = Group.1, y = x, label = round(x, 1)), vjust = -0.5) +
labs(title = "Độ dài x trung bình của Kim cương theo Chất lượng cắt",
x = "Chất lượng cắt",
y = "Độ dài x trung bình (mm)") + coord_flip()

Giải thích
biểu đồ 30
Chúng ta sử dụng hàm aggregate() để tính giá trung
bình của độ dài x theo mỗi mức chất lượng cắt.
geom_text() được sử dụng để thêm số trung bình lên
các cột, với các tham số x là nhóm (mức chất lượng cắt),
y là giá trị trung bình của độ dài x, và
label là số trung bình (được làm tròn đến 1 chữ số thập
phân).
vjust = -0.5 được sử dụng để căn chỉnh văn bản lên
trên các cột.
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA0Ig0KYXV0aG9yOiAiTmhoYW8iDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclSDolTTolUywgJWQgLSAlbSAtICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jOiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2NhbGVzKQ0KYGBgDQogDQojICoqR2nhu5tpIHRoaeG7h3UgYuG7mSBk4buvIGxp4buHdSBkaWFtb25kcyoqDQoNCkLhu5kgZOG7ryBsaeG7h3UgRGlhbW9uZHMgbMOgIG3hu5l0IGLhu5kgZOG7ryBsaeG7h3UgcGjhu5UgYmnhur9uIHRyb25nIGzEqW5oIHbhu7FjIGtob2EgaOG7jWMgZOG7ryBsaeG7h3UuIELhu5kgZOG7ryBsaeG7h3UgYmFvIGfhu5NtIG5o4buvbmcgdGh14buZYyB0w61uaCB2w6Agbmjhu69uZyB0aMO0bmcgdGluIGxpw6puIHF1YW4gduG7gSBuaOG7r25nIHZpw6puIGtpbSBjxrDGoW5nLiBC4buZIGThu68gbGnhu4d1IGfhu5NtIGPDsyA1Mzk0MCBxdWFuIHPDoXQgdMawxqFuZyDEkcawxqFuZyB24bubaSA1Mzk0MCB2acOqbiBraW0gY8awxqFuZyB2w6AgMTAgxJHhu5FpIHTGsMahbmcgxJHGsMahbmcgduG7m2kgMTAgdGh14buZYyB0w61uaC4NCg0Kw50gbmdoxKlhIHThu6tuZyDEkeG7kWkgdMaw4bujbmc6DQoNCi0gY2FyYXQ6IFRy4buNbmcgbMaw4bujbmcgY+G7p2Ega2ltIGPGsMahbmcsIMSRxqFuIHbhu4sgbMOgIGNhcmF0Lg0KDQotIGN1dDogQ2jhuqV0IGzGsOG7o25nIGPhuq90IGPhu6dhIGtpbSBjxrDGoW5nLiBDw7MgdGjhu4MgbMOgIOKAmEZhaXLigJksIOKAmEdvb2TigJksIOKAmFZlcnkgR29vZOKAmSwg4oCYUHJlbWl1beKAmSwgaG/hurdjIOKAmElkZWFs4oCZLg0KDQotIGNvbG9yOiBNw6B1IHPhuq9jIGPhu6dhIGtpbSBjxrDGoW5nLCB04burIEogKGvDqW0gbmjhuqV0KSDEkeG6v24gRCAodOG7kXQgbmjhuqV0KS4NCg0KLSBjbGFyaXR5OiDEkOG7mSB0aW5oIGtoaeG6v3QgY+G7p2Ega2ltIGPGsMahbmcuIEPDsyB0aOG7gyBsw6Ag4oCYSTHigJkgKGvDqW0gbmjhuqV0KSwg4oCYU0ky4oCZLCDigJhTSTHigJksIOKAmFZTMuKAmSwg4oCYVlMx4oCZLCDigJhWVlMy4oCZLCDigJhWVlMx4oCZLCBob+G6t2Mg4oCYSUbigJkgKHThu5F0IG5o4bqldCkuDQoNCi0gZGVwdGg6IFThu4kgbOG7hyBnaeG7r2EgY2hp4buBdSBjYW8gdsOgIGNoaeG7gXUgcuG7mW5nIGPhu6dhIGtpbSBjxrDGoW5nLCDEkcaw4bujYyB0w61uaCBi4bqxbmcgcGjhuqduIHRyxINtLg0KDQotIHRhYmxlOiBU4buJIGzhu4cgZ2nhu69hIGNoaeG7gXUgcuG7mW5nIGPhu6dhIG3hurd0IHRyw6puIGPDuW5nIChiw6BuKSB2w6AgY2hp4buBdSBy4buZbmcgdOG7lW5nIHRo4buDIGPhu6dhIGtpbSBjxrDGoW5nLCDEkcaw4bujYyB0w61uaCBi4bqxbmcgcGjhuqduIHRyxINtLg0KDQotIHByaWNlOiBHacOhIGPhu6dhIGtpbSBjxrDGoW5nLCDEkcahbiB24buLIGzDoCBVU0QuDQoNCi0geDogQ2hp4buBdSBkw6BpIGPhu6dhIGtpbSBjxrDGoW5nLCDEkcahbiB24buLIGzDoCBtbS4NCg0KLSB5OiBDaGnhu4F1IHLhu5luZyBj4bunYSBraW0gY8awxqFuZywgxJHGoW4gduG7iyBsw6AgbW0uDQoNCi0gejogQ2hp4buBdSBjYW8gY+G7p2Ega2ltIGPGsMahbmcsIMSRxqFuIHbhu4sgbMOgIG1tLg0KDQojICoqMzAgQmnhu4N1IMSR4buTKioNCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCnRtcCA8LSBkaWFtb25kcyANCnRtcCA8LSB0bXAgJT4lIG11dGF0ZShjYXJhdGsgPSBjdXQoY2FyYXQsMywgbGFiZWwgPSBjKCduaOG7jycsJ3bhu6thJywnbOG7m24nKSkpDQp0bXAgJT4lIGdncGxvdChhZXMoeCA9IGNhcmF0aykpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICdibGFjaycpDQpgYGANCg0KDQoNCiMjICoqR2nhuqNpIHRow61jaCBiaeG7g3UgxJHhu5MgMToqKg0KDQrEkeG7kyB0aOG7iyBnacO6cCBzbyBzw6FuaCBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyBrw61jaCB0aMaw4bubYyBs4bubbiwgduG7q2EgdsOgIG5o4buPLg0KVHJvbmcgxJHDsyBz4buRIHZpw6puIGtpbSBjxrDGoW5nIGvDrWNoIHRoxrDhu5tjIG5o4buPIGNoaeG6v20gc+G7kSBsxrDhu6NuZyBs4bubbiBuaOG6pXQgdHJvbmcgdG/DoG4gYuG7mSBk4buvIGxp4buHdSwgduG7m2kgc+G7kSBsxrDhu6NuZyBoxqFuIDUwMDAwLg0KVGnhur9wIMSR4bq/biBsw6Aga2ltIGPGsMahbmcga8OtY2ggdGjGsOG7m2MgduG7q2Ega2hv4bqjbmcgduG7m2kgc+G7kSBsxrDhu6NuZyBraG/huqNuZyAyMDAwIHZpw6puLiBLaMO0bmcgY8OzIGtpbSBjxrDGoW5nIGxv4bqhaSBs4bubbi4NCg0KDQotIC0gLQ0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KdG1wIDwtIHRtcCAlPiUgZ3JvdXBfYnkoY3V0LCBjb2xvcikgJT4lIHN1bW1hcmlzZShTTCA9IG4oKSkNCnRtcCAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0LCB5ID0gU0wpKSArDQogIGdlb21fY29sKGRhdGEgPSB0bXAgJT4lIGZpbHRlcihjb2xvciA9PSAnRCcpLCBmaWxsID0gJ3llbGxvdycpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHRtcCAlPiUgZmlsdGVyKGNvbG9yID09ICdKJyksIGZpbGwgPSAncGluaycpDQoNCmBgYA0KDQoNCiMjICoqR2nhuqNpIHRow61jaCBiaeG7g3UgxJHhu5MgMjoqKg0KDQrEkOG7kyB0aOG7iyBuw6B5IGNobyB0YSBzbyBzw6FuaCDEkcaw4bujYyB04buVbmcgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBtw6B1IG3DoHUgRCB2w6AgbcOgdSBKIGPhu6dhIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nKGN1dCkgY8OzIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UuIEPhu6UgdGjhu4MgbMOgIHThu5VuZyBz4buRIGtpbSBjxrDGoW5nIG3DoHUgRCB2w6AgSiBj4bunYSBraW0gY8awxqFuZyBsb+G6oWkgRmFpciBsw6Agw610IG5o4bqldCBraG/huqNuZyBkxrDhu5tpIDI1MCB2acOqbiwgdGnhur9wIMSR4bq/biBsw6AgbG/huqFpIEdvb2Qga2hv4bqjbmcgNjAwIHZpw6puLCB0aeG6v3AgxJHDsyBsw6AgbG/huqFpIFZlcnkgR29vZCB2w6AgUHJlbWl1bSBs4bqnbiBsxrDhu6N0IHbhu5tpIGtob+G6o25nIDE1MDAgdmnDqm4gdsOgIDE1NTAgdmnDqm4uIExv4bqhaSBJZGVhbCBsw6AgbG/huqFpIGPDsyB04buVbmcgc+G7kSBraW0gY8awxqFuZyBtw6B1IEQgdsOgIEogbOG7m24gbmjhuqV0IHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgduG7m2kga2hv4bqjbmcgMjgwMCB2acOqbi5Ucm9uZyDEkeG7kyB0aOG7iyBuw6B5LG3DoHUgdsOgbmcgYmnhu4N1IGRp4buFbiBraW0gY8awxqFuZyBtw6B1IEQgY8OybiBtw6B1IGjhu5NuZyBiaeG7g3UgZGnhu4VuIGNobyBraW0gY8awxqFuZyBtw6B1IEouDQoNCg0KLSAtIC0NCg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KdG1wIDwtIGRpYW1vbmRzIA0KdG1wIDwtIHRtcCAlPiUgZ3JvdXBfYnkoY3V0LCBjb2xvcikgJT4lIHN1bW1hcmlzZShTTCA9IG4oKSkNCnRtcCAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0LCB5ID0gU0wpKSArDQogIGdlb21fY29sKGRhdGEgPSB0bXAgJT4lIGZpbHRlcihjb2xvciA9PSAnRScpLCBmaWxsID0gJ3JlZCcpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHRtcCAlPiUgZmlsdGVyKGNvbG9yID09ICdGJyksIGZpbGwgPSAncGluaycpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHRtcCAlPiUgZmlsdGVyKGNvbG9yID09ICdEJyksIGZpbGwgPSAnYmx1ZScpDQoNCmBgYA0KDQojIyAqKkdp4bqjaSBUaMOtY2ggYmnhu4N1IMSR4buTIDM6KioNCg0KxJDhu5MgdGjhu4sgbsOgeSBjaG8gdGEgc28gc8OhbmggxJHGsOG7o2MgdOG7lW5nIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgbcOgdSBtw6B1IEUsRiB2w6AgbcOgdSBEIGPhu6dhIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nKGN1dCkgY8OzIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UuIEPhu6UgdGjhu4MgbMOgIHThu5VuZyBz4buRIGtpbSBjxrDGoW5nIG3DoHUgRCxFIHbDoCBGIGPhu6dhIGtpbSBjxrDGoW5nIGxv4bqhaSBGYWlyIGzDoCDDrXQgbmjhuqV0IGtob+G6o25nIGfhuqduIDMwMCB2acOqbiwgdGnhur9wIMSR4bq/biBsw6AgbG/huqFpIEdvb2Qga2hv4bqjbmcgNzUwIHZpw6puLCB0aeG6v3AgxJHDsyBsw6AgbG/huqFpIFByZW1pdW0gdsOgIGxv4bqhaSBWZXJ5IEdvb2QgbOG6p24gbMaw4bujdCB24bubaSBraG/huqNuZyAyNDAwIHZpw6puIHbDoCAyNDUwIHZpw6puLiBMb+G6oWkgSWRlYWwgbMOgIGxv4bqhaSBjw7MgdOG7lW5nIHPhu5Ega2ltIGPGsMahbmcgbcOgdSBELEUgdsOgIEYgbOG7m24gbmjhuqV0IHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgduG7m2kga2hv4bqjbmcgMzgwMCB2acOqbi4NCg0KDQotIC0gLQ0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCnRtcCA8LSBkaWFtb25kcyANCmdncGxvdChkaWFtb25kcywgYWVzKHggPSBjdXQsIHkgPSBjYXJhdCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iLCBmaWxsID0gInNreWJsdWUiKSArDQogIGxhYnModGl0bGUgPSAiR2nDoSB0cuG7iyB0cnVuZyBiw6xuaCIsIHggPSAiQ3V0IiwgeSA9ICJ0YiIpDQoNCmBgYA0KDQoNCg0KIyMgKipHaeG6o2kgdGjDrWNoIGJp4buDdSDEkeG7kyA0OioqDQoNCmdlb21fYmFyKCkgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgduG6vSBiaeG7g3UgxJHhu5MgYmFyIGNoYXJ0LCB24bubaSBzdGF0ID0gc3VtbWFyeSDEkeG7gyB0w61uaCB0b8OhbiB0aOG7kW5nIGvDqiB0csOqbiBk4buvIGxp4buHdQ0KKHRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGNhcmF0KSB2w6AgZnVuID0gbWVhbiDEkeG7gyBjaOG7iSDEkeG7i25oIHLhurFuZyBjaMO6bmcgdGEgbXXhu5FuIHTDrW5oDQpnacOhIHRy4buLIHRydW5nIGLDrG5oLg0KbGFicygpIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIMSR4bq3dCB0acOqdSDEkeG7gSBjaG8gYmnhu4N1IMSR4buTIHbDoCBjw6FjIG5ow6NuIHRy4bulYy4NCkJp4buDdSDEkeG7kyBiYXIgY2hhcnQgaGnhu4NuIHRo4buLIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgY2FyYXQgY2hvDQp04burbmcgbeG7qWMgxJHhu5kgY3V0IHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgZGlhbW9uZHMuQ+G7pSB0aOG7gyBsw6AgZ2nDoSB0cuG7iyBraOG7kWkgbMaw4bujbmcgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgbG/huqFpIEZhaXIgbMOgIGzhu5tuIG5o4bqldA0Ka2hv4bqjbmcgMS4wNSB2w6AgdGjhuqVwIG5o4bqldCBsw6Aga2ltIGPGsMahbmcgbG/huqFpIElkZWFsIGtob+G6o25nIDAuNzgNCg0KLSAtIC0NCg0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQoNCiMgVMOtbmggxJHhu5kgbOG7h2NoIGNodeG6qW4gY+G7p2EgY2FyYXQgY2hvIG3hu5dpIG3hu6ljIMSR4buZIGN1dA0KU0QgPC0gYWdncmVnYXRlKGNhcmF0IH4gY3V0LCBkYXRhID0gZGlhbW9uZHMsIEZVTiA9IHNkKQ0KDQojIFThuqFvIGJp4buDdSDEkeG7kyBiYXIgY2hhcnQNCmdncGxvdChTRCwgYWVzKHggPSBjdXQsIHkgPSBjYXJhdCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAib3JhbmdlIikgKw0KICBsYWJzKHRpdGxlID0gIsSQ4buZIGzhu4djaCBjaHXhuqluIiwgeCA9ICJDdXQiLCB5ID0gIlNkIikNCg0KYGBgDQoNCg0KIyMgKipHaeG6o2kgdGjDrWNoIGJp4buDdSDEkeG7kyA1OioqDQoNCi0gQ2jDum5nIHRhIHPhu60gZOG7pW5nIGjDoG0gYWdncmVnYXRlKCkgxJHhu4MgdMOtbmggxJHhu5kgbOG7h2NoIGNodeG6qW4gY+G7p2EgY2FyYXQgY2hvIG3hu5dpIG3hu6ljIMSR4buZIGN1dCB0cm9uZyBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzLg0KDQotIFNhdSDEkcOzLCBjaMO6bmcgdGEgdOG6oW8gYmnhu4N1IMSR4buTIGJhciBjaGFydCB24bubaSB0cuG7pWMgeCBiaeG7g3UgdGjhu4sgY8OhYyBt4bupYyDEkeG7mSBjdXQgdsOgIHRy4bulYyB5IGJp4buDdSB0aOG7iyDEkeG7mSBs4buHY2ggY2h14bqpbiANCmPhu6dhIGNhcmF0IHTGsMahbmcg4bupbmcuDQoNCioqQmnhu4N1IMSR4buTIG7DoHkgc+G6vSBoaeG7g24gdGjhu4sgxJHhu5kgbOG7h2NoIGNodeG6qW4gY+G7p2EgY2FyYXQgY2hvIG3hu5dpIG3hu6ljIMSR4buZIGN1dCwgZ2nDunAgdGEgaGnhu4N1IHbhu4EgbeG7qWMgxJHhu5kgYmnhur9uIMSR4buZbmcNCmPhu6dhIGNhcmF0IHRyb25nIHThu6tuZyBsb+G6oWkga2ltIGPGsMahbmcqKg0KDQoNCi0gLSAtIA0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpkYXRhKGRpYW1vbmRzKQ0KDQojIGzhu41jIHJhIG5o4buvbmcgdmnDqm4ga2ltIGPGsMahbmcgbcOgdSBEDQpmaWx0ZXJlZF9kYXRhX0QgPC0gc3Vic2V0KGRpYW1vbmRzLCBjb2xvciA9PSAiRCIpDQoNCiMgVMOtbmggZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyBtw6B1IEQNCmF2ZXJhZ2VfcHJpY2UgPC0gYWdncmVnYXRlKHByaWNlIH4gY3V0LCBkYXRhID0gZmlsdGVyZWRfZGF0YV9ELCBGVU4gPSBtZWFuKQ0KZ2dwbG90KGF2ZXJhZ2VfcHJpY2UsIGFlcyh4ID0gY3V0LCB5ID0gcHJpY2UsIGZpbGwgPSBjdXQpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIGxhYnModGl0bGUgPSAiR2nDoSB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyBtw6B1IEQiLCB4ID0gIkN1dCIsIHkgPSAiQXZlcmFnZSBQcmljZSIpICsNCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkN1dCIpDQpgYGANCg0KDQojIyAqKkdp4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDYqKg0KDQotIGF2ZXJhZ2VfcHJpY2UgPC0gYWdncmVnYXRlKHByaWNlIH4gY3V0LCBkYXRhID0gZmlsdGVyZWRfZGF0YV9ELCBGVU4gPSBtZWFuKTogZMO5biDEkeG7gyB0w61uaCBnacOhIHRydW5nIGLDrG5oIGNobyBjw6FjDQp2acOqbiBraW0gY8awxqFuZyBtw6B1IEQuDQoNCi0gbGFicyh0aXRsZSA9ICkgZMO5bmcgxJHhu4MgxJHhurd0IHTDqm4gY2hvIGPDoWMgdHLhu6VjIHbDoCB0w6puIGPhu6dhIHRpw6p1IMSR4buBDQoNCi0gc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkN1dCIpOiBkw7luZyDEkeG7gyBjaMO6IGdp4bqjaSBjaG8gYmnhu4N1IMSR4buTDQoNCioqxJDhu5MgdGjhu4sgbsOgeSBnacO6cCBjaMO6bmcgdGEgY8OzIHRo4buDIHNvIHPDoW5oIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgbcOgdSBEIOG7qW5nIHbhu5tpIGPDoWMga2nhu4N1ICBraW0gY8awxqFuZyAoIGN1dCkqKg0KDQoNCg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmRhdGEoZGlhbW9uZHMpDQojIGzhu41jIHJhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgbcOgdSBFIHbDoCBGDQpmaWx0ZXJlZF9kYXRhX0VGIDwtIHN1YnNldChkaWFtb25kcywgY29sb3IgJWluJSBjKCJFIiwgIkYiKSkNCg0KIyBUw61uaCBnScOhIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIDIgbcOgdSBFIHbDoCBtw6B1IEYNCmF2ZXJhZ2VfcHJpY2UgPC0gYWdncmVnYXRlKHByaWNlIH4gY29sb3IsIGRhdGEgPSBmaWx0ZXJlZF9kYXRhX0VGLCBGVU4gPSBtZWFuKQ0KDQojIENyZWF0ZSBhIGJhciBjaGFydCBmb3IgYXZlcmFnZSBwcmljZXMNCmdncGxvdChhdmVyYWdlX3ByaWNlLCBhZXMoeCA9IGNvbG9yLCB5ID0gcHJpY2UsIGZpbGwgPSBjb2xvcikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgbGFicyh0aXRsZSA9ICJHacOhIHRydW5nIGLDrG5oIGPhu6dhIDIgbcOgdSBraW0gY8awxqFuZyBFIHbDoCBGIiwgeCA9ICJDb2xvciIsIHkgPSAiQXZlcmFnZSBQcmljZSIpICsNCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkNvbG9yIikNCg0KYGBgDQoNCg0KIyMgKipHaeG6o2kgdGjDrWNoIGJp4buDdSDEkeG7kyA3OioqDQoNCi0gVHLhu6VjIHggY+G7p2EgYmnhu4N1IMSR4buTIGJp4buDdSB0aOG7iyBjw6FjIG3DoHUga2ltIGPGsMahbmcsIGJhbyBn4buTbSAiRSIgdsOgICJGIi4NCg0KLSBUcuG7pWMgeSBj4bunYSBiaeG7g3UgxJHhu5MgYmnhu4N1IHRo4buLIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyB2acOqbiBraW0gY8awxqFuZyB0xrDGoW5nIOG7qW5nIHbhu5tpIG3hu5dpIG3DoHUuDQoNCi0gTeG7l2kgY+G7mXQgdHJvbmcgYmnhu4N1IMSR4buTIGJp4buDdSBkaeG7hW4gZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBt4buXaSBtw6B1IGtpbSBjxrDGoW5nLg0KDQotIEJp4buDdSDEkeG7kyBuw6B5IGNobyBjaMO6bmcgdGEgYmnhur90IHLhurFuZyB0cnVuZyBiw6xuaCBnacOhIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgbcOgdSAiRSIgdsOgICJGIiBsw6AgYmFvIG5oacOqdS4gTuG6v3UgY8OzIHPhu7Ega2jDoWMgYmnhu4d0IMSRw6FuZyBr4buDIGdp4buvYSBoYWkgbcOgdSBraW0gY8awxqFuZyBuw6B5LCBjaMO6bmcgdGEgY8OzIHRo4buDIG5o4bqtbiB0aOG6pXkgc+G7sSBiaeG6v24gxJHhu5luZyB0cm9uZyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGdpw6EgZ2nhu69hIGNow7puZy4gDQoNCi0gxJBp4buBdSBuw6B5IGPDsyB0aOG7gyBo4buvdSDDrWNoIHRyb25nIHZp4buHYyBoaeG7g3UgduG7gSBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgY8OzIG3DoHUga2jDoWMgbmhhdSB0cm9uZyB0aOG7iyB0csaw4budbmcuDQoNCg0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZGF0YSgiZGlhbW9uZHMiKQ0KDQoNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGN1dCkpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICJza3libHVlIiwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIlPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QiLA0KICAgICAgIHggPSAiQ2jhuqV0IGzGsOG7o25nIGPhuq90IiwNCiAgICAgICB5ID0gIlPhu5EgbMaw4bujbmciKQ0KDQpgYGANCg0KDQoNCiMjICoqR2nhuqNpIHRow61jaCBiaeG7g3UgxJHhu5MgOCoqDQoNCi0gYGdlb21fYmFyKClgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHThuqFvIGJp4buDdSDEkeG7kyBj4buZdC4NCg0KLSBgZmlsbGAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgY2jhu4kgxJHhu4tuaCBtw6B1IGPhu6dhIGPDoWMgY+G7mXQsIHbDoCBgY29sb3JgIGzDoCBtw6B1IGPhu6dhIMSRxrDhu51uZyB2aeG7gW4gY+G7mXQuDQoNCi0gYGxhYnMoKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgxJHhurd0IHRpw6p1IMSR4buBIGNobyBiaeG7g3UgxJHhu5MgdsOgIGPDoWMgdHLhu6VjLg0KDQoqKkJp4buDdSDEkeG7kyBuw6B5IGNobyBjaMO6bmcgdGEgbeG7mXQgY8OhaSBuaMOsbiB04buVbmcgcXVhbiB24buBIHBow6JuIHBo4buRaSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IGPhu6dhIGNow7puZy4gxJDhu5FpIHbhu5tpIG3hu5dpIGxv4bqhaSBjaOG6pXQgbMaw4bujbmcgY+G6r3QsIGNow7puZyB0YSBjw7MgdGjhu4MgdGjhuqV5IHPhu5EgbMaw4bujbmcgdMawxqFuZyDhu6luZyBj4bunYSBraW0gY8awxqFuZy4qKg0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpkYXRhKCJkaWFtb25kcyIpDQpnZ3Bsb3QoZGlhbW9uZHMsIGFlcyh4ID0gY3V0LCB5ID0gcHJpY2UpKSArDQogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIiwgZmlsbCA9ICJyZWQiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBLaW0gY8awxqFuZyB0aGVvIENo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeCA9ICJDaOG6pXQgbMaw4bujbmcgY+G6r3QiLA0KICAgICAgIHkgPSAiR2nDoSB0cnVuZyBiw6xuaCAoVVNEKSIpDQoNCg0KYGBgDQoNCg0KDQojIyAqKkdp4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDkqKg0KDQpUcm9uZyDEkcOzOg0KDQotIGBhZXMoeCA9IGN1dCwgeSA9IHByaWNlKWA6IFRhIHPhu60gZOG7pW5nIGPhu5l0ICoqY3V0KiogxJHhu4MgbMOgbSB0cuG7pWMgeCAoY2jhuqV0IGzGsOG7o25nIGPhuq90KSB2w6AgY+G7mXQgKipwcmljZSoqIMSR4buDIGzDoG0gdHLhu6VjIHkgKGdpw6EpLg0KDQotIGBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVhbiIpYDogU+G7rSBk4bulbmcgYGdlb21fYmFyKClgIHbhu5tpIGBzdGF0ID0gInN1bW1hcnkiYCDEkeG7gyB0w61uaCBnacOhIHRydW5nIGLDrG5oIHbDoCB24bq9IGPDoWMgY+G7mXQuIENow7puZyB0YSBz4butIGThu6VuZyBgZnVuID0gIm1lYW4iYCDEkeG7gyB0w61uaCBnacOhIHRydW5nIGLDrG5oLg0KDQotIGBmaWxsID0gInJlZCIsIGNvbG9yID0gImJsYWNrImA6IMSQ4bq3dCBtw6B1IGZpbGwgY2hvIGPDoWMgY+G7mXQgbMOgIG3DoHUgxJHhu48gdsOgIG3DoHUgdmnhu4FuIGzDoCBtw6B1IMSRZW4uDQoNCi0gYGxhYnMoKWA6IMSQ4bq3dCB0acOqdSDEkeG7gSBjaG8gYmnhu4N1IMSR4buTIHbDoCBjw6FjIHRy4bulYy4NCg0KKipCaeG7g3UgxJHhu5MgbsOgeSBz4bq9IGhp4buDbiB0aOG7iyBnacOhIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gbeG7l2kgbeG7qWMgY2jhuqV0IGzGsOG7o25nIGPhuq90IHTGsMahbmcg4bupbmcuKioNCg0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZGF0YSgiZGlhbW9uZHMiKQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGN1dCwgeSA9IHByaWNlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVhbiIsIGZpbGwgPSAicHVycGxlIiwgY29sb3IgPSAiYmxhY2siKSArDQogIGxhYnModGl0bGUgPSAiQmnhu4N1IMSR4buTIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgS2ltIGPGsMahbmcgdGhlbyBDaOG6pXQgbMaw4bujbmcgY+G6r3QiLA0KICAgICAgIHggPSAiQ2jhuqV0IGzGsOG7o25nIGPhuq90IiwNCiAgICAgICB5ID0gIkdpw6EgdHJ1bmcgYsOsbmggKFVTRCkiKSArIGNvb3JkX2ZsaXAoKQ0KDQpgYGANCg0KDQojIyAqKkdp4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDEwKioNCg0KVHJvbmcgxJHDszoNCg0KLSBgYWVzKHggPSBjdXQsIHkgPSBwcmljZSlgOiBUYSBz4butIGThu6VuZyBj4buZdCAqKmN1dCoqIMSR4buDIGzDoG0gdHLhu6VjIHggKGNo4bqldCBsxrDhu6NuZyBj4bqvdCkgdsOgIGPhu5l0ICoqcHJpY2UqKiDEkeG7gyBsw6BtIHRy4bulYyB5IChnacOhKS4NCg0KLSBgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iKWA6IFPhu60gZOG7pW5nIGBnZW9tX2JhcigpYCB24bubaSBgc3RhdCA9ICJzdW1tYXJ5ImAgxJHhu4MgdMOtbmggZ2nDoSB0cnVuZyBiw6xuaCB2w6AgduG6vSBjw6FjIGPhu5l0LiBDaMO6bmcgdGEgc+G7rSBk4bulbmcgYGZ1biA9ICJtZWFuImAgxJHhu4MgdMOtbmggZ2nDoSB0cnVuZyBiw6xuaC4NCg0KLSBgZmlsbCA9ICJwdXJwbGUiLCBjb2xvciA9ICJibGFjayJgOiDEkOG6t3QgbcOgdSBmaWxsIGNobyBjw6FjIGPhu5l0IGzDoCBtw6B1IHTDrW0gdsOgIG3DoHUgdmnhu4FuIGzDoCBtw6B1IMSRZW4uDQoNCi0gYGxhYnMoKWA6IMSQ4bq3dCB0acOqdSDEkeG7gSBjaG8gYmnhu4N1IMSR4buTIHbDoCBjw6FjIHRy4bulYy4NCg0KLSBjb29yZF9mbGlwKCk6IGzDoG0gY2hvIGJp4buDdSDEkeG7kyBu4bqxbSBuZ2FuZw0KDQoqKkJp4buDdSDEkeG7kyBuw6B5IHPhur0gaGnhu4NuIHRo4buLIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBt4buXaSBt4bupYyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdMawxqFuZyDhu6luZy4qKg0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZGF0YSgiZGlhbW9uZHMiKQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGN1dCwgeSA9IHkpKSArDQogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIiwgZmlsbCA9ICJncmVlbiIsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIsSQ4buZIHLhu5luZyB5IHRydW5nIGLDrG5oIGPhu6dhIEtpbSBjxrDGoW5nIHRoZW8gQ2jhuqV0IGzGsOG7o25nIGPhuq90IiwNCiAgICAgICB4ID0gIkNo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeSA9ICLEkOG7mSBy4buZbmcgeSB0cnVuZyBiw6xuaCAobW0pIikNCg0KYGBgDQoNCg0KIyMgKipHSeG6o2kgdGjDrWNoIGJp4buDdSDEkeG7kyAxMSoqDQoNClRyb25nIGJp4buDdSDEkeG7kyBuw6B5Og0KDQotIGBhZXMoeCA9IGN1dCwgeSA9IHkpYDogQ2jDum5nIHRhIHPhu60gZOG7pW5nIGPhu5l0ICoqY3V0KiogxJHhu4MgbMOgbSB0cuG7pWMgeCAoY2jhuqV0IGzGsOG7o25nIGPhuq90KSB2w6AgY+G7mXQgKip5KirEkeG7gyBsw6BtIHRy4bulYyB5ICjEkeG7mSBy4buZbmcgeSkuDQoNCi0gYGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIilgOiBT4butIGThu6VuZyBgZ2VvbV9iYXIoKWAgduG7m2kgYHN0YXQgPSAic3VtbWFyeSJgIMSR4buDIHTDrW5oIMSR4buZIHLhu5luZyB5IHRydW5nIGLDrG5oIHbDoCB24bq9IGPDoWMgY+G7mXQuIENow7puZyB0YSBz4butIGThu6VuZyBgZnVuID0gIm1lYW4iYCDEkeG7gyB0w61uaCBnacOhIHRydW5nIGLDrG5oLg0KDQotIGBmaWxsID0gImdyZWVuIiwgY29sb3IgPSAiYmxhY2siYDogxJDhurd0IG3DoHUgZmlsbCBjaG8gY8OhYyBj4buZdCBsw6AgbcOgdSB4YW5oIGzDoSBjw6J5IHbDoCBtw6B1IHZp4buBbiBsw6AgbcOgdSDEkWVuLg0KDQotIGBsYWJzKClgOiDEkOG6t3QgdGnDqnUgxJHhu4EgY2hvIGJp4buDdSDEkeG7kyB2w6AgY8OhYyB0cuG7pWMuDQoNCg0KKipCaeG7g3UgxJHhu5MgbsOgeSBz4bq9IGhp4buDbiB0aOG7iyDEkeG7mSBy4buZbmcgeSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIG3hu5dpIG3hu6ljIGNo4bqldCBsxrDhu6NuZyBj4bqvdCB0xrDGoW5nIOG7qW5nLioqDQoNCg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmRhdGEoImRpYW1vbmRzIikNCmdncGxvdChkaWFtb25kcywgYWVzKHggPSBjdXQsIHkgPSB5KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVhbiIsIGZpbGwgPSAiZ3JlZW4iLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICLEkOG7mSBy4buZbmcgeSB0cnVuZyBiw6xuaCBj4bunYSBLaW0gY8awxqFuZyB0aGVvIENo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeCA9ICJDaOG6pXQgbMaw4bujbmcgY+G6r3QiLA0KICAgICAgIHkgPSAixJDhu5kgcuG7mW5nIHkgdHJ1bmcgYsOsbmggKG1tKSIpICsgY29vcmRfZmxpcCgpDQoNCmBgYA0KDQojIyAqKkdJ4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDEyKioNCg0KVHJvbmcgYmnhu4N1IMSR4buTIG7DoHk6DQoNCi0gYGFlcyh4ID0gY3V0LCB5ID0geSlgOiBDaMO6bmcgdGEgc+G7rSBk4bulbmcgY+G7mXQgKipjdXQqKiDEkeG7gyBsw6BtIHRy4bulYyB4IChjaOG6pXQgbMaw4bujbmcgY+G6r3QpIHbDoCBj4buZdCAqKnkqKsSR4buDIGzDoG0gdHLhu6VjIHkgKMSR4buZIHLhu5luZyB5KS4NCg0KLSBgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iKWA6IFPhu60gZOG7pW5nIGBnZW9tX2JhcigpYCB24bubaSBgc3RhdCA9ICJzdW1tYXJ5ImAgxJHhu4MgdMOtbmggxJHhu5kgcuG7mW5nIHkgdHJ1bmcgYsOsbmggdsOgIHbhur0gY8OhYyBj4buZdC4gQ2jDum5nIHRhIHPhu60gZOG7pW5nIGBmdW4gPSAibWVhbiJgIMSR4buDIHTDrW5oIGdpw6EgdHJ1bmcgYsOsbmguDQoNCi0gYGZpbGwgPSAiZ3JlZW4iLCBjb2xvciA9ICJibGFjayJgOiDEkOG6t3QgbcOgdSBmaWxsIGNobyBjw6FjIGPhu5l0IGzDoCBtw6B1IHhhbmggbMOhIGPDonkgdsOgIG3DoHUgdmnhu4FuIGzDoCBtw6B1IMSRZW4uDQoNCi0gYGxhYnMoKWA6IMSQ4bq3dCB0acOqdSDEkeG7gSBjaG8gYmnhu4N1IMSR4buTIHbDoCBjw6FjIHRy4bulYy4NCg0KLSBjb29yZF9mbGlwKCk6IGzDoG0gY2hvIMSR4buTIHRo4buLIG7hurFtIG5nYW5nDQoNCioqQmnhu4N1IMSR4buTIG7DoHkgc+G6vSBoaeG7g24gdGjhu4sgxJHhu5kgcuG7mW5nIHkgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBt4buXaSBt4bupYyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdMawxqFuZyDhu6luZy4qKg0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpkYXRhKCJkaWFtb25kcyIpDQojIFTDrW5oIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgxJHhu5kgZMOgaSB4IHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90DQptZWFuX3ggPC0gYWdncmVnYXRlKGRpYW1vbmRzJHgsIGJ5ID0gbGlzdChkaWFtb25kcyRjdXQpLCBGVU4gPSBtZWFuKQ0KDQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0DQpnZ3Bsb3QoZGlhbW9uZHMsIGFlcyh4ID0gY3V0LCB5ID0geCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iLCBmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV90ZXh0KGRhdGEgPSBtZWFuX3gsIGFlcyh4ID0gR3JvdXAuMSwgeSA9IHgsIGxhYmVsID0gcm91bmQoeCwgMSkpLCB2anVzdCA9IC0wLjUpICsNCiAgbGFicyh0aXRsZSA9ICLEkOG7mSBkw6BpIHggdHJ1bmcgYsOsbmggY+G7p2EgS2ltIGPGsMahbmcgdGhlbyBDaOG6pXQgbMaw4bujbmcgY+G6r3QiLA0KICAgICAgIHggPSAiQ2jhuqV0IGzGsOG7o25nIGPhuq90IiwNCiAgICAgICB5ID0gIsSQ4buZIGTDoGkgeCB0cnVuZyBiw6xuaCAobW0pIikgDQpgYGANCg0KDQoNCiMjICoqR2nhuqNpIHRow61jaCBiaeG7g3UgxJHhu5MgMTMqKg0KDQotIENow7puZyB0YSBz4butIGThu6VuZyBow6BtIGBhZ2dyZWdhdGUoKWAgxJHhu4MgdMOtbmggZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSDEkeG7mSBkw6BpIHggdGhlbyBt4buXaSBt4bupYyBjaOG6pXQgbMaw4bujbmcgY+G6r3QuDQoNCi0gYGdlb21fdGV4dCgpYCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyB0aMOqbSBz4buRIHRydW5nIGLDrG5oIGzDqm4gY8OhYyBj4buZdCwgduG7m2kgY8OhYyB0aGFtIHPhu5EgYHhgIGzDoCBuaMOzbSAobeG7qWMgY2jhuqV0IGzGsOG7o25nIGPhuq90KSwgYHlgIGzDoCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIMSR4buZIGTDoGkgKip4KiosIHbDoCBgbGFiZWxgIGzDoCBz4buRIHRydW5nIGLDrG5oICjEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAxIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuKS4NCg0KLSBgdmp1c3QgPSAtMC41YCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBjxINuIGNo4buJbmggdsSDbiBi4bqjbiBsw6puIHRyw6puIGPDoWMgY+G7mXQuDQoNCiAqKkJp4buDdSDEkeG7kyBuw6B5IHPhur0gaGnhu4NuIHRo4buLIMSR4buZIGTDoGkgeCB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIG3hu5dpIG3hu6ljIGNo4bqldCBsxrDhu6NuZyBj4bqvdCwgdsOgIHPhu5EgdHJ1bmcgYsOsbmggc+G6vSDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHLDqm4gxJHhu4luaCBj4bunYSB04burbmcgY+G7mXQuKioNCg0KDQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIGdncGxvdDINCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGN1dCwgeSA9IHgpKSArDQogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIiwgZmlsbCA9ICJibHVlIiwgY29sb3IgPSAiYmxhY2siKSArDQogIGxhYnModGl0bGUgPSAixJDhu5kgZMOgaSB4IHRydW5nIGLDrG5oIGPhu6dhIEtpbSBjxrDGoW5nIHRoZW8gQ2jhuqV0IGzGsOG7o25nIGPhuq90IiwNCiAgICAgICB4ID0gIkNo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeSA9ICLEkOG7mSBkw6BpIHggdHJ1bmcgYsOsbmggKG1tKSIpDQpgYGANCg0KIyMgKipHaeG6o2kgdGjDrWNoIGJp4buDdSDEkeG7kyAxNCoqDQoNCg0KVHJvbmcgYmnhu4N1IMSR4buTIG7DoHk6DQoNCg0KLSBgYWVzKHggPSBjdXQsIHkgPSB4KWA6IENow7puZyB0YSBz4butIGThu6VuZyBj4buZdCAiY3V0IiDEkeG7gyBsw6BtIHRy4bulYyB4IChjaOG6pXQgbMaw4bujbmcgY+G6r3QpIHbDoCBj4buZdCAieCIgxJHhu4MgbMOgbSB0cuG7pWMgeSAoxJHhu5kgZMOgaSB4KS4NCi0gYGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIilgOiBT4butIGThu6VuZyBgZ2VvbV9iYXIoKWAgduG7m2kgYHN0YXQgPSAic3VtbWFyeSJgIMSR4buDIHTDrW5oIMSR4buZIGTDoGkgeCB0cnVuZyBiw6xuaCB2w6AgduG6vSBjw6FjIGPhu5l0LiBDaMO6bmcgdGEgc+G7rSBk4bulbmcgYGZ1biA9ICJtZWFuImAgxJHhu4MgdMOtbmggZ2nDoSB0cnVuZyBiw6xuaC4NCg0KLSBgZmlsbCA9ICJibHVlIiwgY29sb3IgPSAiYmxhY2siYDogxJDhurd0IG3DoHUgZmlsbCBjaG8gY8OhYyBj4buZdCBsw6AgbcOgdSB4YW5oIGRhIHRy4budaSB2w6AgbcOgdSB2aeG7gW4gbMOgIG3DoHUgxJFlbi4NCg0KLSBgbGFicygpYDogxJDhurd0IHRpw6p1IMSR4buBIGNobyBiaeG7g3UgxJHhu5MgdsOgIGPDoWMgdHLhu6VjLg0KDQoqKkJp4buDdSDEkeG7kyBuw6B5IHPhur0gaGnhu4NuIHRo4buLIMSR4buZIGTDoGkgeCB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIG3hu5dpIG3hu6ljIGNo4bqldCBsxrDhu6NuZyBj4bqvdCB0xrDGoW5nIOG7qW5nLioqDQoNCg0KDQpgYGB7cn0NCiMgTG9hZCB0aMawIHZp4buHbiBnZ3Bsb3QyDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgVMOtbmggxJHhu5kgZMOgaSB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIG3huqt1IGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYw0KbWVhbl9sZW5ndGggPC0gYWdncmVnYXRlKGRpYW1vbmRzJHgsIGJ5ID0gbGlzdChkaWFtb25kcyRjb2xvciksIEZVTiA9IG1lYW4pDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQNCmdncGxvdChtZWFuX2xlbmd0aCwgYWVzKHggPSBHcm91cC4xLCB5ID0geCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAicmVkIiwgY29sb3IgPSAiYmxhY2siKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4LCAxKSksIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiYmxhY2siKSArDQogIGxhYnModGl0bGUgPSAixJDhu5kgZMOgaSB0cnVuZyBiw6xuaCBj4bunYSBLaW0gY8awxqFuZyB0aGVvIE3DoHUgc+G6r2MiLA0KICAgICAgIHggPSAiTcOgdSBz4bqvYyIsDQogICAgICAgeSA9ICLEkOG7mSBkw6BpIHRydW5nIGLDrG5oIChtbSkiKQ0KDQpgYGANCg0KDQojIyAqKkdp4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDE1KioNCg0KDQpUcm9uZyDEkcOzOiANCg0KLSBDaMO6bmcgdGEgc+G7rSBk4bulbmcgaMOgbSBgYWdncmVnYXRlKClgIMSR4buDIHTDrW5oIMSR4buZIGTDoGkgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBt4bqrdSBraW0gY8awxqFuZyB0aGVvIG3DoHUgc+G6r2MuDQoNCi0gYGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgduG6vSBjw6FjIGPhu5l0IGThu7FhIHRyw6puIGdpw6EgdHLhu4sgdHJvbmcgY+G7mXQgeS4NCg0KLSBgZ2VvbV90ZXh0KClgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHRow6ptIHPhu5EgdHLDqm4gY8OhYyBj4buZdCwgduG7m2kgY8OhYyB0aGFtIHPhu5EgYGxhYmVsYCBsw6AgZ2nDoSB0cuG7iyDEkeG7mSBkw6BpIHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyBtw6B1IHPhuq9jICjEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAxIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuKS4NCg0KLSBgdmp1c3QgPSAtMC41YCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBjxINuIGNo4buJbmggdsSDbiBi4bqjbiBsw6puIHRyw6puIGPDoWMgY+G7mXQuDQoNCi0gYGNvbG9yID0gImJsYWNrImAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgxJHhurd0IG3DoHUgY2hvIHbEg24gYuG6o24gbMOgIG3DoHUgxJFlbi4NCg0KKipCaeG7g3UgxJHhu5MgbsOgeSBz4bq9IGhp4buDbiB0aOG7iyDEkeG7mSBkw6BpIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gbeG7l2kgbcOgdSBz4bqvYywgdsOgIHPhu5EgdHJ1bmcgYsOsbmggc+G6vSDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHLDqm4gxJHhu4luaCBj4bunYSB04burbmcgY+G7mXQuKioNCg0KDQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIGdncGxvdDINCmxpYnJhcnkoZ2dwbG90MikNCiMgVMOtbmggxJHhu5kgc8OidSB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIG3huqt1IGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90DQptZWFuX2RlcHRoIDwtIGFnZ3JlZ2F0ZShkaWFtb25kcyRkZXB0aCwgYnkgPSBsaXN0KGRpYW1vbmRzJGN1dCksIEZVTiA9IG1lYW4pDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQNCmdncGxvdChtZWFuX2RlcHRoLCBhZXMoeCA9IEdyb3VwLjEsIHkgPSB4KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJvcmFuZ2UiLCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKHgsIDEpKSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJncmVlbiIpICsNCiAgbGFicyh0aXRsZSA9ICLEkOG7mSBzw6J1IHRydW5nIGLDrG5oIGPhu6dhIEtpbSBjxrDGoW5nIHRoZW8gQ2jhuqV0IGzGsOG7o25nIGPhuq90IiwNCiAgICAgICB4ID0gIkNo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeSA9ICLEkOG7mSBzw6J1IHRydW5nIGLDrG5oICglKSIpDQoNCmBgYA0KDQoNCiMjICoqR2nhuqNpIHRow61jaCBiaeG7g3UgxJHhu5MgMTYqKg0KDQpUcm9uZyBiaeG7g3UgxJHhu5MgbsOgeToNCi0gQ2jDum5nIHRhIHPhu60gZOG7pW5nIGjDoG0gYGFnZ3JlZ2F0ZSgpYCDEkeG7gyB0w61uaCDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIGPhu6dhIGPDoWMgbeG6q3Uga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QuDQoNCi0gYGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgduG6vSBjw6FjIGPhu5l0IGThu7FhIHRyw6puIGdpw6EgdHLhu4sgdHJvbmcgY+G7mXQgeS4NCg0KLSBgZ2VvbV90ZXh0KClgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHRow6ptIHPhu5EgdHJ1bmcgYsOsbmggbMOqbiBjw6FjIGPhu5l0LCB24bubaSBgbGFiZWxgIGzDoCBnacOhIHRy4buLIMSR4buZIHPDonUgdHJ1bmcgYsOsbmggY+G7p2EgdOG7q25nIGxv4bqhaSBjaOG6pXQgbMaw4bujbmcgY+G6r3QgKMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDEgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4pLg0KDQotIGB2anVzdCA9IC0wLjVgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGPEg24gY2jhu4luaCB2xINuIGLhuqNuIGzDqm4gdHLDqm4gY8OhYyBj4buZdC4NCg0KLSBmaWxsID0gIm9yYW5nZSIsIGNvbG9yID0gImJsYWNrIiA6IG3DoHUgY+G7p2EgYmnhu4N1IMSR4buTIGzDoCBtw6B1IGNhbSB2w6AgY+G7p2EgY2jhu68gc+G7kSB0csOqbiBjw6FjIGPhu5l0IGzDoCBtw6B1IHhhbmggbMOhLg0KDQoqKkJp4buDdSDEkeG7kyBuw6B5IHPhur0gaGnhu4NuIHRo4buLIMSR4buZIHPDonUgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBt4buXaSBt4bupYyBjaOG6pXQgbMaw4bujbmcgY+G6r3QgdMawxqFuZyDhu6luZy4qKg0KDQoNCg0KYGBge3J9DQojIExvYWQgdGjGsCB2aeG7h24gZ2dwbG90Mg0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIFTDrW5oIMSR4buZIGzhu4djaCBjaHXhuqluIGPhu6dhIGdpw6EgY2hvIGPDoWMga2ltIGPGsMahbmcgbcOgdSBFLCBGIHbDoCBKDQpzdGRfZGV2IDwtIGFnZ3JlZ2F0ZShwcmljZSB+IGNvbG9yLCBkYXRhID0gc3Vic2V0KGRpYW1vbmRzLCBjb2xvciAlaW4lIGMoIkUiLCAiRiIsICJKIikpLCBGVU4gPSBzZCkNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KHN0ZF9kZXYsIGFlcyh4ID0gY29sb3IsIHkgPSBwcmljZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIsIGNvbG9yID0gImJsYWNrIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQocHJpY2UsIDEpKSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJyZWQiKSArDQogIGxhYnModGl0bGUgPSAixJDhu5kgbOG7h2NoIGNodeG6qW4gduG7gSBnacOhIGPhu6dhIEtpbSBjxrDGoW5nIG3DoHUgRSwgRiwgSiIsDQogICAgICAgeCA9ICJNw6B1IHPhuq9jIiwNCiAgICAgICB5ID0gIsSQ4buZIGzhu4djaCBjaHXhuqluIGdpw6EiKQ0KDQpgYGANCg0KDQojIyAqKkdp4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDE3KioNCg0KDQpUcm9uZyDEkcOzOg0KDQotIENow7puZyB0YSBz4butIGThu6VuZyBow6BtIGBzdWJzZXQoKWAgxJHhu4MgbOG6pXkgY8OhYyBt4bqrdSBraW0gY8awxqFuZyBjw7MgbcOgdSBz4bqvYyBsw6AgRSwgRiB2w6AgSiB04burIGLhu5kgZOG7ryBsaeG7h3UgYGRpYW1vbmRzYC4NCg0KLSBTYXUgxJHDsywgY2jDum5nIHRhIHTDrW5oIMSR4buZIGzhu4djaCBjaHXhuqluIGPhu6dhIGdpw6EgY2hvIG3hu5dpIG3DoHUgc+G6r2Mgc+G7rSBk4bulbmcgaMOgbSBgYWdncmVnYXRlKClgIHbhu5tpIGBGVU4gPSBzZGAuDQoNCi0gYGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgduG6vSBjw6FjIGPhu5l0IGThu7FhIHRyw6puIGdpw6EgdHLhu4sgdHJvbmcgY+G7mXQgeS4NCg0KLSBgZ2VvbV90ZXh0KClgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHRow6ptIHPhu5EgxJHhu5kgbOG7h2NoIGNodeG6qW4gbMOqbiBjw6FjIGPhu5l0LCB24bubaSBgbGFiZWxgIGzDoCBnacOhIHRy4buLIMSR4buZIGzhu4djaCBjaHXhuqluIGPhu6dhIHThu6tuZyBtw6B1IHPhuq9jICjEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAxIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuKS4NCg0KLSBgdmp1c3QgPSAtMC41YCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBjxINuIGNo4buJbmggdsSDbiBi4bqjbiBsw6puIHRyw6puIGPDoWMgY+G7mXQuDQoNCi0gZmlsbCA9ICJza3libHVlIiwgY29sb3IgPSAiYmxhY2siOiBiaeG7g3UgxJHhu5MgbcOgdSB4YW5oIGRhIHRy4budaSB2w6Agdmnhu4FuIMSRZW4NCg0KLSBjb2xvciA9ICJyZWQiOiBz4buRIHRyw6puIGJp4buDdSDEkeG7kyBtw6B1IMSR4buPDQoNCioqQmnhu4N1IMSR4buTIG7DoHkgc+G6vSBoaeG7g24gdGjhu4sgxJHhu5kgbOG7h2NoIGNodeG6qW4gduG7gSBnacOhIGPhu6dhIGPDoWMga2ltIGPGsMahbmcgbcOgdSBFLCBGIHbDoCBKLioqDQoNCg0KDQpgYGB7cn0NCiMgTG9hZCB0aMawIHZp4buHbiBnZ3Bsb3QyDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgVMOtbmggxJHhu5kgbOG7h2NoIGNodeG6qW4gY+G7p2EgZ2nDoSBjaG8gY8OhYyBraW0gY8awxqFuZyBtw6B1IEQsIEYgdsOgIEoNCnN0ZF9kZXYgPC0gYWdncmVnYXRlKHByaWNlIH4gY29sb3IsIGRhdGEgPSBzdWJzZXQoZGlhbW9uZHMsIGNvbG9yICVpbiUgYygiRCIsICJGIiwgIkoiKSksIEZVTiA9IHNkKQ0KDQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0DQpnZ3Bsb3Qoc3RkX2RldiwgYWVzKHggPSBwcmljZSwgeSA9IGNvbG9yKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJ5ZWxsb3ciLCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKHByaWNlLCAxKSksIGhqdXN0ID0gLTAuMywgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIsSQ4buZIGzhu4djaCBjaHXhuqluIHbhu4EgZ2nDoSBj4bunYSBLaW0gY8awxqFuZyBtw6B1IEQsIEYsIEoiLA0KICAgICAgIHggPSAixJDhu5kgbOG7h2NoIGNodeG6qW4gZ2nDoSIsDQogICAgICAgeSA9ICJNw6B1IHPhuq9jIikgKw0KICBjb29yZF9mbGlwKCkNCmBgYA0KDQojIyAqKkdp4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDE4OioqDQoNCg0KVMawxqFuZyB04buxIG5oxrAgYmnhu4N1IMSR4buTIDE3LCBjaOG7iSDEkeG7lWkgbcOgdSBFIHRow6BuaCBtw6B1IEQNCg0KDQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIGdncGxvdDINCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBUw61uaCBz4buRIGzGsOG7o25nIGPhu6dhIG3hu5dpIG3hu6ljIMSR4buZIGNsYXJpdHkNCmNsYXJpdHlfY291bnQgPC0gdGFibGUoZGlhbW9uZHMkY2xhcml0eSkNCg0KIyBDaHV54buDbiB0YWJsZSB0aMOgbmggZGF0YWZyYW1lIMSR4buDIGThu4UgduG6vSBiaeG7g3UgxJHhu5MNCmNsYXJpdHlfZGYgPC0gYXMuZGF0YS5mcmFtZShjbGFyaXR5X2NvdW50KQ0KbmFtZXMoY2xhcml0eV9kZikgPC0gYygiQ2xhcml0eSIsICJDb3VudCIpDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQNCmdncGxvdChjbGFyaXR5X2RmLCBhZXMoeCA9IENsYXJpdHksIHkgPSBDb3VudCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiYmx1ZSIsIGNvbG9yID0gImJsYWNrIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gQ291bnQpLCB2anVzdCA9IC0wLjgsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIlPhu5EgbMaw4bujbmcgY8OhYyBt4bupYyBDbGFyaXR5IGPhu6dhIEtpbSBjxrDGoW5nIiwNCiAgICAgICB4ID0gIkNsYXJpdHkiLA0KICAgICAgIHkgPSAiU+G7kSBsxrDhu6NuZyIpDQoNCmBgYA0KDQoNCiMjICoqR2nhuqNpIHRow61jaCBiaeG7g3UgxJHhu5MgMTkqKg0KDQpUcm9uZyDEkcOzOg0KDQotIENow7puZyB0YSBz4butIGThu6VuZyBow6BtIGB0YWJsZSgpYCDEkeG7gyB0w61uaCBz4buRIGzGsOG7o25nIGPhu6dhIG3hu5dpIG3hu6ljIMSR4buZIGNsYXJpdHkgdHJvbmcgY+G7mXQgYGNsYXJpdHlgLg0KDQotIFNhdSDEkcOzLCBjaMO6bmcgdGEgY2h1eeG7g24ga+G6v3QgcXXhuqMgY+G7p2EgYHRhYmxlKClgIHRow6BuaCBt4buZdCBkYXRhZnJhbWUgxJHhu4MgZOG7hSBkw6BuZyB24bq9IGJp4buDdSDEkeG7ky4NCg0KLSBgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpYCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyB24bq9IGPDoWMgY+G7mXQgZOG7sWEgdHLDqm4gZ2nDoSB0cuG7iyB0cm9uZyBj4buZdCB5Lg0KDQotIGBnZW9tX3RleHQoKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgdGjDqm0gc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbeG7qWMgY2xhcml0eSBsw6puIHRyw6puIGPDoWMgY+G7mXQuDQoNCg0KKipCaeG7g3UgxJHhu5MgbsOgeSBz4bq9IGhp4buDbiB0aOG7iyBz4buRIGzGsOG7o25nIGPDoWMgbeG7qWMgxJHhu5kgY2xhcml0eSBj4bunYSBraW0gY8awxqFuZywgZ2nDunAgcGjDom4gdMOtY2ggcGjDom4gYuG7kSBj4bunYSBk4buvIGxp4buHdSB0cm9uZyBj4buZdCBjbGFyaXR5LioqDQoNCg0KDQpgYGB7cn0NCiMgTG9hZCB0aMawIHZp4buHbiBnZ3Bsb3QyDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgVMOtbmggZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBt4buXaSBt4bupYyDEkeG7mSBjbGFyaXR5DQpjbGFyaXR5X3ByaWNlIDwtIGFnZ3JlZ2F0ZShkaWFtb25kcyRwcmljZSwgYnkgPSBsaXN0KGRpYW1vbmRzJGNsYXJpdHkpLCBGVU4gPSBtZWFuKQ0KDQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0DQpnZ3Bsb3QoY2xhcml0eV9wcmljZSwgYWVzKHggPSBHcm91cC4xLCB5ID0geCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiYmxhY2siLCBjb2xvciA9ICJyZWQiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZCh4LCAxKSksIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiZ3JlZW4iKSArDQogIGxhYnModGl0bGUgPSAiR2nDoSB0cnVuZyBiw6xuaCBj4bunYSBLaW0gY8awxqFuZyB0aGVvIE3hu6ljIMSR4buZIENsYXJpdHkiLA0KICAgICAgIHggPSAiTeG7qWMgxJHhu5kgQ2xhcml0eSIsDQogICAgICAgeSA9ICJHacOhIHRydW5nIGLDrG5oIikNCg0KYGBgDQoNCg0KDQojIyAqKkdp4bqjaSB0aMOtY2ggxJHhu5MgdGjhu4sgMjAqKg0KDQpUcm9uZyDEkcOzOg0KDQotIENow7puZyB0YSBz4butIGThu6VuZyBow6BtIGBhZ2dyZWdhdGUoKWAgxJHhu4MgdMOtbmggZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBt4buXaSBt4bupYyDEkeG7mSBjbGFyaXR5IHRyb25nIGPhu5l0IGBwcmljZWAuDQoNCi0gYGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgduG6vSBjw6FjIGPhu5l0IGThu7FhIHRyw6puIGdpw6EgdHLhu4sgdHJvbmcgY+G7mXQgeS4NCg0KLSBgZ2VvbV90ZXh0KClgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHRow6ptIGdpw6EgdHLhu4sgZ2nDoSB0cnVuZyBiw6xuaCBsw6puIHRyw6puIGPDoWMgY+G7mXQuDQoNCi0gYWVzKGxhYmVsID0gcm91bmQoeCwgMSkpLCB2anVzdCA9IC0wLjUsIGNvbG9yID0gImdyZWVuIjogxJHhu4MgbMOgbSB0csOybiBnacOhIHRydW5nIGLDrG5oIMSR4bq/biAxIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuIHbDoCBtw6B1IGNo4buvIHPhu5EgdHLDqm4gY8OhYyBj4buZdCBsw6AgbcOgdSB4YW5oIGzDoQ0KDQotIGxhYnModGl0bGUgKTogxJHhurd0IHTDqm4gdGnDqnUgxJHhu4EgdsOgIGPDoWMgdHLhu6VjDQoNCioqQmnhu4N1IMSR4buTIG7DoHkgc+G6vSBoaeG7g24gdGjhu4sgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIG3hu5dpIG3hu6ljIMSR4buZIGNsYXJpdHksIGdpw7pwIHBow6JuIHTDrWNoIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgZ2nDoSB2w6AgY2xhcml0eSBj4bunYSBraW0gY8awxqFuZy4qKg0KDQoNCg0KYGBge3J9DQojIExvYWQgdGjGsCB2aeG7h24gZ2dwbG90Mg0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIFTDrW5oIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgbeG7l2kgbeG7qWMgxJHhu5kgY2xhcml0eQ0KY2xhcml0eV9wcmljZSA8LSBhZ2dyZWdhdGUoZGlhbW9uZHMkcHJpY2UsIGJ5ID0gbGlzdChkaWFtb25kcyRjbGFyaXR5KSwgRlVOID0gbWVhbikNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KGNsYXJpdHlfcHJpY2UsIGFlcyh4ID0gR3JvdXAuMSwgeSA9IHgpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gImJsYWNrIiwgY29sb3IgPSAicmVkIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoeCwgMSkpLCB2anVzdCA9IC0wLjUsIGNvbG9yID0gImdyZWVuIikgKw0KICBsYWJzKHRpdGxlID0gIkdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgS2ltIGPGsMahbmcgdGhlbyBN4bupYyDEkeG7mSBDbGFyaXR5IiwNCiAgICAgICB4ID0gIk3hu6ljIMSR4buZIENsYXJpdHkiLA0KICAgICAgIHkgPSAiR2nDoSB0cnVuZyBiw6xuaCIpICsgY29vcmRfZmxpcCgpDQoNCmBgYA0KDQoNCiMjICoqR2nhuqNpIHRow61jaCDEkeG7kyB0aOG7iyAyMSoqDQoNCkdp4buRbmcgxJHhu5MgdGjhu4sgMjAgbmjGsG5nIGNo4buJIHRoYXkgxJHhu5VpIHbhu4sgdHLDrSAyIHRy4bulYyB04buNYSDEkeG7mQ0KDQoNCg0KYGBge3J9DQojIExvYWQgdGjGsCB2aeG7h24gZ2dwbG90Mg0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIFTDrW5oIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgY8OzIG3DoHUgSiB0aGVvIGNo4bqldCBsxrDhu6NuZyBj4bqvdA0KYXZnX3ByaWNlIDwtIGFnZ3JlZ2F0ZShkaWFtb25kcyRwcmljZSwgYnkgPSBsaXN0KGRpYW1vbmRzJGN1dCksIEZVTiA9IG1lYW4pDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQNCmdncGxvdChzdWJzZXQoZGlhbW9uZHMsIGNvbG9yID09ICJKIiksIGFlcyh4ID0gY3V0LCB5ID0gcHJpY2UpKSArDQogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIiwgZmlsbCA9ICJncmVlbiIsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIkdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgS2ltIGPGsMahbmcgbcOgdSBKIHRoZW8gQ2jhuqV0IGzGsOG7o25nIGPhuq90IiwNCiAgICAgICB4ID0gIkNo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeSA9ICJHacOhIHRydW5nIGLDrG5oIikNCmBgYA0KDQoNCiMjICoqR2nhuqNpIHRow61jaCDEkeG7kyB0aOG7iyAyMioqDQoNCg0KVHJvbmcgxJHDszogDQoNCg0KLSBDaMO6bmcgdGEgc+G7rSBk4bulbmcgaMOgbSBgYWdncmVnYXRlKClgIMSR4buDIHTDrW5oIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBt4bqrdSBraW0gY8awxqFuZyBjw7MgbcOgdSBKIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90Lg0KDQotIGBzdWJzZXQoZGlhbW9uZHMsIGNvbG9yID09ICJKIilgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGzhuqV5IHJhIGNo4buJIGPDoWMgbeG6q3Uga2ltIGPGsMahbmcgY8OzIG3DoHUgSi4NCg0KLSBgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgduG6vSBjw6FjIGPhu5l0IGJp4buDdSBkaeG7hW4gZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIG3huqt1IGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90Lg0KDQotIEPDoWMgY8OgaSDEkeG6t3Qga2jDoWMgbmjGsCB0acOqdSDEkeG7gSB2w6AgY2jhu6cgxJHhu4EgY+G7p2EgYmnhu4N1IMSR4buTIHbhuqtuIMSRxrDhu6NjIGdp4buvIG5ndXnDqm4uDQoNCioqQmnhu4N1IMSR4buTIG7DoHkgc+G6vSBoaeG7g24gdGjhu4sgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIG3huqt1IGtpbSBjxrDGoW5nIG3DoHUgSiB0aGVvIHThu6tuZyBt4bupYyBjaOG6pXQgbMaw4bujbmcgY+G6r3QuKioNCg0KDQoNCg0KYGBge3J9DQojIExvYWQgdGjGsCB2aeG7h24gZ2dwbG90Mg0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIFTDrW5oIMSR4buZIHPDonUgdHJ1bmcgYsOsbmggY+G7p2EgbeG7l2kgbeG7qWMgxJHhu5kgY2xhcml0eQ0KY2xhcml0eV9kZXB0aCA8LSBhZ2dyZWdhdGUoZGlhbW9uZHMkZGVwdGgsIGJ5ID0gbGlzdChkaWFtb25kcyRjbGFyaXR5KSwgRlVOID0gbWVhbikNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KGNsYXJpdHlfZGVwdGgsIGFlcyh4ID0gR3JvdXAuMSwgeSA9IHgpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKHgsIDEpKSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJvcmFuZ2UiKSArDQogIGxhYnModGl0bGUgPSAixJDhu5kgc8OidSB0cnVuZyBiw6xuaCBj4bunYSBLaW0gY8awxqFuZyB0aGVvIE3hu6ljIMSR4buZIENsYXJpdHkiLA0KICAgICAgIHggPSAiTeG7qWMgxJHhu5kgQ2xhcml0eSIsDQogICAgICAgeSA9ICLEkOG7mSBzw6J1IHRydW5nIGLDrG5oIikNCmBgYA0KDQoNCg0KIyMgKipHaeG6o2kgdGjDrWNoIMSR4buTIHRo4buLIDIzKioNCg0KVHJvbmcgxJHDszoNCg0KLSBDaMO6bmcgdGEgc+G7rSBk4bulbmcgaMOgbSBgYWdncmVnYXRlKClgIMSR4buDIHTDrW5oIMSR4buZIHPDonUgdHJ1bmcgYsOsbmggY+G7p2EgbeG7l2kgbeG7qWMgxJHhu5kgY2xhcml0eSB0cm9uZyBj4buZdCBgZGVwdGhgLg0KDQotIGBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IilgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHbhur0gY8OhYyBj4buZdCBk4buxYSB0csOqbiBnacOhIHRy4buLIHRyb25nIGPhu5l0IHkuDQoNCi0gYGdlb21fdGV4dCgpYCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyB0aMOqbSBz4buRIGxp4buHdSDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIGzDqm4gdHLDqm4gY8OhYyBj4buZdCwgduG7m2kgYGxhYmVsYCBsw6AgZ2nDoSB0cuG7iyDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyBt4bupYyDEkeG7mSBjbGFyaXR5ICjEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAxIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuKS4NCg0KLSBDw6FjIGPDoGkgxJHhurd0IGtow6FjIG5oxrAgdGnDqnUgxJHhu4EgdsOgIGNo4bunIMSR4buBIGPhu6dhIGJp4buDdSDEkeG7kyB24bqrbiDEkcaw4bujYyBnaeG7ryBuZ3V5w6puIHTGsMahbmcgdOG7sSBjw6FjIGJp4buDdSDEkeG7kyB0csOqbg0KDQoqKkJp4buDdSDEkeG7kyBuw6B5IHPhur0gaGnhu4NuIHRo4buLIMSR4buZIHPDonUgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBt4buXaSBt4bupYyDEkeG7mSBjbGFyaXR5LCBnacO6cCBwaMOibiB0w61jaCBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGNsYXJpdHkgdsOgIMSR4buZIHPDonUgY+G7p2Ega2ltIGPGsMahbmcuKioNCg0KDQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIGdncGxvdDINCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBUw61uaCB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGPhu6dhIG3hu5dpIG3hu6ljIMSR4buZIGNsYXJpdHkNCmNsYXJpdHlfY2FyYXQgPC0gYWdncmVnYXRlKGRpYW1vbmRzJGNhcmF0LCBieSA9IGxpc3QoZGlhbW9uZHMkY2xhcml0eSksIEZVTiA9IG1lYW4pDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQNCmdncGxvdChjbGFyaXR5X2NhcmF0LCBhZXMoeCA9IEdyb3VwLjEsIHkgPSB4KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJncmVlbiIsIGNvbG9yID0gImJsYWNrIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoeCwgMikpLCB2anVzdCA9IC0wLjUsIGNvbG9yID0gImJsdWUiKSArDQogIGxhYnModGl0bGUgPSAiVHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCBj4bunYSBLaW0gY8awxqFuZyB0aGVvIE3hu6ljIMSR4buZIENsYXJpdHkiLA0KICAgICAgIHggPSAiTeG7qWMgxJHhu5kgQ2xhcml0eSIsDQogICAgICAgeSA9ICJUcuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIChjYXJhdCkiKSArIGNvb3JkX2ZsaXAoKQ0KDQpgYGANCg0KDQojIyAqKkdp4bqjaSB0aMOtY2ggxJHhu5MgdGjhu4sgMjQqKg0KDQoNClRyb25nIMSRw7M6DQoNCi0gQ2jDum5nIHRhIHPhu60gZOG7pW5nIGjDoG0gYGFnZ3JlZ2F0ZSgpYCDEkeG7gyB0w61uaCB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGPhu6dhIG3hu5dpIG3hu6ljIMSR4buZIGNsYXJpdHkgdHJvbmcgY+G7mXQgYGNhcmF0YC4NCg0KLSBgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpYCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyB24bq9IGPDoWMgY+G7mXQgZOG7sWEgdHLDqm4gZ2nDoSB0cuG7iyB0cm9uZyBj4buZdCB5Lg0KDQotIGBnZW9tX3RleHQoKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgdGjDqm0gc+G7kSBsaeG7h3UgdHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCBsw6puIHRyw6puIGPDoWMgY+G7mXQsIHbhu5tpIGBsYWJlbGAgbMOgIGdpw6EgdHLhu4sgdHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCBj4bunYSB04burbmcgbeG7qWMgxJHhu5kgY2xhcml0eSAoxJHGsOG7o2MgbMOgbSB0csOybiDEkeG6v24gMiBjaOG7ryBz4buRIHRo4bqtcCBwaMOibikuDQoNCi0gQ8OhYyBjw6BpIMSR4bq3dCBraMOhYyBuaMawIHRpw6p1IMSR4buBIHbDoCBjaOG7pyDEkeG7gSBj4bunYSBiaeG7g3UgxJHhu5MgduG6q24gxJHGsOG7o2MgZ2nhu68gbmd1ecOqbiBuaMawIGPDoWMgxJHhu5MgdGjhu4sgdHLDqm4NCg0KKipCaeG7g3UgxJHhu5MgbsOgeSBz4bq9IGhp4buDbiB0aOG7iyB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gbeG7l2kgbeG7qWMgxJHhu5kgY2xhcml0eSwgZ2nDunAgcGjDom4gdMOtY2ggbeG7kWkgcXVhbiBo4buHIGdp4buvYSBjbGFyaXR5IHbDoCB0cuG7jW5nIGzGsOG7o25nIGPhu6dhIGtpbSBjxrDGoW5nLioqDQoNCg0KDQoNCmBgYHtyfQ0KdG1wICU+JSBncm91cF9ieShjbGFyaXR5LGNvbG9yKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSx5ID0gbikpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgICBnZW9tX2NvbChmaWxsPSdyZWQnKSArDQogICAgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLjUsIGNvbG9yID0gJ2RhcmtncmVlbicpICsNCiAgICBsYWJzKHggPSAnxJDhu5kgdGluaCBraGnhur90JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQojIyAqKkdp4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDI1KioNCg0KDQpCaeG7g3UgxJHhu5MgMjUgbMOgIHThuq1wIGjhu6NwIGPhu6dhIG5o4buvbmcgYmnhu4N1IMSR4buTIG5o4buPIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIHRoZW8gxJHhu5kgdGluaCBraGnhur90IGPhu6dhIHThu6tuZyBtw6B1LiBWw60gZOG7pTogbmjDrG4gdsOgbyBiaeG7g3UgxJHhu5Mgbmjhu48gdGjhu6kgbmjhuqV0IHRhIGPDsyB0aOG7gyB0aOG6pXkgc+G7kSBsxrDhu6NuZyB2acOqbiBraW0gY8awxqFuZyBtw6B1IEQgY8OzIMSR4buZIHRpbmgga2hp4bq/dCBJMSBsw6AgNDIsIHPhu5EgbMaw4bujbmcgdmnDqm4ga2ltIGPGsMahbmcgbcOgdSBEIGPDsyDEkeG7mSB0aW5oIGtoaeG6v3QgU0kyIGzDoCAxMzcwLC4uLg0KDQoNCg0KYGBge3J9DQp0bXAgPC0gZGlhbW9uZHMNCnRtcCAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShtPSBtZWFuKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG0pKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgZ2VvbV9jb2woZmlsbD0nZ3JlZW4nKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ2JsdWUnKSArDQogICAgbGFicyh4ID0gJ8SQ4buZIHRpbmgga2hp4bq/dCcsIHkgPSAnVHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCcpDQpgYGANCg0KDQojIyAqKkdp4bqjaSB0aMOtY2ggYmnhu4N1IMSR4buTIDI2KioNCg0KQmnhu4N1IMSR4buTIDI2IHRo4buDIGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGPhu6dhIG5o4buvbmcgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyDEkeG7mSB0aW5oIGtoaeG6v3QuIFRhIHRo4bqleSBtw6B1IEkxIGPDsyB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGzhu5tuIG5o4bqldCB24bubaSAxLjI4IGNhcmF0IGPDsm4gYsOpIG5o4bqldCBsw6AgVlZTMSB24bubaSAwLjUgY2FyYXQNCg0KDQoNCg0KYGBge3J9DQojIExvYWQgdGjGsCB2aeG7h24gZ2dwbG90Mg0KbGlicmFyeShnZ3Bsb3QyKQ0KIyBUw61uaCDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIGPhu6dhIGPDoWMgbeG6q3Uga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QNCm1lYW5fZGVwdGggPC0gYWdncmVnYXRlKGRpYW1vbmRzJGRlcHRoLCBieSA9IGxpc3QoZGlhbW9uZHMkY3V0KSwgRlVOID0gbWVhbikNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KG1lYW5fZGVwdGgsIGFlcyh4ID0gR3JvdXAuMSwgeSA9IHgpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gImxpZ2h0Z3JlZW4iLCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKHgsIDEpKSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJncmVlbiIpICsNCiAgbGFicyh0aXRsZSA9ICLEkOG7mSBzw6J1IHRydW5nIGLDrG5oIGPhu6dhIEtpbSBjxrDGoW5nIHRoZW8gQ2jhuqV0IGzGsOG7o25nIGPhuq90IiwNCiAgICAgICB4ID0gIkNo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeSA9ICLEkOG7mSBzw6J1IHRydW5nIGLDrG5oICglKSIpDQoNCmBgYA0KDQoNCiMjICoqR2nhuqNpIHRow61jaCBiaeG7g3UgxJHhu5MgMjcqKg0KDQpUcm9uZyBiaeG7g3UgxJHhu5MgbsOgeToNCi0gQ2jDum5nIHRhIHPhu60gZOG7pW5nIGjDoG0gYGFnZ3JlZ2F0ZSgpYCDEkeG7gyB0w61uaCDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIGPhu6dhIGPDoWMgbeG6q3Uga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QuDQoNCi0gYGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgduG6vSBjw6FjIGPhu5l0IGThu7FhIHRyw6puIGdpw6EgdHLhu4sgdHJvbmcgY+G7mXQgeS4NCg0KLSBgZ2VvbV90ZXh0KClgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHRow6ptIHPhu5EgdHJ1bmcgYsOsbmggbMOqbiBjw6FjIGPhu5l0LCB24bubaSBgbGFiZWxgIGzDoCBnacOhIHRy4buLIMSR4buZIHPDonUgdHJ1bmcgYsOsbmggY+G7p2EgdOG7q25nIGxv4bqhaSBjaOG6pXQgbMaw4bujbmcgY+G6r3QgKMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDEgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4pLg0KDQotIGB2anVzdCA9IC0wLjVgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGPEg24gY2jhu4luaCB2xINuIGLhuqNuIGzDqm4gdHLDqm4gY8OhYyBj4buZdC4NCg0KLSBmaWxsID0gIm9yYW5nZSIsIGNvbG9yID0gImJsYWNrIiA6IG3DoHUgY+G7p2EgYmnhu4N1IMSR4buTIGzDoCBtw6B1IGNhbSB2w6AgY+G7p2EgY2jhu68gc+G7kSB0csOqbiBjw6FjIGPhu5l0IGzDoCBtw6B1IHhhbmggbMOhLg0KDQoNCg0KYGBge3J9DQp0bXAgPC0gZGlhbW9uZHMNCnRtcCAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobT0gbWVhbih5KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNvbG9yLHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGdlb21fY29sKGZpbGw9J2RhcmtncmVlbicpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICdNw6B1JywgeSA9ICdDaGnhu4F1IHLhu5luZyB0cnVuZyBiw6xuaCcpDQpgYGANCg0KIyMgKipHaeG6o2kgdGjDrWNoIGJp4buDdSDEkeG7kyAyOCoqDQpCaeG7g3UgxJHhu5MgMjggdGjhu4MgaGnhu4duIGNoaeG7gXUgcuG7mW5nIHRydW5nIGLDrG5oIGPhu6dhIG5o4buvbmcgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyBtw6B1LiBUYSB0aOG6pXkgbcOgdSBKIGPDsyBjaGnhu4F1IGTDoGkgdHJ1bmcgYsOsbmggbOG7m24gbmjhuqV0IHbhu5tpIDYuNTIgbW0gY8OybiBuZ+G6r24gbmjhuql0IGzDoCBtw6B1IEQgdsOgIEUgduG7m2kgNS40MiBtbQ0KDQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIGdncGxvdDINCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBUw61uaCBnacOhIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEogdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QNCmF2Z19wcmljZSA8LSBhZ2dyZWdhdGUoZGlhbW9uZHMkcHJpY2UsIGJ5ID0gbGlzdChkaWFtb25kcyRjdXQpLCBGVU4gPSBtZWFuKQ0KDQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0DQpnZ3Bsb3Qoc3Vic2V0KGRpYW1vbmRzLCBjb2xvciA9PSAiSiIpLCBhZXMoeCA9IGN1dCwgeSA9IHByaWNlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVhbiIsIGZpbGwgPSAiZ3JlZW4iLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJHacOhIHRydW5nIGLDrG5oIGPhu6dhIEtpbSBjxrDGoW5nIG3DoHUgSiB0aGVvIENo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeCA9ICJDaOG6pXQgbMaw4bujbmcgY+G6r3QiLA0KICAgICAgIHkgPSAiR2nDoSB0cnVuZyBiw6xuaCIpICsgY29vcmRfZmxpcCgpDQoNCmBgYA0KDQoNCiMjICoqR2nhuqNpIHRow61jaCDEkeG7kyB0aOG7iyAyOSoqDQoNCg0KVHJvbmcgxJHDszogDQoNCg0KLSBDaMO6bmcgdGEgc+G7rSBk4bulbmcgaMOgbSBgYWdncmVnYXRlKClgIMSR4buDIHTDrW5oIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBt4bqrdSBraW0gY8awxqFuZyBjw7MgbcOgdSBKIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90Lg0KDQotIGBzdWJzZXQoZGlhbW9uZHMsIGNvbG9yID09ICJKIilgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGzhuqV5IHJhIGNo4buJIGPDoWMgbeG6q3Uga2ltIGPGsMahbmcgY8OzIG3DoHUgSi4NCg0KLSBgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgduG6vSBjw6FjIGPhu5l0IGJp4buDdSBkaeG7hW4gZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIG3huqt1IGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90Lg0KDQotIEPDoWMgY8OgaSDEkeG6t3Qga2jDoWMgbmjGsCB0acOqdSDEkeG7gSB2w6AgY2jhu6cgxJHhu4EgY+G7p2EgYmnhu4N1IMSR4buTIHbhuqtuIMSRxrDhu6NjIGdp4buvIG5ndXnDqm4uDQoNCg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmRhdGEoImRpYW1vbmRzIikNCiMgVMOtbmggZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSDEkeG7mSBkw6BpIHggdGhlbyBjaOG6pXQgbMaw4bujbmcgY+G6r3QNCm1lYW5feCA8LSBhZ2dyZWdhdGUoZGlhbW9uZHMkeCwgYnkgPSBsaXN0KGRpYW1vbmRzJGN1dCksIEZVTiA9IG1lYW4pDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQNCmdncGxvdChkaWFtb25kcywgYWVzKHggPSBjdXQsIHkgPSB4KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVhbiIsIGZpbGwgPSAic2t5Ymx1ZSIsIGNvbG9yID0gImJsYWNrIikgKw0KICBnZW9tX3RleHQoZGF0YSA9IG1lYW5feCwgYWVzKHggPSBHcm91cC4xLCB5ID0geCwgbGFiZWwgPSByb3VuZCh4LCAxKSksIHZqdXN0ID0gLTAuNSkgKw0KICBsYWJzKHRpdGxlID0gIsSQ4buZIGTDoGkgeCB0cnVuZyBiw6xuaCBj4bunYSBLaW0gY8awxqFuZyB0aGVvIENo4bqldCBsxrDhu6NuZyBj4bqvdCIsDQogICAgICAgeCA9ICJDaOG6pXQgbMaw4bujbmcgY+G6r3QiLA0KICAgICAgIHkgPSAixJDhu5kgZMOgaSB4IHRydW5nIGLDrG5oIChtbSkiKSArIGNvb3JkX2ZsaXAoKQ0KDQpgYGANCg0KDQoNCiMjICoqR2nhuqNpIHRow61jaCBiaeG7g3UgxJHhu5MgMzAqKg0KDQotIENow7puZyB0YSBz4butIGThu6VuZyBow6BtIGBhZ2dyZWdhdGUoKWAgxJHhu4MgdMOtbmggZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSDEkeG7mSBkw6BpIHggdGhlbyBt4buXaSBt4bupYyBjaOG6pXQgbMaw4bujbmcgY+G6r3QuDQoNCi0gYGdlb21fdGV4dCgpYCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyB0aMOqbSBz4buRIHRydW5nIGLDrG5oIGzDqm4gY8OhYyBj4buZdCwgduG7m2kgY8OhYyB0aGFtIHPhu5EgYHhgIGzDoCBuaMOzbSAobeG7qWMgY2jhuqV0IGzGsOG7o25nIGPhuq90KSwgYHlgIGzDoCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIMSR4buZIGTDoGkgKip4KiosIHbDoCBgbGFiZWxgIGzDoCBz4buRIHRydW5nIGLDrG5oICjEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAxIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuKS4NCg0KLSBgdmp1c3QgPSAtMC41YCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBjxINuIGNo4buJbmggdsSDbiBi4bqjbiBsw6puIHRyw6puIGPDoWMgY+G7mXQuDQoNCg0K