Nhiệm vụ 4

Ở nhiệm vụ này, chúng ta sẽ tiến hành các thao tác để vẽ các biểu đồ nhằm phân tích số liệu của một bộ dữ liệu. Cụ thể ở đây, chúng ta sẽ sử dụng bộ dataset Diamonds, đây là một bộ dataset nằm trong package ggplot2. Ta sẽ tiến hành xem một số thông tin cơ bản của dataset này

library(ggplot2)
data(package = 'ggplot2')
lg <- diamonds
str(lg)
## tibble [53,940 × 10] (S3: tbl_df/tbl/data.frame)
##  $ carat  : num [1:53940] 0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
##  $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...
##  $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2 5 ...
##  $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4 5 ...
##  $ depth  : num [1:53940] 61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
##  $ table  : num [1:53940] 55 61 65 58 58 57 57 55 61 61 ...
##  $ price  : int [1:53940] 326 326 327 334 335 336 336 337 337 338 ...
##  $ x      : num [1:53940] 3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
##  $ y      : num [1:53940] 3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
##  $ z      : num [1:53940] 2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...

Từ kết quả trên, ta đọc được 1 số thông tin như sau:

  • Dataset gồm có 53940 hàng tương đương 53940 viên kim cương được nghiên cứu

  • Gồm có 10 biến, đó là:

    • price: Giá của viên kim cương (USD)
    • carat: Trọng lượng của viên kim cương (carat)
    • cut: Chất lượng của vết cắt (Fair, Good, Very Good, Excellent, Ideal)
    • color: Màu sắc của viên kim cương
    • clarity: Độ trong của viên kim cương
    • 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)
    • table: Chiều rộng của đỉnh kim cương so với điểm rộng nhất
    • depth: Tỷ lệ phần trăm độ sâu Từ những dữ liệu trên, ta sẽ tiến hành trực quan hoá dữ liệu

Vẽ biểu đồ

Biểu đồ 1

Ở biểu đồ đầu tiên, ta tiến hành xem các thông số về Color

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ lubridate 1.9.3     ✔ tibble    3.2.1
## ✔ purrr     1.0.2     ✔ tidyr     1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(scales)
## 
## Attaching package: 'scales'
## 
## The following object is masked from 'package:purrr':
## 
##     discard
## 
## The following object is masked from 'package:readr':
## 
##     col_factor
lg %>% ggplot(aes(x = color)) +
    geom_bar() +
    labs(x = 'Loại', y = 'Số lượng') + labs(title = ': Số lượng kim cương của từng màu')

Từ biểu đồ trên, có thể thấy được tổng quát về màu sắc của các viên kim cương chúng ta phân tích

Biểu đồ 2

Vẫn là phân tích về màu sắc tuy nhiên bây giờ chúng ta sẽ quy đổi sang số liệu % nhằm có cái nhìn tổng quan hơn

lg %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(color,n)) +
    geom_col(fill='orange') +
    geom_text(aes(label = percent(n/length(lg$carat))),vjust = 2, color = 'black') +
    labs(x = 'Loại', y = 'Số lượng') + labs(title = ': % kim cương của từng màu ')

Từ đây ta cũng dễ dàng nắm bắt tỉ trọng màu sắc của các loại hơn

Biểu đồ 3

Tiếp tục là về màu sắc, tuy nhiên ở đây chúng ta sẽ phân tích từng màu sắc theo độ trong

lg %>% group_by(clarity,color) %>% summarise(n=n()) %>%
  ggplot(aes(x = clarity,y = n)) +
    geom_col(position = 'dodge') +
    facet_wrap(~color) +
    labs(x = 'Loại', y = 'Số lượng') + labs(title = ': Số lượng kim cương của từng màu theo độ trong')
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.

Theo bảng trên, dễ dãng thấy được màu E,F,G là trong nhất còn I,J có độ trong thấp nhất

Biểu đồ 4

Ta sẽ tạo một biểu đồ histogram hiển thị phân phối giá của kim cương theo màu sắc.

lg %>% ggplot(aes(x = price, fill = color)) +
  geom_histogram(binwidth = 500)

Biểu đồ 5

Cũng với bảng trên, lần này ta sẽ cho thẳng số liệu của từng thành phần trong mỗi bảng

lg %>% 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 = 'orange') +
    labs(x = 'Loại', y = 'Số lượng') + labs(title = ': Số lượng kim cương của từng màu theo độ trong')
## `summarise()` has grouped output by 'clarity'. You can override using the
## `.groups` argument.

Từ đây, dễ dàng thấy được chính xác thông số của chúng

Biểu đồ 6

Bây giờ ta sẽ phân tích số lượng kim cương của từng loại màu theo chiều dài

Trước tiên, ta sẽ mã hóa chiều dài (biến x) của viên kim cương dựa trên tứ phân vị của nó như sau:Ngắn - Trung bình - Trung bình khá - Dài. Tiếp đến ta sẽ vẽ biểu đồ thể hiện số lượng kim cương của từng loại màu theo các chiều dài khác nhau.

a4 <- quantile(lg$x, probs = .25)
a5 <- quantile(lg$x, probs = .50)
a6 <- quantile(lg$x, probs = .75)

lg$chieudai <- case_when(lg$x <= a4 ~ 'Ngắn', 
                            lg$x > a4 & lg$x <= a5 ~ 'Trung bình', 
                            lg$x > a5 & lg$x <= a6 ~ 'Trung bình khá', 
                            lg$x > a6 ~ 'Dài')

lng <- lg %>% group_by(color, chieudai) %>% summarise(n = n())

lng %>% ggplot(aes(x = color,y = n)) +
          geom_col(fill = 'orange') +
          facet_wrap(~chieudai) +
          labs(x = 'Màu', y = 'Số lượng') + labs(title = 'Số lượng kim cương của từng màu theo chiều dài')

Biểu đồ 7

Dựa vào dữ liệu chiều dài đã được mã hóa ở trên, ta sẽ tiến hành đánh giá chất lượng kim cương theo chiều dài và loại màu thông qua giá trung bình.

long <- lg %>% group_by(chieudai,color) %>% summarise(avg_price6 = mean(price))

long %>% ggplot(aes(x = color, y = avg_price6)) +
          geom_col(fill = 'orange') +
          facet_wrap(~chieudai) +
          geom_text(aes(label = round(avg_price6)), vjust = 0, color = 'black') +
          labs(x = 'Màu', y = 'Average Price') + labs(title = 'Giá trung bình của từng màu theo chiều dài')

Từ biểu đồ, ta có thể thấy được ở mức chiều dài Dài kim cương có giá trung bình cao hơn rất nhiều so với các chiều dài còn lại Và ở đây ta có thể thấy rõ màu của các loại kim cương không ảnh hưởng nhiều đến giá của nó, mức giá trung bình giữa các màu chênh lệch nhau không lớn.

Biểu đồ 8

Ta sẽ tiến hành đánh giá chất lượng kim cương theo chất lượng cut và loại màu thông qua giá trung bình

lg %>% group_by(cut,color) %>% summarise(n=n()) %>%
  ggplot(aes(x = cut,y = n)) +
    geom_col(fill = 'orange') +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    facet_wrap(~color) +
    labs(x = 'Thang đo Cut', y = 'Số lượng')
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.

Biểu đồ 9

Ta sẽ tiến hành đánh giá chất lượng kim cương theo trọng lương và loại màu

Trước tiên, ta sẽ mã hóa trọng lượng (biến carat) của viên kim cương dựa trên tứ phân vị của nó như sau:Rất nhẹ - Nhẹ - Vừa- Nặng - Rất nặng. Tiếp đến ta sẽ vẽ biểu đồ thể hiện số lượng kim cương của từng loại màu theo các khối lượng khác nhau.

lg1 <- lg %>% mutate(KL = cut(carat,5, label = c('Rất nhẹ', 'Nhẹ','Vừa','Nặng','Rất nặng')))

Sau đó ta vẽ biểu đồ

lg1 %>% group_by(KL,color) %>% summarise(n=n()) %>%
  ggplot(aes(x = KL,y = n)) +
    geom_col(fill = 'orange') +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    facet_wrap(~color) +
    labs(x = 'Trọng lượng Carat', y = 'Số lượng')
## `summarise()` has grouped output by 'KL'. You can override using the `.groups`
## argument.

Biểu đồ 10

Tạo ra một biểu đồ mật độ hiển thị phân bố màu sắc của kim cương. Trục x thể hiện màu sắc, trục y thể hiện mật độ (tần suất xuất hiện) của các màu sắc. Màu của biểu đồ được đặt thành màu cam.

lg %>% ggplot(aes(x = color)) +
  geom_density(fill = 'orange')

Biểu đồ 11

Tạo ra một biểu đồ mật độ xếp chồng hiển thị phân phối màu sắc của kim cương theo kiểu cắt. Trục x thể hiện màu sắc, trục y thể hiện mật độ (tần suất xuất hiện) của các màu sắc. Các lớp chồng lên nhau thể hiện mật độ của từng kiểu cắt

lg %>% ggplot(aes(x = color, fill = cut)) +
  geom_density()

Biểu đồ 12

Tạo biểu đồ mật độ phân bố màu sắc kim cương theo từng kiểu cắt.

lg %>% ggplot(aes(x = color)) +
  geom_density(fill = 'orange') +
  facet_wrap(~cut)

Biểu đồ 13

Biểu đồ thể hiện giá trị trung bình của số kim cương phân theo màu

lg %>% group_by(color) %>% summarise(m= mean(carat)) %>%
  ggplot(aes(x = color,y = m)) +
    geom_col(fill = 'orange') +
    geom_text(aes(label = round(m,2)), vjust = 0, color = 'black') +
    labs(x = 'Màu', y = 'Mean')

Biểu đồ 14

Biểu đồ thể hiện tỉ lệ kim cương theo loại và màu

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

Biểu đồ này hiển thị hai cột riêng biệt, một màu đỏ và một màu xanh, thể hiện số lượng kim cương theo từng kiểu cắt (cut) cho hai màu sắc ‘D’ và ‘J’.

Biểu đồ 15

Biểu đồ tỉ số cut kim cương

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

Biểu đồ 16

Biểu đồ hiển thị các cột xếp chồng lên nhau theo từng màu sắc.

lg %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(x = '', y = n,fill = color)) +
    geom_col() +
    geom_text(aes(label = n),position = position_stack(vjust = 1))

Biểu đồ 17

Biểu đồ hiển thị một hình tròn được chia thành các miếng bánh theo tỉ lệ số lượng kim cương của mỗi màu sắc

lg %>% group_by(color) %>% summarise(n = n()) %>%
  ggplot(aes(x = '', y = n,fill = color)) +
    geom_col(color = 'black') +
    coord_polar('y') +
    geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
    theme_void()

Biểu đồ 18

Ta sẽ tiến hành mã hóa biến carat của dataset này dựa trên các tứ phân vị để mã hóa thành 4 giá trị: Nhỏ - Vừa - Khá Lớn - Lớn. Sau đó ta vẽ biểu đồ dựa trên số lượng các giá trị vừa mã hóa.

a <- quantile(mtl$carat, probs = .25)
b <- quantile(mtl$carat, probs = .50)
c <- quantile(mtl$carat, probs = .75)

mtl$KL <- case_when(mtl$carat <= a ~ 'Nhỏ', 
                            mtl$carat > a & mtl$carat <= b ~ 'Vừa', 
                            mtl$carat > b & mtl$carat <= c ~ 'Khá Lớn', 
                            mtl$carat > c ~ 'Lớn')

mtl %>% ggplot(aes(x = KL)) +
          geom_bar(fill = 'purple') +
          labs(x = 'Trọng lượng', y = 'Số viên kim cương') + labs(title = 'Số lượng kim cương theo từng trọng lượng')

Ta có thể thấy, số lượng kim cương ở mỗi trọng lượng gần như bằng nhau, chỉ số viên ở phần có trọng lượng Nhỏ là nhỉnh hơn 3 loại còn lại.

Biểu đồ 19

Từ dữ liệu về biến carat đã được mã hóa ở trên, ta sẽ tiếp tục đánh giá chất lượng của các viên kim cương dựa trên trọng lượng của nó thông qua mức giá trung bình.

mtl5 <- mtl %>% group_by(KL) %>% summarise(avg_price4 = mean(price))

mtl5 %>% ggplot(aes(x = KL, y = avg_price4)) + 
          geom_col(fill = 'blue') + 
          geom_text(aes(label = round(avg_price4)),vjust = 2, color = 'white') +
          labs(x = 'Trọng lượng', y = 'Average Price') + labs(title = 'Giá trung bình theo trọng lượng')

Ở biểu đồ này ta có thể thấy rất rõ sự chênh lệch giá trung bình giữa các viên kim cương có trọng lượng khác nhau:

  • Các viên có trọng lượng Lớn có mức giá cao hơn rất nhiều so với 3 loại còn lại, điều đó thể hiện trọng lượng càng nặng thì giá càng cao.

  • Các viên kim cương Nhỏ có mức giá rất thấp.

  • Ta có thể kết luận mức giá của kim cương tỷ lệ thuận với trọng lượng của nó, kim cương càng nặng giá càng cao cũng như càng nhẹ thì giá càng thấp.

Biểu đồ 20

Tương tự như ở trọng lượng, ta sẽ tiến hành mã hóa biến depth dựa trên tứ phân vị của nó để chia thành 4 giá trị: Thấp - Trung Bình Thấp - Trung Bình - Sâu và sau đó sẽ tiến hành vẽ biểu đồ dựa trên số lượng kim cương các loại.

a1 <- quantile(mtl$depth, probs = .25)
a2 <- quantile(mtl$depth, probs = .50)
a3 <- quantile(mtl$depth, probs = .75)

mtl$dosau <- case_when(mtl$depth <= a1 ~ 'Thấp', 
                            mtl$depth > a1 & mtl$depth <= a2 ~ 'Trung bình thấp', 
                            mtl$depth > a2 & mtl$depth <= a3 ~ 'Trung bình', 
                            mtl$depth > a3 ~ 'Sâu')

mtl %>% ggplot(aes(x = dosau)) +
          geom_bar(fill = 'orange') +
          labs(x = 'Độ sâu', y = 'Số viên kim cương') + labs(title = 'Số lượng kim cương theo từng độ sâu')

Ta có thể thấy số lượng kim cương phân tán đều cho các độ sâu, điều này là hợp lý bởi vì chúng ta mã hóa dữ liệu dựa trên tứ phân vị của biến depth.

Biểu đồ 21

Từ dữ liệu biến depth đã được mã hóa ở trên, ta tiến hành đánh giá chất lượng của kim cương dựa trên độ sâu của nó thông qua mức giá trung bình:

mtl6 <- mtl %>% group_by(dosau) %>% summarise(avg_price5 = mean(price))

mtl6 %>% ggplot(aes(x = dosau, y = avg_price5)) + 
          geom_col(fill = 'red') + 
          geom_text(aes(label = round(avg_price5)),vjust = 2, color = 'white') +
          labs(x = 'Độ Sâu', y = 'Average Price') + labs(title = 'Giá trung bình theo độ sâu')

Ở biểu đồ này, ta thấy giá trung bình ở độ sâu SâuThấp cao hơn hẳn 2 độ sâu còn lại.

Biểu đồ 22

Từ dữ liệu của biến carat đã được mã hóa ở trên, ta kết hợp cùng với biến cut để tạo nên biểu đồ thể hiện số lượng của từng loại trọng lượng và chất lượng vết cắt.

mtl10 <- mtl %>% group_by(KL, cut) %>% summarise(n1 = n())

mtl10 %>% ggplot(aes(x = cut,y = n1)) +
          geom_col(data = mtl10 %>% filter(KL == 'Nhỏ'), fill = 'red') +
          geom_col(data = mtl10 %>% filter(KL == 'Vừa'), fill = 'blue') +
          geom_col(data = mtl10 %>% filter(KL == 'Khá Lớn'), fill = 'yellow') +
           geom_col(data = mtl10 %>% filter(KL == 'Lớn'), fill = 'pink') +
          labs(x = 'Chất lượng vết cắt', y = 'Số lượng') + labs(title = 'Số lượng kim cương theo trọng lượng của từng chất lượng vết cắt')

Theo biểu đồ trên, ta thấy kim cương có trọng lượng lớn hầu như chiếm nhiều nhất ở tất cả các loại cut.

Biểu đồ 23

Từ biến price ta sẽ chia nó thành 5 giá trị tương ứng với giá của nó như sau: Rất Rẻ - Rẻ - Trung bình - Đắt - Rất Đắt, từ đó ta sẽ tiến hành vẽ biểu đồ thể hiện số lượng kim cương theo từng giá trị đã được mã hóa.

mtl <- mtl %>% mutate(price.coded = case_when(
                        price < 500 ~ 'Rất rẻ',
                        price >= 500 & price < 1000 ~ 'Rẻ', 
                        price >=1000 & price <2000 ~ 'Trung bình',
                        price >=2000 & price <3000 ~ 'Đắt',
                        price >= 3000 ~ 'Rất Đắt'))

mtl11 <- mtl %>% group_by(price.coded) %>% summarise(n_price = n())

mtl11 %>% ggplot(aes(x = price.coded, y = n_price)) +
          geom_col(fill = 'blue') +
          geom_text(aes(label = n_price), vjust = 2, color = 'white')+
          labs(title = 'Số lượng kim cương theo giá', x = 'Price', y = 'Số lượng')

Ta dễ dàng nhận xét được rằng đa số viên kim cương được thống kê trong dataset này có mức giá đắt là trên 3000 USD với 23606 viên kim cương, và lớn hơn rất nhiều so với 1729 viên kim cương có giá nhỏ hơn 500 USD.

Biểu đồ 24

Như các cách ở trên, ta dễ dàng tạo được 1 biểu đồ số lượng viên kim cương theo chiều rộng bằng cách mã hóa dữ liệu của biến này theo các giá trị như sau:Nhỏ - Vừa - Rộng. Sau đó sẽ đếm số kim cương theo từng chiều rộng khác nhau.

mtl$chieurong <- case_when(mtl$y < 5.5 ~ 'Nhỏ', mtl$y >=5.5 & mtl$y < 6.5 ~ 'Vừa', mtl$y >= 6.5 ~ 'Rộng')

mtl14 <- mtl %>% group_by(chieurong) %>% summarise(n14 = n())

mtl14 %>% ggplot(aes(x = chieurong, y = n14)) +
          geom_col(fill = 'orange') +
          geom_text(aes(label = n14), vjust = 2, color = 'red')+
          labs(title = 'Số lượng kim cương theo chiều rộng', x = 'Chiều rộng', y = 'Số lượng')

Vậy ta có thể thấy, đa số viên kim cương là nhỏ (chiều rộng nhỏ hơn 5.5mm).

Biểu đồ 25

Ta sẽ tiến hành mã hóa dữ liệu biến table thành các giá trị character như sau: Mặt bàn hẹp - Mặt bàn trung bình - Mặt bàn rộng. Và sau đó sẽ đếm số kim cương theo độ rộng của mặt bàn.

mtl$matban <- case_when(mtl$table <= 55 ~ 'Mặt bàn hẹp', mtl$table >55 & mtl$table <= 60 ~ 'Mặt bàn trung bình', mtl$table > 60 ~ 'Mặt bàn rộng')

mtl15 <- mtl %>% group_by(matban) %>% summarise(n15 = n())

mtl15 %>% ggplot(aes(x = matban, y = n15)) +
          geom_col(fill = 'green') +
          geom_text(aes(label = n15), vjust = 2, color = 'blue')+
          labs(title = 'Số lượng kim cương theo độ rộng của mặt bàn', x = 'Mặt bàn', y = 'Số lượng')

Các viên kim cương trong dataset này đa số có mặt bàn trung bình (table lớn hơn 55 và nhỏ hơn 60).

Biểu đồ 26

Ta tiến hành tính giá trị trung bình của biến price theo dữ liệu biến y(chiều rộng) đã được mã hóa ở trên và vẽ biểu đồ thể hiện mức giá trung bình theo từng chiều rộng để có thể đánh giá chất lượng kim cương của từng độ rộng khác nhau.

mtl16 <- mtl %>% group_by(chieurong) %>% summarise(avg_price15= mean(price))

mtl16 %>% ggplot(aes(x = chieurong, y = avg_price15))+
          geom_col(fill = 'green') +
          geom_text(aes(label = round(avg_price15)), vjust = 2, color ='white') +
          labs(title = 'Giá trung bình của kim cương theo chiều rộng', x = 'Chiều rộng', y = 'Average Price')

Từ biểu đồ 2.16, ta dễ dàng nhận ra chiều rộng cũng sẽ tỷ lệ thuận với giá của viên kim cương. Những viên kim cương có chiều rộng lớn hơn 6.5mm có giá cao hơn rất nhiều so với những viên kim cương khác.

Biểu đồ 27

Ta tiến hành tính giá trị trung bình của biến price theo dữ liệu biến table(độ rộng mặt bàn) đã được mã hóa ở trên và vẽ biểu đồ thể hiện mức giá trung bình theo từng loại mặt bàn để có thể đánh giá chất lượng kim cương của từng loại khác nhau.

mtl16 <- mtl %>% group_by(matban) %>% summarise(avg_price16= mean(price))

mtl16 %>% ggplot(aes(x = matban, y = avg_price16))+
          geom_col(fill = 'purple') +
          geom_text(aes(label = round(avg_price16)), vjust = 2, color ='white') +
          labs(title = 'Giá trung bình của kim cương theo độ rộng mặt bàn', x = 'Độ rộng mặt bàn', y = 'Average Price')

Từ biểu đồ 2.16, ta có thể thấy mức giá trung bình không chênh lệch nhiều giữa các độ rộng mặt bàn khác nhau nên có thể đưa ra 1 kết luận chủ quan rằng độ rộng mặt bàn không ảnh hưởng nhiều đến giá trị của viên kim cương.

Biểu đồ 28

Đầu tiên, ta sẽ tiến hành rút trích dữ liệu các viên kim cương có màu loại D, sao đó từ các biến KL được mã hóa từ carat và biến price.coded được mã hóa từ biến price ta sẽ thực hiện vẽ biểu đồ đếm số lượng các viên kim cương để có thể đánh giá chất lượng của viên kim cương màu D dựa trên trọng lượng của chúng

mtl17 <- mtl %>% filter(color == 'D') %>%
                group_by(KL,price.coded) %>%
                summarise(n17 = n())

mtl17 %>% ggplot(aes(x = price.coded, y = n17)) + 
          geom_col(fill = 'black') +
          facet_wrap(~KL) +
          geom_text(aes(label = n17),vjust = 0.5, color = 'red')+
          labs(title = 'Mức giá của kim cương màu loại D theo trọng lượng', x = 'Mức giá', y = 'Số lượng')

Ở các viên kim cương màu loại D, giá trị gần như sẽ phụ thuộc vào trọng lượng của viên kim cương đó, trọng lượng càng lớn giá càng đắt, trọng lượng càng nhỏ giá càng rẻ. Điều này là hợp lý vì ở biểu đồ 2.13 đã chứng minh giá trị của viên kim cương tỷ lệ thuận với trọng lượng của nó.

Biểu đồ 29

Ta rút trích dữ liệu các viên kim cương có màu loại E, sau đó sẽ tính mức giá trung bình của các viên kim cương này theo biến cut để có thể đánh giá được ảnh hưởng của chất lượng vết cắt đến giá trị của kim cương màu loại E.

mtl18 <- mtl %>% filter(color == 'E') %>%
                group_by(cut) %>%
                summarise(avg_price18 = mean(price))

mtl18 %>% ggplot(aes(x = cut, y = avg_price18)) + 
          geom_col(fill = 'grey') +         
       geom_text(aes(label = round(avg_price18)),vjust = 2, color = 'brown')+
          labs(title = 'Mức giá trung bình của kim cương màu loại E theo chất lượng vết cắt', x = 'Chất lượng vết cắt', y = 'Average Price')

Nhìn chung, mức giá trung bình của kim cương loại E theo chất lượng vết cắt phân bố không khác nhiều so với mức giá trung bình trên toàn bộ kim cương theo chất lượng vết cắt (biểu đồ 2.3). Có 1 điểm khác nhỏ là ở kim cương loại E, chất lượng Fair có giá trị cao nhất, điều này khác so với trên toàn bộ kim cương thì chất lượng Premium có giá trị cao nhất.

Biểu đồ 30

Ta rút trích dữ liệu các viên kim cương có màu loại F, sau đó sẽ tính số lượng của các viên kim cương này theo biến clarity có mức giá như thế nào để có thể đánh giá được ảnh hưởng của độ trong đến giá trị của kim cương màu loại F.

mtl19 <- mtl %>% filter(color == 'F') %>%
                group_by(clarity,price.coded) %>%
                summarise(n19 = n())

mtl19 %>% ggplot(aes(x = price.coded, y = n19)) + 
          geom_col(fill = 'brown') +       
          facet_wrap(~clarity) +
          labs(title = 'Mức giá của kim cương màu F theo độ trong', x = 'Mức giá', y = 'Số lượng')

Ở biểu đồ 2.19, ta có thể thấy những viên kim cương màu loại E có mức giá đắt và rất đắt tập trung chủ yếu ở độ trong SI1 và SI2, điều này là hợp lí bởi vì ở biểu đồ 2.2 khi phân tích mức giá trung bình của từng độ trong thì SI1 và SI2 là 2 nhóm độ trong dẫn đầu ở giá. Vậy ta có thể kết luận rằng mức giá sẽ giảm dần từ SI2 - SI1 - VS2 - VS1 - VVS2 - VVS1 - IF I1

LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA0Ig0KYXV0aG9yOiAiTVRMb25nZ2ciDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclSDolTTolUywgJWQgLSAlbSAtICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgICB0aGVtZTogImRlZmF1bHQiDQogICAgdG9jX2RlcHRoOiAyDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jOiB0cnVlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCiMgTmhp4buHbSB24bulIDQNCg0K4bueIG5oaeG7h20gduG7pSBuw6B5LCBjaMO6bmcgdGEgc+G6vSB0aeG6v24gaMOgbmggY8OhYyB0aGFvIHTDoWMgxJHhu4MgduG6vSBjw6FjIGJp4buDdSDEkeG7kyBuaOG6sW0gcGjDom4gdMOtY2ggc+G7kSBsaeG7h3UgY+G7p2EgbeG7mXQgYuG7mSBk4buvIGxp4buHdS4gQ+G7pSB0aOG7gyDhu58gxJHDonksIGNow7puZyB0YSBz4bq9IHPhu60gZOG7pW5nIGLhu5kgZGF0YXNldCAqKipEaWFtb25kcyoqKiwgxJHDonkgbMOgIG3hu5l0IGLhu5kgZGF0YXNldCBu4bqxbSB0cm9uZyBwYWNrYWdlICoqKmdncGxvdDIqKiouIFRhIHPhur0gdGnhur9uIGjDoG5oIHhlbSBt4buZdCBz4buRIHRow7RuZyB0aW4gY8ahIGLhuqNuIGPhu6dhIGRhdGFzZXQgbsOgeQ0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpkYXRhKHBhY2thZ2UgPSAnZ2dwbG90MicpDQpsZyA8LSBkaWFtb25kcw0Kc3RyKGxnKQ0KYGBgDQpU4burIGvhur90IHF14bqjIHRyw6puLCB0YSDEkeG7jWMgxJHGsOG7o2MgMSBz4buRIHRow7RuZyB0aW4gbmjGsCBzYXU6DQoNCi0gRGF0YXNldCBn4buTbSBjw7MgNTM5NDAgaMOgbmcgdMawxqFuZyDEkcawxqFuZyA1Mzk0MCB2acOqbiBraW0gY8awxqFuZyDEkcaw4bujYyBuZ2hpw6puIGPhu6l1DQoNCi0gR+G7k20gY8OzIDEwIGJp4bq/biwgxJHDsyBsw6A6DQoNCiAgLSAqKnByaWNlKio6IEdpw6EgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgKFVTRCkNCiAgLSAqKmNhcmF0Kio6IFRy4buNbmcgbMaw4bujbmcgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgKGNhcmF0KQ0KICAtICoqY3V0Kio6IENo4bqldCBsxrDhu6NuZyBj4bunYSB24bq/dCBj4bqvdCAoRmFpciwgR29vZCwgVmVyeSBHb29kLCBFeGNlbGxlbnQsIElkZWFsKQ0KICAtICoqY29sb3IqKjogTcOgdSBz4bqvYyBj4bunYSB2acOqbiBraW0gY8awxqFuZw0KICAtICoqY2xhcml0eSoqOiDEkOG7mSB0cm9uZyBj4bunYSB2acOqbiBraW0gY8awxqFuZw0KICAtICoqeCoqOiBDaGnhu4F1IGTDoGkgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgKG1tKQ0KICAtICoqeSoqOiBDaGnhu4F1IHLhu5luZyBj4bunYSB2acOqbiBraW0gY8awxqFuZyAobW0pDQogIC0gKip6Kio6IMSQ4buZIHPDonUgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgKG1tKQ0KICAtICoqdGFibGUqKjogQ2hp4buBdSBy4buZbmcgY+G7p2EgxJHhu4luaCBraW0gY8awxqFuZyBzbyB24bubaSDEkWnhu4NtIHLhu5luZyBuaOG6pXQNCiAgLSAqKmRlcHRoKio6IFThu7cgbOG7hyBwaOG6p24gdHLEg20gxJHhu5kgc8OidQ0KVOG7qyBuaOG7r25nIGThu68gbGnhu4d1IHRyw6puLCB0YSBz4bq9IHRp4bq/biBow6BuaCB0cuG7sWMgcXVhbiBob8OhIGThu68gbGnhu4d1DQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MNCg0KIyMgQmnhu4N1IMSR4buTIDENCg0K4bueIGJp4buDdSDEkeG7kyDEkeG6p3UgdGnDqm4sIHRhIHRp4bq/biBow6BuaCB4ZW0gY8OhYyB0aMO0bmcgc+G7kSB24buBICoqQ29sb3IqKiANCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCmxnICU+JSBnZ3Bsb3QoYWVzKHggPSBjb2xvcikpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykgKyBsYWJzKHRpdGxlID0gJzogU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBj4bunYSB04burbmcgbcOgdScpDQogICAgDQpgYGANClThu6sgYmnhu4N1IMSR4buTIHRyw6puLCBjw7MgdGjhu4MgdGjhuqV5IMSRxrDhu6NjIHThu5VuZyBxdcOhdCB24buBIG3DoHUgc+G6r2MgY+G7p2EgY8OhYyB2acOqbiBraW0gY8awxqFuZyBjaMO6bmcgdGEgcGjDom4gdMOtY2gNCg0KIyMgQmnhu4N1IMSR4buTIDIgDQpW4bqrbiBsw6AgcGjDom4gdMOtY2ggduG7gSBtw6B1IHPhuq9jIHR1eSBuaGnDqm4gYsOieSBnaeG7nSBjaMO6bmcgdGEgc+G6vSBxdXkgxJHhu5VpIHNhbmcgc+G7kSBsaeG7h3UgKiolKiogbmjhurFtIGPDsyBjw6FpIG5ow6xuIHThu5VuZyBxdWFuIGjGoW4NCmBgYHtyfQ0KbGcgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKGNvbG9yLG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0nb3JhbmdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KG4vbGVuZ3RoKGxnJGNhcmF0KSkpLHZqdXN0ID0gMiwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpICsgbGFicyh0aXRsZSA9ICc6ICUga2ltIGPGsMahbmcgY+G7p2EgdOG7q25nIG3DoHUgJykNCmBgYA0KVOG7qyDEkcOieSB0YSBjxaluZyBk4buFIGTDoG5nIG7huq9tIGLhuq90IHThu4kgdHLhu41uZyBtw6B1IHPhuq9jIGPhu6dhIGPDoWMgbG/huqFpIGjGoW4NCg0KIyMgQmnhu4N1IMSR4buTIDMNClRp4bq/cCB04bulYyBsw6AgduG7gSBtw6B1IHPhuq9jLCB0dXkgbmhpw6puIOG7nyDEkcOieSBjaMO6bmcgdGEgc+G6vSBwaMOibiB0w61jaCB04burbmcgKioqbcOgdSBz4bqvYyoqKiB0aGVvICAqKirEkeG7mSB0cm9uZyoqKiANCmBgYHtyfQ0KbGcgJT4lIGdyb3VwX2J5KGNsYXJpdHksY29sb3IpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBjbGFyaXR5LHkgPSBuKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAofmNvbG9yKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpICsgbGFicyh0aXRsZSA9ICc6IFPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY+G7p2EgdOG7q25nIG3DoHUgdGhlbyDEkeG7mSB0cm9uZycpDQpgYGANClRoZW8gYuG6o25nIHRyw6puLCBk4buFIGTDo25nIHRo4bqleSDEkcaw4bujYyBtw6B1IEUsRixHIGzDoCB0cm9uZyBuaOG6pXQgY8OybiBJLEogY8OzIMSR4buZIHRyb25nIHRo4bqlcCBuaOG6pXQNCg0KIyMgQmnhu4N1IMSR4buTIDQNClRhIHPhur0gdOG6oW8gbeG7mXQgYmnhu4N1IMSR4buTIGhpc3RvZ3JhbSBoaeG7g24gdGjhu4sgcGjDom4gcGjhu5FpIGdpw6EgY+G7p2Ega2ltIGPGsMahbmcgdGhlbyBtw6B1IHPhuq9jLg0KYGBge3J9DQpsZyAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UsIGZpbGwgPSBjb2xvcikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1MDApDQpgYGANCg0KIyMgQmnhu4N1IMSR4buTIDUNCkPFqW5nIHbhu5tpIGLhuqNuZyB0csOqbiwgbOG6p24gbsOgeSB0YSBz4bq9IGNobyB0aOG6s25nIHPhu5EgbGnhu4d1IGPhu6dhIHThu6tuZyB0aMOgbmggcGjhuqduIHRyb25nIG3hu5dpIGLhuqNuZw0KYGBge3J9DQpsZyAlPiUgZ3JvdXBfYnkoY2xhcml0eSxjb2xvcikgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsYXJpdHkseSA9IG4pKSArDQogICAgZ2VvbV9jb2wocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgZmFjZXRfd3JhcCh+Y29sb3IpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLCBjb2xvciA9ICdvcmFuZ2UnKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpICsgbGFicyh0aXRsZSA9ICc6IFPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY+G7p2EgdOG7q25nIG3DoHUgdGhlbyDEkeG7mSB0cm9uZycpDQpgYGANClThu6sgxJHDonksIGThu4UgZMOgbmcgdGjhuqV5IMSRxrDhu6NjIGNow61uaCB4w6FjIHRow7RuZyBz4buRIGPhu6dhIGNow7puZw0KDQojIyBCaeG7g3UgxJHhu5MgNg0KQsOieSBnaeG7nSB0YSBz4bq9IHBow6JuIHTDrWNoICBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPhu6dhIHThu6tuZyBsb+G6oWkgbcOgdSB0aGVvIGNoaeG7gXUgZMOgaQ0KDQpUcsaw4bubYyB0acOqbiwgdGEgc+G6vSBtw6MgaMOzYSBjaGnhu4F1IGTDoGkgKGJp4bq/biAqKngqKikgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgZOG7sWEgdHLDqm4gdOG7qSBwaMOibiB24buLIGPhu6dhIG7DsyBuaMawIHNhdToqKk5n4bqvbiAtIFRydW5nIGLDrG5oIC0gVHJ1bmcgYsOsbmgga2jDoSAtIETDoGkqKi4gVGnhur9wIMSR4bq/biB0YSBz4bq9IHbhur0gYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIGPhu6dhIHThu6tuZyBsb+G6oWkgbcOgdSB0aGVvIGPDoWMgY2hp4buBdSBkw6BpIGtow6FjIG5oYXUuDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KYTQgPC0gcXVhbnRpbGUobGckeCwgcHJvYnMgPSAuMjUpDQphNSA8LSBxdWFudGlsZShsZyR4LCBwcm9icyA9IC41MCkNCmE2IDwtIHF1YW50aWxlKGxnJHgsIHByb2JzID0gLjc1KQ0KDQpsZyRjaGlldWRhaSA8LSBjYXNlX3doZW4obGckeCA8PSBhNCB+ICdOZ+G6r24nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZyR4ID4gYTQgJiBsZyR4IDw9IGE1IH4gJ1RydW5nIGLDrG5oJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGckeCA+IGE1ICYgbGckeCA8PSBhNiB+ICdUcnVuZyBiw6xuaCBraMOhJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGckeCA+IGE2IH4gJ0TDoGknKQ0KDQpsbmcgPC0gbGcgJT4lIGdyb3VwX2J5KGNvbG9yLCBjaGlldWRhaSkgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KDQpsbmcgJT4lIGdncGxvdChhZXMoeCA9IGNvbG9yLHkgPSBuKSkgKw0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAnb3JhbmdlJykgKw0KICAgICAgICAgIGZhY2V0X3dyYXAofmNoaWV1ZGFpKSArDQogICAgICAgICAgbGFicyh4ID0gJ03DoHUnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKSArIGxhYnModGl0bGUgPSAnU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBj4bunYSB04burbmcgbcOgdSB0aGVvIGNoaeG7gXUgZMOgaScpDQpgYGANCg0KIyMgQmnhu4N1IMSR4buTIDcNCkThu7FhIHbDoG8gZOG7ryBsaeG7h3UgY2hp4buBdSBkw6BpIMSRw6MgxJHGsOG7o2MgbcOjIGjDs2Eg4bufIHRyw6puLCB0YSBz4bq9IHRp4bq/biBow6BuaCDEkcOhbmggZ2nDoSBjaOG6pXQgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaGnhu4F1IGTDoGkgdsOgIGxv4bqhaSBtw6B1IHRow7RuZyBxdWEgZ2nDoSB0cnVuZyBiw6xuaC4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmxvbmcgPC0gbGcgJT4lIGdyb3VwX2J5KGNoaWV1ZGFpLGNvbG9yKSAlPiUgc3VtbWFyaXNlKGF2Z19wcmljZTYgPSBtZWFuKHByaWNlKSkNCg0KbG9uZyAlPiUgZ2dwbG90KGFlcyh4ID0gY29sb3IsIHkgPSBhdmdfcHJpY2U2KSkgKw0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAnb3JhbmdlJykgKw0KICAgICAgICAgIGZhY2V0X3dyYXAofmNoaWV1ZGFpKSArDQogICAgICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGF2Z19wcmljZTYpKSwgdmp1c3QgPSAwLCBjb2xvciA9ICdibGFjaycpICsNCiAgICAgICAgICBsYWJzKHggPSAnTcOgdScsIHkgPSAnQXZlcmFnZSBQcmljZScpICsgbGFicyh0aXRsZSA9ICdHacOhIHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyBtw6B1IHRoZW8gY2hp4buBdSBkw6BpJykNCmBgYA0KDQpU4burIGJp4buDdSDEkeG7kywgdGEgY8OzIHRo4buDIHRo4bqleSDEkcaw4bujYyDhu58gbeG7qWMgY2hp4buBdSBkw6BpICoqRMOgaSoqIGtpbSBjxrDGoW5nIGPDsyBnacOhIHRydW5nIGLDrG5oIGNhbyBoxqFuIHLhuqV0IG5oaeG7gXUgc28gduG7m2kgY8OhYyBjaGnhu4F1IGTDoGkgY8OybiBs4bqhaQ0KVsOgIOG7nyDEkcOieSB0YSBjw7MgdGjhu4MgdGjhuqV5IHLDtSBtw6B1IGPhu6dhIGPDoWMgbG/huqFpIGtpbSBjxrDGoW5nIGtow7RuZyDhuqNuaCBoxrDhu59uZyBuaGnhu4F1IMSR4bq/biBnacOhIGPhu6dhIG7DsywgbeG7qWMgZ2nDoSB0cnVuZyBiw6xuaCBnaeG7r2EgY8OhYyBtw6B1IGNow6puaCBs4buHY2ggbmhhdSBraMO0bmcgbOG7m24uDQoNCiMjIEJp4buDdSDEkeG7kyA4DQpUYSBz4bq9IHRp4bq/biBow6BuaCDEkcOhbmggZ2nDoSBjaOG6pXQgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBjaOG6pXQgbMaw4bujbmcgY3V0IHbDoCBsb+G6oWkgbcOgdSB0aMO0bmcgcXVhIGdpw6EgdHJ1bmcgYsOsbmgNCmBgYHtyfQ0KbGcgJT4lIGdyb3VwX2J5KGN1dCxjb2xvcikgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gbikpICsNCiAgICBnZW9tX2NvbChmaWxsID0gJ29yYW5nZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBmYWNldF93cmFwKH5jb2xvcikgKw0KICAgIGxhYnMoeCA9ICdUaGFuZyDEkW8gQ3V0JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQojIyBCaeG7g3UgxJHhu5MgOQ0KVGEgc+G6vSB0aeG6v24gaMOgbmggxJHDoW5oIGdpw6EgY2jhuqV0IGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gdHLhu41uZyBsxrDGoW5nIHbDoCBsb+G6oWkgbcOgdSANCg0KVHLGsOG7m2MgdGnDqm4sIHRhIHPhur0gbcOjIGjDs2EgdHLhu41uZyBsxrDhu6NuZyAoYmnhur9uICoqY2FyYXQqKikgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgZOG7sWEgdHLDqm4gdOG7qSBwaMOibiB24buLIGPhu6dhIG7DsyBuaMawIHNhdToqKlLhuqV0IG5o4bq5IC0gTmjhurkgLSBW4burYS0gTuG6t25nIC0gUuG6pXQgbuG6t25nKiouIFRp4bq/cCDEkeG6v24gdGEgc+G6vSB24bq9IGJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBj4bunYSB04burbmcgbG/huqFpIG3DoHUgdGhlbyBjw6FjIGto4buRaSBsxrDhu6NuZyBraMOhYyBuaGF1Lg0KYGBge3J9DQpsZzEgPC0gbGcgJT4lIG11dGF0ZShLTCA9IGN1dChjYXJhdCw1LCBsYWJlbCA9IGMoJ1LhuqV0IG5o4bq5JywgJ05o4bq5JywnVuG7q2EnLCdO4bq3bmcnLCdS4bqldCBu4bq3bmcnKSkpDQpgYGANClNhdSDEkcOzIHRhIHbhur0gYmnhu4N1IMSR4buTIA0KDQpgYGB7cn0NCmxnMSAlPiUgZ3JvdXBfYnkoS0wsY29sb3IpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBLTCx5ID0gbikpICsNCiAgICBnZW9tX2NvbChmaWxsID0gJ29yYW5nZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBmYWNldF93cmFwKH5jb2xvcikgKw0KICAgIGxhYnMoeCA9ICdUcuG7jW5nIGzGsOG7o25nIENhcmF0JywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQojIyBCaeG7g3UgxJHhu5MgMTANClThuqFvIHJhIG3hu5l0IGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSBoaeG7g24gdGjhu4sgcGjDom4gYuG7kSBtw6B1IHPhuq9jIGPhu6dhIGtpbSBjxrDGoW5nLiBUcuG7pWMgeCB0aOG7gyBoaeG7h24gbcOgdSBz4bqvYywgdHLhu6VjIHkgdGjhu4MgaGnhu4duIG3huq10IMSR4buZICh04bqnbiBzdeG6pXQgeHXhuqV0IGhp4buHbikgY+G7p2EgY8OhYyBtw6B1IHPhuq9jLiBNw6B1IGPhu6dhIGJp4buDdSDEkeG7kyDEkcaw4bujYyDEkeG6t3QgdGjDoG5oIG3DoHUgY2FtLg0KYGBge3J9DQpsZyAlPiUgZ2dwbG90KGFlcyh4ID0gY29sb3IpKSArDQogIGdlb21fZGVuc2l0eShmaWxsID0gJ29yYW5nZScpDQoNCmBgYA0KDQojIyBCaeG7g3UgxJHhu5MgMTENClThuqFvIHJhIG3hu5l0IGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSB44bq/cCBjaOG7k25nIGhp4buDbiB0aOG7iyBwaMOibiBwaOG7kWkgbcOgdSBz4bqvYyBj4bunYSBraW0gY8awxqFuZyB0aGVvIGtp4buDdSBj4bqvdC4gVHLhu6VjIHggdGjhu4MgaGnhu4duIG3DoHUgc+G6r2MsIHRy4bulYyB5IHRo4buDIGhp4buHbiBt4bqtdCDEkeG7mSAodOG6p24gc3XhuqV0IHh14bqldCBoaeG7h24pIGPhu6dhIGPDoWMgbcOgdSBz4bqvYy4gQ8OhYyBs4bubcCBjaOG7k25nIGzDqm4gbmhhdSB0aOG7gyBoaeG7h24gbeG6rXQgxJHhu5kgY+G7p2EgdOG7q25nIGtp4buDdSBj4bqvdA0KYGBge3J9DQpsZyAlPiUgZ2dwbG90KGFlcyh4ID0gY29sb3IsIGZpbGwgPSBjdXQpKSArDQogIGdlb21fZGVuc2l0eSgpDQpgYGANCg0KIyMgQmnhu4N1IMSR4buTIDEyIA0KVOG6oW8gYmnhu4N1IMSR4buTIG3huq10IMSR4buZIHBow6JuIGLhu5EgbcOgdSBz4bqvYyBraW0gY8awxqFuZyB0aGVvIHThu6tuZyBraeG7g3UgY+G6r3QuDQpgYGB7cn0NCmxnICU+JSBnZ3Bsb3QoYWVzKHggPSBjb2xvcikpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAnb3JhbmdlJykgKw0KICBmYWNldF93cmFwKH5jdXQpDQpgYGANCg0KIyMgQmnhu4N1IMSR4buTIDEzDQpCaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2Egc+G7kSBraW0gY8awxqFuZyBwaMOibiB0aGVvIG3DoHUNCmBgYHtyfQ0KbGcgJT4lIGdyb3VwX2J5KGNvbG9yKSAlPiUgc3VtbWFyaXNlKG09IG1lYW4oY2FyYXQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gY29sb3IseSA9IG0pKSArDQogICAgZ2VvbV9jb2woZmlsbCA9ICdvcmFuZ2UnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sMikpLCB2anVzdCA9IDAsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICdNw6B1JywgeSA9ICdNZWFuJykNCmBgYA0KDQojIyBCaeG7g3UgxJHhu5MgMTQNCkJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gdOG7iSBs4buHIGtpbSBjxrDGoW5nIHRoZW8gbG/huqFpIHbDoCBtw6B1DQpgYGB7cn0NCmxnIDwtIGxnICU+JSBncm91cF9ieShjdXQsIGNvbG9yKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQpsZyAlPiUgZ2dwbG90KGFlcyh4ID0gY3V0LCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGxnICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0QnKSwgZmlsbCA9ICdyZWQnKSArDQogIGdlb21fY29sKGRhdGEgPSBsZyAlPiUgZmlsdGVyKGNvbG9yID09ICdKJyksIGZpbGwgPSAnb3JhbmdlJykNCmBgYA0KQmnhu4N1IMSR4buTIG7DoHkgaGnhu4NuIHRo4buLIGhhaSBj4buZdCByacOqbmcgYmnhu4d0LCBt4buZdCBtw6B1IMSR4buPIHbDoCBt4buZdCBtw6B1IHhhbmgsIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gdOG7q25nIGtp4buDdSBj4bqvdCAoY3V0KSBjaG8gaGFpIG3DoHUgc+G6r2MgJ0QnIHbDoCAnSicuDQoNCiMjIEJp4buDdSDEkeG7kyAxNQ0KQmnhu4N1IMSR4buTIHThu4kgc+G7kSBjdXQga2ltIGPGsMahbmcNCmBgYHtyfQ0KbGcgJT4lIGdyb3VwX2J5KGN1dCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhjdXQsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdvcmFuZ2UnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBlcmNlbnQobi9sZW5ndGgobGckY3V0KSkpLHZqdXN0ID0gMiwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KIyMgQmnhu4N1IMSR4buTIDE2DQpCaeG7g3UgxJHhu5MgIGhp4buDbiB0aOG7iyBjw6FjIGPhu5l0IHjhur9wIGNo4buTbmcgbMOqbiBuaGF1IHRoZW8gdOG7q25nIG3DoHUgc+G6r2MuDQpgYGB7cn0NCmxnICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBjb2xvcikpICsNCiAgICBnZW9tX2NvbCgpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbikscG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDEpKQ0KYGBgDQoNCiMjIEJp4buDdSDEkeG7kyAxNw0KQmnhu4N1IMSR4buTIGhp4buDbiB0aOG7iyBt4buZdCBow6xuaCB0csOybiDEkcaw4bujYyBjaGlhIHRow6BuaCBjw6FjIG1p4bq/bmcgYsOhbmggdGhlbyB04buJIGzhu4cgc+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyBj4bunYSBt4buXaSBtw6B1IHPhuq9jDQpgYGB7cn0NCmxnICU+JSBncm91cF9ieShjb2xvcikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBjb2xvcikpICsNCiAgICBnZW9tX2NvbChjb2xvciA9ICdibGFjaycpICsNCiAgICBjb29yZF9wb2xhcigneScpICsNCiAgICBnZW9tX3RleHQoYWVzKHggPSAxLjMsIGxhYmVsID0gbikscG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSkgKw0KICAgIHRoZW1lX3ZvaWQoKQ0KYGBgDQoNCiMjIEJp4buDdSDEkeG7kyAxOA0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCm10bCA8LSBkaWFtb25kcw0KYGBgDQoNClRhIHPhur0gdGnhur9uIGjDoG5oIG3DoyBow7NhIGJp4bq/biAqKmNhcmF0KiogY+G7p2EgZGF0YXNldCBuw6B5IGThu7FhIHRyw6puIGPDoWMgdOG7qSBwaMOibiB24buLIMSR4buDIG3DoyBow7NhIHRow6BuaCA0IGdpw6EgdHLhu4s6ICoqTmjhu48gLSBW4burYSAtIEtow6EgTOG7m24gLSBM4bubbioqLiBTYXUgxJHDsyB0YSB24bq9IGJp4buDdSDEkeG7kyBk4buxYSB0csOqbiBz4buRIGzGsOG7o25nIGPDoWMgZ2nDoSB0cuG7iyB24burYSBtw6MgaMOzYS4NCg0KYGBge3J9DQphIDwtIHF1YW50aWxlKG10bCRjYXJhdCwgcHJvYnMgPSAuMjUpDQpiIDwtIHF1YW50aWxlKG10bCRjYXJhdCwgcHJvYnMgPSAuNTApDQpjIDwtIHF1YW50aWxlKG10bCRjYXJhdCwgcHJvYnMgPSAuNzUpDQoNCm10bCRLTCA8LSBjYXNlX3doZW4obXRsJGNhcmF0IDw9IGEgfiAnTmjhu48nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdGwkY2FyYXQgPiBhICYgbXRsJGNhcmF0IDw9IGIgfiAnVuG7q2EnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdGwkY2FyYXQgPiBiICYgbXRsJGNhcmF0IDw9IGMgfiAnS2jDoSBM4bubbicsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG10bCRjYXJhdCA+IGMgfiAnTOG7m24nKQ0KDQptdGwgJT4lIGdncGxvdChhZXMoeCA9IEtMKSkgKw0KICAgICAgICAgIGdlb21fYmFyKGZpbGwgPSAncHVycGxlJykgKw0KICAgICAgICAgIGxhYnMoeCA9ICdUcuG7jW5nIGzGsOG7o25nJywgeSA9ICdT4buRIHZpw6puIGtpbSBjxrDGoW5nJykgKyBsYWJzKHRpdGxlID0gJ1Phu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyB04burbmcgdHLhu41uZyBsxrDhu6NuZycpDQpgYGANCg0KDQpUYSBjw7MgdGjhu4MgdGjhuqV5LCBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIOG7nyBt4buXaSB0cuG7jW5nIGzGsOG7o25nIGfhuqduIG5oxrAgYuG6sW5nIG5oYXUsIGNo4buJIHPhu5EgdmnDqm4g4bufIHBo4bqnbiBjw7MgdHLhu41uZyBsxrDhu6NuZyAqKk5o4buPKiogbMOgIG5o4buJbmggaMahbiAzIGxv4bqhaSBjw7JuIGzhuqFpLg0KDQojIyBCaeG7g3UgxJHhu5MgMTkNCg0KVOG7qyBk4buvIGxp4buHdSB24buBIGJp4bq/biAqKmNhcmF0KiogxJHDoyDEkcaw4bujYyBtw6MgaMOzYSDhu58gdHLDqm4sIHRhIHPhur0gdGnhur9wIHThu6VjIMSRw6FuaCBnacOhIGNo4bqldCBsxrDhu6NuZyBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIGThu7FhIHRyw6puIHRy4buNbmcgbMaw4bujbmcgY+G7p2EgbsOzIHRow7RuZyBxdWEgbeG7qWMgZ2nDoSB0cnVuZyBiw6xuaC4NCg0KYGBge3J9DQptdGw1IDwtIG10bCAlPiUgZ3JvdXBfYnkoS0wpICU+JSBzdW1tYXJpc2UoYXZnX3ByaWNlNCA9IG1lYW4ocHJpY2UpKQ0KDQptdGw1ICU+JSBnZ3Bsb3QoYWVzKHggPSBLTCwgeSA9IGF2Z19wcmljZTQpKSArIA0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAnYmx1ZScpICsgDQogICAgICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGF2Z19wcmljZTQpKSx2anVzdCA9IDIsIGNvbG9yID0gJ3doaXRlJykgKw0KICAgICAgICAgIGxhYnMoeCA9ICdUcuG7jW5nIGzGsOG7o25nJywgeSA9ICdBdmVyYWdlIFByaWNlJykgKyBsYWJzKHRpdGxlID0gJ0dpw6EgdHJ1bmcgYsOsbmggdGhlbyB0cuG7jW5nIGzGsOG7o25nJykNCmBgYA0KDQrhu54gYmnhu4N1IMSR4buTIG7DoHkgdGEgY8OzIHRo4buDIHRo4bqleSBy4bqldCByw7Ugc+G7sSBjaMOqbmggbOG7h2NoIGdpw6EgdHJ1bmcgYsOsbmggZ2nhu69hIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgY8OzIHRy4buNbmcgbMaw4bujbmcga2jDoWMgbmhhdToNCg0KLSBDw6FjIHZpw6puIGPDsyB0cuG7jW5nIGzGsOG7o25nICoqTOG7m24qKiBjw7MgbeG7qWMgZ2nDoSBjYW8gaMahbiBy4bqldCBuaGnhu4F1IHNvIHbhu5tpIDMgbG/huqFpIGPDsm4gbOG6oWksIMSRaeG7gXUgxJHDsyB0aOG7gyBoaeG7h24gdHLhu41uZyBsxrDhu6NuZyBjw6BuZyBu4bq3bmcgdGjDrCBnacOhIGPDoG5nIGNhby4NCg0KLSBDw6FjIHZpw6puIGtpbSBjxrDGoW5nICoqTmjhu48qKiBjw7MgbeG7qWMgZ2nDoSBy4bqldCB0aOG6pXAuDQoNCi0gVGEgY8OzIHRo4buDIGvhur90IGx14bqtbiBt4bupYyBnacOhIGPhu6dhIGtpbSBjxrDGoW5nIHThu7cgbOG7hyB0aHXhuq1uIHbhu5tpIHRy4buNbmcgbMaw4bujbmcgY+G7p2EgbsOzLCBraW0gY8awxqFuZyBjw6BuZyBu4bq3bmcgZ2nDoSBjw6BuZyBjYW8gY8WpbmcgbmjGsCBjw6BuZyBuaOG6uSB0aMOsIGdpw6EgY8OgbmcgdGjhuqVwLg0KDQojIyBCaeG7g3UgxJHhu5MgMjANCg0KVMawxqFuZyB04buxIG5oxrAg4bufIHRy4buNbmcgbMaw4bujbmcsIHRhIHPhur0gdGnhur9uIGjDoG5oIG3DoyBow7NhIGJp4bq/biAqKmRlcHRoKiogZOG7sWEgdHLDqm4gdOG7qSBwaMOibiB24buLIGPhu6dhIG7DsyDEkeG7gyBjaGlhIHRow6BuaCA0IGdpw6EgdHLhu4s6ICoqVGjhuqVwIC0gVHJ1bmcgQsOsbmggVGjhuqVwIC0gVHJ1bmcgQsOsbmggLSBTw6J1KiogdsOgIHNhdSDEkcOzIHPhur0gdGnhur9uIGjDoG5oIHbhur0gYmnhu4N1IMSR4buTIGThu7FhIHRyw6puIHPhu5EgbMaw4bujbmcga2ltIGPGsMahbmcgY8OhYyBsb+G6oWkuDQoNCmBgYHtyfQ0KYTEgPC0gcXVhbnRpbGUobXRsJGRlcHRoLCBwcm9icyA9IC4yNSkNCmEyIDwtIHF1YW50aWxlKG10bCRkZXB0aCwgcHJvYnMgPSAuNTApDQphMyA8LSBxdWFudGlsZShtdGwkZGVwdGgsIHByb2JzID0gLjc1KQ0KDQptdGwkZG9zYXUgPC0gY2FzZV93aGVuKG10bCRkZXB0aCA8PSBhMSB+ICdUaOG6pXAnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdGwkZGVwdGggPiBhMSAmIG10bCRkZXB0aCA8PSBhMiB+ICdUcnVuZyBiw6xuaCB0aOG6pXAnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdGwkZGVwdGggPiBhMiAmIG10bCRkZXB0aCA8PSBhMyB+ICdUcnVuZyBiw6xuaCcsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG10bCRkZXB0aCA+IGEzIH4gJ1PDonUnKQ0KDQptdGwgJT4lIGdncGxvdChhZXMoeCA9IGRvc2F1KSkgKw0KICAgICAgICAgIGdlb21fYmFyKGZpbGwgPSAnb3JhbmdlJykgKw0KICAgICAgICAgIGxhYnMoeCA9ICfEkOG7mSBzw6J1JywgeSA9ICdT4buRIHZpw6puIGtpbSBjxrDGoW5nJykgKyBsYWJzKHRpdGxlID0gJ1Phu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyB04burbmcgxJHhu5kgc8OidScpDQpgYGANCg0KVGEgY8OzIHRo4buDIHRo4bqleSBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHBow6JuIHTDoW4gxJHhu4F1IGNobyBjw6FjIMSR4buZIHPDonUsIMSRaeG7gXUgbsOgeSBsw6AgaOG7o3AgbMO9IGLhu59pIHbDrCBjaMO6bmcgdGEgbcOjIGjDs2EgZOG7ryBsaeG7h3UgZOG7sWEgdHLDqm4gdOG7qSBwaMOibiB24buLIGPhu6dhIGJp4bq/biAqKmRlcHRoKiouDQoNCiMjIEJp4buDdSDEkeG7kyAyMQ0KDQpU4burIGThu68gbGnhu4d1IGJp4bq/biAqKmRlcHRoKiogxJHDoyDEkcaw4bujYyBtw6MgaMOzYSDhu58gdHLDqm4sIHRhIHRp4bq/biBow6BuaCDEkcOhbmggZ2nDoSBjaOG6pXQgbMaw4bujbmcgY+G7p2Ega2ltIGPGsMahbmcgZOG7sWEgdHLDqm4gxJHhu5kgc8OidSBj4bunYSBuw7MgdGjDtG5nIHF1YSBt4bupYyBnacOhIHRydW5nIGLDrG5oOg0KYGBge3J9DQptdGw2IDwtIG10bCAlPiUgZ3JvdXBfYnkoZG9zYXUpICU+JSBzdW1tYXJpc2UoYXZnX3ByaWNlNSA9IG1lYW4ocHJpY2UpKQ0KDQptdGw2ICU+JSBnZ3Bsb3QoYWVzKHggPSBkb3NhdSwgeSA9IGF2Z19wcmljZTUpKSArIA0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAncmVkJykgKyANCiAgICAgICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoYXZnX3ByaWNlNSkpLHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSArDQogICAgICAgICAgbGFicyh4ID0gJ8SQ4buZIFPDonUnLCB5ID0gJ0F2ZXJhZ2UgUHJpY2UnKSArIGxhYnModGl0bGUgPSAnR2nDoSB0cnVuZyBiw6xuaCB0aGVvIMSR4buZIHPDonUnKQ0KYGBgDQoNCuG7niBiaeG7g3UgxJHhu5MgbsOgeSwgdGEgdGjhuqV5IGdpw6EgdHJ1bmcgYsOsbmgg4bufIMSR4buZIHPDonUgKipTw6J1KiogdsOgICoqVGjhuqVwKiogY2FvIGjGoW4gaOG6s24gMiDEkeG7mSBzw6J1IGPDsm4gbOG6oWkuDQoNCiMjIEJp4buDdSDEkeG7kyAyMg0KDQpU4burIGThu68gbGnhu4d1IGPhu6dhIGJp4bq/biAqKmNhcmF0KiogxJHDoyDEkcaw4bujYyBtw6MgaMOzYSDhu58gdHLDqm4sIHRhIGvhur90IGjhu6NwIGPDuW5nIHbhu5tpIGJp4bq/biAqKmN1dCoqIMSR4buDIHThuqFvIG7Dqm4gYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGPhu6dhIHThu6tuZyBsb+G6oWkgdHLhu41uZyBsxrDhu6NuZyB2w6AgY2jhuqV0IGzGsOG7o25nIHbhur90IGPhuq90Lg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCm10bDEwIDwtIG10bCAlPiUgZ3JvdXBfYnkoS0wsIGN1dCkgJT4lIHN1bW1hcmlzZShuMSA9IG4oKSkNCg0KbXRsMTAgJT4lIGdncGxvdChhZXMoeCA9IGN1dCx5ID0gbjEpKSArDQogICAgICAgICAgZ2VvbV9jb2woZGF0YSA9IG10bDEwICU+JSBmaWx0ZXIoS0wgPT0gJ05o4buPJyksIGZpbGwgPSAncmVkJykgKw0KICAgICAgICAgIGdlb21fY29sKGRhdGEgPSBtdGwxMCAlPiUgZmlsdGVyKEtMID09ICdW4burYScpLCBmaWxsID0gJ2JsdWUnKSArDQogICAgICAgICAgZ2VvbV9jb2woZGF0YSA9IG10bDEwICU+JSBmaWx0ZXIoS0wgPT0gJ0tow6EgTOG7m24nKSwgZmlsbCA9ICd5ZWxsb3cnKSArDQogICAgICAgICAgIGdlb21fY29sKGRhdGEgPSBtdGwxMCAlPiUgZmlsdGVyKEtMID09ICdM4bubbicpLCBmaWxsID0gJ3BpbmsnKSArDQogICAgICAgICAgbGFicyh4ID0gJ0No4bqldCBsxrDhu6NuZyB24bq/dCBj4bqvdCcsIHkgPSAnU+G7kSBsxrDhu6NuZycpICsgbGFicyh0aXRsZSA9ICdT4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gdHLhu41uZyBsxrDhu6NuZyBj4bunYSB04burbmcgY2jhuqV0IGzGsOG7o25nIHbhur90IGPhuq90JykNCmBgYA0KDQpUaGVvIGJp4buDdSDEkeG7kyB0csOqbiwgdGEgdGjhuqV5IGtpbSBjxrDGoW5nIGPDsyB0cuG7jW5nIGzGsOG7o25nIGzhu5tuIGjhuqd1IG5oxrAgY2hp4bq/bSBuaGnhu4F1IG5o4bqldCDhu58gdOG6pXQgY+G6oyBjw6FjIGxv4bqhaSAqKmN1dCoqLg0KDQojIyBCaeG7g3UgxJHhu5MgMjMNCg0KVOG7qyBiaeG6v24gKipwcmljZSoqIHRhIHPhur0gY2hpYSBuw7MgdGjDoG5oIDUgZ2nDoSB0cuG7iyB0xrDGoW5nIOG7qW5nIHbhu5tpIGdpw6EgY+G7p2EgbsOzIG5oxrAgc2F1OiAqKlLhuqV0IFLhursgLSBS4bq7IC0gVHJ1bmcgYsOsbmggLSDEkOG6r3QgLSBS4bqldCDEkOG6r3QqKiwgdOG7qyDEkcOzIHRhIHPhur0gdGnhur9uIGjDoG5oIHbhur0gYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buRIGzGsOG7o25nIGtpbSBjxrDGoW5nIHRoZW8gdOG7q25nIGdpw6EgdHLhu4sgxJHDoyDEkcaw4bujYyBtw6MgaMOzYS4NCg0KYGBge3J9DQptdGwgPC0gbXRsICU+JSBtdXRhdGUocHJpY2UuY29kZWQgPSBjYXNlX3doZW4oDQogICAgICAgICAgICAgICAgICAgICAgICBwcmljZSA8IDUwMCB+ICdS4bqldCBy4bq7JywNCiAgICAgICAgICAgICAgICAgICAgICAgIHByaWNlID49IDUwMCAmIHByaWNlIDwgMTAwMCB+ICdS4bq7JywgDQogICAgICAgICAgICAgICAgICAgICAgICBwcmljZSA+PTEwMDAgJiBwcmljZSA8MjAwMCB+ICdUcnVuZyBiw6xuaCcsDQogICAgICAgICAgICAgICAgICAgICAgICBwcmljZSA+PTIwMDAgJiBwcmljZSA8MzAwMCB+ICfEkOG6r3QnLA0KICAgICAgICAgICAgICAgICAgICAgICAgcHJpY2UgPj0gMzAwMCB+ICdS4bqldCDEkOG6r3QnKSkNCg0KbXRsMTEgPC0gbXRsICU+JSBncm91cF9ieShwcmljZS5jb2RlZCkgJT4lIHN1bW1hcmlzZShuX3ByaWNlID0gbigpKQ0KDQptdGwxMSAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UuY29kZWQsIHkgPSBuX3ByaWNlKSkgKw0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAnYmx1ZScpICsNCiAgICAgICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbl9wcmljZSksIHZqdXN0ID0gMiwgY29sb3IgPSAnd2hpdGUnKSsNCiAgICAgICAgICBsYWJzKHRpdGxlID0gJ1Phu5EgbMaw4bujbmcga2ltIGPGsMahbmcgdGhlbyBnacOhJywgeCA9ICdQcmljZScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KVGEgZOG7hSBkw6BuZyBuaOG6rW4geMOpdCDEkcaw4bujYyBy4bqxbmcgxJFhIHPhu5EgdmnDqm4ga2ltIGPGsMahbmcgxJHGsOG7o2MgdGjhu5FuZyBrw6ogdHJvbmcgZGF0YXNldCBuw6B5IGPDsyBt4bupYyBnacOhIMSR4bqvdCBsw6AgdHLDqm4gMzAwMCBVU0QgduG7m2kgMjM2MDYgdmnDqm4ga2ltIGPGsMahbmcsIHbDoCBs4bubbiBoxqFuIHLhuqV0IG5oaeG7gXUgc28gduG7m2kgMTcyOSB2acOqbiBraW0gY8awxqFuZyBjw7MgZ2nDoSBuaOG7jyBoxqFuIDUwMCBVU0QuDQoNCiMjIEJp4buDdSDEkeG7kyAyNA0KDQpOaMawIGPDoWMgY8OhY2gg4bufIHRyw6puLCB0YSBk4buFIGTDoG5nIHThuqFvIMSRxrDhu6NjIDEgYmnhu4N1IMSR4buTIHPhu5EgbMaw4bujbmcgdmnDqm4ga2ltIGPGsMahbmcgdGhlbyBjaGnhu4F1IHLhu5luZyBi4bqxbmcgY8OhY2ggbcOjIGjDs2EgZOG7ryBsaeG7h3UgY+G7p2EgYmnhur9uIG7DoHkgdGhlbyBjw6FjIGdpw6EgdHLhu4sgbmjGsCBzYXU6KipOaOG7jyAtIFbhu6thIC0gUuG7mW5nKiouIFNhdSDEkcOzIHPhur0gxJHhur9tIHPhu5Ega2ltIGPGsMahbmcgdGhlbyB04burbmcgY2hp4buBdSBy4buZbmcga2jDoWMgbmhhdS4NCg0KYGBge3J9DQptdGwkY2hpZXVyb25nIDwtIGNhc2Vfd2hlbihtdGwkeSA8IDUuNSB+ICdOaOG7jycsIG10bCR5ID49NS41ICYgbXRsJHkgPCA2LjUgfiAnVuG7q2EnLCBtdGwkeSA+PSA2LjUgfiAnUuG7mW5nJykNCg0KbXRsMTQgPC0gbXRsICU+JSBncm91cF9ieShjaGlldXJvbmcpICU+JSBzdW1tYXJpc2UobjE0ID0gbigpKQ0KDQptdGwxNCAlPiUgZ2dwbG90KGFlcyh4ID0gY2hpZXVyb25nLCB5ID0gbjE0KSkgKw0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAnb3JhbmdlJykgKw0KICAgICAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuMTQpLCB2anVzdCA9IDIsIGNvbG9yID0gJ3JlZCcpKw0KICAgICAgICAgIGxhYnModGl0bGUgPSAnU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIGNoaeG7gXUgcuG7mW5nJywgeCA9ICdDaGnhu4F1IHLhu5luZycsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCg0KVuG6rXkgdGEgY8OzIHRo4buDIHRo4bqleSwgxJFhIHPhu5EgdmnDqm4ga2ltIGPGsMahbmcgbMOgIG5o4buPIChjaGnhu4F1IHLhu5luZyBuaOG7jyBoxqFuIDUuNW1tKS4NCg0KIyMgQmnhu4N1IMSR4buTIDI1DQoNClRhIHPhur0gdGnhur9uIGjDoG5oIG3DoyBow7NhIGThu68gbGnhu4d1IGJp4bq/biAqKnRhYmxlKiogdGjDoG5oIGPDoWMgZ2nDoSB0cuG7iyAqKmNoYXJhY3RlcioqIG5oxrAgc2F1OiAqKk3hurd0IGLDoG4gaOG6uXAgLSBN4bq3dCBiw6BuIHRydW5nIGLDrG5oIC0gTeG6t3QgYsOgbiBy4buZbmcqKi4gVsOgIHNhdSDEkcOzIHPhur0gxJHhur9tIHPhu5Ega2ltIGPGsMahbmcgdGhlbyDEkeG7mSBy4buZbmcgY+G7p2EgbeG6t3QgYsOgbi4NCg0KYGBge3J9DQptdGwkbWF0YmFuIDwtIGNhc2Vfd2hlbihtdGwkdGFibGUgPD0gNTUgfiAnTeG6t3QgYsOgbiBo4bq5cCcsIG10bCR0YWJsZSA+NTUgJiBtdGwkdGFibGUgPD0gNjAgfiAnTeG6t3QgYsOgbiB0cnVuZyBiw6xuaCcsIG10bCR0YWJsZSA+IDYwIH4gJ03hurd0IGLDoG4gcuG7mW5nJykNCg0KbXRsMTUgPC0gbXRsICU+JSBncm91cF9ieShtYXRiYW4pICU+JSBzdW1tYXJpc2UobjE1ID0gbigpKQ0KDQptdGwxNSAlPiUgZ2dwbG90KGFlcyh4ID0gbWF0YmFuLCB5ID0gbjE1KSkgKw0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAnZ3JlZW4nKSArDQogICAgICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4xNSksIHZqdXN0ID0gMiwgY29sb3IgPSAnYmx1ZScpKw0KICAgICAgICAgIGxhYnModGl0bGUgPSAnU+G7kSBsxrDhu6NuZyBraW0gY8awxqFuZyB0aGVvIMSR4buZIHLhu5luZyBj4bunYSBt4bq3dCBiw6BuJywgeCA9ICdN4bq3dCBiw6BuJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQpDw6FjIHZpw6puIGtpbSBjxrDGoW5nIHRyb25nIGRhdGFzZXQgbsOgeSDEkWEgc+G7kSBjw7MgbeG6t3QgYsOgbiB0cnVuZyBiw6xuaCAoKip0YWJsZSoqIGzhu5tuIGjGoW4gNTUgdsOgIG5o4buPIGjGoW4gNjApLg0KDQojIyBCaeG7g3UgxJHhu5MgMjYNCg0KVGEgdGnhur9uIGjDoG5oIHTDrW5oIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgYmnhur9uICoqcHJpY2UqKiB0aGVvIGThu68gbGnhu4d1IGJp4bq/biAqKnkqKihjaGnhu4F1IHLhu5luZykgxJHDoyDEkcaw4bujYyBtw6MgaMOzYSDhu58gdHLDqm4gdsOgIHbhur0gYmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBt4bupYyBnacOhIHRydW5nIGLDrG5oIHRoZW8gdOG7q25nIGNoaeG7gXUgcuG7mW5nIMSR4buDIGPDsyB0aOG7gyDEkcOhbmggZ2nDoSBjaOG6pXQgbMaw4bujbmcga2ltIGPGsMahbmcgY+G7p2EgdOG7q25nIMSR4buZIHLhu5luZyBraMOhYyBuaGF1Lg0KDQpgYGB7cn0NCm10bDE2IDwtIG10bCAlPiUgZ3JvdXBfYnkoY2hpZXVyb25nKSAlPiUgc3VtbWFyaXNlKGF2Z19wcmljZTE1PSBtZWFuKHByaWNlKSkNCg0KbXRsMTYgJT4lIGdncGxvdChhZXMoeCA9IGNoaWV1cm9uZywgeSA9IGF2Z19wcmljZTE1KSkrDQogICAgICAgICAgZ2VvbV9jb2woZmlsbCA9ICdncmVlbicpICsNCiAgICAgICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoYXZnX3ByaWNlMTUpKSwgdmp1c3QgPSAyLCBjb2xvciA9J3doaXRlJykgKw0KICAgICAgICAgIGxhYnModGl0bGUgPSAnR2nDoSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIGNoaeG7gXUgcuG7mW5nJywgeCA9ICdDaGnhu4F1IHLhu5luZycsIHkgPSAnQXZlcmFnZSBQcmljZScpDQogICAgICAgICAgDQpgYGANCg0KVOG7qyBiaeG7g3UgxJHhu5MgMi4xNiwgdGEgZOG7hSBkw6BuZyBuaOG6rW4gcmEgY2hp4buBdSBy4buZbmcgY8Wpbmcgc+G6vSB04bu3IGzhu4cgdGh14bqtbiB24bubaSBnacOhIGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nLiBOaOG7r25nIHZpw6puIGtpbSBjxrDGoW5nIGPDsyBjaGnhu4F1IHLhu5luZyBs4bubbiBoxqFuIDYuNW1tIGPDsyBnacOhIGNhbyBoxqFuIHLhuqV0IG5oaeG7gXUgc28gduG7m2kgbmjhu69uZyB2acOqbiBraW0gY8awxqFuZyBraMOhYy4NCg0KIyMgQmnhu4N1IMSR4buTIDI3DQoNClRhIHRp4bq/biBow6BuaCB0w61uaCBnacOhIHRy4buLIHRydW5nIGLDrG5oIGPhu6dhIGJp4bq/biAqKnByaWNlKiogdGhlbyBk4buvIGxp4buHdSBiaeG6v24gKip0YWJsZSoqKMSR4buZIHLhu5luZyBt4bq3dCBiw6BuKSDEkcOjIMSRxrDhu6NjIG3DoyBow7NhIOG7nyB0csOqbiB2w6AgduG6vSBiaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG3hu6ljIGdpw6EgdHJ1bmcgYsOsbmggdGhlbyB04burbmcgbG/huqFpIG3hurd0IGLDoG4gxJHhu4MgY8OzIHRo4buDIMSRw6FuaCBnacOhIGNo4bqldCBsxrDhu6NuZyBraW0gY8awxqFuZyBj4bunYSB04burbmcgbG/huqFpIGtow6FjIG5oYXUuDQoNCmBgYHtyfQ0KbXRsMTYgPC0gbXRsICU+JSBncm91cF9ieShtYXRiYW4pICU+JSBzdW1tYXJpc2UoYXZnX3ByaWNlMTY9IG1lYW4ocHJpY2UpKQ0KDQptdGwxNiAlPiUgZ2dwbG90KGFlcyh4ID0gbWF0YmFuLCB5ID0gYXZnX3ByaWNlMTYpKSsNCiAgICAgICAgICBnZW9tX2NvbChmaWxsID0gJ3B1cnBsZScpICsNCiAgICAgICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoYXZnX3ByaWNlMTYpKSwgdmp1c3QgPSAyLCBjb2xvciA9J3doaXRlJykgKw0KICAgICAgICAgIGxhYnModGl0bGUgPSAnR2nDoSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyB0aGVvIMSR4buZIHLhu5luZyBt4bq3dCBiw6BuJywgeCA9ICfEkOG7mSBy4buZbmcgbeG6t3QgYsOgbicsIHkgPSAnQXZlcmFnZSBQcmljZScpDQogICAgICAgICAgDQpgYGANCg0KVOG7qyBiaeG7g3UgxJHhu5MgMi4xNiwgdGEgY8OzIHRo4buDIHRo4bqleSBt4bupYyBnacOhIHRydW5nIGLDrG5oIGtow7RuZyBjaMOqbmggbOG7h2NoIG5oaeG7gXUgZ2nhu69hIGPDoWMgxJHhu5kgcuG7mW5nIG3hurd0IGLDoG4ga2jDoWMgbmhhdSBuw6puIGPDsyB0aOG7gyDEkcawYSByYSAxIGvhur90IGx14bqtbiBjaOG7pyBxdWFuIHLhurFuZyDEkeG7mSBy4buZbmcgbeG6t3QgYsOgbiBraMO0bmcg4bqjbmggaMaw4bufbmcgbmhp4buBdSDEkeG6v24gZ2nDoSB0cuG7iyBj4bunYSB2acOqbiBraW0gY8awxqFuZy4NCg0KIyMgQmnhu4N1IMSR4buTIDI4DQoNCsSQ4bqndSB0acOqbiwgdGEgc+G6vSB0aeG6v24gaMOgbmggcsO6dCB0csOtY2ggZOG7ryBsaeG7h3UgY8OhYyB2acOqbiBraW0gY8awxqFuZyBjw7MgbcOgdSBsb+G6oWkgRCwgc2FvIMSRw7MgdOG7qyBjw6FjIGJp4bq/biAqKktMKiogxJHGsOG7o2MgbcOjIGjDs2EgdOG7qyAqKmNhcmF0KiogdsOgIGJp4bq/biAqKnByaWNlLmNvZGVkKiogxJHGsOG7o2MgbcOjIGjDs2EgdOG7qyBiaeG6v24gKipwcmljZSoqIHRhIHPhur0gdGjhu7FjIGhp4buHbiB24bq9IGJp4buDdSDEkeG7kyDEkeG6v20gc+G7kSBsxrDhu6NuZyBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIMSR4buDIGPDsyB0aOG7gyDEkcOhbmggZ2nDoSBjaOG6pXQgbMaw4bujbmcgY+G7p2EgdmnDqm4ga2ltIGPGsMahbmcgbcOgdSBEIGThu7FhIHRyw6puIHRy4buNbmcgbMaw4bujbmcgY+G7p2EgY2jDum5nDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQptdGwxNyA8LSBtdGwgJT4lIGZpbHRlcihjb2xvciA9PSAnRCcpICU+JQ0KICAgICAgICAgICAgICAgIGdyb3VwX2J5KEtMLHByaWNlLmNvZGVkKSAlPiUNCiAgICAgICAgICAgICAgICBzdW1tYXJpc2UobjE3ID0gbigpKQ0KDQptdGwxNyAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UuY29kZWQsIHkgPSBuMTcpKSArIA0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAnYmxhY2snKSArDQogICAgICAgICAgZmFjZXRfd3JhcCh+S0wpICsNCiAgICAgICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbjE3KSx2anVzdCA9IDAuNSwgY29sb3IgPSAncmVkJykrDQogICAgICAgICAgbGFicyh0aXRsZSA9ICdN4bupYyBnacOhIGPhu6dhIGtpbSBjxrDGoW5nIG3DoHUgbG/huqFpIEQgdGhlbyB0cuG7jW5nIGzGsOG7o25nJywgeCA9ICdN4bupYyBnacOhJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KDQrhu54gY8OhYyB2acOqbiBraW0gY8awxqFuZyBtw6B1IGxv4bqhaSBELCBnacOhIHRy4buLIGfhuqduIG5oxrAgc+G6vSBwaOG7pSB0aHXhu5ljIHbDoG8gdHLhu41uZyBsxrDhu6NuZyBj4bunYSB2acOqbiBraW0gY8awxqFuZyDEkcOzLCB0cuG7jW5nIGzGsOG7o25nIGPDoG5nIGzhu5tuIGdpw6EgY8OgbmcgxJHhuq90LCB0cuG7jW5nIGzGsOG7o25nIGPDoG5nIG5o4buPIGdpw6EgY8OgbmcgcuG6uy4gxJBp4buBdSBuw6B5IGzDoCBo4bujcCBsw70gdsOsIOG7nyBiaeG7g3UgxJHhu5MgMi4xMyDEkcOjIGNo4bupbmcgbWluaCBnacOhIHRy4buLIGPhu6dhIHZpw6puIGtpbSBjxrDGoW5nIHThu7cgbOG7hyB0aHXhuq1uIHbhu5tpIHRy4buNbmcgbMaw4bujbmcgY+G7p2EgbsOzLg0KDQojIyBCaeG7g3UgxJHhu5MgMjkNCg0KVGEgcsO6dCB0csOtY2ggZOG7ryBsaeG7h3UgY8OhYyB2acOqbiBraW0gY8awxqFuZyBjw7MgbcOgdSBsb+G6oWkgRSwgc2F1IMSRw7Mgc+G6vSB0w61uaCBt4bupYyBnacOhIHRydW5nIGLDrG5oIGPhu6dhIGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgbsOgeSB0aGVvIGJp4bq/biAqKmN1dCoqIMSR4buDIGPDsyB0aOG7gyDEkcOhbmggZ2nDoSDEkcaw4bujYyDhuqNuaCBoxrDhu59uZyBj4bunYSBjaOG6pXQgbMaw4bujbmcgduG6v3QgY+G6r3QgxJHhur9uIGdpw6EgdHLhu4sgY+G7p2Ega2ltIGPGsMahbmcgbcOgdSBsb+G6oWkgRS4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCm10bDE4IDwtIG10bCAlPiUgZmlsdGVyKGNvbG9yID09ICdFJykgJT4lDQogICAgICAgICAgICAgICAgZ3JvdXBfYnkoY3V0KSAlPiUNCiAgICAgICAgICAgICAgICBzdW1tYXJpc2UoYXZnX3ByaWNlMTggPSBtZWFuKHByaWNlKSkNCg0KbXRsMTggJT4lIGdncGxvdChhZXMoeCA9IGN1dCwgeSA9IGF2Z19wcmljZTE4KSkgKyANCiAgICAgICAgICBnZW9tX2NvbChmaWxsID0gJ2dyZXknKSArICAgICAgICAgDQogICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGF2Z19wcmljZTE4KSksdmp1c3QgPSAyLCBjb2xvciA9ICdicm93bicpKw0KICAgICAgICAgIGxhYnModGl0bGUgPSAnTeG7qWMgZ2nDoSB0cnVuZyBiw6xuaCBj4bunYSBraW0gY8awxqFuZyBtw6B1IGxv4bqhaSBFIHRoZW8gY2jhuqV0IGzGsOG7o25nIHbhur90IGPhuq90JywgeCA9ICdDaOG6pXQgbMaw4bujbmcgduG6v3QgY+G6r3QnLCB5ID0gJ0F2ZXJhZ2UgUHJpY2UnKQ0KYGBgDQoNCk5ow6xuIGNodW5nLCBt4bupYyBnacOhIHRydW5nIGLDrG5oIGPhu6dhIGtpbSBjxrDGoW5nIGxv4bqhaSBFIHRoZW8gY2jhuqV0IGzGsOG7o25nIHbhur90IGPhuq90IHBow6JuIGLhu5Ega2jDtG5nIGtow6FjIG5oaeG7gXUgc28gduG7m2kgbeG7qWMgZ2nDoSB0cnVuZyBiw6xuaCB0csOqbiB0b8OgbiBi4buZIGtpbSBjxrDGoW5nIHRoZW8gY2jhuqV0IGzGsOG7o25nIHbhur90IGPhuq90IChiaeG7g3UgxJHhu5MgMi4zKS4gQ8OzIDEgxJFp4buDbSBraMOhYyBuaOG7jyBsw6Ag4bufIGtpbSBjxrDGoW5nIGxv4bqhaSBFLCBjaOG6pXQgbMaw4bujbmcgKipGYWlyKiogY8OzIGdpw6EgdHLhu4sgY2FvIG5o4bqldCwgxJFp4buBdSBuw6B5IGtow6FjIHNvIHbhu5tpIHRyw6puIHRvw6BuIGLhu5kga2ltIGPGsMahbmcgdGjDrCBjaOG6pXQgbMaw4bujbmcgKipQcmVtaXVtKiogY8OzIGdpw6EgdHLhu4sgY2FvIG5o4bqldC4NCg0KIyMgQmnhu4N1IMSR4buTIDMwDQoNClRhIHLDunQgdHLDrWNoIGThu68gbGnhu4d1IGPDoWMgdmnDqm4ga2ltIGPGsMahbmcgY8OzIG3DoHUgbG/huqFpIEYsIHNhdSDEkcOzIHPhur0gdMOtbmggc+G7kSBsxrDhu6NuZyBj4bunYSBjw6FjIHZpw6puIGtpbSBjxrDGoW5nIG7DoHkgdGhlbyBiaeG6v24gKipjbGFyaXR5KiogY8OzIG3hu6ljIGdpw6EgbmjGsCB0aOG6vyBuw6BvIMSR4buDIGPDsyB0aOG7gyDEkcOhbmggZ2nDoSDEkcaw4bujYyDhuqNuaCBoxrDhu59uZyBj4bunYSDEkeG7mSB0cm9uZyDEkeG6v24gZ2nDoSB0cuG7iyBj4bunYSBraW0gY8awxqFuZyBtw6B1IGxv4bqhaSBGLg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbXRsMTkgPC0gbXRsICU+JSBmaWx0ZXIoY29sb3IgPT0gJ0YnKSAlPiUNCiAgICAgICAgICAgICAgICBncm91cF9ieShjbGFyaXR5LHByaWNlLmNvZGVkKSAlPiUNCiAgICAgICAgICAgICAgICBzdW1tYXJpc2UobjE5ID0gbigpKQ0KDQptdGwxOSAlPiUgZ2dwbG90KGFlcyh4ID0gcHJpY2UuY29kZWQsIHkgPSBuMTkpKSArIA0KICAgICAgICAgIGdlb21fY29sKGZpbGwgPSAnYnJvd24nKSArICAgICAgIA0KICAgICAgICAgIGZhY2V0X3dyYXAofmNsYXJpdHkpICsNCiAgICAgICAgICBsYWJzKHRpdGxlID0gJ03hu6ljIGdpw6EgY+G7p2Ega2ltIGPGsMahbmcgbcOgdSBGIHRoZW8gxJHhu5kgdHJvbmcnLCB4ID0gJ03hu6ljIGdpw6EnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQoNCuG7niBiaeG7g3UgxJHhu5MgMi4xOSwgdGEgY8OzIHRo4buDIHRo4bqleSBuaOG7r25nIHZpw6puIGtpbSBjxrDGoW5nIG3DoHUgbG/huqFpIEUgY8OzIG3hu6ljIGdpw6EgxJHhuq90IHbDoCBy4bqldCDEkeG6r3QgdOG6rXAgdHJ1bmcgY2jhu6cgeeG6v3Ug4bufIMSR4buZIHRyb25nIFNJMSB2w6AgU0kyLCDEkWnhu4F1IG7DoHkgbMOgIGjhu6NwIGzDrSBi4bufaSB2w6wg4bufIGJp4buDdSDEkeG7kyAyLjIga2hpIHBow6JuIHTDrWNoIG3hu6ljIGdpw6EgdHJ1bmcgYsOsbmggY+G7p2EgdOG7q25nIMSR4buZIHRyb25nIHRow6wgU0kxIHbDoCBTSTIgbMOgIDIgbmjDs20gxJHhu5kgdHJvbmcgZOG6q24gxJHhuqd1IOG7nyBnacOhLiBW4bqteSB0YSBjw7MgdGjhu4Mga+G6v3QgbHXhuq1uIHLhurFuZyBt4bupYyBnacOhIHPhur0gZ2nhuqNtIGThuqduIHThu6sgKipTSTIgLSBTSTEgLSBWUzIgLSBWUzEgLSBWVlMyIC0gVlZTMSAtIElGIEkxKioNCg0KDQo=