“21:32:25, 10 - 03 - 2024”
***

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

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

1.2 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:

library(skimr)
skim(e)
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

skim_variable n_missing complete_rate min max empty n_unique whitespace
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

skim_variable n_missing complete_rate min max median n_unique
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

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
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 dateship 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)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)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)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.

2 Nghiên cứu doanh số bán hàng của Amazon trong giai đoạn 2011 - 2014.

2.1 Biểu đồ mô tả Sales.

library(tidyverse)
## 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.

2.2 Biểu đồ theo Sales và Category.

e %>% ggplot(aes(x = Sales, fill = Category)) +
  geom_histogram(binwidth = 500)

  • Nhận xét:

    • Trục x của biểu đồ hiển thị các giá trị của biến Sales.

    • Chiều cao của mỗi thanh biểu thị tần suất xuất hiện của các giá trị Sales trong một khoảng giá trị nhất định (được xác định bởi binwidth).

    • Màu sắc của các thanh biểu thị các danh mục khác nhau trong biến Category.

    • So sánh độ cao của các thanh trong cùng một danh mục cho phép bạn xem tần suất xuất hiện của các giá trị Sales trong các danh mục khác nhau.

    • Biểu đồ trên thể hiện mức bán ra của các doanh mục sản phẩm, mỗi một danh mục đều tương ứng với giá trị Sales.

    • Có tất cả 17 danh mục, được chú thích theo thứ tự chữ cái bên cạnh bản đồ.

    +Nhìn vào biểu đồ trên ta thấy được danh mục Accessories được bán chạy nhất, đạt mốc 2500 trên biểu đồ.

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

2.4 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

2.5 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 đó.

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

  • Dòng code e\(q <- month(e\)OrderDate) tạo ra một cột mới tên q trong dữ liệu e. Cột này lưu trữ số tháng (1-12) được trích xuất từ cột OrderDate.

    • Bảng tần suất theo tháng:

    • Dòng code table(e$q) in ra bảng tần suất cho thấy số lần xuất hiện của mỗi tháng (1-12) trong dữ liệu.

    • Bảng này giúp bạn hiểu doanh số bán hàng phân bố như thế nào trong năm.

    • Nhóm dữ liệu theo Doanh số và Tháng:

    • Dòng code e %>% group_by(Sales, q) %>% summarise(n = n()) sử dụng dplyr để nhóm dữ liệu theo cặp Sales (doanh số) và q (tháng). Hàm summarise sau đó tính số lần xuất hiện (số lượng) cho mỗi nhóm, lưu trữ số lượng trong biến n. 

    • Tạo biểu đồ:

    • Dòng code ggplot(aes(x = q, y = n)) thiết lập nền tảng cho biểu đồ bằng cách xác định trục hoành (x) là tháng (q) và trục tung (y) là số lượng (n).

    • Dòng code geom_col(fill=‘lightgreen’) tạo biểu đồ dạng hình cột với màu tô là xanh lá nhạt (fill=‘lightgreen’).

    • Dòng code geom_text(aes(label = round(n, 2), vjust = 2, color = ‘black’)) 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’).

    • Nhận xét biểu đồ:

    • Biểu đồ này thể hiện sự phân bố doanh số bán hàng theo tháng. Mỗi cột đại diện cho một tháng, với chiều cao của cột biểu thị số lượng đơn vị dữ liệu (doanh số bán hàng) trong tháng tương ứng. Nhãn trên mỗi cột hiển thị giá trị số lượng đã được làm tròn.

    • Từ biểu đồ này, bạn có thể:

    • Phân tích sự phân bố doanh số theo tháng: Quan sát xem doanh số có phân bố đồng đều theo các tháng hay tập trung chủ yếu vào một số tháng nhất định. So sánh chiều cao của các cột cùng một mức doanh số giữa các tháng khác nhau.

    • Xác định các tháng có hoạt động nổi bật: Những tháng có các cột cao bất thường cho một mức doanh số cụ thể có thể là những tháng có hoạt động kinh doanh đáng chú ý.

    • Kiểm tra sự tương quan giữa doanh số và tháng: Nếu có sự phụ thuộc rõ ràng giữa doanh số và tháng (ví dụ: doanh số luôn cao nhất vào một tháng cụ thể), biểu đồ này có thể giúp bạn xác định điều đó.

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

2.8 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:

  • Biểu đồ giúp so sánh mức độ lợi nhuận giữa các phân vị ở cùng một mức doanh số.

  • Biểu đồ có thể giúp xác định phân vị nào có lợi nhuận cao nhất/thấp nhất cho một mức doanh số cụ thể.

2.9 Quan sát biểu đồ động.

library(gganimate)
## Warning: package 'gganimate' was built under R version 4.3.3
library(magick)
## 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.

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

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

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

2.13 ** 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..

2.14

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

2.15

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.

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

2.17 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 độ")

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

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

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

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

2.18

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:
  1. 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.

  1. So sánh:
  • Biểu đồ cho phép so sánh thời gian giao hàng giữa các loại hàng hóa khác nhau.

  • Bạn có thể dễ dàng xác định loại hàng hóa nào có thời gian giao hàng trung bình cao nhất hoặc thấp nhất.

  1. Biến động:
  • Biểu đồ thể hiện biến động của thời gian giao hàng trong từng loại hàng hóa.

  • Biến động này có thể được đánh giá bằng cách quan sát độ dốc của các đường kẻ và vị trí của các điểm dữ liệu.

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

2.19

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

  • Nhận xét:

    1 Biểu đồ theo thời gian:

    • Trục X thể hiện thời gian (OrderDate).

    • Trục Y thể hiện lợi nhuận (Profit) hoặc doanh số (Sales) tùy theo trường hợp.

    1. Phân loại theo nhóm:
    • Biểu đồ sử dụng màu sắc để phân biệt dữ liệu theo nhóm (Category).

    • Cho phép so sánh hiệu suất của các nhóm khác nhau theo thời gian.

    1. Hiển thị chi tiết:
    • Các điểm dữ liệu (geom_point) thể hiện biến động chi tiết của lợi nhuận/doanh số tại từng thời điểm.

    • Giúp quan sát các biến động đột biến hoặc giảm mạnh.

    1. Hiệu ứng hoạt ảnh (tùy chọn):
    • Tùy chọn transition_reveal (nếu được kích hoạt) tạo hiệu ứng hoạt ảnh hiển thị dữ liệu theo thời gian.

    • Giúp theo dõi các mẫu và xu hướng dễ dàng hơn.

2.20

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==