1 Giới thiệu bộ dữ liệu supermarket_sales-sheet1.csv:

1.1 Mô tả bộ dữ liệu :

Sự phát triển của các siêu thị trong các thành phố đông dân đang tăng lên và cạnh tranh thị trường cũng cao. Tập dữ liệu này là một phần của lịch sử bán hàng của một công ty siêu thị đã được ghi lại trong 3 chi nhánh khác nhau trong suốt 3 tháng. Các phương pháp phân tích dữ liệu dự đoán dễ dàng áp dụng với tập dữ liệu này.

1.2 Thông tin cơ bản

  • Số lượng dữ liệu: Bộ dữ liệu thường chứa khoảng 1000 dòng (bản ghi) và 17 cột (biến).

  • Thuộc tính (biến):

    • Invoice.ID: Số hóa đơn được tạo bởi máy tính để nhận dạng hóa đơn bán hàng

    • Branch: Chi nhánh của siêu thị (có 3 chi nhánh được xác định bằng A, B và C).

    • City: Vị trí của các siêu thị

    • Customer.type: Loại khách hàng, ghi lại bởi “Members” cho khách hàng sử dụng thẻ thành viên và “Normal” cho khách hàng không có thẻ thành viên.

    • Gender: Loại giới tính của khách hàng

    • Product.line: Nhóm phân loại các mặt hàng chung - Phụ kiện điện tử, Phụ kiện thời trang, Thực phẩm và đồ uống, Sức khỏe và sắc đẹp, Đời sống gia đình, Thể thao và du lịch

    • Unit.price: Giá của mỗi sản phẩm tính bằng $

    • Quantity: Số lượng sản phẩm mà khách hàng đã mua

    • Tax.5: Phí thuế 5% cho khách hàng mua hàng

    • Total: Tổng giá bao gồm thuế

    • Date: Ngày mua hàng (Ghi chú từ tháng 1 năm 2019 đến tháng 3 năm 2019)

    • Time: Thời gian mua hàng (từ 10 giờ sáng đến 9 giờ tối)

    • Payment: Phương thức thanh toán được sử dụng bởi khách hàng (có 3 phương pháp có sẵn - Tiền mặt, Thẻ tín dụng và Ví điện tử)

    • COGS: Chi phí hàng hóa bán ra

    • Gross.margin.percentage: Tỷ lệ lợi nhuận gộp

    • Gross.income: Thu nhập gộp

    • Rating: Đánh giá phân loại khách hàng về trải nghiệm mua sắm tổng thể của họ (trên thang điểm từ 1 đến 10)

1.3 Cài và Load bộ dữ liệu vào R

library(csv)
## Warning: package 'csv' was built under R version 4.3.3
a <- read.csv("D:/Hà/supermarket_sales - Sheet1.csv", header= T) 

2 Vẽ Đồ Thị Dạng Bar Chart

2.1 Biểu đồ 1: biểu đồ mật độ của điểm đánh giá (Rating) dựa trên các chi nhánh khác nhau

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
a %>% ggplot(aes(x = Rating, fill = Branch)) +
  geom_density()

Giải thích câu lệnh:

  • %>%: Toán tử ống được sử dụng để chuyển kết quả từ a sang hàm ggplot().

  • ggplot(aes(x = Rating, fill = Branch)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, x = Rating ánh xạ điểm đánh giá vào trục x, và fill = Branch ánh xạ các chi nhánh vào màu sắc của biểu đồ.

  • geom_density(): Hàm này thêm một layer để vẽ biểu đồ mật độ. Trong trường hợp này, mỗi chi nhánh sẽ có một đường mật độ riêng biểu diễn phân phối của điểm đánh giá cho mỗi chi nhánh.

Kết quả:

Biểu đồ hiển thị hai đường cong mật độ, một cho mỗi chi nhánh (Branch). Đường cong mật độ cho thấy phân bố của các giá trị Rating cho từng chi nhánh.

2.2 Biểu đồ 2: biểu đồ mật độ của điểm đánh giá (Rating) dựa trên các chi nhánh khác nhau, với mỗi chi nhánh được hiển thị trong các đồ thị con riêng biệt.

a %>% ggplot(aes(x = Rating)) +
  geom_density(fill = 'skyblue') +
  facet_wrap(~Branch)

Giải thích câu lệnh:

  • ggplot(aes(x = Rating)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, x = Rating ánh xạ điểm đánh giá vào trục x.

  • geom_density(fill = ‘skyblue’): Hàm này thêm một layer để vẽ biểu đồ mật độ. Trong trường hợp này, màu nền của đường mật độ được thiết lập thành ‘skyblue’.

  • facet_wrap(~Branch): Hàm này tạo ra các đồ thị con dựa trên biến Branch. Cụ thể, nó tạo ra một biểu đồ mật độ cho mỗi giá trị duy nhất của biến Branch, với mỗi biểu đồ được hiển thị trong các ô riêng biệt.

Kết quả:

  • Biểu đồ bao gồm:

    • Một biểu đồ mật độ cho mỗi giá trị của biến Branch.

    • Trục hoành hiển thị giá trị của biến Rating.

    • Trục tung hiển thị mật độ xác suất.

    • Biểu đồ được tô màu bằng màu ‘skyblue’.

2.3 Biểu đồ 3: biểu đồ cột thể hiện số lượng này cho mỗi thành phố, cùng với số lượng được hiển thị trên mỗi cột.

a %>% group_by(City) %>% summarise(n = n()) %>%
  ggplot(aes(x = '', y = n,fill = City)) +
    geom_col() +
    geom_text(aes(label = n),position = position_stack(vjust = 1))

Giải thích câu lệnh:

  • group_by(City) %>% summarise(n = n()): Trước tiên, dữ liệu được nhóm lại theo thành phố (City) và sau đó tính tổng số lượng các mẫu trong mỗi nhóm (số lượng thành phố). Kết quả là một bảng dữ liệu mới với hai cột: thành phố (City) và số lượng (n).

  • **ggplot(aes(x = ’‘, y = n, fill = City)):** Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, xác định một trục x trống (’’) để tạo ra các cột độc lập nhau, y là số lượng (n) và fill là thành phố (City).

  • geom_col(): Hàm này thêm một layer để vẽ biểu đồ cột.

  • geom_text(aes(label = n), position = position_stack(vjust = 1)): Hàm này thêm văn bản vào mỗi cột, với label là số lượng (n) và vị trí được điều chỉnh để đặt văn bản trên cột.

Kết quả:

  • Biểu đồ bao gồm:

    • Một cột cho mỗi giá trị của biến City.

    • Chiều cao của mỗi cột biểu thị số lượng bản ghi trong nhóm tương ứng.

    • Biểu đồ được tô màu theo biến City.

    • Giá trị n được hiển thị trên đỉnh của mỗi cột.

2.4 Biểu đồ 4: biểu đồ cột tròn dựa trên số lượng thành phố, trong đó mỗi cột biểu diễn một thành phố, và chiều cao của cột được xác định bởi số lượng (n).

a %>% group_by(City) %>% summarise(n = n()) %>%
  ggplot(aes(x = '', y = n,fill = City)) +
    geom_col() +
    coord_polar('y')

Giải thích câu lệnh:

  • group_by(City) %>% summarise(n = n()): Tính tổng số lượng các thành phố (City) trong tập dữ liệu và lưu kết quả vào một bảng dữ liệu mới với hai cột: thành phố (City) và số lượng (n).

  • **ggplot(aes(x = ’‘, y = n, fill = City)):** Thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, xác định trục x trống (’’) để tạo ra các cột độc lập nhau, y là số lượng (n), và fill là thành phố (City).

  • geom_col(): Thêm một layer để vẽ biểu đồ cột.

  • coord_polar(‘y’): Chuyển đổi biểu đồ thành dạng cột tròn, với chiều cao của cột được xác định bởi giá trị trên trục y (n).

Kết quả:

  • Biểu đồ bao gồm:

    • Một vòng tròn cho mỗi giá trị của biến City.

    • Diện tích của mỗi vòng tròn biểu thị số lượng bản ghi trong nhóm tương ứng.

    • Biểu đồ được tô màu theo biến City.

2.5 Biểu đồ 5: biểu đồ cột tròn, biểu diễn số lượng các thành phố (City) khác nhau. Các cột được tô màu theo từng thành phố, và có chữ số đếm của mỗi thành phố được hiển thị trên biểu đồ.

a %>% group_by(City) %>% summarise(n = n()) %>%
  ggplot(aes(x = '', y = n,fill = City)) +
    geom_col(color = 'black') +
    coord_polar('y') +
    geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
    theme_void()

Giải thích câu lệnh:

  • **ggplot(aes(x = ’‘, y = n, fill = City)):** Thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, xác định trục x trống (’’) để tạo ra các cột độc lập nhau, y là số lượng (n), và fill là thành phố (City).

  • geom_col(color = ‘black’): Thêm một layer để vẽ biểu đồ cột và tô màu cột bằng fill, với màu viền đen (color = ‘black’).

  • coord_polar(‘y’): Chuyển đổi biểu đồ thành dạng cột tròn, với chiều cao của cột được xác định bởi giá trị trên trục y (n).

  • geom_text(aes(x = 1.3, label = n), position = position_stack(vjust = .5)): Thêm văn bản vào biểu đồ với giá trị label là số lượng (n), và vị trí xác định bằng x = 1.3. position_stack(vjust = .5) giúp điều chỉnh vị trí của văn bản trên cột.

  • theme_void(): Loại bỏ các phần bên ngoài biểu đồ để tạo ra một biểu đồ trắng đơn giản.

Kết quả:

  • Biểu đồ bao gồm:

    • Ba vòng tròn (hoặc số lượng theo nhóm trong dữ liệu a) được tô màu theo City.

    • Mỗi vòng tròn có viền màu đen.

    • Giá trị n (số lượng bản ghi) được hiển thị bên ngoài mỗi vòng tròn với màu đen, cách trục hoành 1.3 đơn vị.

    • Biểu đồ nền trong suốt (không có khung nền hoặc trục chú thích).

2.6 Biểu đồ 6: biểu đồ scatter plot biểu diễn mối quan hệ giữa giá của sản phẩm đơn vị và dòng sản phẩm

a %>% ggplot(aes(x = Unit.price, y = Product.line)) +
  geom_point() +
  xlab('Giá của sản phẩm') + 
  ylab('Dòng sản phẩm')

Giải thích câu lệnh:

  • ggplot(aes(x = Unit.price, y = Product.line)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, x = Unit.price ánh xạ giá của sản phẩm đơn vị vào trục x, và y = Product.line ánh xạ dòng sản phẩm vào trục y.

  • geom_point(): Thêm một layer để vẽ biểu đồ scatter plot với các điểm dữ liệu.

  • xlab(‘Giá của sản phẩm’)ylab(‘Dòng sản phẩm’): Thiết lập nhãn cho trục x và trục y tương ứng với “Giá của sản phẩm” và “Dòng sản phẩm”.

Kết quả:

  • Biểu đồ bao gồm:

    • Một tập hợp các điểm, mỗi điểm đại diện cho một sản phẩm.

    • Trục hoành hiển thị giá của sản phẩm.

    • Trục tung hiển thị dòng sản phẩm.

    • Nhãn cho trục hoành và trục tung.

2.7 Biểu đồ 7: biểu đồ scatter plot biểu diễn mối quan hệ giữa giá của sản phẩm đơn vị và dòng sản phẩm, với màu sắc của từng điểm dữ liệu được phân biệt theo chi nhánh (Branch).

a %>% ggplot(aes(x = Unit.price, y = Product.line, color = Branch)) +
  geom_point()

Giải thích câu lệnh:

  • ggplot(aes(x = Unit.price, y = Product.line, color = Branch)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, x = Unit.price ánh xạ giá của sản phẩm đơn vị vào trục x, y = Product.line ánh xạ dòng sản phẩm vào trục y, và color = Branch ánh xạ chi nhánh vào màu sắc của các điểm dữ liệu.

  • geom_point(): Thêm một layer để vẽ biểu đồ scatter plot với các điểm dữ liệu. Các điểm sẽ có màu sắc khác nhau tương ứng với từng chi nhánh.

Kết quả:

  • Biểu đồ bao gồm:

    • Một tập hợp các điểm, mỗi điểm đại diện cho một sản phẩm.

    • Trục hoành hiển thị giá của sản phẩm.

    • Trục tung hiển thị dòng sản phẩm.

    • Các điểm được tô màu theo biến Branch.

2.8 Biểu đồ 8: biểu đồ scatter plot biểu diễn mối quan hệ giữa giá của sản phẩm đơn vị và dòng sản phẩm, với các điểm dữ liệu được phân biệt theo hình dạng (shape) tương ứng với từng chi nhánh

a %>% ggplot(aes(x = Unit.price, y = Product.line, shape = Branch)) +
  geom_point()

Giải thích câu lệnh:

  • ggplot(aes(x = Unit.price, y = Product.line, shape = Branch)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, x = Unit.price ánh xạ giá của sản phẩm đơn vị vào trục x, y = Product.line ánh xạ dòng sản phẩm vào trục y, và shape = Branch ánh xạ chi nhánh vào hình dạng (shape) của các điểm dữ liệu.

  • geom_point(): Thêm một layer để vẽ biểu đồ scatter plot với các điểm dữ liệu. Các điểm sẽ có hình dạng (shape) khác nhau tương ứng với từng chi nhánh.

Kết quả:

  • Biểu đồ bao gồm:

    • Một tập hợp các điểm, mỗi điểm đại diện cho một sản phẩm.

    • Trục hoành hiển thị giá của sản phẩm.

    • Trục tung hiển thị dòng sản phẩm.

    • Các điểm được định dạng hình dạng theo biến Branch.

2.9 Biểu đồ 9: biểu đồ scatter plot biểu diễn mối quan hệ giữa điểm đánh giá và dòng sản phẩm, với kích thước của các điểm dữ liệu được phân biệt theo giới tính

a %>% ggplot(aes(x = Rating, y = Product.line, size = Gender)) +
  geom_point()
## Warning: Using size for a discrete variable is not advised.

Giải thích câu lệnh:

  • ggplot(aes(x = Rating, y = Product.line, size = Gender)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, x = Rating ánh xạ điểm đánh giá vào trục x, y = Product.line ánh xạ dòng sản phẩm vào trục y, và size = Gender ánh xạ giới tính vào kích thước của các điểm dữ liệu.

  • geom_point(): Thêm một layer để vẽ biểu đồ scatter plot với các điểm dữ liệu. Các điểm sẽ có kích thước khác nhau tương ứng với từng giới tính.

Kết quả:

  • Biểu đồ bao gồm:

    • Một tập hợp các điểm, mỗi điểm đại diện cho một sản phẩm.

    • Trục hoành hiển thị xếp hạng của sản phẩm.

    • Trục tung hiển thị dòng sản phẩm.

    • Kích thước của các điểm thay đổi theo biến Gender.

2.10 Biểu đồ 10: biểu đồ scatter plot biểu diễn mối quan hệ giữa giá của sản phẩm đơn vị và dòng sản phẩm, với độ trong suốt của các điểm dữ liệu được phân biệt theo chi nhánh

a %>% ggplot(aes(x = Unit.price, y = Product.line, alpha = Branch)) +
  geom_point()
## Warning: Using alpha for a discrete variable is not advised.

Giải thích câu lệnh:

  • ggplot(aes(x = Unit.price, y = Product.line, alpha = Branch)): Đây là phần cơ bản của biểu đồ ggplot. Nó thiết lập dữ liệu và ánh xạ các biến vào các thuộc tính của biểu đồ. Trong trường hợp này, x = Unit.price ánh xạ giá của sản phẩm đơn vị vào trục x, y = Product.line ánh xạ dòng sản phẩm vào trục y, và alpha = Branch ánh xạ chi nhánh vào độ trong suốt (alpha) của các điểm dữ liệu.

  • geom_point(): Thêm một layer để vẽ biểu đồ scatter plot với các điểm dữ liệu. Các điểm sẽ có độ trong suốt khác nhau tương ứng với từng chi nhánh.

Kết quả:

  • Biểu đồ bao gồm:

    • Một tập hợp các điểm, mỗi điểm đại diện cho một sản phẩm.

    • Trục hoành hiển thị giá của sản phẩm.

    • Trục tung hiển thị dòng sản phẩm.

    • Độ mờ của các điểm thay đổi theo biến Branch.

2.11 Biểu đồ 11: biểu đồ phân tán với đánh giá (Rating) trên trục x và chi nhánh (Branch) trên trục y

a %>% ggplot(aes(x = Rating, y = Branch)) +
  geom_point(color = 'red') +
  geom_smooth(method = 'lm', color = 'yellow')
## `geom_smooth()` using formula = 'y ~ x'

Giải thích câu lệnh:

  • ggplot(aes(x = Rating, y = Branch)): Bắt đầu với một biểu đồ ggplot với dữ liệu được ánh xạ vào trục x là điểm đánh giá (Rating) và trục y là chi nhánh (Branch).

  • geom_point(color = ‘red’): Thêm một layer với điểm dữ liệu, trong đó màu của các điểm được đặt là đỏ

  • geom_smooth(method = ‘lm’, color = ‘yellow’): Thêm một layer với đường cong hồi quy tuyến tính (linear regression) được fit vào dữ liệu. Trong đó, method = ‘lm’ chỉ ra rằng phương pháp sử dụng để fit dữ liệu là phương pháp hồi quy tuyến tính (linear regression), và màu của đường cong được đặt là màu vàng

Kết quả:

  • Biểu đồ bao gồm:

    • Một tập hợp các điểm màu đỏ, mỗi điểm đại diện cho một sản phẩm.

    • Trục hoành hiển thị xếp hạng của sản phẩm.

    • Trục tung hiển thị chi nhánh của sản phẩm.

    • Một đường cong màu vàng thể hiện mối quan hệ xu hướng giữa xếp hạng và chi nhánh.

2.12 Biểu đồ 12:

a %>% ggplot(aes(x = Unit.price, y = Product.line)) +
  geom_point(color = 'red') +
  geom_smooth(method = 'lm', color = 'yellow') +
  facet_wrap(~Branch)
## `geom_smooth()` using formula = 'y ~ x'

Kết quả:

Biểu đồ bao gồm:

  • Nhiều phân đoạn, mỗi phân đoạn tương ứng với một chi nhánh (Branch).

  • Trong mỗi phân đoạn:

    • Các điểm màu đỏ đại diện cho sản phẩm thuộc chi nhánh đó.

    • Đường cong màu vàng thể hiện xu hướng mối quan hệ giữa giá và dòng sản phẩm cho chi nhánh đó.

2.13 Biểu đồ 13: biểu đồ cột sử dụng gói ggplot2 và dữ liệu từ tệp CSV “supermarket_sales - Sheet1.csv”

library(ggplot2)       
data <- read.csv("D:/Hà/supermarket_sales - Sheet1.csv")
ggplot(data, aes(x = Product.line, y = Rating, fill = Product.line)) +
  geom_bar(stat = "identity") +
  scale_y_continuous("Rating")

Giải thích câu lệnh:

  • data <- read.csv(“D:/Hà/supermarket_sales - Sheet1.csv”): Dòng này đọc dữ liệu từ tệp CSV “supermarket_sales - Sheet1.csv” và lưu trữ nó vào biến data. Dữ liệu sẽ được đọc dưới dạng data frame.

  • ggplot(data, aes(x = Product.line, y = Rating, fill = Product.line)): Hàm ggplot() được sử dụng để khởi tạo một biểu đồ mới. Đối số data chỉ định dữ liệu được sử dụng. Trong aes(), chúng ta chỉ định các mapping aesthetics (tương ứng với các biến) cho trục x (x = Product.line), trục y (y = Rating), và fill color (fill = Product.line). Điều này có nghĩa là chúng ta sẽ vẽ cột dựa trên cột “Product.line”, chiều cao của các cột sẽ được xác định bởi cột “Rating”, và màu sắc của các cột sẽ tương ứng với giá trị của “Product.line”.

  • geom_bar(stat = “identity”): Hàm geom_bar() được sử dụng để tạo ra biểu đồ cột. Tham số stat = “identity” cho biết rằng chiều cao của các cột sẽ được xác định trực tiếp từ dữ liệu.

  • scale_y_continuous(“Rating”): Hàm scale_y_continuous() được sử dụng để đặt nhãn cho trục y của biểu đồ, với nhãn là “Rating”.

Kết quả: Mã này sẽ tạo biểu đồ thanh thể hiện trực quan xếp hạng trung bình của các dòng sản phẩm khác nhau trong dữ liệu bán hàng siêu thị.

  • Trục X: Trục này sẽ hiển thị các danh mục duy nhất từ cột Product.line, đại diện cho các dòng sản phẩm khác nhau trong dữ liệu

  • Trục Y: Trục này sẽ được dán nhãn “Rating” và sẽ hiển thị phạm vi xếp hạng số trong dữ liệu

  • Thanh: Biểu đồ sẽ có một thanh dọc cho mỗi danh mục dòng sản phẩm. Chiều cao của mỗi thanh sẽ tương ứng với xếp hạng trung bình cho dòng sản phẩm đó (giả sử stat = “identity” tính toán giá trị trung bình).

  • Màu sắc: Mỗi thanh sẽ được tô bằng một màu khác nhau và các màu sẽ được gán dựa trên danh mục dòng sản phẩm (được xác định bởi yếu tố thẩm mỹ fill = Product.line).

2.14 Biểu đồ 14: tạo một loạt các histogram, mỗi histogram biểu diễn phân phối của biến “Rating” (xếp hạng) trong dữ liệu.

qplot(Rating, data = read.csv("D:/Hà/supermarket_sales - Sheet1.csv"), facets = . ~ Product.line, geom = "histogram", binwidth = 1)
## Warning: `qplot()` was deprecated in ggplot2 3.4.0.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Giải thích câu lệnh:

  • Rating: biến số được sử dụng để vẽ histogram, đại diện cho xếp hạng của các sản phẩm.

  • data = read.csv(“D:/Hà/supermarket_sales - Sheet1.csv”): Đây là dữ liệu bạn sử dụng để vẽ histogram. Hàm read.csv() được sử dụng để đọc dữ liệu từ tệp CSV “supermarket_sales - Sheet1.csv”.

  • facets = . ~ Product.line: Tham số này xác định cách dữ liệu được phân chia thành các mặt hàng (facets) trên biểu đồ. Trong trường hợp này, . ~ Product.line chỉ ra rằng mỗi mặt hàng (facet) sẽ tương ứng với một loại sản phẩm được xác định bởi biến “Product.line”.

  • geom = “histogram”: Loại hình học bạn muốn sử dụng để vẽ biểu đồ. Trong trường hợp này, bạn đang sử dụng histogram để biểu diễn phân phối của dữ liệu.

  • binwidth = 1: Độ rộng của các bin (ngăn) trong histogram. Trong trường hợp này, độ rộng của mỗi bin được thiết lập là 1, có nghĩa là mỗi bin sẽ bao gồm các giá trị xếp hạng trong khoảng có độ rộng là 1.

Kết quả: Biểu đồ tạo ra sẽ hiển thị phân phối xếp hạng (Rating) cho từng dòng sản phẩm (Product.line) riêng biệt. Biểu đồ bao gồm:

  • Nhiều phân đoạn: Mỗi phân đoạn đại diện cho một dòng sản phẩm.

  • Trục Y: Hiển thị xếp hạng sản phẩm.

  • Trục X: Hiển thị số lượng sản phẩm cho mỗi xếp hạng.

  • Cột: Mỗi cột thể hiện số lượng sản phẩm có xếp hạng cụ thể trong một dòng sản phẩm.

2.15 Biểu đồ 15:

qplot( Rating, Unit.price, data = read.csv("D:/Hà/supermarket_sales - Sheet1.csv"), color = Branch)

Giải thích câu lệnh:

  • Rating, Unit.price: Đây là các biến bạn muốn vẽ trên trục x và trục y, tương ứng là “Rating” và “Unit.price”.

  • data = read.csv(“D:/Hà/supermarket_sales - Sheet1.csv”): Đây là dữ liệu bạn sử dụng để vẽ biểu đồ. Hàm read.csv() được sử dụng để đọc dữ liệu từ tệp CSV “supermarket_sales - Sheet1.csv”.

  • color = Branch: Tham số này chỉ định cách biểu đồ phân tán sẽ được màu sắc hóa dựa trên giá trị của biến “Branch”. Cụ thể, mỗi điểm dữ liệu sẽ được màu sắc khác nhau tương ứng với giá trị của biến “Branch”.

Kết quả: Biểu đồ tạo ra sẽ hiển thị mối quan hệ giữa xếp hạng (Rating) và giá bán (Unit.price) của các sản phẩm. Biểu đồ bao gồm:

  • Trục Y: Hiển thị xếp hạng sản phẩm.

  • Trục X: Hiển thị giá bán sản phẩm.

  • Điểm dữ liệu: Mỗi điểm đại diện cho một sản phẩm, được tô màu theo chi nhánh (Branch) của sản phẩm đó.

2.16 Biểu đồ 16:

qplot(Rating, data = read.csv("D:/Hà/supermarket_sales - Sheet1.csv"), geom = "histogram", binwidth = 0.05)

Kết quả: Biểu đồ tạo ra sẽ hiển thị phân phối xếp hạng (Rating) của sản phẩm. Biểu đồ bao gồm:

  • Trục Y: Hiển thị xếp hạng sản phẩm.

  • Trục X: Hiển thị số lượng sản phẩm cho mỗi xếp hạng.

  • Cột: Mỗi cột thể hiện số lượng sản phẩm có xếp hạng nằm trong khoảng cụ thể.

2.17 Biểu đồ 17:

qplot(Quantity, data = read.csv("D:/Hà/supermarket_sales - Sheet1.csv"), geom = "density")

Kết quả: Biểu đồ tạo ra sẽ hiển thị mật độ phân phối của số lượng sản phẩm (Quantity) được bán. Biểu đồ bao gồm:

  • Trục X: Hiển thị số lượng sản phẩm.

  • Trục Y: Hiển thị mật độ, thể hiện số lượng dữ liệu tập trung tại mỗi giá trị của Quantity.

  • Đường cong: Đường cong mượt mà thể hiện mật độ phân phối của dữ liệu.

2.18 Biểu đồ 18:

ggplot() +
  geom_histogram(data = filter(a, Branch == 'A'), aes(x = Unit.price), binwidth = 5, fill = 'pink') +
  geom_histogram(data = filter(a, Branch == 'C'), aes(x = Unit.price), binwidth = 5, fill = 'skyblue')

Giải thích câu lệnh:

  • ggplot(): Bắt đầu một đối tượng ggplot2 mới mà không cần kết nối với dữ liệu cụ thể.

  • geom_histogram(): chúng ta thêm hai lớp dữ liệu histogram, mỗi lớp tương ứng với một chi nhánh khác nhau.

  • data = filter(a, Branch == ‘A’) và data = filter(a, Branch == ‘C’): Lọc dữ liệu từ a (giả sử là data frame chứa dữ liệu) để chỉ lấy các quan sát có giá trị “Branch” tương ứng (“A” và “C” lần lượt). Điều này giúp chúng ta chỉ vẽ histogram cho các quan sát thuộc các chi nhánh này.

  • aes(x = Unit.price): Tạo mapping cho biến Unit.price trên trục x của histogram.

  • binwidth = 5: Xác định độ rộng của các bin (ngăn) trong histogram. Trong trường hợp này, độ rộng của mỗi bin được đặt là 5.

  • fill: Xác định màu sắc cho histogram của mỗi chi nhánh. Histogram cho chi nhánh “A” sẽ có màu hồng (“pink”) và histogram cho chi nhánh “C” sẽ có màu xanh da trời (“skyblue”).

Kết quả: Biểu đồ tạo ra sẽ hiển thị hai biểu đồ hình cột chồng lên nhau, so sánh phân phối giá bán (Unit.price) của hai chi nhánh A và C. Biểu đồ bao gồm:

  • Trục X: Hiển thị giá bán sản phẩm.

  • Trục Y: Hiển thị số lượng sản phẩm cho mỗi giá bán.

  • Cột: Hai nhóm cột, một màu hồng (chi nhánh A) và một màu xanh da trời (chi nhánh C), thể hiện số lượng sản phẩm cho mỗi giá bán của từng chi nhánh.

2.19 Biểu đồ 19:

a %>% ggplot(aes(x = Unit.price)) +
  geom_histogram(binwidth = 3, fill = 'green', color = 'red') +
  facet_wrap(~Branch)

Kết quả: Biểu đồ tạo ra sẽ hiển thị một loạt các biểu đồ hình cột, mỗi biểu đồ thể hiện phân phối giá bán (Unit.price) cho từng chi nhánh (Branch). Biểu đồ bao gồm:

  • Nhiều phân đoạn: Mỗi phân đoạn đại diện cho một chi nhánh.

  • Trục X: Hiển thị giá bán sản phẩm.

  • Trục Y: Hiển thị số lượng sản phẩm cho mỗi giá bán.

  • Cột: Các cột trong mỗi phân đoạn thể hiện số lượng sản phẩm cho mỗi giá bán của từng chi nhánh.

2.20 Biểu đồ 20:

a %>% ggplot(aes(x = Unit.price, fill = Product.line)) +
  geom_histogram(binwidth = 5)

Kết quả: Biểu đồ tạo ra sẽ hiển thị một biểu đồ hình cột với các cột được tô màu theo dòng sản phẩm (Product.line). Biểu đồ bao gồm:

  • Trục X: Hiển thị giá bán sản phẩm.

  • Trục Y: Hiển thị số lượng sản phẩm cho mỗi giá bán.

  • Cột: Các cột được tô màu theo dòng sản phẩm, thể hiện số lượng sản phẩm cho mỗi giá bán của từng dòng sản phẩm.

LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA0Ig0KYXV0aG9yOiAiVGh1IEjDoCINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVIOiVNOiVTLCAlZCAtICVtIC0gJVknKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50OiANCiAgICBkZl9wcmludDoga2FibGUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICB0b2NfZGVwdGg6IDINCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAnMicNCiAgcGRmX2RvY3VtZW50Og0KICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMgKipHaeG7m2kgdGhp4buHdSBi4buZIGThu68gbGnhu4d1IHN1cGVybWFya2V0X3NhbGVzLXNoZWV0MS5jc3Y6KioNCg0KIyMgKipNw7QgdOG6oyBi4buZIGThu68gbGnhu4d1IDoqKg0KDQpT4buxIHBow6F0IHRyaeG7g24gY+G7p2EgY8OhYyBzacOqdSB0aOG7iyB0cm9uZyBjw6FjIHRow6BuaCBwaOG7kSDEkcO0bmcgZMOibiDEkWFuZyB0xINuZyBsw6puIHbDoCBj4bqhbmggdHJhbmggdGjhu4sgdHLGsOG7nW5nIGPFqW5nIGNhby4gVOG6rXAgZOG7ryBsaeG7h3UgbsOgeSBsw6AgbeG7mXQgcGjhuqduIGPhu6dhIGzhu4tjaCBz4butIGLDoW4gaMOgbmcgY+G7p2EgbeG7mXQgY8O0bmcgdHkgc2nDqnUgdGjhu4sgxJHDoyDEkcaw4bujYyBnaGkgbOG6oWkgdHJvbmcgMyBjaGkgbmjDoW5oIGtow6FjIG5oYXUgdHJvbmcgc3Xhu5F0IDMgdGjDoW5nLiBDw6FjIHBoxrDGoW5nIHBow6FwIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IGThu7EgxJFvw6FuIGThu4UgZMOgbmcgw6FwIGThu6VuZyB24bubaSB04bqtcCBk4buvIGxp4buHdSBuw6B5Lg0KDQojIyAqKlRow7RuZyB0aW4gY8ahIGLhuqNuKioNCg0KLSBT4buRIGzGsOG7o25nIGThu68gbGnhu4d1OiBC4buZIGThu68gbGnhu4d1IHRoxrDhu51uZyBjaOG7qWEga2hv4bqjbmcgMTAwMCBkw7JuZyAoYuG6o24gZ2hpKSB2w6AgMTcgY+G7mXQgKGJp4bq/bikuDQoNCi0gVGh14buZYyB0w61uaCAoYmnhur9uKToNCg0KICAtIEludm9pY2UuSUQ6IFPhu5EgaMOzYSDEkcahbiDEkcaw4bujYyB04bqhbyBi4bufaSBtw6F5IHTDrW5oIMSR4buDIG5o4bqtbiBk4bqhbmcgaMOzYSDEkcahbiBiw6FuIGjDoG5nDQogIA0KICAtIEJyYW5jaDogQ2hpIG5ow6FuaCBj4bunYSBzacOqdSB0aOG7iyAoY8OzIDMgY2hpIG5ow6FuaCDEkcaw4bujYyB4w6FjIMSR4buLbmggYuG6sW5nIEEsIEIgdsOgIEMpLg0KICANCiAgLSBDaXR5OiBW4buLIHRyw60gY+G7p2EgY8OhYyBzacOqdSB0aOG7iw0KICANCiAgLSBDdXN0b21lci50eXBlOiBMb+G6oWkga2jDoWNoIGjDoG5nLCBnaGkgbOG6oWkgYuG7n2kgIk1lbWJlcnMiIGNobyBraMOhY2ggaMOgbmcgc+G7rSBk4bulbmcgdGjhursgdGjDoG5oIHZpw6puIHbDoCAiTm9ybWFsIiBjaG8ga2jDoWNoIGjDoG5nIGtow7RuZyBjw7MgdGjhursgdGjDoG5oIHZpw6puLg0KICANCiAgLSBHZW5kZXI6IExv4bqhaSBnaeG7m2kgdMOtbmggY+G7p2Ega2jDoWNoIGjDoG5nDQogIA0KICAtIFByb2R1Y3QubGluZTogTmjDs20gcGjDom4gbG/huqFpIGPDoWMgbeG6t3QgaMOgbmcgY2h1bmcgLSBQaOG7pSBraeG7h24gxJFp4buHbiB04butLCBQaOG7pSBraeG7h24gdGjhu51pIHRyYW5nLCBUaOG7sWMgcGjhuqltIHbDoCDEkeG7kyB14buRbmcsIFPhu6ljIGto4buPZSB2w6Agc+G6r2MgxJHhurlwLCDEkOG7nWkgc+G7kW5nIGdpYSDEkcOsbmgsIFRo4buDIHRoYW8gdsOgIGR1IGzhu4tjaA0KICANCiAgLSBVbml0LnByaWNlOiBHacOhIGPhu6dhIG3hu5dpIHPhuqNuIHBo4bqpbSB0w61uaCBi4bqxbmcgJA0KICANCiAgLSBRdWFudGl0eTogU+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gbcOgIGtow6FjaCBow6BuZyDEkcOjIG11YQ0KICANCiAgLSBUYXguNTogUGjDrSB0aHXhur8gNSUgY2hvIGtow6FjaCBow6BuZyBtdWEgaMOgbmdcDQogIA0KICAtIFRvdGFsOiBU4buVbmcgZ2nDoSBiYW8gZ+G7k20gdGh14bq/DQogIA0KICAtIERhdGU6IE5nw6B5IG11YSBow6BuZyAoR2hpIGNow7ogdOG7qyB0aMOhbmcgMSBuxINtIDIwMTkgxJHhur9uIHRow6FuZyAzIG7Eg20gMjAxOSkNCiAgDQogIC0gVGltZTogVGjhu51pIGdpYW4gbXVhIGjDoG5nICh04burIDEwIGdp4budIHPDoW5nIMSR4bq/biA5IGdp4budIHThu5FpKQ0KICANCiAgLSBQYXltZW50OiBQaMawxqFuZyB0aOG7qWMgdGhhbmggdG/DoW4gxJHGsOG7o2Mgc+G7rSBk4bulbmcgYuG7n2kga2jDoWNoIGjDoG5nIChjw7MgMyBwaMawxqFuZyBwaMOhcCBjw7Mgc+G6tW4gLSBUaeG7gW4gbeG6t3QsIFRo4bq7IHTDrW4gZOG7pW5nIHbDoCBWw60gxJFp4buHbiB04butKQ0KICANCiAgLSBDT0dTOiBDaGkgcGjDrSBow6BuZyBow7NhIGLDoW4gcmENCiAgDQogIC0gR3Jvc3MubWFyZ2luLnBlcmNlbnRhZ2U6IFThu7cgbOG7hyBs4bujaSBuaHXhuq1uIGfhu5lwDQogIA0KICAtIEdyb3NzLmluY29tZTogVGh1IG5o4bqtcCBn4buZcA0KICANCiAgLSBSYXRpbmc6IMSQw6FuaCBnacOhIHBow6JuIGxv4bqhaSBraMOhY2ggaMOgbmcgduG7gSB0cuG6o2kgbmdoaeG7h20gbXVhIHPhuq9tIHThu5VuZyB0aOG7gyBj4bunYSBo4buNICh0csOqbiB0aGFuZyDEkWnhu4NtIHThu6sgMSDEkeG6v24gMTApDQoNCiMjICoqQ8OgaSB2w6AgTG9hZCBi4buZIGThu68gbGnhu4d1IHbDoG8gUioqDQoNCmBgYHtyfQ0KbGlicmFyeShjc3YpDQphIDwtIHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IiwgaGVhZGVyPSBUKSANCmBgYA0KDQojICoqVuG6vSDEkOG7kyBUaOG7iyBE4bqhbmcgQmFyIENoYXJ0KioNCg0KIyMgKipCaeG7g3UgxJHhu5MgMToqKiBiaeG7g3UgxJHhu5MgbeG6rXQgxJHhu5kgY+G7p2EgxJFp4buDbSDEkcOhbmggZ2nDoSAoUmF0aW5nKSBk4buxYSB0csOqbiBjw6FjIGNoaSBuaMOhbmgga2jDoWMgbmhhdQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQphICU+JSBnZ3Bsb3QoYWVzKHggPSBSYXRpbmcsIGZpbGwgPSBCcmFuY2gpKSArDQogIGdlb21fZGVuc2l0eSgpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKiolPiU6KiogVG/DoW4gdOG7rSDhu5FuZyDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBjaHV54buDbiBr4bq/dCBxdeG6oyB04burIGEgc2FuZyBow6BtIGdncGxvdCgpLg0KDQotICoqZ2dwbG90KGFlcyh4ID0gUmF0aW5nLCBmaWxsID0gQnJhbmNoKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gUmF0aW5nIMOhbmggeOG6oSDEkWnhu4NtIMSRw6FuaCBnacOhIHbDoG8gdHLhu6VjIHgsIHbDoCBmaWxsID0gQnJhbmNoIMOhbmggeOG6oSBjw6FjIGNoaSBuaMOhbmggdsOgbyBtw6B1IHPhuq9jIGPhu6dhIGJp4buDdSDEkeG7ky4NCg0KLSAqKmdlb21fZGVuc2l0eSgpOioqIEjDoG0gbsOgeSB0aMOqbSBt4buZdCBsYXllciDEkeG7gyB24bq9IGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mS4gVHJvbmcgdHLGsOG7nW5nIGjhu6NwIG7DoHksIG3hu5dpIGNoaSBuaMOhbmggc+G6vSBjw7MgbeG7mXQgxJHGsOG7nW5nIG3huq10IMSR4buZIHJpw6puZyBiaeG7g3UgZGnhu4VuIHBow6JuIHBo4buRaSBj4bunYSDEkWnhu4NtIMSRw6FuaCBnacOhIGNobyBt4buXaSBjaGkgbmjDoW5oLg0KDQoqKkvhur90IHF14bqjOioqDQoNCkJp4buDdSDEkeG7kyBoaeG7g24gdGjhu4sgaGFpIMSRxrDhu51uZyBjb25nIG3huq10IMSR4buZLCBt4buZdCBjaG8gbeG7l2kgY2hpIG5ow6FuaCAoQnJhbmNoKS4gxJDGsOG7nW5nIGNvbmcgbeG6rXQgxJHhu5kgY2hvIHRo4bqleSBwaMOibiBi4buRIGPhu6dhIGPDoWMgZ2nDoSB0cuG7iyBSYXRpbmcgY2hvIHThu6tuZyBjaGkgbmjDoW5oLg0KDQojIyAqKkJp4buDdSDEkeG7kyAyOioqIGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSBj4bunYSDEkWnhu4NtIMSRw6FuaCBnacOhIChSYXRpbmcpIGThu7FhIHRyw6puIGPDoWMgY2hpIG5ow6FuaCBraMOhYyBuaGF1LCB24bubaSBt4buXaSBjaGkgbmjDoW5oIMSRxrDhu6NjIGhp4buDbiB0aOG7iyB0cm9uZyBjw6FjIMSR4buTIHRo4buLIGNvbiByacOqbmcgYmnhu4d0Lg0KDQpgYGB7cn0NCmEgJT4lIGdncGxvdChhZXMoeCA9IFJhdGluZykpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAnc2t5Ymx1ZScpICsNCiAgZmFjZXRfd3JhcCh+QnJhbmNoKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqZ2dwbG90KGFlcyh4ID0gUmF0aW5nKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gUmF0aW5nIMOhbmggeOG6oSDEkWnhu4NtIMSRw6FuaCBnacOhIHbDoG8gdHLhu6VjIHguDQoNCi0gKipnZW9tX2RlbnNpdHkoZmlsbCA9ICdza3libHVlJyk6KiogSMOgbSBuw6B5IHRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIG3huq10IMSR4buZLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgbcOgdSBu4buBbiBj4bunYSDEkcaw4budbmcgbeG6rXQgxJHhu5kgxJHGsOG7o2MgdGhp4bq/dCBs4bqtcCB0aMOgbmggJ3NreWJsdWUnLg0KDQotICoqZmFjZXRfd3JhcCh+QnJhbmNoKToqKiBIw6BtIG7DoHkgdOG6oW8gcmEgY8OhYyDEkeG7kyB0aOG7iyBjb24gZOG7sWEgdHLDqm4gYmnhur9uIEJyYW5jaC4gQ+G7pSB0aOG7gywgbsOzIHThuqFvIHJhIG3hu5l0IGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSBjaG8gbeG7l2kgZ2nDoSB0cuG7iyBkdXkgbmjhuqV0IGPhu6dhIGJp4bq/biBCcmFuY2gsIHbhu5tpIG3hu5dpIGJp4buDdSDEkeG7kyDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHJvbmcgY8OhYyDDtCByacOqbmcgYmnhu4d0Lg0KDQoqKkvhur90IHF14bqjOioqDQoNCi0gQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KICAgLSBN4buZdCBiaeG7g3UgxJHhu5MgbeG6rXQgxJHhu5kgY2hvIG3hu5dpIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIEJyYW5jaC4NCiAgIA0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyBnacOhIHRy4buLIGPhu6dhIGJp4bq/biBSYXRpbmcuDQogICANCiAgIC0gVHLhu6VjIHR1bmcgaGnhu4NuIHRo4buLIG3huq10IMSR4buZIHjDoWMgc3XhuqV0Lg0KDQogICAtIEJp4buDdSDEkeG7kyDEkcaw4bujYyB0w7QgbcOgdSBi4bqxbmcgbcOgdSAnc2t5Ymx1ZScuDQogICANCiMjICoqQmnhu4N1IMSR4buTIDM6KiogYmnhu4N1IMSR4buTIGPhu5l0IHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIG7DoHkgY2hvIG3hu5dpIHRow6BuaCBwaOG7kSwgY8O5bmcgduG7m2kgc+G7kSBsxrDhu6NuZyDEkcaw4bujYyBoaeG7g24gdGjhu4sgdHLDqm4gbeG7l2kgY+G7mXQuDQoNCmBgYHtyfQ0KYSAlPiUgZ3JvdXBfYnkoQ2l0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBDaXR5KSkgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSxwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMSkpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipncm91cF9ieShDaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpOioqIFRyxrDhu5tjIHRpw6puLCBk4buvIGxp4buHdSDEkcaw4bujYyBuaMOzbSBs4bqhaSB0aGVvIHRow6BuaCBwaOG7kSAoQ2l0eSkgdsOgIHNhdSDEkcOzIHTDrW5oIHThu5VuZyBz4buRIGzGsOG7o25nIGPDoWMgbeG6q3UgdHJvbmcgbeG7l2kgbmjDs20gKHPhu5EgbMaw4bujbmcgdGjDoG5oIHBo4buRKS4gS+G6v3QgcXXhuqMgbMOgIG3hu5l0IGLhuqNuZyBk4buvIGxp4buHdSBt4bubaSB24bubaSBoYWkgY+G7mXQ6IHRow6BuaCBwaOG7kSAoQ2l0eSkgdsOgIHPhu5EgbMaw4bujbmcgKG4pLg0KDQotICoqZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLCBmaWxsID0gQ2l0eSkpOioqIMSQw6J5IGzDoCBwaOG6p24gY8ahIGLhuqNuIGPhu6dhIGJp4buDdSDEkeG7kyBnZ3Bsb3QuIE7DsyB0aGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeMOhYyDEkeG7i25oIG3hu5l0IHRy4bulYyB4IHRy4buRbmcgKCcnKSDEkeG7gyB04bqhbyByYSBjw6FjIGPhu5l0IMSR4buZYyBs4bqtcCBuaGF1LCB5IGzDoCBz4buRIGzGsOG7o25nIChuKSB2w6AgZmlsbCBsw6AgdGjDoG5oIHBo4buRIChDaXR5KS4NCg0KLSAqKmdlb21fY29sKCk6KiogSMOgbSBuw6B5IHRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIGPhu5l0Lg0KDQotICoqZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMSkpOioqIEjDoG0gbsOgeSB0aMOqbSB2xINuIGLhuqNuIHbDoG8gbeG7l2kgY+G7mXQsIHbhu5tpIGxhYmVsIGzDoCBz4buRIGzGsOG7o25nIChuKSB2w6AgduG7iyB0csOtIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDEkeG7gyDEkeG6t3QgdsSDbiBi4bqjbiB0csOqbiBj4buZdC4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgY+G7mXQgY2hvIG3hu5dpIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIENpdHkuDQoNCiAgIC0gQ2hp4buBdSBjYW8gY+G7p2EgbeG7l2kgY+G7mXQgYmnhu4N1IHRo4buLIHPhu5EgbMaw4bujbmcgYuG6o24gZ2hpIHRyb25nIG5ow7NtIHTGsMahbmcg4bupbmcuDQoNCiAgIC0gQmnhu4N1IMSR4buTIMSRxrDhu6NjIHTDtCBtw6B1IHRoZW8gYmnhur9uIENpdHkuDQoNCiAgIC0gR2nDoSB0cuG7iyBuIMSRxrDhu6NjIGhp4buDbiB0aOG7iyB0csOqbiDEkeG7iW5oIGPhu6dhIG3hu5dpIGPhu5l0Lg0KDQojIyAqKkJp4buDdSDEkeG7kyA0OioqIGJp4buDdSDEkeG7kyBj4buZdCB0csOybiBk4buxYSB0csOqbiBz4buRIGzGsOG7o25nIHRow6BuaCBwaOG7kSwgdHJvbmcgxJHDsyBt4buXaSBj4buZdCBiaeG7g3UgZGnhu4VuIG3hu5l0IHRow6BuaCBwaOG7kSwgdsOgIGNoaeG7gXUgY2FvIGPhu6dhIGPhu5l0IMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBi4bufaSBz4buRIGzGsOG7o25nIChuKS4NCg0KYGBge3J9DQphICU+JSBncm91cF9ieShDaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAnJywgeSA9IG4sZmlsbCA9IENpdHkpKSArDQogICAgZ2VvbV9jb2woKSArDQogICAgY29vcmRfcG9sYXIoJ3knKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqZ3JvdXBfYnkoQ2l0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKToqKiBUw61uaCB04buVbmcgc+G7kSBsxrDhu6NuZyBjw6FjIHRow6BuaCBwaOG7kSAoQ2l0eSkgdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UgdsOgIGzGsHUga+G6v3QgcXXhuqMgdsOgbyBt4buZdCBi4bqjbmcgZOG7ryBsaeG7h3UgbeG7m2kgduG7m2kgaGFpIGPhu5l0OiB0aMOgbmggcGjhu5EgKENpdHkpIHbDoCBz4buRIGzGsOG7o25nIChuKS4NCg0KLSAqKmdncGxvdChhZXMoeCA9ICcnLCB5ID0gbiwgZmlsbCA9IENpdHkpKToqKiBUaGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeMOhYyDEkeG7i25oIHRy4bulYyB4IHRy4buRbmcgKCcnKSDEkeG7gyB04bqhbyByYSBjw6FjIGPhu5l0IMSR4buZYyBs4bqtcCBuaGF1LCB5IGzDoCBz4buRIGzGsOG7o25nIChuKSwgdsOgIGZpbGwgbMOgIHRow6BuaCBwaOG7kSAoQ2l0eSkuDQoNCi0gKipnZW9tX2NvbCgpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIGPhu5l0Lg0KDQotICoqY29vcmRfcG9sYXIoJ3knKToqKiBDaHV54buDbiDEkeG7lWkgYmnhu4N1IMSR4buTIHRow6BuaCBk4bqhbmcgY+G7mXQgdHLDsm4sIHbhu5tpIGNoaeG7gXUgY2FvIGPhu6dhIGPhu5l0IMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBi4bufaSBnacOhIHRy4buLIHRyw6puIHRy4bulYyB5IChuKS4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdsOybmcgdHLDsm4gY2hvIG3hu5dpIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIENpdHkuDQoNCiAgIC0gRGnhu4duIHTDrWNoIGPhu6dhIG3hu5dpIHbDsm5nIHRyw7JuIGJp4buDdSB0aOG7iyBz4buRIGzGsOG7o25nIGLhuqNuIGdoaSB0cm9uZyBuaMOzbSB0xrDGoW5nIOG7qW5nLg0KDQogICAtIEJp4buDdSDEkeG7kyDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIGJp4bq/biBDaXR5Lg0KDQojIyAqKkJp4buDdSDEkeG7kyA1OioqIGJp4buDdSDEkeG7kyBj4buZdCB0csOybiwgYmnhu4N1IGRp4buFbiBz4buRIGzGsOG7o25nIGPDoWMgdGjDoG5oIHBo4buRIChDaXR5KSBraMOhYyBuaGF1LiBDw6FjIGPhu5l0IMSRxrDhu6NjIHTDtCBtw6B1IHRoZW8gdOG7q25nIHRow6BuaCBwaOG7kSwgdsOgIGPDsyBjaOG7ryBz4buRIMSR4bq/bSBj4bunYSBt4buXaSB0aMOgbmggcGjhu5EgxJHGsOG7o2MgaGnhu4NuIHRo4buLIHRyw6puIGJp4buDdSDEkeG7ky4NCg0KYGBge3J9DQphICU+JSBncm91cF9ieShDaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAnJywgeSA9IG4sZmlsbCA9IENpdHkpKSArDQogICAgZ2VvbV9jb2woY29sb3IgPSAnYmxhY2snKSArDQogICAgY29vcmRfcG9sYXIoJ3knKSArDQogICAgZ2VvbV90ZXh0KGFlcyh4ID0gMS4zLCBsYWJlbCA9IG4pLHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAuNSkpICsNCiAgICB0aGVtZV92b2lkKCkNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2ggY8OidSBs4buHbmg6KioNCg0KLSAqKmdncGxvdChhZXMoeCA9ICcnLCB5ID0gbiwgZmlsbCA9IENpdHkpKToqKiBUaGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeMOhYyDEkeG7i25oIHRy4bulYyB4IHRy4buRbmcgKCcnKSDEkeG7gyB04bqhbyByYSBjw6FjIGPhu5l0IMSR4buZYyBs4bqtcCBuaGF1LCB5IGzDoCBz4buRIGzGsOG7o25nIChuKSwgdsOgIGZpbGwgbMOgIHRow6BuaCBwaOG7kSAoQ2l0eSkuDQoNCi0gKipnZW9tX2NvbChjb2xvciA9ICdibGFjaycpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIGPhu5l0IHbDoCB0w7QgbcOgdSBj4buZdCBi4bqxbmcgZmlsbCwgduG7m2kgbcOgdSB2aeG7gW4gxJFlbiAoY29sb3IgPSAnYmxhY2snKS4NCg0KLSAqKmNvb3JkX3BvbGFyKCd5Jyk6KiogQ2h1eeG7g24gxJHhu5VpIGJp4buDdSDEkeG7kyB0aMOgbmggZOG6oW5nIGPhu5l0IHRyw7JuLCB24bubaSBjaGnhu4F1IGNhbyBj4bunYSBj4buZdCDEkcaw4bujYyB4w6FjIMSR4buLbmggYuG7n2kgZ2nDoSB0cuG7iyB0csOqbiB0cuG7pWMgeSAobikuDQoNCi0gKipnZW9tX3RleHQoYWVzKHggPSAxLjMsIGxhYmVsID0gbiksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAuNSkpOioqIFRow6ptIHbEg24gYuG6o24gdsOgbyBiaeG7g3UgxJHhu5MgduG7m2kgZ2nDoSB0cuG7iyBsYWJlbCBsw6Agc+G7kSBsxrDhu6NuZyAobiksIHbDoCB24buLIHRyw60geMOhYyDEkeG7i25oIGLhurFuZyB4ID0gMS4zLiBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSBnacO6cCDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIGPhu6dhIHbEg24gYuG6o24gdHLDqm4gY+G7mXQuDQoNCi0gKip0aGVtZV92b2lkKCk6KiogTG/huqFpIGLhu48gY8OhYyBwaOG6p24gYsOqbiBuZ2/DoGkgYmnhu4N1IMSR4buTIMSR4buDIHThuqFvIHJhIG3hu5l0IGJp4buDdSDEkeG7kyB0cuG6r25nIMSRxqFuIGdp4bqjbi4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gQmEgdsOybmcgdHLDsm4gKGhv4bq3YyBz4buRIGzGsOG7o25nIHRoZW8gbmjDs20gdHJvbmcgZOG7ryBsaeG7h3UgYSkgxJHGsOG7o2MgdMO0IG3DoHUgdGhlbyBDaXR5Lg0KDQogICAtIE3hu5dpIHbDsm5nIHRyw7JuIGPDsyB2aeG7gW4gbcOgdSDEkWVuLg0KDQogICAtIEdpw6EgdHLhu4sgbiAoc+G7kSBsxrDhu6NuZyBi4bqjbiBnaGkpIMSRxrDhu6NjIGhp4buDbiB0aOG7iyBiw6puIG5nb8OgaSBt4buXaSB2w7JuZyB0csOybiB24bubaSBtw6B1IMSRZW4sIGPDoWNoIHRy4bulYyBob8OgbmggMS4zIMSRxqFuIHbhu4suDQoNCiAgIC0gQmnhu4N1IMSR4buTIG7hu4FuIHRyb25nIHN14buRdCAoa2jDtG5nIGPDsyBraHVuZyBu4buBbiBob+G6t2MgdHLhu6VjIGNow7ogdGjDrWNoKS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgNjoqKiBiaeG7g3UgxJHhu5Mgc2NhdHRlciBwbG90IGJp4buDdSBkaeG7hW4gbeG7kWkgcXVhbiBo4buHIGdp4buvYSBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbSDEkcahbiB24buLIHbDoCBkw7JuZyBz4bqjbiBwaOG6qW0NCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICB4bGFiKCdHacOhIGPhu6dhIHPhuqNuIHBo4bqpbScpICsgDQogIHlsYWIoJ0TDsm5nIHPhuqNuIHBo4bqpbScpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gVW5pdC5wcmljZSDDoW5oIHjhuqEgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0gxJHGoW4gduG7iyB2w6BvIHRy4bulYyB4LCB2w6AgeSA9IFByb2R1Y3QubGluZSDDoW5oIHjhuqEgZMOybmcgc+G6o24gcGjhuqltIHbDoG8gdHLhu6VjIHkuDQoNCi0gKipnZW9tX3BvaW50KCk6KiogVGjDqm0gbeG7mXQgbGF5ZXIgxJHhu4MgduG6vSBiaeG7g3UgxJHhu5Mgc2NhdHRlciBwbG90IHbhu5tpIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdS4NCg0KLSAqKnhsYWIoJ0dpw6EgY+G7p2Egc+G6o24gcGjhuqltJykqKiB2w6AgKip5bGFiKCdEw7JuZyBz4bqjbiBwaOG6qW0nKToqKiBUaGnhur90IGzhuq1wIG5ow6NuIGNobyB0cuG7pWMgeCB2w6AgdHLhu6VjIHkgdMawxqFuZyDhu6luZyB24bubaSAiR2nDoSBj4bunYSBz4bqjbiBwaOG6qW0iIHbDoCAiRMOybmcgc+G6o24gcGjhuqltIi4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdOG6rXAgaOG7o3AgY8OhYyDEkWnhu4NtLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgdHVuZyBoaeG7g24gdGjhu4sgZMOybmcgc+G6o24gcGjhuqltLg0KDQogICAtIE5ow6NuIGNobyB0cuG7pWMgaG/DoG5oIHbDoCB0cuG7pWMgdHVuZy4NCg0KIyMgKipCaeG7g3UgxJHhu5MgNzoqKiBiaeG7g3UgxJHhu5Mgc2NhdHRlciBwbG90IGJp4buDdSBkaeG7hW4gbeG7kWkgcXVhbiBo4buHIGdp4buvYSBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbSDEkcahbiB24buLIHbDoCBkw7JuZyBz4bqjbiBwaOG6qW0sIHbhu5tpIG3DoHUgc+G6r2MgY+G7p2EgdOG7q25nIMSRaeG7g20gZOG7ryBsaeG7h3UgxJHGsOG7o2MgcGjDom4gYmnhu4d0IHRoZW8gY2hpIG5ow6FuaCAoQnJhbmNoKS4NCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lLCBjb2xvciA9IEJyYW5jaCkpICsNCiAgZ2VvbV9wb2ludCgpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lLCBjb2xvciA9IEJyYW5jaCkpOioqIMSQw6J5IGzDoCBwaOG6p24gY8ahIGLhuqNuIGPhu6dhIGJp4buDdSDEkeG7kyBnZ3Bsb3QuIE7DsyB0aGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeCA9IFVuaXQucHJpY2Ugw6FuaCB44bqhIGdpw6EgY+G7p2Egc+G6o24gcGjhuqltIMSRxqFuIHbhu4sgdsOgbyB0cuG7pWMgeCwgeSA9IFByb2R1Y3QubGluZSDDoW5oIHjhuqEgZMOybmcgc+G6o24gcGjhuqltIHbDoG8gdHLhu6VjIHksIHbDoCBjb2xvciA9IEJyYW5jaCDDoW5oIHjhuqEgY2hpIG5ow6FuaCB2w6BvIG3DoHUgc+G6r2MgY+G7p2EgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1Lg0KDQotICoqZ2VvbV9wb2ludCgpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCB24bubaSBjw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UuIEPDoWMgxJFp4buDbSBz4bq9IGPDsyBtw6B1IHPhuq9jIGtow6FjIG5oYXUgdMawxqFuZyDhu6luZyB24bubaSB04burbmcgY2hpIG5ow6FuaC4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdOG6rXAgaOG7o3AgY8OhYyDEkWnhu4NtLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgdHVuZyBoaeG7g24gdGjhu4sgZMOybmcgc+G6o24gcGjhuqltLg0KDQogICAtIEPDoWMgxJFp4buDbSDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIGJp4bq/biBCcmFuY2guDQoNCiMjICoqQmnhu4N1IMSR4buTIDg6KiogYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCBiaeG7g3UgZGnhu4VuIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0gxJHGoW4gduG7iyB2w6AgZMOybmcgc+G6o24gcGjhuqltLCB24bubaSBjw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UgxJHGsOG7o2MgcGjDom4gYmnhu4d0IHRoZW8gaMOsbmggZOG6oW5nIChzaGFwZSkgdMawxqFuZyDhu6luZyB24bubaSB04burbmcgY2hpIG5ow6FuaA0KDQpgYGB7cn0NCmEgJT4lIGdncGxvdChhZXMoeCA9IFVuaXQucHJpY2UsIHkgPSBQcm9kdWN0LmxpbmUsIHNoYXBlID0gQnJhbmNoKSkgKw0KICBnZW9tX3BvaW50KCkNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2ggY8OidSBs4buHbmg6KioNCg0KLSAqKmdncGxvdChhZXMoeCA9IFVuaXQucHJpY2UsIHkgPSBQcm9kdWN0LmxpbmUsIHNoYXBlID0gQnJhbmNoKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gVW5pdC5wcmljZSDDoW5oIHjhuqEgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0gxJHGoW4gduG7iyB2w6BvIHRy4bulYyB4LCB5ID0gUHJvZHVjdC5saW5lIMOhbmggeOG6oSBkw7JuZyBz4bqjbiBwaOG6qW0gdsOgbyB0cuG7pWMgeSwgdsOgIHNoYXBlID0gQnJhbmNoIMOhbmggeOG6oSBjaGkgbmjDoW5oIHbDoG8gaMOsbmggZOG6oW5nIChzaGFwZSkgY+G7p2EgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1Lg0KDQotICoqZ2VvbV9wb2ludCgpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCB24bubaSBjw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UuIEPDoWMgxJFp4buDbSBz4bq9IGPDsyBow6xuaCBk4bqhbmcgKHNoYXBlKSBraMOhYyBuaGF1IHTGsMahbmcg4bupbmcgduG7m2kgdOG7q25nIGNoaSBuaMOhbmguDQoNCioqS+G6v3QgcXXhuqM6KioNCg0KLSBCaeG7g3UgxJHhu5MgYmFvIGfhu5NtOg0KDQogICAtIE3hu5l0IHThuq1wIGjhu6NwIGPDoWMgxJFp4buDbSwgbeG7l2kgxJFp4buDbSDEkeG6oWkgZGnhu4duIGNobyBt4buZdCBz4bqjbiBwaOG6qW0uDQoNCiAgIC0gVHLhu6VjIGhvw6BuaCBoaeG7g24gdGjhu4sgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0uDQoNCiAgIC0gVHLhu6VjIHR1bmcgaGnhu4NuIHRo4buLIGTDsm5nIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBDw6FjIMSRaeG7g20gxJHGsOG7o2MgxJHhu4tuaCBk4bqhbmcgaMOsbmggZOG6oW5nIHRoZW8gYmnhur9uIEJyYW5jaC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgOToqKiBiaeG7g3UgxJHhu5Mgc2NhdHRlciBwbG90IGJp4buDdSBkaeG7hW4gbeG7kWkgcXVhbiBo4buHIGdp4buvYSDEkWnhu4NtIMSRw6FuaCBnacOhIHbDoCBkw7JuZyBz4bqjbiBwaOG6qW0sIHbhu5tpIGvDrWNoIHRoxrDhu5tjIGPhu6dhIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdSDEkcaw4bujYyBwaMOibiBiaeG7h3QgdGhlbyBnaeG7m2kgdMOtbmgNCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBSYXRpbmcsIHkgPSBQcm9kdWN0LmxpbmUsIHNpemUgPSBHZW5kZXIpKSArDQogIGdlb21fcG9pbnQoKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqZ2dwbG90KGFlcyh4ID0gUmF0aW5nLCB5ID0gUHJvZHVjdC5saW5lLCBzaXplID0gR2VuZGVyKSk6KiogxJDDonkgbMOgIHBo4bqnbiBjxqEgYuG6o24gY+G7p2EgYmnhu4N1IMSR4buTIGdncGxvdC4gTsOzIHRoaeG6v3QgbOG6rXAgZOG7ryBsaeG7h3UgdsOgIMOhbmggeOG6oSBjw6FjIGJp4bq/biB2w6BvIGPDoWMgdGh14buZYyB0w61uaCBj4bunYSBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCB4ID0gUmF0aW5nIMOhbmggeOG6oSDEkWnhu4NtIMSRw6FuaCBnacOhIHbDoG8gdHLhu6VjIHgsIHkgPSBQcm9kdWN0LmxpbmUgw6FuaCB44bqhIGTDsm5nIHPhuqNuIHBo4bqpbSB2w6BvIHRy4bulYyB5LCB2w6Agc2l6ZSA9IEdlbmRlciDDoW5oIHjhuqEgZ2nhu5tpIHTDrW5oIHbDoG8ga8OtY2ggdGjGsOG7m2MgY+G7p2EgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1Lg0KDQotICoqZ2VvbV9wb2ludCgpOioqIFRow6ptIG3hu5l0IGxheWVyIMSR4buDIHbhur0gYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCB24bubaSBjw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UuIEPDoWMgxJFp4buDbSBz4bq9IGPDsyBrw61jaCB0aMaw4bubYyBraMOhYyBuaGF1IHTGsMahbmcg4bupbmcgduG7m2kgdOG7q25nIGdp4bubaSB0w61uaC4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdOG6rXAgaOG7o3AgY8OhYyDEkWnhu4NtLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyB44bq/cCBo4bqhbmcgY+G7p2Egc+G6o24gcGjhuqltLg0KDQogICAtIFRy4bulYyB0dW5nIGhp4buDbiB0aOG7iyBkw7JuZyBz4bqjbiBwaOG6qW0uDQoNCiAgIC0gS8OtY2ggdGjGsOG7m2MgY+G7p2EgY8OhYyDEkWnhu4NtIHRoYXkgxJHhu5VpIHRoZW8gYmnhur9uIEdlbmRlci4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTA6KiogYmnhu4N1IMSR4buTIHNjYXR0ZXIgcGxvdCBiaeG7g3UgZGnhu4VuIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgZ2nDoSBj4bunYSBz4bqjbiBwaOG6qW0gxJHGoW4gduG7iyB2w6AgZMOybmcgc+G6o24gcGjhuqltLCB24bubaSDEkeG7mSB0cm9uZyBzdeG7kXQgY+G7p2EgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1IMSRxrDhu6NjIHBow6JuIGJp4buHdCB0aGVvIGNoaSBuaMOhbmgNCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lLCBhbHBoYSA9IEJyYW5jaCkpICsNCiAgZ2VvbV9wb2ludCgpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlLCB5ID0gUHJvZHVjdC5saW5lLCBhbHBoYSA9IEJyYW5jaCkpOioqIMSQw6J5IGzDoCBwaOG6p24gY8ahIGLhuqNuIGPhu6dhIGJp4buDdSDEkeG7kyBnZ3Bsb3QuIE7DsyB0aGnhur90IGzhuq1wIGThu68gbGnhu4d1IHbDoCDDoW5oIHjhuqEgY8OhYyBiaeG6v24gdsOgbyBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgYmnhu4N1IMSR4buTLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgeCA9IFVuaXQucHJpY2Ugw6FuaCB44bqhIGdpw6EgY+G7p2Egc+G6o24gcGjhuqltIMSRxqFuIHbhu4sgdsOgbyB0cuG7pWMgeCwgeSA9IFByb2R1Y3QubGluZSDDoW5oIHjhuqEgZMOybmcgc+G6o24gcGjhuqltIHbDoG8gdHLhu6VjIHksIHbDoCBhbHBoYSA9IEJyYW5jaCDDoW5oIHjhuqEgY2hpIG5ow6FuaCB2w6BvIMSR4buZIHRyb25nIHN14buRdCAoYWxwaGEpIGPhu6dhIGPDoWMgxJFp4buDbSBk4buvIGxp4buHdS4NCg0KLSAqKmdlb21fcG9pbnQoKToqKiBUaMOqbSBt4buZdCBsYXllciDEkeG7gyB24bq9IGJp4buDdSDEkeG7kyBzY2F0dGVyIHBsb3QgduG7m2kgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1LiBDw6FjIMSRaeG7g20gc+G6vSBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IGtow6FjIG5oYXUgdMawxqFuZyDhu6luZyB24bubaSB04burbmcgY2hpIG5ow6FuaC4NCg0KKipL4bq/dCBxdeG6ozoqKg0KDQotIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCiAgIC0gTeG7mXQgdOG6rXAgaOG7o3AgY8OhYyDEkWnhu4NtLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyBnacOhIGPhu6dhIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgdHVuZyBoaeG7g24gdGjhu4sgZMOybmcgc+G6o24gcGjhuqltLg0KDQogICAtIMSQ4buZIG3hu50gY+G7p2EgY8OhYyDEkWnhu4NtIHRoYXkgxJHhu5VpIHRoZW8gYmnhur9uIEJyYW5jaC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTE6KiogYmnhu4N1IMSR4buTIHBow6JuIHTDoW4gduG7m2kgxJHDoW5oIGdpw6EgKFJhdGluZykgdHLDqm4gdHLhu6VjIHggdsOgIGNoaSBuaMOhbmggKEJyYW5jaCkgdHLDqm4gdHLhu6VjIHkNCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBSYXRpbmcsIHkgPSBCcmFuY2gpKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAncmVkJykgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nLCBjb2xvciA9ICd5ZWxsb3cnKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqZ2dwbG90KGFlcyh4ID0gUmF0aW5nLCB5ID0gQnJhbmNoKSk6KiogQuG6r3QgxJHhuqd1IHbhu5tpIG3hu5l0IGJp4buDdSDEkeG7kyBnZ3Bsb3QgduG7m2kgZOG7ryBsaeG7h3UgxJHGsOG7o2Mgw6FuaCB44bqhIHbDoG8gdHLhu6VjIHggbMOgIMSRaeG7g20gxJHDoW5oIGdpw6EgKFJhdGluZykgdsOgIHRy4bulYyB5IGzDoCBjaGkgbmjDoW5oIChCcmFuY2gpLg0KDQotICoqZ2VvbV9wb2ludChjb2xvciA9ICdyZWQnKToqKiBUaMOqbSBt4buZdCBsYXllciB24bubaSDEkWnhu4NtIGThu68gbGnhu4d1LCB0cm9uZyDEkcOzIG3DoHUgY+G7p2EgY8OhYyDEkWnhu4NtIMSRxrDhu6NjIMSR4bq3dCBsw6AgxJHhu48NCg0KLSAqKmdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScsIGNvbG9yID0gJ3llbGxvdycpOioqIFRow6ptIG3hu5l0IGxheWVyIHbhu5tpIMSRxrDhu51uZyBjb25nIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIChsaW5lYXIgcmVncmVzc2lvbikgxJHGsOG7o2MgZml0IHbDoG8gZOG7ryBsaeG7h3UuIFRyb25nIMSRw7MsIG1ldGhvZCA9ICdsbScgY2jhu4kgcmEgcuG6sW5nIHBoxrDGoW5nIHBow6FwIHPhu60gZOG7pW5nIMSR4buDIGZpdCBk4buvIGxp4buHdSBsw6AgcGjGsMahbmcgcGjDoXAgaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggKGxpbmVhciByZWdyZXNzaW9uKSwgdsOgIG3DoHUgY+G7p2EgxJHGsOG7nW5nIGNvbmcgxJHGsOG7o2MgxJHhurd0IGzDoCBtw6B1IHbDoG5nDQoNCioqS+G6v3QgcXXhuqM6KioNCg0KLSBCaeG7g3UgxJHhu5MgYmFvIGfhu5NtOg0KDQogICAtIE3hu5l0IHThuq1wIGjhu6NwIGPDoWMgxJFp4buDbSBtw6B1IMSR4buPLCBt4buXaSDEkWnhu4NtIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHPhuqNuIHBo4bqpbS4NCg0KICAgLSBUcuG7pWMgaG/DoG5oIGhp4buDbiB0aOG7iyB44bq/cCBo4bqhbmcgY+G7p2Egc+G6o24gcGjhuqltLg0KDQogICAtIFRy4bulYyB0dW5nIGhp4buDbiB0aOG7iyBjaGkgbmjDoW5oIGPhu6dhIHPhuqNuIHBo4bqpbS4NCg0KICAgLSBN4buZdCDEkcaw4budbmcgY29uZyBtw6B1IHbDoG5nIHRo4buDIGhp4buHbiBt4buRaSBxdWFuIGjhu4cgeHUgaMaw4bubbmcgZ2nhu69hIHjhur9wIGjhuqFuZyB2w6AgY2hpIG5ow6FuaC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTI6KiogDQoNCmBgYHtyfQ0KYSAlPiUgZ2dwbG90KGFlcyh4ID0gVW5pdC5wcmljZSwgeSA9IFByb2R1Y3QubGluZSkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICdyZWQnKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScsIGNvbG9yID0gJ3llbGxvdycpICsNCiAgZmFjZXRfd3JhcCh+QnJhbmNoKQ0KYGBgDQoNCioqS+G6v3QgcXXhuqM6KioNCg0KQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KLSBOaGnhu4F1IHBow6JuIMSRb+G6oW4sIG3hu5dpIHBow6JuIMSRb+G6oW4gdMawxqFuZyDhu6luZyB24bubaSBt4buZdCBjaGkgbmjDoW5oIChCcmFuY2gpLg0KDQotIFRyb25nIG3hu5dpIHBow6JuIMSRb+G6oW46DQoNCiAgIC0gQ8OhYyDEkWnhu4NtIG3DoHUgxJHhu48gxJHhuqFpIGRp4buHbiBjaG8gc+G6o24gcGjhuqltIHRodeG7mWMgY2hpIG5ow6FuaCDEkcOzLg0KDQogICAtIMSQxrDhu51uZyBjb25nIG3DoHUgdsOgbmcgdGjhu4MgaGnhu4duIHh1IGjGsOG7m25nIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgZ2nDoSB2w6AgZMOybmcgc+G6o24gcGjhuqltIGNobyBjaGkgbmjDoW5oIMSRw7MuDQoNCiMjICoqQmnhu4N1IMSR4buTIDEzOiBiaeG7g3UgxJHhu5MgY+G7mXQgc+G7rSBk4bulbmcgZ8OzaSBnZ3Bsb3QyIHbDoCBk4buvIGxp4buHdSB04burIHThu4dwIENTViAic3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IioqDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKSAgICAgICANCmRhdGEgPC0gcmVhZC5jc3YoIkQ6L0jDoC9zdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiKQ0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gUHJvZHVjdC5saW5lLCB5ID0gUmF0aW5nLCBmaWxsID0gUHJvZHVjdC5saW5lKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoIlJhdGluZyIpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIGPDonUgbOG7h25oOioqDQoNCi0gKipkYXRhIDwtIHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2Iik6KiogRMOybmcgbsOgeSDEkeG7jWMgZOG7ryBsaeG7h3UgdOG7qyB04buHcCBDU1YgInN1cGVybWFya2V0X3NhbGVzIC0gU2hlZXQxLmNzdiIgdsOgIGzGsHUgdHLhu68gbsOzIHbDoG8gYmnhur9uIGRhdGEuIEThu68gbGnhu4d1IHPhur0gxJHGsOG7o2MgxJHhu41jIGTGsOG7m2kgZOG6oW5nIGRhdGEgZnJhbWUuDQoNCi0gKipnZ3Bsb3QoZGF0YSwgYWVzKHggPSBQcm9kdWN0LmxpbmUsIHkgPSBSYXRpbmcsIGZpbGwgPSBQcm9kdWN0LmxpbmUpKToqKiBIw6BtIGdncGxvdCgpIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGto4bufaSB04bqhbyBt4buZdCBiaeG7g3UgxJHhu5MgbeG7m2kuIMSQ4buRaSBz4buRIGRhdGEgY2jhu4kgxJHhu4tuaCBk4buvIGxp4buHdSDEkcaw4bujYyBz4butIGThu6VuZy4gVHJvbmcgYWVzKCksIGNow7puZyB0YSBjaOG7iSDEkeG7i25oIGPDoWMgbWFwcGluZyBhZXN0aGV0aWNzICh0xrDGoW5nIOG7qW5nIHbhu5tpIGPDoWMgYmnhur9uKSBjaG8gdHLhu6VjIHggKHggPSBQcm9kdWN0LmxpbmUpLCB0cuG7pWMgeSAoeSA9IFJhdGluZyksIHbDoCBmaWxsIGNvbG9yIChmaWxsID0gUHJvZHVjdC5saW5lKS4gxJBp4buBdSBuw6B5IGPDsyBuZ2jEqWEgbMOgIGNow7puZyB0YSBz4bq9IHbhur0gY+G7mXQgZOG7sWEgdHLDqm4gY+G7mXQgIlByb2R1Y3QubGluZSIsIGNoaeG7gXUgY2FvIGPhu6dhIGPDoWMgY+G7mXQgc+G6vSDEkcaw4bujYyB4w6FjIMSR4buLbmggYuG7n2kgY+G7mXQgIlJhdGluZyIsIHbDoCBtw6B1IHPhuq9jIGPhu6dhIGPDoWMgY+G7mXQgc+G6vSB0xrDGoW5nIOG7qW5nIHbhu5tpIGdpw6EgdHLhu4sgY+G7p2EgIlByb2R1Y3QubGluZSIuDQoNCi0gKipnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iik6KiogSMOgbSBnZW9tX2JhcigpIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHThuqFvIHJhIGJp4buDdSDEkeG7kyBj4buZdC4gVGhhbSBz4buRIHN0YXQgPSAiaWRlbnRpdHkiIGNobyBiaeG6v3QgcuG6sW5nIGNoaeG7gXUgY2FvIGPhu6dhIGPDoWMgY+G7mXQgc+G6vSDEkcaw4bujYyB4w6FjIMSR4buLbmggdHLhu7FjIHRp4bq/cCB04burIGThu68gbGnhu4d1Lg0KDQotICoqc2NhbGVfeV9jb250aW51b3VzKCJSYXRpbmciKToqKiBIw6BtIHNjYWxlX3lfY29udGludW91cygpIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIMSR4bq3dCBuaMOjbiBjaG8gdHLhu6VjIHkgY+G7p2EgYmnhu4N1IMSR4buTLCB24bubaSBuaMOjbiBsw6AgIlJhdGluZyIuDQoNCioqS+G6v3QgcXXhuqM6KioNCk3DoyBuw6B5IHPhur0gdOG6oW8gYmnhu4N1IMSR4buTIHRoYW5oIHRo4buDIGhp4buHbiB0cuG7sWMgcXVhbiB44bq/cCBo4bqhbmcgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBkw7JuZyBz4bqjbiBwaOG6qW0ga2jDoWMgbmhhdSB0cm9uZyBk4buvIGxp4buHdSBiw6FuIGjDoG5nIHNpw6p1IHRo4buLLiANCg0KLSBUcuG7pWMgWDogVHLhu6VjIG7DoHkgc+G6vSBoaeG7g24gdGjhu4sgY8OhYyBkYW5oIG3hu6VjIGR1eSBuaOG6pXQgdOG7qyBj4buZdCBQcm9kdWN0LmxpbmUsIMSR4bqhaSBkaeG7h24gY2hvIGPDoWMgZMOybmcgc+G6o24gcGjhuqltIGtow6FjIG5oYXUgdHJvbmcgZOG7ryBsaeG7h3UgDQoNCi0gVHLhu6VjIFk6IFRy4bulYyBuw6B5IHPhur0gxJHGsOG7o2MgZMOhbiBuaMOjbiAiUmF0aW5nIiB2w6Agc+G6vSBoaeG7g24gdGjhu4sgcGjhuqFtIHZpIHjhur9wIGjhuqFuZyBz4buRIHRyb25nIGThu68gbGnhu4d1IA0KDQotIFRoYW5oOiBCaeG7g3UgxJHhu5Mgc+G6vSBjw7MgbeG7mXQgdGhhbmggZOG7jWMgY2hvIG3hu5dpIGRhbmggbeG7pWMgZMOybmcgc+G6o24gcGjhuqltLiBDaGnhu4F1IGNhbyBj4bunYSBt4buXaSB0aGFuaCBz4bq9IHTGsMahbmcg4bupbmcgduG7m2kgeOG6v3AgaOG6oW5nIHRydW5nIGLDrG5oIGNobyBkw7JuZyBz4bqjbiBwaOG6qW0gxJHDsyAoZ2nhuqMgc+G7rSBzdGF0ID0gImlkZW50aXR5IiB0w61uaCB0b8OhbiBnacOhIHRy4buLIHRydW5nIGLDrG5oKS4NCg0KLSBNw6B1IHPhuq9jOiBN4buXaSB0aGFuaCBz4bq9IMSRxrDhu6NjIHTDtCBi4bqxbmcgbeG7mXQgbcOgdSBraMOhYyBuaGF1IHbDoCBjw6FjIG3DoHUgc+G6vSDEkcaw4bujYyBnw6FuIGThu7FhIHRyw6puIGRhbmggbeG7pWMgZMOybmcgc+G6o24gcGjhuqltICjEkcaw4bujYyB4w6FjIMSR4buLbmggYuG7n2kgeeG6v3UgdOG7kSB0aOG6qW0gbeG7uSBmaWxsID0gUHJvZHVjdC5saW5lKS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTQ6KiogdOG6oW8gbeG7mXQgbG/huqF0IGPDoWMgaGlzdG9ncmFtLCBt4buXaSBoaXN0b2dyYW0gYmnhu4N1IGRp4buFbiBwaMOibiBwaOG7kWkgY+G7p2EgYmnhur9uICJSYXRpbmciICh44bq/cCBo4bqhbmcpIHRyb25nIGThu68gbGnhu4d1Lg0KDQpgYGB7cn0NCnFwbG90KFJhdGluZywgZGF0YSA9IHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IiksIGZhY2V0cyA9IC4gfiBQcm9kdWN0LmxpbmUsIGdlb20gPSAiaGlzdG9ncmFtIiwgYmlud2lkdGggPSAxKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqUmF0aW5nOioqIGJp4bq/biBz4buRIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHbhur0gaGlzdG9ncmFtLCDEkeG6oWkgZGnhu4duIGNobyB44bq/cCBo4bqhbmcgY+G7p2EgY8OhYyBz4bqjbiBwaOG6qW0uDQoNCi0gKipkYXRhID0gcmVhZC5jc3YoIkQ6L0jDoC9zdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiKToqKiDEkMOieSBsw6AgZOG7ryBsaeG7h3UgYuG6oW4gc+G7rSBk4bulbmcgxJHhu4MgduG6vSBoaXN0b2dyYW0uDQpIw6BtIHJlYWQuY3N2KCkgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgxJHhu41jIGThu68gbGnhu4d1IHThu6sgdOG7h3AgQ1NWICJzdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiLg0KDQotICoqZmFjZXRzID0gLiB+IFByb2R1Y3QubGluZToqKiBUaGFtIHPhu5EgbsOgeSB4w6FjIMSR4buLbmggY8OhY2ggZOG7ryBsaeG7h3UgxJHGsOG7o2MgcGjDom4gY2hpYSB0aMOgbmggY8OhYyBt4bq3dCBow6BuZyAoZmFjZXRzKSB0csOqbiBiaeG7g3UgxJHhu5MuIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCAuIH4gUHJvZHVjdC5saW5lIGNo4buJIHJhIHLhurFuZyBt4buXaSBt4bq3dCBow6BuZyAoZmFjZXQpIHPhur0gdMawxqFuZyDhu6luZyB24bubaSBt4buZdCBsb+G6oWkgc+G6o24gcGjhuqltIMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBi4bufaSBiaeG6v24gIlByb2R1Y3QubGluZSIuDQoNCi0gKipnZW9tID0gImhpc3RvZ3JhbSI6KiogTG/huqFpIGjDrG5oIGjhu41jIGLhuqFuIG114buRbiBz4butIGThu6VuZyDEkeG7gyB24bq9IGJp4buDdSDEkeG7ky4gVHJvbmcgdHLGsOG7nW5nIGjhu6NwIG7DoHksIGLhuqFuIMSRYW5nIHPhu60gZOG7pW5nIGhpc3RvZ3JhbSDEkeG7gyBiaeG7g3UgZGnhu4VuIHBow6JuIHBo4buRaSBj4bunYSBk4buvIGxp4buHdS4NCg0KLSAqKmJpbndpZHRoID0gMToqKiDEkOG7mSBy4buZbmcgY+G7p2EgY8OhYyBiaW4gKG5nxINuKSB0cm9uZyBoaXN0b2dyYW0uIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCDEkeG7mSBy4buZbmcgY+G7p2EgbeG7l2kgYmluIMSRxrDhu6NjIHRoaeG6v3QgbOG6rXAgbMOgIDEsIGPDsyBuZ2jEqWEgbMOgIG3hu5dpIGJpbiBz4bq9IGJhbyBn4buTbSBjw6FjIGdpw6EgdHLhu4sgeOG6v3AgaOG6oW5nIHRyb25nIGtob+G6o25nIGPDsyDEkeG7mSBy4buZbmcgbMOgIDEuDQoNCioqS+G6v3QgcXXhuqM6KioNCkJp4buDdSDEkeG7kyB04bqhbyByYSBz4bq9IGhp4buDbiB0aOG7iyBwaMOibiBwaOG7kWkgeOG6v3AgaOG6oW5nIChSYXRpbmcpIGNobyB04burbmcgZMOybmcgc+G6o24gcGjhuqltIChQcm9kdWN0LmxpbmUpIHJpw6puZyBiaeG7h3QuIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCi0gTmhp4buBdSBwaMOibiDEkW/huqFuOiBN4buXaSBwaMOibiDEkW/huqFuIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IGTDsm5nIHPhuqNuIHBo4bqpbS4NCg0KLSBUcuG7pWMgWTogSGnhu4NuIHRo4buLIHjhur9wIGjhuqFuZyBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBjaG8gbeG7l2kgeOG6v3AgaOG6oW5nLg0KDQotIEPhu5l0OiBN4buXaSBj4buZdCB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY8OzIHjhur9wIGjhuqFuZyBj4bulIHRo4buDIHRyb25nIG3hu5l0IGTDsm5nIHPhuqNuIHBo4bqpbS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTU6KiogDQoNCmBgYHtyfQ0KcXBsb3QoIFJhdGluZywgVW5pdC5wcmljZSwgZGF0YSA9IHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IiksIGNvbG9yID0gQnJhbmNoKQ0KYGBgDQoNCioqR2nhuqNpIHRow61jaCBjw6J1IGzhu4duaDoqKg0KDQotICoqUmF0aW5nLCBVbml0LnByaWNlOioqIMSQw6J5IGzDoCBjw6FjIGJp4bq/biBi4bqhbiBtdeG7kW4gduG6vSB0csOqbiB0cuG7pWMgeCB2w6AgdHLhu6VjIHksIHTGsMahbmcg4bupbmcgbMOgICJSYXRpbmciIHbDoCAiVW5pdC5wcmljZSIuDQoNCi0gKipkYXRhID0gcmVhZC5jc3YoIkQ6L0jDoC9zdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiKToqKiDEkMOieSBsw6AgZOG7ryBsaeG7h3UgYuG6oW4gc+G7rSBk4bulbmcgxJHhu4MgduG6vSBiaeG7g3UgxJHhu5MuIEjDoG0gcmVhZC5jc3YoKSDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyDEkeG7jWMgZOG7ryBsaeG7h3UgdOG7qyB04buHcCBDU1YgInN1cGVybWFya2V0X3NhbGVzIC0gU2hlZXQxLmNzdiIuDQoNCi0gKipjb2xvciA9IEJyYW5jaDoqKiBUaGFtIHPhu5EgbsOgeSBjaOG7iSDEkeG7i25oIGPDoWNoIGJp4buDdSDEkeG7kyBwaMOibiB0w6FuIHPhur0gxJHGsOG7o2MgbcOgdSBz4bqvYyBow7NhIGThu7FhIHRyw6puIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uICJCcmFuY2giLiBD4bulIHRo4buDLCBt4buXaSDEkWnhu4NtIGThu68gbGnhu4d1IHPhur0gxJHGsOG7o2MgbcOgdSBz4bqvYyBraMOhYyBuaGF1IHTGsMahbmcg4bupbmcgduG7m2kgZ2nDoSB0cuG7iyBj4bunYSBiaeG6v24gIkJyYW5jaCIuDQoNCioqS+G6v3QgcXXhuqM6KioNCkJp4buDdSDEkeG7kyB04bqhbyByYSBz4bq9IGhp4buDbiB0aOG7iyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIHjhur9wIGjhuqFuZyAoUmF0aW5nKSB2w6AgZ2nDoSBiw6FuIChVbml0LnByaWNlKSBj4bunYSBjw6FjIHPhuqNuIHBo4bqpbS4gQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KLSBUcuG7pWMgWTogSGnhu4NuIHRo4buLIHjhur9wIGjhuqFuZyBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBnacOhIGLDoW4gc+G6o24gcGjhuqltLg0KDQotIMSQaeG7g20gZOG7ryBsaeG7h3U6IE3hu5dpIMSRaeG7g20gxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQgc+G6o24gcGjhuqltLCDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIGNoaSBuaMOhbmggKEJyYW5jaCkgY+G7p2Egc+G6o24gcGjhuqltIMSRw7MuDQoNCiMjICoqQmnhu4N1IMSR4buTIDE2OioqDQoNCmBgYHtyfQ0KcXBsb3QoUmF0aW5nLCBkYXRhID0gcmVhZC5jc3YoIkQ6L0jDoC9zdXBlcm1hcmtldF9zYWxlcyAtIFNoZWV0MS5jc3YiKSwgZ2VvbSA9ICJoaXN0b2dyYW0iLCBiaW53aWR0aCA9IDAuMDUpDQpgYGANCioqS+G6v3QgcXXhuqM6KioNCkJp4buDdSDEkeG7kyB04bqhbyByYSBz4bq9IGhp4buDbiB0aOG7iyBwaMOibiBwaOG7kWkgeOG6v3AgaOG6oW5nIChSYXRpbmcpIGPhu6dhIHPhuqNuIHBo4bqpbS4gQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KLSBUcuG7pWMgWTogSGnhu4NuIHRo4buLIHjhur9wIGjhuqFuZyBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBjaG8gbeG7l2kgeOG6v3AgaOG6oW5nLg0KDQotIEPhu5l0OiBN4buXaSBj4buZdCB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY8OzIHjhur9wIGjhuqFuZyBu4bqxbSB0cm9uZyBraG/huqNuZyBj4bulIHRo4buDLg0KDQojIyAqKkJp4buDdSDEkeG7kyAxNzoqKiANCg0KYGBge3J9DQpxcGxvdChRdWFudGl0eSwgZGF0YSA9IHJlYWQuY3N2KCJEOi9Iw6Avc3VwZXJtYXJrZXRfc2FsZXMgLSBTaGVldDEuY3N2IiksIGdlb20gPSAiZGVuc2l0eSIpDQpgYGANCioqS+G6v3QgcXXhuqM6KioNCkJp4buDdSDEkeG7kyB04bqhbyByYSBz4bq9IGhp4buDbiB0aOG7iyBt4bqtdCDEkeG7mSBwaMOibiBwaOG7kWkgY+G7p2Egc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gKFF1YW50aXR5KSDEkcaw4bujYyBiw6FuLiBCaeG7g3UgxJHhu5MgYmFvIGfhu5NtOg0KDQotIFRy4bulYyBYOiBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFk6IEhp4buDbiB0aOG7iyBt4bqtdCDEkeG7mSwgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgZOG7ryBsaeG7h3UgdOG6rXAgdHJ1bmcgdOG6oWkgbeG7l2kgZ2nDoSB0cuG7iyBj4bunYSBRdWFudGl0eS4NCg0KLSDEkMaw4budbmcgY29uZzogxJDGsOG7nW5nIGNvbmcgbcaw4bujdCBtw6AgdGjhu4MgaGnhu4duIG3huq10IMSR4buZIHBow6JuIHBo4buRaSBj4bunYSBk4buvIGxp4buHdS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTg6KioNCg0KYGBge3J9DQpnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGRhdGEgPSBmaWx0ZXIoYSwgQnJhbmNoID09ICdBJyksIGFlcyh4ID0gVW5pdC5wcmljZSksIGJpbndpZHRoID0gNSwgZmlsbCA9ICdwaW5rJykgKw0KICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gZmlsdGVyKGEsIEJyYW5jaCA9PSAnQycpLCBhZXMoeCA9IFVuaXQucHJpY2UpLCBiaW53aWR0aCA9IDUsIGZpbGwgPSAnc2t5Ymx1ZScpDQoNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2ggY8OidSBs4buHbmg6KioNCg0KLSAqKmdncGxvdCgpOioqIELhuq90IMSR4bqndSBt4buZdCDEkeG7kWkgdMaw4bujbmcgZ2dwbG90MiBt4bubaSBtw6Aga2jDtG5nIGPhuqduIGvhur90IG7hu5FpIHbhu5tpIGThu68gbGnhu4d1IGPhu6UgdGjhu4MuDQoNCi0gKipnZW9tX2hpc3RvZ3JhbSgpOioqIGNow7puZyB0YSB0aMOqbSBoYWkgbOG7m3AgZOG7ryBsaeG7h3UgaGlzdG9ncmFtLCBt4buXaSBs4bubcCB0xrDGoW5nIOG7qW5nIHbhu5tpIG3hu5l0IGNoaSBuaMOhbmgga2jDoWMgbmhhdS4NCg0KLSAqKmRhdGEgPSBmaWx0ZXIoYSwgQnJhbmNoID09ICdBJykgdsOgIGRhdGEgPSBmaWx0ZXIoYSwgQnJhbmNoID09ICdDJyk6KiogTOG7jWMgZOG7ryBsaeG7h3UgdOG7qyBhIChnaeG6oyBz4butIGzDoCBkYXRhIGZyYW1lIGNo4bupYSBk4buvIGxp4buHdSkgxJHhu4MgY2jhu4kgbOG6pXkgY8OhYyBxdWFuIHPDoXQgY8OzIGdpw6EgdHLhu4sgIkJyYW5jaCIgdMawxqFuZyDhu6luZyAoIkEiIHbDoCAiQyIgbOG6p24gbMaw4bujdCkuIMSQaeG7gXUgbsOgeSBnacO6cCBjaMO6bmcgdGEgY2jhu4kgduG6vSBoaXN0b2dyYW0gY2hvIGPDoWMgcXVhbiBzw6F0IHRodeG7mWMgY8OhYyBjaGkgbmjDoW5oIG7DoHkuDQoNCi0gKiphZXMoeCA9IFVuaXQucHJpY2UpOioqIFThuqFvIG1hcHBpbmcgY2hvIGJp4bq/biBVbml0LnByaWNlIHRyw6puIHRy4bulYyB4IGPhu6dhIGhpc3RvZ3JhbS4NCg0KLSAqKmJpbndpZHRoID0gNToqKiBYw6FjIMSR4buLbmggxJHhu5kgcuG7mW5nIGPhu6dhIGPDoWMgYmluIChuZ8SDbikgdHJvbmcgaGlzdG9ncmFtLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgxJHhu5kgcuG7mW5nIGPhu6dhIG3hu5dpIGJpbiDEkcaw4bujYyDEkeG6t3QgbMOgIDUuDQoNCi0gKipmaWxsOioqIFjDoWMgxJHhu4tuaCBtw6B1IHPhuq9jIGNobyBoaXN0b2dyYW0gY+G7p2EgbeG7l2kgY2hpIG5ow6FuaC4gSGlzdG9ncmFtIGNobyBjaGkgbmjDoW5oICJBIiBz4bq9IGPDsyBtw6B1IGjhu5NuZyAoInBpbmsiKSB2w6AgaGlzdG9ncmFtIGNobyBjaGkgbmjDoW5oICJDIiBz4bq9IGPDsyBtw6B1IHhhbmggZGEgdHLhu51pICgic2t5Ymx1ZSIpLg0KDQoqKkvhur90IHF14bqjOioqDQpCaeG7g3UgxJHhu5MgdOG6oW8gcmEgc+G6vSBoaeG7g24gdGjhu4sgaGFpIGJp4buDdSDEkeG7kyBow6xuaCBj4buZdCBjaOG7k25nIGzDqm4gbmhhdSwgc28gc8OhbmggcGjDom4gcGjhu5FpIGdpw6EgYsOhbiAoVW5pdC5wcmljZSkgY+G7p2EgaGFpIGNoaSBuaMOhbmggQSB2w6AgQy4gQmnhu4N1IMSR4buTIGJhbyBn4buTbToNCg0KLSBUcuG7pWMgWDogSGnhu4NuIHRo4buLIGdpw6EgYsOhbiBz4bqjbiBwaOG6qW0uDQoNCi0gVHLhu6VjIFk6IEhp4buDbiB0aOG7iyBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBjaG8gbeG7l2kgZ2nDoSBiw6FuLg0KDQotIEPhu5l0OiBIYWkgbmjDs20gY+G7mXQsIG3hu5l0IG3DoHUgaOG7k25nIChjaGkgbmjDoW5oIEEpIHbDoCBt4buZdCBtw6B1IHhhbmggZGEgdHLhu51pIChjaGkgbmjDoW5oIEMpLCB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY2hvIG3hu5dpIGdpw6EgYsOhbiBj4bunYSB04burbmcgY2hpIG5ow6FuaC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgMTk6KioNCg0KYGBge3J9DQphICU+JSBnZ3Bsb3QoYWVzKHggPSBVbml0LnByaWNlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDMsIGZpbGwgPSAnZ3JlZW4nLCBjb2xvciA9ICdyZWQnKSArDQogIGZhY2V0X3dyYXAofkJyYW5jaCkNCmBgYA0KKipL4bq/dCBxdeG6ozoqKg0KQmnhu4N1IMSR4buTIHThuqFvIHJhIHPhur0gaGnhu4NuIHRo4buLIG3hu5l0IGxv4bqhdCBjw6FjIGJp4buDdSDEkeG7kyBow6xuaCBj4buZdCwgbeG7l2kgYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBwaMOibiBwaOG7kWkgZ2nDoSBiw6FuIChVbml0LnByaWNlKSBjaG8gdOG7q25nIGNoaSBuaMOhbmggKEJyYW5jaCkuIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCi0gTmhp4buBdSBwaMOibiDEkW/huqFuOiBN4buXaSBwaMOibiDEkW/huqFuIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IGNoaSBuaMOhbmguDQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBnacOhIGLDoW4gc+G6o24gcGjhuqltLg0KDQotIFRy4bulYyBZOiBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY2hvIG3hu5dpIGdpw6EgYsOhbi4NCg0KLSBD4buZdDogQ8OhYyBj4buZdCB0cm9uZyBt4buXaSBwaMOibiDEkW/huqFuIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBjaG8gbeG7l2kgZ2nDoSBiw6FuIGPhu6dhIHThu6tuZyBjaGkgbmjDoW5oLg0KDQojIyAqKkJp4buDdSDEkeG7kyAyMDoqKg0KDQpgYGB7cn0NCmEgJT4lIGdncGxvdChhZXMoeCA9IFVuaXQucHJpY2UsIGZpbGwgPSBQcm9kdWN0LmxpbmUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSkNCmBgYA0KDQoqKkvhur90IHF14bqjOioqDQpCaeG7g3UgxJHhu5MgdOG6oW8gcmEgc+G6vSBoaeG7g24gdGjhu4sgbeG7mXQgYmnhu4N1IMSR4buTIGjDrG5oIGPhu5l0IHbhu5tpIGPDoWMgY+G7mXQgxJHGsOG7o2MgdMO0IG3DoHUgdGhlbyBkw7JuZyBz4bqjbiBwaOG6qW0gKFByb2R1Y3QubGluZSkuIEJp4buDdSDEkeG7kyBiYW8gZ+G7k206DQoNCi0gVHLhu6VjIFg6IEhp4buDbiB0aOG7iyBnacOhIGLDoW4gc+G6o24gcGjhuqltLg0KDQotIFRy4bulYyBZOiBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gY2hvIG3hu5dpIGdpw6EgYsOhbi4NCg0KLSBD4buZdDogQ8OhYyBj4buZdCDEkcaw4bujYyB0w7QgbcOgdSB0aGVvIGTDsm5nIHPhuqNuIHBo4bqpbSwgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgc+G6o24gcGjhuqltIGNobyBt4buXaSBnacOhIGLDoW4gY+G7p2EgdOG7q25nIGTDsm5nIHPhuqNuIHBo4bqpbS4=