Nhiệm vụ 5

Ở nhiệm vụ này chúng ta sẽ tự tìm 1 dataset và vẽ 20 đồ thị để mô tả và phân tích cho dữ liệu được chứa trong dataset này.

Ở đây, ta sẽ phân tích dataset CR7, đây là 1 dataset bao gồm thông số những bàn thắng của Cristiano Ronaldo trong sự nghiệp của anh ấy tính tới mùa giải 22/23

Một số thông tin về Dataset

Trước tiên, ta gán dataset vào trong Rstudio

library(csv)
## Warning: package 'csv' was built under R version 4.3.3
Long <- read.csv('D:/R/CR7.csv', header = T)

Sau đó sử dụng lệnh str để xem được các thông số của bộ dữ liệu

str(Long)
## 'data.frame':    710 obs. of  13 variables:
##  $ Season          : chr  "02/03" "02/03" "02/03" "02/03" ...
##  $ Competition     : chr  "Liga Portugal" "Liga Portugal" "Liga Portugal" "Taca de Portugal Placard" ...
##  $ Matchday        : chr  "6" "6" "8" "Fourth Round" ...
##  $ Date            : chr  "10-07-02" "10-07-02" "10/26/02" "11/24/02" ...
##  $ Venue           : chr  "H" "H" "A" "H" ...
##  $ Club            : chr  "Sporting CP" "Sporting CP" "Sporting CP" "Sporting CP" ...
##  $ Opponent        : chr  "Moreirense FC" "Moreirense FC" "Boavista FC" "CD Estarreja" ...
##  $ Result          : chr  "3:00" "3:00" "1:02" "4:01" ...
##  $ Playing_Position: chr  "LW" "LW" "" "" ...
##  $ Minute          : chr  "34" "90+5" "88" "67" ...
##  $ At_score        : chr  "2:00" "3:00" "1:02" "3:00" ...
##  $ Type            : chr  "Solo run" "Header" "Right-footed shot" "Left-footed shot" ...
##  $ Goal_assist     : chr  "" "Rui Jorge" "Carlos Martins" "Cesar Prates" ...

Ở đây, một số thông tin cơ bản ta có thể thấy đó là bộ dữ liệu này có 710 quan sát và 13 cột. Trong đó bao gồm

-Season: Mùa giải

-Competition: Giải đấu

-Matchday: Vòng đấu

-Date: Ngày duễn ra

-Venue: Sân nhà hay khách

-Club: CLB

-Opponent: Đối thủ

-Result: Kết quả

-Playing_Position: Vị trí thi đấu

-Minute: Phút ghi bàn

-At_score: Tỉ số

-Type: Cách ghi bàn

-Goal_assist: Người kiến tạo

Bắt đầu vẽ đồ thị và phân tích

Biểu đồ 1: Tổng số bàn thắng mà CR7 đã ghi bàn cho các CLB mà anh đã thi đấu tính

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.1
## ✔ 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
library(scales)
## 
## Attaching package: 'scales'
## 
## The following object is masked from 'package:purrr':
## 
##     discard
## 
## The following object is masked from 'package:readr':
## 
##     col_factor
Long %>% group_by(Club) %>% summarise(n = n()) %>%
  ggplot(aes(Club,n)) +
    geom_col(fill='orange') +
    geom_text(aes(label = n),vjust = 2, color = 'black') +
    labs(x = 'Loại', y = 'CLB')

### Biểu đồ 2 : bàn thắng mà CR7 đã ghi bàn theo từng vị trí

Long %>% group_by(Playing_Position) %>% summarise(n = n()) %>%
  ggplot(aes(Playing_Position,n)) +
    geom_col(fill='orange') +
    geom_text(aes(label = n),vjust = 2, color = 'black') +
    labs(x = 'Loại', y = 'CLB')

Biểu đồ 3: bàn thắng mà CR7 đã ghi bàn theo các cách khác nhau

Long %>% group_by(Type) %>% summarise(n = n()) %>%
  ggplot(aes(Type,n)) +
    geom_col(fill='orange') +
    geom_text(aes(label = n),vjust = 2, color = 'black') +
    labs(x = 'Loại', y = 'CLB')

Biểu đồ 4: Hàm mật độ để coi cách thức ghi bàn của Cr7 ở mỗi CLb

Long %>% ggplot(aes(x = Club, fill = Competition)) +
  geom_density()
## Warning: Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

Biểu đồ 5: Hàm mật độ để coi cách thức ghi bàn của Cr7 ở mỗi vị trí

Long %>% ggplot(aes(x = Playing_Position, fill = Competition)) +
  geom_density()
## Warning: Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

Biểu đồ 6: độ trải bàn thắng của Cr7 ở các giải đấu

Long %>% ggplot(aes(x = Type)) +
    geom_bar() +
    labs(x = 'Giải đấu', y = 'Số lượng') +
    coord_flip() 

Laliga chính là giải đấu CR7 ghi nhiều nhất với ngay sau đó là UCL

Biểu đồ 7: hàm mật độ để xem vị trí của CR7 trong các giải đấu

Long %>% ggplot(aes(x = Playing_Position)) +
  geom_density(fill = 'green') +
  facet_wrap(~Type)
## Warning: Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

Biểu đồ 8: Biểu đồ cách thức ghi bàn theo màu sắc

Long %>% group_by(Type) %>% summarise(n = n()) %>%
  ggplot(aes(x = '', y = n,fill = Type)) +
    geom_col() +
    geom_text(aes(label = n),position = position_stack(vjust = 2))

Biểu đồ 9: Biểu đồ tròn thể hiện bàn thắng theo giải đấu

Long %>% group_by(Competition) %>% summarise(n = n()) %>%
  ggplot(aes(x = '', y = n,fill = Competition)) +
    geom_col() +
    coord_polar('y')

Biểu đồ 10: biểu đồ mật độ giải đấu theo CLB

Long %>% ggplot(aes(x = Club, fill = Competition)) +
  geom_density()
## Warning: Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

Biểu đồ 11: Hàm mật độ bàn thắng theo từng giải đấu

Long %>% ggplot(aes(x = Club)) +
  geom_density(fill = 'orange') +
  facet_wrap(~Competition)
## Warning: Groups with fewer than two data points have been dropped.
## Groups with fewer than two data points have been dropped.
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning
## -Inf

Biểu đồ 12

Long %>% ggplot(aes(x = Club, y = Competition)) +
  geom_point() +
  xlab('CLB') + 
  ylab('Giải đấu')

Biểu đồ 13: Biểu đồ tròn thể hiện bàn thắng của Cr7 ở từng CLB

Long %>% group_by(Club) %>% summarise(n = n()) %>%
  ggplot(aes(x = '', y = n,fill = Club)) +
    geom_col(Club = 'black') +
    coord_polar('y') +
    geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
    theme_void()
## Warning in geom_col(Club = "black"): Ignoring unknown parameters: `Club`

Biểu đồ 14: các bàn thắng được ghi ở những giải đấu

Long %>% group_by(Competition) %>% summarise(n = n()) %>%
  ggplot(aes(Competition,n)) +
    geom_col(fill='orange') +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Giải đấu', y = 'số lượng')

CR7 đã ghi bàn tất cả 17 giải đấu trải dài từ Copa del Ray cho đến Saudi proleague

Một số giải đấu nổi bật: Laliga: 311 bàn Copa del Ray: 22 bàn Premier League: 103 bàn Seria A: 81 bàn UCL: 140 bàn

Biểu đồ 15: các bàn thắng này được CR7 ghi khi chơi ở vị trí nào

Long %>% group_by(Playing_Position) %>% summarise(n = n()) %>%
  ggplot(aes(Playing_Position,n)) +
    geom_col(fill='orange') +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Vị trí', y = 'Số lượng')

Ta có : CF: 212 LW: 361 RW: 79 Còn lại 58 bàn bộ dữ liệu không cho ta biết CR7 ghi bàn ở vị trí nào

Biểu đồ 16: so sánh số bàn thắng CR7 ghi được khi đá sân nhà và sân khách

Long %>% group_by(Club,Venue) %>% summarise(n=n()) %>%
  ggplot(aes(x = Club,y = n)) +
    geom_col(position = 'dodge') +
    facet_wrap(~Venue) +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Loại', y = 'Số lượng')
## `summarise()` has grouped output by 'Club'. You can override using the
## `.groups` argument.

Nhìn vào bảng, ta có thể thấy rằng khi được đá ở sân nhà (H) hiệu suất ghi bàn của CR7 có phần nhỉnh hơn khi phải đá ở sân khách (A)

Biểu đồ 17: so cách thức ghi bàn của CR7 khi được thi đấu ở các vị trị khác nhau

Long %>% group_by(Playing_Position,Type) %>% summarise(n=n()) %>%
  ggplot(aes(x = Playing_Position,y = n)) +
    geom_col(position = 'dodge') +
    facet_wrap(~Type) +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Loại', y = 'Số lượng')
## `summarise()` has grouped output by 'Playing_Position'. You can override using
## the `.groups` argument.

Nhìn vào các bảng số liệu, dễ dàng nhận ra rằng CR7 ghi bàn nhiều nhất khi được đá ở vị trị cánh trái trên hàng tấn công(LW) và cách thức mà CR7 dùng để ghi bàn nhiều nhất là sử dụng chân phải

Biểu đồ 18: xu hướng thi đấu ở mỗi clb của cr7

Long %>% group_by(Club,Playing_Position) %>% summarise(n=n()) %>%
  ggplot(aes(x = Playing_Position,y = n)) +
    geom_col(position = 'dodge') +
    facet_wrap(~Club) +
    geom_text(aes(label = n),vjust = 0, color = 'black') +
    labs(x = 'Loại', y = 'Số lượng')
## `summarise()` has grouped output by 'Club'. You can override using the
## `.groups` argument.

Ta thấy ở real madrid, cr7 đá ở LW là chủ yếu tuy nhiêu CF lại là vị trí mà CR7 thi đấu nhiều hơn sau khi anh rời real

Biểu đồ 19:So sánh 2 vị trí RW và LW của Cr7

Long <- Long %>% group_by(Club, Playing_Position) %>% summarise(n = n())
## `summarise()` has grouped output by 'Club'. You can override using the
## `.groups` argument.
Long %>% ggplot(aes(x = Club, y = n)) +
  geom_col(data = Long %>% filter(Playing_Position == 'RW'), fill = 'red') +
  geom_col(data = Long %>% filter(Playing_Position == 'LW'), fill = 'blue')

Từ bảng ta có thể thấy Cr7 chỉ chủ yếu thi đấu LW và chỉ thay đổi đá RW khi thi đấu ở MU

Biểu đồ 20: So sánh độ trải bàn thắng theo CLB

Long %>% ggplot(aes(x = Club)) +
    geom_bar() +
    labs(x = 'CLB', y = 'Số lượng') +
    coord_flip() 

LS0tDQp0aXRsZTogIk5WNSINCmF1dGhvcjogIk1UTG9uZ2dnIg0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUg6JU06JVMsICVkIC0gJW0gLSAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGRmX3ByaW50OiBrYWJsZQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50Og0KICAgIGV4dHJhX2RlcGVuZGVuY2llczoNCiAgICAgIHZpZXRuYW06IHV0ZjgNCiAgICB0b2M6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBjbGFzcy5zb3VyY2UgPSAibnVtYmVyTGluZXMgbGluZUFuY2hvcnMiLCANCiAgY2xhc3Mub3V0cHV0ID0gYygibnVtYmVyTGluZXMgbGluZUFuY2hvcnMgY2h1bmtvdXQiKSANCikNCg0KIyBBZGQgc29tZSBhcmJpdHJhcnkgc2V0dXAgY29kZXMNCmBgYA0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQpkaXYuc291cmNlQ29kZSBwcmUuY2h1bmtvdXQgew0KICBiYWNrZ3JvdW5kOiB3aGl0ZTsNCn0NCmBgYA0KDQojIE5oaeG7h20gduG7pSA1DQrhu54gbmhp4buHbSB24bulIG7DoHkgY2jDum5nIHRhIHPhur0gdOG7sSB0w6xtIDEgZGF0YXNldCB2w6AgduG6vSAyMCDEkeG7kyB0aOG7iyDEkeG7gyBtw7QgdOG6oyB2w6AgcGjDom4gdMOtY2ggY2hvIGThu68gbGnhu4d1IMSRxrDhu6NjIGNo4bupYSB0cm9uZyBkYXRhc2V0IG7DoHkuDQoNCuG7niDEkcOieSwgdGEgc+G6vSBwaMOibiB0w61jaCBkYXRhc2V0ICoqKkNSNyoqKiwgxJHDonkgbMOgIDEgZGF0YXNldCBiYW8gZ+G7k20gdGjDtG5nIHPhu5Egbmjhu69uZyBiw6BuIHRo4bqvbmcgY+G7p2EgQ3Jpc3RpYW5vIFJvbmFsZG8gdHJvbmcgc+G7sSBuZ2hp4buHcCBj4bunYSBhbmgg4bqleSB0w61uaCB04bubaSBtw7lhIGdp4bqjaSAyMi8yMw0KDQojIyBN4buZdCBz4buRIHRow7RuZyB0aW4gduG7gSBEYXRhc2V0DQpUcsaw4bubYyB0acOqbiwgdGEgZ8OhbiBkYXRhc2V0IHbDoG8gdHJvbmcgUnN0dWRpbyANCmBgYHtyfQ0KbGlicmFyeShjc3YpDQoNCkxvbmcgPC0gcmVhZC5jc3YoJ0Q6L1IvQ1I3LmNzdicsIGhlYWRlciA9IFQpDQpgYGANClNhdSDEkcOzIHPhu60gZOG7pW5nIGzhu4duaCBzdHIgxJHhu4MgeGVtIMSRxrDhu6NjIGPDoWMgdGjDtG5nIHPhu5EgY+G7p2EgYuG7mSBk4buvIGxp4buHdQ0KYGBge3J9DQpzdHIoTG9uZykNCmBgYA0K4bueIMSRw6J5LCBt4buZdCBz4buRIHRow7RuZyB0aW4gY8ahIGLhuqNuIHRhIGPDsyB0aOG7gyB0aOG6pXkgxJHDsyBsw6AgYuG7mSBk4buvIGxp4buHdSBuw6B5IGPDsyA3MTAgcXVhbiBzw6F0IHbDoCAxMyBj4buZdC4gVHJvbmcgxJHDsyBiYW8gZ+G7k20NCg0KLVNlYXNvbjogTcO5YSBnaeG6o2kNCg0KLUNvbXBldGl0aW9uOiBHaeG6o2kgxJHhuqV1DQoNCi1NYXRjaGRheTogVsOybmcgxJHhuqV1DQoNCi1EYXRlOiBOZ8OgeSBkdeG7hW4gcmENCg0KLVZlbnVlOiBTw6JuIG5ow6AgaGF5IGtow6FjaA0KDQotQ2x1YjogQ0xCDQoNCi1PcHBvbmVudDogxJDhu5FpIHRo4bunDQoNCi1SZXN1bHQ6IEvhur90IHF14bqjDQoNCi1QbGF5aW5nX1Bvc2l0aW9uOiBW4buLIHRyw60gdGhpIMSR4bqldQ0KDQotTWludXRlOiBQaMO6dCBnaGkgYsOgbg0KDQotQXRfc2NvcmU6IFThu4kgc+G7kQ0KDQotVHlwZTogQ8OhY2ggZ2hpIGLDoG4NCg0KLUdvYWxfYXNzaXN0OiBOZ8aw4budaSBraeG6v24gdOG6oW8NCg0KIyMgQuG6r3QgxJHhuqd1IHbhur0gxJHhu5MgdGjhu4sgdsOgIHBow6JuIHTDrWNoDQoNCiMjIyBCaeG7g3UgxJHhu5MgMTogVOG7lW5nIHPhu5EgYsOgbiB0aOG6r25nIG3DoCBDUjcgxJHDoyBnaGkgYsOgbiBjaG8gY8OhYyBDTEIgbcOgIGFuaCDEkcOjIHRoaSDEkeG6pXUgdMOtbmggDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShzY2FsZXMpDQpMb25nICU+JSBncm91cF9ieShDbHViKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKENsdWIsbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdvcmFuZ2UnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnQ0xCJykNCmBgYA0KIyMjIEJp4buDdSDEkeG7kyAyIDogYsOgbiB0aOG6r25nIG3DoCBDUjcgxJHDoyBnaGkgYsOgbiB0aGVvIHThu6tuZyB24buLIHRyw60NCmBgYHtyfQ0KTG9uZyAlPiUgZ3JvdXBfYnkoUGxheWluZ19Qb3NpdGlvbikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhQbGF5aW5nX1Bvc2l0aW9uLG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0nb3JhbmdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSx2anVzdCA9IDIsIGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGxhYnMoeCA9ICdMb+G6oWknLCB5ID0gJ0NMQicpDQpgYGANCg0KIyMjIEJp4buDdSDEkeG7kyAzOiBiw6BuIHRo4bqvbmcgbcOgIENSNyDEkcOjIGdoaSBiw6BuIHRoZW8gY8OhYyBjw6FjaCBraMOhYyBuaGF1DQpgYGB7cn0NCkxvbmcgJT4lIGdyb3VwX2J5KFR5cGUpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoVHlwZSxuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J29yYW5nZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdDTEInKQ0KYGBgDQoNCiMjIyBCaeG7g3UgxJHhu5MgNDogSMOgbSBt4bqtdCDEkeG7mSDEkeG7gyBjb2kgY8OhY2ggdGjhu6ljIGdoaSBiw6BuIGPhu6dhIENyNyDhu58gbeG7l2kgQ0xiDQpgYGB7cn0NCkxvbmcgJT4lIGdncGxvdChhZXMoeCA9IENsdWIsIGZpbGwgPSBDb21wZXRpdGlvbikpICsNCiAgZ2VvbV9kZW5zaXR5KCkNCmBgYA0KDQojIyMgQmnhu4N1IMSR4buTIDU6IEjDoG0gbeG6rXQgxJHhu5kgxJHhu4MgY29pIGPDoWNoIHRo4bupYyBnaGkgYsOgbiBj4bunYSBDcjcg4bufIG3hu5dpIHbhu4sgdHLDrQ0KYGBge3J9DQpMb25nICU+JSBnZ3Bsb3QoYWVzKHggPSBQbGF5aW5nX1Bvc2l0aW9uLCBmaWxsID0gQ29tcGV0aXRpb24pKSArDQogIGdlb21fZGVuc2l0eSgpDQpgYGANCg0KIyMjIEJp4buDdSDEkeG7kyA2OiDEkeG7mSB0cuG6o2kgYsOgbiB0aOG6r25nIGPhu6dhIENyNyDhu58gY8OhYyBnaeG6o2kgxJHhuqV1DQpgYGB7cn0NCkxvbmcgJT4lIGdncGxvdChhZXMoeCA9IFR5cGUpKSArDQogICAgZ2VvbV9iYXIoKSArDQogICAgbGFicyh4ID0gJ0dp4bqjaSDEkeG6pXUnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKSArDQogICAgY29vcmRfZmxpcCgpIA0KYGBgDQpMYWxpZ2EgY2jDrW5oIGzDoCBnaeG6o2kgxJHhuqV1IENSNyBnaGkgbmhp4buBdSBuaOG6pXQgduG7m2kgbmdheSBzYXUgxJHDsyBsw6AgVUNMDQoNCiMjIyBCaeG7g3UgxJHhu5MgNzogaMOgbSBt4bqtdCDEkeG7mSDEkeG7gyB4ZW0gduG7iyB0csOtIGPhu6dhIENSNyB0cm9uZyBjw6FjIGdp4bqjaSDEkeG6pXUNCmBgYHtyfQ0KTG9uZyAlPiUgZ2dwbG90KGFlcyh4ID0gUGxheWluZ19Qb3NpdGlvbikpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAnZ3JlZW4nKSArDQogIGZhY2V0X3dyYXAoflR5cGUpDQpgYGANCg0KIyMjIEJp4buDdSDEkeG7kyA4OiBCaeG7g3UgxJHhu5MgY8OhY2ggdGjhu6ljIGdoaSBiw6BuIHRoZW8gbcOgdSBz4bqvYw0KYGBge3J9DQpMb25nICU+JSBncm91cF9ieShUeXBlKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAnJywgeSA9IG4sZmlsbCA9IFR5cGUpKSArDQogICAgZ2VvbV9jb2woKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAyKSkNCmBgYA0KDQojIyMgQmnhu4N1IMSR4buTIDk6IEJp4buDdSDEkeG7kyB0csOybiB0aOG7gyBoaeG7h24gYsOgbiB0aOG6r25nIHRoZW8gZ2nhuqNpIMSR4bqldQ0KYGBge3J9DQpMb25nICU+JSBncm91cF9ieShDb21wZXRpdGlvbikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBDb21wZXRpdGlvbikpICsNCiAgICBnZW9tX2NvbCgpICsNCiAgICBjb29yZF9wb2xhcigneScpDQpgYGANCg0KIyMjIEJp4buDdSDEkeG7kyAxMDogYmnhu4N1IMSR4buTIG3huq10IMSR4buZIGdp4bqjaSDEkeG6pXUgdGhlbyBDTEINCmBgYHtyfQ0KTG9uZyAlPiUgZ2dwbG90KGFlcyh4ID0gQ2x1YiwgZmlsbCA9IENvbXBldGl0aW9uKSkgKw0KICBnZW9tX2RlbnNpdHkoKQ0KYGBgDQoNCiMjIyBCaeG7g3UgxJHhu5MgMTE6IEjDoG0gbeG6rXQgxJHhu5kgYsOgbiB0aOG6r25nIHRoZW8gdOG7q25nIGdp4bqjaSDEkeG6pXUNCmBgYHtyfQ0KTG9uZyAlPiUgZ2dwbG90KGFlcyh4ID0gQ2x1YikpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAnb3JhbmdlJykgKw0KICBmYWNldF93cmFwKH5Db21wZXRpdGlvbikNCmBgYA0KDQojIyMgQmnhu4N1IMSR4buTIDEyDQpgYGB7cn0NCkxvbmcgJT4lIGdncGxvdChhZXMoeCA9IENsdWIsIHkgPSBDb21wZXRpdGlvbikpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgeGxhYignQ0xCJykgKyANCiAgeWxhYignR2nhuqNpIMSR4bqldScpDQpgYGANCg0KIyMjIEJp4buDdSDEkeG7kyAxMzogQmnhu4N1IMSR4buTIHRyw7JuIHRo4buDIGhp4buHbiBiw6BuIHRo4bqvbmcgY+G7p2EgQ3I3IOG7nyB04burbmcgQ0xCDQpgYGB7cn0NCkxvbmcgJT4lIGdyb3VwX2J5KENsdWIpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9ICcnLCB5ID0gbixmaWxsID0gQ2x1YikpICsNCiAgICBnZW9tX2NvbChDbHViID0gJ2JsYWNrJykgKw0KICAgIGNvb3JkX3BvbGFyKCd5JykgKw0KICAgIGdlb21fdGV4dChhZXMoeCA9IDEuMywgbGFiZWwgPSBuKSxwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gLjUpKSArDQogICAgdGhlbWVfdm9pZCgpDQpgYGANCg0KIyMjIEJp4buDdSDEkeG7kyAxNDogY8OhYyBiw6BuIHRo4bqvbmcgIMSRxrDhu6NjIGdoaSDhu58gbmjhu69uZyBnaeG6o2kgxJHhuqV1IA0KYGBge3J9DQpMb25nICU+JSBncm91cF9ieShDb21wZXRpdGlvbikgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhDb21wZXRpdGlvbixuKSkgKw0KICAgIGdlb21fY29sKGZpbGw9J29yYW5nZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnR2nhuqNpIMSR4bqldScsIHkgPSAnc+G7kSBsxrDhu6NuZycpDQpgYGANCkNSNyDEkcOjIGdoaSBiw6BuIHThuqV0IGPhuqMgMTcgZ2nhuqNpIMSR4bqldSB0cuG6o2kgZMOgaSB04burIENvcGEgZGVsIFJheSBjaG8gxJHhur9uIFNhdWRpIHByb2xlYWd1ZQ0KDQpN4buZdCBz4buRIGdp4bqjaSDEkeG6pXUgbuG7lWkgYuG6rXQ6DQpMYWxpZ2E6IDMxMSBiw6BuDQpDb3BhIGRlbCBSYXk6IDIyIGLDoG4NClByZW1pZXIgTGVhZ3VlOiAxMDMgYsOgbg0KU2VyaWEgQTogODEgYsOgbg0KVUNMOiAxNDAgYsOgbg0KDQojIyMgQmnhu4N1IMSR4buTIDE1OiBjw6FjIGLDoG4gdGjhuq9uZyBuw6B5IMSRxrDhu6NjIENSNyBnaGkga2hpIGNoxqFpIOG7nyB24buLIHRyw60gbsOgbw0KYGBge3J9DQpMb25nICU+JSBncm91cF9ieShQbGF5aW5nX1Bvc2l0aW9uKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKFBsYXlpbmdfUG9zaXRpb24sbikpICsNCiAgICBnZW9tX2NvbChmaWxsPSdvcmFuZ2UnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ1bhu4sgdHLDrScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANClRhIGPDsyA6DQpDRjogMjEyDQpMVzogMzYxDQpSVzogNzkNCkPDsm4gbOG6oWkgNTggYsOgbiBi4buZIGThu68gbGnhu4d1IGtow7RuZyBjaG8gdGEgYmnhur90IENSNyBnaGkgYsOgbiDhu58gduG7iyB0csOtIG7DoG8NCg0KIyMjIEJp4buDdSDEkeG7kyAxNjogc28gc8Ohbmggc+G7kSBiw6BuIHRo4bqvbmcgQ1I3IGdoaSDEkcaw4bujYyBraGkgxJHDoSBzw6JuIG5ow6AgdsOgIHPDom4ga2jDoWNoDQpgYGB7cn0NCkxvbmcgJT4lIGdyb3VwX2J5KENsdWIsVmVudWUpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBDbHViLHkgPSBuKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAoflZlbnVlKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANCk5ow6xuIHbDoG8gYuG6o25nLCB0YSBjw7MgdGjhu4MgdGjhuqV5IHLhurFuZyBraGkgxJHGsOG7o2MgxJHDoSDhu58gc8OibiBuaMOgIChIKSBoaeG7h3Ugc3XhuqV0IGdoaSBiw6BuIGPhu6dhIENSNyBjw7MgcGjhuqduIG5o4buJbmggaMahbiBraGkgcGjhuqNpIMSRw6Eg4bufIHPDom4ga2jDoWNoIChBKQ0KDQojIyMgQmnhu4N1IMSR4buTIDE3OiBzbyBjw6FjaCB0aOG7qWMgZ2hpIGLDoG4gY+G7p2EgQ1I3IGtoaSDEkcaw4bujYyB0aGkgxJHhuqV1IOG7nyBjw6FjIHbhu4sgdHLhu4sga2jDoWMgbmhhdQ0KYGBge3J9DQpMb25nICU+JSBncm91cF9ieShQbGF5aW5nX1Bvc2l0aW9uLFR5cGUpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBQbGF5aW5nX1Bvc2l0aW9uLHkgPSBuKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGZhY2V0X3dyYXAoflR5cGUpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAwLCBjb2xvciA9ICdibGFjaycpICsNCiAgICBsYWJzKHggPSAnTG/huqFpJywgeSA9ICdT4buRIGzGsOG7o25nJykNCmBgYA0KTmjDrG4gdsOgbyBjw6FjIGLhuqNuZyBz4buRIGxp4buHdSwgZOG7hSBkw6BuZyBuaOG6rW4gcmEgcuG6sW5nIENSNyBnaGkgYsOgbiBuaGnhu4F1IG5o4bqldCBraGkgxJHGsOG7o2MgxJHDoSDhu58gduG7iyB0cuG7iyBjw6FuaCB0csOhaSB0csOqbiBow6BuZyB04bqlbiBjw7RuZyhMVykgdsOgIGPDoWNoIHRo4bupYyBtw6AgQ1I3IGTDuW5nIMSR4buDIGdoaSBiw6BuIG5oaeG7gXUgbmjhuqV0IGzDoCBz4butIGThu6VuZyBjaMOibiBwaOG6o2kNCg0KIyMjIEJp4buDdSDEkeG7kyAxODogIHh1IGjGsOG7m25nIHRoaSDEkeG6pXUg4bufIG3hu5dpIGNsYiBj4bunYSBjcjcNCmBgYHtyfQ0KTG9uZyAlPiUgZ3JvdXBfYnkoQ2x1YixQbGF5aW5nX1Bvc2l0aW9uKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gUGxheWluZ19Qb3NpdGlvbix5ID0gbikpICsNCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsNCiAgICBmYWNldF93cmFwKH5DbHViKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMCwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ0xv4bqhaScsIHkgPSAnU+G7kSBsxrDhu6NuZycpDQpgYGANClRhIHRo4bqleSDhu58gcmVhbCBtYWRyaWQsIGNyNyDEkcOhIOG7nyBMVyBsw6AgY2jhu6cgeeG6v3UgdHV5IG5oacOqdSBDRiBs4bqhaSBsw6AgduG7iyB0csOtIG3DoCBDUjcgdGhpIMSR4bqldSBuaGnhu4F1IGjGoW4gc2F1IGtoaSBhbmggcuG7nWkgcmVhbA0KDQojIyMgQmnhu4N1IMSR4buTIDE5OlNvIHPDoW5oIDIgduG7iyB0csOtIFJXIHbDoCBMVyBj4bunYSBDcjcNCmBgYHtyfQ0KTG9uZyA8LSBMb25nICU+JSBncm91cF9ieShDbHViLCBQbGF5aW5nX1Bvc2l0aW9uKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpDQpMb25nICU+JSBnZ3Bsb3QoYWVzKHggPSBDbHViLCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IExvbmcgJT4lIGZpbHRlcihQbGF5aW5nX1Bvc2l0aW9uID09ICdSVycpLCBmaWxsID0gJ3JlZCcpICsNCiAgZ2VvbV9jb2woZGF0YSA9IExvbmcgJT4lIGZpbHRlcihQbGF5aW5nX1Bvc2l0aW9uID09ICdMVycpLCBmaWxsID0gJ2JsdWUnKQ0KYGBgDQpU4burIGLhuqNuZyB0YSBjw7MgdGjhu4MgdGjhuqV5IENyNyBjaOG7iSBjaOG7pyB54bq/dSB0aGkgxJHhuqV1IExXIHbDoCBjaOG7iSB0aGF5IMSR4buVaSDEkcOhIFJXIGtoaSB0aGkgxJHhuqV1IOG7nyBNVQ0KDQojIyMgQmnhu4N1IMSR4buTIDIwOiBTbyBzw6FuaCDEkeG7mSB0cuG6o2kgYsOgbiB0aOG6r25nIHRoZW8gQ0xCDQpgYGB7cn0NCkxvbmcgJT4lIGdncGxvdChhZXMoeCA9IENsdWIpKSArDQogICAgZ2VvbV9iYXIoKSArDQogICAgbGFicyh4ID0gJ0NMQicsIHkgPSAnU+G7kSBsxrDhu6NuZycpICsNCiAgICBjb29yZF9mbGlwKCkgDQpgYGANCg0KDQoNCg0K