Nhiệm vụ 3.1


Tóm tắt

Thực hiện các thao tác một số lệch cơ bản và rút trích dữ liệu trên file xlsx ” population-and-demography.xlsx”. File phân tích tổng dân số của các quốc gia theo độ tuổi qua các năm từ năm 1950 - 2021

Đọc dữ liệu từ file csv

#Để vừa chạy dữ liệu đồng thời hiển thị chữ ta nhấn tổ hợp phím CTRL+ALT+I sau đó nhập {r message=TRUE, warning=FALSE}

# Gán dữ liệu của file csv vào a, sau đó đọc dữ liệu từ file csv bằng câu lệnh
a <- read.csv(file.choose(), header = T) # header = T là lấy dữ liệu từ dòng đầu tiên của file csv

Thông tin tổng quan của bộ dữ liệu

Các thông tin tổng quan về dataset:

  • Là một data frame

  • Có 24 cột tương đương 24 biến

  • Các cột lần lượt là:

    • Country.name: Tên các quốc gia

    • Year: năm lấy số liệu

    • Population: Tổng dân số

    • Population.of.children.under.the.age.of.1: Dân số dưới 1 tuổi

    • Population.of.children.under.the.age.of.5: Dân số dưới 5 tuổi

    • Population.of.children.under.the.age.of.15: Dân số dưới 15 tuổi

    • Population.under.the.age.of.25: Dân số dưới 25 tuổi

    • Population.aged.15.to.64.years: Dân số từ 15 đến 64 tuổi

    • Population.older.than.15.years: Dân số lớn hơn 15 tuổi

    • Population.older.than.18.years: Dân số lớn hơn 18 tuổi

    • Population.at.age.1: Dân số tại độ tuổi 1

    • Population.aged.1.to.4.years: Dân số từ 1 đến 4 tuổi

    • Population.aged.5.to.9.years: Dân số từ 5 đến 9 tuổi

    • Population.aged.10.to.14.years: Dân số từ 10 đến 14 tuổi

    • Population.aged.15.to.19.years: Dân số từ 15 đến 19 tuổi

    • Population.aged.20.to.29.years: Dân số từ 20 đến 29 tuổi

    • Population.aged.30.to.39.years: Dân số từ 30 đến 39 tuổi

    • Population.aged.40.to.49.years: Dân số từ 40 đến 49 tuổi

    • Population.aged.50.to.59.years: Dân số từ 50 đến 59 tuổi

    • Population.aged.60.to.69.years: Dân số từ 60 đến 69 tuổi

    • Population.aged.70.to.79.years: Dân số từ 70 đến 79 tuổi

    • Population.aged.80.to.89.years: Dân số từ 80 đến 89 tuổi

    • Population.aged.90.to.99.years: Dân số từ 90 đến 99 tuổi

    • Population.older.than.100.years: Dân số lớn hơn 100 tuổi

  • Có 18288 hàng tương đương 18288 quan sát

  • Data không có dữ liệu trống

# Kiểm tra xem "a" có phải là data frame hay không, nếu đúng thì kết quả trả về TRUE và ngược lại, kiểm tra bằng câu lệnh
is.data.frame(a)
## [1] TRUE
# Hiển thị độ dài của dữ liệu, tức là số cột của "a"
length(a)
## [1] 24
# Hiển thị tên các cột của "a" bằng câu lệnh
names(a)
##  [1] "Country.name"                              
##  [2] "Year"                                      
##  [3] "Population"                                
##  [4] "Population.of.children.under.the.age.of.1" 
##  [5] "Population.of.children.under.the.age.of.5" 
##  [6] "Population.of.children.under.the.age.of.15"
##  [7] "Population.under.the.age.of.25"            
##  [8] "Population.aged.15.to.64.years"            
##  [9] "Population.older.than.15.years"            
## [10] "Population.older.than.18.years"            
## [11] "Population.at.age.1"                       
## [12] "Population.aged.1.to.4.years"              
## [13] "Population.aged.5.to.9.years"              
## [14] "Population.aged.10.to.14.years"            
## [15] "Population.aged.15.to.19.years"            
## [16] "Population.aged.20.to.29.years"            
## [17] "Population.aged.30.to.39.years"            
## [18] "Population.aged.40.to.49.years"            
## [19] "Population.aged.50.to.59.years"            
## [20] "Population.aged.60.to.69.years"            
## [21] "Population.aged.70.to.79.years"            
## [22] "Population.aged.80.to.89.years"            
## [23] "Population.aged.90.to.99.years"            
## [24] "Population.older.than.100.years"
# Hiển thị số hàng và số cột của "a"
dim(a)
## [1] 18288    24
# Kiểm tra tổng số ô trống của dữ liệu bằng câu lệnh
sum(is.na(a))
## [1] 0

Đổi tên cho các biến

# Đổi tên các biến để thuận tiện thao tác trên dữ liệu "a"
a <- rename(a,country = Country.name ,pop = Population, year = Year) # đổi tên các cột Country.name, Population và Year thành country, pop và year

a <- a %>% rename(pop0 = Population.of.children.under.the.age.of.15 ,pop2 = Population.aged.60.to.69.years ,pop3 = Population.aged.70.to.79.years ,pop4 = Population.aged.80.to.89.years ,pop6 = Population.aged.90.to.99.years) ## đổi tên thay thế lần lượt cho các cột Population.of.children.under.the.age.of.15, Population.aged.60.to.69.years, Population.aged.70.to.79.years, Population.aged.80.to.89.years, Population.aged.90.to.99

Phân tích các quốc gia và dân số

Bộ dữ liệu “a” là bộ dữ liệu lớn chứa thông tin về các quốc gia trên thế giới về dân số và số dân thuộc các nhóm tuổi khác nhau. Vì vậy, ta tiến hành rút trích dữ liệu từ đó để dễ dàng thao tác

  • Thực hiện rút trích 5 quốc gia thuộc Đông Nam Á để phân tích, bao gồm các quốc gia: Combodia, Laos, Myanmar, Thailand, Vietnam
# Gán dữ liệu được trích vào n, sau đó lọc bộ dữ liệu "a"
n <- a %>% filter(country %in% c('Vietnam','Colombia','Laos','Myanmar','Thailand')) # lọc các quốc gia trong cột country và giữ các hàng của cột country name bắt đầu bằng chữ 'Vietnam','Colombia','Laos','Myanmar','Thailand'
  • Thực hiện rút trích tổng dân số và dân số thuộc 5 nhóm tuổi khác nhau
n <- n %>% select(country,year,pop,pop0,pop2,pop3,pop4,pop6)# lọc các cột country, year, pop, pop0, pop2, pop3, pop4 và pop6
n

Tóm tắt bộ dữ liệu mới

Bộ dữ liệu “n” là bộ dữ liệu mới phân tích về tổng dân số và dân số của 5 độ tuổi ở 5 quốc gia khác nhau bao gồm:

  • country: tên 5 quốc gia cần phân tích

  • year: năm lấy dữ liệu

  • pop: tổng dân số

  • pop0: dân số của trẻ em dưới 15 tuổi

  • pop2: dân số từ 15 đến 64 tuổi

  • pop3: dân số từ 60 đến 69 tuổi

  • pop4: dân số có độ tuổi từ 70 đến 79

  • pop6: dân số từ 100 tuổi trở lên

Bộ dữ liệu “n” gồm 360 quan sát ( 360 hàng) và 8 biến ( 8 cột)

Tạo cột dữ liệu mới từ bộ dữ liệu “n”

Tiến hành thực hiện các lệnh để tạo thêm biến mới cho bộ dữ liệu n, kết quả của việc tạo ra cột dữ liệu mới là bộ dữ liệu n xuất hiện thêm 3 biến mới là:

  • pop7: Population.older.than.60.years - là dân số lớn hơn 60 tuổi

  • ttds: tỷ trọng dân số nhóm tuổi dưới tuổi lao động ( dưới 15 tuổi)

  • ttds1: tỷ trọng dân số nhóm tuổi trên lao động ( từ 60 trở lên)

n <- n %>% mutate(pop7 = pop2 + pop3 + pop4 + pop6) # dân số lớn hơn 60 tuổi được tính bằng tổng số dân của các nhóm tuổi pop2,pop3,pop4,pop6
n <- n %>% mutate(ttds = ( pop0 / pop ) * 100, ttds1 = ( pop7 / pop ) * 100) # tỷ trọng dân số thuộc nhóm tuổi i được tính bằng (số dân thuộc nhóm tuổi i/tổng số dân)*100
str(n)
## 'data.frame':    360 obs. of  11 variables:
##  $ country: chr  "Colombia" "Colombia" "Colombia" "Colombia" ...
##  $ year   : int  1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 ...
##  $ pop    : num  11769747 12087061 12419969 12767245 13130655 ...
##  $ pop0   : int  5147615 5322337 5508316 5706160 5913987 6130810 6356226 6590926 6833562 7083173 ...
##  $ pop2   : int  368246 376270 384912 393767 402711 411778 420790 429784 439036 448944 ...
##  $ pop3   : int  175991 176932 177867 179904 183683 189050 195604 203238 211350 219122 ...
##  $ pop4   : int  46988 48978 50662 51982 52878 53454 53873 54246 54707 55438 ...
##  $ pop6   : int  2201 2113 2038 2061 2218 2455 2696 2925 3141 3330 ...
##  $ pop7   : int  593426 604293 615479 627714 641490 656737 672963 690193 708234 726834 ...
##  $ ttds   : num  43.7 44 44.4 44.7 45 ...
##  $ ttds1  : num  5.04 5 4.96 4.92 4.89 ...

Mã hóa dữ liệu

Mã hóa dữ liệu tỷ trọng dân số của 2 nhóm tuổi thành: dân số trẻ (T), dân số già (G). Dữ liệu được mã hóa thể hiện cơ cấu dân số của một quốc gia

# tạo ra biến mới tên Ccauds lấy từ biến ttds và biến ttds1
n$Ccauds <- ifelse(n$ttds >= 35 & n$ttds1 < 7, 'T', 'G') # nếu tỷ trọng dân số trong độ tuổi dưới 15 vượt qua 35% và tỷ trọng dân số trong độ tuổi 60-69 không quá 7% thì dân số trẻ, ngược lại là dân số già
str(n)
## 'data.frame':    360 obs. of  12 variables:
##  $ country: chr  "Colombia" "Colombia" "Colombia" "Colombia" ...
##  $ year   : int  1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 ...
##  $ pop    : num  11769747 12087061 12419969 12767245 13130655 ...
##  $ pop0   : int  5147615 5322337 5508316 5706160 5913987 6130810 6356226 6590926 6833562 7083173 ...
##  $ pop2   : int  368246 376270 384912 393767 402711 411778 420790 429784 439036 448944 ...
##  $ pop3   : int  175991 176932 177867 179904 183683 189050 195604 203238 211350 219122 ...
##  $ pop4   : int  46988 48978 50662 51982 52878 53454 53873 54246 54707 55438 ...
##  $ pop6   : int  2201 2113 2038 2061 2218 2455 2696 2925 3141 3330 ...
##  $ pop7   : int  593426 604293 615479 627714 641490 656737 672963 690193 708234 726834 ...
##  $ ttds   : num  43.7 44 44.4 44.7 45 ...
##  $ ttds1  : num  5.04 5 4.96 4.92 4.89 ...
##  $ Ccauds : chr  "T" "T" "T" "T" ...

Lập bảng tần số

Kết quả là tỷ trọng dân số dưới 15 tuổi ở Colombia thấp trong vòng 10 năm, trung bình trong 23 năm và cao trong 39 năm.

Tỷ trọng dân số dưới 15 tuổi ở Lào trung bình trong vòng 13 năm và cao trong 59 năm. Tỷ trọng dân số ở Myanmar thấp trong 6 năm, trung bình 30 năm và cao trong 36 năm.

Tỷ trọng dân số dưới 15 tuổi ở Thái Lan thấp 26 năm, trung bình 13 năm và cao trong vòng 33 năm. Tỷ trọng dân số dưới 15 tuổi ở Việt Nam thấp 15 năm, trung bình 19 năm và cao trong vòng 38

table(n$country) # số lần lặp lại của biến country
## 
## Colombia     Laos  Myanmar Thailand  Vietnam 
##       72       72       72       72       72
table(cut(n$ttds,3)) # kiểm tra số lần lặp lại của 3 tổ, ttds được phân làm 3 tổ: (15.8,26,3], (26.3,36.8], (36.8,47.3]
## 
## (15.8,26.3] (26.3,36.8] (36.8,47.3] 
##          57          98         205
n$nh <- cut(n$ttds,3, labels = c('thấp','trung bình','cao')) # gán dữ liệu vào biến mới là biến nh, sau đó 3 tổ ttds có tên lần lượt là tổ thấp, tổ trung bình và tổ cao
table(n$country,n$nh) # số lần lặp lại của các biến country và biến nh
##           
##            thấp trung bình cao
##   Colombia   10         23  39
##   Laos        0         13  59
##   Myanmar     6         30  36
##   Thailand   26         13  33
##   Vietnam    15         19  38

Phân tích dữ liệu theo thời gian

Theo quốc gia

Tiến hành phân tích dân số của Comlobia trong vòng 5 năm (năm 2017-2021):

  • Tổng dân số của Colombia là 250.263.258 người

  • Tổng dân số ghi nhận ít nhất trong 5 năm qua là 48.351.668 người

  • Có 25% tổng dân số thấp hơn 49.276.970 người và 75% tổng dân số lớn hơn 49.276.970 người

  • Có 50% tổng dân số thấp hơn 50.187.404 và 50% tổng dân số cao hơn 50.187.404 người

  • 75% tổng dân số thấp hơn 50.930.656 người và 25% tổng dân số cao hơn 50.930.656 người

  • Tổng dân số cao nhất của Colombia là 51.516.560 người

  • Tổng dân số qua các thời kì có sự chênh lệch 1.267.587 người

m <- filter(n,country =='Colombia' & year >= '2017') # lọc dữ liệu, chỉ lấy dữ liệu thuộc về Colombia

sum(m$pop) # tổng dân số
## [1] 250263258
summary(m$pop) # tóm tắt giá trị trong biến pop: min:giá trị tối thiểu; 1st Qu.:giá trị của tứ phân vị thứ 1; median:giá trị trung vị; 3rd Qu.:giá trị của tứ phân vị thứ 3; max:giá trị tối đa
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## 48351668 49276970 50187404 50052652 50930656 51516560
sd(m$pop) # độ lệch chuẩn
## [1] 1267587

Theo khu vực Đông Nam Á

Tiến hành phân tích tổng dân số của mỗi quốc gia trong 5 quốc gia thuộc Đông Nam Á: Colombia, Myanmar, Laos, Thailand, Vietnam

  • Tổng dân số của 5 quốc gia là 1.386.789.907 (người)

  • Tổng dân số ghi nhận ít nhất trong 5 năm qua là 6.997.925 người

  • Có 25% tổng dân số thấp hơn 49.276.970 người và 75% tổng dân số lớn hơn 49.276.970 người

  • Có 50% tổng dân số thấp hơn 53.040.212 và 50% tổng dân số cao hơn 53.040.212 người

  • 75% tổng dân số thấp hơn 71.475.660 người và 25% tổng dân số cao hơn 71.475.660 người

  • Tổng dân số cao nhất của các nước Đông Nam Á là 97.468.024 người

  • Trung bình tổng dân số là 55.471.596 (người)

  • Tổng dân số các nước có sự chênh lệch 24.161.223 (người)

h <- filter(n,year >= '2017') # lọc dữ liệu 5 quốc gia trong năm 2021, gán dữ liệu vào h

Tính các đặc trưng đo lường cho “h”

sum(h$pop) # tổng dân số của 5 quốc gia
## [1] 1386789907
summary(h$pop) # tóm tắt giá trị trong biến pop: min:giá trị tối thiểu; 1st Qu.:giá trị của tứ phân vị thứ 1; median:giá trị trung vị; 3rd Qu.:giá trị của tứ phân vị thứ 3; max:giá trị tối đa
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##  6997925 49276970 53040212 55471596 71475660 97468024
sd(n$pop) # độ lệch chuẩn
## [1] 24161223

Nhiệm vụ 3.2


Tóm tắt

Đọc dữ liệu từ file csv

Thực hiện các thao tác trên file csv “all_v2”. File này thống kê về bất động sản ở Nga 2018-2021, bao gồm các tiêu chí:

  • price: giá thành ( đơn vị: rups)

  • date: ngày công bố thông báo

  • time: thời điểm quảng cáo được xuất bản

  • geo_lat: Vĩ độ

  • geo_lon: Kinh độ

  • region: Khu vực của Nga. Tổng cộng có 85 đối tượng trong cả nước.

  • building_type: Loại mặt tiền. 0 - Khác. 1 - Bảng điều khiển. 2 - Nguyên khối. 3 - Gạch. 4 - Khối. 5 - Gỗ

  • object_type: Loại căn hộ. 1 - Thị trường bất động sản thứ cấp; 2 – Xây dựng mới

  • level: Tầng căn hộ tầng

  • levels: Số tầng

  • rooms: số lượng phòng khách. Nếu giá trị là “-1” thì có nghĩa là “studio apartment”

  • area: tổng diện tích căn hộ

  • Kitchen_area - Khu vực bếp

d <- read.csv(file.choose(), header = T)
d

Thông tin tổng quan của bộ dữ liệu

Các thông tin tổng quát về dataset:

  • Là một data frame

  • có 13 cột tương đương với 13 biến

  • Các cột lần lượt là:

    • price: giá thành ( đơn vị: rups)

    • date: ngày công bố thông báo

    • time: thời điểm quảng cáo được xuất bản

    • geo_lat: Vĩ độ

    • geo_lon: Kinh độ

    • region: Khu vực của Nga. Tổng cộng có 85 đối tượng trong cả nước.

    • building_type: Loại mặt tiền. 0 - Khác. 1 - Bảng điều khiển.2 - Nguyên khối. 3 - Gạch. 4 - Khối. 5 - Gỗ

    • object_type: Loại căn hộ. 1 - Thị trường bất động sản thứ cấp; 2 – Xây dựng mới

    • level: Tầng căn hộ tầng

    • levels: Số tầng

    • rooms: số lượng phòng khách. Nếu giá trị là “-1” thì có nghĩa là “studio apartment”

    • area: tổng diện tích căn hộ

    • Kitchen_area - Khu vực bếp

  • Có 5477006 hàng tương đương 5377006 quan sát

  • Data không có dữ liệu trống

is.data.frame(d) # kiểm tra xem "d" có phải là data frame hay không, nếu đúng kết quả trả về TRUE và ngược lại
## [1] TRUE
length(d) # hiển thị độ dài của dữ liệu, là số cột của "d"
## [1] 13
names(d) # hiển thị tên các cột của "a"
##  [1] "price"         "date"          "time"          "geo_lat"      
##  [5] "geo_lon"       "region"        "building_type" "level"        
##  [9] "levels"        "rooms"         "area"          "kitchen_area" 
## [13] "object_type"
dim(d) # hiển thị số hàng và số cột của d
## [1] 5477006      13
sum(is.na(d)) # kiểm tra tổng số ô trống của dữ liệu
## [1] 0

Rút trích dữ liệu

library(tidyverse)
# Vì dữ liệu thuộc khu vực Nga nên cột region không chính xác, tiến hành xóa cột region bằng câu lệnh
d <- select(d,-region) # bộ dữ liệu d là bộ dữ liệu với 12 biến
d # d trở thành bộ dữ liệu với 12 biến
# Gán dữ liệu được trích vào g, sau đó lọc bộ dữ liệu d
g <- d %>% filter(object_type == 1) %>% select(price,building_type,rooms,area,object_type) # kết quả lọc các cột price, building_type, rooms, area và object_type với điều kiện là xây mới (object_type = 1)
str(g)
## 'data.frame':    3863809 obs. of  5 variables:
##  $ price        : int  6050000 8650000 4000000 5450000 3300000 3600000 2800000 4550000 2880000 1450000 ...
##  $ building_type: int  1 3 1 3 1 1 1 3 1 1 ...
##  $ rooms        : int  3 2 3 2 1 1 2 2 2 1 ...
##  $ area         : num  82.6 69.1 66 60 32 31.1 55 54.2 51 43 ...
##  $ object_type  : int  1 1 1 1 1 1 1 1 1 1 ...

Tóm tắt bộ dữ liệu mới

Bộ dữ liệu “g” là bộ dữ liệu mới phân tích về bất động sản ở Nga thông qua các tiêu chí:

  • price: giá thành (rups)

  • building_type: loại mặt tiền

  • rooms: số lượng phòng khách

  • area: tổng diện tích căn hộ

  • object_type: loại căn hộ

Bộ dữ liệu “g” là data frame với 3863809 quan sát ( 3863809 hàng) và 5 biến ( 5 cột)

Mã hóa dữ liệu

Mã hóa dữ liệu của “g” thành: căn hộ mới (Apnew), căn hộ bình thường (Apnor). Dữ liệu được mã hóa thể hiện loại phòng của căn hộ

# Tạo ra biến mới có tên room_tyle, lấy từ biến rooms và object_tyle
g$room_tyle <- ifelse(g$rooms == -1, 'Apnew', 'Apnor')
str(g)
## 'data.frame':    3863809 obs. of  6 variables:
##  $ price        : int  6050000 8650000 4000000 5450000 3300000 3600000 2800000 4550000 2880000 1450000 ...
##  $ building_type: int  1 3 1 3 1 1 1 3 1 1 ...
##  $ rooms        : int  3 2 3 2 1 1 2 2 2 1 ...
##  $ area         : num  82.6 69.1 66 60 32 31.1 55 54.2 51 43 ...
##  $ object_type  : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ room_tyle    : chr  "Apnor" "Apnor" "Apnor" "Apnor" ...

Lập bảng tần số

table(cut(g$area,3)) # số lần xuất hiện của 3 phân tổ area
## 
##    (-7.79,2.62e+03] (2.62e+03,5.24e+03] (5.24e+03,7.86e+03] 
##             3863734                  66                   9
g$kh <- cut(g$area,3, labels = c('nhỏ','trung bình','lớn')) # gán vào kh, sau đó phân area làm 3 tổ có tên lần lượt là 'nhỏ','trung bình','lớn'
table(g$room_tyle,g$kh) # số lần xuất hiện của biến room_tyle và kh
##        
##             nhỏ trung bình     lớn
##   Apnew  152012          1       1
##   Apnor 3711722         65       8
  • Căn hộ mới có 152012 phòng có diện tích nhỏ

  • Căn hộ mới có 1 phòng có diện tích trung bình

  • Không có căn hộ mới cỡ lớn

  • Căn hộ bình thường có 3711722 phòng có diện tích nhỏ

  • Căn hộ bình thường có 56 phòng có diện tích trung bình

  • Có 8 phòng có diện tích lớn trong căn hộ bình thường

Phân tích dữ liệu theo giá thành

# tính các đặc trưng đo lường
ph <- g %>% group_by(price) %>% summarise(mean_of_area = mean(area)) # gán dữ liệu ph được tạo bởi nhóm price và giá trị trung bình của tổng diện tích căn hộ
summary(ph)
##      price             mean_of_area    
##  Min.   :-2.145e+09   Min.   :   1.00  
##  1st Qu.: 2.990e+06   1st Qu.:  43.70  
##  Median : 5.548e+06   Median :  61.20  
##  Mean   : 1.393e+07   Mean   :  73.03  
##  3rd Qu.: 1.133e+07   3rd Qu.:  85.20  
##  Max.   : 2.147e+09   Max.   :4250.00

Tiến hành phân tích dữ liệu theo giá thành, thu được kết quả như sau:

  • Diện tích trung bình ( mean) của một căn hộ là 73.02482 m^2 có giá trung bình là 1,393 triệu rups

  • Diện tích căn hộ nhỏ nhất (min) là 1 m2 có giá thấp nhất là -2,145 triệu rups

  • Diện tích lớn nhất của căn hộ là 4250 m2 có giá cao nhất là 2,147 triệu rups

  • Có 25% căn hộ có diện tích trung bình 61.2m2,giá 2,99 triệu rups và 75% căn hộ có diện tích trung bình 61.2m2, giá 2.99 triệu rups

  • Có 50% căn hộ có diện tích trung bình 73.03m2, giá 1.393 triệu rups và 50% còn lại

  • có 75% căn hộ có diện tích trung bình 85.2m2, giá 1,133 triệu rups và 25% còn lại

LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSAzIg0KYXV0aG9yOiAibnRhdGh1Ig0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUg6JU06JVMsICVkIC0gJW0gLSAlWScpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KIyBOaGnhu4dtIHbhu6UgMy4xDQoqKioNCg0KIyMgVMOzbSB04bqvdA0KDQpUaOG7sWMgaGnhu4duIGPDoWMgdGhhbyB0w6FjIG3hu5l0IHPhu5EgbOG7h2NoIGPGoSBi4bqjbiB2w6AgcsO6dCB0csOtY2ggZOG7ryBsaeG7h3UgdHLDqm4gZmlsZSB4bHN4ICIgcG9wdWxhdGlvbi1hbmQtZGVtb2dyYXBoeS54bHN4Ii4gRmlsZSBwaMOibiB0w61jaCB04buVbmcgZMOibiBz4buRIGPhu6dhIGPDoWMgcXXhu5FjIGdpYSB0aGVvIMSR4buZIHR14buVaSBxdWEgY8OhYyBuxINtIHThu6sgbsSDbSAxOTUwIC0gMjAyMQ0KDQojIyMgxJDhu41jIGThu68gbGnhu4d1IHThu6sgZmlsZSBjc3YNCg0KYGBge3J9DQojxJDhu4MgduG7q2EgY2jhuqF5IGThu68gbGnhu4d1IMSR4buTbmcgdGjhu51pIGhp4buDbiB0aOG7iyBjaOG7ryB0YSBuaOG6pW4gdOG7lSBo4bujcCBwaMOtbSBDVFJMK0FMVCtJIHNhdSDEkcOzIG5o4bqtcCB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQoNCiMgR8OhbiBk4buvIGxp4buHdSBj4bunYSBmaWxlIGNzdiB2w6BvIGEsIHNhdSDEkcOzIMSR4buNYyBk4buvIGxp4buHdSB04burIGZpbGUgY3N2IGLhurFuZyBjw6J1IGzhu4duaA0KYSA8LSByZWFkLmNzdihmaWxlLmNob29zZSgpLCBoZWFkZXIgPSBUKSAjIGhlYWRlciA9IFQgbMOgIGzhuqV5IGThu68gbGnhu4d1IHThu6sgZMOybmcgxJHhuqd1IHRpw6puIGPhu6dhIGZpbGUgY3N2DQpgYGANCg0KIyMjIFRow7RuZyB0aW4gdOG7lW5nIHF1YW4gY+G7p2EgYuG7mSBk4buvIGxp4buHdQ0KDQpDw6FjIHRow7RuZyB0aW4gdOG7lW5nIHF1YW4gduG7gSBkYXRhc2V0Og0KDQotIEzDoCBt4buZdCBkYXRhIGZyYW1lDQoNCi0gQ8OzIDI0IGPhu5l0IHTGsMahbmcgxJHGsMahbmcgMjQgYmnhur9uDQoNCi0gQ8OhYyBj4buZdCBs4bqnbiBsxrDhu6N0IGzDoDoNCg0KICAtIENvdW50cnkubmFtZTogVMOqbiBjw6FjIHF14buRYyBnaWENCiAgDQogIC0gWWVhcjogbsSDbSBs4bqleSBz4buRIGxp4buHdQ0KICANCiAgLSBQb3B1bGF0aW9uOiBU4buVbmcgZMOibiBz4buRDQogIA0KICAtIFBvcHVsYXRpb24ub2YuY2hpbGRyZW4udW5kZXIudGhlLmFnZS5vZi4xOiBEw6JuIHPhu5EgZMaw4bubaSAxIHR14buVaQ0KDQogIC0gUG9wdWxhdGlvbi5vZi5jaGlsZHJlbi51bmRlci50aGUuYWdlLm9mLjU6IETDom4gc+G7kSBkxrDhu5tpIDUgdHXhu5VpDQoNCiAgLSBQb3B1bGF0aW9uLm9mLmNoaWxkcmVuLnVuZGVyLnRoZS5hZ2Uub2YuMTU6IETDom4gc+G7kSBkxrDhu5tpIDE1IHR14buVaQ0KDQogIC0gUG9wdWxhdGlvbi51bmRlci50aGUuYWdlLm9mLjI1OiBEw6JuIHPhu5EgZMaw4bubaSAyNSB0deG7lWkNCg0KICAtIFBvcHVsYXRpb24uYWdlZC4xNS50by42NC55ZWFyczogRMOibiBz4buRIHThu6sgMTUgxJHhur9uIDY0IHR14buVaQ0KICANCiAgLSBQb3B1bGF0aW9uLm9sZGVyLnRoYW4uMTUueWVhcnM6IETDom4gc+G7kSBs4bubbiBoxqFuIDE1IHR14buVaQ0KDQogIC0gUG9wdWxhdGlvbi5vbGRlci50aGFuLjE4LnllYXJzOiBEw6JuIHPhu5EgbOG7m24gaMahbiAxOCB0deG7lWkNCg0KICAtIFBvcHVsYXRpb24uYXQuYWdlLjE6IETDom4gc+G7kSB04bqhaSDEkeG7mSB0deG7lWkgMQ0KDQogIC0gUG9wdWxhdGlvbi5hZ2VkLjEudG8uNC55ZWFyczogRMOibiBz4buRIHThu6sgMSDEkeG6v24gNCB0deG7lWkNCg0KICAtIFBvcHVsYXRpb24uYWdlZC41LnRvLjkueWVhcnM6IETDom4gc+G7kSB04burIDUgxJHhur9uIDkgdHXhu5VpDQoNCiAgLSBQb3B1bGF0aW9uLmFnZWQuMTAudG8uMTQueWVhcnM6IETDom4gc+G7kSB04burIDEwIMSR4bq/biAxNCB0deG7lWkNCg0KICAtIFBvcHVsYXRpb24uYWdlZC4xNS50by4xOS55ZWFyczogRMOibiBz4buRIHThu6sgMTUgxJHhur9uIDE5IHR14buVaQ0KDQogIC0gUG9wdWxhdGlvbi5hZ2VkLjIwLnRvLjI5LnllYXJzOiBEw6JuIHPhu5EgdOG7qyAyMCDEkeG6v24gMjkgdHXhu5VpDQoNCiAgLSBQb3B1bGF0aW9uLmFnZWQuMzAudG8uMzkueWVhcnM6IETDom4gc+G7kSB04burIDMwIMSR4bq/biAzOSB0deG7lWkNCg0KICAtIFBvcHVsYXRpb24uYWdlZC40MC50by40OS55ZWFyczogRMOibiBz4buRIHThu6sgNDAgxJHhur9uIDQ5IHR14buVaQ0KDQogIC0gUG9wdWxhdGlvbi5hZ2VkLjUwLnRvLjU5LnllYXJzOiBEw6JuIHPhu5EgdOG7qyA1MCDEkeG6v24gNTkgdHXhu5VpDQoNCiAgLSBQb3B1bGF0aW9uLmFnZWQuNjAudG8uNjkueWVhcnM6IETDom4gc+G7kSB04burIDYwIMSR4bq/biA2OSB0deG7lWkNCg0KICAtIFBvcHVsYXRpb24uYWdlZC43MC50by43OS55ZWFyczogRMOibiBz4buRIHThu6sgNzAgxJHhur9uIDc5IHR14buVaQ0KDQogIC0gUG9wdWxhdGlvbi5hZ2VkLjgwLnRvLjg5LnllYXJzOiBEw6JuIHPhu5EgdOG7qyA4MCDEkeG6v24gODkgdHXhu5VpDQoNCiAgLSBQb3B1bGF0aW9uLmFnZWQuOTAudG8uOTkueWVhcnM6IETDom4gc+G7kSB04burIDkwIMSR4bq/biA5OSB0deG7lWkNCg0KICAtIFBvcHVsYXRpb24ub2xkZXIudGhhbi4xMDAueWVhcnM6IETDom4gc+G7kSBs4bubbiBoxqFuIDEwMCB0deG7lWkNCg0KLSBDw7MgMTgyODggaMOgbmcgdMawxqFuZyDEkcawxqFuZyAxODI4OCBxdWFuIHPDoXQNCg0KLSBEYXRhIGtow7RuZyBjw7MgZOG7ryBsaeG7h3UgdHLhu5FuZw0KICANCmBgYHtyfQ0KIyBLaeG7g20gdHJhIHhlbSAiYSIgY8OzIHBo4bqjaSBsw6AgZGF0YSBmcmFtZSBoYXkga2jDtG5nLCBu4bq/dSDEkcO6bmcgdGjDrCBr4bq/dCBxdeG6oyB0cuG6oyB24buBIFRSVUUgdsOgIG5nxrDhu6NjIGzhuqFpLCBraeG7g20gdHJhIGLhurFuZyBjw6J1IGzhu4duaA0KaXMuZGF0YS5mcmFtZShhKQ0KDQojIEhp4buDbiB0aOG7iyDEkeG7mSBkw6BpIGPhu6dhIGThu68gbGnhu4d1LCB04bupYyBsw6Agc+G7kSBj4buZdCBj4bunYSAiYSINCmxlbmd0aChhKQ0KDQojIEhp4buDbiB0aOG7iyB0w6puIGPDoWMgY+G7mXQgY+G7p2EgImEiIGLhurFuZyBjw6J1IGzhu4duaA0KbmFtZXMoYSkNCg0KIyBIaeG7g24gdGjhu4sgc+G7kSBow6BuZyB2w6Agc+G7kSBj4buZdCBj4bunYSAiYSINCmRpbShhKQ0KDQojIEtp4buDbSB0cmEgdOG7lW5nIHPhu5Egw7QgdHLhu5FuZyBj4bunYSBk4buvIGxp4buHdSBi4bqxbmcgY8OidSBs4buHbmgNCnN1bShpcy5uYShhKSkNCg0KYGBgDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpICMgbG9hZCBnw7NpIHRpZHl2ZXJzZSDEkeG7gyB0aOG7sWMgaGnhu4duIGPDoWMgY8OidSBs4buHbmggY8OzIGNo4bupYSAlPiUgDQpgYGANCg0KIyMjIMSQ4buVaSB0w6puIGNobyBjw6FjIGJp4bq/bg0KDQpgYGB7cn0NCiMgxJDhu5VpIHTDqm4gY8OhYyBiaeG6v24gxJHhu4MgdGh14bqtbiB0aeG7h24gdGhhbyB0w6FjIHRyw6puIGThu68gbGnhu4d1ICJhIg0KYSA8LSByZW5hbWUoYSxjb3VudHJ5ID0gQ291bnRyeS5uYW1lICxwb3AgPSBQb3B1bGF0aW9uLCB5ZWFyID0gWWVhcikgIyDEkeG7lWkgdMOqbiBjw6FjIGPhu5l0IENvdW50cnkubmFtZSwgUG9wdWxhdGlvbiB2w6AgWWVhciB0aMOgbmggY291bnRyeSwgcG9wIHbDoCB5ZWFyDQoNCmEgPC0gYSAlPiUgcmVuYW1lKHBvcDAgPSBQb3B1bGF0aW9uLm9mLmNoaWxkcmVuLnVuZGVyLnRoZS5hZ2Uub2YuMTUgLHBvcDIgPSBQb3B1bGF0aW9uLmFnZWQuNjAudG8uNjkueWVhcnMgLHBvcDMgPSBQb3B1bGF0aW9uLmFnZWQuNzAudG8uNzkueWVhcnMgLHBvcDQgPSBQb3B1bGF0aW9uLmFnZWQuODAudG8uODkueWVhcnMgLHBvcDYgPSBQb3B1bGF0aW9uLmFnZWQuOTAudG8uOTkueWVhcnMpICMjIMSR4buVaSB0w6puIHRoYXkgdGjhur8gbOG6p24gbMaw4bujdCBjaG8gY8OhYyBj4buZdCBQb3B1bGF0aW9uLm9mLmNoaWxkcmVuLnVuZGVyLnRoZS5hZ2Uub2YuMTUsIFBvcHVsYXRpb24uYWdlZC42MC50by42OS55ZWFycywgUG9wdWxhdGlvbi5hZ2VkLjcwLnRvLjc5LnllYXJzLCBQb3B1bGF0aW9uLmFnZWQuODAudG8uODkueWVhcnMsIFBvcHVsYXRpb24uYWdlZC45MC50by45OQ0KDQpgYGANCg0KIyMgUGjDom4gdMOtY2ggY8OhYyBxdeG7kWMgZ2lhIHbDoCBkw6JuIHPhu5ENCg0KQuG7mSBk4buvIGxp4buHdSAiYSIgbMOgIGLhu5kgZOG7ryBsaeG7h3UgbOG7m24gY2jhu6lhIHRow7RuZyB0aW4gduG7gSBjw6FjIHF14buRYyBnaWEgdHLDqm4gdGjhur8gZ2nhu5tpIHbhu4EgZMOibiBz4buRIHbDoCBz4buRIGTDom4gdGh14buZYyBjw6FjIG5ow7NtIHR14buVaSBraMOhYyBuaGF1LiBWw6wgduG6rXksIHRhIHRp4bq/biBow6BuaCByw7p0IHRyw61jaCBk4buvIGxp4buHdSB04burIMSRw7MgxJHhu4MgZOG7hSBkw6BuZyB0aGFvIHTDoWMNCg0KLSBUaOG7sWMgaGnhu4duIHLDunQgdHLDrWNoIDUgcXXhu5FjIGdpYSB0aHXhu5ljIMSQw7RuZyBOYW0gw4EgxJHhu4MgcGjDom4gdMOtY2gsIGJhbyBn4buTbSBjw6FjIHF14buRYyBnaWE6IENvbWJvZGlhLCBMYW9zLCBNeWFubWFyLCBUaGFpbGFuZCwgVmlldG5hbQ0KYGBge3J9DQojIEfDoW4gZOG7ryBsaeG7h3UgxJHGsOG7o2MgdHLDrWNoIHbDoG8gbiwgc2F1IMSRw7MgbOG7jWMgYuG7mSBk4buvIGxp4buHdSAiYSINCm4gPC0gYSAlPiUgZmlsdGVyKGNvdW50cnkgJWluJSBjKCdWaWV0bmFtJywnQ29sb21iaWEnLCdMYW9zJywnTXlhbm1hcicsJ1RoYWlsYW5kJykpICMgbOG7jWMgY8OhYyBxdeG7kWMgZ2lhIHRyb25nIGPhu5l0IGNvdW50cnkgdsOgIGdp4buvIGPDoWMgaMOgbmcgY+G7p2EgY+G7mXQgY291bnRyeSBuYW1lIGLhuq90IMSR4bqndSBi4bqxbmcgY2jhu68gJ1ZpZXRuYW0nLCdDb2xvbWJpYScsJ0xhb3MnLCdNeWFubWFyJywnVGhhaWxhbmQnDQpgYGANCi0gVGjhu7FjIGhp4buHbiByw7p0IHRyw61jaCB04buVbmcgZMOibiBz4buRIHbDoCBkw6JuIHPhu5EgdGh14buZYyA1IG5ow7NtIHR14buVaSBraMOhYyBuaGF1DQpgYGB7cn0NCm4gPC0gbiAlPiUgc2VsZWN0KGNvdW50cnkseWVhcixwb3AscG9wMCxwb3AyLHBvcDMscG9wNCxwb3A2KSMgbOG7jWMgY8OhYyBj4buZdCBjb3VudHJ5LCB5ZWFyLCBwb3AsIHBvcDAsIHBvcDIsIHBvcDMsIHBvcDQgdsOgIHBvcDYNCm4NCmBgYA0KDQoNCiMjIyBUw7NtIHThuq90IGLhu5kgZOG7ryBsaeG7h3UgbeG7m2kNCg0KQuG7mSBk4buvIGxp4buHdSAibiIgbMOgIGLhu5kgZOG7ryBsaeG7h3UgbeG7m2kgcGjDom4gdMOtY2ggduG7gSB04buVbmcgZMOibiBz4buRIHbDoCBkw6JuIHPhu5EgY+G7p2EgNSDEkeG7mSB0deG7lWkg4bufIDUgcXXhu5FjIGdpYSBraMOhYyBuaGF1IGJhbyBn4buTbToNCg0KLSBjb3VudHJ5OiB0w6puIDUgcXXhu5FjIGdpYSBj4bqnbiBwaMOibiB0w61jaA0KDQotIHllYXI6IG7Eg20gbOG6pXkgZOG7ryBsaeG7h3UNCg0KLSBwb3A6IHThu5VuZyBkw6JuIHPhu5ENCg0KLSBwb3AwOiBkw6JuIHPhu5EgY+G7p2EgdHLhursgZW0gZMaw4bubaSAxNSB0deG7lWkNCg0KLSBwb3AyOiBkw6JuIHPhu5EgdOG7qyAxNSDEkeG6v24gNjQgdHXhu5VpDQoNCi0gcG9wMzogZMOibiBz4buRIHThu6sgNjAgxJHhur9uIDY5IHR14buVaQ0KDQotIHBvcDQ6IGTDom4gc+G7kSBjw7MgxJHhu5kgdHXhu5VpIHThu6sgNzAgxJHhur9uIDc5IA0KDQotIHBvcDY6IGTDom4gc+G7kSB04burIDEwMCB0deG7lWkgdHLhu58gbMOqbg0KDQpC4buZIGThu68gbGnhu4d1ICJuIiBn4buTbSAzNjAgcXVhbiBzw6F0ICggMzYwIGjDoG5nKSB2w6AgOCBiaeG6v24gKCA4IGPhu5l0KQ0KDQoNCiMjIyBU4bqhbyBj4buZdCBk4buvIGxp4buHdSBt4bubaSB04burIGLhu5kgZOG7ryBsaeG7h3UgIm4iDQoNClRp4bq/biBow6BuaCB0aOG7sWMgaGnhu4duIGPDoWMgbOG7h25oIMSR4buDIHThuqFvIHRow6ptIGJp4bq/biBt4bubaSBjaG8gYuG7mSBk4buvIGxp4buHdSBuLCBr4bq/dCBxdeG6oyBj4bunYSB2aeG7h2MgdOG6oW8gcmEgY+G7mXQgZOG7ryBsaeG7h3UgbeG7m2kgbMOgIGLhu5kgZOG7ryBsaeG7h3UgbiB4deG6pXQgaGnhu4duIHRow6ptIDMgYmnhur9uIG3hu5tpIGzDoDoNCg0KLSBwb3A3OiBQb3B1bGF0aW9uLm9sZGVyLnRoYW4uNjAueWVhcnMgLSBsw6AgZMOibiBz4buRIGzhu5tuIGjGoW4gNjAgdHXhu5VpDQoNCi0gdHRkczogdOG7tyB0cuG7jW5nIGTDom4gc+G7kSBuaMOzbSB0deG7lWkgZMaw4bubaSB0deG7lWkgbGFvIMSR4buZbmcgKCBkxrDhu5tpIDE1IHR14buVaSkNCg0KLSB0dGRzMTogdOG7tyB0cuG7jW5nIGTDom4gc+G7kSBuaMOzbSB0deG7lWkgdHLDqm4gbGFvIMSR4buZbmcgKCB04burIDYwIHRy4bufIGzDqm4pDQpgYGB7cn0NCm4gPC0gbiAlPiUgbXV0YXRlKHBvcDcgPSBwb3AyICsgcG9wMyArIHBvcDQgKyBwb3A2KSAjIGTDom4gc+G7kSBs4bubbiBoxqFuIDYwIHR14buVaSDEkcaw4bujYyB0w61uaCBi4bqxbmcgdOG7lW5nIHPhu5EgZMOibiBj4bunYSBjw6FjIG5ow7NtIHR14buVaSBwb3AyLHBvcDMscG9wNCxwb3A2DQpuIDwtIG4gJT4lIG11dGF0ZSh0dGRzID0gKCBwb3AwIC8gcG9wICkgKiAxMDAsIHR0ZHMxID0gKCBwb3A3IC8gcG9wICkgKiAxMDApICMgdOG7tyB0cuG7jW5nIGTDom4gc+G7kSB0aHXhu5ljIG5ow7NtIHR14buVaSBpIMSRxrDhu6NjIHTDrW5oIGLhurFuZyAoc+G7kSBkw6JuIHRodeG7mWMgbmjDs20gdHXhu5VpIGkvdOG7lW5nIHPhu5EgZMOibikqMTAwDQpzdHIobikNCmBgYA0KDQojIyBNw6MgaMOzYSBk4buvIGxp4buHdQ0KDQpNw6MgaMOzYSBk4buvIGxp4buHdSB04bu3IHRy4buNbmcgZMOibiBz4buRIGPhu6dhIDIgbmjDs20gdHXhu5VpIHRow6BuaDogZMOibiBz4buRIHRy4bq7IChUKSwgZMOibiBz4buRIGdpw6AgKEcpLiBE4buvIGxp4buHdSDEkcaw4bujYyBtw6MgaMOzYSB0aOG7gyBoaeG7h24gY8ahIGPhuqV1IGTDom4gc+G7kSBj4bunYSBt4buZdCBxdeG7kWMgZ2lhDQpgYGB7cn0NCiMgdOG6oW8gcmEgYmnhur9uIG3hu5tpIHTDqm4gQ2NhdWRzIGzhuqV5IHThu6sgYmnhur9uIHR0ZHMgdsOgIGJp4bq/biB0dGRzMQ0KbiRDY2F1ZHMgPC0gaWZlbHNlKG4kdHRkcyA+PSAzNSAmIG4kdHRkczEgPCA3LCAnVCcsICdHJykgIyBu4bq/dSB04bu3IHRy4buNbmcgZMOibiBz4buRIHRyb25nIMSR4buZIHR14buVaSBkxrDhu5tpIDE1IHbGsOG7o3QgcXVhIDM1JSB2w6AgdOG7tyB0cuG7jW5nIGTDom4gc+G7kSB0cm9uZyDEkeG7mSB0deG7lWkgNjAtNjkga2jDtG5nIHF1w6EgNyUgdGjDrCBkw6JuIHPhu5EgdHLhurssIG5nxrDhu6NjIGzhuqFpIGzDoCBkw6JuIHPhu5EgZ2nDoA0Kc3RyKG4pDQpgYGANCiMjIEzhuq1wIGLhuqNuZyB04bqnbiBz4buRDQoNCkvhur90IHF14bqjIGzDoCB04bu3IHRy4buNbmcgZMOibiBz4buRIGTGsOG7m2kgMTUgdHXhu5VpIOG7nyBDb2xvbWJpYSB0aOG6pXAgdHJvbmcgdsOybmcgMTAgbsSDbSwgdHJ1bmcgYsOsbmggdHJvbmcgMjMgbsSDbSB2w6AgY2FvIHRyb25nIDM5IG7Eg20uIA0KDQpU4bu3IHRy4buNbmcgZMOibiBz4buRIGTGsOG7m2kgMTUgdHXhu5VpIOG7nyBMw6BvIHRydW5nIGLDrG5oIHRyb25nIHbDsm5nIDEzIG7Eg20gdsOgIGNhbyB0cm9uZyA1OSBuxINtLiBU4bu3IHRy4buNbmcgZMOibiBz4buRIOG7nyBNeWFubWFyIHRo4bqlcCB0cm9uZyA2IG7Eg20sIHRydW5nIGLDrG5oIDMwIG7Eg20gdsOgIGNhbyB0cm9uZyAzNiBuxINtLiANCg0KVOG7tyB0cuG7jW5nIGTDom4gc+G7kSBkxrDhu5tpIDE1IHR14buVaSDhu58gVGjDoWkgTGFuIHRo4bqlcCAyNiBuxINtLCB0cnVuZyBiw6xuaCAxMyBuxINtIHbDoCBjYW8gdHJvbmcgdsOybmcgMzMgbsSDbS4gVOG7tyB0cuG7jW5nIGTDom4gc+G7kSBkxrDhu5tpIDE1IHR14buVaSDhu58gVmnhu4d0IE5hbSB0aOG6pXAgMTUgbsSDbSwgdHJ1bmcgYsOsbmggMTkgbsSDbSB2w6AgY2FvIHRyb25nIHbDsm5nIDM4DQoNCmBgYHtyfQ0KdGFibGUobiRjb3VudHJ5KSAjIHPhu5EgbOG6p24gbOG6t3AgbOG6oWkgY+G7p2EgYmnhur9uIGNvdW50cnkNCnRhYmxlKGN1dChuJHR0ZHMsMykpICMga2nhu4NtIHRyYSBz4buRIGzhuqduIGzhurdwIGzhuqFpIGPhu6dhIDMgdOG7lSwgdHRkcyDEkcaw4bujYyBwaMOibiBsw6BtIDMgdOG7lTogKDE1LjgsMjYsM10sICgyNi4zLDM2LjhdLCAoMzYuOCw0Ny4zXQ0KbiRuaCA8LSBjdXQobiR0dGRzLDMsIGxhYmVscyA9IGMoJ3Ro4bqlcCcsJ3RydW5nIGLDrG5oJywnY2FvJykpICMgZ8OhbiBk4buvIGxp4buHdSB2w6BvIGJp4bq/biBt4bubaSBsw6AgYmnhur9uIG5oLCBzYXUgxJHDsyAzIHThu5UgdHRkcyBjw7MgdMOqbiBs4bqnbiBsxrDhu6N0IGzDoCB04buVIHRo4bqlcCwgdOG7lSB0cnVuZyBiw6xuaCB2w6AgdOG7lSBjYW8NCnRhYmxlKG4kY291bnRyeSxuJG5oKSAjIHPhu5EgbOG6p24gbOG6t3AgbOG6oWkgY+G7p2EgY8OhYyBiaeG6v24gY291bnRyeSB2w6AgYmnhur9uIG5oDQpgYGANCg0KIyMgUGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgdGhlbyB0aOG7nWkgZ2lhbg0KDQojIyMgVGhlbyBxdeG7kWMgZ2lhDQoNClRp4bq/biBow6BuaCBwaMOibiB0w61jaCBkw6JuIHPhu5EgY+G7p2EgQ29tbG9iaWEgdHJvbmcgdsOybmcgNSBuxINtIChuxINtIDIwMTctMjAyMSk6DQoNCi0gVOG7lW5nIGTDom4gc+G7kSBj4bunYSBDb2xvbWJpYSBsw6AgMjUwLjI2My4yNTggbmfGsOG7nWkNCg0KLSBU4buVbmcgZMOibiBz4buRIGdoaSBuaOG6rW4gw610IG5o4bqldCB0cm9uZyA1IG7Eg20gcXVhIGzDoCA0OC4zNTEuNjY4IG5nxrDhu51pDQoNCi0gQ8OzIDI1JSB04buVbmcgZMOibiBz4buRIHRo4bqlcCBoxqFuIDQ5LjI3Ni45NzAgbmfGsOG7nWkgdsOgIDc1JSB04buVbmcgZMOibiBz4buRIGzhu5tuIGjGoW4gNDkuMjc2Ljk3MCBuZ8aw4budaQ0KDQotIEPDsyA1MCUgdOG7lW5nIGTDom4gc+G7kSB0aOG6pXAgaMahbiA1MC4xODcuNDA0IHbDoCA1MCUgdOG7lW5nIGTDom4gc+G7kSBjYW8gaMahbiA1MC4xODcuNDA0IG5nxrDhu51pDQoNCi0gNzUlIHThu5VuZyBkw6JuIHPhu5EgdGjhuqVwIGjGoW4gNTAuOTMwLjY1NiBuZ8aw4budaSB2w6AgMjUlIHThu5VuZyBkw6JuIHPhu5EgY2FvIGjGoW4gNTAuOTMwLjY1NiBuZ8aw4budaQ0KDQotIFThu5VuZyBkw6JuIHPhu5EgY2FvIG5o4bqldCBj4bunYSBDb2xvbWJpYSBsw6AgNTEuNTE2LjU2MCBuZ8aw4budaQ0KDQotIFThu5VuZyBkw6JuIHPhu5EgcXVhIGPDoWMgdGjhu51pIGvDrCBjw7Mgc+G7sSBjaMOqbmggbOG7h2NoIDEuMjY3LjU4NyBuZ8aw4budaQ0KYGBge3J9DQptIDwtIGZpbHRlcihuLGNvdW50cnkgPT0nQ29sb21iaWEnICYgeWVhciA+PSAnMjAxNycpICMgbOG7jWMgZOG7ryBsaeG7h3UsIGNo4buJIGzhuqV5IGThu68gbGnhu4d1IHRodeG7mWMgduG7gSBDb2xvbWJpYQ0KDQpzdW0obSRwb3ApICMgdOG7lW5nIGTDom4gc+G7kQ0Kc3VtbWFyeShtJHBvcCkgIyB0w7NtIHThuq90IGdpw6EgdHLhu4sgdHJvbmcgYmnhur9uIHBvcDogbWluOmdpw6EgdHLhu4sgdOG7kWkgdGhp4buDdTsgMXN0IFF1LjpnacOhIHRy4buLIGPhu6dhIHThu6kgcGjDom4gduG7iyB0aOG7qSAxOyBtZWRpYW46Z2nDoSB0cuG7iyB0cnVuZyB24buLOyAzcmQgUXUuOmdpw6EgdHLhu4sgY+G7p2EgdOG7qSBwaMOibiB24buLIHRo4bupIDM7IG1heDpnacOhIHRy4buLIHThu5FpIMSRYQ0Kc2QobSRwb3ApICMgxJHhu5kgbOG7h2NoIGNodeG6qW4NCmBgYA0KIyMjIFRoZW8ga2h1IHbhu7FjIMSQw7RuZyBOYW0gw4ENCg0KVGnhur9uIGjDoG5oIHBow6JuIHTDrWNoIHThu5VuZyBkw6JuIHPhu5EgY+G7p2EgbeG7l2kgcXXhu5FjIGdpYSB0cm9uZyA1IHF14buRYyBnaWEgdGh14buZYyDEkMO0bmcgTmFtIMOBOiBDb2xvbWJpYSwgTXlhbm1hciwgTGFvcywgVGhhaWxhbmQsIFZpZXRuYW0NCg0KLSBU4buVbmcgZMOibiBz4buRIGPhu6dhIDUgcXXhu5FjIGdpYSBsw6AgMS4zODYuNzg5LjkwNyAobmfGsOG7nWkpDQoNCi0gVOG7lW5nIGTDom4gc+G7kSBnaGkgbmjhuq1uIMOtdCBuaOG6pXQgdHJvbmcgNSBuxINtIHF1YSBsw6AgNi45OTcuOTI1IG5nxrDhu51pDQoNCi0gQ8OzIDI1JSB04buVbmcgZMOibiBz4buRIHRo4bqlcCBoxqFuIDQ5LjI3Ni45NzAgbmfGsOG7nWkgdsOgIDc1JSB04buVbmcgZMOibiBz4buRIGzhu5tuIGjGoW4gNDkuMjc2Ljk3MCBuZ8aw4budaQ0KDQotIEPDsyA1MCUgdOG7lW5nIGTDom4gc+G7kSB0aOG6pXAgaMahbiA1My4wNDAuMjEyIHbDoCA1MCUgdOG7lW5nIGTDom4gc+G7kSBjYW8gaMahbiA1My4wNDAuMjEyIG5nxrDhu51pDQoNCi0gNzUlIHThu5VuZyBkw6JuIHPhu5EgdGjhuqVwIGjGoW4gNzEuNDc1LjY2MCBuZ8aw4budaSB2w6AgMjUlIHThu5VuZyBkw6JuIHPhu5EgY2FvIGjGoW4gNzEuNDc1LjY2MCBuZ8aw4budaQ0KDQotIFThu5VuZyBkw6JuIHPhu5EgY2FvIG5o4bqldCBj4bunYSBjw6FjIG7GsOG7m2MgxJDDtG5nIE5hbSDDgSBsw6AgOTcuNDY4LjAyNCBuZ8aw4budaQ0KDQotIFRydW5nIGLDrG5oIHThu5VuZyBkw6JuIHPhu5EgbMOgIDU1LjQ3MS41OTYgKG5nxrDhu51pKQ0KDQotIFThu5VuZyBkw6JuIHPhu5EgY8OhYyBuxrDhu5tjIGPDsyBz4buxIGNow6puaCBs4buHY2ggMjQuMTYxLjIyMyAobmfGsOG7nWkpDQpgYGB7cn0NCmggPC0gZmlsdGVyKG4seWVhciA+PSAnMjAxNycpICMgbOG7jWMgZOG7ryBsaeG7h3UgNSBxdeG7kWMgZ2lhIHRyb25nIG7Eg20gMjAyMSwgZ8OhbiBk4buvIGxp4buHdSB2w6BvIGgNCmBgYA0KIyMjIyBUw61uaCBjw6FjIMSR4bq3YyB0csawbmcgxJFvIGzGsOG7nW5nIGNobyAiaCINCmBgYHtyfQ0Kc3VtKGgkcG9wKSAjIHThu5VuZyBkw6JuIHPhu5EgY+G7p2EgNSBxdeG7kWMgZ2lhDQpzdW1tYXJ5KGgkcG9wKSAjIHTDs20gdOG6r3QgZ2nDoSB0cuG7iyB0cm9uZyBiaeG6v24gcG9wOiBtaW46Z2nDoSB0cuG7iyB04buRaSB0aGnhu4N1OyAxc3QgUXUuOmdpw6EgdHLhu4sgY+G7p2EgdOG7qSBwaMOibiB24buLIHRo4bupIDE7IG1lZGlhbjpnacOhIHRy4buLIHRydW5nIHbhu4s7IDNyZCBRdS46Z2nDoSB0cuG7iyBj4bunYSB04bupIHBow6JuIHbhu4sgdGjhu6kgMzsgbWF4Omdpw6EgdHLhu4sgdOG7kWkgxJFhDQpzZChuJHBvcCkgIyDEkeG7mSBs4buHY2ggY2h14bqpbg0KYGBgDQoNCiMgTmhp4buHbSB24bulIDMuMg0KKioqDQoNCiMjIFTDs20gdOG6r3QNCg0KIyMjIMSQ4buNYyBk4buvIGxp4buHdSB04burIGZpbGUgY3N2DQoNClRo4buxYyBoaeG7h24gY8OhYyB0aGFvIHTDoWMgdHLDqm4gZmlsZSBjc3YgImFsbF92MiIuIEZpbGUgbsOgeSB0aOG7kW5nIGvDqiB24buBIGLhuqV0IMSR4buZbmcgc+G6o24g4bufIE5nYSAyMDE4LTIwMjEsIGJhbyBn4buTbSBjw6FjIHRpw6p1IGNow606DQoNCi0gcHJpY2U6IGdpw6EgdGjDoG5oICggxJHGoW4gduG7izogcnVwcykNCg0KLSBkYXRlOiBuZ8OgeSBjw7RuZyBi4buRIHRow7RuZyBiw6FvDQoNCi0gdGltZTogdGjhu51pIMSRaeG7g20gcXXhuqNuZyBjw6FvIMSRxrDhu6NjIHh14bqldCBi4bqjbg0KDQotIGdlb19sYXQ6IFbEqSDEkeG7mQ0KDQotIGdlb19sb246IEtpbmggxJHhu5kNCg0KLSByZWdpb246IEtodSB24buxYyBj4bunYSBOZ2EuIFThu5VuZyBj4buZbmcgY8OzIDg1IMSR4buRaSB0xrDhu6NuZyB0cm9uZyBj4bqjIG7GsOG7m2MuDQoNCi0gYnVpbGRpbmdfdHlwZTogTG/huqFpIG3hurd0IHRp4buBbi4gMCAtIEtow6FjLiAxIC0gQuG6o25nIMSRaeG7gXUga2hp4buDbi4gMiAtIE5ndXnDqm4ga2jhu5FpLiAzIC0gR+G6oWNoLiA0IC0gS2jhu5FpLiA1IC0gR+G7lw0KDQotIG9iamVjdF90eXBlOiBMb+G6oWkgY8SDbiBo4buZLiAxIC0gVGjhu4sgdHLGsOG7nW5nIGLhuqV0IMSR4buZbmcgc+G6o24gdGjhu6kgY+G6pXA7IDIg4oCTIFjDonkgZOG7sW5nIG3hu5tpDQoNCi0gbGV2ZWw6IFThuqduZyBjxINuIGjhu5kNCnThuqduZw0KDQotIGxldmVsczogU+G7kSB04bqnbmcNCg0KLSByb29tczogc+G7kSBsxrDhu6NuZyBwaMOybmcga2jDoWNoLiBO4bq/dSBnacOhIHRy4buLIGzDoCAiLTEiIHRow6wgY8OzIG5naMSpYSBsw6AgInN0dWRpbyBhcGFydG1lbnQiDQoNCi0gYXJlYTogdOG7lW5nIGRp4buHbiB0w61jaCBjxINuIGjhu5kNCg0KLSBLaXRjaGVuX2FyZWEgLSBLaHUgduG7sWMgYuG6v3ANCg0KYGBge3J9DQpkIDwtIHJlYWQuY3N2KGZpbGUuY2hvb3NlKCksIGhlYWRlciA9IFQpDQpkDQpgYGANCg0KIyMjIFRow7RuZyB0aW4gdOG7lW5nIHF1YW4gY+G7p2EgYuG7mSBk4buvIGxp4buHdQ0KDQpDw6FjIHRow7RuZyB0aW4gdOG7lW5nIHF1w6F0IHbhu4EgZGF0YXNldDoNCg0KLSBMw6AgbeG7mXQgZGF0YSBmcmFtZQ0KDQotIGPDsyAxMyBj4buZdCB0xrDGoW5nIMSRxrDGoW5nIHbhu5tpIDEzIGJp4bq/bg0KDQotIEPDoWMgY+G7mXQgbOG6p24gbMaw4bujdCBsw6A6DQoNCiAgLSBwcmljZTogZ2nDoSB0aMOgbmggKCDEkcahbiB24buLOiBydXBzKQ0KDQogIC0gZGF0ZTogbmfDoHkgY8O0bmcgYuG7kSB0aMO0bmcgYsOhbw0KDQogIC0gdGltZTogdGjhu51pIMSRaeG7g20gcXXhuqNuZyBjw6FvIMSRxrDhu6NjIHh14bqldCBi4bqjbg0KDQogIC0gZ2VvX2xhdDogVsSpIMSR4buZDQoNCiAgLSBnZW9fbG9uOiBLaW5oIMSR4buZDQoNCiAgLSByZWdpb246IEtodSB24buxYyBj4bunYSBOZ2EuIFThu5VuZyBj4buZbmcgY8OzIDg1IMSR4buRaSB0xrDhu6NuZyB0cm9uZyBj4bqjIG7GsOG7m2MuDQoNCiAgLSBidWlsZGluZ190eXBlOiBMb+G6oWkgbeG6t3QgdGnhu4FuLiAwIC0gS2jDoWMuIDEgLSBC4bqjbmcgxJFp4buBdSBraGnhu4NuLjIgLSBOZ3V5w6puIGto4buRaS4gMyAtIEfhuqFjaC4gNCAtIEto4buRaS4gNSAtIEfhu5cNCg0KICAtIG9iamVjdF90eXBlOiBMb+G6oWkgY8SDbiBo4buZLiAxIC0gVGjhu4sgdHLGsOG7nW5nIGLhuqV0IMSR4buZbmcgc+G6o24gdGjhu6kgY+G6pXA7IDIg4oCTIFjDonkgZOG7sW5nIG3hu5tpDQoNCiAgLSBsZXZlbDogVOG6p25nIGPEg24gaOG7mSB04bqnbmcNCg0KICAtIGxldmVsczogU+G7kSB04bqnbmcNCg0KICAtIHJvb21zOiBz4buRIGzGsOG7o25nIHBow7JuZyBraMOhY2guIE7hur91IGdpw6EgdHLhu4sgbMOgICItMSIgdGjDrCBjw7MgbmdoxKlhIGzDoCAic3R1ZGlvIGFwYXJ0bWVudCINCg0KICAtIGFyZWE6IHThu5VuZyBkaeG7h24gdMOtY2ggY8SDbiBo4buZDQoNCiAgLSBLaXRjaGVuX2FyZWEgLSBLaHUgduG7sWMgYuG6v3ANCiAgDQotIEPDsyA1NDc3MDA2IGjDoG5nIHTGsMahbmcgxJHGsMahbmcgNTM3NzAwNiBxdWFuIHPDoXQNCg0KLSBEYXRhIGtow7RuZyBjw7MgZOG7ryBsaeG7h3UgdHLhu5FuZw0KYGBge3J9DQppcy5kYXRhLmZyYW1lKGQpICMga2nhu4NtIHRyYSB4ZW0gImQiIGPDsyBwaOG6o2kgbMOgIGRhdGEgZnJhbWUgaGF5IGtow7RuZywgbuG6v3UgxJHDum5nIGvhur90IHF14bqjIHRy4bqjIHbhu4EgVFJVRSB2w6AgbmfGsOG7o2MgbOG6oWkNCmxlbmd0aChkKSAjIGhp4buDbiB0aOG7iyDEkeG7mSBkw6BpIGPhu6dhIGThu68gbGnhu4d1LCBsw6Agc+G7kSBj4buZdCBj4bunYSAiZCINCm5hbWVzKGQpICMgaGnhu4NuIHRo4buLIHTDqm4gY8OhYyBj4buZdCBj4bunYSAiYSINCmRpbShkKSAjIGhp4buDbiB0aOG7iyBz4buRIGjDoG5nIHbDoCBz4buRIGPhu5l0IGPhu6dhIGQNCnN1bShpcy5uYShkKSkgIyBraeG7g20gdHJhIHThu5VuZyBz4buRIMO0IHRy4buRbmcgY+G7p2EgZOG7ryBsaeG7h3UNCg0KYGBgDQojIyBSw7p0IHRyw61jaCBk4buvIGxp4buHdQ0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KIyBWw6wgZOG7ryBsaeG7h3UgdGh14buZYyBraHUgduG7sWMgTmdhIG7Dqm4gY+G7mXQgcmVnaW9uIGtow7RuZyBjaMOtbmggeMOhYywgdGnhur9uIGjDoG5oIHjDs2EgY+G7mXQgcmVnaW9uIGLhurFuZyBjw6J1IGzhu4duaA0KZCA8LSBzZWxlY3QoZCwtcmVnaW9uKSAjIGLhu5kgZOG7ryBsaeG7h3UgZCBsw6AgYuG7mSBk4buvIGxp4buHdSB24bubaSAxMiBiaeG6v24NCmQgIyBkIHRy4bufIHRow6BuaCBi4buZIGThu68gbGnhu4d1IHbhu5tpIDEyIGJp4bq/bg0KIyBHw6FuIGThu68gbGnhu4d1IMSRxrDhu6NjIHRyw61jaCB2w6BvIGcsIHNhdSDEkcOzIGzhu41jIGLhu5kgZOG7ryBsaeG7h3UgZA0KZyA8LSBkICU+JSBmaWx0ZXIob2JqZWN0X3R5cGUgPT0gMSkgJT4lIHNlbGVjdChwcmljZSxidWlsZGluZ190eXBlLHJvb21zLGFyZWEsb2JqZWN0X3R5cGUpICMga+G6v3QgcXXhuqMgbOG7jWMgY8OhYyBj4buZdCBwcmljZSwgYnVpbGRpbmdfdHlwZSwgcm9vbXMsIGFyZWEgdsOgIG9iamVjdF90eXBlIHbhu5tpIMSRaeG7gXUga2nhu4duIGzDoCB4w6J5IG3hu5tpIChvYmplY3RfdHlwZSA9IDEpDQpzdHIoZykNCmBgYA0KIyMjIFTDs20gdOG6r3QgYuG7mSBk4buvIGxp4buHdSBt4bubaQ0KDQpC4buZIGThu68gbGnhu4d1ICJnIiBsw6AgYuG7mSBk4buvIGxp4buHdSBt4bubaSBwaMOibiB0w61jaCB24buBIGLhuqV0IMSR4buZbmcgc+G6o24g4bufIE5nYSB0aMO0bmcgcXVhIGPDoWMgdGnDqnUgY2jDrToNCg0KLSBwcmljZTogZ2nDoSB0aMOgbmggKHJ1cHMpDQoNCi0gYnVpbGRpbmdfdHlwZTogbG/huqFpIG3hurd0IHRp4buBbg0KDQotIHJvb21zOiBz4buRIGzGsOG7o25nIHBow7JuZyBraMOhY2gNCg0KLSBhcmVhOiB04buVbmcgZGnhu4duIHTDrWNoIGPEg24gaOG7mQ0KDQotIG9iamVjdF90eXBlOiBsb+G6oWkgY8SDbiBo4buZDQoNCkLhu5kgZOG7ryBsaeG7h3UgImciIGzDoCBkYXRhIGZyYW1lIHbhu5tpIDM4NjM4MDkgcXVhbiBzw6F0ICggMzg2MzgwOSBow6BuZykgdsOgIDUgYmnhur9uICggNSBj4buZdCkNCg0KIyMjIE3DoyBow7NhIGThu68gbGnhu4d1DQoNCk3DoyBow7NhIGThu68gbGnhu4d1IGPhu6dhICJnIiB0aMOgbmg6IGPEg24gaOG7mSBt4bubaSAoQXBuZXcpLCBjxINuIGjhu5kgYsOsbmggdGjGsOG7nW5nIChBcG5vcikuIEThu68gbGnhu4d1IMSRxrDhu6NjIG3DoyBow7NhIHRo4buDIGhp4buHbiBsb+G6oWkgcGjDsm5nIGPhu6dhIGPEg24gaOG7mQ0KYGBge3J9DQojIFThuqFvIHJhIGJp4bq/biBt4bubaSBjw7MgdMOqbiByb29tX3R5bGUsIGzhuqV5IHThu6sgYmnhur9uIHJvb21zIHbDoCBvYmplY3RfdHlsZQ0KZyRyb29tX3R5bGUgPC0gaWZlbHNlKGckcm9vbXMgPT0gLTEsICdBcG5ldycsICdBcG5vcicpDQpzdHIoZykNCmBgYA0KDQojIyMgTOG6rXAgYuG6o25nIHThuqduIHPhu5ENCmBgYHtyfQ0KdGFibGUoY3V0KGckYXJlYSwzKSkgIyBz4buRIGzhuqduIHh14bqldCBoaeG7h24gY+G7p2EgMyBwaMOibiB04buVIGFyZWENCmcka2ggPC0gY3V0KGckYXJlYSwzLCBsYWJlbHMgPSBjKCduaOG7jycsJ3RydW5nIGLDrG5oJywnbOG7m24nKSkgIyBnw6FuIHbDoG8ga2gsIHNhdSDEkcOzIHBow6JuIGFyZWEgbMOgbSAzIHThu5UgY8OzIHTDqm4gbOG6p24gbMaw4bujdCBsw6AgJ25o4buPJywndHJ1bmcgYsOsbmgnLCds4bubbicNCnRhYmxlKGckcm9vbV90eWxlLGcka2gpICMgc+G7kSBs4bqnbiB4deG6pXQgaGnhu4duIGPhu6dhIGJp4bq/biByb29tX3R5bGUgdsOgIGtoDQpgYGANCi0gQ8SDbiBo4buZIG3hu5tpIGPDsyAxNTIwMTIgcGjDsm5nIGPDsyBkaeG7h24gdMOtY2ggbmjhu48NCg0KLSBDxINuIGjhu5kgbeG7m2kgY8OzIDEgcGjDsm5nIGPDsyBkaeG7h24gdMOtY2ggdHJ1bmcgYsOsbmgNCg0KLSBLaMO0bmcgY8OzIGPEg24gaOG7mSBt4bubaSBj4buhIGzhu5tuDQoNCi0gQ8SDbiBo4buZIGLDrG5oIHRoxrDhu51uZyBjw7MgMzcxMTcyMiBwaMOybmcgY8OzIGRp4buHbiB0w61jaCBuaOG7jw0KDQotIEPEg24gaOG7mSBiw6xuaCB0aMaw4budbmcgY8OzIDU2IHBow7JuZyBjw7MgZGnhu4duIHTDrWNoIHRydW5nIGLDrG5oDQoNCi0gQ8OzIDggcGjDsm5nIGPDsyBkaeG7h24gdMOtY2ggbOG7m24gdHJvbmcgY8SDbiBo4buZIGLDrG5oIHRoxrDhu51uZw0KDQojIyMgUGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgdGhlbyBnacOhIHRow6BuaA0KYGBge3J9DQojIHTDrW5oIGPDoWMgxJHhurdjIHRyxrBuZyDEkW8gbMaw4budbmcNCnBoIDwtIGcgJT4lIGdyb3VwX2J5KHByaWNlKSAlPiUgc3VtbWFyaXNlKG1lYW5fb2ZfYXJlYSA9IG1lYW4oYXJlYSkpICMgZ8OhbiBk4buvIGxp4buHdSBwaCDEkcaw4bujYyB04bqhbyBi4bufaSBuaMOzbSBwcmljZSB2w6AgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSB04buVbmcgZGnhu4duIHTDrWNoIGPEg24gaOG7mQ0Kc3VtbWFyeShwaCkNCmBgYA0KVGnhur9uIGjDoG5oIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IHRoZW8gZ2nDoSB0aMOgbmgsIHRodSDEkcaw4bujYyBr4bq/dCBxdeG6oyBuaMawIHNhdToNCg0KLSBEaeG7h24gdMOtY2ggdHJ1bmcgYsOsbmggKCBtZWFuKSBj4bunYSBt4buZdCBjxINuIGjhu5kgbMOgIDczLjAyNDgyIG1eMiBjw7MgZ2nDoSB0cnVuZyBiw6xuaCBsw6AgMSwzOTMgdHJp4buHdSBydXBzDQoNCi0gRGnhu4duIHTDrWNoIGPEg24gaOG7mSBuaOG7jyBuaOG6pXQgKG1pbikgbMOgIDEgbTIgY8OzIGdpw6EgdGjhuqVwIG5o4bqldCBsw6AgLTIsMTQ1IHRyaeG7h3UgcnVwcw0KDQotIERp4buHbiB0w61jaCBs4bubbiBuaOG6pXQgY+G7p2EgY8SDbiBo4buZIGzDoCA0MjUwIG0yIGPDsyBnacOhIGNhbyBuaOG6pXQgbMOgIDIsMTQ3IHRyaeG7h3UgcnVwcw0KDQotIEPDsyAyNSUgY8SDbiBo4buZIGPDsyBkaeG7h24gdMOtY2ggdHJ1bmcgYsOsbmggNjEuMm0yLGdpw6EgMiw5OSB0cmnhu4d1IHJ1cHMgdsOgIDc1JSBjxINuIGjhu5kgY8OzIGRp4buHbiB0w61jaCB0cnVuZyBiw6xuaCA2MS4ybTIsIGdpw6EgMi45OSB0cmnhu4d1IHJ1cHMNCg0KLSBDw7MgNTAlIGPEg24gaOG7mSBjw7MgZGnhu4duIHTDrWNoIHRydW5nIGLDrG5oIDczLjAzbTIsIGdpw6EgMS4zOTMgdHJp4buHdSBydXBzIHbDoCA1MCUgY8OybiBs4bqhaQ0KDQotIGPDsyA3NSUgY8SDbiBo4buZIGPDsyBkaeG7h24gdMOtY2ggdHJ1bmcgYsOsbmggODUuMm0yLCBnacOhIDEsMTMzIHRyaeG7h3UgcnVwcyB2w6AgMjUlIGPDsm4gbOG6oWkNCg0KDQoNCg0KDQoNCg0K