Giới thiệu bộ dữ liệu diamonds
-Bộ dữ liệu có 10 biến và 53940 quan sát
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.4.4 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.0
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(scales)
##
## Attaching package: 'scales'
##
## The following object is masked from 'package:purrr':
##
## discard
##
## The following object is masked from 'package:readr':
##
## col_factor
d <- diamonds
d %>% ggplot(aes(x = cut)) +
geom_bar() +
labs(x = 'Loại', y = 'Số lượng')

Biểu đồ trên biểu diễn số lượng của 5 loại mặt cắt của kim cương từ loại
thấp đến cao, như:
-Loại Fair có khoảng 2000 viên
-Loại Good có khoảng 5000 viên
-Loại Very Good có khoảng 12000 viên
-Loại Premium có khoảng 13000 viên
-Loại Ideal có khoảng hơn 20000 viên
d %>% ggplot(aes(x = cut)) +
geom_bar() +
labs(x = 'Loại', y = 'Số lượng')+
coord_flip()
Giống biểu đồ phía trên nhưng khác ở chỗ cột nằm ngang
library(tidyverse)
library(scales)
d <- diamonds
d %>% group_by(cut) %>% summarise(freq= n()) %>%
ggplot(aes(x = cut,y = freq)) +
geom_col(fill='lightblue') +
geom_text(aes(label =freq),vjust =2, color ='white') +
labs(x= 'Loại', y='Số lượng')
Biểu đồ thể hiện số lượng kim cương các loại
ggplot(diamonds, aes(x = carat)) +
geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

labs(x= 'Trọng lượng', y='Số lượng')
## $x
## [1] "Trọng lượng"
##
## $y
## [1] "Số lượng"
##
## attr(,"class")
## [1] "labels"
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, fill = clarity), position = "dodge")
Biểu đồ thể hiện độ trong của kim cương theo từng loại
Biều đồ phân phối của carat
Biểu đồ tỷ lệ phần trăm số lượng kim cương theo loại cut:
d %>% group_by(cut) %>% summarise(n = n()) %>%
ggplot(aes(cut,n)) +
geom_col(fill='pink') +
geom_text(aes(label = percent(n/length(d$carat))),vjust = 2, color = 'yellow') +
labs(x = 'Loại', y = 'Số lượng')

Biểu đồ này biểu diễn tỷ lệ phần trăm lượng kim cương theo loại
cut
Biểu đồ thể hiện số lượng kim cương phân theo loại với màu sắc đường
viền cắt:
d %>% group_by(cut,color) %>% summarise(n=n()) %>%
ggplot(aes(x = cut,y = n)) +
geom_col(position = 'dodge') +
facet_wrap(~color) +
labs(x = 'Loại', y = 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

d %>% group_by(cut,color) %>% summarise(n=n()) %>%
ggplot(aes(x = cut,y = n)) +
geom_col(position = 'dodge') +
facet_wrap(~color) +
geom_text(aes(label = n),vjust = 2, color = 'yellow') +
labs(x = 'Loại', y = 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

d %>% group_by(cut) %>% summarise(m= mean(carat)) %>%
ggplot(aes(x = cut,y = m)) +
geom_col(position = 'dodge') +
geom_text(aes(label = round(m,2)), vjust = 2, color = 'white') +
labs(x = 'Màu', y = 'Mean')

d %>% group_by(cut,color) %>% summarise(m = mean(price)) %>%
ggplot(aes(x = cut,y = m)) +
geom_col(position = 'dodge') +
facet_wrap(~color) +
geom_text(aes(label = round(m))) +
labs(x = 'Cut', y = 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

Biểu đồ thể hiện tổng trọng lượng kim cương theo màu sắc:
ggplot(d, aes(x = color, y = carat)) +
geom_bar(stat = "summary", fun = "sum")

Biểu đồ trên biểu diễn số lượng của 7 loại màu sắc của kim cương từ loại
‘D’ đến ‘J’ -Màu D có khoảng 6775 viên
-Màu E có khoảng 9797 viên
-Màu F có khoảng 9542 viên
-Màu G có khoảng 11292 viên
-Màu H có khoảng 8304 viên
-Màu I có khoảng 5422 viên
-Màu J có khoảng 2808 viên
Ta thấy được Màu G chiếm tỷ lệ nhiều trong biểu đồ trên
ggplot(d, aes(x = cut, y = price)) +
geom_bar(stat = "summary", fun = "mean")

Biểu đồ thể hiện giá trị kim cương lớn nhất theo độ trong:
ggplot(diamonds, aes(x = clarity, y = price)) +
geom_bar(stat = "summary", fun = max)

Biểu đồ thể hiện giá trị kim cương nhỏ nhất theo màu sắc:
ggplot(diamonds, aes(x = color, y = price)) +
geom_bar(stat = "summary", fun = min)

Biểu đồ thể hiện phân phối giá trị kim cương theo loại cắt:
ggplot(diamonds, aes(x = cut, y = price)) +
geom_bar(stat = "density")

Biểu đồ thể hiện số lượng kim cương theo kích thước của chúng:
ggplot(d, aes(x = carat)) +
geom_bar(binwidth = 0.5)
## Warning in geom_bar(binwidth = 0.5): Ignoring unknown parameters: `binwidth`

Biểu đồ thể hiện tổng giá trị kim cương theo loại cắt và màu
sắc:
ggplot(diamonds, aes(x = cut, fill = color, y = price)) +
geom_bar(position = "stack", stat = "summary", fun = "sum")

Biểu đồ này cho thấy tổng giá trị kim cương theo từng loại cắt và màu
sắc, với các cột được xếp chồng lên nhau.
Biểu đồ thể hiện giá trị trung bình kim cương theo loại cắt và độ
trong:
ggplot(diamonds, aes(x = cut, fill = clarity, y = price)) +
geom_bar(position = "stack", stat = "summary", fun = "mean")

Biểu đồ thể hiện số lượng kim cương theo kích thước và màu sắc:
ggplot(diamonds, aes(x = carat, fill = color)) +
geom_bar(binwidth = 5)
## Warning in geom_bar(binwidth = 5): Ignoring unknown parameters: `binwidth`

Biểu đồ này cho thấy số lượng kim cương theo kích thước và màu sắc,
với các cột được nhóm lại theo khoảng kích thước 0.5 và màu sắc tương
ứng.
Biểu đồ thể hiện số lượng kim cương theo kích thước và loại
cắt:
ggplot(diamonds, aes(x = carat, fill = cut)) +
geom_bar(binwidth = 0.5)
## Warning in geom_bar(binwidth = 0.5): Ignoring unknown parameters: `binwidth`

Biểu đồ này cho thấy số lượng kim cương theo kích thước và loại cắt,
với các cột được nhóm lại theo khoảng kích thước 0.5 và loại cắt tương
ứng.
Biểu đồ thể hiện giá trị trung bình kim cương theo loại cắt và màu
sắc:
ggplot(diamonds, aes(x = cut, fill = color, y = price)) +
stat_summary(fun = "mean", geom = "bar")

Biểu đồ này cho thấy số lượng kim cương theo từng màu sắc và loại
cắt, với các cột được xếp chồng lên nhau.
Biểu đồ thể hiện giá trị trung bình kim cương theo màu sắc và độ
trong:
ggplot(diamonds, aes(x = color, fill = clarity, y = price)) +
geom_bar(position = "stack", stat = "summary", fun = "mean")

Biểu đồ này cho thấy giá trị trung bình của kim cương theo từng màu sắc
và độ trong, với các cột được xếp chồng lên nhau.
Biểu đồ thể hiện số lượng kim cương theo kích thước và màu sắc:
ggplot(diamonds, aes(x = carat, fill = color)) +
geom_bar(binwidth = 0.5)
## Warning in geom_bar(binwidth = 0.5): Ignoring unknown parameters: `binwidth`

Biểu đồ này cho thấy số lượng kim cương theo kích thước và màu sắc,
với các cột được nhóm lại theo khoảng kích thước 0.5 và màu sắc tương
ứng.
Biểu đồ phân tích độ tinh khiết của kim cương
d %>% group_by(clarity) %>% summarise(n = n()) %>%
ggplot(aes(clarity,n)) +
geom_col(fill='lightgreen') +
geom_text(aes(label = n),vjust = 2, color = 'white') +
labs(x = 'Loại', y = 'Số lượng')

Biểu đồ thể hiện mặt phân cắt kim cương theo đơn vị phần trăm
d %>% ggplot(mapping = aes(x = cut, y = ..prop.., group = 1)) +
geom_bar() +
scale_y_continuous(labels = scales::percent_format())+
labs(x = 'Loại', y = 'Số lượng')
## Warning: The dot-dot notation (`..prop..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(prop)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Biểu đồ thể hiện số lượng kim cương theo độ lớn
d <- diamonds
d <- d %>% mutate(caratC = cut(carat,5, label = c('rất nhỏ', 'nhỏ','vừa','lớn','rất lớn')))
d %>% ggplot(aes(x = caratC)) +
geom_bar(fill = 'pink')

Biểu đồ thể hiện độ sâu trung bình của kim cương
d%>% group_by(cut, clarity)%>%summarise(m=mean(depth))%>%ggplot(aes(x=cut, y= m))+
geom_col(position='dodge')+
facet_wrap(~clarity)+
geom_text(aes(label= round(m)), vjust=2, color='red')+
labs(x= 'Loại', y= 'Độ sâu trung bình')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

Biểu đồ thể hiện phương sai trọng lượng của kim cương theo màu
d %>% group_by(color) %>% summarise(v= var(carat)) %>%
ggplot(aes(x = color,y = v)) +
geom_col(position = 'dodge') +
geom_text(aes(label = round(v,2)), vjust = 2, color = 'red') +
labs(x = 'Màu', y = 'Var')

LS0tDQp0aXRsZTogIm52NCINCmF1dGhvcjogImhuZCINCmRhdGU6ICJyIGZvcm1hdChTeXMudGltZSgpLCAnJUg6JU06JVMsICVkIC0gJW0gLSAlWScpIg0Kb3V0cHV0OiANCiBodG1sX2RvY3VtZW50OiANCiAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgdG9jX2Zsb2F0OiB0cnVlDQogICB0b2M6IHRydWUNCi0tLQ0KKipHaeG7m2kgdGhp4buHdSBi4buZIGThu68gbGnhu4d1IGRpYW1vbmRzKio8cD4NCi1C4buZIGThu68gbGnhu4d1IGPDsyAxMCBiaeG6v24gdsOgIDUzOTQwIHF1YW4gc8OhdA0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCmBgYHtyfQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2NhbGVzKQ0KIGQgPC0gZGlhbW9uZHMNCiBkICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQpKSArIA0KICAgICAgICAgIGdlb21fYmFyKCkgKw0KICAgICAgICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCjxwPkJp4buDdSDEkeG7kyB0csOqbiBiaeG7g3UgZGnhu4VuIHPhu5EgbMaw4bujbmcgY+G7p2EgNSBsb+G6oWkgbeG6t3QgY+G6r3QgY+G7p2Ega2ltIGPGsMahbmcgdOG7qyBsb+G6oWkgdGjhuqVwIMSR4bq/biBjYW8sIG5oxrA6PHA+DQogIC1Mb+G6oWkgRmFpciBjw7Mga2hv4bqjbmcgMjAwMCB2acOqbjxwPg0KICAtTG/huqFpIEdvb2QgY8OzIGtob+G6o25nIDUwMDAgdmnDqm48cD4NCiAgLUxv4bqhaSBWZXJ5IEdvb2QgY8OzIGtob+G6o25nIDEyMDAwIHZpw6puPHA+DQogIC1Mb+G6oWkgUHJlbWl1bSBjw7Mga2hv4bqjbmcgMTMwMDAgdmnDqm48cD4NCiAgLUxv4bqhaSBJZGVhbCBjw7Mga2hv4bqjbmcgaMahbiAyMDAwMCB2acOqbjxwPg0KDQpgYGB7cn0NCmQgJT4lIGdncGxvdChhZXMoeCA9IGN1dCkpICsgDQogICAgICAgICAgZ2VvbV9iYXIoKSArDQogICAgICAgICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpKw0KY29vcmRfZmxpcCgpDQpgYGANCjxwPkdp4buRbmcgYmnhu4N1IMSR4buTIHBow61hIHRyw6puIG5oxrBuZyBraMOhYyDhu58gY2jhu5cgY+G7mXQgbuG6sW0gbmdhbmcNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCmQgPC0gZGlhbW9uZHMNCmQgJT4lICBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2UoZnJlcT0gbigpKSAlPiUNCmdncGxvdChhZXMoeCA9IGN1dCx5ID0gZnJlcSkpICsNCiAgZ2VvbV9jb2woZmlsbD0nbGlnaHRibHVlJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID1mcmVxKSx2anVzdCA9MiwgY29sb3IgPSd3aGl0ZScpICsNCiAgbGFicyh4PSAnTG/huqFpJywgeT0nU+G7kSBsxrDhu6NuZycpDQpgYGANCkJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw6FjIGxv4bqhaQ0KYGBge3J9DQpnZ3Bsb3QoZGlhbW9uZHMsIGFlcyh4ID0gY2FyYXQpKSArDQogIGdlb21faGlzdG9ncmFtKCkgDQogIGxhYnMoeD0gJ1Ry4buNbmcgbMaw4bujbmcnLCB5PSdT4buRIGzGsOG7o25nJykNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArDQogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgZmlsbCA9IGNsYXJpdHkpLCBwb3NpdGlvbiA9ICJkb2RnZSIpDQpgYGANCkJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gxJHhu5kgdHJvbmcgY+G7p2Ega2ltIGPGsMahbmcgdGhlbyB04burbmcgbG/huqFpDQoNCiANCiANCiMjIEJp4buBdSDEkeG7kyBwaMOibiAgcGjhu5FpIGPhu6dhIGNhcmF0DQoNCg0KICANCg0KDQoNCiMjICBCaeG7g3UgxJHhu5MgdOG7tyBs4buHIHBo4bqnbiB0csSDbSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gbG/huqFpIGN1dDoNCmBgYHtyfQ0KZCAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JSANCiAgZ2dwbG90KGFlcyhjdXQsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdwaW5rJykgKw0KICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgoZCRjYXJhdCkpKSx2anVzdCA9IDIsIGNvbG9yID0gJ3llbGxvdycpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoNCjxwPkJp4buDdSDEkeG7kyBuw6B5IGJp4buDdSBkaeG7hW4gdOG7tyBs4buHIHBo4bqnbiB0csSDbSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGxv4bqhaSBjdXQNCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHBow6JuIHRoZW8gbG/huqFpIHbhu5tpIG3DoHUgc+G6r2MgxJHGsOG7nW5nIHZp4buBbiBj4bqvdDoNCg0KYGBge3J9DQpkICU+JSBncm91cF9ieShjdXQsY29sb3IpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjdXQseSA9IG4pKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoNCg0KYGBge3J9DQoNCmQgJT4lIGdyb3VwX2J5KGN1dCxjb2xvcikgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gbikpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgICBmYWNldF93cmFwKH5jb2xvcikgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDIsIGNvbG9yID0gJ3llbGxvdycpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoNCmBgYHtyfQ0KZCAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDIpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICd3aGl0ZScpICsNCiAgICBsYWJzKHggPSAnTcOgdScsIHkgPSAnTWVhbicpDQpgYGANCg0KDQpgYGB7cn0NCmQgJT4lIGdyb3VwX2J5KGN1dCxjb2xvcikgJT4lIHN1bW1hcmlzZShtID0gbWVhbihwcmljZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjdXQseSA9IG0pKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSkpKSArDQogICAgbGFicyh4ID0gJ0N1dCcsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHThu5VuZyB0cuG7jW5nIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYzoNCmBgYHtyfQ0KZ2dwbG90KGQsIGFlcyh4ID0gY29sb3IsIHkgPSBjYXJhdCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gInN1bSIpDQpgYGANCiBCaeG7g3UgxJHhu5MgdHLDqm4gYmnhu4N1IGRp4buFbiBz4buRIGzGsOG7o25nIGPhu6dhIDcgbG/huqFpIG3DoHUgc+G6r2MgY+G7p2Ega2ltIGPGsMahbmcgdOG7qyBsb+G6oWkgJ0QnIMSR4bq/biAnSicNCiAgIC1Nw6B1IEQgY8OzIGtob+G6o25nIDY3NzUgdmnDqm48cD4NCiAgIC1Nw6B1IEUgY8OzIGtob+G6o25nIDk3OTcgdmnDqm48cD4NCiAgIC1Nw6B1IEYgY8OzIGtob+G6o25nIDk1NDIgdmnDqm48cD4NCiAgIC1Nw6B1IEcgY8OzIGtob+G6o25nIDExMjkyIHZpw6puPHA+DQogICAtTcOgdSBIIGPDsyBraG/huqNuZyA4MzA0IHZpw6puPHA+DQogICAtTcOgdSBJIGPDsyBraG/huqNuZyA1NDIyIHZpw6puPHA+DQogICAtTcOgdSBKIGPDsyBraG/huqNuZyAyODA4IHZpw6puPHA+DQogIFRhIHRo4bqleSDEkcaw4bujYyBNw6B1IEcgY2hp4bq/bSB04bu3IGzhu4cgbmhp4buBdSB0cm9uZyBiaeG7g3UgxJHhu5MgdHLDqm4NCg0KYGBge3J9DQpnZ3Bsb3QoZCwgYWVzKHggPSBjdXQsIHkgPSBwcmljZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iKQ0KYGBgDQoNCg0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGdpw6EgdHLhu4sga2ltIGPGsMahbmcgbOG7m24gbmjhuqV0IHRoZW8gxJHhu5kgdHJvbmc6DQoNCmBgYHtyfQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGNsYXJpdHksIHkgPSBwcmljZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gbWF4KQ0KYGBgDQoNCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBnacOhIHRy4buLIGtpbSBjxrDGoW5nIG5o4buPIG5o4bqldCB0aGVvIG3DoHUgc+G6r2M6DQoNCmBgYHtyfQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGNvbG9yLCB5ID0gcHJpY2UpKSArDQogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9IG1pbikNCmBgYA0KDQoNCiMjIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gcGjDom4gcGjhu5FpIGdpw6EgdHLhu4sga2ltIGPGsMahbmcgdGhlbyBsb+G6oWkgY+G6r3Q6DQoNCmBgYHtyfQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGN1dCwgeSA9IHByaWNlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImRlbnNpdHkiKQ0KYGBgDQoNCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8ga8OtY2ggdGjGsOG7m2MgY+G7p2EgY2jDum5nOg0KDQpgYGB7cn0NCmdncGxvdChkLCBhZXMoeCA9IGNhcmF0KSkgKw0KICBnZW9tX2JhcihiaW53aWR0aCA9IDAuNSkNCmBgYA0KDQoNCiMjIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gdOG7lW5nIGdpw6EgdHLhu4sga2ltIGPGsMahbmcgdGhlbyBsb+G6oWkgY+G6r3QgdsOgIG3DoHUgc+G6r2M6DQoNCmBgYHtyfQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGN1dCwgZmlsbCA9IGNvbG9yLCB5ID0gcHJpY2UpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIiwgc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gInN1bSIpDQpgYGANCg0KPHA+Qmnhu4N1IMSR4buTIG7DoHkgY2hvIHRo4bqleSB04buVbmcgZ2nDoSB0cuG7iyBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBsb+G6oWkgY+G6r3QgdsOgIG3DoHUgc+G6r2MsIHbhu5tpIGPDoWMgY+G7mXQgxJHGsOG7o2MgeOG6v3AgY2jhu5NuZyBsw6puIG5oYXUuDQoNCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBnacOhIHRy4buLIHRydW5nIGLDrG5oIGtpbSBjxrDGoW5nIHRoZW8gbG/huqFpIGPhuq90IHbDoCDEkeG7mSB0cm9uZzoNCg0KYGBge3J9DQpnZ3Bsb3QoZGlhbW9uZHMsIGFlcyh4ID0gY3V0LCBmaWxsID0gY2xhcml0eSwgeSA9IHByaWNlKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIikNCmBgYA0KDQoNCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8ga8OtY2ggdGjGsOG7m2MgdsOgIG3DoHUgc+G6r2M6IA0KDQpgYGB7cn0NCmdncGxvdChkaWFtb25kcywgYWVzKHggPSBjYXJhdCwgZmlsbCA9IGNvbG9yKSkgKw0KICBnZW9tX2JhcihiaW53aWR0aCA9IDUpDQpgYGANCg0KDQo8cD5CaeG7g3UgxJHhu5MgbsOgeSBjaG8gdGjhuqV5IHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBrw61jaCB0aMaw4bubYyB2w6AgbcOgdSBz4bqvYywgduG7m2kgY8OhYyBj4buZdCDEkcaw4bujYyBuaMOzbSBs4bqhaSB0aGVvIGtob+G6o25nIGvDrWNoIHRoxrDhu5tjIDAuNSB2w6AgbcOgdSBz4bqvYyB0xrDGoW5nIOG7qW5nLg0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBrw61jaCB0aMaw4bubYyB2w6AgbG/huqFpIGPhuq90OiANCg0KYGBge3J9DQpnZ3Bsb3QoZGlhbW9uZHMsIGFlcyh4ID0gY2FyYXQsIGZpbGwgPSBjdXQpKSArDQogIGdlb21fYmFyKGJpbndpZHRoID0gMC41KQ0KYGBgDQoNCg0KPHA+Qmnhu4N1IMSR4buTIG7DoHkgY2hvIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8ga8OtY2ggdGjGsOG7m2MgdsOgIGxv4bqhaSBj4bqvdCwgduG7m2kgY8OhYyBj4buZdCDEkcaw4bujYyBuaMOzbSBs4bqhaSB0aGVvIGtob+G6o25nIGvDrWNoIHRoxrDhu5tjIDAuNSB2w6AgbG/huqFpIGPhuq90IHTGsMahbmcg4bupbmcuDQoNCiMjIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBraW0gY8awxqFuZyB0aGVvIGxv4bqhaSBj4bqvdCB2w6AgbcOgdSBz4bqvYzogDQoNCmBgYHtyfQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGN1dCwgZmlsbCA9IGNvbG9yLCB5ID0gcHJpY2UpKSArDQogIHN0YXRfc3VtbWFyeShmdW4gPSAibWVhbiIsIGdlb20gPSAiYmFyIikNCmBgYA0KDQoNCjxwPkJp4buDdSDEkeG7kyBuw6B5IGNobyB0aOG6pXkgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBtw6B1IHPhuq9jIHbDoCBsb+G6oWkgY+G6r3QsIHbhu5tpIGPDoWMgY+G7mXQgxJHGsOG7o2MgeOG6v3AgY2jhu5NuZyBsw6puIG5oYXUuDQoNCiMjIEJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBraW0gY8awxqFuZyB0aGVvIG3DoHUgc+G6r2MgdsOgIMSR4buZIHRyb25nOg0KDQoNCmBgYHtyfQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGNvbG9yLCBmaWxsID0gY2xhcml0eSwgeSA9IHByaWNlKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIikNCmBgYA0KDQoNCjxwPkJp4buDdSDEkeG7kyBuw6B5IGNobyB0aOG6pXkgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBtw6B1IHPhuq9jIHbDoCDEkeG7mSB0cm9uZywgduG7m2kgY8OhYyBj4buZdCDEkcaw4bujYyB44bq/cCBjaOG7k25nIGzDqm4gbmhhdS48cD4NCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8ga8OtY2ggdGjGsOG7m2MgdsOgIG3DoHUgc+G6r2M6DQoNCmBgYHtyfQ0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGNhcmF0LCBmaWxsID0gY29sb3IpKSArDQogIGdlb21fYmFyKGJpbndpZHRoID0gMC41KQ0KYGBgDQoNCg0KPHA+Qmnhu4N1IMSR4buTIG7DoHkgY2hvIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8ga8OtY2ggdGjGsOG7m2MgdsOgIG3DoHUgc+G6r2MsIHbhu5tpIGPDoWMgY+G7mXQgxJHGsOG7o2MgbmjDs20gbOG6oWkgdGhlbyBraG/huqNuZyBrw61jaCB0aMaw4bubYyAwLjUgdsOgIG3DoHUgc+G6r2MgdMawxqFuZyDhu6luZy4NCg0KIyMgQmnhu4N1IMSR4buTIHBow6JuIHTDrWNoIMSR4buZIHRpbmgga2hp4bq/dCBj4bunYSBraW0gY8awxqFuZw0KDQpgYGB7cn0NCmQgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY2xhcml0eSxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2xpZ2h0Z3JlZW4nKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG3hurd0IHBow6JuIGPhuq90IGtpbSBjxrDGoW5nIHRoZW8gxJHGoW4gduG7iyBwaOG6p24gdHLEg20NCmBgYHtyfQ0KZCAlPiUgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgeSA9IC4ucHJvcC4uLCBncm91cCA9IDEpKSArDQogIGdlb21fYmFyKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSsNCiAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gxJHhu5kgbOG7m24NCmBgYHtyfQ0KZCA8LSBkaWFtb25kcyANCmQgPC0gZCAlPiUgbXV0YXRlKGNhcmF0QyA9IGN1dChjYXJhdCw1LCBsYWJlbCA9IGMoJ3LhuqV0IG5o4buPJywgJ25o4buPJywnduG7q2EnLCds4bubbicsJ3LhuqV0IGzhu5tuJykpKQ0KZCAlPiUgZ2dwbG90KGFlcyh4ID0gY2FyYXRDKSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ3BpbmsnKQ0KICAgDQpgYGANCg0KIyMgQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nDQpgYGB7cn0NCmQlPiUgZ3JvdXBfYnkoY3V0LCBjbGFyaXR5KSU+JXN1bW1hcmlzZShtPW1lYW4oZGVwdGgpKSU+JWdncGxvdChhZXMoeD1jdXQsIHk9IG0pKSsNCiAgZ2VvbV9jb2wocG9zaXRpb249J2RvZGdlJykrDQogIGZhY2V0X3dyYXAofmNsYXJpdHkpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPSByb3VuZChtKSksIHZqdXN0PTIsIGNvbG9yPSdyZWQnKSsgDQogIGxhYnMoeD0gJ0xv4bqhaScsIHk9ICfEkOG7mSBzw6J1IHRydW5nIGLDrG5oJykNCmBgYA0KDQojIyBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIHBoxrDGoW5nIHNhaSB0cuG7jW5nIGzGsOG7o25nIGPhu6dhIGtpbSBjxrDGoW5nIHRoZW8gbcOgdQ0KYGBge3J9DQpkICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZSh2PSB2YXIoY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY29sb3IseSA9IHYpKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKHYsMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgICBsYWJzKHggPSAnTcOgdScsIHkgPSAnVmFyJykNCmBgYA0KDQo=