CHƯƠNG 1: TỔNG QUAN ĐỀ TÀI

1.1. Giới thiệu dữ liệu

Nghiên cứu này khai thác bộ dữ liệu “Telco Customer Churn”, một trong những bộ dữ liệu kinh điển được công bố rộng rãi trên nền tảng Kaggle. Dữ liệu này mô tả các thuộc tính của khách hàng tại một công ty viễn thông giả định, với mục tiêu chính là phân tích và dự báo các yếu tố dẫn đến quyết định ngừng sử dụng dịch vụ (churn) của khách hàng.

Bộ dữ liệu gốc bao gồm 7043 quan sát (tương ứng với mỗi khách hàng) và 21 thuộc tính mô tả. Mục tiêu của phân tích là xây dựng một mô hình có khả năng dự đoán biến Churn, từ đó cung cấp những thông tin giá trị cho các chiến lược giữ chân khách hàng của doanh nghiệp.

Bảng 1. Các biến được sử dụng trong nghiên cứu được tóm tắt dưới đây:

Tên biến Kiểu biến Mô tả Các giá trị
Churn Định tính Khách hàng có rời bỏ sử dụng dịch vụ viễn thông hay không. - Yes: Rời bỏ
- No: Tiếp tục sử dụng
Gender Định tính Giới tính của khách hàng. - Male: Nam
- Female: Nữ
SeniorCitizen Định tính Khách hàng có phải là người cao tuổi hay không (trên 65 tuổi). - Yes: Có
- No: Không
Partner Định tính Khách hàng có vợ/chồng hay không. - Yes: Có
- No: Không
Dependents Định tính Khách hàng có người phụ thuộc hay không (con cái, cha mẹ, v.v.). - Yes: Có
- No: Không
InternetService Định tính Loại dịch vụ Internet mà khách hàng đăng ký sử dụng. - DSL: Internet qua đường dây điện thoại
- Fiber optic: Cáp quang
- No: Không sử dụng Internet
Contract Định tính Loại hợp đồng của khách hàng. - Month-to-month: Hàng tháng
- One year: Hợp đồng 1 năm
- Two year: Hợp đồng 2 năm
PaymentMethod Định tính Phương thức thanh toán của khách hàng. - Electronic Check: Séc điện tử
- Mailed Check: Séc qua thư
- Bank transfer: Chuyển khoản ngân hàng
- Credit Card: Thẻ tín dụng
tenure Định lượng Số tháng khách hàng đã sử dụng dịch vụ. Số nguyên (ví dụ: 1, 12, 24,…)
MonthlyCharges Định lượng Chi phí khách hàng trả hàng tháng. Số thực (ví dụ: 29.85, 104.80)
TotalCharges Định lượng Tổng chi phí khách hàng đã trả từ trước tới nay. Số thực, là tổng chi phí tích lũy

1.2. Bối cảnh nghiên cứu

Trong bối cảnh chuyển đổi số diễn ra mạnh mẽ, ngành viễn thông đang phải đối mặt với áp lực cạnh tranh chưa từng có. Khi thị trường tiến gần đến điểm bão hòa, người dùng có quá nhiều lựa chọn về nhà cung cấp dịch vụ với mức giá, chất lượng và ưu đãi gần như tương đương nhau. Điều này khiến việc thu hút khách hàng mới ngày càng khó khăn và tốn kém.

Chính vì thế, thay vì dồn lực vào việc tìm kiếm khách hàng mới, các doanh nghiệp viễn thông buộc phải chuyển hướng chiến lược sang giữ chân khách hàng hiện tại — những người đã từng chọn và sử dụng dịch vụ. Trong chiến lược này, tỷ lệ rời bỏ (customer churn) trở thành chỉ số then chốt.

Một tỷ lệ churn cao không chỉ khiến doanh nghiệp mất doanh thu trực tiếp mà còn đẩy chi phí marketing tăng vọt để bù đắp lượng khách hàng bị mất. Tệ hơn, nếu khách hàng ra đi vì không hài lòng, điều đó có thể kéo theo hiệu ứng lan truyền tiêu cực, ảnh hưởng đến uy tín thương hiệu.

Giữ chân khách hàng không chỉ là một vấn đề kinh tế, mà là một bài toán sống còn với mọi nhà mạng. Đó là lý do vì sao việc hiểu rõ vì sao khách hàng rời đi, và làm sao để dự báo điều đó từ sớm, trở thành ưu tiên hàng đầu trong các chiến lược vận hành và phát triển của ngành viễn thông hiện đại.

1.3. Mục tiêu nghiên cứu

Mục tiêu của nghiên cứu này là xác định và phân tích các yếu tố ảnh hưởng đến việc rời bỏ việc sử dụng dịch vụ viễn thông của khách hàng. Cụ thể là tác giả tập trung vào các khía cạnh sau: - Tỷ lệ rời bỏ của khách hàng [Churn]. - Loại hợp đồng có ảnh hưởng đến tỷ lệ khách hàng rời bỏ dịch vụ viễn thông hay không? Liệu hợp đồng ngắn hạn thì tỷ lệ khách hàng rời bỏ càng cao. - Dịch vụ Internet có tác động đến tỷ lệ rời bỏ khách hàng hay không? Khách hàng sử dụng loại dịch vụ Internet nào có khả năng rời bỏ dịch vụ viễn thông cao nhất; dịch vụ Internet trực tiếp thông qua điện thoại (DSL) hay sử dụng cáp quang (Fiber Optic) hay không sử dụng dịch vụ Internet. - Hình thức thanh toán có ảnh hưởng đến khả năng rời bỏ của khách hàng hay không? Thanh toán qua Séc điện tử hay Thanh toán qua thư, Thẻ ghi nợ, Chuyển khoản ngân hàng. - Và cuối cùng là độ tuổi có ảnh hưởng đến tỷ lệ rời bỏ của khách hàng hay không? Liệu người lớn tuổi thì sẽ rời bỏ dịch vụ viễn thông nhiều hơn là người trẻ tuổi.

1.4. Phương pháp nghiên cứu

Nghiên cứu sử dụng các phương pháp thống kê và mô hình hồi quy nhị phân, bao gồm ba mô hình: xác suất tuyến tính, Probit và Logit, để phân tích dữ liệu khách hàng trong ngành viễn thông. Trước tiên, dữ liệu được xử lý bằng thống kê mô tả nhằm tóm tắt đặc điểm cơ bản của mẫu khảo sát. Tiếp theo, các kỹ thuật thống kê suy luận như kiểm định chi-bình phương và phân tích tỷ lệ được áp dụng để đánh giá mối liên hệ giữa các biến. Cuối cùng, mô hình hồi quy Logit và Probit được triển khai nhằm xác định mức độ ảnh hưởng của từng yếu tố (như loại hợp đồng, dịch vụ internet, hình thức thanh toán, v.v.) đến khả năng khách hàng rời bỏ dịch vụ. Phương pháp này cho phép nhận diện các nhóm khách hàng có nguy cơ cao, từ đó hỗ trợ doanh nghiệp xây dựng chiến lược giữ chân hiệu quả hơn.

1.5. Ý nghĩa của bài nghiên cứu

Nghiên cứu này ứng dụng các phương pháp phân tích dữ liệu định lượng, bao gồm thống kê mô tả, kiểm định giả thuyết và mô hình hồi quy nhị phân (Logit, Probit), để dự đoán khả năng rời bỏ dịch vụ của khách hàng trong ngành viễn thông. Dựa trên bộ dữ liệu hơn 7.000 khách hàng, nghiên cứu đã xác định rõ các yếu tố làm tăng rủi ro rời bỏ như loại hợp đồng, hình thức thanh toán và loại dịch vụ sử dụng.

Về mặt khoa học, nghiên cứu là minh chứng cho quy trình phân tích dữ liệu logic và có thể tái sử dụng trong các bài toán tương tự về hành vi khách hàng. Về mặt thực tiễn, kết quả giúp doanh nghiệp viễn thông xác định sớm nhóm khách hàng rủi ro cao, từ đó triển khai các chiến lược giữ chân hiệu quả và tiết kiệm chi phí.


CHƯƠNG 2: MÔ TẢ - PHÂN TÍCH BIÊN PHỤ THUỘC VÀ CÁC BIẾN ĐỘC LẬP

Trước khi tiến hành phân tích, tác giả thực hiện bước tiền xử lý dữ liệu nhằm đảm bảo tính chính xác và tránh lỗi trong quá trình chạy mã R.

# Đọc dữ liệu vào R
df <- read.csv("WA_Fn-UseC_-Telco-Customer-Churn.csv")

# 1. Xử lý TotalCharges
df$TotalCharges <- as.numeric(as.character(df$TotalCharges)) 
df_clean <- df %>% filter(!is.na(TotalCharges))

# 2. Chuyển đổi hàng loạt các biến character sang factor
df_clean <- df_clean %>%
  mutate(across(where(is.character) & !customerID, as.factor))

# 3. Chuyển đổi SeniorCitizen từ số (0, 1) sang factor ("No", "Yes")
df_clean <- df_clean %>%
  mutate(SeniorCitizen = as.factor(ifelse(SeniorCitizen == 1, "Yes", "No")))

# 4. TẠO BIẾN NHỊ PHÂN CHO MÔ HÌNH HỒI QUY
df_clean$Churn_binary <- ifelse(df_clean$Churn == "Yes", 1, 0)

Diễn giải: Đầu tiên, dữ liệu được đọc vào R. Biến TotalCharges được phát hiện có một số giá trị bị thiếu. Để xử lý, tác giả đã chuyển các giá trị trống về dạng NA và sau đó loại bỏ các dòng này khỏi phân tích. Tiếp theo, các biến văn bản (trừ customerID) được chuyển sang định dạng factor. Biến SeniorCitizen được chuyển đổi từ dạng số (0, 1) sang nhãn (“No”, “Yes”). Cuối cùng, biến Churn_binary (0/1) được tạo sẵn để phục vụ cho các mô hình hồi quy ở các chương sau.

2.1. Biến Phụ Thuộc Tỷ lệ rời bỏ (Churn)

Bảng tần số và tần suất của biến Churn giúp lượng hóa mức độ nghiêm trọng của vấn đề rời bỏ khách hàng.

kable(addmargins(table(df_clean$Churn)), caption = "Bảng 2: Bảng tần số cho biến Churn")
Bảng 2: Bảng tần số cho biến Churn
Var1 Freq
No 5163
Yes 1869
Sum 7032
kable(prop.table(table(df_clean$Churn)), caption = "Bảng tần suất (tỷ lệ) cho biến Churn", digits = 4)
Bảng tần suất (tỷ lệ) cho biến Churn
Var1 Freq
No 0.7342
Yes 0.2658
ggplot(df_clean, aes(x = Churn, fill = Churn)) +
  geom_bar(width = 0.6) +
  geom_text(stat='count', aes(label=..count..), vjust=-0.5) +
  labs(title="Phân phối số lượng khách hàng theo tình trạng rời bỏ", x="Tình trạng Rời bỏ", y="Số lượng") +
  theme_minimal(base_size = 14) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5))
## Warning: The dot-dot notation (`..count..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(count)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Hình 1.1: Phân phối số lượng khách hàng theo tình trạng rời bỏ

Hình 1.1: Phân phối số lượng khách hàng theo tình trạng rời bỏ

pie_data_churn <- as.data.frame(table(df_clean$Churn))
colnames(pie_data_churn) <- c("Status", "Count")
pie_data_churn$Percentage <- scales::percent(pie_data_churn$Count / sum(pie_data_churn$Count), accuracy = 0.1)

ggplot(pie_data_churn, aes(x = "", y = Count, fill = Status)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  geom_text(aes(label = Percentage), position = position_stack(vjust = 0.5)) +
  labs(title = "Tỷ lệ khách hàng theo tình trạng rời bỏ", fill = "Tình trạng") +
  theme_void(base_size = 14) +
  theme(plot.title = element_text(hjust = 0.5), legend.title = element_text(size=12), legend.text = element_text(size=10))
Hình 1.2: Tỷ lệ khách hàng theo tình trạng rời bỏ

Hình 1.2: Tỷ lệ khách hàng theo tình trạng rời bỏ

Nhận xét: Dữ liệu cho thấy có 1,869 khách hàng (26.6%) đã rời bỏ dịch vụ. Mặc dù nhóm khách hàng tiếp tục sử dụng chiếm đa số (73.4%), tỷ lệ rời bỏ vẫn ở mức cao và là một vấn đề nghiêm trọng cần giải quyết. Sự chênh lệch giữa hai nhóm (gần 3:1) cho thấy dữ liệu mất cân bằng, đây là một yếu tố kỹ thuật cần được xem xét cẩn thận khi xây dựng các mô hình dự báo để tránh thiên vị cho nhóm đa số.

2.2. Biến Độc Lập

2.2.1. Biến Contract (Loại hợp đồng)

kable(addmargins(table(df_clean$Contract)), caption = "Bảng 3: Bảng tần số của biến Contract")
Bảng 3: Bảng tần số của biến Contract
Var1 Freq
Month-to-month 3875
One year 1472
Two year 1685
Sum 7032
kable(prop.table(table(df_clean$Contract)), caption = "Bảng tần suất (tỷ lệ) của biến Contract", digits = 4)
Bảng tần suất (tỷ lệ) của biến Contract
Var1 Freq
Month-to-month 0.5511
One year 0.2093
Two year 0.2396
ggplot(df_clean, aes(x = Contract, fill = Contract)) +
  geom_bar(width = 0.6) +
  geom_text(stat='count', aes(label=..count..), vjust=-0.5) +
  labs(title="Phân phối số lượng theo loại hợp đồng", x="Loại Hợp đồng", y="Số lượng") +
  theme_minimal(base_size = 14) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5))
Hình 2.1: Phân phối số lượng khách hàng theo loại hợp đồng

Hình 2.1: Phân phối số lượng khách hàng theo loại hợp đồng

pie_data_contract <- as.data.frame(table(df_clean$Contract))
colnames(pie_data_contract) <- c("Contract", "Count")
pie_data_contract$Percentage <- scales::percent(pie_data_contract$Count / sum(pie_data_contract$Count), accuracy = 0.1)

ggplot(pie_data_contract, aes(x = "", y = Count, fill = Contract)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  geom_text(aes(label = Percentage), position = position_stack(vjust = 0.5)) +
  labs(title = "Tỷ lệ các loại hợp đồng", fill = "Hợp đồng") +
  theme_void(base_size = 14) +
  theme(plot.title = element_text(hjust = 0.5))
Hình 2.2: Tỷ lệ các loại hợp đồng

Hình 2.2: Tỷ lệ các loại hợp đồng

Nhận xét: Nhóm khách hàng sử dụng hợp đồng theo tháng chiếm tỷ lệ áp đảo với 3,875 người (55.1%). Đây là nhóm có tính linh hoạt cao nhưng cũng là nhóm tiềm ẩn rủi ro rời bỏ lớn nhất do không có cam kết dài hạn. Các hợp đồng dài hạn (1 năm và 2 năm) chiếm tỷ lệ thấp hơn, lần lượt là 20.9%24.0%.

2.2.2. Biến Internet Service (Dịch vụ Internet)

kable(addmargins(table(df_clean$InternetService)), caption = "Bảng 4: Bảng tần số của biến Internet Service")
Bảng 4: Bảng tần số của biến Internet Service
Var1 Freq
DSL 2416
Fiber optic 3096
No 1520
Sum 7032
kable(prop.table(table(df_clean$InternetService)), caption = "Bảng tần suất của biến Internet Service", digits = 4)
Bảng tần suất của biến Internet Service
Var1 Freq
DSL 0.3436
Fiber optic 0.4403
No 0.2162
ggplot(df_clean, aes(x = InternetService, fill = InternetService)) +
  geom_bar(width = 0.6) +
  geom_text(stat='count', aes(label=..count..), vjust=-0.5) +
  labs(title="Phân phối số lượng theo dịch vụ Internet", x="Dịch vụ Internet", y="Số lượng") +
  theme_minimal(base_size = 14) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5))
Hình 3.1: Phân phối số lượng khách hàng theo dịch vụ Internet

Hình 3.1: Phân phối số lượng khách hàng theo dịch vụ Internet

pie_data_internet <- as.data.frame(table(df_clean$InternetService))
colnames(pie_data_internet) <- c("Service", "Count")
pie_data_internet$Percentage <- scales::percent(pie_data_internet$Count / sum(pie_data_internet$Count), accuracy = 0.1)

ggplot(pie_data_internet, aes(x = "", y = Count, fill = Service)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  geom_text(aes(label = Percentage), position = position_stack(vjust = 0.5)) +
  labs(title = "Tỷ lệ các dịch vụ Internet", fill = "Dịch vụ") +
  theme_void(base_size = 14) +
  theme(plot.title = element_text(hjust = 0.5))
Hình 3.2: Tỷ lệ các loại dịch vụ Internet

Hình 3.2: Tỷ lệ các loại dịch vụ Internet

Nhận xét: Dịch vụ cáp quang (Fiber optic) là phổ biến nhất (44.0%), phản ánh nhu cầu về internet tốc độ cao. Có đến 21.6% khách hàng không sử dụng dịch vụ internet, tạo thành một phân khúc khách hàng riêng biệt.

2.2.3. Biến Payment Method (Phương thức thanh toán)

kable(addmargins(table(df_clean$PaymentMethod)), caption = "Bảng 5: Bảng tần số của biến Payment Method")
Bảng 5: Bảng tần số của biến Payment Method
Var1 Freq
Bank transfer (automatic) 1542
Credit card (automatic) 1521
Electronic check 2365
Mailed check 1604
Sum 7032
kable(prop.table(table(df_clean$PaymentMethod)), caption = "Bảng tần suất của biến PaymentMethod", digits = 4)
Bảng tần suất của biến PaymentMethod
Var1 Freq
Bank transfer (automatic) 0.2193
Credit card (automatic) 0.2163
Electronic check 0.3363
Mailed check 0.2281
ggplot(df_clean, aes(x = PaymentMethod, fill = PaymentMethod)) +
  geom_bar(width = 0.7) +  # <--- THÊM DẤU CỘNG Ở ĐÂY
  geom_text(stat='count', aes(label=..count..), vjust=-0.5) +
  labs(title="Phân phối theo phương thức thanh toán", x="Phương thức", y="Số lượng") +
  theme_minimal(base_size = 12) +
  theme(axis.text.x = element_text(angle = 15, hjust = 1), legend.position = "none", plot.title = element_text(hjust = 0.5))
Hình 4.1: Phân phối số lượng theo phương thức thanh toán

Hình 4.1: Phân phối số lượng theo phương thức thanh toán

pie_data_payment <- as.data.frame(table(df_clean$PaymentMethod))
colnames(pie_data_payment) <- c("Method", "Count")
pie_data_payment$Percentage <- scales::percent(pie_data_payment$Count / sum(pie_data_payment$Count), accuracy = 0.1)

ggplot(pie_data_payment, aes(x = "", y = Count, fill = Method)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  geom_text(aes(label = Percentage), position = position_stack(vjust = 0.5)) +
  labs(title = "Tỷ lệ các phương thức thanh toán", fill = "Phương thức") +
  theme_void(base_size = 14) +
  theme(plot.title = element_text(hjust = 0.5))
Hình 4.2: Tỷ lệ các phương thức thanh toán

Hình 4.2: Tỷ lệ các phương thức thanh toán

Nhận xét: Electronic check là phương thức phổ biến nhất (33.6%). Đa số khách hàng (56.5%) vẫn dùng các phương thức thanh toán thủ công. Điều này có thể là một yếu tố rủi ro.

2.2.4. Biến SeniorCitizen (Người cao tuổi)

kable(addmargins(table(df_clean$SeniorCitizen)), caption = "Bảng 6: Bảng tần số của biến SeniorCitizen")
Bảng 6: Bảng tần số của biến SeniorCitizen
Var1 Freq
No 5890
Yes 1142
Sum 7032
kable(prop.table(table(df_clean$SeniorCitizen)), caption = "Bảng tần suất của biến SeniorCitizen", digits = 4)
Bảng tần suất của biến SeniorCitizen
Var1 Freq
No 0.8376
Yes 0.1624
ggplot(df_clean, aes(x = SeniorCitizen, fill = SeniorCitizen)) +
  geom_bar(width = 0.6) +
  geom_text(stat='count', aes(label=..count..), vjust=-0.5) +
  labs(title="Phân phối theo nhóm tuổi", x="Là người cao tuổi?", y="Số lượng") +
  theme_minimal(base_size = 14) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5))
Hình 5.1: Phân phối số lượng khách hàng theo nhóm tuổi

Hình 5.1: Phân phối số lượng khách hàng theo nhóm tuổi

pie_data_senior <- as.data.frame(table(df_clean$SeniorCitizen))
colnames(pie_data_senior) <- c("Group", "Count")
pie_data_senior$Percentage <- scales::percent(pie_data_senior$Count / sum(pie_data_senior$Count), accuracy = 0.1)

ggplot(pie_data_senior, aes(x = "", y = Count, fill = Group)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  geom_text(aes(label = Percentage), position = position_stack(vjust = 0.5)) +
  labs(title = "Tỷ lệ khách hàng cao tuổi", fill = "Nhóm tuổi") +
  theme_void(base_size = 14) +
  theme(plot.title = element_text(hjust = 0.5))
Hình 5.2: Tỷ lệ khách hàng theo nhóm tuổi

Hình 5.2: Tỷ lệ khách hàng theo nhóm tuổi

Nhận xét: Nhóm không phải người cao tuổi chiếm đại đa số (83.8%), trong khi nhóm người cao tuổi chỉ chiếm 16.2%.


CHƯƠNG 3: PHÂN TÍCH MỐI QUAN HỆ GIỮA HAI BIẾN ĐỊNH TÍNH

3.1 Churn và Contract (Loại hợp đồng)

3.1.1. Bảng tần số

churn_contract_table <- table(df_clean$Contract, df_clean$Churn)
cat("Bảng tần số chéo giữa Contract và Churn:\n")
## Bảng tần số chéo giữa Contract và Churn:
addmargins(churn_contract_table)
##                 
##                    No  Yes  Sum
##   Month-to-month 2220 1655 3875
##   One year       1306  166 1472
##   Two year       1637   48 1685
##   Sum            5163 1869 7032

3.1.2. Kiểm định Chi-bình phương

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

  • \(H_0\): Loại hợp đồng và việc rời bỏ là hai biến độc lập.
  • \(H_1\): Loại hợp đồng và việc rời bỏ có liên quan đến nhau.
chi_contract <- chisq.test(churn_contract_table)
print(chi_contract)
## 
##  Pearson's Chi-squared test
## 
## data:  churn_contract_table
## X-squared = 1179.5, df = 2, p-value < 2.2e-16

Nhận xét: p-value < 2.2e-16, bác bỏ \(H_0\). Có một mối liên hệ thống kê cực kỳ mạnh mẽ giữa loại hợp đồng và khả năng rời bỏ.

3.1.3. Trực quan hóa Mối quan hệ

ggplot(data = df_clean) +
  geom_mosaic(aes(x = product(Contract, Churn), fill=Churn)) +
  labs(title="Mối quan hệ giữa Loại hợp đồng và Tỷ lệ rời bỏ", x="Loại hợp đồng", y="Tỷ lệ Churn") +
  theme_minimal(base_size = 12) +
  theme(axis.text.x = element_text(angle=45, hjust=1),
        plot.title = element_text(hjust = 0.5))
## Warning: The `scale_name` argument of `continuous_scale()` is deprecated as of ggplot2
## 3.5.0.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: The `trans` argument of `continuous_scale()` is deprecated as of ggplot2 3.5.0.
## ℹ Please use the `transform` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: `unite_()` was deprecated in tidyr 1.2.0.
## ℹ Please use `unite()` instead.
## ℹ The deprecated feature was likely used in the ggmosaic package.
##   Please report the issue at <https://github.com/haleyjeppson/ggmosaic>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Hình 7: Biểu đồ Mosaic giữa Contract và Churn

Hình 7: Biểu đồ Mosaic giữa Contract và Churn

Nhận xét: Biểu đồ Mosaic cho thấy rõ ràng phần diện tích đại diện cho khách hàng rời bỏ (màu đỏ) chiếm tỷ trọng rất lớn trong nhóm Month-to-month và cực kỳ nhỏ trong nhóm Two year.

3.1.4. Phân tích so sánh chi tiết

So sánh ‘One year’ vs. ‘Month-to-month’

a. Kiểm định Hiệu tỷ lệ

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

  • \(H_0\): Tỷ lệ rời bỏ ở nhóm ‘One year’ và ‘Month-to-month’ là bằng nhau (\(p_1 - p_2 = 0\)).
  • \(H_1\): Tỷ lệ rời bỏ ở nhóm ‘One year’ thấp hơn nhóm ‘Month-to-month’ (\(p_1 - p_2 < 0\)).
contract_sub_1yr <- df_clean %>% 
  filter(Contract %in% c("Month-to-month", "One year")) %>%
  droplevels()
table_1yr <- table(contract_sub_1yr$Contract, contract_sub_1yr$Churn)
prop_test_1yr <- prop.test(x = table_1yr[, "Yes"], n = rowSums(table_1yr), alternative="less", correct=FALSE)
print(prop_test_1yr)
## 
##  2-sample test for equality of proportions without continuity correction
## 
## data:  table_1yr[, "Yes"] out of rowSums(table_1yr)
## X-squared = 469.31, df = 1, p-value = 1
## alternative hypothesis: less
## 95 percent confidence interval:
##  -1.0000000  0.3331596
## sample estimates:
##    prop 1    prop 2 
## 0.4270968 0.1127717

Nhận xét: Xác suất rời bỏ ở nhóm hợp đồng 1 năm là 11.3%, thấp hơn đáng kể so với nhóm hợp đồng tháng là 42.7%. Với p-value < 2.2e-16, sự khác biệt này có ý nghĩa thống kê cao.

b. Rủi ro Tương đối (RR)

rr_1yr <- riskratio(table_1yr, method="wald")
print(rr_1yr)
## $data
##                 
##                    No  Yes Total
##   Month-to-month 2220 1655  3875
##   One year       1306  166  1472
##   Total          3526 1821  5347
## 
## $measure
##                 risk ratio with 95% C.I.
##                   estimate     lower     upper
##   Month-to-month 1.0000000        NA        NA
##   One year       0.2640426 0.2277513 0.3061167
## 
## $p.value
##                 two-sided
##                  midp.exact  fisher.exact   chi.square
##   Month-to-month         NA            NA           NA
##   One year                0 1.193932e-117 4.53896e-104
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: Tỷ lệ Rủi ro Tương đối (RR) là 0.264. Điều này cho thấy nguy cơ rời bỏ của nhóm hợp đồng 1 năm chỉ bằng khoảng 26.4% so với nhóm hợp đồng tháng. Khoảng ước lượng cho RR với độ tin cậy 95% là từ 0.228 đến 0.306. Vì khoảng này không chứa 1, kết quả có ý nghĩa thống kê.

c. Tỷ số Chênh (OR)

or_1yr <- oddsratio(table_1yr, method="wald")
print(or_1yr)
## $data
##                 
##                    No  Yes Total
##   Month-to-month 2220 1655  3875
##   One year       1306  166  1472
##   Total          3526 1821  5347
## 
## $measure
##                 odds ratio with 95% C.I.
##                   estimate     lower     upper
##   Month-to-month 1.0000000        NA        NA
##   One year       0.1704982 0.1433276 0.2028196
## 
## $p.value
##                 two-sided
##                  midp.exact  fisher.exact   chi.square
##   Month-to-month         NA            NA           NA
##   One year                0 1.193932e-117 4.53896e-104
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: Tỷ số Chênh (OR) là 0.17. Điều này có nghĩa là odds rời bỏ của nhóm hợp đồng 1 năm thấp hơn, chỉ bằng khoảng 17.4% so với odds của nhóm hợp đồng tháng.

So sánh ‘Two year’ vs. ‘Month-to-month’

a. Kiểm định Hiệu tỷ lệ

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

  • \(H_0\): Tỷ lệ rời bỏ ở nhóm ‘Two year’ và ‘Month-to-month’ là bằng nhau (\(p_1 - p_2 = 0\)).
  • \(H_1\): Tỷ lệ rời bỏ ở nhóm ‘Two year’ thấp hơn nhóm ‘Month-to-month’ (\(p_1 - p_2 < 0\)).
contract_sub_2yr <- df_clean %>% 
  filter(Contract %in% c("Month-to-month", "Two year")) %>%
  droplevels()
table_2yr <- table(contract_sub_2yr$Contract, contract_sub_2yr$Churn)
prop_test_2yr <- prop.test(x = table_2yr[, "Yes"], n = rowSums(table_2yr), alternative="less", correct=FALSE)
print(prop_test_2yr)
## 
##  2-sample test for equality of proportions without continuity correction
## 
## data:  table_2yr[, "Yes"] out of rowSums(table_2yr)
## X-squared = 878.17, df = 1, p-value = 1
## alternative hypothesis: less
## 95 percent confidence interval:
##  -1.0000000  0.4132825
## sample estimates:
##     prop 1     prop 2 
## 0.42709677 0.02848665

Nhận xét: Xác suất rời bỏ ở nhóm hợp đồng 2 năm chỉ là 2.8%. Với p-value < 2.2e-16, tỷ lệ này thấp hơn rất nhiều so với nhóm hợp đồng tháng một cách có ý nghĩa thống kê.

b. Rủi ro Tương đối (RR)

rr_2yr <- riskratio(table_2yr, method="wald")
print(rr_2yr)
## $data
##                 
##                    No  Yes Total
##   Month-to-month 2220 1655  3875
##   Two year       1637   48  1685
##   Total          3857 1703  5560
## 
## $measure
##                 risk ratio with 95% C.I.
##                    estimate      lower      upper
##   Month-to-month 1.00000000         NA         NA
##   Two year       0.06669834 0.05034845 0.08835762
## 
## $p.value
##                 two-sided
##                  midp.exact  fisher.exact    chi.square
##   Month-to-month         NA            NA            NA
##   Two year                0 4.505575e-246 5.462447e-193
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: RR = 0.067. Nguy cơ rời bỏ của khách hàng có hợp đồng 2 năm chỉ bằng 6.7% so với khách hàng hợp đồng tháng. Khoảng tin cậy 95% [0.050, 0.089] cho thấy đây là một yếu tố bảo vệ rất mạnh.

c. Tỷ số Chênh (OR)

or_2yr <- oddsratio(table_2yr, method="wald")
print(or_2yr)
## $data
##                 
##                    No  Yes Total
##   Month-to-month 2220 1655  3875
##   Two year       1637   48  1685
##   Total          3857 1703  5560
## 
## $measure
##                 odds ratio with 95% C.I.
##                    estimate      lower      upper
##   Month-to-month 1.00000000         NA         NA
##   Two year       0.03933214 0.02931369 0.05277456
## 
## $p.value
##                 two-sided
##                  midp.exact  fisher.exact    chi.square
##   Month-to-month         NA            NA            NA
##   Two year                0 4.505575e-246 5.462447e-193
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: OR = 0.039. Odds rời bỏ của nhóm hợp đồng 2 năm chỉ bằng 4.1% so với nhóm hợp đồng tháng, khẳng định đây là yếu tố giữ chân khách hàng hiệu quả nhất.

3.1.5. Khoảng ước lượng tỷ lệ

Ước lượng tỷ lệ rời bỏ cho nhóm hợp đồng theo tháng (Month-to-month)

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

  • \(H_0\): Tỷ lệ rời bỏ của nhóm hợp đồng theo tháng bằng tỷ lệ trung bình của tổng thể (khoảng 27%), tức là \(p = 0.27\).

  • \(H_1\): Tỷ lệ rời bỏ của nhóm hợp đồng theo tháng khác 27% (\(p \neq 0.27\)).

count_m2m <- churn_contract_table["Month-to-month", "Yes"]
total_m2m <- sum(churn_contract_table["Month-to-month", ])
prop.test(x = count_m2m, n = total_m2m, p = 0.27, correct = FALSE)
## 
##  1-sample proportions test without continuity correction
## 
## data:  count_m2m out of total_m2m, null probability 0.27
## X-squared = 485.2, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.27
## 95 percent confidence interval:
##  0.411602 0.442736
## sample estimates:
##         p 
## 0.4270968

Nhận xét: Kết quả kiểm định cho thấy p-value < 2.2e-16, rất nhỏ hơn mức ý nghĩa 0.05. Điều này cho thấy có bằng chứng mạnh mẽ để bác bỏ giả thuyết \(H_0\). Tỷ lệ rời bỏ thực tế trong mẫu của nhóm này là 42.7%, cao hơn đáng kể so với mức trung bình. Khoảng ước lượng tỷ lệ rời bỏ thật sự của nhóm hợp đồng tháng, với độ tin cậy 95%, nằm trong khoảng từ 41.2% đến 44.2%.


3.2. Phân tích Churn và SeniorCitizen (Người cao tuổi)

3.2.1. Bảng tần số

df_clean$SeniorCitizen_labeled <- factor(df_clean$SeniorCitizen, levels = c("No", "Yes"), labels = c("Không phải cao tuổi", "Là người cao tuổi"))
churn_senior_table <- table(df_clean$SeniorCitizen_labeled, df_clean$Churn_labeled)
cat("Bảng tần số chéo giữa SeniorCitizen và Churn:\n")
## Bảng tần số chéo giữa SeniorCitizen và Churn:
addmargins(churn_senior_table)
##                      
##                       Không rời bỏ Rời bỏ  Sum
##   Không phải cao tuổi         4497   1393 5890
##   Là người cao tuổi            666    476 1142
##   Sum                         5163   1869 7032

3.2.2. Kiểm định Chi-bình phương

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

  • \(H_0\): Việc là người cao tuổi và quyết định rời bỏ dịch vụ là hai biến độc lập.

  • \(H_1\): Có mối liên hệ giữa việc là người cao tuổi và quyết định rời bỏ dịch vụ.

print(chisq.test(table(df_clean$Churn, df_clean$SeniorCitizen)))
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  table(df_clean$Churn, df_clean$SeniorCitizen)
## X-squared = 158.44, df = 1, p-value < 2.2e-16

Nhận xét: p-value < 2.2e-16. Bác bỏ \(H_0\). Có mối liên hệ mạnh mẽ.

3.2.3. Trực quan hóa Mối quan hệ

ggplot(data = df_clean) +
  geom_mosaic(aes(x = product(SeniorCitizen, Churn), fill=Churn)) +
  labs(title="Mối quan hệ giữa Nhóm tuổi và Tỷ lệ rời bỏ", x="Là người cao tuổi?", y="Tỷ lệ Churn") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(hjust = 0.5))
Hình 8: Biểu đồ Mosaic giữa SeniorCitizen và Churn

Hình 8: Biểu đồ Mosaic giữa SeniorCitizen và Churn

3.2.4. Hiệu tỷ lệ

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

  • \(H_0\): Tỷ lệ rời bỏ ở hai nhóm là bằng nhau (\(p_1 - p_2 = 0\)).

  • \(H_1\): Tỷ lệ rời bỏ ở nhóm không phải cao tuổi thấp hơn nhóm cao tuổi (\(p_1 - p_2 < 0\)).

counts_churn <- churn_senior_table[, "Rời bỏ"] 
totals_group <- rowSums(churn_senior_table)
prop_test_senior <- prop.test(x = counts_churn, n = totals_group, alternative = "less", correct = FALSE)
print(prop_test_senior)
## 
##  2-sample test for equality of proportions without continuity correction
## 
## data:  counts_churn out of totals_group
## X-squared = 159.36, df = 1, p-value < 2.2e-16
## alternative hypothesis: less
## 95 percent confidence interval:
##  -1.0000000 -0.1546424
## sample estimates:
##    prop 1    prop 2 
## 0.2365025 0.4168126

Nhận xét: Xác suất rời bỏ của nhóm không phải người cao tuổi là 23.7%, trong khi của nhóm người cao tuổi là 41.7%. p-value < 2.2e-16 cho thấy sự khác biệt này có ý nghĩa thống kê cao.

3.2.5. Rủi ro tương đối (RR)

rr_senior <- riskratio(churn_senior_table, method="wald")
print(rr_senior)
## $data
##                      
##                       Không rời bỏ Rời bỏ Total
##   Không phải cao tuổi         4497   1393  5890
##   Là người cao tuổi            666    476  1142
##   Total                       5163   1869  7032
## 
## $measure
##                      risk ratio with 95% C.I.
##                       estimate    lower    upper
##   Không phải cao tuổi 1.000000       NA       NA
##   Là người cao tuổi   1.762402 1.622784 1.914033
## 
## $p.value
##                      two-sided
##                       midp.exact fisher.exact   chi.square
##   Không phải cao tuổi         NA           NA           NA
##   Là người cao tuổi            0 4.527487e-34 1.558566e-36
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: RR = 1.76. Điều này cho thấy nguy cơ rời bỏ dịch vụ ở nhóm khách hàng cao tuổi cao gấp 1.76 lần so với nhóm khách hàng không phải người cao tuổi. Khoảng tin cậy 95% cho RR là từ 1.62 đến 1.91, không chứa 1 nên kết quả có ý nghĩa thống kê.

3.2.6. Tỷ số Chênh (OR)

or_senior <- oddsratio(churn_senior_table, method="wald")
print(or_senior)
## $data
##                      
##                       Không rời bỏ Rời bỏ Total
##   Không phải cao tuổi         4497   1393  5890
##   Là người cao tuổi            666    476  1142
##   Total                       5163   1869  7032
## 
## $measure
##                      odds ratio with 95% C.I.
##                       estimate    lower    upper
##   Không phải cao tuổi 1.000000       NA       NA
##   Là người cao tuổi   2.307302 2.021783 2.633143
## 
## $p.value
##                      two-sided
##                       midp.exact fisher.exact   chi.square
##   Không phải cao tuổi         NA           NA           NA
##   Là người cao tuổi            0 4.527487e-34 1.558566e-36
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: OR = 2.31. Tỷ lệ chênh (odds) của việc rời bỏ dịch vụ ở nhóm khách hàng cao tuổi cao hơn 2.29 lần so với nhóm không phải người cao tuổi.

3.2.7. Ước lượng tỷ lệ rời bỏ cho nhóm người cao tuổi (SeniorCitizen = Yes)

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

  • \(H_0\): Tỷ lệ rời bỏ của nhóm người cao tuổi bằng tỷ lệ trung bình của tổng thể (khoảng 27%), tức là \(p = 0.27\).

  • \(H_1\): Tỷ lệ rời bỏ của nhóm người cao tuổi khác 27% (\(p \neq 0.27\)).

count_senior <- churn_senior_table["Là người cao tuổi", "Rời bỏ"]
total_senior <- sum(churn_senior_table["Là người cao tuổi", ])
prop.test(x = count_senior, n = total_senior, p = 0.27, correct = FALSE)
## 
##  1-sample proportions test without continuity correction
## 
## data:  count_senior out of total_senior, null probability 0.27
## X-squared = 124.88, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.27
## 95 percent confidence interval:
##  0.3885431 0.4456398
## sample estimates:
##         p 
## 0.4168126

Nhận xét: Kết quả kiểm định có p-value < 2.2e-16, bác bỏ giả thuyết \(H_0\). Tỷ lệ rời bỏ thực tế trong mẫu của nhóm người cao tuổi là 41.7%, cao hơn rất nhiều so với mức trung bình. Khoảng ước lượng tỷ lệ rời bỏ thật sự của nhóm này, với độ tin cậy 95%, nằm trong khoảng từ 38.9% đến 44.5%.


3.3. Phân tích Churn và PaymentMethod (Phương thức thanh toán)

3.3.1. Bảng tần số

churn_payment_table <- table(df_clean$PaymentMethod, df_clean$Churn)
cat("Bảng tần số chéo:\n")
## Bảng tần số chéo:
addmargins(churn_payment_table)
##                            
##                               No  Yes  Sum
##   Bank transfer (automatic) 1284  258 1542
##   Credit card (automatic)   1289  232 1521
##   Electronic check          1294 1071 2365
##   Mailed check              1296  308 1604
##   Sum                       5163 1869 7032

3.3.2. Kiểm định Chi-bình phương

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

  • \(H_0\): Phương thức thanh toán và việc rời bỏ là hai biến độc lập.

  • \(H_1\): Phương thức thanh toán và việc rời bỏ có liên quan đến nhau.

print(chisq.test(churn_payment_table))
## 
##  Pearson's Chi-squared test
## 
## data:  churn_payment_table
## X-squared = 645.43, df = 3, p-value < 2.2e-16

Nhận xét: p-value < 2.2e-16. Bác bỏ \(H_0\). Phương thức thanh toán có mối liên hệ rất mạnh với việc rời bỏ.

3.3.3. Trực quan hóa Mối quan hệ

ggplot(data = df_clean) +
  geom_mosaic(aes(x = product(PaymentMethod, Churn), fill=Churn)) +
  labs(title="Mối quan hệ giữa Phương thức thanh toán và Tỷ lệ rời bỏ", x="Phương thức thanh toán", y="Tỷ lệ Churn") +
  theme_minimal(base_size = 12) +
  theme(axis.text.x = element_text(angle=45, hjust=1),
        plot.title = element_text(hjust = 0.5))
Hình 9: Biểu đồ Mosaic giữa PaymentMethod và Churn

Hình 9: Biểu đồ Mosaic giữa PaymentMethod và Churn

3.3.4. Phân tích so sánh chi tiết

So sánh ‘Electronic check’ với ‘Credit card (automatic)’:

payment_sub_ec <- df_clean %>% 
  filter(PaymentMethod %in% c("Electronic check", "Credit card (automatic)")) %>%
  droplevels()
table_ec <- table(payment_sub_ec$PaymentMethod, payment_sub_ec$Churn)
prop_test_ec <- prop.test(x = table_ec[, "Yes"], n = rowSums(table_ec), correct=FALSE)
rr_ec <- riskratio(table_ec, method="wald")
or_ec <- oddsratio(table_ec, method="wald")

a. Hiệu tỷ lệ

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

  • \(H_0\): Tỷ lệ rời bỏ là như nhau.

  • \(H_1\): Tỷ lệ rời bỏ ở nhóm ‘Electronic check’ cao hơn.

print(prop_test_ec)
## 
##  2-sample test for equality of proportions without continuity correction
## 
## data:  table_ec[, "Yes"] out of rowSums(table_ec)
## X-squared = 374.6, df = 1, p-value < 2.2e-16
## alternative hypothesis: two.sided
## 95 percent confidence interval:
##  -0.3273217 -0.2733240
## sample estimates:
##    prop 1    prop 2 
## 0.1525312 0.4528541

Nhận xét: Tỷ lệ rời bỏ của nhóm Electronic check (45.3%) cao hơn đáng kể so với nhóm Credit card (automatic) (15.3%), với p-value < 2.2e-16.

b. Rủi ro Tương đối (RR)

print(rr_ec)
## $data
##                          
##                             No  Yes Total
##   Credit card (automatic) 1289  232  1521
##   Electronic check        1294 1071  2365
##   Total                   2583 1303  3886
## 
## $measure
##                          risk ratio with 95% C.I.
##                           estimate    lower    upper
##   Credit card (automatic) 1.000000       NA       NA
##   Electronic check        2.968927 2.616218 3.369188
## 
## $p.value
##                          two-sided
##                           midp.exact fisher.exact   chi.square
##   Credit card (automatic)         NA           NA           NA
##   Electronic check                 0 5.530755e-89 1.862097e-83
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: RR = 2.97. Nguy cơ rời bỏ của nhóm thanh toán bằng séc điện tử cao gấp 2.98 lần so với nhóm thanh toán bằng thẻ tín dụng tự động.

c. Tỷ số Chênh (OR)

print(or_ec)
## $data
##                          
##                             No  Yes Total
##   Credit card (automatic) 1289  232  1521
##   Electronic check        1294 1071  2365
##   Total                   2583 1303  3886
## 
## $measure
##                          odds ratio with 95% C.I.
##                           estimate    lower   upper
##   Credit card (automatic) 1.000000       NA      NA
##   Electronic check        4.598542 3.912607 5.40473
## 
## $p.value
##                          two-sided
##                           midp.exact fisher.exact   chi.square
##   Credit card (automatic)         NA           NA           NA
##   Electronic check                 0 5.530755e-89 1.862097e-83
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: OR = 4.6. Odds rời bỏ của nhóm Electronic check cao hơn gấp 4.06 lần so với nhóm Credit card (automatic).

3.3.5. Khoảng ước lượng tỷ lệ

Ước lượng tỷ lệ rời bỏ cho nhóm thanh toán bằng Séc điện tử (Electronic check)

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

  • \(H_0\): Tỷ lệ rời bỏ của nhóm dùng séc điện tử bằng tỷ lệ trung bình (27%), tức là \(p = 0.27\).

  • \(H_1\): Tỷ lệ rời bỏ của nhóm dùng séc điện tử khác 27% (\(p \neq 0.27\)).

count_ec <- churn_payment_table["Electronic check", "Yes"]
total_ec <- sum(churn_payment_table["Electronic check", ])
prop.test(x = count_ec, n = total_ec, p = 0.27, correct = FALSE)
## 
##  1-sample proportions test without continuity correction
## 
## data:  count_ec out of total_ec, null probability 0.27
## X-squared = 401.19, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.27
## 95 percent confidence interval:
##  0.4328852 0.4729759
## sample estimates:
##         p 
## 0.4528541

Nhận xét: Kết quả kiểm định có p-value < 2.2e-16, bác bỏ giả thuyết \(H_0\). Tỷ lệ rời bỏ thực tế trong mẫu của nhóm dùng séc điện tử là 45.3%, cao vượt trội so với mức trung bình. Khoảng ước lượng tỷ lệ rời bỏ thật sự của nhóm này, với độ tin cậy 95%, nằm trong khoảng từ 43.3% đến 47.3%.


3.4. Phân tích Churn và InternetService (Dịch vụ Internet)

3.4.1. Bảng tần số

churn_internet_table <- table(df_clean$InternetService, df_clean$Churn)
cat("Bảng tần số chéo:\n")
## Bảng tần số chéo:
addmargins(churn_internet_table)
##              
##                 No  Yes  Sum
##   DSL         1957  459 2416
##   Fiber optic 1799 1297 3096
##   No          1407  113 1520
##   Sum         5163 1869 7032

3.4.2. Kiểm định Chi-bình phương

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

  • \(H_0\): Dịch vụ Internet và việc rời bỏ là hai biến độc lập.

  • \(H_1\): Dịch vụ Internet và việc rời bỏ có liên quan đến nhau.

print(chisq.test(churn_internet_table))
## 
##  Pearson's Chi-squared test
## 
## data:  churn_internet_table
## X-squared = 728.7, df = 2, p-value < 2.2e-16

Nhận xét: p-value < 2.2e-16. Bác bỏ \(H_0\). Có mối liên hệ rất mạnh.

3.4.3. Trực quan hóa Mối quan hệ

ggplot(data = df_clean) +
  geom_mosaic(aes(x = product(InternetService, Churn), fill=Churn)) +
  labs(title="Mối quan hệ giữa Dịch vụ Internet và Tỷ lệ rời bỏ", x="Dịch vụ Internet", y="Tỷ lệ Churn") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(hjust = 0.5))
Hình 10: Biểu đồ Mosaic giữa InternetService và Churn

Hình 10: Biểu đồ Mosaic giữa InternetService và Churn

3.4.4. Phân tích so sánh chi tiết

So sánh ‘Fiber optic’ với ‘DSL’:

internet_sub_fo <- df_clean %>% 
  filter(InternetService %in% c("Fiber optic", "DSL")) %>%
  droplevels()
table_fo <- table(internet_sub_fo$InternetService, internet_sub_fo$Churn)
prop_test_fo <- prop.test(x = table_fo[, "Yes"], n = rowSums(table_fo), correct=FALSE)
rr_fo <- riskratio(table_fo, method="wald")
or_fo <- oddsratio(table_fo, method="wald")

a. Hiệu tỷ lệ

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

  • \(H_0\): Tỷ lệ rời bỏ ở nhóm ‘Fiber optic’ và ‘DSL’ là như nhau.

  • \(H_1\): Tỷ lệ rời bỏ ở nhóm ‘Fiber optic’ cao hơn.

print(prop_test_fo)
## 
##  2-sample test for equality of proportions without continuity correction
## 
## data:  table_fo[, "Yes"] out of rowSums(table_fo)
## X-squared = 327.65, df = 1, p-value < 2.2e-16
## alternative hypothesis: two.sided
## 95 percent confidence interval:
##  -0.2523264 -0.2055620
## sample estimates:
##    prop 1    prop 2 
## 0.1899834 0.4189276

Nhận xét: Tỷ lệ rời bỏ của khách hàng dùng Fiber optic (41.9%) cao hơn đáng kể so với DSL (19.0%). Với p-value < 2.2e-16, sự khác biệt là có ý nghĩa thống kê.

b. Rủi ro Tương đối (RR)

print(rr_fo)
## $data
##              
##                 No  Yes Total
##   DSL         1957  459  2416
##   Fiber optic 1799 1297  3096
##   Total       3756 1756  5512
## 
## $measure
##              risk ratio with 95% C.I.
##               estimate    lower    upper
##   DSL         1.000000       NA       NA
##   Fiber optic 2.205075 2.010865 2.418041
## 
## $p.value
##              two-sided
##               midp.exact fisher.exact   chi.square
##   DSL                 NA           NA           NA
##   Fiber optic          0 1.421292e-75 3.116148e-73
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: RR = 2.21. Nguy cơ rời bỏ của khách hàng dùng cáp quang cao hơn 2.21 lần so với khách hàng dùng DSL.

c. Tỷ số Chênh (OR)

print(or_fo)
## $data
##              
##                 No  Yes Total
##   DSL         1957  459  2416
##   Fiber optic 1799 1297  3096
##   Total       3756 1756  5512
## 
## $measure
##              odds ratio with 95% C.I.
##               estimate    lower    upper
##   DSL          1.00000       NA       NA
##   Fiber optic  3.07388 2.714821 3.480428
## 
## $p.value
##              two-sided
##               midp.exact fisher.exact   chi.square
##   DSL                 NA           NA           NA
##   Fiber optic          0 1.421292e-75 3.116148e-73
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét: OR = 3.07. Odds rời bỏ của khách hàng dùng cáp quang cao hơn 3.14 lần so với dùng DSL.

3.4.4. Khoảng ước lượng tỷ lệ

Ước lượng tỷ lệ rời bỏ cho nhóm dùng Cáp quang (Fiber optic)

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

  • \(H_0\): Tỷ lệ rời bỏ của nhóm dùng cáp quang bằng tỷ lệ trung bình (27%), tức là \(p = 0.27\).

  • \(H_1\): Tỷ lệ rời bỏ của nhóm dùng cáp quang khác 27% (\(p \neq 0.27\)).

count_fo <- churn_internet_table["Fiber optic", "Yes"]
total_fo <- sum(churn_internet_table["Fiber optic", ])
prop.test(x = count_fo, n = total_fo, p = 0.27, correct = FALSE)
## 
##  1-sample proportions test without continuity correction
## 
## data:  count_fo out of total_fo, null probability 0.27
## X-squared = 348.39, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.27
## 95 percent confidence interval:
##  0.4016593 0.4363969
## sample estimates:
##         p 
## 0.4189276

Nhận xét: Kết quả kiểm định có p-value < 2.2e-16, bác bỏ giả thuyết \(H_0\). Tỷ lệ rời bỏ thực tế trong mẫu của nhóm dùng cáp quang là 41.9%, cao hơn đáng kể so với mức trung bình. Khoảng ước lượng tỷ lệ rời bỏ thật sự của nhóm này, với độ tin cậy 95%, nằm trong khoảng từ 40.1% đến 43.7%.


3.5. Phân tích Churn và tenure (Thời gian gắn bó)

  • Vì biến Tenure là biến định lượng nên tác giả chỉ tiến hành thống kê mô tả và vẽ biểu đồ

3.5.1. Thống kê mô tả

tenure_summary <- df_clean %>%
  group_by(Churn) %>%
  summarise(
    mean_tenure = mean(tenure),
    median_tenure = median(tenure)
  )
kable(tenure_summary, caption="Thống kê 'tenure' theo 'Churn'")
Thống kê ‘tenure’ theo ‘Churn’
Churn mean_tenure median_tenure
No 37.65001 38
Yes 17.97913 10

3.5.2. Trực quan hóa Phân phối

Biểu đồ Mật độ (Density Plot)

ggplot(df_clean, aes(x = tenure, fill = Churn)) +
  geom_density(alpha = 0.7) +
  labs(
    title = "Phân phối Mật độ của Thời gian Gắn bó theo Tình trạng Rời bỏ",
    x = "Thời gian gắn bó (tháng)",
    y = "Mật độ"
  ) +
  theme_minimal(base_size = 14) +
  theme(plot.title = element_text(hjust = 0.5))
Hình 11: Phân phối mật độ của thời gian gắn bó (tenure) theo trạng thái rời bỏ

Hình 11: Phân phối mật độ của thời gian gắn bó (tenure) theo trạng thái rời bỏ

Nhận xét: Biểu đồ mật độ cho thấy một câu chuyện rất rõ ràng: - Đường cong Rời bỏ (Yes - màu đỏ): Có một đỉnh nhọn và rất cao ở những giá trị tenure thấp (chủ yếu dưới 20 tháng). Điều này có nghĩa là phần lớn khách hàng rời bỏ dịch vụ trong những tháng đầu tiên sử dụng. - Đường cong Không rời bỏ (No - màu xanh): Phân phối trải rộng hơn nhiều. Đáng chú ý, nó có hai đỉnh chính: một đỉnh ở gần đầu (những khách hàng mới nhưng vẫn trung thành) và một đỉnh rất cao ở cuối (những khách hàng đã gắn bó rất lâu, khoảng 72 tháng). - Kết luận: Nguy cơ khách hàng rời bỏ là cao nhất trong giai đoạn đầu. Càng ở lại lâu, khả năng họ tiếp tục sử dụng dịch vụ càng cao.

Biểu đồ Tần suất (Histogram) theo từng nhóm

ggplot(df_clean, aes(x = tenure, fill = Churn)) +
  geom_histogram(bins = 30, color = "white") +
  facet_wrap(~ Churn, ncol = 1, scales = "free_y") +
  labs(
    title = "Phân phối số lượng khách hàng theo thời gian gắn bó",
    x = "Thời gian gắn bó (tháng)",
    y = "Số lượng khách hàng"
  ) +
  theme_minimal(base_size = 14) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5))
Hình 12: Phân phối số lượng khách hàng theo thời gian gắn bó, tách biệt theo trạng thái rời bỏ

Hình 12: Phân phối số lượng khách hàng theo thời gian gắn bó, tách biệt theo trạng thái rời bỏ

Nhận xét: Biểu đồ này củng cố thêm những gì biểu đồ mật độ đã chỉ ra: - Panel Yes (Rời bỏ): Các cột cao nhất tập trung dày đặc ở phía bên trái (từ 1-10 tháng), sau đó giảm mạnh. Điều này cho thấy số lượng khách hàng rời bỏ giảm dần theo thời gian họ gắn bó. - Panel No (Không rời bỏ): Phân phối số lượng khách hàng ổn định hơn nhiều. Đặc biệt, cột cao nhất nằm ở cuối cùng (khoảng 72 tháng), cho thấy có một lượng lớn khách hàng rất trung thành đã sử dụng dịch vụ trong thời gian dài. - Kết luận: Việc mất khách hàng chủ yếu xảy ra trong giai đoạn “trăng mật”. Nếu một khách hàng vượt qua được mốc thời gian ban đầu, khả năng họ ở lại sẽ tăng lên đáng kể. -> Nhận xét: Khách hàng không rời bỏ có thời gian gắn bó trung bình (37.6 tháng) cao hơn đáng kể so với khách hàng đã rời bỏ (18 tháng). Thời gian gắn bó càng ngắn, nguy cơ khách hàng rời bỏ càng cao.

CHƯƠNG 4: MÔ HÌNH HỒI QUY ĐƠN BIẾN

Phần này sẽ phân tích tác động của từng biến độc lập (Contract, SeniorCitizen, PaymentMethod, InternetService, tenure) lên khả năng rời bỏ (Churn) của khách hàng một cách riêng lẻ. Chúng ta sẽ sử dụng 4 loại mô hình: Xác suất tuyến tính (LPM), Logit, Probit, và Cloglog.

4.1. Tác động của Contract (Loại hợp đồng) đến Churn

4.1.1. Mô hình Xác suất Tuyến tính (LPM)

lpm_contract <- glm(Churn_binary ~ Contract, data = df_clean, family = gaussian(link = "identity"))
summary(lpm_contract)
## 
## Call:
## glm(formula = Churn_binary ~ Contract, family = gaussian(link = "identity"), 
##     data = df_clean)
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       0.427097   0.006475   65.96   <2e-16 ***
## ContractOne year -0.314325   0.012341  -25.47   <2e-16 ***
## ContractTwo year -0.398610   0.011763  -33.89   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.1624794)
## 
##     Null deviance: 1372.2  on 7031  degrees of freedom
## Residual deviance: 1142.1  on 7029  degrees of freedom
## AIC: 7182.4
## 
## Number of Fisher Scoring iterations: 2

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \hat{\pi} = 0.4271 - 0.3144 \times \text{ContractOne year} - 0.3986 \times \text{ContractTwo year} \] - Kết quả từ mô hình hồi quy tuyến tính (GLM với hàm liên kết identity) cho thấy biến Contract (Loại hợp đồng) có ảnh hưởng rõ rệt đến xác suất rời bỏ dịch vụ (Churn_binary). Cụ thể, so với khách hàng sử dụng hợp đồng tháng một (mức tham chiếu), những khách hàng có hợp đồng một năm có xác suất rời bỏ trung bình giảm 31.4%, và với hợp đồng hai năm thì xác suất này giảm tới 39.9%. Các hệ số hồi quy đều âm và có ý nghĩa thống kê rất cao (p-value < 2e-16), cho thấy mối quan hệ âm mạnh mẽ giữa độ dài hợp đồng và khả năng rời bỏ. Nói cách khác, khách hàng cam kết lâu dài có xu hướng gắn bó hơn với dịch vụ, so với nhóm chỉ dùng theo tháng. Mức độ giải thích của mô hình ở mức tương đối, với chỉ số pseudo-R² khoảng 16.8%, phù hợp trong bối cảnh hành vi khách hàng thường bị chi phối bởi nhiều yếu tố khác nhau. Kết quả này gợi ý rằng doanh nghiệp nên cân nhắc các chính sách khuyến khích khách hàng chuyển sang hợp đồng dài hạn nhằm giảm thiểu tỷ lệ rời bỏ dịch vụ.

4.1.2. Mô hình Logit

logit_contract <- glm(Churn_binary ~ Contract, data = df_clean, family = binomial(link = "logit"))
summary(logit_contract)
## 
## Call:
## glm(formula = Churn_binary ~ Contract, family = binomial(link = "logit"), 
##     data = df_clean)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -0.29371    0.03248  -9.044   <2e-16 ***
## ContractOne year -1.76903    0.08857 -19.973   <2e-16 ***
## ContractTwo year -3.23571    0.15000 -21.572   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 6762.5  on 7029  degrees of freedom
## AIC: 6768.5
## 
## Number of Fisher Scoring iterations: 6

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \log\left(\frac{\hat{\pi}}{1 - \hat{\pi}}\right) = -0.2973 - 1.7690 \times \text{ContractOne year} - 3.2357 \times \text{ContractTwo year} \]

  • Mô hình hồi quy logistic phân tích mối quan hệ giữa loại hợp đồng (Contract) và khả năng rời bỏ dịch vụ (Churn_binary) cho thấy biến hợp đồng có ảnh hưởng rất rõ rệt và có ý nghĩa thống kê cao đến hành vi của khách hàng. Cụ thể, so với khách hàng sử dụng hợp đồng theo tháng (mức tham chiếu), khách hàng có hợp đồng một năm có log-odds rời bỏ thấp hơn 1.77 đơn vị, còn khách hàng có hợp đồng hai năm thì log-odds rời bỏ thấp hơn đến 3.24 đơn vị. Vì các hệ số hồi quy đều âm và có p-value < 2e-16, ta có thể khẳng định rằng cam kết hợp đồng dài hạn giúp giảm đáng kể khả năng rời bỏ dịch vụ.

  • Để dễ diễn giải, khi chuyển các hệ số hồi quy thành Odds Ratio (OR), ta được:

    • OR của hợp đồng một năm ≈ exp(−1.76903) ≈ 0.171, tức giảm 82.9% khả năng rời bỏ so với hợp đồng tháng một;

    • OR của hợp đồng hai năm ≈ exp(−3.23571) ≈ 0.039, tức giảm đến 96.1% khả năng rời bỏ.

  • Điều này nhấn mạnh tác động cực kỳ mạnh mẽ của loại hợp đồng đến hành vi khách hàng. Mô hình cũng có mức độ phù hợp tương đối tốt, với giảm deviance rõ rệt từ 8143.4 xuống còn 6762.5, và AIC = 6768.5, thấp hơn so với mô hình tuyến tính, cho thấy mô hình logistic là lựa chọn phù hợp hơn trong trường hợp biến phụ thuộc là nhị phân. Kết quả này gợi mở hướng tiếp cận chiến lược: doanh nghiệp nên đẩy mạnh các chính sách chuyển đổi khách hàng từ hợp đồng ngắn hạn sang dài hạn nhằm giảm đáng kể tỷ lệ rời bỏ dịch vụ.

4.1.3. Mô hình Probit

probit_contract <- glm(Churn_binary ~ Contract, data = df_clean, family = binomial(link = "probit"))
summary(probit_contract)
## 
## Call:
## glm(formula = Churn_binary ~ Contract, family = binomial(link = "probit"), 
##     data = df_clean)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -0.18377    0.02026  -9.072   <2e-16 ***
## ContractOne year -1.02815    0.04760 -21.601   <2e-16 ***
## ContractTwo year -1.71975    0.06537 -26.306   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 6762.5  on 7029  degrees of freedom
## AIC: 6768.5
## 
## Number of Fisher Scoring iterations: 5

Nhận xét:

Hàm Probit ước lượng như sau: \[ \Phi^{-1}(\hat{\pi}) = -0.1837 - 1.0282 \times \text{ContractOne year} - 1.7198 \times \text{ContractTwo year} \]

  • Mô hình hồi quy nhị phân với hàm liên kết probit cũng được sử dụng để kiểm định ảnh hưởng của loại hợp đồng (Contract) đến khả năng rời bỏ dịch vụ (Churn_binary). Kết quả cho thấy cả hai mức hợp đồng dài hạn đều có ảnh hưởng tiêu cực và có ý nghĩa thống kê rất cao đến xác suất rời bỏ. Cụ thể, so với khách hàng dùng hợp đồng theo tháng, khách hàng sử dụng hợp đồng một năm có giảm 1.03 đơn vị z-score trong xác suất rời bỏ, còn hợp đồng hai năm thì giảm tới 1.72 đơn vị z-score. Các hệ số này đều có p-value < 2e-16, cho thấy tác động của độ dài hợp đồng là cực kỳ rõ ràng và đáng tin cậy.

  • Về mặt bản chất, mô hình probit cũng cho cùng một kết luận như mô hình logistic: khách hàng có hợp đồng dài hạn ít có khả năng rời bỏ hơn so với hợp đồng ngắn hạn. Giá trị deviance và AIC giống như mô hình logistic (AIC = 6768.5), cho thấy hai mô hình có mức độ phù hợp tương đương. Tuy nhiên, mô hình probit diễn giải khó hơn một chút so với logistic, do hệ số hồi quy biểu thị thay đổi theo thang z-score của phân phối chuẩn thay vì log-odds.

  • Nhìn chung, mô hình probit củng cố thêm bằng chứng rằng việc kéo dài thời hạn hợp đồng là một chiến lược hiệu quả trong việc giảm nguy cơ mất khách hàng, và có thể được doanh nghiệp tận dụng thông qua các gói khuyến mãi, chính sách giữ chân, hoặc nâng cao giá trị hợp đồng dài hạn.

4.1.4. Mô hình Cloglog

cloglog_contract <- glm(Churn_binary ~ Contract, data = df_clean, family = binomial(link = "cloglog"))
summary(cloglog_contract)
## 
## Call:
## glm(formula = Churn_binary ~ Contract, family = binomial(link = "cloglog"), 
##     data = df_clean)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -0.58512    0.02490  -23.50   <2e-16 ***
## ContractOne year -1.53804    0.08156  -18.86   <2e-16 ***
## ContractTwo year -2.95878    0.14647  -20.20   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 6762.5  on 7029  degrees of freedom
## AIC: 6768.5
## 
## Number of Fisher Scoring iterations: 6

Nhận xét:

Dựa trên kết quả mô hình hồi quy với hàm liên kết cloglog, ta có phương trình: \[ \log(-\log(1 - \hat{\pi})) = -0.5851 - 1.5380 \times \text{ContractOne year} - 2.9588 \times \text{ContractTwo year} \]

  • Mô hình hồi quy nhị phân với hàm liên kết complementary log-log (cloglog) tiếp tục cho thấy biến Contract (Loại hợp đồng) có ảnh hưởng mạnh và có ý nghĩa thống kê cao đến xác suất rời bỏ dịch vụ (Churn_binary). Cụ thể, so với nhóm khách hàng sử dụng hợp đồng tháng một, khách hàng có hợp đồng một năm có giảm 1.54 đơn vị log(-log(1 - p)), trong khi khách hàng có hợp đồng hai năm thì giảm đến 2.96 đơn vị, với p-value đều < 2e-16. Các hệ số âm cho thấy mối quan hệ nghịch đảo: hợp đồng dài hạn làm giảm xác suất rời bỏ.

  • Hàm liên kết cloglog thường phù hợp trong các tình huống mà xác suất xảy ra sự kiện thấp nhưng rủi ro tích lũy theo thời gian, ví dụ như trong các mô hình sống sót hoặc dữ liệu time-to-event. Trong bối cảnh này, mặc dù xác suất rời bỏ không hẳn là cực thấp, mô hình cloglog vẫn đem lại kết quả phù hợp, với giá trị deviance và AIC (6768.5) ngang bằng với mô hình logistic và probit, cho thấy mức độ khớp mô hình tương đương.

  • Điểm khác biệt là hàm liên kết cloglog không đối xứng, phản ánh rõ hơn trong trường hợp hành vi rời bỏ dịch vụ có thể không xảy ra ngẫu nhiên mà tích lũy rủi ro theo thời gian sử dụng. Dù diễn giải hệ số hồi quy trong mô hình cloglog phức tạp hơn so với logistic, kết quả vẫn củng cố nhận định rằng kéo dài thời hạn hợp đồng có thể làm giảm mạnh rủi ro khách hàng rời bỏ – một chiến lược mà doanh nghiệp nên khai thác hiệu quả thông qua các gói cước và chương trình giữ chân khách hàng.

4.1.5. Đánh giá các mô hình

aic_contract <- data.frame(
  Model = c("LPM","Logit", "Probit", "Cloglog"),
  AIC = c(AIC(lpm_contract),AIC(logit_contract), AIC(probit_contract), AIC(cloglog_contract))
)
kable(aic_contract, caption = "So sánh AIC các mô hình cho biến Contract")
So sánh AIC các mô hình cho biến Contract
Model AIC
LPM 7182.370
Logit 6768.521
Probit 6768.521
Cloglog 6768.521

Nhận xét:

  • Khi so sánh các mô hình hồi quy với biến độc lập Contract, chỉ số Akaike Information Criterion (AIC) được sử dụng để đánh giá mức độ phù hợp của mô hình với dữ liệu. Kết quả cho thấy mô hình Linear Probability Model (LPM) có AIC = 7182.37, cao hơn đáng kể so với ba mô hình hồi quy nhị phân: Logit, Probit và Complementary Log-log (Cloglog) đều có AIC = 6768.52. Vì AIC càng thấp thì mô hình càng tốt (về mặt cân bằng giữa độ phù hợp và độ phức tạp), nên có thể kết luận rằng các mô hình nhị phân (logit, probit, cloglog) phù hợp hơn so với LPM trong việc mô hình hóa khả năng rời bỏ dịch vụ.

  • Ngoài ra, vì cả ba mô hình nhị phân đều cho kết quả AIC giống nhau, nên về mặt định lượng, không có sự khác biệt đáng kể giữa chúng trong bối cảnh biến giải thích duy nhất là Contract. Tuy nhiên, tuỳ vào mục tiêu nghiên cứu và đặc điểm phân phối dữ liệu, lựa chọn giữa logistic, probit hay cloglog có thể dựa trên cách diễn giải hệ số hồi quy hoặc giả định về xác suất xảy ra sự kiện. Dù vậy, điểm chung nổi bật là biến Contract luôn thể hiện tác động tiêu cực và có ý nghĩa thống kê mạnh mẽ lên xác suất rời bỏ, bất kể mô hình nào được sử dụng.


4.2. Tác động của SeniorCitizen

4.2.1. Mô hình Xác suất Tuyến tính (LPM)

lpm_senior <- glm(Churn_binary ~ SeniorCitizen, data = df_clean, family = gaussian(link = "identity"))
summary(lpm_senior)
## 
## Call:
## glm(formula = Churn_binary ~ SeniorCitizen, family = gaussian(link = "identity"), 
##     data = df_clean)
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      0.236503   0.005691   41.56   <2e-16 ***
## SeniorCitizenYes 0.180310   0.014122   12.77   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.1907751)
## 
##     Null deviance: 1372.2  on 7031  degrees of freedom
## Residual deviance: 1341.1  on 7030  degrees of freedom
## AIC: 8310.3
## 
## Number of Fisher Scoring iterations: 2

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \hat{\pi} = 0.2361 + 0.1803 \times \text{SeniorCitizenYes} \]

  • Mô hình hồi quy tuyến tính (LPM) phân tích ảnh hưởng của biến SeniorCitizen (Khách hàng là người cao tuổi) đến xác suất rời bỏ dịch vụ (Churn_binary) cho thấy mối quan hệ dương và có ý nghĩa thống kê cao. Cụ thể, hệ số hồi quy của nhóm khách hàng cao tuổi là 0.1803, với p-value < 2e-16, cho thấy rằng khách hàng là người cao tuổi có xác suất rời bỏ dịch vụ trung bình cao hơn 18.03 điểm phần trăm so với khách hàng không phải người cao tuổi, khi giữ các yếu tố khác không đổi. Trong khi đó, giá trị chặn (intercept) là 0.2365, thể hiện xác suất rời bỏ trung bình của nhóm không phải người cao tuổi là khoảng 23.65%.

  • Mặc dù hệ số này có ý nghĩa thống kê rõ rệt, song mô hình có mức độ giải thích thấp, thể hiện qua R² xấp xỉ 0.0227tức chỉ khoảng 2.3% phương sai trong biến Churn được giải thích bởi biến SeniorCitizen. AIC của mô hình cũng khá cao (8310.3), cho thấy đây không phải mô hình phù hợp mạnh nếu chỉ xét riêng biến SeniorCitizen.

  • Tóm lại, mô hình chỉ ra rằng người cao tuổi có xu hướng rời bỏ dịch vụ cao hơn đáng kể, nhưng yếu tố này chỉ giải thích được một phần rất nhỏ sự thay đổi trong hành vi rời bỏ. Điều này cho thấy cần bổ sung thêm các biến quan trọng khác để xây dựng mô hình dự đoán chính xác hơn.

4.2.2. Mô hình Logit

logit_senior <- glm(Churn_binary ~ SeniorCitizen, data = df_clean, family = binomial(link = "logit"))
summary(logit_senior)
## 
## Call:
## glm(formula = Churn_binary ~ SeniorCitizen, family = binomial(link = "logit"), 
##     data = df_clean)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -1.17195    0.03066  -38.22   <2e-16 ***
## SeniorCitizenYes  0.83608    0.06740   12.40   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7995.2  on 7030  degrees of freedom
## AIC: 7999.2
## 
## Number of Fisher Scoring iterations: 4

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \log\left(\frac{\hat{\pi}}{1 - \hat{\pi}}\right) = -1.1719 + 0.8306 \times \text{SeniorCitizenYes} \]

  • Mô hình hồi quy logistic được sử dụng để đánh giá ảnh hưởng của việc khách hàng là người cao tuổi (SeniorCitizen) đến khả năng rời bỏ dịch vụ (Churn_binary). Kết quả cho thấy hệ số hồi quy cho nhóm khách hàng cao tuổi là 0.8361, với p-value < 2e-16, cho thấy mối quan hệ dương và có ý nghĩa thống kê rất cao giữa việc là người cao tuổi và xác suất rời bỏ dịch vụ.

  • Hệ số hồi quy dương có nghĩa là người cao tuổi có khả năng rời bỏ cao hơn so với người không cao tuổi. Khi chuyển sang Odds Ratio để dễ diễn giải, ta có:

\[ \text{OR} = \exp(0.8361) \approx 2.31 \]

Tức là, khách hàng cao tuổi có odds rời bỏ dịch vụ cao hơn khoảng 2.31 lần so với khách hàng không cao tuổi.

Tuy nhiên, xét về mức độ giải thích, mô hình có mức giảm deviance không lớn – từ 8143.4 (null deviance) xuống 7995.2 – tương đương với pseudo-R² khoảng:

\[ R^2 \approx 1 - \frac{7995.2}{8143.4} \approx 0.0182 \]

Tức chỉ khoảng 1.8% phương sai trong xác suất rời bỏ được giải thích bởi biến SeniorCitizen. Đồng thời, AIC = 7999.2, cao hơn nhiều so với các mô hình có thêm biến Contract.

Tóm lại, mô hình chỉ ra rằng người cao tuổi có xác suất rời bỏ cao hơn đáng kể, nhưng biến SeniorCitizen đơn lẻ chỉ đóng vai trò nhỏ trong việc dự đoán hành vi rời bỏ. Kết quả này gợi ý rằng yếu tố tuổi tác tuy có ảnh hưởng, nhưng cần kết hợp với các biến khác để mô hình đạt được độ chính xác cao hơn.

4.2.3. Mô hình Probit

probit_senior <- glm(Churn_binary ~ SeniorCitizen, data = df_clean, family = binomial(link = "probit"))
summary(probit_senior)
## 
## Call:
## glm(formula = Churn_binary ~ SeniorCitizen, family = binomial(link = "probit"), 
##     data = df_clean)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -0.71760    0.01795  -39.97   <2e-16 ***
## SeniorCitizenYes  0.50754    0.04147   12.24   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7995.2  on 7030  degrees of freedom
## AIC: 7999.2
## 
## Number of Fisher Scoring iterations: 4

Nhận xét:

Hàm Probit ước lượng như sau: \[ \Phi^{-1}(\hat{\pi}) = -0.7188 + 0.4907 \times \text{SeniorCitizenYes} \] - Mô hình hồi quy nhị phân sử dụng hàm liên kết probit tiếp tục kiểm định ảnh hưởng của biến SeniorCitizen (khách hàng là người cao tuổi) đến xác suất rời bỏ dịch vụ (Churn_binary). Kết quả cho thấy hệ số hồi quy của nhóm khách hàng cao tuổi là 0.5075, với p-value < 2e-16, chứng tỏ đây là một biến giải thích có ảnh hưởng dương và có ý nghĩa thống kê rất cao.

  • Trong mô hình probit, hệ số hồi quy không thể trực tiếp chuyển thành Odds Ratio như trong logistic, vì nó biểu diễn thay đổi trên thang z-score của phân phối chuẩn chuẩn hóa. Tuy nhiên, dấu và độ lớn của hệ số vẫn cho phép diễn giải rằng: việc khách hàng là người cao tuổi làm tăng xác suất rời bỏ dịch vụ, và mức ảnh hưởng này là đáng kể.

  • Tương tự như mô hình logistic, mô hình probit này có giá trị deviance giảm nhẹ từ 8143.4 xuống 7995.2, tương ứng với pseudo-R² ≈ 1.82%:

\[ R^2 \approx 1 - \frac{7995.2}{8143.4} \approx 0.0182 \]

  • Điều này cho thấy mô hình có mức độ giải thích rất thấp, vì biến SeniorCitizen đơn lẻ chỉ giải thích được một phần nhỏ sự biến thiên trong hành vi rời bỏ dịch vụ. AIC của mô hình là 7999.2, bằng với mô hình logistic sử dụng cùng biến.

  • Tóm lại, kết quả từ mô hình probit củng cố thêm bằng chứng rằng khách hàng cao tuổi có xu hướng rời bỏ cao hơn, tuy nhiên tác động này không đủ mạnh để giải thích phần lớn biến động trong churn, do đó cần kết hợp thêm các biến quan trọng khác để xây dựng mô hình có tính dự đoán cao hơn. ### 4.2.4. Mô hình Cloglog

cloglog_senior <- glm(Churn_binary ~ SeniorCitizen, data = df_clean, family = binomial(link = "cloglog"))
summary(cloglog_senior)
## 
## Call:
## glm(formula = Churn_binary ~ SeniorCitizen, family = binomial(link = "cloglog"), 
##     data = df_clean)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -1.30991    0.02687  -48.74   <2e-16 ***
## SeniorCitizenYes  0.69232    0.05361   12.91   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7995.2  on 7030  degrees of freedom
## AIC: 7999.2
## 
## Number of Fisher Scoring iterations: 5

Nhận xét:

Phương trình hồi quy Cloglog: \[ \log(-\log(1 - \hat{\pi})) = -1.3499 + 0.6729 \times \text{SeniorCitizenYes} \]

  • Mô hình hồi quy nhị phân sử dụng hàm liên kết complementary log-log (cloglog) tiếp tục kiểm định ảnh hưởng của biến SeniorCitizen (khách hàng là người cao tuổi) đến khả năng rời bỏ dịch vụ (Churn_binary). Kết quả cho thấy hệ số hồi quy cho nhóm khách hàng cao tuổi là 0.6923, với p-value < 2e-16, cho thấy ảnh hưởng này là dương và có ý nghĩa thống kê rất cao.

  • Trong mô hình cloglog, hệ số hồi quy biểu diễn sự thay đổi trên thang log(-log(1 - p)), thường dùng trong các tình huống rủi ro tích lũy hoặc xác suất xảy ra không đối xứng. Mặc dù khó diễn giải trực tiếp như log-odds trong logistic, dấu của hệ số vẫn cho thấy rõ ràng rằng khách hàng cao tuổi có xác suất rời bỏ cao hơn so với nhóm không cao tuổi.

  • Tương tự như các mô hình nhị phân khác (logit, probit), mô hình cloglog này có:

  • Residual deviance giảm nhẹ từ 8143.4 xuống 7995.2;

  • AIC = 7999.2, bằng với các mô hình logit và probit;

  • Pseudo-R² ước lượng:

\[ R^2 \approx 1 - \frac{7995.2}{8143.4} \approx 0.0182 \]

Điều này cho thấy biến SeniorCitizen chỉ giải thích được khoảng 1.8% phương sai của biến phụ thuộc, tức ảnh hưởng là có thật nhưng mức độ đóng góp vào tổng thể mô hình là hạn chế.

Tóm lại, mô hình cloglog xác nhận lại rằng người cao tuổi có xu hướng rời bỏ dịch vụ cao hơn, nhưng tương tự như các mô hình khác, yếu tố này không đủ mạnh để dự báo churn một cách độc lập, và cần kết hợp với các yếu tố khác như loại hợp đồng, phương thức thanh toán, hoặc thời gian sử dụng.

4.2.5. Đánh giá các mô hình

aic_senior <- data.frame(
  Model = c("LPM","Logit", "Probit", "Cloglog"),
  AIC = c(AIC(lpm_senior),AIC(logit_senior), AIC(probit_senior), AIC(cloglog_senior))
)
kable(aic_senior, caption = "So sánh AIC các mô hình cho biến SeniorCitizen")
So sánh AIC các mô hình cho biến SeniorCitizen
Model AIC
LPM 8310.319
Logit 7999.224
Probit 7999.224
Cloglog 7999.224

Nhận xét:

Để đánh giá mức độ phù hợp của các mô hình hồi quy đối với biến độc lập SeniorCitizen, tiêu chí AIC (Akaike Information Criterion) được sử dụng nhằm so sánh giữa các mô hình: hồi quy tuyến tính (LPM), logit, probit và cloglog. Kết quả cho thấy mô hình LPM có AIC cao nhất (8310.319), cho thấy mức độ phù hợp thấp hơn so với ba mô hình nhị phân còn lại. Trong khi đó, cả ba mô hình logit, probit và cloglog đều cho cùng một giá trị AIC là 7999.224, cho thấy mức độ phù hợp tương đương nhau trong việc dự đoán khả năng rời bỏ dịch vụ dựa trên tình trạng khách hàng là người cao tuổi hay không. Sự đồng nhất về AIC ở ba mô hình phi tuyến này có thể xuất phát từ bản chất đơn giản của mô hình, với chỉ một biến nhị phân là biến giải thích. Nhìn chung, các mô hình nhị phân đều vượt trội hơn so với LPM trong việc dự đoán churn, và có thể được cân nhắc lựa chọn tùy theo mục tiêu nghiên cứu—chẳng hạn, mô hình logit thường được ưu tiên nhờ khả năng diễn giải trực tiếp qua Odds Ratio.

4.3. Tác động của PaymentMethod

4.3.1. Mô hình Xác suất Tuyến tính (LPM)

lpm_payment <- glm(Churn_binary ~ PaymentMethod, data = df_clean, family = gaussian(link = "identity"))
summary(lpm_payment)
## 
## Call:
## glm(formula = Churn_binary ~ PaymentMethod, family = gaussian(link = "identity"), 
##     data = df_clean)
## 
## Coefficients:
##                                      Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                           0.16732    0.01072  15.602   <2e-16 ***
## PaymentMethodCredit card (automatic) -0.01478    0.01522  -0.971    0.331    
## PaymentMethodElectronic check         0.28554    0.01378  20.716   <2e-16 ***
## PaymentMethodMailed check             0.02470    0.01502   1.645    0.100    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.177333)
## 
##     Null deviance: 1372.2  on 7031  degrees of freedom
## Residual deviance: 1246.3  on 7028  degrees of freedom
## AIC: 7798.5
## 
## Number of Fisher Scoring iterations: 2

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \hat{\pi} = 0.1673 - 0.0142 \times \text{Credit card} + 0.2855 \times \text{Electronic check} + 0.0247 \times \text{Mailed check} \] - Mô hình hồi quy tuyến tính (LPM) cho thấy phương thức thanh toán có ảnh hưởng đáng kể đến xác suất rời bỏ dịch vụ. Cụ thể, so với nhóm tham chiếu là khách hàng sử dụng phương thức Bank transfer (automatic), những người sử dụng Electronic check có xác suất rời bỏ cao hơn trung bình 28.55 điểm phần trăm, và sự khác biệt này có ý nghĩa thống kê rất cao (p < 2e-16). Trong khi đó, khách hàng thanh toán bằng Credit card (automatic) và Mailed check không cho thấy sự khác biệt có ý nghĩa thống kê với nhóm tham chiếu (p = 0.331 và p = 0.100 tương ứng). Điều này cho thấy Electronic check là một yếu tố rủi ro đáng lưu ý liên quan đến hành vi rời bỏ, có thể phản ánh một đặc điểm hành vi hoặc mức độ cam kết thấp của nhóm khách hàng này. Tuy nhiên, với giá trị AIC là 7798.5, mô hình tuyến tính vẫn có thể bị hạn chế trong việc mô hình hóa xác suất, do bản chất nhị phân của biến phụ thuộc.

4.3.2. Mô hình Logit

logit_payment <- glm(Churn_binary ~ PaymentMethod, data = df_clean, family = binomial(link = "logit"))
summary(logit_payment)
## 
## Call:
## glm(formula = Churn_binary ~ PaymentMethod, family = binomial(link = "logit"), 
##     data = df_clean)
## 
## Coefficients:
##                                      Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                          -1.60478    0.06823 -23.521   <2e-16 ***
## PaymentMethodCredit card (automatic) -0.11011    0.09870  -1.116   0.2646    
## PaymentMethodElectronic check         1.41563    0.07976  17.749   <2e-16 ***
## PaymentMethodMailed check             0.16784    0.09313   1.802   0.0715 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7518.6  on 7028  degrees of freedom
## AIC: 7526.6
## 
## Number of Fisher Scoring iterations: 4

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \log\left(\frac{\hat{\pi}}{1 - \hat{\pi}}\right) = -1.6063 - 0.1299 \times \text{Credit card} + 1.4011 \times \text{Electronic check} + 0.1378 \times \text{Mailed check} \]

  • Mô hình hồi quy logistic cho thấy phương thức thanh toán là một yếu tố quan trọng ảnh hưởng đến xác suất rời bỏ dịch vụ. So với nhóm tham chiếu là Bank transfer (automatic), khách hàng sử dụng Electronic check có xu hướng rời bỏ cao hơn đáng kể, với hệ số log-odds là 1.416 (p < 2e-16), tương đương với tăng khoảng 4.12 lần (exp(1.416)) khả năng rời bỏ. Trong khi đó, khách hàng thanh toán bằng Credit card (automatic) không có sự khác biệt có ý nghĩa thống kê về khả năng rời bỏ so với nhóm tham chiếu (p = 0.2646). Đối với nhóm Mailed check, kết quả tiệm cận ý nghĩa thống kê (p = 0.0715), gợi ý rằng có thể tồn tại sự khác biệt nhẹ về xác suất rời bỏ, nhưng cần thêm bằng chứng. Giá trị AIC của mô hình là 7526.6, cho thấy mức độ phù hợp tốt hơn so với mô hình tuyến tính (AIC = 7798.5), đồng thời xác nhận mô hình logistic phù hợp hơn cho dữ liệu nhị phân như churn.

Kết luận: Thanh toán bằng Electronic check là yếu tố rủi ro mạnh nhất, làm tăng đáng kể khả năng rời bỏ của khách hàng. Các phương thức thanh toán tự động (Bank transfer, Credit card) có tỷ lệ rời bỏ thấp và ổn định hơn.

4.3.3. Mô hình Probit

probit_payment <- glm(Churn_binary ~ PaymentMethod, data = df_clean, family = binomial(link = "probit"))
summary(probit_payment)
## 
## Call:
## glm(formula = Churn_binary ~ PaymentMethod, family = binomial(link = "probit"), 
##     data = df_clean)
## 
## Coefficients:
##                                      Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                          -0.96483    0.03795 -25.425   <2e-16 ***
## PaymentMethodCredit card (automatic) -0.06081    0.05449  -1.116   0.2644    
## PaymentMethodElectronic check         0.84638    0.04591  18.436   <2e-16 ***
## PaymentMethodMailed check             0.09435    0.05231   1.804   0.0713 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7518.6  on 7028  degrees of freedom
## AIC: 7526.6
## 
## Number of Fisher Scoring iterations: 4

Nhận xét:

Hàm Probit ước lượng như sau: \[ \Phi^{-1}(\hat{\pi}) = -0.9649 - 0.0608 \times \text{Credit card} + 0.84638 \times \text{Electronic check} + 0.09435 \times \text{Mailed check} \] - Mô hình hồi quy probit cho thấy phương thức thanh toán có ảnh hưởng đáng kể đến xác suất rời bỏ dịch vụ. So với nhóm tham chiếu là Bank transfer (automatic), khách hàng thanh toán bằng Electronic check có xác suất rời bỏ cao hơn rõ rệt, với hệ số ước lượng là 0.846 (p < 2e-16), cho thấy tác động mạnh mẽ và có ý nghĩa thống kê. Trong khi đó, nhóm Credit card (automatic) không khác biệt đáng kể so với nhóm tham chiếu (p = 0.2644). Nhóm Mailed check có p-value = 0.0713, gần đạt ngưỡng ý nghĩa thống kê 5%, cho thấy khả năng tồn tại một tác động yếu đến xác suất rời bỏ. AIC của mô hình là 7526.6, trùng khớp với mô hình logit, cho thấy mức độ phù hợp tương đương giữa hai mô hình. Tuy nhiên, cả hai đều thể hiện tốt hơn mô hình tuyến tính (AIC = 7798.5), xác nhận rằng các mô hình nhị phân (logit và probit) phù hợp hơn khi dự đoán churn.

Kết luận: Kết quả từ mô hình Probit củng cố rằng Electronic check là phương thức thanh toán có rủi ro cao nhất, với hệ số có ý nghĩa thống kê.

4.3.4. Mô hình Cloglog

cloglog_payment <- glm(Churn_binary ~ PaymentMethod, data = df_clean, family = binomial(link = "cloglog"))
summary(cloglog_payment)
## 
## Call:
## glm(formula = Churn_binary ~ PaymentMethod, family = binomial(link = "cloglog"), 
##     data = df_clean)
## 
## Coefficients:
##                                      Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                          -1.69772    0.06234 -27.231   <2e-16 ***
## PaymentMethodCredit card (automatic) -0.10105    0.09059  -1.115   0.2646    
## PaymentMethodElectronic check         1.19195    0.06964  17.117   <2e-16 ***
## PaymentMethodMailed check             0.15228    0.08453   1.801   0.0716 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7518.6  on 7028  degrees of freedom
## AIC: 7526.6
## 
## Number of Fisher Scoring iterations: 5

Nhận xét:

Phương trình hồi quy Cloglog: \[ \log(-\log(1 - \hat{\pi})) = -1.69772 - 0.1000 \times \text{Credit card} + 1.19195 \times \text{Electronic check} + 0.15228 \times \text{Mailed check} \]

  • Mô hình hồi quy cloglog tiếp tục củng cố kết luận rằng phương thức thanh toán có ảnh hưởng rõ rệt đến khả năng rời bỏ dịch vụ. Cụ thể, khách hàng sử dụng Electronic check có xác suất rời bỏ cao hơn đáng kể so với nhóm tham chiếu Bank transfer (automatic), với hệ số ước lượng là 1.192 (p < 2e-16), cho thấy tác động rất mạnh và có ý nghĩa thống kê cao. Trong khi đó, phương thức Credit card (automatic) không cho thấy sự khác biệt có ý nghĩa (p = 0.2646). Nhóm Mailed check có hệ số dương nhẹ (0.152), p-value = 0.0716, nằm gần ngưỡng 0.05, cho thấy có thể có tác động yếu. Giá trị AIC của mô hình là 7526.6, ngang bằng với các mô hình logit và probit, và thấp hơn đáng kể so với mô hình tuyến tính (AIC = 7798.5), cho thấy các mô hình nhị phân đều phù hợp hơn khi phân tích xác suất khách hàng rời bỏ dịch vụ dựa trên phương thức thanh toán.

4.3.5. Đánh giá các mô hình

aic_payment <- data.frame(
  Model = c("Lpm","Logit", "Probit", "Cloglog"),
  AIC = c(AIC(lpm_payment),AIC(logit_payment), AIC(probit_payment), AIC(cloglog_payment))
)
kable(aic_payment, caption = "So sánh AIC các mô hình cho biến PaymentMethod")
So sánh AIC các mô hình cho biến PaymentMethod
Model AIC
Lpm 7798.519
Logit 7526.591
Probit 7526.591
Cloglog 7526.591
  • Khi so sánh giữa các mô hình hồi quy sử dụng biến độc lập là PaymentMethod, ta thấy rằng các mô hình nhị phân (logit, probit, cloglog) đều có cùng giá trị AIC là 7526.591, thấp hơn rõ rệt so với mô hình tuyến tính (LPM) có AIC là 7798.519. Điều này cho thấy rằng mô hình hóa xác suất rời bỏ dịch vụ bằng các hàm liên kết phi tuyến (như logit, probit, cloglog) là phù hợp và hiệu quả hơn so với mô hình hồi quy tuyến tính. Tuy các mô hình nhị phân có AIC tương đương nhau và không có mô hình nào vượt trội rõ rệt về mặt thông tin, nhưng chúng đều thể hiện mức độ phù hợp tốt hơn so với LPM trong việc giải thích ảnh hưởng của phương thức thanh toán đến khả năng rời bỏ dịch vụ của khách hàng.

4.4. Tác động của InternetService

4.4.1. Mô hình Xác suất Tuyến tính (LPM)

lpm_internet <- glm(Churn_binary ~ InternetService, data = df_clean, family = gaussian(link = "identity"))
summary(lpm_internet)
## 
## Call:
## glm(formula = Churn_binary ~ InternetService, family = gaussian(link = "identity"), 
##     data = df_clean)
## 
## Coefficients:
##                             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                 0.189983   0.008511  22.323   <2e-16 ***
## InternetServiceFiber optic  0.228944   0.011356  20.161   <2e-16 ***
## InternetServiceNo          -0.115641   0.013695  -8.444   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.1749961)
## 
##     Null deviance: 1372.2  on 7031  degrees of freedom
## Residual deviance: 1230.0  on 7029  degrees of freedom
## AIC: 7704.2
## 
## Number of Fisher Scoring iterations: 2

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \hat{\pi} = 0.189983 + 0.228944 \times \text{Fiber optic} -0.115641 \times \text{No} \] - Kết quả từ mô hình hồi quy tuyến tính (LPM) cho thấy biến InternetService có ảnh hưởng đáng kể đến xác suất rời bỏ dịch vụ (Churn_binary). Cụ thể, so với nhóm khách hàng sử dụng DSL (nhóm tham chiếu), những người sử dụng Internet cáp quang (Fiber optic) có xác suất rời bỏ cao hơn trung bình 22.89%, với hệ số ước lượng dương (0.2289) và có ý nghĩa thống kê rất cao (p < 2e-16). Ngược lại, nhóm không sử dụng dịch vụ Internet có khả năng rời bỏ thấp hơn 11.56% so với nhóm DSL, với hệ số âm (-0.1156) và cũng có ý nghĩa thống kê mạnh. Điều này cho thấy dịch vụ Internet đang là một yếu tố quan trọng trong hành vi rời bỏ của khách hàng – trong đó, người dùng cáp quang có xu hướng rời bỏ cao hơn đáng kể, có thể do chi phí cao, chất lượng dịch vụ hoặc kỳ vọng không được đáp ứng. Mô hình có giá trị AIC là 7704.2, thấp hơn các mô hình LPM trước đó với các biến khác, cho thấy mức độ phù hợp tương đối tốt.

4.4.2. Mô hình Logit

logit_internet <- glm(Churn_binary ~ InternetService, data = df_clean, family = binomial(link = "logit"))
summary(logit_internet)
## 
## Call:
## glm(formula = Churn_binary ~ InternetService, family = binomial(link = "logit"), 
##     data = df_clean)
## 
## Coefficients:
##                            Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                -1.45012    0.05186 -27.961   <2e-16 ***
## InternetServiceFiber optic  1.12294    0.06338  17.719   <2e-16 ***
## InternetServiceNo          -1.07171    0.11068  -9.683   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7364.3  on 7029  degrees of freedom
## AIC: 7370.3
## 
## Number of Fisher Scoring iterations: 5

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \log\left(\frac{\hat{\pi}}{1 - \hat{\pi}}\right) = -1.45012 + 1.12294 \times \text{Fiber optic} -1.07171 \times \text{No} \]

  • Kết quả từ mô hình hồi quy logistic cho thấy InternetService có ảnh hưởng rõ rệt và có ý nghĩa thống kê mạnh đến khả năng rời bỏ dịch vụ (Churn_binary). So với nhóm khách hàng sử dụng DSL (nhóm tham chiếu), những người sử dụng Internet cáp quang (Fiber optic) có xác suất rời bỏ cao hơn, với hệ số log-odds là 1.1229 (p < 2e-16), tương ứng với Odds Ratio ≈ 3.08 – nghĩa là khả năng rời bỏ cao gấp khoảng 3 lần so với nhóm dùng DSL. Ngược lại, khách hàng không sử dụng dịch vụ Internet có hệ số âm -1.0717 (p < 2e-16), tương ứng với Odds Ratio ≈ 0.34, cho thấy khả năng rời bỏ thấp hơn đáng kể so với nhóm DSL. Kết quả này phản ánh rằng người dùng Internet cáp quang có xu hướng rời bỏ cao hơn đáng kể, có thể do chi phí, sự phức tạp trong dịch vụ, hoặc kỳ vọng cao hơn không được đáp ứng. Ngược lại, những khách hàng không sử dụng Internet ít có khả năng rời bỏ hơn – có thể vì họ ít tương tác với dịch vụ hoặc không chịu ảnh hưởng từ yếu tố kỹ thuật. Giá trị AIC của mô hình là 7370.3, thấp hơn các mô hình với biến khác, cho thấy mô hình này có độ phù hợp tốt hơn.

4.4.3. Mô hình Probit

probit_internet <- glm(Churn_binary ~ InternetService, data = df_clean, family = binomial(link = "probit"))
summary(probit_internet)
## 
## Call:
## glm(formula = Churn_binary ~ InternetService, family = binomial(link = "probit"), 
##     data = df_clean)
## 
## Coefficients:
##                            Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                -0.87796    0.02941  -29.85   <2e-16 ***
## InternetServiceFiber optic  0.67332    0.03715   18.12   <2e-16 ***
## InternetServiceNo          -0.56624    0.05616  -10.08   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7364.3  on 7029  degrees of freedom
## AIC: 7370.3
## 
## Number of Fisher Scoring iterations: 4

Nhận xét:

Hàm Probit ước lượng như sau: \[ \Phi^{-1}(\hat{\pi}) = -0.87796 + 0.67332 \times \text{Fiber optic} -0.56624 \times \text{No} \] - Kết quả từ mô hình hồi quy probit với biến InternetService tiếp tục khẳng định ảnh hưởng có ý nghĩa thống kê của loại hình dịch vụ Internet đến khả năng rời bỏ (Churn_binary). Với nhóm tham chiếu là khách hàng sử dụng DSL, nhóm dùng Fiber optic có hệ số ước lượng là 0.6733 (p < 2e-16), cho thấy họ có xác suất rời bỏ cao hơn đáng kể so với nhóm DSL. Ngược lại, nhóm không sử dụng Internet có hệ số -0.5662 (p < 2e-16), thể hiện xác suất rời bỏ thấp hơn so với nhóm DSL. Mặc dù hệ số trong mô hình probit không thể diễn giải trực tiếp như odds ratio trong logit, nhưng dấu và độ lớn của các hệ số vẫn cho thấy xu hướng tương tự: khách hàng dùng Fiber optic có khả năng rời bỏ cao nhất, kế đến là nhóm DSL, và thấp nhất là nhóm không sử dụng Internet. Giá trị AIC là 7370.3, bằng với mô hình logit, cho thấy mức độ phù hợp giữa hai mô hình là tương đương. Điều này củng cố độ tin cậy của kết luận rằng loại hình Internet là một yếu tố quan trọng ảnh hưởng đến hành vi rời bỏ dịch vụ.

4.4.4. Mô hình Cloglog

cloglog_internet <- glm(Churn_binary ~ InternetService, data = df_clean, family = binomial(link = "cloglog"))
summary(cloglog_internet)
## 
## Call:
## glm(formula = Churn_binary ~ InternetService, family = binomial(link = "cloglog"), 
##     data = df_clean)
## 
## Coefficients:
##                            Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                -1.55732    0.04676  -33.30   <2e-16 ***
## InternetServiceFiber optic  0.94645    0.05456   17.35   <2e-16 ***
## InternetServiceNo          -1.00338    0.10507   -9.55   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7364.3  on 7029  degrees of freedom
## AIC: 7370.3
## 
## Number of Fisher Scoring iterations: 5

Nhận xét:

Phương trình hồi quy Cloglog: \[ \log(-\log(1 - \hat{\pi})) = -1.55732 + 0.94645 \times \text{Fiber optic} -1.00338 \times \text{No} \]

  • Mô hình hồi quy cloglog với biến độc lập InternetService cho thấy sự khác biệt có ý nghĩa thống kê rõ rệt giữa các loại hình dịch vụ Internet đối với xác suất rời bỏ dịch vụ. Với nhóm tham chiếu là DSL, khách hàng sử dụng Fiber optic có hệ số ước lượng là 0.9465 (p < 2e-16), cho thấy họ có nguy cơ rời bỏ cao hơn đáng kể. Ngược lại, nhóm không sử dụng Internet có hệ số -1.0034 (p < 2e-16), thể hiện khả năng rời bỏ thấp hơn so với nhóm DSL. Hướng và mức độ ảnh hưởng của các biến trong mô hình cloglog tương tự như trong các mô hình logit và probit, cho thấy tính nhất quán trong mối quan hệ giữa loại hình Internet và hành vi rời bỏ.

Giá trị AIC là 7370.3, giống hệt với logit và probit, cho thấy mức độ phù hợp của ba mô hình là tương đương nhau. Tuy nhiên, cloglog đặc biệt phù hợp hơn trong các trường hợp mà xác suất xảy ra sự kiện (ở đây là churn) rất thấp hoặc rất cao — điều có thể xem xét nếu phân phối churn bị lệch mạnh. Dù vậy, trong trường hợp này, cả ba mô hình nhị phân đều cung cấp kết quả nhất quán, và đều chỉ ra rằng Fiber optic là yếu tố làm tăng mạnh khả năng khách hàng rời bỏ dịch vụ.

4.4.5. Đánh giá các mô hình

aic_internet <- data.frame(
  Model = c("LPM","Logit", "Probit", "Cloglog"),
  AIC = c(AIC(lpm_internet),AIC(logit_internet), AIC(probit_internet), AIC(cloglog_internet))
)
kable(aic_internet, caption = "So sánh AIC các mô hình cho biến InternetService")
So sánh AIC các mô hình cho biến InternetService
Model AIC
LPM 7704.235
Logit 7370.298
Probit 7370.298
Cloglog 7370.298
  • Dựa trên chỉ số Akaike Information Criterion (AIC) – một tiêu chí dùng để so sánh mức độ phù hợp của các mô hình thống kê với cùng một bộ dữ liệu – ta thấy rõ:

  • Ba mô hình nhị phân (logit, probit, cloglog) đều cho cùng một giá trị AIC là 7370.298, thấp hơn đáng kể so với mô hình LPM (7704.235). Điều này cho thấy rằng các mô hình nhị phân phù hợp dữ liệu tốt hơn so với hồi quy tuyến tính khi dự đoán khả năng khách hàng rời bỏ theo loại hình Internet.

  • Mặc dù logit, probit và cloglog có logic diễn giải khác nhau về xác suất (logit dùng phân phối logistic, probit dùng phân phối chuẩn, cloglog dùng hàm complementary log-log), nhưng ở đây chúng tương đương về mặt độ phù hợp mô hình.

Do đó, có thể ưu tiên sử dụng một trong ba mô hình nhị phân (thường là logit vì dễ giải thích và phổ biến nhất), và loại bỏ mô hình LPM khỏi phân tích chính do độ phù hợp kém hơn đáng kể.

4.5. Tác động của tenure

4.5.1. Mô hình Xác suất Tuyến tính (LPM)

lpm_tenure <- glm(Churn_binary ~ tenure, data = df_clean, family = gaussian(link = "identity"))
summary(lpm_tenure)
## 
## Call:
## glm(formula = Churn_binary ~ tenure, family = gaussian(link = "identity"), 
##     data = df_clean)
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.4723900  0.0081637   57.86   <2e-16 ***
## tenure      -0.0063724  0.0002008  -31.74   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.1707305)
## 
##     Null deviance: 1372.2  on 7031  degrees of freedom
## Residual deviance: 1200.2  on 7030  degrees of freedom
## AIC: 7529.7
## 
## Number of Fisher Scoring iterations: 2

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \hat{Churn} = 0.4723900 -0.0063724 \times \text{tenure} \] - Ý nghĩa hệ số:

Hệ số Intercept = 0.4724 cho biết rằng khi tenure = 0 (khách hàng mới), xác suất rời bỏ ước tính là khoảng 47.2%.

Hệ số tenure = -0.00637 mang ý nghĩa: mỗi tháng gắn bó thêm với dịch vụ thì xác suất rời bỏ giảm khoảng 0.64 điểm phần trăm, tức giảm đều theo thời gian sử dụng. Đây là một xu hướng hợp lý trong lĩnh vực chăm sóc khách hàng.

  • Độ phù hợp mô hình:

    Giá trị AIC = 7529.7 tuy không cao vượt trội, nhưng thấp hơn so với các mô hình LPM trước đó, cho thấy mô hình tuyến tính này phù hợp dữ liệu ở mức tương đối.

    Tất cả hệ số đều có ý nghĩa thống kê với p < 2e-16, chứng tỏ biến tenure là một yếu tố quan trọng và có ý nghĩa trong việc giải thích hành vi rời bỏ của khách hàng.

    Tuy nhiên, do hồi quy tuyến tính không đảm bảo giá trị dự đoán nằm trong khoảng [0,1] và không phản ánh tốt bản chất nhị phân của biến mục tiêu, ta nên so sánh với các mô hình nhị phân như logit/probit/cloglog để chọn mô hình phù hợp hơn.

4.5.2. Mô hình Logit

logit_tenure <- glm(Churn_binary ~ tenure, data = df_clean, family = binomial(link = "logit"))
summary(logit_tenure)
## 
## Call:
## glm(formula = Churn_binary ~ tenure, family = binomial(link = "logit"), 
##     data = df_clean)
## 
## Coefficients:
##              Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  0.037299   0.042319   0.881    0.378    
## tenure      -0.039010   0.001409 -27.691   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7176.3  on 7030  degrees of freedom
## AIC: 7180.3
## 
## Number of Fisher Scoring iterations: 4

Nhận xét:

Hàm hồi quy được ước lượng như sau: \[ \log\left(\frac{\hat{\pi}}{1 - \hat{\pi}}\right) = 0.037299 -0.039010 \times \text{tenure} \]

  • Hệ số tenure = -0.0390 có ý nghĩa: mỗi tháng khách hàng gắn bó thêm, log odds (logit) của việc rời bỏ giảm 0.039 đơn vị.

  • Tương ứng, odds ratio (tỷ số odds) là:

\[ e^{-0.039} \approx 0.962 \]

→ Nghĩa là mỗi tháng thêm gắn bó làm giảm khoảng 3.8% odds rời bỏ dịch vụ.

  • Ý nghĩa thống kê:

Biến tenure có ý nghĩa thống kê cao (p < 2e-16), cho thấy đây là biến quan trọng và có ảnh hưởng rõ rệt đến khả năng khách hàng rời bỏ.

Trong khi đó, hệ số chặn (Intercept) không có ý nghĩa thống kê (p = 0.378), nhưng điều này không ảnh hưởng lớn đến giá trị mô hình.

Độ phù hợp mô hình:

AIC = 7180.3, thấp hơn đáng kể so với mô hình LPM tương ứng (AIC = 7529.7), chứng tỏ hồi quy logistic phù hợp hơn đáng kể cho dữ liệu nhị phân.

Residual deviance = 7176.3, giảm nhiều so với Null deviance = 8143.4, cho thấy mô hình có cải thiện tốt khi đưa tenure vào.

4.5.3. Mô hình Probit

probit_tenure <- glm(Churn_binary ~ tenure, data = df_clean, family = binomial(link = "probit"))
summary(probit_tenure)
## 
## Call:
## glm(formula = Churn_binary ~ tenure, family = binomial(link = "probit"), 
##     data = df_clean)
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  0.0017355  0.0258491   0.067    0.946    
## tenure      -0.0223316  0.0007691 -29.037   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7181.8  on 7030  degrees of freedom
## AIC: 7185.8
## 
## Number of Fisher Scoring iterations: 4

Nhận xét:

Hàm Probit ước lượng như sau: \[ \Phi^{-1}(\hat{\pi}) = 0.0017355 -0.0223316 \times \text{tenure} \] - Kết quả hồi quy sử dụng mô hình probit cho thấy biến thời gian gắn bó (tenure) có ảnh hưởng tiêu cực và có ý nghĩa thống kê rất cao đến xác suất rời bỏ dịch vụ (Churn). Hệ số ước lượng cho biến tenure là -0.0223 (p < 2e-16), cho thấy khi thời gian gắn bó của khách hàng tăng lên 1 đơn vị, xác suất rời bỏ giảm đáng kể. Mặc dù hệ số chặn không có ý nghĩa thống kê (p = 0.946), nhưng điều này không ảnh hưởng đến ý nghĩa của biến giải thích chính. Giá trị AIC của mô hình là 7185.8, cho thấy mức độ phù hợp tương đối tốt khi so sánh với các mô hình khác.

4.5.4. Mô hình Cloglog

cloglog_tenure <- glm(Churn_binary ~ tenure, data = df_clean, family = binomial(link = "cloglog"))
summary(cloglog_tenure)
## 
## Call:
## glm(formula = Churn_binary ~ tenure, family = binomial(link = "cloglog"), 
##     data = df_clean)
## 
## Coefficients:
##              Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -0.293230   0.032186  -9.111   <2e-16 ***
## tenure      -0.034061   0.001221 -27.886   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 7166.1  on 7030  degrees of freedom
## AIC: 7170.1
## 
## Number of Fisher Scoring iterations: 5

Nhận xét:

Phương trình hồi quy Cloglog: \[ \log(-\log(1 - \hat{\pi})) = -0.293230 -0.034061 \times \text{tenure} \] - Mô hình hồi quy nhị phân với liên kết complementary log-log (cloglog) cho thấy biến thời gian gắn bó (tenure) có ảnh hưởng âm và có ý nghĩa thống kê rất mạnh đến khả năng rời bỏ dịch vụ. Hệ số ước lượng cho tenure là -0.0341 với p-value < 2e-16, điều này cho thấy rằng khi thời gian gắn bó tăng thêm 1 đơn vị, log(-log(1 - P(Churn))) giảm, tức là xác suất rời bỏ giảm. Hệ số chặn cũng có ý nghĩa thống kê cao.

  • Mô hình cloglog đạt được AIC = 7170.1, thấp hơn so với mô hình logit (AIC = 7180.3) và probit (AIC = 7185.8). Điều này cho thấy mô hình cloglog phù hợp dữ liệu tốt hơn so với hai mô hình còn lại khi chỉ xét biến tenure.

4.5.5. Đánh giá các mô hình

aic_tenure <- data.frame(
  Model = c("LPM","Logit", "Probit", "Cloglog"),
  AIC = c(AIC(lpm_tenure),AIC(logit_tenure), AIC(probit_tenure), AIC(cloglog_tenure))
)
kable(aic_tenure, caption = "So sánh AIC các mô hình cho biến tenure")
So sánh AIC các mô hình cho biến tenure
Model AIC
LPM 7529.702
Logit 7180.261
Probit 7185.769
Cloglog 7170.125
  • Mô hình Cloglog là mô hình có mức độ phù hợp tốt nhất với dữ liệu khi chỉ xét biến tenure, do có giá trị AIC thấp nhất (7170.125).

  • Mô hình Logit và Probit đều cho thấy tenure là biến có ý nghĩa thống kê cao, nhưng hiệu quả kém hơn cloglog một chút.

  • Mô hình LPM có AIC rất cao (7529.702), xác nhận rằng phương pháp hồi quy tuyến tính không phù hợp để dự đoán biến nhị phân như Churn.

  • Do đó, mô hình cloglog là lựa chọn ưu tiên khi muốn dự đoán xác suất rời bỏ chỉ dựa vào biến thời gian gắn bó (tenure).

CHƯƠNG 5: MÔ HÌNH HỒI QUY BỘI

5.1. Mô hình Xác suất Tuyến tính (LPM) Bội

lpm_multi <- glm(Churn_binary ~ Contract + SeniorCitizen + PaymentMethod + InternetService + tenure,
                 data = df_clean, family = gaussian)
summary(lpm_multi)
## 
## Call:
## glm(formula = Churn_binary ~ Contract + SeniorCitizen + PaymentMethod + 
##     InternetService + tenure, family = gaussian, data = df_clean)
## 
## Coefficients:
##                                        Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                           0.3828242  0.0145255  26.355  < 2e-16 ***
## ContractOne year                     -0.1290837  0.0138333  -9.331  < 2e-16 ***
## ContractTwo year                     -0.0952259  0.0165655  -5.748 9.38e-09 ***
## SeniorCitizenYes                      0.0651830  0.0128641   5.067 4.14e-07 ***
## PaymentMethodCredit card (automatic) -0.0090382  0.0137316  -0.658   0.5104    
## PaymentMethodElectronic check         0.0899265  0.0133685   6.727 1.87e-11 ***
## PaymentMethodMailed check            -0.0285326  0.0145901  -1.956   0.0506 .  
## InternetServiceFiber optic            0.1717097  0.0110237  15.576  < 2e-16 ***
## InternetServiceNo                    -0.0829515  0.0130722  -6.346 2.35e-10 ***
## tenure                               -0.0048497  0.0002768 -17.518  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for gaussian family taken to be 0.1442149)
## 
##     Null deviance: 1372.2  on 7031  degrees of freedom
## Residual deviance: 1012.7  on 7022  degrees of freedom
## AIC: 6350.8
## 
## Number of Fisher Scoring iterations: 2

\[ \log\left( \frac{\hat{\pi}}{1 - \hat{\pi}} \right) = -0.29371 - 1.38770 \cdot \text{ContractOneYear} -1.79120 \cdot \text{ContractTwoYear} + 0.45661 \cdot \text{SeniorCitizenYes} \] \[ - 0.15394 \cdot \text{PaymentMethodCreditCard} + 0.81012 \cdot \text{PaymentMethodElectronicCheck} - 0.17352 \cdot \text{PaymentMethodMailedCheck} \] \[ + 1.44011 \cdot \text{InternetServiceFiberOptic} - 1.47994 \cdot \text{InternetServiceNo} - 0.07436 \cdot \text{tenure} \]

Trong đó: - \(\hat{\pi}\) là xác suất khách hàng rời bỏ dịch vụ (Churn = 1). - Các biến là biến giả đại diện cho từng nhóm (so với nhóm tham chiếu): - Contract: tham chiếu là “Month-to-month”. - PaymentMethod: tham chiếu là “Bank transfer (automatic)”. - InternetService: tham chiếu là “DSL”. - tenure: số tháng khách hàng đã sử dụng dịch vụ.

Biến Hệ số ước lượng Sai số chuẩn Giá trị t p-value Ý nghĩa thống kê
(Intercept) 0.3828 0.0145 26.355 < 2e-16 ***
ContractOne year -0.1291 0.0138 -9.331 < 2e-16 ***
ContractTwo year -0.0952 0.0166 -5.748 9.38e-09 ***
SeniorCitizenYes 0.0652 0.0129 5.067 4.14e-07 ***
PaymentMethodCredit card (automatic) -0.0090 0.0137 -0.658 0.5104
PaymentMethodElectronic check 0.0899 0.0134 6.727 1.87e-11 ***
PaymentMethodMailed check -0.0285 0.0146 -1.956 0.0506 .
InternetServiceFiber optic 0.1717 0.0110 15.576 < 2e-16 ***
InternetServiceNo -0.0830 0.0131 -6.346 2.35e-10 ***
tenure -0.0048 0.0003 -17.518 < 2e-16 ***

Nhận xét:

Mô hình LPM cho thấy phần lớn các biến đều có ảnh hưởng có ý nghĩa thống kê đến xác suất rời bỏ dịch vụ:

  • Khách hàng có hợp đồng 1 năm hoặc 2 năm có xác suất rời bỏ thấp hơn đáng kể so với khách hàng hợp đồng theo tháng.

  • Người cao tuổi (SeniorCitizen = Yes) có xác suất rời bỏ cao hơn.

  • Phương thức thanh toán bằng electronic check làm tăng khả năng rời bỏ; ngược lại, các phương thức khác như mailed check và credit card (automatic) không có ý nghĩa rõ ràng.

  • Khách hàng sử dụng internet cáp quang (fiber optic) có khả năng rời bỏ cao hơn, trong khi những người không sử dụng Internet lại ít rời bỏ hơn.

  • Thời gian sử dụng dịch vụ (tenure) càng dài thì khả năng rời bỏ càng thấp.

  • Mô hình có AIC = 6350.8, cho thấy mức độ phù hợp tương đối tốt trong bối cảnh đơn giản hóa bằng LPM. Tuy nhiên, do bản chất LPM có thể dự đoán xác suất ngoài khoảng [0,1], việc so sánh với các mô hình phi tuyến như Logit, Probit hay Cloglog là cần thiết để đánh giá toàn diện hơn.

Kết luận: Từ mô hình LPM, có thể kết luận rằng hợp đồng, dịch vụ Internet, và thời gian gắn bó là những yếu tố có ảnh hưởng mạnh mẽ nhất đến xác suất rời bỏ của khách hàng.

5.2. Mô hình Logit Bội

logit_multi <- glm(Churn_binary ~ Contract + SeniorCitizen + PaymentMethod + InternetService + tenure,
                   data = df_clean, family = binomial(link = "logit"))
summary(logit_multi)
## 
## Call:
## glm(formula = Churn_binary ~ Contract + SeniorCitizen + PaymentMethod + 
##     InternetService + tenure, family = binomial(link = "logit"), 
##     data = df_clean)
## 
## Coefficients:
##                                      Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                          -0.49632    0.10168  -4.881 1.06e-06 ***
## ContractOne year                     -0.74708    0.10320  -7.239 4.52e-13 ***
## ContractTwo year                     -1.51119    0.17038  -8.870  < 2e-16 ***
## SeniorCitizenYes                      0.34187    0.08159   4.190 2.79e-05 ***
## PaymentMethodCredit card (automatic) -0.07005    0.11224  -0.624    0.533    
## PaymentMethodElectronic check         0.42688    0.09265   4.607 4.08e-06 ***
## PaymentMethodMailed check            -0.06330    0.11149  -0.568    0.570    
## InternetServiceFiber optic            1.04902    0.07520  13.951  < 2e-16 ***
## InternetServiceNo                    -0.90285    0.12006  -7.520 5.49e-14 ***
## tenure                               -0.03147    0.00201 -15.655  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 5992.6  on 7022  degrees of freedom
## AIC: 6012.6
## 
## Number of Fisher Scoring iterations: 6

\[ \log\left( \frac{\hat{\pi}}{1 - \hat{\pi}} \right) = -0.49632 - 0.74708 \cdot \text{ContractOneYear} - 1.51119 \cdot \text{ContractTwoYear} + 0.34187 \cdot \text{SeniorCitizenYes} \] \[ - 0.07005 \cdot \text{PaymentMethodCreditCard} + 0.42688 \cdot \text{PaymentMethodElectronicCheck} - 0.06330 \cdot \text{PaymentMethodMailedCheck} \] \[ + 1.04902 \cdot \text{InternetServiceFiberOptic} - 0.90285 \cdot \text{InternetServiceNo} - 0.03147 \cdot \text{tenure} \]

Trong đó:
- \(\hat{\pi}\) là xác suất khách hàng rời bỏ dịch vụ. - Các biến là biến giả đại diện cho nhóm so với nhóm tham chiếu.

Biến Nhóm so sánh Hệ số (β) p-value Odds Ratio (e^β)
Hợp đồng: Một năm So với Hợp đồng tháng một -0.74708 4.52e-13 0.47
Hợp đồng: Hai năm So với Hợp đồng tháng một -1.51119 < 2e-16 0.22
Là người cao tuổi So với không cao tuổi 0.34187 2.79e-05 1.41
Thanh toán: Thẻ tín dụng (tự động) So với thanh toán ngân hàng (tự động) -0.07005 0.533 0.93
Thanh toán: Séc điện tử So với thanh toán ngân hàng (tự động) 0.42688 4.08e-06 1.53
Thanh toán: Gửi séc So với thanh toán ngân hàng (tự động) -0.06330 0.570 0.94
Internet: Cáp quang So với DSL 1.04902 < 2e-16 2.86
Internet: Không có So với DSL -0.90285 5.49e-14 0.41
Thâm niên (tháng) Mỗi tháng tăng thêm -0.03147 < 2e-16 0.97

Nhận xét:

  • Hợp đồng một năm hoặc hai năm đều làm giảm đáng kể khả năng rời bỏ, đặc biệt là hợp đồng hai năm với hệ số âm lớn.
  • Khách hàng cao tuổi (SeniorCitizenYes) có khả năng rời bỏ cao hơn (hệ số dương, có ý nghĩa thống kê).
  • Phương thức thanh toán bằng Electronic check có liên quan mạnh nhất đến việc rời bỏ (hệ số dương và p-value < 0.001).
  • Internet Fiber Optic làm tăng đáng kể xác suất rời bỏ, ngược lại, không sử dụng internet (InternetServiceNo) lại làm giảm xác suất rời bỏ.
  • Số tháng sử dụng dịch vụ (tenure) càng cao thì xác suất rời bỏ càng thấp (hệ số âm và có ý nghĩa thống kê cao).

5.3. Mô hình Probit Bội

probit_multi <- glm(Churn_binary ~ Contract + SeniorCitizen + PaymentMethod + InternetService + tenure,
                    data = df_clean, family = binomial(link = "probit"))
summary(probit_multi)
## 
## Call:
## glm(formula = Churn_binary ~ Contract + SeniorCitizen + PaymentMethod + 
##     InternetService + tenure, family = binomial(link = "probit"), 
##     data = df_clean)
## 
## Coefficients:
##                                       Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                          -0.303184   0.058877  -5.149 2.61e-07 ***
## ContractOne year                     -0.424354   0.057076  -7.435 1.05e-13 ***
## ContractTwo year                     -0.740723   0.082071  -9.025  < 2e-16 ***
## SeniorCitizenYes                      0.201394   0.048133   4.184 2.86e-05 ***
## PaymentMethodCredit card (automatic) -0.038732   0.062961  -0.615    0.538    
## PaymentMethodElectronic check         0.254941   0.053566   4.759 1.94e-06 ***
## PaymentMethodMailed check            -0.054114   0.063713  -0.849    0.396    
## InternetServiceFiber optic            0.618866   0.043721  14.155  < 2e-16 ***
## InternetServiceNo                    -0.512903   0.065221  -7.864 3.72e-15 ***
## tenure                               -0.018155   0.001146 -15.838  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 5998.1  on 7022  degrees of freedom
## AIC: 6018.1
## 
## Number of Fisher Scoring iterations: 6

\[ \Phi^{-1}(\hat{\pi}) = -0.30318 - 0.42435 \cdot \text{ContractOneYear} - 0.74072 \cdot \text{ContractTwoYear} + 0.20139 \cdot \text{SeniorCitizenYes} \\ - 0.03873 \cdot \text{PaymentMethodCreditCard} + 0.25494 \cdot \text{PaymentMethodElectronicCheck} - 0.05411 \cdot \text{PaymentMethodMailed} \\ + 0.61887 \cdot \text{InternetServiceFiberOptic} - 0.51290 \cdot \text{InternetServiceNo} - 0.01815 \cdot \text{tenure} \]

Trong đó:

  • \(\Phi^{-1}(\hat{\pi})\) là hàm liên kết probit (hàm nghịch đảo của chuẩn tích lũy chuẩn).
  • Các biến là biến giả so với nhóm tham chiếu.
Biến Nhóm so sánh Hệ số (β) p-value
Hợp đồng: Một năm So với Hợp đồng tháng một -0.42435 1.05e-13
Hợp đồng: Hai năm So với Hợp đồng tháng một -0.74072 < 2e-16
Là người cao tuổi So với không cao tuổi 0.20139 2.86e-05
Thanh toán: Thẻ tín dụng (tự động) So với thanh toán ngân hàng (tự động) -0.03873 0.538
Thanh toán: Séc điện tử So với thanh toán ngân hàng (tự động) 0.25494 1.94e-06
Thanh toán: Gửi séc So với thanh toán ngân hàng (tự động) -0.05411 0.396
Internet: Cáp quang So với DSL 0.61887 < 2e-16
Internet: Không có So với DSL -0.51290 3.72e-15
Thâm niên (tháng) Mỗi tháng tăng thêm -0.01815 < 2e-16

Nhận xét:

  • Hợp đồng dài hạn (một năm và hai năm) đều làm giảm xác suất rời bỏ dịch vụ, đặc biệt là hợp đồng hai năm có tác động mạnh hơn (hệ số âm lớn, p-value rất nhỏ).

  • Khách hàng cao tuổi có xu hướng rời bỏ cao hơn, với hệ số dương và có ý nghĩa thống kê.

  • Phương thức thanh toán bằng Séc điện tử là yếu tố làm tăng khả năng rời bỏ dịch vụ, với ý nghĩa thống kê mạnh mẽ (p-value < 0.001).

  • Sử dụng Internet Fiber Optic làm tăng đáng kể khả năng rời bỏ, trong khi không sử dụng Internet lại giảm đáng kể xác suất này.

  • Thời gian sử dụng dịch vụ (tenure) càng cao thì khách hàng càng ít có khả năng rời bỏ.

5.4. Mô hình Cloglog Bội

cloglog_multi <- glm(Churn_binary ~ Contract + SeniorCitizen + PaymentMethod + InternetService + tenure,
                     data = df_clean, family = binomial(link = "cloglog"))
summary(cloglog_multi)
## 
## Call:
## glm(formula = Churn_binary ~ Contract + SeniorCitizen + PaymentMethod + 
##     InternetService + tenure, family = binomial(link = "cloglog"), 
##     data = df_clean)
## 
## Coefficients:
##                                       Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                          -0.735433   0.081782  -8.993  < 2e-16 ***
## ContractOne year                     -0.678716   0.091827  -7.391 1.45e-13 ***
## ContractTwo year                     -1.519266   0.161131  -9.429  < 2e-16 ***
## SeniorCitizenYes                      0.230358   0.057498   4.006 6.17e-05 ***
## PaymentMethodCredit card (automatic) -0.073993   0.091438  -0.809    0.418    
## PaymentMethodElectronic check         0.289694   0.072515   3.995 6.47e-05 ***
## PaymentMethodMailed check            -0.053088   0.089411  -0.594    0.553    
## InternetServiceFiber optic            0.785994   0.058178  13.510  < 2e-16 ***
## InternetServiceNo                    -0.807526   0.107374  -7.521 5.45e-14 ***
## tenure                               -0.024564   0.001577 -15.581  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8143.4  on 7031  degrees of freedom
## Residual deviance: 5993.8  on 7022  degrees of freedom
## AIC: 6013.8
## 
## Number of Fisher Scoring iterations: 6

\[ \log(-\log(1 - \hat{\pi})) = -0.73543 - 0.67872 \cdot \text{ContractOneYear} - 1.51927 \cdot \text{ContractTwoYear} + 0.23036 \cdot \text{SeniorCitizenYes} \\ - 0.07399 \cdot \text{PaymentMethodCreditCard} + 0.28969 \cdot \text{PaymentMethodElectronicCheck} - 0.05309 \cdot \text{PaymentMethodMailedCheck} \\ + 0.78599 \cdot \text{InternetServiceFiberOptic} - 0.80753 \cdot \text{InternetServiceNo} - 0.02456 \cdot \text{tenure} \]

Trong đó:

  • \(\hat{\pi}\) là xác suất khách hàng rời bỏ dịch vụ (Churn_binary = 1).
  • Hàm liên kết là cloglog: \(\log(-\log(1 - \hat{\pi}))\).
  • Các biến là biến giả so với nhóm tham chiếu:
    • Contract: tham chiếu là Month-to-month.
    • SeniorCitizen: tham chiếu là No.
    • PaymentMethod: tham chiếu là Bank transfer (automatic).
    • InternetService: tham chiếu là DSL.

Bảng: Kết quả ước lượng từ mô hình hồi quy Cloglog đa biến

Biến Nhóm so sánh Hệ số (β) p-value
Hợp đồng: Một năm So với Hợp đồng tháng một -0.6787 1.45e-13
Hợp đồng: Hai năm So với Hợp đồng tháng một -1.5193 < 2e-16
Là người cao tuổi So với không cao tuổi 0.2304 6.17e-05
Thanh toán: Thẻ tín dụng (tự động) So với thanh toán ngân hàng (tự động) -0.0740 0.418
Thanh toán: Séc điện tử So với thanh toán ngân hàng (tự động) 0.2897 6.47e-05
Thanh toán: Gửi séc So với thanh toán ngân hàng (tự động) -0.0531 0.553
Internet: Cáp quang So với DSL 0.7860 < 2e-16
Internet: Không có So với DSL -0.8075 5.45e-14
Thâm niên (tháng) Mỗi tháng tăng thêm -0.0246 < 2e-16

Nhận xét:

  • Hợp đồng dài hạn (một năm và hai năm) đều làm giảm xác suất rời bỏ dịch vụ, đặc biệt là hợp đồng hai năm có tác động mạnh hơn (hệ số âm lớn, p-value rất nhỏ).

  • Khách hàng cao tuổi có xu hướng rời bỏ cao hơn, với hệ số dương và có ý nghĩa thống kê.

  • Phương thức thanh toán bằng Séc điện tử là yếu tố làm tăng khả năng rời bỏ dịch vụ, với ý nghĩa thống kê mạnh mẽ (p-value < 0.001).

  • Sử dụng Internet Fiber Optic làm tăng đáng kể khả năng rời bỏ, trong khi không sử dụng Internet lại giảm đáng kể xác suất này.

  • Thời gian sử dụng dịch vụ (tenure) càng cao thì khách hàng càng ít có khả năng rời bỏ.


CHƯƠNG 6: ĐÁNH GIÁ MÔ HÌNH VÀ DỰ BÁO

6.1. So sánh các mô hình hồi quy bội

# Tạo bảng so sánh
# (Giả định các mô hình lpm_multi, logit_multi, probit_multi, cloglog_multi đã được chạy)
comparison_table <- data.frame(
  "Mô hình" = c("Tuyến tính (LPM)", "Logit", "Probit", "Cloglog"),
  AIC = c(AIC(lpm_multi), AIC(logit_multi), AIC(probit_multi), AIC(cloglog_multi)),
  LogLikelihood = c(logLik(lpm_multi), logLik(logit_multi), logLik(probit_multi), logLik(cloglog_multi)),
  "McFadden R-squared" = c(pR2(lpm_multi)["McFadden"], pR2(logit_multi)["McFadden"], pR2(probit_multi)["McFadden"], pR2(cloglog_multi)["McFadden"]),
  check.names = FALSE
)
## fitting null model for pseudo-r2
## fitting null model for pseudo-r2
## fitting null model for pseudo-r2
## fitting null model for pseudo-r2
# Sử dụng kable để hiển thị bảng đẹp hơn
kable(
  comparison_table,
  caption = "Bảng so sánh hiệu quả các mô hình hồi quy bội",
  digits = 4,
  col.names = c("Mô hình", "AIC", "LogLikelihood", "McFadden R-squared")
)
Bảng so sánh hiệu quả các mô hình hồi quy bội
Mô hình AIC LogLikelihood McFadden R-squared
Tuyến tính (LPM) 6350.823 -3164.412 0.2524
Logit 6012.628 -2996.314 0.2641
Probit 6018.108 -2999.054 0.2634
Cloglog 6013.834 -2996.917 0.2640

Nhận xét:

  • Bảng so sánh cho thấy mô hình Logit vượt trội hơn cả về tiêu chí AIC (6012.628) và hệ số xác định McFadden (0.2641), cho thấy khả năng giải thích biến phụ thuộc tốt hơn so với các mô hình khác. Mặc dù mô hình Cloglog và Probit có hiệu suất gần tương đương, nhưng vẫn kém hơn mô hình Logit ở cả AIC và mức phù hợp tổng thể.

  • Ngược lại, mô hình Tuyến tính (LPM) cho kết quả kém nhất với AIC cao nhất (6350.823) và McFadden R² thấp nhất (0.2524), cho thấy phương pháp này không phù hợp để mô hình hóa biến nhị phân như Churn.

  • Như vậy, mô hình Logit không chỉ đảm bảo tính đơn giản trong diễn giải (qua hệ số log-odds) mà còn cung cấp độ phù hợp tốt nhất, làm cho nó trở thành lựa chọn tối ưu trong bài toán dự đoán khả năng rời bỏ dịch vụ.

6.2. Dự báo khả năng rời bỏ

Chúng ta sẽ sử dụng mô hình Logit bội để dự báo xác suất rời bỏ cho một khách hàng giả định có các đặc điểm rủi ro cao nhất đã được xác định.

# Tạo hồ sơ khách hàng có nguy cơ rời bỏ cao
risky_customer <- data.frame(
  Contract = factor("Month-to-month", levels = levels(df_clean$Contract)),
  SeniorCitizen = factor("Yes", levels = levels(df_clean$SeniorCitizen)),
  PaymentMethod = factor("Electronic check", levels = levels(df_clean$PaymentMethod)),
  InternetService = factor("Fiber optic", levels = levels(df_clean$InternetService)),
  tenure = 1  # Khách hàng mới, chỉ gắn bó 1 tháng
)

cat("Dự báo cho khách hàng có hồ sơ:\n")
## Dự báo cho khách hàng có hồ sơ:
print(risky_customer)
##         Contract SeniorCitizen    PaymentMethod InternetService tenure
## 1 Month-to-month           Yes Electronic check     Fiber optic      1
# Dự báo xác suất
predicted_prob <- predict(logit_multi, newdata = risky_customer, type = "response")

cat("\n-> Xác suất rời bỏ dự báo của khách hàng này là:", scales::percent(predicted_prob, accuracy = 0.1), "\n")
## 
## -> Xác suất rời bỏ dự báo của khách hàng này là: 78.4%

Nhận xét dự báo: Mô hình Logit dự báo rằng một khách hàng cao tuổi, mới sử dụng dịch vụ được 1 tháng, có hợp đồng theo tháng, dùng Internet cáp quang và thanh toán bằng séc điện tử có xác suất rời bỏ lên tới 73.1%. Đây là một con số cực kỳ cao, cho thấy sự kết hợp của các yếu tố rủi ro này tạo ra một “công thức hoàn hảo” cho việc churn.

Kết quả dự báo này không chỉ là một con số, mà là một lời cảnh báo mạnh mẽ. Nó cho phép doanh nghiệp xác định chính xác những “điểm nóng” trong tệp khách hàng của mình. Thay vì các chiến dịch giữ chân dàn trải, công ty có thể tập trung nguồn lực vào đúng nhóm đối tượng này—ví dụ, đưa ra ưu đãi đặc biệt để họ chuyển đổi sang hợp đồng dài hạn ngay trong những tháng đầu tiên, hoặc cung cấp hỗ trợ kỹ thuật chuyên sâu cho người dùng cáp quang mới. Đây chính là giá trị thực tiễn cốt lõi mà phân tích dự báo mang lại: biến dữ liệu thành hành động chiến lược.


CHƯƠNG 7: ƯU ĐIỂM, HẠN CHẾ VÀ KIẾN NGHỊ

7.1. Ưu điểm của Nghiên cứu

  • Tính hệ thống: Nghiên cứu đã áp dụng một quy trình phân tích dữ liệu bài bản, từ thống kê mô tả, kiểm định giả thuyết đến xây dựng và so sánh nhiều mô hình hồi quy.
  • Kết quả rõ ràng: Các yếu tố ảnh hưởng chính đến tỷ lệ rời bỏ đã được xác định một cách rõ ràng và nhất quán qua nhiều phương pháp khác nhau.
  • Tính ứng dụng cao: Kết quả nghiên cứu có thể được áp dụng trực tiếp vào việc xây dựng các chiến lược kinh doanh nhằm giảm tỷ lệ rời bỏ, như tập trung vào các nhóm khách hàng có hợp đồng tháng, dùng cáp quang hoặc thanh toán bằng séc điện tử.

7.2. Hạn chế của Nghiên cứu

  • Dữ liệu giả định: Bộ dữ liệu là giả định và có thể không phản ánh đầy đủ sự phức tạp của thị trường viễn thông thực tế.
  • Bỏ qua các biến tiềm năng: Nghiên cứu chỉ tập trung vào 5 biến được chọn trước. Các yếu tố khác như chất lượng dịch vụ khách hàng, các chương trình khuyến mãi, hoặc tác động của đối thủ cạnh tranh chưa được xem xét.
  • Mô hình tĩnh: Các mô hình hồi quy là mô hình tĩnh, không phản ánh được sự thay đổi trong hành vi của khách hàng theo thời gian.

7.3. Kiến nghị

Dựa trên kết quả phân tích, tác giả đề xuất các kiến nghị sau:

  1. Tối ưu hóa chiến lược hợp đồng: Tích cực triển khai các chương trình khuyến mãi để khuyến khích khách hàng đang sử dụng hợp đồng Month-to-month chuyển đổi sang các hợp đồng dài hạn (One year hoặc Two year).

  2. Cải thiện trải nghiệm dịch vụ Internet: Tỷ lệ rời bỏ cao của nhóm khách hàng Fiber optic cho thấy có thể tồn tại các vấn đề về chất lượng dịch vụ, giá cả, hoặc hỗ trợ kỹ thuật. Cần có các cuộc khảo sát sâu hơn để tìm ra nguyên nhân và cải thiện.

  3. Thúc đẩy các phương thức thanh toán tự động: Cung cấp các ưu đãi (ví dụ: giảm giá, tặng thêm dữ liệu) cho khách hàng khi họ chuyển từ thanh toán thủ công (Electronic check) sang các hình thức tự động như Bank transfer hoặc Credit card .

  4. Chăm sóc đặc biệt cho người cao tuổi: Xây dựng các gói cước và chương trình hỗ trợ đơn giản, dễ sử dụng, nhắm riêng đến phân khúc khách hàng SeniorCitizen để giảm tỷ lệ rời bỏ của nhóm này.

TÀI LIỆU THAM KHẢO

  1. Agresti, A. (2013). Categorical Data Analysis (3rd ed.). Wiley.

  2. Ahmad, A. B., Jantan, A., & Yusoff, S. A. (2007). Predicting customer churn: A data mining approach. Paper presented at the International Conference on Intelligent Systems and Technologies (ICIST 2007).

  3. Auguie, B. (2023). gridExtra: Miscellaneous Functions for “Grid” Graphics. R package version 2.3. https://CRAN.R-project.org/package=gridExtra

  4. De Bleser, R., Luque, F. M., & Mantas, C. G. (2021). A Comparative Study of Machine Learning Algorithms for Churn Prediction. Applied Sciences, 11(16), 7624. https://doi.org/10.3390/app11167624

  5. Field, A., Miles, J., & Field, Z. (2012). Discovering Statistics Using R. Sage Publications.

  6. Fox, J., & Weisberg, S. (2019). An R Companion to Applied Regression (3rd ed.). Sage.

  7. Hosmer, D. W., Lemeshow, S., & Sturdivant, R. X. (2013). Applied Logistic Regression (3rd ed.). Wiley.

  8. IBM Watson Analytics. (n.d.). Telco Customer Churn. Kaggle. Truy cập ngày 15/07/2025, từ https://www.kaggle.com/datasets/blastchar/telco-customer-churn.

  9. Giáo trình Phân Tích Dữ Liệu Định Tính, ThS. Trần Mạnh Tường

LS0tDQp0aXRsZTogIlBIw4JOIFTDjUNIIEPDgUMgWeG6vlUgVOG7kCDhuqJOSCBIxq/hu55ORyDEkOG6vk4gVOG7tiBM4buGIFLhu5xJIELhu44gQ+G7pkEgS0jDgUNIIEjDgE5HIFZJ4buETiBUSMOUTkciDQphdXRob3I6ICJUcuG6p24gTmFtIFRoacOqbiINCmRhdGU6ICIxNDo1MTowMiwgMjcgLSAwNyAtIDIwMjUiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRvYzogdHJ1ZQ0KICAgIGxhbmc6ICJ2aS1WTiINCiAgICB0aGVtZTogam91cm5hbA0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogJzQnDQotLS0NCjxzdHlsZT4NCmJvZHkgew0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIHNlcmlmOw0KICBmb250LXNpemU6IDE2cHg7DQogIHRleHQtYWxpZ246IGp1c3RpZnk7DQp9DQpoMSwgaDIsIGgzLCBoNCB7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgc2VyaWY7DQogIHRleHQtYWxpZ246IGp1c3RpZnk7DQogIGNvbG9yOiBibGFjazsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQpoMSB7IGZvbnQtc2l6ZTogMThweDsgfQ0KaDIsIGgzLCBoNCB7IGZvbnQtc2l6ZTogMTZweDsgfQ0KPC9zdHlsZT4NCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBU4bqjaSBjw6FjIHRoxrAgdmnhu4duIGPhuqduIHRoaeG6v3QNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShlcGl0b29scykgDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmxpYnJhcnkoZ2dtb3NhaWMpDQpsaWJyYXJ5KHBzY2wpIA0KbGlicmFyeShzY2FsZXMpDQpgYGANCg0KIyAqKkNIxq/GoE5HIDE6IFThu5RORyBRVUFOIMSQ4buAIFTDgEkqKg0KDQojIyAqKjEuMS4gR2nhu5tpIHRoaeG7h3UgZOG7ryBsaeG7h3UqKg0KTmdoacOqbiBj4bupdSBuw6B5IGtoYWkgdGjDoWMgYuG7mSBk4buvIGxp4buHdSDigJxUZWxjbyBDdXN0b21lciBDaHVybuKAnSwgbeG7mXQgdHJvbmcgbmjhu69uZyBi4buZIGThu68gbGnhu4d1IGtpbmggxJFp4buDbiDEkcaw4bujYyBjw7RuZyBi4buRIHLhu5luZyByw6NpIHRyw6puIG7hu4FuIHThuqNuZyBLYWdnbGUuIEThu68gbGnhu4d1IG7DoHkgbcO0IHThuqMgY8OhYyB0aHXhu5ljIHTDrW5oIGPhu6dhIGtow6FjaCBow6BuZyB04bqhaSBt4buZdCBjw7RuZyB0eSB2aeG7hW4gdGjDtG5nIGdp4bqjIMSR4buLbmgsIHbhu5tpIG3hu6VjIHRpw6p1IGNow61uaCBsw6AgcGjDom4gdMOtY2ggdsOgIGThu7EgYsOhbyBjw6FjIHnhur91IHThu5EgZOG6q24gxJHhur9uIHF1eeG6v3QgxJHhu4tuaCBuZ+G7q25nIHPhu60gZOG7pW5nIGThu4tjaCB24bulIChjaHVybikgY+G7p2Ega2jDoWNoIGjDoG5nLg0KDQpC4buZIGThu68gbGnhu4d1IGfhu5FjIGJhbyBn4buTbSA3MDQzIHF1YW4gc8OhdCAodMawxqFuZyDhu6luZyB24bubaSBt4buXaSBraMOhY2ggaMOgbmcpIHbDoCAyMSB0aHXhu5ljIHTDrW5oIG3DtCB04bqjLiBN4bulYyB0acOqdSBj4bunYSBwaMOibiB0w61jaCBsw6AgeMOieSBk4buxbmcgbeG7mXQgbcO0IGjDrG5oIGPDsyBraOG6oyBuxINuZyBk4buxIMSRb8OhbiBiaeG6v24gYENodXJuYCwgdOG7qyDEkcOzIGN1bmcgY+G6pXAgbmjhu69uZyB0aMO0bmcgdGluIGdpw6EgdHLhu4sgY2hvIGPDoWMgY2hp4bq/biBsxrDhu6NjIGdp4buvIGNow6JuIGtow6FjaCBow6BuZyBj4bunYSBkb2FuaCBuZ2hp4buHcC4NCg0KKipC4bqjbmcgMS4gQ8OhYyBiaeG6v24gxJHGsOG7o2Mgc+G7rSBk4bulbmcgdHJvbmcgbmdoacOqbiBj4bupdSDEkcaw4bujYyB0w7NtIHThuq90IGTGsOG7m2kgxJHDonk6KioNCg0KfCBUw6puIGJp4bq/biB8IEtp4buDdSBiaeG6v24gfCBNw7QgdOG6oyB8IEPDoWMgZ2nDoSB0cuG7iyB8DQp8IDotLS0gfCA6LS0tIHwgOi0tLSB8IDotLS0gfA0KfCAqKkNodXJuKiogfCDEkOG7i25oIHTDrW5oIHwgS2jDoWNoIGjDoG5nIGPDsyBy4budaSBi4buPIHPhu60gZOG7pW5nIGThu4tjaCB24bulIHZp4buFbiB0aMO0bmcgaGF5IGtow7RuZy4gfCAtIFllczogUuG7nWkgYuG7jzxicj4tIE5vOiBUaeG6v3AgdOG7pWMgc+G7rSBk4bulbmcgfA0KfCAqKkdlbmRlcioqIHwgxJDhu4tuaCB0w61uaCB8IEdp4bubaSB0w61uaCBj4bunYSBraMOhY2ggaMOgbmcuIHwgLSBNYWxlOiBOYW08YnI+LSBGZW1hbGU6IE7hu68gfA0KfCAqKlNlbmlvckNpdGl6ZW4qKiB8IMSQ4buLbmggdMOtbmggfCBLaMOhY2ggaMOgbmcgY8OzIHBo4bqjaSBsw6AgbmfGsOG7nWkgY2FvIHR14buVaSBoYXkga2jDtG5nICh0csOqbiA2NSB0deG7lWkpLiB8IC0gWWVzOiBDw7M8YnI+LSBObzogS2jDtG5nIHwNCnwgKipQYXJ0bmVyKiogfCDEkOG7i25oIHTDrW5oIHwgS2jDoWNoIGjDoG5nIGPDsyB24bujL2No4buTbmcgaGF5IGtow7RuZy4gfCAtIFllczogQ8OzPGJyPi0gTm86IEtow7RuZyB8DQp8ICoqRGVwZW5kZW50cyoqIHwgxJDhu4tuaCB0w61uaCB8IEtow6FjaCBow6BuZyBjw7MgbmfGsOG7nWkgcGjhu6UgdGh14buZYyBoYXkga2jDtG5nIChjb24gY8OhaSwgY2hhIG3hurksIHYudi4pLiB8IC0gWWVzOiBDw7M8YnI+LSBObzogS2jDtG5nIHwNCnwgKipJbnRlcm5ldFNlcnZpY2UqKnwgxJDhu4tuaCB0w61uaCB8IExv4bqhaSBk4buLY2ggduG7pSBJbnRlcm5ldCBtw6Aga2jDoWNoIGjDoG5nIMSRxINuZyBrw70gc+G7rSBk4bulbmcuIHwgLSBEU0w6IEludGVybmV0IHF1YSDEkcaw4budbmcgZMOieSDEkWnhu4duIHRob+G6oWk8YnI+LSBGaWJlciBvcHRpYzogQ8OhcCBxdWFuZzxicj4tIE5vOiBLaMO0bmcgc+G7rSBk4bulbmcgSW50ZXJuZXQgfA0KfCAqKkNvbnRyYWN0KiogfCDEkOG7i25oIHTDrW5oIHwgTG/huqFpIGjhu6NwIMSR4buTbmcgY+G7p2Ega2jDoWNoIGjDoG5nLiB8IC0gTW9udGgtdG8tbW9udGg6IEjDoG5nIHRow6FuZzxicj4tIE9uZSB5ZWFyOiBI4bujcCDEkeG7k25nIDEgbsSDbTxicj4tIFR3byB5ZWFyOiBI4bujcCDEkeG7k25nIDIgbsSDbSB8DQp8ICoqUGF5bWVudE1ldGhvZCoqIHwgxJDhu4tuaCB0w61uaCB8IFBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiBj4bunYSBraMOhY2ggaMOgbmcuIHwgLSBFbGVjdHJvbmljIENoZWNrOiBTw6ljIMSRaeG7h24gdOG7rTxicj4tIE1haWxlZCBDaGVjazogU8OpYyBxdWEgdGjGsDxicj4tIEJhbmsgdHJhbnNmZXI6IENodXnhu4NuIGtob+G6o24gbmfDom4gaMOgbmc8YnI+LSBDcmVkaXQgQ2FyZDogVGjhursgdMOtbiBk4bulbmcgfA0KfCAqKnRlbnVyZSoqIHwgxJDhu4tuaCBsxrDhu6NuZyB8IFPhu5EgdGjDoW5nIGtow6FjaCBow6BuZyDEkcOjIHPhu60gZOG7pW5nIGThu4tjaCB24bulLiB8IFPhu5Egbmd1ecOqbiAodsOtIGThu6U6IDEsIDEyLCAyNCwuLi4pIHwNCnwgKipNb250aGx5Q2hhcmdlcyoqfCDEkOG7i25oIGzGsOG7o25nIHwgQ2hpIHBow60ga2jDoWNoIGjDoG5nIHRy4bqjIGjDoG5nIHRow6FuZy4gfCBT4buRIHRo4buxYyAodsOtIGThu6U6IDI5Ljg1LCAxMDQuODApIHwNCnwgKipUb3RhbENoYXJnZXMqKiB8IMSQ4buLbmggbMaw4bujbmcgfCBU4buVbmcgY2hpIHBow60ga2jDoWNoIGjDoG5nIMSRw6MgdHLhuqMgdOG7qyB0csaw4bubYyB04bubaSBuYXkuIHwgU+G7kSB0aOG7sWMsIGzDoCB04buVbmcgY2hpIHBow60gdMOtY2ggbMWpeSB8DQoNCiMjICoqMS4yLiBC4buRaSBj4bqjbmggbmdoacOqbiBj4bupdSoqDQpUcm9uZyBi4buRaSBj4bqjbmggY2h1eeG7g24gxJHhu5VpIHPhu5EgZGnhu4VuIHJhIG3huqFuaCBt4bq9LCBuZ8Ogbmggdmnhu4VuIHRow7RuZyDEkWFuZyBwaOG6o2kgxJHhu5FpIG3hurd0IHbhu5tpIMOhcCBs4buxYyBj4bqhbmggdHJhbmggY2jGsGEgdOG7q25nIGPDsy4gS2hpIHRo4buLIHRyxrDhu51uZyB0aeG6v24gZ+G6p24gxJHhur9uIMSRaeG7g20gYsOjbyBow7JhLCBuZ8aw4budaSBkw7luZyBjw7MgcXXDoSBuaGnhu4F1IGzhu7FhIGNo4buNbiB24buBIG5ow6AgY3VuZyBj4bqlcCBk4buLY2ggduG7pSB24bubaSBt4bupYyBnacOhLCBjaOG6pXQgbMaw4bujbmcgdsOgIMawdSDEkcOjaSBn4bqnbiBuaMawIHTGsMahbmcgxJHGsMahbmcgbmhhdS4gxJBp4buBdSBuw6B5IGtoaeG6v24gdmnhu4djIHRodSBow7p0IGtow6FjaCBow6BuZyBt4bubaSBuZ8OgeSBjw6BuZyBraMOzIGtoxINuIHbDoCB04buRbiBrw6ltLg0KDQpDaMOtbmggdsOsIHRo4bq/LCB0aGF5IHbDrCBk4buTbiBs4buxYyB2w6BvIHZp4buHYyB0w6xtIGtp4bq/bSBraMOhY2ggaMOgbmcgbeG7m2ksIGPDoWMgZG9hbmggbmdoaeG7h3Agdmnhu4VuIHRow7RuZyBideG7mWMgcGjhuqNpIGNodXnhu4NuIGjGsOG7m25nIGNoaeG6v24gbMaw4bujYyBzYW5nIGdp4buvIGNow6JuIGtow6FjaCBow6BuZyBoaeG7h24gdOG6oWkg4oCUIG5o4buvbmcgbmfGsOG7nWkgxJHDoyB04burbmcgY2jhu41uIHbDoCBz4butIGThu6VuZyBk4buLY2ggduG7pS4gVHJvbmcgY2hp4bq/biBsxrDhu6NjIG7DoHksIHThu7cgbOG7hyBy4budaSBi4buPIChjdXN0b21lciBjaHVybikgdHLhu58gdGjDoG5oIGNo4buJIHPhu5EgdGhlbiBjaOG7kXQuDQoNCk3hu5l0IHThu7cgbOG7hyBjaHVybiBjYW8ga2jDtG5nIGNo4buJIGtoaeG6v24gZG9hbmggbmdoaeG7h3AgbeG6pXQgZG9hbmggdGh1IHRy4buxYyB0aeG6v3AgbcOgIGPDsm4gxJHhuql5IGNoaSBwaMOtIG1hcmtldGluZyB0xINuZyB24buNdCDEkeG7gyBiw7kgxJHhuq9wIGzGsOG7o25nIGtow6FjaCBow6BuZyBi4buLIG3huqV0LiBU4buHIGjGoW4sIG7hur91IGtow6FjaCBow6BuZyByYSDEkWkgdsOsIGtow7RuZyBow6BpIGzDsm5nLCDEkWnhu4F1IMSRw7MgY8OzIHRo4buDIGvDqW8gdGhlbyBoaeG7h3Ug4bupbmcgbGFuIHRydXnhu4FuIHRpw6p1IGPhu7FjLCDhuqNuaCBoxrDhu59uZyDEkeG6v24gdXkgdMOtbiB0aMawxqFuZyBoaeG7h3UuDQoNCkdp4buvIGNow6JuIGtow6FjaCBow6BuZyBraMO0bmcgY2jhu4kgbMOgIG3hu5l0IHbhuqVuIMSR4buBIGtpbmggdOG6vywgbcOgIGzDoCBt4buZdCBiw6BpIHRvw6FuIHPhu5FuZyBjw7JuIHbhu5tpIG3hu41pIG5ow6AgbeG6oW5nLiDEkMOzIGzDoCBsw70gZG8gdsOsIHNhbyB2aeG7h2MgaGnhu4N1IHLDtSB2w6wgc2FvIGtow6FjaCBow6BuZyBy4budaSDEkWksIHbDoCBsw6BtIHNhbyDEkeG7gyBk4buxIGLDoW8gxJFp4buBdSDEkcOzIHThu6sgc+G7m20sIHRy4bufIHRow6BuaCDGsHUgdGnDqm4gaMOgbmcgxJHhuqd1IHRyb25nIGPDoWMgY2hp4bq/biBsxrDhu6NjIHbhuq1uIGjDoG5oIHbDoCBwaMOhdCB0cmnhu4NuIGPhu6dhIG5nw6BuaCB2aeG7hW4gdGjDtG5nIGhp4buHbiDEkeG6oWkuDQoNCiMjICoqMS4zLiBN4bulYyB0acOqdSBuZ2hpw6puIGPhu6l1KioNCk3hu6VjIHRpw6p1IGPhu6dhIG5naGnDqm4gY+G7qXUgbsOgeSBsw6AgeMOhYyDEkeG7i25oIHbDoCBwaMOibiB0w61jaCBjw6FjIHnhur91IHThu5Eg4bqjbmggaMaw4bufbmcgxJHhur9uIHZp4buHYyBy4budaSBi4buPIHZp4buHYyBz4butIGThu6VuZyBk4buLY2ggduG7pSB2aeG7hW4gdGjDtG5nIGPhu6dhIGtow6FjaCBow6BuZy4gQ+G7pSB0aOG7gyBsw6AgdMOhYyBnaeG6oyB04bqtcCB0cnVuZyB2w6BvIGPDoWMga2jDrWEgY+G6oW5oIHNhdToNCi0JVOG7tyBs4buHIHLhu51pIGLhu48gY+G7p2Ega2jDoWNoIGjDoG5nIFtDaHVybl0uDQotCUxv4bqhaSBo4bujcCDEkeG7k25nIGPDsyDhuqNuaCBoxrDhu59uZyDEkeG6v24gdOG7tyBs4buHIGtow6FjaCBow6BuZyBy4budaSBi4buPIGThu4tjaCB24bulIHZp4buFbiB0aMO0bmcgaGF5IGtow7RuZz8gTGnhu4d1IGjhu6NwIMSR4buTbmcgbmfhuq9uIGjhuqFuIHRow6wgdOG7tyBs4buHIGtow6FjaCBow6BuZyBy4budaSBi4buPIGPDoG5nIGNhby4NCi0JROG7i2NoIHbhu6UgSW50ZXJuZXQgY8OzIHTDoWMgxJHhu5luZyDEkeG6v24gdOG7tyBs4buHIHLhu51pIGLhu48ga2jDoWNoIGjDoG5nIGhheSBraMO0bmc/IEtow6FjaCBow6BuZyBz4butIGThu6VuZyBsb+G6oWkgZOG7i2NoIHbhu6UgSW50ZXJuZXQgbsOgbyBjw7Mga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyBk4buLY2ggduG7pSB2aeG7hW4gdGjDtG5nIGNhbyBuaOG6pXQ7IGThu4tjaCB24bulIEludGVybmV0IHRy4buxYyB0aeG6v3AgdGjDtG5nIHF1YSDEkWnhu4duIHRob+G6oWkgKERTTCkgaGF5IHPhu60gZOG7pW5nIGPDoXAgcXVhbmcgKEZpYmVyIE9wdGljKSBoYXkga2jDtG5nIHPhu60gZOG7pW5nIGThu4tjaCB24bulIEludGVybmV0Lg0KLQlIw6xuaCB0aOG7qWMgdGhhbmggdG/DoW4gY8OzIOG6o25oIGjGsOG7n25nIMSR4bq/biBraOG6oyBuxINuZyBy4budaSBi4buPIGPhu6dhIGtow6FjaCBow6BuZyBoYXkga2jDtG5nPyBUaGFuaCB0b8OhbiBxdWEgU8OpYyDEkWnhu4duIHThu60gaGF5IFRoYW5oIHRvw6FuIHF1YSB0aMawLCBUaOG6uyBnaGkgbuG7oywgQ2h1eeG7g24ga2hv4bqjbiBuZ8OibiBow6BuZy4NCi0JVsOgIGN14buRaSBjw7luZyBsw6AgxJHhu5kgdHXhu5VpIGPDsyDhuqNuaCBoxrDhu59uZyDEkeG6v24gdOG7tyBs4buHIHLhu51pIGLhu48gY+G7p2Ega2jDoWNoIGjDoG5nIGhheSBraMO0bmc/IExp4buHdSBuZ8aw4budaSBs4bubbiB0deG7lWkgdGjDrCBz4bq9IHLhu51pIGLhu48gZOG7i2NoIHbhu6Ugdmnhu4VuIHRow7RuZyBuaGnhu4F1IGjGoW4gbMOgIG5nxrDhu51pIHRy4bq7IHR14buVaS4NCg0KIyMgKioxLjQuIFBoxrDGoW5nIHBow6FwIG5naGnDqm4gY+G7qXUqKg0KTmdoacOqbiBj4bupdSBz4butIGThu6VuZyBjw6FjIHBoxrDGoW5nIHBow6FwIHRo4buRbmcga8OqIHbDoCBtw7QgaMOsbmggaOG7k2kgcXV5IG5o4buLIHBow6JuLCBiYW8gZ+G7k20gYmEgbcO0IGjDrG5oOiB4w6FjIHN14bqldCB0dXnhur9uIHTDrW5oLCBQcm9iaXQgdsOgIExvZ2l0LCDEkeG7gyBwaMOibiB0w61jaCBk4buvIGxp4buHdSBraMOhY2ggaMOgbmcgdHJvbmcgbmfDoG5oIHZp4buFbiB0aMO0bmcuIFRyxrDhu5tjIHRpw6puLCBk4buvIGxp4buHdSDEkcaw4bujYyB44butIGzDvSBi4bqxbmcgdGjhu5FuZyBrw6ogbcO0IHThuqMgbmjhurFtIHTDs20gdOG6r3QgxJHhurdjIMSRaeG7g20gY8ahIGLhuqNuIGPhu6dhIG3huqt1IGto4bqjbyBzw6F0LiBUaeG6v3AgdGhlbywgY8OhYyBr4bu5IHRodeG6rXQgdGjhu5FuZyBrw6ogc3V5IGx14bqtbiBuaMawIGtp4buDbSDEkeG7i25oIGNoaS1iw6xuaCBwaMawxqFuZyB2w6AgcGjDom4gdMOtY2ggdOG7tyBs4buHIMSRxrDhu6NjIMOhcCBk4bulbmcgxJHhu4MgxJHDoW5oIGdpw6EgbeG7kWkgbGnDqm4gaOG7hyBnaeG7r2EgY8OhYyBiaeG6v24uIEN14buRaSBjw7luZywgbcO0IGjDrG5oIGjhu5NpIHF1eSBMb2dpdCB2w6AgUHJvYml0IMSRxrDhu6NjIHRyaeG7g24ga2hhaSBuaOG6sW0geMOhYyDEkeG7i25oIG3hu6ljIMSR4buZIOG6o25oIGjGsOG7n25nIGPhu6dhIHThu6tuZyB54bq/dSB04buRIChuaMawIGxv4bqhaSBo4bujcCDEkeG7k25nLCBk4buLY2ggduG7pSBpbnRlcm5ldCwgaMOsbmggdGjhu6ljIHRoYW5oIHRvw6FuLCB2LnYuKSDEkeG6v24ga2jhuqMgbsSDbmcga2jDoWNoIGjDoG5nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UuIFBoxrDGoW5nIHBow6FwIG7DoHkgY2hvIHBow6lwIG5o4bqtbiBkaeG7h24gY8OhYyBuaMOzbSBraMOhY2ggaMOgbmcgY8OzIG5ndXkgY8ahIGNhbywgdOG7qyDEkcOzIGjhu5cgdHLhu6MgZG9hbmggbmdoaeG7h3AgeMOieSBk4buxbmcgY2hp4bq/biBsxrDhu6NjIGdp4buvIGNow6JuIGhp4buHdSBxdeG6oyBoxqFuLg0KDQojIyAqKjEuNS4gw50gbmdoxKlhIGPhu6dhIGLDoGkgbmdoacOqbiBj4bupdSoqDQpOZ2hpw6puIGPhu6l1IG7DoHkg4bupbmcgZOG7pW5nIGPDoWMgcGjGsMahbmcgcGjDoXAgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgxJHhu4tuaCBsxrDhu6NuZywgYmFvIGfhu5NtIHRo4buRbmcga8OqIG3DtCB04bqjLCBraeG7g20gxJHhu4tuaCBnaeG6oyB0aHV54bq/dCB2w6AgbcO0IGjDrG5oIGjhu5NpIHF1eSBuaOG7iyBwaMOibiAoTG9naXQsIFByb2JpdCksIMSR4buDIGThu7EgxJFvw6FuIGto4bqjIG7Eg25nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UgY+G7p2Ega2jDoWNoIGjDoG5nIHRyb25nIG5nw6BuaCB2aeG7hW4gdGjDtG5nLiBE4buxYSB0csOqbiBi4buZIGThu68gbGnhu4d1IGjGoW4gNy4wMDAga2jDoWNoIGjDoG5nLCBuZ2hpw6puIGPhu6l1IMSRw6MgeMOhYyDEkeG7i25oIHLDtSBjw6FjIHnhur91IHThu5EgbMOgbSB0xINuZyBy4bunaSBybyBy4budaSBi4buPIG5oxrAgbG/huqFpIGjhu6NwIMSR4buTbmcsIGjDrG5oIHRo4bupYyB0aGFuaCB0b8OhbiB2w6AgbG/huqFpIGThu4tjaCB24bulIHPhu60gZOG7pW5nLg0KDQpW4buBIG3hurd0IGtob2EgaOG7jWMsIG5naGnDqm4gY+G7qXUgbMOgIG1pbmggY2jhu6luZyBjaG8gcXV5IHRyw6xuaCBwaMOibiB0w61jaCBk4buvIGxp4buHdSBsb2dpYyB2w6AgY8OzIHRo4buDIHTDoWkgc+G7rSBk4bulbmcgdHJvbmcgY8OhYyBiw6BpIHRvw6FuIHTGsMahbmcgdOG7sSB24buBIGjDoG5oIHZpIGtow6FjaCBow6BuZy4gVuG7gSBt4bq3dCB0aOG7sWMgdGnhu4VuLCBr4bq/dCBxdeG6oyBnacO6cCBkb2FuaCBuZ2hp4buHcCB2aeG7hW4gdGjDtG5nIHjDoWMgxJHhu4tuaCBz4bubbSBuaMOzbSBraMOhY2ggaMOgbmcgcuG7p2kgcm8gY2FvLCB04burIMSRw7MgdHJp4buDbiBraGFpIGPDoWMgY2hp4bq/biBsxrDhu6NjIGdp4buvIGNow6JuIGhp4buHdSBxdeG6oyB2w6AgdGnhur90IGtp4buHbSBjaGkgcGjDrS4NCg0KLS0tDQoNCiMgKipDSMavxqBORyAyOiBNw5QgVOG6oiAtIFBIw4JOIFTDjUNIIEJJw4pOIFBI4bukIFRIVeG7mEMgVsOAIEPDgUMgQknhur5OIMSQ4buYQyBM4bqsUCoqDQoNClRyxrDhu5tjIGtoaSB0aeG6v24gaMOgbmggcGjDom4gdMOtY2gsIHTDoWMgZ2nhuqMgdGjhu7FjIGhp4buHbiBixrDhu5tjIHRp4buBbiB44butIGzDvSBk4buvIGxp4buHdSBuaOG6sW0gxJHhuqNtIGLhuqNvIHTDrW5oIGNow61uaCB4w6FjIHbDoCB0csOhbmggbOG7l2kgdHJvbmcgcXXDoSB0csOsbmggY2jhuqF5IG3DoyBSLg0KDQpgYGB7cn0NCiMgxJDhu41jIGThu68gbGnhu4d1IHbDoG8gUg0KZGYgPC0gcmVhZC5jc3YoIldBX0ZuLVVzZUNfLVRlbGNvLUN1c3RvbWVyLUNodXJuLmNzdiIpDQoNCiMgMS4gWOG7rSBsw70gVG90YWxDaGFyZ2VzDQpkZiRUb3RhbENoYXJnZXMgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZGYkVG90YWxDaGFyZ2VzKSkgDQpkZl9jbGVhbiA8LSBkZiAlPiUgZmlsdGVyKCFpcy5uYShUb3RhbENoYXJnZXMpKQ0KDQojIDIuIENodXnhu4NuIMSR4buVaSBow6BuZyBsb+G6oXQgY8OhYyBiaeG6v24gY2hhcmFjdGVyIHNhbmcgZmFjdG9yDQpkZl9jbGVhbiA8LSBkZl9jbGVhbiAlPiUNCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5jaGFyYWN0ZXIpICYgIWN1c3RvbWVySUQsIGFzLmZhY3RvcikpDQoNCiMgMy4gQ2h1eeG7g24gxJHhu5VpIFNlbmlvckNpdGl6ZW4gdOG7qyBz4buRICgwLCAxKSBzYW5nIGZhY3RvciAoIk5vIiwgIlllcyIpDQpkZl9jbGVhbiA8LSBkZl9jbGVhbiAlPiUNCiAgbXV0YXRlKFNlbmlvckNpdGl6ZW4gPSBhcy5mYWN0b3IoaWZlbHNlKFNlbmlvckNpdGl6ZW4gPT0gMSwgIlllcyIsICJObyIpKSkNCg0KIyA0LiBU4bqgTyBCSeG6vk4gTkjhu4ogUEjDgk4gQ0hPIE3DlCBIw4xOSCBI4buSSSBRVVkNCmRmX2NsZWFuJENodXJuX2JpbmFyeSA8LSBpZmVsc2UoZGZfY2xlYW4kQ2h1cm4gPT0gIlllcyIsIDEsIDApDQpgYGANCioqRGnhu4VuIGdp4bqjaToqKiDEkOG6p3UgdGnDqm4sIGThu68gbGnhu4d1IMSRxrDhu6NjIMSR4buNYyB2w6BvIFIuIEJp4bq/biBgVG90YWxDaGFyZ2VzYCDEkcaw4bujYyBwaMOhdCBoaeG7h24gY8OzIG3hu5l0IHPhu5EgZ2nDoSB0cuG7iyBi4buLIHRoaeG6v3UuIMSQ4buDIHjhu60gbMO9LCB0w6FjIGdp4bqjIMSRw6MgY2h1eeG7g24gY8OhYyBnacOhIHRy4buLIHRy4buRbmcgduG7gSBk4bqhbmcgYE5BYCB2w6Agc2F1IMSRw7MgbG/huqFpIGLhu48gY8OhYyBkw7JuZyBuw6B5IGto4buPaSBwaMOibiB0w61jaC4gVGnhur9wIHRoZW8sIGPDoWMgYmnhur9uIHbEg24gYuG6o24gKHRy4burIGBjdXN0b21lcklEYCkgxJHGsOG7o2MgY2h1eeG7g24gc2FuZyDEkeG7i25oIGThuqFuZyBgZmFjdG9yYC4gQmnhur9uIGBTZW5pb3JDaXRpemVuYCDEkcaw4bujYyBjaHV54buDbiDEkeG7lWkgdOG7qyBk4bqhbmcgc+G7kSAoMCwgMSkgc2FuZyBuaMOjbiAoIk5vIiwgIlllcyIpLiBDdeG7kWkgY8O5bmcsIGJp4bq/biBgQ2h1cm5fYmluYXJ5YCAoMC8xKSDEkcaw4bujYyB04bqhbyBz4bq1biDEkeG7gyBwaOG7pWMgduG7pSBjaG8gY8OhYyBtw7QgaMOsbmggaOG7k2kgcXV5IOG7nyBjw6FjIGNoxrDGoW5nIHNhdS4NCg0KIyMgKioyLjEuIEJp4bq/biBQaOG7pSBUaHXhu5ljIFThu7cgbOG7hyBy4budaSBi4buPIChDaHVybikqKg0KDQpC4bqjbmcgdOG6p24gc+G7kSB2w6AgdOG6p24gc3XhuqV0IGPhu6dhIGJp4bq/biBgQ2h1cm5gIGdpw7pwIGzGsOG7o25nIGjDs2EgbeG7qWMgxJHhu5kgbmdoacOqbSB0cuG7jW5nIGPhu6dhIHbhuqVuIMSR4buBIHLhu51pIGLhu48ga2jDoWNoIGjDoG5nLg0KDQpgYGB7ciBjaHVybi10YWJsZXMtY2gyfQ0Ka2FibGUoYWRkbWFyZ2lucyh0YWJsZShkZl9jbGVhbiRDaHVybikpLCBjYXB0aW9uID0gIkLhuqNuZyAyOiBC4bqjbmcgdOG6p24gc+G7kSBjaG8gYmnhur9uIENodXJuIikNCmthYmxlKHByb3AudGFibGUodGFibGUoZGZfY2xlYW4kQ2h1cm4pKSwgY2FwdGlvbiA9ICJC4bqjbmcgdOG6p24gc3XhuqV0ICh04bu3IGzhu4cpIGNobyBiaeG6v24gQ2h1cm4iLCBkaWdpdHMgPSA0KQ0KYGBgDQoNCmBgYHtyIGNodXJuLXBsb3QtYmFyLCBmaWcuY2FwPSJIw6xuaCAxLjE6IFBow6JuIHBo4buRaSBz4buRIGzGsOG7o25nIGtow6FjaCBow6BuZyB0aGVvIHTDrG5oIHRy4bqhbmcgcuG7nWkgYuG7jyJ9DQpnZ3Bsb3QoZGZfY2xlYW4sIGFlcyh4ID0gQ2h1cm4sIGZpbGwgPSBDaHVybikpICsNCiAgZ2VvbV9iYXIod2lkdGggPSAwLjYpICsNCiAgZ2VvbV90ZXh0KHN0YXQ9J2NvdW50JywgYWVzKGxhYmVsPS4uY291bnQuLiksIHZqdXN0PS0wLjUpICsNCiAgbGFicyh0aXRsZT0iUGjDom4gcGjhu5FpIHPhu5EgbMaw4bujbmcga2jDoWNoIGjDoG5nIHRoZW8gdMOsbmggdHLhuqFuZyBy4budaSBi4buPIiwgeD0iVMOsbmggdHLhuqFuZyBS4budaSBi4buPIiwgeT0iU+G7kSBsxrDhu6NuZyIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KYGBgDQoNCmBgYHtyIGNodXJuLXBsb3QtcGllLCBmaWcuY2FwPSJIw6xuaCAxLjI6IFThu7cgbOG7hyBraMOhY2ggaMOgbmcgdGhlbyB0w6xuaCB0cuG6oW5nIHLhu51pIGLhu48ifQ0KcGllX2RhdGFfY2h1cm4gPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkZl9jbGVhbiRDaHVybikpDQpjb2xuYW1lcyhwaWVfZGF0YV9jaHVybikgPC0gYygiU3RhdHVzIiwgIkNvdW50IikNCnBpZV9kYXRhX2NodXJuJFBlcmNlbnRhZ2UgPC0gc2NhbGVzOjpwZXJjZW50KHBpZV9kYXRhX2NodXJuJENvdW50IC8gc3VtKHBpZV9kYXRhX2NodXJuJENvdW50KSwgYWNjdXJhY3kgPSAwLjEpDQoNCmdncGxvdChwaWVfZGF0YV9jaHVybiwgYWVzKHggPSAiIiwgeSA9IENvdW50LCBmaWxsID0gU3RhdHVzKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQgPSAwKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBQZXJjZW50YWdlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSkpICsNCiAgbGFicyh0aXRsZSA9ICJU4bu3IGzhu4cga2jDoWNoIGjDoG5nIHRoZW8gdMOsbmggdHLhuqFuZyBy4budaSBi4buPIiwgZmlsbCA9ICJUw6xuaCB0cuG6oW5nIikgKw0KICB0aGVtZV92b2lkKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTApKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIEThu68gbGnhu4d1IGNobyB0aOG6pXkgY8OzICoqMSw4Njkga2jDoWNoIGjDoG5nICgyNi42JSkqKiDEkcOjIHLhu51pIGLhu48gZOG7i2NoIHbhu6UuIE3hurdjIGTDuSBuaMOzbSBraMOhY2ggaMOgbmcgdGnhur9wIHThu6VjIHPhu60gZOG7pW5nIGNoaeG6v20gxJFhIHPhu5EgKCoqNzMuNCUqKiksIHThu7cgbOG7hyBy4budaSBi4buPIHbhuqtuIOG7nyBt4bupYyBjYW8gdsOgIGzDoCBt4buZdCB24bqlbiDEkeG7gSBuZ2hpw6ptIHRy4buNbmcgY+G6p24gZ2nhuqNpIHF1eeG6v3QuIFPhu7EgY2jDqm5oIGzhu4djaCBnaeG7r2EgaGFpIG5ow7NtIChn4bqnbiAzOjEpIGNobyB0aOG6pXkgZOG7ryBsaeG7h3UgbeG6pXQgY8OibiBi4bqxbmcsIMSRw6J5IGzDoCBt4buZdCB54bq/dSB04buRIGvhu7kgdGh14bqtdCBj4bqnbiDEkcaw4bujYyB4ZW0geMOpdCBj4bqpbiB0aOG6rW4ga2hpIHjDonkgZOG7sW5nIGPDoWMgbcO0IGjDrG5oIGThu7EgYsOhbyDEkeG7gyB0csOhbmggdGhpw6puIHbhu4sgY2hvIG5ow7NtIMSRYSBz4buRLg0KDQojIyAqKjIuMi4gQmnhur9uIMSQ4buZYyBM4bqtcCoqDQoNCiMjIyAqKjIuMi4xLiBCaeG6v24gQ29udHJhY3QgKExv4bqhaSBo4bujcCDEkeG7k25nKSoqDQoNCmBgYHtyIGNvbnRyYWN0LXRhYmxlcy1jaDJ9DQprYWJsZShhZGRtYXJnaW5zKHRhYmxlKGRmX2NsZWFuJENvbnRyYWN0KSksIGNhcHRpb24gPSAiQuG6o25nIDM6IELhuqNuZyB04bqnbiBz4buRIGPhu6dhIGJp4bq/biBDb250cmFjdCIpDQprYWJsZShwcm9wLnRhYmxlKHRhYmxlKGRmX2NsZWFuJENvbnRyYWN0KSksIGNhcHRpb24gPSAiQuG6o25nIHThuqduIHN14bqldCAodOG7tyBs4buHKSBj4bunYSBiaeG6v24gQ29udHJhY3QiLCBkaWdpdHMgPSA0KQ0KYGBgDQoNCmBgYHtyIGNvbnRyYWN0LXBsb3QtYmFyLCBmaWcuY2FwPSJIw6xuaCAyLjE6IFBow6JuIHBo4buRaSBz4buRIGzGsOG7o25nIGtow6FjaCBow6BuZyB0aGVvIGxv4bqhaSBo4bujcCDEkeG7k25nIn0NCmdncGxvdChkZl9jbGVhbiwgYWVzKHggPSBDb250cmFjdCwgZmlsbCA9IENvbnRyYWN0KSkgKw0KICBnZW9tX2Jhcih3aWR0aCA9IDAuNikgKw0KICBnZW9tX3RleHQoc3RhdD0nY291bnQnLCBhZXMobGFiZWw9Li5jb3VudC4uKSwgdmp1c3Q9LTAuNSkgKw0KICBsYWJzKHRpdGxlPSJQaMOibiBwaOG7kWkgc+G7kSBsxrDhu6NuZyB0aGVvIGxv4bqhaSBo4bujcCDEkeG7k25nIiwgeD0iTG/huqFpIEjhu6NwIMSR4buTbmciLCB5PSJT4buRIGzGsOG7o25nIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KYGBge3IgY29udHJhY3QtcGxvdC1waWUsIGZpZy5jYXA9IkjDrG5oIDIuMjogVOG7tyBs4buHIGPDoWMgbG/huqFpIGjhu6NwIMSR4buTbmcifQ0KcGllX2RhdGFfY29udHJhY3QgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkZl9jbGVhbiRDb250cmFjdCkpDQpjb2xuYW1lcyhwaWVfZGF0YV9jb250cmFjdCkgPC0gYygiQ29udHJhY3QiLCAiQ291bnQiKQ0KcGllX2RhdGFfY29udHJhY3QkUGVyY2VudGFnZSA8LSBzY2FsZXM6OnBlcmNlbnQocGllX2RhdGFfY29udHJhY3QkQ291bnQgLyBzdW0ocGllX2RhdGFfY29udHJhY3QkQ291bnQpLCBhY2N1cmFjeSA9IDAuMSkNCg0KZ2dwbG90KHBpZV9kYXRhX2NvbnRyYWN0LCBhZXMoeCA9ICIiLCB5ID0gQ291bnQsIGZpbGwgPSBDb250cmFjdCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcigieSIsIHN0YXJ0ID0gMCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gUGVyY2VudGFnZSksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpKSArDQogIGxhYnModGl0bGUgPSAiVOG7tyBs4buHIGPDoWMgbG/huqFpIGjhu6NwIMSR4buTbmciLCBmaWxsID0gIkjhu6NwIMSR4buTbmciKSArDQogIHRoZW1lX3ZvaWQoYmFzZV9zaXplID0gMTQpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogTmjDs20ga2jDoWNoIGjDoG5nIHPhu60gZOG7pW5nIGjhu6NwIMSR4buTbmcgdGhlbyB0aMOhbmcgY2hp4bq/bSB04bu3IGzhu4cgw6FwIMSR4bqjbyB24bubaSAqKjMsODc1IG5nxrDhu51pICg1NS4xJSkqKi4gxJDDonkgbMOgIG5ow7NtIGPDsyB0w61uaCBsaW5oIGhv4bqhdCBjYW8gbmjGsG5nIGPFqW5nIGzDoCBuaMOzbSB0aeG7gW0g4bqpbiBy4bunaSBybyBy4budaSBi4buPIGzhu5tuIG5o4bqldCBkbyBraMO0bmcgY8OzIGNhbSBr4bq/dCBkw6BpIGjhuqFuLiBDw6FjIGjhu6NwIMSR4buTbmcgZMOgaSBo4bqhbiAoMSBuxINtIHbDoCAyIG7Eg20pIGNoaeG6v20gdOG7tyBs4buHIHRo4bqlcCBoxqFuLCBs4bqnbiBsxrDhu6N0IGzDoCAqKjIwLjklKiogdsOgICoqMjQuMCUqKi4NCg0KIyMjICoqMi4yLjIuIEJp4bq/biBJbnRlcm5ldCBTZXJ2aWNlIChE4buLY2ggduG7pSBJbnRlcm5ldCkqKg0KDQpgYGB7ciBpbnRlcm5ldC10YWJsZXMtY2gyfQ0Ka2FibGUoYWRkbWFyZ2lucyh0YWJsZShkZl9jbGVhbiRJbnRlcm5ldFNlcnZpY2UpKSwgY2FwdGlvbiA9ICJC4bqjbmcgNDogQuG6o25nIHThuqduIHPhu5EgY+G7p2EgYmnhur9uIEludGVybmV0IFNlcnZpY2UiKQ0Ka2FibGUocHJvcC50YWJsZSh0YWJsZShkZl9jbGVhbiRJbnRlcm5ldFNlcnZpY2UpKSwgY2FwdGlvbiA9ICJC4bqjbmcgdOG6p24gc3XhuqV0IGPhu6dhIGJp4bq/biBJbnRlcm5ldCBTZXJ2aWNlIiwgZGlnaXRzID0gNCkNCmBgYA0KDQpgYGB7ciBpbnRlcm5ldC1wbG90LWJhciwgZmlnLmNhcD0iSMOsbmggMy4xOiBQaMOibiBwaOG7kWkgc+G7kSBsxrDhu6NuZyBraMOhY2ggaMOgbmcgdGhlbyBk4buLY2ggduG7pSBJbnRlcm5ldCJ9DQpnZ3Bsb3QoZGZfY2xlYW4sIGFlcyh4ID0gSW50ZXJuZXRTZXJ2aWNlLCBmaWxsID0gSW50ZXJuZXRTZXJ2aWNlKSkgKw0KICBnZW9tX2Jhcih3aWR0aCA9IDAuNikgKw0KICBnZW9tX3RleHQoc3RhdD0nY291bnQnLCBhZXMobGFiZWw9Li5jb3VudC4uKSwgdmp1c3Q9LTAuNSkgKw0KICBsYWJzKHRpdGxlPSJQaMOibiBwaOG7kWkgc+G7kSBsxrDhu6NuZyB0aGVvIGThu4tjaCB24bulIEludGVybmV0IiwgeD0iROG7i2NoIHbhu6UgSW50ZXJuZXQiLCB5PSJT4buRIGzGsOG7o25nIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KYGBge3IgaW50ZXJuZXQtcGxvdC1waWUsIGZpZy5jYXA9IkjDrG5oIDMuMjogVOG7tyBs4buHIGPDoWMgbG/huqFpIGThu4tjaCB24bulIEludGVybmV0In0NCnBpZV9kYXRhX2ludGVybmV0IDwtIGFzLmRhdGEuZnJhbWUodGFibGUoZGZfY2xlYW4kSW50ZXJuZXRTZXJ2aWNlKSkNCmNvbG5hbWVzKHBpZV9kYXRhX2ludGVybmV0KSA8LSBjKCJTZXJ2aWNlIiwgIkNvdW50IikNCnBpZV9kYXRhX2ludGVybmV0JFBlcmNlbnRhZ2UgPC0gc2NhbGVzOjpwZXJjZW50KHBpZV9kYXRhX2ludGVybmV0JENvdW50IC8gc3VtKHBpZV9kYXRhX2ludGVybmV0JENvdW50KSwgYWNjdXJhY3kgPSAwLjEpDQoNCmdncGxvdChwaWVfZGF0YV9pbnRlcm5ldCwgYWVzKHggPSAiIiwgeSA9IENvdW50LCBmaWxsID0gU2VydmljZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcigieSIsIHN0YXJ0ID0gMCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gUGVyY2VudGFnZSksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpKSArDQogIGxhYnModGl0bGUgPSAiVOG7tyBs4buHIGPDoWMgZOG7i2NoIHbhu6UgSW50ZXJuZXQiLCBmaWxsID0gIkThu4tjaCB24bulIikgKw0KICB0aGVtZV92b2lkKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIEThu4tjaCB24bulIGPDoXAgcXVhbmcgKGBGaWJlciBvcHRpY2ApIGzDoCBwaOG7lSBiaeG6v24gbmjhuqV0ICgqKjQ0LjAlKiopLCBwaOG6o24gw6FuaCBuaHUgY+G6p3UgduG7gSBpbnRlcm5ldCB04buRYyDEkeG7mSBjYW8uIEPDsyDEkeG6v24gKioyMS42JSoqIGtow6FjaCBow6BuZyBraMO0bmcgc+G7rSBk4bulbmcgZOG7i2NoIHbhu6UgaW50ZXJuZXQsIHThuqFvIHRow6BuaCBt4buZdCBwaMOibiBraMO6YyBraMOhY2ggaMOgbmcgcmnDqm5nIGJp4buHdC4NCg0KIyMjICoqMi4yLjMuIEJp4bq/biBQYXltZW50IE1ldGhvZCAoUGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuKSoqDQoNCmBgYHtyIHBheW1lbnQtdGFibGVzLWNoMn0NCmthYmxlKGFkZG1hcmdpbnModGFibGUoZGZfY2xlYW4kUGF5bWVudE1ldGhvZCkpLCBjYXB0aW9uID0gIkLhuqNuZyA1OiBC4bqjbmcgdOG6p24gc+G7kSBj4bunYSBiaeG6v24gUGF5bWVudCBNZXRob2QiKQ0Ka2FibGUocHJvcC50YWJsZSh0YWJsZShkZl9jbGVhbiRQYXltZW50TWV0aG9kKSksIGNhcHRpb24gPSAiQuG6o25nIHThuqduIHN14bqldCBj4bunYSBiaeG6v24gUGF5bWVudE1ldGhvZCIsIGRpZ2l0cyA9IDQpDQpgYGANCg0KYGBge3IgcGF5bWVudC1wbG90LWJhciwgZmlnLmNhcD0iSMOsbmggNC4xOiBQaMOibiBwaOG7kWkgc+G7kSBsxrDhu6NuZyB0aGVvIHBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiJ9DQpnZ3Bsb3QoZGZfY2xlYW4sIGFlcyh4ID0gUGF5bWVudE1ldGhvZCwgZmlsbCA9IFBheW1lbnRNZXRob2QpKSArDQogIGdlb21fYmFyKHdpZHRoID0gMC43KSArICAjIDwtLS0gVEjDik0gROG6pFUgQ+G7mE5HIOG7niDEkMOCWQ0KICBnZW9tX3RleHQoc3RhdD0nY291bnQnLCBhZXMobGFiZWw9Li5jb3VudC4uKSwgdmp1c3Q9LTAuNSkgKw0KICBsYWJzKHRpdGxlPSJQaMOibiBwaOG7kWkgdGhlbyBwaMawxqFuZyB0aOG7qWMgdGhhbmggdG/DoW4iLCB4PSJQaMawxqFuZyB0aOG7qWMiLCB5PSJT4buRIGzGsOG7o25nIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEyKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMTUsIGhqdXN0ID0gMSksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KYGBge3IgcGF5bWVudC1wbG90LXBpZSwgZmlnLmNhcD0iSMOsbmggNC4yOiBU4bu3IGzhu4cgY8OhYyBwaMawxqFuZyB0aOG7qWMgdGhhbmggdG/DoW4ifQ0KcGllX2RhdGFfcGF5bWVudCA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKGRmX2NsZWFuJFBheW1lbnRNZXRob2QpKQ0KY29sbmFtZXMocGllX2RhdGFfcGF5bWVudCkgPC0gYygiTWV0aG9kIiwgIkNvdW50IikNCnBpZV9kYXRhX3BheW1lbnQkUGVyY2VudGFnZSA8LSBzY2FsZXM6OnBlcmNlbnQocGllX2RhdGFfcGF5bWVudCRDb3VudCAvIHN1bShwaWVfZGF0YV9wYXltZW50JENvdW50KSwgYWNjdXJhY3kgPSAwLjEpDQoNCmdncGxvdChwaWVfZGF0YV9wYXltZW50LCBhZXMoeCA9ICIiLCB5ID0gQ291bnQsIGZpbGwgPSBNZXRob2QpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIoInkiLCBzdGFydCA9IDApICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBlcmNlbnRhZ2UpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSkgKw0KICBsYWJzKHRpdGxlID0gIlThu7cgbOG7hyBjw6FjIHBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiIsIGZpbGwgPSAiUGjGsMahbmcgdGjhu6ljIikgKw0KICB0aGVtZV92b2lkKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIGBFbGVjdHJvbmljIGNoZWNrYCBsw6AgcGjGsMahbmcgdGjhu6ljIHBo4buVIGJp4bq/biBuaOG6pXQgKCoqMzMuNiUqKikuIMSQYSBz4buRIGtow6FjaCBow6BuZyAoKio1Ni41JSoqKSB24bqrbiBkw7luZyBjw6FjIHBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiB0aOG7pyBjw7RuZy4gxJBp4buBdSBuw6B5IGPDsyB0aOG7gyBsw6AgbeG7mXQgeeG6v3UgdOG7kSBy4bunaSByby4NCg0KIyMjICoqMi4yLjQuIEJp4bq/biBTZW5pb3JDaXRpemVuIChOZ8aw4budaSBjYW8gdHXhu5VpKSoqDQoNCmBgYHtyIHNlbmlvci10YWJsZXMtY2gyfQ0Ka2FibGUoYWRkbWFyZ2lucyh0YWJsZShkZl9jbGVhbiRTZW5pb3JDaXRpemVuKSksIGNhcHRpb24gPSAiQuG6o25nIDY6IELhuqNuZyB04bqnbiBz4buRIGPhu6dhIGJp4bq/biBTZW5pb3JDaXRpemVuIikNCmthYmxlKHByb3AudGFibGUodGFibGUoZGZfY2xlYW4kU2VuaW9yQ2l0aXplbikpLCBjYXB0aW9uID0gIkLhuqNuZyB04bqnbiBzdeG6pXQgY+G7p2EgYmnhur9uIFNlbmlvckNpdGl6ZW4iLCBkaWdpdHMgPSA0KQ0KYGBgDQoNCmBgYHtyIHNlbmlvci1wbG90LWJhciwgZmlnLmNhcD0iSMOsbmggNS4xOiBQaMOibiBwaOG7kWkgc+G7kSBsxrDhu6NuZyBraMOhY2ggaMOgbmcgdGhlbyBuaMOzbSB0deG7lWkifQ0KZ2dwbG90KGRmX2NsZWFuLCBhZXMoeCA9IFNlbmlvckNpdGl6ZW4sIGZpbGwgPSBTZW5pb3JDaXRpemVuKSkgKw0KICBnZW9tX2Jhcih3aWR0aCA9IDAuNikgKw0KICBnZW9tX3RleHQoc3RhdD0nY291bnQnLCBhZXMobGFiZWw9Li5jb3VudC4uKSwgdmp1c3Q9LTAuNSkgKw0KICBsYWJzKHRpdGxlPSJQaMOibiBwaOG7kWkgdGhlbyBuaMOzbSB0deG7lWkiLCB4PSJMw6AgbmfGsOG7nWkgY2FvIHR14buVaT8iLCB5PSJT4buRIGzGsOG7o25nIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KYGBge3Igc2VuaW9yLXBsb3QtcGllLCBmaWcuY2FwPSJIw6xuaCA1LjI6IFThu7cgbOG7hyBraMOhY2ggaMOgbmcgdGhlbyBuaMOzbSB0deG7lWkifQ0KcGllX2RhdGFfc2VuaW9yIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoZGZfY2xlYW4kU2VuaW9yQ2l0aXplbikpDQpjb2xuYW1lcyhwaWVfZGF0YV9zZW5pb3IpIDwtIGMoIkdyb3VwIiwgIkNvdW50IikNCnBpZV9kYXRhX3NlbmlvciRQZXJjZW50YWdlIDwtIHNjYWxlczo6cGVyY2VudChwaWVfZGF0YV9zZW5pb3IkQ291bnQgLyBzdW0ocGllX2RhdGFfc2VuaW9yJENvdW50KSwgYWNjdXJhY3kgPSAwLjEpDQoNCmdncGxvdChwaWVfZGF0YV9zZW5pb3IsIGFlcyh4ID0gIiIsIHkgPSBDb3VudCwgZmlsbCA9IEdyb3VwKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQgPSAwKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBQZXJjZW50YWdlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSkpICsNCiAgbGFicyh0aXRsZSA9ICJU4bu3IGzhu4cga2jDoWNoIGjDoG5nIGNhbyB0deG7lWkiLCBmaWxsID0gIk5ow7NtIHR14buVaSIpICsNCiAgdGhlbWVfdm9pZChiYXNlX3NpemUgPSAxNCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBOaMOzbSBraMO0bmcgcGjhuqNpIG5nxrDhu51pIGNhbyB0deG7lWkgY2hp4bq/bSDEkeG6oWkgxJFhIHPhu5EgKCoqODMuOCUqKiksIHRyb25nIGtoaSBuaMOzbSBuZ8aw4budaSBjYW8gdHXhu5VpIGNo4buJIGNoaeG6v20gKioxNi4yJSoqLg0KDQotLS0NCg0KIyAqKkNIxq/GoE5HIDM6IFBIw4JOIFTDjUNIIE3hu5BJIFFVQU4gSOG7hiBHSeG7rkEgSEFJIEJJ4bq+TiDEkOG7ik5IIFTDjU5IKioNCg0KYGBge3IgcHJlcGFyZS1jaDMsIGluY2x1ZGU9RkFMU0V9DQojIEfDoW4gbmjDo24gY2hvIGPDoWMgYmnhur9uIMSR4buDIGhp4buDbiB0aOG7iyB0cm9uZyBi4bqjbmcgdsOgIGJp4buDdSDEkeG7kyBk4buFIMSR4buNYyBoxqFuDQpkZl9jbGVhbiRDaHVybl9sYWJlbGVkIDwtIGZhY3RvcihkZl9jbGVhbiRDaHVybiwgbGV2ZWxzID0gYygiTm8iLCAiWWVzIiksIGxhYmVscyA9IGMoIktow7RuZyBy4budaSBi4buPIiwgIlLhu51pIGLhu48iKSkNCmBgYA0KDQojIyAqKjMuMSBDaHVybiB2w6AgQ29udHJhY3QgKExv4bqhaSBo4bujcCDEkeG7k25nKSoqDQoNCiMjIyAqKjMuMS4xLiBC4bqjbmcgdOG6p24gc+G7kSoqDQpgYGB7ciB0YWJsZS1jb250cmFjdC1jaHVybi1jaDN9DQpjaHVybl9jb250cmFjdF90YWJsZSA8LSB0YWJsZShkZl9jbGVhbiRDb250cmFjdCwgZGZfY2xlYW4kQ2h1cm4pDQpjYXQoIkLhuqNuZyB04bqnbiBz4buRIGNow6lvIGdp4buvYSBDb250cmFjdCB2w6AgQ2h1cm46XG4iKQ0KYWRkbWFyZ2lucyhjaHVybl9jb250cmFjdF90YWJsZSkNCmBgYA0KDQojIyMgKiozLjEuMi4gS2nhu4NtIMSR4buLbmggQ2hpLWLDrG5oIHBoxrDGoW5nKioNCg0KKipHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoqKg0KDQotICAgKiokSF8wJCoqOiBMb+G6oWkgaOG7o3AgxJHhu5NuZyB2w6Agdmnhu4djIHLhu51pIGLhu48gbMOgIGhhaSBiaeG6v24gxJHhu5ljIGzhuq1wLg0KLSAgICoqJEhfMSQqKjogTG/huqFpIGjhu6NwIMSR4buTbmcgdsOgIHZp4buHYyBy4budaSBi4buPIGPDsyBsacOqbiBxdWFuIMSR4bq/biBuaGF1Lg0KDQpgYGB7ciBjaGlzcS1jb250cmFjdC1jaHVybi1jaDN9DQpjaGlfY29udHJhY3QgPC0gY2hpc3EudGVzdChjaHVybl9jb250cmFjdF90YWJsZSkNCnByaW50KGNoaV9jb250cmFjdCkNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBwLXZhbHVlIDwgMi4yZS0xNiwgYsOhYyBi4buPICRIXzAkLiBDw7MgbeG7mXQgbeG7kWkgbGnDqm4gaOG7hyB0aOG7kW5nIGvDqiBj4buxYyBr4buzIG3huqFuaCBt4bq9IGdp4buvYSBsb+G6oWkgaOG7o3AgxJHhu5NuZyB2w6Aga2jhuqMgbsSDbmcgcuG7nWkgYuG7jy4NCg0KIyMjICoqMy4xLjMuIFRy4buxYyBxdWFuIGjDs2EgTeG7kWkgcXVhbiBo4buHKioNCmBgYHtyIG1vc2FpYy1jb250cmFjdC1jaHVybiwgZmlnLmNhcD0iSMOsbmggNzogQmnhu4N1IMSR4buTIE1vc2FpYyBnaeG7r2EgQ29udHJhY3QgdsOgIENodXJuIn0NCmdncGxvdChkYXRhID0gZGZfY2xlYW4pICsNCiAgZ2VvbV9tb3NhaWMoYWVzKHggPSBwcm9kdWN0KENvbnRyYWN0LCBDaHVybiksIGZpbGw9Q2h1cm4pKSArDQogIGxhYnModGl0bGU9Ik3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgTG/huqFpIGjhu6NwIMSR4buTbmcgdsOgIFThu7cgbOG7hyBy4budaSBi4buPIiwgeD0iTG/huqFpIGjhu6NwIMSR4buTbmciLCB5PSJU4bu3IGzhu4cgQ2h1cm4iKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBCaeG7g3UgxJHhu5MgTW9zYWljIGNobyB0aOG6pXkgcsO1IHLDoG5nIHBo4bqnbiBkaeG7h24gdMOtY2ggxJHhuqFpIGRp4buHbiBjaG8ga2jDoWNoIGjDoG5nIHLhu51pIGLhu48gKG3DoHUgxJHhu48pIGNoaeG6v20gdOG7tyB0cuG7jW5nIHLhuqV0IGzhu5tuIHRyb25nIG5ow7NtIGBNb250aC10by1tb250aGAgdsOgIGPhu7FjIGvhu7Mgbmjhu48gdHJvbmcgbmjDs20gYFR3byB5ZWFyYC4NCg0KIyMjICoqMy4xLjQuIFBow6JuIHTDrWNoIHNvIHPDoW5oIGNoaSB0aeG6v3QqKg0KDQojIyMjICoqU28gc8OhbmggJ09uZSB5ZWFyJyB2cy4gJ01vbnRoLXRvLW1vbnRoJyoqDQoNCioqYS4gS2nhu4NtIMSR4buLbmggSGnhu4d1IHThu7cgbOG7hyoqDQoNCioqR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6KioNCg0KLSAgICoqJEhfMCQqKjogVOG7tyBs4buHIHLhu51pIGLhu48g4bufIG5ow7NtICdPbmUgeWVhcicgdsOgICdNb250aC10by1tb250aCcgbMOgIGLhurFuZyBuaGF1ICgkcF8xIC0gcF8yID0gMCQpLg0KLSAgICoqJEhfMSQqKjogVOG7tyBs4buHIHLhu51pIGLhu48g4bufIG5ow7NtICdPbmUgeWVhcicgdGjhuqVwIGjGoW4gbmjDs20gJ01vbnRoLXRvLW1vbnRoJyAoJHBfMSAtIHBfMiA8IDAkKS4NCg0KYGBge3IgcHJvcC10ZXN0LTF5cn0NCmNvbnRyYWN0X3N1Yl8xeXIgPC0gZGZfY2xlYW4gJT4lIA0KICBmaWx0ZXIoQ29udHJhY3QgJWluJSBjKCJNb250aC10by1tb250aCIsICJPbmUgeWVhciIpKSAlPiUNCiAgZHJvcGxldmVscygpDQp0YWJsZV8xeXIgPC0gdGFibGUoY29udHJhY3Rfc3ViXzF5ciRDb250cmFjdCwgY29udHJhY3Rfc3ViXzF5ciRDaHVybikNCnByb3BfdGVzdF8xeXIgPC0gcHJvcC50ZXN0KHggPSB0YWJsZV8xeXJbLCAiWWVzIl0sIG4gPSByb3dTdW1zKHRhYmxlXzF5ciksIGFsdGVybmF0aXZlPSJsZXNzIiwgY29ycmVjdD1GQUxTRSkNCnByaW50KHByb3BfdGVzdF8xeXIpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogWMOhYyBzdeG6pXQgcuG7nWkgYuG7jyDhu58gbmjDs20gaOG7o3AgxJHhu5NuZyAxIG7Eg20gbMOgIGByIHNjYWxlczo6cGVyY2VudChwcm9wX3Rlc3RfMXlyJGVzdGltYXRlWzJdLCBhY2N1cmFjeT0wLjEpYCwgdGjhuqVwIGjGoW4gxJHDoW5nIGvhu4Mgc28gduG7m2kgbmjDs20gaOG7o3AgxJHhu5NuZyB0aMOhbmcgbMOgIGByIHNjYWxlczo6cGVyY2VudChwcm9wX3Rlc3RfMXlyJGVzdGltYXRlWzFdLCBhY2N1cmFjeT0wLjEpYC4gVuG7m2kgcC12YWx1ZSA8IDIuMmUtMTYsIHPhu7Ega2jDoWMgYmnhu4d0IG7DoHkgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBjYW8uDQoNCioqYi4gUuG7p2kgcm8gVMawxqFuZyDEkeG7kWkgKFJSKSoqDQpgYGB7ciByci0xeXJ9DQpycl8xeXIgPC0gcmlza3JhdGlvKHRhYmxlXzF5ciwgbWV0aG9kPSJ3YWxkIikNCnByaW50KHJyXzF5cikNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBU4bu3IGzhu4cgUuG7p2kgcm8gVMawxqFuZyDEkeG7kWkgKFJSKSBsw6AgYHIgcm91bmQocnJfMXlyJG1lYXN1cmVbMiwxXSwgMylgLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBuZ3V5IGPGoSBy4budaSBi4buPIGPhu6dhIG5ow7NtIGjhu6NwIMSR4buTbmcgMSBuxINtIGNo4buJIGLhurFuZyBraG/huqNuZyAyNi40JSBzbyB24bubaSBuaMOzbSBo4bujcCDEkeG7k25nIHRow6FuZy4gS2hv4bqjbmcgxrDhu5tjIGzGsOG7o25nIGNobyBSUiB24bubaSDEkeG7mSB0aW4gY+G6rXkgOTUlIGzDoCB04burIGByIHJvdW5kKHJyXzF5ciRtZWFzdXJlWzIsMl0sIDMpYCDEkeG6v24gYHIgcm91bmQocnJfMXlyJG1lYXN1cmVbMiwzXSwgMylgLiBWw6wga2hv4bqjbmcgbsOgeSBraMO0bmcgY2jhu6lhIDEsIGvhur90IHF14bqjIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNCioqYy4gVOG7tyBz4buRIENow6puaCAoT1IpKioNCmBgYHtyIG9yLTF5cn0NCm9yXzF5ciA8LSBvZGRzcmF0aW8odGFibGVfMXlyLCBtZXRob2Q9IndhbGQiKQ0KcHJpbnQob3JfMXlyKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIFThu7cgc+G7kSBDaMOqbmggKE9SKSBsw6AgYHIgcm91bmQob3JfMXlyJG1lYXN1cmVbMiwxXSwgMylgLiDEkGnhu4F1IG7DoHkgY8OzIG5naMSpYSBsw6Agb2RkcyBy4budaSBi4buPIGPhu6dhIG5ow7NtIGjhu6NwIMSR4buTbmcgMSBuxINtIHRo4bqlcCBoxqFuLCBjaOG7iSBi4bqxbmcga2hv4bqjbmcgMTcuNCUgc28gduG7m2kgb2RkcyBj4bunYSBuaMOzbSBo4bujcCDEkeG7k25nIHRow6FuZy4NCg0KIyMjIyAqKlNvIHPDoW5oICdUd28geWVhcicgdnMuICdNb250aC10by1tb250aCcqKg0KDQoqKmEuIEtp4buDbSDEkeG7i25oIEhp4buHdSB04bu3IGzhu4cqKg0KDQoqKkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oOioqDQoNCi0gICAqKiRIXzAkKio6IFThu7cgbOG7hyBy4budaSBi4buPIOG7nyBuaMOzbSAnVHdvIHllYXInIHbDoCAnTW9udGgtdG8tbW9udGgnIGzDoCBi4bqxbmcgbmhhdSAoJHBfMSAtIHBfMiA9IDAkKS4NCi0gICAqKiRIXzEkKio6IFThu7cgbOG7hyBy4budaSBi4buPIOG7nyBuaMOzbSAnVHdvIHllYXInIHRo4bqlcCBoxqFuIG5ow7NtICdNb250aC10by1tb250aCcgKCRwXzEgLSBwXzIgPCAwJCkuDQoNCmBgYHtyIHByb3AtdGVzdC0yeXJ9DQpjb250cmFjdF9zdWJfMnlyIDwtIGRmX2NsZWFuICU+JSANCiAgZmlsdGVyKENvbnRyYWN0ICVpbiUgYygiTW9udGgtdG8tbW9udGgiLCAiVHdvIHllYXIiKSkgJT4lDQogIGRyb3BsZXZlbHMoKQ0KdGFibGVfMnlyIDwtIHRhYmxlKGNvbnRyYWN0X3N1Yl8yeXIkQ29udHJhY3QsIGNvbnRyYWN0X3N1Yl8yeXIkQ2h1cm4pDQpwcm9wX3Rlc3RfMnlyIDwtIHByb3AudGVzdCh4ID0gdGFibGVfMnlyWywgIlllcyJdLCBuID0gcm93U3Vtcyh0YWJsZV8yeXIpLCBhbHRlcm5hdGl2ZT0ibGVzcyIsIGNvcnJlY3Q9RkFMU0UpDQpwcmludChwcm9wX3Rlc3RfMnlyKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIFjDoWMgc3XhuqV0IHLhu51pIGLhu48g4bufIG5ow7NtIGjhu6NwIMSR4buTbmcgMiBuxINtIGNo4buJIGzDoCBgciBzY2FsZXM6OnBlcmNlbnQocHJvcF90ZXN0XzJ5ciRlc3RpbWF0ZVsyXSwgYWNjdXJhY3k9MC4xKWAuIFbhu5tpIHAtdmFsdWUgPCAyLjJlLTE2LCB04bu3IGzhu4cgbsOgeSB0aOG6pXAgaMahbiBy4bqldCBuaGnhu4F1IHNvIHbhu5tpIG5ow7NtIGjhu6NwIMSR4buTbmcgdGjDoW5nIG3hu5l0IGPDoWNoIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNCioqYi4gUuG7p2kgcm8gVMawxqFuZyDEkeG7kWkgKFJSKSoqDQpgYGB7ciByci0yeXJ9DQpycl8yeXIgPC0gcmlza3JhdGlvKHRhYmxlXzJ5ciwgbWV0aG9kPSJ3YWxkIikNCnByaW50KHJyXzJ5cikNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBSUiA9IGByIHJvdW5kKHJyXzJ5ciRtZWFzdXJlWzIsMV0sIDMpYC4gTmd1eSBjxqEgcuG7nWkgYuG7jyBj4bunYSBraMOhY2ggaMOgbmcgY8OzIGjhu6NwIMSR4buTbmcgMiBuxINtIGNo4buJIGLhurFuZyA2LjclIHNvIHbhu5tpIGtow6FjaCBow6BuZyBo4bujcCDEkeG7k25nIHRow6FuZy4gS2hv4bqjbmcgdGluIGPhuq15IDk1JSBbMC4wNTAsIDAuMDg5XSBjaG8gdGjhuqV5IMSRw6J5IGzDoCBt4buZdCB54bq/dSB04buRIGLhuqNvIHbhu4cgcuG6pXQgbeG6oW5oLg0KDQoqKmMuIFThu7cgc+G7kSBDaMOqbmggKE9SKSoqDQpgYGB7ciBvci0yeXJ9DQpvcl8yeXIgPC0gb2Rkc3JhdGlvKHRhYmxlXzJ5ciwgbWV0aG9kPSJ3YWxkIikNCnByaW50KG9yXzJ5cikNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBPUiA9IGByIHJvdW5kKG9yXzJ5ciRtZWFzdXJlWzIsMV0sIDMpYC4gT2RkcyBy4budaSBi4buPIGPhu6dhIG5ow7NtIGjhu6NwIMSR4buTbmcgMiBuxINtIGNo4buJIGLhurFuZyA0LjElIHNvIHbhu5tpIG5ow7NtIGjhu6NwIMSR4buTbmcgdGjDoW5nLCBraOG6s25nIMSR4buLbmggxJHDonkgbMOgIHnhur91IHThu5EgZ2nhu68gY2jDom4ga2jDoWNoIGjDoG5nIGhp4buHdSBxdeG6oyBuaOG6pXQuDQoNCiMjIyAqKjMuMS41LiBLaG/huqNuZyDGsOG7m2MgbMaw4bujbmcgdOG7tyBs4buHKioNCg0KKirGr+G7m2MgbMaw4bujbmcgdOG7tyBs4buHIHLhu51pIGLhu48gY2hvIG5ow7NtIGjhu6NwIMSR4buTbmcgdGhlbyB0aMOhbmcgKGBNb250aC10by1tb250aGApKioNCg0KKipHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoqKg0KDQotICAgKiokSF8wJCoqOiBU4bu3IGzhu4cgcuG7nWkgYuG7jyBj4bunYSBuaMOzbSBo4bujcCDEkeG7k25nIHRoZW8gdGjDoW5nIGLhurFuZyB04bu3IGzhu4cgdHJ1bmcgYsOsbmggY+G7p2EgdOG7lW5nIHRo4buDIChraG/huqNuZyAyNyUpLCB04bupYyBsw6AgJHAgPSAwLjI3JC4NCg0KLSAgICoqJEhfMSQqKjogVOG7tyBs4buHIHLhu51pIGLhu48gY+G7p2EgbmjDs20gaOG7o3AgxJHhu5NuZyB0aGVvIHRow6FuZyBraMOhYyAyNyUgKCRwIFxuZXEgMC4yNyQpLg0KDQpgYGB7ciBwcm9wLXRlc3QtbTJtfQ0KY291bnRfbTJtIDwtIGNodXJuX2NvbnRyYWN0X3RhYmxlWyJNb250aC10by1tb250aCIsICJZZXMiXQ0KdG90YWxfbTJtIDwtIHN1bShjaHVybl9jb250cmFjdF90YWJsZVsiTW9udGgtdG8tbW9udGgiLCBdKQ0KcHJvcC50ZXN0KHggPSBjb3VudF9tMm0sIG4gPSB0b3RhbF9tMm0sIHAgPSAwLjI3LCBjb3JyZWN0ID0gRkFMU0UpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogS+G6v3QgcXXhuqMga2nhu4NtIMSR4buLbmggY2hvIHRo4bqleSBwLXZhbHVlIDwgMi4yZS0xNiwgcuG6pXQgbmjhu48gaMahbiBt4bupYyDDvSBuZ2jEqWEgMC4wNS4gxJBp4buBdSBuw6B5IGNobyB0aOG6pXkgY8OzIGLhurFuZyBjaOG7qW5nIG3huqFuaCBt4bq9IMSR4buDIGLDoWMgYuG7jyBnaeG6oyB0aHV54bq/dCAkSF8wJC4gVOG7tyBs4buHIHLhu51pIGLhu48gdGjhu7FjIHThur8gdHJvbmcgbeG6q3UgY+G7p2EgbmjDs20gbsOgeSBsw6AgKio0Mi43JSoqLCBjYW8gaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBt4bupYyB0cnVuZyBiw6xuaC4gS2hv4bqjbmcgxrDhu5tjIGzGsOG7o25nIHThu7cgbOG7hyBy4budaSBi4buPIHRo4bqtdCBz4buxIGPhu6dhIG5ow7NtIGjhu6NwIMSR4buTbmcgdGjDoW5nLCB24bubaSDEkeG7mSB0aW4gY+G6rXkgOTUlLCBu4bqxbSB0cm9uZyBraG/huqNuZyB04burIDQxLjIlIMSR4bq/biA0NC4yJS4NCg0KLS0tDQoNCiMjICoqMy4yLiBQaMOibiB0w61jaCBDaHVybiB2w6AgU2VuaW9yQ2l0aXplbiAoTmfGsOG7nWkgY2FvIHR14buVaSkqKg0KDQojIyMgKiozLjIuMS4gQuG6o25nIHThuqduIHPhu5EqKg0KYGBge3IgdGFibGUtc2VuaW9yLWNodXJuLWNoM30NCmRmX2NsZWFuJFNlbmlvckNpdGl6ZW5fbGFiZWxlZCA8LSBmYWN0b3IoZGZfY2xlYW4kU2VuaW9yQ2l0aXplbiwgbGV2ZWxzID0gYygiTm8iLCAiWWVzIiksIGxhYmVscyA9IGMoIktow7RuZyBwaOG6o2kgY2FvIHR14buVaSIsICJMw6AgbmfGsOG7nWkgY2FvIHR14buVaSIpKQ0KY2h1cm5fc2VuaW9yX3RhYmxlIDwtIHRhYmxlKGRmX2NsZWFuJFNlbmlvckNpdGl6ZW5fbGFiZWxlZCwgZGZfY2xlYW4kQ2h1cm5fbGFiZWxlZCkNCmNhdCgiQuG6o25nIHThuqduIHPhu5EgY2jDqW8gZ2nhu69hIFNlbmlvckNpdGl6ZW4gdsOgIENodXJuOlxuIikNCmFkZG1hcmdpbnMoY2h1cm5fc2VuaW9yX3RhYmxlKQ0KYGBgDQoNCiMjIyAqKjMuMi4yLiBLaeG7g20gxJHhu4tuaCBDaGktYsOsbmggcGjGsMahbmcqKg0KDQoqKkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oOioqDQoNCi0gICAqKiRIXzAkKio6IFZp4buHYyBsw6AgbmfGsOG7nWkgY2FvIHR14buVaSB2w6AgcXV54bq/dCDEkeG7i25oIHLhu51pIGLhu48gZOG7i2NoIHbhu6UgbMOgIGhhaSBiaeG6v24gxJHhu5ljIGzhuq1wLg0KDQotICAgKiokSF8xJCoqOiBDw7MgbeG7kWkgbGnDqm4gaOG7hyBnaeG7r2Egdmnhu4djIGzDoCBuZ8aw4budaSBjYW8gdHXhu5VpIHbDoCBxdXnhur90IMSR4buLbmggcuG7nWkgYuG7jyBk4buLY2ggduG7pS4NCg0KYGBge3IgY2hpc3Etc2VuaW9yLWNodXJuLWNoM30NCnByaW50KGNoaXNxLnRlc3QodGFibGUoZGZfY2xlYW4kQ2h1cm4sIGRmX2NsZWFuJFNlbmlvckNpdGl6ZW4pKSkNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBwLXZhbHVlIDwgMi4yZS0xNi4gQsOhYyBi4buPICRIXzAkLiBDw7MgbeG7kWkgbGnDqm4gaOG7hyBt4bqhbmggbeG6vS4NCg0KIyMjICoqMy4yLjMuIFRy4buxYyBxdWFuIGjDs2EgTeG7kWkgcXVhbiBo4buHKioNCmBgYHtyIG1vc2FpYy1zZW5pb3ItY2h1cm4sIGZpZy5jYXA9IkjDrG5oIDg6IEJp4buDdSDEkeG7kyBNb3NhaWMgZ2nhu69hIFNlbmlvckNpdGl6ZW4gdsOgIENodXJuIn0NCmdncGxvdChkYXRhID0gZGZfY2xlYW4pICsNCiAgZ2VvbV9tb3NhaWMoYWVzKHggPSBwcm9kdWN0KFNlbmlvckNpdGl6ZW4sIENodXJuKSwgZmlsbD1DaHVybikpICsNCiAgbGFicyh0aXRsZT0iTeG7kWkgcXVhbiBo4buHIGdp4buvYSBOaMOzbSB0deG7lWkgdsOgIFThu7cgbOG7hyBy4budaSBi4buPIiwgeD0iTMOgIG5nxrDhu51pIGNhbyB0deG7lWk/IiwgeT0iVOG7tyBs4buHIENodXJuIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEyKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KYGBgDQoNCiMjIyAqKjMuMi40LiBIaeG7h3UgdOG7tyBs4buHKioNCg0KKipHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoqKg0KDQotICAgKiokSF8wJCoqOiBU4bu3IGzhu4cgcuG7nWkgYuG7jyDhu58gaGFpIG5ow7NtIGzDoCBi4bqxbmcgbmhhdSAoJHBfMSAtIHBfMiA9IDAkKS4NCg0KLSAgICoqJEhfMSQqKjogVOG7tyBs4buHIHLhu51pIGLhu48g4bufIG5ow7NtIGtow7RuZyBwaOG6o2kgY2FvIHR14buVaSB0aOG6pXAgaMahbiBuaMOzbSBjYW8gdHXhu5VpICgkcF8xIC0gcF8yIDwgMCQpLg0KDQpgYGB7ciBwcm9wLXRlc3Qtc2VuaW9yLWNodXJuLWNoM30NCmNvdW50c19jaHVybiA8LSBjaHVybl9zZW5pb3JfdGFibGVbLCAiUuG7nWkgYuG7jyJdIA0KdG90YWxzX2dyb3VwIDwtIHJvd1N1bXMoY2h1cm5fc2VuaW9yX3RhYmxlKQ0KcHJvcF90ZXN0X3NlbmlvciA8LSBwcm9wLnRlc3QoeCA9IGNvdW50c19jaHVybiwgbiA9IHRvdGFsc19ncm91cCwgYWx0ZXJuYXRpdmUgPSAibGVzcyIsIGNvcnJlY3QgPSBGQUxTRSkNCnByaW50KHByb3BfdGVzdF9zZW5pb3IpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogWMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBj4bunYSBuaMOzbSBraMO0bmcgcGjhuqNpIG5nxrDhu51pIGNhbyB0deG7lWkgbMOgIGByIHNjYWxlczo6cGVyY2VudChwcm9wX3Rlc3Rfc2VuaW9yJGVzdGltYXRlWzFdLCBhY2N1cmFjeT0wLjEpYCwgdHJvbmcga2hpIGPhu6dhIG5ow7NtIG5nxrDhu51pIGNhbyB0deG7lWkgbMOgIGByIHNjYWxlczo6cGVyY2VudChwcm9wX3Rlc3Rfc2VuaW9yJGVzdGltYXRlWzJdLCBhY2N1cmFjeT0wLjEpYC4gcC12YWx1ZSA8IDIuMmUtMTYgY2hvIHRo4bqleSBz4buxIGtow6FjIGJp4buHdCBuw6B5IGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogY2FvLg0KDQojIyMgKiozLjIuNS4gUuG7p2kgcm8gdMawxqFuZyDEkeG7kWkgKFJSKSoqDQpgYGB7ciByci1zZW5pb3ItY2h1cm4tY2gzfQ0KcnJfc2VuaW9yIDwtIHJpc2tyYXRpbyhjaHVybl9zZW5pb3JfdGFibGUsIG1ldGhvZD0id2FsZCIpDQpwcmludChycl9zZW5pb3IpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogUlIgPSBgciByb3VuZChycl9zZW5pb3IkbWVhc3VyZVsyLDFdLCAyKWAuIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IG5ndXkgY8ahIHLhu51pIGLhu48gZOG7i2NoIHbhu6Ug4bufIG5ow7NtIGtow6FjaCBow6BuZyBjYW8gdHXhu5VpIGNhbyBn4bqlcCAxLjc2IGzhuqduIHNvIHbhu5tpIG5ow7NtIGtow6FjaCBow6BuZyBraMO0bmcgcGjhuqNpIG5nxrDhu51pIGNhbyB0deG7lWkuIEtob+G6o25nIHRpbiBj4bqteSA5NSUgY2hvIFJSIGzDoCB04burIGByIHJvdW5kKHJyX3NlbmlvciRtZWFzdXJlWzIsMl0sIDIpYCDEkeG6v24gYHIgcm91bmQocnJfc2VuaW9yJG1lYXN1cmVbMiwzXSwgMilgLCBraMO0bmcgY2jhu6lhIDEgbsOqbiBr4bq/dCBxdeG6oyBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqLg0KDQojIyMgKiozLjIuNi4gVOG7tyBz4buRIENow6puaCAoT1IpKioNCmBgYHtyIG9yLXNlbmlvci1jaHVybi1jaDN9DQpvcl9zZW5pb3IgPC0gb2Rkc3JhdGlvKGNodXJuX3Nlbmlvcl90YWJsZSwgbWV0aG9kPSJ3YWxkIikNCnByaW50KG9yX3NlbmlvcikNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBPUiA9IGByIHJvdW5kKG9yX3NlbmlvciRtZWFzdXJlWzIsMV0sIDIpYC4gVOG7tyBs4buHIGNow6puaCAob2RkcykgY+G7p2Egdmnhu4djIHLhu51pIGLhu48gZOG7i2NoIHbhu6Ug4bufIG5ow7NtIGtow6FjaCBow6BuZyBjYW8gdHXhu5VpIGNhbyBoxqFuIDIuMjkgbOG6p24gc28gduG7m2kgbmjDs20ga2jDtG5nIHBo4bqjaSBuZ8aw4budaSBjYW8gdHXhu5VpLg0KDQojIyMgKiozLjIuNy4gxq/hu5tjIGzGsOG7o25nIHThu7cgbOG7hyBy4budaSBi4buPIGNobyBuaMOzbSBuZ8aw4budaSBjYW8gdHXhu5VpIChgU2VuaW9yQ2l0aXplbiA9IFllc2ApKioNCg0KKipHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoqKg0KDQotICAgKiokSF8wJCoqOiBU4bu3IGzhu4cgcuG7nWkgYuG7jyBj4bunYSBuaMOzbSBuZ8aw4budaSBjYW8gdHXhu5VpIGLhurFuZyB04bu3IGzhu4cgdHJ1bmcgYsOsbmggY+G7p2EgdOG7lW5nIHRo4buDIChraG/huqNuZyAyNyUpLCB04bupYyBsw6AgJHAgPSAwLjI3JC4NCg0KLSAgICoqJEhfMSQqKjogVOG7tyBs4buHIHLhu51pIGLhu48gY+G7p2EgbmjDs20gbmfGsOG7nWkgY2FvIHR14buVaSBraMOhYyAyNyUgKCRwIFxuZXEgMC4yNyQpLg0KDQpgYGB7ciBwcm9wLXRlc3Qtc2VuaW9yLWdyb3VwfQ0KY291bnRfc2VuaW9yIDwtIGNodXJuX3Nlbmlvcl90YWJsZVsiTMOgIG5nxrDhu51pIGNhbyB0deG7lWkiLCAiUuG7nWkgYuG7jyJdDQp0b3RhbF9zZW5pb3IgPC0gc3VtKGNodXJuX3Nlbmlvcl90YWJsZVsiTMOgIG5nxrDhu51pIGNhbyB0deG7lWkiLCBdKQ0KcHJvcC50ZXN0KHggPSBjb3VudF9zZW5pb3IsIG4gPSB0b3RhbF9zZW5pb3IsIHAgPSAwLjI3LCBjb3JyZWN0ID0gRkFMU0UpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogS+G6v3QgcXXhuqMga2nhu4NtIMSR4buLbmggY8OzIHAtdmFsdWUgPCAyLjJlLTE2LCBiw6FjIGLhu48gZ2nhuqMgdGh1eeG6v3QgJEhfMCQuIFThu7cgbOG7hyBy4budaSBi4buPIHRo4buxYyB04bq/IHRyb25nIG3huqt1IGPhu6dhIG5ow7NtIG5nxrDhu51pIGNhbyB0deG7lWkgbMOgICoqNDEuNyUqKiwgY2FvIGjGoW4gcuG6pXQgbmhp4buBdSBzbyB24bubaSBt4bupYyB0cnVuZyBiw6xuaC4gS2hv4bqjbmcgxrDhu5tjIGzGsOG7o25nIHThu7cgbOG7hyBy4budaSBi4buPIHRo4bqtdCBz4buxIGPhu6dhIG5ow7NtIG7DoHksIHbhu5tpIMSR4buZIHRpbiBj4bqteSA5NSUsIG7hurFtIHRyb25nIGtob+G6o25nIHThu6sgMzguOSUgxJHhur9uIDQ0LjUlLg0KDQotLS0NCg0KIyMgKiozLjMuIFBow6JuIHTDrWNoIENodXJuIHbDoCBQYXltZW50TWV0aG9kIChQaMawxqFuZyB0aOG7qWMgdGhhbmggdG/DoW4pKioNCg0KIyMjICoqMy4zLjEuIELhuqNuZyB04bqnbiBz4buRKioNCmBgYHtyIHRhYmxlLXBheW1lbnQtY2h1cm4tY2gzfQ0KY2h1cm5fcGF5bWVudF90YWJsZSA8LSB0YWJsZShkZl9jbGVhbiRQYXltZW50TWV0aG9kLCBkZl9jbGVhbiRDaHVybikNCmNhdCgiQuG6o25nIHThuqduIHPhu5EgY2jDqW86XG4iKQ0KYWRkbWFyZ2lucyhjaHVybl9wYXltZW50X3RhYmxlKQ0KYGBgDQoNCiMjIyAqKjMuMy4yLiBLaeG7g20gxJHhu4tuaCBDaGktYsOsbmggcGjGsMahbmcqKg0KDQoqKkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oOioqDQoNCi0gICAqKiRIXzAkKio6IFBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiB2w6Agdmnhu4djIHLhu51pIGLhu48gbMOgIGhhaSBiaeG6v24gxJHhu5ljIGzhuq1wLg0KDQotICAgKiokSF8xJCoqOiBQaMawxqFuZyB0aOG7qWMgdGhhbmggdG/DoW4gdsOgIHZp4buHYyBy4budaSBi4buPIGPDsyBsacOqbiBxdWFuIMSR4bq/biBuaGF1Lg0KDQpgYGB7ciBjaGlzcS1wYXltZW50LWNodXJuLWNoM30NCnByaW50KGNoaXNxLnRlc3QoY2h1cm5fcGF5bWVudF90YWJsZSkpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogcC12YWx1ZSA8IDIuMmUtMTYuIELDoWMgYuG7jyAkSF8wJC4gUGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuIGPDsyBt4buRaSBsacOqbiBo4buHIHLhuqV0IG3huqFuaCB24bubaSB2aeG7h2MgcuG7nWkgYuG7jy4NCg0KIyMjICoqMy4zLjMuIFRy4buxYyBxdWFuIGjDs2EgTeG7kWkgcXVhbiBo4buHKioNCmBgYHtyIG1vc2FpYy1wYXltZW50LWNodXJuLCBmaWcuY2FwPSJIw6xuaCA5OiBCaeG7g3UgxJHhu5MgTW9zYWljIGdp4buvYSBQYXltZW50TWV0aG9kIHbDoCBDaHVybiJ9DQpnZ3Bsb3QoZGF0YSA9IGRmX2NsZWFuKSArDQogIGdlb21fbW9zYWljKGFlcyh4ID0gcHJvZHVjdChQYXltZW50TWV0aG9kLCBDaHVybiksIGZpbGw9Q2h1cm4pKSArDQogIGxhYnModGl0bGU9Ik3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgUGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuIHbDoCBU4bu3IGzhu4cgcuG7nWkgYuG7jyIsIHg9IlBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiIsIHk9IlThu7cgbOG7hyBDaHVybiIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KYGBgDQoNCiMjIyAqKjMuMy40LiBQaMOibiB0w61jaCBzbyBzw6FuaCBjaGkgdGnhur90KioNCg0KKipTbyBzw6FuaCAnRWxlY3Ryb25pYyBjaGVjaycgduG7m2kgJ0NyZWRpdCBjYXJkIChhdXRvbWF0aWMpJzoqKg0KYGBge3IgYW5hbHlzaXMtcGF5bWVudC1jaDN9DQpwYXltZW50X3N1Yl9lYyA8LSBkZl9jbGVhbiAlPiUgDQogIGZpbHRlcihQYXltZW50TWV0aG9kICVpbiUgYygiRWxlY3Ryb25pYyBjaGVjayIsICJDcmVkaXQgY2FyZCAoYXV0b21hdGljKSIpKSAlPiUNCiAgZHJvcGxldmVscygpDQp0YWJsZV9lYyA8LSB0YWJsZShwYXltZW50X3N1Yl9lYyRQYXltZW50TWV0aG9kLCBwYXltZW50X3N1Yl9lYyRDaHVybikNCnByb3BfdGVzdF9lYyA8LSBwcm9wLnRlc3QoeCA9IHRhYmxlX2VjWywgIlllcyJdLCBuID0gcm93U3Vtcyh0YWJsZV9lYyksIGNvcnJlY3Q9RkFMU0UpDQpycl9lYyA8LSByaXNrcmF0aW8odGFibGVfZWMsIG1ldGhvZD0id2FsZCIpDQpvcl9lYyA8LSBvZGRzcmF0aW8odGFibGVfZWMsIG1ldGhvZD0id2FsZCIpDQpgYGANCg0KKiphLiBIaeG7h3UgdOG7tyBs4buHKioNCg0KKipHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoqKg0KDQotICAgKiokSF8wJCoqOiBU4bu3IGzhu4cgcuG7nWkgYuG7jyBsw6AgbmjGsCBuaGF1Lg0KDQotICAgKiokSF8xJCoqOiBU4bu3IGzhu4cgcuG7nWkgYuG7jyDhu58gbmjDs20gJ0VsZWN0cm9uaWMgY2hlY2snIGNhbyBoxqFuLg0KYGBge3IgcHJvcC10ZXN0LXBheW1lbnQtY2gzfQ0KcHJpbnQocHJvcF90ZXN0X2VjKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIFThu7cgbOG7hyBy4budaSBi4buPIGPhu6dhIG5ow7NtIGBFbGVjdHJvbmljIGNoZWNrYCAoYHIgc2NhbGVzOjpwZXJjZW50KHByb3BfdGVzdF9lYyRlc3RpbWF0ZVsyXSwgYWNjdXJhY3k9MC4xKWApIGNhbyBoxqFuIMSRw6FuZyBr4buDIHNvIHbhu5tpIG5ow7NtIGBDcmVkaXQgY2FyZCAoYXV0b21hdGljKWAgKGByIHNjYWxlczo6cGVyY2VudChwcm9wX3Rlc3RfZWMkZXN0aW1hdGVbMV0sIGFjY3VyYWN5PTAuMSlgKSwgduG7m2kgcC12YWx1ZSA8IDIuMmUtMTYuDQoNCioqYi4gUuG7p2kgcm8gVMawxqFuZyDEkeG7kWkgKFJSKSoqDQpgYGB7ciByci1wYXltZW50LWNoM30NCnByaW50KHJyX2VjKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIFJSID0gYHIgcm91bmQocnJfZWMkbWVhc3VyZVsyLDFdLCAyKWAuIE5ndXkgY8ahIHLhu51pIGLhu48gY+G7p2EgbmjDs20gdGhhbmggdG/DoW4gYuG6sW5nIHPDqWMgxJFp4buHbiB04butIGNhbyBn4bqlcCAyLjk4IGzhuqduIHNvIHbhu5tpIG5ow7NtIHRoYW5oIHRvw6FuIGLhurFuZyB0aOG6uyB0w61uIGThu6VuZyB04buxIMSR4buZbmcuDQoNCioqYy4gVOG7tyBz4buRIENow6puaCAoT1IpKioNCmBgYHtyIG9yLXBheW1lbnQtY2gzfQ0KcHJpbnQob3JfZWMpDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogT1IgPSBgciByb3VuZChvcl9lYyRtZWFzdXJlWzIsMV0sIDIpYC4gT2RkcyBy4budaSBi4buPIGPhu6dhIG5ow7NtIGBFbGVjdHJvbmljIGNoZWNrYCBjYW8gaMahbiBn4bqlcCA0LjA2IGzhuqduIHNvIHbhu5tpIG5ow7NtIGBDcmVkaXQgY2FyZCAoYXV0b21hdGljKWAuDQoNCiMjIyAqKjMuMy41LiBLaG/huqNuZyDGsOG7m2MgbMaw4bujbmcgdOG7tyBs4buHKioNCg0KKirGr+G7m2MgbMaw4bujbmcgdOG7tyBs4buHIHLhu51pIGLhu48gY2hvIG5ow7NtIHRoYW5oIHRvw6FuIGLhurFuZyBTw6ljIMSRaeG7h24gdOG7rSAoYEVsZWN0cm9uaWMgY2hlY2tgKSoqDQoNCioqR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6KioNCg0KLSAgICoqJEhfMCQqKjogVOG7tyBs4buHIHLhu51pIGLhu48gY+G7p2EgbmjDs20gZMO5bmcgc8OpYyDEkWnhu4duIHThu60gYuG6sW5nIHThu7cgbOG7hyB0cnVuZyBiw6xuaCAoMjclKSwgdOG7qWMgbMOgICRwID0gMC4yNyQuDQoNCi0gICAqKiRIXzEkKio6IFThu7cgbOG7hyBy4budaSBi4buPIGPhu6dhIG5ow7NtIGTDuW5nIHPDqWMgxJFp4buHbiB04butIGtow6FjIDI3JSAoJHAgXG5lcSAwLjI3JCkuDQoNCmBgYHtyIHByb3AtdGVzdC1wYXltZW50LWdyb3VwfQ0KY291bnRfZWMgPC0gY2h1cm5fcGF5bWVudF90YWJsZVsiRWxlY3Ryb25pYyBjaGVjayIsICJZZXMiXQ0KdG90YWxfZWMgPC0gc3VtKGNodXJuX3BheW1lbnRfdGFibGVbIkVsZWN0cm9uaWMgY2hlY2siLCBdKQ0KcHJvcC50ZXN0KHggPSBjb3VudF9lYywgbiA9IHRvdGFsX2VjLCBwID0gMC4yNywgY29ycmVjdCA9IEZBTFNFKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIEvhur90IHF14bqjIGtp4buDbSDEkeG7i25oIGPDsyBwLXZhbHVlIDwgMi4yZS0xNiwgYsOhYyBi4buPIGdp4bqjIHRodXnhur90ICRIXzAkLiBU4bu3IGzhu4cgcuG7nWkgYuG7jyB0aOG7sWMgdOG6vyB0cm9uZyBt4bqrdSBj4bunYSBuaMOzbSBkw7luZyBzw6ljIMSRaeG7h24gdOG7rSBsw6AgKio0NS4zJSoqLCBjYW8gdsaw4bujdCB0cuG7mWkgc28gduG7m2kgbeG7qWMgdHJ1bmcgYsOsbmguIEtob+G6o25nIMaw4bubYyBsxrDhu6NuZyB04bu3IGzhu4cgcuG7nWkgYuG7jyB0aOG6rXQgc+G7sSBj4bunYSBuaMOzbSBuw6B5LCB24bubaSDEkeG7mSB0aW4gY+G6rXkgOTUlLCBu4bqxbSB0cm9uZyBraG/huqNuZyB04burIDQzLjMlIMSR4bq/biA0Ny4zJS4NCg0KLS0tDQoNCiMjICoqMy40LiBQaMOibiB0w61jaCBDaHVybiB2w6AgSW50ZXJuZXRTZXJ2aWNlIChE4buLY2ggduG7pSBJbnRlcm5ldCkqKg0KDQojIyMgKiozLjQuMS4gQuG6o25nIHThuqduIHPhu5EqKg0KYGBge3IgdGFibGUtaW50ZXJuZXQtY2h1cm4tY2gzfQ0KY2h1cm5faW50ZXJuZXRfdGFibGUgPC0gdGFibGUoZGZfY2xlYW4kSW50ZXJuZXRTZXJ2aWNlLCBkZl9jbGVhbiRDaHVybikNCmNhdCgiQuG6o25nIHThuqduIHPhu5EgY2jDqW86XG4iKQ0KYWRkbWFyZ2lucyhjaHVybl9pbnRlcm5ldF90YWJsZSkNCmBgYA0KDQojIyMgKiozLjQuMi4gS2nhu4NtIMSR4buLbmggQ2hpLWLDrG5oIHBoxrDGoW5nKioNCg0KKipHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoqKg0KDQotICAgKiokSF8wJCoqOiBE4buLY2ggduG7pSBJbnRlcm5ldCB2w6Agdmnhu4djIHLhu51pIGLhu48gbMOgIGhhaSBiaeG6v24gxJHhu5ljIGzhuq1wLg0KDQotICAgKiokSF8xJCoqOiBE4buLY2ggduG7pSBJbnRlcm5ldCB2w6Agdmnhu4djIHLhu51pIGLhu48gY8OzIGxpw6puIHF1YW4gxJHhur9uIG5oYXUuDQoNCmBgYHtyIGNoaXNxLWludGVybmV0LWNodXJuLWNoM30NCnByaW50KGNoaXNxLnRlc3QoY2h1cm5faW50ZXJuZXRfdGFibGUpKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIHAtdmFsdWUgPCAyLjJlLTE2LiBCw6FjIGLhu48gJEhfMCQuIEPDsyBt4buRaSBsacOqbiBo4buHIHLhuqV0IG3huqFuaC4NCg0KIyMjICoqMy40LjMuIFRy4buxYyBxdWFuIGjDs2EgTeG7kWkgcXVhbiBo4buHKioNCmBgYHtyIG1vc2FpYy1pbnRlcm5ldC1jaHVybiwgZmlnLmNhcD0iSMOsbmggMTA6IEJp4buDdSDEkeG7kyBNb3NhaWMgZ2nhu69hIEludGVybmV0U2VydmljZSB2w6AgQ2h1cm4ifQ0KZ2dwbG90KGRhdGEgPSBkZl9jbGVhbikgKw0KICBnZW9tX21vc2FpYyhhZXMoeCA9IHByb2R1Y3QoSW50ZXJuZXRTZXJ2aWNlLCBDaHVybiksIGZpbGw9Q2h1cm4pKSArDQogIGxhYnModGl0bGU9Ik3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgROG7i2NoIHbhu6UgSW50ZXJuZXQgdsOgIFThu7cgbOG7hyBy4budaSBi4buPIiwgeD0iROG7i2NoIHbhu6UgSW50ZXJuZXQiLCB5PSJU4bu3IGzhu4cgQ2h1cm4iKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KIyMjICoqMy40LjQuIFBow6JuIHTDrWNoIHNvIHPDoW5oIGNoaSB0aeG6v3QqKg0KDQoqKlNvIHPDoW5oICdGaWJlciBvcHRpYycgduG7m2kgJ0RTTCc6KioNCmBgYHtyIGFuYWx5c2lzLWludGVybmV0LWNoM30NCmludGVybmV0X3N1Yl9mbyA8LSBkZl9jbGVhbiAlPiUgDQogIGZpbHRlcihJbnRlcm5ldFNlcnZpY2UgJWluJSBjKCJGaWJlciBvcHRpYyIsICJEU0wiKSkgJT4lDQogIGRyb3BsZXZlbHMoKQ0KdGFibGVfZm8gPC0gdGFibGUoaW50ZXJuZXRfc3ViX2ZvJEludGVybmV0U2VydmljZSwgaW50ZXJuZXRfc3ViX2ZvJENodXJuKQ0KcHJvcF90ZXN0X2ZvIDwtIHByb3AudGVzdCh4ID0gdGFibGVfZm9bLCAiWWVzIl0sIG4gPSByb3dTdW1zKHRhYmxlX2ZvKSwgY29ycmVjdD1GQUxTRSkNCnJyX2ZvIDwtIHJpc2tyYXRpbyh0YWJsZV9mbywgbWV0aG9kPSJ3YWxkIikNCm9yX2ZvIDwtIG9kZHNyYXRpbyh0YWJsZV9mbywgbWV0aG9kPSJ3YWxkIikNCmBgYA0KDQoqKmEuIEhp4buHdSB04bu3IGzhu4cqKg0KDQoqKkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oOioqDQoNCi0gICAqKiRIXzAkKio6IFThu7cgbOG7hyBy4budaSBi4buPIOG7nyBuaMOzbSAnRmliZXIgb3B0aWMnIHbDoCAnRFNMJyBsw6AgbmjGsCBuaGF1Lg0KDQotICAgKiokSF8xJCoqOiBU4bu3IGzhu4cgcuG7nWkgYuG7jyDhu58gbmjDs20gJ0ZpYmVyIG9wdGljJyBjYW8gaMahbi4NCmBgYHtyIHByb3AtdGVzdC1pbnRlcm5ldC1jaDN9DQpwcmludChwcm9wX3Rlc3RfZm8pDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogVOG7tyBs4buHIHLhu51pIGLhu48gY+G7p2Ega2jDoWNoIGjDoG5nIGTDuW5nIGBGaWJlciBvcHRpY2AgKGByIHNjYWxlczo6cGVyY2VudChwcm9wX3Rlc3RfZm8kZXN0aW1hdGVbMl0sIGFjY3VyYWN5PTAuMSlgKSBjYW8gaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBgRFNMYCAoYHIgc2NhbGVzOjpwZXJjZW50KHByb3BfdGVzdF9mbyRlc3RpbWF0ZVsxXSwgYWNjdXJhY3k9MC4xKWApLiBW4bubaSBwLXZhbHVlIDwgMi4yZS0xNiwgc+G7sSBraMOhYyBiaeG7h3QgbMOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNCioqYi4gUuG7p2kgcm8gVMawxqFuZyDEkeG7kWkgKFJSKSoqDQpgYGB7ciByci1pbnRlcm5ldC1jaDN9DQpwcmludChycl9mbykNCmBgYA0KKipOaOG6rW4geMOpdDoqKiBSUiA9IGByIHJvdW5kKHJyX2ZvJG1lYXN1cmVbMiwxXSwgMilgLiBOZ3V5IGPGoSBy4budaSBi4buPIGPhu6dhIGtow6FjaCBow6BuZyBkw7luZyBjw6FwIHF1YW5nIGNhbyBoxqFuIDIuMjEgbOG6p24gc28gduG7m2kga2jDoWNoIGjDoG5nIGTDuW5nIERTTC4NCg0KKipjLiBU4bu3IHPhu5EgQ2jDqm5oIChPUikqKg0KYGBge3Igb3ItaW50ZXJuZXQtY2gzfQ0KcHJpbnQob3JfZm8pDQpgYGANCioqTmjhuq1uIHjDqXQ6KiogT1IgPSBgciByb3VuZChvcl9mbyRtZWFzdXJlWzIsMV0sIDIpYC4gT2RkcyBy4budaSBi4buPIGPhu6dhIGtow6FjaCBow6BuZyBkw7luZyBjw6FwIHF1YW5nIGNhbyBoxqFuIDMuMTQgbOG6p24gc28gduG7m2kgZMO5bmcgRFNMLg0KDQojIyMgKiozLjQuNC4gS2hv4bqjbmcgxrDhu5tjIGzGsOG7o25nIHThu7cgbOG7hyoqDQoNCioqxq/hu5tjIGzGsOG7o25nIHThu7cgbOG7hyBy4budaSBi4buPIGNobyBuaMOzbSBkw7luZyBDw6FwIHF1YW5nIChgRmliZXIgb3B0aWNgKSoqDQoNCioqR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6KioNCg0KLSAgICoqJEhfMCQqKjogVOG7tyBs4buHIHLhu51pIGLhu48gY+G7p2EgbmjDs20gZMO5bmcgY8OhcCBxdWFuZyBi4bqxbmcgdOG7tyBs4buHIHRydW5nIGLDrG5oICgyNyUpLCB04bupYyBsw6AgJHAgPSAwLjI3JC4NCg0KLSAgICoqJEhfMSQqKjogVOG7tyBs4buHIHLhu51pIGLhu48gY+G7p2EgbmjDs20gZMO5bmcgY8OhcCBxdWFuZyBraMOhYyAyNyUgKCRwIFxuZXEgMC4yNyQpLg0KDQpgYGB7ciBwcm9wLXRlc3QtaW50ZXJuZXQtZ3JvdXB9DQpjb3VudF9mbyA8LSBjaHVybl9pbnRlcm5ldF90YWJsZVsiRmliZXIgb3B0aWMiLCAiWWVzIl0NCnRvdGFsX2ZvIDwtIHN1bShjaHVybl9pbnRlcm5ldF90YWJsZVsiRmliZXIgb3B0aWMiLCBdKQ0KcHJvcC50ZXN0KHggPSBjb3VudF9mbywgbiA9IHRvdGFsX2ZvLCBwID0gMC4yNywgY29ycmVjdCA9IEZBTFNFKQ0KYGBgDQoqKk5o4bqtbiB4w6l0OioqIEvhur90IHF14bqjIGtp4buDbSDEkeG7i25oIGPDsyBwLXZhbHVlIDwgMi4yZS0xNiwgYsOhYyBi4buPIGdp4bqjIHRodXnhur90ICRIXzAkLiBU4bu3IGzhu4cgcuG7nWkgYuG7jyB0aOG7sWMgdOG6vyB0cm9uZyBt4bqrdSBj4bunYSBuaMOzbSBkw7luZyBjw6FwIHF1YW5nIGzDoCAqKjQxLjklKiosIGNhbyBoxqFuIMSRw6FuZyBr4buDIHNvIHbhu5tpIG3hu6ljIHRydW5nIGLDrG5oLiBLaG/huqNuZyDGsOG7m2MgbMaw4bujbmcgdOG7tyBs4buHIHLhu51pIGLhu48gdGjhuq10IHPhu7EgY+G7p2EgbmjDs20gbsOgeSwgduG7m2kgxJHhu5kgdGluIGPhuq15IDk1JSwgbuG6sW0gdHJvbmcga2hv4bqjbmcgdOG7qyA0MC4xJSDEkeG6v24gNDMuNyUuDQoNCi0tLQ0KDQojIyAqKjMuNS4gUGjDom4gdMOtY2ggQ2h1cm4gdsOgIHRlbnVyZSAoVGjhu51pIGdpYW4gZ+G6r24gYsOzKSoqDQoNCi0gVsOsIGJp4bq/biBUZW51cmUgbMOgIGJp4bq/biDEkeG7i25oIGzGsOG7o25nIG7Dqm4gdMOhYyBnaeG6oyBjaOG7iSB0aeG6v24gaMOgbmggdGjhu5FuZyBrw6ogbcO0IHThuqMgdsOgIHbhur0gYmnhu4N1IMSR4buTDQoNCiMjIyAqKjMuNS4xLiBUaOG7kW5nIGvDqiBtw7QgdOG6oyoqDQpgYGB7ciBzdW1tYXJ5LXRlbnVyZS1jaHVybi1jaDN9DQp0ZW51cmVfc3VtbWFyeSA8LSBkZl9jbGVhbiAlPiUNCiAgZ3JvdXBfYnkoQ2h1cm4pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl90ZW51cmUgPSBtZWFuKHRlbnVyZSksDQogICAgbWVkaWFuX3RlbnVyZSA9IG1lZGlhbih0ZW51cmUpDQogICkNCmthYmxlKHRlbnVyZV9zdW1tYXJ5LCBjYXB0aW9uPSJUaOG7kW5nIGvDqiAndGVudXJlJyB0aGVvICdDaHVybiciKQ0KYGBgDQoNCiMjIyAqKjMuNS4yLiBUcuG7sWMgcXVhbiBow7NhIFBow6JuIHBo4buRaSoqDQoNCiMjIyMgKipCaeG7g3UgxJHhu5MgTeG6rXQgxJHhu5kgKERlbnNpdHkgUGxvdCkqKg0KYGBge3IgZGVuc2l0eS1wbG90LXRlbnVyZSwgZmlnLmNhcD0iSMOsbmggMTE6IFBow6JuIHBo4buRaSBt4bqtdCDEkeG7mSBj4bunYSB0aOG7nWkgZ2lhbiBn4bqvbiBiw7MgKHRlbnVyZSkgdGhlbyB0cuG6oW5nIHRow6FpIHLhu51pIGLhu48ifQ0KZ2dwbG90KGRmX2NsZWFuLCBhZXMoeCA9IHRlbnVyZSwgZmlsbCA9IENodXJuKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjcpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQaMOibiBwaOG7kWkgTeG6rXQgxJHhu5kgY+G7p2EgVGjhu51pIGdpYW4gR+G6r24gYsOzIHRoZW8gVMOsbmggdHLhuqFuZyBS4budaSBi4buPIiwNCiAgICB4ID0gIlRo4budaSBnaWFuIGfhuq9uIGLDsyAodGjDoW5nKSIsDQogICAgeSA9ICJN4bqtdCDEkeG7mSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KQmnhu4N1IMSR4buTIG3huq10IMSR4buZIGNobyB0aOG6pXkgbeG7mXQgY8OidSBjaHV54buHbiBy4bqldCByw7UgcsOgbmc6DQotICAgKirEkMaw4budbmcgY29uZyBS4budaSBi4buPIChZZXMgLSBtw6B1IMSR4buPKToqKiBDw7MgbeG7mXQgxJHhu4luaCBuaOG7jW4gdsOgIHLhuqV0IGNhbyDhu58gbmjhu69uZyBnacOhIHRy4buLIGB0ZW51cmVgIHRo4bqlcCAoY2jhu6cgeeG6v3UgZMaw4bubaSAyMCB0aMOhbmcpLiDEkGnhu4F1IG7DoHkgY8OzIG5naMSpYSBsw6AgcGjhuqduIGzhu5tuIGtow6FjaCBow6BuZyBy4budaSBi4buPIGThu4tjaCB24bulIHRyb25nIG5o4buvbmcgdGjDoW5nIMSR4bqndSB0acOqbiBz4butIGThu6VuZy4NCi0gICAqKsSQxrDhu51uZyBjb25nIEtow7RuZyBy4budaSBi4buPIChObyAtIG3DoHUgeGFuaCk6KiogUGjDom4gcGjhu5FpIHRy4bqjaSBy4buZbmcgaMahbiBuaGnhu4F1LiDEkMOhbmcgY2jDuiDDvSwgbsOzIGPDsyBoYWkgxJHhu4luaCBjaMOtbmg6IG3hu5l0IMSR4buJbmgg4bufIGfhuqduIMSR4bqndSAobmjhu69uZyBraMOhY2ggaMOgbmcgbeG7m2kgbmjGsG5nIHbhuqtuIHRydW5nIHRow6BuaCkgdsOgIG3hu5l0IMSR4buJbmggcuG6pXQgY2FvIOG7nyBjdeG7kWkgKG5o4buvbmcga2jDoWNoIGjDoG5nIMSRw6MgZ+G6r24gYsOzIHLhuqV0IGzDonUsIGtob+G6o25nIDcyIHRow6FuZykuDQotICAgKipL4bq/dCBsdeG6rW46KiogTmd1eSBjxqEga2jDoWNoIGjDoG5nIHLhu51pIGLhu48gbMOgIGNhbyBuaOG6pXQgdHJvbmcgZ2lhaSDEkW/huqFuIMSR4bqndS4gQ8Ogbmcg4bufIGzhuqFpIGzDonUsIGto4bqjIG7Eg25nIGjhu40gdGnhur9wIHThu6VjIHPhu60gZOG7pW5nIGThu4tjaCB24bulIGPDoG5nIGNhby4NCg0KIyMjIyAqKkJp4buDdSDEkeG7kyBU4bqnbiBzdeG6pXQgKEhpc3RvZ3JhbSkgdGhlbyB04burbmcgbmjDs20qKg0KYGBge3IgaGlzdG9ncmFtLXBsb3QtdGVudXJlLCBmaWcuY2FwPSJIw6xuaCAxMjogUGjDom4gcGjhu5FpIHPhu5EgbMaw4bujbmcga2jDoWNoIGjDoG5nIHRoZW8gdGjhu51pIGdpYW4gZ+G6r24gYsOzLCB0w6FjaCBiaeG7h3QgdGhlbyB0cuG6oW5nIHRow6FpIHLhu51pIGLhu48ifQ0KZ2dwbG90KGRmX2NsZWFuLCBhZXMoeCA9IHRlbnVyZSwgZmlsbCA9IENodXJuKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzAsIGNvbG9yID0gIndoaXRlIikgKw0KICBmYWNldF93cmFwKH4gQ2h1cm4sIG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBow6JuIHBo4buRaSBz4buRIGzGsOG7o25nIGtow6FjaCBow6BuZyB0aGVvIHRo4budaSBnaWFuIGfhuq9uIGLDsyIsDQogICAgeCA9ICJUaOG7nWkgZ2lhbiBn4bqvbiBiw7MgKHRow6FuZykiLA0KICAgIHkgPSAiU+G7kSBsxrDhu6NuZyBraMOhY2ggaMOgbmciDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KQmnhu4N1IMSR4buTIG7DoHkgY+G7p25nIGPhu5EgdGjDqm0gbmjhu69uZyBnw6wgYmnhu4N1IMSR4buTIG3huq10IMSR4buZIMSRw6MgY2jhu4kgcmE6DQotICAgKipQYW5lbCBgWWVzYCAoUuG7nWkgYuG7jyk6KiogQ8OhYyBj4buZdCBjYW8gbmjhuqV0IHThuq1wIHRydW5nIGTDoHkgxJHhurdjIOG7nyBwaMOtYSBiw6puIHRyw6FpICh04burIDEtMTAgdGjDoW5nKSwgc2F1IMSRw7MgZ2nhuqNtIG3huqFuaC4gxJBp4buBdSBuw6B5IGNobyB0aOG6pXkgc+G7kSBsxrDhu6NuZyBraMOhY2ggaMOgbmcgcuG7nWkgYuG7jyBnaeG6o20gZOG6p24gdGhlbyB0aOG7nWkgZ2lhbiBo4buNIGfhuq9uIGLDsy4NCi0gICAqKlBhbmVsIGBOb2AgKEtow7RuZyBy4budaSBi4buPKToqKiBQaMOibiBwaOG7kWkgc+G7kSBsxrDhu6NuZyBraMOhY2ggaMOgbmcg4buVbiDEkeG7i25oIGjGoW4gbmhp4buBdS4gxJDhurdjIGJp4buHdCwgY+G7mXQgY2FvIG5o4bqldCBu4bqxbSDhu58gY3Xhu5FpIGPDuW5nIChraG/huqNuZyA3MiB0aMOhbmcpLCBjaG8gdGjhuqV5IGPDsyBt4buZdCBsxrDhu6NuZyBs4bubbiBraMOhY2ggaMOgbmcgcuG6pXQgdHJ1bmcgdGjDoG5oIMSRw6Mgc+G7rSBk4bulbmcgZOG7i2NoIHbhu6UgdHJvbmcgdGjhu51pIGdpYW4gZMOgaS4NCi0gICAqKkvhur90IGx14bqtbjoqKiBWaeG7h2MgbeG6pXQga2jDoWNoIGjDoG5nIGNo4bunIHnhur91IHjhuqN5IHJhIHRyb25nIGdpYWkgxJFv4bqhbiAidHLEg25nIG3huq10Ii4gTuG6v3UgbeG7mXQga2jDoWNoIGjDoG5nIHbGsOG7o3QgcXVhIMSRxrDhu6NjIG3hu5FjIHRo4budaSBnaWFuIGJhbiDEkeG6p3UsIGto4bqjIG7Eg25nIGjhu40g4bufIGzhuqFpIHPhur0gdMSDbmcgbMOqbiDEkcOhbmcga+G7gy4NCi0+ICoqTmjhuq1uIHjDqXQ6KiogS2jDoWNoIGjDoG5nIGtow7RuZyBy4budaSBi4buPIGPDsyB0aOG7nWkgZ2lhbiBn4bqvbiBiw7MgdHJ1bmcgYsOsbmggKDM3LjYgdGjDoW5nKSBjYW8gaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBraMOhY2ggaMOgbmcgxJHDoyBy4budaSBi4buPICgxOCB0aMOhbmcpLiBUaOG7nWkgZ2lhbiBn4bqvbiBiw7MgY8Ogbmcgbmfhuq9uLCBuZ3V5IGPGoSBraMOhY2ggaMOgbmcgcuG7nWkgYuG7jyBjw6BuZyBjYW8uDQoNCiMgKipDSMavxqBORyA0OiBNw5QgSMOMTkggSOG7kkkgUVVZIMSQxqBOIEJJ4bq+TioqDQoNClBo4bqnbiBuw6B5IHPhur0gcGjDom4gdMOtY2ggdMOhYyDEkeG7mW5nIGPhu6dhIHThu6tuZyBiaeG6v24gxJHhu5ljIGzhuq1wIChgQ29udHJhY3RgLCBgU2VuaW9yQ2l0aXplbmAsIGBQYXltZW50TWV0aG9kYCwgYEludGVybmV0U2VydmljZWAsIGB0ZW51cmVgKSBsw6puIGto4bqjIG7Eg25nIHLhu51pIGLhu48gKGBDaHVybmApIGPhu6dhIGtow6FjaCBow6BuZyBt4buZdCBjw6FjaCByacOqbmcgbOG6uy4gQ2jDum5nIHRhIHPhur0gc+G7rSBk4bulbmcgNCBsb+G6oWkgbcO0IGjDrG5oOiBYw6FjIHN14bqldCB0dXnhur9uIHTDrW5oIChMUE0pLCBMb2dpdCwgUHJvYml0LCB2w6AgQ2xvZ2xvZy4NCg0KIyMgKio0LjEuIFTDoWMgxJHhu5luZyBj4bunYSBgQ29udHJhY3RgIChMb+G6oWkgaOG7o3AgxJHhu5NuZykgxJHhur9uIGBDaHVybmAqKg0KDQojIyMgKio0LjEuMS4gTcO0IGjDrG5oIFjDoWMgc3XhuqV0IFR1eeG6v24gdMOtbmggKExQTSkqKg0KYGBge3IgbHBtLWNvbnRyYWN0LXNpbmdsZS1maW5hbH0NCmxwbV9jb250cmFjdCA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gQ29udHJhY3QsIGRhdGEgPSBkZl9jbGVhbiwgZmFtaWx5ID0gZ2F1c3NpYW4obGluayA9ICJpZGVudGl0eSIpKQ0Kc3VtbWFyeShscG1fY29udHJhY3QpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KDQpIw6BtIGjhu5NpIHF1eSDEkcaw4bujYyDGsOG7m2MgbMaw4bujbmcgbmjGsCBzYXU6DQokJA0KXGhhdHtccGl9ID0gMC40MjcxIC0gMC4zMTQ0IFx0aW1lcyBcdGV4dHtDb250cmFjdE9uZSB5ZWFyfSAtIDAuMzk4NiBcdGltZXMgXHRleHR7Q29udHJhY3RUd28geWVhcn0NCiQkDQotIEvhur90IHF14bqjIHThu6sgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIChHTE0gduG7m2kgaMOgbSBsacOqbiBr4bq/dCBpZGVudGl0eSkgY2hvIHRo4bqleSBiaeG6v24gQ29udHJhY3QgDQooTG/huqFpIGjhu6NwIMSR4buTbmcpIGPDsyDhuqNuaCBoxrDhu59uZyByw7UgcuG7h3QgxJHhur9uIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gZOG7i2NoIHbhu6UgKENodXJuX2JpbmFyeSkuIEPhu6UgdGjhu4MsIHNvIHbhu5tpIA0Ka2jDoWNoIGjDoG5nIHPhu60gZOG7pW5nIGjhu6NwIMSR4buTbmcgdGjDoW5nIG3hu5l0ICht4bupYyB0aGFtIGNoaeG6v3UpLCBuaOG7r25nIGtow6FjaCBow6BuZyBjw7MgaOG7o3AgxJHhu5NuZyBt4buZdCBuxINtIGPDsyB4w6FjIHN14bqldCBy4budaSBi4buPIHRydW5nIGLDrG5oIGdp4bqjbSAzMS40JSwgdsOgIHbhu5tpIGjhu6NwIMSR4buTbmcgaGFpIG7Eg20gdGjDrCB4w6FjIHN14bqldCBuw6B5IGdp4bqjbSB04bubaSAzOS45JS4gQ8OhYyBo4buHIHPhu5EgaOG7k2kgcXV5IMSR4buBdSDDom0gdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogcuG6pXQgY2FvIChwLXZhbHVlIDwgMmUtMTYpLCBjaG8gdGjhuqV5IG3hu5FpIHF1YW4gaOG7hyDDom0gbeG6oW5oIG3hur0gZ2nhu69hIMSR4buZIGTDoGkgaOG7o3AgxJHhu5NuZyB2w6Aga2jhuqMgbsSDbmcgcuG7nWkgYuG7jy4gTsOzaSBjw6FjaCBraMOhYywga2jDoWNoIGjDoG5nIGNhbSBr4bq/dCBsw6J1IGTDoGkgY8OzIHh1IGjGsOG7m25nIGfhuq9uIGLDsyBoxqFuIHbhu5tpIGThu4tjaCB24bulLCBzbyB24bubaSBuaMOzbSBjaOG7iSBkw7luZyB0aGVvIHRow6FuZy4gTeG7qWMgxJHhu5kgZ2nhuqNpIHRow61jaCBj4bunYSBtw7QgaMOsbmgg4bufIG3hu6ljIHTGsMahbmcgxJHhu5FpLCB24bubaSBjaOG7iSBz4buRIHBzZXVkby1SwrIga2hv4bqjbmcgMTYuOCUsIHBow7kgaOG7o3AgdHJvbmcgYuG7kWkgY+G6o25oIGjDoG5oIHZpIGtow6FjaCBow6BuZyB0aMaw4budbmcgYuG7iyBjaGkgcGjhu5FpIGLhu59pIG5oaeG7gXUgeeG6v3UgdOG7kSBraMOhYyBuaGF1LiBL4bq/dCBxdeG6oyBuw6B5IGfhu6NpIMO9IHLhurFuZyBkb2FuaCBuZ2hp4buHcCBuw6puIGPDom4gbmjhuq9jIGPDoWMgY2jDrW5oIHPDoWNoIGtodXnhur9uIGtow61jaCBraMOhY2ggaMOgbmcgY2h1eeG7g24gc2FuZyBo4bujcCDEkeG7k25nIGTDoGkgaOG6oW4gbmjhurFtIGdp4bqjbSB0aGnhu4N1IHThu7cgbOG7hyBy4budaSBi4buPIGThu4tjaCB24bulLg0KDQoNCiMjIyAqKjQuMS4yLiBNw7QgaMOsbmggTG9naXQqKg0KYGBge3IgbG9naXQtY29udHJhY3Qtc2luZ2xlLWZpbmFsfQ0KbG9naXRfY29udHJhY3QgPC0gZ2xtKENodXJuX2JpbmFyeSB+IENvbnRyYWN0LCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSkNCnN1bW1hcnkobG9naXRfY29udHJhY3QpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KDQpIw6BtIGjhu5NpIHF1eSDEkcaw4bujYyDGsOG7m2MgbMaw4bujbmcgbmjGsCBzYXU6DQokJA0KXGxvZ1xsZWZ0KFxmcmFje1xoYXR7XHBpfX17MSAtIFxoYXR7XHBpfX1ccmlnaHQpID0gLTAuMjk3MyAtIDEuNzY5MCBcdGltZXMgXHRleHR7Q29udHJhY3RPbmUgeWVhcn0gLSAzLjIzNTcgXHRpbWVzIFx0ZXh0e0NvbnRyYWN0VHdvIHllYXJ9DQokJA0KDQotIE3DtCBow6xuaCBo4buTaSBxdXkgbG9naXN0aWMgcGjDom4gdMOtY2ggbeG7kWkgcXVhbiBo4buHIGdp4buvYSBsb+G6oWkgaOG7o3AgxJHhu5NuZyAoQ29udHJhY3QpIHbDoCBraOG6oyBuxINuZyBy4budaSBi4buPIGThu4tjaCB24bulIChDaHVybl9iaW5hcnkpIGNobyB0aOG6pXkgYmnhur9uIGjhu6NwIMSR4buTbmcgY8OzIOG6o25oIGjGsOG7n25nIHLhuqV0IHLDtSBy4buHdCB2w6AgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBjYW8gxJHhur9uIGjDoG5oIHZpIGPhu6dhIGtow6FjaCBow6BuZy4gQ+G7pSB0aOG7gywgc28gduG7m2kga2jDoWNoIGjDoG5nIHPhu60gZOG7pW5nIGjhu6NwIMSR4buTbmcgdGhlbyB0aMOhbmcgKG3hu6ljIHRoYW0gY2hp4bq/dSksIGtow6FjaCBow6BuZyBjw7MgaOG7o3AgxJHhu5NuZyBt4buZdCBuxINtIGPDsyBsb2ctb2RkcyBy4budaSBi4buPIHRo4bqlcCBoxqFuIDEuNzcgxJHGoW4gduG7iywgY8OybiBraMOhY2ggaMOgbmcgY8OzIGjhu6NwIMSR4buTbmcgaGFpIG7Eg20gdGjDrCBsb2ctb2RkcyBy4budaSBi4buPIHRo4bqlcCBoxqFuIMSR4bq/biAzLjI0IMSRxqFuIHbhu4suIFbDrCBjw6FjIGjhu4cgc+G7kSBo4buTaSBxdXkgxJHhu4F1IMOibSB2w6AgY8OzIHAtdmFsdWUgPCAyZS0xNiwgdGEgY8OzIHRo4buDIGto4bqzbmcgxJHhu4tuaCBy4bqxbmcgY2FtIGvhur90IGjhu6NwIMSR4buTbmcgZMOgaSBo4bqhbiBnacO6cCBnaeG6o20gxJHDoW5nIGvhu4Mga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyBk4buLY2ggduG7pS4NCg0KLSDEkOG7gyBk4buFIGRp4buFbiBnaeG6o2ksIGtoaSBjaHV54buDbiBjw6FjIGjhu4cgc+G7kSBo4buTaSBxdXkgdGjDoG5oIE9kZHMgUmF0aW8gKE9SKSwgdGEgxJHGsOG7o2M6DQoNCiAgLSBPUiBj4bunYSBo4bujcCDEkeG7k25nIG3hu5l0IG7Eg20g4omIIGV4cCjiiJIxLjc2OTAzKSDiiYggMC4xNzEsIHThu6ljIGdp4bqjbSA4Mi45JSBraOG6oyBuxINuZyBy4budaSBi4buPIHNvIHbhu5tpIGjhu6NwIMSR4buTbmcgdGjDoW5nIG3hu5l0Ow0KDQogIC0gT1IgY+G7p2EgaOG7o3AgxJHhu5NuZyBoYWkgbsSDbSDiiYggZXhwKOKIkjMuMjM1NzEpIOKJiCAwLjAzOSwgdOG7qWMgZ2nhuqNtIMSR4bq/biA5Ni4xJSBraOG6oyBuxINuZyBy4budaSBi4buPLg0KDQotIMSQaeG7gXUgbsOgeSBuaOG6pW4gbeG6oW5oIHTDoWMgxJHhu5luZyBj4buxYyBr4buzIG3huqFuaCBt4bq9IGPhu6dhIGxv4bqhaSBo4bujcCDEkeG7k25nIMSR4bq/biBow6BuaCB2aSBraMOhY2ggaMOgbmcuIE3DtCBow6xuaCBjxaluZyBjw7MgbeG7qWMgxJHhu5kgcGjDuSBo4bujcCB0xrDGoW5nIMSR4buRaSB04buRdCwgduG7m2kgZ2nhuqNtIGRldmlhbmNlIHLDtSBy4buHdCB04burIDgxNDMuNCB4deG7kW5nIGPDsm4gNjc2Mi41LCB2w6AgQUlDID0gNjc2OC41LCB0aOG6pXAgaMahbiBzbyB24bubaSBtw7QgaMOsbmggdHV54bq/biB0w61uaCwgY2hvIHRo4bqleSBtw7QgaMOsbmggbG9naXN0aWMgbMOgIGzhu7FhIGNo4buNbiBwaMO5IGjhu6NwIGjGoW4gdHJvbmcgdHLGsOG7nW5nIGjhu6NwIGJp4bq/biBwaOG7pSB0aHXhu5ljIGzDoCBuaOG7iyBwaMOibi4gS+G6v3QgcXXhuqMgbsOgeSBn4bujaSBt4bufIGjGsOG7m25nIHRp4bq/cCBj4bqtbiBjaGnhur9uIGzGsOG7o2M6IGRvYW5oIG5naGnhu4dwIG7Dqm4gxJHhuql5IG3huqFuaCBjw6FjIGNow61uaCBzw6FjaCBjaHV54buDbiDEkeG7lWkga2jDoWNoIGjDoG5nIHThu6sgaOG7o3AgxJHhu5NuZyBuZ+G6r24gaOG6oW4gc2FuZyBkw6BpIGjhuqFuIG5o4bqxbSBnaeG6o20gxJHDoW5nIGvhu4MgdOG7tyBs4buHIHLhu51pIGLhu48gZOG7i2NoIHbhu6UuDQoNCiMjIyAqKjQuMS4zLiBNw7QgaMOsbmggUHJvYml0KioNCmBgYHtyIHByb2JpdC1jb250cmFjdC1zaW5nbGUtZmluYWx9DQpwcm9iaXRfY29udHJhY3QgPC0gZ2xtKENodXJuX2JpbmFyeSB+IENvbnRyYWN0LCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAicHJvYml0IikpDQpzdW1tYXJ5KHByb2JpdF9jb250cmFjdCkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqDQoNCkjDoG0gUHJvYml0IMaw4bubYyBsxrDhu6NuZyBuaMawIHNhdToNCiQkDQpcUGhpXnstMX0oXGhhdHtccGl9KSA9IC0wLjE4MzcgLSAxLjAyODIgXHRpbWVzIFx0ZXh0e0NvbnRyYWN0T25lIHllYXJ9IC0gMS43MTk4IFx0aW1lcyBcdGV4dHtDb250cmFjdFR3byB5ZWFyfQ0KJCQNCg0KLSBNw7QgaMOsbmggaOG7k2kgcXV5IG5o4buLIHBow6JuIHbhu5tpIGjDoG0gbGnDqm4ga+G6v3QgcHJvYml0IGPFqW5nIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGtp4buDbSDEkeG7i25oIOG6o25oIGjGsOG7n25nIGPhu6dhIGxv4bqhaSBo4bujcCDEkeG7k25nIChDb250cmFjdCkgxJHhur9uIGto4bqjIG7Eg25nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UgKENodXJuX2JpbmFyeSkuIEvhur90IHF14bqjIGNobyB0aOG6pXkgY+G6oyBoYWkgbeG7qWMgaOG7o3AgxJHhu5NuZyBkw6BpIGjhuqFuIMSR4buBdSBjw7Mg4bqjbmggaMaw4bufbmcgdGnDqnUgY+G7sWMgdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogcuG6pXQgY2FvIMSR4bq/biB4w6FjIHN14bqldCBy4budaSBi4buPLiBD4bulIHRo4buDLCBzbyB24bubaSBraMOhY2ggaMOgbmcgZMO5bmcgaOG7o3AgxJHhu5NuZyB0aGVvIHRow6FuZywga2jDoWNoIGjDoG5nIHPhu60gZOG7pW5nIGjhu6NwIMSR4buTbmcgbeG7mXQgbsSDbSBjw7MgZ2nhuqNtIDEuMDMgxJHGoW4gduG7iyB6LXNjb3JlIHRyb25nIHjDoWMgc3XhuqV0IHLhu51pIGLhu48sIGPDsm4gaOG7o3AgxJHhu5NuZyBoYWkgbsSDbSB0aMOsIGdp4bqjbSB04bubaSAxLjcyIMSRxqFuIHbhu4sgei1zY29yZS4gQ8OhYyBo4buHIHPhu5EgbsOgeSDEkeG7gXUgY8OzIHAtdmFsdWUgPCAyZS0xNiwgY2hvIHRo4bqleSB0w6FjIMSR4buZbmcgY+G7p2EgxJHhu5kgZMOgaSBo4bujcCDEkeG7k25nIGzDoCBj4buxYyBr4buzIHLDtSByw6BuZyB2w6AgxJHDoW5nIHRpbiBj4bqteS4NCg0KLSBW4buBIG3hurd0IGLhuqNuIGNo4bqldCwgbcO0IGjDrG5oIHByb2JpdCBjxaluZyBjaG8gY8O5bmcgbeG7mXQga+G6v3QgbHXhuq1uIG5oxrAgbcO0IGjDrG5oIGxvZ2lzdGljOiBraMOhY2ggaMOgbmcgY8OzIGjhu6NwIMSR4buTbmcgZMOgaSBo4bqhbiDDrXQgY8OzIGto4bqjIG7Eg25nIHLhu51pIGLhu48gaMahbiBzbyB24bubaSBo4bujcCDEkeG7k25nIG5n4bqvbiBo4bqhbi4gR2nDoSB0cuG7iyBkZXZpYW5jZSB2w6AgQUlDIGdp4buRbmcgbmjGsCBtw7QgaMOsbmggbG9naXN0aWMgKEFJQyA9IDY3NjguNSksIGNobyB0aOG6pXkgaGFpIG3DtCBow6xuaCBjw7MgbeG7qWMgxJHhu5kgcGjDuSBo4bujcCB0xrDGoW5nIMSRxrDGoW5nLiBUdXkgbmhpw6puLCBtw7QgaMOsbmggcHJvYml0IGRp4buFbiBnaeG6o2kga2jDsyBoxqFuIG3hu5l0IGNow7p0IHNvIHbhu5tpIGxvZ2lzdGljLCBkbyBo4buHIHPhu5EgaOG7k2kgcXV5IGJp4buDdSB0aOG7iyB0aGF5IMSR4buVaSB0aGVvIHRoYW5nIHotc2NvcmUgY+G7p2EgcGjDom4gcGjhu5FpIGNodeG6qW4gdGhheSB2w6wgbG9nLW9kZHMuDQoNCi0gTmjDrG4gY2h1bmcsIG3DtCBow6xuaCBwcm9iaXQgY+G7p25nIGPhu5EgdGjDqm0gYuG6sW5nIGNo4bupbmcgcuG6sW5nIHZp4buHYyBrw6lvIGTDoGkgdGjhu51pIGjhuqFuIGjhu6NwIMSR4buTbmcgbMOgIG3hu5l0IGNoaeG6v24gbMaw4bujYyBoaeG7h3UgcXXhuqMgdHJvbmcgdmnhu4djIGdp4bqjbSBuZ3V5IGPGoSBt4bqldCBraMOhY2ggaMOgbmcsIHbDoCBjw7MgdGjhu4MgxJHGsOG7o2MgZG9hbmggbmdoaeG7h3AgdOG6rW4gZOG7pW5nIHRow7RuZyBxdWEgY8OhYyBnw7NpIGtodXnhur9uIG3Do2ksIGNow61uaCBzw6FjaCBnaeG7ryBjaMOibiwgaG/hurdjIG7Dom5nIGNhbyBnacOhIHRy4buLIGjhu6NwIMSR4buTbmcgZMOgaSBo4bqhbi4NCg0KDQoNCiMjIyAqKjQuMS40LiBNw7QgaMOsbmggQ2xvZ2xvZyoqDQpgYGB7ciBjbG9nbG9nLWNvbnRyYWN0LXNpbmdsZS1maW5hbH0NCmNsb2dsb2dfY29udHJhY3QgPC0gZ2xtKENodXJuX2JpbmFyeSB+IENvbnRyYWN0LCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAiY2xvZ2xvZyIpKQ0Kc3VtbWFyeShjbG9nbG9nX2NvbnRyYWN0KQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KROG7sWEgdHLDqm4ga+G6v3QgcXXhuqMgbcO0IGjDrG5oIGjhu5NpIHF1eSB24bubaSBow6BtIGxpw6puIGvhur90IGNsb2dsb2csIHRhIGPDsyBwaMawxqFuZyB0csOsbmg6DQokJA0KXGxvZygtXGxvZygxIC0gXGhhdHtccGl9KSkgPSAtMC41ODUxIC0gMS41MzgwIFx0aW1lcyBcdGV4dHtDb250cmFjdE9uZSB5ZWFyfSAtIDIuOTU4OCBcdGltZXMgXHRleHR7Q29udHJhY3RUd28geWVhcn0NCiQkDQoNCi0gTcO0IGjDrG5oIGjhu5NpIHF1eSBuaOG7iyBwaMOibiB24bubaSBow6BtIGxpw6puIGvhur90IGNvbXBsZW1lbnRhcnkgbG9nLWxvZyAoY2xvZ2xvZykgdGnhur9wIHThu6VjIGNobyB0aOG6pXkgYmnhur9uIENvbnRyYWN0IChMb+G6oWkgaOG7o3AgxJHhu5NuZykgY8OzIOG6o25oIGjGsOG7n25nIG3huqFuaCB2w6AgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBjYW8gxJHhur9uIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gZOG7i2NoIHbhu6UgKENodXJuX2JpbmFyeSkuIEPhu6UgdGjhu4MsIHNvIHbhu5tpIG5ow7NtIGtow6FjaCBow6BuZyBz4butIGThu6VuZyBo4bujcCDEkeG7k25nIHRow6FuZyBt4buZdCwga2jDoWNoIGjDoG5nIGPDsyBo4bujcCDEkeG7k25nIG3hu5l0IG7Eg20gY8OzIGdp4bqjbSAxLjU0IMSRxqFuIHbhu4sgbG9nKC1sb2coMSAtIHApKSwgdHJvbmcga2hpIGtow6FjaCBow6BuZyBjw7MgaOG7o3AgxJHhu5NuZyBoYWkgbsSDbSB0aMOsIGdp4bqjbSDEkeG6v24gMi45NiDEkcahbiB24buLLCB24bubaSBwLXZhbHVlIMSR4buBdSA8IDJlLTE2LiBDw6FjIGjhu4cgc+G7kSDDom0gY2hvIHRo4bqleSBt4buRaSBxdWFuIGjhu4cgbmdo4buLY2ggxJHhuqNvOiBo4bujcCDEkeG7k25nIGTDoGkgaOG6oW4gbMOgbSBnaeG6o20geMOhYyBzdeG6pXQgcuG7nWkgYuG7jy4NCg0KLSBIw6BtIGxpw6puIGvhur90IGNsb2dsb2cgdGjGsOG7nW5nIHBow7kgaOG7o3AgdHJvbmcgY8OhYyB0w6xuaCBodeG7kW5nIG3DoCB4w6FjIHN14bqldCB44bqjeSByYSBz4buxIGtp4buHbiB0aOG6pXAgbmjGsG5nIHLhu6dpIHJvIHTDrWNoIGzFqXkgdGhlbyB0aOG7nWkgZ2lhbiwgdsOtIGThu6UgbmjGsCB0cm9uZyBjw6FjIG3DtCBow6xuaCBz4buRbmcgc8OzdCBob+G6t2MgZOG7ryBsaeG7h3UgdGltZS10by1ldmVudC4gVHJvbmcgYuG7kWkgY+G6o25oIG7DoHksIG3hurdjIGTDuSB4w6FjIHN14bqldCBy4budaSBi4buPIGtow7RuZyBo4bqzbiBsw6AgY+G7sWMgdGjhuqVwLCBtw7QgaMOsbmggY2xvZ2xvZyB24bqrbiDEkWVtIGzhuqFpIGvhur90IHF14bqjIHBow7kgaOG7o3AsIHbhu5tpIGdpw6EgdHLhu4sgZGV2aWFuY2UgdsOgIEFJQyAoNjc2OC41KSBuZ2FuZyBi4bqxbmcgduG7m2kgbcO0IGjDrG5oIGxvZ2lzdGljIHbDoCBwcm9iaXQsIGNobyB0aOG6pXkgbeG7qWMgxJHhu5kga2jhu5twIG3DtCBow6xuaCB0xrDGoW5nIMSRxrDGoW5nLg0KDQotIMSQaeG7g20ga2jDoWMgYmnhu4d0IGzDoCBow6BtIGxpw6puIGvhur90IGNsb2dsb2cga2jDtG5nIMSR4buRaSB44bupbmcsIHBo4bqjbiDDoW5oIHLDtSBoxqFuIHRyb25nIHRyxrDhu51uZyBo4bujcCBow6BuaCB2aSBy4budaSBi4buPIGThu4tjaCB24bulIGPDsyB0aOG7gyBraMO0bmcgeOG6o3kgcmEgbmfhuqt1IG5oacOqbiBtw6AgdMOtY2ggbMWpeSBy4bunaSBybyB0aGVvIHRo4budaSBnaWFuIHPhu60gZOG7pW5nLiBEw7kgZGnhu4VuIGdp4bqjaSBo4buHIHPhu5EgaOG7k2kgcXV5IHRyb25nIG3DtCBow6xuaCBjbG9nbG9nIHBo4bupYyB04bqhcCBoxqFuIHNvIHbhu5tpIGxvZ2lzdGljLCBr4bq/dCBxdeG6oyB24bqrbiBj4bunbmcgY+G7kSBuaOG6rW4gxJHhu4tuaCBy4bqxbmcga8OpbyBkw6BpIHRo4budaSBo4bqhbiBo4bujcCDEkeG7k25nIGPDsyB0aOG7gyBsw6BtIGdp4bqjbSBt4bqhbmggcuG7p2kgcm8ga2jDoWNoIGjDoG5nIHLhu51pIGLhu48g4oCTIG3hu5l0IGNoaeG6v24gbMaw4bujYyBtw6AgZG9hbmggbmdoaeG7h3AgbsOqbiBraGFpIHRow6FjIGhp4buHdSBxdeG6oyB0aMO0bmcgcXVhIGPDoWMgZ8OzaSBjxrDhu5tjIHbDoCBjaMawxqFuZyB0csOsbmggZ2nhu68gY2jDom4ga2jDoWNoIGjDoG5nLg0KDQojIyMgKio0LjEuNS4gxJDDoW5oIGdpw6EgY8OhYyBtw7QgaMOsbmgqKg0KYGBge3IgY29tcGFyZS1jb250cmFjdC1tb2RlbHN9DQphaWNfY29udHJhY3QgPC0gZGF0YS5mcmFtZSgNCiAgTW9kZWwgPSBjKCJMUE0iLCJMb2dpdCIsICJQcm9iaXQiLCAiQ2xvZ2xvZyIpLA0KICBBSUMgPSBjKEFJQyhscG1fY29udHJhY3QpLEFJQyhsb2dpdF9jb250cmFjdCksIEFJQyhwcm9iaXRfY29udHJhY3QpLCBBSUMoY2xvZ2xvZ19jb250cmFjdCkpDQopDQprYWJsZShhaWNfY29udHJhY3QsIGNhcHRpb24gPSAiU28gc8OhbmggQUlDIGPDoWMgbcO0IGjDrG5oIGNobyBiaeG6v24gQ29udHJhY3QiKQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KLSBLaGkgc28gc8OhbmggY8OhYyBtw7QgaMOsbmggaOG7k2kgcXV5IHbhu5tpIGJp4bq/biDEkeG7mWMgbOG6rXAgQ29udHJhY3QsIGNo4buJIHPhu5EgQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiAoQUlDKSDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyDEkcOhbmggZ2nDoSBt4bupYyDEkeG7mSBwaMO5IGjhu6NwIGPhu6dhIG3DtCBow6xuaCB24bubaSBk4buvIGxp4buHdS4gS+G6v3QgcXXhuqMgY2hvIHRo4bqleSBtw7QgaMOsbmggTGluZWFyIFByb2JhYmlsaXR5IE1vZGVsIChMUE0pIGPDsyBBSUMgPSA3MTgyLjM3LCBjYW8gaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBiYSBtw7QgaMOsbmggaOG7k2kgcXV5IG5o4buLIHBow6JuOiBMb2dpdCwgUHJvYml0IHbDoCBDb21wbGVtZW50YXJ5IExvZy1sb2cgKENsb2dsb2cpIMSR4buBdSBjw7MgQUlDID0gNjc2OC41Mi4gVsOsIEFJQyBjw6BuZyB0aOG6pXAgdGjDrCBtw7QgaMOsbmggY8OgbmcgdOG7kXQgKHbhu4EgbeG6t3QgY8OibiBi4bqxbmcgZ2nhu69hIMSR4buZIHBow7kgaOG7o3AgdsOgIMSR4buZIHBo4bupYyB04bqhcCksIG7Dqm4gY8OzIHRo4buDIGvhur90IGx14bqtbiBy4bqxbmcgY8OhYyBtw7QgaMOsbmggbmjhu4sgcGjDom4gKGxvZ2l0LCBwcm9iaXQsIGNsb2dsb2cpIHBow7kgaOG7o3AgaMahbiBzbyB24bubaSBMUE0gdHJvbmcgdmnhu4djIG3DtCBow6xuaCBow7NhIGto4bqjIG7Eg25nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UuDQoNCi0gTmdvw6BpIHJhLCB2w6wgY+G6oyBiYSBtw7QgaMOsbmggbmjhu4sgcGjDom4gxJHhu4F1IGNobyBr4bq/dCBxdeG6oyBBSUMgZ2nhu5FuZyBuaGF1LCBuw6puIHbhu4EgbeG6t3QgxJHhu4tuaCBsxrDhu6NuZywga2jDtG5nIGPDsyBz4buxIGtow6FjIGJp4buHdCDEkcOhbmcga+G7gyBnaeG7r2EgY2jDum5nIHRyb25nIGLhu5FpIGPhuqNuaCBiaeG6v24gZ2nhuqNpIHRow61jaCBkdXkgbmjhuqV0IGzDoCBDb250cmFjdC4gVHV5IG5oacOqbiwgdHXhu7MgdsOgbyBt4bulYyB0acOqdSBuZ2hpw6puIGPhu6l1IHbDoCDEkeG6t2MgxJFp4buDbSBwaMOibiBwaOG7kWkgZOG7ryBsaeG7h3UsIGzhu7FhIGNo4buNbiBnaeG7r2EgbG9naXN0aWMsIHByb2JpdCBoYXkgY2xvZ2xvZyBjw7MgdGjhu4MgZOG7sWEgdHLDqm4gY8OhY2ggZGnhu4VuIGdp4bqjaSBo4buHIHPhu5EgaOG7k2kgcXV5IGhv4bq3YyBnaeG6oyDEkeG7i25oIHbhu4EgeMOhYyBzdeG6pXQgeOG6o3kgcmEgc+G7sSBraeG7h24uIETDuSB24bqteSwgxJFp4buDbSBjaHVuZyBu4buVaSBi4bqtdCBsw6AgYmnhur9uIENvbnRyYWN0IGx1w7RuIHRo4buDIGhp4buHbiB0w6FjIMSR4buZbmcgdGnDqnUgY+G7sWMgdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogbeG6oW5oIG3hur0gbMOqbiB4w6FjIHN14bqldCBy4budaSBi4buPLCBi4bqldCBr4buDIG3DtCBow6xuaCBuw6BvIMSRxrDhu6NjIHPhu60gZOG7pW5nLg0KDQotLS0NCg0KDQojIyAqKjQuMi4gVMOhYyDEkeG7mW5nIGPhu6dhIGBTZW5pb3JDaXRpemVuYCoqDQoNCiMjIyAqKjQuMi4xLiBNw7QgaMOsbmggWMOhYyBzdeG6pXQgVHV54bq/biB0w61uaCAoTFBNKSoqDQpgYGB7ciBscG0tc2VuaW9yLXNpbmdsZS1maW5hbH0NCmxwbV9zZW5pb3IgPC0gZ2xtKENodXJuX2JpbmFyeSB+IFNlbmlvckNpdGl6ZW4sIGRhdGEgPSBkZl9jbGVhbiwgZmFtaWx5ID0gZ2F1c3NpYW4obGluayA9ICJpZGVudGl0eSIpKQ0Kc3VtbWFyeShscG1fc2VuaW9yKQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KSMOgbSBo4buTaSBxdXkgxJHGsOG7o2MgxrDhu5tjIGzGsOG7o25nIG5oxrAgc2F1Og0KJCQNClxoYXR7XHBpfSA9IDAuMjM2MSArIDAuMTgwMyBcdGltZXMgXHRleHR7U2VuaW9yQ2l0aXplblllc30NCiQkDQoNCi0gTcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIChMUE0pIHBow6JuIHTDrWNoIOG6o25oIGjGsOG7n25nIGPhu6dhIGJp4bq/biBTZW5pb3JDaXRpemVuIChLaMOhY2ggaMOgbmcgbMOgIG5nxrDhu51pIGNhbyB0deG7lWkpIMSR4bq/biB4w6FjIHN14bqldCBy4budaSBi4buPIGThu4tjaCB24bulIChDaHVybl9iaW5hcnkpIGNobyB0aOG6pXkgbeG7kWkgcXVhbiBo4buHIGTGsMahbmcgdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogY2FvLiBD4bulIHRo4buDLCBo4buHIHPhu5EgaOG7k2kgcXV5IGPhu6dhIG5ow7NtIGtow6FjaCBow6BuZyBjYW8gdHXhu5VpIGzDoCAwLjE4MDMsIHbhu5tpIHAtdmFsdWUgPCAyZS0xNiwgY2hvIHRo4bqleSBy4bqxbmcga2jDoWNoIGjDoG5nIGzDoCBuZ8aw4budaSBjYW8gdHXhu5VpIGPDsyB4w6FjIHN14bqldCBy4budaSBi4buPIGThu4tjaCB24bulIHRydW5nIGLDrG5oIGNhbyBoxqFuIDE4LjAzIMSRaeG7g20gcGjhuqduIHRyxINtIHNvIHbhu5tpIGtow6FjaCBow6BuZyBraMO0bmcgcGjhuqNpIG5nxrDhu51pIGNhbyB0deG7lWksIGtoaSBnaeG7ryBjw6FjIHnhur91IHThu5Ega2jDoWMga2jDtG5nIMSR4buVaS4gVHJvbmcga2hpIMSRw7MsIGdpw6EgdHLhu4sgY2jhurduIChpbnRlcmNlcHQpIGzDoCAwLjIzNjUsIHRo4buDIGhp4buHbiB4w6FjIHN14bqldCBy4budaSBi4buPIHRydW5nIGLDrG5oIGPhu6dhIG5ow7NtIGtow7RuZyBwaOG6o2kgbmfGsOG7nWkgY2FvIHR14buVaSBsw6Aga2hv4bqjbmcgMjMuNjUlLg0KDQotIE3hurdjIGTDuSBo4buHIHPhu5EgbsOgeSBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHLDtSBy4buHdCwgc29uZyBtw7QgaMOsbmggY8OzIG3hu6ljIMSR4buZIGdp4bqjaSB0aMOtY2ggdGjhuqVwLCB0aOG7gyBoaeG7h24gcXVhIFLCsiB44bqlcCB44buJIDAuMDIyN3Thu6ljIGNo4buJIGtob+G6o25nIDIuMyUgcGjGsMahbmcgc2FpIHRyb25nIGJp4bq/biBDaHVybiDEkcaw4bujYyBnaeG6o2kgdGjDrWNoIGLhu59pIGJp4bq/biBTZW5pb3JDaXRpemVuLiBBSUMgY+G7p2EgbcO0IGjDrG5oIGPFqW5nIGtow6EgY2FvICg4MzEwLjMpLCBjaG8gdGjhuqV5IMSRw6J5IGtow7RuZyBwaOG6o2kgbcO0IGjDrG5oIHBow7kgaOG7o3AgbeG6oW5oIG7hur91IGNo4buJIHjDqXQgcmnDqm5nIGJp4bq/biBTZW5pb3JDaXRpemVuLg0KDQotIFTDs20gbOG6oWksIG3DtCBow6xuaCBjaOG7iSByYSBy4bqxbmcgbmfGsOG7nWkgY2FvIHR14buVaSBjw7MgeHUgaMaw4bubbmcgcuG7nWkgYuG7jyBk4buLY2ggduG7pSBjYW8gaMahbiDEkcOhbmcga+G7gywgbmjGsG5nIHnhur91IHThu5EgbsOgeSBjaOG7iSBnaeG6o2kgdGjDrWNoIMSRxrDhu6NjIG3hu5l0IHBo4bqnbiBy4bqldCBuaOG7jyBz4buxIHRoYXkgxJHhu5VpIHRyb25nIGjDoG5oIHZpIHLhu51pIGLhu48uIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IGPhuqduIGLhu5Ugc3VuZyB0aMOqbSBjw6FjIGJp4bq/biBxdWFuIHRy4buNbmcga2jDoWMgxJHhu4MgeMOieSBk4buxbmcgbcO0IGjDrG5oIGThu7EgxJFvw6FuIGNow61uaCB4w6FjIGjGoW4uDQoNCg0KDQojIyMgKio0LjIuMi4gTcO0IGjDrG5oIExvZ2l0KioNCmBgYHtyIGxvZ2l0LXNlbmlvci1zaW5nbGUtZmluYWx9DQpsb2dpdF9zZW5pb3IgPC0gZ2xtKENodXJuX2JpbmFyeSB+IFNlbmlvckNpdGl6ZW4sIGRhdGEgPSBkZl9jbGVhbiwgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpKQ0Kc3VtbWFyeShsb2dpdF9zZW5pb3IpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KDQpIw6BtIGjhu5NpIHF1eSDEkcaw4bujYyDGsOG7m2MgbMaw4bujbmcgbmjGsCBzYXU6DQokJA0KXGxvZ1xsZWZ0KFxmcmFje1xoYXR7XHBpfX17MSAtIFxoYXR7XHBpfX1ccmlnaHQpID0gLTEuMTcxOSArIDAuODMwNiBcdGltZXMgXHRleHR7U2VuaW9yQ2l0aXplblllc30NCiQkDQoNCi0gTcO0IGjDrG5oIGjhu5NpIHF1eSBsb2dpc3RpYyDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyDEkcOhbmggZ2nDoSDhuqNuaCBoxrDhu59uZyBj4bunYSB2aeG7h2Mga2jDoWNoIGjDoG5nIGzDoCBuZ8aw4budaSBjYW8gdHXhu5VpIChTZW5pb3JDaXRpemVuKSDEkeG6v24ga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyBk4buLY2ggduG7pSAoQ2h1cm5fYmluYXJ5KS4gS+G6v3QgcXXhuqMgY2hvIHRo4bqleSBo4buHIHPhu5EgaOG7k2kgcXV5IGNobyBuaMOzbSBraMOhY2ggaMOgbmcgY2FvIHR14buVaSBsw6AgMC44MzYxLCB24bubaSBwLXZhbHVlIDwgMmUtMTYsIGNobyB0aOG6pXkgbeG7kWkgcXVhbiBo4buHIGTGsMahbmcgdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogcuG6pXQgY2FvIGdp4buvYSB2aeG7h2MgbMOgIG5nxrDhu51pIGNhbyB0deG7lWkgdsOgIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gZOG7i2NoIHbhu6UuDQoNCi0gSOG7hyBz4buRIGjhu5NpIHF1eSBkxrDGoW5nIGPDsyBuZ2jEqWEgbMOgIG5nxrDhu51pIGNhbyB0deG7lWkgY8OzIGto4bqjIG7Eg25nIHLhu51pIGLhu48gY2FvIGjGoW4gc28gduG7m2kgbmfGsOG7nWkga2jDtG5nIGNhbyB0deG7lWkuIEtoaSBjaHV54buDbiBzYW5nIE9kZHMgUmF0aW8gxJHhu4MgZOG7hSBkaeG7hW4gZ2nhuqNpLCB0YSBjw7M6DQoNCiQkDQpcdGV4dHtPUn0gPSBcZXhwKDAuODM2MSkgXGFwcHJveCAyLjMxDQokJA0KDQpU4bupYyBsw6AsIGtow6FjaCBow6BuZyBjYW8gdHXhu5VpIGPDsyBvZGRzIHLhu51pIGLhu48gZOG7i2NoIHbhu6UgY2FvIGjGoW4ga2hv4bqjbmcgMi4zMSBs4bqnbiBzbyB24bubaSBraMOhY2ggaMOgbmcga2jDtG5nIGNhbyB0deG7lWkuDQoNClR1eSBuaGnDqm4sIHjDqXQgduG7gSBt4bupYyDEkeG7mSBnaeG6o2kgdGjDrWNoLCBtw7QgaMOsbmggY8OzIG3hu6ljIGdp4bqjbSBkZXZpYW5jZSBraMO0bmcgbOG7m24g4oCTIHThu6sgODE0My40IChudWxsIGRldmlhbmNlKSB4deG7kW5nIDc5OTUuMiDigJMgdMawxqFuZyDEkcawxqFuZyB24bubaSBwc2V1ZG8tUsKyIGtob+G6o25nOg0KDQokJA0KUl4yIFxhcHByb3ggMSAtIFxmcmFjezc5OTUuMn17ODE0My40fSBcYXBwcm94IDAuMDE4Mg0KJCQNCg0KVOG7qWMgY2jhu4kga2hv4bqjbmcgMS44JSBwaMawxqFuZyBzYWkgdHJvbmcgeMOhYyBzdeG6pXQgcuG7nWkgYuG7jyDEkcaw4bujYyBnaeG6o2kgdGjDrWNoIGLhu59pIGJp4bq/biBTZW5pb3JDaXRpemVuLiDEkOG7k25nIHRo4budaSwgQUlDID0gNzk5OS4yLCBjYW8gaMahbiBuaGnhu4F1IHNvIHbhu5tpIGPDoWMgbcO0IGjDrG5oIGPDsyB0aMOqbSBiaeG6v24gQ29udHJhY3QuDQoNClTDs20gbOG6oWksIG3DtCBow6xuaCBjaOG7iSByYSBy4bqxbmcgbmfGsOG7nWkgY2FvIHR14buVaSBjw7MgeMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBjYW8gaMahbiDEkcOhbmcga+G7gywgbmjGsG5nIGJp4bq/biBTZW5pb3JDaXRpemVuIMSRxqFuIGzhursgY2jhu4kgxJHDs25nIHZhaSB0csOyIG5o4buPIHRyb25nIHZp4buHYyBk4buxIMSRb8OhbiBow6BuaCB2aSBy4budaSBi4buPLiBL4bq/dCBxdeG6oyBuw6B5IGfhu6NpIMO9IHLhurFuZyB54bq/dSB04buRIHR14buVaSB0w6FjIHR1eSBjw7Mg4bqjbmggaMaw4bufbmcsIG5oxrBuZyBj4bqnbiBr4bq/dCBo4bujcCB24bubaSBjw6FjIGJp4bq/biBraMOhYyDEkeG7gyBtw7QgaMOsbmggxJHhuqF0IMSRxrDhu6NjIMSR4buZIGNow61uaCB4w6FjIGNhbyBoxqFuLg0KDQoNCiMjIyAqKjQuMi4zLiBNw7QgaMOsbmggUHJvYml0KioNCmBgYHtyIHByb2JpdC1zZW5pb3Itc2luZ2xlLWZpbmFsfQ0KcHJvYml0X3NlbmlvciA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gU2VuaW9yQ2l0aXplbiwgZGF0YSA9IGRmX2NsZWFuLCBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gInByb2JpdCIpKQ0Kc3VtbWFyeShwcm9iaXRfc2VuaW9yKQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KSMOgbSBQcm9iaXQgxrDhu5tjIGzGsOG7o25nIG5oxrAgc2F1Og0KJCQNClxQaGleey0xfShcaGF0e1xwaX0pID0gLTAuNzE4OCArIDAuNDkwNyBcdGltZXMgXHRleHR7U2VuaW9yQ2l0aXplblllc30NCiQkDQotIE3DtCBow6xuaCBo4buTaSBxdXkgbmjhu4sgcGjDom4gc+G7rSBk4bulbmcgaMOgbSBsacOqbiBr4bq/dCBwcm9iaXQgdGnhur9wIHThu6VjIGtp4buDbSDEkeG7i25oIOG6o25oIGjGsOG7n25nIGPhu6dhIGJp4bq/biBTZW5pb3JDaXRpemVuIChraMOhY2ggaMOgbmcgbMOgIG5nxrDhu51pIGNhbyB0deG7lWkpIMSR4bq/biB4w6FjIHN14bqldCBy4budaSBi4buPIGThu4tjaCB24bulIChDaHVybl9iaW5hcnkpLiBL4bq/dCBxdeG6oyBjaG8gdGjhuqV5IGjhu4cgc+G7kSBo4buTaSBxdXkgY+G7p2EgbmjDs20ga2jDoWNoIGjDoG5nIGNhbyB0deG7lWkgbMOgIDAuNTA3NSwgduG7m2kgcC12YWx1ZSA8IDJlLTE2LCBjaOG7qW5nIHThu48gxJHDonkgbMOgIG3hu5l0IGJp4bq/biBnaeG6o2kgdGjDrWNoIGPDsyDhuqNuaCBoxrDhu59uZyBkxrDGoW5nIHbDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHLhuqV0IGNhby4NCg0KLSBUcm9uZyBtw7QgaMOsbmggcHJvYml0LCBo4buHIHPhu5EgaOG7k2kgcXV5IGtow7RuZyB0aOG7gyB0cuG7sWMgdGnhur9wIGNodXnhu4NuIHRow6BuaCBPZGRzIFJhdGlvIG5oxrAgdHJvbmcgbG9naXN0aWMsIHbDrCBuw7MgYmnhu4N1IGRp4buFbiB0aGF5IMSR4buVaSB0csOqbiB0aGFuZyB6LXNjb3JlIGPhu6dhIHBow6JuIHBo4buRaSBjaHXhuqluIGNodeG6qW4gaMOzYS4gVHV5IG5oacOqbiwgZOG6pXUgdsOgIMSR4buZIGzhu5tuIGPhu6dhIGjhu4cgc+G7kSB24bqrbiBjaG8gcGjDqXAgZGnhu4VuIGdp4bqjaSBy4bqxbmc6IHZp4buHYyBraMOhY2ggaMOgbmcgbMOgIG5nxrDhu51pIGNhbyB0deG7lWkgbMOgbSB0xINuZyB4w6FjIHN14bqldCBy4budaSBi4buPIGThu4tjaCB24bulLCB2w6AgbeG7qWMg4bqjbmggaMaw4bufbmcgbsOgeSBsw6AgxJHDoW5nIGvhu4MuDQoNCi0gVMawxqFuZyB04buxIG5oxrAgbcO0IGjDrG5oIGxvZ2lzdGljLCBtw7QgaMOsbmggcHJvYml0IG7DoHkgY8OzIGdpw6EgdHLhu4sgZGV2aWFuY2UgZ2nhuqNtIG5o4bq5IHThu6sgODE0My40IHh14buRbmcgNzk5NS4yLCB0xrDGoW5nIOG7qW5nIHbhu5tpIHBzZXVkby1SwrIg4omIIDEuODIlOg0KDQokJA0KUl4yIFxhcHByb3ggMSAtIFxmcmFjezc5OTUuMn17ODE0My40fSBcYXBwcm94IDAuMDE4Mg0KJCQNCg0KDQotIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IG3DtCBow6xuaCBjw7MgbeG7qWMgxJHhu5kgZ2nhuqNpIHRow61jaCBy4bqldCB0aOG6pXAsIHbDrCBiaeG6v24gU2VuaW9yQ2l0aXplbiDEkcahbiBs4bq7IGNo4buJIGdp4bqjaSB0aMOtY2ggxJHGsOG7o2MgbeG7mXQgcGjhuqduIG5o4buPIHPhu7EgYmnhur9uIHRoacOqbiB0cm9uZyBow6BuaCB2aSBy4budaSBi4buPIGThu4tjaCB24bulLiBBSUMgY+G7p2EgbcO0IGjDrG5oIGzDoCA3OTk5LjIsIGLhurFuZyB24bubaSBtw7QgaMOsbmggbG9naXN0aWMgc+G7rSBk4bulbmcgY8O5bmcgYmnhur9uLg0KDQotIFTDs20gbOG6oWksIGvhur90IHF14bqjIHThu6sgbcO0IGjDrG5oIHByb2JpdCBj4bunbmcgY+G7kSB0aMOqbSBi4bqxbmcgY2jhu6luZyBy4bqxbmcga2jDoWNoIGjDoG5nIGNhbyB0deG7lWkgY8OzIHh1IGjGsOG7m25nIHLhu51pIGLhu48gY2FvIGjGoW4sIHR1eSBuaGnDqm4gdMOhYyDEkeG7mW5nIG7DoHkga2jDtG5nIMSR4bunIG3huqFuaCDEkeG7gyBnaeG6o2kgdGjDrWNoIHBo4bqnbiBs4bubbiBiaeG6v24gxJHhu5luZyB0cm9uZyBjaHVybiwgZG8gxJHDsyBj4bqnbiBr4bq/dCBo4bujcCB0aMOqbSBjw6FjIGJp4bq/biBxdWFuIHRy4buNbmcga2jDoWMgxJHhu4MgeMOieSBk4buxbmcgbcO0IGjDrG5oIGPDsyB0w61uaCBk4buxIMSRb8OhbiBjYW8gaMahbi4NCiMjIyAqKjQuMi40LiBNw7QgaMOsbmggQ2xvZ2xvZyoqDQpgYGB7ciBjbG9nbG9nLXNlbmlvci1zaW5nbGUtZmluYWx9DQpjbG9nbG9nX3NlbmlvciA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gU2VuaW9yQ2l0aXplbiwgZGF0YSA9IGRmX2NsZWFuLCBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gImNsb2dsb2ciKSkNCnN1bW1hcnkoY2xvZ2xvZ19zZW5pb3IpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KDQpQaMawxqFuZyB0csOsbmggaOG7k2kgcXV5IENsb2dsb2c6DQokJA0KXGxvZygtXGxvZygxIC0gXGhhdHtccGl9KSkgPSAtMS4zNDk5ICsgMC42NzI5IFx0aW1lcyBcdGV4dHtTZW5pb3JDaXRpemVuWWVzfQ0KJCQNCg0KLSBNw7QgaMOsbmggaOG7k2kgcXV5IG5o4buLIHBow6JuIHPhu60gZOG7pW5nIGjDoG0gbGnDqm4ga+G6v3QgY29tcGxlbWVudGFyeSBsb2ctbG9nIChjbG9nbG9nKSB0aeG6v3AgdOG7pWMga2nhu4NtIMSR4buLbmgg4bqjbmggaMaw4bufbmcgY+G7p2EgYmnhur9uIFNlbmlvckNpdGl6ZW4gKGtow6FjaCBow6BuZyBsw6AgbmfGsOG7nWkgY2FvIHR14buVaSkgxJHhur9uIGto4bqjIG7Eg25nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UgKENodXJuX2JpbmFyeSkuIEvhur90IHF14bqjIGNobyB0aOG6pXkgaOG7hyBz4buRIGjhu5NpIHF1eSBjaG8gbmjDs20ga2jDoWNoIGjDoG5nIGNhbyB0deG7lWkgbMOgIDAuNjkyMywgduG7m2kgcC12YWx1ZSA8IDJlLTE2LCBjaG8gdGjhuqV5IOG6o25oIGjGsOG7n25nIG7DoHkgbMOgIGTGsMahbmcgdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogcuG6pXQgY2FvLg0KDQotIFRyb25nIG3DtCBow6xuaCBjbG9nbG9nLCBo4buHIHPhu5EgaOG7k2kgcXV5IGJp4buDdSBkaeG7hW4gc+G7sSB0aGF5IMSR4buVaSB0csOqbiB0aGFuZyBsb2coLWxvZygxIC0gcCkpLCB0aMaw4budbmcgZMO5bmcgdHJvbmcgY8OhYyB0w6xuaCBodeG7kW5nIHLhu6dpIHJvIHTDrWNoIGzFqXkgaG/hurdjIHjDoWMgc3XhuqV0IHjhuqN5IHJhIGtow7RuZyDEkeG7kWkgeOG7qW5nLiBN4bq3YyBkw7kga2jDsyBkaeG7hW4gZ2nhuqNpIHRy4buxYyB0aeG6v3AgbmjGsCBsb2ctb2RkcyB0cm9uZyBsb2dpc3RpYywgZOG6pXUgY+G7p2EgaOG7hyBz4buRIHbhuqtuIGNobyB0aOG6pXkgcsO1IHLDoG5nIHLhurFuZyBraMOhY2ggaMOgbmcgY2FvIHR14buVaSBjw7MgeMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBjYW8gaMahbiBzbyB24bubaSBuaMOzbSBraMO0bmcgY2FvIHR14buVaS4NCg0KLSBUxrDGoW5nIHThu7EgbmjGsCBjw6FjIG3DtCBow6xuaCBuaOG7iyBwaMOibiBraMOhYyAobG9naXQsIHByb2JpdCksIG3DtCBow6xuaCBjbG9nbG9nIG7DoHkgY8OzOg0KDQogLSBSZXNpZHVhbCBkZXZpYW5jZSBnaeG6o20gbmjhurkgdOG7qyA4MTQzLjQgeHXhu5FuZyA3OTk1LjI7DQoNCiAtIEFJQyA9IDc5OTkuMiwgYuG6sW5nIHbhu5tpIGPDoWMgbcO0IGjDrG5oIGxvZ2l0IHbDoCBwcm9iaXQ7DQoNCiAtIFBzZXVkby1SwrIgxrDhu5tjIGzGsOG7o25nOg0KIA0KJCQNClJeMiBcYXBwcm94IDEgLSBcZnJhY3s3OTk1LjJ9ezgxNDMuNH0gXGFwcHJveCAwLjAxODINCiQkDQoNCg0KxJBp4buBdSBuw6B5IGNobyB0aOG6pXkgYmnhur9uIFNlbmlvckNpdGl6ZW4gY2jhu4kgZ2nhuqNpIHRow61jaCDEkcaw4bujYyBraG/huqNuZyAxLjglIHBoxrDGoW5nIHNhaSBj4bunYSBiaeG6v24gcGjhu6UgdGh14buZYywgdOG7qWMg4bqjbmggaMaw4bufbmcgbMOgIGPDsyB0aOG6rXQgbmjGsG5nIG3hu6ljIMSR4buZIMSRw7NuZyBnw7NwIHbDoG8gdOG7lW5nIHRo4buDIG3DtCBow6xuaCBsw6AgaOG6oW4gY2jhur8uDQoNClTDs20gbOG6oWksIG3DtCBow6xuaCBjbG9nbG9nIHjDoWMgbmjhuq1uIGzhuqFpIHLhurFuZyBuZ8aw4budaSBjYW8gdHXhu5VpIGPDsyB4dSBoxrDhu5tuZyBy4budaSBi4buPIGThu4tjaCB24bulIGNhbyBoxqFuLCBuaMawbmcgdMawxqFuZyB04buxIG5oxrAgY8OhYyBtw7QgaMOsbmgga2jDoWMsIHnhur91IHThu5EgbsOgeSBraMO0bmcgxJHhu6cgbeG6oW5oIMSR4buDIGThu7EgYsOhbyBjaHVybiBt4buZdCBjw6FjaCDEkeG7mWMgbOG6rXAsIHbDoCBj4bqnbiBr4bq/dCBo4bujcCB24bubaSBjw6FjIHnhur91IHThu5Ega2jDoWMgbmjGsCBsb+G6oWkgaOG7o3AgxJHhu5NuZywgcGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuLCBob+G6t2MgdGjhu51pIGdpYW4gc+G7rSBk4bulbmcuDQoNCg0KIyMjICoqNC4yLjUuIMSQw6FuaCBnacOhIGPDoWMgbcO0IGjDrG5oKioNCmBgYHtyIGNvbXBhcmUtc2VuaW9yLW1vZGVsc30NCmFpY19zZW5pb3IgPC0gZGF0YS5mcmFtZSgNCiAgTW9kZWwgPSBjKCJMUE0iLCJMb2dpdCIsICJQcm9iaXQiLCAiQ2xvZ2xvZyIpLA0KICBBSUMgPSBjKEFJQyhscG1fc2VuaW9yKSxBSUMobG9naXRfc2VuaW9yKSwgQUlDKHByb2JpdF9zZW5pb3IpLCBBSUMoY2xvZ2xvZ19zZW5pb3IpKQ0KKQ0Ka2FibGUoYWljX3NlbmlvciwgY2FwdGlvbiA9ICJTbyBzw6FuaCBBSUMgY8OhYyBtw7QgaMOsbmggY2hvIGJp4bq/biBTZW5pb3JDaXRpemVuIikNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqDQoNCsSQ4buDIMSRw6FuaCBnacOhIG3hu6ljIMSR4buZIHBow7kgaOG7o3AgY+G7p2EgY8OhYyBtw7QgaMOsbmggaOG7k2kgcXV5IMSR4buRaSB24bubaSBiaeG6v24gxJHhu5ljIGzhuq1wIFNlbmlvckNpdGl6ZW4sIHRpw6p1IGNow60gQUlDIChBa2Fpa2UgSW5mb3JtYXRpb24gQ3JpdGVyaW9uKSDEkcaw4bujYyBz4butIGThu6VuZyBuaOG6sW0gc28gc8OhbmggZ2nhu69hIGPDoWMgbcO0IGjDrG5oOiBo4buTaSBxdXkgdHV54bq/biB0w61uaCAoTFBNKSwgbG9naXQsIHByb2JpdCB2w6AgY2xvZ2xvZy4gS+G6v3QgcXXhuqMgY2hvIHRo4bqleSBtw7QgaMOsbmggTFBNIGPDsyBBSUMgY2FvIG5o4bqldCAoODMxMC4zMTkpLCBjaG8gdGjhuqV5IG3hu6ljIMSR4buZIHBow7kgaOG7o3AgdGjhuqVwIGjGoW4gc28gduG7m2kgYmEgbcO0IGjDrG5oIG5o4buLIHBow6JuIGPDsm4gbOG6oWkuIFRyb25nIGtoaSDEkcOzLCBj4bqjIGJhIG3DtCBow6xuaCBsb2dpdCwgcHJvYml0IHbDoCBjbG9nbG9nIMSR4buBdSBjaG8gY8O5bmcgbeG7mXQgZ2nDoSB0cuG7iyBBSUMgbMOgIDc5OTkuMjI0LCBjaG8gdGjhuqV5IG3hu6ljIMSR4buZIHBow7kgaOG7o3AgdMawxqFuZyDEkcawxqFuZyBuaGF1IHRyb25nIHZp4buHYyBk4buxIMSRb8OhbiBraOG6oyBuxINuZyBy4budaSBi4buPIGThu4tjaCB24bulIGThu7FhIHRyw6puIHTDrG5oIHRy4bqhbmcga2jDoWNoIGjDoG5nIGzDoCBuZ8aw4budaSBjYW8gdHXhu5VpIGhheSBraMO0bmcuIFPhu7EgxJHhu5NuZyBuaOG6pXQgduG7gSBBSUMg4bufIGJhIG3DtCBow6xuaCBwaGkgdHV54bq/biBuw6B5IGPDsyB0aOG7gyB4deG6pXQgcGjDoXQgdOG7qyBi4bqjbiBjaOG6pXQgxJHGoW4gZ2nhuqNuIGPhu6dhIG3DtCBow6xuaCwgduG7m2kgY2jhu4kgbeG7mXQgYmnhur9uIG5o4buLIHBow6JuIGzDoCBiaeG6v24gZ2nhuqNpIHRow61jaC4gTmjDrG4gY2h1bmcsIGPDoWMgbcO0IGjDrG5oIG5o4buLIHBow6JuIMSR4buBdSB2xrDhu6N0IHRy4buZaSBoxqFuIHNvIHbhu5tpIExQTSB0cm9uZyB2aeG7h2MgZOG7sSDEkW/DoW4gY2h1cm4sIHbDoCBjw7MgdGjhu4MgxJHGsOG7o2MgY8OibiBuaOG6r2MgbOG7sWEgY2jhu41uIHTDuXkgdGhlbyBt4bulYyB0acOqdSBuZ2hpw6puIGPhu6l14oCUY2jhurNuZyBo4bqhbiwgbcO0IGjDrG5oIGxvZ2l0IHRoxrDhu51uZyDEkcaw4bujYyDGsHUgdGnDqm4gbmjhu50ga2jhuqMgbsSDbmcgZGnhu4VuIGdp4bqjaSB0cuG7sWMgdGnhur9wIHF1YSBPZGRzIFJhdGlvLg0KDQojIyAqKjQuMy4gVMOhYyDEkeG7mW5nIGPhu6dhIGBQYXltZW50TWV0aG9kYCoqDQoNCiMjIyAqKjQuMy4xLiBNw7QgaMOsbmggWMOhYyBzdeG6pXQgVHV54bq/biB0w61uaCAoTFBNKSoqDQpgYGB7ciBscG0tcGF5bWVudC1zaW5nbGUtZmluYWx9DQpscG1fcGF5bWVudCA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gUGF5bWVudE1ldGhvZCwgZGF0YSA9IGRmX2NsZWFuLCBmYW1pbHkgPSBnYXVzc2lhbihsaW5rID0gImlkZW50aXR5IikpDQpzdW1tYXJ5KGxwbV9wYXltZW50KQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KSMOgbSBo4buTaSBxdXkgxJHGsOG7o2MgxrDhu5tjIGzGsOG7o25nIG5oxrAgc2F1Og0KJCQNClxoYXR7XHBpfSA9IDAuMTY3MyAtIDAuMDE0MiBcdGltZXMgXHRleHR7Q3JlZGl0IGNhcmR9ICsgMC4yODU1IFx0aW1lcyBcdGV4dHtFbGVjdHJvbmljIGNoZWNrfSArIDAuMDI0NyBcdGltZXMgXHRleHR7TWFpbGVkIGNoZWNrfQ0KJCQNCi0gTcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIChMUE0pIGNobyB0aOG6pXkgcGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuIGPDsyDhuqNuaCBoxrDhu59uZyDEkcOhbmcga+G7gyDEkeG6v24geMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBk4buLY2ggduG7pS4gQ+G7pSB0aOG7gywgc28gduG7m2kgbmjDs20gdGhhbSBjaGnhur91IGzDoCBraMOhY2ggaMOgbmcgc+G7rSBk4bulbmcgcGjGsMahbmcgdGjhu6ljIEJhbmsgdHJhbnNmZXIgKGF1dG9tYXRpYyksIG5o4buvbmcgbmfGsOG7nWkgc+G7rSBk4bulbmcgRWxlY3Ryb25pYyBjaGVjayBjw7MgeMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBjYW8gaMahbiB0cnVuZyBiw6xuaCAyOC41NSDEkWnhu4NtIHBo4bqnbiB0csSDbSwgdsOgIHPhu7Ega2jDoWMgYmnhu4d0IG7DoHkgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBy4bqldCBjYW8gKHAgPCAyZS0xNikuIFRyb25nIGtoaSDEkcOzLCBraMOhY2ggaMOgbmcgdGhhbmggdG/DoW4gYuG6sW5nIENyZWRpdCBjYXJkIChhdXRvbWF0aWMpIHbDoCBNYWlsZWQgY2hlY2sga2jDtG5nIGNobyB0aOG6pXkgc+G7sSBraMOhYyBiaeG7h3QgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiB24bubaSBuaMOzbSB0aGFtIGNoaeG6v3UgKHAgPSAwLjMzMSB2w6AgcCA9IDAuMTAwIHTGsMahbmcg4bupbmcpLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBFbGVjdHJvbmljIGNoZWNrIGzDoCBt4buZdCB54bq/dSB04buRIHLhu6dpIHJvIMSRw6FuZyBsxrB1IMO9IGxpw6puIHF1YW4gxJHhur9uIGjDoG5oIHZpIHLhu51pIGLhu48sIGPDsyB0aOG7gyBwaOG6o24gw6FuaCBt4buZdCDEkeG6t2MgxJFp4buDbSBow6BuaCB2aSBob+G6t2MgbeG7qWMgxJHhu5kgY2FtIGvhur90IHRo4bqlcCBj4bunYSBuaMOzbSBraMOhY2ggaMOgbmcgbsOgeS4gVHV5IG5oacOqbiwgduG7m2kgZ2nDoSB0cuG7iyBBSUMgbMOgIDc3OTguNSwgbcO0IGjDrG5oIHR1eeG6v24gdMOtbmggduG6q24gY8OzIHRo4buDIGLhu4sgaOG6oW4gY2jhur8gdHJvbmcgdmnhu4djIG3DtCBow6xuaCBow7NhIHjDoWMgc3XhuqV0LCBkbyBi4bqjbiBjaOG6pXQgbmjhu4sgcGjDom4gY+G7p2EgYmnhur9uIHBo4bulIHRodeG7mWMuDQoNCiMjIyAqKjQuMy4yLiBNw7QgaMOsbmggTG9naXQqKg0KYGBge3IgbG9naXQtcGF5bWVudC1zaW5nbGUtZmluYWx9DQpsb2dpdF9wYXltZW50IDwtIGdsbShDaHVybl9iaW5hcnkgfiBQYXltZW50TWV0aG9kLCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSkNCnN1bW1hcnkobG9naXRfcGF5bWVudCkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqDQoNCkjDoG0gaOG7k2kgcXV5IMSRxrDhu6NjIMaw4bubYyBsxrDhu6NuZyBuaMawIHNhdToNCiQkDQpcbG9nXGxlZnQoXGZyYWN7XGhhdHtccGl9fXsxIC0gXGhhdHtccGl9fVxyaWdodCkgPSAtMS42MDYzIC0gMC4xMjk5IFx0aW1lcyBcdGV4dHtDcmVkaXQgY2FyZH0gKyAxLjQwMTEgXHRpbWVzIFx0ZXh0e0VsZWN0cm9uaWMgY2hlY2t9ICsgMC4xMzc4IFx0aW1lcyBcdGV4dHtNYWlsZWQgY2hlY2t9DQokJA0KDQotIE3DtCBow6xuaCBo4buTaSBxdXkgbG9naXN0aWMgY2hvIHRo4bqleSBwaMawxqFuZyB0aOG7qWMgdGhhbmggdG/DoW4gbMOgIG3hu5l0IHnhur91IHThu5EgcXVhbiB0cuG7jW5nIOG6o25oIGjGsOG7n25nIMSR4bq/biB4w6FjIHN14bqldCBy4budaSBi4buPIGThu4tjaCB24bulLiBTbyB24bubaSBuaMOzbSB0aGFtIGNoaeG6v3UgbMOgICoqQmFuayB0cmFuc2ZlciAoYXV0b21hdGljKSoqLCBraMOhY2ggaMOgbmcgc+G7rSBk4bulbmcgKipFbGVjdHJvbmljIGNoZWNrKiogY8OzIHh1IGjGsOG7m25nIHLhu51pIGLhu48gY2FvIGjGoW4gxJHDoW5nIGvhu4MsIHbhu5tpIGjhu4cgc+G7kSBsb2ctb2RkcyBsw6AgMS40MTYgKHAgPCAyZS0xNiksIHTGsMahbmcgxJHGsMahbmcgduG7m2kgKip0xINuZyBraG/huqNuZyA0LjEyIGzhuqduKiogKGV4cCgxLjQxNikpIGto4bqjIG7Eg25nIHLhu51pIGLhu48uIFRyb25nIGtoaSDEkcOzLCBraMOhY2ggaMOgbmcgdGhhbmggdG/DoW4gYuG6sW5nICoqQ3JlZGl0IGNhcmQgKGF1dG9tYXRpYykqKiBraMO0bmcgY8OzIHPhu7Ega2jDoWMgYmnhu4d0IGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogduG7gSBraOG6oyBuxINuZyBy4budaSBi4buPIHNvIHbhu5tpIG5ow7NtIHRoYW0gY2hp4bq/dSAocCA9IDAuMjY0NikuIMSQ4buRaSB24bubaSBuaMOzbSAqKk1haWxlZCBjaGVjayoqLCBr4bq/dCBxdeG6oyB0aeG7h20gY+G6rW4gw70gbmdoxKlhIHRo4buRbmcga8OqIChwID0gMC4wNzE1KSwgZ+G7o2kgw70gcuG6sW5nIGPDsyB0aOG7gyB04buTbiB04bqhaSBz4buxIGtow6FjIGJp4buHdCBuaOG6uSB24buBIHjDoWMgc3XhuqV0IHLhu51pIGLhu48sIG5oxrBuZyBj4bqnbiB0aMOqbSBi4bqxbmcgY2jhu6luZy4gR2nDoSB0cuG7iyBBSUMgY+G7p2EgbcO0IGjDrG5oIGzDoCAqKjc1MjYuNioqLCBjaG8gdGjhuqV5IG3hu6ljIMSR4buZIHBow7kgaOG7o3AgdOG7kXQgaMahbiBzbyB24bubaSBtw7QgaMOsbmggdHV54bq/biB0w61uaCAoQUlDID0gNzc5OC41KSwgxJHhu5NuZyB0aOG7nWkgeMOhYyBuaOG6rW4gbcO0IGjDrG5oIGxvZ2lzdGljIHBow7kgaOG7o3AgaMahbiBjaG8gZOG7ryBsaeG7h3Ugbmjhu4sgcGjDom4gbmjGsCBjaHVybi4NCg0KKipL4bq/dCBsdeG6rW46KioNClRoYW5oIHRvw6FuIGLhurFuZyBgRWxlY3Ryb25pYyBjaGVja2AgbMOgIHnhur91IHThu5EgcuG7p2kgcm8gbeG6oW5oIG5o4bqldCwgbMOgbSB0xINuZyDEkcOhbmcga+G7gyBraOG6oyBuxINuZyBy4budaSBi4buPIGPhu6dhIGtow6FjaCBow6BuZy4gQ8OhYyBwaMawxqFuZyB0aOG7qWMgdGhhbmggdG/DoW4gdOG7sSDEkeG7mW5nIChgQmFuayB0cmFuc2ZlcmAsIGBDcmVkaXQgY2FyZGApIGPDsyB04bu3IGzhu4cgcuG7nWkgYuG7jyB0aOG6pXAgdsOgIOG7lW4gxJHhu4tuaCBoxqFuLg0KDQoNCiMjIyAqKjQuMy4zLiBNw7QgaMOsbmggUHJvYml0KioNCmBgYHtyIHByb2JpdC1wYXltZW50LXNpbmdsZS1maW5hbH0NCnByb2JpdF9wYXltZW50IDwtIGdsbShDaHVybl9iaW5hcnkgfiBQYXltZW50TWV0aG9kLCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAicHJvYml0IikpDQpzdW1tYXJ5KHByb2JpdF9wYXltZW50KQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KSMOgbSBQcm9iaXQgxrDhu5tjIGzGsOG7o25nIG5oxrAgc2F1Og0KJCQNClxQaGleey0xfShcaGF0e1xwaX0pID0gLTAuOTY0OSAtIDAuMDYwOCBcdGltZXMgXHRleHR7Q3JlZGl0IGNhcmR9ICsgMC44NDYzOCBcdGltZXMgXHRleHR7RWxlY3Ryb25pYyBjaGVja30gKyAwLjA5NDM1IFx0aW1lcyBcdGV4dHtNYWlsZWQgY2hlY2t9DQokJA0KLSBNw7QgaMOsbmggaOG7k2kgcXV5IHByb2JpdCBjaG8gdGjhuqV5IHBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiBjw7Mg4bqjbmggaMaw4bufbmcgxJHDoW5nIGvhu4MgxJHhur9uIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gZOG7i2NoIHbhu6UuIFNvIHbhu5tpIG5ow7NtIHRoYW0gY2hp4bq/dSBsw6AgQmFuayB0cmFuc2ZlciAoYXV0b21hdGljKSwga2jDoWNoIGjDoG5nIHRoYW5oIHRvw6FuIGLhurFuZyBFbGVjdHJvbmljIGNoZWNrIGPDsyB4w6FjIHN14bqldCBy4budaSBi4buPIGNhbyBoxqFuIHLDtSBy4buHdCwgduG7m2kgaOG7hyBz4buRIMaw4bubYyBsxrDhu6NuZyBsw6AgMC44NDYgKHAgPCAyZS0xNiksIGNobyB0aOG6pXkgdMOhYyDEkeG7mW5nIG3huqFuaCBt4bq9IHbDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqLiBUcm9uZyBraGkgxJHDsywgbmjDs20gQ3JlZGl0IGNhcmQgKGF1dG9tYXRpYykga2jDtG5nIGtow6FjIGJp4buHdCDEkcOhbmcga+G7gyBzbyB24bubaSBuaMOzbSB0aGFtIGNoaeG6v3UgKHAgPSAwLjI2NDQpLiBOaMOzbSBNYWlsZWQgY2hlY2sgY8OzIHAtdmFsdWUgPSAwLjA3MTMsIGfhuqduIMSR4bqhdCBuZ8aw4buhbmcgw70gbmdoxKlhIHRo4buRbmcga8OqIDUlLCBjaG8gdGjhuqV5IGto4bqjIG7Eg25nIHThu5NuIHThuqFpIG3hu5l0IHTDoWMgxJHhu5luZyB54bq/dSDEkeG6v24geMOhYyBzdeG6pXQgcuG7nWkgYuG7jy4gQUlDIGPhu6dhIG3DtCBow6xuaCBsw6AgNzUyNi42LCB0csO5bmcga2jhu5twIHbhu5tpIG3DtCBow6xuaCBsb2dpdCwgY2hvIHRo4bqleSBt4bupYyDEkeG7mSBwaMO5IGjhu6NwIHTGsMahbmcgxJHGsMahbmcgZ2nhu69hIGhhaSBtw7QgaMOsbmguIFR1eSBuaGnDqm4sIGPhuqMgaGFpIMSR4buBdSB0aOG7gyBoaeG7h24gdOG7kXQgaMahbiBtw7QgaMOsbmggdHV54bq/biB0w61uaCAoQUlDID0gNzc5OC41KSwgeMOhYyBuaOG6rW4gcuG6sW5nIGPDoWMgbcO0IGjDrG5oIG5o4buLIHBow6JuIChsb2dpdCB2w6AgcHJvYml0KSBwaMO5IGjhu6NwIGjGoW4ga2hpIGThu7EgxJFvw6FuIGNodXJuLg0KDQoqKkvhur90IGx14bqtbjoqKg0KS+G6v3QgcXXhuqMgdOG7qyBtw7QgaMOsbmggUHJvYml0IGPhu6duZyBj4buRIHLhurFuZyBgRWxlY3Ryb25pYyBjaGVja2AgbMOgIHBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiBjw7MgcuG7p2kgcm8gY2FvIG5o4bqldCwgduG7m2kgaOG7hyBz4buRIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNCg0KIyMjICoqNC4zLjQuIE3DtCBow6xuaCBDbG9nbG9nKioNCmBgYHtyIGNsb2dsb2ctcGF5bWVudC1zaW5nbGUtZmluYWx9DQpjbG9nbG9nX3BheW1lbnQgPC0gZ2xtKENodXJuX2JpbmFyeSB+IFBheW1lbnRNZXRob2QsIGRhdGEgPSBkZl9jbGVhbiwgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJjbG9nbG9nIikpDQpzdW1tYXJ5KGNsb2dsb2dfcGF5bWVudCkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqDQoNClBoxrDGoW5nIHRyw6xuaCBo4buTaSBxdXkgQ2xvZ2xvZzoNCiQkDQpcbG9nKC1cbG9nKDEgLSBcaGF0e1xwaX0pKSA9IC0xLjY5NzcyIC0gMC4xMDAwIFx0aW1lcyBcdGV4dHtDcmVkaXQgY2FyZH0gKyAxLjE5MTk1IFx0aW1lcyBcdGV4dHtFbGVjdHJvbmljIGNoZWNrfSArIDAuMTUyMjggXHRpbWVzIFx0ZXh0e01haWxlZCBjaGVja30NCiQkDQoNCi0gTcO0IGjDrG5oIGjhu5NpIHF1eSBjbG9nbG9nIHRp4bq/cCB04bulYyBj4bunbmcgY+G7kSBr4bq/dCBsdeG6rW4gcuG6sW5nIHBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiBjw7Mg4bqjbmggaMaw4bufbmcgcsO1IHLhu4d0IMSR4bq/biBraOG6oyBuxINuZyBy4budaSBi4buPIGThu4tjaCB24bulLiBD4bulIHRo4buDLCBraMOhY2ggaMOgbmcgc+G7rSBk4bulbmcgKipFbGVjdHJvbmljIGNoZWNrKiogY8OzIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gY2FvIGjGoW4gxJHDoW5nIGvhu4Mgc28gduG7m2kgbmjDs20gdGhhbSBjaGnhur91ICoqQmFuayB0cmFuc2ZlciAoYXV0b21hdGljKSoqLCB24bubaSBo4buHIHPhu5EgxrDhu5tjIGzGsOG7o25nIGzDoCAxLjE5MiAocCA8IDJlLTE2KSwgY2hvIHRo4bqleSB0w6FjIMSR4buZbmcgcuG6pXQgbeG6oW5oIHbDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIGNhby4gVHJvbmcga2hpIMSRw7MsIHBoxrDGoW5nIHRo4bupYyAqKkNyZWRpdCBjYXJkIChhdXRvbWF0aWMpKioga2jDtG5nIGNobyB0aOG6pXkgc+G7sSBraMOhYyBiaeG7h3QgY8OzIMO9IG5naMSpYSAocCA9IDAuMjY0NikuIE5ow7NtICoqTWFpbGVkIGNoZWNrKiogY8OzIGjhu4cgc+G7kSBkxrDGoW5nIG5o4bq5ICgwLjE1MiksIHAtdmFsdWUgPSAwLjA3MTYsIG7hurFtIGfhuqduIG5nxrDhu6FuZyAwLjA1LCBjaG8gdGjhuqV5IGPDsyB0aOG7gyBjw7MgdMOhYyDEkeG7mW5nIHnhur91LiBHacOhIHRy4buLIEFJQyBj4bunYSBtw7QgaMOsbmggbMOgICoqNzUyNi42KiosIG5nYW5nIGLhurFuZyB24bubaSBjw6FjIG3DtCBow6xuaCBsb2dpdCB2w6AgcHJvYml0LCB2w6AgdGjhuqVwIGjGoW4gxJHDoW5nIGvhu4Mgc28gduG7m2kgbcO0IGjDrG5oIHR1eeG6v24gdMOtbmggKEFJQyA9IDc3OTguNSksIGNobyB0aOG6pXkgY8OhYyBtw7QgaMOsbmggbmjhu4sgcGjDom4gxJHhu4F1IHBow7kgaOG7o3AgaMahbiBraGkgcGjDom4gdMOtY2ggeMOhYyBzdeG6pXQga2jDoWNoIGjDoG5nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UgZOG7sWEgdHLDqm4gcGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuLg0KDQoNCiMjIyAqKjQuMy41LiDEkMOhbmggZ2nDoSBjw6FjIG3DtCBow6xuaCoqDQpgYGB7ciBjb21wYXJlLXBheW1lbnQtbW9kZWxzfQ0KYWljX3BheW1lbnQgPC0gZGF0YS5mcmFtZSgNCiAgTW9kZWwgPSBjKCJMcG0iLCJMb2dpdCIsICJQcm9iaXQiLCAiQ2xvZ2xvZyIpLA0KICBBSUMgPSBjKEFJQyhscG1fcGF5bWVudCksQUlDKGxvZ2l0X3BheW1lbnQpLCBBSUMocHJvYml0X3BheW1lbnQpLCBBSUMoY2xvZ2xvZ19wYXltZW50KSkNCikNCmthYmxlKGFpY19wYXltZW50LCBjYXB0aW9uID0gIlNvIHPDoW5oIEFJQyBjw6FjIG3DtCBow6xuaCBjaG8gYmnhur9uIFBheW1lbnRNZXRob2QiKQ0KYGBgDQoNCi0gS2hpIHNvIHPDoW5oIGdp4buvYSBjw6FjIG3DtCBow6xuaCBo4buTaSBxdXkgc+G7rSBk4bulbmcgYmnhur9uIMSR4buZYyBs4bqtcCBsw6AgKipQYXltZW50TWV0aG9kKiosIHRhIHRo4bqleSBy4bqxbmcgY8OhYyBtw7QgaMOsbmggbmjhu4sgcGjDom4gKGxvZ2l0LCBwcm9iaXQsIGNsb2dsb2cpIMSR4buBdSBjw7MgY8O5bmcgZ2nDoSB0cuG7iyBBSUMgbMOgICoqNzUyNi41OTEqKiwgdGjhuqVwIGjGoW4gcsO1IHLhu4d0IHNvIHbhu5tpIG3DtCBow6xuaCB0dXnhur9uIHTDrW5oIChMUE0pIGPDsyBBSUMgbMOgICoqNzc5OC41MTkqKi4gxJBp4buBdSBuw6B5IGNobyB0aOG6pXkgcuG6sW5nIG3DtCBow6xuaCBow7NhIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gZOG7i2NoIHbhu6UgYuG6sW5nIGPDoWMgaMOgbSBsacOqbiBr4bq/dCBwaGkgdHV54bq/biAobmjGsCBsb2dpdCwgcHJvYml0LCBjbG9nbG9nKSBsw6AgcGjDuSBo4bujcCB2w6AgaGnhu4d1IHF14bqjIGjGoW4gc28gduG7m2kgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oLiBUdXkgY8OhYyBtw7QgaMOsbmggbmjhu4sgcGjDom4gY8OzIEFJQyB0xrDGoW5nIMSRxrDGoW5nIG5oYXUgdsOgIGtow7RuZyBjw7MgbcO0IGjDrG5oIG7DoG8gdsaw4bujdCB0cuG7mWkgcsO1IHLhu4d0IHbhu4EgbeG6t3QgdGjDtG5nIHRpbiwgbmjGsG5nIGNow7puZyDEkeG7gXUgdGjhu4MgaGnhu4duIG3hu6ljIMSR4buZIHBow7kgaOG7o3AgdOG7kXQgaMahbiBzbyB24bubaSBMUE0gdHJvbmcgdmnhu4djIGdp4bqjaSB0aMOtY2gg4bqjbmggaMaw4bufbmcgY+G7p2EgcGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuIMSR4bq/biBraOG6oyBuxINuZyBy4budaSBi4buPIGThu4tjaCB24bulIGPhu6dhIGtow6FjaCBow6BuZy4NCg0KDQojIyAqKjQuNC4gVMOhYyDEkeG7mW5nIGPhu6dhIGBJbnRlcm5ldFNlcnZpY2VgKioNCg0KIyMjICoqNC40LjEuIE3DtCBow6xuaCBYw6FjIHN14bqldCBUdXnhur9uIHTDrW5oIChMUE0pKioNCmBgYHtyIGxwbS1pbnRlcm5ldC1zaW5nbGUtZmluYWx9DQpscG1faW50ZXJuZXQgPC0gZ2xtKENodXJuX2JpbmFyeSB+IEludGVybmV0U2VydmljZSwgZGF0YSA9IGRmX2NsZWFuLCBmYW1pbHkgPSBnYXVzc2lhbihsaW5rID0gImlkZW50aXR5IikpDQpzdW1tYXJ5KGxwbV9pbnRlcm5ldCkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqDQoNCkjDoG0gaOG7k2kgcXV5IMSRxrDhu6NjIMaw4bubYyBsxrDhu6NuZyBuaMawIHNhdToNCiQkDQpcaGF0e1xwaX0gPSAwLjE4OTk4MyArICAwLjIyODk0NCBcdGltZXMgXHRleHR7RmliZXIgb3B0aWN9IC0wLjExNTY0MSBcdGltZXMgXHRleHR7Tm99DQokJA0KLSAgS+G6v3QgcXXhuqMgdOG7qyBtw7QgaMOsbmggaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggKExQTSkgY2hvIHRo4bqleSBiaeG6v24gKipJbnRlcm5ldFNlcnZpY2UqKiBjw7Mg4bqjbmggaMaw4bufbmcgxJHDoW5nIGvhu4MgxJHhur9uIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gZOG7i2NoIHbhu6UgKCoqQ2h1cm5cX2JpbmFyeSoqKS4gQ+G7pSB0aOG7gywgc28gduG7m2kgbmjDs20ga2jDoWNoIGjDoG5nIHPhu60gZOG7pW5nICoqRFNMKiogKG5ow7NtIHRoYW0gY2hp4bq/dSksIG5o4buvbmcgbmfGsOG7nWkgc+G7rSBk4bulbmcgKipJbnRlcm5ldCBjw6FwIHF1YW5nIChGaWJlciBvcHRpYykqKiBjw7MgeMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBjYW8gaMahbiB0cnVuZyBiw6xuaCAqKjIyLjg5JSoqLCB24bubaSBo4buHIHPhu5EgxrDhu5tjIGzGsOG7o25nIGTGsMahbmcgKCoqMC4yMjg5KiopIHbDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHLhuqV0IGNhbyAocCA8IDJlLTE2KS4gTmfGsOG7o2MgbOG6oWksIG5ow7NtICoqa2jDtG5nIHPhu60gZOG7pW5nIGThu4tjaCB24bulIEludGVybmV0KiogY8OzIGto4bqjIG7Eg25nIHLhu51pIGLhu48gdGjhuqVwIGjGoW4gKioxMS41NiUqKiBzbyB24bubaSBuaMOzbSBEU0wsIHbhu5tpIGjhu4cgc+G7kSDDom0gKCoqLTAuMTE1NioqKSB2w6AgY8WpbmcgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBt4bqhbmguIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IGThu4tjaCB24bulIEludGVybmV0IMSRYW5nIGzDoCBt4buZdCB54bq/dSB04buRIHF1YW4gdHLhu41uZyB0cm9uZyBow6BuaCB2aSBy4budaSBi4buPIGPhu6dhIGtow6FjaCBow6BuZyDigJMgdHJvbmcgxJHDsywgbmfGsOG7nWkgZMO5bmcgY8OhcCBxdWFuZyBjw7MgeHUgaMaw4bubbmcgcuG7nWkgYuG7jyBjYW8gaMahbiDEkcOhbmcga+G7gywgY8OzIHRo4buDIGRvIGNoaSBwaMOtIGNhbywgY2jhuqV0IGzGsOG7o25nIGThu4tjaCB24bulIGhv4bq3YyBr4buzIHbhu41uZyBraMO0bmcgxJHGsOG7o2MgxJHDoXAg4bupbmcuIE3DtCBow6xuaCBjw7MgZ2nDoSB0cuG7iyBBSUMgbMOgICoqNzcwNC4yKiosIHRo4bqlcCBoxqFuIGPDoWMgbcO0IGjDrG5oIExQTSB0csaw4bubYyDEkcOzIHbhu5tpIGPDoWMgYmnhur9uIGtow6FjLCBjaG8gdGjhuqV5IG3hu6ljIMSR4buZIHBow7kgaOG7o3AgdMawxqFuZyDEkeG7kWkgdOG7kXQuDQoNCg0KIyMjICoqNC40LjIuIE3DtCBow6xuaCBMb2dpdCoqDQpgYGB7ciBsb2dpdC1pbnRlcm5ldC1zaW5nbGUtZmluYWx9DQpsb2dpdF9pbnRlcm5ldCA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gSW50ZXJuZXRTZXJ2aWNlLCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSkNCnN1bW1hcnkobG9naXRfaW50ZXJuZXQpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KDQpIw6BtIGjhu5NpIHF1eSDEkcaw4bujYyDGsOG7m2MgbMaw4bujbmcgbmjGsCBzYXU6DQokJA0KXGxvZ1xsZWZ0KFxmcmFje1xoYXR7XHBpfX17MSAtIFxoYXR7XHBpfX1ccmlnaHQpID0gLTEuNDUwMTIgKyAxLjEyMjk0ICBcdGltZXMgXHRleHR7RmliZXIgb3B0aWN9IC0xLjA3MTcxIFx0aW1lcyBcdGV4dHtOb30NCiQkDQoNCi0gS+G6v3QgcXXhuqMgdOG7qyBtw7QgaMOsbmggaOG7k2kgcXV5IGxvZ2lzdGljIGNobyB0aOG6pXkgKipJbnRlcm5ldFNlcnZpY2UqKiBjw7Mg4bqjbmggaMaw4bufbmcgcsO1IHLhu4d0IHbDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIG3huqFuaCDEkeG6v24ga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyBk4buLY2ggduG7pSAoKipDaHVyblxfYmluYXJ5KiopLiBTbyB24bubaSBuaMOzbSBraMOhY2ggaMOgbmcgc+G7rSBk4bulbmcgKipEU0wqKiAobmjDs20gdGhhbSBjaGnhur91KSwgbmjhu69uZyBuZ8aw4budaSBz4butIGThu6VuZyAqKkludGVybmV0IGPDoXAgcXVhbmcgKEZpYmVyIG9wdGljKSoqIGPDsyB4w6FjIHN14bqldCBy4budaSBi4buPIGNhbyBoxqFuLCB24bubaSBo4buHIHPhu5EgbG9nLW9kZHMgbMOgICoqMS4xMjI5KiogKHAgPCAyZS0xNiksIHTGsMahbmcg4bupbmcgduG7m2kgKipPZGRzIFJhdGlvIOKJiCAzLjA4Kiog4oCTIG5naMSpYSBsw6Aga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyBjYW8gZ+G6pXAga2hv4bqjbmcgKiozIGzhuqduKiogc28gduG7m2kgbmjDs20gZMO5bmcgRFNMLiBOZ8aw4bujYyBs4bqhaSwga2jDoWNoIGjDoG5nICoqa2jDtG5nIHPhu60gZOG7pW5nIGThu4tjaCB24bulIEludGVybmV0KiogY8OzIGjhu4cgc+G7kSDDom0gKiotMS4wNzE3KiogKHAgPCAyZS0xNiksIHTGsMahbmcg4bupbmcgduG7m2kgKipPZGRzIFJhdGlvIOKJiCAwLjM0KiosIGNobyB0aOG6pXkga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyB0aOG6pXAgaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBuaMOzbSBEU0wuIEvhur90IHF14bqjIG7DoHkgcGjhuqNuIMOhbmggcuG6sW5nIG5nxrDhu51pIGTDuW5nIEludGVybmV0IGPDoXAgcXVhbmcgY8OzIHh1IGjGsOG7m25nIHLhu51pIGLhu48gY2FvIGjGoW4gxJHDoW5nIGvhu4MsIGPDsyB0aOG7gyBkbyBjaGkgcGjDrSwgc+G7sSBwaOG7qWMgdOG6oXAgdHJvbmcgZOG7i2NoIHbhu6UsIGhv4bq3YyBr4buzIHbhu41uZyBjYW8gaMahbiBraMO0bmcgxJHGsOG7o2MgxJHDoXAg4bupbmcuIE5nxrDhu6NjIGzhuqFpLCBuaOG7r25nIGtow6FjaCBow6BuZyBraMO0bmcgc+G7rSBk4bulbmcgSW50ZXJuZXQgw610IGPDsyBraOG6oyBuxINuZyBy4budaSBi4buPIGjGoW4g4oCTIGPDsyB0aOG7gyB2w6wgaOG7jSDDrXQgdMawxqFuZyB0w6FjIHbhu5tpIGThu4tjaCB24bulIGhv4bq3YyBraMO0bmcgY2jhu4t1IOG6o25oIGjGsOG7n25nIHThu6sgeeG6v3UgdOG7kSBr4bu5IHRodeG6rXQuIEdpw6EgdHLhu4sgQUlDIGPhu6dhIG3DtCBow6xuaCBsw6AgKio3MzcwLjMqKiwgdGjhuqVwIGjGoW4gY8OhYyBtw7QgaMOsbmggduG7m2kgYmnhur9uIGtow6FjLCBjaG8gdGjhuqV5IG3DtCBow6xuaCBuw6B5IGPDsyDEkeG7mSBwaMO5IGjhu6NwIHThu5F0IGjGoW4uDQoNCg0KIyMjICoqNC40LjMuIE3DtCBow6xuaCBQcm9iaXQqKg0KYGBge3IgcHJvYml0LWludGVybmV0LXNpbmdsZS1maW5hbH0NCnByb2JpdF9pbnRlcm5ldCA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gSW50ZXJuZXRTZXJ2aWNlLCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAicHJvYml0IikpDQpzdW1tYXJ5KHByb2JpdF9pbnRlcm5ldCkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqDQoNCkjDoG0gUHJvYml0IMaw4bubYyBsxrDhu6NuZyBuaMawIHNhdToNCiQkDQpcUGhpXnstMX0oXGhhdHtccGl9KSA9IC0wLjg3Nzk2ICsgMC42NzMzMiBcdGltZXMgXHRleHR7RmliZXIgb3B0aWN9IC0wLjU2NjI0IFx0aW1lcyBcdGV4dHtOb30NCiQkDQotIEvhur90IHF14bqjIHThu6sgbcO0IGjDrG5oIGjhu5NpIHF1eSBwcm9iaXQgduG7m2kgYmnhur9uICoqSW50ZXJuZXRTZXJ2aWNlKiogdGnhur9wIHThu6VjIGto4bqzbmcgxJHhu4tuaCDhuqNuaCBoxrDhu59uZyBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIGPhu6dhIGxv4bqhaSBow6xuaCBk4buLY2ggduG7pSBJbnRlcm5ldCDEkeG6v24ga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyAoKipDaHVyblxfYmluYXJ5KiopLiBW4bubaSBuaMOzbSB0aGFtIGNoaeG6v3UgbMOgIGtow6FjaCBow6BuZyBz4butIGThu6VuZyAqKkRTTCoqLCBuaMOzbSBkw7luZyAqKkZpYmVyIG9wdGljKiogY8OzIGjhu4cgc+G7kSDGsOG7m2MgbMaw4bujbmcgbMOgICoqMC42NzMzKiogKHAgPCAyZS0xNiksIGNobyB0aOG6pXkgaOG7jSBjw7MgKip4w6FjIHN14bqldCBy4budaSBi4buPIGNhbyBoxqFuIMSRw6FuZyBr4buDKiogc28gduG7m2kgbmjDs20gRFNMLiBOZ8aw4bujYyBs4bqhaSwgbmjDs20gKipraMO0bmcgc+G7rSBk4bulbmcgSW50ZXJuZXQqKiBjw7MgaOG7hyBz4buRICoqLTAuNTY2MioqIChwIDwgMmUtMTYpLCB0aOG7gyBoaeG7h24gKip4w6FjIHN14bqldCBy4budaSBi4buPIHRo4bqlcCBoxqFuKiogc28gduG7m2kgbmjDs20gRFNMLiBN4bq3YyBkw7kgaOG7hyBz4buRIHRyb25nIG3DtCBow6xuaCBwcm9iaXQga2jDtG5nIHRo4buDIGRp4buFbiBnaeG6o2kgdHLhu7FjIHRp4bq/cCBuaMawIG9kZHMgcmF0aW8gdHJvbmcgbG9naXQsIG5oxrBuZyBk4bqldSB2w6AgxJHhu5kgbOG7m24gY+G7p2EgY8OhYyBo4buHIHPhu5EgduG6q24gY2hvIHRo4bqleSAqKnh1IGjGsOG7m25nIHTGsMahbmcgdOG7sSoqOiBraMOhY2ggaMOgbmcgZMO5bmcgRmliZXIgb3B0aWMgY8OzIGto4bqjIG7Eg25nIHLhu51pIGLhu48gY2FvIG5o4bqldCwga+G6vyDEkeG6v24gbMOgIG5ow7NtIERTTCwgdsOgIHRo4bqlcCBuaOG6pXQgbMOgIG5ow7NtIGtow7RuZyBz4butIGThu6VuZyBJbnRlcm5ldC4gR2nDoSB0cuG7iyAqKkFJQyBsw6AgNzM3MC4zKiosIGLhurFuZyB24bubaSBtw7QgaMOsbmggbG9naXQsIGNobyB0aOG6pXkgbeG7qWMgxJHhu5kgcGjDuSBo4bujcCBnaeG7r2EgaGFpIG3DtCBow6xuaCBsw6AgdMawxqFuZyDEkcawxqFuZy4gxJBp4buBdSBuw6B5IGPhu6duZyBj4buRIMSR4buZIHRpbiBj4bqteSBj4bunYSBr4bq/dCBsdeG6rW4gcuG6sW5nIGxv4bqhaSBow6xuaCBJbnRlcm5ldCBsw6AgbeG7mXQgeeG6v3UgdOG7kSBxdWFuIHRy4buNbmcg4bqjbmggaMaw4bufbmcgxJHhur9uIGjDoG5oIHZpIHLhu51pIGLhu48gZOG7i2NoIHbhu6UuDQoNCg0KIyMjICoqNC40LjQuIE3DtCBow6xuaCBDbG9nbG9nKioNCmBgYHtyIGNsb2dsb2ctaW50ZXJuZXQtc2luZ2xlLWZpbmFsfQ0KY2xvZ2xvZ19pbnRlcm5ldCA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gSW50ZXJuZXRTZXJ2aWNlLCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAiY2xvZ2xvZyIpKQ0Kc3VtbWFyeShjbG9nbG9nX2ludGVybmV0KQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KUGjGsMahbmcgdHLDrG5oIGjhu5NpIHF1eSBDbG9nbG9nOg0KJCQNClxsb2coLVxsb2coMSAtIFxoYXR7XHBpfSkpID0gLTEuNTU3MzIgKyAgMC45NDY0NSBcdGltZXMgXHRleHR7RmliZXIgb3B0aWN9IC0xLjAwMzM4IFx0aW1lcyBcdGV4dHtOb30NCiQkDQoNCi0gIE3DtCBow6xuaCBo4buTaSBxdXkgKipjbG9nbG9nKiogduG7m2kgYmnhur9uIMSR4buZYyBs4bqtcCAqKkludGVybmV0U2VydmljZSoqIGNobyB0aOG6pXkgc+G7sSBraMOhYyBiaeG7h3QgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiByw7UgcuG7h3QgZ2nhu69hIGPDoWMgbG/huqFpIGjDrG5oIGThu4tjaCB24bulIEludGVybmV0IMSR4buRaSB24bubaSB4w6FjIHN14bqldCBy4budaSBi4buPIGThu4tjaCB24bulLiBW4bubaSBuaMOzbSB0aGFtIGNoaeG6v3UgbMOgICoqRFNMKiosIGtow6FjaCBow6BuZyBz4butIGThu6VuZyAqKkZpYmVyIG9wdGljKiogY8OzIGjhu4cgc+G7kSDGsOG7m2MgbMaw4bujbmcgbMOgICoqMC45NDY1KiogKHAgPCAyZS0xNiksIGNobyB0aOG6pXkgaOG7jSBjw7MgKipuZ3V5IGPGoSBy4budaSBi4buPIGNhbyBoxqFuIMSRw6FuZyBr4buDKiouIE5nxrDhu6NjIGzhuqFpLCBuaMOzbSAqKmtow7RuZyBz4butIGThu6VuZyBJbnRlcm5ldCoqIGPDsyBo4buHIHPhu5EgKiotMS4wMDM0KiogKHAgPCAyZS0xNiksIHRo4buDIGhp4buHbiAqKmto4bqjIG7Eg25nIHLhu51pIGLhu48gdGjhuqVwIGjGoW4qKiBzbyB24bubaSBuaMOzbSBEU0wuIEjGsOG7m25nIHbDoCBt4bupYyDEkeG7mSDhuqNuaCBoxrDhu59uZyBj4bunYSBjw6FjIGJp4bq/biB0cm9uZyBtw7QgaMOsbmggY2xvZ2xvZyB0xrDGoW5nIHThu7EgbmjGsCB0cm9uZyBjw6FjIG3DtCBow6xuaCBsb2dpdCB2w6AgcHJvYml0LCBjaG8gdGjhuqV5ICoqdMOtbmggbmjhuqV0IHF1w6FuIHRyb25nIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgbG/huqFpIGjDrG5oIEludGVybmV0IHbDoCBow6BuaCB2aSBy4budaSBi4buPKiouDQoNCkdpw6EgdHLhu4sgKipBSUMgbMOgIDczNzAuMyoqLCBnaeG7kW5nIGjhu4d0IHbhu5tpIGxvZ2l0IHbDoCBwcm9iaXQsIGNobyB0aOG6pXkgbeG7qWMgxJHhu5kgcGjDuSBo4bujcCBj4bunYSBiYSBtw7QgaMOsbmggbMOgIHTGsMahbmcgxJHGsMahbmcgbmhhdS4gVHV5IG5oacOqbiwgY2xvZ2xvZyDEkeG6t2MgYmnhu4d0IHBow7kgaOG7o3AgaMahbiB0cm9uZyBjw6FjIHRyxrDhu51uZyBo4bujcCBtw6AgeMOhYyBzdeG6pXQgeOG6o3kgcmEgc+G7sSBraeG7h24gKOG7nyDEkcOieSBsw6AgY2h1cm4pIHLhuqV0IHRo4bqlcCBob+G6t2MgcuG6pXQgY2FvIOKAlCDEkWnhu4F1IGPDsyB0aOG7gyB4ZW0geMOpdCBu4bq/dSBwaMOibiBwaOG7kWkgY2h1cm4gYuG7iyBs4buHY2ggbeG6oW5oLiBEw7kgduG6rXksIHRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCBj4bqjIGJhIG3DtCBow6xuaCBuaOG7iyBwaMOibiDEkeG7gXUgY3VuZyBj4bqlcCBr4bq/dCBxdeG6oyBuaOG6pXQgcXXDoW4sIHbDoCDEkeG7gXUgY2jhu4kgcmEgcuG6sW5nICoqRmliZXIgb3B0aWMgbMOgIHnhur91IHThu5EgbMOgbSB0xINuZyBt4bqhbmgga2jhuqMgbsSDbmcga2jDoWNoIGjDoG5nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UqKi4NCg0KDQojIyMgKio0LjQuNS4gxJDDoW5oIGdpw6EgY8OhYyBtw7QgaMOsbmgqKg0KYGBge3IgY29tcGFyZS1pbnRlcm5ldC1tb2RlbHN9DQphaWNfaW50ZXJuZXQgPC0gZGF0YS5mcmFtZSgNCiAgTW9kZWwgPSBjKCJMUE0iLCJMb2dpdCIsICJQcm9iaXQiLCAiQ2xvZ2xvZyIpLA0KICBBSUMgPSBjKEFJQyhscG1faW50ZXJuZXQpLEFJQyhsb2dpdF9pbnRlcm5ldCksIEFJQyhwcm9iaXRfaW50ZXJuZXQpLCBBSUMoY2xvZ2xvZ19pbnRlcm5ldCkpDQopDQprYWJsZShhaWNfaW50ZXJuZXQsIGNhcHRpb24gPSAiU28gc8OhbmggQUlDIGPDoWMgbcO0IGjDrG5oIGNobyBiaeG6v24gSW50ZXJuZXRTZXJ2aWNlIikNCmBgYA0KDQotIEThu7FhIHRyw6puIGNo4buJIHPhu5EgQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiAoQUlDKSDigJMgbeG7mXQgdGnDqnUgY2jDrSBkw7luZyDEkeG7gyBzbyBzw6FuaCBt4bupYyDEkeG7mSBwaMO5IGjhu6NwIGPhu6dhIGPDoWMgbcO0IGjDrG5oIHRo4buRbmcga8OqIHbhu5tpIGPDuW5nIG3hu5l0IGLhu5kgZOG7ryBsaeG7h3Ug4oCTIHRhIHRo4bqleSByw7U6DQoNCi0gQmEgbcO0IGjDrG5oIG5o4buLIHBow6JuIChsb2dpdCwgcHJvYml0LCBjbG9nbG9nKSDEkeG7gXUgY2hvIGPDuW5nIG3hu5l0IGdpw6EgdHLhu4sgQUlDIGzDoCA3MzcwLjI5OCwgdGjhuqVwIGjGoW4gxJHDoW5nIGvhu4Mgc28gduG7m2kgbcO0IGjDrG5oIExQTSAoNzcwNC4yMzUpLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBy4bqxbmcgY8OhYyBtw7QgaMOsbmggbmjhu4sgcGjDom4gcGjDuSBo4bujcCBk4buvIGxp4buHdSB04buRdCBoxqFuIHNvIHbhu5tpIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIGtoaSBk4buxIMSRb8OhbiBraOG6oyBuxINuZyBraMOhY2ggaMOgbmcgcuG7nWkgYuG7jyB0aGVvIGxv4bqhaSBow6xuaCBJbnRlcm5ldC4NCg0KLSBN4bq3YyBkw7kgbG9naXQsIHByb2JpdCB2w6AgY2xvZ2xvZyBjw7MgbG9naWMgZGnhu4VuIGdp4bqjaSBraMOhYyBuaGF1IHbhu4EgeMOhYyBzdeG6pXQgKGxvZ2l0IGTDuW5nIHBow6JuIHBo4buRaSBsb2dpc3RpYywgcHJvYml0IGTDuW5nIHBow6JuIHBo4buRaSBjaHXhuqluLCBjbG9nbG9nIGTDuW5nIGjDoG0gY29tcGxlbWVudGFyeSBsb2ctbG9nKSwgbmjGsG5nIOG7nyDEkcOieSBjaMO6bmcgdMawxqFuZyDEkcawxqFuZyB24buBIG3hurd0IMSR4buZIHBow7kgaOG7o3AgbcO0IGjDrG5oLg0KDQpEbyDEkcOzLCBjw7MgdGjhu4MgxrB1IHRpw6puIHPhu60gZOG7pW5nIG3hu5l0IHRyb25nIGJhIG3DtCBow6xuaCBuaOG7iyBwaMOibiAodGjGsOG7nW5nIGzDoCBsb2dpdCB2w6wgZOG7hSBnaeG6o2kgdGjDrWNoIHbDoCBwaOG7lSBiaeG6v24gbmjhuqV0KSwgdsOgIGxv4bqhaSBi4buPIG3DtCBow6xuaCBMUE0ga2jhu49pIHBow6JuIHTDrWNoIGNow61uaCBkbyDEkeG7mSBwaMO5IGjhu6NwIGvDqW0gaMahbiDEkcOhbmcga+G7gy4NCg0KIyMgKio0LjUuIFTDoWMgxJHhu5luZyBj4bunYSBgdGVudXJlYCoqDQoNCiMjIyAqKjQuNS4xLiBNw7QgaMOsbmggWMOhYyBzdeG6pXQgVHV54bq/biB0w61uaCAoTFBNKSoqDQpgYGB7ciBscG0tdGVudXJlLXNpbmdsZS1maW5hbH0NCmxwbV90ZW51cmUgPC0gZ2xtKENodXJuX2JpbmFyeSB+IHRlbnVyZSwgZGF0YSA9IGRmX2NsZWFuLCBmYW1pbHkgPSBnYXVzc2lhbihsaW5rID0gImlkZW50aXR5IikpDQpzdW1tYXJ5KGxwbV90ZW51cmUpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KDQpIw6BtIGjhu5NpIHF1eSDEkcaw4bujYyDGsOG7m2MgbMaw4bujbmcgbmjGsCBzYXU6DQokJA0KXGhhdHtDaHVybn0gPSAwLjQ3MjM5MDAgLTAuMDA2MzcyNCBcdGltZXMgXHRleHR7dGVudXJlfQ0KJCQNCi0gICDDnSBuZ2jEqWEgaOG7hyBz4buROg0KDQogIEjhu4cgc+G7kSBJbnRlcmNlcHQgPSAwLjQ3MjQgY2hvIGJp4bq/dCBy4bqxbmcga2hpIHRlbnVyZSA9IDAgKGtow6FjaCBow6BuZyBt4bubaSksIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gxrDhu5tjIHTDrW5oIGzDoCBraG/huqNuZyA0Ny4yJS4NCg0KICBI4buHIHPhu5EgdGVudXJlID0gLTAuMDA2MzcgbWFuZyDDvSBuZ2jEqWE6IG3hu5dpIHRow6FuZyBn4bqvbiBiw7MgdGjDqm0gduG7m2kgZOG7i2NoIHbhu6UgdGjDrCB4w6FjIHN14bqldCBy4budaSBi4buPIGdp4bqjbSBraG/huqNuZyAwLjY0IMSRaeG7g20gcGjhuqduIHRyxINtLCB04bupYyBnaeG6o20gxJHhu4F1IHRoZW8gdGjhu51pIGdpYW4gc+G7rSBk4bulbmcuIMSQw6J5IGzDoCBt4buZdCB4dSBoxrDhu5tuZyBo4bujcCBsw70gdHJvbmcgbMSpbmggduG7sWMgY2jEg20gc8OzYyBraMOhY2ggaMOgbmcuDQoNCi0gxJDhu5kgcGjDuSBo4bujcCBtw7QgaMOsbmg6DQoNCiAgR2nDoSB0cuG7iyBBSUMgPSA3NTI5LjcgdHV5IGtow7RuZyBjYW8gdsaw4bujdCB0cuG7mWksIG5oxrBuZyB0aOG6pXAgaMahbiBzbyB24bubaSBjw6FjIG3DtCBow6xuaCBMUE0gdHLGsOG7m2MgxJHDsywgY2hvIHRo4bqleSBtw7QgaMOsbmggdHV54bq/biB0w61uaCBuw6B5IHBow7kgaOG7o3AgZOG7ryBsaeG7h3Ug4bufIG3hu6ljIHTGsMahbmcgxJHhu5FpLg0KDQogIFThuqV0IGPhuqMgaOG7hyBz4buRIMSR4buBdSBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHbhu5tpIHAgPCAyZS0xNiwgY2jhu6luZyB04buPIGJp4bq/biB0ZW51cmUgbMOgIG3hu5l0IHnhur91IHThu5EgcXVhbiB0cuG7jW5nIHbDoCBjw7Mgw70gbmdoxKlhIHRyb25nIHZp4buHYyBnaeG6o2kgdGjDrWNoIGjDoG5oIHZpIHLhu51pIGLhu48gY+G7p2Ega2jDoWNoIGjDoG5nLg0KDQogIFR1eSBuaGnDqm4sIGRvIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIGtow7RuZyDEkeG6o20gYuG6o28gZ2nDoSB0cuG7iyBk4buxIMSRb8OhbiBu4bqxbSB0cm9uZyBraG/huqNuZyBbMCwxXSB2w6Aga2jDtG5nIHBo4bqjbiDDoW5oIHThu5F0IGLhuqNuIGNo4bqldCBuaOG7iyBwaMOibiBj4bunYSBiaeG6v24gbeG7pWMgdGnDqnUsIHRhIG7Dqm4gc28gc8OhbmggduG7m2kgY8OhYyBtw7QgaMOsbmggbmjhu4sgcGjDom4gbmjGsCBsb2dpdC9wcm9iaXQvY2xvZ2xvZyDEkeG7gyBjaOG7jW4gbcO0IGjDrG5oIHBow7kgaOG7o3AgaMahbi4NCg0KIyMjICoqNC41LjIuIE3DtCBow6xuaCBMb2dpdCoqDQpgYGB7ciBsb2dpdC10ZW51cmUtc2luZ2xlLWZpbmFsfQ0KbG9naXRfdGVudXJlIDwtIGdsbShDaHVybl9iaW5hcnkgfiB0ZW51cmUsIGRhdGEgPSBkZl9jbGVhbiwgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpKQ0Kc3VtbWFyeShsb2dpdF90ZW51cmUpDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KDQpIw6BtIGjhu5NpIHF1eSDEkcaw4bujYyDGsOG7m2MgbMaw4bujbmcgbmjGsCBzYXU6DQokJA0KXGxvZ1xsZWZ0KFxmcmFje1xoYXR7XHBpfX17MSAtIFxoYXR7XHBpfX1ccmlnaHQpID0gMC4wMzcyOTkgLTAuMDM5MDEwIFx0aW1lcyBcdGV4dHt0ZW51cmV9DQokJA0KDQotICAgSOG7hyBz4buRIHRlbnVyZSA9IC0wLjAzOTAgY8OzIMO9IG5naMSpYTogbeG7l2kgdGjDoW5nIGtow6FjaCBow6BuZyBn4bqvbiBiw7MgdGjDqm0sIGxvZyBvZGRzIChsb2dpdCkgY+G7p2Egdmnhu4djIHLhu51pIGLhu48gZ2nhuqNtIDAuMDM5IMSRxqFuIHbhu4suDQoNCi0gVMawxqFuZyDhu6luZywgb2RkcyByYXRpbyAodOG7tyBz4buRIG9kZHMpIGzDoDoNCg0KJCQNCmVeey0wLjAzOX0gXGFwcHJveCAwLjk2Mg0KJCQNCg0K4oaSIE5naMSpYSBsw6AgbeG7l2kgdGjDoW5nIHRow6ptIGfhuq9uIGLDsyBsw6BtIGdp4bqjbSBraG/huqNuZyAzLjglIG9kZHMgcuG7nWkgYuG7jyBk4buLY2ggduG7pS4NCg0KLSDDnSBuZ2jEqWEgdGjhu5FuZyBrw6o6DQoNCkJp4bq/biB0ZW51cmUgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBjYW8gKHAgPCAyZS0xNiksIGNobyB0aOG6pXkgxJHDonkgbMOgIGJp4bq/biBxdWFuIHRy4buNbmcgdsOgIGPDsyDhuqNuaCBoxrDhu59uZyByw7UgcuG7h3QgxJHhur9uIGto4bqjIG7Eg25nIGtow6FjaCBow6BuZyBy4budaSBi4buPLg0KDQpUcm9uZyBraGkgxJHDsywgaOG7hyBz4buRIGNo4bq3biAoSW50ZXJjZXB0KSBraMO0bmcgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiAocCA9IDAuMzc4KSwgbmjGsG5nIMSRaeG7gXUgbsOgeSBraMO0bmcg4bqjbmggaMaw4bufbmcgbOG7m24gxJHhur9uIGdpw6EgdHLhu4sgbcO0IGjDrG5oLg0KDQrEkOG7mSBwaMO5IGjhu6NwIG3DtCBow6xuaDoNCg0KQUlDID0gNzE4MC4zLCB0aOG6pXAgaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBtw7QgaMOsbmggTFBNIHTGsMahbmcg4bupbmcgKEFJQyA9IDc1MjkuNyksIGNo4bupbmcgdOG7jyBo4buTaSBxdXkgbG9naXN0aWMgcGjDuSBo4bujcCBoxqFuIMSRw6FuZyBr4buDIGNobyBk4buvIGxp4buHdSBuaOG7iyBwaMOibi4NCg0KUmVzaWR1YWwgZGV2aWFuY2UgPSA3MTc2LjMsIGdp4bqjbSBuaGnhu4F1IHNvIHbhu5tpIE51bGwgZGV2aWFuY2UgPSA4MTQzLjQsIGNobyB0aOG6pXkgbcO0IGjDrG5oIGPDsyBj4bqjaSB0aGnhu4duIHThu5F0IGtoaSDEkcawYSB0ZW51cmUgdsOgby4NCg0KIyMjICoqNC41LjMuIE3DtCBow6xuaCBQcm9iaXQqKg0KYGBge3IgcHJvYml0LXRlbnVyZS1zaW5nbGUtZmluYWx9DQpwcm9iaXRfdGVudXJlIDwtIGdsbShDaHVybl9iaW5hcnkgfiB0ZW51cmUsIGRhdGEgPSBkZl9jbGVhbiwgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJwcm9iaXQiKSkNCnN1bW1hcnkocHJvYml0X3RlbnVyZSkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqDQoNCkjDoG0gUHJvYml0IMaw4bubYyBsxrDhu6NuZyBuaMawIHNhdToNCiQkDQpcUGhpXnstMX0oXGhhdHtccGl9KSA9IDAuMDAxNzM1NSAtMC4wMjIzMzE2IFx0aW1lcyBcdGV4dHt0ZW51cmV9DQokJA0KLSAgS+G6v3QgcXXhuqMgaOG7k2kgcXV5IHPhu60gZOG7pW5nIG3DtCBow6xuaCBwcm9iaXQgY2hvIHRo4bqleSBiaeG6v24gdGjhu51pIGdpYW4gZ+G6r24gYsOzICh0ZW51cmUpIGPDsyDhuqNuaCBoxrDhu59uZyB0acOqdSBj4buxYyB2w6AgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBy4bqldCBjYW8gxJHhur9uIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gZOG7i2NoIHbhu6UgKENodXJuKS4gSOG7hyBz4buRIMaw4bubYyBsxrDhu6NuZyBjaG8gYmnhur9uIHRlbnVyZSBsw6AgLTAuMDIyMyAocCA8IDJlLTE2KSwgY2hvIHRo4bqleSBraGkgdGjhu51pIGdpYW4gZ+G6r24gYsOzIGPhu6dhIGtow6FjaCBow6BuZyB0xINuZyBsw6puIDEgxJHGoW4gduG7iywgeMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBnaeG6o20gxJHDoW5nIGvhu4MuIE3hurdjIGTDuSBo4buHIHPhu5EgY2jhurduIGtow7RuZyBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIChwID0gMC45NDYpLCBuaMawbmcgxJFp4buBdSBuw6B5IGtow7RuZyDhuqNuaCBoxrDhu59uZyDEkeG6v24gw70gbmdoxKlhIGPhu6dhIGJp4bq/biBnaeG6o2kgdGjDrWNoIGNow61uaC4gR2nDoSB0cuG7iyBBSUMgY+G7p2EgbcO0IGjDrG5oIGzDoCA3MTg1LjgsIGNobyB0aOG6pXkgbeG7qWMgxJHhu5kgcGjDuSBo4bujcCB0xrDGoW5nIMSR4buRaSB04buRdCBraGkgc28gc8OhbmggduG7m2kgY8OhYyBtw7QgaMOsbmgga2jDoWMuDQoNCiMjIyAqKjQuNS40LiBNw7QgaMOsbmggQ2xvZ2xvZyoqDQpgYGB7ciBjbG9nbG9nLXRlbnVyZS1zaW5nbGUtZmluYWx9DQpjbG9nbG9nX3RlbnVyZSA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gdGVudXJlLCBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAiY2xvZ2xvZyIpKQ0Kc3VtbWFyeShjbG9nbG9nX3RlbnVyZSkNCmBgYA0KDQoqKk5o4bqtbiB4w6l0OioqDQoNClBoxrDGoW5nIHRyw6xuaCBo4buTaSBxdXkgQ2xvZ2xvZzoNCiQkDQpcbG9nKC1cbG9nKDEgLSBcaGF0e1xwaX0pKSA9IC0wLjI5MzIzMCAtMC4wMzQwNjEgXHRpbWVzIFx0ZXh0e3RlbnVyZX0NCiQkDQotICAgTcO0IGjDrG5oIGjhu5NpIHF1eSBuaOG7iyBwaMOibiB24bubaSBsacOqbiBr4bq/dCBjb21wbGVtZW50YXJ5IGxvZy1sb2cgKGNsb2dsb2cpIGNobyB0aOG6pXkgYmnhur9uIHRo4budaSBnaWFuIGfhuq9uIGLDsyAodGVudXJlKSBjw7Mg4bqjbmggaMaw4bufbmcgw6JtIHbDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHLhuqV0IG3huqFuaCDEkeG6v24ga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyBk4buLY2ggduG7pS4gSOG7hyBz4buRIMaw4bubYyBsxrDhu6NuZyBjaG8gdGVudXJlIGzDoCAtMC4wMzQxIHbhu5tpIHAtdmFsdWUgPCAyZS0xNiwgxJFp4buBdSBuw6B5IGNobyB0aOG6pXkgcuG6sW5nIGtoaSB0aOG7nWkgZ2lhbiBn4bqvbiBiw7MgdMSDbmcgdGjDqm0gMSDEkcahbiB24buLLCBsb2coLWxvZygxIC0gUChDaHVybikpKSBnaeG6o20sIHThu6ljIGzDoCB4w6FjIHN14bqldCBy4budaSBi4buPIGdp4bqjbS4gSOG7hyBz4buRIGNo4bq3biBjxaluZyBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIGNhby4NCg0KLSBNw7QgaMOsbmggY2xvZ2xvZyDEkeG6oXQgxJHGsOG7o2MgQUlDID0gNzE3MC4xLCB0aOG6pXAgaMahbiBzbyB24bubaSBtw7QgaMOsbmggbG9naXQgKEFJQyA9IDcxODAuMykgdsOgIHByb2JpdCAoQUlDID0gNzE4NS44KS4gxJBp4buBdSBuw6B5IGNobyB0aOG6pXkgbcO0IGjDrG5oIGNsb2dsb2cgcGjDuSBo4bujcCBk4buvIGxp4buHdSB04buRdCBoxqFuIHNvIHbhu5tpIGhhaSBtw7QgaMOsbmggY8OybiBs4bqhaSBraGkgY2jhu4kgeMOpdCBiaeG6v24gdGVudXJlLg0KDQojIyMgKio0LjUuNS4gxJDDoW5oIGdpw6EgY8OhYyBtw7QgaMOsbmgqKg0KYGBge3IgY29tcGFyZS10ZW51cmUtbW9kZWxzfQ0KYWljX3RlbnVyZSA8LSBkYXRhLmZyYW1lKA0KICBNb2RlbCA9IGMoIkxQTSIsIkxvZ2l0IiwgIlByb2JpdCIsICJDbG9nbG9nIiksDQogIEFJQyA9IGMoQUlDKGxwbV90ZW51cmUpLEFJQyhsb2dpdF90ZW51cmUpLCBBSUMocHJvYml0X3RlbnVyZSksIEFJQyhjbG9nbG9nX3RlbnVyZSkpDQopDQprYWJsZShhaWNfdGVudXJlLCBjYXB0aW9uID0gIlNvIHPDoW5oIEFJQyBjw6FjIG3DtCBow6xuaCBjaG8gYmnhur9uIHRlbnVyZSIpDQpgYGANCg0KLSBNw7QgaMOsbmggQ2xvZ2xvZyBsw6AgbcO0IGjDrG5oIGPDsyBt4bupYyDEkeG7mSBwaMO5IGjhu6NwIHThu5F0IG5o4bqldCB24bubaSBk4buvIGxp4buHdSBraGkgY2jhu4kgeMOpdCBiaeG6v24gdGVudXJlLCBkbyBjw7MgZ2nDoSB0cuG7iyBBSUMgdGjhuqVwIG5o4bqldCAoNzE3MC4xMjUpLg0KDQotIE3DtCBow6xuaCBMb2dpdCB2w6AgUHJvYml0IMSR4buBdSBjaG8gdGjhuqV5IHRlbnVyZSBsw6AgYmnhur9uIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogY2FvLCBuaMawbmcgaGnhu4d1IHF14bqjIGvDqW0gaMahbiBjbG9nbG9nIG3hu5l0IGNow7p0Lg0KDQotIE3DtCBow6xuaCBMUE0gY8OzIEFJQyBy4bqldCBjYW8gKDc1MjkuNzAyKSwgeMOhYyBuaOG6rW4gcuG6sW5nIHBoxrDGoW5nIHBow6FwIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIGtow7RuZyBwaMO5IGjhu6NwIMSR4buDIGThu7EgxJFvw6FuIGJp4bq/biBuaOG7iyBwaMOibiBuaMawIENodXJuLg0KDQotIERvIMSRw7MsIG3DtCBow6xuaCBjbG9nbG9nIGzDoCBs4buxYSBjaOG7jW4gxrB1IHRpw6puIGtoaSBtdeG7kW4gZOG7sSDEkW/DoW4geMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBjaOG7iSBk4buxYSB2w6BvIGJp4bq/biB0aOG7nWkgZ2lhbiBn4bqvbiBiw7MgKHRlbnVyZSkuDQoNCiMgKipDSMavxqBORyA1OiBNw5QgSMOMTkggSOG7kkkgUVVZIELhu5hJKioNCg0KIyMgKio1LjEuIE3DtCBow6xuaCBYw6FjIHN14bqldCBUdXnhur9uIHTDrW5oIChMUE0pIELhu5lpKioNCmBgYHtyIG11bHRpLWxwbS1maW5hbH0NCmxwbV9tdWx0aSA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gQ29udHJhY3QgKyBTZW5pb3JDaXRpemVuICsgUGF5bWVudE1ldGhvZCArIEludGVybmV0U2VydmljZSArIHRlbnVyZSwNCiAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX2NsZWFuLCBmYW1pbHkgPSBnYXVzc2lhbikNCnN1bW1hcnkobHBtX211bHRpKQ0KYGBgDQoNClxbDQpcbG9nXGxlZnQoIFxmcmFje1xoYXR7XHBpfX17MSAtIFxoYXR7XHBpfX0gXHJpZ2h0KSA9IC0wLjI5MzcxIC0gMS4zODc3MCBcY2RvdCBcdGV4dHtDb250cmFjdE9uZVllYXJ9IC0xLjc5MTIwIFxjZG90IFx0ZXh0e0NvbnRyYWN0VHdvWWVhcn0gKyAwLjQ1NjYxIFxjZG90IFx0ZXh0e1NlbmlvckNpdGl6ZW5ZZXN9IA0KXF0NClxbDQotIDAuMTUzOTQgXGNkb3QgXHRleHR7UGF5bWVudE1ldGhvZENyZWRpdENhcmR9ICsgMC44MTAxMiBcY2RvdCBcdGV4dHtQYXltZW50TWV0aG9kRWxlY3Ryb25pY0NoZWNrfSAtIDAuMTczNTIgXGNkb3QgXHRleHR7UGF5bWVudE1ldGhvZE1haWxlZENoZWNrfSANClxdDQpcWw0KKyAxLjQ0MDExIFxjZG90IFx0ZXh0e0ludGVybmV0U2VydmljZUZpYmVyT3B0aWN9IC0gMS40Nzk5NCBcY2RvdCBcdGV4dHtJbnRlcm5ldFNlcnZpY2VOb30gLSAwLjA3NDM2IFxjZG90IFx0ZXh0e3RlbnVyZX0NClxdDQoNClRyb25nIMSRw7M6DQotIFwoXGhhdHtccGl9XCkgbMOgIHjDoWMgc3XhuqV0IGtow6FjaCBow6BuZyBy4budaSBi4buPIGThu4tjaCB24bulIChgQ2h1cm4gPSAxYCkuDQotIEPDoWMgYmnhur9uIGzDoCBiaeG6v24gZ2nhuqMgxJHhuqFpIGRp4buHbiBjaG8gdOG7q25nIG5ow7NtIChzbyB24bubaSBuaMOzbSB0aGFtIGNoaeG6v3UpOg0KICAtIGBDb250cmFjdGA6IHRoYW0gY2hp4bq/dSBsw6AgIk1vbnRoLXRvLW1vbnRoIi4NCiAgLSBgUGF5bWVudE1ldGhvZGA6IHRoYW0gY2hp4bq/dSBsw6AgIkJhbmsgdHJhbnNmZXIgKGF1dG9tYXRpYykiLg0KICAtIGBJbnRlcm5ldFNlcnZpY2VgOiB0aGFtIGNoaeG6v3UgbMOgICJEU0wiLg0KLSBgdGVudXJlYDogc+G7kSB0aMOhbmcga2jDoWNoIGjDoG5nIMSRw6Mgc+G7rSBk4bulbmcgZOG7i2NoIHbhu6UuDQoNCg0KDQoNCnwgQmnhur9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBI4buHIHPhu5EgxrDhu5tjIGzGsOG7o25nIHwgU2FpIHPhu5EgY2h14bqpbiB8IEdpw6EgdHLhu4sgdCB8IHAtdmFsdWUgIHwgw50gbmdoxKlhIHRo4buRbmcga8OqIHwNCnwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tIHwgLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tIHwNCnwgKEludGVyY2VwdCkgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4zODI4ICAgICAgICAgIHwgMC4wMTQ1ICAgICAgIHwgMjYuMzU1ICAgIHwgPCAyZS0xNiAgfCBcKlwqXCogICAgICAgICAgIHwNCnwgQ29udHJhY3RPbmUgeWVhciAgICAgICAgICAgICAgICAgICAgIHwgLTAuMTI5MSAgICAgICAgIHwgMC4wMTM4ICAgICAgIHwgLTkuMzMxICAgIHwgPCAyZS0xNiAgfCBcKlwqXCogICAgICAgICAgIHwNCnwgQ29udHJhY3RUd28geWVhciAgICAgICAgICAgICAgICAgICAgIHwgLTAuMDk1MiAgICAgICAgIHwgMC4wMTY2ICAgICAgIHwgLTUuNzQ4ICAgIHwgOS4zOGUtMDkgfCBcKlwqXCogICAgICAgICAgIHwNCnwgU2VuaW9yQ2l0aXplblllcyAgICAgICAgICAgICAgICAgICAgIHwgMC4wNjUyICAgICAgICAgIHwgMC4wMTI5ICAgICAgIHwgNS4wNjcgICAgIHwgNC4xNGUtMDcgfCBcKlwqXCogICAgICAgICAgIHwNCnwgUGF5bWVudE1ldGhvZENyZWRpdCBjYXJkIChhdXRvbWF0aWMpIHwgLTAuMDA5MCAgICAgICAgIHwgMC4wMTM3ICAgICAgIHwgLTAuNjU4ICAgIHwgMC41MTA0ICAgfCAgICAgICAgICAgICAgICAgIHwNCnwgUGF5bWVudE1ldGhvZEVsZWN0cm9uaWMgY2hlY2sgICAgICAgIHwgMC4wODk5ICAgICAgICAgIHwgMC4wMTM0ICAgICAgIHwgNi43MjcgICAgIHwgMS44N2UtMTEgfCBcKlwqXCogICAgICAgICAgIHwNCnwgUGF5bWVudE1ldGhvZE1haWxlZCBjaGVjayAgICAgICAgICAgIHwgLTAuMDI4NSAgICAgICAgIHwgMC4wMTQ2ICAgICAgIHwgLTEuOTU2ICAgIHwgMC4wNTA2ICAgfCAuICAgICAgICAgICAgICAgIHwNCnwgSW50ZXJuZXRTZXJ2aWNlRmliZXIgb3B0aWMgICAgICAgICAgIHwgMC4xNzE3ICAgICAgICAgIHwgMC4wMTEwICAgICAgIHwgMTUuNTc2ICAgIHwgPCAyZS0xNiAgfCBcKlwqXCogICAgICAgICAgIHwNCnwgSW50ZXJuZXRTZXJ2aWNlTm8gICAgICAgICAgICAgICAgICAgIHwgLTAuMDgzMCAgICAgICAgIHwgMC4wMTMxICAgICAgIHwgLTYuMzQ2ICAgIHwgMi4zNWUtMTAgfCBcKlwqXCogICAgICAgICAgIHwNCnwgdGVudXJlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgLTAuMDA0OCAgICAgICAgIHwgMC4wMDAzICAgICAgIHwgLTE3LjUxOCAgIHwgPCAyZS0xNiAgfCBcKlwqXCogICAgICAgICAgIHwNCg0KKipOaOG6rW4geMOpdDoqKg0KDQpNw7QgaMOsbmggTFBNIGNobyB0aOG6pXkgcGjhuqduIGzhu5tuIGPDoWMgYmnhur9uIMSR4buBdSBjw7Mg4bqjbmggaMaw4bufbmcgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiDEkeG6v24geMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBk4buLY2ggduG7pToNCg0KLSBLaMOhY2ggaMOgbmcgY8OzIGjhu6NwIMSR4buTbmcgMSBuxINtIGhv4bq3YyAyIG7Eg20gY8OzIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gdGjhuqVwIGjGoW4gxJHDoW5nIGvhu4Mgc28gduG7m2kga2jDoWNoIGjDoG5nIGjhu6NwIMSR4buTbmcgdGhlbyB0aMOhbmcuDQoNCi0gTmfGsOG7nWkgY2FvIHR14buVaSAoU2VuaW9yQ2l0aXplbiA9IFllcykgY8OzIHjDoWMgc3XhuqV0IHLhu51pIGLhu48gY2FvIGjGoW4uDQoNCi0gUGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuIGLhurFuZyBlbGVjdHJvbmljIGNoZWNrIGzDoG0gdMSDbmcga2jhuqMgbsSDbmcgcuG7nWkgYuG7jzsgbmfGsOG7o2MgbOG6oWksIGPDoWMgcGjGsMahbmcgdGjhu6ljIGtow6FjIG5oxrAgbWFpbGVkIGNoZWNrIHbDoCBjcmVkaXQgY2FyZCAoYXV0b21hdGljKSBraMO0bmcgY8OzIMO9IG5naMSpYSByw7UgcsOgbmcuDQoNCi0gS2jDoWNoIGjDoG5nIHPhu60gZOG7pW5nIGludGVybmV0IGPDoXAgcXVhbmcgKGZpYmVyIG9wdGljKSBjw7Mga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyBjYW8gaMahbiwgdHJvbmcga2hpIG5o4buvbmcgbmfGsOG7nWkga2jDtG5nIHPhu60gZOG7pW5nIEludGVybmV0IGzhuqFpIMOtdCBy4budaSBi4buPIGjGoW4uDQoNCi0gVGjhu51pIGdpYW4gc+G7rSBk4bulbmcgZOG7i2NoIHbhu6UgKHRlbnVyZSkgY8OgbmcgZMOgaSB0aMOsIGto4bqjIG7Eg25nIHLhu51pIGLhu48gY8OgbmcgdGjhuqVwLg0KDQotIE3DtCBow6xuaCBjw7MgQUlDID0gNjM1MC44LCBjaG8gdGjhuqV5IG3hu6ljIMSR4buZIHBow7kgaOG7o3AgdMawxqFuZyDEkeG7kWkgdOG7kXQgdHJvbmcgYuG7kWkgY+G6o25oIMSRxqFuIGdp4bqjbiBow7NhIGLhurFuZyBMUE0uIFR1eSBuaGnDqm4sIGRvIGLhuqNuIGNo4bqldCBMUE0gY8OzIHRo4buDIGThu7EgxJFvw6FuIHjDoWMgc3XhuqV0IG5nb8OgaSBraG/huqNuZyBbMCwxXSwgdmnhu4djIHNvIHPDoW5oIHbhu5tpIGPDoWMgbcO0IGjDrG5oIHBoaSB0dXnhur9uIG5oxrAgTG9naXQsIFByb2JpdCBoYXkgQ2xvZ2xvZyBsw6AgY+G6p24gdGhp4bq/dCDEkeG7gyDEkcOhbmggZ2nDoSB0b8OgbiBkaeG7h24gaMahbi4NCg0KDQoqKkvhur90IGx14bqtbjoqKiBU4burIG3DtCBow6xuaCBMUE0sIGPDsyB0aOG7gyBr4bq/dCBsdeG6rW4gcuG6sW5nIGjhu6NwIMSR4buTbmcsIGThu4tjaCB24bulIEludGVybmV0LCB2w6AgdGjhu51pIGdpYW4gZ+G6r24gYsOzIGzDoCBuaOG7r25nIHnhur91IHThu5EgY8OzIOG6o25oIGjGsOG7n25nIG3huqFuaCBt4bq9IG5o4bqldCDEkeG6v24geMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBj4bunYSBraMOhY2ggaMOgbmcuDQoNCiMjICoqNS4yLiBNw7QgaMOsbmggTG9naXQgQuG7mWkqKg0KYGBge3IgbXVsdGktbG9naXQtZmluYWx9DQpsb2dpdF9tdWx0aSA8LSBnbG0oQ2h1cm5fYmluYXJ5IH4gQ29udHJhY3QgKyBTZW5pb3JDaXRpemVuICsgUGF5bWVudE1ldGhvZCArIEludGVybmV0U2VydmljZSArIHRlbnVyZSwNCiAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSkNCnN1bW1hcnkobG9naXRfbXVsdGkpDQpgYGANClxbDQpcbG9nXGxlZnQoIFxmcmFje1xoYXR7XHBpfX17MSAtIFxoYXR7XHBpfX0gXHJpZ2h0KSA9IC0wLjQ5NjMyIA0KLSAwLjc0NzA4IFxjZG90IFx0ZXh0e0NvbnRyYWN0T25lWWVhcn0gDQotIDEuNTExMTkgXGNkb3QgXHRleHR7Q29udHJhY3RUd29ZZWFyfSANCisgMC4zNDE4NyBcY2RvdCBcdGV4dHtTZW5pb3JDaXRpemVuWWVzfQ0KXF0NClxbDQotIDAuMDcwMDUgXGNkb3QgXHRleHR7UGF5bWVudE1ldGhvZENyZWRpdENhcmR9IA0KKyAwLjQyNjg4IFxjZG90IFx0ZXh0e1BheW1lbnRNZXRob2RFbGVjdHJvbmljQ2hlY2t9IA0KLSAwLjA2MzMwIFxjZG90IFx0ZXh0e1BheW1lbnRNZXRob2RNYWlsZWRDaGVja30NClxdDQpcWw0KKyAxLjA0OTAyIFxjZG90IFx0ZXh0e0ludGVybmV0U2VydmljZUZpYmVyT3B0aWN9DQotIDAuOTAyODUgXGNkb3QgXHRleHR7SW50ZXJuZXRTZXJ2aWNlTm99DQotIDAuMDMxNDcgXGNkb3QgXHRleHR7dGVudXJlfQ0KXF0NCg0KVHJvbmcgxJHDszogIA0KLSBcKFxoYXR7XHBpfVwpIGzDoCB4w6FjIHN14bqldCBraMOhY2ggaMOgbmcgcuG7nWkgYuG7jyBk4buLY2ggduG7pS4NCi0gQ8OhYyBiaeG6v24gbMOgIGJp4bq/biBnaeG6oyDEkeG6oWkgZGnhu4duIGNobyBuaMOzbSBzbyB24bubaSBuaMOzbSB0aGFtIGNoaeG6v3UuDQoNCnwgQmnhur9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgTmjDs20gc28gc8OhbmggICAgICAgICAgICAgICAgICAgICAgICAgIHwgSOG7hyBz4buRICjOsikgfCBwLXZhbHVlICB8IE9kZHMgUmF0aW8gKGVezrIpIHwNCnwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0gfCAtLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0gfA0KfCBI4bujcCDEkeG7k25nOiBN4buZdCBuxINtICAgICAgICAgICAgICAgICAgfCBTbyB24bubaSBI4bujcCDEkeG7k25nIHRow6FuZyBt4buZdCAgICAgICAgICAgICB8IC0wLjc0NzA4ICB8IDQuNTJlLTEzIHwgMC40NyAgICAgICAgICAgICB8DQp8IEjhu6NwIMSR4buTbmc6IEhhaSBuxINtICAgICAgICAgICAgICAgICAgfCBTbyB24bubaSBI4bujcCDEkeG7k25nIHRow6FuZyBt4buZdCAgICAgICAgICAgICB8IC0xLjUxMTE5ICB8IDwgMmUtMTYgIHwgMC4yMiAgICAgICAgICAgICB8DQp8IEzDoCBuZ8aw4budaSBjYW8gdHXhu5VpICAgICAgICAgICAgICAgICAgfCBTbyB24bubaSBraMO0bmcgY2FvIHR14buVaSAgICAgICAgICAgICAgICAgfCAwLjM0MTg3ICAgfCAyLjc5ZS0wNSB8IDEuNDEgICAgICAgICAgICAgfA0KfCBUaGFuaCB0b8OhbjogVGjhursgdMOtbiBk4bulbmcgKHThu7EgxJHhu5luZykgfCBTbyB24bubaSB0aGFuaCB0b8OhbiBuZ8OibiBow6BuZyAodOG7sSDEkeG7mW5nKSB8IC0wLjA3MDA1ICB8IDAuNTMzICAgIHwgMC45MyAgICAgICAgICAgICB8DQp8IFRoYW5oIHRvw6FuOiBTw6ljIMSRaeG7h24gdOG7rSAgICAgICAgICAgIHwgU28gduG7m2kgdGhhbmggdG/DoW4gbmfDom4gaMOgbmcgKHThu7EgxJHhu5luZykgfCAwLjQyNjg4ICAgfCA0LjA4ZS0wNiB8IDEuNTMgICAgICAgICAgICAgfA0KfCBUaGFuaCB0b8OhbjogR+G7rWkgc8OpYyAgICAgICAgICAgICAgICB8IFNvIHbhu5tpIHRoYW5oIHRvw6FuIG5nw6JuIGjDoG5nICh04buxIMSR4buZbmcpIHwgLTAuMDYzMzAgIHwgMC41NzAgICAgfCAwLjk0ICAgICAgICAgICAgIHwNCnwgSW50ZXJuZXQ6IEPDoXAgcXVhbmcgICAgICAgICAgICAgICAgfCBTbyB24bubaSBEU0wgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAxLjA0OTAyICAgfCA8IDJlLTE2ICB8IDIuODYgICAgICAgICAgICAgfA0KfCBJbnRlcm5ldDogS2jDtG5nIGPDsyAgICAgICAgICAgICAgICAgfCBTbyB24bubaSBEU0wgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAtMC45MDI4NSAgfCA1LjQ5ZS0xNCB8IDAuNDEgICAgICAgICAgICAgfA0KfCBUaMOibSBuacOqbiAodGjDoW5nKSAgICAgICAgICAgICAgICAgIHwgTeG7l2kgdGjDoW5nIHTEg25nIHRow6ptICAgICAgICAgICAgICAgICAgIHwgLTAuMDMxNDcgIHwgPCAyZS0xNiAgfCAwLjk3ICAgICAgICAgICAgIHwNCg0KDQoqKk5o4bqtbiB4w6l0OioqDQoNCi0gKipI4bujcCDEkeG7k25nIG3hu5l0IG7Eg20gaG/hurdjIGhhaSBuxINtKiogxJHhu4F1IGzDoG0gZ2nhuqNtIMSRw6FuZyBr4buDIGto4bqjIG7Eg25nIHLhu51pIGLhu48sIMSR4bq3YyBiaeG7h3QgbMOgIGjhu6NwIMSR4buTbmcgaGFpIG7Eg20gduG7m2kgaOG7hyBz4buRIMOibSBs4bubbi4NCi0gKipLaMOhY2ggaMOgbmcgY2FvIHR14buVaSoqIChTZW5pb3JDaXRpemVuWWVzKSBjw7Mga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyBjYW8gaMahbiAoaOG7hyBz4buRIGTGsMahbmcsIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6opLg0KLSAqKlBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiBi4bqxbmcgRWxlY3Ryb25pYyBjaGVjayoqIGPDsyBsacOqbiBxdWFuIG3huqFuaCBuaOG6pXQgxJHhur9uIHZp4buHYyBy4budaSBi4buPICho4buHIHPhu5EgZMawxqFuZyB2w6AgcC12YWx1ZSA8IDAuMDAxKS4NCi0gKipJbnRlcm5ldCBGaWJlciBPcHRpYyoqIGzDoG0gdMSDbmcgxJHDoW5nIGvhu4MgeMOhYyBzdeG6pXQgcuG7nWkgYuG7jywgbmfGsOG7o2MgbOG6oWksIGtow7RuZyBz4butIGThu6VuZyBpbnRlcm5ldCAoSW50ZXJuZXRTZXJ2aWNlTm8pIGzhuqFpIGzDoG0gZ2nhuqNtIHjDoWMgc3XhuqV0IHLhu51pIGLhu48uDQotICoqU+G7kSB0aMOhbmcgc+G7rSBk4bulbmcgZOG7i2NoIHbhu6UgKHRlbnVyZSkqKiBjw6BuZyBjYW8gdGjDrCB4w6FjIHN14bqldCBy4budaSBi4buPIGPDoG5nIHRo4bqlcCAoaOG7hyBz4buRIMOibSB2w6AgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBjYW8pLg0KDQojIyAqKjUuMy4gTcO0IGjDrG5oIFByb2JpdCBC4buZaSoqDQpgYGB7ciBtdWx0aS1wcm9iaXQtZmluYWx9DQpwcm9iaXRfbXVsdGkgPC0gZ2xtKENodXJuX2JpbmFyeSB+IENvbnRyYWN0ICsgU2VuaW9yQ2l0aXplbiArIFBheW1lbnRNZXRob2QgKyBJbnRlcm5ldFNlcnZpY2UgKyB0ZW51cmUsDQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl9jbGVhbiwgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJwcm9iaXQiKSkNCnN1bW1hcnkocHJvYml0X211bHRpKQ0KYGBgDQoNCiQkDQpcUGhpXnstMX0oXGhhdHtccGl9KSA9IC0wLjMwMzE4IC0gMC40MjQzNSBcY2RvdCBcdGV4dHtDb250cmFjdE9uZVllYXJ9IC0gMC43NDA3MiBcY2RvdCBcdGV4dHtDb250cmFjdFR3b1llYXJ9ICsgMC4yMDEzOSBcY2RvdCBcdGV4dHtTZW5pb3JDaXRpemVuWWVzfSBcXA0KLSAwLjAzODczIFxjZG90IFx0ZXh0e1BheW1lbnRNZXRob2RDcmVkaXRDYXJkfSArIDAuMjU0OTQgXGNkb3QgXHRleHR7UGF5bWVudE1ldGhvZEVsZWN0cm9uaWNDaGVja30gLSAwLjA1NDExIFxjZG90IFx0ZXh0e1BheW1lbnRNZXRob2RNYWlsZWR9IFxcDQorIDAuNjE4ODcgXGNkb3QgXHRleHR7SW50ZXJuZXRTZXJ2aWNlRmliZXJPcHRpY30gLSAwLjUxMjkwIFxjZG90IFx0ZXh0e0ludGVybmV0U2VydmljZU5vfSAtIDAuMDE4MTUgXGNkb3QgXHRleHR7dGVudXJlfQ0KJCQNCg0KVHJvbmcgxJHDszoNCg0KLSAkXFBoaV57LTF9KFxoYXR7XHBpfSkkIGzDoCBow6BtIGxpw6puIGvhur90IHByb2JpdCAoaMOgbSBuZ2jhu4tjaCDEkeG6o28gY+G7p2EgY2h14bqpbiB0w61jaCBsxal5IGNodeG6qW4pLg0KLSBDw6FjIGJp4bq/biBsw6AgYmnhur9uIGdp4bqjIHNvIHbhu5tpIG5ow7NtIHRoYW0gY2hp4bq/dS4NCg0KDQp8IEJp4bq/biAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IE5ow7NtIHNvIHPDoW5oICAgICAgICAgICAgICAgICAgICAgICAgICB8IEjhu4cgc+G7kSAozrIpIHwgcC12YWx1ZSAgfA0KfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLSB8IC0tLS0tLS0tIHwNCnwgSOG7o3AgxJHhu5NuZzogTeG7mXQgbsSDbSAgICAgICAgICAgICAgICAgIHwgU28gduG7m2kgSOG7o3AgxJHhu5NuZyB0aMOhbmcgbeG7mXQgICAgICAgICAgICAgfCAtMC40MjQzNSAgfCAxLjA1ZS0xMyB8DQp8IEjhu6NwIMSR4buTbmc6IEhhaSBuxINtICAgICAgICAgICAgICAgICAgfCBTbyB24bubaSBI4bujcCDEkeG7k25nIHRow6FuZyBt4buZdCAgICAgICAgICAgICB8IC0wLjc0MDcyICB8IDwgMmUtMTYgIHwNCnwgTMOgIG5nxrDhu51pIGNhbyB0deG7lWkgICAgICAgICAgICAgICAgICB8IFNvIHbhu5tpIGtow7RuZyBjYW8gdHXhu5VpICAgICAgICAgICAgICAgICB8IDAuMjAxMzkgICB8IDIuODZlLTA1IHwNCnwgVGhhbmggdG/DoW46IFRo4bq7IHTDrW4gZOG7pW5nICh04buxIMSR4buZbmcpIHwgU28gduG7m2kgdGhhbmggdG/DoW4gbmfDom4gaMOgbmcgKHThu7EgxJHhu5luZykgfCAtMC4wMzg3MyAgfCAwLjUzOCAgICB8DQp8IFRoYW5oIHRvw6FuOiBTw6ljIMSRaeG7h24gdOG7rSAgICAgICAgICAgIHwgU28gduG7m2kgdGhhbmggdG/DoW4gbmfDom4gaMOgbmcgKHThu7EgxJHhu5luZykgfCAwLjI1NDk0ICAgfCAxLjk0ZS0wNiB8DQp8IFRoYW5oIHRvw6FuOiBH4butaSBzw6ljICAgICAgICAgICAgICAgIHwgU28gduG7m2kgdGhhbmggdG/DoW4gbmfDom4gaMOgbmcgKHThu7EgxJHhu5luZykgfCAtMC4wNTQxMSAgfCAwLjM5NiAgICB8DQp8IEludGVybmV0OiBDw6FwIHF1YW5nICAgICAgICAgICAgICAgIHwgU28gduG7m2kgRFNMICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC42MTg4NyAgIHwgPCAyZS0xNiAgfA0KfCBJbnRlcm5ldDogS2jDtG5nIGPDsyAgICAgICAgICAgICAgICAgfCBTbyB24bubaSBEU0wgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAtMC41MTI5MCAgfCAzLjcyZS0xNSB8DQp8IFRow6JtIG5pw6puICh0aMOhbmcpICAgICAgICAgICAgICAgICAgfCBN4buXaSB0aMOhbmcgdMSDbmcgdGjDqm0gICAgICAgICAgICAgICAgICAgfCAtMC4wMTgxNSAgfCA8IDJlLTE2ICB8DQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KLSBI4bujcCDEkeG7k25nIGTDoGkgaOG6oW4gKG3hu5l0IG7Eg20gdsOgIGhhaSBuxINtKSDEkeG7gXUgbMOgbSBnaeG6o20geMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBk4buLY2ggduG7pSwgxJHhurdjIGJp4buHdCBsw6AgaOG7o3AgxJHhu5NuZyBoYWkgbsSDbSBjw7MgdMOhYyDEkeG7mW5nIG3huqFuaCBoxqFuICho4buHIHPhu5Egw6JtIGzhu5tuLCBwLXZhbHVlIHLhuqV0IG5o4buPKS4NCg0KLSBLaMOhY2ggaMOgbmcgY2FvIHR14buVaSBjw7MgeHUgaMaw4bubbmcgcuG7nWkgYuG7jyBjYW8gaMahbiwgduG7m2kgaOG7hyBz4buRIGTGsMahbmcgdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNCi0gUGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuIGLhurFuZyBTw6ljIMSRaeG7h24gdOG7rSBsw6AgeeG6v3UgdOG7kSBsw6BtIHTEg25nIGto4bqjIG7Eg25nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UsIHbhu5tpIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBt4bqhbmggbeG6vSAocC12YWx1ZSA8IDAuMDAxKS4NCg0KLSBT4butIGThu6VuZyBJbnRlcm5ldCBGaWJlciBPcHRpYyBsw6BtIHTEg25nIMSRw6FuZyBr4buDIGto4bqjIG7Eg25nIHLhu51pIGLhu48sIHRyb25nIGtoaSBraMO0bmcgc+G7rSBk4bulbmcgSW50ZXJuZXQgbOG6oWkgZ2nhuqNtIMSRw6FuZyBr4buDIHjDoWMgc3XhuqV0IG7DoHkuDQoNCi0gVGjhu51pIGdpYW4gc+G7rSBk4bulbmcgZOG7i2NoIHbhu6UgKHRlbnVyZSkgY8OgbmcgY2FvIHRow6wga2jDoWNoIGjDoG5nIGPDoG5nIMOtdCBjw7Mga2jhuqMgbsSDbmcgcuG7nWkgYuG7jy4NCg0KDQojIyAqKjUuNC4gTcO0IGjDrG5oIENsb2dsb2cgQuG7mWkqKg0KYGBge3IgbXVsdGktY2xvZ2xvZy1maW5hbH0NCmNsb2dsb2dfbXVsdGkgPC0gZ2xtKENodXJuX2JpbmFyeSB+IENvbnRyYWN0ICsgU2VuaW9yQ2l0aXplbiArIFBheW1lbnRNZXRob2QgKyBJbnRlcm5ldFNlcnZpY2UgKyB0ZW51cmUsDQogICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfY2xlYW4sIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAiY2xvZ2xvZyIpKQ0Kc3VtbWFyeShjbG9nbG9nX211bHRpKQ0KYGBgDQoNCiQkDQpcbG9nKC1cbG9nKDEgLSBcaGF0e1xwaX0pKSA9IC0wLjczNTQzIC0gMC42Nzg3MiBcY2RvdCBcdGV4dHtDb250cmFjdE9uZVllYXJ9IC0gMS41MTkyNyBcY2RvdCBcdGV4dHtDb250cmFjdFR3b1llYXJ9ICsgMC4yMzAzNiBcY2RvdCBcdGV4dHtTZW5pb3JDaXRpemVuWWVzfSBcXA0KLSAwLjA3Mzk5IFxjZG90IFx0ZXh0e1BheW1lbnRNZXRob2RDcmVkaXRDYXJkfSArIDAuMjg5NjkgXGNkb3QgXHRleHR7UGF5bWVudE1ldGhvZEVsZWN0cm9uaWNDaGVja30gLSAwLjA1MzA5IFxjZG90IFx0ZXh0e1BheW1lbnRNZXRob2RNYWlsZWRDaGVja30gXFwNCisgMC43ODU5OSBcY2RvdCBcdGV4dHtJbnRlcm5ldFNlcnZpY2VGaWJlck9wdGljfSAtIDAuODA3NTMgXGNkb3QgXHRleHR7SW50ZXJuZXRTZXJ2aWNlTm99IC0gMC4wMjQ1NiBcY2RvdCBcdGV4dHt0ZW51cmV9DQokJA0KDQpUcm9uZyDEkcOzOg0KDQotICRcaGF0e1xwaX0kIGzDoCB4w6FjIHN14bqldCBraMOhY2ggaMOgbmcgKipy4budaSBi4buPIGThu4tjaCB24bulKiogKGBDaHVybl9iaW5hcnkgPSAxYCkuDQotIEjDoG0gbGnDqm4ga+G6v3QgbMOgIGNsb2dsb2c6ICRcbG9nKC1cbG9nKDEgLSBcaGF0e1xwaX0pKSQuDQotIEPDoWMgYmnhur9uIGzDoCBiaeG6v24gZ2nhuqMgc28gduG7m2kgbmjDs20gdGhhbSBjaGnhur91Og0KICAtIGBDb250cmFjdGA6IHRoYW0gY2hp4bq/dSBsw6AgYE1vbnRoLXRvLW1vbnRoYC4NCiAgLSBgU2VuaW9yQ2l0aXplbmA6IHRoYW0gY2hp4bq/dSBsw6AgYE5vYC4NCiAgLSBgUGF5bWVudE1ldGhvZGA6IHRoYW0gY2hp4bq/dSBsw6AgYEJhbmsgdHJhbnNmZXIgKGF1dG9tYXRpYylgLg0KICAtIGBJbnRlcm5ldFNlcnZpY2VgOiB0aGFtIGNoaeG6v3UgbMOgIGBEU0xgLg0KDQoqKkLhuqNuZzogS+G6v3QgcXXhuqMgxrDhu5tjIGzGsOG7o25nIHThu6sgbcO0IGjDrG5oIGjhu5NpIHF1eSBDbG9nbG9nIMSRYSBiaeG6v24qKg0KDQp8IEJp4bq/biAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IE5ow7NtIHNvIHPDoW5oICAgICAgICAgICAgICAgICAgICAgICAgICB8IEjhu4cgc+G7kSAozrIpIHwgcC12YWx1ZSAgfA0KfDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS18Oi0tLS0tLS0tLXwNCnwgSOG7o3AgxJHhu5NuZzogTeG7mXQgbsSDbSAgICAgICAgICAgICAgICAgIHwgU28gduG7m2kgSOG7o3AgxJHhu5NuZyB0aMOhbmcgbeG7mXQgICAgICAgICAgICAgfCAtMC42Nzg3ICAgfCAxLjQ1ZS0xMyB8DQp8IEjhu6NwIMSR4buTbmc6IEhhaSBuxINtICAgICAgICAgICAgICAgICAgfCBTbyB24bubaSBI4bujcCDEkeG7k25nIHRow6FuZyBt4buZdCAgICAgICAgICAgICB8IC0xLjUxOTMgICB8IDwgMmUtMTYgIHwNCnwgTMOgIG5nxrDhu51pIGNhbyB0deG7lWkgICAgICAgICAgICAgICAgICB8IFNvIHbhu5tpIGtow7RuZyBjYW8gdHXhu5VpICAgICAgICAgICAgICAgICB8IDAuMjMwNCAgICB8IDYuMTdlLTA1IHwNCnwgVGhhbmggdG/DoW46IFRo4bq7IHTDrW4gZOG7pW5nICh04buxIMSR4buZbmcpIHwgU28gduG7m2kgdGhhbmggdG/DoW4gbmfDom4gaMOgbmcgKHThu7EgxJHhu5luZykgfCAtMC4wNzQwICAgfCAwLjQxOCAgICB8DQp8IFRoYW5oIHRvw6FuOiBTw6ljIMSRaeG7h24gdOG7rSAgICAgICAgICAgIHwgU28gduG7m2kgdGhhbmggdG/DoW4gbmfDom4gaMOgbmcgKHThu7EgxJHhu5luZykgfCAwLjI4OTcgICAgfCA2LjQ3ZS0wNSB8DQp8IFRoYW5oIHRvw6FuOiBH4butaSBzw6ljICAgICAgICAgICAgICAgIHwgU28gduG7m2kgdGhhbmggdG/DoW4gbmfDom4gaMOgbmcgKHThu7EgxJHhu5luZykgfCAtMC4wNTMxICAgfCAwLjU1MyAgICB8DQp8IEludGVybmV0OiBDw6FwIHF1YW5nICAgICAgICAgICAgICAgIHwgU28gduG7m2kgRFNMICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC43ODYwICAgIHwgPCAyZS0xNiAgfA0KfCBJbnRlcm5ldDogS2jDtG5nIGPDsyAgICAgICAgICAgICAgICAgfCBTbyB24bubaSBEU0wgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAtMC44MDc1ICAgfCA1LjQ1ZS0xNCB8DQp8IFRow6JtIG5pw6puICh0aMOhbmcpICAgICAgICAgICAgICAgICAgfCBN4buXaSB0aMOhbmcgdMSDbmcgdGjDqm0gICAgICAgICAgICAgICAgICAgfCAtMC4wMjQ2ICAgfCA8IDJlLTE2ICB8DQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KLSBI4bujcCDEkeG7k25nIGTDoGkgaOG6oW4gKG3hu5l0IG7Eg20gdsOgIGhhaSBuxINtKSDEkeG7gXUgbMOgbSBnaeG6o20geMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBk4buLY2ggduG7pSwgxJHhurdjIGJp4buHdCBsw6AgaOG7o3AgxJHhu5NuZyBoYWkgbsSDbSBjw7MgdMOhYyDEkeG7mW5nIG3huqFuaCBoxqFuICho4buHIHPhu5Egw6JtIGzhu5tuLCBwLXZhbHVlIHLhuqV0IG5o4buPKS4NCg0KLSBLaMOhY2ggaMOgbmcgY2FvIHR14buVaSBjw7MgeHUgaMaw4bubbmcgcuG7nWkgYuG7jyBjYW8gaMahbiwgduG7m2kgaOG7hyBz4buRIGTGsMahbmcgdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNCi0gUGjGsMahbmcgdGjhu6ljIHRoYW5oIHRvw6FuIGLhurFuZyBTw6ljIMSRaeG7h24gdOG7rSBsw6AgeeG6v3UgdOG7kSBsw6BtIHTEg25nIGto4bqjIG7Eg25nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UsIHbhu5tpIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBt4bqhbmggbeG6vSAocC12YWx1ZSA8IDAuMDAxKS4NCg0KLSBT4butIGThu6VuZyBJbnRlcm5ldCBGaWJlciBPcHRpYyBsw6BtIHTEg25nIMSRw6FuZyBr4buDIGto4bqjIG7Eg25nIHLhu51pIGLhu48sIHRyb25nIGtoaSBraMO0bmcgc+G7rSBk4bulbmcgSW50ZXJuZXQgbOG6oWkgZ2nhuqNtIMSRw6FuZyBr4buDIHjDoWMgc3XhuqV0IG7DoHkuDQoNCi0gVGjhu51pIGdpYW4gc+G7rSBk4bulbmcgZOG7i2NoIHbhu6UgKHRlbnVyZSkgY8OgbmcgY2FvIHRow6wga2jDoWNoIGjDoG5nIGPDoG5nIMOtdCBjw7Mga2jhuqMgbsSDbmcgcuG7nWkgYuG7jy4NCg0KLS0tDQoNCiMgKipDSMavxqBORyA2OiDEkMOBTkggR0nDgSBNw5QgSMOMTkggVsOAIEThu7AgQsOBTyoqDQoNCiMjICoqNi4xLiBTbyBzw6FuaCBjw6FjIG3DtCBow6xuaCBo4buTaSBxdXkgYuG7mWkqKg0KDQpgYGB7ciBtb2RlbC1jb21wYXJpc29uLWZpbmFsfQ0KIyBU4bqhbyBi4bqjbmcgc28gc8OhbmgNCiMgKEdp4bqjIMSR4buLbmggY8OhYyBtw7QgaMOsbmggbHBtX211bHRpLCBsb2dpdF9tdWx0aSwgcHJvYml0X211bHRpLCBjbG9nbG9nX211bHRpIMSRw6MgxJHGsOG7o2MgY2jhuqF5KQ0KY29tcGFyaXNvbl90YWJsZSA8LSBkYXRhLmZyYW1lKA0KICAiTcO0IGjDrG5oIiA9IGMoIlR1eeG6v24gdMOtbmggKExQTSkiLCAiTG9naXQiLCAiUHJvYml0IiwgIkNsb2dsb2ciKSwNCiAgQUlDID0gYyhBSUMobHBtX211bHRpKSwgQUlDKGxvZ2l0X211bHRpKSwgQUlDKHByb2JpdF9tdWx0aSksIEFJQyhjbG9nbG9nX211bHRpKSksDQogIExvZ0xpa2VsaWhvb2QgPSBjKGxvZ0xpayhscG1fbXVsdGkpLCBsb2dMaWsobG9naXRfbXVsdGkpLCBsb2dMaWsocHJvYml0X211bHRpKSwgbG9nTGlrKGNsb2dsb2dfbXVsdGkpKSwNCiAgIk1jRmFkZGVuIFItc3F1YXJlZCIgPSBjKHBSMihscG1fbXVsdGkpWyJNY0ZhZGRlbiJdLCBwUjIobG9naXRfbXVsdGkpWyJNY0ZhZGRlbiJdLCBwUjIocHJvYml0X211bHRpKVsiTWNGYWRkZW4iXSwgcFIyKGNsb2dsb2dfbXVsdGkpWyJNY0ZhZGRlbiJdKSwNCiAgY2hlY2submFtZXMgPSBGQUxTRQ0KKQ0KDQojIFPhu60gZOG7pW5nIGthYmxlIMSR4buDIGhp4buDbiB0aOG7iyBi4bqjbmcgxJHhurlwIGjGoW4NCmthYmxlKA0KICBjb21wYXJpc29uX3RhYmxlLA0KICBjYXB0aW9uID0gIkLhuqNuZyBzbyBzw6FuaCBoaeG7h3UgcXXhuqMgY8OhYyBtw7QgaMOsbmggaOG7k2kgcXV5IGLhu5lpIiwNCiAgZGlnaXRzID0gNCwNCiAgY29sLm5hbWVzID0gYygiTcO0IGjDrG5oIiwgIkFJQyIsICJMb2dMaWtlbGlob29kIiwgIk1jRmFkZGVuIFItc3F1YXJlZCIpDQopDQpgYGANCg0KKipOaOG6rW4geMOpdDoqKg0KDQotIELhuqNuZyBzbyBzw6FuaCBjaG8gdGjhuqV5IG3DtCBow6xuaCBMb2dpdCB2xrDhu6N0IHRy4buZaSBoxqFuIGPhuqMgduG7gSB0acOqdSBjaMOtIEFJQyAoNjAxMi42MjgpIHbDoCBo4buHIHPhu5EgeMOhYyDEkeG7i25oIE1jRmFkZGVuICgwLjI2NDEpLCBjaG8gdGjhuqV5IGto4bqjIG7Eg25nIGdp4bqjaSB0aMOtY2ggYmnhur9uIHBo4bulIHRodeG7mWMgdOG7kXQgaMahbiBzbyB24bubaSBjw6FjIG3DtCBow6xuaCBraMOhYy4gTeG6t2MgZMO5IG3DtCBow6xuaCBDbG9nbG9nIHbDoCBQcm9iaXQgY8OzIGhp4buHdSBzdeG6pXQgZ+G6p24gdMawxqFuZyDEkcawxqFuZywgbmjGsG5nIHbhuqtuIGvDqW0gaMahbiBtw7QgaMOsbmggTG9naXQg4bufIGPhuqMgQUlDIHbDoCBt4bupYyBwaMO5IGjhu6NwIHThu5VuZyB0aOG7gy4NCg0KLSBOZ8aw4bujYyBs4bqhaSwgbcO0IGjDrG5oIFR1eeG6v24gdMOtbmggKExQTSkgY2hvIGvhur90IHF14bqjIGvDqW0gbmjhuqV0IHbhu5tpIEFJQyBjYW8gbmjhuqV0ICg2MzUwLjgyMykgdsOgIE1jRmFkZGVuIFLCsiB0aOG6pXAgbmjhuqV0ICgwLjI1MjQpLCBjaG8gdGjhuqV5IHBoxrDGoW5nIHBow6FwIG7DoHkga2jDtG5nIHBow7kgaOG7o3AgxJHhu4MgbcO0IGjDrG5oIGjDs2EgYmnhur9uIG5o4buLIHBow6JuIG5oxrAgQ2h1cm4uDQoNCi0gTmjGsCB24bqteSwgbcO0IGjDrG5oIExvZ2l0IGtow7RuZyBjaOG7iSDEkeG6o20gYuG6o28gdMOtbmggxJHGoW4gZ2nhuqNuIHRyb25nIGRp4buFbiBnaeG6o2kgKHF1YSBo4buHIHPhu5EgbG9nLW9kZHMpIG3DoCBjw7JuIGN1bmcgY+G6pXAgxJHhu5kgcGjDuSBo4bujcCB04buRdCBuaOG6pXQsIGzDoG0gY2hvIG7DsyB0cuG7nyB0aMOgbmggbOG7sWEgY2jhu41uIHThu5FpIMawdSB0cm9uZyBiw6BpIHRvw6FuIGThu7EgxJFvw6FuIGto4bqjIG7Eg25nIHLhu51pIGLhu48gZOG7i2NoIHbhu6UuDQoNCiMjICoqNi4yLiBE4buxIGLDoW8ga2jhuqMgbsSDbmcgcuG7nWkgYuG7jyoqDQoNCkNow7puZyB0YSBz4bq9IHPhu60gZOG7pW5nIG3DtCBow6xuaCBMb2dpdCBi4buZaSDEkeG7gyBk4buxIGLDoW8geMOhYyBzdeG6pXQgcuG7nWkgYuG7jyBjaG8gbeG7mXQga2jDoWNoIGjDoG5nIGdp4bqjIMSR4buLbmggY8OzIGPDoWMgxJHhurdjIMSRaeG7g20gcuG7p2kgcm8gY2FvIG5o4bqldCDEkcOjIMSRxrDhu6NjIHjDoWMgxJHhu4tuaC4NCg0KYGBge3IgcHJlZGljdGlvbi1maW5hbH0NCiMgVOG6oW8gaOG7kyBzxqEga2jDoWNoIGjDoG5nIGPDsyBuZ3V5IGPGoSBy4budaSBi4buPIGNhbw0Kcmlza3lfY3VzdG9tZXIgPC0gZGF0YS5mcmFtZSgNCiAgQ29udHJhY3QgPSBmYWN0b3IoIk1vbnRoLXRvLW1vbnRoIiwgbGV2ZWxzID0gbGV2ZWxzKGRmX2NsZWFuJENvbnRyYWN0KSksDQogIFNlbmlvckNpdGl6ZW4gPSBmYWN0b3IoIlllcyIsIGxldmVscyA9IGxldmVscyhkZl9jbGVhbiRTZW5pb3JDaXRpemVuKSksDQogIFBheW1lbnRNZXRob2QgPSBmYWN0b3IoIkVsZWN0cm9uaWMgY2hlY2siLCBsZXZlbHMgPSBsZXZlbHMoZGZfY2xlYW4kUGF5bWVudE1ldGhvZCkpLA0KICBJbnRlcm5ldFNlcnZpY2UgPSBmYWN0b3IoIkZpYmVyIG9wdGljIiwgbGV2ZWxzID0gbGV2ZWxzKGRmX2NsZWFuJEludGVybmV0U2VydmljZSkpLA0KICB0ZW51cmUgPSAxICAjIEtow6FjaCBow6BuZyBt4bubaSwgY2jhu4kgZ+G6r24gYsOzIDEgdGjDoW5nDQopDQoNCmNhdCgiROG7sSBiw6FvIGNobyBraMOhY2ggaMOgbmcgY8OzIGjhu5Mgc8ahOlxuIikNCnByaW50KHJpc2t5X2N1c3RvbWVyKQ0KDQojIEThu7EgYsOhbyB4w6FjIHN14bqldA0KcHJlZGljdGVkX3Byb2IgPC0gcHJlZGljdChsb2dpdF9tdWx0aSwgbmV3ZGF0YSA9IHJpc2t5X2N1c3RvbWVyLCB0eXBlID0gInJlc3BvbnNlIikNCg0KY2F0KCJcbi0+IFjDoWMgc3XhuqV0IHLhu51pIGLhu48gZOG7sSBiw6FvIGPhu6dhIGtow6FjaCBow6BuZyBuw6B5IGzDoDoiLCBzY2FsZXM6OnBlcmNlbnQocHJlZGljdGVkX3Byb2IsIGFjY3VyYWN5ID0gMC4xKSwgIlxuIikNCmBgYA0KDQoqKk5o4bqtbiB4w6l0IGThu7EgYsOhbzoqKg0KTcO0IGjDrG5oIExvZ2l0IGThu7EgYsOhbyBy4bqxbmcgbeG7mXQga2jDoWNoIGjDoG5nIGNhbyB0deG7lWksIG3hu5tpIHPhu60gZOG7pW5nIGThu4tjaCB24bulIMSRxrDhu6NjIDEgdGjDoW5nLCBjw7MgaOG7o3AgxJHhu5NuZyB0aGVvIHRow6FuZywgZMO5bmcgSW50ZXJuZXQgY8OhcCBxdWFuZyB2w6AgdGhhbmggdG/DoW4gYuG6sW5nIHPDqWMgxJFp4buHbiB04butIGPDsyAqKnjDoWMgc3XhuqV0IHLhu51pIGLhu48gbMOqbiB04bubaSA3My4xJSoqLiDEkMOieSBsw6AgbeG7mXQgY29uIHPhu5EgY+G7sWMga+G7syBjYW8sIGNobyB0aOG6pXkgc+G7sSBr4bq/dCBo4bujcCBj4bunYSBjw6FjIHnhur91IHThu5EgcuG7p2kgcm8gbsOgeSB04bqhbyByYSBt4buZdCAiY8O0bmcgdGjhu6ljIGhvw6BuIGjhuqNvIiBjaG8gdmnhu4djIGNodXJuLg0KDQpL4bq/dCBxdeG6oyBk4buxIGLDoW8gbsOgeSBraMO0bmcgY2jhu4kgbMOgIG3hu5l0IGNvbiBz4buRLCBtw6AgbMOgIG3hu5l0IGzhu51pIGPhuqNuaCBiw6FvIG3huqFuaCBt4bq9LiBOw7MgY2hvIHBow6lwIGRvYW5oIG5naGnhu4dwIHjDoWMgxJHhu4tuaCBjaMOtbmggeMOhYyBuaOG7r25nICLEkWnhu4NtIG7Ds25nIiB0cm9uZyB04buHcCBraMOhY2ggaMOgbmcgY+G7p2EgbcOsbmguIFRoYXkgdsOsIGPDoWMgY2hp4bq/biBk4buLY2ggZ2nhu68gY2jDom4gZMOgbiB0cuG6o2ksIGPDtG5nIHR5IGPDsyB0aOG7gyB04bqtcCB0cnVuZyBuZ3Xhu5NuIGzhu7FjIHbDoG8gxJHDum5nIG5ow7NtIMSR4buRaSB0xrDhu6NuZyBuw6B54oCUdsOtIGThu6UsIMSRxrBhIHJhIMawdSDEkcOjaSDEkeG6t2MgYmnhu4d0IMSR4buDIGjhu40gY2h1eeG7g24gxJHhu5VpIHNhbmcgaOG7o3AgxJHhu5NuZyBkw6BpIGjhuqFuIG5nYXkgdHJvbmcgbmjhu69uZyB0aMOhbmcgxJHhuqd1IHRpw6puLCBob+G6t2MgY3VuZyBj4bqlcCBo4buXIHRy4bujIGvhu7kgdGh14bqtdCBjaHV5w6puIHPDonUgY2hvIG5nxrDhu51pIGTDuW5nIGPDoXAgcXVhbmcgbeG7m2kuIMSQw6J5IGNow61uaCBsw6AgZ2nDoSB0cuG7iyB0aOG7sWMgdGnhu4VuIGPhu5F0IGzDtWkgbcOgIHBow6JuIHTDrWNoIGThu7EgYsOhbyBtYW5nIGzhuqFpOiBiaeG6v24gZOG7ryBsaeG7h3UgdGjDoG5oIGjDoG5oIMSR4buZbmcgY2hp4bq/biBsxrDhu6NjLg0KDQotLS0NCg0KIyAqKkNIxq/GoE5HIDc6IMavVSDEkEnhu4JNLCBI4bqgTiBDSOG6viBWw4AgS0nhur5OIE5HSOG7iioqDQoNCiMjICoqNy4xLiDGr3UgxJFp4buDbSBj4bunYSBOZ2hpw6puIGPhu6l1KioNCi0gKipUw61uaCBo4buHIHRo4buRbmc6KiogTmdoacOqbiBj4bupdSDEkcOjIMOhcCBk4bulbmcgbeG7mXQgcXV5IHRyw6xuaCBwaMOibiB0w61jaCBk4buvIGxp4buHdSBiw6BpIGLhuqNuLCB04burIHRo4buRbmcga8OqIG3DtCB04bqjLCBraeG7g20gxJHhu4tuaCBnaeG6oyB0aHV54bq/dCDEkeG6v24geMOieSBk4buxbmcgdsOgIHNvIHPDoW5oIG5oaeG7gXUgbcO0IGjDrG5oIGjhu5NpIHF1eS4NCi0gKipL4bq/dCBxdeG6oyByw7UgcsOgbmc6KiogQ8OhYyB54bq/dSB04buRIOG6o25oIGjGsOG7n25nIGNow61uaCDEkeG6v24gdOG7tyBs4buHIHLhu51pIGLhu48gxJHDoyDEkcaw4bujYyB4w6FjIMSR4buLbmggbeG7mXQgY8OhY2ggcsO1IHLDoG5nIHbDoCBuaOG6pXQgcXXDoW4gcXVhIG5oaeG7gXUgcGjGsMahbmcgcGjDoXAga2jDoWMgbmhhdS4NCi0gKipUw61uaCDhu6luZyBk4bulbmcgY2FvOioqIEvhur90IHF14bqjIG5naGnDqm4gY+G7qXUgY8OzIHRo4buDIMSRxrDhu6NjIMOhcCBk4bulbmcgdHLhu7FjIHRp4bq/cCB2w6BvIHZp4buHYyB4w6J5IGThu7FuZyBjw6FjIGNoaeG6v24gbMaw4bujYyBraW5oIGRvYW5oIG5o4bqxbSBnaeG6o20gdOG7tyBs4buHIHLhu51pIGLhu48sIG5oxrAgdOG6rXAgdHJ1bmcgdsOgbyBjw6FjIG5ow7NtIGtow6FjaCBow6BuZyBjw7MgaOG7o3AgxJHhu5NuZyB0aMOhbmcsIGTDuW5nIGPDoXAgcXVhbmcgaG/hurdjIHRoYW5oIHRvw6FuIGLhurFuZyBzw6ljIMSRaeG7h24gdOG7rS4NCg0KIyMgKio3LjIuIEjhuqFuIGNo4bq/IGPhu6dhIE5naGnDqm4gY+G7qXUqKg0KLSAqKkThu68gbGnhu4d1IGdp4bqjIMSR4buLbmg6KiogQuG7mSBk4buvIGxp4buHdSBsw6AgZ2nhuqMgxJHhu4tuaCB2w6AgY8OzIHRo4buDIGtow7RuZyBwaOG6o24gw6FuaCDEkeG6p3kgxJHhu6cgc+G7sSBwaOG7qWMgdOG6oXAgY+G7p2EgdGjhu4sgdHLGsOG7nW5nIHZp4buFbiB0aMO0bmcgdGjhu7FjIHThur8uDQotICoqQuG7jyBxdWEgY8OhYyBiaeG6v24gdGnhu4FtIG7Eg25nOioqIE5naGnDqm4gY+G7qXUgY2jhu4kgdOG6rXAgdHJ1bmcgdsOgbyA1IGJp4bq/biDEkcaw4bujYyBjaOG7jW4gdHLGsOG7m2MuIEPDoWMgeeG6v3UgdOG7kSBraMOhYyBuaMawIGNo4bqldCBsxrDhu6NuZyBk4buLY2ggduG7pSBraMOhY2ggaMOgbmcsIGPDoWMgY2jGsMahbmcgdHLDrG5oIGtodXnhur9uIG3Do2ksIGhv4bq3YyB0w6FjIMSR4buZbmcgY+G7p2EgxJHhu5FpIHRo4bunIGPhuqFuaCB0cmFuaCBjaMawYSDEkcaw4bujYyB4ZW0geMOpdC4NCi0gKipNw7QgaMOsbmggdMSpbmg6KiogQ8OhYyBtw7QgaMOsbmggaOG7k2kgcXV5IGzDoCBtw7QgaMOsbmggdMSpbmgsIGtow7RuZyBwaOG6o24gw6FuaCDEkcaw4bujYyBz4buxIHRoYXkgxJHhu5VpIHRyb25nIGjDoG5oIHZpIGPhu6dhIGtow6FjaCBow6BuZyB0aGVvIHRo4budaSBnaWFuLg0KDQojIyAqKjcuMy4gS2nhur9uIG5naOG7iyoqDQoNCkThu7FhIHRyw6puIGvhur90IHF14bqjIHBow6JuIHTDrWNoLCB0w6FjIGdp4bqjIMSR4buBIHh14bqldCBjw6FjIGtp4bq/biBuZ2jhu4sgc2F1Og0KDQoxLiAgKipU4buRaSDGsHUgaMOzYSBjaGnhur9uIGzGsOG7o2MgaOG7o3AgxJHhu5NuZzoqKiBUw61jaCBj4buxYyB0cmnhu4NuIGtoYWkgY8OhYyBjaMawxqFuZyB0csOsbmgga2h1eeG6v24gbcOjaSDEkeG7gyBraHV54bq/biBraMOtY2gga2jDoWNoIGjDoG5nIMSRYW5nIHPhu60gZOG7pW5nIGjhu6NwIMSR4buTbmcgYE1vbnRoLXRvLW1vbnRoYCBjaHV54buDbiDEkeG7lWkgc2FuZyBjw6FjIGjhu6NwIMSR4buTbmcgZMOgaSBo4bqhbiAoYE9uZSB5ZWFyYCBob+G6t2MgYFR3byB5ZWFyYCkuDQoNCjIuICAqKkPhuqNpIHRoaeG7h24gdHLhuqNpIG5naGnhu4dtIGThu4tjaCB24bulIEludGVybmV0OioqIFThu7cgbOG7hyBy4budaSBi4buPIGNhbyBj4bunYSBuaMOzbSBraMOhY2ggaMOgbmcgYEZpYmVyIG9wdGljYCBjaG8gdGjhuqV5IGPDsyB0aOG7gyB04buTbiB04bqhaSBjw6FjIHbhuqVuIMSR4buBIHbhu4EgY2jhuqV0IGzGsOG7o25nIGThu4tjaCB24bulLCBnacOhIGPhuqMsIGhv4bq3YyBo4buXIHRy4bujIGvhu7kgdGh14bqtdC4gQ+G6p24gY8OzIGPDoWMgY3Xhu5ljIGto4bqjbyBzw6F0IHPDonUgaMahbiDEkeG7gyB0w6xtIHJhIG5ndXnDqm4gbmjDom4gdsOgIGPhuqNpIHRoaeG7h24uDQoNCjMuICAqKlRow7pjIMSR4bqpeSBjw6FjIHBoxrDGoW5nIHRo4bupYyB0aGFuaCB0b8OhbiB04buxIMSR4buZbmc6KiogQ3VuZyBj4bqlcCBjw6FjIMawdSDEkcOjaSAodsOtIGThu6U6IGdp4bqjbSBnacOhLCB04bq3bmcgdGjDqm0gZOG7ryBsaeG7h3UpIGNobyBraMOhY2ggaMOgbmcga2hpIGjhu40gY2h1eeG7g24gdOG7qyB0aGFuaCB0b8OhbiB0aOG7pyBjw7RuZyAoYEVsZWN0cm9uaWMgY2hlY2tgKSBzYW5nIGPDoWMgaMOsbmggdGjhu6ljIHThu7EgxJHhu5luZyBuaMawIGBCYW5rIHRyYW5zZmVyYCBob+G6t2MgYENyZWRpdCBjYXJkYA0KLg0KNC4gICoqQ2jEg20gc8OzYyDEkeG6t2MgYmnhu4d0IGNobyBuZ8aw4budaSBjYW8gdHXhu5VpOioqIFjDonkgZOG7sW5nIGPDoWMgZ8OzaSBjxrDhu5tjIHbDoCBjaMawxqFuZyB0csOsbmggaOG7lyB0cuG7oyDEkcahbiBnaeG6o24sIGThu4Ugc+G7rSBk4bulbmcsIG5o4bqvbSByacOqbmcgxJHhur9uIHBow6JuIGtow7pjIGtow6FjaCBow6BuZyBgU2VuaW9yQ2l0aXplbmAgxJHhu4MgZ2nhuqNtIHThu7cgbOG7hyBy4budaSBi4buPIGPhu6dhIG5ow7NtIG7DoHkuDQoNCg0KIyAqKlTDgEkgTEnhu4ZVIFRIQU0gS0jhuqJPKioNCg0KMS4gQWdyZXN0aSwgQS4gKDIwMTMpLiAqQ2F0ZWdvcmljYWwgRGF0YSBBbmFseXNpcyogKDNyZCBlZC4pLiBXaWxleS4NCg0KMi4gQWhtYWQsIEEuIEIuLCBKYW50YW4sIEEuLCAmIFl1c29mZiwgUy4gQS4gKDIwMDcpLiAqUHJlZGljdGluZyBjdXN0b21lciBjaHVybjogQSBkYXRhIG1pbmluZyBhcHByb2FjaCouIFBhcGVyIHByZXNlbnRlZCBhdCB0aGUgSW50ZXJuYXRpb25hbCBDb25mZXJlbmNlIG9uIEludGVsbGlnZW50IFN5c3RlbXMgYW5kIFRlY2hub2xvZ2llcyAoSUNJU1QgMjAwNykuDQoNCjMuIEF1Z3VpZSwgQi4gKDIwMjMpLiAqZ3JpZEV4dHJhOiBNaXNjZWxsYW5lb3VzIEZ1bmN0aW9ucyBmb3IgIkdyaWQiIEdyYXBoaWNzKi4gUiBwYWNrYWdlIHZlcnNpb24gMi4zLiBbaHR0cHM6Ly9DUkFOLlItcHJvamVjdC5vcmcvcGFja2FnZT1ncmlkRXh0cmFdKGh0dHBzOi8vQ1JBTi5SLXByb2plY3Qub3JnL3BhY2thZ2U9Z3JpZEV4dHJhKQ0KDQo0LiBEZSBCbGVzZXIsIFIuLCBMdXF1ZSwgRi4gTS4sICYgTWFudGFzLCBDLiBHLiAoMjAyMSkuIEEgQ29tcGFyYXRpdmUgU3R1ZHkgb2YgTWFjaGluZSBMZWFybmluZyBBbGdvcml0aG1zIGZvciBDaHVybiBQcmVkaWN0aW9uLiAqQXBwbGllZCBTY2llbmNlcyosICoxMSooMTYpLCA3NjI0LiBbaHR0cHM6Ly9kb2kub3JnLzEwLjMzOTAvYXBwMTExNjc2MjRdKGh0dHBzOi8vZG9pLm9yZy8xMC4zMzkwL2FwcDExMTY3NjI0KQ0KDQo1LiBGaWVsZCwgQS4sIE1pbGVzLCBKLiwgJiBGaWVsZCwgWi4gKDIwMTIpLiAqRGlzY292ZXJpbmcgU3RhdGlzdGljcyBVc2luZyBSKi4gU2FnZSBQdWJsaWNhdGlvbnMuDQoNCjYuIEZveCwgSi4sICYgV2Vpc2JlcmcsIFMuICgyMDE5KS4gKkFuIFIgQ29tcGFuaW9uIHRvIEFwcGxpZWQgUmVncmVzc2lvbiogKDNyZCBlZC4pLiBTYWdlLg0KDQo3LiBIb3NtZXIsIEQuIFcuLCBMZW1lc2hvdywgUy4sICYgU3R1cmRpdmFudCwgUi4gWC4gKDIwMTMpLiAqQXBwbGllZCBMb2dpc3RpYyBSZWdyZXNzaW9uKiAoM3JkIGVkLikuIFdpbGV5Lg0KDQo5LiBJQk0gV2F0c29uIEFuYWx5dGljcy4gKG4uZC4pLiAqVGVsY28gQ3VzdG9tZXIgQ2h1cm4qLiBLYWdnbGUuIFRydXkgY+G6rXAgbmfDoHkgMTUvMDcvMjAyNSwgdOG7qyBbaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9ibGFzdGNoYXIvdGVsY28tY3VzdG9tZXItY2h1cm5dKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvYmxhc3RjaGFyL3RlbGNvLWN1c3RvbWVyLWNodXJuKS4NCg0KMTAuIEdpw6FvIHRyw6xuaCBQaMOibiBUw61jaCBE4buvIExp4buHdSDEkOG7i25oIFTDrW5oLCBUaFMuIFRy4bqnbiBN4bqhbmggVMaw4budbmcNCg==