Phần 1: Tìm hiểu và Chuẩn bị dữ liệu
Đọc và Làm quen Dữ liệu
#Đọc dữ liệu từ file CSV
data <-read.csv("C:/Users/Hoang Quyen/Downloads/Supermarket Transactions.csv")
#Hiển thị cấu trúc dữ liệu
str(data)
## 'data.frame': 14059 obs. of 16 variables:
## $ X : int 1 2 3 4 5 6 7 8 9 10 ...
## $ PurchaseDate : chr "2007-12-18" "2007-12-20" "2007-12-21" "2007-12-21" ...
## $ CustomerID : int 7223 7841 8374 9619 1900 6696 9673 354 1293 7938 ...
## $ Gender : chr "F" "M" "F" "M" ...
## $ MaritalStatus : chr "S" "M" "M" "M" ...
## $ Homeowner : chr "Y" "Y" "N" "Y" ...
## $ Children : int 2 5 2 3 3 3 2 2 3 1 ...
## $ AnnualIncome : chr "$30K - $50K" "$70K - $90K" "$50K - $70K" "$30K - $50K" ...
## $ City : chr "Los Angeles" "Los Angeles" "Bremerton" "Portland" ...
## $ StateorProvince : chr "CA" "CA" "WA" "OR" ...
## $ Country : chr "USA" "USA" "USA" "USA" ...
## $ ProductFamily : chr "Food" "Food" "Food" "Food" ...
## $ ProductDepartment: chr "Snack Foods" "Produce" "Snack Foods" "Snacks" ...
## $ ProductCategory : chr "Snack Foods" "Vegetables" "Snack Foods" "Candy" ...
## $ UnitsSold : int 5 5 3 4 4 3 4 6 1 2 ...
## $ Revenue : num 27.38 14.9 5.52 4.44 14 ...
Kết quả trả về cho thấy data là một data.frame gồm 14,059 quan sát
(dòng) và 16 biến (cột). Mỗi biến được liệt kê với tên, kiểu dữ liệu
(chẳng hạn như int, chr, hoặc num) và một số giá trị mẫu ban đầu.
Biến định tính.
- Gender: Giới tính (M/F) – phân loại nhị phân.
- MaritalStatus: Tình trạng hôn nhân (M/S) – phân loại nhị phân.
- Homeowner: Sở hữu nhà (Y/N) – phân loại nhị phân.
- AnnualIncome: Thu nhập hàng năm (e.g., $10K–$30K, $30K–$50K,…) –
phân loại thứ tự (ordinal), vì các khoảng thu nhập có thứ tự nhưng không
phải số liên tục.
- City: Thành phố (e.g., Los Angeles, Salem,…) – phân loại danh nghĩa
(nominal).
- StateorProvince: Bang hoặc tỉnh (e.g., CA, WA, BC,…) – phân loại
danh nghĩa.
- Country: Quốc gia (USA, Canada, Mexico) – phân loại danh nghĩa.
- ProductFamily: Nhóm sản phẩm (Food, Non-Consumable, Drink) – phân
loại danh nghĩa.
- ProductDepartment: Bộ phận sản phẩm (e.g., Produce, Snack Foods,
Dairy,…) – phân loại danh nghĩa.
- ProductCategory: Danh mục sản phẩm (e.g., Vegetables, Snack Foods,
Dairy,…) – phân loại danh nghĩa.
Biến định lượng (Quantitative Variables):
- UnitsSold: Số lượng sản phẩm bán ra (1–7) – biến định lượng rời
rạc.
- Revenue: Doanh thu ($1.48–$44.78) – biến định lượng liên tục.
# Hiển thị 5 dòng đầu và cuối
head(data, 5)
## X PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## 1 1 2007-12-18 7223 F S Y 2
## 2 2 2007-12-20 7841 M M Y 5
## 3 3 2007-12-21 8374 F M N 2
## 4 4 2007-12-21 9619 M M Y 3
## 5 5 2007-12-22 1900 F S Y 3
## AnnualIncome City StateorProvince Country ProductFamily
## 1 $30K - $50K Los Angeles CA USA Food
## 2 $70K - $90K Los Angeles CA USA Food
## 3 $50K - $70K Bremerton WA USA Food
## 4 $30K - $50K Portland OR USA Food
## 5 $130K - $150K Beverly Hills CA USA Drink
## ProductDepartment ProductCategory UnitsSold Revenue
## 1 Snack Foods Snack Foods 5 27.38
## 2 Produce Vegetables 5 14.90
## 3 Snack Foods Snack Foods 3 5.52
## 4 Snacks Candy 4 4.44
## 5 Beverages Carbonated Beverages 4 14.00
tail(data, 5)
## X PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## 14055 14055 2009-12-29 9102 F M Y 2
## 14056 14056 2009-12-29 4822 F M Y 3
## 14057 14057 2009-12-31 250 M S Y 1
## 14058 14058 2009-12-31 6153 F S N 4
## 14059 14059 2009-12-31 3656 M S N 3
## AnnualIncome City StateorProvince Country ProductFamily
## 14055 $10K - $30K Bremerton WA USA Food
## 14056 $10K - $30K Walla Walla WA USA Food
## 14057 $30K - $50K Portland OR USA Drink
## 14058 $50K - $70K Spokane WA USA Drink
## 14059 $50K - $70K Portland OR USA Non-Consumable
## ProductDepartment ProductCategory UnitsSold Revenue
## 14055 Baking Goods Baking Goods 3 9.64
## 14056 Frozen Foods Vegetables 3 7.45
## 14057 Beverages Pure Juice Beverages 4 3.24
## 14058 Dairy Dairy 2 4.00
## 14059 Household Electrical 5 25.53
Hai hàm head() và tail() được sử dụng để hiển thị lần lượt 5 dòng đầu
tiên và 5 dòng cuối cùng của bộ dữ liệu, giúp đánh giá sơ bộ tính nhất
quán, định dạng và tính hợp lý của các giá trị trong từng biến. Qua việc
quan sát mẫu này, có thể nhận thấy:
Dữ liệu trải dài từ ngày 2007-12-18 đến 2009-12-31, cho thấy đây
là một tập dữ liệu có yếu tố thời gian kéo dài 3 năm.
Giá trị ở biến AnnualIncome được biểu diễn dưới dạng khoảng thu
nhập (ví dụ: “$30K - $50K”), phù hợp để xem như biến phân loại.
Các biến như ProductFamily, ProductDepartment, ProductCategory
thể hiện cấu trúc phân loại sản phẩm nhiều cấp, điều này có thể được
khai thác trong các phân tích đa biến.
Kiểm tra Giá trị Thiếu (NA)
Một bước kiểm tra quan trọng trong quy trình tiền xử lý dữ liệu là
xác định các giá trị thiếu (NA) trong các biến định tính. Trong đoạn mã
trên, các biến định tính được liệt kê thủ công vào vector
qualitative_cols, sau đó hàm sapply() được sử dụng kết hợp với hàm
is.na() để đếm số lượng giá trị thiếu trên từng biến.
#Kiểm tra NA trong các cột định tính
qualitative_cols <- c("Gender", "MaritalStatus", "Homeowner", "AnnualIncome",
"City", "StateorProvince", "Country",
"ProductFamily", "ProductDepartment", "ProductCategory")
sapply(data[qualitative_cols], function(x) sum(is.na(x)))
## Gender MaritalStatus Homeowner AnnualIncome
## 0 0 0 0
## City StateorProvince Country ProductFamily
## 0 0 0 0
## ProductDepartment ProductCategory
## 0 0
Kết quả kiểm tra cho thấy không có giá trị thiếu ở bất kỳ biến định
tính nào. Điều này rất quan trọng vì dữ liệu đầy đủ giúp đơn giản hóa
quá trình phân tích, đồng thời loại bỏ nhu cầu xử lý thiếu như loại bỏ
dòng, nội suy, hoặc thay thế giá trị.
Chuyển đổi Kiểu Dữ liệu sang Factor
Việc chuyển đổi các biến định tính từ kiểu ký tự (character) sang
kiểu nhân tố (factor) là bước then chốt để đảm bảo R hiểu đúng bản chất
của dữ liệu, đặc biệt trong các phân tích thống kê mô tả, kiểm định giả
thuyết hoặc mô hình hóa.
#Chuyển đổi sang factor
data[qualitative_cols] <- lapply(data[qualitative_cols], as.factor)
#Kiểm tra lại cấu trúc
str(data[qualitative_cols])
## 'data.frame': 14059 obs. of 10 variables:
## $ Gender : Factor w/ 2 levels "F","M": 1 2 1 2 1 1 2 1 2 2 ...
## $ MaritalStatus : Factor w/ 2 levels "M","S": 2 1 1 1 2 1 2 1 1 2 ...
## $ Homeowner : Factor w/ 2 levels "N","Y": 2 2 1 2 2 2 2 2 2 1 ...
## $ AnnualIncome : Factor w/ 8 levels "$10K - $30K",..: 5 7 6 5 3 1 5 4 1 6 ...
## $ City : Factor w/ 23 levels "Acapulco","Bellingham",..: 8 8 4 12 3 3 13 23 2 15 ...
## $ StateorProvince : Factor w/ 10 levels "BC","CA","DF",..: 2 2 8 6 2 2 6 8 8 2 ...
## $ Country : Factor w/ 3 levels "Canada","Mexico",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ ProductFamily : Factor w/ 3 levels "Drink","Food",..: 2 2 2 2 1 2 2 2 3 3 ...
## $ ProductDepartment: Factor w/ 22 levels "Alcoholic Beverages",..: 20 18 20 21 4 11 13 6 15 14 ...
## $ ProductCategory : Factor w/ 45 levels "Baking Goods",..: 42 45 42 7 15 41 5 13 16 35 ...
Sau chuyển đổi: - Gender có 2 mức độ (“F”, “M”), phù hợp với biến nhị
phân.
MaritalStatus gồm 2 mức (“M” – Married, “S” – Single).
AnnualIncome có 8 khoảng thu nhập, được xử lý như biến phân loại
thứ tự.
City và StateorProvince có số lượng mức độ lớn hơn (lần lượt 23
và 10), phản ánh sự đa dạng về địa lý.
ProductCategory có đến 45 mức độ, phản ánh sự đa dạng của danh
mục sản phẩm trong hệ thống siêu thị.
Việc chuyển sang factor cũng tối ưu hóa bộ nhớ, đồng thời cho phép sử
dụng nhiều hàm thống kê chuyên biệt như table(), summary(), tapply(),
hoặc mô hình phân loại như glm().
Phần 2: Phân tích Mô tả Một biến Định tính (Univariate
Descriptive Analysis)
Với mỗi biến định tính, tạo bảng tần suất, tỷ lệ phần trăm, biểu đồ
và nhận xét.
Biến Gender
#Bảng tần suất và tỷ lệ
gender_freq <- table(data$Gender)
gender_prop <- prop.table(gender_freq) * 100
gender_table <- data.frame(Frequency = gender_freq, Percentage = gender_prop)
print(gender_table)
## Frequency.Var1 Frequency.Freq Percentage.Var1 Percentage.Freq
## 1 F 7170 F 50.99936
## 2 M 6889 M 49.00064
#Biểu đồ tròn
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
ggplot(data, aes(x = "", fill = Gender)) +
geom_bar(width = 1) +
coord_polar("y") +
labs(title = "Phân bố Giới tính", fill = "Gender") +
theme_void()

Kết quả phân tích cho thấy trong tổng số quan sát, có 7170 khách hàng
là nữ (chiếm 51%) và 6889 khách hàng là nam (chiếm 49%). Sự phân bố giới
tính giữa nam và nữ khá cân bằng. Biểu đồ tròn minh họa rõ sự tương đồng
về tỷ lệ giới tính trong tập dữ liệu.
Biến MaritalStatus
#Bảng tần suất và tỷ lệ
marital_freq <- table(data$MaritalStatus)
marital_prop <- prop.table(marital_freq) * 100
marital_table <- data.frame(Frequency = marital_freq, Percentage = marital_prop)
print(marital_table)
## Frequency.Var1 Frequency.Freq Percentage.Var1 Percentage.Freq
## 1 M 6866 M 48.83704
## 2 S 7193 S 51.16296
# Biểu đồ cột
ggplot(data, aes(x = MaritalStatus, fill = MaritalStatus)) +
geom_bar() +
labs(title = "Phân bố Tình trạng Hôn nhân", x = "Marital Status", y = "Số lượng") +
theme_minimal()

Trong tập dữ liệu, số lượng khách hàng độc thân là 7193 người (chiếm
51.16%), trong khi đã kết hôn là 6866 người (48.84%). Phân bố tình trạng
hôn nhân giữa hai nhóm này cũng khá đồng đều, với sự chênh lệch không
đáng kể. Biểu đồ cột cho thấy mức độ tương đương giữa hai nhóm.
Biến Homeowner
#Bảng tần suất và tỷ lệ
homeowner_freq <- table(data$Homeowner)
homeowner_prop <- prop.table(homeowner_freq) * 100
homeowner_table <- data.frame(Frequency = homeowner_freq, Percentage = homeowner_prop)
print(homeowner_table)
## Frequency.Var1 Frequency.Freq Percentage.Var1 Percentage.Freq
## 1 N 5615 N 39.93883
## 2 Y 8444 Y 60.06117
#Biểu đồ tròn
ggplot(data, aes(x = "", fill = Homeowner)) +
geom_bar(width = 1) +
coord_polar("y") +
labs(title = "Phân bố Tình trạng Sở hữu Nhà", fill = "Homeowner") +
theme_void()

Tỷ lệ khách hàng sở hữu nhà (Y) chiếm ưu thế với 8444 người (60.06%)
so với nhóm không sở hữu nhà (N) là 5615 người (39.94%). Sự chênh lệch
này cho thấy đa số khách hàng trong mẫu có mức độ ổn định nhà ở cao.
Biểu đồ tròn làm rõ sự chênh lệch giữa hai nhóm.
Biến AnnualIncome
#Bảng tần suất và tỷ lệ
income_freq <- table(data$AnnualIncome)
income_prop <- prop.table(income_freq) * 100
income_table <- data.frame(Frequency = income_freq, Percentage = income_prop)
print(income_table)
## Frequency.Var1 Frequency.Freq Percentage.Var1 Percentage.Freq
## 1 $10K - $30K 3090 $10K - $30K 21.978804
## 2 $110K - $130K 643 $110K - $130K 4.573583
## 3 $130K - $150K 760 $130K - $150K 5.405790
## 4 $150K + 273 $150K + 1.941817
## 5 $30K - $50K 4601 $30K - $50K 32.726367
## 6 $50K - $70K 2370 $50K - $70K 16.857529
## 7 $70K - $90K 1709 $70K - $90K 12.155914
## 8 $90K - $110K 613 $90K - $110K 4.360196
#Biểu đồ cột
ggplot(data, aes(x = AnnualIncome, fill = AnnualIncome)) +
geom_bar() +
labs(title = "Phân bố Thu nhập Hàng năm", x = "Annual Income", y = "Số lượng") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Thu nhập của khách hàng được chia thành nhiều nhóm. Phân khúc phổ
biến nhất là từ $30K–$50K (32.73%) và $10K–$30K (21.98%). Trong khi đó,
nhóm có thu nhập trên $150K chỉ chiếm 1.94%. Phân bố thu nhập cho thấy
đa số khách hàng thuộc tầng lớp có thu nhập trung bình – thấp. Biểu đồ
cột minh họa sự phân bố không đồng đều và tập trung ở mức thu nhập thấp
và trung bình.
Biến City
city_freq <- table(data$City) # Tạo bảng tần suất
city_prop <- prop.table(city_freq) * 100 # Tính tỷ lệ phần trăm
city_table <- data.frame(City = names(city_freq),
Frequency = as.vector(city_freq),
Percentage = as.vector(city_prop)) # Chuyển thành data.frame
print(city_table) # Hiển thị toàn bộ bảng
## City Frequency Percentage
## 1 Acapulco 383 2.7242336
## 2 Bellingham 143 1.0171420
## 3 Beverly Hills 811 5.7685468
## 4 Bremerton 834 5.9321431
## 5 Camacho 452 3.2150224
## 6 Guadalajara 75 0.5334661
## 7 Hidalgo 845 6.0103848
## 8 Los Angeles 926 6.5865282
## 9 Merida 654 4.6518245
## 10 Mexico City 194 1.3798990
## 11 Orizaba 464 3.3003770
## 12 Portland 876 6.2308841
## 13 Salem 1386 9.8584537
## 14 San Andres 621 4.4170994
## 15 San Diego 866 6.1597553
## 16 San Francisco 130 0.9246746
## 17 Seattle 922 6.5580767
## 18 Spokane 875 6.2237712
## 19 Tacoma 1257 8.9408920
## 20 Vancouver 633 4.5024539
## 21 Victoria 176 1.2518671
## 22 Walla Walla 160 1.1380610
## 23 Yakima 376 2.6744434
ggplot(city_table, aes(x = City, y = Frequency, fill = City)) +
geom_bar(stat = "identity") +
labs(title = "Phân bố Thành phố", x = "Thành phố", y = "Số lượng") +
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Khách hàng đến từ nhiều thành phố khác nhau, trong đó Salem (9.86%),
Tacoma (8.94%) và Zacatecas (9.23%) là những nơi có số lượng khách hàng
cao nhất. Những thành phố như San Francisco (0.92%) và Guadalajara
(0.53%) lại có số lượng ít hơn nhiều. Biểu đồ cột cho thấy sự phân hóa
rõ rệt theo vùng địa lý.
Biến StateorProvince
#Bảng tần suất và tỷ lệ
state_freq <- table(data$StateorProvince)
state_prop <- prop.table(state_freq) * 100
state_table <- data.frame(Frequency = state_freq, Percentage = state_prop)
print(state_table)
## Frequency.Var1 Frequency.Freq Percentage.Var1 Percentage.Freq
## 1 BC 809 BC 5.7543211
## 2 CA 2733 CA 19.4395049
## 3 DF 815 DF 5.7969984
## 4 Guerrero 383 Guerrero 2.7242336
## 5 Jalisco 75 Jalisco 0.5334661
## 6 OR 2262 OR 16.0893378
## 7 Veracruz 464 Veracruz 3.3003770
## 8 WA 4567 WA 32.4845295
## 9 Yucatan 654 Yucatan 4.6518245
## 10 Zacatecas 1297 Zacatecas 9.2254072
#Biểu đồ cột
ggplot(data, aes(x = StateorProvince, fill = StateorProvince)) +
geom_bar() +
labs(title = "Phân bố Bang/Tỉnh", x = "State or Province", y = "Số lượng") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Phân bố theo bang hoặc tỉnh cho thấy Washington (WA) là khu vực chiếm
tỷ trọng lớn nhất với 32.48% khách hàng, tiếp theo là California (CA)
với 19.44% và Oregon (OR) với 16.09%. Điều này phản ánh sự tập trung dân
số tại một số bang lớn. Biểu đồ cột làm rõ sự phân bố không đồng đều
này.
Biến Country
#Bảng tần suất và tỷ lệ
country_freq <- table(data$Country)
country_prop <- prop.table(country_freq) * 100
country_table <- data.frame(Frequency = country_freq, Percentage = country_prop)
print(country_table)
## Frequency.Var1 Frequency.Freq Percentage.Var1 Percentage.Freq
## 1 Canada 809 Canada 5.754321
## 2 Mexico 3688 Mexico 26.232307
## 3 USA 9562 USA 68.013372
#Biểu đồ cột
ggplot(data, aes(x = Country, fill = Country)) +
geom_bar() +
labs(title = "Phân bố Quốc gia", x = "Country", y = "Số lượng") +
theme_minimal()

Khách hàng chủ yếu đến từ Hoa Kỳ (68.01%), sau đó là Mexico (26.23%)
và Canada (5.75%). Dữ liệu cho thấy thị trường chính của siêu thị tập
trung tại Mỹ. Biểu đồ cột nhấn mạnh sự áp đảo của khách hàng từ Hoa
Kỳ.
Biến ProductFamily
#Bảng tần suất và tỷ lệ
prod_family_freq <- table(data$ProductFamily)
prod_family_prop <- prop.table(prod_family_freq) * 100
prod_family_table <- data.frame(Frequency = prod_family_freq, Percentage = prod_family_prop)
print(prod_family_table)
## Frequency.Var1 Frequency.Freq Percentage.Var1 Percentage.Freq
## 1 Drink 1250 Drink 8.891102
## 2 Food 10153 Food 72.217085
## 3 Non-Consumable 2656 Non-Consumable 18.891813
#Biểu đồ cột
ggplot(data, aes(x = ProductFamily, fill = ProductFamily)) +
geom_bar() +
labs(title = "Phân bố Nhóm Sản phẩm", x = "Product Family", y = "Số lượng") +
theme_minimal()

Nhóm sản phẩm Food (Thực phẩm) chiếm ưu thế vượt trội (72.22%), tiếp
đến là Non-Consumable (Phi tiêu dùng) với 18.89% và Drink (Đồ uống) là
8.89%. Điều này phản ánh siêu thị chủ yếu kinh doanh thực phẩm. Biểu đồ
cột làm nổi bật tỷ trọng lớn của nhóm thực phẩm.
Biến ProductDepartment
#Bảng tần suất và tỷ lệ
prod_dept_freq <- table(data$ProductDepartment)
prod_dept_prop <- prop.table(prod_dept_freq) * 100
prod_dept_table <- data.frame(Frequency = prod_dept_freq, Percentage = prod_dept_prop)
print(prod_dept_table)
## Frequency.Var1 Frequency.Freq Percentage.Var1 Percentage.Freq
## 1 Alcoholic Beverages 356 Alcoholic Beverages 2.5321858
## 2 Baked Goods 425 Baked Goods 3.0229746
## 3 Baking Goods 1072 Baking Goods 7.6250089
## 4 Beverages 680 Beverages 4.8367594
## 5 Breakfast Foods 188 Breakfast Foods 1.3372217
## 6 Canned Foods 977 Canned Foods 6.9492852
## 7 Canned Products 109 Canned Products 0.7753041
## 8 Carousel 59 Carousel 0.4196600
## 9 Checkout 82 Checkout 0.5832563
## 10 Dairy 903 Dairy 6.4229319
## 11 Deli 699 Deli 4.9719041
## 12 Eggs 198 Eggs 1.4083505
## 13 Frozen Foods 1382 Frozen Foods 9.8300021
## 14 Health and Hygiene 893 Health and Hygiene 6.3518031
## 15 Household 1420 Household 10.1002916
## 16 Meat 89 Meat 0.6330464
## 17 Periodicals 202 Periodicals 1.4368020
## 18 Produce 1994 Produce 14.1830856
## 19 Seafood 102 Seafood 0.7255139
## 20 Snack Foods 1600 Snack Foods 11.3806103
## 21 Snacks 352 Snacks 2.5037343
## 22 Starchy Foods 277 Starchy Foods 1.9702682
#Biểu đồ cột
ggplot(data, aes(x = ProductDepartment, fill = ProductDepartment)) +
geom_bar() +
labs(title = "Phân bố Bộ phận Sản phẩm", x = "Product Department", y = "Số lượng") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Danh mục có tần suất cao nhất là Vegetables (12.29%), Snack Foods
(11.38%), và Produce (14.18%). Một số danh mục hiếm như Canned Oysters,
Miscellaneous, và Candles có tỷ lệ dưới 0.5%. Phân tích này cho thấy sự
tập trung mạnh mẽ vào các danh mục thực phẩm tươi sống và đồ ăn nhẹ.
Biểu đồ cột giúp trực quan hóa rõ nét 10 danh mục phổ biến nhất.
Biến ProductCategory
# Tạo bảng tần suất
prod_cat_freq <- table(data$ProductCategory)
# Tính tỷ lệ phần trăm
prod_cat_prop <- prop.table(prod_cat_freq) * 100
# Chuyển thành data.frame
prod_cat_table <- data.frame(Category = names(prod_cat_freq),
Frequency = as.vector(prod_cat_freq),
Percentage = as.vector(prod_cat_prop))
# Hiển thị toàn bộ bảng
print(prod_cat_table)
## Category Frequency Percentage
## 1 Baking Goods 484 3.4426346
## 2 Bathroom Products 365 2.5962017
## 3 Beer and Wine 356 2.5321858
## 4 Bread 425 3.0229746
## 5 Breakfast Foods 417 2.9660716
## 6 Candles 45 0.3200797
## 7 Candy 352 2.5037343
## 8 Canned Anchovies 44 0.3129668
## 9 Canned Clams 53 0.3769827
## 10 Canned Oysters 35 0.2489508
## 11 Canned Sardines 40 0.2845153
## 12 Canned Shrimp 38 0.2702895
## 13 Canned Soup 404 2.8736041
## 14 Canned Tuna 87 0.6188207
## 15 Carbonated Beverages 154 1.0953837
## 16 Cleaning Supplies 189 1.3443346
## 17 Cold Remedies 93 0.6614980
## 18 Dairy 903 6.4229319
## 19 Decongestants 85 0.6045949
## 20 Drinks 135 0.9602390
## 21 Eggs 198 1.4083505
## 22 Electrical 355 2.5250729
## 23 Frozen Desserts 323 2.2974607
## 24 Frozen Entrees 118 0.8393200
## 25 Fruit 765 5.4413543
## 26 Hardware 129 0.9175617
## 27 Hot Beverages 226 1.6075112
## 28 Hygiene 197 1.4012376
## 29 Jams and Jellies 588 4.1823743
## 30 Kitchen Products 217 1.5434953
## 31 Magazines 202 1.4368020
## 32 Meat 761 5.4129028
## 33 Miscellaneous 42 0.2987410
## 34 Packaged Vegetables 48 0.3414183
## 35 Pain Relievers 192 1.3656732
## 36 Paper Products 345 2.4539441
## 37 Pizza 194 1.3798990
## 38 Plastic Products 141 1.0029163
## 39 Pure Juice Beverages 165 1.1736254
## 40 Seafood 102 0.7255139
## 41 Side Dishes 153 1.0882709
## 42 Snack Foods 1600 11.3806103
## 43 Specialty 289 2.0556227
## 44 Starchy Foods 277 1.9702682
## 45 Vegetables 1728 12.2910591
# Biểu đồ cột
ggplot(prod_cat_table, aes(x = Category, y = Frequency)) +
geom_bar(stat = "identity") +
labs(title = "Phân bố Danh mục Sản phẩm", x = "Danh mục Sản phẩm", y = "Số lượng") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Danh mục có tần suất cao nhất là Vegetables (12.29%), Snack Foods
(11.38%), và Produce (14.18%). Một số danh mục hiếm như Canned Oysters,
Miscellaneous, và Candles có tỷ lệ dưới 0.5%. Phân tích này cho thấy sự
tập trung mạnh mẽ vào các danh mục thực phẩm tươi sống và đồ ăn nhẹ.
Biểu đồ cột giúp trực quan hóa rõ nét 10 danh mục phổ biến nhất.
Phần 3: Ước lượng Khoảng và Kiểm định Giả thuyết cho Tỷ
lệ
Trong phần này, mục tiêu là ước lượng khoảng tin cậy cho tỷ lệ của
một số hạng mục định tính cụ thể và thực hiện kiểm định giả thuyết một
tỷ lệ, nhằm kiểm tra xem tỷ lệ quan sát được trong mẫu có khác biệt đáng
kể so với một tỷ lệ giả định hay không.
Biến Gender (Hạng mục: Nữ)
Giả thuyết kiểm định:
H₀: Tỷ lệ nữ trong mẫu bằng 50% (p = 0.5)
H₁: Tỷ lệ nữ khác 50%
#Ước lượng Khoảng Tin cậy
n <- nrow(data)
female_count <- sum(data$Gender == "F")
prop_female <- female_count / n
se_female <- sqrt(prop_female * (1 - prop_female) / n)
ci_female <- prop_female + c(-1, 1) * 1.96 * se_female
cat("Khoảng tin cậy 95% cho tỷ lệ Nữ:", round(ci_female * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ Nữ: 50.17 51.83 %
#Kiểm định Giả thuyết (H0: Tỷ lệ Nữ = 0.5)
prop.test(female_count, n, p = 0.5, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: female_count out of n, null probability 0.5
## X-squared = 5.5765, df = 1, p-value = 0.0182
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.5016931 0.5182886
## sample estimates:
## p
## 0.5099936
Kết quả phân tích
Khoảng tin cậy 95%: [50.17%, 51.83%]
Giá trị p-value: 0.02 < 0.05
Nhận xét
Vì khoảng tin cậy không chứa đúng 50%, và giá trị p nhỏ hơn 0.05, ta
có đủ bằng chứng để bác bỏ giả thuyết H0. Như vậy, tỷ lệ khách hàng nữ
thực tế có sự khác biệt đáng kể so với mức giả định 50%, mặc dù sự khác
biệt là nhỏ. Điều này cho thấy khách hàng nữ chiếm tỷ lệ nhỉnh hơn một
chút so với khách hàng nam.
Biến MaritalStatus (Hạng mục: Đã kết hôn)
Giả thuyết kiểm định
H0: Tỷ lệ đã kết hôn = 50%
H1: Tỷ lệ đã kết hôn ≠ 50%
#Ước lượng Khoảng Tin cậy
married_count <- sum(data$MaritalStatus == "M")
prop_married <- married_count / n
se_married <- sqrt(prop_married * (1 - prop_married) / n)
ci_married <- prop_married + c(-1, 1) * 1.96 * se_married
cat("Khoảng tin cậy 95% cho tỷ lệ Đã kết hôn:", round(ci_married * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ Đã kết hôn: 48.01 49.66 %
#Kiểm định Giả thuyết (H0: Tỷ lệ Đã kết hôn = 0.5)
prop.test(married_count, n, p = 0.5, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: married_count out of n, null probability 0.5
## X-squared = 7.5593, df = 1, p-value = 0.00597
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.4800765 0.4966708
## sample estimates:
## p
## 0.4883704
Kết quả phân tích
Khoảng tin cậy 95%: [48.01%, 49.66%]
p-value: 0.006 < 0.05
Nhận xét Tỷ lệ khách hàng đã kết hôn thấp hơn đáng kể so với mức giả
định 50%. Khoảng tin cậy không chứa 0.5 và p-value nhỏ cho thấy có ý
nghĩa thống kê. Do đó, đa phần khách hàng là người chưa kết hôn, điều
này có thể gợi ý về xu hướng chi tiêu hoặc lối sống khác biệt.
Biến Homeowner (Hạng mục: Có nhà)
Giả thuyết kiểm định
H0: Tỷ lệ sở hữu nhà = 60%
H1: Tỷ lệ sở hữu nhà ≠ 60%
#Ước lượng Khoảng Tin cậy
homeowner_count <- sum(data$Homeowner == "Y")
prop_homeowner <- homeowner_count / n
se_homeowner <- sqrt(prop_homeowner * (1 - prop_homeowner) / n)
ci_homeowner <- prop_homeowner + c(-1, 1) * 1.96 * se_homeowner
cat("Khoảng tin cậy 95% cho tỷ lệ Sở hữu Nhà:", round(ci_homeowner * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ Sở hữu Nhà: 59.25 60.87 %
#Kiểm định Giả thuyết (H0: Tỷ lệ Sở hữu Nhà = 0.6)
prop.test(homeowner_count, n, p = 0.6, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: homeowner_count out of n, null probability 0.6
## X-squared = 0.019445, df = 1, p-value = 0.8891
## alternative hypothesis: true p is not equal to 0.6
## 95 percent confidence interval:
## 0.5924537 0.6087145
## sample estimates:
## p
## 0.6006117
Kết quả phân tích
Khoảng tin cậy 95%: [59.25%, 60.87%]
p-value: 0.90 > 0.05
Nhận xét Khoảng tin cậy bao gồm giá trị 60% và p-value rất lớn, do đó
không có đủ bằng chứng để bác bỏ giả thuyết H0. Điều này cho thấy tỷ lệ
khách hàng sở hữu nhà phù hợp với giả định, tức là khoảng 60% khách hàng
là chủ sở hữu nhà.
Biến AnnualIncome (Hạng mục: $30K - $50K)
Giả thuyết kiểm định
H0: Tỷ lệ thu nhập này = 30%
H1: Tỷ lệ ≠ 30%
#Ước lượng Khoảng Tin cậy
income_count <- sum(data$AnnualIncome == "$30K - $50K")
prop_income <- income_count / n
se_income <- sqrt(prop_income * (1 - prop_income) / n)
ci_income <- prop_income + c(-1, 1) * 1.96 * se_income
cat("Khoảng tin cậy 95% cho tỷ lệ $30K - $50K:", round(ci_income * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ $30K - $50K: 31.95 33.5 %
#Kiểm định Giả thuyết (H0: Tỷ lệ $30K - $50K = 0.3)
prop.test(income_count, n, p = 0.3, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: income_count out of n, null probability 0.3
## X-squared = 49.633, df = 1, p-value = 1.854e-12
## alternative hypothesis: true p is not equal to 0.3
## 95 percent confidence interval:
## 0.3195204 0.3351018
## sample estimates:
## p
## 0.3272637
Kết quả phân tích
Khoảng tin cậy 95%: [31.95%, 33.51%]
p-value: 2e-12 < 0.05
Nhận xét Tỷ lệ khách hàng thuộc nhóm thu nhập 30K–50K cao hơn đáng kể
so với 30%, và điều này có ý nghĩa thống kê mạnh. Kết quả cho thấy đây
là nhóm thu nhập phổ biến, có thể là mục tiêu tiếp thị hiệu quả.
Biến City (Hạng mục: Salem)
Giả thuyết kiểm định
H0: Tỷ lệ khách hàng từ Salem = 15%
H1: Tỷ lệ ≠ 15%
#Ước lượng Khoảng Tin cậy
city_count <- sum(data$City == "Salem")
prop_city <- city_count / n
se_city <- sqrt(prop_city * (1 - prop_city) / n)
ci_city <- prop_city + c(-1, 1) * 1.96 * se_city
cat("Khoảng tin cậy 95% cho tỷ lệ Salem:", round(ci_city * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ Salem: 9.37 10.35 %
#Kiểm định Giả thuyết (H0: Tỷ lệ Salem = 0.15)
prop.test(city_count, n, p = 0.15, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: city_count out of n, null probability 0.15
## X-squared = 291.09, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.15
## 95 percent confidence interval:
## 0.09373125 0.10365871
## sample estimates:
## p
## 0.09858454
Kết quả phân tích
Khoảng tin cậy 95%: [9.37%, 10.35%]
p-value: < 2e-16
Nhận xét Tỷ lệ khách hàng đến từ Salem thấp hơn nhiều so với giả định
15%. Khoảng tin cậy nhỏ và p rất thấp cho thấy sự khác biệt có ý nghĩa
rõ rệt. Điều này cho thấy Salem không phải thị trường trọng yếu trong dữ
liệu hiện tại.
Biến StateorProvince (Hạng mục: WA)
Giả thuyết kiểm định
H0: Tỷ lệ khách hàng ở bang WA = 40%
H1: Tỷ lệ ≠ 40%
#Ước lượng Khoảng Tin cậy
state_count <- sum(data$StateorProvince == "WA")
prop_state <- state_count / n
se_state <- sqrt(prop_state * (1 - prop_state) / n)
ci_state <- prop_state + c(-1, 1) * 1.96 * se_state
cat("Khoảng tin cậy 95% cho tỷ lệ WA:", round(ci_state * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ WA: 31.71 33.26 %
#Kiểm định Giả thuyết (H0: Tỷ lệ WA = 0.4)
prop.test(state_count, n, p = 0.4, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: state_count out of n, null probability 0.4
## X-squared = 330.56, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.4
## 95 percent confidence interval:
## 0.3171175 0.3326693
## sample estimates:
## p
## 0.3248453
Kết quả phân tích
Khoảng tin cậy 95%: [31.71%, 33.26%]
p-value: < 2e-16
Nhận xét Tỷ lệ khách hàng từ bang WA thấp hơn đáng kể so với giả
định. Điều này cho thấy WA không chiếm ưu thế trong mẫu, và có thể cần
điều chỉnh nếu mẫu cần đại diện cho bang này.
# Đếm số lượng giao dịch cho Canada và Mexico
canada_count <- sum(data$Country == "Canada") # 809
mexico_count <- sum(data$Country == "Mexico") # 3688
n <- nrow(data) # 14059
# Kiểm định giả thuyết
prop.test(c(canada_count, mexico_count), n = c(n, n),
p = c(0.5, 0.5), alternative = "less", conf.level = 0.95)
##
## 2-sample test for given proportions with continuity correction
##
## data: c(canada_count, mexico_count) out of c(n, n), null probabilities c(0.5, 0.5)
## X-squared = 14183, df = 2, p-value < 2.2e-16
## alternative hypothesis: two.sided
## null values:
## prop 1 prop 2
## 0.5 0.5
## sample estimates:
## prop 1 prop 2
## 0.05754321 0.26232307
Biến Country (Hạng mục: USA)
Giả thuyết kiểm định
H0: Tỷ lệ khách hàng từ USA = 80%
H1: Tỷ lệ ≠ 80%
#Ước lượng Khoảng Tin cậy
country_count <- sum(data$Country == "USA")
prop_country <- country_count / n
se_country <- sqrt(prop_country * (1 - prop_country) / n)
ci_country <- prop_country + c(-1, 1) * 1.96 * se_country
cat("Khoảng tin cậy 95% cho tỷ lệ USA:", round(ci_country * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ USA: 67.24 68.78 %
#Kiểm định Giả thuyết (H0: Tỷ lệ USA = 0.8)
prop.test(country_count, n, p = 0.8, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: country_count out of n, null probability 0.8
## X-squared = 1261.7, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.8
## 95 percent confidence interval:
## 0.6723397 0.6878289
## sample estimates:
## p
## 0.6801337
Kết quả phân tích
Khoảng tin cậy 95%: [67.24%, 68.78%]
p-value: < 2e-16
Nhận xét Tỷ lệ khách hàng từ Hoa Kỳ thấp hơn hẳn so với giả định 80%.
Điều này cho thấy dữ liệu không hoàn toàn tập trung vào thị trường Mỹ,
có thể do doanh nghiệp mở rộng ra quốc tế hoặc lấy mẫu không đại
diện.
Biến ProductFamily (Hạng mục: Food)
Giả thuyết kiểm định
H0: Tỷ lệ ≥ 70%
H1: Tỷ lệ < 70%
#Ước lượng Khoảng Tin cậy
food_count <- sum(data$ProductFamily == "Food")
prop_food <- food_count / n
se_food <- sqrt(prop_food * (1 - prop_food) / n)
ci_food <- prop_food + c(-1, 1) * 1.96 * se_food
cat("Khoảng tin cậy 95% cho tỷ lệ Food:", round(ci_food * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ Food: 71.48 72.96 %
#Kiểm định Giả thuyết (H0: Tỷ lệ Food ≥ 0.7)
prop.test(food_count, n, p = 0.7, alternative = "greater", conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: food_count out of n, null probability 0.7
## X-squared = 32.802, df = 1, p-value = 5.101e-09
## alternative hypothesis: true p is greater than 0.7
## 95 percent confidence interval:
## 0.7158789 1.0000000
## sample estimates:
## p
## 0.7221709
Kết quả phân tích
Khoảng tin cậy 95%: [71.59%, 100%]
p-value: 5e-09
Nhận xét Vì p rất nhỏ và toàn bộ khoảng tin cậy nằm trên 70%, có đủ
bằng chứng khẳng định rằng tỷ lệ sản phẩm thuộc nhóm “Food” lớn hơn 70%,
cho thấy nhóm này chiếm ưu thế lớn trong danh mục.
Biến ProductDepartment (Hạng mục: Snack Foods)
Giả thuyết kiểm định
H0: Tỷ lệ Snack Foods = 15%
H1: Tỷ lệ ≠ 15%
#Ước lượng Khoảng Tin cậy
dept_count <- sum(data$ProductDepartment == "Snack Foods")
prop_dept <- dept_count / n
se_dept <- sqrt(prop_dept * (1 - prop_dept) / n)
ci_dept <- prop_dept + c(-1, 1) * 1.96 * se_dept
cat("Khoảng tin cậy 95% cho tỷ lệ Snack Foods:", round(ci_dept * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ Snack Foods: 10.86 11.91 %
#Kiểm định Giả thuyết (H0: Tỷ lệ Snack Foods = 0.15)
prop.test(dept_count, n, p = 0.15, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: dept_count out of n, null probability 0.15
## X-squared = 144.17, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.15
## 95 percent confidence interval:
## 0.1086269 0.1191977
## sample estimates:
## p
## 0.1138061
Kết quả phân tích
Khoảng tin cậy 95%: [10.86%, 11.91%]
p-value: < 2e-16
Nhận xét Tỷ lệ sản phẩm Snack Foods thấp hơn đáng kể so với giả định.
Có thể thấy rằng mặc dù phổ biến nhưng chưa đến mức chiếm 15%, và doanh
nghiệp có thể cân nhắc phân phối phù hợp hơn.
Biến ProductCategory (Hạng mục: Snack Foods)
#Ước lượng Khoảng Tin cậy
cat_count <- sum(data$ProductCategory == "Snack Foods")
prop_cat <- cat_count / n
se_cat <- sqrt(prop_cat * (1 - prop_cat) / n)
ci_cat <- prop_cat + c(-1, 1) * 1.96 * se_cat
cat("Khoảng tin cậy 95% cho tỷ lệ Snack Foods:", round(ci_cat * 100, 2), "%\n")
## Khoảng tin cậy 95% cho tỷ lệ Snack Foods: 10.86 11.91 %
#Kiểm định Giả thuyết (H0: Tỷ lệ Snack Foods = 0.15)
prop.test(cat_count, n, p = 0.15, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: cat_count out of n, null probability 0.15
## X-squared = 144.17, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.15
## 95 percent confidence interval:
## 0.1086269 0.1191977
## sample estimates:
## p
## 0.1138061
Kết quả phân tích
Khoảng tin cậy 95%: [10.86%, 11.91%]
p-value: < 2e-16
Nhận xét: Tỷ lệ chỉ khoảng 11.38%, thấp hơn 15% nên cũng bác bỏ giả
thuyết H0.
Phần 4: Phân tích Mối quan hệ giữa Hai biến Định
tính
** Cặp MaritalStatus và Homeowner**
#Bảng Tần suất Chéo
cross_table1 <- table(data$MaritalStatus, data$Homeowner)
cross_prop1 <- prop.table(cross_table1, margin = 1) * 100
print(cross_table1)
##
## N Y
## M 1719 5147
## S 3896 3297
print(round(cross_prop1, 2))
##
## N Y
## M 25.04 74.96
## S 54.16 45.84
Dữ liệu được phân loại theo hai biến định tính: MaritalStatus (Tình
trạng hôn nhân: M – Married, S – Single) và Homeowner (Sở hữu nhà: Y –
Yes, N – No). Bảng tần suất cho thấy người đã kết hôn chiếm tỷ lệ sở hữu
nhà cao hơn (74,96%) so với người độc thân (45,84%). Điều này thể hiện
sự khác biệt đáng kể trong hành vi sở hữu nhà giữa hai nhóm hôn
nhân.
#Trực quan hóa
ggplot(data, aes(x = MaritalStatus, fill = Homeowner)) +
geom_bar(position = "fill") +
labs(title = "Sở hữu Nhà theo Tình trạng Hôn nhân", x = "Marital Status", y = "Tỷ lệ", fill = "Homeowner") +
theme_minimal()
Biểu đồ thanh tỷ lệ (stacked bar chart theo tỷ lệ phần trăm) trực quan
hóa điều này rất rõ ràng: người đã kết hôn có xu hướng sở hữu nhà nhiều
hơn đáng kể so với người độc thân.
Nhằm kiểm định xem MaritalStatus và Homeowner có mối quan hệ thống kê
hay không, kiểm định Chi-bình phương được sử dụng.
Giả thuyết H₀: Hai biến MaritalStatus và Homeowner là độc lập.
Giả thuyết H₁: Hai biến có mối liên hệ thống kê.
#Kiểm định Chi-bình phương
chi_test1 <- chisq.test(cross_table1)
print(chi_test1)
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: cross_table1
## X-squared = 1241.2, df = 1, p-value < 2.2e-16
Kết quả:
Giá trị thống kê chi bình phương (X²) = 1241
Bậc tự do (df) = 1
p-value < 2e-16
Nhận xét:
Kiểm định Chi-bình phương (Pearson’s Chi-squared Test) nhằm xác định
xem hai biến định tính có độc lập nhau hay không. Ở đây, giá trị p rất
nhỏ (< 0,05), cho thấy bác bỏ giả thuyết độc lập, tức là có mối liên
hệ có ý nghĩa thống kê giữa tình trạng hôn nhân và sở hữu nhà. Cụ thể,
người đã kết hôn có xu hướng sở hữu nhà nhiều hơn so với người độc
thân.
Cặp AnnualIncome và ProductFamily
#Bảng Tần suất Chéo
cross_table2 <- table(data$AnnualIncome, data$ProductFamily)
cross_prop2 <- prop.table(cross_table2, margin = 1) * 100
print(cross_table2)
##
## Drink Food Non-Consumable
## $10K - $30K 267 2232 591
## $110K - $130K 59 468 116
## $130K - $150K 56 556 148
## $150K + 25 199 49
## $30K - $50K 421 3340 840
## $50K - $70K 193 1705 472
## $70K - $90K 156 1221 332
## $90K - $110K 73 432 108
print(round(cross_prop2, 2))
##
## Drink Food Non-Consumable
## $10K - $30K 8.64 72.23 19.13
## $110K - $130K 9.18 72.78 18.04
## $130K - $150K 7.37 73.16 19.47
## $150K + 9.16 72.89 17.95
## $30K - $50K 9.15 72.59 18.26
## $50K - $70K 8.14 71.94 19.92
## $70K - $90K 9.13 71.45 19.43
## $90K - $110K 11.91 70.47 17.62
Bảng cho thấy phần lớn các nhóm thu nhập tiêu dùng chủ yếu ở nhóm sản
phẩm “Food” (chiếm khoảng 70–73%), tiếp theo là “Non-Consumable” và thấp
nhất là “Drink”, bất kể mức thu nhập. Tỷ lệ này tương đối ổn định giữa
các nhóm thu nhập, cho thấy sự phân bố đồng đều theo nhóm sản phẩm.
#Trực quan hóa
ggplot(data, aes(x = AnnualIncome, fill = ProductFamily)) +
geom_bar(position = "fill") +
labs(title = "Nhóm Sản phẩm theo Thu nhập", x = "Annual Income", y = "Tỷ lệ", fill = "Product Family") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Biểu đồ tỷ lệ theo nhóm thu nhập cho thấy dù thu nhập tăng hay giảm,
tỷ trọng các nhóm sản phẩm vẫn không có sự chênh lệch lớn.
Nhằm kiểm định xem AnnualIncome và ProductFamily có mối quan hệ thống
kê hay không, kiểm định Chi-bình phương được sử dụng.
Giả thuyết H₀: Hai biến AnnualIncomer và ProductFamily là độc
lập.
Giả thuyết H₁: Hai biến có mối liên hệ thống kê.
#Kiểm định Chi-bình phương
chi_test2 <- chisq.test(cross_table2)
print(chi_test2)
##
## Pearson's Chi-squared test
##
## data: cross_table2
## X-squared = 14.84, df = 14, p-value = 0.3892
Kết quả:
Giá trị thống kê X² = 15
df = 14
p-value = 0.4
Nhận xét:
Với p-value = 0.4 (> 0.05), ta không bác bỏ giả thuyết độc lập,
tức là không có bằng chứng thống kê cho thấy mối quan hệ giữa thu nhập
và loại sản phẩm được tiêu dùng. Điều này cho thấy hành vi mua sắm theo
nhóm sản phẩm dường như không bị ảnh hưởng bởi mức thu nhập.
** Cặp Gender và MaritalStatus**
#Bảng tần suất chéo
cross_table3 <- table(data$Gender, data$ MaritalStatus)
cross_prop3 <- prop.table(cross_table3, margin = 1) * 100
print(cross_table3)
##
## M S
## F 3602 3568
## M 3264 3625
print(round(cross_prop3, 2))
##
## M S
## F 50.24 49.76
## M 47.38 52.62
Nhìn chung, kết quả cho thấy tỷ lệ người kết hôn và độc thân giữa nam
và nữ là khá cân bằng. Trong đó, nữ giới có tỷ lệ kết hôn cao hơn một
chút so với nam giới (50.24% so với 47.38%), trong khi nam giới có tỷ lệ
độc thân cao hơn (52.62%).
# Biểu đồ cột chồng
ggplot(data, aes(x = Gender, fill = MaritalStatus)) +
geom_bar(position = "fill") +
labs(title = "Phân bố Tình trạng hôn nhân theo Giới tính", x = "Gender", y = "Tỷ lệ", fill = " MaritalStatus") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Nhằm kiểm định xem Gender và MaritalStatus có mối quan hệ thống kê
hay không, kiểm định Chi-bình phương được sử dụng.
Giả thuyết H₀: Hai biến Gender và MaritalStatus là độc lập.
Giả thuyết H₁: Hai biến có mối liên hệ thống kê.
# Kiểm định Chi-bình phương
chi_test3 <- chisq.test(cross_table3)
print(chi_test3)
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: cross_table3
## X-squared = 11.365, df = 1, p-value = 0.0007485
Kết quả kiểm định:
Giá trị thống kê Chi-squared: X² = 11
Bậc tự do: df = 1
Giá trị p: p-value < 7e-04
Nhận xét: Với giá trị p nhỏ hơn 0.05 rất nhiều (p < 7e-04), ta bác
bỏ giả thuyết H₀. Điều này cho thấy có mối liên hệ thống kê rõ rệt giữa
giới tính và tình trạng hôn nhân trong tập dữ liệu. Nói cách khác, giới
tính có ảnh hưởng đáng kể đến tình trạng hôn nhân của khách hàng siêu
thị.
Phân tích Suy diễn Thống kê trong Bảng Ngẫu nhiên
2x2
** Lý thuyết**
Rủi ro tương đối (Relative Risk)
Khái niệm: Rủi ro tương đối (Relative Risk, viết tắt
là RR) là một chỉ số thống kê được sử dụng để so sánh xác suất xảy ra
một biến cố (thường là “thành công” hoặc “có đặc điểm”) giữa hai nhóm
phân biệt theo biến độc lập. Chỉ số này đặc biệt phổ biến trong các
nghiên cứu dịch tễ học dạng thuần tập (cohort studies).
Ký hiệu và công thức:
Gọi \pi_1 và \pi_2 lần lượt là xác suất
thành công ở hai nhóm so sánh, khi đó rủi ro tương đối được định nghĩa
như sau:
RR = \frac{\pi_1}{\pi_2}
Giải thích:
RR cho biết xác suất xảy ra sự kiện ở nhóm thứ nhất gấp bao nhiêu lần
so với nhóm thứ hai. Nếu:
- RR = 1`: Không có sự khác biệt giữa hai nhóm.
- RR > 1`: Nhóm 1 có xác suất xảy ra sự kiện cao hơn nhóm 2.
- RR < 1`: Nhóm 1 có xác suất xảy ra sự kiện thấp hơn nhóm 2.
Ví dụ minh họa:
Giả sử một nghiên cứu khảo sát về tỷ lệ người “có nhà riêng” giữa hai
nhóm người:
| Nhóm A |
80 |
20 |
100 |
| Nhóm B |
40 |
60 |
100 |
Khi đó:
Suy ra:
RR = \frac{0.8}{0.4} = 2
Kết luận: Xác suất có nhà riêng ở nhóm A gấp 2 lần
so với nhóm B.
Tỷ lệ chênh (Odds Ratio)
Khái niệm: Tỷ lệ chênh (Odds Ratio, viết tắt là OR)
là một chỉ số thể hiện mức độ chênh lệch giữa tỷ lệ cược xảy ra sự kiện
trong hai nhóm. Khác với RR dựa trên xác suất, OR so sánh tỷ lệ giữa xác
suất thành công và thất bại trong mỗi nhóm.
Tỷ lệ cược (Odds): Tỷ lệ cược (odd) của một nhóm
\(i\) được định nghĩa là:
odd_i = \frac{\pi_i}{1 - \pi_i}
Tỷ lệ chênh giữa hai nhóm \(i\) và \(j\):
OR = \frac{odd_i}{odd_j} = \frac{\dfrac{\pi_i}{1 - \pi_i}}{\dfrac{\pi_j}{1 - \pi_j}} = \frac{\pi_i(1 - \pi_j)}{\pi_j(1 - \pi_i)}
Giải thích: OR đo lường mức độ chênh lệch giữa khả
năng xảy ra và không xảy ra sự kiện trong hai nhóm. Nếu:
- OR = 1: Không có sự khác biệt.
- OR > 1: Nhóm i có tỷ lệ cược thành công cao hơn nhóm j.
- OR < 1: Nhóm i có tỷ lệ cược thành công thấp hơn nhóm j.
Ví dụ minh họa (tiếp tục từ ví dụ RR):
- Tỷ lệ cược nhóm A:
\frac{0.8}{0.2} = 4
- Tỷ lệ cược nhóm B:
\frac{0.4}{0.6} = \frac{2}{3}
Khi đó:
OR = \frac{4}{2/3} = 6
Kết luận: Tỷ lệ cược thành công (có nhà) ở nhóm A
cao gấp 6 lần nhóm B.
So sánh giữa Odds Ratio và Relative Risk
| Công thức |
\(\frac{\pi_1}{\pi_2}\) |
\(\frac{\pi_1(1 - \pi_2)}{\pi_2(1 -
\pi_1)}\) |
| Dựa trên |
Xác suất (probability) |
Tỷ lệ cược (odds) |
| Ý nghĩa |
So sánh khả năng xảy ra sự kiện |
So sánh mức độ chênh lệch giữa odds |
| Trường hợp sử dụng chính |
Nghiên cứu thuần tập (cohort) |
Hồi quy logistic, nghiên cứu bệnh-chứng (case-control) |
| Diễn giải trực tiếp cho người không chuyên |
Dễ hơn |
Khó hơn |
| Giá trị giới hạn |
\(> 0\), thường từ 0 đến ∞ |
\(> 0\), thường từ 0 đến ∞ |
Phân tích cặp Gender và Homeowner
#Tạo bảng tần suất chéo
cross_table_gender <- table(data$Gender, data$Homeowner)
addmargins(cross_table_gender)
##
## N Y Sum
## F 2826 4344 7170
## M 2789 4100 6889
## Sum 5615 8444 14059
#Tính RR (Homeowner = Y cho F so với M)
library(DescTools)
## Warning: package 'DescTools' was built under R version 4.4.3
RelRisk(cross_table_gender)
## [1] 0.9735554
library(epitools)
riskratio(cross_table_gender)
## $data
##
## N Y Total
## F 2826 4344 7170
## M 2789 4100 6889
## Total 5615 8444 14059
##
## $measure
## risk ratio with 95% C.I.
## estimate lower upper
## F 1.0000000 NA NA
## M 0.9823291 0.9561812 1.009192
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## F NA NA NA
## M 0.195158 0.1964833 0.1950884
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
epitab(cross_table_gender, method = "riskratio")
## $tab
##
## N p0 Y p1 riskratio lower upper p.value
## F 2826 0.3941423 4344 0.6058577 1.0000000 NA NA NA
## M 2789 0.4048483 4100 0.5951517 0.9823291 0.9561812 1.009192 0.1964833
##
## $measure
## [1] "wald"
##
## $conf.level
## [1] 0.95
##
## $pvalue
## [1] "fisher.exact"
Tỷ số rủi ro (Risk Ratio - RR):
Tính toán bằng RelRisk() cho thấy RR = 0.9736 (theo DescTools) và RR
= 0.9823 với khoảng tin cậy 95% là (0.9562; 1.009) (theo epitools).
Điều này ngụ ý rằng nam giới có nguy cơ sở hữu nhà thấp hơn một chút
so với nữ giới, tuy nhiên khác biệt không có ý nghĩa thống kê (p =
0.1965 > 0.05).
# Tính OR
OddsRatio(cross_table_gender)
## [1] 0.9563518
oddsratio(cross_table_gender)
## $data
##
## N Y Total
## F 2826 4344 7170
## M 2789 4100 6889
## Total 5615 8444 14059
##
## $measure
## odds ratio with 95% C.I.
## estimate lower upper
## F 1.000000 NA NA
## M 0.956381 0.8938974 1.023169
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## F NA NA NA
## M 0.195158 0.1964833 0.1950884
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
epitab(cross_table_gender, method = "oddsratio")
## $tab
##
## N p0 Y p1 oddsratio lower upper p.value
## F 2826 0.5032947 4344 0.5144481 1.0000000 NA NA NA
## M 2789 0.4967053 4100 0.4855519 0.9563518 0.8939173 1.023147 0.1964833
##
## $measure
## [1] "wald"
##
## $conf.level
## [1] 0.95
##
## $pvalue
## [1] "fisher.exact"
Tỷ số odds (Odds Ratio - OR):
OR = 0.9564 với khoảng tin cậy 95% là (0.8939; 1.023).
Kết quả này cũng cho thấy khả năng sở hữu nhà giữa hai giới là tương
đương, và sự khác biệt không có ý nghĩa thống kê (p = 0.1965).
Mối liên hệ giữa giới tính và khả năng sở hữu nhà không đủ mạnh để
được xem là có ý nghĩa thống kê. Tỷ lệ sở hữu nhà của nữ giới (60.59%)
chỉ nhỉnh hơn nam giới (59.52%) một cách không đáng kể. Do đó, không thể
khẳng định rằng giới tính là yếu tố ảnh hưởng đến việc sở hữu nhà trong
mẫu dữ liệu này.
Phân tích cặp MaritalStatus và Homeowner
# Tạo bảng tần suất chéo
cross_table_ms <- table(data$MaritalStatus, data$Homeowner)
addmargins(cross_table_ms)
##
## N Y Sum
## M 1719 5147 6866
## S 3896 3297 7193
## Sum 5615 8444 14059
#Tính RR
RelRisk(cross_table_ms)
## [1] 0.4622354
riskratio(cross_table_ms)
## $data
##
## N Y Total
## M 1719 5147 6866
## S 3896 3297 7193
## Total 5615 8444 14059
##
## $measure
## risk ratio with 95% C.I.
## estimate lower upper
## M 1.0000000 NA NA
## S 0.6114466 0.5942071 0.6291862
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## M NA NA NA
## S 0 1.822183e-277 3.663022e-272
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
epitab(cross_table_ms, method = "riskratio")
## $tab
##
## N p0 Y p1 riskratio lower upper p.value
## M 1719 0.2503641 5147 0.7496359 1.0000000 NA NA NA
## S 3896 0.5416377 3297 0.4583623 0.6114466 0.5942071 0.6291862 1.822183e-277
##
## $measure
## [1] "wald"
##
## $conf.level
## [1] 0.95
##
## $pvalue
## [1] "fisher.exact"
Tỷ số rủi ro (Risk Ratio - RR) Giá trị RR = 0.6114, với khoảng tin
cậy 95% là (0.5942; 0.6292).
Điều này có nghĩa là nguy cơ sở hữu nhà của người độc thân chỉ bằng
khoảng 61,14% so với người đã kết hôn.
Khác biệt này là có ý nghĩa thống kê cao với p-value ≈ 1.82×10⁻²⁷⁷
(Fisher’s exact test).
#Tính OR
OddsRatio(cross_table_ms)
## [1] 0.2826322
oddsratio(cross_table_ms)
## $data
##
## N Y Total
## M 1719 5147 6866
## S 3896 3297 7193
## Total 5615 8444 14059
##
## $measure
## odds ratio with 95% C.I.
## estimate lower upper
## M 1.000000 NA NA
## S 0.282673 0.2630995 0.3036164
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## M NA NA NA
## S 0 1.822183e-277 3.663022e-272
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
epitab(cross_table_ms, method = "oddsratio")
## $tab
##
## N p0 Y p1 oddsratio lower upper p.value
## M 1719 0.3061443 5147 0.6095452 1.0000000 NA NA NA
## S 3896 0.6938557 3297 0.3904548 0.2826322 0.2630929 0.3036227 1.822183e-277
##
## $measure
## [1] "wald"
##
## $conf.level
## [1] 0.95
##
## $pvalue
## [1] "fisher.exact"
Tỷ số odds (Odds Ratio - OR) Giá trị OR = 0.2826, với khoảng tin cậy
95% là (0.2631; 0.3036).
Điều đó cho thấy rằng odds (tỷ số khả năng xảy ra và không xảy ra) sở
hữu nhà của người độc thân thấp hơn khoảng 71.7% so với người đã kết
hôn.
Kết quả này cũng có ý nghĩa thống kê rất cao (p ≈ 1.82×10⁻²⁷⁷).
Phân tích định lượng cho thấy tình trạng hôn nhân là yếu tố có ảnh
hưởng rõ rệt và có ý nghĩa thống kê cao đến việc sở hữu nhà trong mẫu
khảo sát. Cụ thể, người độc thân có nguy cơ và odds sở hữu nhà thấp hơn
đáng kể so với người đã kết hôn. Kết quả này có thể phản ánh các yếu tố
xã hội và kinh tế như nhu cầu ổn định gia đình, khả năng tài chính kết
hợp từ hai cá nhân trong hôn nhân, hoặc các chính sách hỗ trợ mua nhà
cho gia đình.
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSAyIg0KYXV0aG9yOiAiSG/DoG5nIFF1ecOqbiINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVIOiVNOiVTLCAlZCAtICVtIC0gJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UgIA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogdHJ1ZQ0KICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCmBgYHtyIGVjaG89IFRSVUUsIGV2YWw9RkFMU0V9DQpsaWJyYXJ5KHNob3d0ZXh0KQ0KZm9udF9hZGQoZmFtaWx5ID0gIkFyaWFsIiwgcmVndWxhciA9ICJhcmlhbC50dGYiKSAgIyDEkOG6o20gYuG6o28gZm9udCBBcmlhbCBjw7MgdHLDqm4gbcOheQ0Kc2hvd3RleHRfYXV0bygpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZXBpdG9vbHMpDQpsaWJyYXJ5KERlc2NUb29scykNCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KGVuZXJneSkNCmxpYnJhcnkocmVhZHIpDQpvcHRpb25zKGRpZ2l0cyA9IDQpDQpgYGANCg0KKipQaMOibiB0w61jaCBE4buvIGxp4buHdSBHaWFvIGThu4tjaCBTacOqdSB0aOG7iyoqDQoNCiMgKipQaOG6p24gMTogVMOsbSBoaeG7g3UgdsOgIENodeG6qW4gYuG7iyBk4buvIGxp4buHdSoqDQoNCiMjICoqxJDhu41jIHbDoCBMw6BtIHF1ZW4gROG7ryBsaeG7h3UqKg0KDQpgYGB7cn0NCiPEkOG7jWMgZOG7ryBsaeG7h3UgdOG7qyBmaWxlIENTVg0KZGF0YSA8LXJlYWQuY3N2KCJDOi9Vc2Vycy9Ib2FuZyBRdXllbi9Eb3dubG9hZHMvU3VwZXJtYXJrZXQgVHJhbnNhY3Rpb25zLmNzdiIpDQpgYGANCg0KYGBge3J9DQojSGnhu4NuIHRo4buLIGPhuqV1IHRyw7pjIGThu68gbGnhu4d1DQpzdHIoZGF0YSkNCmBgYA0KDQpL4bq/dCBxdeG6oyB0cuG6oyB24buBIGNobyB0aOG6pXkgZGF0YSBsw6AgbeG7mXQgZGF0YS5mcmFtZSBn4buTbSAxNCwwNTkgcXVhbiBzw6F0IChkw7JuZykgdsOgIDE2IGJp4bq/biAoY+G7mXQpLiBN4buXaSBiaeG6v24gxJHGsOG7o2MgbGnhu4d0IGvDqiB24bubaSB0w6puLCBraeG7g3UgZOG7ryBsaeG7h3UgKGNo4bqzbmcgaOG6oW4gbmjGsCBpbnQsIGNociwgaG/hurdjIG51bSkgdsOgIG3hu5l0IHPhu5EgZ2nDoSB0cuG7iyBt4bqrdSBiYW4gxJHhuqd1LiANCg0KKkJp4bq/biDEkeG7i25oIHTDrW5oLioNCg0KIC0gR2VuZGVyOiBHaeG7m2kgdMOtbmggKE0vRikg4oCTIHBow6JuIGxv4bqhaSBuaOG7iyBwaMOibi4NCiAtIE1hcml0YWxTdGF0dXM6IFTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiAoTS9TKSDigJMgcGjDom4gbG/huqFpIG5o4buLIHBow6JuLg0KIC0gSG9tZW93bmVyOiBT4bufIGjhu691IG5ow6AgKFkvTikg4oCTIHBow6JuIGxv4bqhaSBuaOG7iyBwaMOibi4NCiAtIEFubnVhbEluY29tZTogVGh1IG5o4bqtcCBow6BuZyBuxINtIChlLmcuLCAkMTBL4oCTJDMwSywgJDMwS+KAkyQ1MEssLi4uKSDigJMgcGjDom4gbG/huqFpIHRo4bupIHThu7EgKG9yZGluYWwpLCB2w6wgY8OhYyBraG/huqNuZyB0aHUgbmjhuq1wIGPDsyB0aOG7qSB04buxIG5oxrBuZyBraMO0bmcgcGjhuqNpIHPhu5EgbGnDqm4gdOG7pWMuDQogLSBDaXR5OiBUaMOgbmggcGjhu5EgKGUuZy4sIExvcyBBbmdlbGVzLCBTYWxlbSwuLi4pIOKAkyBwaMOibiBsb+G6oWkgZGFuaCBuZ2jEqWEgKG5vbWluYWwpLg0KIC0gU3RhdGVvclByb3ZpbmNlOiBCYW5nIGhv4bq3YyB04buJbmggKGUuZy4sIENBLCBXQSwgQkMsLi4uKSDigJMgcGjDom4gbG/huqFpIGRhbmggbmdoxKlhLg0KIC0gQ291bnRyeTogUXXhu5FjIGdpYSAoVVNBLCBDYW5hZGEsIE1leGljbykg4oCTIHBow6JuIGxv4bqhaSBkYW5oIG5naMSpYS4NCiAtIFByb2R1Y3RGYW1pbHk6IE5ow7NtIHPhuqNuIHBo4bqpbSAoRm9vZCwgTm9uLUNvbnN1bWFibGUsIERyaW5rKSDigJMgcGjDom4gbG/huqFpIGRhbmggbmdoxKlhLg0KIC0gUHJvZHVjdERlcGFydG1lbnQ6IELhu5kgcGjhuq1uIHPhuqNuIHBo4bqpbSAoZS5nLiwgUHJvZHVjZSwgU25hY2sgRm9vZHMsIERhaXJ5LC4uLikg4oCTIHBow6JuIGxv4bqhaSBkYW5oIG5naMSpYS4NCiAtIFByb2R1Y3RDYXRlZ29yeTogRGFuaCBt4bulYyBz4bqjbiBwaOG6qW0gKGUuZy4sIFZlZ2V0YWJsZXMsIFNuYWNrIEZvb2RzLCBEYWlyeSwuLi4pIOKAkyBwaMOibiBsb+G6oWkgZGFuaCBuZ2jEqWEuDQoNCipCaeG6v24gxJHhu4tuaCBsxrDhu6NuZyAoUXVhbnRpdGF0aXZlIFZhcmlhYmxlcyk6Kg0KDQogLSBVbml0c1NvbGQ6IFPhu5EgbMaw4bujbmcgc+G6o24gcGjhuqltIGLDoW4gcmEgKDHigJM3KSDigJMgYmnhur9uIMSR4buLbmggbMaw4bujbmcgcuG7nWkgcuG6oWMuDQogLSBSZXZlbnVlOiBEb2FuaCB0aHUgKCQxLjQ44oCTJDQ0Ljc4KSDigJMgYmnhur9uIMSR4buLbmggbMaw4bujbmcgbGnDqm4gdOG7pWMuDQogDQpgYGB7cn0NCiMgSGnhu4NuIHRo4buLIDUgZMOybmcgxJHhuqd1IHbDoCBjdeG7kWkNCmhlYWQoZGF0YSwgNSkNCnRhaWwoZGF0YSwgNSkNCmBgYA0KDQpIYWkgaMOgbSBoZWFkKCkgdsOgIHRhaWwoKSDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBoaeG7g24gdGjhu4sgbOG6p24gbMaw4bujdCA1IGTDsm5nIMSR4bqndSB0acOqbiB2w6AgNSBkw7JuZyBjdeG7kWkgY8O5bmcgY+G7p2EgYuG7mSBk4buvIGxp4buHdSwgZ2nDunAgxJHDoW5oIGdpw6Egc8ahIGLhu5kgdMOtbmggbmjhuqV0IHF1w6FuLCDEkeG7i25oIGThuqFuZyB2w6AgdMOtbmggaOG7o3AgbMO9IGPhu6dhIGPDoWMgZ2nDoSB0cuG7iyB0cm9uZyB04burbmcgYmnhur9uLg0KUXVhIHZp4buHYyBxdWFuIHPDoXQgbeG6q3UgbsOgeSwgY8OzIHRo4buDIG5o4bqtbiB0aOG6pXk6DQoNCi0gROG7ryBsaeG7h3UgdHLhuqNpIGTDoGkgdOG7qyBuZ8OgeSAyMDA3LTEyLTE4IMSR4bq/biAyMDA5LTEyLTMxLCBjaG8gdGjhuqV5IMSRw6J5IGzDoCBt4buZdCB04bqtcCBk4buvIGxp4buHdSBjw7MgeeG6v3UgdOG7kSB0aOG7nWkgZ2lhbiBrw6lvIGTDoGkgMyBuxINtLg0KDQoNCi0gR2nDoSB0cuG7iyDhu58gYmnhur9uIEFubnVhbEluY29tZSDEkcaw4bujYyBiaeG7g3UgZGnhu4VuIGTGsOG7m2kgZOG6oW5nIGtob+G6o25nIHRodSBuaOG6rXAgKHbDrSBk4bulOiAiJDMwSyAtICQ1MEsiKSwgcGjDuSBo4bujcCDEkeG7gyB4ZW0gbmjGsCBiaeG6v24gcGjDom4gbG/huqFpLg0KDQoNCi0gQ8OhYyBiaeG6v24gbmjGsCBQcm9kdWN0RmFtaWx5LCBQcm9kdWN0RGVwYXJ0bWVudCwgUHJvZHVjdENhdGVnb3J5IHRo4buDIGhp4buHbiBj4bqldSB0csO6YyBwaMOibiBsb+G6oWkgc+G6o24gcGjhuqltIG5oaeG7gXUgY+G6pXAsIMSRaeG7gXUgbsOgeSBjw7MgdGjhu4MgxJHGsOG7o2Mga2hhaSB0aMOhYyB0cm9uZyBjw6FjIHBow6JuIHTDrWNoIMSRYSBiaeG6v24uDQoNCiMjICoqS2nhu4NtIHRyYSBHacOhIHRy4buLIFRoaeG6v3UgKE5BKSoqDQoNCk3hu5l0IGLGsOG7m2Mga2nhu4NtIHRyYSBxdWFuIHRy4buNbmcgdHJvbmcgcXV5IHRyw6xuaCB0aeG7gW4geOG7rSBsw70gZOG7ryBsaeG7h3UgbMOgIHjDoWMgxJHhu4tuaCBjw6FjIGdpw6EgdHLhu4sgdGhp4bq/dSAoTkEpIHRyb25nIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmguIFRyb25nIMSRb+G6oW4gbcOjIHRyw6puLCBjw6FjIGJp4bq/biDEkeG7i25oIHTDrW5oIMSRxrDhu6NjIGxp4buHdCBrw6ogdGjhu6cgY8O0bmcgdsOgbyB2ZWN0b3IgcXVhbGl0YXRpdmVfY29scywgc2F1IMSRw7MgaMOgbSBzYXBwbHkoKSDEkcaw4bujYyBz4butIGThu6VuZyBr4bq/dCBo4bujcCB24bubaSBow6BtIGlzLm5hKCkgxJHhu4MgxJHhur9tIHPhu5EgbMaw4bujbmcgZ2nDoSB0cuG7iyB0aGnhur91IHRyw6puIHThu6tuZyBiaeG6v24uDQoNCmBgYHtyfQ0KI0tp4buDbSB0cmEgTkEgdHJvbmcgY8OhYyBj4buZdCDEkeG7i25oIHTDrW5oDQpxdWFsaXRhdGl2ZV9jb2xzIDwtIGMoIkdlbmRlciIsICJNYXJpdGFsU3RhdHVzIiwgIkhvbWVvd25lciIsICJBbm51YWxJbmNvbWUiLCANCiAgICAgICAgICAgICAgICAgICAgICAiQ2l0eSIsICJTdGF0ZW9yUHJvdmluY2UiLCAiQ291bnRyeSIsIA0KICAgICAgICAgICAgICAgICAgICAgICJQcm9kdWN0RmFtaWx5IiwgIlByb2R1Y3REZXBhcnRtZW50IiwgIlByb2R1Y3RDYXRlZ29yeSIpDQpzYXBwbHkoZGF0YVtxdWFsaXRhdGl2ZV9jb2xzXSwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkNCmBgYA0KDQpL4bq/dCBxdeG6oyBraeG7g20gdHJhIGNobyB0aOG6pXkga2jDtG5nIGPDsyBnacOhIHRy4buLIHRoaeG6v3Ug4bufIGLhuqV0IGvhu7MgYmnhur9uIMSR4buLbmggdMOtbmggbsOgby4gxJBp4buBdSBuw6B5IHLhuqV0IHF1YW4gdHLhu41uZyB2w6wgZOG7ryBsaeG7h3UgxJHhuqd5IMSR4bunIGdpw7pwIMSRxqFuIGdp4bqjbiBow7NhIHF1w6EgdHLDrG5oIHBow6JuIHTDrWNoLCDEkeG7k25nIHRo4budaSBsb+G6oWkgYuG7jyBuaHUgY+G6p3UgeOG7rSBsw70gdGhp4bq/dSBuaMawIGxv4bqhaSBi4buPIGTDsm5nLCBu4buZaSBzdXksIGhv4bq3YyB0aGF5IHRo4bq/IGdpw6EgdHLhu4suDQoNCiMjICoqQ2h1eeG7g24gxJHhu5VpIEtp4buDdSBE4buvIGxp4buHdSBzYW5nIEZhY3RvcioqDQoNClZp4buHYyBjaHV54buDbiDEkeG7lWkgY8OhYyBiaeG6v24gxJHhu4tuaCB0w61uaCB04burIGtp4buDdSBrw70gdOG7sSAoY2hhcmFjdGVyKSBzYW5nIGtp4buDdSBuaMOibiB04buRIChmYWN0b3IpIGzDoCBixrDhu5tjIHRoZW4gY2jhu5F0IMSR4buDIMSR4bqjbSBi4bqjbyBSIGhp4buDdSDEkcO6bmcgYuG6o24gY2jhuqV0IGPhu6dhIGThu68gbGnhu4d1LCDEkeG6t2MgYmnhu4d0IHRyb25nIGPDoWMgcGjDom4gdMOtY2ggdGjhu5FuZyBrw6ogbcO0IHThuqMsIGtp4buDbSDEkeG7i25oIGdp4bqjIHRodXnhur90IGhv4bq3YyBtw7QgaMOsbmggaMOzYS4NCg0KDQpgYGB7cn0NCiNDaHV54buDbiDEkeG7lWkgc2FuZyBmYWN0b3INCmRhdGFbcXVhbGl0YXRpdmVfY29sc10gPC0gbGFwcGx5KGRhdGFbcXVhbGl0YXRpdmVfY29sc10sIGFzLmZhY3RvcikNCg0KI0tp4buDbSB0cmEgbOG6oWkgY+G6pXUgdHLDumMNCnN0cihkYXRhW3F1YWxpdGF0aXZlX2NvbHNdKQ0KYGBgDQpTYXUgY2h1eeG7g24gxJHhu5VpOg0KLSBHZW5kZXIgY8OzIDIgbeG7qWMgxJHhu5kgKCJGIiwgIk0iKSwgcGjDuSBo4bujcCB24bubaSBiaeG6v24gbmjhu4sgcGjDom4uDQoNCg0KLSBNYXJpdGFsU3RhdHVzIGfhu5NtIDIgbeG7qWMgKCJNIiDigJMgTWFycmllZCwgIlMiIOKAkyBTaW5nbGUpLg0KDQoNCi0gQW5udWFsSW5jb21lIGPDsyA4IGtob+G6o25nIHRodSBuaOG6rXAsIMSRxrDhu6NjIHjhu60gbMO9IG5oxrAgYmnhur9uIHBow6JuIGxv4bqhaSB0aOG7qSB04buxLg0KDQoNCi0gQ2l0eSB2w6AgU3RhdGVvclByb3ZpbmNlIGPDsyBz4buRIGzGsOG7o25nIG3hu6ljIMSR4buZIGzhu5tuIGjGoW4gKGzhuqduIGzGsOG7o3QgMjMgdsOgIDEwKSwgcGjhuqNuIMOhbmggc+G7sSDEkWEgZOG6oW5nIHbhu4EgxJHhu4thIGzDvS4NCg0KDQotIFByb2R1Y3RDYXRlZ29yeSBjw7MgxJHhur9uIDQ1IG3hu6ljIMSR4buZLCBwaOG6o24gw6FuaCBz4buxIMSRYSBk4bqhbmcgY+G7p2EgZGFuaCBt4bulYyBz4bqjbiBwaOG6qW0gdHJvbmcgaOG7hyB0aOG7kW5nIHNpw6p1IHRo4buLLg0KDQoNClZp4buHYyBjaHV54buDbiBzYW5nIGZhY3RvciBjxaluZyB04buRaSDGsHUgaMOzYSBi4buZIG5o4bubLCDEkeG7k25nIHRo4budaSBjaG8gcGjDqXAgc+G7rSBk4bulbmcgbmhp4buBdSBow6BtIHRo4buRbmcga8OqIGNodXnDqm4gYmnhu4d0IG5oxrAgdGFibGUoKSwgc3VtbWFyeSgpLCB0YXBwbHkoKSwgaG/hurdjIG3DtCBow6xuaCBwaMOibiBsb+G6oWkgbmjGsCBnbG0oKS4NCg0KDQojICoqUGjhuqduIDI6IFBow6JuIHTDrWNoIE3DtCB04bqjIE3hu5l0IGJp4bq/biDEkOG7i25oIHTDrW5oIChVbml2YXJpYXRlIERlc2NyaXB0aXZlIEFuYWx5c2lzKSoqDQpW4bubaSBt4buXaSBiaeG6v24gxJHhu4tuaCB0w61uaCwgdOG6oW8gYuG6o25nIHThuqduIHN14bqldCwgdOG7tyBs4buHIHBo4bqnbiB0csSDbSwgYmnhu4N1IMSR4buTIHbDoCBuaOG6rW4geMOpdC4NCg0KIyMgKipCaeG6v24gR2VuZGVyKioNCmBgYHtyfQ0KI0LhuqNuZyB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hw0KZ2VuZGVyX2ZyZXEgPC0gdGFibGUoZGF0YSRHZW5kZXIpDQpnZW5kZXJfcHJvcCA8LSBwcm9wLnRhYmxlKGdlbmRlcl9mcmVxKSAqIDEwMA0KZ2VuZGVyX3RhYmxlIDwtIGRhdGEuZnJhbWUoRnJlcXVlbmN5ID0gZ2VuZGVyX2ZyZXEsIFBlcmNlbnRhZ2UgPSBnZW5kZXJfcHJvcCkNCnByaW50KGdlbmRlcl90YWJsZSkNCmBgYA0KDQoNCmBgYHtyfQ0KI0Jp4buDdSDEkeG7kyB0csOybg0KbGlicmFyeShnZ3Bsb3QyKQ0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gIiIsIGZpbGwgPSBHZW5kZXIpKSArDQogIGdlb21fYmFyKHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcigieSIpICsNCiAgbGFicyh0aXRsZSA9ICJQaMOibiBi4buRIEdp4bubaSB0w61uaCIsIGZpbGwgPSAiR2VuZGVyIikgKw0KICB0aGVtZV92b2lkKCkNCmBgYA0KDQpL4bq/dCBxdeG6oyBwaMOibiB0w61jaCBjaG8gdGjhuqV5IHRyb25nIHThu5VuZyBz4buRIHF1YW4gc8OhdCwgY8OzIDcxNzAga2jDoWNoIGjDoG5nIGzDoCBu4buvIChjaGnhur9tIDUxJSkgdsOgIDY4ODkga2jDoWNoIGjDoG5nIGzDoCBuYW0gKGNoaeG6v20gNDklKS4gU+G7sSBwaMOibiBi4buRIGdp4bubaSB0w61uaCBnaeG7r2EgbmFtIHbDoCBu4buvIGtow6EgY8OibiBi4bqxbmcuIEJp4buDdSDEkeG7kyB0csOybiBtaW5oIGjhu41hIHLDtSBz4buxIHTGsMahbmcgxJHhu5NuZyB24buBIHThu7cgbOG7hyBnaeG7m2kgdMOtbmggdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UuDQoNCg0KIyMgKipCaeG6v24gTWFyaXRhbFN0YXR1cyoqDQoNCmBgYHtyfQ0KI0LhuqNuZyB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hw0KbWFyaXRhbF9mcmVxIDwtIHRhYmxlKGRhdGEkTWFyaXRhbFN0YXR1cykNCm1hcml0YWxfcHJvcCA8LSBwcm9wLnRhYmxlKG1hcml0YWxfZnJlcSkgKiAxMDANCm1hcml0YWxfdGFibGUgPC0gZGF0YS5mcmFtZShGcmVxdWVuY3kgPSBtYXJpdGFsX2ZyZXEsIFBlcmNlbnRhZ2UgPSBtYXJpdGFsX3Byb3ApDQpwcmludChtYXJpdGFsX3RhYmxlKQ0KYGBgDQoNCmBgYHtyfQ0KIyBCaeG7g3UgxJHhu5MgY+G7mXQNCmdncGxvdChkYXRhLCBhZXMoeCA9IE1hcml0YWxTdGF0dXMsIGZpbGwgPSBNYXJpdGFsU3RhdHVzKSkgKw0KICBnZW9tX2JhcigpICsNCiAgbGFicyh0aXRsZSA9ICJQaMOibiBi4buRIFTDrG5oIHRy4bqhbmcgSMO0biBuaMOibiIsIHggPSAiTWFyaXRhbCBTdGF0dXMiLCB5ID0gIlPhu5EgbMaw4bujbmciKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNClRyb25nIHThuq1wIGThu68gbGnhu4d1LCBz4buRIGzGsOG7o25nIGtow6FjaCBow6BuZyDEkeG7mWMgdGjDom4gbMOgIDcxOTMgbmfGsOG7nWkgKGNoaeG6v20gNTEuMTYlKSwgdHJvbmcga2hpIMSRw6Mga+G6v3QgaMO0biBsw6AgNjg2NiBuZ8aw4budaSAoNDguODQlKS4gUGjDom4gYuG7kSB0w6xuaCB0cuG6oW5nIGjDtG4gbmjDom4gZ2nhu69hIGhhaSBuaMOzbSBuw6B5IGPFqW5nIGtow6EgxJHhu5NuZyDEkeG7gXUsIHbhu5tpIHPhu7EgY2jDqm5oIGzhu4djaCBraMO0bmcgxJHDoW5nIGvhu4MuIEJp4buDdSDEkeG7kyBj4buZdCBjaG8gdGjhuqV5IG3hu6ljIMSR4buZIHTGsMahbmcgxJHGsMahbmcgZ2nhu69hIGhhaSBuaMOzbS4NCg0KIyMgKipCaeG6v24gSG9tZW93bmVyKioNCg0KYGBge3J9DQojQuG6o25nIHThuqduIHN14bqldCB2w6AgdOG7tyBs4buHDQpob21lb3duZXJfZnJlcSA8LSB0YWJsZShkYXRhJEhvbWVvd25lcikNCmhvbWVvd25lcl9wcm9wIDwtIHByb3AudGFibGUoaG9tZW93bmVyX2ZyZXEpICogMTAwDQpob21lb3duZXJfdGFibGUgPC0gZGF0YS5mcmFtZShGcmVxdWVuY3kgPSBob21lb3duZXJfZnJlcSwgUGVyY2VudGFnZSA9IGhvbWVvd25lcl9wcm9wKQ0KcHJpbnQoaG9tZW93bmVyX3RhYmxlKQ0KYGBgDQoNCg0KYGBge3J9DQojQmnhu4N1IMSR4buTIHRyw7JuDQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSAiIiwgZmlsbCA9IEhvbWVvd25lcikpICsNCiAgZ2VvbV9iYXIod2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKCJ5IikgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgVMOsbmggdHLhuqFuZyBT4bufIGjhu691IE5ow6AiLCBmaWxsID0gIkhvbWVvd25lciIpICsNCiAgdGhlbWVfdm9pZCgpDQpgYGANCg0KVOG7tyBs4buHIGtow6FjaCBow6BuZyBz4bufIGjhu691IG5ow6AgKFkpIGNoaeG6v20gxrB1IHRo4bq/IHbhu5tpIDg0NDQgbmfGsOG7nWkgKDYwLjA2JSkgc28gduG7m2kgbmjDs20ga2jDtG5nIHPhu58gaOG7r3UgbmjDoCAoTikgbMOgIDU2MTUgbmfGsOG7nWkgKDM5Ljk0JSkuIFPhu7EgY2jDqm5oIGzhu4djaCBuw6B5IGNobyB0aOG6pXkgxJFhIHPhu5Ega2jDoWNoIGjDoG5nIHRyb25nIG3huqt1IGPDsyBt4bupYyDEkeG7mSDhu5VuIMSR4buLbmggbmjDoCDhu58gY2FvLiBCaeG7g3UgxJHhu5MgdHLDsm4gbMOgbSByw7Ugc+G7sSBjaMOqbmggbOG7h2NoIGdp4buvYSBoYWkgbmjDs20uDQoNCg0KDQojIyAqKkJp4bq/biBBbm51YWxJbmNvbWUqKg0KDQpgYGB7cn0NCiNC4bqjbmcgdOG6p24gc3XhuqV0IHbDoCB04bu3IGzhu4cNCmluY29tZV9mcmVxIDwtIHRhYmxlKGRhdGEkQW5udWFsSW5jb21lKQ0KaW5jb21lX3Byb3AgPC0gcHJvcC50YWJsZShpbmNvbWVfZnJlcSkgKiAxMDANCmluY29tZV90YWJsZSA8LSBkYXRhLmZyYW1lKEZyZXF1ZW5jeSA9IGluY29tZV9mcmVxLCBQZXJjZW50YWdlID0gaW5jb21lX3Byb3ApDQpwcmludChpbmNvbWVfdGFibGUpDQpgYGANCg0KYGBge3J9DQojQmnhu4N1IMSR4buTIGPhu5l0DQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBBbm51YWxJbmNvbWUsIGZpbGwgPSBBbm51YWxJbmNvbWUpKSArDQogIGdlb21fYmFyKCkgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgVGh1IG5o4bqtcCBIw6BuZyBuxINtIiwgeCA9ICJBbm51YWwgSW5jb21lIiwgeSA9ICJT4buRIGzGsOG7o25nIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQoNClRodSBuaOG6rXAgY+G7p2Ega2jDoWNoIGjDoG5nIMSRxrDhu6NjIGNoaWEgdGjDoG5oIG5oaeG7gXUgbmjDs20uIFBow6JuIGtow7pjIHBo4buVIGJp4bq/biBuaOG6pXQgbMOgIHThu6sgJDMwS+KAkyQ1MEsgKDMyLjczJSkgdsOgICQxMEvigJMkMzBLICgyMS45OCUpLiBUcm9uZyBraGkgxJHDsywgbmjDs20gY8OzIHRodSBuaOG6rXAgdHLDqm4gJDE1MEsgY2jhu4kgY2hp4bq/bSAxLjk0JS4gUGjDom4gYuG7kSB0aHUgbmjhuq1wIGNobyB0aOG6pXkgxJFhIHPhu5Ega2jDoWNoIGjDoG5nIHRodeG7mWMgdOG6p25nIGzhu5twIGPDsyB0aHUgbmjhuq1wIHRydW5nIGLDrG5oIOKAkyB0aOG6pXAuIEJp4buDdSDEkeG7kyBj4buZdCBtaW5oIGjhu41hIHPhu7EgcGjDom4gYuG7kSBraMO0bmcgxJHhu5NuZyDEkeG7gXUgdsOgIHThuq1wIHRydW5nIOG7nyBt4bupYyB0aHUgbmjhuq1wIHRo4bqlcCB2w6AgdHJ1bmcgYsOsbmguDQoNCiMjICoqQmnhur9uIENpdHkqKg0KDQpgYGB7cn0NCg0KY2l0eV9mcmVxIDwtIHRhYmxlKGRhdGEkQ2l0eSkgIyBU4bqhbyBi4bqjbmcgdOG6p24gc3XhuqV0DQoNCmNpdHlfcHJvcCA8LSBwcm9wLnRhYmxlKGNpdHlfZnJlcSkgKiAxMDAgIyBUw61uaCB04bu3IGzhu4cgcGjhuqduIHRyxINtDQoNCg0KY2l0eV90YWJsZSA8LSBkYXRhLmZyYW1lKENpdHkgPSBuYW1lcyhjaXR5X2ZyZXEpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIEZyZXF1ZW5jeSA9IGFzLnZlY3RvcihjaXR5X2ZyZXEpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIFBlcmNlbnRhZ2UgPSBhcy52ZWN0b3IoY2l0eV9wcm9wKSkgIyBDaHV54buDbiB0aMOgbmggZGF0YS5mcmFtZQ0KDQpwcmludChjaXR5X3RhYmxlKSAjIEhp4buDbiB0aOG7iyB0b8OgbiBi4buZIGLhuqNuZw0KDQpgYGANCg0KDQpgYGB7cn0NCmdncGxvdChjaXR5X3RhYmxlLCBhZXMoeCA9IENpdHksIHkgPSBGcmVxdWVuY3ksIGZpbGwgPSBDaXR5KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgVGjDoG5oIHBo4buRIiwgeCA9ICJUaMOgbmggcGjhu5EiLCB5ID0gIlPhu5EgbMaw4bujbmciKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KS2jDoWNoIGjDoG5nIMSR4bq/biB04burIG5oaeG7gXUgdGjDoG5oIHBo4buRIGtow6FjIG5oYXUsIHRyb25nIMSRw7MgU2FsZW0gKDkuODYlKSwgVGFjb21hICg4Ljk0JSkgdsOgIFphY2F0ZWNhcyAoOS4yMyUpIGzDoCBuaOG7r25nIG7GoWkgY8OzIHPhu5EgbMaw4bujbmcga2jDoWNoIGjDoG5nIGNhbyBuaOG6pXQuIE5o4buvbmcgdGjDoG5oIHBo4buRIG5oxrAgU2FuIEZyYW5jaXNjbyAoMC45MiUpIHbDoCBHdWFkYWxhamFyYSAoMC41MyUpIGzhuqFpIGPDsyBz4buRIGzGsOG7o25nIMOtdCBoxqFuIG5oaeG7gXUuIEJp4buDdSDEkeG7kyBj4buZdCBjaG8gdGjhuqV5IHPhu7EgcGjDom4gaMOzYSByw7UgcuG7h3QgdGhlbyB2w7luZyDEkeG7i2EgbMO9Lg0KDQojIyAqKkJp4bq/biBTdGF0ZW9yUHJvdmluY2UqKg0KDQpgYGB7cn0NCiNC4bqjbmcgdOG6p24gc3XhuqV0IHbDoCB04bu3IGzhu4cNCnN0YXRlX2ZyZXEgPC0gdGFibGUoZGF0YSRTdGF0ZW9yUHJvdmluY2UpDQpzdGF0ZV9wcm9wIDwtIHByb3AudGFibGUoc3RhdGVfZnJlcSkgKiAxMDANCnN0YXRlX3RhYmxlIDwtIGRhdGEuZnJhbWUoRnJlcXVlbmN5ID0gc3RhdGVfZnJlcSwgUGVyY2VudGFnZSA9IHN0YXRlX3Byb3ApDQpwcmludChzdGF0ZV90YWJsZSkNCmBgYA0KDQoNCmBgYHtyfQ0KI0Jp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gU3RhdGVvclByb3ZpbmNlLCBmaWxsID0gU3RhdGVvclByb3ZpbmNlKSkgKw0KICBnZW9tX2JhcigpICsNCiAgbGFicyh0aXRsZSA9ICJQaMOibiBi4buRIEJhbmcvVOG7iW5oIiwgeCA9ICJTdGF0ZSBvciBQcm92aW5jZSIsIHkgPSAiU+G7kSBsxrDhu6NuZyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KDQpQaMOibiBi4buRIHRoZW8gYmFuZyBob+G6t2MgdOG7iW5oIGNobyB0aOG6pXkgV2FzaGluZ3RvbiAoV0EpIGzDoCBraHUgduG7sWMgY2hp4bq/bSB04bu3IHRy4buNbmcgbOG7m24gbmjhuqV0IHbhu5tpIDMyLjQ4JSBraMOhY2ggaMOgbmcsIHRp4bq/cCB0aGVvIGzDoCBDYWxpZm9ybmlhIChDQSkgduG7m2kgMTkuNDQlIHbDoCBPcmVnb24gKE9SKSB24bubaSAxNi4wOSUuIMSQaeG7gXUgbsOgeSBwaOG6o24gw6FuaCBz4buxIHThuq1wIHRydW5nIGTDom4gc+G7kSB04bqhaSBt4buZdCBz4buRIGJhbmcgbOG7m24uIEJp4buDdSDEkeG7kyBj4buZdCBsw6BtIHLDtSBz4buxIHBow6JuIGLhu5Ega2jDtG5nIMSR4buTbmcgxJHhu4F1IG7DoHkuDQoNCiMjICoqQmnhur9uIENvdW50cnkqKg0KDQpgYGB7cn0NCiNC4bqjbmcgdOG6p24gc3XhuqV0IHbDoCB04bu3IGzhu4cNCmNvdW50cnlfZnJlcSA8LSB0YWJsZShkYXRhJENvdW50cnkpDQpjb3VudHJ5X3Byb3AgPC0gcHJvcC50YWJsZShjb3VudHJ5X2ZyZXEpICogMTAwDQpjb3VudHJ5X3RhYmxlIDwtIGRhdGEuZnJhbWUoRnJlcXVlbmN5ID0gY291bnRyeV9mcmVxLCBQZXJjZW50YWdlID0gY291bnRyeV9wcm9wKQ0KcHJpbnQoY291bnRyeV90YWJsZSkNCmBgYA0KDQoNCmBgYHtyfQ0KI0Jp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gQ291bnRyeSwgZmlsbCA9IENvdW50cnkpKSArDQogIGdlb21fYmFyKCkgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgUXXhu5FjIGdpYSIsIHggPSAiQ291bnRyeSIsIHkgPSAiU+G7kSBsxrDhu6NuZyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KS2jDoWNoIGjDoG5nIGNo4bunIHnhur91IMSR4bq/biB04burIEhvYSBL4buzICg2OC4wMSUpLCBzYXUgxJHDsyBsw6AgTWV4aWNvICgyNi4yMyUpIHbDoCBDYW5hZGEgKDUuNzUlKS4gROG7ryBsaeG7h3UgY2hvIHRo4bqleSB0aOG7iyB0csaw4budbmcgY2jDrW5oIGPhu6dhIHNpw6p1IHRo4buLIHThuq1wIHRydW5nIHThuqFpIE3hu7kuIEJp4buDdSDEkeG7kyBj4buZdCBuaOG6pW4gbeG6oW5oIHPhu7Egw6FwIMSR4bqjbyBj4bunYSBraMOhY2ggaMOgbmcgdOG7qyBIb2EgS+G7sy4NCg0KIyMgKipCaeG6v24gUHJvZHVjdEZhbWlseSoqDQoNCmBgYHtyfQ0KI0LhuqNuZyB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hw0KcHJvZF9mYW1pbHlfZnJlcSA8LSB0YWJsZShkYXRhJFByb2R1Y3RGYW1pbHkpDQpwcm9kX2ZhbWlseV9wcm9wIDwtIHByb3AudGFibGUocHJvZF9mYW1pbHlfZnJlcSkgKiAxMDANCnByb2RfZmFtaWx5X3RhYmxlIDwtIGRhdGEuZnJhbWUoRnJlcXVlbmN5ID0gcHJvZF9mYW1pbHlfZnJlcSwgUGVyY2VudGFnZSA9IHByb2RfZmFtaWx5X3Byb3ApDQpwcmludChwcm9kX2ZhbWlseV90YWJsZSkNCmBgYA0KDQoNCmBgYHtyfQ0KI0Jp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gUHJvZHVjdEZhbWlseSwgZmlsbCA9IFByb2R1Y3RGYW1pbHkpKSArDQogIGdlb21fYmFyKCkgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgTmjDs20gU+G6o24gcGjhuqltIiwgeCA9ICJQcm9kdWN0IEZhbWlseSIsIHkgPSAiU+G7kSBsxrDhu6NuZyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KTmjDs20gc+G6o24gcGjhuqltIEZvb2QgKFRo4buxYyBwaOG6qW0pIGNoaeG6v20gxrB1IHRo4bq/IHbGsOG7o3QgdHLhu5lpICg3Mi4yMiUpLCB0aeG6v3AgxJHhur9uIGzDoCBOb24tQ29uc3VtYWJsZSAoUGhpIHRpw6p1IGTDuW5nKSB24bubaSAxOC44OSUgdsOgIERyaW5rICjEkOG7kyB14buRbmcpIGzDoCA4Ljg5JS4gxJBp4buBdSBuw6B5IHBo4bqjbiDDoW5oIHNpw6p1IHRo4buLIGNo4bunIHnhur91IGtpbmggZG9hbmggdGjhu7FjIHBo4bqpbS4gQmnhu4N1IMSR4buTIGPhu5l0IGzDoG0gbuG7lWkgYuG6rXQgdOG7tyB0cuG7jW5nIGzhu5tuIGPhu6dhIG5ow7NtIHRo4buxYyBwaOG6qW0uDQoNCg0KIyMgKipCaeG6v24gUHJvZHVjdERlcGFydG1lbnQqKg0KDQpgYGB7cn0NCiNC4bqjbmcgdOG6p24gc3XhuqV0IHbDoCB04bu3IGzhu4cNCnByb2RfZGVwdF9mcmVxIDwtIHRhYmxlKGRhdGEkUHJvZHVjdERlcGFydG1lbnQpDQpwcm9kX2RlcHRfcHJvcCA8LSBwcm9wLnRhYmxlKHByb2RfZGVwdF9mcmVxKSAqIDEwMA0KcHJvZF9kZXB0X3RhYmxlIDwtIGRhdGEuZnJhbWUoRnJlcXVlbmN5ID0gcHJvZF9kZXB0X2ZyZXEsIFBlcmNlbnRhZ2UgPSBwcm9kX2RlcHRfcHJvcCkNCnByaW50KHByb2RfZGVwdF90YWJsZSkNCmBgYA0KDQoNCmBgYHtyfQ0KI0Jp4buDdSDEkeG7kyBj4buZdA0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gUHJvZHVjdERlcGFydG1lbnQsIGZpbGwgPSBQcm9kdWN0RGVwYXJ0bWVudCkpICsNCiAgZ2VvbV9iYXIoKSArDQogIGxhYnModGl0bGUgPSAiUGjDom4gYuG7kSBC4buZIHBo4bqtbiBT4bqjbiBwaOG6qW0iLCB4ID0gIlByb2R1Y3QgRGVwYXJ0bWVudCIsIHkgPSAiU+G7kSBsxrDhu6NuZyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQoNCkRhbmggbeG7pWMgY8OzIHThuqduIHN14bqldCBjYW8gbmjhuqV0IGzDoCBWZWdldGFibGVzICgxMi4yOSUpLCBTbmFjayBGb29kcyAoMTEuMzglKSwgdsOgIFByb2R1Y2UgKDE0LjE4JSkuIE3hu5l0IHPhu5EgZGFuaCBt4bulYyBoaeG6v20gbmjGsCBDYW5uZWQgT3lzdGVycywgTWlzY2VsbGFuZW91cywgdsOgIENhbmRsZXMgY8OzIHThu7cgbOG7hyBkxrDhu5tpIDAuNSUuIFBow6JuIHTDrWNoIG7DoHkgY2hvIHRo4bqleSBz4buxIHThuq1wIHRydW5nIG3huqFuaCBt4bq9IHbDoG8gY8OhYyBkYW5oIG3hu6VjIHRo4buxYyBwaOG6qW0gdMawxqFpIHPhu5FuZyB2w6AgxJHhu5MgxINuIG5o4bq5LiBCaeG7g3UgxJHhu5MgY+G7mXQgZ2nDunAgdHLhu7FjIHF1YW4gaMOzYSByw7UgbsOpdCAxMCBkYW5oIG3hu6VjIHBo4buVIGJp4bq/biBuaOG6pXQuDQoNCg0KIyMgKipCaeG6v24gUHJvZHVjdENhdGVnb3J5KioNCg0KYGBge3J9DQojIFThuqFvIGLhuqNuZyB04bqnbiBzdeG6pXQNCnByb2RfY2F0X2ZyZXEgPC0gdGFibGUoZGF0YSRQcm9kdWN0Q2F0ZWdvcnkpDQoNCiMgVMOtbmggdOG7tyBs4buHIHBo4bqnbiB0csSDbQ0KcHJvZF9jYXRfcHJvcCA8LSBwcm9wLnRhYmxlKHByb2RfY2F0X2ZyZXEpICogMTAwDQoNCiMgQ2h1eeG7g24gdGjDoG5oIGRhdGEuZnJhbWUNCnByb2RfY2F0X3RhYmxlIDwtIGRhdGEuZnJhbWUoQ2F0ZWdvcnkgPSBuYW1lcyhwcm9kX2NhdF9mcmVxKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRnJlcXVlbmN5ID0gYXMudmVjdG9yKHByb2RfY2F0X2ZyZXEpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQZXJjZW50YWdlID0gYXMudmVjdG9yKHByb2RfY2F0X3Byb3ApKQ0KDQojIEhp4buDbiB0aOG7iyB0b8OgbiBi4buZIGLhuqNuZw0KcHJpbnQocHJvZF9jYXRfdGFibGUpDQpgYGANCg0KDQpgYGB7cn0NCiMgQmnhu4N1IMSR4buTIGPhu5l0IA0KZ2dwbG90KHByb2RfY2F0X3RhYmxlLCBhZXMoeCA9IENhdGVnb3J5LCB5ID0gRnJlcXVlbmN5KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgRGFuaCBt4bulYyBT4bqjbiBwaOG6qW0iLCB4ID0gIkRhbmggbeG7pWMgU+G6o24gcGjhuqltIiwgeSA9ICJT4buRIGzGsOG7o25nIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCiAgDQpgYGANCg0KRGFuaCBt4bulYyBjw7MgdOG6p24gc3XhuqV0IGNhbyBuaOG6pXQgbMOgIFZlZ2V0YWJsZXMgKDEyLjI5JSksIFNuYWNrIEZvb2RzICgxMS4zOCUpLCB2w6AgUHJvZHVjZSAoMTQuMTglKS4gTeG7mXQgc+G7kSBkYW5oIG3hu6VjIGhp4bq/bSBuaMawIENhbm5lZCBPeXN0ZXJzLCBNaXNjZWxsYW5lb3VzLCB2w6AgQ2FuZGxlcyBjw7MgdOG7tyBs4buHIGTGsOG7m2kgMC41JS4gUGjDom4gdMOtY2ggbsOgeSBjaG8gdGjhuqV5IHPhu7EgdOG6rXAgdHJ1bmcgbeG6oW5oIG3hur0gdsOgbyBjw6FjIGRhbmggbeG7pWMgdGjhu7FjIHBo4bqpbSB0xrDGoWkgc+G7kW5nIHbDoCDEkeG7kyDEg24gbmjhurkuIEJp4buDdSDEkeG7kyBj4buZdCBnacO6cCB0cuG7sWMgcXVhbiBow7NhIHLDtSBuw6l0IDEwIGRhbmggbeG7pWMgcGjhu5UgYmnhur9uIG5o4bqldC4NCg0KDQojICoqUGjhuqduIDM6IMav4bubYyBsxrDhu6NuZyBLaG/huqNuZyB2w6AgS2nhu4NtIMSR4buLbmggR2nhuqMgdGh1eeG6v3QgY2hvIFThu7cgbOG7hyoqDQoNClRyb25nIHBo4bqnbiBuw6B5LCBt4bulYyB0acOqdSBsw6AgxrDhu5tjIGzGsOG7o25nIGtob+G6o25nIHRpbiBj4bqteSBjaG8gdOG7tyBs4buHIGPhu6dhIG3hu5l0IHPhu5EgaOG6oW5nIG3hu6VjIMSR4buLbmggdMOtbmggY+G7pSB0aOG7gyB2w6AgdGjhu7FjIGhp4buHbiBraeG7g20gxJHhu4tuaCBnaeG6oyB0aHV54bq/dCBt4buZdCB04bu3IGzhu4csIG5o4bqxbSBraeG7g20gdHJhIHhlbSB04bu3IGzhu4cgcXVhbiBzw6F0IMSRxrDhu6NjIHRyb25nIG3huqt1IGPDsyBraMOhYyBiaeG7h3QgxJHDoW5nIGvhu4Mgc28gduG7m2kgbeG7mXQgdOG7tyBs4buHIGdp4bqjIMSR4buLbmggaGF5IGtow7RuZy4NCg0KIyMgKipCaeG6v24gR2VuZGVyIChI4bqhbmcgbeG7pWM6IE7hu68pKioNCg0KR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6DQoNCkjigoA6IFThu7cgbOG7hyBu4buvIHRyb25nIG3huqt1IGLhurFuZyA1MCUgKHAgPSAwLjUpDQoNCkjigoE6IFThu7cgbOG7hyBu4buvIGtow6FjIDUwJQ0KDQoNCmBgYHtyfQ0KI8av4bubYyBsxrDhu6NuZyBLaG/huqNuZyBUaW4gY+G6rXkNCm4gPC0gbnJvdyhkYXRhKQ0KZmVtYWxlX2NvdW50IDwtIHN1bShkYXRhJEdlbmRlciA9PSAiRiIpDQpwcm9wX2ZlbWFsZSA8LSBmZW1hbGVfY291bnQgLyBuDQpzZV9mZW1hbGUgPC0gc3FydChwcm9wX2ZlbWFsZSAqICgxIC0gcHJvcF9mZW1hbGUpIC8gbikNCmNpX2ZlbWFsZSA8LSBwcm9wX2ZlbWFsZSArIGMoLTEsIDEpICogMS45NiAqIHNlX2ZlbWFsZQ0KY2F0KCJLaG/huqNuZyB0aW4gY+G6rXkgOTUlIGNobyB04bu3IGzhu4cgTuG7rzoiLCByb3VuZChjaV9mZW1hbGUgKiAxMDAsIDIpLCAiJVxuIikNCmBgYA0KDQpgYGB7cn0NCiNLaeG7g20gxJHhu4tuaCBHaeG6oyB0aHV54bq/dCAoSDA6IFThu7cgbOG7hyBO4buvID0gMC41KQ0KcHJvcC50ZXN0KGZlbWFsZV9jb3VudCwgbiwgcCA9IDAuNSwgY29uZi5sZXZlbCA9IDAuOTUpDQpgYGANCkvhur90IHF14bqjIHBow6JuIHTDrWNoDQoNCktob+G6o25nIHRpbiBj4bqteSA5NSU6IFs1MC4xNyUsIDUxLjgzJV0NCg0KR2nDoSB0cuG7iyBwLXZhbHVlOiAwLjAyIDwgMC4wNQ0KDQpOaOG6rW4geMOpdA0KDQpWw6wga2hv4bqjbmcgdGluIGPhuq15IGtow7RuZyBjaOG7qWEgxJHDum5nIDUwJSwgdsOgIGdpw6EgdHLhu4sgcCBuaOG7jyBoxqFuIDAuMDUsIHRhIGPDsyDEkeG7pyBi4bqxbmcgY2jhu6luZyDEkeG7gyBiw6FjIGLhu48gZ2nhuqMgdGh1eeG6v3QgSDAuIE5oxrAgduG6rXksIHThu7cgbOG7hyBraMOhY2ggaMOgbmcgbuG7ryB0aOG7sWMgdOG6vyBjw7Mgc+G7sSBraMOhYyBiaeG7h3QgxJHDoW5nIGvhu4Mgc28gduG7m2kgbeG7qWMgZ2nhuqMgxJHhu4tuaCA1MCUsIG3hurdjIGTDuSBz4buxIGtow6FjIGJp4buHdCBsw6Agbmjhu48uIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IGtow6FjaCBow6BuZyBu4buvIGNoaeG6v20gdOG7tyBs4buHIG5o4buJbmggaMahbiBt4buZdCBjaMO6dCBzbyB24bubaSBraMOhY2ggaMOgbmcgbmFtLg0KDQojIyAqKkJp4bq/biBNYXJpdGFsU3RhdHVzIChI4bqhbmcgbeG7pWM6IMSQw6Mga+G6v3QgaMO0bikqKg0KDQpHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaA0KDQpIMDogVOG7tyBs4buHIMSRw6Mga+G6v3QgaMO0biA9IDUwJQ0KDQpIMTogVOG7tyBs4buHIMSRw6Mga+G6v3QgaMO0biDiiaAgNTAlDQoNCg0KYGBge3J9DQojxq/hu5tjIGzGsOG7o25nIEtob+G6o25nIFRpbiBj4bqteQ0KbWFycmllZF9jb3VudCA8LSBzdW0oZGF0YSRNYXJpdGFsU3RhdHVzID09ICJNIikNCnByb3BfbWFycmllZCA8LSBtYXJyaWVkX2NvdW50IC8gbg0Kc2VfbWFycmllZCA8LSBzcXJ0KHByb3BfbWFycmllZCAqICgxIC0gcHJvcF9tYXJyaWVkKSAvIG4pDQpjaV9tYXJyaWVkIDwtIHByb3BfbWFycmllZCArIGMoLTEsIDEpICogMS45NiAqIHNlX21hcnJpZWQNCmNhdCgiS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gdOG7tyBs4buHIMSQw6Mga+G6v3QgaMO0bjoiLCByb3VuZChjaV9tYXJyaWVkICogMTAwLCAyKSwgIiVcbiIpDQpgYGANCg0KYGBge3J9DQoNCiNLaeG7g20gxJHhu4tuaCBHaeG6oyB0aHV54bq/dCAoSDA6IFThu7cgbOG7hyDEkMOjIGvhur90IGjDtG4gPSAwLjUpDQpwcm9wLnRlc3QobWFycmllZF9jb3VudCwgbiwgcCA9IDAuNSwgY29uZi5sZXZlbCA9IDAuOTUpDQpgYGANCkvhur90IHF14bqjIHBow6JuIHTDrWNoDQoNCktob+G6o25nIHRpbiBj4bqteSA5NSU6IFs0OC4wMSUsIDQ5LjY2JV0NCg0KcC12YWx1ZTogMC4wMDYgPCAwLjA1DQoNCk5o4bqtbiB4w6l0DQpU4bu3IGzhu4cga2jDoWNoIGjDoG5nIMSRw6Mga+G6v3QgaMO0biB0aOG6pXAgaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBt4bupYyBnaeG6oyDEkeG7i25oIDUwJS4gS2hv4bqjbmcgdGluIGPhuq15IGtow7RuZyBjaOG7qWEgMC41IHbDoCBwLXZhbHVlIG5o4buPIGNobyB0aOG6pXkgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4gRG8gxJHDsywgxJFhIHBo4bqnbiBraMOhY2ggaMOgbmcgbMOgIG5nxrDhu51pIGNoxrBhIGvhur90IGjDtG4sIMSRaeG7gXUgbsOgeSBjw7MgdGjhu4MgZ+G7o2kgw70gduG7gSB4dSBoxrDhu5tuZyBjaGkgdGnDqnUgaG/hurdjIGzhu5FpIHPhu5FuZyBraMOhYyBiaeG7h3QuDQoNCiMjICoqQmnhur9uIEhvbWVvd25lciAoSOG6oW5nIG3hu6VjOiBDw7MgbmjDoCkqKg0KDQpHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaA0KDQpIMDogVOG7tyBs4buHIHPhu58gaOG7r3UgbmjDoCA9IDYwJQ0KDQpIMTogVOG7tyBs4buHIHPhu58gaOG7r3UgbmjDoCDiiaAgNjAlDQoNCmBgYHtyfQ0KI8av4bubYyBsxrDhu6NuZyBLaG/huqNuZyBUaW4gY+G6rXkNCmhvbWVvd25lcl9jb3VudCA8LSBzdW0oZGF0YSRIb21lb3duZXIgPT0gIlkiKQ0KcHJvcF9ob21lb3duZXIgPC0gaG9tZW93bmVyX2NvdW50IC8gbg0Kc2VfaG9tZW93bmVyIDwtIHNxcnQocHJvcF9ob21lb3duZXIgKiAoMSAtIHByb3BfaG9tZW93bmVyKSAvIG4pDQpjaV9ob21lb3duZXIgPC0gcHJvcF9ob21lb3duZXIgKyBjKC0xLCAxKSAqIDEuOTYgKiBzZV9ob21lb3duZXINCmNhdCgiS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gdOG7tyBs4buHIFPhu58gaOG7r3UgTmjDoDoiLCByb3VuZChjaV9ob21lb3duZXIgKiAxMDAsIDIpLCAiJVxuIikNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCiNLaeG7g20gxJHhu4tuaCBHaeG6oyB0aHV54bq/dCAoSDA6IFThu7cgbOG7hyBT4bufIGjhu691IE5ow6AgPSAwLjYpDQpwcm9wLnRlc3QoaG9tZW93bmVyX2NvdW50LCBuLCBwID0gMC42LCBjb25mLmxldmVsID0gMC45NSkNCmBgYA0KDQpL4bq/dCBxdeG6oyBwaMOibiB0w61jaA0KDQpLaG/huqNuZyB0aW4gY+G6rXkgOTUlOiBbNTkuMjUlLCA2MC44NyVdDQoNCnAtdmFsdWU6IDAuOTAgPiAwLjA1DQoNCk5o4bqtbiB4w6l0DQpLaG/huqNuZyB0aW4gY+G6rXkgYmFvIGfhu5NtIGdpw6EgdHLhu4sgNjAlIHbDoCBwLXZhbHVlIHLhuqV0IGzhu5tuLCBkbyDEkcOzIGtow7RuZyBjw7MgxJHhu6cgYuG6sW5nIGNo4bupbmcgxJHhu4MgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IEgwLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSB04bu3IGzhu4cga2jDoWNoIGjDoG5nIHPhu58gaOG7r3UgbmjDoCBwaMO5IGjhu6NwIHbhu5tpIGdp4bqjIMSR4buLbmgsIHThu6ljIGzDoCBraG/huqNuZyA2MCUga2jDoWNoIGjDoG5nIGzDoCBjaOG7pyBz4bufIGjhu691IG5ow6AuDQoNCiMjICoqQmnhur9uIEFubnVhbEluY29tZSAoSOG6oW5nIG3hu6VjOiAkMzBLIC0gJDUwSykqKg0KDQpHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaA0KDQpIMDogVOG7tyBs4buHIHRodSBuaOG6rXAgbsOgeSA9IDMwJQ0KDQpIMTogVOG7tyBs4buHIOKJoCAzMCUNCg0KYGBge3J9DQojxq/hu5tjIGzGsOG7o25nIEtob+G6o25nIFRpbiBj4bqteQ0KaW5jb21lX2NvdW50IDwtIHN1bShkYXRhJEFubnVhbEluY29tZSA9PSAiJDMwSyAtICQ1MEsiKQ0KcHJvcF9pbmNvbWUgPC0gaW5jb21lX2NvdW50IC8gbg0Kc2VfaW5jb21lIDwtIHNxcnQocHJvcF9pbmNvbWUgKiAoMSAtIHByb3BfaW5jb21lKSAvIG4pDQpjaV9pbmNvbWUgPC0gcHJvcF9pbmNvbWUgKyBjKC0xLCAxKSAqIDEuOTYgKiBzZV9pbmNvbWUNCmNhdCgiS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gdOG7tyBs4buHICQzMEsgLSAkNTBLOiIsIHJvdW5kKGNpX2luY29tZSAqIDEwMCwgMiksICIlXG4iKQ0KYGBgDQoNCg0KYGBge3J9DQojS2nhu4NtIMSR4buLbmggR2nhuqMgdGh1eeG6v3QgKEgwOiBU4bu3IGzhu4cgJDMwSyAtICQ1MEsgPSAwLjMpDQpwcm9wLnRlc3QoaW5jb21lX2NvdW50LCBuLCBwID0gMC4zLCBjb25mLmxldmVsID0gMC45NSkNCmBgYA0KDQpL4bq/dCBxdeG6oyBwaMOibiB0w61jaA0KDQpLaG/huqNuZyB0aW4gY+G6rXkgOTUlOiBbMzEuOTUlLCAzMy41MSVdDQoNCnAtdmFsdWU6IDJlLTEyIDwgMC4wNQ0KDQpOaOG6rW4geMOpdA0KVOG7tyBs4buHIGtow6FjaCBow6BuZyB0aHXhu5ljIG5ow7NtIHRodSBuaOG6rXAgMzBL4oCTNTBLIGNhbyBoxqFuIMSRw6FuZyBr4buDIHNvIHbhu5tpIDMwJSwgdsOgIMSRaeG7gXUgbsOgeSBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIG3huqFuaC4gS+G6v3QgcXXhuqMgY2hvIHRo4bqleSDEkcOieSBsw6AgbmjDs20gdGh1IG5o4bqtcCBwaOG7lSBiaeG6v24sIGPDsyB0aOG7gyBsw6AgbeG7pWMgdGnDqnUgdGnhur9wIHRo4buLIGhp4buHdSBxdeG6oy4NCg0KIyMgKipCaeG6v24gQ2l0eSAoSOG6oW5nIG3hu6VjOiBTYWxlbSkqKg0KDQpHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaA0KDQpIMDogVOG7tyBs4buHIGtow6FjaCBow6BuZyB04burIFNhbGVtID0gMTUlDQoNCkgxOiBU4bu3IGzhu4cg4omgIDE1JQ0KDQpgYGB7cn0NCiPGr+G7m2MgbMaw4bujbmcgS2hv4bqjbmcgVGluIGPhuq15DQpjaXR5X2NvdW50IDwtIHN1bShkYXRhJENpdHkgPT0gIlNhbGVtIikNCnByb3BfY2l0eSA8LSBjaXR5X2NvdW50IC8gbg0Kc2VfY2l0eSA8LSBzcXJ0KHByb3BfY2l0eSAqICgxIC0gcHJvcF9jaXR5KSAvIG4pDQpjaV9jaXR5IDwtIHByb3BfY2l0eSArIGMoLTEsIDEpICogMS45NiAqIHNlX2NpdHkNCmNhdCgiS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gdOG7tyBs4buHIFNhbGVtOiIsIHJvdW5kKGNpX2NpdHkgKiAxMDAsIDIpLCAiJVxuIikNCg0KYGBgDQoNCg0KYGBge3J9DQojS2nhu4NtIMSR4buLbmggR2nhuqMgdGh1eeG6v3QgKEgwOiBU4bu3IGzhu4cgU2FsZW0gPSAwLjE1KQ0KcHJvcC50ZXN0KGNpdHlfY291bnQsIG4sIHAgPSAwLjE1LCBjb25mLmxldmVsID0gMC45NSkNCmBgYA0KDQpL4bq/dCBxdeG6oyBwaMOibiB0w61jaA0KDQpLaG/huqNuZyB0aW4gY+G6rXkgOTUlOiBbOS4zNyUsIDEwLjM1JV0NCg0KcC12YWx1ZTogPCAyZS0xNg0KDQpOaOG6rW4geMOpdA0KVOG7tyBs4buHIGtow6FjaCBow6BuZyDEkeG6v24gdOG7qyBTYWxlbSB0aOG6pXAgaMahbiBuaGnhu4F1IHNvIHbhu5tpIGdp4bqjIMSR4buLbmggMTUlLiBLaG/huqNuZyB0aW4gY+G6rXkgbmjhu48gdsOgIHAgcuG6pXQgdGjhuqVwIGNobyB0aOG6pXkgc+G7sSBraMOhYyBiaeG7h3QgY8OzIMO9IG5naMSpYSByw7UgcuG7h3QuIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IFNhbGVtIGtow7RuZyBwaOG6o2kgdGjhu4sgdHLGsOG7nW5nIHRy4buNbmcgeeG6v3UgdHJvbmcgZOG7ryBsaeG7h3UgaGnhu4duIHThuqFpLg0KDQojIyAqKkJp4bq/biBTdGF0ZW9yUHJvdmluY2UgKEjhuqFuZyBt4bulYzogV0EpKioNCg0KR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmgNCg0KSDA6IFThu7cgbOG7hyBraMOhY2ggaMOgbmcg4bufIGJhbmcgV0EgPSA0MCUNCg0KSDE6IFThu7cgbOG7hyDiiaAgNDAlDQoNCmBgYHtyfQ0KI8av4bubYyBsxrDhu6NuZyBLaG/huqNuZyBUaW4gY+G6rXkNCnN0YXRlX2NvdW50IDwtIHN1bShkYXRhJFN0YXRlb3JQcm92aW5jZSA9PSAiV0EiKQ0KcHJvcF9zdGF0ZSA8LSBzdGF0ZV9jb3VudCAvIG4NCnNlX3N0YXRlIDwtIHNxcnQocHJvcF9zdGF0ZSAqICgxIC0gcHJvcF9zdGF0ZSkgLyBuKQ0KY2lfc3RhdGUgPC0gcHJvcF9zdGF0ZSArIGMoLTEsIDEpICogMS45NiAqIHNlX3N0YXRlDQpjYXQoIktob+G6o25nIHRpbiBj4bqteSA5NSUgY2hvIHThu7cgbOG7hyBXQToiLCByb3VuZChjaV9zdGF0ZSAqIDEwMCwgMiksICIlXG4iKQ0KYGBgDQoNCg0KDQpgYGB7cn0NCiNLaeG7g20gxJHhu4tuaCBHaeG6oyB0aHV54bq/dCAoSDA6IFThu7cgbOG7hyBXQSA9IDAuNCkNCnByb3AudGVzdChzdGF0ZV9jb3VudCwgbiwgcCA9IDAuNCwgY29uZi5sZXZlbCA9IDAuOTUpDQpgYGANCg0KS+G6v3QgcXXhuqMgcGjDom4gdMOtY2gNCg0KS2hv4bqjbmcgdGluIGPhuq15IDk1JTogWzMxLjcxJSwgMzMuMjYlXQ0KDQpwLXZhbHVlOiA8IDJlLTE2DQoNCk5o4bqtbiB4w6l0DQpU4bu3IGzhu4cga2jDoWNoIGjDoG5nIHThu6sgYmFuZyBXQSB0aOG6pXAgaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBnaeG6oyDEkeG7i25oLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBXQSBraMO0bmcgY2hp4bq/bSDGsHUgdGjhur8gdHJvbmcgbeG6q3UsIHbDoCBjw7MgdGjhu4MgY+G6p24gxJFp4buBdSBjaOG7iW5oIG7hur91IG3huqt1IGPhuqduIMSR4bqhaSBkaeG7h24gY2hvIGJhbmcgbsOgeS4NCg0KDQpgYGB7cn0NCiMgxJDhur9tIHPhu5EgbMaw4bujbmcgZ2lhbyBk4buLY2ggY2hvIENhbmFkYSB2w6AgTWV4aWNvDQpjYW5hZGFfY291bnQgPC0gc3VtKGRhdGEkQ291bnRyeSA9PSAiQ2FuYWRhIikgICMgODA5DQptZXhpY29fY291bnQgPC0gc3VtKGRhdGEkQ291bnRyeSA9PSAiTWV4aWNvIikgICMgMzY4OA0KbiA8LSBucm93KGRhdGEpICAjIDE0MDU5DQpgYGANCg0KDQpgYGB7cn0NCiMgS2nhu4NtIMSR4buLbmggZ2nhuqMgdGh1eeG6v3QNCnByb3AudGVzdChjKGNhbmFkYV9jb3VudCwgbWV4aWNvX2NvdW50KSwgbiA9IGMobiwgbiksIA0KICAgICAgICAgIHAgPSBjKDAuNSwgMC41KSwgYWx0ZXJuYXRpdmUgPSAibGVzcyIsIGNvbmYubGV2ZWwgPSAwLjk1KQ0KYGBgDQoNCiMjICoqQmnhur9uIENvdW50cnkgKEjhuqFuZyBt4bulYzogVVNBKSoqDQoNCkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oDQoNCkgwOiBU4bu3IGzhu4cga2jDoWNoIGjDoG5nIHThu6sgVVNBID0gODAlDQoNCkgxOiBU4bu3IGzhu4cg4omgIDgwJQ0KDQoNCmBgYHtyfQ0KI8av4bubYyBsxrDhu6NuZyBLaG/huqNuZyBUaW4gY+G6rXkNCmNvdW50cnlfY291bnQgPC0gc3VtKGRhdGEkQ291bnRyeSA9PSAiVVNBIikNCnByb3BfY291bnRyeSA8LSBjb3VudHJ5X2NvdW50IC8gbg0Kc2VfY291bnRyeSA8LSBzcXJ0KHByb3BfY291bnRyeSAqICgxIC0gcHJvcF9jb3VudHJ5KSAvIG4pDQpjaV9jb3VudHJ5IDwtIHByb3BfY291bnRyeSArIGMoLTEsIDEpICogMS45NiAqIHNlX2NvdW50cnkNCmNhdCgiS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gdOG7tyBs4buHIFVTQToiLCByb3VuZChjaV9jb3VudHJ5ICogMTAwLCAyKSwgIiVcbiIpDQpgYGANCg0KYGBge3J9DQojS2nhu4NtIMSR4buLbmggR2nhuqMgdGh1eeG6v3QgKEgwOiBU4bu3IGzhu4cgVVNBID0gMC44KQ0KcHJvcC50ZXN0KGNvdW50cnlfY291bnQsIG4sIHAgPSAwLjgsIGNvbmYubGV2ZWwgPSAwLjk1KQ0KYGBgDQoNCkvhur90IHF14bqjIHBow6JuIHTDrWNoDQoNCktob+G6o25nIHRpbiBj4bqteSA5NSU6IFs2Ny4yNCUsIDY4Ljc4JV0NCg0KcC12YWx1ZTogPCAyZS0xNg0KDQpOaOG6rW4geMOpdA0KVOG7tyBs4buHIGtow6FjaCBow6BuZyB04burIEhvYSBL4buzIHRo4bqlcCBoxqFuIGjhurNuIHNvIHbhu5tpIGdp4bqjIMSR4buLbmggODAlLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBk4buvIGxp4buHdSBraMO0bmcgaG/DoG4gdG/DoG4gdOG6rXAgdHJ1bmcgdsOgbyB0aOG7iyB0csaw4budbmcgTeG7uSwgY8OzIHRo4buDIGRvIGRvYW5oIG5naGnhu4dwIG3hu58gcuG7mW5nIHJhIHF14buRYyB04bq/IGhv4bq3YyBs4bqleSBt4bqrdSBraMO0bmcgxJHhuqFpIGRp4buHbi4NCg0KIyMgKipCaeG6v24gUHJvZHVjdEZhbWlseSAoSOG6oW5nIG3hu6VjOiBGb29kKSoqDQoNCkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oDQoNCkgwOiBU4bu3IGzhu4cg4omlIDcwJQ0KDQpIMTogVOG7tyBs4buHIDwgNzAlIA0KDQpgYGB7cn0NCiPGr+G7m2MgbMaw4bujbmcgS2hv4bqjbmcgVGluIGPhuq15DQpmb29kX2NvdW50IDwtIHN1bShkYXRhJFByb2R1Y3RGYW1pbHkgPT0gIkZvb2QiKQ0KcHJvcF9mb29kIDwtIGZvb2RfY291bnQgLyBuDQpzZV9mb29kIDwtIHNxcnQocHJvcF9mb29kICogKDEgLSBwcm9wX2Zvb2QpIC8gbikNCmNpX2Zvb2QgPC0gcHJvcF9mb29kICsgYygtMSwgMSkgKiAxLjk2ICogc2VfZm9vZA0KY2F0KCJLaG/huqNuZyB0aW4gY+G6rXkgOTUlIGNobyB04bu3IGzhu4cgRm9vZDoiLCByb3VuZChjaV9mb29kICogMTAwLCAyKSwgIiVcbiIpDQpgYGANCg0KYGBge3J9DQojS2nhu4NtIMSR4buLbmggR2nhuqMgdGh1eeG6v3QgKEgwOiBU4bu3IGzhu4cgRm9vZCDiiaUgMC43KQ0KcHJvcC50ZXN0KGZvb2RfY291bnQsIG4sIHAgPSAwLjcsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiLCBjb25mLmxldmVsID0gMC45NSkNCmBgYA0KDQpL4bq/dCBxdeG6oyBwaMOibiB0w61jaA0KDQpLaG/huqNuZyB0aW4gY+G6rXkgOTUlOiBbNzEuNTklLCAxMDAlXQ0KDQpwLXZhbHVlOiA1ZS0wOQ0KDQpOaOG6rW4geMOpdA0KVsOsIHAgcuG6pXQgbmjhu48gdsOgIHRvw6BuIGLhu5kga2hv4bqjbmcgdGluIGPhuq15IG7hurFtIHRyw6puIDcwJSwgY8OzIMSR4bunIGLhurFuZyBjaOG7qW5nIGto4bqzbmcgxJHhu4tuaCBy4bqxbmcgdOG7tyBs4buHIHPhuqNuIHBo4bqpbSB0aHXhu5ljIG5ow7NtIOKAnEZvb2TigJ0gbOG7m24gaMahbiA3MCUsIGNobyB0aOG6pXkgbmjDs20gbsOgeSBjaGnhur9tIMawdSB0aOG6vyBs4bubbiB0cm9uZyBkYW5oIG3hu6VjLg0KDQojIyAqKkJp4bq/biBQcm9kdWN0RGVwYXJ0bWVudCAoSOG6oW5nIG3hu6VjOiBTbmFjayBGb29kcykqKg0KDQpHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaA0KDQpIMDogVOG7tyBs4buHIFNuYWNrIEZvb2RzID0gMTUlDQoNCkgxOiBU4bu3IGzhu4cg4omgIDE1JQ0KDQpgYGB7cn0NCiPGr+G7m2MgbMaw4bujbmcgS2hv4bqjbmcgVGluIGPhuq15DQpkZXB0X2NvdW50IDwtIHN1bShkYXRhJFByb2R1Y3REZXBhcnRtZW50ID09ICJTbmFjayBGb29kcyIpDQpwcm9wX2RlcHQgPC0gZGVwdF9jb3VudCAvIG4NCnNlX2RlcHQgPC0gc3FydChwcm9wX2RlcHQgKiAoMSAtIHByb3BfZGVwdCkgLyBuKQ0KY2lfZGVwdCA8LSBwcm9wX2RlcHQgKyBjKC0xLCAxKSAqIDEuOTYgKiBzZV9kZXB0DQpjYXQoIktob+G6o25nIHRpbiBj4bqteSA5NSUgY2hvIHThu7cgbOG7hyBTbmFjayBGb29kczoiLCByb3VuZChjaV9kZXB0ICogMTAwLCAyKSwgIiVcbiIpDQpgYGANCg0KYGBge3J9DQojS2nhu4NtIMSR4buLbmggR2nhuqMgdGh1eeG6v3QgKEgwOiBU4bu3IGzhu4cgU25hY2sgRm9vZHMgPSAwLjE1KQ0KcHJvcC50ZXN0KGRlcHRfY291bnQsIG4sIHAgPSAwLjE1LCBjb25mLmxldmVsID0gMC45NSkNCmBgYA0KDQpL4bq/dCBxdeG6oyBwaMOibiB0w61jaA0KDQpLaG/huqNuZyB0aW4gY+G6rXkgOTUlOiBbMTAuODYlLCAxMS45MSVdDQoNCnAtdmFsdWU6IDwgMmUtMTYNCg0KTmjhuq1uIHjDqXQNClThu7cgbOG7hyBz4bqjbiBwaOG6qW0gU25hY2sgRm9vZHMgdGjhuqVwIGjGoW4gxJHDoW5nIGvhu4Mgc28gduG7m2kgZ2nhuqMgxJHhu4tuaC4gQ8OzIHRo4buDIHRo4bqleSBy4bqxbmcgbeG6t2MgZMO5IHBo4buVIGJp4bq/biBuaMawbmcgY2jGsGEgxJHhur9uIG3hu6ljIGNoaeG6v20gMTUlLCB2w6AgZG9hbmggbmdoaeG7h3AgY8OzIHRo4buDIGPDom4gbmjhuq9jIHBow6JuIHBo4buRaSBwaMO5IGjhu6NwIGjGoW4uDQoNCg0KDQojIyAqKkJp4bq/biBQcm9kdWN0Q2F0ZWdvcnkgKEjhuqFuZyBt4bulYzogU25hY2sgRm9vZHMpKioNCmBgYHtyfQ0KI8av4bubYyBsxrDhu6NuZyBLaG/huqNuZyBUaW4gY+G6rXkNCmNhdF9jb3VudCA8LSBzdW0oZGF0YSRQcm9kdWN0Q2F0ZWdvcnkgPT0gIlNuYWNrIEZvb2RzIikNCnByb3BfY2F0IDwtIGNhdF9jb3VudCAvIG4NCnNlX2NhdCA8LSBzcXJ0KHByb3BfY2F0ICogKDEgLSBwcm9wX2NhdCkgLyBuKQ0KY2lfY2F0IDwtIHByb3BfY2F0ICsgYygtMSwgMSkgKiAxLjk2ICogc2VfY2F0DQpjYXQoIktob+G6o25nIHRpbiBj4bqteSA5NSUgY2hvIHThu7cgbOG7hyBTbmFjayBGb29kczoiLCByb3VuZChjaV9jYXQgKiAxMDAsIDIpLCAiJVxuIikNCmBgYA0KDQpgYGB7cn0NCiNLaeG7g20gxJHhu4tuaCBHaeG6oyB0aHV54bq/dCAoSDA6IFThu7cgbOG7hyBTbmFjayBGb29kcyA9IDAuMTUpDQpwcm9wLnRlc3QoY2F0X2NvdW50LCBuLCBwID0gMC4xNSwgY29uZi5sZXZlbCA9IDAuOTUpDQoNCmBgYA0KS+G6v3QgcXXhuqMgcGjDom4gdMOtY2gNCg0KS2hv4bqjbmcgdGluIGPhuq15IDk1JTogWzEwLjg2JSwgMTEuOTElXQ0KDQpwLXZhbHVlOiA8IDJlLTE2DQoNCk5o4bqtbiB4w6l0Og0KVOG7tyBs4buHIGNo4buJIGtob+G6o25nIDExLjM4JSwgdGjhuqVwIGjGoW4gMTUlIG7Dqm4gY8WpbmcgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IEgwLg0KDQoNCiMgKipQaOG6p24gNDogUGjDom4gdMOtY2ggTeG7kWkgcXVhbiBo4buHIGdp4buvYSBIYWkgYmnhur9uIMSQ4buLbmggdMOtbmgqKg0KDQojIyAqKiBD4bq3cCBNYXJpdGFsU3RhdHVzIHbDoCBIb21lb3duZXIqKg0KDQpgYGB7cn0NCiNC4bqjbmcgVOG6p24gc3XhuqV0IENow6lvDQpjcm9zc190YWJsZTEgPC0gdGFibGUoZGF0YSRNYXJpdGFsU3RhdHVzLCBkYXRhJEhvbWVvd25lcikNCmNyb3NzX3Byb3AxIDwtIHByb3AudGFibGUoY3Jvc3NfdGFibGUxLCBtYXJnaW4gPSAxKSAqIDEwMA0KcHJpbnQoY3Jvc3NfdGFibGUxKQ0KcHJpbnQocm91bmQoY3Jvc3NfcHJvcDEsIDIpKQ0KYGBgDQpE4buvIGxp4buHdSDEkcaw4bujYyBwaMOibiBsb+G6oWkgdGhlbyBoYWkgYmnhur9uIMSR4buLbmggdMOtbmg6IE1hcml0YWxTdGF0dXMgKFTDrG5oIHRy4bqhbmcgaMO0biBuaMOibjogTSDigJMgTWFycmllZCwgUyDigJMgU2luZ2xlKSB2w6AgSG9tZW93bmVyIChT4bufIGjhu691IG5ow6A6IFkg4oCTIFllcywgTiDigJMgTm8pLiBC4bqjbmcgdOG6p24gc3XhuqV0IGNobyB0aOG6pXkgbmfGsOG7nWkgxJHDoyBr4bq/dCBow7RuIGNoaeG6v20gdOG7tyBs4buHIHPhu58gaOG7r3UgbmjDoCBjYW8gaMahbiAoNzQsOTYlKSBzbyB24bubaSBuZ8aw4budaSDEkeG7mWMgdGjDom4gKDQ1LDg0JSkuIMSQaeG7gXUgbsOgeSB0aOG7gyBoaeG7h24gc+G7sSBraMOhYyBiaeG7h3QgxJHDoW5nIGvhu4MgdHJvbmcgaMOgbmggdmkgc+G7nyBo4buvdSBuaMOgIGdp4buvYSBoYWkgbmjDs20gaMO0biBuaMOibi4NCg0KYGBge3J9DQojVHLhu7FjIHF1YW4gaMOzYQ0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gTWFyaXRhbFN0YXR1cywgZmlsbCA9IEhvbWVvd25lcikpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgbGFicyh0aXRsZSA9ICJT4bufIGjhu691IE5ow6AgdGhlbyBUw6xuaCB0cuG6oW5nIEjDtG4gbmjDom4iLCB4ID0gIk1hcml0YWwgU3RhdHVzIiwgeSA9ICJU4bu3IGzhu4ciLCBmaWxsID0gIkhvbWVvd25lciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCkJp4buDdSDEkeG7kyB0aGFuaCB04bu3IGzhu4cgKHN0YWNrZWQgYmFyIGNoYXJ0IHRoZW8gdOG7tyBs4buHIHBo4bqnbiB0csSDbSkgdHLhu7FjIHF1YW4gaMOzYSDEkWnhu4F1IG7DoHkgcuG6pXQgcsO1IHLDoG5nOiBuZ8aw4budaSDEkcOjIGvhur90IGjDtG4gY8OzIHh1IGjGsOG7m25nIHPhu58gaOG7r3UgbmjDoCBuaGnhu4F1IGjGoW4gxJHDoW5nIGvhu4Mgc28gduG7m2kgbmfGsOG7nWkgxJHhu5ljIHRow6JuLg0KDQpOaOG6sW0ga2nhu4NtIMSR4buLbmggeGVtIE1hcml0YWxTdGF0dXMgdsOgIEhvbWVvd25lciBjw7MgbeG7kWkgcXVhbiBo4buHIHRo4buRbmcga8OqIGhheSBraMO0bmcsIGtp4buDbSDEkeG7i25oIENoaS1iw6xuaCBwaMawxqFuZyDEkcaw4bujYyBz4butIGThu6VuZy4NCg0KR2nhuqMgdGh1eeG6v3QgSOKCgDogSGFpIGJp4bq/biBNYXJpdGFsU3RhdHVzIHbDoCBIb21lb3duZXIgbMOgIMSR4buZYyBs4bqtcC4NCg0KR2nhuqMgdGh1eeG6v3QgSOKCgTogSGFpIGJp4bq/biBjw7MgbeG7kWkgbGnDqm4gaOG7hyB0aOG7kW5nIGvDqi4NCg0KYGBge3J9DQoNCiNLaeG7g20gxJHhu4tuaCBDaGktYsOsbmggcGjGsMahbmcNCmNoaV90ZXN0MSA8LSBjaGlzcS50ZXN0KGNyb3NzX3RhYmxlMSkNCnByaW50KGNoaV90ZXN0MSkNCmBgYA0KS+G6v3QgcXXhuqM6DQoNCkdpw6EgdHLhu4sgdGjhu5FuZyBrw6ogY2hpIGLDrG5oIHBoxrDGoW5nIChYwrIpID0gMTI0MQ0KDQpC4bqtYyB04buxIGRvIChkZikgPSAxDQoNCnAtdmFsdWUgPCAyZS0xNg0KDQpOaOG6rW4geMOpdDoNCg0KS2nhu4NtIMSR4buLbmggQ2hpLWLDrG5oIHBoxrDGoW5nIChQZWFyc29uJ3MgQ2hpLXNxdWFyZWQgVGVzdCkgbmjhurFtIHjDoWMgxJHhu4tuaCB4ZW0gaGFpIGJp4bq/biDEkeG7i25oIHTDrW5oIGPDsyDEkeG7mWMgbOG6rXAgbmhhdSBoYXkga2jDtG5nLiDhu54gxJHDonksIGdpw6EgdHLhu4sgcCBy4bqldCBuaOG7jyAoPCAwLDA1KSwgY2hvIHRo4bqleSBiw6FjIGLhu48gZ2nhuqMgdGh1eeG6v3QgxJHhu5ljIGzhuq1wLCB04bupYyBsw6AgY8OzIG3hu5FpIGxpw6puIGjhu4cgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBnaeG7r2EgdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIHbDoCBz4bufIGjhu691IG5ow6AuIEPhu6UgdGjhu4MsIG5nxrDhu51pIMSRw6Mga+G6v3QgaMO0biBjw7MgeHUgaMaw4bubbmcgc+G7nyBo4buvdSBuaMOgIG5oaeG7gXUgaMahbiBzbyB24bubaSBuZ8aw4budaSDEkeG7mWMgdGjDom4uDQoNCg0KIyMgKipD4bq3cCBBbm51YWxJbmNvbWUgdsOgIFByb2R1Y3RGYW1pbHkqKg0KDQoNCg0KYGBge3J9DQojQuG6o25nIFThuqduIHN14bqldCBDaMOpbw0KY3Jvc3NfdGFibGUyIDwtIHRhYmxlKGRhdGEkQW5udWFsSW5jb21lLCBkYXRhJFByb2R1Y3RGYW1pbHkpDQpjcm9zc19wcm9wMiA8LSBwcm9wLnRhYmxlKGNyb3NzX3RhYmxlMiwgbWFyZ2luID0gMSkgKiAxMDANCnByaW50KGNyb3NzX3RhYmxlMikNCnByaW50KHJvdW5kKGNyb3NzX3Byb3AyLCAyKSkNCmBgYA0KDQpC4bqjbmcgY2hvIHRo4bqleSBwaOG6p24gbOG7m24gY8OhYyBuaMOzbSB0aHUgbmjhuq1wIHRpw6p1IGTDuW5nIGNo4bunIHnhur91IOG7nyBuaMOzbSBz4bqjbiBwaOG6qW0g4oCcRm9vZOKAnSAoY2hp4bq/bSBraG/huqNuZyA3MOKAkzczJSksIHRp4bq/cCB0aGVvIGzDoCDigJxOb24tQ29uc3VtYWJsZeKAnSB2w6AgdGjhuqVwIG5o4bqldCBsw6Ag4oCcRHJpbmvigJ0sIGLhuqV0IGvhu4MgbeG7qWMgdGh1IG5o4bqtcC4gVOG7tyBs4buHIG7DoHkgdMawxqFuZyDEkeG7kWkg4buVbiDEkeG7i25oIGdp4buvYSBjw6FjIG5ow7NtIHRodSBuaOG6rXAsIGNobyB0aOG6pXkgc+G7sSBwaMOibiBi4buRIMSR4buTbmcgxJHhu4F1IHRoZW8gbmjDs20gc+G6o24gcGjhuqltLg0KDQpgYGB7cn0NCiNUcuG7sWMgcXVhbiBow7NhDQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBBbm51YWxJbmNvbWUsIGZpbGwgPSBQcm9kdWN0RmFtaWx5KSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBsYWJzKHRpdGxlID0gIk5ow7NtIFPhuqNuIHBo4bqpbSB0aGVvIFRodSBuaOG6rXAiLCB4ID0gIkFubnVhbCBJbmNvbWUiLCB5ID0gIlThu7cgbOG7hyIsIGZpbGwgPSAiUHJvZHVjdCBGYW1pbHkiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KQmnhu4N1IMSR4buTIHThu7cgbOG7hyB0aGVvIG5ow7NtIHRodSBuaOG6rXAgY2hvIHRo4bqleSBkw7kgdGh1IG5o4bqtcCB0xINuZyBoYXkgZ2nhuqNtLCB04bu3IHRy4buNbmcgY8OhYyBuaMOzbSBz4bqjbiBwaOG6qW0gduG6q24ga2jDtG5nIGPDsyBz4buxIGNow6puaCBs4buHY2ggbOG7m24uDQoNCk5o4bqxbSBraeG7g20gxJHhu4tuaCB4ZW0gQW5udWFsSW5jb21lIHbDoCBQcm9kdWN0RmFtaWx5IGPDsyBt4buRaSBxdWFuIGjhu4cgdGjhu5FuZyBrw6ogaGF5IGtow7RuZywga2nhu4NtIMSR4buLbmggQ2hpLWLDrG5oIHBoxrDGoW5nIMSRxrDhu6NjIHPhu60gZOG7pW5nLg0KDQpHaeG6oyB0aHV54bq/dCBI4oKAOiBIYWkgYmnhur9uIEFubnVhbEluY29tZXIgdsOgIFByb2R1Y3RGYW1pbHkgbMOgIMSR4buZYyBs4bqtcC4NCg0KR2nhuqMgdGh1eeG6v3QgSOKCgTogSGFpIGJp4bq/biBjw7MgbeG7kWkgbGnDqm4gaOG7hyB0aOG7kW5nIGvDqi4NCg0KYGBge3J9DQojS2nhu4NtIMSR4buLbmggQ2hpLWLDrG5oIHBoxrDGoW5nDQpjaGlfdGVzdDIgPC0gY2hpc3EudGVzdChjcm9zc190YWJsZTIpDQpwcmludChjaGlfdGVzdDIpDQpgYGANCkvhur90IHF14bqjOg0KDQpHacOhIHRy4buLIHRo4buRbmcga8OqIFjCsiA9IDE1DQoNCmRmID0gMTQNCg0KcC12YWx1ZSA9IDAuNA0KDQpOaOG6rW4geMOpdDoNCg0KVuG7m2kgcC12YWx1ZSA9IDAuNCAoPiAwLjA1KSwgdGEga2jDtG5nIGLDoWMgYuG7jyBnaeG6oyB0aHV54bq/dCDEkeG7mWMgbOG6rXAsIHThu6ljIGzDoCBraMO0bmcgY8OzIGLhurFuZyBjaOG7qW5nIHRo4buRbmcga8OqIGNobyB0aOG6pXkgbeG7kWkgcXVhbiBo4buHIGdp4buvYSB0aHUgbmjhuq1wIHbDoCBsb+G6oWkgc+G6o24gcGjhuqltIMSRxrDhu6NjIHRpw6p1IGTDuW5nLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBow6BuaCB2aSBtdWEgc+G6r20gdGhlbyBuaMOzbSBz4bqjbiBwaOG6qW0gZMaw4budbmcgbmjGsCBraMO0bmcgYuG7iyDhuqNuaCBoxrDhu59uZyBi4bufaSBt4bupYyB0aHUgbmjhuq1wLg0KDQoNCg0KIyMgKiogQ+G6t3AgR2VuZGVyIHbDoCAgTWFyaXRhbFN0YXR1cyoqDQoNCmBgYHtyfQ0KI0LhuqNuZyB04bqnbiBzdeG6pXQgY2jDqW8NCmNyb3NzX3RhYmxlMyA8LSB0YWJsZShkYXRhJEdlbmRlciwgZGF0YSQgTWFyaXRhbFN0YXR1cykNCmNyb3NzX3Byb3AzIDwtIHByb3AudGFibGUoY3Jvc3NfdGFibGUzLCBtYXJnaW4gPSAxKSAqIDEwMA0KcHJpbnQoY3Jvc3NfdGFibGUzKQ0KcHJpbnQocm91bmQoY3Jvc3NfcHJvcDMsIDIpKQ0KYGBgDQoNCk5ow6xuIGNodW5nLCBr4bq/dCBxdeG6oyBjaG8gdGjhuqV5IHThu7cgbOG7hyBuZ8aw4budaSBr4bq/dCBow7RuIHbDoCDEkeG7mWMgdGjDom4gZ2nhu69hIG5hbSB2w6AgbuG7ryBsw6Aga2jDoSBjw6JuIGLhurFuZy4gVHJvbmcgxJHDsywgbuG7ryBnaeG7m2kgY8OzIHThu7cgbOG7hyBr4bq/dCBow7RuIGNhbyBoxqFuIG3hu5l0IGNow7p0IHNvIHbhu5tpIG5hbSBnaeG7m2kgKDUwLjI0JSBzbyB24bubaSA0Ny4zOCUpLCB0cm9uZyBraGkgbmFtIGdp4bubaSBjw7MgdOG7tyBs4buHIMSR4buZYyB0aMOibiBjYW8gaMahbiAoNTIuNjIlKS4NCg0KYGBge3J9DQojIEJp4buDdSDEkeG7kyBj4buZdCBjaOG7k25nDQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBHZW5kZXIsIGZpbGwgPSBNYXJpdGFsU3RhdHVzKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgVMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIHRoZW8gR2nhu5tpIHTDrW5oIiwgeCA9ICJHZW5kZXIiLCB5ID0gIlThu7cgbOG7hyIsIGZpbGwgPSAiIE1hcml0YWxTdGF0dXMiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KDQpgYGANCg0KTmjhurFtIGtp4buDbSDEkeG7i25oIHhlbSBHZW5kZXIgdsOgIE1hcml0YWxTdGF0dXMgY8OzIG3hu5FpIHF1YW4gaOG7hyB0aOG7kW5nIGvDqiBoYXkga2jDtG5nLCBraeG7g20gxJHhu4tuaCBDaGktYsOsbmggcGjGsMahbmcgxJHGsOG7o2Mgc+G7rSBk4bulbmcuDQoNCkdp4bqjIHRodXnhur90IEjigoA6IEhhaSBiaeG6v24gR2VuZGVyIHbDoCBNYXJpdGFsU3RhdHVzIGzDoCDEkeG7mWMgbOG6rXAuDQoNCkdp4bqjIHRodXnhur90IEjigoE6IEhhaSBiaeG6v24gY8OzIG3hu5FpIGxpw6puIGjhu4cgdGjhu5FuZyBrw6ouDQoNCmBgYHtyfQ0KIyBLaeG7g20gxJHhu4tuaCBDaGktYsOsbmggcGjGsMahbmcNCmNoaV90ZXN0MyA8LSBjaGlzcS50ZXN0KGNyb3NzX3RhYmxlMykNCnByaW50KGNoaV90ZXN0MykNCmBgYA0KDQpL4bq/dCBxdeG6oyBraeG7g20gxJHhu4tuaDoNCg0KR2nDoSB0cuG7iyB0aOG7kW5nIGvDqiBDaGktc3F1YXJlZDogWMKyID0gMTENCg0KQuG6rWMgdOG7sSBkbzogZGYgPSAxDQoNCkdpw6EgdHLhu4sgcDogcC12YWx1ZSA8IDdlLTA0DQoNCk5o4bqtbiB4w6l0OiANClbhu5tpIGdpw6EgdHLhu4sgcCBuaOG7jyBoxqFuIDAuMDUgcuG6pXQgbmhp4buBdSAocCA8IDdlLTA0KSwgdGEgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IEjigoAuIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IGPDsyBt4buRaSBsacOqbiBo4buHIHRo4buRbmcga8OqIHLDtSBy4buHdCBnaeG7r2EgZ2nhu5tpIHTDrW5oIHbDoCB0w6xuaCB0cuG6oW5nIGjDtG4gbmjDom4gdHJvbmcgdOG6rXAgZOG7ryBsaeG7h3UuIE7Ds2kgY8OhY2gga2jDoWMsIGdp4bubaSB0w61uaCBjw7Mg4bqjbmggaMaw4bufbmcgxJHDoW5nIGvhu4MgxJHhur9uIHTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiBj4bunYSBraMOhY2ggaMOgbmcgc2nDqnUgdGjhu4suDQoNCg0KIyAqKlBo4bqnbiA1OiBU4buVbmcga+G6v3QgdsOgIFRo4bqjbyBsdeG6rW4qKg0KDQojIyAqKlTDs20gdOG6r3Qgbmjhu69uZyBwaMOhdCBoaeG7h24gY2jDrW5oKioNCg0KUGjDom4gdMOtY2ggY8OhYyBiaeG6v24gxJHhu4tuaCB0w61uaCB0cm9uZyB04bqtcCBk4buvIGxp4buHdSAqU3VwZXJtYXJrZXQgVHJhbnNhY3Rpb25zLmNzdiogxJHDoyBjdW5nIGPhuqVwIG5o4buvbmcgaGnhu4N1IGJp4bq/dCDEkcOhbmcgY2jDuiDDvSB24buBIMSR4bq3YyDEkWnhu4NtIG5ow6JuIGto4bqpdSBo4buNYyBj4bunYSBraMOhY2ggaMOgbmcgdsOgIGjDoG5oIHZpIHRpw6p1IGTDuW5nIGPhu6dhIGjhu40uIE3hu5l0IHPhu5EgcGjDoXQgaGnhu4duIG7hu5VpIGLhuq10IGfhu5NtOg0KDQoqICoqR2nhu5tpIHTDrW5oKiogcGjDom4gYuG7kSBraMOhIGPDom4gYuG6sW5nLCBuaMawbmcgdOG7tyBs4buHIG7hu68gY8OzIHBo4bqnbiBuaOG7iW5oIGjGoW4gKGtob+G6o25nIDUxJSksIMSRaeG7gXUgbsOgeSBjw7MgdGjhu4MgcGjhuqNuIMOhbmggdmFpIHRyw7IgdGjGsOG7nW5nIHRo4bqleSBj4bunYSBwaOG7pSBu4buvIHRyb25nIHF1eeG6v3QgxJHhu4tuaCBtdWEgc+G6r20gZ2lhIMSRw6xuaC4NCiogKipUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4qKiBjaG8gdGjhuqV5IGfhuqduIDQ5JSBraMOhY2ggaMOgbmcgxJHDoyBr4bq/dCBow7RuLCBn4bujaSDDvSBy4bqxbmcgbmh1IGPhuqd1IG11YSBz4bqvbSBj4bunYSBo4buZIGdpYSDEkcOsbmggbMOgIG3hu5l0IHnhur91IHThu5EgcXVhbiB0cuG7jW5nIHRyb25nIGjDoG5oIHZpIHRpw6p1IGTDuW5nLg0KKiAqKlThu7cgbOG7hyBz4bufIGjhu691IG5ow6AgY2FvIChraG/huqNuZyA2MCUpKiogY2hvIHRo4bqleSBwaOG6p24gbOG7m24ga2jDoWNoIGjDoG5nIGPDsyBt4bupYyDEkeG7mSDhu5VuIMSR4buLbmgga2luaCB04bq/IG5o4bqldCDEkeG7i25oLg0KKiAqKlRodSBuaOG6rXAqKiBwaMOibiBi4buRIGNo4bunIHnhur91IHRyb25nIG5ow7NtIDMwLjAwMOKAkzUwLjAwMCBVU0QgKGNoaeG6v20gaMahbiAzMiUpLCBjaG8gdGjhuqV5IHThuq1wIGtow6FjaCBow6BuZyBjaOG7pyB54bq/dSB0aHXhu5ljIG5ow7NtIHRodSBuaOG6rXAgdHJ1bmcgYsOsbmguDQoqICoqSMOgbmggdmkgdGnDqnUgZMO5bmcqKiB04bqtcCB0cnVuZyBt4bqhbmggdsOgbyBuaMOzbSBz4bqjbiBwaOG6qW0gKipUaOG7sWMgcGjhuqltKiogKGjGoW4gNzIlKSwgdHJvbmcgxJHDsyBjw6FjIGRhbmggbeG7pWMgbmjGsCAqKlNuYWNrIEZvb2RzKiogdsOgICoqQnJlYWtmYXN0IEZvb2RzKiogY8WpbmcgY2hp4bq/bSB04bu3IHRy4buNbmcgxJHDoW5nIGvhu4MuDQoqIEPDoWMgcGjDom4gdMOtY2ggYuG6o25nIGNow6lvIHbDoCBraeG7g20gxJHhu4tuaCBDaGktc3F1YXJlZCDEkcOjIHBow6F0IGhp4buHbiAqKm5o4buvbmcgbeG7kWkgbGnDqm4gaOG7hyBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqKiogZ2nhu69hIG5oaeG7gXUgY+G6t3AgYmnhur9uIG5oxrA6ICpHaeG7m2kgdMOtbmgg4oCTIFTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiosICpUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4g4oCTIFPhu58gaOG7r3UgbmjDoCosICpUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4g4oCTIE5ow7NtIHPhuqNuIHBo4bqpbSosIHYudi4sIGNobyB0aOG6pXkgxJHhurdjIMSRaeG7g20gbmjDom4ga2jhuql1IGjhu41jIGPDsyB0aOG7gyDhuqNuaCBoxrDhu59uZyDEkeG6v24gaMOgbmggdmkgbXVhIGjDoG5nLg0KDQojIyAqKkjhuqFuIGNo4bq/IGPhu6dhIHBow6JuIHTDrWNoKioNCg0KRMO5IMSRw6MgbWFuZyBs4bqhaSBuaGnhu4F1IGvhur90IHF14bqjIGjhu691IMOtY2gsIHBow6JuIHTDrWNoIHbhuqtuIHThu5NuIHThuqFpIG3hu5l0IHPhu5EgaOG6oW4gY2jhur86DQoNCiogKipHaeG7m2kgaOG6oW4g4bufIGJp4bq/biDEkeG7i25oIHTDrW5oKio6IFZp4buHYyBjaOG7iSB04bqtcCB0cnVuZyB2w6BvIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmgga2hp4bq/biBwaMOibiB0w61jaCB0aGnhur91IGNoaeG7gXUgc8OidSB0cm9uZyB2aeG7h2MgxJFvIGzGsOG7nW5nIGPGsOG7nW5nIMSR4buZIHRpw6p1IGTDuW5nICh2w60gZOG7pTogZ2nDoSB0cuG7iyDEkcahbiBow6BuZywgdOG6p24gc3XhuqV0IG11YSBz4bqvbSkuDQoqICoqQ2jhuqV0IGzGsOG7o25nIHbDoCB0w61uaCDEkeG6p3kgxJHhu6cgY+G7p2EgZOG7ryBsaeG7h3UqKjogTeG7mXQgc+G7kSBiaeG6v24gY8OzIHRo4buDIGLhu4sgdGhp4bq/dSBnacOhIHRy4buLIGhv4bq3YyBjaMawYSDEkcaw4bujYyBjaHXhuqluIGjDs2EgaG/DoG4gdG/DoG4uDQoqICoqS8OtY2ggdGjGsOG7m2MgbeG6q3Uga2jDtG5nIMSR4buBdSoqOiBN4buZdCBz4buRIG5ow7NtICh2w60gZOG7pTogdGjDoG5oIHBo4buRIFNhbGVtIGhheSBiYW5nIFdBKSBjw7Mgc+G7kSBsxrDhu6NuZyBxdWFuIHPDoXQgbmjhu48sIGPDsyB0aOG7gyBsw6BtIGdp4bqjbSDEkeG7mSB0aW4gY+G6rXkgY+G7p2EgY8OhYyBraeG7g20gxJHhu4tuaCB0aOG7kW5nIGvDqiBsacOqbiBxdWFuLg0KKiAqKkNoxrBhIGtp4buDbSBzb8OhdCB54bq/dSB04buRIG5oaeG7hXUqKjogTeG7mXQgc+G7kSBt4buRaSBxdWFuIGjhu4cgcXVhbiBzw6F0IMSRxrDhu6NjIGPDsyB0aOG7gyBi4buLIOG6o25oIGjGsOG7n25nIGLhu59pIGPDoWMgYmnhur9uIOG6qW4gY2jGsGEgxJHGsOG7o2MgxJHGsGEgdsOgbyBtw7QgaMOsbmguDQoNCiMjIyAqKsSQ4buBIHh14bqldCBjaG8gZG9hbmggbmdoaeG7h3AqKg0KDQpU4burIGPDoWMgcGjDoXQgaGnhu4duIHRyw6puLCBjw7MgdGjhu4MgxJHGsGEgcmEgbeG7mXQgc+G7kSDEkeG7gSB4deG6pXQgbmjGsCBzYXU6DQoNCiogKipDaGnhur9uIGzGsOG7o2MgcGjDom4ga2jDumMga2jDoWNoIGjDoG5nKio6IERvIHThu7cgbOG7hyBraMOhY2ggaMOgbmcgbuG7ryB2w6AgxJHDoyBr4bq/dCBow7RuIGtow6EgY2FvLCBkb2FuaCBuZ2hp4buHcCBjw7MgdGjhu4MgeMOieSBk4buxbmcgY8OhYyBjaMawxqFuZyB0csOsbmgga2h1eeG6v24gbcOjaSBob+G6t2Mgc+G6o24gcGjhuqltIGjGsOG7m25nIMSR4bq/biBuaMOzbSBraMOhY2ggaMOgbmcgZ2lhIMSRw6xuaCBob+G6t2MgcGjhu6UgbuG7ryBu4buZaSB0cuG7oy4NCiogKipU4buRaSDGsHUgaMOzYSBkYW5oIG3hu6VjIHPhuqNuIHBo4bqpbSoqOiBW4bubaSBt4bupYyDEkeG7mSB0acOqdSBkw7luZyBjYW8gY2hvIG5ow7NtIHRo4buxYyBwaOG6qW0sIMSR4bq3YyBiaeG7h3QgbMOgICoqU25hY2sgRm9vZHMqKiwgZG9hbmggbmdoaeG7h3AgbsOqbiB0aeG6v3AgdOG7pWMgbeG7nyBy4buZbmcgY2jhu6duZyBsb+G6oWkgaG/hurdjIHRoxrDGoW5nIGhp4buHdSB0cm9uZyBkYW5oIG3hu6VjIG7DoHkuDQoqICoqUGjDom4gYuG7lSBuZ3Xhu5NuIGzhu7FjIHRp4bq/cCB0aOG7iyB0aGVvIGtodSB24buxYyoqOiBWw6wgdOG7tyBs4buHIGtow6FjaCBow6BuZyBjaMOqbmggbOG7h2NoIHRoZW8gdGjDoG5oIHBo4buRL2JhbmcsIGPhuqduIHhlbSB4w6l0IGzhuqFpIGNoaeG6v24gbMaw4bujYyBwaMOibiBwaOG7kWkgdsOgIHF14bqjbmcgYsOhIHRoZW8gxJHhu4thIHBoxrDGoW5nLCDEkeG6t2MgYmnhu4d0IHThuqFpIG5o4buvbmcgbsahaSBjw7MgdGnhu4FtIG7Eg25nIGNoxrBhIMSRxrDhu6NjIGtoYWkgdGjDoWMgbmjGsCBTYWxlbS4NCg0KIyMjICoqQ8OidSBo4buPaSBt4bufIHbDoCBoxrDhu5tuZyBuZ2hpw6puIGPhu6l1IHRp4bq/cCB0aGVvKioNCg0KUGjDom4gdMOtY2ggbsOgeSBt4bufIHJhIG3hu5l0IHPhu5EgY8OidSBo4buPaSB2w6AgaMaw4bubbmcgbmdoacOqbiBj4bupdSBjw7MgdGjhu4MgdGnhur9wIHThu6VjIGtoYWkgdGjDoWM6DQoNCiogKipN4buRaSBxdWFuIGjhu4cgduG7m2kgY8OhYyBiaeG6v24gxJHhu4tuaCBsxrDhu6NuZyoqOiBMaeG7h3UgdGh1IG5o4bqtcCwgxJHhu5kgdHXhu5VpIGhheSBnacOhIHRy4buLIGjDs2EgxJHGoW4gdHJ1bmcgYsOsbmggY8OzIOG6o25oIGjGsOG7n25nIMSR4bq/biBs4buxYSBjaOG7jW4gbmjDs20gc+G6o24gcGjhuqltIGhheSBraMO0bmc/DQoqICoqUGjDom4gdMOtY2gga+G6v3QgaOG7o3AgxJHhu4tuaCB0w61uaCB2w6AgxJHhu4tuaCBsxrDhu6NuZyoqOiBL4bq/dCBo4bujcCB0aMOqbSBjw6FjIHnhur91IHThu5EgbmjGsCBz4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSBtdWEsIGdpw6EgdHLhu4sgZ2lhbyBk4buLY2gsIGhv4bq3YyB0aOG7nWkgZ2lhbiBtdWEgaMOgbmcgxJHhu4MgaGnhu4N1IHPDonUgaMahbiBow6BuaCB2aSB0acOqdSBkw7luZy4NCiogKipQaMOibiBj4bulbSBraMOhY2ggaMOgbmcgKEN1c3RvbWVyIHNlZ21lbnRhdGlvbikqKjogQ8OzIHRo4buDIMOhcCBk4bulbmcgY8OhYyBr4bu5IHRodeG6rXQgaOG7jWMgbcOheSAobWFjaGluZSBsZWFybmluZykgxJHhu4MgcGjDom4gY+G7pW0ga2jDoWNoIGjDoG5nIGThu7FhIHRyw6puIG5oaeG7gXUgYmnhur9uIMSR4buLbmggdMOtbmggdsOgIMSR4buLbmggbMaw4bujbmcga+G6v3QgaOG7o3AuDQoqICoqUGjDom4gdMOtY2ggeHUgaMaw4bubbmcgdGhlbyB0aOG7nWkgZ2lhbioqOiBO4bq/dSBk4buvIGxp4buHdSBjw7MgeeG6v3UgdOG7kSB0aOG7nWkgZ2lhbiAodsOtIGThu6UgbmfDoHkgbXVhIGjDoG5nKSwgY8OzIHRo4buDIHhlbSB4w6l0IGjDoG5oIHZpIHRpw6p1IGTDuW5nIHRoZW8gbcO5YSB24bulIGhv4bq3YyBjaHUga+G7syB0deG6p24vdGjDoW5nLg0KDQotLS0NCg0KDQojICoqUGjDom4gdMOtY2ggU3V5IGRp4buFbiBUaOG7kW5nIGvDqiB0cm9uZyBC4bqjbmcgTmfhuqt1IG5oacOqbiAyeDIqKg0KIyMgKiogTMO9IHRodXnhur90KioNCg0KDQojIyAqKlLhu6dpIHJvIHTGsMahbmcgxJHhu5FpIChSZWxhdGl2ZSBSaXNrKSoqDQoNCioqS2jDoWkgbmnhu4dtOioqDQpS4bunaSBybyB0xrDGoW5nIMSR4buRaSAoUmVsYXRpdmUgUmlzaywgdmnhur90IHThuq90IGzDoCBSUikgbMOgIG3hu5l0IGNo4buJIHPhu5EgdGjhu5FuZyBrw6ogxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4Mgc28gc8OhbmggeMOhYyBzdeG6pXQgeOG6o3kgcmEgbeG7mXQgYmnhur9uIGPhu5EgKHRoxrDhu51uZyBsw6Ag4oCcdGjDoG5oIGPDtG5n4oCdIGhv4bq3YyDigJxjw7MgxJHhurdjIMSRaeG7g23igJ0pIGdp4buvYSBoYWkgbmjDs20gcGjDom4gYmnhu4d0IHRoZW8gYmnhur9uIMSR4buZYyBs4bqtcC4gQ2jhu4kgc+G7kSBuw6B5IMSR4bq3YyBiaeG7h3QgcGjhu5UgYmnhur9uIHRyb25nIGPDoWMgbmdoacOqbiBj4bupdSBk4buLY2ggdOG7hSBo4buNYyBk4bqhbmcgdGh14bqnbiB04bqtcCAoY29ob3J0IHN0dWRpZXMpLg0KDQoqKkvDvSBoaeG7h3UgdsOgIGPDtG5nIHRo4bupYzoqKg0KDQpH4buNaSBgXHBpXzFgIHbDoCBgXHBpXzJgIGzhuqduIGzGsOG7o3QgbMOgIHjDoWMgc3XhuqV0IHRow6BuaCBjw7RuZyDhu58gaGFpIG5ow7NtIHNvIHPDoW5oLCBraGkgxJHDsyBy4bunaSBybyB0xrDGoW5nIMSR4buRaSDEkcaw4bujYyDEkeG7i25oIG5naMSpYSBuaMawIHNhdToNCg0KDQpSUiA9IGBcZnJhY3tccGlfMX17XHBpXzJ9YA0KDQoqKkdp4bqjaSB0aMOtY2g6KioNCg0KUlIgY2hvIGJp4bq/dCB4w6FjIHN14bqldCB44bqjeSByYSBz4buxIGtp4buHbiDhu58gbmjDs20gdGjhu6kgbmjhuqV0IGfhuqVwIGJhbyBuaGnDqnUgbOG6p24gc28gduG7m2kgbmjDs20gdGjhu6kgaGFpLiBO4bq/dToNCg0KKiBSUiA9IDFgOiBLaMO0bmcgY8OzIHPhu7Ega2jDoWMgYmnhu4d0IGdp4buvYSBoYWkgbmjDs20uDQoqIFJSID4gMWA6IE5ow7NtIDEgY8OzIHjDoWMgc3XhuqV0IHjhuqN5IHJhIHPhu7Ega2nhu4duIGNhbyBoxqFuIG5ow7NtIDIuDQoqIFJSIDwgMWA6IE5ow7NtIDEgY8OzIHjDoWMgc3XhuqV0IHjhuqN5IHJhIHPhu7Ega2nhu4duIHRo4bqlcCBoxqFuIG5ow7NtIDIuDQoNCioqVsOtIGThu6UgbWluaCBo4buNYToqKg0KDQpHaeG6oyBz4butIG3hu5l0IG5naGnDqm4gY+G7qXUga2jhuqNvIHPDoXQgduG7gSB04bu3IGzhu4cgbmfGsOG7nWkg4oCcY8OzIG5ow6AgcmnDqm5n4oCdIGdp4buvYSBoYWkgbmjDs20gbmfGsOG7nWk6DQoNCnwgTmjDs20gICB8IEPDsyBuaMOgIChTdWNjZXNzKSB8IEtow7RuZyBjw7MgbmjDoCAoRmFpbCkgfCBU4buVbmcgc+G7kSB8DQp8IC0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLSB8DQp8IE5ow7NtIEEgfCA4MCAgICAgICAgICAgICAgIHwgMjAgICAgICAgICAgICAgICAgICB8IDEwMCAgICAgfA0KfCBOaMOzbSBCIHwgNDAgICAgICAgICAgICAgICB8IDYwICAgICAgICAgICAgICAgICAgfCAxMDAgICAgIHwNCg0KS2hpIMSRw7M6DQoNCiogXHBpX0EgPSBcZnJhY3s4MH17MTAwfSA9IDAuOA0KKiBccGlfQiA9IFxmcmFjezQwfXsxMDB9ID0gMC40DQoNClN1eSByYToNCg0KYFJSID0gXGZyYWN7MC44fXswLjR9ID0gMmANCg0KKipL4bq/dCBsdeG6rW46KiogWMOhYyBzdeG6pXQgY8OzIG5ow6AgcmnDqm5nIOG7nyBuaMOzbSBBIGfhuqVwIDIgbOG6p24gc28gduG7m2kgbmjDs20gQi4NCg0KLS0tDQoNCiMjICoqVOG7tyBs4buHIGNow6puaCAoT2RkcyBSYXRpbykqKg0KDQoqKktow6FpIG5p4buHbToqKg0KVOG7tyBs4buHIGNow6puaCAoT2RkcyBSYXRpbywgdmnhur90IHThuq90IGzDoCBPUikgbMOgIG3hu5l0IGNo4buJIHPhu5EgdGjhu4MgaGnhu4duIG3hu6ljIMSR4buZIGNow6puaCBs4buHY2ggZ2nhu69hIHThu7cgbOG7hyBjxrDhu6NjIHjhuqN5IHJhIHPhu7Ega2nhu4duIHRyb25nIGhhaSBuaMOzbS4gS2jDoWMgduG7m2kgUlIgZOG7sWEgdHLDqm4geMOhYyBzdeG6pXQsIE9SIHNvIHPDoW5oIHThu7cgbOG7hyBnaeG7r2EgeMOhYyBzdeG6pXQgdGjDoG5oIGPDtG5nIHbDoCB0aOG6pXQgYuG6oWkgdHJvbmcgbeG7l2kgbmjDs20uDQoNCioqVOG7tyBs4buHIGPGsOG7o2MgKE9kZHMpOioqDQpU4bu3IGzhu4cgY8aw4bujYyAob2RkKSBj4bunYSBt4buZdCBuaMOzbSAkaSQgxJHGsOG7o2MgxJHhu4tuaCBuZ2jEqWEgbMOgOg0KDQpgb2RkX2kgPSBcZnJhY3tccGlfaX17MSAtIFxwaV9pfWANCg0KDQoqKlThu7cgbOG7hyBjaMOqbmggZ2nhu69hIGhhaSBuaMOzbSAkaSQgdsOgICRqJDoqKg0KDQpgT1IgPSBcZnJhY3tvZGRfaX17b2RkX2p9ID0gXGZyYWN7XGRmcmFje1xwaV9pfXsxIC0gXHBpX2l9fXtcZGZyYWN7XHBpX2p9ezEgLSBccGlfan19ID0gXGZyYWN7XHBpX2koMSAtIFxwaV9qKX17XHBpX2ooMSAtIFxwaV9pKX1gDQoNCioqR2nhuqNpIHRow61jaDoqKg0KT1IgxJFvIGzGsOG7nW5nIG3hu6ljIMSR4buZIGNow6puaCBs4buHY2ggZ2nhu69hIGto4bqjIG7Eg25nIHjhuqN5IHJhIHbDoCBraMO0bmcgeOG6o3kgcmEgc+G7sSBraeG7h24gdHJvbmcgaGFpIG5ow7NtLiBO4bq/dToNCg0KKiBPUiA9IDE6IEtow7RuZyBjw7Mgc+G7sSBraMOhYyBiaeG7h3QuDQoqIE9SID4gMTogTmjDs20gaSBjw7MgdOG7tyBs4buHIGPGsOG7o2MgdGjDoG5oIGPDtG5nIGNhbyBoxqFuIG5ow7NtIGouDQoqIE9SIDwgMTogTmjDs20gaSBjw7MgdOG7tyBs4buHIGPGsOG7o2MgdGjDoG5oIGPDtG5nIHRo4bqlcCBoxqFuIG5ow7NtIGouDQoNCioqVsOtIGThu6UgbWluaCBo4buNYSAodGnhur9wIHThu6VjIHThu6sgdsOtIGThu6UgUlIpOioqDQoNCiogVOG7tyBs4buHIGPGsOG7o2MgbmjDs20gQTogYFxmcmFjezAuOH17MC4yfSA9IDRgDQoqIFThu7cgbOG7hyBjxrDhu6NjIG5ow7NtIEI6IGBcZnJhY3swLjR9ezAuNn0gPSBcZnJhY3syfXszfWANCg0KS2hpIMSRw7M6DQoNCmBPUiA9IFxmcmFjezR9ezIvM30gPSA2YA0KDQoqKkvhur90IGx14bqtbjoqKiBU4bu3IGzhu4cgY8aw4bujYyB0aMOgbmggY8O0bmcgKGPDsyBuaMOgKSDhu58gbmjDs20gQSBjYW8gZ+G6pXAgNiBs4bqnbiBuaMOzbSBCLg0KDQotLS0NCg0KIyMgKipTbyBzw6FuaCBnaeG7r2EgT2RkcyBSYXRpbyB2w6AgUmVsYXRpdmUgUmlzayoqDQoNCnwgxJDhurdjIMSRaeG7g20gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgUuG7p2kgcm8gdMawxqFuZyDEkeG7kWkgKFJSKSAgICAgICAgICAgfCBU4bu3IGzhu4cgY2jDqm5oIChPUikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfA0KfCBDw7RuZyB0aOG7qWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAkXGZyYWN7XHBpXzF9e1xwaV8yfSQgICAgICAgICAgIHwgJFxmcmFje1xwaV8xKDEgLSBccGlfMil9e1xwaV8yKDEgLSBccGlfMSl9JCAgICAgICAgICAgIHwNCnwgROG7sWEgdHLDqm4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWMOhYyBzdeG6pXQgKHByb2JhYmlsaXR5KSAgICAgICAgICB8IFThu7cgbOG7hyBjxrDhu6NjIChvZGRzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCDDnSBuZ2jEqWEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IFNvIHPDoW5oIGto4bqjIG7Eg25nIHjhuqN5IHJhIHPhu7Ega2nhu4duIHwgU28gc8OhbmggbeG7qWMgxJHhu5kgY2jDqm5oIGzhu4djaCBnaeG7r2Egb2RkcyAgICAgICAgICAgICAgICAgICAgfA0KfCBUcsaw4budbmcgaOG7o3Agc+G7rSBk4bulbmcgY2jDrW5oICAgICAgICAgICAgICAgICAgIHwgTmdoacOqbiBj4bupdSB0aHXhuqduIHThuq1wIChjb2hvcnQpICAgfCBI4buTaSBxdXkgbG9naXN0aWMsIG5naGnDqm4gY+G7qXUgYuG7h25oLWNo4bupbmcgKGNhc2UtY29udHJvbCkgfA0KfCBEaeG7hW4gZ2nhuqNpIHRy4buxYyB0aeG6v3AgY2hvIG5nxrDhu51pIGtow7RuZyBjaHV5w6puIHwgROG7hSBoxqFuICAgICAgICAgICAgICAgICAgICAgICAgICB8IEtow7MgaMahbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgR2nDoSB0cuG7iyBnaeG7m2kgaOG6oW4gICAgICAgICAgICAgICAgICAgICAgICAgICB8ICQ+IDAkLCB0aMaw4budbmcgdOG7qyAwIMSR4bq/biDiiJ4gICAgICAgIHwgJD4gMCQsIHRoxrDhu51uZyB04burIDAgxJHhur9uIOKIniAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQoNCg0KDQojIyAqKlBow6JuIHTDrWNoIGPhurdwIEdlbmRlciB2w6AgSG9tZW93bmVyKioNCg0KYGBge3J9DQojVOG6oW8gYuG6o25nIHThuqduIHN14bqldCBjaMOpbw0KY3Jvc3NfdGFibGVfZ2VuZGVyIDwtIHRhYmxlKGRhdGEkR2VuZGVyLCBkYXRhJEhvbWVvd25lcikNCmFkZG1hcmdpbnMoY3Jvc3NfdGFibGVfZ2VuZGVyKQ0KYGBgDQoNCg0KYGBge3J9DQojVMOtbmggUlIgKEhvbWVvd25lciA9IFkgY2hvIEYgc28gduG7m2kgTSkNCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KDQpSZWxSaXNrKGNyb3NzX3RhYmxlX2dlbmRlcikNCiAgDQpsaWJyYXJ5KGVwaXRvb2xzKQ0Kcmlza3JhdGlvKGNyb3NzX3RhYmxlX2dlbmRlcikNCmVwaXRhYihjcm9zc190YWJsZV9nZW5kZXIsIG1ldGhvZCA9ICJyaXNrcmF0aW8iKQ0KYGBgDQoNClThu7cgc+G7kSBy4bunaSBybyAoUmlzayBSYXRpbyAtIFJSKToNCg0KVMOtbmggdG/DoW4gYuG6sW5nIFJlbFJpc2soKSBjaG8gdGjhuqV5IFJSID0gMC45NzM2ICh0aGVvIERlc2NUb29scykgdsOgIFJSID0gMC45ODIzIHbhu5tpIGtob+G6o25nIHRpbiBj4bqteSA5NSUgbMOgICgwLjk1NjI7IDEuMDA5KSAodGhlbyBlcGl0b29scykuDQoNCsSQaeG7gXUgbsOgeSBuZ+G7pSDDvSBy4bqxbmcgbmFtIGdp4bubaSBjw7Mgbmd1eSBjxqEgc+G7nyBo4buvdSBuaMOgIHRo4bqlcCBoxqFuIG3hu5l0IGNow7p0IHNvIHbhu5tpIG7hu68gZ2nhu5tpLCB0dXkgbmhpw6puIGtow6FjIGJp4buHdCBraMO0bmcgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiAocCA9IDAuMTk2NSA+IDAuMDUpLg0KDQpgYGB7cn0NCiMgVMOtbmggT1INCk9kZHNSYXRpbyhjcm9zc190YWJsZV9nZW5kZXIpIA0Kb2Rkc3JhdGlvKGNyb3NzX3RhYmxlX2dlbmRlcikgDQplcGl0YWIoY3Jvc3NfdGFibGVfZ2VuZGVyLCBtZXRob2QgPSAib2Rkc3JhdGlvIikNCmBgYA0KDQpU4bu3IHPhu5Egb2RkcyAoT2RkcyBSYXRpbyAtIE9SKToNCg0KT1IgPSAwLjk1NjQgduG7m2kga2hv4bqjbmcgdGluIGPhuq15IDk1JSBsw6AgKDAuODkzOTsgMS4wMjMpLg0KDQpL4bq/dCBxdeG6oyBuw6B5IGPFqW5nIGNobyB0aOG6pXkga2jhuqMgbsSDbmcgc+G7nyBo4buvdSBuaMOgIGdp4buvYSBoYWkgZ2nhu5tpIGzDoCB0xrDGoW5nIMSRxrDGoW5nLCB2w6Agc+G7sSBraMOhYyBiaeG7h3Qga2jDtG5nIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogKHAgPSAwLjE5NjUpLg0KDQoNCk3hu5FpIGxpw6puIGjhu4cgZ2nhu69hIGdp4bubaSB0w61uaCB2w6Aga2jhuqMgbsSDbmcgc+G7nyBo4buvdSBuaMOgIGtow7RuZyDEkeG7pyBt4bqhbmggxJHhu4MgxJHGsOG7o2MgeGVtIGzDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqLiBU4bu3IGzhu4cgc+G7nyBo4buvdSBuaMOgIGPhu6dhIG7hu68gZ2nhu5tpICg2MC41OSUpIGNo4buJIG5o4buJbmggaMahbiBuYW0gZ2nhu5tpICg1OS41MiUpIG3hu5l0IGPDoWNoIGtow7RuZyDEkcOhbmcga+G7gy4gRG8gxJHDsywga2jDtG5nIHRo4buDIGto4bqzbmcgxJHhu4tuaCBy4bqxbmcgZ2nhu5tpIHTDrW5oIGzDoCB54bq/dSB04buRIOG6o25oIGjGsOG7n25nIMSR4bq/biB2aeG7h2Mgc+G7nyBo4buvdSBuaMOgIHRyb25nIG3huqt1IGThu68gbGnhu4d1IG7DoHkuDQoNCg0KDQojIyAqKlBow6JuIHTDrWNoIGPhurdwIE1hcml0YWxTdGF0dXMgdsOgIEhvbWVvd25lcioqDQpgYGB7cn0NCiMgVOG6oW8gYuG6o25nIHThuqduIHN14bqldCBjaMOpbw0KY3Jvc3NfdGFibGVfbXMgPC0gdGFibGUoZGF0YSRNYXJpdGFsU3RhdHVzLCBkYXRhJEhvbWVvd25lcikNCmFkZG1hcmdpbnMoY3Jvc3NfdGFibGVfbXMpDQpgYGANCg0KDQpgYGB7cn0NCiNUw61uaCBSUg0KUmVsUmlzayhjcm9zc190YWJsZV9tcykNCnJpc2tyYXRpbyhjcm9zc190YWJsZV9tcykNCmVwaXRhYihjcm9zc190YWJsZV9tcywgbWV0aG9kID0gInJpc2tyYXRpbyIpDQpgYGANCg0KVOG7tyBz4buRIHLhu6dpIHJvIChSaXNrIFJhdGlvIC0gUlIpDQpHacOhIHRy4buLIFJSID0gMC42MTE0LCB24bubaSBraG/huqNuZyB0aW4gY+G6rXkgOTUlIGzDoCAoMC41OTQyOyAwLjYyOTIpLg0KDQrEkGnhu4F1IG7DoHkgY8OzIG5naMSpYSBsw6Agbmd1eSBjxqEgc+G7nyBo4buvdSBuaMOgIGPhu6dhIG5nxrDhu51pIMSR4buZYyB0aMOibiBjaOG7iSBi4bqxbmcga2hv4bqjbmcgNjEsMTQlIHNvIHbhu5tpIG5nxrDhu51pIMSRw6Mga+G6v3QgaMO0bi4NCg0KS2jDoWMgYmnhu4d0IG7DoHkgbMOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogY2FvIHbhu5tpIHAtdmFsdWUg4omIIDEuODLDlzEw4oG7wrLigbfigbcgKEZpc2hlcidzIGV4YWN0IHRlc3QpLg0KDQpgYGB7cn0NCiNUw61uaCBPUg0KT2Rkc1JhdGlvKGNyb3NzX3RhYmxlX21zKQ0Kb2Rkc3JhdGlvKGNyb3NzX3RhYmxlX21zKQ0KZXBpdGFiKGNyb3NzX3RhYmxlX21zLCBtZXRob2QgPSAib2Rkc3JhdGlvIikNCmBgYA0KDQogVOG7tyBz4buRIG9kZHMgKE9kZHMgUmF0aW8gLSBPUikNCkdpw6EgdHLhu4sgT1IgPSAwLjI4MjYsIHbhu5tpIGtob+G6o25nIHRpbiBj4bqteSA5NSUgbMOgICgwLjI2MzE7IDAuMzAzNikuDQoNCsSQaeG7gXUgxJHDsyBjaG8gdGjhuqV5IHLhurFuZyBvZGRzICh04bu3IHPhu5Ega2jhuqMgbsSDbmcgeOG6o3kgcmEgdsOgIGtow7RuZyB44bqjeSByYSkgc+G7nyBo4buvdSBuaMOgIGPhu6dhIG5nxrDhu51pIMSR4buZYyB0aMOibiB0aOG6pXAgaMahbiBraG/huqNuZyA3MS43JSBzbyB24bubaSBuZ8aw4budaSDEkcOjIGvhur90IGjDtG4uDQoNCkvhur90IHF14bqjIG7DoHkgY8WpbmcgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBy4bqldCBjYW8gKHAg4omIIDEuODLDlzEw4oG7wrLigbfigbcpLg0KDQpQaMOibiB0w61jaCDEkeG7i25oIGzGsOG7o25nIGNobyB0aOG6pXkgdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIGzDoCB54bq/dSB04buRIGPDsyDhuqNuaCBoxrDhu59uZyByw7UgcuG7h3QgdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogY2FvIMSR4bq/biB2aeG7h2Mgc+G7nyBo4buvdSBuaMOgIHRyb25nIG3huqt1IGto4bqjbyBzw6F0LiBD4bulIHRo4buDLCBuZ8aw4budaSDEkeG7mWMgdGjDom4gY8OzIG5ndXkgY8ahIHbDoCBvZGRzIHPhu58gaOG7r3UgbmjDoCB0aOG6pXAgaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBuZ8aw4budaSDEkcOjIGvhur90IGjDtG4uIEvhur90IHF14bqjIG7DoHkgY8OzIHRo4buDIHBo4bqjbiDDoW5oIGPDoWMgeeG6v3UgdOG7kSB4w6MgaOG7mWkgdsOgIGtpbmggdOG6vyBuaMawIG5odSBj4bqndSDhu5VuIMSR4buLbmggZ2lhIMSRw6xuaCwga2jhuqMgbsSDbmcgdMOgaSBjaMOtbmgga+G6v3QgaOG7o3AgdOG7qyBoYWkgY8OhIG5ow6JuIHRyb25nIGjDtG4gbmjDom4sIGhv4bq3YyBjw6FjIGNow61uaCBzw6FjaCBo4buXIHRy4bujIG11YSBuaMOgIGNobyBnaWEgxJHDrG5oLg0KDQoNCg==