版权声明:本套课程材料开源,使用和分享必须遵守「创作共用许可协议 CC BY-NC-SA」(来源引用-非商业用途使用-以相同方式共享)。


Chap02:函数对象

往期要点回顾

本章要点目录

## 本章所需R包
library(bruceR)

bruceR (v2026.1)
Broadly Useful Convenient and Efficient R functions

Packages also loaded:
✔ dplyr         ✔ data.table
✔ tidyr         ✔ emmeans
✔ stringr       ✔ lmerTest
✔ forcats       ✔ effectsize
✔ ggplot2       ✔ performance
✔ cowplot       ✔ interactions

Main functions of `bruceR`:
cc()            Describe()  TTEST()
add()           Freq()      MANOVA()
.mean()         Corr()      EMMEANS()
set.wd()        Alpha()     PROCESS()
import()        EFA()       model_summary()
print_table()   CFA()       lavaan_summary()

For full functionality, please install all dependencies:
install.packages("bruceR", dep=TRUE)

Online documentation:
https://psychbruce.github.io/bruceR

To use this package in publications, please cite:
Bao, H. W. S. (2021). bruceR: Broadly useful convenient and efficient R functions (Version 2026.1) [Computer software]. https://doi.org/10.32614/CRAN.package.bruceR

R对象类型与相互转换

【知识点】R对象与函数

“万物皆对象,万事皆函数。” —— John Chambers(R语言创始人之一)

  • “Everything that exists in R is an object.”
    (所用的一切都是对象)
    • 向量(vector)⭐️
      • 数值向量(numeric vector)
      • 字符向量(character vector)
      • 逻辑向量(logical vector)
    • 矩阵(matrix)
    • 数组(array)
    • 列表(list)⭐️
      • 混合存储多种类型的对象和数据
    • 数据框(data frame)⭐️
      • R里90%的分析都是围绕data.frame(包括data.table)展开的
      • 相当于Excel表格在R里的样子(每一列是一个变量,每一行是一个观测值)
  • “Everything that happens in R is the result of a function call.”
    (所做的一切都是函数)

向量(vector)

  • 单维、单类型数据

(1)数值向量

【实践1】数值向量

c():生成任何类型向量(合并一组同类型的数据)⭐️
  • “c”表示“combine”
1
[1] 1
1:5
[1] 1 2 3 4 5
c(1, 2, 3, 4, 5)
[1] 1 2 3 4 5
c(1:5, 10, 15)
[1]  1  2  3  4  5 10 15
seq():生成数值序列
seq(1, 5, 0.5)
[1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0
seq(from=1, to=5, by=0.5)
[1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0
rep():重复向量元素
rep(1:2, 3)
[1] 1 2 1 2 1 2
rep(1:2, each=3)
[1] 1 1 1 2 2 2

(2)字符向量

【实践2】字符向量

c(1:5, 10.5, "next")  # 如果混着放,统统变成字符型!
[1] "1"    "2"    "3"    "4"    "5"    "10.5" "next"
"Psychology"  # 一个字符串,本质上是一个长度为1的字符向量
[1] "Psychology"
"Psychology"[1]  # 向量的第1个元素
[1] "Psychology"
"Psychology"[0]  # 向量的第0个元素(没有)
character(0)
"Psychology"[2]  # 向量的第2个元素(缺失)
[1] NA
nchar():计算字符串的字符个数
length():计算对象内的元素个数
nchar("Psychology")  # 字符个数为10
[1] 10
a = c("Psychology", "ECNU", "Shanghai", "China")
a
[1] "Psychology" "ECNU"       "Shanghai"   "China"     
length(a)
[1] 4
nchar(a)  # 向量化计算
[1] 10  4  8  5
class():获取R对象类型(可能是单个类型或多种类型的叠加)
str():显示R对象内部结构(常用于探索数据结构)⭐️
class(a)
[1] "character"
str(a)  # structure:显示R对象的结构
 chr [1:4] "Psychology" "ECNU" "Shanghai" "China"
cc()(来自bruceR包):比c()更方便的字符向量设定
  • 自动根据分隔符号(英文逗号、换行符等)拆解字符串
  • 为什么要设计这个函数?
    • 只因我觉得原生态的c()不太方便快捷
## cc() 用法:必须是英文逗号或换行符
cc("心理学, 社会学, 教育学, 管理学, 计算机, 人工智能")
[1] "心理学"   "社会学"   "教育学"   "管理学"   "计算机"   "人工智能"
cc("
心理学
社会学
教育学
管理学
计算机
人工智能
")
[1] "心理学"   "社会学"   "教育学"   "管理学"   "计算机"   "人工智能"

【知识点】因子型向量

因子型(factor)变量是社会科学研究中的常用变量类型,本质是对分类变量(categorical variable)的虚拟编码(dummy coding),以方便统计模型的处理。R语言中,原始的分类变量一般都需要转换为因子型变量!

as.factor():将任意类型向量转换为因子型向量⭐️
  • 因子(factor)本质上是带有“类别/分组信息”的向量(将向量中的不重复元素排序后作为类别选项)
  • 因子水平(levels)是所有可能的类别(当涉及类别间的对比时,默认以第一类为参照组)
factor():比as.factor()更完整的因子型向量设定⭐️
  • levels:定义因子水平顺序
  • labels:定义因子水平标签
## 数值向量 ==> 因子向量
a = c(2, 0, 0, 0, 6, 2)
a
[1] 2 0 0 0 6 2
unique(a)
[1] 2 0 6
a = as.factor(a)
a
[1] 2 0 0 0 6 2
Levels: 0 2 6
levels(a)  # 因子水平:所有可能的类别
[1] "0" "2" "6"
## 字符向量 ==> 因子向量
a = c("Psychology", "ECNU", "Shanghai", "China")
as.factor(a)
[1] Psychology ECNU       Shanghai   China     
Levels: China ECNU Psychology Shanghai
factor(a, levels=c("China", "Shanghai", "ECNU", "Psychology"))
[1] Psychology ECNU       Shanghai   China     
Levels: China Shanghai ECNU Psychology
factor(
  a,
  levels = c("China", "Shanghai", "ECNU", "Psychology"),
  labels = c("CN", "SH", "ECNU", "Psy")
)
[1] Psy  ECNU SH   CN  
Levels: CN SH ECNU Psy

(3)逻辑向量

【实践3】逻辑向量

c(TRUE, TRUE, FALSE, TRUE, FALSE, FALSE)
[1]  TRUE  TRUE FALSE  TRUE FALSE FALSE
1:5 > 2
[1] FALSE FALSE  TRUE  TRUE  TRUE
%in%:向量化判断前一个对象的每个元素是否在后一个对象中
c(0, 5, 10, 15) %in% 1:10
[1] FALSE  TRUE  TRUE FALSE
ifelse():根据条件语句,向量化逻辑判断
ifelse(1:10 >= 5, "Yes", "No")  # ifelse(test, yes, no)
 [1] "No"  "No"  "No"  "No"  "Yes" "Yes" "Yes" "Yes" "Yes" "Yes"

【知识点】条件判断运算符与对象类型判断函数

## 条件判断运算符
a == b
a != b
a > b
a < b
a >= b
a <= b
a %in% b

## 对象类型判断函数
is.na(x)
is.null(x)
is.numeric(x)
is.character(x)
is.factor(x)
# 还有非常多其他 is.xxx() 系列函数!

向量相互转换

【实践4】逻辑向量—数值向量—字符向量的相互转换

  • as.logical()0转换为FALSE,非0转换为TRUE
  • as.character():转换为字符向量
  • as.numeric():转换为数值向量(无法转换的记为NA缺失值)
as.logical(0:5)
[1] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
as.character(0:5)
[1] "0" "1" "2" "3" "4" "5"
as.numeric(c("-1.5", "0", "1.5"))
[1] -1.5  0.0  1.5
as.numeric(c("1.2", "-.12", "1.2.3"))  # NA表示缺失值
Warning: 强制改变过程中产生了NA
[1]  1.20 -0.12    NA

【知识点】管道操作符

%>%:管道操作符⭐️(tidyverse系列包的通用函数)
  • 默认将【左侧结果】传给【右侧函数】的【第1个参数】!
    • 如果想传给右侧函数的其他参数,需要用点.占位!
  • 快捷键:Ctrl + Shift + M(注意检查其他软件的快捷键冲突)
  • 如果提示没有"%>%"这个函数,请library(tidyverse)library(bruceR)
a = c("Psychology", "ECNU", "Shanghai", "China")
as.factor(a)  # 不使用管道操作符
[1] Psychology ECNU       Shanghai   China     
Levels: China ECNU Psychology Shanghai
a %>% as.factor()  # 使用管道操作符,默认传给as.factor()第1个参数
[1] Psychology ECNU       Shanghai   China     
Levels: China ECNU Psychology Shanghai
a %>% as.factor() %>% as.numeric()  # 默认传给这些函数的第1个参数
[1] 3 2 4 1
a %>% as.factor() %>% as.numeric() %>% c(666)  # 默认传给c()第1个参数
[1]   3   2   4   1 666
a %>% as.factor() %>% as.numeric() %>% c(., 666)  # .占位第1个参数
[1]   3   2   4   1 666
a %>% as.factor() %>% as.numeric() %>% c(666, .)  # .占位第2个参数
[1] 666   3   2   4   1
a %>% as.factor() %>% as.numeric() %>% c(666, 888, .)  # .占位第3个参数
[1] 666 888   3   2   4   1
a %>% as.factor() %>% as.numeric() %>% c(666, ., 888)  # .占位第2个参数
[1] 666   3   2   4   1 888

知识点小结:LHS %>% RHS这种写法,可以将LHS(Left-Hand Side)的输出结果作为RHS(Right-Hand Side)第1个参数的输入值,从而实现流程化的管道操作效果,避免繁琐、可读性差的“函数套娃”!

## 可读性差的“函数套娃”
c(666, as.numeric(as.factor(as.character(c("Psychology", "ECNU")))))
[1] 666   2   1

向量元素操作

【实践5】向量元素命名与提取

names():对象元素名称或命名
  • 直接使用:返回对象元素名称
  • 赋值使用:赋予对象元素名称(将会改变当前对象)
LETTERS  # 26个英文字母
 [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
a = 1:5
names(a)  # 直接用法(刚刚出生,还没名字)
NULL
names(a) = LETTERS[1:5]  # 赋值用法,a已改变
a
A B C D E 
1 2 3 4 5 
names(a)  # 现在上好户口,有名字了!
[1] "A" "B" "C" "D" "E"
x[...][]操作符取对象元素内容
  • x[逻辑/数值向量]:取对应位置元素(若为负数,则删除对应元素)
  • x[字符向量]:取对应名称元素
a["E"]
E 
5 
a[c("A", "C", "E")]
A C E 
1 3 5 
a[-1]  # 删除元素,但不改变a
B C D E 
2 3 4 5 
a[-(2:4)]  # 删除元素,但不改变a
A E 
1 5 
rev():向量反向排列
sort():按照数值大小或字母序重新排列
unique():取向量中的所有独特元素(去重复值)
table():向量元素频次统计
x = c(2, 0, 0, 0, 6, 2)
rev(x)
[1] 2 6 0 0 0 2
sort(x)
[1] 0 0 0 2 2 6
unique(x)
[1] 2 0 6
x %>% unique() %>% sort() %>% rev()
[1] 6 2 0
table(x)
x
0 2 6 
3 2 1 
x %in% 1:5
[1]  TRUE FALSE FALSE FALSE FALSE  TRUE
x[x %in% 1:5]
[1] 2 2
x[x %in% 1:5] = NA
x
[1] NA  0  0  0  6 NA

【实践6】向量代数运算

a = 1:5
a + 1    # 1:5 + 1 【思考:a + 1:2 的结果?】
[1] 2 3 4 5 6
a * 2    # 1:5 * 2
[1]  2  4  6  8 10
a^2      # (1:5)^2
[1]  1  4  9 16 25
a * 5:1  # 对应位置相乘,长度必须相等
[1] 5 8 9 8 5
a %% 2   # 取余数
[1] 1 0 1 0 1
sum()mean()min()max():向量求和、平均值、最小值、最大值
  • na.rm参数:忽视缺失值NA
sum(1:100)  # 求和
[1] 5050
mean(1:100)  # 求平均值
[1] 50.5
min(1:100)  # 最小值
[1] 1
max(1:100)  # 最大值
[1] 100
x = c(1, NA, 3, NA, 5)
sum(x)
[1] NA
sum(x, na.rm=TRUE)
[1] 9
mean(x)
[1] NA
mean(x, na.rm=TRUE)
[1] 3
min(x)
[1] NA
min(x, na.rm=TRUE)
[1] 1
max(x)
[1] NA
max(x, na.rm=TRUE)
[1] 5
abs()log()sqrt()等:各种常用的数学运算
abs(-1)
[1] 1
log(2.718281828)  # ln 自然对数转换
[1] 1
sqrt(81)
[1] 9
sqrt(sqrt(81))
[1] 3
81 %>% sqrt() %>% sqrt()
[1] 3
abs(log(sqrt(pi)))
[1] 0.5724
pi %>% sqrt() %>% log() %>% abs()  # 管道操作符
[1] 0.5724

【实践7】向量元素拼接

paste()paste0():把向量元素拼接在一起
  • sep参数:多个输入之间的黏合字符
  • collaspe参数:向量不同元素之间的黏合字符
paste(1, 2, 3, 4, 5)  # paste() 拼接带空格
[1] "1 2 3 4 5"
paste0(1, 2, 3, 4, 5)  # paste0() 拼接不带空格
[1] "12345"
paste(1, 2, 3, 4, 5, sep="-")  # 多个参数输入之间拼接
[1] "1-2-3-4-5"
paste(1:5, collapse="-")  # 单个向量的不同元素之间拼接
[1] "1-2-3-4-5"
paste(1:10, collapse="+")  # 打印计算公式
[1] "1+2+3+4+5+6+7+8+9+10"
cat(paste(1:10, collapse="+"), "=", sum(1:10))
1+2+3+4+5+6+7+8+9+10 = 55

列表(list)

  • 单维、多类型数据

【实践8】列表构建与操作

list():建立一个列表对象,可存储任意类型、任意结构的对象
  • $:根据元素名称,取列表中的元素内容(Tab键弹出所有元素名称)
  • [[...]]:取列表中对应位置的元素内容(不同于[...]
输入后按Tab键弹出所有元素名称
输入后按Tab键弹出所有元素名称
l = list(Year=2000:2015, Month=1:12, Day=1:31, Letter=LETTERS)
l
$Year
 [1] 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
[16] 2015

$Month
 [1]  1  2  3  4  5  6  7  8  9 10 11 12

$Day
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
[26] 26 27 28 29 30 31

$Letter
 [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
names(l)
[1] "Year"   "Month"  "Day"    "Letter"
length(l)
[1] 4
l$Year
 [1] 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
[16] 2015
l[2]    # 取第2个子集,返回list子集
$Month
 [1]  1  2  3  4  5  6  7  8  9 10 11 12
l[[2]]  # 取第2个元素,返回元素本身,相当于 l$Month
 [1]  1  2  3  4  5  6  7  8  9 10 11 12
unlist():解除列表结构,还原为向量
unlist(l)  # 解除列表结构,强行统一对象类型(数值 -> 字符)
   Year1    Year2    Year3    Year4    Year5    Year6    Year7    Year8 
  "2000"   "2001"   "2002"   "2003"   "2004"   "2005"   "2006"   "2007" 
   Year9   Year10   Year11   Year12   Year13   Year14   Year15   Year16 
  "2008"   "2009"   "2010"   "2011"   "2012"   "2013"   "2014"   "2015" 
  Month1   Month2   Month3   Month4   Month5   Month6   Month7   Month8 
     "1"      "2"      "3"      "4"      "5"      "6"      "7"      "8" 
  Month9  Month10  Month11  Month12     Day1     Day2     Day3     Day4 
     "9"     "10"     "11"     "12"      "1"      "2"      "3"      "4" 
    Day5     Day6     Day7     Day8     Day9    Day10    Day11    Day12 
     "5"      "6"      "7"      "8"      "9"     "10"     "11"     "12" 
   Day13    Day14    Day15    Day16    Day17    Day18    Day19    Day20 
    "13"     "14"     "15"     "16"     "17"     "18"     "19"     "20" 
   Day21    Day22    Day23    Day24    Day25    Day26    Day27    Day28 
    "21"     "22"     "23"     "24"     "25"     "26"     "27"     "28" 
   Day29    Day30    Day31  Letter1  Letter2  Letter3  Letter4  Letter5 
    "29"     "30"     "31"      "A"      "B"      "C"      "D"      "E" 
 Letter6  Letter7  Letter8  Letter9 Letter10 Letter11 Letter12 Letter13 
     "F"      "G"      "H"      "I"      "J"      "K"      "L"      "M" 
Letter14 Letter15 Letter16 Letter17 Letter18 Letter19 Letter20 Letter21 
     "N"      "O"      "P"      "Q"      "R"      "S"      "T"      "U" 
Letter22 Letter23 Letter24 Letter25 Letter26 
     "V"      "W"      "X"      "Y"      "Z" 
lapply():批量应用函数,返回为列表
## lapply(向量或列表, 函数)
lapply(l, length)  # 每个元素批量应用length()函数
$Year
[1] 16

$Month
[1] 12

$Day
[1] 31

$Letter
[1] 26
lapply(l, mean)    # 每个元素批量应用mean()函数
Warning in mean.default(X[[i]], ...): 参数不是数值也不是逻辑值:返回NA
$Year
[1] 2008

$Month
[1] 6.5

$Day
[1] 16

$Letter
[1] NA
a = 1:5
a^2
[1]  1  4  9 16 25
lapply(a, function(x) x^2)  # x是形参(形式参数)
[[1]]
[1] 1

[[2]]
[1] 4

[[3]]
[1] 9

[[4]]
[1] 16

[[5]]
[1] 25
lapply(a, function(x) x^2) %>% unlist()
[1]  1  4  9 16 25

R函数使用与参数设置

【知识点】R函数体的结构

function(...):函数接收输入参数,内部操作后,返回输出结果
  • { }:大括号内定义所有形式参数(形参)的操作过程
  • 返回结果可用两种方式
    • return(...):显式返回
    • invisible(...):隐式返回
func = function(param1, param2, ...) {
  ## 函数内部操作
  results = param1 + param2
  cat(param1, "+", param2, "=", results, "\n")
  
  ## 函数返回结果
  return(results)
  # 也可以隐式返回:
  # invisible(results)
}
func(16, 9)
16 + 9 = 25 
[1] 25

常用R函数使用

【实践9】文件夹里有什么?

## 请自己运行
library(bruceR)
set.wd()  # 设置工作路径为当前打开文件的路径

list.files()          # 列出当前路径的所有文件/文件夹
list.files("../")     # 列出上一级路径的所有文件/文件夹
list.files("../../")  # 列出上两级路径的所有文件/文件夹

【实践10】今天晚上吃什么?

## 请自己运行
choice = c("河西食堂", "河东食堂", "环球港", "点外卖")
sample(choice, size=1)  # 随机抽样

# 设置随机种子,使结果可重复
set.seed(123)  # 随机种子可以是任意整数,没有特定含义
sample(choice, size=1)

【实践11】正态分布随机数的平均值和标准差?

set.seed(123)  # 设置随机种子,使结果可重复
x = rnorm(30)  # 生成30个随机数(正态分布)

mean(x)  # 求平均值
[1] -0.0471
sd(x)    # 求标准差
[1] 0.981
hist(x)  # 画直方图

x > mean(x) + sd(x)         # 返回TRUE/FALSE向量
 [1] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE
[13] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE  TRUE
x[x > mean(x) + sd(x)]      # 返回(取出)符合条件的数值
[1] 1.559 1.715 1.224 1.787 1.254
which(x > mean(x) + sd(x))  # 返回符合条件数值所在位置
[1]  3  6 11 16 30
set.seed(123)  # 设置随机种子,使结果可重复
x = rnorm(1000)  # 生成1000个随机数(正态分布)

mean(x)  # 求平均值
[1] 0.01613
sd(x)    # 求标准差
[1] 0.9917
hist(x)  # 画直方图

【实践12】“Hello World”的几种打印方法?

  • cli是命令行交互的专业R包,系统性提供了各种输出文本设定函数
print("Hello World!")
[1] "Hello World!"
cat("Hello World!")
Hello World!
cat("Hello", "World!")
Hello World!
cli::cli_text("Hello World!")
cli::cli_h1("Hello World!")
cli::cli_h2("Hello World!")
cli::cli_h3("Hello World!")
cli::cli_alert("Hello World!")
cli::cli_alert_success("Hello World!")
cli::cli_alert_info("Hello World!")
cli::cli_alert_warning("Hello World!")
cli::cli_alert_danger("Hello World!")

R逻辑控制语句

if判断语句

if (condition) {
  # Do something
} else if {
  # Do something
} else {
  # Do sth. else
}
x = 3
if (x %in% 1:5) {
  cat("Yes")
} else {
  cat("No")
}
Yes

while循环语句

while (condition) {
  # Do something
}
x = 1
while (x < 5) {
  cat(x, "is smaller than 5\n")
  x = x + 1
}
1 is smaller than 5
2 is smaller than 5
3 is smaller than 5
4 is smaller than 5

for循环语句

for (var in seq) {
  # Do something
}
for (x in 1:5) {
  y = x * 2
  print(y)
}
[1] 2
[1] 4
[1] 6
[1] 8
[1] 10

【作业3】编程解决抛硬币问题

问题情境:一枚硬币,连续抛了N次都是正面朝上,再抛一次反面朝上的概率是多少?

  • 比如,一枚硬币,连续抛了3次都是正面朝上,再抛一次反面朝上的概率是多少?
  • 连续10次呢?连续1000次呢?连续1亿次呢?……
  • 思路提示:利用假设检验的思想,判断这枚硬币是不是普通硬币(H0:硬币是普通的)

作业要求:

  • 编写一段R程序,计算并判断至少连续多少次正面朝上,可以认定硬币不再是普通硬币(拒绝零假设)
  • 尽可能用R Markdown完成

平台提交:

  • R代码和运行结果截图

返回课程主页

© 包寒吴霜

LS0tDQp0aXRsZTogIuOAilLor63oqIDjgIvnrKwy56ug77ya5Ye95pWw5a+56LGhIg0Kc3VidGl0bGU6IDxhIGhyZWY9Imh0dHBzOi8vcHN5Y2hicnVjZS5naXRodWIuaW8vUkNvdXJzZS8iPui/lOWbnuivvueoi+S4u+mhtTwvYT4NCmF1dGhvcjogIuaOiOivvuaVmeW4iO+8muWMheWvkuWQtOmcnCINCiMgZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogZmFsc2UNCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGFuY2hvcl9zZWN0aW9uczogdHJ1ZQ0KICAgIGhpZ2hsaWdodDogcHlnbWVudHMNCiAgICBjc3M6IFJtZENTUy5jc3MNCi0tLQ0KDQpgYGB7PWh0bWx9DQo8cCBzdHlsZT0iZm9udC1zaXplOiAxMnB4Ij7niYjmnYPlo7DmmI7vvJrmnKzlpZfor77nqIvmnZDmlpnlvIDmupDvvIzkvb/nlKjlkozliIbkuqvlv4XpobvpgbXlrojjgIzliJvkvZzlhbHnlKjorrjlj6/ljY/orq4gQ0MgQlktTkMtU0HjgI3vvIjmnaXmupDlvJXnlKgt6Z2e5ZWG5Lia55So6YCU5L2/55SoLeS7peebuOWQjOaWueW8j+WFseS6q++8ieOAgjxpbWcgc3JjPSJpbWcvQ0MtQlktTkMtU0EuanBnIiB3aWR0aD0iMTIwcHgiIGhlaWdodD0iNDJweCIgc3R5bGU9ImZsb2F0OiByaWdodCIgLz48L3A+DQpgYGANCg0KYGBge3IgQ29uZmlnLCBpbmNsdWRlPUZBTFNFfQ0Kb3B0aW9ucygNCiAga25pdHIua2FibGUuTkEgPSAiIiwNCiAgZGlnaXRzID0gNA0KKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBjb21tZW50ID0gIiIsDQogIGZpZy53aWR0aCA9IDYsDQogIGZpZy5oZWlnaHQgPSA0LA0KICBkcGkgPSAzMDANCikNCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBDaGFwMDLvvJrlh73mlbDlr7nosaENCg0KIyMjIyDlvoDmnJ/opoHngrnlm57pob4NCg0KLSAgIFtDaGFwMDEgXCMgUuWMheWuieijheS4jueuoeeQhl0oaHR0cHM6Ly9wc3ljaGJydWNlLmdpdGh1Yi5pby9SQ291cnNlL0NoYXAwMSNyJUU1JThDJTg1JUU1JUFFJTg5JUU4JUEzJTg1JUU0JUI4JThFJUU3JUFFJUExJUU3JTkwJTg2KXsudXJpfQ0KDQojIyMjIOacrOeroOimgeeCueebruW9lQ0KDQotICAgW+OAkOefpeivhueCueOAkVLlr7nosaHkuI7lh73mlbBdKCPnn6Xor4bngrly5a+56LGh5LiO5Ye95pWwKQ0KLSAgIFvjgJDlrp7ot7Ux44CR5pWw5YC85ZCR6YePXSgj5a6e6Le1MeaVsOWAvOWQkemHjykNCi0gICBb44CQ5a6e6Le1MuOAkeWtl+espuWQkemHj10oI+Wunui3tTLlrZfnrKblkJHph48pDQotICAgW+OAkOefpeivhueCueOAkeWboOWtkOWei+WQkemHj10oI+efpeivhueCueWboOWtkOWei+WQkemHjynvvIjph43ngrnvvIkNCi0gICBb44CQ5a6e6Le1M+OAkemAu+i+keWQkemHj10oI+Wunui3tTPpgLvovpHlkJHph48pDQotICAgW+OAkOefpeivhueCueOAkeadoeS7tuWIpOaWrei/kOeul+espuS4juWvueixoeexu+Wei+WIpOaWreWHveaVsF0oI+efpeivhueCueadoeS7tuWIpOaWrei/kOeul+espuS4juWvueixoeexu+Wei+WIpOaWreWHveaVsCkNCi0gICBb44CQ5a6e6Le1NOOAkemAu+i+keWQkemHj+KAlOaVsOWAvOWQkemHj+KAlOWtl+espuWQkemHj+eahOebuOS6kui9rOaNol0oI+Wunui3tTTpgLvovpHlkJHph4/mlbDlgLzlkJHph4/lrZfnrKblkJHph4/nmoTnm7jkupLovazmjaIpDQotICAgW+OAkOefpeivhueCueOAkeeuoemBk+aTjeS9nOespl0oI+efpeivhueCueeuoemBk+aTjeS9nOespinvvIjph43ngrnvvIkNCi0gICBb44CQ5a6e6Le1NeOAkeWQkemHj+WFg+e0oOWRveWQjeS4juaPkOWPll0oI+Wunui3tTXlkJHph4/lhYPntKDlkb3lkI3kuI7mj5Dlj5YpDQotICAgW+OAkOWunui3tTbjgJHlkJHph4/ku6PmlbDov5DnrpddKCPlrp7ot7U25ZCR6YeP5Luj5pWw6L+Q566XKQ0KLSAgIFvjgJDlrp7ot7U344CR5ZCR6YeP5YWD57Sg5ou85o6lXSgj5a6e6Le1N+WQkemHj+WFg+e0oOaLvOaOpSnvvIjph43ngrnvvIkNCi0gICBb44CQ5a6e6Le1OOOAkeWIl+ihqOaehOW7uuS4juaTjeS9nF0oI+Wunui3tTjliJfooajmnoTlu7rkuI7mk43kvZwp77yI6YeN54K577yJDQotICAgW+OAkOefpeivhueCueOAkVLlh73mlbDkvZPnmoTnu5PmnoRdKCPnn6Xor4bngrly5Ye95pWw5L2T55qE57uT5p6EKe+8iOmHjeeCue+8iQ0KLSAgIFvjgJDlrp7ot7U544CR5paH5Lu25aS56YeM5pyJ5LuA5LmI77yfXSgj5a6e6Le1OeaWh+S7tuWkuemHjOacieS7gOS5iCkNCi0gICBb44CQ5a6e6Le1MTDjgJHku4rlpKnmmZrkuIrlkIPku4DkuYjvvJ9dKCPlrp7ot7UxMOS7iuWkqeaZmuS4iuWQg+S7gOS5iCkNCi0gICBb44CQ5a6e6Le1MTHjgJHmraPmgIHliIbluIPpmo/mnLrmlbDnmoTlubPlnYflgLzlkozmoIflh4blt67vvJ9dKCPlrp7ot7UxMeato+aAgeWIhuW4g+maj+acuuaVsOeahOW5s+Wdh+WAvOWSjOagh+WHhuW3rikNCi0gICBb44CQ5a6e6Le1MTLjgJHigJxIZWxsbyBXb3JsZOKAneeahOWHoOenjeaJk+WNsOaWueazle+8n10oI+Wunui3tTEyaGVsbG8td29ybGTnmoTlh6Dnp43miZPljbDmlrnms5UpDQoNCmBgYHtyfQ0KIyMg5pys56ug5omA6ZyAUuWMhQ0KbGlicmFyeShicnVjZVIpDQpgYGANCg0KIyBS5a+56LGh57G75Z6L5LiO55u45LqS6L2s5o2iDQoNCiFbXShpbWFnZXMvY2xpcGJvYXJkLTQyMjcxODkxODcucG5nKQ0KDQojIyMjIOOAkOefpeivhueCueOAkVLlr7nosaHkuI7lh73mlbAgeyPnn6Xor4bngrly5a+56LGh5LiO5Ye95pWwfQ0KDQo+IOKAnOS4h+eJqeeahuWvueixoe+8jOS4h+S6i+eahuWHveaVsOOAguKAnSDigJTigJQgSm9obiBDaGFtYmVyc++8iFLor63oqIDliJvlp4vkurrkuYvkuIDvvIkNCg0KLSAgIOKAnEV2ZXJ5dGhpbmcgdGhhdCBleGlzdHMgaW4gUiBpcyBhbiBvYmplY3Qu4oCdXA0KICAgIO+8iOaJgOeUqOeahOS4gOWIh+mDveaYr+Wvueixoe+8iQ0KICAgIC0gICDlkJHph4/vvIh2ZWN0b3LvvInirZDvuI8NCiAgICAgICAgLSAgIOaVsOWAvOWQkemHj++8iG51bWVyaWMgdmVjdG9y77yJDQogICAgICAgIC0gICDlrZfnrKblkJHph4/vvIhjaGFyYWN0ZXIgdmVjdG9y77yJDQogICAgICAgIC0gICDpgLvovpHlkJHph4/vvIhsb2dpY2FsIHZlY3Rvcu+8iQ0KICAgIC0gICDnn6npmLXvvIhtYXRyaXjvvIkNCiAgICAtICAg5pWw57uE77yIYXJyYXnvvIkNCiAgICAtICAg5YiX6KGo77yIbGlzdO+8ieKtkO+4jw0KICAgICAgICAtICAg5re35ZCI5a2Y5YKo5aSa56eN57G75Z6L55qE5a+56LGh5ZKM5pWw5o2uDQogICAgLSAgIOaVsOaNruahhu+8iGRhdGEgZnJhbWXvvInirZDvuI8NCiAgICAgICAgLSAgIFLph4w5MCXnmoTliIbmnpDpg73mmK/lm7Tnu5VgZGF0YS5mcmFtZWDvvIjljIXmi6xgZGF0YS50YWJsZWDvvInlsZXlvIDnmoQNCiAgICAgICAgLSAgIOebuOW9k+S6jkV4Y2Vs6KGo5qC85ZyoUumHjOeahOagt+WtkO+8iOavj+S4gOWIl+aYr+S4gOS4quWPmOmHj++8jOavj+S4gOihjOaYr+S4gOS4quingua1i+WAvO+8iQ0KLSAgIOKAnEV2ZXJ5dGhpbmcgdGhhdCBoYXBwZW5zIGluIFIgaXMgdGhlIHJlc3VsdCBvZiBhIGZ1bmN0aW9uIGNhbGwu4oCdXA0KICAgIO+8iOaJgOWBmueahOS4gOWIh+mDveaYr+WHveaVsO+8iQ0KDQohW10oaW1hZ2VzL2NsaXBib2FyZC0yNDgyNTQzOTY2LnBuZykNCg0KIyMg5ZCR6YeP77yIdmVjdG9y77yJDQoNCi0gICDljZXnu7TjgIHljZXnsbvlnovmlbDmja4NCg0KIyMjIO+8iDHvvInmlbDlgLzlkJHph48NCg0KIyMjIyDjgJDlrp7ot7Ux44CR5pWw5YC85ZCR6YePIHsj5a6e6Le1MeaVsOWAvOWQkemHj30NCg0KIyMjIyMgYGMoKWDvvJrnlJ/miJDku7vkvZXnsbvlnovlkJHph4/vvIjlkIjlubbkuIDnu4TlkIznsbvlnovnmoTmlbDmja7vvInirZDvuI8NCg0KLSAgIOKAnGPigJ3ooajnpLrigJxjb21iaW5l4oCdDQoNCmBgYHtyfQ0KMQ0KMTo1DQpjKDEsIDIsIDMsIDQsIDUpDQpjKDE6NSwgMTAsIDE1KQ0KYGBgDQoNCiMjIyMjIGBzZXEoKWDvvJrnlJ/miJDmlbDlgLzluo/liJcNCg0KYGBge3J9DQpzZXEoMSwgNSwgMC41KQ0Kc2VxKGZyb209MSwgdG89NSwgYnk9MC41KQ0KYGBgDQoNCiMjIyMjIGByZXAoKWDvvJrph43lpI3lkJHph4/lhYPntKANCg0KYGBge3J9DQpyZXAoMToyLCAzKQ0KcmVwKDE6MiwgZWFjaD0zKQ0KYGBgDQoNCiMjIyDvvIgy77yJ5a2X56ym5ZCR6YePDQoNCiMjIyMg44CQ5a6e6Le1MuOAkeWtl+espuWQkemHjyB7I+Wunui3tTLlrZfnrKblkJHph499DQoNCmBgYHtyfQ0KYygxOjUsIDEwLjUsICJuZXh0IikgICMg5aaC5p6c5re3552A5pS+77yM57uf57uf5Y+Y5oiQ5a2X56ym5Z6L77yBDQoNCiJQc3ljaG9sb2d5IiAgIyDkuIDkuKrlrZfnrKbkuLLvvIzmnKzotKjkuIrmmK/kuIDkuKrplb/luqbkuLox55qE5a2X56ym5ZCR6YePDQoiUHN5Y2hvbG9neSJbMV0gICMg5ZCR6YeP55qE56ysMeS4quWFg+e0oA0KIlBzeWNob2xvZ3kiWzBdICAjIOWQkemHj+eahOesrDDkuKrlhYPntKDvvIjmsqHmnInvvIkNCiJQc3ljaG9sb2d5IlsyXSAgIyDlkJHph4/nmoTnrKwy5Liq5YWD57Sg77yI57y65aSx77yJDQpgYGANCg0KIyMjIyMgYG5jaGFyKClg77ya6K6h566X5a2X56ym5Liy55qE5a2X56ym5Liq5pWwDQoNCiMjIyMjIGBsZW5ndGgoKWDvvJrorqHnrpflr7nosaHlhoXnmoTlhYPntKDkuKrmlbANCg0KYGBge3J9DQpuY2hhcigiUHN5Y2hvbG9neSIpICAjIOWtl+espuS4quaVsOS4ujEwDQphID0gYygiUHN5Y2hvbG9neSIsICJFQ05VIiwgIlNoYW5naGFpIiwgIkNoaW5hIikNCmENCmxlbmd0aChhKQ0KbmNoYXIoYSkgICMg5ZCR6YeP5YyW6K6h566XDQpgYGANCg0KIyMjIyMgYGNsYXNzKClg77ya6I635Y+WUuWvueixoeexu+Wei++8iOWPr+iDveaYr+WNleS4quexu+Wei+aIluWkmuenjeexu+Wei+eahOWPoOWKoO+8iQ0KDQojIyMjIyBgc3RyKClg77ya5pi+56S6UuWvueixoeWGhemDqOe7k+aehO+8iOW4uOeUqOS6juaOoue0ouaVsOaNrue7k+aehO+8ieKtkO+4jw0KDQpgYGB7cn0NCmNsYXNzKGEpDQpzdHIoYSkgICMgc3RydWN0dXJl77ya5pi+56S6UuWvueixoeeahOe7k+aehA0KYGBgDQoNCiMjIyMjIGBjYygpYO+8iOadpeiHqmBicnVjZVJg5YyF77yJ77ya5q+UYGMoKWDmm7Tmlrnkvr/nmoTlrZfnrKblkJHph4/orr7lrpoNCg0KLSAgIOiHquWKqOagueaNruWIhumalOespuWPt++8iOiLseaWh+mAl+WPt+OAgeaNouihjOespuetie+8ieaLhuino+Wtl+espuS4sg0KLSAgIOS4uuS7gOS5iOimgeiuvuiuoei/meS4quWHveaVsO+8nw0KICAgIC0gICDlj6rlm6DmiJHop4nlvpfljp/nlJ/mgIHnmoRgYygpYOS4jeWkquaWueS+v+W/q+aNtw0KDQpgYGB7cn0NCiMjIGNjKCkg55So5rOV77ya5b+F6aG75piv6Iux5paH6YCX5Y+35oiW5o2i6KGM56ymDQpjYygi5b+D55CG5a2mLCDnpL7kvJrlraYsIOaVmeiCsuWtpiwg566h55CG5a2mLCDorqHnrpfmnLosIOS6uuW3peaZuuiDvSIpDQpjYygiDQrlv4PnkIblraYNCuekvuS8muWtpg0K5pWZ6IKy5a2mDQrnrqHnkIblraYNCuiuoeeul+acug0K5Lq65bel5pm66IO9DQoiKQ0KYGBgDQoNCiMjIyMg44CQ55+l6K+G54K544CR5Zug5a2Q5Z6L5ZCR6YePIHsj55+l6K+G54K55Zug5a2Q5Z6L5ZCR6YePfQ0KDQrlm6DlrZDlnovvvIhmYWN0b3LvvInlj5jph4/mmK/npL7kvJrnp5HlrabnoJTnqbbkuK3nmoTluLjnlKjlj5jph4/nsbvlnovvvIzmnKzotKjmmK/lr7nliIbnsbvlj5jph4/vvIhjYXRlZ29yaWNhbCB2YXJpYWJsZe+8ieeahOiZmuaLn+e8luegge+8iGR1bW15IGNvZGluZ++8ie+8jOS7peaWueS+v+e7n+iuoeaooeWei+eahOWkhOeQhuOAglLor63oqIDkuK3vvIzljp/lp4vnmoTliIbnsbvlj5jph4/kuIDoiKzpg73pnIDopoHovazmjaLkuLrlm6DlrZDlnovlj5jph4/vvIENCg0KIyMjIyMgYGFzLmZhY3RvcigpYO+8muWwhuS7u+aEj+exu+Wei+WQkemHj+i9rOaNouS4uuWboOWtkOWei+WQkemHj+KtkO+4jw0KDQotICAg5Zug5a2Q77yIZmFjdG9y77yJ5pys6LSo5LiK5piv5bim5pyJ4oCc57G75YirL+WIhue7hOS/oeaBr+KAneeahOWQkemHj++8iOWwhuWQkemHj+S4reeahOS4jemHjeWkjeWFg+e0oOaOkuW6j+WQjuS9nOS4uuexu+WIq+mAiemhue+8iQ0KLSAgIOWboOWtkOawtOW5s++8iGxldmVsc++8ieaYr+aJgOacieWPr+iDveeahOexu+WIq++8iOW9k+a2ieWPiuexu+WIq+mXtOeahOWvueavlOaXtu+8jOm7mOiupOS7peesrOS4gOexu+S4uuWPgueFp+e7hO+8iQ0KDQojIyMjIyBgZmFjdG9yKClg77ya5q+UYGFzLmZhY3RvcigpYOabtOWujOaVtOeahOWboOWtkOWei+WQkemHj+iuvuWumuKtkO+4jw0KDQotICAgYGxldmVsc2DvvJrlrprkuYnlm6DlrZDmsLTlubPpobrluo8NCi0gICBgbGFiZWxzYO+8muWumuS5ieWboOWtkOawtOW5s+agh+etvg0KDQpgYGB7cn0NCiMjIOaVsOWAvOWQkemHjyA9PT4g5Zug5a2Q5ZCR6YePDQphID0gYygyLCAwLCAwLCAwLCA2LCAyKQ0KYQ0KdW5pcXVlKGEpDQoNCmEgPSBhcy5mYWN0b3IoYSkNCmENCmxldmVscyhhKSAgIyDlm6DlrZDmsLTlubPvvJrmiYDmnInlj6/og73nmoTnsbvliKsNCg0KIyMg5a2X56ym5ZCR6YePID09PiDlm6DlrZDlkJHph48NCmEgPSBjKCJQc3ljaG9sb2d5IiwgIkVDTlUiLCAiU2hhbmdoYWkiLCAiQ2hpbmEiKQ0KYXMuZmFjdG9yKGEpDQpmYWN0b3IoYSwgbGV2ZWxzPWMoIkNoaW5hIiwgIlNoYW5naGFpIiwgIkVDTlUiLCAiUHN5Y2hvbG9neSIpKQ0KZmFjdG9yKA0KICBhLA0KICBsZXZlbHMgPSBjKCJDaGluYSIsICJTaGFuZ2hhaSIsICJFQ05VIiwgIlBzeWNob2xvZ3kiKSwNCiAgbGFiZWxzID0gYygiQ04iLCAiU0giLCAiRUNOVSIsICJQc3kiKQ0KKQ0KYGBgDQoNCiMjIyDvvIgz77yJ6YC76L6R5ZCR6YePDQoNCiMjIyMg44CQ5a6e6Le1M+OAkemAu+i+keWQkemHjyB7I+Wunui3tTPpgLvovpHlkJHph499DQoNCmBgYHtyfQ0KYyhUUlVFLCBUUlVFLCBGQUxTRSwgVFJVRSwgRkFMU0UsIEZBTFNFKQ0KMTo1ID4gMg0KYGBgDQoNCiMjIyMjIGAlaW4lYO+8muWQkemHj+WMluWIpOaWreWJjeS4gOS4quWvueixoeeahOavj+S4quWFg+e0oOaYr+WQpuWcqOWQjuS4gOS4quWvueixoeS4rQ0KDQpgYGB7cn0NCmMoMCwgNSwgMTAsIDE1KSAlaW4lIDE6MTANCmBgYA0KDQojIyMjIyBgaWZlbHNlKClg77ya5qC55o2u5p2h5Lu26K+t5Y+l77yM5ZCR6YeP5YyW6YC76L6R5Yik5patDQoNCmBgYHtyfQ0KaWZlbHNlKDE6MTAgPj0gNSwgIlllcyIsICJObyIpICAjIGlmZWxzZSh0ZXN0LCB5ZXMsIG5vKQ0KYGBgDQoNCiMjIyMg44CQ55+l6K+G54K544CR5p2h5Lu25Yik5pat6L+Q566X56ym5LiO5a+56LGh57G75Z6L5Yik5pat5Ye95pWwIHsj55+l6K+G54K55p2h5Lu25Yik5pat6L+Q566X56ym5LiO5a+56LGh57G75Z6L5Yik5pat5Ye95pWwfQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiMjIOadoeS7tuWIpOaWrei/kOeul+espg0KYSA9PSBiDQphICE9IGINCmEgPiBiDQphIDwgYg0KYSA+PSBiDQphIDw9IGINCmEgJWluJSBiDQoNCiMjIOWvueixoeexu+Wei+WIpOaWreWHveaVsA0KaXMubmEoeCkNCmlzLm51bGwoeCkNCmlzLm51bWVyaWMoeCkNCmlzLmNoYXJhY3Rlcih4KQ0KaXMuZmFjdG9yKHgpDQojIOi/mOaciemdnuW4uOWkmuWFtuS7liBpcy54eHgoKSDns7vliJflh73mlbDvvIENCmBgYA0KDQojIyMg5ZCR6YeP55u45LqS6L2s5o2iDQoNCiMjIyMg44CQ5a6e6Le1NOOAkemAu+i+keWQkemHj+KAlOaVsOWAvOWQkemHj+KAlOWtl+espuWQkemHj+eahOebuOS6kui9rOaNoiB7I+Wunui3tTTpgLvovpHlkJHph4/mlbDlgLzlkJHph4/lrZfnrKblkJHph4/nmoTnm7jkupLovazmjaJ9DQoNCi0gICBgYXMubG9naWNhbCgpYO+8mmAwYOi9rOaNouS4umBGQUxTRWDvvIzpnZ5gMGDovazmjaLkuLpgVFJVRWANCi0gICBgYXMuY2hhcmFjdGVyKClg77ya6L2s5o2i5Li65a2X56ym5ZCR6YePDQotICAgYGFzLm51bWVyaWMoKWDvvJrovazmjaLkuLrmlbDlgLzlkJHph4/vvIjml6Dms5XovazmjaLnmoTorrDkuLpgTkFg57y65aSx5YC877yJDQoNCmBgYHtyfQ0KYXMubG9naWNhbCgwOjUpDQphcy5jaGFyYWN0ZXIoMDo1KQ0KYXMubnVtZXJpYyhjKCItMS41IiwgIjAiLCAiMS41IikpDQphcy5udW1lcmljKGMoIjEuMiIsICItLjEyIiwgIjEuMi4zIikpICAjIE5B6KGo56S657y65aSx5YC8DQpgYGANCg0KIyMjIyDjgJDnn6Xor4bngrnjgJHnrqHpgZPmk43kvZznrKYgeyPnn6Xor4bngrnnrqHpgZPmk43kvZznrKZ9DQoNCiMjIyMjIGAlPiVg77ya566h6YGT5pON5L2c56ym4q2Q77iP77yIdGlkeXZlcnNl57O75YiX5YyF55qE6YCa55So5Ye95pWw77yJDQoNCi0gICAqKum7mOiupOWwhuOAkOW3puS+p+e7k+aenOOAkeS8oOe7meOAkOWPs+S+p+WHveaVsOOAkeeahOOAkOesrDHkuKrlj4LmlbDjgJHvvIEqKg0KICAgIC0gICAqKuWmguaenOaDs+S8oOe7meWPs+S+p+WHveaVsOeahOWFtuS7luWPguaVsO+8jOmcgOimgeeUqOeCuWAuYOWNoOS9je+8gSoqDQotICAg5b+r5o236ZSu77yaQ3RybCArIFNoaWZ0ICsgTe+8iOazqOaEj+ajgOafpeWFtuS7lui9r+S7tueahOW/q+aNt+mUruWGsueqge+8iQ0KLSAgIOWmguaenOaPkOekumDmsqHmnIkiJT4lIui/meS4quWHveaVsGDvvIzor7dgbGlicmFyeSh0aWR5dmVyc2UpYOaIlmBsaWJyYXJ5KGJydWNlUilgDQoNCmBgYHtyfQ0KYSA9IGMoIlBzeWNob2xvZ3kiLCAiRUNOVSIsICJTaGFuZ2hhaSIsICJDaGluYSIpDQphcy5mYWN0b3IoYSkgICMg5LiN5L2/55So566h6YGT5pON5L2c56ymDQphICU+JSBhcy5mYWN0b3IoKSAgIyDkvb/nlKjnrqHpgZPmk43kvZznrKbvvIzpu5jorqTkvKDnu5lhcy5mYWN0b3IoKeesrDHkuKrlj4LmlbANCmEgJT4lIGFzLmZhY3RvcigpICU+JSBhcy5udW1lcmljKCkgICMg6buY6K6k5Lyg57uZ6L+Z5Lqb5Ye95pWw55qE56ysMeS4quWPguaVsA0KYSAlPiUgYXMuZmFjdG9yKCkgJT4lIGFzLm51bWVyaWMoKSAlPiUgYyg2NjYpICAjIOm7mOiupOS8oOe7mWMoKeesrDHkuKrlj4LmlbANCmEgJT4lIGFzLmZhY3RvcigpICU+JSBhcy5udW1lcmljKCkgJT4lIGMoLiwgNjY2KSAgIyAu5Y2g5L2N56ysMeS4quWPguaVsA0KYSAlPiUgYXMuZmFjdG9yKCkgJT4lIGFzLm51bWVyaWMoKSAlPiUgYyg2NjYsIC4pICAjIC7ljaDkvY3nrKwy5Liq5Y+C5pWwDQphICU+JSBhcy5mYWN0b3IoKSAlPiUgYXMubnVtZXJpYygpICU+JSBjKDY2NiwgODg4LCAuKSAgIyAu5Y2g5L2N56ysM+S4quWPguaVsA0KYSAlPiUgYXMuZmFjdG9yKCkgJT4lIGFzLm51bWVyaWMoKSAlPiUgYyg2NjYsIC4sIDg4OCkgICMgLuWNoOS9jeesrDLkuKrlj4LmlbANCmBgYA0KDQrnn6Xor4bngrnlsI/nu5PvvJpgTEhTICU+JSBSSFNg6L+Z56eN5YaZ5rOV77yM5Y+v5Lul5bCGYExIU2DvvIhMZWZ0LUhhbmQgU2lkZe+8ieeahOi+k+WHuue7k+aenOS9nOS4umBSSFNg77yIUmlnaHQtSGFuZCBTaWRl77yJ56ysMeS4quWPguaVsOeahOi+k+WFpeWAvO+8jOS7juiAjOWunueOsOa1geeoi+WMlueahOeuoemBk+aTjeS9nOaViOaenO+8jOmBv+WFjee5geeQkOOAgeWPr+ivu+aAp+W3rueahOKAnOWHveaVsOWll+Wog+KAne+8gQ0KDQpgYGB7cn0NCiMjIOWPr+ivu+aAp+W3rueahOKAnOWHveaVsOWll+Wog+KAnQ0KYyg2NjYsIGFzLm51bWVyaWMoYXMuZmFjdG9yKGFzLmNoYXJhY3RlcihjKCJQc3ljaG9sb2d5IiwgIkVDTlUiKSkpKSkNCmBgYA0KDQojIyMg5ZCR6YeP5YWD57Sg5pON5L2cDQoNCiMjIyMg44CQ5a6e6Le1NeOAkeWQkemHj+WFg+e0oOWRveWQjeS4juaPkOWPliB7I+Wunui3tTXlkJHph4/lhYPntKDlkb3lkI3kuI7mj5Dlj5Z9DQoNCiMjIyMjIGBuYW1lcygpYO+8muWvueixoeWFg+e0oOWQjeensOaIluWRveWQjQ0KDQotICAg55u05o6l5L2/55So77ya6L+U5Zue5a+56LGh5YWD57Sg5ZCN56ewDQotICAg6LWL5YC85L2/55So77ya6LWL5LqI5a+56LGh5YWD57Sg5ZCN56ew77yI5bCG5Lya5pS55Y+Y5b2T5YmN5a+56LGh77yJDQoNCmBgYHtyfQ0KTEVUVEVSUyAgIyAyNuS4quiLseaWh+Wtl+avjQ0KYSA9IDE6NQ0KbmFtZXMoYSkgICMg55u05o6l55So5rOV77yI5Yia5Yia5Ye655Sf77yM6L+Y5rKh5ZCN5a2X77yJDQoNCm5hbWVzKGEpID0gTEVUVEVSU1sxOjVdICAjIOi1i+WAvOeUqOazle+8jGHlt7LmlLnlj5gNCmENCm5hbWVzKGEpICAjIOeOsOWcqOS4iuWlveaIt+WPo++8jOacieWQjeWtl+S6hu+8gQ0KYGBgDQoNCiMjIyMjIGB4Wy4uLl1g77yaYFtdYOaTjeS9nOespuWPluWvueixoeWFg+e0oOWGheWuuQ0KDQotICAgYHhb6YC76L6RL+aVsOWAvOWQkemHj11g77ya5Y+W5a+55bqU5L2N572u5YWD57Sg77yI6Iul5Li66LSf5pWw77yM5YiZ5Yig6Zmk5a+55bqU5YWD57Sg77yJDQotICAgYHhb5a2X56ym5ZCR6YePXWDvvJrlj5blr7nlupTlkI3np7DlhYPntKANCg0KYGBge3J9DQphWyJFIl0NCmFbYygiQSIsICJDIiwgIkUiKV0NCg0KYVstMV0gICMg5Yig6Zmk5YWD57Sg77yM5L2G5LiN5pS55Y+YYQ0KYVstKDI6NCldICAjIOWIoOmZpOWFg+e0oO+8jOS9huS4jeaUueWPmGENCmBgYA0KDQojIyMjIyBgcmV2KClg77ya5ZCR6YeP5Y+N5ZCR5o6S5YiXDQoNCiMjIyMjIGBzb3J0KClg77ya5oyJ54Wn5pWw5YC85aSn5bCP5oiW5a2X5q+N5bqP6YeN5paw5o6S5YiXDQoNCiMjIyMjIGB1bmlxdWUoKWDvvJrlj5blkJHph4/kuK3nmoTmiYDmnInni6znibnlhYPntKDvvIjljrvph43lpI3lgLzvvIkNCg0KIyMjIyMgYHRhYmxlKClg77ya5ZCR6YeP5YWD57Sg6aKR5qyh57uf6K6hDQoNCmBgYHtyfQ0KeCA9IGMoMiwgMCwgMCwgMCwgNiwgMikNCnJldih4KQ0Kc29ydCh4KQ0KdW5pcXVlKHgpDQp4ICU+JSB1bmlxdWUoKSAlPiUgc29ydCgpICU+JSByZXYoKQ0KdGFibGUoeCkNCg0KeCAlaW4lIDE6NQ0KeFt4ICVpbiUgMTo1XQ0KeFt4ICVpbiUgMTo1XSA9IE5BDQp4DQpgYGANCg0KIyMjIyDjgJDlrp7ot7U244CR5ZCR6YeP5Luj5pWw6L+Q566XIHsj5a6e6Le1NuWQkemHj+S7o+aVsOi/kOeul30NCg0KYGBge3J9DQphID0gMTo1DQphICsgMSAgICAjIDE6NSArIDEg44CQ5oCd6ICD77yaYSArIDE6MiDnmoTnu5PmnpzvvJ/jgJENCmEgKiAyICAgICMgMTo1ICogMg0KYV4yICAgICAgIyAoMTo1KV4yDQphICogNToxICAjIOWvueW6lOS9jee9ruebuOS5mO+8jOmVv+W6puW/hemhu+ebuOetiQ0KYSAlJSAyICAgIyDlj5bkvZnmlbANCmBgYA0KDQojIyMjIyBgc3VtKClg44CBYG1lYW4oKWDjgIFgbWluKClg44CBYG1heCgpYO+8muWQkemHj+axguWSjOOAgeW5s+Wdh+WAvOOAgeacgOWwj+WAvOOAgeacgOWkp+WAvA0KDQotICAgYG5hLnJtYOWPguaVsO+8muW/veinhue8uuWkseWAvGBOQWANCg0KYGBge3J9DQpzdW0oMToxMDApICAjIOaxguWSjA0KbWVhbigxOjEwMCkgICMg5rGC5bmz5Z2H5YC8DQptaW4oMToxMDApICAjIOacgOWwj+WAvA0KbWF4KDE6MTAwKSAgIyDmnIDlpKflgLwNCg0KeCA9IGMoMSwgTkEsIDMsIE5BLCA1KQ0Kc3VtKHgpDQpzdW0oeCwgbmEucm09VFJVRSkNCm1lYW4oeCkNCm1lYW4oeCwgbmEucm09VFJVRSkNCm1pbih4KQ0KbWluKHgsIG5hLnJtPVRSVUUpDQptYXgoeCkNCm1heCh4LCBuYS5ybT1UUlVFKQ0KYGBgDQoNCiMjIyMjIGBhYnMoKWDjgIFgbG9nKClg44CBYHNxcnQoKWDnrYnvvJrlkITnp43luLjnlKjnmoTmlbDlrabov5DnrpcNCg0KYGBge3J9DQphYnMoLTEpDQpsb2coMi43MTgyODE4MjgpICAjIGxuIOiHqueEtuWvueaVsOi9rOaNog0Kc3FydCg4MSkNCnNxcnQoc3FydCg4MSkpDQo4MSAlPiUgc3FydCgpICU+JSBzcXJ0KCkNCg0KYWJzKGxvZyhzcXJ0KHBpKSkpDQpwaSAlPiUgc3FydCgpICU+JSBsb2coKSAlPiUgYWJzKCkgICMg566h6YGT5pON5L2c56ymDQpgYGANCg0KIyMjIyDjgJDlrp7ot7U344CR5ZCR6YeP5YWD57Sg5ou85o6lIHsj5a6e6Le1N+WQkemHj+WFg+e0oOaLvOaOpX0NCg0KIyMjIyMgYHBhc3RlKClg44CBYHBhc3RlMCgpYO+8muaKiuWQkemHj+WFg+e0oOaLvOaOpeWcqOS4gOi1tw0KDQotICAgYHNlcGDlj4LmlbDvvJrlpJrkuKrovpPlhaXkuYvpl7TnmoTpu4/lkIjlrZfnrKYNCi0gICBgY29sbGFzcGVg5Y+C5pWw77ya5ZCR6YeP5LiN5ZCM5YWD57Sg5LmL6Ze055qE6buP5ZCI5a2X56ymDQoNCmBgYHtyfQ0KcGFzdGUoMSwgMiwgMywgNCwgNSkgICMgcGFzdGUoKSDmi7zmjqXluKbnqbrmoLwNCnBhc3RlMCgxLCAyLCAzLCA0LCA1KSAgIyBwYXN0ZTAoKSDmi7zmjqXkuI3luKbnqbrmoLwNCg0KcGFzdGUoMSwgMiwgMywgNCwgNSwgc2VwPSItIikgICMg5aSa5Liq5Y+C5pWw6L6T5YWl5LmL6Ze05ou85o6lDQpwYXN0ZSgxOjUsIGNvbGxhcHNlPSItIikgICMg5Y2V5Liq5ZCR6YeP55qE5LiN5ZCM5YWD57Sg5LmL6Ze05ou85o6lDQpwYXN0ZSgxOjEwLCBjb2xsYXBzZT0iKyIpICAjIOaJk+WNsOiuoeeul+WFrOW8jw0KY2F0KHBhc3RlKDE6MTAsIGNvbGxhcHNlPSIrIiksICI9Iiwgc3VtKDE6MTApKQ0KYGBgDQoNCiFbXShpbWFnZXMvY2xpcGJvYXJkLTM2MjU1ODk1MDcucG5nKQ0KDQojIyDliJfooajvvIhsaXN077yJDQoNCi0gICDljZXnu7TjgIHlpJrnsbvlnovmlbDmja4NCg0KIyMjIyDjgJDlrp7ot7U444CR5YiX6KGo5p6E5bu65LiO5pON5L2cIHsj5a6e6Le1OOWIl+ihqOaehOW7uuS4juaTjeS9nH0NCg0KIyMjIyMgYGxpc3QoKWDvvJrlu7rnq4vkuIDkuKrliJfooajlr7nosaHvvIzlj6/lrZjlgqjku7vmhI/nsbvlnovjgIHku7vmhI/nu5PmnoTnmoTlr7nosaENCg0KLSAgIGAkYO+8muagueaNruWFg+e0oOWQjeensO+8jOWPluWIl+ihqOS4reeahOWFg+e0oOWGheWuue+8iFRhYumUruW8ueWHuuaJgOacieWFg+e0oOWQjeensO+8iQ0KLSAgIGBbWy4uLl1dYO+8muWPluWIl+ihqOS4reWvueW6lOS9jee9rueahOWFg+e0oOWGheWuue+8iOS4jeWQjOS6jmBbLi4uXWDvvIkNCg0KIVvovpPlhaXlkI7mjIlUYWLplK7lvLnlh7rmiYDmnInlhYPntKDlkI3np7BdKGltYWdlcy9jbGlwYm9hcmQtMzEzMTQ4MTMwOC5wbmcpDQoNCmBgYHtyfQ0KbCA9IGxpc3QoWWVhcj0yMDAwOjIwMTUsIE1vbnRoPTE6MTIsIERheT0xOjMxLCBMZXR0ZXI9TEVUVEVSUykNCmwNCm5hbWVzKGwpDQpsZW5ndGgobCkNCmwkWWVhcg0KbFsyXSAgICAjIOWPluesrDLkuKrlrZDpm4bvvIzov5Tlm55saXN05a2Q6ZuGDQpsW1syXV0gICMg5Y+W56ysMuS4quWFg+e0oO+8jOi/lOWbnuWFg+e0oOacrOi6q++8jOebuOW9k+S6jiBsJE1vbnRoDQpgYGANCg0KIyMjIyMgYHVubGlzdCgpYO+8muino+mZpOWIl+ihqOe7k+aehO+8jOi/mOWOn+S4uuWQkemHjw0KDQpgYGB7cn0NCnVubGlzdChsKSAgIyDop6PpmaTliJfooajnu5PmnoTvvIzlvLrooYznu5/kuIDlr7nosaHnsbvlnovvvIjmlbDlgLwgLT4g5a2X56ym77yJDQpgYGANCg0KIyMjIyMgYGxhcHBseSgpYO+8muaJuemHj+W6lOeUqOWHveaVsO+8jOi/lOWbnuS4uuWIl+ihqA0KDQpgYGB7cn0NCiMjIGxhcHBseSjlkJHph4/miJbliJfooagsIOWHveaVsCkNCmxhcHBseShsLCBsZW5ndGgpICAjIOavj+S4quWFg+e0oOaJuemHj+W6lOeUqGxlbmd0aCgp5Ye95pWwDQpsYXBwbHkobCwgbWVhbikgICAgIyDmr4/kuKrlhYPntKDmibnph4/lupTnlKhtZWFuKCnlh73mlbANCg0KYSA9IDE6NQ0KYV4yDQpsYXBwbHkoYSwgZnVuY3Rpb24oeCkgeF4yKSAgIyB45piv5b2i5Y+C77yI5b2i5byP5Y+C5pWw77yJDQpsYXBwbHkoYSwgZnVuY3Rpb24oeCkgeF4yKSAlPiUgdW5saXN0KCkNCmBgYA0KDQojIFLlh73mlbDkvb/nlKjkuI7lj4LmlbDorr7nva4NCg0KIyMjIyDjgJDnn6Xor4bngrnjgJFS5Ye95pWw5L2T55qE57uT5p6EIHsj55+l6K+G54K5cuWHveaVsOS9k+eahOe7k+aehH0NCg0KIyMjIyMgYGZ1bmN0aW9uKC4uLilg77ya5Ye95pWw5o6l5pS26L6T5YWl5Y+C5pWw77yM5YaF6YOo5pON5L2c5ZCO77yM6L+U5Zue6L6T5Ye657uT5p6cDQoNCi0gICBgeyB9YO+8muWkp+aLrOWPt+WGheWumuS5ieaJgOacieW9ouW8j+WPguaVsO+8iOW9ouWPgu+8ieeahOaTjeS9nOi/h+eoiw0KLSAgIOi/lOWbnue7k+aenOWPr+eUqOS4pOenjeaWueW8jw0KICAgIC0gICBgcmV0dXJuKC4uLilg77ya5pi+5byP6L+U5ZueDQogICAgLSAgIGBpbnZpc2libGUoLi4uKWDvvJrpmpDlvI/ov5Tlm54NCg0KYGBge3J9DQpmdW5jID0gZnVuY3Rpb24ocGFyYW0xLCBwYXJhbTIsIC4uLikgew0KICAjIyDlh73mlbDlhoXpg6jmk43kvZwNCiAgcmVzdWx0cyA9IHBhcmFtMSArIHBhcmFtMg0KICBjYXQocGFyYW0xLCAiKyIsIHBhcmFtMiwgIj0iLCByZXN1bHRzLCAiXG4iKQ0KICANCiAgIyMg5Ye95pWw6L+U5Zue57uT5p6cDQogIHJldHVybihyZXN1bHRzKQ0KICAjIOS5n+WPr+S7pemakOW8j+i/lOWbnu+8mg0KICAjIGludmlzaWJsZShyZXN1bHRzKQ0KfQ0KZnVuYygxNiwgOSkNCmBgYA0KDQojIyDluLjnlKhS5Ye95pWw5L2/55SoDQoNCiMjIyMg44CQ5a6e6Le1OeOAkeaWh+S7tuWkuemHjOacieS7gOS5iO+8nyB7I+Wunui3tTnmlofku7blpLnph4zmnInku4DkuYh9DQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KIyMg6K+36Ieq5bex6L+Q6KGMDQpsaWJyYXJ5KGJydWNlUikNCnNldC53ZCgpICAjIOiuvue9ruW3peS9nOi3r+W+hOS4uuW9k+WJjeaJk+W8gOaWh+S7tueahOi3r+W+hA0KDQpsaXN0LmZpbGVzKCkgICAgICAgICAgIyDliJflh7rlvZPliY3ot6/lvoTnmoTmiYDmnInmlofku7Yv5paH5Lu25aS5DQpsaXN0LmZpbGVzKCIuLi8iKSAgICAgIyDliJflh7rkuIrkuIDnuqfot6/lvoTnmoTmiYDmnInmlofku7Yv5paH5Lu25aS5DQpsaXN0LmZpbGVzKCIuLi8uLi8iKSAgIyDliJflh7rkuIrkuKTnuqfot6/lvoTnmoTmiYDmnInmlofku7Yv5paH5Lu25aS5DQpgYGANCg0KIyMjIyDjgJDlrp7ot7UxMOOAkeS7iuWkqeaZmuS4iuWQg+S7gOS5iO+8nyB7I+Wunui3tTEw5LuK5aSp5pma5LiK5ZCD5LuA5LmIfQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiMjIOivt+iHquW3sei/kOihjA0KY2hvaWNlID0gYygi5rKz6KW/6aOf5aCCIiwgIuays+S4nOmjn+WggiIsICLnjq/nkIPmuK8iLCAi54K55aSW5Y2WIikNCnNhbXBsZShjaG9pY2UsIHNpemU9MSkgICMg6ZqP5py65oq95qC3DQoNCiMg6K6+572u6ZqP5py656eN5a2Q77yM5L2/57uT5p6c5Y+v6YeN5aSNDQpzZXQuc2VlZCgxMjMpICAjIOmaj+acuuenjeWtkOWPr+S7peaYr+S7u+aEj+aVtOaVsO+8jOayoeacieeJueWumuWQq+S5iQ0Kc2FtcGxlKGNob2ljZSwgc2l6ZT0xKQ0KYGBgDQoNCiMjIyMg44CQ5a6e6Le1MTHjgJHmraPmgIHliIbluIPpmo/mnLrmlbDnmoTlubPlnYflgLzlkozmoIflh4blt67vvJ8geyPlrp7ot7UxMeato+aAgeWIhuW4g+maj+acuuaVsOeahOW5s+Wdh+WAvOWSjOagh+WHhuW3rn0NCg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpICAjIOiuvue9rumaj+acuuenjeWtkO+8jOS9v+e7k+aenOWPr+mHjeWkjQ0KeCA9IHJub3JtKDMwKSAgIyDnlJ/miJAzMOS4qumaj+acuuaVsO+8iOato+aAgeWIhuW4g++8iQ0KDQptZWFuKHgpICAjIOaxguW5s+Wdh+WAvA0Kc2QoeCkgICAgIyDmsYLmoIflh4blt64NCmhpc3QoeCkgICMg55S755u05pa55Zu+DQoNCnggPiBtZWFuKHgpICsgc2QoeCkgICAgICAgICAjIOi/lOWbnlRSVUUvRkFMU0XlkJHph48NCnhbeCA+IG1lYW4oeCkgKyBzZCh4KV0gICAgICAjIOi/lOWbnijlj5blh7op56ym5ZCI5p2h5Lu255qE5pWw5YC8DQp3aGljaCh4ID4gbWVhbih4KSArIHNkKHgpKSAgIyDov5Tlm57nrKblkIjmnaHku7bmlbDlgLzmiYDlnKjkvY3nva4NCg0Kc2V0LnNlZWQoMTIzKSAgIyDorr7nva7pmo/mnLrnp43lrZDvvIzkvb/nu5Pmnpzlj6/ph43lpI0NCnggPSBybm9ybSgxMDAwKSAgIyDnlJ/miJAxMDAw5Liq6ZqP5py65pWw77yI5q2j5oCB5YiG5biD77yJDQoNCm1lYW4oeCkgICMg5rGC5bmz5Z2H5YC8DQpzZCh4KSAgICAjIOaxguagh+WHhuW3rg0KaGlzdCh4KSAgIyDnlLvnm7Tmlrnlm74NCmBgYA0KDQojIyMjIOOAkOWunui3tTEy44CR4oCcSGVsbG8gV29ybGTigJ3nmoTlh6Dnp43miZPljbDmlrnms5XvvJ8geyPlrp7ot7UxMmhlbGxvLXdvcmxk55qE5Yeg56eN5omT5Y2w5pa55rOVfQ0KDQotICAgYGNsaWDmmK/lkb3ku6TooYzkuqTkupLnmoTkuJPkuJpS5YyF77yM57O757uf5oCn5o+Q5L6b5LqG5ZCE56eN6L6T5Ye65paH5pys6K6+5a6a5Ye95pWwDQogICAgLSAgIOivpuinge+8mjxodHRwczovL2NsaS5yLWxpYi5vcmcvPg0KDQpgYGB7cn0NCnByaW50KCJIZWxsbyBXb3JsZCEiKQ0KY2F0KCJIZWxsbyBXb3JsZCEiKQ0KY2F0KCJIZWxsbyIsICJXb3JsZCEiKQ0KYGBgDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KY2xpOjpjbGlfdGV4dCgiSGVsbG8gV29ybGQhIikNCmNsaTo6Y2xpX2gxKCJIZWxsbyBXb3JsZCEiKQ0KY2xpOjpjbGlfaDIoIkhlbGxvIFdvcmxkISIpDQpjbGk6OmNsaV9oMygiSGVsbG8gV29ybGQhIikNCmNsaTo6Y2xpX2FsZXJ0KCJIZWxsbyBXb3JsZCEiKQ0KY2xpOjpjbGlfYWxlcnRfc3VjY2VzcygiSGVsbG8gV29ybGQhIikNCmNsaTo6Y2xpX2FsZXJ0X2luZm8oIkhlbGxvIFdvcmxkISIpDQpjbGk6OmNsaV9hbGVydF93YXJuaW5nKCJIZWxsbyBXb3JsZCEiKQ0KY2xpOjpjbGlfYWxlcnRfZGFuZ2VyKCJIZWxsbyBXb3JsZCEiKQ0KYGBgDQoNCiFbXShpbWFnZXMvY2xpcGJvYXJkLTcxNDEyNDM5NS5wbmcpDQoNCiMgUumAu+i+keaOp+WItuivreWPpQ0KDQojIyBpZuWIpOaWreivreWPpQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmlmIChjb25kaXRpb24pIHsNCiAgIyBEbyBzb21ldGhpbmcNCn0gZWxzZSBpZiB7DQogICMgRG8gc29tZXRoaW5nDQp9IGVsc2Ugew0KICAjIERvIHN0aC4gZWxzZQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KeCA9IDMNCmlmICh4ICVpbiUgMTo1KSB7DQogIGNhdCgiWWVzIikNCn0gZWxzZSB7DQogIGNhdCgiTm8iKQ0KfQ0KYGBgDQoNCiMjIHdoaWxl5b6q546v6K+t5Y+lDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0Kd2hpbGUgKGNvbmRpdGlvbikgew0KICAjIERvIHNvbWV0aGluZw0KfQ0KYGBgDQoNCmBgYHtyfQ0KeCA9IDENCndoaWxlICh4IDwgNSkgew0KICBjYXQoeCwgImlzIHNtYWxsZXIgdGhhbiA1XG4iKQ0KICB4ID0geCArIDENCn0NCmBgYA0KDQojIyBmb3Llvqrnjq/or63lj6UNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpmb3IgKHZhciBpbiBzZXEpIHsNCiAgIyBEbyBzb21ldGhpbmcNCn0NCmBgYA0KDQpgYGB7cn0NCmZvciAoeCBpbiAxOjUpIHsNCiAgeSA9IHggKiAyDQogIHByaW50KHkpDQp9DQpgYGANCg0KIyDjgJDkvZzkuJoz44CR57yW56iL6Kej5Yaz5oqb56Gs5biB6Zeu6aKYDQoNCumXrumimOaDheWig++8muS4gOaemuehrOW4ge+8jOi/nue7reaKm+S6hk7mrKHpg73mmK/mraPpnaLmnJ3kuIrvvIzlho3mipvkuIDmrKHlj43pnaLmnJ3kuIrnmoTmpoLnjofmmK/lpJrlsJHvvJ8NCg0KLSAgIOavlOWmgu+8jOS4gOaemuehrOW4ge+8jOi/nue7reaKm+S6hjPmrKHpg73mmK/mraPpnaLmnJ3kuIrvvIzlho3mipvkuIDmrKHlj43pnaLmnJ3kuIrnmoTmpoLnjofmmK/lpJrlsJHvvJ8NCi0gICDov57nu60xMOasoeWRou+8n+i/nue7rTEwMDDmrKHlkaLvvJ/ov57nu60x5Lq/5qyh5ZGi77yf4oCm4oCmDQotICAg5oCd6Lev5o+Q56S677ya5Yip55So5YGH6K6+5qOA6aqM55qE5oCd5oOz77yM5Yik5pat6L+Z5p6a56Gs5biB5piv5LiN5piv5pmu6YCa56Gs5biB77yISDDvvJrnoazluIHmmK/mma7pgJrnmoTvvIkNCg0K5L2c5Lia6KaB5rGC77yaDQoNCi0gICDnvJblhpnkuIDmrrVS56iL5bqP77yM6K6h566X5bm25Yik5pat6Iez5bCR6L+e57ut5aSa5bCR5qyh5q2j6Z2i5pyd5LiK77yM5Y+v5Lul6K6k5a6a56Gs5biB5LiN5YaN5piv5pmu6YCa56Gs5biB77yI5ouS57ud6Zu25YGH6K6+77yJDQotICAg5bC95Y+v6IO955SoUiBNYXJrZG93buWujOaIkA0KDQrlubPlj7Dmj5DkuqTvvJoNCg0KLSAgIFLku6PnoIHlkozov5DooYznu5PmnpzmiKrlm74NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNClvov5Tlm57or77nqIvkuLvpobVdKGh0dHBzOi8vcHN5Y2hicnVjZS5naXRodWIuaW8vUkNvdXJzZS8pDQoNCsKpIOWMheWvkuWQtOmcnA0K