From 3df21918f55de8d31a8cb0dadac23c8cac3004d5 Mon Sep 17 00:00:00 2001 From: Dennis Hendriksen Date: Wed, 21 Apr 2021 10:00:34 +0200 Subject: [PATCH 1/2] genome browser: use embedded reference sequence data --- package-lock.json | 14 ++-- package.json | 4 +- src/components/GenomeBrowser.vue | 88 ++++++++++++++------- src/mocks/apiDataMock.ts | 58 +++++++++++++- src/store/actions.ts | 13 ++- tests/unit/components/GenomeBrowser.spec.ts | 67 ---------------- tests/unit/store/actions.spec.ts | 10 ++- 7 files changed, 145 insertions(+), 109 deletions(-) delete mode 100644 tests/unit/components/GenomeBrowser.spec.ts diff --git a/package-lock.json b/package-lock.json index f429df92..3394ce83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "2.0.0", "license": "LGPL-3.0", "dependencies": { - "@molgenis/vip-report-api": "^2.0.0", + "@molgenis/vip-report-api": "^2.1.0", "bootstrap-vue": "^2.21.2", "core-js": "^3.9.1", "file-saver": "^2.0.5", @@ -2359,9 +2359,9 @@ } }, "node_modules/@molgenis/vip-report-api": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@molgenis/vip-report-api/-/vip-report-api-2.0.0.tgz", - "integrity": "sha512-dlpYf/26LMOI5UDidxpmxxhpaStw26H3qUX4qrjaYjt52yd1bYKNOLvjifD0GmVZm1hxifhb3Jva8HvKiIfsvA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@molgenis/vip-report-api/-/vip-report-api-2.1.0.tgz", + "integrity": "sha512-uPCT2JxGFfh3EUkK76GMjwXZeqDKt06OpoSsaE47whGcUndKifULbdQPAYLiMVOu2SPGi+Ol4QCWCSsLexhYwQ==", "dependencies": { "ascii85": "^1.0.2", "buffer": "^6.0.3", @@ -26954,9 +26954,9 @@ } }, "@molgenis/vip-report-api": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@molgenis/vip-report-api/-/vip-report-api-2.0.0.tgz", - "integrity": "sha512-dlpYf/26LMOI5UDidxpmxxhpaStw26H3qUX4qrjaYjt52yd1bYKNOLvjifD0GmVZm1hxifhb3Jva8HvKiIfsvA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@molgenis/vip-report-api/-/vip-report-api-2.1.0.tgz", + "integrity": "sha512-uPCT2JxGFfh3EUkK76GMjwXZeqDKt06OpoSsaE47whGcUndKifULbdQPAYLiMVOu2SPGi+Ol4QCWCSsLexhYwQ==", "requires": { "ascii85": "^1.0.2", "buffer": "^6.0.3", diff --git a/package.json b/package.json index 43b0e96e..13166dcc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@molgenis/vip-report-template", - "version": "2.0.0", + "version": "2.1.0", "description": "Report Template for Variant Call Format (VCF) Report Generator", "scripts": { "serve": "vue-cli-service serve", @@ -10,7 +10,7 @@ "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'" }, "dependencies": { - "@molgenis/vip-report-api": "^2.0.0", + "@molgenis/vip-report-api": "^2.1.0", "bootstrap-vue": "^2.21.2", "core-js": "^3.9.1", "file-saver": "^2.0.5", diff --git a/src/components/GenomeBrowser.vue b/src/components/GenomeBrowser.vue index 00ca5639..539b983d 100644 --- a/src/components/GenomeBrowser.vue +++ b/src/components/GenomeBrowser.vue @@ -6,7 +6,6 @@ import Vue from 'vue'; import igv from 'igv'; import { mapActions, mapGetters, mapState } from 'vuex'; -import { GenomeBrowserDb } from '@/types/GenomeBrowserDb'; import { Vcf } from '@molgenis/vip-report-api'; export default Vue.extend({ @@ -14,42 +13,73 @@ export default Vue.extend({ ...mapGetters(['genomeBrowserDb']), ...mapState(['selectedRecord']) }, - mounted() { - if (this.genomeBrowserDb !== GenomeBrowserDb.hg19 && this.genomeBrowserDb !== GenomeBrowserDb.hg38) { - return; - } - - const options = { - genome: this.genomeBrowserDb - }; - - // store browser in prototype instead of data to prevent very slow report - igv.createBrowser(this.$refs.igv, options).then((browser: never) => { - Vue.prototype.$browser = browser; - this.loadVariantTrack(); - }); - }, methods: { - ...mapActions(['getVcfGz']), - async loadVariantTrack() { - const data = await this.getVcfGz(); - Vue.prototype.$browser.loadTrack({ + ...mapActions(['getFastaGz', 'getVcfGz']), + hasGenomeBrowser() { + return Vue.prototype.$browser !== undefined; + }, + async createGenomeBrowser(config: unknown) { + Vue.prototype.$browser = await igv.createBrowser(this.$refs.igv, config); + }, + async updateGenomeBrowser(record: Vcf.Record | null) { + const config = record !== null ? await this.createBrowserConfig(record) : null; + if (config == null) { + if (this.hasGenomeBrowser()) { + await this.deleteGenomeBrowser(); + } + } else { + if (this.hasGenomeBrowser()) { + Vue.prototype.$browser.loadSessionObject(config); + } else { + await this.createGenomeBrowser(config); + } + } + }, + async deleteGenomeBrowser() { + igv.removeBrowser(Vue.prototype.$browser); + Vue.prototype.$browser = undefined; + }, + async createBrowserConfig(record: Vcf.Record): Promise { + const data = await Promise.all([this.getFastaGz({ contig: record.c, pos: record.p }), this.getVcfGz()]); + const fastaGz = data[0]; + const vcfGz = data[1]; + if (fastaGz === null) { + return null; + } + + let tracks = []; + tracks.push({ type: 'variant', format: 'vcf', name: 'Variants', - url: 'data:application/gzip;base64,' + data.toString('base64') + url: 'data:application/gzip;base64,' + vcfGz.toString('base64') }); - }, - selectRecord(record?: Vcf.Record) { - const locus = record ? `chr${record.c}:${record.p}` : 'all'; - Vue.prototype.$browser.search(locus); + + return { + reference: { + id: this.genomeBrowserDb !== null ? this.genomeBrowserDb : 'reference_unknown', + name: this.genomeBrowserDb !== null ? this.genomeBrowserDb : 'Reference', + fastaURL: 'data:application/gzip;base64,' + fastaGz.toString('base64'), + tracks: tracks + }, + locus: record.c + ':' + record.p, + showChromosomeWidget: false, + loadDefaultGenomes: false, + nucleotideColors: { + A: 'rgb(144, 238, 144)', + C: 'rgb(176, 196, 222)', + T: 'rgb(238, 162, 173)', + G: 'rgb(255, 236, 139)', + N: 'rgb(80,80,80)' + } + // bug in igv? + // showCenterGuide: true + }; } }, watch: { - selectedRecord(newRecord?: Vcf.Record) { - if (Vue.prototype.$browser !== undefined) { - this.selectRecord(newRecord); - } + selectedRecord(newRecord: Vcf.Record | null) { + this.updateGenomeBrowser(newRecord); } } }); diff --git a/src/mocks/apiDataMock.ts b/src/mocks/apiDataMock.ts index 061f3f75..fc8ae837 100644 --- a/src/mocks/apiDataMock.ts +++ b/src/mocks/apiDataMock.ts @@ -102,6 +102,62 @@ export const apiData: ApiData.Container = { }, base85: { vcfGz: - 'ABzYG-0^Q<0t0YibZKR7bYE?6bZBLAUuI!+Xk~IPc4KA$>|N_~+DNwl?ENb!PnBzD$ANx7oXb=Zj4^jGW`JZf_X~xwOsK)Y0M1UP`j5Y-TLOd-0{IEqu@ehPM^c~PIelK;Eq?gnu0QbZMw9!_EdQx^@s(xCKYnlr&pR_OPY^+f5(LLSmFoH9ubLfaX8n6Fe{4^^L+l+E8N|<+I-}$`)9rM>z`0y!Jf7xmJF`x%G@N?(H-j8pp3^M%WpqDkPdnqjH=MTby-Clzg~RP~qxgl&#{o{wKy#Nji0HiZ@PyCiY_W8(;F;L##G;44v=IA&BkL-?a0hw~CR=hqhWw3S!y_<*r;MUy;1DJ3OnpQZ6t0W>s9cRX)!ME`jK;oEW;rBQ*@$RPHANga1+i(%L2YSIxa2B34?cdGv$M!FG7l7m%qlcL{wKC0ne|GN21F!wn8@Io9?>fWbC_AyIv$N?}Aid}hX5M5Y>76^B{dPY9+Dh%>I{!bF^L(*dseLLm+RaM2R=KDY3$My?F^vFy3`U(LyQ7I0Jg+|-Kg@Cg`?)UYZP(lMfM0jvc?8P&$Af1%wYQu(1)XNx!-B4ofv%FxT(~}YmMIJd-oP`V3r*#!UMRLq^S7%H*Hu#nEixBgXZA4h+B10Ye8+sKT(^F!mrUvNbwvW+l!87&MVE9mA+}V8im@qxu_P(&7h&}=Jm%0oVqO6itWm|X_PLSrC-}ug;w#>EY5vuwy!VXM9cU+pM_O4r(p}nSmoz-Wn%+M-mU8QL1m!;bEs<=O170d0bPt}N4?X2f#nd*nkKL`Eay}`H4jW>i-Kb~ejeQaj_`7r!_IQq|Ug&fXR>kImEXZB?T)}!D3F;-8%{@xq3AMU%owr`}#JEGbc42Ehm60g3WekoVm#rX=1|23@@T)kJNc3EmvTnB$NH{pAvW9j0$0lm@P`V00a%%?_2Q)_3lDdmQ%CmmYU5rl$-mo|Ok|#_Pjs(G{3)g=`WrUinoLpW?vDOg1M5t*jHP*`dG>RhBY)ODIXGDsmmhc6&LK<@-P!hFRP)iIqM?xl1FPq9Wrb-B!M6DLoOi;mqwQABttQA9Y!R43wy7b4Y&awd7AjPOFF3S-R)PHxIVq*5U%2}|a4AyUv5qO?kE30X)~P~el3#FmhSK$*fsZxIk#$dhA=7#E4s{~X^tp-B>P5$&D7Et!OlzU9_et;OvG7dlE>ylh-w9o4U!N0sv{0Qk1%K;>X7ecU`T1)7ec&(i2%&$cx-TF4A1s&eQV7>LH^EVwGa?owSo_Y^ZAE{PxHAN9Ed!`VPhK++J)zZ+P`@E%DG=krTTm8fAghUvyAKymQ-M7YFD*F3mc}WqUIgWf|-54?p*Vg3w#D4=4fJX`+m)H=KDjCZhvM2s=}?GxdrVApP6hr^U)8?Hl6-F*m%p^$W3PxNY^_ya9Rio+8sgxlB0af-1nz8Uh>*OPG_zl6K)h*r8yu`oLZC4(09xBRLh;BU}F$B;~+tStQsC`c#fMWO%|VZvjXel&n)~>zT77XN&efN!^(sLJ2eUQw^_u@7+SK4NO4F(fI~?FHDp;R__@FH^6R!%-TC3q&+OffgYPPJ-3|v)$Widphe(X6@R=vopTc6bc4`f0*IgRU2?1T1u(1IM)8Hk}Q>=R(Ho0lSoE2K&o^aPy&g0f4OuqfTQ8vHN8Jx#r!3KqSry$$>zNXLyr?LA<%#<-6-4O{HkD~XAqVpPxEK{CDqSXs*t5prcz54vMusr9Dx-MS`jwy-k%93Y@NAAn=mFd0nR{8y6r}-;G6N#nX_S5V&QBQY!l7Y3vl}WsN6a`uODH9&Nw=P%g*q8W0MI%B?M6f(und=Avu|_$%0f`L^6fAG~skSc$i-Ghvbd(1^>9)!$I~i9S{0luWcK64~j^3$|?L0uaQ(JrjatmYO(gq2SXLn+Pp(qCghtZ6|TuaQhIs+*IWvt`|;>uc$+4BD40M9x1-@`vgmG?mGb4B^C%$k*#l(b>%lS2VG<>BhL#EZ6E6Q;SeP6F?glZA$VsuOp>GQN0TYasCd&|sAQBD~M3!UM>EHvEt3A?oLx{|j+cO58SX1+i+)BM38=)LHhX_@c0lQ#d_LNgy`aqm=bcc?{e<95CG#~V|~9ZP7};sA+emkkXUsie(iCjo~V^pJA?=aP)U3}uWv_Zlxdz{g3=+vAlgF*=kEg`*Svi>A%k)pM`76D{g__!eln*_l*Z4gI4%EN3|9)7VD{8F3po|Rs_9LPLd*c6fnD?OT+__Tz1*zWGsPcumxf%LrPeM?I8D*sE#^#6jn=|H3awj@{ha*@onKlmSLTD{54&p6qit5Wp5U`Jk0n;Qim4JTHp@ssFRBFD_%LBUkt$zL88M)>h~crLkM8p`JMsTYw_SJ(x6Pshd<(a23!+#SzfGYFAOlCC3)q5a(G+{#T&vf0ku?Z`GhvHrNQ0{(uDXU1V`vwHG>EF_Nu-$O(uO_q@XW6&vPEX`8vMU;OO{##!0;F%DQG&9+XfqPtD2(n{*T%OL-KWssyvQ=2P}PmHJx12Y;IQ87YStB+JGOo&4Kq}W7)Ag$~NE~JejHX0h}%~(f9A4yiIWf5}S-o&$e67OLi2L=;%w&w;5%W^DA88{aHc91-ycM(Ehy4AZRF-JAUhbQx-ppinT9HI2XDTdxo=BpE*v$EY)z~b(7uXzfJ%YWM>XMpo=8+dXWozVx=aCirdw}U>BCG6cM^ipC!_M8E*PVH{_0D7^%-U(f`4eL&wy7G$FtL3mwi-1ZW2y?%q2YFP0uuwf<~&z3<<2Zu=*)~wVW=YF#I8r@;HecfYL_B2I>C>aq4q2x6I+>h9}bx$bJl|grKV?K?v(?f*cMZb^*)FsA)=uW#KuQ7L_3kd_PIo|uW<^aOV_ox-6|pAV5{@`Ljec&WeD5nV($4$JZ!zh6BxuuiRTHXaF^k!fVX7~fzLRLuijwEcbUh!TlEJ2UA_5x5=(f>>TEP__d5Ndcl#_Qn~h-yWi(+B3}fE%CWdLimr*-K-ZXOmGR0me*Xng3w3i(FQze6;U@j9(h{{450D-#*1@ky7HQp4=zt|ALqrwuz{UHKqtDo1rIPl+}i11f)!S=O8`szboY}1ezrPv?zqxi6ye@rk$xi5Lxz83TGCjDtKQeeH;hQS_fw>QT~sacL00VDGb#83=zP(>k=XZg^rvwW7ZRBqFRABNXf5uHB%jRR|QexCjcfQ>;8wXv+J*IU?diin++n3WJKekV)*Q^Y?GgD5cZ@eh&fD_2A${;@P}bqA*^68~T&?7|PfA1P$}5$6Q(R|a+?{RmU3?3+9g^dpGk1<@|=&`8@CG}ta>7Xy34+r?5~O$iTK5;v8eFsbH~>XBTXX3wE>2Imx^tKAHp1o=w5f!P@|Mk$jqt4Fno()gt+j#n|$ObNP(89BC?X)Fv78rV&Z**+tsA$E=;MOWR7qw&{_Q?a_1-o6oYv67kz3lz|}|4ckew^kRL?Nt*tTp&bVyh&1tRLGSXo6L!5>iST_ktNPQUkQPzxvZa8L8^#aoVgOGArD2Q!shB@>$git7&PPyC@Yxy{)+)yLuvPWiLvi7R(Vp$!m11RX7R#K5zRS|ne2m&e;f!A2Kx3PQu#;jU#dqo}?&RB*PLdR?0Evpb^Xfp@H4Qh6dd5c4&Yo%dOTZwGIt|Q$94*btpv{gu&3EC^~d#)@on&Wh*j@jUWE5^(c$YA_AWGD2RQ(iynpXE@~6xOc0-~L8Hi`M^QFc8z2O=IrJX2?sMay;r_B*E!UxuOK7NHU8V*I0UCP1&@lS~%9zU6%80F_as3H0fz>h%Mno*iG}k5gj40mH!+fF*Ac2OdC`c542R@5ICWW`f$3BsRM$*X3kC6(yEGC`t0gVJgh;-yZLnAb1TcNQ;vGFlOl4}%+k0rzcd*aO>Qxi^sp1@3RuC=R(g>uw>RTwgN|3wM}ZB9C07MiUIbs8K9RnknnnNz~x-RfIXYKG9uGMHwfQA%Fb8m}}mW6%->>j3>1@xu14B)#Q5`e}FvzHmx83;b%*y&+CM}aDK$eI!Hh<6j@q}8T)GGal0*GgJty^7Go-*pBEmO+GlN{6cjJg1EIcwZf>EZGAKca_Bdl=MdvI?s0YU@2rk<;sZn2l^wt9!|W+dQ1Q=1=p&>@Dj6C{(mk1$bczxy!ZcOOul?;*sHLMok7_LR_r3^AmVTCDLJS(M<2T!QwdOXZm6H5mG}TTy+1OvVu!$vlz4YZ-h02*q-9M3dS)p$Fma{Z`DO<^1{~8DprST_UEBO7>E(YY3F`l-_h=o9J;uIMNL98uMunDxypW_|jD$UXh`YRL=!-6gcyB|B#CN#a=hhsjy{Eg5cJD@>=32Q2X#`0Tl{i(73H)5oj8oO_3&>hgA;puxJG*oo%Uh3Jf`-TSF0S&eR4IM$l4(J~&8um+`2~S32PP3dR6Rd0^SZVp>Niutc2GJC2l#IrlW;vU4{%zTS$Wk}_shoB-e7dQe`-TSI0gaXEWlJ;&iq0(qFPm;|*}kDcc0j}TDOBnR8p{QeMEWzJwE-$Oka3u3#Mq5sTKFna)QmbfSk$S=12&_MQ?Y|`hz-iYBg!GEI#lJr1b)_EW3+@KAXqLiu{cn-APKK5EwO9e(k(4{SrB$xkfs>8%P1(2eQ=Q_k6VHk{;pPkA=+EWcD`H{DYel>uF@=BEolwE3txe076%S+-q8mvg4u;1e$h&Faf9S_~)F*-EZfVRP^BV+}QFnyBnuS{@+ta!=?putk~gK48)%`9PILPT9H~hGwgrHfQA06d@$)QiLF`w<`EH7#esvbL5f)BdF{YjBwpmK@Iplbk`(3386@ro&-@vqf^jb$;`WJlH7#UU2+ppRaxYqS^+~qPR-gb}1Ep%R8mQ-s#zPE$s!k0C{{d37X!?Nv1+GUcJjLEIjRmIm>A0pW36tzwS~8%>X;9!1c7Ol^c61vn_~65w!S8GsA_V>~#G>Lf2uIW+Gq%aNUzrivrOMw$hTL9BzYHnEQF$6GA<+lza{1vg;mc86|PZ_U~9eVQ#d$ut#=moltDPxlym&M~Rvwgm4QLn&Bq!$o8!~9@p*%RW~=SE;L?n#ZE1OZZ2QKartMe(cQZg0YvSHlmZl`_g$vp)ruNT5;Z;G^wfbX7*#6b_`eLg@&x7^Mb_5N#SP+mE+O+X-W^aX(5AnlGM9qT8>`5{W*xHX7r&{W!uc)t$qEaLbOIwbsoqBLyo#*M*^0U6+hKuS6PqerjMP$i7h7F8i_@VSZ|0C8)wQz|tXDh|CtORM8lM+eKq`qnk|#tVB(jjL{v{l*#DaTBXssrv_GnKOVx=r0jxd~3rg#ja@MmxV5(flF#!{6``<^m%wC20};`MD7Np>fflY=szqtKkXUMIH&)wR;W|1!{BV{Ok+-RfY30gd*lQ**3`foW^FFdH>=C@HFRh!6_YO4&zEzAprW#z<9ejf(9<(vE_kho=Gjw(87-buJ8$+CAiK4TNvC(8F0Y;T6}VpI(+MKui*qrEXVege!}fk^(Xk1_Os08(t}!3DQ7p?z1E-8iHsQldhLUVGAPE*7+8%xwNEMydoh8+G&DBIv+G8(uh}>&AIc@rs`1>GB9e3R{$Ap#4Dob4Oy%dpdn;9J}NrMm?ztnklEu#W(yhQ0i5=Yiq6QZl7%5&3M`5|A`9_0ypJ@*KNK&50?k>vjkgRDmn^eFs%F0MC`p=I&2W87vNQ5!1k=8ZDE3^A0GY=NFdPwkHhV&V;dCZ`Tb3;&7R&Q=+Ikq~hu4jT|Z7tb*hBU6>f(e#(s=^DZf-7z&b$S#)>I6=8$gIhP~N92xwr5k41OZ;amTOUSxSSwCicF2*RLMV^>YJXTiTJVyD-+lV0|10W*9AQEbB5Gf)^q!szO`MOOxYm-3)zHl1M%4??jr);JNQJfh-O<+@*3#?$oa*T?JK#c}W1Wpen5e-Mg1U7M$c!<)l6|pIy#JMEPmPyizL5L6Mg3cWrED`*Pg5%pyZcqnDQd*hum^C;m3Jx|^g9tcea^NISdo&PxcWSlvm>t(Xf4VzAeFsKaxGq2X@p@@jWZdM2TbhZ?Zp;A%UPU1r*UOIp1&z1^0UpPMK|#4%p&vPM50-MZs#30?h;5-<{qg&61?P(W-Eo56{^8$#I04I_!X_z?QL$dyf1{s{RUs?AslBo^C{LP7B~P^;eKwH5G{sZRa^6<#T(fp^;{*9ox}6`zMJqpQbM=iAy1uycI<=Qv`3KrcRk>80R9KD-+1rh&t}r3}CzO-ynRflOrFTNpJq7pw^XdJ?`;Zm+0=;}3l%td?-A<_rQLa#`o>5L?VcFesEi^1lNh=QvU}lUsm>B_>!PLMTQ-^t<%q`l++yV#vnu~ps4awhagN+5>HnLYUEEHs~N?4GBJ%@!pewc3Ohec7QVepmq=;CLTyD4Ruv~$X$Fndl}2{R$!{4>lwG&J2xLu(FkB@eAK#M#kpE<@ZSpd2T!=~nU@CbX5kW>Lo2p-dz<*3`fo&xu4L`OQkVg_f?oSJ;>L_F(3T<`R47(G5h1NXBQ0(lFNDP?UtG^9p}anw~ABT6lU8*;tad4}`vr13mR7bX|3B@}bH_OWy4{{TxrOa~^%(Tr-z{vf;%bhcmUP|SpyYOI&bWRhtj&{KP_O%0AR^LU@2D5z_#*5vsJ_fVKkp#Z7@cw>xWQFKYVg^7RbibOi2sRH1oZ|Gp#NTF!TtE1G7Lju6!D$rZ$1)0kDt6ESNa3aW<=tv01B-7HrmMJckfqb&LR8;#ncUKI1urGpl2q*#J*6dpw_pW1EjvHIl7eqV_w8?OJv6yx|-{t5I_E)TzeF#frScXL-bDdBmrcN9>~iD%M8--G02~#O;y8ic(`uVK`A{YtGI$t24I+Lm|qA!adRo(DkdFdtuL6K?X`$#)@vdZ~enAvaVunWZn5-l1!~-xQ$v1pfKk4n_|WQ6flL-SneH^ad2T7&Q@<(ajNTNT0|0eRk1eiYNeOhWA&!oOA?u;F-&L}Iiwa7$0Usx8Uw}iLQ7BxA$-E1B(pffXj-y3E78;j(t}0Qrx6V7;#@M-#<{eZVBvRzYGSOZvEg+VBg}3jN$T~#;Bk+G%-(s8g;PWdG7ZOuQ4uSSL68`6FHWZpD%nOIwB4BaP2CJhV@(abF_Uh*8`qE1jOz#E$NoCdLMz6q<@-Lr8Fy7)J0!9P8n&l`h#7V+S$4hk3d`s#)nMXCoedQmJ8rv{A!g?7^Jbu?LLY54>z0d4{R!jiy--=5iH2V%?)VJR;wE=vSpr3LPqydL+7(uYek?p5*eUTLR@kFbpR*^}|4|TKLppNTwn&9Hk;vW(c5n445GpAr48zA;qG^q3Y}r-SATO-JFYh{a%nJCbo+7-}myhJf*8Vi{5)r%UYr2SVrkHL{cQ6y$_>@rb8Xyc~rbrHmaJv-@>Ejxo6y)Yi|5xiUl{|TK^78oV?C#E8mlY5G@npQz$0kr+Mwde7HUPd~x^j(}(+_BfkD+^ZF^XT6GG+=>5f2G_&1YU1N&=IJ^3Ax4pO}Mqs=UQ0&3i7VtF#ADaJN{bi2Vmn*xO1^Ng_R%D}Xq%QueQT<;&g6HYkYt!>e1{-?LI9f1{N9lQDma5Sy*0|<)B~t~*1uOlgL@y}#3g245w~Sz|ZucauPX|D9HX1{q%t&`f;1T_PaMoG0?t11Kwrh^*f@3zUUAK%$7>RJ|ksV=3I0+(}wQNBv(?U8dEtDAH<`%SxW`?`$O4}td#8gQs&B@8yMl{W&S>PonaxSM-v}KH48=D;%Awuy@YFOyT@Tr1r70zhM-8pyk_@`|pYl0x8>_=agC$~3*C@AQRgfRsS4ZJibt2gHS_;Pi=wVe^$)iSOLM7TvhWD=zm4e22SlC^v@DWlnYg!np+!DZ-jBPwMg-;xT~0-x6d)+6DhBogtH?gAr+6W5}S6NDv!m&)S=iKfL#U}U)6fTHy%aH6MQZa;m#IQ@P5E{E#HuWw&f*OnT~O2ZL^OoO9VVw4CrXgKSo04RT8h+8ZHDwLlwG}&gv8Dt{2uSd9Hb5y`yz~VnXXFnlCAyB2(9oh>v2St0$OR?v3=9ptoC{8j5~gUgrcfrd@%59Gb(oaaT;?!gA}mZ`cz9-Hl0Vm^-wI_jb4a_OPdELYNA;f{>z*Yx};uk!w91A)i~L!{*k#n-mfdU<3`?fKhr1iRB)B_4njKE^@0U7H*v)D;nDPSyDz9mb~nGi;3Rm<{q1a2MhwGv}(){3m6KPtmDLaZ%|g?ZeAE%VR_Y5)ZSuP?OmBN%rL1D8xIYMT^ARkxiH|e+sfxW8uqp6MEmHrtLK>2L_ai7OmIhvBg;d)$OpewY(Hkn@r7k#ZT)@wYq9>Gs>L!O{xGfvJHv%<<~q=6-X&x?e+gDYIinv5xT@jCr|Ds%Qp#3&k5mnn*=cQ{!<)enSq%em@Sz*_9pg;sI!k;uSr{^$Bfn>o?m7nkl%#lO!*Cnir8&Hkl<@sAXGws#sK7lIN8`;BK}d-PMLF@!h-8SbyKei)=(a|=59$sd;tp?fhcxaEK5S!)q)1t(t{b@;T;aeSn!Cd^bMDx_ZtV=baR_&0{O;7GEJ(E{L48Fy5>?qn}KiJyFcpS;sg(sDnsZMS4B?N&tR>!SG&uAjnazEMr`e$d7rj7)bf@4N|InsH8Cb@pz8kd%yN$9A;9KU`gO?D~^n$5{LK`13B$f*;{K38czvOF9$r2O%u(@9w*{sH2aF#Af%vEV}QJQ2|dSpHmu3p<~=+6>^XMv+)Q3)Bg0)RfoJ)gD~EC9{{!Q!zU$#Mk_qkJT9%6zFCRouyP2@csGZG=C&PyetU$sr!eHjh{{piA+19`$5Im_a^-I6`)HalJV@?oNsZ=?O?mpOdDA6*Kfzn5a^_KK^YVFvNX|Bab-3q>oqn4!Bf1Xh|frKpqF-+!4skuo$kT_5$O>0mWoiSHPlv2^HQW7E39hpJy79hVFWqo_eG~HZ%bLAMe(?Jk(7Vt}3Sv@Gt;L89GHSeGnTW|aZ))KY?GRBw~BVq!>Pyb0~*2-<|!bAgNLoO&F{T0(mHfM_Lk*Uoic&m%}-pJ3-Dt*c{a*Y|DFIb`BFv+G2rP{y&$JHv6@ry`4G;?)=ty65c3`x>+cCM@O%N!_uO#1>v3i0tHP;ust|5YTW3=i6^n4P!m(E@(a6n<#-=Ikx-qw9*}!Rv>cX)Dr?!vd=^KAGZ^aqMq%pg%!Pn*BnJN_clg(E>u0v@zyO`s)Q%`M&7}br!*_L8995Yqi^tLN=gOs^@w0w0U#E5z%J-^YPlAh>eN8i$crqK#AA;93l~&36)GXXF@qz@tVk$vvT2BNXAa#S1=O_Re|u_&y$ZAgmAR|c$;x~B&K=+)jc)#y9@hWcT(oUnwjly|6FbVGH2)O?eTVdf4@3Azpt@CNjhmVyX87^ZWM}~8VIEA1h6Y^dP@t;!Q^zLr+`@2`tgnq9o5;scGxjhp1n6*-p>COxd(g^CG&`zN6`k^qEM*0iYXrdfuH6ktlPzRwYG>{O5Yom^@AAi-27$H+lOx0a2zyTsBNkyn=_q3}8-y^3gWXP(bK)`m)_Nh>0dQ1C$0m?J08*IFT;Bv%C8LAJ%IFUcu&90*`=J`Xjw`C&7?u((5kLw$mA4_pQ`sgCoq>fBY7uN-XtbVl)5M=D*^rcON$|-btYh1t+Nv3cQDZSq^bLfS_m28OQSW$BG|eaqZn|`;T&Lw-M$sL1S(T(3)>uB3a9YSuO?462C8TsE$_vGIXC9x|otB>Q%$iW@NBz>-xG;3L4jU*b^W#RRZ%8#G{K`hIK+*?e2+yLHV{;ddSqtRrAi6JuGG!Ak=q6my+X}ro3o@Z+eDL(&^Vn1yT~(~s_xCE5@{U&fT`%rNnJmY-gSyn|Y2@lHjh6Gj&3{=mm0L>M?35xLp2TZi2b?8UyGW#166ML|p^FWJm+o}U%Asvz^V&tGkNoL6*o@X1CTG_(P1D;+6@9R*Mz@8gRa+<16GIiXS_zov(4l|b8DdG3^pQ7C(XI+OTH5L(DAz(Jn@s-WPuGFwl{I$Klq9O;NCYT0o0Gz39F3P#+a!V?nfcPI5^EI^#fX5f+{am@w#>bbR}SY1#9qX-HUqNUvi-v_An_kYEd`YyMMLrXl-(dPr2CPi103v^R|{NLaOtprmtW-7uaG5U`~Vl_AG_G+T=O5ynv135MVX4lf@D53iF0q2bN5rI-x__}3ap*i%)Nslxj`v!&R(@Qfs|uVHq(rEuQOu=9R$AT**|4aICAGDKu0By3!<9)7e4_JPM1$ZoS2AqR(3Lm|h>anQJGL2kc34@d}bZXnz2mLt-Gr)8H&_I#k$vs(T<>~xH%b6RT0+dfFz9#(*429K65(cS@QLBatCK*Gy2I{+N=US~1RY2m97^||C?jmo52^kF0AoQTg(ID=K!Ru&JwV3+;9xg0ak}I^KOkQ#OAfIh+50msJf`Z;uo*eXoterfi@#)@x6Cojq;qaw|R?LXeUM7ANs`mJs)em)I}UX9$nB+#WK>Pcl~N%ymN*lA{;h;E&1Ambl8Ps*Lu%BD-o*B}0E=*6!xaRa0^Tr?D4Z|>v!hmV{0uRgZJZE~I0l5I0^98>}8s5<%9M3h_fS5UDdq1&j?snt<=w#$7~-MOJcQwQaNU7-S$w$)_1961J+4sl-3*SEH{&QNM+&*P9t)2UE}k^Sl|K^KFAKo)0!P^HQugnLkOrg}^OEP{01Q;CjuL5H`lek}AK6(Nxr1XwM;WI_f#J^nlxmyMg^KxxCSY(F4Q>2{G^9Z{EFcd0tK~<93c0%#4-iqw_Lrrh?ALk}7$VeRM`@Mv^;uap<(+(7v~JK;1s8nJW7?93OVk`4Ci2tus39{2m?Cs{BPeSEB1*m5w8wcw;adu(ck-^sIp>@xcr>PsF7Q(!lvtTrQ~voy~F}MAdt{VK&&FU6!eG<1m${8lB0T2Kd_D*hKn=~g%s0+0=Pd(ie7A#ffYPV~R-(+4f~XD%E)S5IvqEMF5MCZ2I|q;*0z{_*G#$}dOWuXKHy+mEQw9A~KsV>M2`Y>2f%N1=`K$v`H3#C1Imwpu`^aWJ5>{`Y)5{|)aB@xpXFQ7_aB5kEEu3B!p#w*)3a64o&;vPyt)}&I2pwh9=U2Az3_^c(%+TuKrLB&g1IG@*p;N#a&mDwkGVj`gw$E;#-A&~V#(TnSUjO(%AAb7dhhNGrF~Pu7wqaSeK?-ttJO2IkeFSt4qPlh9uP)=TU5{GMq1X2{p)EyFZ6j%rBgB43CTP2znJ7PJ2j3Y~vHMo;jO!?kCg7izdp?Qu`@LY5SEO?h7xYiksbB0PtQ`l_SZ>gpvPwhE<)6Jr@aMd;)xhf527{v&I5?1=9;CL_-Tm+Lj9_a|+M4fCqs$;HSYe(Exa@92DT)S+#c})LtYCT&la?+cj6u$_Tn%*;2RjX`*QwZ}v?O>;?-MlX~gPy0O=7%wmV3*EQe*?2%PQ;lef5k_0-}G7mu8vYz8)N!0f&}4tmo3kZI&hkHK>hU8mRAzspWB^_W0NwH=de;iv}e=BCFPoRLEQhqF|tZ?c>edt-`@Xl|K^2QA9+B(|JL6=-8x97C%UFJ=czzVrm>u~@(I#K^3{tuH88=Gf67WN%}UAGpjQuXzkEw2ruBiV9?Y&xFCc6Zn@vdJl;xG(S01iNvD4SQWFTn)WGJ*20sjOcT(oGVuyG7DjbN`VUM(#Av?bgb57C7eKE%WMfI40XamIm)GJGk?B%Fu^E7nBfq6SVcQHs+?np(5&Jf34eCfJu=Fz!+rt_9sI@(gwesxAm`dIry*H*`_UpGZ?)D@t`_$aNAX0PNR54BlhmBKvyj=#h@Ga*AD0Y7kYuz|QEJ#`zoZXcYHJyel=^N#T(>EstMQE|oq}T695vK3AQi{2$m`XjNYso}R-K+3$q)NgvfWA*(z|m9i-8BKv@nwWC{U)z6vOq1_ceMJbk7G%I`oa*U`G*WTgVHlv@SVkXh)G9kdxXV2DgqN+ziz#bKw1$W2fa9x>EugowgSYGs_9CqZLyj`H7_W5H4RusrR_l@~#TsM{-2jFCwB%K6=6r-2d7b7Nob+sQq73ecTN1!VfIn#QGd;C50}%tQxot2Sx>1zH4;kXXvI>WtrnypOLN+Eu*v)JBE>F9Yh;)u_VtWqvfHajq}!T&D8eLN$1UiL+3!59aZhU;olP}^b>hPh4N4J3wg}Sb8KWrdZ`k0EORDrx@DpV@Z~GJ?nmgEPpu}?8mf=S#U@N>tT4m3wn$td2Sfv0w(m}bQOI+uv^{fFnn%#oN_ucRep}^&|HAivA{@K<$S*(THWi=pf4~`vnqhbnV}|y3q{};9TdUgW#Zr%Z0y}xdns7!E)W8LZ^WM&fMWcap$M0?S39Jg@wYhF)y^x>e$FAxZ(nn)!aH3f?`WOTm3BT?#5-Os@8*i-ZmwAF_KM|huUPKxiskOESnmFc*<&!_reHC5{Onlx97V%DwNnwywVy4LCuBn`!^RNc{#9FU0y>5WIATnFks199GCyQ70(l!D9s_x|?jR*Y`~n5^&w$R_c8_N~qw8>!!Iqq%VFv||~sjb(FvQa0BoWqW;6w$~?RcYRWJ*C%CveNy&km-6C(YgeC+wb9v4z||#c1zfu#c5H@ccgpmPJ9of!2z*~1)Ycy7o{1#nvaW=0w(xz(=m~Tby2u|~KKM$ojVet|?GmLab%+Icy92MhfJep=g)Z_3=K(*n0In~C)Ow6#ok{DWb3Nv9I39hM@%=OH1Cc_IdFpeXWdvuR-efF$lOf|1U5Ib*U%ceV*XzJ*#moFfdoWB0K7RN2dwGlMExD*}DTL4J5yfx6{Pg4d4?q0(&!2w&wfp8N<1VF9ud&DGiFPO04I5A;QEE=+t@51HGJ{ijMVu*7;{HkNe8Bn{{NVtPDaTnAK?vNeTx!fIP!GpDxk(|YXC!%D{oHvIp_z^9bmQ0147OKhNUHK^DjEu648+ksqx3t85@p4X=q?8vhP3&~{8^=?pXIds=`}K*#(X1Ez=LM*SbiJSI0Jh^$yLKt)Ik`0CafSjrx3U6T!?E;Sae}eopi^t&ea=D?$IN@x?;=y!xJAqH@fQJZ$w;S6(Nh%U#IkO`$&>Au=|9h8XjMK$RpdH!?7P)K_dl&=_$P|`Gp15X+WEn(ae&2Wo7JW835787X>ZbF#vRG^z3869)O1?$K9ZSNVB3D)OSP{Yonf$;=Mrpd#E#u6mQ;2Bb1xc=~I3_jHA!;}BjrJ2eowDSH9vz5uXkLT4XXKsh`ku8d;Y|U&oXYD2FKGiQ#bO?gV)?omR-Y@d97_~IUc(tjZ?iYt8SWAH+_uHV|C(M5%~Xy5Wvit%-ytmbI#+_)#Ac-Z>XG&-@JVTufL1N1Z(0A-70|3W~kAOF_8~neUJVv#*SFL8tjXthfkD<9D4kJXIHxeFa!f1Xg`+pL(=zuv8_dl)!2R$IUE{k?>tyQG;@Sdur{z|EBi2R&kV;iuHnwoGxxC{>H8pdmY&FWD3RsU)CFA3s!a#f91xYLY`xmN3}3_q+T!WVz9Bx$iU|N_~+DNwl?ENb!PnBzD$ANx7oXb=Zj4^jGW`JZf_X~xwOsK)Y0M1UP`j5Y-TLOd-0{IEqu@ehPM^c~PIelK;Eq?gnu0QbZMw9!_EdQx^@s(xCKYnlr&pR_OPY^+f5(LLSmFoH9ubLfaX8n6Fe{4^^L+l+E8N|<+I-}$`)9rM>z`0y!Jf7xmJF`x%G@N?(H-j8pp3^M%WpqDkPdnqjH=MTby-Clzg~RP~qxgl&#{o{wKy#Nji0HiZ@PyCiY_W8(;F;L##G;44v=IA&BkL-?a0hw~CR=hqhWw3S!y_<*r;MUy;1DJ3OnpQZ6t0W>s9cRX)!ME`jK;oEW;rBQ*@$RPHANga1+i(%L2YSIxa2B34?cdGv$M!FG7l7m%qlcL{wKC0ne|GN21F!wn8@Io9?>fWbC_AyIv$N?}Aid}hX5M5Y>76^B{dPY9+Dh%>I{!bF^L(*dseLLm+RaM2R=KDY3$My?F^vFy3`U(LyQ7I0Jg+|-Kg@Cg`?)UYZP(lMfM0jvc?8P&$Af1%wYQu(1)XNx!-B4ofv%FxT(~}YmMIJd-oP`V3r*#!UMRLq^S7%H*Hu#nEixBgXZA4h+B10Ye8+sKT(^F!mrUvNbwvW+l!87&MVE9mA+}V8im@qxu_P(&7h&}=Jm%0oVqO6itWm|X_PLSrC-}ug;w#>EY5vuwy!VXM9cU+pM_O4r(p}nSmoz-Wn%+M-mU8QL1m!;bEs<=O170d0bPt}N4?X2f#nd*nkKL`Eay}`H4jW>i-Kb~ejeQaj_`7r!_IQq|Ug&fXR>kImEXZB?T)}!D3F;-8%{@xq3AMU%owr`}#JEGbc42Ehm60g3WekoVm#rX=1|23@@T)kJNc3EmvTnB$NH{pAvW9j0$0lm@P`V00a%%?_2Q)_3lDdmQ%CmmYU5rl$-mo|Ok|#_Pjs(G{3)g=`WrUinoLpW?vDOg1M5t*jHP*`dG>RhBY)ODIXGDsmmhc6&LK<@-P!hFRP)iIqM?xl1FPq9Wrb-B!M6DLoOi;mqwQABttQA9Y!R43wy7b4Y&awd7AjPOFF3S-R)PHxIVq*5U%2}|a4AyUv5qO?kE30X)~P~el3#FmhSK$*fsZxIk#$dhA=7#E4s{~X^tp-B>P5$&D7Et!OlzU9_et;OvG7dlE>ylh-w9o4U!N0sv{0Qk1%K;>X7ecU`T1)7ec&(i2%&$cx-TF4A1s&eQV7>LH^EVwGa?owSo_Y^ZAE{PxHAN9Ed!`VPhK++J)zZ+P`@E%DG=krTTm8fAghUvyAKymQ-M7YFD*F3mc}WqUIgWf|-54?p*Vg3w#D4=4fJX`+m)H=KDjCZhvM2s=}?GxdrVApP6hr^U)8?Hl6-F*m%p^$W3PxNY^_ya9Rio+8sgxlB0af-1nz8Uh>*OPG_zl6K)h*r8yu`oLZC4(09xBRLh;BU}F$B;~+tStQsC`c#fMWO%|VZvjXel&n)~>zT77XN&efN!^(sLJ2eUQw^_u@7+SK4NO4F(fI~?FHDp;R__@FH^6R!%-TC3q&+OffgYPPJ-3|v)$Widphe(X6@R=vopTc6bc4`f0*IgRU2?1T1u(1IM)8Hk}Q>=R(Ho0lSoE2K&o^aPy&g0f4OuqfTQ8vHN8Jx#r!3KqSry$$>zNXLyr?LA<%#<-6-4O{HkD~XAqVpPxEK{CDqSXs*t5prcz54vMusr9Dx-MS`jwy-k%93Y@NAAn=mFd0nR{8y6r}-;G6N#nX_S5V&QBQY!l7Y3vl}WsN6a`uODH9&Nw=P%g*q8W0MI%B?M6f(und=Avu|_$%0f`L^6fAG~skSc$i-Ghvbd(1^>9)!$I~i9S{0luWcK64~j^3$|?L0uaQ(JrjatmYO(gq2SXLn+Pp(qCghtZ6|TuaQhIs+*IWvt`|;>uc$+4BD40M9x1-@`vgmG?mGb4B^C%$k*#l(b>%lS2VG<>BhL#EZ6E6Q;SeP6F?glZA$VsuOp>GQN0TYasCd&|sAQBD~M3!UM>EHvEt3A?oLx{|j+cO58SX1+i+)BM38=)LHhX_@c0lQ#d_LNgy`aqm=bcc?{e<95CG#~V|~9ZP7};sA+emkkXUsie(iCjo~V^pJA?=aP)U3}uWv_Zlxdz{g3=+vAlgF*=kEg`*Svi>A%k)pM`76D{g__!eln*_l*Z4gI4%EN3|9)7VD{8F3po|Rs_9LPLd*c6fnD?OT+__Tz1*zWGsPcumxf%LrPeM?I8D*sE#^#6jn=|H3awj@{ha*@onKlmSLTD{54&p6qit5Wp5U`Jk0n;Qim4JTHp@ssFRBFD_%LBUkt$zL88M)>h~crLkM8p`JMsTYw_SJ(x6Pshd<(a23!+#SzfGYFAOlCC3)q5a(G+{#T&vf0ku?Z`GhvHrNQ0{(uDXU1V`vwHG>EF_Nu-$O(uO_q@XW6&vPEX`8vMU;OO{##!0;F%DQG&9+XfqPtD2(n{*T%OL-KWssyvQ=2P}PmHJx12Y;IQ87YStB+JGOo&4Kq}W7)Ag$~NE~JejHX0h}%~(f9A4yiIWf5}S-o&$e67OLi2L=;%w&w;5%W^DA88{aHc91-ycM(Ehy4AZRF-JAUhbQx-ppinT9HI2XDTdxo=BpE*v$EY)z~b(7uXzfJ%YWM>XMpo=8+dXWozVx=aCirdw}U>BCG6cM^ipC!_M8E*PVH{_0D7^%-U(f`4eL&wy7G$FtL3mwi-1ZW2y?%q2YFP0uuwf<~&z3<<2Zu=*)~wVW=YF#I8r@;HecfYL_B2I>C>aq4q2x6I+>h9}bx$bJl|grKV?K?v(?f*cMZb^*)FsA)=uW#KuQ7L_3kd_PIo|uW<^aOV_ox-6|pAV5{@`Ljec&WeD5nV($4$JZ!zh6BxuuiRTHXaF^k!fVX7~fzLRLuijwEcbUh!TlEJ2UA_5x5=(f>>TEP__d5Ndcl#_Qn~h-yWi(+B3}fE%CWdLimr*-K-ZXOmGR0me*Xng3w3i(FQze6;U@j9(h{{450D-#*1@ky7HQp4=zt|ALqrwuz{UHKqtDo1rIPl+}i11f)!S=O8`szboY}1ezrPv?zqxi6ye@rk$xi5Lxz83TGCjDtKQeeH;hQS_fw>QT~sacL00VDGb#83=zP(>k=XZg^rvwW7ZRBqFRABNXf5uHB%jRR|QexCjcfQ>;8wXv+J*IU?diin++n3WJKekV)*Q^Y?GgD5cZ@eh&fD_2A${;@P}bqA*^68~T&?7|PfA1P$}5$6Q(R|a+?{RmU3?3+9g^dpGk1<@|=&`8@CG}ta>7Xy34+r?5~O$iTK5;v8eFsbH~>XBTXX3wE>2Imx^tKAHp1o=w5f!P@|Mk$jqt4Fno()gt+j#n|$ObNP(89BC?X)Fv78rV&Z**+tsA$E=;MOWR7qw&{_Q?a_1-o6oYv67kz3lz|}|4ckew^kRL?Nt*tTp&bVyh&1tRLGSXo6L!5>iST_ktNPQUkQPzxvZa8L8^#aoVgOGArD2Q!shB@>$git7&PPyC@Yxy{)+)yLuvPWiLvi7R(Vp$!m11RX7R#K5zRS|ne2m&e;f!A2Kx3PQu#;jU#dqo}?&RB*PLdR?0Evpb^Xfp@H4Qh6dd5c4&Yo%dOTZwGIt|Q$94*btpv{gu&3EC^~d#)@on&Wh*j@jUWE5^(c$YA_AWGD2RQ(iynpXE@~6xOc0-~L8Hi`M^QFc8z2O=IrJX2?sMay;r_B*E!UxuOK7NHU8V*I0UCP1&@lS~%9zU6%80F_as3H0fz>h%Mno*iG}k5gj40mH!+fF*Ac2OdC`c542R@5ICWW`f$3BsRM$*X3kC6(yEGC`t0gVJgh;-yZLnAb1TcNQ;vGFlOl4}%+k0rzcd*aO>Qxi^sp1@3RuC=R(g>uw>RTwgN|3wM}ZB9C07MiUIbs8K9RnknnnNz~x-RfIXYKG9uGMHwfQA%Fb8m}}mW6%->>j3>1@xu14B)#Q5`e}FvzHmx83;b%*y&+CM}aDK$eI!Hh<6j@q}8T)GGal0*GgJty^7Go-*pBEmO+GlN{6cjJg1EIcwZf>EZGAKca_Bdl=MdvI?s0YU@2rk<;sZn2l^wt9!|W+dQ1Q=1=p&>@Dj6C{(mk1$bczxy!ZcOOul?;*sHLMok7_LR_r3^AmVTCDLJS(M<2T!QwdOXZm6H5mG}TTy+1OvVu!$vlz4YZ-h02*q-9M3dS)p$Fma{Z`DO<^1{~8DprST_UEBO7>E(YY3F`l-_h=o9J;uIMNL98uMunDxypW_|jD$UXh`YRL=!-6gcyB|B#CN#a=hhsjy{Eg5cJD@>=32Q2X#`0Tl{i(73H)5oj8oO_3&>hgA;puxJG*oo%Uh3Jf`-TSF0S&eR4IM$l4(J~&8um+`2~S32PP3dR6Rd0^SZVp>Niutc2GJC2l#IrlW;vU4{%zTS$Wk}_shoB-e7dQe`-TSI0gaXEWlJ;&iq0(qFPm;|*}kDcc0j}TDOBnR8p{QeMEWzJwE-$Oka3u3#Mq5sTKFna)QmbfSk$S=12&_MQ?Y|`hz-iYBg!GEI#lJr1b)_EW3+@KAXqLiu{cn-APKK5EwO9e(k(4{SrB$xkfs>8%P1(2eQ=Q_k6VHk{;pPkA=+EWcD`H{DYel>uF@=BEolwE3txe076%S+-q8mvg4u;1e$h&Faf9S_~)F*-EZfVRP^BV+}QFnyBnuS{@+ta!=?putk~gK48)%`9PILPT9H~hGwgrHfQA06d@$)QiLF`w<`EH7#esvbL5f)BdF{YjBwpmK@Iplbk`(3386@ro&-@vqf^jb$;`WJlH7#UU2+ppRaxYqS^+~qPR-gb}1Ep%R8mQ-s#zPE$s!k0C{{d37X!?Nv1+GUcJjLEIjRmIm>A0pW36tzwS~8%>X;9!1c7Ol^c61vn_~65w!S8GsA_V>~#G>Lf2uIW+Gq%aNUzrivrOMw$hTL9BzYHnEQF$6GA<+lza{1vg;mc86|PZ_U~9eVQ#d$ut#=moltDPxlym&M~Rvwgm4QLn&Bq!$o8!~9@p*%RW~=SE;L?n#ZE1OZZ2QKartMe(cQZg0YvSHlmZl`_g$vp)ruNT5;Z;G^wfbX7*#6b_`eLg@&x7^Mb_5N#SP+mE+O+X-W^aX(5AnlGM9qT8>`5{W*xHX7r&{W!uc)t$qEaLbOIwbsoqBLyo#*M*^0U6+hKuS6PqerjMP$i7h7F8i_@VSZ|0C8)wQz|tXDh|CtORM8lM+eKq`qnk|#tVB(jjL{v{l*#DaTBXssrv_GnKOVx=r0jxd~3rg#ja@MmxV5(flF#!{6``<^m%wC20};`MD7Np>fflY=szqtKkXUMIH&)wR;W|1!{BV{Ok+-RfY30gd*lQ**3`foW^FFdH>=C@HFRh!6_YO4&zEzAprW#z<9ejf(9<(vE_kho=Gjw(87-buJ8$+CAiK4TNvC(8F0Y;T6}VpI(+MKui*qrEXVege!}fk^(Xk1_Os08(t}!3DQ7p?z1E-8iHsQldhLUVGAPE*7+8%xwNEMydoh8+G&DBIv+G8(uh}>&AIc@rs`1>GB9e3R{$Ap#4Dob4Oy%dpdn;9J}NrMm?ztnklEu#W(yhQ0i5=Yiq6QZl7%5&3M`5|A`9_0ypJ@*KNK&50?k>vjkgRDmn^eFs%F0MC`p=I&2W87vNQ5!1k=8ZDE3^A0GY=NFdPwkHhV&V;dCZ`Tb3;&7R&Q=+Ikq~hu4jT|Z7tb*hBU6>f(e#(s=^DZf-7z&b$S#)>I6=8$gIhP~N92xwr5k41OZ;amTOUSxSSwCicF2*RLMV^>YJXTiTJVyD-+lV0|10W*9AQEbB5Gf)^q!szO`MOOxYm-3)zHl1M%4??jr);JNQJfh-O<+@*3#?$oa*T?JK#c}W1Wpen5e-Mg1U7M$c!<)l6|pIy#JMEPmPyizL5L6Mg3cWrED`*Pg5%pyZcqnDQd*hum^C;m3Jx|^g9tcea^NISdo&PxcWSlvm>t(Xf4VzAeFsKaxGq2X@p@@jWZdM2TbhZ?Zp;A%UPU1r*UOIp1&z1^0UpPMK|#4%p&vPM50-MZs#30?h;5-<{qg&61?P(W-Eo56{^8$#I04I_!X_z?QL$dyf1{s{RUs?AslBo^C{LP7B~P^;eKwH5G{sZRa^6<#T(fp^;{*9ox}6`zMJqpQbM=iAy1uycI<=Qv`3KrcRk>80R9KD-+1rh&t}r3}CzO-ynRflOrFTNpJq7pw^XdJ?`;Zm+0=;}3l%td?-A<_rQLa#`o>5L?VcFesEi^1lNh=QvU}lUsm>B_>!PLMTQ-^t<%q`l++yV#vnu~ps4awhagN+5>HnLYUEEHs~N?4GBJ%@!pewc3Ohec7QVepmq=;CLTyD4Ruv~$X$Fndl}2{R$!{4>lwG&J2xLu(FkB@eAK#M#kpE<@ZSpd2T!=~nU@CbX5kW>Lo2p-dz<*3`fo&xu4L`OQkVg_f?oSJ;>L_F(3T<`R47(G5h1NXBQ0(lFNDP?UtG^9p}anw~ABT6lU8*;tad4}`vr13mR7bX|3B@}bH_OWy4{{TxrOa~^%(Tr-z{vf;%bhcmUP|SpyYOI&bWRhtj&{KP_O%0AR^LU@2D5z_#*5vsJ_fVKkp#Z7@cw>xWQFKYVg^7RbibOi2sRH1oZ|Gp#NTF!TtE1G7Lju6!D$rZ$1)0kDt6ESNa3aW<=tv01B-7HrmMJckfqb&LR8;#ncUKI1urGpl2q*#J*6dpw_pW1EjvHIl7eqV_w8?OJv6yx|-{t5I_E)TzeF#frScXL-bDdBmrcN9>~iD%M8--G02~#O;y8ic(`uVK`A{YtGI$t24I+Lm|qA!adRo(DkdFdtuL6K?X`$#)@vdZ~enAvaVunWZn5-l1!~-xQ$v1pfKk4n_|WQ6flL-SneH^ad2T7&Q@<(ajNTNT0|0eRk1eiYNeOhWA&!oOA?u;F-&L}Iiwa7$0Usx8Uw}iLQ7BxA$-E1B(pffXj-y3E78;j(t}0Qrx6V7;#@M-#<{eZVBvRzYGSOZvEg+VBg}3jN$T~#;Bk+G%-(s8g;PWdG7ZOuQ4uSSL68`6FHWZpD%nOIwB4BaP2CJhV@(abF_Uh*8`qE1jOz#E$NoCdLMz6q<@-Lr8Fy7)J0!9P8n&l`h#7V+S$4hk3d`s#)nMXCoedQmJ8rv{A!g?7^Jbu?LLY54>z0d4{R!jiy--=5iH2V%?)VJR;wE=vSpr3LPqydL+7(uYek?p5*eUTLR@kFbpR*^}|4|TKLppNTwn&9Hk;vW(c5n445GpAr48zA;qG^q3Y}r-SATO-JFYh{a%nJCbo+7-}myhJf*8Vi{5)r%UYr2SVrkHL{cQ6y$_>@rb8Xyc~rbrHmaJv-@>Ejxo6y)Yi|5xiUl{|TK^78oV?C#E8mlY5G@npQz$0kr+Mwde7HUPd~x^j(}(+_BfkD+^ZF^XT6GG+=>5f2G_&1YU1N&=IJ^3Ax4pO}Mqs=UQ0&3i7VtF#ADaJN{bi2Vmn*xO1^Ng_R%D}Xq%QueQT<;&g6HYkYt!>e1{-?LI9f1{N9lQDma5Sy*0|<)B~t~*1uOlgL@y}#3g245w~Sz|ZucauPX|D9HX1{q%t&`f;1T_PaMoG0?t11Kwrh^*f@3zUUAK%$7>RJ|ksV=3I0+(}wQNBv(?U8dEtDAH<`%SxW`?`$O4}td#8gQs&B@8yMl{W&S>PonaxSM-v}KH48=D;%Awuy@YFOyT@Tr1r70zhM-8pyk_@`|pYl0x8>_=agC$~3*C@AQRgfRsS4ZJibt2gHS_;Pi=wVe^$)iSOLM7TvhWD=zm4e22SlC^v@DWlnYg!np+!DZ-jBPwMg-;xT~0-x6d)+6DhBogtH?gAr+6W5}S6NDv!m&)S=iKfL#U}U)6fTHy%aH6MQZa;m#IQ@P5E{E#HuWw&f*OnT~O2ZL^OoO9VVw4CrXgKSo04RT8h+8ZHDwLlwG}&gv8Dt{2uSd9Hb5y`yz~VnXXFnlCAyB2(9oh>v2St0$OR?v3=9ptoC{8j5~gUgrcfrd@%59Gb(oaaT;?!gA}mZ`cz9-Hl0Vm^-wI_jb4a_OPdELYNA;f{>z*Yx};uk!w91A)i~L!{*k#n-mfdU<3`?fKhr1iRB)B_4njKE^@0U7H*v)D;nDPSyDz9mb~nGi;3Rm<{q1a2MhwGv}(){3m6KPtmDLaZ%|g?ZeAE%VR_Y5)ZSuP?OmBN%rL1D8xIYMT^ARkxiH|e+sfxW8uqp6MEmHrtLK>2L_ai7OmIhvBg;d)$OpewY(Hkn@r7k#ZT)@wYq9>Gs>L!O{xGfvJHv%<<~q=6-X&x?e+gDYIinv5xT@jCr|Ds%Qp#3&k5mnn*=cQ{!<)enSq%em@Sz*_9pg;sI!k;uSr{^$Bfn>o?m7nkl%#lO!*Cnir8&Hkl<@sAXGws#sK7lIN8`;BK}d-PMLF@!h-8SbyKei)=(a|=59$sd;tp?fhcxaEK5S!)q)1t(t{b@;T;aeSn!Cd^bMDx_ZtV=baR_&0{O;7GEJ(E{L48Fy5>?qn}KiJyFcpS;sg(sDnsZMS4B?N&tR>!SG&uAjnazEMr`e$d7rj7)bf@4N|InsH8Cb@pz8kd%yN$9A;9KU`gO?D~^n$5{LK`13B$f*;{K38czvOF9$r2O%u(@9w*{sH2aF#Af%vEV}QJQ2|dSpHmu3p<~=+6>^XMv+)Q3)Bg0)RfoJ)gD~EC9{{!Q!zU$#Mk_qkJT9%6zFCRouyP2@csGZG=C&PyetU$sr!eHjh{{piA+19`$5Im_a^-I6`)HalJV@?oNsZ=?O?mpOdDA6*Kfzn5a^_KK^YVFvNX|Bab-3q>oqn4!Bf1Xh|frKpqF-+!4skuo$kT_5$O>0mWoiSHPlv2^HQW7E39hpJy79hVFWqo_eG~HZ%bLAMe(?Jk(7Vt}3Sv@Gt;L89GHSeGnTW|aZ))KY?GRBw~BVq!>Pyb0~*2-<|!bAgNLoO&F{T0(mHfM_Lk*Uoic&m%}-pJ3-Dt*c{a*Y|DFIb`BFv+G2rP{y&$JHv6@ry`4G;?)=ty65c3`x>+cCM@O%N!_uO#1>v3i0tHP;ust|5YTW3=i6^n4P!m(E@(a6n<#-=Ikx-qw9*}!Rv>cX)Dr?!vd=^KAGZ^aqMq%pg%!Pn*BnJN_clg(E>u0v@zyO`s)Q%`M&7}br!*_L8995Yqi^tLN=gOs^@w0w0U#E5z%J-^YPlAh>eN8i$crqK#AA;93l~&36)GXXF@qz@tVk$vvT2BNXAa#S1=O_Re|u_&y$ZAgmAR|c$;x~B&K=+)jc)#y9@hWcT(oUnwjly|6FbVGH2)O?eTVdf4@3Azpt@CNjhmVyX87^ZWM}~8VIEA1h6Y^dP@t;!Q^zLr+`@2`tgnq9o5;scGxjhp1n6*-p>COxd(g^CG&`zN6`k^qEM*0iYXrdfuH6ktlPzRwYG>{O5Yom^@AAi-27$H+lOx0a2zyTsBNkyn=_q3}8-y^3gWXP(bK)`m)_Nh>0dQ1C$0m?J08*IFT;Bv%C8LAJ%IFUcu&90*`=J`Xjw`C&7?u((5kLw$mA4_pQ`sgCoq>fBY7uN-XtbVl)5M=D*^rcON$|-btYh1t+Nv3cQDZSq^bLfS_m28OQSW$BG|eaqZn|`;T&Lw-M$sL1S(T(3)>uB3a9YSuO?462C8TsE$_vGIXC9x|otB>Q%$iW@NBz>-xG;3L4jU*b^W#RRZ%8#G{K`hIK+*?e2+yLHV{;ddSqtRrAi6JuGG!Ak=q6my+X}ro3o@Z+eDL(&^Vn1yT~(~s_xCE5@{U&fT`%rNnJmY-gSyn|Y2@lHjh6Gj&3{=mm0L>M?35xLp2TZi2b?8UyGW#166ML|p^FWJm+o}U%Asvz^V&tGkNoL6*o@X1CTG_(P1D;+6@9R*Mz@8gRa+<16GIiXS_zov(4l|b8DdG3^pQ7C(XI+OTH5L(DAz(Jn@s-WPuGFwl{I$Klq9O;NCYT0o0Gz39F3P#+a!V?nfcPI5^EI^#fX5f+{am@w#>bbR}SY1#9qX-HUqNUvi-v_An_kYEd`YyMMLrXl-(dPr2CPi103v^R|{NLaOtprmtW-7uaG5U`~Vl_AG_G+T=O5ynv135MVX4lf@D53iF0q2bN5rI-x__}3ap*i%)Nslxj`v!&R(@Qfs|uVHq(rEuQOu=9R$AT**|4aICAGDKu0By3!<9)7e4_JPM1$ZoS2AqR(3Lm|h>anQJGL2kc34@d}bZXnz2mLt-Gr)8H&_I#k$vs(T<>~xH%b6RT0+dfFz9#(*429K65(cS@QLBatCK*Gy2I{+N=US~1RY2m97^||C?jmo52^kF0AoQTg(ID=K!Ru&JwV3+;9xg0ak}I^KOkQ#OAfIh+50msJf`Z;uo*eXoterfi@#)@x6Cojq;qaw|R?LXeUM7ANs`mJs)em)I}UX9$nB+#WK>Pcl~N%ymN*lA{;h;E&1Ambl8Ps*Lu%BD-o*B}0E=*6!xaRa0^Tr?D4Z|>v!hmV{0uRgZJZE~I0l5I0^98>}8s5<%9M3h_fS5UDdq1&j?snt<=w#$7~-MOJcQwQaNU7-S$w$)_1961J+4sl-3*SEH{&QNM+&*P9t)2UE}k^Sl|K^KFAKo)0!P^HQugnLkOrg}^OEP{01Q;CjuL5H`lek}AK6(Nxr1XwM;WI_f#J^nlxmyMg^KxxCSY(F4Q>2{G^9Z{EFcd0tK~<93c0%#4-iqw_Lrrh?ALk}7$VeRM`@Mv^;uap<(+(7v~JK;1s8nJW7?93OVk`4Ci2tus39{2m?Cs{BPeSEB1*m5w8wcw;adu(ck-^sIp>@xcr>PsF7Q(!lvtTrQ~voy~F}MAdt{VK&&FU6!eG<1m${8lB0T2Kd_D*hKn=~g%s0+0=Pd(ie7A#ffYPV~R-(+4f~XD%E)S5IvqEMF5MCZ2I|q;*0z{_*G#$}dOWuXKHy+mEQw9A~KsV>M2`Y>2f%N1=`K$v`H3#C1Imwpu`^aWJ5>{`Y)5{|)aB@xpXFQ7_aB5kEEu3B!p#w*)3a64o&;vPyt)}&I2pwh9=U2Az3_^c(%+TuKrLB&g1IG@*p;N#a&mDwkGVj`gw$E;#-A&~V#(TnSUjO(%AAb7dhhNGrF~Pu7wqaSeK?-ttJO2IkeFSt4qPlh9uP)=TU5{GMq1X2{p)EyFZ6j%rBgB43CTP2znJ7PJ2j3Y~vHMo;jO!?kCg7izdp?Qu`@LY5SEO?h7xYiksbB0PtQ`l_SZ>gpvPwhE<)6Jr@aMd;)xhf527{v&I5?1=9;CL_-Tm+Lj9_a|+M4fCqs$;HSYe(Exa@92DT)S+#c})LtYCT&la?+cj6u$_Tn%*;2RjX`*QwZ}v?O>;?-MlX~gPy0O=7%wmV3*EQe*?2%PQ;lef5k_0-}G7mu8vYz8)N!0f&}4tmo3kZI&hkHK>hU8mRAzspWB^_W0NwH=de;iv}e=BCFPoRLEQhqF|tZ?c>edt-`@Xl|K^2QA9+B(|JL6=-8x97C%UFJ=czzVrm>u~@(I#K^3{tuH88=Gf67WN%}UAGpjQuXzkEw2ruBiV9?Y&xFCc6Zn@vdJl;xG(S01iNvD4SQWFTn)WGJ*20sjOcT(oGVuyG7DjbN`VUM(#Av?bgb57C7eKE%WMfI40XamIm)GJGk?B%Fu^E7nBfq6SVcQHs+?np(5&Jf34eCfJu=Fz!+rt_9sI@(gwesxAm`dIry*H*`_UpGZ?)D@t`_$aNAX0PNR54BlhmBKvyj=#h@Ga*AD0Y7kYuz|QEJ#`zoZXcYHJyel=^N#T(>EstMQE|oq}T695vK3AQi{2$m`XjNYso}R-K+3$q)NgvfWA*(z|m9i-8BKv@nwWC{U)z6vOq1_ceMJbk7G%I`oa*U`G*WTgVHlv@SVkXh)G9kdxXV2DgqN+ziz#bKw1$W2fa9x>EugowgSYGs_9CqZLyj`H7_W5H4RusrR_l@~#TsM{-2jFCwB%K6=6r-2d7b7Nob+sQq73ecTN1!VfIn#QGd;C50}%tQxot2Sx>1zH4;kXXvI>WtrnypOLN+Eu*v)JBE>F9Yh;)u_VtWqvfHajq}!T&D8eLN$1UiL+3!59aZhU;olP}^b>hPh4N4J3wg}Sb8KWrdZ`k0EORDrx@DpV@Z~GJ?nmgEPpu}?8mf=S#U@N>tT4m3wn$td2Sfv0w(m}bQOI+uv^{fFnn%#oN_ucRep}^&|HAivA{@K<$S*(THWi=pf4~`vnqhbnV}|y3q{};9TdUgW#Zr%Z0y}xdns7!E)W8LZ^WM&fMWcap$M0?S39Jg@wYhF)y^x>e$FAxZ(nn)!aH3f?`WOTm3BT?#5-Os@8*i-ZmwAF_KM|huUPKxiskOESnmFc*<&!_reHC5{Onlx97V%DwNnwywVy4LCuBn`!^RNc{#9FU0y>5WIATnFks199GCyQ70(l!D9s_x|?jR*Y`~n5^&w$R_c8_N~qw8>!!Iqq%VFv||~sjb(FvQa0BoWqW;6w$~?RcYRWJ*C%CveNy&km-6C(YgeC+wb9v4z||#c1zfu#c5H@ccgpmPJ9of!2z*~1)Ycy7o{1#nvaW=0w(xz(=m~Tby2u|~KKM$ojVet|?GmLab%+Icy92MhfJep=g)Z_3=K(*n0In~C)Ow6#ok{DWb3Nv9I39hM@%=OH1Cc_IdFpeXWdvuR-efF$lOf|1U5Ib*U%ceV*XzJ*#moFfdoWB0K7RN2dwGlMExD*}DTL4J5yfx6{Pg4d4?q0(&!2w&wfp8N<1VF9ud&DGiFPO04I5A;QEE=+t@51HGJ{ijMVu*7;{HkNe8Bn{{NVtPDaTnAK?vNeTx!fIP!GpDxk(|YXC!%D{oHvIp_z^9bmQ0147OKhNUHK^DjEu648+ksqx3t85@p4X=q?8vhP3&~{8^=?pXIds=`}K*#(X1Ez=LM*SbiJSI0Jh^$yLKt)Ik`0CafSjrx3U6T!?E;Sae}eopi^t&ea=D?$IN@x?;=y!xJAqH@fQJZ$w;S6(Nh%U#IkO`$&>Au=|9h8XjMK$RpdH!?7P)K_dl&=_$P|`Gp15X+WEn(ae&2Wo7JW835787X>ZbF#vRG^z3869)O1?$K9ZSNVB3D)OSP{Yonf$;=Mrpd#E#u6mQ;2Bb1xc=~I3_jHA!;}BjrJ2eowDSH9vz5uXkLT4XXKsh`ku8d;Y|U&oXYD2FKGiQ#bO?gV)?omR-Y@d97_~IUc(tjZ?iYt8SWAH+_uHV|C(M5%~Xy5Wvit%-ytmbI#+_)#Ac-Z>XG&-@JVTufL1N1Z(0A-70|3W~kAOF_8~neUJVv#*SFL8tjXthfkD<9D4kJXIHxeFa!f1Xg`+pL(=zuv8_dl)!2R$IUE{k?>tyQG;@Sdur{z|EBi2R&kV;iuHnwoGxxC{>H8pdmY&FWD3RsU)CFA3s!a#f91xYLY`xmN3}3_q+T!WVz9Bx$iU8808G~E!>54$YrvcZ(-L#$VpmdhA9B{jC$1ds_c=59}2<_dJ*gKk^RtKZLTEbcW-=QQY~_Iit)WY}kGW$@poJA~D%3|Je2cTbQ393jzQD', + '1:16376162-16376662': + 'ABzY800000002c%IS#`x4BPXU4oLwQ=um**pbzl>Z>dN*t&zYwD2kFl=lfjG*E-krh_Tjnut2K(qaezkPpOL4;XckOcjIi3yP!m(PlwQ@Iq_Tw6W`zxHW^KzIDMfz(JZp(@&Os3&~l)N99eEuHpU_RM4QfhW&m1-+E7rV(sGO<(#2_KqQj#1w9{e8wA}9#H8*50xSx@&W(T%5=A+}KssUC;-`VuRfTK++!&LI?&5(lo$tL-*>z2i*!G0Ysp}lb~(|38Q0RP|6NfCp{&cb$A7dvAC)wWOHX~Mgb}nwDYopk+M)D9X;W8{J4Vt2b~qo2o8eKvYy$|j2VxabXMz-9(ESt;FesGyz*IKP@Wp;m~tujN5nt4wi1kC*sPD}%w)|*NK)42TrYB)kP4*~!H', + '1:17354844-17355425': + 'ABzY800000002FaOKt-(3`6(1OBYFJ&?1WhgciC0?|+u)QAXp**dFRbQh(3)^XL1%ey{6`!+pK(hs#|hyCmMW+2>L~V6)tFDYf#AeSTGh)*|i`*A1{wDo@O;$(oV^ERv`owjy(I%|q!)qdQDQwpE9-#=J-A+0^&3ZP#uGG%*nuOy^qLcfuhQ28I%40_h~sIr5&;}hQzlXAD)s$;-1)7`4_r+w^lNoV|9zgMs0%(y>31l~YHHq;a1fu+DzkM4RH&6FC1@7*+*sns%x>5Q&?)xH!oXk)Q?eUI?P%8VH@?IzI93Tjk9nfGncFt3G1%bCIGhsM;Qpn*Rn1a=e}Lm7f-qwAYHg}?1kR^V}1*@J|xcuWLC7)qQSG)dW4g@F_%^r*u^uvkdW5v+u!JjTg`SSg|n2wpRiR#Mu&0)43x3jzQD', + '1:45797862-45798380': + 'ABzY800000002c%TMoi74EyIUNW3@rK(g|Y3;6zL!FCF4+S<5|lREG7>vrFs+y1y5z1gq(=}@dfp}VzEe|BOTapX-C1}7>#L?>}2P^&%wG#parNVxS2!wZPUXy{RnFpPNg1&BTRBoovm%$av0GMF<>Oo@LH7`HP25NonAU8_Os_FOlzVGDBA$RghOE`hkn7B<7}yOB9sWja^F3SGfD7)QGoQFlp4%PgPEZZP7j#ag!Mg=gW|OBnsTZH8yx$3XXQ!f#gJVR2lFj~nK@P$|5W4p-ChaEe!Gj6mFdvxzzeQlSYV9mV2Jm-%ulu>q`(Epl={eUr*y!qR6pF2}a^{>%7XzX8tQYXYT_!e-BX0>&m~_Mt4uULQx(i}J-w8eQUg;XLu4P39Fhn1ir`&F$4pWQcqv^fdfd(sdG@V5(gBBI!A6X{^=NPGQ9MY5wMrKbE?vGb68541~2UG>v4*4RZncV4t#a-N3b%60)=_}60iJO|S`pxY^=MP8@?35DIlm^n5#nU|J+eW?J)bwxU_yc9$kLnEq000', + '1:156106732-156107249': + 'ABzY800000001qKO|HX02!r>%OQoi-KWZ0GvRL>6-2W`)Gl`N3!x&>c|Ht=uzK+}L{dd16dfy+Pi%V9QYehOyw-@6uM}zTA$P@bMYl4myw;`_<;r~w6k@Fm`=g;T;w$(fNY9>L|baAQLo?0^9&3~xmOq_s(S^7FXWxlsJ5JINvLr#t)oK#|2mv~VY^pYY?%<6HVnd9%plZJLD^aotmcpp7@9<4e8=WK=zurJmF99v)34X^B?B3i-c6^;qE35XQbg%d`{ku>KeMQ@eh(Z>$&?H{4|A{7q;000', + '4:106320044-106320544': + 'ABzY800000002FaL2d*=2m|l?mq?SOlfxb&ArAfk|9?yDVs?9^ZWzEA^LL(~*YEe&b)ECE*3UVQn)2~Anj9S4RrX6nOII{+%&PTNF*r6Sb+m0v{Et2;^@VTD62unMk(!Lw9NXQ5Ck@323cMYLm+zf;~(MZmUayS000', + '7:42017061-42017561': + 'ABzY800000002FaQ4Yc|3`7693lc*xBtDR$eB=VY|5@;J3)|GCsbf3o=kBqbwUKCOT$aeaXtP7QHh-jhfzl}_Y8NEwT`<06HRil`BgM;{;RxO7|)Ko(uNC}US^heqO{{P&R|LS@LB+?j$w1rTrMG5N_Ur)tE$)!A4YPtpW^ncJAL^AiTac@3jzQD', + '7:42064707-42065207': + 'ABzY800000002#qQ3}H_3`75Wmq97r0{a*kfA|8v|5>Idhp|vnN0BAl`Kp}3m&UJKmb!6xxsNhtULaN%hE>dt+7!)KR1q2IJY{;VM8b+lfA-c;ymPoxxD2hi`YU{FXYu7Vyhi*f_gu5jDN9*2j6err+JtYGD9(dH`-gUS;kxU$h7yfmON35aX$Rj4QsZvZ$I_Doh6-E2)K6lnWiWKev$hPpKO#KQOG!8B8ZGjZWC<1|)TFClyZPjIKoP+J2oJ$4d(W000', + '8:145140250-145140750': + 'ABzY800000002EvL5jmb47>L)3+d9((!+w#!5`57-%?9z781uZwj^8md%f?E^Zqz~&*P`r^E_@OMM0xYhQw^tj8hOC<(97OM`C;SFc`Ns?oEKklz{`u%trd$5EU~53N5)%Tx<<1D(8_I*Il-@tBVaQ!W`|6sf^=Ie7g~Ws{+>aIr7s|)R1+I?WC&~A=sHsy7{%oBo))+@ex~;9#`vRmPMbM!^;|GY6CMfYIl85UQ6TaQ!ICLHY|}rS;p?=@A$@;@9h7e7*_Eb@9x_NpKQ<54FUiF', + '9:107546383-107546883': + 'ABzY800000002FaQEtO93`75WmjN5nZdpGH2>Rd!bpNxAk4k44ie%HIsJwokU!OmZ`}c7kADf-$aZ`6qb(M-l>Qp4vI2gf&tLQi>4!}5RyQLxW+RYhd^GVO^foVi;F11-raq40&MD;ZgrNgy2Z_AUpXO8rXQ<$R9giWV4oWBv{`@_)d%WKC6c1yQE&U$hf4FUiF', + '10:126091249-126091749': + 'ABzY800000001?SOAdoT3`6(ar4k_2iY_WyUgQF~|5<7~!@!_SJ};i|JNEB!zW4h$ulqID=ejp`bvFrW1GXR+(Wp4$DcO3Oap;XlIjHO^mrRaLDhC01sYa1Phvr;WE0I`O*C5^XF;_uZinbBMcGL$`5xOfS)4;IPMt#c8v=1d2WpJn*HB+P>UPxk8Js0-NaGe}QOb?GHN-cl3qF~f9SIZnbMbX7TW?1@=>^kw6auqSTcSI$MSZ2$ns(H^P0+TiLYqky+mGt;r@FM&n%HeNEuiv9zZno$))7f8*YMdf!YCMQkooeYj8|spY^N%%0gX8`E5T$qW;}>T4`R@97KS|^xtDp7BQ09Tnri#vhAj3MLl~)es>*zcA2E^4gvrG', + '13:77569878-77570378': + 'ABzY800000001>nK@P$&47=|yNT3NiI3QU*wT^3ro+0Q>pDt{1W~B2LZi#KM$y|bJYq8j_IOL$aEKi0<{VRht6Um!x(gPlhJ4qIb~L592ikry?dD7^^w_0R;n7V5+p*Wa)i4VB0GwhLy+uUtEfq>wxSYK>t1B$D654>(JZtN#)Z-rR60c-VolT-i{YvfnbdaHGXLgaEFCl^-Lcew&g^s&9w6hyn7jk>4r7ZEnFx_v@s;lEHv5&#bNm1qHeiel0ssI', + '14:89336157-89336657': + 'ABzY800000001?RL6XBj2m|l=OAe`Q;@v%@isGOT@c*|&Eo|E}W*A8bK98UO-@oVc{dgVs1n<{z>zS@Dd7G(f&O_*Te8F$T;%Z2=;pJR|ZZDODhJ#?>FKhYoW}Fc+Ys@y?B*&sKCudPJ!xUCLOrQ&oKMTP_B9BvZ7VA&}&EDX7&VCxH6y-+H(On9HlNqQNkk*S>5wAeCcubmuh&`Jr&P~0fm|~@Fv1zr}Gi_q06=9~P+2LmpX(IF2B{NKTbhUJK$ESEq*#H=H=`4hDdhOUnX;D45FQ-Px0Sp2F00', + '14:105167610-105168110': + 'ABzY800000001>nNeaV247=wqg$%T5>7ihJ&>hX<8ngcHkYPZ^xTB^;GpbTy&C<;W?jQ%hnOHVos5^`jb^7YNzbc6JZvD|NlL7Z9a{e!=V{ZOL9+GZ2K$?hpbi2600', + '17:29555814-29556314': + 'ABzY800000001qJyKw_S3`2AE;^1t_zrZs)2+#oguf=%a-AKD!5&%K|U0=WNKd;y8`+B|+e12Td$LQqK@DVxxgg#1Awi2c?93JP+8(_{vA{mfw`Y9x5u2ao~o{E6D%f#w6WVE*c-xlC(C+n;hfV2~rn#$8FTP`v|YmJoAa;IPr!~_o!@0Ew}P^t30<9{&+*Xow5~000', + '17:29663629-29664129': + 'ABzY800000001pfK@P((47&F(J2aa*b%#lagFoQ^zomc^RjCsju*v`Y{?>h6?`z#J2cL7@2li^Ri{1JfM3sKsRZxg7G+9>`TmX$`E(Kn1LSK^Ae-yRr_hM)iMlcEX47Eqnp-`2av?(jSK<+00', + '19:11215896-11216396': + 'ABzY800000001?SF%H8p3EPPY>J|Y>h2U$LR5AM4tk=KuXHL}R0s}1uq1ss@;h^N`~khJXX*?B000', + '19:17451747-17452247': + 'ABzY800000001>n!41Pe4Ekr6J`$yh+D9ei2Mc)rSqk_rQZ7Cl1CD>^=X*Z)TkrF7a9#IvbQcS(E+x9@T@$s8cG3RtH*+Rx|44P{f^E14Io?%3)s}hDFTS>9jva%uiM;?Dcf5F)d0ssI', + '20:62326742-62327242': + 'ABzY800000002FaQ3}H_3`75Sm%+%!3i}ucefR>p|5;|q$=ZfGu`NG4-}U&s*K@tE*Sg!d)@$7gRV1pvDo~~J!&$N$idRfrueRh9`0vw1Ghu}2tjO3%tatEhchTEjb7%LarA}cwNhiWgei_DtNQ8~v*+(gCF+(Hwlf#s314AiiyDX73H@8(ZM1rMsqFo-rLYmTWAfo~>I0KRCIBIH)BnC7SN-|S2O-^Q;GwL+3LG5HTQW==8TZ;cnkv4Q4!WsX*m%*AFwpgHUKcE_18Ps2p%MEy)xqf4=X>^L4+S=k)?Gx*k>CRpYNUQv1~E1U1z)<){HUgK@3OpdD*YMpQZCLsRPOg#3HeB%g=*rDgim-XO`4SIzknUZ$mU&QLN&-bH0qq9Tf)?f?nTFQuea#aiBS=9>g64l!@3tiU_ySz#ZKDkW000' + } } }; diff --git a/src/store/actions.ts b/src/store/actions.ts index 85db6090..1fec332f 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -12,7 +12,12 @@ declare global { } const inputData = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' ? apiData : window.api; -let api = new ApiClient(inputData); +let api: ApiClient = new ApiClient(inputData); + +export type Locus = { + contig: string; + pos: number; +}; export default { async loadMetadata({ commit }: ActionContext): Promise { @@ -96,8 +101,12 @@ export default { setFilterRecordsByDepth({ commit }: ActionContext, value: boolean): void { commit('setFilterRecordsByDepth', value); }, - async getVcfGz(): Promise { + getVcfGz(): Promise { return api.getVcfGz(); + }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + getFastaGz({ commit }: ActionContext, locus: Locus): Promise { + return api.getFastaGz(locus.contig, locus.pos); } }; diff --git a/tests/unit/components/GenomeBrowser.spec.ts b/tests/unit/components/GenomeBrowser.spec.ts deleted file mode 100644 index 29fdd421..00000000 --- a/tests/unit/components/GenomeBrowser.spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { createLocalVue, shallowMount } from '@vue/test-utils'; -import Vuex, { GetterTree, Store } from 'vuex'; -import GenomeBrowser from '@/components/GenomeBrowser.vue'; -import { mock } from 'ts-mockito'; -import { Vcf } from '@molgenis/vip-report-api'; - -import igv from 'igv'; -jest.mock('igv'); - -const localVue = createLocalVue(); -localVue.use(Vuex); - -describe('GenomeBrowser', () => { - const genomeBrowserDbFn = jest.fn(); - - let browser: any; - let store: Store; - - beforeEach(() => { - browser = { search: jest.fn() }; - igv.createBrowser.mockResolvedValue(browser); - - const getters: GetterTree = { genomeBrowserDb: genomeBrowserDbFn }; - store = new Vuex.Store({ getters }); - }); - - it('select record for supported genomeBrowserDb', async () => { - genomeBrowserDbFn.mockReturnValue('hg38'); - - const wrapper = shallowMount(GenomeBrowser, { store, localVue }); - await wrapper.vm.$nextTick(); - - const record = mock(); - record.c = '1'; - record.p = 123456; - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - wrapper.vm.$options.watch.selectedRecord.call(wrapper.vm, record); - expect(browser.search).toBeCalledWith('chr1:123456'); - }); - - it('deselect record for supported genomeBrowserDb', async () => { - genomeBrowserDbFn.mockReturnValue('hg38'); - - const wrapper = shallowMount(GenomeBrowser, { store, localVue }); - await wrapper.vm.$nextTick(); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - wrapper.vm.$options.watch.selectedRecord.call(wrapper.vm, null); - expect(browser.search).toBeCalledWith('all'); - }); - - it('select record for unsupported genomeBrowserDb', async () => { - genomeBrowserDbFn.mockReturnValue('hg17'); - - const wrapper = shallowMount(GenomeBrowser, { store, localVue }); - await wrapper.vm.$nextTick(); - - const record = mock(); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - wrapper.vm.$options.watch.selectedRecord.call(wrapper.vm, record); - expect(browser.search).toBeCalledTimes(0); - }); -}); diff --git a/tests/unit/store/actions.spec.ts b/tests/unit/store/actions.spec.ts index 73e889a1..a9f3af64 100644 --- a/tests/unit/store/actions.spec.ts +++ b/tests/unit/store/actions.spec.ts @@ -166,7 +166,15 @@ test('set filter records by read depth', async (done) => { done(); }); -test('set filter records by read depth', async (done) => { +test('get vcf gz', async (done) => { expect(await actions.getVcfGz()).not.toBe(null); done(); }); + +test('get fasta gz', async (done) => { + const commit = jest.fn() as Commit; + expect(await actions.getFastaGz({ commit } as ActionContext, { contig: '1', pos: 17350500 })).not.toBe( + null + ); + done(); +}); From 5d3f8ee85d09c775799997df0fa62d0e0a8b6a88 Mon Sep 17 00:00:00 2001 From: Dennis Hendriksen Date: Thu, 22 Apr 2021 11:16:13 +0200 Subject: [PATCH 2/2] fix == is === --- package-lock.json | 4 ++-- src/components/GenomeBrowser.vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3394ce83..6c804842 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@molgenis/vip-report-template", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@molgenis/vip-report-template", - "version": "2.0.0", + "version": "2.1.0", "license": "LGPL-3.0", "dependencies": { "@molgenis/vip-report-api": "^2.1.0", diff --git a/src/components/GenomeBrowser.vue b/src/components/GenomeBrowser.vue index 539b983d..4f2492b4 100644 --- a/src/components/GenomeBrowser.vue +++ b/src/components/GenomeBrowser.vue @@ -23,7 +23,7 @@ export default Vue.extend({ }, async updateGenomeBrowser(record: Vcf.Record | null) { const config = record !== null ? await this.createBrowserConfig(record) : null; - if (config == null) { + if (config === null) { if (this.hasGenomeBrowser()) { await this.deleteGenomeBrowser(); }