Vẽ Đồ Thị Dạng
Bar Chart
Biểu đồ
1: biểu đồ mật độ của điểm đánh giá (Rating) dựa trên các chi
nhánh khác nhau
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
a %>% ggplot(aes(x = Rating, fill = Branch)) +
geom_density()

Giải thích câu lệnh:
%>%: Toán tử ống được sử dụng để chuyển kết
quả từ a sang hàm ggplot().
ggplot(aes(x = Rating, fill = Branch)): Đây là
phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến
vào các thuộc tính của biểu đồ. Trong trường hợp này, x = Rating ánh xạ
điểm đánh giá vào trục x, và fill = Branch ánh xạ các chi nhánh vào màu
sắc của biểu đồ.
geom_density(): Hàm này thêm một layer để vẽ
biểu đồ mật độ. Trong trường hợp này, mỗi chi nhánh sẽ có một đường mật
độ riêng biểu diễn phân phối của điểm đánh giá cho mỗi chi
nhánh.
Kết quả:
Biểu đồ hiển thị hai đường cong mật độ, một cho mỗi chi nhánh
(Branch). Đường cong mật độ cho thấy phân bố của các giá trị Rating cho
từng chi nhánh.
Biểu đồ
2: biểu đồ mật độ của điểm đánh giá (Rating) dựa trên các chi
nhánh khác nhau, với mỗi chi nhánh được hiển thị trong các đồ thị con
riêng biệt.
a %>% ggplot(aes(x = Rating)) +
geom_density(fill = 'skyblue') +
facet_wrap(~Branch)

Giải thích câu lệnh:
ggplot(aes(x = Rating)): Đây là phần cơ bản của
biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc
tính của biểu đồ. Trong trường hợp này, x = Rating ánh xạ điểm đánh giá
vào trục x.
geom_density(fill = ‘skyblue’): Hàm này thêm một
layer để vẽ biểu đồ mật độ. Trong trường hợp này, màu nền của đường mật
độ được thiết lập thành ‘skyblue’.
facet_wrap(~Branch): Hàm này tạo ra các đồ thị
con dựa trên biến Branch. Cụ thể, nó tạo ra một biểu đồ mật độ cho mỗi
giá trị duy nhất của biến Branch, với mỗi biểu đồ được hiển thị trong
các ô riêng biệt.
Kết quả:
Biểu đồ bao gồm:
Một biểu đồ mật độ cho mỗi giá trị của biến Branch.
Trục hoành hiển thị giá trị của biến Rating.
Trục tung hiển thị mật độ xác suất.
Biểu đồ được tô màu bằng màu ‘skyblue’.
Biểu đồ
3: biểu đồ cột thể hiện số lượng này cho mỗi thành phố, cùng
với số lượng được hiển thị trên mỗi cột.
a %>% group_by(City) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = City)) +
geom_col() +
geom_text(aes(label = n),position = position_stack(vjust = 1))

Giải thích câu lệnh:
group_by(City) %>% summarise(n = n()): Trước
tiên, dữ liệu được nhóm lại theo thành phố (City) và sau đó tính tổng số
lượng các mẫu trong mỗi nhóm (số lượng thành phố). Kết quả là một bảng
dữ liệu mới với hai cột: thành phố (City) và số lượng (n).
**ggplot(aes(x = ’‘, y = n, fill = City)):** Đây là phần cơ bản
của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các
thuộc tính của biểu đồ. Trong trường hợp này, xác định một trục x trống
(’’) để tạo ra các cột độc lập nhau, y là số lượng (n) và fill là thành
phố (City).
geom_col(): Hàm này thêm một layer để vẽ biểu đồ
cột.
geom_text(aes(label = n), position = position_stack(vjust
= 1)): Hàm này thêm văn bản vào mỗi cột, với label là số lượng
(n) và vị trí được điều chỉnh để đặt văn bản trên cột.
Kết quả:
Biểu đồ bao gồm:
Một cột cho mỗi giá trị của biến City.
Chiều cao của mỗi cột biểu thị số lượng bản ghi trong nhóm tương
ứng.
Biểu đồ được tô màu theo biến City.
Giá trị n được hiển thị trên đỉnh của mỗi cột.
Biểu đồ
4: biểu đồ cột tròn dựa trên số lượng thành phố, trong đó mỗi
cột biểu diễn một thành phố, và chiều cao của cột được xác định bởi số
lượng (n).
a %>% group_by(City) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = City)) +
geom_col() +
coord_polar('y')

Giải thích câu lệnh:
group_by(City) %>% summarise(n = n()): Tính
tổng số lượng các thành phố (City) trong tập dữ liệu và lưu kết quả vào
một bảng dữ liệu mới với hai cột: thành phố (City) và số lượng
(n).
**ggplot(aes(x = ’‘, y = n, fill = City)):** Thiết lập dữ liệu và
ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này,
xác định trục x trống (’’) để tạo ra các cột độc lập nhau, y là số lượng
(n), và fill là thành phố (City).
geom_col(): Thêm một layer để vẽ biểu đồ
cột.
coord_polar(‘y’): Chuyển đổi biểu đồ thành dạng
cột tròn, với chiều cao của cột được xác định bởi giá trị trên trục y
(n).
Kết quả:
Biểu đồ bao gồm:
Một vòng tròn cho mỗi giá trị của biến City.
Diện tích của mỗi vòng tròn biểu thị số lượng bản ghi trong nhóm
tương ứng.
Biểu đồ được tô màu theo biến City.
Biểu đồ
5: biểu đồ cột tròn, biểu diễn số lượng các thành phố (City)
khác nhau. Các cột được tô màu theo từng thành phố, và có chữ số đếm của
mỗi thành phố được hiển thị trên biểu đồ.
a %>% group_by(City) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = City)) +
geom_col(color = 'black') +
coord_polar('y') +
geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
theme_void()

Giải thích câu lệnh:
**ggplot(aes(x = ’‘, y = n, fill = City)):** Thiết lập dữ liệu và
ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này,
xác định trục x trống (’’) để tạo ra các cột độc lập nhau, y là số lượng
(n), và fill là thành phố (City).
geom_col(color = ‘black’): Thêm một layer để vẽ
biểu đồ cột và tô màu cột bằng fill, với màu viền đen (color =
‘black’).
coord_polar(‘y’): Chuyển đổi biểu đồ thành dạng
cột tròn, với chiều cao của cột được xác định bởi giá trị trên trục y
(n).
geom_text(aes(x = 1.3, label = n), position =
position_stack(vjust = .5)): Thêm văn bản vào biểu đồ với giá
trị label là số lượng (n), và vị trí xác định bằng x = 1.3.
position_stack(vjust = .5) giúp điều chỉnh vị trí của văn bản trên
cột.
theme_void(): Loại bỏ các phần bên ngoài biểu đồ
để tạo ra một biểu đồ trắng đơn giản.
Kết quả:
Biểu đồ bao gồm:
Ba vòng tròn (hoặc số lượng theo nhóm trong dữ liệu a) được tô
màu theo City.
Mỗi vòng tròn có viền màu đen.
Giá trị n (số lượng bản ghi) được hiển thị bên ngoài mỗi vòng
tròn với màu đen, cách trục hoành 1.3 đơn vị.
Biểu đồ nền trong suốt (không có khung nền hoặc trục chú
thích).
Biểu đồ
6: biểu đồ scatter plot biểu diễn mối quan hệ giữa giá của sản
phẩm đơn vị và dòng sản phẩm
a %>% ggplot(aes(x = Unit.price, y = Product.line)) +
geom_point() +
xlab('Giá của sản phẩm') +
ylab('Dòng sản phẩm')

Giải thích câu lệnh:
ggplot(aes(x = Unit.price, y = Product.line)):
Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ
các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, x =
Unit.price ánh xạ giá của sản phẩm đơn vị vào trục x, và y =
Product.line ánh xạ dòng sản phẩm vào trục y.
geom_point(): Thêm một layer để vẽ biểu đồ
scatter plot với các điểm dữ liệu.
xlab(‘Giá của sản phẩm’) và ylab(‘Dòng
sản phẩm’): Thiết lập nhãn cho trục x và trục y tương ứng với
“Giá của sản phẩm” và “Dòng sản phẩm”.
Kết quả:
Biểu đồ bao gồm:
Một tập hợp các điểm, mỗi điểm đại diện cho một sản
phẩm.
Trục hoành hiển thị giá của sản phẩm.
Trục tung hiển thị dòng sản phẩm.
Nhãn cho trục hoành và trục tung.
Biểu đồ
7: biểu đồ scatter plot biểu diễn mối quan hệ giữa giá của sản
phẩm đơn vị và dòng sản phẩm, với màu sắc của từng điểm dữ liệu được
phân biệt theo chi nhánh (Branch).
a %>% ggplot(aes(x = Unit.price, y = Product.line, color = Branch)) +
geom_point()

Giải thích câu lệnh:
ggplot(aes(x = Unit.price, y = Product.line, color =
Branch)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập
dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường
hợp này, x = Unit.price ánh xạ giá của sản phẩm đơn vị vào trục x, y =
Product.line ánh xạ dòng sản phẩm vào trục y, và color = Branch ánh xạ
chi nhánh vào màu sắc của các điểm dữ liệu.
geom_point(): Thêm một layer để vẽ biểu đồ
scatter plot với các điểm dữ liệu. Các điểm sẽ có màu sắc khác nhau
tương ứng với từng chi nhánh.
Kết quả:
Biểu đồ bao gồm:
Một tập hợp các điểm, mỗi điểm đại diện cho một sản
phẩm.
Trục hoành hiển thị giá của sản phẩm.
Trục tung hiển thị dòng sản phẩm.
Các điểm được tô màu theo biến Branch.
Biểu đồ
8: biểu đồ scatter plot biểu diễn mối quan hệ giữa giá của sản
phẩm đơn vị và dòng sản phẩm, với các điểm dữ liệu được phân biệt theo
hình dạng (shape) tương ứng với từng chi nhánh
a %>% ggplot(aes(x = Unit.price, y = Product.line, shape = Branch)) +
geom_point()

Giải thích câu lệnh:
ggplot(aes(x = Unit.price, y = Product.line, shape =
Branch)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập
dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường
hợp này, x = Unit.price ánh xạ giá của sản phẩm đơn vị vào trục x, y =
Product.line ánh xạ dòng sản phẩm vào trục y, và shape = Branch ánh xạ
chi nhánh vào hình dạng (shape) của các điểm dữ liệu.
geom_point(): Thêm một layer để vẽ biểu đồ
scatter plot với các điểm dữ liệu. Các điểm sẽ có hình dạng (shape) khác
nhau tương ứng với từng chi nhánh.
Kết quả:
Biểu đồ bao gồm:
Một tập hợp các điểm, mỗi điểm đại diện cho một sản
phẩm.
Trục hoành hiển thị giá của sản phẩm.
Trục tung hiển thị dòng sản phẩm.
Các điểm được định dạng hình dạng theo biến Branch.
Biểu đồ
9: biểu đồ scatter plot biểu diễn mối quan hệ giữa điểm đánh
giá và dòng sản phẩm, với kích thước của các điểm dữ liệu được phân biệt
theo giới tính
a %>% ggplot(aes(x = Rating, y = Product.line, size = Gender)) +
geom_point()
## Warning: Using size for a discrete variable is not advised.

Giải thích câu lệnh:
ggplot(aes(x = Rating, y = Product.line, size =
Gender)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập
dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường
hợp này, x = Rating ánh xạ điểm đánh giá vào trục x, y = Product.line
ánh xạ dòng sản phẩm vào trục y, và size = Gender ánh xạ giới tính vào
kích thước của các điểm dữ liệu.
geom_point(): Thêm một layer để vẽ biểu đồ
scatter plot với các điểm dữ liệu. Các điểm sẽ có kích thước khác nhau
tương ứng với từng giới tính.
Kết quả:
Biểu đồ bao gồm:
Một tập hợp các điểm, mỗi điểm đại diện cho một sản
phẩm.
Trục hoành hiển thị xếp hạng của sản phẩm.
Trục tung hiển thị dòng sản phẩm.
Kích thước của các điểm thay đổi theo biến Gender.
Biểu đồ
10: biểu đồ scatter plot biểu diễn mối quan hệ giữa giá của sản
phẩm đơn vị và dòng sản phẩm, với độ trong suốt của các điểm dữ liệu
được phân biệt theo chi nhánh
a %>% ggplot(aes(x = Unit.price, y = Product.line, alpha = Branch)) +
geom_point()
## Warning: Using alpha for a discrete variable is not advised.

Giải thích câu lệnh:
ggplot(aes(x = Unit.price, y = Product.line, alpha =
Branch)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập
dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường
hợp này, x = Unit.price ánh xạ giá của sản phẩm đơn vị vào trục x, y =
Product.line ánh xạ dòng sản phẩm vào trục y, và alpha = Branch ánh xạ
chi nhánh vào độ trong suốt (alpha) của các điểm dữ liệu.
geom_point(): Thêm một layer để vẽ biểu đồ
scatter plot với các điểm dữ liệu. Các điểm sẽ có độ trong suốt khác
nhau tương ứng với từng chi nhánh.
Kết quả:
Biểu đồ bao gồm:
Một tập hợp các điểm, mỗi điểm đại diện cho một sản
phẩm.
Trục hoành hiển thị giá của sản phẩm.
Trục tung hiển thị dòng sản phẩm.
Độ mờ của các điểm thay đổi theo biến Branch.
Biểu đồ
11: biểu đồ phân tán với đánh giá (Rating) trên trục x và chi
nhánh (Branch) trên trục y
a %>% ggplot(aes(x = Rating, y = Branch)) +
geom_point(color = 'red') +
geom_smooth(method = 'lm', color = 'yellow')
## `geom_smooth()` using formula = 'y ~ x'

Giải thích câu lệnh:
ggplot(aes(x = Rating, y = Branch)): Bắt đầu với
một biểu đồ ggplot với dữ liệu được ánh xạ vào trục x là điểm đánh giá
(Rating) và trục y là chi nhánh (Branch).
geom_point(color = ‘red’): Thêm một layer với
điểm dữ liệu, trong đó màu của các điểm được đặt là đỏ
geom_smooth(method = ‘lm’, color = ‘yellow’):
Thêm một layer với đường cong hồi quy tuyến tính (linear regression)
được fit vào dữ liệu. Trong đó, method = ‘lm’ chỉ ra rằng phương pháp sử
dụng để fit dữ liệu là phương pháp hồi quy tuyến tính (linear
regression), và màu của đường cong được đặt là màu vàng
Kết quả:
Biểu đồ bao gồm:
Một tập hợp các điểm màu đỏ, mỗi điểm đại diện cho một sản
phẩm.
Trục hoành hiển thị xếp hạng của sản phẩm.
Trục tung hiển thị chi nhánh của sản phẩm.
Một đường cong màu vàng thể hiện mối quan hệ xu hướng giữa xếp
hạng và chi nhánh.
Biểu đồ
12:
a %>% ggplot(aes(x = Unit.price, y = Product.line)) +
geom_point(color = 'red') +
geom_smooth(method = 'lm', color = 'yellow') +
facet_wrap(~Branch)
## `geom_smooth()` using formula = 'y ~ x'

Kết quả:
Biểu đồ bao gồm:
Biểu đồ 13:
biểu đồ cột sử dụng gói ggplot2 và dữ liệu từ tệp CSV “supermarket_sales
- Sheet1.csv”
library(ggplot2)
data <- read.csv("D:/Hà/supermarket_sales - Sheet1.csv")
ggplot(data, aes(x = Product.line, y = Rating, fill = Product.line)) +
geom_bar(stat = "identity") +
scale_y_continuous("Rating")

Giải thích câu lệnh:
data <- read.csv(“D:/Hà/supermarket_sales -
Sheet1.csv”): Dòng này đọc dữ liệu từ tệp CSV
“supermarket_sales - Sheet1.csv” và lưu trữ nó vào biến data. Dữ liệu sẽ
được đọc dưới dạng data frame.
ggplot(data, aes(x = Product.line, y = Rating, fill =
Product.line)): Hàm ggplot() được sử dụng để khởi tạo một biểu
đồ mới. Đối số data chỉ định dữ liệu được sử dụng. Trong aes(), chúng ta
chỉ định các mapping aesthetics (tương ứng với các biến) cho trục x (x =
Product.line), trục y (y = Rating), và fill color (fill = Product.line).
Điều này có nghĩa là chúng ta sẽ vẽ cột dựa trên cột “Product.line”,
chiều cao của các cột sẽ được xác định bởi cột “Rating”, và màu sắc của
các cột sẽ tương ứng với giá trị của “Product.line”.
geom_bar(stat = “identity”): Hàm geom_bar() được
sử dụng để tạo ra biểu đồ cột. Tham số stat = “identity” cho biết rằng
chiều cao của các cột sẽ được xác định trực tiếp từ dữ liệu.
scale_y_continuous(“Rating”): Hàm
scale_y_continuous() được sử dụng để đặt nhãn cho trục y của biểu đồ,
với nhãn là “Rating”.
Kết quả: Mã này sẽ tạo biểu đồ thanh thể hiện trực
quan xếp hạng trung bình của các dòng sản phẩm khác nhau trong dữ liệu
bán hàng siêu thị.
Trục X: Trục này sẽ hiển thị các danh mục duy nhất từ cột
Product.line, đại diện cho các dòng sản phẩm khác nhau trong dữ
liệu
Trục Y: Trục này sẽ được dán nhãn “Rating” và sẽ hiển thị phạm vi
xếp hạng số trong dữ liệu
Thanh: Biểu đồ sẽ có một thanh dọc cho mỗi danh mục dòng sản
phẩm. Chiều cao của mỗi thanh sẽ tương ứng với xếp hạng trung bình cho
dòng sản phẩm đó (giả sử stat = “identity” tính toán giá trị trung
bình).
Màu sắc: Mỗi thanh sẽ được tô bằng một màu khác nhau và các màu
sẽ được gán dựa trên danh mục dòng sản phẩm (được xác định bởi yếu tố
thẩm mỹ fill = Product.line).
Biểu đồ
14: tạo một loạt các histogram, mỗi histogram biểu diễn phân
phối của biến “Rating” (xếp hạng) trong dữ liệu.
qplot(Rating, data = read.csv("D:/Hà/supermarket_sales - Sheet1.csv"), facets = . ~ Product.line, geom = "histogram", binwidth = 1)
## Warning: `qplot()` was deprecated in ggplot2 3.4.0.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Giải thích câu lệnh:
Rating: biến số được sử dụng để vẽ histogram,
đại diện cho xếp hạng của các sản phẩm.
data = read.csv(“D:/Hà/supermarket_sales -
Sheet1.csv”): Đây là dữ liệu bạn sử dụng để vẽ histogram. Hàm
read.csv() được sử dụng để đọc dữ liệu từ tệp CSV “supermarket_sales -
Sheet1.csv”.
facets = . ~ Product.line: Tham số này xác định
cách dữ liệu được phân chia thành các mặt hàng (facets) trên biểu đồ.
Trong trường hợp này, . ~ Product.line chỉ ra rằng mỗi mặt hàng (facet)
sẽ tương ứng với một loại sản phẩm được xác định bởi biến
“Product.line”.
geom = “histogram”: Loại hình học bạn muốn sử
dụng để vẽ biểu đồ. Trong trường hợp này, bạn đang sử dụng histogram để
biểu diễn phân phối của dữ liệu.
binwidth = 1: Độ rộng của các bin (ngăn) trong
histogram. Trong trường hợp này, độ rộng của mỗi bin được thiết lập là
1, có nghĩa là mỗi bin sẽ bao gồm các giá trị xếp hạng trong khoảng có
độ rộng là 1.
Kết quả: Biểu đồ tạo ra sẽ hiển thị phân phối xếp
hạng (Rating) cho từng dòng sản phẩm (Product.line) riêng biệt. Biểu đồ
bao gồm:
Nhiều phân đoạn: Mỗi phân đoạn đại diện cho một dòng sản
phẩm.
Trục Y: Hiển thị xếp hạng sản phẩm.
Trục X: Hiển thị số lượng sản phẩm cho mỗi xếp hạng.
Cột: Mỗi cột thể hiện số lượng sản phẩm có xếp hạng cụ thể trong
một dòng sản phẩm.
Biểu đồ
15:
qplot( Rating, Unit.price, data = read.csv("D:/Hà/supermarket_sales - Sheet1.csv"), color = Branch)

Giải thích câu lệnh:
Rating, Unit.price: Đây là các biến bạn muốn vẽ
trên trục x và trục y, tương ứng là “Rating” và “Unit.price”.
data = read.csv(“D:/Hà/supermarket_sales -
Sheet1.csv”): Đây là dữ liệu bạn sử dụng để vẽ biểu đồ. Hàm
read.csv() được sử dụng để đọc dữ liệu từ tệp CSV “supermarket_sales -
Sheet1.csv”.
color = Branch: Tham số này chỉ định cách biểu
đồ phân tán sẽ được màu sắc hóa dựa trên giá trị của biến “Branch”. Cụ
thể, mỗi điểm dữ liệu sẽ được màu sắc khác nhau tương ứng với giá trị
của biến “Branch”.
Kết quả: Biểu đồ tạo ra sẽ hiển thị mối quan hệ giữa
xếp hạng (Rating) và giá bán (Unit.price) của các sản phẩm. Biểu đồ bao
gồm:
Trục Y: Hiển thị xếp hạng sản phẩm.
Trục X: Hiển thị giá bán sản phẩm.
Điểm dữ liệu: Mỗi điểm đại diện cho một sản phẩm, được tô màu
theo chi nhánh (Branch) của sản phẩm đó.
Biểu đồ
16:
qplot(Rating, data = read.csv("D:/Hà/supermarket_sales - Sheet1.csv"), geom = "histogram", binwidth = 0.05)
Kết quả: Biểu đồ tạo ra sẽ hiển thị phân phối xếp hạng
(Rating) của sản phẩm. Biểu đồ bao gồm:
Trục Y: Hiển thị xếp hạng sản phẩm.
Trục X: Hiển thị số lượng sản phẩm cho mỗi xếp hạng.
Cột: Mỗi cột thể hiện số lượng sản phẩm có xếp hạng nằm trong
khoảng cụ thể.
Biểu đồ
17:
qplot(Quantity, data = read.csv("D:/Hà/supermarket_sales - Sheet1.csv"), geom = "density")
Kết quả: Biểu đồ tạo ra sẽ hiển thị mật độ phân phối
của số lượng sản phẩm (Quantity) được bán. Biểu đồ bao gồm:
Trục X: Hiển thị số lượng sản phẩm.
Trục Y: Hiển thị mật độ, thể hiện số lượng dữ liệu tập trung tại
mỗi giá trị của Quantity.
Đường cong: Đường cong mượt mà thể hiện mật độ phân phối của dữ
liệu.
Biểu đồ
18:
ggplot() +
geom_histogram(data = filter(a, Branch == 'A'), aes(x = Unit.price), binwidth = 5, fill = 'pink') +
geom_histogram(data = filter(a, Branch == 'C'), aes(x = Unit.price), binwidth = 5, fill = 'skyblue')

Giải thích câu lệnh:
ggplot(): Bắt đầu một đối tượng ggplot2 mới mà
không cần kết nối với dữ liệu cụ thể.
geom_histogram(): chúng ta thêm hai lớp dữ liệu
histogram, mỗi lớp tương ứng với một chi nhánh khác nhau.
data = filter(a, Branch == ‘A’) và data = filter(a,
Branch == ‘C’): Lọc dữ liệu từ a (giả sử là data frame chứa dữ
liệu) để chỉ lấy các quan sát có giá trị “Branch” tương ứng (“A” và “C”
lần lượt). Điều này giúp chúng ta chỉ vẽ histogram cho các quan sát
thuộc các chi nhánh này.
aes(x = Unit.price): Tạo mapping cho biến
Unit.price trên trục x của histogram.
binwidth = 5: Xác định độ rộng của các bin
(ngăn) trong histogram. Trong trường hợp này, độ rộng của mỗi bin được
đặt là 5.
fill: Xác định màu sắc cho histogram của mỗi chi
nhánh. Histogram cho chi nhánh “A” sẽ có màu hồng (“pink”) và histogram
cho chi nhánh “C” sẽ có màu xanh da trời (“skyblue”).
Kết quả: Biểu đồ tạo ra sẽ hiển thị hai biểu đồ hình
cột chồng lên nhau, so sánh phân phối giá bán (Unit.price) của hai chi
nhánh A và C. Biểu đồ bao gồm:
Trục X: Hiển thị giá bán sản phẩm.
Trục Y: Hiển thị số lượng sản phẩm cho mỗi giá bán.
Cột: Hai nhóm cột, một màu hồng (chi nhánh A) và một màu xanh da
trời (chi nhánh C), thể hiện số lượng sản phẩm cho mỗi giá bán của từng
chi nhánh.
Biểu đồ
19:
a %>% ggplot(aes(x = Unit.price)) +
geom_histogram(binwidth = 3, fill = 'green', color = 'red') +
facet_wrap(~Branch)
Kết quả: Biểu đồ tạo ra sẽ hiển thị một loạt các biểu
đồ hình cột, mỗi biểu đồ thể hiện phân phối giá bán (Unit.price) cho
từng chi nhánh (Branch). Biểu đồ bao gồm:
Nhiều phân đoạn: Mỗi phân đoạn đại diện cho một chi
nhánh.
Trục X: Hiển thị giá bán sản phẩm.
Trục Y: Hiển thị số lượng sản phẩm cho mỗi giá bán.
Cột: Các cột trong mỗi phân đoạn thể hiện số lượng sản phẩm cho
mỗi giá bán của từng chi nhánh.
Biểu đồ
20:
a %>% ggplot(aes(x = Unit.price, fill = Product.line)) +
geom_histogram(binwidth = 5)

Kết quả: Biểu đồ tạo ra sẽ hiển thị một biểu đồ hình
cột với các cột được tô màu theo dòng sản phẩm (Product.line). Biểu đồ
bao gồm:
Trục X: Hiển thị giá bán sản phẩm.
Trục Y: Hiển thị số lượng sản phẩm cho mỗi giá bán.
Cột: Các cột được tô màu theo dòng sản phẩm, thể hiện số lượng
sản phẩm cho mỗi giá bán của từng dòng sản phẩm.
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA1Ig0KYXV0aG9yOiAiVGh1IEjDoCINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVIOiVNOiVTLCAlZCAtICVtIC0gJVknKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50OiANCiAgICBkZl9wcmludDoga2FibGUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICB0b2NfZGVwdGg6IDINCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAnMicNCiAgcGRmX2RvY3VtZW50Og0KICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMgKipHaeG7m2kgdGhp4buHdSBi4buZIGThu68gbGnhu4d1IHN1cGVybWFya2V0X3NhbGVzLXNoZWV0MS5jc3Y6KioNCg0KIyMgKipNw7QgdOG6oyBi4buZIGThu68gbGnhu4d1IDoqKg0KDQpT4buxIHBow6F0IHRyaeG7g24gY+G7p2EgY8OhYyBzacOqdSB0aOG7iyB0cm9uZyBjw6FjIHRow6BuaCBwaOG7kSDEkcO0bmcgZMOibiDEkWFuZyB0xINuZyBsw6puIHbDoCBj4bqhbmggdHJhbmggdGjhu4sgdHLGsOG7nW5nIGPFqW5nIGNhby4gVOG6rXAgZOG7ryBsaeG7h3UgbsOgeSBsw6AgbeG7mXQgcGjhuqduIGPhu6dhIGzhu4tjaCBz4butIGLDoW4gaMOgbmcgY+G7p2EgbeG7mXQgY8O0bmcgdHkgc2nDqnUgdGjhu4sgxJHDoyDEkcaw4bujYyBnaGkgbOG6oWkgdHJvbmcgMyBjaGkgbmjDoW5oIGtow6FjIG5oYXUgdHJvbmcgc3Xhu5F0IDMgdGjDoW5nLiBDw6FjIHBoxrDGoW5nIHBow6FwIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IGThu7EgxJFvw6FuIGThu4UgZMOgbmcgw6FwIGThu6VuZyB24bubaSB04bqtcCBk4buvIGxp4buHdSBuw6B5Lg0KDQojIyAqKlRow7RuZyB0aW4gY8ahIGLhuqNuKioNCg0KLSBT4buRIGzGsOG7o25nIGThu68gbGnhu4d1OiBC4buZIGThu68gbGnhu4d1IHRoxrDhu51uZyBjaOG7qWEga2hv4bqjbmcgMTAwMCBkw7JuZyAoYuG6o24gZ2hpKSB2w6AgMTcgY+G7mXQgKGJp4bq/bikuDQoNCi0gVGh14buZYyB0w61uaCAoYmnhur9uKToNCg0KICAtIEludm9pY2UuSUQ6IFPhu5EgaMOzYSDEkcahbiDEkcaw4bujYyB04bqhbyBi4bufaSBtw6F5IHTDrW5oIMSR4buDIG5o4bqtbiBk4bqhbmcgaMOzYSDEkcahbiBiw6FuIGjDoG5nDQogIA0KICAtIEJyYW5jaDogQ2hpIG5ow6FuaCBj4bunYSBzacOqdSB0aOG7iyAoY8OzIDMgY2hpIG5ow6FuaCDEkcaw4bujYyB4w6FjIMSR4buLbmggYuG6sW5nIEEsIEIgdsOgIEMpLg0KICANCiAgLSBDaXR5OiBW4buLIHRyw60gY+G7p2EgY8OhYyBzacOqdSB0aOG7iw0KICANCiAgLSBDdXN0b21lci50eXBlOiBMb+G6oWkga2jDoWNoIGjDoG5nLCBnaGkgbOG6oWkgYuG7n2kgIk1lbWJlcnMiIGNobyBraMOhY2ggaMOgbmcgc+G7rSBk4bulbmcgdGjhursgdGjDoG5oIHZpw6puIHbDoCAiTm9ybWFsIiBjaG8ga2jDoWNoIGjDoG5nIGtow7RuZyBjw7MgdGjhursgdGjDoG5oIHZpw6puLg0KICANCiAgLSBHZW5kZXI6IExv4bqhaSBnaeG7m2kgdMOtbmggY+G7p2Ega2jDoWNoIGjDoG5nDQogIA0KICAtIFByb2R1Y3QubGluZTogTmjDs20gcGjDom4gbG/huqFpIGPDoWMgbeG6t3QgaMOgbmcgY2h1bmcgLSBQaOG7pSBraeG7h24gxJFp4buHbiB04butLCBQaOG7pSBraeG7h24gdGjhu51pIHRyYW5nLCBUaOG7sWMgcGjhuqltIHbDoCDEkeG7kyB14buRbmcsIFPhu6ljIGto4buPZSB2w6Agc+G6r2MgxJHhurlwLCDEkOG7nWkgc+G7kW5nIGdpYSDEkcOsbmgsIFRo4buDIHRoYW8gdsOgIGR1IGzhu4tjaA0KICANCiAgLSBVbml0LnByaWNlOiBHacOhIGPhu6dhIG3hu5dpIHPhuqNuIHBo4bqpbSB0w61uaCBi4bqxbmcgJA0KICANCiAgLSBRdWFudGl0eTogU+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gbcOgIGtow6FjaCBow6BuZyDEkcOjIG11YQ0KICANCiAgLSBUYXguNTogUGjDrSB0aHXhur8gNSUgY2hvIGtow6FjaCBow6BuZyBtdWEgaMOgbmdcDQogIA0KICAtIFRvdGFsOiBU4buVbmcgZ2nDoSBiYW8gZ+G7k20gdGh14bq/DQogIA0KICAtIERhdGU6IE5nw6B5IG11YSBow6BuZyAoR2hpIGNow7ogdOG7qyB0aMOhbmcgMSBuxINtIDIwMTkgxJHhur9uIHRow6FuZyAzIG7Eg20gMjAxOSkNCiAgDQogIC0gVGltZTogVGjhu51pIGdpYW4gbXVhIGjDoG5nICh04burIDEwIGdp4budIHPDoW5nIMSR4bq/biA5IGdp4budIHThu5FpKQ0KICANCiAgLSBQYXltZW50OiBQaMawxqFuZyB0aOG7qWMgdGhhbmggdG/DoW4gxJHGsOG7o2Mgc+G7rSBk4bulbmcgYuG7n2kga2jDoWNoIGjDoG5nIChjw7MgMyBwaMawxqFuZyBwaMOhcCBjw7Mgc+G6tW4gLSBUaeG7gW4gbeG6t3QsIFRo4bq7IHTDrW4gZOG7pW5nIHbDoCBWw60gxJFp4buHbiB04butKQ0KICANCiAgLSBDT0dTOiBDaGkgcGjDrSBow6BuZyBow7NhIGLDoW4gcmENCiAgDQogIC0gR3Jvc3MubWFyZ2luLnBlcmNlbnRhZ2U6IFThu7cgbOG7hyBs4bujaSBuaHXhuq1uIGfhu5lwDQogIA0KICAtIEdyb3NzLmluY29tZTogVGh1IG5o4bqtcCBn4buZcA0KICANCiAgLSBSYXRpbmc6IMSQw6FuaCBnacOhIHBow6JuIGxv4bqhaSBraMOhY2ggaMOgbmcgduG7gSB0cuG6o2kgbmdoaeG7h20gbXVhIHPhuq9tIHThu5VuZyB0aOG7gyBj4bunYSBo4buNICh0csOqbiB0aGFuZyDEkWnhu4NtIHThu6sgMSDEkeG6v24gMTApDQoNCiMjICoqQ8OgaSB2w6AgTG9hZCBi4buZIGThu68gbGnhu4d1IHbDoG8gUioqDQoNCmBgYHtyfQ0KbGlicmFyeShjc3YpDQphIDwtIHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IiwgaGVhZGVyPSBUKSANCmBgYA0KDQojICoqVuG6vSDEkOG7kyBUaOG7iyBE4bqhbmcgQmFyIENoYXJ0KioNCg0KIyMgKipCaeG7g3UgxJHhu5MgMToqKiBiaeG7g3UgxJHhu5MgbeG6rXQgxJHhu5kgY+G7p2EgxJFp4buDbSDEkcOhbmggZ2nDoSAoUmF0aW5nKSBk4buxYSB0csOqbiBjw6FjIGNoaSBuaMOhbmgga2jDoWMgbmhhdQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQphICU+JSBnZ3Bsb3QoYWVzKHggPSBSYXRpbmcsIGZpbGwgPSBCcmFuY2gpKSArDQogIGdlb21fZGVuc2l0eSgpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKiolPiU6KiogVG/DoW4gdOG7rSDhu5FuZyDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBjaHV54buDbiBr4bq/dCBxdeG6oyB04burIGEgc2FuZyBow6BtIGdncGxvdCgpLg0KDQotICoqZ2dwbG90KGFlcyh4ID0gUmF0aW5nLCBmaWxsID0gQnJhbmNoKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gUmF0aW5nIMOhbmggeOG6oSDEkWnhu4NtIMSRw6FuaCBnacOhIHbDoG8gdHLhu6VjIHgsIHbDoCBmaWxsID0gQnJhbmNoIMOhbmggeOG6oSBjw6FjIGNoaSBuaMOhbmggdsOgbyBtw6B1IHPhuq9jIGPhu6dhIGJp4buDdSDEkeG7ky4NCg0KLSAqKmdlb21fZGVuc2l0eSgpOioqIEjDoG0gbsOgeSB0aMOqbSBt4buZdCBsYXllciDEkeG7gyB24bq9IGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mS4gVHJvbmcgdHLGsOG7nW5nIGjhu6NwIG7DoHksIG3hu5dpIGNoaSBuaMOhbmggc+G6vSBjw7MgbeG7mXQgxJHGsOG7nW5nIG3huq10IMSR4buZIHJpw6puZyBiaeG7g3UgZGnhu4VuIHBow6JuIHBo4buRaSBj4bunYSDEkWnhu4NtIMSRw6FuaCBnacOhIGNobyBt4buXaSBjaGkgbmjDoW5oLg0KDQoqKkvhur90IHF14bqjOioqDQoNCkJp4buDdSDEkeG7kyBoaeG7g24gdGjhu4sgaGFpIMSRxrDhu51uZyBjb25nIG3huq10IMSR4buZLCBt4buZdCBjaG8gbeG7l2kgY2hpIG5ow6FuaCAoQnJhbmNoKS4gxJDGsOG7nW5nIGNvbmcgbeG6rXQgxJHhu5kgY2hvIHRo4bqleSBwaMOibiBi4buRIGPhu6dhIGPDoWMgZ2nDoSB0cuG7iyBSYXRpbmcgY2hvIHThu6tuZyBjaGkgbmjDoW5oLg0KDQojIyAqKkJp4buDdSDEkeG7kyAyOioqIGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSBj4bunYSDEkWnhu4NtIMSRw6FuaCBnacOhIChSYXRpbmcpIGThu7FhIHRyw6puIGPDoWMgY2hpIG5ow6FuaCBraMOhYyBuaGF1LCB24bubaSBt4buXaSBjaGkgbmjDoW5oIMSRxrDhu6NjIGhp4buDbiB0aOG7iyB0cm9uZyBjw6FjIMSR4buTIHRo4buLIGNvbiByacOqbmcgYmnhu4d0Lg0KDQpgYGB7cn0NCmEgJT4lIGdncGxvdChhZXMoeCA9IFJhdGluZykpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAnc2t5Ymx1ZScpICsNCiAgZmFjZXRfd3JhcCh+QnJhbmNoKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqZ2dwbG90KGFlcyh4ID0gUmF0aW5nKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gUmF0aW5nIMOhbmggeOG6oSDEkWnhu4NtIMSRw6FuaCBnacOhIHbDoG8gdHLhu6VjIHguDQoNCi0gKipnZW9tX2RlbnNpdHkoZmlsbCA9ICdza3libHVlJyk6KiogSMOgbSBuw6B5IHRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIG3huq10IMSR4buZLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgbcOgdSBu4buBbiBj4bunYSDEkcaw4budbmcgbeG6rXQgxJHhu5kgxJHGsOG7o2MgdGhp4bq/dCBs4bqtcCB0aMOgbmggJ3NreWJsdWUnLg0KDQotICoqZmFjZXRfd3JhcCh+QnJhbmNoKToqKiBIw6BtIG7DoHkgdOG6oW8gcmEgY8OhYyDEkeG7kyB0aOG7iyBjb24gZOG7sWEgdHLDqm4gYmnhur9uIEJyYW5jaC4gQ+G7pSB0aOG7gywgbsOzIHThuqFvIHJhIG3hu5l0IGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSBjaG8gbeG7l2kgZ2nDoSB0cuG7iyBkdXkgbmjhuqV0IGPhu6dhIGJp4bq/biBCcmFuY2gsIHbhu5tpIG3hu5dpIGJp4buDdSDEkeG7kyDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHJvbmcgY8OhYyDDtCByacOqbmcgYmnhu4d0Lg0KDQoqKkvhur90IHF14bqjOioqDQoNCi0gQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KICAgLSBN4buZdCBiaeG7g3UgxJHhu5MgbeG6rXQgxJHhu5kgY2hvIG3hu5dpIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIEJyYW5jaC4NCiAgIA0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyBnacOhIHRy4buLIGPhu6dhIGJp4bq/biBSYXRpbmcuDQogICANCiAgIC0gVHLhu6VjIHR1bmcgaGnhu4NuIHRo4buLIG3huq10IMSR4buZIHjDoWMgc3XhuqV0Lg0KDQogICAtIEJp4buDdSDEkeG7kyDEkcaw4bujYyB0w7QgbcOgdSBi4bqxbmcgbcOgdSAnc2t5Ymx1ZScuDQogICANCiMjICoqQmnhu4N1IMSR4buTIDM6KiogYmnhu4N1IMSR4buTIGPhu5l0IHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIG7DoHkgY2hvIG3hu5dpIHRow6BuaCBwaOG7kSwgY8O5bmcgduG7m2kgc+G7kSBsxrDhu6NuZyDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHLDqm4gbeG7l2kgY+G7mXQuDQoNCmBgYHtyfQ0KYSAlPiUgZ3JvdXBfYnkoQ2l0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBDaXR5KSkgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSxwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMSkpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipncm91cF9ieShDaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpOioqIFRyxrDhu5tjIHRpw6puLCBk4buvIGxp4buHdSDEkcaw4bujYyBuaMOzbSBs4bqhaSB0aGVvIHRow6BuaCBwaOG7kSAoQ2l0eSkgdsOgIHNhdSDEkcOzIHTDrW5oIHThu5VuZyBz4buRIGzGsOG7o25nIGPDoWMgbeG6q3UgdHJvbmcgbeG7l2kgbmjDs20gKHPhu5EgbMaw4bujbmcgdGjDoG5oIHBo4buRKS4gS+G6v3QgcXXhuqMgbMOgIG3hu5l0IGLhuqNuZyBk4buvIGxp4buHdSBt4bubaSB24bubaSBoYWkgY+G7mXQ6IHRow6BuaCBwaOG7kSAoQ2l0eSkgdsOgIHPhu5EgbMaw4bujbmcgKG4pLg0KDQotICoqZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLCBmaWxsID0gQ2l0eSkpOioqIMSQw6J5IGzDoCBwaOG6p24gY8ahIGLhuqNuIGPhu6dhIGJp4buDdSDEkeG7kyBnZ3Bsb3QuIE7DsyB0aGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeMOhYyDEkeG7i25oIG3hu5l0IHRy4bulYyB4IHRy4buRbmcgKCcnKSDEkeG7gyB04bqhbyByYSBjw6FjIGPhu5l0IMSR4buZYyBs4bqtcCBuaGF1LCB5IGzDoCBz4buRIGzGsOG7o25nIChuKSB2w6AgZmlsbCBsw6AgdGjDoG5oIHBo4buRIChDaXR5KS4NCg0KLSAqKmdlb21fY29sKCk6KiogSMOgbSBuw6B5IHRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIGPhu5l0Lg0KDQotICoqZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMSkpOioqIEjDoG0gbsOgeSB0aMOqbSB2xINuIGLhuqNuIHbDoG8gbeG7l2kgY+G7mXQsIHbhu5tpIGxhYmVsIGzDoCBz4buRIGzGsOG7o25nIChuKSB2w6AgduG7iyB0csOtIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDEkeG7gyDEkeG6t3QgdsSDbiBi4bqjbiB0csOqbiBj4buZdC4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgY+G7mXQgY2hvIG3hu5dpIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIENpdHkuDQoNCiAgIC0gQ2hp4buBdSBjYW8gY+G7p2EgbeG7l2kgY+G7mXQgYmnhu4N1IHRo4buLIHPhu5EgbMaw4bujbmcgYuG6o24gZ2hpIHRyb25nIG5ow7NtIHTGsMahbmcg4bupbmcuDQoNCiAgIC0gQmnhu4N1IMSR4buTIMSRxrDhu6NjIHTDtCBtw6B1IHRoZW8gYmnhur9uIENpdHkuDQoNCiAgIC0gR2nDoSB0cuG7iyBuIMSRxrDhu6NjIGhp4buDbiB0aOG7iyB0csOqbiDEkeG7iW5oIGPhu6dhIG3hu5dpIGPhu5l0Lg0KDQojIyAqKkJp4buDdSDEkeG7kyA0OioqIGJp4buDdSDEkeG7kyBj4buZdCB0csOybiBk4buxYSB0csOqbiBz4buRIGzGsOG7o25nIHRow6BuaCBwaOG7kSwgdHJvbmcgxJHDsyBt4buXaSBj4buZdCBiaeG7g3UgZGnhu4VuIG3hu5l0IHRow6BuaCBwaOG7kSwgdsOgIGNoaeG7gXUgY2FvIGPhu6dhIGPhu5l0IMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBi4bufaSBz4buRIGzGsOG7o25nIChuKS4NCg0KYGBge3J9DQphICU+JSBncm91cF9ieShDaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAnJywgeSA9IG4sZmlsbCA9IENpdHkpKSArDQogICAgZ2VvbV9jb2woKSArDQogICAgY29vcmRfcG9sYXIoJ3knKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqZ3JvdXBfYnkoQ2l0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKToqKiBUw61uaCB04buVbmcgc+G7kSBsxrDhu6NuZyBjw6FjIHRow6BuaCBwaOG7kSAoQ2l0eSkgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UgdsOgIGzGsHUga+G6v3QgcXXhuqMgdsOgbyBt4buZdCBi4bqjbmcgZOG7ryBsaeG7h3UgbeG7m2kgduG7m2kgaGFpIGPhu5l0OiB0aMOgbmggcGjhu5EgKENpdHkpIHbDoCBz4buRIGzGsOG7o25nIChuKS4NCg0KLSAqKmdncGxvdChhZXMoeCA9ICcnLCB5ID0gbiwgZmlsbCA9IENpdHkpKToqKiBUaGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeMOhYyDEkeG7i25oIHRy4bulYyB4IHRy4buRbmcgKCcnKSDEkeG7gyB04bqhbyByYSBjw6FjIGPhu5l0IMSR4buZYyBs4bqtcCBuaGF1LCB5IGzDoCBz4buRIGzGsOG7o25nIChuKSwgdsOgIGZpbGwgbMOgIHRow6BuaCBwaOG7kSAoQ2l0eSkuDQoNCi0gKipnZW9tX2NvbCgpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIGPhu5l0Lg0KDQotICoqY29vcmRfcG9sYXIoJ3knKToqKiBDaHV54buDbiDEkeG7lWkgYmnhu4N1IMSR4buTIHRow6BuaCBk4bqhbmcgY+G7mXQgdHLDsm4sIHbhu5tpIGNoaeG7gXUgY2FvIGPhu6dhIGPhu5l0IMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBi4bufaSBnacOhIHRy4buLIHRyw6puIHRy4bulYyB5IChuKS4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdsOybmcgdHLDsm4gY2hvIG3hu5dpIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIENpdHkuDQoNCiAgIC0gRGnhu4duIHTDrWNoIGPhu6dhIG3hu5dpIHbDsm5nIHRyw7JuIGJp4buDdSB0aOG7iyBz4buRIGzGsOG7o25nIGLhuqNuIGdoaSB0cm9uZyBuaMOzbSB0xrDGoW5nIOG7qW5nLg0KDQogICAtIEJp4buDdSDEkeG7kyDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIGJp4bq/biBDaXR5Lg0KDQojIyAqKkJp4buDdSDEkeG7kyA1OioqIGJp4buDdSDEkeG7kyBj4buZdCB0csOybiwgYmnhu4N1IGRp4buFbiBz4buRIGzGsOG7o25nIGPDoWMgdGjDoG5oIHBo4buRIChDaXR5KSBraMOhYyBuaGF1LiBDw6FjIGPhu5l0IMSRxrDhu6NjIHTDtCBtw6B1IHRoZW8gdOG7q25nIHRow6BuaCBwaOG7kSwgdsOgIGPDsyBjaOG7ryBz4buRIMSR4bq/bSBj4bunYSBt4buXaSB0aMOgbmggcGjhu5EgxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGJp4buDdSDEkeG7ky4NCg0KYGBge3J9DQphICU+JSBncm91cF9ieShDaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAnJywgeSA9IG4sZmlsbCA9IENpdHkpKSArDQogICAgZ2VvbV9jb2woY29sb3IgPSAnYmxhY2snKSArDQogICAgY29vcmRfcG9sYXIoJ3knKSArDQogICAgZ2VvbV90ZXh0KGFlcyh4ID0gMS4zLCBsYWJlbCA9IG4pLHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAuNSkpICsNCiAgICB0aGVtZV92b2lkKCkNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2ggY8OidSBs4buHbmg6KioNCg0KLSAqKmdncGxvdChhZXMoeCA9ICcnLCB5ID0gbiwgZmlsbCA9IENpdHkpKToqKiBUaGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeMOhYyDEkeG7i25oIHRy4bulYyB4IHRy4buRbmcgKCcnKSDEkeG7gyB04bqhbyByYSBjw6FjIGPhu5l0IMSR4buZYyBs4bqtcCBuaGF1LCB5IGzDoCBz4buRIGzGsOG7o25nIChuKSwgdsOgIGZpbGwgbMOgIHRow6BuaCBwaOG7kSAoQ2l0eSkuDQoNCi0gKipnZW9tX2NvbChjb2xvciA9ICdibGFjaycpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIGPhu5l0IHbDoCB0w7QgbcOgdSBj4buZdCBi4bqxbmcgZmlsbCwgduG7m2kgbcOgdSB2aeG7gW4gxJFlbiAoY29sb3IgPSAnYmxhY2snKS4NCg0KLSAqKmNvb3JkX3BvbGFyKCd5Jyk6KiogQ2h1eeG7g24gxJHhu5VpIGJp4buDdSDEkeG7kyB0aMOgbmggZOG6oW5nIGPhu5l0IHRyw7JuLCB24bubaSBjaGnhu4F1IGNhbyBj4bunYSBj4buZdCDEkcaw4bujYyB4w6FjIMSR4buLbmggYuG7n2kgZ2nDoSB0cuG7iyB0csOqbiB0cuG7pWMgeSAobikuDQoNCi0gKipnZW9tX3RleHQoYWVzKHggPSAxLjMsIGxhYmVsID0gbiksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAuNSkpOioqIFRow6ptIHbEg24gYuG6o24gdsOgbyBiaeG7g3UgxJHhu5MgduG7m2kgZ2nDoSB0cuG7iyBsYWJlbCBsw6Agc+G7kSBsxrDhu6NuZyAobiksIHbDoCB24buLIHRyw60geMOhYyDEkeG7i25oIGLhurFuZyB4ID0gMS4zLiBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSBnacO6cCDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIGPhu6dhIHbEg24gYuG6o24gdHLDqm4gY+G7mXQuDQoNCi0gKip0aGVtZV92b2lkKCk6KiogTG/huqFpIGLhu48gY8OhYyBwaOG6p24gYsOqbiBuZ2/DoGkgYmnhu4N1IMSR4buTIMSR4buDIHThuqFvIHJhIG3hu5l0IGJp4buDdSDEkeG7kyB0cuG6r25nIMSRxqFuIGdp4bqjbi4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gQmEgdsOybmcgdHLDsm4gKGhv4bq3YyBz4buRIGzGsOG7o25nIHRoZW8gbmjDs20gdHJvbmcgZOG7ryBsaeG7h3UgYSkgxJHGsOG7o2MgdMO0IG3DoHUgdGhlbyBDaXR5Lg0KDQogICAtIE3hu5dpIHbDsm5nIHRyw7JuIGPDsyB2aeG7gW4gbcOgdSDEkWVuLg0KDQogICAtIEdpw6EgdHLhu4sgbiAoc+G7kSBsxrDhu6NuZyBi4bqjbiBnaGkpIMSRxrDhu6NjIGhp4buDbiB0aOG7iyBiw6puIG5nb8OgaSBt4buXaSB2w7JuZyB0csOybiB24bubaSBtw6B1IMSRZW4sIGPDoWNoIHRy4bulYyBob8OgbmggMS4zIMSRxqFuIHbhu4suDQoNCiAgIC0gQmnhu4N1IMSR4buTIG7hu4FuIHRyb25nIHN14buRdCAoa2jDtG5nIGPDsyBraHVuZyBu4buBbiBob+G6t2MgdHLhu6VjIGNow7ogdGjDrWNoKS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgNjoqKiBiaeG7g3UgxJHhu5Mgc2NhdHRlciBwbG90IGJp4buDdSBkaeG7hW4gbeG7kWkgcXVhbiBo4buHIGdp4buvYSBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbSDEkcahbiB24buLIHbDoCBkw7JuZyBz4bqjbiBwaOG6qW0NCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICB4bGFiKCdHacOhIGPhu6dhIHPhuqNuIHBo4bqpbScpICsgDQogIHlsYWIoJ0TDsm5nIHPhuqNuIHBo4bqpbScpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gVW5pdC5wcmljZSDDoW5oIHjhuqEgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0gxJHGoW4gduG7iyB2w6BvIHRy4bulYyB4LCB2w6AgeSA9IFByb2R1Y3QubGluZSDDoW5oIHjhuqEgZMOybmcgc+G6o24gcGjhuqltIHbDoG8gdHLhu6VjIHkuDQoNCi0gKipnZW9tX3BvaW50KCk6KiogVGjDqm0gbeG7mXQgbGF5ZXIgxJHhu4MgduG6vSBiaeG7g3UgxJHhu5Mgc2NhdHRlciBwbG90IHbhu5tpIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdS4NCg0KLSAqKnhsYWIoJ0dpw6EgY+G7p2Egc+G6o24gcGjhuqltJykqKiB2w6AgKip5bGFiKCdEw7JuZyBz4bqjbiBwaOG6qW0nKToqKiBUaGnhur90IGzhuq1wIG5ow6NuIGNobyB0cuG7pWMgeCB2w6AgdHLhu6VjIHkgdMawxqFuZyDhu6luZyB24bubaSAiR2nDoSBj4bunYSBz4bqjbiBwaOG6qW0iIHbDoCAiRMOybmcgc+G6o24gcGjhuqltIi4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdOG6rXAgaOG7o3AgY8OhYyDEkWnhu4NtLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgdHVuZyBoaeG7g24gdGjhu4sgZMOybmcgc+G6o24gcGjhuqltLg0KDQogICAtIE5ow6NuIGNobyB0cuG7pWMgaG/DoG5oIHbDoCB0cuG7pWMgdHVuZy4NCg0KIyMgKipCaeG7g3UgxJHhu5MgNzoqKiBiaeG7g3UgxJHhu5Mgc2NhdHRlciBwbG90IGJp4buDdSBkaeG7hW4gbeG7kWkgcXVhbiBo4buHIGdp4buvYSBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbSDEkcahbiB24buLIHbDoCBkw7JuZyBz4bqjbiBwaOG6qW0sIHbhu5tpIG3DoHUgc+G6r2MgY+G7p2EgdOG7q25nIMSRaeG7g20gZOG7ryBsaeG7h3UgxJHGsOG7o2MgcGjDom4gYmnhu4d0IHRoZW8gY2hpIG5ow6FuaCAoQnJhbmNoKS4NCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lLCBjb2xvciA9IEJyYW5jaCkpICsNCiAgZ2VvbV9wb2ludCgpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lLCBjb2xvciA9IEJyYW5jaCkpOioqIMSQw6J5IGzDoCBwaOG6p24gY8ahIGLhuqNuIGPhu6dhIGJp4buDdSDEkeG7kyBnZ3Bsb3QuIE7DsyB0aGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeCA9IFVuaXQucHJpY2Ugw6FuaCB44bqhIGdpw6EgY+G7p2Egc+G6o24gcGjhuqltIMSRxqFuIHbhu4sgdsOgbyB0cuG7pWMgeCwgeSA9IFByb2R1Y3QubGluZSDDoW5oIHjhuqEgZMOybmcgc+G6o24gcGjhuqltIHbDoG8gdHLhu6VjIHksIHbDoCBjb2xvciA9IEJyYW5jaCDDoW5oIHjhuqEgY2hpIG5ow6FuaCB2w6BvIG3DoHUgc+G6r2MgY+G7p2EgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1Lg0KDQotICoqZ2VvbV9wb2ludCgpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCB24bubaSBjw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UuIEPDoWMgxJFp4buDbSBz4bq9IGPDsyBtw6B1IHPhuq9jIGtow6FjIG5oYXUgdMawxqFuZyDhu6luZyB24bubaSB04burbmcgY2hpIG5ow6FuaC4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdOG6rXAgaOG7o3AgY8OhYyDEkWnhu4NtLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgdHVuZyBoaeG7g24gdGjhu4sgZMOybmcgc+G6o24gcGjhuqltLg0KDQogICAtIEPDoWMgxJFp4buDbSDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIGJp4bq/biBCcmFuY2guDQoNCiMjICoqQmnhu4N1IMSR4buTIDg6KiogYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCBiaeG7g3UgZGnhu4VuIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0gxJHGoW4gduG7iyB2w6AgZMOybmcgc+G6o24gcGjhuqltLCB24bubaSBjw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UgxJHGsOG7o2MgcGjDom4gYmnhu4d0IHRoZW8gaMOsbmggZOG6oW5nIChzaGFwZSkgdMawxqFuZyDhu6luZyB24bubaSB04burbmcgY2hpIG5ow6FuaA0KDQpgYGB7cn0NCmEgJT4lIGdncGxvdChhZXMoeCA9IFVuaXQucHJpY2UsIHkgPSBQcm9kdWN0LmxpbmUsIHNoYXBlID0gQnJhbmNoKSkgKw0KICBnZW9tX3BvaW50KCkNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2ggY8OidSBs4buHbmg6KioNCg0KLSAqKmdncGxvdChhZXMoeCA9IFVuaXQucHJpY2UsIHkgPSBQcm9kdWN0LmxpbmUsIHNoYXBlID0gQnJhbmNoKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gVW5pdC5wcmljZSDDoW5oIHjhuqEgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0gxJHGoW4gduG7iyB2w6BvIHRy4bulYyB4LCB5ID0gUHJvZHVjdC5saW5lIMOhbmggeOG6oSBkw7JuZyBz4bqjbiBwaOG6qW0gdsOgbyB0cuG7pWMgeSwgdsOgIHNoYXBlID0gQnJhbmNoIMOhbmggeOG6oSBjaGkgbmjDoW5oIHbDoG8gaMOsbmggZOG6oW5nIChzaGFwZSkgY+G7p2EgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1Lg0KDQotICoqZ2VvbV9wb2ludCgpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCB24bubaSBjw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UuIEPDoWMgxJFp4buDbSBz4bq9IGPDsyBow6xuaCBk4bqhbmcgKHNoYXBlKSBraMOhYyBuaGF1IHTGsMahbmcg4bupbmcgduG7m2kgdOG7q25nIGNoaSBuaMOhbmguDQoNCioqS+G6v3QgcXXhuqM6KioNCg0KLSBCaeG7g3UgxJHhu5MgYmFvIGfhu5NtOg0KDQogICAtIE3hu5l0IHThuq1wIGjhu6NwIGPDoWMgxJFp4buDbSwgbeG7l2kgxJFp4buDbSDEkeG6oWkgZGnhu4duIGNobyBt4buZdCBz4bqjbiBwaOG6qW0uDQoNCiAgIC0gVHLhu6VjIGhvw6BuaCBoaeG7g24gdGjhu4sgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0uDQoNCiAgIC0gVHLhu6VjIHR1bmcgaGnhu4NuIHRo4buLIGTDsm5nIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBDw6FjIMSRaeG7g20gxJHGsOG7o2MgxJHhu4tuaCBk4bqhbmcgaMOsbmggZOG6oW5nIHRoZW8gYmnhur9uIEJyYW5jaC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgOToqKiBiaeG7g3UgxJHhu5Mgc2NhdHRlciBwbG90IGJp4buDdSBkaeG7hW4gbeG7kWkgcXVhbiBo4buHIGdp4buvYSDEkWnhu4NtIMSRw6FuaCBnacOhIHbDoCBkw7JuZyBz4bqjbiBwaOG6qW0sIHbhu5tpIGvDrWNoIHRoxrDhu5tjIGPhu6dhIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdSDEkcaw4bujYyBwaMOibiBiaeG7h3QgdGhlbyBnaeG7m2kgdMOtbmgNCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBSYXRpbmcsIHkgPSBQcm9kdWN0LmxpbmUsIHNpemUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqZ2dwbG90KGFlcyh4ID0gUmF0aW5nLCB5ID0gUHJvZHVjdC5saW5lLCBzaXplID0gR2VuZGVyKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gUmF0aW5nIMOhbmggeOG6oSDEkWnhu4NtIMSRw6FuaCBnacOhIHbDoG8gdHLhu6VjIHgsIHkgPSBQcm9kdWN0LmxpbmUgw6FuaCB44bqhIGTDsm5nIHPhuqNuIHBo4bqpbSB2w6BvIHRy4bulYyB5LCB2w6Agc2l6ZSA9IEdlbmRlciDDoW5oIHjhuqEgZ2nhu5tpIHTDrW5oIHbDoG8ga8OtY2ggdGjGsOG7m2MgY+G7p2EgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1Lg0KDQotICoqZ2VvbV9wb2ludCgpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCB24bubaSBjw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UuIEPDoWMgxJFp4buDbSBz4bq9IGPDsyBrw61jaCB0aMaw4bubYyBraMOhYyBuaGF1IHTGsMahbmcg4bupbmcgduG7m2kgdOG7q25nIGdp4bubaSB0w61uaC4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdOG6rXAgaOG7o3AgY8OhYyDEkWnhu4NtLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyB44bq/cCBo4bqhbmcgY+G7p2Egc+G6o24gcGjhuqltLg0KDQogICAtIFRy4bulYyB0dW5nIGhp4buDbiB0aOG7iyBkw7JuZyBz4bqjbiBwaOG6qW0uDQoNCiAgIC0gS8OtY2ggdGjGsOG7m2MgY+G7p2EgY8OhYyDEkWnhu4NtIHRoYXkgxJHhu5VpIHRoZW8gYmnhur9uIEdlbmRlci4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTA6KiogYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCBiaeG7g3UgZGnhu4VuIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0gxJHGoW4gduG7iyB2w6AgZMOybmcgc+G6o24gcGjhuqltLCB24bubaSDEkeG7mSB0cm9uZyBzdeG7kXQgY+G7p2EgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1IMSRxrDhu6NjIHBow6JuIGJp4buHdCB0aGVvIGNoaSBuaMOhbmgNCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lLCBhbHBoYSA9IEJyYW5jaCkpICsNCiAgZ2VvbV9wb2ludCgpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lLCBhbHBoYSA9IEJyYW5jaCkpOioqIMSQw6J5IGzDoCBwaOG6p24gY8ahIGLhuqNuIGPhu6dhIGJp4buDdSDEkeG7kyBnZ3Bsb3QuIE7DsyB0aGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeCA9IFVuaXQucHJpY2Ugw6FuaCB44bqhIGdpw6EgY+G7p2Egc+G6o24gcGjhuqltIMSRxqFuIHbhu4sgdsOgbyB0cuG7pWMgeCwgeSA9IFByb2R1Y3QubGluZSDDoW5oIHjhuqEgZMOybmcgc+G6o24gcGjhuqltIHbDoG8gdHLhu6VjIHksIHbDoCBhbHBoYSA9IEJyYW5jaCDDoW5oIHjhuqEgY2hpIG5ow6FuaCB2w6BvIMSR4buZIHRyb25nIHN14buRdCAoYWxwaGEpIGPhu6dhIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdS4NCg0KLSAqKmdlb21fcG9pbnQoKToqKiBUaMOqbSBt4buZdCBsYXllciDEkeG7gyB24bq9IGJp4buDdSDEkeG7kyBzY2F0dGVyIHBsb3QgduG7m2kgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1LiBDw6FjIMSRaeG7g20gc+G6vSBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IGtow6FjIG5oYXUgdMawxqFuZyDhu6luZyB24bubaSB04burbmcgY2hpIG5ow6FuaC4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdOG6rXAgaOG7o3AgY8OhYyDEkWnhu4NtLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgdHVuZyBoaeG7g24gdGjhu4sgZMOybmcgc+G6o24gcGjhuqltLg0KDQogICAtIMSQ4buZIG3hu50gY+G7p2EgY8OhYyDEkWnhu4NtIHRoYXkgxJHhu5VpIHRoZW8gYmnhur9uIEJyYW5jaC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTE6KiogYmnhu4N1IMSR4buTIHBow6JuIHTDoW4gduG7m2kgxJHDoW5oIGdpw6EgKFJhdGluZykgdHLDqm4gdHLhu6VjIHggdsOgIGNoaSBuaMOhbmggKEJyYW5jaCkgdHLDqm4gdHLhu6VjIHkNCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBSYXRpbmcsIHkgPSBCcmFuY2gpKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAncmVkJykgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nLCBjb2xvciA9ICd5ZWxsb3cnKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqZ2dwbG90KGFlcyh4ID0gUmF0aW5nLCB5ID0gQnJhbmNoKSk6KiogQuG6r3QgxJHhuqd1IHbhu5tpIG3hu5l0IGJp4buDdSDEkeG7kyBnZ3Bsb3QgduG7m2kgZOG7ryBsaeG7h3UgxJHGsOG7o2Mgw6FuaCB44bqhIHbDoG8gdHLhu6VjIHggbMOgIMSRaeG7g20gxJHDoW5oIGdpw6EgKFJhdGluZykgdsOgIHRy4bulYyB5IGzDoCBjaGkgbmjDoW5oIChCcmFuY2gpLg0KDQotICoqZ2VvbV9wb2ludChjb2xvciA9ICdyZWQnKToqKiBUaMOqbSBt4buZdCBsYXllciB24bubaSDEkWnhu4NtIGThu68gbGnhu4d1LCB0cm9uZyDEkcOzIG3DoHUgY+G7p2EgY8OhYyDEkWnhu4NtIMSRxrDhu6NjIMSR4bq3dCBsw6AgxJHhu48NCg0KLSAqKmdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScsIGNvbG9yID0gJ3llbGxvdycpOioqIFRow6ptIG3hu5l0IGxheWVyIHbhu5tpIMSRxrDhu51uZyBjb25nIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIChsaW5lYXIgcmVncmVzc2lvbikgxJHGsOG7o2MgZml0IHbDoG8gZOG7ryBsaeG7h3UuIFRyb25nIMSRw7MsIG1ldGhvZCA9ICdsbScgY2jhu4kgcmEgcuG6sW5nIHBoxrDGoW5nIHBow6FwIHPhu60gZOG7pW5nIMSR4buDIGZpdCBk4buvIGxp4buHdSBsw6AgcGjGsMahbmcgcGjDoXAgaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggKGxpbmVhciByZWdyZXNzaW9uKSwgdsOgIG3DoHUgY+G7p2EgxJHGsOG7nW5nIGNvbmcgxJHGsOG7o2MgxJHhurd0IGzDoCBtw6B1IHbDoG5nDQoNCioqS+G6v3QgcXXhuqM6KioNCg0KLSBCaeG7g3UgxJHhu5MgYmFvIGfhu5NtOg0KDQogICAtIE3hu5l0IHThuq1wIGjhu6NwIGPDoWMgxJFp4buDbSBtw6B1IMSR4buPLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyB44bq/cCBo4bqhbmcgY+G7p2Egc+G6o24gcGjhuqltLg0KDQogICAtIFRy4bulYyB0dW5nIGhp4buDbiB0aOG7iyBjaGkgbmjDoW5oIGPhu6dhIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBN4buZdCDEkcaw4budbmcgY29uZyBtw6B1IHbDoG5nIHRo4buDIGhp4buHbiBt4buRaSBxdWFuIGjhu4cgeHUgaMaw4bubbmcgZ2nhu69hIHjhur9wIGjhuqFuZyB2w6AgY2hpIG5ow6FuaC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTI6KiogDQoNCmBgYHtyfQ0KYSAlPiUgZ2dwbG90KGFlcyh4ID0gVW5pdC5wcmljZSwgeSA9IFByb2R1Y3QubGluZSkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICdyZWQnKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScsIGNvbG9yID0gJ3llbGxvdycpICsNCiAgZmFjZXRfd3JhcCh+QnJhbmNoKQ0KYGBgDQoNCioqS+G6v3QgcXXhuqM6KioNCg0KQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KLSBOaGnhu4F1IHBow6JuIMSRb+G6oW4sIG3hu5dpIHBow6JuIMSRb+G6oW4gdMawxqFuZyDhu6luZyB24bubaSBt4buZdCBjaGkgbmjDoW5oIChCcmFuY2gpLg0KDQotIFRyb25nIG3hu5dpIHBow6JuIMSRb+G6oW46DQoNCiAgIC0gQ8OhYyDEkWnhu4NtIG3DoHUgxJHhu48gxJHhuqFpIGRp4buHbiBjaG8gc+G6o24gcGjhuqltIHRodeG7mWMgY2hpIG5ow6FuaCDEkcOzLg0KDQogICAtIMSQxrDhu51uZyBjb25nIG3DoHUgdsOgbmcgdGjhu4MgaGnhu4duIHh1IGjGsOG7m25nIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgZ2nDoSB2w6AgZMOybmcgc+G6o24gcGjhuqltIGNobyBjaGkgbmjDoW5oIMSRw7MuDQoNCiMjICoqQmnhu4N1IMSR4buTIDEzOiBiaeG7g3UgxJHhu5MgY+G7mXQgc+G7rSBk4bulbmcgZ8OzaSBnZ3Bsb3QyIHbDoCBk4buvIGxp4buHdSB04burIHThu4dwIENTViAic3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IioqDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKSAgICAgICANCmRhdGEgPC0gcmVhZC5jc3YoIkQ6L0jDoC9zdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiKQ0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gUHJvZHVjdC5saW5lLCB5ID0gUmF0aW5nLCBmaWxsID0gUHJvZHVjdC5saW5lKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoIlJhdGluZyIpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipkYXRhIDwtIHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2Iik6KiogRMOybmcgbsOgeSDEkeG7jWMgZOG7ryBsaeG7h3UgdOG7qyB04buHcCBDU1YgInN1cGVybWFya2V0X3NhbGVzIC0gU2hlZXQxLmNzdiIgdsOgIGzGsHUgdHLhu68gbsOzIHbDoG8gYmnhur9uIGRhdGEuIEThu68gbGnhu4d1IHPhur0gxJHGsOG7o2MgxJHhu41jIGTGsOG7m2kgZOG6oW5nIGRhdGEgZnJhbWUuDQoNCi0gKipnZ3Bsb3QoZGF0YSwgYWVzKHggPSBQcm9kdWN0LmxpbmUsIHkgPSBSYXRpbmcsIGZpbGwgPSBQcm9kdWN0LmxpbmUpKToqKiBIw6BtIGdncGxvdCgpIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGto4bufaSB04bqhbyBt4buZdCBiaeG7g3UgxJHhu5MgbeG7m2kuIMSQ4buRaSBz4buRIGRhdGEgY2jhu4kgxJHhu4tuaCBk4buvIGxp4buHdSDEkcaw4bujYyBz4butIGThu6VuZy4gVHJvbmcgYWVzKCksIGNow7puZyB0YSBjaOG7iSDEkeG7i25oIGPDoWMgbWFwcGluZyBhZXN0aGV0aWNzICh0xrDGoW5nIOG7qW5nIHbhu5tpIGPDoWMgYmnhur9uKSBjaG8gdHLhu6VjIHggKHggPSBQcm9kdWN0LmxpbmUpLCB0cuG7pWMgeSAoeSA9IFJhdGluZyksIHbDoCBmaWxsIGNvbG9yIChmaWxsID0gUHJvZHVjdC5saW5lKS4gxJBp4buBdSBuw6B5IGPDsyBuZ2jEqWEgbMOgIGNow7puZyB0YSBz4bq9IHbhur0gY+G7mXQgZOG7sWEgdHLDqm4gY+G7mXQgIlByb2R1Y3QubGluZSIsIGNoaeG7gXUgY2FvIGPhu6dhIGPDoWMgY+G7mXQgc+G6vSDEkcaw4bujYyB4w6FjIMSR4buLbmggYuG7n2kgY+G7mXQgIlJhdGluZyIsIHbDoCBtw6B1IHPhuq9jIGPhu6dhIGPDoWMgY+G7mXQgc+G6vSB0xrDGoW5nIOG7qW5nIHbhu5tpIGdpw6EgdHLhu4sgY+G7p2EgIlByb2R1Y3QubGluZSIuDQoNCi0gKipnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iik6KiogSMOgbSBnZW9tX2JhcigpIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHThuqFvIHJhIGJp4buDdSDEkeG7kyBj4buZdC4gVGhhbSBz4buRIHN0YXQgPSAiaWRlbnRpdHkiIGNobyBiaeG6v3QgcuG6sW5nIGNoaeG7gXUgY2FvIGPhu6dhIGPDoWMgY+G7mXQgc+G6vSDEkcaw4bujYyB4w6FjIMSR4buLbmggdHLhu7FjIHRp4bq/cCB04burIGThu68gbGnhu4d1Lg0KDQotICoqc2NhbGVfeV9jb250aW51b3VzKCJSYXRpbmciKToqKiBIw6BtIHNjYWxlX3lfY29udGludW91cygpIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIMSR4bq3dCBuaMOjbiBjaG8gdHLhu6VjIHkgY+G7p2EgYmnhu4N1IMSR4buTLCB24bubaSBuaMOjbiBsw6AgIlJhdGluZyIuDQoNCioqS+G6v3QgcXXhuqM6KioNCk3DoyBuw6B5IHPhur0gdOG6oW8gYmnhu4N1IMSR4buTIHRoYW5oIHRo4buDIGhp4buHbiB0cuG7sWMgcXVhbiB44bq/cCBo4bqhbmcgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBkw7JuZyBz4bqjbiBwaOG6qW0ga2jDoWMgbmhhdSB0cm9uZyBk4buvIGxp4buHdSBiw6FuIGjDoG5nIHNpw6p1IHRo4buLLiANCg0KLSBUcuG7pWMgWDogVHLhu6VjIG7DoHkgc+G6vSBoaeG7g24gdGjhu4sgY8OhYyBkYW5oIG3hu6VjIGR1eSBuaOG6pXQgdOG7qyBj4buZdCBQcm9kdWN0LmxpbmUsIMSR4bqhaSBkaeG7h24gY2hvIGPDoWMgZMOybmcgc+G6o24gcGjhuqltIGtow6FjIG5oYXUgdHJvbmcgZOG7ryBsaeG7h3UgDQoNCi0gVHLhu6VjIFk6IFRy4bulYyBuw6B5IHPhur0gxJHGsOG7o2MgZMOhbiBuaMOjbiAiUmF0aW5nIiB2w6Agc+G6vSBoaeG7g24gdGjhu4sgcGjhuqFtIHZpIHjhur9wIGjhuqFuZyBz4buRIHRyb25nIGThu68gbGnhu4d1IA0KDQotIFRoYW5oOiBCaeG7g3UgxJHhu5Mgc+G6vSBjw7MgbeG7mXQgdGhhbmggZOG7jWMgY2hvIG3hu5dpIGRhbmggbeG7pWMgZMOybmcgc+G6o24gcGjhuqltLiBDaGnhu4F1IGNhbyBj4bunYSBt4buXaSB0aGFuaCBz4bq9IHTGsMahbmcg4bupbmcgduG7m2kgeOG6v3AgaOG6oW5nIHRydW5nIGLDrG5oIGNobyBkw7JuZyBz4bqjbiBwaOG6qW0gxJHDsyAoZ2nhuqMgc+G7rSBzdGF0ID0gImlkZW50aXR5IiB0w61uaCB0b8OhbiBnacOhIHRy4buLIHRydW5nIGLDrG5oKS4NCg0KLSBNw6B1IHPhuq9jOiBN4buXaSB0aGFuaCBz4bq9IMSRxrDhu6NjIHTDtCBi4bqxbmcgbeG7mXQgbcOgdSBraMOhYyBuaGF1IHbDoCBjw6FjIG3DoHUgc+G6vSDEkcaw4bujYyBnw6FuIGThu7FhIHRyw6puIGRhbmggbeG7pWMgZMOybmcgc+G6o24gcGjhuqltICjEkcaw4bujYyB4w6FjIMSR4buLbmggYuG7n2kgeeG6v3UgdOG7kSB0aOG6qW0gbeG7uSBmaWxsID0gUHJvZHVjdC5saW5lKS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTQ6KiogdOG6oW8gbeG7mXQgbG/huqF0IGPDoWMgaGlzdG9ncmFtLCBt4buXaSBoaXN0b2dyYW0gYmnhu4N1IGRp4buFbiBwaMOibiBwaOG7kWkgY+G7p2EgYmnhur9uICJSYXRpbmciICh44bq/cCBo4bqhbmcpIHRyb25nIGThu68gbGnhu4d1Lg0KDQpgYGB7cn0NCnFwbG90KFJhdGluZywgZGF0YSA9IHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IiksIGZhY2V0cyA9IC4gfiBQcm9kdWN0LmxpbmUsIGdlb20gPSAiaGlzdG9ncmFtIiwgYmlud2lkdGggPSAxKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqUmF0aW5nOioqIGJp4bq/biBz4buRIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHbhur0gaGlzdG9ncmFtLCDEkeG6oWkgZGnhu4duIGNobyB44bq/cCBo4bqhbmcgY+G7p2EgY8OhYyBz4bqjbiBwaOG6qW0uDQoNCi0gKipkYXRhID0gcmVhZC5jc3YoIkQ6L0jDoC9zdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiKToqKiDEkMOieSBsw6AgZOG7ryBsaeG7h3UgYuG6oW4gc+G7rSBk4bulbmcgxJHhu4MgduG6vSBoaXN0b2dyYW0uDQpIw6BtIHJlYWQuY3N2KCkgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgxJHhu41jIGThu68gbGnhu4d1IHThu6sgdOG7h3AgQ1NWICJzdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiLg0KDQotICoqZmFjZXRzID0gLiB+IFByb2R1Y3QubGluZToqKiBUaGFtIHPhu5EgbsOgeSB4w6FjIMSR4buLbmggY8OhY2ggZOG7ryBsaeG7h3UgxJHGsOG7o2MgcGjDom4gY2hpYSB0aMOgbmggY8OhYyBt4bq3dCBow6BuZyAoZmFjZXRzKSB0csOqbiBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCAuIH4gUHJvZHVjdC5saW5lIGNo4buJIHJhIHLhurFuZyBt4buXaSBt4bq3dCBow6BuZyAoZmFjZXQpIHPhur0gdMawxqFuZyDhu6luZyB24bubaSBt4buZdCBsb+G6oWkgc+G6o24gcGjhuqltIMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBi4bufaSBiaeG6v24gIlByb2R1Y3QubGluZSIuDQoNCi0gKipnZW9tID0gImhpc3RvZ3JhbSI6KiogTG/huqFpIGjDrG5oIGjhu41jIGLhuqFuIG114buRbiBz4butIGThu6VuZyDEkeG7gyB24bq9IGJp4buDdSDEkeG7ky4gVHJvbmcgdHLGsOG7nW5nIGjhu6NwIG7DoHksIGLhuqFuIMSRYW5nIHPhu60gZOG7pW5nIGhpc3RvZ3JhbSDEkeG7gyBiaeG7g3UgZGnhu4VuIHBow6JuIHBo4buRaSBj4bunYSBk4buvIGxp4buHdS4NCg0KLSAqKmJpbndpZHRoID0gMToqKiDEkOG7mSBy4buZbmcgY+G7p2EgY8OhYyBiaW4gKG5nxINuKSB0cm9uZyBoaXN0b2dyYW0uIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCDEkeG7mSBy4buZbmcgY+G7p2EgbeG7l2kgYmluIMSRxrDhu6NjIHRoaeG6v3QgbOG6rXAgbMOgIDEsIGPDsyBuZ2jEqWEgbMOgIG3hu5dpIGJpbiBz4bq9IGJhbyBn4buTbSBjw6FjIGdpw6EgdHLhu4sgeOG6v3AgaOG6oW5nIHRyb25nIGtob+G6o25nIGPDsyDEkeG7mSBy4buZbmcgbMOgIDEuDQoNCioqS+G6v3QgcXXhuqM6KioNCkJp4buDdSDEkeG7kyB04bqhbyByYSBz4bq9IGhp4buDbiB0aOG7iyBwaMOibiBwaOG7kWkgeOG6v3AgaOG6oW5nIChSYXRpbmcpIGNobyB04burbmcgZMOybmcgc+G6o24gcGjhuqltIChQcm9kdWN0LmxpbmUpIHJpw6puZyBiaeG7h3QuIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCi0gTmhp4buBdSBwaMOibiDEkW/huqFuOiBN4buXaSBwaMOibiDEkW/huqFuIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IGTDsm5nIHPhuqNuIHBo4bqpbS4NCg0KLSBUcuG7pWMgWTogSGnhu4NuIHRo4buLIHjhur9wIGjhuqFuZyBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBjaG8gbeG7l2kgeOG6v3AgaOG6oW5nLg0KDQotIEPhu5l0OiBN4buXaSBj4buZdCB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY8OzIHjhur9wIGjhuqFuZyBj4bulIHRo4buDIHRyb25nIG3hu5l0IGTDsm5nIHPhuqNuIHBo4bqpbS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTU6KiogDQoNCmBgYHtyfQ0KcXBsb3QoIFJhdGluZywgVW5pdC5wcmljZSwgZGF0YSA9IHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IiksIGNvbG9yID0gQnJhbmNoKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqUmF0aW5nLCBVbml0LnByaWNlOioqIMSQw6J5IGzDoCBjw6FjIGJp4bq/biBi4bqhbiBtdeG7kW4gduG6vSB0csOqbiB0cuG7pWMgeCB2w6AgdHLhu6VjIHksIHTGsMahbmcg4bupbmcgbMOgICJSYXRpbmciIHbDoCAiVW5pdC5wcmljZSIuDQoNCi0gKipkYXRhID0gcmVhZC5jc3YoIkQ6L0jDoC9zdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiKToqKiDEkMOieSBsw6AgZOG7ryBsaeG7h3UgYuG6oW4gc+G7rSBk4bulbmcgxJHhu4MgduG6vSBiaeG7g3UgxJHhu5MuIEjDoG0gcmVhZC5jc3YoKSDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyDEkeG7jWMgZOG7ryBsaeG7h3UgdOG7qyB04buHcCBDU1YgInN1cGVybWFya2V0X3NhbGVzIC0gU2hlZXQxLmNzdiIuDQoNCi0gKipjb2xvciA9IEJyYW5jaDoqKiBUaGFtIHPhu5EgbsOgeSBjaOG7iSDEkeG7i25oIGPDoWNoIGJp4buDdSDEkeG7kyBwaMOibiB0w6FuIHPhur0gxJHGsOG7o2MgbcOgdSBz4bqvYyBow7NhIGThu7FhIHRyw6puIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uICJCcmFuY2giLiBD4bulIHRo4buDLCBt4buXaSDEkWnhu4NtIGThu68gbGnhu4d1IHPhur0gxJHGsOG7o2MgbcOgdSBz4bqvYyBraMOhYyBuaGF1IHTGsMahbmcg4bupbmcgduG7m2kgZ2nDoSB0cuG7iyBj4bunYSBiaeG6v24gIkJyYW5jaCIuDQoNCioqS+G6v3QgcXXhuqM6KioNCkJp4buDdSDEkeG7kyB04bqhbyByYSBz4bq9IGhp4buDbiB0aOG7iyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIHjhur9wIGjhuqFuZyAoUmF0aW5nKSB2w6AgZ2nDoSBiw6FuIChVbml0LnByaWNlKSBj4bunYSBjw6FjIHPhuqNuIHBo4bqpbS4gQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KLSBUcuG7pWMgWTogSGnhu4NuIHRo4buLIHjhur9wIGjhuqFuZyBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBnacOhIGLDoW4gc+G6o24gcGjhuqltLg0KDQotIMSQaeG7g20gZOG7ryBsaeG7h3U6IE3hu5dpIMSRaeG7g20gxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQgc+G6o24gcGjhuqltLCDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIGNoaSBuaMOhbmggKEJyYW5jaCkgY+G7p2Egc+G6o24gcGjhuqltIMSRw7MuDQoNCiMjICoqQmnhu4N1IMSR4buTIDE2OioqDQoNCmBgYHtyfQ0KcXBsb3QoUmF0aW5nLCBkYXRhID0gcmVhZC5jc3YoIkQ6L0jDoC9zdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiKSwgZ2VvbSA9ICJoaXN0b2dyYW0iLCBiaW53aWR0aCA9IDAuMDUpDQpgYGANCioqS+G6v3QgcXXhuqM6KioNCkJp4buDdSDEkeG7kyB04bqhbyByYSBz4bq9IGhp4buDbiB0aOG7iyBwaMOibiBwaOG7kWkgeOG6v3AgaOG6oW5nIChSYXRpbmcpIGPhu6dhIHPhuqNuIHBo4bqpbS4gQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KLSBUcuG7pWMgWTogSGnhu4NuIHRo4buLIHjhur9wIGjhuqFuZyBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBjaG8gbeG7l2kgeOG6v3AgaOG6oW5nLg0KDQotIEPhu5l0OiBN4buXaSBj4buZdCB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY8OzIHjhur9wIGjhuqFuZyBu4bqxbSB0cm9uZyBraG/huqNuZyBj4bulIHRo4buDLg0KDQojIyAqKkJp4buDdSDEkeG7kyAxNzoqKiANCg0KYGBge3J9DQpxcGxvdChRdWFudGl0eSwgZGF0YSA9IHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IiksIGdlb20gPSAiZGVuc2l0eSIpDQpgYGANCioqS+G6v3QgcXXhuqM6KioNCkJp4buDdSDEkeG7kyB04bqhbyByYSBz4bq9IGhp4buDbiB0aOG7iyBt4bqtdCDEkeG7mSBwaMOibiBwaOG7kWkgY+G7p2Egc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gKFF1YW50aXR5KSDEkcaw4bujYyBiw6FuLiBCaeG7g3UgxJHhu5MgYmFvIGfhu5NtOg0KDQotIFRy4bulYyBYOiBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFk6IEhp4buDbiB0aOG7iyBt4bqtdCDEkeG7mSwgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgZOG7ryBsaeG7h3UgdOG6rXAgdHJ1bmcgdOG6oWkgbeG7l2kgZ2nDoSB0cuG7iyBj4bunYSBRdWFudGl0eS4NCg0KLSDEkMaw4budbmcgY29uZzogxJDGsOG7nW5nIGNvbmcgbcaw4bujdCBtw6AgdGjhu4MgaGnhu4duIG3huq10IMSR4buZIHBow6JuIHBo4buRaSBj4bunYSBk4buvIGxp4buHdS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTg6KioNCg0KYGBge3J9DQpnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGRhdGEgPSBmaWx0ZXIoYSwgQnJhbmNoID09ICdBJyksIGFlcyh4ID0gVW5pdC5wcmljZSksIGJpbndpZHRoID0gNSwgZmlsbCA9ICdwaW5rJykgKw0KICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gZmlsdGVyKGEsIEJyYW5jaCA9PSAnQycpLCBhZXMoeCA9IFVuaXQucHJpY2UpLCBiaW53aWR0aCA9IDUsIGZpbGwgPSAnc2t5Ymx1ZScpDQoNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2ggY8OidSBs4buHbmg6KioNCg0KLSAqKmdncGxvdCgpOioqIELhuq90IMSR4bqndSBt4buZdCDEkeG7kWkgdMaw4bujbmcgZ2dwbG90MiBt4bubaSBtw6Aga2jDtG5nIGPhuqduIGvhur90IG7hu5FpIHbhu5tpIGThu68gbGnhu4d1IGPhu6UgdGjhu4MuDQoNCi0gKipnZW9tX2hpc3RvZ3JhbSgpOioqIGNow7puZyB0YSB0aMOqbSBoYWkgbOG7m3AgZOG7ryBsaeG7h3UgaGlzdG9ncmFtLCBt4buXaSBs4bubcCB0xrDGoW5nIOG7qW5nIHbhu5tpIG3hu5l0IGNoaSBuaMOhbmgga2jDoWMgbmhhdS4NCg0KLSAqKmRhdGEgPSBmaWx0ZXIoYSwgQnJhbmNoID09ICdBJykgdsOgIGRhdGEgPSBmaWx0ZXIoYSwgQnJhbmNoID09ICdDJyk6KiogTOG7jWMgZOG7ryBsaeG7h3UgdOG7qyBhIChnaeG6oyBz4butIGzDoCBkYXRhIGZyYW1lIGNo4bupYSBk4buvIGxp4buHdSkgxJHhu4MgY2jhu4kgbOG6pXkgY8OhYyBxdWFuIHPDoXQgY8OzIGdpw6EgdHLhu4sgIkJyYW5jaCIgdMawxqFuZyDhu6luZyAoIkEiIHbDoCAiQyIgbOG6p24gbMaw4bujdCkuIMSQaeG7gXUgbsOgeSBnacO6cCBjaMO6bmcgdGEgY2jhu4kgduG6vSBoaXN0b2dyYW0gY2hvIGPDoWMgcXVhbiBzw6F0IHRodeG7mWMgY8OhYyBjaGkgbmjDoW5oIG7DoHkuDQoNCi0gKiphZXMoeCA9IFVuaXQucHJpY2UpOioqIFThuqFvIG1hcHBpbmcgY2hvIGJp4bq/biBVbml0LnByaWNlIHRyw6puIHRy4bulYyB4IGPhu6dhIGhpc3RvZ3JhbS4NCg0KLSAqKmJpbndpZHRoID0gNToqKiBYw6FjIMSR4buLbmggxJHhu5kgcuG7mW5nIGPhu6dhIGPDoWMgYmluIChuZ8SDbikgdHJvbmcgaGlzdG9ncmFtLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgxJHhu5kgcuG7mW5nIGPhu6dhIG3hu5dpIGJpbiDEkcaw4bujYyDEkeG6t3QgbMOgIDUuDQoNCi0gKipmaWxsOioqIFjDoWMgxJHhu4tuaCBtw6B1IHPhuq9jIGNobyBoaXN0b2dyYW0gY+G7p2EgbeG7l2kgY2hpIG5ow6FuaC4gSGlzdG9ncmFtIGNobyBjaGkgbmjDoW5oICJBIiBz4bq9IGPDsyBtw6B1IGjhu5NuZyAoInBpbmsiKSB2w6AgaGlzdG9ncmFtIGNobyBjaGkgbmjDoW5oICJDIiBz4bq9IGPDsyBtw6B1IHhhbmggZGEgdHLhu51pICgic2t5Ymx1ZSIpLg0KDQoqKkvhur90IHF14bqjOioqDQpCaeG7g3UgxJHhu5MgdOG6oW8gcmEgc+G6vSBoaeG7g24gdGjhu4sgaGFpIGJp4buDdSDEkeG7kyBow6xuaCBj4buZdCBjaOG7k25nIGzDqm4gbmhhdSwgc28gc8OhbmggcGjDom4gcGjhu5FpIGdpw6EgYsOhbiAoVW5pdC5wcmljZSkgY+G7p2EgaGFpIGNoaSBuaMOhbmggQSB2w6AgQy4gQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KLSBUcuG7pWMgWDogSGnhu4NuIHRo4buLIGdpw6EgYsOhbiBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFk6IEhp4buDbiB0aOG7iyBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBjaG8gbeG7l2kgZ2nDoSBiw6FuLg0KDQotIEPhu5l0OiBIYWkgbmjDs20gY+G7mXQsIG3hu5l0IG3DoHUgaOG7k25nIChjaGkgbmjDoW5oIEEpIHbDoCBt4buZdCBtw6B1IHhhbmggZGEgdHLhu51pIChjaGkgbmjDoW5oIEMpLCB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY2hvIG3hu5dpIGdpw6EgYsOhbiBj4bunYSB04burbmcgY2hpIG5ow6FuaC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTk6KioNCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDMsIGZpbGwgPSAnZ3JlZW4nLCBjb2xvciA9ICdyZWQnKSArDQogIGZhY2V0X3dyYXAofkJyYW5jaCkNCmBgYA0KKipL4bq/dCBxdeG6ozoqKg0KQmnhu4N1IMSR4buTIHThuqFvIHJhIHPhur0gaGnhu4NuIHRo4buLIG3hu5l0IGxv4bqhdCBjw6FjIGJp4buDdSDEkeG7kyBow6xuaCBj4buZdCwgbeG7l2kgYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBwaMOibiBwaOG7kWkgZ2nDoSBiw6FuIChVbml0LnByaWNlKSBjaG8gdOG7q25nIGNoaSBuaMOhbmggKEJyYW5jaCkuIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCi0gTmhp4buBdSBwaMOibiDEkW/huqFuOiBN4buXaSBwaMOibiDEkW/huqFuIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IGNoaSBuaMOhbmguDQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBnacOhIGLDoW4gc+G6o24gcGjhuqltLg0KDQotIFRy4bulYyBZOiBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY2hvIG3hu5dpIGdpw6EgYsOhbi4NCg0KLSBD4buZdDogQ8OhYyBj4buZdCB0cm9uZyBt4buXaSBwaMOibiDEkW/huqFuIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBjaG8gbeG7l2kgZ2nDoSBiw6FuIGPhu6dhIHThu6tuZyBjaGkgbmjDoW5oLg0KDQojIyAqKkJp4buDdSDEkeG7kyAyMDoqKg0KDQpgYGB7cn0NCmEgJT4lIGdncGxvdChhZXMoeCA9IFVuaXQucHJpY2UsIGZpbGwgPSBQcm9kdWN0LmxpbmUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSkNCmBgYA0KDQoqKkvhur90IHF14bqjOioqDQpCaeG7g3UgxJHhu5MgdOG6oW8gcmEgc+G6vSBoaeG7g24gdGjhu4sgbeG7mXQgYmnhu4N1IMSR4buTIGjDrG5oIGPhu5l0IHbhu5tpIGPDoWMgY+G7mXQgxJHGsOG7o2MgdMO0IG3DoHUgdGhlbyBkw7JuZyBz4bqjbiBwaOG6qW0gKFByb2R1Y3QubGluZSkuIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBnacOhIGLDoW4gc+G6o24gcGjhuqltLg0KDQotIFRy4bulYyBZOiBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY2hvIG3hu5dpIGdpw6EgYsOhbi4NCg0KLSBD4buZdDogQ8OhYyBj4buZdCDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIGTDsm5nIHPhuqNuIHBo4bqpbSwgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgc+G6o24gcGjhuqltIGNobyBt4buXaSBnacOhIGLDoW4gY+G7p2EgdOG7q25nIGTDsm5nIHPhuqNuIHBo4bqpbS4=