From e6cd2ab44128c90bb6580a0b77a90d886ac42bc8 Mon Sep 17 00:00:00 2001 From: Daniel Gak Anagrov Date: Tue, 15 Jul 2025 10:56:09 +0200 Subject: [PATCH] feat(preview-service): re introduce preview service acceptance test (#5049) * feat: basic structure for running tests * feat: added test to ci * feat: added server test (wip) * refactor: restuctured entrypoint * feat: added supertest * fix: missing deps * fix: test example ci * fix: updated default envs * feat: debug ci * feat: switch browser * fix: superadmin ci * feat: try another image * fix: try another image with node * fix: mr comments * fix: ci job * chore: workaround to push the image * chore: try with new base image * chore: retry * chore: retry * chore: retry * chore: retry * chore: retry * fix: test via debug * fix: envbar * chore: wrapped up changes, cleaned mr * chore: fix linter and skiped puppeteer download * fix: removed paralelism * fix: paralelism issues --- .github/workflows/tests.yml | 27 ++- packages/preview-service/.env.example | 2 +- packages/preview-service/.env.test-example | 11 + packages/preview-service/.gitignore | 4 +- packages/preview-service/package.json | 10 +- packages/preview-service/src/bootstrap.ts | 2 - packages/preview-service/src/config.ts | 6 + packages/preview-service/src/main.ts | 227 +---------------- packages/preview-service/src/server.ts | 229 ++++++++++++++++++ packages/preview-service/tests/main.spec.ts | 141 +++++++++++ .../preview-service/tests/snapshots/base.png | Bin 0 -> 88362 bytes packages/preview-service/vitest.config.ts | 20 ++ utils/ubuntu-chromium/Dockerfile | 30 +++ yarn.lock | 109 ++++++++- 14 files changed, 585 insertions(+), 233 deletions(-) create mode 100644 packages/preview-service/.env.test-example create mode 100644 packages/preview-service/src/server.ts create mode 100644 packages/preview-service/tests/main.spec.ts create mode 100644 packages/preview-service/tests/snapshots/base.png create mode 100644 packages/preview-service/vitest.config.ts create mode 100644 utils/ubuntu-chromium/Dockerfile diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d1e50b61a..c997481bc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -198,7 +198,20 @@ jobs: test-preview-service: name: Preview service runs-on: blacksmith - if: false # disabled as there is nothing to run + container: + image: ghcr.io/specklesystems/speckle-ubuntu-chromium:latest + services: + redis: + image: redis:7.2.4 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 6379:6379 + env: + REDIS_URL: redis://redis:6379 steps: - uses: actions/checkout@v4.2.2 - uses: useblacksmith/setup-node@v5 @@ -206,9 +219,19 @@ jobs: node-version: 22 cache: yarn - name: Install dependencies - run: YARN_ENABLE_HARDENED_MODE=0 PUPPETEER_SKIP_DOWNLOAD=true PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 yarn --immutable + run: YARN_ENABLE_HARDENED_MODE=0 PUPPETEER_SKIP_DOWNLOAD=true PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=0 yarn --immutable - name: Build public packages run: yarn build:public + - run: dbus-daemon --system &> /dev/null + - run: cp .env.test-example .env.test + working-directory: 'packages/preview-service' + - run: yarn build:frontend + working-directory: 'packages/preview-service' + - run: yarn link:frontend + working-directory: 'packages/preview-service' + - name: Run tests + run: yarn test:ci + working-directory: 'packages/preview-service' docker-build-postgres-container: runs-on: blacksmith diff --git a/packages/preview-service/.env.example b/packages/preview-service/.env.example index 503cd0a6e..9787b9425 100644 --- a/packages/preview-service/.env.example +++ b/packages/preview-service/.env.example @@ -11,4 +11,4 @@ LOG_PRETTY='true' # Local dev settings ########################################################## # Uncomment to enable pino-pretty log formatting in debug mode (disabled cause of node22 issues) -# ALLOW_PRETTY_DEBUGGER=true \ No newline at end of file +# ALLOW_PRETTY_DEBUGGER=true diff --git a/packages/preview-service/.env.test-example b/packages/preview-service/.env.test-example new file mode 100644 index 000000000..1c0e8497d --- /dev/null +++ b/packages/preview-service/.env.test-example @@ -0,0 +1,11 @@ +PREVIEWS_HEADED='true' +CHROMIUM_EXECUTABLE_PATH='/usr/bin/chromium' +USER_DATA_DIR='/tmp/puppeteer' +REDIS_URL='redis://localhost:6379' +PORT='3099' +PROMETHEUS_METRICS_PORT='' +PREVIEWS_HEADED='false' + +########################################################## +# Test settings +########################################################## diff --git a/packages/preview-service/.gitignore b/packages/preview-service/.gitignore index d70ebaa1d..c43878203 100644 --- a/packages/preview-service/.gitignore +++ b/packages/preview-service/.gitignore @@ -1 +1,3 @@ -public \ No newline at end of file +public +tests/snapshots/diff.png +tests/snapshots/result.png diff --git a/packages/preview-service/package.json b/packages/preview-service/package.json index 9e41d4b06..f384ed61f 100644 --- a/packages/preview-service/package.json +++ b/packages/preview-service/package.json @@ -19,7 +19,8 @@ "link:frontend": "yarn build:frontend && rimraf ./public && ln -s ../preview-frontend/dist ./public", "dev": "tsx --env-file=.env --watch src/main.ts", "publishTask": "tsx --env-file=.env scripts/publishTask.ts", - "test": "echo 'no tests configured'", + "test": "NODE_ENV=test vitest run --sequence.shuffle", + "test:ci": "NODE_ENV=test LOG_LEVEL=silent LOG_PRETTY=true vitest run --sequence.shuffle", "lint": "yarn lint:tsc && yarn lint:eslint", "lint:ci": "yarn lint:tsc", "lint:tsc": "tsc --noEmit", @@ -46,14 +47,19 @@ "@swc/core": "^1.9.3", "@types/express": "^4.17.13", "@types/node": "^18.19.38", + "@types/pngjs": "^6.0.5", "eslint": "^9.4.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-vitest": "^0.5.4", + "pixelmatch": "^7.1.0", + "pngjs": "^7.0.0", "prettier": "^2.5.1", "rimraf": "^6.0.1", + "supertest": "^7.1.3", "ts-node": "^10.9.2", "tsx": "^4.19.2", "typescript": "^4.6.4", - "typescript-eslint": "^7.12.0" + "typescript-eslint": "^7.12.0", + "vitest": "^1.6.0" } } diff --git a/packages/preview-service/src/bootstrap.ts b/packages/preview-service/src/bootstrap.ts index deda5b6ba..60db1445f 100644 --- a/packages/preview-service/src/bootstrap.ts +++ b/packages/preview-service/src/bootstrap.ts @@ -2,8 +2,6 @@ import generateAliasesResolver from 'esm-module-alias' import path from 'node:path' import fs from 'node:fs' import { fileURLToPath } from 'url' -import dotenv from 'dotenv' -dotenv.config() /** * Singleton module for src root and package root directory resolution diff --git a/packages/preview-service/src/config.ts b/packages/preview-service/src/config.ts index 5f2b04e4c..ab9cdf92f 100644 --- a/packages/preview-service/src/config.ts +++ b/packages/preview-service/src/config.ts @@ -1,3 +1,9 @@ +import dotenv from 'dotenv' + +export const isTestEnvironment = () => process.env['NODE_ENV'] === 'test' + +dotenv.config(isTestEnvironment() ? { path: '.env.test' } : {}) + import { z } from 'zod' import { parseEnv } from 'znv' diff --git a/packages/preview-service/src/main.ts b/packages/preview-service/src/main.ts index c8490497e..0f2bee50e 100644 --- a/packages/preview-service/src/main.ts +++ b/packages/preview-service/src/main.ts @@ -1,232 +1,15 @@ import express from 'express' -import puppeteer, { Browser } from 'puppeteer' -import { createTerminus } from '@godaddy/terminus' -import type { Logger } from 'pino' -import type Bull from 'bull' - -import { JobPayload, PreviewResultPayload } from '@speckle/shared/workers/previews' -import { AppState } from '@speckle/shared/workers' -import { - REDIS_URL, - HOST, - PORT, - CHROMIUM_EXECUTABLE_PATH, - PREVIEWS_HEADED, - USER_DATA_DIR, - PREVIEW_TIMEOUT, - GPU_ENABLED -} from '@/config.js' -import { logger } from '@/logging.js' -import { jobProcessor } from '@/jobProcessor.js' +import { isTestEnvironment } from '@/config.js' import { initMetrics, initPrometheusRegistry } from '@/metrics.js' -import { ensureError } from '@speckle/shared' -import { initializeQueue } from '@speckle/shared/queue' -import { isRedisReady } from '@speckle/shared/redis' +import { buildServer, initServer } from './server' const app = express() -const host = HOST -const port = PORT - -const JobQueueName = 'preview-service-jobs' - -let appState: AppState = AppState.STARTING // serve the preview-frontend app.use(express.static('public')) -await initMetrics({ app, registry: initPrometheusRegistry() }) -let jobQueue: Bull.Queue | undefined = undefined -// store this callback, so on shutdown we can error the job -let currentJob: { logger: Logger; done: Bull.DoneCallback } | undefined = undefined +if (!isTestEnvironment()) await initMetrics({ app, registry: initPrometheusRegistry() }) -// browser is a global variable, so we can handle the shutdown of the browser -// in the beforeShutdown function. We need to stop processing jobs before we -// can close the browser -let browser: Browser | undefined = undefined +const server = buildServer({ app }) -const server = app.listen(port, host, async () => { - logger.info({ port }, '📡 Started Preview Service server, listening on {port}') - appState = AppState.RUNNING - - const gpuArgs = ['--use-gl=angle', '--use-angle=gl-egl'] - - const launchBrowser = async (): Promise => { - const launchArguments = [ - '--no-sandbox', - '--disable-setuid-sandbox', - '--disable-dev-shm-usage', - '--disable-session-crashed-bubble', - ...(GPU_ENABLED ? gpuArgs : []) - ] - logger.debug( - `Starting browser, located at "${CHROMIUM_EXECUTABLE_PATH}", with the following arguments: ${JSON.stringify( - launchArguments - )}` - ) - return await puppeteer.launch({ - headless: !PREVIEWS_HEADED, - executablePath: CHROMIUM_EXECUTABLE_PATH, - userDataDir: USER_DATA_DIR, - // slowMo: 3000, // Use for debugging during development - // we trust the web content that is running, so can disable the sandbox - // disabling the sandbox allows us to run the docker image without linux kernel privileges - args: launchArguments, - protocolTimeout: PREVIEW_TIMEOUT, - // handle closing of the browser by the preview-service, not puppeteer - // this is important for the preview-service to be able to shut down gracefully, - // otherwise we end up in race condition where puppeteer closes before preview-service - handleSIGHUP: false, - handleSIGINT: false, - handleSIGTERM: false - }) - } - - try { - jobQueue = await initializeQueue({ - queueName: JobQueueName, - redisUrl: REDIS_URL - }) - } catch (e) { - const err = ensureError(e, 'Unknown error creating job queue') - logger.error({ err }, 'Error creating job queue') - - // the callback to server.listen has failed, so we need to exit the process and not just return - await beforeShutdown() // handle the shutdown gracefully - await onShutdown() - process.exit(1) - } - - logger.debug(`Starting processing of "${JobQueueName}" message queue`) - - // nothing after this line is getting called, this blocks - await jobQueue.process(async (payload, done) => { - let encounteredError = false - let jobLogger = logger.child({ - payloadId: payload.id, - jobPriorAttemptsMade: payload.attemptsMade - }) - - if (browser) { - const message = 'Tried to start job but Browser is already open.' - done(new Error(message)) - throw new Error(message) - } - - try { - currentJob = { done, logger: jobLogger } - const job = payload.data - jobLogger = jobLogger.child({ - jobId: job.jobId, - serverUrl: job.url - }) - const resultsQueue = await initializeQueue({ - queueName: job.responseQueue, - redisUrl: REDIS_URL - }) - - browser = await launchBrowser() - const result = await jobProcessor({ - logger: jobLogger, - browser, - job, - port: PORT, - timeout: PREVIEW_TIMEOUT, - getAppState: () => appState - }) - - // with removeOnComplete, the job response potentially containing a large images, - // is cleared from the response queue - await resultsQueue.add(result, { removeOnComplete: true }) - } catch (err) { - if (appState === AppState.SHUTTINGDOWN) { - // likely that the job was cancelled due to the service shutting down - jobLogger.warn({ err }, 'Processing job {jobId} failed') - } else { - jobLogger.error({ err }, 'Processing job {jobId} failed') - } - if (err instanceof Error) { - encounteredError = true - done(err) - } else { - throw err - } - } finally { - if (browser) await browser.close() - browser = undefined - if (!encounteredError) done() - currentJob = undefined - } - }) -}) - -const beforeShutdown = async () => { - logger.info('🛑 Beginning shut down, pausing all jobs') - appState = AppState.SHUTTINGDOWN - // stop accepting new jobs and kill any running jobs - if (jobQueue) { - await jobQueue.pause( - true, // just pausing this local worker of the queue - true // do not wait for active jobs to finish - ) - } - - if (currentJob) { - currentJob.logger.warn('Cancelling job due to preview-service shutdown') - currentJob.done(new Error('Job cancelled due to preview-service shutdown')) - } - if (browser) { - // preview-service is responsible for closing the browser - // to allow us to stop listening for new jobs and properly respond to any - // current job before we kill the browser - logger.info('Closing browser') - await browser.close() - browser = undefined - } - // no need to close the job queue and redis client, when the process exits they will be closed automatically -} - -const onShutdown = async () => { - logger.info('👋 Completed shut down, now exiting') -} - -createTerminus(server, { - healthChecks: { - '/liveness': () => Promise.resolve('ok'), - '/readiness': async (args: { state: { isShuttingDown: boolean } }) => { - const { isShuttingDown } = args.state - if (isShuttingDown) { - return Promise.reject(new Error('Preview service is shutting down')) - } - - if (!jobQueue) { - return Promise.reject(new Error('Job queue is not initialized')) - } - - try { - await isRedisReady(jobQueue.client) - } catch (e) { - return Promise.reject( - ensureError(e, 'Unknown error when checking Redis client') - ) - } - const isReady = await jobQueue.isReady() - if (!isReady) - return Promise.reject( - new Error( - 'Preview service is not ready. Redis or Bull is not either reachable or ready.' - ) - ) - - return Promise.resolve('ok') - } - }, - beforeShutdown, - onShutdown, - logger: (msg, err) => { - if (err) { - logger.error({ err }, msg) - return - } - logger.info(msg) - } -}) +initServer(server) diff --git a/packages/preview-service/src/server.ts b/packages/preview-service/src/server.ts new file mode 100644 index 000000000..c1470dcd4 --- /dev/null +++ b/packages/preview-service/src/server.ts @@ -0,0 +1,229 @@ +import puppeteer, { Browser } from 'puppeteer' +import { JobPayload, PreviewResultPayload } from '@speckle/shared/workers/previews' +import { AppState } from '@speckle/shared/workers' +import type Bull from 'bull' +import { + REDIS_URL, + HOST, + PORT, + CHROMIUM_EXECUTABLE_PATH, + PREVIEWS_HEADED, + USER_DATA_DIR, + PREVIEW_TIMEOUT, + GPU_ENABLED +} from '@/config.js' + +import { jobProcessor } from '@/jobProcessor.js' +import { initializeQueue } from '@speckle/shared/queue' +import { Express } from 'express' +import { logger } from '@/logging.js' +import { Logger } from 'pino' +const JobQueueName = 'preview-service-jobs' +import { ensureError } from '@speckle/shared' +import { createTerminus } from '@godaddy/terminus' +import { isRedisReady } from '@speckle/shared/redis' +import { Server } from 'http' + +let appState: AppState = AppState.STARTING + +let jobQueue: Bull.Queue | undefined = undefined + +// store this callback, so on shutdown we can error the job +let currentJob: { logger: Logger; done: Bull.DoneCallback } | undefined = undefined + +// browser is a global variable, so we can handle the shutdown of the browser +// in the beforeShutdown function. We need to stop processing jobs before we +// can close the browser +let browser: Browser | undefined = undefined + +export const buildServer = ({ + port, + host, + app +}: Partial<{ port: number; host: string }> & { app: Express }) => + app.listen(port || PORT, host || HOST, async () => { + logger.info({ port }, '📡 Started Preview Service server, listening on {port}') + appState = AppState.RUNNING + + const gpuArgs = ['--use-gl=angle', '--use-angle=gl-egl'] + + const launchBrowser = async (): Promise => { + const launchArguments = [ + '--no-sandbox', + '--disable-setuid-sandbox', + '--disable-dev-shm-usage', + '--disable-session-crashed-bubble', + ...(GPU_ENABLED ? gpuArgs : []) + ] + logger.debug( + `Starting browser, located at "${CHROMIUM_EXECUTABLE_PATH}", with the following arguments: ${JSON.stringify( + launchArguments + )}` + ) + return await puppeteer.launch({ + headless: !PREVIEWS_HEADED, + executablePath: CHROMIUM_EXECUTABLE_PATH, + userDataDir: USER_DATA_DIR, + // slowMo: 3000, // Use for debugging during development + // we trust the web content that is running, so can disable the sandbox + // disabling the sandbox allows us to run the docker image without linux kernel privileges + args: launchArguments, + protocolTimeout: PREVIEW_TIMEOUT, + // handle closing of the browser by the preview-service, not puppeteer + // this is important for the preview-service to be able to shut down gracefully, + // otherwise we end up in race condition where puppeteer closes before preview-service + handleSIGHUP: false, + handleSIGINT: false, + handleSIGTERM: false + }) + } + + try { + jobQueue = await initializeQueue({ + queueName: JobQueueName, + redisUrl: REDIS_URL + }) + } catch (e) { + const err = ensureError(e, 'Unknown error creating job queue') + logger.error({ err }, 'Error creating job queue') + + // the callback to server.listen has failed, so we need to exit the process and not just return + await beforeShutdown() // handle the shutdown gracefully + await onShutdown() + process.exit(1) + } + logger.debug(`Starting processing of "${JobQueueName}" message queue`) + + // nothing after this line is getting called, this blocks + await jobQueue.process(async (payload, done) => { + let encounteredError = false + let jobLogger = logger.child({ + payloadId: payload.id, + jobPriorAttemptsMade: payload.attemptsMade + }) + + if (browser) { + const message = 'Tried to start job but Browser is already open.' + done(new Error(message)) + throw new Error(message) + } + + try { + currentJob = { done, logger: jobLogger } + const job = payload.data + jobLogger = jobLogger.child({ + jobId: job.jobId, + serverUrl: job.url + }) + const resultsQueue = await initializeQueue({ + queueName: job.responseQueue, + redisUrl: REDIS_URL + }) + + browser = await launchBrowser() + const result = await jobProcessor({ + logger: jobLogger, + browser, + job, + port: PORT, + timeout: PREVIEW_TIMEOUT, + getAppState: () => appState + }) + + // with removeOnComplete, the job response potentially containing a large images, + // is cleared from the response queue + await resultsQueue.add(result, { removeOnComplete: true }) + } catch (err) { + if (appState === AppState.SHUTTINGDOWN) { + // likely that the job was cancelled due to the service shutting down + jobLogger.warn({ err }, 'Processing job {jobId} failed') + } else { + jobLogger.error({ err }, 'Processing job {jobId} failed') + } + if (err instanceof Error) { + encounteredError = true + done(err) + } else { + throw err + } + } finally { + if (browser) await browser.close() + browser = undefined + if (!encounteredError) done() + currentJob = undefined + } + }) + }) + +export const initServer = (server: Server) => + createTerminus(server, { + healthChecks: { + '/liveness': () => Promise.resolve('ok'), + '/readiness': isReady + }, + beforeShutdown, + onShutdown, + logger: (msg, err) => { + if (err) { + logger.error({ err }, msg) + return + } + logger.info(msg) + } + }) + +const beforeShutdown = async () => { + logger.info('🛑 Beginning shut down, pausing all jobs') + appState = AppState.SHUTTINGDOWN + // stop accepting new jobs and kill any running jobs + if (jobQueue) { + await jobQueue.pause( + true, // just pausing this local worker of the queue + true // do not wait for active jobs to finish + ) + } + + if (currentJob) { + currentJob.logger.warn('Cancelling job due to preview-service shutdown') + currentJob.done(new Error('Job cancelled due to preview-service shutdown')) + } + if (browser) { + // preview-service is responsible for closing the browser + // to allow us to stop listening for new jobs and properly respond to any + // current job before we kill the browser + logger.info('Closing browser') + await browser.close() + browser = undefined + } + // no need to close the job queue and redis client, when the process exits they will be closed automatically +} + +const onShutdown = async () => { + logger.info('👋 Completed shut down, now exiting') +} + +const isReady = async (args: { state: { isShuttingDown: boolean } }) => { + const { isShuttingDown } = args.state + if (isShuttingDown) { + return Promise.reject(new Error('Preview service is shutting down')) + } + + if (!jobQueue) { + return Promise.reject(new Error('Job queue is not initialized')) + } + + try { + await isRedisReady(jobQueue.client) + } catch (e) { + return Promise.reject(ensureError(e, 'Unknown error when checking Redis client')) + } + const isReady = await jobQueue.isReady() + if (!isReady) + return Promise.reject( + new Error( + 'Preview service is not ready. Redis or Bull is not either reachable or ready.' + ) + ) + + return Promise.resolve('ok') +} diff --git a/packages/preview-service/tests/main.spec.ts b/packages/preview-service/tests/main.spec.ts new file mode 100644 index 000000000..7187c9544 --- /dev/null +++ b/packages/preview-service/tests/main.spec.ts @@ -0,0 +1,141 @@ +import { describe, it, beforeAll, afterAll, expect } from 'vitest' +import express from 'express' +import { buildServer } from 'src/server' +import { Server } from 'http' +import { initializeQueue } from '@speckle/shared/queue' +import { REDIS_URL } from '@/config.js' +import Bull from 'bull' +import { JobPayload } from '@speckle/shared/workers/previews' +import { randomUUID } from 'crypto' +import supertest, { SuperTest, Test } from 'supertest' +import { TIME_MS } from '@speckle/shared' +import fs from 'fs' +import pixelmatch from 'pixelmatch' +import { PNG } from 'pngjs' +import path from 'path' + +const BASE_IMAGE = path.resolve(__dirname, 'snapshots/base.png') +const TEST_RESULT = path.resolve(__dirname, 'snapshots/result.png') +const DIFF = path.resolve(__dirname, 'snapshots/diff.png') + +describe('preview-service', () => { + let server: Server + let request: SuperTest + let jobQueue: Bull.Queue + let responseQueue: Bull.Queue<{ + jobId: string + status: string + result: { + screenshots: object + } + }> + + const testId = randomUUID() + const JOB_QUEUE = 'preview-service-jobs' + const RESPONSE_QUEUE = 'preview-service-jobs-test-queue-' + testId + + const sleep = async (ms: number) => { + await new Promise((resolve) => setTimeout(resolve, ms)) + } + + beforeAll(async () => { + const app = express() + app.use(express.static('public')) + request = supertest(app) + server = buildServer({ app }) + + jobQueue = await initializeQueue({ + queueName: JOB_QUEUE, + redisUrl: REDIS_URL + }) + + responseQueue = await initializeQueue({ + queueName: RESPONSE_QUEUE, + redisUrl: REDIS_URL + }) + + // delete existing images + fs.rmSync(TEST_RESULT, { recursive: false, force: true }) + fs.rmSync(DIFF, { recursive: false, force: true }) + + // TODO: remove this head start + // only awaiting for the server to start does not work + // we should await the start of the job processing + await sleep(6 * TIME_MS.second) + }) + + afterAll(async () => { + server.close() + await jobQueue.close() + await responseQueue.close() + }) + + it('inits a server', async () => { + expect(server).to.be.instanceOf(Server) + }) + + it('hits the server', async () => { + const response = await request.get('/') + + expect(response.status).to.equal(200) + }) + + it('process a rendering task providing back the image', async () => { + const ID = 'test-job' + testId + + await jobQueue.add({ + url: 'https://latest.speckle.systems/projects/8b94a55ee5/models/7f98c5b62e', + token: '', + jobId: ID, + responseQueue: RESPONSE_QUEUE + }) + + let jobs = null + while (!jobs || !jobs.length) { + // can run until the test suite times out + jobs = await responseQueue.getJobs(['waiting']) + + await sleep(1 * TIME_MS.second) + } + + expect(jobs).to.have.lengthOf(1) + const [job] = jobs + expect(job.data.jobId).to.equal(ID) + expect(job.data.status).to.equal('success') + expect(job.data.result).to.be.an('object') + expect(job.data.result.screenshots).toBeDefined() + + // write the image to a result file, for debugging + + const image = + '0' in job.data.result.screenshots + ? (job.data.result.screenshots['0'] as string) + : null + + if (!image) expect.fail('No image found') + + const clean = Buffer.from(image.replace(/^data:image\/png;base64,/, ''), 'base64') + + fs.writeFileSync(TEST_RESULT, clean) + + // test max diff + + const base = PNG.sync.read(fs.readFileSync(BASE_IMAGE)) + const result = PNG.sync.read(fs.readFileSync(TEST_RESULT)) + const diff = new PNG({ width: base.width, height: base.height }) + const totalPixels = base.width * base.height + + const diffPixels = pixelmatch( + base.data, + result.data, + diff.data, + base.width, + base.height, + { threshold: 0.1 } + ) + + fs.writeFileSync(DIFF, PNG.sync.write(diff)) + const diffPercentage = Number(((diffPixels / totalPixels) * 100).toFixed(2)) + expect(diffPercentage).to.be.lessThan(10) + }) +}) diff --git a/packages/preview-service/tests/snapshots/base.png b/packages/preview-service/tests/snapshots/base.png new file mode 100644 index 0000000000000000000000000000000000000000..0b2ce9d01cb1f7ce7ba5951e56e2105833e53366 GIT binary patch literal 88362 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 z zf7tZsZTF=(T}*N{sEQ(wsCbfZ9Et2>QE;gTz+TYSt97Na8q-|jDhEQ`!jTt;q6A&M;v9d%NmvkP=?%+ zoKMrVXO2TUbhH;CNny$_)EQ(~*z)#f&Opukg=su``!ar1Z>NAl{HLR>&<)o^HuAVK z%ccVHYc+H?8p8X}GpA%Cnjf~|*viy|TD{uzI94)$x#Tfwi3}#eR&lch_fS`TExo>$ z+o#=b2rM9>W6RRmSO zMp;i1i^H$%8Q+M@;899L+St*wjpS_w+P#^q6LhX{MRx$itZKJi0r7_uil1_u7B1 zxh|LMcAr-~o{twrmpndv)L4elDU0e7O`NY3!}1q3IgC>1?kUkyh2L7@yXu!)Nk{Y1 zKZbr#Yr?vL>}US7Ig%7v=j{e={k#U*H~;ZMktXuQT-%}Hs;E&nZ>WJB8U(b}DXil| zX2@ZNef9z43}g3qNqsWVmoTHjo8pQLL1iE6z$XQaMon+dTK3s~c!7_jOHED~U!Hw$ zaQpjpnE|}e(@E*jXwHPgJ-&R(R&tB@BmX#KhiNV+=d?}o%5gSgyHNcyc}C3VVwpzA zc}|y;Wc!(-R|aDwIQYe@Pq^au+ihKU{iTR_VXyY3dBU&zX?zk$H^oQmRjeG!AU*E(pKe}+7_>#)(6@g3v(FwVGpZ<^>6*%Ki%GGA?>_G! zwFH6NID|R+iWE0BJpm8;?U2pYIV`UBm;39g2UwRmYCqvqjRE2VGPXWqH*enoJu3Mp z>{zN>>vA4kI))5|`W%VN!qaX@Zo3~Z%ao#9a1P_9K{$<=#};YZ-SE`m!+Z+YV|KvJ zrSgI3rF&xAeeBYwTlDYn%iX9eOcd}ZaRoCt5Qfcbxa)(tz2mKgz_{aq@e|oAVgoN! zTAS|xJq_#+G_vdzbBhc$$%U2(g|`9lZ#RD~$-a-!3y(;6vgdo{Z*~cQPL>;)0-nh# z>FtBOVlU4;-oMNzZ1D@)KnNE^y0LL}BH?@d_`&nfuD=(Oy55L$UM}J+-m`57;L3{H z6Xa=ooIr)e#cVBWnTPF;{-=~hAXb;X3>l(+-YeFM(r$V2b4A~+6VLCT^Gj1h*pqF@ z>VsWT&y+QFK^pP%e;C6|cW>~lz^L{%HYRFWj3@{k5QsX#>S$%Y$}hX)fZ_Fi+5Q!2 zY!t$uk>ex|9@8+F`opHT(Tfx$rZo41-_^rc&{7yPpU(Vr*XW{19!%S!v-v^0)# zQcuhW@Lv9DSK4-;`hc7gHXk5S_a86aJFuLnZDEbPZ}z-3LiqSzD^WSvNb!AJ_w`oW zWkr=$Q_pr5ISZ$wNKd~PwhMfQrv7Hh7r~IhYahkZ4OwNZX3s12(AG|=(Az*#iMk{i zwV@MMIxc5SdAmXT@KCWHt<)_m6L&@0mF{~gnh9r>6|HeZ94z~CepI7zrSv}d-Nrei z($FhTy(_jh7=8vbe5)DN&g8_*K2M=TUT}rej!MH#t*jj>n6>z^=tjiz!FMa=0>4_R zCEYQJru9;sO56>b6Wn4$1{?0STrXPbbFC8jpjSF8`zcsM%WXMV5PXf9+mMePX%=Co zfu{D@@Pp2Yh98+hYf5&R%3&+A@C4fS{)vO5`ii?_)&(_;(k%)BbmE|y{}O(R^1M@! z*HC7CAcUrz2P8H^x||u0(8QDE-MhJgO=1#DyuAr_M)kiEdB9=u)#4Mh=bs?hRQq{( zuM`DZ0S0JWfx&2Gm~}E)$LC#Mv^|u|2-E{Stj^asY8?MPR?;}2{=DSUp|YmSRv!u1 zDRhD@AN3rm-QfS51we42KNSi!i|7V%Bm4?uZ+RO@H;9d z6Z!<%wu0CCnG%D(B%U3D*7pEF))?ZwM4X^>2+G| zmXI6y*+RE5`3S>1SQ|D&y4EIf4a;OvG=k{DjRS97f1mq@&?1+B8UGWs0z%Wgz8#8GnO(|#szDx}A zui|k+Wd=2bUB62KUbrJD$ZK&v@ZA}De_!D_wW$QB?pX%vWsr}OXZ9e!Mk%^uX1HG&m zaBsi2TEL+x#O*Kk?P;WL!$(q$bU~B8zbD7+v+&yc+)nEXe^4!}h0>w{biwHSSd>od ziedp@!`_LjM7OwU|I?!la!g#xWL38Zo-9s? zp31)Sabs;bL3weBsKD-+=ZBl$(MwLp;rt9nRB?B4q%%~qvbS%OOs^`9$(42Myl`X# z-6SenJO5?Sdd7FN!mu?M;sYaqe4csf1%g?FoxX7(ey=X^uIATlIz40{QQ)P-pci=v z`DlIG#NxSCX~pHK^Cw}J21&lPWpbyxrRec$>ncOpBC!P+kp2#D*jBIq*f-iC&Mza~ zV}Y?p%p=_!LM61WkP3=KA&@v>t&7`=ELBYvAwBecBu#x~`!#zGG9?xAQ~nEiP#UTr zMGzxIeR&Gtfwk4SUcX>(Ru{X+#jmf+ZTf);EDXPt&DEI>bmOG@^}e|3wiFNUFU(d$ z^WzQsm1dZv07?hnTx_EwsXo(5N-iLTNN<{|+(*hUFYlxYdMAER$@^-8Pk*XBjfGy2 zKj;1sLkS%_{CJc9<=M1^M^e-_%&Y=W*nEolsigccW{^xboNkRAq0fzJldT zPqMbv@TL=d;qv1Y!Z2^p-w*+*fLG4?O_shWGADh%``2$o!~xiV$-+p@u-ctz@$t9q zFbBybBGb#;X!IjO9lER>9lK5nr@oi}d|~WN13?IS_0f5_^u-v4V1_MPlF1sP2mTHkNbryDmLUyn9$?F?v8? ziQi3bu@6i0q%&~hSjmGf4LN9PFW<`l3oChc{=}wf2_)FixXy0aN588mA@2gB1sN2; zL+53)_t(Q3yX6FE?-*WE=~gMM+5>3VKfD$s#sUoc>+Yog^yq+k%;m=nRrYbzxcoR? z0vL__&E8BcODfcObqM&m{P}$*hu8@wCS0e<9=!OZIwuw-|i2x!txU0%zu#3_idr%JN1c##pif z*#=?z#R>_9Y)=r7t$0hx1bSn=$31?pf4b9^YDLG~()2UJZyH|lO+T5xUS(}5Pd@tUQqJ>uRnnEz-#D7ZHY#SOQ*OVYK~2FDGS3&lXWQ5#jb#7PafYl!&M|Jr&39h<^E&z|Yvl&DHv6L; z!ACtK0S|43!>Oo5x^0RFosb847VP&Ow(4u&EVJdbl=+pS6ImHo-k)3%gJ~4ExJ$O{ zPwO2Pb^_QXy4cbco?ZdX)V6KSj}cLHQomw4hPQ9u;^I+0JJNt)WPCM%Lr+x^S-2|2?V-15T`U zuvEd_8}Al1^p%9n_@VUM)ijnw;7@)_$)&;)?{j6H!LM9hYq4Umsv*BA^FuV@GFO-x zTkvmDPrC8hFP4+#a#~u%9{aO++B)ZCqdFW$VK~5ywc68gr=;8Vo9mRJrXDeWV< zEQq+fxVrdha%oZB>6#yY%yXN4MrF_*VNPia8Y_yVmc!pd_vbw6q)wng-R~Tq zhTNJ)lbPa{Oed1h$!i+u=`oNeqwI91 zD-j=TTr6?#zz&~{TNgKR<8v?}{jBsA# zwZ3tyIsWbd@5Pn)#5^1%KKtC52o<#bLd>P%F)YFo7>K|0Umtn<$ar!R4&-Q-9xsGg zIhFEK*BrbKAbYdFDc9AmuEHh0JVQtj6u*x$i^=Ap@p~^eF^_<#d@ML0yKEy!Y{Vq` z2n2i2fT-lnuFK7YAIbTg=)@m# z2}~YzE!Q{@Kzf?z)0vfTTvgmUpYp0U+@{pl5zb%o&X@qM_M9v+-<QE`;5{E?qNnaADkEne8X)7c z^4Z(#E?)lrk|BD?#^{qwqOqKIy_8BO-xJQ#S#I4{stsTMxZ#aE=drS9_GM+PY~1qM z5BGvK*^B^+lTLP@XG)0iFujvbrE{hzI_JkO3vii=ya?Y(7w7b5P zGZ<4SaHDm`w>Bxy0Jd3GCYhmYZz#H)OU3=zEE2B#Q%IK%{fV~LFlw&N6(%{-ZG z0KCnk=R4JQ!^p%H(@U<%TVQoAFEWtA{ql@7dfm!i177A*g3!KlMHLJNR!RGPPUZ`iS<%ya=TR2bsbX zyyDMP(u8qpYiqrt%-rWD?fVk?gpoP7{@Uk%9Un&MrEo!tpkxoFSz>x^aV>DauFla( z2EV+R_nq+G{0WtwLV3Vl@Zs7I+X|^4Wih4}cNA0A3Gd~l-GS7e@mXIywt`Iq1_>$C zpF(w7D_o|m-hp!;i4!6fh@Xh8f0RN}t&sM6$A$+?#AX~bj#gy-SrfU50ME66mX0Lii#EL0A_nY>is6!j^4O3OZ7^s~4*}|%ZW>WiWot{Ux z)8Wy}%M02!!9RMLg^|#oOus`Wd2D;PSs7^hWjpH|ftnB}7)9h~`=i`b^m9`VY$_0V zs`DG|9HTPYAhShBz_<+W<-1<@t=&I*-d_ZCMEhL?OBNU=XA2ebE8n-7Q=ZH~nSWJN zV+OSiONYFj=44u-708i5!{>5FtVFV8wRh_Bi}50ksjMwSMY^sDUe)J{Yrt;o0!DV02GG;HT!Y7{|fKvu#2=?_wI(TKGYVN8}G$YI` zz5Ta!Fyr0g7X(J=uLT9~MZ274O0Fw$Uysz`GEL3B`XX zdol+FgvZj7+*b+T%X9&XkHvxg`SqAQu^7QKx$DrXxL`JB>J-+mADdSJT79jmFV^H_ zZS__qlh?|@E~CiM9@rm(X6Pe3W^ElCR%W}xJ+9kids`ohpYcAyvGvsjg#)sZ+;7Pe zWMNl}+yTMp;rQ{aKjP@Wu?<){Bkk*bs^?<8Z$c{uij@Qe1nAUH7(OSP3Gz#6vaIr2 zoS1z{=S$Ywh(Bmi*TP6c-7FoxmD#1F190s;vkIRaw4}@W| z$%xte=BkHn%e&c2TH!!kOV(Yj4P0;tZc%l*#goQ(I6x)VZfR+UirrqA z;yLSi&AuJV;zLbS&wuYI{Fz6RJVcyjAxru*oD&;O80oZ`F{4n$#$iOd0F5oXagOZ6 zP^2ms{gTW0+PH5y$jY%C4jCHBS*YN|Hh|Me4p+6%VvaKI{jIKDqI)y%OfUl@e6%FH z@T>{Exe@W_i<1c>HOVBKQK5N}uw=&^?j|B{Fjge`mS82tcph?2+(`{`;!I91_=SL2 zUR(xTC2~J5Gt&CNsqjk`88yOz%^@@ONIY%i>H=Umm=hM13L@*K8At@y)&JrS3V+o> z*FW%rKEwoOL4SWjuk-q6N|WS1O8Aaf;-Q$tsQ*7+A=2d21F6zGdwS6xIlpyzJzyBz z6Sb}kd#=?C9>8fkaZI^e9=pss|J`;o)JPDMInDjyw`P`XV?v)tPeD(rxa-hu!bI70 zgS}w&-PQCH)P6aXV~qG%v(%3Twf&FD)ugsr43SD}A7vQdR;d)c$7A{_{8-9g5WAvRtG2$liQ@EmX0ZSL4Wrq4c@b+Q3C>r>7eq1x z@k0vHS5J%;q;+8o3Ec5AWy;#31;DJ1qC}^nH}i6VfT)J{;WFTe@%&q=3?Bzykxd0Q zvN*Zqh=aWxa^QG(beU(;Q^%&ol z2TD&!w3EW~6rgCsD;wr~DpSRATc8Ue)peCs6_Lkt(A!5qNK)SA)Rf|y!oLtr$!1lV zX%LP5RsD%;V`JlV;f-89cl2g|4Wo&X3dXt>A{Z}JW6t;fvQ8N(lm(%c%asY6u#flq z{S#-p&6FlQ^c49kCM0EA6qzGd$sce6PO^Vf`##yb>}5Kuw1zXUQgrn4mE-joOO@v- zpk~quiyROCyb!Oz9EXjLK|&@RIIrdC4^^8tg01U%&x?!E!G&~DPeYPnx;{Q>RnW9_ zJt7QA=1jR_PSs3^vd;a;cE_rng)Elz)V^NA`%4Yw1n3j91x*H|f zS5td{bB+znlKr2>qrC(W@r*Lbrz`!(Jm-(T+k2mf%yI$Ps#|)jn195ap_M!!^RwYj z@&b$)G|yU(xE-(k2{$c%Xxe8`q`J*6JH}E>IXD*#$OcxuOP=SBZT_}xQcUAo zU{7Q6kE4A`X78OzkB?R>7UrL4o+{*=rPSZ(Xvgj4SGnKfgQF7^5_x`(u_ovsV$;sU zu`c#!(C^Lb>MmZXWQ$YRV%b*3&}K(}-1&;8?NcCUA^&Su)VxazSKtLW;f#*GaaYLh zXl=a~Md_@5dN}ZGIG>!m^ZQktA7x<9XRSj2ha?xn6&?7Gi}4}* zrh;A@X@c+jl&qq_@7C2Wr#2NX1SDKZR1Z%=q3d|V87;NpVTLyd0n0VcZnFU zTy=Lap2T6M3C}XKkx<+3Ca1PcwdBYPI~^;f?DJY$C*4P~aDzPZ;*0X7YSIc(Q;|it zMUo*2AM6t;>Kc|6nzAKZ*d|&TMO;NIs^9Q##%UE5Z=W-@o+GSo)_qVKXDKK0uf-L! za%zF1@Ax+USbAP2wvt$5`MNhnSP-qUD^RT%PYP4S4kFn^Hr3;RKft76@ypNN5_f+_ zT2H>mKAwxp`qoM+ws$M6lPUduzTJ5tZRCAS9xlHQ$k1YKXX0h;7p^s0-jH3e+W~72 zFJPdf^!u#aJNZYoHSRw*@9zlZCjE^6h55{ARZEQimLm;vyXR!N7$Z;C2Vu7H`at)j z584>uO6sg*^k-PHcm+^~wSrHGB32W?n7C}W+*}_Z^6Rv17sr>6J86#dBFlss1%gxRgUV^)z>=enzA6tgm&7OxRfFo=H?p@I-dbaU+x87Uv`m>S+HlM_ncsYNGQaq@1e3^YCjPO~IBNw#>fg&+(H^d-fm5(S6 zfH%`?6ZlN`^~Pr%`|W;eAwVO({zx(Bp;I8Yx}!j&FU%6Y>7Pl0PX&zt0=Bu;H6&yi zKCsy2KU^jSkmVZ!YT>}&bM-3(;3lC34^d69G0adf)?vcQpu%6aDCb zCv81%+%ezrV_cl?i%_!$Bh}{{wzxA4-=bnEL~v=nZuNC*sh|2i`KEAHDHVJSQ|9WB zq+uaC_kc~sY9k@8$Sb2)l-*vGrp0yux=P$ctKXLTqb&`2q8lQGLQUpmc>8`uEph!| z>32Bk1T)F6PbJ4YJCvhw>Up8sX4j~Z3=!5}G5kjmWvK>Qkp>TR7c}#oPWZ4#fgcwc zTSI`*1TKfPf`#bZ8dIEhn64MqQqqcyNA$9Vg#vEpxI{J&4NWt6hBD;kLRfxG(nZtfiifYXF6M_P__$6bczNZW= za#p+7uXo;P2q!qXb%%k@u*=mUoSjzhw!MkD~;B#-35J`UGL!d3QWX~uATt`RCe;JZPAl&260`kBps$)z zM`ha|86xZZEr|2~kpy1(6EtK!j1mr>WV>uE1A_MdA#wfxABk(h#yDH$g6O4m0`Sv$ z{D0!u?zK;_b6IH*%@6rNxBmX~K4>ONS(!o9CK~=1@Bl+kCTQ@fHN@DvV%_C_jFs|P zymuy+Vr6^E>%J4R&Crzi0h|ujdvWgbsCfMl~P=76V&z__8{;I@%^E5*LrB`}H#G zMHZ5HXNL6*xyoO;j=gbo%x3zDS!aMapL4G_GS}!4wJ#3LqS#x5Nz}&Sx8dZR+Ptii zA#REPBM$sdN2mJ6Ak4mWve@u6BFV-;TL2wn`s!@l%VtK?Oi%w!Z&X2FdGSwOkW~ze z^E`S+F!rC%*QZW2ktJ(cQ4NRG&7RINJ>YblqOt3%@3AJ=JA$c=A5rV#6b|NVfpJJ* z;=(^|t5D0mz1O%Xm(-HDc2Rk$q`7w^oZqY##C5a|d@>A+deDK5X*z|TG}SkT*aFT8 z53DQk^-t8|y1KAD!B4{%R5*E)bJKqnTv9?Gz8vOs1doo*e`cV8<@}~5n0FICz#5Ofw#6+5%H^~M=2&U(=S27Do>Yo2Tuzf+gkew(>*{gE9;K>%fOgSroVQKbST6nq#t)pPQfV_A6Bw!AR$y~dFYX)kLRnEwAS!)Pppzu9a@#- ziWEIb{eH@e+i3L~U}Y`}h1kb@k)05JY+}@6Hroa`$?V)O@vo+j*Oo(4IQ>_B@m*fx zTf|`~ddiX}!^x5a!$eaEBHIgXn5;c$qrakvHT{><%31dPrRU>A;ul-3_|fz9FL%;_ z8r8Uky^V+aU=Swj2gn|y>-!JYKBY|=21K`UV3eLJ%jK*kuM}L=`2&G*ndSG~lQt>c zp8vd%-~Z+Ikb3VxE)0>g44k5%9&o5XAbl--z*#F|FUr}Cr0;DGm|Hlj&9pTB}6i$s@#G0WIM3CzQ6uwo9w+yBS)kR8tua} z)=}i;hp4b07JFr4va21jF%WLI1r`@IX;F2HJbgkMqb6Lu^K)_uV-7ZDr8k;yF%~A@ zyn7e^3nB7M;(A+MBcNgN-H9xZ?3L`>Utj~%LY3Yc-Cv4Uvx;%m2AfKu$kx#*ZVkG!9)M5mUBKptvdU-IG`oi0+Qs&wrcU4vaF$4|tI$BUOH zH+#BPc2?bDfEd!4QQl-Izu(t%G|bTF0uVOfc*a*;Ouhn*;O_j~-Pv(oy1)D$1lG2F zDnp}_Fc|TdEjt}~a{7j2#82V0fj(lN(j%Pk#uQpn$0=3O?<0ti-|{OA<*+ zT*UK4yC0S5>(Jq-!@iZS7u?cUynNyRHw%zxogwn4S1fJ~l?ld4=jeB!?01Q}vdJ>2 z#*iYHzC6Qc<<_Af83CuqKl8?IT;#ze#6VQM%*k96IfcT{7KT*qv3#}LVjL6n^ya*w zu3K{z36@VUyP;Dv>d0bO*uJiWJTU3hhpnxDGfYx(qJ1&+4MN#pNy4f65|@StSBqIi zF2U!GU~7?ZzhGb|jX?_Lm@q{bgj&BHf@B&zeYdMaDMBlPiE!VOIrj6h4LG?T@kO%O zc_algaOUCw<4GM>jdT~LlY+G|Z4R4v>EIJpfI|nPeKN^RpsZKTcER3yV&qa2<2gYC zK&3m}hOD2sSpx(}PnevIJnE|u&VZN2A%Eg|qzP)pHkYzydjDoT z{S2w~Xz1**9#w+E-pnt8tc=R1rNT&*3S?h=pTj~EI_U&cs+c?dXERb8Onl8>EYB8~ z0~k6%g^OsjJET)}69P z8UV~HBTypaTKDZ8L)m`&Tpln*DkkP0g{Ko8CzGTk8v~i0+>o33XWZRwfaZG{U?))N zk#6O|aeMSZ%|HZ^KB45PMOL@M?%%6(ECPn@lj)j+mqnVo@_F}ve~n1fb~V!lu8B~i z;LABl~ zFR-N(_3A)7;Ldol#k=n$6|68ChD(VlzgKg>q39T9rkSd9en@c5K3OW|%n-Q~&|)`~n`#Qt4%I+Ik~uy(-%|hyVMhm&Liw-PP?9Jo~Vjwo|H2 zSZM#u+RjnNREzj^EJf&wOt{HHFEVZol4~l*6&ZEH7qPsP@;7U9(bb@27Oh;y6|;K} zQf|DJBh`lyL(WGZ8NX)hg)onx^)f&celTs42*_CDU2Q)fzTFb7iHGhs2WjnFA20@= zr)NpQj|Ui)OaH#hdvL}v7VNl7068)23#pMR)3O*HG*`Yc` zl}<)JeoQ|Vxl#9~sPAHdK|MwGV2^^6t-rAXZbI804@Sr}EOAuJ@|0iNC30&>{6j0G zUw)Bqbu;+OeX>?(6548FsHlG0v}4OFvn(h@=cQ^}FU_1f) zph`SU82uRQS%_yi0lNFWVcfD`#)HQB%}_ zEk!PAOVaPTZ|}9$dJFyYceXv;LKCsdG+24vIP7&w`5`uvxcB=HN5Pslz|AK3(x|>D zqLlU{X#;Fm9fO{#YB(O-b596s1Chax#i-Cqu(ueBb@<3{qr1WRl2Z!sW~YVBG@?){ zItgy3S!VU{Lt)P>Rl2%07=dU~zM$$!2>^1|Y*uDEg3m~;VXio_0+${i54qmv;UNv7 zw0_}9(nu*nVQ}O-LX6RAy~GO^hQTru+9mS!lb7pP7Ak9nS`5v)h!k@U`Od81lUiEG zBCQXPV%&}7MDDOtCSvTOLcE{SuV_uWi;T$yKVbkfTEaLpV#+B<>Ldw9$7yg62cW3U zJKkV3TFvOX*!Kx|AjrNy81Vz$1@63IU1p^De)~BaSbY0Sfv9UW+;4$v1^`qtexwvT zH7vl*ZkLG{#E9*7&mlf$7xv#~J-TZBJ>?r1IEzJs%O?6Zz6_~8|CKhSd{!F&`AFm( zu#qpL0z?c6eSq%d7`XLdSVS7#U2o`dy=!^4E86~u))r9;mX}Uv>_928RhzN~MSvAQ zD=0WSg8-Ig^;IBM32b2Lw31pT{y1Y&3lW6K#` zeSf|KzhrP1ge%&x1+$$8nD5aie5E(mNUka?Bb{-ZCEhhj053SifvYkFZJ%#)r^W*G z2;Eqbk?*rELWb5RdnpJ*TU2sNis|lT8Tr7|4HSPnqanz@Xny~ASmC6xf@(m%zJ8U- z3}3=>SthBP4qbEFI;ApdwwxphO#G0tM&o}(Z>H;>E#~vQ58E#t zJ0C^lwv^v__RQKp8yyorq*YtWXR--xb$l_a^Q6|6$YprLuQ>NNOLT&hL7}UGP;GIg zw~ooB-CR`m{W7qm)_1%#a~ZJKg3#W1lD(^RG}RZq%f{Vo+99Cs#p3qE(i|T47kdFR zS=gznhr|T;i%fQAcQ8%S|W| z?NP$dNtwLts!MS<&%=XzJrP8& zuxfF_1u5%HrmuL#zphi%EUqRnWb40G$w)PNn`GuMFF^uzfpP#RMvrZ2qi z_dCDq)1~I8f#?87H1qaB-UIx!d!KC0b4uMgh7ov)QadJcM!J}#1G05IG+%dd>kAV~ zUJM3|PdA_U3D3Pg$onyteFYvs<-gBkw;@a#|9Qa3l=_0eQNTc7)*tNLHVXT9J}1<6 zG_^zGVGzCusF%5~CNpOExkut#HoZ_&B2?DArFA06zRMFJzXdujUWVQm-{!z%qo^zGw)s@DUr{qOr`Ox{zSg001R#GMX*j|vG;fqzo=#2%bKbF&6X6LpzY zW1EAADB2N)Wfpk4CT5 zqa()HRfNw$PsR&=FDP0F*ho(~3+!-;$fRl}(FbxZ&WbqL41fhY{E2S_^x1Jq#VxfS z(el}N;o6W~^wE!cqt8=q8=OTigd--_oUwJc%f#HUgR$^B^|_%0SQm$D>Cs7#VNd;- z^uvqT6@xU=$XjcPRi;11UFY2icNv|Z0yo);J%CGQ=t<8PM!3PVj7&25qonw_3F5A;V9;~#pVF4 z*D+KuV8`)syxiPs1^%eA*ODgc@(tQ&`$l^K3t+!`)7;fvZM~J?vAvh*(u{eh0hLW@ z-Fq(z6QSDiXJ$D-tzI+U>XK&TC@%`> z)6I{Eu>IDjB@+D{b_48ejf+pA$LkZpAFj-9#;CVL`Z(U3KWI1x#daNNte$ytQ>j9R}}nUDp# z&CT`k*)z}U2w%tlyC~NaxPW~A=8gOl~qeLus*b@EGUc*`#=WgSkv-9! z!P3$+TH^ARu}q6e)o8rN6zSmcr>8BLJc36U*-pD|AeulQNmuf-7E6CcX;uUqgYp{P z0`;z~x*FuF8#=_VzK;IMO89BOx&~G1)1$Ur@F!7^eP%MmxG6A{%Wwr=Wm1=y7K%Lb zc$87{G+uG*0^xqQ7c2ITK9qHdP7Vh3&&xQ6$@#n@DqioXU)R;vt<(WNOFvPMoTh5r zTaW!tL(c_twGbPfWKoNLz}+t42psf@1GKiAcl>YE#@Jkt2FOoE=us^kC9(TINzxQO zly5I&vLC?TsP>#eh+A5}A>#MLxv}Fc>IX$U;ozXA(7fCWl=8=Y!G=>rvr|Jke)7!| zfz@ml2xVWfjZZOkT5#8Kj3g1TY(Q5$esYR5UfCYcnPYall_h3h_AX~}LZ$IrRV*;= z0OI|(1*4viP3_mMT-ZQ)12;$>_qH5@_c^aEU#Z^;dmYgYC>{uvE(Hbyc+$G>O%E4! zJyonxn2%~9|GXMaq%7##>?f@du5|eZPZ%Ceh+W%`;-WY0{ zwf?q>&M9NY`3nja$)^zGz#m^f1*pw&*`og6EWqLllVh;BJfdi?rk>ybUW80gEz4^| z1g)xc zCFx`!U*Dn52b?3{KU)vgg(O@tuPc*8*VskgWkqDk3?z!Dg-{9D!~$Acn)+w=MVw-?s4T)6nQ8lUKZ_+RuEfmW&^oFFrJ&<5Ke_fJq6z0q;(8w+b^h zxQ$I1hKq!fa35eG#1? zS7grQIz5`Jz^uJ(`qw?e_3z%FpCZMmvh z!6cUvDiNJu>4&#(yPrBgabuTVYV~Wx`q-1eM6Mpab0)^k)e9EHK6?i4!#R1H%;*cn#>m%t32c@=1Dat zlP++~B_|qlbg?<6AgQOyC@H!S5>=e0`> zes>{6rCXc2FI2q7Rx=o1pm0w^0&+*<-fw-D@SZ0D4Yxe@&>0Smm*(Noz9Q)g!}}az zP|X@C&>!wfLBq~ z6KYi{UwI|exvycCez*hg;P1gzg_gcpzOsL9-sVrJ@l4pm)%Dp~vR-FiLq5sPcsql> z|D6Hmh{JTmZ!CNUd6zvZp>A!f2k8A<-@{oH(gcjP0{4y1Rg{FeMl;xjBGruO&|?MdV6;e9!+Y-Q@^PX?3+3Cpy= zDr1rizrAnOK!Zd@FQBQ8N=mx@oGW+uHlD_T!}@j0X%dTH3`fMmIZ8$Vc|+l(fwzuq z!7l!k@%RtqXkk;VQMg0d`-k;JFNlh%mmJW7w&ZTD44Vcbfv7xS)dNb4 zTPwX0rdq(ozfhYfD4FLEP;}1QY|kBI?If@w53u~*hlLKv#Xez2a`{fM$>-7k33DS# z+3ExqvhVZ_@8B^nV*7~;8798U`RHSoalQm9z23w%TpUF#2x>Lh9B>GBN%{{}>^35c zj4|1>4MrNJsfuksW+QBKcl$=-slY(@oHnr#P7?q^R7pkC;|%?ZO1licLXp)21IVFs z2gLIG`4N5gA=RzZG}M)edd5JiaH%aI;9nRFdV9uCs6p0W@9;Q$esd|fEMO=OF*~WFsmh(Ee@7LB(g4~7tfK`IB28L2AJ@kWw!rPOGnc-77U2$ z<{f_e)Bk4-yXjJUENKGv4tKsPg#^vd3zGKUSsARAjNm?9$;U;Yw@Co*Y?)1XbK@L7 zc}Di}qQ(1aeJKF5xDKD<6%`gmdOVOg`*FVOXAV`zbsuu8OxM?oWAR?>VsoY}85psj ziE6#Ky}M(`mSPCnDA6(P9$mRgQ4e_f>>TMfH@6ZAnc8EY?dF8D*~8ZN33)%bUCbz) z;7PmsQ3G{z_tT0>1=GV;Kk;%Q^d9uEQ&lO^k}3O95ir9lmd)iFo@H!TUlnZM{efJ> zL7>AOTYm)`!7>kf>i|e?sbd4Di&XWlLXA;Y3^epMcvWgG<5#>>HoRGz3m`qNNz>BE zcUVL}aD?L;qM+mXc;W)(7|^M$8;=-9eFpvAaaYM!;K~WNGs5}$kIhQ#n%E`BL#Kq_ z^`n28$G~Zfn@B(nTI9R}{B+eL={r<$KGtr#Q#^`VHLnWxb=+`naC>ec6%aRmAjbGS zWj3j0syVlDESJN=-EFwhZ5mHK<*Y9nx0Jbct;IT^&0%J_{l5chMoRO3`;^&N?T!JL z!=k63c3NPJW}zwulGlaV9ux=(BvgeO0s_8I zRME!vF7(4%Wc%5gJe*M;-_nr|8!aImn&EmE(fU2D-qBMGPzA;w!ytYPkAt?0(4%tY zrJw)?)NxwEkEs%{vFk36G8rWzB%1#n?J~7vKsw79aBmJdx*&7A!sQ&Xesa)!(3!Q+ z9M9B9Ip0Pr>z49MZ^rYA#|UqsedmB8VeN^lh3Voq%hgA}GAd*I(cr~tFi&?M5#ur%+#TzE ztp}$K!Gv+gJcO_j6wl7aX&!nFvGey3Tl89lq<*>)7|IYz5&l}qr}sHBk$JWHvW3#e zmcZoC6SAwex=ku%PK1|I=c0qFSesow;Uh(|$YkhzIx>>lmzrcW9iXH~SW%o;7UHvRf3N}4%f6FUc7l+9XiC>PQD zXSRmHB;mjAwjjXm^9(C&s@*3>`w5-y@PAJraP25Ei{-ymZc1Nl&3~YB-xEc%%eQ%V z<-O4+;HK=qWzRfe**vTF5D+=Sb)5wp?L*B9_ZJ623yFK3>Y^7qE;Z;izq01f3{+=mr{(SN7>*ejz z)<~62iF2lFMw^UFDKqo?W385qWM%7D!DSx=gvhah!xyiRx*N)Q1&#f42nd22#R(`} z2#^`|z;#bQ|1j{odPXP^v&66beA}HET@}^s(jG@|8Jd)ns8~uQEOS0PYH50X~r0>e`=l ziv;DF#aGZsTwR$6P(eeUZ4SwvQTNPw9>_+m+b?d9AO9f;z)n$2@IlJml>D!GS<>q2Q0A>ke_4`vtUZ0gRA|eyNR|(bjn5>hak)V zGp&EB2@Od-hGupRK%>4JNxea%3>N~`$4-pQ;sqt*qZ&fgnp9`P)NC+5>_mI~Ro7#P zTLtz!707V#KysOv0f}fDtI*@C?=y#wsB_j87(aJ*(T zr!2ay&*jhffr>Ua*bF0c7D&{QZbZE4vtU!yQ>ad&({;iornjNg1e5vskh2OP|v zwV!9L^|@~=N+IJ4*8YLdF+BOg$LrIuDFe!DWSYZ{ib^nGK-TY4vDDC54j3r100u(+ z9}vv4=y~PnTEKhP{1o(^U?@9WZ)+Ew@L^q&iV$#}M$_lkW6(^3d#5D)Da0h>#7av8 zr$NVX`8Rm!a(HQdeQkH?}Dh8Ay;}2x@qq{-jj1^28wyz=pW2gQojF5IjaLW zICwqJDR;=R5%1J8=C(zHnPS3nNCVRfMB}B1gKZ_o7)Kb%{LoJ}tG52KO56>sdOa)G zb0pu}-v{&@;k3do65ZA}Q~j=k!Yh7u@vI(SANsnWSuIsGHeQQbS;tf>%?{X4zpKGh zYAq}LjXoQ+oxo3s8SxwGy`*HER9}#a=t>0>$lw}jsu2f+{{5(l2Ss$e5&>f&w%lvK zm+{#?f%WtLf^~X%Xf%#6>1)@E0KwNO?j8X`p`^e9qqbkMt#cmlMK%)+w&cGKWN zVu&6v46ohh5>>@yAM^JpqI1%;BUU;TlsBodDhsAAkV4F@R@%@N{^SERWD4m!^qUsKlXofl%Wfw#PnPOv`{MBnbu8lr5u1{A-QW-&9Fky0>t;CD-TI~Q zJ$I%b^zSls*lX)`6?^d;<<&WysJu6Mmy;4xDuNy(G@cg`dL1uUAKs_EcX)Lk!e-rk z?_55}J^)z?9~*df;@9d?v71tW?7P2`T2;@w)qzlu5aV&-#+l97d;kD&+QhEfKqW~3 zt+bymhd+`cjJNn+90ACLRDUOx>-V%I+i=AF{kzxoaOl|;BjKRJXYq8VB5oO-maT?=?j2m7?q8{xvd&evhKM_{wt+8yB^7xKYHYZjbJ z92)-bR(C2W(97a=o>%Sg@#&-@}6X)@%e)2Q>eab3t3P-r^Lj`ASr zLKChN3o)*vm6;|~#UL#yA+O{~+p;C(%0m0nHj0w{$)iVCQyD4zz zQ8$CnCQTf0G$h%NcCw(mz(p_k!;D(l-4>5s_CdkuAAb#_6tgF&Shs37?DJTFU|A2# zfC`88pbyKYYb2GP8n!PobRO7m2Uz6i zk+v2h`!HU!@Jz;wB?xJRlD+Y~PtCkz2s=t-Y9d8UtTzQT3`AKcYsaW zK+%jI@L+mm;}Mg+fE&aW1^;=)Gt?68CP?LVX^>~+1%zyT>sz-Bf$$~8=-%Q}dyTjR z8WrJf=Q8F@ow0>q8#FS1OG^A7uDfmsUh-Nl{J36(`ryM^BV|=r+tek|U9&FHG(OQG zGCT;+;>S3tgzIg(LbIjDKK?5?KIdd-4|$Uz^g){}2L^z7ZIh=L$C*D~m-9`EHcB9< z(;NU!|9$aoj7Z%n!H4Gqw--{Xp9ya4j|{(OI4$~F*Scx~bn-REp)~$@<7UdDy*mCW zql+pN^#T5H!S4x)27M<6pgJpU{{Vora!P6tDixx^Z>_|r^tRc2W_Pa6BqCGE_&Fht zI?8EeeFzJ0466FGbWonDlV9kY>UT+)aMCc-=ou4sR<>wF#p9QRiZ|N5jh*pq@+~rV zgP-K>#_z@(u4(yVIV@$9*EHE!((8F0X#jUA>C-2HVW3e51*_&uYpE|wp$zkpH@^<& z6i!Q=+jU2V^U?3PVYR+Qtr9s*?;#v%@94oc1NjIhSW=7VOAs0+5yO3jgK9fUPq? zJ13vO4A>cDNo!>vDjk*1Jbt^Bph}jB1sO?P*Nb~_8>O`p{$r79Q&5FNra-h1ATb#Z ztIeQ@rLTVxPyhdab?OTPRLR9q&=JLg?854!UxeAi;Oyf~KrRfw*>K5qxvfJP#Y`%( zf^XPq_ZR5oDi98lmZ#Z#X`IpI{{f1S%vx-H2 zJk#<3Fqbg_iK~WajVwLVmp!~(g2y7EF~5?My1O7N zz#QW$4B5Eh7|QK4a9sWRm=&1>Wfmx<<0xJDzx18N)$=6V%z1^UOOw0Lfu@OcLd(wp zC166Aa9jVIj~z7W1)2pv5otDqrVhHoh-5fGvC%BHfA{CKGsGeK(dAB>*Nxy}*mBip zUTx*Hd3B{RSWKsG1`3Ll96uX!!E;SEScbCv*5y0mxpcP)^z)@Hl z8AAT>YQwbhK!wat&3dtuT_7RK7>7mxGy2khK~+nHd|qdl?N87k5SwVo;ErSCuF7W# zmzQPIBSkImx+)sekLx{d7nFG}za)QffoQnO9Cijg6j$1(zX0e&tm&hAdDEWKJ9OmN3`NpdcJo7o%#TO#~g)XJnGLu>0>I`vL3*1$q_=^b|a|06bIUUHZD9{ zeI?Q2$Wpdr=BjL6Hzgr7fRI_Ff%;ig4og77V;JU#ViJrS=wq9i&xEgKH-$&I?NgNs z>{gkf2Io8D4Ub6Hilk{}RsFM}%YUB}6UgGvw_+GITJBBLY4a}*m$uzCg2MOo9-cW}5U`n;OkzE8ybY>vv_{m(9)&sNYc5`k zkIgM@B4Q`~eyrS<0zw+T_PnBr_*0gWxianQUz;V;g*X9d3zMPi%wL*qxCsxI{G8a; zHVXMIfh}7xV~xt;IL9JMywf+bBAS|-5@_?k{BA7T%f&sOoWs}w`hI17*^}3#Rx&CQp>;Ur z4$)S3>&QWe_Uv9lnwlhEqdFtVe>5c*p;mJRqp8_j`M^SRP9YKD%s=YcytF zP7clOOJN%UtnErbZ*c?;Y2i89XQ482r;DEM#z+?OqQ0q;WVhG;7rs4bXM`M) zU)}XVal*ttfBsA<xF;%>0c1IE_J zSu>1P>wu*Tm}c>@RNV5&n;*eV$zBrR2# z7u0JX0J?}@&yC`W^u(xu*9gsd;n9Bo*%TGu$yzQnw=~|EA~r2V;zMKvKzfp#@S*H_ zrFiPo!j!^s`r?Pd?mO`8z?1dR(W%PZd-`%)t`A;P0rchRc>=?=e<1F{ZGKG9pXvvX zYaf|sr$<~(K9j=#%rc}~eawIf;$yUzg_>JDJJgvwDe*nATWjxN92DT&QyCQyEW9+0 znHRSDPgXe;vnb?i4 z++-J@pjK%MB(@dR_#J)kARG8Z8Z`oLB%Z%t5WnBlJod%E3(BeZMg3zQEHv@WC$_u+ zv_f7Fw?eua%gd5(eQc{SB<0i<3Wvy(CB5gxRQ!SII4+w1q+&R;0%u1?b7C1CZ*fyT z2Vn65`7@yILH}IPge@=&mo-=6oo!KUzqlDdo<`Z+4~NJ(9@FzV?<6)6&rZ{S^n%lE zo@)5Sau>7p6x9|3Ut5zF-~E5-AvpfPCBj!4ShhwNll)$@iEyi>h$Z&39q|(EAf>krEGE`bcbMDJ;lS4Z;!u~M*{La`@0m(?H@1%u|9l-yuF2VC~D)H-V^ zh#l_3O)hO%`Az%jDC?C78dYH#{Z~rBrr@N~+5W2Z+Z2$SlIFe-^nOm7u|w6BOmAUdTx{GboOX8ZaQy+CoA|3#M!o;y#mB<4+2g3tSe;myQJDK{ zRzNibpz3>?;@Mcs;La_X8?iuQj9Uu{?1I7Mg?zRrq-#z4U$9!i7j|-|?rZSIVh?b0|+(3tptNap-e<)sEr`JHp8QNQBBl zZxia3PwJCo7k{w&@q>9C!mK3uMN=~}gkGcMo$gpG6BSOhHo&9FP!A_IR#%-05@V3) zi**8BSC-!y$K{a`(o#Qcl*a;C&oZe^m<+tKuv*k&x9bPUatk-rhoPhK zE&uBUxRWkhHD6tq(-)T(OTCTtH6?|RGyWFy5~4^8`F@lJPmRKVM`#YE6T=7kH19j4 zy$;G2IqgNb3@9s7EO8_s@eEX0KbsPMQIKpsN--1K)*o5#a%wngS~VD4@hTak`*)YZ zXNU4w3D7tjIe7sG_!|Gok^AgEYcYTZmbc`8tmWsjuLPw@G~NcDF;?7BuEnr9htmtKZc-@-3KCi;Xb=ZHecOrJt>0 zQT|U?-(*?Qz-ar1i8w7hwNCWEdWfZIUxG!x-F@G%JS~WH27p0I08raeJ104V4+w=B z%jY=H1BnJEElpCWTdMR`E~tqpijMDGs!49&umrD~Yj1)HvnVqEnz!PO(dqMk-|oLS zP|-HB#*v67N4d95rFQ>#(8_mP#;`N)Ec~8uKkQ|$!!8DtIR>HW=^hUo^gYwtX}>s% zrTiHLB}s+cUc7WXOhjXO!FY2)6^eZR2as8!05;w+tg(7%_j-J8_b2s>7hA4fSO|vk z316T$XgGVctk4%mi48lj*mJUJ9ZC!wZAmfoVzs3$k7)9RW-fJX@*w zUnF$Z@^%MUIJ7-{GIcb6*gr7=qw8v@%tfxXUae)r=wP9c=XQS^u@;>VI^KPcLU3vO zK3?T>ORh#}eb)#JC|NpMtsgyBGv)!+(NOGf0S}mAuj6u?veexgf{d`I#IfE!YHMrD z+)^pKtc(uIr4x*xUR0j(L94S`?T3HCU54$aG4lfOTpGSIdg3XMJNd!zMjzL=yXe?3 z^XNR@Q3u6nxX9KIE3%GW#N=2YzWtmd+Ie_nV z7C*aq9w)&_c4dbwv4{_s<%+MvW&_>(&PK#+*83izUVW_JR^awOXpJMDwZgOG1#NA+ zg;#o)iS^62hs&0fqbldjv|*l*O_&qe==hhk0s3$`m{Aqpmbsg9sv~I6heOx`>evGP zFU{~OxC0XP!S?I%$ott;;+=+58jl|CS4xefQEznEbb9cN+@rg1dlun!r=aDnqR%A@AbUVA~hcx0F11v~k1Y--0%|STQ3M3nJvQY=TNQA+MRUfHtD}>5u*?TXyafoy?d+8P zT|;HVcKz&HBW*K}{>~SXhi=24^A&UyoPro8peToJ?hkf$xZ6XS&~bP#s+?cgc8Aze zIPguu2sqTXe}+D|uae2DqLPYf0~iwmjh}!H#291j;09n2Ie&=6HL?S&Rp#b@Wq~F0 zJ#}R1l#q7hrv_0HJr;^S-Ew)W`Q-%QGx|BV38VT`T= zH%hE;cWGe5H)mk^f2oQNbbEh&qKz!{geaV%agTi+`k>MdY~rxzA2r>C1V9!JBM`T7 z>eg|TUi7u#?08w*GaFau{bR8Uq>Y#A`=I7CEBOO1CcgUm2hu$CA{vGj1kTIma>P}v8VuC|&RQXQzR)Rq6i zU=k?iC){=A0K#*_U(VD2617Xwx88K5%h1>zvG*3|Yf!ea#J_LzU12?RAY5>$v8#W~ zuoQ)LZ7kketSq?{#jyykuZk~i`XnhD$pT96z5EjMpsSWybt1`KKG#4y@c7JPc8}t^#k;U0{JQ1(7EIcEPv#xb5YQ_sWw1>};jS z2TC45Uva4Ylx8+*eW^)?L0LP}7s!b`VASILP2cbM$IBfnw-)VjEcF`qe19|z`aW*S zIc_?=`O4M4U&iQt|6XLH1Ddliu$0&frH5)%n;J|HsDgGso0|n`tkP6o_xE@o-_R{7 z2*G(B{FoaR^;aK&gNr3Aokk0pQ*CX@O%f{H%0ve1D$}H0xrJvah zO&aRjNKltLJK|L&T?Ocz)&fr>xnxZEuX-wFgfNbP_S0x74^E8&8~I;Rz@zLdMggS& zdc0%2V|J5nX&leoj!Z?AffTvPu300LP)GUu?ksf_DXB1QeoD^)5+HWhg?tp5m3G=> z9d*LA9dT2h1GDxtIKte?>=oN=P9MV#9`?l_&xM3g$zz*8`X-?tMd<1sM9q!D=~*X` z4?6Qm5#TB!U=6zm_8W%@jhD*2>IUxnq8=&%&O$&c`SlgLQYSNZlA5>wI+60BP3 zOJR*b2gv~o3?MYO1zaUi2e#CgvZ96%!s#wBj8~`(SeZVCQt~ccJ%4S0Ga8R~?F=-i zuz_`>hsQgp!zq6TrkMDoM&V!xRf%prIyRwIZv|t({R=>W19Pz*gSM$TGmCGp)_7s# z>I;8DA)E1N((u;U*1EtbT6FBcH!iodF6)ICFJt>n>>g6^PA+BeVilafsiiyEMq9o@ zQv8_UHVtznk54vj2=ASFA2%`+7zo z7-^_Af*R{ckn z%X;;Q)aa^(OGoE86QQU@(R-!GRe?!sm&J@aPOYlA!(SX)zc}T|3+2Lcl4Z~p&~S*u z`aa}et+ZCpG}hu_CtayBeL&xA{i`aR;WaXUoPAWJQm(tcuXiidZ}jw@X|*bUup;>) zW3G-s@BTC?WigD~p<%uEWwz6gl9gbqEKxML(IeYga4`9LtBn`m3Nm=s&Wa)SAPWW- z0?oOXR+OXIAZ01p)7J3oekt|ZOAQ*@<%rH6Q8El!n7ids#84yIXl+_p?0J$S`M6 z(+_Gyo@t{&9)nEf!mYoi)2R$_h(m-XW@-gj|8(UX8wqoElkqo ztH*U&pTktGy0TluZ~gZ>PfO#MIPm)1>h&h(@< zUxejgjqZ$QlOu$t-PkGkSmcgB?ma2>UqTXbd?qOj?ftGrdZX@Sdb2DJa|{k#9huGN zG}6p)T|Jk@((8?+cK>CON&?0;)3{G0vU~xtbJtCpL&J>-7Et}6AGu^-h4aOmyJeRa zg5#Sum-Pwua_Qn_Ln8ZE2Lr3PGiwent`{-3FVD*H>wDHZi* zXHM(3Ez`36r~r>E!>+v-*VW<=&pjW`d@yYPybmk2AX|zE&Fd>m>1>z{7^Uky8RM~T zJbIHR@;xIjLasN7*Y-0U4#yc{Uy$l+n2o{Gb~+?bueZng#qCB`1O|_H7OEJ1IhfD& z$g15%8THPGaSUz*6Hwlldu1LI%yl*I~FFIRt&rF|IlNMNw^38B&9#h}V z)uq!vZY}!U!lxpz7!Z^OTt+F>ncdS%MXQJ2U*V#!mH};(SKN^USS=GFP_^3;G3MtW z%wm&*aQ6S>KItb$%X5Pjj^&kSq@vTax%;L!%aK$>#5#{NuLLS z<45twavzjY>ihD0L<ijsY}K(t9_qN>r^bW?=%0FQT^g zBVWMGkM9F?kYQx*^JL1Gz11RE`Kd0RrC)h`>6w|k)EoV84XvTla%W^q@q27#wRonl z_~Kr^mQUj9@qV~&@A~SpYs1Mjf_86RCLzww4K#i z{Wx;5^O6hIa!5Y;ER1;h#|Xwai-$A zw5!v?VCJ_-s0;7>Zq6VgJFC8cPaV|0XW%Jji_R4$n)mi18;n`nABnmP{?PRARQ?YS z-`|Skb*Q&QREvYf`(tLTbxPOAVwrgykzK2gtqt41St`HF zO2==id>wtw#UJ;rmGx+ZR>|mUa&#?4)Why>&aOr>rwMJ6X}m zM4pJz7Ufs4JosfKz8YIpOjk5+jqa&t7f_sET*Vn}6`34ZYAEHaQ=9&IyLI=iU}$HO zb$V6^G|aJ`Dyp{a$x(;=cE!5-Nbj=_6~9DbgTGs4hbmF*5?*b6TVjRqZGXQH$5m}# z|4h*nA!HTB}mkz5tUat8K>**R0{? zE$4=$4T_*#rf8iw%}N^6*p8rv%-KB(xGU4p=Wch5!}q_UBG>w=u}@x)%$uy;SeEsc z)-MOsKaA7&441bO%(m~T0*h$v*rpvU6nY9jKv2#diU}dmzb=u^qtjIS`>?gHW#9Wc zO4d`3k%FXG3HMyK2Yrks=2s^(THL+n2)oE=`p7^RLqk%g?D*$819S=Ph!oMWd{~y~ zg@};b2ASp4%>ySWYvn+-J`Q6y?*In(g)Y>lH&c;KR@^GJ z(5qgdhV!@x-nVZ9{W_gJwG&r2t~v0&GJlf~w~$v8ANuL;%@@)7gu4f;$gVZ+-{oPm z*n`jA#_`ZO=~Gc-^i0**xj$dMCBzcrJ=>BCGq#B*z{bKiDAA*@Ze?ouEYVFZLV9nF zHPbCu&V4_EEosf44Oe3nv=if~kwU2S-NehWhs}3H1`$R!j9st|h^z^(; zZAbQd0M4}Y-(`x;uFq$TRV3dipS;rUe(9uWU-;6M;YS|?1mce-i+5x4mJyjANMS{< zbec5TLB3NA%$+r&B{U5U3}BXfRc}2X$eKC#1nBT{k%xgghH}28M{q3+p-2#jlN|~$ z58ut1xn&ygNWS9l&0|xWC^=81LU0?3mX-QlYqB$>#zgqjJ5tHfL$ZV#jutHK;I(S-Bah=Qfp#x} zsrIz)+C@gE%_gqabJ9Dw&x2B>anC2xA`*UFz|PREwR-vefzk(mvEBwIkx^DgN!442 zP1nKtaIKVWL*3NMr5K$N-g+FTum?keQ%y|IO}4xX_i0&#a&ukJEOoJVO?z8ivU&ZQ z?C#0X8sn)rrS7&w#Fup>CA|4ZuekRevq=AGE?y~BU!4JU<|UT0ZOu4GHGE% z?~{s!e0#hR;Hw@{bFT2$dQbRXp-)ytX72K_Tea%e2On(vI`a|yMoM{SXQ>9=`QPfe zyl!`txY6cO;Y#9ZZL9fp7d^$T1E_@piC(E3%X8TNqi z%t653X_45x)0c}Py|y--NRNq0CvMeWT4r-Cr!=)PK-~Xm!uj7Uvxbxghxd%7 z^WbmBh2IhR`hWIJboAsEK0qw;*hlkwAxeyyc6vqJIn0fo(}vnEC@0rj;WqjRxg#Nv z8W^|GUZ%IEEnoiEnklDKG^m5O=|y*^*wOc7&+w;*}?nwdaN924(Bg zMtA>nV5GBuZS)AqKo@_h*X1#tsHWc&zNPI$5uZ*d1VXqkAK7K>g&%Am*hF~f)cpiE z=x-XAyX|cJ(VEH8qIuF#5f-LGv&!7G6O+8hJ8MKD;V&%YjgGaLm1N|IqS+u$t}L+k zr=VRZ-@_A~$r9N1<(;nn5TtmhGm2eQk^(0v_h4SJKjT!dHpE!DxU4t2C`wdsapkQ$ zeaSn$8xzQ`=2SyB{gnVURP(eO_Q83i_L&{0W1i6PwSg(|e7bupmrMQ&B`NUHq!epI z`T*)$RG_p}^C(G-{<^_JbUMc7m8&93e<-2xWUjHK^+c7QIhF8y_k$atbNspV8GFPY zJL8z5&#`5n%d4=EQ|Clo_09Gdg{HwGF5w`AYX1F!(*0`t*?HOhV|mKN6I=w|nu#e0 z?b|hDd)CW3>mE^3ja>zUnmZf~)arS-eEBwX1kVxj(;?&3IZTn&jPt7;sc)aXpftRi zBlqcu)tIF-Mi@mL`{2NDzfI{p#z0~RQ5M$NL8H%OM4L5=IV9<4U^ zAG);hO5Ou;XZ$OXYhqwomuzAw9D6%?Tq-m&`UH8MlIbd5*1o-$T;+h^S~@LKTX!n= zpsmw&);JfvJ*aLt8+6%VoBe7#3>AM6Bs`dp;*DGF3L%uOnq|g)K{iXDz{BUQlF;)p zg-Yn)@cLTaQxTsN>$_FI;b_$tu{L*DI9HfSNI_Mc=(dab)wT8noNtWU;0kYqr3|a% zThoV#eQa(~o1tq;SP42gzUkUo70f(EOF@)-lZS7oarzaBjmZ<6ruDbljc&AcF`EGB zmm~t!fO*5~lu}9QG%Q6TUZdty7Sur07||d*Uxhx)_~U!D0H5cLipw>3!Rv1)@mW#0 z6G7fLKY5`A@U7=XVv57Tm7?E@?3zYGUmtx@h&ik(8YCy9_$pef;#0(KmMy5|L=Ma+ zdinc5V@po@|G_}~0LtC$5=GK>LDQSQvH(MWSRP)LP7{}wt=8KhL&Dp}%m<$bSjO`0 zV@S%^O)i_U347Ak(-l@c5XY8}R4fTRN=v}*lr}CpPWoK#(`NHIQ(Vws`A4%HS^wBG z+0oWyhv{h+18OQNCKOMGXI-v#l`-a4f0;yJRvJZY%Wo>jA9N7D2=E$69a{E+Usgl~@*wE!75^;wr}Vhc zUM~n7{VR-j$Cbb{=8@*;zX-s=8LHMtmbSJz&kDdH2%@_V4`jsSr4MYbPc`Nh1%MGZiQci+%Vy` zt^bNYhpn}!qN#Ql+0b7HiKJ69-D3yg0e81l1qSxK+d zc>+03P!n7I_R)0oU3Bf06K6$I8|?EYoFr?6{WcK=v!=n$%~-Ls*MlA<*|1+kjG!ny z(vIS3L#4iXNu2RTi+X+2$OL-Ykyw)_r~5>{+HR8sIFb8XFHVVwh?p#cu3NCUTf3xw znN$Xgt0hMhpSKLcjff>bM4VZ00u|{FpY3sO{MyXlXAP?KXs_9+PkTyr_oJk!pl&vC zG}gf274`pm0XKPrnV)tEq5a$Tb8^-J;Ro+tr5;@aH|I2Kd6z!cWfRpTosf6!Tr1bV z3AJNraVR#6Qf2f)Y1xkD@buh(BjT-UntXJx;ua(-CS6i-J}!F7c{v|JCVs2(xaD)O z(D>*wOh!uFkN#zEt(9{S9b!3>>KfWTUeZ#SN@a7xxYCiBOXAl!drEe?P+Zn^YQkQb zfVnoKr5ogAsRq-#A*m!T+==tmweSC4qFMW9<^?WVIme)&56OP`rf~^{x)fVjKo2Te z=$_F(*PV%?aP!oVljY5;LU$n+GP}&R!u{Ciz}42qTdb`#NztrUFZR8;?UNnO_O{bu zo1W)iTgmwm#^{T0Yoq<&JlF8--(YEgzg+FUhg!q>;{gEb)02SJv+ph2zl%>|#ZhDn zAUD&kn?aILo7U;Au$|~-kCUCtLrOZj&hm$X$H>aDe}WzfXQ1=@$7^~xC-4yKKK>Da zwe47qaQmmLh6X{qv?bvs#xA0a1v zoFDAd3MP%x&V-3XBVFyv_j;H?HF}RXv-5*AL@_N&iVB9I&`Bi5ZKeJER~n(Ac%8Vh z5#x|nv|g%Nqv>6Rs>q%N@YVIyrK~cIu=H;$Vd#0fd$BT)hUO&p+Ft{}K+T z^{$@sJK(y?wvleqR!hQE7w1e~6X5(UUr-4St3;wI6ZYBu?%M$oM0u%r`D44Ez5K<0 zJd1F3P04Yco0oHXWHUX){3VWZKlGh1eFQbqdIcny97uHPnj#@LPZQ68 zI@|YMyC*-D>MosfXL2$t+;c#w)5I3??PlxSz3QSRL}-Er_0@w>C~4LuU6*?}mW%Dx zE{~dpF@OE5d^>(x*B_1yE$`~a4>nk4{PrkziVhc@d{o_A-iVIg7jiCVH#jCu(4MNU z^CpGM!$uzud{D~;E{C_GD-pYV*96p|2BbvG6eKp6O+WC~SYGcuwdvKCG#bViSaB6y zxxGLBC+<4QezGmlPR>Nenc-ZjTm38*IRAgoc;yT+bQe*5q0SYDF^vb}snU3LlV=2c z&041;9iC_xAo)Z=ufKYh%<{40hV+FR{%)Thi6MF8Vt;^hE^nyCtrylz|G*R+9P$K@ zhY9hcuumBpXnEgMOU&q{e+zeAYhE=GZ_>tMJ1e~SLHqR3>#WIXuKMxAxr-1j2en3^ zOFO*Ob$BbuP5}}#Q(kJ14oBcm&=4ZBU2Cob)e%j&h> zwC5Bf&WB4ubY zn6{{(%wUVFSsnU-e9l_oxb+5~Q|DPL%R(HBd`xw@ds3)c`^_`}e5FRXs*xVgb zoN$&gv-XqE)4rrN$%Y#pIGd(Qo7kT(Ho+0`m?u&=t z6N-i*IfOIV-0?YBR6C<^cmi^BW+oisnxKjuK5$b!&BlQwVp}H%VL5u{hAdnHZ8| zDPz9vyyJX|>c7_@H?)2|*dn9F-NOeJk0y9IW5nrWEG{D0O%e*~fTi#zvGYxSHN1{g zVhl{Cmx~tpa`S0$h)IG3$y43%bZg*gx$X*_w(Wx=(?>pUHnAGPt^pRy9d5bHU{_6d zG7Jn1b7YOOC7#B|iMeg)JS&nziT5JHh^dto^2MXoI!y&LB*N&kmGA9_!m8J1^PJC# zhB2eG&#&5(?fMoH_o&j&gl6WqW=dJZ~@cVI#D54+f$L5y|i*Ht2Z_2~pDK$yCP2Bc3C42fq zV~_rxxt07ke7h#xDYNUe$(irKTk)f?|92XFxkR;meA-A=AUZ&z=&{E?S~zfXFd?jE z-4f=xX66mQayeYOy=^i`>LP~t$))!NTCc@1eWmKha(%5P;910Wfd+5y?0lc#VO$eo z0%Gf8b|)|n?#zC&V^Ocg+ukEI=~NKvx8a`x`CvC}V7e1~mrRAL#(E?3mTa|le^)Nr zo;02=OgRChr~ORY^POUH@=o{f_&bu?UV>QSa2(o&RjJs|G3HKk?u(Ql18fcGmIX_l{>)Sfqu(O2@%7c zFt|^w_j|9z#aek*NNcz9(z=O6P1}oLmKW{foJi~(d+Y~NH{<4Lv6-kj)17osHkhY3 zeg*renW)I^wNgv~6_YxB%TT1{`~WOFNTO_hNdLUpG^wDx!1b;00HB20Vn3NGTfV-d zcqCt}vk6&A)Q{=@?iK-j29*8hQZ7DtP|-V{D&nz}w8;Hw54=pah3jsF7*THfngE%O zx5N00%1w9{lBq`id%fSKgz+I)aHBOUB=~6~DT6WN!1v}C9!0P>W_sjN96@`ItPVTI zYE_fF2ClXwHL{|anx046&Zr(5>?7WYwJu=D#Lr2IK8vNRL9TyCf#73+8&Mf9QDO~6 zHWnz0i4)}Go5}GRaqTPrrpk1Yp|N@O_~T`ZB+eZ^$Ol}S#f?%FX!h7}w#Zu;8p%T#igUDJmA60Rgy~>0YRcV$}+Z+H_3=`~u za!SP3#BZ5aeBm!Ej1+Z9$Dc(7(_h>7&tj*wr!x*C+M%8Qy*=;8q6;oP*#;FK>*H6L z!^k>g@LR$n5|XL_H|ZoN95Y9n-6PUAH{E0Po^fD z4Tc6GN8f4~##I8Mf|Y0W=w52RBem>9I7mT;p1k0@jJ_Fo!M?$r9>t**eATk=F}Csg z06;k-#{!6Am#%F0HecVZt=@JvluN|T#CAT3jQ{)aaQwh^bki$P;n`y!w=WY*Qw?JO zdgC6bvmXpdnWN=i1`eg)t1d+EPoH|i38{4;4+b8{Sk zTGrk70WXAzcEd;zm*lt-X-6}&SZF|8P!c60|0|BTj%pv>GcsXv9hWZdzVeDlM_&0wFCwF_> zy?gDK3bNN)+_i@zYoA@N0F%6Bj=?d5sK~QKXW#9&><(xV?_GabKU=^WQm_at=cB&M z6C&f~9z;hB8F`O51!lQ#UFXUwik#<)pPq?d!|r{+oM!1cL}U(ZvQ5U%P?%SZy0M-U z$nkZNQ@jjraB3-yUl%;YQ6kv*g=+iH&NJYys`9#(UZh@6*ru1F^D#XVt$+$`g3N&+&J*N0KqP0(soV`$=*b& zVB6W>X*jxRQXyXVo={}ovR}V0vzHd@y*9Gt!uZHE!GsFCXf&G7US{^A@%2`C7|Jlq z(mSsr=IN&&C)(q0QfeU}<^~?1zh_r6rH;CM3kqF?+%e7)@Q;?yWrGFI{3?p)$ZY3{yD66TN^? zG=kgnvie#o<2qVNLGn1Lc;y91qi8VSKL}-jlg1nq>UD&tC;g{MDgb9mO}2Fcm!rBW z#(-NXGE@K1vaIo$)_a@oz8nMN1Dob$(|g7=LHBnLUz6lY9yEXV9d%af-bMU)eiJ1) z!^;;+vtQeh3pe8RaRpag+{nz?BHvn9`^s5E&zvFJGGd+VX6@$O&H6R_uKXc z*zM+f)C>(dBD&w-Zh zqpR>m+R48-2R~@a>-yjDy1Xvf;IE^vP5+JGQHW>OQA+mwZPGwl`fOf?dPC+ z^|Pe3aNJRUhVWgW%M7{bW8j~E{=&95BLelLKfH_7+P@U=s+KLBa$<@>2Wxt3jw!@W zQhh4mg=P;QB$m5b?mr$0c%eQebTcp;@K(#w4Mlc$F^%J9-*MBxsMg$cp@m~k3-43x zJil!e7+R!7+Na1W9kDRdzzWChGS-~NEzAU+?{M1g4{yiPnbdSL6tESu8fEI=NkD+E8`D{BYHBET4Ucf~#)2uP`C>`+K9}Mm zZ8|^2s@R?e=n^5=fU#T>zbJV7bjh4gjo;dP*z#o5dxO<>`eGK|`_jfZe0{V3x$BwM zO1H{%SHs2tdxh!N>9u`0)aTsD)exo_x|F#_jRqIjKbsi_`Ni{G&JWE+5K0AeV79>P zv~2eYW_zEjw~8>c7Eb;@y52G>%J6OXmIi51N}54Hx*57dkWr9M>4u?ON;(H+Xiy1} z5|D1`ZiWUKy1QfFKF|Aq-o5r-`y+gqHEZ4XT-SLX=W+Z_B%mauw+678jk<0Z~21ze}(J_pw zUA_=?(EUw)=)Jq#?tw7EFkjl>d;xZT(f{GyRX()hC5>f5`!C)R`ahf|E8g2y`E;xZ z;NP^_erdCm>Q(%XQMSui3xpEPoh3^pEvae`bv`C0fMU9PO^&WzpzvVcwaO`Ys@lrpHTl&xowQ4fWCeSn4S zHz#b=_{d z`_|hm=N?XkNvPCA%*fXv&9_x;UC#l{GG~V@bNBGR%@4X;Y|>|J!K2wJjnQDEQH|Z^ zvex@yZ@%hm@PVR(sZ-=@0FA>ueg_}vDM=X1Fa1}O@BcQeV5uVP?I#OF^>rbbl`^5KRdv7PsA z?bcs47ff!v9;sASX0!_Dw;3;RO-)4KLVk27koA33bXcmyDAq1nu|4APP3_z$PBGn2 zVHRhj4ap&?)&1yV6Xb>!8;hr4Htz(;UC_9l7h)v)v>#Culd%V;mr}TlW9_+?f>gN| zqf5yh|7htLb=PB7*o+ayu4$D&$Ksxv2sFr4MOtPs4ELo-S8(9IdsU`uN{4FiB63f* zDa@ZX(U4a0Tr+{!qiQ@}<<8>5(C_xbi0-i(wnwH0eVg?%LY+@S+uBb}1F9m^@V0P3 z=hJ3E;AOp5$xClUObF+S*p0v|N|^G0u+pb=RoWc%0aDQ&~u*pQbI2n0_v7{9u6!Hv$sr zmQ{a~KKxd;n0m&KOxW-vVvCh3*tB)du-GwjeiZXYIM!BrvXj(ud|zu~I2!njlDtSj z>$k&JrdpWo{wwuD+w<#P=A0D@V3E{uIh(bvFrOD%IFD;gOv>9y0E?dv()!;(9$8vE z9`8jYg~ElGT=|VVCT1S*mmmEW?i%Kg$}U^Tb&MaM;{7(zt#M#mHHfOnNzd=9j&6&O zi~rVB?YLYK%2J9}Q8PWaL2bwzPa_u2y>M*#yDr|V=|Efjel6M1PZ(wqhtOAWug6!8 z-m1mIWNwN!#csJ)N86OGCd13-NelpsJn?_HW~)MXucl zqHm?%2`u-#!8xd#Un6<>B^CLwD?1p#}t15X%eQ{s9$L3m*pONyYVWZL^W!e?gX3SSGclaZvK5s;A? zB-9I1_ihxAo7x2{e3S1M$a#&2XH|C^-}u%gfKfvfqkB^DHELaih498WIjYK7FLWVb zIZLQrx*{GcNd8x2DupdfSpptcZ8tq5jMJ{6A zO0I+Fz}DRiHTYD~Wn?b-B%W3*zP9CpY+*2YH@OF53iHdRe_8Lmy@Uwq)JQO=y-buV zY$TL)p{pbvS#5YBWbUFDUlzz43%J_I^h;xfAd$!@$6>4B=6+-p6mB8ll#^4Jr)*Z_ zdLMM0lg&g`eoX)k$S7|JG45nf*zE;OxP}SmjU`I_-RCOyo(9zmTsGL?9P<9;&zy@% zbK^A8ja+Q=gI5dKP!pwuZ2zr~_qTL+?NZlkt*{AAw;4E1gwz>n2mbBca zw8VI=YzO%GtqfSURRr$W{jiX&^6KS}0t=d(uAA%TZU^Xyy~RW@?l(02zs>Zt1-OAp zo+(}{=Xbc3^Y;Zs-IlobC+nAUT1BY|9&9E?#yjwXBg5G)C8?9y+lLeGmWK%j-KM@| zu|#)z)Gq@ZStNtCsVrv2Z}mDDKa9Pd4N~BfM?q4roW-v&n^=pobt&!5L$iVP-x!i&MgI=+g}QsWlMc3eZ(4^4YDCQ<$Jh>Ctz0(vKM z7D3l?pXK)zuE$~2K=F9)6-e$={K-HWzz#p&eE05YY$X(4_B0UhqM@V=elP_hLk780 zipS9}od4`D-4*D{*&ihSf}Ehgx1WsKTfFp-;17;1mR77RNuDLbV?Z}7tmS92)yY;q zU<;H3)C1?FMW^zffb|8mRddb6y%0o=W5UWdR_mvaci9=o;k8E5!TA!t!P;U>`Zkv0 zpEhTti)edLyRYjHInakyLzyO3qi2Mx3ruq?tf^VpOsq{)mo4zSfaq%aohR^QR=+$H5kMDXsuD4!EITvO_zUHbi ze6+iq*gaWuvoQolg(60KmF`{4G+OibT1DbtcOd)j*`lpI*05+CDsC{T)j%4jq~`w1 zY4??;y`UETEI6(`*_8VVho`hj(}Y;*-f#aY?UHnp>M#7HJ9hmnHkqp1S6fPwevj6V ztM*b%t3=8IgRyz-W*ql<-gYtGX?lZ#{A(b|kP~@}*IULh+o|3BT8yw4>$o=^XpBOk z`wCmI_uFS>=uwoj@vH^V_rHQ@Ap6nfmy_Z>@ic$8EmC_KF`e}=yTTS3NZg72lNOLj(z?UOY zo|z5W*Z|rPV^{i0yFKd|mL`2ucHBgodn?!DjBsk1+YO|p)k3Q;&J9O*wG)@%fs$K# z(E~ja#n!rq(=onbDDwAEHILE=`9C8lCfxwz>&IuCUZIu4 zo&bJh@2a!>UgK`Swq64#;Kz!8ZiTFe+LTVU#K)JdX7K_hlC_(RxBCP4Zb|*b0y%l# z?FLLXlb3l77EY;V-B&*CwVh_OiyuCH6I_7C@0Hth%E@6}Q{i#ELvCNoynAw6s&-8~ zAyRAfYU9Q*Z}WXmANPtm-SvR7@0U?REB*d$8^!U|WS&0GZ;91cCh2U78jP)xQIs^A za(U_bHA#bssfnyHE0Jw&(yNnl3588Y*-ID7t_?<9ynz$~ciV-RX8vX*q~_*;TKf#= zy$V;K3x)7gX7be{-PR8@@=c{vT@T2FziIanrZ7CxEENk5MJKYTa&?)brep}uyI$gj z%axA0hxFoO&Bq&)Zq508b{(^>=;t#nj$*(b4{6303NatwCR^mowM^?E^VW-X?quv5 zBwg%Q1tH^)q)DhB&|*i+Pv(O8EI^UI2pnR!bylyC!daI390rnue1HTy_D#X2cK#TS ziYw`~GWA#T_W>7O=;6mh`%(Q#6x9;};n0gt%Un|qq&a7ihlSqT$N+)0SeaX^)iKiB z3b#YFnTO6$|2x;=DYGU}^U8DCmDDHv-+#|!WbR`7w*q*5`0d|8tRfR_q_e0?um`=N>8@jn-v^JCuB$(KS(-Ju z!`I|~vtd~uCtY7KV?|%lR@iUEuHvdixBqAJ z#=EhHuX0Mn0^y*Dbw->CbQ#RAGb^LggE)F^N2_?rrJ*9OcTZk=uY!emhtFi6^H$mr zA2b{WQj7aj6e_Ct`g{`=7sqRM`jSsS-sH0=Dh^~qdlGS79WzsQIak@7WI6`>DLhK+ z2Q;Tu%bG~!Kz133M3?wj)93bQ%6xQnk0^j+BPTo!x`;s_dCPGjS%sCb^pQ^Twg>{a zmrpSq=6>U-l5u|^7+v2k>we>E#9A1<!H+3?ndR;Gd8C^1`B^6O6WexQod z)L~7JW*_rWyDX>p26FM@*rUcj#1(|G9pbJu<@qSPHd|7ic%8uuxSmw7{(y_-o{_zd z4)~82;3#_Z$36D|*A4K`|FTdy=}S>tIDW}If6uk<*2~hHouKBn>t3$ozn36+*_P0H zD0R0Gh5SyKZkzV>3z2QGp(b`(`ygZRJ4MAxQrSp!MNfL(Bu*nDls*+Jc?-i$mqaW! zys72if$Y1_k4J_ty#LHIcbdzGnU7BvT4&Ef4s~3lhXbiqA>}+6j;- z@snA4Bz1%kW^D}CD-YRQjp9IKjthZC6K>+i2{@40AmZ~jwR6z8a=*o0z~R({1~+t7 zIWr2lw$v384_m%nTxNnwJjd~dyP5bcR#Vv2jxlc^suTBm7JrferH$;(hR#3Uw<_|4 z8rO{e?fY#3N4~tmml?Bj!)ViKJ;vuS`i(uH%@LvQeO`%4YHxlJMVXY4FGn@xoG_3VjEjQIVzN1YL6)=z4P@f&^T?!<2ybi+pgYSP72g?{XuL2* z3`@-1pYd0Oq*ahhW0N_$sPk{HYrZ$fh{NLEw!%CN?M|a~l`N#N%6h^d2mi$He#9rn zZ)L@+WDhLsS_4*MOlH+S_HzS)A{!Jok#s`7x6Cp34s^TFTBC+#%PEs;iIM!C;z}y7 zc|^JYzt<%z>n0DkA1)A(9&%eSs3<`5B%M~g7VU3+S@(qdN{KuDeTcvI)9Ghvj`0G< zUYc*4b`GrvxNRt5A-nf^uGHB~^ByWPlEC}fe05BBODN@cH^X*s)!_d`huth_jbx0+ zJV=t5X%^haGNdfKwtK8}491C4j&{f|^msM^RxJNJl`yD~BAP|38tFh1%O+(V*HoB~ zqC`N~wPLD5jfE-CUV29?u4Ks|PvSAAV8Dp-Ek;$?W+@Z5S2mKR(!7h9TBIQ~Obv+_X-TnW>mai_$J9PKfcpF86b1eEeeh)qma6heLYBBn2qIqac??*gUT8@3#&tO7 zZ;fyhtpQi_GaVB*8q9Fa9qH?CV5`ff9C zsi~cW!Sfp5;9)tmSfP`fRAb7CW0*8~Q|R^P!tqlpazMX+0xBNEk*Ws@#iPO;RwwO- zzeCP?lt}Edfcw*I4v3k9Lx}ypY*B*bg)()c^(BAOTDa+g1`2=2fze3kCbsVAV6IP| zYC2^PCDLaQL!^o!kg4l!tjdPJy7JSNFK#2xCg{2*%~#_mQx3e(#`YLT6TeI{vTDiKse{#ttHY+Q9F4fHQS%~D>gom-)6FUEvaYq26T*FZE$L`ij#qp5m>Q!GU%D&&K) zpaSWXPu{PUG!L+eOEbgrr=0%6O5t(~HA-TIuw-2*6-jnTZv}Kh)LkVS3v-SLJWZ`` zCAhH~Q!B0UsamM(dl^ntEC@D;+ttRlCw@e4?=i;o!LXBbI>u);-Hq>lTwf=zcAg=L z-Q*@0Ds_f-*j4a+Kr7y_Po)KQbB7@Tlm;_b&9=N+I`ktiYdVR(QnhXVMh>wflmf1p zBMZ;VgTPIk zd#h6yDNDAB{1zC67fv)&AUn~ntoX9oL0&;uiMFXNKJdOUC=H57K{#q@MS}hH_xE;) zRep}$9gklbXQdxmAh>h|9h~%fo9!9oZ^fi=^1(IN7lXn^XD*oP#z#YWWiOkOU06}p zPPEoL^72!yo<7M_6j-6mL@-<#Yxr*GjAZtGRUF&`YvbmVcbUmd@f(c*Is=ws$v8Oo zr{yQlNuL!bADmvPdH&^gj#L3@zzB%x5JRtlrD;)-y*Rm!!SbEoAZr+!@U*0>H4v9V zY?PYl*9MybW}*)y0tFMCsq>-A2^)q$x<{U;@s7B)ySH5Y!|pWa@qweJo4qJ8!xSG0 z%eJVIW3sL)9fc5e+QKI}B|=jR3*v)-qYsgHo+_T9pRN!yfQgU^MGOCa6|qrjpjQ*b zn_a~sn_!_%N)9UUSqgO-S@c4VKA_cI7rgLsU5G9$4z~ARYq^E)t;kT%))Ka!-_reI z#S?B`eO~vau)Vwi2*G%sPt|Pz21+L+<{mTHxIcMQC40+CFI*;@q{?G7e`0}4<(Khm zdRs$63J!{<$biut;b~*qr3b)_2oCZ3cqo=c_{MbohT*sJjUd5qty#bkt=WFO@COoaxjW6CP4hN0{p{lyTu0f7z;838kM#3j1odlID>BJAl zPZvDF8LeE#G`rv`mFhokdAM5h0kDu&Sp2NRx|ZA8Zp8K4MKSd6b;k2n4$-%P=YDz) z)w63p3&ESW3Z9b4FYNE<|F($gZJr)SgV)@Q#vS1&`NB$ob*>3y>`EU?M63lQd8pn#PkK2c=tZr{d*`*;%9H!pa7ezZ=rbqcP z)2UlOQyZy}7d9k*&LN^J$&;DvA8i;l8Vq-+qzzod*25$g{;CuERm>aP*>B#Ff+2Xm z!kYV~PvujfW96`yamFRXc?t37kDpS-(BBuj%x2;zF)uSge^ZWCKovniK(HEod)QNZ zc!Svh8Um~~b(aQS<^u(Bb*HKyV;*-~A6~}ONkrE+KX}w#gzp|l>olj^+x<&kC%8ZS=?a7wSduGS5E}}lN5BCR1h;-$OaVUxv+1F}nuqy?jlONvo z7RA!_^b6>?r|EGeV|QF%2WW)x!HNv=qOy$!4t>dxnEMkBQ!dL)fcrBxnv=4u-qBp- zcQ{LjarqTy+m}GIL$1f&%HCP>!5rSO^?Ig4X#~Va)M}uIzEQYDx~fN;32D%@ZsPTb zSz9C8s?9m8^;0*oKBpn>LR;N-h})+JDV!<)YYkQ|gYmyL1G9Hib@N(!r8;o~8)VmS znPeO2TY&=`wfuu`o>?z1S$x67Iq}Opx9V9Xr&?}bkiybk|5};LI`@dxkUdrfU%L64-S2$VjJ#Is7en$O zZ>)7};+9NcsgJrkMG~b-%x4bv$J@qdGRdu~lN^2vd9~RX@?b0IgJtY%Ga2#xT^RQLyXoZ zay6S5z4uFj9ulTt0}UV**P4>lr%q0Ou_pdzs!>dt3JaZ#lD?=VjxNZ zR4|8VzFeYv^qt$O-gW6yFgSkEdjDu9@cU>9aL!9TJkWKp8@utBH9y>3)qMCD8+I&j z{qOjB^-WieS2M0?wQ-e|AQ`tldNW~p?-k%e0L;%eG@+mgLz2~onNSJP(0r{_ zyvbede_;+O!*!k=zli*s#DIra!z(hX2xs{{XVBejwda#?YhSDHl0$3K^&T;X%sfd* zc(byClC>1#;b*8r7>#2zJ%wD_J??7@zFDxVeR~A{+LB7iSN3j%bc&BZRd0{R^ob0q zC7wSAzUfCxT&qfyDh;z84TslpjMe#KR#)o+oLZxgI5NIcXE8eWl^Eqr5}$6F*CF|5 z&uAe5MUn=F^*eES|NT|~R*+Bcb7G9(OeRwAcP|I*?*P}+41gT)Tp#)~a!D|_iMwU! zI?_~?UGGPCcrwU3>RfW7X}a_ClnvB6@YC43k(&ky*jfY+0{i&QTK#XG1I~{3A&_L_ zDpz|^j{y~{0=2ql?L6#m@0EQdU|)&)=_0K4*yMO%RM}iG6w6>(HEICD$Pa(%B)ryi z8}_9xUh3Op?c+tyFRT4mc=&|U9@84jof8^K!^)raxF2-0-RusCP*scweJ_J)`xc(` zLDdHq zQX3#cFC8w#kg`BbFDDv#d3l2mIz>c(A2we~#>U2)#-7GcNVQLx-Q%oCR}OWz3kU}# zTK3M$F$t9!#CWx=3sTeu=r*JTmc6;Pp!)N^-G?d8VkvBeSD3) zl|WhPVULMeIxDh#N#>t}*i{oy@Zj+81Uf0LhqRT1j}J24V6@r+wnF!48!=lo$4lE- z03z{R>!VcTFn7*(eVrOJ*!>FB#LLK-Dw)eW+x_cs%JSDbVBX)D19=dgj4L0=I1&7| z-S%k~2!a`>Cd?05PHmH~2KpLt|E%Yq-S%F`@sPY!ecGS&Orv@DV6*tNI3-t?GxIDx z>*Xsd>Eup@bW@_>XJFZ;*Q*S$SDN)OCkQlCIgpW!kvH1BKID8Cv5K{P%hhx{rIUEK zmiTdEBTjtE2(l`sWD7TmB$Qjf8y`ozk|Gu@L=9GSeV|fqLGuZzt=;bn=tHk;WD*r3Bipj?2XetiyV& zl(k6%6E?^LxwgvdNjl8#Ai!+5_QB%`41Yu_md^Iv=}tYd8S`Qh0j^ip$l-W2j(*vHj+D#L9-{&ukCyAsiG}wO%7^Cjo&l4CwV}$=A-$wVuoY%h zSe|qszgVb$ls0R^_HoBxDtV$MN~veK&=_;npKr_}9xil3j!R)77OyS%Sm8ck6)S8M zGQ41-it#HZB|_xNS8EmB#xX)83oS+sMjJkS&0Ss|7Wp4bqu=np*Pxjv_b@R`_$`nb zmKbM<3h+b5gEI9Am=H zz^nu-=SA2>_j5)GzA>v zN|fnMs&;nd&1*XRKxJY6RLauLz|>hv-m39w?!x;W?)%{$5k{7$vUITfT=8}!@MM{b z0fp(7Su>A!J7l%!GgohpY)jzVY%~6Swm21X0mXl{K^|_AB)I|jRHpjDzgwvOf2Ynk z(WLIjxKhEn&UTZ`WT_zg?{(rG02ib2mu!PC*(@J_4tVx*14H?mJeTkhm2y+y0F@=1eMW=s(6kQHr?Ki zV#CRDYRxn4m$Ez94+pc(2E_nNpM%kEktS9zCRDiltjZBx-xOjhY>v%f4jM+dqxO#H z(-uHkIq!082{$|65gffed|C_`1TR~5{VJdx-QFbB-i$Ys7yDNyIxXR7w}htNHWc0W z#qf}6&1YZ{3BOsnUi}3nTq_jDnh)Nn8D+F>%sS=kRN?hjH&sDxRC>VmLO^US0iwL@ z#jjK+P$8Z)wD^KPHMkn(u!q${70X85MVN#LiF-jq(~~|`>|+P4Vl8XzsmM|%%<9Wr z9zF9u$pTPA5pgdNu7MqG(iwtJ_&ZjC4YVUFO@i@DHpN`4mUj+@FId8${y|(_f{G2Q z+XP)0v#^lfe>Gvzk$<~l7pV!{1Nl68Ip1BThJFz!3jy{^T3$k&!A7B7nL`6|V)-0U zpxyG!*Nf*)aPIG-1#Lu+Di5Tuwe~C*L#$3Wf1ov(4;Q+(a!=Z32^6Yd8g`)%ac=_> z1N^;OqOpS1M?pxX`s7#FuWlMU}-mS^+%?Lc*B%!>dbMXFqf!L(;1xVb!;L!h69a>TJsTA?YAJke(UQMPaW_R4HheEs{~LUJ z(6J-|TD`q6#|ZEx4==27?l```J&F@M=(K)3aT96RG7h359aAuTo7lW>A6K z8Xz%u8+rZh{oA1nkbm`KM0G0yu>lj}sIM$G5zch>Af7~aP4wQuVlAQQ^#N=qoJ0Eb z*%Q>$50M(6-z#d-m&$8#x0;aDf@f>u$5XV-etX}SWSHWUh6Dd8uIv6ZBrA17l7ao} zeBQFHC=T3%vFlIKr@724F-pT30#hm7>PZNAszkyWZv^7mto?zXe+|&^hwr^oN*=@l zV-0;Sugj%|1LyaA0M{3m_m0;$?QZn~lDa<>{@v{o+p<}lt#VMrzk@+ms?|(ukfm0% zrXu5Cl59n19@lk|J4>O}-HUIT`-k-s8{{${@IJ6l^k|!Fi4A?pmaW(F7C#?gX?&%b z;~ug6%<`6ETZ=>FVgM-GloWi2n(*nPd=5T362DC1cmwJs8%qM^M6pCmz?i!RKI>k3Mz%9O{?T&H!8F z{&>Dycl&^~%2r~0Isez&2@9=M=xhLrfhdvKg?HvbVzXtPT}cl8CyJp*ok$8pZF*$- zyts-W`)&D>tKWiBaNA5-^ZaPLOeXbm+~LAw>5LmDQpB9_OSvEhKl(-9z*4XdHs-zN z^6vuRmE_BU8it=2*P6P1>quUrP3lR{Qdc)2m%Dq}B~sJVQ{ABtoK3MF?y!<(8v_2& z9VX+STnaGuzi4edaMq02_?mB8sZfuw>GBzl*31Gk*BHPl^SSd_ias@A>E z20T7yP3m6PV@O8LP`#?u92KMiUIN30x7GuPZx=lJesboFj+E;@KkX}xcLdz%!6f!WAydty`4$@(LV}7LwGxvWfJpSJDvB@vAfL?bpBT# zZrYl+Y{Nvny0iBfw{^HZPu=|h_)TKdWx=K((p(<37_%nT?`jn1qI`uK9WiNHqWVXS zcMM3t7~_=kTXO^P1;9#&9q~NqIMieChqMmc(Cfa^{=OE>RJ|~2hD_UxFTCe+&?>!; z;5W90(*Cv~d2;x@lp6nhsV@Y3k0;s3AZ z9IpYoc-PNVh?9qdIUob%0`=V1lyJ<)dN2C>)vTQzRXbI3Ku=CI`gEt|t-b??cxJih ztOmNdvn@NMa_XFa;@=V3)(UD01u5wBG6(Z0yjP$eid}o9DeFJ*EAbO+JNx%Czq%6$ zDWzI6z;cQ8h?^~xddVUt{$X!*t?2uxtr=WO171F{t#Is_U0 zOkqS&!K-?gn*E@_GP{M3hs|3@@4aD#mB1OlQtY)9b)3v{)CUP98KDM;KetD$&~B9I zx1a(N(D{{))cr)=_EdTIx{h&hGN?O2{6fS)V`Z{PbHc5f+^fQY6T#0X&j^ks?%$4g zA>1*77Y>0hMI@oodG2_=QJvl6P+d{tfEC2y{WFL#?pV+(|xeNCtd;+06!)*IEN+Y6UVmi@KBniLJeFL+5pHwi_wWg{5D*qP$-M=QGnD_b_d0ydIi9aUoj8;Xcz#s}2rdDsA$WRf*#Eh00 zDW$sI-Y8iuugWe_vazv_!i5cE1XaoS;iYL*#U^|csziJTj(sp@@pYQ653nUAT7PU{ zejHuCPa_o=Ti9^9+Mi+k2`z%~?{QB~TdDA37y=jwdY{{yyx6SY-pHtMz4whxOm&|7 zg<=t~b*{XG)#Gv;r&{rs1a_nyvn$)Aj8A;q?Qw+m^tbmbM;>a?6FeN};HW5-Y=2U7 zWbY~MAYQ3wcLVrhZ#L$;5`=yfuC$7y%d;iwb7HYzp37-g;`}zx4UyP%1{ z=fUf1NAd#U*jL8Djm?-GzHk)Wj2E?-kHpO{|P$7Y7&Q_@aLtWh>DYko z293kGf_nL3xOwKdlk|%G@h)feMyCn&pUR&Ns)a^^yb%+Pzbv--@HmbCXfC~j_3?7( zEq3p`iJ1YmMCQgA{A~jL*&)B|EvmB$RW9lcG<*T^X7NFloZXh*I(mVcbwbsOy8Q7G zP2|@hz3APBv|ptuHQ^s3?x)T2at*Ykm{%WoHZWuZ&mT&ieQ*P}10J6^H?LbYA!(dr z50je$J47u&i@up!QV9uYt4O>u!Oe7LtxyP-q^Cp?uW|RczUBsw{`z_qey$RCB*&er z{;-Cu%(jbxhD)nO*1ja;=kovADG2W;wZJV?9mbG+IkbK^$URb18zWzH8)jtn{E7V^3b;x8qNMv`BKzL^=Z=C!?ktGi44DEpR%bd$#Wty zh?zo(JXO_TEBdoo2Gph#HnV54xg*NnPko8crD0!`zF8z@TT)sEaV6Com%rHD^-vMV z$-3(HFZ)Et>(!$PYNiH^^6vtz0;Wm-zS4;i$qp7d1X2n4id*i&7N82lcy&d=R{XfX zTb*1m!Tm91$ws2S0o=K?4_zng6x7u6G01R5MP(6|iiA^IDJY3^)A|%}#$S`_R#@S4 z)!$Vrd-87-N!<+C(U44P6>B5Yi_5!L`U$k1D8e?T^uLf-63r%5u&g{sRRJ?tuUL76 zND3@qzUc8d=K+t&Syw7aBDDR#)-(N>K@$p}VM?uomnv7vDcwNErxz zL+StdcO{r^8#x-Q?grT#uSNf-WO?$$z(Q zTD&<6J2Tx*qAu<3rd+uAZYp-J=>(Y(052@DupwoqM)k6fOv3<}1FSUUbpWaS9JxTm z#0$%x?AdcgWxCM~sT)M%FC}Q0ZewRyq;3#|k!P4B3>cr-j7e4E?kcm+Qqwd@o+Wv2 zfOK4=0e*L1k%Q83ojM;Ri@Kvh(4JRC7P0$0Y4qH;nbj@suia3=My^QR;}aamc+X-C zT!ykJws(Y9Nx3`sW(rga{O-{z!m>OYsCU#o(e4EC6c;p$;iNzXH)_o)l5-&>E*_Fx zs4k0W8>L^Hpewwh%?@ulxv_^HcabBfYM1)y?g^z2>-_-9wYzo6b6*hAeUtqC`_=|l z#p4>9Zmlgw8^#vA^=uqZW=#M$*bTERW(`hibCBr@7~g2J*Jw9vq404(fB{mK*wb>J z_$dfL-gY)qJV8E8ZW?nZ+{4S@t`xB{a(ig!90R%RsR}tab&p#(4o!DY>jx0e_=Q9S zo)GJl>I4H|T@fJ{;~`?y-OB8|X$z}CZU%$Xj4ye*4Nr`Hn-3sOhY07wbW-1~9Ue`N zA;_slGZ#x-e2WZHy%SJ$(>4j9MeOiH`K%jk_ zAPjzXkUo?}NHes0uUB?tJ4)bH=j`ir_3Ql5Qg$`jVT z{xk{S06sJtY;h~H-NmBfD|KpZ@{rpbmzK1J4wKAh>gT`(X(@n2n3KS#e}Qqr7YnSW zL5>Zx9X@t*#v0#^ zQVX(TopM>Y)DEFxp|TnF9jt3z^{Lt<*4#cBCK*PoHI|G28Mga&DG=7|?@~?q2EXK) zp>6XzsE@b~e_Y2}#%=chd!y4rq7+Zvj!ck zeoG)#|(&3tPE=}a+FAZ1|vyXkWppoF;gt1D)*y-v9}Du ziYqGa@MY>Cq}%j!Sst5&^pV)EcXJXKWMi1*U$0reJ8p3pg#zmQ)f@DuF#%(SKRdKt z-jvp*OlnKa>MNyGuOiWaH0K~{4*S{L6aLtfF(t3SRmAY!x`5;>mmv6=|LfO>z{Kl* z_24q|eL=&fNPY!6)`rK?_PtI1z{JOf^3;O7*l=x zi#fa8NPdS%*=;IOJ6nz3BFQXFlam*f3j~V0`Ov3Qn$N$zd4+HOhMAHhn@n?*qgVPV zdNP8jlBmx}rcy*(JoLM{A1@_DR}2W43{Y_FbAAf3Vq{nXKd+VmjFO-~2(I>>8nk1bh(#M4?biAh6VEe#LBFQhOSV_r- zAH;#qVNi*RvAd0~6DAB3gBfq9>m&}lqibw8lnj$-yfo!?BcK)u zIvz_F@n6Hq+>yZLmy4;EzG&Eg zXD+$&vD855b+2f03{M z`5keG5e%Mn`4#{HsW=_S5taLKjIN)FtxwnUT7H)5`Z9Se=C4vQDU*+RK96Y?YI}L5Fh<5vc@a~J2f)Zy}e{mm^~`V|E5czxwQm) zXKw1nwfO_%^nl9Jv&#k`GZ;M zm7d>(m~E&CvLE4f7XTNkrahJ+&@L$z3)bV=7dU&Fqx!|3rJ2Lke0kV z&;b}qR^g5b2X~#2rbmSH<64i@BfaW#T=`+Btf*x5?%8A^v=U>RU^WCuI29|K7a0$^ zWemijFFL}DOd1lqZ)Q&lM^n=rx_*LBhQh8lM&1`kz46L@XZ(r=oBK}l4!UOWvo&zi-sev2Nn-91ay=4Pm>!0FCLhTp2YYLtVbl4zce--8F3GZbe5OS$ zK<*ey*W!I?hS+yEcbuC0?StlE=kIT!Temn&w1yo1%mlO7h6&BqPea7Q+8m@cEDU!? z>q->(Uhj$BVAn`^aFY?@C%yHAQbIf;FjeH0Ab$`1T7pyn#vC-xA~N_Ka8XUD@;?cs z+zpEj6F@6vHPCyqDvP@}bN=jt+8ZxHGEnMbUn-~$6Q=dj6nQh`efC#kOZ{SWy$|5d zOSK460yU*D>NujrNI|2-d-$fLzlF=BCUdPZf=C28>HB_UaAuk@y959Kq}&`?F#oKrLz!>&hGCDO4*+=(q8ZiMgAZ9{#2LS( z(cL0HayR^Gf9llu8KUe6Jfz}=J^ozzZ#%_v+i@w|$KmNWR{iDO{{B-^B8~Om_2gu6E!WNM~F?J#VxG^v(*C_zmxT=jl>@e2rs zb#czU`{MQ#DCvQSyYt6bEB}_aJ920k2#J@=YDeNKUrn3%8(NN0|80I5n@o zeE1O<**U<9Rk8l5Wx7c~i7V#GtlVXi_ge-tX^|15}@jJuIl% zZ2_DsE<;-?fR1UR+_g^RcFt;(-+eM|^848?mtEH!V7CKR1C9ov*hkc!FjFX=*4B7S z)|%(p@KbThFXDl#tlcjOl7KH(YQ$>o@*_^EMuOx#(}yacC56T8QcnYEoC zq`>-M=taC63{N}e|7K!Qd*W+!^onF{665+u^dCfvqz*Xb#45x!OhBoI-sF|0QN=Ub zWbP@;5zJ*JLGE)^a&e^w`bPEs&7;h~3x~jj!b*MqxMm7perq6GUW2x-GkEIhGxR5& zVA3=9AjUrn5<1W*a(K@dX_xH~{MCD+Y@)bgQag}FyeEJ2>dj34Eptu+1iAUtL^HEI z`%E7s$>! z)Yi2Ps|XfEJVz7(0V{|ID4|FfMFA;Msz4G@AV^nwN3bJOg%Da)dJ96Nh3Y|iNN52= zmlhJ55L&433g^C`@x0#{@AvBrkHhS}=bCHQYhF|PvB?zRDRTdz@>2+2!KcF8=F)BZ8#~85KXqS8igwP%Jdh6DxG37`eutrB$GnLs)v~ka?dVVE ze6BLPk9O{0G|}o@nS_=fPV0iK+*DC^;{)BkD9HrAwXws^=6sI(kZ&$FMSL9)yzF-= zC-zchjG%`W3};eTw!l0Njo_+G9j?E@j;&Zd3Jb0`o~^%mPgAt$@!UO_d;6*DJKe&+ zew9DJbE!I{#J^f-?a|NY{h~hh1vO2{)oyBcx+{<(?)?!QYWCOe=G&P}t?$?-^68&d zTj@~Siss(30uX_QFIzt&RNwN@nHR4#emaAaXqFdHCS@$aQ9Kjw&8KZD^XbJ@Hp?|# z>rWT|-*R_QJmC=VF^^V9nXmh>*r1St13ab+#;WS2doZAMywlsQ(2*Az{`pt)ZV1Ot zWvG&%fvFZ$#xK|eUrF%F>c~!lRw4Rs%prvSr|GZ8LCvE7*djX|?Jj2iLOnsgiDG|s zBJ=&^W2ev^xcx9v)XZyHSE=K8_2=ypm zo|(q=h8*`7y`N&wg+}W#+~LKL7}Gz}I4yHfZ-bDH9MkyJ*dyK_RkJm_b-2-xvcIla z>)FcEo5L~ikt9U_pNiTIi*s(bf~GDm@vn|%?X*-bmI`25b@`T4A)>>19WEv3>mQlA z&Sj!ho*lg1am1-2-eV*IPq^k_9t(!6z6w6l3^TLW;U(O+P>GgEprxEi-B@P@VZkA# zBIEbRzfvzM$V8xL0AMchVjL*I9gS@1gPJ<2{_*VlxX3Eocd=7E!N4E2r++>@f2xzb zX02Kg_(2AYj7pUOI=Vk@1MavH-Yhn|%?}>%>RhQ3xYWY>lasc>gO=u5+r_8yF053} z%Ue>grcLcOeIK7=(&-LW9xXhcH8PU$adw(4IpztCD2-ejR60+T z%-?xVVK>8)Gc?3))M;nVINd3%6cj`pm6kqsoa^(D%iWyCF5}7u#S0&DA0wlBs*sJ3 zi|@cRwG-KVpsY^rU@rqBb137vYXJ_8$HUmy9)4SDun{Pj$>h zYuUO_$g)z~n2%f!6lfHPbm@SX{wC zenI3GHf0usOV8 z@HOVvxg)2GVq|bWe&S1_BOvL%@H)&sc`Jq=!{F(4hKvug7e}do`uREdotOUK*|O|J zYoviS7Tr)04Kq7kK7Rmdi#U9K>b_s1RL{&(cW$Eyzf1Koiee_Iv)9_5 z=uI9qhZ0r67?17+EGfTd@=tZSq*y`3k^W;8D-oRa7TW;RWixHEmv- zENSv7oi7Pd8|js#i~un4N?#s^ttEmkLC(mWk;zKMuhzeeEZndOt~;<9IaY|e1ab+c zpqzm6h~o7Tsb6-(Uoe$P4%N8@f8{{`g{_0R$sd8nfJA6AV^!C0=wl@j)%yVEez>dq zks92$)f9$LALuen{=K*F${MO$ooV{2gP@grU9UzXTchgL%_!{*geokoP3i#3_I!*! zQ)6r*)+k8zF5=^*2ZYkTNol~r*?lvj^r+tXNSnwaF$-B%uWC|3f~U<)jjJW=SOJ)q zRQD3rduDK8`OrUKU64I@lJC5NF=Hq^+GIzsN@dF2-6e|{#GfZRV>ffBV+cq2{hQx} z+|~I-I*=sqdi$P%(v63yJTo4@9?4Tx;|3;Mis+x@GB+QtN=3>V)rQaf{*+PmMA5{L zxaEXgCuA+Gzqa(9x70WM>usV`v&sIJpg+nDo3yYa_OQ|p5_RY7yMx9RB;Fccz+~!( zmk>)2Dl;@AQ=f=yK5%ZScv8c3FBq5ryu4@6nyMgDvNqqE9@b zA3d*YpK%>$fZlM*EV8-(w8`ZLm^qPgeohai z6rZmHNf#=^W<1I?$FQnLme56Vq5!;d!1;&sU(+WZmBsxaJaKL}-Ej8XZH>l={S9-h z*gf$GBZM=^EH$Hnx%RVaK?b$St8AF{U+z0@iDUiGPR)~Y4g=wh)))a^#)gAsaN<`-qzWu_9F0Pq)CSG#?3O&K8aW23(=fC?Z;xGk9Bd(G!uQh0F!er``_vkn1~$iNodZ) za%W_|X>Xr0sGs#-kL5W*m7+!!NW64^_Z<^|Hf+A<2)0*7QSo?n{m=Dvo2`p~!DB3< z&EM+V`voiS7G?i)#5g(H)!=6UuK2B7Wfjv8B>FA@4i6w(r@5m z4kwxATd%^B?hw}j+Y2#rcYSkAD(jTterbTq3=}!uc{5si*MM$)${XHA zxRm*L6=tzQXjMdJ7zJ`kL;hSOe(CRO*FBFFjhyIS%X41V3IMPhZ4dWr@Ztl03U`E{ z-XDHNx?HMdUqXbqNJSPyC}@%VqU&lB@X}W`F;R{Z3P*~~6bd&SOy~tB6ub8J$IlB| zB|OvM^O~hrQ>FQk^TkSSI%keXBpf+5)A_NGmNKU>;rU6le6AQn0%MuG%vO&%tiN8_ z<<~t6URU!rU`~^Vb0ri^3G%^M&!j5g<|~i?nO`mjZvHoKEgO~o!3RF1XxYC%veHNw ze{Sgfzqer!$$L;=>1ib?ytm4U!!YhEr`+KKHhU>U zD=;}#!}Q@rrp&Z-?6t3gTKK!Fle|1f%|;UrNThbqxlJcvn0L;R8jnsePpQXCN(XGO zm}bEmC3a@(UEjzN`Ooh@5!Si@1Po1!|n+Gc8!G#}5MI zl-R>NUZ*O5=#f=;TmH&d>}|HbV{!D1c2huLEvi+7c=zo~GHSf;%~1ssp-W`ku8R z{t-_&UpwSPoU6v_r_>Tn8 z>%?p_%kN5O-?tsS@I~C2C}DdP*@}_A0;VfyVZs+eAEGzXndw)nH5BxHk&R4FqV^k^ zyBhw=4dgSTb&BYkr!$vNRCorLSwz*jpM`q+Yj{iBr6hYEO$~baJ>JTB`)lF?XVvtD z5Es4Z*%OzC7B99P0L7@N`g|Dm)4Ll?L8R@VbBo$$4+=CkM9S2#lJ1J|1yO2DT2bps zP#GGOH--B$?kc`*bhD7UNm=og<*PLC{BJFwER9GlQdAh(!t(<~ywx3&&UU_2pae*1 z2uSH6kdlMG11U4>`O3wT499=3{yw%#M9QvJ9R8_*XA5txb{C^Ug{#SD*ZOk;K_ zDZ(;1`{Gl#-{I3wJD4;Qbdlj`vriX3btsmI@5WjM% zI#y+xm+Tg89WyN1;*u3>-P!!a=}|3*&S`Gky*B{(?L;Yl@0T#l=`*QZFew9jIn`VL z_=d~W=KeJ+g0gc`9KQE4vYV-!xO3BMR-@KZzx$GB$1la;6sf?VWG=YuD|`iVDZ@HF z%l{dC$AK$S`=}5~vRU8OxDdC=oWO7g%rnF7-I9*W2qt8(J&yM|3A*d5URILwuYkPz zXma)U;-s$JHJHv4pGwe)px(b~spZ;%HQjFIRhCo%=;*|5Xdf($Os;GCx1p{`iRsy= z>5vrnlVFXsD>V~MxDaq5CgWJM_F3D_1fxWivSBAiPO6y#kzi{UhrAS<``F9RInlDl zEztK;&X7yQwYC$*ZXXLwI8iVUvj7!W)WNd8wl65j=|B%r5q$Y-BB0V;{TS)}b+Fje z@KUD25v;@8&x-7h95F)|8V|J8JTVVDXTh9w_{*J#m*CWYZ?a40%m#pz{OCbPi7vjT z^NX%4V|9+sdxM$JN5+{IT@{1G#C~e!l2ybPeNps|^|Ug8ktGJ$~0cPff4*J>;dF;){Du>lNQaX~ckmeV->)AKC@v zzz*$G%btL#=FCiQVcM{<-z%;B-Z9yIY^a|b3axEltt`^6shx^GqXXSW+G4i=hJLBd z-p&4wn9O?+$Y!bbU1pE0oCl4+ATR-&5UJK)K(7&I&Me~G&UosEULT4la5c>Sb zmeceA2=kOPHSdSF0>V(Yds zYVHB7L(g257Q>pxLDA=vwEgBB^y$zQ2L#!~WsZO1(oxaso-8#2@scGHH*g{F!i%e4 zJ=AR;c%4Gx`gEES;+SMV7wGFRvgzXiDyh^`H^MP?=$HL>@=_Krt(jNt^vXY>jGcP) z1XPz?etwike3;COw+76lkF>|~x?#F-g{D?H@xFM*Pt)^|UPs&O*4twD9FY&^Kk-?= z=roPEJDD3bM7K`t=SKsyNRw&_HMj3$EHt|}3K}(%F;gSQq<(dT9sSt(h?%Z)6sXYB zkuLT=cqV9+0)ECGCUQyKi{w1?5#UKRLVDz?PO1@^OmzzX_0pAl^_9a zcLSAnD64CC`Lz*hZkoEbuG{50Dy0!Yy3w8dTuR>$#O0SCLc~3BJEa_)`d9AWZ2uJb zsEP2Pn!qEKIgWHMyUX9+n#l65HOu-lbz4I6tKOZ_~B>XvyF`Q==7SkR8cuv01hFu6(*<7QCnG1su2BZ>KZ zR{M+o+Kn)swX?LPBmaMr8DVyZATRSi05sqeyd9xQ8FGTz0LmjDCL>BVzRHR>7jxk& z;*!e@aXEo45f#H>PIT;i241A#&by%KVN$?G1UDU(PPlK7`6JY<+S%mqn-If(8I9G< zkNge!HK|#N?Gi4?=v(mzyDjfn)cjPR000904_X?wZ%;g>e!p`mrFbR&$-P>%I{vVG z>e{#GjC;po2fdVr*87K!XB>7a8~AYWQJ3xtLo0Qq-xBfx6sUW7xPqi(Ye6p{fwIhh z-7{z5LS>7kej8ucXLJ()~f?qVtpuq}K26r%IbvcC<7&>ju19U=lkwx^@dcSEee00ga_0kx7Q9?kKelq& zhm74g#YKmpQTFVSGhlZZ&uS^%s!eZh!{Hr-2lVwVZX(l}dW z^ozt5fRH2TKH*2YSX6Bnd640+Fm~Z5QrMTqO<9dI&~)>5ZBluJ9~A`{95BC z-u9BU*(mxNP2aiMt+JiaDt|Jd$_?f%h8YDR$U!ior-0PCRKPH_bsVxH5cS(0U7&JGOZC@Y>wZTf|L+8yHF8Nxfm5k*X*(}WCn13V^= z=3X{qP2sr8DHV(#e4Kg1USF+xWZeTxI~!975L{PpnkG;@au1JuSI=$kH%R;=ND&DD`IH6ML>`>NQT~Z3(SgA>WWE!_lpsIa0=rJ?3>_WJ%I$ z`BcYbx(TzG9bz2C0qVEk@4laqhP<2I0d3&krfHKR9uK`()4q~-GFiFe^VyBaV%f&= zoO#uj9t=IKot<{3FVK=-sv0vg-Wm-C&0yXjTw1%6h?!buWGUpRf;R9hdyf1E7sWqM zygr|=l0vQ}Rcr#&ARk&04vfN3Uo;@OAwMEhOVd9GXajVNy1cEn`g2V{rnnPSY^kpn zT&uX`82$j1@!#MBc{tBkU%ixo{wV{(vn)1FBj7e5IQt7?|7b({FMPWS7C)rV0yrrq zW{HiXR>OrIQa{?Uk8wMI8R|ALcbX9H^dcsb zU>=hSpBChwt&v-(Nol@xII;$P`Buokl~q1I*@%sOsIZJj z;H04wrmAS<{GCe~7g}=XtlRIq0L9|&FM zSvr#ADv57AoT?Oy1xr2>WBbFTco4OUsw;pD)CUU~w?qf5|J$D1wy9MlwYw^_Y)~?p zWrOldabjNazy>AN!x}RbauoJ7z9D{@qn?HlFsj8y0MhLbZ$vbBle7L1m_ye$m0wu?cO zI!EUJcS&}J5?ID5|EK?kN&i@B!pSpG7d!wHBG;nr?c~P_zhn z@9)GKuhWKdnIjImQqb#=zkgi=@!PAXPD{+7{UWLE(_4g|Ghdb;Na$U zR)T8qXD3$~;=SCQeBFgCmOKE=N)pcVYMrQ32p7RrO7h$c%2m%%Nkg~{A@%Q z|0LAy_3IO_J#=&PTtJ;GRUUPgl=8u-IyrqUje3$Mdy>+#q~2wwF_uWp;1N6ZB~C)j zV&V~Z#5s$uSsAf72_Id*Q(-y!ViKuKVKR3V0iC|4xsa>pb1#Zr6uIosz3IeVb;Y#zxtVAYh$bZd;&Ya!h1PPgtbn2%t7V7w8k_ ze&5hSsZE%SWH342^~=qqlGFG%NEpCd1p;8ft2NtQEz5PTN7H)NlH*+fM>mr=7TN^- z+^!RTER=d5+DXDp_0VYL6;V8sq|1daSa6hniJHutmfD4fGtIQ`w})%UU@l~2Kn1Qt z0Hs*F{*0;|hodUm>}*;Tx&fc{Ug{|-ivYSR$ATBpQoG7fua$ngm4f36-7{Op7-~g+ zW1g3+RLLeSH@eYA&GMQ5Vo#~LDC<^Vk&nYxjySjQ*u!?fXq$Cr0yW*OhDrN%kEK3< zh!qIkt_ZD{;|})u(5Iq_v2+>-5I7i=glBh8p4@1dv^=b#ST(OZ9!GsXnN_-J7t`u( z#K>LA^`&yrWFZA{uW+BFH4vBE@5fxVh=N|n(E@M=@{re=+W?K8F%IvODni>I*Nucg zKrwRZOYr(d;q{%!?M_RTeM?riw;4iN_)P`a@InjD(2A++xVlmy?050G;FsZ9bisn(4Cr_T# zID3h`fj9K~o8=(cu3s=}_n9vy$K_4_TMMw%TgzH8fG^%m6|ENbb=vF>P9Obn1P5u! zMOY_coASf6K!x-`(gw22*wT8dq%x+s{aB>)2(w5yc%(4+#W-0s%)Be>QP?l2NM)fz zW$o2&W!i07O)oO0f7|1u#g+27{=lptkQ24X{a1bFcN8&Cz;yBd_I!3lY%8zUuIYDt za!`E6GOhwGPUBMoYXPW!B$y>Hw={^dG)VY>tzy=_e+P`!_@w)gHR$GEHdG>?N;=Yd zsw>$;e{CEU^t*PulX=Up7y)7YG){KpOMcHZj!o7vnWT!|p#zqu*+^zZ^@ z!QOCj(EFBr_iKXmKsjZMte`TIF$VVLfP60xFkP7Zt}xyWa3Y^Lzjz}@(h{IT6^WkO zA8Btrs;JFi%WdyXSFHtIjlNl#hvYGEDmD7P(AqbqqLmjacZVzsXR6(DYBKP%S3z@X zNnFxLKetWP!onS1x=b1MjS1~baE8eayTa(+aDxXQjqvk9WnhB;`C1>7XNGE;f1J@? znAZuGKZ4gi#ClzYrw)co>@;9Uu5k)x>5)IqQFU0pnrxl}^*c(^3v}+S-r z1-oTmJC&xERd&rpu<)!p;IeekDXfRNsc05s@1;bxIq7?mUvU85O2%52&L>|M` zu^6!H(|08iAq%@M{yt}!$_e=(W&0pyyh&eWJuP^bI=Q%77h9bRB~^9z)wMI+wnK)Uo{gfq;(0 z%TRBtFY+18@VvG?kyZA5o$&w_2UAbVZGKes38N!gWQ0~br0LVbwb2^9Y#;N9s`kQL zwN0w!j@jj^j_cwr+4`2UWfXU3CW%8R*lA68dp&adEyh}6F6nFhFM82m0GE&7L!G8s zR?(r(wBzJx$%+RAnVON|Jxkvk{r|l$EA_V!OrPs7&G333Pp+9TkCBn<_Fmw%IncArEeoEv8= zH2MfUisBtowCG1+mN&wQsyLANd%-&bYEh%0bz!5N}R;p5p@u zv?or|J(#Z?V5N7S|8-bfJqXoBWg}}dz~zpEfbB(^a2I@|(b|oNG0VeisNlso%)@^; zkEF~i$`sDT6l0|RF3t+d~B* zxF756i)S7Hf;)RBFz3GgE$YU$gX|7V0f>9S(eb2#Pc`QhI~Lv;Qwuk8OXX%&QS&;^ z%zZzFZFNj_v%3v3Zf5}=QtNFxp!jYz4iHg5B{-yaoY4fzb%O?oG=X6Xi`@EcIlPO) zY}28Rccgd-P8+hNs#z5GK%u0_o*Y@Im)bu!`mK-7`PX!;(-V47bh0u9*AQoT=;KNH z6CAUAWj(+Y0YqbfnTY{9C(#T>w+Tq`!o-VvliB|}W^f+_;dSabhy0}Fx8unll1MOz z-pOS~Mo^z21-d3;GF~j$`WIg`&xE&F_0h@9np~B>ge4@u1uw=P-Ws{yEF7@PE?RA# zV5aTXt~DrrmHFXUQxL3V8Kw|3k~H=lwFES(oa7mO1n?vqq^r_Wlcth6hp4%E1+wWu zEZqe##ltbfn;u=_W7*o0my~yYbqo9Ms_k;CrFA=CEjAao@t<5pp8Z@DL z11zDk%VGIeV`gvFCYhxKV^w9ZwtEiQ@}r>7EP*d+Mtvp9_mv-h7d1snca$U*w&I_s zrU4w(oGNN*?T&ue<^nYNW(JDmsUTG%)hA%>t+v;06lV|O%9xn5XQYcitU^p#(lWPF zB^Fx51D0*Pb{o|9Tx&OW;O3X2f!L!4J(emic0~<@Tb8BQlK_DjCQWg8dwU{)u}N0o z+{x6~%X8;g^}c~3k=@$>-(7x#Oa^pvo8t4XRcAH%{lx0s9>SqxpleSjwIQO_85Ai6?FR#6mOdnCwPIh6Es;c6#wf2B1=V60THrsI170`B*yWu{dYb^@ zT1`O$+Fr05PpQDkM)xjq2T!oM?*0Lm1kqo^t$iLIOxCx~!7A@D3A2a>3vUO#ebRN= z5b#l(#^pdaV0F&WljbB$I~8p788<-Fg>(YD1nprp{|V2HCT}+yIkKjrK$YUMlkj)*uI(n(03CHge9c(y};Fe8lNda{|RdZjt3W5U)V&V5;Z( z$6&sWQSo?1K)g1sUx}Gl(_;eD3hXij3r4%k18%24cY?An%C@d3f(7)xVHp4_`~wjE z7rA*rMH*I?SrNwA5fhqfIs54FwpuimSS*)55gpu~4|fppPy z*`ht^POu`gyFvRBX~4x@Tjr1(xY;0B!$-kZ?p=9Ym<4vhj`OfwqORr~UQ3u(IS4tkd(i#@|5^5WV#Ck=7kKTQQ>EXoTK zk#9)5EAl&B)RUBt?l^3rrdP^*jiMOl&iLydFSx;te`^ZTub)KpSd!!Foi(0Vd~Csf zFb$;n0MWhKO9Qfsf#VLy2V~sPBEYJ#@%X&;2H62{C<3923O?HRTLo$|d@T($g!)1% zhWB+>8Lh=-0?A)(@!qf{kFVbysrGc&@d9g|z{=wTNK3 z0Y(^Tz3xiu`5D8W#axB^sIKN1rmbz)3p4AI)RrqT+QACWenGtpS!)9?H!r`&FD`MC zf58H2H$VPmFruqi#Mz^H*p8- z1928_D<T=gE6AuX3%ca4y|xooNkBZS~U7T z(x1Bn8uW!URqY?!#Y#(iA}g}igBa7DPI7sgM%bJTeTquD8RA8q`lr! zFZZ^?N}KDRz+tyoTF$;~C99(%F6g5wU-CLU#aS1wyizf5pqEWA&ikXxG=zHzRz%lY zB5DJe>>oXwy_!+rFCGjAVo7(eHho#_-Z&IARjbh@Aa8i(mHk-mNd$l~>)@?=M^1-K z(H0kOj8LPD9^_;?7|A;mRm=`>sc($SOzqJ5*ti+X(8%YJqlZU~LMX8uROCp^w^{n}xI(D3C zs8TY?qIuIz$SbtOZb80acXXM0`K+21=Qq}_qkY2Pku6dVho=18br}XjylSSFiI#$l z-6D6%ikJe;Q&`9~k=rkYw5BebR~^$!*mv#~SE***o$!5p*4;~NjV~rSI^^DQgfde6 zYnR-Nwv^U}(Y|!$+xQvmyAqQvf4hmeCDV!*LQx^=z009(`hGo6H=dDmUAftiFG}*` zRrnvo=4B4wNPHGiQ?NU_wlixH$=jQyBPD$7+514B^)aY>*~Z(qZ@EWy-Y)F+j@zzT zL{@BsV>M6KKqrZXe15m&6lRDz7-W{k7p85UzH?2@sSy}lHT6OIAZ@caK`g+5u zEVbnR2nt{{$i%w?Bqew}SrJPTD) zQQdEXaBUcZm{2V?`T3o@2>m-TCvU z0W+lrQoHHnjZrix&sy!3y7Y9DL54R3rCN|v~)_T;`rjl zz^!hW1M)GWR~lcEe~){5e@SzYu{TA+Inoa7WxBI6tfPi;m-{m>2ei?9Esk`^MebQU z_vkQ1r-E)bLbl)+8ch?iD?sskhH^ewHKPX5&Ab`LZ8dr12_0(IuJ$&{a&tg9U`{q&qaUH?wuxu&LEyh@E{`|k{-1jJ4vuanL1 zmPD~78SbSsFpkbiUU*PVW1X#h73*w&OReQbuI{`kWS$>XN~*{o^2+i|RX~TA4BGqL zisXMr2~qbm8&A2Lim^*~k%-03`(%7^9h(VWlpoopE^N;f?({)-set`;zIN;C_V^)q z`??U#v>hSh82GB?02Mbc6R2#(?d`LbAiS&5S5>i`Zz~P%oyzA!J)x>0F3^-)q*Q!& z$B+28Bfkl{-o&T45K5i+U>(fI@;6GZFrbVJ#&}uoE$42w`NbgZ^m@B;SmB#6XyfP3Zh3lJ&*ZHVmx?-vvc2UdqjqP6_QG7!VgW`(vNRE z3%wRN8TaNm!EofHa#koc$F@KOT(Fwt)DqoB^LuP1miE(i3l^$*3f!E;1FO&GI&Wop z^P7E}{Ox@c(wze72iEIPm^{#zqyS&{W`X`XS+xj%yGj^&S{)lNWYms;-Ybh=bC?KW zntQ95-}U}$Ac=-tdkSx~8{5Abv8cY%akV+yv&6i(#J$Du*?cM@Dl0zcr1+4o_k4VO zs_e0wCr>Ze31O@I?>8-UOjZu=3EpWmmi3XbapBhmd^Rv|NZ7{Ho<#g)qwPQAp8 z_ysG8Sdt<&|M4x8%$);Q)Y$q-c&S|ddNUeIdFxau5iHnNWy$vk>(N|6IgDtR;tEYL(HrM?u|JsG#k|51>v zDh#k?Y~VuR0>3t`2PP%$H(GjYV5_~?&#{U2#Ndeeo`|n3#a+5@D0*m`UFGxJAGwV> zHj*p;J$Yc@0He({y>^}N_p#~`E?KQeL_%z5!K8k7n>*P7A$S@&`&<9cA#v9X2<|n` z-NG(Hp7ph3tgk&4?8~5gkJM4OI%iW;%zGsd=w-J|_gw#cdijMa8XtP>7Aog%77hNy zjuGQ&k8BGjx|@*hr||z&QrliZ8@rkSolUzuc;38s`Ig@NcX}rq&cbtLTAkP>YBGGE zM8T^5&v)Kq*&g|&yTqpQ0S+v4aZssJ-c-$oXsZ{Y`i0{q@lJPa=j!LFN=|g*Y(+_J zMvdZt9So!r@mSLeRh{5S7cWxkjPEM3b-Fihr9*u+4?i`nK1DkTzKiN)ibqF!kWSY7Eu4aT%*X4`AIcl)ZQNan z&NJc5COG4)Lkj*mSYLk%a}Zn3dR3L$KL5ca5YK^E4p>C+prQ$R%vaNr1D{yqx@69?yv4gAlNg;abs>0(RO+u{U zIFv^q+Se+WOIX1U+PmFclY}eAE0|SJ^|ZIppE>kO2i^7S2~94kGKENayZec&LU4+X z%fJRw>Z+zXS)VrDD6*R>5B$YUG)2a)7DH8-TKh_cMpZYp}T4q~f zL9220&t6b=ljVAZ5R_vC4s3s2s&KH-H+jv|Jprp`efbEt-YF#sl`S$mC$xvp)2FSz zkeVjApJC-V6*JO~MJiTzE93ksBI8heGp)%Z_S5I8&HILx@zdW`hNHtN69rVH3+r2e z`Ft!{#Ss4CG`h}#-TpG9G%~5!4t-XD0$!T*O+WKAx~SLxI2QE}8B%$c|55uanGx=C zD95&)NwH{KXSot`3{HftLu1u!+zulvG%d3d_f~4vh9H7TX@g{@auGO&J2|HQ*^H=} zWo8Qq+;mat<91m)EAw#VEc~PSXS24a2R`z1nEAgqjBR6v@UAtzwLT(+UGeRPS%&B|hN$^qiXc+#-0_Uf_6Cu7Q6xNhhanAwJGZ)Up3b zbjPMpDJbHv{+7$oT4_=Nze-0M2TN5qG}<#Y16xFKuN|pnM4^Q?u4C;S!($v%P@j>p zGDQrn#A$R`ZFpsC7KgM1*Y}9KLy4woY^R2UnK!CdpOI`KP5P@$xlHK;HJeIR`#O2H zsS)}0KC^kFF-{iq6`n&ZaLcvOYTiUg^Z>Phu7CqA%iG;ief zmw{ZjI(?dA_<^Wd|5nM#cjEtk%z_o`F^4Rd0)AGyj`jDMj;O4v_n2$SEv8| z5B*R4TkchxW-!@Xs^t28@0z-RXRPgxQIFt4R0M7=)$5<0Rgi}eUgVN@4Bk}noymUq za<<^{<2R}1Hkgv2Ny%<|PZw8`*;nFc%PwidnSQDnEyvq@rFowRn!ke$Q0aH%PwEeh z3$`Q_RISV=rUU^~m%!!3dQ8#`pS#?%r)+&Yw}ewhz(U`R^BsnHDhTrQN!gcgMW##yJO(nLexxR;@NO{|`LUu=pGzS@#GwJsvmS-pR7rqx%r4AAtxk%vnaUs+p z5a40FM;PDBYC{}@CnAXpE#Bzd&X-$n97cR?_6c2^K1si>SoNA<)2=($`7_>b>Y8gx zptuyNCDEIxI70a`ilyQ*_J`~pqbf4)=ztvhwys;4tzWEBVeMeEQGpK zMD=}A(oQsenbOApQ8h%Q1DAQ|>9e;IQjDD;Sx0J=T*u284X1$3s2_&!DEu!H2y z7<|_ISzKcl@A8r5*&HPd^S-ccfDdx@MZRI>9hADfU##%Hp-)DN87BX%O{YE@w`$XJ*i_fGdMxqFA#@fm zef2v3zecR{Lsq`tU#{owsr^9D2_iUVNaOQ0g;J0(j)1~)ZF#W_Y3$!>y#YrmdNJ;B@N@mT{AJ_d- zT}#6d-$KQg@eB~km?)a5ocVmj?+ZtsapOrcuBlA*A3JJ_Oior6;MXNhA&pL> znF8yBYU^sdTRUlUEjKB)N*|RKL6ErTrEFxtzb{BQR`>SgQ~xMPucy8WI$WjX!Ao$m zqd(qP^F!dLRi5YRrrK9iopAMgKRqhRQYUz?;#(p|KiA;++udfg&E3t=$giqfzf`yH zNTj}!+AYcW9muz-^>i$4{gFq1+SYPp>ei(orc}v{(cK|3XU--v-W|a2&}-Dh}~&-ejHoNYk1!X35!gl#ua+q>G~D z6+JHwRsC{2&(L(bg`Cy*lIF@q)N@L4#kNiVSbqktrvAs{rXGrk*}nb(Gdcm6lI&9c z>wl4K@)XuN7dI+QfM3kS%p*`Q{8I)3*XPZiK9PMH+-uS9CWJUJ7vGG_DI+!>f^)#9 z2kIT96Cb=JTd|aK{78w8?v6nwgGBVS`^YLJfRJPu{AMBI_u10i$nNMpTqgn zA&_K$uL#Nyosqh#5vS2OmPsvK{*crcv?AbRk2)}{*)#byt)&M9{+DN3$Y~?vo_xst zsk-nlqNW&-<5`4+XY(!hOuxpfgo_xm`B`ysF27Pt#;@G(D|A9&cb5M>PUF4bU2^pA zlv0r@3uc2|t=oCu)?$%d=Gl0eTR4B12ig;^2vhN|Iz=!Ni4ZOj?6cxfT1@y)hELvqFzvW+hJ;c(Md1F0ro65KbH)861$7Xe0+g*KC zNyqX{_@HMO9eRgxF72to?-><&*U%E+kW?3JKD-002De%Z;beQ)L zk+%)?=#2jqq4`5vstx2%Y{wQSRA%*V3*}vCn;N{B5#2>g2Ll6sa{-jXPqAyx>N;K$FbI{RbwL_c7Tk_U^C7HDsdJy5h z;@boQ{o1kxrV0IW?|q)3xT>(=o|;?-_Y^V6kvenXhkIQo`^}5OXzzPOGno*5F7G-e zHliW~1xYS?twK>jZ-i45b4YW3!x`P0Nqfc+6vRLr6m8j7)#Efu3*HIB$|hG-f#2{o zwX^DI&o!Md)|4SBN#o*Hlpn!bV+UH(?M!y2oq3RxAE(7;5Y$vZG+*N0Px-UXO~oRS z;50ht`a&oC=7xRB%Sd8OtxOiT@P50O7a^LsRPMqkJFGMvopBG9BlROcKrFbYwy#2S z#CmB@S?joF$148Jn|HrLvSDo5Ff(q?+uhOZn!JtSHx(;eM>eX+?utWp^(m2WOhbZB zCwqE%kp`TODG7NWUpwM15(O>PI4|K&tAGqEeIG zQN{j&q`@S$q;Um1J3ALv)~7DuQ&=d?JG{2hPND{V6d3I~pUT({6bWdfx~2Z|$1+I` z{v)_4pOIYnz{ogZJ|%TVVF>ph@&AvFvSI00`S@iU25xYsVolMTQ9nqTfV{U*X=RLB zq=3!C%&(09{G&n#wq5Rh`*wHnH5RA#?b`>4uhfm$_Wkp>Y5CostsUV1?9;xhuYtX7 H75aYw@hTH% literal 0 HcmV?d00001 diff --git a/packages/preview-service/vitest.config.ts b/packages/preview-service/vitest.config.ts new file mode 100644 index 000000000..bf52f2daf --- /dev/null +++ b/packages/preview-service/vitest.config.ts @@ -0,0 +1,20 @@ +import { TIME_MS } from '@speckle/shared' +import path from 'path' +import { configDefaults, defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + exclude: [...configDefaults.exclude], + // reporters: ['verbose', 'hanging-process'] //uncomment to debug hanging processes etc. + sequence: { + shuffle: true, + concurrent: true + }, + testTimeout: 2 * TIME_MS.minute + }, + resolve: { + alias: { + '@': path.resolve(__dirname, './src') + } + } +}) diff --git a/utils/ubuntu-chromium/Dockerfile b/utils/ubuntu-chromium/Dockerfile new file mode 100644 index 000000000..b9a93d4f6 --- /dev/null +++ b/utils/ubuntu-chromium/Dockerfile @@ -0,0 +1,30 @@ +FROM node:20-slim + +# hadolint ignore=DL3008 +RUN apt-get update && \ + apt-get install -y \ + chromium \ + fonts-liberation \ + libappindicator3-1 \ + libasound2 \ + libatk-bridge2.0-0 \ + libatk1.0-0 \ + libcups2 \ + libdbus-1-3 \ + libgdk-pixbuf2.0-0 \ + libnspr4 \ + libnss3 \ + libxcomposite1 \ + libxdamage1 \ + libxrandr2 \ + xdg-utils \ + wget \ + ca-certificates \ + --no-install-recommends && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium + +# Create app directory +WORKDIR /usr/src/app diff --git a/yarn.lock b/yarn.lock index 31c358218..d76ec45ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12731,6 +12731,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:^1.1.5": + version: 1.8.0 + resolution: "@noble/hashes@npm:1.8.0" + checksum: 10/474b7f56bc6fb2d5b3a42132561e221b0ea4f91e590f4655312ca13667840896b34195e2b53b7f097ec080a1fdd3b58d902c2a8d0fbdf51d2e238b53808a177e + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -13586,6 +13593,15 @@ __metadata: languageName: node linkType: hard +"@paralleldrive/cuid2@npm:^2.2.2": + version: 2.2.2 + resolution: "@paralleldrive/cuid2@npm:2.2.2" + dependencies: + "@noble/hashes": "npm:^1.1.5" + checksum: 10/40ee269d6e47b4fed7706a2e4da7c27c3c668ebc969110d6d112277b6b16a67cce0503b53b9943f2c55035a72d225f77ea5541e03396d6429eec9252137a53b7 + languageName: node + linkType: hard + "@parcel/watcher-android-arm64@npm:2.4.1": version: 2.4.1 resolution: "@parcel/watcher-android-arm64@npm:2.4.1" @@ -16191,6 +16207,7 @@ __metadata: "@swc/core": "npm:^1.9.3" "@types/express": "npm:^4.17.13" "@types/node": "npm:^18.19.38" + "@types/pngjs": "npm:^6.0.5" bull: "npm:^4.16.4" dotenv: "npm:^16.4.7" eslint: "npm:^9.4.0" @@ -16201,14 +16218,18 @@ __metadata: pino: "npm:^8.7.0" pino-http: "npm:^8.6.1" pino-pretty: "npm:^9.1.1" + pixelmatch: "npm:^7.1.0" + pngjs: "npm:^7.0.0" prettier: "npm:^2.5.1" prom-client: "npm:^14.0.1" puppeteer: "npm:^23.9.0" rimraf: "npm:^6.0.1" + supertest: "npm:^7.1.3" ts-node: "npm:^10.9.2" tsx: "npm:^4.19.2" typescript: "npm:^4.6.4" typescript-eslint: "npm:^7.12.0" + vitest: "npm:^1.6.0" znv: "npm:^0.4.0" zod: "npm:^3.23.8" languageName: unknown @@ -19594,6 +19615,15 @@ __metadata: languageName: node linkType: hard +"@types/pngjs@npm:^6.0.5": + version: 6.0.5 + resolution: "@types/pngjs@npm:6.0.5" + dependencies: + "@types/node": "npm:*" + checksum: 10/132fce25817d47a784ed48aa678332521b0f7e6edbaa76f3fa4e9ca1228078788ae712f99ad4d1a324d9ba0b14829958677eabf3ebef1fb6e120816f433f0cd8 + languageName: node + linkType: hard + "@types/polylabel@npm:1.1.3": version: 1.1.3 resolution: "@types/polylabel@npm:1.1.3" @@ -22255,7 +22285,7 @@ __metadata: languageName: node linkType: hard -"asap@npm:~2.0.3": +"asap@npm:^2.0.0, asap@npm:~2.0.3": version: 2.0.6 resolution: "asap@npm:2.0.6" checksum: 10/b244c0458c571945e4b3be0b14eb001bea5596f9868cc50cc711dc03d58a7e953517d3f0dad81ccde3ff37d1f074701fa76a6f07d41aaa992d7204a37b915dda @@ -24874,6 +24904,13 @@ __metadata: languageName: node linkType: hard +"component-emitter@npm:^1.3.0": + version: 1.3.1 + resolution: "component-emitter@npm:1.3.1" + checksum: 10/94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d + languageName: node + linkType: hard + "compress-commons@npm:^6.0.2": version: 6.0.2 resolution: "compress-commons@npm:6.0.2" @@ -25223,7 +25260,7 @@ __metadata: languageName: node linkType: hard -"cookiejar@npm:^2.1.0, cookiejar@npm:^2.1.1": +"cookiejar@npm:^2.1.0, cookiejar@npm:^2.1.1, cookiejar@npm:^2.1.4": version: 2.1.4 resolution: "cookiejar@npm:2.1.4" checksum: 10/4a184f5a0591df8b07d22a43ea5d020eacb4572c383e853a33361a99710437eaa0971716c688684075bbf695b484f5872e9e3f562382e46858716cb7fc8ce3f4 @@ -26725,6 +26762,16 @@ __metadata: languageName: node linkType: hard +"dezalgo@npm:^1.0.4": + version: 1.0.4 + resolution: "dezalgo@npm:1.0.4" + dependencies: + asap: "npm:^2.0.0" + wrappy: "npm:1" + checksum: 10/895389c6aead740d2ab5da4d3466d20fa30f738010a4d3f4dcccc9fc645ca31c9d10b7e1804ae489b1eb02c7986f9f1f34ba132d409b043082a86d9a4e745624 + languageName: node + linkType: hard + "didyoumean@npm:^1.2.2": version: 1.2.2 resolution: "didyoumean@npm:1.2.2" @@ -30197,6 +30244,17 @@ __metadata: languageName: node linkType: hard +"formidable@npm:^3.5.4": + version: 3.5.4 + resolution: "formidable@npm:3.5.4" + dependencies: + "@paralleldrive/cuid2": "npm:^2.2.2" + dezalgo: "npm:^1.0.4" + once: "npm:^1.4.0" + checksum: 10/4645e6ce3d8bbefd3dd873dcd6211362da3bf8a04c8426d7f454c238be0142975f02e5bdbc792fdbd2be493fdcf5442fe01d9a246bd8c3fd8e779738290cc630 + languageName: node + linkType: hard + "forwarded@npm:0.2.0": version: 0.2.0 resolution: "forwarded@npm:0.2.0" @@ -36614,7 +36672,7 @@ __metadata: languageName: node linkType: hard -"mime@npm:^2.4.6": +"mime@npm:2.6.0, mime@npm:^2.4.6": version: 2.6.0 resolution: "mime@npm:2.6.0" bin: @@ -40669,6 +40727,17 @@ __metadata: languageName: node linkType: hard +"pixelmatch@npm:^7.1.0": + version: 7.1.0 + resolution: "pixelmatch@npm:7.1.0" + dependencies: + pngjs: "npm:^7.0.0" + bin: + pixelmatch: bin/pixelmatch + checksum: 10/57a122196318ea8ce74e8759b1b7b94b9f9627b495cd79e50a49d470dc23b6c679e89c38660d0f7e8f959eac3b279c55b728e52d02c276dc51505f06eaba1141 + languageName: node + linkType: hard + "pkg-dir@npm:^3.0.0": version: 3.0.0 resolution: "pkg-dir@npm:3.0.0" @@ -40807,6 +40876,13 @@ __metadata: languageName: node linkType: hard +"pngjs@npm:^7.0.0": + version: 7.0.0 + resolution: "pngjs@npm:7.0.0" + checksum: 10/e843ebbb0df092ee0f3a3e7dbd91ff87a239a4e4c4198fff202916bfb33b67622f4b83b3c29f3ccae94fcb97180c289df06068624554f61686fe6b9a4811f7db + languageName: node + linkType: hard + "polished@npm:^4.2.2": version: 4.2.2 resolution: "polished@npm:4.2.2" @@ -46308,6 +46384,23 @@ __metadata: languageName: node linkType: hard +"superagent@npm:^10.2.2": + version: 10.2.2 + resolution: "superagent@npm:10.2.2" + dependencies: + component-emitter: "npm:^1.3.0" + cookiejar: "npm:^2.1.4" + debug: "npm:^4.3.4" + fast-safe-stringify: "npm:^2.1.1" + form-data: "npm:^4.0.0" + formidable: "npm:^3.5.4" + methods: "npm:^1.1.2" + mime: "npm:2.6.0" + qs: "npm:^6.11.0" + checksum: 10/e89ae49163df0db50e6a77316a7304a16640df11a8d2219bef11e69f59c74e54c16670ec250c2ab59f06887f71bb5d6e5933f735b931cbdbe34ba490d78b5d70 + languageName: node + linkType: hard + "superagent@npm:^3.7.0, superagent@npm:^3.8.3": version: 3.8.3 resolution: "superagent@npm:3.8.3" @@ -46345,6 +46438,16 @@ __metadata: languageName: node linkType: hard +"supertest@npm:^7.1.3": + version: 7.1.3 + resolution: "supertest@npm:7.1.3" + dependencies: + methods: "npm:^1.1.2" + superagent: "npm:^10.2.2" + checksum: 10/d148d05ed52e2cd487c483aae8721bf83f2611eb630d847b1cb37b3f1b09c499aa6b6446d3739c1db2459df1668bf089870437f71e57fc39c7194f51bdac6119 + languageName: node + linkType: hard + "supports-color@npm:8.1.1, supports-color@npm:^8.0.0, supports-color@npm:^8.1.0, supports-color@npm:^8.1.1, supports-color@npm:~8.1.1": version: 8.1.1 resolution: "supports-color@npm:8.1.1"