“23:23:53, 02 - 03 - 2024”

#ĐỒ THỊ DẠNG BAR CHART CHO BỘ DỮ LIỆU DIAMOND

library(datasets)
data(package = 'datasets')
library(ggplot2)
data(package = 'ggplot2')
dq <- diamonds

#Đồ Thị Số 1

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
## ✔ lubridate 1.9.3     ✔ tibble    3.2.1
## ✔ purrr     1.0.2     ✔ tidyr     1.3.0
## ── 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
dq <- diamonds
dq %>% ggplot(aes(x = cut)) +
    geom_bar() +
    labs(x = 'Loại', y = 'Số lượng')

- Ta phân loại kim cương theo kiểu cắt, có Fair; Good; Very Good; Premium; Ideal
- Gán cho trục x nhãn là " Loại ", gán cho trục y nhãn là "Số lượng"
=> Loại "Ideal" có số lượng nhiều nhất, trên 20000
=> Loại " Fair " có số lượng ít nhất, dưới 5000
=> Loại " Good " có số lượng là 5000

#Đồ Thị Số 2

library(tidyverse)
library(scales)
dq <- diamonds
dq %>% ggplot(aes(x = color)) +
    geom_bar() +
    labs(x = 'Màu sắc', y = 'Số lượng')

- Ta phân loại kim cương theo màu sắc, có D, E, F, G, H, I ,J
- Gán cho trục x nhãn là " Màu sắc ", gán cho trục y nhãn là "Số lượng"
=> Màu "G" có số lượng nhiều nhất
=> Màu " J " có số lượng ít nhấT
=> Màu " E " và màu "F" có số lượng gần bằng nhau

#Đồ Thị Số 3

library(tidyverse)
library(scales)
dq <- diamonds
dq %>% ggplot(aes(x = clarity)) +
    geom_bar() +
    labs(x = 'Độ tinh khiết', y = 'Số lượng')

- Ta phân loại kim cương theo độ tinh khiết, có I1, SI1, SI2, VS1,VS2,VVS1,VVS2,IF
- Gán cho trục x nhãn là " Độ tinh khiết ", gán cho trục y nhãn là "Số lượng"
=> Loại "SI1" có số lượng nhiều nhất
=> Loại " I1 " có số lượng ít nhấT

#Đồ Thị Số 4

 dq <- diamonds
dq %>% ggplot(aes(x = cut)) +
    geom_bar() +
    labs(x = 'Loại', y = 'Số lượng') +
    coord_flip()  

  • Phân loại kim cương theo kiểu cắt
  • Đồ thị xoay ngang cho ta thấy số lượng kim cương từng loại giảm dần từ Ideal -> Premium -> Very Good -> Good -> Fair

#Đồ Thị Số 5

dq <- diamonds
dq %>% ggplot(aes(x = color)) +
    geom_bar() +
    labs(x = 'Màu sắc', y = 'Số lượng') +
coord_flip()

  • Phân loại kim cương theo màu sắc
  • Đồ thị xoay ngang cho ta thấy số lượng kim cương từng loại tăng dần từ màu J -> I -> H -> G; sau đó giảm xuống F rồi tăng lên E rồi giảm về D

#Đồ thị số 6

    dq <- diamonds
dq %>% ggplot(aes(x = clarity)) +
    geom_bar() +
    labs(x = 'Độ tinh khiết', y = 'Số lượng') +
  coord_flip()

  • Phân loại kim cương theo độ tinh khiết
  • Đồ thị xoay ngang cho ta thấy số lượng kim cương từng loại tăng dần từ IF -> VVS1 -> VVS2 -> VS1 -> VS2 -> SI1; sau đó giảm dần từ SI1 -> SI2 -> I1

#Đồ thị số 7

    dq %>% group_by(cut) %>% summarise(n = n()) %>%
  ggplot(aes(cut,n)) +
    geom_col(fill='skyblue') +
    geom_text(aes(label = n),vjust = 2, color = 'red') +
    labs(x = 'Loại', y = 'Số lượng')

- Ta Phân loại kim cương theo từng loại và tính số lượng của từng loại. x là loại của kim cương, y là số lượng của từng loại.
- Các số liệu có màu đỏ, được điều chỉnh ở vị trí dọc cách cột 2 đơn vị. Màu của các cột là màu xanh da trời.
- Qua biểu đồ trên ta thấy được nhiều nhất là loại Ideal với 21551 viên, tiếp đến là Premium với 13791 viên
- Very Good với 12082 viên, Good với 4906 viên,Fair với 1610 viên

#Đồ thị số 8

 dq %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(color,n)) +
    geom_col(fill='turquoise') +
    geom_text(aes(label = n),vjust = 2, color = 'red') +
    labs(x = 'Màu sắc', y = 'Số lượng')

  • Ta Phân loại kim cương theo màu sắc và tính số lượng của từng màu sắc.
  • x là màu sắc của kim cương, y là số lượng của từng loại màu sắc.
  • Các số liệu có màu đỏ, được điều chỉnh ở vị trí dọc cách cột 2 đơn vị. Màu của các cột là xanh ngọc.
  • Qua biểu đồ trên ta thấy được nhiều nhất là màu G với 11292 viên, tiếp đến là E với 9797 viên
  • F với 9542 viên, H với 8304 viên,D với 6775 viên
  • I với 5422 viên và ít nhất là màu J với 2808 viên

#Đồ thị số 9

dq %>% group_by(clarity) %>% summarise(n = n()) %>%
  ggplot(aes(clarity,n)) +
    geom_col(fill='green') +
    geom_text(aes(label = n),vjust = 2, color = 'red') +
    labs(x = 'Độ tinh khiết', y = 'Số lượng')

  • Ta Phân loại kim cương theo độ tinh khiết và tính số lượng của từng loại.
  • x là độ tinh khiết của kim cương, y là số lượng của từng loại.
  • Các số liệu có màu đỏ, được điều chỉnh ở vị trí dọc cách cột 2 đơn vị. Màu của các cột là xanh lá cây.
  • Qua biểu đồ trên ta thấy được nhiều nhất là loại SI1 với 13065 viên, tiếp đến là VS2 với 12258 viên
  • SI2 với 9194 viên, VS1 với 8171 viên,VVS2 với 5066 viên
  • VVS1 với 3655 viên, IF với 1790 viên và ít nhất là I1 với 741 viên

#Đồ thị số 10

    dq %>% group_by(cut) %>% summarise(n = n()) %>%
  ggplot(aes(cut,n)) +
    geom_col(fill='green') +
    geom_text(aes(label = percent(n/length(dq$carat))),vjust = 2, color = 'red') +
    labs(x = 'Loại', y = 'Số lượng')

- Ta Phân loại kim cương theo từng loại và tính phần trăm số lượng của từng loại. x là loại của kim cương, y là số lượng của từng loại.
- Các số liệu có màu đỏ, được điều chỉnh ở vị trí dọc cách cột 2 đơn vị. Màu của các cột là màu xanh lá cây.
- Qua biểu đồ trên ta thấy được nhiều nhất là loại Ideal với 40.0%, tiếp đến là Premium với 25.6%
- Very Good với 22.4%, Good với 9.1% ,Fair với 3.0%

#Đồ thị số 11

    dq %>% 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.

  • Ta phân nhóm kim cương theo kiểu cắt và màu sắc sau đó tính số lượng.
  • Ta gắn x là loại, y la số lượng
  • Chia thành 7 biểu đồ theo 7 loại màu sắc để so sánh.
  • Qua 7 biểu đồ ta nhận xét các màu sắc phân bổ nhiều nhất ở kim cương có kiểu cắt Ideal, giảm dần qua các kiểu cắt Premium, Very Good, Good và phân bổ ít nhất ở kiểu cắt Fair

#Đồ thị số 12

    dq <- diamonds
  dq %>% 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 = 'green') +
    labs(x = 'Loại', y = 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

  • Ta phân nhóm kim cương theo kiểu cắt và màu sắc sau đó tính số lượng.
  • Ta gắn x là loại, y la số lượng
  • Các số liệu có màu xanh lá, được điều chỉnh ở vị trí dọc cách cột 2 đơn vị.
  • Chia thành 7 biểu đồ theo 7 loại màu sắc để so sánh.
  • Qua 7 biểu đồ ta nhận xét các màu sắc phân bổ nhiều nhất ở kim cương có kiểu cắt Ideal, giảm dần qua các kiểu cắt Premium, Very Good, Good và phân bổ ít nhất ở kiểu cắt Fair

#Đồ thị số 13

dq <- diamonds
dq %>% 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.

  • Ta phân nhóm kim cương theo kiểu cắt và màu sắc sau đó tính trung bình về giá của từng loại.
  • Ta gắn x là loại, y la số lượng
  • Chia thành 7 biểu đồ theo 7 loại màu sắc để so sánh.
  • Qua 7 biểu đồ ta nhận xét giá trung bình của loại ‘Premium’ là cao nhất ờ hầu hết các màu trừ màu G và màu H
  • Gía trung bình của loại ‘Ideal’ là thấp nhất ở các màu trừ màu J

#Đồ thị số 14

dq <- diamonds
dq <- dq %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
dq %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = dq %>% filter(color == 'E'), fill = 'purple') +
  geom_col(data = dq %>% filter(color == 'H'), fill = 'turquoise')

  • Ta phân loại kim cương theo kiểu cắt và màu sắc sau đó tính số lượng .
  • Ở biểu đồ trên thì ta gắn x là kiểu cắt, y là số lượng của từng loại;
  • Ta sẽ lọc các loại kim cương có màu E,cột biểu đồ có màu tím và lọc các loại kim cương có màu H, biểu đồ có màu xanh ngọc.
  • Qua biểu đồ trên ta đã lọc được số lượng kim cương màu H phân bổ ít nhất ở kiểu cắt Fair và tăng dần lên từ Good, Very Good, Premium, và nhiều nhất là Ideal. Và số lượng kim cương có màu E phân bổ ở 3 loại nhiều nhất là loại ’ Ideal’ sau đó là ‘Very Good’ và ít nhất là ‘Good’

#Đồ thị số 15

dq <- diamonds
dq <- dq %>% group_by(cut, clarity) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
dq %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = dq %>% filter(clarity == 'VS1'), fill = 'skyblue') +
  geom_col(data = dq %>% filter(clarity == 'IF'), fill = 'pink')

  • Ta phân loại kim cương theo kiểu cắt và độ tinh khiết sau đó tính số lượng .
  • Ở biểu đồ trên thì ta gắn x là kiểu cắt, y là số lượng của từng loại;
  • Ta sẽ lọc các loại kim cương có độ tinh khiết là VS1,cột biểu đồ có màu xanh da trời và lọc các loại kim cương có độ tinh khiết IF, biểu đồ có màu hồng.
  • Qua biểu đồ trên ta đã lọc được số lượng kim cương độ tinh khiết VS1 phân bổ ít nhất ở kiểu cắt Fair và tăng dần lên từ Good, Very Good, Premium, và nhiều nhất là Ideal. Và số lượng kim cương có độ tinh khiết IF phân bổ nhiều nhất là loại ’ Ideal’ sau đó là ‘Very Good’, tiếp đến là ’ Premium’ , sau đó là ’ Good’ và ít nhất là ‘Fair’

#Đồ thị số 16

dq <- diamonds 
dq <- dq %>% mutate(caratC = cut(carat,5, label = c('rất nhỏ', 'nhỏ','vừa','lớn','rất lớn')))
dq %>% ggplot(aes(x = caratC)) +
  geom_bar(fill = 'skyblue')

  • Ta thêm 1 cột dữ liêu caratC vào bộ dữ liệu để đánh giá trọng lượng của các viên kim cương theo mức độ ‘rất nhỏ’ ‘nhỏ’, ‘vừa’ và ‘lớn’.
  • Các cột biểu đồ có màu xanh da trời.
  • Qua biểu đồ trên ta thấy số lượng kim cương có trọng lượng ‘rất nhỏ’ là lớn nhất và giảm dần từ ‘nhỏ’, ‘vừa’, ‘lớn’ và thấp nhất là loại ‘rất lớn’

#Đồ thị số 17

dq <- diamonds 
dq <- dq %>% mutate(price = cut(price,3, label = c('thấp','vừa','cao')))
dq %>% ggplot(aes(x = price)) +
  geom_bar(fill = 'pink')

  • Ta thêm 1 cột dữ liêu price vào bộ dữ liệu để đánh giá về giá cả của các viên kim cương theo mức độ ‘thấp’,‘vừa’,‘cao’.
  • Các cột biểu đồ có màu hồng .
  • Qua biểu đồ trên ta thấy số lượng kim cương có giá ‘thấp’ là lớn nhất trên 40000 viên và giảm dần xuống ‘vừa’ và thấp nhất là loại ‘cao’

#Đồ thị số 18

dq <- diamonds 
dq <- dq %>% mutate(depth = cut(depth,5, label = c('rất nhỏ', 'nhỏ','vừa','lớn','rất lớn')))
dq %>% ggplot(aes(x = depth)) +
  geom_bar(fill = 'blue')

  • Ta thêm 1 cột dữ liêu depth vào bộ dữ liệu để đánh giá về khoảng cách từ mặt đến đáy của các viên kim cương theo mức độ ‘rất nhỏ’,‘nhỏ’,‘vừa’,‘lớn’,‘rất lớn’.
  • Các cột biểu đồ có màu xanh dương .
  • Qua biểu đồ trên ta thấy số lượng kim cương có khoảng cách ‘vừa’ là lớn nhất trên 50000 viên và giảm dần xuống ‘lớn’, ‘nhỏ’ và thấp nhất là loại ‘rất nhỏ’ và ’ rất lớn’

#Đồ Thị Số 19

  dq %>% group_by(clarity) %>% summarise(m= mean(carat)) %>%
  ggplot(aes(x = clarity,y = m)) +
  geom_col(position = 'dodge') +
  geom_text(aes(label = round(m,5)), vjust = 2, color = 'green') +
  labs(x = 'độ tinh khiết', y = 'trọng lượng trung bình')

  • Ta phân loại kim cương theo độ tinh khiết và tính trọng lượng trung bình của chúng theo đơn vị carat.
  • Ở biểu đồ trên thì ta gắn x là độ tinh khiết, y là khối lượng trung bình của từng loại
  • Các số liệu sẽ có màu xanh lá cây, được làm tròn 5 chữ số thập phân và được điều chỉnh ở vị trí dọc cách cột với đơn vị là 2. Và ta thấy được kim cương có độ trong suốt cao nhất là I1, thấp hơn đó là SI2 và giảm dần từ SI1, VS2, VS1, WS2, WS1, và thấp nhất là IF.

#Đồ Thị Số 20

  dq %>% group_by(clarity) %>% summarise(n = n()) %>%
  ggplot(aes(clarity,n)) +
  geom_col(fill='green') +
  geom_text(aes(label = percent(n/length(dq$price))),vjust = 2, color = 'red') +
  labs(x = 'Loại', y = 'Số lượng')

  • Ta phân loại kim cương theo độ tinh khiết và tính số lượng của các màu.
  • Ta gắn x là ‘Loại’, y là ‘Số Lượng’.
  • Các cột biểu đồ được tô màu xanh lá cây, các số liệu là tỷ lệ giá tiền của mỗi loại kim cương, các số liệu này có màu đỏ và được điều chỉnh vị trí dọc các cột dữ liệu với đơn vị là 2.
  • Qua biểu đồ trên ta thấy kim cương có độ trong suốt SI1 chiếm tỷ lệ giá cao nhất là 24,2%, giảm dần từ VS2, SI2, VS1, VVS2, VVS1, IF, I1 là 1,4%

#Đồ thị số 21

dq <- diamonds
dq <- dq %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
dq %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = dq %>% filter(color == 'G'), fill = 'red') +
  geom_col(data = dq %>% filter(color == 'D'), fill = 'turquoise')

  • Ta phân loại kim cương theo kiểu cắt và màu sắc sau đó tính số lượng .
  • Ở biểu đồ trên thì ta gắn x là kiểu cắt, y là số lượng của từng loại;
  • Ta sẽ lọc các loại kim cương có màu G,cột biểu đồ có màu đỏ và lọc các loại kim cương có màu D, biểu đồ có màu xanh ngọc.
  • Qua biểu đồ trên ta đã lọc được số lượng kim cương màu G phân bổ ít nhất ở kiểu cắt Fair và tăng dần lên từ Good, Very Good, Premium, và nhiều nhất là Ideal. Và số lượng kim cương có màu D phân bổ nhiều nhất là loại ’ Ideal’ sau đó giảm dần là ‘Premium’; ‘Very Good’; ‘Good’; và ít nhất là ‘Fair’

#Đồ thị số 22

dq <- diamonds
dq %>% group_by(carat) %>% filter(carat == 0.5 | carat == 1.00 | carat == 1.5 | carat == 2.05) %>% summarise(n = n()) %>%
  ggplot(aes(carat,n)) +
    geom_col(fill='skyblue') +
     geom_text(aes(label = n),vjust = 2, color = 'red') +
    xlab('Carat') +
    ylab('Số lượng')

  • Ta phân loại kim cương theo trọng lượng carat ở các mốc 0.5, 1.0, 1.5, 2.0 và tính số lượng của từng mốc khối lương.
  • Ta gắn x là carat và y là số lượng từng mốc carat.
  • Các cột biểu đồ có màu xanh da trời, các số liệu có màu đỏ, được điều chỉnh ở vị trí dọc cách cột 2 đơn vị .
  • Qua biểu đồ trên ta thấy được số kim cương có trọng lượng 1.0 carat là nhiều nhất với 1558 viên và thấp nhất là 2.0 với 67 viên
  • Ngoài ra kim cương có trọng lượng 0.5 có số lượng là 1258 viên, 1,0 có số lượng là 1558 viên

#Đồ thị số 23

dq <- diamonds
dq <- dq %>% group_by(cut, clarity) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
dq %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = dq %>% filter(clarity == 'SI1'), fill = 'blue') +
  geom_col(data = dq %>% filter(clarity == 'SI2'), fill = 'turquoise') +
  geom_col(data = dq %>% filter(clarity == 'IF'), fill = 'pink')

  • Ta phân loại kim cương theo kiểu cắt và độ tinh khiết sau đó tính số lượng .
  • Ở biểu đồ trên thì ta gắn x là kiểu cắt, y là số lượng của từng loại;
  • Ta sẽ lọc các loại kim cương loại SI1,cột biểu đồ có màu xanh và lọc các loại kim cương loại SI2, biểu đồ có màu xanh ngọc, lọc các viên kim cương loại IF, biểu đồ có màu hồng
  • Qua biểu đồ trên ta đã lọc được số lượng kim cương loại SI1 phân bổ nhiều nhất ở kiểu cắt ‘Ideal’ sau đó tới ‘Very Good’ và ‘Premium’ với ‘Good’ gần như bằng nhau và không có viên nào loại ‘Fair’
  • Số lượng viên kim cương loại SI2 chiếm phần lớn trong 3 loại SI1 SI2 VÀ IF, và SI2 chiếm số lượng nhiều nhất ở loại ‘Premium’ và ít nhất ở ‘Fair’
  • Số lượng viên kim cương loại IF tăng dần từ Good -> Very Good -> Premium -> Ideal

#Đồ thị số 23

dq <- diamonds
dq <- dq %>% group_by(cut, clarity) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
dq %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = dq %>% filter(clarity == 'SI1'), fill = 'blue') +
  geom_col(data = dq %>% filter(clarity == 'VS2'), fill = 'turquoise') +
   geom_col(data = dq %>% filter(clarity == 'SI2'), fill = 'red') +
   geom_col(data = dq %>% filter(clarity == 'VVS1'), fill = 'black')

  geom_col(data = dq %>% filter(clarity == 'VVS2'), fill = 'pink')
## geom_col: just = 0.5, width = NULL, na.rm = FALSE
## stat_identity: na.rm = FALSE
## position_stack
  • Ta phân loại kim cương theo kiểu cắt và độ tinh khiết sau đó tính số lượng .
  • Ở biểu đồ trên thì ta gắn x là kiểu cắt, y là số lượng của từng loại;
  • Ta sẽ lọc các loại kim cương loại SI1,cột biểu đồ có màu xanh và lọc các loại kim cương loại VS2, biểu đồ có màu xanh ngọc, lọc các viên kim cương loại VVS1, biểu đồ có màu đen, các kim cương loại VVS2, biểu đồ cột có màu hồng
  • Qua biểu đồ ta thấy ở loại Fair SI2 chiếm diện tích lớn nhất
  • Ở loại Good SI2 chiếm diện tích lớn nhất sau đó là SI1 và VVS1
  • Ở loại Very Good SI2 chiếm diện tích lớn nhất sau đó là VVS1, SI1 và VS2
  • Ở loại Premium VS2 chiếm diện tích lớn nhất sau đó là VVS1 và sau đó là SI2
  • Ở loại Ideal VS2 chiếm diện tích nhiều nhất, sau đó là VVS1 và SI2

#Đồ thị số 24

dq <- diamonds
dq <- dq %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
dq %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = dq %>% filter(color == 'D'), fill = 'red') +
    geom_col(data = dq %>% filter(color == 'J'), fill = 'blue') +
    geom_col(data = dq %>% filter(color == 'G'), fill = 'pink') +
    geom_col(data = dq %>% filter(color == 'H'), fill = 'brown') +
    geom_col(data = dq %>% filter(color == 'E'), fill = 'purple') +
    geom_col(data = dq %>% filter(color == 'F'), fill = 'yellow') +
  geom_col(data = dq %>% filter(color == 'I'), fill = 'turquoise')

  • Ta phân loại kim cương theo kiểu cắt và màu sắc sau đó tính số lượng .
  • Ở biểu đồ trên thì ta gắn x là kiểu cắt, y là số lượng của từng loại;
  • Ta sẽ lọc các loại kim cương màu D,cột biểu đồ có màu đỏ
  • lọc các loại kim cương màu J, biểu đồ có màu xanh
  • lọc các viên kim cương màu G, biểu đồ có màu hồng
  • các kim cương có màu H, biểu đồ cột có màu nâu
  • lọc các viên kim cương màu E, biểu đồ có màu tím
  • lọc các viên kim cương màu F, biểu đồ có màu vàng
  • lọc các viên kim cương màu I, biểu đồ có màu xanh ngọc
  • Qua biểu đồ ta thấy ở loại Fair F và I chiếm diện tích gần như bằng nhau
  • Ở loại Good I chiếm diện tích lớn nhất sau đó là F và E
  • Ở loại Very Good I chiếm diện tích lớn nhất sau đó là F,E
  • Ở loại Premium I chiếm diện tích lớn nhất sau đó là F, G và sau đó là D
  • Ở loại Ideal I chiếm diện tích lớn nhất sau đó là I,sau đó là F,G và E

#Đồ thị số 25

dq <- diamonds
dq <- dq %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
dq %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = dq %>% filter(color == 'D'), fill = 'red') +
    geom_col(data = dq %>% filter(color == 'J'), fill = 'blue') +
    geom_col(data = dq %>% filter(color == 'G'), fill = 'pink') +
    geom_col(data = dq %>% filter(color == 'H'), fill = 'brown') +
    geom_col(data = dq %>% filter(color == 'E'), fill = 'purple') +
    geom_col(data = dq %>% filter(color == 'F'), fill = 'yellow') +
  geom_col(data = dq %>% filter(color == 'I'), fill = 'turquoise') +
  coord_flip() 

  • Đồ thị nằm ngang của đồ thị 25
  • Qua đồ thị ta thấy số lượng giảm dần từ loại Ideal -> Premium -> Very Good -> Good -> Fair

#Đồ thị số 26

    dq %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(color,n)) +
    geom_col(fill='pink') +
    geom_text(aes(label = percent(n/length(dq$price))),vjust = 2, color = 'black') +
    labs(x = 'Màu', y = 'Số lượng')
## Warning: Unknown or uninitialised column: `price`.
## Unknown or uninitialised column: `price`.

  • Ta phân loại kim cương theo màu sắc và tính số lượng giá của từng loại.
  • Ta gắn x là ‘Màu’, y là ‘Số Lượng’.
  • Các cột biểu đồ được tô màu hồng, các số liệu là tỷ lệ giá tiền của mỗi loại kim cương, các số liệu này có màu đen và được điều chỉnh vị trí dọc các cột dữ liệu với đơn vị là 2.
  • Qua biểu đồ trên ta thấy kim cương màu G chiếm tỷ lệ cao nhất về giá với 20.93%
  • Kim cương màu J chiếm tỷ lệ thấp nhất về giá với 5.21%
  • Kim cương màu G cao hơn và gấp kim cương màu I là 2,08 lần
  • Kim cương màu H cao hơn và gấp kim cương màu J là 2,95 lần
  • Kim cương màu I cao hơn và gấp kim cương màu J là 1,93 lần

#Đồ thị số 27

    dq %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(color,n)) +
    geom_col(fill='pink') +
    geom_text(aes(label = percent(n/length(dq$price))),vjust = 2, color = 'black') +
    labs(x = 'Màu', y = 'Số lượng') +
  coord_flip()
## Warning: Unknown or uninitialised column: `price`.
## Unknown or uninitialised column: `price`.

- Đây là đồ thị nằm ngang của đồ thị số 26
- Qua đồ thị ta thấy  số lượng kim cương tăng dần từ màu J -> I -> H -> G, sau giảm dần

#Đồ thị số 28

dq <- diamonds
dq %>% group_by(color) %>% summarise(m = mean(depth)) %>%
  ggplot(aes(color,m)) +
  geom_col(fill='skyblue') +
  geom_text(aes(label = round(m,2)),vjust = 2, color = 'red') +
  labs(x = 'Loại', y = 'Số lượng')

  • Ta phân loại kim cương theo màu sắc và tính trung bình tỷ lệ độ sâu của từng loại.
  • Các cột biểu đồ có màu xanh da trời, các dữ liệu có màu đỏ, được làm tròn đến 2 chữ số thập phân và được điều chỉnh ở vị trí dọc cách cột 2 đơn vị.
  • Qua biểu đồ trên ta thấy các loại màu của kim cương sẽ có xấp xỉ trung bình tỷ lệ độ sâu bằng nhau. Trong đó cao nhất là màu J với 61.89 và thấp nhất là màu E với 61.66

#Đồ thị số 29

dq %>% group_by(clarity) %>% summarise(m= mean(carat)) %>%
  ggplot(aes(x = clarity,y = m)) +
  geom_col(position = 'dodge') +
  geom_text(aes(label = round(m,3)), vjust = 2, color = 'green') +
  labs(x = 'độ tinh khiết', y = 'trọng lượng trung bình')

  • Ta phân loại kim cương theo độ tinh khiết và tính trọng lượng trung bình của chúng theo đơn vị carat.
  • Ở biểu đồ trên thì ta gắn x là độ tinh khiết, y là khối lượng trung bình của từng loại
  • Các số liệu sẽ có màu xanh lá cây, được làm tròn 3 chữ số thập phân và được điều chỉnh ở vị trí dọc cách cột với đơn vị là 2.
  • Ta thấy được kim cương có độ trong suốt cao nhất là I1 với 1.284, thấp hơn đó là SI2 và giảm dần từ SI1, VS2, VS1, WS2, WS1, và thấp nhất là IF với 0.505

#Đồ thị số 30

dq %>% group_by(clarity) %>% summarise(m= mean(carat)) %>%
  ggplot(aes(x = clarity,y = m)) +
  geom_col(position = 'dodge') +
  geom_text(aes(label = round(m,3)), vjust = 2, color = 'green') +
  labs(x = 'độ tinh khiết', y = 'trọng lượng trung bình') +
    coord_flip()

  • Đồ thị nằm ngang của đồ thị số 30
  • Qua đồ thị ta thấy trọng lượng trung bình của độ tinh khiết tăng dần từ IF -> VVS1 -> VVS2 -> VS1 ->VS2 -> SI1 -> SI1 -> I1
LS0tDQp0aXRsZTogIk5ISeG7hk0gVuG7pCA0Ig0KYXV0aG9yOiAiTmd1eeG7hW0gRGnhu4VtIFF14buzbmgiDQpkYXRlOiAiMjAyNC0wMy0wMiINCm91dHB1dDoNCiBodG1sX2RvY3VtZW50Og0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgDQotLS0NCiJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVIOiVNOiVTLCAlZCAtICVtIC0gJVknKWAiDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQoNCiPEkOG7kiBUSOG7iiBE4bqgTkcgQkFSIENIQVJUIENITyBC4buYIEThu64gTEnhu4ZVIERJQU1PTkQNCg0KDQpgYGB7cn0NCmxpYnJhcnkoZGF0YXNldHMpDQpkYXRhKHBhY2thZ2UgPSAnZGF0YXNldHMnKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZGF0YShwYWNrYWdlID0gJ2dncGxvdDInKQ0KZHEgPC0gZGlhbW9uZHMNCmBgYA0KDQojxJDhu5MgVGjhu4sgU+G7kSAxDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCmRxIDwtIGRpYW1vbmRzDQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0KSkgKw0KICAgIGdlb21fYmFyKCkgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogICAgDQogICAgLSBUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QsIGPDsyBGYWlyOyBHb29kOyBWZXJ5IEdvb2Q7IFByZW1pdW07IElkZWFsDQogICAgLSBHw6FuIGNobyB0cuG7pWMgeCBuaMOjbiBsw6AgIiBMb+G6oWkgIiwgZ8OhbiBjaG8gdHLhu6VjIHkgbmjDo24gbMOgICJT4buRIGzGsOG7o25nIg0KICAgID0+IExv4bqhaSAiSWRlYWwiIGPDsyBz4buRIGzGsOG7o25nIG5oaeG7gXUgbmjhuqV0LCB0csOqbiAyMDAwMA0KICAgID0+IExv4bqhaSAiIEZhaXIgIiBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgbmjhuqV0LCBkxrDhu5tpIDUwMDANCiAgICA9PiBMb+G6oWkgIiBHb29kICIgY8OzIHPhu5EgbMaw4bujbmcgbMOgIDUwMDANCiAgICANCiPEkOG7kyBUaOG7iyBT4buRIDINCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCmRxIDwtIGRpYW1vbmRzDQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gY29sb3IpKSArDQogICAgZ2VvbV9iYXIoKSArDQogICAgbGFicyh4ID0gJ03DoHUgc+G6r2MnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogICAgDQogICAgLSBUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jLCBjw7MgRCwgRSwgRiwgRywgSCwgSSAsSg0KICAgIC0gR8OhbiBjaG8gdHLhu6VjIHggbmjDo24gbMOgICIgTcOgdSBz4bqvYyAiLCBnw6FuIGNobyB0cuG7pWMgeSBuaMOjbiBsw6AgIlPhu5EgbMaw4bujbmciDQogICAgPT4gTcOgdSAiRyIgY8OzIHPhu5EgbMaw4bujbmcgbmhp4buBdSBuaOG6pXQNCiAgICA9PiBNw6B1ICIgSiAiIGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pVQNCiAgICA9PiBNw6B1ICIgRSAiIHbDoCBtw6B1ICJGIiBjw7Mgc+G7kSBsxrDhu6NuZyBn4bqnbiBi4bqxbmcgbmhhdQ0KICAgIA0KI8SQ4buTIFRo4buLIFPhu5EgMyAgICANCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCmRxIDwtIGRpYW1vbmRzDQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSkpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBsYWJzKHggPSAnxJDhu5kgdGluaCBraGnhur90JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KICAgIA0KICAgIC0gVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gxJHhu5kgdGluaCBraGnhur90LCBjw7MgSTEsIFNJMSwgU0kyLCBWUzEsVlMyLFZWUzEsVlZTMixJRg0KICAgIC0gR8OhbiBjaG8gdHLhu6VjIHggbmjDo24gbMOgICIgxJDhu5kgdGluaCBraGnhur90ICIsIGfDoW4gY2hvIHRy4bulYyB5IG5ow6NuIGzDoCAiU+G7kSBsxrDhu6NuZyINCiAgICA9PiBMb+G6oWkgIlNJMSIgY8OzIHPhu5EgbMaw4bujbmcgbmhp4buBdSBuaOG6pXQNCiAgICA9PiBMb+G6oWkgIiBJMSAiIGPDsyBz4buRIGzGsOG7o25nIMOtdCBuaOG6pVQNCiAgICANCiPEkOG7kyBUaOG7iyBT4buRIDQgICAgDQpgYGB7cn0NCiBkcSA8LSBkaWFtb25kcw0KZHEgJT4lIGdncGxvdChhZXMoeCA9IGN1dCkpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykgKw0KICAgIGNvb3JkX2ZsaXAoKSAgDQpgYGANCg0KIA0KIC0gUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90DQogLSAgxJDhu5MgdGjhu4sgeG9heSBuZ2FuZyBjaG8gdGEgdGjhuqV5IHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdOG7q25nIGxv4bqhaSBnaeG6o20gZOG6p24gdOG7qyBJZGVhbCAtPiBQcmVtaXVtIC0+IFZlcnkgR29vZCAtPiBHb29kIC0+IEZhaXINCiANCiPEkOG7kyBUaOG7iyBT4buRIDUNCmBgYHtyfQ0KDQpkcSA8LSBkaWFtb25kcw0KZHEgJT4lIGdncGxvdChhZXMoeCA9IGNvbG9yKSkgKw0KICAgIGdlb21fYmFyKCkgKw0KICAgIGxhYnMoeCA9ICdNw6B1IHPhuq9jJywgeSA9ICdT4buRIGzGsOG7o25nJykgKw0KY29vcmRfZmxpcCgpDQpgYGANCg0KIC0gUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYw0KIC0gIMSQ4buTIHRo4buLIHhvYXkgbmdhbmcgY2hvIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHThu6tuZyBsb+G6oWkgdMSDbmcgZOG6p24gdOG7qyBtw6B1IEogLT4gSSAtPiBIIC0+IEc7IHNhdSDEkcOzIGdp4bqjbSB4deG7kW5nIEYgcuG7k2kgdMSDbmcgbMOqbiBFIHLhu5NpIGdp4bqjbSB24buBIEQNCiANCiANCiPEkOG7kyB0aOG7iyBz4buRIDYgDQpgYGB7cn0NCiAgICBkcSA8LSBkaWFtb25kcw0KZHEgJT4lIGdncGxvdChhZXMoeCA9IGNsYXJpdHkpKSArDQogICAgZ2VvbV9iYXIoKSArDQogICAgbGFicyh4ID0gJ8SQ4buZIHRpbmgga2hp4bq/dCcsIHkgPSAnU+G7kSBsxrDhu6NuZycpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCiANCiAtIFBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIMSR4buZIHRpbmgga2hp4bq/dA0KIC0gIMSQ4buTIHRo4buLIHhvYXkgbmdhbmcgY2hvIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHThu6tuZyBsb+G6oWkgdMSDbmcgZOG6p24gdOG7qyBJRiAtPiBWVlMxIC0+IFZWUzIgLT4gVlMxIC0+IFZTMiAtPiBTSTE7IHNhdSDEkcOzIGdp4bqjbSBk4bqnbiB04burIFNJMSAtPiBTSTIgLT4gSTENCiANCiPEkOG7kyB0aOG7iyBz4buRIDcgDQpgYGB7cn0NCiAgICBkcSAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3NreWJsdWUnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogICAgDQogICAgDQogICAgLSBUYSBQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyB04burbmcgbG/huqFpIHbDoCB0w61uaCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWkuIHggbMOgIGxv4bqhaSBj4bunYSBraW0gY8awxqFuZywgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpLg0KICAgIC0gQ8OhYyBz4buRIGxp4buHdSBjw7MgbcOgdSDEkeG7jywgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIOG7nyB24buLIHRyw60gZOG7jWMgY8OhY2ggY+G7mXQgMiDEkcahbiB24buLLiBNw6B1IGPhu6dhIGPDoWMgY+G7mXQgbMOgIG3DoHUgeGFuaCBkYSB0cuG7nWkuDQogICAgLSBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSDEkcaw4bujYyBuaGnhu4F1IG5o4bqldCBsw6AgbG/huqFpIElkZWFsIHbhu5tpIDIxNTUxIHZpw6puLCB0aeG6v3AgxJHhur9uIGzDoCBQcmVtaXVtIHbhu5tpIDEzNzkxIHZpw6puDQogICAgLSBWZXJ5IEdvb2QgduG7m2kgMTIwODIgdmnDqm4sIEdvb2QgduG7m2kgNDkwNiB2acOqbixGYWlyIHbhu5tpIDE2MTAgdmnDqm4NCiAgICANCiAgDQojxJDhu5MgdGjhu4sgc+G7kSA4ICANCmBgYHtyfQ0KIGRxICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjb2xvcixuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3R1cnF1b2lzZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgbGFicyh4ID0gJ03DoHUgc+G6r2MnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogIA0KICANCiAgLSBUYSBQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jIHbDoCB0w61uaCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBtw6B1IHPhuq9jLiANCiAgLSB4IGzDoCBtw6B1IHPhuq9jIGPhu6dhIGtpbSBjxrDGoW5nLCB5IGzDoCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWkgbcOgdSBz4bqvYy4gDQogIC0gQ8OhYyBz4buRIGxp4buHdSBjw7MgbcOgdSDEkeG7jywgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIOG7nyB24buLIHRyw60gZOG7jWMgY8OhY2ggY+G7mXQgMiDEkcahbiB24buLLiBNw6B1IGPhu6dhIGPDoWMgY+G7mXQgbMOgIHhhbmggbmfhu41jLg0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgdGjhuqV5IMSRxrDhu6NjIG5oaeG7gXUgbmjhuqV0IGzDoCBtw6B1IEcgduG7m2kgMTEyOTIgdmnDqm4sIHRp4bq/cCDEkeG6v24gbMOgIEUgduG7m2kgOTc5NyB2acOqbg0KICAtIEYgduG7m2kgOTU0MiB2acOqbiwgSCB24bubaSA4MzA0IHZpw6puLEQgduG7m2kgNjc3NSB2acOqbg0KICAtIEkgduG7m2kgNTQyMiB2acOqbiB2w6Agw610IG5o4bqldCBsw6AgbcOgdSBKIHbhu5tpIDI4MDggdmnDqm4NCiAgDQogIA0KI8SQ4buTIHRo4buLIHPhu5EgOSAgDQpgYGB7cn0NCmRxICU+JSBncm91cF9ieShjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGNsYXJpdHksbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdncmVlbicpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgbGFicyh4ID0gJ8SQ4buZIHRpbmgga2hp4bq/dCcsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCiAgDQogIA0KICAtIFRhIFBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIMSR4buZIHRpbmgga2hp4bq/dCB2w6AgdMOtbmggc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpLiANCiAgLSB4IGzDoCDEkeG7mSB0aW5oIGtoaeG6v3QgY+G7p2Ega2ltIGPGsMahbmcsIHkgbMOgIHPhu5EgbMaw4bujbmcgY+G7p2EgdOG7q25nIGxv4bqhaS4gDQogIC0gQ8OhYyBz4buRIGxp4buHdSBjw7MgbcOgdSDEkeG7jywgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIOG7nyB24buLIHRyw60gZOG7jWMgY8OhY2ggY+G7mXQgMiDEkcahbiB24buLLiBNw6B1IGPhu6dhIGPDoWMgY+G7mXQgbMOgIHhhbmggbMOhIGPDonkuDQogIC0gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgxJHGsOG7o2Mgbmhp4buBdSBuaOG6pXQgbMOgIGxv4bqhaSBTSTEgduG7m2kgMTMwNjUgdmnDqm4sIHRp4bq/cCDEkeG6v24gbMOgIFZTMiB24bubaSAxMjI1OCB2acOqbg0KICAtIFNJMiB24bubaSA5MTk0IHZpw6puLCBWUzEgduG7m2kgODE3MSB2acOqbixWVlMyIHbhu5tpIDUwNjYgdmnDqm4NCiAgLSBWVlMxIHbhu5tpIDM2NTUgdmnDqm4sIElGIHbhu5tpIDE3OTAgdmnDqm4gdsOgIMOtdCBuaOG6pXQgbMOgIEkxICB24bubaSA3NDEgdmnDqm4NCiAgDQoNCiPEkOG7kyB0aOG7iyBz4buRIDEwDQpgYGB7cn0NCiAgICBkcSAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J2dyZWVuJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKGRxJGNhcmF0KSkpLHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogIA0KICAgIA0KICAgIA0KICAgIC0gVGEgUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gdOG7q25nIGxv4bqhaSB2w6AgdMOtbmggcGjhuqduIHRyxINtIHPhu5EgbMaw4bujbmcgY+G7p2EgdOG7q25nIGxv4bqhaS4geCBsw6AgbG/huqFpIGPhu6dhIGtpbSBjxrDGoW5nLCB5IGzDoCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWkuDQogICAgLSBDw6FjIHPhu5EgbGnhu4d1IGPDsyBtw6B1IMSR4buPLCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCAyIMSRxqFuIHbhu4suIE3DoHUgY+G7p2EgY8OhYyBj4buZdCBsw6AgbcOgdSB4YW5oIGzDoSBjw6J5Lg0KICAgIC0gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgxJHGsOG7o2Mgbmhp4buBdSBuaOG6pXQgbMOgIGxv4bqhaSBJZGVhbCB24bubaSA0MC4wJSwgdGnhur9wIMSR4bq/biBsw6AgUHJlbWl1bSB24bubaSAyNS42JQ0KICAgIC0gVmVyeSBHb29kIHbhu5tpIDIyLjQlLCBHb29kIHbhu5tpIDkuMSUgLEZhaXIgduG7m2kgMy4wJQ0KICAgIA0KI8SQ4buTIHRo4buLIHPhu5EgMTEgICAgDQpgYGB7cn0NCiAgICBkcSAlPiUgZ3JvdXBfYnkoY3V0LGNvbG9yKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBuKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmNvbG9yKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCiAgDQogIA0KICAtIFRhIHBow6JuIG5ow7NtICBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdCB2w6AgbcOgdSBz4bqvYyBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nLiANCiAgLSBUYSBn4bqvbiB4IGzDoCBsb+G6oWksIHkgbGEgc+G7kSBsxrDhu6NuZyANCiAgLSBDaGlhIHRow6BuaCA3IGJp4buDdSDEkeG7kyB0aGVvIDcgbG/huqFpIG3DoHUgc+G6r2MgxJHhu4Mgc28gc8OhbmguIA0KICAtIFF1YSA3IGJp4buDdSDEkeG7kyB0YSBuaOG6rW4geMOpdCBjw6FjIG3DoHUgc+G6r2MgcGjDom4gYuG7lSBuaGnhu4F1IG5o4bqldCDhu58ga2ltIGPGsMahbmcgY8OzIGtp4buDdSBj4bqvdCBJZGVhbCwgZ2nhuqNtIGThuqduIHF1YSBjw6FjIGtp4buDdSBj4bqvdCBQcmVtaXVtLCBWZXJ5IEdvb2QsIEdvb2QgdsOgIHBow6JuIGLhu5Ugw610IG5o4bqldCDhu58ga2nhu4N1IGPhuq90IEZhaXINCg0KI8SQ4buTIHRo4buLIHPhu5EgMTINCmBgYHtyfQ0KICAgIGRxIDwtIGRpYW1vbmRzDQogIGRxICU+JSBncm91cF9ieShjdXQsY29sb3IpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjdXQseSA9IG4pKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdncmVlbicpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KIA0KIA0KICAtIFRhIHBow6JuIG5ow7NtICBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdCB2w6AgbcOgdSBz4bqvYyBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nLiANCiAgLSBUYSBn4bqvbiB4IGzDoCBsb+G6oWksIHkgbGEgc+G7kSBsxrDhu6NuZw0KICAtIEPDoWMgc+G7kSBsaeG7h3UgY8OzIG3DoHUgeGFuaCBsw6EsIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDhu58gduG7iyB0csOtIGThu41jIGPDoWNoIGPhu5l0IDIgxJHGoW4gduG7iy4NCiAgLSBDaGlhIHRow6BuaCA3IGJp4buDdSDEkeG7kyB0aGVvIDcgbG/huqFpIG3DoHUgc+G6r2MgxJHhu4Mgc28gc8OhbmguIA0KICAtIFF1YSA3IGJp4buDdSDEkeG7kyB0YSBuaOG6rW4geMOpdCBjw6FjIG3DoHUgc+G6r2MgcGjDom4gYuG7lSBuaGnhu4F1IG5o4bqldCDhu58ga2ltIGPGsMahbmcgY8OzIGtp4buDdSBj4bqvdCBJZGVhbCwgZ2nhuqNtIGThuqduIHF1YSBjw6FjIGtp4buDdSBj4bqvdCBQcmVtaXVtLCBWZXJ5IEdvb2QsIEdvb2QgdsOgIHBow6JuIGLhu5Ugw610IG5o4bqldCDhu58ga2nhu4N1IGPhuq90IEZhaXINCiAgDQojxJDhu5MgdGjhu4sgc+G7kSAxMyAgDQpgYGB7cn0NCmRxIDwtIGRpYW1vbmRzDQpkcSAlPiUgZ3JvdXBfYnkoY3V0LGNvbG9yKSAlPiUgc3VtbWFyaXNlKG0gPSBtZWFuKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gbSkpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgICBmYWNldF93cmFwKH5jb2xvcikgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtKSkpICsNCiAgICBsYWJzKHggPSAnY3V0JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KICANCiAgDQogIC0gVGEgcGjDom4gbmjDs20gIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90IHbDoCBtw6B1IHPhuq9jIHNhdSDEkcOzIHTDrW5oIHRydW5nIGLDrG5oIHbhu4EgZ2nDoSBj4bunYSB04burbmcgbG/huqFpLiANCiAgLSBUYSBn4bqvbiB4IGzDoCBsb+G6oWksIHkgbGEgc+G7kSBsxrDhu6NuZw0KICAtIENoaWEgdGjDoG5oIDcgYmnhu4N1IMSR4buTIHRoZW8gNyBsb+G6oWkgbcOgdSBz4bqvYyDEkeG7gyBzbyBzw6FuaC4gDQogIC0gUXVhIDcgYmnhu4N1IMSR4buTIHRhIG5o4bqtbiB4w6l0IGdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgbG/huqFpICdQcmVtaXVtJyBsw6AgY2FvIG5o4bqldCDhu50gaOG6p3UgaOG6v3QgY8OhYyBtw6B1IHRy4burIG3DoHUgRyB2w6AgbcOgdSBIDQogIC0gR8OtYSB0cnVuZyBiw6xuaCBj4bunYSBsb+G6oWkgJ0lkZWFsJyBsw6AgdGjhuqVwIG5o4bqldCDhu58gY8OhYyBtw6B1IHRy4burIG3DoHUgSg0KDQogIA0KI8SQ4buTIHRo4buLIHPhu5EgMTQNCmBgYHtyfQ0KZHEgPC0gZGlhbW9uZHMNCmRxIDwtIGRxICU+JSBncm91cF9ieShjdXQsIGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0LCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0UnKSwgZmlsbCA9ICdwdXJwbGUnKSArDQogIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKGNvbG9yID09ICdIJyksIGZpbGwgPSAndHVycXVvaXNlJykNCmBgYA0KICANCiAgDQogIC0gVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90IHbDoCBtw6B1IHPhuq9jIHNhdSDEkcOzIHTDrW5oIHPhu5EgbMaw4bujbmcgLiANCiAgLSDhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6Aga2nhu4N1IGPhuq90LCB5IGzDoCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWk7IA0KICAtIFRhIHPhur0gbOG7jWMgY8OhYyBsb+G6oWkga2ltIGPGsMahbmcgY8OzIG3DoHUgRSxj4buZdCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgdMOtbSB2w6AgbOG7jWMgY8OhYyBsb+G6oWkga2ltIGPGsMahbmcgY8OzIG3DoHUgSCwgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHhhbmggbmfhu41jLiANCiAgLSBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIMSRw6MgbOG7jWMgxJHGsOG7o2Mgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBtw6B1IEggcGjDom4gYuG7lSDDrXQgbmjhuqV0IOG7nyBraeG7g3UgY+G6r3QgRmFpciB2w6AgdMSDbmcgZOG6p24gbMOqbiB04burIEdvb2QsIFZlcnkgR29vZCwgUHJlbWl1bSwgdsOgIG5oaeG7gXUgbmjhuqV0IGzDoCBJZGVhbC4gVsOgIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY8OzIG3DoHUgRSBwaMOibiBi4buVIOG7nyAzIGxv4bqhaSBuaGnhu4F1IG5o4bqldCBsw6AgbG/huqFpICcgSWRlYWwnIHNhdSDEkcOzIGzDoCAnVmVyeSBHb29kJyB2w6Agw610IG5o4bqldCBsw6AgJ0dvb2QnDQogIA0KI8SQ4buTIHRo4buLIHPhu5EgMTUNCmBgYHtyfQ0KZHEgPC0gZGlhbW9uZHMNCmRxIDwtIGRxICU+JSBncm91cF9ieShjdXQsIGNsYXJpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCmRxICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQsIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdWUzEnKSwgZmlsbCA9ICdza3libHVlJykgKw0KICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdJRicpLCBmaWxsID0gJ3BpbmsnKQ0KYGBgDQoNCg0KICANCiAgLSBUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QgdsOgIMSR4buZIHRpbmgga2hp4bq/dCBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nIC4gDQogIC0g4bueIGJp4buDdSDEkeG7kyB0csOqbiB0aMOsIHRhIGfhuq9uIHggbMOgIGtp4buDdSBj4bqvdCwgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpOyANCiAgLSBUYSBz4bq9IGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0aW5oIGtoaeG6v3QgbMOgIFZTMSxj4buZdCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgeGFuaCBkYSB0cuG7nWkgdsOgIGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0aW5oIGtoaeG6v3QgSUYsIGJp4buDdSDEkeG7kyBjw7MgbcOgdSBo4buTbmcuIA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgxJHDoyBs4buNYyDEkcaw4bujYyBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIMSR4buZIHRpbmgga2hp4bq/dCBWUzEgcGjDom4gYuG7lSDDrXQgbmjhuqV0IOG7nyBraeG7g3UgY+G6r3QgRmFpciB2w6AgdMSDbmcgZOG6p24gbMOqbiB04burIEdvb2QsIFZlcnkgR29vZCwgUHJlbWl1bSwgdsOgIG5oaeG7gXUgbmjhuqV0IGzDoCBJZGVhbC4gVsOgIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY8OzIMSR4buZIHRpbmgga2hp4bq/dCBJRiBwaMOibiBi4buVIG5oaeG7gXUgbmjhuqV0IGzDoCBsb+G6oWkgJyBJZGVhbCcgc2F1IMSRw7MgbMOgICdWZXJ5IEdvb2QnLCB0aeG6v3AgxJHhur9uIGzDoCAnIFByZW1pdW0nICwgc2F1IMSRw7MgbMOgICcgR29vZCcgdsOgIMOtdCBuaOG6pXQgbMOgICdGYWlyJw0KICANCiPEkOG7kyB0aOG7iyBz4buRIDE2DQpgYGB7cn0NCmRxIDwtIGRpYW1vbmRzIA0KZHEgPC0gZHEgJT4lIG11dGF0ZShjYXJhdEMgPSBjdXQoY2FyYXQsNSwgbGFiZWwgPSBjKCdy4bqldCBuaOG7jycsICduaOG7jycsJ3bhu6thJywnbOG7m24nLCdy4bqldCBs4bubbicpKSkNCmRxICU+JSBnZ3Bsb3QoYWVzKHggPSBjYXJhdEMpKSArDQogIGdlb21fYmFyKGZpbGwgPSAnc2t5Ymx1ZScpDQpgYGANCiAgDQogIA0KICAtIFRhIHRow6ptIDEgY+G7mXQgZOG7ryBsacOqdSBjYXJhdEMgdsOgbyBi4buZIGThu68gbGnhu4d1IMSR4buDIMSRw6FuaCBnacOhIHRy4buNbmcgbMaw4bujbmcgY+G7p2EgY8OhYyB2acOqbiBraW0gY8awxqFuZyB0aGVvIG3hu6ljIMSR4buZIOKAmHLhuqV0IG5o4buP4oCZIOKAmG5o4buP4oCZLCDigJh24burYeKAmSB2w6Ag4oCYbOG7m27igJkuIA0KICAtIEPDoWMgY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHhhbmggZGEgdHLhu51pLiANCiAgLSBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyB0cuG7jW5nIGzGsOG7o25nIOKAmHLhuqV0IG5o4buP4oCZIGzDoCBs4bubbiBuaOG6pXQgdsOgIGdp4bqjbSBk4bqnbiB04burIOKAmG5o4buP4oCZLCDigJh24burYeKAmSwgJ2zhu5tuJyB2w6AgdGjhuqVwIG5o4bqldCBsw6AgbG/huqFpIOKAmHLhuqV0IGzhu5tu4oCZDQogIA0KI8SQ4buTIHRo4buLIHPhu5EgMTcNCmBgYHtyfQ0KZHEgPC0gZGlhbW9uZHMgDQpkcSA8LSBkcSAlPiUgbXV0YXRlKHByaWNlID0gY3V0KHByaWNlLDMsIGxhYmVsID0gYygndGjhuqVwJywnduG7q2EnLCdjYW8nKSkpDQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UpKSArDQogIGdlb21fYmFyKGZpbGwgPSAncGluaycpDQpgYGANCiANCiAgDQogIC0gVGEgdGjDqm0gMSBj4buZdCBk4buvIGxpw6p1IHByaWNlIHbDoG8gYuG7mSBk4buvIGxp4buHdSDEkeG7gyDEkcOhbmggZ2nDoSB24buBIGdpw6EgY+G6oyBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIHRoZW8gbeG7qWMgxJHhu5kgJ3Ro4bqlcCcsJ3bhu6thJywnY2FvJy4NCiAgLSBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyBjw7MgbcOgdSBo4buTbmcgLiANCiAgLSBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyBnacOhIOKAmHRo4bqlcOKAmSBsw6AgbOG7m24gbmjhuqV0IHRyw6puIDQwMDAwIHZpw6puIHbDoCBnaeG6o20gZOG6p24geHXhu5FuZyDigJh24burYeKAmSB2w6AgdGjhuqVwIG5o4bqldCBsw6AgbG/huqFpIOKAmGNhb+KAmQ0KICANCiPEkOG7kyB0aOG7iyBz4buRIDE4DQpgYGB7cn0NCmRxIDwtIGRpYW1vbmRzIA0KZHEgPC0gZHEgJT4lIG11dGF0ZShkZXB0aCA9IGN1dChkZXB0aCw1LCBsYWJlbCA9IGMoJ3LhuqV0IG5o4buPJywgJ25o4buPJywnduG7q2EnLCds4bubbicsJ3LhuqV0IGzhu5tuJykpKQ0KZHEgJT4lIGdncGxvdChhZXMoeCA9IGRlcHRoKSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ2JsdWUnKQ0KYGBgDQogDQogDQogLSBUYSB0aMOqbSAxIGPhu5l0IGThu68gbGnDqnUgZGVwdGggdsOgbyBi4buZIGThu68gbGnhu4d1IMSR4buDIMSRw6FuaCBnacOhIHbhu4Ega2hv4bqjbmcgY8OhY2ggdOG7qyBt4bq3dCDEkeG6v24gxJHDoXkgY+G7p2EgY8OhYyB2acOqbiBraW0gY8awxqFuZyB0aGVvIG3hu6ljIMSR4buZICdy4bqldCBuaOG7jycsJ25o4buPJywnduG7q2EnLCds4bubbicsJ3LhuqV0IGzhu5tuJy4NCiAgLSBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyBjw7MgbcOgdSB4YW5oIGTGsMahbmcgLiANCiAgLSBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyBraG/huqNuZyBjw6FjaCDigJh24burYeKAmSBsw6AgbOG7m24gbmjhuqV0IHRyw6puIDUwMDAwIHZpw6puIHbDoCBnaeG6o20gZOG6p24geHXhu5FuZyDigJhs4bubbuKAmSwgJ25o4buPJyB2w6AgdGjhuqVwIG5o4bqldCBsw6AgbG/huqFpIOKAmHLhuqV0IG5o4buP4oCZIHbDoCAnIHLhuqV0IGzhu5tuJw0KICANCiAgDQoNCiPEkOG7kyBUaOG7iyBT4buRIDE5DQpgYGB7cn0NCiAgZHEgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UobT0gbWVhbihjYXJhdCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjbGFyaXR5LHkgPSBtKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sNSkpLCB2anVzdCA9IDIsIGNvbG9yID0gJ2dyZWVuJykgKw0KICBsYWJzKHggPSAnxJHhu5kgdGluaCBraGnhur90JywgeSA9ICd0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oJykNCmBgYA0KIA0KIA0KICAtIFRhIHBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIMSR4buZIHRpbmgga2hp4bq/dCB2w6AgdMOtbmggdHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCBj4bunYSBjaMO6bmcgdGhlbyDEkcahbiB24buLIGNhcmF0LiANCiAgLSDhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6AgxJHhu5kgdGluaCBraGnhur90LCB5IGzDoCBraOG7kWkgbMaw4bujbmcgdHJ1bmcgYsOsbmggY+G7p2EgdOG7q25nIGxv4bqhaQ0KICAtIEPDoWMgc+G7kSBsaeG7h3Ugc+G6vSBjw7MgbcOgdSB4YW5oIGzDoSBjw6J5LCDEkcaw4bujYyBsw6BtIHRyw7JuIDUgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gdsOgIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDhu58gduG7iyB0csOtIGThu41jIGPDoWNoIGPhu5l0IHbhu5tpIMSRxqFuIHbhu4sgbMOgIDIuIFbDoCB0YSB0aOG6pXkgxJHGsOG7o2Mga2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCBjYW8gbmjhuqV0IGzDoCBJMSwgdGjhuqVwIGjGoW4gxJHDsyBsw6AgU0kyIHbDoCBnaeG6o20gZOG6p24gdOG7qyBTSTEsIFZTMiwgVlMxLCBXUzIsIFdTMSwgdsOgIHRo4bqlcCBuaOG6pXQgbMOgIElGLg0KICANCiAgDQojxJDhu5MgVGjhu4sgU+G7kSAyMA0KYGBge3J9IA0KICBkcSAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjbGFyaXR5LG4pKSArDQogIGdlb21fY29sKGZpbGw9J2dyZWVuJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGVyY2VudChuL2xlbmd0aChkcSRwcmljZSkpKSx2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KICANCiAgLSBUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyDEkeG7mSB0aW5oIGtoaeG6v3QgdsOgIHTDrW5oIHPhu5EgbMaw4bujbmcgY+G7p2EgY8OhYyBtw6B1LiANCiAgLSBUYSBn4bqvbiB4IGzDoCDigJhMb+G6oWnigJksIHkgbMOgIOKAmFPhu5EgTMaw4bujbmfigJkuIA0KICAtIEPDoWMgY+G7mXQgYmnhu4N1IMSR4buTIMSRxrDhu6NjIHTDtCBtw6B1IHhhbmggbMOhIGPDonksIGPDoWMgc+G7kSBsaeG7h3UgbMOgIHThu7cgbOG7hyBnacOhIHRp4buBbiBj4bunYSBt4buXaSBsb+G6oWkga2ltIGPGsMahbmcsIGPDoWMgc+G7kSBsaeG7h3UgbsOgeSBjw7MgbcOgdSDEkeG7jyB2w6AgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIHbhu4sgdHLDrSBk4buNYyBjw6FjIGPhu5l0IGThu68gbGnhu4d1IHbhu5tpIMSRxqFuIHbhu4sgbMOgIDIuIA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgdGjhuqV5IGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgU0kxIGNoaeG6v20gdOG7tyBs4buHIGdpw6EgY2FvIG5o4bqldCBsw6AgMjQsMiUsIGdp4bqjbSBk4bqnbiB04burIFZTMiwgU0kyLCBWUzEsIFZWUzIsIFZWUzEsIElGLCBJMSBsw6AgMSw0JQ0KICANCiPEkOG7kyB0aOG7iyBz4buRIDIxDQpgYGB7cn0NCmRxIDwtIGRpYW1vbmRzDQpkcSA8LSBkcSAlPiUgZ3JvdXBfYnkoY3V0LCBjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KZHEgJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKGNvbG9yID09ICdHJyksIGZpbGwgPSAncmVkJykgKw0KICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjb2xvciA9PSAnRCcpLCBmaWxsID0gJ3R1cnF1b2lzZScpDQpgYGANCiAgDQogIA0KICAtIFRhIHBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdCB2w6AgbcOgdSBz4bqvYyBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nIC4gDQogIC0g4bueIGJp4buDdSDEkeG7kyB0csOqbiB0aMOsIHRhIGfhuq9uIHggbMOgIGtp4buDdSBj4bqvdCwgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpOyANCiAgLSBUYSBz4bq9IGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEcsY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IMSR4buPIHbDoCBs4buNYyBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyBjw7MgbcOgdSBELCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgeGFuaCBuZ+G7jWMuIA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgxJHDoyBs4buNYyDEkcaw4bujYyBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIG3DoHUgRyBwaMOibiBi4buVIMOtdCBuaOG6pXQg4bufIGtp4buDdSBj4bqvdCBGYWlyIHbDoCB0xINuZyBk4bqnbiBsw6puIHThu6sgR29vZCwgVmVyeSBHb29kLCBQcmVtaXVtLCB2w6Agbmhp4buBdSBuaOG6pXQgbMOgIElkZWFsLiBWw6Agc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgbcOgdSBEIHBow6JuIGLhu5Ugbmhp4buBdSBuaOG6pXQgbMOgIGxv4bqhaSAnIElkZWFsJyBzYXUgxJHDsyBnaeG6o20gZOG6p24gbMOgICdQcmVtaXVtJzsgJ1ZlcnkgR29vZCc7ICdHb29kJzsgdsOgIMOtdCBuaOG6pXQgbMOgICdGYWlyJw0KICANCiPEkOG7kyB0aOG7iyBz4buRIDIyDQpgYGB7cn0NCmRxIDwtIGRpYW1vbmRzDQpkcSAlPiUgZ3JvdXBfYnkoY2FyYXQpICU+JSBmaWx0ZXIoY2FyYXQgPT0gMC41IHwgY2FyYXQgPT0gMS4wMCB8IGNhcmF0ID09IDEuNSB8IGNhcmF0ID09IDIuMDUpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY2FyYXQsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdza3libHVlJykgKw0KICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgeGxhYignQ2FyYXQnKSArDQogICAgeWxhYignU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KDQoNCiAgLSBUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IOG7nyBjw6FjIG3hu5FjIDAuNSwgMS4wLCAxLjUsIDIuMCB2w6AgdMOtbmggc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbeG7kWMga2jhu5FpIGzGsMahbmcuIA0KICAtIFRhIGfhuq9uIHggbMOgIGNhcmF0IHbDoCB5IGzDoCBz4buRIGzGsOG7o25nIHThu6tuZyBt4buRYyBjYXJhdC4gDQogIC0gQ8OhYyBj4buZdCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgeGFuaCBkYSB0cuG7nWksIGPDoWMgc+G7kSBsaeG7h3UgY8OzIG3DoHUgxJHhu48sIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDhu58gduG7iyB0csOtIGThu41jIGPDoWNoIGPhu5l0IDIgxJHGoW4gduG7iyAuIA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgdGjhuqV5IMSRxrDhu6NjIHPhu5Ega2ltIGPGsMahbmcgY8OzIHRy4buNbmcgbMaw4bujbmcgMS4wIGNhcmF0IGzDoCBuaGnhu4F1IG5o4bqldCB24bubaSAxNTU4IHZpw6puIHbDoCB0aOG6pXAgbmjhuqV0IGzDoCAyLjAgduG7m2kgNjcgdmnDqm4NCiAgLSBOZ2/DoGkgcmEga2ltIGPGsMahbmcgY8OzIHRy4buNbmcgbMaw4bujbmcgMC41IGPDsyBz4buRIGzGsOG7o25nIGzDoCAxMjU4IHZpw6puLCAxLDAgY8OzIHPhu5EgbMaw4bujbmcgbMOgIDE1NTggdmnDqm4NCg0KI8SQ4buTIHRo4buLIHPhu5EgMjMNCmBgYHtyfQ0KZHEgPC0gZGlhbW9uZHMNCmRxIDwtIGRxICU+JSBncm91cF9ieShjdXQsIGNsYXJpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCmRxICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQsIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdTSTEnKSwgZmlsbCA9ICdibHVlJykgKw0KICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdTSTInKSwgZmlsbCA9ICd0dXJxdW9pc2UnKSArDQogIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKGNsYXJpdHkgPT0gJ0lGJyksIGZpbGwgPSAncGluaycpDQpgYGANCiAgDQogIA0KICANCiAgLSBUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QgdsOgIMSR4buZIHRpbmgga2hp4bq/dCBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nIC4gDQogIC0g4bueIGJp4buDdSDEkeG7kyB0csOqbiB0aMOsIHRhIGfhuq9uIHggbMOgIGtp4buDdSBj4bqvdCwgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpOyANCiAgLSBUYSBz4bq9IGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGxv4bqhaSBTSTEsY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHhhbmggdsOgIGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGxv4bqhaSBTSTIsIGJp4buDdSDEkeG7kyBjw7MgbcOgdSB4YW5oIG5n4buNYywgbOG7jWMgY8OhYyB2acOqbiBraW0gY8awxqFuZyBsb+G6oWkgSUYsIGJp4buDdSDEkeG7kyBjw7MgbcOgdSBo4buTbmcgDQogIC0gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSDEkcOjIGzhu41jIMSRxrDhu6NjIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgbG/huqFpIFNJMSBwaMOibiBi4buVIG5oaeG7gXUgbmjhuqV0IOG7nyBraeG7g3UgY+G6r3QgJ0lkZWFsJyBzYXUgxJHDsyB04bubaSAnVmVyeSBHb29kJyB2w6AgJ1ByZW1pdW0nIHbhu5tpICdHb29kJyBn4bqnbiBuaMawIGLhurFuZyBuaGF1IHbDoCBraMO0bmcgY8OzIHZpw6puIG7DoG8gbG/huqFpICdGYWlyJw0KICAtIFPhu5EgbMaw4bujbmcgdmnDqm4ga2ltIGPGsMahbmcgbG/huqFpIFNJMiBjaGnhur9tIHBo4bqnbiBs4bubbiB0cm9uZyAzIGxv4bqhaSBTSTEgU0kyIFbDgCBJRiwgdsOgIFNJMiBjaGnhur9tIHPhu5EgbMaw4bujbmcgbmhp4buBdSBuaOG6pXQg4bufIGxv4bqhaSAnUHJlbWl1bScgdsOgIMOtdCBuaOG6pXQg4bufICdGYWlyJw0KICAtIFPhu5EgbMaw4bujbmcgdmnDqm4ga2ltIGPGsMahbmcgbG/huqFpIElGIHTEg25nIGThuqduIHThu6sgR29vZCAtPiBWZXJ5IEdvb2QgLT4gUHJlbWl1bSAtPiBJZGVhbA0KICANCiPEkOG7kyB0aOG7iyBz4buRIDIzDQpgYGB7cn0NCmRxIDwtIGRpYW1vbmRzDQpkcSA8LSBkcSAlPiUgZ3JvdXBfYnkoY3V0LCBjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0LCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnU0kxJyksIGZpbGwgPSAnYmx1ZScpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnVlMyJyksIGZpbGwgPSAndHVycXVvaXNlJykgKw0KICAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnU0kyJyksIGZpbGwgPSAncmVkJykgKw0KICAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnVlZTMScpLCBmaWxsID0gJ2JsYWNrJykNCiAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnVlZTMicpLCBmaWxsID0gJ3BpbmsnKQ0KYGBgDQogIA0KICANCiAgLSBUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QgdsOgIMSR4buZIHRpbmgga2hp4bq/dCBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nIC4gDQogIC0g4bueIGJp4buDdSDEkeG7kyB0csOqbiB0aMOsIHRhIGfhuq9uIHggbMOgIGtp4buDdSBj4bqvdCwgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpOyANCiAgLSBUYSBz4bq9IGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGxv4bqhaSBTSTEsY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHhhbmggdsOgIGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGxv4bqhaSBWUzIsIGJp4buDdSDEkeG7kyBjw7MgbcOgdSB4YW5oIG5n4buNYywgbOG7jWMgY8OhYyB2acOqbiBraW0gY8awxqFuZyBsb+G6oWkgVlZTMSwgYmnhu4N1IMSR4buTIGPDsyBtw6B1IMSRZW4sIGPDoWMga2ltIGPGsMahbmcgbG/huqFpIFZWUzIsIGJp4buDdSDEkeG7kyBj4buZdCBjw7MgbcOgdSBo4buTbmcNCiAgLSBRdWEgYmnhu4N1IMSR4buTIHRhIHRo4bqleSDhu58gbG/huqFpIEZhaXIgU0kyIGNoaeG6v20gZGnhu4duIHTDrWNoIGzhu5tuIG5o4bqldA0KICAtIOG7niBsb+G6oWkgR29vZCBTSTIgY2hp4bq/bSBkaeG7h24gdMOtY2ggbOG7m24gbmjhuqV0IHNhdSDEkcOzIGzDoCBTSTEgdsOgIFZWUzENCiAgLSDhu54gbG/huqFpIFZlcnkgR29vZCBTSTIgY2hp4bq/bSBkaeG7h24gdMOtY2ggbOG7m24gbmjhuqV0IHNhdSDEkcOzIGzDoCBWVlMxLCBTSTEgdsOgIFZTMg0KICAtIOG7niBsb+G6oWkgUHJlbWl1bSBWUzIgY2hp4bq/bSBkaeG7h24gdMOtY2ggbOG7m24gbmjhuqV0IHNhdSDEkcOzIGzDoCBWVlMxIHbDoCBzYXUgxJHDsyBsw6AgU0kyDQogIC0g4bueIGxv4bqhaSBJZGVhbCBWUzIgY2hp4bq/bSBkaeG7h24gdMOtY2ggbmhp4buBdSBuaOG6pXQsIHNhdSDEkcOzIGzDoCBWVlMxIHbDoCBTSTINCiAgDQojxJDhu5MgdGjhu4sgc+G7kSAyNA0KYGBge3J9DQpkcSA8LSBkaWFtb25kcw0KZHEgPC0gZHEgJT4lIGdyb3VwX2J5KGN1dCwgY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCmRxICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQsIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjb2xvciA9PSAnRCcpLCBmaWxsID0gJ3JlZCcpICsNCiAgICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjb2xvciA9PSAnSicpLCBmaWxsID0gJ2JsdWUnKSArDQogICAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0cnKSwgZmlsbCA9ICdwaW5rJykgKw0KICAgIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKGNvbG9yID09ICdIJyksIGZpbGwgPSAnYnJvd24nKSArDQogICAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0UnKSwgZmlsbCA9ICdwdXJwbGUnKSArDQogICAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0YnKSwgZmlsbCA9ICd5ZWxsb3cnKSArDQogIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKGNvbG9yID09ICdJJyksIGZpbGwgPSAndHVycXVvaXNlJykNCmBgYCAgDQoNCiAgDQogIC0gVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90IHbDoCBtw6B1IHPhuq9jIHNhdSDEkcOzIHTDrW5oIHPhu5EgbMaw4bujbmcgLiANCiAgLSDhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6Aga2nhu4N1IGPhuq90LCB5IGzDoCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWk7IA0KICAtIFRhIHPhur0gbOG7jWMgY8OhYyBsb+G6oWkga2ltIGPGsMahbmcgbcOgdSBELGPhu5l0IGJp4buDdSDEkeG7kyBjw7MgbcOgdSDEkeG7jyANCiAgLSBs4buNYyBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyBtw6B1IEosIGJp4buDdSDEkeG7kyBjw7MgbcOgdSB4YW5oDQogIC0gbOG7jWMgY8OhYyB2acOqbiBraW0gY8awxqFuZyBtw6B1IEcsIGJp4buDdSDEkeG7kyBjw7MgbcOgdSBo4buTbmcNCiAgLSBjw6FjIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEgsIGJp4buDdSDEkeG7kyBj4buZdCBjw7MgbcOgdSBuw6J1DQogIC0gbOG7jWMgY8OhYyB2acOqbiBraW0gY8awxqFuZyBtw6B1IEUsIGJp4buDdSDEkeG7kyBjw7MgbcOgdSB0w61tDQogIC0gbOG7jWMgY8OhYyB2acOqbiBraW0gY8awxqFuZyBtw6B1IEYsIGJp4buDdSDEkeG7kyBjw7MgbcOgdSB2w6BuZw0KICAtIGzhu41jIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgbcOgdSBJLCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgeGFuaCBuZ+G7jWMNCiAgLSBRdWEgYmnhu4N1IMSR4buTIHRhIHRo4bqleSDhu58gbG/huqFpIEZhaXIgRiB2w6AgSSBjaGnhur9tIGRp4buHbiB0w61jaCBn4bqnbiBuaMawIGLhurFuZyBuaGF1DQogIC0g4bueIGxv4bqhaSBHb29kIEkgY2hp4bq/bSBkaeG7h24gdMOtY2ggbOG7m24gbmjhuqV0IHNhdSDEkcOzIGzDoCBGIHbDoCBFDQogIC0g4bueIGxv4bqhaSBWZXJ5IEdvb2QgSSBjaGnhur9tIGRp4buHbiB0w61jaCBs4bubbiBuaOG6pXQgc2F1IMSRw7MgbMOgIEYsRQ0KICAtIOG7niBsb+G6oWkgUHJlbWl1bSBJIGNoaeG6v20gZGnhu4duIHTDrWNoIGzhu5tuIG5o4bqldCBzYXUgxJHDsyBsw6AgRiwgRyB2w6Agc2F1IMSRw7MgbMOgIEQNCiAgLSDhu54gbG/huqFpIElkZWFsIEkgY2hp4bq/bSBkaeG7h24gdMOtY2ggbOG7m24gbmjhuqV0IHNhdSDEkcOzIGzDoCBJLHNhdSDEkcOzIGzDoCBGLEcgdsOgIEUNCiAgDQojxJDhu5MgdGjhu4sgc+G7kSAyNQ0KDQpgYGB7cn0NCmRxIDwtIGRpYW1vbmRzDQpkcSA8LSBkcSAlPiUgZ3JvdXBfYnkoY3V0LCBjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KZHEgJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKGNvbG9yID09ICdEJyksIGZpbGwgPSAncmVkJykgKw0KICAgIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKGNvbG9yID09ICdKJyksIGZpbGwgPSAnYmx1ZScpICsNCiAgICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjb2xvciA9PSAnRycpLCBmaWxsID0gJ3BpbmsnKSArDQogICAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0gnKSwgZmlsbCA9ICdicm93bicpICsNCiAgICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjb2xvciA9PSAnRScpLCBmaWxsID0gJ3B1cnBsZScpICsNCiAgICBnZW9tX2NvbChkYXRhID0gZHEgJT4lIGZpbHRlcihjb2xvciA9PSAnRicpLCBmaWxsID0gJ3llbGxvdycpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0knKSwgZmlsbCA9ICd0dXJxdW9pc2UnKSArDQogIGNvb3JkX2ZsaXAoKSANCmBgYCAgDQoNCiAgDQogIC0gxJDhu5MgdGjhu4sgbuG6sW0gbmdhbmcgY+G7p2EgxJHhu5MgdGjhu4sgMjUNCiAgLSBRdWEgxJHhu5MgdGjhu4sgdGEgdGjhuqV5IHPhu5EgbMaw4bujbmcgZ2nhuqNtIGThuqduIHThu6sgbG/huqFpIElkZWFsIC0+IFByZW1pdW0gLT4gVmVyeSBHb29kIC0+IEdvb2QgLT4gRmFpcg0KDQojxJDhu5MgdGjhu4sgc+G7kSAyNg0KDQpgYGB7cn0NCiAgICBkcSAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY29sb3IsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdwaW5rJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKGRxJHByaWNlKSkpLHZqdXN0ID0gMiwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ03DoHUnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogICAgDQogIA0KICAtIFRhIHBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIG3DoHUgc+G6r2MgdsOgIHTDrW5oIHPhu5EgbMaw4bujbmcgZ2nDoSBj4bunYSB04burbmcgbG/huqFpLiANCiAgLSBUYSBn4bqvbiB4IGzDoCDigJhNw6B14oCZLCB5IGzDoCDigJhT4buRIEzGsOG7o25n4oCZLiANCiAgLSBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyDEkcaw4bujYyB0w7QgbcOgdSBo4buTbmcsIGPDoWMgc+G7kSBsaeG7h3UgbMOgIHThu7cgbOG7hyBnacOhIHRp4buBbiBj4bunYSBt4buXaSBsb+G6oWkga2ltIGPGsMahbmcsIGPDoWMgc+G7kSBsaeG7h3UgbsOgeSBjw7MgbcOgdSDEkWVuIHbDoCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggduG7iyB0csOtIGThu41jIGPDoWMgY+G7mXQgZOG7ryBsaeG7h3UgduG7m2kgxJHGoW4gduG7iyBsw6AgMi4gDQogIC0gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkga2ltIGPGsMahbmcgbcOgdSBHIGNoaeG6v20gdOG7tyBs4buHIGNhbyBuaOG6pXQgduG7gSBnacOhIHbhu5tpIDIwLjkzJQ0KICAtIEtpbSBjxrDGoW5nIG3DoHUgSiBjaGnhur9tIHThu7cgbOG7hyB0aOG6pXAgbmjhuqV0IHbhu4EgZ2nDoSB24bubaSA1LjIxJQ0KICAtIEtpbSBjxrDGoW5nIG3DoHUgRyBjYW8gaMahbiB2w6AgZ+G6pXAga2ltIGPGsMahbmcgbcOgdSBJIGzDoCAyLDA4IGzhuqduDQogIC0gS2ltIGPGsMahbmcgbcOgdSBIIGNhbyBoxqFuIHbDoCBn4bqlcCBraW0gY8awxqFuZyBtw6B1IEogbMOgIDIsOTUgbOG6p24NCiAgLSBLaW0gY8awxqFuZyBtw6B1IEkgY2FvIGjGoW4gdsOgIGfhuqVwIGtpbSBjxrDGoW5nIG3DoHUgSiBsw6AgMSw5MyBs4bqnbg0KICANCiPEkOG7kyB0aOG7iyBz4buRIDI3DQoNCmBgYHtyfQ0KICAgIGRxICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjb2xvcixuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3BpbmsnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgoZHEkcHJpY2UpKSksdmp1c3QgPSAyLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnTcOgdScsIHkgPSAnU+G7kSBsxrDhu6NuZycpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCiAgICANCiAgICAtIMSQw6J5IGzDoCDEkeG7kyB0aOG7iyBu4bqxbSBuZ2FuZyBj4bunYSDEkeG7kyB0aOG7iyBz4buRIDI2DQogICAgLSBRdWEgxJHhu5MgdGjhu4sgdGEgdGjhuqV5ICBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHTEg25nIGThuqduIHThu6sgbcOgdSBKIC0+IEkgLT4gSCAtPiBHLCBzYXUgZ2nhuqNtIGThuqduDQogICAgDQojxJDhu5MgdGjhu4sgc+G7kSAyOCANCg0KYGBge3J9DQpkcSA8LSBkaWFtb25kcw0KZHEgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG0gPSBtZWFuKGRlcHRoKSkgJT4lDQogIGdncGxvdChhZXMoY29sb3IsbSkpICsNCiAgZ2VvbV9jb2woZmlsbD0nc2t5Ymx1ZScpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sMikpLHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQogDQogIC0gVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYyB2w6AgdMOtbmggdHJ1bmcgYsOsbmggdOG7tyBs4buHIMSR4buZIHPDonUgY+G7p2EgdOG7q25nIGxv4bqhaS4gDQogIC0gQ8OhYyBj4buZdCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgeGFuaCBkYSB0cuG7nWksIGPDoWMgZOG7ryBsaeG7h3UgY8OzIG3DoHUgxJHhu48sIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gdsOgIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDhu58gduG7iyB0csOtIGThu41jIGPDoWNoIGPhu5l0IDIgxJHGoW4gduG7iy4gDQogIC0gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgY8OhYyBsb+G6oWkgbcOgdSBj4bunYSBraW0gY8awxqFuZyBz4bq9IGPDsyB44bqlcCB44buJIHRydW5nIGLDrG5oIHThu7cgbOG7hyDEkeG7mSBzw6J1IGLhurFuZyBuaGF1LiBUcm9uZyDEkcOzIGNhbyBuaOG6pXQgbMOgIG3DoHUgSiB24bubaSA2MS44OSB2w6AgdGjhuqVwIG5o4bqldCBsw6AgbcOgdSBFIHbhu5tpIDYxLjY2DQogIA0KI8SQ4buTIHRo4buLIHPhu5EgMjkNCg0KYGBge3J9DQpkcSAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShtPSBtZWFuKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG0pKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwzKSksIHZqdXN0ID0gMiwgY29sb3IgPSAnZ3JlZW4nKSArDQogIGxhYnMoeCA9ICfEkeG7mSB0aW5oIGtoaeG6v3QnLCB5ID0gJ3Ry4buNbmcgbMaw4bujbmcgdHJ1bmcgYsOsbmgnKQ0KYGBgDQoNCiAgDQogIC0gVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gxJHhu5kgdGluaCBraGnhur90IHbDoCB0w61uaCB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGPhu6dhIGNow7puZyB0aGVvIMSRxqFuIHbhu4sgY2FyYXQuIA0KICAtIOG7niBiaeG7g3UgxJHhu5MgdHLDqm4gdGjDrCB0YSBn4bqvbiB4IGzDoCDEkeG7mSB0aW5oIGtoaeG6v3QsIHkgbMOgIGto4buRaSBsxrDhu6NuZyB0cnVuZyBiw6xuaCBj4bunYSB04burbmcgbG/huqFpDQogIC0gQ8OhYyBz4buRIGxp4buHdSBz4bq9IGPDsyBtw6B1IHhhbmggbMOhIGPDonksIMSRxrDhu6NjIGzDoG0gdHLDsm4gMyBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiB2w6AgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIOG7nyB24buLIHRyw60gZOG7jWMgY8OhY2ggY+G7mXQgduG7m2kgxJHGoW4gduG7iyBsw6AgMi4NCiAgLSBUYSB0aOG6pXkgxJHGsOG7o2Mga2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCBjYW8gbmjhuqV0IGzDoCBJMSB24bubaSAxLjI4NCwgdGjhuqVwIGjGoW4gxJHDsyBsw6AgU0kyIHbDoCBnaeG6o20gZOG6p24gdOG7qyBTSTEsIFZTMiwgVlMxLCBXUzIsIFdTMSwgdsOgIHRo4bqlcCBuaOG6pXQgbMOgIElGIHbhu5tpIDAuNTA1DQogIA0KICANCiPEkOG7kyB0aOG7iyBz4buRIDMwDQpgYGB7cn0NCmRxICU+JSBncm91cF9ieShjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSx5ID0gbSkpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDMpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICdncmVlbicpICsNCiAgbGFicyh4ID0gJ8SR4buZIHRpbmgga2hp4bq/dCcsIHkgPSAndHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCcpICsNCiAgICBjb29yZF9mbGlwKCkNCmBgYA0KDQogIA0KICAtIMSQ4buTIHRo4buLIG7hurFtIG5nYW5nIGPhu6dhIMSR4buTIHRo4buLIHPhu5EgMzANCiAgLSBRdWEgxJHhu5MgdGjhu4sgdGEgdGjhuqV5IHRy4buNbmcgbMaw4bujbmcgdHJ1bmcgYsOsbmggY+G7p2EgxJHhu5kgdGluaCBraGnhur90IHTEg25nIGThuqduIHThu6sgSUYgLT4gVlZTMSAtPiBWVlMyIC0+IFZTMSAtPlZTMiAtPiBTSTEgLT4gU0kxIC0+IEkx