1 Giới thiệu bộ dữ liệu diamonds

Bộ dữ liệu Diamonds là một bộ dữ liệu phổ biến trong lĩnh vực khoa học dữ liệu. Bộ dữ liệu bao gồm những thuộc tính và những thông tin liên quan về những viên kim cương. Bộ dữ liệu gồm có 53940 quan sát tương đương với 53940 viên kim cương và 10 đối tương đương với 10 thuộc tính.

Ý nghĩa từng đối tượng:

  • carat: Trọng lượng của kim cương, đơn vị là carat.

  • cut: Chất lượng cắt của kim cương. Có thể là ‘Fair’, ‘Good’, ‘Very Good’, ‘Premium’, hoặc ‘Ideal’.

  • color: Màu sắc của kim cương, từ J (kém nhất) đến D (tốt nhất).

  • clarity: Độ tinh khiết của kim cương. Có thể là ‘I1’ (kém nhất), ‘SI2’, ‘SI1’, ‘VS2’, ‘VS1’, ‘VVS2’, ‘VVS1’, hoặc ‘IF’ (tốt nhất).

  • depth: Tỉ lệ giữa chiều cao và chiều rộng của kim cương, được tính bằng phần trăm.

  • table: Tỉ lệ giữa chiều rộng của mặt trên cùng (bàn) và chiều rộng tổng thể của kim cương, được tính bằng phần trăm.

  • price: Giá của kim cương, đơn vị là USD.

  • x: Chiều dài của kim cương, đơn vị là mm.

  • y: Chiều rộng của kim cương, đơn vị là mm.

  • z: Chiều cao của kim cương, đơn vị là mm.

2 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')

2.1 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')

2.2 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')

2.3 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")

2.4 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")

2.5 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")

2.6 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")

2.7 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")

2.8 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)")

2.9 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()

2.10 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)")

2.11 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()

2.12 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)") 

2.13 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)")

2.14 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)")

2.15 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 (%)")

2.16 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á")

2.17 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()

2.18 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")

2.19 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")

2.20 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()

2.21 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")

2.22 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")

2.23 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()

2.24 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.

2.25 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')

2.26 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 (%)")

2.27 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')

2.28 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()

2.29 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()

2.30 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