Giới thiệu bộ
dữ liệu.
Giới thiệu về
tập dữ liệu:
Dữ liệu Amazon 2_Raw là Doanh số bán sản
phẩm của Amazon từ đầu năm 2011 đến cuối năm 2014. Bộ dữ liệu về bán
hàng trên Amazon này chứa 3204 hàng và 9 cột.
Mô tả cột:
Order ID - Mã đơn hàng.
Order Date - Ngày đặt hàng.
Ship Date - Ngày vận chuyển.
Email_ID - Email_ID của người dùng
Geography - Vị trí đặt hàng của người
dùng.
Category - Danh mục sản phẩm
Product Name – Tên sản phẩm của Amazon
Sales - Doanh số bán sản phẩm Amazon
Quantily - có bao nhiêu đơn vị của một sản phẩm
cụ thể có sẵn.
Profit - Lợi nhuận bán hàng trên Amazon
Gán tên e cho bộ dữ liệu Amazon
2_Raw.
library(DT)
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(xlsx)
e <- read.xlsx("F:/R/data1/Amazon 2_Raw.xlsx", sheetIndex= 1, header= T)
names(e) <- c('OrderID','OrderDate','ShipDate','EmailID','Geography','Category','ProductName','Sales','Quantily','Profit')
datatable(e)
Bảng trên là bộ dữ liệu e, được chia thành 321
bảng để dễ quan sát hơn, mỗi bảng 10 quan sát, bảng 321 chứa 3 quan
sát.
- Mỗi một quan sát trong bộ dữ liệu là một sản phẩm được bán ra của
Amazon trong giai đoạn đầu 2011 đến cuối 2014.
Quan sát bộ
dữ liệu.
Sử dụng câu lệnh skim thuộc package skimr quan sát
tổng quan bộ dữ liệu trên:
Data summary
| Name |
e |
| Number of rows |
3203 |
| Number of columns |
10 |
| _______________________ |
|
| Column type frequency: |
|
| character |
5 |
| Date |
2 |
| numeric |
3 |
| ________________________ |
|
| Group variables |
None |
Variable type: character
| OrderID |
0 |
1 |
14 |
14 |
0 |
1611 |
0 |
| EmailID |
0 |
1 |
16 |
31 |
0 |
686 |
0 |
| Geography |
0 |
1 |
23 |
41 |
0 |
170 |
0 |
| Category |
0 |
1 |
3 |
11 |
0 |
17 |
0 |
| ProductName |
0 |
1 |
5 |
109 |
0 |
1494 |
0 |
Variable type: Date
| OrderDate |
0 |
1 |
2011-01-07 |
2014-12-31 |
2013-07-22 |
845 |
| ShipDate |
0 |
1 |
2011-01-09 |
2015-01-06 |
2013-07-25 |
911 |
Variable type: numeric
| Sales |
0 |
1 |
226.49 |
524.88 |
0.99 |
19.44 |
60.84 |
215.81 |
13999.96 |
▇▁▁▁▁ |
| Quantily |
0 |
1 |
3.83 |
2.26 |
1.00 |
2.00 |
3.00 |
5.00 |
14.00 |
▇▅▁▁▁ |
| Profit |
0 |
1 |
33.85 |
174.11 |
-3399.98 |
3.85 |
11.17 |
33.00 |
6719.98 |
▁▇▁▁▁ |
Nhận xét:
Mã đơn hàng (Order ID) là một chuỗi số, ký tự
hoặc kết hợp cả hai, được tạo ra để định danh và theo dõi một đơn hàng
cụ thể trong hệ thống đặt hàng của một công ty. Mỗi đơn hàng được gán
một mã đơn hàng duy nhất để nó có thể được dễ dàng xác định và quản
lý.
Amazon không công bố thông tin chi tiết về cách
họ tạo và quản lý mã đơn hàng (Order ID). Công ty giữ thông tin này là
bí mật và không chia sẻ công khai vì nhiều lý do liên quan đến bảo mật
và quyền riêng tư. Thế nên rất để xác định chính xác thành phần trong mã
order ID trong bộ dữ liệu.
Tuy nhiên, ta có thể phân biệt hai thành phần sau cùng của order
ID. Thành phần thứ hai là năm của đơn hàng và thứ ba có thể đại diện cho
một số duy nhất hoặc định danh cụ thể của đơn hàng đó
trong hệ thống quản lý của Amazon. Số này thường được tạo ra để đảm bảo
tính duy nhất của mỗi đơn hàng và giúp quản lý chúng hiệu quả.
Nhìn vào order date và ship
date, ta thấy bộ dữ liệu này thu thập vào giai đoạn năm
2011-2014.
Tiếp theo là tứ phân vị; trung bình, lớn nhất và nhỏ
nhất của Sales, Quantily, Profit.
Đối với Sales:
Giá trị trung bình của Sales (mean) là
226.49, trung tâm dữ liệu (điểm chính giữa) của
Sales.
Giá trị nhỏ nhất của Sales (p0) là
0.99, có nghĩa là không còn đơn hàng nào có doanh số
bán hàng nhỏ hơn 0.99.
Giá trị lớn nhất của Sales (p100) là
13999.9, có nghĩa là không còn đơn hàng nào có doanh số
bán hàng lớn hơn 13999.9.
Phân vị p25 : có 25% số quan sát có doanh số bán
hàng nhỏ hơn 19.44.
Phân vị p50 :Có nghĩa là có 50% số quan sát có
doanh số bán hàng nhỏ hơn 60.84 và 50% còn lại lớn
hơn.
Phân vị p75 : có 75% quan sát có doanh số bán
hàng nhỏ hơn 215.81, 25% còn lại thì lớn hơn con số
này.
Nghiên cứu
doanh số bán hàng của Amazon trong giai đoạn 2011 - 2014.
Biểu đồ mô tả
Sales.
## Warning: package 'ggplot2' was built under R version 4.3.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0 ✔ readr 2.1.5
## ✔ ggplot2 3.5.0 ✔ stringr 1.5.1
## ✔ lubridate 1.9.3 ✔ tibble 3.2.1
## ✔ purrr 1.0.2 ✔ tidyr 1.3.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(dplyr)
e %>% ggplot(aes(x = Sales)) +
geom_histogram(binwidth = 500, fill = 'blue', color = 'red')

Nhận xét:
Mức doanh số bán hàng thấp từ 1500 trở xuống chiếm số
lượng lớn. Có thể nói mức doanh số thấp chiếm đa phần.
Đồng nghĩa với việc giá trị Sales càng lớn thì số lượng bán ra
càng nhỏ.
Nhìn chung, Doanh nghiệp nên chú trọng các mặt hàng giá thấp được
mua với số lượng nhiều, bên cạnh đó đẩy nhanh quá trình thu hút khách
hàng giành cho mặt hàng cao cấp.
Biểu đồ theo
Sales và Category.
e %>% ggplot(aes(x = Sales, fill = Category)) +
geom_histogram(binwidth = 500)

Biểu đồ quan
sát Profit.
e$p1 <- case_when(e$Profit <= 50 ~'rất nhỏ', e$Profit >= 50 & e$Profit <= 100 ~ 'vừa', e$Profit >= 100 ~ 'lớn')
e %>% ggplot(aes(x = p1)) +
geom_bar(fill='purple') + labs(x='Lợi nhuận bán hàng', y= 'số lượng')

Để có thể xem xét dữ liệu trực quan hơn, ta chia nhỏ biến
Profit thành 3 nhóm ** rất nhỏ, vừa, lớn** bằng lên
case_when và gán tên p1
Nhận xét:
+Ở biến lợi nhuận bán hàng này, nhóm rất nhỏ chiếm phần
lớn.
Trước đó chúng ta đã có thể dự đoán được lợi
nhận bán hàng thuốc nhóm rất nhỏ sẽ chiếm phần lớn. Phần lớn
các đơn đặt hàng được bán ra đều có giá trị thấp, thế
nên lợi nhận cũng thấp theo.
Tuy nhiên, nếu xét tổng thể thì mức doanh thu và lợi nhuận đều
rất cao, bởi vì mặc dù giá trị thấp nhưng lại có rất nhiều đơn hàng. Lấy
số lượng bù chất lượng.
Biểu đồ quan
sát Profit và Sales.
e %>% ggplot(aes(x= Profit, y= Sales)) + geom_point() +
xlab('Lợi nhuận') +
ylab('Doanh số')

Nhận xét:
Nhìn qua biểu đồ, ta thấy sự tăng trưởng của Sales và Profit có
sự quan hệ mặt thiết với nhau.
Mối tương quan: Biểu đồ cho thấy mối tương quan giữa Lợi nhuận và
Doanh số.
Mối tương quan dương: Nếu các điểm có xu hướng
di chuyển từ dưới lên trên và từ trái sang phải, có thể cho thấy mối
tương quan dương giữa hai biến. Điều này có nghĩa là khi Lợi nhuận tăng,
Doanh số cũng có xu hướng tăng.
Mối tương quan âm: Nếu các điểm có xu hướng di
chuyển từ trên xuống dưới và từ trái sang phải, có thể cho thấy mối
tương quan âm giữa hai biến. Điều này có nghĩa là khi Lợi nhuận tăng,
Doanh số có xu hướng giảm.
Không có mối tương quan: Nếu các điểm phân bố
ngẫu nhiên trên biểu đồ, có thể cho thấy không có mối tương quan rõ ràng
giữa hai biến.
+Mức độ tập trung:
+Mật độ cao: Nếu các điểm tập trung dày đặc trong một khu vực, có thể
cho thấy mối liên hệ mạnh mẽ giữa hai biến.
+Mật độ thấp: Nếu các điểm phân bố rải rác trên biểu đồ, có thể cho
thấy mối liên hệ yếu hoặc không có mối liên hệ giữa hai biến
Biểu đồ quan
sát lợi nhận bán hàng theo từng năm.
library(ggplot2)
e$s <- year(e$OrderDate)
table (e$s)
##
## 2011 2012 2013 2014
## 661 642 801 1099
e %>% group_by(Profit,s) %>% summarise(n=n()) %>%
ggplot(aes(x=s,y=n)) + geom_col(fill='pink') +
geom_text(aes(label=round(n,2)),vjust=2, color='black')
## `summarise()` has grouped output by 'Profit'. You can override using the
## `.groups` argument.

Nhận xét:
library(ggplot2): Dòng code này tải thư viện ggplot2 cần thiết để
tạo biểu đồ. e\(s <-
year(e\)OrderDate): Dòng này tạo một cột mới tên s trong dữ liệu
e bằng cách trích xuất năm từ cột OrderDate.
Bảng tần suất theo năm
table(e$s): Dòng này in ra bảng tần suất của các giá trị trong
cột s, cho biết số lần xuất hiện của mỗi năm trong dữ liệu. Bảng này hữu
ích để kiểm tra sự phân bố dữ liệu theo năm.
Nhóm dữ liệu theo Lợi nhuận và Năm
e %>% group_by(Profit, s) %>% summarise(n = n()): Dòng này
sử dụng dplyr để nhóm dữ liệu theo các cặp Profit (lợi nhuận) và s
(năm). Hàm summarise tính tổng số lần xuất hiện (số lượng) của mỗi nhóm,
lưu trữ trong biến n.
Tạo biểu đồ
ggplot(aes(x = s, y = n)): Dòng này thiết lập nền tảng cho biểu
đồ bằng cách xác định trục hoành (x) là năm (s) và trục tung (y) là số
lượng (n).
geom_col(fill=‘pink’): Dòng này tạo biểu đồ hình cột, với màu sắc
được tô là hồng (fill=‘pink’).
geom_text(aes(label = round(n, 2)), vjust = 2, color = ‘black’):
Dòng này thêm nhãn cho các cột, hiển thị giá trị n được làm tròn đến hai
chữ số thập phân (round(n, 2)). Vị trí của nhãn được điều chỉnh theo
trục tung (vjust = 2) và màu sắc nhãn là đen (color = ‘black’).
Giải thích biểu đồ
Biểu đồ này thể hiện số lượng theo năm (n) được phân nhóm theo
lợi nhuận (Profit). Mỗi cột đại diện cho một cặp lợi nhuận-năm, với
chiều cao của cột biểu thị số lượng đơn vị dữ liệu có mức lợi nhuận đó
trong năm tương ứng. Nhãn trên mỗi cột hiển thị giá trị số lượng đã được
làm tròn.
Nhận xét biểu đồ
Biểu đồ giúp bạn:
Phân tích sự phân bố của lợi nhuận theo năm: Bạn có thể quan sát
xem lợi nhuận có phân bố đồng đều theo các năm hay tập trung chủ yếu vào
một số năm nhất định. So sánh chiều cao của các cột cùng một lợi nhuận
giữa các năm khác nhau.
Xác định các năm có hoạt động nổi bật: Những năm có các cột cao
bất thường cho một mức lợi nhuận cụ thể có thể là những năm có hoạt động
kinh doanh đáng chú ý.
Kiểm tra sự tương quan giữa lợi nhuận và năm: Nếu có sự phụ thuộc
rõ ràng giữa lợi nhuận và năm (ví dụ: lợi nhuận luôn cao nhất vào một
năm cụ thể), biểu đồ này có thể giúp bạn xác định điều đó.
Biểu đồ quan
sát doanh số bán hàng theo tháng.
e$q <- month(e$OrderDate)
table(e$q)
##
## 1 2 3 4 5 6 7 8 9 10 11 12
## 108 99 202 192 210 203 224 254 445 299 442 525
e %>% group_by(Sales,q) %>% summarise(n=n()) %>%
ggplot(aes(x=q,y=n)) + geom_col(fill='lightgreen') +geom_text(aes(label=round(n,2) , vjust=2, color='black')) + labs(x='tháng',y ='Doanh số bán hàng')
## `summarise()` has grouped output by 'Sales'. You can override using the
## `.groups` argument.

Biểu đồ quan
sát lượng sản phẩm sẵng sàn cung ứng.
e %>% ggplot(aes(x=Quantily))+ geom_bar(fill='lightblue')

Quan sát
Sales, Profit, Quantily.
e %>% ggplot(aes(x=Sales, y= Quantily, color=Profit)) +geom_point()

Biểu đồ này được tạo bởi đoạn mã R sử dụng gói ggplot2 để thể hiện
mối quan hệ giữa doanh số (Sales), phân vị (Quantily) và lợi nhuận
(Profit).
Phân tích các yếu tố:
Trục hoành (x): Thể hiện doanh số (Sales).
Trục tung (y): Thể hiện phân vị (Quantily).
Điểm (geom_point()): Biểu thị từng cặp dữ liệu (doanh số, phân
vị) với màu sắc được mã hóa theo lợi nhuận (Profit).
Màu sắc (color=Profit): Các điểm được tô màu theo mức độ lợi
nhuận.
Nhận xét:
Quan sát biểu
đồ động.
## Warning: package 'gganimate' was built under R version 4.3.3
## Warning: package 'magick' was built under R version 4.3.3
## Linking to ImageMagick 6.9.12.98
## Enabled features: cairo, freetype, fftw, ghostscript, heic, lcms, pango, raw, rsvg, webp
## Disabled features: fontconfig, x11
e %>% ggplot(aes(x = Sales, y = Profit, color = Quantily)) +
geom_line() +
geom_point(size=2) +
transition_reveal(Sales, keep_last = F)

Biểu đồ động này được tạo bởi đoạn mã R sử dụng gói ggplot2 và hiệu
ứng chuyển tiếp transition_reveal để thể hiện mối quan hệ giữa doanh số
(Sales), lợi nhuận (Profit) và phân vị (Quantily).
Các yếu tố:
+,Trục hoành (x): Thể hiện doanh số (Sales).
Trục tung (y): Thể hiện lợi nhuận (Profit).
Đường kẻ (geom_line()): Thể hiện xu hướng thay đổi lợi nhuận theo
doanh số, được phân biệt theo phân vị (màu sắc).
Điểm (geom_point(size=2)): Biểu thị từng cặp dữ liệu (doanh số,
lợi nhuận) với kích thước 2.
Màu sắc (color = Quantily): Các đường kẻ và điểm được tô màu theo
phân vị (có thể là tứ phân vị hoặc phân vị khác).
Hiệu ứng chuyển tiếp (transition_reveal(Sales, keep_last = F)):
Dữ liệu được tiết lộ dần dần theo thứ tự tăng dần của doanh số.
Nhận xét:
Biểu đồ giúp phân tích mối quan hệ giữa doanh số và lợi nhuận
theo các phân vị khác nhau.
Hiệu ứng chuyển tiếp giúp tập trung vào các điểm dữ liệu và đường
kẻ có doanh số cao hơn.
Bạn có thể phân tích xu hướng của lợi nhuận theo doanh số, so
sánh lợi nhuận giữa các phân vị, và xác định phân vị có lợi nhuận cao
nhất/thấp nhất.
VẼ biểu đồ
động bằng tứ phân vị của Sales.
e %>% group_by(Quantily) %>% summarise(d=cut(e$Quantily,3,label= c('nhỏ','vừa','lớn'))) %>%
ggplot(aes(x=Quantily,y=d)) +
geom_col() +
labs(x='Quantily',y='.')
## Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in
## dplyr 1.1.0.
## ℹ Please use `reframe()` instead.
## ℹ When switching from `summarise()` to `reframe()`, remember that `reframe()`
## always returns an ungrouped data frame and adjust accordingly.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `summarise()` has grouped output by 'Quantily'. You can override using the
## `.groups` argument.

Vẽ biểu đồ
về OrderID.
e %>%
ggplot(aes(x=OrderID)) + geom_bar(fill='violet') + labs(x= 'ID đơn hàng',y='số lượng')

Biểu đồ được tạo bởi đoạn mã R này sử dụng gói ggplot2 để tạo biểu đồ
thanh (bar chart) thể hiện số lượng đơn hàng (số lượng) theo mã đơn hàng
(OrderID).
Phân tích các yếu tố:
Trục hoành (x): Thể hiện mã đơn hàng (OrderID).
Trục tung (y): Thể hiện số lượng đơn hàng (số lượng).
Thanh (geom_bar()): Mỗi thanh thể hiện số lượng đơn hàng cho một
mã đơn hàng cụ thể.
Màu sắc (fill=‘violet’): Tô màu tím cho tất cả các
thanh.
Nhận xét:
Biểu đồ này cung cấp thông tin về số lượng đơn hàng cho từng mã
đơn hàng.
Biểu đồ thanh là lựa chọn phù hợp để thể hiện dữ liệu phân loại
như mã đơn hàng.
Việc sử dụng màu tím cho tất cả các thanh có thể giảm khả năng
phân biệt giữa các thanh.
mối quan hệ
giữa địa chỉ email (EmailID) và mã đơn hàng (OrderID).
e %>% ggplot(aes(x=EmailID, y= OrderID)) + geom_point()

Biểu đồ được tạo bởi đoạn mã R này sử dụng gói ggplot2 để tạo biểu đồ
điểm (scatter plot) thể hiện mối quan hệ giữa địa chỉ email (EmailID) và
mã đơn hàng (OrderID).
Phân tích các yếu tố:
Trục hoành (x): Thể hiện địa chỉ email (EmailID).
Trục tung (y): Thể hiện mã đơn hàng (OrderID).
Các điểm (geom_point()): Mỗi điểm đại diện cho một kết hợp giữa
địa chỉ email và mã đơn hàng.
** Biểu đồ thể hiện
mối quan hệ giữa vùng địa lý (Geography) và mã đơn hàng
(OrderID).**
e %>% ggplot(aes(x=Geography, y= OrderID)) + geom_point()

Biểu đồ được tạo bởi đoạn mã R này sử dụng gói ggplot2 để tạo biểu đồ
điểm (scatter plot). Biểu đồ thể hiện Biểu đồ được tạo bởi đoạn mã R này
sử dụng gói ggplot2 để tạo biểu đồ điểm (scatter plot). Biểu đồ thể hiện
mối quan hệ giữa vùng địa lý (Geography) và mã đơn hàng (OrderID).
Phân tích các yếu tố:
Trục hoành (x): Thể hiện các vùng địa lý (Geography).
Trục tung (y): Thể hiện mã đơn hàng (OrderID).
Các điểm (geom_point()): Mỗi điểm đại diện cho một kết hợp giữa
vùng địa lý và mã đơn hàng..
e %>% ggplot(aes(x=Geography, y= Category)) + geom_point()

Biểu đồ hiển thị các điểm dữ liệu được phân bố trên mặt phẳng với hai
trục:
Trục hoành (x): Thể hiện vùng địa lý.
Trục tung (y): Thể hiện loại hàng hóa.
Vị trí của mỗi điểm dữ liệu thể hiện sự kết hợp của vùng địa lý
và loại hàng hóa.
Kích thước và màu sắc của các điểm dữ liệu có thể được sử dụng để
biểu thị thêm thông tin (như doanh số bán hàng, số lượng khách hàng,
v.v.).
e %>% group_by(Category) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Category)) +
geom_col(Category = 'black') +
coord_polar('y') +
geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
theme_void()
## Warning in geom_col(Category = "black"): Ignoring unknown parameters:
## `Category`

Phân tích các yếu tố:
Trục hoành (góc): Không hiển thị nhãn (x = ’’), do dữ liệu được
phân bố theo các nhóm Category.
Trục tung (độ dài): Thể hiện số lượng quan sát (n) cho mỗi nhóm
Category.
Màu sắc: Tô theo biến Category (fill = Category).
Đường kẻ: Tất cả các đường kẻ có màu đen (geom_col(Category =
‘black’)).
Hệ thống tọa độ cực: Biểu đồ sử dụng hệ tọa độ cực
(coord_polar(‘y’)).
Nhãn dữ liệu: Hiển thị số lượng quan sát (n) bên ngoài biểu đồ
(geom_text).
Chủ đề nền trống: Loại bỏ các yếu tố mặc định của biểu đồ
(theme_void()).
Nhận xét:
Biểu đồ này hữu ích để so sánh tương đối số lượng quan sát giữa
các nhóm Category khác nhau.
Các nhóm Category có số lượng quan sát cao sẽ tạo thành các hình
tam giác lớn hơn trên biểu đồ.
Màu sắc của mỗi hình tam giác giúp phân biệt các nhóm
Category.
Nhãn dữ liệu cung cấp thông tin chi tiết về số lượng quan sát cho
từng nhóm.
Biểu đồ
Geography.
e %>% group_by(Geography) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Geography)) +
geom_col(Geography = 'black') +
coord_polar('y') +
geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
theme_void()
## Warning in geom_col(Geography = "black"): Ignoring unknown parameters:
## `Geography`

Phân tích và nhận xét biểu đồ
Biểu đồ bạn tạo ra sử dụng gói ggplot2 để thể hiện số lượng quan
sát theo khu vực địa lý (Geography) trong tập dữ liệu e. Biểu đồ dạng đa
giác cực (radar chart) với các trục sau:
Trục hoành (góc): Không hiển thị nhãn (x = ’’), do dữ liệu được
phân bố theo các nhóm khu vực địa lý.
Trục tung (độ dài): Thể hiện số lượng quan sát (n) cho mỗi khu
vực địa lý.
Màu sắc: Tô theo biến Geography (fill = Geography).
Đường kẻ: Tất cả các đường kẻ có màu đen (geom_col(Geography =
‘black’)).
Các yếu tố khác:
Hệ thống tọa độ cực (coord_polar(‘y’)): Biểu đồ sử dụng hệ tọa độ
cực, với các trục tỏa ra từ tâm.
Nhãn dữ liệu (geom_text): Thêm nhãn dữ liệu hiển thị số lượng
quan sát (n) bên ngoài biểu đồ, được căn chỉnh theo vị trí chồng chất
(position_stack(vjust = .5)).
Chủ đề nền trống (theme_void()): Loại bỏ các yếu tố mặc định của
biểu đồ, chỉ giữ lại các thành phần cần thiết.
Nhận xét:
Biểu đồ này hữu ích để so sánh tương đối số lượng quan sát giữa
các khu vực địa lý khác nhau.
Các khu vực có số lượng quan sát cao sẽ tạo thành các hình tam
giác lớn hơn trên biểu đồ.
Màu sắc của mỗi hình tam giác giúp phân biệt các khu vực địa
lý.
Nhãn dữ liệu hiển thị bên ngoài biểu đồ cung cấp thông tin chi
tiết về số lượng quan sát cho từng khu vực.
Vẽ biểu đồ dạng
density kết hợp 2 biến Sales và Profit.**
ggplot(data = e) +
geom_density(aes(x = Sales, fill = "Doanh số"), color = "lightblue") +
geom_density(aes(x = Profit, fill = "Lợi nhuận"), color = "lightgreen") +
labs(x = "Giá trị", y = "Mật độ")

- Hình dạng phân bố:
+Phân bố của Sales có thể là đối xứng hoặc léch (tùy thuộc vào dữ
liệu cụ thể).
+Phân bố của Profit cũng có thể là đối xứng hoặc lệch, và có thể khác
với phân bố của Sales.
- Mức độ tập trung:
+Mức độ tập trung của Sales và Profit được thể hiện qua độ cao của
đường cong mật độ.
+Biểu đồ mật độ cao cho thấy dữ liệu tập trung quanh một giá trị nhất
định.
+Biểu đồ mật độ thấp cho thấy dữ liệu phân tán rộng hơn.
- So sánh hai biến:
+So sánh vị trí đỉnh của hai đường cong mật độ để xem biến nào có giá
trị trung bình cao hơn.
+So sánh độ rộng của hai đường cong mật độ để xem biến nào có độ biến
thiên cao hơn.
- Mối quan hệ giữa hai biến:
+Biểu đồ mật độ có thể giúp bạn xác định mối quan hệ giữa Sales và
Profit.
+Nếu hai đường cong mật độ chồng lên nhau, có thể có mối tương quan
cao giữa hai biến.
+Nếu hai đường cong mật độ tách biệt, có thể có ít hoặc không có mối
tương quan giữa hai biến.
e %>% ggplot(aes(x = OrderDate, y = ShipDate, color = Category)) +
geom_line() +
geom_point(size=2) +
transition_reveal(Sales, keep_last = F)

- Biểu đồ động được tạo ra bởi đoạn mã R sử dụng gói ggplot2 và hiệu
ứng chuyển tiếp transition_reveal để thể hiện mối quan hệ giữa ngày đặt
hàng (OrderDate), ngày giao hàng (ShipDate), loại hàng hóa (Category) và
doanh số bán hàng (Sales). Biểu đồ này cung cấp nhiều thông tin hữu
ích:
- Xu hướng:
Biểu đồ thể hiện xu hướng chung của thời gian giao hàng
(ShipDate) tăng dần theo thời gian đặt hàng (OrderDate).
Xu hướng này có thể khác nhau cho từng loại hàng hóa (Category),
được phân biệt bởi màu sắc của các đường kẻ và điểm.
- So sánh:
- Biến động:
- Hiệu ứng chuyển tiếp:
Hiệu ứng transition_reveal giúp tập trung vào các điểm dữ liệu và
đường kẻ có doanh số bán hàng cao hơn.
Điều này giúp người xem dễ dàng nhận diện những sản phẩm có hiệu
quả kinh doanh tốt nhất. Nhận xét chung:
Biểu đồ động này là một công cụ hữu ích để phân tích mối quan hệ
giữa các biến OrderDate, ShipDate, Category và Sales.
Biểu đồ cung cấp thông tin về xu hướng, so sánh, biến động và
doanh số bán hàng.
Hiệu ứng chuyển tiếp giúp tăng cường khả năng trực quan và tập
trung vào thông tin quan trọng.
e %>% ggplot(aes(x = OrderDate, y = Profit, color = Category)) +
geom_line() +
geom_point(size=2) +
transition_reveal(Sales, keep_last = F)

e %>% ggplot(aes(x = OrderDate, y = Sales, color = Category)) +
geom_line() +
geom_point(size=2) +
transition_reveal(Sales, keep_last = F)

Nhận xét:
Biểu đồ này có thể giúp bạn phân tích xu hướng theo thời gian của
doanh số bán hàng theo các phân loại (Category) khác nhau.
Xu hướng: Biểu đồ đường (geom_line) cho thấy xu hướng tổng thể
của doanh số bán hàng theo thời gian (OrderDate) cho mỗi phân loại. Bạn
có thể quan sát xem doanh số tăng, giảm hay ổn định theo thời
gian.
Sự khác biệt giữa các phân loại: Màu sắc khác nhau giúp phân biệt
doanh số theo từng phân loại. Do đó, bạn có thể dễ dàng so sánh xem hiệu
suất bán hàng của các phân loại khác nhau như thế nào theo thời
gian.
Biến động chi tiết: Các điểm dữ liệu (geom_point) cho phép bạn
xem xét các biến động chi tiết của doanh số tại từng thời điểm cụ thể.
Bạn có thể thấy có những thời điểm doanh số tăng đột biến hoặc giảm mạnh
đối với một hoặc nhiều phân loại.
Hiệu ứng hoạt ảnh (tùy chọn): Tùy chọn transition_reveal (nếu
được bật) sẽ tạo hiệu ứng hoạt ảnh để hiển thị dữ liệu theo thời gian.
Điều này có thể hữu ích để trực quan hóa thứ tự xuất hiện của dữ liệu và
theo dõi các mẫu theo thời gian
LS0tDQp0aXRsZTogIm52NSINCmF1dGhvcjogInBubWluaGNoYXUiDQpkYXRlOiAiMjAyNC0wMy0wNyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdG9jOiB0cnVlDQogICAgbnVtYmVyIHNlY3Rpb246IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoY2xhc3Muc291cmNlPSJudW1iZXJMaW5lcyBsaW5lQW5jaG9ycyIpDQpgYGANCg0KImByIGZvcm1hdChTeXMudGltZSgpLCclSDolTTolUywgJWQgLSAlbSAtICVZJylgIiAgDQoqKioNCg0KDQojICoqR2nhu5tpIHRoaeG7h3UgYuG7mSBk4buvIGxp4buHdS4qKiANCg0KIyMgKipHaeG7m2kgdGhp4buHdSB24buBIHThuq1wIGThu68gbGnhu4d1OioqDQpE4buvIGxp4buHdSBbQW1hem9uIDJfUmF3XSh3d3cucnR1ZGlvLmNvbSkgbMOgIERvYW5oIHPhu5EgYsOhbiBz4bqjbiBwaOG6qW0gY+G7p2EgQW1hem9uIHThu6sgxJHhuqd1IG7Eg20gMjAxMSDEkeG6v24gY3Xhu5FpIG7Eg20gMjAxNC4gQuG7mSBk4buvIGxp4buHdSB24buBIGLDoW4gaMOgbmcgdHLDqm4gQW1hem9uIG7DoHkgY2jhu6lhIDMyMDQgaMOgbmcgdsOgIDkgY+G7mXQuICAgDQoNCk3DtCB04bqjIGPhu5l0OiAgICANCg0KKiAqKk9yZGVyIElEKiogLSBNw6MgxJHGoW4gaMOgbmcuICANCg0KKiAqKk9yZGVyIERhdGUqKiAtIE5nw6B5IMSR4bq3dCBow6BuZy4gIA0KDQoqICoqU2hpcCBEYXRlKiogLSBOZ8OgeSB24bqtbiBjaHV54buDbi4gIA0KDQoqICoqRW1haWxfSUQqKiAtIEVtYWlsX0lEIGPhu6dhIG5nxrDhu51pIGTDuW5nICANCg0KKiAqKkdlb2dyYXBoeSoqIC0gVuG7iyB0csOtIMSR4bq3dCBow6BuZyBj4bunYSBuZ8aw4budaSBkw7luZy4gIA0KDQoqICoqQ2F0ZWdvcnkqKiAtIERhbmggbeG7pWMgc+G6o24gcGjhuqltICANCg0KKiAqKlByb2R1Y3QgTmFtZSoqIOKAkyBUw6puIHPhuqNuIHBo4bqpbSBj4bunYSBBbWF6b24gIA0KDQoqICoqU2FsZXMqKiAtIERvYW5oIHPhu5EgYsOhbiBz4bqjbiBwaOG6qW0gQW1hem9uICANCg0KKiAqKlF1YW50aWx5KiogLSBjw7MgYmFvIG5oacOqdSDEkcahbiB24buLIGPhu6dhIG3hu5l0IHPhuqNuIHBo4bqpbSBj4bulIHRo4buDIGPDsyBz4bq1bi4gIA0KDQoqICoqUHJvZml0KiogLSBM4bujaSBuaHXhuq1uIGLDoW4gaMOgbmcgdHLDqm4gQW1hem9uICANCg0KR8OhbiB0w6puICoqZSoqIGNobyBi4buZIGThu68gbGnhu4d1ICoqQW1hem9uIDJfUmF3KiouICANCg0KYGBge3IsZWNobz1UUlVFfQ0KbGlicmFyeShEVCkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHhsc3gpDQplIDwtIHJlYWQueGxzeCgiRjovUi9kYXRhMS9BbWF6b24gMl9SYXcueGxzeCIsIHNoZWV0SW5kZXg9IDEsIGhlYWRlcj0gVCkNCg0KbmFtZXMoZSkgPC0gYygnT3JkZXJJRCcsJ09yZGVyRGF0ZScsJ1NoaXBEYXRlJywnRW1haWxJRCcsJ0dlb2dyYXBoeScsJ0NhdGVnb3J5JywnUHJvZHVjdE5hbWUnLCdTYWxlcycsJ1F1YW50aWx5JywnUHJvZml0JykNCmRhdGF0YWJsZShlKQ0KYGBgDQoNCiogQuG6o25nIHRyw6puIGzDoCBi4buZIGThu68gbGnhu4d1ICoqZSoqLCDEkcaw4bujYyBjaGlhIHRow6BuaCAzMjEgYuG6o25nIMSR4buDIGThu4UgcXVhbiBzw6F0IGjGoW4sIG3hu5dpIGLhuqNuZyAxMCBxdWFuIHPDoXQsIGLhuqNuZyAzMjEgY2jhu6lhIDMgcXVhbiBzw6F0LiAgDQoNCiAgKyBN4buXaSBt4buZdCBxdWFuIHPDoXQgdHJvbmcgYuG7mSBk4buvIGxp4buHdSBsw6AgbeG7mXQgc+G6o24gcGjhuqltIMSRxrDhu6NjIGLDoW4gcmEgY+G7p2EgQW1hem9uIHRyb25nIGdpYWkgxJFv4bqhbiDEkeG6p3UgMjAxMSDEkeG6v24gY3Xhu5FpIDIwMTQuICANCiAgDQogIA0KIyMgKipRdWFuIHPDoXQgYuG7mSBk4buvIGxp4buHdS4qKiAgDQoNClPhu60gZOG7pW5nIGPDonUgbOG7h25oICoqc2tpbSoqIHRodeG7mWMgcGFja2FnZSBza2ltciBxdWFuIHPDoXQgdOG7lW5nIHF1YW4gYuG7mSBk4buvIGxp4buHdSB0csOqbjogIA0KDQpgYGB7cixlY2hvPVRSVUV9DQpsaWJyYXJ5KHNraW1yKQ0Kc2tpbShlKQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KiogICANCiAgDQoqICoqTcOjIMSRxqFuIGjDoG5nIChPcmRlciBJRCkqKiBsw6AgbeG7mXQgY2h14buXaSBz4buRLCBrw70gdOG7sSBob+G6t2Mga+G6v3QgaOG7o3AgY+G6oyBoYWksIMSRxrDhu6NjIHThuqFvIHJhIMSR4buDIMSR4buLbmggZGFuaCB2w6AgdGhlbyBkw7VpIG3hu5l0IMSRxqFuIGjDoG5nIGPhu6UgdGjhu4MgdHJvbmcgaOG7hyB0aOG7kW5nIMSR4bq3dCBow6BuZyBj4bunYSBt4buZdCBjw7RuZyB0eS4gTeG7l2kgxJHGoW4gaMOgbmcgxJHGsOG7o2MgZ8OhbiBt4buZdCBtw6MgxJHGoW4gaMOgbmcgZHV5IG5o4bqldCDEkeG7gyBuw7MgY8OzIHRo4buDIMSRxrDhu6NjIGThu4UgZMOgbmcgeMOhYyDEkeG7i25oIHbDoCBxdeG6o24gbMO9LiAgDQogIA0KICAgICsgQW1hem9uICoqa2jDtG5nIGPDtG5nIGLhu5EqKiB0aMO0bmcgdGluIGNoaSB0aeG6v3QgduG7gSBjw6FjaCBo4buNIHThuqFvIHbDoCBxdeG6o24gbMO9IG3DoyDEkcahbiBow6BuZyAoT3JkZXIgSUQpLiBDw7RuZyB0eSBnaeG7ryB0aMO0bmcgdGluIG7DoHkgbMOgIGLDrSBt4bqtdCB2w6Aga2jDtG5nIGNoaWEgc+G6uyBjw7RuZyBraGFpIHbDrCBuaGnhu4F1IGzDvSBkbyBsacOqbiBxdWFuIMSR4bq/biBi4bqjbyBt4bqtdCB2w6AgcXV54buBbiByacOqbmcgdMawLiBUaOG6vyBuw6puIHLhuqV0IMSR4buDIHjDoWMgxJHhu4tuaCBjaMOtbmggeMOhYyB0aMOgbmggcGjhuqduIHRyb25nIG3DoyAqKm9yZGVyIElEKiogdHJvbmcgYuG7mSBk4buvIGxp4buHdS4gIA0KICAgIA0KICAgICsgVHV5IG5oacOqbiwgdGEgY8OzIHRo4buDIHBow6JuIGJp4buHdCBoYWkgdGjDoG5oIHBo4bqnbiBzYXUgY8O5bmcgY+G7p2Egb3JkZXIgSUQuIFRow6BuaCBwaOG6p24gdGjhu6kgaGFpIGzDoCBuxINtIGPhu6dhIMSRxqFuIGjDoG5nIHbDoCB0aOG7qSBiYSBjw7MgdGjhu4MgxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQgKipz4buRIGR1eSBuaOG6pXQgaG/hurdjIMSR4buLbmgqKiBkYW5oIGPhu6UgdGjhu4MgY+G7p2EgxJHGoW4gaMOgbmcgxJHDsyB0cm9uZyBo4buHIHRo4buRbmcgcXXhuqNuIGzDvSBj4bunYSBBbWF6b24uIFPhu5EgbsOgeSB0aMaw4budbmcgxJHGsOG7o2MgdOG6oW8gcmEgxJHhu4MgxJHhuqNtIGLhuqNvIHTDrW5oIGR1eSBuaOG6pXQgY+G7p2EgbeG7l2kgxJHGoW4gaMOgbmcgdsOgIGdpw7pwIHF14bqjbiBsw70gY2jDum5nIGhp4buHdSBxdeG6oy4gIA0KICAgIA0KKiBOaMOsbiB2w6BvICoqb3JkZXIgZGF0ZSoqIHbDoCAqKnNoaXAgZGF0ZSoqLCB0YSB0aOG6pXkgYuG7mSBk4buvIGxp4buHdSBuw6B5IHRodSB0aOG6rXAgdsOgbyBnaWFpIMSRb+G6oW4gbsSDbSAqKjIwMTEtMjAxNCoqLiAgICAgIA0KDQoqIFRp4bq/cCB0aGVvIGzDoCAqKnThu6kgcGjDom4gduG7izsgdHJ1bmcgYsOsbmgsIGzhu5tuIG5o4bqldCB2w6Agbmjhu48gbmjhuqV0KiogY+G7p2EgKipTYWxlcywgUXVhbnRpbHksIFByb2ZpdC4qKiAgDQoNCiogxJDhu5FpIHbhu5tpICoqU2FsZXMqKjogIA0KDQogICsgKipHacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIFNhbGVzIChtZWFuKSoqIGzDoCAqKjIyNi40OSoqLCB0cnVuZyB0w6JtIGThu68gbGnhu4d1ICjEkWnhu4NtIGNow61uaCBnaeG7r2EpIGPhu6dhIFNhbGVzLiAgIA0KICANCiAgKyAqKkdpw6EgdHLhu4sgbmjhu48gbmjhuqV0IGPhu6dhIFNhbGVzIChwMCkqKiBsw6AgKiowLjk5KiosIGPDsyBuZ2jEqWEgbMOgIGtow7RuZyBjw7JuIMSRxqFuIGjDoG5nIG7DoG8gY8OzIGRvYW5oIHPhu5EgYsOhbiBow6BuZyAgbmjhu48gaMahbiAwLjk5LiAgDQogIA0KICArICoqR2nDoSB0cuG7iyBs4bubbiBuaOG6pXQgY+G7p2EgU2FsZXMgKHAxMDApKiogbMOgICoqMTM5OTkuOSoqLCBjw7MgbmdoxKlhIGzDoCBraMO0bmcgY8OybiDEkcahbiBow6BuZyBuw6BvIGPDsyBkb2FuaCBz4buRIGLDoW4gaMOgbmcgbOG7m24gaMahbiAxMzk5OS45LiAgIA0KICANCiAgKyAqKlBow6JuIHbhu4sgcDI1KiogOiBjw7MgMjUlIHPhu5EgcXVhbiBzw6F0IGPDsyBkb2FuaCBz4buRIGLDoW4gaMOgbmcgbmjhu48gaMahbiAqKjE5LjQ0KiouICANCiAgDQogICsgKipQaMOibiB24buLIHA1MCoqIDpDw7MgbmdoxKlhIGzDoCBjw7MgNTAlIHPhu5EgcXVhbiBzw6F0IGPDsyBkb2FuaCBz4buRIGLDoW4gaMOgbmcgbmjhu48gaMahbiAqKjYwLjg0KiogdsOgIDUwJSBjw7JuIGzhuqFpIGzhu5tuIGjGoW4uICAgIA0KICANCiAgKyAqKlBow6JuIHbhu4sgcDc1KiogOiBjw7MgNzUlIHF1YW4gc8OhdCBjw7MgZG9hbmggc+G7kSBiw6FuIGjDoG5nIG5o4buPIGjGoW4gKioyMTUuODEqKiwgMjUlIGPDsm4gbOG6oWkgdGjDrCBs4bubbiBoxqFuIGNvbiBz4buRIG7DoHkuICANCg0KIyAqKk5naGnDqm4gY+G7qXUgZG9hbmggc+G7kSBiw6FuIGjDoG5nIGPhu6dhIEFtYXpvbiB0cm9uZyBnaWFpIMSRb+G6oW4gMjAxMSAtIDIwMTQuKioNCg0KIyMgKipCaeG7g3UgxJHhu5MgbcO0IHThuqMgU2FsZXMuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KZSAlPiUgZ2dwbG90KGFlcyh4ID0gU2FsZXMpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNTAwLCBmaWxsID0gJ2JsdWUnLCBjb2xvciA9ICdyZWQnKQ0KIA0KDQpgYGANCg0KDQoqIE5o4bqtbiB4w6l0OiAgDQoNCiAgKyBN4bupYyBkb2FuaCBz4buRIGLDoW4gaMOgbmcgdGjhuqVwIHThu6sgMTUwMCB0cuG7nyB4deG7kW5nICoqY2hp4bq/bSBz4buRIGzGsOG7o25nIGzhu5tuKiouIEPDsyB0aOG7gyBuw7NpIG3hu6ljIGRvYW5oIHPhu5EgdGjhuqVwIGNoaeG6v20gxJFhIHBo4bqnbi4gIA0KICANCiAgKyDEkOG7k25nIG5naMSpYSB24bubaSB2aeG7h2MgZ2nDoSB0cuG7iyBTYWxlcyBjw6BuZyBs4bubbiB0aMOsIHPhu5EgbMaw4bujbmcgYsOhbiByYSBjw6BuZyBuaOG7jy4gICANCiAgDQogICsgTmjDrG4gY2h1bmcsIERvYW5oIG5naGnhu4dwIG7Dqm4gY2jDuiB0cuG7jW5nIGPDoWMgbeG6t3QgaMOgbmcgZ2nDoSB0aOG6pXAgxJHGsOG7o2MgbXVhIHbhu5tpIHPhu5EgbMaw4bujbmcgbmhp4buBdSwgYsOqbiBj4bqhbmggxJHDsyDEkeG6qXkgbmhhbmggcXXDoSB0csOsbmggdGh1IGjDunQga2jDoWNoIGjDoG5nIGdpw6BuaCBjaG8gbeG6t3QgaMOgbmcgY2FvIGPhuqVwLiAgDQoNCiAgDQojIyAqKkJp4buDdSDEkeG7kyB0aGVvIFNhbGVzIHbDoCBDYXRlZ29yeS4qKiAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCmUgJT4lIGdncGxvdChhZXMoeCA9IFNhbGVzLCBmaWxsID0gQ2F0ZWdvcnkpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNTAwKQ0KYGBgDQoNCiogTmjhuq1uIHjDqXQ6ICANCiAgIA0KICArIFRy4bulYyB4IGPhu6dhIGJp4buDdSDEkeG7kyBoaeG7g24gdGjhu4sgY8OhYyBnacOhIHRy4buLIGPhu6dhIGJp4bq/biBTYWxlcy4gIA0KICANCiAgKyBDaGnhu4F1IGNhbyBj4bunYSBt4buXaSB0aGFuaCBiaeG7g3UgdGjhu4sgdOG6p24gc3XhuqV0IHh14bqldCBoaeG7h24gY+G7p2EgY8OhYyBnacOhIHRy4buLIFNhbGVzIHRyb25nIG3hu5l0IGtob+G6o25nIGdpw6EgdHLhu4sgbmjhuqV0IMSR4buLbmggKMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBi4bufaSBiaW53aWR0aCkuICANCg0KICArIE3DoHUgc+G6r2MgY+G7p2EgY8OhYyB0aGFuaCBiaeG7g3UgdGjhu4sgY8OhYyBkYW5oIG3hu6VjIGtow6FjIG5oYXUgdHJvbmcgYmnhur9uIENhdGVnb3J5LiAgDQogIA0KICArIFNvIHPDoW5oIMSR4buZIGNhbyBj4bunYSBjw6FjIHRoYW5oIHRyb25nIGPDuW5nIG3hu5l0IGRhbmggbeG7pWMgY2hvIHBow6lwIGLhuqFuIHhlbSB04bqnbiBzdeG6pXQgeHXhuqV0IGhp4buHbiBj4bunYSBjw6FjIGdpw6EgdHLhu4sgU2FsZXMgdHJvbmcgY8OhYyBkYW5oIG3hu6VjIGtow6FjIG5oYXUuICAgIA0KIA0KICArIEJp4buDdSDEkeG7kyB0csOqbiB0aOG7gyBoaeG7h24gbeG7qWMgYsOhbiByYSBj4bunYSBjw6FjIGRvYW5oIG3hu6VjIHPhuqNuIHBo4bqpbSwgbeG7l2kgbeG7mXQgZGFuaCBt4bulYyDEkeG7gXUgdMawxqFuZyDhu6luZyB24bubaSBnacOhIHRy4buLIFNhbGVzLiAgDQogIA0KICArIEPDsyB04bqldCBj4bqjICoqMTcgZGFuaCBt4bulYyoqLCDEkcaw4bujYyBjaMO6IHRow61jaCB0aGVvIHRo4bupIHThu7EgY2jhu68gY8OhaSBiw6puIGPhuqFuaCBi4bqjbiDEkeG7ky4gIA0KICANCiAgK05ow6xuIHbDoG8gYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSDEkcaw4bujYyBkYW5oIG3hu6VjICoqQWNjZXNzb3JpZXMqKiDEkcaw4bujYyBiw6FuIGNo4bqheSBuaOG6pXQsIMSR4bqhdCBt4buRYyAyNTAwIHRyw6puIGJp4buDdSDEkeG7ky4gIA0KICANCiMjICoqQmnhu4N1IMSR4buTIHF1YW4gc8OhdCBQcm9maXQuKiogIA0KDQpgYGB7cixlY2hvPVRSVUV9DQplJHAxIDwtIGNhc2Vfd2hlbihlJFByb2ZpdCA8PSA1MCB+J3LhuqV0IG5o4buPJywgZSRQcm9maXQgPj0gNTAgJiBlJFByb2ZpdCA8PSAxMDAgfiAnduG7q2EnLCBlJFByb2ZpdCA+PSAxMDAgfiAnbOG7m24nKQ0KZSAlPiUgZ2dwbG90KGFlcyh4ID0gcDEpKSArDQogIGdlb21fYmFyKGZpbGw9J3B1cnBsZScpICsgbGFicyh4PSdM4bujaSBuaHXhuq1uIGLDoW4gaMOgbmcnLCB5PSAnc+G7kSBsxrDhu6NuZycpIA0KYGBgDQoNCiogxJDhu4MgY8OzIHRo4buDIHhlbSB4w6l0IGThu68gbGnhu4d1IHRy4buxYyBxdWFuIGjGoW4sIHRhIGNoaWEgbmjhu48gYmnhur9uICoqUHJvZml0KiogdGjDoG5oIDMgbmjDs20gKiogcuG6pXQgbmjhu48sIHbhu6thLCBs4bubbioqIGLhurFuZyBsw6puIGNhc2Vfd2hlbiB2w6AgZ8OhbiB0w6puICoqcDEqKiAgDQoNCiogTmjhuq1uIHjDqXQ6ICANCg0KICAr4bueIGJp4bq/biBs4bujaSBuaHXhuq1uIGLDoW4gaMOgbmcgbsOgeSwgbmjDs20gcuG6pXQgbmjhu48gY2hp4bq/bSAqKnBo4bqnbiBs4bubbioqLiAgDQogIA0KICArIFRyxrDhu5tjIMSRw7MgY2jDum5nIHRhIMSRw6MgY8OzIHRo4buDICoqZOG7sSDEkW/DoW4gxJHGsOG7o2MgbOG7o2kgbmjhuq1uKiogYsOhbiBow6BuZyB0aHXhu5FjIG5ow7NtIHLhuqV0IG5o4buPIHPhur0gY2hp4bq/bSBwaOG6p24gbOG7m24uIFBo4bqnbiBs4bubbiBjw6FjICoqxJHGoW4gxJHhurd0IGjDoG5nIMSRxrDhu6NjIGLDoW4gcmEgxJHhu4F1IGPDsyBnacOhIHRy4buLIHRo4bqlcCoqLCB0aOG6vyBuw6puIGzhu6NpIG5o4bqtbiBjxaluZyB0aOG6pXAgdGhlby4gIA0KICANCiAgKyBUdXkgbmhpw6puLCBu4bq/dSB4w6l0IHThu5VuZyB0aOG7gyB0aMOsIG3hu6ljIGRvYW5oIHRodSB2w6AgbOG7o2kgbmh14bqtbiDEkeG7gXUgcuG6pXQgY2FvLCBi4bufaSB2w6wgbeG6t2MgZMO5IGdpw6EgdHLhu4sgdGjhuqVwIG5oxrBuZyBs4bqhaSBjw7MgcuG6pXQgbmhp4buBdSDEkcahbiBow6BuZy4gTOG6pXkgc+G7kSBsxrDhu6NuZyBiw7kgY2jhuqV0IGzGsOG7o25nLiAgDQogIA0KICANCg0KIyMgKipCaeG7g3UgxJHhu5MgcXVhbiBzw6F0IFByb2ZpdCB2w6AgU2FsZXMuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KZSAlPiUgZ2dwbG90KGFlcyh4PSBQcm9maXQsIHk9IFNhbGVzKSkgKyBnZW9tX3BvaW50KCkgKw0KIHhsYWIoJ0zhu6NpIG5odeG6rW4nKSArDQp5bGFiKCdEb2FuaCBz4buRJykNCmBgYA0KDQoqIE5o4bqtbiB4w6l0OiAgDQogIA0KICArIE5ow6xuIHF1YSBiaeG7g3UgxJHhu5MsIHRhIHRo4bqleSBz4buxIHTEg25nIHRyxrDhu59uZyBj4bunYSBTYWxlcyB2w6AgUHJvZml0IGPDsyBz4buxIHF1YW4gaOG7hyBt4bq3dCB0aGnhur90IHbhu5tpIG5oYXUuICANCiAgDQogICsgTeG7kWkgdMawxqFuZyBxdWFuOiBCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSBt4buRaSB0xrDGoW5nIHF1YW4gZ2nhu69hIEzhu6NpIG5odeG6rW4gdsOgIERvYW5oIHPhu5EuICANCiAgDQogICsgICoqTeG7kWkgdMawxqFuZyBxdWFuIGTGsMahbmcqKjogTuG6v3UgY8OhYyDEkWnhu4NtIGPDsyB4dSBoxrDhu5tuZyBkaSBjaHV54buDbiB04burIGTGsOG7m2kgbMOqbiB0csOqbiB2w6AgdOG7qyB0csOhaSBzYW5nIHBo4bqjaSwgY8OzIHRo4buDIGNobyB0aOG6pXkgbeG7kWkgdMawxqFuZyBxdWFuIGTGsMahbmcgZ2nhu69hIGhhaSBiaeG6v24uIMSQaeG7gXUgbsOgeSBjw7MgbmdoxKlhIGzDoCBraGkgTOG7o2kgbmh14bqtbiB0xINuZywgRG9hbmggc+G7kSBjxaluZyBjw7MgeHUgaMaw4bubbmcgdMSDbmcuICANCiAgDQogICsgICoqTeG7kWkgdMawxqFuZyBxdWFuIMOibSoqOiBO4bq/dSBjw6FjIMSRaeG7g20gY8OzIHh1IGjGsOG7m25nIGRpIGNodXnhu4NuIHThu6sgdHLDqm4geHXhu5FuZyBkxrDhu5tpIHbDoCB04burIHRyw6FpIHNhbmcgcGjhuqNpLCBjw7MgdGjhu4MgY2hvIHRo4bqleSBt4buRaSB0xrDGoW5nIHF1YW4gw6JtIGdp4buvYSBoYWkgYmnhur9uLiDEkGnhu4F1IG7DoHkgY8OzIG5naMSpYSBsw6Aga2hpIEzhu6NpIG5odeG6rW4gdMSDbmcsIERvYW5oIHPhu5EgY8OzIHh1IGjGsOG7m25nIGdp4bqjbS4gIA0KICANCiAgKyAqKktow7RuZyBjw7MgbeG7kWkgdMawxqFuZyBxdWFuKio6IE7hur91IGPDoWMgxJFp4buDbSBwaMOibiBi4buRIG5n4bqrdSBuaGnDqm4gdHLDqm4gYmnhu4N1IMSR4buTLCBjw7MgdGjhu4MgY2hvIHRo4bqleSBraMO0bmcgY8OzIG3hu5FpIHTGsMahbmcgcXVhbiByw7UgcsOgbmcgZ2nhu69hIGhhaSBiaeG6v24uICANCiAgDQogICtN4bupYyDEkeG7mSB04bqtcCB0cnVuZzogIA0KICANCiAgK03huq10IMSR4buZIGNhbzogTuG6v3UgY8OhYyDEkWnhu4NtIHThuq1wIHRydW5nIGTDoHkgxJHhurdjIHRyb25nIG3hu5l0IGtodSB24buxYywgY8OzIHRo4buDIGNobyB0aOG6pXkgbeG7kWkgbGnDqm4gaOG7hyBt4bqhbmggbeG6vSBnaeG7r2EgaGFpIGJp4bq/bi4gIA0KICANCiAgK03huq10IMSR4buZIHRo4bqlcDogTuG6v3UgY8OhYyDEkWnhu4NtIHBow6JuIGLhu5EgcuG6o2kgcsOhYyB0csOqbiBiaeG7g3UgxJHhu5MsIGPDsyB0aOG7gyBjaG8gdGjhuqV5IG3hu5FpIGxpw6puIGjhu4cgeeG6v3UgaG/hurdjIGtow7RuZyBjw7MgbeG7kWkgbGnDqm4gaOG7hyBnaeG7r2EgaGFpIGJp4bq/biAgDQogIA0KICANCiAgDQoNCiMjICoqQmnhu4N1IMSR4buTIHF1YW4gc8OhdCBs4bujaSBuaOG6rW4gYsOhbiBow6BuZyB0aGVvIHThu6tuZyBuxINtLioqDQoNCmBgYHtyLGVjaG89VFJVRX0gDQpsaWJyYXJ5KGdncGxvdDIpDQplJHMgPC0geWVhcihlJE9yZGVyRGF0ZSkNCnRhYmxlIChlJHMpDQplICU+JSBncm91cF9ieShQcm9maXQscykgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9cyx5PW4pKSArIGdlb21fY29sKGZpbGw9J3BpbmsnKSArDQogIGdlb21fdGV4dChhZXMobGFiZWw9cm91bmQobiwyKSksdmp1c3Q9MiwgY29sb3I9J2JsYWNrJykNCmBgYA0KDQoNCiogTmjhuq1uIHjDqXQ6ICANCg0KICArIGxpYnJhcnkoZ2dwbG90Mik6IETDsm5nIGNvZGUgbsOgeSB04bqjaSB0aMawIHZp4buHbiBnZ3Bsb3QyIGPhuqduIHRoaeG6v3QgxJHhu4MgdOG6oW8gYmnhu4N1IMSR4buTLg0KZSRzIDwtIHllYXIoZSRPcmRlckRhdGUpOiBEw7JuZyBuw6B5IHThuqFvIG3hu5l0IGPhu5l0IG3hu5tpIHTDqm4gcyB0cm9uZyBk4buvIGxp4buHdSBlIGLhurFuZyBjw6FjaCB0csOtY2ggeHXhuqV0IG7Eg20gdOG7qyBj4buZdCBPcmRlckRhdGUuICANCg0KICArIELhuqNuZyB04bqnbiBzdeG6pXQgdGhlbyBuxINtICANCg0KICArIHRhYmxlKGUkcyk6IETDsm5nIG7DoHkgaW4gcmEgYuG6o25nIHThuqduIHN14bqldCBj4bunYSBjw6FjIGdpw6EgdHLhu4sgdHJvbmcgY+G7mXQgcywgY2hvIGJp4bq/dCBz4buRIGzhuqduIHh14bqldCBoaeG7h24gY+G7p2EgbeG7l2kgbsSDbSB0cm9uZyBk4buvIGxp4buHdS4gQuG6o25nIG7DoHkgaOG7r3Ugw61jaCDEkeG7gyBraeG7g20gdHJhIHPhu7EgcGjDom4gYuG7kSBk4buvIGxp4buHdSB0aGVvIG7Eg20uICANCiAgDQogICsgTmjDs20gZOG7ryBsaeG7h3UgdGhlbyBM4bujaSBuaHXhuq1uIHbDoCBOxINtDQoNCiAgKyBlICU+JSBncm91cF9ieShQcm9maXQsIHMpICU+JSBzdW1tYXJpc2UobiA9IG4oKSk6IETDsm5nIG7DoHkgc+G7rSBk4bulbmcgZHBseXIgxJHhu4MgbmjDs20gZOG7ryBsaeG7h3UgdGhlbyBjw6FjIGPhurdwIFByb2ZpdCAobOG7o2kgbmh14bqtbikgdsOgIHMgKG7Eg20pLiBIw6BtIHN1bW1hcmlzZSB0w61uaCB04buVbmcgc+G7kSBs4bqnbiB4deG6pXQgaGnhu4duIChz4buRIGzGsOG7o25nKSBj4bunYSBt4buXaSBuaMOzbSwgbMawdSB0cuG7ryB0cm9uZyBiaeG6v24gbi4gIA0KICANCiAgKyBU4bqhbyBiaeG7g3UgxJHhu5MgIA0KDQogICsgZ2dwbG90KGFlcyh4ID0gcywgeSA9IG4pKTogRMOybmcgbsOgeSB0aGnhur90IGzhuq1wIG7hu4FuIHThuqNuZyBjaG8gYmnhu4N1IMSR4buTIGLhurFuZyBjw6FjaCB4w6FjIMSR4buLbmggdHLhu6VjIGhvw6BuaCAoeCkgbMOgIG7Eg20gKHMpIHbDoCB0cuG7pWMgdHVuZyAoeSkgbMOgIHPhu5EgbMaw4bujbmcgKG4pLiAgDQogIA0KICArIGdlb21fY29sKGZpbGw9J3BpbmsnKTogRMOybmcgbsOgeSB04bqhbyBiaeG7g3UgxJHhu5MgaMOsbmggY+G7mXQsIHbhu5tpIG3DoHUgc+G6r2MgxJHGsOG7o2MgdMO0IGzDoCBo4buTbmcgKGZpbGw9J3BpbmsnKS4gIA0KICANCiAgKyBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobiwgMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ2JsYWNrJyk6IETDsm5nIG7DoHkgdGjDqm0gbmjDo24gY2hvIGPDoWMgY+G7mXQsIGhp4buDbiB0aOG7iyBnacOhIHRy4buLIG4gxJHGsOG7o2MgbMOgbSB0csOybiDEkeG6v24gaGFpIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuIChyb3VuZChuLCAyKSkuIFbhu4sgdHLDrSBj4bunYSBuaMOjbiDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggdGhlbyB0cuG7pWMgdHVuZyAodmp1c3QgPSAyKSB2w6AgbcOgdSBz4bqvYyBuaMOjbiBsw6AgxJFlbiAoY29sb3IgPSAnYmxhY2snKS4gIA0KICANCiAgKyBHaeG6o2kgdGjDrWNoIGJp4buDdSDEkeG7kyAgDQoNCiAgKyBCaeG7g3UgxJHhu5MgbsOgeSB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyB0aGVvIG7Eg20gKG4pIMSRxrDhu6NjIHBow6JuIG5ow7NtIHRoZW8gbOG7o2kgbmh14bqtbiAoUHJvZml0KS4gTeG7l2kgY+G7mXQgxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQgY+G6t3AgbOG7o2kgbmh14bqtbi1uxINtLCB24bubaSBjaGnhu4F1IGNhbyBj4bunYSBj4buZdCBiaeG7g3UgdGjhu4sgc+G7kSBsxrDhu6NuZyDEkcahbiB24buLIGThu68gbGnhu4d1IGPDsyBt4bupYyBs4bujaSBuaHXhuq1uIMSRw7MgdHJvbmcgbsSDbSB0xrDGoW5nIOG7qW5nLiBOaMOjbiB0csOqbiBt4buXaSBj4buZdCBoaeG7g24gdGjhu4sgZ2nDoSB0cuG7iyBz4buRIGzGsOG7o25nIMSRw6MgxJHGsOG7o2MgbMOgbSB0csOybi4gIA0KDQoNCiAgKyBOaOG6rW4geMOpdCBiaeG7g3UgxJHhu5MgIA0KDQogICsgQmnhu4N1IMSR4buTIGdpw7pwIGLhuqFuOiAgDQoNCiAgKyBQaMOibiB0w61jaCBz4buxIHBow6JuIGLhu5EgY+G7p2EgbOG7o2kgbmh14bqtbiB0aGVvIG7Eg206IELhuqFuIGPDsyB0aOG7gyBxdWFuIHPDoXQgeGVtIGzhu6NpIG5odeG6rW4gY8OzIHBow6JuIGLhu5EgxJHhu5NuZyDEkeG7gXUgdGhlbyBjw6FjIG7Eg20gaGF5IHThuq1wIHRydW5nIGNo4bunIHnhur91IHbDoG8gbeG7mXQgc+G7kSBuxINtIG5o4bqldCDEkeG7i25oLiBTbyBzw6FuaCBjaGnhu4F1IGNhbyBj4bunYSBjw6FjIGPhu5l0IGPDuW5nIG3hu5l0IGzhu6NpIG5odeG6rW4gZ2nhu69hIGPDoWMgbsSDbSBraMOhYyBuaGF1LiAgDQogIA0KICArIFjDoWMgxJHhu4tuaCBjw6FjIG7Eg20gY8OzIGhv4bqhdCDEkeG7mW5nIG7hu5VpIGLhuq10OiBOaOG7r25nIG7Eg20gY8OzIGPDoWMgY+G7mXQgY2FvIGLhuqV0IHRoxrDhu51uZyBjaG8gbeG7mXQgbeG7qWMgbOG7o2kgbmh14bqtbiBj4bulIHRo4buDIGPDsyB0aOG7gyBsw6Agbmjhu69uZyBuxINtIGPDsyBob+G6oXQgxJHhu5luZyBraW5oIGRvYW5oIMSRw6FuZyBjaMO6IMO9LiAgDQogIA0KICArIEtp4buDbSB0cmEgc+G7sSB0xrDGoW5nIHF1YW4gZ2nhu69hIGzhu6NpIG5odeG6rW4gdsOgIG7Eg206IE7hur91IGPDsyBz4buxIHBo4bulIHRodeG7mWMgcsO1IHLDoG5nIGdp4buvYSBs4bujaSBuaHXhuq1uIHbDoCBuxINtICh2w60gZOG7pTogbOG7o2kgbmh14bqtbiBsdcO0biBjYW8gbmjhuqV0IHbDoG8gbeG7mXQgbsSDbSBj4bulIHRo4buDKSwgYmnhu4N1IMSR4buTIG7DoHkgY8OzIHRo4buDIGdpw7pwIGLhuqFuIHjDoWMgxJHhu4tuaCDEkWnhu4F1IMSRw7MuICANCiAgDQojIyAqKkJp4buDdSDEkeG7kyBxdWFuIHPDoXQgZG9hbmggc+G7kSBiw6FuIGjDoG5nIHRoZW8gdGjDoW5nLioqDQoNCmBgYHtyLGNobz1UUlVFfQ0KZSRxIDwtIG1vbnRoKGUkT3JkZXJEYXRlKQ0KdGFibGUoZSRxKQ0KZSAlPiUgZ3JvdXBfYnkoU2FsZXMscSkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeD1xLHk9bikpICsgZ2VvbV9jb2woZmlsbD0nbGlnaHRncmVlbicpICtnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKG4sMikgLCB2anVzdD0yLCBjb2xvcj0nYmxhY2snKSkgKyBsYWJzKHg9J3Row6FuZycseSA9J0RvYW5oIHPhu5EgYsOhbiBow6BuZycpDQpgYGANCg0KKiBEw7JuZyBjb2RlIGUkcSA8LSBtb250aChlJE9yZGVyRGF0ZSkgdOG6oW8gcmEgbeG7mXQgY+G7mXQgbeG7m2kgdMOqbiBxIHRyb25nIGThu68gbGnhu4d1IGUuIEPhu5l0IG7DoHkgbMawdSB0cuG7ryBz4buRIHRow6FuZyAoMS0xMikgxJHGsOG7o2MgdHLDrWNoIHh14bqldCB04burIGPhu5l0IE9yZGVyRGF0ZS4gICANCg0KICArIELhuqNuZyB04bqnbiBzdeG6pXQgdGhlbyB0aMOhbmc6ICANCg0KICArIETDsm5nIGNvZGUgdGFibGUoZSRxKSBpbiByYSBi4bqjbmcgdOG6p24gc3XhuqV0IGNobyB0aOG6pXkgc+G7kSBs4bqnbiB4deG6pXQgaGnhu4duIGPhu6dhIG3hu5dpIHRow6FuZyAoMS0xMikgdHJvbmcgZOG7ryBsaeG7h3UuICANCiAgKyBC4bqjbmcgbsOgeSBnacO6cCBi4bqhbiBoaeG7g3UgZG9hbmggc+G7kSBiw6FuIGjDoG5nIHBow6JuIGLhu5EgbmjGsCB0aOG6vyBuw6BvIHRyb25nIG7Eg20uICANCiAgDQogICsgTmjDs20gZOG7ryBsaeG7h3UgdGhlbyBEb2FuaCBz4buRIHbDoCBUaMOhbmc6ICANCg0KICArIETDsm5nIGNvZGUgZSAlPiUgZ3JvdXBfYnkoU2FsZXMsIHEpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgc+G7rSBk4bulbmcgZHBseXIgxJHhu4MgbmjDs20gZOG7ryBsaeG7h3UgdGhlbyBj4bq3cCBTYWxlcyAoZG9hbmggc+G7kSkgdsOgIHEgKHRow6FuZykuIEjDoG0gc3VtbWFyaXNlIHNhdSDEkcOzIHTDrW5oIHPhu5EgbOG6p24geHXhuqV0IGhp4buHbiAoc+G7kSBsxrDhu6NuZykgY2hvIG3hu5dpIG5ow7NtLCBsxrB1IHRy4buvIHPhu5EgbMaw4bujbmcgdHJvbmcgYmnhur9uIG4uICANCiAgDQogICsgVOG6oW8gYmnhu4N1IMSR4buTOiAgDQoNCiAgKyBEw7JuZyBjb2RlIGdncGxvdChhZXMoeCA9IHEsIHkgPSBuKSkgdGhp4bq/dCBs4bqtcCBu4buBbiB04bqjbmcgY2hvIGJp4buDdSDEkeG7kyBi4bqxbmcgY8OhY2ggeMOhYyDEkeG7i25oIHRy4bulYyBob8OgbmggKHgpIGzDoCB0aMOhbmcgKHEpIHbDoCB0cuG7pWMgdHVuZyAoeSkgbMOgIHPhu5EgbMaw4bujbmcgKG4pLiAgDQogIA0KICArIETDsm5nIGNvZGUgZ2VvbV9jb2woZmlsbD0nbGlnaHRncmVlbicpIHThuqFvIGJp4buDdSDEkeG7kyBk4bqhbmcgaMOsbmggY+G7mXQgduG7m2kgbcOgdSB0w7QgbMOgIHhhbmggbMOhIG5o4bqhdCAoZmlsbD0nbGlnaHRncmVlbicpLiAgDQogIA0KICArIETDsm5nIGNvZGUgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG4sIDIpLCB2anVzdCA9IDIsIGNvbG9yID0gJ2JsYWNrJykpIHRow6ptIG5ow6NuIGNobyBjw6FjIGPhu5l0LCBoaeG7g24gdGjhu4sgZ2nDoSB0cuG7iyBuIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIGhhaSBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiAocm91bmQobiwgMikpLiBW4buLIHRyw60gY+G7p2EgbmjDo24gxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIHRoZW8gdHLhu6VjIHR1bmcgKHZqdXN0ID0gMikgdsOgIG3DoHUgc+G6r2MgbmjDo24gbMOgIMSRZW4gKGNvbG9yID0gJ2JsYWNrJykuICANCiAgDQogICsgTmjhuq1uIHjDqXQgYmnhu4N1IMSR4buTOiAgDQoNCiAgKyBCaeG7g3UgxJHhu5MgbsOgeSB0aOG7gyBoaeG7h24gc+G7sSBwaMOibiBi4buRIGRvYW5oIHPhu5EgYsOhbiBow6BuZyB0aGVvIHRow6FuZy4gTeG7l2kgY+G7mXQgxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQgdGjDoW5nLCB24bubaSBjaGnhu4F1IGNhbyBj4bunYSBj4buZdCBiaeG7g3UgdGjhu4sgc+G7kSBsxrDhu6NuZyDEkcahbiB24buLIGThu68gbGnhu4d1IChkb2FuaCBz4buRIGLDoW4gaMOgbmcpIHRyb25nIHRow6FuZyB0xrDGoW5nIOG7qW5nLiBOaMOjbiB0csOqbiBt4buXaSBj4buZdCBoaeG7g24gdGjhu4sgZ2nDoSB0cuG7iyBz4buRIGzGsOG7o25nIMSRw6MgxJHGsOG7o2MgbMOgbSB0csOybi4gIA0KDQogICsgVOG7qyBiaeG7g3UgxJHhu5MgbsOgeSwgYuG6oW4gY8OzIHRo4buDOiAgDQoNCiAgKyBQaMOibiB0w61jaCBz4buxIHBow6JuIGLhu5EgZG9hbmggc+G7kSB0aGVvIHRow6FuZzogUXVhbiBzw6F0IHhlbSBkb2FuaCBz4buRIGPDsyBwaMOibiBi4buRIMSR4buTbmcgxJHhu4F1IHRoZW8gY8OhYyB0aMOhbmcgaGF5IHThuq1wIHRydW5nIGNo4bunIHnhur91IHbDoG8gbeG7mXQgc+G7kSB0aMOhbmcgbmjhuqV0IMSR4buLbmguIFNvIHPDoW5oIGNoaeG7gXUgY2FvIGPhu6dhIGPDoWMgY+G7mXQgY8O5bmcgbeG7mXQgbeG7qWMgZG9hbmggc+G7kSBnaeG7r2EgY8OhYyB0aMOhbmcga2jDoWMgbmhhdS4gIA0KICANCiAgKyBYw6FjIMSR4buLbmggY8OhYyB0aMOhbmcgY8OzIGhv4bqhdCDEkeG7mW5nIG7hu5VpIGLhuq10OiBOaOG7r25nIHRow6FuZyBjw7MgY8OhYyBj4buZdCBjYW8gYuG6pXQgdGjGsOG7nW5nIGNobyBt4buZdCBt4bupYyBkb2FuaCBz4buRIGPhu6UgdGjhu4MgY8OzIHRo4buDIGzDoCBuaOG7r25nIHRow6FuZyBjw7MgaG/huqF0IMSR4buZbmcga2luaCBkb2FuaCDEkcOhbmcgY2jDuiDDvS4gIA0KICANCiAgKyBLaeG7g20gdHJhIHPhu7EgdMawxqFuZyBxdWFuIGdp4buvYSBkb2FuaCBz4buRIHbDoCB0aMOhbmc6IE7hur91IGPDsyBz4buxIHBo4bulIHRodeG7mWMgcsO1IHLDoG5nIGdp4buvYSBkb2FuaCBz4buRIHbDoCB0aMOhbmcgKHbDrSBk4bulOiBkb2FuaCBz4buRIGx1w7RuIGNhbyBuaOG6pXQgdsOgbyBt4buZdCB0aMOhbmcgY+G7pSB0aOG7gyksIGJp4buDdSDEkeG7kyBuw6B5IGPDsyB0aOG7gyBnacO6cCBi4bqhbiB4w6FjIMSR4buLbmggxJFp4buBdSDEkcOzLiAgDQogIA0KIyMgKipCaeG7g3UgxJHhu5MgcXVhbiBzw6F0IGzGsOG7o25nIHPhuqNuIHBo4bqpbSBz4bq1bmcgc8OgbiBjdW5nIOG7qW5nLioqDQoNCmBgYHtyLGVjaG89VFJVRX0NCmUgJT4lIGdncGxvdChhZXMoeD1RdWFudGlseSkpKyBnZW9tX2JhcihmaWxsPSdsaWdodGJsdWUnKSANCg0KYGBgDQoNCiMjICoqUXVhbiBzw6F0IFNhbGVzLCBQcm9maXQsIFF1YW50aWx5LioqDQoNCmBgYHtyLGNobz1UUlVFfQ0KZSAlPiUgZ2dwbG90KGFlcyh4PVNhbGVzLCB5PSBRdWFudGlseSwgY29sb3I9UHJvZml0KSkgK2dlb21fcG9pbnQoKQ0KYGBgDQoNCg0KQmnhu4N1IMSR4buTIG7DoHkgxJHGsOG7o2MgdOG6oW8gYuG7n2kgxJFv4bqhbiBtw6MgUiBz4butIGThu6VuZyBnw7NpIGdncGxvdDIgxJHhu4MgdGjhu4MgaGnhu4duIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgZG9hbmggc+G7kSAoU2FsZXMpLCBwaMOibiB24buLIChRdWFudGlseSkgdsOgIGzhu6NpIG5odeG6rW4gKFByb2ZpdCkuICANCg0KUGjDom4gdMOtY2ggY8OhYyB54bq/dSB04buROiAgDQoNCiogVHLhu6VjIGhvw6BuaCAoeCk6IFRo4buDIGhp4buHbiBkb2FuaCBz4buRIChTYWxlcykuICANCg0KKiBUcuG7pWMgdHVuZyAoeSk6IFRo4buDIGhp4buHbiBwaMOibiB24buLIChRdWFudGlseSkuICANCg0KKiDEkGnhu4NtIChnZW9tX3BvaW50KCkpOiBCaeG7g3UgdGjhu4sgdOG7q25nIGPhurdwIGThu68gbGnhu4d1IChkb2FuaCBz4buRLCBwaMOibiB24buLKSB24bubaSBtw6B1IHPhuq9jIMSRxrDhu6NjIG3DoyBow7NhIHRoZW8gbOG7o2kgbmh14bqtbiAoUHJvZml0KS4gIA0KDQoqIE3DoHUgc+G6r2MgKGNvbG9yPVByb2ZpdCk6IEPDoWMgxJFp4buDbSDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIG3hu6ljIMSR4buZIGzhu6NpIG5odeG6rW4uICANCg0KTmjhuq1uIHjDqXQ6DQoNCiogQmnhu4N1IMSR4buTIGdpw7pwIHNvIHPDoW5oIG3hu6ljIMSR4buZIGzhu6NpIG5odeG6rW4gZ2nhu69hIGPDoWMgcGjDom4gduG7iyDhu58gY8O5bmcgbeG7mXQgbeG7qWMgZG9hbmggc+G7kS4gIA0KDQoqIEJp4buDdSDEkeG7kyBjw7MgdGjhu4MgZ2nDunAgeMOhYyDEkeG7i25oIHBow6JuIHbhu4sgbsOgbyBjw7MgbOG7o2kgbmh14bqtbiBjYW8gbmjhuqV0L3Ro4bqlcCBuaOG6pXQgY2hvIG3hu5l0IG3hu6ljIGRvYW5oIHPhu5EgY+G7pSB0aOG7gy4gIA0KDQojIyAqKlF1YW4gc8OhdCBiaeG7g3UgxJHhu5MgxJHhu5luZy4qKg0KDQpgYGB7cixlY2hvPVRSVUV9DQpsaWJyYXJ5KGdnYW5pbWF0ZSkNCmxpYnJhcnkobWFnaWNrKQ0KZSAlPiUgZ2dwbG90KGFlcyh4ID0gU2FsZXMsIHkgPSBQcm9maXQsIGNvbG9yID0gUXVhbnRpbHkpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludChzaXplPTIpICsNCiAgdHJhbnNpdGlvbl9yZXZlYWwoU2FsZXMsIGtlZXBfbGFzdCA9IEYpDQpgYGANCg0KQmnhu4N1IMSR4buTIMSR4buZbmcgbsOgeSDEkcaw4bujYyB04bqhbyBi4bufaSDEkW/huqFuIG3DoyBSIHPhu60gZOG7pW5nIGfDs2kgZ2dwbG90MiB2w6AgaGnhu4d1IOG7qW5nIGNodXnhu4NuIHRp4bq/cCB0cmFuc2l0aW9uX3JldmVhbCDEkeG7gyB0aOG7gyBoaeG7h24gbeG7kWkgcXVhbiBo4buHIGdp4buvYSBkb2FuaCBz4buRIChTYWxlcyksIGzhu6NpIG5odeG6rW4gKFByb2ZpdCkgdsOgIHBow6JuIHbhu4sgKFF1YW50aWx5KS4gIA0KDQpDw6FjIHnhur91IHThu5E6ICANCg0KICArLFRy4bulYyBob8OgbmggKHgpOiBUaOG7gyBoaeG7h24gZG9hbmggc+G7kSAoU2FsZXMpLiAgDQogIA0KICArIFRy4bulYyB0dW5nICh5KTogVGjhu4MgaGnhu4duIGzhu6NpIG5odeG6rW4gKFByb2ZpdCkuICANCiAgDQogICsgxJDGsOG7nW5nIGvhursgKGdlb21fbGluZSgpKTogVGjhu4MgaGnhu4duIHh1IGjGsOG7m25nIHRoYXkgxJHhu5VpIGzhu6NpIG5odeG6rW4gdGhlbyBkb2FuaCBz4buRLCDEkcaw4bujYyBwaMOibiBiaeG7h3QgdGhlbyBwaMOibiB24buLIChtw6B1IHPhuq9jKS4gIA0KICANCiAgKyDEkGnhu4NtIChnZW9tX3BvaW50KHNpemU9MikpOiBCaeG7g3UgdGjhu4sgdOG7q25nIGPhurdwIGThu68gbGnhu4d1IChkb2FuaCBz4buRLCBs4bujaSBuaHXhuq1uKSB24bubaSBrw61jaCB0aMaw4bubYyAyLiAgDQogIA0KICArIE3DoHUgc+G6r2MgKGNvbG9yID0gUXVhbnRpbHkpOiBDw6FjIMSRxrDhu51uZyBr4bq7IHbDoCDEkWnhu4NtIMSRxrDhu6NjIHTDtCBtw6B1IHRoZW8gcGjDom4gduG7iyAoY8OzIHRo4buDIGzDoCB04bupIHBow6JuIHbhu4sgaG/hurdjIHBow6JuIHbhu4sga2jDoWMpLiAgDQogIA0KICArIEhp4buHdSDhu6luZyBjaHV54buDbiB0aeG6v3AgKHRyYW5zaXRpb25fcmV2ZWFsKFNhbGVzLCBrZWVwX2xhc3QgPSBGKSk6IEThu68gbGnhu4d1IMSRxrDhu6NjIHRp4bq/dCBs4buZIGThuqduIGThuqduIHRoZW8gdGjhu6kgdOG7sSB0xINuZyBk4bqnbiBj4bunYSBkb2FuaCBz4buRLiAgDQogIA0KTmjhuq1uIHjDqXQ6DQoNCiAgKyBCaeG7g3UgxJHhu5MgZ2nDunAgcGjDom4gdMOtY2ggbeG7kWkgcXVhbiBo4buHIGdp4buvYSBkb2FuaCBz4buRIHbDoCBs4bujaSBuaHXhuq1uIHRoZW8gY8OhYyBwaMOibiB24buLIGtow6FjIG5oYXUuICANCiAgDQogICsgSGnhu4d1IOG7qW5nIGNodXnhu4NuIHRp4bq/cCBnacO6cCB04bqtcCB0cnVuZyB2w6BvIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdSB2w6AgxJHGsOG7nW5nIGvhursgY8OzIGRvYW5oIHPhu5EgY2FvIGjGoW4uICANCiAgDQogICsgQuG6oW4gY8OzIHRo4buDIHBow6JuIHTDrWNoIHh1IGjGsOG7m25nIGPhu6dhIGzhu6NpIG5odeG6rW4gdGhlbyBkb2FuaCBz4buRLCBzbyBzw6FuaCBs4bujaSBuaHXhuq1uIGdp4buvYSBjw6FjIHBow6JuIHbhu4ssIHbDoCB4w6FjIMSR4buLbmggcGjDom4gduG7iyBjw7MgbOG7o2kgbmh14bqtbiBjYW8gbmjhuqV0L3Ro4bqlcCBuaOG6pXQuICANCiAgDQoNCiMjICoqVuG6vCBiaeG7g3UgxJHhu5MgxJHhu5luZyBi4bqxbmcgdOG7qSBwaMOibiB24buLIGPhu6dhIFNhbGVzLioqICANCg0KYGBge3IsZWNobz1UUlVFfQ0KDQplICU+JSBncm91cF9ieShRdWFudGlseSkgJT4lIHN1bW1hcmlzZShkPWN1dChlJFF1YW50aWx5LDMsbGFiZWw9IGMoJ25o4buPJywnduG7q2EnLCds4bubbicpKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9UXVhbnRpbHkseT1kKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgIGxhYnMoeD0nUXVhbnRpbHknLHk9Jy4nKQ0KYGBgDQoNCiMjICoqVuG6vSBiaeG7g3UgxJHhu5MgduG7gSBPcmRlcklELioqDQoNCmBgYHtyLGVjaG89VFJVRX0NCmUgJT4lDQogIGdncGxvdChhZXMoeD1PcmRlcklEKSkgKyBnZW9tX2JhcihmaWxsPSd2aW9sZXQnKSArIGxhYnMoeD0gJ0lEIMSRxqFuIGjDoG5nJyx5PSdz4buRIGzGsOG7o25nJykNCmBgYA0KDQpCaeG7g3UgxJHhu5MgxJHGsOG7o2MgdOG6oW8gYuG7n2kgxJFv4bqhbiBtw6MgUiBuw6B5IHPhu60gZOG7pW5nIGfDs2kgZ2dwbG90MiDEkeG7gyB04bqhbyBiaeG7g3UgxJHhu5MgdGhhbmggKGJhciBjaGFydCkgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgxJHGoW4gaMOgbmcgKHPhu5EgbMaw4bujbmcpIHRoZW8gbcOjIMSRxqFuIGjDoG5nIChPcmRlcklEKS4gIA0KDQpQaMOibiB0w61jaCBjw6FjIHnhur91IHThu5E6ICANCg0KICArIFRy4bulYyBob8OgbmggKHgpOiBUaOG7gyBoaeG7h24gbcOjIMSRxqFuIGjDoG5nIChPcmRlcklEKS4gIA0KICANCiAgKyBUcuG7pWMgdHVuZyAoeSk6IFRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIMSRxqFuIGjDoG5nIChz4buRIGzGsOG7o25nKS4gIA0KICANCiAgKyBUaGFuaCAoZ2VvbV9iYXIoKSk6IE3hu5dpIHRoYW5oIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIMSRxqFuIGjDoG5nIGNobyBt4buZdCBtw6MgxJHGoW4gaMOgbmcgY+G7pSB0aOG7gy4gIA0KICANCiAgKyBNw6B1IHPhuq9jIChmaWxsPSd2aW9sZXQnKTogVMO0IG3DoHUgdMOtbSBjaG8gdOG6pXQgY+G6oyBjw6FjIHRoYW5oLiAgDQogIA0KTmjhuq1uIHjDqXQ6DQoNCiAgKyBCaeG7g3UgxJHhu5MgbsOgeSBjdW5nIGPhuqVwIHRow7RuZyB0aW4gduG7gSBz4buRIGzGsOG7o25nIMSRxqFuIGjDoG5nIGNobyB04burbmcgbcOjIMSRxqFuIGjDoG5nLiAgDQogIA0KICArIEJp4buDdSDEkeG7kyB0aGFuaCBsw6AgbOG7sWEgY2jhu41uIHBow7kgaOG7o3AgxJHhu4MgdGjhu4MgaGnhu4duIGThu68gbGnhu4d1IHBow6JuIGxv4bqhaSBuaMawIG3DoyDEkcahbiBow6BuZy4gIA0KICANCiAgKyBWaeG7h2Mgc+G7rSBk4bulbmcgbcOgdSB0w61tIGNobyB04bqldCBj4bqjIGPDoWMgdGhhbmggY8OzIHRo4buDIGdp4bqjbSBraOG6oyBuxINuZyBwaMOibiBiaeG7h3QgZ2nhu69hIGPDoWMgdGhhbmguICANCiAgDQojIyAqKm3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgxJHhu4thIGNo4buJIGVtYWlsIChFbWFpbElEKSB2w6AgbcOjIMSRxqFuIGjDoG5nIChPcmRlcklEKS4qKg0KDQoNCmBgYHtyLGVjaG89VFJVRX0NCmUgJT4lIGdncGxvdChhZXMoeD1FbWFpbElELCB5PSBPcmRlcklEKSkgKyBnZW9tX3BvaW50KCkNCmBgYA0KDQpCaeG7g3UgxJHhu5MgxJHGsOG7o2MgdOG6oW8gYuG7n2kgxJFv4bqhbiBtw6MgUiBuw6B5IHPhu60gZOG7pW5nIGfDs2kgZ2dwbG90MiDEkeG7gyB04bqhbyBiaeG7g3UgxJHhu5MgxJFp4buDbSAoc2NhdHRlciBwbG90KSB0aOG7gyBoaeG7h24gbeG7kWkgcXVhbiBo4buHIGdp4buvYSDEkeG7i2EgY2jhu4kgZW1haWwgKEVtYWlsSUQpIHbDoCBtw6MgxJHGoW4gaMOgbmcgKE9yZGVySUQpLiAgDQoNClBow6JuIHTDrWNoIGPDoWMgeeG6v3UgdOG7kTogIA0KDQogICsgVHLhu6VjIGhvw6BuaCAoeCk6IFRo4buDIGhp4buHbiDEkeG7i2EgY2jhu4kgZW1haWwgKEVtYWlsSUQpLiAgDQogIA0KICArIFRy4bulYyB0dW5nICh5KTogVGjhu4MgaGnhu4duIG3DoyDEkcahbiBow6BuZyAoT3JkZXJJRCkuICANCiAgDQogICsgQ8OhYyDEkWnhu4NtIChnZW9tX3BvaW50KCkpOiBN4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IGvhur90IGjhu6NwIGdp4buvYSDEkeG7i2EgY2jhu4kgZW1haWwgdsOgIG3DoyDEkcahbiBow6BuZy4gIA0KDQojIyAqKiBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgdsO5bmcgxJHhu4thIGzDvSAoR2VvZ3JhcGh5KSB2w6AgbcOjIMSRxqFuIGjDoG5nIChPcmRlcklEKS4qKiANCg0KYGBge3IsZWNobz1UUlVFfQ0KZSAlPiUgZ2dwbG90KGFlcyh4PUdlb2dyYXBoeSwgeT0gT3JkZXJJRCkpICsgZ2VvbV9wb2ludCgpDQpgYGANCg0KQmnhu4N1IMSR4buTIMSRxrDhu6NjIHThuqFvIGLhu59pIMSRb+G6oW4gbcOjIFIgbsOgeSBz4butIGThu6VuZyBnw7NpIGdncGxvdDIgxJHhu4MgdOG6oW8gYmnhu4N1IMSR4buTIMSRaeG7g20gKHNjYXR0ZXIgcGxvdCkuIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gQmnhu4N1IMSR4buTIMSRxrDhu6NjIHThuqFvIGLhu59pIMSRb+G6oW4gbcOjIFIgbsOgeSBz4butIGThu6VuZyBnw7NpIGdncGxvdDIgxJHhu4MgdOG6oW8gYmnhu4N1IMSR4buTIMSRaeG7g20gKHNjYXR0ZXIgcGxvdCkuIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gbeG7kWkgcXVhbiBo4buHIGdp4buvYSB2w7luZyDEkeG7i2EgbMO9IChHZW9ncmFwaHkpIHbDoCBtw6MgxJHGoW4gaMOgbmcgKE9yZGVySUQpLg0KDQpQaMOibiB0w61jaCBjw6FjIHnhur91IHThu5E6ICANCg0KICArIFRy4bulYyBob8OgbmggKHgpOiBUaOG7gyBoaeG7h24gY8OhYyB2w7luZyDEkeG7i2EgbMO9IChHZW9ncmFwaHkpLiAgDQoNCiAgKyBUcuG7pWMgdHVuZyAoeSk6IFRo4buDIGhp4buHbiBtw6MgxJHGoW4gaMOgbmcgKE9yZGVySUQpLiAgDQoNCiAgKyBDw6FjIMSRaeG7g20gKGdlb21fcG9pbnQoKSk6IE3hu5dpIMSRaeG7g20gxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQga+G6v3QgaOG7o3AgZ2nhu69hIHbDuW5nIMSR4buLYSBsw70gdsOgIG3DoyDEkcahbiBow6BuZy4uICANCg0KIyMNCmBgYHtyLGVjaG89VFJVRX0NCmUgJT4lIGdncGxvdChhZXMoeD1HZW9ncmFwaHksIHk9IENhdGVnb3J5KSkgKyBnZW9tX3BvaW50KCkNCmBgYA0KDQpCaeG7g3UgxJHhu5MgaGnhu4NuIHRo4buLIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdSDEkcaw4bujYyBwaMOibiBi4buRIHRyw6puIG3hurd0IHBo4bqzbmcgduG7m2kgaGFpIHRy4bulYzogIA0KDQogICsgVHLhu6VjIGhvw6BuaCAoeCk6IFRo4buDIGhp4buHbiB2w7luZyDEkeG7i2EgbMO9LiAgDQogIA0KICArIFRy4bulYyB0dW5nICh5KTogVGjhu4MgaGnhu4duIGxv4bqhaSBow6BuZyBow7NhLiAgDQogIA0KICArIFbhu4sgdHLDrSBj4bunYSBt4buXaSDEkWnhu4NtIGThu68gbGnhu4d1IHRo4buDIGhp4buHbiBz4buxIGvhur90IGjhu6NwIGPhu6dhIHbDuW5nIMSR4buLYSBsw70gdsOgIGxv4bqhaSBow6BuZyBow7NhLiAgDQogIA0KICArIEvDrWNoIHRoxrDhu5tjIHbDoCBtw6B1IHPhuq9jIGPhu6dhIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdSBjw7MgdGjhu4MgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgYmnhu4N1IHRo4buLIHRow6ptIHRow7RuZyB0aW4gKG5oxrAgZG9hbmggc+G7kSBiw6FuIGjDoG5nLCBz4buRIGzGsOG7o25nIGtow6FjaCBow6BuZywgdi52LikuICANCiAgDQojIw0KDQpgYGB7cixlY2hvPVRSVUV9DQplICU+JSBncm91cF9ieShDYXRlZ29yeSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBDYXRlZ29yeSkpICsNCiAgICBnZW9tX2NvbChDYXRlZ29yeSA9ICdibGFjaycpICsNCiAgICBjb29yZF9wb2xhcigneScpICsNCiAgICBnZW9tX3RleHQoYWVzKHggPSAxLjMsIGxhYmVsID0gbikscG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSkgKw0KICAgIHRoZW1lX3ZvaWQoKQ0KYGBgDQoNClBow6JuIHTDrWNoIGPDoWMgeeG6v3UgdOG7kToNCg0KICArIFRy4bulYyBob8OgbmggKGfDs2MpOiBLaMO0bmcgaGnhu4NuIHRo4buLIG5ow6NuICh4ID0gJycpLCBkbyBk4buvIGxp4buHdSDEkcaw4bujYyBwaMOibiBi4buRIHRoZW8gY8OhYyBuaMOzbSBDYXRlZ29yeS4gIA0KICANCiAgKyBUcuG7pWMgdHVuZyAoxJHhu5kgZMOgaSk6IFRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIHF1YW4gc8OhdCAobikgY2hvIG3hu5dpIG5ow7NtIENhdGVnb3J5LiAgDQogIA0KICArIE3DoHUgc+G6r2M6IFTDtCB0aGVvIGJp4bq/biBDYXRlZ29yeSAoZmlsbCA9IENhdGVnb3J5KS4gIA0KICANCiAgKyDEkMaw4budbmcga+G6uzogVOG6pXQgY+G6oyBjw6FjIMSRxrDhu51uZyBr4bq7IGPDsyBtw6B1IMSRZW4gKGdlb21fY29sKENhdGVnb3J5ID0gJ2JsYWNrJykpLiAgDQogIA0KICArIEjhu4cgdGjhu5FuZyB04buNYSDEkeG7mSBj4buxYzogQmnhu4N1IMSR4buTIHPhu60gZOG7pW5nIGjhu4cgdOG7jWEgxJHhu5kgY+G7sWMgKGNvb3JkX3BvbGFyKCd5JykpLiAgDQogIA0KICArIE5ow6NuIGThu68gbGnhu4d1OiBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBxdWFuIHPDoXQgKG4pIGLDqm4gbmdvw6BpIGJp4buDdSDEkeG7kyAoZ2VvbV90ZXh0KS4gIA0KICANCiAgKyBDaOG7pyDEkeG7gSBu4buBbiB0cuG7kW5nOiBMb+G6oWkgYuG7jyBjw6FjIHnhur91IHThu5EgbeG6t2MgxJHhu4tuaCBj4bunYSBiaeG7g3UgxJHhu5MgKHRoZW1lX3ZvaWQoKSkuICANCiAgDQpOaOG6rW4geMOpdDogIA0KDQogICsgQmnhu4N1IMSR4buTIG7DoHkgaOG7r3Ugw61jaCDEkeG7gyBzbyBzw6FuaCB0xrDGoW5nIMSR4buRaSBz4buRIGzGsOG7o25nIHF1YW4gc8OhdCBnaeG7r2EgY8OhYyBuaMOzbSBDYXRlZ29yeSBraMOhYyBuaGF1LiAgDQogIA0KICArIEPDoWMgbmjDs20gQ2F0ZWdvcnkgY8OzIHPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IGNhbyBz4bq9IHThuqFvIHRow6BuaCBjw6FjIGjDrG5oIHRhbSBnacOhYyBs4bubbiBoxqFuIHRyw6puIGJp4buDdSDEkeG7ky4gIA0KICANCiAgKyBNw6B1IHPhuq9jIGPhu6dhIG3hu5dpIGjDrG5oIHRhbSBnacOhYyBnacO6cCBwaMOibiBiaeG7h3QgY8OhYyBuaMOzbSBDYXRlZ29yeS4gIA0KICANCiAgKyBOaMOjbiBk4buvIGxp4buHdSBjdW5nIGPhuqVwIHRow7RuZyB0aW4gY2hpIHRp4bq/dCB24buBIHPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IGNobyB04burbmcgbmjDs20uICANCiAgDQojIyAqKkJp4buDdSDEkeG7kyBHZW9ncmFwaHkuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KZSAlPiUgZ3JvdXBfYnkoR2VvZ3JhcGh5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAnJywgeSA9IG4sZmlsbCA9IEdlb2dyYXBoeSkpICsNCiAgICBnZW9tX2NvbChHZW9ncmFwaHkgPSAnYmxhY2snKSArDQogICAgY29vcmRfcG9sYXIoJ3knKSArDQogICAgZ2VvbV90ZXh0KGFlcyh4ID0gMS4zLCBsYWJlbCA9IG4pLHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAuNSkpICsNCiAgICB0aGVtZV92b2lkKCkNCmBgYA0KDQpQaMOibiB0w61jaCB2w6Agbmjhuq1uIHjDqXQgYmnhu4N1IMSR4buTICANCg0KICArIEJp4buDdSDEkeG7kyBi4bqhbiB04bqhbyByYSBz4butIGThu6VuZyBnw7NpIGdncGxvdDIgxJHhu4MgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IHRoZW8ga2h1IHbhu7FjIMSR4buLYSBsw70gKEdlb2dyYXBoeSkgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UgZS4gQmnhu4N1IMSR4buTIGThuqFuZyDEkWEgZ2nDoWMgY+G7sWMgKHJhZGFyIGNoYXJ0KSB24bubaSBjw6FjIHRy4bulYyBzYXU6ICANCg0KICArIFRy4bulYyBob8OgbmggKGfDs2MpOiBLaMO0bmcgaGnhu4NuIHRo4buLIG5ow6NuICh4ID0gJycpLCBkbyBk4buvIGxp4buHdSDEkcaw4bujYyBwaMOibiBi4buRIHRoZW8gY8OhYyBuaMOzbSBraHUgduG7sWMgxJHhu4thIGzDvS4gIA0KICANCiAgKyBUcuG7pWMgdHVuZyAoxJHhu5kgZMOgaSk6IFRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIHF1YW4gc8OhdCAobikgY2hvIG3hu5dpIGtodSB24buxYyDEkeG7i2EgbMO9LiAgDQogIA0KICArIE3DoHUgc+G6r2M6IFTDtCB0aGVvIGJp4bq/biBHZW9ncmFwaHkgKGZpbGwgPSBHZW9ncmFwaHkpLiAgDQogIA0KICArIMSQxrDhu51uZyBr4bq7OiBU4bqldCBj4bqjIGPDoWMgxJHGsOG7nW5nIGvhursgY8OzIG3DoHUgxJFlbiAoZ2VvbV9jb2woR2VvZ3JhcGh5ID0gJ2JsYWNrJykpLiAgDQogIA0KQ8OhYyB54bq/dSB04buRIGtow6FjOiAgDQoNCiAgKyBI4buHIHRo4buRbmcgdOG7jWEgxJHhu5kgY+G7sWMgKGNvb3JkX3BvbGFyKCd5JykpOiBCaeG7g3UgxJHhu5Mgc+G7rSBk4bulbmcgaOG7hyB04buNYSDEkeG7mSBj4buxYywgduG7m2kgY8OhYyB0cuG7pWMgdOG7j2EgcmEgdOG7qyB0w6JtLiAgDQogIA0KICArIE5ow6NuIGThu68gbGnhu4d1IChnZW9tX3RleHQpOiBUaMOqbSBuaMOjbiBk4buvIGxp4buHdSBoaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBxdWFuIHPDoXQgKG4pIGLDqm4gbmdvw6BpIGJp4buDdSDEkeG7kywgxJHGsOG7o2MgY8SDbiAgICBjaOG7iW5oIHRoZW8gduG7iyB0csOtIGNo4buTbmcgY2jhuqV0IChwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSkuICANCiAgDQogICsgQ2jhu6cgxJHhu4EgbuG7gW4gdHLhu5FuZyAodGhlbWVfdm9pZCgpKTogTG/huqFpIGLhu48gY8OhYyB54bq/dSB04buRIG3hurdjIMSR4buLbmggY+G7p2EgYmnhu4N1IMSR4buTLCBjaOG7iSBnaeG7ryBs4bqhaSBjw6FjIHRow6BuaCBwaOG6p24gY+G6p24gdGhp4bq/dC4gIA0KICANCk5o4bqtbiB4w6l0OiAgDQoNCiAgKyBCaeG7g3UgxJHhu5MgbsOgeSBo4buvdSDDrWNoIMSR4buDIHNvIHPDoW5oIHTGsMahbmcgxJHhu5FpIHPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IGdp4buvYSBjw6FjIGtodSB24buxYyDEkeG7i2EgbMO9IGtow6FjIG5oYXUuICANCiAgDQogICsgQ8OhYyBraHUgduG7sWMgY8OzIHPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IGNhbyBz4bq9IHThuqFvIHRow6BuaCBjw6FjIGjDrG5oIHRhbSBnacOhYyBs4bubbiBoxqFuIHRyw6puIGJp4buDdSDEkeG7ky4gIA0KICANCiAgKyBNw6B1IHPhuq9jIGPhu6dhIG3hu5dpIGjDrG5oIHRhbSBnacOhYyBnacO6cCBwaMOibiBiaeG7h3QgY8OhYyBraHUgduG7sWMgxJHhu4thIGzDvS4gIA0KICANCiAgKyBOaMOjbiBk4buvIGxp4buHdSBoaeG7g24gdGjhu4sgYsOqbiBuZ2/DoGkgYmnhu4N1IMSR4buTIGN1bmcgY+G6pXAgdGjDtG5nIHRpbiBjaGkgdGnhur90IHbhu4Egc+G7kSBsxrDhu6NuZyBxdWFuIHPDoXQgY2hvIHThu6tuZyBraHUgduG7sWMuICANCg0KDQoNCiMjIFbhur0gYmnhu4N1IMSR4buTIGThuqFuZyBkZW5zaXR5IGvhur90IGjhu6NwIDIgYmnhur9uIFNhbGVzIHbDoCBQcm9maXQuKioNCg0KYGBge3IsZWNobz1UUlVFfQ0KZ2dwbG90KGRhdGEgPSBlKSArDQogIGdlb21fZGVuc2l0eShhZXMoeCA9IFNhbGVzLCBmaWxsID0gIkRvYW5oIHPhu5EiKSwgY29sb3IgPSAibGlnaHRibHVlIikgKw0KICBnZW9tX2RlbnNpdHkoYWVzKHggPSBQcm9maXQsIGZpbGwgPSAiTOG7o2kgbmh14bqtbiIpLCBjb2xvciA9ICJsaWdodGdyZWVuIikgKw0KICBsYWJzKHggPSAiR2nDoSB0cuG7iyIsIHkgPSAiTeG6rXQgxJHhu5kiKQ0KYGBgDQoNCg0KMS4gSMOsbmggZOG6oW5nIHBow6JuIGLhu5E6ICANCg0KICArUGjDom4gYuG7kSBj4bunYSBTYWxlcyBjw7MgdGjhu4MgbMOgIMSR4buRaSB44bupbmcgaG/hurdjIGzDqWNoICh0w7l5IHRodeG7mWMgdsOgbyBk4buvIGxp4buHdSBj4bulIHRo4buDKS4gIA0KICANCiAgK1Bow6JuIGLhu5EgY+G7p2EgUHJvZml0IGPFqW5nIGPDsyB0aOG7gyBsw6AgxJHhu5FpIHjhu6luZyBob+G6t2MgbOG7h2NoLCB2w6AgY8OzIHRo4buDIGtow6FjIHbhu5tpIHBow6JuIGLhu5EgY+G7p2EgU2FsZXMuICANCiAgDQoyLiBN4bupYyDEkeG7mSB04bqtcCB0cnVuZzogIA0KDQogICtN4bupYyDEkeG7mSB04bqtcCB0cnVuZyBj4bunYSBTYWxlcyB2w6AgUHJvZml0IMSRxrDhu6NjIHRo4buDIGhp4buHbiBxdWEgxJHhu5kgY2FvIGPhu6dhIMSRxrDhu51uZyBjb25nIG3huq10IMSR4buZLiAgDQogIA0KICArQmnhu4N1IMSR4buTIG3huq10IMSR4buZIGNhbyBjaG8gdGjhuqV5IGThu68gbGnhu4d1IHThuq1wIHRydW5nIHF1YW5oIG3hu5l0IGdpw6EgdHLhu4sgbmjhuqV0IMSR4buLbmguICANCiAgDQogICtCaeG7g3UgxJHhu5MgbeG6rXQgxJHhu5kgdGjhuqVwIGNobyB0aOG6pXkgZOG7ryBsaeG7h3UgcGjDom4gdMOhbiBy4buZbmcgaMahbi4gIA0KICANCjMuIFNvIHPDoW5oIGhhaSBiaeG6v246ICANCg0KICArU28gc8OhbmggduG7iyB0csOtIMSR4buJbmggY+G7p2EgaGFpIMSRxrDhu51uZyBjb25nIG3huq10IMSR4buZIMSR4buDIHhlbSBiaeG6v24gbsOgbyBjw7MgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBjYW8gaMahbi4gIA0KICANCiAgK1NvIHPDoW5oIMSR4buZIHLhu5luZyBj4bunYSBoYWkgxJHGsOG7nW5nIGNvbmcgbeG6rXQgxJHhu5kgxJHhu4MgeGVtIGJp4bq/biBuw6BvIGPDsyDEkeG7mSBiaeG6v24gdGhpw6puIGNhbyBoxqFuLiAgDQogIA0KNC4gTeG7kWkgcXVhbiBo4buHIGdp4buvYSBoYWkgYmnhur9uOiAgDQoNCiAgK0Jp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSBjw7MgdGjhu4MgZ2nDunAgYuG6oW4geMOhYyDEkeG7i25oIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgU2FsZXMgdsOgIFByb2ZpdC4gIA0KICANCiAgK07hur91IGhhaSDEkcaw4budbmcgY29uZyBt4bqtdCDEkeG7mSBjaOG7k25nIGzDqm4gbmhhdSwgY8OzIHRo4buDIGPDsyBt4buRaSB0xrDGoW5nIHF1YW4gY2FvIGdp4buvYSBoYWkgYmnhur9uLiAgDQogIA0KICArTuG6v3UgaGFpIMSRxrDhu51uZyBjb25nIG3huq10IMSR4buZIHTDoWNoIGJp4buHdCwgY8OzIHRo4buDIGPDsyDDrXQgaG/hurdjIGtow7RuZyBjw7MgbeG7kWkgdMawxqFuZyBxdWFuIGdp4buvYSBoYWkgYmnhur9uLiAgDQogIA0KIyMNCg0KYGBge3IsZWNobz1UUlVFfQ0KZSAlPiUgZ2dwbG90KGFlcyh4ID0gT3JkZXJEYXRlLCB5ID0gU2hpcERhdGUsIGNvbG9yID0gQ2F0ZWdvcnkpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludChzaXplPTIpICsNCiAgdHJhbnNpdGlvbl9yZXZlYWwoU2FsZXMsIGtlZXBfbGFzdCA9IEYpDQpgYGANCg0KDQoqIEJp4buDdSDEkeG7kyDEkeG7mW5nIMSRxrDhu6NjIHThuqFvIHJhIGLhu59pIMSRb+G6oW4gbcOjIFIgc+G7rSBk4bulbmcgZ8OzaSBnZ3Bsb3QyIHbDoCBoaeG7h3Ug4bupbmcgY2h1eeG7g24gdGnhur9wIHRyYW5zaXRpb25fcmV2ZWFsIMSR4buDIHRo4buDIGhp4buHbiBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIG5nw6B5IMSR4bq3dCBow6BuZyAoT3JkZXJEYXRlKSwgbmfDoHkgZ2lhbyBow6BuZyAoU2hpcERhdGUpLCBsb+G6oWkgaMOgbmcgaMOzYSAoQ2F0ZWdvcnkpIHbDoCBkb2FuaCBz4buRIGLDoW4gaMOgbmcgKFNhbGVzKS4gQmnhu4N1IMSR4buTIG7DoHkgY3VuZyBj4bqlcCBuaGnhu4F1IHRow7RuZyB0aW4gaOG7r3Ugw61jaDogIA0KDQoxLiBYdSBoxrDhu5tuZzogIA0KDQogICsgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiB4dSBoxrDhu5tuZyBjaHVuZyBj4bunYSB0aOG7nWkgZ2lhbiBnaWFvIGjDoG5nIChTaGlwRGF0ZSkgdMSDbmcgZOG6p24gdGhlbyB0aOG7nWkgZ2lhbiDEkeG6t3QgaMOgbmcgKE9yZGVyRGF0ZSkuICANCiAgDQogICsgWHUgaMaw4bubbmcgbsOgeSBjw7MgdGjhu4Mga2jDoWMgbmhhdSBjaG8gdOG7q25nIGxv4bqhaSBow6BuZyBow7NhIChDYXRlZ29yeSksIMSRxrDhu6NjIHBow6JuIGJp4buHdCBi4bufaSBtw6B1IHPhuq9jIGPhu6dhIGPDoWMgxJHGsOG7nW5nIGvhursgdsOgIMSRaeG7g20uICANCiAgDQoyLiBTbyBzw6FuaDogIA0KDQogICsgQmnhu4N1IMSR4buTIGNobyBwaMOpcCBzbyBzw6FuaCB0aOG7nWkgZ2lhbiBnaWFvIGjDoG5nIGdp4buvYSBjw6FjIGxv4bqhaSBow6BuZyBow7NhIGtow6FjIG5oYXUuICANCiAgDQogICsgQuG6oW4gY8OzIHRo4buDIGThu4UgZMOgbmcgeMOhYyDEkeG7i25oIGxv4bqhaSBow6BuZyBow7NhIG7DoG8gY8OzIHRo4budaSBnaWFuIGdpYW8gaMOgbmcgdHJ1bmcgYsOsbmggY2FvIG5o4bqldCBob+G6t2MgdGjhuqVwIG5o4bqldC4gIA0KICANCjMuIEJp4bq/biDEkeG7mW5nOiAgDQoNCiAgKyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGJp4bq/biDEkeG7mW5nIGPhu6dhIHRo4budaSBnaWFuIGdpYW8gaMOgbmcgdHJvbmcgdOG7q25nIGxv4bqhaSBow6BuZyBow7NhLiAgDQogIA0KICArIEJp4bq/biDEkeG7mW5nIG7DoHkgY8OzIHRo4buDIMSRxrDhu6NjIMSRw6FuaCBnacOhIGLhurFuZyBjw6FjaCBxdWFuIHPDoXQgxJHhu5kgZOG7kWMgY+G7p2EgY8OhYyDEkcaw4budbmcga+G6uyB2w6AgduG7iyB0csOtIGPhu6dhIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdS4gIA0KICANCjQuIEhp4buHdSDhu6luZyBjaHV54buDbiB0aeG6v3A6ICANCg0KICArIEhp4buHdSDhu6luZyB0cmFuc2l0aW9uX3JldmVhbCBnacO6cCB04bqtcCB0cnVuZyB2w6BvIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdSB2w6AgxJHGsOG7nW5nIGvhursgY8OzIGRvYW5oIHPhu5EgYsOhbiBow6BuZyBjYW8gaMahbi4gIA0KICANCiAgKyDEkGnhu4F1IG7DoHkgZ2nDunAgbmfGsOG7nWkgeGVtIGThu4UgZMOgbmcgbmjhuq1uIGRp4buHbiBuaOG7r25nIHPhuqNuIHBo4bqpbSBjw7MgaGnhu4d1IHF14bqjIGtpbmggZG9hbmggdOG7kXQgbmjhuqV0Lg0KTmjhuq1uIHjDqXQgY2h1bmc6ICANCg0KICArIEJp4buDdSDEkeG7kyDEkeG7mW5nIG7DoHkgbMOgIG3hu5l0IGPDtG5nIGPhu6UgaOG7r3Ugw61jaCDEkeG7gyBwaMOibiB0w61jaCBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGPDoWMgYmnhur9uIE9yZGVyRGF0ZSwgU2hpcERhdGUsIENhdGVnb3J5IHbDoCBTYWxlcy4gIA0KICANCiAgKyBCaeG7g3UgxJHhu5MgY3VuZyBj4bqlcCB0aMO0bmcgdGluIHbhu4EgeHUgaMaw4bubbmcsIHNvIHPDoW5oLCBiaeG6v24gxJHhu5luZyB2w6AgZG9hbmggc+G7kSBiw6FuIGjDoG5nLiAgDQogIA0KICArIEhp4buHdSDhu6luZyBjaHV54buDbiB0aeG6v3AgZ2nDunAgdMSDbmcgY8aw4budbmcga2jhuqMgbsSDbmcgdHLhu7FjIHF1YW4gdsOgIHThuq1wIHRydW5nIHbDoG8gdGjDtG5nIHRpbiBxdWFuIHRy4buNbmcuICANCg0KDQojIw0KDQpgYGB7cixlY2hvPVRSVUV9DQplICU+JSBnZ3Bsb3QoYWVzKHggPSBPcmRlckRhdGUsIHkgPSBQcm9maXQsIGNvbG9yID0gQ2F0ZWdvcnkpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludChzaXplPTIpICsNCiAgdHJhbnNpdGlvbl9yZXZlYWwoU2FsZXMsIGtlZXBfbGFzdCA9IEYpDQpgYGANCg0KKiBOaOG6rW4geMOpdDogIA0KDQogIDEgQmnhu4N1IMSR4buTIHRoZW8gdGjhu51pIGdpYW46ICANCg0KICArIFRy4bulYyBYIHRo4buDIGhp4buHbiB0aOG7nWkgZ2lhbiAoT3JkZXJEYXRlKS4gIA0KICANCiAgKyBUcuG7pWMgWSB0aOG7gyBoaeG7h24gbOG7o2kgbmh14bqtbiAoUHJvZml0KSBob+G6t2MgZG9hbmggc+G7kSAoU2FsZXMpIHTDuXkgdGhlbyB0csaw4budbmcgaOG7o3AuICANCiAgDQogIDIuIFBow6JuIGxv4bqhaSB0aGVvIG5ow7NtOiAgDQoNCiAgKyBCaeG7g3UgxJHhu5Mgc+G7rSBk4bulbmcgbcOgdSBz4bqvYyDEkeG7gyBwaMOibiBiaeG7h3QgZOG7ryBsaeG7h3UgdGhlbyBuaMOzbSAoQ2F0ZWdvcnkpLiAgDQogIA0KICArIENobyBwaMOpcCBzbyBzw6FuaCBoaeG7h3Ugc3XhuqV0IGPhu6dhIGPDoWMgbmjDs20ga2jDoWMgbmhhdSB0aGVvIHRo4budaSBnaWFuLiAgDQogIA0KICAzLiBIaeG7g24gdGjhu4sgY2hpIHRp4bq/dDogIA0KDQogICsgQ8OhYyDEkWnhu4NtIGThu68gbGnhu4d1IChnZW9tX3BvaW50KSB0aOG7gyBoaeG7h24gYmnhur9uIMSR4buZbmcgY2hpIHRp4bq/dCBj4bunYSBs4bujaSBuaHXhuq1uL2RvYW5oIHPhu5EgdOG6oWkgdOG7q25nIHRo4budaSDEkWnhu4NtLiAgDQogIA0KICArIEdpw7pwIHF1YW4gc8OhdCBjw6FjIGJp4bq/biDEkeG7mW5nIMSR4buZdCBiaeG6v24gaG/hurdjIGdp4bqjbSBt4bqhbmguICANCiAgDQogIDQuIEhp4buHdSDhu6luZyBob+G6oXQg4bqjbmggKHTDuXkgY2jhu41uKToNCg0KICArIFTDuXkgY2jhu41uIHRyYW5zaXRpb25fcmV2ZWFsIChu4bq/dSDEkcaw4bujYyBrw61jaCBob+G6oXQpIHThuqFvIGhp4buHdSDhu6luZyBob+G6oXQg4bqjbmggaGnhu4NuIHRo4buLIGThu68gbGnhu4d1IHRoZW8gdGjhu51pIGdpYW4uICAgIA0KDQogICsgR2nDunAgdGhlbyBkw7VpIGPDoWMgbeG6q3UgdsOgIHh1IGjGsOG7m25nIGThu4UgZMOgbmcgaMahbi4gDQogIA0KIyMNCg0KYGBge3IsZWNobz1UUlVFfQ0KZSAlPiUgZ2dwbG90KGFlcyh4ID0gT3JkZXJEYXRlLCB5ID0gU2FsZXMsIGNvbG9yID0gQ2F0ZWdvcnkpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludChzaXplPTIpICsNCiAgdHJhbnNpdGlvbl9yZXZlYWwoU2FsZXMsIGtlZXBfbGFzdCA9IEYpDQpgYGANCg0KDQoqIE5o4bqtbiB4w6l0OiAgDQoNCiAgKyBCaeG7g3UgxJHhu5MgbsOgeSBjw7MgdGjhu4MgZ2nDunAgYuG6oW4gcGjDom4gdMOtY2ggeHUgaMaw4bubbmcgdGhlbyB0aOG7nWkgZ2lhbiBj4bunYSBkb2FuaCBz4buRIGLDoW4gaMOgbmcgdGhlbyBjw6FjIHBow6JuIGxv4bqhaSAoQ2F0ZWdvcnkpIGtow6FjIG5oYXUuICANCiAgDQogICsgWHUgaMaw4bubbmc6IEJp4buDdSDEkeG7kyDEkcaw4budbmcgKGdlb21fbGluZSkgY2hvIHRo4bqleSB4dSBoxrDhu5tuZyB04buVbmcgdGjhu4MgY+G7p2EgZG9hbmggc+G7kSBiw6FuIGjDoG5nIHRoZW8gdGjhu51pIGdpYW4gKE9yZGVyRGF0ZSkgY2hvIG3hu5dpIHBow6JuIGxv4bqhaS4gQuG6oW4gY8OzIHRo4buDIHF1YW4gc8OhdCB4ZW0gZG9hbmggc+G7kSB0xINuZywgZ2nhuqNtIGhheSDhu5VuIMSR4buLbmggdGhlbyB0aOG7nWkgZ2lhbi4gIA0KICANCiAgKyBT4buxIGtow6FjIGJp4buHdCBnaeG7r2EgY8OhYyBwaMOibiBsb+G6oWk6IE3DoHUgc+G6r2Mga2jDoWMgbmhhdSBnacO6cCBwaMOibiBiaeG7h3QgZG9hbmggc+G7kSB0aGVvIHThu6tuZyBwaMOibiBsb+G6oWkuIERvIMSRw7MsIGLhuqFuIGPDsyB0aOG7gyBk4buFIGTDoG5nIHNvIHPDoW5oIHhlbSBoaeG7h3Ugc3XhuqV0IGLDoW4gaMOgbmcgY+G7p2EgY8OhYyBwaMOibiBsb+G6oWkga2jDoWMgbmhhdSBuaMawIHRo4bq/IG7DoG8gdGhlbyB0aOG7nWkgZ2lhbi4gIA0KICANCiAgKyBCaeG6v24gxJHhu5luZyBjaGkgdGnhur90OiBDw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UgKGdlb21fcG9pbnQpIGNobyBwaMOpcCBi4bqhbiB4ZW0geMOpdCBjw6FjIGJp4bq/biDEkeG7mW5nIGNoaSB0aeG6v3QgY+G7p2EgZG9hbmggc+G7kSB04bqhaSB04burbmcgdGjhu51pIMSRaeG7g20gY+G7pSB0aOG7gy4gQuG6oW4gY8OzIHRo4buDIHRo4bqleSBjw7Mgbmjhu69uZyB0aOG7nWkgxJFp4buDbSBkb2FuaCBz4buRIHTEg25nIMSR4buZdCBiaeG6v24gaG/hurdjIGdp4bqjbSBt4bqhbmggxJHhu5FpIHbhu5tpIG3hu5l0IGhv4bq3YyBuaGnhu4F1IHBow6JuIGxv4bqhaS4gIA0KICANCiAgKyBIaeG7h3Ug4bupbmcgaG/huqF0IOG6o25oICh0w7l5IGNo4buNbik6IFTDuXkgY2jhu41uIHRyYW5zaXRpb25fcmV2ZWFsIChu4bq/dSDEkcaw4bujYyBi4bqtdCkgc+G6vSB04bqhbyBoaeG7h3Ug4bupbmcgaG/huqF0IOG6o25oIMSR4buDIGhp4buDbiB0aOG7iyBk4buvIGxp4buHdSB0aGVvIHRo4budaSBnaWFuLiDEkGnhu4F1IG7DoHkgY8OzIHRo4buDIGjhu691IMOtY2ggxJHhu4MgdHLhu7FjIHF1YW4gaMOzYSB0aOG7qSB04buxIHh14bqldCBoaeG7h24gY+G7p2EgZOG7ryBsaeG7h3UgdsOgIHRoZW8gZMO1aSBjw6FjIG3huqt1IHRoZW8gdGjhu51pIGdpYW4gIA==