From c9ad32cb870078a17e040b30c88c4cffb37daece Mon Sep 17 00:00:00 2001 From: luoxiang <2806718453@qq.com> Date: Sat, 20 Jul 2019 22:14:51 +0800 Subject: [PATCH] =?UTF-8?q?mongodb=E5=88=86=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/MongoDB_分片.md | 317 ++++++++++++++++++++++++ notes/MongoDB_复制.md | 105 ++++++++ pictures/mongodb-分片模式.png | Bin 0 -> 37924 bytes pictures/mongodb-分片测试.png | Bin 0 -> 24068 bytes pictures/mongodb-分片集群状态.png | Bin 0 -> 24248 bytes pictures/mongodb-副本集状态.png | Bin 0 -> 18237 bytes pictures/mongodb-块拆分.png | Bin 0 -> 10083 bytes pictures/mongodb-块迁移.png | Bin 0 -> 10017 bytes pictures/mongodb-路由查询.png | Bin 0 -> 26185 bytes pictures/mongodb-非分片集合.png | Bin 0 -> 15643 bytes 10 files changed, 422 insertions(+) create mode 100644 pictures/mongodb-分片模式.png create mode 100644 pictures/mongodb-分片测试.png create mode 100644 pictures/mongodb-分片集群状态.png create mode 100644 pictures/mongodb-副本集状态.png create mode 100644 pictures/mongodb-块拆分.png create mode 100644 pictures/mongodb-块迁移.png create mode 100644 pictures/mongodb-路由查询.png create mode 100644 pictures/mongodb-非分片集合.png diff --git a/notes/MongoDB_分片.md b/notes/MongoDB_分片.md index e69de29..88111cc 100644 --- a/notes/MongoDB_分片.md +++ b/notes/MongoDB_分片.md @@ -0,0 +1,317 @@ +# MongoDB Sharding + +## 一、分片机制 + +### 1.1 核心组件 + +在单机环境下,高频率的查询会给服务器 CPU 和 I/O 带来巨大的负担,基于这个原因,MongoDB 提供了分片机制用于解决大数据集的分布式部署,从而提高系统的吞吐量。一个标准的 MongoDB 分片集群通常包含以下三类组件: + ++ **shard** :用于存储分片数据的 Mongod 服务器,为保证数据高可用,建议部署为副本集。 ++ **config servers** :配置服务器,它是整个集群的核心,用于存储集群的元数据和配置信息 (如分片服务器上存储了哪些数据块以及这些块的数据范围) 。从 MongoDB 3.4 开始,必须将配置服务器部署为副本集。 ++ **mongos** :查询服务的路由器,它是集群对外提供服务的门户。mongos 从配置服务器获取数据块的相关信息,并将客户端请求路由到对应的分片服务器上。 + + + +### 1.2 分片键 + +为了将集合中的不同文档分发到不同的数据块,MongoDB 需要用户指定分片键,之后基于选定的分片策略将数据拆分到不同的数据块。每个需要分片的集合只能有一个分片键: + ++ 对于非空集合进行分片时,分片键必须是该集合的索引或者前缀索引 (即索引必须以分片键开头)。 ++ 对于空集合,如果符合规则的索引不存在,则 MongoDB 将自动用分片键创建索引。 + +### 1.3 分片策略 + +当前 MongoDB 4.x 支持两种分片策略:分别是散列分片和范围分片。 + ++ 散列分片:对分片键进额行哈希散列然后分配到某个数据块; ++ 范围分片:对分片键按照范围分配到某个数据块上。 + +散列分片有利于数据更加均匀的分布,但是在按照范围进行查询的场景下性能比较低 (如查询编号范围内的订单信息),因为按照这种分片规则相邻的数据通常不在同一个数据块上,此时需要在整个集群范围内进行广播和查询。 + +范围查询则反之,在范围查询的场景下性能比较好,但是数据可能出现分布不均匀的情况。假设分片键恰好是单调递增的,此时数据可能长期驻留在最后一个数据段,所以范围分片更适合于那些分片键长期稳定在某个区间范围内的数据,如年龄等。 + +需要特别注意的是分片键在选定后就无法修改,所以在选择分片键的时候应该要进行全面的考量。 + +### 1.4 块拆分 + +无论采用何种分片策略,数据最终都被存储到对应范围的数据块 (chunk) 上,每个块默认的大小都是 64 M。由于数据源源不断的加入,当块超过指定大小时,就会进行块拆分。需要强调的是块拆分是一个轻量级的操作,因为在本质上并没有任何数据的移动,只是由 config servers 更新关于块的元数据信息。 + + + +当某个分片服务器上的数据过多时候,此时为了避免单服务器上 CPU 和 IO 操作的性能问题,就会发生块迁移,将块从一个分片迁移到另外一个分片,同时 config servers 也会更新相关块的元数据信息。 块迁移是由在后台运行的平衡器 (balancer) 所负责的,它在后台进行持续监控,如果最大和最小分片之间的块数量差异超过迁移阈值,平衡器则开始在群集中迁移块以确保数据的均匀分布。 + + + +块的大小是可以手动进行配置修改,但需要注意权衡利弊: + +- 小块会导致频繁的数据拆分和迁移,从而致保证数据均匀的分布,但数据迁移会带来额外的网络开销,同时也会降低路由性能; +- 大块意味着更少的数据拆分和迁移,更少的网络开销,但会存在数据分布不均匀的风险。 + +### 1.5 数据查询 + +这里需要注意块的迁移不会对查询造成任何影响,MongoDB 集群和 Redis 集群的查询原理不同。对于 Redis Cluster 而言,数据的散列规则同时也是查询时的路由规则。但是对于 MongoDB 分片集群而言,查询需要先经过 mongos ,mongos 会从 config servers 上获取块的位置信息和数据范围,然后按照这些信息进行匹配后再路由到正确的分片上。因此,从本质上而言 MongoDB 的分片策略和路由规则没有任何关系,假设按照分片策略将某文档分发到 Shard A 的 Chunk01 上,之后 Chunk01 迁移到 Shard B , 由于配置服务器会更新 Chunk01 块的位置信息,所以仍然能够正确路由到。 + + + +### 1.6 非分片集合 + +以上的所有讲解都是针对分片集合的,而在实际开发中并非每个集合都需要进行分片,MongoDB 允许在同一数据库下混合使用分片和非分片集合。每个数据库都有自己的主分片,所有非分片集合同一存储在主分片上。需要特别说明的是主分片和复本集中的主节点没有任何关系,在新数据库创建时程序会自动选择当前集群中最少数据量的分片作为主分片。如下图所示: Shard A 为主分片,集合 Collection1 是分片集合,而集合 Collection2 是非分片集合。 + + + + + +## 二、集群搭建 + +这里我只有三台服务器,所以三台服务器上均部署 mongod 服务,形成两个分片副本集;同时三台服务器上均配置 config servers 服务,形成一个配置副本集。集群架构如下: + + + +### 2.1 分片副本集配置 + +第一个分片副本集的配置 `mongod-27018.conf` 如下: + +```shell +processManagement: + # 以后台进程的方式启动 + fork: true +systemLog: + destination: file + path: "/home/mongodb/log-27018/mongod.log" + logAppend: true +storage: + dbPath: "/home/mongodb/data-27018" +net: + # 分片服务的默认端口号为 27018 + port: 27018 + bindIp: 0.0.0.0 +replication: + # 副本集的名称 + replSetName: rs0 +sharding: + # 在集群中的角色为分片 + clusterRole: shardsvr +``` + +第二个分片副本集的配置 `mongod-37018.conf` 如下: + +```shell +processManagement: + fork: true +systemLog: + destination: file + path: "/home/mongodb/log-37018/mongod.log" + logAppend: true +storage: + dbPath: "/home/mongodb/data-37018" +net: + port: 37018 + bindIp: 0.0.0.0 +replication: + # 副本集的名称 + replSetName: rs1 +sharding: + # 在集群中的角色为分片 + clusterRole: shardsvr +``` + +### 2.2 配置副本集配置 + +新建副本集配置文件 `mongo-config-server.conf` ,内容如下: + +```shell +processManagement: + fork: true +systemLog: + destination: file + path: "/home/mongodb/config-server-log/mongod.log" + logAppend: true +storage: + dbPath: "/home/mongodb/config-serve-data" +net: + # 配置服务的默认端口为27019 + port: 27019 + bindIp: 0.0.0.0 +replication: + replSetName: configReplSet +sharding: + # 在集群中的角色为配置服务 + clusterRole: configsvr +``` + +### 2.3 路由服务配置 + +新建 mongos 路由服务配置文件 `mongos.conf` ,内容如下: + +```shell +processManagement: + fork: true +systemLog: + destination: file + path: "/home/mongodb/mongos-log/mongod.log" + logAppend: true +net: + # mongos服务默认的端口号为27017 + port: 27017 + bindIp: 0.0.0.0 +sharding: + # 至少需要提供配置副本集中任意一个服务的地址 + configDB: configReplSet/hadoop001:27019,hadoop002:27019,hadoop003:27019 +``` + +### 2.4 配置分发 + +将以上所有配置分发到其他两台主机上: + +```shell +scp mongod-27018.conf mongod-37018.conf mongo-config-server.conf mongos.conf root@hadoop002:/etc/ +scp mongod-27018.conf mongod-37018.conf mongo-config-server.conf mongos.conf root@hadoop003:/etc/ +``` + +配置文件中所有用到的文件夹需要预先创建,否则无法正常启动服务,三台主机均执行以下命令: + +```shell +mkdir -p /home/mongodb/log-27018 +mkdir -p /home/mongodb/data-27018 + +mkdir -p /home/mongodb/log-37018 +mkdir -p /home/mongodb/data-37018 + +mkdir -p /home/mongodb/config-server-log +mkdir -p /home/mongodb/config-serve-data + +mkdir -p /home/mongodb/mongos-log +``` + +### 2.5 启动分片和配置服务 + +分片在三台主机上执行以下命令,启动分片服务和配置服务: + +```shell +mongod -f /etc/mongod-27018.conf +mongod -f /etc/mongod-37018.conf +mongod -f /etc/mongo-config-server.conf +``` + +### 2.6 初始化所有副本集 + +在任意一台主机上执行以下命令,初始化所有副本集: + +初始化分片副本集`rs0`: + +```shell +# 连接到 +mongo 127.0.0.1:27018 + +# 初始化副本集rs01 +rs.initiate( { + _id : "rs0", + members: [ + { _id: 0, host: "hadoop001:27018" }, + { _id: 1, host: "hadoop002:27018" }, + { _id: 2, host: "hadoop003:27018" } + ] +}) + +# 退出 +exit +``` + +初始化分片副本集`rs1`,步骤同上,命令如下: + +```shell +rs.initiate( { + _id : "rs1", + members: [ + { _id: 0, host: "hadoop001:37018" }, + { _id: 1, host: "hadoop002:37018" }, + { _id: 2, host: "hadoop003:37018" } + ] +}) +``` + +初始化配置副本集`configReplSet`,步骤同上,命令如下: + +```shell +rs.initiate( { + _id : "configReplSet", + members: [ + { _id: 0, host: "hadoop001:27019" }, + { _id: 1, host: "hadoop002:27019" }, + { _id: 2, host: "hadoop003:27019" } + ] +}) +``` + +### 2.7 启动路由服务 + +在任意一台主机或多台主机上启动路由服务。mongos 是没有副本集的概念的,所以如果你想启动多个路由服务,只需要在多台服务器上分别启动即可,启动命令如下: + +```shell +mongos -f /etc/mongos.conf +``` + +在 `mongos.conf` 文件中已经通过配置参数 `sharding.configDB` 配置了配置副本集的信息,所以路由服务已经能够感知到配置副本集,所以接下来只需要将分片副本集的信息传递给 mongos 即可,命令如下: + +```shell +# 连接到mongos服务 +mongo 127.0.0.1:27017 + +# 切换到管理员角色 +use admin + +# 添加分片副本集 +db.runCommand({ addshard : "rs0/hadoop001:27018,hadoop002:27018,hadoop003:27018",name:"shard0"}) +db.runCommand({ addshard : "rs1/hadoop001:37018,hadoop002:37018,hadoop003:37018",name:"shard1"}) +``` + +务必注意,在添加分片副本集之前一定要切换到管理员角色,否则后面的添加操作会返回 `"ok" : 0` 的失败状态码,同时会提示 `addShard may only be run against the admin database.` 添加成功后,可以使用 `sh.status()` 查看集群状态,此时输出如下,可以看到两个分片副本集已经被成功添加。 + + + +### 2.8 测试分片 + +#### 1. 开启分片功能 + +连接到 mongos ,对 testdb 数据库开启分片功能,同时设置集合 users 的分片键为用户 id,后面的`1`表示范围分片,如果想要采用哈希分片,则对应的写法为: `{uid:"hashed"}` 。 + +```shell +db.runCommand({ enablesharding : "testdb" }) +db.runCommand({ shardcollection : "testdb.users",key : {uid:1} }) +``` + +#### 2. 创建索引 + +切换到 testdb 数据库,为用户表创建索引,命令如下: + +```shell +use testdb +db.users.createIndex({ uid:1 }) +``` + +#### 3. 插入测试数据 + +使用以下命令插入部分数据,用于测试的数据量可以按自己服务器的性能进行修改: + +```shell +var arr=[]; +for(var i=0;i<3000000;i++){ + arr.push({"uid":i,"name":"user"+i}); +} +db.users.insertMany(arr); +``` + +#### 4. 查看分片情况 + +插入数据完成后,执行 `sh.status()` 命令可以查看分片情况,以及块的数据信息,部分输出如下: + + + + + + + +## 参考资料 + ++ 官方文档:https://docs.mongodb.com/manual/sharding/ ++ 官方配置说明:https://docs.mongodb.com/manual/reference/configuration-options/ \ No newline at end of file diff --git a/notes/MongoDB_复制.md b/notes/MongoDB_复制.md index cec1865..af62c21 100644 --- a/notes/MongoDB_复制.md +++ b/notes/MongoDB_复制.md @@ -64,3 +64,108 @@ MongoDB 的选举算法会尝试让高优先级的节点优先发起选举,从 ## 三、搭建副本集 +这里以搭建一个三节点的副本集为例,使用三台服务器,主机名分别为 hadoop001,hadoop002,hadoop003。 + +### 3.1 下载并解压 + +选择所需版本的 MongoDB 进行下载,下载地址为: https://www.mongodb.com/download-center/community + +
pFkBhqK`^{7x9~U_yn|Gr2 z2%ZB)n){?qlXu>;m0BHNRI N9|>1Lbhx6krcy(#bOoawYgo?J9yf!BKml6(7=t(tzJ zbu)tfn!R;F8?ap9iegC55MLMn2O|gkGDl+DPG-6GYgF@s*1G-CXE{|0f 3n;A^euSR{TSU?*9F4`aMFaia+Jw*(=7* zBy!rfja>UD;hIHimuGkJntnoCe4Fadh~$u`e|G2-!; 5^f4YdzTnOoA=bjTEkXU ;fKZUTAYr^A}jBo_1K(K2NVde*@3P34ly zEZ2f3|G_N)zmLWHmW?Mj`fdO!4-KhPjtJ$dFLE9CqF|zIHMQ(ImGW<^|Dj=%tI3}F zdDBaRH)NRhzE8gG+<% q9(~J( zM7ZLPXW-mgb_>p*QwZA(;J*OkPClaF6=8>nek?ibwlM#=V@?Lv32Tk+SDWwh^XB&= zk3htfqQ$T;B7pq@@VMj> l`p)<88q@ob@D{& zT*r>r^d&|-3i`k+U|*M*0l7rNiTlwb7FTq^1am8+_kj>8vo*<7ussvIyHEXtx8bD(zq2m-0 5E*0yyt-UkHVoO6eou$VY=Rj+|h#v^$@$pZ8tAvJWFsOQBa- zLd1S+wc^}l_ZK15`T8n88ynI{kk#gUue892`G*@WE8&n+W}g0AODV^7=Q8m>HDm@_Y1`Xzt)h6 zz}pY?w{zGQ-ZD0wslA>RjrRN%ZY$LXXUD2>bGt6-50VTzwEvw2K!>B5fd@G#u_4gL zKscolfpRt@(ctxJ*@`!x`=N6SOTFN#OUl5ry>34&c OKDw;k4CcXu(+AlHhdUEjhmw)R+q* zuIWt9ptv8n1KVlz?K0n?DX7OyD7+aT9Ur8rFU7%naC$Phl_f>v*dZhuUBE>koP0sk z+kz_TNm_f5Xctg3Rzoq*7*K9Z3(NW%0JRli&{_;qZASLQVsWGo=?p-uy{wasZTBrj z`kc3jpuvHD9Hm;mn+3gjI+eaGcp(@PY7R=jMCBUQvsDD~_ybONnyEXy1q>daQZ)~z zmLOGUcAwI+B^O`P>N3njPb+e}fhIdi{CJ&!b|F1lJk})_gOB2sczxggF^2jBJ9~Em zL2$xj71YZG0}hQaf2WI99|@;fuU>5ttfQ3%+QhMtTRcgO5Uga#o1n%IwW0AZ6s1Q| zRl&|Rg2?1C13o}$RZf(DRh}&>bhrgWe%&2vccs`OrZYqzf(Ho1yXJo^2z3Fx%RENU z+NVj2ALFj*cALNL*oWFqx!@HYWJKlROUk{OT!lx&+aEegF{w+U4~+U!4&n=kdiGy< z9F~ Gfe#W3h{#WU~(8Pp_c@yvF@B #3FuSt z8`5iMZn-{KHWv*8HdDgW#Xwc IfakUO{R zOc>EW =2Q-KDR};~VbauVX-x73tf8TOG@x6HB@G}ullA9De=`pv; zYonqUDcexb=G#^=ce}sX9z7#cn(9%FE8?!s5>%a0EukzO4~QYAa?kiBzts`19Cx4c zrQu0F77rw+73kh`TP@-Dr>^upJ!XEW*;D*b-9mIulAhKg#A>I=JAGBV#NC8?aaDUY z7q$?Thz)}Pj7K_@P`|QUV>xqyDM+HrQwB~ec4eUV@lx)U<%meC@_n| ;{E zQjhX{cnf`9)@~z4eSY6)W8WFn@IZhlKL+EA#*?%l9de>)Kr1OV`aHV&-rg|z2;`L< zkuQ>An82=YP>^Z(q Iv93fKyG2~t+EV7Bkq`{xc*S{lhu?&&_E*UoG6 zN3lnKbvH%cKXK@AUAFV!0KZNHPO?Eks*QVf<9_Jlgqa`>{(nydVrJ_-2W`k8DcJTt zHUBEpr~Q-fqrY_EvMAR&o3lqos`E41-X5a%wu~W282Syy9q9|=q<}*&uglst>)IPe z%-?UK*(WVZ7&U8yWq2gUj4TQdXvZDs-((@PGfeuJGxRNa7m zy!QJ;_P81$0OXl)R@RDLZgvbF_aaCiIUGGtJ-gR8gv7+THEvqtn lgcz zDo{MeUK`w#oX2`C@Qo1rhk9S);-x&WLt4Q_FGk6MtjBoG1(%<-W$%t;^xt0c!e0)d zQ7;L4*T)D{o;Xbc b>t4;DwS>pQS(F`@LW>yQSwQI`qbNYb z{BWmd7oD1%AOIr~`Vy32cJfmf&v~!$832ndor%{>2U$U^hF~b^4C@R*YVfNjSY2H; zIWTI3K2~|yoehaQ5S)&U*gs%8eN%C*+)G|Ygn7=LCB@t%x?F=NDOZ{cc7F}pE-9e> zs$hg@M;PkJh~}5%IEo4pO`!x{d*6H>SWd}rxjE{R8-ai3wny(a#X?&++f39qCLcNp zJ2+STGHCp1K~VIT)#H8}@6`6735maogcrs@b3qXz&eG1S6Dis`MMa138;@avIOF40 z|F|8lb~@~12N bFCYNwB>+`=a32j8Rud zv86XlWM1?Id{EIVSM@k1Fu+*&OFu2;jQy#f@t*4zI`{~7Qa)?Z^ }OBCYTPe<;|Y4B$zH;DK;?49q(4m6kyfgf==YSdpjy`=ftY zjIoQZW49NgaxD@hTZx@4M z(_U1^g1a<=OEJi%?lIoZ6^N7zu=DH}X>C_DSCR@&Z3|eD(uTyp0!%^ Kp6ij>H$g{cSsA?Xw7 zr(*N!GbD)2uI2IvA>*2KkG9A$3%S2g-5;6mdL=)DH1&JulOxudH8fG?TNuo|^7GK_ z)YWKf*!+>zD=1JEaj)4$NX(0!D62{vxmGvZq`f&``y0Lbrfo$-I6w=grEQg+SfHv^ zoZFg&m!JkFMLM!kZQSXHV{!BL%N}F&j1t$-oI;8RlGuZ21)Bf8_`9G6k^VPe=~|&o zqc)=LSby9~@1^BhryRBd+s1=MU36e0MWv1SzqUU@sZubb=Mbvy^p_s0j9~=N=SEBu zD~7MVC0H~hiYBGNADv1;v!D->y|=Fd$@^Y{CHLFGAhAOwvHKW}GtND0X5&xzD<#@V zXjEh}aNlLmSeO9+0xKU}zH9ukRnmYOTa)OPAq(Ggq*ByxGU>GC^NEuc8cO+vJ=gt8 zv b+~ftQW07YzpO2{DR2L&^1^0Ss28$)aIJgGH7WO(>-DEIo 5;tL5ihY=}R@S5w*hwO=lL9^Gho`9xE8BKs&s>?4 z3!zk$d@oZ=Xp6Q)Uh(CJPScxLf5oXENz-)Ds*L>c)T(eHvi`U`kz&M(C)@ic UgeAD9C^h=J!%E4iH$v|HI%FIP~)N)_J zi-gzEHjeZrV|K}hV>4+sgXmPxdsGNU=z<4Qp+dSP-D?q@w(27yKR1&gn%*~5Td*B} zHP3$HygM-0$mTP8ZZDgy)8C1b5pnwB8fhq@b>yB(lMiobl4jnPKj%i@doUHc! 1Pd_*;)XN zLcqOQzp>j75BH20ZSz#RhsLLZc&*O#v+t(W{3RLuwJ0z2`{?$TAM#NcwnHLV`76eW+({lqsNxw)pC&5IQtzEr}%A$QZ$IKW1;+_>99l$5qjMq ze{n#k@du%ksL}5CL0+b%q@4PzEqh3xJzqY`gWG#tPOBm<{-uR9N_mxDzCX&juXEZy zZkNPIu7iC1cB1is_DeS>C$sh~$Z4=hSYYvoc!jb#3K3V`T8+2b#&Tjm@N?z@e7Zd; z+{{IF*rTQlsQ>w_fb#{|hZr#C=iPhg7=M0i*|#_G3aLB$lsF5N5la_M20N*MokMBb zpa*t4BHz+ac89gIN7hMR0O%4+EzDz5gZR7m#9MxZfzl$^9s(b<^72Pn{vG#xHY+4N zx4%)?;DfhL**STsLs$!i^on@a$oM>1qwq4+w0QwO0(QPa#A1~mRVTFDk9EXB=l|g+ z5??+cUpL|}Ndh $rDFd0nYZp0FGYS;TGH_(kVN)lIHC?Va4La%)%*)YLT zAs;wgdTELL4&7=pg~hgBm*~vBEwV?)_!2aNcDd=vWsi0M1@Lqphts-I9pD6CpLYIV zdKQnGs})4Pf0I1b^8$+(wee%llHz#3_B4AM7OIwy(gkp!u=dz1app#Lmk~e=bfIBs zm5OX84!;3INJj*>YQ9q>|12pTYW&rJd&r8%II-f}8{NkhBJ)y|Fi|ifP%&I|6_uVP zn++VxN>(b_OksnXA( >y=_70=RAfk@-iHc(4Um=>xwdE&lG-^ilT5E247Zx?nW0&yLD z^xAl_&j3WURg$1wSLk0#QN-XMXmRuR>XS=g^tp8wXeqR|)uiQbTZBx@+iKK`CfkUi zBBuPyeL{brH@KO9kXnt1J`N$e)>Aev%;Mj?C9%7^A17mS&v~O81XgRKqRL}?c(HZM zZOQ-Qo&-Rq-n)e@w~$A&X?u+OKDs|}K)i>cp69aR6^}dx2w=yW)ece#^4*OLf%e@! zK*P=-L**&8#@G6&c3>}arOJ>Xzd5ZlO%94&4sDgOI4@0#7Tj@v<-Tzf;S4~$Z88I} zfbq33Q!j-lSwP;Fk==X0=i&4M%q 2tqT?0wh>#SH>LlDZRado`Z;R)0*wj Zko6XbOK3b!+i;q~Z_5zK|r$DVlyaj+|__d~vqtM%< zJoM%;_G$b!FLmIMbz6PEQX>^BSTldaGhq nEitzgi3f{I)9 zKFJGI6 J@F1U{8)X;3R+QFS29v&e#FIMf> zB*A#}@Vk&)^4uJ$3BMs?$JaEJ{MrnOF}H*ox5Zayd<5_TR(M^eo{3vnrso>^j78Mw z(6Wx~H6+{K%vfwSBG1B_$^{um*|>t&4-k3ffDS56=`lNky7CCrmDhii#d_{2R1OmX zEowuFX=~!I5XNbZzCjydRebt3dhbI$)3^N*RIg#{K)n~{m`eQ{8dFL9?Y8{OAbqb( zM7S=*D*@A3qBH{|nMU(M=>de?SyG+l4z(9 zdl$22Vi=y=9=2HB2FB996Y|#Yrt}mUcAVLrEHtHbE4`MM{B<$I7dJD~Me)ui$xGOE z(?PY!9$xYI32_-i)_|GO8y#IU0l5{i8{>XtDRrSLq*Jb0GTLsnvw0Vlr#z1iN)5=6 z#=-}XxoAl8Sj+v+gTKxc)9z08L HMBl;x@QhyaZ(c(8JK+1CdxMq#GwIW3dCj z67?`_((;W0-5d#*A)IR5UD=(j%~7%!Y}l8Z&0RdgvzkqWGU*6+$(ivBG6l?DcS64; zk-*&MrS|?(y~nkdZ44w&AL={*b6sV0hhTEk8d(0eY1#JYLL~mpY&>%6mJBKDpGV$+ zHUN6EjM(E5<_^3a4WJ(^zH3b7n|l`Q=bZl}4X-c`8^pn_0qmSe`2sny^6_7VZ7FWk zyDk$~r<7P@YJT6#m*eN$(u9!vjFS3e8LOmg@jZU5X=VS>; >}+I9bkekQ=Fi7GN|^%E(UjJ#`*ez@SDjX`bnrbs(FWNO^pMDqb9yb zlc7;PxddE-Nm|Ib!2bD1B{HzW;qvS)IB*5Ngv7H+0RISlOD?(hvUnWdTda6B%ea42 zBIo;)l}1yat}m_776_!5VLIohxYV4L9*%t#ol!MJy#i5is{6T)>`G%Z%a jCoIC`Hk zX{wgs^7Z4;1e-B|8N{A7lxU?thqISYJsPR>ExH|*0)uKFbaZyBV`|nXYa}BcVMb7x z=Aes0JlpBmSl>QM^+2fZ=T&8Y6ZtAykdsD*S$3qW!|^rFvSL1AmWmJfOt#NXWe8vZ zRjzgsp>$8ySs@6j%ykHVR&3NXvxBtjP_ceQiOVq#^tSFrud`FM9O9rhle~7 ZWZjeHA?7pTIy*i$FYeh*ryJIuG5MusxpuFZ7ZOa~$R?U2k zqIO`=l7zH&u#ukjWRQ4RO`n3iYfaPE#!Y!M%~^d^MvjEq{|X}`Gx}DJA%uy3@rU}+ zuPu8-TGE~R_Cr?2&i0+pdF4+-)`&hW6@B0jj3+gJx8xR6jcH_1k>5ZXvX;SOv?4(b z_U#l5*={$I<()bUZRg198RPAYaN8?PJxMwHqwC{|d1Oh8#7}|g6KB%(>Ed$T^)KB> zBX1K@-5=4b#LvK9N^T&<9i;tt2O0DT+du~Db9tNkbP2g(d`!mwE XZXT&~KQc@`VWKLBu+)`&~0ArK^ZGl(tzXoxD(>qH;kHinYGH}CfU$_6> zgD**!3*37Pw5Lq*w(*|=|G79RxC6Hkvq0dx;OIv%@HKu`0$c|#VV;}Y5&rW3>wC~? zKm9ivIlkWB))+9V2)NsyN(l}pR7%L8!Vf9*?q-9Fq4(MU&*1;B?+J $xMcJG 2=DUKe+|g|5=cb1ilHsgZC_Xv zf`z(Avp3>?0_+)vHrV0tu$NKIlk|Qn2D}ClGUI;S^Zd^vYkRfx+_ex@g|`@dJMKW? zhrxQFlz*wV#V h34Ocp$Zb8<(hBKhq6Lh@Ws8E|uy?!5qYZNy*SFn@t&TcnkT zXEWH71Z=R;^gh4dKd5#yn{~l;*acwHKqUqNnYU#{CXd7?Ks&Y+bIF2qG7Iq^bvvA- z+852mhSWQHl%wdKHcU*2b8r5i2wDamo{$~ =TSy0e`$+)FJ#FoC?Z*@^SALrFQS5GWz3 zNC(u!&)N(|0P_PyvOZzTSQrOTbd!N(WTTGVvsbgT@HqZ2BaJTVa7x)^3_OwEtw>gr z`BCW@@bK~Qz7#42Gzt*5^RKr~y%j(kg?#0=bkQ9HeDFN(;q);Qh|fi%BZfro2Yoi6 zg_qliC@8(YdPnQ#v~8?6u-I_oBxb~u0g>ms0he|V2(Sdy@ IL|(R@gM&~QSqmu8OXL8P32g@x81qrTvrAO6Y%b1l%A zGK;$Jq1~hVpJ@naDqO-X0^%2FvcOQ%aIbc5(`U=9&m{yy%#EIU*n_Pec&f3!fYw?F zIV^%Kp<@&Rf(r0)3=Wd0kh|wt3o6f&rOI?Wys6?!d?SdfW4N`W0bjap+@RMLpmoK; zrdVoP{H w_8T}xr4?|K#Q#J)nEi3 zxILJ&CqgO+U|-er^uk)xxkx6D8*pip#GDJI7ym-dIRHk x$74c2n`+(bxflUTL?=JQY|i1C(Oyo+1m2~!)--f-m_xoV0B5@n2f7Qv*EU; zGXbFF#^ASl09A^wQtNqTf2yaFeWQ;?5{Fcu;PqnKR`#aVZ=XW%RBYp1Oz>0?&=f}z zN)RU(zil_Yq vRZ<;3qc_)t8Upt<-{fV7vC1gk^c25u<9Y=22XsgK0B#g1}imS zfG`9rGUK~OwclYUb*8-#HUsyKaOJx9di#Hba8rVWHih9(0KMjq5$T7H^j2fP7P-= zez&?dQpY`5^SIx=Ks(E>B|ZQ6E@Li3`=#~OOUX)YP+qE?CEwi(SU22?AOtQe7rcob zy8e68*?!iGG7`oDOvkK-Fu``^aU4;Z!~5kBR+YyTUn)LBNk@>UHN;IpN4*Lz_m9Nv zWHyaiYh%8WlUZkep*`%fs9)lwY>Tst85OcG&j_#kx?GyF#8+ {8Ayy+K)k1{ -R>f=;MGdZrCND|^fe=K bBsH6b9?EsBRe`CO=F_iHWFW5Ed0`8eXT9ra-1WG)X_59_o zXCTl&A5J9*#6Te>2aG>AI!O=h4GXJ$U*o_~;GlXp&%Z4LS6~pSKc+yP&Z9s2e+Ato z-$=Rkw^_gB8v#O*H-L2$SHrj5p6 mm2^nYk=TfW{lS 4Tz$1U@#}l_w7{j{k0fpMKBa%TgAqVBx%oWfouK#9Kfcw*l!)+}ilrp1h7#x} zzw;_#eGDS-`>@5`ez=QNQsrZgOH%V<7L4*4Zpv;>>?%H`fFY}?XJ?JJPTV~IlBF;O z76DpK0NcRU0*dpVmLi|9D=<6k>-292flmpzNN&~{rdwygerWvjegb8YI&MD)2Z(e~ zQ>;p7aSEW%RjEu&e+PBx1L{<;UZ(Oh3`nff67En`C5fjt>R-RU6)p*Ih1L~B80v+g z;)v%L0>v2)f&)0NNF?TLfW~N=TB80(mqOycT6UZ(hwkK<3KLi J30E5ER3)|Z?yuVSfSDpvn%~amvC$c2J(k}=MG5t*N7<(a{dezO* zg&hziU~0_R*mU}F*m|Y|`}_`!UX>N@ =`-=h6|LFuDh@mY;fho9z4(H88q_p+yTXR`kN3+zt^_`8G^b7EKG<=B?665l z!JA=9_v>F>_LgN=9u=F9m{K8J(>|MdGB7P^kwk_nxM+C)9jWC38pExKfw4OLbjLA& z;|2r8UN#!-@OS=Rfx{D80prye^0DkY6FBGBBn6fC|I6Ve<=(;1e!+?U{~xvf_vi34 zPw~6Sp91wb$}+%;m78DDTMPLcc$y7Qzdqqyx_eij&Shh@9&-3whcExEX()N9&m34* z!0gP}w-_YT{U84CEFfTVax4qiw|1LlT4AX6_tIr9n@BxI&pq0rZ5l0D6_n9Is)8oQ zSG|1}N_bt;_B|6kCNB5mHYJU (z10oFR%Q9`ic`R*0c|txLi+^&oW1T0J -}C_6q&a?a>6q>?BUc_kdlsWv|@- zAKh9vbq-R`YX>IYUy57T`t)`)(C!d*gp}lGDY|PsCMuN$pl;l04>zpGN59QV_hI<# zu<}dL;Jwo~SqAz00jCDEnCRz~ I2-oMTVU7=Xj%rI^zVa-0{G`ff (a`T32&IZbZHtrSaLxz9KU}0s-OkKwuQ& z2Tf2%MZ~kz2B<*D?$P#S4Cz%{CbNPvv=DAvy@_qJKA=2L`^)3rX1uk$-~eoohdgP!Dt+p;w-O#Q|?njZFh3 z87esN%ac(d6>~_j7T%o!Ui^?XMjeM)om=f+_nVaU$AmJCHUGAbS=J6@`2MXa+>Y?W zaiG}(2|0alV34jFFmydXno^3fTh_yDCcSBlRa4^eSWwG%DXyFlTpgI%eR?jHZ*<%B zRzKg>fvQp;_Ge7gk;Zf`Xb!K@4v@&YRUjn6dXGN4!!iOkwy>*g`a?%-h4T*0w$_=) z?FbL2TZ{Aq`iH_Pm`fq6Lx{R|Bp^1OdnYr0j3fa0?z9h@5JA}cHE{H$kP1y@PXaV| zQdEJn1$DS@Ys&&wGnkz6uQWY>ZemsEcCBCQ_nd4K!G7myKwy-YIupDz6#%dcpzCjK z2JjMByb|e}dLY24LMc)2p-gFF A2eF#Z_M~JS5T>D?y?p)nq%B? zY8(mDV`}^WlYKd@SPpz=poq!FbBQPhw=~ayIzR(JV+M*%>FeLvftjUX2w-KFht+fz zdQrr3qY1;5_m=O!9O$26f!@hv0r{B76JPe%pa4Mt6T1_E+^_rz5L?m&Yr^C1 %uCyCRA HN@gg>`3c+gPVDE08-B#E= z|8qTN;Q{(9p*Ej&a{_g9BD^@ ~y-fngu{LuZi*Tm B^iG>7-=^6`i5lf!U%+8%IEsVQt;rd!e$ZFftKA-qP=}J;MiPjA(|5iO z7Z|m|!`(eHnt}XUogSDc=%_eB?rBFn%5TuX=l=p&4)MlmdE^sc0r!|81s)rH2SC+9 z9>PfG2#9VaK=%%^n!5D#HAw#YkzZ0Q8b?8mZ`Rf2Q5BRA&5#m4F-rss{8dyu{MFUm z6BL~AX2A^T6X5Jy;p&&|q;wiiMDK}!)`0#fUz34F0|sc!gg5L5m0=gWygu+vtOz=K z4Mg{HsY&`oyFvag@psTPxR4&U !Qd4BgUP7gd-^vaBiCv=a? zI5?Z>zzXXIni|AVH6McCz*3sMzFjWoKY8`u)*FzM_XFgr`LRvAGB>SJfOD`+Ch^JReHgnpty{6e4smyqTn3c~6<`)%6Jt!R zcR!y*A#Lu~p1#_peY8-jQS!0$dnUg>FB!1Me@~2
`8!w?R*!^&b%vrmOTTK|)@ z@DV*0jV^ulP~UkMa0nDW{-tC9?GdJyUnzxuG3`=ct66O58lrrg-7-<@*Mybh3RMXH z&J=MmX0`+(2-xo-ARITb=OOpF<-z&qA-+CrBk6=AXf`$3!2Xci5a~u`tt9dKvI@#4 za52(Zo!W8qx`E6Jwv4@l3@N&c=j+Dw*!yFk1?Rnhpr?m-I&bs}kG}fff~V_@$hv@W z4CEK+lD{+clsu`LiRc>pm>@Z_^-xoywf)WS=H6s}gcc9|u&l=q$f@v#Jc3oXrO{Tu zQyl8H;i(pJP)DC5d(p{|J~Y1Ymzf{5OOd|n&WdV6NX%I3F;t8={n>p(m99)pqFpUu z_VBoE*eQlD$B0G41bA3u4g!I}`L`OBD@`?^afp-Y1#f!6*BrQG9vd^b(9O3r&q8LY znp4E606B$x+9bB1{})C!q3dLPj*;$}ghG8So?C7Uw*(;DK%G;Yev}xwe(7i2G`z5U znT#Mv#!Pa3XFYJHKjb)p79?mR>0dotXBW_N5%V= D0f26mA3y&?_#WX~ z?aDME!|!$Sb=;n0*+~R%`finHFJ?B@<6im3RRpy_fa?eB4jc#% E=NIU6u{92Q(6)9;KqmRUp086p_mn)hgb4*~+7y|JtIk z4b)Xzr`}F=^8*mU3L+Tb57>U-$Y6sbT%f>#J{@r_=N$QGR?;7kr%dIy1Q#kGk|^CR z%s?>&@NRe&V=S9r;s!AKbK?c8ceDrA`&!(_@UKPw_--u4zD({;P0l)1ud(V_&~4l1 ztVmbD$0??RV^`3%n58p4Av8VUhFI!H4j6C2J3)Y#c^t>`^>#Xc+1rFBi0s-JSD$Ta z#sM1-DArobkxZuX`S7g_d;SHH2krXwPu#1e1MuTt(Uw8P;^1xIHyA!Q6^n{%_Tbz# zo2|FzK0*vXVF1T6OaNJ zAY03KR#Q $?ULb@Gh%PfXN4Z9Z+byda_!=9($r_9!moqW5u%@s;h>Q`X<)U zg}69&IlK%gvjB0L0QI~eNb5}&rF4-Ar?4S$?TC@s4vzOdkWh`d11)}TPoz=0@HXX* zvu-ghi$!23pg6zLaN@saXF8l7sW-beFb^(VQD8IlU_F*TLURnRiQ{oTi+vSw!T@@% zV8l-MMR9d|_bZiHj&759T-ic?%XZKAF~U!dr54O~D{gsF6-ONe5S$D}89X0nwA^C& zd2gi9V*Rm68t|M}gYwNVajss5)*>CaBDgQ`{HF4`?P7UD*#V}c+D9z$sjTyAAZrOX zZ}D5>PfV&Za{s$x^7Fm{ldKW20)Ph48DW6@QrmDjO)ax%MGP!{<3jB2m-;I9Bt@)^ z)CTu{1Wm<7;!Dp?J6J9>>E_2^y5)j{pmVoby3 zdq=rH=_8io`9IR<=&aR(yJk4`ND+yji7jd7I;8HLO5t}6p^AjT_vQCo8<8>m_OF7^ z!?x^E|Ly32hu8qa=PgMW=mBi-{~54WE`G;6eUk9Hr0n$@i;tXm^ZCDQ^xVnuLhug9 z#EWST^LKX7-tCkY4s7A1Ok&-9iF-0|4&uOd;DS0}jkRvA WwMf@P>}J zUxF-fBx+{FxwRWT)7W=+d^`AE?)=Km%R0brO7iQCSErdjyTT _$5tzEIdxQHn%I)vnk{EEl(|1_ zvbpE^B`)WvC_nT1d?E3-!ZQkPZcJG?>2~^!f1-DSgF(}WcedFy3NSg!?b*k=Vn>=~ zjGVETsCVG51kFjQr4k=MK94P^RyTb5_0gdl5_j%tuh57(@wWKgCf-UXMbP}^c3%wv zCzUhJ*UNQRP1&AwDY?z-pJ`0=4wjabT|InvA|?kv{_wL#LqL ABq51veE0I11OU5mI{i#%I>I3iXHck`zSanZJuLA1gLh^q3g$1X7qc`;*_I6%W`r zSS2k#xOlik3If*~fhK5qe1TnS(3I^$;F>xR (-mOt1v})8UZSB2kD~h5OwMuP@nlX!_)K*H(Qq +yDqo2|5_xb&Q|L4hZv`2*8x!3i6UFUheuS7i5dO${eofr!Xi%eBTQ5OpfXAuhv z8;|e`@QUq9An-pHk+X`C8x|IM2j(AkA`dwu@FLYqrN=MzoUC7ZK6ACg(sQ(Re&+Vl z>M7mO4=gNJELBChN3YU Ly{hLI z2|iCRz?r`OPa!QRSslb`+T=AKX*A*4`5yEnZ7#Fw-rDtPY2LpdPKMSE9|=9E&7u^r zusR?-g(iX56p0ev!1(VwyA6YwqHJ0Go -^*38fOgpNET?EEmiS+9Ipu1j1WzITf4^~5274Gsep_*J z=_g)I&B4Qn*W+vC?eM*}Gnc)yYcIXXZ;dpFNi~0=7`o5V8k*QpQ%@}`7)bkbbZbr$ z{qX|#RHkF< 7XedH~JudrwvroAdH!S`Bo@kq)bQbfSLqMEt!v9dOUF2v8Y6v7Ne+(Eye+ z%R|=D@9NE<@gL4~!(pg4Zw<`0v|4)`xTsW;x?cUXE+0_)fERBT@886f+r~a+Po3f| zs)hL!Nj%`sKHDeC6HdeNl&=YPH6{`n{A#S&h4GMh%u{dp-@|5WtTe;y215vqv%G1n zP20S$%C;2n0f$@8IP-zjBw%BDHwqp;;Vy(zQ)j1kg6wQ%;^?d$Pu>*#bd*4RI7g|v zpah8&hV0t#IrI?V*T `gSD-<3wDZe3AARHa~6)5Xnkr}YmH0y zCQ(vB^Hctwaq 32I%Y-ddfGUiw`YfcWt(+8>)`5* zYt236qPvkRG@>@}q=*b^F_XI@j0smX%WDp!=h?5sdhwI1`7p67G^j4U@MkfX;? 8wo=w%Y^07 zOwDwu-$Hy1lS2I>{FJ@t-I#bRCQM~Yg;U|}yM2Ean#}1SgSj<%iGgk6;RZ94TZK@P zrLcFtVyp=kG%Ejg=YjteTb=DLBfq9ujZ(t3(!hvr@CTBHnqDCkU+9 J2ZO) zQ`{|M$C B#~_44m)cAU=b|9bhTusnNo5gbd4CtNG* zO&+6iIer~iKz1au88qdBn_AA?)LJc!n*D27j&(4|kEq3oD(=f(UpsNxPVYK!?g$S#gyJgDvSJ^1m) zLQc%ta3*x+dnT4Nq!TRTZ>lAVId8FaA+*k;?awdv8Q=@hZtdT@pd#~UU2#&dg&XVA zVhJ9orvA(=rZc%!(c2ta(6!g!U;uIs UZW^Zglj?NoLvbA_A?Kfj$zs7&b)2W9sZGYzfa-7<))G f$Y^WrSD@b8#labRJsAvkiP0za7da z#N;GyD(6f76zy~8uC{2f0Qg{Xva}PgVR2990m}t5`T{sa#10Q?V_W1R0D6G=@Jy@R z#No^XFgz;L|AGPiRL1`JH}o>-v|1-w@hmC1@CSr6F+ zbNOf znz#ub47&X_LN$Sc>k!Fx+Z2~>1Ju%@PLn&Le>JI{TvRLWfVO320fLG~n @VjOa#NI2=)c~5=$>saw9+!icg#L{;}G(jO)t-Te+x3MwXA}mxO5jBd*Y+2g) zF5+usLVo#K1YiG|SccH-vn15$XETEP#Tj_;XEOYnn?IyDRP4b=37!s34mXEBA;#Kl z^iRCtgq~o7yih`^4>Nph9882>3=LGBwHsc%LNLgn5%{fiz7oi&%p!E=+2Qsu{9v*a zeqyKtK`<=%-;Qy5JOn|!&O{^L43C4PSNcn347!o=Mca4T8PW#oGHonUnhTcP;F+za5_TreJrIe2Za{*Lv5dogrAKl9jbcw2H@itx@ zeG7PqDlLF!r}XR^|M>KPX(6Kh8~4xPFTz^4zooo x-hrWMT jbB>HYSe`xGtoXq;oHy!%uonU;|=Qsq_{v$J%kSWv{|XId&N zUjwaVjytnA)cV$X_qrjdj!Y;v82ut9Xmrr?;$V2M6+)+@h1wuNp&$zakb~ic1A;d; zJW9t2dr&_o35LsCPT?%%C#jZ-3~+t|*aZbPfe9(_`XTQKj@AqnnF; 2j&SwMZDl4QQXpqG9*>Y_sVxi0@AM3U0Db>m^aEBN?=#oNG!>i4z=oN+J} z7~l}@65j8(#Qx{V)4JM$xIwH!?qpISrS`5MUt>Z~X~*t>iq2<<-e|&;c_BgZJVo)7 zLFrcadJC=4{vnHF-y_w_ZSDdSAm(sbnMv5aX|u{{GYH jwRV zo^+01f6rTlMX~o<^E$g!KsTeAJOUa$Dt5)MUsie@pwf4N=59v@c4eiH5d5Cw(MFTY zxct6U_P#jI#wLW9KgdfHSN)HQ=#Pu3@xT^7CoTLd>#?%i<^Gzq{!vk#53{*!OhUYx zd^kpK_ n)v%C5rsKgSOAC zX@U8Wca5|9&f~l?rPq{05MnmmnyoKs_YzI}IzurxJcvQ7Rh57^8&3^eHb7mo9sg!4 z10CN8q4NVzL2M6>P?s!3iS3x-bHVeOJvB9w+9IR6Sti-+(i#EIZnb9;M~;lTZR}}V zIjpM8H6(R)m`$!)03@<)`|D2OC)v-#M-YG8heb!}S(ozB?s_aMiV1d7D98$ }h0i_kwMt*oeb{l2_akA^4#zRPa)zpSr-*90GaGoQEzi zT!j!YjO`L$kGtl`xXa#W24)wZ9>@Gv3{RNB6WhkkZyfKOe)K}CtvC-KU0yE*;7rzY z(9{2N=DL|;)5@;*bzh7=Ue12WA1GCIw(*9SWvK7Xr0mKo;AyN|v+AABo_Td=(TQD| z(;(jF-@d|O*4ZWTe-{hit2Teg>_2X*%c62wAyVIt?$>{yOxh<8SK2N8K7Faro38&k zq2?5b7)7O99qlF^q%60HLo#kcsyZ_ `m~AK0GP)r}=9iZ_)jsY_tL^MmCmP#dG?o~pIapaI%`8aW`vAoZ+d~e_ z+bC@sL)F!{_gK0=+ ~fE=K&GZy{2Z5<%c)ulGaB*@=eHBT hy#cg@%Y#H^?YVy!_MLcKnw3bM@va z;5S=!sGcK=r>Epf5z=RpGDb#?;K#oo^I1TZHg;B_3D&qr-qMeg&K8oP7yi1`$ NaJIm@79q#(ZL4J54z+o z2mTIla=s8 TN62ygPH(~;U-B+XN|U-wCJ#c#nbq+;qJf(5iskzwlBU0=tCcpl zJUs>96NFjppxgv{M)63LB{9XThhUi|`|e+E-zqk6e3upa|40tDF){rHFdJj`sQ(jE zhw{_ekXPCUj!-t`T7gu>M5VD=q9vX^&x`)njsDxd^vD;0{JLm6ZH`0jpOJ?T9z z5ZZmgTuygpVfuZIBU+#KYuZ *Ja7GQGZ6tN6~#_`bV}=)amx zI($T{U)}?19v!**jFWJvS{j_d|Mg-WD1i6(9vscx?0SCZj@HM_!eJIt;8s_9SNGBh z-`wq$6B|$7(4(1l_17 );Lzbb=oka4(#98#I?CNbacG*CKV~cHwz UbuU%6)D>tU&4 zSg3oR%2@oYn*^-dX 8*k_g-v^h)Mf8cHxzt3mo4f2|Uw_O|7OIj(d> zK+3Ys0GL@48XoQ0xO;FYiHT4QwHEL5F{UfT{^*_!(*Zb4;F8*}AQX(e4j$* U@WY8aLeFP8yjmXY8Sz*hou&?B3fcCt<+< z%S~ K8VcY2WtfuYF8GLUaB+zSV(`eEfU!TIkK|#$rt-H9pDtcV^)@sg;tx+Xrrh z)-gz`Dds-9j~}HcSw4esGX;j*o*>`Q&YAmi+FJPHT4aFw*+x7}DzEOj%&A($eHY05 z!;7Q1f6Mh*AU|0~Gvd3DASniB{vh+<;ZxM90{Y13qo0DylPxUKT&3Buk~WK(+EXNc zpn(#)dJAOk^E!Y>fCuo76=eNz(9(>>;Ap_1$*kcLn+EDo{i&CUFzBUy5|@bW(+mYI z;Zx3%*D;X(6Q1444U}aGbY4;4X~DQLym{Vve5M6Z58(6Leuo$@N9Jteobj6s88c;C z?eP&!0wYY#7P@s%OXp7Qpgq6wX>PV(npuBA5AIvvT%4VWyL0#W;&GE=^P#cUXHC#X z&!q0ci6rxa^a(pmv&>xkEQ-wQhtL?J7Irp&>Q6t44m>FV-95=Lp8cfIQjVM)|I~Tj zzwLTdE54aGFQecMYZEaa#hHH)PTRYq*3$XmB|o1OgL+M-`a8g%4X9(^=su@>Yf<3G zJjyN?*I+}|_&D>?R8oKU)BcZbZK1BXYW3{r*6U7J(?}(RvH5&1tj@tEB4Jw~tW1HT zyXsKo>f!f08?hW$Qf-)gCpo&Y&lKBFrJxA<5*cicLZiaj;%d7)@C%mjEx2=|Em+E% zhP0Fk@{P%9!Gd}71SxRV>}wZo&N!$yApxYbz5VlhDufIb7H>K%DVx6vy;pxHj_+6S zR07Wume*auo_~@ZL*sZ0=az(uv&}S*f;G)&GUXlhZ+ kS~T~A3Y~FUuCTEx@Ljy6{;7%z#LP_ry<~oPVBz&vQ+JZf#;4xa zX7Ixpzvfax%l?71cwmV`lumZ3pX?7REu{shNpZ&yNjtQZh#JUw3cK5n8fg*TSSCz1 zUJC3U$@h8bQ&9We*$17^2OS))KhzA{`yyl2{AHY{?$b2Z-Te!e*%l+&pXpo+z?lQ~ z&Rn8@{L0)b$oRp-5eZu)7Iot (X?#qL=TD-5u D*+)mM_7}pLQ zPEIW@&IF9ozJr~W*X{bk-)pEyNj*d#?dk`lUcE8imhy|q>0Aw>oc>G}Vt(FRKhItV zR_vY4+-n}*E8k%>w|v)^nCE)8zS$3(fQFdC`*=9D4*TQ 86;q z?`<+ZZTPOwog#^B8PDIYsf<}ym7$GHdB6Rk??c-Kyi g2mZR__~*?tNR?i{>`O%_J-L z|8Rk|s!-kl8n~P68b9~_Tu#a^zadSHPj6 *Bq%==>v34>M_zhjO;G;4XSd!QGM zt{Wu@02F@MRhXU@A)vfu)ZSN)iB#r`_swo$@3GuSK-@>qB>Gpsrq>&(8EdQ2aPObc zLxVqLq4x5L1txVf`m%4IydEj?q<%I@CG%9ZT1b@V`zq^Aga|#oVdN+6o)3U_;g#pA z^!;(ShKudKyj1+$x)6EkV+yjc+#WN69f73! x8T;ipLkBN?Hf z4|sJ&S6hjVd6-T&NE7sCAY+LSPMo5?LrvpE4(9>3_RB}e&iFE=Nr&qn1~j!dys~9` zynYiYCN$1n?e`Owc(QMxAnuAJAJ?vz3RZNiV4rBiewv(W^#E*PjV?q~yHU(~97vxf+}qtVzEXa$S5sr`Y5 $)9?kPCPmerMFoS5`2?5Meg8wT)h|T8|rWCmz2c~mW=sIYoty)jTL|W z(a|9#O_GC?|9n!^-oheN&@btEY0^VVK!39G-}F|op6GR6A2p4Pm`Xu@Mg%3F`YP7l z3!UyFxX4Lz3ZAxrC=OJmo~L*`jxGh^!nQqz99g1ottQd=5HghMD{ZZZZtwLxLB`NZ z>m7rMYpX?{Fah4zr8|bPzcwDtM&A5Cb5He>dvxsHuyZP;#2r+?jg`;XiaaTUR|?~A zm()F`Fge-dusz jao(uBTTTLP1&U2)Wv7vfs zj7bX_;Sj6ln`Al Ld;H^6h~loRH~q!au* zYS4;+k-M8E2K>~)tm+|nzN4sHAi(?szoU$OCNaIUWbv&m&eVwFeCt|5LQ4+8FXs+_ z5Z}ZlxQ2?h4I?kq99BrsR4}_EVk8|VKubbm6mQ$Gfmw;N!9s{cr=<9pw7@s${mFL~ zV}>^-?7>*{IS>oj%Y1ylKKDk1VT5e`O71wWd>0UhTnFG =+5jLxN9o-W8F zqKYZ8y-x>7lh+ZqEQu~@#n$jW*)vq(z4*st7YTq?e*2lpbj=3U%tsqNw3x`Pli#fr z`;=E8EJ$~qo~t3w%~*o}>MhHFKe>arAH0~o;CGEpAvP~rIvaQ!>+`cgi|xq?G#A+G zN8OTh;$RDq?&)nqr+hc@cyfXTr^V(^68&RD+XMV5PWCiOW1xbEpRCa9UiSzSPVdzC z1qZr_HdZ`x Oh4JCfUOX)m7ny*QdnRcdhg-*4@cl{X4myhRl7HnV`KC&X&||tf~{VL9u6l2t 6V{84R}$llpoh9_-O576|He$NG32LTY3@Q!_X6WhVJFqYYH9Q2 z@MtZT!L7GHho2;ze46W1l?vo-R{F(#ia1;IEy~uKfu63bZpo;7dO?s*d^92q^LY=U zlib5|yLLa>`k#{UE#fA)$ZlAhN9puTl-(%yLMkWKOi-E-&(IoFO=vjuPZ-iR87(cT z;mk`Z^1>iPdBaOf{Azj6w__-7)o|p5Idqw`be?ackA%k1KOQaNoAl`!J?hjV9;^!| zY@|9kio6qd>d;7qWF(C$TJvEQAmCiI6a>IyZ1JG!H+L4V0NgoC`ci7yXkl+8kJT~w zESfj8uzftzxB4LK-tlg@Un-HX%ak!Xq5oGd26pXvWX;8!OYU8ZF;PJ7HUz7R7=3(0 z^Xn8U+Kb&lB}r} MUmhe)C=|aenq?ctumEin z!<+VN@}qYG4ve|ON}Qs1K%8Oq$&B4QN)t;09%$^^+3UsW!JP7ti9<6IKqq}xA!~9* zGP~FkS4LC7AMh<)sq97({vux^QRW|2r5KM1L_lN`2ovtw%=f)mSuvI`aHz`HwEBX2 zKmsn;jm>p7iEQsYpe{KE(wyJC+W!B*t5poIhHC>42(B^&lCc`M*$b I-#WPv*Qex{4w{Hj!aS%yze%JqM>a*IS GE)ol*&jhgF9SrXJI7lsT9mo&vo zo;Y?i*07L|%V2GxcY4Tm>t4MqpNDhtCYl6Wt`m&%B0=L2yOUCd_w<(8F8fc@7O$+* zkbxI$Bs$yttNaDfzG;^vyZ+xK6W_cx72LX$Jk)xYi&WnQ5` 5FE4IAW?;#qhG_dl(FMaAN1)?R^Feb!|M78Hk9ECEor!D zEy(8kVF4WrK}GL6bgLE-ta>ft`I5=YzBY!l-WrLYIAeax-!eB|ywWY?MiW2!ZLjVG z-QFqW%MJa~i|#>8{*TBjC8rC2G3{HAfIk$h@3|hoM{>sh7x29O2XB0Q&;R2oG!uEY z?)(zRWOk}RG1G6gyT*x@Qk=7|wo2fkKhx >^qC~{Nnu4eLVo}_BTmh!{5jFgv%JIkL zzEdL+j0b(68pQ@D0S1cgE@R}_IUvV0N+9M(c{IgQfK$2gYSs`TwM>eOkb?U*0?j!h z%BZW)k>bAsEW9WzW^0{)eC8cYOzYj*ArVb^*fWv?8R{S_i!m)`7>BAUs7J-hn
EUc}AW!R2VcF z-dS7)qFbp-?MvfTOY9tpSx7mKdx-8Ol^%fG QVtK1S0sYSNM6TAB$Ss=d9Hi}Z2Q%0*QU2<*v78~1l;`g?MZq22rL z)}CMY?hz^+!I73_c<$zy-+o&b-7fRau*v^slac;y63v_H#&+R6_zomI#&-Etvs;N% z@1t017`EN70xB#h5g~K5m4{z YXKn|j|PHxf4Dd>|Qt zT?Ku--dJdAi^+O~zFRJrRin6*se0{nH$5IWuPedM*S+yeuDv~XyVAaXuv*VB3YC5` z6K9rx*JAI1a#?(mqKSJ#7qu;M*NM}>N|}5Gu@JFVtB(=aH?_1Fv+rT0YW}gFkN5cb z9`*aK&ZiKSiAMv7d-#+RWZ!jlDNSBOm{p=)+wYFbcVmy98%ymT){gdhH59OBz>+l~ z+l=)r@c)`vfIb~T^UzN0rETMCym&}9x#;W*hZmUqbOV?uhG8PO^N{vCUHSUyUct4h zKV{py!=?hi0MzM-i1cq?wR20g{>BSC*V`(FX!DPL{nre5u<&X$|F$+uhK25}MQ-R! z-PrCGD*i|jG>|K*Wi#VL{g<_Qa05`Da!+0##SRq5XAR~x(-M>m`WRZZ#ceQ~tL5Im zx#-1EQr_|7ZzvA>SRkuI9?shErMywsOL6cGka^)HoFaAdz|4~i% 4(S#k+kz>ZGy(vX(ceqPw|*y_?C} z|3oOh{bBjk^<}cjSBA%75HnvKC1umUT~&Q!&vKTUUkjR}KNkW|_zWNG5wx=L8S2 2&7}=)!@^DPM&Qrj^|!EXx(&X+fav)b5S#7%*s@?FM&jFYg;igY4neh& zjFjne@2?7Q{&E&o EcSVa zz@##_q*69QSW%5WAV0|3O5E!!m&>A%pXMRfnFKkx{6^&g`)B z`AM&5QlSa@%ERjfF5C11J^g?)4HDsR=I>e@oupxtP+403rsVvs&)XEI^o3d6Oyv2N zoEM<%Bc`vj-{lN9$$KrbROMPv1)C8UeT2p;K$BEf`7aoNjZA5RS&!u34_*i5AUp?A zo`1zkcJW&QzS&FLjNd+qPC*+`JfRM5H&LC)7~2JGM_Vvf&M^-OVTm$xpcLU;2E!dy zpxq66188LQs4!_;(HZgX;6LEtJN=X$qw?%sU3m+uRts~SzAnCq0rnT(TfezD^50y9 z2Is-fwN_Sm_ee<=`I_X>SAy@UW?RV&vKnjeS6;getg^HPu>dpk7-(N?*j6#x8eY0Y zVwKasNEDP3HSl?fmeewqVvPx=*}o5D?k|=C6J)iGH#|ifMC K;8A#%(2Dss=#7THpc zdf`jEGkaeSDzSr fcbZ_Kd27^f2-35i(U`f+xa%F#6Tn_v9(M zH`GG1cZlM~THOaehi!e5MP{mUyWR8CcQuf1Ro^--fwi@UAmF^h7n(IUhCm>lmWm(C zu*|MZVfvJrBOYO}cw663GYyZowSIZ%n?rYU(YOdt#`YDrs0;3);RT>6ED0kMNhZ7c zMxWHD&ds+3NW=uPAl*0|1N`9T9VsaN>&E6GHxHXIDO-JHdhxKf7Yh4sL-|YEJS6w< zk=`yW?fLZ_RHcRh=(%rM)6>)xIbD1I3ZV^S*NU?_i|(GavjP9Z!$LU0W!BiOZ2PLz zOjyt0zP0HF)-Uh~S=?M0q?ixu^0#4s5%PW({y)tonkfneZnqcjn+x*nba&oy$Uo#L za@8^y^0ydO|9T*2z5lH10i)9Aqp z))tZFCZD->{p7H~M%Zsany$jlQo-{O->RgDw2NKc0`zvmbH~&B$FXbKmw #Li4rggK8qawqc?x+OD}~Cju>f_5$J5 WWDLKM>+HGR+r2gRf^nT>^CMzYRTRAWaP_(i6_tm>L3?-9!Yuu7K1yFX zbOxH(BOm6K?}jt;PAIf@hTvb4G2f)tRL(AR1(lvv;w8yeJ0c;S@OqxPT;OgN2f2w) z2_!3Hvy`g*+2(;>GK`_UEZ+Zh#;{*q)vY#-=gJEht;iSglNiypR}!_ekh1YC)RGnt zi*pf|H^C-vkf3Zc$MBX2pcLJbX=kheY2AlM57Gdzm@KbB%PQd&hrqao!-I>?FTc%5 z5aiXwXv!2zHI2uTdxdRrK8aYdh&TY6qpOmdt5igVOwma!pj*TU)*g*FD`d42PQGJ& z$3XfyP`vF%QdoN9RiyRTuR4<{(@-Q2J-*)|x9!|QHL3Z^g2T- 8RPZVN{Dd{a_eTs|(h(YuHF*a-2|KMy+yIHY0QvQub_DeKcU!pM(gGT&vC69(t z`C9__LX257*eqKOt`$NIzd+**%i{lcATohs*!_RrgY7j9%sEqejldrwuv~lw?qnMb zT;ehJLQA) 8zAK-^%Dy&W9XzI*IPtVN zjPKkt{vN^;m=HYLFT`DpO)^-2pZy-3t NuIIrQq+=b&Je5`liYQ8FJqd>f^#=;+3M