GIỚI THIỆU VỀ BỘ DỮ LIỆU APPLE QUALITY
Apple Quality là bộ dữ liệu chứa các về các thuộc tính khác nhau của
một bộ trái cây,cụ thể hơn là táo và cung cấp thông tin chi tiết về đặc
điểm của chúng. Bộ dữ liệu bao gồm các chi tiết như ID trái cây, kích
thước, trọng lượng, độ ngọt, độ giòn, độ ngon ngọt, độ chín, độ chua và
chất lượng.
Bộ dữ liệu được cung cấp rộng rãi bởi một công ty nông nghiệp Mỹ và
đã được thu nhỏ và làm sạch để dễ sử dụng.
Bộ dữ liệu bao gồm các thuộc tính sau:
A_id: Id của trái táo.
Size: kích thước của trái táo.
Weight: trọng lượng của trái táo.
Sweetness: Độ ngọt của trái táo.
Crunchiness: độ giòn của trái táo.
Juiciness: độ mọng nước của trái táo.
Ripeness: độ chín của trái táo.
Acidity: độ chua của trái táo.
Quality: chất lượng của trái táo.
str(d)
## 'data.frame': 4001 obs. of 9 variables:
## $ A_id : int 0 1 2 3 4 5 6 7 8 9 ...
## $ Size : num -3.97 -1.195 -0.292 -0.657 1.364 ...
## $ Weight : num -2.51 -2.84 -1.35 -2.27 -1.3 ...
## $ Sweetness : num 5.346 3.664 -1.738 1.325 -0.385 ...
## $ Crunchiness: num -1.012 1.5882 -0.3426 -0.0979 -0.553 ...
## $ Juiciness : num 1.845 0.853 2.839 3.638 3.031 ...
## $ Ripeness : num 0.33 0.868 -0.038 -3.414 -1.304 ...
## $ Acidity : chr "-0.491590483" "-0.722809367" "2.621636473" "0.790723217" ...
## $ Quality : chr "good" "good" "bad" "good" ...
BIỂU ĐỒ
Biến “quality” là một biến phân loại (categorical) trong bộ dữ liệu
“Apple Qualty” và được sử dụng để đánh giá mức độ chất lượng của trái
táo.
Biến này có 2 mước đánh giá khác nhau được mô tả như sau:
table(d$Quality)
##
## bad good
## 1 1996 2004
Biểu đồ cột cho biến “quality”:
d %>% group_by(Quality) %>% summarise(n = n()) %>%
ggplot(aes(Quality,n)) +
geom_col(fill='dark blue') +
labs(title = " BIỂU ĐỒ THỂ HIỆN NHÓM THEO QUALITY ") +
geom_text(aes(label = n),vjust = 2, color = 'white') +
labs(x = 'Thang đo Quality', y = 'Số lượng')

Nhận xét
Có thể thấy rằng số lương táo kém chất lượng (bad) và chất
lượng(good) đồng đều nhau lần lượt là 1996 trái và 2004 trái.
Biểu đồ cột theo phân trăm của biến quality
library(dplyr)
library(scales)
library(tidyverse)
d %>% group_by(Quality) %>% summarise(n = n()) %>%
ggplot(aes(Quality,n)) +
geom_col(fill='dark blue') +
geom_text(aes(label = percent(n/length(d$Quality))),vjust = 2, color = 'white') +
labs(x = 'Loại', y = 'Số lượng')

Nhận xét
Tương tự như biểu đồ ở trên không có sự chênh lệch quá mực mà khá
đồng đều của trái táo theo 2 cách đánh giá khác nhau.
Biểu đồ Histogram cho biến Crunchiness
d %>% ggplot(aes(x = Crunchiness)) +
geom_histogram(binwidth = 0.1, fill = 'Pink', color = 'red')
Nhận xét
Trong phân khúc trên độ
giòn của táo từ 0.4 đến 1.5 là đạt đỉnh vì chiếm số lượng táo có độ giòn
đó hơn 100 trái cho từ độ giòn được nêu trước đó.
Biểu đồ Histogram tương quan giữa Juiciness và
Quality
d %>% ggplot(aes(x = Juiciness, fill = Quality)) +
geom_histogram(binwidth = 0.5)
Nhận xét
Nơn 400 trái .
Trong
khi ngược lại số lượng táo chất lượng có độ mọng nước từ 1.6 đến 2 thì
đạt đỉnh hơn 200 trái.
Biểu đồ Histogram tương quan giữa Sweetness và
Quality
d %>% ggplot(aes(x = Sweetness)) +
geom_histogram(binwidth = 0.5, fill = 'pink', color = 'red') +
facet_wrap(~Quality)
Nhận xét
Ta có 2 biểu đồ chia làm
hai : táo kém chất lượng và táo chất lượng.
Táo kém chất lượng
nhưng có độ ngọt từ 1 đến 1.5 thì chiếm rất nhiều hơn 260 trái trong khi
táo chất lượng có độ ngọt từ 0.6 đến 1 chiếm đa số gần 250 trái.
Biểu đồ density của biến Weight
d %>% ggplot(aes(x = Weight)) +
geom_density(fill = 'dark blue')
Nhận xét
Trong phân khúc mật độ từ
0.2 đến 0.27 có sự biến động khá lớn khi ta thấy được đỉnh nhon của biến
Weight.
Biểu đồ density của biến Size
d %>% ggplot(aes(x = Size, fill = Quality)) +
geom_density()

Biểu đồ density của biến Juiciness
d %>% ggplot(aes(x = Juiciness)) +
geom_density(fill = 'dark blue') +
facet_wrap(~Quality)

Biểu đồ cột của biến QUality
d %>% group_by(Quality) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Quality)) +
geom_col() +
geom_text(aes(label = n),position = position_stack(vjust = 1))
Nhận xét
Biểu đồ cho thấy sô lượng
của táo good và táo bad dưới dạng trồng lên nhau.
Biểu đồ tròn biến Quality
d %>% group_by(Quality) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Quality)) +
geom_col() +
coord_polar('y')
Nhận xét
BIểu đồ tròn của biến
QUality cho thấy sô lượng xêm xêm nhau của hai loại táo good và bad.
Biểu đồ phân tán của biến Weight và Juiciness
d %>% ggplot(aes(x = Weight, y = Juiciness)) +
geom_point(color = 'red') +
geom_smooth(method = 'lm', color = 'dark blue')
Nhận xét
Các điểm trên biểu đồ màu
đỏ và biểu thị các cặp giá trị (Weight, Juiciness) trong tập dữ liệu và
có thể thấy rằng các cặp giá trị từ -2 đến 2 tập trung nhiều điểm đỏ
cũng là chiếm nhiều số lượng táo.
đường thẳng màu xanh cho thấy xu
hướng chung của nó trong trường hợp này là giảm ta có thể lí giải rằng
trọng lượng táo càng lớn thì độ mọng nước càng giảm.
Biểu đồ phân tán của giữa biến Crunchiness , Sweetness và
Quality
d %>% ggplot(aes(x = Crunchiness, y = Sweetness, alpha = Quality)) +
geom_point()
Nhận xét
Biểu đồ này có hai đối
tuongj của Quality và được quy định theo màu sắc khác nhau . Tương tự
như ở trên có thể thấy rằng các cặp giá trị từ -2 đến 2 tập trung nhiều
điểm đỏ cũng là chiếm nhiều số lượng táo bất kể loại nào.
Biểu đồ phân tán của biến Weight và Quality
d %>% ggplot(aes(x = Ripeness, y = Weight)) +
geom_point(color = 'dark blue') +
geom_smooth(method = 'lm', color = 'pink') +
facet_wrap(~Quality)
Nhận xét
Như biểu đồ 12 lúc này được
chia thành hai biểu đồ nhỏ tượng trưng cho 2 loại táo bad và good . Nhìn
chung chúng có cùng xu hướng giảm chức tỏ trọng lượng càng ít đi thì
trái đó chín mùi hơn.
Biểu đồ tròn của biến Quality
d %>% group_by(Quality) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Quality)) +
geom_col(color = 'black') +
coord_polar('y') +
geom_text(aes(x = 1.0, label = n),position = position_stack(vjust = .5)) +
theme_void()
Nhận xét
Biểu đò này cho thấy rõ hơn
sô lượng mà cả hai loại táo bad và good sở hữu lần lượt là 1996 trái và
2004 trái trên mặt phẳng tròn và màu sắc được quy định.
Biểu đồ Histogram củ biến Weight và Quality
d %>% ggplot(aes(x = Ripeness)) +
geom_histogram(data = d %>% filter(Quality == 'bad'), binwidth = 1, fill = 'darkblue') +
geom_histogram(data = d %>% filter(Quality == 'good'), binwidth = 1, fill = 'brown')
Nhận xét
Nhìn trên biểu đò ta có thể
thấy được rằng sô táo chất lượng có độ chín từ 0.1 đến 1 chiếm nhiều
nhất là hơn 400 trái .
Trong khi ngược lại số lượng táo kém chất
lượng đã bị che bởi số táo chất lượng có thể tháy trên biểu đồ nên ta
không thể kết luận chính xác được.
Biểu đồ nhóm thể hiện theo Weight
dweight <- d %>% mutate(Weight = cut(Weight,5, label = c('too light', 'light','Fine','Heavy','Extreme Heavy')))
ta chia trọng lượng thành 5 nhóm : too light , light, Fine,
Heavy và Extreme Heavy.
dweight %>% group_by(Weight) %>% summarise(n = n()) %>%
ggplot(aes(Weight,n)) +
geom_col(fill='dark blue') +
labs(title = " Biểu đồ thể hiện nhóm theo Weight ") +
geom_text(aes(label = n),vjust = 0, color = 'brown') +
labs(x = 'Trọng Lượng', y = 'Số lượng')
Nhận xét Ta nhận được kết quả như trên cụ
thể hơn là số lượng táo mà các nhóm sở hữu. Nhiều nhất là Fine 2369 trái
và ít nhất là Extreme Heavy 27 trái.
Biểu đồ tròn biến Weight
dweight <- d %>% mutate(Weight = cut(Weight,5, label = c('too light', 'light','Fine','Heavy','Extreme Heavy')))
dweight %>% group_by(Weight) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Weight)) +
geom_col(color = 'black') +
coord_polar('y') +
geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
theme_void()
Nhận xét
Thay vì biểu đồ cột như
biểu đồ 16 thì các đối tượng của biến Weight được biểu diễn trên biểu đồ
tròn với giá trị tương ứng.
LS0tDQp0aXRsZTogIk5oaeG7h20gVuG7pSA1Ig0KYXV0aG9yOiAiVm9IaWV1Ig0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUg6JU06JVMsICVkIC0gJW0gLSAlWScpYCINCm91dHB1dDogDQogaHRtbF9kb2N1bWVudDogDQogICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgdG9jOiB0cnVlDQotLS0NCmBgYHtyIHNldHVwLGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KZCA8LSByZWFkLmNzdigiQzovVXNlcnMvSFAvRG9jdW1lbnRzL2FwcGxlX3F1YWxpdHkuY3N2IiAsIGhlYWRlciA9IFQgKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNraW1yKQ0Kc2tpbShkKQ0KYGBgDQoNCiMjIEdJ4buaSSBUSEnhu4ZVIFbhu4AgQuG7mCBE4buuIExJ4buGVSBBUFBMRSBRVUFMSVRZDQoNCkFwcGxlIFF1YWxpdHkgbMOgIGLhu5kgZOG7ryBsaeG7h3UgY2jhu6lhIGPDoWMgduG7gSBjw6FjIHRodeG7mWMgdMOtbmgga2jDoWMgbmhhdSBj4bunYSBt4buZdCBi4buZIHRyw6FpIGPDonksY+G7pSB0aOG7gyBoxqFuIGzDoCB0w6FvIHbDoCBjdW5nIGPhuqVwIHRow7RuZyB0aW4gY2hpIHRp4bq/dCB24buBIMSR4bq3YyDEkWnhu4NtIGPhu6dhIGNow7puZy4gQuG7mSBk4buvIGxp4buHdSBiYW8gZ+G7k20gY8OhYyBjaGkgdGnhur90IG5oxrAgSUQgdHLDoWkgY8OieSwga8OtY2ggdGjGsOG7m2MsIHRy4buNbmcgbMaw4bujbmcsIMSR4buZIG5n4buNdCwgxJHhu5kgZ2nDsm4sIMSR4buZIG5nb24gbmfhu410LCDEkeG7mSBjaMOtbiwgxJHhu5kgY2h1YSB2w6AgY2jhuqV0IGzGsOG7o25nLg0KDQpC4buZIGThu68gbGnhu4d1IMSRxrDhu6NjIGN1bmcgY+G6pXAgcuG7mW5nIHLDo2kgYuG7n2kgbeG7mXQgY8O0bmcgdHkgbsO0bmcgbmdoaeG7h3AgTeG7uSB2w6AgxJHDoyDEkcaw4bujYyB0aHUgbmjhu48gdsOgIGzDoG0gc+G6oWNoIMSR4buDIGThu4Ugc+G7rSBk4bulbmcuDQoNCiogQuG7mSBk4buvIGxp4buHdSBiYW8gZ+G7k20gY8OhYyB0aHXhu5ljIHTDrW5oIHNhdToNCg0KLSBBX2lkOiBJZCBj4bunYSB0csOhaSB0w6FvLg0KLSBTaXplOiBrw61jaCB0aMaw4bubYyBj4bunYSB0csOhaSB0w6FvLg0KLSBXZWlnaHQ6IHRy4buNbmcgbMaw4bujbmcgY+G7p2EgdHLDoWkgdMOhby4NCi0gU3dlZXRuZXNzOiDEkOG7mSBuZ+G7jXQgY+G7p2EgdHLDoWkgdMOhby4NCi0gQ3J1bmNoaW5lc3M6IMSR4buZIGdpw7JuIGPhu6dhIHRyw6FpIHTDoW8uDQotIEp1aWNpbmVzczogxJHhu5kgbeG7jW5nIG7GsOG7m2MgY+G7p2EgdHLDoWkgdMOhby4NCi0gUmlwZW5lc3M6IMSR4buZIGNow61uIGPhu6dhIHRyw6FpIHTDoW8uDQotIEFjaWRpdHk6IMSR4buZIGNodWEgY+G7p2EgdHLDoWkgdMOhby4NCi0gUXVhbGl0eTogY2jhuqV0IGzGsOG7o25nIGPhu6dhIHRyw6FpIHTDoW8uDQoNCmBgYHtyfQ0Kc3RyKGQpDQpgYGANCg0KIyMgQknhu4JVIMSQ4buSDQoNCkJp4bq/biDigJxxdWFsaXR54oCdIGzDoCBt4buZdCBiaeG6v24gcGjDom4gbG/huqFpIChjYXRlZ29yaWNhbCkgdHJvbmcgYuG7mSBk4buvIGxp4buHdSDigJxBcHBsZSBRdWFsdHnigJ0gdsOgIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIMSRw6FuaCBnacOhIG3hu6ljIMSR4buZIGNo4bqldCBsxrDhu6NuZyBj4bunYSB0csOhaSB0w6FvLg0KDQpCaeG6v24gbsOgeSBjw7MgMiBtxrDhu5tjIMSRw6FuaCBnacOhIGtow6FjIG5oYXUgxJHGsOG7o2MgbcO0IHThuqMgbmjGsCBzYXU6DQpgYGB7cn0NCnRhYmxlKGQkUXVhbGl0eSkNCmBgYA0KDQoqIGJhZDogbmjhu69uZyB0csOhaSB0w6FvIMSRxrDhu6NjIMSRw6FuaCBnacOhIGJhZCB0aMOsIGzDoCBuaOG7r25nIHRyw6FpIGvDqW0gY2jhuqV0IGzGsOG7o25nIGPDsyAxOTk2IHRyw6FpLg0KDQoqIGdvb2Q6IG5nxrDhu6NjIGzhuqFpIGtoaSB0csOhaSB0w6FvIMSR4bqhdCBjaOG6pXQgbMaw4bujbmcgxJHhuqd1IHJhIHPhur0gxJHGsOG7o2MgxJHDoW5oIGdpw6EgbMOgIGdvb2QgY8OzIDIwMDQgdHLDoWkuDQoNCiMjIEJp4buDdSDEkeG7kyBj4buZdCBjaG8gYmnhur9uICJxdWFsaXR5IjoNCmBgYHtyfQ0KZCAlPiUgZ3JvdXBfYnkoUXVhbGl0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUgDQogIGdncGxvdChhZXMoUXVhbGl0eSxuKSkgKyANCiAgZ2VvbV9jb2woZmlsbD0nZGFyayBibHVlJykgKw0KICAgIGxhYnModGl0bGUgPSAiIEJJ4buCVSDEkOG7kiBUSOG7giBISeG7hk4gTkjDk00gVEhFTyBRVUFMSVRZICIpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICd3aGl0ZScpICsNCiAgICBsYWJzKHggPSAnVGhhbmcgxJFvIFF1YWxpdHknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCioqKk5o4bqtbiB4w6l0KioqDQoNCkPDsyB0aOG7gyB0aOG6pXkgcuG6sW5nIHPhu5EgbMawxqFuZyB0w6FvIGvDqW0gY2jhuqV0IGzGsOG7o25nIChiYWQpIHbDoCBjaOG6pXQgbMaw4bujbmcoZ29vZCkgxJHhu5NuZyDEkeG7gXUgbmhhdSBs4bqnbiBsxrDhu6N0IGzDoCAxOTk2IHRyw6FpIHbDoCAyMDA0IHRyw6FpLg0KDQojIyAqKkJp4buDdSDEkeG7kyBj4buZdCB0aGVvIHBow6JuIHRyxINtIGPhu6dhIGJp4bq/biBxdWFsaXR5KioNCmBgYHtyfQ0KDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmQgJT4lIGdyb3VwX2J5KFF1YWxpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoUXVhbGl0eSxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2RhcmsgYmx1ZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGVyY2VudChuL2xlbmd0aChkJFF1YWxpdHkpKSksdmp1c3QgPSAyLCBjb2xvciA9ICd3aGl0ZScpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqKipOaOG6rW4geMOpdCoqKg0KDQpUxrDGoW5nIHThu7EgbmjGsCBiaeG7g3UgxJHhu5Mg4bufIHRyw6puIGtow7RuZyBjw7Mgc+G7sSBjaMOqbmggbOG7h2NoIHF1w6EgbeG7sWMgbcOgIGtow6EgxJHhu5NuZyDEkeG7gXUgY+G7p2EgdHLDoWkgdMOhbyB0aGVvIDIgY8OhY2ggxJHDoW5oIGdpw6Ega2jDoWMgbmhhdS4gDQoNCiMjIEJp4buDdSDEkeG7kyBIaXN0b2dyYW0gY2hvIGJp4bq/biBDcnVuY2hpbmVzcw0KYGBge3J9DQoNCmQgJT4lIGdncGxvdChhZXMoeCA9IENydW5jaGluZXNzKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMSwgZmlsbCA9ICdQaW5rJywgY29sb3IgPSAncmVkJykNCmBgYA0KPGJyPg0KKioqTmjhuq1uIHjDqXQqKioNCjxicj4NClRyb25nIHBow6JuIGtow7pjIHRyw6puIMSR4buZIGdpw7JuIGPhu6dhIHTDoW8gdOG7qyAwLjQgxJHhur9uIDEuNSBsw6AgxJHhuqF0IMSR4buJbmggdsOsIGNoaeG6v20gc+G7kSBsxrDhu6NuZyB0w6FvIGPDsyDEkeG7mSBnacOybiDEkcOzIGjGoW4gMTAwIHRyw6FpIGNobyB04burIMSR4buZIGdpw7JuIMSRxrDhu6NjIG7DqnUgdHLGsOG7m2MgxJHDsy4NCg0KIyMgKipCaeG7g3UgxJHhu5MgSGlzdG9ncmFtIHTGsMahbmcgcXVhbiBnaeG7r2EgSnVpY2luZXNzIHbDoCBRdWFsaXR5KioNCmBgYHtyfQ0KDQpkICU+JSBnZ3Bsb3QoYWVzKHggPSBKdWljaW5lc3MsIGZpbGwgPSBRdWFsaXR5KSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSkNCmBgYA0KPGJyPg0KKioqTmjhuq1uIHjDqXQqKioNCjxicj4NCk7GoW4gNDAwIHRyw6FpIC4NCjxicj4NClRyb25nIGtoaSBuZ8aw4bujYyBs4bqhaSBz4buRIGzGsOG7o25nIHTDoW8gY2jhuqV0IGzGsOG7o25nIGPDsyDEkeG7mSBt4buNbmcgbsaw4bubYyB04burIDEuNiDEkeG6v24gMiB0aMOsIMSR4bqhdCDEkeG7iW5oIGjGoW4gMjAwIHRyw6FpLg0KDQojIyAqKkJp4buDdSDEkeG7kyBIaXN0b2dyYW0gdMawxqFuZyBxdWFuIGdp4buvYSBTd2VldG5lc3MgdsOgIFF1YWxpdHkqKg0KYGBge3J9DQoNCmQgJT4lIGdncGxvdChhZXMoeCA9IFN3ZWV0bmVzcykpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGZpbGwgPSAncGluaycsIGNvbG9yID0gJ3JlZCcpICsNCiAgZmFjZXRfd3JhcCh+UXVhbGl0eSkNCmBgYA0KPGJyPg0KKioqTmjhuq1uIHjDqXQqKioNCjxicj4NClRhIGPDsyAyIGJp4buDdSDEkeG7kyBjaGlhIGzDoG0gaGFpIDogdMOhbyBrw6ltIGNo4bqldCBsxrDhu6NuZyB2w6AgdMOhbyBjaOG6pXQgbMaw4bujbmcuDQo8YnI+DQpUw6FvIGvDqW0gY2jhuqV0IGzGsOG7o25nIG5oxrBuZyBjw7MgxJHhu5kgbmfhu410IHThu6sgMSDEkeG6v24gMS41IHRow6wgY2hp4bq/bSBy4bqldCBuaGnhu4F1IGjGoW4gMjYwIHRyw6FpIHRyb25nIGtoaSB0w6FvIGNo4bqldCBsxrDhu6NuZyBjw7MgxJHhu5kgbmfhu410IHThu6sgMC42IMSR4bq/biAxIGNoaeG6v20gxJFhIHPhu5EgZ+G6p24gMjUwIHRyw6FpLg0KDQojIyAqKkJp4buDdSDEkeG7kyBkZW5zaXR5IGPhu6dhIGJp4bq/biBXZWlnaHQqKg0KYGBge3J9DQoNCmQgJT4lIGdncGxvdChhZXMoeCA9IFdlaWdodCkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAnZGFyayBibHVlJykNCmBgYA0KPGJyPg0KKioqTmjhuq1uIHjDqXQqKioNCjxicj4NClRyb25nIHBow6JuIGtow7pjIG3huq10IMSR4buZIHThu6sgMC4yIMSR4bq/biAwLjI3IGPDsyBz4buxIGJp4bq/biDEkeG7mW5nIGtow6EgbOG7m24ga2hpIHRhIHRo4bqleSDEkcaw4bujYyDEkeG7iW5oIG5ob24gY+G7p2EgYmnhur9uIFdlaWdodC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgZGVuc2l0eSBj4bunYSBiaeG6v24gU2l6ZSoqDQpgYGB7cn0NCg0KZCAlPiUgZ2dwbG90KGFlcyh4ID0gU2l6ZSwgZmlsbCA9IFF1YWxpdHkpKSArDQogIGdlb21fZGVuc2l0eSgpDQpgYGANCg0KIyMgKipCaeG7g3UgxJHhu5MgZGVuc2l0eSBj4bunYSBiaeG6v24gSnVpY2luZXNzKioNCmBgYHtyfQ0KDQpkICU+JSBnZ3Bsb3QoYWVzKHggPSBKdWljaW5lc3MpKSArDQogIGdlb21fZGVuc2l0eShmaWxsID0gJ2RhcmsgYmx1ZScpICsNCiAgZmFjZXRfd3JhcCh+UXVhbGl0eSkNCmBgYA0KDQojIyAqKkJp4buDdSDEkeG7kyBj4buZdCBj4bunYSBiaeG6v24gUVVhbGl0eSoqDQpgYGB7cn0NCg0KZCAlPiUgZ3JvdXBfYnkoUXVhbGl0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBRdWFsaXR5KSkgKw0KICAgIGdlb21fY29sKCkgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSxwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMSkpDQpgYGANCjxicj4NCioqKk5o4bqtbiB4w6l0KioqDQo8YnI+DQpCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSBzw7QgbMaw4bujbmcgY+G7p2EgdMOhbyBnb29kIHbDoCB0w6FvIGJhZCBkxrDhu5tpIGThuqFuZyB0cuG7k25nIGzDqm4gbmhhdS4NCg0KIyMgKipCaeG7g3UgxJHhu5MgdHLDsm4gYmnhur9uIFF1YWxpdHkqKg0KYGBge3J9DQoNCmQgJT4lIGdyb3VwX2J5KFF1YWxpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9ICcnLCB5ID0gbixmaWxsID0gUXVhbGl0eSkpICsNCiAgICBnZW9tX2NvbCgpICsNCiAgICBjb29yZF9wb2xhcigneScpDQpgYGANCjxicj4NCioqKk5o4bqtbiB4w6l0KioqDQo8YnI+DQpCSeG7g3UgxJHhu5MgdHLDsm4gY+G7p2EgYmnhur9uIFFVYWxpdHkgY2hvIHRo4bqleSBzw7QgbMaw4bujbmcgeMOqbSB4w6ptIG5oYXUgY+G7p2EgaGFpIGxv4bqhaSB0w6FvIGdvb2QgdsOgIGJhZC4NCg0KIyMgKipCaeG7g3UgxJHhu5MgcGjDom4gdMOhbiBj4bunYSBiaeG6v24gV2VpZ2h0IHbDoCBKdWljaW5lc3MqKg0KYGBge3J9DQoNCg0KZCAlPiUgZ2dwbG90KGFlcyh4ID0gV2VpZ2h0LCB5ID0gSnVpY2luZXNzKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gJ3JlZCcpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgY29sb3IgPSAnZGFyayBibHVlJykNCmBgYA0KPGJyPg0KKioqTmjhuq1uIHjDqXQqKioNCjxicj4NCkPDoWMgxJFp4buDbSB0csOqbiBiaeG7g3UgxJHhu5MgbcOgdSDEkeG7jyB2w6AgYmnhu4N1IHRo4buLIGPDoWMgY+G6t3AgZ2nDoSB0cuG7iyAoV2VpZ2h0LCBKdWljaW5lc3MpIHRyb25nIHThuq1wIGThu68gbGnhu4d1IHbDoCBjw7MgdGjhu4MgdGjhuqV5IHLhurFuZyBjw6FjIGPhurdwIGdpw6EgdHLhu4sgdOG7qyAtMiDEkeG6v24gMiB04bqtcCB0cnVuZyBuaGnhu4F1IMSRaeG7g20gxJHhu48gY8WpbmcgbMOgIGNoaeG6v20gbmhp4buBdSBz4buRIGzGsOG7o25nIHTDoW8uDQo8YnI+DQrEkcaw4budbmcgdGjhurNuZyBtw6B1IHhhbmggY2hvIHRo4bqleSB4dSBoxrDhu5tuZyBjaHVuZyBj4bunYSBuw7MgdHJvbmcgdHLGsOG7nW5nIGjhu6NwIG7DoHkgbMOgIGdp4bqjbSB0YSBjw7MgdGjhu4MgbMOtIGdp4bqjaSBy4bqxbmcgdHLhu41uZyBsxrDhu6NuZyB0w6FvIGPDoG5nIGzhu5tuIHRow6wgxJHhu5kgbeG7jW5nIG7GsOG7m2MgY8OgbmcgZ2nhuqNtLg0KDQojIyAqKkJp4buDdSDEkeG7kyBwaMOibiB0w6FuIGPhu6dhIGdp4buvYSBiaeG6v24gQ3J1bmNoaW5lc3MgLCBTd2VldG5lc3MgdsOgIFF1YWxpdHkqKg0KYGBge3J9DQoNCmQgJT4lIGdncGxvdChhZXMoeCA9IENydW5jaGluZXNzLCB5ID0gU3dlZXRuZXNzLCBhbHBoYSA9IFF1YWxpdHkpKSArDQogIGdlb21fcG9pbnQoKQ0KYGBgDQo8YnI+DQoqKipOaOG6rW4geMOpdCoqKg0KPGJyPg0KQmnhu4N1IMSR4buTIG7DoHkgY8OzIGhhaSDEkeG7kWkgdHVvbmdqIGPhu6dhIFF1YWxpdHkgdsOgIMSRxrDhu6NjIHF1eSDEkeG7i25oIHRoZW8gbcOgdSBz4bqvYyBraMOhYyBuaGF1IC4gVMawxqFuZyB04buxIG5oxrAg4bufIHRyw6puIGPDsyB0aOG7gyB0aOG6pXkgcuG6sW5nIGPDoWMgY+G6t3AgZ2nDoSB0cuG7iyB04burIC0yIMSR4bq/biAyIHThuq1wIHRydW5nIG5oaeG7gXUgxJFp4buDbSDEkeG7jyBjxaluZyBsw6AgY2hp4bq/bSBuaGnhu4F1IHPhu5EgbMaw4bujbmcgdMOhbyBi4bqldCBr4buDIGxv4bqhaSBuw6BvLg0KDQojIyAqKkJp4buDdSDEkeG7kyBwaMOibiB0w6FuIGPhu6dhIGJp4bq/biBXZWlnaHQgdsOgIFF1YWxpdHkqKg0KYGBge3J9DQoNCmQgJT4lIGdncGxvdChhZXMoeCA9IFJpcGVuZXNzLCB5ID0gV2VpZ2h0KSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gJ2RhcmsgYmx1ZScpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgY29sb3IgPSAncGluaycpICsNCiAgZmFjZXRfd3JhcCh+UXVhbGl0eSkNCmBgYA0KPGJyPg0KKioqTmjhuq1uIHjDqXQqKioNCjxicj4NCk5oxrAgYmnhu4N1IMSR4buTIDEyIGzDumMgbsOgeSDEkcaw4bujYyBjaGlhIHRow6BuaCBoYWkgYmnhu4N1IMSR4buTIG5o4buPIHTGsOG7o25nIHRyxrBuZyBjaG8gMiBsb+G6oWkgdMOhbyBiYWQgdsOgIGdvb2QgLiBOaMOsbiBjaHVuZyBjaMO6bmcgY8OzIGPDuW5nIHh1IGjGsOG7m25nIGdp4bqjbSBjaOG7qWMgdOG7jyB0cuG7jW5nIGzGsOG7o25nIGPDoG5nIMOtdCDEkWkgdGjDrCB0csOhaSDEkcOzIGNow61uIG3DuWkgaMahbi4NCg0KIyMgKipCaeG7g3UgxJHhu5MgdHLDsm4gY+G7p2EgYmnhur9uIFF1YWxpdHkqKg0KYGBge3J9DQoNCmQgJT4lIGdyb3VwX2J5KFF1YWxpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9ICcnLCB5ID0gbixmaWxsID0gUXVhbGl0eSkpICsNCiAgICBnZW9tX2NvbChjb2xvciA9ICdibGFjaycpICsNCiAgICBjb29yZF9wb2xhcigneScpICsNCiAgICBnZW9tX3RleHQoYWVzKHggPSAxLjAsIGxhYmVsID0gbikscG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSkgKw0KICAgIHRoZW1lX3ZvaWQoKQ0KYGBgDQo8YnI+DQoqKipOaOG6rW4geMOpdCoqKg0KPGJyPg0KQmnhu4N1IMSRw7IgbsOgeSBjaG8gdGjhuqV5IHLDtSBoxqFuIHPDtCBsxrDhu6NuZyBtw6AgY+G6oyBoYWkgbG/huqFpIHTDoW8gYmFkIHbDoCBnb29kIHPhu58gaOG7r3UgbOG6p24gbMaw4bujdCBsw6AgMTk5NiB0csOhaSB2w6AgMjAwNCB0csOhaSB0csOqbiBt4bq3dCBwaOG6s25nIHRyw7JuIHbDoCBtw6B1IHPhuq9jIMSRxrDhu6NjIHF1eSDEkeG7i25oLg0KDQojIyAqKkJp4buDdSDEkeG7kyBIaXN0b2dyYW0gY+G7pyBiaeG6v24gV2VpZ2h0IHbDoCBRdWFsaXR5KioNCmBgYHtyfQ0KZCAlPiUgZ2dwbG90KGFlcyh4ID0gUmlwZW5lc3MpKSArDQogIGdlb21faGlzdG9ncmFtKGRhdGEgPSBkICU+JSBmaWx0ZXIoUXVhbGl0eSA9PSAnYmFkJyksIGJpbndpZHRoID0gMSwgZmlsbCA9ICdkYXJrYmx1ZScpICsNCiAgZ2VvbV9oaXN0b2dyYW0oZGF0YSA9IGQgJT4lIGZpbHRlcihRdWFsaXR5ID09ICdnb29kJyksIGJpbndpZHRoID0gMSwgZmlsbCA9ICdicm93bicpDQpgYGANCjxicj4NCioqKk5o4bqtbiB4w6l0KioqDQo8YnI+DQpOaMOsbiB0csOqbiBiaeG7g3UgxJHDsiB0YSBjw7MgdGjhu4MgdGjhuqV5IMSRxrDhu6NjIHLhurFuZyBzw7QgdMOhbyAgY2jhuqV0IGzGsOG7o25nIGPDsyDEkeG7mSBjaMOtbiB04burIDAuMSDEkeG6v24gMSBjaGnhur9tIG5oaeG7gXUgbmjhuqV0IGzDoCBoxqFuIDQwMCB0csOhaSAuDQo8YnI+DQpUcm9uZyBraGkgbmfGsOG7o2MgbOG6oWkgc+G7kSBsxrDhu6NuZyB0w6FvIGvDqW0gY2jhuqV0IGzGsOG7o25nIMSRw6MgYuG7iyBjaGUgYuG7n2kgc+G7kSB0w6FvIGNo4bqldCBsxrDhu6NuZyBjw7MgdGjhu4MgdGjDoXkgdHLDqm4gYmnhu4N1IMSR4buTIG7Dqm4gdGEga2jDtG5nIHRo4buDIGvhur90IGx14bqtbiBjaMOtbmggeMOhYyDEkcaw4bujYy4NCg0KIyMgKipCaeG7g3UgxJHhu5MgbmjDs20gdGjhu4MgaGnhu4duIHRoZW8gV2VpZ2h0KioNCmBgYHtyfQ0KDQpkd2VpZ2h0IDwtIGQgJT4lIG11dGF0ZShXZWlnaHQgPSBjdXQoV2VpZ2h0LDUsIGxhYmVsID0gYygndG9vIGxpZ2h0JywgJ2xpZ2h0JywnRmluZScsJ0hlYXZ5JywnRXh0cmVtZSBIZWF2eScpKSkNCg0KYGBgDQo8YnI+DQp0YSBjaGlhIHRy4buNbmcgbMaw4bujbmcgdGjDoG5oIDUgbmjDs20gOiB0b28gbGlnaHQgLCBsaWdodCwgRmluZSwgSGVhdnkgdsOgIEV4dHJlbWUgSGVhdnkuDQo8YnI+DQpgYGB7cn0NCmR3ZWlnaHQgJT4lIGdyb3VwX2J5KFdlaWdodCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhXZWlnaHQsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdkYXJrIGJsdWUnKSArDQogICAgbGFicyh0aXRsZSA9ICIgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBuaMOzbSB0aGVvIFdlaWdodCAiKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAnYnJvd24nKSArDQogICAgbGFicyh4ID0gJ1Ry4buNbmcgTMaw4bujbmcnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQo8YnI+DQoqKipOaOG6rW4geMOpdCoqKg0KVGEgbmjhuq1uIMSRxrDhu6NjIGvhur90IHF14bqjIG5oxrAgdHLDqm4gY+G7pSB0aOG7gyBoxqFuIGzDoCBz4buRIGzGsOG7o25nIHTDoW8gbcOgIGPDoWMgbmjDs20gc+G7nyBo4buvdS4gTmhp4buBdSBuaOG6pXQgbMOgIEZpbmUgMjM2OSB0csOhaSB2w6Agw610IG5o4bqldCBsw6AgRXh0cmVtZSBIZWF2eSAyNyB0csOhaS4NCg0KDQojIyAqKkJp4buDdSDEkeG7kyB0csOybiBiaeG6v24gV2VpZ2h0KioNCmBgYHtyfQ0KZHdlaWdodCA8LSBkICU+JSBtdXRhdGUoV2VpZ2h0ID0gY3V0KFdlaWdodCw1LCBsYWJlbCA9IGMoJ3RvbyBsaWdodCcsICdsaWdodCcsJ0ZpbmUnLCdIZWF2eScsJ0V4dHJlbWUgSGVhdnknKSkpDQoNCmR3ZWlnaHQgJT4lIGdyb3VwX2J5KFdlaWdodCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBXZWlnaHQpKSArDQogICAgZ2VvbV9jb2woY29sb3IgPSAnYmxhY2snKSArDQogICAgY29vcmRfcG9sYXIoJ3knKSArDQogICAgZ2VvbV90ZXh0KGFlcyh4ID0gMS4zLCBsYWJlbCA9IG4pLHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAuNSkpICsNCiAgICB0aGVtZV92b2lkKCkNCmBgYA0KPGJyPg0KKioqTmjhuq1uIHjDqXQqKioNCjxicj4NClRoYXkgdsOsIGJp4buDdSDEkeG7kyBj4buZdCBuaMawIGJp4buDdSDEkeG7kyAxNiB0aMOsIGPDoWMgxJHhu5FpIHTGsOG7o25nIGPhu6dhIGJp4bq/biBXZWlnaHQgxJHGsOG7o2MgYmnhu4N1IGRp4buFbiB0csOqbiBiaeG7g3UgxJHhu5MgdHLDsm4gduG7m2kgZ2nDoSB0cuG7iyB0xrDGoW5nIOG7qW5nLg0KDQoNCg0KDQoNCg==