library(DT)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.0 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.0
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
t<- diamonds
datatable(t)
## Warning in instance$preRenderHook(instance): It seems your data is too big for
## client-side DataTables. You may consider server-side processing:
## https://rstudio.github.io/DT/server.html
Sử dụng bộ dữ liệu có sẵn trong R
Bộ dữ liệu được dụng là bộ dữ liệu Diamonds có sẵn trong
R
Bộ dữ liệu diamonds trong R là một tập dữ liệu phổ biến được sử
dụng trong các ví dụ và hướng dẫn về phân tích dữ liệu. Nó bao gồm thông
tin về 53.940 viên kim cương cắt tròn, với 10 biến mô tả các đặc điểm
khác nhau của mỗi viên kim cương:
- carat: Trọng lượng của viên kim cương (carat)
- cut: Chất lượng đường cắt (Fair, Good, Very Good, Ideal,
Premium)
- color: Màu sắc của viên kim cương (từ D (tốt nhất) đến J (kém
nhất))
- price: Giá trị của viên kim cương (đơn vị USD)
- clarity: Độ trong suốt của viên kim cương (từ IF (tốt nhất) đến I1
(kém nhất))
- depth: Tỷ lệ phần trăm độ sâu (tính theo z / x)
- table: Chiều rộng của mặt bàn (tính theo % của đường kính)
- x: Chiều dài của viên kim cương (mm)
- y: Chiều rộng của viên kim cương (mm)
- z: Độ sâu của viên kim cương (mm)
## Thông tin cơ bản của bộ dữ liệu
is.data.frame(t)
## [1] TRUE
length(t)
## [1] 10
names(t)
## [1] "carat" "cut" "color" "clarity" "depth" "table" "price"
## [8] "x" "y" "z"
dim(t)
## [1] 53940 10
library(skimr)
skim(t)
Data summary
Name |
t |
Number of rows |
53940 |
Number of columns |
10 |
_______________________ |
|
Column type frequency: |
|
factor |
3 |
numeric |
7 |
________________________ |
|
Group variables |
None |
Variable type: factor
cut |
0 |
1 |
TRUE |
5 |
Ide: 21551, Pre: 13791, Ver: 12082, Goo: 4906 |
color |
0 |
1 |
TRUE |
7 |
G: 11292, E: 9797, F: 9542, H: 8304 |
clarity |
0 |
1 |
TRUE |
8 |
SI1: 13065, VS2: 12258, SI2: 9194, VS1: 8171 |
Variable type: numeric
carat |
0 |
1 |
0.80 |
0.47 |
0.2 |
0.40 |
0.70 |
1.04 |
5.01 |
▇▂▁▁▁ |
depth |
0 |
1 |
61.75 |
1.43 |
43.0 |
61.00 |
61.80 |
62.50 |
79.00 |
▁▁▇▁▁ |
table |
0 |
1 |
57.46 |
2.23 |
43.0 |
56.00 |
57.00 |
59.00 |
95.00 |
▁▇▁▁▁ |
price |
0 |
1 |
3932.80 |
3989.44 |
326.0 |
950.00 |
2401.00 |
5324.25 |
18823.00 |
▇▂▁▁▁ |
x |
0 |
1 |
5.73 |
1.12 |
0.0 |
4.71 |
5.70 |
6.54 |
10.74 |
▁▁▇▃▁ |
y |
0 |
1 |
5.73 |
1.14 |
0.0 |
4.72 |
5.71 |
6.54 |
58.90 |
▇▁▁▁▁ |
z |
0 |
1 |
3.54 |
0.71 |
0.0 |
2.91 |
3.53 |
4.04 |
31.80 |
▇▁▁▁▁ |
library(DT)
library(tidyverse)
t<- diamonds
datatable(t)
## Warning in instance$preRenderHook(instance): It seems your data is too big for
## client-side DataTables. You may consider server-side processing:
## https://rstudio.github.io/DT/server.html
Phân tích dữ liệu với Bar-Chart
Giới thiệu
Biểu đồ thanh (Bar chart) là một dạng biểu đồ thống kê thị trường
phổ biến, sử dụng các thanh dọc hoặc ngang để biểu diễn dữ liệu theo
thời gian hoặc theo các nhóm khác nhau. Mỗi thanh đại diện cho một giá
trị cụ thể, và độ dài của thanh thể hiện giá trị đó.
Ý nghĩa của biểu đồ thanh:
- So sánh dữ liệu: Biểu đồ thanh giúp so sánh trực quan các giá trị
khác nhau trong cùng một nhóm hoặc giữa các nhóm khác nhau.
- Xác định xu hướng: Biểu đồ thanh có thể giúp xác định xu hướng tăng
hoặc giảm của dữ liệu theo thời gian.
- Phân bố dữ liệu: Biểu đồ thanh giúp so sánh sự phân bố của dữ liệu
giữa các nhóm khác nhau.
library(dplyr)
library(tidyverse)
library(scales)
##
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
##
## discard
## The following object is masked from 'package:readr':
##
## col_factor
Vẽ Đồ Thị Dạng Bar Chart
Đồ Thị 1
t %>% group_by(cut) %>% summarise(n = n()) %>%
ggplot(aes(cut,n)) +
geom_col(fill='red') +
geom_text(aes(label = n),vjust = 2, color = 'blue') +
labs(x = 'Loại', y = 'Số lượng')
Nhận xét kết quả
Kết quả nhận được là một biểu đồ dạng Bar_Chart thể hiện gồm số lượng
của những loại kim cương(Fair(1610), Good(4906), Very good(12082),
Premium(13791), Ideal(21551)).Qua biểu đồ trên chúng ta sẽ thấy được số
lượng của Ideal chiếm nhiều nhất(21551) trong 5 loại
trên. Chiếm tỷ lệ thấp nhất là Fair với 1610 viên kim
cương . Số lượng kim cương giảm dần từ Ideal đến Fair. Có sự chênh lệch
lớn giữa loại lớn nhất và thấp nhất.
Đồ Thị 2
t %>% group_by(color) %>% summarise(n = n()) %>%
ggplot(aes(color,n)) +
geom_col(fill='red') +
geom_text(aes(label = n),vjust = 2, color = 'blue') +
labs(x = 'Loại', y = 'Số lượng')
Nhận xét kết quả - Kết quả nhận được là một
biểu đồ dạng Bar_Chart gồm 7 cột tương ứng với 7 màu D,E,F,G,H,I,J - Dựa
vào biểu đồ ta biết được số lượng của mỗi loại: - D có 6775 viên - E có
9797 viến - F có 9542 viến - G có 11292 viên - H có 8304 viên - I có
5422 viên - J có 2808 viên - Trong đó số lượng của G chiếm nhiều nhất
11292 kim cương, thấp nhất là J với 2808 viên
Đồ Thị 3
t %>% group_by(clarity) %>% summarise(n = n()) %>%
ggplot(aes(clarity,n)) +
geom_col(fill='red') +
geom_text(aes(label = n),vjust = 2, color = 'blue') +
labs(x = 'Loại', y = 'Số lượng')

Nhận xét kết quả - Kết quả nhận được là một
biểu đồ dạng Bar_Chart gồm 8 cột tương ứng với 8 độ trong suốt khác
nhau:I1, SI2, SI1, VS2, VS1, VVS2, VVS1, IF - I1 chiếm 741 viên kim
cương thấp nhất trong các loại - SI2 chiếm 9194 viên - SI1 chiếm 13065
viên nhiều nhất trong các loại - VS2 chiếm 12258 viên - VS1 chiếm 8171
viên - VVS2 chiếm 5066 viên - VVS1 chiếm 3655 viên - IF chiếm 1790
viên
Đồ Thị 4
t %>% group_by(clarity) %>% summarise(n = n()) %>%
ggplot(aes(clarity,n)) +
geom_col(fill='red') +
geom_text(aes(label = percent(n/length(t$carat))),vjust = 2, color = 'blue') +
labs(x = 'Loại', y = 'Số lượng')

Nhận xét kết quả
- Kết quả nhận được là một biểu đồ dạng Bar_Chart gồm 8 cột tương ứng
với 8 độ trong suốt khác nhau:I1, SI2, SI1, VS2, VS1, VVS2, VVS1, IF -
I1 chiếm 1,4% viên kim cương - SI2 chiếm 17% viên - SI1 chiếm 24,2% viên
nhiều nhất trong các loại - VS2 chiếm 22,7% viên - VS1 chiếm 15,1% viên
- VVS2 chiếm 9,4% viên - VVS1 chiếm 6,8% viên - IF chiếm 3,3% viên thấp
nhất trong các loại - Chênh lệch giữa SI1(nhiều nhất) và I1(thấp nhất)
là hơn 17 lần
Đồ Thị 5
t %>% group_by(cut) %>% summarise(n = n()) %>%
ggplot(aes(cut,n)) +
geom_col(fill='red') +
geom_text(aes(label = percent(n/length(t$carat))),vjust = 2, color = 'blue') +
labs(x = 'Loại', y = 'Số lượng')

Nhận xét kết quả
- Kết quả nhận được là một biểu đồ dạng Bar_Chart thể hiện gồm số lượng
của 5 loại kim cương: Fair, Good, Very good, Premium, Ideal. - Fair
chiếm 3% kim cương có tỷ trọng nhỏ nhất - Good chiếm 9.1% kim cương -
Very good chiếm 22.4% kim cương - Premium chiếm 25.6% kim cương - Ideal
chiếm 40% kim cương có tỷ trọng lớn nhất - Số lượng kim cương tăng dần
từ Fair đến Ideal - Số lượng loại lớn nhất(Ideal) và nhỏ nhất(Fair)
chênh lệch với nhau hơn 13 lần
Đồ Thị 6
t%>% group_by(cut) %>% summarise(v= var(carat)) %>%
ggplot(aes(x = cut,y = v)) +
geom_col(position = 'dodge') +
geom_text(aes(label = round(v,2)), vjust = 2, color = 'blue') +
labs(x = 'Loại', y = 'Số lượng')

Nhận xét kết quả
- Dây là là một biểu đò dang Bar_Chart thể hiện mức độ chenh lệch của
biến cut(chất lượn đường cắt) theo biến cut - Biểu đồ cho thấy mức độ
chênh lệch giữa các biến của “cut” dao động trong khoảng 0.19 đến 0.27 -
Nhóm “Fair và Premium” có mức độ chênh lệch cao nhất (khoảng 0.27 ). -
Nhóm “Ideal” có mức đọ chênh lệch thấp nhất (khoảng 0.19 ).
Đồ Thị 7
t %>% group_by(clarity,color) %>% summarise(n=n()) %>%
ggplot(aes(x = color,y = n)) +
geom_col(position = 'dodge') +
facet_wrap(~clarity) +
geom_text(aes(label = n),vjust = 0, color = 'blue') +
labs(x = 'color', y = 'Số lượng')
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
Nhận xét kết quả
- Ta nhận được là một biểu đồ dạng Bar_Chart thể hiện số lượng của các
loại kim cương trong biến color theo từng nhóm gồm 7 biểu đồ nhỏ tương
ứng với từng loại trong cột clarity(I1, SI2, SI1, VS2, VS1, VVS2, VVS1,
IF) - Qua đây ta sẽ thấy rõ độ phân tán về số lượng của của cột color
theo các nhóm clarity
Đồ Thị 8
t %>% group_by(clarity,color) %>% summarise(n=n()) %>%
ggplot(aes(x = clarity,y = n)) +
geom_col(position = 'dodge') +
facet_wrap(~color) +
geom_text(aes(label = n),vjust = 0, color = 'red') +
labs(x = 'clarity', y = 'Số lượng',title='Hình 1.10: Số lượng kim cương theo độ trong suốt và màu')
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.

Nhận xét kết quả
- Ta nhận được là một biểu đồ dạng Bar_Chart thể hiện số lượng của các
loại kim cương trong biến clarity theo từng nhóm gồm 7 biểu đồ nhỏ tương
ứng với từng loại trong cột color(D,E,F,G,H,I,J)
- Qua đây ta sẽ thấy rõ độ phân tán về số lượng của của cột clarity
theo các nhóm color
Đồ Thị 9
t%>% group_by(clarity,color)%>%summarise(m=mean(depth))%>%ggplot(aes(x=color, y= m))+
geom_col(position='dodge')+
facet_wrap(~clarity)+
geom_text(aes(label= round(m,1)), vjust=2, color='blue')+ labs(x= 'color', y= 'Meann')
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.

Nhận xét kết quả - Biểu đồ thể hiện mối
quan hệ giữa màu sắc(color) và độ sâu trung bình (Mean Depth) của kim
cương, phân theo độ trong suốt(Clarity). - Mỗi thanh màu đại diện cho độ
sâu trung bình của kim cương có cùng độ trong suốt và màu sắc. - Có thể
quan sát thấy sự khác biệt về độ sâu trung bình giữa các độ trong suốt
khác nhau trong cùng một màu sắc. - Qua biểu đồ trên ta thầy được giá
trị trung bình của độ sâu (depth) khá là ổn định dao động trong khoảng
61-64
Đồ Thị 10
t%>% group_by(clarity,color)%>%summarise(m=mean(depth))%>%ggplot(aes(x=clarity, y= m))+
geom_col(position='dodge')+
facet_wrap(~color)+
geom_text(aes(label= round(m,1)), vjust=2, color='blue')+ labs(x= 'clarity', y= 'Meann')
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.

Nhận xét biểu đồ
- Biểu đồ thể hiện mối quan hệ giữa độ trong suốt (Clarity) và độ sâu
trung bình (Mean Depth) của kim cương, phân theo màu sắc (Color).
- Mỗi thanh màu đại diện cho độ sâu trung bình của kim cương có cùng
độ trong suốt và màu sắc.
- Có thể quan sát thấy sự khác biệt về độ sâu trung bình giữa các độ
trong suốt khác nhau trong cùng một màu sắc.
- Qua biểu đồ trên ta thầy được giá trị trung bình của độ sâu (depth)
khá là ổn định dao động trong khoảng 61-64
Đồ Thị 11
a<- t %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
a %>% ggplot(aes(x = cut, y = n)) +
geom_col(data = a%>% filter(color == 'H'), fill = 'blue') +
geom_col(data = a%>% filter(color == 'F'), fill = 'red')+labs()
Nhận xét biểu đồ - Biểu đồ cho thấy số lượng
màu H theo cut(chất lượng) cực kỳ ít so với số lượng màu F theo cut(chất
lượng) ## Đồ Thị 12
t %>% ggplot(aes(x = price)) +
geom_histogram(binwidth = 400, fill = 'blue', color = 'red')
Nhận xét biểu đồ - Biểu đồ tăng từ phải sang
trái cho thấy số lượng viên kim cương có giá trị trên 5000 ít hơn số
viên kim cương có giá trị dưới 5000
Đồ Thị 13
t %>% ggplot(aes(x = price, fill = color)) +
geom_histogram(binwidth = 400)
Nhận xét biểu đồ - Biểu đồ thể hiện giá theo
các loại biến color(D,E,F,G,H,I,J) khác nhau ## Đồ Thị 14
t %>% ggplot(aes(x = price)) +
geom_histogram(binwidth = 400, fill = 'blue', color = 'red') +
facet_wrap(~color)
Nhận xét biểu đồ - 7 biểu đồ thể hiện giá theo
7 loại màu: D,E,F,G,H,I,J
BIỂU ĐỒ 15
t <- t %>% mutate(priceC = cut(price,5, label = c('rất thấp', 'thấp','vừa','cao','rất cao')))
t %>% ggplot(aes(x = priceC)) +
geom_bar(fill = 'red') +
labs(x = 'phân loại', y = 'số lượng')
Nhận xét kết quả
- Ta 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’. 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’
BIỂU ĐỒ 16
t <- diamonds
b <- t %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
b %>% ggplot(aes(x = cut, y = n)) +
geom_col(data = b %>% filter(color == 'D'), fill = 'red') +
geom_col(data = b %>% filter(color == 'J'), fill = 'blue')
Nhận xét kết quả
Ta phân loại kim cương theo kiểu cắt và màu sắc sau đó tính
số lượng . Ở biểu đồ trên thì ta gắn x là kiểu cắt, y là số lượng của
từng loại; ta sẽ lọc các loại kim cương có màu 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 # BIỂU ĐỒ 17
t <- diamonds
b <- t %>% group_by(cut, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
b %>% ggplot(aes(x = cut, y = n)) +
geom_col(data = b %>% filter(color == 'E'), fill = 'red') +
geom_col(data = b %>% filter(color == 'H'), fill = 'blue')

***Tương tự như biểu đồ số 17, 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 # BIỂU ĐỒ
18
b <- t %>% group_by(clarity, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
b %>% ggplot(aes(x = clarity, y = n)) +
geom_col(data = b %>% filter(color == 'F'), fill = 'red') +
geom_col(data = b %>% filter(color == 'J'), fill = 'blue')

Ta phân loại kim cương theo kiểu độ trong suốt và màu sắc
sau đó tính 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; 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.
BIỂU ĐỒ 19
b <- t %>% group_by(clarity, color) %>% summarise(n = n())
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
b %>% ggplot(aes(x = clarity, y = n)) +
geom_col(data = b %>% filter(color == 'E'), fill = 'red') +
geom_col(data = b %>% filter(color == 'G'), fill = 'blue')

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’. Ở
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.
BIỂU ĐỒ 20
c <- t %>% group_by(clarity, cut) %>% summarise(n = n())
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
c %>% ggplot(aes(x = cut, y = n)) +
geom_col(data = c %>% filter(clarity == 'IF'), fill = 'red') +
geom_col(data = c %>% filter(clarity == 'I1'), fill = 'blue')

Ta phân loại kim cương theo kiểu độ trong suốt và kiểu
cắt sau đó tính số lượng . Ở biểu đồ trên thì ta gắn x là kiểu cắt, y là
số lượng của từng loại; Ta 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.
BIỂU ĐỒ 21
f <- t %>% group_by(clarity, cut) %>% summarise(n = n())
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.
f %>% ggplot(aes(x = cut, y = n)) +
geom_col(data = f %>% filter(clarity == 'SI1'), fill = 'red') +
geom_col(data = f %>% filter(clarity == 'SI2'), fill = 'blue')

Tương tự như biểu đồ số 20, 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’. Ở 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.
BIỂU ĐỒ 22
t %>% group_by(cut) %>% summarise(n = n()) %>%
ggplot(aes(cut,n)) +
geom_col(fill='green') +
geom_text(aes(label = percent(n/length(t$carat))),vjust = 2, color = 'red') +
labs(x = 'Loại', y = 'Số lượng')

Ta phân loại kim cương theo kiểu cắt và tính số lượng của
các kiểu cắt. ta gắn x là ‘Loại’, y là ‘Số Lượng’. Các cột biểu đồ được
tô màu xanh lá cây, các số liệu là tỷ khối lượng của mỗi kiểu cắt, các
số liệu này có màu đỏ và được điều chỉnh vị trí dọc các cột dữ liệu với
đơn vị là 2. Qua biểu đồ trên ta thấy Kiểu cắt Ideal chiếm tỷ lệ cao
nhất về trọng lượng (đơn vị carat) và giảm dần từ Premium, Very Good,
Good và kiểu cắt Fair có tỷ lệ trọng lượng thấp nhất
BIỂU ĐỒ 23
t %>% group_by(color) %>% summarise(n = n()) %>%
ggplot(aes(color,n)) +
geom_col(fill='green') +
geom_text(aes(label = percent(n/length(t$carat))),vjust = 2, color = 'red') +
labs(x = 'Loại', y = 'Số lượng')

Ta phân loại kim cương theo kiểu màu sắc và tính số lượng
của các màu. ta gắn x là ‘Loại’, y là ‘Số Lượng’. Các cột biểu đồ được
tô màu xanh lá cây, các số liệu là tỷ lệ khối lượng của mỗi kiểu cắt,
các số liệu này có màu đỏ và được điều chỉnh vị trí dọc các cột dữ liệu
với đơn vị là 2. Qua biểu đồ trên ta thấy kim cương màu G chiếm tỷ lệ
cao nhất về trọng lượng(20,93), giảm dần là E, F, H, D, I và kim cương
màu J chiếm tỷ lệ thấp nhất (5,21%)
BIỂU ĐỒ 24
t %>% group_by(color) %>% summarise(n = n()) %>%
ggplot(aes(color,n)) +
geom_col(fill='green') +
geom_text(aes(label = percent(n/length(t$price))),vjust = 2, color = 'red') +
labs(x = 'Loại', y = 'Số lượng')

Ta phân loại kim cương theo kiểu màu sắc và tính số lượng
của các màu. ta gắn x là ‘Loại’, y là ‘Số Lượng’. Các cột biểu đồ được
tô màu xanh lá cây, các số liệu là tỷ lệ giá tiền của mỗi kiểu cắt, các
số liệu này có màu đỏ và được điều chỉnh vị trí dọc các cột dữ liệu với
đơn vị là 2. Qua biểu đồ trên ta thấy kim cương màu G chiếm tỷ lệ cao
nhất về giá(20,93%), giảm dần là E, F, H, D, I và kim cương màu J chiếm
tỷ lệ thấp nhất (5,21%)
BIỂU ĐỒ 25
t %>% group_by(clarity) %>% summarise(n = n()) %>%
ggplot(aes(clarity,n)) +
geom_col(fill='green') +
geom_text(aes(label = percent(n/length(t$price))),vjust = 2, color = 'red') +
labs(x = 'Loại', y = 'Số lượng')

Ta phân loại kim cương theo độ trong suốt và tính số
lượng của các màu. ta gắn x là ‘Loại’, y là ‘Số Lượng’. Các cột biểu đồ
được tô màu xanh lá cây, các số liệu là tỷ lệ giá tiền của mỗi loại kim
cương, các số liệu này có màu đỏ và được điều chỉnh vị trí dọc các cột
dữ liệu với đơn vị là 2. Qua biểu đồ trên ta thấy kim cương có độ trong
suốt SI1 chiếm tỷ lệ giá cao nhất (24,2%), giảm dần từ VS2, SI2, VS1,
VVS2, VVS1, IF, I1(1,4%)
BIỂU ĐỒ 26
t %>% group_by(cut) %>% summarise(n = n()) %>%
ggplot(aes(cut,n)) +
geom_col(fill='green') +
geom_text(aes(label = percent(n/length(t$price))),vjust = 2, color = 'red') +
labs(x = 'Loại', y = 'Số lượng')

BIỂU ĐỒ 27
t %>% group_by(cut,color) %>% summarise(n=n()) %>%
ggplot(aes(x = cut,y = n)) +
geom_col(position = 'dodge') +
facet_wrap(~color) +
labs(x = 'Loại', y = 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

Ta phân loại kim cương theo kiểu cắt và màu sắc sau đó
tính số lượng. ta gắn x là loại, y la số lượng 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
BIỂU ĐỒ 28
t %>% group_by(color) %>% summarise(m = mean(depth)) %>%
ggplot(aes(color,m)) +
geom_col(fill='green') +
geom_text(aes(label = round(m,2)),vjust = 2, color = 'red') +
labs(x = 'Loại', y = 'Số lượng')

Ta phân loại kim cương theo màu sắc và tính trung bình tỷ
lệ độ sâu của từng loại. Các cột biểu đồ có màu xanh 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.
BIỂU ĐỒ 29
t %>% ggplot(aes(x = clarity)) +
geom_bar() +
labs(x = 'Cấp độ tinh khiết', y = 'Số lượng') +
coord_flip() +
labs(title = 'Cấp độ tinh khiết của kim cương (biểu đồ ngang)')

Ta phân loại kim cương theo độ trong suốt. ta gắn x là
cấp độ tinh khiết, y là số lượng Và đây là biểu đồ ngang. Qua biểu đồ
trên ta thấy SI1 có độ tinh khiết cao nhất, giảm dần từ VS2, SI2, VS1,
VVS2, IF và I1 là kim cương có độ trong suốt thấp nhất
BIỂU ĐỒ 30
t %>% 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 = 'green') +
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
LS0tDQp0aXRsZTogIlBow6JuIHTDrWNoIGLhu5kgZOG7ryBsaeG7h3UgRGlhbW9uZHMiDQphdXRob3I6ICJUaGFuaCBUcuG7jW5nIg0KZGF0ZTogIjIwMjQtMDMtMDIiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgbnVtYmVyIHNlY3Rpb246IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KYGBge3J9DQpsaWJyYXJ5KERUKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQp0PC0gZGlhbW9uZHMNCmRhdGF0YWJsZSh0KQ0KYGBgDQojICoqKlPhu60gZOG7pW5nIGLhu5kgZOG7ryBsaeG7h3UgY8OzIHPhurVuIHRyb25nIFIqKioNCg0KICAtIELhu5kgZOG7ryBsaeG7h3UgxJHGsOG7o2MgZOG7pW5nIGzDoCBi4buZIGThu68gbGnhu4d1IERpYW1vbmRzIGPDsyBz4bq1biB0cm9uZyBSIA0KICAtIELhu5kgZOG7ryBsaeG7h3UgZGlhbW9uZHMgdHJvbmcgUiBsw6AgbeG7mXQgdOG6rXAgZOG7ryBsaeG7h3UgcGjhu5UgYmnhur9uIMSRxrDhu6NjIHPhu60gZOG7pW5nIHRyb25nIGPDoWMgdsOtIGThu6UgdsOgIGjGsOG7m25nIGThuqtuIHbhu4EgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UuIE7DsyBiYW8gZ+G7k20gdGjDtG5nIHRpbiB24buBIDUzLjk0MCB2acOqbiBraW0gY8awxqFuZyBj4bqvdCB0csOybiwgduG7m2kgMTAgYmnhur9uIG3DtCB04bqjIGPDoWMgxJHhurdjIMSRaeG7g20ga2jDoWMgbmhhdSBj4bunYSBt4buXaSB2acOqbiBraW0gY8awxqFuZzoNCg0KICAgICAtIGNhcmF0OiBUcuG7jW5nIGzGsOG7o25nIGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nIChjYXJhdCkNCiAgICAgLSBjdXQ6IENo4bqldCBsxrDhu6NuZyDEkcaw4budbmcgY+G6r3QgKEZhaXIsIEdvb2QsIFZlcnkgR29vZCwgSWRlYWwsIFByZW1pdW0pDQogICAgIC0gY29sb3I6IE3DoHUgc+G6r2MgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgKHThu6sgRCAodOG7kXQgbmjhuqV0KSDEkeG6v24gSiAoa8OpbSBuaOG6pXQpKQ0KICAgICAtIHByaWNlOiBHacOhIHRy4buLIGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nICjEkcahbiB24buLIFVTRCkNCiAgICAgLSBjbGFyaXR5OiDEkOG7mSB0cm9uZyBzdeG7kXQgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgKHThu6sgSUYgKHThu5F0IG5o4bqldCkgxJHhur9uIEkxIChrw6ltIG5o4bqldCkpDQogICAgIC0gZGVwdGg6IFThu7cgbOG7hyBwaOG6p24gdHLEg20gxJHhu5kgc8OidSAodMOtbmggdGhlbyB6IC8geCkNCiAgICAgLSB0YWJsZTogQ2hp4buBdSBy4buZbmcgY+G7p2EgbeG6t3QgYsOgbiAodMOtbmggdGhlbyAlIGPhu6dhIMSRxrDhu51uZyBrw61uaCkNCiAgICAgLSB4OiBDaGnhu4F1IGTDoGkgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgKG1tKQ0KICAgICAtIHk6IENoaeG7gXUgcuG7mW5nIGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nIChtbSkNCiAgICAgLSB6OiDEkOG7mSBzw6J1IGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nIChtbSkNCg0KICAjIyAqKlRow7RuZyB0aW4gY8ahIGLhuqNuIGPhu6dhIGLhu5kgZOG7ryBsaeG7h3UqKg0KYGBge3J9DQppcy5kYXRhLmZyYW1lKHQpDQpsZW5ndGgodCkNCm5hbWVzKHQpDQpkaW0odCkNCmxpYnJhcnkoc2tpbXIpDQpza2ltKHQpDQpgYGANCiANCg0KYGBge3J9DQpsaWJyYXJ5KERUKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQp0PC0gZGlhbW9uZHMNCmRhdGF0YWJsZSh0KQ0KYGBgDQoNCiMgKioqUGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgduG7m2kgQmFyLUNoYXJ0KioqDQoNCiMjICoqR2nhu5tpIHRoaeG7h3UqKg0KICAtIEJp4buDdSDEkeG7kyB0aGFuaCAoQmFyIGNoYXJ0KSBsw6AgbeG7mXQgZOG6oW5nIGJp4buDdSDEkeG7kyB0aOG7kW5nIGvDqiB0aOG7iyB0csaw4budbmcgcGjhu5UgYmnhur9uLCBz4butIGThu6VuZyBjw6FjIHRoYW5oIGThu41jIGhv4bq3YyBuZ2FuZyDEkeG7gyBiaeG7g3UgZGnhu4VuIGThu68gbGnhu4d1IHRoZW8gdGjhu51pIGdpYW4gaG/hurdjIHRoZW8gY8OhYyBuaMOzbSBraMOhYyBuaGF1LiBN4buXaSB0aGFuaCDEkeG6oWkgZGnhu4duIGNobyBt4buZdCBnacOhIHRy4buLIGPhu6UgdGjhu4MsIHbDoCDEkeG7mSBkw6BpIGPhu6dhIHRoYW5oIHRo4buDIGhp4buHbiBnacOhIHRy4buLIMSRw7MuDQoNCiAgLSDDnSBuZ2jEqWEgY+G7p2EgYmnhu4N1IMSR4buTIHRoYW5oOg0KICAgIC0gU28gc8OhbmggZOG7ryBsaeG7h3U6IEJp4buDdSDEkeG7kyB0aGFuaCBnacO6cCBzbyBzw6FuaCB0cuG7sWMgcXVhbiBjw6FjIGdpw6EgdHLhu4sga2jDoWMgbmhhdSB0cm9uZyBjw7luZyBt4buZdCBuaMOzbSBob+G6t2MgZ2nhu69hIGPDoWMgbmjDs20ga2jDoWMgbmhhdS4NCiAgICAtIFjDoWMgxJHhu4tuaCB4dSBoxrDhu5tuZzogQmnhu4N1IMSR4buTIHRoYW5oIGPDsyB0aOG7gyBnacO6cCB4w6FjIMSR4buLbmggeHUgaMaw4bubbmcgdMSDbmcgaG/hurdjIGdp4bqjbSBj4bunYSBk4buvIGxp4buHdSB0aGVvIHRo4budaSBnaWFuLg0KICAgIC0gUGjDom4gYuG7kSBk4buvIGxp4buHdTogQmnhu4N1IMSR4buTIHRoYW5oIGdpw7pwIHNvIHPDoW5oIHPhu7EgcGjDom4gYuG7kSBj4bunYSBk4buvIGxp4buHdSBnaeG7r2EgY8OhYyBuaMOzbSBraMOhYyBuaGF1Lg0KICAgIA0KICAgIA0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCmBgYA0KIyAqKlbhur0gxJDhu5MgVGjhu4sgROG6oW5nIEJhciBDaGFydCoqDQoNCiMjIMSQ4buTIFRo4buLIDENCmBgYHtyfQ0KdCAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICBnZW9tX2NvbChmaWxsPSdyZWQnKSArDQogICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdibHVlJykgKw0KICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KKioqTmjhuq1uIHjDqXQga+G6v3QgcXXhuqMqKioNCg0KICAgS+G6v3QgcXXhuqMgbmjhuq1uIMSRxrDhu6NjIGzDoCBt4buZdCBiaeG7g3UgxJHhu5MgZOG6oW5nIEJhcl9DaGFydCB0aOG7gyBoaeG7h24gZ+G7k20gc+G7kSBsxrDhu6NuZyBj4bunYSBuaOG7r25nIGxv4bqhaSBraW0gY8awxqFuZyhGYWlyKDE2MTApLCBHb29kKDQ5MDYpLCBWZXJ5IGdvb2QoMTIwODIpLCBQcmVtaXVtKDEzNzkxKSwgSWRlYWwoMjE1NTEpKS5RdWEgYmnhu4N1IMSR4buTIHRyw6puIGNow7puZyB0YSBz4bq9IHRo4bqleSDEkcaw4bujYyBz4buRIGzGsOG7o25nIGPhu6dhICoqSWRlYWwqKiBjaGnhur9tIG5oaeG7gXUgbmjhuqV0KDIxNTUxKSB0cm9uZyA1IGxv4bqhaSB0csOqbi4gQ2hp4bq/bSB04bu3IGzhu4cgdGjhuqVwIG5o4bqldCBsw6AgKipGYWlyKiogduG7m2kgMTYxMCB2acOqbiBraW0gY8awxqFuZyAuIFPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgZ2nhuqNtIGThuqduIHThu6sgSWRlYWwgxJHhur9uIEZhaXIuIEPDsyBz4buxIGNow6puaCBs4buHY2ggbOG7m24gZ2nhu69hIGxv4bqhaSBs4bubbiBuaOG6pXQgdsOgIHRo4bqlcCBuaOG6pXQuDQogICANCiMjIMSQ4buTIFRo4buLIDINCmBgYHtyfQ0KdCAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY29sb3IsbikpICsNCiAgZ2VvbV9jb2woZmlsbD0ncmVkJykgKw0KICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnYmx1ZScpICsNCiAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCioqKk5o4bqtbiB4w6l0IGvhur90IHF14bqjKioqDQogICAtIEvhur90IHF14bqjIG5o4bqtbiDEkcaw4bujYyBsw6AgbeG7mXQgYmnhu4N1IMSR4buTIGThuqFuZyBCYXJfQ2hhcnQgZ+G7k20gNyBj4buZdCB0xrDGoW5nIOG7qW5nIHbhu5tpIDcgbcOgdSBELEUsRixHLEgsSSxKDQogICAtIEThu7FhIHbDoG8gYmnhu4N1IMSR4buTIHRhIGJp4bq/dCDEkcaw4bujYyBz4buRIGzGsOG7o25nIGPhu6dhIG3hu5dpIGxv4bqhaToNCiAgICAgLSBEIGPDsyA2Nzc1IHZpw6puDQogICAgIC0gRSBjw7MgOTc5NyB2aeG6v24NCiAgICAgLSBGIGPDsyA5NTQyIHZp4bq/bg0KICAgICAtIEcgY8OzIDExMjkyIHZpw6puDQogICAgIC0gSCBjw7MgODMwNCB2acOqbg0KICAgICAtIEkgY8OzIDU0MjIgdmnDqm4NCiAgICAgLSBKIGPDsyAyODA4IHZpw6puIA0KICAgICAtIFRyb25nIMSRw7Mgc+G7kSBsxrDhu6NuZyBj4bunYSBHIGNoaeG6v20gbmhp4buBdSBuaOG6pXQgMTEyOTIga2ltIGPGsMahbmcsICB0aOG6pXAgbmjhuqV0IGzDoCBKIHbhu5tpIDI4MDggdmnDqm4NCiAgICAgDQojIyDEkOG7kyBUaOG7iyAzDQpgYGB7cn0NCnQgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY2xhcml0eSxuKSkgKw0KICBnZW9tX2NvbChmaWxsPSdyZWQnKSArDQogICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdibHVlJykgKw0KICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYCAgICAgDQogIA0KKioqTmjhuq1uIHjDqXQga+G6v3QgcXXhuqMqKioNCiAgIC0gS+G6v3QgcXXhuqMgbmjhuq1uIMSRxrDhu6NjIGzDoCBt4buZdCBiaeG7g3UgxJHhu5MgZOG6oW5nIEJhcl9DaGFydCBn4buTbSA4IGPhu5l0IHTGsMahbmcg4bupbmcgduG7m2kgOCDEkeG7mSB0cm9uZyBzdeG7kXQga2jDoWMgbmhhdTpJMSwgU0kyLCBTSTEsIFZTMiwgVlMxLCBWVlMyLCBWVlMxLCBJRg0KICAgLSBJMSBjaGnhur9tIDc0MSB2acOqbiBraW0gY8awxqFuZyB0aOG6pXAgbmjhuqV0IHRyb25nIGPDoWMgbG/huqFpDQogICAtIFNJMiBjaGnhur9tIDkxOTQgdmnDqm4gDQogICAtIFNJMSBjaGnhur9tIDEzMDY1IHZpw6puIG5oaeG7gXUgbmjhuqV0IHRyb25nIGPDoWMgbG/huqFpDQogICAtIFZTMiBjaGnhur9tIDEyMjU4IHZpw6puDQogICAtIFZTMSBjaGnhur9tIDgxNzEgdmnDqm4gDQogICAtIFZWUzIgY2hp4bq/bSA1MDY2IHZpw6puIA0KICAgLSBWVlMxIGNoaeG6v20gMzY1NSB2acOqbiANCiAgIC0gSUYgY2hp4bq/bSAxNzkwIHZpw6puIA0KICAgDQojIyDEkOG7kyBUaOG7iyA0DQpgYGB7cn0NCnQgJT4lIGdyb3VwX2J5KGNsYXJpdHkpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoY2xhcml0eSxuKSkgKw0KICBnZW9tX2NvbChmaWxsPSdyZWQnKSArDQogICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGVyY2VudChuL2xlbmd0aCh0JGNhcmF0KSkpLHZqdXN0ID0gMiwgY29sb3IgPSAnYmx1ZScpICsNCiAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGAgICAgIA0KICANCioqKk5o4bqtbiB4w6l0IGvhur90IHF14bqjKioqICAgDQogICAgLSBL4bq/dCBxdeG6oyBuaOG6rW4gxJHGsOG7o2MgbMOgIG3hu5l0IGJp4buDdSDEkeG7kyBk4bqhbmcgQmFyX0NoYXJ0IGfhu5NtIDggY+G7mXQgdMawxqFuZyDhu6luZyB24bubaSA4IMSR4buZIHRyb25nIHN14buRdCBraMOhYyBuaGF1OkkxLCBTSTIsIFNJMSwgVlMyLCBWUzEsIFZWUzIsIFZWUzEsIElGDQogICAtIEkxIGNoaeG6v20gMSw0JSB2acOqbiBraW0gY8awxqFuZw0KICAgLSBTSTIgY2hp4bq/bSAxNyUgdmnDqm4gDQogICAtIFNJMSBjaGnhur9tIDI0LDIlIHZpw6puIG5oaeG7gXUgbmjhuqV0IHRyb25nIGPDoWMgbG/huqFpDQogICAtIFZTMiBjaGnhur9tIDIyLDclIHZpw6puDQogICAtIFZTMSBjaGnhur9tIDE1LDElIHZpw6puIA0KICAgLSBWVlMyIGNoaeG6v20gOSw0JSB2acOqbiANCiAgIC0gVlZTMSBjaGnhur9tIDYsOCUgdmnDqm4gDQogICAtIElGIGNoaeG6v20gMywzJSB2acOqbiB0aOG6pXAgbmjhuqV0IHRyb25nIGPDoWMgbG/huqFpDQogICAtIENow6puaCBs4buHY2ggZ2nhu69hIFNJMShuaGnhu4F1IG5o4bqldCkgdsOgIEkxKHRo4bqlcCBuaOG6pXQpIGzDoCBoxqFuIDE3IGzhuqduDQoNCiMjIMSQ4buTIFRo4buLIDUNCmBgYHtyfQ0KdCAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGN1dCxuKSkgKw0KICBnZW9tX2NvbChmaWxsPSdyZWQnKSArDQogICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGVyY2VudChuL2xlbmd0aCh0JGNhcmF0KSkpLHZqdXN0ID0gMiwgY29sb3IgPSAnYmx1ZScpICsNCiAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGAgICAgIA0KICANCioqKk5o4bqtbiB4w6l0IGvhur90IHF14bqjKioqICAgDQogICAtIEvhur90IHF14bqjIG5o4bqtbiDEkcaw4bujYyBsw6AgbeG7mXQgYmnhu4N1IMSR4buTIGThuqFuZyBCYXJfQ2hhcnQgdGjhu4MgaGnhu4duIGfhu5NtIHPhu5EgbMaw4bujbmcgY+G7p2EgNSBsb+G6oWkga2ltIGPGsMahbmc6IEZhaXIsIEdvb2QsIFZlcnkgZ29vZCwgUHJlbWl1bSwgSWRlYWwuDQogICAtIEZhaXIgY2hp4bq/bSAzJSBraW0gY8awxqFuZyBjw7MgdOG7tyB0cuG7jW5nIG5o4buPIG5o4bqldA0KICAgICAtIEdvb2QgY2hp4bq/bSA5LjElIGtpbSBjxrDGoW5nDQogICAgIC0gVmVyeSBnb29kIGNoaeG6v20gMjIuNCUga2ltIGPGsMahbmcgDQogICAgIC0gUHJlbWl1bSBjaGnhur9tIDI1LjYlIGtpbSBjxrDGoW5nDQogICAgIC0gSWRlYWwgY2hp4bq/bSA0MCUga2ltIGPGsMahbmcgY8OzIHThu7cgdHLhu41uZyBs4bubbiBuaOG6pXQNCiAgICAgLSBT4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHTEg25nIGThuqduIHThu6sgRmFpciDEkeG6v24gSWRlYWwNCiAgICAgLSBT4buRIGzGsOG7o25nIGxv4bqhaSBs4bubbiBuaOG6pXQoSWRlYWwpIHbDoCBuaOG7jyBuaOG6pXQoRmFpcikgY2jDqm5oIGzhu4djaCB24bubaSBuaGF1IGjGoW4gKioxMyBs4bqnbioqDQoNCiMjIMSQ4buTIFRo4buLIDYNCmBgYHtyfQ0KdCU+JSBncm91cF9ieShjdXQpICU+JSBzdW1tYXJpc2Uodj0gdmFyKGNhcmF0KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gdikpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQodiwyKSksIHZqdXN0ID0gMiwgY29sb3IgPSAnYmx1ZScpICsNCiAgICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKioqTmjhuq1uIHjDqXQga+G6v3QgcXXhuqMqKiogICANCi0gRMOieSBsw6AgbMOgIG3hu5l0IGJp4buDdSDEkcOyIGRhbmcgQmFyX0NoYXJ0IHRo4buDIGhp4buHbiBt4bupYyDEkeG7mSBjaGVuaCBs4buHY2ggY+G7p2EgYmnhur9uIGN1dChjaOG6pXQgbMaw4bujbiDEkcaw4budbmcgY+G6r3QpIHRoZW8gYmnhur9uIGN1dA0KICAtIEJp4buDdSDEkeG7kyBjaG8gdGjhuqV5IG3hu6ljIMSR4buZIGNow6puaCBs4buHY2ggZ2nhu69hIGPDoWMgYmnhur9uIGPhu6dhICJjdXQiIGRhbyDEkeG7mW5nIHRyb25nIGtob+G6o25nIDAuMTkgxJHhur9uIDAuMjcgDQogIC0gTmjDs20gIkZhaXIgdsOgIFByZW1pdW0gIiBjw7MgbeG7qWMgxJHhu5kgY2jDqm5oIGzhu4djaCBjYW8gbmjhuqV0IChraG/huqNuZyAwLjI3ICkuDQogIC0gTmjDs20gIklkZWFsIiBjw7MgbeG7qWMgxJHhu40gY2jDqm5oIGzhu4djaCB0aOG6pXAgbmjhuqV0IChraG/huqNuZyAwLjE5ICkuDQogIA0KIyMgxJDhu5MgVGjhu4sgNw0KYGBge3J9DQp0ICU+JSBncm91cF9ieShjbGFyaXR5LGNvbG9yKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY29sb3IseSA9IG4pKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgZmFjZXRfd3JhcCh+Y2xhcml0eSkgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDAsIGNvbG9yID0gJ2JsdWUnKSArDQogICAgbGFicyh4ID0gJ2NvbG9yJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KKioqTmjhuq1uIHjDqXQga+G6v3QgcXXhuqMqKiogIA0KIC0gIFRhIG5o4bqtbiDEkcaw4bujYyBsw6AgbeG7mXQgYmnhu4N1IMSR4buTIGThuqFuZyBCYXJfQ2hhcnQgdGjhu4MgaGnhu4duIHPhu5EgbMaw4bujbmcgY+G7p2EgY8OhYyBsb+G6oWkga2ltIGPGsMahbmcgdHJvbmcgYmnhur9uIGNvbG9yIHRoZW8gdOG7q25nIG5ow7NtIGfhu5NtIDcgYmnhu4N1IMSR4buTIG5o4buPIHTGsMahbmcg4bupbmcgduG7m2kgdOG7q25nIGxv4bqhaSB0cm9uZyBj4buZdCBjbGFyaXR5KEkxLCBTSTIsIFNJMSwgVlMyLCBWUzEsIFZWUzIsIFZWUzEsIElGKQ0KIC0gUXVhIMSRw6J5IHRhIHPhur0gdGjhuqV5IHLDtSDEkeG7mSBwaMOibiB0w6FuIHbhu4Egc+G7kSBsxrDhu6NuZyBj4bunYSBj4bunYSBj4buZdCBjb2xvciB0aGVvIGPDoWMgbmjDs20gY2xhcml0eQ0KDQojIyDEkOG7kyBUaOG7iyA4DQpgYGB7cn0NCnQgJT4lIGdyb3VwX2J5KGNsYXJpdHksY29sb3IpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjbGFyaXR5LHkgPSBuKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmNvbG9yKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAncmVkJykgKw0KICAgIGxhYnMoeCA9ICdjbGFyaXR5JywgeSA9ICdT4buRIGzGsOG7o25nJyx0aXRsZT0nSMOsbmggMS4xMDogU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIMSR4buZIHRyb25nIHN14buRdCB2w6AgbcOgdScpDQpgYGANCiANCioqKk5o4bqtbiB4w6l0IGvhur90IHF14bqjKioqICANCg0KICAtICBUYSBuaOG6rW4gxJHGsOG7o2MgbMOgIG3hu5l0IGJp4buDdSDEkeG7kyBk4bqhbmcgQmFyX0NoYXJ0IHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGPhu6dhIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIHRyb25nIGJp4bq/biBjbGFyaXR5IHRoZW8gdOG7q25nIG5ow7NtIGfhu5NtIDcgYmnhu4N1IMSR4buTIG5o4buPIHTGsMahbmcg4bupbmcgduG7m2kgdOG7q25nIGxv4bqhaSB0cm9uZyBj4buZdCBjb2xvcihELEUsRixHLEgsSSxKKQ0KIC0gUXVhIMSRw6J5IHRhIHPhur0gdGjhuqV5IHLDtSDEkeG7mSBwaMOibiB0w6FuIHbhu4Egc+G7kSBsxrDhu6NuZyBj4bunYSBj4bunYSBj4buZdCBjbGFyaXR5IHRoZW8gY8OhYyBuaMOzbSBjb2xvcg0KIA0KIyMgxJDhu5MgVGjhu4sgOQ0KYGBge3J9DQp0JT4lIGdyb3VwX2J5KGNsYXJpdHksY29sb3IpJT4lc3VtbWFyaXNlKG09bWVhbihkZXB0aCkpJT4lZ2dwbG90KGFlcyh4PWNvbG9yLCB5PSBtKSkrDQogIGdlb21fY29sKHBvc2l0aW9uPSdkb2RnZScpKw0KICBmYWNldF93cmFwKH5jbGFyaXR5KSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD0gcm91bmQobSwxKSksIHZqdXN0PTIsIGNvbG9yPSdibHVlJykrIGxhYnMoeD0gJ2NvbG9yJywgeT0gJ01lYW5uJykNCmBgYA0KDQoqKipOaOG6rW4geMOpdCBr4bq/dCBxdeG6oyoqKiANCi0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIG3DoHUgc+G6r2MoY29sb3IpIHbDoCDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIChNZWFuIERlcHRoKSBj4bunYSBraW0gY8awxqFuZywgcGjDom4gdGhlbyDEkeG7mSB0cm9uZyBzdeG7kXQoQ2xhcml0eSkuDQotIE3hu5dpIHRoYW5oIG3DoHUgxJHhuqFpIGRp4buHbiBjaG8gxJHhu5kgc8OidSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyBjw7MgY8O5bmcgxJHhu5kgdHJvbmcgc3Xhu5F0IHbDoCBtw6B1IHPhuq9jLg0KLSBDw7MgdGjhu4MgcXVhbiBzw6F0IHRo4bqleSBz4buxIGtow6FjIGJp4buHdCB24buBIMSR4buZIHPDonUgdHJ1bmcgYsOsbmggZ2nhu69hIGPDoWMgxJHhu5kgdHJvbmcgc3Xhu5F0IGtow6FjIG5oYXUgdHJvbmcgY8O5bmcgbeG7mXQgbcOgdSBz4bqvYy4NCi0gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6p3kgxJHGsOG7o2MgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSDEkeG7mSBzw6J1IChkZXB0aCkga2jDoSBsw6Ag4buVbiDEkeG7i25oIGRhbyDEkeG7mW5nIHRyb25nIGtob+G6o25nIDYxLTY0DQoNCiMjIMSQ4buTIFRo4buLIDEwDQpgYGB7cn0NCnQlPiUgZ3JvdXBfYnkoY2xhcml0eSxjb2xvciklPiVzdW1tYXJpc2UobT1tZWFuKGRlcHRoKSklPiVnZ3Bsb3QoYWVzKHg9Y2xhcml0eSwgeT0gbSkpKw0KICBnZW9tX2NvbChwb3NpdGlvbj0nZG9kZ2UnKSsNCiAgZmFjZXRfd3JhcCh+Y29sb3IpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPSByb3VuZChtLDEpKSwgdmp1c3Q9MiwgY29sb3I9J2JsdWUnKSsgbGFicyh4PSAnY2xhcml0eScsIHk9ICdNZWFubicpDQpgYGANCg0KKioqTmjhuq1uIHjDqXQgYmnhu4N1IMSR4buTKioqDQoNCi0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIMSR4buZIHRyb25nIHN14buRdCAoQ2xhcml0eSkgdsOgIMSR4buZIHPDonUgdHJ1bmcgYsOsbmggKE1lYW4gRGVwdGgpIGPhu6dhIGtpbSBjxrDGoW5nLCBwaMOibiB0aGVvIG3DoHUgc+G6r2MgKENvbG9yKS4NCi0gTeG7l2kgdGhhbmggbcOgdSDEkeG6oWkgZGnhu4duIGNobyDEkeG7mSBzw6J1IHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIGPDsyBjw7luZyDEkeG7mSB0cm9uZyBzdeG7kXQgdsOgIG3DoHUgc+G6r2MuDQotIEPDsyB0aOG7gyBxdWFuIHPDoXQgdGjhuqV5IHPhu7Ega2jDoWMgYmnhu4d0IHbhu4EgxJHhu5kgc8OidSB0cnVuZyBiw6xuaCBnaeG7r2EgY8OhYyDEkeG7mSB0cm9uZyBzdeG7kXQga2jDoWMgbmhhdSB0cm9uZyBjw7luZyBt4buZdCBtw6B1IHPhuq9jLg0KLSBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqneSDEkcaw4bujYyBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIMSR4buZIHPDonUgKGRlcHRoKSBraMOhIGzDoCDhu5VuIMSR4buLbmggZGFvIMSR4buZbmcgdHJvbmcga2hv4bqjbmcgNjEtNjQNCg0KIyMgxJDhu5MgVGjhu4sgMTENCmBgYHtyfQ0KYTwtIHQgJT4lIGdyb3VwX2J5KGN1dCwgY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCmEgJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IG4pKSArDQogIGdlb21fY29sKGRhdGEgPSAgYSU+JSBmaWx0ZXIoY29sb3IgPT0gJ0gnKSwgZmlsbCA9ICdibHVlJykgKw0KICBnZW9tX2NvbChkYXRhID0gIGElPiUgZmlsdGVyKGNvbG9yID09ICdGJyksIGZpbGwgPSAncmVkJykrbGFicygpDQpgYGANCioqKk5o4bqtbiB4w6l0IGJp4buDdSDEkeG7kyoqKg0KLSBCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSBz4buRIGzGsOG7o25nIG3DoHUgSCB0aGVvIGN1dChjaOG6pXQgbMaw4bujbmcpIGPhu7FjIGvhu7Mgw610IHNvIHbhu5tpIHPhu5EgbMaw4bujbmcgbcOgdSBGIHRoZW8gY3V0KGNo4bqldCBsxrDhu6NuZykgDQojIyDEkOG7kyBUaOG7iyAxMg0KYGBgIHtyfQ0KdCAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNDAwLCBmaWxsID0gJ2JsdWUnLCBjb2xvciA9ICdyZWQnKQ0KYGBgDQoqKipOaOG6rW4geMOpdCBiaeG7g3UgxJHhu5MqKioNCi0gQmnhu4N1IMSR4buTIHTEg25nIHThu6sgcGjhuqNpIHNhbmcgdHLDoWkgY2hvIHRo4bqleSBz4buRIGzGsOG7o25nIHZpw6puIGtpbSBjxrDGoW5nIGPDsyBnacOhIHRy4buLIHRyw6puIDUwMDAgw610IGjGoW4gc+G7kSB2acOqbiBraW0gY8awxqFuZyBjw7MgZ2nDoSB0cuG7iyBkxrDhu5tpIDUwMDANCg0KIyMgxJDhu5MgVGjhu4sgMTMNCmBgYHtyfQ0KdCAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UsIGZpbGwgPSBjb2xvcikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA0MDApDQpgYGANCioqKk5o4bqtbiB4w6l0IGJp4buDdSDEkeG7kyoqKg0KLSBCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGdpw6EgdGhlbyBjw6FjIGxv4bqhaSBiaeG6v24gY29sb3IoRCxFLEYsRyxILEksSikga2jDoWMgbmhhdQ0KIyMgxJDhu5MgVGjhu4sgMTQNCmBgYHtyfQ0KdCAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNDAwLCBmaWxsID0gJ2JsdWUnLCBjb2xvciA9ICdyZWQnKSArDQogIGZhY2V0X3dyYXAofmNvbG9yKQ0KYGBgDQoqKipOaOG6rW4geMOpdCBiaeG7g3UgxJHhu5MqKioNCi0gNyBiaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGdpw6EgdGhlbyA3IGxv4bqhaSBtw6B1OiBELEUsRixHLEgsSSxKDQoNCiMgQknhu4JVIMSQ4buSIDE1DQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCnQgPC0gdCAlPiUgbXV0YXRlKHByaWNlQyA9IGN1dChwcmljZSw1LCBsYWJlbCA9IGMoJ3LhuqV0IHRo4bqlcCcsICd0aOG6pXAnLCd24burYScsJ2NhbycsJ3LhuqV0IGNhbycpKSkNCnQgJT4lIGdncGxvdChhZXMoeCA9IHByaWNlQykpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICdyZWQnKSArDQogIGxhYnMoeCA9ICdwaMOibiBsb+G6oWknLCB5ID0gJ3Phu5EgbMaw4bujbmcnKQ0KYGBgDQoqKipOaOG6rW4geMOpdCBr4bq/dCBxdeG6oyoqKiAgDQotIFRhIHRow6ptIDEgY+G7mXQgZOG7ryBsacOqdSBwcmljZUMgdsOgbyBi4buZIGThu68gbGnhu4d1IHQgxJHhu4MgxJHDoW5oIGdpw6EgR8OtYSBj4bqjIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyBt4bupYyDEkeG7mSAncuG6pXQgdGjhuqVwJyAndGjhuqVwJywgJ3bhu6thJywgJ2NhbycgdsOgICdy4bqldCBjYW8nLiBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyBjw7MgbcOgdSDEkeG7jy4gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBjw7MgZ2nDoSAncuG6pXQgdGjhuqVwJyBsw6AgbOG7m24gbmjhuqV0IHbDoCBnaeG6o20gZOG6p24gdOG7qyAndGjhuqVwJywgJ3bhu6thJywgJ2NhbycgdsOgIHRo4bqlcCBuaOG6pXQgbMOgIGxv4bqhaSAncuG6pXQgY2FvJw0KDQojIEJJ4buCVSDEkOG7kiAxNg0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQp0IDwtIGRpYW1vbmRzIA0KYiA8LSB0ICU+JSBncm91cF9ieShjdXQsIGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQpiICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQsIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gYiAlPiUgZmlsdGVyKGNvbG9yID09ICdEJyksIGZpbGwgPSAncmVkJykgKw0KICBnZW9tX2NvbChkYXRhID0gYiAlPiUgZmlsdGVyKGNvbG9yID09ICdKJyksIGZpbGwgPSAnYmx1ZScpDQpgYGANCioqKk5o4bqtbiB4w6l0IGvhur90IHF14bqjKioqICANCioqKlRhIHBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdCB2w6AgbcOgdSBz4bqvYyBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nIC4g4bueIGJp4buDdSDEkeG7kyB0csOqbiB0aMOsIHRhIGfhuq9uIHggbMOgIGtp4buDdSBj4bqvdCwgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpOyB0YSBz4bq9IGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEQsY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IMSR4buPIHbDoCBs4buNYyBjw6FjIGxv4bqhaSBraW0gY8awxqFuZyBjw7MgbcOgdSBKLCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgeGFuaCBkxrDGoW5nLiBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIMSRw6MgbOG7jWMgxJHGsOG7o2Mgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBtw6B1IEQgcGjDom4gYuG7lSDDrXQgbmjhuqV0IOG7nyBraeG7g3UgY+G6r3QgRmFpciB2w6AgdMSDbmcgZOG6p24gbMOqbiB04burIEdvb2QsIFZlcnkgR29vZCwgUHJlbWl1bSwgdsOgIG5oaeG7gXUgbmjhuqV0IGzDoCBJZGVhbC4gVsOgIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY8OzIG3DoHUgSiBjxaluZyBwaOG6qW4gYuG7lSB0xrDGoW5nIHThu7EgbmjGsCBraW0gY8awxqFuZyBjw7MgbcOgdSBEKioqDQojIEJJ4buCVSDEkOG7kiAxNw0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQp0IDwtIGRpYW1vbmRzIA0KYiA8LSB0ICU+JSBncm91cF9ieShjdXQsIGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQpiICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXQsIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gYiAlPiUgZmlsdGVyKGNvbG9yID09ICdFJyksIGZpbGwgPSAncmVkJykgKw0KICBnZW9tX2NvbChkYXRhID0gYiAlPiUgZmlsdGVyKGNvbG9yID09ICdIJyksIGZpbGwgPSAnYmx1ZScpDQoNCmBgYA0KDQoqKipUxrDGoW5nIHThu7EgbmjGsCBiaeG7g3UgxJHhu5Mgc+G7kSAxNywgbOG6p24gbsOgeSB0aGF5IHbDrCBs4buNYyBjw6FjIGtpbSBjxrDGoW5nIGPDsyBtw6B1ICdEJyBWw4AgJ0onIHRow6wgdGEgc+G6vSBs4buNYyBjw6FjIGtpbSBjxrDGoW5nIGPDsyBtw6B1ICdFJyBWw4AgJ0gnLiDhu54gYmnhu4N1IMSR4buTIG7DoHkgdGEgdGjhuqV5IG3DoHUgRSBraMO0bmcgcGjDom4gYuG7lSDhu58gbG/huqFpIGtpbSBjxrDGoW5nIGPDsyBraeG7g3UgY+G6r3QgRmFpciwgUHJlbWl1bSwgdsOgIG3DoHUgc+G6r2MgbsOgeSBwaMOibiBi4buVIG5oaeG7gXUgbmjhuqV0IOG7nyBraeG7g3UgY+G6r3QgSWRlYWwgZ2nhuqNtIGThuqduIHThu6sgVmVyeSBHb29kLCBHb29kLiBNw6B1IEggcGjDom4gYuG7lSDhu58gY8OhYyBraeG7g3UgY+G6r3QsIG5oaeG7gXUgbmjhuqV0IGzDoCBJZGVhbCB2w6AgZ2nhuqNtIGThuqduIHThu6sgUHJlbWl1bSwgVmVyeSBHb29kLCBHb29kIHbDoCB0aOG6pXAgbmjhuqV0IGzDoCBGYWlyDQojIEJJ4buCVSDEkOG7kiAxOA0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQpiIDwtIHQgJT4lIGdyb3VwX2J5KGNsYXJpdHksIGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQpiICU+JSBnZ3Bsb3QoYWVzKHggPSBjbGFyaXR5LCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGIgJT4lIGZpbHRlcihjb2xvciA9PSAnRicpLCBmaWxsID0gJ3JlZCcpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGIgJT4lIGZpbHRlcihjb2xvciA9PSAnSicpLCBmaWxsID0gJ2JsdWUnKQ0KDQpgYGANCg0KKioqVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IMSR4buZIHRyb25nIHN14buRdCB2w6AgbcOgdSBz4bqvYyBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nIC4g4bueIGJp4buDdSDEkeG7kyB0csOqbiB0aMOsIHRhIGfhuq9uIHggbMOgIMSR4buZIHRyb25nIHN14buRdCwgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpOyB0YSBz4bq9IGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGPDsyBtw6B1ICdGJyxj4buZdCBiaeG7g3UgxJHhu5MgY8OzIG3DoHUgxJHhu48gdsOgIGzhu41jIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGPDsyBtw6B1IEosIGJp4buDdSDEkeG7kyBjw7MgbcOgdSB4YW5oIGTGsMahbmcuICBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBjw6FjIG3DoHUgcGjDom4gYuG7lSDhu58gdOG6pXQgY+G6oyDEkeG7mSB0cm9uZyBzdeG7kXQuIFRyb25nIMSRw7MgbcOgdSBKIHPhur0gcGjDom4gYuG7lSBuaGnhu4F1IG5o4bqldCDhu58gU0kxIHLhu5NpIGdp4bqjbSBk4bqnbiB04burIFZTMiwgVlMxLCBTSTIsIFdTMiwgV1MxLCBJRiB2w6AgdGjhuqVwIG5o4bqldCBsw6AgSTEuIEPDsm4gbcOgdSBGIFBow6JuIGLhu5Ugbmhp4buBdSBuaOG6pXQg4bufIFZTMiBy4buTaSBnaeG6o20gZOG6p24gdOG7qyBTSTEsIFNJMiwgVlMxLCBXUzIsIFdTMSwgSUYgdsOgIHRow6FwIG5o4bqldCBsw6AgSTEuKioqDQoNCiMgQknhu4JVIMSQ4buSIDE5DQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCmIgPC0gdCAlPiUgZ3JvdXBfYnkoY2xhcml0eSwgY29sb3IpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkNCmIgJT4lIGdncGxvdChhZXMoeCA9IGNsYXJpdHksIHkgPSBuKSkgKw0KICBnZW9tX2NvbChkYXRhID0gYiAlPiUgZmlsdGVyKGNvbG9yID09ICdFJyksIGZpbGwgPSAncmVkJykgKw0KICBnZW9tX2NvbChkYXRhID0gYiAlPiUgZmlsdGVyKGNvbG9yID09ICdHJyksIGZpbGwgPSAnYmx1ZScpDQpgYGANCg0KKioqVMawxqFuZyB04buxIG5oxrAgYmnhu4N1IMSR4buTIHPhu5EgMTgsIGzhuqduIG7DoHkgdGhheSB2w6wgbOG7jWMgY8OhYyBraW0gY8awxqFuZyBjw7MgbcOgdSAnRicgVsOAICdKJyB0aMOsIHRhIHPhur0gbOG7jWMgY8OhYyBraW0gY8awxqFuZyBjw7MgbcOgdSAnRScgVsOAICdHJy4g4bueIGJp4buDdSDEkeG7kyBuw6B5IHRhIHRo4bqleSBtw6B1IEUgY2jhu4kgcGjDom4gYuG7lSDhu58gbG/huqFpIGtpbSBjxrDGoW5nIMSR4buZIHRyb25nIHN14buRdCBsw6AgU0kyLFZTMiB2w6AgU0kxLiBDw7JuIGtpbSBjxrDGoW5nIG3DoHUgRyBwaMOibiBi4buVIOG7nyB04bqldCBj4bqjIMSR4buZIHRyb25nIHN14buRdCwgdHJvbmcgxJHDsyBuaGnhu4F1IG5o4bqldCBsw6AgVlMyLCBnaeG6o20gZOG6p24gdOG7qyBWUzEsIFNJMSwgU0kyLCBWVlMyLCBWVlMxLCBJRiB2w6AgcGjDom4gYuG7lSDDrXQgbmjhuqV0IOG7nyBJMS4qKioNCg0KIyBCSeG7glUgxJDhu5IgMjANCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KDQpjIDwtIHQgJT4lIGdyb3VwX2J5KGNsYXJpdHksIGN1dCkgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KYyAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0LCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGMgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdJRicpLCBmaWxsID0gJ3JlZCcpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGMgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdJMScpLCBmaWxsID0gJ2JsdWUnKQ0KYGBgDQoNCioqKlRhIHBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSDEkeG7mSB0cm9uZyBzdeG7kXQgdsOgIGtp4buDdSBj4bqvdCBzYXUgxJHDsyB0w61uaCBz4buRIGzGsOG7o25nIC4g4bueIGJp4buDdSDEkeG7kyB0csOqbiB0aMOsIHRhIGfhuq9uIHggbMOgIGtp4buDdSBj4bqvdCwgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbG/huqFpOyBUYSBs4buNYyBjw6FjIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgJ0lGJyBsw6AgY8OhYyBj4buZdCBtw6B1IMSR4buPLCBjw6FjIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgJ0kxJyBsw6AgY8OhYyBj4buZdCBtw6B1IHhhbmguIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgdGjhuqV5IGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgJ0lGJyBjaOG7iSBwaMOibiBi4buVIOG7nyBraeG7g3UgY+G6r3QgSWRlYWwsIFZlcnkgR29vZCwgUHJlbWl1bSB0aGVvIHPhu5EgbMaw4bujbmcgZ2nhuqNtIGThuqduLiBUcm9uZyBraGkgxJHDsyDEkeG7mSB0cm9uZyBzdeG7kXQgSTEgcGjDom4gYuG7lSDhu58gbeG7jWkga2nhu4N1IGPhuq90LCBuaGnhu4F1IG5o4bqldCBsw6AgUHJlbWl1bSB2w6AgZ2nhuqNtIGThuqduIHThu6sgRmFpciwgSWRlYSwgR29vZCwgdGjhuqVwIG5o4bqldCBsw6AgVmVyeSBHb29kLioqKg0KDQojIEJJ4buCVSDEkOG7kiAyMQ0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQpmIDwtIHQgJT4lIGdyb3VwX2J5KGNsYXJpdHksIGN1dCkgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KZiAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0LCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGYgJT4lIGZpbHRlcihjbGFyaXR5ID09ICdTSTEnKSwgZmlsbCA9ICdyZWQnKSArDQogIGdlb21fY29sKGRhdGEgPSBmICU+JSBmaWx0ZXIoY2xhcml0eSA9PSAnU0kyJyksIGZpbGwgPSAnYmx1ZScpDQoNCmBgYA0KDQoqKipUxrDGoW5nIHThu7EgbmjGsCBiaeG7g3UgxJHhu5Mgc+G7kSAyMCwgbOG6p24gbsOgeSB0aGF5IHbDrCBs4buNYyBjw6FjIGtpbSBjxrDGoW5nIGPDsyDEkeG7mSB0cm9uZyBzdeG7kXQgJ2lGJyBWw4AgJ2kxJyB0aMOsIHRhIHPhur0gbOG7jWMgY8OhYyBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0ICdTSTEnIFbDgCAnU0kyJy4g4bueIGJp4buDdSDEkeG7kyBuw6B5IHRhIHRo4bqleSDEkeG7mSB0cm9uZyBzdeG7kXQgU0kxIGtow7RuZyBwaMOibiBi4buVIOG7nyBsb+G6oWkga2ltIGPGsMahbmcgY8OzIGtp4buDdSBj4bqvdCBGYWlyLCBwaMOibiBi4buRIG5oaeG7gXUgbmjhuqV0IOG7nyBraeG7g3UgY+G6r3QgSWRlYWwgZ2nhuqNtIGThuqduIHThu6sgVmVyeSBHb29kLCBQcmVtaXVtIHbDoCBwaMOibiBi4buVIMOtdCBuaOG6pXQg4bufIGtp4buDdSBj4bqvdCBHb29kLiBLaW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IFNJMiBwaMOibiBi4buVIOG7nyB04bqldCBj4bqjIGtp4buDdSBj4bqvdCwgbmhp4buBdSBuaOG6pXQg4bufIGtp4buDdSBj4bqvdCBQcmVtaXVtIGdp4bqjbSBk4bqnbiB04burIElkZWFsLCBWZXJ5IEdvb2QsIEdvb2QgdsOgIHBow6JuIGLhu5Ugw610IG5o4bqldCDhu58ga2nhu4N1IGPhuq90IEZhaXIuKioqDQoNCiMgQknhu4JVIMSQ4buSIDIyDQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCnQgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjdXQsbikpICsNCiAgZ2VvbV9jb2woZmlsbD0nZ3JlZW4nKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKHQkY2FyYXQpKSksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCioqKlRhIHBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdCB2w6AgdMOtbmggc+G7kSBsxrDhu6NuZyBj4bunYSBjw6FjIGtp4buDdSBj4bqvdC4gdGEgZ+G6r24geCBsw6AgJ0xv4bqhaScsIHkgbMOgICdT4buRIEzGsOG7o25nJy4gQ8OhYyBj4buZdCBiaeG7g3UgxJHhu5MgxJHGsOG7o2MgdMO0IG3DoHUgeGFuaCBsw6EgY8OieSwgY8OhYyBz4buRIGxp4buHdSBsw6AgdOG7tyBraOG7kWkgbMaw4bujbmcgY+G7p2EgbeG7l2kga2nhu4N1IGPhuq90LCBjw6FjIHPhu5EgbGnhu4d1IG7DoHkgY8OzIG3DoHUgxJHhu48gdsOgIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCAgduG7iyB0csOtIGThu41jIGPDoWMgY+G7mXQgZOG7ryBsaeG7h3UgduG7m2kgxJHGoW4gduG7iyBsw6AgMi4gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgS2nhu4N1IGPhuq90IElkZWFsIGNoaeG6v20gdOG7tyBs4buHIGNhbyBuaOG6pXQgduG7gSB0cuG7jW5nIGzGsOG7o25nICjEkcahbiB24buLIGNhcmF0KSB2w6AgZ2nhuqNtIGThuqduIHThu6sgUHJlbWl1bSwgVmVyeSBHb29kLCBHb29kIHbDoCBraeG7g3UgY+G6r3QgRmFpciBjw7MgdOG7tyBs4buHIHRy4buNbmcgbMaw4bujbmcgdGjhuqVwIG5o4bqldCoqKg0KDQojIEJJ4buCVSDEkOG7kiAyMw0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQp0ICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjb2xvcixuKSkgKw0KICBnZW9tX2NvbChmaWxsPSdncmVlbicpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgodCRjYXJhdCkpKSx2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKioqVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IG3DoHUgc+G6r2MgdsOgIHTDrW5oIHPhu5EgbMaw4bujbmcgY+G7p2EgY8OhYyBtw6B1LiB0YSBn4bqvbiB4IGzDoCAnTG/huqFpJywgeSBsw6AgJ1Phu5EgTMaw4bujbmcnLiBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyDEkcaw4bujYyB0w7QgbcOgdSB4YW5oIGzDoSBjw6J5LCBjw6FjIHPhu5EgbGnhu4d1IGzDoCB04bu3IGzhu4cga2jhu5FpIGzGsOG7o25nIGPhu6dhIG3hu5dpIGtp4buDdSBj4bqvdCwgY8OhYyBz4buRIGxp4buHdSBuw6B5IGPDsyBtw6B1IMSR4buPIHbDoCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggIHbhu4sgdHLDrSBk4buNYyBjw6FjIGPhu5l0IGThu68gbGnhu4d1IHbhu5tpIMSRxqFuIHbhu4sgbMOgIDIuIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgdGjhuqV5IGtpbSBjxrDGoW5nIG3DoHUgRyBjaGnhur9tIHThu7cgbOG7hyBjYW8gbmjhuqV0IHbhu4EgdHLhu41uZyBsxrDhu6NuZygyMCw5MyksIGdp4bqjbSBk4bqnbiBsw6AgRSwgRiwgSCwgRCwgSSB2w6Aga2ltIGPGsMahbmcgbcOgdSBKIGNoaeG6v20gdOG7tyBs4buHIHRo4bqlcCBuaOG6pXQgKDUsMjElKSoqKg0KDQojIEJJ4buCVSDEkOG7kiAyNA0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQp0ICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjb2xvcixuKSkgKw0KICBnZW9tX2NvbChmaWxsPSdncmVlbicpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgodCRwcmljZSkpKSx2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpICsNCiAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKioqVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IG3DoHUgc+G6r2MgdsOgIHTDrW5oIHPhu5EgbMaw4bujbmcgY+G7p2EgY8OhYyBtw6B1LiB0YSBn4bqvbiB4IGzDoCAnTG/huqFpJywgeSBsw6AgJ1Phu5EgTMaw4bujbmcnLiBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyDEkcaw4bujYyB0w7QgbcOgdSB4YW5oIGzDoSBjw6J5LCBjw6FjIHPhu5EgbGnhu4d1IGzDoCB04bu3IGzhu4cgZ2nDoSB0aeG7gW4gY+G7p2EgbeG7l2kga2nhu4N1IGPhuq90LCBjw6FjIHPhu5EgbGnhu4d1IG7DoHkgY8OzIG3DoHUgxJHhu48gdsOgIMSRxrDhu6NjIMSRaeG7gXUgY2jhu4luaCAgduG7iyB0csOtIGThu41jIGPDoWMgY+G7mXQgZOG7ryBsaeG7h3UgduG7m2kgxJHGoW4gduG7iyBsw6AgMi4gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkga2ltIGPGsMahbmcgbcOgdSBHIGNoaeG6v20gdOG7tyBs4buHIGNhbyBuaOG6pXQgduG7gSBnacOhKDIwLDkzJSksIGdp4bqjbSBk4bqnbiBsw6AgRSwgRiwgSCwgRCwgSSB2w6Aga2ltIGPGsMahbmcgbcOgdSBKIGNoaeG6v20gdOG7tyBs4buHIHRo4bqlcCBuaOG6pXQgKDUsMjElKSoqKg0KDQojIEJJ4buCVSDEkOG7kiAyNQ0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQp0ICU+JSBncm91cF9ieShjbGFyaXR5KSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGNsYXJpdHksbikpICsNCiAgZ2VvbV9jb2woZmlsbD0nZ3JlZW4nKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKHQkcHJpY2UpKSksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCioqKlRhIHBow6JuIGxv4bqhaSBraW0gY8awxqFuZyB0aGVvIMSR4buZIHRyb25nIHN14buRdCB2w6AgdMOtbmggc+G7kSBsxrDhu6NuZyBj4bunYSBjw6FjIG3DoHUuIHRhIGfhuq9uIHggbMOgICdMb+G6oWknLCB5IGzDoCAnU+G7kSBMxrDhu6NuZycuIEPDoWMgY+G7mXQgYmnhu4N1IMSR4buTIMSRxrDhu6NjIHTDtCBtw6B1IHhhbmggbMOhIGPDonksIGPDoWMgc+G7kSBsaeG7h3UgbMOgIHThu7cgbOG7hyBnacOhIHRp4buBbiBj4bunYSBt4buXaSBsb+G6oWkga2ltIGPGsMahbmcsIGPDoWMgc+G7kSBsaeG7h3UgbsOgeSBjw7MgbcOgdSDEkeG7jyB2w6AgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oICB24buLIHRyw60gZOG7jWMgY8OhYyBj4buZdCBk4buvIGxp4buHdSB24bubaSDEkcahbiB24buLIGzDoCAyLiBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IFNJMSBjaGnhur9tIHThu7cgbOG7hyBnacOhIGNhbyBuaOG6pXQgKDI0LDIlKSwgZ2nhuqNtIGThuqduIHThu6sgVlMyLCBTSTIsIFZTMSwgVlZTMiwgVlZTMSwgSUYsIEkxKDEsNCUpKioqDQoNCiMgQknhu4JVIMSQ4buSIDI2DQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCnQgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjdXQsbikpICsNCiAgZ2VvbV9jb2woZmlsbD0nZ3JlZW4nKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKHQkcHJpY2UpKSksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KDQpgYGANCg0KIyBCSeG7glUgxJDhu5IgMjcNCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KdCAlPiUgZ3JvdXBfYnkoY3V0LGNvbG9yKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBuKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmNvbG9yKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KKioqVGEgcGjDom4gbG/huqFpIGtpbSBjxrDGoW5nIHRoZW8ga2nhu4N1IGPhuq90IHbDoCBtw6B1IHPhuq9jIHNhdSDEkcOzIHTDrW5oIHPhu5EgbMaw4bujbmcuIHRhIGfhuq9uIHggbMOgIGxv4bqhaSwgeSBsYSBz4buRIGzGsOG7o25nIHbDoCB0YSBjaGlhIHRow6BuaCA3IGJp4buDdSDEkeG7kyB0aGVvIDcgbG/huqFpIG3DoHUgc+G6r2MgxJHhu4Mgc28gc8OhbmguIFF1YSA3IGJp4buDdSDEkeG7kyB0YSBuaOG6rW4geMOpdCBjw6FjIG3DoHUgc+G6r2MgcGjDom4gYuG7lSBuaGnhu4F1IG5o4bqldCDhu58ga2ltIGPGsMahbmcgY8OzIGtp4buDdSBj4bqvdCBJZGVhbCwgZ2nhuqNtIGThuqduIHF1YSBjw6FjIGtp4buDdSBj4bqvdCBQcmVtaXVtLCBWZXJ5IEdvb2QsIEdvb2QgdsOgIHBow6JuIGLhu5Ugw610IG5o4bqldCDhu58ga2nhu4N1IGPhuq90IEZhaXIgKioqDQoNCiMgQknhu4JVIMSQ4buSIDI4DQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCg0KdCAlPiUgZ3JvdXBfYnkoY29sb3IpICU+JSBzdW1tYXJpc2UobSA9IG1lYW4oZGVwdGgpKSAlPiUNCiAgZ2dwbG90KGFlcyhjb2xvcixtKSkgKw0KICBnZW9tX2NvbChmaWxsPSdncmVlbicpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sMikpLHZqdXN0ID0gMiwgY29sb3IgPSAncmVkJykgKw0KICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQoqKipUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jIHbDoCB0w61uaCB0cnVuZyBiw6xuaCB04bu3IGzhu4cgxJHhu5kgc8OidSBj4bunYSB04burbmcgbG/huqFpLiBDw6FjIGPhu5l0IGJp4buDdSDEkeG7kyBjw7MgbcOgdSB4YW5oIGzDoSBjw6J5LCBjw6FjIGThu68gbGnhu4d1IGPDsyBtw6B1IMSR4buPLCDEkcaw4bujYyBsw6BtIHRyw7JuIMSR4bq/biAyIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuIHbDoCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCAyIMSRxqFuIHbhu4suIFF1YSBiaeG7g3UgxJHhu5MgdHLDqm4gdGEgdGjhuqV5IGPDoWMgbG/huqFpIG3DoHUgY+G7p2Ega2ltIGPGsMahbmcgc+G6vSBjw7MgeOG6pXAgeOG7iSB0cnVuZyBiw6xuaCB04bu3IGzhu4cgxJHhu5kgc8OidSBi4bqxbmcgbmhhdS4gVHJvbmcgxJHDsyBjYW8gbmjhuqV0IGzDoCBtw6B1IEogdsOgIHRo4bqlcCBuaOG6pXQgbMOgIG3DoHUgRS4qKioNCg0KIyBCSeG7glUgxJDhu5IgMjkNCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KdCAlPiUgZ2dwbG90KGFlcyh4ID0gY2xhcml0eSkpICsNCiAgZ2VvbV9iYXIoKSArDQogIGxhYnMoeCA9ICdD4bqlcCDEkeG7mSB0aW5oIGtoaeG6v3QnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGxhYnModGl0bGUgPSAnQ+G6pXAgxJHhu5kgdGluaCBraGnhur90IGPhu6dhIGtpbSBjxrDGoW5nIChiaeG7g3UgxJHhu5MgbmdhbmcpJykNCmBgYA0KDQoqKipUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyDEkeG7mSB0cm9uZyBzdeG7kXQuIHRhIGfhuq9uIHggbMOgIGPhuqVwIMSR4buZIHRpbmgga2hp4bq/dCwgeSBsw6Agc+G7kSBsxrDhu6NuZyBWw6AgxJHDonkgbMOgIGJp4buDdSDEkeG7kyBuZ2FuZy4gUXVhIGJp4buDdSDEkeG7kyB0csOqbiB0YSB0aOG6pXkgU0kxIGPDsyDEkeG7mSB0aW5oIGtoaeG6v3QgY2FvIG5o4bqldCwgZ2nhuqNtIGThuqduIHThu6sgVlMyLCBTSTIsIFZTMSwgVlZTMiwgSUYgdsOgIEkxIGzDoCBraW0gY8awxqFuZyBjw7MgxJHhu5kgdHJvbmcgc3Xhu5F0IHRo4bqlcCBuaOG6pXQqKioNCg0KIyBCSeG7glUgxJDhu5IgMzANCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KdCAlPiUgZ3JvdXBfYnkoY3V0KSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oZGVwdGgpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY3V0LHkgPSBtKSkgKw0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sMikpLCB2anVzdCA9IDIsIGNvbG9yID0gJ2dyZWVuJykgKw0KICBsYWJzKHggPSAnS2nhu4N1IGPhuq90JywgeSA9ICdNZWFuJykNCmBgYA0KDQoqKipUYSBwaMOibiBsb+G6oWkga2ltIGPGsMahbmcgdGhlbyBraeG7g3UgY+G6r3QgdsOgIHTDrW5oIHRydW5nIGLDrG5oIHThu7cgbOG7hyDEkeG7mSBzw6J1ICh0cnVuZyBiw6xuaCB6L3gpLiB0YSBn4bqvbiB4IGzDoCBraeG7g3UgY+G6r3QsIHkgbMOgIHRydW5nIGLDrG5oLiBjw6FjIHPhu5EgbGnhu4d1IMSRxrDhu6NjIGzDoG0gdHLDsm4gMiBjaOG7ryBz4buRIHRo4bqtcCBwaMOibiwgxJHGsOG7o2MgxJFp4buBdSBjaOG7iW5oIOG7nyB24buLIHRyw60gY8OhY2ggY+G7mXQgZOG7jWMgMiDEkcahbiB24buLIHbDoCBjw7MgbcOgdSB4YW5oIGzDoSBjw6J5LiBRdWEgYmnhu4N1IMSR4buTIHRyw6puIHRhIHRo4bqleSBraeG7g3UgY+G6r3QgRmFpciBjw7MgxJHhu5kgc8OidSB0cnVuZyBiw6xuaCBs4bubbiBuaOG6pXQsIGdp4bqjbSBk4bqnbiB04burIEdvb2QsIFZlcnkgR29vZCwgSWRlYWwgdsOgIHRo4bqlcCBuaOG6pXQgbMOgIFByZW1pdW0qKio=