PHẦN 1: TÌM
HIểU VÀ CHUẨN BỊ DỮ LIỆU
Đọ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 ...
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
| 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. |
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
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.
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 ...
PHẦN 2: PHÂN
TÍCH MÔ TẢ MỘT BIẾN ĐỊNH TÍNH
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ư Electronics và Toys có tỷ
trọng nhỏ hơn trong cơ cấu loại sản phẩm.
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, South và West 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, South và
West có vai trò tương đương nhau về quy mô trong cơ cấu khu
vực.
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à Sunny và
Rainy. 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.
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à
Spring và Summer 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, Summer và
Autumn 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.
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ẻ.
Phần 3: Ước
lượng Khoảng và Kiểm định Giả thuyết cho Tỷ lệ
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
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:
# 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%.
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
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:
# 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.
PHẦN 4: PHÂN
TÍCH MỐI QUAN HỆ GIỮA HAI BIẾN ĐỊNH TÍNH
Cặp biến
Weather.Condition và Region
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.
South và West 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ư
Rainy và Snowy.
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))

Kiểm định
thống kê
Giả thuyết kiểm định::
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
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).
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 North và South 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 North và
South 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