CHƯƠNG 1: GIỚI THIỆU ĐỀ
TÀI
Đặt vấn đề nghiên
cứu
Hiện nay, nhiều lĩnh vực đã áp dụng phân tích dữ liệu vào trong quá
trình nghiên cứu để có thể đạt được kết quả tốt hơn và độ chính xác cao
hơn. Tuy nhiên, dữ liệu được thu thập thường rất lớn, phức tạp, cấu trúc
không phù hợp hoặc có thể bị thiếu dữ liệu cho nên không thể nào đưa vào
mô hình phân tích ngay lập tức. Do đó, các nhà nghiên cứu cần phải xử lí
và biến đổi cấu trúc dữ liệu sao cho phù hợp với mục tiêu nghiên cứu, có
thể nói đây chính là một phần khá phức tạp và mất nhiều thời gian trong
một công trình nghiên cứu bởi vì bộ dữ liệu quá lớn và chứa nhiều biến
khác nhau chưa đáp ứng được nhu cầu của người sử dụng. Chính vì thế, họ
luôn tìm kiếm cho mình một công cụ tối ưu để dễ dàng chuẩn hóa và làm
sạch dữ liệu đồng thời tiết kiệm thời gian, công sức mà vẫn đạt hiệu quả
cao.
Nhận thấy vấn đề được nói trên chúng em thực hiện nghiên cứu về gói
“Tidyr”, đây là một công cụ mãnh mẽ hỗ trợ mọi người có thể chuẩn hóa,
biến đổi cấu trúc dữ liệu dựa vào định dạng tidy data, trong đó thì mỗi
cột dữ liệu đại diện cho một biến, mỗi hàng đại diện cho một quan sát và
mỗi ô thì chứa một giá trị cụ thể điều này sẽ giúp việc phân tích và
trực quan hóa dữ liệu trở nên dễ dàng hơn. Hơn thế, nó cũng có thể hỗ
trợ tách, ghép và hoàn chỉnh dữ liệu còn thiếu bằng những cú pháp đơn
giản, rõ ràng từ đó mọi người có thể tiến hành phân tích các mô hình.
Gói Tidyr là một công cụ tối ưu, đa năng, cú pháp đơn giản và nhận được
sử hỗ trợ phát triển từ cộng đồng R, vì thế nó có thể giải quyết nhiều
vấn đề trong quá trình xử lý dữ liệu trong nhiều lĩnh vực. Chẳng hạn như
trong tài chính gói tidyr có thể giúp chúng ta tổ chức và sắp xếp lại dữ
liệu về cổ phiểu của một ngành để đánh giá tình hình hoạt động và xây
dựng mô hình dự báo. Trong lĩnh vực kinh tế thì nó giúp biến đổi dữ liệu
về GDP, thương mại, sản xuất và một số chỉ số kinh tế khác của các quốc
gia theo năm để đánh giá tốc độ phát triển và tổng quan về mối quan hệ
kinh tế giữa các quốc gia. Qua đó, ta thấy rằng lợi ích mà gói Tidyr
mang lại trong giai đoạn chuẩn hóa dữ liệu là vô cùng to lớn, tiết kiệm
được rất nhiều thời gian và cung cấp kết quả phân tích có độ chính xác
cao hơn.
Lý do chọn đề
tài
Trong quá trình thực hành với nhiều dữ liệu phức tạp nhóm em nhận
thấy việc xử lý dữ liệu gặp nhiều khó khăn, ảnh hưởng đến kết quả cũng
như là thời gian thực hiện. Nghiên cứu về gói Tidyr sẽ giúp việc chuẩn
hóa và biến đổi cấu trúc dữ liệu trở nên dễ dàng hơn, các cú pháp tương
đối đơn giản và rõ ràng không đòi hỏi kiến thức chuyên sâu. Ngoài ra,
Tidyr cung cấp cho người sử dụng rất nhiều chức năng khác nhau, nó giúp
người dùng dễ dàng xử lý dữ liệu không đồng nhất, không cấu trúc hoặc
thiếu dữ liệu, tạo điều kiện thuận lợi cho việc phân tích và trực quan
hóa dữ liệu. Cộng đồng R là một cộng đồng lớn về ngôn ngữ lập trình, họ
thường xuyên cập nhập, phát triển gói Tidyr ngày càng tối ưu hơn, điều
này khiến cho nhóm em học tập thêm nhiều kiến thức về phân tích dữ liệu
và sử dụng gói này một cách hiệu quả nhất trong công việc trong tương
lai. Hơn thế, Tidyr được thiết kế dùng để giải quyết các vấn đề phổ biến
và thực tế ở nhiều lĩnh vực khác nhau, mặc dù dữ liệu nghiên cứu kích
thước lớn thì nó vẫn xử lý hiệu quả và tiết kiệm được nhiều thời gian.
Vì thế, nhóm em tin rằng tìm hiểu về gói Tidyr là chủ đề hữu ích có thể
hỗ trợ mọi người đang gặp khó khăn trong việc xử lý dữ liệu.
Giới thiệu về gói
Tidyr
Nguồn gốc
Gói tidyr là một phần của Tidyverse, một bộ sưu tập các gói R được
thiết kế cho việc xử lý và phân tích dữ liệu. Gói tidyr tập trung chủ
yếu vào các hoạt động làm gọn gàng và cấu trúc lại dữ liệu, giúp dễ dàng
chuyển đổi tập dữ liệu thành định dạng tidy (gọn gàng) thuận tiện hơn
cho phân tích và trực quan hóa.
Gói tidyr được phát triển bởi Hadley Wickham, một nhà thống kê và nhà
khoa học dữ liệu nổi tiếng với đóng góp cho ngôn ngữ lập trình R và khái
niệm dữ liệu tidy. Hadley Wickham cũng là người sáng tạo ra các gói phổ
biến khác như ggplot2 và dplyr. Ông đã phát triển tidyr như một phần của
nỗ lực của mình để thúc đẩy nguyên tắc của dữ liệu tidy, nhấn mạnh việc
tổ chức và sắp xếp dữ liệu theo một cấu trúc nhất quán để tạo thuận lợi
cho phân tích và truyền tải thông tin.
Chức năng
Gói tidyr cung cấp một loạt các hàm hỗ trợ chúng ta trong việc làm
gọn và tái cấu trúc dữ liệu. Các hàm này có thể được nhóm thành một số
danh mục chính, mỗi danh mục phục vụ cho một mục đích cụ thể trong việc
chỉnh sửa và tổ chức dữ liệu.
Tách dữ liệu
Trong gói tidyr hỗ trợ người dùng tách dữ liệu một cột thành nhiều
cột dựa trên những ký tự phân tách hoặc các mẫu bằng hàm
separate, điều này thực sự hữu ích khi bạn có một cột chứa
các giá trị kết hợp với nhau làm cho việc phân tích gặp nhiều khó khăn
và bạn muốn phân tách nó ra thành những cột riêng biệt. Chẳng hạn, một
cột chứa thông tin về ngày tháng năm sinh để biết chi tiết hơn ta có thể
sử dụng hàm separate để tách riêng làm ba cột ngày, tháng, năm để phục
vụ cho mục đích công việc cụ thể. Ngoài ra, chức năng này không làm thay
đổi dữ liệu gốc mà chỉ tạo ra các cột mới từ dữ liệu ban đầu, điều này
cho phép chúng ta biến đổi về dữ liệu gốc dễ dàng hơn nếu muốn.
Kết hợp cột
Trái ngược với chức năng tách cột, gói Tidyr sẽ giúp chúng ta kết hợp
các cột lại thành một cột bằng cách ghép các giá trị của chúng lại với
nhau. Giả sử ta có một cột chứa họ và một cột chứa tên thì có thể ghép
hai cột này thành một cột họ và tên hoàn chỉnh bằng hàm
unite, điều này sẽ giúp dữ liệu trở nên gọn gàng và phù hợp
để sử dụng. Đây là một chức năng dễ dàng sử dụng tuy nhiên tạo ra cột
mới có độ linh hoạt cao, thuận tiện trong quá trình xử lý.
Pivoting(Biến
đổi)
“Pivoting” (Chuyển đổi): chuyển đổi giữa các dạng dữ liệu rộng và
dài. tidyr giới thiệu pivot_longer() và pivot_wider(), thay thế các hàm
spread() và gather(). Quá trình biến đổi này đặc biệt hữu ích khi bạn
cần thay đổi cấu trúc dữ liệu để phù hợp hơn với mục đích phân tích hoặc
trực quan hóa.
Biến đổi từ dạng Dài sang Rộng: Khi dữ liệu ở định dạng dài, mỗi
quan sát được biểu diễn bằng nhiều hàng và có các cột xác định riêng
biệt liên kết những hàng này lại với nhau. Do đó, hàm pivot_wider() sẽ
giúp ta chuyển đổi dữ liệu từ định dạng dài sang định dạng rộng bằng
cách phân rải giá trị, điều này phụ thuộc vào mục tiêu phân tích bộ dữ
liệu của người sử dụng.
Biến đổi từ dạng Rộng sang Dài: Ngược lại, khi dữ liệu ở định
dạng rộng, mỗi quan sát được biểu diễn bằng một hàng đơn và các biến
khác nhau được lưu trữ trong các cột riêng biệt. Hàm pivot_longer() sẽ
giúp Chuyển đổi dữ liệu từ định dạng rộng sang định dạng dài bằng cách
gom lại các cột để có thể phù hợp với nhu cầu của người thực
hiện.
Xử lí giá trị
thiếu
Việc phân tích dữ liệu sẽ không đạt được kết quả chính xác nếu dữ
liệu gặp phải những giá trị bị thiếu sót, để khắc phục tình trạng như
vậy thì gói này giúp người sử dụng xử lý những dòng bị thiếu giá trị
bằng hàm complete, hàm này sẽ kết hợp các giá trị không bị
thiếu trong các cột chỉ định từ đó điền vào những dòng bị thiếu. Hơn
nữa, ta có thể loại bỏ các giá trị thiếu bằng hàm drop_na hoặc thay thế
các giá trị bị thiếu bằng hàm fill,
replace_na.
Nesting(Gộp) và
Unnesting(khôi phục)
Nest() được sử dụng để tạo một khung dữ liệu lồng nhau bằng cách nhóm
dữ liệu dựa trên các biến cụ thể. Nó cho phép bạn nhóm các quan sát liên
quan với nhau trong một cột duy nhất.
Unnest() được sử dụng để mở rộng một khung dữ liệu lồng nhau thành
một khung dữ liệu thông thường, trong đó mỗi quan sát lồng nhau trở
thành một dòng riêng. Nó trích xuất dữ liệu lồng nhau và mở rộng chúng
thành nhiều dòng.
Mục tiêu
Mục tiêu chính của tidyr là cung cấp một bộ công cụ với các chức năng
đơn giản hóa quá trình cấu trúc lại và làm gọn dữ liệu. Gói này cung cấp
các chức năng như gather(), spread(), separate(), unite(),
pivot_longer() và pivot_wider(), cho phép người dùng chuyển đổi dữ liệu
giữa các định dạng rộng và dài, phân tách và kết hợp cột, và chuyển đổi
dữ liệu để tạo bảng tóm tắt. Các hoạt động này là cần thiết để tổ chức
và xử lý dữ liệu một cách dễ dàng và trích xuất thông tin.
Gói tidyr đã thu hút sự quan tâm đáng kể trong cộng đồng R nhờ cú
pháp dễ hiểu và nhất quán, phù hợp với nguyên tắc của Tidyverse. Nó đã
trở thành một công cụ được sử dụng rộng rãi để làm sạch dữ liệu, tiền xử
lý và cấu trúc lại trong quy trình phân tích dữ liệu bằng R.
Lợi ích
Các lợi ích của việc sử dụng gói tidyr bao gồm:
Dễ dàng làm sạch dữ liệu: Gói tidyr cung cấp các hàm đơn giản và
dễ hiểu để cấu trúc lại và làm gọn dữ liệu. Nó cung cấp các chức năng
như gather(), spread(), separate(), unite(), pivot_longer(), và
pivot_wider() cho phép người dùng dễ dàng chuyển đổi dữ liệu giữa các
định dạng rộng và dài, phân tách và kết hợp cột, và biến đổi dữ liệu để
tạo bảng tóm tắt. Những thao tác này là cần thiết để tổ chức và xử lý dữ
liệu một cách hiệu quả.
Tích hợp với tidyverse: Gói tidyr là một phần của hệ sinh thái
tidyverse, là một bộ sưu tập các gói R được thiết kế cho việc làm sạch
và phân tích dữ liệu. Nó tích hợp một cách mượt mà với các gói tidyverse
khác như dplyr và ggplot2, cho phép quy trình làm việc mượt mà và cú
pháp nhất quán. Tích hợp này cho phép người dùng thực hiện các thao tác
phức tạp trên dữ liệu và tạo biểu đồ một cách nhất quán và hiệu
quả.
Tương thích với nguyên tắc dữ liệu tidy: Gói tidyr tuân thủ
nguyên tắc của dữ liệu tidy, nhấn mạnh việc tổ chức dữ liệu theo một cấu
trúc nhất quán. Bằng cách tuân thủ nguyên tắc dữ liệu tidy, người dùng
có được dữ liệu rõ ràng hơn, dễ khám phá hơn và kết quả phân tích đáng
tin cậy hơn. Dữ liệu tidy đảm bảo mỗi biến có một cột riêng, mỗi quan
sát có một hàng riêng và mỗi ô chứa một giá trị duy nhất.
Hỗ trợ phân tích và trực quan hóa dữ liệu: Dữ liệu tidy đơn giản
hóa quá trình phân tích và trực quan hóa dữ liệu. Bằng cách chuyển đổi
dữ liệu thành định dạng tidy, việc thực hiện các tác vụ phân tích dữ
liệu thông thường, áp dụng phân tích thống kê và tạo biểu đồ thông tin
trở nên dễ dàng hơn. Dữ liệu tidy giảm thiểu việc phải làm việc phức tạp
với dữ liệu, cho phép các nhà phân tích tập trung nhiều hơn vào việc
trích xuất thông tin và đưa ra quyết định dựa trên dữ liệu.
Tóm lại, mục tiêu chính của gói tidyr là cung cấp các công cụ để làm
sạch và cấu trúc lại dữ liệu, với lợi ích là giúp người dùng dễ dàng
chuyển đổi dữ liệu thành định dạng tidy. Điều này hỗ trợ phân tích dữ
liệu, tích hợp với các gói tidyverse khác và hỗ trợ nguyên tắc dữ liệu
tidy để hiểu dữ liệu tốt hơn và tạo quy trình làm việc hiệu quả
Ưu và nhược điểm
của gói tidyr
Ưu điểm của gói
tidyr
Đơn giản hóa việc xử lý dữ liệu: tidyr cung cấp một bộ công cụ với
các hàm dễ hiểu giúp đơn giản hóa công việc cấu trúc lại và làm sạch dữ
liệu. Nó cung cấp các hàm như gather(), spread(), separate(), unite(),
pivot_longer() và pivot_wider() cho phép người dùng dễ dàng chuyển đổi
dữ liệu giữa các định dạng rộng và dài, phân tách và kết hợp cột, và
biến đổi dữ liệu để tạo bảng tóm tắt. Những hoạt động này là cần thiết
để tổ chức và xử lý dữ liệu một cách hiệu quả.
Tích hợp với tidyverse: tidyr là một phần của hệ sinh thái tidyverse,
một bộ sưu tập các gói R được thiết kế để làm sạch và phân tích dữ liệu.
Nó tích hợp một cách mượt mà với các gói tidyverse khác như dplyr và
ggplot2, cho phép quy trình làm việc trơn tru và có cú pháp nhất quán.
Tích hợp này cho phép người dùng thực hiện các phép toán phức tạp trên
dữ liệu và tạo biểu đồ một cách nhất quán và hiệu quả.
Tuân thủ nguyên tắc dữ liệu tidy: tidyr tuân thủ các nguyên tắc của
dữ liệu tidy, nhấn mạnh việc tổ chức dữ liệu thành một cấu trúc nhất
quán. Bằng việc tuân thủ nguyên tắc dữ liệu tidy, người dùng có dữ liệu
rõ ràng hơn, khám phá dữ liệu hiệu quả hơn và kết quả phân tích đáng tin
cậy hơn. Dữ liệu tidy đảm bảo rằng mỗi biến có một cột riêng, mỗi quan
sát có một hàng riêng, và mỗi ô chứa một giá trị duy nhất.
Nhược điểm của
gói tidyr
Giới hạn chức năng: Mặc dù tidyr cung cấp một tập hợp hữu ích các hàm
để cấu trúc lại và làm sạch dữ liệu, nhưng nó có thể không đáp ứng được
tất cả các tình huống xử lý dữ liệu khác nhau. Có thể có những trường
hợp yêu cầu các phép toán phức tạp hoặc đặc thù hơn và tidyr có thể
không có các hàm dành riêng cho những nhiệm vụ đó.
Khó khăn trong quá trình học tập: Giống như bất kỳ gói hay công cụ
mới nào, việc sử dụng tidyr một cách hiệu quả cũng có thể gặp khó khăn
ban đầu. Người dùng cần làm quen với cú pháp và các hàm cụ thể của tidyr
để tận dụng tối đa khả năng của nó. Quá trình học này có thể yêu cầu một
khoảng thời gian và nỗ lực nhất định.
Phụ thuộc vào tidyverse: Mặc dù việc là một phần của tidyverse mang
lại nhiều lợi ích, nhưng đồng thời cũng có thể là một hạn chế đối với
những người dùng ưa thích hoặc phụ thuộc vào các gói xử lý dữ liệu khác
nằm ngoài hệ sinh thái tidyverse. Sử dụng tidyr trong quy trình làm việc
dựa trên tidyverse có thể yêu cầu sự chuyển đổi sang các gói tidyverse
khác, điều này có thể không phù hợp với mọi người.
Đóng góp của đề
tài
Bài tiểu luận của nhóm em đóng góp cho cộng đồng sử dụng R trong việc
áp dụng gói Tidyr vào việc phân tích dữ liệu ở một số khía cạnh quan
trọng.
Đầu tiên, chúng em đã giới thiệu chi tiết về gói Tidyr, bao gồm các
chức năng, lợi ích, phương pháp và cách thức thực hiện các hàm quan
trọng trong gói Tidyr, điều này giúp cho mọi người có cái nhìn tổng quan
nhất về nó.
Thứ hai, chúng em áp dụng vào việc phân tích dữ liệu tài chính qua đó
làm nổi bật tính ứng dụng của Tidyr trong các lĩnh vực, cũng như nhấn
mạnh sự tiện ích và hiệu quả của nó trong việc giúp người dùng tiết kiệm
thời gian và nỗ lực trong công việc xử lý dữ liệu.
Cuối cùng, nhóm phân tích được tiềm năng và hạn chế của Tidyr, qua đó
giúp cho những người phân tích dữ liệu sử dụng hiệu quả nhất gói này vào
trong công việc của họ.
Kết cấu
Chương 1: Giới thiệu đề tài
Giới thiệu tổng quan về tầm quan trọng của việc thực hiện đề tài
nghiên cứu gói tidyr trong R, đưa ra những lý do để chọn chủ đề này và
nêu những nội dung quan trọng của gói tidyr.
Chương 2: Thực hành các hàm trong tidyr
Chương hai sẽ trình bày cụ thể chức năng các hàm trong gói tidyr và
đưa ra những ví dụ cụ thể để hướng dẫn thực hành.
Chương 3: Ứng dụng của tidyr
Dựa vào các chức năng của các hàm được trình bày trong chương 2 sau
đó được áp dụng lên những dữ liệu lớn hơn và có cấu trúc khó hơn bằng
cách kết hợp thêm một số gói khác như dplyr. Sau khi chuẩn hóa dữ liệu
thì thực hiện tính thóa và trực quan hóa dữ liệu
Chương 4: Kết luận
Chương cuối sẽ kết luận những kết quả thu được trong bài này, đưa ra
những hạn chế trong quá trình nghiên cứu và đề xuất phương hướng làm
tiếp theo.
CHƯƠNG 2: THỰC HÀNH CÁC
HÀM TRONG TIDYR
Trong chương hai nhóm chúng tôi thực hiện các lệnh trong gói Tidyr để
giúp người đọc có thể hiểu rõ các chức năng trong gói này. Từ đó, những
người quan tâm đến gói Tidyr áp dụng các hàm vào công việc xử lí bộ dữ
liệu của họ nhanh chóng hơn. Việc giới thiệu chi tiết về sử dụng gói
Tidyr thông qua việc thực hành trên dữ liệu mẫu là nền tảng quan trọng
để nhóm chúng tôi có thể ứng dụng Tidyr ở các phần sau
Biến đổi dữ liệu
(Pivoting)
Chuyển dữ liệu sang
dạng dài
Hàm pivot_longer hỗ trợ chúng ta chuyển đổi dữ liệu từ dạng rộng
(wide format) sang dạng dài (long format). Việc biến đổi cấu trúc dữ
liệu có ý nghĩa khi người phân tích muốn xử lý trên dữ liệu dạng dài để
có thể thao tác dễ dàng và đạt nhiều hiệu quả hơn dạng rộng.
Chức năng pivot_longer() có một số tham số quan trọng như sau:
data: Tham số này yêu cầu dữ liệu mà chúng ta muốn chuyển đổi từ
dạng rộng sang dạng dài.
cols: tham số này là danh sách các cột mà ta muốn chuyển đổi. Ta
có thể chỉ định tên cột cụ thể trong data hoặc sử dụng các hàm để lựa
chọn các cột theo những tiêu chí mà chúng ta muốn
names_to: Tên của cột mới sẽ lưu trữ các tên biến sau khi chuyển
đổi sang dạng dữ liệu dài.
values_to: Tên của cột mới mà sẽ chứa các giá trị biến sau khi
chuyển đổi.
Trước khi thực hành hàm pivot_longer tôi sẽ gọi một dữ liệu mẫu trong
gói Tidyr đó chính là table4b, dữ liệu này gồm dân số của 3 quốc gia
Afghanistan, Brazil, China trong hai năm 1999,2000.
library(tidyr)
library(tidyverse)
table4b
## # A tibble: 3 × 3
## country `1999` `2000`
## <chr> <dbl> <dbl>
## 1 Afghanistan 19987071 20595360
## 2 Brazil 172006362 174504898
## 3 China 1272915272 1280428583
Từ table4b với mục đích biến đổi các năm về cùng một cột và giá trị
về một cột chung với nhau, ta có thể thực hiện lệnh pivot_longer với dữ
liệu ban đầu muốn chuyển đổi sang dạng dài là table4b, tham số ‘cols’
chỉ định các cột muốn chuyển đổi là cột từ “1999” đến “2000”, tham số
names_to được sử dụng để đặt tên cột mới chứa các biến với
là “year” và tham số values_to đặt tên cho cột chứa các giá
trị biến tương ứng là values.
pivot_longer(table4b,cols= '1999':'2000',
names_to = "year",
values_to = "values")
## # A tibble: 6 × 3
## country year values
## <chr> <chr> <dbl>
## 1 Afghanistan 1999 19987071
## 2 Afghanistan 2000 20595360
## 3 Brazil 1999 172006362
## 4 Brazil 2000 174504898
## 5 China 1999 1272915272
## 6 China 2000 1280428583
Như kết quả sau khi chuyển đổi bên trên ta sẽ có được một dữ liệu
dạng dài với mỗi dòng cho biết về tên quốc gia, năm khảo sát và dân số
tương ứng.
Chuyển dữ liệu sang
dạng rộng
Hàm pivot_wider có chức năng biến đổi dạng dữ liệu dài
sang dữ liệu rộng sao cho phù hợp với mục tiêu của người sử dụng. Hàm
này có thao tác khá đơn giản tuy nhiên mang lại rất nhiều lợi ích trong
quá trình làm việc của mọi người. Pivot_wider có các tham số chính như
sau:
data: Dữ liệu dùng để chuyển sang dữ liệu dạng rộng
names_from: Tên cột hoặc biến mà ta muốn biến đổi thành các cột
mới.
values_from: Tên cột hoặc biến chứa các giá trị tương ứng với các
cột mới.
Dữ liệu được sử dụng để thực hiện hàm pivot_wider là
table2, đây là dữ liệu mẫu trong gói Tidyr chứa thông tin về quốc gia,
năm, loại số liệu về dân số, trường hợp mắc bệnh và số người tương
ứng.
table2
## # A tibble: 12 × 4
## country year type count
## <chr> <dbl> <chr> <dbl>
## 1 Afghanistan 1999 cases 745
## 2 Afghanistan 1999 population 19987071
## 3 Afghanistan 2000 cases 2666
## 4 Afghanistan 2000 population 20595360
## 5 Brazil 1999 cases 37737
## 6 Brazil 1999 population 172006362
## 7 Brazil 2000 cases 80488
## 8 Brazil 2000 population 174504898
## 9 China 1999 cases 212258
## 10 China 1999 population 1272915272
## 11 China 2000 cases 213766
## 12 China 2000 population 1280428583
Đầu tiên, ta cần khai báo dữ liệu dùng để chuyển đổi là table2, phép
toán tử giúp truyền kết quả của table2 phía trước thành đối tượng đầu
vào của hàm pivot_wider. Tham số names_from trong trường
hợp này được khai báo là type để chỉ ra tên cột dùng để biến đổi thành
các cột mới trong dữ liệu rộng, mỗi giá trị trong biến type sẽ là một
cột mới. values_from được chỉ định là biến count để chỉ ra
các giá trị tương ứng với các cột mới
table2 %>% pivot_wider(names_from = type, values_from = count)
## # A tibble: 6 × 4
## country year cases population
## <chr> <dbl> <dbl> <dbl>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
Chuyển đổi cấu trúc dữ liệu table2 sang dạng dữ liệu rộng giúp ta dễ
dàng đánh giá các trường hợp mắc bệnh và dân số của các quốc gia qua
từng năm. Ngoài ra, việc chuyển đổi cấu trúc cũng giúp thực hiện phân
tích theo từng biến và trực quan hóa dữ liệu tốt hơn.
Tách cột
Chức năng tách một cột thành nhiều cột dựa trên những ký tự phân tách
sẽ là một công cụ tốt để chúng ta có thể xử lý dữ liệu của mình khi mà
một cột chứa nhiều giá trị kết hợp với nhau. Việc phân tách cột không
yêu cầu nhiều thao tác nhưng vẫn đảm bảo được độ chính xác so với dữ
liệu ban đầu, thao tác này có thể được coi là một trong những bước xử lý
chuỗi phức tạp. Dữ liệu sau khi được tách cột sẽ đem lại thông tin chi
tiết hơn để có thể phân tích, so sánh, trực quan hóa dữ liệu. Trong
Tidyr để tách cột thì ta dùng hàm separate() với những tham
số chính cần phải lưu ý như
data: Dữ liệu ban đầu.
col: Tên cột cần tách.
into: Tên các cột mới được tạo ra sau khi tách.
sep: Ký tự phân tách hoặc mẫu được sử dụng để tách cột.
remove: Xác định xem cột ban đầu cần được loại bỏ sau khi tách
hay không, mặc định là TRUE.
convert: Xác định xem các cột mới cần được chuyển đổi thành kiểu
dữ liệu phù hợp hay không, mặc định là FALSE.
Dữ liệu đầu vào dùng để tách cột là table3, dữ liệu này có cột rate
dùng ký tự / để tính tỷ lệ người mắc bệnh trên dân số của một quốc gia.
Ta có thể dùng hàm separate() để tách cột rate thành một
cột chứa số liệu về số người mắc bệnh và một cột chứa số liệu về dân
số.
table3
## # A tibble: 6 × 3
## country year rate
## <chr> <dbl> <chr>
## 1 Afghanistan 1999 745/19987071
## 2 Afghanistan 2000 2666/20595360
## 3 Brazil 1999 37737/172006362
## 4 Brazil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
Để thực hiện việc tách cột trước tiên chúng ta cần khai báo dữ liệu
đầu vào là table3, chọn cột cần tách trong tham số col là
cột rate, ở tham số into ta có thể đặt tên cho các cột mới
là “case” và “population”, tiếp theo sep chỉ ra ký tự dùng
để phân tách trong dữ liệu của chúng ta đó là “/”.
separate(data = table3, col= rate, into= c("case","population"),sep = "/")
## # A tibble: 6 × 4
## country year case population
## <chr> <dbl> <chr> <chr>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
Kết quả từ câu lệnh trên sẽ tạo ra hai cột mới là case và population
dựa vào cột rate ban đầu. Điều này sẽ giúp ta quan sát được số trường
hợp mắc bệnh và dân số của một quốc gia một cách chi tiết hơn và sau đó
có thể dễ dàng dùng nó trong các công việc khác.
separate(data = table3 , col = rate, into = c("case", "population"), remove = FALSE, convert = TRUE )
## # A tibble: 6 × 5
## country year rate case population
## <chr> <dbl> <chr> <int> <int>
## 1 Afghanistan 1999 745/19987071 745 19987071
## 2 Afghanistan 2000 2666/20595360 2666 20595360
## 3 Brazil 1999 37737/172006362 37737 172006362
## 4 Brazil 2000 80488/174504898 80488 174504898
## 5 China 1999 212258/1272915272 212258 1272915272
## 6 China 2000 213766/1280428583 213766 1280428583
Ngoài ra, ta có thể thêm vào tham số remove là FALSE để
giữ nguyên cột rate ban đầu và tham số convert bằng TRUE để
xác định chuyển đổi thành kiểu dữ liệu phù hợp
Kết hợp cột
Ở bước làm sạch dữ liệu, chúng ta thường xuyên gặp phải các cột dữ
liệu được tách ra riêng biệt và khi kết hợp chúng lại với nhau thì có
thể được một cột dữ liệu hoàn chỉnh và gọn gàng hơn trước rất nhiều. Gói
Tidyr bao gồm hàm unite() có thể dùng để kết hợp nhiều cột
thành một cột bằng cách ghép các giá trị của chúng lại với nhau. Cấu
trúc của dữ liệu sau khi biến đổi sẽ trở nên đơn giản, ít cột và mang ý
nghĩa tổng quan hơn so với dữ liệu ban đầu. Những tham số chính trong
hàm unite() được giải thích dưới đây:
data: Khung dữ liệu
col : Tên của cột mới được tạo, tên của các cột được hợp nhất sắp
xếp theo trật tự
sep: Dấu phân cách giữa hai giá trị
remove: Nếu là TRUE sẽ xóa bỏ các cột dữ liệu ban đầu sau khi gộp
lại thành cột mới
na.rm: Nếu là TRUE thì sẽ loại bỏ các giá trị bị thiếu trước khi
kết hợp
Bảng dữ liệu table5 bên dưới có hai cột riêng biệt chứa giá trị về
thế kỉ và năm, chúng ta kết hợp hai cột này thành một để có được số liệu
năm hoàn chỉnh.
table5
## # A tibble: 6 × 4
## country century year rate
## <chr> <chr> <chr> <chr>
## 1 Afghanistan 19 99 745/19987071
## 2 Afghanistan 20 00 2666/20595360
## 3 Brazil 19 99 37737/172006362
## 4 Brazil 20 00 80488/174504898
## 5 China 19 99 212258/1272915272
## 6 China 20 00 213766/1280428583
Trong hàm unite() khung dữ liệu được khai báo là table5,
tên của cột mới sau khi kết hợp lại được đặt là “newyear” và các cột
dùng để ghép lại được chỉ định lần lượt là cột century, year. Đối số
sep yêu cầu dấu phân cách sau khi ghép các giá trị lại,
trong trường hợp này tôi sử dụng “” là không có khoảng cách sau khi kết
hợp hai dữ liệu. remove cho bằng FALSE là sẽ không loại bỏ
các cột ban đầu sau khi kết hợp cột.
unite(data = table5, col= newyear , century , year, sep="",remove = FALSE)
## # A tibble: 6 × 5
## country newyear century year rate
## <chr> <chr> <chr> <chr> <chr>
## 1 Afghanistan 1999 19 99 745/19987071
## 2 Afghanistan 2000 20 00 2666/20595360
## 3 Brazil 1999 19 99 37737/172006362
## 4 Brazil 2000 20 00 80488/174504898
## 5 China 1999 19 99 212258/1272915272
## 6 China 2000 20 00 213766/1280428583
Sau khi kết hợp century và year ta được cột mới tên là newyear chứa
các giá trị năm được ghép từ các giá trị trong hai cột trước đó. Từ đó,
ta có thể sử dụng cột mới được tạo ra để làm các thao tác khác, chẳng
hạn như vẽ đồ thị hay dùng để tính toán dựa vào từng năm.
Nest
Lệnh nest() không phải là một lệnh tích hợp trong R. Tuy nhiên, trong
gói tidyr, có hàm nest() cho phép chúng ta tạo một cột mới trong một
dataframe và lồng dữ liệu thành các danh sách dựa trên một hoặc nhiều
biến. Các tham số chính trong hàm nest() được trình bày
dưới đây
.data: Đối số này là dữ liệu gốc mà bạn muốn tạo khung dữ liệu
lồng nhau từ đó
…: Đây là một đối số kiểu tidy-select, cho phép chọn các cột mà
ta muốn lồng vào các khung dữ liệu con
.by: Đối số này cho phép chọn các cột dùng để nhóm dữ
liệu
.key: là một đối số cho phép bạn chỉ định tên cho cột danh sách
được tạo ra sau khi lồng dữ liệu. Nếu không chỉ định tên cho tham số này
thì tên mặc định sẽ là “data”
Dưới đây là một ví dụ về dữ liệu của một bộ phận đang nghiên cứu về
tình hình thời tiết trong các thành phố khác nhau. Chúng ta có một
dataframe chứa thông tin về tên thành phố, ngày và giờ, nhiệt độ và độ
ẩm.
# Tạo dataframe chứa dữ liệu về thời tiết
data <- data.frame(
ThanhPho = c("Hanoi", "Hanoi", "Hanoi", "HoChiMinh", "HoChiMinh", "HoChiMinh"),
Ngay = c("2023-01-01", "2023-01-02", "2023-01-03", "2023-01-01", "2023-01-02", "2023-01-03"),
Gio = c("12:00", "12:00", "12:00", "12:00", "12:00", "12:00"),
NhietDo = c(20.5, 22.3, 21.8, 30.2, 31.5, 30.9),
DoAm = c(60, 65, 62, 70, 68, 72)
)
print(data)
## ThanhPho Ngay Gio NhietDo DoAm
## 1 Hanoi 2023-01-01 12:00 20.5 60
## 2 Hanoi 2023-01-02 12:00 22.3 65
## 3 Hanoi 2023-01-03 12:00 21.8 62
## 4 HoChiMinh 2023-01-01 12:00 30.2 70
## 5 HoChiMinh 2023-01-02 12:00 31.5 68
## 6 HoChiMinh 2023-01-03 12:00 30.9 72
# Lồng dữ liệu thành danh sách theo tên thành phố
nested_data <- data %>%group_by(ThanhPho) %>% nest()
# Lồng dữ liệu bằng .by
nested_data <- nest(data, .by = ThanhPho, .key = "DuLieu")
# In dữ liệu lồng
print(nested_data)
## # A tibble: 2 × 2
## ThanhPho DuLieu
## <chr> <list>
## 1 Hanoi <tibble [3 × 4]>
## 2 HoChiMinh <tibble [3 × 4]>
nested_data$DuLieu <- lapply(nested_data$DuLieu, as.data.frame)
lapply(nested_data$DuLieu, print)
## Ngay Gio NhietDo DoAm
## 1 2023-01-01 12:00 20.5 60
## 2 2023-01-02 12:00 22.3 65
## 3 2023-01-03 12:00 21.8 62
## Ngay Gio NhietDo DoAm
## 1 2023-01-01 12:00 30.2 70
## 2 2023-01-02 12:00 31.5 68
## 3 2023-01-03 12:00 30.9 72
## [[1]]
## Ngay Gio NhietDo DoAm
## 1 2023-01-01 12:00 20.5 60
## 2 2023-01-02 12:00 22.3 65
## 3 2023-01-03 12:00 21.8 62
##
## [[2]]
## Ngay Gio NhietDo DoAm
## 1 2023-01-01 12:00 30.2 70
## 2 2023-01-02 12:00 31.5 68
## 3 2023-01-03 12:00 30.9 72
Trong ví dụ này, chúng ta sử dụng hàm nest() trong gói tidyr và hàm
group_by trong package dplyr để lồng dữ liệu theo tên thành phố. Bằng
cách sử dụng chuỗi dòng lệnh trong gói tidyr và dplyr, chúng ta nhóm dữ
liệu theo cột ThanhPho bằng hàm group_by() và sau đó sử dụng hàm nest()
để tạo một cột mới chứa dữ liệu được lồng thành danh sách. Hoặc sử dụng
tham số .by chọn cột ThanhPho để nhóm dữ liệu và sau đó
dùng tham số .key để đặt tên cột danh sách tạo ra sau khi
lồng dữ liệu.
Kết quả là một dataframe mới nested_data chứa hai cột: ThanhPho và
DuLieu, trong đó cột hai chứa dữ liệu được lồng thành danh sách dựa trên
tên thành phố. Các phần tử trong cột “DuLieu” là các danh sách dữ liệu
con, mỗi danh sách chứa thông tin về ngày, giờ, nhiệt độ và độ ẩm tương
ứng cho từng thành phố.
Lệnh nest() trong ví dụ này giúp chúng ta lồng dữ liệu theo tên thành
phố, giúp tổ chức và xử lý dữ liệu thời tiết một cách trực quan và thuận
tiện hơn
Sau đó, chúng ta tiếp tục sử dụng hàm lapply() để áp dụng hàm print()
cho mỗi tibble trong danh sách nested_data$DuLieu. Kết quả là cả hai dữ
liệu bảng từ các tibble sẽ được hiển thị trên màn hình, mỗi tibble đi
kèm với tên cột và các giá trị tương ứng.
Kết quả hiện thị lần lượt là bảng về thới tiết ở Hà Nội và bảng sau
đó là bảng thời tiết ở Hồ chí Minh. Đó là ví dụ về hàm nest() được sử
dụng kết hợp với hàm group_by() và hàm lapply để cho ra được kết quả là
các dữ liệu bảng được lồng vào nhau theo các biến chúng ta cần thống
kê
Unnest
Trong ngôn ngữ lập trình R, lệnh unnest() được sử dụng
để tách dữ liệu trong một cột chứa các đối tượng lồng nhau thành các cột
riêng biệt. Điều này giúp chúng ta phân tách và truy cập dễ dàng vào các
thành phần của các đối tượng được lồng nhau. Các tham số chính trong hàm
unnest() gồm có:
data: Đối số này là dữ liệu gốc chứa cột danh sách mà chúng ta
muốn giải nén. Đây là một đối số bắt buộc và phải là một khung dữ liệu
(data frame).
col: Đây là đối số dùng để xác định tên của cột danh sách cần
giải nén. Nó cũng là một đối số bắt buộc và phải là một chuỗi ký
tự.
.drop: Một giá trị logical (TRUE hoặc FALSE) xác định xem liệu có
nên loại bỏ cột danh sách sau khi giải nén hay không. Giá trị mặc định
là TRUE, nghĩa là cột danh sách sẽ bị loại bỏ.
Dưới đây là ví dụ về lệnh unnest(), đầu tiên chúng tôi sẽ tạo
dataframe chứa dữ liệu về sản phẩm và đặc điểm
data1 <- data.frame(
SanPham = c("SP1", "SP2", "SP3"),
MauSac = I(list(
rep(c("Đỏ", "Xanh", "Vàng"), each = 3),
rep(c("Trắng", "Đen"), each = 2),
rep("Cam", 3)
)),
KichThuoc = I(list(
rep(c("S", "M", "L"), each = 3),
rep(c("M", "L"), each = 2),
rep("S", 3)
)),
Gia = c(100, 200, 150)
)
print(data1)
## SanPham MauSac KichThuoc Gia
## 1 SP1 Đỏ, Đỏ, .... S, S, S,.... 100
## 2 SP2 Trắng, T.... M, M, L, L 200
## 3 SP3 Cam, Cam.... S, S, S 150
# Tách danh sách đặc điểm thành các cột riêng biệt
data_split <- unnest(data = data1, cols = c(MauSac,KichThuoc))
# In kết quả sau khi tách
datatable(data_split)
Trong ví dụ này, chúng ta có một dataframe data chứa thông tin về sản
phẩm và đặc điểm của chúng. Cột MauSac và KichThuoc là các cột chứa danh
sách các đặc điểm tương ứng với mỗi sản phẩm.
Sử dụng lệnh unnest() trong gói tidyr, chúng ta tách danh sách đặc
điểm (MauSac và KichThuoc) thành các cột riêng biệt. Kết quả là một
dataframe mới data_split với các cột SanPham, MauSac, KichThuoc và Gia,
trong đó các cột MauSac và KichThuoc đã được tách thành các cột riêng
biệt.
complete()
Hàm complete() trong R làm một công cụ mạnh mẽ để điền các giá trị
thiếu và tạo ra các hàng hoàn chỉnh trong một dataframe, . Hàm
complete() cho phép chúng ta điền các giá trị thiếu trong dataframe bằng
cách tạo ra tất cả các kết hợp có thể của các giá trị trong các cột được
chỉ định. Các giá trị đã có sẽ được giữ nguyên, trong khi các giá trị
thiếu sẽ được điền bằng NA trong kết quả hoàn chỉnh. Những đối số có
trong hàm complete() là
data: Là data frame chứa dữ liệu cần mở rộng hoặc hoàn
chỉnh.
…: Được sử dụng để chỉ định các cột cần mở rộng hoặc hoàn chỉnh.
Các cột này có thể là các vectors hoặc danh sách (lists).
fill: Đối số này cho phép chúng ta cung cấp một giá trị duy nhất
cho mỗi biến để điền vào thay vì giá trị NA cho các kết hợp bị
thiếu.
explicit: Nếu tham số này bằng TRUE tất cả giá trị NA đều sẽ được
điền, còn nếu bằng FALSE chỉ các giá trị NA được tạo ra bởi hàm mới được
điền.
Ví dụ: Giả sử chúng ta có một bảng dữ liệu về các sản phẩm có thông
tin về tên sản phẩm, loại sản phẩm và giá tiền. Tuy nhiên, bảng dữ liệu
thiếu một số giá trị hoặc có các sản phẩm không có giá tiền. Chúng ta
muốn điền các giá trị thiếu và tạo ra các sản phẩm hoàn chỉnh với tất cả
các cột.
# Tạo dataframe chứa thông tin về sản phẩm
data2 <- data.frame(
TenSanPham = c("SP1", "SP2", "SP3", "SP4"),
LoaiSanPham = c("A", NA, "B", "C"),
GiaTien = c(100, NA, 200, NA)
)
print(data2)
## TenSanPham LoaiSanPham GiaTien
## 1 SP1 A 100
## 2 SP2 <NA> NA
## 3 SP3 B 200
## 4 SP4 C NA
# Điền các giá trị thiếu và tạo ra các sản phẩm hoàn chỉnh
data_complete <- complete(data2, TenSanPham, LoaiSanPham, GiaTien)
# In kết quả sau khi điền giá trị thiếu và tạo hàng hoàn chỉnh
options(max.print= 100)
print(data_complete, n = nrow(data_complete))
## # A tibble: 48 × 3
## TenSanPham LoaiSanPham GiaTien
## <chr> <chr> <dbl>
## 1 SP1 A 100
## 2 SP1 A 200
## 3 SP1 A NA
## 4 SP1 B 100
## 5 SP1 B 200
## 6 SP1 B NA
## 7 SP1 C 100
## 8 SP1 C 200
## 9 SP1 C NA
## 10 SP1 <NA> 100
## 11 SP1 <NA> 200
## 12 SP1 <NA> NA
## 13 SP2 A 100
## 14 SP2 A 200
## 15 SP2 A NA
## 16 SP2 B 100
## 17 SP2 B 200
## 18 SP2 B NA
## 19 SP2 C 100
## 20 SP2 C 200
## 21 SP2 C NA
## 22 SP2 <NA> 100
## 23 SP2 <NA> 200
## 24 SP2 <NA> NA
## 25 SP3 A 100
## 26 SP3 A 200
## 27 SP3 A NA
## 28 SP3 B 100
## 29 SP3 B 200
## 30 SP3 B NA
## 31 SP3 C 100
## 32 SP3 C 200
## 33 SP3 C NA
## 34 SP3 <NA> 100
## 35 SP3 <NA> 200
## 36 SP3 <NA> NA
## 37 SP4 A 100
## 38 SP4 A 200
## 39 SP4 A NA
## 40 SP4 B 100
## 41 SP4 B 200
## 42 SP4 B NA
## 43 SP4 C 100
## 44 SP4 C 200
## 45 SP4 C NA
## 46 SP4 <NA> 100
## 47 SP4 <NA> 200
## 48 SP4 <NA> NA
Trong ví dụ trên, chúng ta đã sử dụng hàm complete() để điền các giá
trị thiếu và tạo ra các hàng hoàn chỉnh trong dataframe data. Các cột
TenSanPham, LoaiSanPham và GiaTien đã được chỉ định là các cột cần hoàn
chỉnh. Hàm complete() đã tạo ra tất cả các kết hợp có thể của các giá
trị trong các cột được chỉ định và điền các giá trị thiếu bằng NA để tạo
ra các hàng hoàn chỉnh. Kết quả được in ra màn hình để hiển thị dữ liệu
đã được điền và tạo hàng hoàn chỉnh.
Trong kết quả, chúng ta có các hàng hoàn chỉnh với tất cả các kết hợp
của các giá trị trong các cột TenSanPham, LoaiSanPham và GiaTien. Các
giá trị thiếu được điền bằng NA để tạo ra các hàng hoàn chỉnh.
# Thêm vào tham số fill
data_complete <- complete(data2, TenSanPham, LoaiSanPham, GiaTien, fill = list(LoaiSanPham="C",GiaTien=150) )
datatable(data_complete)
Tuy nhiên, chúng ta có thể áp dụng tham số fill để cung cấp một giá
trị cho mỗi cột dữ liệu thay cho giá trị NA. Ở cột LoaiSanPham ta có thể
chọn “C” để thay thế cho những giá trị NA, tương tự trong cột GiaTien
chọn giá trị là 150.
Tóm lại, việc sử dụng hàm complete() sẽ giúp ta quản lý dữ liệu thiếu
và chuẩn bị dữ liệu cho phân tích và khám phá dữ liệu một cách dễ dàng
và hiệu quả.
Các hàm xử lý giá trị
NA
Trong package tidyr, chúng ta có thể sử dụng các hàm như
drop_na(), fill(), vàreplace_na()
để xử lý các giá trị NA trong dữ liệu của mình. Thao tác này rất cần
thiết đối vì dữ liệu được đem vào phân tích phải đầy đủ và độ chính xác
cao thì kết quả thu được sẽ phản ánh đúng nhất với thực tế. Do đó, việc
sử dụng thành thạo các công cụ trên sẽ giúp chúng ta tối ưu hóa thời
gian làm việc của mình cũng như là đạt được kết quả tốt hơn ở những bước
tiếp theo.
Chúng tôi sẽ thực hiện các ví dụ dựa trên dữ liệu có cấu trúc khá đơn
giản nhằm mục đích giới thiệu những hàm xử lý các giá trị bị thiếu,
ngoài ra cũng giúp người đọc có thể dễ dàng nhận ra được mức độ hiệu quả
của nó khi được áp dụng lên bộ dữ liệu đơn giản. Sau đó, chương tiếp
theo chúng tôi sẽ sử dụng lên dữ liệu phức tạp hơn và kết hợp thêm một
số hàm khác để biến đổi về dạng dữ liệu sạch.
Để thực hiện các lệnh chúng tôi sẽ tạo một dataframe có tên là
df gồm có cột date chứa chuỗi ngày bắt đầu từ
“2023-07-01” đến “2023-07-10” và cột sales chứa số lượng sản
phẩm được bán hàng ngày, trong đó có một số giá trị NA (thiếu thông tin)
để đại diện cho các ngày không có dữ liệu.
# Tạo dữ liệu ví dụ
df <- data.frame(
date = seq(as.Date("2023-07-01"), as.Date("2023-07-10"), by = "day"),
sales = c(100, NA, 120, 80, NA, 90, NA, NA, 110, 95)
)
print(df)
## date sales
## 1 2023-07-01 100
## 2 2023-07-02 NA
## 3 2023-07-03 120
## 4 2023-07-04 80
## 5 2023-07-05 NA
## 6 2023-07-06 90
## 7 2023-07-07 NA
## 8 2023-07-08 NA
## 9 2023-07-09 110
## 10 2023-07-10 95
- Xóa các dòng chứa giá trị NA “drop_na()”
Hàm drop_na(df) sẽ xóa các dòng trong dataframe df chứa
giá trị NA. Kết quả được gán vào dataframe df_cleaned được thể
hiện bên dưới. Chúng ta thấy rằng cả 4 dòng có giá trị NA đã bị xóa đi
mất bây giờ dữ liệu chỉ còn lại 6 dòng.
# Xóa các dòng chứa giá trị NA
df_cleaned <- drop_na(df)
## date sales
## 1 2023-07-01 100
## 2 2023-07-03 120
## 3 2023-07-04 80
## 4 2023-07-06 90
## 5 2023-07-09 110
## 6 2023-07-10 95
- Điền các giá trị NA bằng giá trị cụ thể “fill()”
Ngoài ra, chúng ta có thể điền hoặc thay thế các giá trị mới cho các
dòng bị NA trong cột dữ liệu bằng hàm fill(). Điền giá trị
sẽ dựa vào các dòng dữ liệu ở phía trên hoặc phía dưới để hoàn thiện các
dòng NA trong cột.
Để sử dụng hàm fill() thì trước tiên ta cần khai báo bộ
dữ liệu cần xử lý dữ liệu thiếu trong trường hợp này là df, sau
đó chọn cột chứa các giá trị là sales và đối số
.direction giúp ta chọn hướng để điền giá trị thiếu, mặc
định sẽ là “down” điền từ trên xuống.
Dựa vào bảng kết quả ta có thể thấy ở ngày 2 thì số lượng sản phẩm
được bán trong ngày sẽ được điền là 100 dựa vào dòng dữ liệu ở trước đó,
tương tự cho các ngày bên dưới.
df_filled <- fill(data=df,sales,.direction = "down")
## date sales
## 1 2023-07-01 100
## 2 2023-07-02 100
## 3 2023-07-03 120
## 4 2023-07-04 80
## 5 2023-07-05 80
## 6 2023-07-06 90
## 7 2023-07-07 90
## 8 2023-07-08 90
## 9 2023-07-09 110
## 10 2023-07-10 95
Tùy vào mục đích chúng ta có thể điền giá trị bị thiếu theo điều
hướng từ phía dưới lên như bảng kết quả bên dưới ở ngày 7 và 8 giá trị
NA được thay thế bằng 110 dựa vào số lượng bán hàng của ngày 9
df_filled2 <- fill(data=df,sales,.direction = "up")
## date sales
## 1 2023-07-01 100
## 2 2023-07-02 120
## 3 2023-07-03 120
## 4 2023-07-04 80
## 5 2023-07-05 90
## 6 2023-07-06 90
## 7 2023-07-07 110
## 8 2023-07-08 110
## 9 2023-07-09 110
## 10 2023-07-10 95
- Thay thế các giá trị NA bằng giá trị khác “replace_na()”
Một cách khác dùng để xử lý giá trị thiếu là thay thế nó bằng một giá
trị cụ thể mà chúng ta xác định, giá trị được dùng thay thế có thể là
một con số, một vector và nó thay thế cho tất cả giá trị thiếu trong cột
dữ liệu mà chúng ta chỉ định.
Trong ví dụ chúng tôi tính giá trị trung bình của cột sales trong
dataframe df và loại bỏ các giá trị NA bằng đối số
na.rm = TRUE . Tiếp theo, sử dụng hàm
replace_na() để thay thế các giá trị NA trong cột
sales của dataframe df bằng giá trị trung bình và kết quả được
gán vào dataframe df_replaced
# Thay thế các giá trị NA bằng giá trị trung bình của sales
mean_sales <- mean(df$sales, na.rm = TRUE)
df_replaced <- replace_na(data=df, replace = list(sales = mean_sales))
## date sales
## 1 2023-07-01 100.00000
## 2 2023-07-02 99.16667
## 3 2023-07-03 120.00000
## 4 2023-07-04 80.00000
## 5 2023-07-05 99.16667
## 6 2023-07-06 90.00000
## 7 2023-07-07 99.16667
## 8 2023-07-08 99.16667
## 9 2023-07-09 110.00000
## 10 2023-07-10 95.00000
CHƯƠNG 3: ỨNG DỤNG CỦA
TIDYR
Trong chương này chúng tôi sẽ ứng dụng các hàm được giới thiệu ở
chương 2 vào phân tích một số bộ dữ liệu để mọi người nhận thấy được sự
hiệu quả của gói Tidyr trong giai đoạn xử lý dữ liệu chưa sạch. Ngoài
ra, chúng tôi kết hợp một số gói khác chẳng hạn như dplyr, ggplot,
tidyverse… để thuận tiện trong các thao tác phân tích cũng như trực quan
hóa dữ liệu từ đó thu được kết quả tốt nhất.
Bộ dữ liệu
gapminder
Trước khi phân tích thì chúng tôi sẽ giới thiệu bộ dữ liệu
“gapminder” trong package gapminder gồm có những thông tin và biến nào
để người đọc có sự nhìn nhận tổng quát về nó, điều này sẽ hữu ích trong
việc hiểu rõ các lệnh được áp dụng sẽ mang lại kết quả như thế nào.
Bộ dữ liệu “gapminder” cung cấp thông tin về tuổi thọ trung bình, dân
số và GDP per capita của các quốc gia từ năm 1952 đến 2007 với chu kỳ là
5 năm sẽ thu thập dữ liệu một lần. Nó giúp ta nắm bắt được sự thay đổi
và sự phát triển của các quốc gia theo thời gian. Dữ liệu này gồm 1704
quan sát và có 6 biến trong đó:
country: Tên quốc gia.
continent: Lục địa nơi quốc gia thuộc về. Có 5 giá trị: Africa,
Americas, Asia, Europe, và Oceania.
year: Năm ghi nhận dữ liệu.
lifeExp: Tuổi thọ trung bình của dân số trong quốc gia, tính bằng
đơn vị năm.
population: Dân số của quốc gia trong năm cụ thể.
gdpPercap: GDP trên mỗi người dân của một quốc gia trong năm cụ
thể.
Đầu tiên, chúng ta cần gọi dữ liệu “gapminder” bằng lệnh
data sau khi đã cài đặt package gapminder và tải
thư viện của nó lên, dữ liệu sẽ được gán vào biến “g” giúp việc nhập
lệnh trở nên dễ dàng hơn so với tên ban đầu.
Bảng dữ liệu bên dưới, mỗi quan sát sẽ cho biết thông tin về tên quốc
gia, châu lục của quốc gia, năm khảo sát và các chỉ số về tuổi thọ trung
bình, dân số, GDP trên mỗi cá nhân tương ứng. Do đó, nó thuộc dạng dữ
liệu “rộng” điều này sẽ giúp việc nhập dữ liệu hoặc trình bày bảng tốt
hơn, người đọc báo cáo có thể hiểu rõ được nội dung mà không mất quá
nhiều thời gian. Tuy nhiên dạng dữ liệu “rộng” sẽ gặp khó khăn trong
việc phân tích vì vậy chúng ta cần phải chuyển sang dạng “dài”.
library(gapminder)
data("gapminder")
g <- gapminder
datatable(g)
Hàm pivot_longer()sẽ chuyển dữ liệu “g” sang dạng dài
bằng cách chuyển đổi ba cột lifeExp, pop, gdpPercap thành hai
cột mới là chiso chứa tên các chỉ số và giatri chứa
các giá trị của các biến ban đầu. Sau đó sẽ gán dữ liệu được chuyển đổi
vào “g2”, dữ liệu này sẽ có số quan sát là 5112 tuy nhiên thì số lượng
biến sẽ ít hơn dữ liệu ban đầu (5 cột so với 6 cột).
g2 <- pivot_longer(data = g , cols = c(lifeExp,pop,gdpPercap), names_to = "chiso", values_to = "giatri")
head(g2)
## # A tibble: 6 × 5
## country continent year chiso giatri
## <fct> <fct> <int> <chr> <dbl>
## 1 Afghanistan Asia 1952 lifeExp 28.8
## 2 Afghanistan Asia 1952 pop 8425333
## 3 Afghanistan Asia 1952 gdpPercap 779.
## 4 Afghanistan Asia 1957 lifeExp 30.3
## 5 Afghanistan Asia 1957 pop 9240934
## 6 Afghanistan Asia 1957 gdpPercap 821.
Nếu ta muốn tính trung bình của các chỉ số này theo từng châu lục
khác nhau nhằm mục đích đánh giá tổng thể sự phát triển giữa các châu
với nhau, ta có thể sử dụng thêm hàm group_by để nhóm dữ
liệu theo cột continent, chiso và hàm summarise để
thực hiện phép tính trung bình cho cột giatri của các nhóm dữ
liệu. Cả hai hàm trên đều nằm trong gói dplyr có thể
kết hợp với gói tidyr để biến đổi dữ liệu chưa sạch rất
hiệu quả.
Kết quả thu được sẽ được gán vào “mean_g2” trong đó sẽ có cột
continent chứa thông tin về các châu lục. Cột chiso
gồm giá trị là GDP, tuổi thọ, dân số. Cột trungbinh sẽ chứa giá
trị trung bình của các chỉ số tương ứng với mỗi châu lục.
mean_g2 <- g2 %>% group_by(continent,chiso) %>% summarise(trungbinh=mean(giatri))
datatable(mean_g2)
Từ đó, chúng ta trực quan hóa bộ dữ liệu vừa được tính trung bình
bằng cách vẽ biểu đồ cột cho ba chỉ số với các màu sắc khác nhau. Các
cột trên đồ thị sẽ tương ứng với các châu lục trong dữ liệu.
Biểu đồ có các cột màu đỏ là biểu đồ về GDP trên mỗi cá nhân trung
bình của 5 châu lục. Dựa vào biểu đồ ta có thể thấy Châu Đại Đương có
GDP cao nhất trong 5 châu lục (khoảng 18621 đô), ngược lại thì Châu Phi
có GDP trung bình thấp với con số khiêm tốn là khoảng 2193 đô trên mỗi
cá nhân.
Biểu đồ cột màu xanh lá đại diện cho tuổi thọ trung bình của người
dân ở mỗi châu lục, nhìn tổng thể thì các châu lục có tuổi thọ trung
bình không chênh lệch nhiều, ngoại trừ Châu Phi có tuổi thọ trung bình
là khoảng 49 tuổi khá thấp so với Châu Âu (72 tuổi) và Châu Đại Đương
(74 tuổi).
Cuối cùng, biểu đồ có cột màu xanh dương cho biết thông tin về dân số
trung bình của các quốc gia trong một châu lục cụ thể. Ta nhận thấy rằng
các quốc gia Châu Á có dân số trung bình cao vượt trội so với các châu
lục còn lại( khoảng 77 triệu người). Tuy nhiên thì các quốc gia thuộc
Châu Đại Đương và Châu Phi có dân số thấp (dưới mức 10 triệu người).
ggplot(mean_g2, aes(x = continent, y = trungbinh, fill = chiso)) +
geom_col() +
facet_grid(chiso ~ ., scales = "free_y") +
labs(x = "ChauLuc", y = "GiaTri") +
theme_minimal() +
scale_y_continuous(expand = expansion(mult = c(0.1, 0.1)))

Trong một vài tình huống nhu cầu của người phân tích chỉ cần chọn một
số quốc gia cụ thể để đánh giá sự phát triển của nó bằng các chỉ số thì
chúng ta cũng có để kết hợp thêm hàm select() và
filter thuộc gói dplyr, sau đó thể hiện dữ
liệu ở dạng đồ thị bằng các công cụ mạnh mẽ từ gói
ggplot2.
Dưới đây chúng tôi chọn các cột country, lifeExp, year bằng
hàm select() để dữ liệu đầu trong hàm phía sau sẽ nhỏ hơn
bộ dữ liệu ban đầu. Phép toán tử %>% giúp dữ liệu sau khi
được chọn đưa vào đối số đầu tiên của hàm filter để thực
hiện lọc một số quốc gia trong cột country. Cuối cùng sử dụng
hàm ggplot để vẽ đồ thị đường về tuổi thọ trung bình của ba
quốc gia China, Vietnam, United States.
g %>% select(country,lifeExp,year) %>% filter(country %in% c("China","Vietnam","United States"))%>%
ggplot(aes(x = year , y = lifeExp, color=country))+
geom_line()+
labs(x= "NĂM", y= "TUỔI THỌ", title = "BIỂU ĐỒ TUỔI THỌ TRUNG BÌNH", color = "QUỐC GIA")

Để biết thêm thông tin về sự thay đổi tổng dân số trong châu lục qua
các năm, chúng tôi đã tính tổng dân số được nhóm theo biến
continent, year. Kết quả sẽ được gán vào “g3” để thuận tiện
thực hiện các lệnh tiếp theo.
Dữ liệu sau khi tính tổng dân số đã thuộc dạng dữ liệu dài, điều này
sẽ khiến việc thực hiện trực quan hóa một cách rất dễ dàng. Do đó chúng
ta có thể sử dụng nó biểu diễn đồ thị cột về sự thay đổi tổng dân số của
các châu lục này qua các năm ngay lập tức.
g3 <- g %>% group_by(continent,year) %>%
summarise(spop=sum(pop))
head(g3)
## # A tibble: 6 × 3
## # Groups: continent [1]
## continent year spop
## <fct> <int> <dbl>
## 1 Africa 1952 237640501
## 2 Africa 1957 264837738
## 3 Africa 1962 296516865
## 4 Africa 1967 335289489
## 5 Africa 1972 379879541
## 6 Africa 1977 433061021
ggplot(g3)+
geom_col(
aes(x= year, y = spop, fill= continent ),
width = 2
)

Để phù hợp cho việc thực hiện các báo cáo và trình bày bảng chúng ta
có thể dùng hàm pivot_wider() để chuyển g3 sang
dạng rộng như bên dưới đây. Bảng này sẽ giúp ta quan sát tổng dân số của
từng lục địa qua các năm một cách thuận tiện hơn.
wider_g3<- pivot_wider(g3 ,names_from = continent, values_from = spop)
datatable(wider_g3)
- Sau đó vẽ đồ thị cột thể hiện tổng dân số thay đổi qua các năm cho
châu Âu
ggplot(wider_g3, aes(x = year, y= Europe ,fill= "Europe" ))+
geom_col()+
scale_fill_manual(values = "blue") +
theme_minimal()+
labs(x = "Năm",y="Dân số", title = "BIỂU ĐỒ DÂN SỐ CHÂU ÂU ", fill = "Châu")

Dựa vào đồ thị, tổng dân số của Châu Âu có sự gia tăng qua các
năm và tốc độ tăng này khá đồng đều nhau. Năm 1952 tổng dân số của châu
lục này chỉ có khoảng 400 triệu người và tăng dần đến năm 2007 thì có
khoảng 600 triệu người.
Tiếp theo, chúng tôi sử dụng hàm nest() để gom các cột
pop, gdpPercap và lifeExp thành một cột dạng nested list. Điều này giúp
giảm sự phức tạp của dữ liệu và thực hiện các tính toán linh hoạt hơn
theo nhóm đã được gộp.
# Sử dụng hàm nest() để gom các năm và chỉ số tương ứng thành cột dạng nested list
nested <- g %>% nest(.by = c(country, continent,year),.key = "chiso")
## # A tibble: 1,704 × 4
## country continent year chiso
## <fct> <fct> <int> <list>
## 1 Afghanistan Asia 1952 <tibble [1 × 3]>
## 2 Afghanistan Asia 1957 <tibble [1 × 3]>
## 3 Afghanistan Asia 1962 <tibble [1 × 3]>
## 4 Afghanistan Asia 1967 <tibble [1 × 3]>
## 5 Afghanistan Asia 1972 <tibble [1 × 3]>
## 6 Afghanistan Asia 1977 <tibble [1 × 3]>
## 7 Afghanistan Asia 1982 <tibble [1 × 3]>
## 8 Afghanistan Asia 1987 <tibble [1 × 3]>
## 9 Afghanistan Asia 1992 <tibble [1 × 3]>
## 10 Afghanistan Asia 1997 <tibble [1 × 3]>
## # ℹ 1,694 more rows
- Như kết quả hiển thị bên trên, cột chiso nằm ở dạng danh
sách lồng nhau ( nested list), mỗi phần tử sẽ chứa thông tin về pop,
gdp, lifeExp của mỗi quốc gia theo từng năm.
Hơn thế, nếu chúng ta cần thông tin về các chỉ số của một quốc gia cụ
thể chẳng hạn như United States ta có thể dùng hàm filter()
để lọc nó ra và hiển thị kết quả về những chỉ số đã được gom.
nested$chiso <- lapply(nested$chiso, as.data.frame)
US <- nested %>% filter(country == "United States")
## [[1]]
## lifeExp pop gdpPercap
## 1 68.44 157553000 13990.48
##
## [[2]]
## lifeExp pop gdpPercap
## 1 69.49 171984000 14847.13
##
## [[3]]
## lifeExp pop gdpPercap
## 1 70.21 186538000 16173.15
##
## [[4]]
## lifeExp pop gdpPercap
## 1 70.76 198712000 19530.37
##
## [[5]]
## lifeExp pop gdpPercap
## 1 71.34 209896000 21806.04
##
## [[6]]
## lifeExp pop gdpPercap
## 1 73.38 220239000 24072.63
##
## [[7]]
## lifeExp pop gdpPercap
## 1 74.65 232187835 25009.56
##
## [[8]]
## lifeExp pop gdpPercap
## 1 75.02 242803533 29884.35
##
## [[9]]
## lifeExp pop gdpPercap
## 1 76.09 256894189 32003.93
##
## [[10]]
## lifeExp pop gdpPercap
## 1 76.81 272911760 35767.43
##
## [[11]]
## lifeExp pop gdpPercap
## 1 77.31 287675526 39097.1
##
## [[12]]
## lifeExp pop gdpPercap
## 1 78.242 301139947 42951.65
- Để giải nén dữ liệu ở dạng list nested thì ta dùng hàm
unnest(), kết quả thu được sẽ tương tự dữ liệu ban đầu ban
đầu.
# Sử dụng hàm unnest() để giải nén dữ liệu
unnest <- nested %>% unnest(chiso)
## # A tibble: 1,704 × 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Afghanistan Asia 1952 28.8 8425333 779.
## 2 Afghanistan Asia 1957 30.3 9240934 821.
## 3 Afghanistan Asia 1962 32.0 10267083 853.
## 4 Afghanistan Asia 1967 34.0 11537966 836.
## 5 Afghanistan Asia 1972 36.1 13079460 740.
## 6 Afghanistan Asia 1977 38.4 14880372 786.
## 7 Afghanistan Asia 1982 39.9 12881816 978.
## 8 Afghanistan Asia 1987 40.8 13867957 852.
## 9 Afghanistan Asia 1992 41.7 16317921 649.
## 10 Afghanistan Asia 1997 41.8 22227415 635.
## # ℹ 1,694 more rows
# Vẽ biểu đồ cột cho tổng dân số (pop) của từng quốc gia trong năm 2007
unnest %>%
filter(year == 2007 & country %in% c("Vietnam", "China", "Korea, Rep.", "Japan","Indonesia","Thailand","Malaysia","India")) %>%
ggplot( aes(x = reorder(country, pop), y = pop,fill = country)) +
geom_bar(stat = "identity") +
labs(title = "Dân số của một quốc gia Asia trong năm 2007",
x = "Quốc gia",
y = "Tổng dân số")

- Biểu đồ cho thấy rằng dân số của India (Khoảng 1,1 tỷ người), China
(khoảng 1,3 tỷ người) trong năm 2007 cao hơn rất nhiều so với một số
quốc gia trong khu vực Châu Á. Quốc gia có dân số thấp nhất trong các
quốc gia trên là Malaysia chỉ có khoảng 25 triệu người
Việc sử dụng nest() và unnest() cho bộ dữ liệu gapminder cho phép ta
chuyển đổi dữ liệu từ dạng bảng thông thường thành dạng nested list và
ngược lại. Điều này có thể hữu ích trong việc thao tác và xử lý dữ liệu,
đặc biệt là khi làm việc với dữ liệu có cấu trúc phức tạp hơn và có
nhiều cấp độ lồng nhau.
WHO
Trong phần này chúng tôi sẽ làm việc trên bộ dữ liệu
who, đây là bộ dữ liệu con được thu thập từ báo cáo về
bệnh lao toàn cầu của Tổ chức Y tế Thế giới. Nó gồm có 60 cột và 7240
quan sát, tuy nhiên thì từ cột thứ 5 đến cột 60 có ký tự “new_” được kết
nối với các thông tin khác.
country là tên của các quốc gia được thu
thập.
ios2, ios3 lần lượt là mã quốc gia 2 ký tự và 3
ký tự.
year là năm thu thập dữ liệu.
Phương pháp chẩn đoán nếu là rel nghĩa là tái
phát, sn là bệnh nhân không có vi khuẩn lao ,
sp là bệnh nhân có vi khuẩn lao, ep
bệnh nhân lao ngoài phổi.
Ký tự f đại diện cho giới tính nữ và
m là giới tính nam
Số trong mỗi cột được dùng để thể hiện nhóm tuổi ví dụ 014 là
0-14 tuổi, 1524 là 15-24 tuổi, 2534 là 25-34 tuổi, 3544 là 35-44 tuổi,
4554 là 45-54 tuổi, 5564 là 55-64 tuổi và 65 là 65 tuổi trở
lên.
Ví dụ tên cột thứ 5 là “new_sp_m014” đại diện cho những bệnh nhân có
kết quả chuẩn đoán có vi khuẩn lao lao dương tính, giới tính nam và
thuộc nhóm tuổi từ 0 đến 14 tuổi.
data("who")
## # A tibble: 6 × 60
## country iso2 iso3 year new_sp_m014 new_sp_m1524 new_sp_m2534 new_sp_m3544
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Afghanis… AF AFG 1980 NA NA NA NA
## 2 Afghanis… AF AFG 1981 NA NA NA NA
## 3 Afghanis… AF AFG 1982 NA NA NA NA
## 4 Afghanis… AF AFG 1983 NA NA NA NA
## 5 Afghanis… AF AFG 1984 NA NA NA NA
## 6 Afghanis… AF AFG 1985 NA NA NA NA
## # ℹ 52 more variables: new_sp_m4554 <dbl>, new_sp_m5564 <dbl>,
## # new_sp_m65 <dbl>, new_sp_f014 <dbl>, new_sp_f1524 <dbl>,
## # new_sp_f2534 <dbl>, new_sp_f3544 <dbl>, new_sp_f4554 <dbl>,
## # new_sp_f5564 <dbl>, new_sp_f65 <dbl>, new_sn_m014 <dbl>,
## # new_sn_m1524 <dbl>, new_sn_m2534 <dbl>, new_sn_m3544 <dbl>,
## # new_sn_m4554 <dbl>, new_sn_m5564 <dbl>, new_sn_m65 <dbl>,
## # new_sn_f014 <dbl>, new_sn_f1524 <dbl>, new_sn_f2534 <dbl>, …
Ta thực hiện chuyển dữ liệu sang dạng long bằng hàm
pivot_longer() như đã được giới thiệu ở phần trước, các cột
chuyển đổi được chọn bằng starts_with bắt đầu với ký tự
“new”. Tên biến chứa các cột sau khi chuyển sang dạng long là
method và giá trị tương ứng được chứa trong cột
values. Sau đó chúng ta có thể dùng hàm drop_na()
để loại bỏ đi các giá trị NA.
#Chuyển dữ liệu sang dạng dài
longer <- pivot_longer(data = who,cols = starts_with("new"), names_to = "method", values_to = "values")
longer <- drop_na(longer)
## # A tibble: 6 × 6
## country iso2 iso3 year method values
## <chr> <chr> <chr> <dbl> <chr> <dbl>
## 1 Afghanistan AF AFG 1997 new_sp_m014 0
## 2 Afghanistan AF AFG 1997 new_sp_m1524 10
## 3 Afghanistan AF AFG 1997 new_sp_m2534 6
## 4 Afghanistan AF AFG 1997 new_sp_m3544 3
## 5 Afghanistan AF AFG 1997 new_sp_m4554 5
## 6 Afghanistan AF AFG 1997 new_sp_m5564 2
Chúng ta thấy rằng trong cột method chứa các thông
tin về dữ liệu khảo sát bệnh lao dưới dạng chuỗi khá phức tạp, chính vì
thế chúng ta cần kết hợp thêm hàm gsub để có thể loại bỏ
cũng như là thêm vào một số chuỗi cần thiết. Hàm mutate()
sẽ giúp cập nhập các giá trị vừa được thay đổi ở cột method trong trường
hợp này chúng tôi tạo cột mới trùng với tên cột cũ.
- Loại bỏ chuỗi “new_” trong cột method bằng các thay thế nó bằng ““,
tuy nhiên một số chuỗi chỉ xuất hiện”new” chứ không phải là “new_” cho
nên chúng ta cần khai báo cho hàm
gsub() các chuỗi cần thay
thế là “new_?”.
longer <- longer %>% mutate(method = gsub("new_?","",method))
## # A tibble: 6 × 6
## country iso2 iso3 year method values
## <chr> <chr> <chr> <dbl> <chr> <dbl>
## 1 Afghanistan AF AFG 1997 sp_m014 0
## 2 Afghanistan AF AFG 1997 sp_m1524 10
## 3 Afghanistan AF AFG 1997 sp_m2534 6
## 4 Afghanistan AF AFG 1997 sp_m3544 3
## 5 Afghanistan AF AFG 1997 sp_m4554 5
## 6 Afghanistan AF AFG 1997 sp_m5564 2
- Tiếp theo, chúng ta thêm vào ký tự “_” sau ký “f” hoặc “m” để có thể
phân cách giới tính và nhóm tuổi
longer <- longer %>% mutate(method = gsub("(f|m)(\\d+)","\\1_\\2",method))
## # A tibble: 6 × 6
## country iso2 iso3 year method values
## <chr> <chr> <chr> <dbl> <chr> <dbl>
## 1 Afghanistan AF AFG 1997 sp_m_014 0
## 2 Afghanistan AF AFG 1997 sp_m_1524 10
## 3 Afghanistan AF AFG 1997 sp_m_2534 6
## 4 Afghanistan AF AFG 1997 sp_m_3544 3
## 5 Afghanistan AF AFG 1997 sp_m_4554 5
## 6 Afghanistan AF AFG 1997 sp_m_5564 2
- Thực hiện tác cột method thành ba cột mt, gender,
age bằng hàm
separate()
longer <- longer %>% separate(col = method,into = c("mt","gender","age"), sep = "_")
## # A tibble: 6 × 8
## country iso2 iso3 year mt gender age values
## <chr> <chr> <chr> <dbl> <chr> <chr> <chr> <dbl>
## 1 Afghanistan AF AFG 1997 sp m 014 0
## 2 Afghanistan AF AFG 1997 sp m 1524 10
## 3 Afghanistan AF AFG 1997 sp m 2534 6
## 4 Afghanistan AF AFG 1997 sp m 3544 3
## 5 Afghanistan AF AFG 1997 sp m 4554 5
## 6 Afghanistan AF AFG 1997 sp m 5564 2
- Chuyển đổi các giá trị viết tắt trong cột age và
gender về nhóm tuổi, giới tính cụ thể.
longer <- mutate(longer, age = case_when(
age == "014" ~ "0-14 years",
age == "1524" ~ "15-24 years",
age == "2534" ~ "25-34 years",
age == "3544" ~ "35-44 years",
age == "4554" ~ "45-54 years",
age == "5564" ~ "55-64 years",
age == "65" ~ "65 years or older",
))
longer <- longer %>% mutate(gender = case_when(
gender == "m" ~ "male",
gender == "f" ~ "female"
))
Qua nhiều thao tác xử lý và biến đổi từ dữ liệu who
ban đầu chúng ta đã có được bộ dữ liệu mới gọn gàng hơn rất nhiều. Việc
làm sạch dữ liệu chưa hoàn chỉnh rất quan trọng trong quá trình phân
tích, nó giúp chúng ta dễ dàng trực quan hóa bằng các hình ảnh, đồ thị
cũng như là tính toán các số liệu thống kê.
longer %>% group_by(gender,year) %>% summarise(case= sum(values)) %>%
ggplot(aes(x=year, y = case , color=gender ))+
geom_line()+
scale_color_manual(values = c("blue", "red")) +
theme_minimal() +
labs(title = "TỔNG SỐ CA BỆNH THEO GIỚI TÍNH" )

- Dựa vào biểu đồ đường ở trên, tổng trường hợp mắc bệnh lao qua các
năm ở hai giới tính có xu hướng tăng lên từ những năm 1995. Xu hướng
tăng có tự tương đồng với nhau giữa hai nhóm giới tính tuy nhiên ở nam
giới sự gia tăng tổng số ca mắc bệnh nhiều hơn ở nữ giới. Cụ thể, năm
2010 tổng các trường hợp mắc bệnh lao ở nam giới là 2,5 triệu người còn
ở nữ giới chỉ có khoảng 1,5 triệu người.
# tính tổng số người bệnh theo giới tính và phương pháp chuẩn đoán (mt)
df1 <- longer %>% group_by(gender,mt) %>% summarise(sum= sum(values))
## # A tibble: 8 × 3
## # Groups: gender [2]
## gender mt sum
## <chr> <chr> <dbl>
## 1 female ep 941049
## 2 female rel 1197703
## 3 female sn 2437544
## 4 female sp 11292279
## 5 male ep 1043265
## 6 male rel 2013437
## 7 male sn 3838291
## 8 male sp 20542472
- Tính tổng số ca mắc bệnh theo giới tính và phương pháp chuẩn đoán
bằng hàm
group_by() và summarise(), sau đó vẽ
đồ thị cột đôi để đánh giá kết quả.
# Đồ thị
ggplot( df1,aes(x = mt, y = sum, fill = gender)) +
geom_col(position = "dodge") +
labs(title = "Tổng số ca theo phương pháp và giới tính",
x = "Phương pháp",
y = "Số lượng",
fill = "Giới tính") +
theme_minimal()

- Đồ thị bên trên cho chúng ta thấy số người được chuẩn đoán là sp (có
vi khuẩn lao) có số lượng cao nhất trong 4 nhóm cụ thể có 20542472 nam
và 11292279 nữ trong trường hợp này. Chuẩn đoán là bệnh lao ngoài phổi
(ep) có số lượng thấp nhất, trong đó ở nữ giới có 941049 người và nam
giới có 1043265 người thuộc chuẩn đoán này.
longer %>% group_by(age)%>% summarise(total=sum(values)) %>%
mutate(p = total/sum(total)) %>%
ggplot(aes(x="", y= p, fill = age))+
geom_bar(stat = "identity",width = 1)+
scale_fill_brewer(palette = "Set3") +
coord_polar("y",start = 0)+
geom_text(aes(label = scales::percent(p)),position = position_stack(vjust = 0.5), size = 3) +
theme_void() +
labs(title= "Tình trạng bệnh lao ở các nhóm tuổi")

- Nhóm từ 25 đến 34 tuổi có tỷ lệ mắc bệnh lớn nhất trong tất cả nhóm
tuổi (khoảng 22.2%), ở nhóm từ 45 đến 54 tuổi cũng đạt tỷ lệ khá cao là
20.2%. Ngược lại thì nhóm 0-14 tuổi chiếm tỷ lệ mắc bệnh lao thấp nhất
chỉ khoảng 3.9%. Nhìn chung tỷ lệ mắc bệnh cao sẽ thuộc các nhóm tuổi
trung niên.
Để gom các biến thành một danh sách lồng nhau theo mỗi quốc gia ta áp
dụng hàm nest(), dữ liệu mới này gọn gàng hơn rất nhiều so
với ban đầu nếu chúng ta cần khai thác thông tin của quốc gia thì chỉ
cần mở danh sách dữ liệu của nó mà không cần phải nhìn toàn bộ thông tin
như ban đầu.
nested_data <- nest(longer, .by = country, .key = "year")
## # A tibble: 218 × 2
## country year
## <chr> <list>
## 1 Afghanistan <tibble [244 × 7]>
## 2 Albania <tibble [448 × 7]>
## 3 Algeria <tibble [224 × 7]>
## 4 American Samoa <tibble [172 × 7]>
## 5 Andorra <tibble [387 × 7]>
## 6 Angola <tibble [270 × 7]>
## 7 Anguilla <tibble [155 × 7]>
## 8 Antigua and Barbuda <tibble [346 × 7]>
## 9 Argentina <tibble [448 × 7]>
## 10 Armenia <tibble [461 × 7]>
## # ℹ 208 more rows
Hàm filter() trong trường hợp bên dưới được sử dụng để
lọc Việt Nam ra khỏi bộ dữ liệu trên và sau đó ta hiển thị thông tin về
các trường hợp mắc bệnh lao của nó như bên dưới đây.
nested_data$year <- lapply(nested_data$year, as.data.frame)
VN <- nested_data %>% filter(country== "Viet Nam")
## # A tibble: 1 × 2
## country year
## <chr> <list>
## 1 Viet Nam <df [252 × 7]>
## [[1]]
## iso2 iso3 year mt gender age values
## 1 VN VNM 1996 sp male 0-14 years 92
## 2 VN VNM 1996 sp male 15-24 years 1994
## 3 VN VNM 1996 sp male 25-34 years 5716
## 4 VN VNM 1996 sp male 35-44 years 7137
## 5 VN VNM 1996 sp male 45-54 years 5170
## 6 VN VNM 1996 sp male 55-64 years 5839
## 7 VN VNM 1996 sp male 65 years or older 6292
## 8 VN VNM 1996 sp female 0-14 years 91
## 9 VN VNM 1996 sp female 15-24 years 1127
## 10 VN VNM 1996 sp female 25-34 years 2606
## 11 VN VNM 1996 sp female 35-44 years 3045
## 12 VN VNM 1996 sp female 45-54 years 2504
## 13 VN VNM 1996 sp female 55-64 years 3360
## 14 VN VNM 1996 sp female 65 years or older 3938
## [ reached 'max' / getOption("max.print") -- omitted 238 rows ]
Giải nén dữ liệu ở dạng nested ta cần sử dụng hàm
unnest() dữ liệu được trả về sẽ bao gồm các thông tin như
dữ liệu ban đầu.
# Sử dụng hàm unnest()
unnest_data <- unnest(nested_data,cols = year)
## # A tibble: 75,752 × 8
## country iso2 iso3 year mt gender age values
## <chr> <chr> <chr> <dbl> <chr> <chr> <chr> <dbl>
## 1 Afghanistan AF AFG 1997 sp male 0-14 years 0
## 2 Afghanistan AF AFG 1997 sp male 15-24 years 10
## 3 Afghanistan AF AFG 1997 sp male 25-34 years 6
## 4 Afghanistan AF AFG 1997 sp male 35-44 years 3
## 5 Afghanistan AF AFG 1997 sp male 45-54 years 5
## 6 Afghanistan AF AFG 1997 sp male 55-64 years 2
## 7 Afghanistan AF AFG 1997 sp male 65 years or older 0
## 8 Afghanistan AF AFG 1997 sp female 0-14 years 5
## 9 Afghanistan AF AFG 1997 sp female 15-24 years 38
## 10 Afghanistan AF AFG 1997 sp female 25-34 years 36
## # ℹ 75,742 more rows
LS0tDQp0aXRsZTogIlRp4buDdSBsdeG6rW4gcGFja2FnZSBUaWR5ciINCmF1dGhvcjogIkzDqiBUaMOgbmggxJDhurduZyAtIENow6J1IEEgS2nhu4d0Ig0KZGF0ZTogIjIwMjMtMDYtMjgiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jX2RlcHRoOiA1DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHllcw0KICAgICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgdGhlbWU6IHVuaXRlZA0KDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQpgYGB7Y3NzLGVjaG8gPSBGQUxTRX0NCmgxIHsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGZvbnQtc2l6ZTogMzJweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQNCiAgfQ0KDQpoMiB7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBmb250LXNpemU6IDI4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KIA0KfQ0KDQpoMyB7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBmb250LXNpemU6IDI0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXN0eWxlOiBpdGFsaWM7DQp9DQoNCmg0IHtmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgZm9udC1zaXplOiAyMHB4Ow0KICBmb250LXN0eWxlOiBpdGFsaWN9DQoNCmJvZHkgew0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgZm9udC1zaXplOiAxOHB4Ow0KICANCn0NCnA6bm90KGgxKTpub3QoaDIpOm5vdChoMyk6bm90KGg0KTpub3QoaDUpIHsNCiAgdGV4dC1pbmRlbnQ6IDJlbTt9DQpwIHsNCiAgdGV4dC1hbGlnbjoganVzdGlmeTsNCiAgfQ0KLnRvY2lmeS1oZWFkZXIgew0KICBmb250LXdlaWdodDogYm9sZDsNCn0NCg0KYGBgDQoNCiFbXShpbWFnZXMvMThmMmNkZDQ5ZDc2NGUyODE3NjctMDEuanBnKQ0KDQojIENIxq/GoE5HIDE6IEdJ4buaSSBUSEnhu4ZVIMSQ4buAIFTDgEkNCg0KIyMgxJDhurd0IHbhuqVuIMSR4buBIG5naGnDqm4gY+G7qXUNCg0KSGnhu4duIG5heSwgbmhp4buBdSBsxKluaCB24buxYyDEkcOjIMOhcCBk4bulbmcgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgdsOgbyB0cm9uZyBxdcOhIHRyw6xuaCBuZ2hpw6puIGPhu6l1IMSR4buDIGPDsyB0aOG7gyDEkeG6oXQgxJHGsOG7o2Mga+G6v3QgcXXhuqMgdOG7kXQgaMahbiB2w6AgxJHhu5kgY2jDrW5oIHjDoWMgY2FvIGjGoW4uIFR1eSBuaGnDqm4sIGThu68gbGnhu4d1IMSRxrDhu6NjIHRodSB0aOG6rXAgdGjGsOG7nW5nIHLhuqV0IGzhu5tuLCBwaOG7qWMgdOG6oXAsIGPhuqV1IHRyw7pjIGtow7RuZyBwaMO5IGjhu6NwIGhv4bq3YyBjw7MgdGjhu4MgYuG7iyB0aGnhur91IGThu68gbGnhu4d1IGNobyBuw6puIGtow7RuZyB0aOG7gyBuw6BvIMSRxrBhIHbDoG8gbcO0IGjDrG5oIHBow6JuIHTDrWNoIG5nYXkgbOG6rXAgdOG7qWMuIERvIMSRw7MsIGPDoWMgbmjDoCBuZ2hpw6puIGPhu6l1IGPhuqduIHBo4bqjaSB44butIGzDrSB2w6AgYmnhur9uIMSR4buVaSBj4bqldSB0csO6YyBk4buvIGxp4buHdSBzYW8gY2hvIHBow7kgaOG7o3AgduG7m2kgbeG7pWMgdGnDqnUgbmdoacOqbiBj4bupdSwgY8OzIHRo4buDIG7Ds2kgxJHDonkgY2jDrW5oIGzDoCBt4buZdCBwaOG6p24ga2jDoSBwaOG7qWMgdOG6oXAgdsOgIG3huqV0IG5oaeG7gXUgdGjhu51pIGdpYW4gdHJvbmcgbeG7mXQgY8O0bmcgdHLDrG5oIG5naGnDqm4gY+G7qXUgYuG7n2kgdsOsIGLhu5kgZOG7ryBsaeG7h3UgcXXDoSBs4bubbiB2w6AgY2jhu6lhIG5oaeG7gXUgYmnhur9uIGtow6FjIG5oYXUgY2jGsGEgxJHDoXAg4bupbmcgxJHGsOG7o2Mgbmh1IGPhuqd1IGPhu6dhIG5nxrDhu51pIHPhu60gZOG7pW5nLiBDaMOtbmggdsOsIHRo4bq/LCBo4buNIGx1w7RuIHTDrG0ga2nhur9tIGNobyBtw6xuaCBt4buZdCBjw7RuZyBj4bulIHThu5FpIMawdSDEkeG7gyBk4buFIGTDoG5nIGNodeG6qW4gaMOzYSB2w6AgbMOgbSBz4bqhY2ggZOG7ryBsaeG7h3UgxJHhu5NuZyB0aOG7nWkgdGnhur90IGtp4buHbSB0aOG7nWkgZ2lhbiwgY8O0bmcgc+G7qWMgbcOgIHbhuqtuIMSR4bqhdCBoaeG7h3UgcXXhuqMgY2FvLg0KDQpOaOG6rW4gdGjhuqV5IHbhuqVuIMSR4buBIMSRxrDhu6NjIG7Ds2kgdHLDqm4gY2jDum5nIGVtIHRo4buxYyBoaeG7h24gbmdoacOqbiBj4bupdSB24buBIGfDs2kgIlRpZHlyIiwgxJHDonkgbMOgIG3hu5l0IGPDtG5nIGPhu6UgbcOjbmggbeG6vSBo4buXIHRy4bujIG3hu41pIG5nxrDhu51pIGPDsyB0aOG7gyBjaHXhuqluIGjDs2EsIGJp4bq/biDEkeG7lWkgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3UgZOG7sWEgdsOgbyDEkeG7i25oIGThuqFuZyB0aWR5IGRhdGEsIHRyb25nIMSRw7MgdGjDrCBt4buXaSBj4buZdCBk4buvIGxp4buHdSDEkeG6oWkgZGnhu4duIGNobyBt4buZdCBiaeG6v24sIG3hu5dpIGjDoG5nIMSR4bqhaSBkaeG7h24gY2hvIG3hu5l0IHF1YW4gc8OhdCB2w6AgbeG7l2kgw7QgdGjDrCBjaOG7qWEgbeG7mXQgZ2nDoSB0cuG7iyBj4bulIHRo4buDIMSRaeG7gXUgbsOgeSBz4bq9IGdpw7pwIHZp4buHYyBwaMOibiB0w61jaCB2w6AgdHLhu7FjIHF1YW4gaMOzYSBk4buvIGxp4buHdSB0cuG7nyBuw6puIGThu4UgZMOgbmcgaMahbi4gSMahbiB0aOG6vywgbsOzIGPFqW5nIGPDsyB0aOG7gyBo4buXIHRy4bujIHTDoWNoLCBnaMOpcCB2w6AgaG/DoG4gY2jhu4luaCBk4buvIGxp4buHdSBjw7JuIHRoaeG6v3UgYuG6sW5nIG5o4buvbmcgY8O6IHBow6FwIMSRxqFuIGdp4bqjbiwgcsO1IHLDoG5nIHThu6sgxJHDsyBt4buNaSBuZ8aw4budaSBjw7MgdGjhu4MgdGnhur9uIGjDoG5oIHBow6JuIHTDrWNoIGPDoWMgbcO0IGjDrG5oLiBHw7NpIFRpZHlyIGzDoCBt4buZdCBjw7RuZyBj4bulIHThu5FpIMawdSwgxJFhIG7Eg25nLCBjw7ogcGjDoXAgxJHGoW4gZ2nhuqNuIHbDoCBuaOG6rW4gxJHGsOG7o2Mgc+G7rSBo4buXIHRy4bujIHBow6F0IHRyaeG7g24gdOG7qyBj4buZbmcgxJHhu5NuZyBSLCB2w6wgdGjhur8gbsOzIGPDsyB0aOG7gyBnaeG6o2kgcXV54bq/dCBuaGnhu4F1IHbhuqVuIMSR4buBIHRyb25nIHF1w6EgdHLDrG5oIHjhu60gbMO9IGThu68gbGnhu4d1IHRyb25nIG5oaeG7gXUgbMSpbmggduG7sWMuIENo4bqzbmcgaOG6oW4gbmjGsCB0cm9uZyB0w6BpIGNow61uaCBnw7NpIHRpZHlyIGPDsyB0aOG7gyBnacO6cCBjaMO6bmcgdGEgdOG7lSBjaOG7qWMgdsOgIHPhuq9wIHjhur9wIGzhuqFpIGThu68gbGnhu4d1IHbhu4EgY+G7lSBwaGnhu4N1IGPhu6dhIG3hu5l0IG5nw6BuaCDEkeG7gyDEkcOhbmggZ2nDoSB0w6xuaCBow6xuaCBob+G6oXQgxJHhu5luZyB2w6AgeMOieSBk4buxbmcgbcO0IGjDrG5oIGThu7EgYsOhby4gVHJvbmcgbMSpbmggduG7sWMga2luaCB04bq/IHRow6wgbsOzIGdpw7pwIGJp4bq/biDEkeG7lWkgZOG7ryBsaeG7h3UgduG7gSBHRFAsIHRoxrDGoW5nIG3huqFpLCBz4bqjbiB4deG6pXQgdsOgIG3hu5l0IHPhu5EgY2jhu4kgc+G7kSBraW5oIHThur8ga2jDoWMgY+G7p2EgY8OhYyBxdeG7kWMgZ2lhIHRoZW8gbsSDbSDEkeG7gyDEkcOhbmggZ2nDoSB04buRYyDEkeG7mSBwaMOhdCB0cmnhu4NuIHbDoCB04buVbmcgcXVhbiB24buBIG3hu5FpIHF1YW4gaOG7hyBraW5oIHThur8gZ2nhu69hIGPDoWMgcXXhu5FjIGdpYS4gUXVhIMSRw7MsIHRhIHRo4bqleSBy4bqxbmcgbOG7o2kgw61jaCBtw6AgZ8OzaSBUaWR5ciBtYW5nIGzhuqFpIHRyb25nIGdpYWkgxJFv4bqhbiBjaHXhuqluIGjDs2EgZOG7ryBsaeG7h3UgbMOgIHbDtCBjw7luZyB0byBs4bubbiwgdGnhur90IGtp4buHbSDEkcaw4bujYyBy4bqldCBuaGnhu4F1IHRo4budaSBnaWFuIHbDoCBjdW5nIGPhuqVwIGvhur90IHF14bqjIHBow6JuIHTDrWNoIGPDsyDEkeG7mSBjaMOtbmggeMOhYyBjYW8gaMahbi4NCg0KIyMgTMO9IGRvIGNo4buNbiDEkeG7gSB0w6BpDQoNClRyb25nIHF1w6EgdHLDrG5oIHRo4buxYyBow6BuaCB24bubaSBuaGnhu4F1IGThu68gbGnhu4d1IHBo4bupYyB04bqhcCBuaMOzbSBlbSBuaOG6rW4gdGjhuqV5IHZp4buHYyB44butIGzDvSBk4buvIGxp4buHdSBn4bq3cCBuaGnhu4F1IGtow7Mga2jEg24sIOG6o25oIGjGsOG7n25nIMSR4bq/biBr4bq/dCBxdeG6oyBjxaluZyBuaMawIGzDoCB0aOG7nWkgZ2lhbiB0aOG7sWMgaGnhu4duLiBOZ2hpw6puIGPhu6l1IHbhu4EgZ8OzaSBUaWR5ciBz4bq9IGdpw7pwIHZp4buHYyBjaHXhuqluIGjDs2EgdsOgIGJp4bq/biDEkeG7lWkgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3UgdHLhu58gbsOqbiBk4buFIGTDoG5nIGjGoW4sIGPDoWMgY8O6IHBow6FwIHTGsMahbmcgxJHhu5FpIMSRxqFuIGdp4bqjbiB2w6AgcsO1IHLDoG5nIGtow7RuZyDEkcOyaSBo4buPaSBraeG6v24gdGjhu6ljIGNodXnDqm4gc8OidS4gTmdvw6BpIHJhLCBUaWR5ciBjdW5nIGPhuqVwIGNobyBuZ8aw4budaSBz4butIGThu6VuZyBy4bqldCBuaGnhu4F1IGNo4bupYyBuxINuZyBraMOhYyBuaGF1LCBuw7MgZ2nDunAgbmfGsOG7nWkgZMO5bmcgZOG7hSBkw6BuZyB44butIGzDvSBk4buvIGxp4buHdSBraMO0bmcgxJHhu5NuZyBuaOG6pXQsIGtow7RuZyBj4bqldSB0csO6YyBob+G6t2MgdGhp4bq/dSBk4buvIGxp4buHdSwgdOG6oW8gxJFp4buBdSBraeG7h24gdGh14bqtbiBs4bujaSBjaG8gdmnhu4djIHBow6JuIHTDrWNoIHbDoCB0cuG7sWMgcXVhbiBow7NhIGThu68gbGnhu4d1LiBD4buZbmcgxJHhu5NuZyBSIGzDoCBt4buZdCBj4buZbmcgxJHhu5NuZyBs4bubbiB24buBIG5nw7RuIG5n4buvIGzhuq1wIHRyw6xuaCwgaOG7jSB0aMaw4budbmcgeHV5w6puIGPhuq1wIG5o4bqtcCwgcGjDoXQgdHJp4buDbiBnw7NpIFRpZHlyIG5nw6B5IGPDoG5nIHThu5FpIMawdSBoxqFuLCDEkWnhu4F1IG7DoHkga2hp4bq/biBjaG8gbmjDs20gZW0gaOG7jWMgdOG6rXAgdGjDqm0gbmhp4buBdSBraeG6v24gdGjhu6ljIHbhu4EgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgdsOgIHPhu60gZOG7pW5nIGfDs2kgbsOgeSBt4buZdCBjw6FjaCBoaeG7h3UgcXXhuqMgbmjhuqV0IHRyb25nIGPDtG5nIHZp4buHYyB0cm9uZyB0xrDGoW5nIGxhaS4gSMahbiB0aOG6vywgVGlkeXIgxJHGsOG7o2MgdGhp4bq/dCBr4bq/IGTDuW5nIMSR4buDIGdp4bqjaSBxdXnhur90IGPDoWMgduG6pW4gxJHhu4EgcGjhu5UgYmnhur9uIHbDoCB0aOG7sWMgdOG6vyDhu58gbmhp4buBdSBsxKluaCB24buxYyBraMOhYyBuaGF1LCBt4bq3YyBkw7kgZOG7ryBsaeG7h3UgbmdoacOqbiBj4bupdSBrw61jaCB0aMaw4bubYyBs4bubbiB0aMOsIG7DsyB24bqrbiB44butIGzDvSBoaeG7h3UgcXXhuqMgdsOgIHRp4bq/dCBraeG7h20gxJHGsOG7o2Mgbmhp4buBdSB0aOG7nWkgZ2lhbi4gVsOsIHRo4bq/LCBuaMOzbSBlbSB0aW4gcuG6sW5nIHTDrG0gaGnhu4N1IHbhu4EgZ8OzaSBUaWR5ciBsw6AgY2jhu6cgxJHhu4EgaOG7r3Ugw61jaCBjw7MgdGjhu4MgaOG7lyB0cuG7oyBt4buNaSBuZ8aw4budaSDEkWFuZyBn4bq3cCBraMOzIGtoxINuIHRyb25nIHZp4buHYyB44butIGzDvSBk4buvIGxp4buHdS4NCg0KIyMgR2nhu5tpIHRoaeG7h3UgduG7gSBnw7NpIFRpZHlyDQoNCiMjIyBOZ3Xhu5NuIGfhu5FjDQoNCkfDs2kgdGlkeXIgbMOgIG3hu5l0IHBo4bqnbiBj4bunYSBUaWR5dmVyc2UsIG3hu5l0IGLhu5kgc8awdSB04bqtcCBjw6FjIGfDs2kgUiDEkcaw4bujYyB0aGnhur90IGvhur8gY2hvIHZp4buHYyB44butIGzDvSB2w6AgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UuIEfDs2kgdGlkeXIgdOG6rXAgdHJ1bmcgY2jhu6cgeeG6v3UgdsOgbyBjw6FjIGhv4bqhdCDEkeG7mW5nIGzDoG0gZ+G7jW4gZ8OgbmcgdsOgIGPhuqV1IHRyw7pjIGzhuqFpIGThu68gbGnhu4d1LCBnacO6cCBk4buFIGTDoG5nIGNodXnhu4NuIMSR4buVaSB04bqtcCBk4buvIGxp4buHdSB0aMOgbmggxJHhu4tuaCBk4bqhbmcgdGlkeSAoZ+G7jW4gZ8OgbmcpIHRodeG6rW4gdGnhu4duIGjGoW4gY2hvIHBow6JuIHTDrWNoIHbDoCB0cuG7sWMgcXVhbiBow7NhLg0KDQpHw7NpIHRpZHlyIMSRxrDhu6NjIHBow6F0IHRyaeG7g24gYuG7n2kgSGFkbGV5IFdpY2toYW0sIG3hu5l0IG5ow6AgdGjhu5FuZyBrw6ogdsOgIG5ow6Aga2hvYSBo4buNYyBk4buvIGxp4buHdSBu4buVaSB0aeG6v25nIHbhu5tpIMSRw7NuZyBnw7NwIGNobyBuZ8O0biBuZ+G7ryBs4bqtcCB0csOsbmggUiB2w6Aga2jDoWkgbmnhu4dtIGThu68gbGnhu4d1IHRpZHkuIEhhZGxleSBXaWNraGFtIGPFqW5nIGzDoCBuZ8aw4budaSBzw6FuZyB04bqhbyByYSBjw6FjIGfDs2kgcGjhu5UgYmnhur9uIGtow6FjIG5oxrAgZ2dwbG90MiB2w6AgZHBseXIuIMOUbmcgxJHDoyBwaMOhdCB0cmnhu4NuIHRpZHlyIG5oxrAgbeG7mXQgcGjhuqduIGPhu6dhIG7hu5cgbOG7sWMgY+G7p2EgbcOsbmggxJHhu4MgdGjDumMgxJHhuql5IG5ndXnDqm4gdOG6r2MgY+G7p2EgZOG7ryBsaeG7h3UgdGlkeSwgbmjhuqVuIG3huqFuaCB2aeG7h2MgdOG7lSBjaOG7qWMgdsOgIHPhuq9wIHjhur9wIGThu68gbGnhu4d1IHRoZW8gbeG7mXQgY+G6pXUgdHLDumMgbmjhuqV0IHF1w6FuIMSR4buDIHThuqFvIHRodeG6rW4gbOG7o2kgY2hvIHBow6JuIHTDrWNoIHbDoCB0cnV54buBbiB04bqjaSB0aMO0bmcgdGluLg0KDQojIyMgQ2jhu6ljIG7Eg25nDQoNCkfDs2kgdGlkeXIgY3VuZyBj4bqlcCBt4buZdCBsb+G6oXQgY8OhYyBow6BtIGjhu5cgdHLhu6MgY2jDum5nIHRhIHRyb25nIHZp4buHYyBsw6BtIGfhu41uIHbDoCB0w6FpIGPhuqV1IHRyw7pjIGThu68gbGnhu4d1LiBDw6FjIGjDoG0gbsOgeSBjw7MgdGjhu4MgxJHGsOG7o2MgbmjDs20gdGjDoG5oIG3hu5l0IHPhu5EgZGFuaCBt4bulYyBjaMOtbmgsIG3hu5dpIGRhbmggbeG7pWMgcGjhu6VjIHbhu6UgY2hvIG3hu5l0IG3hu6VjIMSRw61jaCBj4bulIHRo4buDIHRyb25nIHZp4buHYyBjaOG7iW5oIHPhu61hIHbDoCB04buVIGNo4bupYyBk4buvIGxp4buHdS4NCg0KIyMjIyBUw6FjaCBk4buvIGxp4buHdQ0KDQpUcm9uZyBnw7NpIHRpZHlyIGjhu5cgdHLhu6MgbmfGsOG7nWkgZMO5bmcgdMOhY2ggZOG7ryBsaeG7h3UgbeG7mXQgY+G7mXQgdGjDoG5oIG5oaeG7gXUgY+G7mXQgZOG7sWEgdHLDqm4gbmjhu69uZyBrw70gdOG7sSBwaMOibiB0w6FjaCBob+G6t2MgY8OhYyBt4bqrdSBi4bqxbmcgaMOgbSBgc2VwYXJhdGVgLCDEkWnhu4F1IG7DoHkgdGjhu7FjIHPhu7EgaOG7r3Ugw61jaCBraGkgYuG6oW4gY8OzIG3hu5l0IGPhu5l0IGNo4bupYSBjw6FjIGdpw6EgdHLhu4sga+G6v3QgaOG7o3AgduG7m2kgbmhhdSBsw6BtIGNobyB2aeG7h2MgcGjDom4gdMOtY2ggZ+G6t3Agbmhp4buBdSBraMOzIGtoxINuIHbDoCBi4bqhbiBtdeG7kW4gcGjDom4gdMOhY2ggbsOzIHJhIHRow6BuaCBuaOG7r25nIGPhu5l0IHJpw6puZyBiaeG7h3QuIENo4bqzbmcgaOG6oW4sIG3hu5l0IGPhu5l0IGNo4bupYSB0aMO0bmcgdGluIHbhu4EgbmfDoHkgdGjDoW5nIG7Eg20gc2luaCDEkeG7gyBiaeG6v3QgY2hpIHRp4bq/dCBoxqFuIHRhIGPDsyB0aOG7gyBz4butIGThu6VuZyBow6BtIHNlcGFyYXRlIMSR4buDIHTDoWNoIHJpw6puZyBsw6BtIGJhIGPhu5l0IG5nw6B5LCB0aMOhbmcsIG7Eg20gxJHhu4MgcGjhu6VjIHbhu6UgY2hvIG3hu6VjIMSRw61jaCBjw7RuZyB2aeG7h2MgY+G7pSB0aOG7gy4gTmdvw6BpIHJhLCBjaOG7qWMgbsSDbmcgbsOgeSBraMO0bmcgbMOgbSB0aGF5IMSR4buVaSBk4buvIGxp4buHdSBn4buRYyBtw6AgY2jhu4kgdOG6oW8gcmEgY8OhYyBj4buZdCBt4bubaSB04burIGThu68gbGnhu4d1IGJhbiDEkeG6p3UsIMSRaeG7gXUgbsOgeSBjaG8gcGjDqXAgY2jDum5nIHRhIGJp4bq/biDEkeG7lWkgduG7gSBk4buvIGxp4buHdSBn4buRYyBk4buFIGTDoG5nIGjGoW4gbuG6v3UgbXXhu5FuLg0KDQojIyMjIEvhur90IGjhu6NwIGPhu5l0DQoNClRyw6FpIG5nxrDhu6NjIHbhu5tpIGNo4bupYyBuxINuZyB0w6FjaCBj4buZdCwgZ8OzaSBUaWR5ciBz4bq9IGdpw7pwIGNow7puZyB0YSBr4bq/dCBo4bujcCBjw6FjIGPhu5l0IGzhuqFpIHRow6BuaCBt4buZdCBj4buZdCBi4bqxbmcgY8OhY2ggZ2jDqXAgY8OhYyBnacOhIHRy4buLIGPhu6dhIGNow7puZyBs4bqhaSB24bubaSBuaGF1LiBHaeG6oyBz4butIHRhIGPDsyBt4buZdCBj4buZdCBjaOG7qWEgaOG7jSB2w6AgbeG7mXQgY+G7mXQgY2jhu6lhIHTDqm4gdGjDrCBjw7MgdGjhu4MgZ2jDqXAgaGFpIGPhu5l0IG7DoHkgdGjDoG5oIG3hu5l0IGPhu5l0IGjhu40gdsOgIHTDqm4gaG/DoG4gY2jhu4luaCBi4bqxbmcgaMOgbSBgdW5pdGVgLCDEkWnhu4F1IG7DoHkgc+G6vSBnacO6cCBk4buvIGxp4buHdSB0cuG7nyBuw6puIGfhu41uIGfDoG5nIHbDoCBwaMO5IGjhu6NwIMSR4buDIHPhu60gZOG7pW5nLiDEkMOieSBsw6AgbeG7mXQgY2jhu6ljIG7Eg25nIGThu4UgZMOgbmcgc+G7rSBk4bulbmcgdHV5IG5oacOqbiB04bqhbyByYSBj4buZdCBt4bubaSBjw7MgxJHhu5kgbGluaCBob+G6oXQgY2FvLCB0aHXhuq1uIHRp4buHbiB0cm9uZyBxdcOhIHRyw6xuaCB44butIGzDvS4NCg0KIyMjIyBQaXZvdGluZyhCaeG6v24gxJHhu5VpKQ0KDQotICAgIlBpdm90aW5nIiAoQ2h1eeG7g24gxJHhu5VpKTogY2h1eeG7g24gxJHhu5VpIGdp4buvYSBjw6FjIGThuqFuZyBk4buvIGxp4buHdSBy4buZbmcgdsOgIGTDoGkuIHRpZHlyIGdp4bubaSB0aGnhu4d1IHBpdm90X2xvbmdlcigpIHbDoCBwaXZvdF93aWRlcigpLCB0aGF5IHRo4bq/IGPDoWMgaMOgbSBzcHJlYWQoKSB2w6AgZ2F0aGVyKCkuIFF1w6EgdHLDrG5oIGJp4bq/biDEkeG7lWkgbsOgeSDEkeG6t2MgYmnhu4d0IGjhu691IMOtY2gga2hpIGLhuqFuIGPhuqduIHRoYXkgxJHhu5VpIGPhuqV1IHRyw7pjIGThu68gbGnhu4d1IMSR4buDIHBow7kgaOG7o3AgaMahbiB24bubaSBt4bulYyDEkcOtY2ggcGjDom4gdMOtY2ggaG/hurdjIHRy4buxYyBxdWFuIGjDs2EuDQoNCi0gICBCaeG6v24gxJHhu5VpIHThu6sgZOG6oW5nIETDoGkgc2FuZyBS4buZbmc6IEtoaSBk4buvIGxp4buHdSDhu58gxJHhu4tuaCBk4bqhbmcgZMOgaSwgbeG7l2kgcXVhbiBzw6F0IMSRxrDhu6NjIGJp4buDdSBkaeG7hW4gYuG6sW5nIG5oaeG7gXUgaMOgbmcgdsOgIGPDsyBjw6FjIGPhu5l0IHjDoWMgxJHhu4tuaCByacOqbmcgYmnhu4d0IGxpw6puIGvhur90IG5o4buvbmcgaMOgbmcgbsOgeSBs4bqhaSB24bubaSBuaGF1LiBEbyDEkcOzLCBow6BtIHBpdm90X3dpZGVyKCkgc+G6vSBnacO6cCB0YSBjaHV54buDbiDEkeG7lWkgZOG7ryBsaeG7h3UgdOG7qyDEkeG7i25oIGThuqFuZyBkw6BpIHNhbmcgxJHhu4tuaCBk4bqhbmcgcuG7mW5nIGLhurFuZyBjw6FjaCBwaMOibiBy4bqjaSBnacOhIHRy4buLLCDEkWnhu4F1IG7DoHkgcGjhu6UgdGh14buZYyB2w6BvIG3hu6VjIHRpw6p1IHBow6JuIHTDrWNoIGLhu5kgZOG7ryBsaeG7h3UgY+G7p2EgbmfGsOG7nWkgc+G7rSBk4bulbmcuDQoNCi0gICBCaeG6v24gxJHhu5VpIHThu6sgZOG6oW5nIFLhu5luZyBzYW5nIETDoGk6IE5nxrDhu6NjIGzhuqFpLCBraGkgZOG7ryBsaeG7h3Ug4bufIMSR4buLbmggZOG6oW5nIHLhu5luZywgbeG7l2kgcXVhbiBzw6F0IMSRxrDhu6NjIGJp4buDdSBkaeG7hW4gYuG6sW5nIG3hu5l0IGjDoG5nIMSRxqFuIHbDoCBjw6FjIGJp4bq/biBraMOhYyBuaGF1IMSRxrDhu6NjIGzGsHUgdHLhu68gdHJvbmcgY8OhYyBj4buZdCByacOqbmcgYmnhu4d0LiBIw6BtIHBpdm90X2xvbmdlcigpIHPhur0gZ2nDunAgQ2h1eeG7g24gxJHhu5VpIGThu68gbGnhu4d1IHThu6sgxJHhu4tuaCBk4bqhbmcgcuG7mW5nIHNhbmcgxJHhu4tuaCBk4bqhbmcgZMOgaSBi4bqxbmcgY8OhY2ggZ29tIGzhuqFpIGPDoWMgY+G7mXQgxJHhu4MgY8OzIHRo4buDIHBow7kgaOG7o3AgduG7m2kgbmh1IGPhuqd1IGPhu6dhIG5nxrDhu51pIHRo4buxYyBoaeG7h24uDQoNCiMjIyMgWOG7rSBsw60gZ2nDoSB0cuG7iyB0aGnhur91DQoNClZp4buHYyBwaMOibiB0w61jaCBk4buvIGxp4buHdSBz4bq9IGtow7RuZyDEkeG6oXQgxJHGsOG7o2Mga+G6v3QgcXXhuqMgY2jDrW5oIHjDoWMgbuG6v3UgZOG7ryBsaeG7h3UgZ+G6t3AgcGjhuqNpIG5o4buvbmcgZ2nDoSB0cuG7iyBi4buLIHRoaeG6v3Ugc8OzdCwgxJHhu4Mga2jhuq9jIHBo4bulYyB0w6xuaCB0cuG6oW5nIG5oxrAgduG6rXkgdGjDrCBnw7NpIG7DoHkgZ2nDunAgbmfGsOG7nWkgc+G7rSBk4bulbmcgeOG7rSBsw70gbmjhu69uZyBkw7JuZyBi4buLIHRoaeG6v3UgZ2nDoSB0cuG7iyBi4bqxbmcgaMOgbSBgY29tcGxldGVgLCBow6BtIG7DoHkgc+G6vSBr4bq/dCBo4bujcCBjw6FjIGdpw6EgdHLhu4sga2jDtG5nIGLhu4sgdGhp4bq/dSB0cm9uZyBjw6FjIGPhu5l0IGNo4buJIMSR4buLbmggdOG7qyDEkcOzIMSRaeG7gW4gdsOgbyBuaOG7r25nIGTDsm5nIGLhu4sgdGhp4bq/dS4gSMahbiBu4buvYSwgdGEgY8OzIHRo4buDIGxv4bqhaSBi4buPIGPDoWMgZ2nDoSB0cuG7iyB0aGnhur91IGLhurFuZyBow6BtIGRyb3BfbmEgaG/hurdjIHRoYXkgdGjhur8gY8OhYyBnacOhIHRy4buLIGLhu4sgdGhp4bq/dSBi4bqxbmcgaMOgbSBgZmlsbGAsIGByZXBsYWNlX25hYC4NCg0KIyMjIyBOZXN0aW5nKEfhu5lwKSB2w6AgVW5uZXN0aW5nKGtow7RpIHBo4bulYykNCg0KTmVzdCgpIMSRxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIHThuqFvIG3hu5l0IGtodW5nIGThu68gbGnhu4d1IGzhu5NuZyBuaGF1IGLhurFuZyBjw6FjaCBuaMOzbSBk4buvIGxp4buHdSBk4buxYSB0csOqbiBjw6FjIGJp4bq/biBj4bulIHRo4buDLiBOw7MgY2hvIHBow6lwIGLhuqFuIG5ow7NtIGPDoWMgcXVhbiBzw6F0IGxpw6puIHF1YW4gduG7m2kgbmhhdSB0cm9uZyBt4buZdCBj4buZdCBkdXkgbmjhuqV0Lg0KDQpVbm5lc3QoKSDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBt4bufIHLhu5luZyBt4buZdCBraHVuZyBk4buvIGxp4buHdSBs4buTbmcgbmhhdSB0aMOgbmggbeG7mXQga2h1bmcgZOG7ryBsaeG7h3UgdGjDtG5nIHRoxrDhu51uZywgdHJvbmcgxJHDsyBt4buXaSBxdWFuIHPDoXQgbOG7k25nIG5oYXUgdHLhu58gdGjDoG5oIG3hu5l0IGTDsm5nIHJpw6puZy4gTsOzIHRyw61jaCB4deG6pXQgZOG7ryBsaeG7h3UgbOG7k25nIG5oYXUgdsOgIG3hu58gcuG7mW5nIGNow7puZyB0aMOgbmggbmhp4buBdSBkw7JuZy4NCg0KIyMjIE3hu6VjIHRpw6p1DQoNCk3hu6VjIHRpw6p1IGNow61uaCBj4bunYSB0aWR5ciBsw6AgY3VuZyBj4bqlcCBt4buZdCBi4buZIGPDtG5nIGPhu6UgduG7m2kgY8OhYyBjaOG7qWMgbsSDbmcgxJHGoW4gZ2nhuqNuIGjDs2EgcXXDoSB0csOsbmggY+G6pXUgdHLDumMgbOG6oWkgdsOgIGzDoG0gZ+G7jW4gZOG7ryBsaeG7h3UuIEfDs2kgbsOgeSBjdW5nIGPhuqVwIGPDoWMgY2jhu6ljIG7Eg25nIG5oxrAgZ2F0aGVyKCksIHNwcmVhZCgpLCBzZXBhcmF0ZSgpLCB1bml0ZSgpLCBwaXZvdF9sb25nZXIoKSB2w6AgcGl2b3Rfd2lkZXIoKSwgY2hvIHBow6lwIG5nxrDhu51pIGTDuW5nIGNodXnhu4NuIMSR4buVaSBk4buvIGxp4buHdSBnaeG7r2EgY8OhYyDEkeG7i25oIGThuqFuZyBy4buZbmcgdsOgIGTDoGksIHBow6JuIHTDoWNoIHbDoCBr4bq/dCBo4bujcCBj4buZdCwgdsOgIGNodXnhu4NuIMSR4buVaSBk4buvIGxp4buHdSDEkeG7gyB04bqhbyBi4bqjbmcgdMOzbSB04bqvdC4gQ8OhYyBob+G6oXQgxJHhu5luZyBuw6B5IGzDoCBj4bqnbiB0aGnhur90IMSR4buDIHThu5UgY2jhu6ljIHbDoCB44butIGzDvSBk4buvIGxp4buHdSBt4buZdCBjw6FjaCBk4buFIGTDoG5nIHbDoCB0csOtY2ggeHXhuqV0IHRow7RuZyB0aW4uDQoNCkfDs2kgdGlkeXIgxJHDoyB0aHUgaMO6dCBz4buxIHF1YW4gdMOibSDEkcOhbmcga+G7gyB0cm9uZyBj4buZbmcgxJHhu5NuZyBSIG5o4budIGPDuiBwaMOhcCBk4buFIGhp4buDdSB2w6AgbmjhuqV0IHF1w6FuLCBwaMO5IGjhu6NwIHbhu5tpIG5ndXnDqm4gdOG6r2MgY+G7p2EgVGlkeXZlcnNlLiBOw7MgxJHDoyB0cuG7nyB0aMOgbmggbeG7mXQgY8O0bmcgY+G7pSDEkcaw4bujYyBz4butIGThu6VuZyBy4buZbmcgcsOjaSDEkeG7gyBsw6BtIHPhuqFjaCBk4buvIGxp4buHdSwgdGnhu4FuIHjhu60gbMO9IHbDoCBj4bqldSB0csO6YyBs4bqhaSB0cm9uZyBxdXkgdHLDrG5oIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IGLhurFuZyBSLg0KDQojIyMgTOG7o2kgw61jaA0KDQpDw6FjIGzhu6NpIMOtY2ggY+G7p2Egdmnhu4djIHPhu60gZOG7pW5nIGfDs2kgdGlkeXIgYmFvIGfhu5NtOg0KDQotICAgROG7hSBkw6BuZyBsw6BtIHPhuqFjaCBk4buvIGxp4buHdTogR8OzaSB0aWR5ciBjdW5nIGPhuqVwIGPDoWMgaMOgbSDEkcahbiBnaeG6o24gdsOgIGThu4UgaGnhu4N1IMSR4buDIGPhuqV1IHRyw7pjIGzhuqFpIHbDoCBsw6BtIGfhu41uIGThu68gbGnhu4d1LiBOw7MgY3VuZyBj4bqlcCBjw6FjIGNo4bupYyBuxINuZyBuaMawIGdhdGhlcigpLCBzcHJlYWQoKSwgc2VwYXJhdGUoKSwgdW5pdGUoKSwgcGl2b3RfbG9uZ2VyKCksIHbDoCBwaXZvdF93aWRlcigpIGNobyBwaMOpcCBuZ8aw4budaSBkw7luZyBk4buFIGTDoG5nIGNodXnhu4NuIMSR4buVaSBk4buvIGxp4buHdSBnaeG7r2EgY8OhYyDEkeG7i25oIGThuqFuZyBy4buZbmcgdsOgIGTDoGksIHBow6JuIHTDoWNoIHbDoCBr4bq/dCBo4bujcCBj4buZdCwgdsOgIGJp4bq/biDEkeG7lWkgZOG7ryBsaeG7h3UgxJHhu4MgdOG6oW8gYuG6o25nIHTDs20gdOG6r3QuIE5o4buvbmcgdGhhbyB0w6FjIG7DoHkgbMOgIGPhuqduIHRoaeG6v3QgxJHhu4MgdOG7lSBjaOG7qWMgdsOgIHjhu60gbMO9IGThu68gbGnhu4d1IG3hu5l0IGPDoWNoIGhp4buHdSBxdeG6oy4NCg0KLSAgIFTDrWNoIGjhu6NwIHbhu5tpIHRpZHl2ZXJzZTogR8OzaSB0aWR5ciBsw6AgbeG7mXQgcGjhuqduIGPhu6dhIGjhu4cgc2luaCB0aMOhaSB0aWR5dmVyc2UsIGzDoCBt4buZdCBi4buZIHPGsHUgdOG6rXAgY8OhYyBnw7NpIFIgxJHGsOG7o2MgdGhp4bq/dCBr4bq/IGNobyB2aeG7h2MgbMOgbSBz4bqhY2ggdsOgIHBow6JuIHTDrWNoIGThu68gbGnhu4d1LiBOw7MgdMOtY2ggaOG7o3AgbeG7mXQgY8OhY2ggbcaw4bujdCBtw6AgduG7m2kgY8OhYyBnw7NpIHRpZHl2ZXJzZSBraMOhYyBuaMawIGRwbHlyIHbDoCBnZ3Bsb3QyLCBjaG8gcGjDqXAgcXV5IHRyw6xuaCBsw6BtIHZp4buHYyBtxrDhu6N0IG3DoCB2w6AgY8O6IHBow6FwIG5o4bqldCBxdcOhbi4gVMOtY2ggaOG7o3AgbsOgeSBjaG8gcGjDqXAgbmfGsOG7nWkgZMO5bmcgdGjhu7FjIGhp4buHbiBjw6FjIHRoYW8gdMOhYyBwaOG7qWMgdOG6oXAgdHLDqm4gZOG7ryBsaeG7h3UgdsOgIHThuqFvIGJp4buDdSDEkeG7kyBt4buZdCBjw6FjaCBuaOG6pXQgcXXDoW4gdsOgIGhp4buHdSBxdeG6oy4NCg0KLSAgIFTGsMahbmcgdGjDrWNoIHbhu5tpIG5ndXnDqm4gdOG6r2MgZOG7ryBsaeG7h3UgdGlkeTogR8OzaSB0aWR5ciB0dcOibiB0aOG7pyBuZ3V5w6puIHThuq9jIGPhu6dhIGThu68gbGnhu4d1IHRpZHksIG5o4bqlbiBt4bqhbmggdmnhu4djIHThu5UgY2jhu6ljIGThu68gbGnhu4d1IHRoZW8gbeG7mXQgY+G6pXUgdHLDumMgbmjhuqV0IHF1w6FuLiBC4bqxbmcgY8OhY2ggdHXDom4gdGjhu6cgbmd1ecOqbiB04bqvYyBk4buvIGxp4buHdSB0aWR5LCBuZ8aw4budaSBkw7luZyBjw7MgxJHGsOG7o2MgZOG7ryBsaeG7h3UgcsO1IHLDoG5nIGjGoW4sIGThu4Uga2jDoW0gcGjDoSBoxqFuIHbDoCBr4bq/dCBxdeG6oyBwaMOibiB0w61jaCDEkcOhbmcgdGluIGPhuq15IGjGoW4uIEThu68gbGnhu4d1IHRpZHkgxJHhuqNtIGLhuqNvIG3hu5dpIGJp4bq/biBjw7MgbeG7mXQgY+G7mXQgcmnDqm5nLCBt4buXaSBxdWFuIHPDoXQgY8OzIG3hu5l0IGjDoG5nIHJpw6puZyB2w6AgbeG7l2kgw7QgY2jhu6lhIG3hu5l0IGdpw6EgdHLhu4sgZHV5IG5o4bqldC4NCg0KLSAgIEjhu5cgdHLhu6MgcGjDom4gdMOtY2ggdsOgIHRy4buxYyBxdWFuIGjDs2EgZOG7ryBsaeG7h3U6IEThu68gbGnhu4d1IHRpZHkgxJHGoW4gZ2nhuqNuIGjDs2EgcXXDoSB0csOsbmggcGjDom4gdMOtY2ggdsOgIHRy4buxYyBxdWFuIGjDs2EgZOG7ryBsaeG7h3UuIELhurFuZyBjw6FjaCBjaHV54buDbiDEkeG7lWkgZOG7ryBsaeG7h3UgdGjDoG5oIMSR4buLbmggZOG6oW5nIHRpZHksIHZp4buHYyB0aOG7sWMgaGnhu4duIGPDoWMgdMOhYyB24bulIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IHRow7RuZyB0aMaw4budbmcsIMOhcCBk4bulbmcgcGjDom4gdMOtY2ggdGjhu5FuZyBrw6ogdsOgIHThuqFvIGJp4buDdSDEkeG7kyB0aMO0bmcgdGluIHRy4bufIG7Dqm4gZOG7hSBkw6BuZyBoxqFuLiBE4buvIGxp4buHdSB0aWR5IGdp4bqjbSB0aGnhu4N1IHZp4buHYyBwaOG6o2kgbMOgbSB2aeG7h2MgcGjhu6ljIHThuqFwIHbhu5tpIGThu68gbGnhu4d1LCBjaG8gcGjDqXAgY8OhYyBuaMOgIHBow6JuIHTDrWNoIHThuq1wIHRydW5nIG5oaeG7gXUgaMahbiB2w6BvIHZp4buHYyB0csOtY2ggeHXhuqV0IHRow7RuZyB0aW4gdsOgIMSRxrBhIHJhIHF1eeG6v3QgxJHhu4tuaCBk4buxYSB0csOqbiBk4buvIGxp4buHdS4NCg0KVMOzbSBs4bqhaSwgbeG7pWMgdGnDqnUgY2jDrW5oIGPhu6dhIGfDs2kgdGlkeXIgbMOgIGN1bmcgY+G6pXAgY8OhYyBjw7RuZyBj4bulIMSR4buDIGzDoG0gc+G6oWNoIHbDoCBj4bqldSB0csO6YyBs4bqhaSBk4buvIGxp4buHdSwgduG7m2kgbOG7o2kgw61jaCBsw6AgZ2nDunAgbmfGsOG7nWkgZMO5bmcgZOG7hSBkw6BuZyBjaHV54buDbiDEkeG7lWkgZOG7ryBsaeG7h3UgdGjDoG5oIMSR4buLbmggZOG6oW5nIHRpZHkuIMSQaeG7gXUgbsOgeSBo4buXIHRy4bujIHBow6JuIHTDrWNoIGThu68gbGnhu4d1LCB0w61jaCBo4bujcCB24bubaSBjw6FjIGfDs2kgdGlkeXZlcnNlIGtow6FjIHbDoCBo4buXIHRy4bujIG5ndXnDqm4gdOG6r2MgZOG7ryBsaeG7h3UgdGlkeSDEkeG7gyBoaeG7g3UgZOG7ryBsaeG7h3UgdOG7kXQgaMahbiB2w6AgdOG6oW8gcXV5IHRyw6xuaCBsw6BtIHZp4buHYyBoaeG7h3UgcXXhuqMNCg0KIyMjIMavdSB2w6AgbmjGsOG7o2MgxJFp4buDbSBj4bunYSBnw7NpIHRpZHlyDQoNCiMjIyMgxq91IMSRaeG7g20gY+G7p2EgZ8OzaSB0aWR5cg0KDQrEkMahbiBnaeG6o24gaMOzYSB2aeG7h2MgeOG7rSBsw70gZOG7ryBsaeG7h3U6IHRpZHlyIGN1bmcgY+G6pXAgbeG7mXQgYuG7mSBjw7RuZyBj4bulIHbhu5tpIGPDoWMgaMOgbSBk4buFIGhp4buDdSBnacO6cCDEkcahbiBnaeG6o24gaMOzYSBjw7RuZyB2aeG7h2MgY+G6pXUgdHLDumMgbOG6oWkgdsOgIGzDoG0gc+G6oWNoIGThu68gbGnhu4d1LiBOw7MgY3VuZyBj4bqlcCBjw6FjIGjDoG0gbmjGsCBnYXRoZXIoKSwgc3ByZWFkKCksIHNlcGFyYXRlKCksIHVuaXRlKCksIHBpdm90X2xvbmdlcigpIHbDoCBwaXZvdF93aWRlcigpIGNobyBwaMOpcCBuZ8aw4budaSBkw7luZyBk4buFIGTDoG5nIGNodXnhu4NuIMSR4buVaSBk4buvIGxp4buHdSBnaeG7r2EgY8OhYyDEkeG7i25oIGThuqFuZyBy4buZbmcgdsOgIGTDoGksIHBow6JuIHTDoWNoIHbDoCBr4bq/dCBo4bujcCBj4buZdCwgdsOgIGJp4bq/biDEkeG7lWkgZOG7ryBsaeG7h3UgxJHhu4MgdOG6oW8gYuG6o25nIHTDs20gdOG6r3QuIE5o4buvbmcgaG/huqF0IMSR4buZbmcgbsOgeSBsw6AgY+G6p24gdGhp4bq/dCDEkeG7gyB04buVIGNo4bupYyB2w6AgeOG7rSBsw70gZOG7ryBsaeG7h3UgbeG7mXQgY8OhY2ggaGnhu4d1IHF14bqjLg0KDQpUw61jaCBo4bujcCB24bubaSB0aWR5dmVyc2U6IHRpZHlyIGzDoCBt4buZdCBwaOG6p24gY+G7p2EgaOG7hyBzaW5oIHRow6FpIHRpZHl2ZXJzZSwgbeG7mXQgYuG7mSBzxrB1IHThuq1wIGPDoWMgZ8OzaSBSIMSRxrDhu6NjIHRoaeG6v3Qga+G6vyDEkeG7gyBsw6BtIHPhuqFjaCB2w6AgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UuIE7DsyB0w61jaCBo4bujcCBt4buZdCBjw6FjaCBtxrDhu6N0IG3DoCB24bubaSBjw6FjIGfDs2kgdGlkeXZlcnNlIGtow6FjIG5oxrAgZHBseXIgdsOgIGdncGxvdDIsIGNobyBwaMOpcCBxdXkgdHLDrG5oIGzDoG0gdmnhu4djIHRyxqFuIHRydSB2w6AgY8OzIGPDuiBwaMOhcCBuaOG6pXQgcXXDoW4uIFTDrWNoIGjhu6NwIG7DoHkgY2hvIHBow6lwIG5nxrDhu51pIGTDuW5nIHRo4buxYyBoaeG7h24gY8OhYyBwaMOpcCB0b8OhbiBwaOG7qWMgdOG6oXAgdHLDqm4gZOG7ryBsaeG7h3UgdsOgIHThuqFvIGJp4buDdSDEkeG7kyBt4buZdCBjw6FjaCBuaOG6pXQgcXXDoW4gdsOgIGhp4buHdSBxdeG6oy4NCg0KVHXDom4gdGjhu6cgbmd1ecOqbiB04bqvYyBk4buvIGxp4buHdSB0aWR5OiB0aWR5ciB0dcOibiB0aOG7pyBjw6FjIG5ndXnDqm4gdOG6r2MgY+G7p2EgZOG7ryBsaeG7h3UgdGlkeSwgbmjhuqVuIG3huqFuaCB2aeG7h2MgdOG7lSBjaOG7qWMgZOG7ryBsaeG7h3UgdGjDoG5oIG3hu5l0IGPhuqV1IHRyw7pjIG5o4bqldCBxdcOhbi4gQuG6sW5nIHZp4buHYyB0dcOibiB0aOG7pyBuZ3V5w6puIHThuq9jIGThu68gbGnhu4d1IHRpZHksIG5nxrDhu51pIGTDuW5nIGPDsyBk4buvIGxp4buHdSByw7UgcsOgbmcgaMahbiwga2jDoW0gcGjDoSBk4buvIGxp4buHdSBoaeG7h3UgcXXhuqMgaMahbiB2w6Aga+G6v3QgcXXhuqMgcGjDom4gdMOtY2ggxJHDoW5nIHRpbiBj4bqteSBoxqFuLiBE4buvIGxp4buHdSB0aWR5IMSR4bqjbSBi4bqjbyBy4bqxbmcgbeG7l2kgYmnhur9uIGPDsyBt4buZdCBj4buZdCByacOqbmcsIG3hu5dpIHF1YW4gc8OhdCBjw7MgbeG7mXQgaMOgbmcgcmnDqm5nLCB2w6AgbeG7l2kgw7QgY2jhu6lhIG3hu5l0IGdpw6EgdHLhu4sgZHV5IG5o4bqldC4NCg0KIyMjIyBOaMaw4bujYyDEkWnhu4NtIGPhu6dhIGfDs2kgdGlkeXINCg0KR2nhu5tpIGjhuqFuIGNo4bupYyBuxINuZzogTeG6t2MgZMO5IHRpZHlyIGN1bmcgY+G6pXAgbeG7mXQgdOG6rXAgaOG7o3AgaOG7r3Ugw61jaCBjw6FjIGjDoG0gxJHhu4MgY+G6pXUgdHLDumMgbOG6oWkgdsOgIGzDoG0gc+G6oWNoIGThu68gbGnhu4d1LCBuaMawbmcgbsOzIGPDsyB0aOG7gyBraMO0bmcgxJHDoXAg4bupbmcgxJHGsOG7o2MgdOG6pXQgY+G6oyBjw6FjIHTDrG5oIGh14buRbmcgeOG7rSBsw70gZOG7ryBsaeG7h3Uga2jDoWMgbmhhdS4gQ8OzIHRo4buDIGPDsyBuaOG7r25nIHRyxrDhu51uZyBo4bujcCB5w6p1IGPhuqd1IGPDoWMgcGjDqXAgdG/DoW4gcGjhu6ljIHThuqFwIGhv4bq3YyDEkeG6t2MgdGjDuSBoxqFuIHbDoCB0aWR5ciBjw7MgdGjhu4Mga2jDtG5nIGPDsyBjw6FjIGjDoG0gZMOgbmggcmnDqm5nIGNobyBuaOG7r25nIG5oaeG7h20gduG7pSDEkcOzLg0KDQpLaMOzIGtoxINuIHRyb25nIHF1w6EgdHLDrG5oIGjhu41jIHThuq1wOiBHaeG7kW5nIG5oxrAgYuG6pXQga+G7syBnw7NpIGhheSBjw7RuZyBj4bulIG3hu5tpIG7DoG8sIHZp4buHYyBz4butIGThu6VuZyB0aWR5ciBt4buZdCBjw6FjaCBoaeG7h3UgcXXhuqMgY8WpbmcgY8OzIHRo4buDIGfhurdwIGtow7Mga2jEg24gYmFuIMSR4bqndS4gTmfGsOG7nWkgZMO5bmcgY+G6p24gbMOgbSBxdWVuIHbhu5tpIGPDuiBwaMOhcCB2w6AgY8OhYyBow6BtIGPhu6UgdGjhu4MgY+G7p2EgdGlkeXIgxJHhu4MgdOG6rW4gZOG7pW5nIHThu5FpIMSRYSBraOG6oyBuxINuZyBj4bunYSBuw7MuIFF1w6EgdHLDrG5oIGjhu41jIG7DoHkgY8OzIHRo4buDIHnDqnUgY+G6p3UgbeG7mXQga2hv4bqjbmcgdGjhu51pIGdpYW4gdsOgIG7hu5cgbOG7sWMgbmjhuqV0IMSR4buLbmguDQoNClBo4bulIHRodeG7mWMgdsOgbyB0aWR5dmVyc2U6IE3hurdjIGTDuSB2aeG7h2MgbMOgIG3hu5l0IHBo4bqnbiBj4bunYSB0aWR5dmVyc2UgbWFuZyBs4bqhaSBuaGnhu4F1IGzhu6NpIMOtY2gsIG5oxrBuZyDEkeG7k25nIHRo4budaSBjxaluZyBjw7MgdGjhu4MgbMOgIG3hu5l0IGjhuqFuIGNo4bq/IMSR4buRaSB24bubaSBuaOG7r25nIG5nxrDhu51pIGTDuW5nIMawYSB0aMOtY2ggaG/hurdjIHBo4bulIHRodeG7mWMgdsOgbyBjw6FjIGfDs2kgeOG7rSBsw70gZOG7ryBsaeG7h3Uga2jDoWMgbuG6sW0gbmdvw6BpIGjhu4cgc2luaCB0aMOhaSB0aWR5dmVyc2UuIFPhu60gZOG7pW5nIHRpZHlyIHRyb25nIHF1eSB0csOsbmggbMOgbSB2aeG7h2MgZOG7sWEgdHLDqm4gdGlkeXZlcnNlIGPDsyB0aOG7gyB5w6p1IGPhuqd1IHPhu7EgY2h1eeG7g24gxJHhu5VpIHNhbmcgY8OhYyBnw7NpIHRpZHl2ZXJzZSBraMOhYywgxJFp4buBdSBuw6B5IGPDsyB0aOG7gyBraMO0bmcgcGjDuSBo4bujcCB24bubaSBt4buNaSBuZ8aw4budaS4NCg0KIyMgxJDDs25nIGfDs3AgY+G7p2EgxJHhu4EgdMOgaQ0KDQpCw6BpIHRp4buDdSBsdeG6rW4gY+G7p2EgbmjDs20gZW0gxJHDs25nIGfDs3AgY2hvIGPhu5luZyDEkeG7k25nIHPhu60gZOG7pW5nIFIgdHJvbmcgdmnhu4djIMOhcCBk4bulbmcgZ8OzaSBUaWR5ciB2w6BvIHZp4buHYyBwaMOibiB0w61jaCBk4buvIGxp4buHdSDhu58gbeG7mXQgc+G7kSBraMOtYSBj4bqhbmggcXVhbiB0cuG7jW5nLg0KDQrEkOG6p3UgdGnDqm4sIGNow7puZyBlbSDEkcOjIGdp4bubaSB0aGnhu4d1IGNoaSB0aeG6v3QgduG7gSBnw7NpIFRpZHlyLCBiYW8gZ+G7k20gY8OhYyBjaOG7qWMgbsSDbmcsIGzhu6NpIMOtY2gsIHBoxrDGoW5nIHBow6FwIHbDoCBjw6FjaCB0aOG7qWMgdGjhu7FjIGhp4buHbiBjw6FjIGjDoG0gcXVhbiB0cuG7jW5nIHRyb25nIGfDs2kgVGlkeXIsIMSRaeG7gXUgbsOgeSBnacO6cCBjaG8gbeG7jWkgbmfGsOG7nWkgY8OzIGPDoWkgbmjDrG4gdOG7lW5nIHF1YW4gbmjhuqV0IHbhu4EgbsOzLg0KDQpUaOG7qSBoYWksIGNow7puZyBlbSDDoXAgZOG7pW5nIHbDoG8gdmnhu4djIHBow6JuIHTDrWNoIGThu68gbGnhu4d1IHTDoGkgY2jDrW5oIHF1YSDEkcOzIGzDoG0gbuG7lWkgYuG6rXQgdMOtbmgg4bupbmcgZOG7pW5nIGPhu6dhIFRpZHlyIHRyb25nIGPDoWMgbMSpbmggduG7sWMsIGPFqW5nIG5oxrAgbmjhuqVuIG3huqFuaCBz4buxIHRp4buHbiDDrWNoIHbDoCBoaeG7h3UgcXXhuqMgY+G7p2EgbsOzIHRyb25nIHZp4buHYyBnacO6cCBuZ8aw4budaSBkw7luZyB0aeG6v3Qga2nhu4dtIHRo4budaSBnaWFuIHbDoCBu4buXIGzhu7FjIHRyb25nIGPDtG5nIHZp4buHYyB44butIGzDvSBk4buvIGxp4buHdS4NCg0KQ3Xhu5FpIGPDuW5nLCBuaMOzbSBwaMOibiB0w61jaCDEkcaw4bujYyB0aeG7gW0gbsSDbmcgdsOgIGjhuqFuIGNo4bq/IGPhu6dhIFRpZHlyLCBxdWEgxJHDsyBnacO6cCBjaG8gbmjhu69uZyBuZ8aw4budaSBwaMOibiB0w61jaCBk4buvIGxp4buHdSBz4butIGThu6VuZyBoaeG7h3UgcXXhuqMgbmjhuqV0IGfDs2kgbsOgeSB2w6BvIHRyb25nIGPDtG5nIHZp4buHYyBj4bunYSBo4buNLg0KDQojIyBL4bq/dCBj4bqldQ0KDQoqKkNoxrDGoW5nIDE6IEdp4bubaSB0aGnhu4d1IMSR4buBIHTDoGkqKg0KDQpHaeG7m2kgdGhp4buHdSB04buVbmcgcXVhbiB24buBIHThuqdtIHF1YW4gdHLhu41uZyBj4bunYSB2aeG7h2MgdGjhu7FjIGhp4buHbiDEkeG7gSB0w6BpIG5naGnDqm4gY+G7qXUgZ8OzaSB0aWR5ciB0cm9uZyBSLCDEkcawYSByYSBuaOG7r25nIGzDvSBkbyDEkeG7gyBjaOG7jW4gY2jhu6cgxJHhu4EgbsOgeSB2w6AgbsOqdSBuaOG7r25nIG7hu5lpIGR1bmcgcXVhbiB0cuG7jW5nIGPhu6dhIGfDs2kgdGlkeXIuDQoNCioqQ2jGsMahbmcgMjogVGjhu7FjIGjDoG5oIGPDoWMgaMOgbSB0cm9uZyB0aWR5cioqDQoNCkNoxrDGoW5nIGhhaSBz4bq9IHRyw6xuaCBiw6B5IGPhu6UgdGjhu4MgY2jhu6ljIG7Eg25nIGPDoWMgaMOgbSB0cm9uZyBnw7NpIHRpZHlyIHbDoCDEkcawYSByYSBuaOG7r25nIHbDrSBk4bulIGPhu6UgdGjhu4MgxJHhu4MgaMaw4bubbmcgZOG6q24gdGjhu7FjIGjDoG5oLg0KDQoqKkNoxrDGoW5nIDM6IOG7qG5nIGThu6VuZyBj4bunYSB0aWR5cioqDQoNCkThu7FhIHbDoG8gY8OhYyBjaOG7qWMgbsSDbmcgY+G7p2EgY8OhYyBow6BtIMSRxrDhu6NjIHRyw6xuaCBiw6B5IHRyb25nIGNoxrDGoW5nIDIgc2F1IMSRw7MgxJHGsOG7o2Mgw6FwIGThu6VuZyBsw6puIG5o4buvbmcgZOG7ryBsaeG7h3UgbOG7m24gaMahbiB2w6AgY8OzIGPhuqV1IHRyw7pjIGtow7MgaMahbiBi4bqxbmcgY8OhY2gga+G6v3QgaOG7o3AgdGjDqm0gbeG7mXQgc+G7kSBnw7NpIGtow6FjIG5oxrAgZHBseXIuIFNhdSBraGkgY2h14bqpbiBow7NhIGThu68gbGnhu4d1IHRow6wgdGjhu7FjIGhp4buHbiB0w61uaCB0aMOzYSB2w6AgdHLhu7FjIHF1YW4gaMOzYSBk4buvIGxp4buHdQ0KDQoqKkNoxrDGoW5nIDQ6IEvhur90IGx14bqtbioqDQoNCkNoxrDGoW5nIGN14buRaSBz4bq9IGvhur90IGx14bqtbiBuaOG7r25nIGvhur90IHF14bqjIHRodSDEkcaw4bujYyB0cm9uZyBiw6BpIG7DoHksIMSRxrBhIHJhIG5o4buvbmcgaOG6oW4gY2jhur8gdHJvbmcgcXXDoSB0csOsbmggbmdoacOqbiBj4bupdSB2w6AgxJHhu4EgeHXhuqV0IHBoxrDGoW5nIGjGsOG7m25nIGzDoG0gdGnhur9wIHRoZW8uDQoNCiMgQ0jGr8agTkcgMjogVEjhu7BDIEjDgE5IIEPDgUMgSMOATSBUUk9ORyBUSURZUg0KDQpgYGB7cixlY2hvPUZBTFNFLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoRFQpDQpgYGANCg0KVHJvbmcgY2jGsMahbmcgaGFpIG5ow7NtIGNow7puZyB0w7RpIHRo4buxYyBoaeG7h24gY8OhYyBs4buHbmggdHJvbmcgZ8OzaSBUaWR5ciDEkeG7gyBnacO6cCBuZ8aw4budaSDEkeG7jWMgY8OzIHRo4buDIGhp4buDdSByw7UgY8OhYyBjaOG7qWMgbsSDbmcgdHJvbmcgZ8OzaSBuw6B5LiBU4burIMSRw7MsIG5o4buvbmcgbmfGsOG7nWkgcXVhbiB0w6JtIMSR4bq/biBnw7NpIFRpZHlyIMOhcCBk4bulbmcgY8OhYyBow6BtIHbDoG8gY8O0bmcgdmnhu4djIHjhu60gbMOtIGLhu5kgZOG7ryBsaeG7h3UgY+G7p2EgaOG7jSBuaGFuaCBjaMOzbmcgaMahbi4gVmnhu4djIGdp4bubaSB0aGnhu4d1IGNoaSB0aeG6v3QgduG7gSBz4butIGThu6VuZyBnw7NpIFRpZHlyIHRow7RuZyBxdWEgdmnhu4djIHRo4buxYyBow6BuaCB0csOqbiBk4buvIGxp4buHdSBt4bqrdSBsw6AgbuG7gW4gdOG6o25nIHF1YW4gdHLhu41uZyDEkeG7gyBuaMOzbSBjaMO6bmcgdMO0aSBjw7MgdGjhu4Mg4bupbmcgZOG7pW5nIFRpZHlyIOG7nyBjw6FjIHBo4bqnbiBzYXUNCg0KIyMgQmnhur9uIMSR4buVaSBk4buvIGxp4buHdSAoUGl2b3RpbmcpDQoNCiMjIyBDaHV54buDbiBk4buvIGxp4buHdSBzYW5nIGThuqFuZyBkw6BpDQoNCkjDoG0gcGl2b3RfbG9uZ2VyIGjhu5cgdHLhu6MgY2jDum5nIHRhIGNodXnhu4NuIMSR4buVaSBk4buvIGxp4buHdSB04burIGThuqFuZyBy4buZbmcgKHdpZGUgZm9ybWF0KSBzYW5nIGThuqFuZyBkw6BpIChsb25nIGZvcm1hdCkuIFZp4buHYyBiaeG6v24gxJHhu5VpIGPhuqV1IHRyw7pjIGThu68gbGnhu4d1IGPDsyDDvSBuZ2jEqWEga2hpIG5nxrDhu51pIHBow6JuIHTDrWNoIG114buRbiB44butIGzDvSB0csOqbiBk4buvIGxp4buHdSBk4bqhbmcgZMOgaSDEkeG7gyBjw7MgdGjhu4MgdGhhbyB0w6FjIGThu4UgZMOgbmcgdsOgIMSR4bqhdCBuaGnhu4F1IGhp4buHdSBxdeG6oyBoxqFuIGThuqFuZyBy4buZbmcuDQoNCkNo4bupYyBuxINuZyBwaXZvdF9sb25nZXIoKSBjw7MgbeG7mXQgc+G7kSB0aGFtIHPhu5EgcXVhbiB0cuG7jW5nIG5oxrAgc2F1Og0KDQotICAgZGF0YTogVGhhbSBz4buRIG7DoHkgecOqdSBj4bqndSBk4buvIGxp4buHdSBtw6AgY2jDum5nIHRhIG114buRbiBjaHV54buDbiDEkeG7lWkgdOG7qyBk4bqhbmcgcuG7mW5nIHNhbmcgZOG6oW5nIGTDoGkuDQoNCi0gICBjb2xzOiB0aGFtIHPhu5EgbsOgeSBsw6AgZGFuaCBzw6FjaCBjw6FjIGPhu5l0IG3DoCB0YSBtdeG7kW4gY2h1eeG7g24gxJHhu5VpLiBUYSBjw7MgdGjhu4MgY2jhu4kgxJHhu4tuaCB0w6puIGPhu5l0IGPhu6UgdGjhu4MgdHJvbmcgZGF0YSBob+G6t2Mgc+G7rSBk4bulbmcgY8OhYyBow6BtIMSR4buDIGzhu7FhIGNo4buNbiBjw6FjIGPhu5l0IHRoZW8gbmjhu69uZyB0acOqdSBjaMOtIG3DoCBjaMO6bmcgdGEgbXXhu5FuDQoNCi0gICBuYW1lc190bzogVMOqbiBj4bunYSBj4buZdCBt4bubaSBz4bq9IGzGsHUgdHLhu68gY8OhYyB0w6puIGJp4bq/biBzYXUga2hpIGNodXnhu4NuIMSR4buVaSBzYW5nIGThuqFuZyBk4buvIGxp4buHdSBkw6BpLg0KDQotICAgdmFsdWVzX3RvOiBUw6puIGPhu6dhIGPhu5l0IG3hu5tpIG3DoCBz4bq9IGNo4bupYSBjw6FjIGdpw6EgdHLhu4sgYmnhur9uIHNhdSBraGkgY2h1eeG7g24gxJHhu5VpLg0KDQpUcsaw4bubYyBraGkgdGjhu7FjIGjDoG5oIGjDoG0gcGl2b3RfbG9uZ2VyIHTDtGkgc+G6vSBn4buNaSBt4buZdCBk4buvIGxp4buHdSBt4bqrdSB0cm9uZyBnw7NpIFRpZHlyIMSRw7MgY2jDrW5oIGzDoCB0YWJsZTRiLCBk4buvIGxp4buHdSBuw6B5IGfhu5NtIGTDom4gc+G7kSBj4bunYSAzIHF14buRYyBnaWEgQWZnaGFuaXN0YW4sIEJyYXppbCwgQ2hpbmEgdHJvbmcgaGFpIG7Eg20gMTk5OSwyMDAwLg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KdGFibGU0Yg0KDQpgYGANCg0KVOG7qyB0YWJsZTRiIHbhu5tpIG3hu6VjIMSRw61jaCBiaeG6v24gxJHhu5VpIGPDoWMgbsSDbSB24buBIGPDuW5nIG3hu5l0IGPhu5l0IHbDoCBnacOhIHRy4buLIHbhu4EgbeG7mXQgY+G7mXQgY2h1bmcgduG7m2kgbmhhdSwgdGEgY8OzIHRo4buDIHRo4buxYyBoaeG7h24gbOG7h25oIHBpdm90X2xvbmdlciB24bubaSBk4buvIGxp4buHdSBiYW4gxJHhuqd1IG114buRbiBjaHV54buDbiDEkeG7lWkgc2FuZyBk4bqhbmcgZMOgaSBsw6AgdGFibGU0YiwgdGhhbSBz4buRICdjb2xzJyBjaOG7iSDEkeG7i25oIGPDoWMgY+G7mXQgbXXhu5FuIGNodXnhu4NuIMSR4buVaSBsw6AgY+G7mXQgdOG7qyAiMTk5OSIgxJHhur9uICIyMDAwIiwgdGhhbSBz4buRIGBuYW1lc190b2AgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgxJHhurd0IHTDqm4gY+G7mXQgbeG7m2kgY2jhu6lhIGPDoWMgYmnhur9uIHbhu5tpIGzDoCAieWVhciIgdsOgIHRoYW0gc+G7kSBgdmFsdWVzX3RvYCDEkeG6t3QgdMOqbiBjaG8gY+G7mXQgY2jhu6lhIGPDoWMgZ2nDoSB0cuG7iyBiaeG6v24gdMawxqFuZyDhu6luZyBsw6AgdmFsdWVzLg0KDQpgYGB7cn0NCnBpdm90X2xvbmdlcih0YWJsZTRiLGNvbHM9ICcxOTk5JzonMjAwMCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAieWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlcyIpDQpgYGANCg0KTmjGsCBr4bq/dCBxdeG6oyBzYXUga2hpIGNodXnhu4NuIMSR4buVaSBiw6puIHRyw6puIHRhIHPhur0gY8OzIMSRxrDhu6NjIG3hu5l0IGThu68gbGnhu4d1IGThuqFuZyBkw6BpIHbhu5tpIG3hu5dpIGTDsm5nIGNobyBiaeG6v3QgduG7gSB0w6puIHF14buRYyBnaWEsIG7Eg20ga2jhuqNvIHPDoXQgdsOgIGTDom4gc+G7kSB0xrDGoW5nIOG7qW5nLg0KDQojIyMgQ2h1eeG7g24gZOG7ryBsaeG7h3Ugc2FuZyBk4bqhbmcgcuG7mW5nDQoNCkjDoG0gYHBpdm90X3dpZGVyYCBjw7MgY2jhu6ljIG7Eg25nIGJp4bq/biDEkeG7lWkgZOG6oW5nIGThu68gbGnhu4d1IGTDoGkgc2FuZyBk4buvIGxp4buHdSBy4buZbmcgc2FvIGNobyBwaMO5IGjhu6NwIHbhu5tpIG3hu6VjIHRpw6p1IGPhu6dhIG5nxrDhu51pIHPhu60gZOG7pW5nLiBIw6BtIG7DoHkgY8OzIHRoYW8gdMOhYyBraMOhIMSRxqFuIGdp4bqjbiB0dXkgbmhpw6puIG1hbmcgbOG6oWkgcuG6pXQgbmhp4buBdSBs4bujaSDDrWNoIHRyb25nIHF1w6EgdHLDrG5oIGzDoG0gdmnhu4djIGPhu6dhIG3hu41pIG5nxrDhu51pLiBQaXZvdF93aWRlciBjw7MgY8OhYyB0aGFtIHPhu5EgY2jDrW5oIG5oxrAgc2F1Og0KDQotICAgZGF0YTogROG7ryBsaeG7h3UgZMO5bmcgxJHhu4MgY2h1eeG7g24gc2FuZyBk4buvIGxp4buHdSBk4bqhbmcgcuG7mW5nDQoNCi0gICBuYW1lc19mcm9tOiBUw6puIGPhu5l0IGhv4bq3YyBiaeG6v24gbcOgIHRhIG114buRbiBiaeG6v24gxJHhu5VpIHRow6BuaCBjw6FjIGPhu5l0IG3hu5tpLg0KDQotICAgdmFsdWVzX2Zyb206IFTDqm4gY+G7mXQgaG/hurdjIGJp4bq/biBjaOG7qWEgY8OhYyBnacOhIHRy4buLIHTGsMahbmcg4bupbmcgduG7m2kgY8OhYyBj4buZdCBt4bubaS4NCg0KROG7ryBsaeG7h3UgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgdGjhu7FjIGhp4buHbiBow6BtIGBwaXZvdF93aWRlcmAgbMOgIHRhYmxlMiwgxJHDonkgbMOgIGThu68gbGnhu4d1IG3huqt1IHRyb25nIGfDs2kgVGlkeXIgY2jhu6lhIHRow7RuZyB0aW4gduG7gSBxdeG7kWMgZ2lhLCBuxINtLCBsb+G6oWkgc+G7kSBsaeG7h3UgduG7gSBkw6JuIHPhu5EsIHRyxrDhu51uZyBo4bujcCBt4bqvYyBi4buHbmggdsOgIHPhu5EgbmfGsOG7nWkgdMawxqFuZyDhu6luZy4NCg0KYGBge3J9DQp0YWJsZTINCmBgYA0KDQrEkOG6p3UgdGnDqm4sIHRhIGPhuqduIGtoYWkgYsOhbyBk4buvIGxp4buHdSBkw7luZyDEkeG7gyBjaHV54buDbiDEkeG7lWkgbMOgIHRhYmxlMiwgcGjDqXAgdG/DoW4gdOG7rSBnacO6cCB0cnV54buBbiBr4bq/dCBxdeG6oyBj4bunYSB0YWJsZTIgcGjDrWEgdHLGsOG7m2MgdGjDoG5oIMSR4buRaSB0xrDhu6NuZyDEkeG6p3UgdsOgbyBj4bunYSBow6BtIHBpdm90X3dpZGVyLiBUaGFtIHPhu5EgYG5hbWVzX2Zyb21gIHRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5IMSRxrDhu6NjIGtoYWkgYsOhbyBsw6AgdHlwZSDEkeG7gyBjaOG7iSByYSB0w6puIGPhu5l0IGTDuW5nIMSR4buDIGJp4bq/biDEkeG7lWkgdGjDoG5oIGPDoWMgY+G7mXQgbeG7m2kgdHJvbmcgZOG7ryBsaeG7h3UgcuG7mW5nLCBt4buXaSBnacOhIHRy4buLIHRyb25nIGJp4bq/biB0eXBlIHPhur0gbMOgIG3hu5l0IGPhu5l0IG3hu5tpLiBgdmFsdWVzX2Zyb21gIMSRxrDhu6NjIGNo4buJIMSR4buLbmggbMOgIGJp4bq/biBjb3VudCDEkeG7gyBjaOG7iSByYSBjw6FjIGdpw6EgdHLhu4sgdMawxqFuZyDhu6luZyB24bubaSBjw6FjIGPhu5l0IG3hu5tpDQoNCmBgYHtyfQ0KdGFibGUyICU+JSBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gdHlwZSwgdmFsdWVzX2Zyb20gPSBjb3VudCkNCmBgYA0KDQpDaHV54buDbiDEkeG7lWkgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3UgdGFibGUyIHNhbmcgZOG6oW5nIGThu68gbGnhu4d1IHLhu5luZyBnacO6cCB0YSBk4buFIGTDoG5nIMSRw6FuaCBnacOhIGPDoWMgdHLGsOG7nW5nIGjhu6NwIG3huq9jIGLhu4duaCB2w6AgZMOibiBz4buRIGPhu6dhIGPDoWMgcXXhu5FjIGdpYSBxdWEgdOG7q25nIG7Eg20uIE5nb8OgaSByYSwgdmnhu4djIGNodXnhu4NuIMSR4buVaSBj4bqldSB0csO6YyBjxaluZyBnacO6cCB0aOG7sWMgaGnhu4duIHBow6JuIHTDrWNoIHRoZW8gdOG7q25nIGJp4bq/biB2w6AgdHLhu7FjIHF1YW4gaMOzYSBk4buvIGxp4buHdSB04buRdCBoxqFuLg0KDQojIyBUw6FjaCBj4buZdA0KDQpDaOG7qWMgbsSDbmcgdMOhY2ggbeG7mXQgY+G7mXQgdGjDoG5oIG5oaeG7gXUgY+G7mXQgZOG7sWEgdHLDqm4gbmjhu69uZyBrw70gdOG7sSBwaMOibiB0w6FjaCBz4bq9IGzDoCBt4buZdCBjw7RuZyBj4bulIHThu5F0IMSR4buDIGNow7puZyB0YSBjw7MgdGjhu4MgeOG7rSBsw70gZOG7ryBsaeG7h3UgY+G7p2EgbcOsbmgga2hpIG3DoCBt4buZdCBj4buZdCBjaOG7qWEgbmhp4buBdSBnacOhIHRy4buLIGvhur90IGjhu6NwIHbhu5tpIG5oYXUuIFZp4buHYyBwaMOibiB0w6FjaCBj4buZdCBraMO0bmcgecOqdSBj4bqndSBuaGnhu4F1IHRoYW8gdMOhYyBuaMawbmcgduG6q24gxJHhuqNtIGLhuqNvIMSRxrDhu6NjIMSR4buZIGNow61uaCB4w6FjIHNvIHbhu5tpIGThu68gbGnhu4d1IGJhbiDEkeG6p3UsIHRoYW8gdMOhYyBuw6B5IGPDsyB0aOG7gyDEkcaw4bujYyBjb2kgbMOgIG3hu5l0IHRyb25nIG5o4buvbmcgYsaw4bubYyB44butIGzDvSBjaHXhu5dpIHBo4bupYyB04bqhcC4gROG7ryBsaeG7h3Ugc2F1IGtoaSDEkcaw4bujYyB0w6FjaCBj4buZdCBz4bq9IMSRZW0gbOG6oWkgdGjDtG5nIHRpbiBjaGkgdGnhur90IGjGoW4gxJHhu4MgY8OzIHRo4buDIHBow6JuIHTDrWNoLCBzbyBzw6FuaCwgdHLhu7FjIHF1YW4gaMOzYSBk4buvIGxp4buHdS4gVHJvbmcgVGlkeXIgxJHhu4MgdMOhY2ggY+G7mXQgdGjDrCB0YSBkw7luZyBow6BtIGBzZXBhcmF0ZSgpYCB24bubaSBuaOG7r25nIHRoYW0gc+G7kSBjaMOtbmggY+G6p24gcGjhuqNpIGzGsHUgw70gbmjGsA0KDQotICAgZGF0YTogROG7ryBsaeG7h3UgYmFuIMSR4bqndS4NCg0KLSAgIGNvbDogVMOqbiBj4buZdCBj4bqnbiB0w6FjaC4NCg0KLSAgIGludG86IFTDqm4gY8OhYyBj4buZdCBt4bubaSDEkcaw4bujYyB04bqhbyByYSBzYXUga2hpIHTDoWNoLg0KDQotICAgc2VwOiBLw70gdOG7sSBwaMOibiB0w6FjaCBob+G6t2MgbeG6q3UgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgdMOhY2ggY+G7mXQuDQoNCi0gICByZW1vdmU6IFjDoWMgxJHhu4tuaCB4ZW0gY+G7mXQgYmFuIMSR4bqndSBj4bqnbiDEkcaw4bujYyBsb+G6oWkgYuG7jyBzYXUga2hpIHTDoWNoIGhheSBraMO0bmcsIG3hurdjIMSR4buLbmggbMOgIFRSVUUuDQoNCi0gICBjb252ZXJ0OiBYw6FjIMSR4buLbmggeGVtIGPDoWMgY+G7mXQgbeG7m2kgY+G6p24gxJHGsOG7o2MgY2h1eeG7g24gxJHhu5VpIHRow6BuaCBraeG7g3UgZOG7ryBsaeG7h3UgcGjDuSBo4bujcCBoYXkga2jDtG5nLCBt4bq3YyDEkeG7i25oIGzDoCBGQUxTRS4NCg0KROG7ryBsaeG7h3UgxJHhuqd1IHbDoG8gZMO5bmcgxJHhu4MgdMOhY2ggY+G7mXQgbMOgIHRhYmxlMywgZOG7ryBsaeG7h3UgbsOgeSBjw7MgY+G7mXQgcmF0ZSBkw7luZyBrw70gdOG7sSAvIMSR4buDIHTDrW5oIHThu7cgbOG7hyBuZ8aw4budaSBt4bqvYyBi4buHbmggdHLDqm4gZMOibiBz4buRIGPhu6dhIG3hu5l0IHF14buRYyBnaWEuIFRhIGPDsyB0aOG7gyBkw7luZyBow6BtIGBzZXBhcmF0ZSgpYCDEkeG7gyB0w6FjaCBj4buZdCByYXRlIHRow6BuaCBt4buZdCBj4buZdCBjaOG7qWEgc+G7kSBsaeG7h3UgduG7gSBz4buRIG5nxrDhu51pIG3huq9jIGLhu4duaCB2w6AgbeG7mXQgY+G7mXQgY2jhu6lhIHPhu5EgbGnhu4d1IHbhu4EgZMOibiBz4buRLg0KDQpgYGB7cn0NCnRhYmxlMw0KYGBgDQoNCsSQ4buDIHRo4buxYyBoaeG7h24gdmnhu4djIHTDoWNoIGPhu5l0IHRyxrDhu5tjIHRpw6puIGNow7puZyB0YSBj4bqnbiBraGFpIGLDoW8gZOG7ryBsaeG7h3UgxJHhuqd1IHbDoG8gbMOgIHRhYmxlMywgY2jhu41uIGPhu5l0IGPhuqduIHTDoWNoIHRyb25nIHRoYW0gc+G7kSBgY29sYCBsw6AgY+G7mXQgcmF0ZSwg4bufIHRoYW0gc+G7kSBgaW50b2AgdGEgY8OzIHRo4buDIMSR4bq3dCB0w6puIGNobyBjw6FjIGPhu5l0IG3hu5tpIGzDoCAiY2FzZSIgdsOgICJwb3B1bGF0aW9uIiwgdGnhur9wIHRoZW8gYHNlcGAgY2jhu4kgcmEga8O9IHThu7EgZMO5bmcgxJHhu4MgcGjDom4gdMOhY2ggdHJvbmcgZOG7ryBsaeG7h3UgY+G7p2EgY2jDum5nIHRhIMSRw7MgbMOgICIvIi4NCg0KYGBge3J9DQpzZXBhcmF0ZShkYXRhID0gdGFibGUzLCBjb2w9IHJhdGUsIGludG89IGMoImNhc2UiLCJwb3B1bGF0aW9uIiksc2VwID0gIi8iKQ0KYGBgDQoNCkvhur90IHF14bqjIHThu6sgY8OidSBs4buHbmggdHLDqm4gc+G6vSB04bqhbyByYSBoYWkgY+G7mXQgbeG7m2kgbMOgIGNhc2UgdsOgIHBvcHVsYXRpb24gZOG7sWEgdsOgbyBj4buZdCByYXRlIGJhbiDEkeG6p3UuIMSQaeG7gXUgbsOgeSBz4bq9IGdpw7pwIHRhIHF1YW4gc8OhdCDEkcaw4bujYyBz4buRIHRyxrDhu51uZyBo4bujcCBt4bqvYyBi4buHbmggdsOgIGTDom4gc+G7kSBj4bunYSBt4buZdCBxdeG7kWMgZ2lhIG3hu5l0IGPDoWNoIGNoaSB0aeG6v3QgaMahbiB2w6Agc2F1IMSRw7MgY8OzIHRo4buDIGThu4UgZMOgbmcgZMO5bmcgbsOzIHRyb25nIGPDoWMgY8O0bmcgdmnhu4djIGtow6FjLg0KDQpgYGB7cn0NCnNlcGFyYXRlKGRhdGEgPSB0YWJsZTMgLCBjb2wgPSByYXRlLCBpbnRvID0gYygiY2FzZSIsICJwb3B1bGF0aW9uIiksIHJlbW92ZSA9IEZBTFNFLCBjb252ZXJ0ID0gVFJVRSApDQoNCmBgYA0KDQpOZ2/DoGkgcmEsIHRhIGPDsyB0aOG7gyB0aMOqbSB2w6BvIHRoYW0gc+G7kSBgcmVtb3ZlYCBsw6AgRkFMU0UgxJHhu4MgZ2nhu68gbmd1ecOqbiBj4buZdCByYXRlIGJhbiDEkeG6p3UgdsOgIHRoYW0gc+G7kSBgY29udmVydGAgYuG6sW5nIFRSVUUgxJHhu4MgeMOhYyDEkeG7i25oIGNodXnhu4NuIMSR4buVaSB0aMOgbmgga2nhu4N1IGThu68gbGnhu4d1IHBow7kgaOG7o3ANCg0KIyMgS+G6v3QgaOG7o3AgY+G7mXQNCg0K4bueIGLGsOG7m2MgbMOgbSBz4bqhY2ggZOG7ryBsaeG7h3UsIGNow7puZyB0YSB0aMaw4budbmcgeHV5w6puIGfhurdwIHBo4bqjaSBjw6FjIGPhu5l0IGThu68gbGnhu4d1IMSRxrDhu6NjIHTDoWNoIHJhIHJpw6puZyBiaeG7h3QgdsOgIGtoaSBr4bq/dCBo4bujcCBjaMO6bmcgbOG6oWkgduG7m2kgbmhhdSB0aMOsIGPDsyB0aOG7gyDEkcaw4bujYyBt4buZdCBj4buZdCBk4buvIGxp4buHdSBob8OgbiBjaOG7iW5oIHbDoCBn4buNbiBnw6BuZyBoxqFuIHRyxrDhu5tjIHLhuqV0IG5oaeG7gXUuIEfDs2kgVGlkeXIgYmFvIGfhu5NtIGjDoG0gYHVuaXRlKClgIGPDsyB0aOG7gyBkw7luZyDEkeG7gyBr4bq/dCBo4bujcCBuaGnhu4F1IGPhu5l0IHRow6BuaCBt4buZdCBj4buZdCBi4bqxbmcgY8OhY2ggZ2jDqXAgY8OhYyBnacOhIHRy4buLIGPhu6dhIGNow7puZyBs4bqhaSB24bubaSBuaGF1LiBD4bqldSB0csO6YyBj4bunYSBk4buvIGxp4buHdSBzYXUga2hpIGJp4bq/biDEkeG7lWkgc+G6vSB0cuG7nyBuw6puIMSRxqFuIGdp4bqjbiwgw610IGPhu5l0IHbDoCBtYW5nIMO9IG5naMSpYSB04buVbmcgcXVhbiBoxqFuIHNvIHbhu5tpIGThu68gbGnhu4d1IGJhbiDEkeG6p3UuIE5o4buvbmcgdGhhbSBz4buRIGNow61uaCB0cm9uZyBow6BtIGB1bml0ZSgpYCDEkcaw4bujYyBnaeG6o2kgdGjDrWNoIGTGsOG7m2kgxJHDonk6DQoNCi0gICBkYXRhOiBLaHVuZyBk4buvIGxp4buHdQ0KDQotICAgY29sIDogVMOqbiBj4bunYSBj4buZdCBt4bubaSDEkcaw4bujYyB04bqhbywgdMOqbiBj4bunYSBjw6FjIGPhu5l0IMSRxrDhu6NjIGjhu6NwIG5o4bqldCBz4bqvcCB44bq/cCB0aGVvIHRy4bqtdCB04buxDQoNCi0gICBzZXA6IEThuqV1IHBow6JuIGPDoWNoIGdp4buvYSBoYWkgZ2nDoSB0cuG7iw0KDQotICAgcmVtb3ZlOiBO4bq/dSBsw6AgVFJVRSBz4bq9IHjDs2EgYuG7jyBjw6FjIGPhu5l0IGThu68gbGnhu4d1IGJhbiDEkeG6p3Ugc2F1IGtoaSBn4buZcCBs4bqhaSB0aMOgbmggY+G7mXQgbeG7m2kNCg0KLSAgIG5hLnJtOiBO4bq/dSBsw6AgVFJVRSB0aMOsIHPhur0gbG/huqFpIGLhu48gY8OhYyBnacOhIHRy4buLIGLhu4sgdGhp4bq/dSB0csaw4bubYyBraGkga+G6v3QgaOG7o3ANCg0KQuG6o25nIGThu68gbGnhu4d1IHRhYmxlNSBiw6puIGTGsOG7m2kgY8OzIGhhaSBj4buZdCByacOqbmcgYmnhu4d0IGNo4bupYSBnacOhIHRy4buLIHbhu4EgdGjhur8ga+G7iSB2w6AgbsSDbSwgY2jDum5nIHRhIGvhur90IGjhu6NwIGhhaSBj4buZdCBuw6B5IHRow6BuaCBt4buZdCDEkeG7gyBjw7MgxJHGsOG7o2Mgc+G7kSBsaeG7h3UgbsSDbSBob8OgbiBjaOG7iW5oLg0KDQpgYGB7cn0NCnRhYmxlNQ0KYGBgDQoNClRyb25nIGjDoG0gYHVuaXRlKClgIGtodW5nIGThu68gbGnhu4d1IMSRxrDhu6NjIGtoYWkgYsOhbyBsw6AgdGFibGU1LCB0w6puIGPhu6dhIGPhu5l0IG3hu5tpIHNhdSBraGkga+G6v3QgaOG7o3AgbOG6oWkgxJHGsOG7o2MgxJHhurd0IGzDoCAibmV3eWVhciIgdsOgIGPDoWMgY+G7mXQgZMO5bmcgxJHhu4MgZ2jDqXAgbOG6oWkgxJHGsOG7o2MgY2jhu4kgxJHhu4tuaCBs4bqnbiBsxrDhu6N0IGzDoCBj4buZdCBjZW50dXJ5LCB5ZWFyLiDEkOG7kWkgc+G7kSBgc2VwYCB5w6p1IGPhuqd1IGThuqV1IHBow6JuIGPDoWNoIHNhdSBraGkgZ2jDqXAgY8OhYyBnacOhIHRy4buLIGzhuqFpLCB0cm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSB0w7RpIHPhu60gZOG7pW5nICIiIGzDoCBraMO0bmcgY8OzIGtob+G6o25nIGPDoWNoIHNhdSBraGkga+G6v3QgaOG7o3AgaGFpIGThu68gbGnhu4d1LiBgcmVtb3ZlYCBjaG8gYuG6sW5nIEZBTFNFIGzDoCBz4bq9IGtow7RuZyBsb+G6oWkgYuG7jyBjw6FjIGPhu5l0IGJhbiDEkeG6p3Ugc2F1IGtoaSBr4bq/dCBo4bujcCBj4buZdC4NCg0KYGBge3J9DQp1bml0ZShkYXRhID0gdGFibGU1LCBjb2w9IG5ld3llYXIgLCBjZW50dXJ5ICwgeWVhciwgc2VwPSIiLHJlbW92ZSA9IEZBTFNFKQ0KYGBgDQoNClNhdSBraGkga+G6v3QgaOG7o3AgY2VudHVyeSB2w6AgeWVhciB0YSDEkcaw4bujYyBj4buZdCBt4bubaSB0w6puIGzDoCBuZXd5ZWFyIGNo4bupYSBjw6FjIGdpw6EgdHLhu4sgbsSDbSDEkcaw4bujYyBnaMOpcCB04burIGPDoWMgZ2nDoSB0cuG7iyB0cm9uZyBoYWkgY+G7mXQgdHLGsOG7m2MgxJHDsy4gVOG7qyDEkcOzLCB0YSBjw7MgdGjhu4Mgc+G7rSBk4bulbmcgY+G7mXQgbeG7m2kgxJHGsOG7o2MgdOG6oW8gcmEgxJHhu4MgbMOgbSBjw6FjIHRoYW8gdMOhYyBraMOhYywgY2jhurNuZyBo4bqhbiBuaMawIHbhur0gxJHhu5MgdGjhu4sgaGF5IGTDuW5nIMSR4buDIHTDrW5oIHRvw6FuIGThu7FhIHbDoG8gdOG7q25nIG7Eg20uDQoNCiMjIE5lc3QNCg0KTOG7h25oIG5lc3QoKSBraMO0bmcgcGjhuqNpIGzDoCBt4buZdCBs4buHbmggdMOtY2ggaOG7o3AgdHJvbmcgUi4gVHV5IG5oacOqbiwgdHJvbmcgZ8OzaSB0aWR5ciwgY8OzIGjDoG0gbmVzdCgpIGNobyBwaMOpcCBjaMO6bmcgdGEgdOG6oW8gbeG7mXQgY+G7mXQgbeG7m2kgdHJvbmcgbeG7mXQgZGF0YWZyYW1lIHbDoCBs4buTbmcgZOG7ryBsaeG7h3UgdGjDoG5oIGPDoWMgZGFuaCBzw6FjaCBk4buxYSB0csOqbiBt4buZdCBob+G6t2Mgbmhp4buBdSBiaeG6v24uIEPDoWMgdGhhbSBz4buRIGNow61uaCB0cm9uZyBow6BtIGBuZXN0KClgIMSRxrDhu6NjIHRyw6xuaCBiw6B5IGTGsOG7m2kgxJHDonkNCg0KLSAgIC5kYXRhOiDEkOG7kWkgc+G7kSBuw6B5IGzDoCBk4buvIGxp4buHdSBn4buRYyBtw6AgYuG6oW4gbXXhu5FuIHThuqFvIGtodW5nIGThu68gbGnhu4d1IGzhu5NuZyBuaGF1IHThu6sgxJHDsw0KDQotICAgLi4uOiDEkMOieSBsw6AgbeG7mXQgxJHhu5FpIHPhu5Ega2nhu4N1IHRpZHktc2VsZWN0LCBjaG8gcGjDqXAgY2jhu41uIGPDoWMgY+G7mXQgbcOgIHRhIG114buRbiBs4buTbmcgdsOgbyBjw6FjIGtodW5nIGThu68gbGnhu4d1IGNvbg0KDQotICAgLmJ5OiDEkOG7kWkgc+G7kSBuw6B5IGNobyBwaMOpcCBjaOG7jW4gY8OhYyBj4buZdCBkw7luZyDEkeG7gyBuaMOzbSBk4buvIGxp4buHdQ0KDQotICAgLmtleTogbMOgIG3hu5l0IMSR4buRaSBz4buRIGNobyBwaMOpcCBi4bqhbiBjaOG7iSDEkeG7i25oIHTDqm4gY2hvIGPhu5l0IGRhbmggc8OhY2ggxJHGsOG7o2MgdOG6oW8gcmEgc2F1IGtoaSBs4buTbmcgZOG7ryBsaeG7h3UuIE7hur91IGtow7RuZyBjaOG7iSDEkeG7i25oIHTDqm4gY2hvIHRoYW0gc+G7kSBuw6B5IHRow6wgdMOqbiBt4bq3YyDEkeG7i25oIHPhur0gbMOgICJkYXRhIg0KDQpExrDhu5tpIMSRw6J5IGzDoCBt4buZdCB2w60gZOG7pSB24buBIGThu68gbGnhu4d1IGPhu6dhIG3hu5l0IGLhu5kgcGjhuq1uIMSRYW5nIG5naGnDqm4gY+G7qXUgduG7gSB0w6xuaCBow6xuaCB0aOG7nWkgdGnhur90IHRyb25nIGPDoWMgdGjDoG5oIHBo4buRIGtow6FjIG5oYXUuIENow7puZyB0YSBjw7MgbeG7mXQgZGF0YWZyYW1lIGNo4bupYSB0aMO0bmcgdGluIHbhu4EgdMOqbiB0aMOgbmggcGjhu5EsIG5nw6B5IHbDoCBnaeG7nSwgbmhp4buHdCDEkeG7mSB2w6AgxJHhu5kg4bqpbS4NCg0KYGBge3J9DQojIFThuqFvIGRhdGFmcmFtZSBjaOG7qWEgZOG7ryBsaeG7h3UgduG7gSB0aOG7nWkgdGnhur90DQpkYXRhIDwtIGRhdGEuZnJhbWUoDQogIFRoYW5oUGhvID0gYygiSGFub2kiLCAiSGFub2kiLCAiSGFub2kiLCAiSG9DaGlNaW5oIiwgIkhvQ2hpTWluaCIsICJIb0NoaU1pbmgiKSwNCiAgTmdheSA9IGMoIjIwMjMtMDEtMDEiLCAiMjAyMy0wMS0wMiIsICIyMDIzLTAxLTAzIiwgIjIwMjMtMDEtMDEiLCAiMjAyMy0wMS0wMiIsICIyMDIzLTAxLTAzIiksDQogIEdpbyA9IGMoIjEyOjAwIiwgIjEyOjAwIiwgIjEyOjAwIiwgIjEyOjAwIiwgIjEyOjAwIiwgIjEyOjAwIiksDQogIE5oaWV0RG8gPSBjKDIwLjUsIDIyLjMsIDIxLjgsIDMwLjIsIDMxLjUsIDMwLjkpLA0KICBEb0FtID0gYyg2MCwgNjUsIDYyLCA3MCwgNjgsIDcyKQ0KKQ0KcHJpbnQoZGF0YSkNCmBgYA0KDQpgYGB7cn0NCiMgTOG7k25nIGThu68gbGnhu4d1IHRow6BuaCBkYW5oIHPDoWNoIHRoZW8gdMOqbiB0aMOgbmggcGjhu5EgDQpuZXN0ZWRfZGF0YSA8LSBkYXRhICU+JWdyb3VwX2J5KFRoYW5oUGhvKSAlPiUgbmVzdCgpDQoNCiMgTOG7k25nIGThu68gbGnhu4d1IGLhurFuZyAuYnkgDQpuZXN0ZWRfZGF0YSA8LSBuZXN0KGRhdGEsIC5ieSA9IFRoYW5oUGhvLCAua2V5ID0gIkR1TGlldSIpDQoNCiMgSW4gZOG7ryBsaeG7h3UgbOG7k25nDQpwcmludChuZXN0ZWRfZGF0YSkNCg0KbmVzdGVkX2RhdGEkRHVMaWV1IDwtIGxhcHBseShuZXN0ZWRfZGF0YSREdUxpZXUsIGFzLmRhdGEuZnJhbWUpDQpsYXBwbHkobmVzdGVkX2RhdGEkRHVMaWV1LCBwcmludCkNCg0KYGBgDQoNClRyb25nIHbDrSBk4bulIG7DoHksIGNow7puZyB0YSBz4butIGThu6VuZyBow6BtIG5lc3QoKSB0cm9uZyBnw7NpIHRpZHlyIHbDoCBow6BtIGdyb3VwX2J5IHRyb25nIHBhY2thZ2UgZHBseXIgxJHhu4MgbOG7k25nIGThu68gbGnhu4d1IHRoZW8gdMOqbiB0aMOgbmggcGjhu5EuIELhurFuZyBjw6FjaCBz4butIGThu6VuZyBjaHXhu5dpIGTDsm5nIGzhu4duaCB0cm9uZyBnw7NpIHRpZHlyIHbDoCBkcGx5ciwgY2jDum5nIHRhIG5ow7NtIGThu68gbGnhu4d1IHRoZW8gY+G7mXQgVGhhbmhQaG8gYuG6sW5nIGjDoG0gZ3JvdXBfYnkoKSB2w6Agc2F1IMSRw7Mgc+G7rSBk4bulbmcgaMOgbSBuZXN0KCkgxJHhu4MgdOG6oW8gbeG7mXQgY+G7mXQgbeG7m2kgY2jhu6lhIGThu68gbGnhu4d1IMSRxrDhu6NjIGzhu5NuZyB0aMOgbmggZGFuaCBzw6FjaC4gSG/hurdjIHPhu60gZOG7pW5nIHRoYW0gc+G7kSBgLmJ5YCBjaOG7jW4gY+G7mXQgVGhhbmhQaG8gxJHhu4MgbmjDs20gZOG7ryBsaeG7h3UgdsOgIHNhdSDEkcOzIGTDuW5nIHRoYW0gc+G7kSBgLmtleWAgxJHhu4MgxJHhurd0IHTDqm4gY+G7mXQgZGFuaCBzw6FjaCB04bqhbyByYSBzYXUga2hpIGzhu5NuZyBk4buvIGxp4buHdS4NCg0KS+G6v3QgcXXhuqMgbMOgIG3hu5l0IGRhdGFmcmFtZSBt4bubaSBuZXN0ZWRfZGF0YSBjaOG7qWEgaGFpIGPhu5l0OiBUaGFuaFBobyB2w6AgRHVMaWV1LCB0cm9uZyDEkcOzIGPhu5l0IGhhaSBjaOG7qWEgZOG7ryBsaeG7h3UgxJHGsOG7o2MgbOG7k25nIHRow6BuaCBkYW5oIHPDoWNoIGThu7FhIHRyw6puIHTDqm4gdGjDoG5oIHBo4buRLiBDw6FjIHBo4bqnbiB04butIHRyb25nIGPhu5l0ICJEdUxpZXUiIGzDoCBjw6FjIGRhbmggc8OhY2ggZOG7ryBsaeG7h3UgY29uLCBt4buXaSBkYW5oIHPDoWNoIGNo4bupYSB0aMO0bmcgdGluIHbhu4EgbmfDoHksIGdp4budLCBuaGnhu4d0IMSR4buZIHbDoCDEkeG7mSDhuqltIHTGsMahbmcg4bupbmcgY2hvIHThu6tuZyB0aMOgbmggcGjhu5EuDQoNCkzhu4duaCBuZXN0KCkgdHJvbmcgdsOtIGThu6UgbsOgeSBnacO6cCBjaMO6bmcgdGEgbOG7k25nIGThu68gbGnhu4d1IHRoZW8gdMOqbiB0aMOgbmggcGjhu5EsIGdpw7pwIHThu5UgY2jhu6ljIHbDoCB44butIGzDvSBk4buvIGxp4buHdSB0aOG7nWkgdGnhur90IG3hu5l0IGPDoWNoIHRy4buxYyBxdWFuIHbDoCB0aHXhuq1uIHRp4buHbiBoxqFuDQoNClNhdSDEkcOzLCBjaMO6bmcgdGEgdGnhur9wIHThu6VjIHPhu60gZOG7pW5nIGjDoG0gbGFwcGx5KCkgxJHhu4Mgw6FwIGThu6VuZyBow6BtIHByaW50KCkgY2hvIG3hu5dpIHRpYmJsZSB0cm9uZyBkYW5oIHPDoWNoIG5lc3RlZF9kYXRhXCREdUxpZXUuIEvhur90IHF14bqjIGzDoCBj4bqjIGhhaSBk4buvIGxp4buHdSBi4bqjbmcgdOG7qyBjw6FjIHRpYmJsZSBz4bq9IMSRxrDhu6NjIGhp4buDbiB0aOG7iyB0csOqbiBtw6BuIGjDrG5oLCBt4buXaSB0aWJibGUgxJFpIGvDqG0gduG7m2kgdMOqbiBj4buZdCB2w6AgY8OhYyBnacOhIHRy4buLIHTGsMahbmcg4bupbmcuDQoNCkvhur90IHF14bqjIGhp4buHbiB0aOG7iyBs4bqnbiBsxrDhu6N0IGzDoCBi4bqjbmcgduG7gSB0aOG7m2kgdGnhur90IOG7nyBIw6AgTuG7mWkgdsOgIGLhuqNuZyBzYXUgxJHDsyBsw6AgYuG6o25nIHRo4budaSB0aeG6v3Qg4bufIEjhu5MgY2jDrSBNaW5oLiDEkMOzIGzDoCB2w60gZOG7pSB24buBIGjDoG0gbmVzdCgpIMSRxrDhu6NjIHPhu60gZOG7pW5nIGvhur90IGjhu6NwIHbhu5tpIGjDoG0gZ3JvdXBfYnkoKSB2w6AgaMOgbSBsYXBwbHkgxJHhu4MgY2hvIHJhIMSRxrDhu6NjIGvhur90IHF14bqjIGzDoCBjw6FjIGThu68gbGnhu4d1IGLhuqNuZyDEkcaw4bujYyBs4buTbmcgdsOgbyBuaGF1IHRoZW8gY8OhYyBiaeG6v24gY2jDum5nIHRhIGPhuqduIHRo4buRbmcga8OqDQoNCiMjIFVubmVzdA0KDQpUcm9uZyBuZ8O0biBuZ+G7ryBs4bqtcCB0csOsbmggUiwgbOG7h25oIGB1bm5lc3QoKWAgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgdMOhY2ggZOG7ryBsaeG7h3UgdHJvbmcgbeG7mXQgY+G7mXQgY2jhu6lhIGPDoWMgxJHhu5FpIHTGsOG7o25nIGzhu5NuZyBuaGF1IHRow6BuaCBjw6FjIGPhu5l0IHJpw6puZyBiaeG7h3QuIMSQaeG7gXUgbsOgeSBnacO6cCBjaMO6bmcgdGEgcGjDom4gdMOhY2ggdsOgIHRydXkgY+G6rXAgZOG7hSBkw6BuZyB2w6BvIGPDoWMgdGjDoG5oIHBo4bqnbiBj4bunYSBjw6FjIMSR4buRaSB0xrDhu6NuZyDEkcaw4bujYyBs4buTbmcgbmhhdS4gQ8OhYyB0aGFtIHPhu5EgY2jDrW5oIHRyb25nIGjDoG0gYHVubmVzdCgpYCBn4buTbSBjw7M6DQoNCi0gICBkYXRhOiDEkOG7kWkgc+G7kSBuw6B5IGzDoCBk4buvIGxp4buHdSBn4buRYyBjaOG7qWEgY+G7mXQgZGFuaCBzw6FjaCBtw6AgY2jDum5nIHRhIG114buRbiBnaeG6o2kgbsOpbi4gxJDDonkgbMOgIG3hu5l0IMSR4buRaSBz4buRIGLhuq90IGJ14buZYyB2w6AgcGjhuqNpIGzDoCBt4buZdCBraHVuZyBk4buvIGxp4buHdSAoZGF0YSBmcmFtZSkuDQoNCi0gICBjb2w6IMSQw6J5IGzDoCDEkeG7kWkgc+G7kSBkw7luZyDEkeG7gyB4w6FjIMSR4buLbmggdMOqbiBj4bunYSBj4buZdCBkYW5oIHPDoWNoIGPhuqduIGdp4bqjaSBuw6luLiBOw7MgY8WpbmcgbMOgIG3hu5l0IMSR4buRaSBz4buRIGLhuq90IGJ14buZYyB2w6AgcGjhuqNpIGzDoCBt4buZdCBjaHXhu5dpIGvDvSB04buxLg0KDQotICAgLmRyb3A6IE3hu5l0IGdpw6EgdHLhu4sgbG9naWNhbCAoVFJVRSBob+G6t2MgRkFMU0UpIHjDoWMgxJHhu4tuaCB4ZW0gbGnhu4d1IGPDsyBuw6puIGxv4bqhaSBi4buPIGPhu5l0IGRhbmggc8OhY2ggc2F1IGtoaSBnaeG6o2kgbsOpbiBoYXkga2jDtG5nLiBHacOhIHRy4buLIG3hurdjIMSR4buLbmggbMOgIFRSVUUsIG5naMSpYSBsw6AgY+G7mXQgZGFuaCBzw6FjaCBz4bq9IGLhu4sgbG/huqFpIGLhu48uDQoNCkTGsOG7m2kgxJHDonkgbMOgIHbDrSBk4bulIHbhu4EgbOG7h25oIHVubmVzdCgpLCDEkeG6p3UgdGnDqm4gY2jDum5nIHTDtGkgc+G6vSB04bqhbyBkYXRhZnJhbWUgY2jhu6lhIGThu68gbGnhu4d1IHbhu4Egc+G6o24gcGjhuqltIHbDoCDEkeG6t2MgxJFp4buDbQ0KDQpgYGB7cn0NCmRhdGExIDwtIGRhdGEuZnJhbWUoDQogIFNhblBoYW0gPSBjKCJTUDEiLCAiU1AyIiwgIlNQMyIpLA0KICBNYXVTYWMgPSBJKGxpc3QoDQogICAgcmVwKGMoIsSQ4buPIiwgIlhhbmgiLCAiVsOgbmciKSwgZWFjaCA9IDMpLA0KICAgIHJlcChjKCJUcuG6r25nIiwgIsSQZW4iKSwgZWFjaCA9IDIpLA0KICAgIHJlcCgiQ2FtIiwgMykNCiAgKSksDQogIEtpY2hUaHVvYyA9IEkobGlzdCgNCiAgICByZXAoYygiUyIsICJNIiwgIkwiKSwgZWFjaCA9IDMpLA0KICAgIHJlcChjKCJNIiwgIkwiKSwgZWFjaCA9IDIpLA0KICAgIHJlcCgiUyIsIDMpDQogICkpLA0KICBHaWEgPSBjKDEwMCwgMjAwLCAxNTApDQopDQpwcmludChkYXRhMSkgIA0KYGBgDQoNCmBgYHtyfQ0KIyBUw6FjaCBkYW5oIHPDoWNoIMSR4bq3YyDEkWnhu4NtIHRow6BuaCBjw6FjIGPhu5l0IHJpw6puZyBiaeG7h3QNCmRhdGFfc3BsaXQgPC0gdW5uZXN0KGRhdGEgPSBkYXRhMSwgY29scyA9IGMoTWF1U2FjLEtpY2hUaHVvYykpDQoNCg0KIyBJbiBr4bq/dCBxdeG6oyBzYXUga2hpIHTDoWNoDQpkYXRhdGFibGUoZGF0YV9zcGxpdCkNCmBgYA0KDQpUcm9uZyB2w60gZOG7pSBuw6B5LCBjaMO6bmcgdGEgY8OzIG3hu5l0IGRhdGFmcmFtZSBkYXRhIGNo4bupYSB0aMO0bmcgdGluIHbhu4Egc+G6o24gcGjhuqltIHbDoCDEkeG6t2MgxJFp4buDbSBj4bunYSBjaMO6bmcuIEPhu5l0IE1hdVNhYyB2w6AgS2ljaFRodW9jIGzDoCBjw6FjIGPhu5l0IGNo4bupYSBkYW5oIHPDoWNoIGPDoWMgxJHhurdjIMSRaeG7g20gdMawxqFuZyDhu6luZyB24bubaSBt4buXaSBz4bqjbiBwaOG6qW0uDQoNClPhu60gZOG7pW5nIGzhu4duaCB1bm5lc3QoKSB0cm9uZyBnw7NpIHRpZHlyLCBjaMO6bmcgdGEgdMOhY2ggZGFuaCBzw6FjaCDEkeG6t2MgxJFp4buDbSAoTWF1U2FjIHbDoCBLaWNoVGh1b2MpIHRow6BuaCBjw6FjIGPhu5l0IHJpw6puZyBiaeG7h3QuIEvhur90IHF14bqjIGzDoCBt4buZdCBkYXRhZnJhbWUgbeG7m2kgZGF0YV9zcGxpdCB24bubaSBjw6FjIGPhu5l0IFNhblBoYW0sIE1hdVNhYywgS2ljaFRodW9jIHbDoCBHaWEsIHRyb25nIMSRw7MgY8OhYyBj4buZdCBNYXVTYWMgdsOgIEtpY2hUaHVvYyDEkcOjIMSRxrDhu6NjIHTDoWNoIHRow6BuaCBjw6FjIGPhu5l0IHJpw6puZyBiaeG7h3QuDQoNCiMjIGNvbXBsZXRlKCkNCg0KSMOgbSBjb21wbGV0ZSgpIHRyb25nIFIgbMOgbSBt4buZdCBjw7RuZyBj4bulIG3huqFuaCBt4bq9IMSR4buDIMSRaeG7gW4gY8OhYyBnacOhIHRy4buLIHRoaeG6v3UgdsOgIHThuqFvIHJhIGPDoWMgaMOgbmcgaG/DoG4gY2jhu4luaCB0cm9uZyBt4buZdCBkYXRhZnJhbWUsIC4gSMOgbSBjb21wbGV0ZSgpIGNobyBwaMOpcCBjaMO6bmcgdGEgxJFp4buBbiBjw6FjIGdpw6EgdHLhu4sgdGhp4bq/dSB0cm9uZyBkYXRhZnJhbWUgYuG6sW5nIGPDoWNoIHThuqFvIHJhIHThuqV0IGPhuqMgY8OhYyBr4bq/dCBo4bujcCBjw7MgdGjhu4MgY+G7p2EgY8OhYyBnacOhIHRy4buLIHRyb25nIGPDoWMgY+G7mXQgxJHGsOG7o2MgY2jhu4kgxJHhu4tuaC4gQ8OhYyBnacOhIHRy4buLIMSRw6MgY8OzIHPhur0gxJHGsOG7o2MgZ2nhu68gbmd1ecOqbiwgdHJvbmcga2hpIGPDoWMgZ2nDoSB0cuG7iyB0aGnhur91IHPhur0gxJHGsOG7o2MgxJFp4buBbiBi4bqxbmcgTkEgdHJvbmcga+G6v3QgcXXhuqMgaG/DoG4gY2jhu4luaC4gTmjhu69uZyDEkeG7kWkgc+G7kSBjw7MgdHJvbmcgaMOgbSBgY29tcGxldGUoKWAgbMOgDQoNCi0gICBkYXRhOiBMw6AgZGF0YSBmcmFtZSBjaOG7qWEgZOG7ryBsaeG7h3UgY+G6p24gbeG7nyBy4buZbmcgaG/hurdjIGhvw6BuIGNo4buJbmguDQoNCi0gICAuLi46IMSQxrDhu6NjIHPhu60gZOG7pW5nIMSR4buDIGNo4buJIMSR4buLbmggY8OhYyBj4buZdCBj4bqnbiBt4bufIHLhu5luZyBob+G6t2MgaG/DoG4gY2jhu4luaC4gQ8OhYyBj4buZdCBuw6B5IGPDsyB0aOG7gyBsw6AgY8OhYyB2ZWN0b3JzIGhv4bq3YyBkYW5oIHPDoWNoIChsaXN0cykuDQoNCi0gICBmaWxsOiDEkOG7kWkgc+G7kSBuw6B5IGNobyBwaMOpcCBjaMO6bmcgdGEgY3VuZyBj4bqlcCBt4buZdCBnacOhIHRy4buLIGR1eSBuaOG6pXQgY2hvIG3hu5dpIGJp4bq/biDEkeG7gyDEkWnhu4FuIHbDoG8gdGhheSB2w6wgZ2nDoSB0cuG7iyBOQSBjaG8gY8OhYyBr4bq/dCBo4bujcCBi4buLIHRoaeG6v3UuDQoNCi0gICBleHBsaWNpdDogTuG6v3UgdGhhbSBz4buRIG7DoHkgYuG6sW5nIFRSVUUgdOG6pXQgY+G6oyBnacOhIHRy4buLIE5BIMSR4buBdSBz4bq9IMSRxrDhu6NjIMSRaeG7gW4sIGPDsm4gbuG6v3UgYuG6sW5nIEZBTFNFIGNo4buJIGPDoWMgZ2nDoSB0cuG7iyBOQSDEkcaw4bujYyB04bqhbyByYSBi4bufaSBow6BtIG3hu5tpIMSRxrDhu6NjIMSRaeG7gW4uDQoNClbDrSBk4bulOiBHaeG6oyBz4butIGNow7puZyB0YSBjw7MgbeG7mXQgYuG6o25nIGThu68gbGnhu4d1IHbhu4EgY8OhYyBz4bqjbiBwaOG6qW0gY8OzIHRow7RuZyB0aW4gduG7gSB0w6puIHPhuqNuIHBo4bqpbSwgbG/huqFpIHPhuqNuIHBo4bqpbSB2w6AgZ2nDoSB0aeG7gW4uIFR1eSBuaGnDqm4sIGLhuqNuZyBk4buvIGxp4buHdSB0aGnhur91IG3hu5l0IHPhu5EgZ2nDoSB0cuG7iyBob+G6t2MgY8OzIGPDoWMgc+G6o24gcGjhuqltIGtow7RuZyBjw7MgZ2nDoSB0aeG7gW4uIENow7puZyB0YSBtdeG7kW4gxJFp4buBbiBjw6FjIGdpw6EgdHLhu4sgdGhp4bq/dSB2w6AgdOG6oW8gcmEgY8OhYyBz4bqjbiBwaOG6qW0gaG/DoG4gY2jhu4luaCB24bubaSB04bqldCBj4bqjIGPDoWMgY+G7mXQuDQoNCmBgYHtyfQ0KIyBU4bqhbyBkYXRhZnJhbWUgY2jhu6lhIHRow7RuZyB0aW4gduG7gSBz4bqjbiBwaOG6qW0NCmRhdGEyIDwtIGRhdGEuZnJhbWUoDQogIFRlblNhblBoYW0gPSBjKCJTUDEiLCAiU1AyIiwgIlNQMyIsICJTUDQiKSwNCiAgTG9haVNhblBoYW0gPSBjKCJBIiwgTkEsICJCIiwgIkMiKSwNCiAgR2lhVGllbiA9IGMoMTAwLCBOQSwgMjAwLCBOQSkNCikNCnByaW50KGRhdGEyKQ0KYGBgDQoNCmBgYHtyfQ0KIyDEkGnhu4FuIGPDoWMgZ2nDoSB0cuG7iyB0aGnhur91IHbDoCB04bqhbyByYSBjw6FjIHPhuqNuIHBo4bqpbSBob8OgbiBjaOG7iW5oDQpkYXRhX2NvbXBsZXRlIDwtIGNvbXBsZXRlKGRhdGEyLCBUZW5TYW5QaGFtLCBMb2FpU2FuUGhhbSwgR2lhVGllbikNCg0KIyBJbiBr4bq/dCBxdeG6oyBzYXUga2hpIMSRaeG7gW4gZ2nDoSB0cuG7iyB0aGnhur91IHbDoCB04bqhbyBow6BuZyBob8OgbiBjaOG7iW5oDQpvcHRpb25zKG1heC5wcmludD0gMTAwKQ0KcHJpbnQoZGF0YV9jb21wbGV0ZSwgbiA9IG5yb3coZGF0YV9jb21wbGV0ZSkpDQoNCmBgYA0KDQpUcm9uZyB2w60gZOG7pSB0csOqbiwgY2jDum5nIHRhIMSRw6Mgc+G7rSBk4bulbmcgaMOgbSBjb21wbGV0ZSgpIMSR4buDIMSRaeG7gW4gY8OhYyBnacOhIHRy4buLIHRoaeG6v3UgdsOgIHThuqFvIHJhIGPDoWMgaMOgbmcgaG/DoG4gY2jhu4luaCB0cm9uZyBkYXRhZnJhbWUgZGF0YS4gQ8OhYyBj4buZdCBUZW5TYW5QaGFtLCBMb2FpU2FuUGhhbSB2w6AgR2lhVGllbiDEkcOjIMSRxrDhu6NjIGNo4buJIMSR4buLbmggbMOgIGPDoWMgY+G7mXQgY+G6p24gaG/DoG4gY2jhu4luaC4gSMOgbSBjb21wbGV0ZSgpIMSRw6MgdOG6oW8gcmEgdOG6pXQgY+G6oyBjw6FjIGvhur90IGjhu6NwIGPDsyB0aOG7gyBj4bunYSBjw6FjIGdpw6EgdHLhu4sgdHJvbmcgY8OhYyBj4buZdCDEkcaw4bujYyBjaOG7iSDEkeG7i25oIHbDoCDEkWnhu4FuIGPDoWMgZ2nDoSB0cuG7iyB0aGnhur91IGLhurFuZyBOQSDEkeG7gyB04bqhbyByYSBjw6FjIGjDoG5nIGhvw6BuIGNo4buJbmguIEvhur90IHF14bqjIMSRxrDhu6NjIGluIHJhIG3DoG4gaMOsbmggxJHhu4MgaGnhu4NuIHRo4buLIGThu68gbGnhu4d1IMSRw6MgxJHGsOG7o2MgxJFp4buBbiB2w6AgdOG6oW8gaMOgbmcgaG/DoG4gY2jhu4luaC4NCg0KVHJvbmcga+G6v3QgcXXhuqMsIGNow7puZyB0YSBjw7MgY8OhYyBow6BuZyBob8OgbiBjaOG7iW5oIHbhu5tpIHThuqV0IGPhuqMgY8OhYyBr4bq/dCBo4bujcCBj4bunYSBjw6FjIGdpw6EgdHLhu4sgdHJvbmcgY8OhYyBj4buZdCBUZW5TYW5QaGFtLCBMb2FpU2FuUGhhbSB2w6AgR2lhVGllbi4gQ8OhYyBnacOhIHRy4buLIHRoaeG6v3UgxJHGsOG7o2MgxJFp4buBbiBi4bqxbmcgTkEgxJHhu4MgdOG6oW8gcmEgY8OhYyBow6BuZyBob8OgbiBjaOG7iW5oLg0KDQpgYGB7cn0NCiMgVGjDqm0gdsOgbyB0aGFtIHPhu5EgZmlsbCANCmRhdGFfY29tcGxldGUgPC0gY29tcGxldGUoZGF0YTIsIFRlblNhblBoYW0sIExvYWlTYW5QaGFtLCBHaWFUaWVuLCBmaWxsID0gbGlzdChMb2FpU2FuUGhhbT0iQyIsR2lhVGllbj0xNTApICkNCmRhdGF0YWJsZShkYXRhX2NvbXBsZXRlKQ0KYGBgDQoNClR1eSBuaGnDqm4sIGNow7puZyB0YSBjw7MgdGjhu4Mgw6FwIGThu6VuZyB0aGFtIHPhu5EgZmlsbCDEkeG7gyBjdW5nIGPhuqVwIG3hu5l0IGdpw6EgdHLhu4sgY2hvIG3hu5dpIGPhu5l0IGThu68gbGnhu4d1IHRoYXkgY2hvIGdpw6EgdHLhu4sgTkEuIOG7niBj4buZdCBMb2FpU2FuUGhhbSB0YSBjw7MgdGjhu4MgY2jhu41uICJDIiDEkeG7gyB0aGF5IHRo4bq/IGNobyBuaOG7r25nIGdpw6EgdHLhu4sgTkEsIHTGsMahbmcgdOG7sSB0cm9uZyBj4buZdCBHaWFUaWVuIGNo4buNbiBnacOhIHRy4buLIGzDoCAxNTAuDQoNClTDs20gbOG6oWksIHZp4buHYyBz4butIGThu6VuZyBow6BtIGNvbXBsZXRlKCkgc+G6vSBnacO6cCB0YSBxdeG6o24gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdsOgIGNodeG6qW4gYuG7iyBk4buvIGxp4buHdSBjaG8gcGjDom4gdMOtY2ggdsOgIGtow6FtIHBow6EgZOG7ryBsaeG7h3UgbeG7mXQgY8OhY2ggZOG7hSBkw6BuZyB2w6AgaGnhu4d1IHF14bqjLg0KDQojIyBDw6FjIGjDoG0geOG7rSBsw70gZ2nDoSB0cuG7iyBOQQ0KDQpUcm9uZyBwYWNrYWdlIHRpZHlyLCBjaMO6bmcgdGEgY8OzIHRo4buDIHPhu60gZOG7pW5nIGPDoWMgaMOgbSBuaMawIGBkcm9wX25hKClgLCBgZmlsbCgpYCwgdsOgYHJlcGxhY2VfbmEoKWAgxJHhu4MgeOG7rSBsw70gY8OhYyBnacOhIHRy4buLIE5BIHRyb25nIGThu68gbGnhu4d1IGPhu6dhIG3DrG5oLiBUaGFvIHTDoWMgbsOgeSBy4bqldCBj4bqnbiB0aGnhur90IMSR4buRaSB2w6wgZOG7ryBsaeG7h3UgxJHGsOG7o2MgxJFlbSB2w6BvIHBow6JuIHTDrWNoIHBo4bqjaSDEkeG6p3kgxJHhu6cgdsOgIMSR4buZIGNow61uaCB4w6FjIGNhbyB0aMOsIGvhur90IHF14bqjIHRodSDEkcaw4bujYyBz4bq9IHBo4bqjbiDDoW5oIMSRw7puZyBuaOG6pXQgduG7m2kgdGjhu7FjIHThur8uIERvIMSRw7MsIHZp4buHYyBz4butIGThu6VuZyB0aMOgbmggdGjhuqFvIGPDoWMgY8O0bmcgY+G7pSB0csOqbiBz4bq9IGdpw7pwIGNow7puZyB0YSB04buRaSDGsHUgaMOzYSB0aOG7nWkgZ2lhbiBsw6BtIHZp4buHYyBj4bunYSBtw6xuaCBjxaluZyBuaMawIGzDoCDEkeG6oXQgxJHGsOG7o2Mga+G6v3QgcXXhuqMgdOG7kXQgaMahbiDhu58gbmjhu69uZyBixrDhu5tjIHRp4bq/cCB0aGVvLg0KDQpDaMO6bmcgdMO0aSBz4bq9IHRo4buxYyBoaeG7h24gY8OhYyB2w60gZOG7pSBk4buxYSB0csOqbiBk4buvIGxp4buHdSBjw7MgY+G6pXUgdHLDumMga2jDoSDEkcahbiBnaeG6o24gbmjhurFtIG3hu6VjIMSRw61jaCBnaeG7m2kgdGhp4buHdSBuaOG7r25nIGjDoG0geOG7rSBsw70gY8OhYyBnacOhIHRy4buLIGLhu4sgdGhp4bq/dSwgbmdvw6BpIHJhIGPFqW5nIGdpw7pwIG5nxrDhu51pIMSR4buNYyBjw7MgdGjhu4MgZOG7hSBkw6BuZyBuaOG6rW4gcmEgxJHGsOG7o2MgbeG7qWMgxJHhu5kgaGnhu4d1IHF14bqjIGPhu6dhIG7DsyBraGkgxJHGsOG7o2Mgw6FwIGThu6VuZyBsw6puIGLhu5kgZOG7ryBsaeG7h3UgxJHGoW4gZ2nhuqNuLiBTYXUgxJHDsywgY2jGsMahbmcgdGnhur9wIHRoZW8gY2jDum5nIHTDtGkgc+G6vSBz4butIGThu6VuZyBsw6puIGThu68gbGnhu4d1IHBo4bupYyB04bqhcCBoxqFuIHbDoCBr4bq/dCBo4bujcCB0aMOqbSBt4buZdCBz4buRIGjDoG0ga2jDoWMgxJHhu4MgYmnhur9uIMSR4buVaSB24buBIGThuqFuZyBk4buvIGxp4buHdSBz4bqhY2guDQoNCsSQ4buDIHRo4buxYyBoaeG7h24gY8OhYyBs4buHbmggY2jDum5nIHTDtGkgc+G6vSB04bqhbyBt4buZdCBkYXRhZnJhbWUgY8OzIHTDqm4gbMOgICpkZiogZ+G7k20gY8OzIGPhu5l0ICpkYXRlKiBjaOG7qWEgY2h14buXaSBuZ8OgeSBi4bqvdCDEkeG6p3UgdOG7qyAiMjAyMy0wNy0wMSIgxJHhur9uICIyMDIzLTA3LTEwIiB2w6AgY+G7mXQgKnNhbGVzKiBjaOG7qWEgc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gxJHGsOG7o2MgYsOhbiBow6BuZyBuZ8OgeSwgdHJvbmcgxJHDsyBjw7MgbeG7mXQgc+G7kSBnacOhIHRy4buLIE5BICh0aGnhur91IHRow7RuZyB0aW4pIMSR4buDIMSR4bqhaSBkaeG7h24gY2hvIGPDoWMgbmfDoHkga2jDtG5nIGPDsyBk4buvIGxp4buHdS4NCg0KYGBge3J9DQojIFThuqFvIGThu68gbGnhu4d1IHbDrSBk4bulDQpkZiA8LSBkYXRhLmZyYW1lKA0KICBkYXRlID0gc2VxKGFzLkRhdGUoIjIwMjMtMDctMDEiKSwgYXMuRGF0ZSgiMjAyMy0wNy0xMCIpLCBieSA9ICJkYXkiKSwNCiAgc2FsZXMgPSBjKDEwMCwgTkEsIDEyMCwgODAsIE5BLCA5MCwgTkEsIE5BLCAxMTAsIDk1KQ0KKQ0KcHJpbnQoZGYpDQoNCg0KYGBgDQoNCjEuICBYw7NhIGPDoWMgZMOybmcgY2jhu6lhIGdpw6EgdHLhu4sgTkEgImRyb3BfbmEoKSINCg0KSMOgbSBgZHJvcF9uYShkZilgIHPhur0geMOzYSBjw6FjIGTDsm5nIHRyb25nIGRhdGFmcmFtZSBkZiBjaOG7qWEgZ2nDoSB0cuG7iyBOQS4gS+G6v3QgcXXhuqMgxJHGsOG7o2MgZ8OhbiB2w6BvIGRhdGFmcmFtZSAqZGZfY2xlYW5lZCogxJHGsOG7o2MgdGjhu4MgaGnhu4duIGLDqm4gZMaw4bubaS4gQ2jDum5nIHRhIHRo4bqleSBy4bqxbmcgY+G6oyA0IGTDsm5nIGPDsyBnacOhIHRy4buLIE5BIMSRw6MgYuG7iyB4w7NhIMSRaSBt4bqldCBiw6J5IGdp4budIGThu68gbGnhu4d1IGNo4buJIGPDsm4gbOG6oWkgNiBkw7JuZy4NCg0KYGBge3J9DQojIFjDs2EgY8OhYyBkw7JuZyBjaOG7qWEgZ2nDoSB0cuG7iyBOQQ0KZGZfY2xlYW5lZCA8LSBkcm9wX25hKGRmKQ0KYGBgDQoNCmBgYHtyLGVjaG89RkFMU0V9DQpwcmludChkZl9jbGVhbmVkKQ0KYGBgDQoNCjIuICDEkGnhu4FuIGPDoWMgZ2nDoSB0cuG7iyBOQSBi4bqxbmcgZ2nDoSB0cuG7iyBj4bulIHRo4buDICJmaWxsKCkiDQoNCk5nb8OgaSByYSwgY2jDum5nIHRhIGPDsyB0aOG7gyDEkWnhu4FuIGhv4bq3YyB0aGF5IHRo4bq/IGPDoWMgZ2nDoSB0cuG7iyBt4bubaSBjaG8gY8OhYyBkw7JuZyBi4buLIE5BIHRyb25nIGPhu5l0IGThu68gbGnhu4d1IGLhurFuZyBow6BtIGBmaWxsKClgLiDEkGnhu4FuIGdpw6EgdHLhu4sgc+G6vSBk4buxYSB2w6BvIGPDoWMgZMOybmcgZOG7ryBsaeG7h3Ug4bufIHBow61hIHRyw6puIGhv4bq3YyBwaMOtYSBkxrDhu5tpIMSR4buDIGhvw6BuIHRoaeG7h24gY8OhYyBkw7JuZyBOQSB0cm9uZyBj4buZdC4NCg0KxJDhu4Mgc+G7rSBk4bulbmcgaMOgbSBgZmlsbCgpYCB0aMOsIHRyxrDhu5tjIHRpw6puIHRhIGPhuqduIGtoYWkgYsOhbyBi4buZIGThu68gbGnhu4d1IGPhuqduIHjhu60gbMO9IGThu68gbGnhu4d1IHRoaeG6v3UgdHJvbmcgdHLGsOG7nW5nIGjhu6NwIG7DoHkgbMOgICpkZiosIHNhdSDEkcOzIGNo4buNbiBj4buZdCBjaOG7qWEgY8OhYyBnacOhIHRy4buLIGzDoCAqc2FsZXMqIHbDoCDEkeG7kWkgc+G7kSBgLmRpcmVjdGlvbmAgZ2nDunAgdGEgY2jhu41uIGjGsOG7m25nIMSR4buDIMSRaeG7gW4gZ2nDoSB0cuG7iyB0aGnhur91LCBt4bq3YyDEkeG7i25oIHPhur0gbMOgICJkb3duIiDEkWnhu4FuIHThu6sgdHLDqm4geHXhu5FuZy4NCg0KROG7sWEgdsOgbyBi4bqjbmcga+G6v3QgcXXhuqMgdGEgY8OzIHRo4buDIHRo4bqleSDhu58gbmfDoHkgMiB0aMOsIHPhu5EgbMaw4bujbmcgc+G6o24gcGjhuqltIMSRxrDhu6NjIGLDoW4gdHJvbmcgbmfDoHkgc+G6vSDEkcaw4bujYyDEkWnhu4FuIGzDoCAxMDAgZOG7sWEgdsOgbyBkw7JuZyBk4buvIGxp4buHdSDhu58gdHLGsOG7m2MgxJHDsywgdMawxqFuZyB04buxIGNobyBjw6FjIG5nw6B5IGLDqm4gZMaw4bubaS4NCg0KYGBge3J9DQpkZl9maWxsZWQgPC0gZmlsbChkYXRhPWRmLHNhbGVzLC5kaXJlY3Rpb24gPSAiZG93biIpDQpgYGANCg0KYGBge3IsZWNobz1GQUxTRX0NCnByaW50KGRmX2ZpbGxlZCkNCmBgYA0KDQpUw7l5IHbDoG8gbeG7pWMgxJHDrWNoIGNow7puZyB0YSBjw7MgdGjhu4MgxJFp4buBbiBnacOhIHRy4buLIGLhu4sgdGhp4bq/dSB0aGVvIMSRaeG7gXUgaMaw4bubbmcgdOG7qyBwaMOtYSBkxrDhu5tpIGzDqm4gbmjGsCBi4bqjbmcga+G6v3QgcXXhuqMgYsOqbiBkxrDhu5tpIOG7nyBuZ8OgeSA3IHbDoCA4IGdpw6EgdHLhu4sgTkEgxJHGsOG7o2MgdGhheSB0aOG6vyBi4bqxbmcgMTEwIGThu7FhIHbDoG8gc+G7kSBsxrDhu6NuZyBiw6FuIGjDoG5nIGPhu6dhIG5nw6B5IDkNCg0KYGBge3J9DQpkZl9maWxsZWQyIDwtIGZpbGwoZGF0YT1kZixzYWxlcywuZGlyZWN0aW9uID0gInVwIikNCg0KYGBgDQoNCmBgYHtyLGVjaG89RkFMU0V9DQpwcmludChkZl9maWxsZWQyKQ0KYGBgDQoNCjMuICBUaGF5IHRo4bq/IGPDoWMgZ2nDoSB0cuG7iyBOQSBi4bqxbmcgZ2nDoSB0cuG7iyBraMOhYyAicmVwbGFjZV9uYSgpIg0KDQpN4buZdCBjw6FjaCBraMOhYyBkw7luZyDEkeG7gyB44butIGzDvSBnacOhIHRy4buLIHRoaeG6v3UgbMOgIHRoYXkgdGjhur8gbsOzIGLhurFuZyBt4buZdCBnacOhIHRy4buLIGPhu6UgdGjhu4MgbcOgIGNow7puZyB0YSB4w6FjIMSR4buLbmgsIGdpw6EgdHLhu4sgxJHGsOG7o2MgZMO5bmcgdGhheSB0aOG6vyBjw7MgdGjhu4MgbMOgIG3hu5l0IGNvbiBz4buRLCBt4buZdCB2ZWN0b3IgdsOgIG7DsyB0aGF5IHRo4bq/IGNobyB04bqldCBj4bqjIGdpw6EgdHLhu4sgdGhp4bq/dSB0cm9uZyBj4buZdCBk4buvIGxp4buHdSBtw6AgY2jDum5nIHRhIGNo4buJIMSR4buLbmguDQoNClRyb25nIHbDrSBk4bulIGNow7puZyB0w7RpIHTDrW5oIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgY+G7mXQgc2FsZXMgdHJvbmcgZGF0YWZyYW1lICpkZiogdsOgIGxv4bqhaSBi4buPIGPDoWMgZ2nDoSB0cuG7iyBOQSBi4bqxbmcgxJHhu5FpIHPhu5EgYG5hLnJtID0gVFJVRWAgLiBUaeG6v3AgdGhlbywgc+G7rSBk4bulbmcgaMOgbSBgcmVwbGFjZV9uYSgpYCDEkeG7gyB0aGF5IHRo4bq/IGPDoWMgZ2nDoSB0cuG7iyBOQSB0cm9uZyBj4buZdCAqc2FsZXMqIGPhu6dhIGRhdGFmcmFtZSBkZiBi4bqxbmcgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCB2w6Aga+G6v3QgcXXhuqMgxJHGsOG7o2MgZ8OhbiB2w6BvIGRhdGFmcmFtZSBkZl9yZXBsYWNlZA0KDQpgYGB7cn0NCiMgVGhheSB0aOG6vyBjw6FjIGdpw6EgdHLhu4sgTkEgYuG6sW5nIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2Egc2FsZXMNCm1lYW5fc2FsZXMgPC0gbWVhbihkZiRzYWxlcywgbmEucm0gPSBUUlVFKQ0KZGZfcmVwbGFjZWQgPC0gcmVwbGFjZV9uYShkYXRhPWRmLCByZXBsYWNlID0gIGxpc3Qoc2FsZXMgPSBtZWFuX3NhbGVzKSkNCmBgYA0KDQpgYGB7cixlY2hvPUZBTFNFfQ0KIyBJbiBk4buvIGxp4buHdSDEkcOjIHjhu60gbMO9DQpwcmludChkZl9yZXBsYWNlZCkNCg0KYGBgDQoNCiMgQ0jGr8agTkcgMzog4buoTkcgROG7pE5HIEPhu6ZBIFRJRFlSDQoNClRyb25nIGNoxrDGoW5nIG7DoHkgY2jDum5nIHTDtGkgc+G6vSDhu6luZyBk4bulbmcgY8OhYyBow6BtIMSRxrDhu6NjIGdp4bubaSB0aGnhu4d1IOG7nyBjaMawxqFuZyAyIHbDoG8gcGjDom4gdMOtY2ggbeG7mXQgc+G7kSBi4buZIGThu68gbGnhu4d1IMSR4buDIG3hu41pIG5nxrDhu51pIG5o4bqtbiB0aOG6pXkgxJHGsOG7o2Mgc+G7sSBoaeG7h3UgcXXhuqMgY+G7p2EgZ8OzaSBUaWR5ciB0cm9uZyBnaWFpIMSRb+G6oW4geOG7rSBsw70gZOG7ryBsaeG7h3UgY2jGsGEgc+G6oWNoLiBOZ2/DoGkgcmEsIGNow7puZyB0w7RpIGvhur90IGjhu6NwIG3hu5l0IHPhu5EgZ8OzaSBraMOhYyBjaOG6s25nIGjhuqFuIG5oxrAgZHBseXIsIGdncGxvdCwgdGlkeXZlcnNlLi4uIMSR4buDIHRodeG6rW4gdGnhu4duIHRyb25nIGPDoWMgdGhhbyB0w6FjIHBow6JuIHTDrWNoIGPFqW5nIG5oxrAgdHLhu7FjIHF1YW4gaMOzYSBk4buvIGxp4buHdSB04burIMSRw7MgdGh1IMSRxrDhu6NjIGvhur90IHF14bqjIHThu5F0IG5o4bqldC4NCg0KIyMgQuG7mSBk4buvIGxp4buHdSBnYXBtaW5kZXINCg0KVHLGsOG7m2Mga2hpIHBow6JuIHTDrWNoIHRow6wgY2jDum5nIHTDtGkgc+G6vSBnaeG7m2kgdGhp4buHdSBi4buZIGThu68gbGnhu4d1ICJnYXBtaW5kZXIiIHRyb25nIHBhY2thZ2UgZ2FwbWluZGVyIGfhu5NtIGPDsyBuaOG7r25nIHRow7RuZyB0aW4gdsOgIGJp4bq/biBuw6BvIMSR4buDIG5nxrDhu51pIMSR4buNYyBjw7Mgc+G7sSBuaMOsbiBuaOG6rW4gdOG7lW5nIHF1w6F0IHbhu4EgbsOzLCDEkWnhu4F1IG7DoHkgc+G6vSBo4buvdSDDrWNoIHRyb25nIHZp4buHYyBoaeG7g3UgcsO1IGPDoWMgbOG7h25oIMSRxrDhu6NjIMOhcCBk4bulbmcgc+G6vSBtYW5nIGzhuqFpIGvhur90IHF14bqjIG5oxrAgdGjhur8gbsOgby4NCg0KQuG7mSBk4buvIGxp4buHdSAiZ2FwbWluZGVyIiBjdW5nIGPhuqVwIHRow7RuZyB0aW4gduG7gSB0deG7lWkgdGjhu40gdHJ1bmcgYsOsbmgsIGTDom4gc+G7kSB2w6AgR0RQIHBlciBjYXBpdGEgY+G7p2EgY8OhYyBxdeG7kWMgZ2lhIHThu6sgbsSDbSAxOTUyIMSR4bq/biAyMDA3IHbhu5tpIGNodSBr4buzIGzDoCA1IG7Eg20gc+G6vSB0aHUgdGjhuq1wIGThu68gbGnhu4d1IG3hu5l0IGzhuqduLiBOw7MgZ2nDunAgdGEgbuG6r20gYuG6r3QgxJHGsOG7o2Mgc+G7sSB0aGF5IMSR4buVaSB2w6Agc+G7sSBwaMOhdCB0cmnhu4NuIGPhu6dhIGPDoWMgcXXhu5FjIGdpYSB0aGVvIHRo4budaSBnaWFuLiBE4buvIGxp4buHdSBuw6B5IGfhu5NtIDE3MDQgcXVhbiBzw6F0IHbDoCBjw7MgNiBiaeG6v24gdHJvbmcgxJHDszoNCg0KLSAgIGNvdW50cnk6IFTDqm4gcXXhu5FjIGdpYS4NCg0KLSAgIGNvbnRpbmVudDogTOG7pWMgxJHhu4thIG7GoWkgcXXhu5FjIGdpYSB0aHXhu5ljIHbhu4EuIEPDsyA1IGdpw6EgdHLhu4s6IEFmcmljYSwgQW1lcmljYXMsIEFzaWEsIEV1cm9wZSwgdsOgIE9jZWFuaWEuDQoNCi0gICB5ZWFyOiBOxINtIGdoaSBuaOG6rW4gZOG7ryBsaeG7h3UuDQoNCi0gICBsaWZlRXhwOiBUdeG7lWkgdGjhu40gdHJ1bmcgYsOsbmggY+G7p2EgZMOibiBz4buRIHRyb25nIHF14buRYyBnaWEsIHTDrW5oIGLhurFuZyDEkcahbiB24buLIG7Eg20uDQoNCi0gICBwb3B1bGF0aW9uOiBEw6JuIHPhu5EgY+G7p2EgcXXhu5FjIGdpYSB0cm9uZyBuxINtIGPhu6UgdGjhu4MuDQoNCi0gICBnZHBQZXJjYXA6IEdEUCB0csOqbiBt4buXaSBuZ8aw4budaSBkw6JuIGPhu6dhIG3hu5l0IHF14buRYyBnaWEgdHJvbmcgbsSDbSBj4bulIHRo4buDLg0KDQpgYGB7cix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KERUKQ0KYGBgDQoNCsSQ4bqndSB0acOqbiwgY2jDum5nIHRhIGPhuqduIGfhu41pIGThu68gbGnhu4d1ICJnYXBtaW5kZXIiIGLhurFuZyBs4buHbmggYGRhdGFgIHNhdSBraGkgxJHDoyBjw6BpIMSR4bq3dCBwYWNrYWdlICpnYXBtaW5kZXIqIHbDoCB04bqjaSB0aMawIHZp4buHbiBj4bunYSBuw7MgbMOqbiwgZOG7ryBsaeG7h3Ugc+G6vSDEkcaw4bujYyBnw6FuIHbDoG8gYmnhur9uICJnIiBnacO6cCB2aeG7h2Mgbmjhuq1wIGzhu4duaCB0cuG7nyBuw6puIGThu4UgZMOgbmcgaMahbiBzbyB24bubaSB0w6puIGJhbiDEkeG6p3UuDQoNCkLhuqNuZyBk4buvIGxp4buHdSBiw6puIGTGsOG7m2ksIG3hu5dpIHF1YW4gc8OhdCBz4bq9IGNobyBiaeG6v3QgdGjDtG5nIHRpbiB24buBIHTDqm4gcXXhu5FjIGdpYSwgY2jDonUgbOG7pWMgY+G7p2EgcXXhu5FjIGdpYSwgbsSDbSBraOG6o28gc8OhdCB2w6AgY8OhYyBjaOG7iSBz4buRIHbhu4EgdHXhu5VpIHRo4buNIHRydW5nIGLDrG5oLCBkw6JuIHPhu5EsIEdEUCB0csOqbiBt4buXaSBjw6EgbmjDom4gdMawxqFuZyDhu6luZy4gRG8gxJHDsywgbsOzIHRodeG7mWMgZOG6oW5nIGThu68gbGnhu4d1ICJy4buZbmciIMSRaeG7gXUgbsOgeSBz4bq9IGdpw7pwIHZp4buHYyBuaOG6rXAgZOG7ryBsaeG7h3UgaG/hurdjIHRyw6xuaCBiw6B5IGLhuqNuZyB04buRdCBoxqFuLCBuZ8aw4budaSDEkeG7jWMgYsOhbyBjw6FvIGPDsyB0aOG7gyBoaeG7g3UgcsO1IMSRxrDhu6NjIG7hu5lpIGR1bmcgbcOgIGtow7RuZyBt4bqldCBxdcOhIG5oaeG7gXUgdGjhu51pIGdpYW4uIFR1eSBuaGnDqm4gZOG6oW5nIGThu68gbGnhu4d1ICJy4buZbmciIHPhur0gZ+G6t3Aga2jDsyBraMSDbiB0cm9uZyB2aeG7h2MgcGjDom4gdMOtY2ggdsOsIHbhuq15IGNow7puZyB0YSBj4bqnbiBwaOG6o2kgY2h1eeG7g24gc2FuZyBk4bqhbmcgImTDoGkiLg0KDQpgYGB7cix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KGdhcG1pbmRlcikNCmRhdGEoImdhcG1pbmRlciIpDQpnIDwtIGdhcG1pbmRlcg0KZGF0YXRhYmxlKGcpDQoNCmBgYA0KDQpIw6BtIGBwaXZvdF9sb25nZXIoKWBz4bq9IGNodXnhu4NuIGThu68gbGnhu4d1ICJnIiBzYW5nIGThuqFuZyBkw6BpIGLhurFuZyBjw6FjaCBjaHV54buDbiDEkeG7lWkgYmEgY+G7mXQgKmxpZmVFeHAsIHBvcCwgZ2RwUGVyY2FwKiB0aMOgbmggaGFpIGPhu5l0IG3hu5tpIGzDoCAqY2hpc28qIGNo4bupYSB0w6puIGPDoWMgY2jhu4kgc+G7kSB2w6AgKmdpYXRyaSogY2jhu6lhIGPDoWMgZ2nDoSB0cuG7iyBj4bunYSBjw6FjIGJp4bq/biBiYW4gxJHhuqd1LiBTYXUgxJHDsyBz4bq9IGfDoW4gZOG7ryBsaeG7h3UgxJHGsOG7o2MgY2h1eeG7g24gxJHhu5VpIHbDoG8gImcyIiwgZOG7ryBsaeG7h3UgbsOgeSBz4bq9IGPDsyBz4buRIHF1YW4gc8OhdCBsw6AgNTExMiB0dXkgbmhpw6puIHRow6wgc+G7kSBsxrDhu6NuZyBiaeG6v24gc+G6vSDDrXQgaMahbiBk4buvIGxp4buHdSBiYW4gxJHhuqd1ICg1IGPhu5l0IHNvIHbhu5tpIDYgY+G7mXQpLg0KDQpgYGB7cn0NCmcyIDwtIHBpdm90X2xvbmdlcihkYXRhID0gZyAsIGNvbHMgPSBjKGxpZmVFeHAscG9wLGdkcFBlcmNhcCksIG5hbWVzX3RvID0gImNoaXNvIiwgdmFsdWVzX3RvID0gImdpYXRyaSIpDQpoZWFkKGcyKQ0KYGBgDQoNCk7hur91IHRhIG114buRbiB0w61uaCB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIGNo4buJIHPhu5EgbsOgeSB0aGVvIHThu6tuZyBjaMOidSBs4bulYyBraMOhYyBuaGF1IG5o4bqxbSBt4bulYyDEkcOtY2ggxJHDoW5oIGdpw6EgdOG7lW5nIHRo4buDIHPhu7EgcGjDoXQgdHJp4buDbiBnaeG7r2EgY8OhYyBjaMOidSB24bubaSBuaGF1LCB0YSBjw7MgdGjhu4Mgc+G7rSBk4bulbmcgdGjDqm0gaMOgbSBgZ3JvdXBfYnlgIMSR4buDIG5ow7NtIGThu68gbGnhu4d1IHRoZW8gY+G7mXQgKmNvbnRpbmVudCwgY2hpc28qIHbDoCBow6BtIGBzdW1tYXJpc2VgIMSR4buDIHRo4buxYyBoaeG7h24gcGjDqXAgdMOtbmggdHJ1bmcgYsOsbmggY2hvIGPhu5l0ICpnaWF0cmkqIGPhu6dhIGPDoWMgbmjDs20gZOG7ryBsaeG7h3UuIEPhuqMgaGFpIGjDoG0gdHLDqm4gxJHhu4F1IG7hurFtIHRyb25nIGfDs2kgKipkcGx5cioqIGPDsyB0aOG7gyBr4bq/dCBo4bujcCB24bubaSBnw7NpICoqdGlkeXIqKiDEkeG7gyBiaeG6v24gxJHhu5VpIGThu68gbGnhu4d1IGNoxrBhIHPhuqFjaCBy4bqldCBoaeG7h3UgcXXhuqMuDQoNCkvhur90IHF14bqjIHRodSDEkcaw4bujYyBz4bq9IMSRxrDhu6NjIGfDoW4gdsOgbyAibWVhbl9nMiIgdHJvbmcgxJHDsyBz4bq9IGPDsyBj4buZdCAqY29udGluZW50KiBjaOG7qWEgdGjDtG5nIHRpbiB24buBIGPDoWMgY2jDonUgbOG7pWMuIEPhu5l0ICpjaGlzbyogZ+G7k20gZ2nDoSB0cuG7iyBsw6AgR0RQLCB0deG7lWkgdGjhu40sIGTDom4gc+G7kS4gQ+G7mXQgKnRydW5nYmluaCogc+G6vSBjaOG7qWEgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBjw6FjIGNo4buJIHPhu5EgdMawxqFuZyDhu6luZyB24bubaSBt4buXaSBjaMOidSBs4bulYy4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQptZWFuX2cyIDwtIGcyICU+JSBncm91cF9ieShjb250aW5lbnQsY2hpc28pICU+JSBzdW1tYXJpc2UodHJ1bmdiaW5oPW1lYW4oZ2lhdHJpKSkNCmRhdGF0YWJsZShtZWFuX2cyKQ0KYGBgDQoNClThu6sgxJHDsywgY2jDum5nIHRhIHRy4buxYyBxdWFuIGjDs2EgYuG7mSBk4buvIGxp4buHdSB24burYSDEkcaw4bujYyB0w61uaCB0cnVuZyBiw6xuaCBi4bqxbmcgY8OhY2ggduG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgY2hvIGJhIGNo4buJIHPhu5EgduG7m2kgY8OhYyBtw6B1IHPhuq9jIGtow6FjIG5oYXUuIEPDoWMgY+G7mXQgdHLDqm4gxJHhu5MgdGjhu4sgc+G6vSB0xrDGoW5nIOG7qW5nIHbhu5tpIGPDoWMgY2jDonUgbOG7pWMgdHJvbmcgZOG7ryBsaeG7h3UuDQoNCkJp4buDdSDEkeG7kyBjw7MgY8OhYyBj4buZdCBtw6B1IMSR4buPIGzDoCBiaeG7g3UgxJHhu5MgduG7gSBHRFAgdHLDqm4gbeG7l2kgY8OhIG5ow6JuIHRydW5nIGLDrG5oIGPhu6dhIDUgY2jDonUgbOG7pWMuIEThu7FhIHbDoG8gYmnhu4N1IMSR4buTIHRhIGPDsyB0aOG7gyB0aOG6pXkgQ2jDonUgxJDhuqFpIMSQxrDGoW5nIGPDsyBHRFAgY2FvIG5o4bqldCB0cm9uZyA1IGNow6J1IGzhu6VjIChraG/huqNuZyAxODYyMSDEkcO0KSwgbmfGsOG7o2MgbOG6oWkgdGjDrCBDaMOidSBQaGkgY8OzIEdEUCB0cnVuZyBiw6xuaCB0aOG6pXAgduG7m2kgY29uIHPhu5Ega2hpw6ptIHThu5FuIGzDoCBraG/huqNuZyAyMTkzIMSRw7QgdHLDqm4gbeG7l2kgY8OhIG5ow6JuLg0KDQpCaeG7g3UgxJHhu5MgY+G7mXQgbcOgdSB4YW5oIGzDoSDEkeG6oWkgZGnhu4duIGNobyB0deG7lWkgdGjhu40gdHJ1bmcgYsOsbmggY+G7p2EgbmfGsOG7nWkgZMOibiDhu58gbeG7l2kgY2jDonUgbOG7pWMsIG5ow6xuIHThu5VuZyB0aOG7gyB0aMOsIGPDoWMgY2jDonUgbOG7pWMgY8OzIHR14buVaSB0aOG7jSB0cnVuZyBiw6xuaCBraMO0bmcgY2jDqm5oIGzhu4djaCBuaGnhu4F1LCBuZ2/huqFpIHRy4burIENow6J1IFBoaSBjw7MgdHXhu5VpIHRo4buNIHRydW5nIGLDrG5oIGzDoCBraG/huqNuZyA0OSB0deG7lWkga2jDoSB0aOG6pXAgc28gduG7m2kgQ2jDonUgw4J1ICg3MiB0deG7lWkpIHbDoCBDaMOidSDEkOG6oWkgxJDGsMahbmcgKDc0IHR14buVaSkuDQoNCkN14buRaSBjw7luZywgYmnhu4N1IMSR4buTIGPDsyBj4buZdCBtw6B1IHhhbmggZMawxqFuZyBjaG8gYmnhur90IHRow7RuZyB0aW4gduG7gSBkw6JuIHPhu5EgdHJ1bmcgYsOsbmggY+G7p2EgY8OhYyBxdeG7kWMgZ2lhIHRyb25nIG3hu5l0IGNow6J1IGzhu6VjIGPhu6UgdGjhu4MuIFRhIG5o4bqtbiB0aOG6pXkgcuG6sW5nIGPDoWMgcXXhu5FjIGdpYSBDaMOidSDDgSBjw7MgZMOibiBz4buRIHRydW5nIGLDrG5oIGNhbyB2xrDhu6N0IHRy4buZaSBzbyB24bubaSBjw6FjIGNow6J1IGzhu6VjIGPDsm4gbOG6oWkoIGtob+G6o25nIDc3IHRyaeG7h3UgbmfGsOG7nWkpLiBUdXkgbmhpw6puIHRow6wgY8OhYyBxdeG7kWMgZ2lhIHRodeG7mWMgQ2jDonUgxJDhuqFpIMSQxrDGoW5nIHbDoCBDaMOidSBQaGkgY8OzIGTDom4gc+G7kSB0aOG6pXAgKGTGsOG7m2kgbeG7qWMgMTAgdHJp4buHdSBuZ8aw4budaSkuDQoNCmBgYHtyfQ0KZ2dwbG90KG1lYW5fZzIsIGFlcyh4ID0gY29udGluZW50LCB5ID0gdHJ1bmdiaW5oLCBmaWxsID0gY2hpc28pKSArDQogIGdlb21fY29sKCkgKw0KICBmYWNldF9ncmlkKGNoaXNvIH4gLiwgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicyh4ID0gIkNoYXVMdWMiLCB5ID0gIkdpYVRyaSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjEsIDAuMSkpKQ0KDQoNCmBgYA0KDQpUcm9uZyBt4buZdCB2w6BpIHTDrG5oIGh14buRbmcgbmh1IGPhuqd1IGPhu6dhIG5nxrDhu51pIHBow6JuIHTDrWNoIGNo4buJIGPhuqduIGNo4buNbiBt4buZdCBz4buRIHF14buRYyBnaWEgY+G7pSB0aOG7gyDEkeG7gyDEkcOhbmggZ2nDoSBz4buxIHBow6F0IHRyaeG7g24gY+G7p2EgbsOzIGLhurFuZyBjw6FjIGNo4buJIHPhu5EgdGjDrCBjaMO6bmcgdGEgY8WpbmcgY8OzIMSR4buDIGvhur90IGjhu6NwIHRow6ptIGjDoG0gYHNlbGVjdCgpYCB2w6AgYGZpbHRlcmAgdGh14buZYyBnw7NpICoqZHBseXIqKiwgc2F1IMSRw7MgdGjhu4MgaGnhu4duIGThu68gbGnhu4d1IOG7nyBk4bqhbmcgxJHhu5MgdGjhu4sgYuG6sW5nIGPDoWMgY8O0bmcgY+G7pSBt4bqhbmggbeG6vSB04burIGfDs2kgKipnZ3Bsb3QyKiouDQoNCkTGsOG7m2kgxJHDonkgY2jDum5nIHTDtGkgY2jhu41uIGPDoWMgY+G7mXQgKmNvdW50cnksIGxpZmVFeHAsIHllYXIqIGLhurFuZyBow6BtIGBzZWxlY3QoKWAgxJHhu4MgZOG7ryBsaeG7h3UgxJHhuqd1IHRyb25nIGjDoG0gcGjDrWEgc2F1IHPhur0gbmjhu48gaMahbiBi4buZIGThu68gbGnhu4d1IGJhbiDEkeG6p3UuIFBow6lwIHRvw6FuIHThu60gKiVcPiUqIGdpw7pwIGThu68gbGnhu4d1IHNhdSBraGkgxJHGsOG7o2MgY2jhu41uIMSRxrBhIHbDoG8gxJHhu5FpIHPhu5EgxJHhuqd1IHRpw6puIGPhu6dhIGjDoG0gYGZpbHRlcmAgxJHhu4MgdGjhu7FjIGhp4buHbiBs4buNYyBt4buZdCBz4buRIHF14buRYyBnaWEgdHJvbmcgY+G7mXQgKmNvdW50cnkqLiBDdeG7kWkgY8O5bmcgc+G7rSBk4bulbmcgaMOgbSBgZ2dwbG90YCDEkeG7gyB24bq9IMSR4buTIHRo4buLIMSRxrDhu51uZyB24buBIHR14buVaSB0aOG7jSB0cnVuZyBiw6xuaCBj4bunYSBiYSBxdeG7kWMgZ2lhIENoaW5hLCBWaWV0bmFtLCBVbml0ZWQgU3RhdGVzLg0KDQpgYGB7cn0NCmcgJT4lIHNlbGVjdChjb3VudHJ5LGxpZmVFeHAseWVhcikgJT4lICBmaWx0ZXIoY291bnRyeSAlaW4lIGMoIkNoaW5hIiwiVmlldG5hbSIsIlVuaXRlZCBTdGF0ZXMiKSklPiUgDQogIGdncGxvdChhZXMoeCA9IHllYXIgLCB5ID0gbGlmZUV4cCwgY29sb3I9Y291bnRyeSkpKw0KICAgICAgZ2VvbV9saW5lKCkrDQogICAgICBsYWJzKHg9ICJOxIJNIiwgeT0gIlRV4buUSSBUSOG7jCIsIHRpdGxlID0gIkJJ4buCVSDEkOG7kiBUVeG7lEkgVEjhu4wgVFJVTkcgQsOMTkgiLCBjb2xvciA9ICJRVeG7kEMgR0lBIikNCg0KYGBgDQoNCsSQ4buDIGJp4bq/dCB0aMOqbSB0aMO0bmcgdGluIHbhu4Egc+G7sSB0aGF5IMSR4buVaSB04buVbmcgZMOibiBz4buRIHRyb25nIGNow6J1IGzhu6VjIHF1YSBjw6FjIG7Eg20sIGNow7puZyB0w7RpIMSRw6MgdMOtbmggdOG7lW5nIGTDom4gc+G7kSDEkcaw4bujYyBuaMOzbSB0aGVvIGJp4bq/biAqY29udGluZW50LCB5ZWFyKi4gS+G6v3QgcXXhuqMgc+G6vSDEkcaw4bujYyBnw6FuIHbDoG8gImczIiDEkeG7gyB0aHXhuq1uIHRp4buHbiB0aOG7sWMgaGnhu4duIGPDoWMgbOG7h25oIHRp4bq/cCB0aGVvLg0KDQpE4buvIGxp4buHdSBzYXUga2hpIHTDrW5oIHThu5VuZyBkw6JuIHPhu5EgxJHDoyB0aHXhu5ljIGThuqFuZyBk4buvIGxp4buHdSBkw6BpLCDEkWnhu4F1IG7DoHkgc+G6vSBraGnhur9uIHZp4buHYyB0aOG7sWMgaGnhu4duIHRy4buxYyBxdWFuIGjDs2EgbeG7mXQgY8OhY2ggcuG6pXQgZOG7hSBkw6BuZy4gRG8gxJHDsyBjaMO6bmcgdGEgY8OzIHRo4buDIHPhu60gZOG7pW5nIG7DsyBiaeG7g3UgZGnhu4VuIMSR4buTIHRo4buLIGPhu5l0IHbhu4Egc+G7sSB0aGF5IMSR4buVaSB04buVbmcgZMOibiBz4buRIGPhu6dhIGPDoWMgY2jDonUgbOG7pWMgbsOgeSBxdWEgY8OhYyBuxINtIG5nYXkgbOG6rXAgdOG7qWMuDQoNCmBgYHtyLG1lc3NhZ2UgPSBGQUxTRX0NCmczIDwtIGcgJT4lIGdyb3VwX2J5KGNvbnRpbmVudCx5ZWFyKSAlPiUgDQogIHN1bW1hcmlzZShzcG9wPXN1bShwb3ApKQ0KaGVhZChnMykNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChnMykrDQogIGdlb21fY29sKA0KICAgIGFlcyh4PSB5ZWFyLCB5ID0gc3BvcCwgZmlsbD0gY29udGluZW50ICksDQogICAgd2lkdGggPSAyDQogICkNCmBgYA0KDQrEkOG7gyBwaMO5IGjhu6NwIGNobyB2aeG7h2MgdGjhu7FjIGhp4buHbiBjw6FjIGLDoW8gY8OhbyB2w6AgdHLDrG5oIGLDoHkgYuG6o25nIGNow7puZyB0YSBjw7MgdGjhu4MgZMO5bmcgaMOgbSBgcGl2b3Rfd2lkZXIoKWAgxJHhu4MgY2h1eeG7g24gKmczKiBzYW5nIGThuqFuZyBy4buZbmcgbmjGsCBiw6puIGTGsOG7m2kgxJHDonkuIELhuqNuZyBuw6B5IHPhur0gZ2nDunAgdGEgcXVhbiBzw6F0IHThu5VuZyBkw6JuIHPhu5EgY+G7p2EgdOG7q25nIGzhu6VjIMSR4buLYSBxdWEgY8OhYyBuxINtIG3hu5l0IGPDoWNoIHRodeG6rW4gdGnhu4duIGjGoW4uDQoNCmBgYHtyfQ0Kd2lkZXJfZzM8LSBwaXZvdF93aWRlcihnMyAsbmFtZXNfZnJvbSA9IGNvbnRpbmVudCwgdmFsdWVzX2Zyb20gPSBzcG9wKQ0KZGF0YXRhYmxlKHdpZGVyX2czKQ0KYGBgDQoNCi0gICBTYXUgxJHDsyB24bq9IMSR4buTIHRo4buLIGPhu5l0IHRo4buDIGhp4buHbiB04buVbmcgZMOibiBz4buRIHRoYXkgxJHhu5VpIHF1YSBjw6FjIG7Eg20gY2hvIGNow6J1IMOCdQ0KDQpgYGB7cn0NCg0KZ2dwbG90KHdpZGVyX2czLCBhZXMoeCA9IHllYXIsIHk9IEV1cm9wZSAsZmlsbD0gIkV1cm9wZSIgKSkrDQogIGdlb21fY29sKCkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9ICJibHVlIikgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogICBsYWJzKHggPSAiTsSDbSIseT0iRMOibiBz4buRIiwgdGl0bGUgPSAgIkJJ4buCVSDEkOG7kiBEw4JOIFPhu5AgQ0jDglUgw4JVICIsIGZpbGwgPSAiQ2jDonUiKQ0KDQpgYGANCg0KLSAgIEThu7FhIHbDoG8gxJHhu5MgdGjhu4ssIHThu5VuZyBkw6JuIHPhu5EgY+G7p2EgQ2jDonUgw4J1IGPDsyBz4buxIGdpYSB0xINuZyBxdWEgY8OhYyBuxINtIHbDoCB04buRYyDEkeG7mSB0xINuZyBuw6B5IGtow6EgxJHhu5NuZyDEkeG7gXUgbmhhdS4gTsSDbSAxOTUyIHThu5VuZyBkw6JuIHPhu5EgY+G7p2EgY2jDonUgbOG7pWMgbsOgeSBjaOG7iSBjw7Mga2hv4bqjbmcgNDAwIHRyaeG7h3UgbmfGsOG7nWkgdsOgIHTEg25nIGThuqduIMSR4bq/biBuxINtIDIwMDcgdGjDrCBjw7Mga2hv4bqjbmcgNjAwIHRyaeG7h3UgbmfGsOG7nWkuDQoNCiAgICBUaeG6v3AgdGhlbywgY2jDum5nIHTDtGkgc+G7rSBk4bulbmcgaMOgbSBgbmVzdCgpYCDEkeG7gyBnb20gY8OhYyBj4buZdCBwb3AsIGdkcFBlcmNhcCB2w6AgbGlmZUV4cCB0aMOgbmggbeG7mXQgY+G7mXQgZOG6oW5nIG5lc3RlZCBsaXN0LiDEkGnhu4F1IG7DoHkgZ2nDunAgZ2nhuqNtIHPhu7EgcGjhu6ljIHThuqFwIGPhu6dhIGThu68gbGnhu4d1IHbDoCB0aOG7sWMgaGnhu4duIGPDoWMgdMOtbmggdG/DoW4gbGluaCBob+G6oXQgaMahbiB0aGVvIG5ow7NtIMSRw6MgxJHGsOG7o2MgZ+G7mXAuDQoNCmBgYHtyfQ0KIyBT4butIGThu6VuZyBow6BtIG5lc3QoKSDEkeG7gyBnb20gY8OhYyBuxINtIHbDoCBjaOG7iSBz4buRIHTGsMahbmcg4bupbmcgdGjDoG5oIGPhu5l0IGThuqFuZyBuZXN0ZWQgbGlzdA0KbmVzdGVkIDwtIGcgJT4lICBuZXN0KC5ieSAgPSBjKGNvdW50cnksIGNvbnRpbmVudCx5ZWFyKSwua2V5ID0gImNoaXNvIikNCmBgYA0KDQpgYGB7cixlY2hvPUZBTFNFfQ0KcHJpbnQobmVzdGVkKQ0KYGBgDQoNCi0gICBOaMawIGvhur90IHF14bqjIGhp4buDbiB0aOG7iyBiw6puIHRyw6puLCBj4buZdCAqY2hpc28qIG7hurFtIOG7nyBk4bqhbmcgZGFuaCBzw6FjaCBs4buTbmcgbmhhdSAoIG5lc3RlZCBsaXN0KSwgbeG7l2kgcGjhuqduIHThu60gc+G6vSBjaOG7qWEgdGjDtG5nIHRpbiB24buBICpwb3AsIGdkcCwgbGlmZUV4cCogY+G7p2EgbeG7l2kgcXXhu5FjIGdpYSB0aGVvIHThu6tuZyBuxINtLg0KDQpIxqFuIHRo4bq/LCBu4bq/dSBjaMO6bmcgdGEgY+G6p24gdGjDtG5nIHRpbiB24buBIGPDoWMgY2jhu4kgc+G7kSBj4bunYSBt4buZdCBxdeG7kWMgZ2lhIGPhu6UgdGjhu4MgY2jhurNuZyBo4bqhbiBuaMawIFVuaXRlZCBTdGF0ZXMgdGEgY8OzIHRo4buDIGTDuW5nIGjDoG0gYGZpbHRlcigpYCDEkeG7gyBs4buNYyBuw7MgcmEgdsOgIGhp4buDbiB0aOG7iyBr4bq/dCBxdeG6oyB24buBIG5o4buvbmcgY2jhu4kgc+G7kSDEkcOjIMSRxrDhu6NjIGdvbS4NCg0KYGBge3J9DQpuZXN0ZWQkY2hpc28gPC0gbGFwcGx5KG5lc3RlZCRjaGlzbywgYXMuZGF0YS5mcmFtZSkNClVTIDwtIG5lc3RlZCAlPiUgIGZpbHRlcihjb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIikNCmBgYA0KDQpgYGB7cixlY2hvPUZBTFNFfQ0KcHJpbnQoVVMkY2hpc28pDQpgYGANCg0KLSAgIMSQ4buDIGdp4bqjaSBuw6luIGThu68gbGnhu4d1IOG7nyBk4bqhbmcgbGlzdCBuZXN0ZWQgdGjDrCB0YSBkw7luZyBow6BtIGB1bm5lc3QoKWAsIGvhur90IHF14bqjIHRodSDEkcaw4bujYyBz4bq9IHTGsMahbmcgdOG7sSBk4buvIGxp4buHdSBiYW4gxJHhuqd1IGJhbiDEkeG6p3UuDQoNCmBgYHtyfQ0KIyBT4butIGThu6VuZyBow6BtIHVubmVzdCgpIMSR4buDIGdp4bqjaSBuw6luIGThu68gbGnhu4d1DQp1bm5lc3QgPC0gbmVzdGVkICU+JSB1bm5lc3QoY2hpc28pDQpgYGANCg0KYGBge3IsZWNobz1GQUxTRX0NCnByaW50KHVubmVzdCkNCmBgYA0KDQpgYGB7cn0NCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgY2hvIHThu5VuZyBkw6JuIHPhu5EgKHBvcCkgY+G7p2EgdOG7q25nIHF14buRYyBnaWEgdHJvbmcgbsSDbSAyMDA3DQogdW5uZXN0ICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAwNyAmIGNvdW50cnkgJWluJSBjKCJWaWV0bmFtIiwgIkNoaW5hIiwgIktvcmVhLCBSZXAuIiwgIkphcGFuIiwiSW5kb25lc2lhIiwiVGhhaWxhbmQiLCJNYWxheXNpYSIsIkluZGlhIikpICU+JSANCiAgZ2dwbG90KCBhZXMoeCA9IHJlb3JkZXIoY291bnRyeSwgcG9wKSwgeSA9IHBvcCxmaWxsID0gY291bnRyeSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgbGFicyh0aXRsZSA9ICJEw6JuIHPhu5EgY+G7p2EgbeG7mXQgcXXhu5FjIGdpYSBBc2lhIHRyb25nIG7Eg20gMjAwNyIsDQogICAgICAgeCA9ICJRdeG7kWMgZ2lhIiwNCiAgICAgICB5ID0gIlThu5VuZyBkw6JuIHPhu5EiKQ0KDQpgYGANCg0KLSAgIEJp4buDdSDEkeG7kyBjaG8gdGjhuqV5IHLhurFuZyBkw6JuIHPhu5EgY+G7p2EgSW5kaWEgKEtob+G6o25nIDEsMSB04bu3IG5nxrDhu51pKSwgQ2hpbmEgKGtob+G6o25nIDEsMyB04bu3IG5nxrDhu51pKSB0cm9uZyBuxINtIDIwMDcgY2FvIGjGoW4gcuG6pXQgbmhp4buBdSBzbyB24bubaSBt4buZdCBz4buRIHF14buRYyBnaWEgdHJvbmcga2h1IHbhu7FjIENow6J1IMOBLiBRdeG7kWMgZ2lhIGPDsyBkw6JuIHPhu5EgdGjhuqVwIG5o4bqldCB0cm9uZyBjw6FjIHF14buRYyBnaWEgdHLDqm4gbMOgIE1hbGF5c2lhIGNo4buJIGPDsyBraG/huqNuZyAyNSB0cmnhu4d1IG5nxrDhu51pDQoNClZp4buHYyBz4butIGThu6VuZyBuZXN0KCkgdsOgIHVubmVzdCgpIGNobyBi4buZIGThu68gbGnhu4d1IGdhcG1pbmRlciBjaG8gcGjDqXAgdGEgY2h1eeG7g24gxJHhu5VpIGThu68gbGnhu4d1IHThu6sgZOG6oW5nIGLhuqNuZyB0aMO0bmcgdGjGsOG7nW5nIHRow6BuaCBk4bqhbmcgbmVzdGVkIGxpc3QgdsOgIG5nxrDhu6NjIGzhuqFpLiDEkGnhu4F1IG7DoHkgY8OzIHRo4buDIGjhu691IMOtY2ggdHJvbmcgdmnhu4djIHRoYW8gdMOhYyB2w6AgeOG7rSBsw70gZOG7ryBsaeG7h3UsIMSR4bq3YyBiaeG7h3QgbMOgIGtoaSBsw6BtIHZp4buHYyB24bubaSBk4buvIGxp4buHdSBjw7MgY+G6pXUgdHLDumMgcGjhu6ljIHThuqFwIGjGoW4gdsOgIGPDsyBuaGnhu4F1IGPhuqVwIMSR4buZIGzhu5NuZyBuaGF1Lg0KDQojIyBXSE8NCg0KVHJvbmcgcGjhuqduIG7DoHkgY2jDum5nIHTDtGkgc+G6vSBsw6BtIHZp4buHYyB0csOqbiBi4buZIGThu68gbGnhu4d1ICoqd2hvKiosIMSRw6J5IGzDoCBi4buZIGThu68gbGnhu4d1IGNvbiDEkcaw4bujYyB0aHUgdGjhuq1wIHThu6sgYsOhbyBjw6FvIHbhu4EgYuG7h25oIGxhbyB0b8OgbiBj4bqndSBj4bunYSBU4buVIGNo4bupYyBZIHThur8gVGjhur8gZ2nhu5tpLiBOw7MgZ+G7k20gY8OzIDYwIGPhu5l0IHbDoCA3MjQwIHF1YW4gc8OhdCwgdHV5IG5oacOqbiB0aMOsIHThu6sgY+G7mXQgdGjhu6kgNSDEkeG6v24gY+G7mXQgNjAgY8OzIGvDvSB04buxICJuZXdcXyIgxJHGsOG7o2Mga+G6v3QgbuG7kWkgduG7m2kgY8OhYyB0aMO0bmcgdGluIGtow6FjLg0KDQotICAgKipjb3VudHJ5KiogbMOgIHTDqm4gY+G7p2EgY8OhYyBxdeG7kWMgZ2lhIMSRxrDhu6NjIHRodSB0aOG6rXAuDQoNCi0gICAqKmlvczIsIGlvczMqKiBs4bqnbiBsxrDhu6N0IGzDoCBtw6MgcXXhu5FjIGdpYSAyIGvDvSB04buxIHbDoCAzIGvDvSB04buxLg0KDQotICAgKip5ZWFyKiogbMOgIG7Eg20gdGh1IHRo4bqtcCBk4buvIGxp4buHdS4NCg0KLSAgIFBoxrDGoW5nIHBow6FwIGNo4bqpbiDEkW/DoW4gbuG6v3UgbMOgICoqcmVsKiogbmdoxKlhIGzDoCB0w6FpIHBow6F0LCAqKnNuKiogbMOgIGLhu4duaCBuaMOibiBraMO0bmcgY8OzIHZpIGtodeG6qW4gbGFvICwgKipzcCoqIGzDoCBi4buHbmggbmjDom4gY8OzIHZpIGtodeG6qW4gbGFvLCAqKmVwKiogYuG7h25oIG5ow6JuIGxhbyBuZ2/DoGkgcGjhu5VpLg0KDQotICAgS8O9IHThu7EgKipmKiogxJHhuqFpIGRp4buHbiBjaG8gZ2nhu5tpIHTDrW5oIG7hu68gdsOgICoqbSoqIGzDoCBnaeG7m2kgdMOtbmggbmFtDQoNCi0gICBT4buRIHRyb25nIG3hu5dpIGPhu5l0IMSRxrDhu6NjIGTDuW5nIMSR4buDIHRo4buDIGhp4buHbiBuaMOzbSB0deG7lWkgdsOtIGThu6UgMDE0IGzDoCAwLTE0IHR14buVaSwgMTUyNCBsw6AgMTUtMjQgdHXhu5VpLCAyNTM0IGzDoCAyNS0zNCB0deG7lWksIDM1NDQgbMOgIDM1LTQ0IHR14buVaSwgNDU1NCBsw6AgNDUtNTQgdHXhu5VpLCA1NTY0IGzDoCA1NS02NCB0deG7lWkgdsOgIDY1IGzDoCA2NSB0deG7lWkgdHLhu58gbMOqbi4NCg0KVsOtIGThu6UgdMOqbiBj4buZdCB0aOG7qSA1IGzDoCAibmV3X3NwX20wMTQiIMSR4bqhaSBkaeG7h24gY2hvIG5o4buvbmcgYuG7h25oIG5ow6JuIGPDsyBr4bq/dCBxdeG6oyBjaHXhuqluIMSRb8OhbiBjw7Mgdmkga2h14bqpbiBsYW8gbGFvIGTGsMahbmcgdMOtbmgsIGdp4bubaSB0w61uaCBuYW0gdsOgIHRodeG7mWMgbmjDs20gdHXhu5VpIHThu6sgMCDEkeG6v24gMTQgdHXhu5VpLg0KDQpgYGB7cn0NCmRhdGEoIndobyIpDQpgYGANCg0KYGBge3IsZWNobz1GQUxTRX0NCmhlYWQod2hvKQ0KYGBgDQoNClRhIHRo4buxYyBoaeG7h24gY2h1eeG7g24gZOG7ryBsaeG7h3Ugc2FuZyBk4bqhbmcgbG9uZyBi4bqxbmcgaMOgbSBgcGl2b3RfbG9uZ2VyKClgIG5oxrAgxJHDoyDEkcaw4bujYyBnaeG7m2kgdGhp4buHdSDhu58gcGjhuqduIHRyxrDhu5tjLCBjw6FjIGPhu5l0IGNodXnhu4NuIMSR4buVaSDEkcaw4bujYyBjaOG7jW4gYuG6sW5nIGBzdGFydHNfd2l0aGAgYuG6r3QgxJHhuqd1IHbhu5tpIGvDvSB04buxICJuZXciLiBUw6puIGJp4bq/biBjaOG7qWEgY8OhYyBj4buZdCBzYXUga2hpIGNodXnhu4NuIHNhbmcgZOG6oW5nIGxvbmcgbMOgICptZXRob2QqIHbDoCBnacOhIHRy4buLIHTGsMahbmcg4bupbmcgxJHGsOG7o2MgY2jhu6lhIHRyb25nIGPhu5l0ICp2YWx1ZXMqLiBTYXUgxJHDsyBjaMO6bmcgdGEgY8OzIHRo4buDIGTDuW5nIGjDoG0gYGRyb3BfbmEoKWAgxJHhu4MgbG/huqFpIGLhu48gxJFpIGPDoWMgZ2nDoSB0cuG7iyBOQS4NCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCiNDaHV54buDbiBk4buvIGxp4buHdSBzYW5nIGThuqFuZyBkw6BpIA0KbG9uZ2VyIDwtIHBpdm90X2xvbmdlcihkYXRhID0gd2hvLGNvbHMgPSBzdGFydHNfd2l0aCgibmV3IiksIG5hbWVzX3RvID0gIm1ldGhvZCIsIHZhbHVlc190byA9ICJ2YWx1ZXMiKQ0KbG9uZ2VyIDwtIGRyb3BfbmEobG9uZ2VyKQ0KYGBgDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0NCmhlYWQobG9uZ2VyKQ0KYGBgDQoNCkNow7puZyB0YSB0aOG6pXkgcuG6sW5nIHRyb25nIGPhu5l0ICoqbWV0aG9kKiogY2jhu6lhIGPDoWMgdGjDtG5nIHRpbiB24buBIGThu68gbGnhu4d1IGto4bqjbyBzw6F0IGLhu4duaCBsYW8gZMaw4bubaSBk4bqhbmcgY2h14buXaSBraMOhIHBo4bupYyB04bqhcCwgY2jDrW5oIHbDrCB0aOG6vyBjaMO6bmcgdGEgY+G6p24ga+G6v3QgaOG7o3AgdGjDqm0gaMOgbSBgZ3N1YmAgxJHhu4MgY8OzIHRo4buDIGxv4bqhaSBi4buPIGPFqW5nIG5oxrAgbMOgIHRow6ptIHbDoG8gbeG7mXQgc+G7kSBjaHXhu5dpIGPhuqduIHRoaeG6v3QuIEjDoG0gYG11dGF0ZSgpYCBz4bq9IGdpw7pwIGPhuq1wIG5o4bqtcCBjw6FjIGdpw6EgdHLhu4sgduG7q2EgxJHGsOG7o2MgdGhheSDEkeG7lWkg4bufIGPhu5l0IG1ldGhvZCB0cm9uZyB0csaw4budbmcgaOG7o3AgbsOgeSBjaMO6bmcgdMO0aSB04bqhbyBj4buZdCBt4bubaSB0csO5bmcgduG7m2kgdMOqbiBj4buZdCBjxakuDQoNCi0gICBMb+G6oWkgYuG7jyBjaHXhu5dpICJuZXdcXyIgdHJvbmcgY+G7mXQgbWV0aG9kIGLhurFuZyBjw6FjIHRoYXkgdGjhur8gbsOzIGLhurFuZyAiIiwgdHV5IG5oacOqbiBt4buZdCBz4buRIGNodeG7l2kgY2jhu4kgeHXhuqV0IGhp4buHbiJuZXciIGNo4bupIGtow7RuZyBwaOG6o2kgbMOgICJuZXdcXyIgY2hvIG7Dqm4gY2jDum5nIHRhIGPhuqduIGtoYWkgYsOhbyBjaG8gaMOgbSBgZ3N1YigpYCBjw6FjIGNodeG7l2kgY+G6p24gdGhheSB0aOG6vyBsw6AgIm5ld1xfPyIuDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0Usd2FybmluZyA9RkFMU0V9DQpsb25nZXIgPC0gbG9uZ2VyICU+JSBtdXRhdGUobWV0aG9kID0gZ3N1YigibmV3Xz8iLCIiLG1ldGhvZCkpDQpgYGANCg0KYGBge3IsbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQ0KaGVhZChsb25nZXIpDQpgYGANCg0KLSAgIFRp4bq/cCB0aGVvLCBjaMO6bmcgdGEgdGjDqm0gdsOgbyBrw70gdOG7sSAiXF8iIHNhdSBrw70gImYiIGhv4bq3YyAibSIgxJHhu4MgY8OzIHRo4buDIHBow6JuIGPDoWNoIGdp4bubaSB0w61uaCB2w6AgbmjDs20gdHXhu5VpDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0Usd2FybmluZyA9RkFMU0V9DQpsb25nZXIgPC0gbG9uZ2VyICU+JSBtdXRhdGUobWV0aG9kID0gZ3N1YigiKGZ8bSkoXFxkKykiLCJcXDFfXFwyIixtZXRob2QpKQ0KYGBgDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0NCmhlYWQobG9uZ2VyKQ0KYGBgDQoNCi0gICBUaOG7sWMgaGnhu4duIHTDoWMgY+G7mXQgKm1ldGhvZCogdGjDoG5oIGJhIGPhu5l0ICptdCwgZ2VuZGVyLCBhZ2UqIGLhurFuZyBow6BtIGBzZXBhcmF0ZSgpYA0KDQpgYGB7cixtZXNzYWdlPUZBTFNFLHdhcm5pbmcgPUZBTFNFfQ0KbG9uZ2VyIDwtIGxvbmdlciAlPiUgc2VwYXJhdGUoY29sID0gbWV0aG9kLGludG8gPSBjKCJtdCIsImdlbmRlciIsImFnZSIpLCBzZXAgPSAiXyIpDQpgYGANCg0KYGBge3IsbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQ0KaGVhZChsb25nZXIpDQpgYGANCg0KLSAgIENodXnhu4NuIMSR4buVaSBjw6FjIGdpw6EgdHLhu4sgdmnhur90IHThuq90IHRyb25nIGPhu5l0ICphZ2UqIHbDoCAqZ2VuZGVyKiB24buBIG5ow7NtIHR14buVaSwgZ2nhu5tpIHTDrW5oIGPhu6UgdGjhu4MuDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0Usd2FybmluZyA9RkFMU0V9DQpsb25nZXIgPC0gbXV0YXRlKGxvbmdlciwgYWdlID0gY2FzZV93aGVuKA0KIGFnZSA9PSAiMDE0IiB+ICIwLTE0IHllYXJzIiwNCiAgICBhZ2UgPT0gIjE1MjQiIH4gIjE1LTI0IHllYXJzIiwNCiAgICBhZ2UgPT0gIjI1MzQiIH4gIjI1LTM0IHllYXJzIiwNCiAgICBhZ2UgPT0gIjM1NDQiIH4gIjM1LTQ0IHllYXJzIiwNCiAgICBhZ2UgPT0gIjQ1NTQiIH4gIjQ1LTU0IHllYXJzIiwNCiAgICBhZ2UgPT0gIjU1NjQiIH4gIjU1LTY0IHllYXJzIiwNCiAgICBhZ2UgPT0gIjY1IiB+ICI2NSB5ZWFycyBvciBvbGRlciIsDQopKQ0KDQpsb25nZXIgPC0gbG9uZ2VyICU+JSAgbXV0YXRlKGdlbmRlciA9IGNhc2Vfd2hlbigNCiAgZ2VuZGVyID09ICJtIiB+ICJtYWxlIiwNCiAgZ2VuZGVyID09ICJmIiB+ICJmZW1hbGUiDQopKQ0KYGBgDQoNClF1YSBuaGnhu4F1IHRoYW8gdMOhYyB44butIGzDvSB2w6AgYmnhur9uIMSR4buVaSB04burIGThu68gbGnhu4d1ICoqd2hvKiogYmFuIMSR4bqndSBjaMO6bmcgdGEgxJHDoyBjw7MgxJHGsOG7o2MgYuG7mSBk4buvIGxp4buHdSBt4bubaSBn4buNbiBnw6BuZyBoxqFuIHLhuqV0IG5oaeG7gXUuIFZp4buHYyBsw6BtIHPhuqFjaCBk4buvIGxp4buHdSBjaMawYSBob8OgbiBjaOG7iW5oIHLhuqV0IHF1YW4gdHLhu41uZyB0cm9uZyBxdcOhIHRyw6xuaCBwaMOibiB0w61jaCwgbsOzIGdpw7pwIGNow7puZyB0YSBk4buFIGTDoG5nIHRy4buxYyBxdWFuIGjDs2EgYuG6sW5nIGPDoWMgaMOsbmgg4bqjbmgsIMSR4buTIHRo4buLIGPFqW5nIG5oxrAgbMOgIHTDrW5oIHRvw6FuIGPDoWMgc+G7kSBsaeG7h3UgdGjhu5FuZyBrw6ouDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0Usd2FybmluZyA9RkFMU0UsZWNobz1GQUxTRX0NCmRhdGF0YWJsZShsb25nZXIpDQpgYGANCg0KYGBge3IsbWVzc2FnZT1GQUxTRX0NCg0KbG9uZ2VyICU+JSBncm91cF9ieShnZW5kZXIseWVhcikgJT4lIHN1bW1hcmlzZShjYXNlPSBzdW0odmFsdWVzKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9eWVhciwgeSA9IGNhc2UgLCBjb2xvcj1nZW5kZXIgKSkrDQogIGdlb21fbGluZSgpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJyZWQiKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIlThu5RORyBT4buQIENBIELhu4ZOSCBUSEVPIEdJ4buaSSBUw41OSCIgICkNCmBgYA0KDQotICAgROG7sWEgdsOgbyBiaeG7g3UgxJHhu5MgxJHGsOG7nW5nIOG7nyB0csOqbiwgdOG7lW5nIHRyxrDhu51uZyBo4bujcCBt4bqvYyBi4buHbmggbGFvIHF1YSBjw6FjIG7Eg20g4bufIGhhaSBnaeG7m2kgdMOtbmggY8OzIHh1IGjGsOG7m25nIHTEg25nIGzDqm4gdOG7qyBuaOG7r25nIG7Eg20gMTk5NS4gWHUgaMaw4bubbmcgdMSDbmcgY8OzIHThu7EgdMawxqFuZyDEkeG7k25nIHbhu5tpIG5oYXUgZ2nhu69hIGhhaSBuaMOzbSBnaeG7m2kgdMOtbmggdHV5IG5oacOqbiDhu58gbmFtIGdp4bubaSBz4buxIGdpYSB0xINuZyB04buVbmcgc+G7kSBjYSBt4bqvYyBi4buHbmggbmhp4buBdSBoxqFuIOG7nyBu4buvIGdp4bubaS4gQ+G7pSB0aOG7gywgbsSDbSAyMDEwIHThu5VuZyBjw6FjIHRyxrDhu51uZyBo4bujcCBt4bqvYyBi4buHbmggbGFvIOG7nyBuYW0gZ2nhu5tpIGzDoCAyLDUgdHJp4buHdSBuZ8aw4budaSBjw7JuIOG7nyBu4buvIGdp4bubaSBjaOG7iSBjw7Mga2hv4bqjbmcgMSw1IHRyaeG7h3UgbmfGsOG7nWkuDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQojIHTDrW5oIHThu5VuZyBz4buRIG5nxrDhu51pIGLhu4duaCB0aGVvIGdp4bubaSB0w61uaCB2w6AgcGjGsMahbmcgcGjDoXAgY2h14bqpbiDEkW/DoW4gKG10KQ0KIGRmMSA8LSBsb25nZXIgJT4lIGdyb3VwX2J5KGdlbmRlcixtdCkgJT4lIHN1bW1hcmlzZShzdW09IHN1bSh2YWx1ZXMpKQ0KYGBgDQoNCmBgYHtyLGVjaG89RkFMU0V9DQpwcmludChkZjEpDQpgYGANCg0KLSAgIFTDrW5oIHThu5VuZyBz4buRIGNhIG3huq9jIGLhu4duaCB0aGVvIGdp4bubaSB0w61uaCB2w6AgcGjGsMahbmcgcGjDoXAgY2h14bqpbiDEkW/DoW4gYuG6sW5nIGjDoG0gYGdyb3VwX2J5KClgIHbDoCBgc3VtbWFyaXNlKClgLCBzYXUgxJHDsyB24bq9IMSR4buTIHRo4buLIGPhu5l0IMSRw7RpIMSR4buDIMSRw6FuaCBnacOhIGvhur90IHF14bqjLg0KDQpgYGB7cixtZXNzYWdlPUZBTFNFfQ0KIyDEkOG7kyB0aOG7iyANCiAgZ2dwbG90KCBkZjEsYWVzKHggPSBtdCwgeSA9IHN1bSwgZmlsbCA9IGdlbmRlcikpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnModGl0bGUgPSAiVOG7lW5nIHPhu5EgY2EgdGhlbyBwaMawxqFuZyBwaMOhcCB2w6AgZ2nhu5tpIHTDrW5oIiwNCiAgICAgICB4ID0gIlBoxrDGoW5nIHBow6FwIiwNCiAgICAgICB5ID0gIlPhu5EgbMaw4bujbmciLA0KICAgICAgIGZpbGwgPSAiR2nhu5tpIHTDrW5oIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQotICAgxJDhu5MgdGjhu4sgYsOqbiB0csOqbiBjaG8gY2jDum5nIHRhIHRo4bqleSBz4buRIG5nxrDhu51pIMSRxrDhu6NjIGNodeG6qW4gxJFvw6FuIGzDoCBzcCAoY8OzIHZpIGtodeG6qW4gbGFvKSBjw7Mgc+G7kSBsxrDhu6NuZyBjYW8gbmjhuqV0IHRyb25nIDQgbmjDs20gY+G7pSB0aOG7gyBjw7MgMjA1NDI0NzIgbmFtIHbDoCAxMTI5MjI3OSBu4buvIHRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LiBDaHXhuqluIMSRb8OhbiBsw6AgYuG7h25oIGxhbyBuZ2/DoGkgcGjhu5VpIChlcCkgY8OzIHPhu5EgbMaw4bujbmcgdGjhuqVwIG5o4bqldCwgdHJvbmcgxJHDsyDhu58gbuG7ryBnaeG7m2kgY8OzIDk0MTA0OSBuZ8aw4budaSB2w6AgbmFtIGdp4bubaSBjw7MgMTA0MzI2NSBuZ8aw4budaSB0aHXhu5ljIGNodeG6qW4gxJFvw6FuIG7DoHkuDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0V9DQogICAgICAgIA0KbG9uZ2VyICU+JSBncm91cF9ieShhZ2UpJT4lICBzdW1tYXJpc2UodG90YWw9c3VtKHZhbHVlcykpICU+JSANCiAgbXV0YXRlKHAgPSB0b3RhbC9zdW0odG90YWwpKSAlPiUNCiAgZ2dwbG90KGFlcyh4PSIiLCB5PSBwLCBmaWxsID0gYWdlKSkrDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLHdpZHRoID0gMSkrDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MyIpICsNCiAgY29vcmRfcG9sYXIoInkiLHN0YXJ0ID0gMCkrDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzY2FsZXM6OnBlcmNlbnQocCkpLHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCBzaXplID0gMykgKw0KICB0aGVtZV92b2lkKCkgKw0KICBsYWJzKHRpdGxlPSAiVMOsbmggdHLhuqFuZyBi4buHbmggbGFvIOG7nyBjw6FjIG5ow7NtIHR14buVaSIpDQoNCmBgYA0KDQotICAgTmjDs20gdOG7qyAyNSDEkeG6v24gMzQgdHXhu5VpIGPDsyB04bu3IGzhu4cgbeG6r2MgYuG7h25oIGzhu5tuIG5o4bqldCB0cm9uZyB04bqldCBj4bqjIG5ow7NtIHR14buVaSAoa2hv4bqjbmcgMjIuMiUpLCDhu58gbmjDs20gdOG7qyA0NSDEkeG6v24gNTQgdHXhu5VpIGPFqW5nIMSR4bqhdCB04bu3IGzhu4cga2jDoSBjYW8gbMOgIDIwLjIlLiBOZ8aw4bujYyBs4bqhaSB0aMOsIG5ow7NtIDAtMTQgdHXhu5VpIGNoaeG6v20gdOG7tyBs4buHIG3huq9jIGLhu4duaCBsYW8gdGjhuqVwIG5o4bqldCBjaOG7iSBraG/huqNuZyAzLjklLiBOaMOsbiBjaHVuZyB04bu3IGzhu4cgbeG6r2MgYuG7h25oIGNhbyBz4bq9IHRodeG7mWMgY8OhYyBuaMOzbSB0deG7lWkgdHJ1bmcgbmnDqm4uDQoNCsSQ4buDIGdvbSBjw6FjIGJp4bq/biB0aMOgbmggbeG7mXQgZGFuaCBzw6FjaCBs4buTbmcgbmhhdSB0aGVvIG3hu5dpIHF14buRYyBnaWEgdGEgw6FwIGThu6VuZyBow6BtIGBuZXN0KClgLCBk4buvIGxp4buHdSBt4bubaSBuw6B5IGfhu41uIGfDoG5nIGjGoW4gcuG6pXQgbmhp4buBdSBzbyB24bubaSBiYW4gxJHhuqd1IG7hur91IGNow7puZyB0YSBj4bqnbiBraGFpIHRow6FjIHRow7RuZyB0aW4gY+G7p2EgcXXhu5FjIGdpYSB0aMOsIGNo4buJIGPhuqduIG3hu58gZGFuaCBzw6FjaCBk4buvIGxp4buHdSBj4bunYSBuw7MgbcOgIGtow7RuZyBj4bqnbiBwaOG6o2kgbmjDrG4gdG/DoG4gYuG7mSB0aMO0bmcgdGluIG5oxrAgYmFuIMSR4bqndS4NCg0KYGBge3J9DQpuZXN0ZWRfZGF0YSA8LSBuZXN0KGxvbmdlciwgLmJ5ID0gY291bnRyeSwgLmtleSA9ICJ5ZWFyIikNCmBgYA0KDQpgYGB7cixlY2hvPUZBTFNFfQ0KcHJpbnQobmVzdGVkX2RhdGEpDQpgYGANCg0KSMOgbSBgZmlsdGVyKClgIHRyb25nIHRyxrDhu51uZyBo4bujcCBiw6puIGTGsOG7m2kgxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgbOG7jWMgVmnhu4d0IE5hbSByYSBraOG7j2kgYuG7mSBk4buvIGxp4buHdSB0csOqbiB2w6Agc2F1IMSRw7MgdGEgaGnhu4NuIHRo4buLIHRow7RuZyB0aW4gduG7gSBjw6FjIHRyxrDhu51uZyBo4bujcCBt4bqvYyBi4buHbmggbGFvIGPhu6dhIG7DsyBuaMawIGLDqm4gZMaw4bubaSDEkcOieS4NCg0KYGBge3J9DQpuZXN0ZWRfZGF0YSR5ZWFyIDwtIGxhcHBseShuZXN0ZWRfZGF0YSR5ZWFyLCBhcy5kYXRhLmZyYW1lKQ0KVk4gPC0gIG5lc3RlZF9kYXRhICU+JSBmaWx0ZXIoY291bnRyeT09ICJWaWV0IE5hbSIpDQpgYGANCg0KYGBge3IsZWNobz1GQUxTRX0NCnByaW50KFZOKQ0KcHJpbnQoVk4keWVhcikNCmBgYA0KDQpHaeG6o2kgbsOpbiBk4buvIGxp4buHdSDhu58gZOG6oW5nIG5lc3RlZCB0YSBj4bqnbiBz4butIGThu6VuZyBow6BtIGB1bm5lc3QoKWAgZOG7ryBsaeG7h3UgxJHGsOG7o2MgdHLhuqMgduG7gSBz4bq9IGJhbyBn4buTbSBjw6FjIHRow7RuZyB0aW4gbmjGsCBk4buvIGxp4buHdSBiYW4gxJHhuqd1Lg0KDQpgYGB7cn0NCiMgU+G7rSBk4bulbmcgaMOgbSB1bm5lc3QoKQ0KdW5uZXN0X2RhdGEgPC0gdW5uZXN0KG5lc3RlZF9kYXRhLGNvbHMgPSB5ZWFyKQ0KYGBgDQoNCmBgYHtyLGVjaG89RkFMU0V9DQpwcmludCh1bm5lc3RfZGF0YSkNCmBgYA0KDQojIENIxq/GoE5HIDQ6IEvhur5UIExV4bqsTg0KDQojIyBL4bq/dCBsdeG6rW4NCg0KQsOgaSB0aeG7g3UgbHXhuq1uIGPhu6dhIGNow7puZyB0w7RpIMSRw6MgdHLDrG5oIGLDoHkgY8OhYyBjaOG7qWMgbsSDbmcgcXVhbiB0cuG7jW5nIGPhu6dhIGfDs2kgVGlkeXIgdHJvbmcgbmfDtG4gbmfhu68gbOG6rXAgdHLDrG5oIFIsIG7DsyBjaMOtbmggbMOgIGPDtG5nIGPhu6UgbeG6oW5oIG3hur0gZ2nDunAgbeG7jWkgbmfGsOG7nWkgeOG7rSBsw70gbmjhu69uZyBi4buZIGThu68gbGnhu4d1IGNoxrBhIMSRxrDhu6NjIGNodeG6qW4gaMOzYSB24buBIGThuqFuZyBk4buvIGxp4buHdSBz4bqhY2ggdsOgIHNhdSDEkcOzIMSRxrBhIHbDoG8gcGjDom4gdMOtY2ggdsOgIHRy4buxYyBxdWFuIGjDs2EgZOG7ryBsaeG7h3UuIELDqm4gY+G6oW5oIHZp4buHYyBnaeG7m2kgdGhp4buHdSB24buBIGfDs2kgbsOgeSBjaMO6bmcgdMO0aSBjxaluZyDEkcOjIHRo4buxYyBoaeG7h24gY8OhYyB0aGFvIHTDoWMgaMaw4bubbmcgZOG6q24gY2hpIHRp4bq/dCBk4buxYSB0csOqbiBk4buvIGxp4buHdSBt4bqrdSDEkeG7gyBsw6BtIG7hu5VpIGLhuq10IHPhu7EgaGnhu4d1IHF14bqjIGPhu6dhIGfDs2kgVGlkeXIgdHJvbmcgdmnhu4djIGzDoG0gc+G6oWNoIGThu68gbGnhu4d1LiBOaOG7r25nIGThu68gbGnhu4d1IHRow7QgYmFuIMSR4bqndSB0aMaw4budbmcgY8OzIGPhuqV1IHRyw7pjIHBo4bupYyB04bqhcCwgbmhp4buBdSBiaeG6v24ga+G6v3QgaOG7o3AgduG7m2kgbmhhdSBi4bqxbmcgY8OhYyBrw70gdOG7sSBwaMOibiBjw6FjaCBob+G6t2MgdGjhuq1tIGNow60gbOG7k25nIGdow6lwIHbhu5tpIG5oYXUgdGjDoG5oIGPDoWMgZGFuaCBzw6FjaC4gVsOsIHbhuq15LCBjaMO6bmcgdMO0aSDEkcOjIHRo4buxYyBoaeG7h24gY8OhYyBow6BtIHjhu60gbMO9IGThu68gbGnhu4d1IGLhu4sgdGhp4bq/dSwgYmnhur9uIMSR4buVaSBj4bqldSB0csO6YywgdMOhY2ggZ2jDqXAgdsOgIGzhu5NuZyBnaMOpcCBkYW5oIHPDoWNoIHNhbyBjaG8gcGjDuSBo4bujcCB04burbmcgZOG7ryBsaeG7h3UuDQoNCkfDs2kgVGlkeXIgY8OzIHRo4buDIGvhur90IGjhu6NwIHbhu5tpIG3hu5l0IHPhu5EgZ8OzaSBraMOhYyBjaOG6s25nIGjhuqFuIG5oxrAgbMOgIGRwbHlyLCBnZ3Bsb3QyLCBzdHJpbmdyIMSR4buDIHThu5FpIMawdSB2w6AgdGnhur90IGtp4buHbSBuaGnhu4F1IHRo4budaSBnaWFuLCB0dXkgbmhpw6puIGNow7puZyB0YSBjxaluZyBj4bqnbiBuZ2hpw6puIGPhu6l1IHLhuqV0IG5oaeG7gXUgxJHhu4MgY8OzIHRo4buDIGvhur90IGjhu6NwIHbhu5tpIGPDoWMgaMOgbSB0cm9uZyBnw7NpIFRpZHlyLiBOaMOsbiBjaHVuZyBuaOG7r25nIGjDoG0gdHJvbmcgZ8OzaSB0aWR5ciBjw7MgdMOtbmgg4bupbmcgZOG7pW5nIHLhuqV0IGNhbyB0cm9uZyBuaGnhu4F1IGzEqW5oIHbhu7FjIG5oxrBuZyBz4butIGThu6VuZyB0aMOsIGtow6EgxJHGoW4gZ2nhuqNuIGNo4buJIGPhuqduIGtoYWkgYsOhbyBt4buZdCB2w6BpIMSR4buRaSBz4buRLiBDaOG6s25nIGjhuqFuIGjDoG0gYHBpdm90X2xvbmdlcmAgYmnhur9uIMSR4buVaSBk4buvIGxp4buHdSBy4buZbmcgc2FuZyBk4bqhbmcgZMOgaSBnacO6cCB0YSB0cuG7sWMgaMOzYSBk4buvIGxp4buHdSB04buRdCBoxqFuIHRyxrDhu5tjLCBow6BtIGBzZXBhcmF0ZWAgY8OzIGNo4bupYyBuxINuZyB0w6FjaCB0aMOgbmggY8OhYyBj4buZdCBk4buxYSB2w6BvIGPDoWMga8O9IHThu7EgcGjDom4gY8OhY2ggbmfGsOG7o2MgbOG6oWkgdGjDrCBgdW5pdGVgIGdpw7pwIGvhur90IGjhu6NwIGPDoWMgY+G7mXQgbOG6oWkgduG7m2kgbmhhdSB2w6AgbeG7mXQgc+G7kSBow6BtIHjhu60gbMO9IGThu68gbGnhu4d1IGtow6FjLg0KDQpOZ2/DoGkgcmEsIG5nw7RuIG5n4buvIFIgc+G6vSBwaMOhdCB0cmnhu4NuIGfDs2kgbsOgeSB0aGVvIHRo4budaSBnaWFuIGNow61uaCB2w6wgduG6rXkgbmjhu69uZyBuaMaw4bujYyDEkWnhu4NtIGPhu6dhIG7DsyBz4bq9IMSRxrDhu6NjIGPhuqNpIHRoaeG7h24gYuG7n2kgY2jDrW5oIG5o4buvbmcgbmfGsOG7nWkgZMO5bmcsIG3hu5l0IHPhu5EgY2jhu6ljIG7Eg25nIG3hu5tpIGPDsyB0aOG7gyDEkcaw4bujYyB0aMOqbSB2w6BvIGtoaeG6v24gY2hvIFRpZHlyIHRy4bufIG7Dqm4gbGluaCBob+G6oXQgdsOgIMSRYSBk4bqhbmcgaMahbi4gVHJvbmcgcXXDoSB0csOsbmggdGjhu7FjIGjDoG5oIGPDoWMgaMOgbSBu4bq/dSBn4bq3cCBwaOG6o2kgbmjhu69uZyB24bqlbiDEkeG7gSBraMOzIGtoxINuIHRow6wgY+G7mW5nIMSR4buTbmcgUiBjw7MgY8OhYyBiw6BpIGjGsOG7m25nIGThuqtuIGdpw7pwIHRhIGdp4bqjaSBxdXnhur90IG7Dsy4NCg0KVMOzbSBs4bqhaSwgZ8OzaSB0aWR5ciBsw6AgY8O0bmcgY+G7pSBnacO6cCBjaG8gY2jDum5nIHRhIGJp4bq/biDEkeG7lWkgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3UsIHTDoWNoLCBnaMOpcCB2w6AgeOG7rSBsw70gZOG7ryBsaeG7h3UgYuG7iyB0aGnhur91IG3hu5l0IGPDoWNoIMSRxqFuIGdp4bqjbiBuaMawbmcgbsOzIGzhuqFpIGdpw7pwIGdpYWkgxJFv4bqhbiB44butIGzDvSBk4buvIGxp4buHdSDEkeG6p3UgdsOgbyBj4bunYSBt4buNaSBuZ8aw4budaSBz4bq9IHRp4bq/dCBraeG7h20gbmhp4buBdSB0aOG7nWkgZ2lhbiB2w6AgxJHhuqF0IGvhur90IHF14bqjIGNhbyBoxqFuLiBIxqFuIHRo4bq/LCBnw7NpIG7DoHkgY8OybiBr4bq/dCBo4bujcCB24bubaSBo4buHIHNpbmggdGjDoWkgVGlkeXZlcnNlIHbDoCBuaGnhu4F1IHBhY2thZ2VzIGtow6FjIG5o4bqxbSDEkcOhcCDhu6luZyBjw6FjIG5odSBj4bqndSBraMOhYyBuaGF1IGPhu6dhIG5nxrDhu51pIHBow6JuIHTDrWNoLiBC4bufaSB2w6wgbmjhu69uZyBjaOG7qWMgbsSDbmcgbuG7lWkgYuG6rXQgxJHDsyBtw6AgZ8OzaSB0aWR5ciDEkcaw4bujYyDDoXAgZOG7pW5nIHRyb25nIG5oaeG7gXUgbMSpbmggduG7sWMgdMOgaSBjaMOtbmgsIGLhuqNvIGhp4buDbSwgeSBo4buNYy4NCg0KIyMgSOG6oW4gY2jhur8gdsOgIHBoxrDGoW5nIGjGsOG7m25nIHRp4bq/cCB0aGVvIGPhu6dhIMSR4buBIHTDoGkNCg0KVHJvbmcgdGjhu51pIGdpYW4gbmdoacOqbiBj4bupdSDEkeG7gSB0w6BpIHbhu4EgZ8OzaSB0aWR5ciBjaMO6bmcgdMO0aSDEkcOjIGfhurdwIG3hu5l0IHPhu5Ega2jDsyBraMSDbiB0cm9uZyB2aeG7h2MgdMOsbSBraeG6v20gbmd14buTbiB0w6BpIGxp4buHdSB0aGFtIGto4bqjbyB2w6wgY+G6p24gcGjhuqNpIGPDsyBt4buZdCBsxrDhu6NuZyBs4bubbiBraeG6v24gdGjhu6ljIGPFqW5nIG5oxrAgaGnhu4N1IHLDtSBt4buZdCBz4buRIGtow6FpIG5p4buHbSDEkeG7gyBob8OgbiB0aMOgbmggbsOzLiBN4buZdCBz4buRIGjDoG0gY+G6p24gcGjhuqNpIHhlbSBxdWEgbmhp4buBdSB0w6BpIGxp4buHdSBoxrDhu5tuZyBk4bqrbiwgdsOtIGThu6UgY+G7pSB0aOG7gyB0aMOsIGNow7puZyB0YSBt4bubaSBjw7MgdGjhu4MgaGnhu4N1IG7DsyB2w6AgdHLDrG5oIGLDoHkgY2jhu6ljIG7Eg25nIGPhu6dhIGjDoG0gxJHDsy4gSMahbiB0aOG6vywgY2jDum5nIHTDtGkgY8WpbmcgbeG6pXQgbmhp4buBdSB0aOG7nWkgZ2lhbiDEkeG7gyBjaOG7jW4gcmEgbmjhu69uZyBk4buvIGxp4buHdSB0aMOtY2ggaOG7o3AgY2hvIHZp4buHYyDDoXAgZOG7pW5nIGPDoWMgaMOgbSBtaW5oIGjhu41hLiBWaeG7h2MgaGnhu4N1IGPhuqV1IHRyw7pjIGPhu6dhIG3hu5l0IGLhu5kgZOG7ryBsaeG7h3UgcGjhu6ljIHThuqFwIHPhur0gZ2nDunAgdGEgZMO5bmcgbmjhu69uZyBow6BtIHBow7kgaOG7o3AgxJHhu4MgYmnhur9uIMSR4buVaSBuw7MgduG7gSBk4buvIGxp4buHdSBz4bqhY2guDQoNCkNow7puZyB0w7RpIG114buRbiDEkeG7gSB4deG6pXQgbeG7mXQgc+G7kSBwaMawxqFuZyBoxrDhu5tuZyBjaG8gbmjhu69uZyBuZ2hpw6puIGPhu6l1IHRp4bq/cCB0aGVvIOG7nyDEkeG7gSB0w6BpIG7DoHkuIEfDs2kgbsOgeSBjw7MgdGjhu4Mgc+G7rSBk4bulbmcgxJHhu4MgcGjDom4gdMOtY2ggbmjhu69uZyBi4buZIGThu68gbGnhu4d1IG5oaeG7gXUgYmnhur9uIHbDoCBuaGnhu4F1IGTDsm5nIGThu68gbGnhu4d1IGjGoW4uIENow7puZyB0YSBuw6puIGvhur90IGjhu6NwIHbhu5tpIGPDoWMgZ8OzaSBjw7Mga2jhuqMgbsSDbmcgdHLhu7FjIHF1YW4gaMOzYSBk4buvIGxp4buHdSB24burYSB44butIGzDrSBi4bqxbmcgY8OhYyDEkeG7kyB0aOG7iyBoYXkgdGjhuq1tIGNow60gbMOgIMSR4buTIHRo4buLIDNEIMSR4buDIHRyw6xuaCBiw6B5IGvhur90IHF14bqjLiBOZ2/DoGkgcmEgbmjhu69uZyBow6BtIHjhu60gbMO9IGNodeG7l2kgdHJvbmcgZ8OzaSBzdHJpbmdyIHPhur0gZ2nDunAgbmfGsOG7nWkgc+G7rSBk4bulbmcgcGjDoXQgaHV5IMSRxrDhu6NjIGPDoWMgY2jhu6ljIG7Eg25nIGPhu6dhIGfDs2kgdGlkeXIga2hpIHPhu60gZOG7pW5nIMSR4buTbmcgdGjhu51pIGNow7puZyB24bubaSBuaGF1DQo=