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