1 Tổng quan về bộ dữ liệu

  • Bộ dự liệu ChickenWeight bao gồm các cột sau:

    • Weight (Trọng lượng): Biến này đo lường trọng lượng của gà con và được ghi lại bằng đơn vị grams. Trọng lượng của gà con được theo dõi qua thời gian để đo lường sự phát triển và tăng trưởng của chúng.

    • Time (Thời gian): Biến này thể hiện thời gian quan sát, thường được đo bằng đơn vị ngày. Nó cho biết khoảng thời gian mà mỗi quan sát trọng lượng được thực hiện.

    • Chick (Con gà): Đây là số thứ tự của từng con gà trong bộ dữ liệu. Mỗi con gà có một số thứ tự duy nhất để phân biệt chúng.

    • Diet (Chế độ dinh dưỡng): Biến này chỉ ra loại chế độ dinh dưỡng mà mỗi con gà được cung cấp. Có bốn loại chế độ dinh dưỡng được sử dụng trong bộ dữ liệu, thường được đánh số từ 1 đến 4.

2 Phân tích dữ liệu

Gọi bộ dữ liệu ggplot2 để dùng hiệu quả hơn cho các phép tính

options(repos = c(CRAN = "http://cran.rstudio.com/"))
install.packages("ggplot2")
## Installing package into 'C:/Users/a/AppData/Local/R/win-library/4.3'
## (as 'lib' is unspecified)
## package 'ggplot2' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\a\AppData\Local\Temp\Rtmp21MBeg\downloaded_packages
library(ggplot2)
library(dplyr)
## 
## 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(scales)
library(DT)

Trước hết tôi sẽ gán bộ dữ liệu cho biến cụ thể

ck <- ChickWeight

2.1 Biểu đồ thể hiện số lượng gà theo Diet

ck  %>% group_by(Diet) %>% summarise(n = n()) %>% 
 ggplot( aes( x = as.factor(Diet), y = n)) + 
  geom_col(fill = 'skyblue') + 
  geom_text(aes(label = n), vjust = 1, color = 'red') + 
  xlab('Số thứ tự Chick') + 
  ylab('Số lượng gà') + 
  labs(title = 'Biểu đồ số lượng gà theo loại khẩu phần của gà con') 

  • Nhìn vào ta thấy biểu đồ thể hiện số lượng gà con trên mỗi chế độ dinh dưỡng
  • Loại dinh dưỡng 1 nhiều nhất có 220 con, loại 2 có 120 con, loại 3 có 120 con, loại 4 có 118 con là ít nhất nhưng không đáng kể

2.2 Biểu đồ thể hiện Trọng lượng gà trung bình theo Diet

ck %>% group_by(Diet) %>% summarise(avg = mean(weight)) %>% 
   ggplot(aes(x = as.factor(Diet), y = avg)) + 
  geom_col(fill = 'yellow') + 
  geom_text(aes(label = round(avg,2)), vjust = 1, color = 'red') + 
  labs( x = 'loại Diet', y = 'Trọng lượng gà con trung bình  (gram)', title = 'trọng lượng gà con trung bình theo Diet') + 
  coord_flip() 

  • Biểu đồ thể hiện trọng lượng gà trung bình theo từng loại Diet
  • Loại 1 thấp nhất với trọng lượng trung bình xấp xỉ 102.65, tiếp đó là loại 2 là 122.52, loại 4 là 135.26 và cao nhất là loại 4 với trọng lượng trung bình đạt 142.95

2.3 Biểu độ phân tích trung tâm cân nặng ( theo từng Diet)

ck %>% group_by(Diet) %>% summarise(m= median(weight)) %>% 
  ggplot(aes(x = Diet,y = m)) + 
  geom_col(position = 'dodge', fill = 'pink', color = 'black') +
  geom_text(aes(label = round(m,2)), vjust = 2, color = 'red') + 
  labs(x = 'Loại dinh dưỡng', y = 'Trung vị', title ='Trung vị theo cân nặng từng loại dinh dưỡng')

  • Biểu độ cho ta thấy được trung vị, từng có 50% phần tử bên trong nhỏ hơn và số còn lại lớn hơn. Tức với mỗi từng loại dinh dưỡng, trung vị theo cân nặng sẽ khác nhau.
  • với loại dinh dưỡng 1, có khoảng 50% số kg được ghi nhận là nhỏ hơn 88, 50% số kg được ghi nhân là lớn hơn 88, theo đó thi loại 2 là 104.5, loại 3 là 125.5 và loại dinh dưỡng 4 là 129.5

2.4 Biểu đồ thể hiện tương quan giữa weight và Diet

ck %>% ggplot(aes(x = weight, y = Time, color = Diet)) + 
  geom_point() +
  labs( x = 'cân nặng gà con', y = 'Thời gian quan sát', title = 'Tương quan giữa gà con và cân nặng theo loại dinh dưỡng') 

  • Biểu độ cho ta thấy tượng quan giữa cân nặng gà con theo thời gian quan sát chúng theo từng loại dinh dưỡng
  • Ta thấy được cân nặng gà con càng lớn thì thòi gian quan sát cũng phải lâu, tùy theo loại dinh dưỡng có ảnh hưởng tới cân nặng của gà con
  • Mật độ dinh dưỡng của loại 4, 1 phân bổ rất dày với gà con trong khoảng 0 đến 200 gam.

2.5 Biểu đồ thể hiện số lượng Diet theo Pie chart

ck %>% group_by(Diet) %>% summarise(n=n()) %>% 
  ggplot(aes(x= '', y=n, fill = Diet))+ 
  geom_col(color = 'black', width = 1) + 
  coord_polar('y') +
  geom_text(aes(x = 1.4, label = n), position = position_stack(vjust = .5)) + 
  labs( title = 'Số lượng Diet') +
  theme_void() 

  • Biểu đồ cho ta thấy số lượng gà con của từng loại dinh dưỡng nhưng ở dạng Pie chart
  • với loại 1 là 220 con là lớn nhất và loại 4 là ít nhất với 118 con

2.6 Biểu đồ density thể hiện weight và Diet theo số lượng

ck %>% ggplot( aes(x = weight, fill = as.factor(Diet))) +
  geom_density(alpha = 0.5) +  
  labs(title = "Density plot của trọng lượng gà con theo loại khẩu phần", x = "Trọng lượng (grams)", y = "Mật độ") +
  scale_fill_discrete(name = "Loại khẩu phần") 

  • Biểu đồ cho ta thấy sự phân bố trọng lượng trong mỗi nhóm với từng loại khẩu phần dinh dưỡng cho gà con riêng biệt
  • Mật độ loại một chiếm rất cao và dày trong khoảng từ 100 đến nửa 200g rồi làm giảm một cách rõ rệt, tiếp đó là loại 2 và xuống lần tới loại 3,4
  • Khoang có sự chênh lệnh quá lớn từ khoảng nửa 100 đến 200g trở đi của khẩu phần 1, 2, 3, Loại dinh dưỡng 4 ảnh hưởng lớn đến cân nặng từ 100 đến 200g của gà con

2.7 Biểu đồ thể hiện mật độ trọng trọng lượng gà con (Density plot)

ck %>% ggplot( aes(x = weight, fill = as.factor(Diet))) +
  geom_density(alpha = 0.5) +  
  facet_wrap(~Diet) + 
  labs(title = "Density plot của trọng lượng gà con theo loại khẩu phần", x = "Trọng lượng (grams)", y = "Mật độ") +
  scale_fill_discrete(name = "Loại khẩu phần") 

  • Tương tự như biểu đồ trên, mỗi phần nhỏ chỉ ra mật độ trọng lượng khi cho các loại khẩu phần riêng biệt đối với gà con
  • Loại khẩu phần 1 với trọng lượng gà con 100g đổ lại rất nhiều

2.8 Biểu đồ thể hiện số lượng gà theo Diet

ck %>% group_by(Diet) %>% summarise(n = n()) %>% 
  ggplot(aes(x = '', y = n,fill = Diet)) + 
  geom_col( color = 'black' ) + 
  geom_text(aes(label = n),position = position_stack(vjust = 1)) +
  labs( y = 'số lượng', title = 'số lượng gà con cho mỗi chế độ dinh dưỡng') 

  • Biểu đồ thể hiện cho ta thấy số lượng gà con theo từng loại dinh dưỡng, các số liệu được chồng theo một cột và tùy theo số lượng mà độ dày khác nhau
  • Loại dinh dưỡng 1 có độ dày chiếm ưu thế, số lượng nhiều nhất, 3 loại kia không chênh lệch đáng kể

2.9 Biểu đồ thể hiện tương quan giữa cân nặng gà con và loại dinh dưỡng theo Diet

ck %>% ggplot(aes(x = weight, y = Time, color = Diet)) +
  geom_point() + 
  labs( x = 'cân nặng gà con', y = 'Thời gian quan sát', title = 'Tương quan giữa gà con và cân nặng theo loại dinh dưỡng') + 
geom_smooth(method = 'lm', color = 'black')
## `geom_smooth()` using formula = 'y ~ x'

  • Đường trend line có xu hướng lên trên, mối tương quan dương giữa các dữ liệu
  • Với cân nặng gà con lớn, phải bổ sung dinh dưỡng theo đó mà thời gian quan sát cũng sẽ phải tăng lên

2.10 Biểu đồ thể hiện tỷ lệ dinh dưỡng theo Diet

ck %>% group_by(Diet) %>% summarise(n = n()) %>%  
  ggplot(aes(Diet,n)) + 
  geom_col(fill='green') + 
  geom_text(aes(label = percent(n/length(ck$Diet))),vjust = 2, color = 'red') + 
  labs(x = 'Loại dinh dưỡng', y = 'Số lượng', title = 'Tỷ lệ loại dinh dưỡng') 

  • Biểu đồ cho ta thấy phần trăm số lượng gà con trong mỗi loại dinh dưỡng được nuôi
  • Loại dinh dưỡng số 1 có số lượng gà con chiếm 38.6%, loại dinh dưỡng số 2,3 có 20.76% tổng số lượng gà con, còn lại là loại dinh dưỡng số 4 số lượng gà con chiếm 20.42%.

2.11 Biểu đồ thể hiện Tương quan giữa cân nặng gà con và thời gian quan sát theo loại Diet

ck %>% ggplot(aes(x = weight, y = Time, color = Diet)) + 
  geom_point() + 
  labs( x = 'cân nặng gà con', y = 'Thời gian quan sát', title = 'Tương quan giữa gà con và cân nặng theo loại dinh dưỡng') +  
geom_smooth(method = 'lm', color = 'green') +
  facet_wrap(~Diet) 
## `geom_smooth()` using formula = 'y ~ x'

  • Cân nặng gà con tùy theo từng loại dinh dưỡng có xu hướng tăng theo thời gian quan sát

2.12 Biểu đồ thể hiện lượng cân nặng trung bình theo Diet ( Dạng Pie )

ck %>% group_by(Diet) %>% summarise(n=mean(weight)) %>% 
  ggplot(aes(x= '', y=n, fill = Diet))+ 
  geom_col(color = 'black', width = 1) + 
  coord_polar('y') + 
  geom_text(aes(x = 1.3, label = round(n,2)), position = position_stack(vjust = .5)) + 
  labs( title = 'Trọng lượng trung bình') + 
  theme_void() 

  • Biểu đồ thể hiện trọng lượng gà con trung bình theo từng loại dinh dưỡng
  • Loại 1 có trọng lượng trung bình là 102.65, loại 2 là 122.62, loại 3 là 142.95, loại 4 là 135.26

2.13 Biểu đồ thể hiện thời gian trung bình theo Diet ( dạng Pie )

ck %>% group_by(Diet) %>% summarise(n=mean(Time)) %>% 
  ggplot(aes(x= '', y=n, fill = Diet))+ 
  geom_col(color = 'black', width = 1) + 
  coord_polar('y') + 
  geom_text(aes(x = 1.3, label = round(n,2)), position = position_stack(vjust = .5)) +
  labs( title = 'Thời gian trung bình') + 
  theme_bw()  

  • Thời gian quan sát trung bình của gà con theo từng loại dinh dưỡng
  • Loại dinh dưỡng 1 có thời gian quan sát trung bình là 10.48, loại 2 là 10.92, loại 3 là 10.92 còn loại 4 là 10.75

2.14 Biểu đồ thể hiện tần suất xuất hiện trọng lượng gà con

ck %>% ggplot(aes(x = weight)) + 
  geom_histogram(binwidth = 50, fill = "skyblue", color = "black", aes(y=..count..)) +
  labs(x = "Trọng lượng (g)", y = "Tần suất") + 
  ggtitle("Phân phối của trọng lượng gà con") +
  theme_bw() 

  • Biểu đồ cho thấy tần suất suất hiện các chỉ số trọng lượng gà con
  • tần suất xuất hiện của trọng lượng dưới 100g xuất hiện nhiều nhất hơn 200 lần và giảm dần

2.15 Biểu đồ phân phối trong lượng gà con với tần suất (theo Diet)

ck %>% ggplot(aes(x = weight)) + 
  geom_histogram(binwidth = 50, fill = "skyblue", color = "black", aes(y=..count..)) + 
  labs(x = "Trọng lượng (g)", y = "Tần suất") + 
  facet_wrap(~Diet) + 
  ggtitle("Phân phối của trọng lượng gà con") 

  • Biểu đồ cho ra thấy chỉ số xuất hiện của các chỉ số trọng lượng gà con được phân ra theo loại dinh dưỡng

2.16 Biểu đồ thể hiện tần suất xuất hiện các mốc thời gian quan sát

ck %>% ggplot(aes(x = Time)) + 
  geom_histogram(binwidth = 3, fill = "red", color = "black", aes(y=..count..)) + 
  labs(x = "Thời gian (h)", y = "Tần suất") +
  ggtitle("Phân phối của thời gian theo dõi gà con") + 
  theme_bw() 

  • Biểu đố cho ta thấy các tần suất các khoảng thời gian xuất hiện
  • Khoảng thời gian xuất hiện nhiều nhất từ 0 đến 5 và giảm dần về 20

2.17 Biểu đồ thể hiện trọng lượng gà con theo thời gian (line)

ggplot(ChickWeight, aes(x = Time, y = weight, color = Chick)) +
  geom_line() +
  labs(x = "Thời gian (ngày)", y = "Trọng lượng (g)", color = "Gà") +
  ggtitle("Biểu đồ đường của trọng lượng gà theo thời gian") +
  theme_bw()

2.18 Biểu đồ thể hiện mật độ của trọng lượng gà ( violin plot)

ck %>% ggplot(aes(x = as.factor(Diet), y = weight, fill = as.factor(Diet))) + 
  geom_violin() + 
  labs(x = "chế độ dinh dưỡng", y = "Trọng lượng (g)") +
  ggtitle("Biểu đồ violin plot của trọng lượng gà") + 
  theme_bw()

  • Biểu đồ cho ta thấy mật độ phân phối của trọng lượng các gà con theo từng chế độ dinh dưỡng
  • ở chế độ dinh dưỡng 1 thì có mật độ phân phối trọng lượng dưới 100g nhiều nhất, cả 4 loại đều có xu hướng giảm dần, trọng lượng các lớn thì càng ít, lớn nhất có thể đạt được ở khẩu phần dinh dưỡng số 3

2.19 Biểu đồ thể hiện mật độ trọng lượng qua các mốc

ck %>% 
  ggplot(aes(x = Time, y = weight)) +
  geom_violin(fill = "skyblue", color = "black") +
  labs(x = "Thời gian", y = "Trọng lượng (g)",
       title = "Sự phát triển của trọng lượng gà con  theo thời gian") + 
  theme_bw()

  • Biểu đồ cho ta thấy mật độ phân phối của trọng lượng, trọng lượng càng lớn và ít

2.20 Biểu đồ phân phối trọng lượng dạng Boxplot

ck %>% ggplot(aes(x = factor(Diet), y = weight, fill = factor(Diet))) +
  geom_boxplot() +
  labs(x = "Loại khẩu phần", y = "Trọng lượng gà con", fill = "Loại khẩu phần") + 
  ggtitle("Biểu đồ Boxplot của trọng lượng gà con theo loại khẩu phần") 

  • Biểu đồ cho thấy các giá trị như trung vị, tứ phân vị và các giá trị ngoại vi có thể xuất hiện
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA1Ig0KYXV0aG9yOiAiTMO9IFbEqW5oIE5naGkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclSDolTTolUywgJWQgLSAlbSAtICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jOiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgIHRvYzogdHJ1ZQ0KICAgICB0b2NfZGVwdGg6ICcyJw0KICBwZGZfZG9jdW1lbnQ6DQogICAgbGF0ZXhfZW5naW5lOiB4ZWxhdGV4DQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KIyAqVOG7lW5nIHF1YW4gduG7gSBi4buZIGThu68gbGnhu4d1Kg0KDQoNCi0gQuG7mSBk4buxIGxp4buHdSAqQ2hpY2tlbldlaWdodCogYmFvIGfhu5NtIGPDoWMgY+G7mXQgc2F1Og0KICAgDQogICAtICBXZWlnaHQgKFRy4buNbmcgbMaw4bujbmcpOiBCaeG6v24gbsOgeSDEkW8gbMaw4budbmcgdHLhu41uZyBsxrDhu6NuZyBj4bunYSBnw6AgY29uIHbDoCDEkcaw4bujYyBnaGkgbOG6oWkgYuG6sW5nIMSRxqFuIHbhu4sgZ3JhbXMuIFRy4buNbmcgbMaw4bujbmcgY+G7p2EgZ8OgIGNvbiDEkcaw4bujYyB0aGVvIGTDtWkgcXVhIHRo4budaSBnaWFuIMSR4buDIMSRbyBsxrDhu51uZyBz4buxIHBow6F0IHRyaeG7g24gdsOgIHTEg25nIHRyxrDhu59uZyBj4bunYSBjaMO6bmcuDQoNCiAgIC0gIFRpbWUgKFRo4budaSBnaWFuKTogQmnhur9uIG7DoHkgdGjhu4MgaGnhu4duIHRo4budaSBnaWFuIHF1YW4gc8OhdCwgdGjGsOG7nW5nIMSRxrDhu6NjIMSRbyBi4bqxbmcgxJHGoW4gduG7iyBuZ8OgeS4gTsOzIGNobyBiaeG6v3Qga2hv4bqjbmcgdGjhu51pIGdpYW4gbcOgIG3hu5dpIHF1YW4gc8OhdCB0cuG7jW5nIGzGsOG7o25nIMSRxrDhu6NjIHRo4buxYyBoaeG7h24uDQoNCiAgIC0gIENoaWNrIChDb24gZ8OgKTogxJDDonkgbMOgIHPhu5EgdGjhu6kgdOG7sSBj4bunYSB04burbmcgY29uIGfDoCB0cm9uZyBi4buZIGThu68gbGnhu4d1LiBN4buXaSBjb24gZ8OgIGPDsyBt4buZdCBz4buRIHRo4bupIHThu7EgZHV5IG5o4bqldCDEkeG7gyBwaMOibiBiaeG7h3QgY2jDum5nLg0KDQogICAtICBEaWV0IChDaOG6vyDEkeG7mSBkaW5oIGTGsOG7oW5nKTogQmnhur9uIG7DoHkgY2jhu4kgcmEgbG/huqFpIGNo4bq/IMSR4buZIGRpbmggZMaw4buhbmcgbcOgIG3hu5dpIGNvbiBnw6AgxJHGsOG7o2MgY3VuZyBj4bqlcC4gQ8OzIGLhu5FuIGxv4bqhaSBjaOG6vyDEkeG7mSBkaW5oIGTGsOG7oW5nIMSRxrDhu6NjIHPhu60gZOG7pW5nIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UsIHRoxrDhu51uZyDEkcaw4bujYyDEkcOhbmggc+G7kSB04burIDEgxJHhur9uIDQuDQogICANCiMgKlBow6JuIHTDrWNoIGThu68gbGnhu4d1Kg0KDQpH4buNaSBi4buZIGThu68gbGnhu4d1ICpnZ3Bsb3QyKiDEkeG7gyBkw7luZyBoaeG7h3UgcXXhuqMgaMahbiBjaG8gY8OhYyBwaMOpcCB0w61uaA0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0Kb3B0aW9ucyhyZXBvcyA9IGMoQ1JBTiA9ICJodHRwOi8vY3Jhbi5yc3R1ZGlvLmNvbS8iKSkNCmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShEVCkNCmBgYA0KDQpUcsaw4bubYyBo4bq/dCB0w7RpIHPhur0gZ8OhbiBi4buZIGThu68gbGnhu4d1IGNobyBiaeG6v24gY+G7pSB0aOG7gw0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KY2sgPC0gQ2hpY2tXZWlnaHQNCmBgYA0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgZ8OgIHRoZW8gRGlldA0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KDQpjayAgJT4lIGdyb3VwX2J5KERpZXQpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lIA0KIGdncGxvdCggYWVzKCB4ID0gYXMuZmFjdG9yKERpZXQpLCB5ID0gbikpICsgDQogIGdlb21fY29sKGZpbGwgPSAnc2t5Ymx1ZScpICsgDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSwgdmp1c3QgPSAxLCBjb2xvciA9ICdyZWQnKSArIA0KICB4bGFiKCdT4buRIHRo4bupIHThu7EgQ2hpY2snKSArIA0KICB5bGFiKCdT4buRIGzGsOG7o25nIGfDoCcpICsgDQogIGxhYnModGl0bGUgPSAnQmnhu4N1IMSR4buTIHPhu5EgbMaw4bujbmcgZ8OgIHRoZW8gbG/huqFpIGto4bqpdSBwaOG6p24gY+G7p2EgZ8OgIGNvbicpIA0KYGBgDQogDQotIE5ow6xuIHbDoG8gdGEgdGjhuqV5IGJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBnw6AgY29uIHRyw6puIG3hu5dpIGNo4bq/IMSR4buZIGRpbmggZMaw4buhbmcNCi0gTG/huqFpIGRpbmggZMaw4buhbmcgMSBuaGnhu4F1IG5o4bqldCBjw7MgMjIwIGNvbiwgbG/huqFpIDIgY8OzIDEyMCBjb24sIGxv4bqhaSAzIGPDsyAxMjAgY29uLCBsb+G6oWkgNCBjw7MgMTE4IGNvbiBsw6Agw610IG5o4bqldCBuaMawbmcga2jDtG5nIMSRw6FuZyBr4buDDQoNCiMjIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gVHLhu41uZyBsxrDhu6NuZyBnw6AgdHJ1bmcgYsOsbmggdGhlbyBEaWV0DQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcyd9DQpjayAlPiUgZ3JvdXBfYnkoRGlldCkgJT4lIHN1bW1hcmlzZShhdmcgPSBtZWFuKHdlaWdodCkpICU+JSANCiAgIGdncGxvdChhZXMoeCA9IGFzLmZhY3RvcihEaWV0KSwgeSA9IGF2ZykpICsgDQogIGdlb21fY29sKGZpbGwgPSAneWVsbG93JykgKyANCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGF2ZywyKSksIHZqdXN0ID0gMSwgY29sb3IgPSAncmVkJykgKyANCiAgbGFicyggeCA9ICdsb+G6oWkgRGlldCcsIHkgPSAnVHLhu41uZyBsxrDhu6NuZyBnw6AgY29uIHRydW5nIGLDrG5oICAoZ3JhbSknLCB0aXRsZSA9ICd0cuG7jW5nIGzGsOG7o25nIGfDoCBjb24gdHJ1bmcgYsOsbmggdGhlbyBEaWV0JykgKyANCiAgY29vcmRfZmxpcCgpIA0KYGBgDQoNCi0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIGfDoCB0cnVuZyBiw6xuaCB0aGVvIHThu6tuZyBsb+G6oWkgRGlldA0KLSBMb+G6oWkgMSB0aOG6pXAgbmjhuqV0IHbhu5tpIHRy4buNbmcgbMaw4bujbmcgdHJ1bmcgYsOsbmggeOG6pXAgeOG7iSAxMDIuNjUsIHRp4bq/cCDEkcOzIGzDoCBsb+G6oWkgMiBsw6AgMTIyLjUyLCBsb+G6oWkgNCBsw6AgMTM1LjI2IHbDoCBjYW8gbmjhuqV0IGzDoCBsb+G6oWkgNCB24bubaSB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIMSR4bqhdCAxNDIuOTUNCg0KIyMgQmnhu4N1IMSR4buZIHBow6JuIHTDrWNoIHRydW5nIHTDom0gY8OibiBu4bq3bmcgKCB0aGVvIHThu6tuZyBEaWV0KQ0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KY2sgJT4lIGdyb3VwX2J5KERpZXQpICU+JSBzdW1tYXJpc2UobT0gbWVkaWFuKHdlaWdodCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gRGlldCx5ID0gbSkpICsgDQogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJywgZmlsbCA9ICdwaW5rJywgY29sb3IgPSAnYmxhY2snKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDIpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArIA0KICBsYWJzKHggPSAnTG/huqFpIGRpbmggZMaw4buhbmcnLCB5ID0gJ1RydW5nIHbhu4snLCB0aXRsZSA9J1RydW5nIHbhu4sgdGhlbyBjw6JuIG7hurduZyB04burbmcgbG/huqFpIGRpbmggZMaw4buhbmcnKQ0KYGBgDQoNCi0gQmnhu4N1IMSR4buZIGNobyB0YSB0aOG6pXkgxJHGsOG7o2MgdHJ1bmcgduG7iywgdOG7q25nIGPDsyA1MCUgcGjhuqduIHThu60gYsOqbiB0cm9uZyBuaOG7jyBoxqFuIHbDoCBz4buRIGPDsm4gbOG6oWkgbOG7m24gaMahbi4gVOG7qWMgduG7m2kgbeG7l2kgdOG7q25nIGxv4bqhaSBkaW5oIGTGsOG7oW5nLCB0cnVuZyB24buLIHRoZW8gY8OibiBu4bq3bmcgc+G6vSBraMOhYyBuaGF1Lg0KLSB24bubaSBsb+G6oWkgZGluaCBkxrDhu6FuZyAxLCBjw7Mga2hv4bqjbmcgNTAlIHPhu5Ega2cgxJHGsOG7o2MgZ2hpIG5o4bqtbiBsw6Agbmjhu48gaMahbiA4OCwgNTAlIHPhu5Ega2cgxJHGsOG7o2MgZ2hpIG5ow6JuIGzDoCBs4bubbiBoxqFuIDg4LCB0aGVvIMSRw7MgdGhpIGxv4bqhaSAyIGzDoCAxMDQuNSwgbG/huqFpIDMgbMOgIDEyNS41IHbDoCBsb+G6oWkgZGluaCBkxrDhu6FuZyA0IGzDoCAxMjkuNQ0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHTGsMahbmcgcXVhbiBnaeG7r2Egd2VpZ2h0IHbDoCBEaWV0DQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcyd9DQpjayAlPiUgZ2dwbG90KGFlcyh4ID0gd2VpZ2h0LCB5ID0gVGltZSwgY29sb3IgPSBEaWV0KSkgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicyggeCA9ICdjw6JuIG7hurduZyBnw6AgY29uJywgeSA9ICdUaOG7nWkgZ2lhbiBxdWFuIHPDoXQnLCB0aXRsZSA9ICdUxrDGoW5nIHF1YW4gZ2nhu69hIGfDoCBjb24gdsOgIGPDom4gbuG6t25nIHRoZW8gbG/huqFpIGRpbmggZMaw4buhbmcnKSANCmBgYA0KDQotICBCaeG7g3UgxJHhu5kgY2hvIHRhIHRo4bqleSB0xrDhu6NuZyBxdWFuIGdp4buvYSBjw6JuIG7hurduZyBnw6AgY29uIHRoZW8gdGjhu51pIGdpYW4gcXVhbiBzw6F0IGNow7puZyB0aGVvIHThu6tuZyBsb+G6oWkgZGluaCBkxrDhu6FuZw0KLSAgVGEgdGjhuqV5IMSRxrDhu6NjIGPDom4gbuG6t25nIGfDoCBjb24gY8OgbmcgbOG7m24gdGjDrCB0aMOyaSBnaWFuIHF1YW4gc8OhdCBjxaluZyBwaOG6o2kgbMOidSwgdMO5eSB0aGVvIGxv4bqhaSBkaW5oIGTGsOG7oW5nIGPDsyDhuqNuaCBoxrDhu59uZyB04bubaSBjw6JuIG7hurduZyBj4bunYSBnw6AgY29uDQotICBN4bqtdCDEkeG7mSBkaW5oIGTGsOG7oW5nIGPhu6dhIGxv4bqhaSA0LCAxIHBow6JuIGLhu5UgcuG6pXQgZMOgeSB24bubaSBnw6AgY29uIHRyb25nIGtob+G6o25nIDAgxJHhur9uIDIwMCBnYW0uDQoNCiMjIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBEaWV0IHRoZW8gUGllIGNoYXJ0DQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcyd9DQpjayAlPiUgZ3JvdXBfYnkoRGlldCkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9ICcnLCB5PW4sIGZpbGwgPSBEaWV0KSkrIA0KICBnZW9tX2NvbChjb2xvciA9ICdibGFjaycsIHdpZHRoID0gMSkgKyANCiAgY29vcmRfcG9sYXIoJ3knKSArDQogIGdlb21fdGV4dChhZXMoeCA9IDEuNCwgbGFiZWwgPSBuKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSkgKyANCiAgbGFicyggdGl0bGUgPSAnU+G7kSBsxrDhu6NuZyBEaWV0JykgKw0KICB0aGVtZV92b2lkKCkgDQpgYGANCg0KLSBCaeG7g3UgxJHhu5MgY2hvIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGfDoCBjb24gY+G7p2EgdOG7q25nIGxv4bqhaSBkaW5oIGTGsOG7oW5nIG5oxrBuZyDhu58gZOG6oW5nIFBpZSBjaGFydA0KLSB24bubaSBsb+G6oWkgMSBsw6AgMjIwIGNvbiBsw6AgbOG7m24gbmjhuqV0IHbDoCBsb+G6oWkgNCBsw6Agw610IG5o4bqldCB24bubaSAxMTggY29uDQoNCiMjIEJp4buDdSDEkeG7kyBkZW5zaXR5IHRo4buDIGhp4buHbiB3ZWlnaHQgdsOgIERpZXQgdGhlbyBz4buRIGzGsOG7o25nDQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcyd9DQpjayAlPiUgZ2dwbG90KCBhZXMoeCA9IHdlaWdodCwgZmlsbCA9IGFzLmZhY3RvcihEaWV0KSkpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC41KSArICANCiAgbGFicyh0aXRsZSA9ICJEZW5zaXR5IHBsb3QgY+G7p2EgdHLhu41uZyBsxrDhu6NuZyBnw6AgY29uIHRoZW8gbG/huqFpIGto4bqpdSBwaOG6p24iLCB4ID0gIlRy4buNbmcgbMaw4bujbmcgKGdyYW1zKSIsIHkgPSAiTeG6rXQgxJHhu5kiKSArDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJMb+G6oWkga2jhuql1IHBo4bqnbiIpIA0KYGBgDQoNCi0gQmnhu4N1IMSR4buTIGNobyB0YSB0aOG6pXkgc+G7sSBwaMOibiBi4buRIHRy4buNbmcgbMaw4bujbmcgdHJvbmcgbeG7l2kgbmjDs20gduG7m2kgdOG7q25nIGxv4bqhaSBraOG6qXUgcGjhuqduIGRpbmggZMaw4buhbmcgY2hvIGfDoCBjb24gcmnDqm5nIGJp4buHdA0KLSBN4bqtdCDEkeG7mSBsb+G6oWkgbeG7mXQgY2hp4bq/bSBy4bqldCBjYW8gdsOgIGTDoHkgdHJvbmcga2hv4bqjbmcgdOG7qyAxMDAgxJHhur9uIG7hu61hIDIwMGcgcuG7k2kgbMOgbSBnaeG6o20gbeG7mXQgY8OhY2ggcsO1IHLhu4d0LCB0aeG6v3AgxJHDsyBsw6AgbG/huqFpIDIgdsOgIHh14buRbmcgbOG6p24gdOG7m2kgbG/huqFpIDMsNA0KLSBLaG9hbmcgY8OzIHPhu7EgY2jDqm5oIGzhu4duaCBxdcOhIGzhu5tuIHThu6sga2hv4bqjbmcgbuG7rWEgMTAwIMSR4bq/biAyMDBnIHRy4bufIMSRaSBj4bunYSBraOG6qXUgcGjhuqduIDEsIDIsIDMsIExv4bqhaSBkaW5oIGTGsOG7oW5nIDQg4bqjbmggaMaw4bufbmcgbOG7m24gxJHhur9uIGPDom4gbuG6t25nIHThu6sgMTAwIMSR4bq/biAyMDBnIGPhu6dhIGfDoCBjb24NCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBt4bqtdCDEkeG7mSB0cuG7jW5nIHRy4buNbmcgbMaw4bujbmcgZ8OgIGNvbiAoRGVuc2l0eSBwbG90KQ0KYGBge3IgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBhdHRyLnNvdXJjZT0nLm51bWJlckxpbmVzJ30NCmNrICU+JSBnZ3Bsb3QoIGFlcyh4ID0gd2VpZ2h0LCBmaWxsID0gYXMuZmFjdG9yKERpZXQpKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjUpICsgIA0KICBmYWNldF93cmFwKH5EaWV0KSArIA0KICBsYWJzKHRpdGxlID0gIkRlbnNpdHkgcGxvdCBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGfDoCBjb24gdGhlbyBsb+G6oWkga2jhuql1IHBo4bqnbiIsIHggPSAiVHLhu41uZyBsxrDhu6NuZyAoZ3JhbXMpIiwgeSA9ICJN4bqtdCDEkeG7mSIpICsNCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkxv4bqhaSBraOG6qXUgcGjhuqduIikgDQpgYGANCg0KLSBUxrDGoW5nIHThu7EgbmjGsCBiaeG7g3UgxJHhu5MgdHLDqm4sIG3hu5dpIHBo4bqnbiBuaOG7jyBjaOG7iSByYSBt4bqtdCDEkeG7mSB0cuG7jW5nIGzGsOG7o25nIGtoaSBjaG8gY8OhYyBsb+G6oWkga2jhuql1IHBo4bqnbiByacOqbmcgYmnhu4d0IMSR4buRaSB24bubaSBnw6AgY29uDQotIExv4bqhaSBraOG6qXUgcGjhuqduIDEgduG7m2kgdHLhu41uZyBsxrDhu6NuZyBnw6AgY29uIDEwMGcgxJHhu5UgbOG6oWkgcuG6pXQgbmhp4buBdQ0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgZ8OgIHRoZW8gRGlldA0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KY2sgJT4lIGdyb3VwX2J5KERpZXQpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSAnJywgeSA9IG4sZmlsbCA9IERpZXQpKSArIA0KICBnZW9tX2NvbCggY29sb3IgPSAnYmxhY2snICkgKyANCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAxKSkgKw0KICBsYWJzKCB5ID0gJ3Phu5EgbMaw4bujbmcnLCB0aXRsZSA9ICdz4buRIGzGsOG7o25nIGfDoCBjb24gY2hvIG3hu5dpIGNo4bq/IMSR4buZIGRpbmggZMaw4buhbmcnKSANCmBgYA0KDQotIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gY2hvIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGfDoCBjb24gdGhlbyB04burbmcgbG/huqFpIGRpbmggZMaw4buhbmcsIGPDoWMgc+G7kSBsaeG7h3UgxJHGsOG7o2MgY2jhu5NuZyB0aGVvIG3hu5l0IGPhu5l0IHbDoCB0w7l5IHRoZW8gc+G7kSBsxrDhu6NuZyBtw6AgxJHhu5kgZMOgeSBraMOhYyBuaGF1DQotIExv4bqhaSBkaW5oIGTGsOG7oW5nIDEgY8OzIMSR4buZIGTDoHkgY2hp4bq/bSDGsHUgdGjhur8sIHPhu5EgbMaw4bujbmcgbmhp4buBdSBuaOG6pXQsIDMgbG/huqFpIGtpYSBraMO0bmcgY2jDqm5oIGzhu4djaCDEkcOhbmcga+G7gw0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHTGsMahbmcgcXVhbiBnaeG7r2EgY8OibiBu4bq3bmcgZ8OgIGNvbiB2w6AgbG/huqFpIGRpbmggZMaw4buhbmcgdGhlbyBEaWV0DQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcyd9DQpjayAlPiUgZ2dwbG90KGFlcyh4ID0gd2VpZ2h0LCB5ID0gVGltZSwgY29sb3IgPSBEaWV0KSkgKw0KICBnZW9tX3BvaW50KCkgKyANCiAgbGFicyggeCA9ICdjw6JuIG7hurduZyBnw6AgY29uJywgeSA9ICdUaOG7nWkgZ2lhbiBxdWFuIHPDoXQnLCB0aXRsZSA9ICdUxrDGoW5nIHF1YW4gZ2nhu69hIGfDoCBjb24gdsOgIGPDom4gbuG6t25nIHRoZW8gbG/huqFpIGRpbmggZMaw4buhbmcnKSArIA0KZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgY29sb3IgPSAnYmxhY2snKQ0KYGBgDQoNCi0gxJDGsOG7nW5nIHRyZW5kIGxpbmUgY8OzIHh1IGjGsOG7m25nIGzDqm4gdHLDqm4sIG3hu5FpIHTGsMahbmcgcXVhbiBkxrDGoW5nIGdp4buvYSBjw6FjIGThu68gbGnhu4d1DQotIFbhu5tpIGPDom4gbuG6t25nIGfDoCBjb24gbOG7m24sIHBo4bqjaSBi4buVIHN1bmcgZGluaCBkxrDhu6FuZyB0aGVvIMSRw7MgbcOgIHRo4budaSBnaWFuIHF1YW4gc8OhdCBjxaluZyBz4bq9IHBo4bqjaSB0xINuZyBsw6puDQoNCiMjIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gdOG7tyBs4buHIGRpbmggZMaw4buhbmcgdGhlbyBEaWV0IA0KICANCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcyd9DQpjayAlPiUgZ3JvdXBfYnkoRGlldCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUgIA0KICBnZ3Bsb3QoYWVzKERpZXQsbikpICsgDQogIGdlb21fY29sKGZpbGw9J2dyZWVuJykgKyANCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgoY2skRGlldCkpKSx2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsgDQogIGxhYnMoeCA9ICdMb+G6oWkgZGluaCBkxrDhu6FuZycsIHkgPSAnU+G7kSBsxrDhu6NuZycsIHRpdGxlID0gJ1Thu7cgbOG7hyBsb+G6oWkgZGluaCBkxrDhu6FuZycpIA0KYGBgDQoNCi0gQmnhu4N1IMSR4buTIGNobyB0YSB0aOG6pXkgcGjhuqduIHRyxINtIHPhu5EgbMaw4bujbmcgZ8OgIGNvbiB0cm9uZyBt4buXaSBsb+G6oWkgZGluaCBkxrDhu6FuZyDEkcaw4bujYyBudcO0aQ0KLSBMb+G6oWkgZGluaCBkxrDhu6FuZyBz4buRIDEgY8OzIHPhu5EgbMaw4bujbmcgZ8OgIGNvbiBjaGnhur9tIDM4LjYlLCBsb+G6oWkgZGluaCBkxrDhu6FuZyBz4buRIDIsMyBjw7MgMjAuNzYlIHThu5VuZyBz4buRIGzGsOG7o25nIGfDoCBjb24sIGPDsm4gbOG6oWkgbMOgIGxv4bqhaSBkaW5oIGTGsOG7oW5nIHPhu5EgNCBz4buRIGzGsOG7o25nIGfDoCBjb24gY2hp4bq/bSAyMC40MiUuDQoNCiMjIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gVMawxqFuZyBxdWFuIGdp4buvYSBjw6JuIG7hurduZyBnw6AgY29uIHbDoCB0aOG7nWkgZ2lhbiBxdWFuIHPDoXQgdGhlbyBsb+G6oWkgRGlldA0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KY2sgJT4lIGdncGxvdChhZXMoeCA9IHdlaWdodCwgeSA9IFRpbWUsIGNvbG9yID0gRGlldCkpICsgDQogIGdlb21fcG9pbnQoKSArIA0KICBsYWJzKCB4ID0gJ2PDom4gbuG6t25nIGfDoCBjb24nLCB5ID0gJ1Ro4budaSBnaWFuIHF1YW4gc8OhdCcsIHRpdGxlID0gJ1TGsMahbmcgcXVhbiBnaeG7r2EgZ8OgIGNvbiB2w6AgY8OibiBu4bq3bmcgdGhlbyBsb+G6oWkgZGluaCBkxrDhu6FuZycpICsgIA0KZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgY29sb3IgPSAnZ3JlZW4nKSArDQogIGZhY2V0X3dyYXAofkRpZXQpIA0KYGBgDQoNCi0gQ8OibiBu4bq3bmcgZ8OgIGNvbiB0w7l5IHRoZW8gdOG7q25nIGxv4bqhaSBkaW5oIGTGsOG7oW5nIGPDsyB4dSBoxrDhu5tuZyB0xINuZyB0aGVvIHRo4budaSBnaWFuIHF1YW4gc8OhdA0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGzGsOG7o25nIGPDom4gbuG6t25nIHRydW5nIGLDrG5oIHRoZW8gRGlldCAoIEThuqFuZyBQaWUgKQ0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KY2sgJT4lIGdyb3VwX2J5KERpZXQpICU+JSBzdW1tYXJpc2Uobj1tZWFuKHdlaWdodCkpICU+JSANCiAgZ2dwbG90KGFlcyh4PSAnJywgeT1uLCBmaWxsID0gRGlldCkpKyANCiAgZ2VvbV9jb2woY29sb3IgPSAnYmxhY2snLCB3aWR0aCA9IDEpICsgDQogIGNvb3JkX3BvbGFyKCd5JykgKyANCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMS4zLCBsYWJlbCA9IHJvdW5kKG4sMikpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gLjUpKSArIA0KICBsYWJzKCB0aXRsZSA9ICdUcuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oJykgKyANCiAgdGhlbWVfdm9pZCgpIA0KYGBgDQoNCi0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIGfDoCBjb24gdHJ1bmcgYsOsbmggdGhlbyB04burbmcgbG/huqFpIGRpbmggZMaw4buhbmcNCi0gTG/huqFpIDEgY8OzIHRy4buNbmcgbMaw4bujbmcgdHJ1bmcgYsOsbmggbMOgIDEwMi42NSwgbG/huqFpIDIgbMOgIDEyMi42MiwgbG/huqFpIDMgbMOgIDE0Mi45NSwgbG/huqFpIDQgbMOgIDEzNS4yNg0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHRo4budaSBnaWFuIHRydW5nIGLDrG5oIHRoZW8gRGlldCAoIGThuqFuZyBQaWUgKQ0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KY2sgJT4lIGdyb3VwX2J5KERpZXQpICU+JSBzdW1tYXJpc2Uobj1tZWFuKFRpbWUpKSAlPiUgDQogIGdncGxvdChhZXMoeD0gJycsIHk9biwgZmlsbCA9IERpZXQpKSsgDQogIGdlb21fY29sKGNvbG9yID0gJ2JsYWNrJywgd2lkdGggPSAxKSArIA0KICBjb29yZF9wb2xhcigneScpICsgDQogIGdlb21fdGV4dChhZXMoeCA9IDEuMywgbGFiZWwgPSByb3VuZChuLDIpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSkgKw0KICBsYWJzKCB0aXRsZSA9ICdUaOG7nWkgZ2lhbiB0cnVuZyBiw6xuaCcpICsgDQogIHRoZW1lX2J3KCkgIA0KYGBgDQoNCi0gVGjhu51pIGdpYW4gcXVhbiBzw6F0IHRydW5nIGLDrG5oIGPhu6dhIGfDoCBjb24gdGhlbyB04burbmcgbG/huqFpIGRpbmggZMaw4buhbmcNCi0gTG/huqFpIGRpbmggZMaw4buhbmcgMSBjw7MgdGjhu51pIGdpYW4gcXVhbiBzw6F0IHRydW5nIGLDrG5oIGzDoCAxMC40OCwgbG/huqFpIDIgbMOgIDEwLjkyLCBsb+G6oWkgMyBsw6AgMTAuOTIgY8OybiBsb+G6oWkgNCBsw6AgMTAuNzUNCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiB04bqnbiBzdeG6pXQgeHXhuqV0IGhp4buHbiB0cuG7jW5nIGzGsOG7o25nIGfDoCBjb24NCg0KYGBge3IgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBhdHRyLnNvdXJjZT0nLm51bWJlckxpbmVzJ30NCmNrICU+JSBnZ3Bsb3QoYWVzKHggPSB3ZWlnaHQpKSArIA0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUwLCBmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJibGFjayIsIGFlcyh5PS4uY291bnQuLikpICsNCiAgbGFicyh4ID0gIlRy4buNbmcgbMaw4bujbmcgKGcpIiwgeSA9ICJU4bqnbiBzdeG6pXQiKSArIA0KICBnZ3RpdGxlKCJQaMOibiBwaOG7kWkgY+G7p2EgdHLhu41uZyBsxrDhu6NuZyBnw6AgY29uIikgKw0KICB0aGVtZV9idygpIA0KYGBgDQoNCi0gQmnhu4N1IMSR4buTIGNobyB0aOG6pXkgdOG6p24gc3XhuqV0IHN14bqldCBoaeG7h24gY8OhYyBjaOG7iSBz4buRIHRy4buNbmcgbMaw4bujbmcgZ8OgIGNvbg0KLSB04bqnbiBzdeG6pXQgeHXhuqV0IGhp4buHbiBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGTGsOG7m2kgMTAwZyB4deG6pXQgaGnhu4duIG5oaeG7gXUgbmjhuqV0IGjGoW4gMjAwIGzhuqduIHbDoCBnaeG6o20gZOG6p24NCg0KIyMgQmnhu4N1IMSR4buTIHBow6JuIHBo4buRaSB0cm9uZyBsxrDhu6NuZyBnw6AgY29uIHbhu5tpIHThuqduIHN14bqldCAgKHRoZW8gRGlldCkNCg0KYGBge3IgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBhdHRyLnNvdXJjZT0nLm51bWJlckxpbmVzJ30NCmNrICU+JSBnZ3Bsb3QoYWVzKHggPSB3ZWlnaHQpKSArIA0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUwLCBmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJibGFjayIsIGFlcyh5PS4uY291bnQuLikpICsgDQogIGxhYnMoeCA9ICJUcuG7jW5nIGzGsOG7o25nIChnKSIsIHkgPSAiVOG6p24gc3XhuqV0IikgKyANCiAgZmFjZXRfd3JhcCh+RGlldCkgKyANCiAgZ2d0aXRsZSgiUGjDom4gcGjhu5FpIGPhu6dhIHRy4buNbmcgbMaw4bujbmcgZ8OgIGNvbiIpIA0KYGBgDQoNCi0gIEJp4buDdSDEkeG7kyBjaG8gcmEgdGjhuqV5IGNo4buJIHPhu5EgeHXhuqV0IGhp4buHbiBj4bunYSBjw6FjIGNo4buJIHPhu5EgdHLhu41uZyBsxrDhu6NuZyBnw6AgY29uIMSRxrDhu6NjIHBow6JuIHJhIHRoZW8gbG/huqFpIGRpbmggZMaw4buhbmcNCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiB04bqnbiBzdeG6pXQgeHXhuqV0IGhp4buHbiBjw6FjIG3hu5FjIHRo4budaSBnaWFuIHF1YW4gc8OhdA0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KY2sgJT4lIGdncGxvdChhZXMoeCA9IFRpbWUpKSArIA0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDMsIGZpbGwgPSAicmVkIiwgY29sb3IgPSAiYmxhY2siLCBhZXMoeT0uLmNvdW50Li4pKSArIA0KICBsYWJzKHggPSAiVGjhu51pIGdpYW4gKGgpIiwgeSA9ICJU4bqnbiBzdeG6pXQiKSArDQogIGdndGl0bGUoIlBow6JuIHBo4buRaSBj4bunYSB0aOG7nWkgZ2lhbiB0aGVvIGTDtWkgZ8OgIGNvbiIpICsgDQogIHRoZW1lX2J3KCkgDQpgYGANCg0KLSBCaeG7g3UgxJHhu5EgY2hvIHRhIHRo4bqleSBjw6FjIHThuqduIHN14bqldCBjw6FjICBraG/huqNuZyB0aOG7nWkgZ2lhbiB4deG6pXQgaGnhu4duDQotIEtob+G6o25nIHRo4budaSBnaWFuIHh14bqldCBoaeG7h24gbmhp4buBdSBuaOG6pXQgdOG7qyAwIMSR4bq/biA1IHbDoCBnaeG6o20gZOG6p24gduG7gSAyMA0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHRy4buNbmcgbMaw4bujbmcgZ8OgIGNvbiB0aGVvIHRo4budaSBnaWFuIChsaW5lKQ0KYGBge3IgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBhdHRyLnNvdXJjZT0nLm51bWJlckxpbmVzJ30NCmdncGxvdChDaGlja1dlaWdodCwgYWVzKHggPSBUaW1lLCB5ID0gd2VpZ2h0LCBjb2xvciA9IENoaWNrKSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGxhYnMoeCA9ICJUaOG7nWkgZ2lhbiAobmfDoHkpIiwgeSA9ICJUcuG7jW5nIGzGsOG7o25nIChnKSIsIGNvbG9yID0gIkfDoCIpICsNCiAgZ2d0aXRsZSgiQmnhu4N1IMSR4buTIMSRxrDhu51uZyBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGfDoCB0aGVvIHRo4budaSBnaWFuIikgKw0KICB0aGVtZV9idygpDQpgYGANCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBt4bqtdCDEkeG7mSBj4bunYSB0cuG7jW5nIGzGsOG7o25nIGfDoCAoIHZpb2xpbiBwbG90KQ0KDQpgYGB7ciBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGF0dHIuc291cmNlPScubnVtYmVyTGluZXMnfQ0KY2sgJT4lIGdncGxvdChhZXMoeCA9IGFzLmZhY3RvcihEaWV0KSwgeSA9IHdlaWdodCwgZmlsbCA9IGFzLmZhY3RvcihEaWV0KSkpICsgDQogIGdlb21fdmlvbGluKCkgKyANCiAgbGFicyh4ID0gImNo4bq/IMSR4buZIGRpbmggZMaw4buhbmciLCB5ID0gIlRy4buNbmcgbMaw4bujbmcgKGcpIikgKw0KICBnZ3RpdGxlKCJCaeG7g3UgxJHhu5MgdmlvbGluIHBsb3QgY+G7p2EgdHLhu41uZyBsxrDhu6NuZyBnw6AiKSArIA0KICB0aGVtZV9idygpDQpgYGANCg0KLSBCaeG7g3UgxJHhu5MgY2hvIHRhIHRo4bqleSBt4bqtdCDEkeG7mSBwaMOibiBwaOG7kWkgY+G7p2EgdHLhu41uZyBsxrDhu6NuZyBjw6FjIGfDoCBjb24gdGhlbyB04burbmcgY2jhur8gxJHhu5kgZGluaCBkxrDhu6FuZw0KLSDhu58gY2jhur8gxJHhu5kgZGluaCBkxrDhu6FuZyAxIHRow6wgY8OzIG3huq10IMSR4buZIHBow6JuIHBo4buRaSB0cuG7jW5nIGzGsOG7o25nIGTGsOG7m2kgMTAwZyBuaGnhu4F1IG5o4bqldCwgY+G6oyA0IGxv4bqhaSDEkeG7gXUgY8OzIHh1IGjGsOG7m25nIGdp4bqjbSBk4bqnbiwgdHLhu41uZyBsxrDhu6NuZyBjw6FjIGzhu5tuIHRow6wgY8Ogbmcgw610LCBs4bubbiBuaOG6pXQgY8OzIHRo4buDIMSR4bqhdCDEkcaw4bujYyDhu58ga2jhuql1IHBo4bqnbiBkaW5oIGTGsOG7oW5nIHPhu5EgMw0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG3huq10IMSR4buZIHRy4buNbmcgbMaw4bujbmcgcXVhIGPDoWMgbeG7kWMgDQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcyd9DQpjayAlPiUgDQogIGdncGxvdChhZXMoeCA9IFRpbWUsIHkgPSB3ZWlnaHQpKSArDQogIGdlb21fdmlvbGluKGZpbGwgPSAic2t5Ymx1ZSIsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHggPSAiVGjhu51pIGdpYW4iLCB5ID0gIlRy4buNbmcgbMaw4bujbmcgKGcpIiwNCiAgICAgICB0aXRsZSA9ICJT4buxIHBow6F0IHRyaeG7g24gY+G7p2EgdHLhu41uZyBsxrDhu6NuZyBnw6AgY29uICB0aGVvIHRo4budaSBnaWFuIikgKyANCiAgdGhlbWVfYncoKQ0KYGBgDQoNCi0gQmnhu4N1IMSR4buTIGNobyB0YSB0aOG6pXkgbeG6rXQgxJHhu5kgcGjDom4gcGjhu5FpIGPhu6dhIHRy4buNbmcgbMaw4bujbmcsIHRy4buNbmcgbMaw4bujbmcgY8OgbmcgbOG7m24gdsOgIMOtdCANCg0KIyMgQmnhu4N1IMSR4buTIHBow6JuIHBo4buRaSB0cuG7jW5nIGzGsOG7o25nIGThuqFuZyBCb3hwbG90DQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcyd9DQpjayAlPiUgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKERpZXQpLCB5ID0gd2VpZ2h0LCBmaWxsID0gZmFjdG9yKERpZXQpKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnMoeCA9ICJMb+G6oWkga2jhuql1IHBo4bqnbiIsIHkgPSAiVHLhu41uZyBsxrDhu6NuZyBnw6AgY29uIiwgZmlsbCA9ICJMb+G6oWkga2jhuql1IHBo4bqnbiIpICsgDQogIGdndGl0bGUoIkJp4buDdSDEkeG7kyBCb3hwbG90IGPhu6dhIHRy4buNbmcgbMaw4bujbmcgZ8OgIGNvbiB0aGVvIGxv4bqhaSBraOG6qXUgcGjhuqduIikgDQpgYGANCg0KLSBCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSBjw6FjIGdpw6EgdHLhu4sgbmjGsCB0cnVuZyB24buLLCB04bupIHBow6JuIHbhu4sgdsOgIGPDoWMgZ2nDoSB0cuG7iyBuZ2/huqFpIHZpIGPDsyB0aOG7gyB4deG6pXQgaGnhu4duDQoNCg0KDQo=