1 PHẦN 1: TÌM HIểU VÀ CHUẨN BỊ DỮ LIỆU

1.1 Đọc và làm quen với dữ liệu

# Đọc file
library("csv")
## Warning: package 'csv' was built under R version 4.3.3
data <- read.csv("D:/Downloads/sales_data.csv", header = T)

# Hiển thị cấu trúc dữ liệu
str(data)
## 'data.frame':    76000 obs. of  16 variables:
##  $ Date              : chr  "2022-01-01" "2022-01-01" "2022-01-01" "2022-01-01" ...
##  $ Store.ID          : chr  "S001" "S001" "S001" "S001" ...
##  $ Product.ID        : chr  "P0001" "P0002" "P0003" "P0004" ...
##  $ Category          : chr  "Electronics" "Clothing" "Clothing" "Electronics" ...
##  $ Region            : chr  "North" "North" "North" "North" ...
##  $ Inventory.Level   : int  195 117 247 139 152 209 118 244 115 192 ...
##  $ Units.Sold        : int  102 117 114 45 65 60 81 42 88 70 ...
##  $ Units.Ordered     : int  252 249 612 102 271 0 335 0 139 300 ...
##  $ Price             : num  72.7 80.2 62.9 87.6 54.4 ...
##  $ Discount          : int  5 15 10 10 0 0 5 5 5 10 ...
##  $ Weather.Condition : chr  "Snowy" "Snowy" "Snowy" "Snowy" ...
##  $ Promotion         : int  0 1 1 0 0 0 0 0 0 0 ...
##  $ Competitor.Pricing: num  85.7 92 60.1 85.2 51.6 ...
##  $ Seasonality       : chr  "Winter" "Winter" "Winter" "Winter" ...
##  $ Epidemic          : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Demand            : int  115 229 157 52 59 55 94 61 129 69 ...
# Hiển thị vài dòng đầu và cuối
head(data)
##         Date Store.ID Product.ID    Category Region Inventory.Level Units.Sold
## 1 2022-01-01     S001      P0001 Electronics  North             195        102
## 2 2022-01-01     S001      P0002    Clothing  North             117        117
## 3 2022-01-01     S001      P0003    Clothing  North             247        114
## 4 2022-01-01     S001      P0004 Electronics  North             139         45
## 5 2022-01-01     S001      P0005   Groceries  North             152         65
## 6 2022-01-01     S001      P0006        Toys  North             209         60
##   Units.Ordered Price Discount Weather.Condition Promotion Competitor.Pricing
## 1           252 72.72        5             Snowy         0              85.73
## 2           249 80.16       15             Snowy         1              92.02
## 3           612 62.94       10             Snowy         1              60.08
## 4           102 87.63       10             Snowy         0              85.19
## 5           271 54.41        0             Snowy         0              51.63
## 6             0 35.53        0             Snowy         0              40.01
##   Seasonality Epidemic Demand
## 1      Winter        0    115
## 2      Winter        0    229
## 3      Winter        0    157
## 4      Winter        0     52
## 5      Winter        0     59
## 6      Winter        0     55
tail(data)
##             Date Store.ID Product.ID  Category Region Inventory.Level
## 75995 2024-01-30     S005      P0015 Groceries  North             520
## 75996 2024-01-30     S005      P0016      Toys  North             233
## 75997 2024-01-30     S005      P0017      Toys  North             137
## 75998 2024-01-30     S005      P0018  Clothing  North             197
## 75999 2024-01-30     S005      P0019 Furniture  North             125
## 76000 2024-01-30     S005      P0020      Toys  North             126
##       Units.Sold Units.Ordered  Price Discount Weather.Condition Promotion
## 75995        116             0  48.62       10             Snowy         0
## 75996         63             0  29.80        5             Snowy         0
## 75997        115           141  42.92        5             Snowy         0
## 75998         44             0  17.81       10             Snowy         0
## 75999         58             0 151.72        0             Snowy         0
## 76000         63            59  25.78       10             Snowy         0
##       Competitor.Pricing Seasonality Epidemic Demand
## 75995              53.71      Winter        0    122
## 75996              32.23      Winter        0     64
## 75997              40.73      Winter        0    137
## 75998              19.41      Winter        0     68
## 75999             143.71      Winter        0     84
## 76000              29.32      Winter        0     73
# Chuyển các biến định tính phù hợp sang factor
factor <- c("Date", "Store.ID", "Product.ID", "Category", "Region",
                 "Weather.Condition", "Seasonality")

# Kiểm tra biến nào tồn tại trong data
factor <- intersect(factor, names(data))

# Chuyển sang factor
data[factor] <- lapply(data[factor], as.factor)

# Kiểm tra lại cấu trúc
str(data)
## 'data.frame':    76000 obs. of  16 variables:
##  $ Date              : Factor w/ 760 levels "2022-01-01","2022-01-02",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ Store.ID          : Factor w/ 5 levels "S001","S002",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ Product.ID        : Factor w/ 20 levels "P0001","P0002",..: 1 2 3 4 5 6 7 8 9 10 ...
##  $ Category          : Factor w/ 5 levels "Clothing","Electronics",..: 2 1 1 2 4 5 4 2 1 3 ...
##  $ Region            : Factor w/ 4 levels "East","North",..: 2 2 2 2 2 2 2 2 2 2 ...
##  $ Inventory.Level   : int  195 117 247 139 152 209 118 244 115 192 ...
##  $ Units.Sold        : int  102 117 114 45 65 60 81 42 88 70 ...
##  $ Units.Ordered     : int  252 249 612 102 271 0 335 0 139 300 ...
##  $ Price             : num  72.7 80.2 62.9 87.6 54.4 ...
##  $ Discount          : int  5 15 10 10 0 0 5 5 5 10 ...
##  $ Weather.Condition : Factor w/ 4 levels "Cloudy","Rainy",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ Promotion         : int  0 1 1 0 0 0 0 0 0 0 ...
##  $ Competitor.Pricing: num  85.7 92 60.1 85.2 51.6 ...
##  $ Seasonality       : Factor w/ 4 levels "Autumn","Spring",..: 4 4 4 4 4 4 4 4 4 4 ...
##  $ Epidemic          : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Demand            : int  115 229 157 52 59 55 94 61 129 69 ...

1.2 Tổng quan về bộ dữ liệu

Bộ dữ liệu Retail Store Inventory and Demand Forecasting bao gồm 76,000 quan sát với 16 biến mô tả các giao dịch bán hàng của các cửa hàng bán lẻ khác nhau. Dữ liệu này ghi lại chi tiết thông tin về tồn kho, số lượng bán ra, các yếu tố ảnh hưởng như khuyến mãi, thời tiết, giá cạnh tranh, dịch bệnh cùng nhiều thông tin khác liên quan đến hoạt động bán lẻ.

Mục đích chính của bộ dữ liệu là:

  • Dự báo nhu cầu sản phẩm (Demand Forecasting),

  • Phân tích tồn kho,

  • Đánh giá ảnh hưởng của các yếu tố bên ngoài như khuyến mãi, thời tiết, dịch bệnh (COVID-19 giả lập) đến nhu cầu tiêu dùng,

  • Mô phỏng hoạt động bán lẻ trong bối cảnh có dịch bệnh để hỗ trợ ra quyết định quản lý tồn kho và điều phối hàng hóa hiệu quả.

Giải thích chi tiết các biến trong bộ dữ liệu

Tên biến Ý nghĩa
Date Ngày diễn ra giao dịch (định dạng YYYY-MM-DD).
Store.ID Mã định danh duy nhất của cửa hàng (ví dụ: S001, S002).
Product.ID Mã định danh duy nhất của sản phẩm.
Category Loại sản phẩm (ví dụ: Electronics, Clothing, Toys, Furniture, Groceries,…).
Region Khu vực cửa hàng (North, South, East, West).
Inventory.Level Số lượng sản phẩm còn trong kho tại thời điểm ghi nhận.
Units.Sold Số lượng sản phẩm đã bán trong ngày.
Units.Ordered Số lượng hàng đã đặt thêm để bổ sung kho.
Price Giá bán sản phẩm trong ngày (theo đơn vị tiền tệ).
Discount Mức chiết khấu áp dụng cho sản phẩm (tính theo %).
Weather.Condition Tình trạng thời tiết trong ngày giao dịch (ví dụ: Snowy, Cloudy, Rainy, Sunny,…).
Promotion Có áp dụng khuyến mãi hay không (1 = có, 0 = không).
Competitor.Pricing Giá bán của sản phẩm tương tự từ đối thủ cạnh tranh.
Seasonality Mùa trong năm (Winter, Spring, Summer, Fall).
Epidemic Tình trạng dịch bệnh (0 = không có dịch, 1 = có dịch, mô phỏng COVID-19).
Demand Nhu cầu sản phẩm ước tính trong ngày, là biến mục tiêu cần dự báo.

1.3 Phân loại biến theo kiểu dữ liệu

Dữ liệu Định tính

  • Category

  • Region

  • Weather.Condition

  • Promotion

  • Seasonality

  • Epidemic

Dữ liệu Định lượng

  • Inventory.Level

  • Units.Sold

  • Units.Ordered

  • Price

  • Discount

  • Competitor.Pricing

  • Demand

1.4 Kiểm tra giá trị NA

Trước khi tiến hành phân tích dữ liệu, chúng ta cần kiểm tra và xử lý các giá trị bị thiếu nhằm đảm bảo độ chính xác và tính toàn vẹn của kết quả phân tích.

sum(is.na(data))
## [1] 0
which(is.na(data))
## integer(0)

Cả hai lệnh đều trả về kết quả cho thấy không tồn tại giá trị thiếu:

  • sum(is.na(data)) trả về 0, nghĩa là không có giá trị NA nào.

  • which(is.na(data)) trả về integer(0), nghĩa là không có vị trí nào chứa NA.

Điều này cho phép chúng ta tiếp tục các bước xử lý dữ liệu và phân tích mà không cần thực hiện bước xử lý giá trị thiếu.

1.5 Tạo bộ dữ liệu chỉ có biến định tính

dataDT <- data[, c("Category", "Region",
                  "Weather.Condition", "Promotion", "Seasonality", "Epidemic")]
str(dataDT)
## 'data.frame':    76000 obs. of  6 variables:
##  $ Category         : Factor w/ 5 levels "Clothing","Electronics",..: 2 1 1 2 4 5 4 2 1 3 ...
##  $ Region           : Factor w/ 4 levels "East","North",..: 2 2 2 2 2 2 2 2 2 2 ...
##  $ Weather.Condition: Factor w/ 4 levels "Cloudy","Rainy",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ Promotion        : int  0 1 1 0 0 0 0 0 0 0 ...
##  $ Seasonality      : Factor w/ 4 levels "Autumn","Spring",..: 4 4 4 4 4 4 4 4 4 4 ...
##  $ Epidemic         : int  0 0 0 0 0 0 0 0 0 0 ...

2 PHẦN 2: PHÂN TÍCH MÔ TẢ MỘT BIẾN ĐỊNH TÍNH

2.1 Biến Category

Lập bảng tần số và tần suất

#Bảng tần số
table(dataDT$Category)
## 
##    Clothing Electronics   Furniture   Groceries        Toys 
##       12160        9120       13680       30400       10640
#Bảng tần suất
table(dataDT$Category)/sum(table(dataDT$Category))
## 
##    Clothing Electronics   Furniture   Groceries        Toys 
##        0.16        0.12        0.18        0.40        0.14

Biểu đồ cột

library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
# Chuẩn bị dữ liệu từ bảng tần số
category <- as.data.frame(table(dataDT$Category))
colnames(category) <- c("Category", "Frequency")

# Vẽ biểu đồ cột có số trên mỗi cột
ggplot(category, aes(x = Category, y = Frequency, fill = Category)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Frequency), vjust = -0.5, size = 4) +
  labs(title = "Biểu đồ cột: Tần số theo loại sản phẩm (Category)",
       x = "Loại sản phẩm",
       y = "Tần số") +
  theme_minimal() +
  theme(legend.position = "none")

Biểu đồ tròn

category$Percentage <- round(100 * category$Frequency / sum(category$Frequency), 1)
ggplot(category, aes(x = "", y = Frequency, fill = Category)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  labs(title = "Biểu đồ tròn: Tỷ lệ loại sản phẩm (Category)") +
  theme_void()

Nhận xét

  • Dựa vào bảng tần số, phần lớn sản phẩm trong dữ liệu thuộc nhóm Groceries với 30400 mục, chiếm khoảng 40% tổng số quan sát. Theo sau là Furniture với 13680 mục (~18%), và Clothing với 12160 mục (~16%). Nhóm Toys có 10640 mục (~14%), trong khi Electronics là nhóm có số lượng thấp nhất với 9120 mục (~12%).

  • Biểu đồ cột thể hiện rõ rằng Groceries là loại sản phẩm chiếm ưu thế trong tập dữ liệu, với số lượng vượt trội so với các nhóm còn lại. Biểu đồ tròn giúp trực quan hóa tỷ lệ phân bổ, cho thấy phần hình tròn của Groceries lớn hơn đáng kể. Điều này phản ánh rằng nhu cầu hoặc tần suất giao dịch liên quan đến thực phẩm cao hơn đáng kể, trong khi các sản phẩm như ElectronicsToys có tỷ trọng nhỏ hơn trong cơ cấu loại sản phẩm.

2.2 Biến Region

Lập bảng tần số và tần suất

# Bảng tần số
table(dataDT$Region)
## 
##  East North South  West 
## 15200 30400 15200 15200
# Bảng tần suất
table(dataDT$Region)/sum(table(dataDT$Region))
## 
##  East North South  West 
##   0.2   0.4   0.2   0.2

Biểu đồ cột

region <- as.data.frame(table(dataDT$Region))
colnames(region) <- c("Region", "Frequency")
ggplot(region, aes(x = Region, y = Frequency, fill = Region)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Frequency), vjust = -0.5, size = 4) +
  labs(title = "Biểu đồ cột: Tần số theo khu vực (Region)",
       x = "Khu vực",
       y = "Tần số") +
  theme_minimal() +
  theme(legend.position = "none")

Biểu đồ tròn

region$Percentage <- round(100 * region$Frequency / sum(region$Frequency), 1)
ggplot(region, aes(x = "", y = Frequency, fill = Region)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
   labs(title = "Biểu đồ tròn: Tỷ lệ khu vực (Region)") +
  theme_void()

Nhận xét

  • Dựa vào bảng tần số, phần lớn quan sát trong dữ liệu đến từ khu vực North với 30400 mục, chiếm khoảng 40% tổng số quan sát. Các khu vực East, SouthWest có cùng số lượng là 15200 mục (~20%).

  • Biểu đồ cột thể hiện rõ rằng North là khu vực chiếm ưu thế trong tập dữ liệu, với số lượng vượt trội so với ba khu vực còn lại. Biểu đồ tròn giúp trực quan hóa tỷ lệ phân bổ, cho thấy phần hình tròn của North lớn hơn đáng kể. Điều này phản ánh rằng hoạt động hoặc tần suất giao dịch tại khu vực phía Bắc diễn ra nhiều hơn so với các khu vực khác, trong khi East, SouthWest có vai trò tương đương nhau về quy mô trong cơ cấu khu vực.

2.3 Biến Weather.Condition

Lập bảng tần số và tần suất

table(dataDT$Weather.Condition)
## 
## Cloudy  Rainy  Snowy  Sunny 
##  24360  17500  11160  22980
table(dataDT$Weather.Condition)/sum(table(dataDT$Weather.Condition))
## 
##    Cloudy     Rainy     Snowy     Sunny 
## 0.3205263 0.2302632 0.1468421 0.3023684

Biểu đồ cột

weather <- as.data.frame(table(dataDT$Weather.Condition))
colnames(weather) <- c("Weather.Condition", "Frequency")

ggplot(weather, aes(x = Weather.Condition, y = Frequency, fill = Weather.Condition)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Frequency), vjust = -0.5, size = 4) +
  labs(title = "Biểu đồ cột: Tình trạng thời tiết (Weather.Condition)",
       x = "Thời tiết",
       y = "Tần số") +
  theme_minimal() +
  theme(legend.position = "none")

Biểu đồ tròn

weather$Percentage <- round(100 * weather$Frequency / sum(weather$Frequency), 1)
ggplot(weather, aes(x = "", y = Frequency, fill = Weather.Condition)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  labs(title = "Biểu đồ tròn: Tỷ lệ tình trạng thời tiết") +
  theme_void()

Nhận xét

  • Dựa vào bảng tần số, phần lớn các quan sát rơi vào điều kiện thời tiết Cloudy với 24360 mục, chiếm khoảng 32% tổng số. Theo sau là Sunny với 22980 mục (~30%), và Rainy với 17500 mục (~23%). Trong khi đó, điều kiện Snowy xuất hiện ít nhất với 11160 mục (~15%).

  • Biểu đồ cột thể hiện rõ rằng Cloudy là trạng thái thời tiết phổ biến nhất trong dữ liệu, với số lượng vượt trội hơn hẳn các trạng thái khác. Sunny cũng chiếm tỷ lệ lớn, chỉ thấp hơn một chút so với Cloudy. Ngược lại, Snowy có tần suất thấp nhất. Biểu đồ tròn giúp trực quan hóa tỷ lệ này, thể hiện rõ phần diện tích lớn nhất thuộc về Cloudy, tiếp theo là SunnyRainy. Những kết quả này cho thấy dữ liệu thu thập được chủ yếu diễn ra trong điều kiện thời tiết nhiều mây và nắng, trong khi điều kiện tuyết ít gặp hơn.

2.4 Biến Seasonality

Lập bảng tần số và tần suất

table(dataDT$Seasonality)
## 
## Autumn Spring Summer Winter 
##  18200  18400  18400  21000
table(dataDT$Seasonality)/sum(table(dataDT$Seasonality))
## 
##    Autumn    Spring    Summer    Winter 
## 0.2394737 0.2421053 0.2421053 0.2763158

Biểu đồ cột

season <- as.data.frame(table(dataDT$Seasonality))
colnames(season) <- c("Season", "Frequency")
ggplot(season, aes(x = Season, y = Frequency, fill = Season)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Frequency), vjust = -0.5, size = 4) +
  labs(title = "Biểu đồ cột: Mùa trong năm (Seasonality)",
       x = "Mùa",
       y = "Tần số") +
  theme_minimal() +
  theme(legend.position = "none")

Biểu đồ tròn

season$Percentage <- round(100 * season$Frequency / sum(season$Frequency), 1)
ggplot(season, aes(x = "", y = Frequency, fill = Season)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  labs(title = "Biểu đồ tròn: Phân bố theo mùa (Seasonality)") +
  theme_void()

Nhận xét

  • Dựa vào bảng tần số, phần lớn các quan sát rơi vào mùa Winter với 21000 mục, chiếm khoảng 28% tổng số. Ba mùa còn lại có số lượng quan sát khá gần nhau, lần lượt là SpringSummer với 18400 và 18400 mục (~24% và 24%), và Autumn với 18200 mục (~24%).

  • Biểu đồ cột thể hiện rõ rằng Winter là mùa chiếm tỷ lệ quan sát lớn nhất trong dữ liệu, vượt trội hơn một chút so với các mùa còn lại. Ba mùa Spring, SummerAutumn có số lượng quan sát khá đồng đều, chỉ chênh lệch nhẹ. Biểu đồ tròn trực quan hóa tỷ lệ này rất rõ ràng, với diện tích lớn nhất thuộc về Winter, tiếp theo là ba mùa còn lại có tỷ lệ khá tương đương nhau. Những kết quả này cho thấy dữ liệu được thu thập trải đều trong các mùa, với một lượng quan sát nhỉnh hơn vào mùa đông.

2.5 Biến Promotion

Lập bảng tần số và tần suất

table(dataDT$Promotion)
## 
##     0     1 
## 51000 25000
table(dataDT$Promotion)/sum(table(dataDT$Promotion))
## 
##         0         1 
## 0.6710526 0.3289474

Biểu đồ cột

promo <- as.data.frame(table(dataDT$Promotion))
colnames(promo) <- c("Promotion", "Frequency")
ggplot(promo, aes(x = Promotion, y = Frequency, fill = Promotion)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Frequency), vjust = -0.5) +
  labs(title = "Tần số áp dụng khuyến mãi (Promotion)", x = "Promotion (0=No,1=Yes)", y = "Tần số") +
  theme_minimal() +
  theme(legend.position = "none")

Nhận xét

  • Dựa vào bảng tần số, số lượng quan sát không áp dụng khuyến mãi (Promotion = 0) là 51000 mục, chiếm khoảng 67.1% tổng số. Trong khi đó, số quan sát áp dụng khuyến mãi (Promotion = 1) là 25000 mục, chiếm khoảng 32.9%.

  • Biểu đồ tần số thể hiện rõ rằng phần lớn giao dịch không có khuyến mãi, nhưng khuyến mãi vẫn chiếm tỷ lệ đáng kể trong hoạt động bán hàng.

2.6 Biến Epidemic

Lập bảng tần số và tần suất

table(dataDT$Epidemic)
## 
##     0     1 
## 60800 15200
table(dataDT$Epidemic)/sum(table(dataDT$Epidemic))
## 
##   0   1 
## 0.8 0.2

Biểu đồ cột

epi <- as.data.frame(table(dataDT$Epidemic))
colnames(epi) <- c("Epidemic", "Frequency")
ggplot(epi, aes(x = Epidemic, y = Frequency, fill = Epidemic)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Frequency), vjust = -0.5) +
  labs(title = "Tần số dịch bệnh (Epidemic)", x = "Epidemic (0=No,1=Yes)", y = "Tần số") +
  theme_minimal() +
  theme(legend.position = "none")

Nhận xét

  • Theo bảng tần số, số quan sát không có dịch bệnh (Epidemic = 0) là 60800 mục, chiếm khoảng 80% tổng số. Các quan sát trong điều kiện có dịch bệnh (Epidemic = 1) là 15200 mục, chiếm khoảng 20%.

  • Dữ liệu cho thấy phần lớn giao dịch diễn ra trong điều kiện không có dịch bệnh, trong khi khoảng 20% giao dịch xảy ra trong bối cảnh dịch bệnh (mô phỏng COVID-19), cho phép phân tích tác động dịch bệnh tới hoạt động bán lẻ.

3 Phần 3: Ước lượng Khoảng và Kiểm định Giả thuyết cho Tỷ lệ

3.1 Biến Category

Mục tiêu

Thực hiện kiểm định để xác định xem tỷ lệ thuộc hạng mục “Groceries” trong biến Category có khác biệt so với 50% hay không.

Dữ liệu và biến quan tâm

  • Biến quan tâm: Category

  • Hạng mục quan tâm: "Groceries"

Tính toán tỷ lệ mẫu

# Số lượng cá thể thuộc Category = "Groceries"
sumGroceries <- sum(dataDT$Category == "Groceries")

# Tổng số cá thể trong dữ liệu
totalCategory <- length(dataDT$Category)

Thực hiện kiểm định tỷ lệ 1 mẫu

Giả thuyết kiểm định:

  • Giả thuyết H0: Tỷ lệ cá thể thuộc “Groceries” bằng 0.5

  • Giả thuyết H1: Tỷ lệ cá thể thuộc “Groceries” khác 0.5

# Kiểm định tỷ lệ 1 mẫu với giả thuyết p = 0.5
prop.test(x = sumGroceries, n = totalCategory, p = 0.5, conf.level = 0.95, correct = TRUE)
## 
##  1-sample proportions test with continuity correction
## 
## data:  sumGroceries out of totalCategory, null probability 0.5
## X-squared = 3039.6, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.3965156 0.4034945
## sample estimates:
##   p 
## 0.4

Kết quả kiểm định:

  • Giá trị thống kê Chi-squared: 3039.6

  • Bậc tự do (df): 1

  • p-value: < 2.2e-16

  • Khoảng tin cậy 95% cho tỷ lệ “Groceries”: (0.3965, 0.4035)

  • Ước lượng tỷ lệ “Groceries” từ mẫu: 0.40 (tức 40%)

Kết luận:

Với mức ý nghĩa 5%, vì p-value rất nhỏ (< 0.05), ta bác bỏ giả thuyết H0. Điều này chứng tỏ tỷ lệ cá thể thuộc hạng mục “Groceries” trong dữ liệu khác biệt có ý nghĩa thống kê so với tỷ lệ 50%. Cụ thể, tỷ lệ thực tế khoảng 40%, thấp hơn đáng kể so với 50%.

3.2 Biến Region

Mục tiêu

Thực hiện kiểm định để xác định xem tỷ lệ thuộc vùng “North” trong biến Region có khác biệt so với 40% hay không.

Dữ liệu và biến quan tâm

  • Biến quan tâm: Region

  • Hạng mục quan tâm: "North"

Tính toán tỷ lệ mẫu

# Số lượng cá thể thuộc Region = "North"
sumNorth <- sum(dataDT$Region == "North")

# Tổng số cá thể trong dữ liệu
totalRegion <- length(dataDT$Region)

Thực hiện kiểm định tỷ lệ 1 mẫu

Giả thuyết kiểm định:

  • Giả thuyết H0: Tỷ lệ cá thể thuộc “North” bằng 0.4

  • Giả thuyết H1: ỷ lệ cá thể thuộc “North” khác 0.4

# Kiểm định tỷ lệ 1 mẫu với giả thuyết p = 0.4
prop.test(x = sumNorth, n = totalRegion, p = 0.4, conf.level = 0.95, correct = TRUE)
## 
##  1-sample proportions test without continuity correction
## 
## data:  sumNorth out of totalRegion, null probability 0.4
## X-squared = 0, df = 1, p-value = 1
## alternative hypothesis: true p is not equal to 0.4
## 95 percent confidence interval:
##  0.3965222 0.4034879
## sample estimates:
##   p 
## 0.4

Kết quả kiểm định:

  • Giá trị thống kê Chi-squared: 0

  • Bậc tự do (df): 1

  • p-value: 1

  • Khoảng tin cậy 95% cho tỷ lệ “North”: (0.3965, 0.4035)

  • Ước lượng tỷ lệ “North” từ mẫu: 0.40 (tức 40%)

Kết luận:

Với mức ý nghĩa 5%, vì p-value = 1 > 0.05, ta không bác bỏ giả thuyết H0. Điều này cho thấy tỷ lệ cá thể thuộc vùng “North” trong dữ liệu không khác biệt có ý nghĩa thống kê so với tỷ lệ 40%. Tỷ lệ thực tế ước lượng là 40%, phù hợp với tỉ lệ giả định.

4 PHẦN 4: PHÂN TÍCH MỐI QUAN HỆ GIỮA HAI BIẾN ĐỊNH TÍNH

4.1 Cặp biến Weather.Condition và Region

4.1.1 Thống kê mô tả cặp biến Weather.Condition và Region

Bảng tần số chéo

weather_region <- table(dataDT$Weather.Condition, dataDT$Region)
weather_region
##         
##          East North South West
##   Cloudy 4920  9440  5260 4740
##   Rainy  3580  7480  3320 3120
##   Snowy  2400  4280  2140 2340
##   Sunny  4300  9200  4480 5000

Nhận xét

  • Điều kiện thời tiết Cloudy (nhiều mây): Xuất hiện phổ biến nhất ở vùng North với 9440 lượt quan sát, gần gấp đôi so với các vùng khác như East (4920), South (5260), và West (4740).

  • Thời tiết Rainy (mưa): Cũng có tần suất cao nhất ở vùng North (7480 lượt), trong khi các vùng East, South, và West dao động từ 3120 đến 3580 lượt.

  • Thời tiết Snowy (tuyết): Chủ yếu tập trung ở vùng North (4280), cao gần gấp đôi so với vùng South (2140) – điều này phản ánh đặc điểm khí hậu lạnh hơn của miền Bắc.

  • Thời tiết Sunny (nắng): Ghi nhận số lượng lớn ở North (9200) và West (5000), trong khi hai vùng còn lại – East (4300) và South (4480) – có số lượng gần tương đương.

  • So sánh giữa các vùng:

    • North là vùng có số lượng quan sát cao nhất ở tất cả các loại thời tiết. Điều này có thể cho thấy:

      • Đây là khu vực được quan sát, thu thập dữ liệu nhiều hơn.

      • Hoặc khí hậu nơi đây đa dạng và biến động rõ rệt theo mùa.

    • SouthWest có số lượng quan sát thấp hơn, đặc biệt là với thời tiết Snowy, có thể liên quan đến đặc điểm khí hậu ấm hơn, ít tuyết hơn so với các vùng còn lại.

Bảng tần suất chéo

prop.table(weather_region)
##         
##                East      North      South       West
##   Cloudy 0.06473684 0.12421053 0.06921053 0.06236842
##   Rainy  0.04710526 0.09842105 0.04368421 0.04105263
##   Snowy  0.03157895 0.05631579 0.02815789 0.03078947
##   Sunny  0.05657895 0.12105263 0.05894737 0.06578947

Nhận xét bảng tần suất chéo

  • Weather.Condition = Cloudy (nhiều mây): Chiếm tỷ lệ cao nhất tại vùng North (12.42%), cao hơn đáng kể so với các vùng South (6.92%), East (6.47%), và West (6.24%). Điều này cho thấy thời tiết nhiều mây xảy ra thường xuyên hơn ở khu vực miền Bắc.

  • Weather.Condition = Rainy (mưa): Vẫn ghi nhận tỷ lệ cao nhất tại vùng North (9.84%), trong khi ba vùng còn lại dao động thấp hơn: East (4.71%), South (4.37%), West (4.11%).

  • Weather.Condition = Snowy (tuyết): Rõ ràng tập trung nhiều ở North (5.63%), cao hơn gần gấp đôi so với South (2.82%) và nhỉnh hơn các vùng East (3.16%), West (3.08%). Điều này phù hợp với đặc điểm khí hậu lạnh ở miền Bắc.

  • Weather.Condition = Sunny (nắng): Vùng North vẫn dẫn đầu với tỷ lệ 12.11%, tiếp theo là West (6.58%), South (5.89%) và East (5.66%).

  • So sánh tổng thể giữa các vùng:

    • North là vùng có tỷ lệ xuất hiện cao nhất ở mọi điều kiện thời tiết, chiếm ưu thế rõ rệt, phản ánh sự đa dạng khí hậu hoặc mức độ ghi nhận dữ liệu lớn hơn so với các vùng khác.

    • Các vùng East, South, và West có phân bố khá tương đồng và thấp hơn đáng kể so với North, đặc biệt ở các điều kiện như RainySnowy.

Nhìn chung, North là vùng nổi bật với tần suất thời tiết đa dạng và cao, trong khi các vùng khác có mức xuất hiện đều và thấp hơn, phản ánh sự khác biệt về điều kiện tự nhiên hoặc quy mô thu thập dữ liệu.

Vẽ đồ thị

df_weather_region <- as.data.frame(weather_region)
colnames(df_weather_region) <- c("Weather.Condition", "Region", "Count")
ggplot(df_weather_region, aes(x = Region, y = Count, fill = Weather.Condition)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Số lượng quan sát theo Region và Weather.Condition", 
       x = "Region", y = "Count") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

4.1.2 Kiểm định thống kê

Giả thuyết kiểm định::

  • H0: Hai biến Weather.Condition và Region độc lập

  • H1: Hai biến Weather.Condition và Region có mối liên hệ

Thực hiện kiểm định Chi- bình phương

chisq_result <- chisq.test(weather_region)
chisq_result
## 
##  Pearson's Chi-squared test
## 
## data:  weather_region
## X-squared = 216.45, df = 9, p-value < 2.2e-16

Kết quả kiểm định Chi-squared

  • Giá trị thống kê Chi-squared: X-squared = 216.45

  • Bậc tự do: df = 9

  • Giá trị p-value: p-value < 2.2e-16

Kết luận

Vì giá trị p rất nhỏ (p-value < 0.05), ta bác bỏ giả thuyết không (H0). Điều này cho thấy có mối liên hệ có ý nghĩa thống kê giữa điều kiện thời tiết (Weather.Condition) và vùng miền (Region).

4.2 Cặp biến region và epidemic

Tính Relative Risk

library(epitools)

# 1. Lọc dữ liệu chỉ lấy 2 vùng North và South
subset_data <- subset(dataDT, Region %in% c("North", "South"))
subset_data$Region <- droplevels(subset_data$Region)

# 2. Tạo bảng tần số chéo
region_epidemic <- table(subset_data$Region, subset_data$Epidemic)
addmargins(region_epidemic)
##        
##             0     1   Sum
##   North 24320  6080 30400
##   South 12160  3040 15200
##   Sum   36480  9120 45600
# 3. Tính Rủi ro tương đối (Relative Risk)
riskratio(region_epidemic)
## $data
##        
##             0    1 Total
##   North 24320 6080 30400
##   South 12160 3040 15200
##   Total 36480 9120 45600
## 
## $measure
##        risk ratio with 95% C.I.
##         estimate     lower    upper
##   North        1        NA       NA
##   South        1 0.9618079 1.039709
## 
## $p.value
##        two-sided
##         midp.exact fisher.exact chi.square
##   North         NA           NA         NA
##   South  0.9993396            1          1
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Kết quả tính Rủi ro tương đối (Relative Risk)

  • Rủi ro mắc dịch ở North = 6,080 / 30,400 = 0.20

  • Rủi ro mắc dịch ở South = 3,040 / 15,200 = 0.20

  • RR (South so với North) = 1.000

    → Khoảng tin cậy 95%: [0.9618 ; 1.0397]

  • Giá trị p-value = 0.999 (từ kiểm định Fisher’s Exact và Chi-squared)

Kết luận và Nhận xét

  • Rủi ro tương đối (RR = 1) cho thấy khả năng mắc dịch (Epidemic = 1) giữa hai vùng NorthSouth là tương đương.

  • Khoảng tin cậy 95% của RR bao gồm 1 → Không có sự khác biệt có ý nghĩa thống kê.

  • Giá trị p-value cao (p ≈ 1) → Không bác bỏ giả thuyết H₀, tức là không có mối liên hệ đáng kể giữa vùng miền (Region) và tình trạng dịch bệnh (Epidemic) trong hai khu vực này.

Tính odd và oddratio

# 4. Tính Odds và Odds Ratio thủ công
odd_North <- region_epidemic["North", "1"] / region_epidemic["North", "0"]
odd_South <- region_epidemic["South", "1"] / region_epidemic["South", "0"]

cat("Odds (North):", odd_North, "\n")
## Odds (North): 0.25
cat("Odds (South):", odd_South, "\n")
## Odds (South): 0.25
odds_ratio <- odd_South / odd_North
cat("Odds Ratio (South vs. North):", odds_ratio, "\n")
## Odds Ratio (South vs. North): 1
# 5. Hoặc dùng epitools để tính Odds Ratio kèm khoảng tin cậy
oddsratio(region_epidemic, method = "midp")
## $data
##        
##             0    1 Total
##   North 24320 6080 30400
##   South 12160 3040 15200
##   Total 36480 9120 45600
## 
## $measure
##        odds ratio with 95% C.I.
##         estimate     lower    upper
##   North 1.000000        NA       NA
##   South 1.000022 0.9524335 1.049819
## 
## $p.value
##        two-sided
##         midp.exact fisher.exact chi.square
##   North         NA           NA         NA
##   South  0.9993396            1          1
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"

Kết luận và Nhận xét

  • Odds mắc dịch giữa hai vùng NorthSouth là bằng nhau (OR = 1), cho thấy khả năng mắc dịch tương đương.

  • Khoảng tin cậy 95% của Odds Ratio bao gồm 1 → không có sự khác biệt có ý nghĩa thống kê.

  • Giá trị p-value rất cao (p ≈ 1) → không có bằng chứng bác bỏ giả thuyết H₀, tức không có mối liên hệ đáng kể giữa vùng miền (Region) và tình trạng dịch bệnh (Epidemic) trong hai khu vực này.

LS0tDQp0aXRsZTogIk5oaWVtdnUyIg0KYXV0aG9yOiAiVHLhu4tuaCBUaOG7iyBUaHUgSMOgIg0KZGF0ZTogIjIwMjUtMDUtMjQiDQpvdXRwdXQ6DQogaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogeWVzDQogICAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojICoqUEjhuqZOIDE6IFTDjE0gSEnhu4NVIFbDgCBDSFXhuqhOIELhu4ogROG7riBMSeG7hlUqKg0KDQojIyAqKsSQ4buNYyB2w6AgbMOgbSBxdWVuIHbhu5tpIGThu68gbGnhu4d1KioNCg0KYGBge3J9DQojIMSQ4buNYyBmaWxlDQpsaWJyYXJ5KCJjc3YiKQ0KZGF0YSA8LSByZWFkLmNzdigiRDovRG93bmxvYWRzL3NhbGVzX2RhdGEuY3N2IiwgaGVhZGVyID0gVCkNCg0KIyBIaeG7g24gdGjhu4sgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3UNCnN0cihkYXRhKQ0KDQojIEhp4buDbiB0aOG7iyB2w6BpIGTDsm5nIMSR4bqndSB2w6AgY3Xhu5FpDQpoZWFkKGRhdGEpDQoNCnRhaWwoZGF0YSkNCg0KIyBDaHV54buDbiBjw6FjIGJp4bq/biDEkeG7i25oIHTDrW5oIHBow7kgaOG7o3Agc2FuZyBmYWN0b3INCmZhY3RvciA8LSBjKCJEYXRlIiwgIlN0b3JlLklEIiwgIlByb2R1Y3QuSUQiLCAiQ2F0ZWdvcnkiLCAiUmVnaW9uIiwNCiAgICAgICAgICAgICAgICAgIldlYXRoZXIuQ29uZGl0aW9uIiwgIlNlYXNvbmFsaXR5IikNCg0KIyBLaeG7g20gdHJhIGJp4bq/biBuw6BvIHThu5NuIHThuqFpIHRyb25nIGRhdGENCmZhY3RvciA8LSBpbnRlcnNlY3QoZmFjdG9yLCBuYW1lcyhkYXRhKSkNCg0KIyBDaHV54buDbiBzYW5nIGZhY3Rvcg0KZGF0YVtmYWN0b3JdIDwtIGxhcHBseShkYXRhW2ZhY3Rvcl0sIGFzLmZhY3RvcikNCg0KIyBLaeG7g20gdHJhIGzhuqFpIGPhuqV1IHRyw7pjDQpzdHIoZGF0YSkNCmBgYA0KIyMgKipU4buVbmcgcXVhbiB24buBIGLhu5kgZOG7ryBsaeG7h3UqKg0KDQpC4buZIGThu68gbGnhu4d1ICoqUmV0YWlsIFN0b3JlIEludmVudG9yeSBhbmQgRGVtYW5kIEZvcmVjYXN0aW5nKiogYmFvIGfhu5NtICoqNzYsMDAwIHF1YW4gc8OhdCoqIHbhu5tpICoqMTYgYmnhur9uKiogbcO0IHThuqMgY8OhYyBnaWFvIGThu4tjaCBiw6FuIGjDoG5nIGPhu6dhIGPDoWMgY+G7rWEgaMOgbmcgYsOhbiBs4bq7IGtow6FjIG5oYXUuIEThu68gbGnhu4d1IG7DoHkgZ2hpIGzhuqFpIGNoaSB0aeG6v3QgdGjDtG5nIHRpbiB24buBIHThu5NuIGtobywgc+G7kSBsxrDhu6NuZyBiw6FuIHJhLCBjw6FjIHnhur91IHThu5Eg4bqjbmggaMaw4bufbmcgbmjGsCBraHV54bq/biBtw6NpLCB0aOG7nWkgdGnhur90LCBnacOhIGPhuqFuaCB0cmFuaCwgZOG7i2NoIGLhu4duaCBjw7luZyBuaGnhu4F1IHRow7RuZyB0aW4ga2jDoWMgbGnDqm4gcXVhbiDEkeG6v24gaG/huqF0IMSR4buZbmcgYsOhbiBs4bq7Lg0KDQpN4bulYyDEkcOtY2ggY2jDrW5oIGPhu6dhIGLhu5kgZOG7ryBsaeG7h3UgbMOgOg0KDQotIEThu7EgYsOhbyBuaHUgY+G6p3Ugc+G6o24gcGjhuqltIChEZW1hbmQgRm9yZWNhc3RpbmcpLA0KDQotIFBow6JuIHTDrWNoIHThu5NuIGtobywNCg0KLSDEkMOhbmggZ2nDoSDhuqNuaCBoxrDhu59uZyBj4bunYSBjw6FjIHnhur91IHThu5EgYsOqbiBuZ2/DoGkgbmjGsCBraHV54bq/biBtw6NpLCB0aOG7nWkgdGnhur90LCBk4buLY2ggYuG7h25oIChDT1ZJRC0xOSBnaeG6oyBs4bqtcCkgxJHhur9uIG5odSBj4bqndSB0acOqdSBkw7luZywNCg0KLSBNw7QgcGjhu49uZyBob+G6oXQgxJHhu5luZyBiw6FuIGzhursgdHJvbmcgYuG7kWkgY+G6o25oIGPDsyBk4buLY2ggYuG7h25oIMSR4buDIGjhu5cgdHLhu6MgcmEgcXV54bq/dCDEkeG7i25oIHF14bqjbiBsw70gdOG7k24ga2hvIHbDoCDEkWnhu4F1IHBo4buRaSBow6BuZyBow7NhIGhp4buHdSBxdeG6oy4NCg0KKipHaeG6o2kgdGjDrWNoIGNoaSB0aeG6v3QgY8OhYyBiaeG6v24gdHJvbmcgYuG7mSBk4buvIGxp4buHdSoqDQoNCnwgVMOqbiBiaeG6v24gICAgICAgICAgICAgIHwgw50gbmdoxKlhICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCAqKkRhdGUqKiAgICAgICAgICAgICAgfCBOZ8OgeSBkaeG7hW4gcmEgZ2lhbyBk4buLY2ggKMSR4buLbmggZOG6oW5nIFlZWVktTU0tREQpLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKlN0b3JlLklEKiogICAgICAgICAgfCBNw6MgxJHhu4tuaCBkYW5oIGR1eSBuaOG6pXQgY+G7p2EgY+G7rWEgaMOgbmcgKHbDrSBk4bulOiBTMDAxLCBTMDAyKS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgKipQcm9kdWN0LklEKiogICAgICAgIHwgTcOjIMSR4buLbmggZGFuaCBkdXkgbmjhuqV0IGPhu6dhIHPhuqNuIHBo4bqpbS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKkNhdGVnb3J5KiogICAgICAgICAgfCBMb+G6oWkgc+G6o24gcGjhuqltICh2w60gZOG7pTogRWxlY3Ryb25pY3MsIENsb3RoaW5nLCBUb3lzLCBGdXJuaXR1cmUsIEdyb2NlcmllcywuLi4pLiAgICAgICAgICAgICAgICAgIHwNCnwgKipSZWdpb24qKiAgICAgICAgICAgIHwgS2h1IHbhu7FjIGPhu61hIGjDoG5nIChOb3J0aCwgU291dGgsIEVhc3QsIFdlc3QpLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8ICoqSW52ZW50b3J5LkxldmVsKiogICB8IFPhu5EgbMaw4bujbmcgc+G6o24gcGjhuqltIGPDsm4gdHJvbmcga2hvIHThuqFpIHRo4budaSDEkWnhu4NtIGdoaSBuaOG6rW4uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8ICoqVW5pdHMuU29sZCoqICAgICAgICB8IFPhu5EgbMaw4bujbmcgc+G6o24gcGjhuqltIMSRw6MgYsOhbiB0cm9uZyBuZ8OgeS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8ICoqVW5pdHMuT3JkZXJlZCoqICAgICB8IFPhu5EgbMaw4bujbmcgaMOgbmcgxJHDoyDEkeG6t3QgdGjDqm0gxJHhu4MgYuG7lSBzdW5nIGtoby4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKlByaWNlKiogICAgICAgICAgICAgfCBHacOhIGLDoW4gc+G6o24gcGjhuqltIHRyb25nIG5nw6B5ICh0aGVvIMSRxqFuIHbhu4sgdGnhu4FuIHThu4cpLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8ICoqRGlzY291bnQqKiAgICAgICAgICB8IE3hu6ljIGNoaeG6v3Qga2jhuqV1IMOhcCBk4bulbmcgY2hvIHPhuqNuIHBo4bqpbSAodMOtbmggdGhlbyAlKS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8ICoqV2VhdGhlci5Db25kaXRpb24qKiB8IFTDrG5oIHRy4bqhbmcgdGjhu51pIHRp4bq/dCB0cm9uZyBuZ8OgeSBnaWFvIGThu4tjaCAodsOtIGThu6U6IFNub3d5LCBDbG91ZHksIFJhaW55LCBTdW5ueSwuLi4pLiAgICAgICAgICAgIHwNCnwgKipQcm9tb3Rpb24qKiAgICAgICAgIHwgQ8OzIMOhcCBk4bulbmcga2h1eeG6v24gbcOjaSBoYXkga2jDtG5nICgxID0gY8OzLCAwID0ga2jDtG5nKS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgKipDb21wZXRpdG9yLlByaWNpbmcqKnwgR2nDoSBiw6FuIGPhu6dhIHPhuqNuIHBo4bqpbSB0xrDGoW5nIHThu7EgdOG7qyDEkeG7kWkgdGjhu6cgY+G6oW5oIHRyYW5oLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKlNlYXNvbmFsaXR5KiogICAgICAgfCBNw7lhIHRyb25nIG7Eg20gKFdpbnRlciwgU3ByaW5nLCBTdW1tZXIsIEZhbGwpLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgKipFcGlkZW1pYyoqICAgICAgICAgIHwgVMOsbmggdHLhuqFuZyBk4buLY2ggYuG7h25oICgwID0ga2jDtG5nIGPDsyBk4buLY2gsIDEgPSBjw7MgZOG7i2NoLCBtw7QgcGjhu49uZyBDT1ZJRC0xOSkuICAgICAgICAgICAgICAgICAgICAgICB8DQp8ICoqRGVtYW5kKiogICAgICAgICAgICB8IE5odSBj4bqndSBz4bqjbiBwaOG6qW0gxrDhu5tjIHTDrW5oIHRyb25nIG5nw6B5LCBsw6AgYmnhur9uIG3hu6VjIHRpw6p1IGPhuqduIGThu7EgYsOhby4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KIyMgKipQaMOibiBsb+G6oWkgYmnhur9uIHRoZW8ga2nhu4N1IGThu68gbGnhu4d1KioNCg0KKipE4buvIGxp4buHdSDEkOG7i25oIHTDrW5oKioNCg0KLSBDYXRlZ29yeSANCg0KLSBSZWdpb24gDQoNCi0gV2VhdGhlci5Db25kaXRpb24gDQoNCi0gUHJvbW90aW9uIA0KDQotIFNlYXNvbmFsaXR5IA0KDQotIEVwaWRlbWljIA0KDQoqKkThu68gbGnhu4d1IMSQ4buLbmggbMaw4bujbmcqKg0KDQotIEludmVudG9yeS5MZXZlbCANCg0KLSBVbml0cy5Tb2xkIA0KDQotIFVuaXRzLk9yZGVyZWQgDQoNCi0gUHJpY2UgDQoNCi0gRGlzY291bnQgDQoNCi0gQ29tcGV0aXRvci5QcmljaW5nIA0KDQotIERlbWFuZCANCg0KIyMgKipLaeG7g20gdHJhIGdpw6EgdHLhu4sgTkEqKg0KDQpUcsaw4bubYyBraGkgdGnhur9uIGjDoG5oIHBow6JuIHTDrWNoIGThu68gbGnhu4d1LCBjaMO6bmcgdGEgY+G6p24ga2nhu4NtIHRyYSB2w6AgeOG7rSBsw70gY8OhYyBnacOhIHRy4buLIGLhu4sgdGhp4bq/dSBuaOG6sW0gxJHhuqNtIGLhuqNvIMSR4buZIGNow61uaCB4w6FjIHbDoCB0w61uaCB0b8OgbiB24bq5biBj4bunYSBr4bq/dCBxdeG6oyBwaMOibiB0w61jaC4NCg0KYGBge3J9DQpzdW0oaXMubmEoZGF0YSkpDQp3aGljaChpcy5uYShkYXRhKSkNCmBgYA0KQ+G6oyBoYWkgbOG7h25oIMSR4buBdSB0cuG6oyB24buBIGvhur90IHF14bqjIGNobyB0aOG6pXkga2jDtG5nIHThu5NuIHThuqFpIGdpw6EgdHLhu4sgdGhp4bq/dToNCg0KLSAqKnN1bShpcy5uYShkYXRhKSkqKiB0cuG6oyB24buBIDAsIG5naMSpYSBsw6Aga2jDtG5nIGPDsyBnacOhIHRy4buLIE5BIG7DoG8uDQoNCi0gKip3aGljaChpcy5uYShkYXRhKSkqKiB0cuG6oyB24buBIGludGVnZXIoMCksIG5naMSpYSBsw6Aga2jDtG5nIGPDsyB24buLIHRyw60gbsOgbyBjaOG7qWEgTkEuDQoNCsSQaeG7gXUgbsOgeSBjaG8gcGjDqXAgY2jDum5nIHRhIHRp4bq/cCB04bulYyBjw6FjIGLGsOG7m2MgeOG7rSBsw70gZOG7ryBsaeG7h3UgdsOgIHBow6JuIHTDrWNoIG3DoCBraMO0bmcgY+G6p24gdGjhu7FjIGhp4buHbiBixrDhu5tjIHjhu60gbMO9IGdpw6EgdHLhu4sgdGhp4bq/dS4NCg0KIyMgKipU4bqhbyBi4buZIGThu68gbGnhu4d1IGNo4buJIGPDsyBiaeG6v24gxJHhu4tuaCB0w61uaCoqDQoNCmBgYHtyfQ0KZGF0YURUIDwtIGRhdGFbLCBjKCJDYXRlZ29yeSIsICJSZWdpb24iLA0KICAgICAgICAgICAgICAgICAgIldlYXRoZXIuQ29uZGl0aW9uIiwgIlByb21vdGlvbiIsICJTZWFzb25hbGl0eSIsICJFcGlkZW1pYyIpXQ0Kc3RyKGRhdGFEVCkNCmBgYA0KDQojICoqUEjhuqZOIDI6IFBIw4JOIFTDjUNIIE3DlCBU4bqiIE3hu5hUIEJJ4bq+TiDEkOG7ik5IIFTDjU5IKioNCg0KIyMgKipCaeG6v24gQ2F0ZWdvcnkqKg0KDQoqKkzhuq1wIGLhuqNuZyB04bqnbiBz4buRIHbDoCB04bqnbiBzdeG6pXQqKg0KYGBge3J9DQojQuG6o25nIHThuqduIHPhu5ENCnRhYmxlKGRhdGFEVCRDYXRlZ29yeSkNCiNC4bqjbmcgdOG6p24gc3XhuqV0DQp0YWJsZShkYXRhRFQkQ2F0ZWdvcnkpL3N1bSh0YWJsZShkYXRhRFQkQ2F0ZWdvcnkpKQ0KYGBgDQoqKkJp4buDdSDEkeG7kyBj4buZdCoqDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCiMgQ2h14bqpbiBi4buLIGThu68gbGnhu4d1IHThu6sgYuG6o25nIHThuqduIHPhu5ENCmNhdGVnb3J5IDwtIGFzLmRhdGEuZnJhbWUodGFibGUoZGF0YURUJENhdGVnb3J5KSkNCmNvbG5hbWVzKGNhdGVnb3J5KSA8LSBjKCJDYXRlZ29yeSIsICJGcmVxdWVuY3kiKQ0KDQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0IGPDsyBz4buRIHRyw6puIG3hu5dpIGPhu5l0DQpnZ3Bsb3QoY2F0ZWdvcnksIGFlcyh4ID0gQ2F0ZWdvcnksIHkgPSBGcmVxdWVuY3ksIGZpbGwgPSBDYXRlZ29yeSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXF1ZW5jeSksIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDQpICsNCiAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgY+G7mXQ6IFThuqduIHPhu5EgdGhlbyBsb+G6oWkgc+G6o24gcGjhuqltIChDYXRlZ29yeSkiLA0KICAgICAgIHggPSAiTG/huqFpIHPhuqNuIHBo4bqpbSIsDQogICAgICAgeSA9ICJU4bqnbiBz4buRIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCioqQmnhu4N1IMSR4buTIHRyw7JuKioNCmBgYHtyfQ0KY2F0ZWdvcnkkUGVyY2VudGFnZSA8LSByb3VuZCgxMDAgKiBjYXRlZ29yeSRGcmVxdWVuY3kgLyBzdW0oY2F0ZWdvcnkkRnJlcXVlbmN5KSwgMSkNCmdncGxvdChjYXRlZ29yeSwgYWVzKHggPSAiIiwgeSA9IEZyZXF1ZW5jeSwgZmlsbCA9IENhdGVnb3J5KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQgPSAwKSArDQogIGxhYnModGl0bGUgPSAiQmnhu4N1IMSR4buTIHRyw7JuOiBU4bu3IGzhu4cgbG/huqFpIHPhuqNuIHBo4bqpbSAoQ2F0ZWdvcnkpIikgKw0KICB0aGVtZV92b2lkKCkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0KioNCg0KLSBE4buxYSB2w6BvIGLhuqNuZyB04bqnbiBz4buRLCBwaOG6p24gbOG7m24gc+G6o24gcGjhuqltIHRyb25nIGThu68gbGnhu4d1IHRodeG7mWMgbmjDs20gKkdyb2NlcmllcyogduG7m2kgYHIgdGFibGUoZGF0YURUJENhdGVnb3J5KVsiR3JvY2VyaWVzIl1gIG3hu6VjLCBjaGnhur9tIGtob+G6o25nIGByIHJvdW5kKDEwMCAqIHRhYmxlKGRhdGFEVCRDYXRlZ29yeSlbIkdyb2NlcmllcyJdIC8gc3VtKHRhYmxlKGRhdGFEVCRDYXRlZ29yeSkpLCAwKWAlIHThu5VuZyBz4buRIHF1YW4gc8OhdC4gVGhlbyBzYXUgbMOgICpGdXJuaXR1cmUqIHbhu5tpIGByIHRhYmxlKGRhdGFEVCRDYXRlZ29yeSlbIkZ1cm5pdHVyZSJdYCBt4bulYyAofmByIHJvdW5kKDEwMCAqIHRhYmxlKGRhdGFEVCRDYXRlZ29yeSlbIkZ1cm5pdHVyZSJdIC8gc3VtKHRhYmxlKGRhdGFEVCRDYXRlZ29yeSkpLCAwKWAlKSwgdsOgICpDbG90aGluZyogduG7m2kgYHIgdGFibGUoZGF0YURUJENhdGVnb3J5KVsiQ2xvdGhpbmciXWAgbeG7pWMgKH5gciByb3VuZCgxMDAgKiB0YWJsZShkYXRhRFQkQ2F0ZWdvcnkpWyJDbG90aGluZyJdIC8gc3VtKHRhYmxlKGRhdGFEVCRDYXRlZ29yeSkpLCAwKWAlKS4gTmjDs20gKlRveXMqIGPDsyBgciB0YWJsZShkYXRhRFQkQ2F0ZWdvcnkpWyJUb3lzIl1gIG3hu6VjICh+YHIgcm91bmQoMTAwICogdGFibGUoZGF0YURUJENhdGVnb3J5KVsiVG95cyJdIC8gc3VtKHRhYmxlKGRhdGFEVCRDYXRlZ29yeSkpLCAwKWAlKSwgdHJvbmcga2hpICpFbGVjdHJvbmljcyogbMOgIG5ow7NtIGPDsyBz4buRIGzGsOG7o25nIHRo4bqlcCBuaOG6pXQgduG7m2kgYHIgdGFibGUoZGF0YURUJENhdGVnb3J5KVsiRWxlY3Ryb25pY3MiXWAgbeG7pWMgKH5gciByb3VuZCgxMDAgKiB0YWJsZShkYXRhRFQkQ2F0ZWdvcnkpWyJFbGVjdHJvbmljcyJdIC8gc3VtKHRhYmxlKGRhdGFEVCRDYXRlZ29yeSkpLCAwKWAlKS4NCg0KLSBCaeG7g3UgxJHhu5MgY+G7mXQgdGjhu4MgaGnhu4duIHLDtSBy4bqxbmcgKkdyb2NlcmllcyogbMOgIGxv4bqhaSBz4bqjbiBwaOG6qW0gY2hp4bq/bSDGsHUgdGjhur8gdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UsIHbhu5tpIHPhu5EgbMaw4bujbmcgdsaw4bujdCB0cuG7mWkgc28gduG7m2kgY8OhYyBuaMOzbSBjw7JuIGzhuqFpLiBCaeG7g3UgxJHhu5MgdHLDsm4gZ2nDunAgdHLhu7FjIHF1YW4gaMOzYSB04bu3IGzhu4cgcGjDom4gYuG7lSwgY2hvIHRo4bqleSBwaOG6p24gaMOsbmggdHLDsm4gY+G7p2EgKkdyb2NlcmllcyogbOG7m24gaMahbiDEkcOhbmcga+G7gy4gxJBp4buBdSBuw6B5IHBo4bqjbiDDoW5oIHLhurFuZyBuaHUgY+G6p3UgaG/hurdjIHThuqduIHN14bqldCBnaWFvIGThu4tjaCBsacOqbiBxdWFuIMSR4bq/biB0aOG7sWMgcGjhuqltIGNhbyBoxqFuIMSRw6FuZyBr4buDLCB0cm9uZyBraGkgY8OhYyBz4bqjbiBwaOG6qW0gbmjGsCAqRWxlY3Ryb25pY3MqIHbDoCAqVG95cyogY8OzIHThu7cgdHLhu41uZyBuaOG7jyBoxqFuIHRyb25nIGPGoSBj4bqldSBsb+G6oWkgc+G6o24gcGjhuqltLg0KDQojIyAqKkJp4bq/biBSZWdpb24qKg0KDQoqKkzhuq1wIGLhuqNuZyB04bqnbiBz4buRIHbDoCB04bqnbiBzdeG6pXQqKg0KYGBge3J9DQojIELhuqNuZyB04bqnbiBz4buRDQp0YWJsZShkYXRhRFQkUmVnaW9uKQ0KDQojIELhuqNuZyB04bqnbiBzdeG6pXQNCnRhYmxlKGRhdGFEVCRSZWdpb24pL3N1bSh0YWJsZShkYXRhRFQkUmVnaW9uKSkNCmBgYA0KKipCaeG7g3UgxJHhu5MgY+G7mXQqKg0KYGBge3J9DQpyZWdpb24gPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkYXRhRFQkUmVnaW9uKSkNCmNvbG5hbWVzKHJlZ2lvbikgPC0gYygiUmVnaW9uIiwgIkZyZXF1ZW5jeSIpDQpnZ3Bsb3QocmVnaW9uLCBhZXMoeCA9IFJlZ2lvbiwgeSA9IEZyZXF1ZW5jeSwgZmlsbCA9IFJlZ2lvbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXF1ZW5jeSksIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDQpICsNCiAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgY+G7mXQ6IFThuqduIHPhu5EgdGhlbyBraHUgduG7sWMgKFJlZ2lvbikiLA0KICAgICAgIHggPSAiS2h1IHbhu7FjIiwNCiAgICAgICB5ID0gIlThuqduIHPhu5EiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQoqKkJp4buDdSDEkeG7kyB0csOybioqDQpgYGB7cn0NCnJlZ2lvbiRQZXJjZW50YWdlIDwtIHJvdW5kKDEwMCAqIHJlZ2lvbiRGcmVxdWVuY3kgLyBzdW0ocmVnaW9uJEZyZXF1ZW5jeSksIDEpDQpnZ3Bsb3QocmVnaW9uLCBhZXMoeCA9ICIiLCB5ID0gRnJlcXVlbmN5LCBmaWxsID0gUmVnaW9uKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQgPSAwKSArDQogICBsYWJzKHRpdGxlID0gIkJp4buDdSDEkeG7kyB0csOybjogVOG7tyBs4buHIGtodSB24buxYyAoUmVnaW9uKSIpICsNCiAgdGhlbWVfdm9pZCgpDQpgYGANCg0KKipOaOG6rW4geMOpdCoqDQoNCi0gROG7sWEgdsOgbyBi4bqjbmcgdOG6p24gc+G7kSwgcGjhuqduIGzhu5tuIHF1YW4gc8OhdCB0cm9uZyBk4buvIGxp4buHdSDEkeG6v24gdOG7qyBraHUgduG7sWMgKk5vcnRoKiB24bubaSBgciB0YWJsZShkYXRhRFQkUmVnaW9uKVsiTm9ydGgiXWAgbeG7pWMsIGNoaeG6v20ga2hv4bqjbmcgYHIgcm91bmQoMTAwICogdGFibGUoZGF0YURUJFJlZ2lvbilbIk5vcnRoIl0gLyBzdW0odGFibGUoZGF0YURUJFJlZ2lvbikpLCAwKWAlIHThu5VuZyBz4buRIHF1YW4gc8OhdC4gQ8OhYyBraHUgduG7sWMgKkVhc3QqLCAqU291dGgqIHbDoCAqV2VzdCogY8OzIGPDuW5nIHPhu5EgbMaw4bujbmcgbMOgIGByIHRhYmxlKGRhdGFEVCRSZWdpb24pWyJFYXN0Il1gIG3hu6VjICh+YHIgcm91bmQoMTAwICogdGFibGUoZGF0YURUJFJlZ2lvbilbIkVhc3QiXSAvIHN1bSh0YWJsZShkYXRhRFQkUmVnaW9uKSksIDApYCUpLg0KDQotIEJp4buDdSDEkeG7kyBj4buZdCB0aOG7gyBoaeG7h24gcsO1IHLhurFuZyAqTm9ydGgqIGzDoCBraHUgduG7sWMgY2hp4bq/bSDGsHUgdGjhur8gdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UsIHbhu5tpIHPhu5EgbMaw4bujbmcgdsaw4bujdCB0cuG7mWkgc28gduG7m2kgYmEga2h1IHbhu7FjIGPDsm4gbOG6oWkuIEJp4buDdSDEkeG7kyB0csOybiBnacO6cCB0cuG7sWMgcXVhbiBow7NhIHThu7cgbOG7hyBwaMOibiBi4buVLCBjaG8gdGjhuqV5IHBo4bqnbiBow6xuaCB0csOybiBj4bunYSAqTm9ydGgqIGzhu5tuIGjGoW4gxJHDoW5nIGvhu4MuIMSQaeG7gXUgbsOgeSBwaOG6o24gw6FuaCBy4bqxbmcgaG/huqF0IMSR4buZbmcgaG/hurdjIHThuqduIHN14bqldCBnaWFvIGThu4tjaCB04bqhaSBraHUgduG7sWMgcGjDrWEgQuG6r2MgZGnhu4VuIHJhIG5oaeG7gXUgaMahbiBzbyB24bubaSBjw6FjIGtodSB24buxYyBraMOhYywgdHJvbmcga2hpICpFYXN0KiwgKlNvdXRoKiB2w6AgKldlc3QqIGPDsyB2YWkgdHLDsiB0xrDGoW5nIMSRxrDGoW5nIG5oYXUgduG7gSBxdXkgbcO0IHRyb25nIGPGoSBj4bqldSBraHUgduG7sWMuDQoNCiMjICoqQmnhur9uIFdlYXRoZXIuQ29uZGl0aW9uKioNCg0KKipM4bqtcCBi4bqjbmcgdOG6p24gc+G7kSB2w6AgdOG6p24gc3XhuqV0KioNCmBgYHtyfQ0KdGFibGUoZGF0YURUJFdlYXRoZXIuQ29uZGl0aW9uKQ0KdGFibGUoZGF0YURUJFdlYXRoZXIuQ29uZGl0aW9uKS9zdW0odGFibGUoZGF0YURUJFdlYXRoZXIuQ29uZGl0aW9uKSkNCmBgYA0KDQoqKkJp4buDdSDEkeG7kyBj4buZdCoqDQpgYGB7cn0NCndlYXRoZXIgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkYXRhRFQkV2VhdGhlci5Db25kaXRpb24pKQ0KY29sbmFtZXMod2VhdGhlcikgPC0gYygiV2VhdGhlci5Db25kaXRpb24iLCAiRnJlcXVlbmN5IikNCg0KZ2dwbG90KHdlYXRoZXIsIGFlcyh4ID0gV2VhdGhlci5Db25kaXRpb24sIHkgPSBGcmVxdWVuY3ksIGZpbGwgPSBXZWF0aGVyLkNvbmRpdGlvbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXF1ZW5jeSksIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDQpICsNCiAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgY+G7mXQ6IFTDrG5oIHRy4bqhbmcgdGjhu51pIHRp4bq/dCAoV2VhdGhlci5Db25kaXRpb24pIiwNCiAgICAgICB4ID0gIlRo4budaSB0aeG6v3QiLA0KICAgICAgIHkgPSAiVOG6p24gc+G7kSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCioqQmnhu4N1IMSR4buTIHRyw7JuKioNCmBgYHtyfQ0Kd2VhdGhlciRQZXJjZW50YWdlIDwtIHJvdW5kKDEwMCAqIHdlYXRoZXIkRnJlcXVlbmN5IC8gc3VtKHdlYXRoZXIkRnJlcXVlbmN5KSwgMSkNCmdncGxvdCh3ZWF0aGVyLCBhZXMoeCA9ICIiLCB5ID0gRnJlcXVlbmN5LCBmaWxsID0gV2VhdGhlci5Db25kaXRpb24pKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIoInkiLCBzdGFydCA9IDApICsNCiAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgdHLDsm46IFThu7cgbOG7hyB0w6xuaCB0cuG6oW5nIHRo4budaSB0aeG6v3QiKSArDQogIHRoZW1lX3ZvaWQoKQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQqKg0KDQotIEThu7FhIHbDoG8gYuG6o25nIHThuqduIHPhu5EsIHBo4bqnbiBs4bubbiBjw6FjIHF1YW4gc8OhdCByxqFpIHbDoG8gxJFp4buBdSBraeG7h24gdGjhu51pIHRp4bq/dCAqQ2xvdWR5KiB24bubaSBgciB0YWJsZShkYXRhRFQkV2VhdGhlci5Db25kaXRpb24pWyJDbG91ZHkiXWAgbeG7pWMsIGNoaeG6v20ga2hv4bqjbmcgYHIgcm91bmQoMTAwICogdGFibGUoZGF0YURUJFdlYXRoZXIuQ29uZGl0aW9uKVsiQ2xvdWR5Il0gLyBzdW0odGFibGUoZGF0YURUJFdlYXRoZXIuQ29uZGl0aW9uKSksIDApYCUgdOG7lW5nIHPhu5EuIFRoZW8gc2F1IGzDoCAqU3VubnkqIHbhu5tpIGByIHRhYmxlKGRhdGFEVCRXZWF0aGVyLkNvbmRpdGlvbilbIlN1bm55Il1gIG3hu6VjICh+YHIgcm91bmQoMTAwICogdGFibGUoZGF0YURUJFdlYXRoZXIuQ29uZGl0aW9uKVsiU3VubnkiXSAvIHN1bSh0YWJsZShkYXRhRFQkV2VhdGhlci5Db25kaXRpb24pKSwgMClgJSksIHbDoCAqUmFpbnkqIHbhu5tpIGByIHRhYmxlKGRhdGFEVCRXZWF0aGVyLkNvbmRpdGlvbilbIlJhaW55Il1gIG3hu6VjICh+YHIgcm91bmQoMTAwICogdGFibGUoZGF0YURUJFdlYXRoZXIuQ29uZGl0aW9uKVsiUmFpbnkiXSAvIHN1bSh0YWJsZShkYXRhRFQkV2VhdGhlci5Db25kaXRpb24pKSwgMClgJSkuIFRyb25nIGtoaSDEkcOzLCDEkWnhu4F1IGtp4buHbiAqU25vd3kqIHh14bqldCBoaeG7h24gw610IG5o4bqldCB24bubaSBgciB0YWJsZShkYXRhRFQkV2VhdGhlci5Db25kaXRpb24pWyJTbm93eSJdYCBt4bulYyAofmByIHJvdW5kKDEwMCAqIHRhYmxlKGRhdGFEVCRXZWF0aGVyLkNvbmRpdGlvbilbIlNub3d5Il0gLyBzdW0odGFibGUoZGF0YURUJFdlYXRoZXIuQ29uZGl0aW9uKSksIDApYCUpLg0KDQotIEJp4buDdSDEkeG7kyBj4buZdCB0aOG7gyBoaeG7h24gcsO1IHLhurFuZyAqQ2xvdWR5KiBsw6AgdHLhuqFuZyB0aMOhaSB0aOG7nWkgdGnhur90IHBo4buVIGJp4bq/biBuaOG6pXQgdHJvbmcgZOG7ryBsaeG7h3UsIHbhu5tpIHPhu5EgbMaw4bujbmcgdsaw4bujdCB0cuG7mWkgaMahbiBo4bqzbiBjw6FjIHRy4bqhbmcgdGjDoWkga2jDoWMuICpTdW5ueSogY8WpbmcgY2hp4bq/bSB04bu3IGzhu4cgbOG7m24sIGNo4buJIHRo4bqlcCBoxqFuIG3hu5l0IGNow7p0IHNvIHbhu5tpICpDbG91ZHkqLiBOZ8aw4bujYyBs4bqhaSwgKlNub3d5KiBjw7MgdOG6p24gc3XhuqV0IHRo4bqlcCBuaOG6pXQuIEJp4buDdSDEkeG7kyB0csOybiBnacO6cCB0cuG7sWMgcXVhbiBow7NhIHThu7cgbOG7hyBuw6B5LCB0aOG7gyBoaeG7h24gcsO1IHBo4bqnbiBkaeG7h24gdMOtY2ggbOG7m24gbmjhuqV0IHRodeG7mWMgduG7gSAqQ2xvdWR5KiwgdGnhur9wIHRoZW8gbMOgICpTdW5ueSogdsOgICpSYWlueSouIE5o4buvbmcga+G6v3QgcXXhuqMgbsOgeSBjaG8gdGjhuqV5IGThu68gbGnhu4d1IHRodSB0aOG6rXAgxJHGsOG7o2MgY2jhu6cgeeG6v3UgZGnhu4VuIHJhIHRyb25nIMSRaeG7gXUga2nhu4duIHRo4budaSB0aeG6v3Qgbmhp4buBdSBtw6J5IHbDoCBu4bqvbmcsIHRyb25nIGtoaSDEkWnhu4F1IGtp4buHbiB0dXnhur90IMOtdCBn4bq3cCBoxqFuLg0KDQojIyAqKkJp4bq/biBTZWFzb25hbGl0eSoqDQoNCioqTOG6rXAgYuG6o25nIHThuqduIHPhu5EgdsOgIHThuqduIHN14bqldCoqDQpgYGB7cn0NCnRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSkNCnRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSkvc3VtKHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSkpDQpgYGANCg0KKipCaeG7g3UgxJHhu5MgY+G7mXQqKg0KYGBge3J9DQpzZWFzb24gPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkYXRhRFQkU2Vhc29uYWxpdHkpKQ0KY29sbmFtZXMoc2Vhc29uKSA8LSBjKCJTZWFzb24iLCAiRnJlcXVlbmN5IikNCmdncGxvdChzZWFzb24sIGFlcyh4ID0gU2Vhc29uLCB5ID0gRnJlcXVlbmN5LCBmaWxsID0gU2Vhc29uKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcXVlbmN5KSwgdmp1c3QgPSAtMC41LCBzaXplID0gNCkgKw0KICBsYWJzKHRpdGxlID0gIkJp4buDdSDEkeG7kyBj4buZdDogTcO5YSB0cm9uZyBuxINtIChTZWFzb25hbGl0eSkiLA0KICAgICAgIHggPSAiTcO5YSIsDQogICAgICAgeSA9ICJU4bqnbiBz4buRIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KKipCaeG7g3UgxJHhu5MgdHLDsm4qKg0KYGBge3J9DQpzZWFzb24kUGVyY2VudGFnZSA8LSByb3VuZCgxMDAgKiBzZWFzb24kRnJlcXVlbmN5IC8gc3VtKHNlYXNvbiRGcmVxdWVuY3kpLCAxKQ0KZ2dwbG90KHNlYXNvbiwgYWVzKHggPSAiIiwgeSA9IEZyZXF1ZW5jeSwgZmlsbCA9IFNlYXNvbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcigieSIsIHN0YXJ0ID0gMCkgKw0KICBsYWJzKHRpdGxlID0gIkJp4buDdSDEkeG7kyB0csOybjogUGjDom4gYuG7kSB0aGVvIG3DuWEgKFNlYXNvbmFsaXR5KSIpICsNCiAgdGhlbWVfdm9pZCgpDQpgYGANCg0KKipOaOG6rW4geMOpdCoqDQoNCi0gROG7sWEgdsOgbyBi4bqjbmcgdOG6p24gc+G7kSwgcGjhuqduIGzhu5tuIGPDoWMgcXVhbiBzw6F0IHLGoWkgdsOgbyBtw7lhICoqV2ludGVyKiogduG7m2kgYHIgdGFibGUoZGF0YURUJFNlYXNvbmFsaXR5KVsiV2ludGVyIl1gIG3hu6VjLCBjaGnhur9tIGtob+G6o25nIGByIHJvdW5kKDEwMCAqIHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSlbIldpbnRlciJdIC8gc3VtKHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSkpLCAwKWAlIHThu5VuZyBz4buRLiBCYSBtw7lhIGPDsm4gbOG6oWkgY8OzIHPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IGtow6EgZ+G6p24gbmhhdSwgbOG6p24gbMaw4bujdCBsw6AgKipTcHJpbmcqKiB2w6AgKipTdW1tZXIqKiB24bubaSBgciB0YWJsZShkYXRhRFQkU2Vhc29uYWxpdHkpWyJTcHJpbmciXWAgdsOgIGByIHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSlbIlN1bW1lciJdYCBt4bulYyAofmByIHJvdW5kKDEwMCAqIHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSlbIlNwcmluZyJdIC8gc3VtKHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSkpLCAwKWAlIHbDoCBgciByb3VuZCgxMDAgKiB0YWJsZShkYXRhRFQkU2Vhc29uYWxpdHkpWyJTdW1tZXIiXSAvIHN1bSh0YWJsZShkYXRhRFQkU2Vhc29uYWxpdHkpKSwgMClgJSksIHbDoCAqKkF1dHVtbioqIHbhu5tpIGByIHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSlbIkF1dHVtbiJdYCBt4bulYyAofmByIHJvdW5kKDEwMCAqIHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSlbIkF1dHVtbiJdIC8gc3VtKHRhYmxlKGRhdGFEVCRTZWFzb25hbGl0eSkpLCAwKWAlKS4NCg0KLSBCaeG7g3UgxJHhu5MgY+G7mXQgdGjhu4MgaGnhu4duIHLDtSBy4bqxbmcgKipXaW50ZXIqKiBsw6AgbcO5YSBjaGnhur9tIHThu7cgbOG7hyBxdWFuIHPDoXQgbOG7m24gbmjhuqV0IHRyb25nIGThu68gbGnhu4d1LCB2xrDhu6N0IHRy4buZaSBoxqFuIG3hu5l0IGNow7p0IHNvIHbhu5tpIGPDoWMgbcO5YSBjw7JuIGzhuqFpLiBCYSBtw7lhICoqU3ByaW5nKiosICoqU3VtbWVyKiogdsOgICoqQXV0dW1uKiogY8OzIHPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IGtow6EgxJHhu5NuZyDEkeG7gXUsIGNo4buJIGNow6puaCBs4buHY2ggbmjhurkuIEJp4buDdSDEkeG7kyB0csOybiB0cuG7sWMgcXVhbiBow7NhIHThu7cgbOG7hyBuw6B5IHLhuqV0IHLDtSByw6BuZywgduG7m2kgZGnhu4duIHTDrWNoIGzhu5tuIG5o4bqldCB0aHXhu5ljIHbhu4EgKipXaW50ZXIqKiwgdGnhur9wIHRoZW8gbMOgIGJhIG3DuWEgY8OybiBs4bqhaSBjw7MgdOG7tyBs4buHIGtow6EgdMawxqFuZyDEkcawxqFuZyBuaGF1LiBOaOG7r25nIGvhur90IHF14bqjIG7DoHkgY2hvIHRo4bqleSBk4buvIGxp4buHdSDEkcaw4bujYyB0aHUgdGjhuq1wIHRy4bqjaSDEkeG7gXUgdHJvbmcgY8OhYyBtw7lhLCB24bubaSBt4buZdCBsxrDhu6NuZyBxdWFuIHPDoXQgbmjhu4luaCBoxqFuIHbDoG8gbcO5YSDEkcO0bmcuDQoNCiMjICoqQmnhur9uIFByb21vdGlvbioqDQoNCioqTOG6rXAgYuG6o25nIHThuqduIHPhu5EgdsOgIHThuqduIHN14bqldCoqDQpgYGB7cn0NCnRhYmxlKGRhdGFEVCRQcm9tb3Rpb24pDQp0YWJsZShkYXRhRFQkUHJvbW90aW9uKS9zdW0odGFibGUoZGF0YURUJFByb21vdGlvbikpDQpgYGANCg0KKipCaeG7g3UgxJHhu5MgY+G7mXQqKg0KYGBge3J9DQpwcm9tbyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKGRhdGFEVCRQcm9tb3Rpb24pKQ0KY29sbmFtZXMocHJvbW8pIDwtIGMoIlByb21vdGlvbiIsICJGcmVxdWVuY3kiKQ0KZ2dwbG90KHByb21vLCBhZXMoeCA9IFByb21vdGlvbiwgeSA9IEZyZXF1ZW5jeSwgZmlsbCA9IFByb21vdGlvbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXF1ZW5jeSksIHZqdXN0ID0gLTAuNSkgKw0KICBsYWJzKHRpdGxlID0gIlThuqduIHPhu5Egw6FwIGThu6VuZyBraHV54bq/biBtw6NpIChQcm9tb3Rpb24pIiwgeCA9ICJQcm9tb3Rpb24gKDA9Tm8sMT1ZZXMpIiwgeSA9ICJU4bqnbiBz4buRIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KKipOaOG6rW4geMOpdCoqDQoNCi0gROG7sWEgdsOgbyBi4bqjbmcgdOG6p24gc+G7kSwgc+G7kSBsxrDhu6NuZyBxdWFuIHPDoXQga2jDtG5nIMOhcCBk4bulbmcga2h1eeG6v24gbcOjaSAoUHJvbW90aW9uID0gMCkgbMOgIGByIHRhYmxlKGRhdGFEVCRQcm9tb3Rpb24pWyIwIl1gIG3hu6VjLCBjaGnhur9tIGtob+G6o25nIGByIHJvdW5kKDEwMCAqIHRhYmxlKGRhdGFEVCRQcm9tb3Rpb24pWyIwIl0gLyBzdW0odGFibGUoZGF0YURUJFByb21vdGlvbikpLCAxKWAlIHThu5VuZyBz4buRLiBUcm9uZyBraGkgxJHDsywgc+G7kSBxdWFuIHPDoXQgw6FwIGThu6VuZyBraHV54bq/biBtw6NpIChQcm9tb3Rpb24gPSAxKSBsw6AgYHIgdGFibGUoZGF0YURUJFByb21vdGlvbilbIjEiXWAgbeG7pWMsIGNoaeG6v20ga2hv4bqjbmcgYHIgcm91bmQoMTAwICogdGFibGUoZGF0YURUJFByb21vdGlvbilbIjEiXSAvIHN1bSh0YWJsZShkYXRhRFQkUHJvbW90aW9uKSksIDEpYCUuICANCg0KLSBCaeG7g3UgxJHhu5MgdOG6p24gc+G7kSB0aOG7gyBoaeG7h24gcsO1IHLhurFuZyBwaOG6p24gbOG7m24gZ2lhbyBk4buLY2gga2jDtG5nIGPDsyBraHV54bq/biBtw6NpLCBuaMawbmcga2h1eeG6v24gbcOjaSB24bqrbiBjaGnhur9tIHThu7cgbOG7hyDEkcOhbmcga+G7gyB0cm9uZyBob+G6oXQgxJHhu5luZyBiw6FuIGjDoG5nLg0KDQojIyAqKkJp4bq/biBFcGlkZW1pYyoqDQoNCioqTOG6rXAgYuG6o25nIHThuqduIHPhu5EgdsOgIHThuqduIHN14bqldCoqDQpgYGB7cn0NCnRhYmxlKGRhdGFEVCRFcGlkZW1pYykNCnRhYmxlKGRhdGFEVCRFcGlkZW1pYykvc3VtKHRhYmxlKGRhdGFEVCRFcGlkZW1pYykpDQpgYGANCg0KKipCaeG7g3UgxJHhu5MgY+G7mXQqKg0KYGBge3J9DQplcGkgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkYXRhRFQkRXBpZGVtaWMpKQ0KY29sbmFtZXMoZXBpKSA8LSBjKCJFcGlkZW1pYyIsICJGcmVxdWVuY3kiKQ0KZ2dwbG90KGVwaSwgYWVzKHggPSBFcGlkZW1pYywgeSA9IEZyZXF1ZW5jeSwgZmlsbCA9IEVwaWRlbWljKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcXVlbmN5KSwgdmp1c3QgPSAtMC41KSArDQogIGxhYnModGl0bGUgPSAiVOG6p24gc+G7kSBk4buLY2ggYuG7h25oIChFcGlkZW1pYykiLCB4ID0gIkVwaWRlbWljICgwPU5vLDE9WWVzKSIsIHkgPSAiVOG6p24gc+G7kSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQqKg0KDQotIFRoZW8gYuG6o25nIHThuqduIHPhu5EsIHPhu5EgcXVhbiBzw6F0IGtow7RuZyBjw7MgZOG7i2NoIGLhu4duaCAoRXBpZGVtaWMgPSAwKSBsw6AgYHIgdGFibGUoZGF0YURUJEVwaWRlbWljKVsiMCJdYCBt4bulYywgY2hp4bq/bSBraG/huqNuZyBgciByb3VuZCgxMDAgKiB0YWJsZShkYXRhRFQkRXBpZGVtaWMpWyIwIl0gLyBzdW0odGFibGUoZGF0YURUJEVwaWRlbWljKSksIDEpYCUgdOG7lW5nIHPhu5EuIEPDoWMgcXVhbiBzw6F0IHRyb25nIMSRaeG7gXUga2nhu4duIGPDsyBk4buLY2ggYuG7h25oIChFcGlkZW1pYyA9IDEpIGzDoCBgciB0YWJsZShkYXRhRFQkRXBpZGVtaWMpWyIxIl1gIG3hu6VjLCBjaGnhur9tIGtob+G6o25nIGByIHJvdW5kKDEwMCAqIHRhYmxlKGRhdGFEVCRFcGlkZW1pYylbIjEiXSAvIHN1bSh0YWJsZShkYXRhRFQkRXBpZGVtaWMpKSwgMSlgJS4gIA0KDQotIEThu68gbGnhu4d1IGNobyB0aOG6pXkgcGjhuqduIGzhu5tuIGdpYW8gZOG7i2NoIGRp4buFbiByYSB0cm9uZyDEkWnhu4F1IGtp4buHbiBraMO0bmcgY8OzIGThu4tjaCBi4buHbmgsIHRyb25nIGtoaSBraG/huqNuZyAyMCUgZ2lhbyBk4buLY2ggeOG6o3kgcmEgdHJvbmcgYuG7kWkgY+G6o25oIGThu4tjaCBi4buHbmggKG3DtCBwaOG7j25nIENPVklELTE5KSwgY2hvIHBow6lwIHBow6JuIHTDrWNoIHTDoWMgxJHhu5luZyBk4buLY2ggYuG7h25oIHThu5tpIGhv4bqhdCDEkeG7mW5nIGLDoW4gbOG6uy4NCg0KIyAqKlBo4bqnbiAzOiDGr+G7m2MgbMaw4bujbmcgS2hv4bqjbmcgdsOgIEtp4buDbSDEkeG7i25oIEdp4bqjIHRodXnhur90IGNobyBU4bu3IGzhu4cqKg0KDQojIyAqKkJp4bq/biBDYXRlZ29yeSoqDQoNCioqTeG7pWMgdGnDqnUqKg0KDQpUaOG7sWMgaGnhu4duIGtp4buDbSDEkeG7i25oIMSR4buDIHjDoWMgxJHhu4tuaCB4ZW0gKip04bu3IGzhu4cgdGh14buZYyBo4bqhbmcgbeG7pWMgIkdyb2NlcmllcyIgdHJvbmcgYmnhur9uIENhdGVnb3J5IGPDsyBraMOhYyBiaeG7h3Qgc28gduG7m2kgNTAlIGhheSBraMO0bmcqKi4NCg0KKipE4buvIGxp4buHdSB2w6AgYmnhur9uIHF1YW4gdMOibSoqDQoNCi0gQmnhur9uIHF1YW4gdMOibTogYENhdGVnb3J5YA0KDQotIEjhuqFuZyBt4bulYyBxdWFuIHTDom06IGAiR3JvY2VyaWVzImANCg0KKipUw61uaCB0b8OhbiB04bu3IGzhu4cgbeG6q3UqKg0KDQpgYGB7cn0NCiMgU+G7kSBsxrDhu6NuZyBjw6EgdGjhu4MgdGh14buZYyBDYXRlZ29yeSA9ICJHcm9jZXJpZXMiDQpzdW1Hcm9jZXJpZXMgPC0gc3VtKGRhdGFEVCRDYXRlZ29yeSA9PSAiR3JvY2VyaWVzIikNCg0KIyBU4buVbmcgc+G7kSBjw6EgdGjhu4MgdHJvbmcgZOG7ryBsaeG7h3UNCnRvdGFsQ2F0ZWdvcnkgPC0gbGVuZ3RoKGRhdGFEVCRDYXRlZ29yeSkNCmBgYA0KDQoqKlRo4buxYyBoaeG7h24ga2nhu4NtIMSR4buLbmggdOG7tyBs4buHIDEgbeG6q3UqKg0KDQpHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoNCg0KLSAqKkdp4bqjIHRodXnhur90IEgwOioqIFThu7cgbOG7hyBjw6EgdGjhu4MgdGh14buZYyAiR3JvY2VyaWVzIiBi4bqxbmcgMC41DQoNCi0gKipHaeG6oyB0aHV54bq/dCBIMToqKiBU4bu3IGzhu4cgY8OhIHRo4buDIHRodeG7mWMgIkdyb2NlcmllcyIga2jDoWMgMC41DQoNCmBgYHtyfQ0KIyBLaeG7g20gxJHhu4tuaCB04bu3IGzhu4cgMSBt4bqrdSB24bubaSBnaeG6oyB0aHV54bq/dCBwID0gMC41DQpwcm9wLnRlc3QoeCA9IHN1bUdyb2NlcmllcywgbiA9IHRvdGFsQ2F0ZWdvcnksIHAgPSAwLjUsIGNvbmYubGV2ZWwgPSAwLjk1LCBjb3JyZWN0ID0gVFJVRSkNCmBgYA0KDQoqKkvhur90IHF14bqjIGtp4buDbSDEkeG7i25oOioqDQoNCi0gR2nDoSB0cuG7iyB0aOG7kW5nIGvDqiBDaGktc3F1YXJlZDogMzAzOS42ICANCg0KLSBC4bqtYyB04buxIGRvIChkZik6IDEgIA0KDQotIHAtdmFsdWU6IDwgMi4yZS0xNiAgDQoNCi0gS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gdOG7tyBs4buHICJHcm9jZXJpZXMiOiAoMC4zOTY1LCAwLjQwMzUpIA0KDQotIMav4bubYyBsxrDhu6NuZyB04bu3IGzhu4cgIkdyb2NlcmllcyIgdOG7qyBt4bqrdTogMC40MCAodOG7qWMgNDAlKQ0KDQoqKkvhur90IGx14bqtbjoqKg0KDQpW4bubaSBt4bupYyDDvSBuZ2jEqWEgNSUsIHbDrCBwLXZhbHVlIHLhuqV0IG5o4buPICg8IDAuMDUpLCB0YSBiw6FjIGLhu48gZ2nhuqMgdGh1eeG6v3QgSDAuIMSQaeG7gXUgbsOgeSBjaOG7qW5nIHThu48gdOG7tyBs4buHIGPDoSB0aOG7gyB0aHXhu5ljIGjhuqFuZyBt4bulYyAiR3JvY2VyaWVzIiB0cm9uZyBk4buvIGxp4buHdSBraMOhYyBiaeG7h3QgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBzbyB24bubaSB04bu3IGzhu4cgNTAlLiBD4bulIHRo4buDLCB04bu3IGzhu4cgdGjhu7FjIHThur8ga2hv4bqjbmcgNDAlLCB0aOG6pXAgaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSA1MCUuDQoNCiMjICoqQmnhur9uIFJlZ2lvbioqDQoNCioqTeG7pWMgdGnDqnUqKg0KDQpUaOG7sWMgaGnhu4duIGtp4buDbSDEkeG7i25oIMSR4buDIHjDoWMgxJHhu4tuaCB4ZW0gKip04bu3IGzhu4cgdGh14buZYyB2w7luZyAiTm9ydGgiIHRyb25nIGJp4bq/biBSZWdpb24gY8OzIGtow6FjIGJp4buHdCBzbyB24bubaSA0MCUgaGF5IGtow7RuZyoqLg0KDQoqKkThu68gbGnhu4d1IHbDoCBiaeG6v24gcXVhbiB0w6JtKioNCg0KLSBCaeG6v24gcXVhbiB0w6JtOiBgUmVnaW9uYA0KDQotIEjhuqFuZyBt4bulYyBxdWFuIHTDom06IGAiTm9ydGgiYA0KDQoqKlTDrW5oIHRvw6FuIHThu7cgbOG7hyBt4bqrdSoqDQoNCmBgYHtyfQ0KIyBT4buRIGzGsOG7o25nIGPDoSB0aOG7gyB0aHXhu5ljIFJlZ2lvbiA9ICJOb3J0aCINCnN1bU5vcnRoIDwtIHN1bShkYXRhRFQkUmVnaW9uID09ICJOb3J0aCIpDQoNCiMgVOG7lW5nIHPhu5EgY8OhIHRo4buDIHRyb25nIGThu68gbGnhu4d1DQp0b3RhbFJlZ2lvbiA8LSBsZW5ndGgoZGF0YURUJFJlZ2lvbikNCmBgYA0KDQoqKlRo4buxYyBoaeG7h24ga2nhu4NtIMSR4buLbmggdOG7tyBs4buHIDEgbeG6q3UqKg0KDQpHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoNCg0KLSAqKkdp4bqjIHRodXnhur90IEgwOioqIFThu7cgbOG7hyBjw6EgdGjhu4MgdGh14buZYyAiTm9ydGgiIGLhurFuZyAwLjQNCg0KLSAqKkdp4bqjIHRodXnhur90IEgxOioqIOG7tyBs4buHIGPDoSB0aOG7gyB0aHXhu5ljICJOb3J0aCIga2jDoWMgMC40DQoNCmBgYHtyfQ0KIyBLaeG7g20gxJHhu4tuaCB04bu3IGzhu4cgMSBt4bqrdSB24bubaSBnaeG6oyB0aHV54bq/dCBwID0gMC40DQpwcm9wLnRlc3QoeCA9IHN1bU5vcnRoLCBuID0gdG90YWxSZWdpb24sIHAgPSAwLjQsIGNvbmYubGV2ZWwgPSAwLjk1LCBjb3JyZWN0ID0gVFJVRSkNCmBgYA0KDQoqKkvhur90IHF14bqjIGtp4buDbSDEkeG7i25oOioqDQoNCi0gR2nDoSB0cuG7iyB0aOG7kW5nIGvDqiBDaGktc3F1YXJlZDogMA0KDQotIELhuq1jIHThu7EgZG8gKGRmKTogMSAgDQoNCi0gcC12YWx1ZTogMSAgDQoNCi0gS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gdOG7tyBs4buHICJOb3J0aCI6ICgwLjM5NjUsIDAuNDAzNSkgIA0KDQotIMav4bubYyBsxrDhu6NuZyB04bu3IGzhu4cgIk5vcnRoIiB04burIG3huqt1OiAwLjQwICh04bupYyA0MCUpDQoNCioqS+G6v3QgbHXhuq1uOioqDQoNClbhu5tpIG3hu6ljIMO9IG5naMSpYSA1JSwgdsOsIHAtdmFsdWUgPSAxID4gMC4wNSwgdGEga2jDtG5nIGLDoWMgYuG7jyBnaeG6oyB0aHV54bq/dCBIMC4gxJBp4buBdSBuw6B5IGNobyB0aOG6pXkgdOG7tyBs4buHIGPDoSB0aOG7gyB0aHXhu5ljIHbDuW5nICJOb3J0aCIgdHJvbmcgZOG7ryBsaeG7h3Uga2jDtG5nIGtow6FjIGJp4buHdCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHNvIHbhu5tpIHThu7cgbOG7hyA0MCUuIFThu7cgbOG7hyB0aOG7sWMgdOG6vyDGsOG7m2MgbMaw4bujbmcgbMOgIDQwJSwgcGjDuSBo4bujcCB24bubaSB04buJIGzhu4cgZ2nhuqMgxJHhu4tuaC4NCg0KIyAqKlBI4bqmTiA0OiBQSMOCTiBUw41DSCBN4buQSSBRVUFOIEjhu4YgR0nhu65BIEhBSSBCSeG6vk4gxJDhu4pOSCBUw41OSCoqDQoNCiMjICoqQ+G6t3AgYmnhur9uIFdlYXRoZXIuQ29uZGl0aW9uIHbDoCBSZWdpb24qKg0KDQojIyMgKipUaOG7kW5nIGvDqiBtw7QgdOG6oyBj4bq3cCBiaeG6v24gV2VhdGhlci5Db25kaXRpb24gdsOgIFJlZ2lvbioqDQoNCioqQuG6o25nIHThuqduIHPhu5EgY2jDqW8qKg0KYGBge3J9DQp3ZWF0aGVyX3JlZ2lvbiA8LSB0YWJsZShkYXRhRFQkV2VhdGhlci5Db25kaXRpb24sIGRhdGFEVCRSZWdpb24pDQp3ZWF0aGVyX3JlZ2lvbg0KYGBgDQoNCioqTmjhuq1uIHjDqXQqKg0KDQotICoqxJBp4buBdSBraeG7h24gdGjhu51pIHRp4bq/dCBgQ2xvdWR5YCAobmhp4buBdSBtw6J5KSoqOiBYdeG6pXQgaGnhu4duIHBo4buVIGJp4bq/biBuaOG6pXQg4bufIHbDuW5nICoqTm9ydGgqKiB24bubaSAqKjk0NDAqKiBsxrDhu6N0IHF1YW4gc8OhdCwgZ+G6p24gZ+G6pXAgxJHDtGkgc28gduG7m2kgY8OhYyB2w7luZyBraMOhYyBuaMawICoqRWFzdCoqICg0OTIwKSwgKipTb3V0aCoqICg1MjYwKSwgdsOgICoqV2VzdCoqICg0NzQwKS4NCg0KLSAqKlRo4budaSB0aeG6v3QgYFJhaW55YCAobcawYSkqKjogQ8WpbmcgY8OzIHThuqduIHN14bqldCBjYW8gbmjhuqV0IOG7nyB2w7luZyAqKk5vcnRoKiogKCoqNzQ4MCoqIGzGsOG7o3QpLCB0cm9uZyBraGkgY8OhYyB2w7luZyAqKkVhc3QqKiwgKipTb3V0aCoqLCB2w6AgKipXZXN0KiogZGFvIMSR4buZbmcgdOG7qyAqKjMxMjAqKiDEkeG6v24gKiozNTgwKiogbMaw4bujdC4NCg0KLSAqKlRo4budaSB0aeG6v3QgYFNub3d5YCAodHV54bq/dCkqKjogQ2jhu6cgeeG6v3UgdOG6rXAgdHJ1bmcg4bufIHbDuW5nICoqTm9ydGgqKiAoKio0MjgwKiopLCBjYW8gZ+G6p24gZ+G6pXAgxJHDtGkgc28gduG7m2kgdsO5bmcgKipTb3V0aCoqICgqKjIxNDAqKikg4oCTIMSRaeG7gXUgbsOgeSBwaOG6o24gw6FuaCDEkeG6t2MgxJFp4buDbSBraMOtIGjhuq11IGzhuqFuaCBoxqFuIGPhu6dhIG1p4buBbiBC4bqvYy4NCg0KLSAqKlRo4budaSB0aeG6v3QgYFN1bm55YCAobuG6r25nKSoqOiBHaGkgbmjhuq1uIHPhu5EgbMaw4bujbmcgbOG7m24g4bufICoqTm9ydGgqKiAoKio5MjAwKiopIHbDoCAqKldlc3QqKiAoKio1MDAwKiopLCB0cm9uZyBraGkgaGFpIHbDuW5nIGPDsm4gbOG6oWkg4oCTICoqRWFzdCoqICgqKjQzMDAqKikgdsOgICoqU291dGgqKiAoKio0NDgwKiopIOKAkyBjw7Mgc+G7kSBsxrDhu6NuZyBn4bqnbiB0xrDGoW5nIMSRxrDGoW5nLg0KDQotICoqU28gc8OhbmggZ2nhu69hIGPDoWMgdsO5bmcqKjoNCg0KICAtICoqTm9ydGgqKiBsw6AgdsO5bmcgY8OzIHPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IGNhbyBuaOG6pXQg4bufICoqdOG6pXQgY+G6oyoqIGPDoWMgbG/huqFpIHRo4budaSB0aeG6v3QuIMSQaeG7gXUgbsOgeSBjw7MgdGjhu4MgY2hvIHRo4bqleToNCiAgDQogICAgLSDEkMOieSBsw6Aga2h1IHbhu7FjIMSRxrDhu6NjIHF1YW4gc8OhdCwgdGh1IHRo4bqtcCBk4buvIGxp4buHdSBuaGnhu4F1IGjGoW4uDQogICAgDQogICAgLSBIb+G6t2Mga2jDrSBo4bqtdSBuxqFpIMSRw6J5IMSRYSBk4bqhbmcgdsOgIGJp4bq/biDEkeG7mW5nIHLDtSBy4buHdCB0aGVvIG3DuWEuDQoNCiAgLSAqKlNvdXRoKiogdsOgICoqV2VzdCoqIGPDsyBz4buRIGzGsOG7o25nIHF1YW4gc8OhdCB0aOG6pXAgaMahbiwgxJHhurdjIGJp4buHdCBsw6AgduG7m2kgdGjhu51pIHRp4bq/dCBgU25vd3lgLCBjw7MgdGjhu4MgbGnDqm4gcXVhbiDEkeG6v24gxJHhurdjIMSRaeG7g20gKipraMOtIGjhuq11IOG6pW0gaMahbioqLCDDrXQgdHV54bq/dCBoxqFuIHNvIHbhu5tpIGPDoWMgdsO5bmcgY8OybiBs4bqhaS4NCg0KKipC4bqjbmcgdOG6p24gc3XhuqV0IGNow6lvKioNCmBgYHtyfQ0KcHJvcC50YWJsZSh3ZWF0aGVyX3JlZ2lvbikNCmBgYA0KDQoqKk5o4bqtbiB4w6l0IGLhuqNuZyB04bqnbiBzdeG6pXQgY2jDqW8qKg0KDQotICoqV2VhdGhlci5Db25kaXRpb24gPSBDbG91ZHkgKG5oaeG7gXUgbcOieSkqKjogQ2hp4bq/bSB04bu3IGzhu4cgY2FvIG5o4bqldCB04bqhaSB2w7luZyAqKk5vcnRoKiogKDEyLjQyJSksIGNhbyBoxqFuIMSRw6FuZyBr4buDIHNvIHbhu5tpIGPDoWMgdsO5bmcgKipTb3V0aCoqICg2LjkyJSksICoqRWFzdCoqICg2LjQ3JSksIHbDoCAqKldlc3QqKiAoNi4yNCUpLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSB0aOG7nWkgdGnhur90IG5oaeG7gXUgbcOieSB44bqjeSByYSB0aMaw4budbmcgeHV5w6puIGjGoW4g4bufIGtodSB24buxYyBtaeG7gW4gQuG6r2MuDQoNCi0gKipXZWF0aGVyLkNvbmRpdGlvbiA9IFJhaW55IChtxrBhKSoqOiBW4bqrbiBnaGkgbmjhuq1uIHThu7cgbOG7hyBjYW8gbmjhuqV0IHThuqFpIHbDuW5nICoqTm9ydGgqKiAoOS44NCUpLCB0cm9uZyBraGkgYmEgdsO5bmcgY8OybiBs4bqhaSBkYW8gxJHhu5luZyB0aOG6pXAgaMahbjogKipFYXN0KiogKDQuNzElKSwgKipTb3V0aCoqICg0LjM3JSksICoqV2VzdCoqICg0LjExJSkuDQoNCi0gKipXZWF0aGVyLkNvbmRpdGlvbiA9IFNub3d5ICh0dXnhur90KSoqOiBSw7UgcsOgbmcgdOG6rXAgdHJ1bmcgbmhp4buBdSDhu58gKipOb3J0aCoqICg1LjYzJSksIGNhbyBoxqFuIGfhuqduIGfhuqVwIMSRw7RpIHNvIHbhu5tpICoqU291dGgqKiAoMi44MiUpIHbDoCBuaOG7iW5oIGjGoW4gY8OhYyB2w7luZyAqKkVhc3QqKiAoMy4xNiUpLCAqKldlc3QqKiAoMy4wOCUpLiDEkGnhu4F1IG7DoHkgcGjDuSBo4bujcCB24bubaSDEkeG6t2MgxJFp4buDbSBraMOtIGjhuq11IGzhuqFuaCDhu58gbWnhu4FuIELhuq9jLg0KDQotICoqV2VhdGhlci5Db25kaXRpb24gPSBTdW5ueSAobuG6r25nKSoqOiBWw7luZyAqKk5vcnRoKiogduG6q24gZOG6q24gxJHhuqd1IHbhu5tpIHThu7cgbOG7hyAqKjEyLjExJSoqLCB0aeG6v3AgdGhlbyBsw6AgKipXZXN0KiogKDYuNTglKSwgKipTb3V0aCoqICg1Ljg5JSkgdsOgICoqRWFzdCoqICg1LjY2JSkuDQoNCi0gKipTbyBzw6FuaCB04buVbmcgdGjhu4MgZ2nhu69hIGPDoWMgdsO5bmcqKjoNCg0KICAtICoqTm9ydGgqKiBsw6AgdsO5bmcgY8OzIHThu7cgbOG7hyB4deG6pXQgaGnhu4duIGNhbyBuaOG6pXQg4bufICoqbeG7jWkgxJFp4buBdSBraeG7h24gdGjhu51pIHRp4bq/dCoqLCBjaGnhur9tIMawdSB0aOG6vyByw7UgcuG7h3QsIHBo4bqjbiDDoW5oIHPhu7EgxJFhIGThuqFuZyBraMOtIGjhuq11IGhv4bq3YyBt4bupYyDEkeG7mSBnaGkgbmjhuq1uIGThu68gbGnhu4d1IGzhu5tuIGjGoW4gc28gduG7m2kgY8OhYyB2w7luZyBraMOhYy4NCiAgDQogIC0gQ8OhYyB2w7luZyAqKkVhc3QqKiwgKipTb3V0aCoqLCB2w6AgKipXZXN0KiogY8OzIHBow6JuIGLhu5Ega2jDoSB0xrDGoW5nIMSR4buTbmcgdsOgIHRo4bqlcCBoxqFuIMSRw6FuZyBr4buDIHNvIHbhu5tpICoqTm9ydGgqKiwgxJHhurdjIGJp4buHdCDhu58gY8OhYyDEkWnhu4F1IGtp4buHbiBuaMawIGBSYWlueWAgdsOgIGBTbm93eWAuDQoNCk5ow6xuIGNodW5nLCAqKk5vcnRoKiogbMOgIHbDuW5nIG7hu5VpIGLhuq10IHbhu5tpIHThuqduIHN14bqldCB0aOG7nWkgdGnhur90IMSRYSBk4bqhbmcgdsOgIGNhbywgdHJvbmcga2hpIGPDoWMgdsO5bmcga2jDoWMgY8OzIG3hu6ljIHh14bqldCBoaeG7h24gxJHhu4F1IHbDoCB0aOG6pXAgaMahbiwgcGjhuqNuIMOhbmggc+G7sSBraMOhYyBiaeG7h3QgduG7gSDEkWnhu4F1IGtp4buHbiB04buxIG5oacOqbiBob+G6t2MgcXV5IG3DtCB0aHUgdGjhuq1wIGThu68gbGnhu4d1Lg0KDQoqKlbhur0gxJHhu5MgdGjhu4sqKg0KYGBge3J9DQpkZl93ZWF0aGVyX3JlZ2lvbiA8LSBhcy5kYXRhLmZyYW1lKHdlYXRoZXJfcmVnaW9uKQ0KY29sbmFtZXMoZGZfd2VhdGhlcl9yZWdpb24pIDwtIGMoIldlYXRoZXIuQ29uZGl0aW9uIiwgIlJlZ2lvbiIsICJDb3VudCIpDQpnZ3Bsb3QoZGZfd2VhdGhlcl9yZWdpb24sIGFlcyh4ID0gUmVnaW9uLCB5ID0gQ291bnQsIGZpbGwgPSBXZWF0aGVyLkNvbmRpdGlvbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKHRpdGxlID0gIlPhu5EgbMaw4bujbmcgcXVhbiBzw6F0IHRoZW8gUmVnaW9uIHbDoCBXZWF0aGVyLkNvbmRpdGlvbiIsIA0KICAgICAgIHggPSAiUmVnaW9uIiwgeSA9ICJDb3VudCIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KIyMjICoqS2nhu4NtIMSR4buLbmggdGjhu5FuZyBrw6oqKg0KDQoqKkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oOjoqKg0KDQotICoqSDA6KiogSGFpIGJp4bq/biBXZWF0aGVyLkNvbmRpdGlvbiB2w6AgUmVnaW9uIMSR4buZYyBs4bqtcA0KDQotICoqSDE6KiogSGFpIGJp4bq/biBXZWF0aGVyLkNvbmRpdGlvbiB2w6AgUmVnaW9uIGPDsyBt4buRaSBsacOqbiBo4buHDQoNCioqVGjhu7FjIGhp4buHbiBraeG7g20gxJHhu4tuaCBDaGktIGLDrG5oIHBoxrDGoW5nKioNCmBgYHtyfQ0KY2hpc3FfcmVzdWx0IDwtIGNoaXNxLnRlc3Qod2VhdGhlcl9yZWdpb24pDQpjaGlzcV9yZXN1bHQNCmBgYA0KKipL4bq/dCBxdeG6oyBraeG7g20gxJHhu4tuaCBDaGktc3F1YXJlZCoqDQoNCi0gR2nDoSB0cuG7iyB0aOG7kW5nIGvDqiBDaGktc3F1YXJlZDogYFgtc3F1YXJlZCA9IDIxNi40NWANCg0KLSBC4bqtYyB04buxIGRvOiBgZGYgPSA5YA0KDQotIEdpw6EgdHLhu4sgcC12YWx1ZTogYHAtdmFsdWUgPCAyLjJlLTE2YA0KDQoqKkvhur90IGx14bqtbioqDQoNClbDrCBnacOhIHRy4buLIHAgcuG6pXQgbmjhu48gKHAtdmFsdWUgPCAwLjA1KSwgdGEgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IGtow7RuZyAoSDApLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBjw7MgbeG7kWkgbGnDqm4gaOG7hyBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIGdp4buvYSDEkWnhu4F1IGtp4buHbiB0aOG7nWkgdGnhur90IChgV2VhdGhlci5Db25kaXRpb25gKSB2w6AgdsO5bmcgbWnhu4FuIChgUmVnaW9uYCkuDQoNCiMjICoqQ+G6t3AgYmnhur9uIHJlZ2lvbiB2w6AgZXBpZGVtaWMqKg0KDQoqKlTDrW5oIFJlbGF0aXZlIFJpc2sqKg0KDQpgYGB7cn0NCmxpYnJhcnkoZXBpdG9vbHMpDQoNCiMgMS4gTOG7jWMgZOG7ryBsaeG7h3UgY2jhu4kgbOG6pXkgMiB2w7luZyBOb3J0aCB2w6AgU291dGgNCnN1YnNldF9kYXRhIDwtIHN1YnNldChkYXRhRFQsIFJlZ2lvbiAlaW4lIGMoIk5vcnRoIiwgIlNvdXRoIikpDQpzdWJzZXRfZGF0YSRSZWdpb24gPC0gZHJvcGxldmVscyhzdWJzZXRfZGF0YSRSZWdpb24pDQoNCiMgMi4gVOG6oW8gYuG6o25nIHThuqduIHPhu5EgY2jDqW8NCnJlZ2lvbl9lcGlkZW1pYyA8LSB0YWJsZShzdWJzZXRfZGF0YSRSZWdpb24sIHN1YnNldF9kYXRhJEVwaWRlbWljKQ0KYWRkbWFyZ2lucyhyZWdpb25fZXBpZGVtaWMpDQoNCiMgMy4gVMOtbmggUuG7p2kgcm8gdMawxqFuZyDEkeG7kWkgKFJlbGF0aXZlIFJpc2spDQpyaXNrcmF0aW8ocmVnaW9uX2VwaWRlbWljKQ0KYGBgDQoNCioqS+G6v3QgcXXhuqMgdMOtbmggUuG7p2kgcm8gdMawxqFuZyDEkeG7kWkgKFJlbGF0aXZlIFJpc2spKioNCg0KLSBS4bunaSBybyBt4bqvYyBk4buLY2gg4bufICoqTm9ydGgqKiA9IDYsMDgwIC8gMzAsNDAwID0gKiowLjIwKioNCg0KLSBS4bunaSBybyBt4bqvYyBk4buLY2gg4bufICoqU291dGgqKiA9IDMsMDQwIC8gMTUsMjAwID0gKiowLjIwKioNCg0KLSBSUiAoU291dGggc28gduG7m2kgTm9ydGgpID0gKioxLjAwMCoqICANCg0KICDihpIgS2hv4bqjbmcgdGluIGPhuq15IDk1JTogKipbMC45NjE4IDsgMS4wMzk3XSoqDQoNCi0gR2nDoSB0cuG7iyBwLXZhbHVlID0gKiowLjk5OSoqICh04burIGtp4buDbSDEkeG7i25oIEZpc2hlcuKAmXMgRXhhY3QgdsOgIENoaS1zcXVhcmVkKQ0KDQoqKkvhur90IGx14bqtbiB2w6AgTmjhuq1uIHjDqXQqKg0KDQotIFLhu6dpIHJvIHTGsMahbmcgxJHhu5FpIChSUiA9IDEpIGNobyB0aOG6pXkga2jhuqMgbsSDbmcgbeG6r2MgZOG7i2NoIChFcGlkZW1pYyA9IDEpIGdp4buvYSBoYWkgdsO5bmcgKipOb3J0aCoqIHbDoCAqKlNvdXRoKiogbMOgIHTGsMahbmcgxJHGsMahbmcuDQoNCi0gS2hv4bqjbmcgdGluIGPhuq15IDk1JSBj4bunYSBSUiBiYW8gZ+G7k20gMSDihpIgS2jDtG5nIGPDsyBz4buxIGtow6FjIGJp4buHdCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqLg0KDQotIEdpw6EgdHLhu4sgcC12YWx1ZSBjYW8gKHAg4omIIDEpIOKGkiBLaMO0bmcgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IEjigoAsIHThu6ljIGzDoCBraMO0bmcgY8OzIG3hu5FpIGxpw6puIGjhu4cgxJHDoW5nIGvhu4MgZ2nhu69hIHbDuW5nIG1p4buBbiAoUmVnaW9uKSB2w6AgdMOsbmggdHLhuqFuZyBk4buLY2ggYuG7h25oIChFcGlkZW1pYykgdHJvbmcgaGFpIGtodSB24buxYyBuw6B5Lg0KDQoqKlTDrW5oIG9kZCB2w6Agb2RkcmF0aW8qKg0KDQpgYGB7cn0NCiMgNC4gVMOtbmggT2RkcyB2w6AgT2RkcyBSYXRpbyB0aOG7pyBjw7RuZw0Kb2RkX05vcnRoIDwtIHJlZ2lvbl9lcGlkZW1pY1siTm9ydGgiLCAiMSJdIC8gcmVnaW9uX2VwaWRlbWljWyJOb3J0aCIsICIwIl0NCm9kZF9Tb3V0aCA8LSByZWdpb25fZXBpZGVtaWNbIlNvdXRoIiwgIjEiXSAvIHJlZ2lvbl9lcGlkZW1pY1siU291dGgiLCAiMCJdDQoNCmNhdCgiT2RkcyAoTm9ydGgpOiIsIG9kZF9Ob3J0aCwgIlxuIikNCmNhdCgiT2RkcyAoU291dGgpOiIsIG9kZF9Tb3V0aCwgIlxuIikNCg0Kb2Rkc19yYXRpbyA8LSBvZGRfU291dGggLyBvZGRfTm9ydGgNCmNhdCgiT2RkcyBSYXRpbyAoU291dGggdnMuIE5vcnRoKToiLCBvZGRzX3JhdGlvLCAiXG4iKQ0KDQojIDUuIEhv4bq3YyBkw7luZyBlcGl0b29scyDEkeG7gyB0w61uaCBPZGRzIFJhdGlvIGvDqG0ga2hv4bqjbmcgdGluIGPhuq15DQpvZGRzcmF0aW8ocmVnaW9uX2VwaWRlbWljLCBtZXRob2QgPSAibWlkcCIpDQpgYGANCg0KKipL4bq/dCBsdeG6rW4gdsOgIE5o4bqtbiB4w6l0KioNCg0KLSBPZGRzIG3huq9jIGThu4tjaCBnaeG7r2EgaGFpIHbDuW5nICoqTm9ydGgqKiB2w6AgKipTb3V0aCoqIGzDoCBi4bqxbmcgbmhhdSAoT1IgPSAxKSwgY2hvIHRo4bqleSBraOG6oyBuxINuZyBt4bqvYyBk4buLY2ggdMawxqFuZyDEkcawxqFuZy4NCg0KLSBLaG/huqNuZyB0aW4gY+G6rXkgOTUlIGPhu6dhIE9kZHMgUmF0aW8gYmFvIGfhu5NtIDEg4oaSIGtow7RuZyBjw7Mgc+G7sSBraMOhYyBiaeG7h3QgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4NCg0KLSBHacOhIHRy4buLIHAtdmFsdWUgcuG6pXQgY2FvIChwIOKJiCAxKSDihpIga2jDtG5nIGPDsyBi4bqxbmcgY2jhu6luZyBiw6FjIGLhu48gZ2nhuqMgdGh1eeG6v3QgSOKCgCwgdOG7qWMga2jDtG5nIGPDsyBt4buRaSBsacOqbiBo4buHIMSRw6FuZyBr4buDIGdp4buvYSB2w7luZyBtaeG7gW4gKFJlZ2lvbikgdsOgIHTDrG5oIHRy4bqhbmcgZOG7i2NoIGLhu4duaCAoRXBpZGVtaWMpIHRyb25nIGhhaSBraHUgduG7sWMgbsOgeS4NCg0K