From 0138af9237b77dd7d3a49260d164193b4048de84 Mon Sep 17 00:00:00 2001 From: Florent Fayolle Date: Sat, 2 Jun 2018 21:39:41 +0200 Subject: [PATCH] Add create-import-video-file-job command --- package.json | 1 + scripts/create-import-video-file-job.ts | 39 ++++++ server/helpers/core-utils.ts | 4 +- server/initializers/constants.ts | 2 + server/lib/job-queue/handlers/video-file.ts | 29 ++++- server/lib/job-queue/job-queue.ts | 4 +- server/models/video/video.ts | 35 +++++- .../tests/api/fixtures/video_short-480.webm | Bin 0 -> 69217 bytes .../tests/cli/create-import-video-file-job.ts | 111 ++++++++++++++++++ server/tests/cli/index.ts | 1 + shared/models/server/job.model.ts | 1 + 11 files changed, 221 insertions(+), 6 deletions(-) create mode 100644 scripts/create-import-video-file-job.ts create mode 100644 server/tests/api/fixtures/video_short-480.webm create mode 100644 server/tests/cli/create-import-video-file-job.ts diff --git a/package.json b/package.json index 707579af3..4daeecb88 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "start": "node dist/server", "update-host": "node ./dist/scripts/update-host.js", "create-transcoding-job": "node ./dist/scripts/create-transcoding-job.js", + "create-import-video-file-job": "node ./dist/scripts/create-import-video-file-job.js", "test": "scripty", "help": "scripty", "generate-api-doc": "scripty", diff --git a/scripts/create-import-video-file-job.ts b/scripts/create-import-video-file-job.ts new file mode 100644 index 000000000..a2f4f38f2 --- /dev/null +++ b/scripts/create-import-video-file-job.ts @@ -0,0 +1,39 @@ +import * as program from 'commander' +import { resolve } from 'path' +import { VideoModel } from '../server/models/video/video' +import { initDatabaseModels } from '../server/initializers' +import { JobQueue } from '../server/lib/job-queue' + +program + .option('-v, --video [videoUUID]', 'Video UUID') + .option('-i, --import [videoFile]', 'Video file') + .description('Import a video file to replace an already uploaded file or to add a new resolution') + .parse(process.argv) + +if (program['video'] === undefined || program['import'] === undefined) { + console.error('All parameters are mandatory.') + process.exit(-1) +} + +run() + .then(() => process.exit(0)) + .catch(err => { + console.error(err) + process.exit(-1) + }) + +async function run () { + await initDatabaseModels(true) + + const video = await VideoModel.loadByUUID(program['video']) + if (!video) throw new Error('Video not found.') + + const dataInput = { + videoUUID: video.uuid, + filePath: resolve(program['import']) + } + + await JobQueue.Instance.init() + await JobQueue.Instance.createJob({ type: 'video-file-import', payload: dataInput }) + console.log('Import job for video %s created.', video.uuid) +} diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index a3dfe27b5..c560222d3 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts @@ -6,7 +6,7 @@ import * as bcrypt from 'bcrypt' import * as createTorrent from 'create-torrent' import { pseudoRandomBytes } from 'crypto' -import { readdir, readFile, rename, stat, Stats, unlink, writeFile } from 'fs' +import { copyFile, readdir, readFile, rename, stat, Stats, unlink, writeFile } from 'fs' import * as mkdirp from 'mkdirp' import { isAbsolute, join } from 'path' import * as pem from 'pem' @@ -136,6 +136,7 @@ function promisify2WithVoid (func: (arg1: T, arg2: U, cb: (err: any) => vo } } +const copyFilePromise = promisify2WithVoid(copyFile) const readFileBufferPromise = promisify1(readFile) const unlinkPromise = promisify1WithVoid(unlink) const renamePromise = promisify2WithVoid(rename) @@ -167,6 +168,7 @@ export { promisify0, promisify1, + copyFilePromise, readdirPromise, readFileBufferPromise, unlinkPromise, diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 9b459c241..482db2d5c 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -74,6 +74,7 @@ const JOB_ATTEMPTS: { [ id in JobType ]: number } = { 'activitypub-http-unicast': 5, 'activitypub-http-fetcher': 5, 'activitypub-follow': 5, + 'video-file-import': 1, 'video-file': 1, 'email': 5 } @@ -82,6 +83,7 @@ const JOB_CONCURRENCY: { [ id in JobType ]: number } = { 'activitypub-http-unicast': 5, 'activitypub-http-fetcher': 1, 'activitypub-follow': 3, + 'video-file-import': 1, 'video-file': 1, 'email': 5 } diff --git a/server/lib/job-queue/handlers/video-file.ts b/server/lib/job-queue/handlers/video-file.ts index 93f9e9fe7..38eb3511c 100644 --- a/server/lib/job-queue/handlers/video-file.ts +++ b/server/lib/job-queue/handlers/video-file.ts @@ -16,6 +16,28 @@ export type VideoFilePayload = { isPortraitMode?: boolean } +export type VideoImportPayload = { + videoUUID: string, + filePath: string +} + +async function processVideoImport (job: kue.Job) { + const payload = job.data as VideoImportPayload + logger.info('Processing video import in job %d.', job.id) + + const video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(payload.videoUUID) + // No video, maybe deleted? + if (!video) { + logger.info('Do not process job %d, video does not exist.', job.id, { videoUUID: video.uuid }) + return undefined + } + + await video.importVideoFile(payload.filePath) + + await onVideoFileTranscoderOrImportSuccess(video) + return video +} + async function processVideoFile (job: kue.Job) { const payload = job.data as VideoFilePayload logger.info('Processing video file in job %d.', job.id) @@ -30,7 +52,7 @@ async function processVideoFile (job: kue.Job) { // Transcoding in other resolution if (payload.resolution) { await video.transcodeOriginalVideofile(payload.resolution, payload.isPortraitMode) - await onVideoFileTranscoderSuccess(video) + await onVideoFileTranscoderOrImportSuccess(video) } else { await video.optimizeOriginalVideofile() await onVideoFileOptimizerSuccess(video, payload.isNewVideo) @@ -39,7 +61,7 @@ async function processVideoFile (job: kue.Job) { return video } -async function onVideoFileTranscoderSuccess (video: VideoModel) { +async function onVideoFileTranscoderOrImportSuccess (video: VideoModel) { if (video === undefined) return undefined // Maybe the video changed in database, refresh it @@ -109,5 +131,6 @@ async function onVideoFileOptimizerSuccess (video: VideoModel, isNewVideo: boole // --------------------------------------------------------------------------- export { - processVideoFile + processVideoFile, + processVideoImport } diff --git a/server/lib/job-queue/job-queue.ts b/server/lib/job-queue/job-queue.ts index 0333464bd..69335acf0 100644 --- a/server/lib/job-queue/job-queue.ts +++ b/server/lib/job-queue/job-queue.ts @@ -7,7 +7,7 @@ import { ActivitypubHttpBroadcastPayload, processActivityPubHttpBroadcast } from import { ActivitypubHttpFetcherPayload, processActivityPubHttpFetcher } from './handlers/activitypub-http-fetcher' import { ActivitypubHttpUnicastPayload, processActivityPubHttpUnicast } from './handlers/activitypub-http-unicast' import { EmailPayload, processEmail } from './handlers/email' -import { processVideoFile, VideoFilePayload } from './handlers/video-file' +import { processVideoFile, processVideoImport, VideoFilePayload, VideoImportPayload } from './handlers/video-file' import { ActivitypubFollowPayload, processActivityPubFollow } from './handlers/activitypub-follow' type CreateJobArgument = @@ -15,6 +15,7 @@ type CreateJobArgument = { type: 'activitypub-http-unicast', payload: ActivitypubHttpUnicastPayload } | { type: 'activitypub-http-fetcher', payload: ActivitypubHttpFetcherPayload } | { type: 'activitypub-follow', payload: ActivitypubFollowPayload } | + { type: 'video-file-import', payload: VideoImportPayload } | { type: 'video-file', payload: VideoFilePayload } | { type: 'email', payload: EmailPayload } @@ -23,6 +24,7 @@ const handlers: { [ id in JobType ]: (job: kue.Job) => Promise} = { 'activitypub-http-unicast': processActivityPubHttpUnicast, 'activitypub-http-fetcher': processActivityPubHttpFetcher, 'activitypub-follow': processActivityPubFollow, + 'video-file-import': processVideoImport, 'video-file': processVideoFile, 'email': processEmail } diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 5821ea397..2875e6685 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -2,7 +2,7 @@ import * as Bluebird from 'bluebird' import { map, maxBy } from 'lodash' import * as magnetUtil from 'magnet-uri' import * as parseTorrent from 'parse-torrent' -import { join } from 'path' +import { join, extname } from 'path' import * as Sequelize from 'sequelize' import { AllowNull, @@ -32,6 +32,7 @@ import { VideoFilter } from '../../../shared/models/videos/video-query.type' import { createTorrentPromise, peertubeTruncate, + copyFilePromise, renamePromise, statPromise, unlinkPromise, @@ -1315,6 +1316,38 @@ export class VideoModel extends Model { this.VideoFiles.push(newVideoFile) } + async importVideoFile (inputFilePath: string) { + let updatedVideoFile = new VideoFileModel({ + resolution: (await getVideoFileResolution(inputFilePath)).videoFileResolution, + extname: extname(inputFilePath), + size: (await statPromise(inputFilePath)).size, + videoId: this.id + }) + + const outputPath = this.getVideoFilePath(updatedVideoFile) + await copyFilePromise(inputFilePath, outputPath) + + const currentVideoFile = this.VideoFiles.find(videoFile => videoFile.resolution === updatedVideoFile.resolution) + const isNewVideoFile = !currentVideoFile + + if (!isNewVideoFile) { + if (currentVideoFile.extname !== updatedVideoFile.extname) { + await this.removeFile(currentVideoFile) + currentVideoFile.set('extname', updatedVideoFile.extname) + } + currentVideoFile.set('size', updatedVideoFile.size) + updatedVideoFile = currentVideoFile + } + + await this.createTorrentAndSetInfoHash(updatedVideoFile) + + await updatedVideoFile.save() + + if (isNewVideoFile) { + this.VideoFiles.push(updatedVideoFile) + } + } + getOriginalFileResolution () { const originalFilePath = this.getVideoFilePath(this.getOriginalFile()) diff --git a/server/tests/api/fixtures/video_short-480.webm b/server/tests/api/fixtures/video_short-480.webm new file mode 100644 index 0000000000000000000000000000000000000000..3145105e17cc3f082025c9ac68760da325fc231e GIT binary patch literal 69217 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

Y3WA9mo z5WgiVD47E?fdeKPX=Ud(p+Kurf?Z)hgLyR#=M5R&&?Aa6f1~LNaj2xWUyubmRB$^Lnzu1D9<;Bpre@ooVJn)`u<19& zK_y=`6)m8(d5D?)(y3+Q%{~9c#))3uG$no_0zJI#MP?@mXsFeQMQI7W#r07;jSzf< zK@GfBYQlg$($)>!jhS3Y*V(LjI?noXV&mj85+WB=yPP_6oCh`<7H^sC`hqKhO0LX> zH%Kh-pl5sK7j=qUg=?Y zS+?68VKm4&N5a|S5_|8+t&i)!)qS08yC{J~Z0Zk;c-au|a63rspOGPWG^b%bey2O# zaXh@We?-!KtKiCSKIQb1xfnGjLiTL`7L8Bh=}%||N3XnYTV2lNpBgbEu_j_)nRvG| zvEbFy5jl~72#7IpYnSTKFsVnaT6*>noRQ9T$O$K2phT8~cA-N`>!8OfvF>iCt6&)! zJWFM2$w4@xci;RqjlVpFy7w?H<29KRM-RjJ?Wo9Lx9iioL~A?705VsPkr;ugQY z9DnJ9U5{>@l=cq;U79dz^QoG;xhAfyika)Ez_mV%vqy2o)fYPZaDFce1Xnq%p4z6f zaQ*K(FFffakvndySX^pv4bcH(wAPrp{X{tG?Ac6!9u9ZRYt;$8s z9GusOj6)fDo$N#3Xn$hc`@x`)0lxDyy@K~TiM6pMR+OWThlr=(F|Ysq+L81}%4j1< zWkQ2x18}^H;l%>sS+17vnH9cJnM&0qfeJ=jAeR!rCXOIdtb*~npI}Fv(prAwp ziWA%g8yPST;=2&oU^6`t$ybFUj!$#|`l>Ez__AF~MRp@NS|usS^@MZFI>9H>9-pPifl&7AEKHug7Yk@VPw4d# z^3^>Ef5iwZCmJsw*V8!8)1gEv;A;A?{_uRR_=L77Y6SANhiS6mRUgAPlBATFMLmI# zzi;R++|kc+b_Zg!ELo06i+g;jnSS@xcpBXwtDEsu4%r87L#RZxNgowTbAy3CsJvpEHYYIk+DQ5vXvk0ZBXeZmpi z9Yr!s+_{8Dt-xUbkE2OO@%O-ICx|PrgMQ`U?0jc?=l%t|uW5-HYG3bHnAEFJMZ8Y2 zc{Hw#s62%sS{5Be3b;2LJ<;g`jdbBrd1TyKZuN?cz}j1K2n>1Or(WV|hvBa($}cnXn!`nJ+?^w!szg9`87W6fYPy(qO3-)Ii}ykbVECTb3q zo)+llAO<_PNs|z=hB)4x$(!v7QEJ}L%!&jJsY;oJg>cLMfn}$~yORR1A-iMaX5#D| znYdUiN@%Ul_T3Lc_wUbR8oXO~7z;BEX+$8=MDYcSjt5cCPKNs-~q3W}T> z1i2#nR=etlypR%>wIt3{H+nWY9Q!_GE}yg4J0=zjZ2lS>d zO3!#(UhBOy#NI9P5;P0R$A=t*Z#FLS9a6PB?)IV9Y)1*eJpHLq%K~72DyNlj9)q8BKm(B-~UzI9>g_cx<8TPQee}k2#MssWnV5AR1NAJV)QA+)Q#D z*@+27L|xkb;?Ho}Y3UGU?~lxk{>Aa<1Mm)uzE@0%E=wk9!K*iTf5m$9dyASFwxu<( zZ2*A%8ba3-?|XDgm*@K%f!z}HUUpGdgPIsy+^#UIOsT7HH`L)MIU~rg^A#E86+2S* zN%FzOeK`A?04UKyVKlm5ad;FanNoz>{Jot{se2ocrNa7(+P@=}@sx&qo6?h_^mj{n zEg06xvBZxSJrNDQ)M6xI3%iM^BFpE`{ciCkd+`KT0qnSV=|nd0G+K``d+U+08AG59 zuk;|WrMYl_EIY&0044!z*g3K=JBotl4^7Zi7T^3 zO`+I%U=-VJLZ${tk6)K{$Eu{3S z5&LApuw~A~HT$M+1!q@al!mUL?LSp-#lmPkvI>S3cGtNB&k>=Rf2zm3u5buP75s9c zj{%Jpyc#ifuRc|9(J!oQ{XX;NDz#eZ02W@Oq_c16J1@dcqO>|XyR5m3za!13e$K)6 zpgu7V@9Ox9K{&a6{+2?dRSThxR)L4I0r#hTrZ2-KHOG?(tmQcdbejVT?yZ=4m75qd z!5-4XacV_Dh#YKWM_^W+#>5c2iTp%u);UVDWf?XcssivIOs0M z$u(S-QWQU*;U-$}X2*1ZQMCEdsqsE1n~v8K?>EhDPMT}(KER}eUX!)wQ8f5&iwKuV zD}$qR-QI5dI46P3X*?$2aw=jr=JM^k_**8egP&SxgUu|sb*^ukiw6_~3N4ax1e%2ZXwVQ95LAUK)MI0> zF*0QJ1#41ZTHy!fjV>?Yats6`PQBI#+z$6wcxk-ASfgs85_~fJ+zacOMaRasoyKTj z3NB%ibYl&}*YLd6;^!Hwa}Xb?$lF19LoT1KYmuGYsyfjX|Lua)z=~>Dt%vqPEQr`$ z?yY3r@!ASjP`3!1n7oHH$!D=Dy}~EoJ!oobg%wyGv>zb>Jkb*D3#`H@Ma!&OFWNC(7_O#Mkpzx_SiLivxJ{6 z#bM%LFw9b~AGQA^G@YqsA5o7f#KBQ+ljs2H2!b}f@3^|C*?IiXSw`x@%(xnIQ5!cI zr2LY~`iAN>uc|ZMGZBrIf?BW`VAhM+gX%fxhpJpkzvS&?EXrP_-m{ysy!OefhyyI`iVE}kNlAvlwD^wOXm3DQCa}(XgT;o4E6!u>+nVJUIz+bAZ(Uhr9zw3v@ zt@klI_%%2K^4#R1==&68k(}{0DFDPjNhS)N)jc__OpOL4c#(T!8Q@hA`>K2mvj=su z&bQ>jWkA)V5t0CTkTk5kdMOhf7ivBn93t?kj?@J^g;VHI#kniXIV5`k0C)Iy0;%bx zW<5jI8ty}qp(}6h<9d>v=c28@h_qjKZazCXCjUJlY#}rV@%^7|W^#MdfXG?^_aY(@ zE<~i6G&SDw1?rn+qadr|?l~AGuU++PhWY$AHyKuvdo;u%hsVtf#tjB|w%Ao;z2ef|TG{1XiN1IPfsAOVO-?*I${h8pcXnloo9`l;vKb2}amuVQKiZ^4w=NBCX#1bM?Ej#{`_HBXQ5Hx3(*NiN@Xv0f zKKucoesnGWwK)Oe?|*Mjz#9On(oV!z9O*{hLo5D*cpHm)zLxTZ=G)`@e~|Vb@KpW( z&**^!E9D zf4|S?@%TT!kN>Nj^E~I=bDsNoUa#kCobL;l8>Nt&KTQaojWNui{=~IY5Z3F1_n5O6 z$=*K6ZD@Xv*1H%m-}yBJD*OGBq?BAg?Y)c2e!+Q|#HOXU3B8+emrtg4_HHC|p7O5LYfqH_qH_XEiiNKwb_;f4;WKx21kWQ6kz(%MCk{__W2ep1n3r9k@-rXq zU;bb(EHY02*8I#K3}(#hT9_}HvKq8^-u+)Jd_!&7Ht~_6ezuwEbIJY7&f(XAi`S*9+IiNOc@fYEC>-RO-?>A6+&Fic=yQ_Z#JkT_mv8{00pZ*=kGZJ!14LJ`=kGdc5{*vAqxn4 z-VfRntDF2Y8|{#4q^t4NYT`e91@)Hwk@8mUe|5BwcB4+!|K@i*F?F|Z{1?yrR{7AI zVfjBDSDxms^=HxX|8!mNQf{6j?%h_#0?5Avc7N)MDAbTN{;VYCp}n%SjtSd#s`NBO zzH75FeRaKj`Wp#J@8`f$Sie(-cknb?qG#+VL~QvC{*4$f3n*w98*ZhQjYXuBF{kS6 zUbh_WfB6C>E}o?p{e5#hi~sA00RF-3^Apj>;b!W<{v8-wTV?_85THy?<(P=k{G_^ z{Bu9!h=9p#;&76%M3P7-ZllzHj5Gh{3y!^m@@muL;ANWy{l{2+biC$a_Rno(rkSLS z4E1!()?CG_@44AurEJ6VjA_HgqjQM8!pG6>w{BMxp5pXb-K`Y-m(nE4LL2Pm8;2}uR4;?097h{F{V!%Ls$PBtW57LKn zH)p)2DcHR?$fR?HoC>r3AaRCj>A|{%m2V|ba7K+1X#6U{obAyY4;+UP; zQ6GJN!zlp&>3@fj*=(suyH&Mbo5GC6KM_IRLN~kk`&B4aGr{NsAc@iSh5l4=ktRbM z;v`<90cmt!U^EKQHjOhXlZpdS^=VMnJ%Ah_9u4*EqE4y~Y@vEZ?>a}6co*_KT7H7A zW}HRMpLUY_N`1@R3~mr_1Bo%e6iGD|y%RR1@;1p~S|OmlCgkDk9}Ssicf_{KaLm5E z!jTHx7$NLQMCv$ao+{4}ou(VwUI&MzV@OQ5k%pE(cDttPC=cfuPD6&t8jVll^7Nm6 zmY%IrwYJ(dGZHoRe>);a82uQq^c#QeRYcA&9(aYMsu|PhJKE^T#G#gtu~o(V{0TRM zNWE?ZK}uJcNm)~Z>#bkjFXzq{LgY^EW%8cIwz0tFSvdl?sP$+_F{F3tkR=*Cns%*E zYNG(8Amx{g(zY4p-LF(htu|^RM4?dJwDZ>!4(kR6$qH73YYiZ{n^m@50NT=bI@O<( zHW6rv0SeaJ75b||E09qf+Yo_d+zH`yuJyD9hV zilt-3$zI>E#lsxhiQ`Mu0R0S0i`-c>RJJR5jb)WRHj8A6^y@;9n$kY@ou|TdjYonj zPM{_Z`&n9^w79iY_m*)ZKu{`KM2S0_qInuqqV)dM=2QVPfO-ivD$DtZOW>h*$;QE2 zf4}MAu*X18Il6vB^RmE7FaX@7$ZTY77Z0(==>TKc6q*GiPEL3BDeFLkJL|^3R zktR(6WP`kMwwGLzgt*V8h__M|sO94sQ8J&g(*Ot(wzMphI1Dpyuzwskp0|Ow?M$#`?lx5E1uNvS82fN!3hG8O8`n!fC?v&o4 zw$2<4@BO>mslW&##ax%RW4va(gJ48>7h>rRYk6LFJp5o zV)ok#?mOx__7xh&T2u<5g(r;plSN+ACl-M7A7SLOcUuE>o|xp1BmkIKO}M!4H?C7G z^AM>AmnH;9B77D*7Lo)}fM%3E*MHndBq$dk(*IxpfpEi?V`|7E5CdA|Tm2kCa5HO! zjFcmQHYnUu#KX+eENh~$$waXw%{k0`(gAR*yGd6wf45TRKCAArrZ+=9;E5YnQgH61 ztdL|B*}_9PTa}$90ljyIVBk9-{GebPNyiEpi)YLGA6Do;e#TA3nzeMTDD6^kU-Bom zD&B(yN|$*^UOdzr&Cu+*!1iX2cT%Je4jE!>`gQA~?YCaqDcdU_77cV6=OkqBa5>%A z=D|v>F;8VHE@aq)oKB)>*yPl8wDR9gd{@%& z;96%GgZM){hFw?0lmF)Vw0HVR2Jxr^E2|(CdyK~F!YuTDPLJAk#;d-IJG^h1;$GgR zsizHd7D|Y1@4N8ew9*t6TT&D=;Q~iMM%-O3bu^&#v3Bzv0SO`J?~>Nls-Jvtsnrp% zA^K&8nXcxQvg<&E`QhEnpH0nhERe?=IN6ZPl^b|i+4e-H4%-Cb@P{E`Cz z<&6Xkw8H~~15kFxgIwoMuFxkhCMUL(&=HqTPrcYyI{8k-VL?brB(R|O z_aOH}KRq_$gze{ClJHWJvbyI+TnF2-nL%L^S3*H2+QGazX^nBlr%9?K}h9o zX6eeF`rFf6DW0x&T#G^YIE8IEcHQMx%uMfCcFJDM*kf}L2vVFal6$VQF}3kqv;+S3 zWYYmT>&@Hs5p2|z4`n)UrfHk&)!J6Io37h#ecl0svQ3&L_Sz7AmOBid@_$=~YR3ec z9RZrGSmIny89t!#mq6R3t)J>85Q#7KSI1uj{`|XJDo!&H_}~3Ex8HhwbF0j@;f6-Z zBh?eGzxRaXjP>a9-o_nLjg@HF}l=%eyAw z-^sO@Z@>g)3HzzS3xq$a76gL0p&smftxUKnJk3DRB$$ECxZ!c_$Bb(eIhU{YTH$PZ))ZHM=(7XKz}4_HbOMleU}bUv0=&|hgGupksva|5M+q;-R4v4af7 zgT_MP|LjPe|965S3f2&Q^U0cgX8Mx%c&n;$RenKG^(WPv7RF(Th1q+Swk}h{n@

A`p3bu2+ZS~0WnvtP7M1;moW6L64l6mjm!a^p9A5P5i(K+L*ZaAm)2UaUq~$UV z`5YLg8b17){rV4$+q&78x>CAi8qdv)J9Y|w2ik{s{qn6xEQzvpUg|Y#^$&h?I`-a3 z+s~6)7ImL-hHC0h7)6-qEMC)2AOvOZwhd53`=$tTaeexm2}nGa4DJX(uM<}%1m>JT z=2$Wsi=7M>HSu?wOHPPn+xA%0#Qkq=$Uq?7wJ=>~dk-)0&XIj5`;Ccf(Ry{Ch^Sb- zp!~t}Ob-jg0k$;7^sagRY%vl0ca+)&26<#v84S2b0wrtsN&bzzcIk_DB`pSiN#IQiWR;542JlCC1f+JJl za(iIVpf*hrivVp*FtM6&m}MC|Mz(qce87SYAVUrqj*;abAwv^u4whoNI*&W{lkY7) zOaC1!f+($eP|m19E5;aObw293MY&40g_xk$ql3tHo3UjTQAWA~%T8qCArc7uA0!Z# zBLH2Cg|Ht+Fh$xuhD+k|sH&+mQr#FL5@P1RBQtG4!7ck)m3S1u+&?ka&4%BALzPZS z*>n`(rBMkj+@gGrqFOoktiC<4e6qRp_~xTTL1Ez`L@yy3~6fQ?hp3P@MsQ9USyD5>Mic zVXi0!B%ndCd;0eauO_IJ4^Jz&K888uL;RQz^bzn53(*E2$d2QjwG@tps2MUM7hJju zOm!CdZx>vRUtG)-2rEhYDd3YJRFB0(Whz*RRz0sllnbcWYMf;`7?c%}6?y$TQ|L%i zR>v6J|4Isrg?IuPnt#Q5$qW=(_6j5S-H=1K**$Iv*>LZQTl+U@~bxLm%!>$^D?izwIQKf%|Kp+sSk8@E1^1KN$ zBPJLB#O0!=E2bj~AsxI-wd2&$f<@)ri{h%;ru14QtI6r~kEa-l5^;8XWz2CsdIR=~ z#Z6mMGZ2&PYO=SrnA9(067X|Uq8NfJ`K7sV62v5UI zF=P)a4OKQm;>htpdKiDGh0TB1gp&PbGX)E!0Be*$ipVAl`C#|r+SREjohJ?EAjXJ!c1v+L8fnhrY4KbdXoF~rA;6aNtl3VpbRnjLP5xT^l{k4y#1 zaZIH25ipO1%7JPMAbD&lmQ%-;Lb$utN!J;9rL=c7)aogp`kbiX_j9eXZY0eblY4~L zT}at<&rXa6ze3I00byaE@M*8{!%D$e^i&ne!_LbGD5hshXP*-^R`xK5MgY}0Mr?fq zjA5a+AQk!VaOx#;gct(IxE)Ig&^>J9TmI4^!*cQKk@^Ay+<3F__Aw+^r}4-8%A&vF zueZhVP9Z@g=#ZhL=64^+%lpG*-*5#;;CY&e;r|ey*D*fK5%3-hjRb4NR_ZaMbr>SP ze?=q{p3DKaZL6Ui4$EC5&d>T2OF>nf=9NBfm#rt>b*&DbZuaV5eK)XS8})8L?|0yl z^FuR^QIsA5x;$8D1)!BCM!hVC8?XJIQ8lrXgt$ftQIjBSCJ6`2vJ?mBzC9wF&_i3z zM_0@9CyrEBFy8JACG55m9OQPTnwxIfI$4z4ZS4)5sg0~$Mi!4MbT9k@8UmGLVa87- zW?fkyQ}Xqoht^B{81;-RmsQ_yySv{)IZ4xsA?$gJiu12#Q4c+id5FJ_70Z(*?#o;;sOL z#iB2Ny~?OM-{S63c_9;uB&mI--!y=Bmg?3TMV0xO3A&$^0vfnD3-p3Sig*?Ei>=jn z?eMKin~n1makmBau+&0|`-rNG`41V9qYk75f+AsxaSaV%7I+}<2tuDcqe6}7qGc&c zfx0|e2M0YFG@b(Pw$anHWZKox8Q;V}_%8qobA|>8>rg=X0+24bieIVk@D1)}1Taa{ z%`>l1o}aJX%tHjfe5v;I7l5B1*FyFr-Pd49KUWHZn9}p9LNnASYxg)QUrPfhl;<=+ziD?vRHg*n zKXcxewC;&m(Gh}33Hh-C=zBDgWNAkTEpbm8(-e zBk^Y}l;ALxW8%-qkUoTg27MR-P$WQ{KC7s`O8T}H044kTfFXt_P%EmS7XahNLOf6^ zLL*Iex>FT0ugs^VBoe0#n1p~z^`yI8&v1y9xphD>PjFx5yYt}_9qAWl6ZlE>2kaJT;dU+_*}EW0n%@dK|yPMolqF zF_tDZTe(F;ntjzpo?VM=Jacs0sZ_hrIs||79G1;E$O1z4rtKNE>JyyGNy?KHxDg;Y zL!S?@z-Woe{7(CsMza@^2jR5l$-T|&XC za)ew@Af*!wBx~NI##td^K2X1YJ&pX%CN?Q@qJh0^+q3e-KAoHA^l;aeH{Lho^(rtU ze0&6F@LINxy-o8Lnwj~;7U>GVFfm2>+sJE4Ka{A;!?@gh95nlnfN?Bz5crV;IojU8 zouv(jHAOT4JnT*VtuErqjvn8wYP&;B@Oeuknl*bX8s=-wH}MXwKD(yl_1~KgP~Jkf zT_&^9+Lx9?mqK>lKkf!VmkiPjPGSBcoI6IieFUKKSm-V=rvt*Y4M!LyAM2BaPZDb% zn-DXVWyskZVNn7c(K#F`xQ_RTmE@p6->d4;-CmSgpX^wC({*Dm{f5XtXx=e`+H-0* zq;vFZtP)_`wAH?HdNR81yg`zeQ^J%`Jl0q(1hJ7S=NLapCmlGR;bPFA@FWZ#*`Y{d z0H- z6`Boe41ic2N)bl+4^uFnBVZ8=;|H{qfQz={uN2k)RpHyn-y%4kGs~jUYY%uh+Wd|F zduiSepz!GEjg47l@)d?@MH_8(Ob}OBPu?PEtV!O|CJLnVADSBe zO;hz_{FgZOsaeA}gBVgsYUx(vQ>(zP)BaUSX2DBQTrq#{?^9%un!Q{RXu)b8PzSRK zapc@N&1!&0tEp63bY4rsWk)jWsuwn1a ztrH(JCr@>q3UwI%^)p=B!q_soXlwi+@=M)*naM%&cbT!z9Q&uc)>i&L`{VJm7momR z3l{brq|yK(+AP3z3rzveTB^l35_uw~-ysx#>bXQh`I_Xde+r5%XzZx)VqYxNIlGCp zFCZhQiOb&sr?dNm zdPvOx#ZACj_`VyimHx^!`JHun8yTKc3L=6(vaY>CC*(S8cPvQPhydjbDm6LlA&~u$< zXXg7AG7|TMz7%s@z*lTJ8DGb9!gbTxASMs7&4S_q=-e}%vs&QbD@H5!hGojnrQ1H4 zujrV>;r`mH#3zO?h3~Bqg3-+%eTzy+IHvsq1b#XsPQQm%8}my&D;1FKb^v3r17fAC;3@uLf*3Km34xrwJCbA;dG1mt)$ zT-o@|X+aU-N+}@o@?r=o1HjI|@~(m*(w8c~Au#OCL@$BE0Vn|gTenFx272cpfPHgk zYO0SjDmV}R(J$~913d`?YHDhYmjSj!Ukm*Vt3+ZA=ihdBRKtwI14vD}IrP9g={Zf5 zdD;Xq_e-oxI0hbWH{3DcJq3V&pCKL*iv<%gaHE2A z9^TjhNDRj@y`g?Ca8c@48A!AU4>(a|c6f;a2b#9uLY9JoQVrGNiNA#&@KS@b%V;uz z05r@Q8X03OPkQf$`KpVJ4Nn&jAhU}`fHh)g7?H*o6br$2A9&Y+nv(CgCw3gzAf47; z2$Hkd@4+DX=lVR(!aWsMu&OX8LO3zGBJ+y|BeRm)YqaHq2caGv%#rFa3?!c zMj1~U)f;Nd{h~!pfzEq1Z3v*e-ZW84IsT=IEt9<*w#`9bWZ_d2YRE17Yowd-+Vw*(h6@~fvC*B4&tcU|#aRHr34&o(rB*`3728C!=kv@zoiqIUKeSbG<}9kD9Zl;P zWslFMe9`^=OXK}vT$Emy>qxgDX$@JlS;{9BOOW2edtM1hm#9jA674 zRxnx-h$TcceRTxoOQM6PU5cWH^gdI~#DEiA7DRtMXvk5AVvO_~2smI)% zf_%W3;OPf3OnCAUSs2`=%g;I*qE^R4{f)}6ipC7i=%@-ftzj=Pv}0VvFGH<8BVB$~ z1s&jNn(K-Jq%YQd;#w#1YBL$i^1AC*AUfq1b2Ps+V(l|N21Bm`prt)$pu!j%qYjTs z=M(Y^kM_%&uV(S9$0A zsaL6217+Y&FBA4}jpxsfH?MQxPj%R~x6@s&@tC{3b?c_rr`&U#1*%(i5X-enC+Pd>AHqgBV^xY4iZiggY53geviMtqn!gNOC9b@?mrnPCe82tMTbb9_i#`Q(9{xtzRlM`@ zh3dC5#2@q}T}Y7eJm=-#Ym0ZdFb;+t_(f0o? z-kDW{fk=>vbyo9B|6XELYqx(nLafBd$?J_ZI`CXf8SJ@#jsspaEJ6#vjJ<(rGa*kUM zb$yqC3FT=>i|14g8{sHqY2zHYQoUfe5(?Ur@X|?~GFt1KWiO$t*r$zyUnK0V=Xy$S zN_bRDrg~|oD%I9rTyMGL3e(VEdT@llZ0*={HwYNH@t)mUZ@ zt1B8;+@{_6jnZSiskI`uaq`p#(mYf3>Z(?+Ng?@%1&$Nf+04-Nq4$v;*OQ#}@iqP#Rlm(ezJg2R4rBp+od@~LzA%Drfta1uazcQcoE zWUxa-s5(6ICY~kd3A2TGI~p4LQ>;khOU`$#A|`rVxt9e!< zj7hh$OIKNUkPJ_$#IMcjualgo47q6)(V>Dxg-luL*(Ec)_Ug&RS3sU5nH1M|tV4@? zEl8g@NpTvfV)X=}=+D=45Gp4oemT^HMJC!U@g6y&+PwY3ETY{{k(&D=;=d(Ox8 z)yY=IGN#TQi?{QgURpueduUeS@LE2Ws!|9~BC3n$AnSmqAsegF@NIhfGn8kKD#Vd; zx|l|0sH%V1kyQ69lX-&4Lshe-N(0wXj)R&HkUOM)U+N`^D;ZV1GHO9%a`>oz_b|U% z^1EQ*rsk}h?QS4AVk~V$c!PT8CC>djRi{aij3u_y5<|krnuD9FfGB=JoX68~mqR>q zE2Fo^UJTMed+P7nq}+ORa!)-8`jD!qqso`SXIJ>?qvJNmCUg0+dpU3hKUz=A0 zRRM9D7kEwXj>5;V%_6!>ji#?M>0SUt$fJT-?BeCvT=IzgGJ*T|4@O#WNxqBSh}kL3 zQX+3N1G{}YQ^6UsVZMsnPwwbgki&hEc)ENlMTsj9$rRIhcim1#37*U6yfsl_@G{=Q zH0DflB*K?9+jAL1?M>pirvC7~VOZ5nP%}K_4qBiZ%Rp^EJoVmY^WN>@fZz`8FU-_y zES&)IwB$rO(pUWCWg0`>&Y9m59uL<*S-P-G5o$+MKO!TJU%m|UStil}Bcdcphax!F zPCxDW!86w@@5eqnLiJYCYf8nEZTC|#U7sW~NlNgjJa?j&M*|=~SdexRePcNM0D_9e zw`)^8p&ns5Qylx5Se0i+E4IL3cevcpysKaJbPl4i6ro;ZC~()wH@qWj$XnuPnN>ro z0b>Uhhd8mS(9fWMy;z+am%@EI_fJ}$!*lX<9gnfPzF_iDd!L)9NmN4hI8Y}&!o7f+ zS8ltG&FTxtyPyD|?43#RhVoZ%{e@jmSQ57J2cp_v+}|h8v4dB0K-%#Q8(_q&w@ifE`nwzk=QC8-ax^z`yteL!3BjVg;3odRoDc zI5Q$&eJMJFMkK;xR>%H)s`zudoS@20z0Gb-M^S*k6Wf{689xP7F{_~a)RL}9Q48K1 zF|1X;R#3rZrs($cZUMINcioLpN9t(D)58}(v6uVmY4PlHi8T}%Hlbx8=Qe*n?X@UV zVZmN^xy_{@ZEbDTN?W1D8Go`pW5rxo7!c)h1*?CJ69?Q>NMUcWCVhhIG`Yi1ks3a+lMln%bE%C(k+ZTqfW z?d#gfR4?JVW1NQf$%9l$I@1HSPT8BcBn_+9)a!LUHF;Sb( zt4o)C`qPesgB8oQfz9A)c)PSj!Hoevv+ZOC*w0G-XE{ruO*8!g%8zs_?k}@;B*kNv zY%rX!NoNy2rUy|l+}J%?BPU{T^%8eqjZN-g`?4%p5y7s(L!xw}TON`$22|vp-$-#} zNfwSTDzgi#I;BTxM@K>O;rBidwpm%3!bpUD#OvepUn!?xDia1;)STdsU4&Rs=k^Vg z#(VQ>?cZl-&;%@XN~1}3b{2<#W|psB1J&h=qlz7{8s+g|uq->LqxfrB{KR<|o)-l3 zSVyp+R1*JyR{Q-aC7bM~li@u&-^mFyr(^)a`&Bc`$CoR0&fx{Odw;TVtKTZeQD_=L z#-Ju{$|j6fA$46OY4YHY5huGLa0*T4^bXWnjyP=-b`k z;sL{@(>C+Ui&N`{VRM=KQF@}SQ=HS2!IOCRF4Bsl1 zh<3TW#{pUyQCbrPZtr|ddmj*1bYs~o^E!!Ci3X6%(L~GWtzd(s-Fkg7KiJ2zNwQ4q zN(_c#;3r~Ws^&Y6xbA(Q2Te6HX6VHnWD%N3_b4t0Z^`5lRe!c)+IgJD#?UlG?<_hl zTE#FXPJ+UrS#yJSW}_Y=?ugm95SWtDb&j0Qy6hItl(P1!?QYtRp6_HG(d=AZBPB+8 z)DFw32%)1BuC591Ge)xyOW|MJbai!a{zKG4_8}H^`==__cLmST0s7>c#wPjsM>YGnpeRrfHuA1tgiqAQnqItpJNu2}D_^x~> z?%dVXXYn)b$;mz}TgnL}lc8h^qSlTtlF&%ipJXaG$gS?M;EF`C*5Um2pR>bLwhgIl zM7VKVmNQy)jnb))%yO<17aw5TLwtQ*FPL-XHQbz)59J*!l<-;dHsjCOn_K#wa6|RW zy%a1qPp7^rIdHJ8XiTSuMkLU|R})$DPqbRKoUJt~Gkmwe5>uv={^Ezwt8A{cm0+$u zK`%QCxD0p50dsD=Ksj!l!iJ9G9JX*dBe%_&chw-TAB0k;?OPPN-%gHI`UBL=kcnT_FL6$ihnwI%SV2CaxYZ ztgFu|VE$tFlEZVpYbhoi1AoLIIsiiWaT@XC@xB_<6p1GF*?TzZ(*usEmy2KgIe+8@ zz6^Gm5mMF{k?oL5$NWsVWza2&dHkyFqqj$F!}i2X$$_2n&Y*oV{EaUl|5{J7_@T@E zy)_v~EY2lXfyI!4>Z+p*+SBU!`}>#&7^&)koErPK`&`K;R#4Q6+PA%zV~pLct=JFZ7rx z*@k9YTIfa7?5EE}Z`?Kah^;6Xee2#oPE|HKD{6SXBqgCj#Wxpqp?yjuD=yd3tqH!VG|Ih52=(GqMU1m7%|VFK-0cov7eD@^CwM^Yaur6t07p(D|PJe?}#52Am$|H*5}}`YK;i z5*-_F{As=ZbSnGCwx$zW%#+ddH;fO)I_v;>DC&ph`0-L8bGfAS-NLn2CE9AA*mB(y z8cZ`x6bd$Mj;#CJVnasJ^)~A4Kd+rIl0OZ3F7!cXqJ@WP;B30?58K^Bf53lV`qCF6 zLXhEDH*RZ;<@vQsGXwAgGl#E@Q_<6l)o|aD_Ajt$obZFjx0~LOG=&P+bA+RJrfrfH z;Ei^Y6o1%DEFYBaHq-o5Xk%&AEf3XYi$Bb$1stbm;*J3H4i=sOXlVc!svmIW;<^`n zA3B}F;L85y`kWNCLhA<=-vveTxeFjGg5S5(XV8)`#BU|(JgsFrk_rli+Lj+%F z)jECDo<8xrlL|8wQOlUK%-e){LdC)4UJS+P>V)&1meTHdrTs!bMADd&O!(R^)i?_yYMecdZ5oW}YgW4~Z*Ka<5;OufcSlQHv?;$OW_kAicyBFT(m z_<4AtQpFq{^zIzQq2YUAh>SSMEI6uP>iysqf{KXd`NdJocDVQ)LiPP!Y%)sz1ijbX+d&kB}9);fT$jorH z81Lz(XuQCa=0)I8E6jqi{n&|K98+$%z^fLyj%?Fr&emXS7`6F$n}?&BmMTVR#F70` z{@CJ1>-8DNm`&lpuA`d6eCv*CbDCBXT30_<8K5Nd=i*phoc);8r+jXRCt>?j=t6$_M1{e!a1~ zKfZ@2KM}by`^`#97IJfy+>%@dc!N*q)TYUPa>j5#8i5mvld>{CQVoLPm~4^1WUpZn zC%_s7U?8f7qg@*LZAe25jy`lq44kIwyeTUK&8F|$M%Ml+AoLT5h@@M8cvbx}v40bT zy@{ab%H**c;b47d5C=i@(;W`NYQ?HMy=HLCAda+hqezR#G%GX^M`F1jKJc&*J9Yj? zdG|lyzaaTc)PJ1&dxDp^Bj!8)@2g16(J>_L|33Y%BbL9H`!N4H^H&OL$5Jr+D}@~_ z!V>tg5T!s&oI{MSO6Yy$)R}Qc1LAmA0P8G;tvGNgnWKUlHH8d)Ge##~hPLbrNV5q2 z%J+9O{eoR_L-af6HOk*hVTr8Et0xT|WjH^Svr~V!4>Ucf`X<|CPicovlhd-;2)X=; z^Uv0^lL24)RM$r6rTQ)Ku+wWRfdYkeTNk*V3^1M8elR^I4hhYX!aX4rSV9o@)R#Yn zjz1f0J1=j$!wiL%Qdoyeo;R506K(%W7WlzCB`bAjE?N86OUoLKZCeL4>^vYbk#Xc% zCE3=1W$nSZq<9blfYA>Np#V@0ma%PsEKEiNNFXF<6W0D$9L~q$2s#2ZC$NZ6@PP-= zAK5Z1i`274-qy($q7bQeBvcZ;oY!S!C(rsI^Gr@1fVrfp-tV2uPAeWO71F^BJKsv* zQrW!kj_`c+iHG<-nzKRFOwAP>=r|>q#*!-(ZW@YUu zZqx-9(OAis4JI6WB_6h{jA$^M$$A-wV5@5+wMW=t}uM$EBkXXv&OWQRc-M)qEE}W z0i4Q};le{&AUx^-6~Z*AJ$uF}84rhoOHe{ah~rnB@xTMkfK{u*=OhAO$T$zNn|cKwrGh5+B9{j#7=|dsVC|*!i%;T8 zK9r*&lT*Y_n^~!D0Hn}>ZsZ0(XgqhbNTg!7*s?3Qa81~R>vZ%wv=TLF}?V+B*`1@zfMDFs% z#-#N3Ohqb{@vmP^)2l8K8F2E~C$4IFNqD&f0piHBJ%9+q0Ri58h&TEPK&>YJHSA}{ zTz3EE@)H*E7F06>vcEyvTB`SOkUr7Pi31t-MMa{KbdeP2B<-$PPvcjy%OkoquwZOs zo0juq6`rdpb;9hY+lIs^El)N7VQRC{VF@adKi9>g$QHGSxtS~asc+45LiX}F-?~9T z6d50vE~NhQR@g2kG*ijXC#3W3JxROTzHoV`u7~b_nD7Y0`%8E8333a;JIQwz?HL4r zCESy|kUlxpVXa{|m2blGkINnPbI)ur2680 zX~(um*hzLots;9;JV&ua_5$7NjWddqBrgy(Hno*5DO|c@=L7WZjqhaGE9;+rH94-_ z^FH6Cefnki>^4=alVz=WUZ3GzF{_6Ixt6)IE^gnKf-TaF>d3yoUWVNYPjMM^B|mLe zpcM@b3)A`-U1Jk_#U{Fp!ueq^SAXrYC#fBaz0%~D--s|gS1Hlti0qKS|6zxO!hj3 zMfxCD$rQ5Y<1^!%; z2_88I^|*Bjo+cbN?^WT8bq)QJaKXz}ni>=0w_+*;qV>>W&6F(OrU04JOD9*JG6mSs zc2*bS&s}~9EDGM^=)^ERdpM<86b4pR%M=30l0HI=YTP{*VSfT`M55TM$mbnexV!PD z&)$@1j-KN8DY<|10|p_M8bfJWqJXFqEeld=G2s+|4GXt)f$S>%sT*h)W=?mkcM?xUYxzd!zVyhs1K*$ z{nMO|10+}>{1*vFPF{C-r*J+y_8j2_c+K~~3w1-})9`19GbyLh8aZ%HI(Rvx8hSlF zPETJv7Gk92PTmX<0@-A2v!<0YZ|OY04&HdnH6PJ7;|$S!cgeMbfrkV#e39pzetDV_ zOF2oym)Z&kT{y>>H?H+darB;5ouPTWxVcty@4~ka-{=?Ux$!SC z%!TZA23s#e%nbL*(1L?CECBv8BCjA6pPlbWWu?_TEDa#b3?C^2Jq+ZarVm6P$9~(^ zy7JzT+6P+JM@&CzF~Nlp&HW?G-O_dn*SS>KJngXYp~&7lwJD%SZ53fH-295`npiJl zX+3FKeW{9!4U|x~@YsA7fk)cG=YJOp_=sPltHQqKi6f;qpGoapO~gKvs)M+QRLETU zlbH`QBX!TM#iL0-Vy;Aq(gI75m_gx2cQrhIHGnRk za@hnJa*u`+*oUVx(VnJlS4)Xw-~8|~Ru@ZaVB|wHkBuF!`=8Lp1G0tKYv+ic_}i3? z5K+J>32-{pwBw#mm2}Wm#+>Zw&H^^#Ksl-Gimr7kA98PsxW2E(NV}4kGfLwYqjeIZ zoGw@7bVmxp7lL^-@)9PM#Y63@M|>{~os()cI3@h?d3#0*oAq>^XKO)Uu>y>K-8RdF zeK%MxV69}n^FNF&uGiEkL@f}9{EYHoYf_`X1T+Gz6Dv&@! z72b-7et$bmZAT(NT#raW;c=AFFX9Y$+0WgQo z?up4Yiws|T9HgJ1ejRXy!7Wd)Ed#;#-=#ckv!^kv>V%RzznrP3l|uX@o<@z6?GFGZ z$un>fZ$H-QKd)J!K7H-p*CXu|+a9*kNQ^V~Co18g?*k~~#=2Ni-l9=AD=*2jSTlgr z+>ZC(U&0B2nnz9*7+MyU8zV)MR5{=VA;3TM7DYQ*tl|IR>`efn{JzKG`^;uA_C4E> zoh;d-j5SLnODSYXQI?Q3+l+nBR#eg?6(TB0A!FByQpq}^QnD42^?gkFe!kz|_xHa4 z_kBmroaa8zbI-ZwZs(qR&biv)F15$w{98?Z{n>;a);cnrl?7SbEWp7DQ-COIQ3Ke; z!F^4M4uH3#95#L8>+uA#D2|io?|q_Cfze3;b~ZmC@#evejJm);*6)LR>$SJRxj{?q;6OJg$|Yf+&)4$$Ryf(zxGe1z zyNih!iq|(EsT(J`*8&YCJTI|SiZV%zm&n{S4$(=N#XM1HYA=;AYkV`Pt-roj!m$>> z8k1oCGMLdlsUseLj+=@oh);uPhOSM$WyZT7lm&nD!GA2eXF6FZmmbWhI<)vQ8xKl~i-PNRXmV^tJfp>wYIXiL#5t=)`Sf;fo8g4hn z^l1tr#StrUc0Pw!WRuW-EE&b_@QiasyfaRl5`U!1QYNANQ2j)4Sbee0U4N-!eLP-h zZcOU?pykW*<|>bTuXn#*d}N<1m;ZQk7U1Nw))Ism2!uOZj{FIy&W_N2g2>nG+}TA*zp)#dc_GK_Brrp23FXb zfeCcr3mId$X^G9mUa+~qb@(@*J(E@HgC1`q1M4i`Tg^S&mGY0jdyaGRai&XiC#27q z$-#me`P8xB2G8#Grg+O6WVZ@mOP?g1BmhwC2QaX_8k!shNan=9sO`2;d(r`YMKZ<< z9AF3A*poJKcPmL@1@szM);Fk7h6uBvbG{mhKXVsb{ot8WlgPseEwRLgx@}I!{XXP3 zpXHZejb;0_gzneN1kxpKsiU-NU9$_f1Sr@hLF7@J-#I5Nj+J2Drd!J^7B46z#`MT= zKWegRsS(?IO79nbDzBN!U^JMl7|-nXQKpg#PKnY04~cmk0L~h4mjsK;$PAcj-g~cL z5nnULg#>``GHi|8JgvB=kAS#F1(;PSIJ`Ou2{YK8BDECzgTy=!OF7XbAYMX+>hRmx zv1s5*0_;-o`fBJxJ)D~(?A-n>6NIc^TZNy36JAijv8!O)AiOEU>Gly32`5#OfK>NR zCva$n2(5|0){Xm2qHjPiB^URQHsz;?Ef!|}VW9;X1G^q_0%7*JO%_flwuK7#o(>Nm z9$uQ#GWvXuN53S(=jYBH{5FTfezW1PWKVr0NaVcG%{(O_=dFy;7UONMjl3`wCLdJniW+U$SJEK-RzxF~XjFB>>G2pf5ac z*6gTK4RA?qv;g`Rv<)bU7Y!0i3?c03EXJf=?(FV#ag8vE=1iivRSE;w}Ex(g8vu8B+)5SOAVa zliocP7ht!6jR_bpvTRyfL;@Gs(keY`#Eb0YLa#ZvCG6I>-&RC-NPb^JmIV`@r%rvCEV9067qk;L?AvT+ z^M6q>VE?dTjLZN#HExa)Nq_Z8N57(A!%vtGY~q)hUEL5-F~`ZR4k~MN11Kk%J#YDb zmZDCd*e)o`J)|=4v!fvWSh&u%$J{y>xC#X|c$x@CFDt6&tl`)HexMgHfZ#_vleSXm zzh{X5afze-$K~b)++O}kgXk)u{(lnY#*w6duKt09`u>4osO=>D1(%yaXsg`HbU;6r z%%BSV@qlBq`XQp&M8TJny#ZyzaxSS;b4k6~jqfh+ zd1L&(@{RFJrocv)r?>b|kJD~;ocd|4Hb{-}HoO?E-1Xag34?RK*k$?UxvIn{1H5G= zi9IY=%X2-ImHEy+ZlfnkCqF&yRCI{RJCR?*t?O!0nf*p9FzDm%5j?7yQgtRfAfmWH zzu~AzkYBx}rANLs+W4}n<0TPqhn^3ddv|LQFL364Rh9YjSSroUhU=sF`TH+_wZ%H& zc3@*P_7b4$OxA~}jI(?u{%dLg zQmw^nu`>>cfD;ZhU z`=4jQr^mn>{a_=RhO`rj`BN`OTlM1br#;S+861JiHoy!UnA2yie64@lzQ>mv&lqOV zJ~nNsyb28Pin!i*;Oy?evpKh_g)>$)8>UY#?bo^U#Q2NrQLDRBnsEX70*#XkMO?eN0kVru9|i{e4kW~kS= zvr_S#?(VOL+b*k$7KWepwa&C$j&*-_-Oi{RNdep`DhW7KK>~9pf-gp@C5WUuDoSsh z-dju{{b526nIRS&-~;HtW0O+bCKCvM)E*pMx$RTSbo~U}GTU!tIH`kUl_O7%jb(l2 z{0y1zNnrnA^5mh5JnoIW>E8C6d>;9F0r?yv3_?ihbpWy0~@-@<`g z;!Z@GvahZW`gcVtu|iDnT)pe5DAt6Ms4GvxUnwjPH&jv`0RnHY-AzGG62L{7KUJN( zRmu`NVB$+=xDDp`;avuA?oe?y_n(ueM_m(I#R+$hug|F+j7OXelW@=8*UMl-+6V@B zK_9=h5F@8ivba$Wr*Z0%R5vzT!i@8zkgE)25gb*^DUnCvkTAV1exUh1yFI^p8IkL; zmGL*yA-uQ|DvXfp$w@g{l*5<;shB30$7Rn85yXQ^cFXRFJrJUM#O?LfDQVOqpisF@ z5a}C7NEZ}`4v@HO237+k%!ISm#~UC8IXq`l_8v7xmbd(n*?7!#+@T@63m=jRg;Z{S z#1Q~#%g*{i#gDQ8Q~*cvEc`+xzIXU`s}gnvI9Oql37`Oj7vPo=U;ykIR1GoY@+-4Z zE)sZPas+G`K3)E?opd@*F(C=KD>ltrv3o}8wGtx_c3BZ|AgRZ$Tg%sL9>@^uzz&ZW ztfp{`E6kCbA!Vlh2Y~uMW41fxk=LOKfHdViiPcaG0v10RY1@vhBInPUca*=1tFXF# zyMvb*a|g3MIAs(MADMH(Ug4NfsI@z4e;|L3>%OF1aQUg3w_}Y5gd^8 zY(tM<=g?bdO86cKAhDdel*^I|UVi7)ZQAwFm&!C*;zK~M${ngFfL~Q;;9CqlvtG2@$*4 zJ5_Cza-B#hYtH9P7yEDpUyjPLtI>2MLBOZZ@Qgme>URC#%};4iDzybstc;b*-tW9T z7UT$a%(4~&H)65(JdzW!?^X#=6P%s?#RXJHSGO5aK*k1|)pm{l(gcXsLWthnefplN zFKfT%hgzWMOM^X_1=Yxmclb$Jl;a6T0E}JLb`*F~W_6Fow2KiLCm*s zAs6Bb9oo(U>@Og`0%SP} zu3sP;o(XTy-rY&RaN|+g#+B*Ko78dTN`95)kMpL8%%39)jsS|t25~X#w7Kd7LBie4 zrwysca-b*xY|&KFuKNjwCL6kqffy5`dH-!}wZ+ASiH(RWpO!3@vyG9AXcenBBwlW}`F?;Rz`d;*-{m`(!()CQKhMvqx~7m-ItLvM&U ze7hWJX5fg!NILiu5(XHLdGZ2sOsB4GCaa-L1$?Roia}tSW2U8->ZEJRiqv^NDrvAp z085&k+LCaNzOlr-LvK;HlCTnd)mE`&$2ST6D5B|VdYn4HQZ z+UGq5x>YsV^=%i0oz)C^gJf*;PC8z)X4SSmTc@7t^X`KyPlIwLl@nfm@VpHp0Z><7 z3V)-$M`i(3tPEIw!;Wp!0Plo|jDv>*8JaE$F-`eH=J*zwOLRcroy@SZxfbML_XZ+1 zT1ilS4&nO`=i#BDsk(;2LuPH47+TI!^^DHODttY?;I78WKL4UEfNRLjwvv$DiCFI={9UgyH zNHD8~ut(37`#e1N`Vv}K=HBlh9d`!N+%A1LbBB7fpL4HVhCCr#@VDI{2 zj58B;URsl^UH~p|I@6fme~?!Yz4`?kO2NQ9O1#Wfh46;%r%-u3yE%sW^1DG4xs}Rh zT-m8CW{@XmjoPC~v4-~=npXK0oOT(4wktbzIII)y`1CIl#V}Y_P}6DzDae3Q$|~%) z7q^FK#uN@R^_5WweRGQzceIq~mjxRdo$*-QU&dqcbihE1jNJ~hcwmbUces5BP?aPc zG;WH!Nx}cx2iSZPGiajzI=bS6xVXI@&4GA{0e)oIK3y&kgt)lfYmFCB)vEb+)6_3$ zb8D`y8ux2H?`)4768Kshv}2g^2j8Ds7ZUP%kYx5o+Ve~~6q*`lLge5G#_cNJ{p)M# zjRBjf(%{~@Q_c?*lY~gvv>BiCwg(qz3e~%ujEq;}ZI6m_`M*C0+K-kc?-|;Y?SCZv zWKQ+dK0olR;0_gaOcMC^R^i_Fqb`3?b%R{>X)R4-E2++hV)O3wgey* zn@7qH0Jt_NK{Ixk1`Mnbr!ZZ1G|Vb{;r!W2@mPTbJV0C=lF-U*?pAf7C*cwp5 zNhm$41jjTUv)D5$2RP&G=Awu$N>mJI;(UvbW3iQ!-PLsgWN$q?@o23MNw@@bDvLI^ zO-Qk$-$xwhwL6@7;uwp4h`!P&_P#+u;N-5_hd^)^Q7ms0d(UJ1^}z$ZcZ-q(+X6uR zL+#!;*Ua!)p92BrHy9$O#wj48WK*igs%!wGIB7?1xOKBq7#Xt@a4;cB~aImv_AV1804Y{1i&u3XwOhKEg zQJfWHjY!3>`%t+!l9p)}NmYhpX5241%QXBp^>XI4|Z{;Q1`#4UF13I9`Dd)se**KBX= z+n)-0&uCt3QewAiRAM)0I1!W2eZ-*aW>7^;(%9=_Co{_OFn^`lkd;ZC~`JeUNX4XepCiqI*mlpLxMjoz}=!taA>4u0V z&(y6kJoH&n$Lc;hq8B+b2(rxa^xS*5a-Y~Dd~!2)%oeXYX8*NXTLS$_P30` zvgz+X`~6~4FGUD!HqAP2TEv_}B!+-FJp>Rp0nduq#eQ-dyGW?^JYeKTECL>t@sXDelKB7@ z`=?i$Q<^ye!kgM74S->c8vslf$hB1N!-W1!#61!dgBbD_U?s|4IST;yE2x2d5Tt(; z0#RKem}D$hoWXl`Aa&;f4KXmSzi25#AxS5^a}bo22vBDH zL}=rh8=N5%FDnm;Kw+Vj|}s`HPkQ&Cj#tMlR^R(1d$ z#X+$I729rrHU*#hT~ZvZp?xIWlbi7*gcX&m2N5z&5n3Mg8L%u7BnfvOECy(@g4qN> z?4^2jlEOWj&u6?m)p^C4gmz2xlbpNuLZw0ZGqiA#9c@}=D7tWsg=f_I#(i3B5A^is z*!&qMQhFcI%1p$5etVxX5MM6LaJ-#_6l;o5XcD1Szha1qK(mreGC!D}IXoi7A9j&J z86|UD*bDcS+&XPF@dhI9IDh$Mua&VD;7AI~`25biMX17j zZFMms9atnY9s?@Ou;q*&5Si+R?F7xuTM4iR36?rb&ns(sG%Pp##$A;U#d{YRF%Q>Q zA%1eiNumS#m&lB%oAVwsI}r$%8+#o36^wgxJ+Jxf2NzMBI@V31{$P+I()@8e!r;m9wybFI2 zdr9aR6Tq%Zzk<#}en`3vBWnSifI7OF$_TG*`Ps+8HVR^m5ZXkh6+?&#@ z2*926Cl&ekCM@0Jfs8>Rz`-t1u`0@clWlYf09u4sUrLYitOfevtOiJc*&O)LUr&M; zCwMktNFNS10qc(dFx~uO5+y+U;9n?>`WV1OaR4?VyoNA)wBrz!g$_D!G&iA|0DQ6}`mmF`um3fR2Cy50>Bs$90EtGw9 zfN+k?H~_LXH#~@&(~O@|$1J=I!@vaMMecfFBljp*Nr)|^8BDAhvVUV>*e54{0BVlC z8jMOT5fWA|Y2`C+sXbe+-7kBn1-Y)EN2U0}BL}G4Ea4*8WTZ;;Tbv9YuEbMt7!e}; zTLNp+;Cn!W3Jwtg#)AsOh%|_IGY#lC&}sbsmqsQ)2VRqzkl+C0Ka=d;B<#QJ?W{80 z_A})dYMNSmGPFy|^Y(RKcw!r!u;C5qh(#p29r?}LT7zmVeJHryzp=@mHdy$kA4~7G zOx#;oWavN}nMoep-JHt*GXI4ijD-O6VKZ<~B1+I?pDUubYPOqWDD+M;aa70*g>iNA49s;U3{lsVGPb==Vo$x6DY|-Lo>iv6+8;pyQ1hG5HX>rQO)X z+OOmhlezh*mB!l5dSOc2%9%n3sAQ(=fMYY~za0BF31y9}*Ep>Mo3ptrqN7ErJ}Zdm z=)vIC4SeHNpIw7A)Tr0VOV6`pkbo2v_;y=G+bz3Ow4Z<4t`l*hHM>F=j3|BAjdw)}WJnOmqT`PQsT z1hDZ&7`>a7NKXFURq46>t?~BTWwy$Yc{d5uELD$DGh?tf__er%X};hn%JdUMyd*bk zQ`|S#y8)3ZYkud-&o6a@Vi^KZ%)$dxu-q57za2~w7!pYk7ZEea_j%cxKvsB5u-pv< z0uuYh_<==@%$EY^Y5=?mEO#=QVlvCG;sKNAKw`jt0@4Otl8lyt=X+}a(v$NWPJ%sx zqR~x(4o}ZaEF|jD7;)Vqdz_qv7{5P^DnFgh9P@^el;lDzg?ERwG_j@Zv(?)G6XtD3 zDDX%}befsX^6DO^oM_Tqf2;t+s3+tf8!*J1VrfZGJhJnpDd}c{?X`^V+gfZ?9cQv- zH!w?%SrC{Ye9IJ`Z6h*Zq6J9UHz^P&M4q;~7o6UTLC7 zL>{2AasB{iHV;ox0$ExhO8B(DpIG6k!#`8Y4O|G|cc+AYIcslQ!x{mxeQH0+wy_&j zM4qeDH7Ua^A}nWz^O1p3{D>2{6CxrDA8T6BvO)eUP1m>h704BYCHwcM8iGZ(j zog^A8D+I!nFC|M95tqh|T>%B0#eaA_v^!MzMfOXMN`SnB<8D{ z@_4Bg5y9LqNR9KKh4g)wG6k?A9 zh^h`@H7(BAMH1Y`BNG6)Qc|dwM+lj~pcQb8`BmVvlntvQr}yE44m!qmA2lwsu-v#c zQ6y}7+;?nFL#*M-3@M|#0=xaND9;U1rum%A&T0Mn{gdgnz=bvQ_VfFj8iReOf1 zYTDeGKP6YFov;JX7E)7j#HI2?a%j_M0^&4-0PO~d z#?U{*7BlMau*J+z2MF)U%z|K!6-cl<0Fi4(hrn*xh08kk;9(#B2;F#ZTpB7XGOvje zNK%pYapxd!N3bw{d5qvV`mn+7alEs6yOq{x{29t}X>!+_pkg8M#CEIx4Tm){;lfYS zt0kcYjmL&R?AoE@-`|}eb@AuCf4I%t{~W%e(~A1WqUdG;W=BS|KFde&Y5QwtH-p1{ znT+44!h5*7?${!f2~YqKutT0v)moOCHQn5u3CUD2GlVV&LhG@e;2<}fOs|xuz7Ula z-%w@%zVdKda(FX%LxxE-`Vh^muvJ#VpRzt7GaG`rO;ObWj#Fx2I@hDWazbfiFuT3eJwyzQzW~sB6-q*VKOruR((^P`#bT+IlvMHEX{4kAC&A`KREd{^@POntFe^B{x02? z;Rk9gw|VsA(=@+WUP#0^RG7Zm(}Qv?^gKiMzT&0h@aN))!c)LOWKQ~nF=7j2CLI_e zGv@$*EI@7YaMSK=1Xf4D_%`j>;TgH)^9gq4VYFz=P|J=LMB_P{#wwszF7ElOKB&yU zy){`!QJH4>Nq~eEu?7obkg%&VOgKETG8b+XxSnI zh4>|643Xtor{ZmYTyamiPJmQA6b;H-4D3ZpiZ9w#oqHC{;u$B#^==>UE6?$$(zn`H znHFE{_dg3tr-5$ZMnaXFf^UAJq0D~BG)59Yy@`u{LRJ2q`ih&yN_9VokX*#7$5V=8AmY}hw$#jCtvqHpOcmUzihIW8O-_ef^3t}wRB_8Ad z@OS<%e{onkKqw&Nm^T-zoBV~FOp;O!iMgo0Z4lD%+n#vEgmZFJOIqkil@~s-!&0#v+h3E#gihB)A`Xj80$_ zq7#f0+9Ft)4vdmxex1NLQ%BOv_=-#gN{hyasv7lY@m-;ttq^Clh17u# ztdnt$o1xutFjAOFeoEDTI4S_JEQK3-e`9K6-@#n@4CM{!rwgR9*YenurgbW5@+> zYiJr=JNy2Hgavoskq?SFk)09a$+xOG8uHV;uU`I0DYwb@yXeSNamLllomr+8A^4H7 zi70mqQ3)L|j3wi40~H>?%f630)S0TZ)4ud=B#9*nD+)K^!RNz9^TrGTi(;~&t*GP< z(!n@`*#*XiN@OY*)1cA3F2SJMz^Fh>oIB-5fCGpR5I4PM!AOKSm2)57zLhE!^l%@? zjz?~6$qC<8gX+)T)SZL4F{i8e#cy+*`JLd%w0}|H@$hb2k-T$+=}&&UO1WB1(5?aPE5EPLZo|hm<q zGfbudizfrCZfQ^wn5K2t(Ga;D3{(|^87OxGcM@n_H4xxtCXCmZ+D@TWC&AU=Ob$}qrDkxqV; zQ~Zq?ZPAUK!MMaEXeT?ZY!E=Vm5D=Zhq>GTW-{g4#R!%lTH%=@oE9yov z4Rv=#mkji@k&f{6DEFI?qMl+G4uJkW0;C^y{!`NHbF7E_&|ZvrrnH^1;5iqzT^1{ zSq{Mw+V5U6zx27#H0hh&^JLRc&4RsVZh!#~vC}|w5#BSVHXV6Bl@nZwrm60kv?G&A z#x>Kk+=~KZ7tkfj%3lbiE3a?!!W&>_@Zd?P2$_WSPpKB!SI-hH76n|AlLgk>sr%m| zi|2TvBo=H=oEF)UHc+crkfeq0laM9=a9}CrhvZIx^fo=;)%K)WyfWu0p_)`n0J)?; z<6!+(zwD+1gj_Q2&89apePVo*37`C7&(sN9Mgt(hh&(Jpn{Y-vUg|t(gpDV~Ns{w% z{);=p1(Q*`T<4|YyF0dBSL>BepjG^8^jLsMMoi>$JZBdKGMxBy<-0CiX^*9d{=C`I zy&+89MZUUr?F3@%M+xoO^@&L3(Ku)*pH{T=Ar5M_&L~Jsy;ZgMQEN*Mcj*K23;NhO zzD4K~9r#7YtpE-d*vgeYb~-58dTvTV@CUVVe&f`zGM;Mi{!k2R(4W`#*D?gVKdfMbf5@2R80CK;P$d zSB!EQm#I9G`Q&9|TDEE9>Etq>eWmarLx;;0+PI%(9gySEJ)j6NRM*_uLl*Esy>&Rk zUKY!`X#sqIq=9+4OS234oZ!7VV6&)g;WniM@5w9{faBi=><(oZH;fuqFRhb82bDFV z&5IdbMjmRUT>raA)S$BRKIr#VovwFI;C?8V8Yo!k=jl(s8a1+biPT)Sx`NwHZyGF4 zTd4f#Krfl)%pZjleM)yw`j0IyUq0$ui%2J<%ggtlBj_REBk`dkUw%Ys!l9^J6^2V* znM&^tjt_p44l95bsUyYWNj8&>n>EW4w}mHv3(w{Mz(Zp=Vnl-li+@R+cvYWOy|+xF z-y_AA)}mdzW>zvru8#AqkzG1w23@8x-0Ka-jh#v>h$pn>Z`%?c4xFRoDc{0Fr33oB zWR{lAcmX)}eL#eyS_nO!+-GzI4>muL)~d`MkdpOmOyN1!aYWKFP9-bxI0577pt3hk zOlgAA%7Eul31wb5ZX?z`QQ2bRK|&n*c8Yxr_Tqib=Cl|Ms}hM<*f;t7ty1!_ z>tYVXt>20?F#9Nu_n^r=%9qd+w;=RzdCs=nC|Wt+zYF(X$EIx;b1Xv+;~t6}sI493 zVMk=RC9ff;=$nQty<4oBpaX;)GRq`@qt~;*tfGr^m-^`99IT~A@ck%O>Z+$!AAV%f z5Y2#g%gv7QN{llG|vt4%Z8~8d|FOG0~zj? z$F-fj*K#5Bxpi(5&IO-81Kublv#WS%lMaR&kO(>IoK7!Hlb?E85h(4v=Me*sG)8wr zJE-(3UHwZZD?1%nB(rjD_Qbzr`YBz;ZwgcZ)~~zQXqRAZb|~t(48LY96Iz_VF1a|f z(@~&G?sYAJneh2U`y%W7qS6X9y3JLT2^52gOm&8BXmkwCAKKhq66Q^tU8YPG0 zJsK_Bc(!!kwlGb#!+|$s&24fwzp{VT4gU%`9TL(o{Hv}myslw-MB=-1YR#|E*uKJ4 z8E#2)h3KAL(nb?kcqZ&kNf+eLC0{QXy!hD8H{17fhwQKtAre{;W}-^_p&7%y?Xy{|@b%(MEYFjoxs^1S1`RPgT9?%4RO#WF@S&lG zq2XWQ!_!mK({ysKh3|)NDbfj~f2FERl?^-feUgm*nkP~=V;@ph!_rijDY~vNZ+-3D zI@wj&ezp_!0|>FMF=nec|0kh6T%KYTs! zecfb)w8qYz)Y`7iM`|qO7Iwcmb2Iqr=Ci-7MG39EBb-l29U->j{G81eR3w5n4GvReLrG!YX;Y}K-L{e*o^Cm-ojrPVB=l$jPW^oQ$b4Wg{ ztAk741-FajLZ?}*=co%FHm5iHToYF$6IJb&(4I;{NVko{(NI=C&F2c{JE-^*xIfM^ zJLMnt1C0J8^jBDW#P;Ph6)P9cCijjdq@Senb<93p6Z>IYei?F3pkkK>T4-_tk9t)y z1!rFi0masSYoKK2pRiOBFE^wspvb!JN@SGWJw7M5{aAYy82e6PhL4x>bs@Ttm zuRQayGA&afa$ZNy846Rmi05uo>kq|W7Sdg~bt|x|nkZS*Q}t{zcF}amNNMTAc`62t z54p^?aNc+=KD`PsroH2iIN_e)!WuDKtutgQC{^37!Pm;bnNfC#+G)lin&e~j^nvn+ z>(}`9ah{K>a;$ufx^CXSfi6MKu4Qb;Jb!%0=!WiHuMooV^W){g-a!wzrKyC0APX5- zohH_{K@u6#rYHB(MxjTsi~r_zS0N%YFz=K8h3PF#@g(pzG@oilE~*2{3xt6k8v_P zJ_JRkvNR-}i@o7N_(0%By@)PQzegkO@NJwqk<#zte1tG`j$u(nC5Ncm81T+YB}@2e zPE)+lF3mP7I>|i#>#X}Brh%upp@VkPo}x0z`$Ed6SAiK7+>1YcWA+PsUcvX*8rh}n zh0UI+o98jqyz;g1r_C+ed#<{r)%_=62d~q!H>}1#99Y$lY`O142K!NjI zMem;HA)fS_%>t}KurlU&g$mo|EtAGS&uVsF)r_(zNx1 zy}way2rp!ytzOi`k^AzOh1BBSc9WQjqmN~ofB1Z`o&=Di^IRvP=>(j+^9#f6V)mpp zUGUa4(;+@sE!nGu#G|=xVL?~`F4Vv{cE)9X=EFr(FVro>^!K;bikJ!=igv?jSRLHK zmVmUmt~7L`h&}0sJQXdM-gS(`NwPxvH*kIv%jqcIlLDNQ_a6IPpQQ=RquDJ?Xnqek zMDur{v*ogQWA5;|#9Kq;N&lB?g1s&PJN5#)d|FDJ;j*$z%-w=e>58XJT#_yuJL+!ts2ld-L5TLKcKZ7tD0?=3(~oaToFVGh$vPwK z8)8yoZ}l*I{*mcT!oF|7qo?)g5)nQ)6);4Tq(b1HAH87e#;!gXJZnrcqD@g4U(#0w)Q7u;nd5#w2JHt4fT?QKw>t75 zw)_o+5g#B@yYAuf{wIxl9QMnfAiWmbap)&Ql9JEumfhUmBv$K#y=DpsBNgvoc}+fN z!WLp|rCAC6XW9uMVumMB-eiTGH@lzICD`!(*)s#gIM&>zn_2Y8HEuoWsj7xcjK&hy z2*ZNg?P~T|P4A?l%r**XF6j;Ie%8Pp>=L;eOaPgf1LaYGF+C$3vyF|bQ?!Nc_9IQ~VkD`$ zPX2eDZ0nmP&gIp|wXsym65RTpp8Kb9zDBE-Ew5JbU1R)h*VDD?j}e{6ODi6HPR`WG zCvlJ6))OUZFh2NkSaOO%O6T=2LbiT#s^5`T?2GK>*KS-+Tl*HpVG_X*?%yB5_`uZ)!TTfyr&7B?f zm_Y zs?Ir-MV#L!@mkp4XlKW9UIO3Q64AKi;`MeQzq9|bh(R`P3FirWGQ-D*8x!}!l2xAE z^~P~ZVd;6TSlgc@q4aM2-ji6R(`0cOgKS88*IF5sbqhCdKi@yUN4;vDAbsS{w zWZCil*i}yA+we#~Wb6AiE~-5y^4q6TQ8Kf(*2^KJlka3{tW3M+LI}aE*svaKfBMLB zk-Y8bxJwL_MACyrnx<8mb&>C>PG@t~u^UMX0q@Iy#nj}cag>F*!~Nm$E&Kb_D)ltC z!S?48$1j|Jy(qdEM#3n=@%(Db7a{R!cGJA_tx+OxYzFt=mz4EutsMR_1;14D_RH@J2Sc52YMJLnZ1;gv?xj2Ah~2HZ?eoAT_lmvZ zF@H~QQ_m`C1RX^`giZ6odfnT=PFBozQ+b_vha=&gUi2{ z;)%jGdpc*mDWC%|bc=3F0!&iikr9nSizDkNs39o39yvr1<5J+rl;BWw2ADE{)TJ^b z&p?+21Zl{ACMJRxK>whI5JY23fIJPr_LoY<8K>4FUzH9Xffy|^p~LYf0D5+N71&8t zd>?s_z~k=q##^JAhr07CJ2#DGu8fL2jw(Ub;ei;1hea~AAUSN}6~Xk;-uyGrrc54%+2$zIy4gWQ4Qqm6jR^eNef>)enn>PWjDUZ#KLrG-Mq41YhOyV!X=3n+w5Rx&D0@8p=# z@nQP5=c5kKta@I+*L_$%Rn}1C^O_b$agQ%+m*4W=Oga*FqpToKZ{lmvef?oob>`1{ zq&TC@s|EgH`^1dz_#c@S@5@o}3Fp80K*t&x2Evm6kI=V#ZrNflB&JXpGo18iH&R}6iP?)mCtiS==jSH|%>ksd^2BUtk%E>1W&o`3YGP5Hmh%6-SAZTH=N z$tP6hz~7dZ``%y7|MtJyn`d|qCzbb;@BjaH_kU`%tuM2^+YIs3lZ)#g2z#^#)VIgR zE=B}#4hjTiiG9qTNtsgWH80&0cVamF!YZ~><9B~QuTao{Ua#-}X!kdN%6@+tpZcrm z>f(e7qah}JgP+TtUjg-Zu_@P8ERtVhJfrTBNc z+!*e?61-h*CIVr`G3|SF|GUFI+RG68ulo4kyW9V%*#D1x_5a<=@ncc%S})!+m(ymL zfyES70ok2tV+?y^GK4Hgf0|bfE;q{hQPX{{wKX?1X()O!T{F>Gx`Sc#b=5vm{EX{? z1GVwpe+?L9+-RTw%^%(CVAO8P1oc`Ze z(W`E-{=FJI_P$_+^Q^&&Jo3T?CRUWQW}YdNGgBskShvpn9Tj@ND1mX`30V~_-1e~< zU+uorN9>R};_6oOv{y0@?p-?)aSVaAmNn?|7v$HPkTr~|@3u_{93ZTWdU%$98NJuk zH-JZcl733iTMfaO6kwI*kMA7f`}lt~_TBMVe*gdHUflL=Mv*-;vq#)!5@jXQxQR%V zRfxE6o5)@n*;EpdjBqO%MP?G>7Rt!pBYqdv`~CTR9^XHH=a1`popWFJ8LxA$b6)2< zuh;X1ZZq@S;acGS!gI^6;QAN>L-&)-Xo1!lxY#~QiSO_@G_F(ip7nlmobdA*Pv!AV zjr5FH_wITZzHlZuX5b|a<|mD=-cF+_QD`8i@X*L|*a<$9XR*wSWk871(UznI%@%oT z()QZE7{oBX+^)Ob93?~>|7~S8tE$ZriKRSofyW-^+P4;CDbo;9 z$WdYv(${V~_iNDO)1|Q9Q$v)br1Ng1++Jd#MP;kwg_qHXERGF+9pyb?HFlI!esa4b z*80$wH=fsDZTYlF!UiL!66_7=bep+lzj%@S<>B$E53_X_Giew4{g-Z}7QNPWF!7-D z7|f(5YSZ(gVMUhP51Znd_5!^tS#CK3%C%bqY*iE#Gd2(Mxhj_IUhJ;W8dDA?o298_ zMcQ5S!^6wdr^lS#uR9MTmgA$h1TQexaAeyBbDr`er(jW0UpPJ6{+0_5=wAriH2}Dp z7`c0WUrSc$M07~?dI{11jd*%`J;I1jz4>Kf_{sGWL^*+39Q!VsnxV+;=+|D=pX)~p zx7QQ_%s|>pW0-qE!3nR43Tcx>c+3(xzpbWaqXl|Yeb|JImtPPMM!J*|;nz6xt9ssY6&8u}snUpF zF>&GaXB7_Xs_juMbbP1FT&kk(?PJ}wKy_H4Q`iw>*v=eOSXMS>ga<0R=Ptb-udUmu$V+WF?F%bt)J&-7%3dMja%BK^y*x{0c!gQ)tz_9bLZoI4F|X&Z<@?- zZWp>@{-21e+V-B+QJYd$xp5vj3Vk=mOu8ZIFX1`kJlHm0X|H9sk?9(np=uiasDB!R ze!9$9-PGY6h)h;1zb6ubR5N|9{njzbKO|bN!gGj>$Q|&^fH9eG6n)bmBwkX+_!JSr z(etfB%kS`RBnd;lv~bj^(cd6{GcwJ(Y6Wg&EU_2d`TwHQ`X))wRo($%By9xeF z6h_o+VUarLm^2r~XS4bTPJRkK$)(Ar4SFepZ)>9>DT=E=FO7xvlo)$eY>#4oUIJ)i zc}Y!%NP!4V{^wl~q1i zb>^`Q+zLq0SIMwZP$)fVK1Dye3)kCe2dAm?hG=wz_;Xz&xSC$CEgtS2mkNQ+4Mf-UFD*{Z05V(n*nyUJ`Qd5*!^*Cw6vq>TzmNM*EMoV-y& z_?OyIzSF8gv)q8*A&`J6ICg%mhsG&6G8+}P(-8~b zWrP_vc3)C#ct*fmFQ_#YEU{1< zRz{KpQ6Ji6un*m0ha9LQh%gc|Jh9wO+8ASpH(bW^id?zG;m|0i*3S@%rm39b3x^x)TCj*JPR*q^#}f$>Y9vhr4)f+pcC27VIU-+kJdJHKhi)3E zFag-1huLId>MRotbExEP@z7*s31ly(z5)=7a80C-qJEGGT1KXAM$qcFf*j>!v^#}oIRzR znot>pL*|rT^iyOw>f-vg=6!3e9LR2GIR;}5U>_vjQK?qyOIL_f)uYZym%a96HJc+_ zgZ)Z6lj1A9k~(qFy_gazfOrcEdMI66F94@bF2$2dCN zI8iA}l-t3V-6V?-9G)j>jG9*XgePM-ed)C|$e5_9Pd*Mj{QAM^Uq`e&&wsfHY`H=h zhtBYE8CIJ}X$@;x)38@eo*D~2LAsfArs{RQl<@nT1_+{)h(Asri?rc*QtG%#1Qcm~k=zz@L zj@IImA){Kb25xr&b{&1eH7c(1ennw3o$n-Tc!1?Q%k{5WK13XmY%y$e8hu)_Wp&-? z9)av@9YrMVT7hc%Ivm|*ZbJks#P1eq%t@`C*VC21&}va2@3%Olm&xexWwB$pDs9jYX~_-e+V7t{QhZ(mggU9GennME z(c;nvy9%T+O2cinql?Qnw7>6 zOI`r$9l7!AL6BUL`{^N^ry3px+qfTm;kIttCOs|EX3c>$xbBoIk;~cdVKDlz&aYdK zr0(S}3U37Y@aDdoF64Yy%oG8^?j$|c?~g$qCY4)XWvHge&4{~S&&Gk*c{1tI_qC^l zM)US;?Gg6F!u)wBugS(-@q1QG8}Uu8`UDY?a_+^IsjzLO>yknj-ZUzGYLpR|@0V-3 zWpQ>-%W2S@e&=Yzr{Q>9axIx;Y#mn-dI)OS3;r-OqAX0$LYRCq0^sg z;2!nP71VszPkRycXJ=nXb4wngMmF7v9EsKd~XiwRkKntSrDL3hq(!>zmMAYcH zkQAS9(+-ub%niW(yg0>nR;tQ`F#hO82v&%Z=3Z;+r^*xU&OYu&9~Zh56}nc!nLa3A zHbVHuQ5R-yzAt`Rz2kH7v9`ylhk`LDbZ(h^sFx`iupB7gAs=WYzqG~Q*HHCF zRICT@Es|_C98ylzw`qg(kjwKDVy>X3pOql^P-7g*In zmi^8{&-jVrWtL}yYedNkp@qx<5;B-sYQd&nBcbMUf zPmS~Uu`3Eto&t;XcONF0VqXxu$us3LUqxW_~r!ivhj?dD!3NtzzoacEj8-`F? zPsb>UvRbD>5Ku;z_lCMTT4CD8&vA_H(V*D;WR!Loxscxpi3?Ut3tWK8{YSq2t#HyI z2`%PaO0WCpE<-DZ!ZhpjjfHqqUlKq)+Y+4DQI785C08y1Y#Lv5ACUd(!2-lxvn=w` zzWiK0h0g|;eD4tflU-HaWacILr#}Hw^yhIq>Zj5IlzZ)|Pm$kB8(nzZs>N#8iruBg zDnx-$BKO%J^*ssS;U!Y4`nAe5X=GDs19wkGTx{zZIU`LsY*2=o;0%`UU;j$vD0DnE zy5>{0d`{}zPQGv57PY~!W0DXRe_dKtyNvReB!|S~_KdltwoETCNwV*q4vNYWHcgBR zFT(}M8+F_tE$@YjvA%2?Rb05ULRYj&W0inVdIz=+l znA*ZDNq8e^IxJ_<`BA2Qb(f7GBO%#VG(lv4FFvnzN^8XI z)$M^_!c58G`r08mTbjk@=~3Kf=X}HJgMV~I$0(_vLL+%J1jZkoP8WE0l*h;(t=V}v zlTYoo=1rg;)_sl7B@@mZ?>^Re2py`)m}}m!#KZ6F*e~zGtfRxEm8(%6wAs4I;GitR zBj!{2jIb6;!n_HM4>gMs%HZMA(z-Sk&*x)VR?efff6djWM!0lLm(8R>M;C!}7i%l8YjXpC9>zd-PPY6bDXdk-)it zI78=?-~yWS!YJjF5)O``y5wCzoeF4gD#==+ANywmBa;<QqMvnVd;j>R8Y8)Sj%z z5=7S2yZ}R>Wy_DJ!9O9?AtJyJ_X5cV8{ZZ%{VDo+L=XIiS33mZ*LEcyI%MP>t5TA*@4I!HR2hlhz&ECA&71pqEWhhm7ZD0mAs(Ajv8 zhg^UFKyN1rJ*oH<3&(-TqmaVn<^#MNo)Rc}?&sh-MuO2uGc3NZ}U881Eq zWB}5Id*wP2fsfCW!$x};z=0A8p(+QtqEZj^&x!-Edzp2TR2MG4z()v8@!r_gzWI+^(&@Kt}S}Yj!!wCq-!}D4Z3| zsoCcRN%kpiZ>9`Is;$KyBVXVNm(|W*8n2>Iecb0Wmay6H*Rj zrRZr{>>_*?*k=vIvq!W97o9P+br27@L6neRcPihJ^~HrH-i^DiY?6w?NcaS;M zCOC1Q5z>pF6nB^@lnvhW(p%z!#gpeDORW`Ut>#-~64Ko*gnL`SiYK@N@KQDd->*3jWrz zC*PzXW@iwIrN^^po1>k7ie#C*qkLp8@am++lYPD5{g_GTSt{GneH>sPR4jDm;y$n; z0TF*o%KY5}UkD%v#85#!fQI0HWvrf#6hK8Kv+frKi%4v86p*fH@$5ve<<{oJ(l8Ja z>%th{2Npqsm&@I#yiHvZyw~q|w+Az5$zn_`Q z0g_t({{m9zzn{~<|9AXP%p6)Ue;;1`pFjU+qM-eM#{N$lVfv?2VWI!$@Bfns75*QA z4)-6Cza%UEFZJ)8T!;GK$UoEx{6FNs1k(9m8X9-DZ;1aHKcEBuCk1gZ_54@j{`*$` zx3^mk2<$Wgd;n61px)*JtTYjgduvZTdOxz6rJ9HWBmk@^L7551{P#Rtbw@;|>3?|) zMXpR}8XJ%L_!%s2+GD-hmzkOv7$ba@OqAZN@}Yn5Pw_@psnJi(-#Z(Tw9TpFaV{^G zT6#XeiId@3xlsEh^~EzXpI;ZGUsXO9gg$Y(py~APmHIU&1&_L7&D)erLflm}?_n3$ zeq?=CGYh%65{H60+cpz#y-4nz6e-P@ZP^?-Pgdz1v&Is`ykuiD5y<#%RrMQ-8BA2{lvx7%&u zLq5wq_F2b1Mtpn3)+NKHZucak*yA{|{Y$P}u%FL;s}q{KD$cH=TkD<^^(eDb^Jy1} zw}b?}?WW!sM(C8-HwE%a-)(xlhgzMBQ$OiBeD2B$?$@o>Z9mW9tXFdsHq}hdI)SgBDJJVCBhop2ovoh*9+ecsJe#&s4HM z|9LwD#tndsR=}TgHndZ9vWJiJj9cHE;n!pW2we|A(crG70CWG3@pwlU_*`hlLA?S) z{^=DM>j82476Ar12I2z}m|P~0uBS%4Z3`AVqVW=p$;bG{B?Ie@qs|T9pWkj>`Ql5T zHQX)hJW4%s>^hAd@kj0oeCfo7#NKwG-`lqDGkcNMIeVMMvXsrf$mN8ia?#Oss!+f_ zZM8@dTUd-w4cD40cJ$>-yt@k%iaE(EWH9XPv35^$aczXlR9;AeIse&cr3_JpM>hrn zQ-U!BYOh3M1X}#wq`BvbVO*7MN z3Lbr3+N+8cZ@3_+;vMlm{#@jPiK!GGttd_GPPJ~VNqM!BR6%U)lEpPW0C+xlLrR$D zW;8lS-ijvk41ibL4e?=T$E4>jcVf<+>d+mX=Z1jTjID}Y?ymtd@YFrk+e?ynR&sIX z>Ru!?%nOe%zypo7lhJl|xDU!X9aB$p)nZ;7xwnL7u@pXMpqcUzV{_@f-7lWdcK@L%_nI}M_c=~ zr^bDho8GTx0j2We6MX?+nw3-Sn>tWVx|C)b~~(F#=#o# zIDv3!FdIoH&vPi8pLuXG|6Ydn4BJ(uh8DFf8)1dx6t+Iw27)8>fT_O(!0s+az7&EK zVcn*QCTriYmMBbljb-XPs+mCaNp*2q06(knutxd$yOkBj$!OEZhI-v1$w2v<%auaJ zYxfn>cKUVCnmRY0 z@@3{%x$8$@=r6URfjtj{h%oQ>-8U%Rj;&Qhq9zHkju8#H%$g%>aOAQK?oJ<#0bQ;+ zFUuzD`dj&O*^e}zl8$d91Io4egm|yfPrRp>P!SHiTBZG6x$`FM#}2GtQg8Hi502b| zK&+d&kh)y9(k(Ex2NP}zs_%_$mkI7SVF~r_9uz4z#7g)2RgftGPq%_0X%9My^^5SE z-}nZr9Bs(oi()_8d_H8}80RLNpP#$)>?|OEdbm}kLzGR2X^beZpdLj}1RPvfs*Va- z#IfGaW@IYPy$hFzp+toiQ`efvINvy8X88)}j2j~}v!e|kE}uce^iFW;MoI=#UQKIn zAc{=#HRC8VA|u|tVx`^fN7jBf&I{ynckoU6@e?d=ow}cb7-9~N;PgiWRHJn}BX3<= zegQz)a6Iup*DA)yV^M?(Wm0+H+eM|5Vwx-gC_4cqiE$B6{)_v`y0;vv7z?vb(Xg_5 z4Gyze4GHW~j6dSOM4sSUS}l2ewJ30weZZ>nGN!9Dwkt9Bh*b$Zx>=~vz}961n#T~> zVx_iSZ@cFwe{s)EU{Tb$+_T0QSWzbbUYJUa{4HOLrFI^C=r0UF^c|_iysUu9bWXnq z0&`$~X!C`B_|MlDggt>JsmkHx8c)-+uJ3E95fG3AIL>lY8Rf=>p?S}y6I?Qw3E=L8 zmY}0)v5i@?&yQ#U6fY%17P&8em^|}>&|2`&P`Ow~IqaLHb;~XHz7z0BH;W-W(&ecu zLTy&V{}a#%C4L{E7{~V`eS?~~O$3e1pt^t2nkF-2#jz>sNxoMJz_BND6QkZTbpj?z zEOHH%@}PuL_ooPnWT}R5K8kv<*!fM# z9b^f^6K*D@P!J=#FD6c8rErtrXQNAVb%C+K=0xbBsw5U`!w;yvt5UViK?9WU>F<5K zW1MlVb6Y@nijkP}aD-irnY;+kHcf6r4G`te^!r{XMM{b(i&6|D$WSqf-7`mPa#nEeI0)*7)NHPh)GOGYh7K&C3s#JDXhq z9+{wml!N~wgz>4X;`$A7=0pG!PzWnrxF7^~@{zdNK+1nj=VHx2j=CdCmr+Ldskg?l zQR8%~Gvl&BCdgCaxmUen$H&tW2SKfTI!;IaA;bxzBTTwcV9)1MB=<2#5~&iwVk#Ie zfY*q5SX{kva)cmLe5CtR)-(T}F*RAI>JZlY=x3)E^f#kLZV~W8Zh;wxCK-^1fF3Sc zp$LN0)S0;e!c2N~Wv>6wcdXr$rYwD`rt>iMr zWfrP9xf|^^N0{nr3xC#%>%u=W*V5Y3Oz5K@+s-7c`GULSM0j1Ni%UO3Bgmb#3M+-R zXBT^pR`S|ysIHWXq!1HTVqe?k0usG6 z(j>sBh4IENoV_FN-aC3)V2IFzyC;BnF!d?@Zjk$uxnkW3h3FGy?~N_JhS8rxm$!Xu zoxHmFKM#0MSgfXL=Cc`5IO_}`KT_QinX)jC5L>O%Ef1c4k=oC1V6FDqBF^8g65Od1 z@Fc5${d}DVd)^~Zru6F9)k3*f7L*0#j;5($R6o1SO<)=t6Oq>v8n?AtG&j)Bj?<3(@(azPVySxa9v7pKzVIh zZ`Rt<6f+-{cWTEvkhU`buHJO3J z(PQloQZMI1r&+*6J*uxGozJ5e+GKEs5Nfxs}&H5OdaX%w- zYXH}OWH#ormGK(OPK?6>aGa8#^2*`kXSlxA*1H^wd0$Xt1W?rqf<&4{ETFsAb0JEc zB48B2R%SdED9k977rMXU$)Z|)tje$?P0=C%6Ep6M-15BcWIsJ=DF;M<1epeA-?U#k z91RF#6gIgVZJA@20q^jaVSie?wU=VA1^qtpLkj)meUjhp5u9|tZ~*D#_QNfAsNxy* zOCja*Zy&K`-z<8hH7t3M9A!r7#+N^P4l{L=lM^9tbiAAoJIvY#xL4J;(uHp7x0%{J z;BbqX*&)xK`t-yzyjSX$_J;gd&ISsZS>aRSJ>_HCwC7XbN&C1!f$=g27j6}hK=bpq1`AB9FW>h?)y90pLI4!6< z_hoR=zcM)XfWTG|V49$d2J#+D{B5Bb%KDFmCadtrM7?Vws;`4+zSA<EJDEo) zF_1+yW5-$l!UyazwN4f2a28150FZTLUjgL(0OpJb$Spku04P)S$u9u_qcov_#*hN! zp&aP~%?h9>GmDXkFvdgw+1uYv?>EKtZ&U1lHzkPxyRq-99EEwk-xPE4HLm~gmd|Aha5lk z!jTjeAbsu#fExg~5@qH=U48!6HTr<)C&1$Nzw=Q3=DN8=`@iPbJBGS-m(qo4KZ?;& zNh_UGsW_#R{_1(r)^J_pPuDJC$5p9)2)s_8V+rH83tTobw%-w&OSfwwUj)S8e98S= zR^@NL#1ddNK#B%3CMW^yC!G;*n{7p4(3SvjK_-Jgey!iVS1y;3yCFN1^ge2}Ae+mEV^?CiZWfAU2@MG})D(mcm>PFl7a zA*{Zrz1Ok5#|6`M5eHU1RM6D#LZ*QMy;uNxaDWwZ9YREt04HQx26bQC-)fS6SCc@1 zje#yI2-?2}cnwvLj*-vPNap+Gmmbut*51YH;UQIk7RXlV1io97 zWP@x0(C!K-5F(-Leyvvi)C!J1Ak>2ia4OKn1lTdTkg>OOw&hM{gcSNrQPS@2?p}R; zKTQtd?Q+;7^0G#Y(%7g?%-2S#RGY9<(NEb!)O?Gcov_hqbuWsvzwTY@3)4%}3b{Lb z&cyn(wqw!dR#a(Ci8;;P#+bZnt`rK3<2TV$%vZm?YtSmN_^A;%oHzEYJvO1Tc0I{o71k;L8dtf~+=}ADdo*9u%$wic63=i1rd) zQ6@lg0boaj&@?+1r{hWN&H!oAPmPfxq7CUg5zWYB)U!`W&|Y?v91q~rkR41kprOJ; z>J%^`^;kf!15W^T{Q!B!?izgg&5so%{qb-;0KconOxo`nIQ!qOkvt$~32^Cs6dW`( ztoL7c3Dp*8yzB?$@}o@?I!RX3@zlH>Kj#9X#gkjR_=}v)+k1~T;CS}-cZ7PPEP_LN zb|1ZgbAC5-iafKaXUkjZ~piL;vE4Vunz(HPyQW~|Gp4s?@h~)L`ObDFrR~~6UW={ z+5LvGT3&U_^yaKtJn3XtS2p8%FsR}2e={yTAan=>IOK1M4RB)cOdid+aTtFIe&L;B zK3Ngfk1ZyYUY_w|(Z>xa9)}6+o|6p?9Hj|7rdUW6~ph?Rd1%v0a`|Cu2&GP z@}Cga$iyBm+JrGY+trWZckd12MII_l^V{X!tM&Uv1jqcjO#rF|+KaM{bC&=qJfKKm z2MnkUltx6zd!0x~Tm!zxt#G;+`ZIu{+#F}EqutMeMJgk^fe0hkd0{TPlu92@X%5W! zV?AF?QBHbSvd)PT0mbPZJk+mf5d$=f#UmVP{xdf zRKcgM>vM0xxZsIcvdJ7u2l#`lx`+Uy4>RikeET^wbZ4Qw7Y~*ptYUdeN?2~wP3)oT z3&Ne27&5;(NAXNr5!Fu98EZN92Ry2H7_y55fQaIKVPg%1RW#tn@;Kd%h(?)DViy^2 zDr7~xGUYPWbLIn=u!=>T(I8d>iHFU4K%f125!h}B)5cmj*|)G1lEHj(#Jw=&MraE-wmF(k zVW@2fLi8TfF`s1WLWJoziCD=imlJCm`LemL5%dhV=5`%FNue&{36 zUC}Q4Tnspd$r1rswT5yfQn&g+O4#9Azm6@%&uci!${&oKNVi{4zAy&(uxGlf6Y%uTW-UbjKnzD{D1Nanv4_xo- z6S5W4T>wC9DHOhv&r)&q3C)|S@`1eo1P&TBo0rRy=c2lY0A*fFrqK%=YC)=1)%DCh z{MqPS@CMk3mAGtg88XG@?tvOHDJxfdCfFu)m^<#b0zjMw#YDL z30g@2HcD0N1mGt>m+3LDLd*OcfOr9oCQIcTp#XNA4W0GD^?;OELtf@nWs*=@-K|=I*Ll6yXwX_|KHdnI9M-v)g2u7$TiJw5I-Em0tf{l{ycIW&#{SkRk^Zn9Sen zc_r)L<*o|$?c&*5R{f=ddtxKMrMtoIuLr(1{(uv0CBC~^O4ax44*p;z9sis4#sPu7 zPk?WO7-}f*2yir>3&OycPH)8SR|LTQ-fxXIkoD41vH9Py9zNo#C8bz!W|A_Hrn(c2 zp+YV0LNfARKZQ=+o*~2QA`Z(xkWagY&nx}NM7wa*eo1Ph?A!Kqs%~`adusi3*+89P zs}s$nsZYGk2Uw4T2n-EB+?@1|Ac%(wghUwx^`H77xDJQ`0)lrRK93x#-hn7nX8*4w zaaKS^e6@v6OXqp_Z7*>7xA>4~eO}IAzKlLHKHTv%Wztce3xj7waq7yPakb^8?Vj2) zEIeQk>ydd-n#|wQbPtGT0^;;OqyORG6_G+{(=5>i&sNcS{>DsBJ37MC)gIcQ8^(C!nEDU!gMNdTlx$u{5~Py)hG62k2#f^r-bfi>fiJAkbO+;xUx z``uaex4y&!LLE*(Kwe&G0UPA8`KUCBiWwSi@9m+7Ax?zjO*xWw;&lK4@t8c)={U?A0F@JQ~~mH5&iT(d3t+stS3auJiA`cbb(>$Huz zAjALTQs5yol+oUYnHrCj8Bc+&UEe2{>k3fPJ47JwNIVIBV}3yg4rSvVJpuYPt=W-J zh5$hgU_97E&sYJ>Rg#$%P^}RKb|4uEhcd*26L?+4G=OX(frMjFBT)cmA*phl380(+ zNN6Ea1Ol>fE_XviCupgcgboFZNbZuoqR~hoh$aG|a)h%r)(96?0^qS4iND#>`G>BCIEJ$s^Ji3O#ts)R zsaUWQh>z)N3_j1LxW0biZrL7itFY!qv28T$R(SQV9`WMxt$wRsF67C>>Xp09eQvVwmcJZ{($B4h-qRYj<c8WEW1<+uROa6Z z1ov_W=3KwieqRwA|Hl41%l*N#^M^}F%x^AH5|EIm9X4pLg1oiEuGcJZo(mDB zne#&F0yrKTKu35w9uBH@ zB`m{Pl>*4iId8aaaEg7E7#rLC>06yucTpE3$;G{kFrGZ;R($(o)o`uHSB)T~n*97o z&GXbI=NARt@@kq_2F34@jx2)_p3{~$oSdG$tf;(Z1RdQQW?{Vxg*8?1gXs-*I%bzk zjVCv@ldy4p+(-S!2U)|8F>F#1AN7r{p09Dr_OwrDj0eaxETCO525`D9Kr2xKf5VPD z{FLN^Jxhe8z!_!GlSp0<-(KI%htajt=G{*nIj%cz2Zf;`TvZqq%Df{5TR;ukuq zkH(x`qWT43;lSRB%a(Y^@G4f3hzf&{gMPPAf4^aw&@8zh=(0lmkvIUQ+|CYQaHe55 ysk!mzCz+b4G6HxNzD|HG`XeM42#Eaz!#@d{?-mHuHPL1MbV7epI+Yg)H2)84e}pao literal 0 HcmV?d00001 diff --git a/server/tests/cli/create-import-video-file-job.ts b/server/tests/cli/create-import-video-file-job.ts new file mode 100644 index 000000000..d486db600 --- /dev/null +++ b/server/tests/cli/create-import-video-file-job.ts @@ -0,0 +1,111 @@ +/* tslint:disable:no-unused-expression */ + +import 'mocha' +import * as chai from 'chai' +import { VideoDetails, VideoFile } from '../../../shared/models/videos' +const expect = chai.expect + +import { + execCLI, + flushTests, + getEnvCli, + getVideosList, + killallServers, + parseTorrentVideo, + runServer, + ServerInfo, + setAccessTokensToServers, + uploadVideo, + wait, + getVideo, flushAndRunMultipleServers, doubleFollow +} from '../utils' + +function assertVideoProperties (video: VideoFile, resolution: number, extname: string) { + expect(video).to.have.nested.property('resolution.id', resolution) + expect(video).to.have.property('magnetUri').that.includes(`.${extname}`) + expect(video).to.have.property('torrentUrl').that.includes(`-${resolution}.torrent`) + expect(video).to.have.property('fileUrl').that.includes(`.${extname}`) + expect(video).to.have.property('size').that.is.above(0) +} + +describe('Test create import video jobs', function () { + this.timeout(60000) + + let servers: ServerInfo[] = [] + let video1UUID: string + let video2UUID: string + + before(async function () { + this.timeout(90000) + await flushTests() + + // Run server 2 to have transcoding enabled + servers = await flushAndRunMultipleServers(2) + await setAccessTokensToServers(servers) + + await doubleFollow(servers[0], servers[1]) + + // Upload two videos for our needs + const res1 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video1' }) + video1UUID = res1.body.video.uuid + const res2 = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video2' }) + video2UUID = res2.body.video.uuid + + await wait(40000) + }) + + it('Should run a import job on video 1 with a lower resolution', async function () { + const env = getEnvCli(servers[0]) + await execCLI(`${env} npm run create-import-video-file-job -- -v ${video1UUID} -i server/tests/api/fixtures/video_short-480.webm`) + + await wait(30000) + + for (const server of servers) { + const { data: videos } = (await getVideosList(server.url)).body + expect(videos).to.have.lengthOf(2) + + let infoHashes: { [ id: number ]: string } = {} + + const video = videos.find(({ uuid }) => uuid === video1UUID) + const videoDetail: VideoDetails = (await getVideo(server.url, video.uuid)).body + + expect(videoDetail.files).to.have.lengthOf(2) + const [originalVideo, transcodedVideo] = videoDetail.files + assertVideoProperties(originalVideo, 720, 'webm') + assertVideoProperties(transcodedVideo, 480, 'webm') + } + }) + + it('Should run a import job on video 2 with the same resolution', async function () { + const env = getEnvCli(servers[1]) + await execCLI(`${env} npm run create-import-video-file-job -- -v ${video2UUID} -i server/tests/api/fixtures/video_short.ogv`) + + await wait(30000) + + for (const server of servers.reverse()) { + const { data: videos } = (await getVideosList(server.url)).body + expect(videos).to.have.lengthOf(2) + + let infoHashes: { [ id: number ]: string } + + const video = videos.find(({ uuid }) => uuid === video2UUID) + const videoDetail: VideoDetails = (await getVideo(server.url, video.uuid)).body + + expect(videoDetail.files).to.have.lengthOf(4) + const [originalVideo, transcodedVideo420, transcodedVideo320, transcodedVideo240] = videoDetail.files + assertVideoProperties(originalVideo, 720, 'ogv') + assertVideoProperties(transcodedVideo420, 480, 'mp4') + assertVideoProperties(transcodedVideo320, 360, 'mp4') + assertVideoProperties(transcodedVideo240, 240, 'mp4') + } + }) + + after(async function () { + killallServers(servers) + + // Keep the logs if the test failed + if (this['ok']) { + await flushTests() + } + }) +}) diff --git a/server/tests/cli/index.ts b/server/tests/cli/index.ts index f0317aac0..f99eafe03 100644 --- a/server/tests/cli/index.ts +++ b/server/tests/cli/index.ts @@ -1,4 +1,5 @@ // Order of the tests we want to execute import './create-transcoding-job' +import './create-import-video-file-job' import './reset-password' import './update-host' diff --git a/shared/models/server/job.model.ts b/shared/models/server/job.model.ts index 0fa36820e..7d8d39a19 100644 --- a/shared/models/server/job.model.ts +++ b/shared/models/server/job.model.ts @@ -4,6 +4,7 @@ export type JobType = 'activitypub-http-unicast' | 'activitypub-http-broadcast' | 'activitypub-http-fetcher' | 'activitypub-follow' | + 'video-file-import' | 'video-file' | 'email' -- 2.41.0