From aa35d5b33cff3f0d5a98ce5639cfb0646e96880d Mon Sep 17 00:00:00 2001 From: fishu Date: Mon, 11 Nov 2019 18:42:47 +0800 Subject: [PATCH] update readme --- README.md | 157 +++++++++++++++++- .../{role.yaml => cluster/cluster_role.yaml} | 0 deploy/cluster/cluster_role_binding.yaml | 12 ++ deploy/cluster/operator.yaml | 31 ++++ ...is.kun_v1alpha1_redisclusterbackup_cr.yaml | 7 - .../backup-restore/redisclusterbackup_cr.yaml | 21 +++ deploy/example/backup-restore/restore.yaml | 9 + deploy/example/custom-config.yaml | 28 ++++ deploy/example/custom-password.yaml | 25 +++ deploy/example/custom-resources.yaml | 15 ++ deploy/example/custom-service.yaml | 9 + deploy/example/persistent.yaml | 13 ++ deploy/example/prometheus-exporter.yaml | 10 ++ ...n_v1alpha1_distributedrediscluster_cr.yaml | 2 +- deploy/{ => namespace}/operator.yaml | 2 +- deploy/namespace/role.yaml | 95 +++++++++++ deploy/{ => namespace}/role_binding.yaml | 1 + static/redis-cluster.png | Bin 0 -> 26683 bytes 18 files changed, 427 insertions(+), 10 deletions(-) rename deploy/{role.yaml => cluster/cluster_role.yaml} (100%) create mode 100644 deploy/cluster/cluster_role_binding.yaml create mode 100644 deploy/cluster/operator.yaml delete mode 100644 deploy/crds/redis.kun_v1alpha1_redisclusterbackup_cr.yaml create mode 100644 deploy/example/backup-restore/redisclusterbackup_cr.yaml create mode 100644 deploy/example/backup-restore/restore.yaml create mode 100644 deploy/example/custom-config.yaml create mode 100644 deploy/example/custom-password.yaml create mode 100644 deploy/example/custom-resources.yaml create mode 100644 deploy/example/custom-service.yaml create mode 100644 deploy/example/persistent.yaml create mode 100644 deploy/example/prometheus-exporter.yaml rename deploy/{crds => example}/redis.kun_v1alpha1_distributedrediscluster_cr.yaml (86%) rename deploy/{ => namespace}/operator.yaml (91%) create mode 100644 deploy/namespace/role.yaml rename deploy/{ => namespace}/role_binding.yaml (92%) create mode 100644 static/redis-cluster.png diff --git a/README.md b/README.md index edb08582e..d4532eea6 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,159 @@ ## Overview -Redis Cluster Operator setup a [Redis Cluster](https://redis.io/topics/cluster-spec) atop Kubernetes. \ No newline at end of file +Redis Cluster Operator manages [Redis Cluster](https://redis.io/topics/cluster-spec) atop Kubernetes. + +The operator itself is built with the [Operator framework](https://github.com/operator-framework/operator-sdk). + +![Redis Cluster atop Kubernetes](/static/redis-cluster.png) + +## Prerequisites + +* go version v1.12+. +* Access to a Kubernetes v1.13.3 cluster. + +## Features + +- __Customize the number of master nodes and the number of replica nodes per master__ + +- __Password__ + +- __Safely Scaling the Redis Cluster__ + +- __Backup and Restore__ + +- __Persistent Volume__ + +- __Custom Configuration__ + +- __Prometheus Discovery__ + + +## Quick Start + +### Deploy redis cluster operator + +Register the DistributedRedisCluster and RedisClusterBackup custom resource definition (CRD). +``` +$ kubectl create -f deploy/crds/redis.kun_distributedredisclusters_crd.yaml +$ kubectl create -f deploy/crds/redis.kun_redisclusterbackups_crd.yaml +``` + +A namespace-scoped operator watches and manages resources in a single namespace, whereas a cluster-scoped operator watches and manages resources cluster-wide. +You can chose run your operator as namespace-scoped or cluster-scoped. +``` +// cluster-scoped +$ kubectl create -f deploy/service_account.yaml +$ kubectl create -f deploy/cluster/cluster_role.yaml +$ kubectl create -f deploy/cluster/cluster_role_binding.yaml +$ kubectl create -f deploy/cluster/operator.yaml + +// namespace-scoped +$ kubectl create -f deploy/service_account.yaml +$ kubectl create -f deploy/namespace/role.yaml +$ kubectl create -f deploy/namespace/role_binding.yaml +$ kubectl create -f deploy/namespace/operator.yaml +``` + +Verify that the redis-cluster-operator is up and running: +``` +$ kubectl get deployment +NAME READY UP-TO-DATE AVAILABLE AGE +redis-cluster-operator 1/1 1 1 1d +``` + +#### Deploy a sample Redis Cluster + +``` +$ kubectl apply -f deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml +``` + +Verify that the cluster instances and its components are running. +``` +$ kubectl get distributedrediscluster +NAME MASTERSIZE STATUS AGE +example-distributedrediscluster 3 Scaling 11s + +$ kubectl get all -l redis.kun/name=example-distributedrediscluster +NAME READY STATUS RESTARTS AGE +pod/drc-example-distributedrediscluster-0 1/1 Running 0 4m5s +pod/drc-example-distributedrediscluster-1 1/1 Running 0 3m31s +pod/drc-example-distributedrediscluster-2 1/1 Running 0 2m54s +pod/drc-example-distributedrediscluster-3 1/1 Running 0 2m20s +pod/drc-example-distributedrediscluster-4 1/1 Running 0 103s +pod/drc-example-distributedrediscluster-5 1/1 Running 0 62s + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/example-distributedrediscluster ClusterIP None 6379/TCP,16379/TCP 4m5s + +NAME READY AGE +statefulset.apps/drc-example-distributedrediscluster 6/6 4m5s + +$ kubectl get distributedrediscluster +NAME MASTERSIZE STATUS AGE +example-distributedrediscluster 3 Healthy 4m +``` + +#### Scaling the Redis Cluster + +Increase the masterSize to trigger the scaling. + +``` +apiVersion: redis.kun/v1alpha1 +kind: DistributedRedisCluster +metadata: + name: example-distributedrediscluster +spec: + # Increase the masterSize to trigger the scaling. + masterSize: 4 + ClusterReplicas: 1 + image: redis:5.0.4-alpine +``` + +#### Backup and Restore + +Backup +``` +$ kubectl create -f deploy/example/backup-restore/redisclusterbackup_cr.yaml +``` + +Restore from backup +``` +$ kubectl create -f deploy/example/backup-restore/restore.yaml +``` + +#### Prometheus Discovery + +``` +$ kubectl create -f deploy/example/prometheus-exporter.yaml +``` + +#### Create Redis Cluster with password + +``` +$ kubectl create -f deploy/example/custom-password.yaml +``` + +#### Persistent Volume + +``` +$ kubectl create -f deploy/example/persistent.yaml +``` + +#### Custom Configuration + +``` +$ kubectl create -f deploy/example/custom-config.yaml +``` + +#### Custom Headless Service + +``` +$ kubectl create -f deploy/example/custom-service.yaml +``` + +#### Custom Resource + +``` +$ kubectl create -f deploy/example/custom-resources.yaml +``` \ No newline at end of file diff --git a/deploy/role.yaml b/deploy/cluster/cluster_role.yaml similarity index 100% rename from deploy/role.yaml rename to deploy/cluster/cluster_role.yaml diff --git a/deploy/cluster/cluster_role_binding.yaml b/deploy/cluster/cluster_role_binding.yaml new file mode 100644 index 000000000..19673ee10 --- /dev/null +++ b/deploy/cluster/cluster_role_binding.yaml @@ -0,0 +1,12 @@ +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: redis-cluster-operator +subjects: +- kind: ServiceAccount + name: redis-cluster-operator + namespace: default +roleRef: + kind: ClusterRole + name: redis-cluster-operator + apiGroup: rbac.authorization.k8s.io diff --git a/deploy/cluster/operator.yaml b/deploy/cluster/operator.yaml new file mode 100644 index 000000000..f4c73bb2c --- /dev/null +++ b/deploy/cluster/operator.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-cluster-operator +spec: + replicas: 1 + selector: + matchLabels: + name: redis-cluster-operator + template: + metadata: + labels: + name: redis-cluster-operator + spec: + serviceAccountName: redis-cluster-operator + containers: + - name: redis-cluster-operator + # Replace this with the built image name + image: uhub.service.ucloud.cn/operator/redis-cluster-operator:latest + command: + - redis-cluster-operator + imagePullPolicy: Always + env: + - name: WATCH_NAMESPACE + value: "" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: "redis-cluster-operator" diff --git a/deploy/crds/redis.kun_v1alpha1_redisclusterbackup_cr.yaml b/deploy/crds/redis.kun_v1alpha1_redisclusterbackup_cr.yaml deleted file mode 100644 index fd9e18bef..000000000 --- a/deploy/crds/redis.kun_v1alpha1_redisclusterbackup_cr.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: redis.kun/v1alpha1 -kind: RedisClusterBackup -metadata: - name: example-redisclusterbackup -spec: - # Add fields here - size: 3 diff --git a/deploy/example/backup-restore/redisclusterbackup_cr.yaml b/deploy/example/backup-restore/redisclusterbackup_cr.yaml new file mode 100644 index 000000000..d881435ec --- /dev/null +++ b/deploy/example/backup-restore/redisclusterbackup_cr.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +data: + AWS_ACCESS_KEY_ID: dGVzdA== + AWS_SECRET_ACCESS_KEY: dGVzdA== +kind: Secret +metadata: + name: s3-secret +type: Opaque +--- +apiVersion: redis.kun/v1alpha1 +kind: RedisClusterBackup +metadata: + name: example-redisclusterbackup +spec: + image: uhub.service.ucloud.cn/operator/redis-tools:5.0.4 + redisClusterName: example-distributedrediscluster + storageSecretName: s3-secret + # Replace this with the s3 info + s3: + endpoint: REPLACE_ENDPOINT + bucket: REPLACE_BUCKET diff --git a/deploy/example/backup-restore/restore.yaml b/deploy/example/backup-restore/restore.yaml new file mode 100644 index 000000000..a25bc23e3 --- /dev/null +++ b/deploy/example/backup-restore/restore.yaml @@ -0,0 +1,9 @@ +apiVersion: redis.kun/v1alpha1 +kind: DistributedRedisCluster +metadata: + name: example-restore +spec: + init: + backupSource: + name: example-redisclusterbackup + namespace: default \ No newline at end of file diff --git a/deploy/example/custom-config.yaml b/deploy/example/custom-config.yaml new file mode 100644 index 000000000..09ce59a01 --- /dev/null +++ b/deploy/example/custom-config.yaml @@ -0,0 +1,28 @@ +apiVersion: redis.kun/v1alpha1 +kind: DistributedRedisCluster +metadata: + name: example-distributedrediscluster +spec: + image: uhub.service.ucloud.cn/operator/redis:5.0.4-alpine + masterSize: 3 + clusterReplicas: 1 + config: + activerehashing: "yes" + appendfsync: everysec + appendonly: "yes" + hash-max-ziplist-entries: "512" + hash-max-ziplist-value: "64" + hll-sparse-max-bytes: "3000" + list-compress-depth: "0" + maxmemory-policy: noeviction + maxmemory-samples: "5" + no-appendfsync-on-rewrite: "no" + notify-keyspace-events: "" + set-max-intset-entries: "512" + slowlog-log-slower-than: "10000" + slowlog-max-len: "128" + stop-writes-on-bgsave-error: "yes" + tcp-keepalive: "0" + timeout: "0" + zset-max-ziplist-entries: "128" + zset-max-ziplist-value: "64" diff --git a/deploy/example/custom-password.yaml b/deploy/example/custom-password.yaml new file mode 100644 index 000000000..2295fad8c --- /dev/null +++ b/deploy/example/custom-password.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: Secret +metadata: + name: mysecret +type: Opaque +data: + password: MWYyZDFlMmU2N2Rm +--- +apiVersion: redis.kun/v1alpha1 +kind: DistributedRedisCluster +metadata: + name: example-distributedrediscluster +spec: + image: uhub.service.ucloud.cn/operator/redis:5.0.4-alpine + masterSize: 3 + clusterReplicas: 1 + rootPasswordSecret: + name: mysecret + resources: + limits: + cpu: 200m + memory: 200Mi + requests: + cpu: 200m + memory: 100Mi diff --git a/deploy/example/custom-resources.yaml b/deploy/example/custom-resources.yaml new file mode 100644 index 000000000..0ba03edbc --- /dev/null +++ b/deploy/example/custom-resources.yaml @@ -0,0 +1,15 @@ +apiVersion: redis.kun/v1alpha1 +kind: DistributedRedisCluster +metadata: + name: example-distributedrediscluster +spec: + image: uhub.service.ucloud.cn/operator/redis:5.0.4-alpine + masterSize: 3 + clusterReplicas: 1 + resources: + limits: + cpu: 200m + memory: 200Mi + requests: + cpu: 200m + memory: 100Mi \ No newline at end of file diff --git a/deploy/example/custom-service.yaml b/deploy/example/custom-service.yaml new file mode 100644 index 000000000..76d561d5e --- /dev/null +++ b/deploy/example/custom-service.yaml @@ -0,0 +1,9 @@ +apiVersion: redis.kun/v1alpha1 +kind: DistributedRedisCluster +metadata: + name: example-distributedrediscluster +spec: + image: uhub.service.ucloud.cn/operator/redis:5.0.4-alpine + masterSize: 3 + clusterReplicas: 1 + serviceName: redis-svc \ No newline at end of file diff --git a/deploy/example/persistent.yaml b/deploy/example/persistent.yaml new file mode 100644 index 000000000..9699185c0 --- /dev/null +++ b/deploy/example/persistent.yaml @@ -0,0 +1,13 @@ +apiVersion: redis.kun/v1alpha1 +kind: DistributedRedisCluster +metadata: + name: example-distributedrediscluster +spec: + image: uhub.service.ucloud.cn/operator/redis:5.0.4-alpine + masterSize: 3 + clusterReplicas: 1 + storage: + type: persistent-claim + size: 1Gi + class: csi-rbd-sc + deleteClaim: true \ No newline at end of file diff --git a/deploy/example/prometheus-exporter.yaml b/deploy/example/prometheus-exporter.yaml new file mode 100644 index 000000000..007381c72 --- /dev/null +++ b/deploy/example/prometheus-exporter.yaml @@ -0,0 +1,10 @@ +apiVersion: redis.kun/v1alpha1 +kind: DistributedRedisCluster +metadata: + name: example-distributedrediscluster +spec: + image: uhub.service.ucloud.cn/operator/redis:5.0.4-alpine + masterSize: 3 + clusterReplicas: 1 + monitor: + image: oliver006/redis_exporter \ No newline at end of file diff --git a/deploy/crds/redis.kun_v1alpha1_distributedrediscluster_cr.yaml b/deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml similarity index 86% rename from deploy/crds/redis.kun_v1alpha1_distributedrediscluster_cr.yaml rename to deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml index 14469e586..d9c38e17a 100644 --- a/deploy/crds/redis.kun_v1alpha1_distributedrediscluster_cr.yaml +++ b/deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml @@ -6,4 +6,4 @@ spec: # Add fields here masterSize: 3 ClusterReplicas: 1 - serviceName: redis-nodes + image: redis:5.0.4-alpine diff --git a/deploy/operator.yaml b/deploy/namespace/operator.yaml similarity index 91% rename from deploy/operator.yaml rename to deploy/namespace/operator.yaml index 19366e547..e4aec0982 100644 --- a/deploy/operator.yaml +++ b/deploy/namespace/operator.yaml @@ -16,7 +16,7 @@ spec: containers: - name: redis-cluster-operator # Replace this with the built image name - image: REPLACE_IMAGE + image: uhub.service.ucloud.cn/operator/redis-cluster-operator:latest command: - redis-cluster-operator imagePullPolicy: Always diff --git a/deploy/namespace/role.yaml b/deploy/namespace/role.yaml new file mode 100644 index 000000000..a32cb4e48 --- /dev/null +++ b/deploy/namespace/role.yaml @@ -0,0 +1,95 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: redis-cluster-operator +rules: + - apiGroups: + - "" + resources: + - pods + - secrets + - endpoints + - persistentvolumeclaims + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - configmaps + - secrets + - services + - events + - persistentvolumeclaims + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch + - apiGroups: + - batch + resources: + - jobs + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments + - replicasets + - statefulsets + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resourceNames: + - redis-operator + resources: + - deployments/finalizers + verbs: + - update + - apiGroups: + - redis.kun + resources: + - '*' + - redisclusterbackups + verbs: + - delete + - deletecollection + - get + - list + - patch + - update + - watch \ No newline at end of file diff --git a/deploy/role_binding.yaml b/deploy/namespace/role_binding.yaml similarity index 92% rename from deploy/role_binding.yaml rename to deploy/namespace/role_binding.yaml index e8728a8ac..fd81daee2 100644 --- a/deploy/role_binding.yaml +++ b/deploy/namespace/role_binding.yaml @@ -5,6 +5,7 @@ metadata: subjects: - kind: ServiceAccount name: redis-cluster-operator + namespace: default roleRef: kind: Role name: redis-cluster-operator diff --git a/static/redis-cluster.png b/static/redis-cluster.png new file mode 100644 index 0000000000000000000000000000000000000000..57a8196568a8d1f43da940702e6f837963937eb3 GIT binary patch literal 26683 zcmeFZWmr{R+cpY_5`wfSNOy~r(kb2DQqtWZr8E+fN_Q{1Qwb^QZb6y_$fElj>v`V$ z*6+_g_P_mOzdtxU)^yG>#vF0Qd7jq{Q&Nz`L?=Q=KtRBhmJ(M%KtLKnKtN1DeE_aZ zGk#wJ{~$W6NQxqq4L#ciKhPYcw4D(UP!-^Rh#%Pzpa=-U2-4yrY95GtX(*}q5_2KT zG#^Zn`=sBS(iD-0<50cre)h}?#BdF9O2#9IO%vGZB&i{LhFalyE=6?qBKflS*kWja%-+UtY>lP$b3!A?mL6XK6 z7N$dtDE-q461ZY=@9*DI?-7uA(X>p1{^9ID&U+)X1=)wO^(Z7rPzf<)8VizefgtfqTqo~}Q-6;sS-|f4rlW9ZS zm5!h~yG7plDl^$oUAb{^l+@tF_&0*CuTHv$-o#2U$LNJ*p zMGPu9$dvKD_X4o-v|7DtTkmeK>W+r^bm!}A4_^i~lv@xXk4Yflq_K`o#Fc}Ca4~nZ z;I4qJRcn>ddNQS3H*Mhks@z#&0iOpE5fxb!0fz+jHF|)s9@59%uI>&I)W8h?+n2r< z>q%49=89d;=gkq1MalP&@tfG+d__>r-RS*9B|nUTi%gD<0Y>ut8N+=fOS(+756RRs zl_otk)AB*!OuAtUi2?}k%{bRw%u|V@j72}O&f6QY*6`rtg zQW}ZoU)FGq0*sZ^jkg}--=jsY90p&F~C$}@uleo|1o^@d|)WEvyL>#qKa>BE>G$# zMk&v#-wr0{&RwlWuqA%JYrnfW;NF~u=$Z>%|Nc<4G^3`YUFmsrbCmkZ*=BnzFX;KZ zo0I9&0k(F0-o#?I_M6ib7Q?m{x$c7Mv_ql>anR{Pm18iT|aB)Tmgl|HaOy8XGC zVKYW%|A^y*(yjJNgz!96RAJx}5@LI0fomZjK;^$V9(TLDIn%ATTeMm4PpEU<)!_U6 z_1+#BRNedc?{N<{z|ODu6)n^@!#}O(97*C0t=zw!tF_*H|B$sJ!}qeU$!*U{HD9i> z$#r+`AzRCv$r8Hk zrsvmsd%0V;=r%t)QKYKBTx&T_YgYdpoMvKPmqJ_cmSw(ZBbyn1OI8zwpB&Q4TVUZQ z+v7d`<3q6L{Fhrf5U2J2q0`5#dKP@piVtb7Q`&WBOWt(vunu1grM?;`^<2Z5H_z~q zqx4zr3fp&XX(;u3z?TPV>FoE-H(HQ6K~ugWVs2*lC2ih8{o_%|CWi zIeF7-T?3_ zZuLoj$_oc-yy4=D5V_U-!lGGty`6m*$bg6D7CZ|-67zd2iU z&(L>Ybafk(rb{ULVanR{D~eC<#^Zb?q7=`PjGqacYBnv7!hya(sBFZ z%kiKiB68J7usa8MKW>O-@*{&4*a$q@8qLW;(#a6If^w8-mZxJrebME4pw+lubf%Kl-rXj)H)guof>CE5I$JGI+9q(eFdp=%_rid4`7gkK{^pYKy^y4y36z1c(>3KxKaQMArvn66+jo z3`S_!!j_~%ck4T-qj-1d-G!)Le|#Q9CWUZNGp;bY>+2HZ$0R1z0fg{&B-+abVU?i5XNm1wluP~7IW1$owF?c~+c1eZdmTR-Kz*>A zACd5Cf&OwrGJH<8`7YMtOlIGeL(J5$kkCZ^9s zy6kh7ChalcZOB=4dwX*=f41y*z<a$;97e}b=8P*-)AUCYS*n@YB1p%WvjDMTSbUZ%CfbZqI)Y}g1A6`Hp#%N=%M?Fz`#*S(xXH5@RR4o zEMA^UR%5wgC1NK=BSoDxUT<~9E)@y&kNQYhW)oaKnC5#SR-=}dD91Xeab zpQG?A8h7C}?w8QTQ>9PO3lSU|uu?7|xA!^^3lJW55NG!Ye0qFS3cJa@Jq&EU<68C9 zr%IPx^f_zE$6?dpS@ryuv*}vC!#2G8^pJlAXSkC@z#SZ6$rkC9(SyrOFM$KAF1)RM z5A82qk9U%0vn3*WCCPm7y^BZ8Yw1p}L9|4bUh%Q3PW5a*QU||jX!DonDpmSV_f41O z9c!A|Z30cb6~SFU8upfzU}DOh_L*Ekn0PHy&qMc6k5%r~pzjULG_zMc%kS_G4M-^s z7F=pxE@sdbF1n`)?Kk|YyMVSzi4VQnOx@yI>Xq&~YH4meGziS@X;lsjJ&RS!j+Eq} z`z>;|(fX4*ruv*Yj9)0cJ(&YUKNQa_eT}ksQFBxLSJMf~GSxZocgV{NVnrXUF+@i4 zO#ZH-vq+nsv@hUKNq&;wr|lbCFn6ZWf3Ij|2SyuY)~i~A{jmF*QBFMT{$XtJ2!Ydz zw;2I0Ia?L~7aE#c?Ue_nAHX3+CcNCyLcV&?A;+0q7=TEm4M)Unb;>@gwJczLY3o!&*^-kz2iT)axa zPG<0b4W~$QpFc3HWFA^tztL=nA!E#Xp1Q?Q>5gqE+F$6cdDq3-(@%ZVK z_C7DTNm=5tKtM|mA}+C67EW}eZ#Xf}M`VygNWBUpMvwVN@+(jwsaeau%mr2x=G`^l zY2{z4y|cB6tvC_m<}8xwoC>22;_J$v$+`pkVxs#2lc@;a1A+%5)#k%9(EVxy^aoyt z`IUPrPedpg+@9#Ye|@$|x0tjnD4!npRehnTgBIU+cR<_nr6)JR%1U)g<8?Xdq^V* zC06chvpo%G6WpsAUq!d*F4QbmgJoc~VsCYSR}7y&HK`{cDXQ|Ud-!>Djri#t*&jW?(k#ZyY^!=PliB^W^) zX5`t&CBnj;&?Sz+^`){Q*G-mFwvge0wzT6&B`Ivinqa!b?Yy!(IhXFh&Sq@j1OIk- zv?dX|abSeylzA)Xw!~{H%qIKR=UsRsH0)}xDqBtjxTUWLh6tEgu$-k&S*M6Bm6k70 z*$!$AC}m`-)Yp%aoa1{8a@cjwt}l1XqZQ~U0+sV(ZS<(bZnu=AU7a3*loorFUKBG!Ej~YF-q&nU?k9Or?1^4(CJa?;IYumB-Ee>6Z-9TAmcwKXNR(-(AsB- zGH~K3ov}IQIbf}i%3$*5pAyP@1t_0~(^g791zY%18TrsXQ-Z ztWwjKy*$|i`?)J2b>huFxY5ngEXbCuxjb23taw)7fVHTpjMZ|fU6y_U((l=Pvj0FEXa=PK}H8>18ZWS=med$f`(gu10RI;z%R# ziEoNex0m13W;4o(xfS{Aw%pAq;wv& zljJ}7mZZDeJ)*s399GkBH!&Sh8xj1SCaHHa_W4A2Yq)` zD)82}%XdmP7iy42nBjNZNSvkQU7H=&p?*wRMEG#Fp(9eJ>M-{5yHEk4LhH|7H?=l{ zpEdEuj_hl`87Js za=jzvTze7~ zkMw6jW9X1)`uP-jn{wy*FAn=?(l(y`)7Mk#-_Vhvr=@Adzi@k{EIIM zZ=wBMLpLYH>A)HC%~JnsG!!)c{*NqsMwtI>n*aw~Vd0Q!Lkog`S_gJW3Lc8gv2#BB z>xEMRNVEba)Vcp>h}bG%5@Osi2H|`1f2IMI4s6YrS3w#gf1s|wc<^?)Bx2S7+yr)M zhcuYy{~g}{C$p!9ZrN<{7%W-9N9>s@*Xqa=jt<}JJ>4tUS$y3_-!R*SDhevwzEhbJ zwNk6v60VBJC%jq(-&-N(M*$j@NPcebcQkFd=wsi`SUE5s7t02|SyQ z)M4B6HFIbTYk_Y0V{bYKE^Qe~e@LP@-G%dv73>G>1|8X@O;?y`KLf?5BF1wBWni3b zZ}5Puy06{GgzmJdV~z{DPqyLy3U#YnObFAOyVlqCQJrN(TXoOtWeevd#rkiH!HGF* z*KPQ^m~D5JlRv*~c!i;E=^dXI3&X7yQ-c$=@-;vt(N8I5);A{o!TgK#WrF;(88hPEa?q)t#k z&}B(eW^{g2Qk0vLW=54+UA-*2XhnMbWsj8fIP55+`dx9Y{S4LN!``R#0jHSmZq~La zIu=ongCTG0Oe!aTz_3jAP`93+$|Tl@q4>Pzi$U>Oz1A$%g+h+>*#7erBBT-$X(g41 z_f@$EXYTRKs=*E?_Vq)+^d**XI%I)y;t1)7#+nnW8xnaBUaFUy7hoq31Je6crjnCQQ z^zHSg&^$%RGhs>2WvZ(lpQz zM{%_B;ogFuKCJu9v|sL&Ol66oc&`Kz;ub~mzmm(enk?pi`{T3i{%?R~bKJz!-N2FO z^7h-N9};@bgIuTQzoMHn;5Z<_+s(Ugni-vG^ga_H!!i52i(x!3mkh~kbljpB zU>wzh@>s;&KNMcB1d8@ZetfdRKL+N>YvMFMs}N!pD1Q3Nr~~=z3Sg_@i5y?1-2=eqb1^ zrM*4mY|DTYvgsjlPxb2!qLI$!1Qcd6kG&lVsmB{N>a7N-S9$BHlhI>1N%H`csDZEs zfbC7zjB15H4Hgvm55?o2s5~`K_so~hrSJ202hGk`4+~lgcpX;&;6kU|pf&qsw-Y4z zZvg3Fon`W_j|>SgGPm4p-f+m1SiZ!t-50;hy1aG607l(#(m~sNtje#OAkWmM(+>8f zchU)fkXr(-lgU)k zvCesciYzC*s&<$M>%UpS@(WF59i9j1nhD@wwT@>RH`8|mJ4n5uMqU;J-iP4Sjjn(C zsqt(F&{Y<=G+yV^h02}ac&wA2&fC_frRZ^)_F~V2jb;1QACcDn<87e@>fyAZpR1n~ z_1L<6d~cC{vs;awps;Wbc9pW{xT(9$LEBYXL?oQy#E-F&r=0e?7$5jzfD5QHTj$N8 z+MFof{`E=r+4lYf@>u|3LhP5@_7?!wY|pdk5(j4id^EMaJmW_`6;3_O-HA%Vzhl0d zQW9hkLUTD-TAV7=-+hJz$7rxQDYMPDK0f8hR=PYpI6yA7(Kw|mud-327%ktetdP{f-h0=8h!3^TIDrCR7(W6j!W>)<;a$ z{J4OTQ8%y?NCE`WoyF|sGh$lYVU3g6q8O~3-mt9SpMVdN82EV)c}xVPZ;$#XJ~<)z z{zylzp*52h@1cd*GDe3c8a6?z1{UsJ#wiLqYCqzGJ|}E0Sdk2~^gO?&IGuTMT#=O2 zwAE=az{?Q$0mXxvMUYTZxQ{_DI74to?Mq-# z$BTD}dk+cqsa7Da1q9()xz0o+hpILPB;)N*gIN1^BRx(T*3axC?WDw+)I@Xai6$fD zZwrG(x$qz7Qf~$(iZJ(SnAj>(kR)3`DjH-Ge3PhPZcNnF24mL*5Txu8OrawFj`ep$ z*9vq29jr|*Q*!#)s4@N>3^ik4fpOaJV7@+AZbyd@Fp4-qD|?zels#i656y>cd<4McwN*(j#_T7`VGi9Y)}3gcsI|!2ExDsl zJTtg1v&~L9V{MXh6tHa>LG`oW4`i&1CSy4AF6D@oVsRKJz4 z#|<$~14PzNSH&|zxD>z#Fl=sXpCn(?4St_07*2jtlB5{6O! z>6VL9epEbO%(UD0(T6}tPXmZZQ%!-u?vk2939Kfy9>5%O)ZAQNtiD@Du^8)cnQw)~p7AKUIEwjam zt@Suow@e{h&q!XT={1wvxiovhB@a0wY07a&5wG-xm~a+OGV&f>WSKq?yNsG=M_J zykv*%^>LIu4wXkQX}&WgG`^Tb5xI+0pvig1NQ~toc;XhdSVBg%vz*A^e~bR~mfdsv zI``b-=DcsYOv~s=x9#U_0>R^71tfsePT_S?D535OHz#45drU(04}uVLgB%(#bSt>_ z=&xvf3@)j8J);JX%*myY4k>@*+Z*aJZtFQtZ+WzMt&%VmVGO}r=%oQ+jNXp?e%=By z{y}NN!&Mpy?_W6O*O< zZx}U1G?M_UrYX2xH^ngB_=4c9JQuB0r(d?j={!!02Sjh&C!^2&J)|8klj%!7`_Vw? zbJmG!sh0|sa~9a;H&j~Mxu3$4hMSMaWc5qicc%MMlHD`WOp=ca-`(~t*MOGkb%YZkGFH&C3~1z zNYFxR*68HdrmQ%rQIX-03blN{3^AhZxdRZtH0Q+~znO^DJ!m;nShzg#m+#We4-1@A zmc>K8Ip3N=;&N^g3wgBPlVMtTg!`mzYwCk;iOV^Yx5eJpSbrqs!|<$_@PLEmSn+Mc zRm!dfUc86p;c9m`>mWgj;d^mwFyvKFw_ZDkJL_5- zXt^B*a1(+lWf9XJxPr0cz zxG@eRxdIRd#)B`kXWd>MH5z5ysUud;bTZVMtNN?`?Q=Z?j#55J=u+2WHcm#OpC zT)u9h7AfVD>f6WIZio(@)FVxQ0tC;8jztZrht<;>9pdtww{UF*^a*0l3jmh^x(38DO6+ zI4ib$)SF}?f2`9y?GEXxu(9n5#Tk8fi*my^s$ybQ-7Y!^v~cpPua{}$j&7D{K1&NtnVF)K zo`sL^Y#dZ=*hJvN$zr|sY(}C@d~1*F9H+!?oHc_o&1{N|l5Bt#rseFL(HCo#`}6hX z#4MjSwOy^&sUV@bqhh$o?da@UQ5lw!b17IrgXZnz}AWXR5U;R?d6~jk>Zk&z=XO6^z9R`H`bo~p1miT zNp#c(jg~dZ=% zd_Ufu9&Ww9z?`@ogc(~mN(9OFj_14Dt=~)zq;Ly-V%gaQ`Y$)@O_|;<**Sj+S%w`m z4ue?zD`TB?2Fo>x_Y%8lnuWjb{77Bk5u&@SC}T#~Czz$CBHB|G5BT1^(Z6@oJjJ1K zngyIWay3-;lnJZC0Lkp2iYIc;0^;n)DV}nTZ!RXWJ1Sem-{-Y&rABS=6r5;B1&kZw zc#EVs@jJnFhfyymd@KIE%ZL$4ka~qJbq~?=E9Z4VNN#Zc4K>@B;H34%aeL1-w*^N@ zx;Ja;anGmTBEm|$?NCZ~b-g2wuXed*nFr!1MRLeI)zZCo80uvckt6wOLGD$Jw{Z!X znHUzl`T;>>iB2^ZukEh7^~YzKCS>tVxkyVxrsl0}j53Y_InMf){8o@W6{XCalIZF; zMO~E6r-70_N_C0_X>}yESKNj@Ln(T?bXCp z>wErOrI{^o`>5)9d6wzcOI(;F7v{6qQbg@N-HzhdiQbxPRgKv#e8orcohid)g**nG zkHyOzpc!GoSeB9RY-6*Ncp?ieoC$(1>HDI%hzbX_s4HrV5?VU?3zEdTPp!L@s5}p2 z#hYwYbw64c3<0BODzV}Q>{jhcXGpUjnO6WjCypS|{-{aVL#{*=Ad_eIlOMT5N?268 z(@AGjTg=0E?4Aae1C8g0^?(>UMM{y*Z9hO?rxhk9De8XzPAg!#ele~wfJ=+ZdeC}y z75p4`33m*AAVy2YAj~uj&9e?%HQ=!+^y1Vj_o7KZ3CXo+taOFF@z8IA?oGez)S;1x0rDB|u zS2APRH)uBMUvl9$P~kgP)r&>ZrjW%wye!T29&5*JMWz=QXD@`kwvLy)drbYA#)~ta zHH)oTQHBF2V6L=yjGnnU;EgkOXB zMC`q=67o#gbNX1s_#C0{mmhXQaPV1FumVX1yu|Nj9t#*w9f%w_#YZhB<7X6QIeNx% znbK93pw!o`Xk1qXkDi1W7@$J@DHLloaAG#Kki=KdI$mnO@}$4&ncK4;nB)DXq`YOLo)+QXs@K#cAhd3 zPZz)N+TUq@hVB)n78|23IEXm1Cfb^5X(v5OEmG#dPZL?VwVc>8ne3dsn-HFuh4VBh z(gIn+PjQk}{?T+hVc5~k2(_j#?j4gN8MX2txAuoy;#T?l&*zT(NV(mzI+CfZfpUM}NC&?SKpd`mpfiqJ)<<5X%`ntjiy# z*r16Ep7QyneAeX8=l9nz;=cl}qg0~xQ9$CCk|3j!FMHZHT-Dc|T6{>n;;q>v4?-}B zAJ4fN&F?-oW7q6qhQdR_XrVp@-`nlo$t=FT z(t1*tJgd;H!7(88v6d=RY=Q}{W)lEdtlOvr;VjUHEtY*)es>hfz^xO9ih@aG3e=#O z$`QYKf>34)DmIHo&i ztTtvs8sEa-w*Z{C)7z_qc_5PA16XXmcJM z|5hB8UZp4vU&E2*DJ&4>i`?gDO-}1e6`pAV+?TKUatF5a18%Ov`mMK?`_FZ=I}@5!%Q~fvn7@@_Q>Rgi$hP^ z;M@t^5$b6^LEh=hdVwEawKIIR3F}(hGge-F_`33J2R0>`h$K~{<1kks3wDDP1959B zP|CUiSY~d!AOnuIKGe33uz!SgxjLJ>`jPb5PclCK>E2H}bM5H2_n`Ui!PrB}Z^QEp z3vpt-CH1WMc;-7FxD)GK-d~#uMyPATjE#TxRYUbXR{^>ilv#Z70?5;5S?U*z4Sh}$ zCQG%)gPiqTC)M|70@3hndSfU~fdVtQu$zWQ0?Vr!iB4u{$Gy4MdZu;l;Y(dwB(D)B zVq~NtzG4&T6uM@$*#RRA5IBsW-D% zjt-UALW83tk51TI^py}BuaT>BY#PC^>noOk>E`veeLAQ++3Zf(CQ5Xz4&9TiL6sZVjG~egji-Ewij8bHi4ouDW$U^U|>CKY=O?asF+AR}Mdg;Tk|_Af7@6 zTq*qkCF@#%_V>2SjQDP{&r+RLDu^Ze3MG~`^ zJPU6C7-n7LivCNh*$q+)N_@ONVii$fGs&o^-pdosyhg6Wp_TPx@ym)w2=GUJ7#d!^Qfw!0Hq7eoy*|MlSQ-TqdlD!vDE6rlyQMWpJ5Oq4&U3e zEtPmLT!u~lfLGHi_6ju-A)8t&Jw8zs2{jJCBX27c^|u^mIQ4p9Ai$quTmq91fy89C zRJ(e$j(%0(9pG!;fYOUP%P)K?#b6#(ppPmc!5qVj_gI;gqy7`U{MW-KfC z8CZTHJD9(1c_?Eq-0F1#9g}6N1z`Ws#&CuqFirGAh@_|M=2B>2jv@IW9JTRr2nu0N zNNcbdAR`GW6_c@203|%OpcH||Y(-BAY!-N;91k{2?lX3R_zduBFpk_nCHURNeBt&V zJ6;<2-MCuMR2Ut8d5K4kC@$^)oPjX`8Jo5!S9Uf4=jRuqCo<^h_YsXV#YQpPc~(J{ z$MRc(D8L}jyubet3Ri*y8e(?8`G7S0@uq_+HqEPr#zr@5)HuD}(bN{QADnc}Tp9N0 zh$Pud(e>ydZlv+k7gM_St|bm?rCRLbEJN%0ziWoqmj;WxJJpiml%sQl>}qA+?oB@v8p+XS;D=CR3{?TD$L_1XbA3FCB`sl3G))Q^PMy#X~4 zm4M3=yiCLTLhVoANA0tt@E)wo{}h$}kMKwF(_&G{D3YKUIr zSk3Bd$0E1Ax!2EJ99@w3qv+B8OA&i2`kPxVr3jZHg410gc{XE$H4iNEe+ra<~mbCzu3~$Wwq=E&(22N++RbP&j_ganpPr0;Uww1FLHNY-!-;&AQA9k7-IgEb>6b z-W-_!J>#r$fYi9#fMWm{Y>u-pcX=NW6tCd$E&}SCVnpHG&V;v7=nZ zSo6x{Q@Ce8Ns?NE1iBIwB#n`RA|v;1!1+S_?ru*37?h-fRB(^#Yqj9>c>H)Pq$k$J zXsW&l$fywy5hx`B!@&8)KKTy3>we1+hxw38)-#E3}}kMbb%-`8&oFg zdq|Etzf(j68y`JW#Z(5BTu$YEf+#SnN=n%8vf@z#Fu++cM}5~~Rf{VLO3_x+oO+13 zZ7d!VvNE6Y(*Zree-=A087$jmAVYf#vQ@^}JI{!pUZ{cLKr2YG^N7U+AdJtO*AsQ? zEGGeP3C)QXtRl8+FiLTrb$Bx{HOOr@gnD&YZ@)KfrfRc(NmJ)I5In+t^SazDsohP9 zeqJ-rSiM9a5>Q(>{f(Dv-&P<6t0tV_yx^IdxmgNievW+smR>4$IG6MT`ASoU?rD3aOr%EVaf#xh&zY>>GDb|!~*Qx{6->EgF|02viXVvE(KMSJmopY0tZ@`g% zSpR~RM*s?4v3QbM&R+Ulx-?(I2KGR0R;}mJhISA-L8*F)#(!d8U~e*F(E{m&1ZUGp z=3dc+E?wWUr(DnTxcwL+)M*Z0R8^5|BjmLmbw8ci0-I{S)5f7b>mn-W$5}Ka@u_|X zp>YXX4kJ5NoepKXutIR3hUx_mFSeGa4k{9F7fCx%7}OVqYph6_$xI3j@wEFb(EhmT zC|f!+%sS;Rh_!9%hX=Wfhog;k&ea0^I6fLp#e-kGDkhIzY3g(Yr)I1!&S{)owQRW5 z{c_@rM3!vPo`*T;(mv&TVL3*v+w5jrb9;HR+e`z!z6T^4F1qiomOHPn=4Zt}t$sv6 zpqqey3*c{Yk(i|VKhmNs{lBC|EPN6+wNPlk6X^D_)rB)AIG#R`=a@kb_(`OoK!;e! z_nl*bn6n<9?o!%yeA?uJ+xWdupf(C;&@BA8Iyi}vJBIeAB#%Qz;*kxPXE9ur^}YcK zE?KgJOO|4N7pu%7XOlmXZ2~3c#&@kXm$X?MM(U@G&BuBL{p&X z*H$M_UJcGt4jw)y{S0JF^=gX@Mm9PIHAOz1X?x?K$hW&S@r<@|5{ApXd;)J5uFd+t z+tqAzGTR-=`T*B?0Ma4^7{Wo(k>V;Iqwc2eCEnqaeggzephlXSnR?Cj&#ak&S#xXx z4VJ0^p_lyqNhm8GaB8XKjj zfoC;}dc)u%FSn#H|3}()kxx0k8+h+=rSQ3z0j-c@$`m|oALw61t#8D6^sgv5fSKki znBAQQLIaO)045`Y7ZHL&)?wi1=yt~oqEpn)0kf~$?t4=TXjKX;cKJWT*9%DmESJ#B z>i`te3LsdSmZwhTwoM)c)u&}mJB-sEZ0*-$`%Sy7a9%@f!Z`Vlcoi1?AH&<&!CjM^ zHU`YJJM;jf-FH^~riOKBe3so}Q+{oR z$*)Z7sZvWY!;Gh13je+qB5H0r5N4fx#4B6L{P3tsRZ(CvUm?ttm4>w01Fag)> zB*gprFJWr$GZ2Mv^!TPEv$gydwI0n5vYfZe12u(%kNAHJThCVI!3!WR3l8d`A2;WVavhTtL)#F)WTJ5VMQp72tJM*6|O zP)H0fQlLX_lR zu?I+N>7Q0r@NQRUixVrZ*OLs#rctfl3nL-p>omA*kBPpjoD_X|9{UUVx3IZ13R9^` ze>?-Iah_tfbbOiY34$2#p@0EB)Q>F}bD?kHG8tK9L0B)9-Qu1@O}xe$U%;x(NrI+< zU2*D-a0gO@c>qB~G`{b| z?!`c~;o?{*;_^ho5;%^*8v#f`MYGlw;ez|J54@(B#_)-zFnI)AemvsI)^?svoJ|7G zudXXqdO?vpN*5f5BxWwd9mbuMh+F*u)|DEc5NVV zhwCgJ_upP04bP8ClEJGetAM6pxx2_6=v1O!u7-+UoFfH@qfwibfO6alc9ZWj3VeH} zI*kQDV6)$x*fzl~1b25eh;dMN5HrmbV+Aj-Q)ZfHw|`4QA6q-~7**i->fwrI#>(at0%?3dTSJLQMFfe&p|Srt%q&3>tS1Fas0 zrnxUMOuUDS{N&T8rJx{t*)l*sVHQ04!SPU_{h@vrA*$(Ta2z{HuytEWWpEvH-=JEU z5QT*Tf!RSF7;1yjYxyz8Wc=oW=UA;Ry%Fz#DrOE;U8aSIQ*ebJ9F12PbwWWI`iEBF z$63pCvL#kGK^eL$sf`d>J4FmefVgcfJl=z&D4-zS5|?C7Pnz#D$Qs)A%@j(G&$oeU z%6Yfnq(l(M7ez#PplBb+v)p3D9>cfd~*Fw@Nv4d;$;Klj&zeWo+Aj!n66JkE6&{=L!2~F6Mm3&;$4i6hcbZ(A8 zfqs+GVTyg*EM~;rNx5Gnw^Vu?JVV1D5_vCNg^XJ{31Zcy)&o;A`q%f!PK~%d3>cxTFzF^xw9Vi2o|d)1WX=|vPv@*3>Z_(g7@5VW zJc%x>M=}GPol?Qa1NP_8@MvGoCk!%L!dg0B!DUHjX?G&za=@@X-H(K)6Q2C*+wn?A z;{Y{SU+Mw}(w%Mx-~4pOB)aiAmJn7u9$jWgBX|C%-y@x`+-8)Ku7>??s~-+pEVs2D zt@Y)UPBc23pE+@WPaLQk7749YCerC{*4Wi&9BZd6#gGG)rGzb49rK_nNAJi2!$i-`wv-WAM>-z%r1vJ%p z$dSsujmjA0skG+G&|stRBRUcCkNR%W7$;G|oa-qk{9ILS$zgFF^zm&v7Avh>C za;A}Y8$DZU^=>}6%n;}H!R!7OLX8@4TH?#z#-l(%ocyvdSIY-8kIAw+4^ zT4WlVNu!^Bh}a|4){!n2l$mT!wU29_VO17!>Q25Rlb=fL6lvbGB8`ddSLSbTpNltm zREtD_hGawy5R(Vq5(87)h!lq#cOq)e_`eGC_TGsUn1pl1nTJQJiBnbPqSUlphL6Ub zoh$lX#u4vK!Aso^bL?AB5^q2q-w-hjsK>g}-S8^#o3e}~4WI9ty=Hp00HXJOUNjpL z)h8%uNPW0cT^ayp-s1O3PNl)Qf!Dx?Mb0#>1x-0LXoMX~YFA8ZiN0gSLTt_4J{SW* z^ucQwC&h1ITwJs4D%TU=mP8V9y$}fD5|S`-@{J|b^}||!9!n)n#e%y_jT-m~cz=x3 zaO2d7vN8&hn;#s*4QTcfDfun1%vfBi%qL1g#x1}E?MucXm$zM7xmR){j<^HO5eGh0lH0X{g= zk#N$5r`Rxx-HHK1*~6(y6G?0EshXN}_{T2Lh=Ux@(R5FwfAgUt!K*=uNhYh+>+*i{ z_$^7ksAH@wH7~STRwR;F{(}B+6gSJsZp$nNIp8@ikl4&0Ai5aY=ttE{A2y(`#PAe} z1}&r9J06Kak+xskwAcKT))o>`PTP;+Pki(rn+q{i2f8QN|Pp_f^<--6hT0xND(lUVEj># z9u%Z^0hJ=CNKksSAcRinh*SXu1Sv@fp;wbg4J~q3_{;H}aqq)@xMQ4$^TJ^45!idr zHP@Qu`{tKvX{1z-4)`D@+SE{7^m)bQ8d2$eb}{%%hXGItf7X@HXQ$OaDinE2+}6HF zlonHSt#m5o#nyaoLJDvV-ZwTZriOAztJ3D+A>soY90*(Aozp{^y*>GB;;^P7x@ z$67NSMW*xvQv19rF6Q=d^PWwJK2+S5nKZ&_Q5MbPZlp&BT1Ce^4 z-6AvQm{>T#yVaI=!EUVczF)by2gv2~i+wFtPyxw==O>1!sT+GUFA<^gEUa<-0aGD} zm~S-sF;177tt4OT{n*SmOqMZLan1jzpC~Gv5iGZB{5Y(&`GvUoXuvdJ(wFGRr3Dge z;03p%Z#UFCBRvT(Yd~r^u)U0_Z)PPt_cf8dUq%9r>Qfet9BI3}B@d2Z=LBbHbnMs8o& z`938$t4w$7q|ihkAlD^Z=0L`7Bbh!77^~GBpRNGWS^_zM0vr09*_Wj@;1NBg`?pe>R{>8gXLA1AGiek+Rf zJgG`jGUV?p$U{U>4 zX}ATLp4l_P_Ak$#5QtB@+=SP22FgNSvUj(Uw^y2-t8H~~$C?A82TW^Pqakz80EH)+ z@mjxJRlHN__yZ{^VKI=+uL++5_5Q0wmnC0e@lB2Ph{7v{Pz zRbuE$hy4e^;I(H@1U1K8h6?j_+AxctRL99Y;?)=CUWT-_kvuI1+wHC_ zt!_zIy9}Xt*rNZ&N$NST`yr{G;rdaNySgDiw;aj1)rY$EH-vy{he*I@cBy9|gOZ)} zU$Z^Y+s$tcWOa7FClmIDyg|*FsmA?qFX}aGb5l;9Qe=3dn*nO(Er0=a>z`(S0_~Ag zW1sX|nbczZQpGP3JV9-BRCZeI94H(gD=QFXR@HrvnPD2d45c@NTXwQRrM7-7 z7S_sS;+fg<katKOV@h|eo%4?On^eic1Nh6UW6gH0c{&GG z5RuUr@0Wd~50~^fn>-t~ozYRk&lranv+{1|f*3FS8P-<(d5H3DhVSwNnwG6^PYc2B*PJLR7VKvES=NsuVZ(clsH z!!uqrx-SNTGsg`m?hJM~naw{7xs@nLJ1Mx@y{0p}ID}j>_Ge+>-XYCRDO25#MgVmp zTf_Q_R_Fmx{-zYVDl_+J(lVYs`B`jlTZ4~OJs)3>_G7I$U&X+7Fda+j#{I?21Qk5p zRq*$6rZJ%T{1-d(lRGHpM~OFyKtkXz@LuS5a4js{?C%*?Fl7p-&Sm-RdHVkSsROh$ z;M#9TUQB*|4@M8ch~S}155W}Lzd-n+#@tY&wCfU{x2QNV4&cP)b$iuT|<9@^vAnUGdj5dt^Zwm(fiXQ zs5DvQR>90=t0G#^1X{K$h%Ps{WbCHMX;EHx6==ngZ;CzI58rTYC%yOW4!)`r?;8@7u|T71AWidyZExqwoXsBUku{jVe2XgMmlS{+ zc|7WZkeVRfbOKOmcGS6>k<^wb%=U3uPb|FWvk?o?2eIy?)C3Q3q@Umy|4z#+JEk^i zmau+8sT$kIG4!JD((QtU1t=ck+YaeI!Vi^}ug#Nbg(Nm7CBNdC`_c_J!5bO&DIy1k zGWY_k{^}QFl)u|mz8@-gNpj6A7Cvv0Sbx$+)KoIv=~gTi&^|@t$o~!o7|Y5fi3V6u^zpV%8GnckPB5v~(pLSC`kyIwYRE~Tz z<#8YVZial_FAHEs13u(qehpCKQb<2UobzJV5%5Ikw5FcNu{A;DAEX-ykJGaqd?Nfy z$BL>?_g~4<|0h+~cXYJ$kDEFZOb*k5X5uM2h^&pHA|IspS>1#Z^;n8b(7M=aIN{1A zz26ZGFFQ7}7jtc60!Qf%I6u69oN0;E(NBmSVte~9ssV=JbTf?T{pEyW6N>_r0S>LS zUsMpow4?xHE5&@_7kx*qEDo^VW(V&5Gi?XnPzoy5QiaW5gc}cpn*ng!kfzo7?_?c3 za4W#EJNn1v|2|Z~L24iz7AEtb{eY(VFIN9BOt_TrkA=-kO8&DF!#lL3{payBugAvQp9I<@Nn|FcBpj(R%*x7YaOH#*DDvjC7^9xoL56t098#ZguO3z z4PgXz|I+^i<@V8~j`Se8&>>e~m5?TUNQK z7QB%GgAB3sh1QK95xqA&$Z2HtjCrX=(9}+hqrQe5aMO=>^El}9lEOq84Rq!0 z?Dc$iz6!l)%r(qO@&ApOVBK+uP(&AOD)JCk=j`DO(%pis4(V z%RE%CHU=H@ISXG;poXTU${_YRcZ#I}sZW3?d9=xHwCu{}4oa%$+|JE_WM@4vN>l3x zNa)7ioQndg$jF!6$UQQRZ;UySK+g827-u}Hu0vugFzsJ>?3R=%jfi6Pp>#g-dVKM6 z*CqzyVMR=We8j-CIvS|y2ov>rQ}+#%7VcvkP%{YoV}>>7Z|Lj`q6br z_d!Z>3oIJh9$aLb9YYwldyG4`dm77&zNIOB+*RUj(%i+Ox#+K%4J7&GpYtn=UadPG zZv_I-KuiPu;Ci`6!sd}PX0cqm*!R{OyCZcscFT1M!{rw$WF1+mjG#(>88ee4=T*d$ zp$6yBy5)4?9=;+^*44?%0?2zfpHi{c;F?=$m4^C?>KOzjAa&T?5vXIVV%GE2Dt;d< zmKm$dtKD_oV*dAi^`gnLd`$T!{|@uByBdSB+z=O7al`d|i!basdz$EyoHHe<-{4bG zCcBf6rFop^%>v7YXHdee!H4*^3ejQlxQ`}$8WW35c6%>Fl=BDLS7nMz8nA-w8n!s5 z@cD1m3BhM6%-FXrXCZX~2l>cL^r=5TtTd)+uePz{}o(Fl#=4V{~|u8Ha%8x?K%z;)7Ml%FlpAK8KKFo#*(yO-D%O6qV_ zFWxZD@Pp4SN)a;_uY1fhtVBh1Z3WE!=A%uLOba6}MR~++%`|Awt-sFT?h&@Tp^(&C z>;!A1W*neHax1H4=u`!eK>EZ;yV5>H7Crd0Hppeov29xf{v0p!gxjjdI`~4$p`I4oQH{1)vgVS5-O`Y>46(+c zAzsPhD=G0XWp%s3Z@pf7d1xg^lBNE1Na^tE{^@ueM8lR5$qEMW1{&eTj=|Fm6UH*F zIq-FYd-Ci-LMzO&wt6Z*R@4tRj=S2SrhsWfwol-nLZ(#;mjp){d6D(eAss}|(l5)m zA|)a3<{j^S5QzzWNq)_|tloL7L%NF!|nEMS`Q6A1$PGD8;_& zGgE@8UX&00?o8;}mc-eFWeEP=QuJ!WDDZ3`NsM?q;KIfD#B@X#>Ecbu&AfS^)(?{t zjWW-L8LM}zsk^jeQD|33x93-a+9w6C)(N`wXV;HNSa#!*?wi#58r_MzL2EK2v(YSH zvC>YJv}u?AU{WIW13|LKdYl|SZdS3z7? zQ#u9jY>?r-Y-T%sz3YJ%@z{?{o|?c%qdau|Ak$BWjeR>Du0^k>KKu?cfO5m|>iKg3 zR>QOsjfSL)#qGh2QKAD;CLQD(3wcJ=x$Gtx!Zx~=Gb&k(sl+b^oFAT#n^Io$xhMNj zyyoMpIqB^YAWJIW%@?3`5S6nZN25F^4nxa>bY69jYlGB<%rMVW3ev;@`9EeC!o2@T z;Xcvt=a?dU>OG4D(*ab$%{B>0(fF-g`TpY))Gr6n(K_49i0un@I=d4}PP91#} z2@kb|uwYY_H~i)tI>!F8&hJgbIKe+S>pC literal 0 HcmV?d00001