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

skim_variable n_missing complete_rate ordered n_unique top_counts
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

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
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=