GIỚI THIỆU TỔNG QUAN VỀ BỘ DỮ LIỆU DIAMONDS

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.0     ✔ readr     2.1.5
## ✔ ggplot2   3.4.4     ✔ 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(ggplot2)
library(scales)
## 
## Attaching package: 'scales'
## 
## The following object is masked from 'package:purrr':
## 
##     discard
## 
## The following object is masked from 'package:readr':
## 
##     col_factor
hieu <- diamonds
hieu
## # A tibble: 53,940 × 10
##    carat cut       color clarity depth table price     x     y     z
##    <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
##  1  0.23 Ideal     E     SI2      61.5    55   326  3.95  3.98  2.43
##  2  0.21 Premium   E     SI1      59.8    61   326  3.89  3.84  2.31
##  3  0.23 Good      E     VS1      56.9    65   327  4.05  4.07  2.31
##  4  0.29 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63
##  5  0.31 Good      J     SI2      63.3    58   335  4.34  4.35  2.75
##  6  0.24 Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48
##  7  0.24 Very Good I     VVS1     62.3    57   336  3.95  3.98  2.47
##  8  0.26 Very Good H     SI1      61.9    55   337  4.07  4.11  2.53
##  9  0.22 Fair      E     VS2      65.1    61   337  3.87  3.78  2.49
## 10  0.23 Very Good H     VS1      59.4    61   338  4     4.05  2.39
## # ℹ 53,930 more rows

Thông tin cơ bản về bộ dữ liệu:

dim(hieu)
## [1] 53940    10
  • Số lượng: 53.940 viên kim cương

  • Biến: 10 đặc tính

  • Price: Giá thành của các viên kim cương (USD)

  • Carat: Trọng lượng của các viên kim cương (carat)

  • Cut: Chất lượng cắt (Khá, Tốt, Rất tốt, Đặc biệt, Lý tưởng)

  • Color: Các Màu của viên Kim cương (J - kém nhất, D - tốt nhất)

  • Clarity: Độ trong của viên kim cương

  • x: Chiều dài (mm)

  • y: Chiều rộng (mm)

  • z: Độ sâu (mm)

  • Depth: Độ sâu vết cắt

  • Table: Chiều rộng đỉnh kim cương so với điểm rộng nhất

1. Biểu đồ 1:

Phân loại kim cương theo kiểu cắt

hieu %>% ggplot(aes(x = cut)) +
    geom_bar() +
    labs(x = 'Loại', y = 'Số lượng') +
    coord_flip() +
    labs(title = 'Số kim cương theo kiểu cắt(biểu đồ ngang)')

* Biểu đồ ngang trên cho ta thấy được kiểu Gía của kim cương theo từng kiểu cắt. Ta thấy số kim cương sẽ tăng dần từ Fair, Good, Very Good, Premium, Ideal.

2. Biểu đồ 2:

Phân loại kim cương theo độ trong suốt và tính giá trung bình của từng loại

hieu %>% group_by(clarity) %>% summarise(m= mean(price)) %>%
  ggplot(aes(x = clarity,y = m)) +
  geom_col(position = 'dodge') +  
  geom_text(aes(label = round(m,1)), vjust = 2, color = 'green') +
  labs(x = 'độ trong suốt', y = 'giá')

  • Ta gắn: x là độ trong suốt, y là giá 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 01 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. Qua biểu đồ trên ta thấy kim cương có độ trong suốt SI2 là có giá trung bình cao nhất, tiếp đến là SI2, thấp hơn nữa lần lượt là VS2, I1, VS1, WS2, IF và thấp nhất là Ws1.

3. Biểu đồ 3:

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

hieu %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(color,n)) +
    geom_col(fill='red') +
    geom_text(aes(label = n),vjust = 2, color = 'black') +
    xlab('Color') +
    ylab('Số lượng') +
    labs(title ='Số lượng kim cương theo 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 đen, đượ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 đỏ . 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.

4.Biểu đồ 4:

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

hieu %>% 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='purple') +
     geom_text(aes(label = n),vjust = 2, color = 'white') +
    xlab('Carat') +
    ylab('Số 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 lá cây, các số liệu có màu trắng, đượ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à thấp nhất là 2.0.

5. Biểu đồ 5:

Phân loại kiểu cắt kim cương và tính trọng lượng trung bình (carat)

hieu %>% 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 = 'yellow') +
  labs(x = 'Kiểu cắt', y = 'Trọng lượng trung bình')

  • Ta gắn: x là kiểu cắt, y là trọng lượng trung bình.

  • Các số liệu sẽ có màu đỏ, được làm tròn đến 2 chữ thập phân và được điều chỉnh ở vị trí dọc cách cột với đơn vị là 2. Qua biểu đồ ta thấy được trọng lương trung bình của kim cương tăng từ Ideal(0.7 carat) < Very Good(0.81 carat) < Good(0.85 carat) < Premium(0.89 carat) < Fair(1.05 carat).

6. Biểu đồ 6:

Phân loại kim cương theo màu sắc và tính giá trung bình của từng loại

hieu %>% group_by(color) %>% summarise(m= mean(price)) %>%
  ggplot(aes(x = color,y = m)) +
  geom_col(position = 'dodge') +
  geom_text(aes(label = round(m,0)), vjust = 2, color = 'white') +
  labs(x = 'màu sắc', y = 'Gía trung bình')

  • Ở biểu đồ trên thì ta gắn: x là màu sắc, y là giá 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 0 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. Qua biểu đồ trên .
  • Ta thấy màu J có giá trung bình cao nhất và giảm dần từ I, H, G, F, D và thấp nhất là màu D VỚI 3170 Đơn vị giá.

7. Biểu đồ 7:

Phân loại kim cương theo kiểu cắt và tính số lượng của từng màu

hieu %>% group_by(cut) %>% summarise(n = n()) %>%
  ggplot(aes(cut,n)) +
  geom_col(fill='green') +
  geom_text(aes(label = n),vjust = 2, color = 'white') +
  labs(x = 'Kiểu Cắt', y = '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.

  • Các số liệu sẽ có màu đỏ và được điều chỉnh ở vị trí dọc cách cột với đơn vị là 2; các cột sẽ có màu xanh lá cây.

  • Qua biểu đồ trên ta thấy loại Fair có số lượng ít nhất và tăng dần theo kiểu cắt Good, Very Good, Premium và kiểu cắt Premium là cố số lượng nhiều nhất.

8. Biểu đồ 8:

Phân loại kim cương theo độ trong suốt và tính trọng lượng trung bình của chúng theo đơn vị carat

hieu %>% 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 = 'orange') +
  labs(x = 'độ trong suốt', y = 'trọng lượng trung bình')

  • Ở biểu đồ trên thì ta gắn x là độ trong suố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.

9. Biểu đồ 9:

Phân loại kim cương theo kiểu cắt và tính giá trung bình

hieu %>% group_by(cut) %>% summarise(n = mean(price)) %>%
  ggplot(aes(cut,n)) +
  geom_col(fill='lightgreen') +
  geom_text(aes(label = round(n,2)),vjust = 2, color = 'white') +
  labs(x = 'Loại', y = 'Số lượng')

  • Ta gắn x là kiểu cắt, y là số lượng.
  • Các số liệu sẽ có màu đỏ, được làm tròn đến 2 chữ thập phân và được điều chỉnh ở vị trí dọc cách cột với đơn vị là 2; cột biểu đồ có màu xanh lá cây. Qua biểu đồ ta thấy giá trung bình của từng kiểu cắt sẽ tăng dần từ Ideal, Good, Very Good, Fair, Premium.

10. Biểu đồ 10:

Phân loại kim cương theo màu sắc và tính trọng lượng trung bình theo đơn vị carat của từng loại

hieu %>% group_by(color) %>% summarise(m= mean(carat)) %>%
  ggplot(aes(x = color,y = m)) +
  geom_col(position = 'dodge') +
  geom_text(aes(label = round(m,2)), vjust = 2, color = 'white') +
  labs(x = 'Màu', y = 'Trọng lượng trung bình')

  • Ở biểu đồ trên thì ta gắn x là màu sắc, y là trọng 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 2 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. Qua biểu đồ trên ta thấy màu J có trọng lượng trung bình cao nhất là giảm dần từ I, H , G , F, màu D Và E có trọng lượng trung bình thấp nhất.

11. Biểu đồ 11:

Phân loại kim cương theo tổng giá và kiểu cắt

ggplot(diamonds , aes_string(x = "cut", y = "price")) +
  geom_bar(stat = "identity") +
  labs(title = "Giá kim cương theo kiểu cắt",
       x = "Kiểu cắt",
       y = "Giá")
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

  • Ta thấy giá kim cương sẽ tăng dần từ Fair < Good < Very Good < Premium < Ideal.

12. Biểu đồ 12:

Phân loại kim cương theo độ trong suốt và tính số lượng

hieu %>% group_by(clarity) %>% summarise(n = n()) %>%
  ggplot(aes(x = clarity,y = n)) +
  geom_col(position = 'dodge') +
  geom_text(aes(label = round(n,2)), vjust = 2, color = 'white') +
  labs(x = 'độ trong suốt', y = 'số lượng')

  • Ở biểu đồ trên thì ta gắn x là độ trong suốt, y là số lượng 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. Qua biểu đồ trên ta thấy độ trong suốt có số lượng nhiều nhất là SI1, giảm dần từ VS2 ,SI2, VS1, WS2, WS1, IF và I1 là độ trong suốt có số lượng thấp nhất.

13. Biểu đồ 13:

Phân loại kim cương theo kiểu cắt

hieu %>% ggplot(aes(x = cut)) +
    geom_bar() +
    labs(x = 'Loại', y = 'Số lượng') +
    labs(title = 'Số kim cương theo kiểu cắt(biểu đồ dọc)')

  • Biểu đồ dọc trên cho ta thấy được kiểu Gía của kim cương theo từng kiểu cắt.
  • Ta thấy số kim cương sẽ tăng dần từ Fair < Good < Very Good< Premium < Ideal.

14. Biểu đồ 14:

Thêm 1 cột dữ liêu caratC vào bộ dữ liệu t để đá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’

hieu <- hieu %>% mutate(caratC = cut(carat,4, label = c('rất nhỏ', 'nhỏ','vừa','lớn')))
hieu %>% ggplot(aes(x = caratC)) +
  geom_bar(fill = 'orange') +
  labs(x = 'phân loại', y = 'số lượng')

  • Các cột biểu đồ có màu đỏ.

  • 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’ và thấp nhất là loại ‘lớn’.

15. Biểu đồ 15:

Phân loại kim cương theo kiểu cắt và màu sắc sau đó tính số lượng

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

  • Ở 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 D,cột biểu đồ có màu đỏ và lọc các loại kim cương có màu J, biểu đồ có màu xanh dương.
  • Qua biểu đồ trên ta đã lọc được số lượng kim cương màu D 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 J cũng phẩn bổ tương tự như kim cương có màu D.

16. Biểu đồ 16:

Tương tự như biểu đồ số 15, lần này thay vì lọc các kim cương có màu ‘D’ VÀ ‘J’ thì ta sẽ lọc các kim cương có màu ‘E’ VÀ ‘H’

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

  • Tương tự như biểu đồ số 15, lần này thay vì lọc các kim cương có màu ‘D’ VÀ ‘J’ thì ta sẽ lọc các kim cương có màu ‘E’ VÀ ‘H’.
  • Ở biểu đồ này ta thấy màu E không phân bổ ở loại kim cương có kiểu cắt Fair, Premium, và màu sắc này phân bổ nhiều nhất ở kiểu cắt Ideal giảm dần từ Very Good, Good. Màu H phân bổ ở các kiểu cắt, nhiều nhất là Ideal và giảm dần từ Premium, Very Good, Good và thấp nhất là Fair.

17. Biểu đồ 17:

Thêm 1 cột dữ liêu priceC vào bộ dữ liệu t để đánh giá gía cả của các viên kim cương theo mức độ ‘rất thấp’ ‘thấp’, ‘vừa’, ‘cao’ và ‘rất cao’

hieu <- hieu %>% mutate(priceC = cut(price,5, label = c('rất thấp', 'thấp','vừa','cao','rất cao')))
hieu %>% ggplot(aes(x = priceC)) +
  geom_bar(fill = 'orange') +
  labs(x = 'phân loại', y = 'số lượng')

  • Các cột biểu đồ có màu đỏ. Qua biểu đồ trên ta thấy số lượng kim cương có giá ‘rất thấp’ là lớn nhất và giảm dần từ ‘thấp’, ‘vừa’, ‘cao’ và thấp nhất là loại ‘rất cao’.

18. Biểu đồ 18:

Phân loại kim cương theo kiểu độ trong suốt và màu sắc sau đó tính số lượng

vo <- hieu %>% group_by(clarity, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
vo %>% ggplot(aes(x = clarity, y = n)) +
  geom_col(data = vo %>% filter(color == 'F'), fill = 'gray') +
  geom_col(data = vo %>% filter(color == 'J'), fill = 'blue')

  • Ở biểu đồ trên thì ta gắn x là độ trong suố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 ‘F’,cột biểu đồ có màu đỏ và lọc các loại kim cương có màu J, biểu đồ có màu xanh dương.
  • Qua biểu đồ trên ta thấy các màu phân bổ ở tất cả độ trong suốt. Trong đó màu J sẽ phân bổ nhiều nhất ở SI1 rồi giảm dần từ VS2, VS1, SI2, WS2, WS1, IF và thấp nhất là I1. Còn màu F Phân bổ nhiều nhất ở VS2 rồi giảm dần từ SI1, SI2, VS1, WS2, WS1, IF và tháp nhất là I1.

19. Biểu đồ 19:

Phân loại kim cương theo kiểu độ trong suốt và kiểu cắt sau đó tính số lượng

vh <- hieu %>% group_by(clarity, cut) %>% summarise(n = n())
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
vh %>% ggplot(aes(x = cut, y = n)) +
  geom_col(data = vh %>% filter(clarity == 'IF'), fill = 'red') +
  geom_col(data = vh %>% filter(clarity == 'I1'), fill = 'green')

  • Ở 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 lọc các kim cương có độ trong suốt ‘IF’ là các cột màu đỏ, các kim cương có độ trong suốt ‘I1’ là các cột màu xanh. Qua biểu đồ trên ta thấy kim cương có độ trong suốt ‘IF’ chỉ phân bổ ở kiểu cắt Ideal, Very Good, Premium theo số lượng giảm dần.
  • Trong khi đó độ trong suốt I1 phân bổ ở mọi kiểu cắt, nhiều nhất là Premium và giảm dần từ Fair, Idea, Good, thấp nhất là Very Good.

20. Biểu đồ 20:

Biểu đồ thể hiện mối quan hệ giữa trọng lượng và số lượng của các viên kim cương

hieu1 <- hieu %>% mutate(caratC = cut(carat,5, label = c('Rất Nhỏ', 'Nhỏ','Vừa','Lớn','Rất Lớn')))
hieu1 %>% ggplot(aes(x = caratC)) +
  geom_bar(fill = 'darkblue') +
  labs(x = 'Trọng lương', y = 'Số Lượng')

  • Ta gắn x là ‘Loại’, y là ‘Số Lượng’.
  • Tạo ra một biểu đồ thể hiện mối quan hệ giữa trọng lượng các viên kim cương và số lượng của chúng gồm 5 cột màu đỏ. Trục hoành (x) là trọng lượng của các viên kim cương lần lượt là ‘rất nhỏ’, ‘nhỏ’, ‘vừa’, ‘lớn’, ‘rất lớn’. Trục tung(y) là số lượng của các viên kim cương ứng với trọng lượng đó.
  • Qua biểu đồ trên ta thấy trọng lượng của các viên kim cương chiếm đa số (khoảng hơn 40000 viên) là Rất Nhỏ và giảm dần xuống khi đó trọng lượng của các viên kim cương Rất lớn là ít nhất

21. Biểu đồ 21:

Biểu đồ thể hiện 4 đặc tính độ trong của các viên kim cương

hieu2 <- hieu %>% group_by(color, clarity) %>% summarise(n = n())
## `summarise()` has grouped output by 'color'. You can override using the
## `.groups` argument.
  • Tạo ra một biểu đồ gồm 4 cột xanh dương, đỏ, xanh lá, vàng, trục hoành (x) ứng với mức độ tinh khiết của viên kim cương lần lượt là VS1,VS2,VVS2,VVS1, trục tung (y) số lượng của các viên kim cương đó.

  • Theo biểu đồđồ ta thấy là viên kim cương có độ trong VS2 có số lượng nhiều nhất (gần 12500 viên kim cương). Tiếp theo là viên kim cương có độ trong là VS1 (khoảng hơn 7500 viên) và VVS2 (khoảng hơn 5000 viên). Và viên kim cương có độ trong VVS1 chiếm số lượng ít nhất trong 4 loại (khoảng hơn 2500 viên).

22. Biểu đồ 22:

Phân loại kim cương theo trung bình giá thành theo chất lượng cắt (cut)

hieu %>% group_by(cut) %>% summarise(mp= mean(price)) %>%
  ggplot(aes(x = cut,y = mp)) +
    geom_col(position = 'dodge') +
    geom_text(aes(label = round(mp,2)), vjust = 2, color = 'white') +
    labs(x = 'Loại', y = 'Mean Price')

* Theo biểu đồ ta thấy:Loại Fair có mức giá trung bình là 4358.76, Loại Good có mức giá trung bình là 3829.8, Loại Very Good có mức giá trung bình là 3981.76, Loại Premium có mức giá trung bình là 4584.76, Loại Ideal có mức giá trung bình là 3457.54.

23. Biểu đồ 23:

Tương tự như biểu đồ số 18, lần này thay vì lọc các kim cương có màu ‘F’ VÀ ‘J’ thì ta sẽ lọc các kim cương có màu ‘E’ VÀ ‘G’

vo <- hieu %>% group_by(clarity, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
vo %>% ggplot(aes(x = clarity, y = n)) +
  geom_col(data = vo %>% filter(color == 'E'), fill = 'gray') +
  geom_col(data = vo %>% filter(color == 'G'), fill = 'blue')

  • Ở biểu đồ này ta thấy màu E chỉ phân bổ ở loại kim cương độ trong suốt là SI2,VS2 và SI1. Còn kim cương màu G phân bổ ở tất cả độ trong suốt, trong đó nhiều nhất là VS2, giảm dần từ VS1, SI1, SI2, VVS2, VVS1, IF và phân bổ ít nhất ở I1.

24. Biểu đồ 24:

Phân loại rung bình giá kim cương theo màu sắc, kiểu cắt và độ trong suốt

hieu %>%
  group_by(color, cut, clarity) %>%
  summarise(mean_price = mean(price)) %>%
  ggplot(aes(x = color, y = mean_price, fill = interaction(cut, clarity))) +
  geom_bar(stat = "identity", position = "dodge") +
  xlab("Color") +
  ylab("Average Price") +
  ggtitle("Trung bình giá kim cương theo màu sắc, kiểu cắt và độ trong suốt") +
  scale_fill_discrete(name = "Cut & Clarity")
## `summarise()` has grouped output by 'color', 'cut'. You can override using the
## `.groups` argument.

25. Biểu đồ 25:

Phân loại kim cương theo độ trong suốt và tính số lượng của các màu

hieu %>%
  group_by(cut, clarity) %>%
  summarise(count = n()) %>%
  ggplot(aes(x = cut, y = count, fill = clarity)) +
  geom_bar(stat = "identity", position = "dodge") +
  xlab("Cut") +
  ylab("Count") +
  ggtitle("Số lượng kim cương theo kiểu cắt và độ trong suốt") +
  scale_fill_discrete(name = "Clarity")
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

26. Biểu đồ 26:

Tương tự như biểu đồ số 19, lần này thay vì lọc các kim cương có độ trong suốt ‘iF’ VÀ ‘i1’ thì ta sẽ lọc các kim cương có độ trong suốt ‘SI1’ VÀ ‘SI2’

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

  • Ở biểu đồ này ta thấy độ trong suốt SI1 không phân bổ ở loại kim cương có kiểu cắt Fair, phân bố nhiều nhất ở kiểu cắt Ideal giảm dần từ Very Good, Premium và phân bổ ít nhất ở kiểu cắt Good.
  • Kim cương có độ trong suốt SI2 phân bổ ở tất cả kiểu cắt, nhiều nhất ở kiểu cắt Premium giảm dần từ Ideal, Very Good, Good và phân bổ ít nhất ở kiểu cắt Fair.

27. Biểu đồ 27:

Phân loại kim cương theo kiểu cắt và màu sắc sau đó tính số lượng

hieu %>% 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 gắn x là loại, y la số lượng và ta 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.

28. Biểu đồ 28:

Phân loại kim cương theo kiểu cắt và tính trung bình tỷ lệ độ sâu (trung bình z/x)

hieu %>% group_by(cut) %>% summarise(m= mean(depth)) %>%
  ggplot(aes(x = cut,y = m)) +
  geom_col(position = 'dodge') +
  geom_text(aes(label = round(m,2)), vjust = 2, color = 'darkgrey') +
  labs(x = 'Kiểu cắt', y = 'Mean')

***Ta phân loại kim cương theo kiểu cắt và tính trung bình tỷ lệ độ sâu (trung bình z/x). ta gắn x là kiểu cắt, y là trung bình. các số liệu được làm tròn 2 chữ số thập phân, được điều chỉnh ở vị trí cách cột dọc 2 đơn vị và có màu xanh lá cây. Qua biểu đồ trên ta thấy kiểu cắt Fair có độ sâu trung bình lớn nhất, giảm dần từ Good, Very Good, Ideal và thấp nhất là Premium

29. Biểu đồ 29:

Phân loại kim cương theo độ trong suốt

hieu %>% ggplot(aes(x = price)) +
  geom_histogram(binwidth = 500, fill = 'green', color = 'red') +
  labs(x = 'Price', y = 'Số lượng')

  • Ta gắn x là giá của kim cương , y là số lượng. Trục hoành(x) là các mức giá của kim cương và trục tung (y) là số lượng của các viên kim cương tương ứng với các mức giá.
  • Theo đồ thị ta thấy khoảng giá từ 0-5000(USD) có số lượng các viên kim cương nhiều nhất và sô lượng các viên kim cương giảm dần về sau khi mức giá tăng lên đến khoảng gần 200000(USD). ## 30. Biểu đồ 30:

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

hieu %>% group_by(color) %>% summarise(m = mean(depth)) %>%
  ggplot(aes(color,m)) +
  geom_col(fill='lightpink') +
  geom_text(aes(label = round(m,2)),vjust = 2, color = 'lightyellow') +
  labs(x = 'Loại', y = 'Số lượng')

  • Các cột biểu đồ có màu xanh lá cây, 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à thấp nhất là màu E.
LS0tDQp0aXRsZTogIk5oaeG7h20gVuG7pSA0Ig0KYXV0aG9yOiAiVm9IaWV1Ig0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUg6JU06JVMsICVkIC0gJW0gLSAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgdGhlbWU6ICJkZWZhdWx0Ig0KICAgIHRvY19kZXB0aDogMw0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRvYzogdHJ1ZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMjIEdJ4buaSSBUSEnhu4ZVIFThu5RORyBRVUFOIFbhu4AgQuG7mCBE4buuIExJ4buGVSBESUFNT05EUw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoc2NhbGVzKQ0KaGlldSA8LSBkaWFtb25kcw0KaGlldQ0KYGBgDQojIyBUaMO0bmcgdGluIGPGoSBi4bqjbiB24buBIGLhu5kgZOG7ryBsaeG7h3U6DQpgYGB7cn0NCmRpbShoaWV1KQ0KYGBgIA0KKiBT4buRIGzGsOG7o25nOiA1My45NDAgdmnDqm4ga2ltIGPGsMahbmcNCg0KKiBCaeG6v246IDEwIMSR4bq3YyB0w61uaA0KDQoqIFByaWNlOiBHacOhIHRow6BuaCBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIChVU0QpDQoNCiogQ2FyYXQ6IFRy4buNbmcgbMaw4bujbmcgY+G7p2EgY8OhYyB2acOqbiBraW0gY8awxqFuZyAoY2FyYXQpDQoNCiogQ3V0OiBDaOG6pXQgbMaw4bujbmcgY+G6r3QgKEtow6EsIFThu5F0LCBS4bqldCB04buRdCwgxJDhurdjIGJp4buHdCwgTMO9IHTGsOG7n25nKQ0KDQoqIENvbG9yOiBDw6FjIE3DoHUgY+G7p2EgdmnDqm4gS2ltIGPGsMahbmcgKEogLSBrw6ltIG5o4bqldCwgRCAtIHThu5F0IG5o4bqldCkNCg0KKiBDbGFyaXR5OiDEkOG7mSB0cm9uZyBj4bunYSB2acOqbiBraW0gY8awxqFuZw0KDQoqIHg6IENoaeG7gXUgZMOgaSAobW0pDQoNCiogeTogQ2hp4buBdSBy4buZbmcgKG1tKQ0KDQoqIHo6IMSQ4buZIHPDonUgKG1tKQ0KDQoqIERlcHRoOiDEkOG7mSBzw6J1IHbhur90IGPhuq90DQoNCiogVGFibGU6IENoaeG7gXUgcuG7mW5nIMSR4buJbmgga2ltIGPGsMahbmcgc28gduG7m2kgxJFp4buDbSBy4buZbmcgbmjhuqV0DQoNCg0KIyMgMS4gQmnhu4N1IMSR4buTIDE6DQoNCipQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QqDQoNCmBgYHtyfQ0KaGlldSAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0KSkgKw0KICAgIGdlb21fYmFyKCkgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBsYWJzKHRpdGxlID0gJ1Phu5Ega2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QoYmnhu4N1IMSR4buTIG5nYW5nKScpDQpgYGANCiogQmnhu4N1IMSR4buTIG5nYW5nIHRyw6puIGNobyB0YSB0aOG6pXkgxJHGsOG7o2Mga2nhu4N1IEfDrWEgY+G7p2Ega2ltIGPGsMahbmcgdGhlbyB04burbmcga2nhu4N1IGPhuq90LiBUYSB0aOG6pXkgc+G7kSBraW0gY8awxqFuZyBz4bq9IHTEg25nIGThuqduIHThu6sgRmFpciwgR29vZCwgVmVyeSBHb29kLCBQcmVtaXVtLCBJZGVhbC4NCg0KIyMgMi4gQmnhu4N1IMSR4buTIDI6DQoNCiAqUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gxJHhu5kgdHJvbmcgc3Xhu5F0IHbDoCB0w61uaCBnacOhIHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyBsb+G6oWkqDQoNCmBgYHtyfQ0KaGlldSAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShtPSBtZWFuKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG0pKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKyAgDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDEpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICdncmVlbicpICsNCiAgbGFicyh4ID0gJ8SR4buZIHRyb25nIHN14buRdCcsIHkgPSAnZ2nDoScpDQpgYGANCg0KKiBUYSBn4bqvbjogeCBsw6AgxJHhu5kgdHJvbmcgc3Xhu5F0LCB5IGzDoCBnacOhIHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyBsb+G6oWkNCiANCiogQ8OhYyBz4buRIGxp4buHdSBz4bq9IGPDsyBtw6B1IHhhbmggbMOhIGPDonksIMSRxrDhu6NjIGzDoG0gdHLDsm4gMDEgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gdsOgIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDhu58gduG7iyB0csOtIGThu41jIGPDoWNoIGPhu5l0IHbhu5tpIMSRxqFuIHbhu4sgbMOgIDIuIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgdGjhuqV5IGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgU0kyIGzDoCBjw7MgZ2nDoSB0cnVuZyBiw6xuaCBjYW8gbmjhuqV0LCB0aeG6v3AgxJHhur9uIGzDoCBTSTIsIHRo4bqlcCBoxqFuIG7hu69hIGzhuqduIGzGsOG7o3QgbMOgIFZTMiwgSTEsIFZTMSwgV1MyLCBJRiB2w6AgdGjhuqVwIG5o4bqldCBsw6AgV3MxLg0KDQoNCiMjIDMuIEJp4buDdSDEkeG7kyAzOg0KDQoqUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYyB2w6AgdMOtbmggc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbcOgdSBz4bqvYyoNCg0KYGBge3J9DQpoaWV1ICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjb2xvcixuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3JlZCcpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdibGFjaycpICsNCiAgICB4bGFiKCdDb2xvcicpICsNCiAgICB5bGFiKCdT4buRIGzGsOG7o25nJykgKw0KICAgIGxhYnModGl0bGUgPSdT4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYycpDQpgYGANCg0KKiB4IGzDoCBtw6B1IHPhuq9jIGPhu6dhIGtpbSBjxrDGoW5nDQoqIHkgbMOgIHPhu5EgbMaw4bujbmcgY+G7p2EgdOG7q25nIGxv4bqhaSBtw6B1IHPhuq9jLiANCiogQ8OhYyBz4buRIGxp4buHdSBjw7MgbcOgdSDEkWVuLCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCAyIMSRxqFuIHbhu4suIE3DoHUgY+G7p2EgY8OhYyBj4buZdCBsw6AgbcOgdSDEkeG7jyAgLiBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSDEkcaw4bujYyBuaGnhu4F1IG5o4bqldCBsw6AgbcOgdSBHIHbhu5tpIDExMjkyIHZpw6puLCB0aeG6v3AgxJHhur9uIGzDoCBFIHbhu5tpIDk3OTcgdmnDqm4sIEYgduG7m2kgOTU0MiB2acOqbiwgSCB24bubaSA4MzA0IHZpw6puLEQgduG7m2kgNjc3NSB2acOqbiwgSSB24bubaSA1NDIyIHZpw6puIHbDoCDDrXQgbmjhuqV0IGzDoCBtw6B1IEogduG7m2kgMjgwOCB2acOqbi4NCg0KIyMgNC5CaeG7g3UgxJHhu5MgNDoNCg0KICpQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyB0cuG7jW5nIGzGsOG7o25nIGNhcmF0IOG7nyBjw6FjIG3hu5FjIDAuNSwgMS4wLCAxLjUsIDIuMCB2w6AgdMOtbmggc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbeG7kWMga2jhu5FpIGzGsOG7o25nKg0KIA0KYGBge3J9DQpoaWV1ICU+JSBncm91cF9ieShjYXJhdCkgJT4lIGZpbHRlcihjYXJhdCA9PSAwLjUgfCBjYXJhdCA9PSAxLjAwIHwgY2FyYXQgPT0gMS41IHwgY2FyYXQgPT0gMi4wNSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjYXJhdCxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J3B1cnBsZScpICsNCiAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogICAgeGxhYignQ2FyYXQnKSArDQogICAgeWxhYignU+G7kSBsxrDhu6NuZycpDQpgYGANCiAqVGEgZ+G6r246IHggbMOgIGNhcmF0IHbDoCB5IGzDoCBz4buRIGzGsOG7o25nIHThu6tuZyBt4buRYyBjYXJhdC4gDQogKkPDoWMgY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHhhbmggbMOhIGPDonksIGPDoWMgc+G7kSBsaeG7h3UgY8OzIG3DoHUgdHLhuq9uZywgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIOG7nyB24buLIHRyw60gZOG7jWMgY8OhY2ggY+G7mXQgMiDEkcahbiB24buLIC4gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgxJHGsOG7o2Mgc+G7kSBraW0gY8awxqFuZyBjw7MgdHLhu41uZyBsxrDhu6NuZyAxLjAgY2FyYXQgbMOgIG5oaeG7gXUgbmjhuqV0IHbDoCB0aOG6pXAgbmjhuqV0IGzDoCAyLjAuDQoNCiMjIDUuIEJp4buDdSDEkeG7kyA1Og0KDQoqUGjDom4gbG/huqFpIGtp4buDdSBj4bqvdCBraW0gY8awxqFuZyB2w6AgdMOtbmggdHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaCAoY2FyYXQpKg0KDQpgYGB7cn0NCmhpZXUgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShtPSBtZWFuKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gbSkpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLDIpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICd5ZWxsb3cnKSArDQogIGxhYnMoeCA9ICdLaeG7g3UgY+G6r3QnLCB5ID0gJ1Ry4buNbmcgbMaw4bujbmcgdHJ1bmcgYsOsbmgnKQ0KYGBgDQoNCiogVGEgZ+G6r246IHggbMOgIGtp4buDdSBj4bqvdCwgeSBsw6AgdHLhu41uZyBsxrDhu6NuZyB0cnVuZyBiw6xuaC4NCg0KKiBDw6FjIHPhu5EgbGnhu4d1IHPhur0gY8OzIG3DoHUgxJHhu48sIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gdGjhuq1wIHBow6JuIHbDoCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCB24bubaSDEkcahbiB24buLIGzDoCAyLiBRdWEgYmnhu4N1IMSR4buTIHRhIHRo4bqleSDEkcaw4bujYyB0cuG7jW5nIGzGsMahbmcgdHJ1bmcgYsOsbmggY+G7p2Ega2ltIGPGsMahbmcgdMSDbmcgdOG7qyBJZGVhbCgwLjcgY2FyYXQpIDwgVmVyeSBHb29kKDAuODEgY2FyYXQpIDwgR29vZCgwLjg1IGNhcmF0KSA8IFByZW1pdW0oMC44OSBjYXJhdCkgPCBGYWlyKDEuMDUgY2FyYXQpLg0KDQoNCiMjIDYuIEJp4buDdSDEkeG7kyA2Og0KDQoqUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gbcOgdSBz4bqvYyB2w6AgdMOtbmggZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSB04burbmcgbG/huqFpKg0KDQpgYGB7cn0NCmhpZXUgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG09IG1lYW4ocHJpY2UpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY29sb3IseSA9IG0pKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwwKSksIHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogIGxhYnMoeCA9ICdtw6B1IHPhuq9jJywgeSA9ICdHw61hIHRydW5nIGLDrG5oJykNCmBgYA0KDQoqIOG7niBiaeG7g3UgxJHhu5MgdHLDqm4gdGjDrCB0YSBn4bqvbjogeCBsw6AgbcOgdSBz4bqvYywgeSBsw6AgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSB04burbmcgbG/huqFpDQoqIEPDoWMgc+G7kSBsaeG7h3Ugc+G6vSBjw7MgbcOgdSB4YW5oIGzDoSBjw6J5LCDEkcaw4bujYyBsw6BtIHRyw7JuIDAgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gdsOgIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDhu58gduG7iyB0csOtIGThu41jIGPDoWNoIGPhu5l0IHbhu5tpIMSRxqFuIHbhu4sgbMOgIDIuIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gLg0KKiBUYSB0aOG6pXkgbcOgdSBKIGPDsyBnacOhIHRydW5nIGLDrG5oIGNhbyBuaOG6pXQgdsOgIGdp4bqjbSBk4bqnbiB04burIEksIEgsIEcsIEYsIEQgdsOgIHRo4bqlcCBuaOG6pXQgbMOgIG3DoHUgRCBW4buaSSAzMTcwIMSQxqFuIHbhu4sgZ2nDoS4NCg0KIyMgNy4gQmnhu4N1IMSR4buTIDc6DQoNCipQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QgdsOgIHTDrW5oIHPhu5EgbMaw4bujbmcgY+G7p2EgdOG7q25nIG3DoHUqDQoNCmBgYHtyfQ0KaGlldSAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICBnZW9tX2NvbChmaWxsPSdncmVlbicpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogIGxhYnMoeCA9ICdLaeG7g3UgQ+G6r3QnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCirhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6Aga2nhu4N1IGPhuq90LCB5IGzDoCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWkuDQoNCiogQ8OhYyBz4buRIGxp4buHdSBz4bq9IGPDsyBtw6B1IMSR4buPIHbDoCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCB24bubaSDEkcahbiB24buLIGzDoCAyOyBjw6FjIGPhu5l0IHPhur0gY8OzIG3DoHUgeGFuaCBsw6EgY8OieS4gDQoNCiogUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgbG/huqFpIEZhaXIgY8OzIHPhu5EgbMaw4bujbmcgw610IG5o4bqldCB2w6AgdMSDbmcgZOG6p24gdGhlbyBraeG7g3UgY+G6r3QgR29vZCwgVmVyeSBHb29kLCBQcmVtaXVtIHbDoCBraeG7g3UgY+G6r3QgUHJlbWl1bSBsw6AgY+G7kSBz4buRIGzGsOG7o25nIG5oaeG7gXUgbmjhuqV0Lg0KDQoNCiMjIDguIEJp4buDdSDEkeG7kyA4Og0KDQoqUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8gxJHhu5kgdHJvbmcgc3Xhu5F0IHbDoCB0w61uaCB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGPhu6dhIGNow7puZyB0aGVvIMSRxqFuIHbhu4sgY2FyYXQqDQoNCmBgYHtyfQ0KaGlldSAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShtPSBtZWFuKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG0pKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSw1KSksIHZqdXN0ID0gMiwgY29sb3IgPSAnb3JhbmdlJykgKw0KICBsYWJzKHggPSAnxJHhu5kgdHJvbmcgc3Xhu5F0JywgeSA9ICd0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oJykNCmBgYA0KDQoqIOG7niBiaeG7g3UgxJHhu5MgdHLDqm4gdGjDrCB0YSBn4bqvbiB4IGzDoCDEkeG7mSB0cm9uZyBzdeG7kXQsIHkgbMOgIGto4buRaSBsxrDhu6NuZyB0cnVuZyBiw6xuaCBj4bunYSB04burbmcgbG/huqFpDQoqIEPDoWMgc+G7kSBsaeG7h3Ugc+G6vSBjw7MgbcOgdSB4YW5oIGzDoSBjw6J5LCDEkcaw4bujYyBsw6BtIHRyw7JuIDUgY2jhu68gc+G7kSB0aOG6rXAgcGjDom4gdsOgIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCDhu58gduG7iyB0csOtIGThu41jIGPDoWNoIGPhu5l0IHbhu5tpIMSRxqFuIHbhu4sgbMOgIDIuIFbDoCB0YSB0aOG6pXkgxJHGsOG7o2Mga2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCBjYW8gbmjhuqV0IGzDoCBJMSwgdGjhuqVwIGjGoW4gxJHDsyBsw6AgU0kyIHbDoCBnaeG6o20gZOG6p24gdOG7qyBTSTEsIFZTMiwgVlMxLCBXUzIsIFdTMSwgdsOgIHRo4bqlcCBuaOG6pXQgbMOgIElGLg0KDQojIyA5LiBCaeG7g3UgxJHhu5MgOToNCg0KKlBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdCB2w6AgdMOtbmggZ2nDoSB0cnVuZyBiw6xuaCoNCg0KYGBge3J9DQpoaWV1ICU+JSBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2UobiA9IG1lYW4ocHJpY2UpKSAlPiUNCiAgZ2dwbG90KGFlcyhjdXQsbikpICsNCiAgZ2VvbV9jb2woZmlsbD0nbGlnaHRncmVlbicpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG4sMikpLHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiogVGEgZ+G6r24geCBsw6Aga2nhu4N1IGPhuq90LCB5IGzDoCBz4buRIGzGsOG7o25nLg0KKiBDw6FjIHPhu5EgbGnhu4d1IHPhur0gY8OzIG3DoHUgxJHhu48sIMSRxrDhu6NjIGzDoG0gdHLDsm4gxJHhur9uIDIgY2jhu68gdGjhuq1wIHBow6JuIHbDoCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCB24bubaSDEkcahbiB24buLIGzDoCAyOyBj4buZdCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgeGFuaCBsw6EgY8OieS4gUXVhIGJp4buDdSDEkeG7kyB0YSB0aOG6pXkgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSB04burbmcga2nhu4N1IGPhuq90IHPhur0gdMSDbmcgZOG6p24gdOG7qyBJZGVhbCwgR29vZCwgVmVyeSBHb29kLCBGYWlyLCBQcmVtaXVtLg0KDQoNCiMjIDEwLiBCaeG7g3UgxJHhu5MgMTA6DQoNCipQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jIHbDoCB0w61uaCB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIHRoZW8gxJHGoW4gduG7iyBjYXJhdCBj4bunYSB04burbmcgbG/huqFpKg0KDQpgYGB7cn0NCmhpZXUgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY29sb3IseSA9IG0pKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogIGxhYnMoeCA9ICdNw6B1JywgeSA9ICdUcuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oJykNCmBgYA0KDQoqIOG7niBiaeG7g3UgxJHhu5MgdHLDqm4gdGjDrCB0YSBn4bqvbiB4IGzDoCBtw6B1IHPhuq9jLCB5IGzDoCB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyBsb+G6oWkNCiogQ8OhYyBz4buRIGxp4buHdSBz4bq9IGPDsyBtw6B1IHhhbmggbMOhIGPDonksIMSRxrDhu6NjIGzDoG0gdHLDsm4gMiBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiB2w6AgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIOG7nyB24buLIHRyw60gZOG7jWMgY8OhY2ggY+G7mXQgduG7m2kgxJHGoW4gduG7iyBsw6AgMi4gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgbcOgdSBKIGPDsyB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIGNhbyBuaOG6pXQgbMOgIGdp4bqjbSBk4bqnbiB04burIEksIEggLCBHICwgRiwgbcOgdSBEIFbDoCBFIGPDsyB0cuG7jW5nIGzGsOG7o25nIHRydW5nIGLDrG5oIHRo4bqlcCBuaOG6pXQuDQoNCiMjIDExLiBCaeG7g3UgxJHhu5MgMTE6DQoNCipQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyB04buVbmcgZ2nDoSB2w6Aga2nhu4N1IGPhuq90Kg0KDQpgYGB7cn0NCmdncGxvdChkaWFtb25kcyAsIGFlc19zdHJpbmcoeCA9ICJjdXQiLCB5ID0gInByaWNlIikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgbGFicyh0aXRsZSA9ICJHacOhIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90IiwNCiAgICAgICB4ID0gIktp4buDdSBj4bqvdCIsDQogICAgICAgeSA9ICJHacOhIikNCmBgYA0KDQoqICBUYSB0aOG6pXkgZ2nDoSBraW0gY8awxqFuZyBz4bq9IHTEg25nIGThuqduIHThu6sgRmFpciA8IEdvb2QgPCBWZXJ5IEdvb2QgPCBQcmVtaXVtIDwgSWRlYWwuDQoNCg0KIyMgMTIuIEJp4buDdSDEkeG7kyAxMjoNCg0KKlBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIMSR4buZIHRyb25nIHN14buRdCB2w6AgdMOtbmggc+G7kSBsxrDhu6NuZyAqDQoNCmBgYHtyfQ0KaGlldSAlPiUgZ3JvdXBfYnkoY2xhcml0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSx5ID0gbikpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChuLDIpKSwgdmp1c3QgPSAyLCBjb2xvciA9ICd3aGl0ZScpICsNCiAgbGFicyh4ID0gJ8SR4buZIHRyb25nIHN14buRdCcsIHkgPSAnc+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiDhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6AgxJHhu5kgdHJvbmcgc3Xhu5F0LCB5IGzDoCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWkNCiogQ8OhYyBz4buRIGxp4buHdSBz4bq9IGPDsyBtw6B1IHhhbmggbMOhIGPDonksIMSRxrDhu6NjIGzDoG0gdHLDsm4gNSBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiB2w6AgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIOG7nyB24buLIHRyw60gZOG7jWMgY8OhY2ggY+G7mXQgduG7m2kgxJHGoW4gduG7iyBsw6AgMi4gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgxJHhu5kgdHJvbmcgc3Xhu5F0IGPDsyBz4buRIGzGsOG7o25nIG5oaeG7gXUgbmjhuqV0IGzDoCBTSTEsIGdp4bqjbSBk4bqnbiB04burIFZTMiAsU0kyLCBWUzEsIFdTMiwgV1MxLCBJRiB2w6AgSTEgbMOgIMSR4buZIHRyb25nIHN14buRdCBjw7Mgc+G7kSBsxrDhu6NuZyB0aOG6pXAgbmjhuqV0Lg0KDQoNCiMjIDEzLiBCaeG7g3UgxJHhu5MgMTM6DQoNCipQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QqDQoNCmBgYHtyfQ0KaGlldSAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0KSkgKw0KICAgIGdlb21fYmFyKCkgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKSArDQogICAgbGFicyh0aXRsZSA9ICdT4buRIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90KGJp4buDdSDEkeG7kyBk4buNYyknKQ0KYGBgDQoNCiogQmnhu4N1IMSR4buTIGThu41jIHRyw6puIGNobyB0YSB0aOG6pXkgxJHGsOG7o2Mga2nhu4N1IEfDrWEgY+G7p2Ega2ltIGPGsMahbmcgdGhlbyB04burbmcga2nhu4N1IGPhuq90Lg0KKiBUYSB0aOG6pXkgc+G7kSBraW0gY8awxqFuZyBz4bq9IHTEg25nIGThuqduIHThu6sgRmFpciA8IEdvb2QgPCBWZXJ5IEdvb2Q8IFByZW1pdW0gPCBJZGVhbC4NCg0KDQojIyAxNC4gQmnhu4N1IMSR4buTIDE0Og0KDQoqVGjDqm0gMSBj4buZdCBk4buvIGxpw6p1IGNhcmF0QyB2w6BvIGLhu5kgZOG7ryBsaeG7h3UgdCDEkeG7gyDEkcOhbmggZ2nDoSB0cuG7jW5nIGzGsOG7o25nIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyBt4bupYyDEkeG7mSAncuG6pXQgbmjhu48nICduaOG7jycsICd24burYScgdsOgICds4bubbicqDQoNCmBgYHtyfQ0KaGlldSA8LSBoaWV1ICU+JSBtdXRhdGUoY2FyYXRDID0gY3V0KGNhcmF0LDQsIGxhYmVsID0gYygncuG6pXQgbmjhu48nLCAnbmjhu48nLCd24burYScsJ2zhu5tuJykpKQ0KaGlldSAlPiUgZ2dwbG90KGFlcyh4ID0gY2FyYXRDKSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ29yYW5nZScpICsNCiAgbGFicyh4ID0gJ3Bow6JuIGxv4bqhaScsIHkgPSAnc+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyBjw7MgbcOgdSDEkeG7jy4NCg0KKiBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyB0cuG7jW5nIGzGsOG7o25nICdy4bqldCBuaOG7jycgbMOgIGzhu5tuIG5o4bqldCB2w6AgZ2nhuqNtIGThuqduIHThu6sgJ25o4buPJywgJ3bhu6thJyB2w6AgdGjhuqVwIG5o4bqldCBsw6AgbG/huqFpICds4bubbicuDQoNCiMjIDE1LiBCaeG7g3UgxJHhu5MgMTU6DQoNCipQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QgdsOgIG3DoHUgc+G6r2Mgc2F1IMSRw7MgdMOtbmggc+G7kSBsxrDhu6NuZyoNCg0KYGBge3J9DQpoaWV1IDwtIGRpYW1vbmRzIA0Kdm8gPC0gaGlldSAlPiUgZ3JvdXBfYnkoY3V0LCBjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0Kdm8gJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSB2byAlPiUgZmlsdGVyKGNvbG9yID09ICdEJyksIGZpbGwgPSAncGluaycpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHZvICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0onKSwgZmlsbCA9ICd3aGl0ZScpDQpgYGANCg0KKiDhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6Aga2nhu4N1IGPhuq90LCB5IGzDoCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWkNCiogVGEgc+G6vSBs4buNYyBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyBjw7MgbcOgdSBELGPhu5l0IGJp4buDdSDEkeG7kyBjw7MgbcOgdSDEkeG7jyB2w6AgbOG7jWMgY8OhYyBsb+G6oWkga2ltIGPGsMahbmcgY8OzIG3DoHUgSiwgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHhhbmggZMawxqFuZy4gDQoqIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgxJHDoyBs4buNYyDEkcaw4bujYyBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIG3DoHUgRCBwaMOibiBi4buVIMOtdCBuaOG6pXQg4bufIGtp4buDdSBj4bqvdCBGYWlyIHbDoCB0xINuZyBk4bqnbiBsw6puIHThu6sgR29vZCwgVmVyeSBHb29kLCBQcmVtaXVtLCB2w6Agbmhp4buBdSBuaOG6pXQgbMOgIElkZWFsLCB2w6Agc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgbcOgdSBKIGPFqW5nIHBo4bqpbiBi4buVIHTGsMahbmcgdOG7sSBuaMawIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEQuDQoNCg0KIyMgMTYuIEJp4buDdSDEkeG7kyAxNjoNCg0KKlTGsMahbmcgdOG7sSBuaMawIGJp4buDdSDEkeG7kyBz4buRIDE1LCBs4bqnbiBuw6B5IHRoYXkgdsOsIGzhu41jIGPDoWMga2ltIGPGsMahbmcgY8OzIG3DoHUgJ0QnIFbDgCAnSicgdGjDrCB0YSBz4bq9IGzhu41jIGPDoWMga2ltIGPGsMahbmcgY8OzIG3DoHUgJ0UnIFbDgCAnSCcqDQoNCmBgYHtyfQ0KaGlldSA8LSBkaWFtb25kcyANCnZvIDwtIGhpZXUgJT4lIGdyb3VwX2J5KGN1dCwgY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCnZvICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQsIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gdm8gJT4lIGZpbHRlcihjb2xvciA9PSAnRScpLCBmaWxsID0gJ3doaXRlJykgKw0KICBnZW9tX2NvbChkYXRhID0gdm8gJT4lIGZpbHRlcihjb2xvciA9PSAnSCcpLCBmaWxsID0gJ2RhcmtncmVlbicpDQoNCmBgYA0KDQoqIFTGsMahbmcgdOG7sSBuaMawIGJp4buDdSDEkeG7kyBz4buRIDE1LCBs4bqnbiBuw6B5IHRoYXkgdsOsIGzhu41jIGPDoWMga2ltIGPGsMahbmcgY8OzIG3DoHUgJ0QnIFbDgCAnSicgdGjDrCB0YSBz4bq9IGzhu41jIGPDoWMga2ltIGPGsMahbmcgY8OzIG3DoHUgJ0UnIFbDgCAnSCcuIA0KKiDhu54gYmnhu4N1IMSR4buTIG7DoHkgdGEgdGjhuqV5IG3DoHUgRSBraMO0bmcgcGjDom4gYuG7lSDhu58gbG/huqFpIGtpbSBjxrDGoW5nIGPDsyBraeG7g3UgY+G6r3QgRmFpciwgUHJlbWl1bSwgdsOgIG3DoHUgc+G6r2MgbsOgeSBwaMOibiBi4buVIG5oaeG7gXUgbmjhuqV0IOG7nyBraeG7g3UgY+G6r3QgSWRlYWwgZ2nhuqNtIGThuqduIHThu6sgVmVyeSBHb29kLCBHb29kLiBNw6B1IEggcGjDom4gYuG7lSDhu58gY8OhYyBraeG7g3UgY+G6r3QsIG5oaeG7gXUgbmjhuqV0IGzDoCBJZGVhbCB2w6AgZ2nhuqNtIGThuqduIHThu6sgUHJlbWl1bSwgVmVyeSBHb29kLCBHb29kIHbDoCB0aOG6pXAgbmjhuqV0IGzDoCBGYWlyLg0KDQoNCiMjIDE3LiBCaeG7g3UgxJHhu5MgMTc6DQoNCipUaMOqbSAxIGPhu5l0IGThu68gbGnDqnUgcHJpY2VDIHbDoG8gYuG7mSBk4buvIGxp4buHdSB0IMSR4buDIMSRw6FuaCBnacOhIGfDrWEgY+G6oyBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIHRoZW8gbeG7qWMgxJHhu5kgJ3LhuqV0IHRo4bqlcCcgJ3Ro4bqlcCcsICd24burYScsICdjYW8nIHbDoCAncuG6pXQgY2FvJyoNCg0KYGBge3J9DQpoaWV1IDwtIGhpZXUgJT4lIG11dGF0ZShwcmljZUMgPSBjdXQocHJpY2UsNSwgbGFiZWwgPSBjKCdy4bqldCB0aOG6pXAnLCAndGjhuqVwJywnduG7q2EnLCdjYW8nLCdy4bqldCBjYW8nKSkpDQpoaWV1ICU+JSBnZ3Bsb3QoYWVzKHggPSBwcmljZUMpKSArDQogIGdlb21fYmFyKGZpbGwgPSAnb3JhbmdlJykgKw0KICBsYWJzKHggPSAncGjDom4gbG/huqFpJywgeSA9ICdz4buRIGzGsOG7o25nJykNCmBgYA0KDQoqIEPDoWMgY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IMSR4buPLiBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPDsyBnacOhICdy4bqldCB0aOG6pXAnIGzDoCBs4bubbiBuaOG6pXQgdsOgIGdp4bqjbSBk4bqnbiB04burICd0aOG6pXAnLCAnduG7q2EnLCAnY2FvJyB2w6AgdGjhuqVwIG5o4bqldCBsw6AgbG/huqFpICdy4bqldCBjYW8nLg0KDQoNCg0KIyMgMTguIEJp4buDdSDEkeG7kyAxODoNCg0KKlBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSDEkeG7mSB0cm9uZyBzdeG7kXQgdsOgIG3DoHUgc+G6r2Mgc2F1IMSRw7MgdMOtbmggc+G7kSBsxrDhu6NuZyoNCg0KYGBge3J9DQp2byA8LSBoaWV1ICU+JSBncm91cF9ieShjbGFyaXR5LCBjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0Kdm8gJT4lIGdncGxvdChhZXMoeCA9IGNsYXJpdHksIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gdm8gJT4lIGZpbHRlcihjb2xvciA9PSAnRicpLCBmaWxsID0gJ2dyYXknKSArDQogIGdlb21fY29sKGRhdGEgPSB2byAlPiUgZmlsdGVyKGNvbG9yID09ICdKJyksIGZpbGwgPSAnYmx1ZScpDQoNCmBgYA0KDQoqIOG7niBiaeG7g3UgxJHhu5MgdHLDqm4gdGjDrCB0YSBn4bqvbiB4IGzDoCDEkeG7mSB0cm9uZyBzdeG7kXQsIHkgbMOgIHPhu5EgbMaw4bujbmcgY+G7p2EgdOG7q25nIGxv4bqhaS4NCiogVGEgc+G6vSBs4buNYyBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyBjw7MgbcOgdSAnRicsY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IMSR4buPIHbDoCBs4buNYyBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyBjw7MgbcOgdSBKLCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgeGFuaCBkxrDGoW5nLiANCiogUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgY8OhYyBtw6B1IHBow6JuIGLhu5Ug4bufIHThuqV0IGPhuqMgxJHhu5kgdHJvbmcgc3Xhu5F0LiBUcm9uZyDEkcOzIG3DoHUgSiBz4bq9IHBow6JuIGLhu5Ugbmhp4buBdSBuaOG6pXQg4bufIFNJMSBy4buTaSBnaeG6o20gZOG6p24gdOG7qyBWUzIsIFZTMSwgU0kyLCBXUzIsIFdTMSwgSUYgdsOgIHRo4bqlcCBuaOG6pXQgbMOgIEkxLiBDw7JuIG3DoHUgRiBQaMOibiBi4buVIG5oaeG7gXUgbmjhuqV0IOG7nyBWUzIgcuG7k2kgZ2nhuqNtIGThuqduIHThu6sgU0kxLCBTSTIsIFZTMSwgV1MyLCBXUzEsIElGIHbDoCB0aMOhcCBuaOG6pXQgbMOgIEkxLg0KDQoNCiMjIDE5LiBCaeG7g3UgxJHhu5MgMTk6DQoNCiAqUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IMSR4buZIHRyb25nIHN14buRdCB2w6Aga2nhu4N1IGPhuq90IHNhdSDEkcOzIHTDrW5oIHPhu5EgbMaw4bujbmcqDQoNCmBgYHtyfQ0KDQp2aCA8LSBoaWV1ICU+JSBncm91cF9ieShjbGFyaXR5LCBjdXQpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCnZoICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQsIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gdmggJT4lIGZpbHRlcihjbGFyaXR5ID09ICdJRicpLCBmaWxsID0gJ3JlZCcpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHZoICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnSTEnKSwgZmlsbCA9ICdncmVlbicpDQpgYGANCg0KKiDhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6Aga2nhu4N1IGPhuq90LCB5IGzDoCBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWkNCiogVGEgbOG7jWMgY8OhYyBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0ICdJRicgbMOgIGPDoWMgY+G7mXQgbcOgdSDEkeG7jywgY8OhYyBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0ICdJMScgbMOgIGPDoWMgY+G7mXQgbcOgdSB4YW5oLiBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0ICdJRicgY2jhu4kgcGjDom4gYuG7lSDhu58ga2nhu4N1IGPhuq90IElkZWFsLCBWZXJ5IEdvb2QsIFByZW1pdW0gdGhlbyBz4buRIGzGsOG7o25nIGdp4bqjbSBk4bqnbi4gDQoqIFRyb25nIGtoaSDEkcOzIMSR4buZIHRyb25nIHN14buRdCBJMSBwaMOibiBi4buVIOG7nyBt4buNaSBraeG7g3UgY+G6r3QsIG5oaeG7gXUgbmjhuqV0IGzDoCBQcmVtaXVtIHbDoCBnaeG6o20gZOG6p24gdOG7qyBGYWlyLCBJZGVhLCBHb29kLCB0aOG6pXAgbmjhuqV0IGzDoCBWZXJ5IEdvb2QuDQoNCg0KDQojIyAgMjAuIEJp4buDdSDEkeG7kyAyMDoNCg0KKkJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gbeG7kWkgcXVhbiBo4buHIGdp4buvYSB0cuG7jW5nIGzGsOG7o25nIHbDoCBz4buRIGzGsOG7o25nIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcqDQoNCg0KYGBge3J9DQpoaWV1MSA8LSBoaWV1ICU+JSBtdXRhdGUoY2FyYXRDID0gY3V0KGNhcmF0LDUsIGxhYmVsID0gYygnUuG6pXQgTmjhu48nLCAnTmjhu48nLCdW4burYScsJ0zhu5tuJywnUuG6pXQgTOG7m24nKSkpDQpoaWV1MSAlPiUgZ2dwbG90KGFlcyh4ID0gY2FyYXRDKSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ2RhcmtibHVlJykgKw0KICBsYWJzKHggPSAnVHLhu41uZyBsxrDGoW5nJywgeSA9ICdT4buRIEzGsOG7o25nJykNCmBgYA0KDQoqIFRhIGfhuq9uIHggbMOgICdMb+G6oWknLCB5IGzDoCAnU+G7kSBMxrDhu6NuZycuIA0KKiBU4bqhbyByYSBt4buZdCBiaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgdHLhu41uZyBsxrDhu6NuZyBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIHbDoCBz4buRIGzGsOG7o25nIGPhu6dhIGNow7puZyBn4buTbSA1IGPhu5l0IG3DoHUgxJHhu48uIFRy4bulYyBob8OgbmggKHgpIGzDoCB0cuG7jW5nIGzGsOG7o25nIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgbOG6p24gbMaw4bujdCBsw6Ag4oCYcuG6pXQgbmjhu4/igJksIOKAmG5o4buP4oCZLCDigJh24burYeKAmSwg4oCYbOG7m27igJksIOKAmHLhuqV0IGzhu5tu4oCZLiBUcuG7pWMgdHVuZyh5KSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIOG7qW5nIHbhu5tpIHRy4buNbmcgbMaw4bujbmcgxJHDsy4NCiogUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgdHLhu41uZyBsxrDhu6NuZyBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIGNoaeG6v20gxJFhIHPhu5EgKGtob+G6o25nIGjGoW4gNDAwMDAgdmnDqm4pIGzDoCBS4bqldCBOaOG7jyB2w6AgZ2nhuqNtIGThuqduIHh14buRbmcga2hpIMSRw7MgdHLhu41uZyBsxrDhu6NuZyBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIFLhuqV0IGzhu5tuIGzDoCDDrXQgbmjhuqV0DQoNCg0KIyMgMjEuIEJp4buDdSDEkeG7kyAyMToNCg0KICpCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIDQgxJHhurdjIHTDrW5oIMSR4buZIHRyb25nIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcqDQogDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQpoaWV1MiA8LSBoaWV1ICU+JSBncm91cF9ieShjb2xvciwgY2xhcml0eSkgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KYGBgDQoNCiogVOG6oW8gcmEgbeG7mXQgYmnhu4N1IMSR4buTIGfhu5NtIDQgY+G7mXQgeGFuaCBkxrDGoW5nLCDEkeG7jywgeGFuaCBsw6EsIHbDoG5nLCB0cuG7pWMgaG/DoG5oICh4KSDhu6luZyB24bubaSBt4bupYyDEkeG7mSB0aW5oIGtoaeG6v3QgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgbOG6p24gbMaw4bujdCBsw6AgVlMxLFZTMixWVlMyLFZWUzEsIHRy4bulYyB0dW5nICh5KSBz4buRIGzGsOG7o25nIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgxJHDsy4NCg0KKiBUaGVvIGJp4buDdSDEkeG7k8SR4buTIHRhIHRo4bqleSBsw6AgdmnDqm4ga2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIFZTMiBjw7Mgc+G7kSBsxrDhu6NuZyBuaGnhu4F1IG5o4bqldCAoZ+G6p24gMTI1MDAgdmnDqm4ga2ltIGPGsMahbmcpLiBUaeG6v3AgdGhlbyBsw6AgdmnDqm4ga2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIGzDoCBWUzEgKGtob+G6o25nIGjGoW4gNzUwMCB2acOqbikgdsOgIFZWUzIgKGtob+G6o25nIGjGoW4gNTAwMCB2acOqbikuIFbDoCB2acOqbiBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgVlZTMSBjaGnhur9tIHPhu5EgbMaw4bujbmcgw610IG5o4bqldCB0cm9uZyA0IGxv4bqhaSAoa2hv4bqjbmcgaMahbiAyNTAwIHZpw6puKS4NCg0KIyMgMjIuIEJp4buDdSDEkeG7kyAyMjoNCg0KKlBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIHRydW5nIGLDrG5oIGdpw6EgdGjDoG5oIHRoZW8gY2jhuqV0IGzGsOG7o25nIGPhuq90IChjdXQpKg0KDQpgYGB7cn0NCmhpZXUgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShtcD0gbWVhbihwcmljZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjdXQseSA9IG1wKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtcCwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnTWVhbiBQcmljZScpDQoNCmBgYA0KKiBUaGVvIGJp4buDdSDEkeG7kyB0YSB0aOG6pXk6TG/huqFpIEZhaXIgY8OzIG3hu6ljIGdpw6EgdHJ1bmcgYsOsbmggbMOgIDQzNTguNzYsIExv4bqhaSBHb29kIGPDsyBt4bupYyBnacOhIHRydW5nIGLDrG5oIGzDoCAzODI5LjgsIExv4bqhaSBWZXJ5IEdvb2QgY8OzIG3hu6ljIGdpw6EgdHJ1bmcgYsOsbmggbMOgIDM5ODEuNzYsIExv4bqhaSBQcmVtaXVtIGPDsyBt4bupYyBnacOhIHRydW5nIGLDrG5oIGzDoCA0NTg0Ljc2LCBMb+G6oWkgSWRlYWwgY8OzIG3hu6ljIGdpw6EgdHJ1bmcgYsOsbmggbMOgIDM0NTcuNTQuDQoNCiMjIDIzLiBCaeG7g3UgxJHhu5MgMjM6DQoNCipUxrDGoW5nIHThu7EgbmjGsCBiaeG7g3UgxJHhu5Mgc+G7kSAxOCwgbOG6p24gbsOgeSB0aGF5IHbDrCBs4buNYyBjw6FjIGtpbSBjxrDGoW5nIGPDsyBtw6B1ICdGJyBWw4AgJ0onIHRow6wgdGEgc+G6vSBs4buNYyBjw6FjIGtpbSBjxrDGoW5nIGPDsyBtw6B1ICdFJyBWw4AgJ0cnKg0KDQpgYGB7cn0NCnZvIDwtIGhpZXUgJT4lIGdyb3VwX2J5KGNsYXJpdHksIGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQp2byAlPiUgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSB2byAlPiUgZmlsdGVyKGNvbG9yID09ICdFJyksIGZpbGwgPSAnZ3JheScpICsNCiAgZ2VvbV9jb2woZGF0YSA9IHZvICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0cnKSwgZmlsbCA9ICdibHVlJykNCmBgYA0KDQoqIOG7niBiaeG7g3UgxJHhu5MgbsOgeSB0YSB0aOG6pXkgbcOgdSBFIGNo4buJIHBow6JuIGLhu5Ug4bufIGxv4bqhaSBraW0gY8awxqFuZyDEkeG7mSB0cm9uZyBzdeG7kXQgbMOgIFNJMixWUzIgdsOgIFNJMS4gQ8OybiBraW0gY8awxqFuZyBtw6B1IEcgcGjDom4gYuG7lSDhu58gdOG6pXQgY+G6oyDEkeG7mSB0cm9uZyBzdeG7kXQsIHRyb25nIMSRw7Mgbmhp4buBdSBuaOG6pXQgbMOgIFZTMiwgZ2nhuqNtIGThuqduIHThu6sgVlMxLCBTSTEsIFNJMiwgVlZTMiwgVlZTMSwgSUYgdsOgIHBow6JuIGLhu5Ugw610IG5o4bqldCDhu58gSTEuDQoNCg0KIyMgMjQuIEJp4buDdSDEkeG7kyAyNDoNCg0KKlBow6JuIGxv4bqhaSBydW5nIGLDrG5oIGdpw6Ega2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jLCBraeG7g3UgY+G6r3QgdsOgIMSR4buZIHRyb25nIHN14buRdCoNCg0KYGBge3J9DQpoaWV1ICU+JQ0KICBncm91cF9ieShjb2xvciwgY3V0LCBjbGFyaXR5KSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fcHJpY2UgPSBtZWFuKHByaWNlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNvbG9yLCB5ID0gbWVhbl9wcmljZSwgZmlsbCA9IGludGVyYWN0aW9uKGN1dCwgY2xhcml0eSkpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgeGxhYigiQ29sb3IiKSArDQogIHlsYWIoIkF2ZXJhZ2UgUHJpY2UiKSArDQogIGdndGl0bGUoIlRydW5nIGLDrG5oIGdpw6Ega2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jLCBraeG7g3UgY+G6r3QgdsOgIMSR4buZIHRyb25nIHN14buRdCIpICsNCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkN1dCAmIENsYXJpdHkiKQ0KYGBgDQoNCiMjIDI1LiBCaeG7g3UgxJHhu5MgMjU6DQoNCipQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyDEkeG7mSB0cm9uZyBzdeG7kXQgdsOgIHTDrW5oIHPhu5EgbMaw4bujbmcgY+G7p2EgY8OhYyBtw6B1Kg0KDQpgYGB7cn0NCmhpZXUgJT4lDQogIGdyb3VwX2J5KGN1dCwgY2xhcml0eSkgJT4lDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IGNvdW50LCBmaWxsID0gY2xhcml0eSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICB4bGFiKCJDdXQiKSArDQogIHlsYWIoIkNvdW50IikgKw0KICBnZ3RpdGxlKCJT4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90IHbDoCDEkeG7mSB0cm9uZyBzdeG7kXQiKSArDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJDbGFyaXR5IikNCmBgYA0KDQojIyAyNi4gQmnhu4N1IMSR4buTIDI2Og0KDQoqVMawxqFuZyB04buxIG5oxrAgYmnhu4N1IMSR4buTIHPhu5EgMTksIGzhuqduIG7DoHkgdGhheSB2w6wgbOG7jWMgY8OhYyBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0ICdpRicgVsOAICdpMScgdGjDrCB0YSBz4bq9IGzhu41jIGPDoWMga2ltIGPGsMahbmcgY8OzIMSR4buZIHRyb25nIHN14buRdCAnU0kxJyBWw4AgJ1NJMicqDQoNCmBgYHtyfQ0KdnRoIDwtIGhpZXUgJT4lIGdyb3VwX2J5KGNsYXJpdHksIGN1dCkgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KdnRoICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQsIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gdnRoICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnU0kxJyksIGZpbGwgPSAncmVkJykgKw0KICBnZW9tX2NvbChkYXRhID0gdnRoICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnU0kyJyksIGZpbGwgPSAnZ3JlZW4nKQ0KDQpgYGANCg0KKiDhu54gYmnhu4N1IMSR4buTIG7DoHkgdGEgdGjhuqV5IMSR4buZIHRyb25nIHN14buRdCBTSTEga2jDtG5nIHBow6JuIGLhu5Ug4bufIGxv4bqhaSBraW0gY8awxqFuZyBjw7Mga2nhu4N1IGPhuq90IEZhaXIsIHBow6JuIGLhu5Egbmhp4buBdSBuaOG6pXQg4bufIGtp4buDdSBj4bqvdCBJZGVhbCBnaeG6o20gZOG6p24gdOG7qyBWZXJ5IEdvb2QsIFByZW1pdW0gdsOgIHBow6JuIGLhu5Ugw610IG5o4bqldCDhu58ga2nhu4N1IGPhuq90IEdvb2QuIA0KKiBLaW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IFNJMiBwaMOibiBi4buVIOG7nyB04bqldCBj4bqjIGtp4buDdSBj4bqvdCwgbmhp4buBdSBuaOG6pXQg4bufIGtp4buDdSBj4bqvdCBQcmVtaXVtIGdp4bqjbSBk4bqnbiB04burIElkZWFsLCBWZXJ5IEdvb2QsIEdvb2QgdsOgIHBow6JuIGLhu5Ugw610IG5o4bqldCDhu58ga2nhu4N1IGPhuq90IEZhaXIuDQoNCg0KIyMgMjcuIEJp4buDdSDEkeG7kyAyNzoNCg0KKlBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdCB2w6AgbcOgdSBz4bqvYyBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nKg0KDQpgYGB7cn0NCmhpZXUgJT4lIGdyb3VwX2J5KGN1dCxjb2xvcikgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gbikpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgICBmYWNldF93cmFwKH5jb2xvcikgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCiogVGEgZ+G6r24geCBsw6AgbG/huqFpLCB5IGxhIHPhu5EgbMaw4bujbmcgdsOgIHRhIGNoaWEgdGjDoG5oIDcgYmnhu4N1IMSR4buTIHRoZW8gNyBsb+G6oWkgbcOgdSBz4bqvYyDEkeG7gyBzbyBzw6FuaC4gIA0KKiBRdWEgNyBiaeG7g3UgxJHhu5MgdGEgbmjhuq1uIHjDqXQgY8OhYyBtw6B1IHPhuq9jIHBow6JuIGLhu5Ugbmhp4buBdSBuaOG6pXQg4bufIGtpbSBjxrDGoW5nIGPDsyBraeG7g3UgY+G6r3QgSWRlYWwsIGdp4bqjbSBk4bqnbiBxdWEgY8OhYyBraeG7g3UgY+G6r3QgUHJlbWl1bSwgVmVyeSBHb29kLCBHb29kIHbDoCBwaMOibiBi4buVIMOtdCBuaOG6pXQg4bufIGtp4buDdSBj4bqvdCBGYWlyLg0KDQojIyAyOC4gQmnhu4N1IMSR4buTIDI4Og0KDQoqUGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90IHbDoCB0w61uaCB0cnVuZyBiw6xuaCB04bu3IGzhu4cgxJHhu5kgc8OidSAodHJ1bmcgYsOsbmggei94KSoNCg0KYGBge3J9DQpoaWV1ICU+JSBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2UobT0gbWVhbihkZXB0aCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjdXQseSA9IG0pKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAnZGFya2dyZXknKSArDQogIGxhYnMoeCA9ICdLaeG7g3UgY+G6r3QnLCB5ID0gJ01lYW4nKQ0KYGBgDQoNCioqKlRhIHBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdCB2w6AgdMOtbmggdHJ1bmcgYsOsbmggdOG7tyBs4buHIMSR4buZIHPDonUgKHRydW5nIGLDrG5oIHoveCkuIHRhIGfhuq9uIHggbMOgIGtp4buDdSBj4bqvdCwgeSBsw6AgdHJ1bmcgYsOsbmguIGPDoWMgc+G7kSBsaeG7h3UgxJHGsOG7o2MgbMOgbSB0csOybiAyIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuLCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBjw6FjaCBj4buZdCBk4buNYyAyIMSRxqFuIHbhu4sgdsOgIGPDsyBtw6B1IHhhbmggbMOhIGPDonkuIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgdGjhuqV5IGtp4buDdSBj4bqvdCBGYWlyIGPDsyDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIGzhu5tuIG5o4bqldCwgZ2nhuqNtIGThuqduIHThu6sgR29vZCwgVmVyeSBHb29kLCBJZGVhbCB2w6AgdGjhuqVwIG5o4bqldCBsw6AgUHJlbWl1bQ0KDQojIyAyOS4gIEJp4buDdSDEkeG7kyAyOToNCg0KKlBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIMSR4buZIHRyb25nIHN14buRdCoNCg0KYGBge3J9DQpoaWV1ICU+JSBnZ3Bsb3QoYWVzKHggPSBwcmljZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1MDAsIGZpbGwgPSAnZ3JlZW4nLCBjb2xvciA9ICdyZWQnKSArDQogIGxhYnMoeCA9ICdQcmljZScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiBUYSBn4bqvbiB4IGzDoCBnacOhIGPhu6dhIGtpbSBjxrDGoW5nICwgeSBsw6Agc+G7kSBsxrDhu6NuZy4gVHLhu6VjIGhvw6BuaCh4KSBsw6AgY8OhYyBt4bupYyBnacOhIGPhu6dhIGtpbSBjxrDGoW5nIHbDoCB0cuG7pWMgdHVuZyAoeSkgbMOgIHPhu5EgbMaw4bujbmcgY+G7p2EgY8OhYyB2acOqbiBraW0gY8awxqFuZyB0xrDGoW5nIOG7qW5nIHbhu5tpIGPDoWMgbeG7qWMgZ2nDoS4NCiogVGhlbyDEkeG7kyB0aOG7iyB0YSB0aOG6pXkga2hv4bqjbmcgZ2nDoSB04burIDAtNTAwMChVU0QpIGPDsyBz4buRIGzGsOG7o25nIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgbmhp4buBdSBuaOG6pXQgdsOgIHPDtCBsxrDhu6NuZyBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIGdp4bqjbSBk4bqnbiB24buBIHNhdSBraGkgbeG7qWMgZ2nDoSB0xINuZyBsw6puIMSR4bq/biBraG/huqNuZyBn4bqnbiAyMDAwMDAoVVNEKS4NCiMjIDMwLiBCaeG7g3UgxJHhu5MgMzA6DQoNCipQaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jIHbDoCB0w61uaCB0cnVuZyBiw6xuaCB04bu3IGzhu4cgxJHhu5kgc8OidSBj4bunYSB04burbmcgbG/huqFpKg0KDQpgYGB7cn0NCmhpZXUgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG0gPSBtZWFuKGRlcHRoKSkgJT4lDQogIGdncGxvdChhZXMoY29sb3IsbSkpICsNCiAgZ2VvbV9jb2woZmlsbD0nbGlnaHRwaW5rJykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobSwyKSksdmp1c3QgPSAyLCBjb2xvciA9ICdsaWdodHllbGxvdycpICsNCiAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKiBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyBjw7MgbcOgdSB4YW5oIGzDoSBjw6J5LCBjw6FjIGThu68gbGnhu4d1IGPDsyBtw6B1IMSR4buPLCDEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAyIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuIHbDoCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCAyIMSRxqFuIHbhu4suIA0KKiBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBjw6FjIGxv4bqhaSBtw6B1IGPhu6dhIGtpbSBjxrDGoW5nIHPhur0gY8OzIHjhuqVwIHjhu4kgdHJ1bmcgYsOsbmggdOG7tyBs4buHIMSR4buZIHPDonUgYuG6sW5nIG5oYXUuIFRyb25nIMSRw7MgY2FvIG5o4bqldCBsw6AgbcOgdSBKIHbDoCB0aOG6pXAgbmjhuqV0IGzDoCBtw6B1IEUuDQoNCg0K