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=