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

1.1 ĐỌC DỮ LIỆU

  • Bộ dữ liệu “Student Social Media & Relationships” chứa các bản ghi ẩn danh về hành vi mạng xã hội của sinh viên và các kết quả cuộc sống liên quan. Bộ dữ liệu này trải dài trên nhiều quốc gia và trình độ học vấn, tập trung vào các chiều chính như cường độ sử dụng, sở thích nền tảng và động lực mối quan hệ. Mỗi hàng đại diện cho một phản hồi khảo sát của sinh viên, cung cấp ảnh chụp nhanh theo chiều ngang phù hợp cho phân tích thống kê và các ứng dụng học máy.

  • Đối tượng: Học sinh trong độ tuổi từ 16 đến 25 đang theo học chương trình trung học, đại học hoặc sau đại học.

  • Địa lý: Phạm vi nhiều quốc gia (ví dụ: Bangladesh, Ấn Độ, Hoa Kỳ, Vương quốc Anh, Canada, Úc, Đức, Brazil, Nhật Bản, Hàn Quốc).

  • Bộ dữ liệu bao gồm 506 quan sát và 13 biến gồm 6 biến định tính

1.1.1 Đọc file dữ liệu gốc

library(xlsx)
## Warning: package 'xlsx' was built under R version 4.3.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.3
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
library(gmodels)
## Warning: package 'gmodels' was built under R version 4.3.3
data <- read.xlsx(file =file.choose(), sheetIndex = 1, header = T)
  • Cấu trúc bộ dữ liệu
str(data)
## 'data.frame':    506 obs. of  13 variables:
##  $ Student_ID                  : num  1 2 3 4 5 6 7 8 9 10 ...
##  $ Age                         : num  19 22 20 18 21 19 23 20 18 21 ...
##  $ Gender                      : chr  "Female" "Male" "Female" "Male" ...
##  $ Academic_Level              : chr  "Undergraduate" "Graduate" "Undergraduate" "High School" ...
##  $ Country                     : chr  "USA" "USA" "USA" "Maldives" ...
##  $ Avg_Daily_Usage_Hours       : num  8.5 8.4 8.3 4.5 8.2 6.4 8.1 4.6 8 6.3 ...
##  $ Most_Used_Platform          : chr  "Instagram" "TikTok" "Instagram" "TikTok" ...
##  $ Affects_Academic_Performance: chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ Sleep_Hours_Per_Night       : num  3.8 3.9 4 4.1 4.1 4.2 4.2 4.3 4.3 4.4 ...
##  $ Mental_Health_Score         : num  5 5 5 6 5 6 5 6 5 6 ...
##  $ Relationship_Status         : chr  "In Relationship" "In Relationship" "In Relationship" "In Relationship" ...
##  $ Conflicts_Over_Social_Media : num  4 4 4 4 4 4 4 4 4 4 ...
##  $ Addicted_Score              : num  9 9 9 8 9 8 9 8 9 8 ...

1.2. TỔNG QUAN VỀ DỮ LIỆU

1.2.1 Danh sách các biến và mô tả

Tên biến Kiểu dữ liệu Giải thích
Student_ID Integer (Số nguyên) Mã số định danh duy nhất cho từng sinh viên tham gia khảo sát
Age Integer (Số nguyên) Tuổi của sinh viên (tính theo năm)
Gender Categorical Giới tính của sinh viên: Nam hoặc Nữ
Academic_Level Categorical Trình độ học vấn: Trung học, Đại học, Sau đại học
Country Categorical Quốc gia sinh sống của sinh viên
Avg_Daily_Usage_Hours Float (Số thực) Số giờ trung bình mỗi ngày sinh viên dành cho mạng xã hội
Most_Used_Platform Categorical Nền tảng mạng xã hội được sử dụng nhiều nhất: Instagram, Facebook, TikTok,…
Affects_Academic_Performance Boolean (Yes/No) Tự đánh giá xem mạng xã hội có ảnh hưởng đến việc học hay không
Sleep_Hours_Per_Night Float (Số thực) Số giờ ngủ trung bình mỗi đêm của sinh viên
Mental_Health_Score Integer (1-10) Mức độ sức khỏe tinh thần tự đánh giá (1 = kém, 10 = rất tốt)
Relationship_Status Categorical Tình trạng mối quan hệ: Độc thân, Đang yêu, Phức tạp
Conflicts_Over_Social_Media Integer (Số nguyên) Số lần mâu thuẫn trong mối quan hệ do mạng xã hội gây ra
Addicted_Score Integer (1-10) Điểm nghiện mạng xã hội (1 = không nghiện, 10 = rất nghiện)

1.2.2 THAY ĐỔI BIẾN ĐỊNH LƯỢNG THÀNH BIẾN ĐỊNH TÍNH

  • Để thuận tiện hơn cho việc phân tích dữ liệu, em sẽ thay đổi 2 biến định lượng thành định tính việc phân tích dễ hiểu hơn

Mục tiêu phân loại

Phân loại sức khỏe tinh thần theo 3 dạng (Mental_Health_Score) “Kém”, “Bình thường”, “Tốt”

  • 1–3 → Kém, 4–6 → Bình thường, 7–10 → Tốt

- Phân loại độ nghiện mạng xã hội theo 3 dạnh Addicted_Score “Không nghiện”, “Bình thường”, “Nghiện nặng”

  • 1–3 → Không nghiện, 4–6 → Bình thường, 7–10 → Nghiện nặng

- Phân loại số giờ ngủ để đánh giá theo 2 dạng (Sleep_Hours_Per_Night) “thiếu ngủ” và “ngủ đủ”

  • Nếu ngủ trên 6.5 trung bình mỗi đêm là ngủ đủ và ngược lại

Số lần mâu thuẫn (Conflicts_Over_Social_Media) Nhóm mới(Conflict_Level)

  • = 0 “Không”

  • 1 đến 4 “Khá nhiều”

  • 4 “Rất nhiều”

Số giờ dùng MXH mỗi ngày (Avg_Daily_Usage_Hours) Mức độ sử dụng (Usage_Level)

  • < 3 giờ “Thấp”
  • 3 đến dưới 5 giờ “Trung bình”
  • ≥ 5 giờ “Cao”
data$Mental_Health_Category <- cut(
  data$Mental_Health_Score,
  breaks = c(0, 3, 6, 10),
  labels = c("Kem", "Bình thường", "Tốt"),
  include.lowest = TRUE,
  right = TRUE
)

# Phân loại Addicted_Score
data$Addiction_Level <- cut(
  data$Addicted_Score,
  breaks = c(0, 3, 6, 10),
  labels = c("Không nghiện", "Bình thường", "Nghiện nặng"),
  include.lowest = TRUE,
  right = TRUE
)
# Phân loại giấc ngủ
data$Sleep_Quality <- ifelse(
  data$Sleep_Hours_Per_Night > 6.5,
  "Ngủ đủ",
  "Thiếu ngủ"
)

# Chuyển đổi số lần mâu thuẫn sang biến định tính
data$Conflict_Level <- cut(data$Conflicts_Over_Social_Media,
                           breaks = c(-1, 0, 4, Inf),
                           labels = c("Khong", "Khá nhiều", "Rất nhiều"),
                           right = TRUE)

data$Usage_Level <- cut(data$Avg_Daily_Usage_Hours,
                        breaks = c(-Inf, 3, 5, Inf),
                        labels = c("Thấp", "Trung bình", "Cao"),
                        right = FALSE)

# Kiểm tra lại kết quả
table(data$Mental_Health_Category)
## 
##         Kem Bình thường         Tốt 
##           0         385         121
table(data$Addiction_Level)
## 
## Không nghiện  Bình thường  Nghiện nặng 
##            3          130          373
table(data$Sleep_Quality)
## 
##    Ngủ đủ Thiếu ngủ 
##       230       276
table(data$Conflict_Level)
## 
##     Khong Khá nhiều Rất nhiều 
##         2       489        15
table(data$Usage_Level)
## 
##       Thấp Trung bình        Cao 
##         21        177        308

1.2.3 Kiểm tra dữ liệu

1.2.3.1 Kiểm tra số lượng NA trong cột định tính
# Kiểm tra số lượng NA trong mỗi cột định tính
na_counts <- sapply(data, function(x) sum(is.na(x)))
na_counts
##                   Student_ID                          Age 
##                            0                            0 
##                       Gender               Academic_Level 
##                            0                            0 
##                      Country        Avg_Daily_Usage_Hours 
##                            0                            0 
##           Most_Used_Platform Affects_Academic_Performance 
##                            0                            0 
##        Sleep_Hours_Per_Night          Mental_Health_Score 
##                            0                            0 
##          Relationship_Status  Conflicts_Over_Social_Media 
##                            0                            0 
##               Addicted_Score       Mental_Health_Category 
##                            0                            0 
##              Addiction_Level                Sleep_Quality 
##                            0                            0 
##               Conflict_Level                  Usage_Level 
##                            0                            0

Nhận xét

  • Kết quả thu được cho thấy rằng tất cả các cột định tính đều không có giá trị thiếu (NA) vì số lượng NA trong các cột đều hiển thị là 0
1.2.3.2 Chuyển đổi các biến định tính sang kiểu factor
# Chuyển các biến định tính sang factor
data$Age <- as.factor(data$Age)
data$Gender <- as.factor(data$Gender)
data$Academic_Level <- as.factor(data$Academic_Level)
data$Country <- as.factor(data$Country)
data$Most_Used_Platform <- as.factor(data$Most_Used_Platform)
data$Affects_Academic_Performance <- as.factor(data$Affects_Academic_Performance)
data$Sleep_Quality <- as.factor(data$Sleep_Quality)
data$Mental_Health_Category <- as.factor(data$Mental_Health_Category)
data$Addiction_Level <- as.factor(data$Addiction_Level)
data$Relationship_Status <- as.factor(data$Relationship_Status)
data$Conflict_Level <- as.factor(data$Conflict_Level)

Kiểm tra lại sau khi chuyển đổi

Giải thích:

  • sapply(data, class): Áp dụng hàm class() cho từng cột để kiểm tra kiểu dữ liệu. Kết quả trả về là một vector hiển thị tên cột và loại dữ liệu tương ứng.

  • Nếu kết quả là “factor” cho tất cả các cột → chuyển đổi thành công.

sapply(data, class)
##                   Student_ID                          Age 
##                    "numeric"                     "factor" 
##                       Gender               Academic_Level 
##                     "factor"                     "factor" 
##                      Country        Avg_Daily_Usage_Hours 
##                     "factor"                    "numeric" 
##           Most_Used_Platform Affects_Academic_Performance 
##                     "factor"                     "factor" 
##        Sleep_Hours_Per_Night          Mental_Health_Score 
##                    "numeric"                    "numeric" 
##          Relationship_Status  Conflicts_Over_Social_Media 
##                     "factor"                    "numeric" 
##               Addicted_Score       Mental_Health_Category 
##                    "numeric"                     "factor" 
##              Addiction_Level                Sleep_Quality 
##                     "factor"                     "factor" 
##               Conflict_Level                  Usage_Level 
##                     "factor"                     "factor"

Nhận xét - Kết quả thu được toàn bộ các biến định tính đã được chuyển đổi thành dạng factor.

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

install.packages("ggplot2", repos = "https://cloud.r-project.org")
## Warning: package 'ggplot2' is in use and will not be installed
library(ggplot2)

2.1. Gender - Giới tính

2.1.1 Thống kê tần số, tần suất và trực quan hóa

tab_gender <- table(data$Gender)
tab_gender
## 
## Female   Male 
##    253    253
table(data$Gender)/sum(nrow(data))
## 
## Female   Male 
##    0.5    0.5
2.1.1.2 Trực quan hoá
# Tạo dataframe từ bảng tần số
gender_freq <- as.data.frame(tab_gender)
colnames(gender_freq) <- c("Gender", "Frequency")

# Tính phần trăm
gender_freq$Percentage <- gender_freq$Frequency / sum(gender_freq$Frequency) * 100

# Tạo nhãn chỉ gồm phần trăm
gender_freq$Label <- paste0(round(gender_freq$Percentage, 1), "%")

# Vẽ biểu đồ tròn với nhãn chỉ phần trăm
ggplot(gender_freq, aes(x = "", y = Percentage, fill = Gender)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  theme_void() +
  geom_text(aes(label = Label), position = position_stack(vjust = 0.5), size = 5) +
  labs(title = "Phân bố giới tính của sinh viên") +
  scale_fill_brewer(palette = "Pastel1")

2.1.2 Nhận xét

  • Biểu đồ tròn thể hiện phân bố giới tính trong bộ dữ liệu sinh viên cho thấy tỷ lệ giữa nam và nữ là gần như tương đương:

  • Giới tính phân bố hoàn toàn đồng đều: 253 nam và 253 nữ (50% mỗi giới).

  • Điều này giúp đảm bảo tính công bằng khi so sánh theo giới.

2.2: Trình độ học vấn

2.2.1 Thống kê tần số, tần suất và trực quan hóa

level_freq <- table(data$Academic_Level)
level_percent <- prop.table(level_freq) * 100
data.frame(Academic_Level = names(level_freq),
           Frequency = as.numeric(level_freq),
           Percentage = round(as.numeric(level_percent), 1))
##   Academic_Level Frequency Percentage
## 1       Graduate       226       44.7
## 2    High School        27        5.3
## 3  Undergraduate       253       50.0
2.1.1.2 Trực quan hoá
# Load thư viện
library(ggplot2)
library(RColorBrewer)  # dùng cho palette màu

# Hàm tái sử dụng để xử lý và vẽ biểu đồ
plot_pie <- function(data, var, title) {
  tab <- table(data[[var]])
  df <- as.data.frame(tab)
  colnames(df) <- c("Category", "Frequency")
  df$Percentage <- df$Frequency / sum(df$Frequency) * 100
  df$Label <- paste0(round(df$Percentage, 1), "%")
  
  ggplot(df, aes(x = "", y = Percentage, fill = Category)) +
    geom_col(width = 1, color = "white") +
    coord_polar(theta = "y") +
    theme_void() +
    geom_text(aes(label = Label), position = position_stack(vjust = 0.5), size = 5) +
    labs(title = title, fill = var) +
    scale_fill_brewer(palette = "Pastel1")
}
plot_pie(data, "Academic_Level", "Phân bố trình độ học vấn của sinh viên")

2.2.2 Nhận xét

  • Trình độ học vấn của sinh viên chủ yếu tập trung ở bậc Đại học (Undergraduate – 50%), sau đại học (Graduate – 44.7%) và chỉ 5.3% thuộc bậc Trung học (High School). Điều này cho thấy phần lớn người tham gia khảo sát là sinh viên từ bậc đại học trở lên.

2.3. Tác động của mạng xã hội đến học tập

2.3.1 Thống kê tần số, tần suất và trực quan hóa

affect_freq <- table(data$Affects_Academic_Performance)
affect_percent <- prop.table(affect_freq) * 100
data.frame(Affects = names(affect_freq),
           Frequency = as.numeric(affect_freq),
           Percentage = round(as.numeric(affect_percent), 1))
##   Affects Frequency Percentage
## 1      No       112       22.1
## 2     Yes       394       77.9

2.3.1.1 trực quan hóa

plot_pie(data, "Affects_Academic_Performance", "Tác động của mạng xã hội đến học tập")

2.3.2 Nhận xét

  • Tổng cộng 394 sinh viên (77.87%) cho rằng mạng xã hội ảnh hưởng đến học tập, cho thấy đây là vấn đề đáng lo ngại.

2.4. Tình trạng mối quan hệ

2.4.1 Thống kê tần số, tần suất và trực quan hóa

rel_freq <- table(data$Relationship_Status)
rel_percent <- prop.table(rel_freq) * 100
data.frame(Relationship_Status = names(rel_freq),
           Frequency = as.numeric(rel_freq),
           Percentage = round(as.numeric(rel_percent), 1))
##   Relationship_Status Frequency Percentage
## 1         Complicated        32        6.3
## 2     In Relationship       212       41.9
## 3              Single       262       51.8
2.4.1.1 Trực quan hoá
plot_pie(data, "Relationship_Status", "Phân bố tình trạng mối quan hệ")

2.4.2 Nhận xét

  • Sinh viên độc thân chiếm 51.78%, đang yêu chiếm 41.9% và 6.32% có mối quan hệ phức tạp.

2.5. Phân loại sức khỏe tinh thần

2.5.1 Thống kê tần số, tần suất và trực quan hóa

mh_freq <- table(data$Mental_Health_Category)
mh_percent <- prop.table(mh_freq) * 100
data.frame(Mental_Health = names(mh_freq),
           Frequency = as.numeric(mh_freq),
           Percentage = round(as.numeric(mh_percent), 1))
##   Mental_Health Frequency Percentage
## 1           Kem         0        0.0
## 2   Bình thường       385       76.1
## 3           Tốt       121       23.9
2.5.1.1 Trực quan hoá
plot_pie(data, "Mental_Health_Category", "Phân loại sức khỏe tinh thần")

2.5.2 Nhận xét

  • Sức khỏe tinh thần chủ yếu ở mức bình thường (76.09%), 23.91% được đánh giá tốt. Không ai thuộc nhóm ‘kém’.

2.6. Mức độ nghiện mạng xã hội

2.6.1 Thống kê tần số, tần suất và trực quan hóa

addict_freq <- table(data$Addiction_Level)
addict_percent <- prop.table(addict_freq) * 100
data.frame(Addiction_Level = names(addict_freq),
           Frequency = as.numeric(addict_freq),
           Percentage = round(as.numeric(addict_percent), 1))
##   Addiction_Level Frequency Percentage
## 1    Không nghiện         3        0.6
## 2     Bình thường       130       25.7
## 3     Nghiện nặng       373       73.7
2.6.1.1 Trực quan hoá
plot_pie(data, "Addiction_Level", "Mức độ nghiện mạng xã hội")

2.6.2 Nhận xét

Tỷ lệ nghiện mạng xã hội nặng rất cao với 373 sinh viên (73.71%). Chỉ có 3 sinh viên (0.59%) không nghiện.

2.7. Tình trạng giấc ngủ

2.7.1 Thống kê tần số, tần suất và trực quan hóa

sleep_freq <- table(data$Sleep_Quality)
sleep_percent <- prop.table(sleep_freq) * 100
data.frame(Sleep_Quality = names(sleep_freq),
           Frequency = as.numeric(sleep_freq),
           Percentage = round(as.numeric(sleep_percent), 1))
##   Sleep_Quality Frequency Percentage
## 1        Ngủ đủ       230       45.5
## 2     Thiếu ngủ       276       54.5
2.7.1.1 Trực quan hoá
plot_pie(data, "Sleep_Quality", "Tình trạng giấc ngủ")

2.7.2 Nhận xét

Có 276 sinh viên (54.55%) thiếu ngủ và 230 người ngủ đủ giấc (45.45%). Tỷ lệ thiếu ngủ vượt quá nửa mẫu khảo sát.

2.8. Mức độ mâu thuẫn do mạng xã hội

2.8.1 Thống kê tần số, tần suất và trực quan hóa

conflict_freq <- table(data$Conflict_Level)
conflict_percent <- prop.table(conflict_freq) * 100
data.frame(Conflict_Level = names(conflict_freq),
           Frequency = as.numeric(conflict_freq),
           Percentage = round(as.numeric(conflict_percent), 1))
##   Conflict_Level Frequency Percentage
## 1          Khong         2        0.4
## 2      Khá nhiều       489       96.6
## 3      Rất nhiều        15        3.0
2.8.1.1 Trực quan hoá
plot_pie(data, "Conflict_Level", "Số lần mâu thuẫn do mạng xã hội")

2.8.2 Nhận xét

504/506 sinh viên (99.6%) gặp mâu thuẫn liên quan đến mạng xã hội. Đây là tỷ lệ cực kỳ cao và cảnh báo mối lo ngại xã hội.

2.9. Nền tảng mạng xã hội được sử dụng phổ biến

2.9.1 Thống kê tần số, tần suất và trực quan hóa

platform_freq <- table(data$Most_Used_Platform)
platform_percent <- prop.table(platform_freq) * 100
data.frame(Platform = names(platform_freq),
           Frequency = as.numeric(platform_freq),
           Percentage = round(as.numeric(platform_percent), 1))
##     Platform Frequency Percentage
## 1   Facebook        71       14.0
## 2  Instagram       163       32.2
## 3  KakaoTalk        11        2.2
## 4   LinkedIn        19        3.8
## 5   Snapchat        13        2.6
## 6     TikTok       126       24.9
## 7    Twitter        27        5.3
## 8  VKontakte         4        0.8
## 9     WeChat         8        1.6
## 10  WhatsApp        54       10.7
## 11   YouTube        10        2.0
2.9.1.1 Trực quan hoá
# Tạo bảng tần số
platform_freq <- as.data.frame(table(data$Most_Used_Platform))
colnames(platform_freq) <- c("Platform", "Frequency")

# Vẽ biểu đồ cột
ggplot(platform_freq, aes(x = reorder(Platform, -Frequency), y = Frequency, fill = Platform)) +
  geom_bar(stat = "identity") +
  labs(title = "Nền tảng mạng xã hội được sử dụng phổ biến",
       x = "Nền tảng", y = "Số lượng") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 30, hjust = 1)) +
  guides(fill = "none")

2.9.2 Nhận xét

Instagram được sử dụng nhiều nhất (163 sinh viên – 32.21%), sau đó là TikTok (126 sinh viên – 24.9%) và Facebook (71 sinh viên – 14.03%).

2.10. Mức độ sử dụng MXH

2.10.1 Thống kê tần số, tần suất và trực quan hóa

# Thống kê tần số
table_usage <- table(data$Usage_Level)
table_usage
## 
##       Thấp Trung bình        Cao 
##         21        177        308
# Thống kê tỷ lệ phần trăm
prop.table(table_usage) * 100
## 
##       Thấp Trung bình        Cao 
##   4.150198  34.980237  60.869565
plot_pie(data, "Usage_Level", "Phân bố trình Mức độ sử dụng mạng xã hội mỗi ngày")

2.10.2 Nhận xét

307 sinh viên (60.87%) sử dụng mạng xã hội từ 5 giờ trở lên mỗi ngày. Đây là mức sử dụng rất cao và có thể ảnh hưởng đến sức khỏe.

PHẦN 3: ƯỚC LƯỢNG & KIỂM ĐỊNH GIẢ THUYẾT TỶ LỆ

3.1 – Tỷ lệ sinh viên nam

# Bước 1: Đếm số lượng sinh viên nam
x <- sum(data$Gender == "Male")  # x là số sinh viên có giới tính "Male"

# Bước 2: Tính tổng số sinh viên trong dữ liệu
n <- nrow(data)  # n là kích thước mẫu (tổng sinh viên)

# Bước 3: Kiểm định giả thuyết H0: tỷ lệ nam = 0.5 (50%)
# prop.test thực hiện kiểm định tỷ lệ 1 mẫu và xuất ra khoảng tin cậy
prop.test(x = x, n = n, p = 0.5, conf.level = 0.95)
## 
##  1-sample proportions test without continuity correction
## 
## data:  x out of n, null probability 0.5
## X-squared = 0, df = 1, p-value = 1
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.4565989 0.5434011
## sample estimates:
##   p 
## 0.5

Giải thích toán học và thống kê:

  • Tính tỷ lệ mẫu: \(\hat{p} = \frac{x}{n} = \frac{253}{506} = 0.5\)
  • Sai số chuẩn (Standard Error - SE): \[SE = \sqrt{ \frac{p(1-p)}{n} } = \sqrt{ \frac{0.5(1-0.5)}{506} } = 0.022\] - Khoảng tin cậy 95%: \[CI = \hat{p} \pm z_{0.025} \cdot SE = 0.5 \pm 1.96 \cdot 0.022 = [0.4566, 0.5434]\] - p-value = 1 → Không bác bỏ H0 → Không có khác biệt so với tỷ lệ giả định.

Nhận xét:

Tỷ lệ sinh viên nam đúng bằng 50% như giả định ban đầu, không có khác biệt đáng kể.


3.2 – Tỷ lệ sinh viên Undergraduate

x <- sum(data$Academic_Level == "Undergraduate")
n <- nrow(data)
prop.test(x = x, n = n, p = 0.5, conf.level = 0.95)
## 
##  1-sample proportions test without continuity correction
## 
## data:  x out of n, null probability 0.5
## X-squared = 0, df = 1, p-value = 1
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.4565989 0.5434011
## sample estimates:
##   p 
## 0.5

Giải thích:

  • Giống 3.1, nhưng thay biến Gender thành Academic_Level
  • Tỷ lệ mẫu cũng là 0.5 → không khác biệt với giả định 50%

Nhận xét:

Tỷ lệ sinh viên bậc đại học và cao học là cân bằng trong mẫu nghiên cứu.


3.3 – Tỷ lệ thiếu ngủ

x <- sum(data$Sleep_Quality == "Thiếu ngủ")    # Đếm số sinh viên thiếu ngủ
n <- sum(!is.na(data$Sleep_Quality))            # Tổng số sinh viên có dữ liệu
prop.test(x = x, n = n, p = 0.4, conf.level = 0.95)  # So sánh với giả định 40%
## 
##  1-sample proportions test with continuity correction
## 
## data:  x out of n, null probability 0.4
## X-squared = 44.002, df = 1, p-value = 3.28e-11
## alternative hypothesis: true p is not equal to 0.4
## 95 percent confidence interval:
##  0.5009010 0.5893076
## sample estimates:
##         p 
## 0.5454545

Giải thích:

  • \(x = 276\), \(n = 506\) - \(p_0 = 0.4\) là tỷ lệ giả định để so sánh
  • Tính tỷ lệ mẫu: \[\hat{p} = \frac{276}{506} \approx 0.5455\] - Sai số chuẩn: \[SE = \sqrt{ \frac{0.4(1-0.4)}{506} } \approx 0.0218\] - Khoảng tin cậy: \[CI = 0.5455 \pm 1.96 \cdot 0.0218 = [0.501, 0.589]\]

Nhận xét:

Tỷ lệ sinh viên thiếu ngủ cao hơn đáng kể so với giả định 40%, có ý nghĩa thống kê (p < 0.05).


3.4 – Tỷ lệ nghiện mạng xã hội nặng

x <- sum(data$Addiction_Level == "Nghiện nặng")
n <- sum(!is.na(data$Addiction_Level))
prop.test(x = x, n = n, p = 0.5, alternative = "greater", conf.level = 0.95)
## 
##  1-sample proportions test with continuity correction
## 
## data:  x out of n, null probability 0.5
## X-squared = 112.89, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is greater than 0.5
## 95 percent confidence interval:
##  0.7027453 1.0000000
## sample estimates:
##         p 
## 0.7371542

Giải thích:

  • alternative = "greater": kiểm định 1 phía, xem có lớn hơn 50%
  • Tỷ lệ mẫu: \(\hat{p} = 373 / 506 \approx 0.737\)
  • Khoảng tin cậy: \[CI = [0.703, 0.770]\]

Nhận xét:

Tỷ lệ nghiện mạng xã hội nặng vượt xa mức giả định 50%, p-value < 0.001 rất có ý nghĩa.


3.5 – Mức độ mâu thuẫn cao

x <- sum(data$Conflict_Level %in% c("Khá nhiều", "Rất nhiều"))  # Đếm các mức cao
n <- sum(!is.na(data$Conflict_Level))
prop.test(x = x, n = n, p = 0.8, alternative = "greater")  # Giả định >= 80%
## 
##  1-sample proportions test with continuity correction
## 
## data:  x out of n, null probability 0.8
## X-squared = 120.33, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is greater than 0.8
## 95 percent confidence interval:
##  0.9866748 1.0000000
## sample estimates:
##         p 
## 0.9960474

Giải thích:

- \(\hat{p} = 504 / 506 \approx 0.996\) - Khoảng tin cậy: \[CI = [0.986, 0.999]\] - p rất nhỏ, cho thấy tỷ lệ thực tế vượt xa giả định 80%

Nhận xét:

Gần như tất cả sinh viên gặp xung đột mức cao, tỷ lệ này vượt rất xa mức dự đoán.


PHẦN 4: PHÂN TÍCH MỐI LIÊN HỆ GIỮA HAI BIẾN

4.1 THIẾU NGỦ VÀ NGHIỆN MẠNG XÃ HỘI

Tìm hiểu xem liệu Thiếu ngủ có liên hệ với mức độ nghiện mạng xã hội không? (Nói cách khác: Liệu những người thiếu ngủ có nghiện mạng xã hội nhiều hơn không?)

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

# Bảng chéo giữa chất lượng giấc ngủ và mức độ nghiện
table_sleep_addict <- table(data$Sleep_Quality, data$Addiction_Level)
table_sleep_addict
##            
##             Không nghiện Bình thường Nghiện nặng
##   Ngủ đủ               3         123         104
##   Thiếu ngủ            0           7         269
# Bảng tần suất chéo (contingency table) cho hai biến định tính:
# - Sleep_Quality: “Ngủ đủ” hoặc “Thiếu ngủ”
# - Addiction_Level: “Không nghiện”, “Bình thường”, “Nghiện nặng”
#
# table_sleep_addict[i, j] thể hiện số lượng sinh viên có
# Sleep_Quality = i và Addiction_Level = j

Ký hiệu và công thức

Gọi \(n_{ij}\) là số sinh viên ở hàng \(i\), cột \(j\), với:

  • \(i = 1\): nhóm “Ngủ đủ”, \(i = 2\): nhóm “Thiếu ngủ”
  • \(j = 1\): “Không nghiện”, \(j = 2\): “Bình thường”, \(j = 3\): “Nghiện nặng”
  • Tổng số quan sát: \(n = 506\)

Tần suất (tỷ lệ) tại ô \((i, j)\) được tính theo công thức:

\[ p_{ij} = \frac{n_{ij}}{n} \]


Một số tính toán cụ thể

Tỷ lệ sinh viên thuộc nhóm thiếu ngủnghiện mạng xã hội nặng:

\[ p_{23} = \frac{269}{506} \approx 0.5318 \]

Tổng số sinh viên thuộc nhóm thiếu ngủ:

\[ n_{2\cdot} = n_{21} + n_{22} + n_{23} = 0 + 7 + 269 = 276 \]

Tổng số sinh viên nghiện mạng xã hội nặng:

\[ n_{\cdot 3} = n_{13} + n_{23} = 104 + 269 = 373 \]

Tỷ lệ sinh viên nghiện nặng trong từng nhóm giấc ngủ:

  • Với nhóm thiếu ngủ:

\[ \frac{269}{276} \approx 0.9746 \quad (97.46\%) \]

  • Với nhóm ngủ đủ:

\[ \frac{104}{230} \approx 0.4522 \quad (45.22\%) \]


Nhận xét

Nhóm Thiếu ngủ có đến 269 sinh viên nghiện mạng xã hội nặng, chiếm 97.5% trong nhóm này.

Trong khi đó, nhóm Ngủ đủ chỉ có 104/230 = 45.2% là nghiện nặng.

Tỷ lệ “Bình thường” trong nhóm ngủ đủ (123/230 = 53.5%) cao hơn rất nhiều so với nhóm thiếu ngủ (7/276 = 2.5%).

Điều này cho thấy sinh viên thiếu ngủ có xu hướng nghiện mạng xã hội nặng hơn rõ rệt so với sinh viên ngủ đủ.

4.1.2 Trực quan hoá

library(ggplot2)

# Bảng tần số giữa Sleep_Quality và Addiction_Level
sleep_addict_tbl <- as.data.frame(table(data$Sleep_Quality, data$Addiction_Level))
colnames(sleep_addict_tbl) <- c("Sleep_Quality", "Addiction_Level", "Count")

ggplot(sleep_addict_tbl, aes(x = Sleep_Quality, y = Count, fill = Addiction_Level)) +
  geom_col(position = "dodge", width = 0.7) +
  labs(
    title = "Mối liên hệ giữa chất lượng giấc ngủ và mức độ nghiện mạng xã hội",
    x = "Chất lượng giấc ngủ",
    y = "Số lượng sinh viên",
    fill = "Mức độ nghiện"
  ) +
  scale_fill_brewer(palette = "Pastel2") +
  theme_minimal(base_size = 13)

Biểu đồ cho thấy sự khác biệt rất rõ rệt:Nhóm “Thiếu ngủ” gần như chỉ có sinh viên ở mức “Nghiện nặng”, trong khi nhóm “Ngủ đủ” phân bố đều hơn. Điều này củng cố nghi ngờ rằng giấc ngủ và mức độ nghiện mxh có mối liên hệ thống kê.

4.1.4 Kiểm định chi bình phương

# Bảng tần số 
table_sleep_addict <- table(data$Sleep_Quality, data$Addiction_Level)
table_sleep_addict
##            
##             Không nghiện Bình thường Nghiện nặng
##   Ngủ đủ               3         123         104
##   Thiếu ngủ            0           7         269
# Kiểm định Chi bình phương
chisq.test(table_sleep_addict)
## Warning in chisq.test(table_sleep_addict): Chi-squared approximation may be
## incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  table_sleep_addict
## X-squared = 176.78, df = 2, p-value < 2.2e-16

Mục tiêu kiểm định

Kiểm tra giả thuyết về sự độc lập giữa hai biến phân loại.

  • Giả thuyết không (H₀): Hai biến độc lập (không có mối liên hệ)
  • Giả thuyết đối (H₁): Hai biến không độc lập (có mối liên hệ)

Công thức toán học

Giá trị kỳ vọng (Expected frequency) tại ô hàng \(i\), cột \(j\) được tính như sau:

\[ E_{ij} = \frac{n_{i\cdot} \times n_{\cdot j}}{n} \]

Trong đó:

  • \(E_{ij}\): tần số kỳ vọng tại ô \((i, j)\)
  • \(n_{i\cdot}\): tổng hàng \(i\)
  • \(n_{\cdot j}\): tổng cột \(j\)
  • \(n\): tổng toàn bộ mẫu

Ví dụ, tại ô \((1, 3)\):

\[ E_{13} = \frac{230 \times 373}{506} \approx 169.61 \]


Thống kê kiểm định Chi bình phương:

\[ \chi^2 = \sum_{i=1}^{r} \sum_{j=1}^{c} \frac{(O_{ij} - E_{ij})^2}{E_{ij}} \]

Trong đó:

  • \(O_{ij}\): tần số quan sát tại ô \((i, j)\)
  • \(E_{ij}\): tần số kỳ vọng tại ô \((i, j)\)

Bậc tự do (degrees of freedom):

\[ df = (r - 1)(c - 1) \]

Ở đây:

  • \(r = 2\) (số hàng: “Ngủ đủ”, “Thiếu ngủ”)
  • \(c = 3\) (số cột: 3 mức độ nghiện)

Nên:

\[ df = (2 - 1)(3 - 1) = 2 \]Giá trị thống kê rất lớn (χ² = 176.78), với p-value < 2.2e-1, rất nhỏ. Bác bỏ H₀: Chất lượng giấc ngủ và mức độ nghiện mạng xã hội không độc lập. Tồn tại mối liên hệ có ý nghĩa thống kê giữa hai biến.

4.1.5 Relative Risk

install.packages("epitools", repos = "https://cloud.r-project.org")
## Installing package into 'C:/Users/Tuyet Nhi/AppData/Local/R/win-library/4.3'
## (as 'lib' is unspecified)
## package 'epitools' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Tuyet Nhi\AppData\Local\Temp\RtmpAZbLCq\downloaded_packages
library(epitools)
# Tạo bảng chéo
table_Sleep_Addict <- table(data$Sleep_Quality, data$Addiction_Level)
# RR
riskratio(table_Sleep_Addict)
## Warning in chisq.test(xx, correct = correction): Chi-squared approximation may
## be incorrect
## $data
##            
##             Không nghiện Bình thường Nghiện nặng Total
##   Ngủ đủ               3         123         104   230
##   Thiếu ngủ            0           7         269   276
##   Total                3         130         373   506
## 
## $measure
##            risk ratio with 95% C.I.
##             estimate     lower    upper
##   Ngủ đủ     1.00000        NA       NA
##   Thiếu ngủ  1.02439 0.9968335 1.052709
## 
## $p.value
##            two-sided
##             midp.exact fisher.exact   chi.square
##   Ngủ đủ            NA           NA           NA
##   Thiếu ngủ   0.849191 7.927858e-45 4.107291e-39
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét

Giá trị RR = 1.024 nhóm thiếu ngủ có nguy cơ nghiện mạng xã hội nặng cao hơn 2.4% so với nhóm ngủ đủ. Tuy nhiên, khoảng tin cậy chứa 1 không có ý nghĩa thống kê. Không đủ cơ sở để kết luận rằng thiếu ngủ tăng nguy cơ nghiện mxh nặng

4.1.6 Odds ratio

# Tạo biến Addiction_Binary: TRUE nếu là "Nghiện nặng", FALSE nếu không
data$Addict_Heavy <- data$Addiction_Level == "Nghiện nặng"

# Tạo bảng 2x2 giữa Chất lượng giấc ngủ và Nghiện nặng
table_sleep_addict_2x2 <- table(data$Sleep_Quality, data$Addict_Heavy)

# Hiệu chỉnh để tránh lỗi
table_corrected <- table_sleep_addict_2x2

# Tính Odds Ratio
library(epitools)
oddsratio(table_corrected)
## $data
##            
##             FALSE TRUE Total
##   Ngủ đủ      126  104   230
##   Thiếu ngủ     7  269   276
##   Total       133  373   506
## 
## $measure
##            odds ratio with 95% C.I.
##             estimate   lower    upper
##   Ngủ đủ     1.00000      NA       NA
##   Thiếu ngủ 45.26287 21.8881 111.1026
## 
## $p.value
##            two-sided
##             midp.exact fisher.exact   chi.square
##   Ngủ đủ            NA           NA           NA
##   Thiếu ngủ          0 4.746216e-45 2.493726e-40
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"

Nhận xét

  • Giá trị OR = 45.26 sinh viên thiếu ngủ có nguy cơ nghiện mạng xã hội nặng cao gấp 45 lần so với nhóm ngủ đủ. Khoảng tin cậy 95%: [21.88 ; 111.10] và p-value ≈ 0 cực kỳ có ý nghĩa thống kê. Mối liên hệ rất mạnh và đáng tin cậy giữa hai biến.
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA1Ig0KYXV0aG9yOiAiVsO1IEhvw6BuZyBUw61uaCINCmRhdGU6ICIyMDI1LTA2LTEyIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICB0aGVtZTogY29zbW8NCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6ICc0Jw0KICBwZGZfZG9jdW1lbnQ6DQogICAgbGF0ZXhfZW5naW5lOiB4ZWxhdGV4DQplZGl0b3Jfb3B0aW9uczogDQogIG1hcmtkb3duOiANCiAgICB3cmFwOiA3Mg0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMjICoqUEjhuqZOIDE6IFTDjE0gSEnhu4JVIFbDgCBDSFXhuqhOIELhu4ogROG7riBMSeG7hlUqKg0KDQojIyMgKioxLjEgxJDhu4xDIEThu64gTEnhu4ZVKioNCg0KLSAgIELhu5kgZOG7ryBsaeG7h3UgIlN0dWRlbnQgU29jaWFsIE1lZGlhICYgUmVsYXRpb25zaGlwcyIgY2jhu6lhIGPDoWMgYuG6o24gZ2hpDQogICAg4bqpbiBkYW5oIHbhu4EgaMOgbmggdmkgbeG6oW5nIHjDoyBo4buZaSBj4bunYSBzaW5oIHZpw6puIHbDoCBjw6FjIGvhur90IHF14bqjIGN14buZYw0KICAgIHPhu5FuZyBsacOqbiBxdWFuLiBC4buZIGThu68gbGnhu4d1IG7DoHkgdHLhuqNpIGTDoGkgdHLDqm4gbmhp4buBdSBxdeG7kWMgZ2lhIHbDoCB0csOsbmgNCiAgICDEkeG7mSBo4buNYyB24bqlbiwgdOG6rXAgdHJ1bmcgdsOgbyBjw6FjIGNoaeG7gXUgY2jDrW5oIG5oxrAgY8aw4budbmcgxJHhu5kgc+G7rSBk4bulbmcsIHPhu58NCiAgICB0aMOtY2ggbuG7gW4gdOG6o25nIHbDoCDEkeG7mW5nIGzhu7FjIG3hu5FpIHF1YW4gaOG7hy4gTeG7l2kgaMOgbmcgxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQNCiAgICBwaOG6o24gaOG7k2kga2jhuqNvIHPDoXQgY+G7p2Egc2luaCB2acOqbiwgY3VuZyBj4bqlcCDhuqNuaCBjaOG7pXAgbmhhbmggdGhlbyBjaGnhu4F1DQogICAgbmdhbmcgcGjDuSBo4bujcCBjaG8gcGjDom4gdMOtY2ggdGjhu5FuZyBrw6ogdsOgIGPDoWMg4bupbmcgZOG7pW5nIGjhu41jIG3DoXkuDQoNCi0gICDEkOG7kWkgdMaw4bujbmc6IEjhu41jIHNpbmggdHJvbmcgxJHhu5kgdHXhu5VpIHThu6sgMTYgxJHhur9uIDI1IMSRYW5nIHRoZW8gaOG7jWMgY2jGsMahbmcNCiAgICB0csOsbmggdHJ1bmcgaOG7jWMsIMSR4bqhaSBo4buNYyBob+G6t2Mgc2F1IMSR4bqhaSBo4buNYy4NCg0KLSAgIMSQ4buLYSBsw706IFBo4bqhbSB2aSBuaGnhu4F1IHF14buRYyBnaWEgKHbDrSBk4bulOiBCYW5nbGFkZXNoLCDhuqRuIMSQ4buZLCBIb2EgS+G7sywNCiAgICBWxrDGoW5nIHF14buRYyBBbmgsIENhbmFkYSwgw5pjLCDEkOG7qWMsIEJyYXppbCwgTmjhuq10IELhuqNuLCBIw6BuIFF14buRYykuDQoNCi0gICBC4buZIGThu68gbGnhu4d1IGJhbyBn4buTbSA1MDYgcXVhbiBzw6F0IHbDoCAxMyBiaeG6v24gZ+G7k20gNiBiaeG6v24gxJHhu4tuaCB0w61uaCAgDQoNCiMjIyMgKioxLjEuMSDEkOG7jWMgZmlsZSBk4buvIGxp4buHdSBn4buRYyoqDQoNCmBgYHtyfQ0KbGlicmFyeSh4bHN4KQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ21vZGVscykNCg0KZGF0YSA8LSByZWFkLnhsc3goZmlsZSA9ZmlsZS5jaG9vc2UoKSwgc2hlZXRJbmRleCA9IDEsIGhlYWRlciA9IFQpDQpgYGANCg0KLSAgICoqQ+G6pXUgdHLDumMgYuG7mSBk4buvIGxp4buHdSoqDQoNCmBgYHtyfQ0Kc3RyKGRhdGEpDQpgYGANCg0KIyMjICoqMS4yLiBU4buUTkcgUVVBTiBW4buAIEThu64gTEnhu4ZVKioNCg0KIyMjIyAqKjEuMi4xIERhbmggc8OhY2ggY8OhYyBiaeG6v24gdsOgIG3DtCB04bqjKioNCg0KfCBUw6puIGJp4bq/biAgICAgICAgICAgICAgICAgICAgICAgICB8IEtp4buDdSBk4buvIGxp4buHdSAgICAgICAgfCBHaeG6o2kgdGjDrWNoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8LS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18DQp8ICoqU3R1ZGVudF9JRCoqICAgICAgICAgICAgICAgICAgIHwgSW50ZWdlciAoU+G7kSBuZ3V5w6puKSB8IE3DoyBz4buRIMSR4buLbmggZGFuaCBkdXkgbmjhuqV0IGNobyB04burbmcgc2luaCB2acOqbiB0aGFtIGdpYSBraOG6o28gc8OhdCAgICAgICAgICAgICAgICAgfA0KfCAqKkFnZSoqICAgICAgICAgICAgICAgICAgICAgICAgICB8IEludGVnZXIgKFPhu5Egbmd1ecOqbikgfCBUdeG7lWkgY+G7p2Egc2luaCB2acOqbiAodMOtbmggdGhlbyBuxINtKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKkdlbmRlcioqICAgICAgICAgICAgICAgICAgICAgICB8IENhdGVnb3JpY2FsICAgICAgICAgfCBHaeG7m2kgdMOtbmggY+G7p2Egc2luaCB2acOqbjogKk5hbSogaG/hurdjICpO4buvKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKkFjYWRlbWljX0xldmVsKiogICAgICAgICAgICAgICB8IENhdGVnb3JpY2FsICAgICAgICAgfCBUcsOsbmggxJHhu5kgaOG7jWMgduG6pW46IFRydW5nIGjhu41jLCDEkOG6oWkgaOG7jWMsIFNhdSDEkeG6oWkgaOG7jWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgKipDb3VudHJ5KiogICAgICAgICAgICAgICAgICAgICAgfCBDYXRlZ29yaWNhbCAgICAgICAgIHwgUXXhu5FjIGdpYSBzaW5oIHPhu5FuZyBj4bunYSBzaW5oIHZpw6puICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgKipBdmdfRGFpbHlfVXNhZ2VfSG91cnMqKiAgICAgICAgfCBGbG9hdCAoU+G7kSB0aOG7sWMpICAgICB8IFPhu5EgZ2nhu50gdHJ1bmcgYsOsbmggbeG7l2kgbmfDoHkgc2luaCB2acOqbiBkw6BuaCBjaG8gbeG6oW5nIHjDoyBo4buZaSAgICAgICAgICAgICAgICAgICAgIHwNCnwgKipNb3N0X1VzZWRfUGxhdGZvcm0qKiAgICAgICAgICAgfCBDYXRlZ29yaWNhbCAgICAgICAgIHwgTuG7gW4gdOG6o25nIG3huqFuZyB4w6MgaOG7mWkgxJHGsOG7o2Mgc+G7rSBk4bulbmcgbmhp4buBdSBuaOG6pXQ6IEluc3RhZ3JhbSwgRmFjZWJvb2ssIFRpa1RvaywuLi4gfA0KfCAqKkFmZmVjdHNfQWNhZGVtaWNfUGVyZm9ybWFuY2UqKiB8IEJvb2xlYW4gKFllcy9ObykgICAgfCBU4buxIMSRw6FuaCBnacOhIHhlbSBt4bqhbmcgeMOjIGjhu5lpIGPDsyDhuqNuaCBoxrDhu59uZyDEkeG6v24gdmnhu4djIGjhu41jIGhheSBraMO0bmcgICAgICAgICAgICAgICB8DQp8ICoqU2xlZXBfSG91cnNfUGVyX05pZ2h0KiogICAgICAgIHwgRmxvYXQgKFPhu5EgdGjhu7FjKSAgICAgfCBT4buRIGdp4budIG5n4bunIHRydW5nIGLDrG5oIG3hu5dpIMSRw6ptIGPhu6dhIHNpbmggdmnDqm4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgKipNZW50YWxfSGVhbHRoX1Njb3JlKiogICAgICAgICAgfCBJbnRlZ2VyICgxLTEwKSAgICAgIHwgTeG7qWMgxJHhu5kgc+G7qWMga2jhu49lIHRpbmggdGjhuqduIHThu7EgxJHDoW5oIGdpw6EgKDEgPSBrw6ltLCAxMCA9IHLhuqV0IHThu5F0KSAgICAgICAgICAgICAgICAgfA0KfCAqKlJlbGF0aW9uc2hpcF9TdGF0dXMqKiAgICAgICAgICB8IENhdGVnb3JpY2FsICAgICAgICAgfCBUw6xuaCB0cuG6oW5nIG3hu5FpIHF1YW4gaOG7hzogxJDhu5ljIHRow6JuLCDEkGFuZyB5w6p1LCBQaOG7qWMgdOG6oXAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgKipDb25mbGljdHNfT3Zlcl9Tb2NpYWxfTWVkaWEqKiAgfCBJbnRlZ2VyIChT4buRIG5ndXnDqm4pIHwgU+G7kSBs4bqnbiBtw6J1IHRodeG6q24gdHJvbmcgbeG7kWkgcXVhbiBo4buHIGRvIG3huqFuZyB4w6MgaOG7mWkgZ8OieSByYSAgICAgICAgICAgICAgICAgICAgICB8DQp8ICoqQWRkaWN0ZWRfU2NvcmUqKiAgICAgICAgICAgICAgIHwgSW50ZWdlciAoMS0xMCkgICAgICB8IMSQaeG7g20gbmdoaeG7h24gbeG6oW5nIHjDoyBo4buZaSAoMSA9IGtow7RuZyBuZ2hp4buHbiwgMTAgPSBy4bqldCBuZ2hp4buHbikgICAgICAgICAgICAgICAgICAgfA0KDQojIyMjICoqMS4yLjIgVEhBWSDEkOG7lEkgQknhur5OIMSQ4buKTkggTMav4buiTkcgVEjDgE5IIEJJ4bq+TiDEkOG7ik5IIFTDjU5IKioNCg0KLSAgIMSQ4buDIHRodeG6rW4gdGnhu4duIGjGoW4gY2hvIHZp4buHYyBwaMOibiB0w61jaCBk4buvIGxp4buHdSwgZW0gc+G6vSB0aGF5IMSR4buVaSAyIGJp4bq/biDEkeG7i25oIGzGsOG7o25nIHRow6BuaCDEkeG7i25oIHTDrW5oIHZp4buHYyBwaMOibiB0w61jaCBk4buFIGhp4buDdSBoxqFuDQoNCioqTeG7pWMgdGnDqnUgcGjDom4gbG/huqFpKioNCg0KKipQaMOibiBsb+G6oWkgc+G7qWMga2jhu49lIHRpbmggdGjhuqduIHRoZW8gMyBk4bqhbmcgKE1lbnRhbF9IZWFsdGhfU2NvcmUpICJLw6ltIiwgIkLDrG5oIHRoxrDhu51uZyIsICJU4buRdCIqKg0KDQotICAgMeKAkzMg4oaSIEvDqW0sIDTigJM2IOKGkiBCw6xuaCB0aMaw4budbmcsIDfigJMxMCDihpIgVOG7kXQNCg0KKiotIFBow6JuIGxv4bqhaSDEkeG7mSBuZ2hp4buHbiBt4bqhbmcgeMOjIGjhu5lpIHRoZW8gMyBk4bqhbmggQWRkaWN0ZWRfU2NvcmUgIktow7RuZyBuZ2hp4buHbiIsICJCw6xuaCB0aMaw4budbmciLCAiTmdoaeG7h24gbuG6t25nIioqDQoNCi0gICAx4oCTMyDihpIgS2jDtG5nIG5naGnhu4duLCA04oCTNiDihpIgQsOsbmggdGjGsOG7nW5nLCA34oCTMTAg4oaSIE5naGnhu4duIG7hurduZw0KDQoqKi0gUGjDom4gbG/huqFpIHPhu5EgZ2nhu50gbmfhu6cgxJHhu4MgxJHDoW5oIGdpw6EgdGhlbyAyIGThuqFuZyAoU2xlZXBfSG91cnNfUGVyX05pZ2h0KSAidGhp4bq/dSBuZ+G7pyIgdsOgICJuZ+G7pyDEkeG7pyIqKg0KDQotICAgTuG6v3Ugbmfhu6cgdHLDqm4gNi41IHRydW5nIGLDrG5oIG3hu5dpIMSRw6ptIGzDoCBuZ+G7pyDEkeG7pyB2w6AgbmfGsOG7o2MgbOG6oWkNCg0KKipT4buRIGzhuqduIG3DonUgdGh14bqrbiAoQ29uZmxpY3RzX092ZXJfU29jaWFsX01lZGlhKSBOaMOzbSBt4bubaShDb25mbGljdF9MZXZlbCkqKg0KDQotICAgPSAwICJLaMO0bmciDQoNCi0gICAxIMSR4bq/biA0ICJLaMOhIG5oaeG7gXUiDQoNCi0gICA+IDQgIlLhuqV0IG5oaeG7gXUiDQoNCioqU+G7kSBnaeG7nSBkw7luZyBNWEggbeG7l2kgbmfDoHkgKEF2Z19EYWlseV9Vc2FnZV9Ib3VycykgTeG7qWMgxJHhu5kgc+G7rSBk4bulbmcgKFVzYWdlX0xldmVsKSoqDQoNCi0gPCAzIGdp4budICJUaOG6pXAiIA0KLSAzIMSR4bq/biBkxrDhu5tpIDUgZ2nhu50gIlRydW5nIGLDrG5oIg0KLSDiiaUgNSBnaeG7nSAiQ2FvIg0KDQpgYGB7cn0NCmRhdGEkTWVudGFsX0hlYWx0aF9DYXRlZ29yeSA8LSBjdXQoDQogIGRhdGEkTWVudGFsX0hlYWx0aF9TY29yZSwNCiAgYnJlYWtzID0gYygwLCAzLCA2LCAxMCksDQogIGxhYmVscyA9IGMoIktlbSIsICJCw6xuaCB0aMaw4budbmciLCAiVOG7kXQiKSwNCiAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFLA0KICByaWdodCA9IFRSVUUNCikNCg0KIyBQaMOibiBsb+G6oWkgQWRkaWN0ZWRfU2NvcmUNCmRhdGEkQWRkaWN0aW9uX0xldmVsIDwtIGN1dCgNCiAgZGF0YSRBZGRpY3RlZF9TY29yZSwNCiAgYnJlYWtzID0gYygwLCAzLCA2LCAxMCksDQogIGxhYmVscyA9IGMoIktow7RuZyBuZ2hp4buHbiIsICJCw6xuaCB0aMaw4budbmciLCAiTmdoaeG7h24gbuG6t25nIiksDQogIGluY2x1ZGUubG93ZXN0ID0gVFJVRSwNCiAgcmlnaHQgPSBUUlVFDQopDQojIFBow6JuIGxv4bqhaSBnaeG6pWMgbmfhu6cNCmRhdGEkU2xlZXBfUXVhbGl0eSA8LSBpZmVsc2UoDQogIGRhdGEkU2xlZXBfSG91cnNfUGVyX05pZ2h0ID4gNi41LA0KICAiTmfhu6cgxJHhu6ciLA0KICAiVGhp4bq/dSBuZ+G7pyINCikNCg0KIyBDaHV54buDbiDEkeG7lWkgc+G7kSBs4bqnbiBtw6J1IHRodeG6q24gc2FuZyBiaeG6v24gxJHhu4tuaCB0w61uaA0KZGF0YSRDb25mbGljdF9MZXZlbCA8LSBjdXQoZGF0YSRDb25mbGljdHNfT3Zlcl9Tb2NpYWxfTWVkaWEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKC0xLCAwLCA0LCBJbmYpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiS2hvbmciLCAiS2jDoSBuaGnhu4F1IiwgIlLhuqV0IG5oaeG7gXUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gVFJVRSkNCg0KZGF0YSRVc2FnZV9MZXZlbCA8LSBjdXQoZGF0YSRBdmdfRGFpbHlfVXNhZ2VfSG91cnMsDQogICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKC1JbmYsIDMsIDUsIEluZiksDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJUaOG6pXAiLCAiVHJ1bmcgYsOsbmgiLCAiQ2FvIiksDQogICAgICAgICAgICAgICAgICAgICAgICByaWdodCA9IEZBTFNFKQ0KDQojIEtp4buDbSB0cmEgbOG6oWkga+G6v3QgcXXhuqMNCnRhYmxlKGRhdGEkTWVudGFsX0hlYWx0aF9DYXRlZ29yeSkNCnRhYmxlKGRhdGEkQWRkaWN0aW9uX0xldmVsKQ0KdGFibGUoZGF0YSRTbGVlcF9RdWFsaXR5KQ0KdGFibGUoZGF0YSRDb25mbGljdF9MZXZlbCkNCnRhYmxlKGRhdGEkVXNhZ2VfTGV2ZWwpDQpgYGANCg0KIyMjIyAqKjEuMi4zIEtp4buDbSB0cmEgZOG7ryBsaeG7h3UqKg0KDQojIyMjIyAqKjEuMi4zLjEgS2nhu4NtIHRyYSBz4buRIGzGsOG7o25nIE5BIHRyb25nIGPhu5l0IMSR4buLbmggdMOtbmgqKg0KDQpgYGB7cn0NCiMgS2nhu4NtIHRyYSBz4buRIGzGsOG7o25nIE5BIHRyb25nIG3hu5dpIGPhu5l0IMSR4buLbmggdMOtbmgNCm5hX2NvdW50cyA8LSBzYXBwbHkoZGF0YSwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkNCm5hX2NvdW50cw0KYGBgDQoNCioqTmjhuq1uIHjDqXQqKg0KDQotIEvhur90IHF14bqjIHRodSDEkcaw4bujYyBjaG8gdGjhuqV5IHLhurFuZyB04bqldCBj4bqjIGPDoWMgY+G7mXQgxJHhu4tuaCB0w61uaA0KxJHhu4F1IGtow7RuZyBjw7MgZ2nDoSB0cuG7iyB0aGnhur91IChOQSkgdsOsIHPhu5EgbMaw4bujbmcgTkEgdHJvbmcgY8OhYyBj4buZdCDEkeG7gXUgaGnhu4NuDQp0aOG7iyBsw6AgMA0KDQojIyMjIyAqKjEuMi4zLjIgQ2h1eeG7g24gxJHhu5VpIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmggc2FuZyBraeG7g3UgZmFjdG9yKioNCg0KYGBge3J9DQojIENodXnhu4NuIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmggc2FuZyBmYWN0b3INCmRhdGEkQWdlIDwtIGFzLmZhY3RvcihkYXRhJEFnZSkNCmRhdGEkR2VuZGVyIDwtIGFzLmZhY3RvcihkYXRhJEdlbmRlcikNCmRhdGEkQWNhZGVtaWNfTGV2ZWwgPC0gYXMuZmFjdG9yKGRhdGEkQWNhZGVtaWNfTGV2ZWwpDQpkYXRhJENvdW50cnkgPC0gYXMuZmFjdG9yKGRhdGEkQ291bnRyeSkNCmRhdGEkTW9zdF9Vc2VkX1BsYXRmb3JtIDwtIGFzLmZhY3RvcihkYXRhJE1vc3RfVXNlZF9QbGF0Zm9ybSkNCmRhdGEkQWZmZWN0c19BY2FkZW1pY19QZXJmb3JtYW5jZSA8LSBhcy5mYWN0b3IoZGF0YSRBZmZlY3RzX0FjYWRlbWljX1BlcmZvcm1hbmNlKQ0KZGF0YSRTbGVlcF9RdWFsaXR5IDwtIGFzLmZhY3RvcihkYXRhJFNsZWVwX1F1YWxpdHkpDQpkYXRhJE1lbnRhbF9IZWFsdGhfQ2F0ZWdvcnkgPC0gYXMuZmFjdG9yKGRhdGEkTWVudGFsX0hlYWx0aF9DYXRlZ29yeSkNCmRhdGEkQWRkaWN0aW9uX0xldmVsIDwtIGFzLmZhY3RvcihkYXRhJEFkZGljdGlvbl9MZXZlbCkNCmRhdGEkUmVsYXRpb25zaGlwX1N0YXR1cyA8LSBhcy5mYWN0b3IoZGF0YSRSZWxhdGlvbnNoaXBfU3RhdHVzKQ0KZGF0YSRDb25mbGljdF9MZXZlbCA8LSBhcy5mYWN0b3IoZGF0YSRDb25mbGljdF9MZXZlbCkNCmBgYA0KDQoqKktp4buDbSB0cmEgbOG6oWkgc2F1IGtoaSBjaHV54buDbiDEkeG7lWkqKg0KDQpHaeG6o2kgdGjDrWNoOg0KDQotIHNhcHBseShkYXRhLCBjbGFzcyk6IMOBcCBk4bulbmcgaMOgbSBjbGFzcygpIGNobyB04burbmcgY+G7mXQgxJHhu4Mga2nhu4NtIHRyYQ0KICAgIGtp4buDdSBk4buvIGxp4buHdS4gS+G6v3QgcXXhuqMgdHLhuqMgduG7gSBsw6AgbeG7mXQgdmVjdG9yIGhp4buDbiB0aOG7iyB0w6puIGPhu5l0IHbDoCBsb+G6oWkNCiAgICBk4buvIGxp4buHdSB0xrDGoW5nIOG7qW5nLg0KDQotIE7hur91IGvhur90IHF14bqjIGzDoCAiZmFjdG9yIiBjaG8gdOG6pXQgY+G6oyBjw6FjIGPhu5l0IOKGkiBjaHV54buDbiDEkeG7lWkgdGjDoG5oIGPDtG5nLg0KDQpgYGB7cn0NCnNhcHBseShkYXRhLCBjbGFzcykNCmBgYA0KDQoqKk5o4bqtbiB4w6l0KiogDQotIEvhur90IHF14bqjIHRodSDEkcaw4bujYyB0b8OgbiBi4buZIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmggxJHDoyDEkcaw4bujYw0KY2h1eeG7g24gxJHhu5VpIHRow6BuaCBk4bqhbmcgZmFjdG9yLg0KDQojIyAqKlBI4bqmTiAyOiBQSMOCTiBUw41DSCBNw5QgVOG6oiBCSeG6vk4gxJDhu4pOSCBUw41OSCoqDQoNCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIsIHJlcG9zID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIpDQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KIyMjICoqMi4xLiBHZW5kZXIgLSBHaeG7m2kgdMOtbmgqKg0KDQojIyMjICoqMi4xLjEgVGjhu5FuZyBrw6ogdOG6p24gc+G7kSwgdOG6p24gc3XhuqV0IHbDoCB0cuG7sWMgcXVhbiBow7NhKioNCg0KYGBge3J9DQp0YWJfZ2VuZGVyIDwtIHRhYmxlKGRhdGEkR2VuZGVyKQ0KdGFiX2dlbmRlcg0KdGFibGUoZGF0YSRHZW5kZXIpL3N1bShucm93KGRhdGEpKQ0KYGBgDQoNCiMjIyMjICoqMi4xLjEuMiBUcuG7sWMgcXVhbiBob8OhKioNCg0KYGBge3J9DQojIFThuqFvIGRhdGFmcmFtZSB04burIGLhuqNuZyB04bqnbiBz4buRDQpnZW5kZXJfZnJlcSA8LSBhcy5kYXRhLmZyYW1lKHRhYl9nZW5kZXIpDQpjb2xuYW1lcyhnZW5kZXJfZnJlcSkgPC0gYygiR2VuZGVyIiwgIkZyZXF1ZW5jeSIpDQoNCiMgVMOtbmggcGjhuqduIHRyxINtDQpnZW5kZXJfZnJlcSRQZXJjZW50YWdlIDwtIGdlbmRlcl9mcmVxJEZyZXF1ZW5jeSAvIHN1bShnZW5kZXJfZnJlcSRGcmVxdWVuY3kpICogMTAwDQoNCiMgVOG6oW8gbmjDo24gY2jhu4kgZ+G7k20gcGjhuqduIHRyxINtDQpnZW5kZXJfZnJlcSRMYWJlbCA8LSBwYXN0ZTAocm91bmQoZ2VuZGVyX2ZyZXEkUGVyY2VudGFnZSwgMSksICIlIikNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyB0csOybiB24bubaSBuaMOjbiBjaOG7iSBwaOG6p24gdHLEg20NCmdncGxvdChnZW5kZXJfZnJlcSwgYWVzKHggPSAiIiwgeSA9IFBlcmNlbnRhZ2UsIGZpbGwgPSBHZW5kZXIpKSArDQogIGdlb21fY29sKHdpZHRoID0gMSwgY29sb3IgPSAid2hpdGUiKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIHRoZW1lX3ZvaWQoKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBMYWJlbCksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCBzaXplID0gNSkgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgZ2nhu5tpIHTDrW5oIGPhu6dhIHNpbmggdmnDqm4iKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiUGFzdGVsMSIpDQoNCmBgYA0KDQojIyMjICoqMi4xLjIgTmjhuq1uIHjDqXQqKg0KDQotIEJp4buDdSDEkeG7kyB0csOybiB0aOG7gyBoaeG7h24gcGjDom4gYuG7kSBnaeG7m2kgdMOtbmggdHJvbmcgYuG7mSBk4buvIGxp4buHdSBzaW5oIHZpw6puIGNobyB0aOG6pXkgdOG7tyBs4buHIGdp4buvYSBuYW0gdsOgIG7hu68gbMOgIGfhuqduIG5oxrAgdMawxqFuZyDEkcawxqFuZzoNCg0KLSBHaeG7m2kgdMOtbmggcGjDom4gYuG7kSBob8OgbiB0b8OgbiDEkeG7k25nIMSR4buBdTogMjUzIG5hbSB2w6AgMjUzIG7hu68gKDUwJSBt4buXaSBnaeG7m2kpLg0KLSDEkGnhu4F1IG7DoHkgZ2nDunAgxJHhuqNtIGLhuqNvIHTDrW5oIGPDtG5nIGLhurFuZyBraGkgc28gc8OhbmggdGhlbyBnaeG7m2kuDQoNCiMjIyAqKjIuMjogVHLDrG5oIMSR4buZIGjhu41jIHbhuqVuKioNCg0KIyMjIyAqKjIuMi4xIFRo4buRbmcga8OqIHThuqduIHPhu5EsIHThuqduIHN14bqldCB2w6AgdHLhu7FjIHF1YW4gaMOzYSoqDQoNCmBgYHtyfQ0KbGV2ZWxfZnJlcSA8LSB0YWJsZShkYXRhJEFjYWRlbWljX0xldmVsKQ0KbGV2ZWxfcGVyY2VudCA8LSBwcm9wLnRhYmxlKGxldmVsX2ZyZXEpICogMTAwDQpkYXRhLmZyYW1lKEFjYWRlbWljX0xldmVsID0gbmFtZXMobGV2ZWxfZnJlcSksDQogICAgICAgICAgIEZyZXF1ZW5jeSA9IGFzLm51bWVyaWMobGV2ZWxfZnJlcSksDQogICAgICAgICAgIFBlcmNlbnRhZ2UgPSByb3VuZChhcy5udW1lcmljKGxldmVsX3BlcmNlbnQpLCAxKSkNCmBgYA0KDQojIyMjIyAqKjIuMS4xLjIgVHLhu7FjIHF1YW4gaG/DoSoqDQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikgICMgZMO5bmcgY2hvIHBhbGV0dGUgbcOgdQ0KDQojIEjDoG0gdMOhaSBz4butIGThu6VuZyDEkeG7gyB44butIGzDvSB2w6AgduG6vSBiaeG7g3UgxJHhu5MNCnBsb3RfcGllIDwtIGZ1bmN0aW9uKGRhdGEsIHZhciwgdGl0bGUpIHsNCiAgdGFiIDwtIHRhYmxlKGRhdGFbW3Zhcl1dKQ0KICBkZiA8LSBhcy5kYXRhLmZyYW1lKHRhYikNCiAgY29sbmFtZXMoZGYpIDwtIGMoIkNhdGVnb3J5IiwgIkZyZXF1ZW5jeSIpDQogIGRmJFBlcmNlbnRhZ2UgPC0gZGYkRnJlcXVlbmN5IC8gc3VtKGRmJEZyZXF1ZW5jeSkgKiAxMDANCiAgZGYkTGFiZWwgPC0gcGFzdGUwKHJvdW5kKGRmJFBlcmNlbnRhZ2UsIDEpLCAiJSIpDQogIA0KICBnZ3Bsb3QoZGYsIGFlcyh4ID0gIiIsIHkgPSBQZXJjZW50YWdlLCBmaWxsID0gQ2F0ZWdvcnkpKSArDQogICAgZ2VvbV9jb2wod2lkdGggPSAxLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKw0KICAgIHRoZW1lX3ZvaWQoKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IExhYmVsKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA1KSArDQogICAgbGFicyh0aXRsZSA9IHRpdGxlLCBmaWxsID0gdmFyKSArDQogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQYXN0ZWwxIikNCn0NCnBsb3RfcGllKGRhdGEsICJBY2FkZW1pY19MZXZlbCIsICJQaMOibiBi4buRIHRyw6xuaCDEkeG7mSBo4buNYyB24bqlbiBj4bunYSBzaW5oIHZpw6puIikNCmBgYA0KDQojIyMjICoqMi4yLjIgTmjhuq1uIHjDqXQqKg0KDQotIFRyw6xuaCDEkeG7mSBo4buNYyB24bqlbiBj4bunYSBzaW5oIHZpw6puIGNo4bunIHnhur91IHThuq1wIHRydW5nIOG7nyBi4bqtYyDEkOG6oWkgaOG7jWMgKFVuZGVyZ3JhZHVhdGUg4oCTIDUwJSksIHNhdSDEkeG6oWkgaOG7jWMgKEdyYWR1YXRlIOKAkyA0NC43JSkgdsOgIGNo4buJIDUuMyUgdGh14buZYyBi4bqtYyBUcnVuZyBo4buNYyAoSGlnaCBTY2hvb2wpLiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBwaOG6p24gbOG7m24gbmfGsOG7nWkgdGhhbSBnaWEga2jhuqNvIHPDoXQgbMOgIHNpbmggdmnDqm4gdOG7qyBi4bqtYyDEkeG6oWkgaOG7jWMgdHLhu58gbMOqbi4NCg0KIyMjICoqMi4zLiBUw6FjIMSR4buZbmcgY+G7p2EgbeG6oW5nIHjDoyBo4buZaSDEkeG6v24gaOG7jWMgdOG6rXAqKg0KDQojIyMjICoqMi4zLjEgVGjhu5FuZyBrw6ogdOG6p24gc+G7kSwgdOG6p24gc3XhuqV0IHbDoCB0cuG7sWMgcXVhbiBow7NhKioNCg0KYGBge3J9DQphZmZlY3RfZnJlcSA8LSB0YWJsZShkYXRhJEFmZmVjdHNfQWNhZGVtaWNfUGVyZm9ybWFuY2UpDQphZmZlY3RfcGVyY2VudCA8LSBwcm9wLnRhYmxlKGFmZmVjdF9mcmVxKSAqIDEwMA0KZGF0YS5mcmFtZShBZmZlY3RzID0gbmFtZXMoYWZmZWN0X2ZyZXEpLA0KICAgICAgICAgICBGcmVxdWVuY3kgPSBhcy5udW1lcmljKGFmZmVjdF9mcmVxKSwNCiAgICAgICAgICAgUGVyY2VudGFnZSA9IHJvdW5kKGFzLm51bWVyaWMoYWZmZWN0X3BlcmNlbnQpLCAxKSkNCmBgYA0KDQojIyMjICoqMi4zLjEuMSB0cuG7sWMgcXVhbiBow7NhKioNCg0KYGBge3J9DQpwbG90X3BpZShkYXRhLCAiQWZmZWN0c19BY2FkZW1pY19QZXJmb3JtYW5jZSIsICJUw6FjIMSR4buZbmcgY+G7p2EgbeG6oW5nIHjDoyBo4buZaSDEkeG6v24gaOG7jWMgdOG6rXAiKQ0KYGBgDQoNCiMjIyMgKioyLjMuMiBOaOG6rW4geMOpdCoqDQoNCi0gVOG7lW5nIGPhu5luZyAzOTQgc2luaCB2acOqbiAoNzcuODclKSBjaG8gcuG6sW5nIG3huqFuZyB4w6MgaOG7mWkg4bqjbmggaMaw4bufbmcgxJHhur9uIGjhu41jIHThuq1wLCBjaG8gdGjhuqV5IMSRw6J5IGzDoCB24bqlbiDEkeG7gSDEkcOhbmcgbG8gbmfhuqFpLg0KDQojIyMgKioyLjQuIFTDrG5oIHRy4bqhbmcgbeG7kWkgcXVhbiBo4buHKioNCg0KIyMjIyAqKjIuNC4xIFRo4buRbmcga8OqIHThuqduIHPhu5EsIHThuqduIHN14bqldCB2w6AgdHLhu7FjIHF1YW4gaMOzYSoqDQoNCmBgYHtyfQ0KcmVsX2ZyZXEgPC0gdGFibGUoZGF0YSRSZWxhdGlvbnNoaXBfU3RhdHVzKQ0KcmVsX3BlcmNlbnQgPC0gcHJvcC50YWJsZShyZWxfZnJlcSkgKiAxMDANCmRhdGEuZnJhbWUoUmVsYXRpb25zaGlwX1N0YXR1cyA9IG5hbWVzKHJlbF9mcmVxKSwNCiAgICAgICAgICAgRnJlcXVlbmN5ID0gYXMubnVtZXJpYyhyZWxfZnJlcSksDQogICAgICAgICAgIFBlcmNlbnRhZ2UgPSByb3VuZChhcy5udW1lcmljKHJlbF9wZXJjZW50KSwgMSkpDQpgYGANCg0KIyMjIyMgKioyLjQuMS4xIFRy4buxYyBxdWFuIGhvw6EqKg0KDQpgYGB7cn0NCnBsb3RfcGllKGRhdGEsICJSZWxhdGlvbnNoaXBfU3RhdHVzIiwgIlBow6JuIGLhu5EgdMOsbmggdHLhuqFuZyBt4buRaSBxdWFuIGjhu4ciKQ0KDQpgYGANCg0KIyMjIyAqKjIuNC4yIE5o4bqtbiB4w6l0KioNCg0KLSBTaW5oIHZpw6puIMSR4buZYyB0aMOibiBjaGnhur9tIDUxLjc4JSwgxJFhbmcgecOqdSBjaGnhur9tIDQxLjklIHbDoCA2LjMyJSBjw7MgbeG7kWkgcXVhbiBo4buHIHBo4bupYyB04bqhcC4NCg0KIyMjICoqMi41LiBQaMOibiBsb+G6oWkgc+G7qWMga2jhu49lIHRpbmggdGjhuqduKioNCg0KIyMjIyAqKjIuNS4xIFRo4buRbmcga8OqIHThuqduIHPhu5EsIHThuqduIHN14bqldCB2w6AgdHLhu7FjIHF1YW4gaMOzYSoqDQoNCmBgYHtyfQ0KbWhfZnJlcSA8LSB0YWJsZShkYXRhJE1lbnRhbF9IZWFsdGhfQ2F0ZWdvcnkpDQptaF9wZXJjZW50IDwtIHByb3AudGFibGUobWhfZnJlcSkgKiAxMDANCmRhdGEuZnJhbWUoTWVudGFsX0hlYWx0aCA9IG5hbWVzKG1oX2ZyZXEpLA0KICAgICAgICAgICBGcmVxdWVuY3kgPSBhcy5udW1lcmljKG1oX2ZyZXEpLA0KICAgICAgICAgICBQZXJjZW50YWdlID0gcm91bmQoYXMubnVtZXJpYyhtaF9wZXJjZW50KSwgMSkpDQpgYGANCg0KIyMjIyMgKioyLjUuMS4xIFRy4buxYyBxdWFuIGhvw6EqKg0KDQpgYGB7cn0NCnBsb3RfcGllKGRhdGEsICJNZW50YWxfSGVhbHRoX0NhdGVnb3J5IiwgIlBow6JuIGxv4bqhaSBz4bupYyBraOG7j2UgdGluaCB0aOG6p24iKQ0KYGBgDQoNCiMjIyMgKioyLjUuMiBOaOG6rW4geMOpdCoqDQoNCi0gU+G7qWMga2jhu49lIHRpbmggdGjhuqduIGNo4bunIHnhur91IOG7nyBt4bupYyBiw6xuaCB0aMaw4budbmcgKDc2LjA5JSksIDIzLjkxJSDEkcaw4bujYyDEkcOhbmggZ2nDoSB04buRdC4gS2jDtG5nIGFpIHRodeG7mWMgbmjDs20gJ2vDqW0nLg0KDQojIyMgKioyLjYuIE3hu6ljIMSR4buZIG5naGnhu4duIG3huqFuZyB4w6MgaOG7mWkqKg0KDQojIyMjICoqMi42LjEgVGjhu5FuZyBrw6ogdOG6p24gc+G7kSwgdOG6p24gc3XhuqV0IHbDoCB0cuG7sWMgcXVhbiBow7NhKioNCg0KYGBge3J9DQoNCmFkZGljdF9mcmVxIDwtIHRhYmxlKGRhdGEkQWRkaWN0aW9uX0xldmVsKQ0KYWRkaWN0X3BlcmNlbnQgPC0gcHJvcC50YWJsZShhZGRpY3RfZnJlcSkgKiAxMDANCmRhdGEuZnJhbWUoQWRkaWN0aW9uX0xldmVsID0gbmFtZXMoYWRkaWN0X2ZyZXEpLA0KICAgICAgICAgICBGcmVxdWVuY3kgPSBhcy5udW1lcmljKGFkZGljdF9mcmVxKSwNCiAgICAgICAgICAgUGVyY2VudGFnZSA9IHJvdW5kKGFzLm51bWVyaWMoYWRkaWN0X3BlcmNlbnQpLCAxKSkNCmBgYA0KDQojIyMjIyAqKjIuNi4xLjEgVHLhu7FjIHF1YW4gaG/DoSoqDQoNCmBgYHtyfQ0KcGxvdF9waWUoZGF0YSwgIkFkZGljdGlvbl9MZXZlbCIsICJN4bupYyDEkeG7mSBuZ2hp4buHbiBt4bqhbmcgeMOjIGjhu5lpIikNCg0KYGBgDQoNCiMjIyMgKioyLjYuMiBOaOG6rW4geMOpdCoqDQoNClThu7cgbOG7hyBuZ2hp4buHbiBt4bqhbmcgeMOjIGjhu5lpIG7hurduZyBy4bqldCBjYW8gduG7m2kgMzczIHNpbmggdmnDqm4gKDczLjcxJSkuIENo4buJIGPDsyAzIHNpbmggdmnDqm4gKDAuNTklKSBraMO0bmcgbmdoaeG7h24uDQoNCiMjIyAqKjIuNy4gVMOsbmggdHLhuqFuZyBnaeG6pWMgbmfhu6cqKg0KDQojIyMjICoqMi43LjEgVGjhu5FuZyBrw6ogdOG6p24gc+G7kSwgdOG6p24gc3XhuqV0IHbDoCB0cuG7sWMgcXVhbiBow7NhKioNCg0KYGBge3J9DQpzbGVlcF9mcmVxIDwtIHRhYmxlKGRhdGEkU2xlZXBfUXVhbGl0eSkNCnNsZWVwX3BlcmNlbnQgPC0gcHJvcC50YWJsZShzbGVlcF9mcmVxKSAqIDEwMA0KZGF0YS5mcmFtZShTbGVlcF9RdWFsaXR5ID0gbmFtZXMoc2xlZXBfZnJlcSksDQogICAgICAgICAgIEZyZXF1ZW5jeSA9IGFzLm51bWVyaWMoc2xlZXBfZnJlcSksDQogICAgICAgICAgIFBlcmNlbnRhZ2UgPSByb3VuZChhcy5udW1lcmljKHNsZWVwX3BlcmNlbnQpLCAxKSkNCmBgYA0KDQojIyMjIyAqKjIuNy4xLjEgVHLhu7FjIHF1YW4gaG/DoSoqDQoNCmBgYHtyfQ0KcGxvdF9waWUoZGF0YSwgIlNsZWVwX1F1YWxpdHkiLCAiVMOsbmggdHLhuqFuZyBnaeG6pWMgbmfhu6ciKQ0KYGBgDQoNCiMjIyMgKioyLjcuMiBOaOG6rW4geMOpdCoqDQoNCkPDsyAyNzYgc2luaCB2acOqbiAoNTQuNTUlKSB0aGnhur91IG5n4bunIHbDoCAyMzAgbmfGsOG7nWkgbmfhu6cgxJHhu6cgZ2nhuqVjICg0NS40NSUpLg0KVOG7tyBs4buHIHRoaeG6v3Ugbmfhu6cgdsaw4bujdCBxdcOhIG7hu61hIG3huqt1IGto4bqjbyBzw6F0Lg0KDQojIyMgKioyLjguIE3hu6ljIMSR4buZIG3DonUgdGh14bqrbiBkbyBt4bqhbmcgeMOjIGjhu5lpKioNCg0KIyMjIyAqKjIuOC4xIFRo4buRbmcga8OqIHThuqduIHPhu5EsIHThuqduIHN14bqldCB2w6AgdHLhu7FjIHF1YW4gaMOzYSoqDQoNCmBgYHtyfQ0KY29uZmxpY3RfZnJlcSA8LSB0YWJsZShkYXRhJENvbmZsaWN0X0xldmVsKQ0KY29uZmxpY3RfcGVyY2VudCA8LSBwcm9wLnRhYmxlKGNvbmZsaWN0X2ZyZXEpICogMTAwDQpkYXRhLmZyYW1lKENvbmZsaWN0X0xldmVsID0gbmFtZXMoY29uZmxpY3RfZnJlcSksDQogICAgICAgICAgIEZyZXF1ZW5jeSA9IGFzLm51bWVyaWMoY29uZmxpY3RfZnJlcSksDQogICAgICAgICAgIFBlcmNlbnRhZ2UgPSByb3VuZChhcy5udW1lcmljKGNvbmZsaWN0X3BlcmNlbnQpLCAxKSkNCmBgYA0KDQojIyMjIyAqKjIuOC4xLjEgVHLhu7FjIHF1YW4gaG/DoSoqDQoNCmBgYHtyfQ0KcGxvdF9waWUoZGF0YSwgIkNvbmZsaWN0X0xldmVsIiwgIlPhu5EgbOG6p24gbcOidSB0aHXhuqtuIGRvIG3huqFuZyB4w6MgaOG7mWkiKQ0KDQpgYGANCg0KIyMjIyAqKjIuOC4yIE5o4bqtbiB4w6l0KioNCg0KNTA0LzUwNiBzaW5oIHZpw6puICg5OS42JSkgZ+G6t3AgbcOidSB0aHXhuqtuIGxpw6puIHF1YW4gxJHhur9uIG3huqFuZyB4w6MgaOG7mWkuIMSQw6J5IGzDoCB04bu3IGzhu4cgY+G7sWMga+G7syBjYW8gdsOgIGPhuqNuaCBiw6FvIG3hu5FpIGxvIG5n4bqhaSB4w6MgaOG7mWkuDQoNCiMjIyAqKjIuOS4gTuG7gW4gdOG6o25nIG3huqFuZyB4w6MgaOG7mWkgxJHGsOG7o2Mgc+G7rSBk4bulbmcgcGjhu5UgYmnhur9uKioNCg0KIyMjIyAqKjIuOS4xIFRo4buRbmcga8OqIHThuqduIHPhu5EsIHThuqduIHN14bqldCB2w6AgdHLhu7FjIHF1YW4gaMOzYSoqDQoNCmBgYHtyfQ0KcGxhdGZvcm1fZnJlcSA8LSB0YWJsZShkYXRhJE1vc3RfVXNlZF9QbGF0Zm9ybSkNCnBsYXRmb3JtX3BlcmNlbnQgPC0gcHJvcC50YWJsZShwbGF0Zm9ybV9mcmVxKSAqIDEwMA0KZGF0YS5mcmFtZShQbGF0Zm9ybSA9IG5hbWVzKHBsYXRmb3JtX2ZyZXEpLA0KICAgICAgICAgICBGcmVxdWVuY3kgPSBhcy5udW1lcmljKHBsYXRmb3JtX2ZyZXEpLA0KICAgICAgICAgICBQZXJjZW50YWdlID0gcm91bmQoYXMubnVtZXJpYyhwbGF0Zm9ybV9wZXJjZW50KSwgMSkpDQpgYGANCg0KIyMjIyMgKioyLjkuMS4xIFRy4buxYyBxdWFuIGhvw6EqKg0KDQpgYGB7cn0NCiMgVOG6oW8gYuG6o25nIHThuqduIHPhu5ENCnBsYXRmb3JtX2ZyZXEgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkYXRhJE1vc3RfVXNlZF9QbGF0Zm9ybSkpDQpjb2xuYW1lcyhwbGF0Zm9ybV9mcmVxKSA8LSBjKCJQbGF0Zm9ybSIsICJGcmVxdWVuY3kiKQ0KDQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0DQpnZ3Bsb3QocGxhdGZvcm1fZnJlcSwgYWVzKHggPSByZW9yZGVyKFBsYXRmb3JtLCAtRnJlcXVlbmN5KSwgeSA9IEZyZXF1ZW5jeSwgZmlsbCA9IFBsYXRmb3JtKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBsYWJzKHRpdGxlID0gIk7hu4FuIHThuqNuZyBt4bqhbmcgeMOjIGjhu5lpIMSRxrDhu6NjIHPhu60gZOG7pW5nIHBo4buVIGJp4bq/biIsDQogICAgICAgeCA9ICJO4buBbiB04bqjbmciLCB5ID0gIlPhu5EgbMaw4bujbmciKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0ID0gMSkpICsNCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIpDQpgYGANCg0KIyMjIyAqKjIuOS4yIE5o4bqtbiB4w6l0KioNCg0KSW5zdGFncmFtIMSRxrDhu6NjIHPhu60gZOG7pW5nIG5oaeG7gXUgbmjhuqV0ICgxNjMgc2luaCB2acOqbiDigJMgMzIuMjElKSwgc2F1IMSRw7MgbMOgIFRpa1RvayAoMTI2IHNpbmggdmnDqm4g4oCTIDI0LjklKSB2w6AgRmFjZWJvb2sgKDcxIHNpbmggdmnDqm4g4oCTIDE0LjAzJSkuDQoNCiMjIyAqKjIuMTAuIE3hu6ljIMSR4buZIHPhu60gZOG7pW5nIE1YSCoqDQoNCiMjIyMgKioyLjEwLjEgVGjhu5FuZyBrw6ogdOG6p24gc+G7kSwgdOG6p24gc3XhuqV0IHbDoCB0cuG7sWMgcXVhbiBow7NhKioNCg0KYGBge3J9DQojIFRo4buRbmcga8OqIHThuqduIHPhu5ENCnRhYmxlX3VzYWdlIDwtIHRhYmxlKGRhdGEkVXNhZ2VfTGV2ZWwpDQp0YWJsZV91c2FnZQ0KDQojIFRo4buRbmcga8OqIHThu7cgbOG7hyBwaOG6p24gdHLEg20NCnByb3AudGFibGUodGFibGVfdXNhZ2UpICogMTAwDQoNCmBgYA0KDQpgYGB7cn0NCnBsb3RfcGllKGRhdGEsICJVc2FnZV9MZXZlbCIsICJQaMOibiBi4buRIHRyw6xuaCBN4bupYyDEkeG7mSBz4butIGThu6VuZyBt4bqhbmcgeMOjIGjhu5lpIG3hu5dpIG5nw6B5IikNCmBgYA0KDQojIyMjICoqMi4xMC4yIE5o4bqtbiB4w6l0KioNCg0KMzA3IHNpbmggdmnDqm4gKDYwLjg3JSkgc+G7rSBk4bulbmcgbeG6oW5nIHjDoyBo4buZaSB04burIDUNCmdp4budIHRy4bufIGzDqm4gbeG7l2kgbmfDoHkuIMSQw6J5IGzDoCBt4bupYyBz4butIGThu6VuZyBy4bqldCBjYW8gdsOgIGPDsyB0aOG7gyDhuqNuaCBoxrDhu59uZyDEkeG6v24NCnPhu6ljIGto4buPZS4NCg0KIyMgKipQSOG6pk4gMzogxq/hu5pDIEzGr+G7ok5HICYgS0nhu4JNIMSQ4buKTkggR0nhuqIgVEhVWeG6vlQgVOG7tiBM4buGKioNCg0KIyMjICoqMy4xIOKAkyBU4bu3IGzhu4cgc2luaCB2acOqbiBuYW0qKg0KDQpgYGB7cn0NCiMgQsaw4bubYyAxOiDEkOG6v20gc+G7kSBsxrDhu6NuZyBzaW5oIHZpw6puIG5hbQ0KeCA8LSBzdW0oZGF0YSRHZW5kZXIgPT0gIk1hbGUiKSAgIyB4IGzDoCBz4buRIHNpbmggdmnDqm4gY8OzIGdp4bubaSB0w61uaCAiTWFsZSINCg0KIyBCxrDhu5tjIDI6IFTDrW5oIHThu5VuZyBz4buRIHNpbmggdmnDqm4gdHJvbmcgZOG7ryBsaeG7h3UNCm4gPC0gbnJvdyhkYXRhKSAgIyBuIGzDoCBrw61jaCB0aMaw4bubYyBt4bqrdSAodOG7lW5nIHNpbmggdmnDqm4pDQoNCiMgQsaw4bubYyAzOiBLaeG7g20gxJHhu4tuaCBnaeG6oyB0aHV54bq/dCBIMDogdOG7tyBs4buHIG5hbSA9IDAuNSAoNTAlKQ0KIyBwcm9wLnRlc3QgdGjhu7FjIGhp4buHbiBraeG7g20gxJHhu4tuaCB04bu3IGzhu4cgMSBt4bqrdSB2w6AgeHXhuqV0IHJhIGtob+G6o25nIHRpbiBj4bqteQ0KcHJvcC50ZXN0KHggPSB4LCBuID0gbiwgcCA9IDAuNSwgY29uZi5sZXZlbCA9IDAuOTUpDQpgYGANCg0KKipHaeG6o2kgdGjDrWNoIHRvw6FuIGjhu41jIHbDoCB0aOG7kW5nIGvDqjoqKiANCg0KLSBUw61uaCB04bu3IGzhu4cgbeG6q3U6DQokXGhhdHtwfSA9IFxmcmFje3h9e259ID0gXGZyYWN7MjUzfXs1MDZ9ID0gMC41JCANCi0gU2FpIHPhu5EgY2h14bqpbiAoU3RhbmRhcmQNCkVycm9yIC0gU0UpOg0KJCRTRSA9IFxzcXJ0eyBcZnJhY3twKDEtcCl9e259IH0gPSBcc3FydHsgXGZyYWN7MC41KDEtMC41KX17NTA2fSB9ID0gMC4wMjIkJCAtDQpLaG/huqNuZyB0aW4gY+G6rXkgOTUlOg0KJCRDSSA9IFxoYXR7cH0gXHBtIHpfezAuMDI1fSBcY2RvdCBTRSA9IDAuNSBccG0gMS45NiBcY2RvdCAwLjAyMiA9IFswLjQ1NjYsIDAuNTQzNF0kJCAtDQpwLXZhbHVlID0gMSDihpIgS2jDtG5nIGLDoWMgYuG7jyBIMCDihpIgS2jDtG5nIGPDsyBraMOhYyBiaeG7h3Qgc28gduG7m2kgdOG7tyBs4buHIGdp4bqjDQrEkeG7i25oLg0KDQojIyMgTmjhuq1uIHjDqXQ6DQoNClThu7cgbOG7hyBzaW5oIHZpw6puIG5hbSDEkcO6bmcgYuG6sW5nIDUwJSBuaMawIGdp4bqjIMSR4buLbmggYmFuIMSR4bqndSwga2jDtG5nIGPDsyBraMOhYyBiaeG7h3QgxJHDoW5nIGvhu4MuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyMgKiozLjIg4oCTIFThu7cgbOG7hyBzaW5oIHZpw6puIFVuZGVyZ3JhZHVhdGUqKg0KDQpgYGB7cn0NCnggPC0gc3VtKGRhdGEkQWNhZGVtaWNfTGV2ZWwgPT0gIlVuZGVyZ3JhZHVhdGUiKQ0KbiA8LSBucm93KGRhdGEpDQpwcm9wLnRlc3QoeCA9IHgsIG4gPSBuLCBwID0gMC41LCBjb25mLmxldmVsID0gMC45NSkNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2g6KioNCg0KLSBHaeG7kW5nIDMuMSwgbmjGsG5nIHRoYXkgYmnhur9uIGBHZW5kZXJgIHRow6BuaA0KYEFjYWRlbWljX0xldmVsYA0KLSBU4bu3IGzhu4cgbeG6q3UgY8WpbmcgbMOgIDAuNSDihpIga2jDtG5nIGtow6FjIGJp4buHdCB24bubaSBnaeG6oyDEkeG7i25oDQo1MCUNCg0KIyMjIE5o4bqtbiB4w6l0Og0KDQpU4bu3IGzhu4cgc2luaCB2acOqbiBi4bqtYyDEkeG6oWkgaOG7jWMgdsOgIGNhbyBo4buNYyBsw6AgY8OibiBi4bqxbmcgdHJvbmcgbeG6q3UgbmdoacOqbiBj4bupdS4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMjIyAqKjMuMyDigJMgVOG7tyBs4buHIHRoaeG6v3Ugbmfhu6cqKg0KDQpgYGB7cn0NCnggPC0gc3VtKGRhdGEkU2xlZXBfUXVhbGl0eSA9PSAiVGhp4bq/dSBuZ+G7pyIpICAgICMgxJDhur9tIHPhu5Egc2luaCB2acOqbiB0aGnhur91IG5n4bunDQpuIDwtIHN1bSghaXMubmEoZGF0YSRTbGVlcF9RdWFsaXR5KSkgICAgICAgICAgICAjIFThu5VuZyBz4buRIHNpbmggdmnDqm4gY8OzIGThu68gbGnhu4d1DQpwcm9wLnRlc3QoeCA9IHgsIG4gPSBuLCBwID0gMC40LCBjb25mLmxldmVsID0gMC45NSkgICMgU28gc8OhbmggduG7m2kgZ2nhuqMgxJHhu4tuaCA0MCUNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2g6KioNCg0KLSAkeCA9IDI3NiQsICRuID0gNTA2JCAtICRwXzAgPSAwLjQkIGzDoCB04bu3IGzhu4cgZ2nhuqMgxJHhu4tuaA0KxJHhu4Mgc28gc8OhbmggDQotIFTDrW5oIHThu7cgbOG7hyBt4bqrdToNCiQkXGhhdHtwfSA9IFxmcmFjezI3Nn17NTA2fSBcYXBwcm94IDAuNTQ1NSQkIC0gU2FpIHPhu5EgY2h14bqpbjoNCiQkU0UgPSBcc3FydHsgXGZyYWN7MC40KDEtMC40KX17NTA2fSB9IFxhcHByb3ggMC4wMjE4JCQgLSANCktob+G6o25nIHRpbiBj4bqteTogJCRDSSA9IDAuNTQ1NSBccG0gMS45NiBcY2RvdCAwLjAyMTggPSBbMC41MDEsIDAuNTg5XSQkDQoNCiMjIyBOaOG6rW4geMOpdDoNCg0KVOG7tyBs4buHIHNpbmggdmnDqm4gdGhp4bq/dSBuZ+G7pyBjYW8gaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBnaeG6oyDEkeG7i25oIDQwJSwgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiAocCA8IDAuMDUpLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMjICoqMy40IOKAkyBU4bu3IGzhu4cgbmdoaeG7h24gbeG6oW5nIHjDoyBo4buZaSBu4bq3bmcqKg0KDQpgYGB7cn0NCnggPC0gc3VtKGRhdGEkQWRkaWN0aW9uX0xldmVsID09ICJOZ2hp4buHbiBu4bq3bmciKQ0KbiA8LSBzdW0oIWlzLm5hKGRhdGEkQWRkaWN0aW9uX0xldmVsKSkNCnByb3AudGVzdCh4ID0geCwgbiA9IG4sIHAgPSAwLjUsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiLCBjb25mLmxldmVsID0gMC45NSkNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2g6KioNCg0KLSBgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciJgOiBraeG7g20gxJHhu4tuaCAxIHBow61hLCB4ZW0gY8OzIGzhu5tuIGjGoW4gNTAlIA0KLSBU4bu3IGzhu4cgbeG6q3U6ICRcaGF0e3B9ID0gMzczIC8gNTA2IFxhcHByb3ggMC43MzckIA0KLSBLaG/huqNuZyB0aW4gY+G6rXk6ICQkQ0kgPSBbMC43MDMsIDAuNzcwXSQkDQoNCiMjIyBOaOG6rW4geMOpdDoNCg0KVOG7tyBs4buHIG5naGnhu4duIG3huqFuZyB4w6MgaOG7mWkgbuG6t25nIHbGsOG7o3QgeGEgbeG7qWMgZ2nhuqMgxJHhu4tuaCA1MCUsIHAtdmFsdWUgPCAwLjAwMSBy4bqldCBjw7Mgw70gbmdoxKlhLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMjICoqMy41IOKAkyBN4bupYyDEkeG7mSBtw6J1IHRodeG6q24gY2FvKioNCg0KYGBge3J9DQp4IDwtIHN1bShkYXRhJENvbmZsaWN0X0xldmVsICVpbiUgYygiS2jDoSBuaGnhu4F1IiwgIlLhuqV0IG5oaeG7gXUiKSkgICMgxJDhur9tIGPDoWMgbeG7qWMgY2FvDQpuIDwtIHN1bSghaXMubmEoZGF0YSRDb25mbGljdF9MZXZlbCkpDQpwcm9wLnRlc3QoeCA9IHgsIG4gPSBuLCBwID0gMC44LCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikgICMgR2nhuqMgxJHhu4tuaCA+PSA4MCUNCmBgYA0KDQoqKkdp4bqjaSB0aMOtY2g6KioNCg0KXC0gJFxoYXR7cH0gPSA1MDQgLyA1MDYgXGFwcHJveCAwLjk5NiQgDQotIEtob+G6o25nIHRpbiBj4bqteToNCiQkQ0kgPSBbMC45ODYsIDAuOTk5XSQkIA0KLSBwIHLhuqV0IG5o4buPLCBjaG8gdGjhuqV5IHThu7cgbOG7hyB0aOG7sWMgdOG6vyB2xrDhu6N0IHhhIGdp4bqjIMSR4buLbmggODAlDQoNCiMjIyBOaOG6rW4geMOpdDoNCg0KR+G6p24gbmjGsCB04bqldCBj4bqjIHNpbmggdmnDqm4gZ+G6t3AgeHVuZyDEkeG7mXQgbeG7qWMgY2FvLCB04bu3IGzhu4cgbsOgeSB2xrDhu6N0IHLhuqV0IHhhIG3hu6ljIGThu7EgxJFvw6FuLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgKipQSOG6pk4gNDogUEjDgk4gVMONQ0ggTeG7kEkgTEnDik4gSOG7hiBHSeG7rkEgSEFJIEJJ4bq+TioqDQoNCiMjIyAqKjQuMSBUSEnhur5VIE5H4bumIFbDgCBOR0hJ4buGTiBN4bqgTkcgWMODIEjhu5hJKioNCg0KVMOsbSBoaeG7g3UgeGVtIGxp4buHdSBUaGnhur91IG5n4bunIGPDsyBsacOqbiBo4buHIHbhu5tpIG3hu6ljIMSR4buZIG5naGnhu4duIG3huqFuZyB4w6MgaOG7mWkga2jDtG5nPyANCihOw7NpIGPDoWNoIGtow6FjOiBMaeG7h3Ugbmjhu69uZyBuZ8aw4budaSB0aGnhur91IG5n4bunIGPDsyBuZ2hp4buHbiBt4bqhbmcgeMOjIGjhu5lpIG5oaeG7gXUgaMahbiBraMO0bmc/KQ0KDQojIyMjICoqNC4xLjEgQuG6o25nIHThuqduIHN14bqldCBjaMOpbyoqDQoNCmBgYHtyfQ0KDQojIELhuqNuZyBjaMOpbyBnaeG7r2EgY2jhuqV0IGzGsOG7o25nIGdp4bqlYyBuZ+G7pyB2w6AgbeG7qWMgxJHhu5kgbmdoaeG7h24NCnRhYmxlX3NsZWVwX2FkZGljdCA8LSB0YWJsZShkYXRhJFNsZWVwX1F1YWxpdHksIGRhdGEkQWRkaWN0aW9uX0xldmVsKQ0KdGFibGVfc2xlZXBfYWRkaWN0DQojIELhuqNuZyB04bqnbiBzdeG6pXQgY2jDqW8gKGNvbnRpbmdlbmN5IHRhYmxlKSBjaG8gaGFpIGJp4bq/biDEkeG7i25oIHTDrW5oOg0KIyAtIFNsZWVwX1F1YWxpdHk6IOKAnE5n4bunIMSR4bun4oCdIGhv4bq3YyDigJxUaGnhur91IG5n4bun4oCdDQojIC0gQWRkaWN0aW9uX0xldmVsOiDigJxLaMO0bmcgbmdoaeG7h27igJ0sIOKAnELDrG5oIHRoxrDhu51uZ+KAnSwg4oCcTmdoaeG7h24gbuG6t25n4oCdDQojDQojIHRhYmxlX3NsZWVwX2FkZGljdFtpLCBqXSB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBzaW5oIHZpw6puIGPDsw0KIyBTbGVlcF9RdWFsaXR5ID0gaSB2w6AgQWRkaWN0aW9uX0xldmVsID0gag0KDQpgYGANCg0KKipLw70gaGnhu4d1IHbDoCBjw7RuZyB0aOG7qWMqKg0KDQpH4buNaSAkbl97aWp9JCBsw6Agc+G7kSBzaW5oIHZpw6puIOG7nyBow6BuZyAkaSQsIGPhu5l0ICRqJCwgduG7m2k6DQoNCi0gICAkaSA9IDEkOiBuaMOzbSAiTmfhu6cgxJHhu6ciLCAkaSA9IDIkOiBuaMOzbSAiVGhp4bq/dSBuZ+G7pyJcDQotICAgJGogPSAxJDogIktow7RuZyBuZ2hp4buHbiIsICRqID0gMiQ6ICJCw6xuaCB0aMaw4budbmciLCAkaiA9IDMkOiAiTmdoaeG7h24NCiAgICBu4bq3bmciXA0KLSAgIFThu5VuZyBz4buRIHF1YW4gc8OhdDogJG4gPSA1MDYkDQoNClThuqduIHN14bqldCAodOG7tyBs4buHKSB04bqhaSDDtCAkKGksIGopJCDEkcaw4bujYyB0w61uaCB0aGVvIGPDtG5nIHRo4bupYzoNCg0KJCQNCnBfe2lqfSA9IFxmcmFje25fe2lqfX17bn0NCiQkDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoqKk3hu5l0IHPhu5EgdMOtbmggdG/DoW4gY+G7pSB0aOG7gyoqDQoNClThu7cgbOG7hyBzaW5oIHZpw6puIHRodeG7mWMgbmjDs20gKip0aGnhur91IG5n4bunKiogdsOgICoqbmdoaeG7h24gbeG6oW5nIHjDoyBo4buZaSBu4bq3bmcqKjoNCg0KJCQNCnBfezIzfSA9IFxmcmFjezI2OX17NTA2fSBcYXBwcm94IDAuNTMxOA0KJCQNCg0KVOG7lW5nIHPhu5Egc2luaCB2acOqbiB0aHXhu5ljIG5ow7NtICoqdGhp4bq/dSBuZ+G7pyoqOg0KDQokJA0Kbl97MlxjZG90fSA9IG5fezIxfSArIG5fezIyfSArIG5fezIzfSA9IDAgKyA3ICsgMjY5ID0gMjc2DQokJA0KDQpU4buVbmcgc+G7kSBzaW5oIHZpw6puIG5naGnhu4duICoqbeG6oW5nIHjDoyBo4buZaSBu4bq3bmcqKjoNCg0KJCQNCm5fe1xjZG90IDN9ID0gbl97MTN9ICsgbl97MjN9ID0gMTA0ICsgMjY5ID0gMzczDQokJA0KDQpU4bu3IGzhu4cgc2luaCB2acOqbiBuZ2hp4buHbiBu4bq3bmcgdHJvbmcgdOG7q25nIG5ow7NtIGdp4bqlYyBuZ+G7pzoNCg0KLSAgIFbhu5tpIG5ow7NtICoqdGhp4bq/dSBuZ+G7pyoqOg0KDQokJA0KXGZyYWN7MjY5fXsyNzZ9IFxhcHByb3ggMC45NzQ2IFxxdWFkICg5Ny40NlwlKQ0KJCQNCg0KLSAgIFbhu5tpIG5ow7NtICoqbmfhu6cgxJHhu6cqKjoNCg0KJCQNClxmcmFjezEwNH17MjMwfSBcYXBwcm94IDAuNDUyMiBccXVhZCAoNDUuMjJcJSkNCiQkDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoqKk5o4bqtbiB4w6l0KioNCg0KTmjDs20gVGhp4bq/dSBuZ+G7pyBjw7MgxJHhur9uIDI2OSBzaW5oIHZpw6puIG5naGnhu4duIG3huqFuZyB4w6MgaOG7mWkgbuG6t25nLCBjaGnhur9tIDk3LjUlDQp0cm9uZyBuaMOzbSBuw6B5Lg0KDQpUcm9uZyBraGkgxJHDsywgbmjDs20gTmfhu6cgxJHhu6cgY2jhu4kgY8OzIDEwNC8yMzAgPSA0NS4yJSBsw6AgbmdoaeG7h24gbuG6t25nLg0KDQpU4bu3IGzhu4cg4oCcQsOsbmggdGjGsOG7nW5n4oCdIHRyb25nIG5ow7NtIG5n4bunIMSR4bunICgxMjMvMjMwID0gNTMuNSUpIGNhbyBoxqFuIHLhuqV0DQpuaGnhu4F1IHNvIHbhu5tpIG5ow7NtIHRoaeG6v3Ugbmfhu6cgKDcvMjc2ID0gMi41JSkuDQoNCsSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IHNpbmggdmnDqm4gdGhp4bq/dSBuZ+G7pyBjw7MgeHUgaMaw4bubbmcgbmdoaeG7h24gbeG6oW5nIHjDoyBo4buZaQ0KbuG6t25nIGjGoW4gcsO1IHLhu4d0IHNvIHbhu5tpIHNpbmggdmnDqm4gbmfhu6cgxJHhu6cuDQoNCiMjIyAqKjQuMS4yIFRy4buxYyBxdWFuIGhvw6EqKg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBC4bqjbmcgdOG6p24gc+G7kSBnaeG7r2EgU2xlZXBfUXVhbGl0eSB2w6AgQWRkaWN0aW9uX0xldmVsDQpzbGVlcF9hZGRpY3RfdGJsIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoZGF0YSRTbGVlcF9RdWFsaXR5LCBkYXRhJEFkZGljdGlvbl9MZXZlbCkpDQpjb2xuYW1lcyhzbGVlcF9hZGRpY3RfdGJsKSA8LSBjKCJTbGVlcF9RdWFsaXR5IiwgIkFkZGljdGlvbl9MZXZlbCIsICJDb3VudCIpDQoNCmdncGxvdChzbGVlcF9hZGRpY3RfdGJsLCBhZXMoeCA9IFNsZWVwX1F1YWxpdHksIHkgPSBDb3VudCwgZmlsbCA9IEFkZGljdGlvbl9MZXZlbCkpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aCA9IDAuNykgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk3hu5FpIGxpw6puIGjhu4cgZ2nhu69hIGNo4bqldCBsxrDhu6NuZyBnaeG6pWMgbmfhu6cgdsOgIG3hu6ljIMSR4buZIG5naGnhu4duIG3huqFuZyB4w6MgaOG7mWkiLA0KICAgIHggPSAiQ2jhuqV0IGzGsOG7o25nIGdp4bqlYyBuZ+G7pyIsDQogICAgeSA9ICJT4buRIGzGsOG7o25nIHNpbmggdmnDqm4iLA0KICAgIGZpbGwgPSAiTeG7qWMgxJHhu5kgbmdoaeG7h24iDQogICkgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlBhc3RlbDIiKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpDQoNCmBgYA0KDQpCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSBz4buxIGtow6FjIGJp4buHdCBy4bqldCByw7UgcuG7h3Q6TmjDs20g4oCcVGhp4bq/dSBuZ+G7p+KAnSBn4bqnbiBuaMawIGNo4buJIGPDsyBzaW5oIHZpw6puIOG7nyBt4bupYyDigJxOZ2hp4buHbiBu4bq3bmfigJ0sIHRyb25nIGtoaSBuaMOzbSDigJxOZ+G7pyDEkeG7p+KAnSBwaMOibiBi4buRIMSR4buBdSBoxqFuLiDEkGnhu4F1IG7DoHkgY+G7p25nIGPhu5EgbmdoaSBuZ+G7nSBy4bqxbmcgZ2nhuqVjIG5n4bunIHbDoCBt4bupYyDEkeG7mSBuZ2hp4buHbiBteGggY8OzIG3hu5FpIGxpw6puIGjhu4cgdGjhu5FuZyBrw6ouDQoNCiMjIyAqKjQuMS40IEtp4buDbSDEkeG7i25oIGNoaSBiw6xuaCBwaMawxqFuZyoqDQoNCmBgYHtyfQ0KIyBC4bqjbmcgdOG6p24gc+G7kSANCnRhYmxlX3NsZWVwX2FkZGljdCA8LSB0YWJsZShkYXRhJFNsZWVwX1F1YWxpdHksIGRhdGEkQWRkaWN0aW9uX0xldmVsKQ0KdGFibGVfc2xlZXBfYWRkaWN0DQojIEtp4buDbSDEkeG7i25oIENoaSBiw6xuaCBwaMawxqFuZw0KY2hpc3EudGVzdCh0YWJsZV9zbGVlcF9hZGRpY3QpDQpgYGANCg0KIyMjIyBN4bulYyB0acOqdSBraeG7g20gxJHhu4tuaA0KDQpLaeG7g20gdHJhIGdp4bqjIHRodXnhur90IHbhu4EgKipz4buxIMSR4buZYyBs4bqtcCoqIGdp4buvYSBoYWkgYmnhur9uIHBow6JuIGxv4bqhaS4NCg0KLSAgICoqR2nhuqMgdGh1eeG6v3Qga2jDtG5nIChI4oKAKSoqOiBIYWkgYmnhur9uIMSR4buZYyBs4bqtcCAoa2jDtG5nIGPDsyBt4buRaSBsacOqbiBo4buHKQ0KLSAgICoqR2nhuqMgdGh1eeG6v3QgxJHhu5FpIChI4oKBKSoqOiBIYWkgYmnhur9uIGtow7RuZyDEkeG7mWMgbOG6rXAgKGPDsyBt4buRaSBsacOqbiBo4buHKQ0KDQoqKkPDtG5nIHRo4bupYyB0b8OhbiBo4buNYyoqDQoNCioqR2nDoSB0cuG7iyBr4buzIHbhu41uZyAoRXhwZWN0ZWQgZnJlcXVlbmN5KSoqIHThuqFpIMO0IGjDoG5nICRpJCwgY+G7mXQgJGokIMSRxrDhu6NjDQp0w61uaCBuaMawIHNhdToNCg0KJCQNCkVfe2lqfSA9IFxmcmFje25fe2lcY2RvdH0gXHRpbWVzIG5fe1xjZG90IGp9fXtufQ0KJCQNCg0KVHJvbmcgxJHDszoNCg0KLSAgICRFX3tpan0kOiB04bqnbiBz4buRIGvhu7MgduG7jW5nIHThuqFpIMO0ICQoaSwgaikkXA0KLSAgICRuX3tpXGNkb3R9JDogdOG7lW5nIGjDoG5nICRpJFwNCi0gICAkbl97XGNkb3Qgan0kOiB04buVbmcgY+G7mXQgJGokXA0KLSAgICRuJDogdOG7lW5nIHRvw6BuIGLhu5kgbeG6q3UNCg0KVsOtIGThu6UsIHThuqFpIMO0ICQoMSwgMykkOg0KDQokJA0KRV97MTN9ID0gXGZyYWN7MjMwIFx0aW1lcyAzNzN9ezUwNn0gXGFwcHJveCAxNjkuNjENCiQkDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoqKlRo4buRbmcga8OqIGtp4buDbSDEkeG7i25oIENoaSBiw6xuaCBwaMawxqFuZzoqKg0KDQokJA0KXGNoaV4yID0gXHN1bV97aT0xfV57cn0gXHN1bV97aj0xfV57Y30gXGZyYWN7KE9fe2lqfSAtIEVfe2lqfSleMn17RV97aWp9fQ0KJCQNCg0KVHJvbmcgxJHDszoNCg0KLSAgICRPX3tpan0kOiB04bqnbiBz4buRIHF1YW4gc8OhdCB04bqhaSDDtCAkKGksIGopJFwNCi0gICAkRV97aWp9JDogdOG6p24gc+G7kSBr4buzIHbhu41uZyB04bqhaSDDtCAkKGksIGopJA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KKipC4bqtYyB04buxIGRvIChkZWdyZWVzIG9mIGZyZWVkb20pOioqDQoNCiQkDQpkZiA9IChyIC0gMSkoYyAtIDEpDQokJA0KDQrhu54gxJHDonk6DQoNCi0gICAkciA9IDIkIChz4buRIGjDoG5nOiAiTmfhu6cgxJHhu6ciLCAiVGhp4bq/dSBuZ+G7pyIpXA0KLSAgICRjID0gMyQgKHPhu5EgY+G7mXQ6IDMgbeG7qWMgxJHhu5kgbmdoaeG7h24pDQoNCk7Dqm46DQoNCiQkDQpkZiA9ICgyIC0gMSkoMyAtIDEpID0gMg0KJCRHacOhIHRy4buLIHRo4buRbmcga8OqIHLhuqV0IGzhu5tuICjPh8KyID0gMTc2Ljc4KSwgduG7m2kgcC12YWx1ZSA8IDIuMmUtMSwgcuG6pXQgbmjhu48uIA0KQsOhYyBi4buPIEjigoA6IENo4bqldCBsxrDhu6NuZyBnaeG6pWMgbmfhu6cgdsOgIG3hu6ljIMSR4buZIG5naGnhu4duIG3huqFuZyB4w6MNCmjhu5lpIGtow7RuZyDEkeG7mWMgbOG6rXAuIA0KVOG7k24gdOG6oWkgbeG7kWkgbGnDqm4gaOG7hyBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIGdp4buvYSBoYWkNCmJp4bq/bi4gDQoNCiMjIyAqKjQuMS41IFJlbGF0aXZlIFJpc2sqKg0KDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoImVwaXRvb2xzIiwgcmVwb3MgPSAiaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnIikNCmxpYnJhcnkoZXBpdG9vbHMpDQpgYGANCg0KYGBge3J9DQojIFThuqFvIGLhuqNuZyBjaMOpbw0KdGFibGVfU2xlZXBfQWRkaWN0IDwtIHRhYmxlKGRhdGEkU2xlZXBfUXVhbGl0eSwgZGF0YSRBZGRpY3Rpb25fTGV2ZWwpDQojIFJSDQpyaXNrcmF0aW8odGFibGVfU2xlZXBfQWRkaWN0KQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQqKiANCg0KR2nDoSB0cuG7iyBSUiA9IDEuMDI0IG5ow7NtIHRoaeG6v3Ugbmfhu6cgY8OzIG5ndXkgY8ahIG5naGnhu4duIG3huqFuZw0KeMOjIGjhu5lpIG7hurduZyBjYW8gaMahbiAyLjQlIHNvIHbhu5tpIG5ow7NtIG5n4bunIMSR4bunLiBUdXkgbmhpw6puLCBraG/huqNuZyB0aW4gY+G6rXkgY2jhu6lhIDEga2jDtG5nIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouIEtow7RuZyDEkeG7pyBjxqEgc+G7nyDEkeG7gyBr4bq/dCBsdeG6rW4gcuG6sW5nIHRoaeG6v3Ugbmfhu6cgdMSDbmcgbmd1eSBjxqEgbmdoaeG7h24gbXhoIG7hurduZyANCg0KIyMjICoqNC4xLjYgT2RkcyByYXRpbyoqDQoNCmBgYHtyfQ0KIyBU4bqhbyBiaeG6v24gQWRkaWN0aW9uX0JpbmFyeTogVFJVRSBu4bq/dSBsw6AgIk5naGnhu4duIG7hurduZyIsIEZBTFNFIG7hur91IGtow7RuZw0KZGF0YSRBZGRpY3RfSGVhdnkgPC0gZGF0YSRBZGRpY3Rpb25fTGV2ZWwgPT0gIk5naGnhu4duIG7hurduZyINCg0KIyBU4bqhbyBi4bqjbmcgMngyIGdp4buvYSBDaOG6pXQgbMaw4bujbmcgZ2nhuqVjIG5n4bunIHbDoCBOZ2hp4buHbiBu4bq3bmcNCnRhYmxlX3NsZWVwX2FkZGljdF8yeDIgPC0gdGFibGUoZGF0YSRTbGVlcF9RdWFsaXR5LCBkYXRhJEFkZGljdF9IZWF2eSkNCg0KIyBIaeG7h3UgY2jhu4luaCDEkeG7gyB0csOhbmggbOG7l2kNCnRhYmxlX2NvcnJlY3RlZCA8LSB0YWJsZV9zbGVlcF9hZGRpY3RfMngyDQoNCiMgVMOtbmggT2RkcyBSYXRpbw0KbGlicmFyeShlcGl0b29scykNCm9kZHNyYXRpbyh0YWJsZV9jb3JyZWN0ZWQpDQpgYGANCg0KKipOaOG6rW4geMOpdCoqIA0KDQotIEdpw6EgdHLhu4sgT1IgPSA0NS4yNiBzaW5oIHZpw6puIHRoaeG6v3Ugbmfhu6cgY8OzIG5ndXkgY8ahIG5naGnhu4duDQpt4bqhbmcgeMOjIGjhu5lpIG7hurduZyBjYW8gZ+G6pXAgNDUgbOG6p24gc28gduG7m2kgbmjDs20gbmfhu6cgxJHhu6cuIA0KS2hv4bqjbmcgdGluIGPhuq15IDk1JTogWzIxLjg4IDsgMTExLjEwXSB2w6AgcC12YWx1ZSDiiYggMCBj4buxYyBr4buzIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouIE3hu5FpIGxpw6puIGjhu4cgcuG6pXQgbeG6oW5oIHbDoCDEkcOhbmcgdGluIGPhuq15IGdp4buvYSBoYWkgYmnhur9uLg0K