“ĐỀ TÀI: PACKAGE TIBBLE TRONG R”

Chương 1: Giới thiệu về package Tibble

1.1 Giới thiệu

   Trong thời đại số hóa ngày nay, phân tích dữ liệu đóng vai trò không thể thiếu và trở thành một yếu tố quyết định trong quá trình ra quyết định và định hướng chiến lược. Tuy nhiên, việc làm việc với dữ liệu đôi khi gặp phải nhiều khó khăn và thách thức, từ việc nhập liệu không chính xác, dữ liệu không đầy đủ, đến quá trình xử lý dữ liệu phức tạp và đồng nhất.

   Trong bối cảnh đó, package Tibble trong ngôn ngữ lập trình R đã nhanh chóng trở thành một công cụ phổ biến và hữu ích trong việc quản lý và xử lý dữ liệu. Tibble cung cấp một cách tiếp cận hiện đại và linh hoạt hơn để làm việc với dữ liệu, mang lại những lợi ích đáng kể cho những người làm việc trong lĩnh vực phân tích dữ liệu. Trong phần giới thiệu này, em sẽ tìm hiểu về package Tibble, mục tiêu nghiên cứu của bài tiểu luận, và phạm vi nghiên cứu.

1.2 Lý do chọn đề tài

   Trong thời đại số hóa và phát triển mạnh mẽ của dữ liệu, việc quản lý và xử lý dữ liệu đã trở thành một thách thức không nhỏ đối với các nhà nghiên cứu, chuyên gia phân tích dữ liệu và những người làm việc trong lĩnh vực tài chính, kinh doanh, y tế và nhiều lĩnh vực khác. Với số lượng dữ liệu ngày càng tăng, việc xử lý và khai thác tri thức từ dữ liệu trở thành một yêu cầu cấp bách để đưa ra quyết định thông minh và phát triển bền vững.

   Em lựa chọn đề tài nghiên cứu về package Tibble trong ngôn ngữ lập trình R. Tibble là một công cụ mạnh mẽ và linh hoạt giúp người dùng quản lý và xử lý dữ liệu một cách hiệu quả. Đây là một bước tiến quan trọng trong việc cải thiện quy trình làm việc với dữ liệu và nâng cao hiệu suất phân tích dữ liệu.

Lý do em quyết định nghiên cứu về package Tibble :

  • Đơn giản và dễ sử dụng: Tibble cung cấp cấu trúc dữ liệu trực quan và dễ đọc, giúp người dùng làm việc dễ dàng và linh hoạt.
  • Tương thích với các công cụ phân tích dữ liệu: Tibble tích hợp tốt với các package dplyr và ggplot2, giúp thực hiện biến đổi và tạo biểu đồ một cách thuận tiện.
  • Hiệu suất và khả năng mở rộng: Tibble được tối ưu hóa để xử lý dữ liệu lớn, giúp làm việc nhanh chóng và hiệu quả.
  • Quản lý dữ liệu đồng nhất: Tibble giúp đảm bảo tính nhất quán và đồng nhất của dữ liệu, từ đặt tên cột dễ hiểu đến xử lý dữ liệu thiếu.

Với nghiên cứu về package Tibble, em hy vọng đóng góp vào quy trình làm việc với dữ liệu và nâng cao hiệu suất phân tích dữ liệu. Điều này sẽ mang lại giá trị và tiềm năng cho các lĩnh vực như nghiên cứu khoa học và quản lý kinh doanh.

1.3 Mục tiêu nghiên cứu

   Mục tiêu của nghiên cứu này là khám phá và hiểu rõ hơn về package Tibble trong R và khả năng của nó trong việc quản lý và xử lý dữ liệu.

Cụ thể, em đề ra các mục tiêu sau :

  • Tìm hiểu về cấu trúc và tính năng của Tibble: Em sẽ nghiên cứu cách Tibble tổ chức và lưu trữ dữ liệu, cũng như các tính năng và ưu điểm của nó so với các cấu trúc dữ liệu khác.
  • Thực hiện các phép biến đổi dữ liệu: Em sẽ tìm hiểu cách sử dụng Tibble để thực hiện các phép biến đổi dữ liệu như lọc, sắp xếp, đổi tên cột và thêm cột mới. Em cũng sẽ khám phá các tính năng linh hoạt của Tibble trong việc làm việc với dữ liệu.
  • Tạo biểu đồ và trực quan hóa dữ liệu: Em sẽ thực hiện việc tạo biểu đồ và trực quan hóa dữ liệu sử dụng Tibble và package ggplot2. Em sẽ khám phá các loại biểu đồ phổ biến như biểu đồ cột, biểu đồ điểm và biểu đồ đường.
  • Áp dụng Tibble vào các tình huống thực tế: Em sẽ trình bày các ví dụ và tình huống thực tế để minh họa sự ứng dụng của Tibble trong việc quản lý và xử lý dữ liệu. Em sẽ thực hiện các thao tác phân tích dữ liệu và trả lời các câu hỏi phân tích sử dụng Tibble.
  • Đánh giá hiệu quả và lợi ích của Tibble: Em sẽ đánh giá hiệu quả và lợi ích của việc sử dụng Tibble trong quy trình làm việc với dữ liệu. Em sẽ so sánh Tibble với các phương pháp và công cụ khác để hiểu rõ hơn về ưu điểm và giới hạn của nó.

1.4 Phạm vi nghiên cứu

   Phạm vi nghiên cứu của bài tiểu luận về package Tibble trong phân tích dữ liệu sẽ tập trung vào các khía cạnh sau:

  • Tìm hiểu về package Tibble và hiểu rõ định nghĩa và mô tả của nó. Nghiên cứu sẽ tập trung vào các tính năng và lợi ích của Tibble trong việc phân tích dữ liệu.
  • So sánh sự khác biệt giữa Tibble và data frame thông thường. Phân tích sẽ tập trung vào những ưu điểm và tiềm năng của Tibble so với data frame truyền thống trong việc phân tích dữ liệu.
  • Tìm hiểu về các tính năng chính của Tibble, bao gồm cấu trúc dữ liệu linh hoạt và tiện ích, xử lý dữ liệu thiếu và xử lý metadata, cũng như khả năng tương thích và tích hợp với các gói phân tích dữ liệu khác trong R.
  • Nghiên cứu về các ứng dụng của Tibble trong phân tích dữ liệu. Phân tích sẽ tập trung vào khả năng xử lý và biến đổi dữ liệu một cách nhanh chóng và linh hoạt, thao tác và truy vấn dữ liệu hiệu quả, cũng như khả năng tạo biểu đồ và báo cáo chất lượng cao với Tibble.
  • Tiến hành các thực nghiệm và áp dụng thực tế của Tibble trong các phân tích dữ liệu thống kê, xây dựng mô hình hồi quy tuyến tính và trực quan hóa dữ liệu với ggplot2 và Tibble.
  • Đánh giá ưu điểm và hạn chế của package Tibble. Phân tích sẽ xem xét các ưu điểm của Tibble như tính linh hoạt, tiện ích và tích hợp tốt với các gói phân tích dữ liệu khác, cũng như những hạn chế có thể gặp phải khi sử dụng Tibble trong một số trường hợp cụ thể.
  • Tổng kết nội dung và kết quả nghiên cứu, đánh giá hiệu quả và tiềm năng của Tibble trong phân tích dữ liệu.
  • Đề xuất hướng phát triển và nghiên cứu tiếp theo cho Tibble, bao gồm cải tiến và mở rộng tính năng của nó, cũng như nghiên cứu sâu hơn về ứng dụng của Tibble trong các lĩnh vực cụ thể.

Với phạm vi nghiên cứu như trên, bài tiểu luận sẽ giúp định rõ tiềm năng và ứng dụng của package Tibble trong phân tích dữ liệu. Nó sẽ cung cấp kiến thức cần thiết để hiểu và sử dụng Tibble một cách hiệu quả trong quá trình xử lý, truy vấn và biểu đồ hóa dữ liệu.

Chương 2 : Khái quát về package Tibble

2.1 Định nghĩa và mô tả

   Package Tibble trong ngôn ngữ lập trình R là một công cụ phân tích dữ liệu linh hoạt và tiện ích hơn so với data frame thông thường. Tibble giữ nguyên các đặc điểm cơ bản của data frame, nhưng cải thiện chúng bằng cách thêm tính năng mạnh mẽ. Nó giúp xử lý dữ liệu thiếu và metadata dễ dàng hơn, tương thích với các gói phân tích dữ liệu khác trong R. Tibble cung cấp một cú pháp đơn giản và tránh các lỗi phổ biến khi làm việc với data frame.

   Trong bài tiểu luận này, em sẽ tìm hiểu các tính năng chính của Tibble như cấu trúc dữ liệu linh hoạt, xử lý dữ liệu thiếu và metadata, tích hợp với các gói phân tích dữ liệu khác. Ngoài ra,chúng ta sẽ khám phá ứng dụng Tibble trong xử lý, truy vấn và biến đổi dữ liệu, tạo biểu đồ. Đánh giá ưu điểm, hạn chế và tiềm năng của Tibble cùng đề xuất hướng phát triển và nghiên cứu tiếp theo cho Tibble.

2.2 Lợi ích và tiềm năng của package Tibble trong phân tích dữ liệu

   Tibble đem lại nhiều lợi ích và tiềm năng quan trọng trong phân tích dữ liệu:

  • Linh hoạt và tiện ích: Tibble cung cấp cấu trúc dữ liệu linh hoạt, giúp xử lý dữ liệu dễ dàng và thuận tiện hơn. Nó giúp giảm thời gian và công sức trong quá trình phân tích dữ liệu.
  • Xử lý dữ liệu thiếu và metadata: Tibble cung cấp công cụ mạnh mẽ để xử lý dữ liệu thiếu và quản lý metadata. Người dùng có thể dễ dàng làm việc với giá trị thiếu và gắn kết thông tin bổ sung vào dữ liệu, tăng tính linh hoạt và hiểu biết về dữ liệu.
  • Tương thích và tích hợp: Tibble tương thích hoàn toàn với các gói phân tích dữ liệu khác trong R như dplyr, tidyr và ggplot2. Điều này giúp người dùng kết hợp các công cụ phân tích một cách dễ dàng và tận dụng tối đa tiềm năng của hệ sinh thái R để phân tích dữ liệu.
  • Xử lý nhanh chóng và linh hoạt: Tibble cho phép xử lý và biến đổi dữ liệu nhanh chóng và linh hoạt. Cú pháp đơn giản của Tibble giúp tránh ràng buộc và lỗi phổ biến khi làm việc với data frame, tăng hiệu suất phân tích.
  • Tạo biểu đồ và báo cáo chất lượng cao: Tibble kết hợp tốt với gói ggplot2 để tạo biểu đồ và báo cáo chất lượng cao. Sự kết hợp này giúp người dùng trực quan hóa dữ liệu dễ dàng và linh hoạt, tạo ra báo cáo thẩm mỹ và thông tin trực quan.

Tóm lại, Tibble mang lại lợi ích và tiềm năng quan trọng trong phân tích dữ liệu nhờ vào cấu trúc linh hoạt, khả năng xử lý dữ liệu thiếu và thông tin metadata, khả năng tích hợp mượt mà với các gói phân tích khác, cùng khả năng xử lý dữ liệu nhanh chóng và linh hoạt.

Chương 3: Các tính năng chính của Tibble

3.1 Cấu trúc dữ liệu linh hoạt và những tiện ích

   Tibble cung cấp một cấu trúc dữ liệu linh hoạt và tiện ích, cho phép lưu trữ và làm việc với dữ liệu theo dạng bảng, với các cột và hàng có tên. Dưới đây là một số tính năng chính của cấu trúc dữ liệu tibble:

  • Lưu trữ dữ liệu dưới dạng bảng: Tibble cho phép lưu trữ dữ liệu theo dạng bảng, giống như một bảng tính Excel. Mỗi cột đại diện cho một biến và mỗi hàng đại diện cho một quan sát.
  • Các cột và hàng có tên: Mỗi cột và hàng trong tibble có tên riêng, giúp xác định và truy cập dữ liệu một cách dễ dàng. Ta có thể sử dụng tên cột để tham chiếu và thao tác với dữ liệu trong tibble.
  • Cấu trúc dữ liệu đồng nhất: Các cột trong tibble phải có cùng độ dài, đảm bảo tính đồng nhất của cấu trúc dữ liệu. Điều này giúp tránh nhầm lẫn và xử lý dữ liệu một cách hiệu quả.
  • Hỗ trợ dữ liệu thô và dạng tổng hợp: Tibble có thể lưu trữ dữ liệu thô và dạng tổng hợp một cách linh hoạt. Ta có thể sử dụng tibble để lưu trữ dữ liệu chi tiết và tính toán các thống kê tổng hợp trên dữ liệu đó. Hỗ trợ dữ liệu phân loại: Tibble có khả năng hỗ trợ dữ liệu phân loại (categorical data). Ta có thể sử dụng các hàm và gói mở rộng để xử lý và phân tích dữ liệu phân loại trong tibble.
  • Tích hợp với các gói phân tích dữ liệu khác: Tibble tích hợp tốt với các gói phân tích dữ liệu phổ biến trong R như dplyr, tidyr, ggplot và nhiều gói khác. Điều này mang lại khả năng linh hoạt và tiện ích trong việc thực hiện các phân tích và xử lý dữ liệu.

Ví dụ:

library(tibble)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# Tạo một tibble với thông tin về sinh viên
sinhvien <- tibble(id = c(1, 2, 3, 4, 5, 6),ten = c("Linh", "Lan", "Long", "Phụng", "Quy", "Nguyên"),tuoi = c(20, 19, 21, 20, 22, 18),major = c("Tài chính", "Marketing", "Kế toán", "Ngôn ngữ Anh", "Quản trị kinh doanh", "Toán tài chính"),gpa = c(3.5, 3.2, 3.8, 3.6, 3.4, 3.2))

# Truy cập và thao tác dữ liệu dễ dàng
tensinhvien <- sinhvien$ten
sinhvien_b <- sinhvien %>%filter(tuoi >= 19) %>% select(ten, major)

# Tính toán các thống kê tổng hợp
tinhtoan_gpa <- mean(sinhvien$gpa)

# Thêm cột mới vào tibble
themcot <- sinhvien %>%mutate(grade = ifelse(gpa >= 3.5, "A","B"))

Xem kết quả

print(tensinhvien)
## [1] "Linh"   "Lan"    "Long"   "Phụng"  "Quy"    "Nguyên"
print(sinhvien_b)
## # A tibble: 5 × 2
##   ten   major              
##   <chr> <chr>              
## 1 Linh  Tài chính          
## 2 Lan   Marketing          
## 3 Long  Kế toán            
## 4 Phụng Ngôn ngữ Anh       
## 5 Quy   Quản trị kinh doanh
print(tinhtoan_gpa)
## [1] 3.45
print(themcot)
## # A tibble: 6 × 6
##      id ten     tuoi major                 gpa grade
##   <dbl> <chr>  <dbl> <chr>               <dbl> <chr>
## 1     1 Linh      20 Tài chính             3.5 A    
## 2     2 Lan       19 Marketing             3.2 B    
## 3     3 Long      21 Kế toán               3.8 A    
## 4     4 Phụng     20 Ngôn ngữ Anh          3.6 A    
## 5     5 Quy       22 Quản trị kinh doanh   3.4 B    
## 6     6 Nguyên    18 Toán tài chính        3.2 B

3.2 Xử lý dữ liệu thiếu và xử lý metadata

   Tibble cung cấp tính năng xử lý dữ liệu thiếu và xử lý metadata để làm việc với dữ liệu một cách linh hoạt và hiệu quả. Dưới đây là một số tính năng chính trong mục này:

  • Xử lý dữ liệu thiếu: Tibble hỗ trợ xử lý dữ liệu thiếu, giúp chúng ta làm việc với các giá trị thiếu trong dữ liệu. Ta có thể sử dụng các hàm như complete() để hoàn thiện các giá trị thiếu trong tibble bằng các giá trị mặc định hoặc các giá trị từ dữ liệu khác.
  • Xử lý metadata: Tibble không hỗ trợ trực tiếp việc thêm metadata cho cột hoặc tập dữ liệu. Tuy nhiên, ta có thể sử dụng các gói mở rộng như dplyr và tidyverse để thêm metadata vào tibble bằng cách sử dụng các hàm như mutate() và attr(). Ví dụ,ta có thể sử dụng mutate() để thêm thông tin mô tả cho cột và attr() để gán nhãn cho cột trong tibble.
  • Xử lý dữ liệu phân loại: Tibble hỗ trợ xử lý dữ liệu phân loại (categorical data). Ta có thể sử dụng các hàm và gói mở rộng như forcats để chuyển đổi, sắp xếp và xử lý dữ liệu phân loại trong tibble.

Ví dụ:

library(tibble)
# Tạo một tibble với thông tin về sinh viên
sinhvien <- tibble(ten = c("Hải", "Long", NA, "Phụng", "Vân"),
  tuoi = c(21, 22, 20, NA,19),nganh = c("Tài chính", NA, "Kế toán", "Quản trị kinh doanh","Marketing"))

# Hiển thị tibble
sinhvien
## # A tibble: 5 × 3
##   ten    tuoi nganh              
##   <chr> <dbl> <chr>              
## 1 Hải      21 Tài chính          
## 2 Long     22 <NA>               
## 3 <NA>     20 Kế toán            
## 4 Phụng    NA Quản trị kinh doanh
## 5 Vân      19 Marketing

Xuất hiện các thông tin bị thiếu ký hiệu NA,ta xử lý các thông tin bị thiếu này bằng lệnh na.omit()

# Loại bỏ các hàng chứa giá trị thiếu
xulydulieu <- na.omit(sinhvien)
# Hiển thị tibble đã được xử lý
xulydulieu
## # A tibble: 2 × 3
##   ten    tuoi nganh    
##   <chr> <dbl> <chr>    
## 1 Hải      21 Tài chính
## 2 Vân      19 Marketing

Xử lý metadata: Tibble cho phép lưu trữ thông tin metadata cùng với dữ liệu. Thông tin metadata không thể hiện trực tiếp nghĩa của dữ liệu, mà thường là các thông tin bổ sung về các thuộc tính, nguồn gốc, hoặc ngữ cảnh của dữ liệu. Điều này giúp làm cho dữ liệu trở nên dễ hiểu hơn và tạo điều kiện thuận lợi cho việc xử lý và phân tích dữ liệu sau này.

Ví dụ: ta có thể thêm nhãn và chú thích cho các cột trong tibble để giải thích ý nghĩa của chúng. Tuy nhiên, thông tin metadata không ảnh hưởng trực tiếp đến việc thực hiện các phép biến đổi dữ liệu như lọc, sắp xếp, hay tổng hợp. Thay vào đó, chúng giúp ta có cái nhìn tổng quan hơn về dữ liệu và đảm bảo rằng chúng ta hiểu rõ hơn về ngữ cảnh và ý nghĩa của dữ liệu trong quá trình làm việc với nó.

library(tibble)
library(dplyr)
# Tạo một tibble với thông tin về sản phẩm
sanpham <- tibble(id = c(1, 2, 3),tensanpham = c("Áo", "Quần", "Giày"),
  gia_ban = c(29.99, 49.99, 79.99)) %>% mutate(mieu_ta = "Thông tin về các sản phẩm",
    label_id = "Mã sản phẩm",
    label_name = "Tên sản phẩm",
    label_price = "Giá sản phẩm")

# Hiển thị tibble
sanpham
## # A tibble: 3 × 7
##      id tensanpham gia_ban mieu_ta               label_id label_name label_price
##   <dbl> <chr>        <dbl> <chr>                 <chr>    <chr>      <chr>      
## 1     1 Áo            30.0 Thông tin về các sản… Mã sản … Tên sản p… Giá sản ph…
## 2     2 Quần          50.0 Thông tin về các sản… Mã sản … Tên sản p… Giá sản ph…
## 3     3 Giày          80.0 Thông tin về các sản… Mã sản … Tên sản p… Giá sản ph…

3.3 Tương thích và tích hợp với các gói phân tích dữ liệu khác trong R

   Tibble tương thích và tích hợp tốt với các gói phân tích dữ liệu khác trong R, giúp chúng ta thực hiện các phân tích và xử lý dữ liệu một cách linh hoạt và hiệu quả. Dưới đây là một số ví dụ về việc tích hợp tibble với các gói phân tích dữ liệu phổ biến:

  • Tích hợp với dplyr: Tibble hoạt động tốt với gói dplyr, cung cấp các hàm mạnh mẽ để thực hiện các phép biến đổi dữ liệu như lọc (filter), sắp xếp (arrange), nhóm (group_by) và tổng hợp (summarise). Chúng ta có thể sử dụng các hàm dplyr trực tiếp trên tibble để xử lý dữ liệu một cách dễ dàng và linh hoạt.
  • Tích hợp với tidyr: Tibble cũng tích hợp tốt với gói tidyr, cho phép ta thực hiện các phép biến đổi dữ liệu để làm sạch và chuẩn hóa dữ liệu. Bằng cách sử dụng các hàm tidyr như gather và spread, ta có thể chuyển đổi dữ liệu giữa định dạng rộng (wide) và định dạng dài (long), thuận tiện cho việc phân tích và trực quan hóa dữ liệu.
  • Tích hợp với ggplot: Tibble có tích hợp tốt với gói ggplot, gói đồ thị phổ biến trong R. Ta có thể sử dụng tibble để chuẩn bị dữ liệu và sau đó trực tiếp sử dụng ggplot để tạo các biểu đồ và đồ thị trực quan.
  • Tích hợp với các gói phân tích thống kê khác: Tibble tương thích với các gói phân tích thống kê khác như stats, MASS, lme4, và nhiều gói khác. Chúng ta có thể sử dụng tibble làm đầu vào cho các phân tích thống kê, kiểm định giả thuyết, hồi quy, phân tích phương sai và nhiều phương pháp khác trong R.

Ví dụ:

library(tibble)
library(dplyr)
# Tạo một tibble với thông tin về sản phẩm và số lượng bán hàng
sanpham <- tibble(
  id = c(1, 2, 3, 4, 5),
  ten = c("Áo", "Quần", "Giày", "Áo", "Quần"),
  gia = c(29.99, 49.99, 79.99, 29.99, 49.99),
  soluong = c(10, 5, 3, 8, 6))
# Tính tổng doanh thu theo sản phẩm
doanhthu <- sanpham %>%
  group_by(ten) %>%
  summarise(tongdoanhthu = sum(gia * soluong))
# Hiển thị kết quả
doanhthu
## # A tibble: 3 × 2
##   ten   tongdoanhthu
##   <chr>        <dbl>
## 1 Giày          240.
## 2 Quần          550.
## 3 Áo            540.

Chương 4: Ứng dụng của package Tibble trong phân tích dữ liệu

4.1 Tạo Tibble và chuyển đổi dữ liệu

   Trong phần này, chúng ta sẽ tìm hiểu về cách tạo tibble bằng cách sử dụng các hàm như as_tibble(), tibble(), và tribble(). Chúng ta sẽ giới thiệu cách tạo tibble từ các đối tượng có sẵn như data.frame, list, matrix hoặc table, và cung cấp các ví dụ cụ thể để minh họa quá trình chuyển đổi dữ liệu.

Giới thiệu về các hàm tạo tibble

  • Hàm as_tibble(): Đây là một hàm chuyển đổi linh hoạt cho phép chúng ta chuyển đổi các đối tượng đã tồn tại như data.frame, list, matrix hoặc table thành tibble. Hàm này sẽ giữ nguyên cấu trúc và kiểu dữ liệu của đối tượng gốc và trả về một tibble tương tự.
  • Hàm tibble(): Hàm này cho phép ta tạo một tibble mới từ các vector cột có sẵn. Điểm đặc biệt của hàm này là nó không thay đổi kiểu dữ liệu của các vector, không chuyển đổi chuỗi thành factor, và không tạo ra row.names. Điều này giúp bảo đảm tính nhất quán và giữ nguyên cấu trúc dữ liệu khi tạo tibble mới.
  • Hàm tribble(): Hàm này cho phép chúng ta định nghĩa tibble dễ dàng theo hàng. Nó cho phép ta tạo một tibble từ các giá trị cột và chúng ta có thể định nghĩa các giá trị dưới dạng các dòng riêng biệt.

Ví dụ : Sử dụng as_tibble() để đọc dữ liệu từ file .xlsx và chuyển đổi thành tibble:

library(tibble)
library(readxl)
# Đọc dữ liệu từ file .xlsx (ví dụ: "s&p500_data.xlsx")
data_df <- read_xlsx("D:/nnlt/stock.xlsx")

# Chuyển đổi thành tibble
data_tibble <- as_tibble(data_df)

# Hiển thị tibble
print(data_tibble)
## # A tibble: 19 × 4
##    date                close   volume Name 
##    <dttm>              <dbl>    <dbl> <chr>
##  1 2013-02-08 00:00:00  14.8  8407500 AAL  
##  2 2013-02-11 00:00:00  14.5  8882000 AAL  
##  3 2013-02-12 00:00:00  14.3  8126000 AAL  
##  4 2013-02-13 00:00:00  14.7 10259500 AAL  
##  5 2013-02-14 00:00:00  14.0 31879900 AAL  
##  6 2013-02-15 00:00:00  14.5 15628000 AAL  
##  7 2013-02-19 00:00:00  14.3 11354400 AAL  
##  8 2013-02-20 00:00:00  13.3 14725200 AAL  
##  9 2013-02-21 00:00:00  13.4 11922100 AAL  
## 10 2013-02-22 00:00:00  13.6  6071400 AAL  
## 11 2013-02-25 00:00:00  13.0  7186400 AAL  
## 12 2013-02-26 00:00:00  13.3  9419000 AAL  
## 13 2013-02-27 00:00:00  13.4  7390500 AAL  
## 14 2013-02-28 00:00:00  13.4  6143600 AAL  
## 15 2013-03-01 00:00:00  13.6  7376800 AAL  
## 16 2013-03-04 00:00:00  13.9  8174800 AAL  
## 17 2013-03-05 00:00:00  14.0  7676100 AAL  
## 18 2013-03-06 00:00:00  14.6 13243200 AAL  
## 19 2013-03-07 00:00:00  14.8  9125300 AAL

Ví dụ : Sử dụng tibble() để tạo tibble từ các vector cột riêng lẻ

# Đọc dữ liệu từ file .xlsx (ví dụ: "stock.xlsx")
data_df <- read_xlsx("D:/nnlt/stock.xlsx")

# Tạo tibble từ các vector cột riêng lẻ
date <- data_df$date
close <- data_df$close
volume <- data_df$volume

stock_a <- tibble(Date = date, Close = close, Volume = volume)

# Hiển thị tibble
print(stock_a)
## # A tibble: 19 × 3
##    Date                Close   Volume
##    <dttm>              <dbl>    <dbl>
##  1 2013-02-08 00:00:00  14.8  8407500
##  2 2013-02-11 00:00:00  14.5  8882000
##  3 2013-02-12 00:00:00  14.3  8126000
##  4 2013-02-13 00:00:00  14.7 10259500
##  5 2013-02-14 00:00:00  14.0 31879900
##  6 2013-02-15 00:00:00  14.5 15628000
##  7 2013-02-19 00:00:00  14.3 11354400
##  8 2013-02-20 00:00:00  13.3 14725200
##  9 2013-02-21 00:00:00  13.4 11922100
## 10 2013-02-22 00:00:00  13.6  6071400
## 11 2013-02-25 00:00:00  13.0  7186400
## 12 2013-02-26 00:00:00  13.3  9419000
## 13 2013-02-27 00:00:00  13.4  7390500
## 14 2013-02-28 00:00:00  13.4  6143600
## 15 2013-03-01 00:00:00  13.6  7376800
## 16 2013-03-04 00:00:00  13.9  8174800
## 17 2013-03-05 00:00:00  14.0  7676100
## 18 2013-03-06 00:00:00  14.6 13243200
## 19 2013-03-07 00:00:00  14.8  9125300

Ví dụ: Sử dụng tribble() để tạo tibble từ các giá trị dưới dạng hàng

Giả sử ta có bảng dữ liệu sau:

\[ \begin{array}{|l|l|l|l|} \hline \text { Tên } & \text { Kinh tế lượng } & \text { Mô phỏng ngẫu nhiên } & \text { Toán kinh tế } \\ \hline Ánh Linh & 8.5 & 8.75 & 7.5 \\ \hline Hải Phụng & 9.0 & 7.5 & 8.5 \\ \hline Thanh Huệ & 7.75 & 7.5& 7.0\\ \hline Duy Quang & 8.0 &7.5 & 7.0 \\ \hline \end{array} \] Bây giờ, hãy sử dụng hàm tribble() để tạo tibble từ dữ liệu này:

library(tibble)
# Sử dụng hàm tribble() để tạo tibble từ dữ liệu
data_tibble <- tribble(
  ~Ten, ~Kinh_te_luong, ~Mo_phong_nn, ~Toan_kinh_te,
  "Ánh Linh", 8.5, 8.75, 7.5,
  "Hải Phụng", 9.0, 7.5, 8.5,
  "Thanh Huệ", 7.75, 7.5, 7.0,
  "Duy Quang", 8.0, 7.5, 7.0)

# Hiển thị tibble
print(data_tibble)
## # A tibble: 4 × 4
##   Ten       Kinh_te_luong Mo_phong_nn Toan_kinh_te
##   <chr>             <dbl>       <dbl>        <dbl>
## 1 Ánh Linh           8.5         8.75          7.5
## 2 Hải Phụng          9           7.5           8.5
## 3 Thanh Huệ          7.75        7.5           7  
## 4 Duy Quang          8           7.5           7

   Hàm tribble() thường được sử dụng để nhanh chóng tạo tibble từ các dòng dữ liệu nhỏ và đơn giản mà không cần phải tạo một file dữ liệu riêng biệt. Điều này hữu ích khi chúng ta muốn kiểm tra nhanh các hàm và xử lý dữ liệu nhỏ mà không cần tạo một file dữ liệu lưu trữ.

   Tuy nhiên, trong thực tế, khi ta có dữ liệu lớn và phức tạp hơn, thì việc nhập dữ liệu trực tiếp vào mã R như vậy sẽ không hiệu quả và không khả thi. Trong trường hợp này, chúng ta sẽ đọc dữ liệu từ các file lưu trữ dữ liệu (ví dụ: CSV, Excel, SQL, v.v.) bằng các hàm đọc dữ liệu như read.csv(), read_excel(), readr::read_delim(), readr::read_tsv()….

4.2 Các thao tác Dữ liệu với Tibble

   Trong mục này, chúng ta sẽ tìm hiểu cách sử dụng các hàm add_column() và add_row() để thêm cột và hàng vào một tibble, cũng như hướng dẫn về việc sử dụng enframe() để chuyển đổi các vector thành data.frame và ngược lại. Sau đó, chúng ta sẽ cung cấp các ví dụ minh họa về các thao tác chọn lọc dữ liệu trên tibble bằng cách sử dụng các hàm tương ứng.

4.2.1. Thêm cột và hàng vào một tibble

   Sử dụng add_column() để thêm cột vào tibble: Hàm add_column() cho phép bạn thêm một cột mới vào tibble bằng cách chỉ định tên cột và giá trị của cột mới.

# Thêm cột "Trung bình" vào tibble
trungbinh <- add_column(data_tibble, trung_binh = (data_tibble$Kinh_te_luong + data_tibble$Mo_phong_nn + data_tibble$Toan_kinh_te) / 3)
# Hiển thị tibble sau khi thêm cột
print(trungbinh)
## # A tibble: 4 × 5
##   Ten       Kinh_te_luong Mo_phong_nn Toan_kinh_te trung_binh
##   <chr>             <dbl>       <dbl>        <dbl>      <dbl>
## 1 Ánh Linh           8.5         8.75          7.5       8.25
## 2 Hải Phụng          9           7.5           8.5       8.33
## 3 Thanh Huệ          7.75        7.5           7         7.42
## 4 Duy Quang          8           7.5           7         7.5

Tiếp theo, chúng ta sẽ sử dụng hàm add_row() để thêm một hàng mới vào tibble với thông tin của một người mới.

# Tạo dòng mới với tên cột là các symbol
new_row <- list(Ten = "Hoàng Nguyên", Kinh_te_luong = 8.25, Mo_phong_nn = 8.0, Toan_kinh_te = 7.75)

# Thêm dòng mới vào tibble bằng hàm add_row()
new_rows <- add_row(data_tibble, !!!new_row)

# Hiển thị tibble sau khi thêm dòng mới
print(new_rows)
## # A tibble: 5 × 4
##   Ten          Kinh_te_luong Mo_phong_nn Toan_kinh_te
##   <chr>                <dbl>       <dbl>        <dbl>
## 1 Ánh Linh              8.5         8.75         7.5 
## 2 Hải Phụng             9           7.5          8.5 
## 3 Thanh Huệ             7.75        7.5          7   
## 4 Duy Quang             8           7.5          7   
## 5 Hoàng Nguyên          8.25        8            7.75

4.2.2 Chuyển đổi vector thành data.frame và ngược lại

   Sử dụng enframe() để chuyển đổi vector thành data frame: Hàm enframe() cho phép ta chuyển đổi một vector thành một data frame có hai cột: cột tên và cột giá trị.

Ví dụ: từ file stock.xlsx,ta sẽ sử dụng hàm enframe() để chuyển đổi cột “close” thành một data frame có hai cột: cột “name” và cột “value”.

# Chuyển đổi cột "close" thành data frame
close_df <- enframe(stock_a$Close)
# Hiển thị data frame mới
print(close_df)
## # A tibble: 19 × 2
##     name value
##    <int> <dbl>
##  1     1  14.8
##  2     2  14.5
##  3     3  14.3
##  4     4  14.7
##  5     5  14.0
##  6     6  14.5
##  7     7  14.3
##  8     8  13.3
##  9     9  13.4
## 10    10  13.6
## 11    11  13.0
## 12    12  13.3
## 13    13  13.4
## 14    14  13.4
## 15    15  13.6
## 16    16  13.9
## 17    17  14.0
## 18    18  14.6
## 19    19  14.8

Tiếp theo, chúng ta sẽ thực hiện ví dụ về chuyển đổi data frame thành vector sử dụng hàm deframe()

# Chuyển đổi data frame thành vector
close_vector <- deframe(close_df)
# Hiển thị vector mới
print(close_vector)
##     1     2     3     4     5     6     7     8     9    10    11    12    13 
## 14.75 14.46 14.27 14.66 13.99 14.50 14.26 13.33 13.37 13.57 13.02 13.26 13.41 
##    14    15    16    17    18    19 
## 13.43 13.61 13.90 14.05 14.57 14.82

4.2.3 Tạo một đối tượng tibble mới hoặc kiểm tra tính hợp lệ của một đối tượng tibble hiện có

   Hàm new_tibble() trong gói tibble được sử dụng để tạo hoặc xác thực một lớp con của tibble. Đây là hàm hữu ích đặc biệt cho các tác giả gói dự án thực hiện lớp con của tibble, chẳng hạn như sf hay tsibble.

  • new_tibble(): Tạo một đối tượng mới là một lớp con của tbl_df, tbl và data.frame. Hàm này được tối ưu hóa cho hiệu suất, số lượng kiểm tra được giảm xuống tối thiểu. Xem vctrs::new_data_frame() để biết thêm chi tiết.
  • validate_tibble(): Kiểm tra tính nhất quán bên trong của một tibble. Hành vi đúng đắn chỉ đảm bảo nếu hàm này chạy mà không gây ra lỗi.

Ví dụ :

# Sử dụng hàm new_tibble() để tạo tibble mới từ tibble hiện có
new_data_tibble <- new_tibble(data_tibble)
# Sử dụng hàm validate_tibble() để kiểm tra tính hợp lệ của tibble
validate_tibble(new_data_tibble)
## # A tibble: 4 × 4
##   Ten       Kinh_te_luong Mo_phong_nn Toan_kinh_te
##   <chr>             <dbl>       <dbl>        <dbl>
## 1 Ánh Linh           8.5         8.75          7.5
## 2 Hải Phụng          9           7.5           8.5
## 3 Thanh Huệ          7.75        7.5           7  
## 4 Duy Quang          8           7.5           7

4.2.4 Tạo ma trận dữ liệu theo hướng dữ liệu hàng (row-wise)

  • Hàm frame_matrix() trong gói tibble dùng để tạo ma trận dữ liệu theo hướng dữ liệu hàng (row-wise). Điểm nổi bật của hàm này là cú pháp gọn gàng và dễ đọc, giống như hàm tribble().
  • Hàm frame_matrix() được sử dụng để tạo ma trận dữ liệu bằng cách cung cấp các giá trị cho từng cột trong mỗi hàng của ma trận.
  • Cú pháp của hàm là frame_matrix(…) trong đó … là các đối số, mỗi đối số đại diện cho một cột của ma trận. Các cột được đặt tên bằng cú pháp ~tencot trong đó tencot là tên cột.
  • Các cột trong frame_matrix() có thể chứa các loại dữ liệu khác nhau, chẳng hạn như chuỗi ký tự, số, logic…
  • Các cột của frame_matrix() được đặt theo thứ tự mà chúng xuất hiện trong cú pháp, và mỗi cột chứa dữ liệu tương ứng từng hàng của ma trận.
  • Các dữ liệu trong mỗi cột phải có cùng số lượng phần tử, nếu không sẽ xảy ra lỗi.

Ví dụ:

# Tạo ma trận điểm của sinh viên
diem_matrix <- frame_matrix(
  ~Ten, ~Toan, ~Van, ~Anh,
  "Ánh Linh", 8.5, 8.75, 7.5,
  "Hải Phụng", 9.0, 7.5, 8.5,
  "Thanh Huệ", 7.75, 7.5, 7.0,
  "Duy Quang", 8.0, 7.5, 7.0)

# Hiển thị ma trận điểm
print(diem_matrix)
##      Ten         Toan   Van    Anh  
## [1,] "Ánh Linh"  "8.5"  "8.75" "7.5"
## [2,] "Hải Phụng" "9"    "7.5"  "8.5"
## [3,] "Thanh Huệ" "7.75" "7.5"  "7"  
## [4,] "Duy Quang" "8"    "7.5"  "7"

4.2.5 Chuyển đổi vector thành data frame và ngược lại

   Hàm enframe() trong gói tibble được sử dụng để chuyển đổi vector thành data frame và ngược lại. Hàm này hỗ trợ việc làm việc với các cấu trúc dữ liệu vector và data frame một cách thuận tiện và linh hoạt.

   Khi chuyển đổi vector thành data frame, hàm enframe() sẽ tạo ra một data frame với hai cột, một cột để lưu trữ tên của các phần tử trong vector và một cột để lưu trữ giá trị tương ứng của chúng.

   Khi chuyển đổi data frame thành vector, hàm enframe() sẽ lấy giá trị trong một cột của data frame và trả về một vector chứa các giá trị đó.

Ví dụ về chuyển đổi vector thành data frame:

# Vector dữ liệu
vec <- c(10, 20, 30, 40, 50)

# Chuyển đổi vector thành data frame
df <- enframe(vec)

# Hiển thị data frame
print(df)
## # A tibble: 5 × 2
##    name value
##   <int> <dbl>
## 1     1    10
## 2     2    20
## 3     3    30
## 4     4    40
## 5     5    50

Ví dụ về chuyển đổi data frame thành vector:

# Data frame dữ liệu
df <- data.frame(name = c("A", "B", "C"), value = c(10, 20, 30))

# Chuyển đổi data frame thành vector
vec <- enframe(df$value)

# Hiển thị vector
print(vec)
## # A tibble: 3 × 2
##    name value
##   <int> <dbl>
## 1     1    10
## 2     2    20
## 3     3    30

4.2.6 Công cụ làm việc với tên hàng

   Hàm rownames trong gói tibble cung cấp các công cụ để làm việc với tên các hàng trong data frame (rownames).Tuy nhiên, khi thực hiện phép lọc dữ liệu bằng toán tử [ , tên hàng sẽ bị loại bỏ. Nếu chúng ta cố gắng gán tên hàng khác NULL cho một tibble, một cảnh báo sẽ xuất hiện. Thông thường, nên tránh sử dụng tên hàng, vì nó chỉ là một cột ký tự với ý nghĩa khác biệt so với các cột khác.

Có một số hàm hữu ích trong gói tibble để làm việc với tên hàng:

  • has_rownames(.data): Kiểm tra xem một data frame có tên hàng hay không. Hàm trả về giá trị logic (TRUE hoặc FALSE).
  • remove_rownames(.data): Loại bỏ tên hàng khỏi data frame.
  • rownames_to_column(.data, var = “rowname”): Chuyển đổi tên hàng thành một cột cụ thể trong data frame. Bạn có thể chỉ định tên cho cột mới bằng tham số “var”.
  • rowid_to_column(.data, var = “rowid”): Thêm một cột chứa các số ID tăng dần từ 1 đến số hàng của data frame. Hàm này sẽ loại bỏ tên hàng hiện có.
  • column_to_rownames(.data, var = “rowname”): Chuyển đổi một cột cụ thể của data frame thành tên hàng. Tên của cột được chỉ định bởi tham số “var”.

Lưu ý: Một số hàm đã bị loại bỏ ra khỏi gói Tibble mới nhất

Ví dụ:

# Khởi tạo tibble
data_g <- tibble::tribble(
  ~Ten, ~Toan, ~Van, ~Anh,
  "Hải Phụng", 9.0, 7.5, 8.5,
  "Thanh Huệ", 7.75, 7.5, 7.0,
  "Duy Quang", 8.0, 7.5, 7.0)

# Kiểm tra xem tibble có tên hàng hay không
has_row_names <- !is.null(rownames(data_g))

# Chuyển đổi tên hàng thành một cột mới có tên là "ID"
data_tibble_with_id <- tibble::rownames_to_column(data_g, var = "ID")

# Loại bỏ tên hàng khỏi tibble
data_tibble_without_rownames <- tibble::remove_rownames(data_g)

# Chuyển cột "ID" về tên hàng
data_tibble_with_rownames <- tibble::column_to_rownames(data_tibble_with_id, var = "ID")

# Hiển thị kết quả
print("Kiểm tra xem tibble có tên hàng hay không:")
## [1] "Kiểm tra xem tibble có tên hàng hay không:"
print(has_row_names)
## [1] TRUE
print("Chuyển đổi tên hàng thành cột mới:")
## [1] "Chuyển đổi tên hàng thành cột mới:"
print(data_tibble_with_id)
## # A tibble: 3 × 5
##   ID    Ten        Toan   Van   Anh
##   <chr> <chr>     <dbl> <dbl> <dbl>
## 1 1     Hải Phụng  9      7.5   8.5
## 2 2     Thanh Huệ  7.75   7.5   7  
## 3 3     Duy Quang  8      7.5   7
print("Loại bỏ tên hàng khỏi tibble:")
## [1] "Loại bỏ tên hàng khỏi tibble:"
print(data_tibble_without_rownames)
## # A tibble: 3 × 4
##   Ten        Toan   Van   Anh
##   <chr>     <dbl> <dbl> <dbl>
## 1 Hải Phụng  9      7.5   8.5
## 2 Thanh Huệ  7.75   7.5   7  
## 3 Duy Quang  8      7.5   7
print("Chuyển cột ID về tên hàng:")
## [1] "Chuyển cột ID về tên hàng:"
print(data_tibble_with_rownames)
##         Ten Toan Van Anh
## 1 Hải Phụng 9.00 7.5 8.5
## 2 Thanh Huệ 7.75 7.5 7.0
## 3 Duy Quang 8.00 7.5 7.0

4.3 Kết hợp gói tibble với các gói dplyr và ggplot2 trong R để xử lý và trực quan hóa dữ liệu

4.3.1. Sử dụng gói “tidyr” để xử lý dữ liệu với tibble

Trong phần này, chúng ta sẽ giới thiệu cách sử dụng gói “tidyr” cùng với gói “tibble” để xử lý dữ liệu. Gói “tidyr” cung cấp các hàm như gather(), spread(), separate(), unite(), pivot_longer() và pivot_wider() giúp chuyển đổi dữ liệu giữa các định dạng rộng (wide) và dài (long), tách các cột thành nhiều cột mới và kết hợp nhiều cột thành một cột.

Ví dụ:

library(tibble)
library(tidyr)
# Dữ liệu ban đầu (dạng wide)
data_wide <- tibble(
  "Họ tên" = c("Hải Phụng", "Ánh Linh", "Hoàng Nguyên", "Thanh Huệ", "Duy Quang"),
  "Kinh tế lượng" = c(8.5, 9.0, 7.5, 8.25, 8.76),
  "Xác xuất thống kê" = c(7.0, 8.0, 7.5, 8.25, 7.5),
  "Toán cao cấp" = c(8.0, 7.5, 8.25, 8.5, 8.25))

# Chuyển đổi dữ liệu từ wide sang long bằng gather()
data_long <- data_wide %>%
  gather(key = "Môn học", value = "Điểm", "Kinh tế lượng", "Xác xuất thống kê", "Toán cao cấp")

# Hiển thị dữ liệu sau khi chuyển đổi
print(data_long)
## # A tibble: 15 × 3
##    `Họ tên`     `Môn học`          Điểm
##    <chr>        <chr>             <dbl>
##  1 Hải Phụng    Kinh tế lượng      8.5 
##  2 Ánh Linh     Kinh tế lượng      9   
##  3 Hoàng Nguyên Kinh tế lượng      7.5 
##  4 Thanh Huệ    Kinh tế lượng      8.25
##  5 Duy Quang    Kinh tế lượng      8.76
##  6 Hải Phụng    Xác xuất thống kê  7   
##  7 Ánh Linh     Xác xuất thống kê  8   
##  8 Hoàng Nguyên Xác xuất thống kê  7.5 
##  9 Thanh Huệ    Xác xuất thống kê  8.25
## 10 Duy Quang    Xác xuất thống kê  7.5 
## 11 Hải Phụng    Toán cao cấp       8   
## 12 Ánh Linh     Toán cao cấp       7.5 
## 13 Hoàng Nguyên Toán cao cấp       8.25
## 14 Thanh Huệ    Toán cao cấp       8.5 
## 15 Duy Quang    Toán cao cấp       8.25

4.3.2. Sử dụng gói “lubridate” để làm việc với ngày tháng trong tibble:

Gói “lubridate” cung cấp các hàm mạnh mẽ để làm việc với ngày tháng trong R. Khi kết hợp gói “lubridate” với gói “tibble”, chúng ta có thể xử lý dữ liệu ngày tháng một cách dễ dàng và hiệu quả.

Ví dụ:

# Gọi thư viện lubridate
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
# Tạo tibble từ dữ liệu với cột Ngay_sinh dưới dạng character
data_tibble <- tibble(
  Ten = c("Ánh Linh", "Hải Phụng", "Thanh Huệ", "Duy Quang"),
  Ngay_sinh = c("1997-03-15", "2004-09-21", "1999-07-04", "1996-11-30"))

# Sử dụng gói lubridate để tạo cột ngày tháng mới
data_tibble <- data_tibble %>%
  mutate(Ngay_sinh = lubridate::ymd(Ngay_sinh))

# Hiển thị tibble sau khi thêm cột ngày tháng
print(data_tibble)
## # A tibble: 4 × 2
##   Ten       Ngay_sinh 
##   <chr>     <date>    
## 1 Ánh Linh  1997-03-15
## 2 Hải Phụng 2004-09-21
## 3 Thanh Huệ 1999-07-04
## 4 Duy Quang 1996-11-30

4.3.3. Tổng hợp và biểu diễn dữ liệu với dplyr và ggplot2:

Trong phần này, chúng ta sẽ kết hợp sử dụng gói “dplyr” và gói “ggplot2” để tổng hợp và biểu diễn dữ liệu từ tibble.

Ví dụ:

Trong ví dụ này, chúng ta sẽ sử dụng gói “tibble” kết hợp với gói “dplyr” để thực hiện một số phép biến đổi đơn giản trên tập dữ liệu và hiển thị kết quả bằng ggplot2.

Trước hết ta cần cài đăt các gói cần thiết cho việc xử lý dữ liệu.

# Gọi các thư viện cần thiết
library(tibble)
library(dplyr)
library(ggplot2)
library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
# Tạo tibble từ dữ liệu
data_m <- tibble(
  Ten = c("Ánh Linh", "Hải Phụng", "Thanh Huệ", "Duy Quang"),
  MPNN = c(8.5, 9.0, 7.75, 8.0),
  Toan_kt = c(8.75, 7.5, 7.5, 7.5),
  Kinhteluong = c(7.5, 8.5, 7.0, 7.0))

# Lọc ra các sinh viên có điểm Mô phỏng ngẫu nhiên lớn hơn 8.0
filtered_data <- filter(data_m, MPNN > 8.0)

# Sắp xếp các học sinh theo điểm Toán kinh tế giảm dần
sorted_data <- arrange(data_m, desc(Toan_kt))

# Gom nhóm dữ liệu theo điểm Kinh tế lượng và tính tổng điểm của mỗi nhóm
grouped_data <- data_m %>% 
  group_by(Kinhteluong) %>% 
  summarize(Total_Diem = sum(MPNN + Toan_kt + Kinhteluong))

Trực quan hóa dữ liệu bằng ggplot2

Biểu đồ cột thể hiện điểm Mô phỏng ngẫu nhiên của các học sinh

ggplot(data_m, aes(x = Ten, y = MPNN)) +
  geom_bar(stat = "identity", fill = "pink") +
  labs(title = "Điểm Mô phỏng ngẫu nhiên của sinh viên",
       x = "Sinh viên",
       y = "Điểm Mô phỏng ngẫu nhiên")

Biểu đồ 2D điểm của các môn Mô phỏng ngẫu nhiên, Toán kinh tế và Kinh tế lượng của sinh viên

ggplot(data_m, aes(x = Ten)) +
  geom_point(aes(y = MPNN, color = "Mô phỏng ngẫu nhiên")) +
  geom_point(aes(y = Toan_kt, color = "Toán kinh tế")) +
  geom_point(aes(y = Kinhteluong, color = "Kinh tế lượng")) +
  labs(title = "Điểm Mô phỏng ngẫu nhiên, Toán kinh tế và Kinh tế lượng của sinh viên",
       x = "sinh viên",
       y = "Điểm") +
  scale_color_manual(values = c("Mô phỏng ngẫu nhiên" = "blue", "Toán kinh tế" = "red", "Kinh tế lượng" = "green"),
                     labels = c("Mô phỏng ngẫu nhiên", "Toán kinh tế", "Kinh tế lượng"))

Biểu đồ 3D điểm của các môn Mô phỏng ngẫu nhiên, Toán kinh tế và Kinh tế lượng của sinh viên

plot_ly(data_m, x = ~MPNN, y = ~Toan_kt, z = ~Kinhteluong,
        color = ~Ten, colors = c("blue", "red", "green", "orange"),
        text = ~Ten, type = "scatter3d", mode = "markers",
        marker = list(size = 10, opacity = 0.8)) %>%
  layout(scene = list(xaxis = list(title = "Điểm Mô phỏng ngẫu nhiên"),
                      yaxis = list(title = "Điểm Toán kinh tế"),
                      zaxis = list(title = "Điểm Kinh tế lượng")))

Biểu đồ cột thể hiện tổng điểm của các nhóm dựa trên điểm Kinh tế lượng

ggplot(grouped_data, aes(x = Kinhteluong, y = Total_Diem)) +
  geom_bar(stat = "identity", fill = "salmon") +
  labs(title = "Tổng điểm theo điểm Kinh tế lượng",
       x = "Điểm Kinh tế lượng",
       y = "Tổng điểm")

4.3.4. Sử dụng gói “stringr” để làm việc với chuỗi trong tibble

Gói “stringr” cung cấp các hàm hỗ trợ xử lý và biến đổi chuỗi trong R. Khi kết hợp gói “stringr” với gói “tibble”, chúng ta có thể thực hiện các phép biến đổi chuỗi một cách dễ dàng.

Ví dụ:

# Tạo tibble từ dữ liệu với cột Ten dưới dạng character
data_tibble <- tibble(
  Ten = c("Ánh Linh", "Hải Phụng", "Thanh Huệ", "Duy Quang"))

# Sử dụng gói stringr để thay đổi tên sinh viên thành in hoa
data_tibble <- data_tibble %>%
  mutate(Ten = stringr::str_to_upper(Ten))

# Hiển thị tibble sau khi thay đổi tên
print(data_tibble)
## # A tibble: 4 × 1
##   Ten      
##   <chr>    
## 1 ÁNH LINH 
## 2 HẢI PHỤNG
## 3 THANH HUỆ
## 4 DUY QUANG

4.3.5. Xử lý dữ liệu thiếu và lỗi trong tibble

Trong phần này, chúng ta sẽ tìm hiểu cách xử lý dữ liệu thiếu và lỗi trong tibble. Chúng ta sẽ sử dụng các hàm như na.omit(), complete(), fill(), drop_na() để xử lý các giá trị thiếu và lỗi trong dữ liệu.

Ví dụ:

# Tạo tibble từ dữ liệu với một số giá trị thiếu
data_tibble <- tibble(
  Ten = c("Ánh Linh", NA, "Thanh Huệ", "Duy Quang"),
  Diem = c(NA, 9.0, 7.5, 8.0)
)

# Sử dụng na.omit() để loại bỏ các hàng có giá trị thiếu
data_tibble <- na.omit(data_tibble)

# Sử dụng complete() và fill() để điền giá trị thiếu
data_tibble <- data_tibble %>%
  complete(Ten, fill = list(Diem = 0))

# Sử dụng drop_na() để loại bỏ các hàng có giá trị thiếu
data_tibble <- drop_na(data_tibble)

# Hiển thị tibble sau khi xử lý dữ liệu thiếu
print(data_tibble)
## # A tibble: 2 × 2
##   Ten        Diem
##   <chr>     <dbl>
## 1 Duy Quang   8  
## 2 Thanh Huệ   7.5

4.3.6. Định dạng dữ liệu trong tibble

Trong phần này, chúng ta sẽ tìm hiểu cách định dạng dữ liệu trong tibble. Điều này bao gồm định dạng kiểu dữ liệu của các cột và định dạng hiển thị của các giá trị.

Ví dụ:

# Tạo tibble từ dữ liệu với cột điểm dưới dạng numeric
data_tibble <- tibble(
  Ten = c("Ánh Linh", "Hải Phụng", "Thanh Huệ", "Duy Quang"),
  Diem = c(8.5, 9.0, 7.75, 8.0))

# Định dạng kiểu dữ liệu của cột Diem thành số thập phân có hai chữ số sau dấu phẩy
data_tibble$Diem <- round(data_tibble$Diem, 2)

# Hiển thị tibble sau khi định dạng dữ liệu
print(data_tibble)
## # A tibble: 4 × 2
##   Ten        Diem
##   <chr>     <dbl>
## 1 Ánh Linh   8.5 
## 2 Hải Phụng  9   
## 3 Thanh Huệ  7.75
## 4 Duy Quang  8

Chương 5 : Ưu điểm và hạn chế của package Tibble

5.1 Ưu điểm

  • Cú pháp dễ đọc và sáng sủa: Tibble sử dụng cú pháp đơn giản và dễ hiểu, giúp người dùng dễ dàng đọc, sửa đổi và thao tác dữ liệu một cách hiệu quả.
  • Xử lý dữ liệu linh hoạt: Tibble hỗ trợ việc chọn lọc, biến đổi và truy xuất dữ liệu một cách linh hoạt, giúp tiết kiệm thời gian và công sức khi thực hiện phân tích dữ liệu phức tạp.
  • Xử lý metadata: Tibble cho phép lưu trữ các metadata (thông tin về biến và quan sát) cùng với dữ liệu, giúp người dùng dễ dàng thêm, sửa đổi và sử dụng thông tin bổ sung về dữ liệu trong quá trình phân tích.
  • Tích hợp tốt với dữ liệu dạng danh sách (list-columns): Tibble cho phép lưu trữ dữ liệu dạng danh sách (list-columns), giúp giải quyết vấn đề xử lý dữ liệu phức tạp và đa cấp độ một cách hiệu quả.
  • Hỗ trợ tích hợp và tương thích: Tibble được tích hợp mạnh mẽ với các gói phân tích dữ liệu phổ biến trong R như dplyr, ggplot2, tidyr, dtplyr, giúp người dùng tận dụng toàn bộ khả năng của R trong phân tích dữ liệu.
  • Hiệu suất tối ưu: Tibble tối ưu hóa hiệu suất xử lý dữ liệu, giúp giảm thời gian thực thi các thao tác phức tạp và xử lý dữ liệu lớn nhanh chóng và hiệu quả.
  • Hỗ trợ dễ dàng: Package Tibble được hỗ trợ và phát triển liên tục bởi cộng đồng người dùng và nhà phát triển R, đảm bảo sự ổn định và cải tiến liên tục.

5.2 Hạn chế

  • Yêu cầu cài đặt package: Mặc dù package Tibble là một công cụ mạnh mẽ, nhưng nó cần phải được cài đặt trong R trước khi sử dụng. Điều này có thể tạo ra một số rào cản đối với người dùng mới hoặc trong môi trường không cho phép cài đặt package.
  • Sự khác biệt với data.frame: Mặc dù Tibble chủ yếu là một phiên bản tối ưu của data.frame, nhưng nó có một số sự khác biệt về cú pháp và tính năng so với data.frame, điều này có thể đòi hỏi người dùng học thêm và thích nghi với Tibble.
  • Đối với dữ liệu lớn: Trong một số trường hợp với dữ liệu rất lớn, hiệu suất của Tibble có thể bị ảnh hưởng. Dựa vào tính chất của dữ liệu và loại phân tích, người dùng có thể phải xem xét việc sử dụng Tibble so với các phương pháp xử lý dữ liệu lớn khác.
  • Không tương thích với một số gói cũ: Trong một số trường hợp, Tibble có thể không tương thích hoặc hỗ trợ không đầy đủ với một số gói cũ trong R, đặc biệt là các gói không còn được phát triển và cập nhập.

5.3 Kết luận

   Trong quá trình nghiên cứu và thực hiện đề tài này, em đã khám phá sâu hơn về package Tibble và hứng thú hơn với sự tiện ích mà nó mang lại trong việc xử lý và quản lý dữ liệu. Tibble không chỉ là một phiên bản cải tiến của data.frame, mà còn là một công cụ linh hoạt và hiệu quả hơn trong việc làm việc với dữ liệu trong môi trường R.

   Những ưu điểm đáng chú ý của Tibble đã thể hiện rõ ràng qua việc giúp tiết kiệm bộ nhớ, tăng tốc độ xử lý dữ liệu và tránh được những lỗi thường gặp khi sử dụng data.frame. Sự linh hoạt và khả năng chuyển đổi linh hoạt giữa data.frame và Tibble đã giúp em dễ dàng tích hợp Tibble vào các dự án phân tích dữ liệu hiện có.

   Thành công của Tibble cũng nằm ở khả năng hỗ trợ tốt từ cộng đồng và sự liên tục cải tiến, giúp bảo đảm tính ổn định và phù hợp với nhu cầu của người dùng. Việc tích hợp các tính năng tiện ích như việc xử lý dữ liệu thô, phân tích dữ liệu mà không cần chuyển đổi về dạng data.frame đã thúc đẩy quá trình làm việc của em một cách hiệu quả và hiệu nghiệm.

   Tuy đề tài này chỉ tập trung vào package Tibble, nhưng từ những kiến thức và kinh nghiệm thu thập được, em có cái nhìn tổng quan hơn về quy trình xử lý dữ liệu trong R. Package Tibble đã mở ra cánh cửa mới cho em và chắc chắn sẽ tiếp tục được áp dụng trong những dự án tương lai.

   Cuối cùng, việc thực hiện đề tài này đã giúp em nâng cao kỹ năng phân tích dữ liệu và làm việc hiệu quả với R. Em rất hài lòng với kết quả đạt được và hy vọng rằng bài viết này sẽ hỗ trợ và khơi gợi sự quan tâm của những người quan tâm đến việc xử lý dữ liệu trong môi trường R.

LS0tDQp0aXRsZTogJ1Rp4buDdSBsdeG6rW4gbcO0bjogTmfDtG4gbmfhu68gbOG6rXAgdHLDrG5oIHRyb25nIHBow6JuIHTDrWNoIGThu68gbGnhu4d1Jw0KYXV0aG9yOiAiSOG7kyBEdXkgUXVhbmciDQpkYXRlOiAiMjAyMy0wNy0wMyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgICBkZl9wcmludDogcGFnZWQNCiAgICAgIGhpZ2hsaWdodDoga2F0ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQotLS0NCiMgKioixJDhu4AgVMOASTogUEFDS0FHRSBUSUJCTEUgVFJPTkcgUiIqKg0KDQoNCg0KIyAqKkNoxrDGoW5nIDE6IEdp4bubaSB0aGnhu4d1IHbhu4EgcGFja2FnZSBUaWJibGUqKg0KDQojIyAxLjEgR2nhu5tpIHRoaeG7h3UNCg0KJmVuc3A7JmVuc3A7JmVuc3A7VHJvbmcgdGjhu51pIMSR4bqhaSBz4buRIGjDs2EgbmfDoHkgbmF5LCBwaMOibiB0w61jaCBk4buvIGxp4buHdSDEkcOzbmcgdmFpIHRyw7Iga2jDtG5nIHRo4buDIHRoaeG6v3UgdsOgIHRy4bufIHRow6BuaCBt4buZdCB54bq/dSB04buRIHF1eeG6v3QgxJHhu4tuaCB0cm9uZyBxdcOhIHRyw6xuaCByYSBxdXnhur90IMSR4buLbmggdsOgIMSR4buLbmggaMaw4bubbmcgY2hp4bq/biBsxrDhu6NjLiBUdXkgbmhpw6puLCB2aeG7h2MgbMOgbSB2aeG7h2MgduG7m2kgZOG7ryBsaeG7h3UgxJHDtGkga2hpIGfhurdwIHBo4bqjaSBuaGnhu4F1IGtow7Mga2jEg24gdsOgIHRow6FjaCB0aOG7qWMsIHThu6sgdmnhu4djIG5o4bqtcCBsaeG7h3Uga2jDtG5nIGNow61uaCB4w6FjLCBk4buvIGxp4buHdSBraMO0bmcgxJHhuqd5IMSR4bunLCDEkeG6v24gcXXDoSB0csOsbmggeOG7rSBsw70gZOG7ryBsaeG7h3UgcGjhu6ljIHThuqFwIHbDoCDEkeG7k25nIG5o4bqldC4NCg0KJmVuc3A7JmVuc3A7JmVuc3A7VHJvbmcgYuG7kWkgY+G6o25oIMSRw7MsIHBhY2thZ2UgVGliYmxlIHRyb25nIG5nw7RuIG5n4buvIGzhuq1wIHRyw6xuaCBSIMSRw6MgbmhhbmggY2jDs25nIHRy4bufIHRow6BuaCBt4buZdCBjw7RuZyBj4bulIHBo4buVIGJp4bq/biB2w6AgaOG7r3Ugw61jaCB0cm9uZyB2aeG7h2MgcXXhuqNuIGzDvSB2w6AgeOG7rSBsw70gZOG7ryBsaeG7h3UuIFRpYmJsZSBjdW5nIGPhuqVwIG3hu5l0IGPDoWNoIHRp4bq/cCBj4bqtbiBoaeG7h24gxJHhuqFpIHbDoCBsaW5oIGhv4bqhdCBoxqFuIMSR4buDIGzDoG0gdmnhu4djIHbhu5tpIGThu68gbGnhu4d1LCBtYW5nIGzhuqFpIG5o4buvbmcgbOG7o2kgw61jaCDEkcOhbmcga+G7gyBjaG8gbmjhu69uZyBuZ8aw4budaSBsw6BtIHZp4buHYyB0cm9uZyBsxKluaCB24buxYyBwaMOibiB0w61jaCBk4buvIGxp4buHdS4gVHJvbmcgcGjhuqduIGdp4bubaSB0aGnhu4d1IG7DoHksIGVtIHPhur0gdMOsbSBoaeG7g3UgduG7gSBwYWNrYWdlIFRpYmJsZSwgbeG7pWMgdGnDqnUgbmdoacOqbiBj4bupdSBj4bunYSBiw6BpIHRp4buDdSBsdeG6rW4sIHbDoCBwaOG6oW0gdmkgbmdoacOqbiBj4bupdS4NCg0KIyMgMS4yIEzDvSBkbyBjaOG7jW4gxJHhu4EgdMOgaQ0KDQomZW5zcDsmZW5zcDsmZW5zcDtUcm9uZyB0aOG7nWkgxJHhuqFpIHPhu5EgaMOzYSB2w6AgcGjDoXQgdHJp4buDbiBt4bqhbmggbeG6vSBj4bunYSBk4buvIGxp4buHdSwgdmnhu4djIHF14bqjbiBsw70gdsOgIHjhu60gbMO9IGThu68gbGnhu4d1IMSRw6MgdHLhu58gdGjDoG5oIG3hu5l0IHRow6FjaCB0aOG7qWMga2jDtG5nIG5o4buPIMSR4buRaSB24bubaSBjw6FjIG5ow6AgbmdoacOqbiBj4bupdSwgY2h1ecOqbiBnaWEgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgdsOgIG5o4buvbmcgbmfGsOG7nWkgbMOgbSB2aeG7h2MgdHJvbmcgbMSpbmggduG7sWMgdMOgaSBjaMOtbmgsIGtpbmggZG9hbmgsIHkgdOG6vyB2w6Agbmhp4buBdSBsxKluaCB24buxYyBraMOhYy4gVuG7m2kgc+G7kSBsxrDhu6NuZyBk4buvIGxp4buHdSBuZ8OgeSBjw6BuZyB0xINuZywgdmnhu4djIHjhu60gbMO9IHbDoCBraGFpIHRow6FjIHRyaSB0aOG7qWMgdOG7qyBk4buvIGxp4buHdSB0cuG7nyB0aMOgbmggbeG7mXQgecOqdSBj4bqndSBj4bqlcCBiw6FjaCDEkeG7gyDEkcawYSByYSBxdXnhur90IMSR4buLbmggdGjDtG5nIG1pbmggdsOgIHBow6F0IHRyaeG7g24gYuG7gW4gduG7r25nLg0KDQomZW5zcDsmZW5zcDsmZW5zcDtFbSBs4buxYSBjaOG7jW4gxJHhu4EgdMOgaSBuZ2hpw6puIGPhu6l1IHbhu4EgcGFja2FnZSBUaWJibGUgdHJvbmcgbmfDtG4gbmfhu68gbOG6rXAgdHLDrG5oIFIuIFRpYmJsZSBsw6AgbeG7mXQgY8O0bmcgY+G7pSBt4bqhbmggbeG6vSB2w6AgbGluaCBob+G6oXQgZ2nDunAgbmfGsOG7nWkgZMO5bmcgcXXhuqNuIGzDvSB2w6AgeOG7rSBsw70gZOG7ryBsaeG7h3UgbeG7mXQgY8OhY2ggaGnhu4d1IHF14bqjLiDEkMOieSBsw6AgbeG7mXQgYsaw4bubYyB0aeG6v24gcXVhbiB0cuG7jW5nIHRyb25nIHZp4buHYyBj4bqjaSB0aGnhu4duIHF1eSB0csOsbmggbMOgbSB2aeG7h2MgduG7m2kgZOG7ryBsaeG7h3UgdsOgIG7Dom5nIGNhbyBoaeG7h3Ugc3XhuqV0IHBow6JuIHTDrWNoIGThu68gbGnhu4d1Lg0KDQpMw70gZG8gZW0gcXV54bq/dCDEkeG7i25oIG5naGnDqm4gY+G7qXUgduG7gSBwYWNrYWdlIFRpYmJsZSA6DQoNCi0gxJDGoW4gZ2nhuqNuIHbDoCBk4buFIHPhu60gZOG7pW5nOiBUaWJibGUgY3VuZyBj4bqlcCBj4bqldSB0csO6YyBk4buvIGxp4buHdSB0cuG7sWMgcXVhbiB2w6AgZOG7hSDEkeG7jWMsIGdpw7pwIG5nxrDhu51pIGTDuW5nIGzDoG0gdmnhu4djIGThu4UgZMOgbmcgdsOgIGxpbmggaG/huqF0Lg0KLSBUxrDGoW5nIHRow61jaCB24bubaSBjw6FjIGPDtG5nIGPhu6UgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3U6IFRpYmJsZSB0w61jaCBo4bujcCB04buRdCB24bubaSBjw6FjIHBhY2thZ2UgZHBseXIgdsOgIGdncGxvdDIsIGdpw7pwIHRo4buxYyBoaeG7h24gYmnhur9uIMSR4buVaSB2w6AgdOG6oW8gYmnhu4N1IMSR4buTIG3hu5l0IGPDoWNoIHRodeG6rW4gdGnhu4duLg0KLSBIaeG7h3Ugc3XhuqV0IHbDoCBraOG6oyBuxINuZyBt4bufIHLhu5luZzogVGliYmxlIMSRxrDhu6NjIHThu5FpIMawdSBow7NhIMSR4buDIHjhu60gbMO9IGThu68gbGnhu4d1IGzhu5tuLCBnacO6cCBsw6BtIHZp4buHYyBuaGFuaCBjaMOzbmcgdsOgIGhp4buHdSBxdeG6oy4NCi0gUXXhuqNuIGzDvSBk4buvIGxp4buHdSDEkeG7k25nIG5o4bqldDogVGliYmxlIGdpw7pwIMSR4bqjbSBi4bqjbyB0w61uaCBuaOG6pXQgcXXDoW4gdsOgIMSR4buTbmcgbmjhuqV0IGPhu6dhIGThu68gbGnhu4d1LCB04burIMSR4bq3dCB0w6puIGPhu5l0IGThu4UgaGnhu4N1IMSR4bq/biB44butIGzDvSBk4buvIGxp4buHdSB0aGnhur91Lg0KDQpW4bubaSBuZ2hpw6puIGPhu6l1IHbhu4EgcGFja2FnZSBUaWJibGUsIGVtIGh5IHbhu41uZyDEkcOzbmcgZ8OzcCB2w6BvIHF1eSB0csOsbmggbMOgbSB2aeG7h2MgduG7m2kgZOG7ryBsaeG7h3UgdsOgIG7Dom5nIGNhbyBoaeG7h3Ugc3XhuqV0IHBow6JuIHTDrWNoIGThu68gbGnhu4d1LiDEkGnhu4F1IG7DoHkgc+G6vSBtYW5nIGzhuqFpIGdpw6EgdHLhu4sgdsOgIHRp4buBbSBuxINuZyBjaG8gY8OhYyBsxKluaCB24buxYyBuaMawIG5naGnDqm4gY+G7qXUga2hvYSBo4buNYyB2w6AgcXXhuqNuIGzDvSBraW5oIGRvYW5oLg0KDQojIyAxLjMgTeG7pWMgdGnDqnUgbmdoacOqbiBj4bupdQ0KDQomZW5zcDsmZW5zcDsmZW5zcDtN4bulYyB0acOqdSBj4bunYSBuZ2hpw6puIGPhu6l1IG7DoHkgbMOgIGtow6FtIHBow6EgdsOgIGhp4buDdSByw7UgaMahbiB24buBIHBhY2thZ2UgVGliYmxlIHRyb25nIFIgdsOgIGto4bqjIG7Eg25nIGPhu6dhIG7DsyB0cm9uZyB2aeG7h2MgcXXhuqNuIGzDvSB2w6AgeOG7rSBsw70gZOG7ryBsaeG7h3UuDQoNCkPhu6UgdGjhu4MsIGVtIMSR4buBIHJhIGPDoWMgbeG7pWMgdGnDqnUgc2F1IDoNCg0KLSBUw6xtIGhp4buDdSB24buBIGPhuqV1IHRyw7pjIHbDoCB0w61uaCBuxINuZyBj4bunYSBUaWJibGU6IEVtIHPhur0gbmdoacOqbiBj4bupdSBjw6FjaCBUaWJibGUgdOG7lSBjaOG7qWMgdsOgIGzGsHUgdHLhu68gZOG7ryBsaeG7h3UsIGPFqW5nIG5oxrAgY8OhYyB0w61uaCBuxINuZyB2w6AgxrB1IMSRaeG7g20gY+G7p2EgbsOzIHNvIHbhu5tpIGPDoWMgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3Uga2jDoWMuDQotIFRo4buxYyBoaeG7h24gY8OhYyBwaMOpcCBiaeG6v24gxJHhu5VpIGThu68gbGnhu4d1OiBFbSBz4bq9IHTDrG0gaGnhu4N1IGPDoWNoIHPhu60gZOG7pW5nIFRpYmJsZSDEkeG7gyB0aOG7sWMgaGnhu4duIGPDoWMgcGjDqXAgYmnhur9uIMSR4buVaSBk4buvIGxp4buHdSBuaMawIGzhu41jLCBz4bqvcCB44bq/cCwgxJHhu5VpIHTDqm4gY+G7mXQgdsOgIHRow6ptIGPhu5l0IG3hu5tpLiBFbSBjxaluZyBz4bq9IGtow6FtIHBow6EgY8OhYyB0w61uaCBuxINuZyBsaW5oIGhv4bqhdCBj4bunYSBUaWJibGUgdHJvbmcgdmnhu4djIGzDoG0gdmnhu4djIHbhu5tpIGThu68gbGnhu4d1Lg0KLSBU4bqhbyBiaeG7g3UgxJHhu5MgdsOgIHRy4buxYyBxdWFuIGjDs2EgZOG7ryBsaeG7h3U6IEVtIHPhur0gdGjhu7FjIGhp4buHbiB2aeG7h2MgdOG6oW8gYmnhu4N1IMSR4buTIHbDoCB0cuG7sWMgcXVhbiBow7NhIGThu68gbGnhu4d1IHPhu60gZOG7pW5nIFRpYmJsZSB2w6AgcGFja2FnZSBnZ3Bsb3QyLiBFbSBz4bq9IGtow6FtIHBow6EgY8OhYyBsb+G6oWkgYmnhu4N1IMSR4buTIHBo4buVIGJp4bq/biBuaMawIGJp4buDdSDEkeG7kyBj4buZdCwgYmnhu4N1IMSR4buTIMSRaeG7g20gdsOgIGJp4buDdSDEkeG7kyDEkcaw4budbmcuDQotIMOBcCBk4bulbmcgVGliYmxlIHbDoG8gY8OhYyB0w6xuaCBodeG7kW5nIHRo4buxYyB04bq/OiBFbSBz4bq9IHRyw6xuaCBiw6B5IGPDoWMgdsOtIGThu6UgdsOgIHTDrG5oIGh14buRbmcgdGjhu7FjIHThur8gxJHhu4MgbWluaCBo4buNYSBz4buxIOG7qW5nIGThu6VuZyBj4bunYSBUaWJibGUgdHJvbmcgdmnhu4djIHF14bqjbiBsw70gdsOgIHjhu60gbMO9IGThu68gbGnhu4d1LiBFbSBz4bq9IHRo4buxYyBoaeG7h24gY8OhYyB0aGFvIHTDoWMgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgdsOgIHRy4bqjIGzhu51pIGPDoWMgY8OidSBo4buPaSBwaMOibiB0w61jaCBz4butIGThu6VuZyBUaWJibGUuDQotIMSQw6FuaCBnacOhIGhp4buHdSBxdeG6oyB2w6AgbOG7o2kgw61jaCBj4bunYSBUaWJibGU6IEVtIHPhur0gxJHDoW5oIGdpw6EgaGnhu4d1IHF14bqjIHbDoCBs4bujaSDDrWNoIGPhu6dhIHZp4buHYyBz4butIGThu6VuZyBUaWJibGUgdHJvbmcgcXV5IHRyw6xuaCBsw6BtIHZp4buHYyB24bubaSBk4buvIGxp4buHdS4gRW0gc+G6vSBzbyBzw6FuaCBUaWJibGUgduG7m2kgY8OhYyBwaMawxqFuZyBwaMOhcCB2w6AgY8O0bmcgY+G7pSBraMOhYyDEkeG7gyBoaeG7g3UgcsO1IGjGoW4gduG7gSDGsHUgxJFp4buDbSB2w6AgZ2nhu5tpIGjhuqFuIGPhu6dhIG7Dsy4NCg0KIyMgMS40IFBo4bqhbSB2aSBuZ2hpw6puIGPhu6l1DQoNCiZlbnNwOyZlbnNwOyZlbnNwO1Bo4bqhbSB2aSBuZ2hpw6puIGPhu6l1IGPhu6dhIGLDoGkgdGnhu4N1IGx14bqtbiB24buBIHBhY2thZ2UgVGliYmxlIHRyb25nIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IHPhur0gdOG6rXAgdHJ1bmcgdsOgbyBjw6FjIGtow61hIGPhuqFuaCBzYXU6DQoNCi0gVMOsbSBoaeG7g3UgduG7gSBwYWNrYWdlIFRpYmJsZSB2w6AgaGnhu4N1IHLDtSDEkeG7i25oIG5naMSpYSB2w6AgbcO0IHThuqMgY+G7p2EgbsOzLiBOZ2hpw6puIGPhu6l1IHPhur0gdOG6rXAgdHJ1bmcgdsOgbyBjw6FjIHTDrW5oIG7Eg25nIHbDoCBs4bujaSDDrWNoIGPhu6dhIFRpYmJsZSB0cm9uZyB2aeG7h2MgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UuDQotIFNvIHPDoW5oIHPhu7Ega2jDoWMgYmnhu4d0IGdp4buvYSBUaWJibGUgdsOgIGRhdGEgZnJhbWUgdGjDtG5nIHRoxrDhu51uZy4gUGjDom4gdMOtY2ggc+G6vSB04bqtcCB0cnVuZyB2w6BvIG5o4buvbmcgxrB1IMSRaeG7g20gdsOgIHRp4buBbSBuxINuZyBj4bunYSBUaWJibGUgc28gduG7m2kgZGF0YSBmcmFtZSB0cnV54buBbiB0aOG7kW5nIHRyb25nIHZp4buHYyBwaMOibiB0w61jaCBk4buvIGxp4buHdS4NCi0gVMOsbSBoaeG7g3UgduG7gSBjw6FjIHTDrW5oIG7Eg25nIGNow61uaCBj4bunYSBUaWJibGUsIGJhbyBn4buTbSBj4bqldSB0csO6YyBk4buvIGxp4buHdSBsaW5oIGhv4bqhdCB2w6AgdGnhu4duIMOtY2gsIHjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdsOgIHjhu60gbMO9IG1ldGFkYXRhLCBjxaluZyBuaMawIGto4bqjIG7Eg25nIHTGsMahbmcgdGjDrWNoIHbDoCB0w61jaCBo4bujcCB24bubaSBjw6FjIGfDs2kgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3Uga2jDoWMgdHJvbmcgUi4NCi0gTmdoacOqbiBj4bupdSB24buBIGPDoWMg4bupbmcgZOG7pW5nIGPhu6dhIFRpYmJsZSB0cm9uZyBwaMOibiB0w61jaCBk4buvIGxp4buHdS4gUGjDom4gdMOtY2ggc+G6vSB04bqtcCB0cnVuZyB2w6BvIGto4bqjIG7Eg25nIHjhu60gbMO9IHbDoCBiaeG6v24gxJHhu5VpIGThu68gbGnhu4d1IG3hu5l0IGPDoWNoIG5oYW5oIGNow7NuZyB2w6AgbGluaCBob+G6oXQsIHRoYW8gdMOhYyB2w6AgdHJ1eSB24bqlbiBk4buvIGxp4buHdSBoaeG7h3UgcXXhuqMsIGPFqW5nIG5oxrAga2jhuqMgbsSDbmcgdOG6oW8gYmnhu4N1IMSR4buTIHbDoCBiw6FvIGPDoW8gY2jhuqV0IGzGsOG7o25nIGNhbyB24bubaSBUaWJibGUuDQotIFRp4bq/biBow6BuaCBjw6FjIHRo4buxYyBuZ2hp4buHbSB2w6Agw6FwIGThu6VuZyB0aOG7sWMgdOG6vyBj4bunYSBUaWJibGUgdHJvbmcgY8OhYyBwaMOibiB0w61jaCBk4buvIGxp4buHdSB0aOG7kW5nIGvDqiwgeMOieSBk4buxbmcgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIHbDoCB0cuG7sWMgcXVhbiBow7NhIGThu68gbGnhu4d1IHbhu5tpIGdncGxvdDIgdsOgIFRpYmJsZS4NCi0gxJDDoW5oIGdpw6EgxrB1IMSRaeG7g20gdsOgIGjhuqFuIGNo4bq/IGPhu6dhIHBhY2thZ2UgVGliYmxlLiBQaMOibiB0w61jaCBz4bq9IHhlbSB4w6l0IGPDoWMgxrB1IMSRaeG7g20gY+G7p2EgVGliYmxlIG5oxrAgdMOtbmggbGluaCBob+G6oXQsIHRp4buHbiDDrWNoIHbDoCB0w61jaCBo4bujcCB04buRdCB24bubaSBjw6FjIGfDs2kgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3Uga2jDoWMsIGPFqW5nIG5oxrAgbmjhu69uZyBo4bqhbiBjaOG6vyBjw7MgdGjhu4MgZ+G6t3AgcGjhuqNpIGtoaSBz4butIGThu6VuZyBUaWJibGUgdHJvbmcgbeG7mXQgc+G7kSB0csaw4budbmcgaOG7o3AgY+G7pSB0aOG7gy4NCi0gVOG7lW5nIGvhur90IG7hu5lpIGR1bmcgdsOgIGvhur90IHF14bqjIG5naGnDqm4gY+G7qXUsIMSRw6FuaCBnacOhIGhp4buHdSBxdeG6oyB2w6AgdGnhu4FtIG7Eg25nIGPhu6dhIFRpYmJsZSB0cm9uZyBwaMOibiB0w61jaCBk4buvIGxp4buHdS4NCi0gxJDhu4EgeHXhuqV0IGjGsOG7m25nIHBow6F0IHRyaeG7g24gdsOgIG5naGnDqm4gY+G7qXUgdGnhur9wIHRoZW8gY2hvIFRpYmJsZSwgYmFvIGfhu5NtIGPhuqNpIHRp4bq/biB2w6AgbeG7nyBy4buZbmcgdMOtbmggbsSDbmcgY+G7p2EgbsOzLCBjxaluZyBuaMawIG5naGnDqm4gY+G7qXUgc8OidSBoxqFuIHbhu4Eg4bupbmcgZOG7pW5nIGPhu6dhIFRpYmJsZSB0cm9uZyBjw6FjIGzEqW5oIHbhu7FjIGPhu6UgdGjhu4MuDQoNClbhu5tpIHBo4bqhbSB2aSBuZ2hpw6puIGPhu6l1IG5oxrAgdHLDqm4sIGLDoGkgdGnhu4N1IGx14bqtbiBz4bq9IGdpw7pwIMSR4buLbmggcsO1IHRp4buBbSBuxINuZyB2w6Ag4bupbmcgZOG7pW5nIGPhu6dhIHBhY2thZ2UgVGliYmxlIHRyb25nIHBow6JuIHTDrWNoIGThu68gbGnhu4d1LiBOw7Mgc+G6vSBjdW5nIGPhuqVwIGtp4bq/biB0aOG7qWMgY+G6p24gdGhp4bq/dCDEkeG7gyBoaeG7g3UgdsOgIHPhu60gZOG7pW5nIFRpYmJsZSBt4buZdCBjw6FjaCBoaeG7h3UgcXXhuqMgdHJvbmcgcXXDoSB0csOsbmggeOG7rSBsw70sIHRydXkgduG6pW4gdsOgIGJp4buDdSDEkeG7kyBow7NhIGThu68gbGnhu4d1Lg0KDQojICoqQ2jGsMahbmcgMiA6IEtow6FpIHF1w6F0IHbhu4EgcGFja2FnZSBUaWJibGUqKg0KDQojIyAyLjEgxJDhu4tuaCBuZ2jEqWEgdsOgIG3DtCB04bqjDQoNCiZlbnNwOyZlbnNwOyZlbnNwO1BhY2thZ2UgVGliYmxlIHRyb25nIG5nw7RuIG5n4buvIGzhuq1wIHRyw6xuaCBSIGzDoCBt4buZdCBjw7RuZyBj4bulIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IGxpbmggaG/huqF0IHbDoCB0aeG7h24gw61jaCBoxqFuIHNvIHbhu5tpIGRhdGEgZnJhbWUgdGjDtG5nIHRoxrDhu51uZy4gVGliYmxlIGdp4buvIG5ndXnDqm4gY8OhYyDEkeG6t2MgxJFp4buDbSBjxqEgYuG6o24gY+G7p2EgZGF0YSBmcmFtZSwgbmjGsG5nIGPhuqNpIHRoaeG7h24gY2jDum5nIGLhurFuZyBjw6FjaCB0aMOqbSB0w61uaCBuxINuZyBt4bqhbmggbeG6vS4gTsOzIGdpw7pwIHjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdsOgIG1ldGFkYXRhIGThu4UgZMOgbmcgaMahbiwgdMawxqFuZyB0aMOtY2ggduG7m2kgY8OhYyBnw7NpIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IGtow6FjIHRyb25nIFIuIFRpYmJsZSBjdW5nIGPhuqVwIG3hu5l0IGPDuiBwaMOhcCDEkcahbiBnaeG6o24gdsOgIHRyw6FuaCBjw6FjIGzhu5dpIHBo4buVIGJp4bq/biBraGkgbMOgbSB2aeG7h2MgduG7m2kgZGF0YSBmcmFtZS4NCg0KJmVuc3A7JmVuc3A7JmVuc3A7VHJvbmcgYsOgaSB0aeG7g3UgbHXhuq1uIG7DoHksIGVtIHPhur0gdMOsbSBoaeG7g3UgY8OhYyB0w61uaCBuxINuZyBjaMOtbmggY+G7p2EgVGliYmxlIG5oxrAgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3UgbGluaCBob+G6oXQsIHjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdsOgIG1ldGFkYXRhLCB0w61jaCBo4bujcCB24bubaSBjw6FjIGfDs2kgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3Uga2jDoWMuIE5nb8OgaSByYSxjaMO6bmcgdGEgc+G6vSBraMOhbSBwaMOhIOG7qW5nIGThu6VuZyBUaWJibGUgdHJvbmcgeOG7rSBsw70sIHRydXkgduG6pW4gdsOgIGJp4bq/biDEkeG7lWkgZOG7ryBsaeG7h3UsIHThuqFvIGJp4buDdSDEkeG7ky4gxJDDoW5oIGdpw6EgxrB1IMSRaeG7g20sIGjhuqFuIGNo4bq/IHbDoCB0aeG7gW0gbsSDbmcgY+G7p2EgVGliYmxlIGPDuW5nIMSR4buBIHh14bqldCBoxrDhu5tuZyBwaMOhdCB0cmnhu4NuIHbDoCBuZ2hpw6puIGPhu6l1IHRp4bq/cCB0aGVvIGNobyBUaWJibGUuDQoNCiMjIDIuMiBM4bujaSDDrWNoIHbDoCB0aeG7gW0gbsSDbmcgY+G7p2EgcGFja2FnZSBUaWJibGUgdHJvbmcgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UNCg0KJmVuc3A7JmVuc3A7JmVuc3A7VGliYmxlIMSRZW0gbOG6oWkgbmhp4buBdSBs4bujaSDDrWNoIHbDoCB0aeG7gW0gbsSDbmcgcXVhbiB0cuG7jW5nIHRyb25nIHBow6JuIHTDrWNoIGThu68gbGnhu4d1Og0KDQotIExpbmggaG/huqF0IHbDoCB0aeG7h24gw61jaDogVGliYmxlIGN1bmcgY+G6pXAgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3UgbGluaCBob+G6oXQsIGdpw7pwIHjhu60gbMO9IGThu68gbGnhu4d1IGThu4UgZMOgbmcgdsOgIHRodeG6rW4gdGnhu4duIGjGoW4uIE7DsyBnacO6cCBnaeG6o20gdGjhu51pIGdpYW4gdsOgIGPDtG5nIHPhu6ljIHRyb25nIHF1w6EgdHLDrG5oIHBow6JuIHTDrWNoIGThu68gbGnhu4d1Lg0KLSBY4butIGzDvSBk4buvIGxp4buHdSB0aGnhur91IHbDoCBtZXRhZGF0YTogVGliYmxlIGN1bmcgY+G6pXAgY8O0bmcgY+G7pSBt4bqhbmggbeG6vSDEkeG7gyB44butIGzDvSBk4buvIGxp4buHdSB0aGnhur91IHbDoCBxdeG6o24gbMO9IG1ldGFkYXRhLiBOZ8aw4budaSBkw7luZyBjw7MgdGjhu4MgZOG7hSBkw6BuZyBsw6BtIHZp4buHYyB24bubaSBnacOhIHRy4buLIHRoaeG6v3UgdsOgIGfhuq9uIGvhur90IHRow7RuZyB0aW4gYuG7lSBzdW5nIHbDoG8gZOG7ryBsaeG7h3UsIHTEg25nIHTDrW5oIGxpbmggaG/huqF0IHbDoCBoaeG7g3UgYmnhur90IHbhu4EgZOG7ryBsaeG7h3UuDQotIFTGsMahbmcgdGjDrWNoIHbDoCB0w61jaCBo4bujcDogVGliYmxlIHTGsMahbmcgdGjDrWNoIGhvw6BuIHRvw6BuIHbhu5tpIGPDoWMgZ8OzaSBwaMOibiB0w61jaCBk4buvIGxp4buHdSBraMOhYyB0cm9uZyBSIG5oxrAgZHBseXIsIHRpZHlyIHbDoCBnZ3Bsb3QyLiDEkGnhu4F1IG7DoHkgZ2nDunAgbmfGsOG7nWkgZMO5bmcga+G6v3QgaOG7o3AgY8OhYyBjw7RuZyBj4bulIHBow6JuIHTDrWNoIG3hu5l0IGPDoWNoIGThu4UgZMOgbmcgdsOgIHThuq1uIGThu6VuZyB04buRaSDEkWEgdGnhu4FtIG7Eg25nIGPhu6dhIGjhu4cgc2luaCB0aMOhaSBSIMSR4buDIHBow6JuIHTDrWNoIGThu68gbGnhu4d1Lg0KLSBY4butIGzDvSBuaGFuaCBjaMOzbmcgdsOgIGxpbmggaG/huqF0OiBUaWJibGUgY2hvIHBow6lwIHjhu60gbMO9IHbDoCBiaeG6v24gxJHhu5VpIGThu68gbGnhu4d1IG5oYW5oIGNow7NuZyB2w6AgbGluaCBob+G6oXQuIEPDuiBwaMOhcCDEkcahbiBnaeG6o24gY+G7p2EgVGliYmxlIGdpw7pwIHRyw6FuaCByw6BuZyBideG7mWMgdsOgIGzhu5dpIHBo4buVIGJp4bq/biBraGkgbMOgbSB2aeG7h2MgduG7m2kgZGF0YSBmcmFtZSwgdMSDbmcgaGnhu4d1IHN14bqldCBwaMOibiB0w61jaC4NCi0gVOG6oW8gYmnhu4N1IMSR4buTIHbDoCBiw6FvIGPDoW8gY2jhuqV0IGzGsOG7o25nIGNhbzogVGliYmxlIGvhur90IGjhu6NwIHThu5F0IHbhu5tpIGfDs2kgZ2dwbG90MiDEkeG7gyB04bqhbyBiaeG7g3UgxJHhu5MgdsOgIGLDoW8gY8OhbyBjaOG6pXQgbMaw4bujbmcgY2FvLiBT4buxIGvhur90IGjhu6NwIG7DoHkgZ2nDunAgbmfGsOG7nWkgZMO5bmcgdHLhu7FjIHF1YW4gaMOzYSBk4buvIGxp4buHdSBk4buFIGTDoG5nIHbDoCBsaW5oIGhv4bqhdCwgdOG6oW8gcmEgYsOhbyBjw6FvIHRo4bqpbSBt4bu5IHbDoCB0aMO0bmcgdGluIHRy4buxYyBxdWFuLg0KDQpUw7NtIGzhuqFpLCBUaWJibGUgbWFuZyBs4bqhaSBs4bujaSDDrWNoIHbDoCB0aeG7gW0gbsSDbmcgcXVhbiB0cuG7jW5nIHRyb25nIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IG5o4budIHbDoG8gY+G6pXUgdHLDumMgbGluaCBob+G6oXQsIGto4bqjIG7Eg25nIHjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdsOgIHRow7RuZyB0aW4gbWV0YWRhdGEsIGto4bqjIG7Eg25nIHTDrWNoIGjhu6NwIG3GsOG7o3QgbcOgIHbhu5tpIGPDoWMgZ8OzaSBwaMOibiB0w61jaCBraMOhYywgY8O5bmcga2jhuqMgbsSDbmcgeOG7rSBsw70gZOG7ryBsaeG7h3UgbmhhbmggY2jDs25nIHbDoCBsaW5oIGhv4bqhdC4NCg0KDQojICoqQ2jGsMahbmcgMzogQ8OhYyB0w61uaCBuxINuZyBjaMOtbmggY+G7p2EgVGliYmxlKioNCg0KIyMgMy4xIEPhuqV1IHRyw7pjIGThu68gbGnhu4d1IGxpbmggaG/huqF0IHbDoCBuaOG7r25nIHRp4buHbiDDrWNoDQoNCiZlbnNwOyZlbnNwOyZlbnNwO1RpYmJsZSBjdW5nIGPhuqVwIG3hu5l0IGPhuqV1IHRyw7pjIGThu68gbGnhu4d1IGxpbmggaG/huqF0IHbDoCB0aeG7h24gw61jaCwgY2hvIHBow6lwIGzGsHUgdHLhu68gdsOgIGzDoG0gdmnhu4djIHbhu5tpIGThu68gbGnhu4d1IHRoZW8gZOG6oW5nIGLhuqNuZywgduG7m2kgY8OhYyBj4buZdCB2w6AgaMOgbmcgY8OzIHTDqm4uIETGsOG7m2kgxJHDonkgbMOgIG3hu5l0IHPhu5EgdMOtbmggbsSDbmcgY2jDrW5oIGPhu6dhIGPhuqV1IHRyw7pjIGThu68gbGnhu4d1IHRpYmJsZToNCg0KLSBMxrB1IHRy4buvIGThu68gbGnhu4d1IGTGsOG7m2kgZOG6oW5nIGLhuqNuZzogVGliYmxlIGNobyBwaMOpcCBsxrB1IHRy4buvIGThu68gbGnhu4d1IHRoZW8gZOG6oW5nIGLhuqNuZywgZ2nhu5FuZyBuaMawIG3hu5l0IGLhuqNuZyB0w61uaCBFeGNlbC4gTeG7l2kgY+G7mXQgxJHhuqFpIGRp4buHbiBjaG8gbeG7mXQgYmnhur9uIHbDoCBt4buXaSBow6BuZyDEkeG6oWkgZGnhu4duIGNobyBt4buZdCBxdWFuIHPDoXQuDQotIEPDoWMgY+G7mXQgdsOgIGjDoG5nIGPDsyB0w6puOiBN4buXaSBj4buZdCB2w6AgaMOgbmcgdHJvbmcgdGliYmxlIGPDsyB0w6puIHJpw6puZywgZ2nDunAgeMOhYyDEkeG7i25oIHbDoCB0cnV5IGPhuq1wIGThu68gbGnhu4d1IG3hu5l0IGPDoWNoIGThu4UgZMOgbmcuIFRhIGPDsyB0aOG7gyBz4butIGThu6VuZyB0w6puIGPhu5l0IMSR4buDIHRoYW0gY2hp4bq/dSB2w6AgdGhhbyB0w6FjIHbhu5tpIGThu68gbGnhu4d1IHRyb25nIHRpYmJsZS4NCi0gQ+G6pXUgdHLDumMgZOG7ryBsaeG7h3UgxJHhu5NuZyBuaOG6pXQ6IEPDoWMgY+G7mXQgdHJvbmcgdGliYmxlIHBo4bqjaSBjw7MgY8O5bmcgxJHhu5kgZMOgaSwgxJHhuqNtIGLhuqNvIHTDrW5oIMSR4buTbmcgbmjhuqV0IGPhu6dhIGPhuqV1IHRyw7pjIGThu68gbGnhu4d1LiDEkGnhu4F1IG7DoHkgZ2nDunAgdHLDoW5oIG5o4bqnbSBs4bqrbiB2w6AgeOG7rSBsw70gZOG7ryBsaeG7h3UgbeG7mXQgY8OhY2ggaGnhu4d1IHF14bqjLg0KLSBI4buXIHRy4bujIGThu68gbGnhu4d1IHRow7QgdsOgIGThuqFuZyB04buVbmcgaOG7o3A6IFRpYmJsZSBjw7MgdGjhu4MgbMawdSB0cuG7ryBk4buvIGxp4buHdSB0aMO0IHbDoCBk4bqhbmcgdOG7lW5nIGjhu6NwIG3hu5l0IGPDoWNoIGxpbmggaG/huqF0LiBUYSBjw7MgdGjhu4Mgc+G7rSBk4bulbmcgdGliYmxlIMSR4buDIGzGsHUgdHLhu68gZOG7ryBsaeG7h3UgY2hpIHRp4bq/dCB2w6AgdMOtbmggdG/DoW4gY8OhYyB0aOG7kW5nIGvDqiB04buVbmcgaOG7o3AgdHLDqm4gZOG7ryBsaeG7h3UgxJHDsy4NCkjhu5cgdHLhu6MgZOG7ryBsaeG7h3UgcGjDom4gbG/huqFpOiBUaWJibGUgY8OzIGto4bqjIG7Eg25nIGjhu5cgdHLhu6MgZOG7ryBsaeG7h3UgcGjDom4gbG/huqFpIChjYXRlZ29yaWNhbCBkYXRhKS4gVGEgY8OzIHRo4buDIHPhu60gZOG7pW5nIGPDoWMgaMOgbSB2w6AgZ8OzaSBt4bufIHLhu5luZyDEkeG7gyB44butIGzDvSB2w6AgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgcGjDom4gbG/huqFpIHRyb25nIHRpYmJsZS4NCi0gVMOtY2ggaOG7o3AgduG7m2kgY8OhYyBnw7NpIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IGtow6FjOiBUaWJibGUgdMOtY2ggaOG7o3AgdOG7kXQgduG7m2kgY8OhYyBnw7NpIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IHBo4buVIGJp4bq/biB0cm9uZyBSIG5oxrAgZHBseXIsIHRpZHlyLCBnZ3Bsb3QgdsOgIG5oaeG7gXUgZ8OzaSBraMOhYy4gxJBp4buBdSBuw6B5IG1hbmcgbOG6oWkga2jhuqMgbsSDbmcgbGluaCBob+G6oXQgdsOgIHRp4buHbiDDrWNoIHRyb25nIHZp4buHYyB0aOG7sWMgaGnhu4duIGPDoWMgcGjDom4gdMOtY2ggdsOgIHjhu60gbMO9IGThu68gbGnhu4d1Lg0KDQpWw60gZOG7pTogDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWJibGUpDQpsaWJyYXJ5KGRwbHlyKQ0KDQojIFThuqFvIG3hu5l0IHRpYmJsZSB24bubaSB0aMO0bmcgdGluIHbhu4Egc2luaCB2acOqbg0Kc2luaHZpZW4gPC0gdGliYmxlKGlkID0gYygxLCAyLCAzLCA0LCA1LCA2KSx0ZW4gPSBjKCJMaW5oIiwgIkxhbiIsICJMb25nIiwgIlBo4bulbmciLCAiUXV5IiwgIk5ndXnDqm4iKSx0dW9pID0gYygyMCwgMTksIDIxLCAyMCwgMjIsIDE4KSxtYWpvciA9IGMoIlTDoGkgY2jDrW5oIiwgIk1hcmtldGluZyIsICJL4bq/IHRvw6FuIiwgIk5nw7RuIG5n4buvIEFuaCIsICJRdeG6o24gdHLhu4sga2luaCBkb2FuaCIsICJUb8OhbiB0w6BpIGNow61uaCIpLGdwYSA9IGMoMy41LCAzLjIsIDMuOCwgMy42LCAzLjQsIDMuMikpDQoNCiMgVHJ1eSBj4bqtcCB2w6AgdGhhbyB0w6FjIGThu68gbGnhu4d1IGThu4UgZMOgbmcNCnRlbnNpbmh2aWVuIDwtIHNpbmh2aWVuJHRlbg0Kc2luaHZpZW5fYiA8LSBzaW5odmllbiAlPiVmaWx0ZXIodHVvaSA+PSAxOSkgJT4lIHNlbGVjdCh0ZW4sIG1ham9yKQ0KDQojIFTDrW5oIHRvw6FuIGPDoWMgdGjhu5FuZyBrw6ogdOG7lW5nIGjhu6NwDQp0aW5odG9hbl9ncGEgPC0gbWVhbihzaW5odmllbiRncGEpDQoNCiMgVGjDqm0gY+G7mXQgbeG7m2kgdsOgbyB0aWJibGUNCnRoZW1jb3QgPC0gc2luaHZpZW4gJT4lbXV0YXRlKGdyYWRlID0gaWZlbHNlKGdwYSA+PSAzLjUsICJBIiwiQiIpKQ0KDQpgYGANCg0KWGVtIGvhur90IHF14bqjDQoNCmBgYHtyfQ0KcHJpbnQodGVuc2luaHZpZW4pDQpwcmludChzaW5odmllbl9iKQ0KcHJpbnQodGluaHRvYW5fZ3BhKQ0KcHJpbnQodGhlbWNvdCkNCmBgYA0KDQoNCg0KIyMgMy4yIFjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdsOgIHjhu60gbMO9IG1ldGFkYXRhDQoNCiZlbnNwOyZlbnNwOyZlbnNwO1RpYmJsZSBjdW5nIGPhuqVwIHTDrW5oIG7Eg25nIHjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdsOgIHjhu60gbMO9IG1ldGFkYXRhIMSR4buDIGzDoG0gdmnhu4djIHbhu5tpIGThu68gbGnhu4d1IG3hu5l0IGPDoWNoIGxpbmggaG/huqF0IHbDoCBoaeG7h3UgcXXhuqMuIETGsOG7m2kgxJHDonkgbMOgIG3hu5l0IHPhu5EgdMOtbmggbsSDbmcgY2jDrW5oIHRyb25nIG3hu6VjIG7DoHk6DQoNCi0gWOG7rSBsw70gZOG7ryBsaeG7h3UgdGhp4bq/dTogVGliYmxlIGjhu5cgdHLhu6MgeOG7rSBsw70gZOG7ryBsaeG7h3UgdGhp4bq/dSwgZ2nDunAgY2jDum5nIHRhIGzDoG0gdmnhu4djIHbhu5tpIGPDoWMgZ2nDoSB0cuG7iyB0aGnhur91IHRyb25nIGThu68gbGnhu4d1LiBUYSBjw7MgdGjhu4Mgc+G7rSBk4bulbmcgY8OhYyBow6BtIG5oxrAgY29tcGxldGUoKSDEkeG7gyBob8OgbiB0aGnhu4duIGPDoWMgZ2nDoSB0cuG7iyB0aGnhur91IHRyb25nIHRpYmJsZSBi4bqxbmcgY8OhYyBnacOhIHRy4buLIG3hurdjIMSR4buLbmggaG/hurdjIGPDoWMgZ2nDoSB0cuG7iyB04burIGThu68gbGnhu4d1IGtow6FjLg0KLSBY4butIGzDvSBtZXRhZGF0YTogVGliYmxlIGtow7RuZyBo4buXIHRy4bujIHRy4buxYyB0aeG6v3Agdmnhu4djIHRow6ptIG1ldGFkYXRhIGNobyBj4buZdCBob+G6t2MgdOG6rXAgZOG7ryBsaeG7h3UuIFR1eSBuaGnDqm4sIHRhIGPDsyB0aOG7gyBz4butIGThu6VuZyBjw6FjIGfDs2kgbeG7nyBy4buZbmcgbmjGsCBkcGx5ciB2w6AgdGlkeXZlcnNlIMSR4buDIHRow6ptIG1ldGFkYXRhIHbDoG8gdGliYmxlIGLhurFuZyBjw6FjaCBz4butIGThu6VuZyBjw6FjIGjDoG0gbmjGsCBtdXRhdGUoKSB2w6AgYXR0cigpLiBWw60gZOG7pSx0YSBjw7MgdGjhu4Mgc+G7rSBk4bulbmcgbXV0YXRlKCkgxJHhu4MgdGjDqm0gdGjDtG5nIHRpbiBtw7QgdOG6oyBjaG8gY+G7mXQgdsOgIGF0dHIoKSDEkeG7gyBnw6FuIG5ow6NuIGNobyBj4buZdCB0cm9uZyB0aWJibGUuDQotIFjhu60gbMO9IGThu68gbGnhu4d1IHBow6JuIGxv4bqhaTogVGliYmxlIGjhu5cgdHLhu6MgeOG7rSBsw70gZOG7ryBsaeG7h3UgcGjDom4gbG/huqFpIChjYXRlZ29yaWNhbCBkYXRhKS4gVGEgY8OzIHRo4buDIHPhu60gZOG7pW5nIGPDoWMgaMOgbSB2w6AgZ8OzaSBt4bufIHLhu5luZyBuaMawIGZvcmNhdHMgxJHhu4MgY2h1eeG7g24gxJHhu5VpLCBz4bqvcCB44bq/cCB2w6AgeOG7rSBsw70gZOG7ryBsaeG7h3UgcGjDom4gbG/huqFpIHRyb25nIHRpYmJsZS4NCg0KVsOtIGThu6U6DQoNCmBgYHtyfQ0KbGlicmFyeSh0aWJibGUpDQojIFThuqFvIG3hu5l0IHRpYmJsZSB24bubaSB0aMO0bmcgdGluIHbhu4Egc2luaCB2acOqbg0Kc2luaHZpZW4gPC0gdGliYmxlKHRlbiA9IGMoIkjhuqNpIiwgIkxvbmciLCBOQSwgIlBo4bulbmciLCAiVsOibiIpLA0KICB0dW9pID0gYygyMSwgMjIsIDIwLCBOQSwxOSksbmdhbmggPSBjKCJUw6BpIGNow61uaCIsIE5BLCAiS+G6vyB0b8OhbiIsICJRdeG6o24gdHLhu4sga2luaCBkb2FuaCIsIk1hcmtldGluZyIpKQ0KDQojIEhp4buDbiB0aOG7iyB0aWJibGUNCnNpbmh2aWVuDQpgYGANCg0KWHXhuqV0IGhp4buHbiBjw6FjIHRow7RuZyB0aW4gYuG7iyB0aGnhur91IGvDvSBoaeG7h3UgTkEsdGEgeOG7rSBsw70gY8OhYyB0aMO0bmcgdGluIGLhu4sgdGhp4bq/dSBuw6B5IGLhurFuZyBs4buHbmggbmEub21pdCgpDQoNCmBgYHtyfQ0KIyBMb+G6oWkgYuG7jyBjw6FjIGjDoG5nIGNo4bupYSBnacOhIHRy4buLIHRoaeG6v3UNCnh1bHlkdWxpZXUgPC0gbmEub21pdChzaW5odmllbikNCiMgSGnhu4NuIHRo4buLIHRpYmJsZSDEkcOjIMSRxrDhu6NjIHjhu60gbMO9DQp4dWx5ZHVsaWV1DQoNCmBgYA0KDQpY4butIGzDvSBtZXRhZGF0YTogVGliYmxlIGNobyBwaMOpcCBsxrB1IHRy4buvIHRow7RuZyB0aW4gbWV0YWRhdGEgY8O5bmcgduG7m2kgZOG7ryBsaeG7h3UuIFRow7RuZyB0aW4gbWV0YWRhdGEga2jDtG5nIHRo4buDIGhp4buHbiB0cuG7sWMgdGnhur9wIG5naMSpYSBj4bunYSBk4buvIGxp4buHdSwgbcOgIHRoxrDhu51uZyBsw6AgY8OhYyB0aMO0bmcgdGluIGLhu5Ugc3VuZyB24buBIGPDoWMgdGh14buZYyB0w61uaCwgbmd14buTbiBn4buRYywgaG/hurdjIG5n4buvIGPhuqNuaCBj4bunYSBk4buvIGxp4buHdS4gxJBp4buBdSBuw6B5IGdpw7pwIGzDoG0gY2hvIGThu68gbGnhu4d1IHRy4bufIG7Dqm4gZOG7hSBoaeG7g3UgaMahbiB2w6AgdOG6oW8gxJFp4buBdSBraeG7h24gdGh14bqtbiBs4bujaSBjaG8gdmnhu4djIHjhu60gbMO9IHbDoCBwaMOibiB0w61jaCBk4buvIGxp4buHdSBzYXUgbsOgeS4NCg0KVsOtIGThu6U6IHRhIGPDsyB0aOG7gyB0aMOqbSBuaMOjbiB2w6AgY2jDuiB0aMOtY2ggY2hvIGPDoWMgY+G7mXQgdHJvbmcgdGliYmxlIMSR4buDIGdp4bqjaSB0aMOtY2ggw70gbmdoxKlhIGPhu6dhIGNow7puZy4gVHV5IG5oacOqbiwgdGjDtG5nIHRpbiBtZXRhZGF0YSBraMO0bmcg4bqjbmggaMaw4bufbmcgdHLhu7FjIHRp4bq/cCDEkeG6v24gdmnhu4djIHRo4buxYyBoaeG7h24gY8OhYyBwaMOpcCBiaeG6v24gxJHhu5VpIGThu68gbGnhu4d1IG5oxrAgbOG7jWMsIHPhuq9wIHjhur9wLCBoYXkgdOG7lW5nIGjhu6NwLiBUaGF5IHbDoG8gxJHDsywgY2jDum5nIGdpw7pwIHRhIGPDsyBjw6FpIG5ow6xuIHThu5VuZyBxdWFuIGjGoW4gduG7gSBk4buvIGxp4buHdSB2w6AgxJHhuqNtIGLhuqNvIHLhurFuZyBjaMO6bmcgdGEgaGnhu4N1IHLDtSBoxqFuIHbhu4Egbmfhu68gY+G6o25oIHbDoCDDvSBuZ2jEqWEgY+G7p2EgZOG7ryBsaeG7h3UgdHJvbmcgcXXDoSB0csOsbmggbMOgbSB2aeG7h2MgduG7m2kgbsOzLg0KDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWJibGUpDQpsaWJyYXJ5KGRwbHlyKQ0KIyBU4bqhbyBt4buZdCB0aWJibGUgduG7m2kgdGjDtG5nIHRpbiB24buBIHPhuqNuIHBo4bqpbQ0Kc2FucGhhbSA8LSB0aWJibGUoaWQgPSBjKDEsIDIsIDMpLHRlbnNhbnBoYW0gPSBjKCLDgW8iLCAiUXXhuqduIiwgIkdpw6B5IiksDQogIGdpYV9iYW4gPSBjKDI5Ljk5LCA0OS45OSwgNzkuOTkpKSAlPiUgbXV0YXRlKG1pZXVfdGEgPSAiVGjDtG5nIHRpbiB24buBIGPDoWMgc+G6o24gcGjhuqltIiwNCiAgICBsYWJlbF9pZCA9ICJNw6Mgc+G6o24gcGjhuqltIiwNCiAgICBsYWJlbF9uYW1lID0gIlTDqm4gc+G6o24gcGjhuqltIiwNCiAgICBsYWJlbF9wcmljZSA9ICJHacOhIHPhuqNuIHBo4bqpbSIpDQoNCiMgSGnhu4NuIHRo4buLIHRpYmJsZQ0Kc2FucGhhbQ0KDQpgYGANCg0KDQojIyAzLjMgVMawxqFuZyB0aMOtY2ggdsOgIHTDrWNoIGjhu6NwIHbhu5tpIGPDoWMgZ8OzaSBwaMOibiB0w61jaCBk4buvIGxp4buHdSBraMOhYyB0cm9uZyBSDQoNCiZlbnNwOyZlbnNwOyZlbnNwO1RpYmJsZSB0xrDGoW5nIHRow61jaCB2w6AgdMOtY2ggaOG7o3AgdOG7kXQgduG7m2kgY8OhYyBnw7NpIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IGtow6FjIHRyb25nIFIsIGdpw7pwIGNow7puZyB0YSB0aOG7sWMgaGnhu4duIGPDoWMgcGjDom4gdMOtY2ggdsOgIHjhu60gbMO9IGThu68gbGnhu4d1IG3hu5l0IGPDoWNoIGxpbmggaG/huqF0IHbDoCBoaeG7h3UgcXXhuqMuIETGsOG7m2kgxJHDonkgbMOgIG3hu5l0IHPhu5EgdsOtIGThu6UgduG7gSB2aeG7h2MgdMOtY2ggaOG7o3AgdGliYmxlIHbhu5tpIGPDoWMgZ8OzaSBwaMOibiB0w61jaCBk4buvIGxp4buHdSBwaOG7lSBiaeG6v246DQoNCi0gVMOtY2ggaOG7o3AgduG7m2kgZHBseXI6IFRpYmJsZSBob+G6oXQgxJHhu5luZyB04buRdCB24bubaSBnw7NpIGRwbHlyLCBjdW5nIGPhuqVwIGPDoWMgaMOgbSBt4bqhbmggbeG6vSDEkeG7gyB0aOG7sWMgaGnhu4duIGPDoWMgcGjDqXAgYmnhur9uIMSR4buVaSBk4buvIGxp4buHdSBuaMawIGzhu41jIChmaWx0ZXIpLCBz4bqvcCB44bq/cCAoYXJyYW5nZSksIG5ow7NtIChncm91cF9ieSkgdsOgIHThu5VuZyBo4bujcCAoc3VtbWFyaXNlKS4gQ2jDum5nIHRhIGPDsyB0aOG7gyBz4butIGThu6VuZyBjw6FjIGjDoG0gZHBseXIgdHLhu7FjIHRp4bq/cCB0csOqbiB0aWJibGUgxJHhu4MgeOG7rSBsw70gZOG7ryBsaeG7h3UgbeG7mXQgY8OhY2ggZOG7hSBkw6BuZyB2w6AgbGluaCBob+G6oXQuDQotIFTDrWNoIGjhu6NwIHbhu5tpIHRpZHlyOiBUaWJibGUgY8WpbmcgdMOtY2ggaOG7o3AgdOG7kXQgduG7m2kgZ8OzaSB0aWR5ciwgY2hvIHBow6lwIHRhIHRo4buxYyBoaeG7h24gY8OhYyBwaMOpcCBiaeG6v24gxJHhu5VpIGThu68gbGnhu4d1IMSR4buDIGzDoG0gc+G6oWNoIHbDoCBjaHXhuqluIGjDs2EgZOG7ryBsaeG7h3UuIELhurFuZyBjw6FjaCBz4butIGThu6VuZyBjw6FjIGjDoG0gdGlkeXIgbmjGsCBnYXRoZXIgdsOgIHNwcmVhZCwgdGEgY8OzIHRo4buDIGNodXnhu4NuIMSR4buVaSBk4buvIGxp4buHdSBnaeG7r2EgxJHhu4tuaCBk4bqhbmcgcuG7mW5nICh3aWRlKSB2w6AgxJHhu4tuaCBk4bqhbmcgZMOgaSAobG9uZyksIHRodeG6rW4gdGnhu4duIGNobyB2aeG7h2MgcGjDom4gdMOtY2ggdsOgIHRy4buxYyBxdWFuIGjDs2EgZOG7ryBsaeG7h3UuDQotIFTDrWNoIGjhu6NwIHbhu5tpIGdncGxvdDogVGliYmxlIGPDsyB0w61jaCBo4bujcCB04buRdCB24bubaSBnw7NpIGdncGxvdCwgZ8OzaSDEkeG7kyB0aOG7iyBwaOG7lSBiaeG6v24gdHJvbmcgUi4gVGEgY8OzIHRo4buDIHPhu60gZOG7pW5nIHRpYmJsZSDEkeG7gyBjaHXhuqluIGLhu4sgZOG7ryBsaeG7h3UgdsOgIHNhdSDEkcOzIHRy4buxYyB0aeG6v3Agc+G7rSBk4bulbmcgZ2dwbG90IMSR4buDIHThuqFvIGPDoWMgYmnhu4N1IMSR4buTIHbDoCDEkeG7kyB0aOG7iyB0cuG7sWMgcXVhbi4NCi0gVMOtY2ggaOG7o3AgduG7m2kgY8OhYyBnw7NpIHBow6JuIHTDrWNoIHRo4buRbmcga8OqIGtow6FjOiBUaWJibGUgdMawxqFuZyB0aMOtY2ggduG7m2kgY8OhYyBnw7NpIHBow6JuIHTDrWNoIHRo4buRbmcga8OqIGtow6FjIG5oxrAgc3RhdHMsIE1BU1MsIGxtZTQsIHbDoCBuaGnhu4F1IGfDs2kga2jDoWMuIENow7puZyB0YSBjw7MgdGjhu4Mgc+G7rSBk4bulbmcgdGliYmxlIGzDoG0gxJHhuqd1IHbDoG8gY2hvIGPDoWMgcGjDom4gdMOtY2ggdGjhu5FuZyBrw6osIGtp4buDbSDEkeG7i25oIGdp4bqjIHRodXnhur90LCBo4buTaSBxdXksIHBow6JuIHTDrWNoIHBoxrDGoW5nIHNhaSB2w6Agbmhp4buBdSBwaMawxqFuZyBwaMOhcCBraMOhYyB0cm9uZyBSLg0KDQpWw60gZOG7pToNCg0KYGBge3J9DQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkoZHBseXIpDQojIFThuqFvIG3hu5l0IHRpYmJsZSB24bubaSB0aMO0bmcgdGluIHbhu4Egc+G6o24gcGjhuqltIHbDoCBz4buRIGzGsOG7o25nIGLDoW4gaMOgbmcNCnNhbnBoYW0gPC0gdGliYmxlKA0KICBpZCA9IGMoMSwgMiwgMywgNCwgNSksDQogIHRlbiA9IGMoIsOBbyIsICJRdeG6p24iLCAiR2nDoHkiLCAiw4FvIiwgIlF14bqnbiIpLA0KICBnaWEgPSBjKDI5Ljk5LCA0OS45OSwgNzkuOTksIDI5Ljk5LCA0OS45OSksDQogIHNvbHVvbmcgPSBjKDEwLCA1LCAzLCA4LCA2KSkNCiMgVMOtbmggdOG7lW5nIGRvYW5oIHRodSB0aGVvIHPhuqNuIHBo4bqpbQ0KZG9hbmh0aHUgPC0gc2FucGhhbSAlPiUNCiAgZ3JvdXBfYnkodGVuKSAlPiUNCiAgc3VtbWFyaXNlKHRvbmdkb2FuaHRodSA9IHN1bShnaWEgKiBzb2x1b25nKSkNCiMgSGnhu4NuIHRo4buLIGvhur90IHF14bqjDQpkb2FuaHRodQ0KYGBgDQoNCiMgKipDaMawxqFuZyA0OiDhu6huZyBk4bulbmcgY+G7p2EgcGFja2FnZSBUaWJibGUgdHJvbmcgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UqKg0KDQojIyA0LjEgVOG6oW8gVGliYmxlIHbDoCBjaHV54buDbiDEkeG7lWkgZOG7ryBsaeG7h3UNCg0KJmVuc3A7JmVuc3A7JmVuc3A7VHJvbmcgcGjhuqduIG7DoHksIGNow7puZyB0YSBz4bq9IHTDrG0gaGnhu4N1IHbhu4EgY8OhY2ggdOG6oW8gdGliYmxlIGLhurFuZyBjw6FjaCBz4butIGThu6VuZyBjw6FjIGjDoG0gbmjGsCBhc190aWJibGUoKSwgdGliYmxlKCksIHbDoCB0cmliYmxlKCkuIENow7puZyB0YSBz4bq9IGdp4bubaSB0aGnhu4d1IGPDoWNoIHThuqFvIHRpYmJsZSB04burIGPDoWMgxJHhu5FpIHTGsOG7o25nIGPDsyBz4bq1biBuaMawIGRhdGEuZnJhbWUsIGxpc3QsIG1hdHJpeCBob+G6t2MgdGFibGUsIHbDoCBjdW5nIGPhuqVwIGPDoWMgdsOtIGThu6UgY+G7pSB0aOG7gyDEkeG7gyBtaW5oIGjhu41hIHF1w6EgdHLDrG5oIGNodXnhu4NuIMSR4buVaSBk4buvIGxp4buHdS4NCg0KKipHaeG7m2kgdGhp4buHdSB24buBIGPDoWMgaMOgbSB04bqhbyB0aWJibGUqKg0KDQotIEjDoG0gYXNfdGliYmxlKCk6IMSQw6J5IGzDoCBt4buZdCBow6BtIGNodXnhu4NuIMSR4buVaSBsaW5oIGhv4bqhdCBjaG8gcGjDqXAgY2jDum5nIHRhIGNodXnhu4NuIMSR4buVaSBjw6FjIMSR4buRaSB0xrDhu6NuZyDEkcOjIHThu5NuIHThuqFpIG5oxrAgZGF0YS5mcmFtZSwgbGlzdCwgbWF0cml4IGhv4bq3YyB0YWJsZSB0aMOgbmggdGliYmxlLiBIw6BtIG7DoHkgc+G6vSBnaeG7ryBuZ3V5w6puIGPhuqV1IHRyw7pjIHbDoCBraeG7g3UgZOG7ryBsaeG7h3UgY+G7p2EgxJHhu5FpIHTGsOG7o25nIGfhu5FjIHbDoCB0cuG6oyB24buBIG3hu5l0IHRpYmJsZSB0xrDGoW5nIHThu7EuDQotIEjDoG0gdGliYmxlKCk6IEjDoG0gbsOgeSBjaG8gcGjDqXAgdGEgdOG6oW8gbeG7mXQgdGliYmxlIG3hu5tpIHThu6sgY8OhYyB2ZWN0b3IgY+G7mXQgY8OzIHPhurVuLiDEkGnhu4NtIMSR4bq3YyBiaeG7h3QgY+G7p2EgaMOgbSBuw6B5IGzDoCBuw7Mga2jDtG5nIHRoYXkgxJHhu5VpIGtp4buDdSBk4buvIGxp4buHdSBj4bunYSBjw6FjIHZlY3Rvciwga2jDtG5nIGNodXnhu4NuIMSR4buVaSBjaHXhu5dpIHRow6BuaCBmYWN0b3IsIHbDoCBraMO0bmcgdOG6oW8gcmEgcm93Lm5hbWVzLiDEkGnhu4F1IG7DoHkgZ2nDunAgYuG6o28gxJHhuqNtIHTDrW5oIG5o4bqldCBxdcOhbiB2w6AgZ2nhu68gbmd1ecOqbiBj4bqldSB0csO6YyBk4buvIGxp4buHdSBraGkgdOG6oW8gdGliYmxlIG3hu5tpLg0KLSBIw6BtIHRyaWJibGUoKTogSMOgbSBuw6B5IGNobyBwaMOpcCBjaMO6bmcgdGEgxJHhu4tuaCBuZ2jEqWEgdGliYmxlIGThu4UgZMOgbmcgdGhlbyBow6BuZy4gTsOzIGNobyBwaMOpcCB0YSB04bqhbyBt4buZdCB0aWJibGUgdOG7qyBjw6FjIGdpw6EgdHLhu4sgY+G7mXQgdsOgIGNow7puZyB0YSBjw7MgdGjhu4MgxJHhu4tuaCBuZ2jEqWEgY8OhYyBnacOhIHRy4buLIGTGsOG7m2kgZOG6oW5nIGPDoWMgZMOybmcgcmnDqm5nIGJp4buHdC4NCg0KVsOtIGThu6UgOiBT4butIGThu6VuZyBhc190aWJibGUoKSDEkeG7gyDEkeG7jWMgZOG7ryBsaeG7h3UgdOG7qyBmaWxlIC54bHN4IHbDoCBjaHV54buDbiDEkeG7lWkgdGjDoG5oIHRpYmJsZToNCg0KYGBge3J9DQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkocmVhZHhsKQ0KIyDEkOG7jWMgZOG7ryBsaeG7h3UgdOG7qyBmaWxlIC54bHN4ICh2w60gZOG7pTogInMmcDUwMF9kYXRhLnhsc3giKQ0KZGF0YV9kZiA8LSByZWFkX3hsc3goIkQ6L25ubHQvc3RvY2sueGxzeCIpDQoNCiMgQ2h1eeG7g24gxJHhu5VpIHRow6BuaCB0aWJibGUNCmRhdGFfdGliYmxlIDwtIGFzX3RpYmJsZShkYXRhX2RmKQ0KDQojIEhp4buDbiB0aOG7iyB0aWJibGUNCnByaW50KGRhdGFfdGliYmxlKQ0KDQpgYGANCg0KVsOtIGThu6UgOiBT4butIGThu6VuZyB0aWJibGUoKSDEkeG7gyB04bqhbyB0aWJibGUgdOG7qyBjw6FjIHZlY3RvciBj4buZdCByacOqbmcgbOG6uw0KDQpgYGB7cn0NCiMgxJDhu41jIGThu68gbGnhu4d1IHThu6sgZmlsZSAueGxzeCAodsOtIGThu6U6ICJzdG9jay54bHN4IikNCmRhdGFfZGYgPC0gcmVhZF94bHN4KCJEOi9ubmx0L3N0b2NrLnhsc3giKQ0KDQojIFThuqFvIHRpYmJsZSB04burIGPDoWMgdmVjdG9yIGPhu5l0IHJpw6puZyBs4bq7DQpkYXRlIDwtIGRhdGFfZGYkZGF0ZQ0KY2xvc2UgPC0gZGF0YV9kZiRjbG9zZQ0Kdm9sdW1lIDwtIGRhdGFfZGYkdm9sdW1lDQoNCnN0b2NrX2EgPC0gdGliYmxlKERhdGUgPSBkYXRlLCBDbG9zZSA9IGNsb3NlLCBWb2x1bWUgPSB2b2x1bWUpDQoNCiMgSGnhu4NuIHRo4buLIHRpYmJsZQ0KcHJpbnQoc3RvY2tfYSkNCg0KYGBgDQoNClbDrSBk4bulOiBT4butIGThu6VuZyB0cmliYmxlKCkgxJHhu4MgdOG6oW8gdGliYmxlIHThu6sgY8OhYyBnacOhIHRy4buLIGTGsOG7m2kgZOG6oW5nIGjDoG5nDQoNCkdp4bqjIHPhu60gdGEgY8OzIGLhuqNuZyBk4buvIGxp4buHdSBzYXU6DQoNCiQkDQpcYmVnaW57YXJyYXl9e3xsfGx8bHxsfH0NClxobGluZSBcdGV4dCB7IFTDqm4gfSAmIFx0ZXh0IHsgS2luaCB04bq/IGzGsOG7o25nIH0gJiBcdGV4dCB7IE3DtCBwaOG7j25nIG5n4bqrdSBuaGnDqm4gfSAmIFx0ZXh0IHsgVG/DoW4ga2luaCB04bq/IH0gXFwNClxobGluZSDDgW5oIExpbmggJiA4LjUgJiA4Ljc1ICYgNy41IFxcDQpcaGxpbmUgSOG6o2kgUGjhu6VuZyAmIDkuMCAmIDcuNSAmIDguNSBcXA0KXGhsaW5lIFRoYW5oIEh14buHICYgNy43NSAmIDcuNSYgNy4wXFwNClxobGluZSBEdXkgUXVhbmcgJiA4LjAgJjcuNSAmIDcuMCBcXA0KXGhsaW5lDQpcZW5ke2FycmF5fQ0KJCQNCkLDonkgZ2nhu50sIGjDo3kgc+G7rSBk4bulbmcgaMOgbSB0cmliYmxlKCkgxJHhu4MgdOG6oW8gdGliYmxlIHThu6sgZOG7ryBsaeG7h3UgbsOgeToNCg0KYGBge3J9DQpsaWJyYXJ5KHRpYmJsZSkNCiMgU+G7rSBk4bulbmcgaMOgbSB0cmliYmxlKCkgxJHhu4MgdOG6oW8gdGliYmxlIHThu6sgZOG7ryBsaeG7h3UNCmRhdGFfdGliYmxlIDwtIHRyaWJibGUoDQogIH5UZW4sIH5LaW5oX3RlX2x1b25nLCB+TW9fcGhvbmdfbm4sIH5Ub2FuX2tpbmhfdGUsDQogICLDgW5oIExpbmgiLCA4LjUsIDguNzUsIDcuNSwNCiAgIkjhuqNpIFBo4bulbmciLCA5LjAsIDcuNSwgOC41LA0KICAiVGhhbmggSHXhu4ciLCA3Ljc1LCA3LjUsIDcuMCwNCiAgIkR1eSBRdWFuZyIsIDguMCwgNy41LCA3LjApDQoNCiMgSGnhu4NuIHRo4buLIHRpYmJsZQ0KcHJpbnQoZGF0YV90aWJibGUpDQoNCmBgYA0KDQomZW5zcDsmZW5zcDsmZW5zcDtIw6BtIHRyaWJibGUoKSB0aMaw4budbmcgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgbmhhbmggY2jDs25nIHThuqFvIHRpYmJsZSB04burIGPDoWMgZMOybmcgZOG7ryBsaeG7h3Ugbmjhu48gdsOgIMSRxqFuIGdp4bqjbiBtw6Aga2jDtG5nIGPhuqduIHBo4bqjaSB04bqhbyBt4buZdCBmaWxlIGThu68gbGnhu4d1IHJpw6puZyBiaeG7h3QuIMSQaeG7gXUgbsOgeSBo4buvdSDDrWNoIGtoaSBjaMO6bmcgdGEgbXXhu5FuIGtp4buDbSB0cmEgbmhhbmggY8OhYyBow6BtIHbDoCB44butIGzDvSBk4buvIGxp4buHdSBuaOG7jyBtw6Aga2jDtG5nIGPhuqduIHThuqFvIG3hu5l0IGZpbGUgZOG7ryBsaeG7h3UgbMawdSB0cuG7ry4NCg0KJmVuc3A7JmVuc3A7JmVuc3A7VHV5IG5oacOqbiwgdHJvbmcgdGjhu7FjIHThur8sIGtoaSB0YSBjw7MgZOG7ryBsaeG7h3UgbOG7m24gdsOgIHBo4bupYyB04bqhcCBoxqFuLCB0aMOsIHZp4buHYyBuaOG6rXAgZOG7ryBsaeG7h3UgdHLhu7FjIHRp4bq/cCB2w6BvIG3DoyBSIG5oxrAgduG6rXkgc+G6vSBraMO0bmcgaGnhu4d1IHF14bqjIHbDoCBraMO0bmcga2jhuqMgdGhpLiBUcm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSwgY2jDum5nIHRhIHPhur0gxJHhu41jIGThu68gbGnhu4d1IHThu6sgY8OhYyBmaWxlIGzGsHUgdHLhu68gZOG7ryBsaeG7h3UgKHbDrSBk4bulOiBDU1YsIEV4Y2VsLCBTUUwsIHYudi4pIGLhurFuZyBjw6FjIGjDoG0gxJHhu41jIGThu68gbGnhu4d1IG5oxrAgcmVhZC5jc3YoKSwgcmVhZF9leGNlbCgpLCByZWFkcjo6cmVhZF9kZWxpbSgpLCByZWFkcjo6cmVhZF90c3YoKS4uLi4NCg0KDQojIyA0LjIgQ8OhYyB0aGFvIHTDoWMgROG7ryBsaeG7h3UgduG7m2kgVGliYmxlDQoNCiZlbnNwOyZlbnNwOyZlbnNwO1Ryb25nIG3hu6VjIG7DoHksIGNow7puZyB0YSBz4bq9IHTDrG0gaGnhu4N1IGPDoWNoIHPhu60gZOG7pW5nIGPDoWMgaMOgbSBhZGRfY29sdW1uKCkgdsOgIGFkZF9yb3coKSDEkeG7gyB0aMOqbSBj4buZdCB2w6AgaMOgbmcgdsOgbyBt4buZdCB0aWJibGUsIGPFqW5nIG5oxrAgaMaw4bubbmcgZOG6q24gduG7gSB2aeG7h2Mgc+G7rSBk4bulbmcgZW5mcmFtZSgpIMSR4buDIGNodXnhu4NuIMSR4buVaSBjw6FjIHZlY3RvciB0aMOgbmggZGF0YS5mcmFtZSB2w6AgbmfGsOG7o2MgbOG6oWkuIFNhdSDEkcOzLCBjaMO6bmcgdGEgc+G6vSBjdW5nIGPhuqVwIGPDoWMgdsOtIGThu6UgbWluaCBo4buNYSB24buBIGPDoWMgdGhhbyB0w6FjIGNo4buNbiBs4buNYyBk4buvIGxp4buHdSB0csOqbiB0aWJibGUgYuG6sW5nIGPDoWNoIHPhu60gZOG7pW5nIGPDoWMgaMOgbSB0xrDGoW5nIOG7qW5nLg0KDQojIyMgNC4yLjEuIFRow6ptIGPhu5l0IHbDoCBow6BuZyB2w6BvIG3hu5l0IHRpYmJsZQ0KDQomZW5zcDsmZW5zcDsmZW5zcDtT4butIGThu6VuZyBhZGRfY29sdW1uKCkgxJHhu4MgdGjDqm0gY+G7mXQgdsOgbyB0aWJibGU6DQpIw6BtIGFkZF9jb2x1bW4oKSBjaG8gcGjDqXAgYuG6oW4gdGjDqm0gbeG7mXQgY+G7mXQgbeG7m2kgdsOgbyB0aWJibGUgYuG6sW5nIGPDoWNoIGNo4buJIMSR4buLbmggdMOqbiBj4buZdCB2w6AgZ2nDoSB0cuG7iyBj4bunYSBj4buZdCBt4bubaS4NCg0KYGBge3J9DQojIFRow6ptIGPhu5l0ICJUcnVuZyBiw6xuaCIgdsOgbyB0aWJibGUNCnRydW5nYmluaCA8LSBhZGRfY29sdW1uKGRhdGFfdGliYmxlLCB0cnVuZ19iaW5oID0gKGRhdGFfdGliYmxlJEtpbmhfdGVfbHVvbmcgKyBkYXRhX3RpYmJsZSRNb19waG9uZ19ubiArIGRhdGFfdGliYmxlJFRvYW5fa2luaF90ZSkgLyAzKQ0KIyBIaeG7g24gdGjhu4sgdGliYmxlIHNhdSBraGkgdGjDqm0gY+G7mXQNCnByaW50KHRydW5nYmluaCkNCmBgYA0KDQoNClRp4bq/cCB0aGVvLCBjaMO6bmcgdGEgc+G6vSBz4butIGThu6VuZyBow6BtIGFkZF9yb3coKSDEkeG7gyB0aMOqbSBt4buZdCBow6BuZyBt4bubaSB2w6BvIHRpYmJsZSB24bubaSB0aMO0bmcgdGluIGPhu6dhIG3hu5l0IG5nxrDhu51pIG3hu5tpLg0KDQpgYGB7cn0NCiMgVOG6oW8gZMOybmcgbeG7m2kgduG7m2kgdMOqbiBj4buZdCBsw6AgY8OhYyBzeW1ib2wNCm5ld19yb3cgPC0gbGlzdChUZW4gPSAiSG/DoG5nIE5ndXnDqm4iLCBLaW5oX3RlX2x1b25nID0gOC4yNSwgTW9fcGhvbmdfbm4gPSA4LjAsIFRvYW5fa2luaF90ZSA9IDcuNzUpDQoNCiMgVGjDqm0gZMOybmcgbeG7m2kgdsOgbyB0aWJibGUgYuG6sW5nIGjDoG0gYWRkX3JvdygpDQpuZXdfcm93cyA8LSBhZGRfcm93KGRhdGFfdGliYmxlLCAhISFuZXdfcm93KQ0KDQojIEhp4buDbiB0aOG7iyB0aWJibGUgc2F1IGtoaSB0aMOqbSBkw7JuZyBt4bubaQ0KcHJpbnQobmV3X3Jvd3MpDQpgYGANCg0KDQojIyMgNC4yLjIgQ2h1eeG7g24gxJHhu5VpIHZlY3RvciB0aMOgbmggZGF0YS5mcmFtZSB2w6AgbmfGsOG7o2MgbOG6oWkNCg0KJmVuc3A7JmVuc3A7JmVuc3A7U+G7rSBk4bulbmcgZW5mcmFtZSgpIMSR4buDIGNodXnhu4NuIMSR4buVaSB2ZWN0b3IgdGjDoG5oIGRhdGEgZnJhbWU6DQpIw6BtIGVuZnJhbWUoKSBjaG8gcGjDqXAgdGEgY2h1eeG7g24gxJHhu5VpIG3hu5l0IHZlY3RvciB0aMOgbmggbeG7mXQgZGF0YSBmcmFtZSBjw7MgaGFpIGPhu5l0OiBj4buZdCB0w6puIHbDoCBj4buZdCBnacOhIHRy4buLLg0KDQpWw60gZOG7pTogdOG7qyBmaWxlIHN0b2NrLnhsc3gsdGEgc+G6vSBz4butIGThu6VuZyBow6BtIGVuZnJhbWUoKSDEkeG7gyBjaHV54buDbiDEkeG7lWkgY+G7mXQgImNsb3NlIiB0aMOgbmggbeG7mXQgZGF0YSBmcmFtZSBjw7MgaGFpIGPhu5l0OiBj4buZdCAibmFtZSIgdsOgIGPhu5l0ICJ2YWx1ZSIuDQoNCmBgYHtyfQ0KIyBDaHV54buDbiDEkeG7lWkgY+G7mXQgImNsb3NlIiB0aMOgbmggZGF0YSBmcmFtZQ0KY2xvc2VfZGYgPC0gZW5mcmFtZShzdG9ja19hJENsb3NlKQ0KIyBIaeG7g24gdGjhu4sgZGF0YSBmcmFtZSBt4bubaQ0KcHJpbnQoY2xvc2VfZGYpDQoNCmBgYA0KDQpUaeG6v3AgdGhlbywgY2jDum5nIHRhIHPhur0gdGjhu7FjIGhp4buHbiB2w60gZOG7pSB24buBIGNodXnhu4NuIMSR4buVaSBkYXRhIGZyYW1lIHRow6BuaCB2ZWN0b3Igc+G7rSBk4bulbmcgaMOgbSBkZWZyYW1lKCkNCg0KYGBge3J9DQojIENodXnhu4NuIMSR4buVaSBkYXRhIGZyYW1lIHRow6BuaCB2ZWN0b3INCmNsb3NlX3ZlY3RvciA8LSBkZWZyYW1lKGNsb3NlX2RmKQ0KIyBIaeG7g24gdGjhu4sgdmVjdG9yIG3hu5tpDQpwcmludChjbG9zZV92ZWN0b3IpDQpgYGANCg0KIyMjIDQuMi4zIFThuqFvIG3hu5l0IMSR4buRaSB0xrDhu6NuZyB0aWJibGUgbeG7m2kgaG/hurdjIGtp4buDbSB0cmEgdMOtbmggaOG7o3AgbOG7hyBj4bunYSBt4buZdCDEkeG7kWkgdMaw4bujbmcgdGliYmxlIGhp4buHbiBjw7MNCg0KJmVuc3A7JmVuc3A7JmVuc3A7SMOgbSBuZXdfdGliYmxlKCkgdHJvbmcgZ8OzaSB0aWJibGUgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgdOG6oW8gaG/hurdjIHjDoWMgdGjhu7FjIG3hu5l0IGzhu5twIGNvbiBj4bunYSB0aWJibGUuIMSQw6J5IGzDoCBow6BtIGjhu691IMOtY2ggxJHhurdjIGJp4buHdCBjaG8gY8OhYyB0w6FjIGdp4bqjIGfDs2kgZOG7sSDDoW4gdGjhu7FjIGhp4buHbiBs4bubcCBjb24gY+G7p2EgdGliYmxlLCBjaOG6s25nIGjhuqFuIG5oxrAgc2YgaGF5IHRzaWJibGUuDQoNCi0gbmV3X3RpYmJsZSgpOiBU4bqhbyBt4buZdCDEkeG7kWkgdMaw4bujbmcgbeG7m2kgbMOgIG3hu5l0IGzhu5twIGNvbiBj4bunYSB0YmxfZGYsIHRibCB2w6AgZGF0YS5mcmFtZS4gSMOgbSBuw6B5IMSRxrDhu6NjIHThu5FpIMawdSBow7NhIGNobyBoaeG7h3Ugc3XhuqV0LCBz4buRIGzGsOG7o25nIGtp4buDbSB0cmEgxJHGsOG7o2MgZ2nhuqNtIHh14buRbmcgdOG7kWkgdGhp4buDdS4gWGVtIHZjdHJzOjpuZXdfZGF0YV9mcmFtZSgpIMSR4buDIGJp4bq/dCB0aMOqbSBjaGkgdGnhur90Lg0KLSB2YWxpZGF0ZV90aWJibGUoKTogS2nhu4NtIHRyYSB0w61uaCBuaOG6pXQgcXXDoW4gYsOqbiB0cm9uZyBj4bunYSBt4buZdCB0aWJibGUuIEjDoG5oIHZpIMSRw7puZyDEkeG6r24gY2jhu4kgxJHhuqNtIGLhuqNvIG7hur91IGjDoG0gbsOgeSBjaOG6oXkgbcOgIGtow7RuZyBnw6J5IHJhIGzhu5dpLg0KDQpWw60gZOG7pSA6DQoNCmBgYHtyfQ0KIyBT4butIGThu6VuZyBow6BtIG5ld190aWJibGUoKSDEkeG7gyB04bqhbyB0aWJibGUgbeG7m2kgdOG7qyB0aWJibGUgaGnhu4duIGPDsw0KbmV3X2RhdGFfdGliYmxlIDwtIG5ld190aWJibGUoZGF0YV90aWJibGUpDQojIFPhu60gZOG7pW5nIGjDoG0gdmFsaWRhdGVfdGliYmxlKCkgxJHhu4Mga2nhu4NtIHRyYSB0w61uaCBo4bujcCBs4buHIGPhu6dhIHRpYmJsZQ0KdmFsaWRhdGVfdGliYmxlKG5ld19kYXRhX3RpYmJsZSkNCmBgYA0KDQojIyMgNC4yLjQgVOG6oW8gbWEgdHLhuq1uIGThu68gbGnhu4d1IHRoZW8gaMaw4bubbmcgZOG7ryBsaeG7h3UgaMOgbmcgKHJvdy13aXNlKQ0KDQotIEjDoG0gZnJhbWVfbWF0cml4KCkgdHJvbmcgZ8OzaSB0aWJibGUgZMO5bmcgxJHhu4MgdOG6oW8gbWEgdHLhuq1uIGThu68gbGnhu4d1IHRoZW8gaMaw4bubbmcgZOG7ryBsaeG7h3UgaMOgbmcgKHJvdy13aXNlKS4gxJBp4buDbSBu4buVaSBi4bqtdCBj4bunYSBow6BtIG7DoHkgbMOgIGPDuiBwaMOhcCBn4buNbiBnw6BuZyB2w6AgZOG7hSDEkeG7jWMsIGdp4buRbmcgbmjGsCBow6BtIHRyaWJibGUoKS4NCi0gSMOgbSBmcmFtZV9tYXRyaXgoKSDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyB04bqhbyBtYSB0cuG6rW4gZOG7ryBsaeG7h3UgYuG6sW5nIGPDoWNoIGN1bmcgY+G6pXAgY8OhYyBnacOhIHRy4buLIGNobyB04burbmcgY+G7mXQgdHJvbmcgbeG7l2kgaMOgbmcgY+G7p2EgbWEgdHLhuq1uLg0KLSBDw7ogcGjDoXAgY+G7p2EgaMOgbSBsw6AgZnJhbWVfbWF0cml4KC4uLikgdHJvbmcgxJHDsyAuLi4gbMOgIGPDoWMgxJHhu5FpIHPhu5EsIG3hu5dpIMSR4buRaSBz4buRIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IGPhu5l0IGPhu6dhIG1hIHRy4bqtbi4gQ8OhYyBj4buZdCDEkcaw4bujYyDEkeG6t3QgdMOqbiBi4bqxbmcgY8O6IHBow6FwIH50ZW5jb3QgdHJvbmcgxJHDsyB0ZW5jb3QgbMOgIHTDqm4gY+G7mXQuDQotIEPDoWMgY+G7mXQgdHJvbmcgZnJhbWVfbWF0cml4KCkgY8OzIHRo4buDIGNo4bupYSBjw6FjIGxv4bqhaSBk4buvIGxp4buHdSBraMOhYyBuaGF1LCBjaOG6s25nIGjhuqFuIG5oxrAgY2h14buXaSBrw70gdOG7sSwgc+G7kSwgbG9naWMuLi4NCi0gQ8OhYyBj4buZdCBj4bunYSBmcmFtZV9tYXRyaXgoKSDEkcaw4bujYyDEkeG6t3QgdGhlbyB0aOG7qSB04buxIG3DoCBjaMO6bmcgeHXhuqV0IGhp4buHbiB0cm9uZyBjw7ogcGjDoXAsIHbDoCBt4buXaSBj4buZdCBjaOG7qWEgZOG7ryBsaeG7h3UgdMawxqFuZyDhu6luZyB04burbmcgaMOgbmcgY+G7p2EgbWEgdHLhuq1uLg0KLSBDw6FjIGThu68gbGnhu4d1IHRyb25nIG3hu5dpIGPhu5l0IHBo4bqjaSBjw7MgY8O5bmcgc+G7kSBsxrDhu6NuZyBwaOG6p24gdOG7rSwgbuG6v3Uga2jDtG5nIHPhur0geOG6o3kgcmEgbOG7l2kuDQoNClbDrSBk4bulOg0KDQpgYGB7cn0NCiMgVOG6oW8gbWEgdHLhuq1uIMSRaeG7g20gY+G7p2Egc2luaCB2acOqbg0KZGllbV9tYXRyaXggPC0gZnJhbWVfbWF0cml4KA0KICB+VGVuLCB+VG9hbiwgflZhbiwgfkFuaCwNCiAgIsOBbmggTGluaCIsIDguNSwgOC43NSwgNy41LA0KICAiSOG6o2kgUGjhu6VuZyIsIDkuMCwgNy41LCA4LjUsDQogICJUaGFuaCBIdeG7hyIsIDcuNzUsIDcuNSwgNy4wLA0KICAiRHV5IFF1YW5nIiwgOC4wLCA3LjUsIDcuMCkNCg0KIyBIaeG7g24gdGjhu4sgbWEgdHLhuq1uIMSRaeG7g20NCnByaW50KGRpZW1fbWF0cml4KQ0KYGBgDQoNCg0KIyMjIDQuMi41IENodXnhu4NuIMSR4buVaSB2ZWN0b3IgdGjDoG5oIGRhdGEgZnJhbWUgdsOgIG5nxrDhu6NjIGzhuqFpDQoNCiZlbnNwOyZlbnNwOyZlbnNwO0jDoG0gZW5mcmFtZSgpIHRyb25nIGfDs2kgdGliYmxlIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGNodXnhu4NuIMSR4buVaSB2ZWN0b3IgdGjDoG5oIGRhdGEgZnJhbWUgdsOgIG5nxrDhu6NjIGzhuqFpLiBIw6BtIG7DoHkgaOG7lyB0cuG7oyB2aeG7h2MgbMOgbSB2aeG7h2MgduG7m2kgY8OhYyBj4bqldSB0csO6YyBk4buvIGxp4buHdSB2ZWN0b3IgdsOgIGRhdGEgZnJhbWUgbeG7mXQgY8OhY2ggdGh14bqtbiB0aeG7h24gdsOgIGxpbmggaG/huqF0Lg0KDQomZW5zcDsmZW5zcDsmZW5zcDtLaGkgY2h1eeG7g24gxJHhu5VpIHZlY3RvciB0aMOgbmggZGF0YSBmcmFtZSwgaMOgbSBlbmZyYW1lKCkgc+G6vSB04bqhbyByYSBt4buZdCBkYXRhIGZyYW1lIHbhu5tpIGhhaSBj4buZdCwgbeG7mXQgY+G7mXQgxJHhu4MgbMawdSB0cuG7ryB0w6puIGPhu6dhIGPDoWMgcGjhuqduIHThu60gdHJvbmcgdmVjdG9yIHbDoCBt4buZdCBj4buZdCDEkeG7gyBsxrB1IHRy4buvIGdpw6EgdHLhu4sgdMawxqFuZyDhu6luZyBj4bunYSBjaMO6bmcuDQoNCiZlbnNwOyZlbnNwOyZlbnNwO0toaSBjaHV54buDbiDEkeG7lWkgZGF0YSBmcmFtZSB0aMOgbmggdmVjdG9yLCBow6BtIGVuZnJhbWUoKSBz4bq9IGzhuqV5IGdpw6EgdHLhu4sgdHJvbmcgbeG7mXQgY+G7mXQgY+G7p2EgZGF0YSBmcmFtZSB2w6AgdHLhuqMgduG7gSBt4buZdCB2ZWN0b3IgY2jhu6lhIGPDoWMgZ2nDoSB0cuG7iyDEkcOzLg0KDQoqKlbDrSBk4bulIHbhu4EgY2h1eeG7g24gxJHhu5VpIHZlY3RvciB0aMOgbmggZGF0YSBmcmFtZToqKg0KDQpgYGB7cn0NCiMgVmVjdG9yIGThu68gbGnhu4d1DQp2ZWMgPC0gYygxMCwgMjAsIDMwLCA0MCwgNTApDQoNCiMgQ2h1eeG7g24gxJHhu5VpIHZlY3RvciB0aMOgbmggZGF0YSBmcmFtZQ0KZGYgPC0gZW5mcmFtZSh2ZWMpDQoNCiMgSGnhu4NuIHRo4buLIGRhdGEgZnJhbWUNCnByaW50KGRmKQ0KDQpgYGANCg0KKipWw60gZOG7pSB24buBIGNodXnhu4NuIMSR4buVaSBkYXRhIGZyYW1lIHRow6BuaCB2ZWN0b3I6KioNCg0KYGBge3J9DQojIERhdGEgZnJhbWUgZOG7ryBsaeG7h3UNCmRmIDwtIGRhdGEuZnJhbWUobmFtZSA9IGMoIkEiLCAiQiIsICJDIiksIHZhbHVlID0gYygxMCwgMjAsIDMwKSkNCg0KIyBDaHV54buDbiDEkeG7lWkgZGF0YSBmcmFtZSB0aMOgbmggdmVjdG9yDQp2ZWMgPC0gZW5mcmFtZShkZiR2YWx1ZSkNCg0KIyBIaeG7g24gdGjhu4sgdmVjdG9yDQpwcmludCh2ZWMpDQoNCmBgYA0KDQojIyMgNC4yLjYgQ8O0bmcgY+G7pSBsw6BtIHZp4buHYyB24bubaSB0w6puIGjDoG5nDQoNCiZlbnNwOyZlbnNwOyZlbnNwO0jDoG0gcm93bmFtZXMgdHJvbmcgZ8OzaSB0aWJibGUgY3VuZyBj4bqlcCBjw6FjIGPDtG5nIGPhu6UgxJHhu4MgbMOgbSB2aeG7h2MgduG7m2kgdMOqbiBjw6FjIGjDoG5nIHRyb25nIGRhdGEgZnJhbWUgKHJvd25hbWVzKS5UdXkgbmhpw6puLCBraGkgdGjhu7FjIGhp4buHbiBwaMOpcCBs4buNYyBk4buvIGxp4buHdSBi4bqxbmcgdG/DoW4gdOG7rSBbICwgdMOqbiBow6BuZyBz4bq9IGLhu4sgbG/huqFpIGLhu48uIE7hur91IGNow7puZyB0YSBj4buRIGfhuq9uZyBnw6FuIHTDqm4gaMOgbmcga2jDoWMgTlVMTCBjaG8gbeG7mXQgdGliYmxlLCBt4buZdCBj4bqjbmggYsOhbyBz4bq9IHh14bqldCBoaeG7h24uIFRow7RuZyB0aMaw4budbmcsIG7Dqm4gdHLDoW5oIHPhu60gZOG7pW5nIHTDqm4gaMOgbmcsIHbDrCBuw7MgY2jhu4kgbMOgIG3hu5l0IGPhu5l0IGvDvSB04buxIHbhu5tpIMO9IG5naMSpYSBraMOhYyBiaeG7h3Qgc28gduG7m2kgY8OhYyBj4buZdCBraMOhYy4NCg0KQ8OzIG3hu5l0IHPhu5EgaMOgbSBo4buvdSDDrWNoIHRyb25nIGfDs2kgdGliYmxlIMSR4buDIGzDoG0gdmnhu4djIHbhu5tpIHTDqm4gaMOgbmc6DQoNCi0gaGFzX3Jvd25hbWVzKC5kYXRhKTogS2nhu4NtIHRyYSB4ZW0gbeG7mXQgZGF0YSBmcmFtZSBjw7MgdMOqbiBow6BuZyBoYXkga2jDtG5nLiBIw6BtIHRy4bqjIHbhu4EgZ2nDoSB0cuG7iyBsb2dpYyAoVFJVRSBob+G6t2MgRkFMU0UpLg0KLSByZW1vdmVfcm93bmFtZXMoLmRhdGEpOiBMb+G6oWkgYuG7jyB0w6puIGjDoG5nIGto4buPaSBkYXRhIGZyYW1lLg0KLSByb3duYW1lc190b19jb2x1bW4oLmRhdGEsIHZhciA9ICJyb3duYW1lIik6IENodXnhu4NuIMSR4buVaSB0w6puIGjDoG5nIHRow6BuaCBt4buZdCBj4buZdCBj4bulIHRo4buDIHRyb25nIGRhdGEgZnJhbWUuIELhuqFuIGPDsyB0aOG7gyBjaOG7iSDEkeG7i25oIHTDqm4gY2hvIGPhu5l0IG3hu5tpIGLhurFuZyB0aGFtIHPhu5EgInZhciIuDQotIHJvd2lkX3RvX2NvbHVtbiguZGF0YSwgdmFyID0gInJvd2lkIik6IFRow6ptIG3hu5l0IGPhu5l0IGNo4bupYSBjw6FjIHPhu5EgSUQgdMSDbmcgZOG6p24gdOG7qyAxIMSR4bq/biBz4buRIGjDoG5nIGPhu6dhIGRhdGEgZnJhbWUuIEjDoG0gbsOgeSBz4bq9IGxv4bqhaSBi4buPIHTDqm4gaMOgbmcgaGnhu4duIGPDsy4NCi0gY29sdW1uX3RvX3Jvd25hbWVzKC5kYXRhLCB2YXIgPSAicm93bmFtZSIpOiBDaHV54buDbiDEkeG7lWkgbeG7mXQgY+G7mXQgY+G7pSB0aOG7gyBj4bunYSBkYXRhIGZyYW1lIHRow6BuaCB0w6puIGjDoG5nLiBUw6puIGPhu6dhIGPhu5l0IMSRxrDhu6NjIGNo4buJIMSR4buLbmggYuG7n2kgdGhhbSBz4buRICJ2YXIiLg0KDQogTMawdSDDvTogTeG7mXQgc+G7kSBow6BtIMSRw6MgYuG7iyBsb+G6oWkgYuG7jyByYSBraOG7j2kgZ8OzaSBUaWJibGUgbeG7m2kgbmjhuqV0DQogDQpWw60gZOG7pTogDQoNCmBgYHtyfQ0KIyBLaOG7n2kgdOG6oW8gdGliYmxlDQpkYXRhX2cgPC0gdGliYmxlOjp0cmliYmxlKA0KICB+VGVuLCB+VG9hbiwgflZhbiwgfkFuaCwNCiAgIkjhuqNpIFBo4bulbmciLCA5LjAsIDcuNSwgOC41LA0KICAiVGhhbmggSHXhu4ciLCA3Ljc1LCA3LjUsIDcuMCwNCiAgIkR1eSBRdWFuZyIsIDguMCwgNy41LCA3LjApDQoNCiMgS2nhu4NtIHRyYSB4ZW0gdGliYmxlIGPDsyB0w6puIGjDoG5nIGhheSBraMO0bmcNCmhhc19yb3dfbmFtZXMgPC0gIWlzLm51bGwocm93bmFtZXMoZGF0YV9nKSkNCg0KIyBDaHV54buDbiDEkeG7lWkgdMOqbiBow6BuZyB0aMOgbmggbeG7mXQgY+G7mXQgbeG7m2kgY8OzIHTDqm4gbMOgICJJRCINCmRhdGFfdGliYmxlX3dpdGhfaWQgPC0gdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oZGF0YV9nLCB2YXIgPSAiSUQiKQ0KDQojIExv4bqhaSBi4buPIHTDqm4gaMOgbmcga2jhu49pIHRpYmJsZQ0KZGF0YV90aWJibGVfd2l0aG91dF9yb3duYW1lcyA8LSB0aWJibGU6OnJlbW92ZV9yb3duYW1lcyhkYXRhX2cpDQoNCiMgQ2h1eeG7g24gY+G7mXQgIklEIiB24buBIHTDqm4gaMOgbmcNCmRhdGFfdGliYmxlX3dpdGhfcm93bmFtZXMgPC0gdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXMoZGF0YV90aWJibGVfd2l0aF9pZCwgdmFyID0gIklEIikNCg0KIyBIaeG7g24gdGjhu4sga+G6v3QgcXXhuqMNCnByaW50KCJLaeG7g20gdHJhIHhlbSB0aWJibGUgY8OzIHTDqm4gaMOgbmcgaGF5IGtow7RuZzoiKQ0KcHJpbnQoaGFzX3Jvd19uYW1lcykNCg0KcHJpbnQoIkNodXnhu4NuIMSR4buVaSB0w6puIGjDoG5nIHRow6BuaCBj4buZdCBt4bubaToiKQ0KcHJpbnQoZGF0YV90aWJibGVfd2l0aF9pZCkNCg0KcHJpbnQoIkxv4bqhaSBi4buPIHTDqm4gaMOgbmcga2jhu49pIHRpYmJsZToiKQ0KcHJpbnQoZGF0YV90aWJibGVfd2l0aG91dF9yb3duYW1lcykNCg0KcHJpbnQoIkNodXnhu4NuIGPhu5l0IElEIHbhu4EgdMOqbiBow6BuZzoiKQ0KcHJpbnQoZGF0YV90aWJibGVfd2l0aF9yb3duYW1lcykNCg0KYGBgDQoNCg0KIyMgNC4zIEvhur90IGjhu6NwIGfDs2kgdGliYmxlIHbhu5tpIGPDoWMgZ8OzaSBkcGx5ciB2w6AgZ2dwbG90MiB0cm9uZyBSIMSR4buDIHjhu60gbMO9IHbDoCB0cuG7sWMgcXVhbiBow7NhIGThu68gbGnhu4d1DQoNCg0KIyMjIDQuMy4xLiBT4butIGThu6VuZyBnw7NpICJ0aWR5ciIgxJHhu4MgeOG7rSBsw70gZOG7ryBsaeG7h3UgduG7m2kgdGliYmxlDQoNClRyb25nIHBo4bqnbiBuw6B5LCBjaMO6bmcgdGEgc+G6vSBnaeG7m2kgdGhp4buHdSBjw6FjaCBz4butIGThu6VuZyBnw7NpICJ0aWR5ciIgY8O5bmcgduG7m2kgZ8OzaSAidGliYmxlIiDEkeG7gyB44butIGzDvSBk4buvIGxp4buHdS4gR8OzaSAidGlkeXIiIGN1bmcgY+G6pXAgY8OhYyBow6BtIG5oxrAgZ2F0aGVyKCksIHNwcmVhZCgpLCBzZXBhcmF0ZSgpLCB1bml0ZSgpLCBwaXZvdF9sb25nZXIoKSB2w6AgcGl2b3Rfd2lkZXIoKSBnacO6cCBjaHV54buDbiDEkeG7lWkgZOG7ryBsaeG7h3UgZ2nhu69hIGPDoWMgxJHhu4tuaCBk4bqhbmcgcuG7mW5nICh3aWRlKSB2w6AgZMOgaSAobG9uZyksIHTDoWNoIGPDoWMgY+G7mXQgdGjDoG5oIG5oaeG7gXUgY+G7mXQgbeG7m2kgdsOgIGvhur90IGjhu6NwIG5oaeG7gXUgY+G7mXQgdGjDoG5oIG3hu5l0IGPhu5l0Lg0KDQpWw60gZOG7pToNCg0KYGBge3J9DQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkodGlkeXIpDQojIEThu68gbGnhu4d1IGJhbiDEkeG6p3UgKGThuqFuZyB3aWRlKQ0KZGF0YV93aWRlIDwtIHRpYmJsZSgNCiAgIkjhu40gdMOqbiIgPSBjKCJI4bqjaSBQaOG7pW5nIiwgIsOBbmggTGluaCIsICJIb8OgbmcgTmd1ecOqbiIsICJUaGFuaCBIdeG7hyIsICJEdXkgUXVhbmciKSwNCiAgIktpbmggdOG6vyBsxrDhu6NuZyIgPSBjKDguNSwgOS4wLCA3LjUsIDguMjUsIDguNzYpLA0KICAiWMOhYyB4deG6pXQgdGjhu5FuZyBrw6oiID0gYyg3LjAsIDguMCwgNy41LCA4LjI1LCA3LjUpLA0KICAiVG/DoW4gY2FvIGPhuqVwIiA9IGMoOC4wLCA3LjUsIDguMjUsIDguNSwgOC4yNSkpDQoNCiMgQ2h1eeG7g24gxJHhu5VpIGThu68gbGnhu4d1IHThu6sgd2lkZSBzYW5nIGxvbmcgYuG6sW5nIGdhdGhlcigpDQpkYXRhX2xvbmcgPC0gZGF0YV93aWRlICU+JQ0KICBnYXRoZXIoa2V5ID0gIk3DtG4gaOG7jWMiLCB2YWx1ZSA9ICLEkGnhu4NtIiwgIktpbmggdOG6vyBsxrDhu6NuZyIsICJYw6FjIHh14bqldCB0aOG7kW5nIGvDqiIsICJUb8OhbiBjYW8gY+G6pXAiKQ0KDQojIEhp4buDbiB0aOG7iyBk4buvIGxp4buHdSBzYXUga2hpIGNodXnhu4NuIMSR4buVaQ0KcHJpbnQoZGF0YV9sb25nKQ0KDQpgYGANCg0KDQojIyMgNC4zLjIuIFPhu60gZOG7pW5nIGfDs2kgImx1YnJpZGF0ZSIgxJHhu4MgbMOgbSB2aeG7h2MgduG7m2kgbmfDoHkgdGjDoW5nIHRyb25nIHRpYmJsZToNCg0KR8OzaSAibHVicmlkYXRlIiBjdW5nIGPhuqVwIGPDoWMgaMOgbSBt4bqhbmggbeG6vSDEkeG7gyBsw6BtIHZp4buHYyB24bubaSBuZ8OgeSB0aMOhbmcgdHJvbmcgUi4gS2hpIGvhur90IGjhu6NwIGfDs2kgImx1YnJpZGF0ZSIgduG7m2kgZ8OzaSAidGliYmxlIiwgY2jDum5nIHRhIGPDsyB0aOG7gyB44butIGzDvSBk4buvIGxp4buHdSBuZ8OgeSB0aMOhbmcgbeG7mXQgY8OhY2ggZOG7hSBkw6BuZyB2w6AgaGnhu4d1IHF14bqjLg0KDQpWw60gZOG7pToNCg0KYGBge3J9DQojIEfhu41pIHRoxrAgdmnhu4duIGx1YnJpZGF0ZQ0KbGlicmFyeShsdWJyaWRhdGUpDQoNCiMgVOG6oW8gdGliYmxlIHThu6sgZOG7ryBsaeG7h3UgduG7m2kgY+G7mXQgTmdheV9zaW5oIGTGsOG7m2kgZOG6oW5nIGNoYXJhY3Rlcg0KZGF0YV90aWJibGUgPC0gdGliYmxlKA0KICBUZW4gPSBjKCLDgW5oIExpbmgiLCAiSOG6o2kgUGjhu6VuZyIsICJUaGFuaCBIdeG7hyIsICJEdXkgUXVhbmciKSwNCiAgTmdheV9zaW5oID0gYygiMTk5Ny0wMy0xNSIsICIyMDA0LTA5LTIxIiwgIjE5OTktMDctMDQiLCAiMTk5Ni0xMS0zMCIpKQ0KDQojIFPhu60gZOG7pW5nIGfDs2kgbHVicmlkYXRlIMSR4buDIHThuqFvIGPhu5l0IG5nw6B5IHRow6FuZyBt4bubaQ0KZGF0YV90aWJibGUgPC0gZGF0YV90aWJibGUgJT4lDQogIG11dGF0ZShOZ2F5X3NpbmggPSBsdWJyaWRhdGU6OnltZChOZ2F5X3NpbmgpKQ0KDQojIEhp4buDbiB0aOG7iyB0aWJibGUgc2F1IGtoaSB0aMOqbSBj4buZdCBuZ8OgeSB0aMOhbmcNCnByaW50KGRhdGFfdGliYmxlKQ0KDQpgYGANCg0KIyMjIDQuMy4zLiBU4buVbmcgaOG7o3AgdsOgIGJp4buDdSBkaeG7hW4gZOG7ryBsaeG7h3UgduG7m2kgZHBseXIgdsOgIGdncGxvdDI6DQoNClRyb25nIHBo4bqnbiBuw6B5LCBjaMO6bmcgdGEgc+G6vSBr4bq/dCBo4bujcCBz4butIGThu6VuZyBnw7NpICJkcGx5ciIgdsOgIGfDs2kgImdncGxvdDIiIMSR4buDIHThu5VuZyBo4bujcCB2w6AgYmnhu4N1IGRp4buFbiBk4buvIGxp4buHdSB04burIHRpYmJsZS4NCg0KVsOtIGThu6U6DQoNClRyb25nIHbDrSBk4bulIG7DoHksIGNow7puZyB0YSBz4bq9IHPhu60gZOG7pW5nIGfDs2kgInRpYmJsZSIga+G6v3QgaOG7o3AgduG7m2kgZ8OzaSAiZHBseXIiIMSR4buDIHRo4buxYyBoaeG7h24gbeG7mXQgc+G7kSBwaMOpcCBiaeG6v24gxJHhu5VpIMSRxqFuIGdp4bqjbiB0csOqbiB04bqtcCBk4buvIGxp4buHdSB2w6AgaGnhu4NuIHRo4buLIGvhur90IHF14bqjIGLhurFuZyBnZ3Bsb3QyLg0KDQpUcsaw4bubYyBo4bq/dCB0YSBj4bqnbiBjw6BpIMSRxIN0IGPDoWMgZ8OzaSBj4bqnbiB0aGnhur90IGNobyB2aeG7h2MgeOG7rSBsw70gZOG7ryBsaeG7h3UuDQoNCmBgYHtyfQ0KIyBH4buNaSBjw6FjIHRoxrAgdmnhu4duIGPhuqduIHRoaeG6v3QNCmxpYnJhcnkodGliYmxlKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGxvdGx5KQ0KDQojIFThuqFvIHRpYmJsZSB04burIGThu68gbGnhu4d1DQpkYXRhX20gPC0gdGliYmxlKA0KICBUZW4gPSBjKCLDgW5oIExpbmgiLCAiSOG6o2kgUGjhu6VuZyIsICJUaGFuaCBIdeG7hyIsICJEdXkgUXVhbmciKSwNCiAgTVBOTiA9IGMoOC41LCA5LjAsIDcuNzUsIDguMCksDQogIFRvYW5fa3QgPSBjKDguNzUsIDcuNSwgNy41LCA3LjUpLA0KICBLaW5odGVsdW9uZyA9IGMoNy41LCA4LjUsIDcuMCwgNy4wKSkNCg0KIyBM4buNYyByYSBjw6FjIHNpbmggdmnDqm4gY8OzIMSRaeG7g20gTcO0IHBo4buPbmcgbmfhuqt1IG5oacOqbiBs4bubbiBoxqFuIDguMA0KZmlsdGVyZWRfZGF0YSA8LSBmaWx0ZXIoZGF0YV9tLCBNUE5OID4gOC4wKQ0KDQojIFPhuq9wIHjhur9wIGPDoWMgaOG7jWMgc2luaCB0aGVvIMSRaeG7g20gVG/DoW4ga2luaCB04bq/IGdp4bqjbSBk4bqnbg0Kc29ydGVkX2RhdGEgPC0gYXJyYW5nZShkYXRhX20sIGRlc2MoVG9hbl9rdCkpDQoNCiMgR29tIG5ow7NtIGThu68gbGnhu4d1IHRoZW8gxJFp4buDbSBLaW5oIHThur8gbMaw4bujbmcgdsOgIHTDrW5oIHThu5VuZyDEkWnhu4NtIGPhu6dhIG3hu5dpIG5ow7NtDQpncm91cGVkX2RhdGEgPC0gZGF0YV9tICU+JSANCiAgZ3JvdXBfYnkoS2luaHRlbHVvbmcpICU+JSANCiAgc3VtbWFyaXplKFRvdGFsX0RpZW0gPSBzdW0oTVBOTiArIFRvYW5fa3QgKyBLaW5odGVsdW9uZykpDQpgYGANCg0KKipUcuG7sWMgcXVhbiBow7NhIGThu68gbGnhu4d1IGLhurFuZyBnZ3Bsb3QyKioNCg0KKipCaeG7g3UgxJHhu5MgY+G7mXQgdGjhu4MgaGnhu4duIMSRaeG7g20gTcO0IHBo4buPbmcgbmfhuqt1IG5oacOqbiBj4bunYSBjw6FjIGjhu41jIHNpbmgqKg0KDQpgYGB7cn0NCmdncGxvdChkYXRhX20sIGFlcyh4ID0gVGVuLCB5ID0gTVBOTikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAicGluayIpICsNCiAgbGFicyh0aXRsZSA9ICLEkGnhu4NtIE3DtCBwaOG7j25nIG5n4bqrdSBuaGnDqm4gY+G7p2Egc2luaCB2acOqbiIsDQogICAgICAgeCA9ICJTaW5oIHZpw6puIiwNCiAgICAgICB5ID0gIsSQaeG7g20gTcO0IHBo4buPbmcgbmfhuqt1IG5oacOqbiIpDQpgYGANCg0KDQoqKkJp4buDdSDEkeG7kyAyRCDEkWnhu4NtIGPhu6dhIGPDoWMgbcO0biBNw7QgcGjhu49uZyBuZ+G6q3Ugbmhpw6puLCBUb8OhbiBraW5oIHThur8gdsOgIEtpbmggdOG6vyBsxrDhu6NuZyBj4bunYSBzaW5oIHZpw6puKioNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YV9tLCBhZXMoeCA9IFRlbikpICsNCiAgZ2VvbV9wb2ludChhZXMoeSA9IE1QTk4sIGNvbG9yID0gIk3DtCBwaOG7j25nIG5n4bqrdSBuaGnDqm4iKSkgKw0KICBnZW9tX3BvaW50KGFlcyh5ID0gVG9hbl9rdCwgY29sb3IgPSAiVG/DoW4ga2luaCB04bq/IikpICsNCiAgZ2VvbV9wb2ludChhZXMoeSA9IEtpbmh0ZWx1b25nLCBjb2xvciA9ICJLaW5oIHThur8gbMaw4bujbmciKSkgKw0KICBsYWJzKHRpdGxlID0gIsSQaeG7g20gTcO0IHBo4buPbmcgbmfhuqt1IG5oacOqbiwgVG/DoW4ga2luaCB04bq/IHbDoCBLaW5oIHThur8gbMaw4bujbmcgY+G7p2Egc2luaCB2acOqbiIsDQogICAgICAgeCA9ICJzaW5oIHZpw6puIiwNCiAgICAgICB5ID0gIsSQaeG7g20iKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJNw7QgcGjhu49uZyBuZ+G6q3Ugbmhpw6puIiA9ICJibHVlIiwgIlRvw6FuIGtpbmggdOG6vyIgPSAicmVkIiwgIktpbmggdOG6vyBsxrDhu6NuZyIgPSAiZ3JlZW4iKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk3DtCBwaOG7j25nIG5n4bqrdSBuaGnDqm4iLCAiVG/DoW4ga2luaCB04bq/IiwgIktpbmggdOG6vyBsxrDhu6NuZyIpKQ0KYGBgDQoNCg0KKipCaeG7g3UgxJHhu5MgM0QgxJFp4buDbSBj4bunYSBjw6FjIG3DtG4gTcO0IHBo4buPbmcgbmfhuqt1IG5oacOqbiwgVG/DoW4ga2luaCB04bq/IHbDoCBLaW5oIHThur8gbMaw4bujbmcgY+G7p2Egc2luaCB2acOqbioqDQoNCg0KYGBge3J9DQpwbG90X2x5KGRhdGFfbSwgeCA9IH5NUE5OLCB5ID0gflRvYW5fa3QsIHogPSB+S2luaHRlbHVvbmcsDQogICAgICAgIGNvbG9yID0gflRlbiwgY29sb3JzID0gYygiYmx1ZSIsICJyZWQiLCAiZ3JlZW4iLCAib3JhbmdlIiksDQogICAgICAgIHRleHQgPSB+VGVuLCB0eXBlID0gInNjYXR0ZXIzZCIsIG1vZGUgPSAibWFya2VycyIsDQogICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDEwLCBvcGFjaXR5ID0gMC44KSkgJT4lDQogIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gIsSQaeG7g20gTcO0IHBo4buPbmcgbmfhuqt1IG5oacOqbiIpLA0KICAgICAgICAgICAgICAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICLEkGnhu4NtIFRvw6FuIGtpbmggdOG6vyIpLA0KICAgICAgICAgICAgICAgICAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICLEkGnhu4NtIEtpbmggdOG6vyBsxrDhu6NuZyIpKSkNCmBgYA0KDQoqKkJp4buDdSDEkeG7kyBj4buZdCB0aOG7gyBoaeG7h24gdOG7lW5nIMSRaeG7g20gY+G7p2EgY8OhYyBuaMOzbSBk4buxYSB0csOqbiDEkWnhu4NtIEtpbmggdOG6vyBsxrDhu6NuZyoqDQoNCmBgYHtyfQ0KZ2dwbG90KGdyb3VwZWRfZGF0YSwgYWVzKHggPSBLaW5odGVsdW9uZywgeSA9IFRvdGFsX0RpZW0pKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInNhbG1vbiIpICsNCiAgbGFicyh0aXRsZSA9ICJU4buVbmcgxJFp4buDbSB0aGVvIMSRaeG7g20gS2luaCB04bq/IGzGsOG7o25nIiwNCiAgICAgICB4ID0gIsSQaeG7g20gS2luaCB04bq/IGzGsOG7o25nIiwNCiAgICAgICB5ID0gIlThu5VuZyDEkWnhu4NtIikNCmBgYA0KDQoNCiMjIyA0LjMuNC4gU+G7rSBk4bulbmcgZ8OzaSAic3RyaW5nciIgxJHhu4MgbMOgbSB2aeG7h2MgduG7m2kgY2h14buXaSB0cm9uZyB0aWJibGUNCg0KR8OzaSAic3RyaW5nciIgY3VuZyBj4bqlcCBjw6FjIGjDoG0gaOG7lyB0cuG7oyB44butIGzDvSB2w6AgYmnhur9uIMSR4buVaSBjaHXhu5dpIHRyb25nIFIuIEtoaSBr4bq/dCBo4bujcCBnw7NpICJzdHJpbmdyIiB24bubaSBnw7NpICJ0aWJibGUiLCBjaMO6bmcgdGEgY8OzIHRo4buDIHRo4buxYyBoaeG7h24gY8OhYyBwaMOpcCBiaeG6v24gxJHhu5VpIGNodeG7l2kgbeG7mXQgY8OhY2ggZOG7hSBkw6BuZy4NCg0KVsOtIGThu6U6DQoNCmBgYHtyfQ0KIyBU4bqhbyB0aWJibGUgdOG7qyBk4buvIGxp4buHdSB24bubaSBj4buZdCBUZW4gZMaw4bubaSBk4bqhbmcgY2hhcmFjdGVyDQpkYXRhX3RpYmJsZSA8LSB0aWJibGUoDQogIFRlbiA9IGMoIsOBbmggTGluaCIsICJI4bqjaSBQaOG7pW5nIiwgIlRoYW5oIEh14buHIiwgIkR1eSBRdWFuZyIpKQ0KDQojIFPhu60gZOG7pW5nIGfDs2kgc3RyaW5nciDEkeG7gyB0aGF5IMSR4buVaSB0w6puIHNpbmggdmnDqm4gdGjDoG5oIGluIGhvYQ0KZGF0YV90aWJibGUgPC0gZGF0YV90aWJibGUgJT4lDQogIG11dGF0ZShUZW4gPSBzdHJpbmdyOjpzdHJfdG9fdXBwZXIoVGVuKSkNCg0KIyBIaeG7g24gdGjhu4sgdGliYmxlIHNhdSBraGkgdGhheSDEkeG7lWkgdMOqbg0KcHJpbnQoZGF0YV90aWJibGUpDQpgYGANCg0KDQojIyMgNC4zLjUuIFjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdsOgIGzhu5dpIHRyb25nIHRpYmJsZQ0KDQpUcm9uZyBwaOG6p24gbsOgeSwgY2jDum5nIHRhIHPhur0gdMOsbSBoaeG7g3UgY8OhY2ggeOG7rSBsw70gZOG7ryBsaeG7h3UgdGhp4bq/dSB2w6AgbOG7l2kgdHJvbmcgdGliYmxlLiBDaMO6bmcgdGEgc+G6vSBz4butIGThu6VuZyBjw6FjIGjDoG0gbmjGsCBuYS5vbWl0KCksIGNvbXBsZXRlKCksIGZpbGwoKSwgZHJvcF9uYSgpIMSR4buDIHjhu60gbMO9IGPDoWMgZ2nDoSB0cuG7iyB0aGnhur91IHbDoCBs4buXaSB0cm9uZyBk4buvIGxp4buHdS4NCg0KVsOtIGThu6U6DQoNCmBgYHtyfQ0KIyBU4bqhbyB0aWJibGUgdOG7qyBk4buvIGxp4buHdSB24bubaSBt4buZdCBz4buRIGdpw6EgdHLhu4sgdGhp4bq/dQ0KZGF0YV90aWJibGUgPC0gdGliYmxlKA0KICBUZW4gPSBjKCLDgW5oIExpbmgiLCBOQSwgIlRoYW5oIEh14buHIiwgIkR1eSBRdWFuZyIpLA0KICBEaWVtID0gYyhOQSwgOS4wLCA3LjUsIDguMCkNCikNCg0KIyBT4butIGThu6VuZyBuYS5vbWl0KCkgxJHhu4MgbG/huqFpIGLhu48gY8OhYyBow6BuZyBjw7MgZ2nDoSB0cuG7iyB0aGnhur91DQpkYXRhX3RpYmJsZSA8LSBuYS5vbWl0KGRhdGFfdGliYmxlKQ0KDQojIFPhu60gZOG7pW5nIGNvbXBsZXRlKCkgdsOgIGZpbGwoKSDEkeG7gyDEkWnhu4FuIGdpw6EgdHLhu4sgdGhp4bq/dQ0KZGF0YV90aWJibGUgPC0gZGF0YV90aWJibGUgJT4lDQogIGNvbXBsZXRlKFRlbiwgZmlsbCA9IGxpc3QoRGllbSA9IDApKQ0KDQojIFPhu60gZOG7pW5nIGRyb3BfbmEoKSDEkeG7gyBsb+G6oWkgYuG7jyBjw6FjIGjDoG5nIGPDsyBnacOhIHRy4buLIHRoaeG6v3UNCmRhdGFfdGliYmxlIDwtIGRyb3BfbmEoZGF0YV90aWJibGUpDQoNCiMgSGnhu4NuIHRo4buLIHRpYmJsZSBzYXUga2hpIHjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UNCnByaW50KGRhdGFfdGliYmxlKQ0KYGBgDQoNCiMjIyA0LjMuNi4gxJDhu4tuaCBk4bqhbmcgZOG7ryBsaeG7h3UgdHJvbmcgdGliYmxlDQoNClRyb25nIHBo4bqnbiBuw6B5LCBjaMO6bmcgdGEgc+G6vSB0w6xtIGhp4buDdSBjw6FjaCDEkeG7i25oIGThuqFuZyBk4buvIGxp4buHdSB0cm9uZyB0aWJibGUuIMSQaeG7gXUgbsOgeSBiYW8gZ+G7k20gxJHhu4tuaCBk4bqhbmcga2nhu4N1IGThu68gbGnhu4d1IGPhu6dhIGPDoWMgY+G7mXQgdsOgIMSR4buLbmggZOG6oW5nIGhp4buDbiB0aOG7iyBj4bunYSBjw6FjIGdpw6EgdHLhu4suDQoNClbDrSBk4bulOg0KDQpgYGB7cn0NCiMgVOG6oW8gdGliYmxlIHThu6sgZOG7ryBsaeG7h3UgduG7m2kgY+G7mXQgxJFp4buDbSBkxrDhu5tpIGThuqFuZyBudW1lcmljDQpkYXRhX3RpYmJsZSA8LSB0aWJibGUoDQogIFRlbiA9IGMoIsOBbmggTGluaCIsICJI4bqjaSBQaOG7pW5nIiwgIlRoYW5oIEh14buHIiwgIkR1eSBRdWFuZyIpLA0KICBEaWVtID0gYyg4LjUsIDkuMCwgNy43NSwgOC4wKSkNCg0KIyDEkOG7i25oIGThuqFuZyBraeG7g3UgZOG7ryBsaeG7h3UgY+G7p2EgY+G7mXQgRGllbSB0aMOgbmggc+G7kSB0aOG6rXAgcGjDom4gY8OzIGhhaSBjaOG7ryBz4buRIHNhdSBk4bqldSBwaOG6qXkNCmRhdGFfdGliYmxlJERpZW0gPC0gcm91bmQoZGF0YV90aWJibGUkRGllbSwgMikNCg0KIyBIaeG7g24gdGjhu4sgdGliYmxlIHNhdSBraGkgxJHhu4tuaCBk4bqhbmcgZOG7ryBsaeG7h3UNCnByaW50KGRhdGFfdGliYmxlKQ0KYGBgDQoNCiMgKipDaMawxqFuZyA1IDogxq91IMSRaeG7g20gdsOgIGjhuqFuIGNo4bq/IGPhu6dhIHBhY2thZ2UgVGliYmxlKioNCg0KIyMgNS4xIMavdSDEkWnhu4NtDQoNCi0gQ8O6IHBow6FwIGThu4UgxJHhu41jIHbDoCBzw6FuZyBz4bunYTogVGliYmxlIHPhu60gZOG7pW5nIGPDuiBwaMOhcCDEkcahbiBnaeG6o24gdsOgIGThu4UgaGnhu4N1LCBnacO6cCBuZ8aw4budaSBkw7luZyBk4buFIGTDoG5nIMSR4buNYywgc+G7rWEgxJHhu5VpIHbDoCB0aGFvIHTDoWMgZOG7ryBsaeG7h3UgbeG7mXQgY8OhY2ggaGnhu4d1IHF14bqjLg0KLSBY4butIGzDvSBk4buvIGxp4buHdSBsaW5oIGhv4bqhdDogVGliYmxlIGjhu5cgdHLhu6Mgdmnhu4djIGNo4buNbiBs4buNYywgYmnhur9uIMSR4buVaSB2w6AgdHJ1eSB4deG6pXQgZOG7ryBsaeG7h3UgbeG7mXQgY8OhY2ggbGluaCBob+G6oXQsIGdpw7pwIHRp4bq/dCBraeG7h20gdGjhu51pIGdpYW4gdsOgIGPDtG5nIHPhu6ljIGtoaSB0aOG7sWMgaGnhu4duIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IHBo4bupYyB04bqhcC4NCi0gWOG7rSBsw70gbWV0YWRhdGE6IFRpYmJsZSBjaG8gcGjDqXAgbMawdSB0cuG7ryBjw6FjIG1ldGFkYXRhICh0aMO0bmcgdGluIHbhu4EgYmnhur9uIHbDoCBxdWFuIHPDoXQpIGPDuW5nIHbhu5tpIGThu68gbGnhu4d1LCBnacO6cCBuZ8aw4budaSBkw7luZyBk4buFIGTDoG5nIHRow6ptLCBz4butYSDEkeG7lWkgdsOgIHPhu60gZOG7pW5nIHRow7RuZyB0aW4gYuG7lSBzdW5nIHbhu4EgZOG7ryBsaeG7h3UgdHJvbmcgcXXDoSB0csOsbmggcGjDom4gdMOtY2guDQotIFTDrWNoIGjhu6NwIHThu5F0IHbhu5tpIGThu68gbGnhu4d1IGThuqFuZyBkYW5oIHPDoWNoIChsaXN0LWNvbHVtbnMpOiBUaWJibGUgY2hvIHBow6lwIGzGsHUgdHLhu68gZOG7ryBsaeG7h3UgZOG6oW5nIGRhbmggc8OhY2ggKGxpc3QtY29sdW1ucyksIGdpw7pwIGdp4bqjaSBxdXnhur90IHbhuqVuIMSR4buBIHjhu60gbMO9IGThu68gbGnhu4d1IHBo4bupYyB04bqhcCB2w6AgxJFhIGPhuqVwIMSR4buZIG3hu5l0IGPDoWNoIGhp4buHdSBxdeG6oy4NCi0gSOG7lyB0cuG7oyB0w61jaCBo4bujcCB2w6AgdMawxqFuZyB0aMOtY2g6IFRpYmJsZSDEkcaw4bujYyB0w61jaCBo4bujcCBt4bqhbmggbeG6vSB24bubaSBjw6FjIGfDs2kgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgcGjhu5UgYmnhur9uIHRyb25nIFIgbmjGsCBkcGx5ciwgZ2dwbG90MiwgdGlkeXIsIGR0cGx5ciwgZ2nDunAgbmfGsOG7nWkgZMO5bmcgdOG6rW4gZOG7pW5nIHRvw6BuIGLhu5kga2jhuqMgbsSDbmcgY+G7p2EgUiB0cm9uZyBwaMOibiB0w61jaCBk4buvIGxp4buHdS4NCi0gSGnhu4d1IHN14bqldCB04buRaSDGsHU6IFRpYmJsZSB04buRaSDGsHUgaMOzYSBoaeG7h3Ugc3XhuqV0IHjhu60gbMO9IGThu68gbGnhu4d1LCBnacO6cCBnaeG6o20gdGjhu51pIGdpYW4gdGjhu7FjIHRoaSBjw6FjIHRoYW8gdMOhYyBwaOG7qWMgdOG6oXAgdsOgIHjhu60gbMO9IGThu68gbGnhu4d1IGzhu5tuIG5oYW5oIGNow7NuZyB2w6AgaGnhu4d1IHF14bqjLg0KLSBI4buXIHRy4bujIGThu4UgZMOgbmc6IFBhY2thZ2UgVGliYmxlIMSRxrDhu6NjIGjhu5cgdHLhu6MgdsOgIHBow6F0IHRyaeG7g24gbGnDqm4gdOG7pWMgYuG7n2kgY+G7mW5nIMSR4buTbmcgbmfGsOG7nWkgZMO5bmcgdsOgIG5ow6AgcGjDoXQgdHJp4buDbiBSLCDEkeG6o20gYuG6o28gc+G7sSDhu5VuIMSR4buLbmggdsOgIGPhuqNpIHRp4bq/biBsacOqbiB04bulYy4NCg0KIyMgNS4yIEjhuqFuIGNo4bq/DQoNCi0gWcOqdSBj4bqndSBjw6BpIMSR4bq3dCBwYWNrYWdlOiBN4bq3YyBkw7kgcGFja2FnZSBUaWJibGUgbMOgIG3hu5l0IGPDtG5nIGPhu6UgbeG6oW5oIG3hur0sIG5oxrBuZyBuw7MgY+G6p24gcGjhuqNpIMSRxrDhu6NjIGPDoGkgxJHhurd0IHRyb25nIFIgdHLGsOG7m2Mga2hpIHPhu60gZOG7pW5nLiDEkGnhu4F1IG7DoHkgY8OzIHRo4buDIHThuqFvIHJhIG3hu5l0IHPhu5EgcsOgbyBj4bqjbiDEkeG7kWkgduG7m2kgbmfGsOG7nWkgZMO5bmcgbeG7m2kgaG/hurdjIHRyb25nIG3DtGkgdHLGsOG7nW5nIGtow7RuZyBjaG8gcGjDqXAgY8OgaSDEkeG6t3QgcGFja2FnZS4NCi0gU+G7sSBraMOhYyBiaeG7h3QgduG7m2kgZGF0YS5mcmFtZTogTeG6t2MgZMO5IFRpYmJsZSBjaOG7pyB54bq/dSBsw6AgbeG7mXQgcGhpw6puIGLhuqNuIHThu5FpIMawdSBj4bunYSBkYXRhLmZyYW1lLCBuaMawbmcgbsOzIGPDsyBt4buZdCBz4buRIHPhu7Ega2jDoWMgYmnhu4d0IHbhu4EgY8O6IHBow6FwIHbDoCB0w61uaCBuxINuZyBzbyB24bubaSBkYXRhLmZyYW1lLCDEkWnhu4F1IG7DoHkgY8OzIHRo4buDIMSRw7JpIGjhu49pIG5nxrDhu51pIGTDuW5nIGjhu41jIHRow6ptIHbDoCB0aMOtY2ggbmdoaSB24bubaSBUaWJibGUuDQotIMSQ4buRaSB24bubaSBk4buvIGxp4buHdSBs4bubbjogVHJvbmcgbeG7mXQgc+G7kSB0csaw4budbmcgaOG7o3AgduG7m2kgZOG7ryBsaeG7h3UgcuG6pXQgbOG7m24sIGhp4buHdSBzdeG6pXQgY+G7p2EgVGliYmxlIGPDsyB0aOG7gyBi4buLIOG6o25oIGjGsOG7n25nLiBE4buxYSB2w6BvIHTDrW5oIGNo4bqldCBj4bunYSBk4buvIGxp4buHdSB2w6AgbG/huqFpIHBow6JuIHTDrWNoLCBuZ8aw4budaSBkw7luZyBjw7MgdGjhu4MgcGjhuqNpIHhlbSB4w6l0IHZp4buHYyBz4butIGThu6VuZyBUaWJibGUgc28gduG7m2kgY8OhYyBwaMawxqFuZyBwaMOhcCB44butIGzDvSBk4buvIGxp4buHdSBs4bubbiBraMOhYy4NCi0gS2jDtG5nIHTGsMahbmcgdGjDrWNoIHbhu5tpIG3hu5l0IHPhu5EgZ8OzaSBjxak6IFRyb25nIG3hu5l0IHPhu5EgdHLGsOG7nW5nIGjhu6NwLCBUaWJibGUgY8OzIHRo4buDIGtow7RuZyB0xrDGoW5nIHRow61jaCBob+G6t2MgaOG7lyB0cuG7oyBraMO0bmcgxJHhuqd5IMSR4bunIHbhu5tpIG3hu5l0IHPhu5EgZ8OzaSBjxakgdHJvbmcgUiwgxJHhurdjIGJp4buHdCBsw6AgY8OhYyBnw7NpIGtow7RuZyBjw7JuIMSRxrDhu6NjIHBow6F0IHRyaeG7g24gdsOgIGPhuq1wIG5o4bqtcC4NCg0KIyMgNS4zIEvhur90IGx14bqtbg0KDQomZW5zcDsmZW5zcDsmZW5zcDtUcm9uZyBxdcOhIHRyw6xuaCBuZ2hpw6puIGPhu6l1IHbDoCB0aOG7sWMgaGnhu4duIMSR4buBIHTDoGkgbsOgeSwgZW0gxJHDoyBraMOhbSBwaMOhIHPDonUgaMahbiB24buBIHBhY2thZ2UgVGliYmxlIHbDoCBo4bupbmcgdGjDuiBoxqFuIHbhu5tpIHPhu7EgdGnhu4duIMOtY2ggbcOgIG7DsyBtYW5nIGzhuqFpIHRyb25nIHZp4buHYyB44butIGzDvSB2w6AgcXXhuqNuIGzDvSBk4buvIGxp4buHdS4gVGliYmxlIGtow7RuZyBjaOG7iSBsw6AgbeG7mXQgcGhpw6puIGLhuqNuIGPhuqNpIHRp4bq/biBj4bunYSBkYXRhLmZyYW1lLCBtw6AgY8OybiBsw6AgbeG7mXQgY8O0bmcgY+G7pSBsaW5oIGhv4bqhdCB2w6AgaGnhu4d1IHF14bqjIGjGoW4gdHJvbmcgdmnhu4djIGzDoG0gdmnhu4djIHbhu5tpIGThu68gbGnhu4d1IHRyb25nIG3DtGkgdHLGsOG7nW5nIFIuDQoNCiZlbnNwOyZlbnNwOyZlbnNwO05o4buvbmcgxrB1IMSRaeG7g20gxJHDoW5nIGNow7ogw70gY+G7p2EgVGliYmxlIMSRw6MgdGjhu4MgaGnhu4duIHLDtSByw6BuZyBxdWEgdmnhu4djIGdpw7pwIHRp4bq/dCBraeG7h20gYuG7mSBuaOG7mywgdMSDbmcgdOG7kWMgxJHhu5kgeOG7rSBsw70gZOG7ryBsaeG7h3UgdsOgIHRyw6FuaCDEkcaw4bujYyBuaOG7r25nIGzhu5dpIHRoxrDhu51uZyBn4bq3cCBraGkgc+G7rSBk4bulbmcgZGF0YS5mcmFtZS4gU+G7sSBsaW5oIGhv4bqhdCB2w6Aga2jhuqMgbsSDbmcgY2h1eeG7g24gxJHhu5VpIGxpbmggaG/huqF0IGdp4buvYSBkYXRhLmZyYW1lIHbDoCBUaWJibGUgxJHDoyBnacO6cCBlbSBk4buFIGTDoG5nIHTDrWNoIGjhu6NwIFRpYmJsZSB2w6BvIGPDoWMgZOG7sSDDoW4gcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgaGnhu4duIGPDsy4NCg0KJmVuc3A7JmVuc3A7JmVuc3A7VGjDoG5oIGPDtG5nIGPhu6dhIFRpYmJsZSBjxaluZyBu4bqxbSDhu58ga2jhuqMgbsSDbmcgaOG7lyB0cuG7oyB04buRdCB04burIGPhu5luZyDEkeG7k25nIHbDoCBz4buxIGxpw6puIHThu6VjIGPhuqNpIHRp4bq/biwgZ2nDunAgYuG6o28gxJHhuqNtIHTDrW5oIOG7lW4gxJHhu4tuaCB2w6AgcGjDuSBo4bujcCB24bubaSBuaHUgY+G6p3UgY+G7p2EgbmfGsOG7nWkgZMO5bmcuIFZp4buHYyB0w61jaCBo4bujcCBjw6FjIHTDrW5oIG7Eg25nIHRp4buHbiDDrWNoIG5oxrAgdmnhu4djIHjhu60gbMO9IGThu68gbGnhu4d1IHRow7QsIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IG3DoCBraMO0bmcgY+G6p24gY2h1eeG7g24gxJHhu5VpIHbhu4EgZOG6oW5nIGRhdGEuZnJhbWUgxJHDoyB0aMO6YyDEkeG6qXkgcXXDoSB0csOsbmggbMOgbSB2aeG7h2MgY+G7p2EgZW0gbeG7mXQgY8OhY2ggaGnhu4d1IHF14bqjIHbDoCBoaeG7h3UgbmdoaeG7h20uDQoNCiZlbnNwOyZlbnNwOyZlbnNwO1R1eSDEkeG7gSB0w6BpIG7DoHkgY2jhu4kgdOG6rXAgdHJ1bmcgdsOgbyBwYWNrYWdlIFRpYmJsZSwgbmjGsG5nIHThu6sgbmjhu69uZyBraeG6v24gdGjhu6ljIHbDoCBraW5oIG5naGnhu4dtIHRodSB0aOG6rXAgxJHGsOG7o2MsIGVtIGPDsyBjw6FpIG5ow6xuIHThu5VuZyBxdWFuIGjGoW4gduG7gSBxdXkgdHLDrG5oIHjhu60gbMO9IGThu68gbGnhu4d1IHRyb25nIFIuIFBhY2thZ2UgVGliYmxlIMSRw6MgbeG7nyByYSBjw6FuaCBj4butYSBt4bubaSBjaG8gZW0gdsOgIGNo4bqvYyBjaOG6r24gc+G6vSB0aeG6v3AgdOG7pWMgxJHGsOG7o2Mgw6FwIGThu6VuZyB0cm9uZyBuaOG7r25nIGThu7Egw6FuIHTGsMahbmcgbGFpLg0KDQomZW5zcDsmZW5zcDsmZW5zcDtDdeG7kWkgY8O5bmcsIHZp4buHYyB0aOG7sWMgaGnhu4duIMSR4buBIHTDoGkgbsOgeSDEkcOjIGdpw7pwIGVtIG7Dom5nIGNhbyBr4bu5IG7Eg25nIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IHbDoCBsw6BtIHZp4buHYyBoaeG7h3UgcXXhuqMgduG7m2kgUi4gRW0gcuG6pXQgaMOgaSBsw7JuZyB24bubaSBr4bq/dCBxdeG6oyDEkeG6oXQgxJHGsOG7o2MgdsOgIGh5IHbhu41uZyBy4bqxbmcgYsOgaSB2aeG6v3QgbsOgeSBz4bq9IGjhu5cgdHLhu6MgdsOgIGtoxqFpIGfhu6NpIHPhu7EgcXVhbiB0w6JtIGPhu6dhIG5o4buvbmcgbmfGsOG7nWkgcXVhbiB0w6JtIMSR4bq/biB2aeG7h2MgeOG7rSBsw70gZOG7ryBsaeG7h3UgdHJvbmcgbcO0aSB0csaw4budbmcgUi4NCg0KIyAqKlTDoGkgbGnhu4d1IHRoYW0ga2jhuqNvKioNCg0KaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3RpYmJsZS92ZXJzaW9ucy8zLjIuMQ0KDQpodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdGliYmxlL3RpYmJsZS5wZGYNCg0KDQo=