Giới thiệu về Data mining

DataMining - Khai phá dữ liệu là một tập hợp, một hệ thống các phương pháp tính toán, thuật toán được áp dụng cho các cơ sở dữ liệu lớn và phức tạp, mục đích là loại bỏ các chi tiết ngẫu nhiên, chi tiết ngoại lệ, khám phá các mẫu, mô hình, quy luật tiềm ẩn, các thông tin có giá trị trong bộ dữ liệu. Datamining là thành quả của công nghệ tiên tiến ngày nay, là quá trình khám phá các kiến thức vô giá bằng cách phân tích khối lượng lớn dữ liệu đồng thời lưu trú chúng trên nhiều cơ sở dữ liệu khác nhau.

Cũng theo Data - Flair Data mining là một trong những lợi thế của các công ty trong ngành sản xuất, kinh doanh, marketing nếu họ biết cách ứng dụng hợp lý để tăng hiệu quả hoạt động. Do đó, nhu cầu xây dựng một hệ thống Data minning tiêu chuẩn ngày càng tăng cao. Các quy trình, mô hình Data mining phải có độ tin cậy cao và tạo điều kiện để các nhà kinh doanh - những ngừoi có thể không nắm rõ kiến thức chuyên môn về khoa học dữ liệu - Có thể sử dụng được.

Khai thác dữ liệu chính là trích xuất thông tin từ bộ dữ liệu khổng lồ. Nói cách khác, khai thác dữ liệu là quy trình khai thác, tiếp thu kiến thức từ dữ liệu. Chính vì vậy Data mining được ứng dụng vào nhiều lĩnh vực khác nhau.

Còn theo SAS - công ty chuyên cung cấp phần mềm, giải pháp lưu trữ và phân tích dữ liệu toàn cầu - Định nghĩa Data mining là quá trình tìm kiếm những chi tiết bất thường, các mẫu, các mô hình, quy luật của dữ liệu và mối tương quan giữa các tập dữ liệu để dự đoán hiệu quả, thiết lập các dự báo. Bằng cách áp dụng một loạt các kỹ thuật khác nhau, thông tin có được từ Data mining sẽ hỗ trợ tăng doanh thu, cắt giảm chi phí, cải thiện mối quan hệ khách hàng, giảm rủi ro,..

Các mẫu trong dữ liệu tiếng Anh gọi là “Data patterns”, là một phần của thống kê mô tả tức là một mẫu từ tổng thế, một mẫu dữ liệu phân tích đang thể hiện điều gì? Cụ thể Data patterns có thể được xác định thông qua các đồ thị đo lường mức độ tập trung, phân tán, biến động, các giá trị ngoại lệ, bất thường của dữ liệu.

Data patterns đóng vai trò cực kỳ quan trọng ở những bước đầu tiên của Data mining cho ta cái nhìn tổng quan về dữ liệu, mục đích của việc thu thập dữ liệu này là gì, tập dữ liệu có ý nghĩa phân tích không, dữ liệu nào cần quan tâm để phân tích để đem lại kết quả dự báo chính xác, dữ liệu nào cần loại bỏ để tránh nhiễu thông tin,..?

Ứng dụng của Data mining

Ngày nay Big Data trỗi dậy và tác động đến mọi ngành, lĩnh vực các công ty phương pháp data mining ngày càng được biết đến, được ứng dụng rộng rãi và nhu cầu cải thiện ngày càng cao để có thể bắt kịp khả năng tính toán, tốc độ phân tích, khối lượng dữ liệu, sự đa dạng của Big Data.

Trong những năm qua sự tiến bộ của công nghệ kỹ thuật cung cấp các phần mềm với khả năng, tốc độ xử lý cực kỳ thông minh, cho phép nhiều công ty vượt ra khỏi các công việc thủ công, tẻ nhạt và tốn thời gian để phân tích dữ liệu nhanh chóng, dễ dàng và tự động. Các bộ dữ liệu được thu thập ngày càng phức tạp, nhưng lại chứa đựng nhiều thông tin hữu ích.

Các công ty bán lẻ, các ngân hàng, tổ chức tín dụng, công ty sản xuất kinh doanh, công ty viễn thông,… đang ứng dụng khai phá dữ liệu để phân tích mọi vấn đề từ tối ưu giá cả. Chương trình khuyến mãi, nhân khẩu học đến phân tích khách hàng, rủi ro, cạnh tranh, marketing đến truyền thông xã hội - ảnh hưởng đến mô hình kinh doanh, mối quan hệ khách hàng, doanh thu, hoạt động kinh doanh toàn tổ chức.

Xét về lợi ích sau cùng của Data mining trong quá trình phân tích dữ liệu:

  • Chọn lọc, xóa bỏ tất cả các dữ liệu không liên quan và trùng lặp trong tập dữ liệu.
  • Xác định các mẫu dữ liệu, dữ liệu có liên quan và dùng các thuật toán để phân tích, tận dụng dữ liệu để dự báo kết quả đầu ra ví dụ như xu hướng, hành vi tiêu dùng.
  • Với Data Mining chúng ta có thể phân tích khối lượng lớn dữ liệu trong thời gian ngắn và sau đó chuyển đổi dữ liệu đó thành thông tin, kiến thức có ý nghĩa.
  • Hỗ trợ ra quyết định tự động.
  • Hỗ trợ giảm thiểu chi phí.
  • Hỗ trợ đưa ra dự báo chính xác .
  • Hỗ trợ giảm thiểu chi phí.
  • Hỗ trợ khả năng thấu hiểu khách hàng.

Thách thức của việc khai phá dữ liệu

Như đã nói ở trên do khối lượng dữ liệu mà mỗi công ty, tổ chức phải thu thập ngày nay cực kỳ lớn và phức tạp, đa dạng vô cùng nhưng lại chứa đựng những thông tin hữu ích đem lại các giá trị tiềm năng. Dưới đây là một số thách thức điển hình.

  • Thách thức của BigData (Khối lượng dữ liệu lớn, sự đa dạng dữ liệu, độ chính xác, tính xác thực của dữ liệu, tố độ xử lý dữ liệu).
  • Thách thức trong việc lựa chọn các công cụ, phương pháp Datamining.
  • Thách thức về mô hình Over - fitting.
  • Chi phí trong việc sử dụng, mở rộng hệ thống Data mining và vấn đề training.
  • Bảo mật thông tin và quyền riêng tư.

Thực hành với bộ dữ liệu thực tế

  1. Chuẩn bị dữ liệu
  2. Làm sạch dữ liệu và lựa chọn biến
  3. Lựa chọn mô hình phù hợp

Dữ liệu sử dụng là westroxbury.csv ở textbook Wiley and SAS Business: Credit Risk Analytics: Measurement Techniques, Applications, and Examples in SAS.

Data Preparation

Các thuật toán Machine Learning đòi hỏi cả features lẫn target phải là đầy đủ. Với dữ liệu trống (missing) thì có thể có nhiều phương pháp thay thế dữ liệu trống (imputation) cho từng loại feature khác nhau. Trước hết chúng ta đánh giá mức độ thiếu của hai nhóm dữ liệu:

#=================================
#      chuẩn bị dữ liệu
#=================================
# tải một số thư viện chính
library(tidyverse)
library(dplyr)
library(knitr)
# xóa  
rm(list = ls())

# Import dữ liệu: 
westroxbury <- read_csv("https://raw.githubusercontent.com/reisanar/datasets/master/WestRoxbury.csv")

 
library(knitr)

westroxbury %>% 
  head() %>% 
  kable()
TOTAL VALUE TAX LOT SQFT YR BUILT GROSS AREA LIVING AREA FLOORS ROOMS BEDROOMS FULL BATH HALF BATH KITCHEN FIREPLACE REMODEL
344.2 4330 9965 1880 2436 1352 2 6 3 1 1 1 0 None
412.6 5190 6590 1945 3108 1976 2 10 4 2 1 1 0 Recent
330.1 4152 7500 1890 2294 1371 2 8 4 1 1 1 0 None
498.6 6272 13773 1957 5032 2608 1 9 5 1 1 1 1 None
331.5 4170 5000 1910 2370 1438 2 7 3 2 0 1 0 None
337.4 4244 5142 1950 2124 1060 1 6 3 1 0 1 1 Old
# Kiểm tra số lượng giá trị missing trong bảng 
sapply(westroxbury %>% select_if(is.character), function(x) {table(x, useNA = "ifany")})
##        REMODEL
## None      4346
## Old        581
## Recent     875
# Kiểm tra tỷ lệ giá trị missing trong biến
sapply(westroxbury %>% select_if(is.numeric), function(x) {sum(is.na(x)) / length(x)})
## TOTAL VALUE         TAX    LOT SQFT    YR BUILT  GROSS AREA LIVING AREA 
##           0           0           0           0           0           0 
##      FLOORS       ROOMS    BEDROOMS   FULL BATH   HALF BATH     KITCHEN 
##           0           0           0           0           0           0 
##   FIREPLACE 
##           0

Tất cả các biến trong bảng dữ liệu đều không có giá trị missing do đó ta không cần phải thực hiện các giải pháp thống kê để thay những giá trị bị missing.

Giải thích sơ qua một chút về ý nghĩa của các biến trong bảng sau:

#---------------------------------------------------
#  Kiểm tra dữ liệu
#---------------------------------------------------

names(westroxbury) # in tên biế
##  [1] "TOTAL VALUE" "TAX"         "LOT SQFT"    "YR BUILT"    "GROSS AREA" 
##  [6] "LIVING AREA" "FLOORS"      "ROOMS"       "BEDROOMS"    "FULL BATH"  
## [11] "HALF BATH"   "KITCHEN"     "FIREPLACE"   "REMODEL"
t(t(names(westroxbury))) # list tên biến
##       [,1]         
##  [1,] "TOTAL VALUE"
##  [2,] "TAX"        
##  [3,] "LOT SQFT"   
##  [4,] "YR BUILT"   
##  [5,] "GROSS AREA" 
##  [6,] "LIVING AREA"
##  [7,] "FLOORS"     
##  [8,] "ROOMS"      
##  [9,] "BEDROOMS"   
## [10,] "FULL BATH"  
## [11,] "HALF BATH"  
## [12,] "KITCHEN"    
## [13,] "FIREPLACE"  
## [14,] "REMODEL"
colnames(westroxbury)[1] <- c("TOTAL_VALUE") # thay đổi tên cột đầu tiên
class(westroxbury$REMODEL) # REMODEL là biến factor
## [1] "character"
class(westroxbury[ ,14]) # tương tự câu trên.
## [1] "tbl_df"     "tbl"        "data.frame"
levels(westroxbury[, 14]) 
## NULL
class(westroxbury$BEDROOMS)
## [1] "numeric"
class(westroxbury[, 1])
## [1] "tbl_df"     "tbl"        "data.frame"

Sau bước kiểm tra dữ liệu, thì chúng ta có thể tạo thêm nhiều biến mới dựa vào biến ban đầu.Việc lựa chọn biến nhiều không hẳn là tốt cho mô hình, kiểm tra mức độ tương quan giữa các biến.

# Sử dụng model.matrix() để chuyển tất cả dữ liệu categorical thành dữ liệu bảng
# Chuyển tập hợp này thành biến giả sau đó chuyển từ ma trận sang khung dữ liệu để làm việc


xtotal <- model.matrix(~ 0 + BEDROOMS + REMODEL, data = westroxbury)

xtotal <- as.data.frame(xtotal)
t(t(names(xtotal))) # kiểm tra tên biến dummy
##      [,1]           
## [1,] "BEDROOMS"     
## [2,] "REMODELNone"  
## [3,] "REMODELOld"   
## [4,] "REMODELRecent"
head(xtotal)
##   BEDROOMS REMODELNone REMODELOld REMODELRecent
## 1        3           1          0             0
## 2        4           0          0             1
## 3        4           1          0             0
## 4        5           1          0             0
## 5        3           1          0             0
## 6        3           0          1             0
xtotal <- xtotal[, -4] # xóa cột thứ 4 trong bảng

Mô hình có quá nhiều biến thường gây khó khăn cho việc thu thập dữ liệu trong tương lai. Trực quan hóa dữ liệu, .. là những phương pháp giúp giảm thiểu biến để dư thừa và giảm chồng chéo thông tin.

Outlier là giá trị ngoại lai, có nhiều nguyên nhân, nhập sai dữ liệu, .. Nếu giá trị nhập sai nằm trong vùng của dữ liệu nó có thể vô hai, nhưng nếu dữ liệu không nằm trong tập dữ liệu sẽ gây hại và làm nhiễu. Một số nhà phân tích sử dụng quy tắc những giá trị mà nằm ngoài giá trị trung bình và 3 lần độ lệch chuẩn sẽ là giá trị ngoại lai.

Missing value trong một bảng dữ liệu thông thường sẽ chứa các bản ghi bị thiếu, nếu số lượng chiếm tỷ lệ thấp thì có thể bỏ qua. Nhưng nếu chúng ta có một lượng lớn các biến thì sẽ ảnh hưởng tương đối lớn đến dữ liệu. Có nhiều cách để bổ sung các giá trị thiếu này, như thay thế bằng giá trị trung bình của biến, hồi quy đơn biến, hay sử dụng giá trị gần nhất, trung vị,…

# Để minh họa các thủ tục dữ liệu bị thiếu trước tiên chuyển một số mục nhập BEBROOMS thành giá trị bị thiếu sau đó điền những giá trị thiếu nà bằng giá trị trung bình của nó.
rows.to.missing <- sample(row.names(westroxbury), 10)
westroxbury[rows.to.missing,]$BEDROOMS <- NA
summary(westroxbury$BEDROOMS) # Hiện tại có 10 giá trị bị thiếu.
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    1.00    3.00    3.00    3.23    4.00    9.00      10
# Giá trị trung bình là 3
# Thay thế những giá trị bị thiếu thành những giá trị trung bình
# sử dụng hàm median() with na.rm = TRUE để chuyển những giá trị bị thiếu thành những giá trị trug bình.
westroxbury[rows.to.missing,]$BEDROOMS <- median(westroxbury$BEDROOMS, na.rm = TRUE)
summary(westroxbury$BEDROOMS)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1.00    3.00    3.00    3.23    4.00    9.00

Phân phối chuẩn và giảm chiều dữ liệu là một yêu cầu thường thấy của người phân tích dữ liệu, để chuẩn hóa một dữ liệu ta lấy giá trị biến trừ đi giá trị trung bình sau đó chia cho độ lệch chuẩn. Hàm Scale() trong R có thể thực hiện thao tác này, đây còn được gọi là Z chuẩn hóa là dạng đưa tất các các biến về cùng một dạng thang đo. Một dạng khác là đưa tất cả các biến về dạng [0,1]. Điều này thực hiện bằng cách trừ đi giá trị nhỏ nhất và sau đó chia cho số lượng quan sát, trong R chúng ta có thể thực hiện bằng hàm rescale(). Hơn hết, chúng ta thay đổi kiểu dữ liệu để thực hiện phân tích tốt hơn.

Dự đoán và overfiting

Trong quá trình học tập có giám sát chúng ta thường muốn biết được hiệu quả của việc học tập này như thế nào khi ứng dụng vào dữ liệu mới. So sánh hiệu suất hoạt động của mô hình. Nếu mô hình học tập ban đầu có quá nhiều biến thì nguy cơ bị overfiting xảy ra cao hơn. Để giải quyết vấn đề bị overfiting chúng ta có thể phân chia dữ liệu của mình thành các lớp dữ liệu khác nhau, việc thực hiện này phải là ngẫu nhiên.

  • Nhóm đào tạo: Dùng để phát triển học tập, xây dựng nhiều mô hình.
  • Nhóm kiểm tra: Được dùng để đánh giá hiệu suất sử dụng của mô hình, so sánh các mô hình và chọn một mô hình tốt nhất để ứng dụng vào thực tế.
  • Nhóm thực tế: Sau khi có được mô hình tốt nhất thì ta ứng dụng mô hình này với dữ liệu mới cần phải dự đoán.
# Sử dụng set.seed() để tạo các nhóm dữ liệu giống nhau trong R
set.seed(1)
## Phân vùng thành 2 nhóm: Đào tạo (60%) và xác nhận (40%)
# lấy ngẫu nhiên 60% để đào tạo và 40% để xác nhận
train.rows <- sample(rownames(westroxbury), dim(westroxbury)[1]*0.6)
# gộp tất cả những cột ID có hàng huấn luyện vào tập huấn luyện
train.data <- westroxbury[train.rows, ]
# Gán các ID hàng chưa có trong tập huấn luyện vào xác thực
valid.rows <- setdiff(rownames(westroxbury), train.rows)
valid.data <- westroxbury[valid.rows, ]
# Mã thay thế để xác thực (chỉ hoạt động khi tên hàng là số)
# Thu thập tất các những cột không có ID hàng huấn luyện vào tập xác thức
#valid.data <- westroxbury[-train.rows, ] # does not work in this case

## phân vùng thành training (50%), validation (30%), test (20%)
# randomly sample 50% of the row IDs for training
train.rows <- sample(rownames(westroxbury), dim(westroxbury)[1]*0.5)
# mẫu 30% ID hàng trong tập xác thực, chỉ lấy từ các bản ghi
# chưa có trong tập huấn luyện
# sử setdiff() để tìm các bản ghi chưa có trong tập huấn luyện
valid.rows <- sample(setdiff(rownames(westroxbury), train.rows),
dim(westroxbury)[1]*0.3)
# chỉ định 20% ID hàng còn lại dùng làm thử nghiệm
test.rows <- setdiff(rownames(westroxbury), union(train.rows, valid.rows))
# Tạo 3 khung dữ liệu bằng cách thu thập tất cả các cột từ các hàng thích hợp
train.data <- westroxbury[train.rows, ]
valid.data <- westroxbury[valid.rows, ]
test.data <- westroxbury[test.rows, ]

Xây dựng mô hình dự đoán

Việc khai thác các thủ tục: Hồi quy đa tuyến:

  1. Xác định mục đích: VD là dự đoán nhà ở ở West Roxbury.
  2. Lấy dữ liệu: Chúng ta sẽ sử dụng bộ dữ liệu nhà ở của West Roxbury.
  3. Khai phá, làm sạch dữ liệu, xử lý tiền dữ liệu.
  4. Giảm kích thước tập dữ liệu (có thể áp dụng phương pháp phân tích thành phần chính để gộp dữ liệu tương tự như (Khu vực, sinh hoạt, phòng ngủ, ).
  5. Xác định nhiệm vụ khai thác dữ liệu: Cụ thể là dự đoán tổng giá trị bằng cách sử dụng cac sbieens dự đoán (đây là một giám sát).
  6. Phân vùng dữ liệu: Phân chia dữ liệu thành các vùng khác nhau để phân tích.
  7. Chọn mô hình phù hợp.
  8. Sử dụng thuật toán trong R: ử dụng hàm lm() để dự đoán giá trị.
reg <- lm(TOTAL_VALUE ~ ., data = westroxbury, subset = train.rows)
tr.res <- data.frame(train.data$TOTAL_VALUE, reg$fitted.values, reg$residuals)
head(tr.res)
##      train.data.TOTAL_VALUE reg.fitted.values reg.residuals
## 1886                  356.7          356.7174  -0.017443731
## 3515                  333.3          333.2672   0.032786258
## 460                   298.6          298.6112  -0.011213163
## 855                   265.3          265.3050  -0.004994979
## 4094                  575.1          575.0798   0.020195188
## 3581                  348.0          347.9750   0.025022051

RMS (RMSE) - root mean squarederror lỗi trung bình bình phương là một hàm chi phí trên cơ sở xác định hiệu suất mô hình trong việc đưa ra dự đáon hoặc tìm ước tính. Giá trị này càng gần với 0, mô hình của càng tốt. RMSE được tính toán trên dữ liệu ước tính/ dự đoán bằng cách so sánh nó với các giá trị thực.

pred <- predict(reg, newdata = valid.data)
vl.res <- data.frame(valid.data$TOTAL_VALUE, pred, residuals =
valid.data$TOTAL_VALUE - pred)
head(vl.res)
##   valid.data.TOTAL_VALUE     pred    residuals
## 1                  318.0 318.0047 -0.004673323
## 2                  498.7 498.6882  0.011815989
## 3                  331.8 331.8371 -0.037078438
## 4                  371.9 371.8998  0.000226353
## 5                  436.2 436.2079 -0.007861767
## 6                  280.2 280.1660  0.034003966

Tính chính xác của mô hình ra sao

library(forecast)
# máy tính tính độ chính xác của bảng đào tạo
accuracy(reg$fitted.values, train.data$TOTAL_VALUE)
##                    ME       RMSE        MAE         MPE        MAPE
## Test set 6.858406e-17 0.02273259 0.01969253 2.70331e-06 0.005303581
# tính độ chính xác của bảng kiểm tra
pred <- predict(reg, newdata = valid.data)
accuracy(pred, valid.data$TOTAL_VALUE)
##                     ME       RMSE        MAE           MPE        MAPE
## Test set -0.0001658837 0.02300693 0.01984708 -9.549559e-05 0.005331568

Chọn mô hình có lỗi thấp nhất trong các mô hình. Sau khi mô hình tốt nhất được chọn thì mô hình đó sẽ áp dụng cho dữ liệu mới để dự đoán tổng giá trị cho những ngôi nhà không xác định.

Kết thúc chương 1 về vấn đề mở đầu với khai phá dữ liệu.

Vẫn còn tiếp

LS0tDQp0aXRsZTogJ0toYWkgcGjDoSBk4buvIGxp4buHdSB0cm9uZyBSc3R1ZGlvJw0KYXV0aG9yOiAnQXV0aG9yOiBOZ3V54buFbiBUaOG7iyBMacOqbicNCnN1YnRpdGxlOiAiUiBNYWNoaW5lIExlYXJuaW5nIFNlcmllcyAoQ2hhcHRlciAxKSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgICNjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4NCiAgICAjIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6ICJmbGF0bHkiDQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQotLS0NCg0KYGBge3Igc2V0dXAsaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gNikNCmBgYA0KDQoNCg0KIyBHaeG7m2kgdGhp4buHdSB24buBIERhdGEgbWluaW5nDQoNCkRhdGFNaW5pbmcgIC0gS2hhaSBwaMOhIGThu68gbGnhu4d1IGzDoCBt4buZdCB04bqtcCBo4bujcCwgbeG7mXQgaOG7hyB0aOG7kW5nIGPDoWMgcGjGsMahbmcgcGjDoXAgdMOtbmggIHRvw6FuLCB0aHXhuq10IHRvw6FuIMSRxrDhu6NjIMOhcCBk4bulbmcgY2hvIGPDoWMgY8ahIHPhu58gZOG7ryBsaeG7h3UgbOG7m24gdsOgIHBo4bupYyB04bqhcCwgbeG7pWMgxJHDrWNoIGzDoCBsb+G6oWkgYuG7jyBjw6FjIGNoaSB0aeG6v3Qgbmfhuqt1IG5oacOqbiwgY2hpIHRp4bq/dCBuZ2/huqFpIGzhu4csIGtow6FtIHBow6EgY8OhYyBt4bqrdSwgbcO0IGjDrG5oLCBxdXkgbHXhuq10IHRp4buBbSDhuqluLCBjw6FjIHRow7RuZyB0aW4gY8OzIGdpw6EgdHLhu4sgdHJvbmcgYuG7mSBk4buvIGxp4buHdS4gRGF0YW1pbmluZyBsw6AgdGjDoG5oIHF14bqjIGPhu6dhIGPDtG5nIG5naOG7hyB0acOqbiB0aeG6v24gbmfDoHkgbmF5LCBsw6AgcXXDoSB0csOsbmgga2jDoW0gcGjDoSBjw6FjIGtp4bq/biB0aOG7qWMgdsO0IGdpw6EgYuG6sW5nIGPDoWNoIHBow6JuIHTDrWNoIGto4buRaSBsxrDhu6NuZyBs4bubbiBk4buvIGxp4buHdSDEkeG7k25nIHRo4budaSBsxrB1IHRyw7ogY2jDum5nIHRyw6puIG5oaeG7gXUgY8ahIHPhu58gZOG7ryBsaeG7h3Uga2jDoWMgbmhhdS4NCg0KQ8WpbmcgdGhlbyAqKkRhdGEgLSBGbGFpcioqIERhdGEgbWluaW5nIGzDoCBt4buZdCB0cm9uZyBuaOG7r25nIGzhu6NpIHRo4bq/IGPhu6dhIGPDoWMgY8O0bmcgdHkgdHJvbmcgbmfDoG5oIHPhuqNuIHh14bqldCwga2luaCBkb2FuaCwgbWFya2V0aW5nIG7hur91IGjhu40gYmnhur90IGPDoWNoIOG7qW5nIGThu6VuZyBo4bujcCBsw70gxJHhu4MgdMSDbmcgaGnhu4d1IHF14bqjIGhv4bqhdCDEkeG7mW5nLiBEbyDEkcOzLCBuaHUgY+G6p3UgeMOieSBk4buxbmcgbeG7mXQgaOG7hyB0aOG7kW5nIERhdGEgbWlubmluZyB0acOqdSBjaHXhuqluIG5nw6B5IGPDoG5nIHTEg25nIGNhby4gQ8OhYyBxdXkgdHLDrG5oLCBtw7QgaMOsbmggRGF0YSBtaW5pbmcgcGjhuqNpIGPDsyDEkeG7mSB0aW4gY+G6rXkgY2FvIHbDoCB04bqhbyDEkWnhu4F1IGtp4buHbiDEkeG7gyBjw6FjIG5ow6Aga2luaCBkb2FuaCAtIG5o4buvbmcgbmfhu6tvaSBjw7MgdGjhu4Mga2jDtG5nIG7huq9tIHLDtSBraeG6v24gdGjhu6ljIGNodXnDqm4gbcO0biB24buBIGtob2EgaOG7jWMgZOG7ryBsaeG7h3UgLSBDw7MgdGjhu4Mgc+G7rSBk4bulbmcgxJHGsOG7o2MuDQoNCktoYWkgdGjDoWMgZOG7ryBsaeG7h3UgY2jDrW5oIGzDoCB0csOtY2ggeHXhuqV0IHRow7RuZyB0aW4gdOG7qyBi4buZIGThu68gbGnhu4d1IGto4buVbmcgbOG7ky4gTsOzaSBjw6FjaCBraMOhYywga2hhaSB0aMOhYyBk4buvIGxp4buHdSBsw6AgcXV5IHRyw6xuaCBraGFpIHRow6FjLCB0aeG6v3AgdGh1IGtp4bq/biB0aOG7qWMgdOG7qyBk4buvIGxp4buHdS4gQ2jDrW5oIHbDrCB24bqteSBEYXRhIG1pbmluZyDEkcaw4bujYyDhu6luZyBk4bulbmcgdsOgbyBuaGnhu4F1IGzEqW5oIHbhu7FjIGtow6FjIG5oYXUuDQoNCkPDsm4gdGhlbyBTQVMgLSBjw7RuZyB0eSBjaHV5w6puIGN1bmcgY+G6pXAgcGjhuqduIG3hu4FtLCBnaeG6o2kgcGjDoXAgbMawdSB0cuG7ryB2w6AgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgdG/DoG4gY+G6p3UgLSDEkOG7i25oIG5naMSpYSBEYXRhIG1pbmluZyBsw6AgcXXDoSB0csOsbmggdMOsbSBraeG6v20gbmjhu69uZyBjaGkgdGnhur90IGLhuqV0IHRoxrDhu51uZywgY8OhYyBt4bqrdSwgY8OhYyBtw7QgaMOsbmgsIHF1eSBsdeG6rXQgY+G7p2EgZOG7ryBsaeG7h3UgdsOgIG3hu5FpIHTGsMahbmcgcXVhbiBnaeG7r2EgY8OhYyB04bqtcCBk4buvIGxp4buHdSDEkeG7gyBk4buxIMSRb8OhbiBoaeG7h3UgcXXhuqMsIHRoaeG6v3QgbOG6rXAgY8OhYyBk4buxIGLDoW8uIELhurFuZyBjw6FjaCDDoXAgZOG7pW5nIG3hu5l0IGxv4bqhdCBjw6FjIGvhu7kgdGh14bqtdCBraMOhYyBuaGF1LCB0aMO0bmcgdGluIGPDsyDEkcaw4bujYyB04burIERhdGEgbWluaW5nIHPhur0gaOG7lyB0cuG7oyB0xINuZyBkb2FuaCB0aHUsIGPhuq90IGdp4bqjbSBjaGkgcGjDrSwgY+G6o2kgdGhp4buHbiBt4buRaSBxdWFuIGjhu4cga2jDoWNoIGjDoG5nLCBnaeG6o20gcuG7p2kgcm8sLi4NCg0KIVtdKEQ6L01hY2hpbmVMZWFybmluZy9kYXRhLnBuZykNCg0KQ8OhYyBt4bqrdSB0cm9uZyBk4buvIGxp4buHdSB0aeG6v25nIEFuaCBn4buNaSBsw6AgIkRhdGEgcGF0dGVybnMiLCBsw6AgbeG7mXQgcGjhuqduIGPhu6dhIHRo4buRbmcga8OqIG3DtCB04bqjIHThu6ljIGzDoCBt4buZdCBt4bqrdSB04burIHThu5VuZyB0aOG6vywgbeG7mXQgbeG6q3UgZOG7ryBsaeG7h3UgcGjDom4gdMOtY2ggxJFhbmcgdGjhu4MgaGnhu4duIMSRaeG7gXUgZ8OsPyBD4bulIHRo4buDICoqRGF0YSBwYXR0ZXJucyoqIGPDsyB0aOG7gyDEkcaw4bujYyB4w6FjIMSR4buLbmggdGjDtG5nIHF1YSBjw6FjIMSR4buTIHRo4buLIMSRbyBsxrDhu51uZyBt4bupYyDEkeG7mSB04bqtcCB0cnVuZywgcGjDom4gdMOhbiwgYmnhur9uIMSR4buZbmcsIGPDoWMgZ2nDoSB0cuG7iyBuZ2/huqFpIGzhu4csIGLhuqV0IHRoxrDhu51uZyBj4bunYSBk4buvIGxp4buHdS4NCg0KKipEYXRhIHBhdHRlcm5zKiogxJHDs25nIHZhaSB0csOyIGPhu7FjIGvhu7MgcXVhbiB0cuG7jW5nIOG7nyBuaOG7r25nIGLGsOG7m2MgxJHhuqd1IHRpw6puIGPhu6dhICoqRGF0YSBtaW5pbmcqKiBjaG8gdGEgY8OhaSBuaMOsbiB04buVbmcgcXVhbiB24buBIGThu68gbGnhu4d1LCBt4bulYyDEkcOtY2ggY+G7p2Egdmnhu4djIHRodSB0aOG6rXAgZOG7ryBsaeG7h3UgbsOgeSBsw6AgZ8OsLCB04bqtcCBk4buvIGxp4buHdSBjw7Mgw70gbmdoxKlhIHBow6JuIHTDrWNoIGtow7RuZywgZOG7ryBsaeG7h3UgbsOgbyBj4bqnbiBxdWFuIHTDom0gxJHhu4MgcGjDom4gdMOtY2ggxJHhu4MgxJFlbSBs4bqhaSBr4bq/dCBxdeG6oyBk4buxIGLDoW8gY2jDrW5oIHjDoWMsIGThu68gbGnhu4d1IG7DoG8gY+G6p24gbG/huqFpIGLhu48gxJHhu4MgdHLDoW5oIG5oaeG7hXUgdGjDtG5nIHRpbiwuLj8NCg0KIyDhu6huZyBk4bulbmcgY+G7p2EgRGF0YSBtaW5pbmcNCg0KTmfDoHkgbmF5IEJpZyBEYXRhIHRy4buXaSBk4bqteSB2w6AgdMOhYyDEkeG7mW5nIMSR4bq/biBt4buNaSBuZ8OgbmgsIGzEqW5oIHbhu7FjIGPDoWMgY8O0bmcgdHkgcGjGsMahbmcgcGjDoXAgZGF0YSBtaW5pbmcgbmfDoHkgY8OgbmcgxJHGsOG7o2MgYmnhur90IMSR4bq/biwgxJHGsOG7o2Mg4bupbmcgZOG7pW5nIHLhu5luZyByw6NpIHbDoCBuaHUgY+G6p3UgY+G6o2kgdGhp4buHbiBuZ8OgeSBjw6BuZyBjYW8gxJHhu4MgY8OzIHRo4buDIGLhuq90IGvhu4twIGto4bqjIG7Eg25nIHTDrW5oIHRvw6FuLCB04buRYyDEkeG7mSBwaMOibiB0w61jaCwga2jhu5FpIGzGsOG7o25nIGThu68gbGnhu4d1LCBz4buxIMSRYSBk4bqhbmcgY+G7p2EgQmlnIERhdGEuDQoNClRyb25nIG5o4buvbmcgbsSDbSBxdWEgc+G7sSB0aeG6v24gYuG7mSBj4bunYSBjw7RuZyBuZ2jhu4cga+G7uSB0aHXhuq10IGN1bmcgY+G6pXAgY8OhYyBwaOG6p24gbeG7gW0gduG7m2kga2jhuqMgbsSDbmcsIHThu5FjIMSR4buZIHjhu60gbMO9IGPhu7FjIGvhu7MgdGjDtG5nIG1pbmgsIGNobyBwaMOpcCBuaGnhu4F1IGPDtG5nIHR5IHbGsOG7o3QgcmEga2jhu49pIGPDoWMgY8O0bmcgdmnhu4djIHRo4bunIGPDtG5nLCB04bq7IG5o4bqhdCB2w6AgdOG7kW4gdGjhu51pIGdpYW4gxJHhu4MgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgbmhhbmggY2jDs25nLCBk4buFIGTDoG5nIHbDoCB04buxIMSR4buZbmcuIEPDoWMgYuG7mSBk4buvIGxp4buHdSDEkcaw4bujYyB0aHUgdGjhuq1wIG5nw6B5IGPDoG5nIHBo4bupYyB04bqhcCwgbmjGsG5nIGzhuqFpIGNo4bupYSDEkeG7sW5nIG5oaeG7gXUgdGjDtG5nIHRpbiBo4buvdSDDrWNoLg0KDQpDw6FjIGPDtG5nIHR5IGLDoW4gbOG6uywgY8OhYyBuZ8OibiBow6BuZywgdOG7lSBjaOG7qWMgdMOtbiBk4bulbmcsIGPDtG5nIHR5IHPhuqNuIHh14bqldCBraW5oIGRvYW5oLCBjw7RuZyB0eSB2aeG7hW4gdGjDtG5nLC4uLiDEkWFuZyDhu6luZyBk4bulbmcga2hhaSBwaMOhIGThu68gbGnhu4d1IMSR4buDIHBow6JuIHTDrWNoIG3hu41pIHbhuqVuIMSR4buBIHThu6sgdOG7kWkgxrB1IGdpw6EgY+G6oy4gQ2jGsMahbmcgdHLDrG5oIGtodXnhur9uIG3Do2ksIG5ow6JuIGto4bqpdSBo4buNYyDEkeG6v24gcGjDom4gdMOtY2gga2jDoWNoIGjDoG5nLCBy4bunaSBybywgY+G6oW5oIHRyYW5oLCBtYXJrZXRpbmcgxJHhur9uIHRydXnhu4FuIHRow7RuZyB4w6MgaOG7mWkgLSDhuqNuaCBoxrDhu59uZyDEkeG6v24gbcO0IGjDrG5oIGtpbmggZG9hbmgsIG3hu5FpIHF1YW4gaOG7hyBraMOhY2ggaMOgbmcsIGRvYW5oIHRodSwgaG/huqF0IMSR4buZbmcga2luaCBkb2FuaCB0b8OgbiB04buVIGNo4bupYy4NCg0KWMOpdCB24buBIGzhu6NpIMOtY2ggc2F1IGPDuW5nIGPhu6dhIERhdGEgbWluaW5nIHRyb25nIHF1w6EgdHLDrG5oIHBow6JuIHTDrWNoIGThu68gbGnhu4d1Og0KDQoqIENo4buNbiBs4buNYywgeMOzYSBi4buPIHThuqV0IGPhuqMgY8OhYyBk4buvIGxp4buHdSBraMO0bmcgbGnDqm4gcXVhbiB2w6AgdHLDuW5nIGzhurdwIHRyb25nIHThuq1wIGThu68gbGnhu4d1Lg0KKiBYw6FjIMSR4buLbmggY8OhYyBt4bqrdSBk4buvIGxp4buHdSwgZOG7ryBsaeG7h3UgY8OzIGxpw6puIHF1YW4gdsOgIGTDuW5nIGPDoWMgdGh14bqtdCB0b8OhbiDEkeG7gyBwaMOibiB0w61jaCwgdOG6rW4gZOG7pW5nIGThu68gbGnhu4d1IMSR4buDIGThu7EgYsOhbyBr4bq/dCBxdeG6oyDEkeG6p3UgcmEgdsOtIGThu6UgbmjGsCB4dSBoxrDhu5tuZywgaMOgbmggdmkgdGnDqnUgZMO5bmcuDQoqIFbhu5tpIERhdGEgTWluaW5nIGNow7puZyB0YSBjw7MgdGjhu4MgcGjDom4gdMOtY2gga2jhu5FpIGzGsOG7o25nIGzhu5tuIGThu68gbGnhu4d1IHRyb25nIHRo4budaSBnaWFuIG5n4bqvbiB2w6Agc2F1IMSRw7MgY2h1eeG7g24gxJHhu5VpIGThu68gbGnhu4d1IMSRw7MgdGjDoG5oIHRow7RuZyB0aW4sIGtp4bq/biB0aOG7qWMgY8OzIMO9IG5naMSpYS4NCiogSOG7lyB0cuG7oyByYSBxdXnhur90IMSR4buLbmggdOG7sSDEkeG7mW5nLg0KKiBI4buXIHRy4bujIGdp4bqjbSB0aGnhu4N1IGNoaSBwaMOtLg0KKiBI4buXIHRy4bujIMSRxrBhIHJhIGThu7EgYsOhbyBjaMOtbmggeMOhYyAuDQoqIEjhu5cgdHLhu6MgZ2nhuqNtIHRoaeG7g3UgY2hpIHBow60uDQoqIEjhu5cgdHLhu6Mga2jhuqMgbsSDbmcgdGjhuqV1IGhp4buDdSBraMOhY2ggaMOgbmcuDQoNCiMgVGjDoWNoIHRo4bupYyBj4bunYSB2aeG7h2Mga2hhaSBwaMOhIGThu68gbGnhu4d1DQpOaMawIMSRw6MgbsOzaSDhu58gdHLDqm4gZG8ga2jhu5FpIGzGsOG7o25nIGThu68gbGnhu4d1IG3DoCBt4buXaSBjw7RuZyB0eSwgdOG7lSBjaOG7qWMgcGjhuqNpIHRodSB0aOG6rXAgbmfDoHkgbmF5IGPhu7FjIGvhu7MgbOG7m24gdsOgIHBo4bupYyB04bqhcCwgxJFhIGThuqFuZyB2w7QgY8O5bmcgbmjGsG5nIGzhuqFpIGNo4bupYSDEkeG7sW5nIG5o4buvbmcgdGjDtG5nIHRpbiBo4buvdSDDrWNoIMSRZW0gbOG6oWkgY8OhYyBnacOhIHRy4buLIHRp4buBbSBuxINuZy4gRMaw4bubaSDEkcOieSBsw6AgbeG7mXQgc+G7kSB0aMOhY2ggdGjhu6ljIMSRaeG7g24gaMOsbmguDQoNCiogVGjDoWNoIHRo4bupYyBj4bunYSBCaWdEYXRhIChLaOG7kWkgbMaw4bujbmcgZOG7ryBsaeG7h3UgbOG7m24sIHPhu7EgxJFhIGThuqFuZyBk4buvIGxp4buHdSwgxJHhu5kgY2jDrW5oIHjDoWMsIHTDrW5oIHjDoWMgdGjhu7FjIGPhu6dhIGThu68gbGnhu4d1LCB04buRIMSR4buZIHjhu60gbMO9IGThu68gbGnhu4d1KS4NCiogVGjDoWNoIHRo4bupYyB0cm9uZyB2aeG7h2MgbOG7sWEgY2jhu41uIGPDoWMgY8O0bmcgY+G7pSwgcGjGsMahbmcgcGjDoXAgRGF0YW1pbmluZy4NCiogVGjDoWNoIHRo4bupYyB24buBIG3DtCBow6xuaCBPdmVyIC0gZml0dGluZy4NCiogQ2hpIHBow60gdHJvbmcgdmnhu4djIHPhu60gZOG7pW5nLCBt4bufIHLhu5luZyBo4buHIHRo4buRbmcgRGF0YSBtaW5pbmcgdsOgIHbhuqVuIMSR4buBIHRyYWluaW5nLg0KKiBC4bqjbyBt4bqtdCB0aMO0bmcgdGluIHbDoCBxdXnhu4FuIHJpw6puZyB0xrAuDQoNCiMgVGjhu7FjIGjDoG5oIHbhu5tpIGLhu5kgZOG7ryBsaeG7h3UgdGjhu7FjIHThur8NCg0KDQoxLiBDaHXhuqluIGLhu4sgZOG7ryBsaeG7h3UNCjIuIEzDoG0gc+G6oWNoIGThu68gbGnhu4d1IHbDoCBs4buxYSBjaOG7jW4gYmnhur9uIA0KMy4gTOG7sWEgY2jhu41uIG3DtCBow6xuaCBwaMO5IGjhu6NwDQoNCg0KROG7ryBsaeG7h3Ugc+G7rSBk4bulbmcgbMOgICoqd2VzdHJveGJ1cnkuY3N2Kiog4bufIHRleHRib29rIFtXaWxleSBhbmQgU0FTIEJ1c2luZXNzOiBDcmVkaXQgUmlzayBBbmFseXRpY3M6IE1lYXN1cmVtZW50IFRlY2huaXF1ZXMsIEFwcGxpY2F0aW9ucywgYW5kIEV4YW1wbGVzIGluIFNBU10oaHR0cDovL3d3dy5jcmVkaXRyaXNrYW5hbHl0aWNzLm5ldC8pLiANCg0KDQojIyBEYXRhIFByZXBhcmF0aW9uDQoNCkPDoWMgdGh14bqtdCB0b8OhbiBNYWNoaW5lIExlYXJuaW5nIMSRw7JpIGjhu49pIGPhuqMgZmVhdHVyZXMgbOG6q24gdGFyZ2V0IHBo4bqjaSBsw6AgxJHhuqd5IMSR4bunLiBW4bubaSBk4buvIGxp4buHdSB0cuG7kW5nIChtaXNzaW5nKSB0aMOsIGPDsyB0aOG7gyBjw7Mgbmhp4buBdSBwaMawxqFuZyBwaMOhcCB0aGF5IHRo4bq/IGThu68gbGnhu4d1IHRy4buRbmcgKGltcHV0YXRpb24pIGNobyB04burbmcgbG/huqFpIGZlYXR1cmUga2jDoWMgbmhhdS4gVHLGsOG7m2MgaOG6v3QgY2jDum5nIHRhIMSRw6FuaCBnacOhIG3hu6ljIMSR4buZIHRoaeG6v3UgY+G7p2EgaGFpIG5ow7NtIGThu68gbGnhu4d1OiANCg0KDQpgYGB7cn0NCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgICAgICBjaHXhuqluIGLhu4sgZOG7ryBsaeG7h3UNCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgdOG6o2kgbeG7mXQgc+G7kSB0aMawIHZp4buHbiBjaMOtbmgNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoa25pdHIpDQojIHjDs2EgIA0Kcm0obGlzdCA9IGxzKCkpDQoNCiMgSW1wb3J0IGThu68gbGnhu4d1OiANCndlc3Ryb3hidXJ5IDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmVpc2FuYXIvZGF0YXNldHMvbWFzdGVyL1dlc3RSb3hidXJ5LmNzdiIpDQoNCiANCmxpYnJhcnkoa25pdHIpDQoNCndlc3Ryb3hidXJ5ICU+JSANCiAgaGVhZCgpICU+JSANCiAga2FibGUoKQ0KDQojIEtp4buDbSB0cmEgc+G7kSBsxrDhu6NuZyBnacOhIHRy4buLIG1pc3NpbmcgdHJvbmcgYuG6o25nIA0Kc2FwcGx5KHdlc3Ryb3hidXJ5ICU+JSBzZWxlY3RfaWYoaXMuY2hhcmFjdGVyKSwgZnVuY3Rpb24oeCkge3RhYmxlKHgsIHVzZU5BID0gImlmYW55Iil9KQ0KDQojIEtp4buDbSB0cmEgdOG7tyBs4buHIGdpw6EgdHLhu4sgbWlzc2luZyB0cm9uZyBiaeG6v24NCnNhcHBseSh3ZXN0cm94YnVyeSAlPiUgc2VsZWN0X2lmKGlzLm51bWVyaWMpLCBmdW5jdGlvbih4KSB7c3VtKGlzLm5hKHgpKSAvIGxlbmd0aCh4KX0pDQoNCmBgYA0KDQpU4bqldCBj4bqjIGPDoWMgYmnhur9uIHRyb25nIGLhuqNuZyBk4buvIGxp4buHdSDEkeG7gXUga2jDtG5nIGPDsyBnacOhIHRy4buLIG1pc3NpbmcgZG8gxJHDsyB0YSBraMO0bmcgY+G6p24gcGjhuqNpIHRo4buxYyBoaeG7h24gY8OhYyBnaeG6o2kgcGjDoXAgdGjhu5FuZyBrw6ogxJHhu4MgdGhheSBuaOG7r25nIGdpw6EgdHLhu4sgYuG7iyBtaXNzaW5nLg0KDQpHaeG6o2kgdGjDrWNoIHPGoSBxdWEgbeG7mXQgY2jDunQgduG7gSDDvSBuZ2jEqWEgY+G7p2EgY8OhYyBiaeG6v24gdHJvbmcgYuG6o25nIHNhdToNCg0KIVtdKEQ6L01hY2hpbmVMZWFybmluZy9iaWVuLnBuZykNCg0KDQpgYGB7cn0NCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgS2nhu4NtIHRyYSBk4buvIGxp4buHdQ0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpuYW1lcyh3ZXN0cm94YnVyeSkgIyBpbiB0w6puIGJp4bq/DQp0KHQobmFtZXMod2VzdHJveGJ1cnkpKSkgIyBsaXN0IHTDqm4gYmnhur9uDQpjb2xuYW1lcyh3ZXN0cm94YnVyeSlbMV0gPC0gYygiVE9UQUxfVkFMVUUiKSAjIHRoYXkgxJHhu5VpIHTDqm4gY+G7mXQgxJHhuqd1IHRpw6puDQpjbGFzcyh3ZXN0cm94YnVyeSRSRU1PREVMKSAjIFJFTU9ERUwgbMOgIGJp4bq/biBmYWN0b3INCmNsYXNzKHdlc3Ryb3hidXJ5WyAsMTRdKSAjIHTGsMahbmcgdOG7sSBjw6J1IHRyw6puLg0KbGV2ZWxzKHdlc3Ryb3hidXJ5WywgMTRdKSANCmNsYXNzKHdlc3Ryb3hidXJ5JEJFRFJPT01TKQ0KY2xhc3Mod2VzdHJveGJ1cnlbLCAxXSkNCg0KYGBgDQoNClNhdSBixrDhu5tjIGtp4buDbSB0cmEgZOG7ryBsaeG7h3UsIHRow6wgY2jDum5nIHRhIGPDsyB0aOG7gyB04bqhbyB0aMOqbSBuaGnhu4F1IGJp4bq/biBt4bubaSBk4buxYSB2w6BvIGJp4bq/biBiYW4gxJHhuqd1LlZp4buHYyBs4buxYSBjaOG7jW4gYmnhur9uIG5oaeG7gXUga2jDtG5nIGjhurNuIGzDoCB04buRdCBjaG8gbcO0IGjDrG5oLCBraeG7g20gdHJhIG3hu6ljIMSR4buZIHTGsMahbmcgcXVhbiBnaeG7r2EgY8OhYyBiaeG6v24uDQoNCmBgYHtyfQ0KDQojIFPhu60gZOG7pW5nIG1vZGVsLm1hdHJpeCgpIMSR4buDIGNodXnhu4NuIHThuqV0IGPhuqMgZOG7ryBsaeG7h3UgY2F0ZWdvcmljYWwgdGjDoG5oIGThu68gbGnhu4d1IGLhuqNuZw0KIyBDaHV54buDbiB04bqtcCBo4bujcCBuw6B5IHRow6BuaCBiaeG6v24gZ2nhuqMgc2F1IMSRw7MgY2h1eeG7g24gdOG7qyBtYSB0cuG6rW4gc2FuZyBraHVuZyBk4buvIGxp4buHdSDEkeG7gyBsw6BtIHZp4buHYw0KDQoNCnh0b3RhbCA8LSBtb2RlbC5tYXRyaXgofiAwICsgQkVEUk9PTVMgKyBSRU1PREVMLCBkYXRhID0gd2VzdHJveGJ1cnkpDQoNCnh0b3RhbCA8LSBhcy5kYXRhLmZyYW1lKHh0b3RhbCkNCnQodChuYW1lcyh4dG90YWwpKSkgIyBraeG7g20gdHJhIHTDqm4gYmnhur9uIGR1bW15DQpoZWFkKHh0b3RhbCkNCnh0b3RhbCA8LSB4dG90YWxbLCAtNF0gIyB4w7NhIGPhu5l0IHRo4bupIDQgdHJvbmcgYuG6o25nDQoNCmBgYA0KDQpNw7QgaMOsbmggY8OzIHF1w6Egbmhp4buBdSBiaeG6v24gdGjGsOG7nW5nIGfDonkga2jDsyBraMSDbiBjaG8gdmnhu4djIHRodSB0aOG6rXAgZOG7ryBsaeG7h3UgdHJvbmcgdMawxqFuZyBsYWkuIFRy4buxYyBxdWFuIGjDs2EgZOG7ryBsaeG7h3UsIC4uIGzDoCBuaOG7r25nIHBoxrDGoW5nIHBow6FwIGdpw7pwIGdp4bqjbSB0aGnhu4N1IGJp4bq/biDEkeG7gyBkxrAgdGjhu6thIHbDoCBnaeG6o20gY2jhu5NuZyBjaMOpbyB0aMO0bmcgdGluLg0KDQoqKk91dGxpZXIqKiBsw6AgZ2nDoSB0cuG7iyBuZ2/huqFpIGxhaSwgY8OzIG5oaeG7gXUgbmd1ecOqbiBuaMOibiwgbmjhuq1wIHNhaSBk4buvIGxp4buHdSwgLi4gTuG6v3UgZ2nDoSB0cuG7iyBuaOG6rXAgc2FpIG7hurFtIHRyb25nIHbDuW5nIGPhu6dhIGThu68gbGnhu4d1IG7DsyBjw7MgdGjhu4MgdsO0IGhhaSwgbmjGsG5nIG7hur91IGThu68gbGnhu4d1IGtow7RuZyBu4bqxbSB0cm9uZyB04bqtcCBk4buvIGxp4buHdSBz4bq9IGfDonkgaOG6oWkgdsOgIGzDoG0gbmhp4buFdS4gTeG7mXQgc+G7kSBuaMOgIHBow6JuIHTDrWNoIHPhu60gZOG7pW5nIHF1eSB04bqvYyBuaOG7r25nIGdpw6EgdHLhu4sgbcOgIG7hurFtIG5nb8OgaSBnacOhIHRy4buLIHRydW5nIGLDrG5oIHbDoCAzIGzhuqduIMSR4buZIGzhu4djaCBjaHXhuqluIHPhur0gbMOgIGdpw6EgdHLhu4sgbmdv4bqhaSBsYWkuDQoNCioqTWlzc2luZyB2YWx1ZSoqIHRyb25nIG3hu5l0IGLhuqNuZyBk4buvIGxp4buHdSB0aMO0bmcgdGjGsOG7nW5nIHPhur0gY2jhu6lhIGPDoWMgYuG6o24gZ2hpIGLhu4sgdGhp4bq/dSwgbuG6v3Ugc+G7kSBsxrDhu6NuZyBjaGnhur9tIHThu7cgbOG7hyB0aOG6pXAgdGjDrCBjw7MgdGjhu4MgYuG7jyBxdWEuIE5oxrBuZyBu4bq/dSBjaMO6bmcgdGEgY8OzIG3hu5l0IGzGsOG7o25nIGzhu5tuIGPDoWMgYmnhur9uIHRow6wgc+G6vSDhuqNuaCBoxrDhu59uZyB0xrDGoW5nIMSR4buRaSBs4bubbiDEkeG6v24gZOG7ryBsaeG7h3UuIEPDsyBuaGnhu4F1IGPDoWNoIMSR4buDIGLhu5Ugc3VuZyBjw6FjIGdpw6EgdHLhu4sgdGhp4bq/dSBuw6B5LCBuaMawIHRoYXkgdGjhur8gYuG6sW5nIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgYmnhur9uLCBo4buTaSBxdXkgxJHGoW4gYmnhur9uLCBoYXkgc+G7rSBk4bulbmcgZ2nDoSB0cuG7iyBn4bqnbiBuaOG6pXQsIHRydW5nIHbhu4ssLi4uDQoNCg0KYGBge3J9DQojIMSQ4buDIG1pbmggaOG7jWEgY8OhYyB0aOG7pyB04bulYyBk4buvIGxp4buHdSBi4buLIHRoaeG6v3UgdHLGsOG7m2MgdGnDqm4gY2h1eeG7g24gbeG7mXQgc+G7kSBt4bulYyBuaOG6rXAgQkVCUk9PTVMgdGjDoG5oIGdpw6EgdHLhu4sgYuG7iyB0aGnhur91IHNhdSDEkcOzIMSRaeG7gW4gbmjhu69uZyBnacOhIHRy4buLIHRoaeG6v3UgbsOgIGLhurFuZyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIG7Dsy4NCnJvd3MudG8ubWlzc2luZyA8LSBzYW1wbGUocm93Lm5hbWVzKHdlc3Ryb3hidXJ5KSwgMTApDQp3ZXN0cm94YnVyeVtyb3dzLnRvLm1pc3NpbmcsXSRCRURST09NUyA8LSBOQQ0Kc3VtbWFyeSh3ZXN0cm94YnVyeSRCRURST09NUykgIyBIaeG7h24gdOG6oWkgY8OzIDEwIGdpw6EgdHLhu4sgYuG7iyB0aGnhur91Lg0KIyBHacOhIHRy4buLIHRydW5nIGLDrG5oIGzDoCAzDQojIFRoYXkgdGjhur8gbmjhu69uZyBnacOhIHRy4buLIGLhu4sgdGhp4bq/dSB0aMOgbmggbmjhu69uZyBnacOhIHRy4buLIHRydW5nIGLDrG5oDQojIHPhu60gZOG7pW5nIGjDoG0gbWVkaWFuKCkgd2l0aCBuYS5ybSA9IFRSVUUgxJHhu4MgY2h1eeG7g24gbmjhu69uZyBnacOhIHRy4buLIGLhu4sgdGhp4bq/dSB0aMOgbmggbmjhu69uZyBnacOhIHRy4buLIHRydWcgYsOsbmguDQp3ZXN0cm94YnVyeVtyb3dzLnRvLm1pc3NpbmcsXSRCRURST09NUyA8LSBtZWRpYW4od2VzdHJveGJ1cnkkQkVEUk9PTVMsIG5hLnJtID0gVFJVRSkNCnN1bW1hcnkod2VzdHJveGJ1cnkkQkVEUk9PTVMpDQpgYGANCg0KKipQaMOibiBwaOG7kWkgY2h14bqpbiB2w6AgZ2nhuqNtIGNoaeG7gXUgZOG7ryBsaeG7h3UqKiBsw6AgbeG7mXQgecOqdSBj4bqndSB0aMaw4budbmcgdGjhuqV5IGPhu6dhIG5nxrDhu51pIHBow6JuIHTDrWNoIGThu68gbGnhu4d1LCDEkeG7gyBjaHXhuqluIGjDs2EgbeG7mXQgZOG7ryBsaeG7h3UgdGEgbOG6pXkgZ2nDoSB0cuG7iyBiaeG6v24gdHLhu6sgxJFpIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggc2F1IMSRw7MgY2hpYSBjaG8gxJHhu5kgbOG7h2NoIGNodeG6qW4uIEjDoG0gKipTY2FsZSgpKiogdHJvbmcgUiBjw7MgdGjhu4MgdGjhu7FjIGhp4buHbiB0aGFvIHTDoWMgbsOgeSwgxJHDonkgY8OybiDEkcaw4bujYyBn4buNaSBsw6AgKipaKiogY2h14bqpbiBow7NhIGzDoCBk4bqhbmcgxJHGsGEgdOG6pXQgY8OhYyBjw6FjIGJp4bq/biB24buBIGPDuW5nIG3hu5l0IGThuqFuZyB0aGFuZyDEkW8uIE3hu5l0IGThuqFuZyBraMOhYyBsw6AgxJHGsGEgdOG6pXQgY+G6oyBjw6FjIGJp4bq/biB24buBIGThuqFuZyBbMCwxXS4gxJBp4buBdSBuw6B5IHRo4buxYyBoaeG7h24gYuG6sW5nIGPDoWNoIHRy4burIMSRaSBnacOhIHRy4buLIG5o4buPIG5o4bqldCB2w6Agc2F1IMSRw7MgY2hpYSBjaG8gc+G7kSBsxrDhu6NuZyBxdWFuIHPDoXQsIHRyb25nIFIgY2jDum5nIHRhIGPDsyB0aOG7gyB0aOG7sWMgaGnhu4duIGLhurFuZyBow6BtIHJlc2NhbGUoKS4gSMahbiBo4bq/dCwgY2jDum5nIHRhIHRoYXkgxJHhu5VpIGtp4buDdSBk4buvIGxp4buHdSDEkeG7gyB0aOG7sWMgaGnhu4duIHBow6JuIHTDrWNoIHThu5F0IGjGoW4uDQoNCiMjIEThu7EgxJFvw6FuIHbDoCBvdmVyZml0aW5nDQoNClRyb25nIHF1w6EgdHLDrG5oIGjhu41jIHThuq1wIGPDsyBnacOhbSBzw6F0IGNow7puZyB0YSB0aMaw4budbmcgbXXhu5FuIGJp4bq/dCDEkcaw4bujYyBoaeG7h3UgcXXhuqMgY+G7p2Egdmnhu4djIGjhu41jIHThuq1wIG7DoHkgbmjGsCB0aOG6vyBuw6BvIGtoaSDhu6luZyBk4bulbmcgdsOgbyBk4buvIGxp4buHdSBt4bubaS4gU28gc8OhbmggaGnhu4d1IHN14bqldCBob+G6oXQgxJHhu5luZyBj4bunYSBtw7QgaMOsbmguIE7hur91IG3DtCBow6xuaCBo4buNYyB04bqtcCBiYW4gxJHhuqd1IGPDsyBxdcOhIG5oaeG7gXUgYmnhur9uIHRow6wgbmd1eSBjxqEgYuG7iyBvdmVyZml0aW5nIHjhuqN5IHJhIGNhbyBoxqFuLiDEkOG7gyBnaeG6o2kgcXV54bq/dCB24bqlbiDEkeG7gSBi4buLIG92ZXJmaXRpbmcgY2jDum5nIHRhIGPDsyB0aOG7gyBwaMOibiBjaGlhIGThu68gbGnhu4d1IGPhu6dhIG3DrG5oIHRow6BuaCBjw6FjIGzhu5twIGThu68gbGnhu4d1IGtow6FjIG5oYXUsIHZp4buHYyB0aOG7sWMgaGnhu4duIG7DoHkgcGjhuqNpIGzDoCBuZ+G6q3Ugbmhpw6puLg0KDQoqIE5ow7NtIMSRw6BvIHThuqFvOiBEw7luZyDEkeG7gyBwaMOhdCB0cmnhu4NuIGjhu41jIHThuq1wLCB4w6J5IGThu7FuZyBuaGnhu4F1IG3DtCBow6xuaC4NCiogTmjDs20ga2nhu4NtIHRyYTogxJDGsOG7o2MgZMO5bmcgxJHhu4MgxJHDoW5oIGdpw6EgaGnhu4d1IHN14bqldCBz4butIGThu6VuZyBj4bunYSBtw7QgaMOsbmgsIHNvIHPDoW5oIGPDoWMgbcO0IGjDrG5oIHbDoCBjaOG7jW4gbeG7mXQgbcO0IGjDrG5oIHThu5F0IG5o4bqldCDEkeG7gyDhu6luZyBk4bulbmcgdsOgbyB0aOG7sWMgdOG6vy4NCiogTmjDs20gdGjhu7FjIHThur86IFNhdSBraGkgY8OzIMSRxrDhu6NjIG3DtCBow6xuaCB04buRdCBuaOG6pXQgdGjDrCB0YSDhu6luZyBk4bulbmcgbcO0IGjDrG5oIG7DoHkgduG7m2kgZOG7ryBsaeG7h3UgbeG7m2kgY+G6p24gcGjhuqNpIGThu7EgxJFvw6FuLg0KDQohW10oRDovTWFjaGluZUxlYXJuaW5nL2NodW9pLnBuZykNCg0KYGBge3J9DQojIFPhu60gZOG7pW5nIHNldC5zZWVkKCkgxJHhu4MgdOG6oW8gY8OhYyBuaMOzbSBk4buvIGxp4buHdSBnaeG7kW5nIG5oYXUgdHJvbmcgUg0Kc2V0LnNlZWQoMSkNCiMjIFBow6JuIHbDuW5nIHRow6BuaCAyIG5ow7NtOiDEkMOgbyB04bqhbyAoNjAlKSB2w6AgeMOhYyBuaOG6rW4gKDQwJSkNCiMgbOG6pXkgbmfhuqt1IG5oacOqbiA2MCUgxJHhu4MgxJHDoG8gdOG6oW8gdsOgIDQwJSDEkeG7gyB4w6FjIG5o4bqtbg0KdHJhaW4ucm93cyA8LSBzYW1wbGUocm93bmFtZXMod2VzdHJveGJ1cnkpLCBkaW0od2VzdHJveGJ1cnkpWzFdKjAuNikNCiMgZ+G7mXAgdOG6pXQgY+G6oyBuaOG7r25nIGPhu5l0IElEIGPDsyBow6BuZyBodeG6pW4gbHV54buHbiB2w6BvIHThuq1wIGh14bqlbiBsdXnhu4duDQp0cmFpbi5kYXRhIDwtIHdlc3Ryb3hidXJ5W3RyYWluLnJvd3MsIF0NCiMgR8OhbiBjw6FjIElEIGjDoG5nIGNoxrBhIGPDsyB0cm9uZyB04bqtcCBodeG6pW4gbHV54buHbiB2w6BvIHjDoWMgdGjhu7FjDQp2YWxpZC5yb3dzIDwtIHNldGRpZmYocm93bmFtZXMod2VzdHJveGJ1cnkpLCB0cmFpbi5yb3dzKQ0KdmFsaWQuZGF0YSA8LSB3ZXN0cm94YnVyeVt2YWxpZC5yb3dzLCBdDQojIE3DoyB0aGF5IHRo4bq/IMSR4buDIHjDoWMgdGjhu7FjIChjaOG7iSBob+G6oXQgxJHhu5luZyBraGkgdMOqbiBow6BuZyBsw6Agc+G7kSkNCiMgVGh1IHRo4bqtcCB04bqldCBjw6FjIG5o4buvbmcgY+G7mXQga2jDtG5nIGPDsyBJRCBow6BuZyBodeG6pW4gbHV54buHbiB2w6BvIHThuq1wIHjDoWMgdGjhu6ljDQojdmFsaWQuZGF0YSA8LSB3ZXN0cm94YnVyeVstdHJhaW4ucm93cywgXSAjIGRvZXMgbm90IHdvcmsgaW4gdGhpcyBjYXNlDQoNCiMjIHBow6JuIHbDuW5nIHRow6BuaCB0cmFpbmluZyAoNTAlKSwgdmFsaWRhdGlvbiAoMzAlKSwgdGVzdCAoMjAlKQ0KIyByYW5kb21seSBzYW1wbGUgNTAlIG9mIHRoZSByb3cgSURzIGZvciB0cmFpbmluZw0KdHJhaW4ucm93cyA8LSBzYW1wbGUocm93bmFtZXMod2VzdHJveGJ1cnkpLCBkaW0od2VzdHJveGJ1cnkpWzFdKjAuNSkNCiMgbeG6q3UgMzAlIElEIGjDoG5nIHRyb25nIHThuq1wIHjDoWMgdGjhu7FjLCBjaOG7iSBs4bqleSB04burIGPDoWMgYuG6o24gZ2hpDQojIGNoxrBhIGPDsyB0cm9uZyB04bqtcCBodeG6pW4gbHV54buHbg0KIyBz4butIHNldGRpZmYoKSDEkeG7gyB0w6xtIGPDoWMgYuG6o24gZ2hpIGNoxrBhIGPDsyB0cm9uZyB04bqtcCBodeG6pW4gbHV54buHbg0KdmFsaWQucm93cyA8LSBzYW1wbGUoc2V0ZGlmZihyb3duYW1lcyh3ZXN0cm94YnVyeSksIHRyYWluLnJvd3MpLA0KZGltKHdlc3Ryb3hidXJ5KVsxXSowLjMpDQojIGNo4buJIMSR4buLbmggMjAlIElEIGjDoG5nIGPDsm4gbOG6oWkgZMO5bmcgbMOgbSB0aOG7rSBuZ2hp4buHbQ0KdGVzdC5yb3dzIDwtIHNldGRpZmYocm93bmFtZXMod2VzdHJveGJ1cnkpLCB1bmlvbih0cmFpbi5yb3dzLCB2YWxpZC5yb3dzKSkNCiMgVOG6oW8gMyBraHVuZyBk4buvIGxp4buHdSBi4bqxbmcgY8OhY2ggdGh1IHRo4bqtcCB04bqldCBj4bqjIGPDoWMgY+G7mXQgdOG7qyBjw6FjIGjDoG5nIHRow61jaCBo4bujcA0KdHJhaW4uZGF0YSA8LSB3ZXN0cm94YnVyeVt0cmFpbi5yb3dzLCBdDQp2YWxpZC5kYXRhIDwtIHdlc3Ryb3hidXJ5W3ZhbGlkLnJvd3MsIF0NCnRlc3QuZGF0YSA8LSB3ZXN0cm94YnVyeVt0ZXN0LnJvd3MsIF0NCmBgYA0KDQojIyBYw6J5IGThu7FuZyBtw7QgaMOsbmggZOG7sSDEkW/DoW4NCg0KVmnhu4djIGtoYWkgdGjDoWMgY8OhYyB0aOG7pyB04bulYzogSOG7k2kgcXV5IMSRYSB0dXnhur9uOg0KDQoxLiBYw6FjIMSR4buLbmggbeG7pWMgxJHDrWNoOiBWRCBsw6AgZOG7sSDEkW/DoW4gbmjDoCDhu58g4bufIFdlc3QgUm94YnVyeS4NCjIuIEzhuqV5IGThu68gbGnhu4d1OiBDaMO6bmcgdGEgc+G6vSBz4butIGThu6VuZyBi4buZIGThu68gbGnhu4d1IG5ow6Ag4bufIGPhu6dhIFdlc3QgUm94YnVyeS4NCjMuIEtoYWkgcGjDoSwgbMOgbSBz4bqhY2ggZOG7ryBsaeG7h3UsIHjhu60gbMO9IHRp4buBbiBk4buvIGxp4buHdS4NCjQuIEdp4bqjbSBrw61jaCB0aMaw4bubYyB04bqtcCBk4buvIGxp4buHdSAoY8OzIHRo4buDIMOhcCBk4bulbmcgcGjGsMahbmcgcGjDoXAgcGjDom4gdMOtY2ggdGjDoG5oIHBo4bqnbiBjaMOtbmggxJHhu4MgZ+G7mXAgZOG7ryBsaeG7h3UgdMawxqFuZyB04buxIG5oxrAgKEtodSB24buxYywgc2luaCBob+G6oXQsIHBow7JuZyBuZ+G7pywgICApLg0KNS4gWMOhYyDEkeG7i25oIG5oaeG7h20gduG7pSBraGFpIHRow6FjIGThu68gbGnhu4d1OiBD4bulIHRo4buDIGzDoCBk4buxIMSRb8OhbiB04buVbmcgZ2nDoSB0cuG7iyBi4bqxbmcgY8OhY2ggc+G7rSBk4bulbmcgY2FjIHNiaWVlbnMgZOG7sSDEkW/DoW4gKMSRw6J5IGzDoCBt4buZdCBnacOhbSBzw6F0KS4NCjYuIFBow6JuIHbDuW5nIGThu68gbGnhu4d1OiBQaMOibiBjaGlhIGThu68gbGnhu4d1IHRow6BuaCBjw6FjIHbDuW5nIGtow6FjIG5oYXUgxJHhu4MgcGjDom4gdMOtY2guDQo3LiBDaOG7jW4gbcO0IGjDrG5oIHBow7kgaOG7o3AuDQo4LiBT4butIGThu6VuZyB0aHXhuq10IHRvw6FuIHRyb25nIFI6IOG7rSBk4bulbmcgaMOgbSBsbSgpIMSR4buDIGThu7EgxJFvw6FuIGdpw6EgdHLhu4suDQoNCg0KYGBge3J9DQpyZWcgPC0gbG0oVE9UQUxfVkFMVUUgfiAuLCBkYXRhID0gd2VzdHJveGJ1cnksIHN1YnNldCA9IHRyYWluLnJvd3MpDQp0ci5yZXMgPC0gZGF0YS5mcmFtZSh0cmFpbi5kYXRhJFRPVEFMX1ZBTFVFLCByZWckZml0dGVkLnZhbHVlcywgcmVnJHJlc2lkdWFscykNCmhlYWQodHIucmVzKQ0KDQpgYGANClJNUyAoUk1TRSkgLSByb290IG1lYW4gc3F1YXJlZGVycm9yIGzhu5dpIHRydW5nIGLDrG5oIGLDrG5oIHBoxrDGoW5nIGzDoCBt4buZdCBow6BtIGNoaSBwaMOtIHRyw6puIGPGoSBz4bufIHjDoWMgxJHhu4tuaCBoaeG7h3Ugc3XhuqV0IG3DtCBow6xuaCB0cm9uZyB2aeG7h2MgxJHGsGEgcmEgZOG7sSDEkcOhb24gaG/hurdjIHTDrG0gxrDhu5tjIHTDrW5oLiBHacOhIHRy4buLIG7DoHkgY8OgbmcgZ+G6p24gduG7m2kgMCwgbcO0IGjDrG5oIGPhu6dhIGPDoG5nIHThu5F0LiBSTVNFIMSRxrDhu6NjIHTDrW5oIHRvw6FuIHRyw6puIGThu68gbGnhu4d1IMaw4bubYyB0w61uaC8gZOG7sSDEkW/DoW4gYuG6sW5nIGPDoWNoIHNvIHPDoW5oIG7DsyB24bubaSBjw6FjIGdpw6EgdHLhu4sgdGjhu7FjLg0KDQpgYGB7cn0NCnByZWQgPC0gcHJlZGljdChyZWcsIG5ld2RhdGEgPSB2YWxpZC5kYXRhKQ0KdmwucmVzIDwtIGRhdGEuZnJhbWUodmFsaWQuZGF0YSRUT1RBTF9WQUxVRSwgcHJlZCwgcmVzaWR1YWxzID0NCnZhbGlkLmRhdGEkVE9UQUxfVkFMVUUgLSBwcmVkKQ0KaGVhZCh2bC5yZXMpDQpgYGANCg0KVMOtbmggY2jDrW5oIHjDoWMgY+G7p2EgbcO0IGjDrG5oIHJhIHNhbw0KDQpgYGB7cn0NCmxpYnJhcnkoZm9yZWNhc3QpDQojIG3DoXkgdMOtbmggdMOtbmggxJHhu5kgY2jDrW5oIHjDoWMgY+G7p2EgYuG6o25nIMSRw6BvIHThuqFvDQphY2N1cmFjeShyZWckZml0dGVkLnZhbHVlcywgdHJhaW4uZGF0YSRUT1RBTF9WQUxVRSkNCiMgdMOtbmggxJHhu5kgY2jDrW5oIHjDoWMgY+G7p2EgYuG6o25nIGtp4buDbSB0cmENCnByZWQgPC0gcHJlZGljdChyZWcsIG5ld2RhdGEgPSB2YWxpZC5kYXRhKQ0KYWNjdXJhY3kocHJlZCwgdmFsaWQuZGF0YSRUT1RBTF9WQUxVRSkNCmBgYA0KDQpDaOG7jW4gbcO0IGjDrG5oIGPDsyBs4buXaSB0aOG6pXAgbmjhuqV0IHRyb25nIGPDoWMgbcO0IGjDrG5oLiBTYXUga2hpIG3DtCBow6xuaCB04buRdCBuaOG6pXQgxJHGsOG7o2MgY2jhu41uIHRow6wgbcO0IGjDrG5oIMSRw7Mgc+G6vSDDoXAgZOG7pW5nIGNobyBk4buvIGxp4buHdSBt4bubaSDEkeG7gyBk4buxIMSRb8OhbiB04buVbmcgZ2nDoSB0cuG7iyBjaG8gbmjhu69uZyBuZ8O0aSBuaMOgIGtow7RuZyB4w6FjIMSR4buLbmguDQoNCg0KS+G6v3QgdGjDumMgY2jGsMahbmcgMSB24buBIHbhuqVuIMSR4buBIG3hu58gxJHhuqd1IHbhu5tpIGtoYWkgcGjDoSBk4buvIGxp4buHdS4NCg0KDQoqKlbhuqtuIGPDsm4gdGnhur9wKioNCg0KDQoNCg0KDQo=