THÔNG TIN VỀ CHẤT LƯỢNG KHÔNG KHÍ TẠI NEW YORK TỪ THÁNG 5 NĂM 1973 ĐẾN THÁNG 9 NĂM 1973

  1. Thông tin bộ dữ liệu
  • Ozone: Nồng độ ozone (O3)

  • Solar.R: Bức xạ mặt trời

  • Wind: Tốc độ gió

  • Temp: Nhiệt độ

  • Month: Tháng

  • Day: Ngày

  • Bộ dữ liệu có 153 quan sát, 6 biến

library(datasets)
data(package = 'datasets')
library(ggplot2)
data(package = 'ggplot2')
dq <- airquality

Đồ thị số 1

library(tidyverse)
library(scales)
  dq <- airquality
    dq %>% group_by(Wind) %>% summarise(n = n()) %>%
  ggplot(aes(Wind,n)) +
    geom_col(fill='skyblue') +
    geom_text(aes(label = n),vjust = 2, color = 'red') +
    labs(x = 'Tốc độ gió', y = 'Số lượng')

  • Ta Phân loại tốc độ gió theo từng mức độ và tính số lượng của từng mức độ.

  • x là từng mức độ của tốc độ gió, y là số lượng của từng mức .

  • Các số liệu có màu đỏ, được điều chỉnh ở vị trí dọc cách cột 2 đơn vị. Màu của các cột là màu xanh da trời.

  • Biểu đồ thể hiện sự phân bố số lượng theo từng mức tốc độ gió.

  • Có một số mức tốc độ gió có số lượng cao hơn, cụ thể là:

    • Mức 5-10 mph (dặm/giờ) có số lượng cao nhất.

    • Mức 10-15 mph có số lượng cao thứ hai.

  • Có một số mức tốc độ gió có số lượng thấp hơn, cụ thể là:

    • Mức dưới 5 mph và trên 20 mph có số lượng thấp nhất.

Đồ thị số 2

dq <- airquality
dq <- dq %>% group_by(Month, Ozone) %>% summarise(n = n())
## `summarise()` has grouped output by 'Month'. You can override using the
## `.groups` argument.
dq %>% ggplot(aes(x = Month, y = n)) +
  geom_col(data = dq %>% filter( Month== '5'), fill = 'purple') +
  geom_col(data = dq %>% filter(Month == '9'), fill = 'turquoise')

  • Ta phân loại nồng độ theo các tháng sau đó tính số lượng .
  • Ở biểu đồ trên thì ta gắn x là Month, y là nồng độ ozone của 2 tháng 5 và 9;
  • Ta sẽ lọc nồng độ ozone của tháng 5, cột biểu đồ có màu tím và nồng độ của tháng 9, biểu đồ có màu xanh ngọc.
  • Tổng số lượng nồng độ ozone trong tháng 5 cao hơn so với tháng 9.
  • Tổng số lượng nồng độ ozone trong tháng 5 với mức trung bình khoảng 31 ppb.
  • Tổng số lượng nồng độ ozone trong tháng 9 với mức trung bình khoảng 30 ppb.

Đồ thị số 3

dq <- airquality
dq %>% ggplot(aes(x = Solar.R)) +
  geom_histogram(binwidth = 10, fill = 'blue', color = 'red')
## Warning: Removed 7 rows containing non-finite values (`stat_bin()`).

- Biểu đồ thể hiện sự thay đổi cường độ bức xạ mặt trời

  • Bức xạ ở mức từ 200 đến 300 có có số lượng cường độ là nhiều nhất

  • Bức xạ ở mức từ 0 đến 100 có có số lượng cường độ là ít nhất

Đồ thị số 4

dq <- airquality
dq %>% ggplot(aes(x = Wind)) +
  geom_density(fill = 'red')

- Qua biểu đồ ta thấy hầu hết tốc độ gió đều nằm trong khoảng 5 đến 15

  • Ở mức tốc độ gió đạt 10mph có số lượng cao nhất

Đồ thị số 5

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

  • Biểu đồ biểu diễn số lượng từng mức nhiệt độ

  • Ở mức nhiệt độ càng cao thì có số lượng càng ít

  • Số lượng nhiệt độ nhiều nhất là 11 với mức nhiệt độ là từ 70 đến 80

Đồ thị số 6

dq <- airquality
dq %>% ggplot(aes(x = Day, y = Month, color = Solar.R)) +
  geom_point()

- Biểu đồ biểu diễn bức xạ mặt trời theo từng tháng từ tháng 5 đến tháng 9

  • Qua đồ thị ta thấy tháng 7 ,8 là những tháng có mức bức xạ cao nhất với nhiều số lượng bức xạ từ 200 đến 300

Đồ thị số 7

dq <- airquality
    dq %>% group_by(Temp) %>% summarise(n = n()) %>%
  ggplot(aes(Temp,n)) +
    geom_area(fill='skyblue') +
    geom_text(aes(label = n),vjust = 2, color = 'red') +
    labs(x = 'Nhiệt độ', y = 'Số lượng')

- Biểu đồ miền biểu diễn số lượng các mức nhiệt độ

  • Qua biểu đồ ta thấy ở nhiệt độ 80 độ có số lượng nhiều nhất là 11

  • Số lượng có xu hướng tăng dần từ mức 60 đến 80 và sau đó giảm dần từ 80 xuống 90

Đồ thị số 8

dq <- airquality
    dq %>% ggplot(aes(x = Temp)) + 
        geom_density(color = 'red', fill = 'skyblue')+
        labs( x = 'Nhiệt độ')

- Qua biểu đồ ta thấy được: mật độ nhiệt độ phân phối không đồng đều

  • Nhiệt độ ở mức 80 độ có mật độ cao nhất

  • Mức nhiệt độ từ 60 có mật độ tăng dần đến 80 độ sau đó giảm dần xuống 90

Đồ thị số 9

dq <- airquality
    dq %>% group_by(Wind) %>% summarise(n = n()) %>%
  ggplot(aes(Wind,n)) +
    geom_bin2d(fill='pink') +
    geom_text(aes(label = n),vjust = 2, color = 'black') +
    labs(x = 'Tốc độ gió', y = 'Số lượng')

- Đây là biểu đồ mật độ 2D, chia dữ liệu thành các ô vuông, mỗi ô vuông là 1 dữ liệu

  • Biểu đồ biểu diễn số lượng từng mức của tốc độ gió

  • Ở mức 5 đến 10 có số lượng tốc độ gió nhiều nhất

  • Ở mức 10 đến 15 chứa số lượng tốc độ gió cao nhất là 15

Đồ thị số 10

dq <- airquality
    dq %>% ggplot(aes(x = Solar.R)) + 
        geom_density(color = 'black', fill = 'pink')+
        labs( x = 'Bức xạ mặt trời')
## Warning: Removed 7 rows containing non-finite values (`stat_density()`).

  • Qua đồ thị ta thấy mật độ bức xạ mặt trời cao nhất nằm vào khoảng 250

    • Mật độ phân phối không đồng đều, tăng giảm liên tục

Đồ thị số 11

dq <- airquality
    dq %>% ggplot(aes(x = Ozone)) + 
        geom_density(color = 'red', fill = 'blue')+
        labs( x = 'nồng độ ozone')
## Warning: Removed 37 rows containing non-finite values (`stat_density()`).

- Mật độ về nồng độ ozone tăng cao nhất ở khoảng dưới 50, sau đó giảm dần xuống tận 150

  • Vị trí có mật độ cao nhất nằm tầm khoảng 25

Đồ thị số 12

dq <- airquality
dq %>% group_by(Month) %>% summarise(m = mean(Wind)) %>%
  ggplot(aes(x = Month,y = m)) +
    geom_col(position = 'dodge') +
    geom_text(aes(label = round(m))) +
    labs(x = 'Tháng', y = 'Tốc độ gió trung bình')

- Biểu đồ biểu diễn tốc độ gió trung bình của từng tháng

- Tháng 5 có tốc độ trung bình cao nhất là 12

- Tháng 6 và tháng 9 có tốc độ gió trung bình bằng nhau là 10

- Tháng 7 và 8 có tốc độ gió trung bình bằng nhau là 9 và là thấp nhất trong 5 tháng

Đồ thị số 13

dq <- airquality
dq %>% ggplot(aes(x = Month, y = Temp)) +
  geom_point(color = 'red') +
  geom_smooth(method = 'lm', color = 'green')
## `geom_smooth()` using formula = 'y ~ x'

- Cho biết mối quan hệ của nhiệt độ theo từng tháng

  • Tháng 5 có nhiệt độ thấp so với các tháng còn lại

  • Tháng 7, 8 có nhiệt độ tương đối cao

Đồ thị số 14

dq <- airquality 
dq %>% ggplot(aes(x= Month, y= Wind)) +
 geom_area(fill="skyblue") +

  labs(x='Tháng', y='Tốc độ gió')

- Biểu đồ diện tích thể hiện kích thước về tốc độ gió theo từng tháng

  • Tốc độ gió tăng ở tháng 5 lên tháng 6

  • Có sự giảm sau khi đến tháng 7

  • Đến tháng 8 thì tăng lại và tháng 9 cũng tăng nhẹ # Đồ thị số 15

dq <- airquality
dq %>% ggplot(aes(x= Month, y= Ozone)) +
geom_bin_2d() +
  labs(x='Tháng', y='Ozone')
## Warning: Removed 37 rows containing non-finite values (`stat_bin2d()`).

- Biểu đồ biểu diễn nồng độ ozone theo tháng

  • Nồng độ ozone thấp có màu đậm và nồng độ ozone cao thì màu càng nhạt

  • Tháng 6 là tháng có nồng độ ozone thấp nhất

  • Tháng 8 có số lượng nồng độ ozone nhiều nhất

Đồ thị số 16

dq <- airquality
dq %>% ggplot(aes(x= Solar.R)) +
geom_dotplot() +
  labs(x='Bức xạ mặt trời')
## Bin width defaults to 1/30 of the range of the data. Pick better value with
## `binwidth`.
## Warning: Removed 7 rows containing missing values (`stat_bindot()`).

- Mỗi chấm trên biểu đồ thể hiện một giá trị của bức xạ mặt trời

  • Bức xạ từ 200 tới 300 có số lượng nhiều và mật độ cao

  • Bức xạ trên 300 có số lượng ít và mật độ thấp nhất

Đồ thị số 17

dq <- airquality
dq %>% group_by(Month) %>% summarise(m = mean(Temp)) %>%
  ggplot(aes(x = Month,y = m)) +
    geom_col(position = 'dodge') +
    geom_text(aes(label = round(m))) +
    labs(x = 'Tháng', y = 'Nhiệt độ trung bình')

- Biểu đồ biểu diễn nhiệt độ trung bình của từng tháng

  • Nhiệt độ trung bình tháng 7 và tháng 8 là bằng nhau: 84

  • Nhiệt độ trung bình tháng 6 là nhỏ nhất: 66

Đồ thị số 18

dq <- airquality
dq <- dq %>% mutate(WindC = cut(Wind,5, label = c('rất nhỏ', 'nhỏ','vừa','lớn','rất lớn')))
dq %>% ggplot(aes(x = WindC)) +
  geom_bar(fill = 'pink') +
coord_flip()

- Biểu đồ biểu diễn số lượng các cấp độ của tốc độ gió

  • Tốc độ gió nhỏ có số lượng nhiều nhất sau đó đến vừa

  • Tốc độ gió rất lớn có số lượng ít nhất

Đồ thị số 19

dq <- airquality
dq <- dq %>% mutate(tempc = cut(Temp,3, label = c('nhỏ','vừa','lớn')))
dq %>% ggplot(aes(x = tempc)) +
  geom_bar(fill = 'blue') 

- Biểu đồ biểu diễn cấp độ của nhiệt độ

  • Cấp độ vừa có số lượng nhiều nhất, sau đó tới lớn và ít nhất là nhỏ

Đồ thị số 20

dq <- airquality
dq %>% ggplot(aes(x = Ozone)) +
  geom_histogram(binwidth = 20, fill = 'blue', color = 'red')
## Warning: Removed 37 rows containing non-finite values (`stat_bin()`).

- Biểu đồ biểu diễn sự thay đổi của nồng độ Ozone

- Nồng độ Ozone phân phối không đồng đều

- Nồng độ ở mức dưới 50 là lớn nhất, sau đó giảm dần về 150
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA1LiINCmF1dGhvcjogIk5ndXnhu4VuIERp4buFbSBRdeG7s25oIg0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUg6JU06JVMsICVkIC0gJW0gLSAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGRmX3ByaW50OiBrYWJsZQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50Og0KICAgIGV4dHJhX2RlcGVuZGVuY2llczoNCiAgICAgIHZpZXRuYW06IHV0ZjgNCiAgICB0b2M6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgY2xhc3Muc291cmNlID0gIm51bWJlckxpbmVzIGxpbmVBbmNob3JzIiwgDQogIGNsYXNzLm91dHB1dCA9IGMoIm51bWJlckxpbmVzIGxpbmVBbmNob3JzIGNodW5rb3V0IikgDQopDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkoRFQpDQoNCmBgYA0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQpkaXYuc291cmNlQ29kZSBwcmUuY2h1bmtvdXQgew0KICBiYWNrZ3JvdW5kOiB3aGl0ZTsNCn0NCmBgYA0KIA0KIyBUSMOUTkcgVElOIFbhu4AgQ0jhuqRUIEzGr+G7ok5HIEtIw5RORyBLSMONIFThuqBJIE5FVyBZT1JLIFThu6ogVEjDgU5HIDUgTsSCTSAxOTczIMSQ4bq+TiBUSMOBTkcgOSBOxIJNIDE5NzMNCg0KIy4gVGjDtG5nIHRpbiBi4buZIGThu68gbGnhu4d1DQoNCi0gT3pvbmU6IE7hu5NuZyDEkeG7mSBvem9uZSAoTzMpDQoNCi0gU29sYXIuUjogQuG7qWMgeOG6oSBt4bq3dCB0cuG7nWkNCg0KLSBXaW5kOiBU4buRYyDEkeG7mSBnacOzDQoNCi0gVGVtcDogTmhp4buHdCDEkeG7mQ0KDQotIE1vbnRoOiBUaMOhbmcNCg0KLSBEYXk6IE5nw6B5DQoNCi0gQuG7mSBk4buvIGxp4buHdSBjw7MgMTUzIHF1YW4gc8OhdCwgNiBiaeG6v24NCg0KDQpgYGB7cn0NCmxpYnJhcnkoZGF0YXNldHMpDQpkYXRhKHBhY2thZ2UgPSAnZGF0YXNldHMnKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZGF0YShwYWNrYWdlID0gJ2dncGxvdDInKQ0KZHEgPC0gYWlycXVhbGl0eQ0KYGBgDQoNCg0KIA0KIyDEkOG7kyB0aOG7iyBz4buRIDEgDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShzY2FsZXMpDQogIGRxIDwtIGFpcnF1YWxpdHkNCiAgICBkcSAlPiUgZ3JvdXBfYnkoV2luZCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhXaW5kLG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0nc2t5Ymx1ZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgbGFicyh4ID0gJ1Thu5FjIMSR4buZIGdpw7MnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogICAgDQogICAgDQogIC0gVGEgUGjDom4gbG/huqFpIHThu5FjIMSR4buZIGdpw7MgdGhlbyB04burbmcgbeG7qWMgxJHhu5kgdsOgIHTDrW5oIHPhu5EgbMaw4bujbmcgY+G7p2EgdOG7q25nIG3hu6ljIMSR4buZLg0KICANCiAgLSB4IGzDoCB04burbmcgbeG7qWMgxJHhu5kgY+G7p2EgdOG7kWMgxJHhu5kgZ2nDsywgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbeG7qWMgLg0KICANCiAgLSBDw6FjIHPhu5EgbGnhu4d1IGPDsyBtw6B1IMSR4buPLCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCAyIMSRxqFuIHbhu4suIE3DoHUgY+G7p2EgY8OhYyBj4buZdCBsw6AgbcOgdSB4YW5oIGRhIHRy4budaS4NCiAgDQogIC0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buxIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyB0aGVvIHThu6tuZyBt4bupYyB04buRYyDEkeG7mSBnacOzLg0KICANCiAgLSBDw7MgbeG7mXQgc+G7kSBt4bupYyB04buRYyDEkeG7mSBnacOzIGPDsyBz4buRIGzGsOG7o25nIGNhbyBoxqFuLCBj4bulIHRo4buDIGzDoDoNCiAgDQogICAgICArIE3hu6ljIDUtMTAgbXBoIChk4bq3bS9naeG7nSkgY8OzIHPhu5EgbMaw4bujbmcgY2FvIG5o4bqldC4NCiAgICAgIA0KICAgICAgKyBN4bupYyAxMC0xNSBtcGggY8OzIHPhu5EgbMaw4bujbmcgY2FvIHRo4bupIGhhaS4NCiAgICAgIA0KICAtIEPDsyBt4buZdCBz4buRIG3hu6ljIHThu5FjIMSR4buZIGdpw7MgY8OzIHPhu5EgbMaw4bujbmcgdGjhuqVwIGjGoW4sIGPhu6UgdGjhu4MgbMOgOg0KICANCiAgICAgICsgTeG7qWMgZMaw4bubaSA1IG1waCB2w6AgdHLDqm4gMjAgbXBoIGPDsyBz4buRIGzGsOG7o25nIHRo4bqlcCBuaOG6pXQuDQogICAgDQogIA0KDQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDINCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KZHEgPC0gZHEgJT4lIGdyb3VwX2J5KE1vbnRoLCBPem9uZSkgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KZHEgJT4lIGdncGxvdChhZXMoeCA9IE1vbnRoLCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoIE1vbnRoPT0gJzUnKSwgZmlsbCA9ICdwdXJwbGUnKSArDQogIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKE1vbnRoID09ICc5JyksIGZpbGwgPSAndHVycXVvaXNlJykNCmBgYA0KICANCiAgDQogIC0gVGEgcGjDom4gbG/huqFpIG7hu5NuZyDEkeG7mSB0aGVvIGPDoWMgdGjDoW5nIHNhdSDEkcOzIHTDrW5oIHPhu5EgbMaw4bujbmcgLiANCiAgLSDhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6AgTW9udGgsIHkgbMOgIG7hu5NuZyDEkeG7mSBvem9uZSBj4bunYSAyIHRow6FuZyA1IHbDoCA5OyANCiAgLSBUYSBz4bq9IGzhu41jIG7hu5NuZyDEkeG7mSBvem9uZSBj4bunYSB0aMOhbmcgNSwgY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHTDrW0gdsOgIG7hu5NuZyDEkeG7mSBj4bunYSB0aMOhbmcgOSwgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHhhbmggbmfhu41jLiANCiAgLSBU4buVbmcgc+G7kSBsxrDhu6NuZyBu4buTbmcgxJHhu5kgb3pvbmUgdHJvbmcgdGjDoW5nIDUgY2FvIGjGoW4gc28gduG7m2kgdGjDoW5nIDkuDQogIC0gVOG7lW5nIHPhu5EgbMaw4bujbmcgbuG7k25nIMSR4buZIG96b25lIHRyb25nIHRow6FuZyA1IHbhu5tpIG3hu6ljIHRydW5nIGLDrG5oIGtob+G6o25nIDMxIHBwYi4NCiAgLSBU4buVbmcgc+G7kSBsxrDhu6NuZyBu4buTbmcgxJHhu5kgb3pvbmUgdHJvbmcgdGjDoW5nIDkgduG7m2kgbeG7qWMgdHJ1bmcgYsOsbmgga2hv4bqjbmcgMzAgcHBiLg0KDQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDMNCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gU29sYXIuUikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMCwgZmlsbCA9ICdibHVlJywgY29sb3IgPSAncmVkJykNCg0KYGBgDQogIC0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buxIHRoYXkgxJHhu5VpIGPGsOG7nW5nIMSR4buZIGLhu6ljIHjhuqEgbeG6t3QgdHLhu51pIA0KICANCiAgLSBC4bupYyB44bqhIOG7nyBt4bupYyB04burIDIwMCDEkeG6v24gMzAwIGPDsyBjw7Mgc+G7kSBsxrDhu6NuZyBjxrDhu51uZyDEkeG7mSBsw6Agbmhp4buBdSBuaOG6pXQNCiAgDQogIC0gQuG7qWMgeOG6oSDhu58gbeG7qWMgdOG7qyAwIMSR4bq/biAxMDAgY8OzIGPDsyBz4buRIGzGsOG7o25nIGPGsOG7nW5nIMSR4buZIGzDoCDDrXQgbmjhuqV0DQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDQNCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gV2luZCkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAncmVkJykNCmBgYA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IGjhuqd1IGjhur90IHThu5FjIMSR4buZIGdpw7MgxJHhu4F1IG7hurFtIHRyb25nIGtob+G6o25nIDUgxJHhur9uIDE1DQogIA0KICAtIOG7niBt4bupYyB04buRYyDEkeG7mSBnacOzIMSR4bqhdCAxMG1waCBjw7Mgc+G7kSBsxrDhu6NuZyBjYW8gbmjhuqV0DQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDUNCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ3JvdXBfYnkoVGVtcCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBUZW1wKSkgKw0KICAgIGdlb21fY29sKGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGNvb3JkX3BvbGFyKCd5JykgKw0KICAgIGdlb21fdGV4dChhZXMoeCA9IDEuMywgbGFiZWwgPSBuKSxwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gLjUpKSArDQogDQogICAgdGhlbWVfdm9pZCgpDQpgYGANCg0KICAtIEJp4buDdSDEkeG7kyBiaeG7g3UgZGnhu4VuIHPhu5EgbMaw4bujbmcgdOG7q25nIG3hu6ljIG5oaeG7h3QgxJHhu5kNCiAgDQogIC0g4bueIG3hu6ljIG5oaeG7h3QgxJHhu5kgY8OgbmcgY2FvIHRow6wgY8OzIHPhu5EgbMaw4bujbmcgY8Ogbmcgw610DQogIA0KICAtIFPhu5EgbMaw4bujbmcgbmhp4buHdCDEkeG7mSBuaGnhu4F1IG5o4bqldCBsw6AgMTEgduG7m2kgbeG7qWMgbmhp4buHdCDEkeG7mSBsw6AgdOG7qyA3MCDEkeG6v24gODANCg0KIyDEkOG7kyB0aOG7iyBz4buRIDYNCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gRGF5LCB5ID0gTW9udGgsIGNvbG9yID0gU29sYXIuUikpICsNCiAgZ2VvbV9wb2ludCgpDQpgYGANCiAgLSBCaeG7g3UgxJHhu5MgYmnhu4N1IGRp4buFbiBi4bupYyB44bqhIG3hurd0IHRy4budaSB0aGVvIHThu6tuZyB0aMOhbmcgdOG7qyB0aMOhbmcgNSDEkeG6v24gdGjDoW5nIDkNCiAgDQogIC0gUXVhIMSR4buTIHRo4buLIHRhIHRo4bqleSB0aMOhbmcgNyAsOCBsw6Agbmjhu69uZyB0aMOhbmcgY8OzIG3hu6ljIGLhu6ljIHjhuqEgY2FvIG5o4bqldCB24bubaSBuaGnhu4F1IHPhu5EgbMaw4bujbmcgYuG7qWMgeOG6oSB04burIDIwMCDEkeG6v24gMzAwDQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDcNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KICAgIGRxICU+JSBncm91cF9ieShUZW1wKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKFRlbXAsbikpICsNCiAgICBnZW9tX2FyZWEoZmlsbD0nc2t5Ymx1ZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgbGFicyh4ID0gJ05oaeG7h3QgxJHhu5knLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogIC0gQmnhu4N1IMSR4buTIG1p4buBbiBiaeG7g3UgZGnhu4VuIHPhu5EgbMaw4bujbmcgY8OhYyBt4bupYyBuaGnhu4d0IMSR4buZDQogIA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IOG7nyBuaGnhu4d0IMSR4buZIDgwIMSR4buZIGPDsyBz4buRIGzGsOG7o25nIG5oaeG7gXUgbmjhuqV0IGzDoCAxMQ0KICANCiAgLSBT4buRIGzGsOG7o25nIGPDsyB4dSBoxrDhu5tuZyB0xINuZyBk4bqnbiB04burIG3hu6ljIDYwIMSR4bq/biA4MCB2w6Agc2F1IMSRw7MgZ2nhuqNtIGThuqduIHThu6sgODAgeHXhu5FuZyA5MA0KICANCiMgxJDhu5MgdGjhu4sgc+G7kSA4DQpgYGB7cn0NCmRxIDwtIGFpcnF1YWxpdHkNCiAgICBkcSAlPiUgZ2dwbG90KGFlcyh4ID0gVGVtcCkpICsgDQogICAgICAgIGdlb21fZGVuc2l0eShjb2xvciA9ICdyZWQnLCBmaWxsID0gJ3NreWJsdWUnKSsNCiAgICAgICAgbGFicyggeCA9ICdOaGnhu4d0IMSR4buZJykNCmBgYA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IMSRxrDhu6NjOiBt4bqtdCDEkeG7mSBuaGnhu4d0IMSR4buZIHBow6JuIHBo4buRaSBraMO0bmcgxJHhu5NuZyDEkeG7gXUNCg0KICAtIE5oaeG7h3QgxJHhu5kg4bufIG3hu6ljIDgwIMSR4buZIGPDsyBt4bqtdCDEkeG7mSBjYW8gbmjhuqV0DQogIA0KICAtIE3hu6ljIG5oaeG7h3QgxJHhu5kgdOG7qyA2MCBjw7MgbeG6rXQgxJHhu5kgdMSDbmcgZOG6p24gxJHhur9uIDgwIMSR4buZIHNhdSDEkcOzIGdp4bqjbSBk4bqnbiB4deG7kW5nIDkwDQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDkNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KICAgIGRxICU+JSBncm91cF9ieShXaW5kKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKFdpbmQsbikpICsNCiAgICBnZW9tX2JpbjJkKGZpbGw9J3BpbmsnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ1Thu5FjIMSR4buZIGdpw7MnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogIC0gxJDDonkgbMOgIGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSAyRCwgY2hpYSBk4buvIGxp4buHdSB0aMOgbmggY8OhYyDDtCB2dcO0bmcsIG3hu5dpIMO0IHZ1w7RuZyBsw6AgMSBk4buvIGxp4buHdQ0KICANCiAgLSAgQmnhu4N1IMSR4buTIGJp4buDdSBkaeG7hW4gc+G7kSBsxrDhu6NuZyB04burbmcgbeG7qWMgY+G7p2EgdOG7kWMgxJHhu5kgZ2nDsw0KICANCiAgLSDhu54gbeG7qWMgNSDEkeG6v24gMTAgY8OzIHPhu5EgbMaw4bujbmcgdOG7kWMgxJHhu5kgZ2nDsyBuaGnhu4F1IG5o4bqldA0KICANCiAgLSDhu54gbeG7qWMgMTAgxJHhur9uIDE1IGNo4bupYSBz4buRIGzGsOG7o25nIHThu5FjIMSR4buZIGdpw7MgY2FvIG5o4bqldCBsw6AgMTUNCiAgDQojIMSQ4buTIHRo4buLIHPhu5EgMTANCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQogICAgZHEgJT4lIGdncGxvdChhZXMoeCA9IFNvbGFyLlIpKSArIA0KICAgICAgICBnZW9tX2RlbnNpdHkoY29sb3IgPSAnYmxhY2snLCBmaWxsID0gJ3BpbmsnKSsNCiAgICAgICAgbGFicyggeCA9ICdC4bupYyB44bqhIG3hurd0IHRy4budaScpDQpgYGANCg0KICAtIFF1YSDEkeG7kyB0aOG7iyB0YSB0aOG6pXkgbeG6rXQgxJHhu5kgYuG7qWMgeOG6oSBt4bq3dCB0cuG7nWkgY2FvIG5o4bqldCBu4bqxbSB2w6BvIGtob+G6o25nIDI1MCANCiAgDQogICAgLSBN4bqtdCDEkeG7mSBwaMOibiBwaOG7kWkga2jDtG5nIMSR4buTbmcgxJHhu4F1LCB0xINuZyBnaeG6o20gbGnDqm4gdOG7pWMNCiAgICANCiMgxJDhu5MgdGjhu4sgc+G7kSAxMQ0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQogICAgZHEgJT4lIGdncGxvdChhZXMoeCA9IE96b25lKSkgKyANCiAgICAgICAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gJ3JlZCcsIGZpbGwgPSAnYmx1ZScpKw0KICAgICAgICBsYWJzKCB4ID0gJ27hu5NuZyDEkeG7mSBvem9uZScpDQpgYGANCiAgLSBN4bqtdCDEkeG7mSB24buBIG7hu5NuZyDEkeG7mSBvem9uZSB0xINuZyBjYW8gbmjhuqV0IOG7nyBraG/huqNuZyBkxrDhu5tpIDUwLCBzYXUgxJHDsyBnaeG6o20gZOG6p24geHXhu5FuZyB04bqtbiAxNTANCiAgDQogIC0gVuG7iyB0csOtIGPDsyBt4bqtdCDEkeG7mSBjYW8gbmjhuqV0IG7hurFtIHThuqdtIGtob+G6o25nIDI1DQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDEyDQpgYGB7cn0NCmRxIDwtIGFpcnF1YWxpdHkNCmRxICU+JSBncm91cF9ieShNb250aCkgJT4lIHN1bW1hcmlzZShtID0gbWVhbihXaW5kKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IE1vbnRoLHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtKSkpICsNCiAgICBsYWJzKHggPSAnVGjDoW5nJywgeSA9ICdU4buRYyDEkeG7mSBnacOzIHRydW5nIGLDrG5oJykNCiAgICAgICAgICAgICAgIA0KYGBgDQogICAgLSBCaeG7g3UgxJHhu5MgYmnhu4N1IGRp4buFbiB04buRYyDEkeG7mSBnacOzIHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyB0aMOhbmcNCiAgICANCiAgICAtIFRow6FuZyA1IGPDsyB04buRYyDEkeG7mSB0cnVuZyBiw6xuaCBjYW8gbmjhuqV0IGzDoCAxMg0KICAgIA0KICAgIC0gVGjDoW5nIDYgdsOgIHRow6FuZyA5IGPDsyB04buRYyDEkeG7mSBnacOzIHRydW5nIGLDrG5oIGLhurFuZyBuaGF1IGzDoCAxMA0KICAgIA0KICAgIC0gVGjDoW5nIDcgdsOgIDggY8OzIHThu5FjIMSR4buZIGdpw7MgdHJ1bmcgYsOsbmggYuG6sW5nIG5oYXUgbMOgIDkgdsOgIGzDoCB0aOG6pXAgbmjhuqV0IHRyb25nIDUgdGjDoW5nDQogIA0KICANCiMgxJDhu5MgdGjhu4sgc+G7kSAxMw0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gTW9udGgsIHkgPSBUZW1wKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gJ3JlZCcpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgY29sb3IgPSAnZ3JlZW4nKQ0KYGBgDQogIC0gQ2hvIGJp4bq/dCBt4buRaSBxdWFuIGjhu4cgY+G7p2Egbmhp4buHdCDEkeG7mSB0aGVvIHThu6tuZyB0aMOhbmcNCiAgDQogIC0gVGjDoW5nIDUgY8OzIG5oaeG7h3QgxJHhu5kgdGjhuqVwIHNvIHbhu5tpIGPDoWMgdGjDoW5nIGPDsm4gbOG6oWkNCiAgDQogIC0gVGjDoW5nIDcsIDggY8OzIG5oaeG7h3QgxJHhu5kgdMawxqFuZyDEkeG7kWkgY2FvIA0KICANCg0KDQojIMSQ4buTIHRo4buLIHPhu5EgMTQNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eSANCmRxICU+JSBnZ3Bsb3QoYWVzKHg9IE1vbnRoLCB5PSBXaW5kKSkgKw0KIGdlb21fYXJlYShmaWxsPSJza3libHVlIikgKw0KDQogIGxhYnMoeD0nVGjDoW5nJywgeT0nVOG7kWMgxJHhu5kgZ2nDsycpDQpgYGANCiAgLSBCaeG7g3UgxJHhu5MgZGnhu4duIHTDrWNoIHRo4buDIGhp4buHbiBrw61jaCB0aMaw4bubYyB24buBIHThu5FjIMSR4buZIGdpw7MgdGhlbyB04burbmcgdGjDoW5nDQogIA0KICAtIFThu5FjIMSR4buZIGdpw7MgdMSDbmcg4bufIHRow6FuZyA1IGzDqm4gdGjDoW5nIDYNCiAgDQogIC0gQ8OzIHPhu7EgZ2nhuqNtIHNhdSBraGkgxJHhur9uIHRow6FuZyA3DQogIA0KICAtIMSQ4bq/biB0aMOhbmcgOCB0aMOsIHTEg25nIGzhuqFpIHbDoCB0aMOhbmcgOSBjxaluZyB0xINuZyBuaOG6uQ0KIyDEkOG7kyB0aOG7iyBz4buRIDE1DQpgYGB7cn0NCmRxIDwtIGFpcnF1YWxpdHkNCmRxICU+JSBnZ3Bsb3QoYWVzKHg9IE1vbnRoLCB5PSBPem9uZSkpICsNCmdlb21fYmluXzJkKCkgKw0KICBsYWJzKHg9J1Row6FuZycsIHk9J096b25lJykNCmBgYA0KICAtIEJp4buDdSDEkeG7kyBiaeG7g3UgZGnhu4VuIG7hu5NuZyDEkeG7mSBvem9uZSB0aGVvIHRow6FuZw0KICANCiAgLSBO4buTbmcgxJHhu5kgb3pvbmUgdGjhuqVwIGPDsyBtw6B1IMSR4bqtbSB2w6AgbuG7k25nIMSR4buZIG96b25lIGNhbyB0aMOsIG3DoHUgY8OgbmcgbmjhuqF0DQogIA0KICAtIFRow6FuZyA2IGzDoCB0aMOhbmcgY8OzIG7hu5NuZyDEkeG7mSBvem9uZSB0aOG6pXAgbmjhuqV0DQogIA0KICAtIFRow6FuZyA4IGPDsyBz4buRIGzGsOG7o25nIG7hu5NuZyDEkeG7mSBvem9uZSBuaGnhu4F1IG5o4bqldA0KICANCiMgxJDhu5MgdGjhu4sgc+G7kSAxNg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4PSBTb2xhci5SKSkgKw0KZ2VvbV9kb3RwbG90KCkgKw0KICBsYWJzKHg9J0Lhu6ljIHjhuqEgbeG6t3QgdHLhu51pJykNCmBgYA0KICAtIE3hu5dpIGNo4bqlbSB0csOqbiBiaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG3hu5l0IGdpw6EgdHLhu4sgY+G7p2EgYuG7qWMgeOG6oSBt4bq3dCB0cuG7nWkNCiAgDQogIC0gQuG7qWMgeOG6oSB04burIDIwMCB04bubaSAzMDAgY8OzIHPhu5EgbMaw4bujbmcgbmhp4buBdSB2w6AgbeG6rXQgxJHhu5kgY2FvIA0KICANCiAgLSBC4bupYyB44bqhIHRyw6puIDMwMCBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgdsOgIG3huq10IMSR4buZIHRo4bqlcCBuaOG6pXQNCg0KIyDEkOG7kyB0aOG7iyBz4buRIDE3DQpgYGB7cn0NCmRxIDwtIGFpcnF1YWxpdHkNCmRxICU+JSBncm91cF9ieShNb250aCkgJT4lIHN1bW1hcmlzZShtID0gbWVhbihUZW1wKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IE1vbnRoLHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtKSkpICsNCiAgICBsYWJzKHggPSAnVGjDoW5nJywgeSA9ICdOaGnhu4d0IMSR4buZIHRydW5nIGLDrG5oJykNCmBgYA0KICAtIEJp4buDdSDEkeG7kyBiaeG7g3UgZGnhu4VuIG5oaeG7h3QgxJHhu5kgdHJ1bmcgYsOsbmggY+G7p2EgdOG7q25nIHRow6FuZw0KICANCiAgLSBOaGnhu4d0IMSR4buZIHRydW5nIGLDrG5oIHRow6FuZyA3IHbDoCB0aMOhbmcgOCBsw6AgYuG6sW5nIG5oYXU6IDg0DQogIA0KICAtIE5oaeG7h3QgxJHhu5kgdHJ1bmcgYsOsbmggdGjDoW5nIDYgbMOgIG5o4buPIG5o4bqldDogNjYNCiAgDQojIMSQ4buTIHRo4buLIHPhu5EgMTgNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KZHEgPC0gZHEgJT4lIG11dGF0ZShXaW5kQyA9IGN1dChXaW5kLDUsIGxhYmVsID0gYygncuG6pXQgbmjhu48nLCAnbmjhu48nLCd24burYScsJ2zhu5tuJywncuG6pXQgbOG7m24nKSkpDQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gV2luZEMpKSArDQogIGdlb21fYmFyKGZpbGwgPSAncGluaycpICsNCmNvb3JkX2ZsaXAoKQ0KYGBgDQogIC0gQmnhu4N1IMSR4buTIGJp4buDdSBkaeG7hW4gc+G7kSBsxrDhu6NuZyBjw6FjIGPhuqVwIMSR4buZIGPhu6dhIHThu5FjIMSR4buZIGdpw7MNCiAgDQogIC0gVOG7kWMgxJHhu5kgZ2nDsyBuaOG7jyBjw7Mgc+G7kSBsxrDhu6NuZyBuaGnhu4F1IG5o4bqldCBzYXUgxJHDsyDEkeG6v24gduG7q2ENCiAgDQogIC0gVOG7kWMgxJHhu5kgZ2nDsyBy4bqldCBs4bubbiBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgbmjhuqV0DQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDE5DQoNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KZHEgPC0gZHEgJT4lIG11dGF0ZSh0ZW1wYyA9IGN1dChUZW1wLDMsIGxhYmVsID0gYygnbmjhu48nLCd24burYScsJ2zhu5tuJykpKQ0KZHEgJT4lIGdncGxvdChhZXMoeCA9IHRlbXBjKSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ2JsdWUnKSANCg0KYGBgDQogIC0gQmnhu4N1IMSR4buTIGJp4buDdSBkaeG7hW4gY+G6pXAgxJHhu5kgY+G7p2Egbmhp4buHdCDEkeG7mQ0KICANCiAgLSBD4bqlcCDEkeG7mSB24burYSBjw7Mgc+G7kSBsxrDhu6NuZyBuaGnhu4F1IG5o4bqldCwgc2F1IMSRw7MgdOG7m2kgbOG7m24gdsOgIMOtdCBuaOG6pXQgbMOgIG5o4buPDQoNCiMgxJDhu5MgdGjhu4sgc+G7kSAyMA0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gT3pvbmUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMjAsIGZpbGwgPSAnYmx1ZScsIGNvbG9yID0gJ3JlZCcpDQoNCmBgYA0KDQogICAgLSBCaeG7g3UgxJHhu5MgYmnhu4N1IGRp4buFbiBz4buxIHRoYXkgxJHhu5VpIGPhu6dhIG7hu5NuZyDEkeG7mSBPem9uZQ0KICAgIA0KICAgIC0gTuG7k25nIMSR4buZIE96b25lIHBow6JuIHBo4buRaSBraMO0bmcgxJHhu5NuZyDEkeG7gXUNCiAgICANCiAgICAtIE7hu5NuZyDEkeG7mSDhu58gbeG7qWMgZMaw4bubaSA1MCBsw6AgbOG7m24gbmjhuqV0LCBzYXUgxJHDsyBnaeG6o20gZOG6p24gduG7gSAxNTA=